trunk.c (120860B)
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 * Triumph3 LAG dynamic load balancing 8 */ 9 10 #include <soc/defs.h> 11 #include <sal/core/libc.h> 12 #include <shared/bsl.h> 13 #ifdef BCM_TRIUMPH3_SUPPORT 14 15 #include <soc/mem.h> 16 #include <soc/profile_mem.h> 17 18 #include <bcm/error.h> 19 20 #include <bcm_int/esw/mbcm.h> 21 #include <bcm_int/esw/trunk.h> 22 #include <bcm_int/esw_dispatch.h> 23 24 /* ------------------------------------------------- */ 25 /* Bookkeeping info for LAG dynamic load balancing */ 26 /* ------------------------------------------------- */ 27 28 typedef struct _tr3_lag_dlb_bookkeeping_s { 29 SHR_BITDCL *lag_dlb_id_used_bitmap; 30 SHR_BITDCL *lag_dlb_flowset_block_bitmap; /* Each block corresponds to 31 512 entries */ 32 SHR_BITDCL *lag_dlb_member_id_used_bitmap; 33 int lag_dlb_sample_rate; 34 int lag_dlb_tx_load_min_th; 35 int lag_dlb_tx_load_max_th; 36 int lag_dlb_qsize_min_th; 37 int lag_dlb_qsize_max_th; 38 int lag_dlb_exp_load_min_th; 39 int lag_dlb_exp_load_max_th; 40 int lag_dlb_imbalance_min_th; 41 int lag_dlb_imbalance_max_th; 42 uint8 *lag_dlb_load_weight; 43 soc_profile_mem_t *lag_dlb_quality_map_profile; 44 #ifdef BCM_WARM_BOOT_SUPPORT 45 uint8 recovered_from_scache; /* Indicates if the following members of this 46 structure have been recovered from scached: 47 lag_dlb_sample_rate, 48 lag_dlb_tx_load_min_th, 49 lag_dlb_tx_load_max_th, 50 lag_dlb_tx_qsize_min_th, 51 lag_dlb_tx_qsize_max_th, 52 lag_dlb_exp_load_min_th, 53 lag_dlb_exp_load_max_th, 54 lag_dlb_imbalance_min_th, 55 lag_dlb_imbalance_max_th, 56 lag_dlb_load_weight */ 57 #endif /* BCM_WARM_BOOT_SUPPORT */ 58 } _tr3_lag_dlb_bookkeeping_t; 59 60 static _tr3_lag_dlb_bookkeeping_t *_tr3_lag_dlb_bk[BCM_MAX_NUM_UNITS]; 61 62 #define LAG_DLB_INFO(_unit_) (_tr3_lag_dlb_bk[_unit_]) 63 64 #define _BCM_LAG_DLB_ID_USED_GET(_u_, _idx_) \ 65 SHR_BITGET(LAG_DLB_INFO(_u_)->lag_dlb_id_used_bitmap, _idx_) 66 #define _BCM_LAG_DLB_ID_USED_SET(_u_, _idx_) \ 67 SHR_BITSET(LAG_DLB_INFO(_u_)->lag_dlb_id_used_bitmap, _idx_) 68 #define _BCM_LAG_DLB_ID_USED_CLR(_u_, _idx_) \ 69 SHR_BITCLR(LAG_DLB_INFO(_u_)->lag_dlb_id_used_bitmap, _idx_) 70 71 #define _BCM_LAG_DLB_FLOWSET_BLOCK_USED_GET(_u_, _idx_) \ 72 SHR_BITGET(LAG_DLB_INFO(_u_)->lag_dlb_flowset_block_bitmap, _idx_) 73 #define _BCM_LAG_DLB_FLOWSET_BLOCK_USED_SET(_u_, _idx_) \ 74 SHR_BITSET(LAG_DLB_INFO(_u_)->lag_dlb_flowset_block_bitmap, _idx_) 75 #define _BCM_LAG_DLB_FLOWSET_BLOCK_USED_CLR(_u_, _idx_) \ 76 SHR_BITCLR(LAG_DLB_INFO(_u_)->lag_dlb_flowset_block_bitmap, _idx_) 77 #define _BCM_LAG_DLB_FLOWSET_BLOCK_USED_SET_RANGE(_u_, _idx_, _count_) \ 78 SHR_BITSET_RANGE(LAG_DLB_INFO(_u_)->lag_dlb_flowset_block_bitmap, _idx_, _count_) 79 #define _BCM_LAG_DLB_FLOWSET_BLOCK_USED_CLR_RANGE(_u_, _idx_, _count_) \ 80 SHR_BITCLR_RANGE(LAG_DLB_INFO(_u_)->lag_dlb_flowset_block_bitmap, _idx_, _count_) 81 #define _BCM_LAG_DLB_FLOWSET_BLOCK_TEST_RANGE(_u_, _idx_, _count_, _result_) \ 82 SHR_BITTEST_RANGE(LAG_DLB_INFO(_u_)->lag_dlb_flowset_block_bitmap, _idx_, _count_, _result_) 83 84 #define _BCM_LAG_DLB_MEMBER_ID_USED_GET(_u_, _idx_) \ 85 SHR_BITGET(LAG_DLB_INFO(_u_)->lag_dlb_member_id_used_bitmap, _idx_) 86 #define _BCM_LAG_DLB_MEMBER_ID_USED_SET(_u_, _idx_) \ 87 SHR_BITSET(LAG_DLB_INFO(_u_)->lag_dlb_member_id_used_bitmap, _idx_) 88 #define _BCM_LAG_DLB_MEMBER_ID_USED_CLR(_u_, _idx_) \ 89 SHR_BITCLR(LAG_DLB_INFO(_u_)->lag_dlb_member_id_used_bitmap, _idx_) 90 91 /* Function prototypes */ 92 93 STATIC int _bcm_tr3_lag_dlb_quality_assign(int unit, int tx_load_percent, 94 uint32 *entry_arr); 95 STATIC int _bcm_tr3_lag_dlb_sample_rate_pla_thresholds_set(int unit, 96 int sample_rate, int min_th, int max_th); 97 STATIC int _bcm_tr3_lag_dlb_sample_rate_vla_thresholds_set(int unit, 98 int sample_rate, int exp_load_min_th, int exp_load_max_th, 99 int imbalance_min_th, int imbalance_max_th); 100 STATIC int _bcm_tr3_lag_dlb_qsize_thresholds_set(int unit, int min_th, 101 int max_th); 102 103 104 /* 105 * Function: 106 * _bcm_tr3_lag_dlb_quality_map_profile_init 107 * Purpose: 108 * Initialize LAG DLB quality mapping profile. 109 * Parameters: 110 * unit - (IN)SOC unit number. 111 * Returns: 112 * BCM_X_XXX 113 */ 114 STATIC int 115 _bcm_tr3_lag_dlb_quality_map_profile_init(int unit) 116 { 117 soc_profile_mem_t *profile; 118 soc_mem_t mem; 119 int entry_words; 120 int entries_per_profile; 121 int tx_load_percent; 122 int alloc_size; 123 uint32 *entry_arr; 124 int rv = BCM_E_NONE; 125 void *entries; 126 uint32 base_index; 127 int i; 128 int member_id; 129 dlb_lag_quality_control_entry_t quality_control_entry; 130 131 if (NULL == _tr3_lag_dlb_bk[unit]->lag_dlb_quality_map_profile) { 132 _tr3_lag_dlb_bk[unit]->lag_dlb_quality_map_profile = 133 sal_alloc(sizeof(soc_profile_mem_t), 134 "LAG DLB Quality Map Profile Mem"); 135 if (NULL == _tr3_lag_dlb_bk[unit]->lag_dlb_quality_map_profile) { 136 return BCM_E_MEMORY; 137 } 138 } else { 139 soc_profile_mem_destroy(unit, 140 _tr3_lag_dlb_bk[unit]->lag_dlb_quality_map_profile); 141 } 142 profile = _tr3_lag_dlb_bk[unit]->lag_dlb_quality_map_profile; 143 soc_profile_mem_t_init(profile); 144 145 mem = DLB_LAG_QUALITY_MAPPINGm; 146 entry_words = sizeof(dlb_lag_quality_mapping_entry_t) / sizeof(uint32); 147 SOC_IF_ERROR_RETURN 148 (soc_profile_mem_create(unit, &mem, &entry_words, 1, profile)); 149 150 entries_per_profile = 64; 151 if (!SOC_WARM_BOOT(unit)) { 152 alloc_size = entries_per_profile * entry_words * sizeof(uint32); 153 entry_arr = sal_alloc(alloc_size, "LAG DLB Quality Map entries"); 154 if (entry_arr == NULL) { 155 return BCM_E_MEMORY; 156 } 157 sal_memset(entry_arr, 0, alloc_size); 158 159 /* Assign quality in the entry array, with 100% weight for port load, 160 * 0% for queue size. 161 */ 162 tx_load_percent = 100; 163 rv = _bcm_tr3_lag_dlb_quality_assign(unit, tx_load_percent, 164 entry_arr); 165 if (BCM_FAILURE(rv)) { 166 sal_free(entry_arr); 167 return rv; 168 } 169 170 entries = entry_arr; 171 rv = soc_profile_mem_add(unit, profile, &entries, entries_per_profile, 172 &base_index); 173 sal_free(entry_arr); 174 if (SOC_FAILURE(rv)) { 175 return rv; 176 } 177 178 for (member_id = 0; 179 member_id < soc_mem_index_count(unit, 180 DLB_LAG_QUALITY_CONTROLm); 181 member_id++) { 182 BCM_IF_ERROR_RETURN 183 (READ_DLB_LAG_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY, 184 member_id, 185 &quality_control_entry)); 186 soc_DLB_LAG_QUALITY_CONTROLm_field32_set(unit, 187 &quality_control_entry, PROFILE_PTRf, 188 base_index / entries_per_profile); 189 BCM_IF_ERROR_RETURN 190 (WRITE_DLB_LAG_QUALITY_CONTROLm(unit, MEM_BLOCK_ALL, 191 member_id, 192 &quality_control_entry)); 193 } 194 195 for (i = 0; i < entries_per_profile; i++) { 196 SOC_PROFILE_MEM_REFERENCE(unit, profile, base_index + i, 197 member_id - 1); 198 } 199 200 LAG_DLB_INFO(unit)-> 201 lag_dlb_load_weight[base_index/entries_per_profile] = 202 tx_load_percent; 203 204 } else { /* Warm boot, recover reference counts and entries_per_set */ 205 206 for (member_id = 0; 207 member_id < soc_mem_index_count(unit, 208 DLB_LAG_QUALITY_CONTROLm); 209 member_id++) { 210 BCM_IF_ERROR_RETURN 211 (READ_DLB_LAG_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY, 212 member_id, 213 &quality_control_entry)); 214 base_index = soc_DLB_LAG_QUALITY_CONTROLm_field32_get(unit, 215 &quality_control_entry, PROFILE_PTRf); 216 base_index *= entries_per_profile; 217 for (i = 0; i < entries_per_profile; i++) { 218 SOC_PROFILE_MEM_REFERENCE(unit, profile, base_index + i, 1); 219 SOC_PROFILE_MEM_ENTRIES_PER_SET(unit, profile, 220 base_index + i, entries_per_profile); 221 } 222 } 223 } 224 225 return BCM_E_NONE; 226 } 227 228 /* 229 * Function: 230 * bcm_tr3_lag_dlb_deinit 231 * Purpose: 232 * Deallocate _tr3_lag_dlb_bk 233 * Parameters: 234 * unit - (IN)SOC unit number. 235 * Returns: 236 * None 237 */ 238 void 239 bcm_tr3_lag_dlb_deinit(int unit) 240 { 241 int rv; 242 uint32 rsel2_hw_control_reg; 243 244 if (_tr3_lag_dlb_bk[unit]) { 245 if (_tr3_lag_dlb_bk[unit]->lag_dlb_id_used_bitmap) { 246 sal_free(_tr3_lag_dlb_bk[unit]->lag_dlb_id_used_bitmap); 247 _tr3_lag_dlb_bk[unit]->lag_dlb_id_used_bitmap = NULL; 248 } 249 if (_tr3_lag_dlb_bk[unit]->lag_dlb_flowset_block_bitmap) { 250 sal_free(_tr3_lag_dlb_bk[unit]->lag_dlb_flowset_block_bitmap); 251 _tr3_lag_dlb_bk[unit]->lag_dlb_flowset_block_bitmap = NULL; 252 } 253 if (_tr3_lag_dlb_bk[unit]->lag_dlb_member_id_used_bitmap) { 254 sal_free(_tr3_lag_dlb_bk[unit]->lag_dlb_member_id_used_bitmap); 255 _tr3_lag_dlb_bk[unit]->lag_dlb_member_id_used_bitmap = NULL; 256 } 257 if (_tr3_lag_dlb_bk[unit]->lag_dlb_load_weight) { 258 sal_free(_tr3_lag_dlb_bk[unit]->lag_dlb_load_weight); 259 _tr3_lag_dlb_bk[unit]->lag_dlb_load_weight = NULL; 260 } 261 if (_tr3_lag_dlb_bk[unit]->lag_dlb_quality_map_profile) { 262 soc_profile_mem_destroy(unit, 263 _tr3_lag_dlb_bk[unit]->lag_dlb_quality_map_profile); 264 sal_free(_tr3_lag_dlb_bk[unit]->lag_dlb_quality_map_profile); 265 _tr3_lag_dlb_bk[unit]->lag_dlb_quality_map_profile = NULL; 266 } 267 268 sal_free(_tr3_lag_dlb_bk[unit]); 269 _tr3_lag_dlb_bk[unit] = NULL; 270 } 271 272 rv = READ_RSEL2_HW_CONTROLr(unit, &rsel2_hw_control_reg); 273 if (SOC_SUCCESS(rv)) { 274 soc_reg_field_set(unit, RSEL2_HW_CONTROLr, &rsel2_hw_control_reg, 275 ENABLE_LAG_DLBf, 0); 276 (void)WRITE_RSEL2_HW_CONTROLr(unit, rsel2_hw_control_reg); 277 } 278 } 279 280 /* 281 * Function: 282 * bcm_tr3_lag_dlb_init 283 * Purpose: 284 * Allocate and initialize _tr3_lag_dlb_bk 285 * Parameters: 286 * unit - (IN)SOC unit number. 287 * Returns: 288 * BCM_X_XXX 289 */ 290 int 291 bcm_tr3_lag_dlb_init(int unit) 292 { 293 int rv = BCM_E_NONE; 294 int num_lag_dlb_id; 295 int lag_flowset_tbl_size; 296 int total_num_blocks; 297 int num_lag_dlb_member_id; 298 int num_quality_map_profiles; 299 int member_id; 300 dlb_lag_quality_control_entry_t quality_control_entry; 301 uint32 rsel2_hw_control_reg; 302 uint32 measure_control_reg; 303 int sample_rate; 304 305 if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit))) { 306 return BCM_E_NONE; 307 } 308 309 if (_tr3_lag_dlb_bk[unit] == NULL) { 310 _tr3_lag_dlb_bk[unit] = sal_alloc( 311 sizeof(_tr3_lag_dlb_bookkeeping_t), "_tr3_lag_dlb_bk"); 312 if (_tr3_lag_dlb_bk[unit] == NULL) { 313 return BCM_E_MEMORY; 314 } 315 } 316 sal_memset(_tr3_lag_dlb_bk[unit], 0, sizeof(_tr3_lag_dlb_bookkeeping_t)); 317 318 num_lag_dlb_id = soc_mem_index_count(unit, DLB_LAG_GROUP_CONTROLm); 319 if (_tr3_lag_dlb_bk[unit]->lag_dlb_id_used_bitmap == NULL) { 320 _tr3_lag_dlb_bk[unit]->lag_dlb_id_used_bitmap = 321 sal_alloc(SHR_BITALLOCSIZE(num_lag_dlb_id), 322 "lag_dlb_id_used_bitmap"); 323 if (_tr3_lag_dlb_bk[unit]->lag_dlb_id_used_bitmap == NULL) { 324 bcm_tr3_lag_dlb_deinit(unit); 325 return BCM_E_MEMORY; 326 } 327 } 328 sal_memset(_tr3_lag_dlb_bk[unit]->lag_dlb_id_used_bitmap, 0, 329 SHR_BITALLOCSIZE(num_lag_dlb_id)); 330 331 lag_flowset_tbl_size = soc_mem_index_count(unit, DLB_LAG_FLOWSETm); 332 /* Each bit in lag_dlb_flowset_block_bitmap corresponds to a block of 512 333 * flow set table entries. 334 */ 335 total_num_blocks = lag_flowset_tbl_size / 512; 336 if (_tr3_lag_dlb_bk[unit]->lag_dlb_flowset_block_bitmap == NULL) { 337 _tr3_lag_dlb_bk[unit]->lag_dlb_flowset_block_bitmap = 338 sal_alloc(SHR_BITALLOCSIZE(total_num_blocks), 339 "lag_dlb_flowset_block_bitmap"); 340 if (_tr3_lag_dlb_bk[unit]->lag_dlb_flowset_block_bitmap == NULL) { 341 bcm_tr3_lag_dlb_deinit(unit); 342 return BCM_E_MEMORY; 343 } 344 } 345 sal_memset(_tr3_lag_dlb_bk[unit]->lag_dlb_flowset_block_bitmap, 0, 346 SHR_BITALLOCSIZE(total_num_blocks)); 347 348 num_lag_dlb_member_id = soc_mem_index_count(unit, 349 DLB_LAG_MEMBER_ATTRIBUTEm); 350 if (_tr3_lag_dlb_bk[unit]->lag_dlb_member_id_used_bitmap == NULL) { 351 _tr3_lag_dlb_bk[unit]->lag_dlb_member_id_used_bitmap = 352 sal_alloc(SHR_BITALLOCSIZE(num_lag_dlb_member_id), 353 "lag_dlb_member_id_used_bitmap"); 354 if (_tr3_lag_dlb_bk[unit]->lag_dlb_member_id_used_bitmap == NULL) { 355 bcm_tr3_lag_dlb_deinit(unit); 356 return BCM_E_MEMORY; 357 } 358 } 359 sal_memset(_tr3_lag_dlb_bk[unit]->lag_dlb_member_id_used_bitmap, 0, 360 SHR_BITALLOCSIZE(num_lag_dlb_member_id)); 361 362 num_quality_map_profiles = 1 << soc_mem_field_length(unit, 363 DLB_LAG_QUALITY_CONTROLm, PROFILE_PTRf); 364 if (_tr3_lag_dlb_bk[unit]->lag_dlb_load_weight == NULL) { 365 _tr3_lag_dlb_bk[unit]->lag_dlb_load_weight = 366 sal_alloc(num_quality_map_profiles * sizeof(uint8), 367 "lag_dlb_load_weight"); 368 if (_tr3_lag_dlb_bk[unit]->lag_dlb_load_weight == NULL) { 369 bcm_tr3_lag_dlb_deinit(unit); 370 return BCM_E_MEMORY; 371 } 372 } 373 sal_memset(_tr3_lag_dlb_bk[unit]->lag_dlb_load_weight, 0, 374 num_quality_map_profiles * sizeof(uint8)); 375 376 /* Initialize port quality mapping profile */ 377 rv = _bcm_tr3_lag_dlb_quality_map_profile_init(unit); 378 if (BCM_FAILURE(rv)) { 379 bcm_tr3_lag_dlb_deinit(unit); 380 return rv; 381 } 382 383 if (!SOC_WARM_BOOT(unit)) { 384 385 /* Configure accounting mode to physical link accounting */ 386 rv = bcm_tr3_lag_dlb_config_set(unit, 387 bcmSwitchTrunkDynamicAccountingSelect, 0); 388 if (BCM_FAILURE(rv)) { 389 bcm_tr3_lag_dlb_deinit(unit); 390 return rv; 391 } 392 393 /* Set DLB sampling period and load thresholds */ 394 sample_rate = 1000; 395 rv = _bcm_tr3_lag_dlb_sample_rate_pla_thresholds_set(unit, sample_rate, 396 125, 875); 397 if (BCM_FAILURE(rv)) { 398 bcm_tr3_lag_dlb_deinit(unit); 399 return rv; 400 } 401 rv = _bcm_tr3_lag_dlb_sample_rate_vla_thresholds_set(unit, sample_rate, 402 125, 875, -75, 75); 403 if (BCM_FAILURE(rv)) { 404 bcm_tr3_lag_dlb_deinit(unit); 405 return rv; 406 } 407 408 /* Configure LAG DLB load EWMA weight */ 409 rv = bcm_tr3_lag_dlb_config_set(unit, 410 bcmSwitchTrunkDynamicEgressBytesExponent, 0); 411 if (BCM_FAILURE(rv)) { 412 bcm_tr3_lag_dlb_deinit(unit); 413 return rv; 414 } 415 416 /* Configure LAG DLB queue size EWMA weight */ 417 rv = bcm_tr3_lag_dlb_config_set(unit, 418 bcmSwitchTrunkDynamicQueuedBytesExponent, 0); 419 if (BCM_FAILURE(rv)) { 420 bcm_tr3_lag_dlb_deinit(unit); 421 return rv; 422 } 423 424 /* Configure LAG DLB load cap control */ 425 rv = bcm_tr3_lag_dlb_config_set(unit, 426 bcmSwitchTrunkDynamicEgressBytesDecreaseReset, 0); 427 if (BCM_FAILURE(rv)) { 428 bcm_tr3_lag_dlb_deinit(unit); 429 return rv; 430 } 431 432 /* Configure LAG DLB queue size cap control */ 433 rv = bcm_tr3_lag_dlb_config_set(unit, 434 bcmSwitchTrunkDynamicQueuedBytesDecreaseReset, 0); 435 if (BCM_FAILURE(rv)) { 436 bcm_tr3_lag_dlb_deinit(unit); 437 return rv; 438 } 439 440 /* Configure LAG DLB queue size thresholds */ 441 rv = _bcm_tr3_lag_dlb_qsize_thresholds_set(unit, 0, 0); 442 if (BCM_FAILURE(rv)) { 443 bcm_tr3_lag_dlb_deinit(unit); 444 return rv; 445 } 446 447 /* Disable link status override by software */ 448 rv = soc_mem_clear(unit, DLB_LAG_MEMBER_SW_STATEm, MEM_BLOCK_ALL, 0); 449 if (BCM_FAILURE(rv)) { 450 bcm_tr3_lag_dlb_deinit(unit); 451 return rv; 452 } 453 454 /* Clear group membership */ 455 rv = soc_mem_clear(unit, DLB_LAG_GROUP_MEMBERSHIPm, MEM_BLOCK_ALL, 0); 456 if (BCM_FAILURE(rv)) { 457 bcm_tr3_lag_dlb_deinit(unit); 458 return rv; 459 } 460 461 /* Clear port<->member mapping tables */ 462 rv = soc_mem_clear(unit, DLB_LAG_MEMBERSHIP_REVERSE_MAPm, 463 MEM_BLOCK_ALL, 0); 464 if (BCM_FAILURE(rv)) { 465 bcm_tr3_lag_dlb_deinit(unit); 466 return rv; 467 } 468 rv = soc_mem_clear(unit, DLB_LAG_MEMBER_ATTRIBUTEm, MEM_BLOCK_ALL, 0); 469 if (BCM_FAILURE(rv)) { 470 bcm_tr3_lag_dlb_deinit(unit); 471 return rv; 472 } 473 474 /* Configure per member threshold scaling factor and 475 * quality measure update control. 476 */ 477 for (member_id = 0; 478 member_id < soc_mem_index_count(unit, 479 DLB_LAG_QUALITY_CONTROLm); 480 member_id++) { 481 rv = READ_DLB_LAG_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY, 482 member_id, &quality_control_entry); 483 if (SOC_FAILURE(rv)) { 484 bcm_tr3_lag_dlb_deinit(unit); 485 return rv; 486 } 487 soc_DLB_LAG_QUALITY_CONTROLm_field32_set(unit, 488 &quality_control_entry, ENABLE_AVG_CALCf, 1); 489 soc_DLB_LAG_QUALITY_CONTROLm_field32_set(unit, 490 &quality_control_entry, ENABLE_QUALITY_UPDATEf, 1); 491 soc_DLB_LAG_QUALITY_CONTROLm_field32_set(unit, 492 &quality_control_entry, ENABLE_CREDIT_COLLECTIONf, 1); 493 soc_DLB_LAG_QUALITY_CONTROLm_field32_set(unit, 494 &quality_control_entry, LOADING_SCALING_FACTORf, 1); 495 soc_DLB_LAG_QUALITY_CONTROLm_field32_set(unit, 496 &quality_control_entry, QSIZE_SCALING_FACTORf, 1); 497 rv = WRITE_DLB_LAG_QUALITY_CONTROLm(unit, MEM_BLOCK_ALL, 498 member_id, &quality_control_entry); 499 if (SOC_FAILURE(rv)) { 500 bcm_tr3_lag_dlb_deinit(unit); 501 return rv; 502 } 503 } 504 505 /* Enable DLB HGT refresh */ 506 507 rv = READ_RSEL2_HW_CONTROLr(unit, &rsel2_hw_control_reg); 508 if (BCM_SUCCESS(rv)) { 509 soc_reg_field_set(unit, RSEL2_HW_CONTROLr, &rsel2_hw_control_reg, 510 ENABLE_LAG_DLBf, 1); 511 rv = WRITE_RSEL2_HW_CONTROLr(unit, rsel2_hw_control_reg); 512 } 513 if (BCM_FAILURE(rv)) { 514 bcm_tr3_lag_dlb_deinit(unit); 515 return rv; 516 } 517 518 /* Configure Ethertype eligibility */ 519 520 rv = soc_mem_clear(unit, DLB_LAG_ETHERTYPE_ELIGIBILITY_MAPm, 521 MEM_BLOCK_ALL, 0); 522 if (BCM_FAILURE(rv)) { 523 bcm_tr3_lag_dlb_deinit(unit); 524 return rv; 525 } 526 rv = READ_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit, 527 &measure_control_reg); 528 if (SOC_SUCCESS(rv)) { 529 soc_reg_field_set(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr, 530 &measure_control_reg, 531 ETHERTYPE_ELIGIBILITY_CONFIGf, 0); 532 soc_reg_field_set(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr, 533 &measure_control_reg, 534 INNER_OUTER_ETHERTYPE_SELECTIONf, 0); 535 rv = WRITE_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit, 536 measure_control_reg); 537 } 538 if (BCM_FAILURE(rv)) { 539 bcm_tr3_lag_dlb_deinit(unit); 540 return rv; 541 } 542 543 } 544 545 return rv; 546 } 547 548 /* 549 * Function: 550 * _bcm_tr3_lag_dlb_accounting_set 551 * Purpose: 552 * Set LAG DLB accounting mode. 553 * Parameters: 554 * unit - (IN) SOC unit number. 555 * accounting_mode - (IN) Accounting mode. 556 * Returns: 557 * BCM_E_xxx 558 */ 559 STATIC int 560 _bcm_tr3_lag_dlb_accounting_set(int unit, int accounting_mode) 561 { 562 uint32 measure_control_reg; 563 int old_accounting_mode; 564 SHR_BITDCL active; 565 566 SOC_IF_ERROR_RETURN 567 (READ_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg)); 568 old_accounting_mode = soc_reg_field_get(unit, 569 DLB_LAG_QUALITY_MEASURE_CONTROLr, measure_control_reg, 570 ACCOUNTING_SELf); 571 if (old_accounting_mode == accounting_mode) { 572 return BCM_E_NONE; 573 } 574 575 SHR_BITTEST_RANGE(LAG_DLB_INFO(unit)->lag_dlb_id_used_bitmap, 576 0, soc_mem_index_count(unit, DLB_LAG_GROUP_CONTROLm), active); 577 if (active) { 578 /* Accounting mode cannot be changed while there are active 579 * DLB groups. 580 */ 581 return BCM_E_BUSY; 582 } 583 584 soc_reg_field_set(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr, 585 &measure_control_reg, ACCOUNTING_SELf, accounting_mode); 586 if (accounting_mode) { /* virtual link accounting */ 587 soc_reg_field_set(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr, 588 &measure_control_reg, INST_METRIC_UPDATE_INTERVALf, 1); 589 } else { /* physical link accounting */ 590 soc_reg_field_set(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr, 591 &measure_control_reg, INST_METRIC_UPDATE_INTERVALf, 0); 592 } 593 SOC_IF_ERROR_RETURN 594 (WRITE_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg)); 595 return BCM_E_NONE; 596 } 597 598 /* 599 * Function: 600 * _bcm_tr3_lag_dlb_accounting_get 601 * Purpose: 602 * Get LAG DLB accounting mode. 603 * Parameters: 604 * unit - (IN) SOC unit number. 605 * accounting_mode - (OUT) Accounting mode. 606 * Returns: 607 * BCM_E_xxx 608 */ 609 STATIC int 610 _bcm_tr3_lag_dlb_accounting_get(int unit, int *accounting_mode) 611 { 612 uint32 measure_control_reg; 613 614 SOC_IF_ERROR_RETURN 615 (READ_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg)); 616 *accounting_mode = soc_reg_field_get(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr, 617 measure_control_reg, ACCOUNTING_SELf); 618 619 return BCM_E_NONE; 620 } 621 622 /* 623 * Function: 624 * _bcm_tr3_lag_dlb_sample_rate_pla_thresholds_set 625 * Purpose: 626 * Set LAG DLB sample period and physical link accounting thresholds. 627 * Parameters: 628 * unit - (IN) SOC unit number. 629 * sample_rate - (IN) Number of samplings per second. 630 * min_th - (IN) Minimum port load threshold, in mbps. 631 * max_th - (IN) Maximum port load threshold, in mbps. 632 * Returns: 633 * BCM_E_xxx 634 */ 635 STATIC int 636 _bcm_tr3_lag_dlb_sample_rate_pla_thresholds_set(int unit, int sample_rate, 637 int min_th, int max_th) 638 { 639 int num_time_units; 640 uint32 measure_control_reg; 641 int max_th_bytes; 642 int th_increment; 643 dlb_lag_pla_quantize_threshold_entry_t quantize_threshold_entry; 644 int i; 645 int th_bytes[7]; 646 647 if (sample_rate <= 0 || min_th < 0 || max_th < 0) { 648 return BCM_E_PARAM; 649 } 650 651 if (min_th > max_th) { 652 max_th = min_th; 653 } 654 655 /* Compute sampling period in units of 1us: 656 * number of 1us time units = 10^6 / sample_rate 657 */ 658 num_time_units = 1000000 / sample_rate; 659 if (num_time_units < 1 || num_time_units > 0x3fff) { 660 /* Hardware limits the sampling period to 14 bits */ 661 return BCM_E_PARAM; 662 } 663 SOC_IF_ERROR_RETURN 664 (READ_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg)); 665 soc_reg_field_set(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr, 666 &measure_control_reg, HISTORICAL_SAMPLING_PERIODf, num_time_units); 667 SOC_IF_ERROR_RETURN 668 (WRITE_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg)); 669 LAG_DLB_INFO(unit)->lag_dlb_sample_rate = sample_rate; 670 671 /* Compute threshold in bytes per sampling period: 672 * bytes per 1us = (million bits per sec) * 10^6 / 8 * 10^(-6), 673 * bytes per sampling period = (bytes per 1us) * (number of 1us 674 * time units in sampling period) 675 * = mbps * num_time_units / 8 676 */ 677 max_th_bytes = max_th * num_time_units / 8; 678 679 if (max_th_bytes > 0x3fffffff) { 680 /* Hardware limits port load threshold to 30 bits */ 681 return BCM_E_PARAM; 682 } 683 684 /* Use min threshold as threshold 0, and max threshold as threshold 6. 685 * Thresholds 1 to 5 will be evenly spread out between min and max 686 * thresholds. 687 */ 688 th_increment = (max_th - min_th) / 6; 689 for (i = 0; i < 7; i++) { 690 SOC_IF_ERROR_RETURN 691 (READ_DLB_LAG_PLA_QUANTIZE_THRESHOLDm(unit, MEM_BLOCK_ANY, i, 692 &quantize_threshold_entry)); 693 th_bytes[i] = (min_th + i * th_increment) * num_time_units / 8; 694 soc_DLB_LAG_PLA_QUANTIZE_THRESHOLDm_field32_set 695 (unit, &quantize_threshold_entry, THRESHOLD_HIST_LOADf, 696 th_bytes[i]); 697 SOC_IF_ERROR_RETURN 698 (WRITE_DLB_LAG_PLA_QUANTIZE_THRESHOLDm(unit, MEM_BLOCK_ALL, i, 699 &quantize_threshold_entry)); 700 } 701 702 LAG_DLB_INFO(unit)->lag_dlb_tx_load_min_th = min_th; 703 LAG_DLB_INFO(unit)->lag_dlb_tx_load_max_th = max_th; 704 705 return BCM_E_NONE; 706 } 707 708 /* 709 * Function: 710 * _bcm_tr3_lag_dlb_sample_rate_vla_thresholds_set 711 * Purpose: 712 * Set LAG DLB sample period and virtual link accounting thresholds. 713 * Parameters: 714 * unit - (IN) SOC unit number. 715 * sample_rate - (IN) Number of samplings per second. 716 * exp_load_min_th - (IN) Minimum expected load threshold, in mbps. 717 * exp_load_max_th - (IN) Maximum expected load threshold, in mbps. 718 * imbalance_min_th - (IN) Minimum member imbalance threshold, 719 * in percentage. 720 * imbalance_max_th - (IN) Maximum member imbalance threshold. 721 * in percentage. 722 * Returns: 723 * BCM_E_xxx 724 */ 725 STATIC int 726 _bcm_tr3_lag_dlb_sample_rate_vla_thresholds_set(int unit, int sample_rate, 727 int exp_load_min_th, int exp_load_max_th, 728 int imbalance_min_th, int imbalance_max_th) 729 { 730 int num_time_units; 731 uint32 measure_control_reg; 732 int exp_load_max_th_kbytes; 733 int num_exp_load_th; 734 int exp_load_th_increment; 735 dlb_lag_vla_expected_loading_threshold_entry_t exp_load_threshold_entry; 736 int exp_load_th_kbytes; 737 int num_imbalance_th; 738 int imbalance_th_increment; 739 int imbalance_max_th_kbytes; 740 int imbalance_th_kbytes; 741 dlb_lag_vla_member_imbalance_threshold_entry_t imbalance_threshold_entry; 742 int i, j; 743 int imbalance_th_fields[7] = {THRESHOLD_0f, THRESHOLD_1f, THRESHOLD_2f, 744 THRESHOLD_3f, THRESHOLD_4f, THRESHOLD_5f, 745 THRESHOLD_6f}; 746 747 if (sample_rate <= 0 || exp_load_min_th < 0 || exp_load_max_th < 0) { 748 return BCM_E_PARAM; 749 } 750 751 if (exp_load_min_th > exp_load_max_th) { 752 exp_load_max_th = exp_load_min_th; 753 } 754 755 if (imbalance_min_th > imbalance_max_th) { 756 imbalance_max_th = imbalance_min_th; 757 } 758 759 /* Compute sampling period in units of 1us: 760 * number of 1us time units = 10^6 / sample_rate 761 */ 762 num_time_units = 1000000 / sample_rate; 763 if (num_time_units < 1 || num_time_units > 0x3fff) { 764 /* Hardware limits the sampling period to 14 bits */ 765 return BCM_E_PARAM; 766 } 767 SOC_IF_ERROR_RETURN 768 (READ_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg)); 769 soc_reg_field_set(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr, 770 &measure_control_reg, HISTORICAL_SAMPLING_PERIODf, num_time_units); 771 SOC_IF_ERROR_RETURN 772 (WRITE_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg)); 773 LAG_DLB_INFO(unit)->lag_dlb_sample_rate = sample_rate; 774 775 /* Compute expected loading threshold in kbytes per sampling period: 776 * bytes per 1us = (million bits per sec) * 10^6 / 8 * 10^(-6) 777 * = mbps / 8. 778 * bytes per sampling period = (bytes per 1us) * (number of 1us 779 * time units in sampling period) 780 * = mbps * num_time_units / 8. 781 * kbytes per sampling period = mbps * num_times_units / 8000. 782 */ 783 exp_load_max_th_kbytes = exp_load_max_th * num_time_units / 8000; 784 if (exp_load_max_th_kbytes > 0xfffff) { 785 /* Hardware limits expected loading threshold in kbytes to 20 bits */ 786 return BCM_E_PARAM; 787 } 788 789 /* Use expected load min threshold as threshold 0, and max threshold as 790 * threshold 14. Thresholds 1 to 13 will be evenly spread out between them. 791 */ 792 num_exp_load_th = soc_mem_index_count(unit, 793 DLB_LAG_VLA_EXPECTED_LOADING_THRESHOLDm); 794 exp_load_th_increment = (exp_load_max_th - exp_load_min_th) / 795 (num_exp_load_th - 1); 796 for (i = 0; i < num_exp_load_th; i++) { 797 SOC_IF_ERROR_RETURN(READ_DLB_LAG_VLA_EXPECTED_LOADING_THRESHOLDm(unit, 798 MEM_BLOCK_ANY, i, &exp_load_threshold_entry)); 799 exp_load_th_kbytes = (exp_load_min_th + i * exp_load_th_increment) * 800 num_time_units / 8000; 801 soc_DLB_LAG_VLA_EXPECTED_LOADING_THRESHOLDm_field32_set 802 (unit, &exp_load_threshold_entry, THRESHOLDf, exp_load_th_kbytes); 803 SOC_IF_ERROR_RETURN(WRITE_DLB_LAG_VLA_EXPECTED_LOADING_THRESHOLDm(unit, 804 MEM_BLOCK_ALL, i, &exp_load_threshold_entry)); 805 } 806 807 LAG_DLB_INFO(unit)->lag_dlb_exp_load_min_th = exp_load_min_th; 808 LAG_DLB_INFO(unit)->lag_dlb_exp_load_max_th = exp_load_max_th; 809 810 /* Use member imbalance min threshold as threshold 0, and max threshold as 811 * threshold 6. Thresholds 1 to 5 will be evenly spread out between them. 812 */ 813 num_imbalance_th = 7; 814 imbalance_th_increment = (imbalance_max_th - imbalance_min_th) / 815 (num_imbalance_th - 1); 816 for (i = 0; 817 i < soc_mem_index_count(unit, 818 DLB_LAG_VLA_MEMBER_IMBALANCE_THRESHOLDm); 819 i++) { 820 /* There are 16 sets of member imbalance thresholds. 821 * For sets 0 to 14, use expected loading thresholds 0 to 14 from 822 * DLB_LAG_VLA_EXPECTED_LOADING_THRESHOLD table as the 823 * expected load. For set 15, extrapolate the expected load. 824 */ 825 if (i < num_exp_load_th) { 826 SOC_IF_ERROR_RETURN 827 (READ_DLB_LAG_VLA_EXPECTED_LOADING_THRESHOLDm(unit, 828 MEM_BLOCK_ANY, i, &exp_load_threshold_entry)); 829 exp_load_th_kbytes = 830 soc_DLB_LAG_VLA_EXPECTED_LOADING_THRESHOLDm_field32_get(unit, 831 &exp_load_threshold_entry, THRESHOLDf); 832 } else { 833 exp_load_th_kbytes = 834 (exp_load_min_th + num_exp_load_th * exp_load_th_increment) * 835 num_time_units / 8000; 836 } 837 838 /* Compute member imbalance thresholds */ 839 imbalance_max_th_kbytes = exp_load_th_kbytes * imbalance_max_th / 100; 840 if (imbalance_max_th_kbytes > 0xfffff) { 841 /* Hardware limits imbalance threshold in kbytes to 1 sign bit 842 * plus 20 bits. 843 */ 844 return BCM_E_PARAM; 845 } 846 SOC_IF_ERROR_RETURN(READ_DLB_LAG_VLA_MEMBER_IMBALANCE_THRESHOLDm(unit, 847 MEM_BLOCK_ANY, i, &imbalance_threshold_entry)); 848 for (j = 0; j < num_imbalance_th; j++) { 849 imbalance_th_kbytes = exp_load_th_kbytes * 850 (imbalance_min_th + j * imbalance_th_increment) / 100; 851 if (imbalance_th_kbytes < 0) { 852 /* Convert to two's complement representation */ 853 imbalance_th_kbytes = -1 * imbalance_th_kbytes; 854 imbalance_th_kbytes = (~imbalance_th_kbytes) + 1; 855 } 856 soc_DLB_LAG_VLA_MEMBER_IMBALANCE_THRESHOLDm_field32_set(unit, 857 &imbalance_threshold_entry, imbalance_th_fields[j], 858 imbalance_th_kbytes & 0x1fffff); 859 } 860 SOC_IF_ERROR_RETURN(WRITE_DLB_LAG_VLA_MEMBER_IMBALANCE_THRESHOLDm(unit, 861 MEM_BLOCK_ALL, i, &imbalance_threshold_entry)); 862 } 863 864 LAG_DLB_INFO(unit)->lag_dlb_imbalance_min_th = imbalance_min_th; 865 LAG_DLB_INFO(unit)->lag_dlb_imbalance_max_th = imbalance_max_th; 866 867 return BCM_E_NONE; 868 } 869 870 /* 871 * Function: 872 * _bcm_tr3_lag_dlb_sample_rate_set 873 * Purpose: 874 * Set LAG dynamic load balancing sample rate. 875 * Parameters: 876 * unit - (IN) SOC unit number. 877 * sample_rate - (IN) Number of samplings per second. 878 * Returns: 879 * BCM_E_xxx 880 */ 881 STATIC int 882 _bcm_tr3_lag_dlb_sample_rate_set(int unit, int sample_rate) 883 { 884 BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_sample_rate_pla_thresholds_set(unit, 885 sample_rate, LAG_DLB_INFO(unit)->lag_dlb_tx_load_min_th, 886 LAG_DLB_INFO(unit)->lag_dlb_tx_load_max_th)); 887 888 BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_sample_rate_vla_thresholds_set(unit, 889 sample_rate, LAG_DLB_INFO(unit)->lag_dlb_exp_load_min_th, 890 LAG_DLB_INFO(unit)->lag_dlb_exp_load_max_th, 891 LAG_DLB_INFO(unit)->lag_dlb_imbalance_min_th, 892 LAG_DLB_INFO(unit)->lag_dlb_imbalance_max_th)); 893 return BCM_E_NONE; 894 } 895 896 /* 897 * Function: 898 * _bcm_tr3_lag_dlb_tx_load_min_th_set 899 * Purpose: 900 * Set LAG DLB port load minimum threshold. 901 * Parameters: 902 * unit - (IN) SOC unit number. 903 * min_th - (IN) Minimum port loading threshold. 904 * Returns: 905 * BCM_E_xxx 906 */ 907 STATIC int 908 _bcm_tr3_lag_dlb_tx_load_min_th_set(int unit, int min_th) 909 { 910 BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_sample_rate_pla_thresholds_set(unit, 911 LAG_DLB_INFO(unit)->lag_dlb_sample_rate, min_th, 912 LAG_DLB_INFO(unit)->lag_dlb_tx_load_max_th)); 913 return BCM_E_NONE; 914 } 915 916 /* 917 * Function: 918 * _bcm_trident_lag_dlb_tx_load_max_th_set 919 * Purpose: 920 * Set LAG DLB port load maximum threshold. 921 * Parameters: 922 * unit - (IN) SOC unit number. 923 * max_th - (IN) Maximum port loading threshold. 924 * Returns: 925 * BCM_E_xxx 926 */ 927 STATIC int 928 _bcm_tr3_lag_dlb_tx_load_max_th_set(int unit, int max_th) 929 { 930 BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_sample_rate_pla_thresholds_set(unit, 931 LAG_DLB_INFO(unit)->lag_dlb_sample_rate, 932 LAG_DLB_INFO(unit)->lag_dlb_tx_load_min_th, 933 max_th)); 934 return BCM_E_NONE; 935 } 936 937 /* 938 * Function: 939 * _bcm_tr3_lag_dlb_exp_load_min_th_set 940 * Purpose: 941 * Set LAG DLB expected load minimum threshold. 942 * Parameters: 943 * unit - (IN) SOC unit number. 944 * min_th - (IN) Minimum expected load threshold. 945 * Returns: 946 * BCM_E_xxx 947 */ 948 STATIC int 949 _bcm_tr3_lag_dlb_exp_load_min_th_set(int unit, int min_th) 950 { 951 BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_sample_rate_vla_thresholds_set(unit, 952 LAG_DLB_INFO(unit)->lag_dlb_sample_rate, 953 min_th, 954 LAG_DLB_INFO(unit)->lag_dlb_exp_load_max_th, 955 LAG_DLB_INFO(unit)->lag_dlb_imbalance_min_th, 956 LAG_DLB_INFO(unit)->lag_dlb_imbalance_max_th)); 957 return BCM_E_NONE; 958 } 959 960 /* 961 * Function: 962 * _bcm_tr3_lag_dlb_exp_load_max_th_set 963 * Purpose: 964 * Set LAG DLB expected load maximum threshold. 965 * Parameters: 966 * unit - (IN) SOC unit number. 967 * max_th - (IN) Maximum expected load threshold. 968 * Returns: 969 * BCM_E_xxx 970 */ 971 STATIC int 972 _bcm_tr3_lag_dlb_exp_load_max_th_set(int unit, int max_th) 973 { 974 BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_sample_rate_vla_thresholds_set(unit, 975 LAG_DLB_INFO(unit)->lag_dlb_sample_rate, 976 LAG_DLB_INFO(unit)->lag_dlb_exp_load_min_th, 977 max_th, 978 LAG_DLB_INFO(unit)->lag_dlb_imbalance_min_th, 979 LAG_DLB_INFO(unit)->lag_dlb_imbalance_max_th)); 980 return BCM_E_NONE; 981 } 982 983 /* 984 * Function: 985 * _bcm_tr3_lag_dlb_imbalance_min_th_set 986 * Purpose: 987 * Set LAG DLB member imbalance minimum threshold. 988 * Parameters: 989 * unit - (IN) SOC unit number. 990 * min_th - (IN) Minimum member imbalance threshold. 991 * Returns: 992 * BCM_E_xxx 993 */ 994 STATIC int 995 _bcm_tr3_lag_dlb_imbalance_min_th_set(int unit, int min_th) 996 { 997 BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_sample_rate_vla_thresholds_set(unit, 998 LAG_DLB_INFO(unit)->lag_dlb_sample_rate, 999 LAG_DLB_INFO(unit)->lag_dlb_exp_load_min_th, 1000 LAG_DLB_INFO(unit)->lag_dlb_exp_load_max_th, 1001 min_th, 1002 LAG_DLB_INFO(unit)->lag_dlb_imbalance_max_th)); 1003 return BCM_E_NONE; 1004 } 1005 1006 /* 1007 * Function: 1008 * _bcm_tr3_lag_dlb_imbalance_max_th_set 1009 * Purpose: 1010 * Set LAG DLB member imbalance maximum threshold. 1011 * Parameters: 1012 * unit - (IN) SOC unit number. 1013 * max_th - (IN) Maximum member imbalance threshold. 1014 * Returns: 1015 * BCM_E_xxx 1016 */ 1017 STATIC int 1018 _bcm_tr3_lag_dlb_imbalance_max_th_set(int unit, int max_th) 1019 { 1020 BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_sample_rate_vla_thresholds_set(unit, 1021 LAG_DLB_INFO(unit)->lag_dlb_sample_rate, 1022 LAG_DLB_INFO(unit)->lag_dlb_exp_load_min_th, 1023 LAG_DLB_INFO(unit)->lag_dlb_exp_load_max_th, 1024 LAG_DLB_INFO(unit)->lag_dlb_imbalance_min_th, 1025 max_th)); 1026 return BCM_E_NONE; 1027 } 1028 1029 /* 1030 * Function: 1031 * _bcm_tr3_lag_dlb_qsize_thresholds_set 1032 * Purpose: 1033 * Set LAG DLB queue size thresholds. 1034 * Parameters: 1035 * unit - (IN) SOC unit number. 1036 * min_th - (IN) Minimum queue size threshold, in bytes. 1037 * max_th - (IN) Maximum queue size threshold, in bytes. 1038 * Returns: 1039 * BCM_E_xxx 1040 */ 1041 STATIC int 1042 _bcm_tr3_lag_dlb_qsize_thresholds_set(int unit, int min_th, int max_th) 1043 { 1044 int max_th_cells; 1045 int th_increment; 1046 dlb_hgt_quantize_threshold_entry_t quantize_threshold_entry; 1047 int i; 1048 int th_cells[7]; 1049 1050 if (min_th < 0 || max_th < 0) { 1051 return BCM_E_PARAM; 1052 } 1053 1054 if (min_th > max_th) { 1055 max_th = min_th; 1056 } 1057 1058 /* Convert threshold to number of cells */ 1059 max_th_cells = max_th / 208; 1060 if (max_th_cells > 0xffff) { 1061 /* Hardware limits queue size threshold to 16 bits */ 1062 return BCM_E_PARAM; 1063 } 1064 1065 /* Use min threshold as threshold 0, and max threshold as threshold 6. 1066 * Thresholds 1 to 5 will be evenly spread out between min and max 1067 * thresholds. 1068 */ 1069 th_increment = (max_th - min_th) / 6; 1070 for (i = 0; i < 7; i++) { 1071 SOC_IF_ERROR_RETURN 1072 (READ_DLB_LAG_PLA_QUANTIZE_THRESHOLDm(unit, MEM_BLOCK_ANY, i, 1073 &quantize_threshold_entry)); 1074 th_cells[i] = (min_th + i * th_increment) / 208; 1075 soc_DLB_LAG_PLA_QUANTIZE_THRESHOLDm_field32_set 1076 (unit, &quantize_threshold_entry, THRESHOLD_HIST_QSIZEf, 1077 th_cells[i]); 1078 SOC_IF_ERROR_RETURN 1079 (WRITE_DLB_LAG_PLA_QUANTIZE_THRESHOLDm(unit, MEM_BLOCK_ALL, i, 1080 &quantize_threshold_entry)); 1081 } 1082 1083 LAG_DLB_INFO(unit)->lag_dlb_qsize_min_th = min_th; 1084 LAG_DLB_INFO(unit)->lag_dlb_qsize_max_th = max_th; 1085 1086 return BCM_E_NONE; 1087 } 1088 1089 /* 1090 * Function: 1091 * _bcm_tr3_lag_dlb_qsize_min_th_set 1092 * Purpose: 1093 * Set LAG DLB queue size minimum threshold. 1094 * Parameters: 1095 * unit - (IN) SOC unit number. 1096 * min_th - (IN) Minimum queue size threshold, in bytes. 1097 * Returns: 1098 * BCM_E_xxx 1099 */ 1100 STATIC int 1101 _bcm_tr3_lag_dlb_qsize_min_th_set(int unit, int min_th) 1102 { 1103 BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_qsize_thresholds_set(unit, 1104 min_th, LAG_DLB_INFO(unit)->lag_dlb_qsize_max_th)); 1105 1106 return BCM_E_NONE; 1107 } 1108 1109 /* 1110 * Function: 1111 * _bcm_tr3_lag_dlb_qsize_max_th_set 1112 * Purpose: 1113 * Set LAG DLB queue size maximum threshold. 1114 * Parameters: 1115 * unit - (IN) SOC unit number. 1116 * max_th - (IN) Maximum queue size threshold, in bytes. 1117 * Returns: 1118 * BCM_E_xxx 1119 */ 1120 STATIC int 1121 _bcm_tr3_lag_dlb_qsize_max_th_set(int unit, int max_th) 1122 { 1123 BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_qsize_thresholds_set(unit, 1124 LAG_DLB_INFO(unit)->lag_dlb_qsize_min_th, max_th)); 1125 1126 return BCM_E_NONE; 1127 } 1128 1129 /* 1130 * Function: 1131 * _bcm_tr3_lag_dlb_tx_load_weight_set 1132 * Purpose: 1133 * Set LAG DLB port load weight. 1134 * Parameters: 1135 * unit - (IN) SOC unit number. 1136 * weight - (IN) Port load weight. 1137 * Returns: 1138 * BCM_E_xxx 1139 */ 1140 STATIC int 1141 _bcm_tr3_lag_dlb_tx_load_weight_set(int unit, int weight) 1142 { 1143 uint32 measure_control_reg; 1144 1145 if (weight < 0 || 1146 weight > 0xf) { 1147 /* Hardware limits port load weight to 4 bits */ 1148 return BCM_E_PARAM; 1149 } 1150 1151 SOC_IF_ERROR_RETURN 1152 (READ_DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg)); 1153 soc_reg_field_set(unit, DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr, 1154 &measure_control_reg, PLA_WEIGHT_LOADINGf, weight); 1155 SOC_IF_ERROR_RETURN 1156 (WRITE_DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg)); 1157 return BCM_E_NONE; 1158 } 1159 1160 /* 1161 * Function: 1162 * _bcm_tr3_lag_dlb_tx_load_weight_get 1163 * Purpose: 1164 * Get LAG DLB port load weight. 1165 * Parameters: 1166 * unit - (IN) SOC unit number. 1167 * weight - (OUT) Port load weight. 1168 * Returns: 1169 * BCM_E_xxx 1170 */ 1171 STATIC int 1172 _bcm_tr3_lag_dlb_tx_load_weight_get(int unit, int *weight) 1173 { 1174 uint32 measure_control_reg; 1175 1176 SOC_IF_ERROR_RETURN 1177 (READ_DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg)); 1178 *weight = soc_reg_field_get(unit, DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr, 1179 measure_control_reg, PLA_WEIGHT_LOADINGf); 1180 1181 return BCM_E_NONE; 1182 } 1183 1184 /* 1185 * Function: 1186 * _bcm_tr3_lag_dlb_qsize_weight_set 1187 * Purpose: 1188 * Set LAG DLB qsize weight. 1189 * Parameters: 1190 * unit - (IN) SOC unit number. 1191 * weight - (IN) Qsize weight. 1192 * Returns: 1193 * BCM_E_xxx 1194 */ 1195 STATIC int 1196 _bcm_tr3_lag_dlb_qsize_weight_set(int unit, int weight) 1197 { 1198 uint32 measure_control_reg; 1199 1200 if (weight < 0 || 1201 weight > 0xf) { 1202 /* Hardware limits qsize weight to 4 bits */ 1203 return BCM_E_PARAM; 1204 } 1205 1206 SOC_IF_ERROR_RETURN 1207 (READ_DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg)); 1208 soc_reg_field_set(unit, DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr, 1209 &measure_control_reg, PLA_WEIGHT_QSIZEf, weight); 1210 SOC_IF_ERROR_RETURN 1211 (WRITE_DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg)); 1212 return BCM_E_NONE; 1213 } 1214 1215 /* 1216 * Function: 1217 * _bcm_tr3_lag_dlb_qsize_weight_get 1218 * Purpose: 1219 * Get LAG DLB qsize weight. 1220 * Parameters: 1221 * unit - (IN) SOC unit number. 1222 * weight - (OUT) Qsize weight. 1223 * Returns: 1224 * BCM_E_xxx 1225 */ 1226 STATIC int 1227 _bcm_tr3_lag_dlb_qsize_weight_get(int unit, int *weight) 1228 { 1229 uint32 measure_control_reg; 1230 1231 SOC_IF_ERROR_RETURN 1232 (READ_DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg)); 1233 *weight = soc_reg_field_get(unit, DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr, 1234 measure_control_reg, PLA_WEIGHT_QSIZEf); 1235 1236 return BCM_E_NONE; 1237 } 1238 1239 /* 1240 * Function: 1241 * _bcm_tr3_lag_dlb_tx_load_cap_set 1242 * Purpose: 1243 * Set LAG DLB port load cap control. 1244 * Parameters: 1245 * unit - (IN) SOC unit number. 1246 * cap - (IN) Port load cap control. 1247 * Returns: 1248 * BCM_E_xxx 1249 */ 1250 STATIC int 1251 _bcm_tr3_lag_dlb_tx_load_cap_set(int unit, int cap) 1252 { 1253 uint32 measure_control_reg; 1254 1255 if (cap < 0 || 1256 cap > 1) { 1257 /* Hardware limits port load cap control to 1 bit */ 1258 return BCM_E_PARAM; 1259 } 1260 1261 SOC_IF_ERROR_RETURN 1262 (READ_DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg)); 1263 soc_reg_field_set(unit, DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr, 1264 &measure_control_reg, PLA_CAP_LOADING_AVGf, cap); 1265 SOC_IF_ERROR_RETURN 1266 (WRITE_DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg)); 1267 return BCM_E_NONE; 1268 } 1269 1270 /* 1271 * Function: 1272 * _bcm_tr3_lag_dlb_tx_load_cap_get 1273 * Purpose: 1274 * Get LAG DLB port load cap control. 1275 * Parameters: 1276 * unit - (IN) SOC unit number. 1277 * cap - (OUT) Cap control. 1278 * Returns: 1279 * BCM_E_xxx 1280 */ 1281 STATIC int 1282 _bcm_tr3_lag_dlb_tx_load_cap_get(int unit, int *cap) 1283 { 1284 uint32 measure_control_reg; 1285 1286 SOC_IF_ERROR_RETURN 1287 (READ_DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg)); 1288 *cap= soc_reg_field_get(unit, DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr, 1289 measure_control_reg, PLA_CAP_LOADING_AVGf); 1290 1291 return BCM_E_NONE; 1292 } 1293 /* 1294 * Function: 1295 * _bcm_tr3_lag_dlb_qsize_cap_set 1296 * Purpose: 1297 * Set LAG DLB queue size cap control. 1298 * Parameters: 1299 * unit - (IN) SOC unit number. 1300 * cap - (IN) Queue size cap control. 1301 * Returns: 1302 * BCM_E_xxx 1303 */ 1304 STATIC int 1305 _bcm_tr3_lag_dlb_qsize_cap_set(int unit, int cap) 1306 { 1307 uint32 measure_control_reg; 1308 1309 if (cap < 0 || 1310 cap > 1) { 1311 /* Hardware limits port load cap control to 1 bit */ 1312 return BCM_E_PARAM; 1313 } 1314 1315 SOC_IF_ERROR_RETURN 1316 (READ_DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg)); 1317 soc_reg_field_set(unit, DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr, 1318 &measure_control_reg, PLA_CAP_QSIZE_AVGf, cap); 1319 SOC_IF_ERROR_RETURN 1320 (WRITE_DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg)); 1321 return BCM_E_NONE; 1322 } 1323 1324 /* 1325 * Function: 1326 * _bcm_tr3_lag_dlb_qsize_cap_get 1327 * Purpose: 1328 * Get LAG DLB queue size cap control. 1329 * Parameters: 1330 * unit - (IN) SOC unit number. 1331 * cap - (OUT) Cap control. 1332 * Returns: 1333 * BCM_E_xxx 1334 */ 1335 STATIC int 1336 _bcm_tr3_lag_dlb_qsize_cap_get(int unit, int *cap) 1337 { 1338 uint32 measure_control_reg; 1339 1340 SOC_IF_ERROR_RETURN 1341 (READ_DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg)); 1342 *cap= soc_reg_field_get(unit, DLB_LAG_PLA_QUALITY_MEASURE_CONTROLr, 1343 measure_control_reg, PLA_CAP_QSIZE_AVGf); 1344 1345 return BCM_E_NONE; 1346 } 1347 1348 /* 1349 * Function: 1350 * bcm_tr3_lag_dlb_config_set 1351 * Purpose: 1352 * Set per-chip LAG dynamic load balancing configuration parameters. 1353 * Parameters: 1354 * unit - (IN) SOC unit number. 1355 * type - (IN) Configuration parameter type. 1356 * arg - (IN) Configuration paramter value. 1357 * Returns: 1358 * BCM_E_xxx 1359 */ 1360 int 1361 bcm_tr3_lag_dlb_config_set(int unit, bcm_switch_control_t type, int arg) 1362 { 1363 switch (type) { 1364 case bcmSwitchTrunkDynamicSampleRate: 1365 return _bcm_tr3_lag_dlb_sample_rate_set(unit, arg); 1366 1367 case bcmSwitchTrunkDynamicAccountingSelect: 1368 return _bcm_tr3_lag_dlb_accounting_set(unit, arg); 1369 1370 case bcmSwitchTrunkDynamicEgressBytesExponent: 1371 return _bcm_tr3_lag_dlb_tx_load_weight_set(unit, arg); 1372 1373 case bcmSwitchTrunkDynamicQueuedBytesExponent: 1374 return _bcm_tr3_lag_dlb_qsize_weight_set(unit, arg); 1375 1376 case bcmSwitchTrunkDynamicEgressBytesDecreaseReset: 1377 return _bcm_tr3_lag_dlb_tx_load_cap_set(unit, arg); 1378 1379 case bcmSwitchTrunkDynamicQueuedBytesDecreaseReset: 1380 return _bcm_tr3_lag_dlb_qsize_cap_set(unit, arg); 1381 1382 case bcmSwitchTrunkDynamicEgressBytesMinThreshold: 1383 return _bcm_tr3_lag_dlb_tx_load_min_th_set(unit, arg); 1384 1385 case bcmSwitchTrunkDynamicEgressBytesMaxThreshold: 1386 return _bcm_tr3_lag_dlb_tx_load_max_th_set(unit, arg); 1387 1388 case bcmSwitchTrunkDynamicQueuedBytesMinThreshold: 1389 return _bcm_tr3_lag_dlb_qsize_min_th_set(unit, arg); 1390 1391 case bcmSwitchTrunkDynamicQueuedBytesMaxThreshold: 1392 return _bcm_tr3_lag_dlb_qsize_max_th_set(unit, arg); 1393 1394 case bcmSwitchTrunkDynamicExpectedLoadMinThreshold: 1395 return _bcm_tr3_lag_dlb_exp_load_min_th_set(unit, arg); 1396 1397 case bcmSwitchTrunkDynamicExpectedLoadMaxThreshold: 1398 return _bcm_tr3_lag_dlb_exp_load_max_th_set(unit, arg); 1399 1400 case bcmSwitchTrunkDynamicImbalanceMinThreshold: 1401 return _bcm_tr3_lag_dlb_imbalance_min_th_set(unit, arg); 1402 1403 case bcmSwitchTrunkDynamicImbalanceMaxThreshold: 1404 return _bcm_tr3_lag_dlb_imbalance_max_th_set(unit, arg); 1405 1406 default: 1407 return BCM_E_PARAM; 1408 } 1409 } 1410 1411 /* 1412 * Function: 1413 * bcm_tr3_lag_dlb_config_get 1414 * Purpose: 1415 * Get per-chip LAG dynamic load balancing configuration parameters. 1416 * Parameters: 1417 * unit - (IN) SOC unit number. 1418 * type - (IN) Configuration parameter type. 1419 * arg - (OUT) Configuration paramter value. 1420 * Returns: 1421 * BCM_E_xxx 1422 */ 1423 int 1424 bcm_tr3_lag_dlb_config_get(int unit, bcm_switch_control_t type, int *arg) 1425 { 1426 switch (type) { 1427 case bcmSwitchTrunkDynamicSampleRate: 1428 *arg = LAG_DLB_INFO(unit)->lag_dlb_sample_rate; 1429 break; 1430 1431 case bcmSwitchTrunkDynamicAccountingSelect: 1432 return _bcm_tr3_lag_dlb_accounting_get(unit, arg); 1433 break; 1434 1435 case bcmSwitchTrunkDynamicEgressBytesExponent: 1436 return _bcm_tr3_lag_dlb_tx_load_weight_get(unit, arg); 1437 1438 case bcmSwitchTrunkDynamicQueuedBytesExponent: 1439 return _bcm_tr3_lag_dlb_qsize_weight_get(unit, arg); 1440 1441 case bcmSwitchTrunkDynamicEgressBytesDecreaseReset: 1442 return _bcm_tr3_lag_dlb_tx_load_cap_get(unit, arg); 1443 1444 case bcmSwitchTrunkDynamicQueuedBytesDecreaseReset: 1445 return _bcm_tr3_lag_dlb_qsize_cap_get(unit, arg); 1446 1447 case bcmSwitchTrunkDynamicEgressBytesMinThreshold: 1448 *arg = LAG_DLB_INFO(unit)->lag_dlb_tx_load_min_th; 1449 break; 1450 1451 case bcmSwitchTrunkDynamicEgressBytesMaxThreshold: 1452 *arg = LAG_DLB_INFO(unit)->lag_dlb_tx_load_max_th; 1453 break; 1454 1455 case bcmSwitchTrunkDynamicQueuedBytesMinThreshold: 1456 *arg = LAG_DLB_INFO(unit)->lag_dlb_qsize_min_th; 1457 break; 1458 1459 case bcmSwitchTrunkDynamicQueuedBytesMaxThreshold: 1460 *arg = LAG_DLB_INFO(unit)->lag_dlb_qsize_max_th; 1461 break; 1462 1463 case bcmSwitchTrunkDynamicExpectedLoadMinThreshold: 1464 *arg = LAG_DLB_INFO(unit)->lag_dlb_exp_load_min_th; 1465 break; 1466 1467 case bcmSwitchTrunkDynamicExpectedLoadMaxThreshold: 1468 *arg = LAG_DLB_INFO(unit)->lag_dlb_exp_load_max_th; 1469 break; 1470 1471 case bcmSwitchTrunkDynamicImbalanceMinThreshold: 1472 *arg = LAG_DLB_INFO(unit)->lag_dlb_imbalance_min_th; 1473 break; 1474 1475 case bcmSwitchTrunkDynamicImbalanceMaxThreshold: 1476 *arg = LAG_DLB_INFO(unit)->lag_dlb_imbalance_max_th; 1477 break; 1478 1479 default: 1480 return BCM_E_PARAM; 1481 } 1482 1483 return BCM_E_NONE; 1484 } 1485 1486 /* 1487 * Function: 1488 * _bcm_tr3_lag_dlb_dynamic_size_encode 1489 * Purpose: 1490 * Encode LAG dynamic load balancing flow set size. 1491 * Parameters: 1492 * dynamic_size - (IN) Number of flow sets. 1493 * encoded_value - (OUT) Encoded value. 1494 * Returns: 1495 * BCM_E_xxx 1496 */ 1497 int 1498 bcm_tr3_lag_dlb_dynamic_size_encode(int dynamic_size, 1499 int *encoded_value) 1500 { 1501 switch (dynamic_size) { 1502 case 512: 1503 *encoded_value = 1; 1504 break; 1505 case 1024: 1506 *encoded_value = 2; 1507 break; 1508 case 2048: 1509 *encoded_value = 3; 1510 break; 1511 case 4096: 1512 *encoded_value = 4; 1513 break; 1514 case 8192: 1515 *encoded_value = 5; 1516 break; 1517 case 16384: 1518 *encoded_value = 6; 1519 break; 1520 case 32768: 1521 *encoded_value = 7; 1522 break; 1523 default: 1524 return BCM_E_PARAM; 1525 } 1526 1527 return BCM_E_NONE; 1528 } 1529 1530 /* 1531 * Function: 1532 * _bcm_tr3_lag_dlb_dynamic_size_decode 1533 * Purpose: 1534 * Decode LAG trunk dynamic load balancing flow set size. 1535 * Parameters: 1536 * encoded_value - (IN) Encoded value. 1537 * dynamic_size - (OUT) Number of flow sets. 1538 * Returns: 1539 * BCM_E_xxx 1540 */ 1541 STATIC int 1542 _bcm_tr3_lag_dlb_dynamic_size_decode(int encoded_value, 1543 int *dynamic_size) 1544 { 1545 switch (encoded_value) { 1546 case 1: 1547 *dynamic_size = 512; 1548 break; 1549 case 2: 1550 *dynamic_size = 1024; 1551 break; 1552 case 3: 1553 *dynamic_size = 2048; 1554 break; 1555 case 4: 1556 *dynamic_size = 4096; 1557 break; 1558 case 5: 1559 *dynamic_size = 8192; 1560 break; 1561 case 6: 1562 *dynamic_size = 16384; 1563 break; 1564 case 7: 1565 *dynamic_size = 32768; 1566 break; 1567 default: 1568 return BCM_E_INTERNAL; 1569 } 1570 1571 return BCM_E_NONE; 1572 } 1573 1574 /* 1575 * Function: 1576 * _bcm_tr3_lag_dlb_id_alloc 1577 * Purpose: 1578 * Get a free LAG DLB ID and mark it used. 1579 * Parameters: 1580 * unit - (IN) SOC unit number. 1581 * dlb_id - (OUT) Allocated DLB ID. 1582 * Returns: 1583 * BCM_E_xxx 1584 */ 1585 STATIC int 1586 _bcm_tr3_lag_dlb_id_alloc(int unit, int *dlb_id) 1587 { 1588 int i; 1589 1590 for (i = 0; i < soc_mem_index_count(unit, DLB_LAG_GROUP_CONTROLm); i++) { 1591 if (!_BCM_LAG_DLB_ID_USED_GET(unit, i)) { 1592 _BCM_LAG_DLB_ID_USED_SET(unit, i); 1593 *dlb_id = i; 1594 return BCM_E_NONE; 1595 } 1596 } 1597 1598 return BCM_E_RESOURCE; 1599 } 1600 1601 /* 1602 * Function: 1603 * _bcm_tr3_lag_dlb_id_free 1604 * Purpose: 1605 * Free a LAG DLB ID. 1606 * Parameters: 1607 * unit - (IN) SOC unit number. 1608 * dlb_id - (IN) DLB ID to be freed. 1609 * Returns: 1610 * BCM_E_xxx 1611 */ 1612 STATIC int 1613 _bcm_tr3_lag_dlb_id_free(int unit, int dlb_id) 1614 { 1615 if (dlb_id < 0 || 1616 dlb_id > soc_mem_index_max(unit, DLB_LAG_GROUP_CONTROLm)) { 1617 return BCM_E_PARAM; 1618 } 1619 1620 _BCM_LAG_DLB_ID_USED_CLR(unit, dlb_id); 1621 1622 return BCM_E_NONE; 1623 } 1624 1625 /* 1626 * Function: 1627 * _bcm_tr3_lag_dlb_member_id_alloc 1628 * Purpose: 1629 * Get a free LAG DLB Member ID and mark it used. 1630 * Parameters: 1631 * unit - (IN) SOC unit number. 1632 * member_id - (OUT) Allocated Member ID. 1633 * Returns: 1634 * BCM_E_xxx 1635 */ 1636 STATIC int 1637 _bcm_tr3_lag_dlb_member_id_alloc(int unit, int *member_id) 1638 { 1639 int vla; 1640 int i; 1641 int max_members; 1642 1643 BCM_IF_ERROR_RETURN(bcm_esw_switch_control_get(unit, 1644 bcmSwitchTrunkDynamicAccountingSelect, &vla)); 1645 if (vla) { 1646 max_members = soc_mem_index_count(unit, DLB_LAG_MEMBER_ATTRIBUTEm); 1647 } else { 1648 /* In physical link accounting, the number of members is limited to 1649 * the number of physical ports. 1650 */ 1651 max_members = soc_reg_field_length(unit, DLB_LAG_MEMBER_HW_STATE_64r, 1652 BITMAPf); 1653 } 1654 1655 for (i = 0; i < max_members; i++) { 1656 if (!_BCM_LAG_DLB_MEMBER_ID_USED_GET(unit, i)) { 1657 _BCM_LAG_DLB_MEMBER_ID_USED_SET(unit, i); 1658 *member_id = i; 1659 return BCM_E_NONE; 1660 } 1661 } 1662 1663 return BCM_E_RESOURCE; 1664 } 1665 1666 /* 1667 * Function: 1668 * _bcm_tr3_lag_dlb_member_id_free 1669 * Purpose: 1670 * Free a LAG DLB Member ID. 1671 * Parameters: 1672 * unit - (IN) SOC unit number. 1673 * member_id - (IN) Member ID to be freed. 1674 * Returns: 1675 * BCM_E_xxx 1676 */ 1677 STATIC int 1678 _bcm_tr3_lag_dlb_member_id_free(int unit, int member_id) 1679 { 1680 if (member_id < 0 || member_id > soc_mem_index_max(unit, 1681 DLB_LAG_MEMBER_ATTRIBUTEm)) { 1682 return BCM_E_PARAM; 1683 } 1684 1685 _BCM_LAG_DLB_MEMBER_ID_USED_CLR(unit, member_id); 1686 1687 return BCM_E_NONE; 1688 } 1689 1690 /* 1691 * Function: 1692 * _bcm_tr3_lag_dlb_quality_assign 1693 * Purpose: 1694 * Assign quality based on port loading and queue size. 1695 * Parameters: 1696 * unit - (IN)SOC unit number. 1697 * tx_load_percent - (IN) Percent weight of port loading in determing 1698 * port quality. The remaining percentage is 1699 * the weight of queue size. 1700 * entry_arr - (IN) Array of 64 quality map table entries. 1701 * Returns: 1702 * BCM_X_XXX 1703 */ 1704 STATIC int 1705 _bcm_tr3_lag_dlb_quality_assign(int unit, int tx_load_percent, 1706 uint32 *entry_arr) 1707 { 1708 int quantized_tx_load; 1709 int quantized_qsize; 1710 int quality; 1711 int entry_index; 1712 1713 if (entry_arr == NULL) { 1714 return BCM_E_PARAM; 1715 } 1716 1717 for (quantized_tx_load = 0; quantized_tx_load < 8; quantized_tx_load++) { 1718 for (quantized_qsize = 0; quantized_qsize < 8; quantized_qsize++) { 1719 quality = (quantized_tx_load * tx_load_percent + 1720 quantized_qsize * (100 - tx_load_percent)) / 100; 1721 entry_index = (quantized_tx_load << 3) + quantized_qsize; 1722 soc_DLB_LAG_QUALITY_MAPPINGm_field32_set(unit, 1723 &entry_arr[entry_index], QUALITYf, quality); 1724 } 1725 } 1726 1727 return BCM_E_NONE; 1728 } 1729 1730 /* 1731 * Function: 1732 * _bcm_tr3_lag_dlb_member_quality_map_set 1733 * Purpose: 1734 * Set per-member LAG DLB quality mapping table. 1735 * Parameters: 1736 * unit - (IN) SOC unit number. 1737 * member_id - (IN) Member ID. 1738 * tx_load_percent - (IN) Percent weight of port loading in determing 1739 * port quality. The remaining percentage is 1740 * the weight of queue size. 1741 * Returns: 1742 * BCM_E_xxx 1743 */ 1744 STATIC int 1745 _bcm_tr3_lag_dlb_member_quality_map_set(int unit, int member_id, 1746 int tx_load_percent) 1747 { 1748 soc_profile_mem_t *profile; 1749 soc_mem_t mem; 1750 int entry_bytes; 1751 int entries_per_profile; 1752 int alloc_size; 1753 uint32 *entry_arr; 1754 int rv = BCM_E_NONE; 1755 void *entries; 1756 uint32 base_index; 1757 uint32 old_base_index; 1758 dlb_lag_quality_control_entry_t quality_control_entry; 1759 1760 profile = _tr3_lag_dlb_bk[unit]->lag_dlb_quality_map_profile; 1761 1762 entries_per_profile = 64; 1763 entry_bytes = sizeof(dlb_lag_quality_mapping_entry_t); 1764 alloc_size = entries_per_profile * entry_bytes; 1765 entry_arr = sal_alloc(alloc_size, "LAG DLB Quality Map entries"); 1766 if (entry_arr == NULL) { 1767 return BCM_E_MEMORY; 1768 } 1769 sal_memset(entry_arr, 0, alloc_size); 1770 1771 /* Assign quality in the entry array */ 1772 rv = _bcm_tr3_lag_dlb_quality_assign(unit, tx_load_percent, entry_arr); 1773 if (BCM_FAILURE(rv)) { 1774 sal_free(entry_arr); 1775 return rv; 1776 } 1777 1778 mem = DLB_LAG_QUALITY_MAPPINGm; 1779 soc_mem_lock(unit, mem); 1780 1781 /* Add profile */ 1782 entries = entry_arr; 1783 rv = soc_profile_mem_add(unit, profile, &entries, entries_per_profile, 1784 &base_index); 1785 sal_free(entry_arr); 1786 if (SOC_FAILURE(rv)) { 1787 soc_mem_unlock(unit, mem); 1788 return rv; 1789 } 1790 1791 /* Update member profile pointer */ 1792 rv = READ_DLB_LAG_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY, member_id, 1793 &quality_control_entry); 1794 if (SOC_FAILURE(rv)) { 1795 soc_mem_unlock(unit, mem); 1796 return rv; 1797 } 1798 old_base_index = entries_per_profile * soc_mem_field32_get(unit, 1799 DLB_LAG_QUALITY_CONTROLm, &quality_control_entry, 1800 PROFILE_PTRf); 1801 soc_DLB_LAG_QUALITY_CONTROLm_field32_set(unit, &quality_control_entry, 1802 PROFILE_PTRf, base_index / entries_per_profile); 1803 rv = WRITE_DLB_LAG_QUALITY_CONTROLm(unit, MEM_BLOCK_ALL, member_id, 1804 &quality_control_entry); 1805 if (SOC_FAILURE(rv)) { 1806 soc_mem_unlock(unit, mem); 1807 return rv; 1808 } 1809 1810 /* Delete old profile */ 1811 rv = soc_profile_mem_delete(unit, profile, old_base_index); 1812 soc_mem_unlock(unit, mem); 1813 1814 LAG_DLB_INFO(unit)->lag_dlb_load_weight[base_index/entries_per_profile] = 1815 tx_load_percent; 1816 1817 return rv; 1818 } 1819 1820 /* 1821 * Function: 1822 * bcm_tr3_lag_dlb_free_resource 1823 * Purpose: 1824 * Free resources for a LAG dynamic load balancing group. 1825 * Parameters: 1826 * unit - (IN) SOC unit number. 1827 * dlb_id - (IN) LAG DLB group ID. 1828 * member_info - (IN) Trunk member info. 1829 * Returns: 1830 * BCM_E_xxx 1831 */ 1832 int 1833 bcm_tr3_lag_dlb_free_resource(int unit, int tid) 1834 { 1835 int rv = BCM_E_NONE; 1836 trunk_group_entry_t tg_entry; 1837 int dlb_enable; 1838 int dlb_id; 1839 dlb_lag_group_control_entry_t dlb_lag_group_control_entry; 1840 int entry_base_ptr; 1841 int flow_set_size; 1842 int num_entries; 1843 int block_base_ptr; 1844 int num_blocks; 1845 int vla; 1846 dlb_lag_group_membership_entry_t dlb_lag_group_membership_entry; 1847 int member_bitmap_width; 1848 int alloc_size; 1849 SHR_BITDCL *member_bitmap = NULL; 1850 SHR_BITDCL *status_bitmap = NULL; 1851 SHR_BITDCL *override_bitmap = NULL; 1852 int i; 1853 int reverse_map_index; 1854 dlb_lag_member_attribute_entry_t dlb_lag_member_attribute_entry; 1855 bcm_module_t mod; 1856 bcm_port_t port; 1857 int is_local; 1858 dlb_lag_quality_control_entry_t dlb_lag_quality_control_entry; 1859 dlb_lag_member_sw_state_entry_t dlb_lag_member_sw_state_entry; 1860 1861 SOC_IF_ERROR_RETURN 1862 (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry)); 1863 dlb_enable = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, 1864 GROUP_ENABLEf); 1865 dlb_id = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, 1866 DLB_IDf); 1867 1868 if (!dlb_enable) { 1869 return BCM_E_NONE; 1870 } 1871 1872 /* Clear DLB fields in TRUNK_GROUP table */ 1873 1874 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, GROUP_ENABLEf, 0); 1875 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, DLB_IDf, 0); 1876 SOC_IF_ERROR_RETURN 1877 (WRITE_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, tid, &tg_entry)); 1878 1879 /* Clear VLA quality measure control */ 1880 1881 SOC_IF_ERROR_RETURN(WRITE_DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm(unit, 1882 MEM_BLOCK_ALL, dlb_id, 1883 soc_mem_entry_null(unit, 1884 DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm))); 1885 1886 /* Free flow set table resources */ 1887 1888 SOC_IF_ERROR_RETURN 1889 (READ_DLB_LAG_GROUP_CONTROLm(unit, MEM_BLOCK_ANY, dlb_id, 1890 &dlb_lag_group_control_entry)); 1891 entry_base_ptr = soc_DLB_LAG_GROUP_CONTROLm_field32_get(unit, 1892 &dlb_lag_group_control_entry, FLOW_SET_BASEf); 1893 flow_set_size = soc_DLB_LAG_GROUP_CONTROLm_field32_get(unit, 1894 &dlb_lag_group_control_entry, FLOW_SET_SIZEf); 1895 BCM_IF_ERROR_RETURN 1896 (_bcm_tr3_lag_dlb_dynamic_size_decode(flow_set_size, &num_entries)); 1897 block_base_ptr = entry_base_ptr >> 9; 1898 num_blocks = num_entries >> 9; 1899 _BCM_LAG_DLB_FLOWSET_BLOCK_USED_CLR_RANGE(unit, block_base_ptr, num_blocks); 1900 1901 /* Clear LAG DLB group control */ 1902 1903 SOC_IF_ERROR_RETURN(WRITE_DLB_LAG_GROUP_CONTROLm(unit, 1904 MEM_BLOCK_ALL, dlb_id, 1905 soc_mem_entry_null(unit, DLB_LAG_GROUP_CONTROLm))); 1906 1907 /* Free Member IDs */ 1908 1909 BCM_IF_ERROR_RETURN(bcm_esw_switch_control_get(unit, 1910 bcmSwitchTrunkDynamicAccountingSelect, &vla)); 1911 1912 SOC_IF_ERROR_RETURN(READ_DLB_LAG_GROUP_MEMBERSHIPm(unit, MEM_BLOCK_ANY, 1913 dlb_id, &dlb_lag_group_membership_entry)); 1914 member_bitmap_width = soc_mem_field_length(unit, 1915 DLB_LAG_GROUP_MEMBERSHIPm, MEMBER_BITMAPf); 1916 alloc_size = SHR_BITALLOCSIZE(member_bitmap_width); 1917 member_bitmap = sal_alloc(alloc_size, "DLB LAG member bitmap"); 1918 if (NULL == member_bitmap) { 1919 return BCM_E_MEMORY; 1920 } 1921 sal_memset(member_bitmap, 0, alloc_size); 1922 soc_DLB_LAG_GROUP_MEMBERSHIPm_field_get(unit, 1923 &dlb_lag_group_membership_entry, MEMBER_BITMAPf, member_bitmap); 1924 1925 for (i = 0; i < member_bitmap_width; i++) { 1926 if (SHR_BITGET(member_bitmap, i)) { 1927 1928 /* Clear membership reverse map */ 1929 1930 if (vla) { 1931 reverse_map_index = i; 1932 } else { 1933 rv = READ_DLB_LAG_MEMBER_ATTRIBUTEm(unit, MEM_BLOCK_ANY, i, 1934 &dlb_lag_member_attribute_entry); 1935 if (BCM_FAILURE(rv)) { 1936 goto error; 1937 } 1938 mod = soc_DLB_LAG_MEMBER_ATTRIBUTEm_field32_get(unit, 1939 &dlb_lag_member_attribute_entry, MODULE_IDf); 1940 port = soc_DLB_LAG_MEMBER_ATTRIBUTEm_field32_get(unit, 1941 &dlb_lag_member_attribute_entry, PORT_NUMf); 1942 rv = _bcm_esw_modid_is_local(unit, mod, &is_local); 1943 if (BCM_FAILURE(rv)) { 1944 goto error; 1945 } 1946 if (!is_local) { 1947 rv = BCM_E_INTERNAL; 1948 goto error; 1949 } 1950 reverse_map_index = port; 1951 } 1952 rv = WRITE_DLB_LAG_MEMBERSHIP_REVERSE_MAPm(unit, MEM_BLOCK_ALL, 1953 reverse_map_index, soc_mem_entry_null(unit, 1954 DLB_LAG_MEMBERSHIP_REVERSE_MAPm)); 1955 if (BCM_FAILURE(rv)) { 1956 goto error; 1957 } 1958 1959 /* Clear member attribute */ 1960 1961 rv = WRITE_DLB_LAG_MEMBER_ATTRIBUTEm(unit, MEM_BLOCK_ALL, i, 1962 soc_mem_entry_null(unit, DLB_LAG_MEMBER_ATTRIBUTEm)); 1963 if (BCM_FAILURE(rv)) { 1964 goto error; 1965 } 1966 1967 /* Revert member quality mapping profile to default */ 1968 1969 rv = _bcm_tr3_lag_dlb_member_quality_map_set(unit, i, 100); 1970 if (BCM_FAILURE(rv)) { 1971 goto error; 1972 } 1973 1974 /* Clear threshold scaling factors */ 1975 1976 rv = READ_DLB_LAG_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY, i, 1977 &dlb_lag_quality_control_entry); 1978 if (BCM_FAILURE(rv)) { 1979 goto error; 1980 } 1981 soc_DLB_LAG_QUALITY_CONTROLm_field32_set(unit, 1982 &dlb_lag_quality_control_entry, LOADING_SCALING_FACTORf, 0); 1983 soc_DLB_LAG_QUALITY_CONTROLm_field32_set(unit, 1984 &dlb_lag_quality_control_entry, QSIZE_SCALING_FACTORf, 0); 1985 rv = WRITE_DLB_LAG_QUALITY_CONTROLm(unit, MEM_BLOCK_ALL, i, 1986 &dlb_lag_quality_control_entry); 1987 if (BCM_FAILURE(rv)) { 1988 goto error; 1989 } 1990 1991 /* Free member ID */ 1992 1993 rv = _bcm_tr3_lag_dlb_member_id_free(unit, i); 1994 if (BCM_FAILURE(rv)) { 1995 goto error; 1996 } 1997 } 1998 } 1999 2000 /* Clear member software state */ 2001 2002 rv = READ_DLB_LAG_MEMBER_SW_STATEm(unit, MEM_BLOCK_ANY, 0, 2003 &dlb_lag_member_sw_state_entry); 2004 if (BCM_FAILURE(rv)) { 2005 goto error; 2006 } 2007 2008 status_bitmap = sal_alloc(alloc_size, "DLB LAG member status bitmap"); 2009 if (NULL == status_bitmap) { 2010 rv = BCM_E_MEMORY; 2011 goto error; 2012 } 2013 soc_DLB_LAG_MEMBER_SW_STATEm_field_get(unit, 2014 &dlb_lag_member_sw_state_entry, MEMBER_BITMAPf, status_bitmap); 2015 SHR_BITREMOVE_RANGE(status_bitmap, member_bitmap, 0, member_bitmap_width, 2016 status_bitmap); 2017 soc_DLB_LAG_MEMBER_SW_STATEm_field_set(unit, 2018 &dlb_lag_member_sw_state_entry, MEMBER_BITMAPf, status_bitmap); 2019 2020 override_bitmap = sal_alloc(alloc_size, "DLB LAG member override bitmap"); 2021 if (NULL == override_bitmap) { 2022 rv = BCM_E_MEMORY; 2023 goto error; 2024 } 2025 soc_DLB_LAG_MEMBER_SW_STATEm_field_get(unit, 2026 &dlb_lag_member_sw_state_entry, OVERRIDE_MEMBER_BITMAPf, override_bitmap); 2027 SHR_BITREMOVE_RANGE(override_bitmap, member_bitmap, 0, member_bitmap_width, 2028 override_bitmap); 2029 soc_DLB_LAG_MEMBER_SW_STATEm_field_set(unit, 2030 &dlb_lag_member_sw_state_entry, OVERRIDE_MEMBER_BITMAPf, override_bitmap); 2031 2032 rv = WRITE_DLB_LAG_MEMBER_SW_STATEm(unit, MEM_BLOCK_ALL, 0, 2033 &dlb_lag_member_sw_state_entry); 2034 if (BCM_FAILURE(rv)) { 2035 goto error; 2036 } 2037 2038 sal_free(member_bitmap); 2039 sal_free(status_bitmap); 2040 sal_free(override_bitmap); 2041 2042 /* Clear group membership */ 2043 2044 SOC_IF_ERROR_RETURN(WRITE_DLB_LAG_GROUP_MEMBERSHIPm(unit, 2045 MEM_BLOCK_ALL, dlb_id, 2046 soc_mem_entry_null(unit, DLB_LAG_GROUP_MEMBERSHIPm))); 2047 2048 /* Free DLB ID */ 2049 2050 BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_id_free(unit, dlb_id)); 2051 2052 return rv; 2053 2054 error: 2055 if (NULL != member_bitmap) { 2056 sal_free(member_bitmap); 2057 } 2058 if (NULL != status_bitmap) { 2059 sal_free(status_bitmap); 2060 } 2061 if (NULL != override_bitmap) { 2062 sal_free(override_bitmap); 2063 } 2064 return rv; 2065 } 2066 2067 /* 2068 * Function: 2069 * _bcm_tr3_lag_dlb_member_id_array_get 2070 * Purpose: 2071 * Get member IDs for each LAG member. 2072 * Parameters: 2073 * unit - (IN) SOC unit number. 2074 * dlb_id - (IN) DLB group ID. 2075 * num_dlb_ports - (IN) Number of DLB ports. 2076 * mod_array - (IN) Array of module IDs. 2077 * port_array - (IN) Array of port numbers. 2078 * scaling_factor_array - (IN) Array of scaling factors. 2079 * load_weight_array - (IN) Array of load weights. 2080 * member_id_array - (OUT) Array of member IDs. 2081 * Returns: 2082 * BCM_E_xxx 2083 */ 2084 STATIC int 2085 _bcm_tr3_lag_dlb_member_id_array_get(int unit, int dlb_id, int num_dlb_ports, 2086 bcm_module_t *mod_array, bcm_port_t *port_array, 2087 int *scaling_factor_array, int *load_weight_array, 2088 int *member_id_array) 2089 { 2090 int rv = BCM_E_NONE; 2091 int vla; 2092 int i; 2093 dlb_lag_membership_reverse_map_entry_t member_reverse_map_entry; 2094 dlb_lag_member_attribute_entry_t member_attribute_entry; 2095 int is_local; 2096 dlb_lag_quality_control_entry_t dlb_lag_quality_control_entry; 2097 port_tab_entry_t ptab; 2098 int hw_mask; 2099 2100 BCM_IF_ERROR_RETURN(bcm_esw_switch_control_get(unit, 2101 bcmSwitchTrunkDynamicAccountingSelect, &vla)); 2102 2103 for (i = 0; i < num_dlb_ports; i++) { 2104 BCM_IF_ERROR_RETURN 2105 (_bcm_tr3_lag_dlb_member_id_alloc(unit, &member_id_array[i])); 2106 2107 /* Set member reverse map */ 2108 2109 sal_memset(&member_reverse_map_entry, 0, 2110 sizeof(dlb_lag_membership_reverse_map_entry_t)); 2111 if (vla) { /* Virtual link accounting */ 2112 soc_DLB_LAG_MEMBERSHIP_REVERSE_MAPm_field32_set(unit, 2113 &member_reverse_map_entry, VALIDf, 1); 2114 soc_DLB_LAG_MEMBERSHIP_REVERSE_MAPm_field32_set(unit, 2115 &member_reverse_map_entry, GROUP_IDf, dlb_id); 2116 soc_DLB_LAG_MEMBERSHIP_REVERSE_MAPm_field32_set(unit, 2117 &member_reverse_map_entry, MEMBER_COUNTf, 2118 num_dlb_ports - 1); 2119 SOC_IF_ERROR_RETURN(WRITE_DLB_LAG_MEMBERSHIP_REVERSE_MAPm(unit, 2120 MEM_BLOCK_ALL, member_id_array[i], 2121 &member_reverse_map_entry)); 2122 } else { /* Physical link accounting */ 2123 BCM_IF_ERROR_RETURN 2124 (_bcm_esw_modid_is_local(unit, mod_array[i], &is_local)); 2125 if (!is_local) { 2126 /* In physical link accounting mode, LAG members should be 2127 * local. 2128 */ 2129 return BCM_E_PARAM; 2130 } 2131 soc_DLB_LAG_MEMBERSHIP_REVERSE_MAPm_field32_set(unit, 2132 &member_reverse_map_entry, VALIDf, 1); 2133 soc_DLB_LAG_MEMBERSHIP_REVERSE_MAPm_field32_set(unit, 2134 &member_reverse_map_entry, 2135 MEMBER_IDf, member_id_array[i]); 2136 SOC_IF_ERROR_RETURN 2137 (READ_PORT_TABm(unit, MEM_BLOCK_ANY, port_array[i], &ptab)); 2138 if (soc_PORT_TABm_field32_get(unit, &ptab, PORT_TYPEf) == 3) { 2139 /* Port is an embedded Higig port */ 2140 soc_DLB_LAG_MEMBERSHIP_REVERSE_MAPm_field32_set(unit, 2141 &member_reverse_map_entry, EMBEDDED_HGf, 1); 2142 } 2143 SOC_IF_ERROR_RETURN(WRITE_DLB_LAG_MEMBERSHIP_REVERSE_MAPm(unit, 2144 MEM_BLOCK_ALL, port_array[i], 2145 &member_reverse_map_entry)); 2146 } 2147 2148 /* Set member attribute */ 2149 2150 sal_memset(&member_attribute_entry, 0, 2151 sizeof(dlb_lag_member_attribute_entry_t)); 2152 soc_DLB_LAG_MEMBER_ATTRIBUTEm_field32_set(unit, 2153 &member_attribute_entry, MODULE_IDf, mod_array[i]); 2154 soc_DLB_LAG_MEMBER_ATTRIBUTEm_field32_set(unit, 2155 &member_attribute_entry, PORT_NUMf, port_array[i]); 2156 SOC_IF_ERROR_RETURN(WRITE_DLB_LAG_MEMBER_ATTRIBUTEm(unit, 2157 MEM_BLOCK_ALL, member_id_array[i], 2158 &member_attribute_entry)); 2159 2160 /* Set member quality mapping profile */ 2161 2162 BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_member_quality_map_set(unit, 2163 member_id_array[i], load_weight_array[i])); 2164 2165 /* Set threshold scaling factors */ 2166 2167 SOC_IF_ERROR_RETURN(READ_DLB_LAG_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY, 2168 member_id_array[i], &dlb_lag_quality_control_entry)); 2169 hw_mask = (1 << soc_mem_field_length(unit, DLB_LAG_QUALITY_CONTROLm, 2170 LOADING_SCALING_FACTORf)) - 1; 2171 soc_DLB_LAG_QUALITY_CONTROLm_field32_set(unit, 2172 &dlb_lag_quality_control_entry, LOADING_SCALING_FACTORf, 2173 scaling_factor_array[i] & hw_mask); 2174 hw_mask = (1 << soc_mem_field_length(unit, DLB_LAG_QUALITY_CONTROLm, 2175 QSIZE_SCALING_FACTORf)) - 1; 2176 soc_DLB_LAG_QUALITY_CONTROLm_field32_set(unit, 2177 &dlb_lag_quality_control_entry, QSIZE_SCALING_FACTORf, 2178 scaling_factor_array[i] & hw_mask); 2179 SOC_IF_ERROR_RETURN(WRITE_DLB_LAG_QUALITY_CONTROLm(unit, MEM_BLOCK_ALL, 2180 member_id_array[i], &dlb_lag_quality_control_entry)); 2181 } 2182 2183 return rv; 2184 } 2185 2186 /* 2187 * Function: 2188 * bcm_tr3_lag_dlb_set 2189 * Purpose: 2190 * Configure a LAG dynamic load balancing group. 2191 * Parameters: 2192 * unit - (IN) SOC unit number. 2193 * tid - (IN) Trunk group ID. 2194 * add_info - (IN) Pointer to trunk add info structure. 2195 * num_dlb_ports - (IN) Number of trunk member ports eligible for 2196 * LAG DLB 2197 * mod_array - (IN) Array of module IDs 2198 * port_array - (IN) Array of port IDs 2199 * scaling_factor_array - (IN) Array of scaling factors. 2200 * load_weight_array - (IN) Array of load weights. 2201 * Returns: 2202 * BCM_E_xxx 2203 */ 2204 int 2205 bcm_tr3_lag_dlb_set(int unit, int tid, _esw_trunk_add_info_t *add_info, 2206 int num_dlb_ports, int *mod_array, int *port_array, 2207 int *scaling_factor_array, int *load_weight_array) 2208 { 2209 int rv = BCM_E_NONE; 2210 int dlb_enable; 2211 int dlb_id; 2212 int *member_id_array = NULL; 2213 soc_mem_t flowset_mem; 2214 int flowset_entry_size; 2215 dlb_lag_flowset_entry_t *flowset_entry; 2216 int num_blocks; 2217 int total_blocks; 2218 int max_block_base_ptr; 2219 int block_base_ptr; 2220 SHR_BITDCL occupied; 2221 int entry_base_ptr; 2222 int num_entries_per_block; 2223 int alloc_size; 2224 uint32 *block_ptr = NULL; 2225 int i, k; 2226 int index_min, index_max; 2227 dlb_lag_group_control_entry_t dlb_lag_group_control_entry; 2228 int flow_set_size; 2229 int dlb_mode; 2230 dlb_lag_group_membership_entry_t dlb_lag_group_membership_entry; 2231 SHR_BITDCL *member_bitmap = NULL; 2232 SHR_BITDCL *status_bitmap = NULL; 2233 SHR_BITDCL *override_bitmap = NULL; 2234 dlb_lag_member_sw_state_entry_t dlb_lag_member_sw_state_entry; 2235 int vla; 2236 dlb_lag_vla_quality_measure_control_entry_t vla_quality_measure_control_entry; 2237 trunk_group_entry_t tg_entry; 2238 int member_bitmap_width; 2239 2240 dlb_enable = (add_info->psc == BCM_TRUNK_PSC_DYNAMIC) || 2241 (add_info->psc == BCM_TRUNK_PSC_DYNAMIC_ASSIGNED) || 2242 (add_info->psc == BCM_TRUNK_PSC_DYNAMIC_OPTIMAL); 2243 2244 if (!dlb_enable) { 2245 return BCM_E_NONE; 2246 } 2247 2248 /* Allocate a DLB ID */ 2249 2250 BCM_IF_ERROR_RETURN(_bcm_tr3_lag_dlb_id_alloc(unit, &dlb_id)); 2251 2252 /* Allocate member IDs */ 2253 2254 member_id_array = sal_alloc(sizeof(int) * num_dlb_ports, 2255 "LAG DLB Member IDs"); 2256 if (NULL == member_id_array) { 2257 rv = BCM_E_MEMORY; 2258 goto error; 2259 } 2260 rv = _bcm_tr3_lag_dlb_member_id_array_get(unit, dlb_id, num_dlb_ports, 2261 mod_array, port_array, scaling_factor_array, load_weight_array, 2262 member_id_array); 2263 if (BCM_FAILURE(rv)) { 2264 goto error; 2265 } 2266 2267 /* Set group membership table */ 2268 2269 member_bitmap_width = soc_mem_field_length(unit, 2270 DLB_LAG_GROUP_MEMBERSHIPm, MEMBER_BITMAPf); 2271 alloc_size = SHR_BITALLOCSIZE(member_bitmap_width); 2272 member_bitmap = sal_alloc(alloc_size, "DLB LAG member bitmap"); 2273 if (NULL == member_bitmap) { 2274 rv = BCM_E_MEMORY; 2275 goto error; 2276 } 2277 sal_memset(member_bitmap, 0, alloc_size); 2278 for (i = 0; i < num_dlb_ports; i++) { 2279 SHR_BITSET(member_bitmap, member_id_array[i]); 2280 } 2281 2282 sal_memset(&dlb_lag_group_membership_entry, 0, 2283 sizeof(dlb_lag_group_membership_entry_t)); 2284 soc_DLB_LAG_GROUP_MEMBERSHIPm_field_set(unit, 2285 &dlb_lag_group_membership_entry, MEMBER_BITMAPf, member_bitmap); 2286 rv = WRITE_DLB_LAG_GROUP_MEMBERSHIPm(unit, MEM_BLOCK_ALL, dlb_id, 2287 &dlb_lag_group_membership_entry); 2288 if (SOC_FAILURE(rv)) { 2289 goto error; 2290 } 2291 2292 /* Set member software state */ 2293 2294 rv = bcm_esw_switch_control_get(unit, 2295 bcmSwitchTrunkDynamicAccountingSelect, &vla); 2296 if (SOC_FAILURE(rv)) { 2297 goto error; 2298 } 2299 2300 rv = READ_DLB_LAG_MEMBER_SW_STATEm(unit, MEM_BLOCK_ANY, 0, 2301 &dlb_lag_member_sw_state_entry); 2302 if (BCM_FAILURE(rv)) { 2303 goto error; 2304 } 2305 2306 status_bitmap = sal_alloc(alloc_size, "DLB LAG member status bitmap"); 2307 if (NULL == status_bitmap) { 2308 rv = BCM_E_MEMORY; 2309 goto error; 2310 } 2311 soc_DLB_LAG_MEMBER_SW_STATEm_field_get(unit, 2312 &dlb_lag_member_sw_state_entry, MEMBER_BITMAPf, status_bitmap); 2313 2314 if (vla) { 2315 SHR_BITOR_RANGE(status_bitmap, member_bitmap, 0, member_bitmap_width, 2316 status_bitmap); 2317 } else { 2318 SHR_BITREMOVE_RANGE(status_bitmap, member_bitmap, 0, member_bitmap_width, 2319 status_bitmap); 2320 } 2321 soc_DLB_LAG_MEMBER_SW_STATEm_field_set(unit, 2322 &dlb_lag_member_sw_state_entry, MEMBER_BITMAPf, status_bitmap); 2323 2324 override_bitmap = sal_alloc(alloc_size, "DLB LAG member override bitmap"); 2325 if (NULL == override_bitmap) { 2326 rv = BCM_E_MEMORY; 2327 goto error; 2328 } 2329 soc_DLB_LAG_MEMBER_SW_STATEm_field_get(unit, 2330 &dlb_lag_member_sw_state_entry, OVERRIDE_MEMBER_BITMAPf, 2331 override_bitmap); 2332 2333 if (vla) { 2334 SHR_BITOR_RANGE(override_bitmap, member_bitmap, 0, member_bitmap_width, 2335 override_bitmap); 2336 } else { 2337 SHR_BITREMOVE_RANGE(override_bitmap, member_bitmap, 0, member_bitmap_width, 2338 override_bitmap); 2339 } 2340 soc_DLB_LAG_MEMBER_SW_STATEm_field_set(unit, 2341 &dlb_lag_member_sw_state_entry, OVERRIDE_MEMBER_BITMAPf, override_bitmap); 2342 2343 rv = WRITE_DLB_LAG_MEMBER_SW_STATEm(unit, MEM_BLOCK_ALL, 0, 2344 &dlb_lag_member_sw_state_entry); 2345 if (BCM_FAILURE(rv)) { 2346 goto error; 2347 } 2348 2349 /* Set DLB flow set table */ 2350 2351 flowset_mem = DLB_LAG_FLOWSETm; 2352 flowset_entry_size = sizeof(dlb_lag_flowset_entry_t); 2353 num_blocks = add_info->dynamic_size >> 9; 2354 total_blocks = soc_mem_index_count(unit, flowset_mem) >> 9; 2355 max_block_base_ptr = total_blocks - num_blocks; 2356 for (block_base_ptr = 0; 2357 block_base_ptr <= max_block_base_ptr; 2358 block_base_ptr++) { 2359 /* Check if the contiguous region of flow set table from 2360 * block_base_ptr to (block_base_ptr + num_blocks - 1) is free. 2361 */ 2362 _BCM_LAG_DLB_FLOWSET_BLOCK_TEST_RANGE(unit, block_base_ptr, num_blocks, 2363 occupied); 2364 if (!occupied) { 2365 break; 2366 } 2367 } 2368 if (block_base_ptr > max_block_base_ptr) { 2369 /* A contiguous region of the desired size could not be found in 2370 * flow set table. 2371 */ 2372 rv = BCM_E_RESOURCE; 2373 goto error; 2374 } 2375 2376 entry_base_ptr = block_base_ptr << 9; 2377 num_entries_per_block = 512; 2378 alloc_size = num_entries_per_block * flowset_entry_size; 2379 block_ptr = soc_cm_salloc(unit, alloc_size, 2380 "Block of DLB_LAG_FLOWSET entries"); 2381 if (NULL == block_ptr) { 2382 rv = BCM_E_MEMORY; 2383 goto error; 2384 } 2385 sal_memset(block_ptr, 0, alloc_size); 2386 for (i = 0; i < num_blocks; i++) { 2387 for (k = 0; k < num_entries_per_block; k++) { 2388 flowset_entry = soc_mem_table_idx_to_pointer(unit, 2389 DLB_LAG_FLOWSETm, dlb_lag_flowset_entry_t *, 2390 block_ptr, k); 2391 soc_DLB_LAG_FLOWSETm_field32_set(unit, flowset_entry, 2392 VALIDf, 1); 2393 soc_DLB_LAG_FLOWSETm_field32_set(unit, flowset_entry, 2394 MEMBER_IDf, 2395 member_id_array[(i * num_entries_per_block + k) 2396 % num_dlb_ports]); 2397 } 2398 index_min = entry_base_ptr + i * num_entries_per_block; 2399 index_max = index_min + num_entries_per_block - 1; 2400 rv = soc_mem_write_range(unit, flowset_mem, MEM_BLOCK_ALL, 2401 index_min, index_max, block_ptr); 2402 if (SOC_FAILURE(rv)) { 2403 goto error; 2404 } 2405 } 2406 2407 _BCM_LAG_DLB_FLOWSET_BLOCK_USED_SET_RANGE(unit, block_base_ptr, num_blocks); 2408 2409 /* Set LAG DLB group control table */ 2410 2411 sal_memset(&dlb_lag_group_control_entry, 0, 2412 sizeof(dlb_lag_group_control_entry_t)); 2413 soc_DLB_LAG_GROUP_CONTROLm_field32_set(unit, &dlb_lag_group_control_entry, 2414 ENABLE_OPTIMAL_CANDIDATE_UPDATEf, 1); 2415 soc_DLB_LAG_GROUP_CONTROLm_field32_set(unit, &dlb_lag_group_control_entry, 2416 FLOW_SET_BASEf, entry_base_ptr); 2417 2418 rv = bcm_tr3_lag_dlb_dynamic_size_encode(add_info->dynamic_size, 2419 &flow_set_size); 2420 if (SOC_FAILURE(rv)) { 2421 goto error; 2422 } 2423 soc_DLB_LAG_GROUP_CONTROLm_field32_set(unit, &dlb_lag_group_control_entry, 2424 FLOW_SET_SIZEf, flow_set_size); 2425 2426 switch (add_info->psc) { 2427 case BCM_TRUNK_PSC_DYNAMIC: 2428 dlb_mode = 0; 2429 break; 2430 case BCM_TRUNK_PSC_DYNAMIC_ASSIGNED: 2431 dlb_mode = 1; 2432 break; 2433 case BCM_TRUNK_PSC_DYNAMIC_OPTIMAL: 2434 dlb_mode = 2; 2435 break; 2436 default: 2437 rv = BCM_E_PARAM; 2438 goto error; 2439 } 2440 soc_DLB_LAG_GROUP_CONTROLm_field32_set(unit, &dlb_lag_group_control_entry, 2441 MEMBER_ASSIGNMENT_MODEf, dlb_mode); 2442 2443 soc_DLB_LAG_GROUP_CONTROLm_field32_set(unit, &dlb_lag_group_control_entry, 2444 INACTIVITY_DURATIONf, add_info->dynamic_age); 2445 2446 rv = WRITE_DLB_LAG_GROUP_CONTROLm(unit, MEM_BLOCK_ALL, dlb_id, 2447 &dlb_lag_group_control_entry); 2448 if (SOC_FAILURE(rv)) { 2449 goto error; 2450 } 2451 2452 /* Set VLA quality measure control */ 2453 2454 if (vla) { 2455 sal_memset(&vla_quality_measure_control_entry, 0, 2456 sizeof(dlb_lag_vla_quality_measure_control_entry_t)); 2457 soc_DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm_field32_set(unit, 2458 &vla_quality_measure_control_entry, 2459 ENABLE_GROUP_AVG_CALCf, 1); 2460 soc_DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm_field32_set(unit, 2461 &vla_quality_measure_control_entry, 2462 VLA_WEIGHT_LOADINGf, add_info->dynamic_load_exponent); 2463 soc_DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm_field32_set(unit, 2464 &vla_quality_measure_control_entry, 2465 VLA_WEIGHT_EXPECTED_LOADINGf, 2466 add_info->dynamic_expected_load_exponent); 2467 soc_DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm_field32_set(unit, 2468 &vla_quality_measure_control_entry, 2469 VLA_CAP_LOADING_AVGf, (add_info->flags & 2470 BCM_TRUNK_FLAG_DYNAMIC_LOAD_DECREASE_RESET) ? 1 : 0); 2471 soc_DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm_field32_set(unit, 2472 &vla_quality_measure_control_entry, 2473 VLA_CAP_EXPECTED_LOADINGf, (add_info->flags & 2474 BCM_TRUNK_FLAG_DYNAMIC_EXPECTED_LOAD_DECREASE_RESET) ? 2475 1 : 0); 2476 rv = WRITE_DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm(unit, MEM_BLOCK_ALL, 2477 dlb_id, &vla_quality_measure_control_entry); 2478 if (SOC_FAILURE(rv)) { 2479 goto error; 2480 } 2481 } 2482 2483 /* Update trunk group table */ 2484 2485 rv = READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry); 2486 if (SOC_FAILURE(rv)) { 2487 goto error; 2488 } 2489 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, GROUP_ENABLEf, 1); 2490 soc_TRUNK_GROUPm_field32_set(unit, &tg_entry, DLB_IDf, dlb_id); 2491 rv = WRITE_TRUNK_GROUPm(unit, MEM_BLOCK_ALL, tid, &tg_entry); 2492 if (SOC_FAILURE(rv)) { 2493 goto error; 2494 } 2495 2496 sal_free(member_id_array); 2497 soc_cm_sfree(unit, block_ptr); 2498 sal_free(member_bitmap); 2499 sal_free(status_bitmap); 2500 sal_free(override_bitmap); 2501 2502 return rv; 2503 2504 error: 2505 if (NULL != member_id_array) { 2506 sal_free(member_id_array); 2507 } 2508 if (NULL != block_ptr) { 2509 soc_cm_sfree(unit, block_ptr); 2510 } 2511 if (NULL != member_bitmap) { 2512 sal_free(member_bitmap); 2513 } 2514 if (NULL != status_bitmap) { 2515 sal_free(status_bitmap); 2516 } 2517 if (NULL != override_bitmap) { 2518 sal_free(override_bitmap); 2519 } 2520 return rv; 2521 } 2522 2523 /* 2524 * Function: 2525 * _bcm_tr3_lag_dlb_member_id_get 2526 * Purpose: 2527 * Get LAG DLB member ID based on module ID and port. 2528 * Parameters: 2529 * unit - (IN) SOC unit number. 2530 * mod - (IN) Module ID of the member. 2531 * port - (IN) Port number of the member. 2532 * member_id - (OUT) Member ID. 2533 * Returns: 2534 * BCM_E_xxx 2535 */ 2536 STATIC int 2537 _bcm_tr3_lag_dlb_member_id_get(int unit, bcm_module_t mod, bcm_port_t port, 2538 int *member_id) 2539 { 2540 int match; 2541 int i; 2542 dlb_lag_member_attribute_entry_t member_attr_entry; 2543 2544 match = FALSE; 2545 for (i = 0; i < soc_mem_index_count(unit, DLB_LAG_MEMBER_ATTRIBUTEm); i++) { 2546 SOC_IF_ERROR_RETURN(READ_DLB_LAG_MEMBER_ATTRIBUTEm(unit, MEM_BLOCK_ANY, 2547 i, &member_attr_entry)); 2548 if ((mod == soc_DLB_LAG_MEMBER_ATTRIBUTEm_field32_get(unit, 2549 &member_attr_entry, MODULE_IDf)) && 2550 (port == soc_DLB_LAG_MEMBER_ATTRIBUTEm_field32_get(unit, 2551 &member_attr_entry, PORT_NUMf))) { 2552 match = TRUE; 2553 *member_id = i; 2554 break; 2555 } 2556 } 2557 if (!match) { 2558 return BCM_E_NOT_FOUND; 2559 } 2560 2561 return BCM_E_NONE; 2562 } 2563 2564 2565 /* 2566 * Function: 2567 * bcm_tr3_lag_dlb_member_attr_get 2568 * Purpose: 2569 * Get attributes of a LAG DLB member. 2570 * Parameters: 2571 * unit - (IN) SOC unit number. 2572 * mod - (IN) Module ID of the member. 2573 * port - (IN) Port number of the member. 2574 * scaling_factor - (OUT) Member's scaling factor. 2575 * load_weight - (OUT) Member's load weight. 2576 * Returns: 2577 * BCM_E_xxx 2578 */ 2579 int 2580 bcm_tr3_lag_dlb_member_attr_get(int unit, bcm_module_t mod, bcm_port_t port, 2581 int *scaling_factor, int *load_weight) 2582 { 2583 int member_id; 2584 dlb_lag_quality_control_entry_t quality_control_entry; 2585 int profile_ptr; 2586 2587 /* Find member ID of the given module and port */ 2588 BCM_IF_ERROR_RETURN 2589 (_bcm_tr3_lag_dlb_member_id_get(unit, mod, port, &member_id)); 2590 2591 /* Get member's scaling factor and load weight */ 2592 SOC_IF_ERROR_RETURN(READ_DLB_LAG_QUALITY_CONTROLm(unit, MEM_BLOCK_ANY, 2593 member_id, &quality_control_entry)); 2594 *scaling_factor = soc_DLB_LAG_QUALITY_CONTROLm_field32_get(unit, 2595 &quality_control_entry, LOADING_SCALING_FACTORf); 2596 profile_ptr = soc_DLB_LAG_QUALITY_CONTROLm_field32_get(unit, 2597 &quality_control_entry, PROFILE_PTRf); 2598 *load_weight = LAG_DLB_INFO(unit)->lag_dlb_load_weight[profile_ptr]; 2599 2600 return BCM_E_NONE; 2601 } 2602 2603 /* 2604 * Function: 2605 * bcm_tr3_lag_dlb_member_status_set 2606 * Purpose: 2607 * Set LAG DLB member status. 2608 * Parameters: 2609 * unit - (IN) SOC unit number. 2610 * mod - (IN) Member module ID. 2611 * port - (IN) Member port number. 2612 * status - (IN) Member status. 2613 * Returns: 2614 * BCM_E_xxx 2615 */ 2616 int 2617 bcm_tr3_lag_dlb_member_status_set(int unit, bcm_module_t mod, bcm_port_t port, 2618 int status) 2619 { 2620 int member_id; 2621 dlb_lag_member_sw_state_entry_t sw_state_entry; 2622 int member_bitmap_width, alloc_size; 2623 SHR_BITDCL *status_bitmap = NULL; 2624 SHR_BITDCL *override_bitmap = NULL; 2625 2626 BCM_IF_ERROR_RETURN 2627 (_bcm_tr3_lag_dlb_member_id_get(unit, mod, port, &member_id)); 2628 2629 /* Get status bitmap */ 2630 SOC_IF_ERROR_RETURN(READ_DLB_LAG_MEMBER_SW_STATEm(unit, MEM_BLOCK_ANY, 0, 2631 &sw_state_entry)); 2632 member_bitmap_width = soc_mem_field_length(unit, DLB_LAG_MEMBER_SW_STATEm, 2633 MEMBER_BITMAPf); 2634 alloc_size = SHR_BITALLOCSIZE(member_bitmap_width); 2635 status_bitmap = sal_alloc(alloc_size, "DLB LAG member status bitmap"); 2636 if (NULL == status_bitmap) { 2637 return BCM_E_MEMORY; 2638 } 2639 soc_DLB_LAG_MEMBER_SW_STATEm_field_get(unit, &sw_state_entry, 2640 MEMBER_BITMAPf, status_bitmap); 2641 2642 /* Get override bitmap */ 2643 override_bitmap = sal_alloc(alloc_size, "DLB LAG member override bitmap"); 2644 if (NULL == override_bitmap) { 2645 sal_free(status_bitmap); 2646 return BCM_E_MEMORY; 2647 } 2648 soc_DLB_LAG_MEMBER_SW_STATEm_field_get(unit, &sw_state_entry, 2649 OVERRIDE_MEMBER_BITMAPf, override_bitmap); 2650 2651 /* Update status and override bitmaps */ 2652 switch (status) { 2653 case BCM_TRUNK_DYNAMIC_MEMBER_FORCE_DOWN: 2654 SHR_BITSET(override_bitmap, member_id); 2655 SHR_BITCLR(status_bitmap, member_id); 2656 break; 2657 case BCM_TRUNK_DYNAMIC_MEMBER_FORCE_UP: 2658 SHR_BITSET(override_bitmap, member_id); 2659 SHR_BITSET(status_bitmap, member_id); 2660 break; 2661 case BCM_TRUNK_DYNAMIC_MEMBER_HW: 2662 SHR_BITCLR(override_bitmap, member_id); 2663 SHR_BITCLR(status_bitmap, member_id); 2664 break; 2665 default: 2666 sal_free(status_bitmap); 2667 sal_free(override_bitmap); 2668 return BCM_E_PARAM; 2669 } 2670 2671 /* Write status and override bitmaps to hardware */ 2672 soc_DLB_LAG_MEMBER_SW_STATEm_field_set(unit, &sw_state_entry, 2673 MEMBER_BITMAPf, status_bitmap); 2674 soc_DLB_LAG_MEMBER_SW_STATEm_field_set(unit, &sw_state_entry, 2675 OVERRIDE_MEMBER_BITMAPf, override_bitmap); 2676 sal_free(status_bitmap); 2677 sal_free(override_bitmap); 2678 SOC_IF_ERROR_RETURN(WRITE_DLB_LAG_MEMBER_SW_STATEm(unit, MEM_BLOCK_ALL, 0, 2679 &sw_state_entry)); 2680 2681 return BCM_E_NONE; 2682 } 2683 2684 /* 2685 * Function: 2686 * bcm_tr3_lag_dlb_member_status_get 2687 * Purpose: 2688 * Get LAG DLB member status. 2689 * Parameters: 2690 * unit - (IN) SOC unit number. 2691 * mod - (IN) Member module ID. 2692 * port - (IN) Member port number. 2693 * status - (OUT) Member status. 2694 * Returns: 2695 * BCM_E_xxx 2696 */ 2697 int 2698 bcm_tr3_lag_dlb_member_status_get(int unit, bcm_module_t mod, bcm_port_t port, 2699 int *status) 2700 { 2701 int member_id; 2702 dlb_lag_member_sw_state_entry_t sw_state_entry; 2703 int member_bitmap_width, alloc_size; 2704 SHR_BITDCL *status_bitmap = NULL; 2705 SHR_BITDCL *override_bitmap = NULL; 2706 uint64 hw_state, hw_status_bitmap; 2707 uint32 bitmap32; 2708 int rv = BCM_E_NONE; 2709 2710 BCM_IF_ERROR_RETURN 2711 (_bcm_tr3_lag_dlb_member_id_get(unit, mod, port, &member_id)); 2712 2713 /* Get status bitmap */ 2714 SOC_IF_ERROR_RETURN(READ_DLB_LAG_MEMBER_SW_STATEm(unit, MEM_BLOCK_ANY, 0, 2715 &sw_state_entry)); 2716 member_bitmap_width = soc_mem_field_length(unit, DLB_LAG_MEMBER_SW_STATEm, 2717 MEMBER_BITMAPf); 2718 alloc_size = SHR_BITALLOCSIZE(member_bitmap_width); 2719 status_bitmap = sal_alloc(alloc_size, "DLB LAG member status bitmap"); 2720 if (NULL == status_bitmap) { 2721 return BCM_E_MEMORY; 2722 } 2723 soc_DLB_LAG_MEMBER_SW_STATEm_field_get(unit, &sw_state_entry, 2724 MEMBER_BITMAPf, status_bitmap); 2725 2726 /* Get override bitmap */ 2727 override_bitmap = sal_alloc(alloc_size, "DLB LAG member override bitmap"); 2728 if (NULL == override_bitmap) { 2729 sal_free(status_bitmap); 2730 return BCM_E_MEMORY; 2731 } 2732 soc_DLB_LAG_MEMBER_SW_STATEm_field_get(unit, &sw_state_entry, 2733 OVERRIDE_MEMBER_BITMAPf, override_bitmap); 2734 2735 /* Derive status from software override and status bitmaps or 2736 * hardware state bitmap. 2737 */ 2738 if (SHR_BITGET(override_bitmap, member_id)) { 2739 if (SHR_BITGET(status_bitmap, member_id)) { 2740 *status = BCM_TRUNK_DYNAMIC_MEMBER_FORCE_UP; 2741 } else { 2742 *status = BCM_TRUNK_DYNAMIC_MEMBER_FORCE_DOWN; 2743 } 2744 } else { 2745 rv = READ_DLB_LAG_MEMBER_HW_STATE_64r(unit, &hw_state); 2746 if (SOC_FAILURE(rv)) { 2747 sal_free(status_bitmap); 2748 sal_free(override_bitmap); 2749 return rv; 2750 } 2751 hw_status_bitmap = soc_reg64_field_get(unit, 2752 DLB_LAG_MEMBER_HW_STATE_64r, hw_state, BITMAPf); 2753 if (member_id < 32) { 2754 bitmap32 = COMPILER_64_LO(hw_status_bitmap); 2755 } else { 2756 bitmap32 = COMPILER_64_HI(hw_status_bitmap); 2757 member_id -= 32; 2758 } 2759 if ((1 << member_id) & bitmap32) { 2760 *status = BCM_TRUNK_DYNAMIC_MEMBER_HW_UP; 2761 } else { 2762 *status = BCM_TRUNK_DYNAMIC_MEMBER_HW_DOWN; 2763 } 2764 } 2765 2766 sal_free(status_bitmap); 2767 sal_free(override_bitmap); 2768 return rv; 2769 } 2770 2771 /* 2772 * Function: 2773 * bcm_tr3_lag_dlb_ethertype_set 2774 * Purpose: 2775 * Set the Ethertypes that are eligible or ineligible for 2776 * LAG dynamic load balancing. 2777 * Parameters: 2778 * unit - (IN) Unit number. 2779 * flags - (IN) BCM_TRUNK_DYNAMIC_ETHERTYPE_xxx flags. 2780 * ethertype_count - (IN) Number of elements in ethertype_array. 2781 * ethertype_array - (IN) Array of Ethertypes. 2782 * Returns: 2783 * BCM_E_XXX 2784 */ 2785 int 2786 bcm_tr3_lag_dlb_ethertype_set( 2787 int unit, 2788 uint32 flags, 2789 int ethertype_count, 2790 int *ethertype_array) 2791 { 2792 uint32 measure_control_reg; 2793 int i, j; 2794 dlb_lag_ethertype_eligibility_map_entry_t ethertype_entry; 2795 2796 /* Input check */ 2797 if (ethertype_count > soc_mem_index_count(unit, 2798 DLB_LAG_ETHERTYPE_ELIGIBILITY_MAPm)) { 2799 return BCM_E_RESOURCE; 2800 } 2801 2802 /* Update quality measure control register */ 2803 SOC_IF_ERROR_RETURN 2804 (READ_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg)); 2805 soc_reg_field_set(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr, 2806 &measure_control_reg, ETHERTYPE_ELIGIBILITY_CONFIGf, 2807 flags & BCM_TRUNK_DYNAMIC_ETHERTYPE_ELIGIBLE ? 1 : 0); 2808 soc_reg_field_set(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr, 2809 &measure_control_reg, INNER_OUTER_ETHERTYPE_SELECTIONf, 2810 flags & BCM_TRUNK_DYNAMIC_ETHERTYPE_INNER ? 1 : 0); 2811 SOC_IF_ERROR_RETURN 2812 (WRITE_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit, measure_control_reg)); 2813 2814 /* Update Ethertype eligibility map table */ 2815 for (i = 0; i < ethertype_count; i++) { 2816 sal_memset(ðertype_entry, 0, 2817 sizeof(dlb_lag_ethertype_eligibility_map_entry_t)); 2818 soc_DLB_LAG_ETHERTYPE_ELIGIBILITY_MAPm_field32_set(unit, 2819 ðertype_entry, VALIDf, 1); 2820 soc_DLB_LAG_ETHERTYPE_ELIGIBILITY_MAPm_field32_set(unit, 2821 ðertype_entry, ETHERTYPEf, ethertype_array[i]); 2822 SOC_IF_ERROR_RETURN(WRITE_DLB_LAG_ETHERTYPE_ELIGIBILITY_MAPm(unit, 2823 MEM_BLOCK_ALL, i, ðertype_entry)); 2824 } 2825 2826 /* Zero out remaining entries of Ethertype eligibility map table */ 2827 for (j = i; j < soc_mem_index_count(unit, 2828 DLB_LAG_ETHERTYPE_ELIGIBILITY_MAPm); j++) { 2829 SOC_IF_ERROR_RETURN(WRITE_DLB_LAG_ETHERTYPE_ELIGIBILITY_MAPm(unit, 2830 MEM_BLOCK_ALL, j, soc_mem_entry_null(unit, 2831 DLB_LAG_ETHERTYPE_ELIGIBILITY_MAPm))); 2832 } 2833 2834 return BCM_E_NONE; 2835 } 2836 2837 /* 2838 * Function: 2839 * bcm_tr3_lag_dlb_ethertype_get 2840 * Purpose: 2841 * Get the Ethertypes that are eligible or ineligible for 2842 * LAG dynamic load balancing. 2843 * Parameters: 2844 * unit - (IN) Unit number. 2845 * flags - (INOUT) BCM_TRUNK_DYNAMIC_ETHERTYPE_xxx flags. 2846 * ethertype_max - (IN) Number of elements in ethertype_array. 2847 * ethertype_array - (OUT) Array of Ethertypes. 2848 * ethertype_count - (OUT) Number of elements returned in ethertype_array. 2849 * Returns: 2850 * BCM_E_XXX 2851 */ 2852 int 2853 bcm_tr3_lag_dlb_ethertype_get( 2854 int unit, 2855 uint32 *flags, 2856 int ethertype_max, 2857 int *ethertype_array, 2858 int *ethertype_count) 2859 { 2860 uint32 measure_control_reg; 2861 int i; 2862 int ethertype; 2863 dlb_lag_ethertype_eligibility_map_entry_t ethertype_entry; 2864 2865 *ethertype_count = 0; 2866 2867 /* Get flags */ 2868 SOC_IF_ERROR_RETURN 2869 (READ_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit, &measure_control_reg)); 2870 if (soc_reg_field_get(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr, 2871 measure_control_reg, ETHERTYPE_ELIGIBILITY_CONFIGf)) { 2872 *flags |= BCM_TRUNK_DYNAMIC_ETHERTYPE_ELIGIBLE; 2873 } 2874 if (soc_reg_field_get(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr, 2875 measure_control_reg, INNER_OUTER_ETHERTYPE_SELECTIONf)) { 2876 *flags |= BCM_TRUNK_DYNAMIC_ETHERTYPE_INNER; 2877 } 2878 2879 /* Get Ethertypes */ 2880 for (i = 0; i < soc_mem_index_count(unit, 2881 DLB_LAG_ETHERTYPE_ELIGIBILITY_MAPm); i++) { 2882 SOC_IF_ERROR_RETURN(READ_DLB_LAG_ETHERTYPE_ELIGIBILITY_MAPm(unit, 2883 MEM_BLOCK_ANY, i, ðertype_entry)); 2884 if (soc_DLB_LAG_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit, 2885 ðertype_entry, VALIDf)) { 2886 ethertype = soc_DLB_LAG_ETHERTYPE_ELIGIBILITY_MAPm_field32_get(unit, 2887 ðertype_entry, ETHERTYPEf); 2888 if (NULL != ethertype_array) { 2889 ethertype_array[*ethertype_count] = ethertype; 2890 } 2891 (*ethertype_count)++; 2892 if ((ethertype_max > 0) && (*ethertype_count == ethertype_max)) { 2893 break; 2894 } 2895 } 2896 } 2897 2898 return BCM_E_NONE; 2899 } 2900 2901 #ifdef BCM_WARM_BOOT_SUPPORT 2902 2903 /* 2904 * Function: 2905 * bcm_tr3_lag_dlb_wb_alloc_size_get 2906 * Purpose: 2907 * Get level 2 warm boot scache size for LAG DLB. 2908 * Parameters: 2909 * unit - (IN) SOC unit number. 2910 * size - (OUT) Allocation size. 2911 * Returns: 2912 * BCM_E_XXX 2913 */ 2914 int 2915 bcm_tr3_lag_dlb_wb_alloc_size_get(int unit, int *size) 2916 { 2917 int alloc_size = 0; 2918 int num_elements; 2919 2920 /* Allocate size for the following LAG DLB parameters: 2921 * int lag_dlb_sample_rate; 2922 * int lag_dlb_tx_load_min_th; 2923 * int lag_dlb_tx_load_max_th; 2924 * int lag_dlb_qsize_min_th; 2925 * int lag_dlb_qsize_max_th; 2926 * int lag_dlb_exp_load_min_th; 2927 * int lag_dlb_exp_load_max_th; 2928 * int lag_dlb_imbalance_min_th; 2929 * int lag_dlb_imbalance_max_th; 2930 */ 2931 alloc_size += sizeof(int) * 9; 2932 2933 /* Allocate size of lag_dlb_load_weight array */ 2934 num_elements = 1 << soc_mem_field_length(unit, 2935 DLB_LAG_QUALITY_CONTROLm, PROFILE_PTRf); 2936 alloc_size += sizeof(uint8) * num_elements; 2937 2938 *size = alloc_size; 2939 2940 return BCM_E_NONE; 2941 } 2942 2943 /* 2944 * Function: 2945 * bcm_tr3_lag_dlb_sync 2946 * Purpose: 2947 * Store LAG DLB parameters into scache. 2948 * Parameters: 2949 * unit - (IN) SOC unit number. 2950 * scache_ptr - (IN/OUT) Scache pointer 2951 * Returns: 2952 * BCM_E_XXX 2953 */ 2954 int 2955 bcm_tr3_lag_dlb_sync(int unit, uint8 **scache_ptr) 2956 { 2957 int value; 2958 int num_elements; 2959 int i; 2960 uint8 load_weight; 2961 2962 /* Store the following LAG DLB parameters: 2963 * int lag_dlb_sample_rate; 2964 * int lag_dlb_tx_load_min_th; 2965 * int lag_dlb_tx_load_max_th; 2966 * int lag_dlb_qsize_min_th; 2967 * int lag_dlb_qsize_max_th; 2968 * int lag_dlb_exp_load_min_th; 2969 * int lag_dlb_exp_load_max_th; 2970 * int lag_dlb_imbalance_min_th; 2971 * int lag_dlb_imbalance_max_th; 2972 */ 2973 value = LAG_DLB_INFO(unit)->lag_dlb_sample_rate; 2974 sal_memcpy((*scache_ptr), &value, sizeof(int)); 2975 (*scache_ptr) += sizeof(int); 2976 2977 value = LAG_DLB_INFO(unit)->lag_dlb_tx_load_min_th; 2978 sal_memcpy((*scache_ptr), &value, sizeof(int)); 2979 (*scache_ptr) += sizeof(int); 2980 2981 value = LAG_DLB_INFO(unit)->lag_dlb_tx_load_max_th; 2982 sal_memcpy((*scache_ptr), &value, sizeof(int)); 2983 (*scache_ptr) += sizeof(int); 2984 2985 value = LAG_DLB_INFO(unit)->lag_dlb_qsize_min_th; 2986 sal_memcpy((*scache_ptr), &value, sizeof(int)); 2987 (*scache_ptr) += sizeof(int); 2988 2989 value = LAG_DLB_INFO(unit)->lag_dlb_qsize_max_th; 2990 sal_memcpy((*scache_ptr), &value, sizeof(int)); 2991 (*scache_ptr) += sizeof(int); 2992 2993 value = LAG_DLB_INFO(unit)->lag_dlb_exp_load_min_th; 2994 sal_memcpy((*scache_ptr), &value, sizeof(int)); 2995 (*scache_ptr) += sizeof(int); 2996 2997 value = LAG_DLB_INFO(unit)->lag_dlb_exp_load_max_th; 2998 sal_memcpy((*scache_ptr), &value, sizeof(int)); 2999 (*scache_ptr) += sizeof(int); 3000 3001 value = LAG_DLB_INFO(unit)->lag_dlb_imbalance_min_th; 3002 sal_memcpy((*scache_ptr), &value, sizeof(int)); 3003 (*scache_ptr) += sizeof(int); 3004 3005 value = LAG_DLB_INFO(unit)->lag_dlb_imbalance_max_th; 3006 sal_memcpy((*scache_ptr), &value, sizeof(int)); 3007 (*scache_ptr) += sizeof(int); 3008 3009 /* Store lag_dlb_load_weight array */ 3010 num_elements = 1 << soc_mem_field_length(unit, 3011 DLB_LAG_QUALITY_CONTROLm, PROFILE_PTRf); 3012 for (i = 0; i < num_elements; i++) { 3013 load_weight = LAG_DLB_INFO(unit)->lag_dlb_load_weight[i]; 3014 sal_memcpy((*scache_ptr), &load_weight, sizeof(uint8)); 3015 (*scache_ptr) += sizeof(uint8); 3016 } 3017 3018 return BCM_E_NONE; 3019 } 3020 3021 /* 3022 * Function: 3023 * bcm_tr3_lag_dlb_scache_recover 3024 * Purpose: 3025 * Recover LAG DLB parameters from scache. 3026 * Parameters: 3027 * unit - (IN) SOC unit number. 3028 * scache_ptr - (IN/OUT) Scache pointer 3029 * Returns: 3030 * BCM_E_XXX 3031 */ 3032 int 3033 bcm_tr3_lag_dlb_scache_recover(int unit, uint8 **scache_ptr) 3034 { 3035 int value; 3036 int num_elements; 3037 int i; 3038 uint8 load_weight; 3039 3040 /* Recover the following LAG DLB parameters: 3041 * int lag_dlb_sample_rate; 3042 * int lag_dlb_tx_load_min_th; 3043 * int lag_dlb_tx_load_max_th; 3044 * int lag_dlb_qsize_min_th; 3045 * int lag_dlb_qsize_max_th; 3046 * int lag_dlb_exp_load_min_th; 3047 * int lag_dlb_exp_load_max_th; 3048 * int lag_dlb_imbalance_min_th; 3049 * int lag_dlb_imbalance_max_th; 3050 */ 3051 sal_memcpy(&value, (*scache_ptr), sizeof(int)); 3052 LAG_DLB_INFO(unit)->lag_dlb_sample_rate = value; 3053 (*scache_ptr) += sizeof(int); 3054 3055 sal_memcpy(&value, (*scache_ptr), sizeof(int)); 3056 LAG_DLB_INFO(unit)->lag_dlb_tx_load_min_th = value; 3057 (*scache_ptr) += sizeof(int); 3058 3059 sal_memcpy(&value, (*scache_ptr), sizeof(int)); 3060 LAG_DLB_INFO(unit)->lag_dlb_tx_load_max_th = value; 3061 (*scache_ptr) += sizeof(int); 3062 3063 sal_memcpy(&value, (*scache_ptr), sizeof(int)); 3064 LAG_DLB_INFO(unit)->lag_dlb_qsize_min_th = value; 3065 (*scache_ptr) += sizeof(int); 3066 3067 sal_memcpy(&value, (*scache_ptr), sizeof(int)); 3068 LAG_DLB_INFO(unit)->lag_dlb_qsize_max_th = value; 3069 (*scache_ptr) += sizeof(int); 3070 3071 sal_memcpy(&value, (*scache_ptr), sizeof(int)); 3072 LAG_DLB_INFO(unit)->lag_dlb_exp_load_min_th = value; 3073 (*scache_ptr) += sizeof(int); 3074 3075 sal_memcpy(&value, (*scache_ptr), sizeof(int)); 3076 LAG_DLB_INFO(unit)->lag_dlb_exp_load_max_th = value; 3077 (*scache_ptr) += sizeof(int); 3078 3079 sal_memcpy(&value, (*scache_ptr), sizeof(int)); 3080 LAG_DLB_INFO(unit)->lag_dlb_imbalance_min_th = value; 3081 (*scache_ptr) += sizeof(int); 3082 3083 sal_memcpy(&value, (*scache_ptr), sizeof(int)); 3084 LAG_DLB_INFO(unit)->lag_dlb_imbalance_max_th = value; 3085 (*scache_ptr) += sizeof(int); 3086 3087 /* Recover lag_dlb_load_weight array */ 3088 num_elements = 1 << soc_mem_field_length(unit, 3089 DLB_LAG_QUALITY_CONTROLm, PROFILE_PTRf); 3090 for (i = 0; i < num_elements; i++) { 3091 sal_memcpy(&load_weight, (*scache_ptr), sizeof(uint8)); 3092 LAG_DLB_INFO(unit)->lag_dlb_load_weight[i] = load_weight; 3093 (*scache_ptr) += sizeof(uint8); 3094 } 3095 3096 LAG_DLB_INFO(unit)->recovered_from_scache = TRUE; 3097 3098 return BCM_E_NONE; 3099 } 3100 3101 /* 3102 * Function: 3103 * bcm_tr3_lag_dlb_member_recover 3104 * Purpose: 3105 * Recover LAG DLB member ID usage. 3106 * Parameters: 3107 * unit - (IN) SOC unit number. 3108 * Returns: 3109 * BCM_E_XXX 3110 */ 3111 int 3112 bcm_tr3_lag_dlb_member_recover(int unit) 3113 { 3114 int rv = BCM_E_NONE; 3115 int member_bitmap_width; 3116 int alloc_size; 3117 SHR_BITDCL *member_bitmap = NULL; 3118 int dlb_id; 3119 int i; 3120 dlb_lag_group_membership_entry_t group_membership_entry; 3121 3122 member_bitmap_width = soc_mem_field_length(unit, 3123 DLB_LAG_GROUP_MEMBERSHIPm, MEMBER_BITMAPf); 3124 alloc_size = SHR_BITALLOCSIZE(member_bitmap_width); 3125 member_bitmap = sal_alloc(alloc_size, "DLB LAG member bitmap"); 3126 if (NULL == member_bitmap) { 3127 return BCM_E_MEMORY; 3128 } 3129 3130 for (dlb_id = 0; 3131 dlb_id < soc_mem_index_count(unit, DLB_LAG_GROUP_MEMBERSHIPm); 3132 dlb_id++) { 3133 rv = READ_DLB_LAG_GROUP_MEMBERSHIPm(unit, MEM_BLOCK_ANY, 3134 dlb_id, &group_membership_entry); 3135 if (SOC_FAILURE(rv)) { 3136 sal_free(member_bitmap); 3137 return rv; 3138 } 3139 sal_memset(member_bitmap, 0, alloc_size); 3140 soc_DLB_LAG_GROUP_MEMBERSHIPm_field_get(unit, 3141 &group_membership_entry, MEMBER_BITMAPf, member_bitmap); 3142 for (i = 0; i < member_bitmap_width; i++) { 3143 if (SHR_BITGET(member_bitmap, i)) { 3144 _BCM_LAG_DLB_MEMBER_ID_USED_SET(unit, i); 3145 } 3146 } 3147 } 3148 3149 sal_free(member_bitmap); 3150 3151 return BCM_E_NONE; 3152 } 3153 3154 /* 3155 * Function: 3156 * bcm_tr3_lag_dlb_group_recover 3157 * Purpose: 3158 * Recover LAG DLB group usage and flowset table usage. 3159 * Parameters: 3160 * unit - (IN) SOC unit number. 3161 * tid - (IN) Trunk group ID. 3162 * trunk_info - (OUT) Per trunk group DLB info. 3163 * Returns: 3164 * BCM_E_XXX 3165 */ 3166 int 3167 bcm_tr3_lag_dlb_group_recover(int unit, bcm_trunk_t tid, 3168 trunk_private_t *trunk_info) 3169 { 3170 trunk_group_entry_t tg_entry; 3171 int group_enable, dlb_id; 3172 dlb_lag_group_control_entry_t group_control_entry; 3173 int dlb_mode; 3174 int dynamic_size_encode, dynamic_size; 3175 int entry_base_ptr; 3176 int block_base_ptr, num_blocks; 3177 dlb_lag_vla_quality_measure_control_entry_t vla_quality_measure_control_entry; 3178 3179 SOC_IF_ERROR_RETURN 3180 (READ_TRUNK_GROUPm(unit, MEM_BLOCK_ANY, tid, &tg_entry)); 3181 group_enable = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, 3182 GROUP_ENABLEf); 3183 if (0 == group_enable) { 3184 /* DLB not enabled */ 3185 return BCM_E_NONE; 3186 } 3187 3188 /* Get DLB group ID and marked it as used */ 3189 dlb_id = soc_TRUNK_GROUPm_field32_get(unit, &tg_entry, DLB_IDf); 3190 _BCM_LAG_DLB_ID_USED_SET(unit, dlb_id); 3191 3192 SOC_IF_ERROR_RETURN(READ_DLB_LAG_GROUP_CONTROLm(unit, 3193 MEM_BLOCK_ANY, dlb_id, &group_control_entry)); 3194 3195 /* Recover DLB mode */ 3196 dlb_mode = soc_DLB_LAG_GROUP_CONTROLm_field32_get(unit, 3197 &group_control_entry, MEMBER_ASSIGNMENT_MODEf); 3198 switch (dlb_mode) { 3199 case 0: 3200 trunk_info->psc = BCM_TRUNK_PSC_DYNAMIC; 3201 break; 3202 case 1: 3203 trunk_info->psc = BCM_TRUNK_PSC_DYNAMIC_ASSIGNED; 3204 break; 3205 case 2: 3206 trunk_info->psc = BCM_TRUNK_PSC_DYNAMIC_OPTIMAL; 3207 break; 3208 default: 3209 return BCM_E_INTERNAL; 3210 } 3211 3212 /* Recover dynamic_size */ 3213 dynamic_size_encode = soc_DLB_LAG_GROUP_CONTROLm_field32_get(unit, 3214 &group_control_entry, FLOW_SET_SIZEf); 3215 BCM_IF_ERROR_RETURN 3216 (_bcm_tr3_lag_dlb_dynamic_size_decode(dynamic_size_encode, 3217 &dynamic_size)); 3218 trunk_info->dynamic_size = dynamic_size; 3219 3220 /* Recover dynamic_age */ 3221 trunk_info->dynamic_age = soc_DLB_LAG_GROUP_CONTROLm_field32_get(unit, 3222 &group_control_entry, INACTIVITY_DURATIONf); 3223 3224 /* Recover flow set table usage */ 3225 entry_base_ptr = soc_DLB_LAG_GROUP_CONTROLm_field32_get(unit, 3226 &group_control_entry, FLOW_SET_BASEf); 3227 block_base_ptr = entry_base_ptr >> 9; 3228 num_blocks = dynamic_size >> 9; 3229 _BCM_LAG_DLB_FLOWSET_BLOCK_USED_SET_RANGE(unit, block_base_ptr, 3230 num_blocks); 3231 3232 SOC_IF_ERROR_RETURN(READ_DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm(unit, 3233 MEM_BLOCK_ANY, dlb_id, &vla_quality_measure_control_entry)); 3234 3235 /* Recover BCM_TRUNK_FLAG_DYNAMIC_LOAD_DECREASE_RESET flag */ 3236 if (soc_DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm_field32_get(unit, 3237 &vla_quality_measure_control_entry, VLA_CAP_LOADING_AVGf)) { 3238 trunk_info->flags |= BCM_TRUNK_FLAG_DYNAMIC_LOAD_DECREASE_RESET; 3239 } 3240 3241 /* Recover BCM_TRUNK_FLAG_DYNAMIC_EXPECTED_LOAD_DECREASE_RESET flag */ 3242 if (soc_DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm_field32_get(unit, 3243 &vla_quality_measure_control_entry, VLA_CAP_EXPECTED_LOADINGf)) { 3244 trunk_info->flags |= BCM_TRUNK_FLAG_DYNAMIC_EXPECTED_LOAD_DECREASE_RESET; 3245 } 3246 3247 /* Recover dynamic_load_exponent */ 3248 trunk_info->dynamic_load_exponent = 3249 soc_DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm_field32_get(unit, 3250 &vla_quality_measure_control_entry, VLA_WEIGHT_LOADINGf); 3251 3252 /* Recover dynamic_expected_load_exponent */ 3253 trunk_info->dynamic_expected_load_exponent = 3254 soc_DLB_LAG_VLA_QUALITY_MEASURE_CONTROLm_field32_get(unit, 3255 &vla_quality_measure_control_entry, VLA_WEIGHT_EXPECTED_LOADINGf); 3256 3257 return BCM_E_NONE; 3258 } 3259 3260 /* 3261 * Function: 3262 * bcm_tr3_lag_dlb_quality_parameters_recover 3263 * Purpose: 3264 * Recover LAG DLB parameters used to derive a member's quality. 3265 * Parameters: 3266 * unit - (IN) SOC unit number. 3267 * Returns: 3268 * BCM_E_XXX 3269 */ 3270 int 3271 bcm_tr3_lag_dlb_quality_parameters_recover(int unit) 3272 { 3273 uint32 measure_control_reg; 3274 int num_time_units; 3275 dlb_lag_pla_quantize_threshold_entry_t quantize_threshold_entry; 3276 int min_th_bytes, min_th_cells; 3277 int max_th_bytes, max_th_cells; 3278 dlb_lag_vla_expected_loading_threshold_entry_t expected_loading_threshold_entry; 3279 int exp_load_min_th_kbytes, exp_load_max_th_kbytes; 3280 dlb_lag_vla_member_imbalance_threshold_entry_t imbalance_threshold_entry; 3281 int imbalance_min_th_kbytes, imbalance_max_th_kbytes; 3282 int entries_per_profile; 3283 int profile_ptr, base_index; 3284 dlb_lag_quality_mapping_entry_t quality_mapping_entry; 3285 int quality; 3286 3287 if (LAG_DLB_INFO(unit)->recovered_from_scache) { 3288 /* If already recovered from scache, do nothing. */ 3289 return BCM_E_NONE; 3290 } 3291 3292 /* Recover sampling rate */ 3293 SOC_IF_ERROR_RETURN(READ_DLB_LAG_QUALITY_MEASURE_CONTROLr(unit, 3294 &measure_control_reg)); 3295 num_time_units = soc_reg_field_get(unit, DLB_LAG_QUALITY_MEASURE_CONTROLr, 3296 measure_control_reg, HISTORICAL_SAMPLING_PERIODf); 3297 if (num_time_units > 0) { 3298 LAG_DLB_INFO(unit)->lag_dlb_sample_rate = 1000000 / num_time_units; 3299 } 3300 3301 /* Recover min and max load and queue size thresholds: 3302 * Load threshold (in mbps) 3303 * = (bytes per sampling period) * 8 bits per byte / 3304 * (sampling period in seconds) / 10^6 3305 * = (bytes per sampling period) * 8 bits per byte / 3306 * (num_time_units * 1 us per time unit * 10^-6) / 10^6 3307 * = (bytes per sampling period) * 8 / num_time_units 3308 */ 3309 SOC_IF_ERROR_RETURN(READ_DLB_LAG_PLA_QUANTIZE_THRESHOLDm(unit, 3310 MEM_BLOCK_ANY, 0, &quantize_threshold_entry)); 3311 min_th_bytes = soc_DLB_LAG_PLA_QUANTIZE_THRESHOLDm_field32_get 3312 (unit, &quantize_threshold_entry, THRESHOLD_HIST_LOADf); 3313 LAG_DLB_INFO(unit)->lag_dlb_tx_load_min_th = (min_th_bytes << 3) / 3314 num_time_units; 3315 min_th_cells = soc_DLB_LAG_PLA_QUANTIZE_THRESHOLDm_field32_get 3316 (unit, &quantize_threshold_entry, THRESHOLD_HIST_QSIZEf); 3317 LAG_DLB_INFO(unit)->lag_dlb_qsize_min_th = min_th_cells * 208; 3318 3319 SOC_IF_ERROR_RETURN(READ_DLB_LAG_PLA_QUANTIZE_THRESHOLDm(unit, 3320 MEM_BLOCK_ANY, soc_mem_index_max(unit, 3321 DLB_LAG_PLA_QUANTIZE_THRESHOLDm), 3322 &quantize_threshold_entry)); 3323 max_th_bytes = soc_DLB_LAG_PLA_QUANTIZE_THRESHOLDm_field32_get 3324 (unit, &quantize_threshold_entry, THRESHOLD_HIST_LOADf); 3325 LAG_DLB_INFO(unit)->lag_dlb_tx_load_max_th = (max_th_bytes << 3) / 3326 num_time_units; 3327 max_th_cells = soc_DLB_LAG_PLA_QUANTIZE_THRESHOLDm_field32_get 3328 (unit, &quantize_threshold_entry, THRESHOLD_HIST_QSIZEf); 3329 LAG_DLB_INFO(unit)->lag_dlb_qsize_max_th = max_th_cells * 208; 3330 3331 /* Recover min and max expected load thresholds: 3332 * Load threshold (in mbps) 3333 * = (bytes per sampling period) * 8 bits per byte / 3334 * (sampling period in seconds) / 10^6 3335 * = (bytes per sampling period) * 8 bits per byte / 3336 * (num_time_units * 1 us per time unit * 10^-6) / 10^6 3337 * = (bytes per sampling period) * 8 / num_time_units 3338 * = (kilobytes per sampling period) * 8000 / num_time_units 3339 */ 3340 SOC_IF_ERROR_RETURN(READ_DLB_LAG_VLA_EXPECTED_LOADING_THRESHOLDm(unit, 3341 MEM_BLOCK_ANY, 0, &expected_loading_threshold_entry)); 3342 exp_load_min_th_kbytes = 3343 soc_DLB_LAG_VLA_EXPECTED_LOADING_THRESHOLDm_field32_get 3344 (unit, &expected_loading_threshold_entry, THRESHOLDf); 3345 LAG_DLB_INFO(unit)->lag_dlb_exp_load_min_th = 3346 (exp_load_min_th_kbytes << 3) * 1000 / num_time_units; 3347 3348 SOC_IF_ERROR_RETURN(READ_DLB_LAG_VLA_EXPECTED_LOADING_THRESHOLDm(unit, 3349 MEM_BLOCK_ANY, 14, &expected_loading_threshold_entry)); 3350 exp_load_max_th_kbytes = 3351 soc_DLB_LAG_VLA_EXPECTED_LOADING_THRESHOLDm_field32_get 3352 (unit, &expected_loading_threshold_entry, THRESHOLDf); 3353 LAG_DLB_INFO(unit)->lag_dlb_exp_load_max_th = 3354 (exp_load_max_th_kbytes << 3) * 1000 / num_time_units; 3355 3356 /* Recover min and max imbalance thresholds: 3357 * Imbalance threshold (in percentage) 3358 * = (imbalance threshold in kbytes) / 3359 * (expected load threshold in kbytes) * 100 3360 */ 3361 SOC_IF_ERROR_RETURN(READ_DLB_LAG_VLA_MEMBER_IMBALANCE_THRESHOLDm(unit, 3362 MEM_BLOCK_ANY, 14, &imbalance_threshold_entry)); 3363 imbalance_min_th_kbytes = 3364 soc_DLB_LAG_VLA_MEMBER_IMBALANCE_THRESHOLDm_field32_get 3365 (unit, &imbalance_threshold_entry, THRESHOLD_0f); 3366 if ((imbalance_min_th_kbytes >> 20) & 0x1) { 3367 /* Imbalance threshold is negative. Take absolute value. */ 3368 imbalance_min_th_kbytes = ((~imbalance_min_th_kbytes) + 1) & 0x1fffff; 3369 LAG_DLB_INFO(unit)->lag_dlb_imbalance_min_th = 3370 imbalance_min_th_kbytes * 100 / (exp_load_max_th_kbytes) * -1; 3371 } else { 3372 LAG_DLB_INFO(unit)->lag_dlb_imbalance_min_th = 3373 imbalance_min_th_kbytes * 100 / (exp_load_max_th_kbytes); 3374 } 3375 3376 imbalance_max_th_kbytes = 3377 soc_DLB_LAG_VLA_MEMBER_IMBALANCE_THRESHOLDm_field32_get 3378 (unit, &imbalance_threshold_entry, THRESHOLD_6f); 3379 if ((imbalance_max_th_kbytes >> 20) & 0x1) { 3380 /* Imbalance threshold is negative. Take absolute value. */ 3381 imbalance_max_th_kbytes = ((~imbalance_max_th_kbytes) + 1) & 0x1fffff; 3382 LAG_DLB_INFO(unit)->lag_dlb_imbalance_max_th = 3383 imbalance_max_th_kbytes * 100 / (exp_load_max_th_kbytes) * -1; 3384 } else { 3385 LAG_DLB_INFO(unit)->lag_dlb_imbalance_max_th = 3386 imbalance_max_th_kbytes * 100 / (exp_load_max_th_kbytes); 3387 } 3388 3389 /* Recover load weights */ 3390 entries_per_profile = 64; 3391 for (profile_ptr = 0; profile_ptr < (1 << soc_mem_field_length(unit, 3392 DLB_LAG_QUALITY_CONTROLm, PROFILE_PTRf)); profile_ptr++) { 3393 base_index = profile_ptr * entries_per_profile; 3394 /* quality = (quantized_tx_load * tx_load_percent + 3395 * quantized_qsize * (100 - tx_load_percent)) / 3396 * 100; 3397 * quality = ((quantized_tx_load - quantized_qsize) * 3398 * tx_load_percent + quantized_qsize * 100) / 3399 * 100; 3400 * quality = (quantized_tx_load - quantized_qsize) * 3401 * tx_load_percent / 100 + quantized_qsize; 3402 * tx_load_percent = (quality - quantized_qsize) * 100 / 3403 * (quantized_tx_load - quantized_qsize); 3404 * 3405 * The index to DLB_LAG_QUALITY_MAPPING table consists of 3406 * base_index + quantized_tx_load * 8 + quantized_qsize, 3407 * where quantized_tx_load and quantized_qsize range from 3408 * 0 to 7. 3409 * 3410 * With quantized_tx_load = 7 and quantized_qsize = 0, the 3411 * index to DLB_LAG_QUALITY_MAPPING table is 3412 * base_index + 56, and the tx_load_percent expression 3413 * simplifies to quality * 100 / 7; 3414 */ 3415 BCM_IF_ERROR_RETURN(READ_DLB_LAG_QUALITY_MAPPINGm(unit, 3416 MEM_BLOCK_ANY, base_index + 56, 3417 &quality_mapping_entry)); 3418 quality = soc_DLB_LAG_QUALITY_MAPPINGm_field32_get(unit, 3419 &quality_mapping_entry, QUALITYf); 3420 LAG_DLB_INFO(unit)->lag_dlb_load_weight[profile_ptr] = 3421 quality * 100 / 7; 3422 } 3423 3424 return BCM_E_NONE; 3425 } 3426 3427 #endif /* BCM_WARM_BOOT_SUPPORT */ 3428 3429 #ifndef BCM_SW_STATE_DUMP_DISABLE 3430 3431 /* 3432 * Function: 3433 * bcm_tr3_lag_dlb_sw_dump 3434 * Purpose: 3435 * Displays LAG DLB information maintained by software. 3436 * Parameters: 3437 * unit - Device unit number 3438 * Returns: 3439 * None 3440 */ 3441 void 3442 bcm_tr3_lag_dlb_sw_dump(int unit) 3443 { 3444 int i; 3445 int num_entries_per_profile; 3446 int num_profiles; 3447 int rv; 3448 int ref_count; 3449 3450 LOG_CLI((BSL_META_U(unit, 3451 "LAG DLB Info -\n"))); 3452 3453 /* Print LAG DLB group usage */ 3454 LOG_CLI((BSL_META_U(unit, 3455 " LAG DLB Groups Used:"))); 3456 for (i = 0; i < soc_mem_index_count(unit, DLB_LAG_GROUP_CONTROLm); i++) { 3457 if (_BCM_LAG_DLB_ID_USED_GET(unit, i)) { 3458 LOG_CLI((BSL_META_U(unit, 3459 " %d"), i)); 3460 } 3461 } 3462 LOG_CLI((BSL_META_U(unit, 3463 "\n"))); 3464 3465 /* Print LAG DLB flowset table usage */ 3466 LOG_CLI((BSL_META_U(unit, 3467 " LAG DLB Flowset Table Blocks Used:"))); 3468 for (i = 0; i < soc_mem_index_count(unit, DLB_LAG_FLOWSETm) >> 9; i++) { 3469 if (_BCM_LAG_DLB_FLOWSET_BLOCK_USED_GET(unit, i)) { 3470 LOG_CLI((BSL_META_U(unit, 3471 " %d"), i)); 3472 } 3473 } 3474 LOG_CLI((BSL_META_U(unit, 3475 "\n"))); 3476 3477 /* Print LAG DLB member ID usage */ 3478 LOG_CLI((BSL_META_U(unit, 3479 " LAG DLB Member IDs Used:"))); 3480 for (i = 0; i < soc_mem_index_count(unit, DLB_LAG_MEMBER_ATTRIBUTEm); i++) { 3481 if (_BCM_LAG_DLB_MEMBER_ID_USED_GET(unit, i)) { 3482 LOG_CLI((BSL_META_U(unit, 3483 " %d"), i)); 3484 } 3485 } 3486 LOG_CLI((BSL_META_U(unit, 3487 "\n"))); 3488 3489 /* Print sample rate and threshold parameters */ 3490 LOG_CLI((BSL_META_U(unit, 3491 " Sample rate: %d per second\n"), 3492 LAG_DLB_INFO(unit)->lag_dlb_sample_rate)); 3493 LOG_CLI((BSL_META_U(unit, 3494 " Tx load min threshold: %d mbps\n"), 3495 LAG_DLB_INFO(unit)->lag_dlb_tx_load_min_th)); 3496 LOG_CLI((BSL_META_U(unit, 3497 " Tx load max threshold: %d mbps\n"), 3498 LAG_DLB_INFO(unit)->lag_dlb_tx_load_max_th)); 3499 LOG_CLI((BSL_META_U(unit, 3500 " Queue size min threshold: %d cells\n"), 3501 LAG_DLB_INFO(unit)->lag_dlb_qsize_min_th)); 3502 LOG_CLI((BSL_META_U(unit, 3503 " Queue size max threshold: %d cells\n"), 3504 LAG_DLB_INFO(unit)->lag_dlb_qsize_max_th)); 3505 LOG_CLI((BSL_META_U(unit, 3506 " Expected load min threshold: %d mbps\n"), 3507 LAG_DLB_INFO(unit)->lag_dlb_exp_load_min_th)); 3508 LOG_CLI((BSL_META_U(unit, 3509 " Expected load max threshold: %d mbps\n"), 3510 LAG_DLB_INFO(unit)->lag_dlb_exp_load_max_th)); 3511 LOG_CLI((BSL_META_U(unit, 3512 " Imbalance min threshold: %d percent\n"), 3513 LAG_DLB_INFO(unit)->lag_dlb_imbalance_min_th)); 3514 LOG_CLI((BSL_META_U(unit, 3515 " Imbalance max threshold: %d percent\n"), 3516 LAG_DLB_INFO(unit)->lag_dlb_imbalance_max_th)); 3517 3518 /* Print quality mapping profiles */ 3519 LOG_CLI((BSL_META_U(unit, 3520 " Quality mapping profiles:\n"))); 3521 num_entries_per_profile = 64; 3522 num_profiles = soc_mem_index_count(unit, DLB_LAG_QUALITY_MAPPINGm) / 3523 num_entries_per_profile; 3524 for (i = 0; i < num_profiles; i++) { 3525 LOG_CLI((BSL_META_U(unit, 3526 " Profile %d: load weight %d percent, "), 3527 i, LAG_DLB_INFO(unit)->lag_dlb_load_weight[i])); 3528 rv = soc_profile_mem_ref_count_get(unit, 3529 LAG_DLB_INFO(unit)->lag_dlb_quality_map_profile, 3530 i * num_entries_per_profile, &ref_count); 3531 if (SOC_FAILURE(rv)) { 3532 LOG_CLI((BSL_META_U(unit, 3533 "\n"))); 3534 continue; 3535 } 3536 LOG_CLI((BSL_META_U(unit, 3537 "ref count %d\n"), ref_count)); 3538 } 3539 3540 return; 3541 } 3542 3543 #endif /* BCM_SW_STATE_DUMP_DISABLE */ 3544 3545 3546 #endif /* BCM_TRIUMPH3_SUPPORT */