trunk.c (465484B)
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 * Trident Front Panel and Higig Trunking 8 */ 9 10 #include <soc/defs.h> 11 #include <sal/core/libc.h> 12 #include <shared/bsl.h> 13 #ifdef BCM_TRIDENT_SUPPORT 14 15 #include <soc/mem.h> 16 #include <soc/profile_mem.h> 17 #include <soc/bradley.h> 18 #include <sal/appl/sal.h> 19 20 #if defined BCM_METROLITE_SUPPORT 21 #include <soc/katana2.h> 22 #endif 23 #include <bcm/error.h> 24 25 #include <bcm_int/esw/mbcm.h> 26 #include <bcm_int/esw/link.h> /* LAG failover support */ 27 #include <bcm_int/esw_dispatch.h> 28 #include <bcm_int/esw/switch.h> 29 #include <bcm_int/esw/stack.h> 30 #include <bcm_int/esw/trunk.h> 31 #include <bcm_int/esw/trident.h> 32 #include <bcm_int/esw/triumph3.h> 33 #include <bcm_int/esw/trident2.h> 34 #include <bcm_int/esw/katana2.h> 35 #if defined(BCM_TRIUMPH_SUPPORT) && defined(INCLUDE_L3) 36 #include <bcm_int/esw/triumph.h> 37 #endif 38 #ifdef BCM_HGPROXY_COE_SUPPORT 39 #include <bcm_int/esw/xgs5.h> 40 #endif /* BCM_HGPROXY_COE_SUPPORT */ 41 42 #include <bcm_int/esw/portctrl.h> 43 #define _BCM_TD_FP_TRUNK_RTAG1_6_MAX_PORTCNT 16 44 #define _BCM_TD_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT 16 45 46 #ifdef BCM_KATANA_SUPPORT 47 #define _BCM_KATANA_FP_TRUNK_RTAG1_6_MAX_PORTCNT 8 48 #define _BCM_KATANA_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT 4 49 #endif 50 51 /* -------------------------------- */ 52 /* Trunk membership info */ 53 /* -------------------------------- */ 54 typedef struct { 55 uint16 num_ports; 56 uint16 *modport; 57 uint32 *member_flags; 58 #ifdef BCM_WARM_BOOT_SUPPORT 59 uint8 recovered_from_scache; 60 #endif /* BCM_WARM_BOOT_SUPPORT */ 61 } _trident_member_info_t; 62 63 typedef struct { 64 _trident_member_info_t *member_info; 65 } _trident_trunk_member_info_t; 66 67 STATIC _trident_trunk_member_info_t *_trident_trunk_member_info[BCM_MAX_NUM_UNITS]; 68 69 #define MEMBER_INFO(_unit_, _tid_) (_trident_trunk_member_info[_unit_]->member_info[_tid_]) 70 71 /* -------------------------------- */ 72 /* Module and port to trunk mapping */ 73 /* -------------------------------- */ 74 STATIC uint16 *_trident_mod_port_to_tid_map[BCM_MAX_NUM_UNITS]; 75 76 /* ----------------------------------------------------------------- */ 77 /* Bookkeeping info on which entries of trunk member tables are used */ 78 /* ----------------------------------------------------------------- */ 79 typedef struct _trident_trunk_member_bookkeeping_s { 80 SHR_BITDCL *fp_trunk_member_bitmap; 81 SHR_BITDCL *hg_trunk_member_bitmap; 82 } _trident_trunk_member_bookkeeping_t; 83 84 STATIC _trident_trunk_member_bookkeeping_t *_trident_trunk_member_bk[BCM_MAX_NUM_UNITS]; 85 86 #define TRUNK_MEMBER_INFO(_unit_) (_trident_trunk_member_bk[_unit_]) 87 88 #define _BCM_FP_TRUNK_MEMBER_USED_GET(_u_, _idx_) \ 89 SHR_BITGET(TRUNK_MEMBER_INFO(_u_)->fp_trunk_member_bitmap, _idx_) 90 #define _BCM_FP_TRUNK_MEMBER_USED_SET(_u_, _idx_) \ 91 SHR_BITSET(TRUNK_MEMBER_INFO(_u_)->fp_trunk_member_bitmap, _idx_) 92 #define _BCM_FP_TRUNK_MEMBER_USED_CLR(_u_, _idx_) \ 93 SHR_BITCLR(TRUNK_MEMBER_INFO(_u_)->fp_trunk_member_bitmap, _idx_) 94 #define _BCM_FP_TRUNK_MEMBER_USED_SET_RANGE(_u_, _idx_, _count_) \ 95 SHR_BITSET_RANGE(TRUNK_MEMBER_INFO(_u_)->fp_trunk_member_bitmap, _idx_, _count_) 96 #define _BCM_FP_TRUNK_MEMBER_USED_CLR_RANGE(_u_, _idx_, _count_) \ 97 SHR_BITCLR_RANGE(TRUNK_MEMBER_INFO(_u_)->fp_trunk_member_bitmap, _idx_, _count_) 98 #define _BCM_FP_TRUNK_MEMBER_TEST_RANGE(_u_, _idx_, _count_, _result_) \ 99 SHR_BITTEST_RANGE(TRUNK_MEMBER_INFO(_u_)->fp_trunk_member_bitmap, _idx_, _count_, _result_) 100 101 #define _BCM_HG_TRUNK_MEMBER_USED_GET(_u_, _idx_) \ 102 SHR_BITGET(TRUNK_MEMBER_INFO(_u_)->hg_trunk_member_bitmap, _idx_) 103 #define _BCM_HG_TRUNK_MEMBER_USED_SET(_u_, _idx_) \ 104 SHR_BITSET(TRUNK_MEMBER_INFO(_u_)->hg_trunk_member_bitmap, _idx_) 105 #define _BCM_HG_TRUNK_MEMBER_USED_CLR(_u_, _idx_) \ 106 SHR_BITCLR(TRUNK_MEMBER_INFO(_u_)->hg_trunk_member_bitmap, _idx_) 107 #define _BCM_HG_TRUNK_MEMBER_USED_SET_RANGE(_u_, _idx_, _count_) \ 108 SHR_BITSET_RANGE(TRUNK_MEMBER_INFO(_u_)->hg_trunk_member_bitmap, _idx_, _count_) 109 #define _BCM_HG_TRUNK_MEMBER_USED_CLR_RANGE(_u_, _idx_, _count_) \ 110 SHR_BITCLR_RANGE(TRUNK_MEMBER_INFO(_u_)->hg_trunk_member_bitmap, _idx_, _count_) 111 #define _BCM_HG_TRUNK_MEMBER_TEST_RANGE(_u_, _idx_, _count_, _result_) \ 112 SHR_BITTEST_RANGE(TRUNK_MEMBER_INFO(_u_)->hg_trunk_member_bitmap, _idx_, _count_, _result_) 113 114 /* ------------------------------------------------- */ 115 /* Bookkeeping info for Higig dynamic load balancing */ 116 /* ------------------------------------------------- */ 117 typedef struct _trident_hg_dlb_bookkeeping_s { 118 /* Higig DLB parameters */ 119 SHR_BITDCL *hg_dlb_id_used_bitmap; 120 SHR_BITDCL *hg_dlb_flowset_block_bitmap; /* Each block corresponds to 121 512 entries */ 122 #ifdef BCM_TRIUMPH3_SUPPORT 123 SHR_BITDCL *hg_dlb_member_id_used_bitmap; 124 #endif /* BCM_TRIUMPH3_SUPPORT */ 125 int hg_dlb_sample_rate; 126 int hg_dlb_tx_load_min_th; 127 int hg_dlb_tx_load_max_th; 128 int hg_dlb_qsize_min_th; 129 int hg_dlb_qsize_max_th; 130 uint8 *hg_dlb_load_weight; 131 soc_profile_mem_t *hg_dlb_quality_map_profile; 132 #ifdef BCM_WARM_BOOT_SUPPORT 133 uint8 recovered_from_scache; /* Indicates if the following members of this 134 structure have been recovered from scached: 135 hg_dlb_sample_rate, 136 hg_dlb_tx_load_min_th, 137 hg_dlb_tx_load_max_th, 138 hg_dlb_tx_qsize_min_th, 139 hg_dlb_tx_qsize_max_th, 140 hg_dlb_load_weight */ 141 #endif /* BCM_WARM_BOOT_SUPPORT */ 142 } _trident_hg_dlb_bookkeeping_t; 143 144 STATIC _trident_hg_dlb_bookkeeping_t *_trident_hg_dlb_bk[BCM_MAX_NUM_UNITS]; 145 146 #define HG_DLB_INFO(_unit_) (_trident_hg_dlb_bk[_unit_]) 147 148 #define _BCM_HG_DLB_ID_USED_GET(_u_, _idx_) \ 149 SHR_BITGET(HG_DLB_INFO(_u_)->hg_dlb_id_used_bitmap, _idx_) 150 #define _BCM_HG_DLB_ID_USED_SET(_u_, _idx_) \ 151 SHR_BITSET(HG_DLB_INFO(_u_)->hg_dlb_id_used_bitmap, _idx_) 152 #define _BCM_HG_DLB_ID_USED_CLR(_u_, _idx_) \ 153 SHR_BITCLR(HG_DLB_INFO(_u_)->hg_dlb_id_used_bitmap, _idx_) 154 155 #define _BCM_HG_DLB_FLOWSET_BLOCK_USED_GET(_u_, _idx_) \ 156 SHR_BITGET(HG_DLB_INFO(_u_)->hg_dlb_flowset_block_bitmap, _idx_) 157 #define _BCM_HG_DLB_FLOWSET_BLOCK_USED_SET(_u_, _idx_) \ 158 SHR_BITSET(HG_DLB_INFO(_u_)->hg_dlb_flowset_block_bitmap, _idx_) 159 #define _BCM_HG_DLB_FLOWSET_BLOCK_USED_CLR(_u_, _idx_) \ 160 SHR_BITCLR(HG_DLB_INFO(_u_)->hg_dlb_flowset_block_bitmap, _idx_) 161 #define _BCM_HG_DLB_FLOWSET_BLOCK_USED_SET_RANGE(_u_, _idx_, _count_) \ 162 SHR_BITSET_RANGE(HG_DLB_INFO(_u_)->hg_dlb_flowset_block_bitmap, _idx_, _count_) 163 #define _BCM_HG_DLB_FLOWSET_BLOCK_USED_CLR_RANGE(_u_, _idx_, _count_) \ 164 SHR_BITCLR_RANGE(HG_DLB_INFO(_u_)->hg_dlb_flowset_block_bitmap, _idx_, _count_) 165 #define _BCM_HG_DLB_FLOWSET_BLOCK_TEST_RANGE(_u_, _idx_, _count_, _result_) \ 166 SHR_BITTEST_RANGE(HG_DLB_INFO(_u_)->hg_dlb_flowset_block_bitmap, _idx_, _count_, _result_) 167 168 #ifdef BCM_TRIUMPH3_SUPPORT 169 #define _BCM_HG_DLB_MEMBER_ID_USED_GET(_u_, _idx_) \ 170 SHR_BITGET(HG_DLB_INFO(_u_)->hg_dlb_member_id_used_bitmap, _idx_) 171 #define _BCM_HG_DLB_MEMBER_ID_USED_SET(_u_, _idx_) \ 172 SHR_BITSET(HG_DLB_INFO(_u_)->hg_dlb_member_id_used_bitmap, _idx_) 173 #define _BCM_HG_DLB_MEMBER_ID_USED_CLR(_u_, _idx_) \ 174 SHR_BITCLR(HG_DLB_INFO(_u_)->hg_dlb_member_id_used_bitmap, _idx_) 175 #endif /* BCM_TRIUMPH3_SUPPORT */ 176 177 /* ---------------------------- */ 178 /* Higig trunk override profile */ 179 /* ---------------------------- */ 180 STATIC soc_profile_mem_t *_trident_hg_trunk_override_profile[BCM_MAX_NUM_UNITS]; 181 182 /* ----------------------- */ 183 /* Hardware Trunk Failover */ 184 /* ----------------------- */ 185 186 /* For the devices which support hardware trunk failover, the failover 187 * configuration must be retained if it is one of the standard models 188 * for the retrieval function to use the same encoding as the set function. 189 * 190 * Note: The trunk members stored in _trident_hw_tinfo_t's modport array do not 191 * include those members with the BCM_TRUNK_MEMBER_EGRESS_DISABLE set. 192 */ 193 194 typedef struct { 195 uint16 num_ports; 196 uint8 *psc; 197 uint16 *modport; 198 uint32 *flags; 199 } _trident_hw_tinfo_t; 200 201 typedef struct { 202 _trident_hw_tinfo_t *hw_tinfo; 203 } _trident_trunk_hwfail_t; 204 205 STATIC _trident_trunk_hwfail_t *_trident_trunk_hwfail[BCM_MAX_NUM_UNITS]; 206 207 /* ----------------------- */ 208 /* Software Trunk Failover */ 209 /* ----------------------- */ 210 211 /* Even without hardware failover support, given the high speed link 212 * change notification possible with trident devices, a port that has been 213 * indicated as link down can cause the trunk_group table to be immediately 214 * updated with the link down port removed. This works well for two cases: 215 * (1) this is a higig trunk, or (2) the local device is the only device 216 * in the system. 217 * 218 * Note: The trunk members stored in _trident_tinfo_t's modport array do not 219 * include those members with the BCM_TRUNK_MEMBER_EGRESS_DISABLE set. 220 * If a trunk member port is down, it'll be removed from_trident_tinfo_t's 221 * modport array by _bcm_trident_trunk_swfailover_trigger. 222 */ 223 typedef struct { 224 uint8 rtag; 225 uint16 num_ports; 226 uint16 *modport; 227 uint32 *member_flags; 228 uint32 flags; 229 } _trident_tinfo_t; 230 231 typedef struct { 232 uint8 mymodid; 233 #if (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS) 234 bcm_trunk_t trunk[SOC_MAX_NUM_PP_PORTS]; 235 #else 236 bcm_trunk_t trunk[SOC_MAX_NUM_PORTS]; /* If port is not a member of any 237 trunk group, trunk = 0; else 238 trunk = trunk id + 1. */ 239 #endif 240 _trident_tinfo_t *tinfo; 241 } _trident_trunk_swfail_t; 242 243 STATIC _trident_trunk_swfail_t *_trident_trunk_swfail[BCM_MAX_NUM_UNITS]; 244 245 int bcm_trident_trunk_mbr_zero_rsvd[BCM_MAX_NUM_UNITS] = {0}; 246 247 /* Function prototypes */ 248 STATIC int _bcm_trident_trunk_set_port_property(int unit, 249 bcm_module_t mod, bcm_port_t port, int tid); 250 STATIC int _bcm_trident_trunk_fabric_port_set(int unit, 251 bcm_trunk_t hgtid, pbmp_t old_ports, pbmp_t new_ports); 252 STATIC int _bcm_trident_nuc_tpbm_get(int unit, 253 int num_ports, bcm_module_t *tm, SHR_BITDCL *nuc_tpbm); 254 STATIC int _bcm_trident_trunk_block_mask(int unit, int nuc_type, 255 pbmp_t old_ports, pbmp_t new_ports, 256 int *localport_array, int localport_count, 257 SHR_BITDCL *my_modid_bmap, uint32 member_count, 258 uint32 flags); 259 STATIC int _bcm_trident_hg_dlb_sample_rate_thresholds_set(int unit, 260 int sample_rate, int min_th, int max_th); 261 STATIC int _bcm_trident_hg_dlb_qsize_thresholds_set(int unit, 262 int min_th, int max_th); 263 STATIC int _bcm_trident_hg_dlb_quality_assign(int unit, int tx_load_percent, 264 uint32 *entry_arr); 265 266 /* ----------------------------------------------------------------------------- 267 * 268 * Routines for initialization and de-initialization 269 * 270 * ----------------------------------------------------------------------------- 271 */ 272 273 /* 274 * Function: 275 * _bcm_trident_trunk_member_info_deinit 276 * Purpose: 277 * Deallocate trunk membership info. 278 * Parameters: 279 * unit - (IN)SOC unit number. 280 * Returns: 281 * None 282 */ 283 STATIC void 284 _bcm_trident_trunk_member_info_deinit(int unit) 285 { 286 int trunk_num_groups; 287 int i; 288 289 if (_trident_trunk_member_info[unit]) { 290 if (_trident_trunk_member_info[unit]->member_info) { 291 trunk_num_groups = soc_mem_index_count(unit, TRUNK_GROUPm) + 292 soc_mem_index_count(unit, HG_TRUNK_GROUPm); 293 for (i = 0; i < trunk_num_groups; i++) { 294 if (MEMBER_INFO(unit, i).modport) { 295 sal_free(MEMBER_INFO(unit, i).modport); 296 MEMBER_INFO(unit, i).modport = NULL; 297 } 298 if (MEMBER_INFO(unit, i).member_flags) { 299 sal_free(MEMBER_INFO(unit, i).member_flags); 300 MEMBER_INFO(unit, i).member_flags = NULL; 301 } 302 } 303 sal_free(_trident_trunk_member_info[unit]->member_info); 304 _trident_trunk_member_info[unit]->member_info = NULL; 305 } 306 sal_free(_trident_trunk_member_info[unit]); 307 _trident_trunk_member_info[unit] = NULL; 308 } 309 } 310 311 /* 312 * Function: 313 * _bcm_trident_trunk_member_info_init 314 * Purpose: 315 * Allocate and initialize trunk member info. 316 * Parameters: 317 * unit - (IN)SOC unit number. 318 * Returns: 319 * BCM_X_XXX 320 */ 321 STATIC int 322 _bcm_trident_trunk_member_info_init(int unit) 323 { 324 int trunk_num_groups; 325 326 if (_trident_trunk_member_info[unit] == NULL) { 327 _trident_trunk_member_info[unit] = 328 sal_alloc(sizeof(_trident_trunk_member_info_t), "trunk member info"); 329 if (_trident_trunk_member_info[unit] == NULL) { 330 return BCM_E_MEMORY; 331 } 332 } 333 sal_memset(_trident_trunk_member_info[unit], 0, 334 sizeof(_trident_trunk_member_info_t)); 335 336 trunk_num_groups = soc_mem_index_count(unit, TRUNK_GROUPm) + 337 soc_mem_index_count(unit, HG_TRUNK_GROUPm); 338 if (_trident_trunk_member_info[unit]->member_info == NULL) { 339 _trident_trunk_member_info[unit]->member_info = 340 sal_alloc(sizeof(_trident_member_info_t) * trunk_num_groups, 341 "member info"); 342 if (_trident_trunk_member_info[unit]->member_info == NULL) { 343 _bcm_trident_trunk_member_info_deinit(unit); 344 return BCM_E_MEMORY; 345 } 346 } 347 sal_memset(_trident_trunk_member_info[unit]->member_info, 0, 348 sizeof(_trident_member_info_t) * trunk_num_groups); 349 350 /* Note: The maximum number of member ports in a trunk group is 256 in Trident. 351 * But it would be quite wasteful to allocate 256 entries to each 352 * _trident_trunk_member_info[unit]->member_info[x].modport/member_flags arrays. 353 * These arrays will be allocated as member ports are added to trunk group. 354 */ 355 356 return BCM_E_NONE; 357 } 358 359 /* 360 * Function: 361 * _bcm_trident_trunk_mod_port_map_deinit 362 * Purpose: 363 * Deinitialize a software cache for the SOURCE_TRUNK_MAP_TABLE. 364 * Parameters: 365 * unit - (IN)SOC unit number. 366 * Returns: 367 * None 368 */ 369 STATIC void 370 _bcm_trident_trunk_mod_port_map_deinit(int unit) 371 { 372 if (_trident_mod_port_to_tid_map[unit]) { 373 sal_free(_trident_mod_port_to_tid_map[unit]); 374 _trident_mod_port_to_tid_map[unit] = NULL; 375 } 376 } 377 378 /* 379 * Function: 380 * _bcm_trident_trunk_mod_port_map_init 381 * Purpose: 382 * Initialize a software cache for the SOURCE_TRUNK_MAP_TABLE. 383 * Parameters: 384 * unit - (IN)SOC unit number. 385 * Returns: 386 * BCM_X_XXX 387 */ 388 STATIC int 389 _bcm_trident_trunk_mod_port_map_init(int unit) 390 { 391 if (_trident_mod_port_to_tid_map[unit] == NULL) { 392 _trident_mod_port_to_tid_map[unit] = 393 sal_alloc(sizeof(uint16) * _BCM_XGS3_TRUNK_MOD_PORT_MAP_IDX_COUNT(unit), 394 "_trident_mod_port_to_tid_map"); 395 if (_trident_mod_port_to_tid_map[unit] == NULL) { 396 return BCM_E_MEMORY; 397 } 398 } 399 sal_memset(_trident_mod_port_to_tid_map[unit], 0, 400 sizeof(uint16) * _BCM_XGS3_TRUNK_MOD_PORT_MAP_IDX_COUNT(unit)); 401 402 return BCM_E_NONE; 403 } 404 405 /* 406 * Function: 407 * _bcm_trident_trunk_member_bk_deinit 408 * Purpose: 409 * Deallocate _trident_trunk_member_bk 410 * Parameters: 411 * unit - (IN)SOC unit number. 412 * Returns: 413 * None 414 */ 415 STATIC void 416 _bcm_trident_trunk_member_bk_deinit(int unit) 417 { 418 if (_trident_trunk_member_bk[unit]) { 419 if (_trident_trunk_member_bk[unit]->fp_trunk_member_bitmap) { 420 sal_free(_trident_trunk_member_bk[unit]->fp_trunk_member_bitmap); 421 _trident_trunk_member_bk[unit]->fp_trunk_member_bitmap = NULL; 422 } 423 if (_trident_trunk_member_bk[unit]->hg_trunk_member_bitmap) { 424 sal_free(_trident_trunk_member_bk[unit]->hg_trunk_member_bitmap); 425 _trident_trunk_member_bk[unit]->hg_trunk_member_bitmap = NULL; 426 } 427 sal_free(_trident_trunk_member_bk[unit]); 428 _trident_trunk_member_bk[unit] = NULL; 429 } 430 } 431 432 /* 433 * Function: 434 * _bcm_trident_trunk_member_bk_init 435 * Purpose: 436 * Allocate and initialize _trident_trunk_member_bk 437 * Parameters: 438 * unit - (IN)SOC unit number. 439 * Returns: 440 * BCM_X_XXX 441 */ 442 STATIC int 443 _bcm_trident_trunk_member_bk_init(int unit) 444 { 445 int fp_trunk_member_tbl_size; 446 int hg_trunk_member_tbl_size; 447 448 if (_trident_trunk_member_bk[unit] == NULL) { 449 _trident_trunk_member_bk[unit] = 450 sal_alloc(sizeof(_trident_trunk_member_bookkeeping_t), "_trident_trunk_member_bk"); 451 if (_trident_trunk_member_bk[unit] == NULL) { 452 return BCM_E_MEMORY; 453 } 454 } 455 sal_memset(_trident_trunk_member_bk[unit], 0, 456 sizeof(_trident_trunk_member_bookkeeping_t)); 457 458 fp_trunk_member_tbl_size = soc_mem_index_count(unit, TRUNK_MEMBERm); 459 if (_trident_trunk_member_bk[unit]->fp_trunk_member_bitmap == NULL) { 460 _trident_trunk_member_bk[unit]->fp_trunk_member_bitmap = 461 sal_alloc(SHR_BITALLOCSIZE(fp_trunk_member_tbl_size), "fp_trunk_member_bitmap"); 462 if (_trident_trunk_member_bk[unit]->fp_trunk_member_bitmap == NULL) { 463 _bcm_trident_trunk_member_bk_deinit(unit); 464 return BCM_E_MEMORY; 465 } 466 } 467 sal_memset(_trident_trunk_member_bk[unit]->fp_trunk_member_bitmap, 0, 468 SHR_BITALLOCSIZE(fp_trunk_member_tbl_size)); 469 470 if (!SOC_WARM_BOOT(unit)) { 471 _BCM_FP_TRUNK_MEMBER_USED_SET(unit, 0); 472 bcm_trident_trunk_mbr_zero_rsvd[unit] = TRUE; 473 } 474 475 hg_trunk_member_tbl_size = soc_mem_index_count(unit, HG_TRUNK_MEMBERm); 476 if (_trident_trunk_member_bk[unit]->hg_trunk_member_bitmap == NULL) { 477 _trident_trunk_member_bk[unit]->hg_trunk_member_bitmap = 478 sal_alloc(SHR_BITALLOCSIZE(hg_trunk_member_tbl_size), "hg_trunk_member_bitmap"); 479 if (_trident_trunk_member_bk[unit]->hg_trunk_member_bitmap == NULL) { 480 _bcm_trident_trunk_member_bk_deinit(unit); 481 return BCM_E_MEMORY; 482 } 483 } 484 sal_memset(_trident_trunk_member_bk[unit]->hg_trunk_member_bitmap, 0, 485 SHR_BITALLOCSIZE(hg_trunk_member_tbl_size)); 486 487 /* Reserve entry 0 of HG_TRUNK_MEMBERm, as invalid Higig trunk groups have 488 * their HG_TRUNK_GROUP table entry's BASE_PTR and TG_SIZE fields set to 0. 489 */ 490 if (!SOC_WARM_BOOT(unit)) { 491 SOC_IF_ERROR_RETURN 492 (WRITE_HG_TRUNK_MEMBERm(unit, MEM_BLOCK_ALL, 0, 493 soc_mem_entry_null(unit, HG_TRUNK_MEMBERm))); 494 } 495 496 if (!SOC_IS_KATANAX(unit)) { 497 /* Katana's HG_TRUNK_MEMBER table only has 8 members. 498 * It would be too expensive to reserve entry 0. 499 */ 500 _BCM_HG_TRUNK_MEMBER_USED_SET(unit, 0); 501 } 502 503 return BCM_E_NONE; 504 } 505 506 /* 507 * Function: 508 * _bcm_trident_hg_dlb_quality_map_profile_init 509 * Purpose: 510 * Initialize Higig DLB quality mapping profile. 511 * Parameters: 512 * unit - (IN)SOC unit number. 513 * Returns: 514 * BCM_X_XXX 515 */ 516 STATIC int 517 _bcm_trident_hg_dlb_quality_map_profile_init(int unit) 518 { 519 soc_profile_mem_t *profile; 520 soc_mem_t mem; 521 int entry_words; 522 int entries_per_profile; 523 int tx_load_percent; 524 int alloc_size; 525 uint32 *entry_arr; 526 int rv = BCM_E_NONE; 527 void *entries; 528 uint32 base_index = 0; 529 int port_count; 530 bcm_port_t port; 531 uint32 quantize_control_reg; 532 int i; 533 534 if (NULL == _trident_hg_dlb_bk[unit]->hg_dlb_quality_map_profile) { 535 _trident_hg_dlb_bk[unit]->hg_dlb_quality_map_profile = 536 sal_alloc(sizeof(soc_profile_mem_t), 537 "HG DLB Quality Map Profile Mem"); 538 if (NULL == _trident_hg_dlb_bk[unit]->hg_dlb_quality_map_profile) { 539 return BCM_E_MEMORY; 540 } 541 } else { 542 soc_profile_mem_destroy(unit, 543 _trident_hg_dlb_bk[unit]->hg_dlb_quality_map_profile); 544 } 545 profile = _trident_hg_dlb_bk[unit]->hg_dlb_quality_map_profile; 546 soc_profile_mem_t_init(profile); 547 548 if (soc_mem_is_valid(unit, DLB_HGT_PORT_QUALITY_MAPPINGm)) { 549 mem = DLB_HGT_PORT_QUALITY_MAPPINGm; 550 entry_words = sizeof(dlb_hgt_port_quality_mapping_entry_t) / 551 sizeof(uint32); 552 } else { 553 mem = DLB_HGT_QUALITY_MAPPINGm; 554 entry_words = sizeof(dlb_hgt_quality_mapping_entry_t) / sizeof(uint32); 555 } 556 SOC_IF_ERROR_RETURN 557 (soc_profile_mem_create(unit, &mem, &entry_words, 1, profile)); 558 559 entries_per_profile = 64; 560 if (!SOC_WARM_BOOT(unit)) { 561 alloc_size = entries_per_profile * entry_words * sizeof(uint32); 562 entry_arr = sal_alloc(alloc_size, "HG DLB Quality Map entries"); 563 if (entry_arr == NULL) { 564 return BCM_E_MEMORY; 565 } 566 sal_memset(entry_arr, 0, alloc_size); 567 568 /* Assign quality in the entry array, with 100% weight for port load, 569 * 0% for queue size. 570 */ 571 tx_load_percent = 100; 572 rv = _bcm_trident_hg_dlb_quality_assign(unit, tx_load_percent, 573 entry_arr); 574 if (BCM_FAILURE(rv)) { 575 sal_free(entry_arr); 576 return rv; 577 } 578 579 entries = entry_arr; 580 rv = soc_profile_mem_add(unit, profile, &entries, entries_per_profile, 581 &base_index); 582 sal_free(entry_arr); 583 if (SOC_FAILURE(rv)) { 584 return rv; 585 } 586 587 #ifdef BCM_TRIUMPH3_SUPPORT 588 if (soc_feature(unit, soc_feature_hg_dlb_member_id)) { 589 int member_id; 590 dlb_hgt_quality_control_entry_t quality_control_entry; 591 soc_field_t profile_ptr_f; 592 593 for (member_id = 0; 594 member_id < soc_mem_index_count(unit, 595 DLB_HGT_QUALITY_CONTROLm); 596 member_id++) { 597 BCM_IF_ERROR_RETURN 598 (READ_DLB_HGT_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY, 599 member_id, 600 &quality_control_entry)); 601 profile_ptr_f = soc_mem_field_valid(unit, 602 DLB_HGT_QUALITY_CONTROLm, PROFILE_PTRf) ? 603 PROFILE_PTRf : QMT_PROFILE_PTRf; 604 soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit, 605 &quality_control_entry, profile_ptr_f, 606 base_index / entries_per_profile); 607 BCM_IF_ERROR_RETURN 608 (WRITE_DLB_HGT_QUALITY_CONTROLm(unit, MEM_BLOCK_ALL, 609 member_id, 610 &quality_control_entry)); 611 } 612 613 for (i = 0; i < entries_per_profile; i++) { 614 SOC_PROFILE_MEM_REFERENCE(unit, profile, base_index + i, 615 member_id - 1); 616 } 617 618 HG_DLB_INFO(unit)-> 619 hg_dlb_load_weight[base_index/entries_per_profile] = 620 tx_load_percent; 621 } else 622 #endif /* BCM_TRIUMPH3_SUPPORT */ 623 { 624 port_count = 0; 625 PBMP_ALL_ITER(unit, port) { 626 BCM_IF_ERROR_RETURN 627 (READ_DLB_HGT_QUANTIZE_CONTROLr(unit, port, 628 &quantize_control_reg)); 629 soc_reg_field_set(unit, DLB_HGT_QUANTIZE_CONTROLr, 630 &quantize_control_reg, 631 PORT_QUALITY_MAPPING_PROFILE_PTRf, 632 base_index / entries_per_profile); 633 BCM_IF_ERROR_RETURN 634 (WRITE_DLB_HGT_QUANTIZE_CONTROLr(unit, port, 635 quantize_control_reg)); 636 port_count++; 637 } 638 639 for (i = 0; i < entries_per_profile; i++) { 640 SOC_PROFILE_MEM_REFERENCE(unit, profile, base_index + i, 641 port_count - 1); 642 } 643 644 HG_DLB_INFO(unit)-> 645 hg_dlb_load_weight[base_index/entries_per_profile] = 646 tx_load_percent; 647 } 648 } else { /* Warm boot, recover reference counts and entries_per_set */ 649 #ifdef BCM_TRIUMPH3_SUPPORT 650 if (soc_feature(unit, soc_feature_hg_dlb_member_id)) { 651 int member_id; 652 dlb_hgt_quality_control_entry_t quality_control_entry; 653 soc_field_t profile_ptr_f; 654 655 for (member_id = 0; 656 member_id < soc_mem_index_count(unit, 657 DLB_HGT_QUALITY_CONTROLm); 658 member_id++) { 659 BCM_IF_ERROR_RETURN 660 (READ_DLB_HGT_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY, 661 member_id, 662 &quality_control_entry)); 663 profile_ptr_f = soc_mem_field_valid(unit, 664 DLB_HGT_QUALITY_CONTROLm, PROFILE_PTRf) ? 665 PROFILE_PTRf : QMT_PROFILE_PTRf; 666 base_index = soc_DLB_HGT_QUALITY_CONTROLm_field32_get(unit, 667 &quality_control_entry, profile_ptr_f); 668 669 base_index *= entries_per_profile; 670 for (i = 0; i < entries_per_profile; i++) { 671 SOC_PROFILE_MEM_REFERENCE(unit, profile, base_index + i, 1); 672 SOC_PROFILE_MEM_ENTRIES_PER_SET(unit, profile, 673 base_index + i, entries_per_profile); 674 } 675 } 676 } else 677 #endif /* BCM_TRIUMPH3_SUPPORT */ 678 { 679 PBMP_ALL_ITER(unit, port) { 680 BCM_IF_ERROR_RETURN(READ_DLB_HGT_QUANTIZE_CONTROLr(unit, port, 681 &quantize_control_reg)); 682 base_index = soc_reg_field_get(unit, DLB_HGT_QUANTIZE_CONTROLr, 683 quantize_control_reg, PORT_QUALITY_MAPPING_PROFILE_PTRf); 684 base_index *= entries_per_profile; 685 for (i = 0; i < entries_per_profile; i++) { 686 SOC_PROFILE_MEM_REFERENCE(unit, profile, base_index + i, 1); 687 SOC_PROFILE_MEM_ENTRIES_PER_SET(unit, profile, 688 base_index + i, entries_per_profile); 689 } 690 } 691 } 692 } 693 694 return BCM_E_NONE; 695 } 696 697 /* 698 * Function: 699 * _bcm_trident_hg_dlb_deinit 700 * Purpose: 701 * Deallocate _trident_hg_dlb_bk 702 * Parameters: 703 * unit - (IN)SOC unit number. 704 * Returns: 705 * None 706 */ 707 STATIC void 708 _bcm_trident_hg_dlb_deinit(int unit) 709 { 710 int rv; 711 soc_field_t dlb_refresh_f; 712 uint32 arb_control_reg; 713 714 if (_trident_hg_dlb_bk[unit]) { 715 if (_trident_hg_dlb_bk[unit]->hg_dlb_id_used_bitmap) { 716 sal_free(_trident_hg_dlb_bk[unit]->hg_dlb_id_used_bitmap); 717 _trident_hg_dlb_bk[unit]->hg_dlb_id_used_bitmap = NULL; 718 } 719 if (_trident_hg_dlb_bk[unit]->hg_dlb_flowset_block_bitmap) { 720 sal_free(_trident_hg_dlb_bk[unit]->hg_dlb_flowset_block_bitmap); 721 _trident_hg_dlb_bk[unit]->hg_dlb_flowset_block_bitmap = NULL; 722 } 723 #ifdef BCM_TRIUMPH3_SUPPORT 724 if (soc_feature(unit, soc_feature_hg_dlb_member_id)) { 725 if (_trident_hg_dlb_bk[unit]->hg_dlb_member_id_used_bitmap) { 726 sal_free(_trident_hg_dlb_bk[unit]->hg_dlb_member_id_used_bitmap); 727 _trident_hg_dlb_bk[unit]->hg_dlb_member_id_used_bitmap = NULL; 728 } 729 } 730 #endif /* BCM_TRIUMPH3_SUPPORT */ 731 if (_trident_hg_dlb_bk[unit]->hg_dlb_load_weight) { 732 sal_free(_trident_hg_dlb_bk[unit]->hg_dlb_load_weight); 733 _trident_hg_dlb_bk[unit]->hg_dlb_load_weight = NULL; 734 } 735 if (_trident_hg_dlb_bk[unit]->hg_dlb_quality_map_profile) { 736 soc_profile_mem_destroy(unit, 737 _trident_hg_dlb_bk[unit]->hg_dlb_quality_map_profile); 738 sal_free(_trident_hg_dlb_bk[unit]->hg_dlb_quality_map_profile); 739 _trident_hg_dlb_bk[unit]->hg_dlb_quality_map_profile = NULL; 740 } 741 742 sal_free(_trident_hg_dlb_bk[unit]); 743 _trident_hg_dlb_bk[unit] = NULL; 744 } 745 746 /* Disable DLB HGT refresh */ 747 dlb_refresh_f = soc_reg_field_valid(unit, AUX_ARB_CONTROL_2r, 748 DLB_HGT_REFRESH_ENABLEf) ? DLB_HGT_REFRESH_ENABLEf : 749 DLB_REFRESH_ENABLEf; 750 rv = READ_AUX_ARB_CONTROL_2r(unit, &arb_control_reg); 751 if (BCM_SUCCESS(rv)) { 752 soc_reg_field_set(unit, AUX_ARB_CONTROL_2r, &arb_control_reg, 753 dlb_refresh_f, 0); 754 if (soc_reg_field_valid(unit, AUX_ARB_CONTROL_2r, 755 DLB_HGT_256NS_REFRESH_ENABLEf)) { 756 soc_reg_field_set(unit, AUX_ARB_CONTROL_2r, &arb_control_reg, 757 DLB_HGT_256NS_REFRESH_ENABLEf, 0); 758 } else if (soc_reg_field_valid(unit, AUX_ARB_CONTROL_2r, 759 DLB_1US_TICK_ENABLEf)) { 760 soc_reg_field_set(unit, AUX_ARB_CONTROL_2r, &arb_control_reg, 761 DLB_1US_TICK_ENABLEf, 0); 762 } 763 (void)WRITE_AUX_ARB_CONTROL_2r(unit, arb_control_reg); 764 } 765 766 #ifdef BCM_TRIUMPH3_SUPPORT 767 if (soc_reg_field_valid(unit, SW2_HW_CONTROLr, ENABLE_HGT_DLBf)) { 768 uint32 sw2_hw_control_reg; 769 770 rv = READ_SW2_HW_CONTROLr(unit, &sw2_hw_control_reg); 771 if (BCM_SUCCESS(rv)) { 772 soc_reg_field_set(unit, SW2_HW_CONTROLr, &sw2_hw_control_reg, 773 ENABLE_HGT_DLBf, 0); 774 (void)WRITE_SW2_HW_CONTROLr(unit, sw2_hw_control_reg); 775 } 776 } 777 #endif /* BCM_TRIUMPH3_SUPPORT */ 778 779 } 780 781 /* 782 * Function: 783 * _bcm_trident_hg_dlb_init 784 * Purpose: 785 * Allocate and initialize _trident_hg_dlb_bk 786 * Parameters: 787 * unit - (IN)SOC unit number. 788 * Returns: 789 * BCM_X_XXX 790 */ 791 STATIC int 792 _bcm_trident_hg_dlb_init(int unit) 793 { 794 int num_hg_dlb_id; 795 int hg_flowset_tbl_size; 796 int total_num_blocks; 797 int rv = BCM_E_NONE; 798 uint32 quantize_control_reg; 799 bcm_port_t port; 800 uint32 measure_update_control_reg; 801 soc_field_t dlb_refresh_f; 802 uint32 arb_control_reg; 803 uint64 arb_control_reg_64; 804 int num_quality_map_profiles = 0; 805 806 if (_trident_hg_dlb_bk[unit] == NULL) { 807 _trident_hg_dlb_bk[unit] = sal_alloc( 808 sizeof(_trident_hg_dlb_bookkeeping_t), "_trident_hg_dlb_bk"); 809 if (_trident_hg_dlb_bk[unit] == NULL) { 810 return BCM_E_MEMORY; 811 } 812 } 813 sal_memset(_trident_hg_dlb_bk[unit], 0, 814 sizeof(_trident_hg_dlb_bookkeeping_t)); 815 816 num_hg_dlb_id = soc_mem_index_count(unit, DLB_HGT_GROUP_CONTROLm); 817 if (_trident_hg_dlb_bk[unit]->hg_dlb_id_used_bitmap == NULL) { 818 _trident_hg_dlb_bk[unit]->hg_dlb_id_used_bitmap = 819 sal_alloc(SHR_BITALLOCSIZE(num_hg_dlb_id), "hg_dlb_id_used_bitmap"); 820 if (_trident_hg_dlb_bk[unit]->hg_dlb_id_used_bitmap == NULL) { 821 _bcm_trident_hg_dlb_deinit(unit); 822 return BCM_E_MEMORY; 823 } 824 } 825 sal_memset(_trident_hg_dlb_bk[unit]->hg_dlb_id_used_bitmap, 0, 826 SHR_BITALLOCSIZE(num_hg_dlb_id)); 827 828 #ifdef BCM_TRIUMPH3_SUPPORT 829 if (soc_feature(unit, soc_feature_hg_dlb_member_id)) { 830 hg_flowset_tbl_size = soc_mem_index_count(unit, DLB_HGT_FLOWSETm); 831 } else 832 #endif 833 { 834 hg_flowset_tbl_size = soc_mem_index_count(unit, DLB_HGT_FLOWSET_PORTm); 835 } 836 /* Each bit in hg_dlb_flowset_block_bitmap corresponds to a block of 512 837 * flow set table entries. 838 */ 839 total_num_blocks = hg_flowset_tbl_size / 512; 840 if (_trident_hg_dlb_bk[unit]->hg_dlb_flowset_block_bitmap == NULL) { 841 _trident_hg_dlb_bk[unit]->hg_dlb_flowset_block_bitmap = 842 sal_alloc(SHR_BITALLOCSIZE(total_num_blocks), 843 "hg_dlb_flowset_block_bitmap"); 844 if (_trident_hg_dlb_bk[unit]->hg_dlb_flowset_block_bitmap == NULL) { 845 _bcm_trident_hg_dlb_deinit(unit); 846 return BCM_E_MEMORY; 847 } 848 } 849 sal_memset(_trident_hg_dlb_bk[unit]->hg_dlb_flowset_block_bitmap, 0, 850 SHR_BITALLOCSIZE(total_num_blocks)); 851 852 #ifdef BCM_TRIUMPH3_SUPPORT 853 if (soc_feature(unit, soc_feature_hg_dlb_member_id)) { 854 int num_hg_dlb_member_id; 855 soc_field_t profile_ptr_f; 856 857 num_hg_dlb_member_id = soc_mem_index_count(unit, 858 DLB_HGT_MEMBER_ATTRIBUTEm); 859 if (_trident_hg_dlb_bk[unit]->hg_dlb_member_id_used_bitmap == NULL) { 860 _trident_hg_dlb_bk[unit]->hg_dlb_member_id_used_bitmap = 861 sal_alloc(SHR_BITALLOCSIZE(num_hg_dlb_member_id), 862 "hg_dlb_member_id_used_bitmap"); 863 if (_trident_hg_dlb_bk[unit]->hg_dlb_member_id_used_bitmap == NULL) { 864 _bcm_trident_hg_dlb_deinit(unit); 865 return BCM_E_MEMORY; 866 } 867 } 868 sal_memset(_trident_hg_dlb_bk[unit]->hg_dlb_member_id_used_bitmap, 0, 869 SHR_BITALLOCSIZE(num_hg_dlb_member_id)); 870 871 profile_ptr_f = soc_mem_field_valid(unit, DLB_HGT_QUALITY_CONTROLm, 872 PROFILE_PTRf) ? PROFILE_PTRf : QMT_PROFILE_PTRf; 873 num_quality_map_profiles = 1 << soc_mem_field_length(unit, 874 DLB_HGT_QUALITY_CONTROLm, profile_ptr_f); 875 } else 876 #endif /* BCM_TRIUMPH3_SUPPORT */ 877 { 878 num_quality_map_profiles = 1 << soc_reg_field_length(unit, 879 DLB_HGT_QUANTIZE_CONTROLr, PORT_QUALITY_MAPPING_PROFILE_PTRf); 880 } 881 882 if (_trident_hg_dlb_bk[unit]->hg_dlb_load_weight == NULL) { 883 _trident_hg_dlb_bk[unit]->hg_dlb_load_weight = 884 sal_alloc(num_quality_map_profiles * sizeof(uint8), 885 "hg_dlb_load_weight"); 886 if (_trident_hg_dlb_bk[unit]->hg_dlb_load_weight == NULL) { 887 _bcm_trident_hg_dlb_deinit(unit); 888 return BCM_E_MEMORY; 889 } 890 } 891 sal_memset(_trident_hg_dlb_bk[unit]->hg_dlb_load_weight, 0, 892 num_quality_map_profiles * sizeof(uint8)); 893 894 /* Initialize port quality mapping profile */ 895 rv = _bcm_trident_hg_dlb_quality_map_profile_init(unit); 896 if (BCM_FAILURE(rv)) { 897 _bcm_trident_hg_dlb_deinit(unit); 898 return rv; 899 } 900 901 if (!SOC_WARM_BOOT(unit)) { 902 /* Set Higig DLB sampling period and port load thresholds */ 903 rv = _bcm_trident_hg_dlb_sample_rate_thresholds_set(unit, 1000000, 904 1250, 8750); 905 if (BCM_FAILURE(rv)) { 906 _bcm_trident_hg_dlb_deinit(unit); 907 return rv; 908 } 909 910 /* Configure Higig DLB port load EWMA weight */ 911 rv = _bcm_trident_hg_dlb_config_set(unit, 912 bcmSwitchFabricTrunkDynamicEgressBytesExponent, 0); 913 if (BCM_FAILURE(rv)) { 914 _bcm_trident_hg_dlb_deinit(unit); 915 return rv; 916 } 917 918 /* Configure Higig DLB port queue size EWMA weight */ 919 rv = _bcm_trident_hg_dlb_config_set(unit, 920 bcmSwitchFabricTrunkDynamicQueuedBytesExponent, 0); 921 if (BCM_FAILURE(rv)) { 922 _bcm_trident_hg_dlb_deinit(unit); 923 return rv; 924 } 925 926 /* Configure Higig DLB port load cap control */ 927 rv = _bcm_trident_hg_dlb_config_set(unit, 928 bcmSwitchFabricTrunkDynamicEgressBytesDecreaseReset, 0); 929 if (BCM_FAILURE(rv)) { 930 _bcm_trident_hg_dlb_deinit(unit); 931 return rv; 932 } 933 934 /* Configure Higig DLB port queue size cap control */ 935 rv = _bcm_trident_hg_dlb_config_set(unit, 936 bcmSwitchFabricTrunkDynamicQueuedBytesDecreaseReset, 0); 937 if (BCM_FAILURE(rv)) { 938 _bcm_trident_hg_dlb_deinit(unit); 939 return rv; 940 } 941 942 /* Configure Higig DLB port queue size thresholds */ 943 rv = _bcm_trident_hg_dlb_qsize_thresholds_set(unit, 0, 0); 944 if (BCM_FAILURE(rv)) { 945 _bcm_trident_hg_dlb_deinit(unit); 946 return rv; 947 } 948 949 /* Disable link status override by software */ 950 if (soc_mem_is_valid(unit, DLB_HGT_LINK_CONTROLm)) { 951 rv = soc_mem_clear(unit, DLB_HGT_LINK_CONTROLm, MEM_BLOCK_ALL, 0); 952 } else { 953 rv = soc_mem_clear(unit, DLB_HGT_MEMBER_SW_STATEm, MEM_BLOCK_ALL, 0); 954 } 955 if (BCM_FAILURE(rv)) { 956 _bcm_trident_hg_dlb_deinit(unit); 957 return rv; 958 } 959 960 /* Disable all HGT DLB groups */ 961 if (SOC_MEM_IS_VALID(unit, HGT_DLB_CONTROLm)) { 962 rv = soc_mem_clear(unit, HGT_DLB_CONTROLm, MEM_BLOCK_ALL, 0); 963 if (BCM_FAILURE(rv)) { 964 _bcm_trident_hg_dlb_deinit(unit); 965 return rv; 966 } 967 } else { 968 rv = soc_mem_clear(unit, DLB_HGT_GROUP_CONTROLm, MEM_BLOCK_ALL, 0); 969 if (BCM_FAILURE(rv)) { 970 _bcm_trident_hg_dlb_deinit(unit); 971 return rv; 972 } 973 } 974 975 #ifdef BCM_TRIUMPH3_SUPPORT 976 if (soc_feature(unit, soc_feature_hg_dlb_member_id)) { 977 int member_id; 978 dlb_hgt_quality_control_entry_t quality_control_entry; 979 soc_field_t enable_credit_collect_f; 980 981 /* Clear group membership */ 982 rv = soc_mem_clear(unit, DLB_HGT_GROUP_MEMBERSHIPm, MEM_BLOCK_ALL, 0); 983 if (BCM_FAILURE(rv)) { 984 _bcm_trident_hg_dlb_deinit(unit); 985 return rv; 986 } 987 988 /* Clear port<->member mapping tables */ 989 rv = soc_mem_clear(unit, DLB_HGT_PORT_MEMBER_MAPm, MEM_BLOCK_ALL, 0); 990 if (BCM_FAILURE(rv)) { 991 _bcm_trident_hg_dlb_deinit(unit); 992 return rv; 993 } 994 rv = soc_mem_clear(unit, DLB_HGT_MEMBER_ATTRIBUTEm, MEM_BLOCK_ALL, 0); 995 if (BCM_FAILURE(rv)) { 996 _bcm_trident_hg_dlb_deinit(unit); 997 return rv; 998 } 999 1000 /* Clear per member threshold scaling factor and 1001 * quality measure update control. 1002 */ 1003 for (member_id = 0; 1004 member_id < soc_mem_index_count(unit, 1005 DLB_HGT_QUALITY_CONTROLm); 1006 member_id++) { 1007 rv = READ_DLB_HGT_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY, 1008 member_id, &quality_control_entry); 1009 if (SOC_FAILURE(rv)) { 1010 _bcm_trident_hg_dlb_deinit(unit); 1011 return rv; 1012 } 1013 soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit, 1014 &quality_control_entry, ENABLE_AVG_CALCf, 0); 1015 soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit, 1016 &quality_control_entry, ENABLE_QUALITY_UPDATEf, 0); 1017 enable_credit_collect_f = soc_mem_field_valid(unit, 1018 DLB_HGT_QUALITY_CONTROLm, ENABLE_CREDIT_COLLECTIONf) ? 1019 ENABLE_CREDIT_COLLECTIONf : ENB_CREDIT_COLLECTIONf; 1020 soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit, 1021 &quality_control_entry, enable_credit_collect_f, 0); 1022 soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit, 1023 &quality_control_entry, LOADING_SCALING_FACTORf, 0); 1024 soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit, 1025 &quality_control_entry, QSIZE_SCALING_FACTORf, 0); 1026 rv = WRITE_DLB_HGT_QUALITY_CONTROLm(unit, MEM_BLOCK_ALL, 1027 member_id, &quality_control_entry); 1028 if (SOC_FAILURE(rv)) { 1029 _bcm_trident_hg_dlb_deinit(unit); 1030 return rv; 1031 } 1032 } 1033 } else 1034 #endif /* BCM_TRIUMPH3_SUPPORT */ 1035 { 1036 /* Clear per port threshold scaling factor and 1037 * quality measure update control. 1038 */ 1039 PBMP_ALL_ITER(unit, port) { 1040 rv = READ_DLB_HGT_QUANTIZE_CONTROLr(unit, port, 1041 &quantize_control_reg); 1042 if (BCM_FAILURE(rv)) { 1043 _bcm_trident_hg_dlb_deinit(unit); 1044 return rv; 1045 } 1046 soc_reg_field_set(unit, DLB_HGT_QUANTIZE_CONTROLr, 1047 &quantize_control_reg, 1048 PORT_LOADING_THRESHOLD_SCALING_FACTORf, 0); 1049 soc_reg_field_set(unit, DLB_HGT_QUANTIZE_CONTROLr, 1050 &quantize_control_reg, 1051 PORT_QSIZE_THRESHOLD_SCALING_FACTORf, 0); 1052 rv = WRITE_DLB_HGT_QUANTIZE_CONTROLr(unit, port, 1053 quantize_control_reg); 1054 if (BCM_FAILURE(rv)) { 1055 _bcm_trident_hg_dlb_deinit(unit); 1056 return rv; 1057 } 1058 1059 rv = READ_DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr(unit, 1060 port, &measure_update_control_reg); 1061 if (BCM_FAILURE(rv)) { 1062 _bcm_trident_hg_dlb_deinit(unit); 1063 return rv; 1064 } 1065 soc_reg_field_set(unit, 1066 DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr, 1067 &measure_update_control_reg, 1068 ENABLE_MEASURE_COLLECTIONf, 0); 1069 soc_reg_field_set(unit, 1070 DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr, 1071 &measure_update_control_reg, 1072 ENABLE_MEASURE_AVERAGE_CALCULATIONf, 0); 1073 soc_reg_field_set(unit, 1074 DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr, 1075 &measure_update_control_reg, 1076 ENABLE_PORT_QUALITY_UPDATEf, 0); 1077 rv = WRITE_DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr(unit, 1078 port, measure_update_control_reg); 1079 if (BCM_FAILURE(rv)) { 1080 _bcm_trident_hg_dlb_deinit(unit); 1081 return rv; 1082 } 1083 } 1084 } 1085 1086 /* Enable DLB HGT refresh */ 1087 /* coverity[result_independent_of_operands] */ 1088 if (SOC_REG_IS_VALID(unit, AUX_ARB_CONTROL_2r)) { 1089 dlb_refresh_f = soc_reg_field_valid(unit, AUX_ARB_CONTROL_2r, 1090 DLB_HGT_REFRESH_ENABLEf) ? 1091 DLB_HGT_REFRESH_ENABLEf : DLB_REFRESH_ENABLEf; 1092 rv = READ_AUX_ARB_CONTROL_2r(unit, &arb_control_reg); 1093 if (BCM_SUCCESS(rv)) { 1094 soc_reg_field_set(unit, AUX_ARB_CONTROL_2r, &arb_control_reg, 1095 dlb_refresh_f, 1); 1096 if (soc_reg_field_valid(unit, AUX_ARB_CONTROL_2r, 1097 DLB_HGT_256NS_REFRESH_ENABLEf)) { 1098 soc_reg_field_set(unit, AUX_ARB_CONTROL_2r, &arb_control_reg, 1099 DLB_HGT_256NS_REFRESH_ENABLEf, 1); 1100 } else if (soc_reg_field_valid(unit, AUX_ARB_CONTROL_2r, 1101 DLB_1US_TICK_ENABLEf)) { 1102 soc_reg_field_set(unit, AUX_ARB_CONTROL_2r, &arb_control_reg, 1103 DLB_1US_TICK_ENABLEf, 1); 1104 } 1105 rv = WRITE_AUX_ARB_CONTROL_2r(unit, arb_control_reg); 1106 } 1107 if (BCM_FAILURE(rv)) { 1108 _bcm_trident_hg_dlb_deinit(unit); 1109 return rv; 1110 } 1111 /* coverity[result_independent_of_operands] */ 1112 } else if (SOC_REG_IS_VALID(unit, AUX_ARB_CONTROL_2_64r)) { 1113 dlb_refresh_f = soc_reg_field_valid(unit, AUX_ARB_CONTROL_2_64r, 1114 DLB_HGT_REFRESH_ENABLEf) ? 1115 DLB_HGT_REFRESH_ENABLEf : DLB_REFRESH_ENABLEf; 1116 rv = READ_AUX_ARB_CONTROL_2_64r(unit, &arb_control_reg_64); 1117 if (BCM_SUCCESS(rv)) { 1118 soc_reg64_field32_set(unit, AUX_ARB_CONTROL_2_64r, &arb_control_reg_64, 1119 dlb_refresh_f, 1); 1120 if (soc_reg_field_valid(unit, AUX_ARB_CONTROL_2_64r, 1121 DLB_HGT_256NS_REFRESH_ENABLEf)) { 1122 soc_reg64_field32_set(unit, AUX_ARB_CONTROL_2_64r, &arb_control_reg_64, 1123 DLB_HGT_256NS_REFRESH_ENABLEf, 1); 1124 } else if (soc_reg_field_valid(unit, AUX_ARB_CONTROL_2_64r, 1125 DLB_1US_TICK_ENABLEf)) { 1126 soc_reg64_field32_set(unit, AUX_ARB_CONTROL_2_64r, &arb_control_reg_64, 1127 DLB_1US_TICK_ENABLEf, 1); 1128 } 1129 rv = WRITE_AUX_ARB_CONTROL_2_64r(unit, arb_control_reg_64); 1130 } 1131 if (BCM_FAILURE(rv)) { 1132 _bcm_trident_hg_dlb_deinit(unit); 1133 return rv; 1134 } 1135 } 1136 1137 #ifdef BCM_TRIUMPH3_SUPPORT 1138 if (soc_reg_field_valid(unit, SW2_HW_CONTROLr, ENABLE_HGT_DLBf)) { 1139 uint32 sw2_hw_control_reg; 1140 1141 rv = READ_SW2_HW_CONTROLr(unit, &sw2_hw_control_reg); 1142 if (BCM_SUCCESS(rv)) { 1143 soc_reg_field_set(unit, SW2_HW_CONTROLr, &sw2_hw_control_reg, 1144 ENABLE_HGT_DLBf, 1); 1145 rv = WRITE_SW2_HW_CONTROLr(unit, sw2_hw_control_reg); 1146 } 1147 if (BCM_FAILURE(rv)) { 1148 _bcm_trident_hg_dlb_deinit(unit); 1149 return rv; 1150 } 1151 } 1152 #endif /* BCM_TRIUMPH3_SUPPORT */ 1153 1154 /* Configure Ethertype eligibility */ 1155 #ifdef BCM_TRIUMPH3_SUPPORT 1156 if (soc_mem_is_valid(unit, DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm)) { 1157 uint32 measure_control_reg; 1158 1159 rv = soc_mem_clear(unit, DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm, 1160 MEM_BLOCK_ALL, 0); 1161 if (BCM_FAILURE(rv)) { 1162 _bcm_trident_hg_dlb_deinit(unit); 1163 return rv; 1164 } 1165 rv = READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, 1166 &measure_control_reg); 1167 if (SOC_SUCCESS(rv)) { 1168 soc_reg_field_set(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr, 1169 &measure_control_reg, 1170 ETHERTYPE_ELIGIBILITY_CONFIGf, 0); 1171 soc_reg_field_set(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr, 1172 &measure_control_reg, 1173 INNER_OUTER_ETHERTYPE_SELECTIONf, 0); 1174 rv = WRITE_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, 1175 measure_control_reg); 1176 } 1177 if (BCM_FAILURE(rv)) { 1178 _bcm_trident_hg_dlb_deinit(unit); 1179 return rv; 1180 } 1181 } 1182 #endif /* BCM_TRIUMPH3_SUPPORT */ 1183 1184 } 1185 1186 return rv; 1187 } 1188 1189 /* 1190 * Function: 1191 * _bcm_trident_hg_trunk_override_profile_deinit 1192 * Purpose: 1193 * Deallocate _trident_hg_trunk_override_profile 1194 * Parameters: 1195 * unit - (IN)SOC unit number. 1196 * Returns: 1197 * BCM_X_XXX 1198 */ 1199 STATIC void 1200 _bcm_trident_hg_trunk_override_profile_deinit(int unit) 1201 { 1202 if (_trident_hg_trunk_override_profile[unit]) { 1203 (void)soc_profile_mem_destroy(unit, _trident_hg_trunk_override_profile[unit]); 1204 sal_free(_trident_hg_trunk_override_profile[unit]); 1205 _trident_hg_trunk_override_profile[unit] = NULL; 1206 } 1207 } 1208 1209 /* 1210 * Function: 1211 * _bcm_trident_hg_trunk_override_profile_init 1212 * Purpose: 1213 * Allocate and initialize _trident_hg_trunk_override_profile 1214 * Parameters: 1215 * unit - (IN)SOC unit number. 1216 * Returns: 1217 * BCM_X_XXX 1218 */ 1219 STATIC int 1220 _bcm_trident_hg_trunk_override_profile_init(int unit) 1221 { 1222 soc_mem_t mem; 1223 int entry_words; 1224 void *entry_ptr; 1225 int ref_count; 1226 uint32 index; 1227 int i; 1228 uint32 profile_ptr; 1229 vlan_tab_entry_t vlan_tab_entry; 1230 l2mc_entry_t l2mc_entry; 1231 ipmc_entry_t ipmc_entry; 1232 ifp_redirection_profile_entry_t ifp_redirection_profile_entry; 1233 1234 if (_trident_hg_trunk_override_profile[unit] == NULL) { 1235 _trident_hg_trunk_override_profile[unit] = 1236 sal_alloc(sizeof(soc_profile_mem_t), "HG Trunk Override Profile Mem"); 1237 if (_trident_hg_trunk_override_profile[unit] == NULL) { 1238 return BCM_E_MEMORY; 1239 } 1240 } else { 1241 soc_profile_mem_destroy(unit, _trident_hg_trunk_override_profile[unit]); 1242 } 1243 soc_profile_mem_t_init(_trident_hg_trunk_override_profile[unit]); 1244 1245 /* Create profile table cache (or re-init if it already exists) */ 1246 mem = ING_HIGIG_TRUNK_OVERRIDE_PROFILEm; 1247 entry_words = sizeof(ing_higig_trunk_override_profile_entry_t) / sizeof(uint32); 1248 SOC_IF_ERROR_RETURN 1249 (soc_profile_mem_create(unit, &mem, &entry_words, 1, 1250 _trident_hg_trunk_override_profile[unit])); 1251 1252 if (!SOC_WARM_BOOT(unit)) { 1253 /* By default, VLAN, L2MC, IPMC, and IFP Redirection Profile tables' Higig 1254 * trunk override profile pointer is 0. Add a profile at index 0 of 1255 * ING_HIGIG_TRUNK_OVERRIDE_PROFILE table with the reference count equal 1256 * to the number of entries in VLAN, L2MC, IPMC, and IFP Redirection 1257 * Profile tables. 1258 */ 1259 entry_ptr = soc_mem_entry_null(unit, ING_HIGIG_TRUNK_OVERRIDE_PROFILEm); 1260 SOC_IF_ERROR_RETURN 1261 (soc_profile_mem_add(unit, _trident_hg_trunk_override_profile[unit], 1262 &entry_ptr, 1, &index)); 1263 ref_count = soc_mem_index_count(unit, VLAN_TABm); 1264 ref_count += soc_mem_index_count(unit, L2MCm); 1265 ref_count += soc_mem_index_count(unit, L3_IPMCm); 1266 ref_count += soc_mem_index_count(unit, IFP_REDIRECTION_PROFILEm); 1267 SOC_PROFILE_MEM_REFERENCE(unit, _trident_hg_trunk_override_profile[unit], 1268 index, ref_count - 1); 1269 } else { /* Warm boot, recover reference counts and entries_per_set */ 1270 1271 /* Recover from VLAN_TAB */ 1272 for (i = soc_mem_index_min(unit, VLAN_TABm); 1273 i <= soc_mem_index_max(unit, VLAN_TABm); 1274 i++) { 1275 SOC_IF_ERROR_RETURN 1276 (READ_VLAN_TABm(unit, MEM_BLOCK_ANY, i, &vlan_tab_entry)); 1277 profile_ptr = soc_VLAN_TABm_field32_get(unit, &vlan_tab_entry, 1278 HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf); 1279 SOC_PROFILE_MEM_REFERENCE(unit, 1280 _trident_hg_trunk_override_profile[unit], 1281 profile_ptr, 1); 1282 SOC_PROFILE_MEM_ENTRIES_PER_SET(unit, 1283 _trident_hg_trunk_override_profile[unit], 1284 profile_ptr, 1); 1285 } 1286 1287 /* Recover from L2MC */ 1288 for (i = soc_mem_index_min(unit, L2MCm); 1289 i <= soc_mem_index_max(unit, L2MCm); 1290 i++) { 1291 SOC_IF_ERROR_RETURN 1292 (READ_L2MCm(unit, MEM_BLOCK_ANY, i, &l2mc_entry)); 1293 profile_ptr = soc_L2MCm_field32_get(unit, &l2mc_entry, 1294 HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf); 1295 SOC_PROFILE_MEM_REFERENCE(unit, 1296 _trident_hg_trunk_override_profile[unit], 1297 profile_ptr, 1); 1298 SOC_PROFILE_MEM_ENTRIES_PER_SET(unit, 1299 _trident_hg_trunk_override_profile[unit], 1300 profile_ptr, 1); 1301 } 1302 1303 /* Recover from IPMC */ 1304 for (i = soc_mem_index_min(unit, L3_IPMCm); 1305 i <= soc_mem_index_max(unit, L3_IPMCm); 1306 i++) { 1307 SOC_IF_ERROR_RETURN 1308 (READ_L3_IPMCm(unit, MEM_BLOCK_ANY, i, &ipmc_entry)); 1309 profile_ptr = soc_L3_IPMCm_field32_get(unit, &ipmc_entry, 1310 HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf); 1311 SOC_PROFILE_MEM_REFERENCE(unit, 1312 _trident_hg_trunk_override_profile[unit], 1313 profile_ptr, 1); 1314 SOC_PROFILE_MEM_ENTRIES_PER_SET(unit, 1315 _trident_hg_trunk_override_profile[unit], 1316 profile_ptr, 1); 1317 } 1318 1319 /* Recover from IFP_REDIRECTION_PROFILE */ 1320 for (i = soc_mem_index_min(unit, IFP_REDIRECTION_PROFILEm); 1321 i <= soc_mem_index_max(unit, IFP_REDIRECTION_PROFILEm); 1322 i++) { 1323 SOC_IF_ERROR_RETURN 1324 (READ_IFP_REDIRECTION_PROFILEm(unit, MEM_BLOCK_ANY, i, 1325 &ifp_redirection_profile_entry)); 1326 profile_ptr = soc_IFP_REDIRECTION_PROFILEm_field32_get(unit, 1327 &ifp_redirection_profile_entry, 1328 HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf); 1329 SOC_PROFILE_MEM_REFERENCE(unit, 1330 _trident_hg_trunk_override_profile[unit], 1331 profile_ptr, 1); 1332 SOC_PROFILE_MEM_ENTRIES_PER_SET(unit, 1333 _trident_hg_trunk_override_profile[unit], 1334 profile_ptr, 1); 1335 } 1336 } 1337 1338 return BCM_E_NONE; 1339 } 1340 1341 /* 1342 * Function: 1343 * _bcm_trident_trunk_hwfailover_deinit 1344 * Purpose: 1345 * Deallocate _trident_trunk_hwfail 1346 * Parameters: 1347 * unit - (IN)SOC unit number. 1348 * Returns: 1349 * None 1350 */ 1351 STATIC void 1352 _bcm_trident_trunk_hwfailover_deinit(int unit) 1353 { 1354 int trunk_num_groups; 1355 int i; 1356 1357 if (_trident_trunk_hwfail[unit]) { 1358 if (_trident_trunk_hwfail[unit]->hw_tinfo) { 1359 trunk_num_groups = soc_mem_index_count(unit, TRUNK_GROUPm) + 1360 soc_mem_index_count(unit, HG_TRUNK_GROUPm); 1361 for (i = 0; i < trunk_num_groups; i++) { 1362 if (_trident_trunk_hwfail[unit]->hw_tinfo[i].modport) { 1363 sal_free(_trident_trunk_hwfail[unit]->hw_tinfo[i].modport); 1364 _trident_trunk_hwfail[unit]->hw_tinfo[i].modport = NULL; 1365 } 1366 if (_trident_trunk_hwfail[unit]->hw_tinfo[i].psc) { 1367 sal_free(_trident_trunk_hwfail[unit]->hw_tinfo[i].psc); 1368 _trident_trunk_hwfail[unit]->hw_tinfo[i].psc = NULL; 1369 } 1370 if (_trident_trunk_hwfail[unit]->hw_tinfo[i].flags) { 1371 sal_free(_trident_trunk_hwfail[unit]->hw_tinfo[i].flags); 1372 _trident_trunk_hwfail[unit]->hw_tinfo[i].flags = NULL; 1373 } 1374 } 1375 sal_free(_trident_trunk_hwfail[unit]->hw_tinfo); 1376 _trident_trunk_hwfail[unit]->hw_tinfo = NULL; 1377 } 1378 sal_free(_trident_trunk_hwfail[unit]); 1379 _trident_trunk_hwfail[unit] = NULL; 1380 } 1381 } 1382 1383 /* 1384 * Function: 1385 * _bcm_trident_trunk_hwfailover_init 1386 * Purpose: 1387 * Allocate and initialize _trident_trunk_hwfail 1388 * Parameters: 1389 * unit - (IN)SOC unit number. 1390 * Returns: 1391 * BCM_X_XXX 1392 */ 1393 STATIC int 1394 _bcm_trident_trunk_hwfailover_init(int unit) 1395 { 1396 int trunk_num_groups; 1397 1398 if (_trident_trunk_hwfail[unit] == NULL) { 1399 _trident_trunk_hwfail[unit] = sal_alloc(sizeof(_trident_trunk_hwfail_t), 1400 "_trident_trunk_hwfail"); 1401 if (_trident_trunk_hwfail[unit] == NULL) { 1402 return BCM_E_MEMORY; 1403 } 1404 } 1405 sal_memset(_trident_trunk_hwfail[unit], 0, sizeof(_trident_trunk_hwfail_t)); 1406 1407 trunk_num_groups = soc_mem_index_count(unit, TRUNK_GROUPm) + 1408 soc_mem_index_count(unit, HG_TRUNK_GROUPm); 1409 if (_trident_trunk_hwfail[unit]->hw_tinfo == NULL) { 1410 _trident_trunk_hwfail[unit]->hw_tinfo = 1411 sal_alloc(sizeof(_trident_hw_tinfo_t) * trunk_num_groups, 1412 "_trident_trunk_hwfail_hw_tinfo"); 1413 if (_trident_trunk_hwfail[unit]->hw_tinfo == NULL) { 1414 _bcm_trident_trunk_hwfailover_deinit(unit); 1415 return BCM_E_MEMORY; 1416 } 1417 } 1418 sal_memset(_trident_trunk_hwfail[unit]->hw_tinfo, 0, 1419 sizeof(_trident_hw_tinfo_t) * trunk_num_groups); 1420 1421 /* Note: The maximum number of member ports in a trunk group is 256 in Trident. 1422 * But it would be quite wasteful to allocate 256 entries to each 1423 * _trident_trunk_hwfail[unit]->hw_tinfo[x].modport/psc/flags arrays. 1424 * These arrays will be allocated as member ports are added to trunk group. 1425 */ 1426 1427 return BCM_E_NONE; 1428 } 1429 1430 /* 1431 * Function: 1432 * _bcm_trident_trunk_swfailover_deinit 1433 * Purpose: 1434 * Deallocate _trident_trunk_swfail 1435 * Parameters: 1436 * unit - (IN)SOC unit number. 1437 * Returns: 1438 * None 1439 */ 1440 STATIC void 1441 _bcm_trident_trunk_swfailover_deinit(int unit) 1442 { 1443 int trunk_num_groups; 1444 int i; 1445 1446 if (_trident_trunk_swfail[unit]) { 1447 if (_trident_trunk_swfail[unit]->tinfo) { 1448 trunk_num_groups = soc_mem_index_count(unit, TRUNK_GROUPm) + 1449 soc_mem_index_count(unit, HG_TRUNK_GROUPm); 1450 for (i = 0; i < trunk_num_groups; i++) { 1451 if (_trident_trunk_swfail[unit]->tinfo[i].modport) { 1452 sal_free(_trident_trunk_swfail[unit]->tinfo[i].modport); 1453 _trident_trunk_swfail[unit]->tinfo[i].modport = NULL; 1454 } 1455 } 1456 sal_free(_trident_trunk_swfail[unit]->tinfo); 1457 _trident_trunk_swfail[unit]->tinfo = NULL; 1458 } 1459 sal_free(_trident_trunk_swfail[unit]); 1460 _trident_trunk_swfail[unit] = NULL; 1461 } 1462 } 1463 1464 /* 1465 * Function: 1466 * _bcm_trident_trunk_swfailover_init 1467 * Purpose: 1468 * Allocate and initialize _trident_trunk_swfail 1469 * Parameters: 1470 * unit - (IN)SOC unit number. 1471 * Returns: 1472 * BCM_X_XXX 1473 */ 1474 STATIC int 1475 _bcm_trident_trunk_swfailover_init(int unit) 1476 { 1477 int trunk_num_groups; 1478 1479 if (_trident_trunk_swfail[unit] == NULL) { 1480 _trident_trunk_swfail[unit] = sal_alloc(sizeof(_trident_trunk_swfail_t), 1481 "_trident_trunk_swfail"); 1482 if (_trident_trunk_swfail[unit] == NULL) { 1483 return BCM_E_MEMORY; 1484 } 1485 } 1486 sal_memset(_trident_trunk_swfail[unit], 0, sizeof(_trident_trunk_swfail_t)); 1487 1488 trunk_num_groups = soc_mem_index_count(unit, TRUNK_GROUPm) + 1489 soc_mem_index_count(unit, HG_TRUNK_GROUPm); 1490 if (_trident_trunk_swfail[unit]->tinfo == NULL) { 1491 _trident_trunk_swfail[unit]->tinfo = 1492 sal_alloc(sizeof(_trident_tinfo_t) * trunk_num_groups, 1493 "_trident_trunk_swfail_tinfo"); 1494 if (_trident_trunk_swfail[unit]->tinfo == NULL) { 1495 _bcm_trident_trunk_swfailover_deinit(unit); 1496 return BCM_E_MEMORY; 1497 } 1498 } 1499 sal_memset(_trident_trunk_swfail[unit]->tinfo, 0, 1500 sizeof(_trident_tinfo_t) * trunk_num_groups); 1501 1502 /* Note: The maximum number of member ports in a trunk group is 256 in Trident. 1503 * But it would be quite wasteful to allocate 256 entries to each 1504 * _trident_trunk_swfail[unit]->tinfo[x].modport array. The modport 1505 * array will be allocated as member ports are added to trunk group. 1506 */ 1507 1508 return BCM_E_NONE; 1509 } 1510 1511 /* 1512 * Function: 1513 * _bcm_trident_trunk_deinit 1514 * Purpose: 1515 * Deallocate global data structures 1516 * Parameters: 1517 * unit - (IN)SOC unit number. 1518 * Returns: 1519 * BCM_E_xxx 1520 */ 1521 void 1522 _bcm_trident_trunk_deinit(int unit) 1523 { 1524 _bcm_trident_trunk_member_info_deinit(unit); 1525 1526 _bcm_trident_trunk_mod_port_map_deinit(unit); 1527 1528 _bcm_trident_trunk_member_bk_deinit(unit); 1529 1530 if (soc_feature(unit, soc_feature_hg_dlb) && 1531 !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 1532 _bcm_trident_hg_dlb_deinit(unit); 1533 } 1534 1535 #ifdef BCM_TRIUMPH3_SUPPORT 1536 if (soc_feature(unit, soc_feature_lag_dlb) && 1537 !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 1538 bcm_tr3_lag_dlb_deinit(unit); 1539 } 1540 #endif /* BCM_TRIUMPH3_SUPPORT */ 1541 1542 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 1543 if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 1544 bcm_th2_hgt_lag_dlb_deinit(unit); 1545 } 1546 #endif /* BCM_TOMAHAWK2_SUPPORT */ 1547 1548 _bcm_trident_hg_trunk_override_profile_deinit(unit); 1549 1550 _bcm_trident_trunk_hwfailover_deinit(unit); 1551 1552 _bcm_trident_trunk_swfailover_deinit(unit); 1553 1554 #ifdef BCM_TRIDENT2_SUPPORT 1555 if (soc_feature(unit, soc_feature_hg_resilient_hash)) { 1556 bcm_td2_hg_rh_deinit(unit); 1557 } 1558 if (soc_feature(unit, soc_feature_lag_resilient_hash)) { 1559 bcm_td2_lag_rh_deinit(unit); 1560 } 1561 #endif /* BCM_TRIDENT2_SUPPORT */ 1562 1563 } 1564 1565 /* 1566 * Function: 1567 * _bcm_trident_trunk_init 1568 * Purpose: 1569 * Initialize global data structures 1570 * Parameters: 1571 * unit - (IN)SOC unit number. 1572 * Returns: 1573 * BCM_E_xxx 1574 */ 1575 int 1576 _bcm_trident_trunk_init(int unit) 1577 { 1578 int rv; 1579 1580 _bcm_trident_trunk_deinit(unit); 1581 1582 rv = _bcm_trident_trunk_member_info_init(unit); 1583 if (BCM_FAILURE(rv)) { 1584 _bcm_trident_trunk_deinit(unit); 1585 return rv; 1586 } 1587 1588 rv = _bcm_trident_trunk_mod_port_map_init(unit); 1589 if (BCM_FAILURE(rv)) { 1590 _bcm_trident_trunk_deinit(unit); 1591 return rv; 1592 } 1593 1594 rv = _bcm_trident_trunk_member_bk_init(unit); 1595 if (BCM_FAILURE(rv)) { 1596 _bcm_trident_trunk_deinit(unit); 1597 return rv; 1598 } 1599 1600 if (soc_feature(unit, soc_feature_hg_dlb) && 1601 !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 1602 rv = _bcm_trident_hg_dlb_init(unit); 1603 if (BCM_FAILURE(rv)) { 1604 _bcm_trident_trunk_deinit(unit); 1605 return rv; 1606 } 1607 } 1608 1609 #ifdef BCM_TRIUMPH3_SUPPORT 1610 if (soc_feature(unit, soc_feature_lag_dlb) && 1611 !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 1612 rv = bcm_tr3_lag_dlb_init(unit); 1613 if (BCM_FAILURE(rv)) { 1614 _bcm_trident_trunk_deinit(unit); 1615 return rv; 1616 } 1617 } 1618 #endif /* BCM_TRIUMPH3_SUPPORT */ 1619 1620 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 1621 if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 1622 rv = bcm_th2_hgt_lag_dlb_init(unit); 1623 if (BCM_FAILURE(rv)) { 1624 bcm_th2_hgt_lag_dlb_deinit(unit); 1625 return rv; 1626 } 1627 } 1628 #endif /* BCM_TOMAHAWK2_SUPPORT */ 1629 1630 rv = _bcm_trident_hg_trunk_override_profile_init(unit); 1631 if (BCM_FAILURE(rv)) { 1632 _bcm_trident_trunk_deinit(unit); 1633 return rv; 1634 } 1635 1636 rv = _bcm_trident_trunk_hwfailover_init(unit); 1637 if (BCM_FAILURE(rv)) { 1638 _bcm_trident_trunk_deinit(unit); 1639 return rv; 1640 } 1641 1642 rv = _bcm_trident_trunk_swfailover_init(unit); 1643 if (BCM_FAILURE(rv)) { 1644 _bcm_trident_trunk_deinit(unit); 1645 return rv; 1646 } 1647 1648 #ifdef BCM_TRIDENT2_SUPPORT 1649 if (soc_feature(unit, soc_feature_hg_resilient_hash)) { 1650 rv = bcm_td2_hg_rh_init(unit); 1651 if (BCM_FAILURE(rv)) { 1652 _bcm_trident_trunk_deinit(unit); 1653 return rv; 1654 } 1655 } 1656 1657 if (soc_feature(unit, soc_feature_lag_resilient_hash)) { 1658 rv = bcm_td2_lag_rh_init(unit); 1659 if (BCM_FAILURE(rv)) { 1660 _bcm_trident_trunk_deinit(unit); 1661 return rv; 1662 } 1663 } 1664 #endif /* BCM_TRIDENT2_SUPPORT */ 1665 1666 return BCM_E_NONE; 1667 } 1668 1669 /* ----------------------------------------------------------------------------- 1670 * 1671 * Routines for hardware failover 1672 * 1673 * ----------------------------------------------------------------------------- 1674 */ 1675 1676 static soc_field_t _hg_trunk_failover_portf[8] = { 1677 PORT0f, PORT1f, PORT2f, PORT3f, 1678 PORT4f, PORT5f, PORT6f, PORT7f 1679 }; 1680 1681 1682 #if defined(BCM_KATANA2_SUPPORT) 1683 static soc_field_t _hg_trunk_failover_pp_portf[16]= { 1684 PP_PORT0f, PP_PORT1f, PP_PORT2f, PP_PORT3f, 1685 PP_PORT4f, PP_PORT5f, PP_PORT6f, PP_PORT7f, 1686 PP_PORT8f, PP_PORT9f, PP_PORT10f, PP_PORT11f, 1687 PP_PORT12f, PP_PORT13f, PP_PORT14f, PP_PORT15f 1688 }; 1689 static soc_field_t _hg_trunk_failover_physical_portf[16]= { 1690 PHYSICAL_PORT0f, PHYSICAL_PORT1f, PHYSICAL_PORT2f, PHYSICAL_PORT3f, 1691 PHYSICAL_PORT4f, PHYSICAL_PORT5f, PHYSICAL_PORT6f, PHYSICAL_PORT7f, 1692 PHYSICAL_PORT8f, PHYSICAL_PORT9f, PHYSICAL_PORT10f, PHYSICAL_PORT11f, 1693 PHYSICAL_PORT12f, PHYSICAL_PORT13f, PHYSICAL_PORT14f, PHYSICAL_PORT15f 1694 }; 1695 #endif /* defined(BCM_KATANA2_SUPPORT) */ 1696 1697 1698 /* 1699 * Function: 1700 * _bcm_trident_trunk_hwfailover_hg_write 1701 * Purpose: 1702 * Set Higig trunk hardware failover config. 1703 * Parameters: 1704 * unit - (IN) SOC unit number. 1705 * failport - (IN) Fail port. 1706 * rtag - (IN) Port selection criteria for failover port list. 1707 * hw_count - (IN) Number of ports in failover port list. 1708 * ftp - (IN) Pointer to failover port list. 1709 * Returns: 1710 * BCM_E_xxx 1711 */ 1712 STATIC int 1713 _bcm_trident_trunk_hwfailover_hg_write(int unit, 1714 bcm_port_t failport, int rtag, 1715 int hw_count, bcm_port_t *ftp) 1716 { 1717 hg_trunk_failover_set_entry_t fail_entry; 1718 hg_trunk_failover_enable_entry_t failover_enable_entry; 1719 int ix; 1720 bcm_pbmp_t fail_ports; 1721 int failover_max_portcnt; 1722 1723 failover_max_portcnt = 1 << soc_mem_field_length(unit, 1724 HG_TRUNK_FAILOVER_SETm, FAILOVER_SET_SIZEf); 1725 1726 sal_memset(&fail_entry, 0, sizeof(fail_entry)); 1727 1728 if (hw_count) { /* Enabling HG trunk failover */ 1729 soc_HG_TRUNK_FAILOVER_SETm_field32_set(unit, &fail_entry, 1730 FAILOVER_SET_SIZEf, hw_count - 1); 1731 soc_HG_TRUNK_FAILOVER_SETm_field32_set(unit, &fail_entry, 1732 RTAGf, rtag); 1733 1734 for (ix = 0; ix < failover_max_portcnt; ix++) { 1735 #if defined(BCM_KATANA2_SUPPORT) 1736 if (SOC_IS_KATANA2(unit)) { 1737 soc_HG_TRUNK_FAILOVER_SETm_field32_set(unit, &fail_entry, 1738 _hg_trunk_failover_pp_portf[ix], ftp[ix % hw_count]); 1739 soc_HG_TRUNK_FAILOVER_SETm_field32_set(unit, &fail_entry, 1740 _hg_trunk_failover_physical_portf[ix], ftp[ix % hw_count]); 1741 1742 } else 1743 #endif /* (defined(BCM_KATANA2_SUPPORT) */ 1744 { 1745 soc_HG_TRUNK_FAILOVER_SETm_field32_set(unit, &fail_entry, 1746 _hg_trunk_failover_portf[ix], ftp[ix % hw_count]); 1747 } 1748 } 1749 SOC_IF_ERROR_RETURN 1750 (WRITE_HG_TRUNK_FAILOVER_SETm(unit, MEM_BLOCK_ALL, failport, 1751 &fail_entry)); 1752 } 1753 1754 /* Update HG trunk mode selection bitmap */ 1755 1756 SOC_IF_ERROR_RETURN 1757 (READ_HG_TRUNK_FAILOVER_ENABLEm(unit, MEM_BLOCK_ANY, 0, 1758 &failover_enable_entry)); 1759 SOC_PBMP_CLEAR(fail_ports); 1760 soc_mem_pbmp_field_get(unit, HG_TRUNK_FAILOVER_ENABLEm, 1761 &failover_enable_entry, BITMAPf, &fail_ports); 1762 1763 if (hw_count) { 1764 SOC_PBMP_PORT_ADD(fail_ports, failport); 1765 } else { 1766 SOC_PBMP_PORT_REMOVE(fail_ports, failport); 1767 } 1768 1769 soc_mem_pbmp_field_set(unit, HG_TRUNK_FAILOVER_ENABLEm, 1770 &failover_enable_entry, BITMAPf, &fail_ports); 1771 1772 SOC_IF_ERROR_RETURN 1773 (WRITE_HG_TRUNK_FAILOVER_ENABLEm(unit, MEM_BLOCK_ALL, 0, 1774 &failover_enable_entry)); 1775 1776 return BCM_E_NONE; 1777 } 1778 1779 /* 1780 * Function: 1781 * _bcm_trident_trunk_hwfailover_hg_read 1782 * Purpose: 1783 * Get trunk hardware failover config. 1784 * Parameters: 1785 * unit - (IN) SOC unit number. 1786 * failport - (IN) Port ID of the fail port. 1787 * array_size - (IN) Max number of ports in failover port list. 1788 * rtag - (OUT) Pointer to failover rtag. 1789 * ftp - (OUT) Pointer to port IDs in failover port list. 1790 * ftm - (OUT) Pointer to module IDs in failover port list. 1791 * array_count - (OUT) Number of ports in failover port list. 1792 * Returns: 1793 * BCM_E_xxx 1794 */ 1795 STATIC int 1796 _bcm_trident_trunk_hwfailover_hg_read(int unit, 1797 bcm_port_t failport, int array_size, 1798 int *rtag, bcm_port_t *ftp, bcm_module_t *ftm, 1799 int *array_count) 1800 { 1801 hg_trunk_failover_enable_entry_t failover_enable_entry; 1802 hg_trunk_failover_set_entry_t fail_entry; 1803 bcm_pbmp_t fail_ports; 1804 int ix, hw_count; 1805 1806 SOC_IF_ERROR_RETURN 1807 (READ_HG_TRUNK_FAILOVER_ENABLEm(unit, MEM_BLOCK_ANY, 0, 1808 &failover_enable_entry)); 1809 SOC_PBMP_CLEAR(fail_ports); 1810 soc_mem_pbmp_field_get(unit, HG_TRUNK_FAILOVER_ENABLEm, 1811 &failover_enable_entry, BITMAPf, &fail_ports); 1812 1813 if (SOC_PBMP_MEMBER(fail_ports, failport)) { 1814 SOC_IF_ERROR_RETURN 1815 (READ_HG_TRUNK_FAILOVER_SETm(unit, MEM_BLOCK_ALL, failport, 1816 &fail_entry)); 1817 hw_count = 1 + soc_mem_field32_get(unit, HG_TRUNK_FAILOVER_SETm, 1818 &fail_entry, FAILOVER_SET_SIZEf); 1819 if ((hw_count > array_size) && (array_size != 0)) { 1820 hw_count = array_size; 1821 } 1822 for (ix = 0; ix < hw_count; ix++) { 1823 if (NULL != ftm) { 1824 ftm[ix] = 0; 1825 } 1826 if (NULL != ftp) { 1827 #if defined(BCM_KATANA2_SUPPORT) 1828 if (SOC_IS_KATANA2(unit)) { 1829 ftp[ix] = soc_mem_field32_get(unit, HG_TRUNK_FAILOVER_SETm, 1830 &fail_entry, 1831 _hg_trunk_failover_pp_portf[ix]); 1832 ftp[ix] = soc_mem_field32_get(unit, HG_TRUNK_FAILOVER_SETm, 1833 &fail_entry, 1834 _hg_trunk_failover_physical_portf[ix]); 1835 } else 1836 #endif /* (defined(BCM_KATANA2_SUPPORT) */ 1837 { 1838 ftp[ix] = soc_mem_field32_get(unit, HG_TRUNK_FAILOVER_SETm, 1839 &fail_entry, 1840 _hg_trunk_failover_portf[ix]); 1841 } 1842 } 1843 } 1844 if (NULL != array_count) { 1845 *array_count = hw_count; 1846 } 1847 if (NULL != rtag) { 1848 *rtag = soc_mem_field32_get(unit, HG_TRUNK_FAILOVER_SETm, 1849 &fail_entry, RTAGf); 1850 } 1851 } else { 1852 if (NULL != array_count) { 1853 *array_count = 0; 1854 } 1855 if (NULL != rtag) { 1856 *rtag = 0; 1857 } 1858 } 1859 return BCM_E_NONE; 1860 } 1861 1862 static soc_field_t _trunk_failover_portf[8] = { 1863 PORT0f, PORT1f, PORT2f, PORT3f, 1864 PORT4f, PORT5f, PORT6f, PORT7f 1865 }; 1866 1867 static soc_field_t _trunk_failover_modulef[8] = { 1868 MODULE0f, MODULE1f, MODULE2f, MODULE3f, 1869 MODULE4f, MODULE5f, MODULE6f, MODULE7f 1870 }; 1871 1872 /* 1873 * Function: 1874 * _bcm_trident_trunk_hwfailover_write 1875 * Purpose: 1876 * Set front panel trunk hardware failover config. 1877 * Parameters: 1878 * unit - (IN) SOC unit number. 1879 * failport - (IN) Fail port. 1880 * rtag - (IN) Port selection criteria for failover port list. 1881 * hw_count - (IN) Number of ports in failover port list. 1882 * ftp - (IN) Pointer to failover port list port ID. 1883 * ftm - (IN) Pointer to failover port list module ID. 1884 * Returns: 1885 * BCM_E_xxx 1886 */ 1887 STATIC int 1888 _bcm_trident_trunk_hwfailover_write(int unit, 1889 bcm_port_t failport, int rtag, 1890 int hw_count, bcm_port_t *ftp, bcm_module_t *ftm) 1891 { 1892 port_lag_failover_set_entry_t fail_entry; 1893 uint64 val64; 1894 int ix, mirror_enable; 1895 int failover_max_portcnt; 1896 soc_reg_t lag_failover_status_reg; 1897 soc_reg_t lag_failover_config_reg; 1898 int old_failover_en, new_failover_en; 1899 int old_link_status_sel, new_link_status_sel; 1900 int old_reset_flow_control, new_reset_flow_control; 1901 int failover_status; 1902 1903 if (SOC_USE_PORTCTRL(unit)) { 1904 BCM_IF_ERROR_RETURN 1905 (bcmi_esw_portctrl_hwfailover_status_get(unit, failport, 1906 &failover_status)); 1907 } else { 1908 lag_failover_status_reg = SOC_REG_IS_VALID(unit, LAG_FAILOVER_STATUSr) ? 1909 LAG_FAILOVER_STATUSr: IS_CL_PORT(unit, failport) ? 1910 CLMAC_LAG_FAILOVER_STATUSr : XLMAC_LAG_FAILOVER_STATUSr; 1911 SOC_IF_ERROR_RETURN 1912 (soc_reg_get(unit, lag_failover_status_reg, failport, 0, &val64)); 1913 1914 failover_status = soc_reg64_field32_get(unit, lag_failover_status_reg, 1915 val64, LAG_FAILOVER_LOOPBACKf); 1916 } 1917 1918 if (failover_status) { 1919 /* 1920 * Already in failover mode. Do not change HW settings! 1921 * This should be dealt with as part of the port link processing. 1922 */ 1923 if (hw_count == 0) { 1924 /* Notify linkscan of port removal from trunk */ 1925 BCM_IF_ERROR_RETURN 1926 (_bcm_esw_link_failover_set(unit, failport, FALSE)); 1927 return BCM_E_NONE; 1928 } else { 1929 /* Failed port has not yet been removed from the trunk 1930 -- do not change the failover configuration */ 1931 return BCM_E_NONE; 1932 } 1933 } 1934 1935 if (hw_count) { /* Enabling trunk failover */ 1936 /* We must be in directed mirroring mode to use this feature */ 1937 BCM_IF_ERROR_RETURN 1938 (bcm_esw_switch_control_get(unit, bcmSwitchDirectedMirroring, 1939 &mirror_enable)); 1940 if (!mirror_enable) { 1941 return BCM_E_CONFIG; 1942 } 1943 1944 sal_memset(&fail_entry, 0, sizeof(fail_entry)); 1945 soc_mem_field32_set(unit, PORT_LAG_FAILOVER_SETm, 1946 (uint32 *)&fail_entry, 1947 FAILOVER_SET_SIZEf, hw_count - 1); 1948 soc_mem_field32_set(unit, PORT_LAG_FAILOVER_SETm, 1949 (uint32 *)&fail_entry, RTAGf, rtag); 1950 1951 failover_max_portcnt = 1 << soc_mem_field_length(unit, 1952 PORT_LAG_FAILOVER_SETm, FAILOVER_SET_SIZEf); 1953 for (ix = 0; ix < failover_max_portcnt; ix++) { 1954 soc_mem_field32_set(unit, PORT_LAG_FAILOVER_SETm, 1955 (uint32 *)&fail_entry, 1956 _trunk_failover_portf[ix], 1957 ftp[ix % hw_count]); 1958 soc_mem_field32_set(unit, PORT_LAG_FAILOVER_SETm, 1959 (uint32 *)&fail_entry, 1960 _trunk_failover_modulef[ix], 1961 ftm[ix % hw_count]); 1962 } 1963 SOC_IF_ERROR_RETURN 1964 (WRITE_PORT_LAG_FAILOVER_SETm(unit, MEM_BLOCK_ALL, failport, 1965 &fail_entry)); 1966 } 1967 1968 if (SOC_USE_PORTCTRL(unit)) { 1969 BCM_IF_ERROR_RETURN 1970 (bcmi_esw_portctrl_hwfailover_enable_set(unit, failport, 1971 (hw_count != 0) ? 1 : 0)); 1972 } else { 1973 lag_failover_config_reg = SOC_REG_IS_VALID(unit, LAG_FAILOVER_CONFIGr) ? 1974 LAG_FAILOVER_CONFIGr: IS_CL_PORT(unit, failport) ? 1975 CLMAC_CTRLr : XLMAC_CTRLr; 1976 SOC_IF_ERROR_RETURN 1977 (soc_reg_get(unit, lag_failover_config_reg, failport, 0, &val64)); 1978 1979 old_failover_en = soc_reg64_field32_get(unit, lag_failover_config_reg, 1980 val64, LAG_FAILOVER_ENf); 1981 new_failover_en = (hw_count != 0) ? 1 : 0; 1982 1983 if (soc_reg_field_valid(unit, lag_failover_config_reg, 1984 LINK_STATUS_SELECTf)) { 1985 old_link_status_sel = soc_reg64_field32_get(unit, 1986 lag_failover_config_reg, val64, LINK_STATUS_SELECTf); 1987 new_link_status_sel = (hw_count != 0) ? 1 : 0; 1988 } else { 1989 old_link_status_sel = 0; 1990 new_link_status_sel = 0; 1991 } 1992 1993 if (old_failover_en != new_failover_en || 1994 old_link_status_sel != new_link_status_sel) { 1995 soc_reg64_field32_set(unit, lag_failover_config_reg, &val64, 1996 LAG_FAILOVER_ENf, new_failover_en); 1997 if (soc_reg_field_valid(unit, lag_failover_config_reg, 1998 LINK_STATUS_SELECTf)) { 1999 soc_reg64_field32_set(unit, lag_failover_config_reg, &val64, 2000 LINK_STATUS_SELECTf, new_link_status_sel); 2001 } 2002 SOC_IF_ERROR_RETURN 2003 (soc_reg_set(unit, lag_failover_config_reg, failport, 0, val64)); 2004 } 2005 2006 if (SOC_REG_IS_VALID(unit, XLMAC_RX_LSS_CTRLr) || 2007 SOC_REG_IS_VALID(unit, CLMAC_RX_LSS_CTRLr)) { 2008 soc_reg_t reg = XLMAC_RX_LSS_CTRLr; 2009 2010 if (IS_CL_PORT(unit, failport)) { 2011 reg = CLMAC_RX_LSS_CTRLr; 2012 } 2013 SOC_IF_ERROR_RETURN 2014 (soc_reg_get(unit, reg, failport, 0, &val64)); 2015 if (IS_CL_PORT(unit, failport)) { 2016 soc_reg64_field32_set(unit, reg, &val64, 2017 DROP_TX_DATA_ON_LINK_INTERRUPTf, 0x1); 2018 } 2019 old_reset_flow_control = soc_reg64_field32_get(unit, reg, 2020 val64, RESET_FLOW_CONTROL_TIMERS_ON_LINK_DOWNf); 2021 new_reset_flow_control = (hw_count != 0) ? 1 : 0; 2022 if (old_reset_flow_control != new_reset_flow_control) { 2023 soc_reg64_field32_set(unit, reg, &val64, 2024 RESET_FLOW_CONTROL_TIMERS_ON_LINK_DOWNf, 2025 new_reset_flow_control); 2026 SOC_IF_ERROR_RETURN 2027 (soc_reg_set(unit, reg, failport, 0, val64)); 2028 } 2029 } 2030 } 2031 2032 /* Notify linkscan of failover status */ 2033 BCM_IF_ERROR_RETURN 2034 (_bcm_esw_link_failover_set(unit, failport, (hw_count != 0))); 2035 2036 return BCM_E_NONE; 2037 } 2038 2039 /* 2040 * Function: 2041 * _bcm_trident_trunk_hwfailover_read 2042 * Purpose: 2043 * Get front-panel trunk hardware failover config. 2044 * Parameters: 2045 * unit - (IN) SOC unit number. 2046 * failport - (IN) Port ID of the fail port. 2047 * array_size - (IN) Max number of ports in failover port list. 2048 * rtag - (OUT) Pointer to fail port RTAG. 2049 * ftp - (OUT) Pointer to port IDs in failover port list. 2050 * ftm - (OUT) Pointer to module IDs in failover port list. 2051 * array_count - (OUT) Number of ports in failover port list. 2052 * Returns: 2053 * BCM_E_xxx 2054 */ 2055 STATIC int 2056 _bcm_trident_trunk_hwfailover_read(int unit, 2057 bcm_port_t failport, int array_size, 2058 int *rtag, bcm_port_t *ftp, bcm_module_t *ftm, 2059 int *array_count) 2060 { 2061 port_lag_failover_set_entry_t fail_entry; 2062 uint64 val64; 2063 int ix, hw_count, enable = FALSE; 2064 soc_reg_t lag_failover_config_reg; 2065 2066 if (SOC_USE_PORTCTRL(unit)) { 2067 BCM_IF_ERROR_RETURN 2068 (bcmi_esw_portctrl_hwfailover_enable_get(unit, failport, 2069 &enable)); 2070 } else { 2071 lag_failover_config_reg = SOC_REG_IS_VALID(unit, LAG_FAILOVER_CONFIGr) ? 2072 LAG_FAILOVER_CONFIGr : IS_CL_PORT(unit, failport) ? 2073 CLMAC_CTRLr : XLMAC_CTRLr; 2074 SOC_IF_ERROR_RETURN 2075 (soc_reg_get(unit, lag_failover_config_reg, failport, 0, &val64)); 2076 enable = soc_reg64_field32_get(unit, lag_failover_config_reg, val64, 2077 LAG_FAILOVER_ENf); 2078 } 2079 2080 if (enable) { 2081 SOC_IF_ERROR_RETURN 2082 (READ_PORT_LAG_FAILOVER_SETm(unit, MEM_BLOCK_ALL, failport, 2083 &fail_entry)); 2084 hw_count = 1 + soc_mem_field32_get(unit, PORT_LAG_FAILOVER_SETm, 2085 &fail_entry, 2086 FAILOVER_SET_SIZEf); 2087 if ((hw_count > array_size) && (array_size != 0)) { 2088 hw_count = array_size; 2089 } 2090 for (ix = 0; ix < hw_count; ix++) { 2091 if (NULL != ftp) { 2092 ftp[ix] = soc_mem_field32_get(unit, PORT_LAG_FAILOVER_SETm, 2093 &fail_entry, 2094 _trunk_failover_portf[ix]); 2095 } 2096 if (NULL != ftm) { 2097 ftm[ix] = soc_mem_field32_get(unit, PORT_LAG_FAILOVER_SETm, 2098 &fail_entry, 2099 _trunk_failover_modulef[ix]); 2100 } 2101 } 2102 if (NULL != rtag) { 2103 *rtag = soc_mem_field32_get(unit, PORT_LAG_FAILOVER_SETm, 2104 &fail_entry, RTAGf); 2105 } 2106 if (NULL != array_count) { 2107 *array_count = hw_count; 2108 } 2109 } else { 2110 if (NULL != array_count) { 2111 *array_count = 0; 2112 } 2113 if (NULL != rtag) { 2114 *rtag = 0; 2115 } 2116 } 2117 2118 return BCM_E_NONE; 2119 } 2120 2121 /* 2122 * Function: 2123 * _bcm_trident_trunk_psc_to_rtag 2124 * Purpose: 2125 * Convert PSC to RTAG. 2126 * Parameters: 2127 * unit - (IN) StrataSwitch PCI device unit number (driver internal). 2128 * psc - (OUT) Port selection criteria. 2129 * rtag - (OUT) Pointer to RTAG. 2130 * Returns: 2131 * BCM_E_XXX 2132 */ 2133 STATIC int 2134 _bcm_trident_trunk_psc_to_rtag(int unit, int psc, int *rtag) 2135 { 2136 switch (psc) { 2137 case BCM_TRUNK_PSC_SRCMAC: 2138 case BCM_TRUNK_PSC_DSTMAC: 2139 case BCM_TRUNK_PSC_SRCDSTMAC: 2140 case BCM_TRUNK_PSC_SRCIP: 2141 case BCM_TRUNK_PSC_DSTIP: 2142 case BCM_TRUNK_PSC_SRCDSTIP: 2143 /* These BCM_TRUNK_PSC_ values match the hardware RTAG values */ 2144 *rtag = psc; 2145 break; 2146 case BCM_TRUNK_PSC_PORTINDEX: 2147 if (!soc_feature(unit, soc_feature_port_trunk_index)) { 2148 return BCM_E_PARAM; 2149 } 2150 *rtag = 7; 2151 break; 2152 case BCM_TRUNK_PSC_PORTFLOW: 2153 if (!soc_feature(unit, soc_feature_port_flow_hash)) { 2154 return BCM_E_PARAM; 2155 } 2156 *rtag = 7; 2157 break; 2158 case BCM_TRUNK_PSC_DYNAMIC: 2159 case BCM_TRUNK_PSC_DYNAMIC_ASSIGNED: 2160 case BCM_TRUNK_PSC_DYNAMIC_OPTIMAL: 2161 case BCM_TRUNK_PSC_DYNAMIC_RESILIENT: 2162 *rtag = 7; 2163 break; 2164 case BCM_TRUNK_PSC_ROUND_ROBIN: 2165 case BCM_TRUNK_PSC_RANDOMIZED: 2166 *rtag = 0; 2167 break; 2168 default: 2169 return BCM_E_PARAM; 2170 } 2171 return BCM_E_NONE; 2172 } 2173 2174 /* 2175 * Function: 2176 * _bcm_trident_trunk_hwfailover_set 2177 * Purpose: 2178 * Derive hardware failover port list, and 2179 * set trunk hardware failover config. 2180 * Parameters: 2181 * unit - (IN) SOC unit number. 2182 * tid - (IN) Trunk group ID. 2183 * hg_trunk - (IN) Indicate if trunk group is a Higig trunk. 2184 * port - (IN) Port ID of the fail port. 2185 * modid - (IN) Module ID of the fail port. 2186 * psc - (IN) Port selection criteria for failover port list. 2187 * flags - (IN) BCM_TRUNK_FLAG_FAILOVER_xxx 2188 * count - (IN) Number of ports in failover port list. 2189 * ftp - (IN) Pointer to port IDs in failover port list. 2190 * ftm - (IN) Pointer to module IDs in failover port list. 2191 * Returns: 2192 * BCM_E_xxx 2193 */ 2194 int 2195 _bcm_trident_trunk_hwfailover_set(int unit, 2196 bcm_trunk_t tid, int hg_trunk, 2197 bcm_port_t port, bcm_module_t modid, 2198 int psc, uint32 flags, int count, 2199 bcm_port_t *ftp, bcm_module_t *ftm) 2200 { 2201 bcm_trunk_chip_info_t chip_info; 2202 int rv = BCM_E_NONE; 2203 int ix, tix, tid_ix, tports, next, local, mod_is_local, hw_count, rtag; 2204 uint8 tp_mod; 2205 uint16 fail_modport; 2206 bcm_gport_t gport; 2207 bcm_port_t local_port; 2208 int failover_max_portcnt; 2209 bcm_port_t *port_list = NULL; 2210 bcm_module_t *modid_list = NULL; 2211 _trident_hw_tinfo_t *hwft; 2212 2213 /* Need the HW port number for the table write later */ 2214 if (hg_trunk) { 2215 fail_modport = local_port = port; 2216 } else { 2217 BCM_GPORT_MODPORT_SET(gport, modid, port); 2218 BCM_IF_ERROR_RETURN 2219 (bcm_esw_port_local_get(unit, gport, &local_port)); 2220 2221 /*For Higig ports that are members of a LAG, 2222 it Should not configure a list of failover ports for Higig ports, 2223 since Higig ports do not support LAG failover loopback. 2224 However, the Higig ports can still be part of the list of 2225 failover ports for other LAG members.*/ 2226 if (IS_HG_PORT(unit, local_port)) { 2227 return BCM_E_UNAVAIL; 2228 } 2229 /* not supported on Cascaded Physical Ports */ 2230 if ((soc_feature(unit, soc_feature_linkphy_coe) && 2231 IS_LP_PORT(unit, local_port)) || 2232 (soc_feature(unit, soc_feature_subtag_coe) && 2233 IS_SUBTAG_PORT(unit, local_port)) || 2234 (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 2235 IS_SUBTAG_PORT (unit, local_port))) { 2236 return BCM_E_UNAVAIL; 2237 } 2238 2239 #if defined(BCM_HELIX5_SUPPORT) 2240 /* Skip q-ports in HX5 since trunk hardware failover is not 2241 * supported for PM4x10Q. 2242 */ 2243 if (IS_QSGMII_PORT(unit, local_port)) { 2244 return BCM_E_UNAVAIL; 2245 } 2246 #endif /* BCM_HELIX5_SUPPORT */ 2247 2248 fail_modport = (modid << 8) | port; 2249 } 2250 2251 BCM_IF_ERROR_RETURN(_bcm_trident_trunk_psc_to_rtag(unit, psc, &rtag)); 2252 2253 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 2254 tid_ix = tid + (hg_trunk ? chip_info.trunk_group_count : 0); 2255 hwft = &(_trident_trunk_hwfail[unit]->hw_tinfo[tid_ix]); 2256 2257 /* Where is our port in the trunk list? */ 2258 tports = hwft->num_ports; 2259 for (tix = 0; tix < tports; tix++) { 2260 if (fail_modport == hwft->modport[tix]) { 2261 break; 2262 } 2263 } 2264 2265 if ((0 != count) && (tix == tports)) { 2266 /* Port not in trunk! */ 2267 return BCM_E_NOT_FOUND; 2268 } 2269 2270 if (hg_trunk) { 2271 failover_max_portcnt = 1 << soc_mem_field_length(unit, 2272 HG_TRUNK_FAILOVER_SETm, FAILOVER_SET_SIZEf); 2273 } else { 2274 failover_max_portcnt = 1 << soc_mem_field_length(unit, 2275 PORT_LAG_FAILOVER_SETm, FAILOVER_SET_SIZEf); 2276 } 2277 port_list = sal_alloc(sizeof(bcm_port_t) * failover_max_portcnt, 2278 "failover port list"); 2279 if (port_list == NULL) { 2280 return BCM_E_MEMORY; 2281 } 2282 modid_list = sal_alloc(sizeof(bcm_module_t) * failover_max_portcnt, 2283 "failover module list"); 2284 if (modid_list == NULL) { 2285 sal_free(port_list); 2286 return BCM_E_MEMORY; 2287 } 2288 2289 if (flags) { 2290 switch (flags) { 2291 case BCM_TRUNK_FLAG_FAILOVER_NEXT_LOCAL: 2292 next = TRUE; 2293 local = TRUE; 2294 break; 2295 case BCM_TRUNK_FLAG_FAILOVER_NEXT: 2296 next = TRUE; 2297 local = FALSE; 2298 break; 2299 case BCM_TRUNK_FLAG_FAILOVER_ALL_LOCAL: 2300 next = FALSE; 2301 local = TRUE; 2302 break; 2303 case BCM_TRUNK_FLAG_FAILOVER_ALL: 2304 next = FALSE; 2305 local = FALSE; 2306 break; 2307 default: 2308 /* Illegal flags setting */ 2309 sal_free(port_list); 2310 sal_free(modid_list); 2311 return BCM_E_PARAM; 2312 } 2313 2314 hw_count = 0; 2315 2316 for (ix = ((tix + 1) % tports); /* Start after fail port */ 2317 ix != tix; /* Stop when we get back */ 2318 ix = ((ix + 1) % tports)) { /* Cycle through trunk port list */ 2319 tp_mod = hwft->modport[ix] >> 8; 2320 if (local && !hg_trunk) { 2321 rv = _bcm_esw_modid_is_local(unit, tp_mod, &mod_is_local); 2322 if (BCM_FAILURE(rv)) { 2323 sal_free(port_list); 2324 sal_free(modid_list); 2325 return rv; 2326 } 2327 if (!mod_is_local) { 2328 continue; 2329 } 2330 } 2331 port_list[hw_count] = hwft->modport[ix] & 0xff; 2332 modid_list[hw_count] = tp_mod; 2333 hw_count++; 2334 if (hw_count == failover_max_portcnt) { 2335 break; 2336 } 2337 if (next) { 2338 break; 2339 } 2340 } 2341 } else { 2342 hw_count = 0; 2343 2344 if (count) { 2345 for (ix = 0; ix < count && ix < failover_max_portcnt; ix++) { 2346 port_list[ix] = ftp[ix]; 2347 modid_list[ix] = ftm[ix]; 2348 } 2349 hw_count = ix; 2350 } 2351 } 2352 2353 if (hg_trunk) { 2354 rv = _bcm_trident_trunk_hwfailover_hg_write(unit, local_port, rtag, 2355 hw_count, port_list); 2356 } else { 2357 rv = _bcm_trident_trunk_hwfailover_write(unit, local_port, rtag, 2358 hw_count, port_list, modid_list); 2359 } 2360 sal_free(port_list); 2361 sal_free(modid_list); 2362 if (BCM_FAILURE(rv)) { 2363 return rv; 2364 } 2365 2366 if (tix < hwft->num_ports) { 2367 hwft->flags[tix] = flags; 2368 hwft->psc[tix] = psc; 2369 } 2370 2371 return rv; 2372 } 2373 2374 /* 2375 * Function: 2376 * _bcm_trident_trunk_hwfailover_get 2377 * Purpose: 2378 * Get trunk hardware failover config. 2379 * Parameters: 2380 * unit - (IN) SOC unit number. 2381 * tid - (IN) Trunk group ID. 2382 * hg_trunk - (IN) Indicate if trunk group is a Higig trunk. 2383 * port - (IN) Port ID of the fail port. 2384 * modid - (IN) Module ID of the fail port. 2385 * psc - (OUT) Port selection criteria for failover port list. 2386 * flags - (OUT) BCM_TRUNK_FLAG_FAILOVER_xxx 2387 * array_size - (IN) Max number of ports in failover port list. 2388 * ftp - (OUT) Pointer to port IDs in failover port list. 2389 * ftm - (OUT) Pointer to module IDs in failover port list. 2390 * array_count - (OUT) Number of ports in failover port list. 2391 * Returns: 2392 * BCM_E_xxx 2393 */ 2394 int 2395 _bcm_trident_trunk_hwfailover_get(int unit, 2396 bcm_trunk_t tid, int hg_trunk, 2397 bcm_port_t port, bcm_module_t modid, 2398 int *psc, uint32 *flags, int array_size, 2399 bcm_port_t *ftp, bcm_module_t *ftm, 2400 int *array_count) 2401 { 2402 bcm_trunk_chip_info_t chip_info; 2403 int tix, tid_ix, tports; 2404 uint16 fail_modport; 2405 bcm_gport_t gport; 2406 bcm_port_t local_port; 2407 _trident_hw_tinfo_t *hwft; 2408 2409 /* Need the HW port number for the table write later */ 2410 if (hg_trunk) { 2411 fail_modport = local_port = port; 2412 } else { 2413 BCM_GPORT_MODPORT_SET(gport, modid, port); 2414 BCM_IF_ERROR_RETURN 2415 (bcm_esw_port_local_get(unit, gport, &local_port)); 2416 fail_modport = (modid << 8) | port; 2417 } 2418 2419 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 2420 tid_ix = tid + (hg_trunk ? chip_info.trunk_group_count : 0); 2421 hwft = &(_trident_trunk_hwfail[unit]->hw_tinfo[tid_ix]); 2422 2423 /* Where is our port in the trunk list? */ 2424 tports = hwft->num_ports; 2425 for (tix = 0; tix < tports; tix++) { 2426 if (fail_modport == hwft->modport[tix]) { 2427 break; 2428 } 2429 } 2430 2431 if (tix == tports) { 2432 /* Port not in trunk! */ 2433 return BCM_E_NOT_FOUND; 2434 } 2435 2436 *psc = hwft->psc[tix]; 2437 2438 if (hwft->flags[tix]) { 2439 /* Just return the flags value */ 2440 *flags = hwft->flags[tix]; 2441 *array_count = 0; 2442 } else { 2443 /* Access the HW to get the list */ 2444 *flags = 0; 2445 if (hg_trunk) { 2446 BCM_IF_ERROR_RETURN 2447 (_bcm_trident_trunk_hwfailover_hg_read(unit, local_port, 2448 array_size, NULL, 2449 ftp, ftm, array_count)); 2450 } else { 2451 BCM_IF_ERROR_RETURN 2452 (_bcm_trident_trunk_hwfailover_read(unit, local_port, 2453 array_size, NULL, 2454 ftp, ftm, array_count)); 2455 } 2456 } 2457 2458 return BCM_E_NONE; 2459 } 2460 2461 /* 2462 * Function: 2463 * _bcm_trident_trunk_failover_set 2464 * Purpose: 2465 * Disable hardware failover for old trunk ports, and 2466 * configure hardware failover for new trunk ports. 2467 * Parameters: 2468 * unit - (IN) SOC unit number. 2469 * tid - (IN) Trunk group ID. 2470 * hg_trunk - (IN) Indicate if trunk group is a Higig trunk 2471 * add_info - (IN) Pointer to trunk add info structure. 2472 * Returns: 2473 * BCM_E_xxx 2474 */ 2475 STATIC int 2476 _bcm_trident_trunk_failover_set(int unit, 2477 bcm_trunk_t tid, 2478 int hg_trunk, 2479 _esw_trunk_add_info_t *add_info) 2480 { 2481 bcm_trunk_chip_info_t chip_info; 2482 int rv = BCM_E_NONE; 2483 int tix, mod_is_local, tid_ix; 2484 bcm_port_t tp_port, local_port; 2485 bcm_module_t tp_mod = -1; 2486 _trident_hw_tinfo_t *hwft; 2487 bcm_port_t *port_array = NULL; 2488 bcm_module_t *mod_array = NULL; 2489 int num_hwft_ports; 2490 int failover_flags; 2491 bcm_gport_t gport; 2492 2493 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 2494 tid_ix = tid + (hg_trunk ? chip_info.trunk_group_count : 0); 2495 hwft = &(_trident_trunk_hwfail[unit]->hw_tinfo[tid_ix]); 2496 2497 failover_flags = 0; 2498 if (add_info != NULL) { 2499 if (add_info->flags & BCM_TRUNK_FLAG_FAILOVER_NEXT) { 2500 failover_flags = BCM_TRUNK_FLAG_FAILOVER_NEXT; 2501 } else if (add_info->flags & BCM_TRUNK_FLAG_FAILOVER_NEXT_LOCAL) { 2502 failover_flags = BCM_TRUNK_FLAG_FAILOVER_NEXT_LOCAL; 2503 } else if (add_info->flags & BCM_TRUNK_FLAG_FAILOVER_ALL) { 2504 failover_flags = BCM_TRUNK_FLAG_FAILOVER_ALL; 2505 } else if (add_info->flags & BCM_TRUNK_FLAG_FAILOVER_ALL_LOCAL) { 2506 failover_flags = BCM_TRUNK_FLAG_FAILOVER_ALL_LOCAL; 2507 } 2508 } 2509 2510 if ((NULL == add_info) || (0 != failover_flags)) { 2511 /* Disable hardware failover for old trunk ports */ 2512 for (tix = 0; tix < hwft->num_ports; tix++) { 2513 tp_port = hwft->modport[tix] & 0xff; 2514 if (!hg_trunk) { 2515 tp_mod = hwft->modport[tix] >> 8; 2516 BCM_IF_ERROR_RETURN 2517 (_bcm_esw_modid_is_local(unit, tp_mod, &mod_is_local)); 2518 if (!mod_is_local) { 2519 continue; 2520 } 2521 2522 BCM_GPORT_MODPORT_SET(gport, tp_mod, tp_port); 2523 BCM_IF_ERROR_RETURN 2524 (bcm_esw_port_local_get(unit, gport, &local_port)); 2525 if (IS_HG_PORT(unit, local_port)) { 2526 continue; 2527 } 2528 /* skip Cascaded Physical Ports */ 2529 if ((soc_feature(unit, soc_feature_linkphy_coe) && 2530 IS_LP_PORT(unit, local_port)) || 2531 (soc_feature(unit, soc_feature_subtag_coe) && 2532 IS_SUBTAG_PORT(unit, local_port))|| 2533 (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 2534 IS_SUBTAG_PORT (unit, local_port))) { 2535 continue; 2536 } 2537 2538 #if defined(BCM_HELIX5_SUPPORT) 2539 /* Skip q-ports in HX5 since trunk hardware failover is not 2540 * supported for PM4x10Q. 2541 */ 2542 if (IS_QSGMII_PORT(unit, local_port)) { 2543 continue; 2544 } 2545 #endif /* BCM_HELIX5_SUPPORT */ 2546 } 2547 BCM_IF_ERROR_RETURN 2548 (_bcm_trident_trunk_hwfailover_set(unit, tid, hg_trunk, 2549 tp_port, tp_mod, 2550 hwft->psc[tix], 2551 0, 0, NULL, NULL)); 2552 } 2553 } 2554 /* Else, updating trunk with failover_flags == 0, 2555 * do not change failover configuration */ 2556 2557 if (hwft->modport) { 2558 sal_free(hwft->modport); 2559 hwft->modport = NULL; 2560 } 2561 if (hwft->psc) { 2562 sal_free(hwft->psc); 2563 hwft->psc = NULL; 2564 } 2565 if (hwft->flags) { 2566 sal_free(hwft->flags); 2567 hwft->flags = NULL; 2568 } 2569 hwft->num_ports = 0; 2570 2571 if (NULL == add_info) { 2572 /* We're deleting the trunk */ 2573 return BCM_E_NONE; 2574 } 2575 2576 /* Record new trunk data */ 2577 2578 if (hwft->modport == NULL) { 2579 hwft->modport = sal_alloc(sizeof(uint16) * add_info->num_ports, "hw_tinfo_modport"); 2580 if (hwft->modport == NULL) { 2581 return BCM_E_MEMORY; 2582 } 2583 } 2584 sal_memset(hwft->modport, 0, sizeof(uint16) * add_info->num_ports); 2585 2586 if (hwft->psc == NULL) { 2587 hwft->psc = sal_alloc(sizeof(uint8) * add_info->num_ports, "hw_tinfo_psc"); 2588 if (hwft->psc == NULL) { 2589 sal_free(hwft->modport); 2590 hwft->modport = NULL; 2591 return BCM_E_MEMORY; 2592 } 2593 } 2594 sal_memset(hwft->psc, 0, sizeof(uint8) * add_info->num_ports); 2595 2596 if (hwft->flags == NULL) { 2597 hwft->flags = sal_alloc(sizeof(uint32) * add_info->num_ports, "hw_tinfo_flags"); 2598 if (hwft->flags == NULL) { 2599 sal_free(hwft->modport); 2600 hwft->modport = NULL; 2601 sal_free(hwft->psc); 2602 hwft->psc = NULL; 2603 return BCM_E_MEMORY; 2604 } 2605 } 2606 sal_memset(hwft->flags, 0, sizeof(uint32) * add_info->num_ports); 2607 2608 if (mod_array == NULL) { 2609 mod_array = sal_alloc(sizeof(bcm_module_t) * add_info->num_ports, "mod_array"); 2610 if (mod_array == NULL) { 2611 sal_free(hwft->modport); 2612 hwft->modport = NULL; 2613 sal_free(hwft->psc); 2614 hwft->psc = NULL; 2615 sal_free(hwft->flags); 2616 hwft->flags = NULL; 2617 return BCM_E_MEMORY; 2618 } 2619 } 2620 sal_memset(mod_array, 0, sizeof(bcm_module_t) * add_info->num_ports); 2621 2622 if (port_array == NULL) { 2623 port_array = sal_alloc(sizeof(bcm_port_t) * add_info->num_ports, "port_array"); 2624 if (port_array == NULL) { 2625 sal_free(hwft->modport); 2626 hwft->modport = NULL; 2627 sal_free(hwft->psc); 2628 hwft->psc = NULL; 2629 sal_free(hwft->flags); 2630 hwft->flags = NULL; 2631 sal_free(mod_array); 2632 return BCM_E_MEMORY; 2633 } 2634 } 2635 sal_memset(port_array, 0, sizeof(bcm_port_t) * add_info->num_ports); 2636 2637 num_hwft_ports = 0; 2638 for (tix = 0; tix < add_info->num_ports; tix++) { 2639 if (add_info->member_flags[tix] & BCM_TRUNK_MEMBER_EGRESS_DISABLE) { 2640 continue; 2641 } 2642 hwft->flags[num_hwft_ports] = failover_flags; 2643 hwft->psc[num_hwft_ports] = add_info->psc; 2644 hwft->modport[num_hwft_ports] = add_info->tp[tix]; 2645 port_array[num_hwft_ports] = add_info->tp[tix]; 2646 if (!hg_trunk) { 2647 hwft->modport[num_hwft_ports] |= (add_info->tm[tix] << 8); 2648 mod_array[num_hwft_ports] = add_info->tm[tix]; 2649 } 2650 num_hwft_ports++; 2651 } 2652 hwft->num_ports = num_hwft_ports; 2653 2654 /* No failover flags in trunk_set means no failover changes */ 2655 if (0 != failover_flags) { 2656 /* Configure hardware failover for new trunk ports */ 2657 for (tix = 0; tix < hwft->num_ports; tix++) { 2658 if (!hg_trunk) { 2659 rv = _bcm_esw_modid_is_local(unit, hwft->modport[tix] >> 8, 2660 &mod_is_local); 2661 if (BCM_FAILURE(rv)) { 2662 sal_free(mod_array); 2663 sal_free(port_array); 2664 return rv; 2665 } 2666 if (!mod_is_local) { 2667 continue; 2668 } 2669 2670 tp_mod = hwft->modport[tix] >> 8; 2671 BCM_GPORT_MODPORT_SET(gport, tp_mod, hwft->modport[tix] & 0xff); 2672 rv = bcm_esw_port_local_get(unit, gport, &local_port); 2673 if (BCM_FAILURE(rv)) { 2674 sal_free(mod_array); 2675 sal_free(port_array); 2676 return rv; 2677 } 2678 if (IS_HG_PORT(unit, local_port)) { 2679 continue; 2680 } 2681 /* skip Cascaded Physical Ports*/ 2682 if ((soc_feature(unit, soc_feature_linkphy_coe) && 2683 IS_LP_PORT(unit, local_port)) || 2684 (soc_feature(unit, soc_feature_subtag_coe) && 2685 IS_SUBTAG_PORT(unit, local_port)) || 2686 (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 2687 IS_SUBTAG_PORT (unit, local_port))) { 2688 continue; 2689 } 2690 2691 #if defined(BCM_HELIX5_SUPPORT) 2692 /* Skip q-ports in HX5 since trunk hardware failover is not 2693 * supported for PM4x10Q. 2694 */ 2695 if (IS_QSGMII_PORT(unit, local_port)) { 2696 continue; 2697 } 2698 #endif /* BCM_HELIX5_SUPPORT */ 2699 } 2700 rv = _bcm_trident_trunk_hwfailover_set(unit, tid, hg_trunk, 2701 hwft->modport[tix] & 0xff, 2702 hwft->modport[tix] >> 8, 2703 hwft->psc[tix], 2704 hwft->flags[tix], 2705 hwft->num_ports, 2706 port_array, 2707 mod_array); 2708 if (BCM_FAILURE(rv)) { 2709 sal_free(mod_array); 2710 sal_free(port_array); 2711 return rv; 2712 } 2713 } 2714 } 2715 2716 sal_free(mod_array); 2717 sal_free(port_array); 2718 2719 return BCM_E_NONE; 2720 } 2721 2722 /* ----------------------------------------------------------------------------- 2723 * 2724 * Routines for software failover 2725 * 2726 * ----------------------------------------------------------------------------- 2727 */ 2728 2729 /* 2730 * Function: 2731 * _bcm_trident_trunk_swfailover_fabric_set 2732 * Purpose: 2733 * Set Higig trunk software failover config. 2734 * Parameters: 2735 * unit - (IN) SOC unit number. 2736 * hgtid - (IN) Higig trunk ID. 2737 * rtag - (IN) Port selection criteria. 2738 * ports - (IN) Higig trunk member ports. 2739 * Returns: 2740 * BCM_E_xxx 2741 */ 2742 STATIC int 2743 _bcm_trident_trunk_swfailover_fabric_set(int unit, 2744 bcm_trunk_t hgtid, 2745 int rtag, 2746 bcm_pbmp_t ports) 2747 { 2748 bcm_trunk_chip_info_t chip_info; 2749 _trident_trunk_swfail_t *swf; 2750 _trident_tinfo_t *swft; 2751 bcm_port_t port; 2752 int i; 2753 int fabric_trunk_swf_tid_offset = 0; 2754 2755 if (_trident_trunk_swfail[unit] == NULL) { 2756 return BCM_E_INIT; 2757 } 2758 2759 swf = _trident_trunk_swfail[unit]; 2760 2761 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 2762 swft = &swf->tinfo[hgtid + chip_info.trunk_group_count]; 2763 fabric_trunk_swf_tid_offset = chip_info.trunk_group_count + 1; 2764 2765 swft->rtag = rtag; 2766 SOC_PBMP_COUNT(ports, swft->num_ports); 2767 2768 if (swft->modport) { 2769 sal_free(swft->modport); 2770 swft->modport = NULL; 2771 } 2772 2773 if (swft->num_ports > 0) { 2774 swft->modport = sal_alloc(sizeof(uint16) * swft->num_ports, 2775 "swfail_tinfo_modport"); 2776 if (swft->modport == NULL) { 2777 return BCM_E_MEMORY; 2778 } 2779 2780 i = 0; 2781 SOC_PBMP_ITER(ports, port) { 2782 swft->modport[i++] = port; 2783 } 2784 } 2785 2786 PBMP_ALL_ITER(unit, port) { 2787 if (BCM_PBMP_MEMBER(ports, port)) { 2788 swf->trunk[port] = hgtid + fabric_trunk_swf_tid_offset; 2789 } else if (swf->trunk[port] == 2790 (hgtid + fabric_trunk_swf_tid_offset)) { 2791 swf->trunk[port] = 0; /* remove stale pointers to tid */ 2792 } 2793 } 2794 return BCM_E_NONE; 2795 } 2796 2797 /* 2798 * Function: 2799 * _bcm_trident_trunk_swfailover_fp_set 2800 * Purpose: 2801 * Set front panel trunk software failover config. 2802 * Parameters: 2803 * unit - (IN) SOC unit number. 2804 * tid - (IN) Trunk ID. 2805 * rtag - (IN) Port selection criteria. 2806 * nports - (IN) Number of trunk members. 2807 * mods - (IN) Trunk member module ID array. 2808 * ports - (IN) Trunk member port ID array. 2809 * member_flags - (IN) Trunk member flags array. 2810 * flags - (IN) Trunk group flags. 2811 * Returns: 2812 * BCM_E_xxx 2813 */ 2814 STATIC int 2815 _bcm_trident_trunk_swfailover_fp_set(int unit, 2816 bcm_trunk_t tid, 2817 int rtag, 2818 int nports, 2819 int *mods, 2820 int *ports, 2821 uint32 *member_flags, 2822 uint32 flags) 2823 { 2824 _trident_trunk_swfail_t *swf; 2825 _trident_tinfo_t *swft; 2826 bcm_pbmp_t localports; 2827 bcm_port_t port; 2828 bcm_module_t my_modid; 2829 int i; 2830 bcm_pbmp_t all_pbmp; 2831 #if defined(BCM_KATANA2_SUPPORT) 2832 int pp_port; 2833 #endif 2834 #if defined(BCM_HGPROXY_COE_SUPPORT) 2835 int phy_port = 0; 2836 #endif 2837 2838 if (_trident_trunk_swfail[unit] == NULL) { 2839 return BCM_E_INIT; 2840 } 2841 2842 BCM_IF_ERROR_RETURN 2843 (bcm_esw_stk_my_modid_get(unit, &my_modid)); 2844 2845 swf = _trident_trunk_swfail[unit]; 2846 swft = &swf->tinfo[tid]; 2847 2848 swf->mymodid = my_modid; 2849 swft->rtag = rtag; 2850 swft->num_ports = nports; 2851 swft->flags = flags; 2852 2853 if (swft->modport) { 2854 sal_free(swft->modport); 2855 swft->modport = NULL; 2856 } 2857 if (swft->member_flags) { 2858 sal_free(swft->member_flags); 2859 swft->member_flags = NULL; 2860 } 2861 2862 BCM_PBMP_CLEAR(localports); 2863 if (swft->num_ports > 0) { 2864 swft->modport = sal_alloc(sizeof(uint16) * swft->num_ports, 2865 "swfail_tinfo_modport"); 2866 if (swft->modport == NULL) { 2867 return BCM_E_MEMORY; 2868 } 2869 swft->member_flags = sal_alloc(sizeof(uint32) * swft->num_ports, 2870 "swfail_tinfo_member_flags"); 2871 if (swft->member_flags == NULL) { 2872 sal_free(swft->modport); 2873 swft->modport = NULL; 2874 return BCM_E_MEMORY; 2875 } 2876 2877 for (i = 0; i < nports; i++) { 2878 swft->modport[i] = (mods[i] << 8) | ports[i]; 2879 if (mods[i] == my_modid) { 2880 BCM_PBMP_PORT_ADD(localports, ports[i]); 2881 } 2882 2883 #if defined(BCM_HGPROXY_COE_SUPPORT) 2884 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe)) { 2885 if(_bcm_xgs5_subport_coe_mod_local(unit, mods[i])) { 2886 2887 BCM_IF_ERROR_RETURN( 2888 _bcmi_coe_subport_mod_port_physical_port_get(unit, 2889 mods[i], 2890 ports[i], 2891 &phy_port)); 2892 BCM_PBMP_PORT_ADD(localports, phy_port); 2893 } 2894 } 2895 #endif 2896 if (soc_feature(unit, soc_feature_linkphy_coe) || 2897 soc_feature(unit, soc_feature_subtag_coe)) { 2898 #if defined(BCM_KATANA2_SUPPORT) 2899 if (_bcm_kt2_mod_is_coe_mod_check(unit, mods[i]) == BCM_E_NONE) { 2900 pp_port = 0; 2901 BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get( 2902 unit, mods[i], ports[i], &pp_port)); 2903 #if defined BCM_METROLITE_SUPPORT 2904 if (soc_feature(unit, soc_feature_discontinuous_pp_port)) { 2905 if (_SOC_IS_PP_PORT_LINKPHY_SUBTAG(unit, pp_port)) { 2906 BCM_PBMP_PORT_ADD(localports, pp_port); 2907 } 2908 } else 2909 #endif 2910 { 2911 if ((pp_port >= SOC_INFO(unit).pp_port_index_min) && 2912 (pp_port <= SOC_INFO(unit).pp_port_index_max)) { 2913 BCM_PBMP_PORT_ADD(localports, pp_port); 2914 } 2915 } 2916 } 2917 #endif 2918 } 2919 swft->member_flags[i] = member_flags[i]; 2920 } 2921 } 2922 2923 BCM_PBMP_CLEAR(all_pbmp); 2924 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 2925 2926 #if defined(BCM_KATANA2_SUPPORT) 2927 if (soc_feature(unit, soc_feature_linkphy_coe) || 2928 soc_feature(unit, soc_feature_subtag_coe)) { 2929 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp); 2930 } 2931 if (SOC_IS_KATANA2(unit) && soc_feature(unit, soc_feature_flex_port)) { 2932 BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update (unit, &all_pbmp)); 2933 } 2934 #endif 2935 2936 PBMP_ITER(all_pbmp, port) { 2937 if (BCM_PBMP_MEMBER(localports, port)) { 2938 /* coverity[overrun-local : FALSE] */ 2939 swf->trunk[port] = tid + 1; 2940 } else if (swf->trunk[port] == tid + 1) { 2941 swf->trunk[port] = 0; /* remove stale pointers to tid */ 2942 } 2943 } 2944 return BCM_E_NONE; 2945 } 2946 2947 #ifdef BCM_TRUNK_FAILOVER_SUPPORT 2948 2949 /* 2950 * Function: 2951 * _bcm_trident_trunk_fabric_swfailover_trigger 2952 * Purpose: 2953 * Delete failed port from Higig trunk config. 2954 * Parameters: 2955 * unit - (IN) SOC unit number. 2956 * port - (IN) Failed port number. 2957 * hgtid - (IN) Higig trunk ID. 2958 * swf - (IN) Pointer to software failover info. 2959 * Returns: 2960 * BCM_E_xxx 2961 */ 2962 STATIC int 2963 _bcm_trident_trunk_fabric_swfailover_trigger(int unit, 2964 bcm_port_t port, 2965 int hgtid, 2966 _trident_trunk_swfail_t *swf) 2967 { 2968 bcm_trunk_chip_info_t chip_info; 2969 _trident_tinfo_t *swft; 2970 int i, j, nmp; 2971 hg_trunk_group_entry_t hg_trunk_group_entry; 2972 hg_trunk_member_entry_t hg_trunk_member_entry; 2973 hg_trunk_bitmap_entry_t hg_trunk_bitmap_entry; 2974 int old_base_ptr, old_tg_size, old_rtag; 2975 int max_base_ptr, base_ptr; 2976 int num_entries, old_num_entries; 2977 pbmp_t old_trunk_pbmp, new_trunk_pbmp; 2978 SHR_BITDCL occupied; 2979 #if defined(BCM_HGPROXY_COE_SUPPORT) 2980 int entry_type = 0; 2981 #endif 2982 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 2983 swft = &swf->tinfo[hgtid + chip_info.trunk_group_count]; 2984 2985 /* update the _trident_trunk_swfail entry */ 2986 nmp = swft->num_ports; 2987 for (i = j = 0; i < nmp; i++) { 2988 if (swft->modport[i] != port) { 2989 if (i != j) { 2990 swft->modport[j] = swft->modport[i]; 2991 } 2992 j += 1; 2993 } 2994 } 2995 2996 if (j == nmp) { 2997 return BCM_E_NONE; /* no changes, so no need to write out */ 2998 } 2999 3000 swft->num_ports = nmp = j; 3001 3002 /* Update Higig trunk tables */ 3003 3004 SOC_IF_ERROR_RETURN 3005 (READ_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, hgtid, &hg_trunk_group_entry)); 3006 old_base_ptr = soc_HG_TRUNK_GROUPm_field32_get(unit, &hg_trunk_group_entry, BASE_PTRf); 3007 old_tg_size = 1 + soc_HG_TRUNK_GROUPm_field32_get(unit, &hg_trunk_group_entry, TG_SIZEf); 3008 old_rtag = soc_HG_TRUNK_GROUPm_field32_get(unit, &hg_trunk_group_entry, RTAGf); 3009 #if defined(BCM_HGPROXY_COE_SUPPORT) 3010 if (soc_mem_field_valid(unit, HG_TRUNK_GROUPm, ENTRY_TYPEf)) { 3011 entry_type = soc_HG_TRUNK_GROUPm_field32_get(unit, &hg_trunk_group_entry, ENTRY_TYPEf); 3012 } 3013 #endif 3014 3015 if (nmp == 0) { 3016 soc_HG_TRUNK_GROUPm_field32_set(unit, &hg_trunk_group_entry, BASE_PTRf, 0); 3017 soc_HG_TRUNK_GROUPm_field32_set(unit, &hg_trunk_group_entry, TG_SIZEf, 0); 3018 soc_HG_TRUNK_GROUPm_field32_set(unit, &hg_trunk_group_entry, RTAGf, swft->rtag); 3019 SOC_IF_ERROR_RETURN 3020 (WRITE_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, hgtid, &hg_trunk_group_entry)); 3021 } else { 3022 3023 /* Find a contiguous region of HG_TRUNK_MEMBERm table that's large 3024 * enough to hold all of the Higig trunk group's member ports. 3025 */ 3026 num_entries = nmp; 3027 3028 /* If RTAG is 1-6, Trident A0 and Katana ignore the TG_SIZE field and 3029 * assume the Higig trunk group occupies FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT 3030 * contiguous entries in HG_TRUNK_MEMBER table. 3031 */ 3032 if (swft->rtag >= 1 && swft->rtag <= 6) { 3033 #ifdef BCM_KATANA_SUPPORT 3034 if(SOC_IS_KATANAX(unit)) { 3035 num_entries = _BCM_KATANA_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT; 3036 } else 3037 #endif 3038 if (soc_feature(unit, 3039 soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 3040 num_entries = _BCM_TD_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT; 3041 } 3042 } 3043 3044 max_base_ptr = soc_mem_index_count(unit, HG_TRUNK_MEMBERm) - num_entries; 3045 for (base_ptr = 0; base_ptr <= max_base_ptr; base_ptr++) { 3046 /* Check if the contiguous region of HG_TRUNK_MEMBERm table from 3047 * index base_ptr to (base_ptr + num_entries - 1) is free. 3048 */ 3049 _BCM_HG_TRUNK_MEMBER_TEST_RANGE(unit, base_ptr, num_entries, occupied); 3050 if (!occupied) { 3051 break; 3052 } 3053 } 3054 3055 if (base_ptr > max_base_ptr) { 3056 /* A contiguous region of the desired size could not be found in 3057 * HG_TRUNK_MEMBERm table. 3058 */ 3059 return BCM_E_RESOURCE; 3060 } 3061 3062 for (i = 0; i < num_entries; i++) { 3063 sal_memset(&hg_trunk_member_entry, 0, sizeof(hg_trunk_member_entry_t)); 3064 #if defined(BCM_KATANA2_SUPPORT) 3065 if (SOC_IS_KATANA2(unit)) { 3066 soc_HG_TRUNK_MEMBERm_field32_set(unit, &hg_trunk_member_entry, 3067 PHYSICAL_PORTf, swft->modport[i%nmp] & 0xff); 3068 soc_HG_TRUNK_MEMBERm_field32_set(unit, &hg_trunk_member_entry, 3069 PP_PORTf, swft->modport[i%nmp] & 0xff); 3070 } else 3071 #endif /* (defined(BCM_KATANA2_SUPPORT) */ 3072 { 3073 soc_HG_TRUNK_MEMBERm_field32_set 3074 (unit, &hg_trunk_member_entry, PORT_NUMf, swft->modport[i%nmp] & 0xff); 3075 } 3076 SOC_IF_ERROR_RETURN 3077 (WRITE_HG_TRUNK_MEMBERm(unit, MEM_BLOCK_ALL, base_ptr + i, 3078 &hg_trunk_member_entry)); 3079 } 3080 3081 /* Set hg_trunk_member_bitmap */ 3082 _BCM_HG_TRUNK_MEMBER_USED_SET_RANGE(unit, base_ptr, num_entries); 3083 3084 soc_HG_TRUNK_GROUPm_field32_set 3085 (unit, &hg_trunk_group_entry, BASE_PTRf, base_ptr); 3086 soc_HG_TRUNK_GROUPm_field32_set 3087 (unit, &hg_trunk_group_entry, TG_SIZEf, nmp-1); 3088 soc_HG_TRUNK_GROUPm_field32_set 3089 (unit, &hg_trunk_group_entry, RTAGf, swft->rtag); 3090 #if defined(BCM_HGPROXY_COE_SUPPORT) 3091 if (soc_mem_field_valid(unit, HG_TRUNK_GROUPm, ENTRY_TYPEf)) { 3092 soc_HG_TRUNK_GROUPm_field32_set 3093 (unit, &hg_trunk_group_entry, ENTRY_TYPEf, entry_type); 3094 } 3095 #endif 3096 SOC_IF_ERROR_RETURN 3097 (WRITE_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, hgtid, &hg_trunk_group_entry)); 3098 } 3099 3100 SOC_IF_ERROR_RETURN 3101 (READ_HG_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, hgtid, &hg_trunk_bitmap_entry)); 3102 SOC_PBMP_CLEAR(old_trunk_pbmp); 3103 soc_mem_pbmp_field_get(unit, HG_TRUNK_BITMAPm, &hg_trunk_bitmap_entry, 3104 HIGIG_TRUNK_BITMAPf, &old_trunk_pbmp); 3105 3106 SOC_PBMP_ASSIGN(new_trunk_pbmp, old_trunk_pbmp); 3107 SOC_PBMP_PORT_REMOVE(new_trunk_pbmp, port); 3108 3109 soc_mem_pbmp_field_set(unit, HG_TRUNK_BITMAPm, &hg_trunk_bitmap_entry, 3110 HIGIG_TRUNK_BITMAPf, &new_trunk_pbmp); 3111 SOC_IF_ERROR_RETURN 3112 (WRITE_HG_TRUNK_BITMAPm(unit, MEM_BLOCK_ALL, hgtid, &hg_trunk_bitmap_entry)); 3113 3114 BCM_IF_ERROR_RETURN 3115 (_bcm_trident_trunk_fabric_port_set(unit, 3116 hgtid, 3117 old_trunk_pbmp, 3118 new_trunk_pbmp)); 3119 3120 /* Clear the previously used region in HG_TRUNK_MEMBERm and hg_trunk_member_bitmap. */ 3121 old_num_entries = old_tg_size; 3122 if (old_rtag >= 1 && old_rtag <= 6) { 3123 #ifdef BCM_KATANA_SUPPORT 3124 if(SOC_IS_KATANAX(unit)) { 3125 old_num_entries = _BCM_KATANA_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT; 3126 } else 3127 #endif 3128 if (soc_feature(unit, soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 3129 old_num_entries = _BCM_TD_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT; 3130 } 3131 } 3132 _BCM_HG_TRUNK_MEMBER_USED_CLR_RANGE(unit, old_base_ptr, old_num_entries); 3133 for (i = 0; i < old_num_entries; i++) { 3134 sal_memset(&hg_trunk_member_entry, 0, sizeof(hg_trunk_member_entry_t)); 3135 SOC_IF_ERROR_RETURN 3136 (WRITE_HG_TRUNK_MEMBERm(unit, MEM_BLOCK_ALL, old_base_ptr + i, 3137 soc_mem_entry_null(unit, HG_TRUNK_MEMBERm))); 3138 } 3139 3140 return BCM_E_NONE; 3141 } 3142 3143 /* 3144 * Function: 3145 * _bcm_trident_trunk_swfailover_nonuc_update 3146 * Purpose: 3147 * Update non-unicast trunk block mask table for 3148 * software failover. 3149 * Parameters: 3150 * unit - (IN) SOC unit number. 3151 * num_ports - (IN) Number of ports remaining in the trunk group, 3152 * excluding the failed port. 3153 * swft - (IN) Software failover trunk group info, excluding 3154 * the failed port. 3155 * mymodid - (IN) Local module ID. 3156 * old_trunk_pbmp - (IN) Trunk port bitmap before removing failed port. 3157 * new_trunk_pbmp - (IN) Trunk port bitmap after removing failed port. 3158 * Returns: 3159 * BCM_E_xxx 3160 */ 3161 STATIC int 3162 _bcm_trident_trunk_swfailover_nonuc_update(int unit, 3163 int num_ports, 3164 _trident_tinfo_t *swft, 3165 int mymodid, 3166 pbmp_t old_trunk_pbmp, 3167 pbmp_t new_trunk_pbmp) 3168 { 3169 int rv = BCM_E_NONE; 3170 bcm_module_t *mods = NULL; 3171 int i; 3172 SHR_BITDCL *nuc_tpbm = NULL; 3173 SHR_BITDCL *ipmc_tpbm = NULL; 3174 SHR_BITDCL *l2mc_tpbm = NULL; 3175 SHR_BITDCL *bcast_tpbm = NULL; 3176 SHR_BITDCL *dlf_tpbm = NULL; 3177 SHR_BITDCL *ipmc_my_modid_bmap = NULL; 3178 SHR_BITDCL *l2mc_my_modid_bmap = NULL; 3179 SHR_BITDCL *bcast_my_modid_bmap = NULL; 3180 SHR_BITDCL *dlf_my_modid_bmap = NULL; 3181 uint32 ipmc_member_count; 3182 uint32 l2mc_member_count; 3183 uint32 bcast_member_count; 3184 uint32 dlf_member_count; 3185 bcm_port_t loc_port; 3186 int *ipmc_localport_array = NULL; 3187 int *l2mc_localport_array = NULL; 3188 int *bcast_localport_array = NULL; 3189 int *dlf_localport_array = NULL; 3190 int ipmc_localport_count; 3191 int l2mc_localport_count; 3192 int bcast_localport_count; 3193 int dlf_localport_count; 3194 3195 if (num_ports > 0) { 3196 /* Derive a member bitmap of non-unicast eligible members */ 3197 mods = sal_alloc(sizeof(bcm_module_t) * num_ports, "mods"); 3198 if (mods == NULL) { 3199 rv = BCM_E_MEMORY; 3200 goto cleanup; 3201 } 3202 for (i = 0; i < num_ports; i++) { 3203 mods[i] = swft->modport[i] >> 8; 3204 } 3205 3206 nuc_tpbm = sal_alloc(SHR_BITALLOCSIZE(num_ports), "nuc_tpbm"); 3207 if (nuc_tpbm == NULL) { 3208 rv = BCM_E_MEMORY; 3209 goto cleanup; 3210 } 3211 sal_memset(nuc_tpbm, 0, SHR_BITALLOCSIZE(num_ports)); 3212 rv = _bcm_trident_nuc_tpbm_get(unit, num_ports, mods, nuc_tpbm); 3213 if (BCM_FAILURE(rv)) { 3214 goto cleanup; 3215 } 3216 3217 /* Copy the non-unicast eligible member bitmap to IPMC, L2MC, 3218 * broadcast, and DLF eligible member bitmaps. 3219 */ 3220 ipmc_tpbm = sal_alloc(SHR_BITALLOCSIZE(num_ports), "ipmc_tpbm"); 3221 if (ipmc_tpbm == NULL) { 3222 rv = BCM_E_MEMORY; 3223 goto cleanup; 3224 } 3225 sal_memcpy(ipmc_tpbm, nuc_tpbm, SHR_BITALLOCSIZE(num_ports)); 3226 3227 l2mc_tpbm = sal_alloc(SHR_BITALLOCSIZE(num_ports), "l2mc_tpbm"); 3228 if (l2mc_tpbm == NULL) { 3229 rv = BCM_E_MEMORY; 3230 goto cleanup; 3231 } 3232 sal_memcpy(l2mc_tpbm, nuc_tpbm, SHR_BITALLOCSIZE(num_ports)); 3233 3234 bcast_tpbm = sal_alloc(SHR_BITALLOCSIZE(num_ports), "bcast_tpbm"); 3235 if (bcast_tpbm == NULL) { 3236 rv = BCM_E_MEMORY; 3237 goto cleanup; 3238 } 3239 sal_memcpy(bcast_tpbm, nuc_tpbm, SHR_BITALLOCSIZE(num_ports)); 3240 3241 dlf_tpbm = sal_alloc(SHR_BITALLOCSIZE(num_ports), "dlf_tpbm"); 3242 if (dlf_tpbm == NULL) { 3243 rv = BCM_E_MEMORY; 3244 goto cleanup; 3245 } 3246 sal_memcpy(dlf_tpbm, nuc_tpbm, SHR_BITALLOCSIZE(num_ports)); 3247 3248 /* Iterate through the trunk member list to get port bitmaps 3249 * of IPMC/L2MC/BCAST/DLF eligible local members. 3250 */ 3251 ipmc_my_modid_bmap = sal_alloc(SHR_BITALLOCSIZE(num_ports), 3252 "ipmc_my_modid_bmap"); 3253 if (ipmc_my_modid_bmap == NULL) { 3254 rv = BCM_E_MEMORY; 3255 goto cleanup; 3256 } 3257 sal_memset(ipmc_my_modid_bmap, 0, SHR_BITALLOCSIZE(num_ports)); 3258 3259 l2mc_my_modid_bmap = sal_alloc(SHR_BITALLOCSIZE(num_ports), 3260 "l2mc_my_modid_bmap"); 3261 if (l2mc_my_modid_bmap == NULL) { 3262 rv = BCM_E_MEMORY; 3263 goto cleanup; 3264 } 3265 sal_memset(l2mc_my_modid_bmap, 0, SHR_BITALLOCSIZE(num_ports)); 3266 3267 bcast_my_modid_bmap = sal_alloc(SHR_BITALLOCSIZE(num_ports), 3268 "bcast_my_modid_bmap"); 3269 if (bcast_my_modid_bmap == NULL) { 3270 rv = BCM_E_MEMORY; 3271 goto cleanup; 3272 } 3273 sal_memset(bcast_my_modid_bmap, 0, SHR_BITALLOCSIZE(num_ports)); 3274 3275 dlf_my_modid_bmap = sal_alloc(SHR_BITALLOCSIZE(num_ports), 3276 "dlf_my_modid_bmap"); 3277 if (dlf_my_modid_bmap == NULL) { 3278 rv = BCM_E_MEMORY; 3279 goto cleanup; 3280 } 3281 sal_memset(dlf_my_modid_bmap, 0, SHR_BITALLOCSIZE(num_ports)); 3282 3283 ipmc_localport_array = sal_alloc(num_ports * sizeof(int), 3284 "ipmc_localport_array"); 3285 if (ipmc_localport_array == NULL) { 3286 rv = BCM_E_MEMORY; 3287 goto cleanup; 3288 } 3289 sal_memset(ipmc_localport_array, 0, num_ports * sizeof(int)); 3290 l2mc_localport_array = sal_alloc(num_ports * sizeof(int), 3291 "l2mc_localport_array"); 3292 if (l2mc_localport_array == NULL) { 3293 rv = BCM_E_MEMORY; 3294 goto cleanup; 3295 } 3296 sal_memset(l2mc_localport_array, 0, num_ports * sizeof(int)); 3297 bcast_localport_array = sal_alloc(num_ports * sizeof(int), 3298 "bcast_localport_array"); 3299 if (bcast_localport_array == NULL) { 3300 rv = BCM_E_MEMORY; 3301 goto cleanup; 3302 } 3303 sal_memset(bcast_localport_array, 0, num_ports * sizeof(int)); 3304 dlf_localport_array = sal_alloc(num_ports * sizeof(int), 3305 "dlf_localport_array"); 3306 if (dlf_localport_array == NULL) { 3307 rv = BCM_E_MEMORY; 3308 goto cleanup; 3309 } 3310 sal_memset(dlf_localport_array, 0, num_ports * sizeof(int)); 3311 3312 ipmc_member_count = 0; 3313 l2mc_member_count = 0; 3314 bcast_member_count = 0; 3315 dlf_member_count = 0; 3316 ipmc_localport_count = 0; 3317 l2mc_localport_count = 0; 3318 bcast_localport_count = 0; 3319 dlf_localport_count = 0; 3320 3321 for (i= 0; i < num_ports; i++) { 3322 if (swft->member_flags[i] & 3323 BCM_TRUNK_MEMBER_IPMC_EGRESS_DISABLE) { 3324 SHR_BITCLR(ipmc_tpbm, i); 3325 } 3326 if (swft->member_flags[i] & 3327 BCM_TRUNK_MEMBER_L2MC_EGRESS_DISABLE) { 3328 SHR_BITCLR(l2mc_tpbm, i); 3329 } 3330 if (swft->member_flags[i] & 3331 BCM_TRUNK_MEMBER_BCAST_EGRESS_DISABLE) { 3332 SHR_BITCLR(bcast_tpbm, i); 3333 } 3334 if (swft->member_flags[i] & 3335 BCM_TRUNK_MEMBER_DLF_EGRESS_DISABLE) { 3336 SHR_BITCLR(dlf_tpbm, i); 3337 } 3338 3339 if (mymodid == (swft->modport[i] >> 8)) { 3340 /* local port */ 3341 loc_port = swft->modport[i] & 0xff; 3342 if (SHR_BITGET(ipmc_tpbm, i)) { 3343 ipmc_localport_array[ipmc_localport_count++] = loc_port; 3344 SHR_BITSET(ipmc_my_modid_bmap, ipmc_member_count); 3345 } 3346 if (SHR_BITGET(l2mc_tpbm, i)) { 3347 l2mc_localport_array[l2mc_localport_count++] = loc_port; 3348 SHR_BITSET(l2mc_my_modid_bmap, l2mc_member_count); 3349 } 3350 if (SHR_BITGET(bcast_tpbm, i)) { 3351 bcast_localport_array[bcast_localport_count++] = loc_port; 3352 SHR_BITSET(bcast_my_modid_bmap, bcast_member_count); 3353 } 3354 if (SHR_BITGET(dlf_tpbm, i)) { 3355 dlf_localport_array[dlf_localport_count++] = loc_port; 3356 SHR_BITSET(dlf_my_modid_bmap, dlf_member_count); 3357 } 3358 } 3359 3360 if (SHR_BITGET(ipmc_tpbm, i)) { 3361 /* Eligible for IPMC forwarding */ 3362 ipmc_member_count++; 3363 } 3364 if (SHR_BITGET(l2mc_tpbm, i)) { 3365 /* Eligible for L2MC forwarding */ 3366 l2mc_member_count++; 3367 } 3368 if (SHR_BITGET(bcast_tpbm, i)) { 3369 /* Eligible for broadcast forwarding */ 3370 bcast_member_count++; 3371 } 3372 if (SHR_BITGET(dlf_tpbm, i)) { 3373 /* Eligible for DLF forwarding */ 3374 dlf_member_count++; 3375 } 3376 } 3377 3378 /* Update trunk block masks */ 3379 rv = _bcm_trident_trunk_block_mask(unit, 3380 TRUNK_BLOCK_MASK_TYPE_IPMC, 3381 old_trunk_pbmp, 3382 new_trunk_pbmp, 3383 ipmc_localport_array, 3384 ipmc_localport_count, 3385 ipmc_my_modid_bmap, 3386 ipmc_member_count, 3387 swft->flags); 3388 if (BCM_FAILURE(rv)) { 3389 goto cleanup; 3390 } 3391 rv = _bcm_trident_trunk_block_mask(unit, 3392 TRUNK_BLOCK_MASK_TYPE_L2MC, 3393 old_trunk_pbmp, 3394 new_trunk_pbmp, 3395 l2mc_localport_array, 3396 l2mc_localport_count, 3397 l2mc_my_modid_bmap, 3398 l2mc_member_count, 3399 swft->flags); 3400 if (BCM_FAILURE(rv)) { 3401 goto cleanup; 3402 } 3403 rv = _bcm_trident_trunk_block_mask(unit, 3404 TRUNK_BLOCK_MASK_TYPE_BCAST, 3405 old_trunk_pbmp, 3406 new_trunk_pbmp, 3407 bcast_localport_array, 3408 bcast_localport_count, 3409 bcast_my_modid_bmap, 3410 bcast_member_count, 3411 swft->flags); 3412 if (BCM_FAILURE(rv)) { 3413 goto cleanup; 3414 } 3415 rv = _bcm_trident_trunk_block_mask(unit, 3416 TRUNK_BLOCK_MASK_TYPE_DLF, 3417 old_trunk_pbmp, 3418 new_trunk_pbmp, 3419 dlf_localport_array, 3420 dlf_localport_count, 3421 dlf_my_modid_bmap, 3422 dlf_member_count, 3423 swft->flags); 3424 if (BCM_FAILURE(rv)) { 3425 goto cleanup; 3426 } 3427 } else { 3428 rv = _bcm_trident_trunk_block_mask(unit, 3429 TRUNK_BLOCK_MASK_TYPE_IPMC, 3430 old_trunk_pbmp, 3431 new_trunk_pbmp, 3432 NULL, 0, 3433 NULL, 3434 0, 3435 swft->flags); 3436 if (BCM_FAILURE(rv)) { 3437 goto cleanup; 3438 } 3439 rv = _bcm_trident_trunk_block_mask(unit, 3440 TRUNK_BLOCK_MASK_TYPE_L2MC, 3441 old_trunk_pbmp, 3442 new_trunk_pbmp, 3443 NULL, 0, 3444 NULL, 3445 0, 3446 swft->flags); 3447 if (BCM_FAILURE(rv)) { 3448 goto cleanup; 3449 } 3450 rv = _bcm_trident_trunk_block_mask(unit, 3451 TRUNK_BLOCK_MASK_TYPE_BCAST, 3452 old_trunk_pbmp, 3453 new_trunk_pbmp, 3454 NULL, 0, 3455 NULL, 3456 0, 3457 swft->flags); 3458 if (BCM_FAILURE(rv)) { 3459 goto cleanup; 3460 } 3461 rv = _bcm_trident_trunk_block_mask(unit, 3462 TRUNK_BLOCK_MASK_TYPE_DLF, 3463 old_trunk_pbmp, 3464 new_trunk_pbmp, 3465 NULL, 0, 3466 NULL, 3467 0, 3468 swft->flags); 3469 if (BCM_FAILURE(rv)) { 3470 goto cleanup; 3471 } 3472 } 3473 3474 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3) 3475 if (soc_feature(unit, soc_feature_axp)) { 3476 rv = _bcm_tr3_wlan_trunk_block_mask_update(unit); 3477 if (BCM_FAILURE(rv)) { 3478 goto cleanup; 3479 } 3480 } 3481 #endif /* BCM_TRIUMPH3_SUPPORT && defined(INCLUDE_L3) */ 3482 3483 3484 cleanup: 3485 if (mods) { 3486 sal_free(mods); 3487 } 3488 if (nuc_tpbm) { 3489 sal_free(nuc_tpbm); 3490 } 3491 if (ipmc_tpbm) { 3492 sal_free(ipmc_tpbm); 3493 } 3494 if (l2mc_tpbm) { 3495 sal_free(l2mc_tpbm); 3496 } 3497 if (bcast_tpbm) { 3498 sal_free(bcast_tpbm); 3499 } 3500 if (dlf_tpbm) { 3501 sal_free(dlf_tpbm); 3502 } 3503 if (ipmc_my_modid_bmap) { 3504 sal_free(ipmc_my_modid_bmap); 3505 } 3506 if (l2mc_my_modid_bmap) { 3507 sal_free(l2mc_my_modid_bmap); 3508 } 3509 if (bcast_my_modid_bmap) { 3510 sal_free(bcast_my_modid_bmap); 3511 } 3512 if (dlf_my_modid_bmap) { 3513 sal_free(dlf_my_modid_bmap); 3514 } 3515 if (ipmc_localport_array) { 3516 sal_free(ipmc_localport_array); 3517 } 3518 if (l2mc_localport_array) { 3519 sal_free(l2mc_localport_array); 3520 } 3521 if (bcast_localport_array) { 3522 sal_free(bcast_localport_array); 3523 } 3524 if (dlf_localport_array) { 3525 sal_free(dlf_localport_array); 3526 } 3527 3528 return rv; 3529 } 3530 3531 /* 3532 * Function: 3533 * _bcm_trident_trunk_swfailover_trigger 3534 * Purpose: 3535 * Delete failed port from trunk config. 3536 * Parameters: 3537 * unit - (IN) SOC unit number. 3538 * ports_active - (IN) Port bitmap of active ports. 3539 * ports_status - (IN) Bitmap of ports status. 3540 * Returns: 3541 * BCM_E_xxx 3542 */ 3543 int 3544 _bcm_trident_trunk_swfailover_trigger(int unit, 3545 bcm_pbmp_t ports_active, 3546 bcm_pbmp_t ports_status) 3547 { 3548 bcm_trunk_chip_info_t chip_info; 3549 bcm_port_t port; 3550 int tid; 3551 _trident_trunk_swfail_t *swf; 3552 _trident_tinfo_t *swft; 3553 int fabric_trunk_swf_tid_offset; 3554 3555 swf = _trident_trunk_swfail[unit]; 3556 3557 if (swf == NULL) { 3558 return BCM_E_NONE; 3559 } 3560 3561 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 3562 fabric_trunk_swf_tid_offset = chip_info.trunk_group_count + 1; 3563 3564 PBMP_ITER(ports_active, port) { 3565 if (BCM_PBMP_MEMBER(ports_status, port)) { 3566 continue; /* link up */ 3567 } 3568 3569 /* link down */ 3570 tid = swf->trunk[port]; 3571 swf->trunk[port] = 0; 3572 if (tid <= 0) { 3573 continue; /* already removed */ 3574 } 3575 3576 if (tid >= 1 && tid <= chip_info.trunk_group_count) { 3577 pbmp_t new_trunk_pbmp; 3578 pbmp_t old_trunk_pbmp; 3579 uint16 modport; 3580 int i, j, nmp, rv; 3581 int uc_nmp; 3582 int old_base_ptr, old_tg_size, old_rtag; 3583 int max_base_ptr, base_ptr; 3584 int num_entries, old_num_entries; 3585 SHR_BITDCL occupied; 3586 trunk_member_entry_t trunk_member_entry; 3587 trunk_group_entry_t tg_entry; 3588 trunk_bitmap_entry_t trunk_bitmap_entry; 3589 uint16 *uc_modport = NULL; 3590 3591 tid = tid - 1; 3592 swft = &swf->tinfo[tid]; 3593 SOC_PBMP_CLEAR(new_trunk_pbmp); 3594 3595 /* update _trident_trunk_swfail: remove matching ports, update size */ 3596 3597 modport = (swf->mymodid << 8) | port; 3598 nmp = swft->num_ports; 3599 3600 for (i = j = 0; i < nmp; i++) { 3601 if (swft->modport[i] != modport) { 3602 if (i != j) { 3603 swft->modport[j] = swft->modport[i]; 3604 swft->member_flags[j] = swft->member_flags[i]; 3605 } 3606 j += 1; 3607 } 3608 } 3609 if (j == nmp) { 3610 continue; /* no changes, so no need to write out */ 3611 } 3612 swft->num_ports = nmp = j; 3613 3614 /* Get unicast egress trunk member ports */ 3615 uc_modport = sal_alloc(sizeof(uint16) * nmp, "uc_modport"); 3616 if (uc_modport == NULL) { 3617 return BCM_E_MEMORY; 3618 } 3619 uc_nmp = 0; 3620 for (i = 0; i < nmp; i++) { 3621 if (swft->member_flags[i] & 3622 BCM_TRUNK_MEMBER_UNICAST_EGRESS_DISABLE) { 3623 continue; 3624 } 3625 uc_modport[uc_nmp++] = swft->modport[i]; 3626 } 3627 3628 /* Convert _trident_trunk_swfail into trunk_group, trunk_member, 3629 * and trunk_bitmap tables 3630 */ 3631 rv = READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry); 3632 if (BCM_FAILURE(rv)) { 3633 sal_free(uc_modport); 3634 return rv; 3635 } 3636 old_base_ptr = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, 3637 BASE_PTRf); 3638 old_tg_size = 1 + soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, 3639 TG_SIZEf); 3640 old_rtag = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, RTAGf); 3641 3642 if (uc_nmp == 0) { 3643 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, BASE_PTRf, 0); 3644 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, TG_SIZEf, 0); 3645 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, RTAGf, 0); 3646 rv = WRITE_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, tid, &tg_entry); 3647 if (BCM_FAILURE(rv)) { 3648 sal_free(uc_modport); 3649 return rv; 3650 } 3651 } else { 3652 /* Find a contiguous region of TRUNK_MEMBERm table that's large 3653 * enough to hold all of the trunk group's member ports. 3654 */ 3655 num_entries = uc_nmp; 3656 3657 /* If RTAG is 1-6, Trident A0 and Katana ignore the TG_SIZE field 3658 * and assume the trunk group occupies FP_TRUNK_RTAG1_6_MAX_PORTCNT 3659 * contiguous entries in TRUNK_MEMBER table. 3660 */ 3661 if (swft->rtag >= 1 && swft->rtag <= 6) { 3662 #ifdef BCM_KATANA_SUPPORT 3663 if(SOC_IS_KATANAX(unit)) { 3664 num_entries = _BCM_KATANA_FP_TRUNK_RTAG1_6_MAX_PORTCNT; 3665 } else 3666 #endif 3667 if (soc_feature(unit, 3668 soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 3669 num_entries = _BCM_TD_FP_TRUNK_RTAG1_6_MAX_PORTCNT; 3670 } 3671 } 3672 3673 max_base_ptr = soc_mem_index_count(unit, TRUNK_MEMBERm) - num_entries; 3674 for (base_ptr = 0; base_ptr <= max_base_ptr; base_ptr++) { 3675 /* Check if the contiguous region of TRUNK_MEMBERm table from 3676 * index base_ptr to (base_ptr + num_entries - 1) is free. 3677 */ 3678 _BCM_FP_TRUNK_MEMBER_TEST_RANGE(unit, base_ptr, num_entries, occupied); 3679 if (!occupied) { 3680 break; 3681 } 3682 } 3683 3684 if (base_ptr > max_base_ptr) { 3685 /* A contiguous region of the desired size could not be found in 3686 * TRUNK_MEMBERm table. 3687 */ 3688 sal_free(uc_modport); 3689 return BCM_E_RESOURCE; 3690 } 3691 3692 for (i = 0; i < num_entries; i++) { 3693 sal_memset(&trunk_member_entry, 0, sizeof(trunk_member_entry_t)); 3694 soc_TRUNK_MEMBERm_field32_set(unit, &trunk_member_entry, 3695 MODULE_IDf, uc_modport[i%uc_nmp] >> 8); 3696 soc_TRUNK_MEMBERm_field32_set(unit, &trunk_member_entry, 3697 PORT_NUMf, uc_modport[i%uc_nmp] & 0xff); 3698 rv = WRITE_TRUNK_MEMBERm(unit, MEM_BLOCK_ALL, base_ptr + i, 3699 &trunk_member_entry); 3700 if (BCM_FAILURE(rv)) { 3701 sal_free(uc_modport); 3702 return rv; 3703 } 3704 } 3705 3706 /* Set fp_trunk_member_bitmap */ 3707 _BCM_FP_TRUNK_MEMBER_USED_SET_RANGE(unit, base_ptr, num_entries); 3708 3709 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, BASE_PTRf, base_ptr); 3710 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, TG_SIZEf, uc_nmp-1); 3711 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, RTAGf, swft->rtag); 3712 rv = WRITE_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, tid, &tg_entry); 3713 if (BCM_FAILURE(rv)) { 3714 sal_free(uc_modport); 3715 return rv; 3716 } 3717 } 3718 3719 sal_free(uc_modport); 3720 uc_modport = NULL; 3721 3722 rv = READ_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, tid, &trunk_bitmap_entry); 3723 if (BCM_FAILURE(rv)) { 3724 return rv; 3725 } 3726 SOC_PBMP_CLEAR(old_trunk_pbmp); 3727 soc_mem_pbmp_field_get(unit, TRUNK_BITMAPm, &trunk_bitmap_entry, 3728 TRUNK_BITMAPf, &old_trunk_pbmp); 3729 3730 SOC_PBMP_ASSIGN(new_trunk_pbmp, old_trunk_pbmp); 3731 SOC_PBMP_PORT_REMOVE(new_trunk_pbmp, port); 3732 soc_mem_pbmp_field_set(unit, TRUNK_BITMAPm, &trunk_bitmap_entry, 3733 TRUNK_BITMAPf, &new_trunk_pbmp); 3734 rv = WRITE_TRUNK_BITMAPm(unit, MEM_BLOCK_ALL, tid, &trunk_bitmap_entry); 3735 if (BCM_FAILURE(rv)) { 3736 return rv; 3737 } 3738 3739 /* Update SOURCE_TRUNK_MAP table */ 3740 rv = _bcm_trident_trunk_set_port_property(unit, swf->mymodid, port, -1); 3741 if (BCM_FAILURE(rv)) { 3742 return rv; 3743 } 3744 3745 /* Clear the previously used region in TRUNK_MEMBERm and fp_trunk_member_bitmap. */ 3746 if (old_rtag != 0) { 3747 old_num_entries = old_tg_size; 3748 if (old_rtag >= 1 && old_rtag <= 6) { 3749 #ifdef BCM_KATANA_SUPPORT 3750 if (SOC_IS_KATANAX(unit)) { 3751 old_num_entries = _BCM_KATANA_FP_TRUNK_RTAG1_6_MAX_PORTCNT; 3752 } else 3753 #endif 3754 if (soc_feature(unit, 3755 soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 3756 old_num_entries = _BCM_TD_FP_TRUNK_RTAG1_6_MAX_PORTCNT; 3757 } 3758 } 3759 3760 _BCM_FP_TRUNK_MEMBER_USED_CLR_RANGE(unit, old_base_ptr, old_num_entries); 3761 for (i = 0; i < old_num_entries; i++) { 3762 rv = WRITE_TRUNK_MEMBERm(unit, MEM_BLOCK_ALL, old_base_ptr + i, 3763 soc_mem_entry_null(unit, TRUNK_MEMBERm)); 3764 if (BCM_FAILURE(rv)) { 3765 return rv; 3766 } 3767 } 3768 } 3769 3770 /* update non uc trunk block mask table */ 3771 rv = _bcm_trident_trunk_swfailover_nonuc_update(unit, nmp, swft, 3772 swf->mymodid, old_trunk_pbmp, new_trunk_pbmp); 3773 if (BCM_FAILURE(rv)) { 3774 return rv; 3775 } 3776 3777 } else if ((tid >= fabric_trunk_swf_tid_offset) && 3778 (tid <= (chip_info.trunk_fabric_id_max + 1))) { 3779 /* higig trunk */ 3780 BCM_IF_ERROR_RETURN( 3781 _bcm_trident_trunk_fabric_swfailover_trigger 3782 (unit, 3783 port, 3784 tid - fabric_trunk_swf_tid_offset, 3785 swf)); 3786 } 3787 } 3788 3789 return BCM_E_NONE; 3790 } 3791 #endif /* BCM_TRUNK_FAILOVER_SUPPORT */ 3792 3793 /* ----------------------------------------------------------------------------- 3794 * 3795 * Routines for front panel trunking 3796 * 3797 * ----------------------------------------------------------------------------- 3798 */ 3799 3800 /* 3801 * Function: 3802 * _bcm_trident_lag_slb_free_resource 3803 * Purpose: 3804 * Free resources for a LAG static load balancing group. 3805 * Parameters: 3806 * unit - (IN) SOC unit number. 3807 * tid - (IN) Trunk group ID. 3808 * Returns: 3809 * BCM_E_xxx 3810 */ 3811 STATIC int 3812 _bcm_trident_lag_slb_free_resource(int unit, int tid) 3813 { 3814 trunk_group_entry_t tg_entry; 3815 int base_ptr; 3816 int tg_size; 3817 int rtag; 3818 int num_entries; 3819 int trunk_mode = 0; 3820 3821 SOC_IF_ERROR_RETURN 3822 (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry)); 3823 base_ptr = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, 3824 BASE_PTRf); 3825 tg_size = 1 + soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, 3826 TG_SIZEf); 3827 rtag = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, 3828 RTAGf); 3829 if (soc_mem_field_valid(unit, TRUNK_GROUPm, TRUNK_MODEf)) { 3830 trunk_mode = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, 3831 TRUNK_MODEf); 3832 } 3833 3834 if ((rtag != 0) || (trunk_mode != 0)) { 3835 num_entries = tg_size; 3836 if (rtag >= 1 && rtag <= 6) { 3837 #ifdef BCM_KATANA_SUPPORT 3838 if (SOC_IS_KATANAX(unit)) { 3839 num_entries = _BCM_KATANA_FP_TRUNK_RTAG1_6_MAX_PORTCNT; 3840 } else 3841 #endif 3842 if (soc_feature(unit, 3843 soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 3844 num_entries = _BCM_TD_FP_TRUNK_RTAG1_6_MAX_PORTCNT; 3845 } 3846 } 3847 3848 _BCM_FP_TRUNK_MEMBER_USED_CLR_RANGE(unit, base_ptr, num_entries); 3849 } 3850 3851 return BCM_E_NONE; 3852 } 3853 3854 /* 3855 * Function: 3856 * _bcm_trident_lag_slb_set 3857 * Purpose: 3858 * Configure a LAG static load balancing group. 3859 * Parameters: 3860 * unit - (IN) SOC unit number. 3861 * tid - (IN) Trunk group ID. 3862 * num_uc_egr_ports - (IN) Number of trunk member ports eligible for 3863 * unicast egress 3864 * uc_egr_hwmod - (IN) Array of module IDs 3865 * uc_egr_hwport - (IN) Array of port IDs 3866 * t_info - (IN) Pointer to trunk info. 3867 * Returns: 3868 * BCM_E_xxx 3869 */ 3870 STATIC int 3871 _bcm_trident_lag_slb_set(int unit, int tid, int num_uc_egr_ports, 3872 int *uc_egr_hwmod, int *uc_egr_hwport, trunk_private_t *t_info) 3873 { 3874 int i; 3875 int num_entries; 3876 int max_base_ptr; 3877 int base_ptr; 3878 SHR_BITDCL occupied; 3879 trunk_member_entry_t trunk_member_entry; 3880 trunk_group_entry_t tg_entry; 3881 #ifdef BCM_TOMAHAWK_SUPPORT 3882 trunk_rr_cnt_entry_t rrlb_cnt_entry; 3883 uint16 seed=0; 3884 soc_reg_t reg; 3885 uint32 rval; 3886 int pipe; 3887 #endif 3888 3889 if (num_uc_egr_ports == 0) { 3890 SOC_IF_ERROR_RETURN 3891 (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry)); 3892 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, BASE_PTRf, 0); 3893 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, TG_SIZEf, 0); 3894 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, RTAGf, 0); 3895 SOC_IF_ERROR_RETURN 3896 (WRITE_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, tid, &tg_entry)); 3897 return BCM_E_NONE; 3898 } 3899 3900 /* Find a contiguous region of TRUNK_MEMBERm table that's large 3901 * enough to hold all of the trunk group's egress member ports. 3902 */ 3903 3904 num_entries = num_uc_egr_ports; 3905 3906 /* If RTAG is 1-6, Trident A0 and Katana ignore the TG_SIZE field and 3907 * assume the trunk group occupies FP_TRUNK_RTAG1_6_MAX_PORTCNT 3908 * contiguous entries in TRUNK_MEMBER table. 3909 */ 3910 if (t_info->rtag >= 1 && t_info->rtag <= 6) { 3911 #ifdef BCM_KATANA_SUPPORT 3912 if (SOC_IS_KATANAX(unit)) { 3913 num_entries = _BCM_KATANA_FP_TRUNK_RTAG1_6_MAX_PORTCNT; 3914 } else 3915 #endif 3916 if (soc_feature(unit, 3917 soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 3918 num_entries = _BCM_TD_FP_TRUNK_RTAG1_6_MAX_PORTCNT; 3919 } 3920 } 3921 3922 max_base_ptr = soc_mem_index_count(unit, TRUNK_MEMBERm) - num_entries; 3923 for (base_ptr = 0; base_ptr <= max_base_ptr; base_ptr++) { 3924 /* Check if the contiguous region of TRUNK_MEMBERm table from 3925 * index base_ptr to (base_ptr + num_entries - 1) is free. 3926 */ 3927 _BCM_FP_TRUNK_MEMBER_TEST_RANGE(unit, base_ptr, num_entries, occupied); 3928 if (!occupied) { 3929 break; 3930 } 3931 } 3932 3933 if (base_ptr > max_base_ptr) { 3934 /* A contiguous region of the desired size could not be found in 3935 * TRUNK_MEMBERm table. 3936 */ 3937 return BCM_E_RESOURCE; 3938 } 3939 3940 for (i = 0; i < num_entries; i++) { 3941 sal_memset(&trunk_member_entry, 0, sizeof(trunk_member_entry_t)); 3942 soc_TRUNK_MEMBERm_field32_set 3943 (unit, &trunk_member_entry, MODULE_IDf, 3944 uc_egr_hwmod[i % num_uc_egr_ports]); 3945 soc_TRUNK_MEMBERm_field32_set 3946 (unit, &trunk_member_entry, PORT_NUMf, 3947 uc_egr_hwport[i % num_uc_egr_ports]); 3948 SOC_IF_ERROR_RETURN(WRITE_TRUNK_MEMBERm(unit, MEM_BLOCK_ALL, 3949 base_ptr + i, &trunk_member_entry)); 3950 } 3951 3952 /* Set fp_trunk_member_bitmap */ 3953 _BCM_FP_TRUNK_MEMBER_USED_SET_RANGE(unit, base_ptr, num_entries); 3954 3955 /* Update TRUNK_GROUP table */ 3956 3957 SOC_IF_ERROR_RETURN 3958 (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry)); 3959 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, BASE_PTRf, base_ptr); 3960 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, TG_SIZEf, 3961 num_uc_egr_ports-1); 3962 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, RTAGf, t_info->rtag); 3963 3964 #ifdef BCM_APACHE_SUPPORT 3965 if (t_info->psc == BCM_TRUNK_PSC_ROUND_ROBIN) { 3966 if (soc_feature(unit, soc_feature_apache_round_robin_fp_lag)) { 3967 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, RR_LB_ENABLEf, 0x1); 3968 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, RR_LB_COUNTER_SELECTf, t_info->rr_lag_select); 3969 } 3970 } 3971 #endif /* BCM_APACHE_SUPPORT */ 3972 3973 #ifdef BCM_TOMAHAWK_SUPPORT 3974 if (t_info->psc == BCM_TRUNK_PSC_ROUND_ROBIN) { 3975 if (soc_feature(unit, soc_feature_round_robin_load_balance)) { 3976 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, TRUNK_MODEf, 0x2); 3977 3978 BCM_IF_ERROR_RETURN(READ_TRUNK_RR_CNTm(unit, MEM_BLOCK_ANY, 3979 tid, &rrlb_cnt_entry)); 3980 soc_TRUNK_RR_CNTm_field32_set(unit, &rrlb_cnt_entry, 3981 RRLB_CNTf, 0); 3982 BCM_IF_ERROR_RETURN(WRITE_TRUNK_RR_CNTm(unit, MEM_BLOCK_ALL, 3983 tid, &rrlb_cnt_entry)); 3984 } 3985 } else if (t_info->psc == BCM_TRUNK_PSC_RANDOMIZED) { 3986 if (soc_feature(unit, soc_feature_randomized_load_balance)) { 3987 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, TRUNK_MODEf, 0x1); 3988 /* Configure Rand LB Seed */ 3989 seed = (sal_rand()) % 0xFFFF; 3990 rval = 0; 3991 for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) { 3992 reg = SOC_REG_UNIQUE_ACC(unit, TRUNK_RAND_LB_SEEDr)[pipe]; 3993 soc_reg_field_set(unit, reg, &rval, SEEDf, seed); 3994 SOC_IF_ERROR_RETURN 3995 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 3996 } 3997 } 3998 } else if (t_info->psc != BCM_TRUNK_PSC_DYNAMIC_RESILIENT) { 3999 if (soc_mem_field_valid(unit, TRUNK_GROUPm, TRUNK_MODEf)) { 4000 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, TRUNK_MODEf, 0x0); 4001 } 4002 } 4003 #endif 4004 4005 SOC_IF_ERROR_RETURN 4006 (WRITE_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, tid, &tg_entry)); 4007 4008 return BCM_E_NONE; 4009 } 4010 4011 /* 4012 * Function: 4013 * _bcm_trident_trunk_block_mask 4014 * Purpose: 4015 * Update the trunk block mask table. 4016 * Old ports are cleared and new ports are added to each entry. 4017 * Each hash index location entry is owned by a specific unit/modid 4018 * across all units in a stack. Hash index location entry owned by 4019 * local unit/modid is provided by my_modid_bmap. member_count is 4020 * the number of NUC forwarding eligible ports in the trunk group. 4021 * Each eligible entry also has a rolling port that is not masked 4022 * from among the new NUC forwarding eligible ports (nuc_ports). 4023 * This is what spreads non-unicast traffic across multiple ports. 4024 * Parameters: 4025 * unit - (IN) SOC unit number. 4026 * nuc_type - (IN) Type of non-unicast: IPMC, L2MC, BCAST, or DLF. 4027 * old_ports - (IN) Old local trunk member ports. 4028 * new_ports - (IN) New local trunk member ports. 4029 * nuc_ports - (IN) New local trunk member ports eligible for non-unicast. 4030 * my_modid_bmap - (IN) Bitmap indicating which non-unicast eligible trunk 4031 * member port is local. 4032 * member_count - (IN) Number of new non-unicast eligible trunk member 4033 * ports, including both local and remote members. 4034 * flags - (IN) Trunk group flags. 4035 * Returns: 4036 * BCM_E_xxx 4037 */ 4038 STATIC int 4039 _bcm_trident_trunk_block_mask(int unit, 4040 int nuc_type, 4041 pbmp_t old_ports, 4042 pbmp_t new_ports, 4043 int *localport_array, 4044 int localport_count, 4045 SHR_BITDCL *my_modid_bmap, 4046 uint32 member_count, 4047 uint32 flags) 4048 { 4049 int all_local; 4050 int i, imin, imax, rv; 4051 int index_count; 4052 soc_mem_t mem; 4053 bcm_pbmp_t pbmp, old_pbmp; 4054 nonucast_trunk_block_mask_entry_t *mask_entry; 4055 nonucast_trunk_block_mask_entry_t *mask_table; 4056 int region_size; 4057 4058 rv = BCM_E_NONE; 4059 4060 all_local = FALSE; 4061 if ((localport_count > 0) && (localport_count == member_count)) { 4062 all_local = TRUE; 4063 } 4064 4065 /* The NONUCAST_TRUNK_BLOCK_MASK table is divided into 4 regions: 4066 * IPMC, L2MC, broadcast, and unknown unicast/multicast. 4067 */ 4068 mem = NONUCAST_TRUNK_BLOCK_MASKm; 4069 region_size = soc_mem_index_count(unit, mem) / 4; 4070 if (nuc_type == TRUNK_BLOCK_MASK_TYPE_IPMC) { 4071 imin = 0; 4072 } else if (nuc_type == TRUNK_BLOCK_MASK_TYPE_L2MC) { 4073 imin = region_size; 4074 } else if (nuc_type == TRUNK_BLOCK_MASK_TYPE_BCAST) { 4075 imin = region_size * 2; 4076 } else if (nuc_type == TRUNK_BLOCK_MASK_TYPE_DLF) { 4077 imin = region_size * 3; 4078 } else { 4079 return BCM_E_PARAM; 4080 } 4081 imax = imin + region_size - 1; 4082 4083 mask_table = soc_cm_salloc(unit, 4084 sizeof(nonucast_trunk_block_mask_entry_t) * region_size, 4085 "nonuc trunk mask tbl dma"); 4086 if (NULL == mask_table) { 4087 return BCM_E_MEMORY; 4088 } 4089 4090 soc_mem_lock(unit, mem); 4091 4092 if ((rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, 4093 imin, imax, mask_table)) < 0) { 4094 soc_mem_unlock(unit, mem); 4095 soc_cm_sfree(unit, mask_table); 4096 return rv; 4097 } 4098 4099 index_count = 0; 4100 for (i = imin; i <= imax; i++) { 4101 mask_entry = soc_mem_table_idx_to_pointer(unit, mem, 4102 nonucast_trunk_block_mask_entry_t *, 4103 mask_table, i - imin); 4104 soc_mem_pbmp_field_get(unit, mem, mask_entry, BLOCK_MASKf, &pbmp); 4105 SOC_PBMP_ASSIGN(old_pbmp, pbmp); 4106 SOC_PBMP_REMOVE(pbmp, old_ports); 4107 if (nuc_type == TRUNK_BLOCK_MASK_TYPE_IPMC && 4108 (flags & BCM_TRUNK_FLAG_IPMC_CLEAVE)) { 4109 /* If the flag BCM_TRUNK_FLAG_IPMC_CLEAVE is set, 4110 * IPMC trunk resolution is disabled, and the bits in 4111 * pbmp corresponding to new_ports are not set. 4112 */ 4113 } else { 4114 SOC_PBMP_OR(pbmp, new_ports); 4115 if (localport_count > 0) { 4116 if (all_local || (member_count > BCM_SWITCH_TRUNK_MAX_PORTCNT)) { 4117 if (SHR_BITGET(my_modid_bmap, 4118 ((i % region_size) % member_count))) { 4119 SOC_PBMP_PORT_REMOVE( 4120 pbmp, localport_array[index_count % localport_count]); 4121 index_count++; 4122 } 4123 } else { 4124 /* Not all trunk members are local, and number of 4125 * members is BCM_SWITCH_TRUNK_MAX_PORTCNT or less. 4126 * We need to conservatively configure 4127 * NONUCAST_TRUNK_BLOCK_MASK table to interoperate 4128 * with pre-Trident XGS3 devices. 4129 */ 4130 if ((i % 16) == 0) { 4131 index_count = 0; 4132 } 4133 if (SHR_BITGET(my_modid_bmap, ((i % 16) % member_count))) { 4134 SOC_PBMP_PORT_REMOVE( 4135 pbmp, localport_array[index_count % localport_count]); 4136 index_count++; 4137 } 4138 } 4139 } 4140 } 4141 if (SOC_PBMP_EQ(pbmp, old_pbmp)) { 4142 continue; 4143 } 4144 4145 soc_mem_pbmp_field_set(unit, mem, mask_entry, BLOCK_MASKf, &pbmp); 4146 } 4147 4148 rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ANY, imin, imax, mask_table); 4149 4150 soc_mem_unlock(unit, mem); 4151 soc_cm_sfree(unit, mask_table); 4152 4153 return rv; 4154 } 4155 4156 /* 4157 * Function: 4158 * _bcm_trident_trunk_mod_port_map_set 4159 * Purpose: 4160 * Set (mod, port) to trunk id map. 4161 * Map implements a software cache for the SOURCE_TRUNK_MAP_TABLE. 4162 * Parameters: 4163 * unit - (IN) BCM device number. 4164 * modid - (IN) Member port module id. 4165 * port - (IN) Member port number. 4166 * trunk_id - (IN) Trunk number or negative value for reset. 4167 * Returns: 4168 * BCM_X_XXX 4169 */ 4170 STATIC int 4171 _bcm_trident_trunk_mod_port_map_set(int unit, 4172 bcm_module_t modid, 4173 bcm_port_t port, 4174 bcm_trunk_t trunk_id) 4175 { 4176 int idx; /* Map array index. */ 4177 4178 if (NULL == _trident_mod_port_to_tid_map[unit]) { 4179 return (BCM_E_INIT); 4180 } 4181 4182 /* Trunk id range check, only 16 bits are allocated per trunk ID in 4183 * _trident_mod_port_to_tid_map 4184 */ 4185 if (trunk_id >= 0xffff) { 4186 return (BCM_E_INTERNAL); 4187 } 4188 4189 idx = modid * SOC_MAX_NUM_PORTS + port; 4190 if (idx >= _BCM_XGS3_TRUNK_MOD_PORT_MAP_IDX_COUNT(unit)) { 4191 return (BCM_E_PARAM); 4192 } 4193 4194 _trident_mod_port_to_tid_map[unit][idx] = (trunk_id < 0) ? 0 : (++trunk_id); 4195 4196 return (BCM_E_NONE); 4197 } 4198 4199 /* 4200 * Function: 4201 * _bcm_trident_trunk_mod_port_map_get 4202 * Purpose: 4203 * Read mapping (mod, port) to trunk id from software cache 4204 * for the SOURCE_TRUNK_MAP_TABLE. 4205 * Parameters: 4206 * unit - (IN) BCM device number. 4207 * modid - (IN) Member port module id. 4208 * port - (IN) Member port number. 4209 * trunk_id - (OUT) Trunk number or negative value for reset. 4210 * Returns: 4211 * BCM_X_XXX 4212 */ 4213 STATIC int 4214 _bcm_trident_trunk_mod_port_map_get(int unit, 4215 bcm_module_t modid, 4216 bcm_port_t port, 4217 bcm_trunk_t *trunk_id) 4218 { 4219 int idx; /* Map array index. */ 4220 bcm_module_t mymodid; /* Local module id. */ 4221 int isLocal; /* Local module id flag. */ 4222 int rv; /* Operation return status. */ 4223 int is_local_subport = FALSE; 4224 4225 if (NULL == _trident_mod_port_to_tid_map[unit]) { 4226 return (BCM_E_INIT); 4227 } 4228 4229 rv = _bcm_esw_modid_is_local(unit, modid, &isLocal); 4230 BCM_IF_ERROR_RETURN(rv); 4231 4232 #if defined(BCM_HGPROXY_COE_SUPPORT) 4233 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe)) { 4234 if(_bcm_xgs5_subport_coe_mod_port_local(unit, modid, port)) { 4235 is_local_subport = TRUE; 4236 } 4237 } 4238 #endif 4239 if (isLocal && !is_local_subport) { 4240 rv = bcm_esw_stk_my_modid_get(unit, &mymodid); 4241 BCM_IF_ERROR_RETURN(rv); 4242 if (mymodid != modid) { 4243 modid = mymodid; 4244 port += 32; 4245 } 4246 } 4247 4248 idx = modid * SOC_MAX_NUM_PORTS + port; 4249 if (idx >= _BCM_XGS3_TRUNK_MOD_PORT_MAP_IDX_COUNT(unit)) { 4250 return (BCM_E_PARAM); 4251 } 4252 4253 *trunk_id = _trident_mod_port_to_tid_map[unit][idx] - 1; 4254 4255 return (_trident_mod_port_to_tid_map[unit][idx]) ? BCM_E_NONE : BCM_E_NOT_FOUND; 4256 } 4257 4258 /* 4259 * Function: 4260 * _bcm_trident_trunk_set_port_property 4261 * Purpose: 4262 * Mark a mod/port pair as being in a particular trunk (or not) 4263 * A negative tid sets the mod/port back to non-trunk status. 4264 * Parameters: 4265 * unit - (IN) SOC unit number. 4266 * mod - (IN) Module ID. 4267 * port - (IN) Port number. 4268 * tid - (IN) Trunk group ID. 4269 * Returns: 4270 * BCM_E_xxx 4271 */ 4272 STATIC int 4273 _bcm_trident_trunk_set_port_property(int unit, 4274 bcm_module_t mod, 4275 bcm_port_t port, 4276 int tid) 4277 { 4278 int ptype_get, ptype_set, tid_get, tid_set; 4279 int idx; 4280 soc_mem_t mem; 4281 source_trunk_map_table_entry_t stm; 4282 egr_gpp_attributes_entry_t ega; 4283 int rv; 4284 soc_field_t tgid_f = TGIDf; 4285 4286 if (tid < 0) { 4287 ptype_set = 0; /* normal port */ 4288 tid_set = 0; 4289 } else { 4290 ptype_set = 1; /* trunk port */ 4291 tid_set = tid; 4292 } 4293 4294 BCM_IF_ERROR_RETURN 4295 (_bcm_esw_src_mod_port_table_index_get(unit, mod, port, &idx)); 4296 4297 mem = SOURCE_TRUNK_MAP_TABLEm; 4298 if (soc_mem_field_valid(unit, mem, SRC_TGIDf)) { 4299 tgid_f = SRC_TGIDf; 4300 } 4301 soc_mem_lock(unit, mem); 4302 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, &stm); 4303 if (BCM_SUCCESS(rv)) { 4304 ptype_get = soc_mem_field32_get(unit, mem, &stm, PORT_TYPEf); 4305 tid_get = soc_mem_field32_get(unit, mem, &stm, tgid_f); 4306 if ((ptype_get != ptype_set) || (tid_get != tid_set)) { 4307 soc_mem_field32_set(unit, mem, &stm, PORT_TYPEf, ptype_set); 4308 soc_mem_field32_set(unit, mem, &stm, tgid_f, tid_set); 4309 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, idx, &stm); 4310 } 4311 } 4312 soc_mem_unlock(unit, mem); 4313 4314 if(!SOC_IS_KATANA(unit)) { 4315 mem = EGR_GPP_ATTRIBUTESm; 4316 soc_mem_lock(unit, mem); 4317 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, &ega); 4318 if (BCM_SUCCESS(rv)) { 4319 ptype_get = soc_mem_field32_get(unit, mem, &ega, ISTRUNKf); 4320 tid_get = soc_mem_field32_get(unit, mem, &ega, TGIDf); 4321 if ((ptype_get != ptype_set) || (tid_get != tid_set)) { 4322 soc_mem_field32_set(unit, mem, &ega, ISTRUNKf, ptype_set); 4323 soc_mem_field32_set(unit, mem, &ega, TGIDf, tid_set); 4324 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, idx, &ega); 4325 } 4326 } 4327 soc_mem_unlock(unit, mem); 4328 } 4329 /* Update SW module, port to tid mapping. */ 4330 if (BCM_SUCCESS(rv)) { 4331 rv = _bcm_trident_trunk_mod_port_map_set(unit, mod, port, tid); 4332 } 4333 4334 return rv; 4335 } 4336 4337 /* 4338 * Function: 4339 * _bcm_trident_trunk_get_port_property 4340 * Purpose: 4341 * Get trunk group ID for a mod/port pair. 4342 * Parameters: 4343 * unit - (IN) SOC unit number. 4344 * mod - (IN) Module ID. 4345 * port - (IN) Port number. 4346 * tid - (OUT) Trunk group ID. 4347 * Returns: 4348 * BCM_E_xxx 4349 */ 4350 int 4351 _bcm_trident_trunk_get_port_property(int unit, 4352 bcm_module_t mod, 4353 bcm_port_t port, 4354 int *tid) 4355 { 4356 return _bcm_trident_trunk_mod_port_map_get(unit, mod, port, tid); 4357 } 4358 4359 /* 4360 * Function: 4361 * _bcm_trident_nuc_tpbm_get 4362 * Purpose: 4363 * Get non-unicast panel trunk members. 4364 * Parameters: 4365 * unit - (IN) SOC unit number. 4366 * num_ports - (IN) Number of ports in trunk group. 4367 * tm - (IN) Pointer to array of module IDs. 4368 * nuc_tpbm - (OUT) Bitmap of ports eligible for non-unicast. 4369 * Returns: 4370 * BCM_E_xxx 4371 */ 4372 STATIC 4373 int _bcm_trident_nuc_tpbm_get(int unit, 4374 int num_ports, 4375 bcm_module_t *tm, 4376 SHR_BITDCL *nuc_tpbm) 4377 { 4378 int rv = BCM_E_NONE; 4379 int i, mod = -1; 4380 uint32 mod_type; 4381 int all_equal = 1; 4382 4383 SHR_BITDCL *xgs12_tpbm = NULL; 4384 SHR_BITDCL *xgs3_tpbm = NULL; 4385 SHR_BITDCL *unknown_tpbm = NULL; 4386 4387 SHR_BITDCL xgs12_tpbm_result; 4388 SHR_BITDCL xgs3_tpbm_result; 4389 SHR_BITDCL unknown_tpbm_result; 4390 4391 xgs12_tpbm = sal_alloc(SHR_BITALLOCSIZE(num_ports), "xgs12_tpbm"); 4392 if (xgs12_tpbm == NULL) { 4393 return BCM_E_MEMORY; 4394 } 4395 sal_memset(xgs12_tpbm, 0, SHR_BITALLOCSIZE(num_ports)); 4396 4397 xgs3_tpbm = sal_alloc(SHR_BITALLOCSIZE(num_ports), "xgs3_tpbm"); 4398 if (xgs3_tpbm == NULL) { 4399 sal_free(xgs12_tpbm); 4400 return BCM_E_MEMORY; 4401 } 4402 sal_memset(xgs3_tpbm, 0, SHR_BITALLOCSIZE(num_ports)); 4403 4404 unknown_tpbm = sal_alloc(SHR_BITALLOCSIZE(num_ports), "unknown_tpbm"); 4405 if (unknown_tpbm == NULL) { 4406 sal_free(xgs12_tpbm); 4407 sal_free(xgs3_tpbm); 4408 return BCM_E_MEMORY; 4409 } 4410 sal_memset(unknown_tpbm, 0, SHR_BITALLOCSIZE(num_ports)); 4411 4412 SHR_BITSET(nuc_tpbm, 0); 4413 for (i = 0; i < num_ports; i++) { 4414 if (i == 0) { 4415 mod = tm[i]; 4416 } else if (mod != tm[i]) { 4417 all_equal = 0; 4418 } 4419 rv = _bcm_switch_module_type_get(unit, tm[i], &mod_type); 4420 if (BCM_FAILURE(rv)) { 4421 sal_free(xgs12_tpbm); 4422 sal_free(xgs3_tpbm); 4423 sal_free(unknown_tpbm); 4424 return rv; 4425 } 4426 switch(mod_type) { 4427 case BCM_SWITCH_MODULE_XGS1: 4428 /* passthru */ 4429 case BCM_SWITCH_MODULE_XGS2: 4430 SHR_BITSET(xgs12_tpbm, i); 4431 break; 4432 case BCM_SWITCH_MODULE_XGS3: 4433 SHR_BITSET(xgs3_tpbm, i); 4434 break; 4435 case BCM_SWITCH_MODULE_UNKNOWN: 4436 /* passthru */ 4437 default: 4438 SHR_BITSET(unknown_tpbm, i); 4439 break; 4440 } 4441 } 4442 4443 /* tpbm_result will be 0 if all bits in the range are 0 */ 4444 SHR_BITTEST_RANGE(xgs12_tpbm, 0, num_ports, xgs12_tpbm_result); 4445 SHR_BITTEST_RANGE(xgs3_tpbm, 0, num_ports, xgs3_tpbm_result); 4446 SHR_BITTEST_RANGE(unknown_tpbm, 0, num_ports, unknown_tpbm_result); 4447 4448 if (all_equal) { 4449 SHR_BITSET_RANGE(nuc_tpbm, 0, num_ports); 4450 } else if (xgs12_tpbm_result || unknown_tpbm_result) { 4451 SHR_BITSET(nuc_tpbm, 0); 4452 } else if (xgs3_tpbm_result) { 4453 SHR_BITCOPY_RANGE(nuc_tpbm, 0, xgs3_tpbm, 0, num_ports); 4454 } 4455 4456 sal_free(xgs12_tpbm); 4457 sal_free(xgs3_tpbm); 4458 sal_free(unknown_tpbm); 4459 4460 return rv; 4461 } 4462 4463 /* Macro to free memory and return code */ 4464 4465 #define _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(_r_) \ 4466 if (nuc_tpbm) { \ 4467 sal_free(nuc_tpbm); \ 4468 } \ 4469 if (ipmc_tpbm) { \ 4470 sal_free(ipmc_tpbm); \ 4471 } \ 4472 if (l2mc_tpbm) { \ 4473 sal_free(l2mc_tpbm); \ 4474 } \ 4475 if (bcast_tpbm) { \ 4476 sal_free(bcast_tpbm); \ 4477 } \ 4478 if (dlf_tpbm) { \ 4479 sal_free(dlf_tpbm); \ 4480 } \ 4481 if (ipmc_my_modid_bmap) { \ 4482 sal_free(ipmc_my_modid_bmap); \ 4483 } \ 4484 if (l2mc_my_modid_bmap) { \ 4485 sal_free(l2mc_my_modid_bmap); \ 4486 } \ 4487 if (bcast_my_modid_bmap) { \ 4488 sal_free(bcast_my_modid_bmap); \ 4489 } \ 4490 if (dlf_my_modid_bmap) { \ 4491 sal_free(dlf_my_modid_bmap); \ 4492 } \ 4493 if (hwmod) { \ 4494 sal_free(hwmod); \ 4495 } \ 4496 if (hwport) { \ 4497 sal_free(hwport); \ 4498 } \ 4499 if (egr_hwmod) { \ 4500 sal_free(egr_hwmod); \ 4501 } \ 4502 if (egr_hwport) { \ 4503 sal_free(egr_hwport); \ 4504 } \ 4505 if (egr_member_flags) { \ 4506 sal_free(egr_member_flags); \ 4507 } \ 4508 if (egr_scaling_factor) { \ 4509 sal_free(egr_scaling_factor); \ 4510 } \ 4511 if (egr_load_weight) { \ 4512 sal_free(egr_load_weight); \ 4513 } \ 4514 if (egr_qsize_weight) { \ 4515 sal_free(egr_qsize_weight); \ 4516 } \ 4517 if (uc_egr_hwmod) { \ 4518 sal_free(uc_egr_hwmod); \ 4519 } \ 4520 if (uc_egr_hwport) { \ 4521 sal_free(uc_egr_hwport); \ 4522 } \ 4523 if (uc_egr_scaling_factor) { \ 4524 sal_free(uc_egr_scaling_factor); \ 4525 } \ 4526 if (uc_egr_load_weight) { \ 4527 sal_free(uc_egr_load_weight); \ 4528 } \ 4529 if (uc_egr_qsize_weight) { \ 4530 sal_free(uc_egr_qsize_weight); \ 4531 } \ 4532 if (leaving_members) { \ 4533 sal_free(leaving_members); \ 4534 } \ 4535 if (staying_members) { \ 4536 sal_free(staying_members); \ 4537 } \ 4538 if (joining_members) { \ 4539 sal_free(joining_members); \ 4540 } \ 4541 if (ipmc_localport_array) { \ 4542 sal_free(ipmc_localport_array); \ 4543 } \ 4544 if (l2mc_localport_array) { \ 4545 sal_free(l2mc_localport_array); \ 4546 } \ 4547 if (bcast_localport_array) { \ 4548 sal_free(bcast_localport_array); \ 4549 } \ 4550 if (dlf_localport_array) { \ 4551 sal_free(dlf_localport_array); \ 4552 } \ 4553 return _r_; 4554 4555 /* 4556 * Function: 4557 * _bcm_trident_trunk_fp_set 4558 * Purpose: 4559 * Set front panel trunk members. 4560 * Parameters: 4561 * unit - (IN) SOC unit number. 4562 * tid - (IN) Trunk group ID. 4563 * add_info - (IN) Pointer to trunk add info structure. 4564 * t_info - (IN) Pointer to trunk info. 4565 * op - (IN) Type of operation: TRUNK_MEMBER_OP_SET, ADD or DELETE. 4566 * member - (IN) Member to add or delete. 4567 * Returns: 4568 * BCM_E_xxx 4569 */ 4570 STATIC int 4571 _bcm_trident_trunk_fp_modify(int unit, 4572 bcm_trunk_t tid, 4573 _esw_trunk_add_info_t *add_info, 4574 trunk_private_t *t_info, 4575 trunk_private_t *stored_info, 4576 int op, 4577 bcm_trunk_member_t *member) 4578 { 4579 int rv = BCM_E_NONE; 4580 SHR_BITDCL *nuc_tpbm = NULL; 4581 SHR_BITDCL *ipmc_tpbm = NULL; 4582 SHR_BITDCL *l2mc_tpbm = NULL; 4583 SHR_BITDCL *bcast_tpbm = NULL; 4584 SHR_BITDCL *dlf_tpbm = NULL; 4585 SHR_BITDCL *ipmc_my_modid_bmap = NULL; 4586 SHR_BITDCL *l2mc_my_modid_bmap = NULL; 4587 SHR_BITDCL *bcast_my_modid_bmap = NULL; 4588 SHR_BITDCL *dlf_my_modid_bmap = NULL; 4589 int *hwmod = NULL; 4590 int *hwport = NULL; 4591 int num_egr_ports = 0; 4592 int *egr_hwmod = NULL; 4593 int *egr_hwport = NULL; 4594 uint32 *egr_member_flags = NULL; 4595 int *egr_scaling_factor = NULL; 4596 int *egr_load_weight = NULL; 4597 int *egr_qsize_weight = NULL; 4598 int num_uc_egr_ports = 0; 4599 int *uc_egr_hwmod = NULL; 4600 int *uc_egr_hwport = NULL; 4601 int *uc_egr_scaling_factor = NULL; 4602 int *uc_egr_load_weight = NULL; 4603 int *uc_egr_qsize_weight = NULL; 4604 int negr_disable_port = 0; 4605 int num_uc_egr_disable_port = 0; 4606 pbmp_t new_trunk_pbmp; 4607 uint32 ipmc_member_count; 4608 uint32 l2mc_member_count; 4609 uint32 bcast_member_count; 4610 uint32 dlf_member_count; 4611 int mod, port, mod_out, port_out; 4612 bcm_gport_t gport; 4613 bcm_port_t loc_port = BCM_GPORT_INVALID; 4614 int i; 4615 trunk_bitmap_entry_t trunk_bitmap_entry; 4616 pbmp_t old_trunk_pbmp; 4617 int j, k, remove_trunk_port; 4618 int num_leaving_members = 0; 4619 bcm_gport_t *leaving_members = NULL; 4620 int match_leaving_members; 4621 int num_staying_members = 0; 4622 bcm_gport_t *staying_members = NULL; 4623 int match_staying_members; 4624 int num_joining_members = 0; 4625 bcm_gport_t *joining_members = NULL; 4626 int match_joining_members; 4627 bcm_trunk_chip_info_t chip_info; 4628 int is_local; 4629 int is_local_subport = 0; 4630 int *ipmc_localport_array = NULL; 4631 int *l2mc_localport_array = NULL; 4632 int *bcast_localport_array = NULL; 4633 int *dlf_localport_array = NULL; 4634 int ipmc_localport_count; 4635 int l2mc_localport_count; 4636 int bcast_localport_count; 4637 int dlf_localport_count; 4638 4639 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 4640 if (add_info->num_ports > chip_info.trunk_ports_max || 4641 add_info->num_ports < 1) { 4642 return BCM_E_PARAM; 4643 } 4644 4645 /* On Trident A0, the max number of trunk members for RTAG 1-6 is smaller 4646 * than for RTAG 7. 4647 */ 4648 if (soc_feature(unit, soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 4649 if (t_info->rtag >= 1 && t_info->rtag <= 6) { 4650 if (add_info->num_ports > _BCM_TD_FP_TRUNK_RTAG1_6_MAX_PORTCNT) { 4651 return BCM_E_PARAM; 4652 } 4653 } 4654 } 4655 4656 /* Audit unsupported flag combination */ 4657 for (i = 0; i < add_info->num_ports; i++) { 4658 if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_EGRESS_DISABLE) { 4659 if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_INGRESS_DISABLE) { 4660 return BCM_E_PARAM; 4661 } 4662 if (add_info->member_flags[i] & 4663 BCM_TRUNK_MEMBER_UNICAST_EGRESS_DISABLE) { 4664 return BCM_E_PARAM; 4665 } 4666 if (add_info->member_flags[i] & 4667 BCM_TRUNK_MEMBER_IPMC_EGRESS_DISABLE) { 4668 return BCM_E_PARAM; 4669 } 4670 if (add_info->member_flags[i] & 4671 BCM_TRUNK_MEMBER_L2MC_EGRESS_DISABLE) { 4672 return BCM_E_PARAM; 4673 } 4674 if (add_info->member_flags[i] & 4675 BCM_TRUNK_MEMBER_BCAST_EGRESS_DISABLE) { 4676 return BCM_E_PARAM; 4677 } 4678 if (add_info->member_flags[i] & 4679 BCM_TRUNK_MEMBER_DLF_EGRESS_DISABLE) { 4680 return BCM_E_PARAM; 4681 } 4682 } 4683 if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_IPMC_EGRESS_DISABLE) { 4684 if (add_info->ipmc_index != BCM_TRUNK_UNSPEC_INDEX) { 4685 return BCM_E_PARAM; 4686 } 4687 } 4688 if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_L2MC_EGRESS_DISABLE) { 4689 if (add_info->mc_index != BCM_TRUNK_UNSPEC_INDEX) { 4690 return BCM_E_PARAM; 4691 } 4692 } 4693 if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_BCAST_EGRESS_DISABLE) { 4694 if (add_info->dlf_index != BCM_TRUNK_UNSPEC_INDEX) { 4695 return BCM_E_PARAM; 4696 } 4697 } 4698 if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_DLF_EGRESS_DISABLE) { 4699 if (add_info->dlf_index != BCM_TRUNK_UNSPEC_INDEX) { 4700 return BCM_E_PARAM; 4701 } 4702 } 4703 } 4704 4705 if (add_info->dlf_index >= add_info->num_ports) { 4706 return BCM_E_PARAM; 4707 } 4708 4709 /* Derive a member bitmap of non-unicast eligible members */ 4710 nuc_tpbm = sal_alloc(SHR_BITALLOCSIZE(add_info->num_ports), "nuc_tpbm"); 4711 if (nuc_tpbm == NULL) { 4712 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 4713 } 4714 sal_memset(nuc_tpbm, 0, SHR_BITALLOCSIZE(add_info->num_ports)); 4715 if (add_info->dlf_index == -1) { 4716 rv = _bcm_trident_nuc_tpbm_get(unit, add_info->num_ports, 4717 add_info->tm, nuc_tpbm); 4718 if (BCM_FAILURE(rv)) { 4719 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 4720 } 4721 } else { 4722 SHR_BITSET(nuc_tpbm, add_info->dlf_index); 4723 } 4724 4725 /* Copy the non-unicast eligible member bitmap to IPMC, L2MC, broadcast, 4726 * and DLF eligible member bitmaps. 4727 */ 4728 ipmc_tpbm = sal_alloc(SHR_BITALLOCSIZE(add_info->num_ports), "ipmc_tpbm"); 4729 if (ipmc_tpbm == NULL) { 4730 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 4731 } 4732 sal_memcpy(ipmc_tpbm, nuc_tpbm, SHR_BITALLOCSIZE(add_info->num_ports)); 4733 4734 l2mc_tpbm = sal_alloc(SHR_BITALLOCSIZE(add_info->num_ports), "l2mc_tpbm"); 4735 if (l2mc_tpbm == NULL) { 4736 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 4737 } 4738 sal_memcpy(l2mc_tpbm, nuc_tpbm, SHR_BITALLOCSIZE(add_info->num_ports)); 4739 4740 bcast_tpbm = sal_alloc(SHR_BITALLOCSIZE(add_info->num_ports), "bcast_tpbm"); 4741 if (bcast_tpbm == NULL) { 4742 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 4743 } 4744 sal_memcpy(bcast_tpbm, nuc_tpbm, SHR_BITALLOCSIZE(add_info->num_ports)); 4745 4746 dlf_tpbm = sal_alloc(SHR_BITALLOCSIZE(add_info->num_ports), "dlf_tpbm"); 4747 if (dlf_tpbm == NULL) { 4748 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 4749 } 4750 sal_memcpy(dlf_tpbm, nuc_tpbm, SHR_BITALLOCSIZE(add_info->num_ports)); 4751 4752 /* Iterate through the trunk member list to get module ID and port 4753 * number of each member, a port bitmap of local members, and 4754 * port bitmaps of IPMC/L2MC/BCAST/DLF eligible local members. 4755 */ 4756 hwmod = sal_alloc(sizeof(int) * (add_info->num_ports), "hwmod"); 4757 if (hwmod == NULL) { 4758 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 4759 } 4760 sal_memset(hwmod, 0, sizeof(int) * (add_info->num_ports)); 4761 4762 hwport = sal_alloc(sizeof(int) * (add_info->num_ports), "hwport"); 4763 if (hwport == NULL) { 4764 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 4765 } 4766 sal_memset(hwport, 0, sizeof(int) * (add_info->num_ports)); 4767 4768 ipmc_my_modid_bmap = sal_alloc(SHR_BITALLOCSIZE(add_info->num_ports), 4769 "ipmc_my_modid_bmap"); 4770 if (ipmc_my_modid_bmap == NULL) { 4771 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 4772 } 4773 sal_memset(ipmc_my_modid_bmap, 0, SHR_BITALLOCSIZE(add_info->num_ports)); 4774 4775 l2mc_my_modid_bmap = sal_alloc(SHR_BITALLOCSIZE(add_info->num_ports), 4776 "l2mc_my_modid_bmap"); 4777 if (l2mc_my_modid_bmap == NULL) { 4778 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 4779 } 4780 sal_memset(l2mc_my_modid_bmap, 0, SHR_BITALLOCSIZE(add_info->num_ports)); 4781 4782 bcast_my_modid_bmap = sal_alloc(SHR_BITALLOCSIZE(add_info->num_ports), 4783 "bcast_my_modid_bmap"); 4784 if (bcast_my_modid_bmap == NULL) { 4785 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 4786 } 4787 sal_memset(bcast_my_modid_bmap, 0, SHR_BITALLOCSIZE(add_info->num_ports)); 4788 4789 dlf_my_modid_bmap = sal_alloc(SHR_BITALLOCSIZE(add_info->num_ports), 4790 "dlf_my_modid_bmap"); 4791 if (dlf_my_modid_bmap == NULL) { 4792 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 4793 } 4794 sal_memset(dlf_my_modid_bmap, 0, SHR_BITALLOCSIZE(add_info->num_ports)); 4795 ipmc_localport_array = sal_alloc(add_info->num_ports * sizeof(int), 4796 "ipmc_localport_array"); 4797 if (ipmc_localport_array == NULL) { 4798 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 4799 } 4800 sal_memset(ipmc_localport_array, 0, add_info->num_ports * sizeof(int)); 4801 l2mc_localport_array = sal_alloc(add_info->num_ports * sizeof(int), 4802 "l2mc_localport_array"); 4803 if (l2mc_localport_array == NULL) { 4804 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 4805 } 4806 sal_memset(l2mc_localport_array, 0, add_info->num_ports * sizeof(int)); 4807 bcast_localport_array = sal_alloc(add_info->num_ports * sizeof(int), 4808 "bcast_localport_array"); 4809 if (bcast_localport_array == NULL) { 4810 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 4811 } 4812 sal_memset(bcast_localport_array, 0, add_info->num_ports * sizeof(int)); 4813 dlf_localport_array = sal_alloc(add_info->num_ports * sizeof(int), 4814 "dlf_localport_array"); 4815 if (dlf_localport_array == NULL) { 4816 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 4817 } 4818 sal_memset(dlf_localport_array, 0, add_info->num_ports * sizeof(int)); 4819 4820 SOC_PBMP_CLEAR(new_trunk_pbmp); 4821 ipmc_member_count = 0; 4822 l2mc_member_count = 0; 4823 bcast_member_count = 0; 4824 dlf_member_count = 0; 4825 negr_disable_port = 0; 4826 num_uc_egr_disable_port = 0; 4827 ipmc_localport_count = 0; 4828 l2mc_localport_count = 0; 4829 bcast_localport_count = 0; 4830 dlf_localport_count = 0; 4831 4832 for (i = 0; i < add_info->num_ports; i++) { 4833 mod = add_info->tm[i]; 4834 port = add_info->tp[i]; 4835 /*In case of feature not supported on chip return E_PARAM*/ 4836 if (!soc_feature(unit, soc_feature_shared_trunk_member_table)) { 4837 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_PARAM); 4838 } 4839 rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET, 4840 mod, port, 4841 &mod_out, &port_out); 4842 if (BCM_FAILURE(rv)) { 4843 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 4844 } 4845 if (!SOC_MODID_ADDRESSABLE(unit, mod_out)) { 4846 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_BADID); 4847 } 4848 if (!SOC_PORT_ADDRESSABLE(unit, port_out)) { 4849 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_PORT); 4850 } 4851 hwmod[i] = mod_out; 4852 hwport[i] = port_out; 4853 4854 if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_EGRESS_DISABLE) { 4855 SHR_BITCLR(ipmc_tpbm, i); 4856 SHR_BITCLR(l2mc_tpbm, i); 4857 SHR_BITCLR(bcast_tpbm, i); 4858 SHR_BITCLR(dlf_tpbm, i); 4859 negr_disable_port++; 4860 } else { 4861 if (add_info->member_flags[i] & 4862 BCM_TRUNK_MEMBER_UNICAST_EGRESS_DISABLE) { 4863 num_uc_egr_disable_port++; 4864 } 4865 if (add_info->member_flags[i] & 4866 BCM_TRUNK_MEMBER_IPMC_EGRESS_DISABLE) { 4867 SHR_BITCLR(ipmc_tpbm, i); 4868 } 4869 if (add_info->member_flags[i] & 4870 BCM_TRUNK_MEMBER_L2MC_EGRESS_DISABLE) { 4871 SHR_BITCLR(l2mc_tpbm, i); 4872 } 4873 if (add_info->member_flags[i] & 4874 BCM_TRUNK_MEMBER_BCAST_EGRESS_DISABLE) { 4875 SHR_BITCLR(bcast_tpbm, i); 4876 } 4877 if (add_info->member_flags[i] & 4878 BCM_TRUNK_MEMBER_DLF_EGRESS_DISABLE) { 4879 SHR_BITCLR(dlf_tpbm, i); 4880 } 4881 } 4882 4883 BCM_GPORT_MODPORT_SET(gport, mod_out, port_out); 4884 loc_port = BCM_GPORT_INVALID; 4885 if (BCM_SUCCESS(bcm_esw_port_local_get(unit, gport, &loc_port))) { 4886 4887 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe)) { 4888 #if defined(BCM_HGPROXY_COE_SUPPORT) 4889 if(_bcm_xgs5_subport_coe_mod_port_local(unit, mod_out, 4890 port_out)) { 4891 4892 is_local_subport = 1; 4893 } 4894 #endif 4895 } else 4896 4897 if (soc_feature(unit, soc_feature_linkphy_coe) || 4898 soc_feature(unit, soc_feature_subtag_coe)) { 4899 #if defined(BCM_KATANA2_SUPPORT) 4900 BCM_IF_ERROR_RETURN(_bcm_kt2_modport_is_local_coe_subport(unit, 4901 mod_out, port_out, &is_local_subport)); 4902 #endif 4903 } 4904 if (!is_local_subport) { 4905 if (!(IS_E_PORT(unit, loc_port) || IS_HG_PORT(unit, loc_port)) || 4906 /* Cascaded physical ports are not considered as front-panel port */ 4907 (soc_feature(unit, soc_feature_linkphy_coe) && 4908 IS_LP_PORT(unit, loc_port)) || 4909 (soc_feature(unit, soc_feature_subtag_coe) && 4910 IS_SUBTAG_PORT(unit, loc_port)) || 4911 (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 4912 IS_SUBTAG_PORT (unit, loc_port))) { 4913 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_PARAM); 4914 } 4915 } 4916 SOC_PBMP_PORT_ADD(new_trunk_pbmp, loc_port); 4917 if (SHR_BITGET(ipmc_tpbm, i)) { 4918 ipmc_localport_array[ipmc_localport_count++] = loc_port; 4919 SHR_BITSET(ipmc_my_modid_bmap, ipmc_member_count); 4920 } 4921 if (SHR_BITGET(l2mc_tpbm, i)) { 4922 l2mc_localport_array[l2mc_localport_count++] = loc_port; 4923 SHR_BITSET(l2mc_my_modid_bmap, l2mc_member_count); 4924 } 4925 if (SHR_BITGET(bcast_tpbm, i)) { 4926 bcast_localport_array[bcast_localport_count++] = loc_port; 4927 SHR_BITSET(bcast_my_modid_bmap, bcast_member_count); 4928 } 4929 if (SHR_BITGET(dlf_tpbm, i)) { 4930 dlf_localport_array[dlf_localport_count++] = loc_port; 4931 SHR_BITSET(dlf_my_modid_bmap, dlf_member_count); 4932 } 4933 } 4934 4935 if (SHR_BITGET(ipmc_tpbm, i)) { 4936 /* Eligible for IPMC forwarding */ 4937 ipmc_member_count++; 4938 } 4939 if (SHR_BITGET(l2mc_tpbm, i)) { 4940 /* Eligible for L2MC forwarding */ 4941 l2mc_member_count++; 4942 } 4943 if (SHR_BITGET(bcast_tpbm, i)) { 4944 /* Eligible for broadcast forwarding */ 4945 bcast_member_count++; 4946 } 4947 if (SHR_BITGET(dlf_tpbm, i)) { 4948 /* Eligible for DLF forwarding */ 4949 dlf_member_count++; 4950 } 4951 } 4952 4953 /* Figure out which trunk ports are eligible for egress and 4954 * unicast egress 4955 */ 4956 num_egr_ports = add_info->num_ports - negr_disable_port; 4957 if (num_egr_ports > 0) { 4958 egr_hwmod = sal_alloc(sizeof(bcm_module_t) * num_egr_ports, 4959 "egr_hwmod"); 4960 if (egr_hwmod == NULL) { 4961 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 4962 } 4963 egr_hwport = sal_alloc(sizeof(bcm_port_t) * num_egr_ports, 4964 "egr_hwport"); 4965 if (egr_hwport == NULL) { 4966 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 4967 } 4968 egr_member_flags = sal_alloc(sizeof(uint32) * num_egr_ports, 4969 "egr_member_flags"); 4970 if (egr_member_flags == NULL) { 4971 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 4972 } 4973 egr_scaling_factor = sal_alloc(sizeof(int) * num_egr_ports, 4974 "egr_scaling_factor"); 4975 if (egr_scaling_factor == NULL) { 4976 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 4977 } 4978 egr_load_weight = sal_alloc(sizeof(int) * num_egr_ports, 4979 "egr_load_weight"); 4980 if (egr_load_weight == NULL) { 4981 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 4982 } 4983 egr_qsize_weight = sal_alloc(sizeof(int) * num_egr_ports, 4984 "egr_qsize_weight"); 4985 if (egr_qsize_weight == NULL) { 4986 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 4987 } 4988 for (i = 0, j = 0; i < add_info->num_ports; i++) { 4989 if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_EGRESS_DISABLE) { 4990 continue; 4991 } 4992 egr_hwmod[j] = hwmod[i]; 4993 egr_hwport[j] = hwport[i]; 4994 egr_member_flags[j] = add_info->member_flags[i]; 4995 egr_scaling_factor[j] = add_info->dynamic_scaling_factor[i]; 4996 egr_load_weight[j] = add_info->dynamic_load_weight[i]; 4997 egr_qsize_weight[j] = add_info->dynamic_queue_size_weight[i]; 4998 j++; 4999 } 5000 5001 num_uc_egr_ports = num_egr_ports - num_uc_egr_disable_port; 5002 if (num_uc_egr_ports > 0 ) { 5003 uc_egr_hwmod = sal_alloc(sizeof(bcm_module_t) * num_uc_egr_ports, 5004 "uc_egr_hwmod"); 5005 if (uc_egr_hwmod == NULL) { 5006 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 5007 } 5008 uc_egr_hwport = sal_alloc(sizeof(bcm_port_t) * num_uc_egr_ports, 5009 "uc_egr_hwport"); 5010 if (uc_egr_hwport == NULL) { 5011 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 5012 } 5013 uc_egr_scaling_factor = sal_alloc(sizeof(int) * num_uc_egr_ports, 5014 "uc_egr_scaling_factor"); 5015 if (uc_egr_scaling_factor == NULL) { 5016 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 5017 } 5018 uc_egr_load_weight = sal_alloc(sizeof(int) * num_uc_egr_ports, 5019 "uc_egr_load_weight"); 5020 if (uc_egr_load_weight == NULL) { 5021 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 5022 } 5023 uc_egr_qsize_weight = sal_alloc(sizeof(int) * num_uc_egr_ports, 5024 "uc_egr_qsize_weight"); 5025 if (uc_egr_qsize_weight == NULL) { 5026 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 5027 } 5028 for (i = 0, k = 0; i < j; i++) { 5029 if (egr_member_flags[i] & 5030 BCM_TRUNK_MEMBER_UNICAST_EGRESS_DISABLE) { 5031 continue; 5032 } 5033 uc_egr_hwmod[k] = egr_hwmod[i]; 5034 uc_egr_hwport[k] = egr_hwport[i]; 5035 uc_egr_scaling_factor[k] = egr_scaling_factor[i]; 5036 uc_egr_load_weight[k] = egr_load_weight[i]; 5037 uc_egr_qsize_weight[k] = egr_qsize_weight[i]; 5038 k++; 5039 } 5040 } 5041 } else { 5042 /* Time to use entry 0 reserved for this purpose. 5043 * Set mod and port to inavlid values in entry */ 5044 if (bcm_trident_trunk_mbr_zero_rsvd[unit] == TRUE) { 5045 trunk_member_entry_t trunk_member_entry; 5046 sal_memset(&trunk_member_entry, 0, sizeof(trunk_member_entry_t)); 5047 soc_TRUNK_MEMBERm_field32_set(unit,&trunk_member_entry, 5048 MODULE_IDf,0xff); 5049 soc_TRUNK_MEMBERm_field32_set(unit,&trunk_member_entry, 5050 PORT_NUMf, 0x7f); 5051 SOC_IF_ERROR_RETURN 5052 (WRITE_TRUNK_MEMBERm(unit, MEM_BLOCK_ALL, 5053 0,&trunk_member_entry)); 5054 } 5055 } 5056 5057 /* Configure static load balancing */ 5058 if (t_info->in_use) { 5059 rv = _bcm_trident_lag_slb_free_resource(unit, tid); 5060 if (BCM_FAILURE(rv)) { 5061 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5062 } 5063 } 5064 rv = _bcm_trident_lag_slb_set(unit, tid, num_uc_egr_ports, 5065 uc_egr_hwmod, uc_egr_hwport, t_info); 5066 if (BCM_FAILURE(rv)) { 5067 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5068 } 5069 5070 #ifdef BCM_TRIUMPH3_SUPPORT 5071 /* Configure dynamic load balancing */ 5072 if (soc_feature(unit, soc_feature_lag_dlb) && 5073 !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 5074 if (t_info->in_use) { 5075 rv = bcm_tr3_lag_dlb_free_resource(unit, tid); 5076 if (BCM_FAILURE(rv)) { 5077 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5078 } 5079 } 5080 rv = bcm_tr3_lag_dlb_set(unit, tid, add_info, num_uc_egr_ports, 5081 uc_egr_hwmod, uc_egr_hwport, uc_egr_scaling_factor, 5082 uc_egr_load_weight); 5083 if (BCM_FAILURE(rv)) { 5084 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5085 } 5086 } 5087 #endif /* BCM_TRIUMPH3_SUPPORT */ 5088 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 5089 /* Configure dynamic load balancing */ 5090 if (soc_feature(unit, soc_feature_lag_dlb) && 5091 soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 5092 if (t_info->in_use) { 5093 rv = bcm_th2_hgt_lag_dlb_free_resource(unit, tid, 0); 5094 if (BCM_FAILURE(rv)) { 5095 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5096 } 5097 } 5098 rv = bcm_th2_hgt_lag_dlb_set(unit, tid, 0, add_info, num_uc_egr_ports, 5099 uc_egr_hwmod, uc_egr_hwport, uc_egr_scaling_factor, 5100 uc_egr_load_weight, uc_egr_qsize_weight); 5101 if (BCM_FAILURE(rv)) { 5102 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5103 } 5104 } 5105 #endif /* BCM_TOMAHAWK2_SUPPORT */ 5106 #ifdef BCM_TRIDENT2_SUPPORT 5107 /* Configure resilient hashing */ 5108 if (soc_feature(unit, soc_feature_lag_resilient_hash)) { 5109 bcm_module_t del_mod; 5110 bcm_port_t del_port; 5111 5112 if (op == TRUNK_MEMBER_OP_SET) { 5113 if ((stored_info->in_use) && 5114 (add_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) && 5115 (stored_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) && 5116 (add_info->dynamic_size != 0) && 5117 (add_info->dynamic_size == stored_info->dynamic_size)) { 5118 rv = bcm_td2_lag_rh_replace(unit, tid, add_info, 5119 num_uc_egr_ports, uc_egr_hwmod, uc_egr_hwport, 5120 MEMBER_INFO(unit, tid).num_ports, 5121 MEMBER_INFO(unit, tid).modport, 5122 MEMBER_INFO(unit, tid).member_flags); 5123 if (BCM_FAILURE(rv)) { 5124 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5125 } 5126 } else { 5127 if (t_info->in_use) { 5128 rv = bcm_td2_lag_rh_free_resource(unit, tid); 5129 if (BCM_FAILURE(rv)) { 5130 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5131 } 5132 } 5133 if (add_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) { 5134 rv = bcm_td2_lag_rh_set(unit, tid, add_info, 5135 num_uc_egr_ports, uc_egr_hwmod, uc_egr_hwport); 5136 if (BCM_FAILURE(rv)) { 5137 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5138 } 5139 } 5140 } 5141 } else if (op == TRUNK_MEMBER_OP_ADD) { 5142 if (add_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) { 5143 /* Add the new member if it's eligible for resilient hashing */ 5144 if (!(member->flags & BCM_TRUNK_MEMBER_EGRESS_DISABLE) && 5145 !(member->flags & BCM_TRUNK_MEMBER_UNICAST_EGRESS_DISABLE)) { 5146 rv = bcm_td2_lag_rh_add(unit, tid, add_info, 5147 num_uc_egr_ports, uc_egr_hwmod, uc_egr_hwport, 5148 member); 5149 if (BCM_FAILURE(rv)) { 5150 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5151 } 5152 } 5153 } 5154 } else if (op == TRUNK_MEMBER_OP_DELETE) { 5155 if (add_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) { 5156 for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) { 5157 mod = MEMBER_INFO(unit, tid).modport[i] >> 8; 5158 port = MEMBER_INFO(unit, tid).modport[i] & 0xff; 5159 rv = _bcm_esw_trunk_gport_array_resolve(unit, FALSE, 1, 5160 &member->gport, &del_port, &del_mod); 5161 if (BCM_FAILURE(rv)) { 5162 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5163 } 5164 if (mod == del_mod && port == del_port) { 5165 break; 5166 } 5167 } 5168 if (i == MEMBER_INFO(unit, tid).num_ports) { 5169 /* The member to be deleted is not found. */ 5170 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_NOT_FOUND); 5171 } 5172 /* Delete the member if it was resilient hashing eligible */ 5173 if (!(MEMBER_INFO(unit, tid).member_flags[i] & 5174 BCM_TRUNK_MEMBER_EGRESS_DISABLE) && 5175 !(MEMBER_INFO(unit, tid).member_flags[i] & 5176 BCM_TRUNK_MEMBER_UNICAST_EGRESS_DISABLE)) { 5177 rv = bcm_td2_lag_rh_delete(unit, tid, add_info, 5178 num_uc_egr_ports, uc_egr_hwmod, uc_egr_hwport, 5179 member); 5180 if (BCM_FAILURE(rv)) { 5181 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5182 } 5183 } 5184 } 5185 } else { 5186 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_PARAM); 5187 } 5188 } 5189 #endif /* BCM_TRIDENT2_SUPPORT */ 5190 5191 /* Update TRUNK_BITMAP table */ 5192 rv = READ_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, tid, &trunk_bitmap_entry); 5193 if (BCM_FAILURE(rv)) { 5194 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5195 } 5196 SOC_PBMP_CLEAR(old_trunk_pbmp); 5197 soc_mem_pbmp_field_get(unit, TRUNK_BITMAPm, &trunk_bitmap_entry, 5198 TRUNK_BITMAPf, &old_trunk_pbmp); 5199 soc_mem_pbmp_field_set(unit, TRUNK_BITMAPm, &trunk_bitmap_entry, 5200 TRUNK_BITMAPf, &new_trunk_pbmp); 5201 rv = WRITE_TRUNK_BITMAPm(unit, MEM_BLOCK_ALL, tid, &trunk_bitmap_entry); 5202 if (BCM_FAILURE(rv)) { 5203 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5204 } 5205 5206 /* Update source trunk map configuration */ 5207 for (i = 0; i < add_info->num_ports; i++) { 5208 mod = hwmod[i%add_info->num_ports]; 5209 port = hwport[i%add_info->num_ports]; 5210 5211 if (add_info->member_flags[i] & BCM_TRUNK_MEMBER_INGRESS_DISABLE) { 5212 rv = _bcm_trident_trunk_set_port_property(unit, mod, port, -1); 5213 } else { 5214 rv = _bcm_trident_trunk_set_port_property(unit, mod, port, tid); 5215 } 5216 if (BCM_FAILURE(rv)) { 5217 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5218 } 5219 } 5220 5221 /* Update the trunk block mask */ 5222 if (SOC_PBMP_NOT_NULL(new_trunk_pbmp) || 5223 SOC_PBMP_NOT_NULL(old_trunk_pbmp)) { 5224 rv = _bcm_trident_trunk_block_mask(unit, 5225 TRUNK_BLOCK_MASK_TYPE_IPMC, 5226 old_trunk_pbmp, 5227 new_trunk_pbmp, 5228 ipmc_localport_array, 5229 ipmc_localport_count, 5230 ipmc_my_modid_bmap, 5231 ipmc_member_count, 5232 add_info->flags); 5233 if (BCM_FAILURE(rv)) { 5234 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5235 } 5236 rv = _bcm_trident_trunk_block_mask(unit, 5237 TRUNK_BLOCK_MASK_TYPE_L2MC, 5238 old_trunk_pbmp, 5239 new_trunk_pbmp, 5240 l2mc_localport_array, 5241 l2mc_localport_count, 5242 l2mc_my_modid_bmap, 5243 l2mc_member_count, 5244 add_info->flags); 5245 if (BCM_FAILURE(rv)) { 5246 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5247 } 5248 rv = _bcm_trident_trunk_block_mask(unit, 5249 TRUNK_BLOCK_MASK_TYPE_BCAST, 5250 old_trunk_pbmp, 5251 new_trunk_pbmp, 5252 bcast_localport_array, 5253 bcast_localport_count, 5254 bcast_my_modid_bmap, 5255 bcast_member_count, 5256 add_info->flags); 5257 if (BCM_FAILURE(rv)) { 5258 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5259 } 5260 rv = _bcm_trident_trunk_block_mask(unit, 5261 TRUNK_BLOCK_MASK_TYPE_DLF, 5262 old_trunk_pbmp, 5263 new_trunk_pbmp, 5264 dlf_localport_array, 5265 dlf_localport_count, 5266 dlf_my_modid_bmap, 5267 dlf_member_count, 5268 add_info->flags); 5269 if (BCM_FAILURE(rv)) { 5270 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5271 } 5272 5273 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3) 5274 if (soc_feature(unit, soc_feature_axp)) { 5275 rv = _bcm_tr3_wlan_trunk_block_mask_update(unit); 5276 if (BCM_FAILURE(rv)) { 5277 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5278 } 5279 } 5280 #endif /* BCM_TRIUMPH3_SUPPORT && defined(INCLUDE_L3) */ 5281 } 5282 5283 /* Harware trunk failover */ 5284 if (soc_feature(unit, soc_feature_port_lag_failover)) { 5285 rv = _bcm_trident_trunk_failover_set(unit, tid, FALSE, add_info); 5286 if (BCM_FAILURE(rv)) { 5287 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5288 } 5289 } 5290 5291 /* Software trunk failover */ 5292 rv = _bcm_trident_trunk_swfailover_fp_set(unit, 5293 tid, 5294 t_info->rtag, 5295 num_egr_ports, 5296 egr_hwmod, 5297 egr_hwport, 5298 egr_member_flags, 5299 add_info->flags); 5300 if (BCM_FAILURE(rv)) { 5301 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5302 } 5303 5304 /* Figure out which members are leaving, staying or joining 5305 * the trunk group 5306 */ 5307 if (t_info->in_use) { 5308 if (MEMBER_INFO(unit, tid).num_ports > 0) { 5309 leaving_members = sal_alloc(sizeof(bcm_gport_t) * 5310 MEMBER_INFO(unit, tid).num_ports, "leaving members"); 5311 if (leaving_members == NULL) { 5312 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 5313 } 5314 sal_memset(leaving_members, 0, 5315 sizeof(bcm_gport_t) * MEMBER_INFO(unit, tid).num_ports); 5316 5317 staying_members = sal_alloc(sizeof(bcm_gport_t) * 5318 MEMBER_INFO(unit, tid).num_ports, "staying members"); 5319 if (staying_members == NULL) { 5320 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 5321 } 5322 sal_memset(staying_members, 0, 5323 sizeof(bcm_gport_t) * MEMBER_INFO(unit, tid).num_ports); 5324 5325 for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) { 5326 mod = MEMBER_INFO(unit, tid).modport[i] >> 8; 5327 port = MEMBER_INFO(unit, tid).modport[i] & 0xff; 5328 BCM_GPORT_MODPORT_SET(gport, mod, port); 5329 5330 /* Invalidate port only if it is not a part from new trunk group */ 5331 remove_trunk_port = TRUE; 5332 for (j = 0; j < add_info->num_ports; j++) { 5333 if (mod == add_info->tm[j] && port == add_info->tp[j]) { 5334 remove_trunk_port = FALSE; 5335 } 5336 } 5337 if (remove_trunk_port) { 5338 /* Add port to array containing members leaving the trunk 5339 * group if it is different from previous leaving members 5340 */ 5341 match_leaving_members = FALSE; 5342 for (k = 0; k < num_leaving_members; k++) { 5343 if (gport == leaving_members[k]) { 5344 match_leaving_members = TRUE; 5345 break; 5346 } 5347 } 5348 if (!match_leaving_members) { 5349 leaving_members[num_leaving_members++] = gport; 5350 } 5351 5352 rv = _bcm_trident_trunk_set_port_property(unit, mod, port, -1); 5353 if (BCM_FAILURE(rv)) { 5354 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5355 } 5356 if (soc_feature(unit, soc_feature_port_lag_failover)) { 5357 is_local = is_local_subport = 0; 5358 /* If deleted port is local, clear HW failover info */ 5359 rv = _bcm_esw_modid_is_local(unit, mod, &is_local); 5360 if (BCM_FAILURE(rv)) { 5361 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5362 } 5363 #if defined(BCM_KATANA2_SUPPORT) 5364 if (soc_feature(unit, soc_feature_linkphy_coe) || 5365 soc_feature(unit, soc_feature_subtag_coe)) { 5366 rv = _bcm_kt2_modport_is_local_coe_subport(unit, 5367 mod, port, &is_local_subport); 5368 if (BCM_FAILURE(rv)) { 5369 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5370 } 5371 } 5372 #endif 5373 if (!is_local && !is_local_subport) { 5374 continue; 5375 } 5376 5377 BCM_GPORT_MODPORT_SET(gport, mod, port); 5378 rv = bcm_esw_port_local_get(unit, gport, &loc_port); 5379 if (BCM_FAILURE(rv)) { 5380 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5381 } 5382 if (IS_HG_PORT(unit, loc_port)) { 5383 continue; 5384 } 5385 /* skip Cascaded Physical Ports*/ 5386 if ((soc_feature(unit, soc_feature_linkphy_coe) && 5387 IS_LP_PORT(unit, loc_port)) || 5388 (soc_feature(unit, soc_feature_subtag_coe) && 5389 IS_SUBTAG_PORT(unit, loc_port)) || 5390 (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 5391 IS_SUBTAG_PORT (unit, loc_port))) { 5392 continue; 5393 } 5394 #if defined(BCM_HELIX5_SUPPORT) 5395 /* Skip q-ports in HX5 since trunk hardware failover is 5396 * not supported for PM4x10Q. 5397 */ 5398 if (IS_QSGMII_PORT(unit, loc_port)) { 5399 continue; 5400 } 5401 #endif /* BCM_HELIX5_SUPPORT */ 5402 rv = _bcm_trident_trunk_hwfailover_set(unit, tid, 5403 FALSE, port, mod, add_info->psc, 5404 0, 0, NULL, NULL); 5405 if (BCM_FAILURE(rv)) { 5406 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5407 } 5408 } 5409 } else { 5410 /* Add port to array containing members staying in the trunk 5411 * group if it is different from previous staying members 5412 */ 5413 match_staying_members = FALSE; 5414 for (k = 0; k < num_staying_members; k++) { 5415 if (gport == staying_members[k]) { 5416 match_staying_members = TRUE; 5417 break; 5418 } 5419 } 5420 if (!match_staying_members) { 5421 staying_members[num_staying_members++] = gport; 5422 } 5423 5424 } 5425 } 5426 } 5427 } 5428 5429 joining_members = sal_alloc(sizeof(bcm_gport_t) * add_info->num_ports, 5430 "joining members"); 5431 if (joining_members == NULL) { 5432 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 5433 } 5434 sal_memset(joining_members, 0, sizeof(bcm_gport_t) * add_info->num_ports); 5435 for (i = 0; i < add_info->num_ports; i++) { 5436 BCM_GPORT_MODPORT_SET(gport, hwmod[i], hwport[i]); 5437 match_staying_members = FALSE; 5438 for (j = 0; j < num_staying_members; j++) { 5439 if (gport == staying_members[j]) { 5440 match_staying_members = TRUE; 5441 break; 5442 } 5443 } 5444 if (!match_staying_members) { 5445 match_joining_members = FALSE; 5446 for (j = 0; j < num_joining_members; j++) { 5447 if (gport == joining_members[j]) { 5448 match_joining_members = TRUE; 5449 break; 5450 } 5451 } 5452 if (!match_joining_members) { 5453 joining_members[num_joining_members++] = gport; 5454 } 5455 } 5456 } 5457 5458 /* Migrate trunk properties from old members to new members */ 5459 rv = _bcm_xgs3_trunk_property_migrate(unit, 5460 num_leaving_members, leaving_members, 5461 num_staying_members, staying_members, 5462 num_joining_members, joining_members); 5463 if (BCM_FAILURE(rv)) { 5464 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5465 } 5466 5467 /* Save new trunk member info */ 5468 if (MEMBER_INFO(unit, tid).modport) { 5469 sal_free(MEMBER_INFO(unit, tid).modport); 5470 MEMBER_INFO(unit, tid).modport = NULL; 5471 } 5472 if (MEMBER_INFO(unit, tid).member_flags) { 5473 sal_free(MEMBER_INFO(unit, tid).member_flags); 5474 MEMBER_INFO(unit, tid).member_flags = NULL; 5475 } 5476 5477 MEMBER_INFO(unit, tid).modport = sal_alloc( 5478 sizeof(uint16) * add_info->num_ports, "member info modport"); 5479 if (NULL == MEMBER_INFO(unit, tid).modport) { 5480 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 5481 } 5482 5483 MEMBER_INFO(unit, tid).member_flags = sal_alloc( 5484 sizeof(uint32) * add_info->num_ports, "member info flags"); 5485 if (NULL == MEMBER_INFO(unit, tid).member_flags) { 5486 sal_free(MEMBER_INFO(unit, tid).modport); 5487 MEMBER_INFO(unit, tid).modport = NULL; 5488 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(BCM_E_MEMORY); 5489 } 5490 5491 for (i = 0; i < add_info->num_ports; i++) { 5492 MEMBER_INFO(unit, tid).modport[i] = ((hwmod[i] & 0xff) << 8) | 5493 (hwport[i] & 0xff); 5494 MEMBER_INFO(unit, tid).member_flags[i] = add_info->member_flags[i]; 5495 } 5496 MEMBER_INFO(unit, tid).num_ports = add_info->num_ports; 5497 5498 /* Call Trill module to clear states for local leaving members, joining members */ 5499 #ifdef INCLUDE_L3 5500 if (soc_feature(unit, soc_feature_trill) 5501 || soc_feature(unit, soc_feature_mpls) 5502 || soc_feature(unit, soc_feature_vxlan) 5503 || soc_feature(unit, soc_feature_l2gre)) { 5504 bcm_port_t local_member; 5505 bcm_port_t local_member_arr[SOC_MAX_NUM_PORTS]; 5506 int num_local_members; 5507 5508 num_local_members = 0; 5509 for (i = 0; i < num_leaving_members; i++) { 5510 if (BCM_SUCCESS(bcm_esw_port_local_get(unit, leaving_members[i], 5511 &local_member))) { 5512 local_member_arr[num_local_members++] = local_member; 5513 } 5514 } 5515 5516 /* Support remote trunk members */ 5517 if (num_leaving_members > 0) { 5518 #ifdef BCM_TRIDENT2_SUPPORT 5519 if (soc_feature(unit, soc_feature_vxlan)) { 5520 rv = _bcm_esw_vxlan_trunk_member_delete(unit, tid, 5521 num_leaving_members, leaving_members); 5522 if (BCM_FAILURE(rv)) { 5523 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5524 } 5525 } 5526 #endif 5527 5528 #ifdef BCM_TRIUMPH3_SUPPORT 5529 if (soc_feature(unit, soc_feature_l2gre)) { 5530 rv = _bcm_esw_l2gre_trunk_member_delete(unit, tid, 5531 num_leaving_members, leaving_members); 5532 if (BCM_FAILURE(rv)) { 5533 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5534 } 5535 } 5536 #endif 5537 } 5538 5539 if (num_local_members > 0) { 5540 if (soc_feature(unit, soc_feature_trill)) { 5541 rv = _bcm_esw_trill_trunk_member_delete(unit, tid, 5542 num_local_members, local_member_arr); 5543 if (BCM_FAILURE(rv)) { 5544 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5545 } 5546 } 5547 #ifdef BCM_TRIUMPH_SUPPORT 5548 if (soc_feature(unit, soc_feature_mpls)) { 5549 rv = _bcm_esw_mpls_trunk_member_delete(unit, tid, 5550 num_local_members, local_member_arr); 5551 if (BCM_FAILURE(rv)) { 5552 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5553 } 5554 } 5555 #endif 5556 } 5557 5558 num_local_members = 0; 5559 for (i = 0; i < num_joining_members; i++) { 5560 if (BCM_SUCCESS(bcm_esw_port_local_get(unit, joining_members[i], 5561 &local_member))) { 5562 local_member_arr[num_local_members++] = local_member; 5563 } 5564 } 5565 5566 /* Support remote trunk members */ 5567 if (num_joining_members > 0) { 5568 #ifdef BCM_TRIDENT2_SUPPORT 5569 if (soc_feature(unit, soc_feature_vxlan)) { 5570 rv = _bcm_esw_vxlan_trunk_member_add(unit, tid, 5571 num_joining_members, joining_members); 5572 if (BCM_FAILURE(rv)) { 5573 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5574 } 5575 } 5576 #endif 5577 5578 #ifdef BCM_TRIUMPH3_SUPPORT 5579 if (soc_feature(unit, soc_feature_l2gre)) { 5580 rv = _bcm_esw_l2gre_trunk_member_add(unit, tid, 5581 num_joining_members, joining_members); 5582 if (BCM_FAILURE(rv)) { 5583 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5584 } 5585 } 5586 #endif 5587 } 5588 5589 if (num_local_members > 0) { 5590 if (soc_feature(unit, soc_feature_trill)) { 5591 rv = _bcm_esw_trill_trunk_member_add(unit, tid, 5592 num_local_members, local_member_arr); 5593 if (BCM_FAILURE(rv)) { 5594 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5595 } 5596 } 5597 #ifdef BCM_TRIUMPH_SUPPORT 5598 if (soc_feature(unit, soc_feature_mpls)) { 5599 rv = _bcm_esw_mpls_trunk_member_add(unit, tid, 5600 num_local_members, local_member_arr); 5601 if (BCM_FAILURE(rv)) { 5602 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5603 } 5604 } 5605 #endif 5606 } 5607 } 5608 #endif /* INCLUDE_L3 */ 5609 5610 _BCM_TRIDENT_TRUNK_FP_SET_FREE_MEM_RETURN(rv); 5611 } 5612 5613 /* 5614 * Function: 5615 * bcm_trident_trunk_fp_destroy 5616 * Purpose: 5617 * Remove front-panel trunk group. 5618 * Parameters: 5619 * unit - (IN) SOC unit number. 5620 * tid - (IN) Trunk group ID. 5621 * t_info - (IN) Pointer to trunk info. 5622 * Returns: 5623 * BCM_E_xxx 5624 */ 5625 STATIC int 5626 _bcm_trident_trunk_fp_destroy(int unit, 5627 bcm_trunk_t tid, 5628 trunk_private_t *t_info) 5629 { 5630 trunk_group_entry_t tg_entry; 5631 trunk_bitmap_entry_t trunk_bitmap_entry; 5632 trunk_member_entry_t trunk_member_entry; 5633 pbmp_t old_trunk_pbmp, new_trunk_pbmp; 5634 int old_base_ptr, old_tg_size, old_rtag; 5635 int old_num_entries; 5636 bcm_module_t mod; 5637 bcm_port_t port; 5638 bcm_gport_t gport; 5639 int i, j; 5640 int num_leaving_members = 0; 5641 bcm_gport_t *leaving_members = NULL; 5642 int match_leaving_members; 5643 int rv = BCM_E_NONE; 5644 5645 /* Clear dynamic load balancing */ 5646 #ifdef BCM_TRIUMPH3_SUPPORT 5647 if (soc_feature(unit, soc_feature_lag_dlb)) { 5648 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 5649 if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 5650 BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_free_resource(unit, tid, 0)); 5651 } else 5652 #endif /* BCM_TOMAHAWK2_SUPPORT */ 5653 { 5654 BCM_IF_ERROR_RETURN(bcm_tr3_lag_dlb_free_resource(unit, tid)); 5655 } 5656 } 5657 #endif /* BCM_TRIUMPH3_SUPPORT */ 5658 5659 #ifdef BCM_TRIDENT2_SUPPORT 5660 /* Clear resilient hashing configuration */ 5661 if (soc_feature(unit, soc_feature_lag_resilient_hash)) { 5662 BCM_IF_ERROR_RETURN(bcm_td2_lag_rh_free_resource(unit, tid)); 5663 } 5664 #endif /* BCM_TRIDENT2_SUPPORT */ 5665 5666 /* Get old trunk bitmap */ 5667 SOC_IF_ERROR_RETURN 5668 (READ_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, tid, &trunk_bitmap_entry)); 5669 SOC_PBMP_CLEAR(old_trunk_pbmp); 5670 soc_mem_pbmp_field_get(unit, TRUNK_BITMAPm, &trunk_bitmap_entry, 5671 TRUNK_BITMAPf, &old_trunk_pbmp); 5672 5673 /* Get old trunk group entry */ 5674 SOC_IF_ERROR_RETURN 5675 (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry)); 5676 old_base_ptr = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, BASE_PTRf); 5677 old_tg_size = 1 + soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, TG_SIZEf); 5678 old_rtag = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, RTAGf); 5679 5680 /* Clear TRUNK_BITMAP table */ 5681 SOC_IF_ERROR_RETURN 5682 (WRITE_TRUNK_BITMAPm(unit, MEM_BLOCK_ALL, tid, 5683 soc_mem_entry_null(unit, TRUNK_BITMAPm))); 5684 5685 /* Clear TRUNK_GROUP table */ 5686 SOC_IF_ERROR_RETURN 5687 (WRITE_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, tid, 5688 soc_mem_entry_null(unit, TRUNK_GROUPm))); 5689 5690 /* Clear TRUNK_MEMBER table */ 5691 if (old_rtag != 0) { 5692 old_num_entries = old_tg_size; 5693 if (old_rtag >= 1 && old_rtag <= 6) { 5694 #ifdef BCM_KATANA_SUPPORT 5695 if (SOC_IS_KATANAX(unit)) { 5696 old_num_entries = _BCM_KATANA_FP_TRUNK_RTAG1_6_MAX_PORTCNT; 5697 } else 5698 #endif 5699 if (soc_feature(unit, 5700 soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 5701 old_num_entries = _BCM_TD_FP_TRUNK_RTAG1_6_MAX_PORTCNT; 5702 } 5703 } 5704 5705 _BCM_FP_TRUNK_MEMBER_USED_CLR_RANGE(unit, old_base_ptr, old_num_entries); 5706 5707 for (i = 0; i < old_num_entries; i++) { 5708 sal_memset(&trunk_member_entry, 0, sizeof(trunk_member_entry_t)); 5709 rv = WRITE_TRUNK_MEMBERm(unit, MEM_BLOCK_ALL, old_base_ptr + i, 5710 &trunk_member_entry); 5711 if (BCM_FAILURE(rv)) { 5712 return rv; 5713 } 5714 } 5715 } 5716 5717 /* Update source port to trunk mapping */ 5718 5719 if (MEMBER_INFO(unit, tid).num_ports > 0) { 5720 leaving_members = sal_alloc(sizeof(bcm_gport_t) * 5721 MEMBER_INFO(unit, tid).num_ports, "leaving members"); 5722 if (leaving_members == NULL) { 5723 return BCM_E_MEMORY; 5724 } 5725 sal_memset(leaving_members, 0, 5726 sizeof(bcm_gport_t) * MEMBER_INFO(unit, tid).num_ports); 5727 5728 for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) { 5729 mod = MEMBER_INFO(unit, tid).modport[i] >> 8; 5730 port = MEMBER_INFO(unit, tid).modport[i] & 0xff; 5731 BCM_GPORT_MODPORT_SET(gport, mod, port); 5732 5733 match_leaving_members = FALSE; 5734 for (j = 0; j < num_leaving_members; j++) { 5735 if (gport == leaving_members[j]) { 5736 match_leaving_members = TRUE; 5737 break; 5738 } 5739 } 5740 if (!match_leaving_members) { 5741 leaving_members[num_leaving_members++] = gport; 5742 } 5743 5744 rv = _bcm_trident_trunk_set_port_property(unit, mod, port, -1); 5745 if (BCM_FAILURE(rv)) { 5746 sal_free(leaving_members); 5747 return rv; 5748 } 5749 } 5750 } 5751 5752 /* 5753 * Remove ports from the block mask table 5754 */ 5755 if (SOC_PBMP_NOT_NULL(old_trunk_pbmp)) { 5756 SOC_PBMP_CLEAR(new_trunk_pbmp); 5757 /* coverity[divide_by_zero] */ 5758 rv = _bcm_trident_trunk_block_mask(unit, TRUNK_BLOCK_MASK_TYPE_IPMC, 5759 old_trunk_pbmp, new_trunk_pbmp, NULL, 0, 5760 NULL, 0, t_info->flags); 5761 if (BCM_FAILURE(rv)) { 5762 sal_free(leaving_members); 5763 return rv; 5764 } 5765 rv = _bcm_trident_trunk_block_mask(unit, TRUNK_BLOCK_MASK_TYPE_L2MC, 5766 old_trunk_pbmp, new_trunk_pbmp, NULL, 0, 5767 NULL, 0, t_info->flags); 5768 if (BCM_FAILURE(rv)) { 5769 sal_free(leaving_members); 5770 return rv; 5771 } 5772 rv = _bcm_trident_trunk_block_mask(unit, TRUNK_BLOCK_MASK_TYPE_BCAST, 5773 old_trunk_pbmp, new_trunk_pbmp, NULL, 0, 5774 NULL, 0, t_info->flags); 5775 if (BCM_FAILURE(rv)) { 5776 sal_free(leaving_members); 5777 return rv; 5778 } 5779 rv = _bcm_trident_trunk_block_mask(unit, TRUNK_BLOCK_MASK_TYPE_DLF, 5780 old_trunk_pbmp, new_trunk_pbmp, NULL, 0, 5781 NULL, 0, t_info->flags); 5782 if (BCM_FAILURE(rv)) { 5783 sal_free(leaving_members); 5784 return rv; 5785 } 5786 5787 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_L3) 5788 if (soc_feature(unit, soc_feature_axp)) { 5789 rv = _bcm_tr3_wlan_trunk_block_mask_update(unit); 5790 if (BCM_FAILURE(rv)) { 5791 sal_free(leaving_members); 5792 return rv; 5793 } 5794 } 5795 #endif /* BCM_TRIUMPH3_SUPPORT && defined(INCLUDE_L3) */ 5796 } 5797 5798 /* 5799 * Remove ports from failover 5800 */ 5801 if (soc_feature(unit, soc_feature_port_lag_failover)) { 5802 rv = _bcm_trident_trunk_failover_set(unit, tid, FALSE, NULL); 5803 if (BCM_FAILURE(rv)) { 5804 sal_free(leaving_members); 5805 return rv; 5806 } 5807 } 5808 5809 rv = _bcm_trident_trunk_swfailover_fp_set(unit, 5810 tid, 5811 0, 5812 0, 5813 NULL, 5814 NULL, 5815 NULL, 5816 0); 5817 if (BCM_FAILURE(rv)) { 5818 sal_free(leaving_members); 5819 return rv; 5820 } 5821 5822 /* Clear trunk properties from members */ 5823 rv = _bcm_xgs3_trunk_property_migrate(unit, 5824 num_leaving_members, leaving_members, 5825 0, NULL, 0, NULL); 5826 if (BCM_FAILURE(rv)) { 5827 sal_free(leaving_members); 5828 return rv; 5829 } 5830 5831 /* Clear trunk member info */ 5832 if (MEMBER_INFO(unit, tid).modport) { 5833 sal_free(MEMBER_INFO(unit, tid).modport); 5834 MEMBER_INFO(unit, tid).modport = NULL; 5835 } 5836 if (MEMBER_INFO(unit, tid).member_flags) { 5837 sal_free(MEMBER_INFO(unit, tid).member_flags); 5838 MEMBER_INFO(unit, tid).member_flags = NULL; 5839 } 5840 MEMBER_INFO(unit, tid).num_ports = 0; 5841 5842 t_info->in_use = FALSE; 5843 5844 sal_free(leaving_members); 5845 return rv; 5846 } 5847 5848 /* 5849 * Function: 5850 * bcm_trident_trunk_fp_get 5851 * Purpose: 5852 * Return trunk information of given front panel trunk ID. 5853 * If t_data->num_ports = 0, return number of trunk members in 5854 * t_data->num_ports. 5855 * Parameters: 5856 * unit - (IN) StrataSwitch PCI device unit number (driver internal). 5857 * tid - (IN) Trunk ID. 5858 * t_data - (OUT) Place to store returned trunk add info. 5859 * t_info - (IN) Trunk info. 5860 * Returns: 5861 * BCM_E_NONE Success. 5862 * BCM_E_XXX 5863 */ 5864 STATIC int 5865 _bcm_trident_trunk_fp_get(int unit, 5866 bcm_trunk_t tid, 5867 _esw_trunk_add_info_t *t_data, 5868 trunk_private_t *t_info) 5869 { 5870 int i; 5871 bcm_module_t mod; 5872 bcm_port_t port; 5873 5874 if (t_data->num_ports == 0) { 5875 t_data->num_ports = MEMBER_INFO(unit, tid).num_ports; 5876 } else { 5877 if (MEMBER_INFO(unit, tid).num_ports <= t_data->num_ports) { 5878 t_data->num_ports = MEMBER_INFO(unit, tid).num_ports; 5879 } 5880 5881 for (i = 0; i < t_data->num_ports; i++) { 5882 mod = MEMBER_INFO(unit, tid).modport[i] >> 8; 5883 port = MEMBER_INFO(unit, tid).modport[i] & 0xff; 5884 BCM_IF_ERROR_RETURN 5885 (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET, mod, port, 5886 &t_data->tm[i], &t_data->tp[i])); 5887 t_data->member_flags[i] = MEMBER_INFO(unit, tid).member_flags[i]; 5888 5889 t_data->dynamic_scaling_factor[i] = 0; 5890 t_data->dynamic_load_weight[i] = 0; 5891 t_data->dynamic_queue_size_weight[i] = 0; 5892 if ((t_data->psc == BCM_TRUNK_PSC_DYNAMIC) || 5893 (t_data->psc == BCM_TRUNK_PSC_DYNAMIC_ASSIGNED) || 5894 (t_data->psc == BCM_TRUNK_PSC_DYNAMIC_OPTIMAL)) { 5895 if (!(t_data->member_flags[i] & 5896 BCM_TRUNK_MEMBER_EGRESS_DISABLE) && 5897 !(t_data->member_flags[i] & 5898 BCM_TRUNK_MEMBER_UNICAST_EGRESS_DISABLE)) { 5899 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 5900 if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 5901 BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_member_attr_get(unit, 5902 port, 5903 &t_data->dynamic_scaling_factor[i], 5904 &t_data->dynamic_load_weight[i], 5905 &t_data->dynamic_queue_size_weight[i])); 5906 } else 5907 #endif /* BCM_TOMAHAWK2_SUPPORT */ 5908 #ifdef BCM_TRIUMPH3_SUPPORT 5909 if (soc_feature(unit, soc_feature_lag_dlb)) { 5910 BCM_IF_ERROR_RETURN(bcm_tr3_lag_dlb_member_attr_get(unit, 5911 mod, port, 5912 &t_data->dynamic_scaling_factor[i], 5913 &t_data->dynamic_load_weight[i])); 5914 } 5915 #endif /* BCM_TRIUMPH3_SUPPORT */ 5916 } 5917 } 5918 } 5919 } 5920 5921 return BCM_E_NONE; 5922 } 5923 5924 /* ----------------------------------------------------------------------------- 5925 * 5926 * Routines for Higig trunking 5927 * 5928 * ----------------------------------------------------------------------------- 5929 */ 5930 5931 static soc_field_t port_loading_threshold_fields[] = { 5932 PORT_LOADING_THRESHOLD_1f, 5933 PORT_LOADING_THRESHOLD_2f, 5934 PORT_LOADING_THRESHOLD_3f, 5935 PORT_LOADING_THRESHOLD_4f, 5936 PORT_LOADING_THRESHOLD_5f, 5937 PORT_LOADING_THRESHOLD_6f, 5938 PORT_LOADING_THRESHOLD_7f 5939 }; 5940 5941 /* 5942 * Function: 5943 * _bcm_trident_hg_dlb_sample_rate_thresholds_set 5944 * Purpose: 5945 * Set Higig DLB port load sample period and thresholds. 5946 * Parameters: 5947 * unit - (IN) SOC unit number. 5948 * sample_rate - (IN) Number of samplings per second. 5949 * min_th - (IN) Minimum port load threshold, in mbps. 5950 * max_th - (IN) Maximum port load threshold, in mbps. 5951 * Returns: 5952 * BCM_E_xxx 5953 */ 5954 STATIC int 5955 _bcm_trident_hg_dlb_sample_rate_thresholds_set(int unit, int sample_rate, 5956 int min_th, int max_th) 5957 { 5958 int num_time_units; 5959 uint32 measure_control_reg; 5960 int max_th_bytes; 5961 int th_increment; 5962 dlb_hgt_glb_quantize_thresholds_entry_t thresholds_entry; 5963 int i; 5964 int th_bytes[7]; 5965 5966 if (sample_rate <= 0 || min_th < 0 || max_th < 0) { 5967 return BCM_E_PARAM; 5968 } 5969 5970 if (min_th > max_th) { 5971 max_th = min_th; 5972 } 5973 5974 #ifdef BCM_TRIUMPH3_SUPPORT 5975 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TD2_TT2(unit)) { 5976 /* Compute sampling period in units of 1us: 5977 * number of 1us time units = 10^6 / sample_rate 5978 */ 5979 num_time_units = 1000000 / sample_rate; 5980 if (num_time_units < 1 || num_time_units > 255) { 5981 /* Hardware limits the sampling period to 1 to 255 time units. */ 5982 return BCM_E_PARAM; 5983 } 5984 } else 5985 #endif /* BCM_TRIUMPH3_SUPPORT */ 5986 { 5987 /* Compute sampling period in units of 256ns: 5988 * number of 256ns time units = 10^9 / 256 / sample_rate 5989 * = 3906250 / sample_rate 5990 */ 5991 num_time_units = 3906250 / sample_rate; 5992 if (num_time_units < 2 || num_time_units > 255) { 5993 /* Hardware limits the sampling period to 2 to 255 time units. */ 5994 return BCM_E_PARAM; 5995 } 5996 } 5997 SOC_IF_ERROR_RETURN 5998 (READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg)); 5999 soc_reg_field_set(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr, 6000 &measure_control_reg, SAMPLING_PERIODf, num_time_units); 6001 SOC_IF_ERROR_RETURN 6002 (WRITE_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg)); 6003 HG_DLB_INFO(unit)->hg_dlb_sample_rate = sample_rate; 6004 6005 #ifdef BCM_TRIUMPH3_SUPPORT 6006 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TD2_TT2(unit)) { 6007 dlb_hgt_quantize_threshold_entry_t quantize_threshold_entry; 6008 soc_mem_t quantize_threshold_m; 6009 6010 /* Compute threshold in bytes per sampling period: 6011 * bytes per 1us = (million bits per sec) * 10^6 / 8 * 10^(-6), 6012 * bytes per sampling period = (bytes per 1us) * (number of 1us 6013 * time units in sampling period) 6014 * = mbps * num_time_units / 8 6015 */ 6016 max_th_bytes = max_th * num_time_units / 8; 6017 6018 if (max_th_bytes > 0xffffff) { 6019 /* Hardware limits port load threshold to 24-bits */ 6020 return BCM_E_PARAM; 6021 } 6022 6023 /* Use min threshold as LOADING_THRESHOLD 0, and max threshold as 6024 * LOADING_THRESHOLD 6. LOADING_THRESHOLD 1 to 5 will be 6025 * evenly spread out between min and max thresholds. 6026 */ 6027 th_increment = (max_th - min_th) / 6; 6028 quantize_threshold_m = soc_mem_is_valid(unit, 6029 DLB_HGT_PLA_QUANTIZE_THRESHOLDm) ? 6030 DLB_HGT_PLA_QUANTIZE_THRESHOLDm : DLB_HGT_QUANTIZE_THRESHOLDm; 6031 for (i = 0; i < 7; i++) { 6032 SOC_IF_ERROR_RETURN 6033 (soc_mem_read(unit, quantize_threshold_m, MEM_BLOCK_ANY, i, 6034 &quantize_threshold_entry)); 6035 th_bytes[i] = (min_th + i * th_increment) * num_time_units / 8; 6036 soc_mem_field32_set(unit, quantize_threshold_m, 6037 &quantize_threshold_entry, LOADING_THRESHOLDf, th_bytes[i]); 6038 SOC_IF_ERROR_RETURN 6039 (soc_mem_write(unit, quantize_threshold_m, MEM_BLOCK_ALL, i, 6040 &quantize_threshold_entry)); 6041 } 6042 } else 6043 #endif /* BCM_TRIUMPH3_SUPPORT */ 6044 { 6045 /* Compute threshold in bytes per sampling period: 6046 * bytes per 256ns = (million bits per sec) * 10^6 / 8 * 256 * 10^(-9), 6047 * bytes per sampling period = (bytes per 256ns) * (number of 256ns 6048 * time units in sampling period) 6049 * = mbps * 256 * num_time_units / 8000 6050 * 6051 * Note: The portion of the formula, (mbps * 256 * num_time_units), may 6052 * overflow when mbps exceeds 33000 and num_time_units equals to 6053 * to its max value of 255. Hence, the formula will be rewritten 6054 * as ((mbps * 256) / 8000) * num_time_units. 6055 */ 6056 max_th_bytes = ((max_th << 8) / 8000) * num_time_units; 6057 6058 if (max_th_bytes > 0xffff) { 6059 /* Hardware limits port load threshold to 16-bits */ 6060 return BCM_E_PARAM; 6061 } 6062 6063 /* Use min threshold as PORT_LOADING_THRESHOLD_1, and max threshold as 6064 * PORT_LOADING_THRESHOLD_7. PORT_LOADING_THRESHOLD 2 to 6 will be 6065 * evenly spread out between min and max thresholds. 6066 */ 6067 th_increment = (max_th - min_th) / 6; 6068 SOC_IF_ERROR_RETURN 6069 (READ_DLB_HGT_GLB_QUANTIZE_THRESHOLDSm(unit, MEM_BLOCK_ANY, 0, 6070 &thresholds_entry)); 6071 for (i = 0; i < 7; i++) { 6072 th_bytes[i] = (((min_th + i * th_increment) << 8) / 8000) * 6073 num_time_units; 6074 soc_DLB_HGT_GLB_QUANTIZE_THRESHOLDSm_field32_set 6075 (unit, &thresholds_entry, port_loading_threshold_fields[i], 6076 th_bytes[i]); 6077 } 6078 SOC_IF_ERROR_RETURN 6079 (WRITE_DLB_HGT_GLB_QUANTIZE_THRESHOLDSm(unit, MEM_BLOCK_ALL, 0, 6080 &thresholds_entry)); 6081 } 6082 6083 HG_DLB_INFO(unit)->hg_dlb_tx_load_min_th = min_th; 6084 HG_DLB_INFO(unit)->hg_dlb_tx_load_max_th = max_th; 6085 6086 return BCM_E_NONE; 6087 } 6088 6089 /* 6090 * Function: 6091 * _bcm_trident_hg_dlb_sample_rate_set 6092 * Purpose: 6093 * Set Higig dynamic load balancing sample rate. 6094 * Parameters: 6095 * unit - (IN) SOC unit number. 6096 * sample_rate - (IN) Number of samplings per second. 6097 * Returns: 6098 * BCM_E_xxx 6099 */ 6100 STATIC int 6101 _bcm_trident_hg_dlb_sample_rate_set(int unit, int sample_rate) 6102 { 6103 BCM_IF_ERROR_RETURN(_bcm_trident_hg_dlb_sample_rate_thresholds_set(unit, 6104 sample_rate, HG_DLB_INFO(unit)->hg_dlb_tx_load_min_th, 6105 HG_DLB_INFO(unit)->hg_dlb_tx_load_max_th)); 6106 return BCM_E_NONE; 6107 } 6108 6109 /* 6110 * Function: 6111 * _bcm_trident_hg_dlb_tx_load_min_th_set 6112 * Purpose: 6113 * Set Higig DLB port load minimum threshold. 6114 * Parameters: 6115 * unit - (IN) SOC unit number. 6116 * min_th - (IN) Minimum port loading threshold. 6117 * Returns: 6118 * BCM_E_xxx 6119 */ 6120 STATIC int 6121 _bcm_trident_hg_dlb_tx_load_min_th_set(int unit, int min_th) 6122 { 6123 BCM_IF_ERROR_RETURN(_bcm_trident_hg_dlb_sample_rate_thresholds_set(unit, 6124 HG_DLB_INFO(unit)->hg_dlb_sample_rate, min_th, 6125 HG_DLB_INFO(unit)->hg_dlb_tx_load_max_th)); 6126 return BCM_E_NONE; 6127 } 6128 6129 /* 6130 * Function: 6131 * _bcm_trident_hg_dlb_tx_load_max_th_set 6132 * Purpose: 6133 * Set Higig DLB port load maximum threshold. 6134 * Parameters: 6135 * unit - (IN) SOC unit number. 6136 * max_th - (IN) Maximum port loading threshold. 6137 * Returns: 6138 * BCM_E_xxx 6139 */ 6140 STATIC int 6141 _bcm_trident_hg_dlb_tx_load_max_th_set(int unit, int max_th) 6142 { 6143 BCM_IF_ERROR_RETURN(_bcm_trident_hg_dlb_sample_rate_thresholds_set(unit, 6144 HG_DLB_INFO(unit)->hg_dlb_sample_rate, 6145 HG_DLB_INFO(unit)->hg_dlb_tx_load_min_th, 6146 max_th)); 6147 return BCM_E_NONE; 6148 } 6149 6150 static soc_field_t port_qsize_threshold_fields[] = { 6151 PORT_QSIZE_THRESHOLD_1f, 6152 PORT_QSIZE_THRESHOLD_2f, 6153 PORT_QSIZE_THRESHOLD_3f, 6154 PORT_QSIZE_THRESHOLD_4f, 6155 PORT_QSIZE_THRESHOLD_5f, 6156 PORT_QSIZE_THRESHOLD_6f, 6157 PORT_QSIZE_THRESHOLD_7f 6158 }; 6159 6160 /* 6161 * Function: 6162 * _bcm_trident_hg_dlb_qsize_thresholds_set 6163 * Purpose: 6164 * Set Higig DLB queue size thresholds. 6165 * Parameters: 6166 * unit - (IN) SOC unit number. 6167 * min_th - (IN) Minimum queue size threshold, in bytes. 6168 * max_th - (IN) Maximum queue size threshold, in bytes. 6169 * Returns: 6170 * BCM_E_xxx 6171 */ 6172 STATIC int 6173 _bcm_trident_hg_dlb_qsize_thresholds_set(int unit, int min_th, int max_th) 6174 { 6175 int max_th_cells; 6176 int th_increment; 6177 dlb_hgt_glb_quantize_thresholds_entry_t thresholds_entry; 6178 int i; 6179 int th_cells[7]; 6180 6181 if (min_th < 0 || max_th < 0) { 6182 return BCM_E_PARAM; 6183 } 6184 6185 if (min_th > max_th) { 6186 max_th = min_th; 6187 } 6188 6189 /* Convert threshold to number of cells */ 6190 max_th_cells = max_th / 208; 6191 6192 if (max_th_cells > 0xffff) { 6193 /* Hardware limits queue size threshold to 16-bits */ 6194 return BCM_E_PARAM; 6195 } 6196 6197 #ifdef BCM_TRIUMPH3_SUPPORT 6198 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TD2_TT2(unit)) { 6199 dlb_hgt_quantize_threshold_entry_t quantize_threshold_entry; 6200 soc_mem_t quantize_threshold_m; 6201 6202 /* Use min threshold as QSIZE_THRESHOLD 0, and max threshold as 6203 * QSIZE_THRESHOLD 6. QSIZE_THRESHOLD 1 to 5 will be 6204 * evenly spread out between min and max thresholds. 6205 */ 6206 th_increment = (max_th - min_th) / 6; 6207 quantize_threshold_m = soc_mem_is_valid(unit, 6208 DLB_HGT_PLA_QUANTIZE_THRESHOLDm) ? 6209 DLB_HGT_PLA_QUANTIZE_THRESHOLDm : DLB_HGT_QUANTIZE_THRESHOLDm; 6210 for (i = 0; i < 7; i++) { 6211 SOC_IF_ERROR_RETURN 6212 (soc_mem_read(unit, quantize_threshold_m, MEM_BLOCK_ANY, i, 6213 &quantize_threshold_entry)); 6214 th_cells[i] = (min_th + i * th_increment) / 208; 6215 soc_mem_field32_set(unit, quantize_threshold_m, 6216 &quantize_threshold_entry, QSIZE_THRESHOLDf, th_cells[i]); 6217 SOC_IF_ERROR_RETURN 6218 (soc_mem_write(unit, quantize_threshold_m, MEM_BLOCK_ALL, i, 6219 &quantize_threshold_entry)); 6220 } 6221 } else 6222 #endif /* BCM_TRIUMPH3_SUPPORT */ 6223 { 6224 /* Use min threshold as PORT_QSIZE_THRESHOLD_1, and max threshold as 6225 * PORT_QSIZE_THRESHOLD_7. PORT_QSIZE_THRESHOLD 2 to 6 will be 6226 * evenly spread out between min and max thresholds. 6227 */ 6228 th_increment = (max_th - min_th) / 6; 6229 SOC_IF_ERROR_RETURN 6230 (READ_DLB_HGT_GLB_QUANTIZE_THRESHOLDSm(unit, MEM_BLOCK_ANY, 0, 6231 &thresholds_entry)); 6232 for (i = 0; i < 7; i++) { 6233 th_cells[i] = (min_th + i * th_increment) >> 7; 6234 soc_DLB_HGT_GLB_QUANTIZE_THRESHOLDSm_field32_set 6235 (unit, &thresholds_entry, port_qsize_threshold_fields[i], 6236 th_cells[i]); 6237 } 6238 SOC_IF_ERROR_RETURN 6239 (WRITE_DLB_HGT_GLB_QUANTIZE_THRESHOLDSm(unit, MEM_BLOCK_ALL, 0, 6240 &thresholds_entry)); 6241 } 6242 HG_DLB_INFO(unit)->hg_dlb_qsize_min_th = min_th; 6243 HG_DLB_INFO(unit)->hg_dlb_qsize_max_th = max_th; 6244 6245 return BCM_E_NONE; 6246 } 6247 6248 /* 6249 * Function: 6250 * _bcm_trident_hg_dlb_qsize_min_th_set 6251 * Purpose: 6252 * Set Higig DLB queue size minimum threshold. 6253 * Parameters: 6254 * unit - (IN) SOC unit number. 6255 * min_th - (IN) Minimum queue size threshold, in bytes. 6256 * Returns: 6257 * BCM_E_xxx 6258 */ 6259 STATIC int 6260 _bcm_trident_hg_dlb_qsize_min_th_set(int unit, int min_th) 6261 { 6262 BCM_IF_ERROR_RETURN(_bcm_trident_hg_dlb_qsize_thresholds_set(unit, 6263 min_th, HG_DLB_INFO(unit)->hg_dlb_qsize_max_th)); 6264 6265 return BCM_E_NONE; 6266 } 6267 6268 /* 6269 * Function: 6270 * _bcm_trident_hg_dlb_qsize_max_th_set 6271 * Purpose: 6272 * Set Higig DLB queue size maximum threshold. 6273 * Parameters: 6274 * unit - (IN) SOC unit number. 6275 * max_th - (IN) Maximum queue size threshold, in bytes. 6276 * Returns: 6277 * BCM_E_xxx 6278 */ 6279 STATIC int 6280 _bcm_trident_hg_dlb_qsize_max_th_set(int unit, int max_th) 6281 { 6282 BCM_IF_ERROR_RETURN(_bcm_trident_hg_dlb_qsize_thresholds_set(unit, 6283 HG_DLB_INFO(unit)->hg_dlb_qsize_min_th, max_th)); 6284 6285 return BCM_E_NONE; 6286 } 6287 6288 /* 6289 * Function: 6290 * _bcm_trident_hg_dlb_tx_load_weight_set 6291 * Purpose: 6292 * Set Higig DLB port load weight. 6293 * Parameters: 6294 * unit - (IN) SOC unit number. 6295 * weight - (IN) Port load weight. 6296 * Returns: 6297 * BCM_E_xxx 6298 */ 6299 STATIC int 6300 _bcm_trident_hg_dlb_tx_load_weight_set(int unit, int weight) 6301 { 6302 uint32 measure_control_reg; 6303 soc_field_t load_weight_f; 6304 6305 if (weight < 0 || 6306 weight > 0xf) { 6307 /* Hardware limits port load weight to 4 bits */ 6308 return BCM_E_PARAM; 6309 } 6310 6311 SOC_IF_ERROR_RETURN 6312 (READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg)); 6313 if (SOC_REG_FIELD_VALID(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr, 6314 PORT_LOADING_WEIGHTf)) { 6315 load_weight_f = PORT_LOADING_WEIGHTf; 6316 } else { 6317 load_weight_f = WEIGHT_LOADINGf; 6318 } 6319 soc_reg_field_set(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr, 6320 &measure_control_reg, load_weight_f, weight); 6321 SOC_IF_ERROR_RETURN 6322 (WRITE_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg)); 6323 return BCM_E_NONE; 6324 } 6325 6326 /* 6327 * Function: 6328 * _bcm_trident_hg_dlb_tx_load_weight_get 6329 * Purpose: 6330 * Get Higig DLB port load weight. 6331 * Parameters: 6332 * unit - (IN) SOC unit number. 6333 * weight - (OUT) Port load weight. 6334 * Returns: 6335 * BCM_E_xxx 6336 */ 6337 STATIC int 6338 _bcm_trident_hg_dlb_tx_load_weight_get(int unit, int *weight) 6339 { 6340 uint32 measure_control_reg; 6341 soc_field_t load_weight_f; 6342 6343 SOC_IF_ERROR_RETURN 6344 (READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg)); 6345 if (SOC_REG_FIELD_VALID(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr, 6346 PORT_LOADING_WEIGHTf)) { 6347 load_weight_f = PORT_LOADING_WEIGHTf; 6348 } else { 6349 load_weight_f = WEIGHT_LOADINGf; 6350 } 6351 *weight = soc_reg_field_get(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr, 6352 measure_control_reg, load_weight_f); 6353 6354 return BCM_E_NONE; 6355 } 6356 6357 /* 6358 * Function: 6359 * _bcm_trident_hg_dlb_qsize_weight_set 6360 * Purpose: 6361 * Set Higig DLB queue size weight. 6362 * Parameters: 6363 * unit - (IN) SOC unit number. 6364 * weight - (IN) Queue size weight. 6365 * Returns: 6366 * BCM_E_xxx 6367 */ 6368 STATIC int 6369 _bcm_trident_hg_dlb_qsize_weight_set(int unit, int weight) 6370 { 6371 uint32 measure_control_reg; 6372 soc_field_t qsize_weight_f; 6373 6374 if (weight < 0 || 6375 weight > 0xf) { 6376 /* Hardware limits queue size weight to 4 bits */ 6377 return BCM_E_PARAM; 6378 } 6379 6380 SOC_IF_ERROR_RETURN 6381 (READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg)); 6382 if (SOC_REG_FIELD_VALID(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr, 6383 PORT_QSIZE_WEIGHTf)) { 6384 qsize_weight_f = PORT_QSIZE_WEIGHTf; 6385 } else { 6386 qsize_weight_f = WEIGHT_QSIZEf; 6387 } 6388 soc_reg_field_set(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr, 6389 &measure_control_reg, qsize_weight_f, weight); 6390 SOC_IF_ERROR_RETURN 6391 (WRITE_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg)); 6392 return BCM_E_NONE; 6393 } 6394 6395 /* 6396 * Function: 6397 * _bcm_trident_hg_dlb_qsize_weight_get 6398 * Purpose: 6399 * Get Higig DLB queue size weight. 6400 * Parameters: 6401 * unit - (IN) SOC unit number. 6402 * weight - (OUT) Queue size weight. 6403 * Returns: 6404 * BCM_E_xxx 6405 */ 6406 STATIC int 6407 _bcm_trident_hg_dlb_qsize_weight_get(int unit, int *weight) 6408 { 6409 uint32 measure_control_reg; 6410 soc_field_t qsize_weight_f; 6411 6412 SOC_IF_ERROR_RETURN 6413 (READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg)); 6414 if (SOC_REG_FIELD_VALID(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr, 6415 PORT_QSIZE_WEIGHTf)) { 6416 qsize_weight_f = PORT_QSIZE_WEIGHTf; 6417 } else { 6418 qsize_weight_f = WEIGHT_QSIZEf; 6419 } 6420 *weight = soc_reg_field_get(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr, 6421 measure_control_reg, qsize_weight_f); 6422 6423 return BCM_E_NONE; 6424 } 6425 6426 /* 6427 * Function: 6428 * _bcm_trident_hg_dlb_tx_load_cap_set 6429 * Purpose: 6430 * Set Higig DLB port load cap control. 6431 * Parameters: 6432 * unit - (IN) SOC unit number. 6433 * cap - (IN) Port load cap control. 6434 * Returns: 6435 * BCM_E_xxx 6436 */ 6437 STATIC int 6438 _bcm_trident_hg_dlb_tx_load_cap_set(int unit, int cap) 6439 { 6440 uint32 measure_control_reg; 6441 soc_field_t cap_load_f; 6442 6443 if (cap < 0 || 6444 cap > 1) { 6445 /* Hardware limits port load cap control to 1 bit */ 6446 return BCM_E_PARAM; 6447 } 6448 6449 SOC_IF_ERROR_RETURN 6450 (READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg)); 6451 if (SOC_REG_FIELD_VALID(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr, 6452 CAP_LOADING_AVERAGEf)) { 6453 cap_load_f = CAP_LOADING_AVERAGEf; 6454 } else { 6455 cap_load_f = CAP_LOADING_AVGf; 6456 } 6457 soc_reg_field_set(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr, 6458 &measure_control_reg, cap_load_f, cap); 6459 SOC_IF_ERROR_RETURN 6460 (WRITE_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg)); 6461 return BCM_E_NONE; 6462 } 6463 6464 /* 6465 * Function: 6466 * _bcm_trident_hg_dlb_tx_load_cap_get 6467 * Purpose: 6468 * Get Higig DLB port load cap control. 6469 * Parameters: 6470 * unit - (IN) SOC unit number. 6471 * cap - (OUT) Cap control. 6472 * Returns: 6473 * BCM_E_xxx 6474 */ 6475 STATIC int 6476 _bcm_trident_hg_dlb_tx_load_cap_get(int unit, int *cap) 6477 { 6478 uint32 measure_control_reg; 6479 soc_field_t cap_load_f; 6480 6481 SOC_IF_ERROR_RETURN 6482 (READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg)); 6483 if (SOC_REG_FIELD_VALID(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr, 6484 CAP_LOADING_AVERAGEf)) { 6485 cap_load_f = CAP_LOADING_AVERAGEf; 6486 } else { 6487 cap_load_f = CAP_LOADING_AVGf; 6488 } 6489 *cap= soc_reg_field_get(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr, 6490 measure_control_reg, cap_load_f); 6491 6492 return BCM_E_NONE; 6493 } 6494 6495 /* 6496 * Function: 6497 * _bcm_trident_hg_dlb_qsize_cap_set 6498 * Purpose: 6499 * Set Higig DLB queue size cap control. 6500 * Parameters: 6501 * unit - (IN) SOC unit number. 6502 * cap - (IN) Queue size cap control. 6503 * Returns: 6504 * BCM_E_xxx 6505 */ 6506 STATIC int 6507 _bcm_trident_hg_dlb_qsize_cap_set(int unit, int cap) 6508 { 6509 uint32 measure_control_reg; 6510 soc_field_t cap_qsize_f; 6511 6512 if (cap < 0 || 6513 cap > 1) { 6514 /* Hardware limits queue size cap control to 1 bit */ 6515 return BCM_E_PARAM; 6516 } 6517 6518 SOC_IF_ERROR_RETURN 6519 (READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg)); 6520 if (SOC_REG_FIELD_VALID(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr, 6521 CAP_QSIZE_AVERAGEf)) { 6522 cap_qsize_f = CAP_QSIZE_AVERAGEf; 6523 } else { 6524 cap_qsize_f = CAP_QSIZE_AVGf; 6525 } 6526 soc_reg_field_set(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr, 6527 &measure_control_reg, cap_qsize_f, cap); 6528 SOC_IF_ERROR_RETURN 6529 (WRITE_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg)); 6530 6531 return BCM_E_NONE; 6532 } 6533 6534 /* 6535 * Function: 6536 * _bcm_trident_hg_dlb_qsize_cap_get 6537 * Purpose: 6538 * Get Higig DLB queue size cap control. 6539 * Parameters: 6540 * unit - (IN) SOC unit number. 6541 * cap - (OUT) Cap control. 6542 * Returns: 6543 * BCM_E_xxx 6544 */ 6545 STATIC int 6546 _bcm_trident_hg_dlb_qsize_cap_get(int unit, int *cap) 6547 { 6548 uint32 measure_control_reg; 6549 soc_field_t cap_qsize_f; 6550 6551 SOC_IF_ERROR_RETURN 6552 (READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg)); 6553 if (SOC_REG_FIELD_VALID(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr, 6554 CAP_QSIZE_AVERAGEf)) { 6555 cap_qsize_f = CAP_QSIZE_AVERAGEf; 6556 } else { 6557 cap_qsize_f = CAP_QSIZE_AVGf; 6558 } 6559 *cap= soc_reg_field_get(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr, 6560 measure_control_reg, cap_qsize_f); 6561 6562 return BCM_E_NONE; 6563 } 6564 6565 /* 6566 * Function: 6567 * _bcm_trident_hg_dlb_config_set 6568 * Purpose: 6569 * Set per-chip Higig dynamic load balancing configuration parameters. 6570 * Parameters: 6571 * unit - (IN) SOC unit number. 6572 * type - (IN) Configuration parameter type. 6573 * arg - (IN) Configuration paramter value. 6574 * Returns: 6575 * BCM_E_xxx 6576 */ 6577 int 6578 _bcm_trident_hg_dlb_config_set(int unit, bcm_switch_control_t type, int arg) 6579 { 6580 switch (type) { 6581 case bcmSwitchFabricTrunkDynamicSampleRate: 6582 return _bcm_trident_hg_dlb_sample_rate_set(unit, arg); 6583 6584 case bcmSwitchFabricTrunkDynamicEgressBytesExponent: 6585 return _bcm_trident_hg_dlb_tx_load_weight_set(unit, arg); 6586 6587 case bcmSwitchFabricTrunkDynamicQueuedBytesExponent: 6588 return _bcm_trident_hg_dlb_qsize_weight_set(unit, arg); 6589 6590 case bcmSwitchFabricTrunkDynamicEgressBytesDecreaseReset: 6591 return _bcm_trident_hg_dlb_tx_load_cap_set(unit, arg); 6592 6593 case bcmSwitchFabricTrunkDynamicQueuedBytesDecreaseReset: 6594 return _bcm_trident_hg_dlb_qsize_cap_set(unit, arg); 6595 6596 case bcmSwitchFabricTrunkDynamicEgressBytesMinThreshold: 6597 return _bcm_trident_hg_dlb_tx_load_min_th_set(unit, arg); 6598 6599 case bcmSwitchFabricTrunkDynamicEgressBytesMaxThreshold: 6600 return _bcm_trident_hg_dlb_tx_load_max_th_set(unit, arg); 6601 6602 case bcmSwitchFabricTrunkDynamicQueuedBytesMinThreshold: 6603 return _bcm_trident_hg_dlb_qsize_min_th_set(unit, arg); 6604 6605 case bcmSwitchFabricTrunkDynamicQueuedBytesMaxThreshold: 6606 return _bcm_trident_hg_dlb_qsize_max_th_set(unit, arg); 6607 6608 default: 6609 return BCM_E_PARAM; 6610 } 6611 } 6612 6613 /* 6614 * Function: 6615 * _bcm_trident_hg_dlb_config_get 6616 * Purpose: 6617 * Get per-chip Higig dynamic load balancing configuration parameters. 6618 * Parameters: 6619 * unit - (IN) SOC unit number. 6620 * type - (IN) Configuration parameter type. 6621 * arg - (OUT) Configuration paramter value. 6622 * Returns: 6623 * BCM_E_xxx 6624 */ 6625 int 6626 _bcm_trident_hg_dlb_config_get(int unit, bcm_switch_control_t type, int *arg) 6627 { 6628 switch (type) { 6629 case bcmSwitchFabricTrunkDynamicSampleRate: 6630 *arg = HG_DLB_INFO(unit)->hg_dlb_sample_rate; 6631 break; 6632 6633 case bcmSwitchFabricTrunkDynamicEgressBytesExponent: 6634 return _bcm_trident_hg_dlb_tx_load_weight_get(unit, arg); 6635 6636 case bcmSwitchFabricTrunkDynamicQueuedBytesExponent: 6637 return _bcm_trident_hg_dlb_qsize_weight_get(unit, arg); 6638 6639 case bcmSwitchFabricTrunkDynamicEgressBytesDecreaseReset: 6640 return _bcm_trident_hg_dlb_tx_load_cap_get(unit, arg); 6641 6642 case bcmSwitchFabricTrunkDynamicQueuedBytesDecreaseReset: 6643 return _bcm_trident_hg_dlb_qsize_cap_get(unit, arg); 6644 6645 case bcmSwitchFabricTrunkDynamicEgressBytesMinThreshold: 6646 *arg = HG_DLB_INFO(unit)->hg_dlb_tx_load_min_th; 6647 break; 6648 6649 case bcmSwitchFabricTrunkDynamicEgressBytesMaxThreshold: 6650 *arg = HG_DLB_INFO(unit)->hg_dlb_tx_load_max_th; 6651 break; 6652 6653 case bcmSwitchFabricTrunkDynamicQueuedBytesMinThreshold: 6654 *arg = HG_DLB_INFO(unit)->hg_dlb_qsize_min_th; 6655 break; 6656 6657 case bcmSwitchFabricTrunkDynamicQueuedBytesMaxThreshold: 6658 *arg = HG_DLB_INFO(unit)->hg_dlb_qsize_max_th; 6659 break; 6660 6661 default: 6662 return BCM_E_PARAM; 6663 } 6664 6665 return BCM_E_NONE; 6666 } 6667 6668 /* 6669 * Function: 6670 * _bcm_trident_hg_dlb_quality_assign 6671 * Purpose: 6672 * Assign quality based on port loading and queue size. 6673 * Parameters: 6674 * unit - (IN)SOC unit number. 6675 * tx_load_percent - (IN) Percent weight of port loading in determing 6676 * port quality. The remaining percentage is 6677 * the weight of queue size. 6678 * entry_arr - (IN) Array of 64 quality map table entries. 6679 * Returns: 6680 * BCM_X_XXX 6681 */ 6682 STATIC int 6683 _bcm_trident_hg_dlb_quality_assign(int unit, int tx_load_percent, 6684 uint32 *entry_arr) 6685 { 6686 int quantized_tx_load; 6687 int quantized_qsize; 6688 int quality; 6689 int entry_index; 6690 6691 if (entry_arr == NULL) { 6692 return BCM_E_PARAM; 6693 } 6694 6695 for (quantized_tx_load = 0; quantized_tx_load < 8; quantized_tx_load++) { 6696 for (quantized_qsize = 0; quantized_qsize < 8; quantized_qsize++) { 6697 quality = (quantized_tx_load * tx_load_percent + 6698 quantized_qsize * (100 - tx_load_percent)) / 100; 6699 entry_index = (quantized_tx_load << 3) + quantized_qsize; 6700 if (soc_mem_is_valid(unit, DLB_HGT_PORT_QUALITY_MAPPINGm)) { 6701 soc_DLB_HGT_PORT_QUALITY_MAPPINGm_field32_set(unit, 6702 &entry_arr[entry_index], ASSIGNED_QUALITYf, quality); 6703 } else if (soc_mem_field_valid(unit, DLB_HGT_QUALITY_MAPPINGm, 6704 ASSIGNED_QUALITYf)) { 6705 soc_DLB_HGT_QUALITY_MAPPINGm_field32_set(unit, 6706 &entry_arr[entry_index], ASSIGNED_QUALITYf, quality); 6707 } else { 6708 soc_DLB_HGT_QUALITY_MAPPINGm_field32_set(unit, 6709 &entry_arr[entry_index], QUALITYf, quality); 6710 } 6711 } 6712 } 6713 6714 return BCM_E_NONE; 6715 } 6716 6717 #ifdef BCM_TRIUMPH3_SUPPORT 6718 /* 6719 * Function: 6720 * _bcm_tr3_hg_dlb_member_quality_map_set 6721 * Purpose: 6722 * Set per-member Higig DLB quality mapping table. 6723 * Parameters: 6724 * unit - (IN) SOC unit number. 6725 * member_id - (IN) Member ID. 6726 * tx_load_percent - (IN) Percent weight of port loading in determing 6727 * port quality. The remaining percentage is 6728 * the weight of queue size. 6729 * Returns: 6730 * BCM_E_xxx 6731 */ 6732 STATIC int 6733 _bcm_tr3_hg_dlb_member_quality_map_set(int unit, int member_id, 6734 int tx_load_percent) 6735 { 6736 soc_profile_mem_t *profile; 6737 soc_mem_t mem; 6738 int entry_bytes; 6739 int entries_per_profile; 6740 int alloc_size; 6741 uint32 *entry_arr; 6742 int rv = BCM_E_NONE; 6743 void *entries; 6744 uint32 base_index; 6745 uint32 old_base_index = 0; 6746 dlb_hgt_quality_control_entry_t quality_control_entry; 6747 soc_field_t profile_ptr_f; 6748 6749 profile = _trident_hg_dlb_bk[unit]->hg_dlb_quality_map_profile; 6750 6751 entries_per_profile = 64; 6752 entry_bytes = sizeof(dlb_hgt_quality_mapping_entry_t); 6753 alloc_size = entries_per_profile * entry_bytes; 6754 entry_arr = sal_alloc(alloc_size, "HG DLB Quality Map entries"); 6755 if (entry_arr == NULL) { 6756 return BCM_E_MEMORY; 6757 } 6758 sal_memset(entry_arr, 0, alloc_size); 6759 6760 /* Assign quality in the entry array */ 6761 rv = _bcm_trident_hg_dlb_quality_assign(unit, tx_load_percent, entry_arr); 6762 if (BCM_FAILURE(rv)) { 6763 sal_free(entry_arr); 6764 return rv; 6765 } 6766 6767 mem = DLB_HGT_QUALITY_MAPPINGm; 6768 soc_mem_lock(unit, mem); 6769 6770 /* Add profile */ 6771 entries = entry_arr; 6772 rv = soc_profile_mem_add(unit, profile, &entries, entries_per_profile, 6773 &base_index); 6774 sal_free(entry_arr); 6775 if (SOC_FAILURE(rv)) { 6776 soc_mem_unlock(unit, mem); 6777 return rv; 6778 } 6779 6780 /* Update member profile pointer */ 6781 rv = READ_DLB_HGT_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY, member_id, 6782 &quality_control_entry); 6783 if (SOC_FAILURE(rv)) { 6784 soc_mem_unlock(unit, mem); 6785 return rv; 6786 } 6787 profile_ptr_f = soc_mem_field_valid(unit, DLB_HGT_QUALITY_CONTROLm, 6788 PROFILE_PTRf) ? PROFILE_PTRf : QMT_PROFILE_PTRf; 6789 old_base_index = entries_per_profile * soc_mem_field32_get(unit, 6790 DLB_HGT_QUALITY_CONTROLm, &quality_control_entry, profile_ptr_f); 6791 soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit, &quality_control_entry, 6792 profile_ptr_f, base_index / entries_per_profile); 6793 rv = WRITE_DLB_HGT_QUALITY_CONTROLm(unit, MEM_BLOCK_ALL, member_id, 6794 &quality_control_entry); 6795 if (SOC_FAILURE(rv)) { 6796 soc_mem_unlock(unit, mem); 6797 return rv; 6798 } 6799 6800 /* Delete old profile */ 6801 rv = soc_profile_mem_delete(unit, profile, old_base_index); 6802 soc_mem_unlock(unit, mem); 6803 6804 HG_DLB_INFO(unit)->hg_dlb_load_weight[base_index/entries_per_profile] = 6805 tx_load_percent; 6806 6807 return rv; 6808 } 6809 #endif /* BCM_TRIUMPH3_SUPPORT */ 6810 6811 /* 6812 * Function: 6813 * _bcm_trident_hg_dlb_quality_map_set 6814 * Purpose: 6815 * Set per-port Higig DLB quality mapping table. 6816 * Parameters: 6817 * unit - (IN) SOC unit number. 6818 * port - (IN) Port number. 6819 * tx_load_percent - (IN) Percent weight of port loading in determing 6820 * port quality. The remaining percentage is 6821 * the weight of queue size. 6822 * Returns: 6823 * BCM_E_xxx 6824 */ 6825 STATIC int 6826 _bcm_trident_hg_dlb_quality_map_set(int unit, bcm_port_t port, 6827 int tx_load_percent) 6828 { 6829 soc_profile_mem_t *profile; 6830 int entries_per_profile; 6831 int alloc_size; 6832 uint32 *entry_arr; 6833 int rv; 6834 void *entries; 6835 uint32 base_index; 6836 uint32 old_base_index; 6837 uint32 quantize_control_reg; 6838 soc_mem_t mem; 6839 6840 profile = _trident_hg_dlb_bk[unit]->hg_dlb_quality_map_profile; 6841 6842 entries_per_profile = 64; 6843 alloc_size = entries_per_profile * 6844 sizeof(dlb_hgt_port_quality_mapping_entry_t); 6845 entry_arr = sal_alloc(alloc_size, "HG DLB Quality Map entries"); 6846 if (entry_arr == NULL) { 6847 return BCM_E_MEMORY; 6848 } 6849 sal_memset(entry_arr, 0, alloc_size); 6850 6851 /* Assign quality in the entry array */ 6852 rv = _bcm_trident_hg_dlb_quality_assign(unit, tx_load_percent, entry_arr); 6853 if (BCM_FAILURE(rv)) { 6854 sal_free(entry_arr); 6855 return rv; 6856 } 6857 6858 mem = DLB_HGT_PORT_QUALITY_MAPPINGm; 6859 soc_mem_lock(unit, mem); 6860 entries = entry_arr; 6861 rv = soc_profile_mem_add(unit, profile, &entries, entries_per_profile, 6862 &base_index); 6863 sal_free(entry_arr); 6864 if (SOC_FAILURE(rv)) { 6865 soc_mem_unlock(unit, mem); 6866 return rv; 6867 } 6868 6869 rv = READ_DLB_HGT_QUANTIZE_CONTROLr(unit, port, &quantize_control_reg); 6870 if (SOC_FAILURE(rv)) { 6871 soc_mem_unlock(unit, mem); 6872 return rv; 6873 } 6874 old_base_index = entries_per_profile * soc_reg_field_get(unit, 6875 DLB_HGT_QUANTIZE_CONTROLr, quantize_control_reg, 6876 PORT_QUALITY_MAPPING_PROFILE_PTRf); 6877 soc_reg_field_set(unit, DLB_HGT_QUANTIZE_CONTROLr, 6878 &quantize_control_reg, PORT_QUALITY_MAPPING_PROFILE_PTRf, 6879 base_index / entries_per_profile); 6880 rv = WRITE_DLB_HGT_QUANTIZE_CONTROLr(unit, port, quantize_control_reg); 6881 if (SOC_FAILURE(rv)) { 6882 soc_mem_unlock(unit, mem); 6883 return rv; 6884 } 6885 6886 rv = soc_profile_mem_delete(unit, profile, old_base_index); 6887 6888 soc_mem_unlock(unit, mem); 6889 6890 HG_DLB_INFO(unit)->hg_dlb_load_weight[base_index/entries_per_profile] = 6891 tx_load_percent; 6892 6893 return rv; 6894 } 6895 6896 /* 6897 * Function: 6898 * _bcm_trident_hg_dlb_id_alloc 6899 * Purpose: 6900 * Get a free Higig DLB ID and mark it used. 6901 * Parameters: 6902 * unit - (IN) SOC unit number. 6903 * hgtid - (IN) Higig trunk ID. 6904 * dlb_id - (OUT) Allocated DLB ID. 6905 * Returns: 6906 * BCM_E_xxx 6907 */ 6908 STATIC int 6909 _bcm_trident_hg_dlb_id_alloc(int unit, int hgtid, int *dlb_id) 6910 { 6911 int i; 6912 6913 #ifdef BCM_TRIDENT2_SUPPORT 6914 if (soc_feature(unit, soc_feature_hg_dlb_id_equal_hg_tid)) { 6915 if (_BCM_HG_DLB_ID_USED_GET(unit, hgtid)) { 6916 return BCM_E_EXISTS; 6917 } 6918 _BCM_HG_DLB_ID_USED_SET(unit, hgtid); 6919 *dlb_id = hgtid; 6920 return BCM_E_NONE; 6921 } else 6922 #endif /* BCM_TRIDENT2_SUPPORT */ 6923 { 6924 for (i = 0; i < soc_mem_index_count(unit, DLB_HGT_GROUP_CONTROLm); i++) { 6925 if (!_BCM_HG_DLB_ID_USED_GET(unit, i)) { 6926 _BCM_HG_DLB_ID_USED_SET(unit, i); 6927 *dlb_id = i; 6928 return BCM_E_NONE; 6929 } 6930 } 6931 } 6932 6933 return BCM_E_RESOURCE; 6934 } 6935 6936 /* 6937 * Function: 6938 * _bcm_trident_hg_dlb_id_free 6939 * Purpose: 6940 * Free a Higig DLB ID. 6941 * Parameters: 6942 * unit - (IN) SOC unit number. 6943 * dlb_id - (IN) DLB ID to be freed. 6944 * Returns: 6945 * BCM_E_xxx 6946 */ 6947 STATIC int 6948 _bcm_trident_hg_dlb_id_free(int unit, int dlb_id) 6949 { 6950 if (dlb_id < 0 || dlb_id > soc_mem_index_max(unit, DLB_HGT_GROUP_CONTROLm)) { 6951 return BCM_E_PARAM; 6952 } 6953 6954 _BCM_HG_DLB_ID_USED_CLR(unit, dlb_id); 6955 6956 return BCM_E_NONE; 6957 } 6958 6959 #ifdef BCM_TRIUMPH3_SUPPORT 6960 /* 6961 * Function: 6962 * _bcm_tr3_hg_dlb_member_id_alloc 6963 * Purpose: 6964 * Get a free Higig DLB Member ID and mark it used. 6965 * Parameters: 6966 * unit - (IN) SOC unit number. 6967 * member_id - (OUT) Allocated Member ID. 6968 * Returns: 6969 * BCM_E_xxx 6970 */ 6971 STATIC int 6972 _bcm_tr3_hg_dlb_member_id_alloc(int unit, int *member_id) 6973 { 6974 int i; 6975 6976 for (i = 0; i < soc_mem_index_count(unit, DLB_HGT_MEMBER_ATTRIBUTEm); i++) { 6977 if (!_BCM_HG_DLB_MEMBER_ID_USED_GET(unit, i)) { 6978 _BCM_HG_DLB_MEMBER_ID_USED_SET(unit, i); 6979 *member_id = i; 6980 return BCM_E_NONE; 6981 } 6982 } 6983 6984 return BCM_E_RESOURCE; 6985 } 6986 6987 /* 6988 * Function: 6989 * _bcm_tr3_hg_dlb_member_id_free 6990 * Purpose: 6991 * Free a Higig DLB Member ID. 6992 * Parameters: 6993 * unit - (IN) SOC unit number. 6994 * member_id - (IN) Member ID to be freed. 6995 * Returns: 6996 * BCM_E_xxx 6997 */ 6998 STATIC int 6999 _bcm_tr3_hg_dlb_member_id_free(int unit, int member_id) 7000 { 7001 if (member_id < 0 || member_id > soc_mem_index_max(unit, 7002 DLB_HGT_MEMBER_ATTRIBUTEm)) { 7003 return BCM_E_PARAM; 7004 } 7005 7006 _BCM_HG_DLB_MEMBER_ID_USED_CLR(unit, member_id); 7007 7008 return BCM_E_NONE; 7009 } 7010 7011 /* 7012 * Function: 7013 * _bcm_tr3_hg_dlb_member_array_alloc 7014 * Purpose: 7015 * Allocate member IDs for each Higig trunk member. 7016 * Parameters: 7017 * unit - (IN) SOC unit number. 7018 * add_info - (IN) Pointer to trunk add info structure. 7019 * member_id_array - (OUT) Array of member IDs. 7020 * Returns: 7021 * BCM_E_xxx 7022 */ 7023 STATIC int 7024 _bcm_tr3_hg_dlb_member_array_alloc(int unit, 7025 _esw_trunk_add_info_t *add_info, 7026 int *member_id_array) 7027 { 7028 int i; 7029 dlb_hgt_port_member_map_entry_t port_member_map_entry; 7030 port_tab_entry_t ptab; 7031 dlb_hgt_member_attribute_entry_t member_attr_entry; 7032 dlb_hgt_quality_control_entry_t quality_control_entry; 7033 soc_field_t enable_credit_collect_f; 7034 int hw_mask; 7035 7036 for (i = 0; i < add_info->num_ports; i++) { 7037 SOC_IF_ERROR_RETURN(READ_DLB_HGT_PORT_MEMBER_MAPm(unit, MEM_BLOCK_ANY, 7038 add_info->tp[i], &port_member_map_entry)); 7039 if (soc_DLB_HGT_PORT_MEMBER_MAPm_field32_get(unit, 7040 &port_member_map_entry, VALIDf)) { 7041 member_id_array[i] = 7042 soc_DLB_HGT_PORT_MEMBER_MAPm_field32_get(unit, 7043 &port_member_map_entry, MEMBER_IDf); 7044 } else { 7045 BCM_IF_ERROR_RETURN(_bcm_tr3_hg_dlb_member_id_alloc(unit, 7046 &member_id_array[i])); 7047 7048 /* Set member map entry */ 7049 soc_DLB_HGT_PORT_MEMBER_MAPm_field32_set(unit, 7050 &port_member_map_entry, VALIDf, 1); 7051 soc_DLB_HGT_PORT_MEMBER_MAPm_field32_set(unit, 7052 &port_member_map_entry, MEMBER_IDf, member_id_array[i]); 7053 if (soc_mem_field_valid(unit, DLB_HGT_PORT_MEMBER_MAPm, EMBEDDED_HGf)) { 7054 SOC_IF_ERROR_RETURN 7055 (READ_PORT_TABm(unit, MEM_BLOCK_ANY, add_info->tp[i], &ptab)); 7056 if (soc_PORT_TABm_field32_get(unit, &ptab, PORT_TYPEf) == 3) { 7057 /* Port is an embedded Higig port */ 7058 soc_DLB_HGT_PORT_MEMBER_MAPm_field32_set(unit, 7059 &port_member_map_entry, EMBEDDED_HGf, 1); 7060 } else { 7061 soc_DLB_HGT_PORT_MEMBER_MAPm_field32_set(unit, 7062 &port_member_map_entry, EMBEDDED_HGf, 0); 7063 } 7064 } 7065 SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_PORT_MEMBER_MAPm(unit, 7066 MEM_BLOCK_ALL, add_info->tp[i], 7067 &port_member_map_entry)); 7068 7069 /* Set member attribute entry */ 7070 SOC_IF_ERROR_RETURN(READ_DLB_HGT_MEMBER_ATTRIBUTEm(unit, 7071 MEM_BLOCK_ANY, member_id_array[i], 7072 &member_attr_entry)); 7073 soc_DLB_HGT_MEMBER_ATTRIBUTEm_field32_set(unit, &member_attr_entry, 7074 PORT_NUMf, add_info->tp[i]); 7075 SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_MEMBER_ATTRIBUTEm(unit, 7076 MEM_BLOCK_ALL, member_id_array[i], 7077 &member_attr_entry)); 7078 7079 /* Set member quality mapping profile */ 7080 BCM_IF_ERROR_RETURN(_bcm_tr3_hg_dlb_member_quality_map_set(unit, 7081 member_id_array[i], add_info->dynamic_load_weight[i])); 7082 7083 /* Enable member quality control */ 7084 SOC_IF_ERROR_RETURN(READ_DLB_HGT_QUALITY_CONTROLm(unit, 7085 MEM_BLOCK_ANY, member_id_array[i], 7086 &quality_control_entry)); 7087 soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit, 7088 &quality_control_entry, ENABLE_AVG_CALCf, 1); 7089 soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit, 7090 &quality_control_entry, ENABLE_QUALITY_UPDATEf, 1); 7091 enable_credit_collect_f = soc_mem_field_valid(unit, 7092 DLB_HGT_QUALITY_CONTROLm, ENABLE_CREDIT_COLLECTIONf) ? 7093 ENABLE_CREDIT_COLLECTIONf : ENB_CREDIT_COLLECTIONf; 7094 soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit, 7095 &quality_control_entry, enable_credit_collect_f, 1); 7096 hw_mask = (1 << soc_mem_field_length(unit, DLB_HGT_QUALITY_CONTROLm, 7097 LOADING_SCALING_FACTORf)) - 1; 7098 soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit, 7099 &quality_control_entry, LOADING_SCALING_FACTORf, 7100 add_info->dynamic_scaling_factor[i] & hw_mask); 7101 hw_mask = (1 << soc_mem_field_length(unit, DLB_HGT_QUALITY_CONTROLm, 7102 QSIZE_SCALING_FACTORf)) - 1; 7103 soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit, 7104 &quality_control_entry, QSIZE_SCALING_FACTORf, 7105 add_info->dynamic_scaling_factor[i] & hw_mask); 7106 SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_QUALITY_CONTROLm(unit, 7107 MEM_BLOCK_ALL, member_id_array[i], 7108 &quality_control_entry)); 7109 } 7110 } 7111 7112 return BCM_E_NONE; 7113 } 7114 7115 /* 7116 * Function: 7117 * _bcm_tr3_hg_dlb_member_free_resource 7118 * Purpose: 7119 * Clear state and free resources associated with a Higig DLB member. 7120 * Parameters: 7121 * unit - (IN) SOC unit number. 7122 * member_id - (IN) Member ID. 7123 * Returns: 7124 * BCM_E_xxx 7125 */ 7126 STATIC int 7127 _bcm_tr3_hg_dlb_member_free_resource(int unit, int member_id) 7128 { 7129 dlb_hgt_quality_control_entry_t quality_control_entry; 7130 soc_field_t enable_credit_collect_f; 7131 dlb_hgt_member_attribute_entry_t member_attribute_entry; 7132 int port_num; 7133 7134 /* Disable member quality control */ 7135 SOC_IF_ERROR_RETURN(READ_DLB_HGT_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY, 7136 member_id, &quality_control_entry)); 7137 soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit, 7138 &quality_control_entry, ENABLE_AVG_CALCf, 0); 7139 soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit, 7140 &quality_control_entry, ENABLE_QUALITY_UPDATEf, 0); 7141 enable_credit_collect_f = soc_mem_field_valid(unit, 7142 DLB_HGT_QUALITY_CONTROLm, ENABLE_CREDIT_COLLECTIONf) ? 7143 ENABLE_CREDIT_COLLECTIONf : ENB_CREDIT_COLLECTIONf; 7144 soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit, 7145 &quality_control_entry, enable_credit_collect_f, 0); 7146 soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit, &quality_control_entry, 7147 LOADING_SCALING_FACTORf, 0); 7148 soc_DLB_HGT_QUALITY_CONTROLm_field32_set(unit, &quality_control_entry, 7149 QSIZE_SCALING_FACTORf, 0); 7150 SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_QUALITY_CONTROLm(unit, MEM_BLOCK_ALL, 7151 member_id, &quality_control_entry)); 7152 7153 /* Revert member quality mapping profile to default */ 7154 BCM_IF_ERROR_RETURN 7155 (_bcm_tr3_hg_dlb_member_quality_map_set(unit, member_id, 100)); 7156 7157 /* Clear member attribute entry */ 7158 SOC_IF_ERROR_RETURN(READ_DLB_HGT_MEMBER_ATTRIBUTEm(unit, MEM_BLOCK_ANY, 7159 member_id, &member_attribute_entry)); 7160 port_num = soc_DLB_HGT_MEMBER_ATTRIBUTEm_field32_get(unit, 7161 &member_attribute_entry, PORT_NUMf); 7162 SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_MEMBER_ATTRIBUTEm(unit, MEM_BLOCK_ALL, 7163 member_id, soc_mem_entry_null(unit, DLB_HGT_MEMBER_ATTRIBUTEm))); 7164 7165 /* Clear member map entry */ 7166 SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_PORT_MEMBER_MAPm(unit, MEM_BLOCK_ALL, 7167 port_num, soc_mem_entry_null(unit, DLB_HGT_PORT_MEMBER_MAPm))); 7168 7169 /* Free member ID */ 7170 BCM_IF_ERROR_RETURN(_bcm_tr3_hg_dlb_member_id_free(unit, member_id)); 7171 7172 return BCM_E_NONE; 7173 } 7174 7175 /* 7176 * Function: 7177 * _bcm_tr3_hg_dlb_member_attr_get 7178 * Purpose: 7179 * Get attributes of a Higig DLB member. 7180 * Parameters: 7181 * unit - (IN) SOC unit number. 7182 * port - (IN) Port number of the member. 7183 * scaling_factor - (OUT) Member's scaling factor. 7184 * load_weight - (OUT) Member's load weight. 7185 * Returns: 7186 * BCM_E_xxx 7187 */ 7188 STATIC int 7189 _bcm_tr3_hg_dlb_member_attr_get(int unit, bcm_port_t port, 7190 int *scaling_factor, int *load_weight) 7191 { 7192 dlb_hgt_port_member_map_entry_t port_member_map_entry; 7193 int member_id; 7194 dlb_hgt_quality_control_entry_t quality_control_entry; 7195 soc_field_t profile_ptr_f; 7196 int profile_ptr = 0; 7197 7198 /* Find member ID of the given module and port */ 7199 SOC_IF_ERROR_RETURN(READ_DLB_HGT_PORT_MEMBER_MAPm(unit, MEM_BLOCK_ANY, 7200 port, &port_member_map_entry)); 7201 if (!soc_DLB_HGT_PORT_MEMBER_MAPm_field32_get(unit, &port_member_map_entry, 7202 VALIDf)) { 7203 return BCM_E_NOT_FOUND; 7204 } 7205 member_id = soc_DLB_HGT_PORT_MEMBER_MAPm_field32_get(unit, 7206 &port_member_map_entry, MEMBER_IDf); 7207 7208 /* Get member's scaling factor and load weight */ 7209 SOC_IF_ERROR_RETURN(READ_DLB_HGT_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY, 7210 member_id, &quality_control_entry)); 7211 *scaling_factor = soc_DLB_HGT_QUALITY_CONTROLm_field32_get(unit, 7212 &quality_control_entry, LOADING_SCALING_FACTORf); 7213 profile_ptr_f = soc_mem_field_valid(unit, DLB_HGT_QUALITY_CONTROLm, 7214 PROFILE_PTRf) ? PROFILE_PTRf : QMT_PROFILE_PTRf; 7215 profile_ptr = soc_DLB_HGT_QUALITY_CONTROLm_field32_get(unit, 7216 &quality_control_entry, profile_ptr_f); 7217 *load_weight = HG_DLB_INFO(unit)->hg_dlb_load_weight[profile_ptr]; 7218 7219 return BCM_E_NONE; 7220 } 7221 7222 #endif /* BCM_TRIUMPH3_SUPPORT */ 7223 7224 /* 7225 * Function: 7226 * _bcm_trident_hg_dlb_dynamic_size_encode 7227 * Purpose: 7228 * Encode Higig trunk dynamic load balancing flow set size. 7229 * Parameters: 7230 * dynamic_size - (IN) Number of flow sets. 7231 * encoded_value - (OUT) Encoded value. 7232 * Returns: 7233 * BCM_E_xxx 7234 */ 7235 STATIC int 7236 _bcm_trident_hg_dlb_dynamic_size_encode(int dynamic_size, 7237 int *encoded_value) 7238 { 7239 switch (dynamic_size) { 7240 case 512: 7241 *encoded_value = 1; 7242 break; 7243 case 1024: 7244 *encoded_value = 2; 7245 break; 7246 case 2048: 7247 *encoded_value = 3; 7248 break; 7249 case 4096: 7250 *encoded_value = 4; 7251 break; 7252 case 8192: 7253 *encoded_value = 5; 7254 break; 7255 case 16384: 7256 *encoded_value = 6; 7257 break; 7258 case 32768: 7259 *encoded_value = 7; 7260 break; 7261 default: 7262 return BCM_E_PARAM; 7263 } 7264 7265 return BCM_E_NONE; 7266 } 7267 7268 /* 7269 * Function: 7270 * _bcm_trident_hg_dlb_dynamic_size_decode 7271 * Purpose: 7272 * Decode Higig trunk dynamic load balancing flow set size. 7273 * Parameters: 7274 * encoded_value - (IN) Encoded value. 7275 * dynamic_size - (OUT) Number of flow sets. 7276 * Returns: 7277 * BCM_E_xxx 7278 */ 7279 STATIC int 7280 _bcm_trident_hg_dlb_dynamic_size_decode(int encoded_value, 7281 int *dynamic_size) 7282 { 7283 switch (encoded_value) { 7284 case 1: 7285 *dynamic_size = 512; 7286 break; 7287 case 2: 7288 *dynamic_size = 1024; 7289 break; 7290 case 3: 7291 *dynamic_size = 2048; 7292 break; 7293 case 4: 7294 *dynamic_size = 4096; 7295 break; 7296 case 5: 7297 *dynamic_size = 8192; 7298 break; 7299 case 6: 7300 *dynamic_size = 16384; 7301 break; 7302 case 7: 7303 *dynamic_size = 32768; 7304 break; 7305 default: 7306 return BCM_E_INTERNAL; 7307 } 7308 7309 return BCM_E_NONE; 7310 } 7311 7312 /* 7313 * Function: 7314 * _bcm_trident_hg_dlb_free_resource 7315 * Purpose: 7316 * Free resources for a Higig dynamic load balancing group. 7317 * Parameters: 7318 * unit - (IN) SOC unit number. 7319 * hgtid - (IN) Higig group ID. 7320 * Returns: 7321 * BCM_E_xxx 7322 */ 7323 STATIC int 7324 _bcm_trident_hg_dlb_free_resource(int unit, int hgtid) 7325 { 7326 int rv = BCM_E_NONE; 7327 hgt_dlb_control_entry_t hgt_dlb_control_entry; 7328 int dlb_enable, dlb_id; 7329 dlb_hgt_group_control_entry_t dlb_hgt_group_control_entry; 7330 int entry_base_ptr; 7331 int flow_set_size; 7332 int num_entries; 7333 int block_base_ptr; 7334 int num_blocks; 7335 7336 #ifdef BCM_TRIDENT2_SUPPORT 7337 if (soc_feature(unit, soc_feature_hg_dlb_id_equal_hg_tid)) { 7338 SOC_IF_ERROR_RETURN(READ_DLB_HGT_GROUP_CONTROLm(unit, MEM_BLOCK_ANY, 7339 hgtid, &dlb_hgt_group_control_entry)); 7340 dlb_enable = soc_DLB_HGT_GROUP_CONTROLm_field32_get(unit, 7341 &dlb_hgt_group_control_entry, GROUP_ENABLEf); 7342 dlb_id = hgtid; 7343 } else 7344 #endif /* BCM_TRIDENT2_SUPPORT */ 7345 { 7346 SOC_IF_ERROR_RETURN(READ_HGT_DLB_CONTROLm(unit, MEM_BLOCK_ANY, hgtid, 7347 &hgt_dlb_control_entry)); 7348 dlb_enable = soc_HGT_DLB_CONTROLm_field32_get(unit, 7349 &hgt_dlb_control_entry, GROUP_ENABLEf); 7350 dlb_id = soc_HGT_DLB_CONTROLm_field32_get(unit, 7351 &hgt_dlb_control_entry, DLB_IDf); 7352 } 7353 if (!dlb_enable) { 7354 return BCM_E_NONE; 7355 } 7356 7357 /* Clear ENHANCED_HASHING_ENABLE in HG_TRUNK_GROUP */ 7358 #ifdef BCM_TRIDENT2_SUPPORT 7359 if (soc_mem_field_valid(unit, HG_TRUNK_GROUPm, ENHANCED_HASHING_ENABLEf)) { 7360 hg_trunk_group_entry_t hg_trunk_group_entry; 7361 7362 SOC_IF_ERROR_RETURN(READ_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, hgtid, 7363 &hg_trunk_group_entry)); 7364 soc_HG_TRUNK_GROUPm_field32_set(unit, &hg_trunk_group_entry, 7365 ENHANCED_HASHING_ENABLEf, 0); 7366 SOC_IF_ERROR_RETURN(WRITE_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, hgtid, 7367 &hg_trunk_group_entry)); 7368 } 7369 #endif /* BCM_TRIDENT2_SUPPORT */ 7370 7371 /* Clear HGT_DLB_CONTROL entry */ 7372 if (soc_mem_is_valid(unit, HGT_DLB_CONTROLm)) { 7373 SOC_IF_ERROR_RETURN(WRITE_HGT_DLB_CONTROLm(unit, MEM_BLOCK_ALL, hgtid, 7374 soc_mem_entry_null(unit, HGT_DLB_CONTROLm))); 7375 } 7376 7377 /* Clear DLB_HGT_GROUP_CONTROL entry */ 7378 SOC_IF_ERROR_RETURN(READ_DLB_HGT_GROUP_CONTROLm(unit, MEM_BLOCK_ANY, dlb_id, 7379 &dlb_hgt_group_control_entry)); 7380 entry_base_ptr = soc_DLB_HGT_GROUP_CONTROLm_field32_get(unit, 7381 &dlb_hgt_group_control_entry, FLOW_SET_BASEf); 7382 flow_set_size = soc_DLB_HGT_GROUP_CONTROLm_field32_get(unit, 7383 &dlb_hgt_group_control_entry, FLOW_SET_SIZEf); 7384 SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_GROUP_CONTROLm(unit, MEM_BLOCK_ALL, 7385 dlb_id, soc_mem_entry_null(unit, DLB_HGT_GROUP_CONTROLm))); 7386 7387 if (SOC_MEM_IS_VALID(unit, DLB_HGT_GROUP_CONTROL_Xm)) { 7388 SOC_IF_ERROR_RETURN( 7389 WRITE_DLB_HGT_GROUP_CONTROL_Xm( 7390 unit, MEM_BLOCK_ALL, dlb_id, 7391 soc_mem_entry_null(unit, DLB_HGT_GROUP_CONTROL_Xm))); 7392 } 7393 7394 if (SOC_MEM_IS_VALID(unit, DLB_HGT_GROUP_CONTROL_Ym)) { 7395 SOC_IF_ERROR_RETURN( 7396 WRITE_DLB_HGT_GROUP_CONTROL_Ym( 7397 unit, MEM_BLOCK_ALL, dlb_id, 7398 soc_mem_entry_null(unit, DLB_HGT_GROUP_CONTROL_Ym))); 7399 } 7400 7401 /* Free flow set table resources */ 7402 BCM_IF_ERROR_RETURN 7403 (_bcm_trident_hg_dlb_dynamic_size_decode(flow_set_size, &num_entries)); 7404 block_base_ptr = entry_base_ptr >> 9; 7405 num_blocks = num_entries >> 9; 7406 _BCM_HG_DLB_FLOWSET_BLOCK_USED_CLR_RANGE(unit, block_base_ptr, num_blocks); 7407 7408 #ifdef BCM_TRIUMPH3_SUPPORT 7409 if (soc_feature(unit, soc_feature_hg_dlb_member_id)) { 7410 dlb_hgt_group_membership_entry_t dlb_hgt_group_membership_entry; 7411 int member_bitmap_width, alloc_size; 7412 int i; 7413 SHR_BITDCL *member_bitmap = NULL; 7414 SHR_BITDCL *status_bitmap = NULL; 7415 SHR_BITDCL *override_bitmap = NULL; 7416 dlb_hgt_member_sw_state_entry_t dlb_hgt_member_sw_state_entry; 7417 7418 /* Get membership and clear each member's state */ 7419 SOC_IF_ERROR_RETURN(READ_DLB_HGT_GROUP_MEMBERSHIPm(unit, MEM_BLOCK_ANY, 7420 dlb_id, &dlb_hgt_group_membership_entry)); 7421 member_bitmap_width = soc_mem_field_length(unit, 7422 DLB_HGT_GROUP_MEMBERSHIPm, MEMBER_BITMAPf); 7423 alloc_size = SHR_BITALLOCSIZE(member_bitmap_width); 7424 member_bitmap = sal_alloc(alloc_size, "DLB HGT member bitmap"); 7425 if (NULL == member_bitmap) { 7426 return BCM_E_MEMORY; 7427 } 7428 soc_DLB_HGT_GROUP_MEMBERSHIPm_field_get(unit, 7429 &dlb_hgt_group_membership_entry, MEMBER_BITMAPf, member_bitmap); 7430 for (i = 0; i < member_bitmap_width; i++) { 7431 if (SHR_BITGET(member_bitmap, i)) { 7432 rv = _bcm_tr3_hg_dlb_member_free_resource(unit, i); 7433 if (BCM_FAILURE(rv)) { 7434 sal_free(member_bitmap); 7435 return rv; 7436 } 7437 } 7438 } 7439 7440 /* Clear member software state */ 7441 rv = READ_DLB_HGT_MEMBER_SW_STATEm(unit, MEM_BLOCK_ANY, 0, 7442 &dlb_hgt_member_sw_state_entry); 7443 if (BCM_FAILURE(rv)) { 7444 sal_free(member_bitmap); 7445 return rv; 7446 } 7447 7448 status_bitmap = sal_alloc(alloc_size, "DLB HGT member status bitmap"); 7449 if (NULL == status_bitmap) { 7450 sal_free(member_bitmap); 7451 return BCM_E_MEMORY; 7452 } 7453 soc_DLB_HGT_MEMBER_SW_STATEm_field_get(unit, 7454 &dlb_hgt_member_sw_state_entry, MEMBER_BITMAPf, status_bitmap); 7455 SHR_BITREMOVE_RANGE(status_bitmap, member_bitmap, 0, member_bitmap_width, 7456 status_bitmap); 7457 soc_DLB_HGT_MEMBER_SW_STATEm_field_set(unit, 7458 &dlb_hgt_member_sw_state_entry, MEMBER_BITMAPf, status_bitmap); 7459 7460 override_bitmap = sal_alloc(alloc_size, "DLB HGT member override bitmap"); 7461 if (NULL == override_bitmap) { 7462 sal_free(member_bitmap); 7463 sal_free(status_bitmap); 7464 return BCM_E_MEMORY; 7465 } 7466 soc_DLB_HGT_MEMBER_SW_STATEm_field_get(unit, 7467 &dlb_hgt_member_sw_state_entry, OVERRIDE_MEMBER_BITMAPf, override_bitmap); 7468 SHR_BITREMOVE_RANGE(override_bitmap, member_bitmap, 0, member_bitmap_width, 7469 override_bitmap); 7470 soc_DLB_HGT_MEMBER_SW_STATEm_field_set(unit, 7471 &dlb_hgt_member_sw_state_entry, OVERRIDE_MEMBER_BITMAPf, override_bitmap); 7472 7473 rv = WRITE_DLB_HGT_MEMBER_SW_STATEm(unit, MEM_BLOCK_ALL, 0, 7474 &dlb_hgt_member_sw_state_entry); 7475 sal_free(member_bitmap); 7476 sal_free(status_bitmap); 7477 sal_free(override_bitmap); 7478 if (BCM_FAILURE(rv)) { 7479 return rv; 7480 } 7481 7482 /* Clear group membership */ 7483 SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_GROUP_MEMBERSHIPm(unit, 7484 MEM_BLOCK_ALL, dlb_id, soc_mem_entry_null(unit, 7485 DLB_HGT_GROUP_MEMBERSHIPm))); 7486 } else 7487 #endif /* BCM_TRIUMPH3_SUPPORT */ 7488 { 7489 dlb_hgt_group_membership_entry_t dlb_hgt_group_membership_entry; 7490 bcm_pbmp_t port_map, negated_port_map; 7491 bcm_port_t port; 7492 uint32 quantize_control; 7493 uint32 measure_update_control; 7494 dlb_hgt_link_control_entry_t dlb_hgt_link_control_entry; 7495 bcm_pbmp_t sw_port_state, override_port_map; 7496 7497 SOC_IF_ERROR_RETURN(READ_DLB_HGT_GROUP_MEMBERSHIPm(unit, MEM_BLOCK_ANY, 7498 dlb_id, &dlb_hgt_group_membership_entry)); 7499 soc_mem_pbmp_field_get(unit, DLB_HGT_GROUP_MEMBERSHIPm, 7500 &dlb_hgt_group_membership_entry, PORT_MAPf, &port_map); 7501 BCM_PBMP_ITER(port_map, port) { 7502 /* Disable quality measure update */ 7503 SOC_IF_ERROR_RETURN 7504 (READ_DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr(unit, 7505 port, &measure_update_control)); 7506 soc_reg_field_set(unit, DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr, 7507 &measure_update_control, ENABLE_MEASURE_COLLECTIONf, 0); 7508 soc_reg_field_set(unit, DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr, 7509 &measure_update_control, ENABLE_MEASURE_AVERAGE_CALCULATIONf, 0); 7510 soc_reg_field_set(unit, DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr, 7511 &measure_update_control, ENABLE_PORT_QUALITY_UPDATEf, 0); 7512 SOC_IF_ERROR_RETURN 7513 (WRITE_DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr(unit, 7514 port, measure_update_control)); 7515 7516 /* Revert member quality mapping profile to default */ 7517 BCM_IF_ERROR_RETURN 7518 (_bcm_trident_hg_dlb_quality_map_set(unit, port, 100)); 7519 7520 /* Clear threshold scaling factors */ 7521 SOC_IF_ERROR_RETURN(READ_DLB_HGT_QUANTIZE_CONTROLr(unit, port, 7522 &quantize_control)); 7523 soc_reg_field_set(unit, DLB_HGT_QUANTIZE_CONTROLr, 7524 &quantize_control, PORT_LOADING_THRESHOLD_SCALING_FACTORf, 0); 7525 soc_reg_field_set(unit, DLB_HGT_QUANTIZE_CONTROLr, 7526 &quantize_control, PORT_QSIZE_THRESHOLD_SCALING_FACTORf, 0); 7527 SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_QUANTIZE_CONTROLr(unit, port, 7528 quantize_control)); 7529 } 7530 7531 /* Clear member software state */ 7532 SOC_IF_ERROR_RETURN(READ_DLB_HGT_LINK_CONTROLm(unit, MEM_BLOCK_ANY, 7533 0, &dlb_hgt_link_control_entry)); 7534 7535 soc_mem_pbmp_field_get(unit, DLB_HGT_LINK_CONTROLm, 7536 &dlb_hgt_link_control_entry, SW_PORT_STATEf, &sw_port_state); 7537 BCM_PBMP_NEGATE(negated_port_map, port_map); 7538 BCM_PBMP_AND(sw_port_state, negated_port_map); 7539 soc_mem_pbmp_field_set(unit, DLB_HGT_LINK_CONTROLm, 7540 &dlb_hgt_link_control_entry, SW_PORT_STATEf, &sw_port_state); 7541 7542 soc_mem_pbmp_field_get(unit, DLB_HGT_LINK_CONTROLm, 7543 &dlb_hgt_link_control_entry, SW_OVERRIDE_PORT_MAPf, 7544 &override_port_map); 7545 BCM_PBMP_AND(override_port_map, negated_port_map); 7546 soc_mem_pbmp_field_set(unit, DLB_HGT_LINK_CONTROLm, 7547 &dlb_hgt_link_control_entry, SW_OVERRIDE_PORT_MAPf, 7548 &override_port_map); 7549 7550 SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_LINK_CONTROLm(unit, MEM_BLOCK_ALL, 7551 0, &dlb_hgt_link_control_entry)); 7552 7553 /* Clear group membership */ 7554 SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_GROUP_MEMBERSHIPm(unit, 7555 MEM_BLOCK_ALL, dlb_id, soc_mem_entry_null(unit, 7556 DLB_HGT_GROUP_MEMBERSHIPm))); 7557 } 7558 7559 /* Free DLB ID */ 7560 BCM_IF_ERROR_RETURN(_bcm_trident_hg_dlb_id_free(unit, dlb_id)); 7561 7562 return rv; 7563 } 7564 7565 /* 7566 * Function: 7567 * _bcm_trident_hg_dlb_set 7568 * Purpose: 7569 * Configure a Higig dynamic load balancing group. 7570 * Parameters: 7571 * unit - (IN) SOC unit number. 7572 * hgtid - (IN) Higig trunk group ID. 7573 * add_info - (IN) Pointer to trunk add info structure. 7574 * Returns: 7575 * BCM_E_xxx 7576 */ 7577 STATIC int 7578 _bcm_trident_hg_dlb_set(int unit, 7579 int hgtid, 7580 _esw_trunk_add_info_t *add_info) 7581 { 7582 int dlb_enable; 7583 int dlb_id; 7584 int num_blocks; 7585 int total_blocks; 7586 int max_block_base_ptr; 7587 int block_base_ptr; 7588 SHR_BITDCL occupied; 7589 int entry_base_ptr; 7590 int num_entries_per_block; 7591 int alloc_size; 7592 uint32 *block_ptr = NULL; 7593 int i, k, m; 7594 int index_min, index_max; 7595 int rv = BCM_E_NONE; 7596 dlb_hgt_group_control_entry_t dlb_hgt_group_control_entry; 7597 int flow_set_size; 7598 int dlb_mode; 7599 hgt_dlb_control_entry_t hgt_dlb_control_entry; 7600 int *member_id_array = NULL; 7601 soc_mem_t flowset_mem[3] = {INVALIDm, INVALIDm, INVALIDm}; 7602 int flowset_entry_size; 7603 SHR_BITDCL *member_bitmap = NULL; 7604 SHR_BITDCL *override_bitmap = NULL; 7605 7606 dlb_enable = (add_info->psc == BCM_TRUNK_PSC_DYNAMIC) || 7607 (add_info->psc == BCM_TRUNK_PSC_DYNAMIC_ASSIGNED) || 7608 (add_info->psc == BCM_TRUNK_PSC_DYNAMIC_OPTIMAL); 7609 if (!dlb_enable) { 7610 return BCM_E_NONE; 7611 } 7612 7613 /* Allocate a free DLB ID */ 7614 BCM_IF_ERROR_RETURN(_bcm_trident_hg_dlb_id_alloc(unit, hgtid, &dlb_id)); 7615 7616 #ifdef BCM_TRIUMPH3_SUPPORT 7617 if (soc_feature(unit, soc_feature_hg_dlb_member_id)) { 7618 int member_bitmap_width; 7619 dlb_hgt_group_membership_entry_t dlb_hgt_group_membership_entry; 7620 dlb_hgt_member_sw_state_entry_t dlb_hgt_member_sw_state_entry; 7621 7622 /* Allocate member IDs */ 7623 member_id_array = sal_alloc(sizeof(int) * add_info->num_ports, 7624 "Higig DLB Member IDs"); 7625 if (NULL == member_id_array) { 7626 rv = BCM_E_MEMORY; 7627 goto error; 7628 } 7629 rv = _bcm_tr3_hg_dlb_member_array_alloc(unit, add_info, 7630 member_id_array); 7631 if (BCM_FAILURE(rv)) { 7632 goto error; 7633 } 7634 7635 /* Set group membership */ 7636 member_bitmap_width = soc_mem_field_length(unit, 7637 DLB_HGT_GROUP_MEMBERSHIPm, MEMBER_BITMAPf); 7638 alloc_size = SHR_BITALLOCSIZE(member_bitmap_width); 7639 member_bitmap = sal_alloc(alloc_size, "DLB HGT member bitmap"); 7640 if (NULL == member_bitmap) { 7641 rv = BCM_E_MEMORY; 7642 goto error; 7643 } 7644 sal_memset(member_bitmap, 0, alloc_size); 7645 for (i = 0; i < add_info->num_ports; i++) { 7646 SHR_BITSET(member_bitmap, member_id_array[i]); 7647 } 7648 sal_memset(&dlb_hgt_group_membership_entry, 0, 7649 sizeof(dlb_hgt_group_membership_entry_t)); 7650 soc_DLB_HGT_GROUP_MEMBERSHIPm_field_set(unit, 7651 &dlb_hgt_group_membership_entry, MEMBER_BITMAPf, member_bitmap); 7652 rv = WRITE_DLB_HGT_GROUP_MEMBERSHIPm(unit, MEM_BLOCK_ALL, dlb_id, 7653 &dlb_hgt_group_membership_entry); 7654 if (BCM_FAILURE(rv)) { 7655 goto error; 7656 } 7657 7658 /* Disable member state software override */ 7659 rv = READ_DLB_HGT_MEMBER_SW_STATEm(unit, MEM_BLOCK_ANY, 7660 0, &dlb_hgt_member_sw_state_entry); 7661 if (BCM_FAILURE(rv)) { 7662 goto error; 7663 } 7664 override_bitmap = sal_alloc(alloc_size, "DLB HGT member override bitmap"); 7665 if (NULL == override_bitmap) { 7666 rv = BCM_E_MEMORY; 7667 goto error; 7668 } 7669 soc_DLB_HGT_MEMBER_SW_STATEm_field_get(unit, 7670 &dlb_hgt_member_sw_state_entry, OVERRIDE_MEMBER_BITMAPf, 7671 override_bitmap); 7672 SHR_BITREMOVE_RANGE(override_bitmap, member_bitmap, 0, member_bitmap_width, 7673 override_bitmap); 7674 soc_DLB_HGT_MEMBER_SW_STATEm_field_set(unit, 7675 &dlb_hgt_member_sw_state_entry, OVERRIDE_MEMBER_BITMAPf, 7676 override_bitmap); 7677 rv = WRITE_DLB_HGT_MEMBER_SW_STATEm(unit, MEM_BLOCK_ALL, 7678 0, &dlb_hgt_member_sw_state_entry); 7679 if (BCM_FAILURE(rv)) { 7680 goto error; 7681 } 7682 } else 7683 #endif /* BCM_TRIUMPH3_SUPPORT */ 7684 { 7685 uint32 quantize_control; 7686 uint32 measure_update_control; 7687 dlb_hgt_group_membership_entry_t dlb_hgt_group_membership_entry; 7688 bcm_pbmp_t port_map, negated_port_map, override_port_map; 7689 dlb_hgt_link_control_entry_t dlb_hgt_link_control_entry; 7690 7691 BCM_PBMP_CLEAR(port_map); 7692 for (i = 0; i < add_info->num_ports; i++) { 7693 /* Set port quality mapping profile */ 7694 rv = _bcm_trident_hg_dlb_quality_map_set(unit, 7695 add_info->tp[i], add_info->dynamic_load_weight[i]); 7696 if (BCM_FAILURE(rv)) { 7697 goto error; 7698 } 7699 7700 /* Set port threshold scaling factors */ 7701 rv = READ_DLB_HGT_QUANTIZE_CONTROLr(unit, add_info->tp[i], 7702 &quantize_control); 7703 if (BCM_FAILURE(rv)) { 7704 goto error; 7705 } 7706 soc_reg_field_set(unit, DLB_HGT_QUANTIZE_CONTROLr, 7707 &quantize_control, PORT_LOADING_THRESHOLD_SCALING_FACTORf, 7708 add_info->dynamic_scaling_factor[i]); 7709 soc_reg_field_set(unit, DLB_HGT_QUANTIZE_CONTROLr, 7710 &quantize_control, PORT_QSIZE_THRESHOLD_SCALING_FACTORf, 7711 add_info->dynamic_scaling_factor[i]); 7712 rv = WRITE_DLB_HGT_QUANTIZE_CONTROLr(unit, add_info->tp[i], 7713 quantize_control); 7714 if (BCM_FAILURE(rv)) { 7715 goto error; 7716 } 7717 7718 /* Enable quality measure update */ 7719 rv = READ_DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr(unit, 7720 add_info->tp[i], &measure_update_control); 7721 if (BCM_FAILURE(rv)) { 7722 goto error; 7723 } 7724 soc_reg_field_set(unit, DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr, 7725 &measure_update_control, ENABLE_MEASURE_COLLECTIONf, 1); 7726 soc_reg_field_set(unit, DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr, 7727 &measure_update_control, ENABLE_MEASURE_AVERAGE_CALCULATIONf, 1); 7728 soc_reg_field_set(unit, DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr, 7729 &measure_update_control, ENABLE_PORT_QUALITY_UPDATEf, 1); 7730 rv = WRITE_DLB_HGT_PORT_QUALITY_MEASURE_UPDATE_CONTROLr(unit, 7731 add_info->tp[i], measure_update_control); 7732 if (BCM_FAILURE(rv)) { 7733 goto error; 7734 } 7735 7736 /* Set group port bitmap */ 7737 BCM_PBMP_PORT_ADD(port_map, add_info->tp[i]); 7738 } 7739 7740 /* Set group membership */ 7741 sal_memset(&dlb_hgt_group_membership_entry, 0, 7742 sizeof(dlb_hgt_group_membership_entry_t)); 7743 soc_mem_pbmp_field_set(unit, DLB_HGT_GROUP_MEMBERSHIPm, 7744 &dlb_hgt_group_membership_entry, PORT_MAPf, &port_map); 7745 rv = WRITE_DLB_HGT_GROUP_MEMBERSHIPm(unit, MEM_BLOCK_ALL, dlb_id, 7746 &dlb_hgt_group_membership_entry); 7747 if (BCM_FAILURE(rv)) { 7748 goto error; 7749 } 7750 7751 /* Disable member state software override */ 7752 rv = READ_DLB_HGT_LINK_CONTROLm(unit, MEM_BLOCK_ANY, 0, 7753 &dlb_hgt_link_control_entry); 7754 if (BCM_FAILURE(rv)) { 7755 goto error; 7756 } 7757 soc_mem_pbmp_field_get(unit, DLB_HGT_LINK_CONTROLm, 7758 &dlb_hgt_link_control_entry, SW_OVERRIDE_PORT_MAPf, 7759 &override_port_map); 7760 BCM_PBMP_NEGATE(negated_port_map, port_map); 7761 BCM_PBMP_AND(override_port_map, negated_port_map); 7762 soc_mem_pbmp_field_set(unit, DLB_HGT_LINK_CONTROLm, 7763 &dlb_hgt_link_control_entry, SW_OVERRIDE_PORT_MAPf, 7764 &override_port_map); 7765 rv = WRITE_DLB_HGT_LINK_CONTROLm(unit, MEM_BLOCK_ALL, 0, 7766 &dlb_hgt_link_control_entry); 7767 if (BCM_FAILURE(rv)) { 7768 goto error; 7769 } 7770 } 7771 7772 /* Find a contiguous region of flow set table that's large 7773 * enough to hold the requested number of flow sets. 7774 * The flow set table is allocated in 512-entry blocks. 7775 */ 7776 m = 0; 7777 #ifdef BCM_TRIUMPH3_SUPPORT 7778 if (soc_feature(unit, soc_feature_hg_dlb_member_id)) { 7779 flowset_mem[m++] = DLB_HGT_FLOWSETm; 7780 if (soc_mem_is_valid(unit, DLB_HGT_FLOWSET_Xm) 7781 && soc_mem_is_valid(unit, DLB_HGT_FLOWSET_Ym)) { 7782 flowset_mem[m++] = DLB_HGT_FLOWSET_Xm; 7783 flowset_mem[m] = DLB_HGT_FLOWSET_Ym; 7784 } else { 7785 flowset_mem[m] = flowset_mem[0]; 7786 } 7787 flowset_entry_size = sizeof(dlb_hgt_flowset_entry_t); 7788 } else 7789 #endif /* BCM_TRIUMPH3_SUPPORT */ 7790 { 7791 flowset_mem[m++] = DLB_HGT_FLOWSET_PORTm; 7792 if (soc_mem_is_valid(unit, DLB_HGT_FLOWSET_PORT_Xm) 7793 && soc_mem_is_valid(unit, DLB_HGT_FLOWSET_PORT_Ym)) { 7794 flowset_mem[m++] = DLB_HGT_FLOWSET_PORT_Xm; 7795 flowset_mem[m] = DLB_HGT_FLOWSET_PORT_Ym; 7796 } else { 7797 flowset_mem[m] = flowset_mem[0]; 7798 } 7799 flowset_entry_size = sizeof(dlb_hgt_flowset_port_entry_t); 7800 } 7801 num_blocks = add_info->dynamic_size >> 9; 7802 total_blocks = soc_mem_index_count(unit, flowset_mem[0]) >> 9; 7803 max_block_base_ptr = total_blocks - num_blocks; 7804 for (block_base_ptr = 0; 7805 block_base_ptr <= max_block_base_ptr; 7806 block_base_ptr++) { 7807 /* Check if the contiguous region of flow set table from 7808 * block_base_ptr to (block_base_ptr + num_blocks - 1) is free. 7809 */ 7810 _BCM_HG_DLB_FLOWSET_BLOCK_TEST_RANGE(unit, block_base_ptr, num_blocks, 7811 occupied); 7812 if (!occupied) { 7813 break; 7814 } 7815 } 7816 if (block_base_ptr > max_block_base_ptr) { 7817 /* A contiguous region of the desired size could not be found in 7818 * flow set table. 7819 */ 7820 rv = BCM_E_RESOURCE; 7821 goto error; 7822 } 7823 7824 /* Configure flow set table */ 7825 entry_base_ptr = block_base_ptr << 9; 7826 num_entries_per_block = 512; 7827 alloc_size = num_entries_per_block * flowset_entry_size; 7828 block_ptr = soc_cm_salloc(unit, alloc_size, 7829 "Block of DLB_HGT_FLOWSET entries"); 7830 if (NULL == block_ptr) { 7831 rv = BCM_E_MEMORY; 7832 goto error; 7833 } 7834 sal_memset(block_ptr, 0, alloc_size); 7835 for (i = 0; i < num_blocks; i++) { 7836 for (k = 0; k < num_entries_per_block; k++) { 7837 #ifdef BCM_TRIUMPH3_SUPPORT 7838 if (soc_feature(unit, soc_feature_hg_dlb_member_id)) { 7839 dlb_hgt_flowset_entry_t *flowset_entry; 7840 7841 flowset_entry = soc_mem_table_idx_to_pointer(unit, 7842 DLB_HGT_FLOWSETm, dlb_hgt_flowset_entry_t *, 7843 block_ptr, k); 7844 soc_DLB_HGT_FLOWSETm_field32_set(unit, flowset_entry, VALIDf, 1); 7845 soc_DLB_HGT_FLOWSETm_field32_set(unit, flowset_entry, MEMBER_IDf, 7846 member_id_array[(i * num_entries_per_block + k) 7847 % add_info->num_ports]); 7848 } else 7849 #endif /* BCM_TRIUMPH3_SUPPORT */ 7850 { 7851 dlb_hgt_flowset_port_entry_t *flowset_port_entry; 7852 7853 flowset_port_entry = soc_mem_table_idx_to_pointer(unit, 7854 DLB_HGT_FLOWSET_PORTm, dlb_hgt_flowset_port_entry_t *, 7855 block_ptr, k); 7856 soc_DLB_HGT_FLOWSET_PORTm_field32_set(unit, flowset_port_entry, 7857 VALIDf, 1); 7858 soc_DLB_HGT_FLOWSET_PORTm_field32_set(unit, flowset_port_entry, 7859 PORT_NUMf, add_info->tp[(i * num_entries_per_block + k) 7860 % add_info->num_ports]); 7861 } 7862 } 7863 index_min = entry_base_ptr + i * num_entries_per_block; 7864 index_max = index_min + num_entries_per_block - 1; 7865 for (m = 1; m < 3; m++) { 7866 if (flowset_mem[m] == INVALIDm) { 7867 continue; 7868 } 7869 rv = soc_mem_write_range(unit, flowset_mem[m], MEM_BLOCK_ALL, 7870 index_min, index_max, block_ptr); 7871 if (SOC_FAILURE(rv)) { 7872 goto error; 7873 } 7874 } 7875 } 7876 _BCM_HG_DLB_FLOWSET_BLOCK_USED_SET_RANGE(unit, block_base_ptr, num_blocks); 7877 7878 /* Update Higig DLB group control table */ 7879 sal_memset(&dlb_hgt_group_control_entry, 0, 7880 sizeof(dlb_hgt_group_control_entry_t)); 7881 #ifdef BCM_TRIDENT2_SUPPORT 7882 if (soc_mem_field_valid(unit, DLB_HGT_GROUP_CONTROLm, GROUP_ENABLEf)) { 7883 soc_DLB_HGT_GROUP_CONTROLm_field32_set(unit, &dlb_hgt_group_control_entry, 7884 GROUP_ENABLEf, 1); 7885 } 7886 #endif /* BCM_TRIDENT2_SUPPORT */ 7887 soc_DLB_HGT_GROUP_CONTROLm_field32_set(unit, &dlb_hgt_group_control_entry, 7888 ENABLE_OPTIMAL_CANDIDATE_UPDATEf, 1); 7889 soc_DLB_HGT_GROUP_CONTROLm_field32_set(unit, &dlb_hgt_group_control_entry, 7890 FLOW_SET_BASEf, entry_base_ptr); 7891 7892 rv = _bcm_trident_hg_dlb_dynamic_size_encode(add_info->dynamic_size, 7893 &flow_set_size); 7894 if (SOC_FAILURE(rv)) { 7895 goto error; 7896 } 7897 soc_DLB_HGT_GROUP_CONTROLm_field32_set(unit, &dlb_hgt_group_control_entry, 7898 FLOW_SET_SIZEf, flow_set_size); 7899 7900 switch (add_info->psc) { 7901 case BCM_TRUNK_PSC_DYNAMIC: 7902 dlb_mode = 0; 7903 break; 7904 case BCM_TRUNK_PSC_DYNAMIC_ASSIGNED: 7905 dlb_mode = 1; 7906 break; 7907 case BCM_TRUNK_PSC_DYNAMIC_OPTIMAL: 7908 dlb_mode = 2; 7909 break; 7910 default: 7911 rv = BCM_E_PARAM; 7912 goto error; 7913 } 7914 #ifdef BCM_TRIUMPH3_SUPPORT 7915 if (soc_mem_field_valid(unit, DLB_HGT_GROUP_CONTROLm, 7916 MEMBER_ASSIGNMENT_MODEf)) { 7917 soc_DLB_HGT_GROUP_CONTROLm_field32_set(unit, 7918 &dlb_hgt_group_control_entry, 7919 MEMBER_ASSIGNMENT_MODEf, dlb_mode); 7920 } else 7921 #endif /* BCM_TRIUMPH3_SUPPORT */ 7922 { 7923 soc_DLB_HGT_GROUP_CONTROLm_field32_set(unit, 7924 &dlb_hgt_group_control_entry, 7925 PORT_ASSIGNMENT_MODEf, dlb_mode); 7926 } 7927 7928 soc_DLB_HGT_GROUP_CONTROLm_field32_set(unit, &dlb_hgt_group_control_entry, 7929 INACTIVITY_DURATIONf, add_info->dynamic_age); 7930 7931 rv = WRITE_DLB_HGT_GROUP_CONTROLm(unit, MEM_BLOCK_ALL, dlb_id, 7932 &dlb_hgt_group_control_entry); 7933 if (SOC_FAILURE(rv)) { 7934 goto error; 7935 } 7936 7937 if (SOC_MEM_IS_VALID(unit, DLB_HGT_GROUP_CONTROL_Xm)) { 7938 rv = WRITE_DLB_HGT_GROUP_CONTROL_Xm(unit, MEM_BLOCK_ALL, dlb_id, 7939 &dlb_hgt_group_control_entry); 7940 if (SOC_FAILURE(rv)) { 7941 goto error; 7942 } 7943 } 7944 if (SOC_MEM_IS_VALID(unit, DLB_HGT_GROUP_CONTROL_Ym)) { 7945 rv = WRITE_DLB_HGT_GROUP_CONTROL_Ym(unit, MEM_BLOCK_ALL, dlb_id, 7946 &dlb_hgt_group_control_entry); 7947 if (SOC_FAILURE(rv)) { 7948 goto error; 7949 } 7950 } 7951 7952 /* Update Higig DLB control table */ 7953 if (soc_mem_is_valid(unit, HGT_DLB_CONTROLm)) { 7954 sal_memset(&hgt_dlb_control_entry, 0, sizeof(hgt_dlb_control_entry_t)); 7955 soc_HGT_DLB_CONTROLm_field32_set 7956 (unit, &hgt_dlb_control_entry, DLB_IDf, dlb_id); 7957 soc_HGT_DLB_CONTROLm_field32_set 7958 (unit, &hgt_dlb_control_entry, GROUP_ENABLEf, 1); 7959 rv = WRITE_HGT_DLB_CONTROLm(unit, MEM_BLOCK_ALL, hgtid, 7960 &hgt_dlb_control_entry); 7961 if (SOC_FAILURE(rv)) { 7962 goto error; 7963 } 7964 } 7965 7966 /* Update HG_TRUNK_GROUP */ 7967 #ifdef BCM_TRIDENT2_SUPPORT 7968 if (soc_mem_field_valid(unit, HG_TRUNK_GROUPm, ENHANCED_HASHING_ENABLEf)) { 7969 hg_trunk_group_entry_t hg_trunk_group_entry; 7970 7971 rv = READ_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, hgtid, 7972 &hg_trunk_group_entry); 7973 if (SOC_FAILURE(rv)) { 7974 goto error; 7975 } 7976 soc_HG_TRUNK_GROUPm_field32_set(unit, &hg_trunk_group_entry, 7977 ENHANCED_HASHING_ENABLEf, 1); 7978 rv = WRITE_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, hgtid, 7979 &hg_trunk_group_entry); 7980 if (SOC_FAILURE(rv)) { 7981 goto error; 7982 } 7983 } 7984 #endif /* BCM_TRIDENT2_SUPPORT */ 7985 7986 error: 7987 if (NULL != member_id_array) { 7988 sal_free(member_id_array); 7989 } 7990 if (NULL != member_bitmap) { 7991 sal_free(member_bitmap); 7992 } 7993 if (NULL != override_bitmap) { 7994 sal_free(override_bitmap); 7995 } 7996 if (NULL != block_ptr) { 7997 soc_cm_sfree(unit, block_ptr); 7998 } 7999 return rv; 8000 } 8001 8002 /* 8003 * Function: 8004 * _bcm_trident_hg_slb_free_resource 8005 * Purpose: 8006 * Free resources for a Higig static load balancing group. 8007 * Parameters: 8008 * unit - (IN) SOC unit number. 8009 * hgtid - (IN) Higig trunk group ID. 8010 * Returns: 8011 * BCM_E_xxx 8012 */ 8013 STATIC int 8014 _bcm_trident_hg_slb_free_resource(int unit, int hgtid) 8015 { 8016 hg_trunk_group_entry_t hg_trunk_group_entry; 8017 int base_ptr; 8018 int tg_size; 8019 int rtag; 8020 int num_entries; 8021 8022 SOC_IF_ERROR_RETURN 8023 (READ_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, hgtid, 8024 &hg_trunk_group_entry)); 8025 base_ptr = soc_HG_TRUNK_GROUPm_field32_get(unit, 8026 &hg_trunk_group_entry, BASE_PTRf); 8027 tg_size = 1 + soc_HG_TRUNK_GROUPm_field32_get(unit, 8028 &hg_trunk_group_entry, TG_SIZEf); 8029 rtag = soc_HG_TRUNK_GROUPm_field32_get(unit, 8030 &hg_trunk_group_entry, RTAGf); 8031 8032 num_entries = tg_size; 8033 if (rtag >= 1 && rtag <= 6) { 8034 #ifdef BCM_KATANA_SUPPORT 8035 if (SOC_IS_KATANAX(unit)) { 8036 num_entries = _BCM_KATANA_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT; 8037 } else 8038 #endif 8039 if (soc_feature(unit, 8040 soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 8041 num_entries = _BCM_TD_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT; 8042 } 8043 } 8044 8045 _BCM_HG_TRUNK_MEMBER_USED_CLR_RANGE(unit, base_ptr, num_entries); 8046 8047 return BCM_E_NONE; 8048 } 8049 8050 /* 8051 * Function: 8052 * _bcm_trident_hg_slb_set 8053 * Purpose: 8054 * Configure a Higig static load balancing group. 8055 * Parameters: 8056 * unit - (IN) SOC unit number. 8057 * hgtid - (IN) Higig trunk group ID. 8058 * add_info - (IN) Pointer to trunk add info structure. 8059 * t_info - (IN) Pointer to trunk info. 8060 * trunk_flag - (IN) 0: hg trunk; 1: cascaded trunk. 8061 * Returns: 8062 * BCM_E_xxx 8063 */ 8064 STATIC int 8065 _bcm_trident_hg_slb_set(int unit, 8066 int hgtid, 8067 _esw_trunk_add_info_t *add_info, 8068 trunk_private_t *t_info, 8069 int trunk_flag) 8070 { 8071 int num_entries; 8072 int max_base_ptr=0; 8073 int base_ptr; 8074 SHR_BITDCL occupied; 8075 int i; 8076 hg_trunk_member_entry_t hg_trunk_member_entry; 8077 hg_trunk_group_entry_t hg_trunk_group_entry; 8078 #ifdef BCM_TOMAHAWK_SUPPORT 8079 random_rrlb_hg_trunk_member_entry_t random_rrlb_hg_trunk_member_entry; 8080 hg_trunk_mode_entry_t hg_trunk_mode_entry; 8081 hg_trunk_rr_cnt_entry_t rrlb_cnt_entry; 8082 uint16 seed=0; 8083 soc_reg_t reg; 8084 uint32 rval; 8085 int pipe; 8086 #endif 8087 8088 /* Find a contiguous region of HG_TRUNK_MEMBER table that's large 8089 * enough to hold all of the Higig trunk group's member ports. 8090 */ 8091 8092 num_entries = add_info->num_ports; 8093 8094 /* If RTAG is 1-6, Trident A0 and Katana ignore the TG_SIZE field and assume 8095 * the Higig trunk group occupies FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT 8096 * contiguous entries in HG_TRUNK_MEMBER table. 8097 */ 8098 if (t_info->rtag >= 1 && t_info->rtag <= 6) { 8099 #ifdef BCM_KATANA_SUPPORT 8100 if(SOC_IS_KATANAX(unit)) { 8101 num_entries = _BCM_KATANA_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT; 8102 } else 8103 #endif 8104 if (soc_feature(unit, 8105 soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 8106 num_entries = _BCM_TD_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT; 8107 } 8108 } 8109 8110 #ifdef BCM_TOMAHAWK_SUPPORT 8111 if (soc_feature(unit, soc_feature_round_robin_load_balance)) { 8112 if (t_info->psc == BCM_TRUNK_PSC_ROUND_ROBIN) { 8113 base_ptr = 0; 8114 max_base_ptr = soc_mem_index_count(unit, RANDOM_RRLB_HG_TRUNK_MEMBERm) - num_entries; 8115 } else { 8116 base_ptr = soc_mem_index_count(unit, RANDOM_RRLB_HG_TRUNK_MEMBERm); 8117 max_base_ptr = soc_mem_index_count(unit, HG_TRUNK_MEMBERm) - num_entries; 8118 } 8119 } else 8120 #endif 8121 { 8122 base_ptr = 0; 8123 max_base_ptr = soc_mem_index_count(unit, HG_TRUNK_MEMBERm) - num_entries; 8124 } 8125 8126 for (; base_ptr <= max_base_ptr; base_ptr++) { 8127 /* Check if the contiguous region of HG_TRUNK_MEMBERm table from 8128 * index base_ptr to (base_ptr + num_entries - 1) is free. 8129 */ 8130 _BCM_HG_TRUNK_MEMBER_TEST_RANGE(unit, base_ptr, num_entries, occupied); 8131 if (!occupied) { 8132 break; 8133 } 8134 } 8135 8136 #ifdef BCM_TOMAHAWK_SUPPORT 8137 if (soc_feature(unit, soc_feature_round_robin_load_balance) && 8138 t_info->psc != BCM_TRUNK_PSC_ROUND_ROBIN) { 8139 if (base_ptr > max_base_ptr) { 8140 /* start from zero, try again. */ 8141 for (base_ptr = 0; base_ptr <= max_base_ptr; base_ptr++) { 8142 _BCM_HG_TRUNK_MEMBER_TEST_RANGE(unit, base_ptr, num_entries, occupied); 8143 if (!occupied) { 8144 break; 8145 } 8146 } 8147 } 8148 } 8149 #endif 8150 8151 if (base_ptr > max_base_ptr) { 8152 /* A contiguous region of the desired size could not be found in 8153 * HG_TRUNK_MEMBER table. 8154 */ 8155 return BCM_E_RESOURCE; 8156 } 8157 8158 for (i = 0; i < num_entries; i++) { 8159 sal_memset(&hg_trunk_member_entry, 0, sizeof(hg_trunk_member_entry_t)); 8160 #if defined(BCM_KATANA2_SUPPORT) 8161 if (SOC_IS_KATANA2(unit)) { 8162 soc_HG_TRUNK_MEMBERm_field32_set(unit, &hg_trunk_member_entry, 8163 PHYSICAL_PORTf, add_info->tp[i % add_info->num_ports]); 8164 soc_HG_TRUNK_MEMBERm_field32_set(unit, &hg_trunk_member_entry, 8165 PP_PORTf, add_info->tp[i % add_info->num_ports]); 8166 } else 8167 #endif /* (defined(BCM_KATANA2_SUPPORT) */ 8168 { 8169 8170 #ifdef BCM_TOMAHAWK_SUPPORT 8171 if (t_info->psc == BCM_TRUNK_PSC_ROUND_ROBIN) { 8172 if (soc_feature(unit, soc_feature_round_robin_load_balance)) { 8173 sal_memset(&random_rrlb_hg_trunk_member_entry, 0, sizeof(random_rrlb_hg_trunk_member_entry_t)); 8174 soc_RANDOM_RRLB_HG_TRUNK_MEMBERm_field32_set(unit, &random_rrlb_hg_trunk_member_entry, 8175 PORT_NUMf, add_info->tp[i % add_info->num_ports]); 8176 SOC_IF_ERROR_RETURN 8177 (WRITE_RANDOM_RRLB_HG_TRUNK_MEMBERm(unit, MEM_BLOCK_ALL, base_ptr + i, 8178 &random_rrlb_hg_trunk_member_entry)); 8179 } 8180 } else if ((t_info->psc == BCM_TRUNK_PSC_RANDOMIZED)) { 8181 if (soc_feature(unit, soc_feature_randomized_load_balance)) { 8182 /* Configure HG Rand LB Seed */ 8183 seed = (sal_rand()) % 0xFFFF; 8184 rval = 0; 8185 for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) { 8186 reg = SOC_REG_UNIQUE_ACC(unit, HG_TRUNK_RAND_LB_SEEDr)[pipe]; 8187 soc_reg_field_set(unit, reg, &rval, SEEDf, seed); 8188 SOC_IF_ERROR_RETURN 8189 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 8190 } 8191 } 8192 } 8193 #endif 8194 8195 soc_HG_TRUNK_MEMBERm_field32_set(unit, &hg_trunk_member_entry, 8196 PORT_NUMf, add_info->tp[i % add_info->num_ports]); 8197 } 8198 8199 SOC_IF_ERROR_RETURN 8200 (WRITE_HG_TRUNK_MEMBERm(unit, MEM_BLOCK_ALL, base_ptr + i, 8201 &hg_trunk_member_entry)); 8202 } 8203 8204 /* Set hg_trunk_member_bitmap */ 8205 _BCM_HG_TRUNK_MEMBER_USED_SET_RANGE(unit, base_ptr, num_entries); 8206 8207 /* Update Higig trunk base_ptr, tg_size, and rtag */ 8208 SOC_IF_ERROR_RETURN(READ_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, hgtid, 8209 &hg_trunk_group_entry)); 8210 soc_HG_TRUNK_GROUPm_field32_set 8211 (unit, &hg_trunk_group_entry, BASE_PTRf, base_ptr); 8212 soc_HG_TRUNK_GROUPm_field32_set 8213 (unit, &hg_trunk_group_entry, TG_SIZEf, add_info->num_ports-1); 8214 soc_HG_TRUNK_GROUPm_field32_set 8215 (unit, &hg_trunk_group_entry, RTAGf, t_info->rtag); 8216 #if defined(BCM_HGPROXY_COE_SUPPORT) 8217 if (soc_mem_field_valid(unit, HG_TRUNK_GROUPm, ENTRY_TYPEf) && 8218 (trunk_flag == 1)) { 8219 /*cascaded trunk*/ 8220 soc_HG_TRUNK_GROUPm_field32_set 8221 (unit, &hg_trunk_group_entry, ENTRY_TYPEf, 1); 8222 } 8223 #endif 8224 SOC_IF_ERROR_RETURN 8225 (WRITE_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, hgtid, &hg_trunk_group_entry)); 8226 8227 #ifdef BCM_TOMAHAWK_SUPPORT 8228 if (t_info->psc == BCM_TRUNK_PSC_ROUND_ROBIN) { 8229 if (soc_feature(unit, soc_feature_round_robin_load_balance)) { 8230 soc_HG_TRUNK_MODEm_field32_set(unit, &hg_trunk_mode_entry, HG_TRUNK_LB_MODEf, 0x3); 8231 SOC_IF_ERROR_RETURN 8232 (WRITE_HG_TRUNK_MODEm(unit, MEM_BLOCK_ALL, hgtid, &hg_trunk_mode_entry)); 8233 8234 BCM_IF_ERROR_RETURN(READ_HG_TRUNK_RR_CNTm(unit, MEM_BLOCK_ANY, 8235 hgtid, &rrlb_cnt_entry)); 8236 soc_HG_TRUNK_RR_CNTm_field32_set(unit, &rrlb_cnt_entry, 8237 RR_CNTf, 0); 8238 BCM_IF_ERROR_RETURN(WRITE_HG_TRUNK_RR_CNTm(unit, MEM_BLOCK_ALL, 8239 hgtid, &rrlb_cnt_entry)); 8240 8241 } 8242 } else if ((t_info->psc == BCM_TRUNK_PSC_RANDOMIZED)) { 8243 if (soc_feature(unit, soc_feature_randomized_load_balance)) { 8244 soc_HG_TRUNK_MODEm_field32_set(unit, &hg_trunk_mode_entry, HG_TRUNK_LB_MODEf, 0x2); 8245 seed = (sal_rand()) % 0xF; 8246 soc_HG_TRUNK_MODEm_field32_set(unit, &hg_trunk_mode_entry, OFFSET_RANDOM_LBf, seed); 8247 SOC_IF_ERROR_RETURN 8248 (WRITE_HG_TRUNK_MODEm(unit, MEM_BLOCK_ALL, hgtid, &hg_trunk_mode_entry)); 8249 } 8250 } else if ((t_info->psc != BCM_TRUNK_PSC_DYNAMIC) && 8251 (t_info->psc != BCM_TRUNK_PSC_DYNAMIC_ASSIGNED) && 8252 (t_info->psc != BCM_TRUNK_PSC_DYNAMIC_OPTIMAL) && 8253 (t_info->psc != BCM_TRUNK_PSC_DYNAMIC_RESILIENT)) { 8254 if (soc_mem_field_valid(unit, HG_TRUNK_MODEm, HG_TRUNK_LB_MODEf)) { 8255 soc_HG_TRUNK_MODEm_field32_set(unit, &hg_trunk_mode_entry, HG_TRUNK_LB_MODEf, 0x0); 8256 SOC_IF_ERROR_RETURN 8257 (WRITE_HG_TRUNK_MODEm(unit, MEM_BLOCK_ALL, hgtid, &hg_trunk_mode_entry)); 8258 } 8259 } 8260 #endif 8261 8262 return BCM_E_NONE; 8263 } 8264 8265 /* 8266 * Function: 8267 * bcm_trident_trunk_fabric_port_set 8268 * Purpose: 8269 * Update port table for Higig trunks. 8270 * Parameters: 8271 * unit - (IN) SOC unit number. 8272 * hgtid - (IN) Higig trunk group ID. 8273 * old_ports - (IN) Higig trunk group's old port bitmap. 8274 * new_ports - (IN) Higig trunk group's new port bitmap. 8275 * Returns: 8276 * BCM_E_xxx 8277 */ 8278 STATIC int 8279 _bcm_trident_trunk_fabric_port_set(int unit, 8280 bcm_trunk_t hgtid, 8281 pbmp_t old_ports, 8282 pbmp_t new_ports) 8283 { 8284 bcm_port_t port; 8285 bcm_pbmp_t pbm; 8286 int ctid; 8287 8288 BCM_PBMP_ASSIGN(pbm, PBMP_HG_ALL(unit)); 8289 BCM_PBMP_OR(pbm, PBMP_ST_ALL(unit)); 8290 PBMP_ITER(pbm, port) { 8291 if (BCM_PBMP_MEMBER(new_ports, port)) { 8292 ctid = hgtid; 8293 } else if (BCM_PBMP_MEMBER(old_ports, port)) { 8294 ctid = -1; 8295 if (soc_feature(unit, soc_feature_hg_trunk_failover)) { 8296 /* Clear HW failover info for deleted port */ 8297 BCM_IF_ERROR_RETURN 8298 (_bcm_trident_trunk_hwfailover_set(unit, hgtid, TRUE, 8299 port, -1, 8300 BCM_TRUNK_PSC_DEFAULT, 8301 0, 0, NULL, NULL)); 8302 } 8303 } else { 8304 continue; 8305 } 8306 BCM_IF_ERROR_RETURN 8307 (_bcm_esw_port_config_set(unit, port, 8308 _bcmPortHigigTrunkId, ctid)); 8309 } 8310 if (soc_feature(unit, soc_feature_linkphy_coe) && 8311 BCM_PBMP_NOT_NULL(PBMP_LP_ALL(unit))) { 8312 PBMP_LP_ITER(unit, port) { 8313 if (BCM_PBMP_MEMBER(old_ports, port)) { 8314 if (soc_feature(unit, soc_feature_hg_trunk_failover)) { 8315 /* Clear HW failover info for deleted port */ 8316 BCM_IF_ERROR_RETURN 8317 (_bcm_trident_trunk_hwfailover_set(unit, hgtid, TRUE, 8318 port, -1, 8319 BCM_TRUNK_PSC_DEFAULT, 8320 0, 0, NULL, NULL)); 8321 } 8322 } 8323 BCM_IF_ERROR_RETURN 8324 (_bcm_esw_port_config_set(unit, port, 8325 _bcmPortHigigTrunkId, -1)); 8326 } 8327 } 8328 if ((soc_feature(unit, soc_feature_subtag_coe) || 8329 soc_feature(unit, soc_feature_hgproxy_subtag_coe)) && 8330 BCM_PBMP_NOT_NULL(PBMP_SUBTAG_ALL(unit))) { 8331 PBMP_SUBTAG_ITER(unit, port) { 8332 if (BCM_PBMP_MEMBER(old_ports, port)) { 8333 if (soc_feature(unit, soc_feature_hg_trunk_failover)) { 8334 /* Clear HW failover info for deleted port */ 8335 BCM_IF_ERROR_RETURN 8336 (_bcm_trident_trunk_hwfailover_set(unit, hgtid, TRUE, 8337 port, -1, 8338 BCM_TRUNK_PSC_DEFAULT, 8339 0, 0, NULL, NULL)); 8340 } 8341 } 8342 BCM_IF_ERROR_RETURN 8343 (_bcm_esw_port_config_set(unit, port, 8344 _bcmPortHigigTrunkId, -1)); 8345 } 8346 } 8347 return BCM_E_NONE; 8348 } 8349 8350 /* 8351 * Function: 8352 * bcm_trident_trunk_fabric_modify 8353 * Purpose: 8354 * Set, add or delete trunk members. 8355 * Parameters: 8356 * unit - (IN) SOC unit number. 8357 * hgtid - (IN) Higig trunk group ID. 8358 * add_info - (IN) Pointer to trunk add info structure. 8359 * t_info - (IN) Pointer to trunk info. 8360 * op - (IN) Type of operation: TRUNK_MEMBER_OP_SET, ADD or DELETE. 8361 * member - (IN) Member to add or delete. 8362 * Returns: 8363 * BCM_E_xxx 8364 */ 8365 STATIC int 8366 _bcm_trident_trunk_fabric_modify(int unit, 8367 bcm_trunk_t hgtid, 8368 _esw_trunk_add_info_t *add_info, 8369 trunk_private_t *t_info, 8370 trunk_private_t *stored_info, 8371 int op, 8372 bcm_trunk_member_t *member) 8373 { 8374 bcm_trunk_chip_info_t chip_info; 8375 int i, local_id; 8376 bcm_gport_t gport; 8377 bcm_trunk_t trunk, tid; 8378 pbmp_t old_trunk_pbmp, new_trunk_pbmp; 8379 hg_trunk_bitmap_entry_t hg_trunk_bitmap_entry; 8380 int auto_include_disable = 0; 8381 int rv = BCM_E_NONE; 8382 int trunk_flag = 0; /*hg trunk or cascaded trunk*/ 8383 #if defined(BCM_HGPROXY_COE_SUPPORT) 8384 bcm_port_t local_port; 8385 #endif 8386 8387 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 8388 8389 if (add_info->num_ports > chip_info.trunk_fabric_ports_max || 8390 add_info->num_ports < 1) { 8391 return BCM_E_PARAM; 8392 } 8393 8394 /* On Trident, the max number of trunk members for RTAG 1-6 is smaller 8395 * than for RTAG 7. 8396 */ 8397 if (soc_feature(unit, soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 8398 if (t_info->rtag >= 1 && t_info->rtag <= 6) { 8399 if (add_info->num_ports > _BCM_TD_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT) { 8400 return BCM_E_PARAM; 8401 } 8402 } 8403 } 8404 8405 tid = hgtid + chip_info.trunk_group_count; 8406 8407 SOC_PBMP_CLEAR(new_trunk_pbmp); 8408 for (i = 0; i < add_info->num_ports; i++) { 8409 /* if given modid is -1 devport was used */ 8410 if (BCM_MODID_INVALID != add_info->tm[i]) { 8411 BCM_GPORT_MODPORT_SET(gport, add_info->tm[i], add_info->tp[i]); 8412 8413 BCM_IF_ERROR_RETURN 8414 (_bcm_esw_gport_resolve(unit, gport, &add_info->tm[i], 8415 &add_info->tp[i], &trunk, &local_id)); 8416 #if defined(BCM_HGPROXY_COE_SUPPORT) 8417 BCM_IF_ERROR_RETURN 8418 (bcm_esw_port_local_get(unit, gport, &local_port)); 8419 /*Cascaded port*/ 8420 if (IS_SUBTAG_PORT(unit, local_port) && 8421 soc_feature(unit, soc_feature_hgproxy_subtag_coe)) { 8422 /*cascaded trunk*/ 8423 trunk_flag = 1; 8424 } 8425 #endif 8426 } 8427 8428 if (!SOC_PORT_VALID(unit, add_info->tp[i])) { 8429 return BCM_E_PORT; 8430 } 8431 if (!(IS_ST_PORT(unit, add_info->tp[i]) || 8432 (trunk_flag == 1))) { 8433 return BCM_E_PARAM; 8434 } 8435 SOC_PBMP_PORT_ADD(new_trunk_pbmp, add_info->tp[i]); 8436 } 8437 8438 /* Configure static load balancing */ 8439 if (t_info->in_use) { 8440 BCM_IF_ERROR_RETURN(_bcm_trident_hg_slb_free_resource(unit, hgtid)); 8441 } 8442 BCM_IF_ERROR_RETURN(_bcm_trident_hg_slb_set(unit, hgtid, add_info, 8443 t_info, trunk_flag)); 8444 8445 /* Configure dynamic load balancing, if enabled */ 8446 if (soc_feature(unit, soc_feature_hg_dlb) && 8447 !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 8448 if (t_info->in_use) { 8449 BCM_IF_ERROR_RETURN(_bcm_trident_hg_dlb_free_resource(unit, hgtid)); 8450 } 8451 BCM_IF_ERROR_RETURN(_bcm_trident_hg_dlb_set(unit, hgtid, add_info)); 8452 } 8453 8454 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 8455 /* Configure dynamic load balancing */ 8456 if (soc_feature(unit, soc_feature_hg_dlb) && 8457 soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 8458 if (t_info->in_use) { 8459 BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_free_resource(unit, hgtid, 1)); 8460 } 8461 BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_set(unit, hgtid, 1, add_info, 8462 add_info->num_ports, add_info->tm, add_info->tp, 8463 add_info->dynamic_scaling_factor, add_info->dynamic_load_weight, 8464 add_info->dynamic_queue_size_weight)); 8465 } 8466 #endif /* BCM_TOMAHAWK2_SUPPORT */ 8467 8468 #ifdef BCM_TRIDENT2_SUPPORT 8469 /* Configure resilient hashing, if enabled */ 8470 if (soc_feature(unit, soc_feature_hg_resilient_hash)) { 8471 if (op == TRUNK_MEMBER_OP_SET) { 8472 if ((stored_info->in_use) && 8473 (add_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) && 8474 (stored_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) && 8475 (add_info->dynamic_size != 0) && 8476 (add_info->dynamic_size == stored_info->dynamic_size)) { 8477 BCM_IF_ERROR_RETURN(bcm_td2_hg_rh_replace(unit, hgtid, add_info, 8478 MEMBER_INFO(unit, tid).num_ports, 8479 MEMBER_INFO(unit, tid).modport, 8480 MEMBER_INFO(unit, tid).member_flags)); 8481 } else { 8482 if (t_info->in_use) { 8483 BCM_IF_ERROR_RETURN(bcm_td2_hg_rh_free_resource(unit, hgtid)); 8484 } 8485 if (add_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) { 8486 BCM_IF_ERROR_RETURN(bcm_td2_hg_rh_set(unit, hgtid, add_info)); 8487 } 8488 } 8489 } else if (op == TRUNK_MEMBER_OP_ADD) { 8490 if (add_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) { 8491 BCM_IF_ERROR_RETURN(bcm_td2_hg_rh_add(unit, hgtid, add_info, 8492 member)); 8493 } 8494 } else if (op == TRUNK_MEMBER_OP_DELETE) { 8495 if (add_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) { 8496 BCM_IF_ERROR_RETURN(bcm_td2_hg_rh_delete(unit, hgtid, add_info, 8497 member)); 8498 } 8499 } else { 8500 return BCM_E_PARAM; 8501 } 8502 } 8503 #endif /* BCM_TRIDENT2_SUPPORT */ 8504 8505 /* Update Higig trunk bitmap */ 8506 8507 SOC_IF_ERROR_RETURN 8508 (READ_HG_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, hgtid, &hg_trunk_bitmap_entry)); 8509 SOC_PBMP_CLEAR(old_trunk_pbmp); 8510 soc_mem_pbmp_field_get(unit, HG_TRUNK_BITMAPm, &hg_trunk_bitmap_entry, 8511 HIGIG_TRUNK_BITMAPf, &old_trunk_pbmp); 8512 8513 soc_mem_pbmp_field_set(unit, HG_TRUNK_BITMAPm, &hg_trunk_bitmap_entry, 8514 HIGIG_TRUNK_BITMAPf, &new_trunk_pbmp); 8515 SOC_IF_ERROR_RETURN 8516 (WRITE_HG_TRUNK_BITMAPm(unit, MEM_BLOCK_ALL, hgtid, &hg_trunk_bitmap_entry)); 8517 8518 BCM_IF_ERROR_RETURN 8519 (_bcm_trident_trunk_fabric_port_set(unit, 8520 hgtid, 8521 old_trunk_pbmp, 8522 new_trunk_pbmp)); 8523 8524 if (soc_feature(unit, soc_feature_hg_trunk_failover)) { 8525 BCM_IF_ERROR_RETURN 8526 (_bcm_trident_trunk_failover_set(unit, hgtid, TRUE, add_info)); 8527 } 8528 8529 BCM_IF_ERROR_RETURN 8530 (_bcm_trident_trunk_swfailover_fabric_set(unit, 8531 hgtid, 8532 t_info->rtag, 8533 new_trunk_pbmp)); 8534 8535 if (MEMBER_INFO(unit, tid).modport) { 8536 sal_free(MEMBER_INFO(unit, tid).modport); 8537 MEMBER_INFO(unit, tid).modport = NULL; 8538 } 8539 if (MEMBER_INFO(unit, tid).member_flags) { 8540 sal_free(MEMBER_INFO(unit, tid).member_flags); 8541 MEMBER_INFO(unit, tid).member_flags = NULL; 8542 } 8543 8544 MEMBER_INFO(unit, tid).modport = sal_alloc( 8545 sizeof(uint16) * add_info->num_ports, "member info modport"); 8546 if (NULL == MEMBER_INFO(unit, tid).modport) { 8547 return BCM_E_MEMORY; 8548 } 8549 8550 MEMBER_INFO(unit, tid).member_flags = sal_alloc( 8551 sizeof(uint32) * add_info->num_ports, "member info flags"); 8552 if (NULL == MEMBER_INFO(unit, tid).member_flags) { 8553 sal_free(MEMBER_INFO(unit, tid).modport); 8554 MEMBER_INFO(unit, tid).modport = NULL; 8555 return BCM_E_MEMORY; 8556 } 8557 8558 for (i = 0; i < add_info->num_ports; i++) { 8559 /* Save new trunk member info */ 8560 MEMBER_INFO(unit, tid).modport[i] = add_info->tp[i]; 8561 MEMBER_INFO(unit, tid).member_flags[i] = add_info->member_flags[i]; 8562 } 8563 MEMBER_INFO(unit, tid).num_ports = add_info->num_ports; 8564 8565 /* On Trident, changing Higig trunk membership requires 8566 * updating the modport map table. 8567 */ 8568 rv = bcm_esw_switch_control_get(unit, 8569 bcmSwitchFabricTrunkAutoIncludeDisable, &auto_include_disable); 8570 if (BCM_FAILURE(rv)) { 8571 if (BCM_E_UNAVAIL == rv) { 8572 auto_include_disable = 0; 8573 } else { 8574 return rv; 8575 } 8576 } 8577 if (!auto_include_disable) { 8578 BCM_IF_ERROR_RETURN(bcm_td_stk_modport_map_update(unit)); 8579 } 8580 8581 return BCM_E_NONE; 8582 } 8583 8584 /* 8585 * Function: 8586 * bcm_trident_trunk_fabric_destroy 8587 * Purpose: 8588 * Remove fabric trunk group. 8589 * Parameters: 8590 * unit - (IN) SOC unit number. 8591 * hgtid - (IN) Higig trunk group ID. 8592 * t_info - (IN) Pointer to trunk info. 8593 * Returns: 8594 * BCM_E_xxx 8595 */ 8596 STATIC int 8597 _bcm_trident_trunk_fabric_destroy(int unit, 8598 bcm_trunk_t hgtid, 8599 trunk_private_t *t_info) 8600 { 8601 bcm_trunk_chip_info_t chip_info; 8602 pbmp_t old_trunk_pbmp, new_trunk_pbmp; 8603 hg_trunk_bitmap_entry_t hg_trunk_bitmap_entry; 8604 bcm_trunk_t tid; 8605 int auto_include_disable = 0; 8606 int rv = BCM_E_NONE; 8607 8608 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 8609 tid = hgtid + chip_info.trunk_group_count; 8610 8611 /* Clear DLB configuration */ 8612 if (soc_feature(unit, soc_feature_hg_dlb) && 8613 !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 8614 BCM_IF_ERROR_RETURN(_bcm_trident_hg_dlb_free_resource(unit, hgtid)); 8615 } 8616 8617 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 8618 if (soc_feature(unit, soc_feature_hg_dlb) && 8619 soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 8620 BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_free_resource(unit, hgtid, 1)); 8621 } 8622 #endif /* BCM_TOMAHAWK2_SUPPORT */ 8623 8624 #ifdef BCM_TRIDENT2_SUPPORT 8625 /* Clear resilient hashing configuration */ 8626 if (soc_feature(unit, soc_feature_hg_resilient_hash)) { 8627 BCM_IF_ERROR_RETURN(bcm_td2_hg_rh_free_resource(unit, hgtid)); 8628 } 8629 #endif /* BCM_TRIDENT2_SUPPORT */ 8630 8631 BCM_IF_ERROR_RETURN(_bcm_trident_hg_slb_free_resource(unit, hgtid)); 8632 8633 if (MEMBER_INFO(unit, tid).modport) { 8634 sal_free(MEMBER_INFO(unit, tid).modport); 8635 MEMBER_INFO(unit, tid).modport = NULL; 8636 } 8637 if (MEMBER_INFO(unit, tid).member_flags) { 8638 sal_free(MEMBER_INFO(unit, tid).member_flags); 8639 MEMBER_INFO(unit, tid).member_flags = NULL; 8640 } 8641 MEMBER_INFO(unit, tid).num_ports = 0; 8642 8643 /* Get old Higig trunk bitmap */ 8644 SOC_IF_ERROR_RETURN 8645 (READ_HG_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, hgtid, &hg_trunk_bitmap_entry)); 8646 SOC_PBMP_CLEAR(old_trunk_pbmp); 8647 soc_mem_pbmp_field_get(unit, HG_TRUNK_BITMAPm, &hg_trunk_bitmap_entry, 8648 HIGIG_TRUNK_BITMAPf, &old_trunk_pbmp); 8649 8650 /* Clear Higig trunk bitmap */ 8651 SOC_IF_ERROR_RETURN 8652 (WRITE_HG_TRUNK_BITMAPm(unit, MEM_BLOCK_ALL, hgtid, 8653 soc_mem_entry_null(unit, HG_TRUNK_BITMAPm))); 8654 8655 /* Clear Higig trunk group table */ 8656 SOC_IF_ERROR_RETURN 8657 (WRITE_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, hgtid, 8658 soc_mem_entry_null(unit, HG_TRUNK_GROUPm))); 8659 8660 SOC_PBMP_CLEAR(new_trunk_pbmp); 8661 8662 BCM_IF_ERROR_RETURN 8663 (_bcm_trident_trunk_fabric_port_set(unit, 8664 hgtid, 8665 old_trunk_pbmp, 8666 new_trunk_pbmp)); 8667 8668 if (soc_feature(unit, soc_feature_hg_trunk_failover)) { 8669 BCM_IF_ERROR_RETURN 8670 (_bcm_trident_trunk_failover_set(unit, hgtid, TRUE, NULL)); 8671 } 8672 8673 BCM_IF_ERROR_RETURN 8674 (_bcm_trident_trunk_swfailover_fabric_set(unit, 8675 hgtid, 8676 0, 8677 new_trunk_pbmp)); 8678 8679 /* On Trident, changing Higig trunk membership requires 8680 * updating the modport map table. 8681 */ 8682 rv = bcm_esw_switch_control_get(unit, 8683 bcmSwitchFabricTrunkAutoIncludeDisable, &auto_include_disable); 8684 if (BCM_FAILURE(rv)) { 8685 if (BCM_E_UNAVAIL == rv) { 8686 auto_include_disable = 0; 8687 } else { 8688 return rv; 8689 } 8690 } 8691 if (!auto_include_disable) { 8692 BCM_IF_ERROR_RETURN(bcm_td_stk_modport_map_update(unit)); 8693 } 8694 8695 t_info->in_use = FALSE; 8696 return BCM_E_NONE; 8697 } 8698 8699 /* 8700 * Function: 8701 * bcm_trident_trunk_fabric_get 8702 * Purpose: 8703 * Return a fabric trunk information of given fabric trunk ID. 8704 * If t_data->num_ports = 0, return number of trunk members in 8705 * t_data->num_ports. 8706 * Parameters: 8707 * unit - (IN) StrataSwitch PCI device unit number (driver internal). 8708 * tid - (IN) Trunk ID. 8709 * t_data - (OUT) Place to store returned trunk add info. 8710 * t_info - (IN) Trunk info. 8711 * Returns: 8712 * BCM_E_NONE Success. 8713 * BCM_E_XXX 8714 */ 8715 STATIC int 8716 _bcm_trident_trunk_fabric_get(int unit, 8717 bcm_trunk_t hgtid, 8718 _esw_trunk_add_info_t *t_data, 8719 trunk_private_t *t_info) 8720 { 8721 bcm_trunk_chip_info_t chip_info; 8722 bcm_trunk_t tid; 8723 bcm_module_t modid; 8724 bcm_port_t port; 8725 int i; 8726 uint32 quantize_control_reg; 8727 int profile_ptr; 8728 8729 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 8730 tid = hgtid + chip_info.trunk_group_count; 8731 8732 if (t_data->num_ports == 0) { 8733 t_data->num_ports = MEMBER_INFO(unit, tid).num_ports; 8734 } else { 8735 if (MEMBER_INFO(unit, tid).num_ports <= t_data->num_ports) { 8736 t_data->num_ports = MEMBER_INFO(unit, tid).num_ports; 8737 } 8738 8739 if (BCM_FAILURE(bcm_esw_stk_my_modid_get(unit, &modid))) { 8740 modid = 0; 8741 } 8742 8743 for (i = 0; i < t_data->num_ports; i++) { 8744 port = MEMBER_INFO(unit, tid).modport[i] & 0xff; 8745 BCM_IF_ERROR_RETURN(_bcm_esw_stk_modmap_map(unit, 8746 BCM_STK_MODMAP_GET, modid, port, 8747 &t_data->tm[i], &t_data->tp[i])); 8748 8749 /* Get per trunk member DLB attributes */ 8750 t_data->dynamic_scaling_factor[i] = 0; 8751 t_data->dynamic_load_weight[i] = 0; 8752 t_data->dynamic_queue_size_weight[i] = 0; 8753 if ((t_data->psc == BCM_TRUNK_PSC_DYNAMIC) || 8754 (t_data->psc == BCM_TRUNK_PSC_DYNAMIC_ASSIGNED) || 8755 (t_data->psc == BCM_TRUNK_PSC_DYNAMIC_OPTIMAL)) { 8756 8757 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 8758 if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 8759 BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_member_attr_get(unit, 8760 port, 8761 &t_data->dynamic_scaling_factor[i], 8762 &t_data->dynamic_load_weight[i], 8763 &t_data->dynamic_queue_size_weight[i])); 8764 } else 8765 #endif /* BCM_TOMAHAWK2_SUPPORT */ 8766 8767 #ifdef BCM_TRIUMPH3_SUPPORT 8768 if (soc_feature(unit, soc_feature_hg_dlb_member_id)) { 8769 BCM_IF_ERROR_RETURN(_bcm_tr3_hg_dlb_member_attr_get(unit, 8770 port, 8771 &t_data->dynamic_scaling_factor[i], 8772 &t_data->dynamic_load_weight[i])); 8773 } else 8774 #endif /* BCM_TRIUMPH3_SUPPORT */ 8775 { 8776 SOC_IF_ERROR_RETURN(READ_DLB_HGT_QUANTIZE_CONTROLr(unit, 8777 port, &quantize_control_reg)); 8778 t_data->dynamic_scaling_factor[i] = soc_reg_field_get(unit, 8779 DLB_HGT_QUANTIZE_CONTROLr, quantize_control_reg, 8780 PORT_LOADING_THRESHOLD_SCALING_FACTORf); 8781 profile_ptr = soc_reg_field_get(unit, 8782 DLB_HGT_QUANTIZE_CONTROLr, quantize_control_reg, 8783 PORT_QUALITY_MAPPING_PROFILE_PTRf); 8784 t_data->dynamic_load_weight[i] = 8785 HG_DLB_INFO(unit)->hg_dlb_load_weight[profile_ptr]; 8786 } 8787 } 8788 } 8789 } 8790 8791 return BCM_E_NONE; 8792 } 8793 8794 /* 8795 * Function: 8796 * _bcm_trident_trunk_fabric_find 8797 * Description: 8798 * Get fabric trunk id that contains the given Higig port 8799 * Parameters: 8800 * unit - Unit number 8801 * port - Port number 8802 * tid - (OUT) Fabric trunk id 8803 * Returns: 8804 * BCM_E_xxxx 8805 */ 8806 int 8807 _bcm_trident_trunk_fabric_find(int unit, 8808 bcm_port_t port, 8809 int *tid) 8810 { 8811 bcm_trunk_chip_info_t chip_info; 8812 int num_hg_trunk_groups; 8813 int hgtid; 8814 hg_trunk_bitmap_entry_t hg_trunk_bitmap_entry; 8815 pbmp_t trunk_pbmp; 8816 8817 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 8818 if (chip_info.trunk_fabric_id_min == -1) { 8819 return BCM_E_NOT_FOUND; 8820 } else { 8821 num_hg_trunk_groups = chip_info.trunk_fabric_id_max - 8822 chip_info.trunk_fabric_id_min + 1; 8823 } 8824 8825 for (hgtid = 0; hgtid < num_hg_trunk_groups; hgtid++) { 8826 SOC_IF_ERROR_RETURN 8827 (READ_HG_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, hgtid, &hg_trunk_bitmap_entry)); 8828 SOC_PBMP_CLEAR(trunk_pbmp); 8829 soc_mem_pbmp_field_get(unit, HG_TRUNK_BITMAPm, &hg_trunk_bitmap_entry, 8830 HIGIG_TRUNK_BITMAPf, &trunk_pbmp); 8831 if (SOC_PBMP_MEMBER(trunk_pbmp, port)) { 8832 *tid = hgtid + chip_info.trunk_fabric_id_min; 8833 return BCM_E_NONE; 8834 } 8835 } 8836 return BCM_E_NOT_FOUND; 8837 } 8838 8839 /* 8840 * Function: 8841 * _bcm_trident_trunk_override_mcast_set 8842 * Purpose: 8843 * Set Higig trunk override in L2MC table. 8844 * Parameters: 8845 * unit - (IN) SOC unit number. 8846 * hgtid - (IN) Higig trunk group ID. 8847 * idx - (IN) L2MC table index. 8848 * enable - (IN) Higig trunk override enable. 8849 * Returns: 8850 * BCM_E_xxx 8851 */ 8852 int 8853 _bcm_trident_trunk_override_mcast_set(int unit, 8854 bcm_trunk_t hgtid, 8855 int idx, 8856 int enable) 8857 { 8858 l2mc_entry_t l2mc_entry; 8859 ing_higig_trunk_override_profile_entry_t hgo_profile_entry; 8860 8861 int rv; 8862 uint32 old_profile_ptr, new_profile_ptr; 8863 int hgo_bits, alloc_sz; 8864 SHR_BITDCL *hgo_bitmap = NULL; 8865 void *entry_ptr; 8866 8867 /* Get old profile entry */ 8868 8869 soc_mem_lock(unit, L2MCm); 8870 rv = READ_L2MCm(unit, MEM_BLOCK_ANY, idx, &l2mc_entry); 8871 if (SOC_FAILURE(rv)) { 8872 soc_mem_unlock(unit, L2MCm); 8873 return rv; 8874 } 8875 8876 old_profile_ptr = soc_L2MCm_field32_get(unit, &l2mc_entry, 8877 HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf); 8878 rv = READ_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm(unit, MEM_BLOCK_ANY, 8879 old_profile_ptr, &hgo_profile_entry); 8880 if (SOC_FAILURE(rv)) { 8881 soc_mem_unlock(unit, L2MCm); 8882 return rv; 8883 } 8884 8885 hgo_bits = soc_mem_field_length(unit, 8886 ING_HIGIG_TRUNK_OVERRIDE_PROFILEm, 8887 HIGIG_TRUNK_OVERRIDE_BITMAPf); 8888 alloc_sz = SHR_BITALLOCSIZE(hgo_bits); 8889 hgo_bitmap = sal_alloc(alloc_sz, "HGT override bitmap"); 8890 if (hgo_bitmap == NULL) { 8891 soc_mem_unlock(unit, L2MCm); 8892 return BCM_E_MEMORY; 8893 } 8894 /* Add new profile entry */ 8895 soc_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm_field_get(unit, 8896 &hgo_profile_entry, HIGIG_TRUNK_OVERRIDE_BITMAPf, hgo_bitmap); 8897 if (enable) { 8898 SHR_BITSET(hgo_bitmap, hgtid); 8899 } else { 8900 SHR_BITCLR(hgo_bitmap, hgtid); 8901 } 8902 soc_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm_field_set(unit, 8903 &hgo_profile_entry, HIGIG_TRUNK_OVERRIDE_BITMAPf, hgo_bitmap); 8904 sal_free(hgo_bitmap); 8905 hgo_bitmap = NULL; 8906 8907 entry_ptr = &hgo_profile_entry; 8908 rv = soc_profile_mem_add(unit, _trident_hg_trunk_override_profile[unit], 8909 &entry_ptr, 1, &new_profile_ptr); 8910 if (SOC_FAILURE(rv)) { 8911 soc_mem_unlock(unit, L2MCm); 8912 return rv; 8913 } 8914 8915 soc_L2MCm_field32_set(unit, &l2mc_entry, HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf, 8916 new_profile_ptr); 8917 rv = WRITE_L2MCm(unit, MEM_BLOCK_ALL, idx, &l2mc_entry); 8918 soc_mem_unlock(unit, L2MCm); 8919 if (SOC_FAILURE(rv)) { 8920 return rv; 8921 } 8922 8923 /* Delete old profile entry */ 8924 rv = soc_profile_mem_delete(unit, _trident_hg_trunk_override_profile[unit], 8925 old_profile_ptr); 8926 8927 return rv; 8928 } 8929 8930 /* 8931 * Function: 8932 * _bcm_trident_trunk_override_mcast_get 8933 * Purpose: 8934 * Get Higig trunk override for L2MC group. 8935 * Parameters: 8936 * unit - (IN) SOC unit number. 8937 * hgtid - (IN) Higig trunk group ID. 8938 * idx - (IN) L2MC index. 8939 * enable - (OUT) Pointer to Higig trunk override enable. 8940 * Returns: 8941 * BCM_E_xxx 8942 */ 8943 int 8944 _bcm_trident_trunk_override_mcast_get(int unit, 8945 bcm_trunk_t hgtid, 8946 int idx, 8947 int *enable) 8948 { 8949 l2mc_entry_t l2mc_entry; 8950 ing_higig_trunk_override_profile_entry_t hgo_profile_entry; 8951 8952 int profile_ptr; 8953 int hgo_bits, alloc_sz; 8954 SHR_BITDCL *hgo_bitmap = NULL; 8955 8956 SOC_IF_ERROR_RETURN 8957 (READ_L2MCm(unit, MEM_BLOCK_ANY, idx, &l2mc_entry)); 8958 8959 profile_ptr = soc_L2MCm_field32_get(unit, &l2mc_entry, 8960 HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf); 8961 8962 SOC_IF_ERROR_RETURN 8963 (READ_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm(unit, MEM_BLOCK_ANY, 8964 profile_ptr, &hgo_profile_entry)); 8965 hgo_bits = soc_mem_field_length(unit, 8966 ING_HIGIG_TRUNK_OVERRIDE_PROFILEm, 8967 HIGIG_TRUNK_OVERRIDE_BITMAPf); 8968 alloc_sz = SHR_BITALLOCSIZE(hgo_bits); 8969 hgo_bitmap = sal_alloc(alloc_sz, "HGT override bitmap"); 8970 if (hgo_bitmap == NULL) { 8971 return BCM_E_MEMORY; 8972 } 8973 soc_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm_field_get(unit, 8974 &hgo_profile_entry, HIGIG_TRUNK_OVERRIDE_BITMAPf, hgo_bitmap); 8975 8976 *enable = SHR_BITGET(hgo_bitmap, hgtid) ? 1 : 0; 8977 8978 sal_free(hgo_bitmap); 8979 hgo_bitmap = NULL; 8980 8981 return BCM_E_NONE; 8982 } 8983 8984 /* 8985 * Function: 8986 * _bcm_trident_trunk_override_ipmc_set 8987 * Purpose: 8988 * Set Higig trunk override for IPMC group. 8989 * Parameters: 8990 * unit - (IN) SOC unit number. 8991 * hgtid - (IN) Higig trunk group ID. 8992 * idx - (IN) IPMC index. 8993 * enable - (IN) Higig trunk override enable. 8994 * Returns: 8995 * BCM_E_xxx 8996 */ 8997 int 8998 _bcm_trident_trunk_override_ipmc_set(int unit, 8999 bcm_trunk_t hgtid, 9000 int idx, 9001 int enable) 9002 { 9003 ipmc_entry_t ipmc_entry; 9004 ing_higig_trunk_override_profile_entry_t hgo_profile_entry; 9005 9006 int rv; 9007 uint32 old_profile_ptr, new_profile_ptr; 9008 int hgo_bits, alloc_sz; 9009 SHR_BITDCL *hgo_bitmap = NULL; 9010 void *entry_ptr; 9011 int mc_base = 0, mc_size, mc_index; 9012 9013 /* Get old profile entry */ 9014 9015 soc_mem_lock(unit, L3_IPMCm); 9016 rv = READ_L3_IPMCm(unit, MEM_BLOCK_ANY, idx, &ipmc_entry); 9017 if (SOC_FAILURE(rv)) { 9018 soc_mem_unlock(unit, L3_IPMCm); 9019 return rv; 9020 } 9021 9022 old_profile_ptr = soc_L3_IPMCm_field32_get(unit, &ipmc_entry, 9023 HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf); 9024 rv = READ_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm(unit, MEM_BLOCK_ANY, 9025 old_profile_ptr, &hgo_profile_entry); 9026 if (SOC_FAILURE(rv)) { 9027 soc_mem_unlock(unit, L3_IPMCm); 9028 return rv; 9029 } 9030 9031 hgo_bits = soc_mem_field_length(unit, 9032 ING_HIGIG_TRUNK_OVERRIDE_PROFILEm, 9033 HIGIG_TRUNK_OVERRIDE_BITMAPf); 9034 alloc_sz = SHR_BITALLOCSIZE(hgo_bits); 9035 hgo_bitmap = sal_alloc(alloc_sz, "HGT override bitmap"); 9036 if (hgo_bitmap == NULL) { 9037 soc_mem_unlock(unit, L3_IPMCm); 9038 return BCM_E_MEMORY; 9039 } 9040 /* Add new profile entry */ 9041 soc_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm_field_get(unit, 9042 &hgo_profile_entry, HIGIG_TRUNK_OVERRIDE_BITMAPf, hgo_bitmap); 9043 if (enable) { 9044 SHR_BITSET(hgo_bitmap, hgtid); 9045 } else { 9046 SHR_BITCLR(hgo_bitmap, hgtid); 9047 } 9048 soc_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm_field_set(unit, 9049 &hgo_profile_entry, HIGIG_TRUNK_OVERRIDE_BITMAPf, hgo_bitmap); 9050 sal_free(hgo_bitmap); 9051 hgo_bitmap = NULL; 9052 9053 entry_ptr = &hgo_profile_entry; 9054 rv = soc_profile_mem_add(unit, _trident_hg_trunk_override_profile[unit], 9055 &entry_ptr, 1, &new_profile_ptr); 9056 if (SOC_FAILURE(rv)) { 9057 soc_mem_unlock(unit, L3_IPMCm); 9058 return rv; 9059 } 9060 9061 soc_L3_IPMCm_field32_set(unit, &ipmc_entry, HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf, 9062 new_profile_ptr); 9063 rv = WRITE_L3_IPMCm(unit, MEM_BLOCK_ALL, idx, &ipmc_entry); 9064 soc_mem_unlock(unit, L3_IPMCm); 9065 if (SOC_FAILURE(rv)) { 9066 return rv; 9067 } 9068 9069 /* Delete old profile entry */ 9070 SOC_IF_ERROR_RETURN 9071 (soc_profile_mem_delete(unit, _trident_hg_trunk_override_profile[unit], 9072 old_profile_ptr)); 9073 9074 /* In Trident, for IPMC packets from Higig ports, the L2 port bitmap is 9075 * derived from L2MC table. Hence, the Higig trunk override in L2MC table 9076 * also needs to be updated. 9077 */ 9078 if(!(SOC_IS_MONTEREY(unit))) { 9079 if (SOC_REG_FIELD_VALID(unit, MC_CONTROL_5r, SHARED_TABLE_L2MC_SIZEf) && 9080 SOC_REG_FIELD_VALID(unit, MC_CONTROL_5r, SHARED_TABLE_IPMC_SIZEf)) { 9081 SOC_IF_ERROR_RETURN(soc_hbx_ipmc_size_get(unit, &mc_base, &mc_size)); 9082 if (idx >= mc_size) { 9083 return BCM_E_PARAM; 9084 } 9085 mc_index = idx + mc_base; 9086 SOC_IF_ERROR_RETURN 9087 (_bcm_trident_trunk_override_mcast_set(unit, hgtid, mc_index, enable)); 9088 } 9089 } 9090 return BCM_E_NONE; 9091 } 9092 9093 /* 9094 * Function: 9095 * _bcm_trident_trunk_override_ipmc_get 9096 * Purpose: 9097 * Get Higig trunk override for IPMC group. 9098 * Parameters: 9099 * unit - (IN) SOC unit number. 9100 * hgtid - (IN) Higig trunk group ID. 9101 * idx - (IN) IPMC index. 9102 * enable - (OUT) Pointer to Higig trunk override enable. 9103 * Returns: 9104 * BCM_E_xxx 9105 */ 9106 int 9107 _bcm_trident_trunk_override_ipmc_get(int unit, 9108 bcm_trunk_t hgtid, 9109 int idx, 9110 int *enable) 9111 { 9112 ipmc_entry_t ipmc_entry; 9113 ing_higig_trunk_override_profile_entry_t hgo_profile_entry; 9114 9115 int profile_ptr; 9116 int hgo_bits, alloc_sz; 9117 SHR_BITDCL *hgo_bitmap = NULL; 9118 9119 SOC_IF_ERROR_RETURN 9120 (READ_L3_IPMCm(unit, MEM_BLOCK_ANY, idx, &ipmc_entry)); 9121 9122 profile_ptr = soc_L3_IPMCm_field32_get(unit, &ipmc_entry, 9123 HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf); 9124 9125 SOC_IF_ERROR_RETURN 9126 (READ_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm(unit, MEM_BLOCK_ANY, 9127 profile_ptr, &hgo_profile_entry)); 9128 hgo_bits = soc_mem_field_length(unit, 9129 ING_HIGIG_TRUNK_OVERRIDE_PROFILEm, 9130 HIGIG_TRUNK_OVERRIDE_BITMAPf); 9131 alloc_sz = SHR_BITALLOCSIZE(hgo_bits); 9132 hgo_bitmap = sal_alloc(alloc_sz, "HGT override bitmap"); 9133 if (hgo_bitmap == NULL) { 9134 return BCM_E_MEMORY; 9135 } 9136 soc_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm_field_get(unit, 9137 &hgo_profile_entry, HIGIG_TRUNK_OVERRIDE_BITMAPf, hgo_bitmap); 9138 9139 *enable = SHR_BITGET(hgo_bitmap, hgtid) ? 1 : 0; 9140 9141 sal_free(hgo_bitmap); 9142 hgo_bitmap = NULL; 9143 9144 return BCM_E_NONE; 9145 } 9146 9147 /* 9148 * Function: 9149 * _bcm_trident_trunk_override_vlan_set 9150 * Purpose: 9151 * Set Higig trunk override in VLAN table. 9152 * Parameters: 9153 * unit - (IN) SOC unit number. 9154 * hgtid - (IN) Higig trunk group ID. 9155 * idx - (IN) VLAN table index. 9156 * enable - (IN) Higig trunk override enable. 9157 * Returns: 9158 * BCM_E_xxx 9159 */ 9160 int 9161 _bcm_trident_trunk_override_vlan_set(int unit, 9162 bcm_trunk_t hgtid, 9163 int idx, 9164 int enable) 9165 { 9166 vlan_tab_entry_t vlan_tab_entry; 9167 ing_higig_trunk_override_profile_entry_t hgo_profile_entry; 9168 9169 int rv; 9170 uint32 old_profile_ptr, new_profile_ptr; 9171 int hgo_bits, alloc_sz; 9172 SHR_BITDCL *hgo_bitmap = NULL; 9173 void *entry_ptr; 9174 9175 /* Get old profile entry */ 9176 9177 soc_mem_lock(unit, VLAN_TABm); 9178 rv = READ_VLAN_TABm(unit, MEM_BLOCK_ANY, idx, &vlan_tab_entry); 9179 if (SOC_FAILURE(rv)) { 9180 soc_mem_unlock(unit, VLAN_TABm); 9181 return rv; 9182 } 9183 9184 old_profile_ptr = soc_VLAN_TABm_field32_get(unit, &vlan_tab_entry, 9185 HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf); 9186 rv = READ_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm(unit, MEM_BLOCK_ANY, 9187 old_profile_ptr, &hgo_profile_entry); 9188 if (SOC_FAILURE(rv)) { 9189 soc_mem_unlock(unit, VLAN_TABm); 9190 return rv; 9191 } 9192 9193 hgo_bits = soc_mem_field_length(unit, 9194 ING_HIGIG_TRUNK_OVERRIDE_PROFILEm, 9195 HIGIG_TRUNK_OVERRIDE_BITMAPf); 9196 alloc_sz = SHR_BITALLOCSIZE(hgo_bits); 9197 hgo_bitmap = sal_alloc(alloc_sz, "HGT override bitmap"); 9198 if (hgo_bitmap == NULL) { 9199 soc_mem_unlock(unit, VLAN_TABm); 9200 return BCM_E_MEMORY; 9201 } 9202 /* Add new profile entry */ 9203 soc_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm_field_get(unit, 9204 &hgo_profile_entry, HIGIG_TRUNK_OVERRIDE_BITMAPf, hgo_bitmap); 9205 if (enable) { 9206 SHR_BITSET(hgo_bitmap, hgtid); 9207 } else { 9208 SHR_BITCLR(hgo_bitmap, hgtid); 9209 } 9210 soc_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm_field_set(unit, 9211 &hgo_profile_entry, HIGIG_TRUNK_OVERRIDE_BITMAPf, hgo_bitmap); 9212 sal_free(hgo_bitmap); 9213 hgo_bitmap = NULL; 9214 9215 entry_ptr = &hgo_profile_entry; 9216 rv = soc_profile_mem_add(unit, _trident_hg_trunk_override_profile[unit], 9217 &entry_ptr, 1, &new_profile_ptr); 9218 if (SOC_FAILURE(rv)) { 9219 soc_mem_unlock(unit, VLAN_TABm); 9220 return rv; 9221 } 9222 9223 soc_VLAN_TABm_field32_set(unit, &vlan_tab_entry, HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf, 9224 new_profile_ptr); 9225 rv = WRITE_VLAN_TABm(unit, MEM_BLOCK_ALL, idx, &vlan_tab_entry); 9226 soc_mem_unlock(unit, VLAN_TABm); 9227 if (SOC_FAILURE(rv)) { 9228 return rv; 9229 } 9230 9231 /* Delete old profile entry */ 9232 rv = soc_profile_mem_delete(unit, _trident_hg_trunk_override_profile[unit], 9233 old_profile_ptr); 9234 9235 return rv; 9236 } 9237 9238 /* 9239 * Function: 9240 * _bcm_trident_trunk_override_vlan_get 9241 * Purpose: 9242 * Get Higig trunk override for VLAN table. 9243 * Parameters: 9244 * unit - (IN) SOC unit number. 9245 * hgtid - (IN) Higig trunk group ID. 9246 * idx - (IN) VLAN table index. 9247 * enable - (OUT) Pointer to Higig trunk override enable. 9248 * Returns: 9249 * BCM_E_xxx 9250 */ 9251 int 9252 _bcm_trident_trunk_override_vlan_get(int unit, 9253 bcm_trunk_t hgtid, 9254 int idx, 9255 int *enable) 9256 { 9257 vlan_tab_entry_t vlan_tab_entry; 9258 ing_higig_trunk_override_profile_entry_t hgo_profile_entry; 9259 9260 int profile_ptr; 9261 int hgo_bits, alloc_sz; 9262 SHR_BITDCL *hgo_bitmap = NULL; 9263 9264 SOC_IF_ERROR_RETURN 9265 (READ_VLAN_TABm(unit, MEM_BLOCK_ANY, idx, &vlan_tab_entry)); 9266 9267 profile_ptr = soc_VLAN_TABm_field32_get(unit, &vlan_tab_entry, 9268 HIGIG_TRUNK_OVERRIDE_PROFILE_PTRf); 9269 9270 SOC_IF_ERROR_RETURN 9271 (READ_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm(unit, MEM_BLOCK_ANY, 9272 profile_ptr, &hgo_profile_entry)); 9273 9274 hgo_bits = soc_mem_field_length(unit, 9275 ING_HIGIG_TRUNK_OVERRIDE_PROFILEm, 9276 HIGIG_TRUNK_OVERRIDE_BITMAPf); 9277 alloc_sz = SHR_BITALLOCSIZE(hgo_bits); 9278 hgo_bitmap = sal_alloc(alloc_sz, "HGT override bitmap"); 9279 if (hgo_bitmap == NULL) { 9280 return BCM_E_MEMORY; 9281 } 9282 soc_ING_HIGIG_TRUNK_OVERRIDE_PROFILEm_field_get(unit, 9283 &hgo_profile_entry, HIGIG_TRUNK_OVERRIDE_BITMAPf, hgo_bitmap); 9284 9285 *enable = SHR_BITGET(hgo_bitmap, hgtid) ? 1 : 0; 9286 9287 sal_free(hgo_bitmap); 9288 hgo_bitmap = NULL; 9289 9290 return BCM_E_NONE; 9291 } 9292 9293 /* ----------------------------------------------------------------------------- 9294 * 9295 * Routines shared by front panel and Higig trunking 9296 * 9297 * ----------------------------------------------------------------------------- 9298 */ 9299 9300 /* 9301 * Function: 9302 * bcm_trident_trunk_destroy 9303 * Purpose: 9304 * Remove trunk group. 9305 * Parameters: 9306 * unit - (IN) SOC unit number. 9307 * tid - (IN) Trunk group ID. 9308 * t_info - (IN) Pointer to trunk info. 9309 * Returns: 9310 * BCM_E_xxx 9311 */ 9312 int 9313 bcm_trident_trunk_destroy(int unit, 9314 bcm_trunk_t tid, 9315 trunk_private_t *t_info) 9316 { 9317 bcm_trunk_chip_info_t chip_info; 9318 int hgtid; 9319 9320 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 9321 if (chip_info.trunk_fabric_id_min >= 0 && 9322 tid >= chip_info.trunk_fabric_id_min) { /* fabric trunk */ 9323 hgtid = tid - chip_info.trunk_fabric_id_min; 9324 return _bcm_trident_trunk_fabric_destroy(unit, hgtid, t_info); 9325 } 9326 9327 /* Front panel trunks */ 9328 return _bcm_trident_trunk_fp_destroy(unit, tid, t_info); 9329 } 9330 9331 /* 9332 * Function: 9333 * _trident_trunk_add_info_member_alloc 9334 * Purpose: 9335 * Allocate member_flags, tp, and tm of _esw_trunk_add_info_t. 9336 * Parameters: 9337 * add_info - (IN) Pointer to trident trunk add info structure. 9338 * num_ports - (IN) Number of member ports. 9339 * Returns: 9340 * BCM_E_xxx 9341 */ 9342 STATIC int 9343 _trident_trunk_add_info_member_alloc(_esw_trunk_add_info_t *add_info, 9344 int num_ports) 9345 { 9346 int rv = BCM_E_NONE; 9347 9348 add_info->member_flags = sal_alloc(sizeof(uint32) * num_ports, 9349 "_trident_trunk_add_info_member_flags"); 9350 if (add_info->member_flags == NULL) { 9351 rv = BCM_E_MEMORY; 9352 goto error; 9353 } 9354 sal_memset(add_info->member_flags, 0, sizeof(uint32) * num_ports); 9355 9356 add_info->tp = sal_alloc(sizeof(bcm_port_t) * num_ports, 9357 "_trident_trunk_add_info_tp"); 9358 if (add_info->tp == NULL) { 9359 rv = BCM_E_MEMORY; 9360 goto error; 9361 } 9362 sal_memset(add_info->tp, 0, sizeof(bcm_port_t) * num_ports); 9363 9364 add_info->tm = sal_alloc(sizeof(bcm_module_t) * num_ports, 9365 "_trident_trunk_add_info_tm"); 9366 if (add_info->tm == NULL) { 9367 rv = BCM_E_MEMORY; 9368 goto error; 9369 } 9370 sal_memset(add_info->tm, 0, sizeof(bcm_module_t) * num_ports); 9371 9372 add_info->dynamic_scaling_factor = sal_alloc(sizeof(int) * num_ports, 9373 "_trident_trunk_add_info_dynamic_scaling_factor"); 9374 if (add_info->dynamic_scaling_factor == NULL) { 9375 rv = BCM_E_MEMORY; 9376 goto error; 9377 } 9378 sal_memset(add_info->dynamic_scaling_factor, 0, sizeof(int) * num_ports); 9379 9380 add_info->dynamic_load_weight = sal_alloc(sizeof(int) * num_ports, 9381 "_trident_trunk_add_info_dynamic_load_weight"); 9382 if (add_info->dynamic_load_weight == NULL) { 9383 rv = BCM_E_MEMORY; 9384 goto error; 9385 } 9386 sal_memset(add_info->dynamic_load_weight, 0, sizeof(int) * num_ports); 9387 9388 add_info->dynamic_queue_size_weight = sal_alloc(sizeof(int) * num_ports, 9389 "_trident_trunk_add_info_dynamic_queue_size_weight"); 9390 if (add_info->dynamic_queue_size_weight == NULL) { 9391 rv = BCM_E_MEMORY; 9392 goto error; 9393 } 9394 sal_memset(add_info->dynamic_queue_size_weight, 0, sizeof(int) * num_ports); 9395 9396 return rv; 9397 9398 error: 9399 if (NULL != add_info->member_flags) { 9400 sal_free(add_info->member_flags); 9401 } 9402 if (NULL != add_info->tp) { 9403 sal_free(add_info->tp); 9404 } 9405 if (NULL != add_info->tm) { 9406 sal_free(add_info->tm); 9407 } 9408 if (NULL != add_info->dynamic_scaling_factor) { 9409 sal_free(add_info->dynamic_scaling_factor); 9410 } 9411 if (NULL != add_info->dynamic_load_weight) { 9412 sal_free(add_info->dynamic_load_weight); 9413 } 9414 if (NULL != add_info->dynamic_queue_size_weight) { 9415 sal_free(add_info->dynamic_queue_size_weight); 9416 } 9417 9418 return rv; 9419 } 9420 9421 /* 9422 * Function: 9423 * _trident_trunk_add_info_member_free 9424 * Purpose: 9425 * Free member_flags, tp, and tm of _esw_trunk_add_info_t. 9426 * Parameters: 9427 * add_info - (IN) Pointer to trident trunk add info structure. 9428 * Returns: 9429 * BCM_E_xxx 9430 */ 9431 STATIC void 9432 _trident_trunk_add_info_member_free(_esw_trunk_add_info_t *add_info) 9433 { 9434 if (NULL != add_info->member_flags) { 9435 sal_free(add_info->member_flags); 9436 } 9437 if (NULL != add_info->tp) { 9438 sal_free(add_info->tp); 9439 } 9440 if (NULL != add_info->tm) { 9441 sal_free(add_info->tm); 9442 } 9443 if (NULL != add_info->dynamic_scaling_factor) { 9444 sal_free(add_info->dynamic_scaling_factor); 9445 } 9446 if (NULL != add_info->dynamic_load_weight) { 9447 sal_free(add_info->dynamic_load_weight); 9448 } 9449 if (NULL != add_info->dynamic_queue_size_weight) { 9450 sal_free(add_info->dynamic_queue_size_weight); 9451 } 9452 } 9453 9454 /* 9455 * Function: 9456 * _bcm_trident_trunk_modify 9457 * Purpose: 9458 * Set, add or delete trunk members. 9459 * Parameters: 9460 * unit - (IN) SOC unit number. 9461 * tid - (IN) Trunk group ID. 9462 * add_info - (IN) Pointer to trident trunk add info structure. 9463 * t_info - (IN) Pointer to trunk info. 9464 * op - (IN) Type of operation: TRUNK_MEMBER_OP_SET, ADD or DELETE. 9465 * member - (IN) Member to add or delete. 9466 * Returns: 9467 * BCM_E_xxx 9468 */ 9469 STATIC int 9470 _bcm_trident_trunk_modify(int unit, 9471 bcm_trunk_t tid, 9472 _esw_trunk_add_info_t *add_info, 9473 trunk_private_t *t_info, 9474 trunk_private_t *stored_info, 9475 int op, 9476 bcm_trunk_member_t *member) 9477 { 9478 bcm_trunk_chip_info_t chip_info; 9479 int hgtid; 9480 9481 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 9482 9483 if (chip_info.trunk_fabric_id_min >= 0 && 9484 tid >= chip_info.trunk_fabric_id_min) { 9485 /* Higig trunks */ 9486 hgtid = tid - chip_info.trunk_fabric_id_min; 9487 return _bcm_trident_trunk_fabric_modify(unit, hgtid, add_info, t_info, 9488 stored_info, op, member); 9489 } 9490 9491 /* Front panel trunks */ 9492 return _bcm_trident_trunk_fp_modify(unit, tid, add_info, t_info, 9493 stored_info, op, member); 9494 } 9495 9496 /* 9497 * Function: 9498 * _bcm_trident_hg_dlb_status_get 9499 * Purpose: 9500 * Check if dynamic load balancing is enabled on any Higig trunk group. 9501 * Parameters: 9502 * unit - (IN) SOC unit number. 9503 * dlb_status - (OUT) Higig DLB status 9504 * Returns: 9505 * BCM_E_xxx 9506 */ 9507 STATIC int 9508 _bcm_trident_hg_dlb_status_get(int unit, int *dlb_status) 9509 { 9510 int rv = BCM_E_NONE; 9511 bcm_trunk_chip_info_t chip_info; 9512 int i; 9513 int psc; 9514 9515 *dlb_status = FALSE; 9516 9517 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 9518 if (chip_info.trunk_fabric_id_min < 0) { 9519 /* There are no Higig trunk groups. */ 9520 return BCM_E_NOT_FOUND; 9521 } 9522 9523 for (i = chip_info.trunk_fabric_id_min; 9524 i <= chip_info.trunk_fabric_id_max; i++) { 9525 rv = bcm_esw_trunk_psc_get(unit, i, &psc); 9526 if (rv == BCM_E_NOT_FOUND) { 9527 continue; 9528 } 9529 if ((psc == BCM_TRUNK_PSC_DYNAMIC) || 9530 (psc == BCM_TRUNK_PSC_DYNAMIC_ASSIGNED) || 9531 (psc == BCM_TRUNK_PSC_DYNAMIC_OPTIMAL)) { 9532 *dlb_status = TRUE; 9533 break; 9534 } 9535 } 9536 9537 return BCM_E_NONE; 9538 } 9539 9540 #ifdef BCM_TRIDENT3_SUPPORT 9541 /* 9542 * Function: 9543 * _bcm_trident_hg_dlb_status_get 9544 * Purpose: 9545 * Check if dynamic load balancing is enabled on any lag trunk group. 9546 * Parameters: 9547 * unit - (IN) SOC unit number. 9548 * dlb_status - (OUT) lag DLB status 9549 * Returns: 9550 * BCM_E_xxx 9551 */ 9552 STATIC int 9553 _bcm_trident_lag_dlb_status_get(int unit, int *dlb_status) 9554 { 9555 int rv = BCM_E_NONE; 9556 bcm_trunk_chip_info_t chip_info; 9557 int i; 9558 int psc; 9559 9560 *dlb_status = FALSE; 9561 9562 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 9563 if (chip_info.trunk_id_min < 0) { 9564 /* There are no Higig trunk groups. */ 9565 return BCM_E_NOT_FOUND; 9566 } 9567 9568 for (i = chip_info.trunk_id_min; 9569 i <= chip_info.trunk_id_max; i++) { 9570 rv = bcm_esw_trunk_psc_get(unit, i, &psc); 9571 if (rv == BCM_E_NOT_FOUND) { 9572 continue; 9573 } 9574 if ((psc == BCM_TRUNK_PSC_DYNAMIC) || 9575 (psc == BCM_TRUNK_PSC_DYNAMIC_ASSIGNED) || 9576 (psc == BCM_TRUNK_PSC_DYNAMIC_OPTIMAL)) { 9577 *dlb_status = TRUE; 9578 break; 9579 } 9580 } 9581 9582 return BCM_E_NONE; 9583 } 9584 9585 /* 9586 * Function: 9587 * bcm_td2_lag_rh_status_get 9588 * Purpose: 9589 * Check if resilient hashing is enabled on any lag trunk group. 9590 * Parameters: 9591 * unit - (IN) SOC unit number. 9592 * rh_status - (OUT) lag resilient hashing status 9593 * Returns: 9594 * BCM_E_xxx 9595 */ 9596 static int 9597 bcm_td2_lag_rh_status_get(int unit, int *rh_status) 9598 { 9599 bcm_trunk_chip_info_t chip_info; 9600 int i; 9601 int psc; 9602 int rv; 9603 9604 *rh_status = FALSE; 9605 9606 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 9607 if (chip_info.trunk_id_min < 0) { 9608 /* There are no Higig trunk groups. */ 9609 return BCM_E_NOT_FOUND; 9610 } 9611 9612 for (i = chip_info.trunk_id_min; 9613 i <= chip_info.trunk_id_max; i++) { 9614 rv = bcm_esw_trunk_psc_get(unit, i, &psc); 9615 if ((rv != BCM_E_NONE) && (rv != BCM_E_NOT_FOUND)) { 9616 return rv; 9617 } 9618 if (psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) { 9619 *rh_status = TRUE; 9620 break; 9621 } 9622 } 9623 9624 return BCM_E_NONE; 9625 } 9626 #endif 9627 9628 9629 /* 9630 * Function: 9631 * _bcm_trident_trunk_clear 9632 * Purpose: 9633 * Clear existing trunk group members if any. 9634 * Parameters: 9635 * unit - (IN) SOC unit number. 9636 * tid - (IN) Trunk group ID. 9637 * t_info - (IN) Pointer to trunk info. 9638 * Returns: 9639 * BCM_E_xxx 9640 */ 9641 STATIC int 9642 _bcm_trident_trunk_clear(int unit, 9643 bcm_trunk_t tid, 9644 trunk_private_t *t_info) 9645 { 9646 bcm_trunk_chip_info_t chip_info; 9647 int higig_trunk; 9648 #ifdef BCM_TRIDENT2_SUPPORT 9649 int hgtid; 9650 #endif 9651 9652 if (t_info->in_use) { 9653 BCM_IF_ERROR_RETURN(bcm_trident_trunk_destroy(unit, tid, t_info)); 9654 } 9655 9656 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 9657 if (chip_info.trunk_fabric_id_min >= 0 && 9658 tid >= chip_info.trunk_fabric_id_min) { 9659 higig_trunk = 1; 9660 #ifdef BCM_TRIDENT2_SUPPORT 9661 hgtid = tid - chip_info.trunk_fabric_id_min; 9662 #endif 9663 } else { 9664 higig_trunk = 0; 9665 } 9666 9667 if (higig_trunk) { 9668 #ifdef BCM_TRIDENT2_SUPPORT 9669 if (soc_feature(unit, soc_feature_hg_resilient_hash)) { 9670 if (t_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) { 9671 /* Write the dynamic_size to hardware, so it can be recovered 9672 * during warm boot. 9673 */ 9674 BCM_IF_ERROR_RETURN(bcm_td2_hg_rh_dynamic_size_set(unit, hgtid, 9675 t_info->dynamic_size)); 9676 } 9677 } 9678 #endif /* BCM_TRIDENT2_SUPPORT */ 9679 } else { 9680 #ifdef BCM_TRIDENT2_SUPPORT 9681 if (soc_feature(unit, soc_feature_lag_resilient_hash)) { 9682 if (t_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) { 9683 /* Write the dynamic_size to hardware, so it can be recovered 9684 * during warm boot. 9685 */ 9686 BCM_IF_ERROR_RETURN(bcm_td2_lag_rh_dynamic_size_set(unit, tid, 9687 t_info->dynamic_size)); 9688 } 9689 } 9690 #endif /* BCM_TRIDENT2_SUPPORT */ 9691 } 9692 9693 return BCM_E_NONE; 9694 } 9695 9696 /* 9697 * Function: 9698 * bcm_trident_trunk_modify 9699 * Purpose: 9700 * Set, add or delete trunk members. 9701 * Parameters: 9702 * unit - (IN) SOC unit number. 9703 * tid - (IN) Trunk group ID. 9704 * trunk_info - (IN) Pointer to user provided trunk info. 9705 * member_count - (IN) Number of trunk members. 9706 * member_array - (IN) Array of trunk members. 9707 * t_info - (IN) Pointer to internal trunk info. 9708 * op - (IN) Type of operation: TRUNK_MEMBER_OP_SET, ADD or DELETE. 9709 * member - (IN) Member to add or delete. 9710 * Returns: 9711 * BCM_E_xxx 9712 */ 9713 int 9714 bcm_trident_trunk_modify(int unit, 9715 bcm_trunk_t tid, 9716 bcm_trunk_info_t *trunk_info, 9717 int member_count, 9718 bcm_trunk_member_t *member_array, 9719 trunk_private_t *t_info, 9720 int op, 9721 bcm_trunk_member_t *member) 9722 { 9723 int dlb_enable=0, rh_enable=0; 9724 bcm_trunk_chip_info_t chip_info; 9725 int rv = BCM_E_NONE; 9726 int dynamic_size_encode; 9727 int dlb_status; 9728 _esw_trunk_add_info_t add_info; 9729 int i; 9730 int higig_trunk; 9731 trunk_private_t stored_info; 9732 #ifdef INCLUDE_L3 9733 int old_member_count, old_local_member_cnt = 0; 9734 bcm_trunk_info_t tmp_trunk_info; 9735 bcm_trunk_member_t *tmp_member_array = NULL; 9736 trunk_private_t tmp_t_info; 9737 bcm_port_t *tmp_member_port_array = NULL; 9738 bcm_module_t member_modid; 9739 bcm_trunk_t member_tgid; 9740 int member_id, mod_is_local; 9741 bcm_gport_t *tmp_member_gport_array = NULL; 9742 #endif 9743 9744 if (trunk_info->psc <= 0) { 9745 trunk_info->psc = BCM_TRUNK_PSC_DEFAULT; 9746 } 9747 9748 if ((trunk_info->psc == BCM_TRUNK_PSC_DYNAMIC) || 9749 (trunk_info->psc == BCM_TRUNK_PSC_DYNAMIC_ASSIGNED) || 9750 (trunk_info->psc == BCM_TRUNK_PSC_DYNAMIC_OPTIMAL)) { 9751 dlb_enable = 1; 9752 } else if (trunk_info->psc == BCM_TRUNK_PSC_DYNAMIC_RESILIENT) { 9753 rh_enable = 1; 9754 } 9755 9756 #ifdef INCLUDE_L3 9757 sal_memset(&tmp_t_info, 0, sizeof(trunk_private_t)); 9758 #endif 9759 sal_memcpy(&stored_info, t_info, sizeof(trunk_private_t)); 9760 9761 BCM_IF_ERROR_RETURN 9762 (_bcm_trident_trunk_psc_to_rtag(unit, trunk_info->psc, &(t_info->rtag))); 9763 t_info->psc = trunk_info->psc; 9764 9765 t_info->flags = trunk_info->flags; 9766 9767 if ((trunk_info->dlf_index != trunk_info->mc_index) || 9768 (trunk_info->dlf_index != trunk_info->ipmc_index)) { 9769 return BCM_E_PARAM; 9770 } 9771 t_info->dlf_index_spec = 9772 t_info->dlf_index_used = 9773 t_info->mc_index_spec = 9774 t_info->mc_index_used = 9775 t_info->ipmc_index_spec = 9776 t_info->ipmc_index_used = trunk_info->dlf_index; 9777 9778 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 9779 if (chip_info.trunk_fabric_id_min >= 0 && 9780 tid >= chip_info.trunk_fabric_id_min) { 9781 higig_trunk = 1; 9782 } else { 9783 higig_trunk = 0; 9784 } 9785 9786 if (!higig_trunk) { 9787 /* Front panel trunks */ 9788 9789 if (dlb_enable) { 9790 #ifdef BCM_TRIUMPH3_SUPPORT 9791 if (soc_feature(unit, soc_feature_lag_dlb)) { 9792 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 9793 if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 9794 uint32 hw_limit; 9795 /* Verify dynamic_size */ 9796 BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_dynamic_size_encode( 9797 trunk_info->dynamic_size, &dynamic_size_encode)); 9798 t_info->dynamic_size = trunk_info->dynamic_size; 9799 9800 /* Verify dynamic_age */ 9801 hw_limit = (1 << soc_mem_field_length( 9802 unit, DLB_HGT_LAG_GROUP_CONTROLm, 9803 INACTIVITY_DURATIONf)) - 1; 9804 if (trunk_info->dynamic_age < 16 || 9805 trunk_info->dynamic_age > hw_limit) { 9806 /* Hardware limits */ 9807 return BCM_E_PARAM; 9808 } 9809 t_info->dynamic_age = trunk_info->dynamic_age; 9810 #ifdef BCM_TRIDENT3_SUPPORT 9811 if (soc_feature(unit, soc_feature_td3_dlb)) { 9812 int lag_rh_status; 9813 9814 BCM_IF_ERROR_RETURN(bcm_td2_lag_rh_status_get(unit, &lag_rh_status)); 9815 if (lag_rh_status) { 9816 /* LAG DLB and resilient hashing cannot be enabled 9817 * at the same time. 9818 */ 9819 return BCM_E_PARAM; 9820 } 9821 } 9822 #endif /* BCM_TRIDENT3_SUPPORT */ 9823 } else 9824 #endif /* BCM_TOMAHAWK2_SUPPORT */ 9825 { 9826 /* Verify dynamic_size */ 9827 BCM_IF_ERROR_RETURN(bcm_tr3_lag_dlb_dynamic_size_encode( 9828 trunk_info->dynamic_size, &dynamic_size_encode)); 9829 t_info->dynamic_size = trunk_info->dynamic_size; 9830 9831 /* Verify dynamic_age */ 9832 /* Error rate in calculating INACTIVITY_DURATION is higher 9833 if it is allowed to be configured too low. 9834 Minimum limit of 16 microseconds is required to reduce 9835 the error rate in time duration calculation.*/ 9836 if ((trunk_info->dynamic_age < 16) || 9837 (trunk_info->dynamic_age > 0xffff)) { 9838 return BCM_E_PARAM; 9839 } 9840 t_info->dynamic_age = trunk_info->dynamic_age; 9841 9842 /* Verify dynamic exponents */ 9843 if (trunk_info->dynamic_load_exponent > 0xf) { 9844 return BCM_E_PARAM; 9845 } 9846 t_info->dynamic_load_exponent = 9847 trunk_info->dynamic_load_exponent; 9848 9849 if (trunk_info->dynamic_expected_load_exponent > 0xf) { 9850 return BCM_E_PARAM; 9851 } 9852 t_info->dynamic_expected_load_exponent = 9853 trunk_info->dynamic_expected_load_exponent; 9854 if (soc_feature(unit, soc_feature_td3_dlb)) { 9855 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, 9856 ENHANCED_HASHING_CONTROL_2r, REG_PORT_ANY, 9857 RH_DLB_SELECTIONf, 0)); 9858 } 9859 } 9860 } else 9861 #endif /* BCM_TRIUMPH3_SUPPORT */ 9862 { 9863 /* Dynamic load balancing not supported for LAGs */ 9864 return BCM_E_UNAVAIL; 9865 } 9866 } else if (rh_enable) { 9867 #ifdef BCM_TRIDENT2_SUPPORT 9868 if (soc_feature(unit, soc_feature_lag_resilient_hash)) { 9869 /* Verify dynamic_size */ 9870 BCM_IF_ERROR_RETURN(bcm_td2_lag_rh_dynamic_size_encode(unit, 9871 trunk_info->dynamic_size, &dynamic_size_encode)); 9872 t_info->dynamic_size = trunk_info->dynamic_size; 9873 #ifdef BCM_TRIDENT3_SUPPORT 9874 if (soc_feature(unit, soc_feature_td3_dlb)) { 9875 BCM_IF_ERROR_RETURN 9876 (_bcm_trident_lag_dlb_status_get(unit, &dlb_status)); 9877 if (dlb_status) { 9878 /* DLB and resilient hashing cannot be enabled 9879 * at the same time. 9880 */ 9881 return BCM_E_PARAM; 9882 } 9883 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, 9884 ENHANCED_HASHING_CONTROL_2r, 9885 REG_PORT_ANY, RH_DLB_SELECTIONf,1)); 9886 } 9887 #endif /* BCM_TRIDENT3_SUPPORT */ 9888 } else 9889 #endif /* BCM_TRIDENT2_SUPPORT */ 9890 { 9891 /* Resilient hashing not supported for LAGs */ 9892 return BCM_E_UNAVAIL; 9893 } 9894 } 9895 9896 } else { 9897 /* Higig trunk */ 9898 9899 if (dlb_enable) { 9900 if (soc_feature(unit, soc_feature_hg_dlb)) { 9901 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 9902 if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 9903 uint32 hw_limit; 9904 /* Verify dynamic_size */ 9905 BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_dynamic_size_encode( 9906 trunk_info->dynamic_size, &dynamic_size_encode)); 9907 t_info->dynamic_size = trunk_info->dynamic_size; 9908 9909 /* Verify dynamic_age */ 9910 hw_limit = (1 << soc_mem_field_length( 9911 unit, DLB_HGT_LAG_GROUP_CONTROLm, 9912 INACTIVITY_DURATIONf)) - 1; 9913 if (trunk_info->dynamic_age < 16 || 9914 trunk_info->dynamic_age > hw_limit) { 9915 /* Hardware limits */ 9916 return BCM_E_PARAM; 9917 } 9918 t_info->dynamic_age = trunk_info->dynamic_age; 9919 } else 9920 #endif /* BCM_TOMAHAWK2_SUPPORT */ 9921 { 9922 /* Verify dynamic_size */ 9923 BCM_IF_ERROR_RETURN(_bcm_trident_hg_dlb_dynamic_size_encode( 9924 trunk_info->dynamic_size, &dynamic_size_encode)); 9925 t_info->dynamic_size = trunk_info->dynamic_size; 9926 9927 /* Verify dynamic_age */ 9928 if ((trunk_info->dynamic_age < 16) || 9929 (trunk_info->dynamic_age > 0x7fff)) { 9930 return BCM_E_PARAM; 9931 } 9932 t_info->dynamic_age = trunk_info->dynamic_age; 9933 } 9934 } else { 9935 /* Dynamic load balancing not supported for Higig trunks */ 9936 return BCM_E_UNAVAIL; 9937 } 9938 9939 #ifdef BCM_TRIDENT2_SUPPORT 9940 if (soc_feature(unit, soc_feature_hg_resilient_hash)) { 9941 int rh_status; 9942 9943 BCM_IF_ERROR_RETURN(bcm_td2_hg_rh_status_get(unit, &rh_status)); 9944 if (rh_status) { 9945 /* Higig DLB and resilient hashing cannot be enabled 9946 * at the same time. 9947 */ 9948 return BCM_E_PARAM; 9949 } 9950 } 9951 9952 if (SOC_REG_IS_VALID(unit, ENHANCED_HASHING_CONTROLr)) { 9953 if (soc_feature(unit, soc_feature_td3_dlb)) { 9954 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, 9955 ENHANCED_HASHING_CONTROL_2r, REG_PORT_ANY, 9956 RH_DLB_SELECTIONf, 0)); 9957 } else { 9958 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, 9959 ENHANCED_HASHING_CONTROLr, REG_PORT_ANY, 9960 RH_HGT_ENABLEf, 0)); 9961 } 9962 } 9963 /* On TD2/TD2+ even when DLB is disabled, parity is still calculated 9964 * for both RH_HGT_FLOWSET view and DLB_HGT_FLOWSET view. As a result, 9965 * erroneous parity error would be reported for DLB_HGT_FLOWSET. So only when 9966 * using DLB enable DLB parity control, otherwise disable. 9967 */ 9968 if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit))) { 9969 soc_td2x_ser_dlb_parity_set(unit, 1); 9970 } 9971 #endif /* BCM_TRIDENT2_SUPPORT */ 9972 9973 } else if (rh_enable) { 9974 9975 #ifdef BCM_TRIDENT2_SUPPORT 9976 if (soc_feature(unit, soc_feature_hg_resilient_hash)) { 9977 /* Verify dynamic_size */ 9978 BCM_IF_ERROR_RETURN(bcm_td2_hg_rh_dynamic_size_encode(unit, 9979 trunk_info->dynamic_size, &dynamic_size_encode)); 9980 t_info->dynamic_size = trunk_info->dynamic_size; 9981 } else 9982 #endif /* BCM_TRIDENT2_SUPPORT */ 9983 { 9984 /* Resilient hashing not supported for Higig trunks */ 9985 return BCM_E_UNAVAIL; 9986 } 9987 9988 if (soc_feature(unit, soc_feature_hg_dlb)) { 9989 BCM_IF_ERROR_RETURN 9990 (_bcm_trident_hg_dlb_status_get(unit, &dlb_status)); 9991 if (dlb_status) { 9992 /* DLB and resilient hashing cannot be enabled 9993 * at the same time. 9994 */ 9995 return BCM_E_PARAM; 9996 } 9997 } 9998 9999 #ifdef BCM_TRIDENT2_SUPPORT 10000 if (SOC_REG_IS_VALID(unit, ENHANCED_HASHING_CONTROLr)) { 10001 if (soc_feature(unit, soc_feature_td3_dlb)) { 10002 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, 10003 ENHANCED_HASHING_CONTROL_2r, 10004 REG_PORT_ANY, RH_DLB_SELECTIONf,1)); 10005 } else { 10006 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, 10007 ENHANCED_HASHING_CONTROLr, REG_PORT_ANY, 10008 RH_HGT_ENABLEf, 1)); 10009 } 10010 } 10011 if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit))) { 10012 soc_td2x_ser_dlb_parity_set(unit, 0); 10013 } 10014 #endif /* BCM_TRIDENT2_SUPPORT */ 10015 } 10016 } 10017 10018 if (member_count < 1) { 10019 /* Member count is less than 1 when the operation is 10020 * TRUNK_MEMBER_OP_SET with zero members or TRUNK_MEMBER_OP_DELETE 10021 * on the final member of the group. In either case, 10022 * clear the existing trunk member ports if any. 10023 */ 10024 #ifdef INCLUDE_L3 10025 if ((chip_info.trunk_fabric_id_min >= 0 && 10026 tid >= chip_info.trunk_fabric_id_min) == 0) { 10027 if (soc_feature(unit, soc_feature_trill) 10028 || soc_feature(unit, soc_feature_mpls) 10029 || soc_feature(unit, soc_feature_vxlan) 10030 || soc_feature(unit, soc_feature_l2gre)) { 10031 if (op == TRUNK_MEMBER_OP_SET) { 10032 tmp_t_info.in_use = t_info->in_use; 10033 /* Get count of ports in this trunk. */ 10034 BCM_IF_ERROR_RETURN( 10035 bcm_trident_trunk_get(unit, tid, &tmp_trunk_info, 0, 10036 NULL, &old_member_count, &tmp_t_info)); 10037 if (old_member_count) { 10038 tmp_member_array = sal_alloc(sizeof(bcm_trunk_member_t) * 10039 old_member_count, "trunk_member_array"); 10040 if (tmp_member_array == NULL) { 10041 rv = BCM_E_MEMORY; 10042 goto clean_up; 10043 } 10044 sal_memset(tmp_member_array, 0, 10045 sizeof(bcm_trunk_member_t) * old_member_count); 10046 /* Get trunk info */ 10047 rv = bcm_trident_trunk_get(unit, tid, &tmp_trunk_info, 10048 old_member_count, tmp_member_array, 10049 &old_member_count, &tmp_t_info); 10050 if (BCM_FAILURE(rv)) { 10051 goto clean_up; 10052 } 10053 tmp_member_port_array = sal_alloc(sizeof(bcm_port_t) * 10054 old_member_count, "trunk_member_port_array"); 10055 if (tmp_member_port_array == NULL) { 10056 rv = BCM_E_MEMORY; 10057 goto clean_up; 10058 } 10059 sal_memset(tmp_member_port_array, 0, 10060 sizeof(bcm_port_t) * old_member_count); 10061 10062 tmp_member_gport_array = sal_alloc(sizeof(bcm_gport_t) * 10063 old_member_count, "trunk_member_gport_array"); 10064 if (tmp_member_gport_array == NULL) { 10065 rv = BCM_E_MEMORY; 10066 goto clean_up; 10067 } 10068 sal_memset(tmp_member_gport_array, 0, 10069 sizeof(bcm_gport_t) * old_member_count); 10070 10071 old_local_member_cnt = 0; 10072 for (i = 0; i < old_member_count; i++) { 10073 tmp_member_gport_array[i] = tmp_member_array[i].gport; 10074 rv = _bcm_esw_gport_resolve(unit, tmp_member_array[i].gport, 10075 &member_modid, &tmp_member_port_array[i], 10076 &member_tgid, &member_id); 10077 if (BCM_FAILURE(rv)) { 10078 goto clean_up; 10079 } 10080 rv = _bcm_esw_modid_is_local(unit, member_modid, 10081 &mod_is_local); 10082 if (BCM_FAILURE(rv)) { 10083 goto clean_up; 10084 } 10085 10086 if (!mod_is_local) { 10087 continue; 10088 } 10089 10090 tmp_member_port_array[old_local_member_cnt] = 10091 tmp_member_port_array[i]; 10092 old_local_member_cnt++; 10093 } 10094 } 10095 } else if (op == TRUNK_MEMBER_OP_DELETE) { 10096 old_member_count = 1; 10097 tmp_member_port_array = sal_alloc(sizeof(bcm_port_t) * 10098 old_member_count, "trunk_member_port_array"); 10099 if (tmp_member_port_array == NULL) { 10100 rv = BCM_E_MEMORY; 10101 goto clean_up; 10102 } 10103 sal_memset(tmp_member_port_array, 0, 10104 sizeof(bcm_port_t) * old_member_count); 10105 10106 tmp_member_gport_array = sal_alloc(sizeof(bcm_gport_t) * 10107 old_member_count, "trunk_member_gport_array"); 10108 if (tmp_member_gport_array == NULL) { 10109 rv = BCM_E_MEMORY; 10110 goto clean_up; 10111 } 10112 sal_memset(tmp_member_gport_array, 0, 10113 sizeof(bcm_gport_t) * old_member_count); 10114 10115 tmp_member_gport_array[0] = member->gport; 10116 rv = _bcm_esw_gport_resolve(unit, member->gport, 10117 &member_modid, &tmp_member_port_array[0], 10118 &member_tgid, &member_id); 10119 if (BCM_FAILURE(rv)) { 10120 goto clean_up; 10121 } 10122 10123 rv = _bcm_esw_modid_is_local(unit, member_modid, &mod_is_local); 10124 if (BCM_FAILURE(rv)) { 10125 goto clean_up; 10126 } 10127 10128 if (mod_is_local) { 10129 old_local_member_cnt = 1; 10130 } 10131 10132 } else { 10133 rv = BCM_E_PARAM; 10134 goto clean_up; 10135 } 10136 } 10137 } 10138 #endif 10139 rv = _bcm_trident_trunk_clear(unit, tid, t_info); 10140 if (BCM_FAILURE(rv)) { 10141 #ifdef INCLUDE_L3 10142 goto clean_up; 10143 #else 10144 return rv; 10145 #endif 10146 } 10147 #ifdef INCLUDE_L3 10148 if ((chip_info.trunk_fabric_id_min >= 0 && 10149 tid >= chip_info.trunk_fabric_id_min) == 0) { 10150 /* Front Panel trunks */ 10151 /* Remove the my_station_tcam entry for TRILL, 10152 * VxLAN and L2GRE when clearing the trunk. 10153 */ 10154 #ifdef BCM_TRIDENT2_SUPPORT 10155 if (soc_feature(unit, soc_feature_vxlan)) { 10156 if (old_member_count) { 10157 rv = _bcm_esw_vxlan_trunk_member_delete(unit, tid, 10158 old_member_count, tmp_member_gport_array); 10159 } 10160 } 10161 #endif 10162 #ifdef BCM_TRIUMPH3_SUPPORT 10163 if (soc_feature(unit, soc_feature_l2gre)) { 10164 if (old_member_count) { 10165 rv = _bcm_esw_l2gre_trunk_member_delete(unit, tid, 10166 old_member_count, tmp_member_gport_array); 10167 } 10168 } 10169 #endif 10170 if (soc_feature(unit, soc_feature_trill)) { 10171 if (old_local_member_cnt) { 10172 rv = _bcm_esw_trill_trunk_member_delete(unit, tid, 10173 old_local_member_cnt, tmp_member_port_array); 10174 } 10175 } 10176 #ifdef BCM_TRIUMPH_SUPPORT 10177 if (soc_feature(unit, soc_feature_mpls)) { 10178 if (old_local_member_cnt) { 10179 rv = _bcm_esw_mpls_trunk_member_delete(unit, tid, 10180 old_local_member_cnt, tmp_member_port_array); 10181 } 10182 } 10183 #endif 10184 } 10185 #endif 10186 } else { 10187 sal_memset(&add_info, 0, sizeof(_esw_trunk_add_info_t)); 10188 add_info.flags = trunk_info->flags; 10189 add_info.num_ports = member_count; 10190 add_info.psc = trunk_info->psc; 10191 add_info.ipmc_psc = trunk_info->ipmc_psc; 10192 add_info.dlf_index = trunk_info->dlf_index; 10193 add_info.mc_index = trunk_info->mc_index; 10194 add_info.ipmc_index = trunk_info->ipmc_index; 10195 add_info.dynamic_size = trunk_info->dynamic_size; 10196 add_info.dynamic_age = trunk_info->dynamic_age; 10197 add_info.dynamic_load_exponent = trunk_info->dynamic_load_exponent; 10198 add_info.dynamic_expected_load_exponent = 10199 trunk_info->dynamic_expected_load_exponent; 10200 10201 BCM_IF_ERROR_RETURN 10202 (_trident_trunk_add_info_member_alloc(&add_info, member_count)); 10203 for (i = 0; i < member_count; i++) { 10204 add_info.member_flags[i] = member_array[i].flags; 10205 add_info.tp[i] = member_array[i].gport; 10206 add_info.tm[i] = -1; 10207 add_info.dynamic_scaling_factor[i] = 10208 member_array[i].dynamic_scaling_factor; 10209 add_info.dynamic_load_weight[i] = 10210 member_array[i].dynamic_load_weight; 10211 add_info.dynamic_queue_size_weight[i] = 10212 member_array[i].dynamic_queue_size_weight; 10213 } 10214 10215 /* Convert member gport to module and port */ 10216 rv = _bcm_esw_trunk_gport_array_resolve(unit, 10217 higig_trunk, 10218 member_count, 10219 add_info.tp, 10220 add_info.tp, 10221 add_info.tm); 10222 if (BCM_FAILURE(rv)) { 10223 _trident_trunk_add_info_member_free(&add_info); 10224 return rv; 10225 } 10226 10227 rv = _bcm_trident_trunk_modify(unit, tid, &add_info, 10228 t_info, &stored_info, op, member); 10229 _trident_trunk_add_info_member_free(&add_info); 10230 } 10231 10232 #ifdef INCLUDE_L3 10233 clean_up: 10234 if (NULL != tmp_member_array) { 10235 sal_free(tmp_member_array); 10236 } 10237 10238 if (NULL != tmp_member_port_array) { 10239 sal_free(tmp_member_port_array); 10240 } 10241 10242 if (NULL != tmp_member_gport_array) { 10243 sal_free(tmp_member_gport_array); 10244 } 10245 #endif 10246 10247 10248 return rv; 10249 } 10250 10251 /* 10252 * Function: 10253 * _bcm_trident_trunk_get 10254 * Purpose: 10255 * Return a trunk information of given trunk ID. 10256 * Parameters: 10257 * unit - (IN) StrataSwitch PCI device unit number (driver internal). 10258 * tid - (IN) Trunk ID. 10259 * t_data - (OUT) Place to store returned trunk add info. 10260 * t_info - (IN) Trunk info. 10261 * Returns: 10262 * BCM_E_NONE Success. 10263 * BCM_E_XXX 10264 */ 10265 STATIC int 10266 _bcm_trident_trunk_get(int unit, 10267 bcm_trunk_t tid, 10268 _esw_trunk_add_info_t *t_data, 10269 trunk_private_t *t_info) 10270 { 10271 bcm_trunk_chip_info_t chip_info; 10272 int hgtid; 10273 10274 t_data->flags = t_info->flags; 10275 t_data->psc = t_info->psc; 10276 t_data->ipmc_psc = t_info->ipmc_psc; 10277 t_data->dlf_index = t_info->dlf_index_used; 10278 t_data->mc_index = t_info->mc_index_used; 10279 t_data->ipmc_index = t_info->ipmc_index_used; 10280 t_data->dynamic_size = t_info->dynamic_size; 10281 t_data->dynamic_age = t_info->dynamic_age; 10282 t_data->dynamic_load_exponent = 10283 t_info->dynamic_load_exponent; 10284 t_data->dynamic_expected_load_exponent = 10285 t_info->dynamic_expected_load_exponent; 10286 10287 if (!t_info->in_use) { 10288 t_data->num_ports = 0; 10289 return BCM_E_NONE; 10290 } 10291 10292 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 10293 if (chip_info.trunk_fabric_id_min >= 0 && 10294 tid >= chip_info.trunk_fabric_id_min) { /* fabric trunk */ 10295 hgtid = tid - chip_info.trunk_fabric_id_min; 10296 return _bcm_trident_trunk_fabric_get(unit, hgtid, t_data, t_info); 10297 } 10298 10299 /* Front panel trunk */ 10300 return _bcm_trident_trunk_fp_get(unit, tid, t_data, t_info); 10301 } 10302 10303 /* 10304 * Function: 10305 * bcm_trident_trunk_get 10306 * Purpose: 10307 * Return a trunk information of given trunk ID. 10308 * Parameters: 10309 * unit - (IN) StrataSwitch PCI device unit number (driver internal). 10310 * tid - (IN) Trunk ID. 10311 * trunk_info - (OUT) Place to store returned trunk info. 10312 * member_max - (IN) Size of member_array. 10313 * member_array - (OUT) Array of trunk member structures. 10314 * member_count - (OUT) Number of trunk members returned. 10315 * t_info - (IN) Internal trunk info. 10316 * Returns: 10317 * BCM_E_NONE Success. 10318 * BCM_E_XXX 10319 */ 10320 int 10321 bcm_trident_trunk_get(int unit, 10322 bcm_trunk_t tid, 10323 bcm_trunk_info_t *trunk_info, 10324 int member_max, 10325 bcm_trunk_member_t *member_array, 10326 int *member_count, 10327 trunk_private_t *t_info) 10328 { 10329 _esw_trunk_add_info_t add_info; 10330 int i; 10331 int rv = BCM_E_NONE; 10332 bcm_trunk_chip_info_t chip_info; 10333 int higig_trunk; 10334 10335 sal_memset(&add_info, 0, sizeof(_esw_trunk_add_info_t)); 10336 add_info.num_ports = member_max; 10337 if (member_max > 0) { 10338 BCM_IF_ERROR_RETURN 10339 (_trident_trunk_add_info_member_alloc(&add_info, member_max)); 10340 } 10341 10342 rv = _bcm_trident_trunk_get(unit, tid, &add_info, t_info); 10343 if (BCM_FAILURE(rv)) { 10344 if (member_max > 0) { 10345 _trident_trunk_add_info_member_free(&add_info); 10346 } 10347 return rv; 10348 } 10349 10350 trunk_info->flags = add_info.flags; 10351 trunk_info->psc = add_info.psc; 10352 trunk_info->ipmc_psc = add_info.ipmc_psc; 10353 trunk_info->dlf_index = add_info.dlf_index; 10354 trunk_info->mc_index = add_info.mc_index; 10355 trunk_info->ipmc_index = add_info.ipmc_index; 10356 trunk_info->dynamic_size = add_info.dynamic_size; 10357 trunk_info->dynamic_age = add_info.dynamic_age; 10358 trunk_info->dynamic_load_exponent = 10359 add_info.dynamic_load_exponent; 10360 trunk_info->dynamic_expected_load_exponent = 10361 add_info.dynamic_expected_load_exponent; 10362 10363 *member_count = add_info.num_ports; 10364 10365 if (member_max > 0) { 10366 if (member_max < *member_count) { 10367 *member_count = member_max; 10368 } 10369 10370 /* Construct member gport */ 10371 rv = bcm_esw_trunk_chip_info_get(unit, &chip_info); 10372 if (BCM_FAILURE(rv)) { 10373 _trident_trunk_add_info_member_free(&add_info); 10374 return rv; 10375 } 10376 if (chip_info.trunk_fabric_id_min >= 0 && 10377 tid >= chip_info.trunk_fabric_id_min) { 10378 higig_trunk = 1; 10379 } else { 10380 higig_trunk = 0; 10381 } 10382 rv = _bcm_esw_trunk_gport_construct(unit, higig_trunk, 10383 *member_count, 10384 add_info.tp, add_info.tm, 10385 add_info.tp); 10386 if (BCM_FAILURE(rv)) { 10387 _trident_trunk_add_info_member_free(&add_info); 10388 return rv; 10389 } 10390 10391 for (i = 0; i < *member_count; i++) { 10392 bcm_trunk_member_t_init(&member_array[i]); 10393 member_array[i].flags = add_info.member_flags[i]; 10394 member_array[i].gport = add_info.tp[i]; 10395 member_array[i].dynamic_scaling_factor = 10396 add_info.dynamic_scaling_factor[i]; 10397 member_array[i].dynamic_load_weight = 10398 add_info.dynamic_load_weight[i]; 10399 member_array[i].dynamic_queue_size_weight= 10400 add_info.dynamic_queue_size_weight[i]; 10401 } 10402 10403 _trident_trunk_add_info_member_free(&add_info); 10404 } 10405 10406 return rv; 10407 } 10408 10409 /* 10410 * Function: 10411 * bcm_trident_trunk_mcast_join 10412 * Purpose: 10413 * Add the trunk group to existing MAC multicast entry. 10414 * Parameters: 10415 * unit - StrataSwitch PCI device unit number (driver internal). 10416 * tid - Trunk Id. 10417 * vid - Vlan ID. 10418 * mac - MAC address. 10419 * Returns: 10420 * BCM_E_XXX 10421 * Notes: 10422 * Applications have to remove the MAC multicast entry and re-add in with 10423 * new port bitmap to remove the trunk group from MAC multicast entry. 10424 */ 10425 int 10426 bcm_trident_trunk_mcast_join(int unit, 10427 bcm_trunk_t tid, 10428 bcm_vlan_t vid, 10429 sal_mac_addr_t mac, 10430 trunk_private_t *t_info) 10431 { 10432 trunk_bitmap_entry_t trunk_bitmap_entry; 10433 bcm_mcast_addr_t mc_addr; 10434 bcm_trunk_chip_info_t chip_info; 10435 10436 /* Initialising and setting the mc_addr by bcm_mcast_addr_t_init() */ 10437 bcm_mcast_addr_t_init(&mc_addr, mac, vid); 10438 10439 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 10440 if ((tid >= chip_info.trunk_id_min) && (tid <= chip_info.trunk_id_max)) { 10441 /* get the ports in the trunk group */ 10442 SOC_IF_ERROR_RETURN 10443 (soc_mem_read(unit, TRUNK_BITMAPm, MEM_BLOCK_ANY, tid, 10444 &trunk_bitmap_entry)); 10445 soc_mem_pbmp_field_get(unit, TRUNK_BITMAPm, &trunk_bitmap_entry, 10446 TRUNK_BITMAPf, &mc_addr.pbmp); 10447 } else { 10448 return BCM_E_PARAM; 10449 } 10450 10451 /* Add the trunk group's ports to the multicast group. */ 10452 return bcm_esw_mcast_port_add(unit, &mc_addr); 10453 } 10454 10455 /* 10456 * Function: 10457 * bcm_trident_hg_dlb_member_status_set 10458 * Purpose: 10459 * Set Higig DLB member status. 10460 * Parameters: 10461 * unit - (IN) SOC unit number. 10462 * port - (IN) Member port number. 10463 * status - (IN) Member status. 10464 * Returns: 10465 * BCM_E_xxx 10466 */ 10467 int 10468 bcm_trident_hg_dlb_member_status_set(int unit, bcm_port_t port, 10469 int status) 10470 { 10471 dlb_hgt_link_control_entry_t dlb_hgt_link_control_entry; 10472 bcm_pbmp_t sw_port_state, override_port_map; 10473 10474 #ifdef BCM_TRIUMPH3_SUPPORT 10475 if (soc_feature(unit, soc_feature_hg_dlb_member_id)) { 10476 dlb_hgt_port_member_map_entry_t port_member_map_entry; 10477 int member_id; 10478 dlb_hgt_member_sw_state_entry_t sw_state_entry; 10479 int member_bitmap_width, alloc_size; 10480 SHR_BITDCL *status_bitmap = NULL; 10481 SHR_BITDCL *override_bitmap = NULL; 10482 10483 /* Get Higig port's DLB member ID */ 10484 SOC_IF_ERROR_RETURN(READ_DLB_HGT_PORT_MEMBER_MAPm(unit, MEM_BLOCK_ANY, 10485 port, &port_member_map_entry)); 10486 if (soc_DLB_HGT_PORT_MEMBER_MAPm_field32_get(unit, 10487 &port_member_map_entry, VALIDf)) { 10488 member_id = soc_DLB_HGT_PORT_MEMBER_MAPm_field32_get(unit, 10489 &port_member_map_entry, MEMBER_IDf); 10490 } else { 10491 /* The given Higig port is not assigned a DLB member ID */ 10492 return BCM_E_NOT_FOUND; 10493 } 10494 10495 /* Get status bitmap and override bitmap */ 10496 SOC_IF_ERROR_RETURN(READ_DLB_HGT_MEMBER_SW_STATEm(unit, MEM_BLOCK_ANY, 10497 0, &sw_state_entry)); 10498 member_bitmap_width = soc_mem_field_length(unit, 10499 DLB_HGT_MEMBER_SW_STATEm, MEMBER_BITMAPf); 10500 alloc_size = SHR_BITALLOCSIZE(member_bitmap_width); 10501 status_bitmap = sal_alloc(alloc_size, "DLB HGT member status bitmap"); 10502 if (NULL == status_bitmap) { 10503 return BCM_E_MEMORY; 10504 } 10505 soc_DLB_HGT_MEMBER_SW_STATEm_field_get(unit, &sw_state_entry, 10506 MEMBER_BITMAPf, status_bitmap); 10507 10508 override_bitmap = sal_alloc(alloc_size, "DLB HGT member override bitmap"); 10509 if (NULL == override_bitmap) { 10510 sal_free(status_bitmap); 10511 return BCM_E_MEMORY; 10512 } 10513 soc_DLB_HGT_MEMBER_SW_STATEm_field_get(unit, &sw_state_entry, 10514 OVERRIDE_MEMBER_BITMAPf, override_bitmap); 10515 10516 /* Update status and override bitmaps */ 10517 switch (status) { 10518 case BCM_TRUNK_DYNAMIC_MEMBER_FORCE_DOWN: 10519 SHR_BITSET(override_bitmap, member_id); 10520 SHR_BITCLR(status_bitmap, member_id); 10521 break; 10522 case BCM_TRUNK_DYNAMIC_MEMBER_FORCE_UP: 10523 SHR_BITSET(override_bitmap, member_id); 10524 SHR_BITSET(status_bitmap, member_id); 10525 break; 10526 case BCM_TRUNK_DYNAMIC_MEMBER_HW: 10527 SHR_BITCLR(override_bitmap, member_id); 10528 SHR_BITCLR(status_bitmap, member_id); 10529 break; 10530 default: 10531 sal_free(status_bitmap); 10532 sal_free(override_bitmap); 10533 return BCM_E_PARAM; 10534 } 10535 10536 /* Write status and override bitmaps to hardware */ 10537 soc_DLB_HGT_MEMBER_SW_STATEm_field_set(unit, &sw_state_entry, 10538 MEMBER_BITMAPf, status_bitmap); 10539 soc_DLB_HGT_MEMBER_SW_STATEm_field_set(unit, &sw_state_entry, 10540 OVERRIDE_MEMBER_BITMAPf, override_bitmap); 10541 sal_free(status_bitmap); 10542 sal_free(override_bitmap); 10543 SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_MEMBER_SW_STATEm(unit, MEM_BLOCK_ALL, 10544 0, &sw_state_entry)); 10545 } else 10546 #endif /* BCM_TRIUMPH3_SUPPORT */ 10547 { 10548 /* Get status bitmap and override bitmap */ 10549 SOC_IF_ERROR_RETURN(READ_DLB_HGT_LINK_CONTROLm(unit, MEM_BLOCK_ANY, 10550 0, &dlb_hgt_link_control_entry)); 10551 soc_mem_pbmp_field_get(unit, DLB_HGT_LINK_CONTROLm, 10552 &dlb_hgt_link_control_entry, SW_PORT_STATEf, &sw_port_state); 10553 soc_mem_pbmp_field_get(unit, DLB_HGT_LINK_CONTROLm, 10554 &dlb_hgt_link_control_entry, SW_OVERRIDE_PORT_MAPf, 10555 &override_port_map); 10556 10557 /* Update status and override bitmaps */ 10558 switch (status) { 10559 case BCM_TRUNK_DYNAMIC_MEMBER_FORCE_DOWN: 10560 BCM_PBMP_PORT_ADD(override_port_map, port); 10561 BCM_PBMP_PORT_REMOVE(sw_port_state, port); 10562 break; 10563 case BCM_TRUNK_DYNAMIC_MEMBER_FORCE_UP: 10564 BCM_PBMP_PORT_ADD(override_port_map, port); 10565 BCM_PBMP_PORT_ADD(sw_port_state, port); 10566 break; 10567 case BCM_TRUNK_DYNAMIC_MEMBER_HW: 10568 BCM_PBMP_PORT_REMOVE(override_port_map, port); 10569 BCM_PBMP_PORT_REMOVE(sw_port_state, port); 10570 break; 10571 default: 10572 return BCM_E_PARAM; 10573 } 10574 10575 /* Write status and override bitmaps to hardware */ 10576 soc_mem_pbmp_field_set(unit, DLB_HGT_LINK_CONTROLm, 10577 &dlb_hgt_link_control_entry, SW_PORT_STATEf, &sw_port_state); 10578 soc_mem_pbmp_field_set(unit, DLB_HGT_LINK_CONTROLm, 10579 &dlb_hgt_link_control_entry, SW_OVERRIDE_PORT_MAPf, 10580 &override_port_map); 10581 SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_LINK_CONTROLm(unit, MEM_BLOCK_ALL, 10582 0, &dlb_hgt_link_control_entry)); 10583 } 10584 10585 return BCM_E_NONE; 10586 } 10587 10588 /* 10589 * Function: 10590 * bcm_trident_hg_dlb_member_status_get 10591 * Purpose: 10592 * Get Higig DLB member status. 10593 * Parameters: 10594 * unit - (IN) SOC unit number. 10595 * port - (IN) Higig port number. 10596 * status - (OUT) Member status. 10597 * Returns: 10598 * BCM_E_xxx 10599 */ 10600 int 10601 bcm_trident_hg_dlb_member_status_get(int unit, bcm_port_t port, 10602 int *status) 10603 { 10604 int rv = BCM_E_NONE; 10605 dlb_hgt_link_control_entry_t dlb_hgt_link_control_entry; 10606 bcm_pbmp_t sw_port_state, override_port_map, port_pbmp; 10607 dlb_hgt_port_state_entry_t port_state_entry; 10608 bcm_pbmp_t hw_port_state; 10609 10610 #ifdef BCM_TRIUMPH3_SUPPORT 10611 if (soc_feature(unit, soc_feature_hg_dlb_member_id)) { 10612 dlb_hgt_port_member_map_entry_t port_member_map_entry; 10613 int member_id; 10614 dlb_hgt_member_sw_state_entry_t sw_state_entry; 10615 int member_bitmap_width, alloc_size; 10616 SHR_BITDCL *status_bitmap = NULL; 10617 SHR_BITDCL *override_bitmap = NULL; 10618 uint32 hw_state_reg, hw_state_reg_bitmap; 10619 10620 /* Get Higig port's DLB member ID */ 10621 SOC_IF_ERROR_RETURN(READ_DLB_HGT_PORT_MEMBER_MAPm(unit, MEM_BLOCK_ANY, 10622 port, &port_member_map_entry)); 10623 if (soc_DLB_HGT_PORT_MEMBER_MAPm_field32_get(unit, 10624 &port_member_map_entry, VALIDf)) { 10625 member_id = soc_DLB_HGT_PORT_MEMBER_MAPm_field32_get(unit, 10626 &port_member_map_entry, MEMBER_IDf); 10627 } else { 10628 /* The given Higig port is not assigned a DLB member ID */ 10629 return BCM_E_NOT_FOUND; 10630 } 10631 10632 /* Get status bitmap and override bitmap */ 10633 SOC_IF_ERROR_RETURN(READ_DLB_HGT_MEMBER_SW_STATEm(unit, MEM_BLOCK_ANY, 10634 0, &sw_state_entry)); 10635 member_bitmap_width = soc_mem_field_length(unit, 10636 DLB_HGT_MEMBER_SW_STATEm, MEMBER_BITMAPf); 10637 alloc_size = SHR_BITALLOCSIZE(member_bitmap_width); 10638 status_bitmap = sal_alloc(alloc_size, "DLB HGT member status bitmap"); 10639 if (NULL == status_bitmap) { 10640 return BCM_E_MEMORY; 10641 } 10642 soc_DLB_HGT_MEMBER_SW_STATEm_field_get(unit, &sw_state_entry, 10643 MEMBER_BITMAPf, status_bitmap); 10644 10645 override_bitmap = sal_alloc(alloc_size, "DLB HGT member override bitmap"); 10646 if (NULL == override_bitmap) { 10647 sal_free(status_bitmap); 10648 return BCM_E_MEMORY; 10649 } 10650 soc_DLB_HGT_MEMBER_SW_STATEm_field_get(unit, &sw_state_entry, 10651 OVERRIDE_MEMBER_BITMAPf, override_bitmap); 10652 10653 /* Derive status from software override and status bitmaps or 10654 * hardware state bitmap. 10655 */ 10656 if (SHR_BITGET(override_bitmap, member_id)) { 10657 if (SHR_BITGET(status_bitmap, member_id)) { 10658 *status = BCM_TRUNK_DYNAMIC_MEMBER_FORCE_UP; 10659 } else { 10660 *status = BCM_TRUNK_DYNAMIC_MEMBER_FORCE_DOWN; 10661 } 10662 } else { 10663 #ifdef BCM_TRIDENT2_SUPPORT 10664 if (soc_mem_is_valid(unit, DLB_HGT_MEMBER_HW_STATEm)) { 10665 dlb_hgt_member_hw_state_entry_t hw_state_entry; 10666 SHR_BITDCL *hw_state_bitmap = NULL; 10667 10668 rv = READ_DLB_HGT_MEMBER_HW_STATEm(unit, MEM_BLOCK_ANY, 0, 10669 &hw_state_entry); 10670 if (BCM_FAILURE(rv)) { 10671 sal_free(status_bitmap); 10672 sal_free(override_bitmap); 10673 return rv; 10674 } 10675 hw_state_bitmap = sal_alloc(alloc_size, "DLB HGT HW status bitmap"); 10676 if (NULL == hw_state_bitmap) { 10677 sal_free(status_bitmap); 10678 sal_free(override_bitmap); 10679 return BCM_E_MEMORY; 10680 } 10681 soc_DLB_HGT_MEMBER_HW_STATEm_field_get(unit, &hw_state_entry, 10682 BITMAPf, hw_state_bitmap); 10683 if (SHR_BITGET(hw_state_bitmap, member_id)) { 10684 *status = BCM_TRUNK_DYNAMIC_MEMBER_HW_UP; 10685 } else { 10686 *status = BCM_TRUNK_DYNAMIC_MEMBER_HW_DOWN; 10687 } 10688 sal_free(hw_state_bitmap); 10689 } else 10690 #endif /* BCM_TRIDENT2_SUPPORT */ 10691 { 10692 rv = READ_DLB_HGT_MEMBER_HW_STATEr(unit, &hw_state_reg); 10693 if (BCM_FAILURE(rv)) { 10694 sal_free(status_bitmap); 10695 sal_free(override_bitmap); 10696 return rv; 10697 } 10698 hw_state_reg_bitmap = soc_reg_field_get(unit, 10699 DLB_HGT_MEMBER_HW_STATEr, hw_state_reg, BITMAPf); 10700 if (hw_state_reg_bitmap & (1 << member_id)) { 10701 *status = BCM_TRUNK_DYNAMIC_MEMBER_HW_UP; 10702 } else { 10703 *status = BCM_TRUNK_DYNAMIC_MEMBER_HW_DOWN; 10704 } 10705 } 10706 } 10707 10708 sal_free(status_bitmap); 10709 sal_free(override_bitmap); 10710 10711 } else 10712 #endif /* BCM_TRIUMPH3_SUPPORT */ 10713 { 10714 /* Get status bitmap and override bitmap */ 10715 SOC_IF_ERROR_RETURN(READ_DLB_HGT_LINK_CONTROLm(unit, MEM_BLOCK_ANY, 10716 0, &dlb_hgt_link_control_entry)); 10717 soc_mem_pbmp_field_get(unit, DLB_HGT_LINK_CONTROLm, 10718 &dlb_hgt_link_control_entry, SW_PORT_STATEf, &sw_port_state); 10719 soc_mem_pbmp_field_get(unit, DLB_HGT_LINK_CONTROLm, 10720 &dlb_hgt_link_control_entry, SW_OVERRIDE_PORT_MAPf, 10721 &override_port_map); 10722 10723 /* Derive status from software override and status bitmaps or 10724 * hardware state bitmap. 10725 */ 10726 BCM_PBMP_PORT_SET(port_pbmp, port); 10727 BCM_PBMP_AND(override_port_map, port_pbmp); 10728 BCM_PBMP_AND(sw_port_state, port_pbmp); 10729 if (BCM_PBMP_NOT_NULL(override_port_map)) { 10730 if (BCM_PBMP_NOT_NULL(sw_port_state)) { 10731 *status = BCM_TRUNK_DYNAMIC_MEMBER_FORCE_UP; 10732 } else { 10733 *status = BCM_TRUNK_DYNAMIC_MEMBER_FORCE_DOWN; 10734 } 10735 } else { 10736 SOC_IF_ERROR_RETURN(READ_DLB_HGT_PORT_STATEm(unit, MEM_BLOCK_ANY, 10737 0, &port_state_entry)); 10738 soc_mem_pbmp_field_get(unit, DLB_HGT_PORT_STATEm, 10739 &port_state_entry, BITMAPf, &hw_port_state); 10740 BCM_PBMP_AND(hw_port_state, port_pbmp); 10741 if (BCM_PBMP_NOT_NULL(hw_port_state)) { 10742 *status = BCM_TRUNK_DYNAMIC_MEMBER_HW_UP; 10743 } else { 10744 *status = BCM_TRUNK_DYNAMIC_MEMBER_HW_DOWN; 10745 } 10746 } 10747 } 10748 10749 return rv; 10750 } 10751 10752 #ifdef BCM_TRIUMPH3_SUPPORT 10753 /* 10754 * Function: 10755 * bcm_tr3_hg_dlb_ethertype_set 10756 * Purpose: 10757 * Set the Ethertypes that are eligible or ineligible for 10758 * Higig dynamic load balancing. 10759 * Parameters: 10760 * unit - (IN) Unit number. 10761 * flags - (IN) BCM_TRUNK_DYNAMIC_ETHERTYPE_xxx flags. 10762 * ethertype_count - (IN) Number of elements in ethertype_array. 10763 * ethertype_array - (IN) Array of Ethertypes. 10764 * Returns: 10765 * BCM_E_XXX 10766 */ 10767 int 10768 bcm_tr3_hg_dlb_ethertype_set( 10769 int unit, 10770 uint32 flags, 10771 int ethertype_count, 10772 int *ethertype_array) 10773 { 10774 uint32 measure_control_reg; 10775 int i, j; 10776 dlb_hgt_ethertype_eligibility_map_entry_t ethertype_entry; 10777 10778 /* Input check */ 10779 if (ethertype_count > soc_mem_index_count(unit, 10780 DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm)) { 10781 return BCM_E_RESOURCE; 10782 } 10783 10784 /* Update quality measure control register */ 10785 SOC_IF_ERROR_RETURN 10786 (READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg)); 10787 soc_reg_field_set(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr, 10788 &measure_control_reg, ETHERTYPE_ELIGIBILITY_CONFIGf, 10789 flags & BCM_TRUNK_DYNAMIC_ETHERTYPE_ELIGIBLE ? 1 : 0); 10790 soc_reg_field_set(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr, 10791 &measure_control_reg, INNER_OUTER_ETHERTYPE_SELECTIONf, 10792 flags & BCM_TRUNK_DYNAMIC_ETHERTYPE_INNER ? 1 : 0); 10793 SOC_IF_ERROR_RETURN 10794 (WRITE_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg)); 10795 10796 /* Update Ethertype eligibility map table */ 10797 for (i = 0; i < ethertype_count; i++) { 10798 sal_memset(ðertype_entry, 0, 10799 sizeof(dlb_hgt_ethertype_eligibility_map_entry_t)); 10800 soc_DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm_field32_set(unit, 10801 ðertype_entry, VALIDf, 1); 10802 soc_DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm_field32_set(unit, 10803 ðertype_entry, ETHERTYPEf, ethertype_array[i]); 10804 SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm(unit, 10805 MEM_BLOCK_ALL, i, ðertype_entry)); 10806 } 10807 10808 /* Zero out remaining entries of Ethertype eligibility map table */ 10809 for (j = i; j < soc_mem_index_count(unit, 10810 DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm); j++) { 10811 SOC_IF_ERROR_RETURN(WRITE_DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm(unit, 10812 MEM_BLOCK_ALL, j, soc_mem_entry_null(unit, 10813 DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm))); 10814 } 10815 10816 return BCM_E_NONE; 10817 } 10818 10819 /* 10820 * Function: 10821 * bcm_tr3_hg_dlb_ethertype_get 10822 * Purpose: 10823 * Get the Ethertypes that are eligible or ineligible for 10824 * Higig dynamic load balancing. 10825 * Parameters: 10826 * unit - (IN) Unit number. 10827 * flags - (INOUT) BCM_TRUNK_DYNAMIC_ETHERTYPE_xxx flags. 10828 * ethertype_max - (IN) Number of elements in ethertype_array. 10829 * ethertype_array - (OUT) Array of Ethertypes. 10830 * ethertype_count - (OUT) Number of elements returned in ethertype_array. 10831 * Returns: 10832 * BCM_E_XXX 10833 */ 10834 int 10835 bcm_tr3_hg_dlb_ethertype_get( 10836 int unit, 10837 uint32 *flags, 10838 int ethertype_max, 10839 int *ethertype_array, 10840 int *ethertype_count) 10841 { 10842 uint32 measure_control_reg; 10843 int i; 10844 int ethertype; 10845 dlb_hgt_ethertype_eligibility_map_entry_t ethertype_entry; 10846 10847 *ethertype_count = 0; 10848 10849 /* Get flags */ 10850 SOC_IF_ERROR_RETURN 10851 (READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg)); 10852 if (soc_reg_field_get(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr, 10853 measure_control_reg, ETHERTYPE_ELIGIBILITY_CONFIGf)) { 10854 *flags |= BCM_TRUNK_DYNAMIC_ETHERTYPE_ELIGIBLE; 10855 } 10856 if (soc_reg_field_get(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr, 10857 measure_control_reg, INNER_OUTER_ETHERTYPE_SELECTIONf)) { 10858 *flags |= BCM_TRUNK_DYNAMIC_ETHERTYPE_INNER; 10859 } 10860 10861 /* Get Ethertypes */ 10862 for (i = 0; i < soc_mem_index_count(unit, 10863 DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm); i++) { 10864 SOC_IF_ERROR_RETURN(READ_DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm(unit, 10865 MEM_BLOCK_ANY, i, ðertype_entry)); 10866 if (soc_DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit, 10867 ðertype_entry, VALIDf)) { 10868 ethertype = soc_DLB_HGT_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit, 10869 ðertype_entry, ETHERTYPEf); 10870 if (NULL != ethertype_array) { 10871 ethertype_array[*ethertype_count] = ethertype; 10872 } 10873 (*ethertype_count)++; 10874 if ((ethertype_max > 0) && (*ethertype_count == ethertype_max)) { 10875 break; 10876 } 10877 } 10878 } 10879 10880 return BCM_E_NONE; 10881 } 10882 10883 #endif /* BCM_TRIUMPH3_SUPPORT */ 10884 10885 /* ----------------------------------------------------------------------------- 10886 * 10887 * Warm Boot routines 10888 * 10889 * ----------------------------------------------------------------------------- 10890 */ 10891 #ifdef BCM_WARM_BOOT_SUPPORT 10892 10893 void 10894 _bcm_trident_hw_failover_num_ports_set(int unit, bcm_trunk_t tid, 10895 int hg_trunk, uint16 num_ports) 10896 { 10897 bcm_trunk_chip_info_t chip_info; 10898 int tid_ix; 10899 10900 (void) bcm_esw_trunk_chip_info_get(unit, &chip_info); 10901 tid_ix = tid + (hg_trunk ? chip_info.trunk_group_count : 0); 10902 _trident_trunk_hwfail[unit]->hw_tinfo[tid_ix].num_ports = num_ports; 10903 10904 return; 10905 } 10906 10907 uint16 10908 _bcm_trident_hw_failover_num_ports_get(int unit, bcm_trunk_t tid, 10909 int hg_trunk) 10910 { 10911 bcm_trunk_chip_info_t chip_info; 10912 int tid_ix; 10913 uint16 num_ports; 10914 10915 (void) bcm_esw_trunk_chip_info_get(unit, &chip_info); 10916 tid_ix = tid + (hg_trunk ? chip_info.trunk_group_count : 0); 10917 num_ports = _trident_trunk_hwfail[unit]->hw_tinfo[tid_ix].num_ports; 10918 10919 return num_ports; 10920 } 10921 10922 int 10923 _bcm_trident_hw_failover_flags_set(int unit, bcm_trunk_t tid, 10924 int port_index, int hg_trunk, uint8 flags) 10925 { 10926 bcm_trunk_chip_info_t chip_info; 10927 int tid_ix; 10928 _trident_hw_tinfo_t *hwft; 10929 10930 BCM_IF_ERROR_RETURN(bcm_esw_trunk_chip_info_get(unit, &chip_info)); 10931 tid_ix = tid + (hg_trunk ? chip_info.trunk_group_count : 0); 10932 hwft = &(_trident_trunk_hwfail[unit]->hw_tinfo[tid_ix]); 10933 10934 if (NULL == hwft->flags) { 10935 hwft->flags = sal_alloc(sizeof(uint32) * hwft->num_ports, 10936 "hw_tinfo_flags"); 10937 if (hwft->flags == NULL) { 10938 return BCM_E_MEMORY; 10939 } 10940 } 10941 hwft->flags[port_index] = flags; 10942 10943 return BCM_E_NONE; 10944 } 10945 10946 uint8 10947 _bcm_trident_hw_failover_flags_get(int unit, bcm_trunk_t tid, 10948 int port_index, int hg_trunk) 10949 { 10950 bcm_trunk_chip_info_t chip_info; 10951 int tid_ix; 10952 uint8 flags; 10953 _trident_hw_tinfo_t *hwft; 10954 10955 (void) bcm_esw_trunk_chip_info_get(unit, &chip_info); 10956 tid_ix = tid + (hg_trunk ? chip_info.trunk_group_count : 0); 10957 hwft = &(_trident_trunk_hwfail[unit]->hw_tinfo[tid_ix]); 10958 10959 if (NULL != hwft->flags) { 10960 flags = _trident_trunk_hwfail[unit]->hw_tinfo[tid_ix].flags[port_index]; 10961 } else { 10962 flags = 0; 10963 } 10964 10965 return flags; 10966 } 10967 10968 int 10969 _bcm_trident_trunk_member_info_set(int unit, bcm_trunk_t tid, 10970 uint16 num_ports, 10971 uint16 *modport, 10972 uint32 *member_flags) 10973 { 10974 int i; 10975 10976 if (MEMBER_INFO(unit, tid).modport) { 10977 sal_free(MEMBER_INFO(unit, tid).modport); 10978 MEMBER_INFO(unit, tid).modport = NULL; 10979 } 10980 if (MEMBER_INFO(unit, tid).member_flags) { 10981 sal_free(MEMBER_INFO(unit, tid).member_flags); 10982 MEMBER_INFO(unit, tid).member_flags = NULL; 10983 } 10984 10985 MEMBER_INFO(unit, tid).num_ports = num_ports; 10986 10987 MEMBER_INFO(unit, tid).modport = sal_alloc( 10988 sizeof(uint16) * MEMBER_INFO(unit, tid).num_ports, 10989 "member info modport"); 10990 if (NULL == MEMBER_INFO(unit, tid).modport) { 10991 return BCM_E_MEMORY; 10992 } 10993 10994 MEMBER_INFO(unit, tid).member_flags = sal_alloc( 10995 sizeof(uint32) * MEMBER_INFO(unit, tid).num_ports, 10996 "member info flags"); 10997 if (NULL == MEMBER_INFO(unit, tid).member_flags) { 10998 sal_free(MEMBER_INFO(unit, tid).modport); 10999 MEMBER_INFO(unit, tid).modport = NULL; 11000 return BCM_E_MEMORY; 11001 } 11002 11003 for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) { 11004 MEMBER_INFO(unit, tid).modport[i] = modport[i]; 11005 MEMBER_INFO(unit, tid).member_flags[i] = member_flags[i]; 11006 } 11007 11008 MEMBER_INFO(unit, tid).recovered_from_scache = 1; 11009 11010 return BCM_E_NONE; 11011 } 11012 11013 int 11014 _bcm_trident_trunk_member_info_get(int unit, bcm_trunk_t tid, 11015 uint16 array_size, 11016 uint16 *modport, 11017 uint32 *member_flags, 11018 uint16 *num_ports) 11019 { 11020 int i; 11021 11022 if (NULL == num_ports) { 11023 return BCM_E_PARAM; 11024 } 11025 *num_ports = MEMBER_INFO(unit, tid).num_ports; 11026 11027 if (array_size == 0) { 11028 return BCM_E_NONE; 11029 } 11030 11031 for (i = 0; i < array_size; i++) { 11032 if (i == *num_ports) { 11033 break; 11034 } 11035 modport[i] = MEMBER_INFO(unit, tid).modport[i]; 11036 member_flags[i] = MEMBER_INFO(unit, tid).member_flags[i]; 11037 } 11038 11039 return BCM_E_NONE; 11040 } 11041 11042 STATIC int 11043 _bcm_trident_trunk_rtag_to_psc(int unit, int rtag, int *psc) 11044 { 11045 if (7 == rtag) { 11046 if (soc_feature(unit, soc_feature_port_flow_hash)) { 11047 *psc = BCM_TRUNK_PSC_PORTFLOW; 11048 } else if (soc_feature(unit, soc_feature_port_trunk_index)) { 11049 *psc = BCM_TRUNK_PSC_PORTINDEX; 11050 } else { 11051 return BCM_E_PARAM; 11052 } 11053 } else if (0 <= rtag) { 11054 /* HW and SW values match */ 11055 *psc = rtag; 11056 } else { 11057 /* Unknown rtag value */ 11058 return BCM_E_PARAM; 11059 } 11060 11061 return BCM_E_NONE; 11062 } 11063 11064 /* 11065 * Function: 11066 * _bcm_trident_trunk_mod_port_map_reinit 11067 * Purpose: 11068 * Reinitialize the software cache for the SOURCE_TRUNK_MAP_TABLE. 11069 * Recover trunk members with egress disable flag set. 11070 * Parameters: 11071 * unit - (IN) SOC unit number. 11072 * mod - (IN) Module ID. 11073 * base_index - (IN) Module ID's base index. 11074 * num_ports - (IN) Number of ports in the given module. 11075 * Returns: 11076 * BCM_X_XXX 11077 * Notes: 11078 * This function is called during stacking module reinit, since 11079 * the number of ports in a given module is not known until then. 11080 */ 11081 int 11082 _bcm_trident_trunk_mod_port_map_reinit(int unit, bcm_module_t mod, 11083 int base_index, int num_ports) 11084 { 11085 bcm_port_t port; 11086 int rv = BCM_E_NONE; 11087 source_trunk_map_table_entry_t stm; 11088 int port_type; 11089 bcm_trunk_t tid; 11090 int array_size; 11091 bcm_module_t *mod_array = NULL; 11092 bcm_port_t *port_array = NULL; 11093 uint32 *flags_array = NULL; 11094 int i, found; 11095 soc_field_t tgid_f = TGIDf; 11096 11097 if (soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm, SRC_TGIDf)) { 11098 tgid_f = SRC_TGIDf; 11099 } 11100 /* 11101 * Recover from SOURCE_TRUNK_MAP tables. 11102 */ 11103 for (port = 0; port < num_ports; port++) { 11104 11105 rv = soc_mem_read(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ANY, 11106 base_index + port, &stm); 11107 if (BCM_FAILURE(rv)) { 11108 break; 11109 } 11110 11111 port_type = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm, 11112 PORT_TYPEf); 11113 if (port_type != 1) { 11114 continue; 11115 } 11116 11117 tid = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm, tgid_f); 11118 11119 /* Recover source trunk map cache */ 11120 rv = _bcm_trident_trunk_mod_port_map_set(unit, mod, port, tid); 11121 if (BCM_FAILURE(rv)) { 11122 break; 11123 } 11124 11125 /* Allocate arrays that can accommodate an additional member, 11126 * in case a new member needs to be added to the trunk group. 11127 */ 11128 array_size = MEMBER_INFO(unit, tid).num_ports + 1; 11129 mod_array = sal_alloc(sizeof(bcm_module_t) * array_size, "mod_array"); 11130 if (mod_array == NULL) { 11131 rv = BCM_E_MEMORY; 11132 break; 11133 } 11134 sal_memset(mod_array, 0, sizeof(bcm_module_t) * array_size); 11135 11136 port_array = sal_alloc(sizeof(bcm_port_t) * array_size, "port_array"); 11137 if (port_array == NULL) { 11138 rv = BCM_E_MEMORY; 11139 break; 11140 } 11141 sal_memset(port_array, 0, sizeof(bcm_port_t) * array_size); 11142 11143 flags_array = sal_alloc(sizeof(uint32) * array_size, "flags_array"); 11144 if (flags_array == NULL) { 11145 rv = BCM_E_MEMORY; 11146 break; 11147 } 11148 sal_memset(flags_array, 0, sizeof(uint32) * array_size); 11149 11150 /* Try to find mod-port in the trunk group */ 11151 found = 0; 11152 for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) { 11153 mod_array[i] = MEMBER_INFO(unit, tid).modport[i] >> 8; 11154 port_array[i] = MEMBER_INFO(unit, tid).modport[i] & 0xff; 11155 flags_array[i] = MEMBER_INFO(unit, tid).member_flags[i]; 11156 if (port_array[i] == port && mod_array[i] == mod) { 11157 found = 1; 11158 break; 11159 } 11160 } 11161 11162 /* If the mod-port was not found, then add it with 11163 * EGRESS_DISABLE flag set. 11164 */ 11165 if (!found && !MEMBER_INFO(unit, tid).recovered_from_scache) { 11166 /* Find where to insert */ 11167 for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) { 11168 if (port > port_array[i] || mod != mod_array[i]) { 11169 continue; 11170 } 11171 break; 11172 } 11173 11174 /* Insert at the required location in sw state */ 11175 mod_array[i] = mod; 11176 port_array[i] = port; 11177 flags_array[i] |= BCM_TRUNK_MEMBER_EGRESS_DISABLE; 11178 11179 /* Copy remaining members as is */ 11180 for (; i < MEMBER_INFO(unit, tid).num_ports; i++) { 11181 mod_array[i+1] = MEMBER_INFO(unit, tid).modport[i] >> 8; 11182 port_array[i+1] = MEMBER_INFO(unit, tid).modport[i] & 0xff; 11183 flags_array[i+1] = MEMBER_INFO(unit, tid).member_flags[i]; 11184 } 11185 11186 MEMBER_INFO(unit, tid).num_ports++; 11187 11188 if (MEMBER_INFO(unit, tid).modport) { 11189 sal_free(MEMBER_INFO(unit, tid).modport); 11190 MEMBER_INFO(unit, tid).modport = NULL; 11191 } 11192 if (MEMBER_INFO(unit, tid).member_flags) { 11193 sal_free(MEMBER_INFO(unit, tid).member_flags); 11194 MEMBER_INFO(unit, tid).member_flags = NULL; 11195 } 11196 11197 MEMBER_INFO(unit, tid).modport = sal_alloc( 11198 sizeof(uint16) * MEMBER_INFO(unit, tid).num_ports, 11199 "member info modport"); 11200 if (NULL == MEMBER_INFO(unit, tid).modport) { 11201 rv = BCM_E_MEMORY; 11202 break; 11203 } 11204 11205 MEMBER_INFO(unit, tid).member_flags = sal_alloc( 11206 sizeof(uint32) * MEMBER_INFO(unit, tid).num_ports, "member info flags"); 11207 if (NULL == MEMBER_INFO(unit, tid).member_flags) { 11208 sal_free(MEMBER_INFO(unit, tid).modport); 11209 MEMBER_INFO(unit, tid).modport = NULL; 11210 rv = BCM_E_MEMORY; 11211 break; 11212 } 11213 11214 for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) { 11215 MEMBER_INFO(unit, tid).modport[i] = (mod_array[i] << 8) | 11216 port_array[i]; 11217 MEMBER_INFO(unit, tid).member_flags[i] = flags_array[i]; 11218 } 11219 } 11220 11221 sal_free(mod_array); 11222 mod_array = NULL; 11223 sal_free(port_array); 11224 port_array = NULL; 11225 sal_free(flags_array); 11226 flags_array = NULL; 11227 } 11228 11229 if (mod_array) { 11230 sal_free(mod_array); 11231 } 11232 if (port_array) { 11233 sal_free(port_array); 11234 } 11235 if (flags_array) { 11236 sal_free(flags_array); 11237 } 11238 11239 return rv; 11240 } 11241 11242 /* 11243 * Handle state recovery for front panel trunks 11244 */ 11245 int 11246 _bcm_trident_trunk_lag_reinit(int unit, int ngroups_fp, trunk_private_t *trunk_info) 11247 { 11248 int rv = BCM_E_NONE; 11249 int tid, tid_get; 11250 int ptype; 11251 trunk_group_entry_t tg_entry; 11252 trunk_member_entry_t tm_entry; 11253 int mod_id = 0, port_num = 0; 11254 int base_ptr, tg_size, rtag; 11255 bcm_module_t *egr_hw_mods; 11256 bcm_port_t *egr_hw_ports; 11257 uint32 *egr_member_flags; 11258 trunk_member_entry_t trunk_member_entry; 11259 source_trunk_map_table_entry_t stm; 11260 int stm_idx; 11261 int i, j, mod_is_local; 11262 int hwf_rtag, hwf_psc; 11263 _trident_hw_tinfo_t *hwft; 11264 int num_egr_ports; 11265 int num_entries; 11266 int num_ports_temp = 0; 11267 soc_field_t tgid_f = TGIDf; 11268 #ifdef BCM_TRIDENT2_SUPPORT 11269 trunk_private_t *trunk_info_temp = trunk_info; 11270 #endif 11271 11272 /* 11273 * On warmboot, reserve entry "0" only if indicated so 11274 * by the flag. 11275 * Else, reserve entry "0" if indicated by the HW entry 11276 * Else, do not reserve entry "0". 11277 */ 11278 if (bcm_trident_trunk_mbr_zero_rsvd[unit] == TRUE) { 11279 _BCM_FP_TRUNK_MEMBER_USED_SET(unit, 0); 11280 } else { 11281 SOC_IF_ERROR_RETURN 11282 (READ_TRUNK_MEMBERm(unit, MEM_BLOCK_ANY, 0, &tm_entry)); 11283 mod_id = soc_TRUNK_MEMBERm_field32_get(unit, &tm_entry, MODULE_IDf); 11284 port_num = soc_TRUNK_MEMBERm_field32_get(unit, &tm_entry, PORT_NUMf); 11285 if ((mod_id == 0xff) && (port_num == 0x7f)) { 11286 bcm_trident_trunk_mbr_zero_rsvd[unit] = TRUE; 11287 _BCM_FP_TRUNK_MEMBER_USED_SET(unit, 0); 11288 } 11289 } 11290 11291 if (soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm, SRC_TGIDf)) { 11292 tgid_f = SRC_TGIDf; 11293 } 11294 11295 for (tid = 0; tid < ngroups_fp; tid++, trunk_info++) { 11296 11297 SOC_IF_ERROR_RETURN 11298 (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry)); 11299 11300 base_ptr = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, BASE_PTRf); 11301 tg_size = 1 + soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, TG_SIZEf); 11302 rtag = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, RTAGf); 11303 11304 num_ports_temp = MEMBER_INFO(unit, tid).num_ports; 11305 /* if BCM_TRUNK_MEMBER_EGRESS_DISABLE is set, the rtag will be zero. 11306 we should not return if a trunk has some ports and even if rtag is 0 */ 11307 if (0 == rtag && num_ports_temp == 0 ) { 11308 /* Invalid trunk group */ 11309 continue; 11310 } 11311 11312 /* Recover trunk_info */ 11313 trunk_info->tid = tid; 11314 trunk_info->in_use = TRUE; 11315 if(rtag != 0) { 11316 BCM_IF_ERROR_RETURN 11317 (_bcm_trident_trunk_rtag_to_psc(unit, rtag, &trunk_info->psc)); 11318 } 11319 trunk_info->rtag = rtag; 11320 11321 #ifdef BCM_APACHE_SUPPORT 11322 trunk_info->rr_lag_select = -1; 11323 if (soc_feature(unit, soc_feature_apache_round_robin_fp_lag)) { 11324 if (soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, RR_LB_ENABLEf)) { 11325 trunk_info->rr_lag_select = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, RR_LB_COUNTER_SELECTf); 11326 } 11327 } 11328 #endif /* BCM_APACHE_SUPPORT */ 11329 11330 /* Recover trunk member table bookkeeping info */ 11331 num_entries = tg_size; 11332 if (rtag >= 1 && rtag <= 6) { 11333 #ifdef BCM_KATANA_SUPPORT 11334 if (SOC_IS_KATANAX(unit)) { 11335 num_entries = _BCM_KATANA_FP_TRUNK_RTAG1_6_MAX_PORTCNT; 11336 } else 11337 #endif 11338 if (soc_feature(unit, 11339 soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 11340 num_entries = _BCM_TD_FP_TRUNK_RTAG1_6_MAX_PORTCNT; 11341 } 11342 } 11343 _BCM_FP_TRUNK_MEMBER_USED_SET_RANGE(unit, base_ptr, num_entries); 11344 11345 /* Recover trunk members */ 11346 if (MEMBER_INFO(unit, tid).recovered_from_scache) { 11347 egr_hw_mods = sal_alloc(sizeof(bcm_module_t) * 11348 MEMBER_INFO(unit, tid).num_ports, "egr_hw_mods"); 11349 if (egr_hw_mods == NULL) { 11350 return BCM_E_MEMORY; 11351 } 11352 11353 egr_hw_ports = sal_alloc(sizeof(bcm_port_t) * 11354 MEMBER_INFO(unit, tid).num_ports, "egr_hw_ports"); 11355 if (egr_hw_ports == NULL) { 11356 sal_free(egr_hw_mods); 11357 return BCM_E_MEMORY; 11358 } 11359 11360 egr_member_flags = sal_alloc(sizeof(uint32) * 11361 MEMBER_INFO(unit, tid).num_ports, "egr_member_flags"); 11362 if (egr_member_flags == NULL) { 11363 sal_free(egr_hw_mods); 11364 sal_free(egr_hw_ports); 11365 return BCM_E_MEMORY; 11366 } 11367 11368 for (i = 0, j = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) { 11369 if (MEMBER_INFO(unit, tid).member_flags[i] & 11370 BCM_TRUNK_MEMBER_EGRESS_DISABLE) { 11371 continue; 11372 } 11373 egr_hw_mods[j] = MEMBER_INFO(unit, tid).modport[i] >> 8; 11374 egr_hw_ports[j] = MEMBER_INFO(unit, tid).modport[i] & 0xff; 11375 egr_member_flags[j] = MEMBER_INFO(unit, tid).member_flags[i]; 11376 j++; 11377 } 11378 num_egr_ports = j; 11379 11380 } else { 11381 /* In level 1 warm boot, not all egress trunk members can be 11382 * recovered from TRUNK_MEMBER table, as those members with 11383 * the UNICAST_EGRESS_DISABLE flag set will not be in 11384 * TRUNK_MEMBER table. 11385 */ 11386 11387 egr_hw_mods = sal_alloc(sizeof(bcm_module_t) * tg_size, 11388 "egr_hw_mods"); 11389 if (egr_hw_mods == NULL) { 11390 return BCM_E_MEMORY; 11391 } 11392 11393 egr_hw_ports = sal_alloc(sizeof(bcm_port_t) * tg_size, 11394 "egr_hw_ports"); 11395 if (egr_hw_ports == NULL) { 11396 sal_free(egr_hw_mods); 11397 return BCM_E_MEMORY; 11398 } 11399 11400 egr_member_flags = sal_alloc(sizeof(uint32) * tg_size, 11401 "egr_member_flags"); 11402 if (egr_member_flags == NULL) { 11403 sal_free(egr_hw_mods); 11404 sal_free(egr_hw_ports); 11405 return BCM_E_MEMORY; 11406 } 11407 11408 for (i = 0; i < tg_size; i++) { 11409 rv = READ_TRUNK_MEMBERm(unit, MEM_BLOCK_ANY, base_ptr + i, 11410 &trunk_member_entry); 11411 if (BCM_FAILURE(rv)) { 11412 sal_free(egr_hw_mods); 11413 sal_free(egr_hw_ports); 11414 sal_free(egr_member_flags); 11415 return rv; 11416 } 11417 egr_hw_mods[i] = soc_TRUNK_MEMBERm_field32_get 11418 (unit, &trunk_member_entry, MODULE_IDf); 11419 egr_hw_ports[i] = soc_TRUNK_MEMBERm_field32_get 11420 (unit, &trunk_member_entry, PORT_NUMf); 11421 egr_member_flags[i] = 0; 11422 11423 /* Recreate INGRESS_DISABLE flag */ 11424 rv = _bcm_esw_src_mod_port_table_index_get(unit, egr_hw_mods[i], 11425 egr_hw_ports[i], &stm_idx); 11426 if (BCM_FAILURE(rv)) { 11427 sal_free(egr_hw_mods); 11428 sal_free(egr_hw_ports); 11429 sal_free(egr_member_flags); 11430 return rv; 11431 } 11432 rv = soc_mem_read(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ANY, 11433 stm_idx, &stm); 11434 if (BCM_FAILURE(rv)) { 11435 sal_free(egr_hw_mods); 11436 sal_free(egr_hw_ports); 11437 sal_free(egr_member_flags); 11438 return rv; 11439 } 11440 ptype = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm, 11441 PORT_TYPEf); 11442 tid_get = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm, 11443 tgid_f); 11444 if (ptype != 1 || tid_get != tid) { 11445 egr_member_flags[i] |= BCM_TRUNK_MEMBER_INGRESS_DISABLE; 11446 } 11447 } 11448 11449 num_egr_ports = tg_size; 11450 11451 if (MEMBER_INFO(unit, tid).modport) { 11452 sal_free(MEMBER_INFO(unit, tid).modport); 11453 MEMBER_INFO(unit, tid).modport = NULL; 11454 } 11455 if (MEMBER_INFO(unit, tid).member_flags) { 11456 sal_free(MEMBER_INFO(unit, tid).member_flags); 11457 MEMBER_INFO(unit, tid).member_flags = NULL; 11458 } 11459 11460 MEMBER_INFO(unit, tid).num_ports = tg_size; 11461 MEMBER_INFO(unit, tid).modport = sal_alloc( 11462 sizeof(uint16) * MEMBER_INFO(unit, tid).num_ports, 11463 "member info modport"); 11464 if (NULL == MEMBER_INFO(unit, tid).modport) { 11465 sal_free(egr_hw_mods); 11466 sal_free(egr_hw_ports); 11467 sal_free(egr_member_flags); 11468 return BCM_E_MEMORY; 11469 } 11470 11471 MEMBER_INFO(unit, tid).member_flags = sal_alloc( 11472 sizeof(uint32) * MEMBER_INFO(unit, tid).num_ports, 11473 "member info flags"); 11474 if (NULL == MEMBER_INFO(unit, tid).member_flags) { 11475 sal_free(egr_hw_mods); 11476 sal_free(egr_hw_ports); 11477 sal_free(egr_member_flags); 11478 sal_free(MEMBER_INFO(unit, tid).modport); 11479 MEMBER_INFO(unit, tid).modport = NULL; 11480 return BCM_E_MEMORY; 11481 } 11482 11483 for (i = 0; i < MEMBER_INFO(unit, tid).num_ports; i++) { 11484 MEMBER_INFO(unit, tid).modport[i] = 11485 (egr_hw_mods[i] << 8) | egr_hw_ports[i]; 11486 MEMBER_INFO(unit, tid).member_flags[i] = egr_member_flags[i]; 11487 } 11488 } 11489 11490 /* Recover software trunk failover state */ 11491 rv = _bcm_trident_trunk_swfailover_fp_set(unit, tid, rtag, 11492 num_egr_ports, 11493 egr_hw_mods, 11494 egr_hw_ports, 11495 egr_member_flags, 11496 trunk_info->flags); 11497 if (BCM_FAILURE(rv)) { 11498 sal_free(egr_hw_mods); 11499 sal_free(egr_hw_ports); 11500 sal_free(egr_member_flags); 11501 return rv; 11502 } 11503 11504 /* Recover hardware trunk failover state. */ 11505 if (soc_feature(unit, soc_feature_port_lag_failover)) { 11506 hwft = &(_trident_trunk_hwfail[unit]->hw_tinfo[tid]); 11507 hwft->num_ports = num_egr_ports; 11508 if (hwft->modport == NULL) { 11509 hwft->modport = sal_alloc(sizeof(uint16) * num_egr_ports, 11510 "hw_tinfo_modport"); 11511 if (hwft->modport == NULL) { 11512 sal_free(egr_hw_mods); 11513 sal_free(egr_hw_ports); 11514 sal_free(egr_member_flags); 11515 return BCM_E_MEMORY; 11516 } 11517 } 11518 sal_memset(hwft->modport, 0, sizeof(uint16) * num_egr_ports); 11519 11520 if (hwft->psc == NULL) { 11521 hwft->psc = sal_alloc(sizeof(uint8) * num_egr_ports, 11522 "hw_tinfo_psc"); 11523 if (hwft->psc == NULL) { 11524 sal_free(hwft->modport); 11525 hwft->modport = NULL; 11526 sal_free(egr_hw_mods); 11527 sal_free(egr_hw_ports); 11528 sal_free(egr_member_flags); 11529 return BCM_E_MEMORY; 11530 } 11531 } 11532 sal_memset(hwft->psc, 0, sizeof(uint8) * num_egr_ports); 11533 11534 if (hwft->flags == NULL) { 11535 /* If flags are not recovered from scache, allocate flags and 11536 * set them to zero. 11537 */ 11538 hwft->flags = sal_alloc(sizeof(uint32) * num_egr_ports, 11539 "hw_tinfo_flags"); 11540 if (hwft->flags == NULL) { 11541 sal_free(hwft->modport); 11542 hwft->modport = NULL; 11543 sal_free(hwft->psc); 11544 hwft->psc = NULL; 11545 sal_free(egr_hw_mods); 11546 sal_free(egr_hw_ports); 11547 sal_free(egr_member_flags); 11548 return BCM_E_MEMORY; 11549 } 11550 sal_memset(hwft->flags, 0, sizeof(uint32) * num_egr_ports); 11551 } 11552 11553 11554 for (i = 0; i < num_egr_ports; i++) { 11555 hwft->modport[i] = (egr_hw_mods[i] << 8) | egr_hw_ports[i]; 11556 rv = _bcm_esw_modid_is_local(unit, egr_hw_mods[i], &mod_is_local); 11557 if (BCM_FAILURE(rv)) { 11558 sal_free(egr_hw_mods); 11559 sal_free(egr_hw_ports); 11560 sal_free(egr_member_flags); 11561 return rv; 11562 } 11563 if (mod_is_local) { 11564 #if defined(BCM_HELIX5_SUPPORT) 11565 /* Skip q-ports in HX5 since trunk hardware failover is not 11566 * supported for PM4x10Q. 11567 */ 11568 if (IS_QSGMII_PORT(unit, egr_hw_ports[i])) { 11569 continue; 11570 } 11571 #endif /* BCM_HELIX5_SUPPORT */ 11572 rv = _bcm_trident_trunk_hwfailover_read(unit, 11573 egr_hw_ports[i], 0, &hwf_rtag, NULL, NULL, NULL); 11574 if (BCM_FAILURE(rv)) { 11575 sal_free(egr_hw_mods); 11576 sal_free(egr_hw_ports); 11577 sal_free(egr_member_flags); 11578 return rv; 11579 } 11580 if (hwf_rtag > 0) { 11581 rv = _bcm_trident_trunk_rtag_to_psc(unit, hwf_rtag, 11582 &hwf_psc); 11583 if (BCM_FAILURE(rv)) { 11584 sal_free(egr_hw_mods); 11585 sal_free(egr_hw_ports); 11586 sal_free(egr_member_flags); 11587 return rv; 11588 } 11589 } else { 11590 hwf_psc = trunk_info->psc; 11591 } 11592 hwft->psc[i] = hwf_psc; 11593 } 11594 } 11595 } 11596 11597 sal_free(egr_hw_mods); 11598 sal_free(egr_hw_ports); 11599 sal_free(egr_member_flags); 11600 11601 #ifdef BCM_TRIUMPH3_SUPPORT 11602 if (soc_feature(unit, soc_feature_lag_dlb) && 11603 !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 11604 BCM_IF_ERROR_RETURN 11605 (bcm_tr3_lag_dlb_group_recover(unit, tid, trunk_info)); 11606 } 11607 #endif /* BCM_TRIUMPH3_SUPPORT */ 11608 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 11609 if (soc_feature(unit, soc_feature_lag_dlb) && 11610 soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 11611 BCM_IF_ERROR_RETURN 11612 (bcm_th2_hgt_lag_dlb_group_recover(unit, tid, 0, trunk_info)); 11613 } 11614 #endif /* BCM_TOMAHAWK2_SUPPORT */ 11615 11616 11617 } 11618 11619 #ifdef BCM_TRIDENT2_SUPPORT 11620 if (soc_feature(unit, soc_feature_lag_resilient_hash)) { 11621 for (tid = 0; tid < ngroups_fp; tid++, trunk_info_temp++) { 11622 if (trunk_info_temp->psc == 0) { 11623 continue; 11624 } 11625 BCM_IF_ERROR_RETURN( 11626 bcm_td2_lag_rh_recover(unit, tid, trunk_info_temp)); 11627 } 11628 } 11629 #endif /* BCM_TRIDENT2_SUPPORT */ 11630 11631 #ifdef BCM_TRIUMPH3_SUPPORT 11632 if (soc_feature(unit, soc_feature_lag_dlb) && 11633 !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 11634 BCM_IF_ERROR_RETURN(bcm_tr3_lag_dlb_member_recover(unit)); 11635 BCM_IF_ERROR_RETURN(bcm_tr3_lag_dlb_quality_parameters_recover(unit)); 11636 } 11637 #endif /* BCM_TRIUMPH3_SUPPORT */ 11638 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined (BCM_TRIDENT3_SUPPORT) 11639 if (soc_feature(unit, soc_feature_lag_dlb) && 11640 soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 11641 BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_quality_parameters_recover(unit)); 11642 } 11643 #endif /* BCM_TOMAHAWK2_SUPPORT */ 11644 11645 11646 return rv; 11647 } 11648 11649 /* 11650 * Function: 11651 * bcm_trident_hg_dlb_wb_alloc_size_get 11652 * Purpose: 11653 * Get level 2 warm boot scache size for Higig DLB. 11654 * Parameters: 11655 * unit - (IN) SOC unit number. 11656 * size - (OUT) Allocation size. 11657 * Returns: 11658 * BCM_E_XXX 11659 */ 11660 int 11661 bcm_trident_hg_dlb_wb_alloc_size_get(int unit, int *size) 11662 { 11663 int alloc_size = 0; 11664 int num_elements = 0; 11665 soc_field_t profile_ptr_f; 11666 11667 /* Allocate size for the following Higig DLB parameters: 11668 * int hg_dlb_sample_rate; 11669 * int hg_dlb_tx_load_min_th; 11670 * int hg_dlb_tx_load_max_th; 11671 * int hg_dlb_qsize_min_th; 11672 * int hg_dlb_qsize_max_th; 11673 */ 11674 alloc_size += sizeof(int) * 5; 11675 11676 /* Allocate size of hg_dlb_load_weight array */ 11677 if (soc_reg_field_valid(unit, DLB_HGT_QUANTIZE_CONTROLr, 11678 PORT_QUALITY_MAPPING_PROFILE_PTRf)) { 11679 num_elements = 1 << soc_reg_field_length(unit, 11680 DLB_HGT_QUANTIZE_CONTROLr, PORT_QUALITY_MAPPING_PROFILE_PTRf); 11681 } else { 11682 profile_ptr_f = soc_mem_field_valid(unit, DLB_HGT_QUALITY_CONTROLm, 11683 PROFILE_PTRf) ? PROFILE_PTRf : QMT_PROFILE_PTRf; 11684 num_elements = 1 << soc_mem_field_length(unit, 11685 DLB_HGT_QUALITY_CONTROLm, profile_ptr_f); 11686 } 11687 alloc_size += sizeof(uint8) * num_elements; 11688 11689 *size = alloc_size; 11690 11691 return BCM_E_NONE; 11692 } 11693 11694 /* 11695 * Function: 11696 * bcm_trident_hg_dlb_sync 11697 * Purpose: 11698 * Store Higig DLB parameters into scache. 11699 * Parameters: 11700 * unit - (IN) SOC unit number. 11701 * scache_ptr - (IN/OUT) Scache pointer 11702 * Returns: 11703 * BCM_E_XXX 11704 */ 11705 int 11706 bcm_trident_hg_dlb_sync(int unit, uint8 **scache_ptr) 11707 { 11708 int value; 11709 int num_elements = 0; 11710 int i; 11711 uint8 load_weight; 11712 soc_field_t profile_ptr_f; 11713 11714 /* Store the following Higig DLB parameters: 11715 * int hg_dlb_sample_rate; 11716 * int hg_dlb_tx_load_min_th; 11717 * int hg_dlb_tx_load_max_th; 11718 * int hg_dlb_qsize_min_th; 11719 * int hg_dlb_qsize_max_th; 11720 */ 11721 value = HG_DLB_INFO(unit)->hg_dlb_sample_rate; 11722 sal_memcpy((*scache_ptr), &value, sizeof(int)); 11723 (*scache_ptr) += sizeof(int); 11724 11725 value = HG_DLB_INFO(unit)->hg_dlb_tx_load_min_th; 11726 sal_memcpy((*scache_ptr), &value, sizeof(int)); 11727 (*scache_ptr) += sizeof(int); 11728 11729 value = HG_DLB_INFO(unit)->hg_dlb_tx_load_max_th; 11730 sal_memcpy((*scache_ptr), &value, sizeof(int)); 11731 (*scache_ptr) += sizeof(int); 11732 11733 value = HG_DLB_INFO(unit)->hg_dlb_qsize_min_th; 11734 sal_memcpy((*scache_ptr), &value, sizeof(int)); 11735 (*scache_ptr) += sizeof(int); 11736 11737 value = HG_DLB_INFO(unit)->hg_dlb_qsize_max_th; 11738 sal_memcpy((*scache_ptr), &value, sizeof(int)); 11739 (*scache_ptr) += sizeof(int); 11740 11741 /* Store hg_dlb_load_weight array */ 11742 if (soc_reg_field_valid(unit, DLB_HGT_QUANTIZE_CONTROLr, 11743 PORT_QUALITY_MAPPING_PROFILE_PTRf)) { 11744 num_elements = 1 << soc_reg_field_length(unit, 11745 DLB_HGT_QUANTIZE_CONTROLr, PORT_QUALITY_MAPPING_PROFILE_PTRf); 11746 } else { 11747 profile_ptr_f = soc_mem_field_valid(unit, DLB_HGT_QUALITY_CONTROLm, 11748 PROFILE_PTRf) ? PROFILE_PTRf : QMT_PROFILE_PTRf; 11749 num_elements = 1 << soc_mem_field_length(unit, 11750 DLB_HGT_QUALITY_CONTROLm, profile_ptr_f); 11751 } 11752 for (i = 0; i < num_elements; i++) { 11753 load_weight = HG_DLB_INFO(unit)->hg_dlb_load_weight[i]; 11754 sal_memcpy((*scache_ptr), &load_weight, sizeof(uint8)); 11755 (*scache_ptr) += sizeof(uint8); 11756 } 11757 11758 return BCM_E_NONE; 11759 } 11760 11761 /* 11762 * Function: 11763 * bcm_trident_hg_dlb_scache_recover 11764 * Purpose: 11765 * Recover Higig DLB parameters from scache. 11766 * Parameters: 11767 * unit - (IN) SOC unit number. 11768 * scache_ptr - (IN/OUT) Scache pointer 11769 * Returns: 11770 * BCM_E_XXX 11771 */ 11772 int 11773 bcm_trident_hg_dlb_scache_recover(int unit, uint8 **scache_ptr) 11774 { 11775 int value; 11776 int num_elements = 0; 11777 int i; 11778 uint8 load_weight; 11779 soc_field_t profile_ptr_f; 11780 11781 /* Recover the following Higig DLB parameters: 11782 * int hg_dlb_sample_rate; 11783 * int hg_dlb_tx_load_min_th; 11784 * int hg_dlb_tx_load_max_th; 11785 * int hg_dlb_qsize_min_th; 11786 * int hg_dlb_qsize_max_th; 11787 */ 11788 sal_memcpy(&value, (*scache_ptr), sizeof(int)); 11789 HG_DLB_INFO(unit)->hg_dlb_sample_rate = value; 11790 (*scache_ptr) += sizeof(int); 11791 11792 sal_memcpy(&value, (*scache_ptr), sizeof(int)); 11793 HG_DLB_INFO(unit)->hg_dlb_tx_load_min_th = value; 11794 (*scache_ptr) += sizeof(int); 11795 11796 sal_memcpy(&value, (*scache_ptr), sizeof(int)); 11797 HG_DLB_INFO(unit)->hg_dlb_tx_load_max_th = value; 11798 (*scache_ptr) += sizeof(int); 11799 11800 sal_memcpy(&value, (*scache_ptr), sizeof(int)); 11801 HG_DLB_INFO(unit)->hg_dlb_qsize_min_th = value; 11802 (*scache_ptr) += sizeof(int); 11803 11804 sal_memcpy(&value, (*scache_ptr), sizeof(int)); 11805 HG_DLB_INFO(unit)->hg_dlb_qsize_max_th = value; 11806 (*scache_ptr) += sizeof(int); 11807 11808 /* Recover hg_dlb_load_weight array */ 11809 if (soc_reg_field_valid(unit, DLB_HGT_QUANTIZE_CONTROLr, 11810 PORT_QUALITY_MAPPING_PROFILE_PTRf)) { 11811 num_elements = 1 << soc_reg_field_length(unit, 11812 DLB_HGT_QUANTIZE_CONTROLr, PORT_QUALITY_MAPPING_PROFILE_PTRf); 11813 } else { 11814 profile_ptr_f = soc_mem_field_valid(unit, DLB_HGT_QUALITY_CONTROLm, 11815 PROFILE_PTRf) ? PROFILE_PTRf : QMT_PROFILE_PTRf; 11816 num_elements = 1 << soc_mem_field_length(unit, 11817 DLB_HGT_QUALITY_CONTROLm, profile_ptr_f); 11818 } 11819 for (i = 0; i < num_elements; i++) { 11820 sal_memcpy(&load_weight, (*scache_ptr), sizeof(uint8)); 11821 HG_DLB_INFO(unit)->hg_dlb_load_weight[i] = load_weight; 11822 (*scache_ptr) += sizeof(uint8); 11823 } 11824 11825 HG_DLB_INFO(unit)->recovered_from_scache = TRUE; 11826 11827 return BCM_E_NONE; 11828 } 11829 11830 #ifdef BCM_TRIUMPH3_SUPPORT 11831 /* 11832 * Function: 11833 * _bcm_tr3_hg_dlb_member_recover 11834 * Purpose: 11835 * Recover Higig DLB member ID usage. 11836 * Parameters: 11837 * unit - (IN) SOC unit number. 11838 * Returns: 11839 * BCM_E_XXX 11840 */ 11841 STATIC int 11842 _bcm_tr3_hg_dlb_member_recover(int unit) 11843 { 11844 int i, member_id; 11845 dlb_hgt_port_member_map_entry_t port_member_map_entry; 11846 11847 for (i = 0; i < soc_mem_index_count(unit, DLB_HGT_PORT_MEMBER_MAPm); 11848 i++) { 11849 SOC_IF_ERROR_RETURN(READ_DLB_HGT_PORT_MEMBER_MAPm(unit, 11850 MEM_BLOCK_ANY, i, &port_member_map_entry)); 11851 if (soc_DLB_HGT_PORT_MEMBER_MAPm_field32_get(unit, 11852 &port_member_map_entry, VALIDf)) { 11853 member_id = soc_DLB_HGT_PORT_MEMBER_MAPm_field32_get(unit, 11854 &port_member_map_entry, MEMBER_IDf); 11855 _BCM_HG_DLB_MEMBER_ID_USED_SET(unit, member_id); 11856 } 11857 } 11858 11859 return BCM_E_NONE; 11860 } 11861 #endif /* BCM_TRIUMPH3_SUPPORT */ 11862 11863 /* 11864 * Function: 11865 * _bcm_trident_hg_dlb_quality_parameters_recover 11866 * Purpose: 11867 * Recover Higig DLB parameters used to derive a member's quality. 11868 * Parameters: 11869 * unit - (IN) SOC unit number. 11870 * Returns: 11871 * BCM_E_XXX 11872 */ 11873 STATIC int 11874 _bcm_trident_hg_dlb_quality_parameters_recover(int unit) 11875 { 11876 uint32 measure_control_reg; 11877 int num_time_units; 11878 dlb_hgt_glb_quantize_thresholds_entry_t thresholds_entry; 11879 int max_th_bytes; 11880 int min_th_bytes; 11881 int max_th_cells; 11882 int min_th_cells; 11883 int entries_per_profile; 11884 int base_index; 11885 int profile_ptr; 11886 dlb_hgt_port_quality_mapping_entry_t port_quality_mapping_entry; 11887 int quality; 11888 11889 if (HG_DLB_INFO(unit)->recovered_from_scache) { 11890 /* If already recovered fro scache, do nothing */ 11891 return BCM_E_NONE; 11892 } 11893 11894 /* Recover sampling rate */ 11895 SOC_IF_ERROR_RETURN(READ_DLB_HGT_QUALITY_MEASURE_CONTROLr(unit, 11896 &measure_control_reg)); 11897 num_time_units = soc_reg_field_get(unit, DLB_HGT_QUALITY_MEASURE_CONTROLr, 11898 measure_control_reg, SAMPLING_PERIODf); 11899 #ifdef BCM_TRIUMPH3_SUPPORT 11900 if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TD2_TT2(unit)) { 11901 /* Sampling rate = 10^6 / num_time_units */ 11902 if (num_time_units > 0) { 11903 HG_DLB_INFO(unit)->hg_dlb_sample_rate = 1000000 / num_time_units; 11904 } 11905 } else 11906 #endif /* BCM_TRIUMPH3_SUPPORT */ 11907 { 11908 /* Sampling rate = 10^9 ns / (256 ns * num_time_units) 11909 * = 3906250 / num_time_units 11910 */ 11911 if (num_time_units > 0) { 11912 HG_DLB_INFO(unit)->hg_dlb_sample_rate = 3906250 / num_time_units; 11913 } 11914 } 11915 11916 /* Recover max and min load and queue size thresholds */ 11917 /* Threshold (in mbps) 11918 * = (bytes per sampling period) * 8 bits per byte / 11919 * (sampling period in seconds) / 10^6 11920 * = (bytes per sampling period) * 8 bits per byte / 11921 * (num_time_units * 1 us per time unit * 10^-6) / 10^6 11922 * = (bytes per sampling period) * 8 / num_time_units 11923 */ 11924 11925 #ifdef BCM_TRIDENT2_SUPPORT 11926 if (SOC_IS_TD2_TT2(unit)) { 11927 dlb_hgt_pla_quantize_threshold_entry_t quantize_threshold_entry; 11928 11929 SOC_IF_ERROR_RETURN(READ_DLB_HGT_PLA_QUANTIZE_THRESHOLDm(unit, 11930 MEM_BLOCK_ANY, 0, &quantize_threshold_entry)); 11931 min_th_bytes = soc_DLB_HGT_PLA_QUANTIZE_THRESHOLDm_field32_get 11932 (unit, &quantize_threshold_entry, LOADING_THRESHOLDf); 11933 HG_DLB_INFO(unit)->hg_dlb_tx_load_min_th = (min_th_bytes << 3) / 11934 num_time_units; 11935 11936 min_th_cells = soc_DLB_HGT_PLA_QUANTIZE_THRESHOLDm_field32_get 11937 (unit, &quantize_threshold_entry, QSIZE_THRESHOLDf); 11938 HG_DLB_INFO(unit)->hg_dlb_qsize_min_th = min_th_cells * 208; 11939 11940 SOC_IF_ERROR_RETURN(READ_DLB_HGT_PLA_QUANTIZE_THRESHOLDm(unit, 11941 MEM_BLOCK_ANY, 6, &quantize_threshold_entry)); 11942 max_th_bytes = soc_DLB_HGT_PLA_QUANTIZE_THRESHOLDm_field32_get 11943 (unit, &quantize_threshold_entry, LOADING_THRESHOLDf); 11944 HG_DLB_INFO(unit)->hg_dlb_tx_load_max_th = (max_th_bytes << 3) / 11945 num_time_units; 11946 11947 max_th_cells = soc_DLB_HGT_PLA_QUANTIZE_THRESHOLDm_field32_get 11948 (unit, &quantize_threshold_entry, QSIZE_THRESHOLDf); 11949 HG_DLB_INFO(unit)->hg_dlb_qsize_max_th = max_th_cells * 208; 11950 11951 } else 11952 #endif /* BCM_TRIDENT2_SUPPORT */ 11953 #ifdef BCM_TRIUMPH3_SUPPORT 11954 if (SOC_IS_TRIUMPH3(unit)) { 11955 dlb_hgt_quantize_threshold_entry_t quantize_threshold_entry; 11956 11957 SOC_IF_ERROR_RETURN(READ_DLB_HGT_QUANTIZE_THRESHOLDm(unit, 11958 MEM_BLOCK_ANY, 0, &quantize_threshold_entry)); 11959 min_th_bytes = soc_DLB_HGT_QUANTIZE_THRESHOLDm_field32_get 11960 (unit, &quantize_threshold_entry, LOADING_THRESHOLDf); 11961 HG_DLB_INFO(unit)->hg_dlb_tx_load_min_th = (min_th_bytes << 3) / 11962 num_time_units; 11963 11964 min_th_cells = soc_DLB_HGT_QUANTIZE_THRESHOLDm_field32_get 11965 (unit, &quantize_threshold_entry, QSIZE_THRESHOLDf); 11966 HG_DLB_INFO(unit)->hg_dlb_qsize_min_th = min_th_cells * 208; 11967 11968 SOC_IF_ERROR_RETURN(READ_DLB_HGT_QUANTIZE_THRESHOLDm(unit, 11969 MEM_BLOCK_ANY, 6, &quantize_threshold_entry)); 11970 max_th_bytes = soc_DLB_HGT_QUANTIZE_THRESHOLDm_field32_get 11971 (unit, &quantize_threshold_entry, LOADING_THRESHOLDf); 11972 HG_DLB_INFO(unit)->hg_dlb_tx_load_max_th = (max_th_bytes << 3) / 11973 num_time_units; 11974 11975 max_th_cells = soc_DLB_HGT_QUANTIZE_THRESHOLDm_field32_get 11976 (unit, &quantize_threshold_entry, QSIZE_THRESHOLDf); 11977 HG_DLB_INFO(unit)->hg_dlb_qsize_max_th = max_th_cells * 208; 11978 } else 11979 #endif /* BCM_TRIUMPH3_SUPPORT */ 11980 { 11981 /* Threshold (in mbps) 11982 * = (bytes per sampling period) * 8 bits per byte / 11983 * (sampling period in seconds) / 10^6 11984 * = (bytes per sampling period) * 8 bits per byte / 11985 * (num_time_units * 256 ns per time unit * 10^-9) / 10^6 11986 * = (bytes per sampling period) * 8000 / num_time_units / 256 11987 */ 11988 SOC_IF_ERROR_RETURN(READ_DLB_HGT_GLB_QUANTIZE_THRESHOLDSm(unit, 11989 MEM_BLOCK_ANY, 0, &thresholds_entry)); 11990 min_th_bytes = soc_DLB_HGT_GLB_QUANTIZE_THRESHOLDSm_field32_get 11991 (unit, &thresholds_entry, PORT_LOADING_THRESHOLD_1f); 11992 HG_DLB_INFO(unit)->hg_dlb_tx_load_min_th = 11993 ((min_th_bytes << 3) * 1000 / num_time_units) >> 8; 11994 11995 max_th_bytes = soc_DLB_HGT_GLB_QUANTIZE_THRESHOLDSm_field32_get 11996 (unit, &thresholds_entry, PORT_LOADING_THRESHOLD_7f); 11997 HG_DLB_INFO(unit)->hg_dlb_tx_load_max_th = 11998 ((max_th_bytes << 3) * 1000 / num_time_units) >> 8; 11999 12000 min_th_cells = soc_DLB_HGT_GLB_QUANTIZE_THRESHOLDSm_field32_get 12001 (unit, &thresholds_entry, PORT_QSIZE_THRESHOLD_1f); 12002 HG_DLB_INFO(unit)->hg_dlb_qsize_min_th = min_th_cells * 208; 12003 12004 max_th_cells = soc_DLB_HGT_GLB_QUANTIZE_THRESHOLDSm_field32_get 12005 (unit, &thresholds_entry, PORT_QSIZE_THRESHOLD_7f); 12006 HG_DLB_INFO(unit)->hg_dlb_qsize_max_th = max_th_cells * 208; 12007 } 12008 12009 /* Recover load weights */ 12010 12011 #ifdef BCM_TRIUMPH3_SUPPORT 12012 if (soc_feature(unit, soc_feature_hg_dlb_member_id)) { 12013 soc_field_t profile_ptr_f, quality_f; 12014 dlb_hgt_quality_mapping_entry_t quality_mapping_entry; 12015 12016 entries_per_profile = 64; 12017 profile_ptr_f = soc_mem_field_valid(unit, DLB_HGT_QUALITY_CONTROLm, 12018 PROFILE_PTRf) ? PROFILE_PTRf : QMT_PROFILE_PTRf; 12019 quality_f = soc_mem_field_valid(unit, DLB_HGT_QUALITY_MAPPINGm, 12020 QUALITYf) ? QUALITYf : ASSIGNED_QUALITYf; 12021 for (profile_ptr = 0; 12022 profile_ptr < (1 << soc_mem_field_length(unit, 12023 DLB_HGT_QUALITY_CONTROLm, profile_ptr_f)); 12024 profile_ptr++) { 12025 base_index = profile_ptr * entries_per_profile; 12026 /* quality = (quantized_tx_load * tx_load_percent + 12027 * quantized_qsize * (100 - tx_load_percent)) / 12028 * 100; 12029 * quality = ((quantized_tx_load - quantized_qsize) * 12030 * tx_load_percent + quantized_qsize * 100) / 12031 * 100; 12032 * quality = (quantized_tx_load - quantized_qsize) * 12033 * tx_load_percent / 100 + quantized_qsize; 12034 * tx_load_percent = (quality - quantized_qsize) * 100 / 12035 * (quantized_tx_load - quantized_qsize); 12036 * 12037 * The index to DLB_HGT_QUALITY_MAPPING table consists of 12038 * base_index + quantized_tx_load * 8 + quantized_qsize, 12039 * where quantized_tx_load and quantized_qsize range from 12040 * 0 to 7. 12041 * 12042 * With quantized_tx_load = 7 and quantized_qsize = 0, the 12043 * index to DLB_HGT_QUALITY_MAPPING table is 12044 * base_index + 56, and the tx_load_present expression 12045 * simplifies to quality * 100 / 7; 12046 */ 12047 BCM_IF_ERROR_RETURN(READ_DLB_HGT_QUALITY_MAPPINGm(unit, 12048 MEM_BLOCK_ANY, base_index + 56, 12049 &quality_mapping_entry)); 12050 quality = soc_DLB_HGT_QUALITY_MAPPINGm_field32_get(unit, 12051 &port_quality_mapping_entry, quality_f); 12052 HG_DLB_INFO(unit)->hg_dlb_load_weight[profile_ptr] = 12053 quality * 100 / 7; 12054 } 12055 } else 12056 #endif /* BCM_TRIUMPH3_SUPPORT */ 12057 { 12058 entries_per_profile = 64; 12059 for (profile_ptr = 0; 12060 profile_ptr < (1 << soc_reg_field_length(unit, 12061 DLB_HGT_QUANTIZE_CONTROLr, 12062 PORT_QUALITY_MAPPING_PROFILE_PTRf)); 12063 profile_ptr++) { 12064 base_index = profile_ptr * entries_per_profile; 12065 /* quality = (quantized_tx_load * tx_load_percent + 12066 * quantized_qsize * (100 - tx_load_percent)) / 100; 12067 * quality = ((quantized_tx_load - quantized_qsize) * 12068 * tx_load_percent + quantized_qsize * 100) / 100; 12069 * quality = (quantized_tx_load - quantized_qsize) * 12070 * tx_load_percent / 100 + quantized_qsize; 12071 * tx_load_percent = (quality - quantized_qsize) * 100 / 12072 * (quantized_tx_load - quantized_qsize); 12073 * 12074 * The index to DLB_HGT_PORT_QUALITY_MAPPING table consists of 12075 * base_index + quantized_tx_load * 8 + quantized_qsize, where 12076 * quantized_tx_load and quantized_qsize range from 0 to 7. 12077 * 12078 * With quantized_tx_load = 7 and quantized_qsize = 0, the 12079 * index to DLB_HGT_PORT_QUALITY_MAPPING table is 12080 * base_index + 56, and the tx_load_present expression 12081 * simplifies to quality * 100 / 7; 12082 */ 12083 BCM_IF_ERROR_RETURN(READ_DLB_HGT_PORT_QUALITY_MAPPINGm(unit, 12084 MEM_BLOCK_ANY, base_index + 56, 12085 &port_quality_mapping_entry)); 12086 quality = soc_DLB_HGT_PORT_QUALITY_MAPPINGm_field32_get(unit, 12087 &port_quality_mapping_entry, ASSIGNED_QUALITYf); 12088 HG_DLB_INFO(unit)->hg_dlb_load_weight[profile_ptr] = 12089 quality * 100 / 7; 12090 } 12091 } 12092 12093 return BCM_E_NONE; 12094 } 12095 12096 /* 12097 * Function: 12098 * _bcm_trident_hg_tg_size_field_forced 12099 * Purpose: 12100 * Determine if the TG_SIZE field in HG_TRUNK_GROUP table is forced 12101 * by hardware to be 0xf when RTAG field is less than or equal to 6. 12102 * Parameters: 12103 * unit - (IN) SOC unit number. 12104 * Returns: 12105 * BCM_E_xxx 12106 */ 12107 STATIC int 12108 _bcm_trident_hg_tg_size_field_forced(int unit) 12109 { 12110 uint16 dev_id; 12111 uint8 rev_id; 12112 12113 soc_cm_get_id(unit, &dev_id, &rev_id); 12114 12115 if ((dev_id == BCM56841_DEVICE_ID && rev_id >= BCM56841_B0_REV_ID) || 12116 (dev_id == BCM56843_DEVICE_ID && rev_id >= BCM56843_B0_REV_ID) || 12117 (dev_id == BCM56845_DEVICE_ID && rev_id >= BCM56845_B0_REV_ID)) { 12118 /* For these devices, the HG_TRUNK_GROUP.TG_SIZE field is forced 12119 * by harware to be 0xf when RTAG field is less than or equal to 6. 12120 */ 12121 return TRUE; 12122 } else { 12123 return FALSE; 12124 } 12125 } 12126 12127 /* 12128 * Function: 12129 * _bcm_trident_hg_dlb_group_recover 12130 * Purpose: 12131 * Recover HGT DLB group usage and flowset table usage. 12132 * Parameters: 12133 * unit - (IN) SOC unit number. 12134 * hgtid - (IN) HiGig Trunk group ID. 12135 * trunk_info - (OUT) Per trunk group DLB info. 12136 * Returns: 12137 * BCM_E_XXX 12138 */ 12139 STATIC int 12140 _bcm_trident_hg_dlb_group_recover(int unit, bcm_trunk_t hgtid, 12141 trunk_private_t *trunk_info) 12142 { 12143 hgt_dlb_control_entry_t hgt_dlb_control_entry; 12144 12145 int dlb_enable, dlb_id; 12146 dlb_hgt_group_control_entry_t dlb_hgt_group_control_entry; 12147 int dlb_mode; 12148 int dynamic_size_encode, dynamic_size; 12149 int entry_base_ptr; 12150 int block_base_ptr, num_blocks; 12151 12152 #ifdef BCM_TRIDENT2_SUPPORT 12153 if (soc_feature(unit, soc_feature_hg_dlb_id_equal_hg_tid)) { 12154 SOC_IF_ERROR_RETURN(READ_DLB_HGT_GROUP_CONTROLm(unit, MEM_BLOCK_ANY, 12155 hgtid, &dlb_hgt_group_control_entry)); 12156 dlb_enable = soc_DLB_HGT_GROUP_CONTROLm_field32_get(unit, 12157 &dlb_hgt_group_control_entry, GROUP_ENABLEf); 12158 dlb_id = hgtid; 12159 } else 12160 #endif /* BCM_TRIDENT2_SUPPORT */ 12161 { 12162 SOC_IF_ERROR_RETURN(READ_HGT_DLB_CONTROLm(unit, MEM_BLOCK_ANY, 12163 hgtid, &hgt_dlb_control_entry)); 12164 dlb_enable = soc_HGT_DLB_CONTROLm_field32_get(unit, 12165 &hgt_dlb_control_entry, GROUP_ENABLEf); 12166 dlb_id = soc_HGT_DLB_CONTROLm_field32_get(unit, 12167 &hgt_dlb_control_entry, DLB_IDf); 12168 } 12169 12170 if (dlb_enable) { 12171 12172 /* Mark Higig DLB group as used */ 12173 _BCM_HG_DLB_ID_USED_SET(unit, dlb_id); 12174 12175 SOC_IF_ERROR_RETURN(READ_DLB_HGT_GROUP_CONTROLm(unit, 12176 MEM_BLOCK_ANY, dlb_id, &dlb_hgt_group_control_entry)); 12177 12178 /* Recover DLB mode */ 12179 #ifdef BCM_TRIUMPH3_SUPPORT 12180 if (soc_mem_field_valid(unit, DLB_HGT_GROUP_CONTROLm, 12181 MEMBER_ASSIGNMENT_MODEf)) { 12182 dlb_mode = soc_DLB_HGT_GROUP_CONTROLm_field32_get(unit, 12183 &dlb_hgt_group_control_entry, MEMBER_ASSIGNMENT_MODEf); 12184 } else 12185 #endif /* BCM_TRIUMPH3_SUPPORT */ 12186 { 12187 dlb_mode = soc_DLB_HGT_GROUP_CONTROLm_field32_get(unit, 12188 &dlb_hgt_group_control_entry, PORT_ASSIGNMENT_MODEf); 12189 } 12190 switch (dlb_mode) { 12191 case 0: 12192 trunk_info->psc = BCM_TRUNK_PSC_DYNAMIC; 12193 break; 12194 case 1: 12195 trunk_info->psc = BCM_TRUNK_PSC_DYNAMIC_ASSIGNED; 12196 break; 12197 case 2: 12198 trunk_info->psc = BCM_TRUNK_PSC_DYNAMIC_OPTIMAL; 12199 break; 12200 default: 12201 return BCM_E_INTERNAL; 12202 } 12203 12204 /* Recover dynamic_size */ 12205 dynamic_size_encode = soc_DLB_HGT_GROUP_CONTROLm_field32_get(unit, 12206 &dlb_hgt_group_control_entry, FLOW_SET_SIZEf); 12207 BCM_IF_ERROR_RETURN 12208 (_bcm_trident_hg_dlb_dynamic_size_decode(dynamic_size_encode, 12209 &dynamic_size)); 12210 trunk_info->dynamic_size = dynamic_size; 12211 12212 /* Recover dynamic_age */ 12213 trunk_info->dynamic_age = soc_DLB_HGT_GROUP_CONTROLm_field32_get(unit, 12214 &dlb_hgt_group_control_entry, INACTIVITY_DURATIONf); 12215 12216 12217 /* Recover flow set table usage */ 12218 entry_base_ptr = soc_DLB_HGT_GROUP_CONTROLm_field32_get(unit, 12219 &dlb_hgt_group_control_entry, FLOW_SET_BASEf); 12220 block_base_ptr = entry_base_ptr >> 9; 12221 num_blocks = trunk_info->dynamic_size >> 9; 12222 _BCM_HG_DLB_FLOWSET_BLOCK_USED_SET_RANGE(unit, block_base_ptr, 12223 num_blocks); 12224 } 12225 return BCM_E_NONE; 12226 } 12227 /* 12228 * Handle state recovery for fabric trunks 12229 */ 12230 int 12231 _bcm_trident_trunk_fabric_reinit(int unit, int min_tid, int max_tid, 12232 trunk_private_t *trunk_info) 12233 { 12234 int rv = BCM_E_NONE; 12235 int tid, hgtid; 12236 hg_trunk_group_entry_t hg_tg_entry; 12237 hg_trunk_member_entry_t hg_trunk_member_entry; 12238 hg_trunk_bitmap_entry_t hg_trunk_bitmap_entry; 12239 int base_ptr, tg_size, rtag; 12240 bcm_port_t *hwport; 12241 int i; 12242 bcm_pbmp_t hg_trunk_pbmp; 12243 int hwf_rtag, hwf_psc; 12244 _trident_hw_tinfo_t *hwft; 12245 int num_entries; 12246 12247 for (tid = min_tid; tid <= max_tid; tid++, trunk_info++) { 12248 12249 hgtid = tid - min_tid; 12250 12251 SOC_IF_ERROR_RETURN 12252 (READ_HG_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, hgtid, 12253 &hg_tg_entry)); 12254 base_ptr = soc_HG_TRUNK_GROUPm_field32_get(unit, &hg_tg_entry, 12255 BASE_PTRf); 12256 if (_bcm_trident_hg_tg_size_field_forced(unit)) { 12257 tg_size = _bcm_trident_hw_failover_num_ports_get(unit, hgtid, TRUE); 12258 if (tg_size == 0) { 12259 /* Invalid Higig trunk group */ 12260 continue; 12261 } 12262 } else { 12263 tg_size = 1 + soc_HG_TRUNK_GROUPm_field32_get(unit, &hg_tg_entry, 12264 TG_SIZEf); 12265 if ((0 == base_ptr) && (tg_size == 1)) { 12266 /* Invalid Higig trunk group */ 12267 continue; 12268 } 12269 } 12270 12271 rtag = soc_HG_TRUNK_GROUPm_field32_get(unit, &hg_tg_entry, RTAGf); 12272 12273 /* Recover trunk info */ 12274 trunk_info->tid = tid; 12275 trunk_info->in_use = TRUE; 12276 BCM_IF_ERROR_RETURN 12277 (_bcm_trident_trunk_rtag_to_psc(unit, rtag, &trunk_info->psc)); 12278 trunk_info->rtag = rtag; 12279 /* trunk_info->flags already recovered from scache */ 12280 12281 /* Recover trunk member table bookkeeping info */ 12282 num_entries = tg_size; 12283 if (rtag >= 1 && rtag <= 6) { 12284 #ifdef BCM_KATANA_SUPPORT 12285 if (SOC_IS_KATANAX(unit)) { 12286 num_entries = _BCM_KATANA_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT; 12287 } else 12288 #endif 12289 if (soc_feature(unit, 12290 soc_feature_rtag1_6_max_portcnt_less_than_rtag7)) { 12291 num_entries = _BCM_TD_FABRIC_TRUNK_RTAG1_6_MAX_PORTCNT; 12292 } 12293 } 12294 _BCM_HG_TRUNK_MEMBER_USED_SET_RANGE(unit, base_ptr, num_entries); 12295 12296 /* Recover Higig DLB group info */ 12297 if (soc_feature(unit, soc_feature_hg_dlb) && 12298 !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 12299 BCM_IF_ERROR_RETURN 12300 (_bcm_trident_hg_dlb_group_recover(unit, hgtid, trunk_info)); 12301 } 12302 12303 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 12304 if (soc_feature(unit, soc_feature_hg_dlb) && 12305 soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 12306 BCM_IF_ERROR_RETURN 12307 (bcm_th2_hgt_lag_dlb_group_recover(unit, hgtid, 1, trunk_info)); 12308 } 12309 #endif /* BCM_TOMAHAWK2_SUPPORT */ 12310 12311 #ifdef BCM_TRIDENT2_SUPPORT 12312 /* Recover Higig resilient hashing group info */ 12313 if (soc_feature(unit, soc_feature_hg_resilient_hash)) { 12314 BCM_IF_ERROR_RETURN(bcm_td2_hg_rh_recover(unit, hgtid, trunk_info)); 12315 } 12316 #endif /* BCM_TRIDENT2_SUPPORT */ 12317 12318 /* Recover trunk member info */ 12319 hwport = sal_alloc(sizeof(bcm_port_t) * tg_size, "hwport"); 12320 if (hwport == NULL) { 12321 return BCM_E_MEMORY; 12322 } 12323 sal_memset(hwport, 0, sizeof(bcm_port_t) * tg_size); 12324 for (i = 0; i < tg_size; i++) { 12325 rv = READ_HG_TRUNK_MEMBERm(unit, MEM_BLOCK_ANY, base_ptr + i, 12326 &hg_trunk_member_entry); 12327 if (BCM_FAILURE(rv)) { 12328 sal_free(hwport); 12329 return rv; 12330 } 12331 #if defined(BCM_KATANA2_SUPPORT) 12332 if (SOC_IS_KATANA2(unit)) { 12333 hwport[i] = soc_HG_TRUNK_MEMBERm_field32_get 12334 (unit, &hg_trunk_member_entry, PHYSICAL_PORTf); 12335 } else 12336 #endif /* BCM_KATANA2_SUPPORT */ 12337 { 12338 hwport[i] = soc_HG_TRUNK_MEMBERm_field32_get 12339 (unit, &hg_trunk_member_entry, PORT_NUMf); 12340 } 12341 } 12342 12343 if (MEMBER_INFO(unit, tid).modport) { 12344 sal_free(MEMBER_INFO(unit, tid).modport); 12345 MEMBER_INFO(unit, tid).modport = NULL; 12346 } 12347 if (MEMBER_INFO(unit, tid).member_flags) { 12348 sal_free(MEMBER_INFO(unit, tid).member_flags); 12349 MEMBER_INFO(unit, tid).member_flags = NULL; 12350 } 12351 MEMBER_INFO(unit, tid).num_ports = tg_size; 12352 MEMBER_INFO(unit, tid).modport = sal_alloc( 12353 sizeof(uint16) * MEMBER_INFO(unit, tid).num_ports, 12354 "member info modport"); 12355 if (NULL == MEMBER_INFO(unit, tid).modport) { 12356 sal_free(hwport); 12357 return BCM_E_MEMORY; 12358 } 12359 MEMBER_INFO(unit, tid).member_flags = sal_alloc( 12360 sizeof(uint32) * MEMBER_INFO(unit, tid).num_ports, 12361 "member info flags"); 12362 if (NULL == MEMBER_INFO(unit, tid).member_flags) { 12363 sal_free(hwport); 12364 sal_free(MEMBER_INFO(unit, tid).modport); 12365 MEMBER_INFO(unit, tid).modport = NULL; 12366 return BCM_E_MEMORY; 12367 } 12368 for (i = 0; i < tg_size; i++) { 12369 MEMBER_INFO(unit, tid).modport[i] = hwport[i]; 12370 MEMBER_INFO(unit, tid).member_flags[i] = 0; 12371 } 12372 12373 /* Recover software trunk failover state */ 12374 rv = READ_HG_TRUNK_BITMAPm(unit, MEM_BLOCK_ANY, hgtid, 12375 &hg_trunk_bitmap_entry); 12376 if (BCM_FAILURE(rv)) { 12377 sal_free(hwport); 12378 return rv; 12379 } 12380 soc_mem_pbmp_field_get(unit, HG_TRUNK_BITMAPm, &hg_trunk_bitmap_entry, 12381 HIGIG_TRUNK_BITMAPf, &hg_trunk_pbmp); 12382 rv = _bcm_trident_trunk_swfailover_fabric_set(unit, hgtid, 12383 trunk_info->rtag, hg_trunk_pbmp); 12384 if (BCM_FAILURE(rv)) { 12385 sal_free(hwport); 12386 return rv; 12387 } 12388 12389 /* Recover hardware trunk failover state. */ 12390 if (soc_feature(unit, soc_feature_hg_trunk_failover)) { 12391 hwft = &(_trident_trunk_hwfail[unit]->hw_tinfo[tid]); 12392 hwft->num_ports = tg_size; 12393 if (hwft->modport == NULL) { 12394 hwft->modport = sal_alloc(sizeof(uint16) * tg_size, 12395 "hw_tinfo_modport"); 12396 if (hwft->modport == NULL) { 12397 sal_free(hwport); 12398 return BCM_E_MEMORY; 12399 } 12400 } 12401 sal_memset(hwft->modport, 0, sizeof(uint16) * tg_size); 12402 12403 if (hwft->psc == NULL) { 12404 hwft->psc = sal_alloc(sizeof(uint8) * tg_size, 12405 "hw_tinfo_psc"); 12406 if (hwft->psc == NULL) { 12407 sal_free(hwft->modport); 12408 hwft->modport = NULL; 12409 sal_free(hwport); 12410 return BCM_E_MEMORY; 12411 } 12412 } 12413 sal_memset(hwft->psc, 0, sizeof(uint8) * tg_size); 12414 12415 if (hwft->flags == NULL) { 12416 /* If flags are not recovered from scache, allocate flags and 12417 * set them to zero. 12418 */ 12419 hwft->flags = sal_alloc(sizeof(uint32) * tg_size, 12420 "hw_tinfo_flags"); 12421 if (hwft->flags == NULL) { 12422 sal_free(hwft->modport); 12423 hwft->modport = NULL; 12424 sal_free(hwft->psc); 12425 hwft->psc = NULL; 12426 sal_free(hwport); 12427 return BCM_E_MEMORY; 12428 } 12429 sal_memset(hwft->flags, 0, sizeof(uint32) * tg_size); 12430 } 12431 12432 for (i = 0; i < tg_size; i++) { 12433 hwft->modport[i] = hwport[i]; 12434 rv = _bcm_trident_trunk_hwfailover_hg_read(unit, hwport[i], 12435 0, &hwf_rtag, NULL, NULL, NULL); 12436 if (BCM_FAILURE(rv)) { 12437 sal_free(hwport); 12438 return rv; 12439 } 12440 if (hwf_rtag != 0) { 12441 rv = _bcm_trident_trunk_rtag_to_psc(unit, hwf_rtag, 12442 &hwf_psc); 12443 if (BCM_FAILURE(rv)) { 12444 sal_free(hwport); 12445 return rv; 12446 } 12447 hwft->psc[i] = hwf_psc; 12448 } else { 12449 /* Use trunk group value as the default */ 12450 hwft->psc[i] = trunk_info->psc; 12451 } 12452 } 12453 } 12454 12455 sal_free(hwport); 12456 } 12457 12458 if (soc_feature(unit, soc_feature_hg_dlb) && 12459 !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 12460 #ifdef BCM_TRIUMPH3_SUPPORT 12461 if (soc_feature(unit, soc_feature_hg_dlb_member_id)) { 12462 BCM_IF_ERROR_RETURN(_bcm_tr3_hg_dlb_member_recover(unit)); 12463 } 12464 #endif /* BCM_TRIUMPH3_SUPPORT */ 12465 12466 BCM_IF_ERROR_RETURN 12467 (_bcm_trident_hg_dlb_quality_parameters_recover(unit)); 12468 } 12469 12470 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 12471 if (soc_feature(unit, soc_feature_hg_dlb) && 12472 soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 12473 BCM_IF_ERROR_RETURN(bcm_th2_hgt_lag_dlb_quality_parameters_recover(unit)); 12474 } 12475 #endif /* BCM_TOMAHAWK2_SUPPORT */ 12476 12477 return rv; 12478 } 12479 12480 #endif /* BCM_WARM_BOOT_SUPPORT */ 12481 12482 #ifndef BCM_SW_STATE_DUMP_DISABLE 12483 12484 /* 12485 * Function: 12486 * _bcm_trident_hg_dlb_sw_dump 12487 * Purpose: 12488 * Displays Higig DLB information maintained by software. 12489 * Parameters: 12490 * unit - Device unit number 12491 * Returns: 12492 * None 12493 */ 12494 STATIC void 12495 _bcm_trident_hg_dlb_sw_dump(int unit) 12496 { 12497 int i; 12498 soc_mem_t flowset_mem, quality_mapping_mem; 12499 int num_entries_per_profile; 12500 int num_profiles; 12501 int rv; 12502 int ref_count; 12503 12504 LOG_CLI((BSL_META_U(unit, 12505 "Higig DLB Info -\n"))); 12506 12507 /* Print Higig DLB group usage */ 12508 LOG_CLI((BSL_META_U(unit, 12509 " Higig DLB Groups Used:"))); 12510 for (i = 0; i < soc_mem_index_count(unit, DLB_HGT_GROUP_CONTROLm); i++) { 12511 if (_BCM_HG_DLB_ID_USED_GET(unit, i)) { 12512 LOG_CLI((BSL_META_U(unit, 12513 " %d"), i)); 12514 } 12515 } 12516 LOG_CLI((BSL_META_U(unit, 12517 "\n"))); 12518 12519 /* Print Higig DLB flowset table usage */ 12520 LOG_CLI((BSL_META_U(unit, 12521 " Higig DLB Flowset Table Blocks Used:"))); 12522 flowset_mem = soc_mem_is_valid(unit, DLB_HGT_FLOWSETm) ? 12523 DLB_HGT_FLOWSETm : DLB_HGT_FLOWSET_PORTm; 12524 for (i = 0; i < (soc_mem_index_count(unit, flowset_mem) >> 9); i++) { 12525 if (_BCM_HG_DLB_FLOWSET_BLOCK_USED_GET(unit, i)) { 12526 LOG_CLI((BSL_META_U(unit, 12527 " %d"), i)); 12528 } 12529 } 12530 LOG_CLI((BSL_META_U(unit, 12531 "\n"))); 12532 12533 #ifdef BCM_TRIUMPH3_SUPPORT 12534 if (soc_feature(unit, soc_feature_hg_dlb_member_id)) { 12535 /* Print Higig DLB member ID usage */ 12536 LOG_CLI((BSL_META_U(unit, 12537 " Higig DLB Member IDs Used:"))); 12538 for (i = 0; i < soc_mem_index_count(unit, DLB_HGT_MEMBER_ATTRIBUTEm); i++) { 12539 if (_BCM_HG_DLB_MEMBER_ID_USED_GET(unit, i)) { 12540 LOG_CLI((BSL_META_U(unit, 12541 " %d"), i)); 12542 } 12543 } 12544 LOG_CLI((BSL_META_U(unit, 12545 "\n"))); 12546 } 12547 #endif /* BCM_TRIUMPH3_SUPPORT */ 12548 12549 /* Print sample rate and threshold parameters */ 12550 LOG_CLI((BSL_META_U(unit, 12551 " Sample rate: %d per second\n"), 12552 HG_DLB_INFO(unit)->hg_dlb_sample_rate)); 12553 LOG_CLI((BSL_META_U(unit, 12554 " Tx load min threshold: %d mbps\n"), 12555 HG_DLB_INFO(unit)->hg_dlb_tx_load_min_th)); 12556 LOG_CLI((BSL_META_U(unit, 12557 " Tx load max threshold: %d mbps\n"), 12558 HG_DLB_INFO(unit)->hg_dlb_tx_load_max_th)); 12559 LOG_CLI((BSL_META_U(unit, 12560 " Queue size min threshold: %d cells\n"), 12561 HG_DLB_INFO(unit)->hg_dlb_qsize_min_th)); 12562 LOG_CLI((BSL_META_U(unit, 12563 " Queue size max threshold: %d cells\n"), 12564 HG_DLB_INFO(unit)->hg_dlb_qsize_max_th)); 12565 12566 /* Print quality mapping profiles */ 12567 LOG_CLI((BSL_META_U(unit, 12568 " Quality mapping profiles:\n"))); 12569 num_entries_per_profile = 64; 12570 quality_mapping_mem = soc_mem_is_valid(unit, DLB_HGT_QUALITY_MAPPINGm) ? 12571 DLB_HGT_QUALITY_MAPPINGm : DLB_HGT_PORT_QUALITY_MAPPINGm; 12572 num_profiles = soc_mem_index_count(unit, quality_mapping_mem) / 12573 num_entries_per_profile; 12574 for (i = 0; i < num_profiles; i++) { 12575 LOG_CLI((BSL_META_U(unit, 12576 " Profile %d: load weight %d percent, "), 12577 i, HG_DLB_INFO(unit)->hg_dlb_load_weight[i])); 12578 rv = soc_profile_mem_ref_count_get(unit, 12579 HG_DLB_INFO(unit)->hg_dlb_quality_map_profile, 12580 i * num_entries_per_profile, &ref_count); 12581 if (SOC_FAILURE(rv)) { 12582 LOG_CLI((BSL_META_U(unit, 12583 "\n"))); 12584 continue; 12585 } 12586 LOG_CLI((BSL_META_U(unit, 12587 "ref count %d\n"), ref_count)); 12588 } 12589 12590 return; 12591 } 12592 12593 /* 12594 * Function: 12595 * _bcm_trident_trunk_sw_dump 12596 * Purpose: 12597 * Displays trunk information maintained by software. 12598 * Parameters: 12599 * unit - Device unit number 12600 * Returns: 12601 * None 12602 */ 12603 void 12604 _bcm_trident_trunk_sw_dump(int unit) 12605 { 12606 int rv, i, j, tid_ix, tid_min, tid_max; 12607 bcm_trunk_chip_info_t chip_info; 12608 _trident_trunk_swfail_t *swf; 12609 _trident_tinfo_t *swft; 12610 int num_profiles; 12611 int ref_count; 12612 #if (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS) 12613 int soc_max_num_ports = SOC_MAX_NUM_PP_PORTS; 12614 #else 12615 int soc_max_num_ports = SOC_MAX_NUM_PORTS; 12616 #endif 12617 12618 rv = bcm_esw_trunk_chip_info_get(unit, &chip_info); 12619 if (BCM_FAILURE(rv)) { 12620 LOG_CLI((BSL_META_U(unit, 12621 "Unable to retrieve unit %d chip info %d\n"), 12622 unit, rv)); 12623 return; 12624 } 12625 12626 if (chip_info.trunk_id_min < 0) { 12627 if (chip_info.trunk_fabric_id_min < 0) { 12628 /* No trunks! Abort */ 12629 LOG_CLI((BSL_META_U(unit, 12630 "No trunk groups on unit %d\n"), unit)); 12631 return; 12632 } else { 12633 tid_min = chip_info.trunk_fabric_id_min; 12634 tid_max = chip_info.trunk_fabric_id_max; 12635 } 12636 } else { 12637 tid_min = chip_info.trunk_id_min; 12638 if (chip_info.trunk_fabric_id_min < 0) { 12639 tid_max = chip_info.trunk_id_max; 12640 } else { 12641 tid_max = chip_info.trunk_fabric_id_max; 12642 } 12643 } 12644 12645 /* Print software trunk failover states */ 12646 12647 swf = _trident_trunk_swfail[unit]; 12648 if (NULL != swf) { 12649 LOG_CLI((BSL_META_U(unit, 12650 "Software failover parameters:\n"))); 12651 LOG_CLI((BSL_META_U(unit, 12652 " Local modid: %d\n"), swf->mymodid)); 12653 LOG_CLI((BSL_META_U(unit, 12654 " Port: Trunk\n"))); 12655 for (j = 0; j < soc_max_num_ports; j++) { 12656 if (0 != swf->trunk[j]) { 12657 LOG_CLI((BSL_META_U(unit, 12658 " %d: %d\n"), 12659 j, swf->trunk[j]-1)); 12660 } 12661 } 12662 LOG_CLI((BSL_META_U(unit, 12663 " Trunk SW failover parameters\n"))); 12664 for (i = tid_min; i <= tid_max; i++) { 12665 if (i >= chip_info.trunk_fabric_id_min) { 12666 tid_ix = (i - chip_info.trunk_fabric_id_min) + 12667 chip_info.trunk_group_count; 12668 } else { 12669 tid_ix = i; 12670 } 12671 swft = &swf->tinfo[tid_ix]; 12672 if (0 != swft->num_ports) { 12673 LOG_CLI((BSL_META_U(unit, 12674 " Trunk %d, index %d\n"), i, tid_ix)); 12675 LOG_CLI((BSL_META_U(unit, 12676 " Flags value 0x%x\n"), swft->flags)); 12677 LOG_CLI((BSL_META_U(unit, 12678 " RTAG value %d\n"), swft->rtag)); 12679 LOG_CLI((BSL_META_U(unit, 12680 " Port count %d\n"), swft->num_ports)); 12681 for (j = 0; j < swft->num_ports; j++) { 12682 LOG_CLI((BSL_META_U(unit, 12683 " ModPort 0x%04x\n"), swft->modport[j])); 12684 } 12685 } 12686 } 12687 } else { 12688 LOG_CLI((BSL_META_U(unit, 12689 "SW trunk failover not initialized on unit %d\n"), 12690 unit)); 12691 } 12692 12693 /* Print hardware trunk failover states */ 12694 if (soc_feature(unit, soc_feature_port_lag_failover) || 12695 soc_feature(unit, soc_feature_hg_trunk_failover)) { 12696 _trident_hw_tinfo_t *hwft; 12697 12698 if (NULL == _trident_trunk_hwfail[unit]) { 12699 LOG_CLI((BSL_META_U(unit, 12700 "HW trunk failover not initialized on unit %d\n"), 12701 unit)); 12702 return; 12703 } 12704 LOG_CLI((BSL_META_U(unit, 12705 "Trunk HW failover parameters\n"))); 12706 for (i = tid_min; i <= tid_max; i++) { 12707 if (i >= chip_info.trunk_fabric_id_min) { 12708 tid_ix = (i - chip_info.trunk_fabric_id_min) + 12709 chip_info.trunk_group_count; 12710 } else { 12711 tid_ix = i; 12712 } 12713 hwft = &(_trident_trunk_hwfail[unit]->hw_tinfo[tid_ix]); 12714 if (0 != hwft->num_ports) { 12715 LOG_CLI((BSL_META_U(unit, 12716 " Trunk %d, index %d\n"), i, tid_ix)); 12717 LOG_CLI((BSL_META_U(unit, 12718 " Port count %d\n"), hwft->num_ports)); 12719 for (j = 0; j < hwft->num_ports; j++) { 12720 LOG_CLI((BSL_META_U(unit, 12721 " PSC value %d\n"), hwft->psc[j])); 12722 LOG_CLI((BSL_META_U(unit, 12723 " Flags 0x%08x\n"), hwft->flags[j])); 12724 LOG_CLI((BSL_META_U(unit, 12725 " ModPort 0x%04x\n"), hwft->modport[j])); 12726 } 12727 } 12728 } 12729 } 12730 12731 /* Print Higig trunk override profile info */ 12732 LOG_CLI((BSL_META_U(unit, 12733 "Higig trunk override profile info\n"))); 12734 num_profiles = soc_mem_index_count(unit, ING_HIGIG_TRUNK_OVERRIDE_PROFILEm); 12735 for (i = 0; i < num_profiles; i++) { 12736 rv = soc_profile_mem_ref_count_get(unit, 12737 _trident_hg_trunk_override_profile[unit], 12738 i, &ref_count); 12739 if (SOC_FAILURE(rv)) { 12740 continue; 12741 } 12742 if (ref_count > 0) { 12743 LOG_CLI((BSL_META_U(unit, 12744 " Higig trunk override profile %d ref count %d\n"), 12745 i, ref_count)); 12746 } 12747 } 12748 12749 /* Print trunk membership info */ 12750 if (NULL != _trident_trunk_member_info[unit]) { 12751 LOG_CLI((BSL_META_U(unit, 12752 "Trunk membership info:\n"))); 12753 for (i = tid_min; i <= tid_max; i++) { 12754 if (i >= chip_info.trunk_fabric_id_min) { 12755 tid_ix = (i - chip_info.trunk_fabric_id_min) + 12756 chip_info.trunk_group_count; 12757 } else { 12758 tid_ix = i; 12759 } 12760 12761 if (0 != MEMBER_INFO(unit, tid_ix).num_ports) { 12762 LOG_CLI((BSL_META_U(unit, 12763 " Trunk %d, index %d\n"), i, tid_ix)); 12764 LOG_CLI((BSL_META_U(unit, 12765 " Port count %d\n"), 12766 MEMBER_INFO(unit, tid_ix).num_ports)); 12767 for (j = 0; j < MEMBER_INFO(unit, tid_ix).num_ports; j++) { 12768 LOG_CLI((BSL_META_U(unit, 12769 " ModPort 0x%04x\n"), 12770 MEMBER_INFO(unit, tid_ix).modport[j])); 12771 LOG_CLI((BSL_META_U(unit, 12772 " Member flags 0x%x\n"), 12773 MEMBER_INFO(unit, tid_ix).member_flags[j])); 12774 } 12775 } 12776 } 12777 } else { 12778 LOG_CLI((BSL_META_U(unit, 12779 "Trunk membership info not initialized on unit %d\n"), 12780 unit)); 12781 } 12782 12783 if (soc_feature(unit, soc_feature_hg_dlb) && 12784 !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 12785 _bcm_trident_hg_dlb_sw_dump(unit); 12786 } 12787 #ifdef BCM_TRIUMPH3_SUPPORT 12788 if (soc_feature(unit, soc_feature_lag_dlb) && 12789 !soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 12790 bcm_tr3_lag_dlb_sw_dump(unit); 12791 } 12792 #endif /* BCM_TRIUMPH3_SUPPORT */ 12793 12794 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 12795 if (soc_feature(unit, soc_feature_hgt_lag_dlb_optimized)) { 12796 bcm_th2_hgt_lag_dlb_sw_dump(unit); 12797 } 12798 #endif /* BCM_TOMAHAWK2_SUPPORT */ 12799 12800 #ifdef BCM_TRIDENT2_SUPPORT 12801 if (soc_feature(unit, soc_feature_hg_resilient_hash)) { 12802 bcm_td2_hg_rh_sw_dump(unit); 12803 } 12804 if (soc_feature(unit, soc_feature_lag_resilient_hash)) { 12805 bcm_td2_lag_rh_sw_dump(unit); 12806 } 12807 #endif /* BCM_TRIDENT2_SUPPORT */ 12808 12809 return; 12810 } 12811 #endif /* BCM_SW_STATE_DUMP_DISABLE */ 12812 12813 #else /* BCM_TRIDENT_SUPPORT */ 12814 12815 int _trident_trunk_not_empty; 12816 12817 #endif /* BCM_TRIDENT_SUPPORT */