qos.c (81607B)
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 * All Rights Reserved.$ 7 * 8 * QoS module 9 */ 10 #include <soc/defs.h> 11 12 #include <assert.h> 13 #include <shared/bsl.h> 14 #include <sal/core/libc.h> 15 #if defined(BCM_TRIUMPH_SUPPORT) 16 17 #include <shared/util.h> 18 #include <soc/cm.h> 19 #include <soc/drv.h> 20 #include <soc/scache.h> 21 #include <bcm/qos.h> 22 #include <bcm/error.h> 23 #include <bcm_int/esw/triumph.h> 24 #include <bcm_int/esw/port.h> 25 #include <bcm_int/esw/firebolt.h> 26 #include <bcm_int/esw/trx.h> 27 #include <bcm_int/esw/virtual.h> 28 #include <bcm_int/esw/xgs3.h> 29 #include <bcm_int/esw_dispatch.h> 30 #include <bcm_int/esw/switch.h> 31 #if defined(INCLUDE_L3) && defined(BCM_MPLS_SUPPORT) 32 #include <bcm_int/esw/mpls.h> 33 #endif /* INCLUDE_L3 && BCM_MPLS_SUPPORT */ 34 35 #define _BCM_QOS_MAP_TYPE_ING_PRI_CNG_MAP 1 36 #define _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS 2 37 #define _BCM_QOS_MAP_TYPE_DSCP_TABLE 3 38 /* _BCM_QOS_MAP_TYPE_* ids 6-8 are defined in bcm_int/esw/trident2.h 39 * and used in esw/trident2/qos.c. Make sure not to reuse them if new 40 * types are added here. 41 */ 42 43 #define _BCM_QOS_MAP_TYPE_MASK 0x3ff 44 #define _BCM_QOS_MAP_SHIFT 10 45 46 #define _BCM_QOS_MAP_CHUNK_PRI_CNG 16 47 #define _BCM_QOS_MAP_CHUNK_EGR_MPLS 64 48 #define _BCM_QOS_MAP_CHUNK_DSCP 64 49 #define _BCM_QOS_MAP_CHUNK_ING_MPLS_EXP 8 50 51 #define _BCM_QOS_MAP_LEN_ING_PRI_CNG_MAP \ 52 (soc_mem_index_count(unit, ING_PRI_CNG_MAPm)/ \ 53 _BCM_QOS_MAP_CHUNK_PRI_CNG) 54 #define _BCM_QOS_MAP_LEN_EGR_MPLS_MAPS \ 55 (soc_mem_index_count(unit, EGR_MPLS_PRI_MAPPINGm)/ \ 56 _BCM_QOS_MAP_CHUNK_EGR_MPLS) 57 #define _BCM_QOS_MAP_LEN_DSCP_TABLE \ 58 (soc_mem_index_count(unit, DSCP_TABLEm)/ \ 59 _BCM_QOS_MAP_CHUNK_DSCP) 60 #define _BCM_QOS_MAP_LEN_ING_MPLS_EXP_MAP \ 61 (soc_mem_is_valid(unit, ING_MPLS_EXP_MAPPINGm) ? \ 62 (soc_mem_index_count(unit, ING_MPLS_EXP_MAPPINGm)/ \ 63 _BCM_QOS_MAP_CHUNK_ING_MPLS_EXP) : 0) 64 65 typedef struct _bcm_tr_qos_bookkeeping_s { 66 SHR_BITDCL *ing_pri_cng_bitmap; /* ING_PRI_CNG_MAP chunks used */ 67 uint32 *pri_cng_hw_idx; /* Actual profile number used */ 68 SHR_BITDCL *egr_mpls_bitmap; /* EGR_MPLS_EXP_MAPPING_1 / 69 EGR_MPLS_PRI_MAPPING chunks used */ 70 uint32 *egr_mpls_hw_idx; /* Actual profile number used */ 71 SHR_BITDCL *dscp_table_bitmap; /* DSCP_TABLE chunks used */ 72 uint32 *dscp_hw_idx; /* Actual profile number used */ 73 SHR_BITDCL *egr_mpls_bitmap_flags; /* indicates if egr_mpls_bitmap 74 entry is L2 or MPLS */ 75 SHR_BITDCL *ing_mpls_exp_bitmap; /* indicates which chunks of 76 ING_MPLS_EXP_MAPPINGm are used by QOS module */ 77 } _bcm_tr_qos_bookkeeping_t; 78 79 STATIC _bcm_tr_qos_bookkeeping_t _bcm_tr_qos_bk_info[BCM_MAX_NUM_UNITS]; 80 STATIC sal_mutex_t _tr_qos_mutex[BCM_MAX_NUM_UNITS] = {NULL}; 81 STATIC int tr_qos_initialized[BCM_MAX_NUM_UNITS]; /* Flag to check init status */ 82 83 /* 84 * QoS resource lock 85 */ 86 #define QOS_LOCK(unit) \ 87 sal_mutex_take(_tr_qos_mutex[unit], sal_mutex_FOREVER); 88 89 #define QOS_UNLOCK(unit) \ 90 sal_mutex_give(_tr_qos_mutex[unit]); 91 92 #define QOS_INFO(_unit_) (&_bcm_tr_qos_bk_info[_unit_]) 93 #define DSCP_CODE_POINT_CNT 64 94 #define DSCP_CODE_POINT_MAX (DSCP_CODE_POINT_CNT - 1) 95 96 /* 97 * ING_PRI_CNG_MAP usage bitmap operations 98 */ 99 #define _BCM_QOS_ING_PRI_CNG_USED_GET(_u_, _identifier_) \ 100 SHR_BITGET(QOS_INFO(_u_)->ing_pri_cng_bitmap, (_identifier_)) 101 #define _BCM_QOS_ING_PRI_CNG_USED_SET(_u_, _identifier_) \ 102 SHR_BITSET(QOS_INFO((_u_))->ing_pri_cng_bitmap, (_identifier_)) 103 #define _BCM_QOS_ING_PRI_CNG_USED_CLR(_u_, _identifier_) \ 104 SHR_BITCLR(QOS_INFO((_u_))->ing_pri_cng_bitmap, (_identifier_)) 105 106 /* 107 * EGR_MPLS_EXP_MAPPING_1 / EGR_MPLS_PRI_MAPPING usage bitmap operations 108 */ 109 #define _BCM_QOS_EGR_MPLS_USED_GET(_u_, _identifier_) \ 110 SHR_BITGET(QOS_INFO(_u_)->egr_mpls_bitmap, (_identifier_)) 111 #define _BCM_QOS_EGR_MPLS_USED_SET(_u_, _identifier_) \ 112 SHR_BITSET(QOS_INFO((_u_))->egr_mpls_bitmap, (_identifier_)) 113 #define _BCM_QOS_EGR_MPLS_USED_CLR(_u_, _identifier_) \ 114 SHR_BITCLR(QOS_INFO((_u_))->egr_mpls_bitmap, (_identifier_)) 115 116 /* 117 * DSCP_TABLE usage bitmap operations 118 */ 119 #define _BCM_QOS_DSCP_TABLE_USED_GET(_u_, _identifier_) \ 120 SHR_BITGET(QOS_INFO(_u_)->dscp_table_bitmap, (_identifier_)) 121 #define _BCM_QOS_DSCP_TABLE_USED_SET(_u_, _identifier_) \ 122 SHR_BITSET(QOS_INFO((_u_))->dscp_table_bitmap, (_identifier_)) 123 #define _BCM_QOS_DSCP_TABLE_USED_CLR(_u_, _identifier_) \ 124 SHR_BITCLR(QOS_INFO((_u_))->dscp_table_bitmap, (_identifier_)) 125 126 /* 127 * EGR_MPLS flags bitmap operations 128 */ 129 #define _BCM_QOS_EGR_MPLS_FLAGS_USED_GET(_u_, _identifier_) \ 130 SHR_BITGET(QOS_INFO(_u_)->egr_mpls_bitmap_flags, (_identifier_)) 131 #define _BCM_QOS_EGR_MPLS_FLAGS_USED_SET(_u_, _identifier_) \ 132 SHR_BITSET(QOS_INFO((_u_))->egr_mpls_bitmap_flags, (_identifier_)) 133 #define _BCM_QOS_EGR_MPLS_FLAGS_USED_CLR(_u_, _identifier_) \ 134 SHR_BITCLR(QOS_INFO((_u_))->egr_mpls_bitmap_flags, (_identifier_)) 135 136 /* 137 * ING_MPLS_EXP_MAPPING bitmap operations 138 */ 139 #define _BCM_QOS_ING_MPLS_EXP_USED_GET(_u_, _identifier_) \ 140 SHR_BITGET(QOS_INFO(_u_)->ing_mpls_exp_bitmap, (_identifier_)) 141 #define _BCM_QOS_ING_MPLS_EXP_USED_SET(_u_, _identifier_) \ 142 SHR_BITSET(QOS_INFO((_u_))->ing_mpls_exp_bitmap, (_identifier_)) 143 #define _BCM_QOS_ING_MPLS_EXP_USED_CLR(_u_, _identifier_) \ 144 SHR_BITCLR(QOS_INFO((_u_))->ing_mpls_exp_bitmap, (_identifier_)) 145 146 #define QOS_INIT(unit) \ 147 do { \ 148 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { \ 149 return BCM_E_UNIT; \ 150 } \ 151 if (!tr_qos_initialized[unit]) { \ 152 return BCM_E_INIT; \ 153 } \ 154 } while (0) 155 156 STATIC int 157 _bcm_tr_qos_id_alloc(int unit, SHR_BITDCL *bitmap, uint8 map_type) 158 { 159 int i, map_size = -1; 160 161 switch (map_type) { 162 case _BCM_QOS_MAP_TYPE_ING_PRI_CNG_MAP: 163 map_size = _BCM_QOS_MAP_LEN_ING_PRI_CNG_MAP; 164 break; 165 case _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS: 166 map_size = _BCM_QOS_MAP_LEN_EGR_MPLS_MAPS; 167 break; 168 case _BCM_QOS_MAP_TYPE_DSCP_TABLE: 169 map_size = _BCM_QOS_MAP_LEN_DSCP_TABLE; 170 break; 171 default: 172 return BCM_E_PARAM; 173 } 174 175 for (i = 0; i < map_size; i++) { 176 if (!SHR_BITGET(bitmap, i)) { 177 return i; 178 } 179 } 180 return -1; 181 } 182 183 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP 184 /* 185 * Function: 186 * _bcm_qos_sw_dump 187 * Purpose: 188 * Displays QOS software state info 189 * Parameters: 190 * unit : (IN) Device Unit Number 191 * Returns: 192 * NONE 193 */ 194 void 195 _bcm_tr_qos_sw_dump(int unit) 196 { 197 int i; 198 199 if (!tr_qos_initialized[unit]) { 200 LOG_CLI((BSL_META_U(unit, 201 "ERROR: QOS module not initialized\n"))); 202 return; 203 } 204 205 LOG_CLI((BSL_META_U(unit, 206 "QOS: ING_PRI_CNG_MAP info \n"))); 207 for (i=0; i<_BCM_QOS_MAP_LEN_ING_PRI_CNG_MAP; i++) { 208 if (_BCM_QOS_ING_PRI_CNG_USED_GET(unit, i)) { 209 LOG_CLI((BSL_META_U(unit, 210 " map id:%4d HW index:%4d\n"), i, 211 QOS_INFO(unit)->pri_cng_hw_idx[i])); 212 } 213 } 214 215 LOG_CLI((BSL_META_U(unit, 216 "QOS: EGR_MPLS_PRI_MAPPING info \n"))); 217 for (i=0; i<_BCM_QOS_MAP_LEN_EGR_MPLS_MAPS; i++) { 218 if (_BCM_QOS_EGR_MPLS_USED_GET(unit, i)) { 219 LOG_CLI((BSL_META_U(unit, 220 " map id:%4d HW index:%4d (%s)\n"), i, 221 QOS_INFO(unit)->egr_mpls_hw_idx[i], 222 (_BCM_QOS_EGR_MPLS_FLAGS_USED_GET(unit, i)? "MPLS" : "L2"))); 223 } 224 } 225 226 LOG_CLI((BSL_META_U(unit, 227 "QOS: DSCP_TABLE info \n"))); 228 for (i=0; i<_BCM_QOS_MAP_LEN_DSCP_TABLE; i++) { 229 if (_BCM_QOS_DSCP_TABLE_USED_GET(unit, i)) { 230 LOG_CLI((BSL_META_U(unit, 231 " map id:%4d HW index:%4d\n"), i, 232 QOS_INFO(unit)->dscp_hw_idx[i])); 233 } 234 } 235 236 LOG_CLI((BSL_META_U(unit, 237 "QOS: ING_MPLS_EXP_MAPPING info \n"))); 238 for (i=0; i<_BCM_QOS_MAP_LEN_ING_MPLS_EXP_MAP; i++) { 239 if (_BCM_QOS_ING_MPLS_EXP_USED_GET(unit, i)) { 240 LOG_CLI((BSL_META_U(unit, 241 " map id:%4d\n"), i)); 242 } 243 } 244 } 245 #endif 246 247 #ifdef BCM_WARM_BOOT_SUPPORT 248 249 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 250 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 251 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_1 252 #define _BCM_TR_REINIT_INVALID_HW_IDX 0xff /* used as an invalid hw idx */ 253 254 /* 255 * Function: 256 * _bcm_tr_qos_reinit_scache_len_get 257 * Purpose: 258 * Helper utility to determine scache details. 259 * Parameters: 260 * unit : (IN) Device Unit Number 261 * scache_len : (OUT) Total required scache length 262 * Returns: 263 * BCM_E_XXX 264 */ 265 int 266 _bcm_tr_qos_reinit_scache_len_get(int unit, uint32* scache_len) 267 { 268 if (scache_len == NULL) { 269 return BCM_E_PARAM; 270 } 271 272 *scache_len = _BCM_QOS_MAP_LEN_ING_PRI_CNG_MAP; 273 *scache_len += _BCM_QOS_MAP_LEN_EGR_MPLS_MAPS; 274 *scache_len += _BCM_QOS_MAP_LEN_DSCP_TABLE; 275 *scache_len += SHR_BITALLOCSIZE(_BCM_QOS_MAP_LEN_EGR_MPLS_MAPS); 276 *scache_len += SHR_BITALLOCSIZE(_BCM_QOS_MAP_LEN_ING_MPLS_EXP_MAP); 277 278 return BCM_E_NONE; 279 } 280 281 int 282 _bcm_tr_qos_reinit_from_hw_state(int unit, soc_mem_t mem, soc_field_t field, 283 uint8 map_type, SHR_BITDCL *hw_idx_bmp, 284 int hw_idx_bmp_len) 285 { 286 int prof_count, rv = BCM_E_NONE; 287 int i, idx, min_idx, max_idx, map_id, hw_prof_idx; 288 uint32 buf[SOC_MAX_MEM_FIELD_WORDS]; 289 uint32 *hw_idx_table; 290 SHR_BITDCL *map_bmp; 291 soc_field_t prof_field[4]; 292 293 switch (map_type) { 294 case _BCM_QOS_MAP_TYPE_ING_PRI_CNG_MAP: 295 map_bmp = QOS_INFO(unit)->ing_pri_cng_bitmap; 296 hw_idx_table = QOS_INFO(unit)->pri_cng_hw_idx; 297 break; 298 case _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS: 299 map_bmp = QOS_INFO(unit)->egr_mpls_bitmap; 300 hw_idx_table = QOS_INFO(unit)->egr_mpls_hw_idx; 301 break; 302 case _BCM_QOS_MAP_TYPE_DSCP_TABLE: 303 map_bmp = QOS_INFO(unit)->dscp_table_bitmap; 304 hw_idx_table = QOS_INFO(unit)->dscp_hw_idx; 305 break; 306 default: 307 return BCM_E_PARAM; 308 } 309 310 min_idx = soc_mem_index_min(unit, mem); 311 max_idx = soc_mem_index_max(unit, mem); 312 if (mem == EGR_IP_TUNNEL_MPLSm) { 313 prof_count = 4; 314 prof_field[0] = MPLS_EXP_MAPPING_PTR_0f; 315 prof_field[1] = MPLS_EXP_MAPPING_PTR_1f; 316 prof_field[2] = MPLS_EXP_MAPPING_PTR_2f; 317 prof_field[3] = MPLS_EXP_MAPPING_PTR_3f; 318 } else { 319 prof_count = 1; 320 prof_field[0] = field; 321 } 322 for (idx = min_idx; idx < max_idx; idx++) { 323 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, &buf); 324 if (SOC_FAILURE(rv)) { 325 LOG_ERROR(BSL_LS_BCM_QOS, 326 (BSL_META_U(unit, 327 "Error(%s) reading mem(%d) at " 328 "index:%d \n"), soc_errmsg(rv), mem, idx)); 329 return rv; 330 } 331 if (soc_mem_field_valid(unit, mem, MPLS_ACTION_IF_BOSf)) { 332 if (soc_mem_field32_get(unit, mem, &buf, 333 MPLS_ACTION_IF_BOSf) != 1) { 334 continue; 335 } 336 } 337 for (i = 0; i < prof_count; i++) { 338 hw_prof_idx = soc_mem_field32_get(unit, mem, &buf, prof_field[i]); 339 if (hw_prof_idx == 0x3f && mem == L3_IIFm && 340 field == TRUST_DSCP_PTRf) { 341 continue; 342 } 343 344 if (hw_prof_idx > (hw_idx_bmp_len - 1)) { 345 LOG_ERROR(BSL_LS_BCM_QOS, 346 (BSL_META_U(unit, 347 "Invalid profile(%d) in mem(%d) " 348 "at index:%d\n"), hw_prof_idx, mem, idx)); 349 return BCM_E_INTERNAL; 350 } 351 if (hw_prof_idx && (!SHR_BITGET(hw_idx_bmp, hw_prof_idx))) { 352 /* non-zero profile id and not stored previously */ 353 map_id = _bcm_tr_qos_id_alloc(unit, map_bmp, map_type); 354 if (map_id < 0) { 355 LOG_ERROR(BSL_LS_BCM_QOS, 356 (BSL_META_U(unit, 357 "Invalid profile(%d) in mem" 358 "(%d) at index:%d\n"), hw_prof_idx, mem, idx)); 359 return BCM_E_RESOURCE; 360 } 361 hw_idx_table[map_id] = hw_prof_idx; 362 SHR_BITSET(hw_idx_bmp, hw_prof_idx); 363 SHR_BITSET(map_bmp, map_id); 364 } 365 } 366 } 367 368 return rv; 369 } 370 371 /* 372 * Function: 373 * _bcm_tr_qos_unsynchronized_reinit 374 * Purpose: 375 * This routine handles Level 1 Warmboot init. In this style of reinit, the 376 * map-ids allocated previously are not guaranteed to be the same. 377 * Cold-boot: Does nothing 378 * Warm-boot: The data-structures are populated by reading the HW tables. 379 * Parameters: 380 * unit : (IN) Device Unit Number 381 * Returns: 382 * BCM_E_XXX 383 */ 384 int 385 _bcm_tr_qos_unsynchronized_reinit(int unit) 386 { 387 int rv = BCM_E_NONE; 388 int bmp_len; 389 SHR_BITDCL *temp_bmp; 390 391 /* read hw tables and populate the state */ 392 bmp_len = _BCM_QOS_MAP_LEN_ING_PRI_CNG_MAP; 393 temp_bmp = sal_alloc(SHR_BITALLOCSIZE(bmp_len), "temp_bmp"); 394 sal_memset(temp_bmp, 0x0, SHR_BITALLOCSIZE(bmp_len)); 395 396 if (soc_mem_is_valid(unit, MPLS_ENTRYm)) { 397 rv = _bcm_tr_qos_reinit_from_hw_state(unit, MPLS_ENTRYm, 398 TRUST_OUTER_DOT1P_PTRf, _BCM_QOS_MAP_TYPE_ING_PRI_CNG_MAP, 399 temp_bmp, bmp_len); 400 } 401 sal_free(temp_bmp); 402 403 /* now extract EGR_MPLS_PRI_MAPPING state */ 404 if (BCM_SUCCESS(rv)) { 405 bmp_len = _BCM_QOS_MAP_LEN_EGR_MPLS_MAPS; 406 temp_bmp = sal_alloc(SHR_BITALLOCSIZE(bmp_len), "temp_bmp"); 407 sal_memset(temp_bmp, 0x0, SHR_BITALLOCSIZE(bmp_len)); 408 if (BCM_SUCCESS(rv) && 409 soc_mem_field_valid(unit, EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 410 MPLS_EXP_MAPPING_PTRf)) { 411 rv = _bcm_tr_qos_reinit_from_hw_state(unit, 412 EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm, 413 MPLS_EXP_MAPPING_PTRf, _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS, 414 temp_bmp, bmp_len); 415 } 416 if (BCM_SUCCESS(rv) && 417 soc_mem_field_valid(unit, EGR_IP_TUNNEL_MPLSm, 418 MPLS_EXP_MAPPING_PTR_0f)) { 419 rv = _bcm_tr_qos_reinit_from_hw_state(unit, 420 EGR_IP_TUNNEL_MPLSm, 421 MPLS_EXP_MAPPING_PTR_0f, _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS, 422 temp_bmp, bmp_len); 423 } 424 sal_free(temp_bmp); 425 } 426 427 /* now extract DSCP_TABLE state */ 428 if (BCM_SUCCESS(rv)) { 429 bmp_len = _BCM_QOS_MAP_LEN_DSCP_TABLE; 430 temp_bmp = sal_alloc(SHR_BITALLOCSIZE(bmp_len), "temp_bmp"); 431 sal_memset(temp_bmp, 0x0, SHR_BITALLOCSIZE(bmp_len)); 432 if (soc_mem_is_valid(unit, L3_IIFm)) { 433 rv = _bcm_tr_qos_reinit_from_hw_state(unit, L3_IIFm, 434 TRUST_DSCP_PTRf, 435 _BCM_QOS_MAP_TYPE_DSCP_TABLE, temp_bmp, bmp_len); 436 } 437 sal_free(temp_bmp); 438 } 439 440 return rv; 441 } 442 443 /* 444 * Function: 445 * _bcm_tr_qos_extended_reinit 446 * Purpose: 447 * This routine handles Level 2 Warmboot init. 448 * Cold-boot: scache location is allocated. 449 * Warm-boot: The data-structs are populated from recovered scache state 450 * Parameters: 451 * unit : (IN) Device Unit Number 452 * Returns: 453 * BCM_E_XXX 454 */ 455 int 456 _bcm_tr_qos_extended_reinit(int unit) 457 { 458 soc_scache_handle_t handle; 459 uint16 recovered_ver; 460 uint8 *scache_ptr; 461 uint32 hw_idx, scache_len; 462 int idx; 463 int rv = BCM_E_NONE; 464 465 BCM_IF_ERROR_RETURN(_bcm_tr_qos_reinit_scache_len_get(unit, &scache_len)); 466 SOC_SCACHE_HANDLE_SET(handle, unit, BCM_MODULE_QOS, 0); 467 468 if (SOC_WARM_BOOT(unit)) { 469 /* during warm-boot recover state */ 470 rv = _bcm_esw_scache_ptr_get(unit, handle, FALSE, 471 scache_len, &scache_ptr, 472 BCM_WB_DEFAULT_VERSION, &recovered_ver); 473 474 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 475 return rv; 476 } 477 478 if (rv == BCM_E_NOT_FOUND) { 479 BCM_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, handle, 480 TRUE, scache_len, &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL)); 481 } else { 482 483 if (recovered_ver >= BCM_WB_VERSION_1_1) { 484 /* recover from scache into book-keeping structs */ 485 for (idx = 0; idx < _BCM_QOS_MAP_LEN_ING_PRI_CNG_MAP; idx++) { 486 hw_idx = (uint32) (*scache_ptr++); 487 if (hw_idx != _BCM_TR_REINIT_INVALID_HW_IDX) { 488 _BCM_QOS_ING_PRI_CNG_USED_SET(unit, idx); 489 QOS_INFO(unit)->pri_cng_hw_idx[idx] = hw_idx; 490 } 491 } 492 for (idx = 0; idx < _BCM_QOS_MAP_LEN_EGR_MPLS_MAPS; idx++) { 493 hw_idx = (uint32) (*scache_ptr++); 494 if (hw_idx != _BCM_TR_REINIT_INVALID_HW_IDX) { 495 _BCM_QOS_EGR_MPLS_USED_SET(unit, idx); 496 QOS_INFO(unit)->egr_mpls_hw_idx[idx] = hw_idx; 497 } 498 } 499 for (idx = 0; idx < _BCM_QOS_MAP_LEN_DSCP_TABLE; idx++) { 500 hw_idx = (uint32) (*scache_ptr++); 501 if (hw_idx != _BCM_TR_REINIT_INVALID_HW_IDX) { 502 _BCM_QOS_DSCP_TABLE_USED_SET(unit, idx); 503 QOS_INFO(unit)->dscp_hw_idx[idx] = hw_idx; 504 } 505 } 506 sal_memcpy(QOS_INFO(unit)->egr_mpls_bitmap_flags, scache_ptr, 507 SHR_BITALLOCSIZE(_BCM_QOS_MAP_LEN_EGR_MPLS_MAPS)); 508 scache_ptr += SHR_BITALLOCSIZE(_BCM_QOS_MAP_LEN_EGR_MPLS_MAPS); 509 sal_memcpy(QOS_INFO(unit)->ing_mpls_exp_bitmap, scache_ptr, 510 SHR_BITALLOCSIZE(_BCM_QOS_MAP_LEN_ING_MPLS_EXP_MAP)); 511 } 512 } 513 } else { 514 /* During cold-boot. Allocate a stable cache if not already done */ 515 BCM_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, handle, 516 TRUE, scache_len, &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL)); 517 } 518 519 return BCM_E_NONE; 520 } 521 522 /* 523 * Function: 524 * _bcm_tr_qos_reinit_hw_profiles_update 525 * Purpose: 526 * Updates the shared memory profile tables reference counts 527 * Parameters: 528 * unit : (IN) Device Unit Number 529 * Returns: 530 * BCM_E_XXX 531 */ 532 int 533 _bcm_tr_qos_reinit_hw_profiles_update (int unit) 534 { 535 int i; 536 537 for (i=0; i<_BCM_QOS_MAP_LEN_ING_PRI_CNG_MAP; i++) { 538 if (_BCM_QOS_ING_PRI_CNG_USED_GET(unit, i)) { 539 BCM_IF_ERROR_RETURN(_bcm_ing_pri_cng_map_entry_reference(unit, 540 ((QOS_INFO(unit)->pri_cng_hw_idx[i]) * 541 _BCM_QOS_MAP_CHUNK_PRI_CNG), 542 _BCM_QOS_MAP_CHUNK_PRI_CNG)); 543 } 544 } 545 for (i=0; i<_BCM_QOS_MAP_LEN_EGR_MPLS_MAPS; i++) { 546 if (_BCM_QOS_EGR_MPLS_USED_GET(unit, i)) { 547 BCM_IF_ERROR_RETURN(_bcm_egr_mpls_combo_map_entry_reference(unit, 548 ((QOS_INFO(unit)->egr_mpls_hw_idx[i]) * 549 _BCM_QOS_MAP_CHUNK_EGR_MPLS), 550 _BCM_QOS_MAP_CHUNK_EGR_MPLS)); 551 } 552 } 553 for (i=0; i<_BCM_QOS_MAP_LEN_DSCP_TABLE; i++) { 554 if (_BCM_QOS_DSCP_TABLE_USED_GET(unit, i)) { 555 BCM_IF_ERROR_RETURN(_bcm_dscp_table_entry_reference(unit, 556 ((QOS_INFO(unit)->dscp_hw_idx[i]) * 557 _BCM_QOS_MAP_CHUNK_DSCP), 558 _BCM_QOS_MAP_CHUNK_DSCP)); 559 } 560 } 561 562 return BCM_E_NONE; 563 } 564 565 /* 566 * Function: 567 * _bcm_tr_qos_reinit 568 * Purpose: 569 * Top level QOS init routine for Warm-Boot 570 * Parameters: 571 * unit : (IN) Device Unit Number 572 * Returns: 573 * BCM_E_XXX 574 */ 575 int 576 _bcm_tr_qos_reinit(int unit) 577 { 578 int rv = BCM_E_NONE; 579 int stable_size = 0; 580 581 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 582 583 if (stable_size == 0) { 584 if (!SOC_WARM_BOOT(unit)) { 585 return rv; /* do nothing in cold-boot */ 586 } 587 rv = _bcm_tr_qos_unsynchronized_reinit(unit); 588 } else { 589 /* Limited is same as extended */ 590 rv = _bcm_tr_qos_extended_reinit(unit); 591 } 592 593 if (BCM_SUCCESS(rv)) { 594 rv = _bcm_tr_qos_reinit_hw_profiles_update(unit); 595 } 596 597 return rv; 598 } 599 600 /* 601 * Function: 602 * _bcm_tr_qos_sync 603 * Purpose: 604 * This routine extracts the state that needs to be stored from the 605 * book-keeping structs and stores it in the allocated scache location 606 * Compression format: 0 - A pri_cng_hw_idx table 607 * A+1 - B egr_mpls_hw_idx table 608 * D+1 - E egr_mpls flags 609 * E+1 - F ing_mpls_exp table usage by QOS module 610 * Parameters: 611 * unit : (IN) Device Unit Number 612 * Returns: 613 * BCM_E_XXX 614 */ 615 int 616 _bcm_tr_qos_sync(int unit) 617 { 618 soc_scache_handle_t handle; 619 uint8 *scache_ptr; 620 uint32 hw_idx, scache_len; 621 int idx; 622 623 BCM_IF_ERROR_RETURN(_bcm_tr_qos_reinit_scache_len_get(unit, &scache_len)); 624 SOC_SCACHE_HANDLE_SET(handle, unit, BCM_MODULE_QOS, 0); 625 BCM_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, handle, FALSE, 626 scache_len, &scache_ptr, 627 BCM_WB_DEFAULT_VERSION, NULL)); 628 629 /* now store the state into the compressed format */ 630 for (idx = 0; idx < _BCM_QOS_MAP_LEN_ING_PRI_CNG_MAP; idx++) { 631 if (_BCM_QOS_ING_PRI_CNG_USED_GET(unit, idx)) { 632 hw_idx = QOS_INFO(unit)->pri_cng_hw_idx[idx]; 633 } else { 634 hw_idx = _BCM_TR_REINIT_INVALID_HW_IDX; 635 } 636 *scache_ptr++ = hw_idx; 637 } 638 for (idx = 0; idx < _BCM_QOS_MAP_LEN_EGR_MPLS_MAPS; idx++) { 639 if (_BCM_QOS_EGR_MPLS_USED_GET(unit, idx)) { 640 hw_idx = QOS_INFO(unit)->egr_mpls_hw_idx[idx]; 641 } else { 642 hw_idx = _BCM_TR_REINIT_INVALID_HW_IDX; 643 } 644 *scache_ptr++ = hw_idx; 645 } 646 for (idx = 0; idx < _BCM_QOS_MAP_LEN_DSCP_TABLE; idx++) { 647 if (_BCM_QOS_DSCP_TABLE_USED_GET(unit, idx)) { 648 hw_idx = QOS_INFO(unit)->dscp_hw_idx[idx]; 649 } else { 650 hw_idx = _BCM_TR_REINIT_INVALID_HW_IDX; 651 } 652 *scache_ptr++ = hw_idx; 653 } 654 sal_memcpy(scache_ptr, QOS_INFO(unit)->egr_mpls_bitmap_flags, 655 SHR_BITALLOCSIZE(_BCM_QOS_MAP_LEN_EGR_MPLS_MAPS)); 656 scache_ptr += SHR_BITALLOCSIZE(_BCM_QOS_MAP_LEN_EGR_MPLS_MAPS); 657 sal_memcpy(scache_ptr, QOS_INFO(unit)->ing_mpls_exp_bitmap, 658 SHR_BITALLOCSIZE(_BCM_QOS_MAP_LEN_ING_MPLS_EXP_MAP)); 659 660 return BCM_E_NONE; 661 } 662 #endif 663 664 STATIC void 665 _bcm_tr_qos_free_resources(int unit) 666 { 667 _bcm_tr_qos_bookkeeping_t *qos_info = QOS_INFO(unit); 668 669 if (!qos_info) { 670 /* coverity[dead_error_line] */ 671 return; 672 } 673 674 /* Destroy ingress profile bitmap */ 675 if (qos_info->ing_pri_cng_bitmap) { 676 sal_free(qos_info->ing_pri_cng_bitmap); 677 qos_info->ing_pri_cng_bitmap = NULL; 678 } 679 if (qos_info->pri_cng_hw_idx) { 680 sal_free(qos_info->pri_cng_hw_idx); 681 qos_info->pri_cng_hw_idx = NULL; 682 } 683 684 /* Destroy egress profile usage bitmap */ 685 if (qos_info->egr_mpls_bitmap) { 686 sal_free(qos_info->egr_mpls_bitmap); 687 qos_info->egr_mpls_bitmap = NULL; 688 } 689 if (qos_info->egr_mpls_hw_idx) { 690 sal_free(qos_info->egr_mpls_hw_idx); 691 qos_info->egr_mpls_hw_idx = NULL; 692 } 693 694 /* Destroy DSCP table profile usage bitmap */ 695 if (qos_info->dscp_table_bitmap) { 696 sal_free(qos_info->dscp_table_bitmap); 697 qos_info->dscp_table_bitmap = NULL; 698 } 699 if (qos_info->dscp_hw_idx) { 700 sal_free(qos_info->dscp_hw_idx); 701 qos_info->dscp_hw_idx = NULL; 702 } 703 704 /* Destroy egress profile flags bitmap */ 705 if (qos_info->egr_mpls_bitmap_flags) { 706 sal_free(qos_info->egr_mpls_bitmap_flags); 707 qos_info->egr_mpls_bitmap_flags = NULL; 708 } 709 710 /* Destroy ing_mpls_exp bitmap */ 711 if (qos_info->ing_mpls_exp_bitmap) { 712 sal_free(qos_info->ing_mpls_exp_bitmap); 713 qos_info->ing_mpls_exp_bitmap = NULL; 714 } 715 716 /* Destroy the mutex */ 717 if (_tr_qos_mutex[unit]) { 718 sal_mutex_destroy(_tr_qos_mutex[unit]); 719 _tr_qos_mutex[unit] = NULL; 720 } 721 } 722 723 /* Initialize the QoS module. */ 724 int 725 bcm_tr_qos_init(int unit) 726 { 727 _bcm_tr_qos_bookkeeping_t *qos_info = QOS_INFO(unit); 728 int ing_profiles, egr_profiles, rv = BCM_E_NONE; 729 int dscp_profiles, ing_mpls_profiles; 730 ing_profiles = _BCM_QOS_MAP_LEN_ING_PRI_CNG_MAP; 731 egr_profiles = _BCM_QOS_MAP_LEN_EGR_MPLS_MAPS; 732 dscp_profiles = _BCM_QOS_MAP_LEN_DSCP_TABLE; 733 ing_mpls_profiles = _BCM_QOS_MAP_LEN_ING_MPLS_EXP_MAP; 734 735 if (tr_qos_initialized[unit]) { 736 BCM_IF_ERROR_RETURN(bcm_tr_qos_detach(unit)); 737 } 738 739 /* Create mutex */ 740 if (NULL == _tr_qos_mutex[unit]) { 741 _tr_qos_mutex[unit] = sal_mutex_create("qos mutex"); 742 if (_tr_qos_mutex[unit] == NULL) { 743 _bcm_tr_qos_free_resources(unit); 744 return BCM_E_MEMORY; 745 } 746 } 747 748 /* Allocate ingress profile usage bitmap */ 749 if (NULL == qos_info->ing_pri_cng_bitmap) { 750 qos_info->ing_pri_cng_bitmap = 751 sal_alloc(SHR_BITALLOCSIZE(ing_profiles), "ing_pri_cng_bitmap"); 752 if (qos_info->ing_pri_cng_bitmap == NULL) { 753 _bcm_tr_qos_free_resources(unit); 754 return BCM_E_MEMORY; 755 } 756 } 757 sal_memset(qos_info->ing_pri_cng_bitmap, 0, SHR_BITALLOCSIZE(ing_profiles)); 758 if (NULL == qos_info->pri_cng_hw_idx) { 759 qos_info->pri_cng_hw_idx = 760 sal_alloc(sizeof(uint32) * ing_profiles, "pri_cng_hw_idx"); 761 if (qos_info->pri_cng_hw_idx == NULL) { 762 _bcm_tr_qos_free_resources(unit); 763 return BCM_E_MEMORY; 764 } 765 } 766 sal_memset(qos_info->pri_cng_hw_idx, 0, (sizeof(uint32) * ing_profiles)); 767 768 /* Allocate egress profile usage bitmap */ 769 if (NULL == qos_info->egr_mpls_bitmap) { 770 qos_info->egr_mpls_bitmap = 771 sal_alloc(SHR_BITALLOCSIZE(egr_profiles), "egr_mpls_bitmap"); 772 if (qos_info->egr_mpls_bitmap == NULL) { 773 _bcm_tr_qos_free_resources(unit); 774 return BCM_E_MEMORY; 775 } 776 } 777 sal_memset(qos_info->egr_mpls_bitmap, 0, SHR_BITALLOCSIZE(egr_profiles)); 778 if (NULL == qos_info->egr_mpls_hw_idx) { 779 qos_info->egr_mpls_hw_idx = 780 sal_alloc(sizeof(uint32) * egr_profiles, "egr_mpls_hw_idx"); 781 if (qos_info->egr_mpls_hw_idx == NULL) { 782 _bcm_tr_qos_free_resources(unit); 783 return BCM_E_MEMORY; 784 } 785 } 786 sal_memset(qos_info->egr_mpls_hw_idx, 0, (sizeof(uint32) * egr_profiles)); 787 788 /* Allocate DSCP_TABLE profile usage bitmap */ 789 if (NULL == qos_info->dscp_table_bitmap) { 790 qos_info->dscp_table_bitmap = 791 sal_alloc(SHR_BITALLOCSIZE(dscp_profiles), "dscp_table_bitmap"); 792 if (qos_info->dscp_table_bitmap == NULL) { 793 _bcm_tr_qos_free_resources(unit); 794 return BCM_E_MEMORY; 795 } 796 } 797 sal_memset(qos_info->dscp_table_bitmap, 0, SHR_BITALLOCSIZE(dscp_profiles)); 798 if (NULL == qos_info->dscp_hw_idx) { 799 qos_info->dscp_hw_idx = 800 sal_alloc(sizeof(uint32) * dscp_profiles, "dscp_hw_idx"); 801 if (qos_info->dscp_hw_idx == NULL) { 802 _bcm_tr_qos_free_resources(unit); 803 return BCM_E_MEMORY; 804 } 805 } 806 sal_memset(qos_info->dscp_hw_idx, 0, (sizeof(uint32) * dscp_profiles)); 807 808 /* Allocate egress profile usage bitmap */ 809 if (NULL == qos_info->egr_mpls_bitmap_flags) { 810 qos_info->egr_mpls_bitmap_flags = 811 sal_alloc(SHR_BITALLOCSIZE(egr_profiles), "egr_mpls_bitmap_flags"); 812 if (qos_info->egr_mpls_bitmap_flags == NULL) { 813 _bcm_tr_qos_free_resources(unit); 814 return BCM_E_MEMORY; 815 } 816 } 817 sal_memset(qos_info->egr_mpls_bitmap_flags, 0, SHR_BITALLOCSIZE(egr_profiles)); 818 819 /* Allocate ingress mpls profile usage bitmap */ 820 if (NULL == qos_info->ing_mpls_exp_bitmap) { 821 qos_info->ing_mpls_exp_bitmap = 822 sal_alloc(SHR_BITALLOCSIZE(ing_mpls_profiles), "ing_mpls_exp_bitmap"); 823 if (qos_info->ing_mpls_exp_bitmap == NULL) { 824 _bcm_tr_qos_free_resources(unit); 825 return BCM_E_MEMORY; 826 } 827 } 828 sal_memset(qos_info->ing_mpls_exp_bitmap, 0, SHR_BITALLOCSIZE(ing_mpls_profiles)); 829 830 #ifdef BCM_WARM_BOOT_SUPPORT 831 rv = _bcm_tr_qos_reinit(unit); 832 if (SOC_FAILURE(rv)) { 833 _bcm_tr_qos_free_resources(unit); 834 return rv; 835 } 836 #endif /* BCM_WARM_BOOT_SUPPORT */ 837 838 tr_qos_initialized[unit] = TRUE; 839 return rv; 840 } 841 842 /* Detach the QoS module. */ 843 int 844 bcm_tr_qos_detach(int unit) 845 { 846 int rv = BCM_E_NONE; 847 _bcm_tr_qos_free_resources(unit); 848 tr_qos_initialized[unit] = FALSE; 849 return rv; 850 } 851 852 STATIC int 853 _bcm_tr_qos_l2_map_create(int unit, uint32 flags, int *map_id) 854 { 855 ing_pri_cng_map_entry_t ing_pri_map[_BCM_QOS_MAP_CHUNK_PRI_CNG]; 856 egr_mpls_pri_mapping_entry_t egr_mpls_pri_map[_BCM_QOS_MAP_CHUNK_EGR_MPLS]; 857 egr_mpls_exp_mapping_1_entry_t egr_mpls_exp_map[_BCM_QOS_MAP_CHUNK_EGR_MPLS]; 858 egr_mpls_exp_mapping_2_entry_t egr_mpls_exp_map2[_BCM_QOS_MAP_CHUNK_EGR_MPLS]; 859 int id, index = -1, rv = BCM_E_NONE; 860 void *entries[3]; 861 if (flags & BCM_QOS_MAP_INGRESS) { 862 /* Check for pre-specified ID */ 863 if (flags & BCM_QOS_MAP_WITH_ID) { 864 id = *map_id & _BCM_QOS_MAP_TYPE_MASK; 865 if ((*map_id >> _BCM_QOS_MAP_SHIFT) != 866 _BCM_QOS_MAP_TYPE_ING_PRI_CNG_MAP) { 867 return BCM_E_BADID; 868 } 869 if (id >= _BCM_QOS_MAP_LEN_ING_PRI_CNG_MAP) { 870 return BCM_E_PARAM; 871 } 872 if (_BCM_QOS_ING_PRI_CNG_USED_GET(unit, id)) { 873 if (!(flags & BCM_QOS_MAP_REPLACE)) { 874 return BCM_E_EXISTS; 875 } 876 } else { 877 _BCM_QOS_ING_PRI_CNG_USED_SET(unit, id); 878 } 879 } else { 880 id = _bcm_tr_qos_id_alloc(unit, QOS_INFO(unit)->ing_pri_cng_bitmap, 881 _BCM_QOS_MAP_TYPE_ING_PRI_CNG_MAP); 882 if (id == -1) { 883 return BCM_E_RESOURCE; 884 } 885 _BCM_QOS_ING_PRI_CNG_USED_SET(unit, id); 886 *map_id = id | (_BCM_QOS_MAP_TYPE_ING_PRI_CNG_MAP 887 << _BCM_QOS_MAP_SHIFT); 888 } 889 /* Reserve a chunk in the ING_PRI_CNG_MAP table */ 890 sal_memset(ing_pri_map, 0, sizeof(ing_pri_map)); 891 entries[0] = &ing_pri_map; 892 BCM_IF_ERROR_RETURN(_bcm_ing_pri_cng_map_entry_add(unit, entries, 893 _BCM_QOS_MAP_CHUNK_PRI_CNG, 894 (uint32 *)&index)); 895 QOS_INFO(unit)->pri_cng_hw_idx[id] = (index / 896 _BCM_QOS_MAP_CHUNK_PRI_CNG); 897 } else if (flags & BCM_QOS_MAP_EGRESS) { 898 /* Check for pre-specified ID */ 899 if (flags & BCM_QOS_MAP_WITH_ID) { 900 id = *map_id & _BCM_QOS_MAP_TYPE_MASK; 901 if ((*map_id >> _BCM_QOS_MAP_SHIFT) != 902 _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS) { 903 return BCM_E_BADID; 904 } 905 if (_BCM_QOS_EGR_MPLS_USED_GET(unit, id)) { 906 if (!(flags & BCM_QOS_MAP_REPLACE)) { 907 return BCM_E_EXISTS; 908 } 909 } else { 910 _BCM_QOS_EGR_MPLS_USED_SET(unit, id); 911 } 912 } else { 913 id = _bcm_tr_qos_id_alloc(unit, QOS_INFO(unit)->egr_mpls_bitmap, 914 _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS); 915 if (id == -1) { 916 return BCM_E_RESOURCE; 917 } 918 _BCM_QOS_EGR_MPLS_USED_SET(unit, id); 919 *map_id = id | (_BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS 920 << _BCM_QOS_MAP_SHIFT); 921 } 922 /* Reserve a chunk in the EGR_MPLS_EXP_MAPPING_1/EGR_MPLS_PRI_MAPPING 923 tables - these two tables always done together */ 924 sal_memset(egr_mpls_pri_map, 0, sizeof(egr_mpls_pri_map)); 925 entries[0] = egr_mpls_pri_map; 926 sal_memset(egr_mpls_exp_map, 0, sizeof(egr_mpls_exp_map)); 927 entries[1] = egr_mpls_exp_map; 928 sal_memset(egr_mpls_exp_map, 0, sizeof(egr_mpls_exp_map2)); 929 entries[2] = egr_mpls_exp_map2; 930 BCM_IF_ERROR_RETURN(_bcm_egr_mpls_combo_map_entry_add(unit, entries, 931 _BCM_QOS_MAP_CHUNK_EGR_MPLS, 932 (uint32 *)&index)); 933 QOS_INFO(unit)->egr_mpls_hw_idx[id] = (index / 934 _BCM_QOS_MAP_CHUNK_EGR_MPLS); 935 } 936 return rv; 937 } 938 939 STATIC int 940 _bcm_tr_qos_l3_map_create(int unit, uint32 flags, int *map_id) 941 { 942 dscp_table_entry_t dscp_table[_BCM_QOS_MAP_CHUNK_DSCP]; 943 int id, index = -1, rv = BCM_E_NONE; 944 void *entries[1]; 945 if (flags & BCM_QOS_MAP_INGRESS) { 946 /* Check for pre-specified ID */ 947 if (flags & BCM_QOS_MAP_WITH_ID) { 948 id = *map_id & _BCM_QOS_MAP_TYPE_MASK; 949 if ((*map_id >> _BCM_QOS_MAP_SHIFT) != 950 _BCM_QOS_MAP_TYPE_DSCP_TABLE) { 951 return BCM_E_BADID; 952 } 953 if (_BCM_QOS_DSCP_TABLE_USED_GET(unit, id)) { 954 if (!(flags & BCM_QOS_MAP_REPLACE)) { 955 return BCM_E_EXISTS; 956 } 957 } else { 958 _BCM_QOS_DSCP_TABLE_USED_SET(unit, id); 959 } 960 } else { 961 id = _bcm_tr_qos_id_alloc(unit, QOS_INFO(unit)->dscp_table_bitmap, 962 _BCM_QOS_MAP_TYPE_DSCP_TABLE); 963 if (id == -1) { 964 return BCM_E_RESOURCE; 965 } 966 _BCM_QOS_DSCP_TABLE_USED_SET(unit, id); 967 *map_id = id | (_BCM_QOS_MAP_TYPE_DSCP_TABLE 968 << _BCM_QOS_MAP_SHIFT); 969 } 970 /* Reserve a chunk in the DSCP_TABLE */ 971 sal_memset(dscp_table, 0, sizeof(dscp_table)); 972 entries[0] = &dscp_table; 973 BCM_IF_ERROR_RETURN(_bcm_dscp_table_entry_add(unit, entries, 974 _BCM_QOS_MAP_CHUNK_DSCP, 975 (uint32 *)&index)); 976 QOS_INFO(unit)->dscp_hw_idx[id] = index / _BCM_QOS_MAP_CHUNK_DSCP; 977 } else if (flags & BCM_QOS_MAP_EGRESS) { 978 /* Only physical port based mapping is available for EGR_DSCP */ 979 return BCM_E_UNAVAIL; 980 } 981 return rv; 982 } 983 984 STATIC int 985 _bcm_tr_qos_mpls_map_create(int unit, uint32 flags, int *map_id) 986 { 987 if (flags & BCM_QOS_MAP_INGRESS) { 988 /* The ING_MPLS_EXP_MAPPING table is used */ 989 #if defined(INCLUDE_L3) && defined(BCM_MPLS_SUPPORT) 990 BCM_IF_ERROR_RETURN(bcm_tr_mpls_exp_map_create(unit, 991 BCM_MPLS_EXP_MAP_INGRESS, map_id)); 992 _BCM_QOS_ING_MPLS_EXP_USED_SET(unit, 993 ((*map_id) & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK)); 994 #endif 995 } else if (flags & BCM_QOS_MAP_EGRESS) { 996 /* The EGR_MPLS_EXP_MAPPING_1 table is used */ 997 /* Shared with L2 egress map */ 998 BCM_IF_ERROR_RETURN(_bcm_tr_qos_l2_map_create(unit, 999 BCM_QOS_MAP_EGRESS, map_id)); 1000 _BCM_QOS_EGR_MPLS_FLAGS_USED_SET(unit, 1001 ((*map_id) & _BCM_QOS_MAP_TYPE_MASK)); 1002 } else { 1003 return BCM_E_PARAM; 1004 } 1005 return BCM_E_NONE; 1006 } 1007 1008 /* Create a QoS map profile */ 1009 /* This will allocate an ID and a profile index with all-zero mapping */ 1010 int 1011 bcm_tr_qos_map_create(int unit, uint32 flags, int *map_id) 1012 { 1013 int rv = BCM_E_UNAVAIL; 1014 QOS_INIT(unit); 1015 if (flags == 0) { 1016 return BCM_E_PARAM; 1017 } 1018 QOS_LOCK(unit); 1019 if (flags & BCM_QOS_MAP_L2) { 1020 rv = _bcm_tr_qos_l2_map_create(unit, flags, map_id); 1021 } else if (flags & BCM_QOS_MAP_L3) { 1022 rv = _bcm_tr_qos_l3_map_create(unit, flags, map_id); 1023 } else if (flags & BCM_QOS_MAP_MPLS) { 1024 if (!soc_feature(unit, soc_feature_mpls)) { 1025 QOS_UNLOCK(unit); 1026 return rv; 1027 } 1028 rv = _bcm_tr_qos_mpls_map_create(unit, flags, map_id); 1029 } 1030 #ifdef BCM_WARM_BOOT_SUPPORT 1031 SOC_CONTROL_LOCK(unit); 1032 SOC_CONTROL(unit)->scache_dirty = 1; 1033 SOC_CONTROL_UNLOCK(unit); 1034 #endif 1035 QOS_UNLOCK(unit); 1036 return rv; 1037 } 1038 1039 /* Destroy a QoS map profile */ 1040 /* This will free the profile index and de-allocate the ID */ 1041 int 1042 bcm_tr_qos_map_destroy(int unit, int map_id) 1043 { 1044 int id, rv = BCM_E_UNAVAIL; 1045 QOS_INIT(unit); 1046 id = map_id & _BCM_QOS_MAP_TYPE_MASK; 1047 QOS_LOCK(unit); 1048 switch (map_id >> _BCM_QOS_MAP_SHIFT) { 1049 case _BCM_QOS_MAP_TYPE_ING_PRI_CNG_MAP: 1050 if (id >= _BCM_QOS_MAP_LEN_ING_PRI_CNG_MAP) { 1051 QOS_UNLOCK(unit); 1052 return BCM_E_PARAM; 1053 } 1054 if (!_BCM_QOS_ING_PRI_CNG_USED_GET(unit, id)) { 1055 QOS_UNLOCK(unit); 1056 return BCM_E_NOT_FOUND; 1057 } else { 1058 rv = _bcm_ing_pri_cng_map_entry_delete 1059 (unit, QOS_INFO(unit)->pri_cng_hw_idx[id] * 1060 _BCM_QOS_MAP_CHUNK_PRI_CNG); 1061 QOS_INFO(unit)->pri_cng_hw_idx[id] = 0; 1062 _BCM_QOS_ING_PRI_CNG_USED_CLR(unit, id); 1063 } 1064 break; 1065 case _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS: 1066 if (!_BCM_QOS_EGR_MPLS_USED_GET(unit, id)) { 1067 QOS_UNLOCK(unit); 1068 return BCM_E_NOT_FOUND; 1069 } else { 1070 rv = _bcm_egr_mpls_combo_map_entry_delete (unit, 1071 (QOS_INFO(unit)->egr_mpls_hw_idx[id] * 1072 _BCM_QOS_MAP_CHUNK_EGR_MPLS)); 1073 QOS_INFO(unit)->egr_mpls_hw_idx[id] = 0; 1074 _BCM_QOS_EGR_MPLS_USED_CLR(unit, id); 1075 _BCM_QOS_EGR_MPLS_FLAGS_USED_CLR(unit, id); 1076 } 1077 break; 1078 case _BCM_QOS_MAP_TYPE_DSCP_TABLE: 1079 if (!_BCM_QOS_DSCP_TABLE_USED_GET(unit, id)) { 1080 QOS_UNLOCK(unit); 1081 return BCM_E_NOT_FOUND; 1082 } else { 1083 rv = _bcm_dscp_table_entry_delete 1084 (unit, (QOS_INFO(unit)->dscp_hw_idx[id] * 1085 _BCM_QOS_MAP_CHUNK_DSCP)); 1086 QOS_INFO(unit)->dscp_hw_idx[id] = 0; 1087 _BCM_QOS_DSCP_TABLE_USED_CLR(unit, id); 1088 } 1089 break; 1090 default: 1091 #if defined(INCLUDE_L3) && defined(BCM_MPLS_SUPPORT) 1092 if (map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS) { 1093 if (!soc_feature(unit, soc_feature_mpls)) { 1094 QOS_UNLOCK(unit); 1095 return rv; 1096 } 1097 rv = bcm_tr_mpls_exp_map_destroy(unit, map_id); 1098 } else 1099 #endif /* INCLUDE_L3 && BCM_MPLS_SUPPORT */ 1100 { 1101 rv = BCM_E_PARAM; 1102 } 1103 break; 1104 } 1105 #ifdef BCM_WARM_BOOT_SUPPORT 1106 SOC_CONTROL_LOCK(unit); 1107 SOC_CONTROL(unit)->scache_dirty = 1; 1108 SOC_CONTROL_UNLOCK(unit); 1109 #endif 1110 QOS_UNLOCK(unit); 1111 return rv; 1112 } 1113 1114 /* Add an entry to a QoS map */ 1115 /* Read the existing profile chunk, modify what's needed and add the 1116 * new profile. This can result in the HW profile index changing for a 1117 * given ID */ 1118 int 1119 bcm_tr_qos_map_add(int unit, uint32 flags, bcm_qos_map_t *map, int map_id) 1120 { 1121 int alloc_size, offset, cng, id, index, rv = BCM_E_NONE; 1122 ing_pri_cng_map_entry_t ing_pri_map[_BCM_QOS_MAP_CHUNK_PRI_CNG]; 1123 ing_untagged_phb_entry_t ing_untagged_phb; 1124 egr_mpls_pri_mapping_entry_t *egr_mpls_pri_map; 1125 egr_mpls_exp_mapping_1_entry_t *egr_mpls_exp_map; 1126 egr_mpls_exp_mapping_2_entry_t *egr_mpls_exp_map2; 1127 dscp_table_entry_t *dscp_table; 1128 void *entries[3], *entry; 1129 1130 QOS_INIT(unit); 1131 1132 id = map_id & _BCM_QOS_MAP_TYPE_MASK; 1133 QOS_LOCK(unit); 1134 switch (map_id >> _BCM_QOS_MAP_SHIFT) { 1135 case _BCM_QOS_MAP_TYPE_ING_PRI_CNG_MAP: 1136 if (id >= _BCM_QOS_MAP_LEN_ING_PRI_CNG_MAP) { 1137 QOS_UNLOCK(unit); 1138 return BCM_E_PARAM; 1139 } 1140 if (!_BCM_QOS_ING_PRI_CNG_USED_GET(unit, id)) { 1141 QOS_UNLOCK(unit); 1142 return BCM_E_PARAM; 1143 } else { 1144 if (!(flags & BCM_QOS_MAP_L2) || !(flags & BCM_QOS_MAP_INGRESS)) { 1145 QOS_UNLOCK(unit); 1146 return BCM_E_PARAM; 1147 } 1148 if ((map->int_pri > 15) || (map->int_pri < 0) || 1149 (map->pkt_pri > 7) || (map->pkt_cfi > 1) || 1150 ((map->color != bcmColorGreen) && 1151 (map->color != bcmColorYellow) && 1152 (map->color != bcmColorRed))) { 1153 QOS_UNLOCK(unit); 1154 return BCM_E_PARAM; 1155 } 1156 1157 entries[0] = ing_pri_map; 1158 entries[1] = &ing_untagged_phb; 1159 1160 /* Base index of table in hardware */ 1161 index = QOS_INFO(unit)->pri_cng_hw_idx[id] * 1162 _BCM_QOS_MAP_CHUNK_PRI_CNG; 1163 1164 rv = _bcm_ing_pri_cng_map_entry_get(unit, index, 1165 _BCM_QOS_MAP_CHUNK_PRI_CNG, 1166 entries); 1167 if (BCM_FAILURE(rv)) { 1168 QOS_UNLOCK(unit); 1169 return (rv); 1170 } 1171 1172 /* Offset within table */ 1173 offset = (map->pkt_pri << 1) | map->pkt_cfi; 1174 1175 /* Modify what's needed */ 1176 entry = &ing_pri_map[offset]; 1177 soc_mem_field32_set(unit, ING_PRI_CNG_MAPm, entry, 1178 PRIf, map->int_pri); 1179 soc_mem_field32_set(unit, ING_PRI_CNG_MAPm, entry, 1180 CNGf, _BCM_COLOR_ENCODING(unit, map->color)); 1181 1182 /* Delete the old profile chunk */ 1183 rv = _bcm_ing_pri_cng_map_entry_delete(unit, index); 1184 if (BCM_FAILURE(rv)) { 1185 QOS_UNLOCK(unit); 1186 return (rv); 1187 } 1188 1189 /* Add new chunk and store new HW index */ 1190 rv = _bcm_ing_pri_cng_map_entry_add(unit, entries, 1191 _BCM_QOS_MAP_CHUNK_PRI_CNG, 1192 (uint32 *)&index); 1193 QOS_INFO(unit)->pri_cng_hw_idx[id] = (index / 1194 _BCM_QOS_MAP_CHUNK_PRI_CNG); 1195 } 1196 break; 1197 case _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS: 1198 if (!_BCM_QOS_EGR_MPLS_USED_GET(unit, id)) { 1199 QOS_UNLOCK(unit); 1200 return BCM_E_PARAM; 1201 } else { 1202 if (!((flags & BCM_QOS_MAP_L2) || (flags & BCM_QOS_MAP_MPLS)) 1203 || !(flags & BCM_QOS_MAP_EGRESS)) { 1204 QOS_UNLOCK(unit); 1205 return BCM_E_PARAM; 1206 } 1207 if ((map->int_pri > 15) || (map->int_pri < 0) || 1208 (map->pkt_pri > 7) || (map->pkt_cfi > 1) || 1209 ((map->color != bcmColorGreen) && 1210 (map->color != bcmColorYellow) && 1211 (map->color != bcmColorRed))) { 1212 QOS_UNLOCK(unit); 1213 return BCM_E_PARAM; 1214 } 1215 if (flags & BCM_QOS_MAP_MPLS) { 1216 if ((map->exp > 7) || (map->exp < 0)) { 1217 QOS_UNLOCK(unit); 1218 return BCM_E_PARAM; 1219 } 1220 } 1221 1222 /* Allocate memory for DMA */ 1223 alloc_size = (_BCM_QOS_MAP_CHUNK_EGR_MPLS * 1224 sizeof(egr_mpls_pri_mapping_entry_t)); 1225 egr_mpls_pri_map = soc_cm_salloc(unit, alloc_size, 1226 "TR egr mpls pri map"); 1227 if (NULL == egr_mpls_pri_map) { 1228 QOS_UNLOCK(unit); 1229 return (BCM_E_MEMORY); 1230 } 1231 sal_memset(egr_mpls_pri_map, 0, alloc_size); 1232 1233 alloc_size = (_BCM_QOS_MAP_CHUNK_EGR_MPLS * 1234 sizeof(egr_mpls_exp_mapping_1_entry_t)); 1235 egr_mpls_exp_map = soc_cm_salloc(unit, alloc_size, 1236 "TR egr mpls exp map"); 1237 if (NULL == egr_mpls_exp_map) { 1238 sal_free(egr_mpls_pri_map); 1239 QOS_UNLOCK(unit); 1240 return (BCM_E_MEMORY); 1241 } 1242 sal_memset(egr_mpls_exp_map, 0, alloc_size); 1243 1244 alloc_size = (_BCM_QOS_MAP_CHUNK_EGR_MPLS * 1245 sizeof(egr_mpls_exp_mapping_2_entry_t)); 1246 egr_mpls_exp_map2 = soc_cm_salloc(unit, alloc_size, 1247 "TR egr mpls exp map"); 1248 if (NULL == egr_mpls_exp_map2) { 1249 sal_free(egr_mpls_pri_map); 1250 sal_free(egr_mpls_exp_map); 1251 QOS_UNLOCK(unit); 1252 return (BCM_E_MEMORY); 1253 } 1254 sal_memset(egr_mpls_exp_map2, 0, alloc_size); 1255 1256 /* Base index of table in hardware */ 1257 index = (QOS_INFO(unit)->egr_mpls_hw_idx[id] * 1258 _BCM_QOS_MAP_CHUNK_EGR_MPLS); 1259 1260 /* Offset within table */ 1261 cng = _BCM_COLOR_ENCODING(unit, map->color); 1262 offset = (map->int_pri << 2) | cng; 1263 1264 /* Read the old profile chunk */ 1265 rv = soc_mem_read_range(unit, EGR_MPLS_PRI_MAPPINGm, MEM_BLOCK_ANY, 1266 index, 1267 (index + (_BCM_QOS_MAP_CHUNK_EGR_MPLS -1)), 1268 egr_mpls_pri_map); 1269 if (BCM_FAILURE(rv)) { 1270 soc_cm_sfree(unit, egr_mpls_pri_map); 1271 soc_cm_sfree(unit, egr_mpls_exp_map); 1272 QOS_UNLOCK(unit); 1273 return (rv); 1274 } 1275 if (SOC_MEM_IS_VALID(unit, EGR_MPLS_EXP_MAPPING_1m)) { 1276 rv = soc_mem_read_range(unit, EGR_MPLS_EXP_MAPPING_1m, MEM_BLOCK_ANY, 1277 index, 1278 (index + (_BCM_QOS_MAP_CHUNK_EGR_MPLS -1)), 1279 egr_mpls_exp_map); 1280 if (BCM_FAILURE(rv)) { 1281 soc_cm_sfree(unit, egr_mpls_pri_map); 1282 soc_cm_sfree(unit, egr_mpls_exp_map); 1283 QOS_UNLOCK(unit); 1284 return (rv); 1285 } 1286 } 1287 1288 if (SOC_MEM_IS_VALID(unit, EGR_MPLS_EXP_MAPPING_2m)) { 1289 rv = soc_mem_read_range(unit, EGR_MPLS_EXP_MAPPING_2m, MEM_BLOCK_ANY, 1290 index, 1291 (index + (_BCM_QOS_MAP_CHUNK_EGR_MPLS -1)), 1292 egr_mpls_exp_map2); 1293 if (BCM_FAILURE(rv)) { 1294 soc_cm_sfree(unit, egr_mpls_pri_map); 1295 soc_cm_sfree(unit, egr_mpls_exp_map); 1296 soc_cm_sfree(unit, egr_mpls_exp_map2); 1297 QOS_UNLOCK(unit); 1298 return (rv); 1299 } 1300 } 1301 1302 /* Modify what's needed */ 1303 entry = &egr_mpls_pri_map[offset]; 1304 soc_mem_field32_set(unit, EGR_MPLS_PRI_MAPPINGm, entry, 1305 NEW_PRIf, map->pkt_pri); 1306 soc_mem_field32_set(unit, EGR_MPLS_PRI_MAPPINGm, entry, 1307 NEW_CFIf, map->pkt_cfi); 1308 if (SOC_MEM_IS_VALID(unit, EGR_MPLS_EXP_MAPPING_1m)) { 1309 entry = &egr_mpls_exp_map[offset]; 1310 if (flags & BCM_QOS_MAP_MPLS) { 1311 soc_mem_field32_set(unit, EGR_MPLS_EXP_MAPPING_1m, entry, 1312 MPLS_EXPf, map->exp); 1313 } 1314 } 1315 1316 if (SOC_MEM_IS_VALID(unit, EGR_MPLS_EXP_MAPPING_2m)) { 1317 entry = &egr_mpls_exp_map2[offset]; 1318 if (flags & BCM_QOS_MAP_MPLS) { 1319 soc_mem_field32_set(unit, EGR_MPLS_EXP_MAPPING_2m, entry, 1320 MPLS_EXPf, map->exp); 1321 } 1322 } 1323 1324 /* Delete the old profile chunk */ 1325 rv = _bcm_egr_mpls_combo_map_entry_delete(unit, index); 1326 if (BCM_FAILURE(rv)) { 1327 soc_cm_sfree(unit, egr_mpls_pri_map); 1328 soc_cm_sfree(unit, egr_mpls_exp_map); 1329 soc_cm_sfree(unit, egr_mpls_exp_map2); 1330 QOS_UNLOCK(unit); 1331 return (rv); 1332 } 1333 1334 /* Add new chunk and store new HW index */ 1335 entries[0] = egr_mpls_pri_map; 1336 entries[1] = egr_mpls_exp_map; 1337 entries[2] = egr_mpls_exp_map2; 1338 rv = _bcm_egr_mpls_combo_map_entry_add(unit, entries, 1339 _BCM_QOS_MAP_CHUNK_EGR_MPLS, 1340 (uint32 *)&index); 1341 QOS_INFO(unit)->egr_mpls_hw_idx[id] = (index / 1342 _BCM_QOS_MAP_CHUNK_EGR_MPLS); 1343 1344 /* Free the DMA memory */ 1345 soc_cm_sfree(unit, egr_mpls_pri_map); 1346 soc_cm_sfree(unit, egr_mpls_exp_map); 1347 soc_cm_sfree(unit, egr_mpls_exp_map2); 1348 } 1349 break; 1350 case _BCM_QOS_MAP_TYPE_DSCP_TABLE: 1351 if (!_BCM_QOS_DSCP_TABLE_USED_GET(unit, id)) { 1352 QOS_UNLOCK(unit); 1353 return BCM_E_PARAM; 1354 } else { 1355 if (!(flags & BCM_QOS_MAP_L3) || !(flags & BCM_QOS_MAP_INGRESS)) { 1356 QOS_UNLOCK(unit); 1357 return BCM_E_PARAM; 1358 } 1359 if ((map->int_pri > 15) || (map->int_pri < 0) || 1360 (map->dscp > DSCP_CODE_POINT_MAX) || (map->dscp < 0) || 1361 ((map->color != bcmColorGreen) && 1362 (map->color != bcmColorYellow) && 1363 (map->color != bcmColorRed))) { 1364 QOS_UNLOCK(unit); 1365 return BCM_E_PARAM; 1366 } 1367 1368 /* Allocate memory for DMA */ 1369 alloc_size = _BCM_QOS_MAP_CHUNK_DSCP * sizeof(dscp_table_entry_t); 1370 dscp_table = soc_cm_salloc(unit, alloc_size, 1371 "TR dscp table"); 1372 if (NULL == dscp_table) { 1373 QOS_UNLOCK(unit); 1374 return (BCM_E_MEMORY); 1375 } 1376 sal_memset(dscp_table, 0, alloc_size); 1377 1378 /* Base index of table in hardware */ 1379 index = QOS_INFO(unit)->dscp_hw_idx[id] * _BCM_QOS_MAP_CHUNK_DSCP; 1380 1381 /* Offset within table */ 1382 offset = map->dscp; 1383 1384 /* Read the old profile chunk */ 1385 rv = soc_mem_read_range(unit, DSCP_TABLEm, MEM_BLOCK_ANY, 1386 index, index + (_BCM_QOS_MAP_CHUNK_DSCP-1), 1387 dscp_table); 1388 if (BCM_FAILURE(rv)) { 1389 soc_cm_sfree(unit, dscp_table); 1390 QOS_UNLOCK(unit); 1391 return (rv); 1392 } 1393 1394 /* Modify what's needed */ 1395 entry = &dscp_table[offset]; 1396 cng = _BCM_COLOR_ENCODING(unit, map->color); 1397 soc_DSCP_TABLEm_field32_set(unit, entry, DSCPf, map->dscp); 1398 soc_DSCP_TABLEm_field32_set(unit, entry, PRIf, map->int_pri); 1399 soc_DSCP_TABLEm_field32_set(unit, entry, CNGf, cng); 1400 1401 /* Delete the old profile chunk */ 1402 rv = _bcm_dscp_table_entry_delete(unit, index); 1403 if (BCM_FAILURE(rv)) { 1404 soc_cm_sfree(unit, dscp_table); 1405 QOS_UNLOCK(unit); 1406 return (rv); 1407 } 1408 1409 /* Add new chunk and store new HW index */ 1410 entries[0] = dscp_table; 1411 rv = _bcm_dscp_table_entry_add(unit, entries, _BCM_QOS_MAP_CHUNK_DSCP, 1412 (uint32 *)&index); 1413 QOS_INFO(unit)->dscp_hw_idx[id] = index / _BCM_QOS_MAP_CHUNK_DSCP; 1414 1415 /* Free the DMA memory */ 1416 soc_cm_sfree(unit, dscp_table); 1417 } 1418 break; 1419 default: 1420 #if defined(INCLUDE_L3) && defined(BCM_MPLS_SUPPORT) 1421 if (map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS) { 1422 bcm_mpls_exp_map_t ing_exp_map; 1423 bcm_mpls_exp_map_t_init(&ing_exp_map); 1424 if (!(flags & BCM_QOS_MAP_MPLS) || !(flags & BCM_QOS_MAP_INGRESS)) { 1425 QOS_UNLOCK(unit); 1426 return BCM_E_PARAM; 1427 } 1428 if ((map->int_pri > 15) || (map->int_pri < 0) || 1429 (map->exp > 7) || (map->exp < 0) || 1430 ((map->color != bcmColorGreen) && 1431 (map->color != bcmColorYellow) && 1432 (map->color != bcmColorRed))) { 1433 QOS_UNLOCK(unit); 1434 return BCM_E_PARAM; 1435 } 1436 /* Call the triumph/mpls.c implementation */ 1437 ing_exp_map.exp = map->exp; 1438 ing_exp_map.priority = map->int_pri; 1439 ing_exp_map.color = map->color; 1440 rv = bcm_tr_mpls_exp_map_set(unit, map_id, &ing_exp_map); 1441 } else 1442 #endif /* defined(INCLUDE_L3) && defined(BCM_MPLS_SUPPORT) */ 1443 { 1444 QOS_UNLOCK(unit); 1445 return BCM_E_PARAM; 1446 } 1447 break; 1448 } 1449 #ifdef BCM_WARM_BOOT_SUPPORT 1450 SOC_CONTROL_LOCK(unit); 1451 SOC_CONTROL(unit)->scache_dirty = 1; 1452 SOC_CONTROL_UNLOCK(unit); 1453 #endif 1454 QOS_UNLOCK(unit); 1455 return rv; 1456 } 1457 1458 /* Clear an entry from a QoS map */ 1459 /* Read the existing profile chunk, modify what's needed and add the 1460 * new profile. This can result in the HW profile index changing for a 1461 * given ID */ 1462 int 1463 bcm_tr_qos_map_delete(int unit, uint32 flags, bcm_qos_map_t *map, int map_id) 1464 { 1465 int rv = BCM_E_NONE; 1466 bcm_qos_map_t clr_map; 1467 1468 QOS_INIT(unit); 1469 1470 switch (map_id >> _BCM_QOS_MAP_SHIFT) { 1471 case _BCM_QOS_MAP_TYPE_ING_PRI_CNG_MAP: 1472 sal_memcpy(&clr_map, map, sizeof(clr_map)); 1473 clr_map.int_pri = 0; 1474 clr_map.color = bcmColorGreen; 1475 rv = bcm_tr_qos_map_add(unit, flags, &clr_map, map_id); 1476 break; 1477 case _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS: 1478 sal_memcpy(&clr_map, map, sizeof(clr_map)); 1479 clr_map.pkt_pri = 0; 1480 clr_map.pkt_cfi = 0; 1481 rv = bcm_tr_qos_map_add(unit, flags, &clr_map, map_id); 1482 break; 1483 case _BCM_QOS_MAP_TYPE_DSCP_TABLE: 1484 sal_memcpy(&clr_map, map, sizeof(clr_map)); 1485 clr_map.int_pri = 0; 1486 clr_map.color = bcmColorGreen; 1487 rv = bcm_tr_qos_map_add(unit, flags, &clr_map, map_id); 1488 break; 1489 default: 1490 sal_memcpy(&clr_map, map, sizeof(clr_map)); 1491 clr_map.int_pri = 0; 1492 clr_map.color = bcmColorGreen; 1493 rv = bcm_tr_qos_map_add(unit, flags, &clr_map, map_id); 1494 break; 1495 } 1496 #ifdef BCM_WARM_BOOT_SUPPORT 1497 SOC_CONTROL_LOCK(unit); 1498 SOC_CONTROL(unit)->scache_dirty = 1; 1499 SOC_CONTROL_UNLOCK(unit); 1500 #endif 1501 return rv; 1502 } 1503 1504 /* Attach a QoS map to an object (Gport) */ 1505 int 1506 bcm_tr_qos_port_map_set(int unit, bcm_gport_t port, int ing_map, int egr_map) 1507 { 1508 int index, id, alloc_size, rv = BCM_E_NONE; 1509 uint8 pri=0, cfi=0; 1510 bcm_color_t color; 1511 char *buf, *buf2; 1512 void *entries[1]; 1513 #ifdef INCLUDE_L3 1514 mpls_entry_entry_t *mpls_entry=NULL; 1515 int vp; 1516 int index_max, index_min; 1517 #endif 1518 bcm_color_t used_colors[3] = {bcmColorGreen,bcmColorYellow,bcmColorRed}; 1519 int idx; 1520 1521 QOS_INIT(unit); 1522 1523 QOS_LOCK(unit); 1524 #ifdef INCLUDE_L3 1525 if (BCM_GPORT_IS_SET(port) && !BCM_GPORT_IS_MODPORT(port) && 1526 !BCM_GPORT_IS_LOCAL(port)) { 1527 /* Deal with MPLS gports */ 1528 if (BCM_GPORT_IS_MPLS_PORT(port)) { 1529 /* Deal with MiM and MPLS ports */ 1530 vp = BCM_GPORT_MPLS_PORT_ID_GET(port); 1531 if (!_bcm_vp_used_get(unit, vp, _bcmVpTypeMpls)) { 1532 QOS_UNLOCK(unit); 1533 return BCM_E_BADID; 1534 } 1535 if (ing_map != -1) { /* -1 means no change */ 1536 /* TRUST_DOT1P_PTR from MPLS_ENTRY table */ 1537 index_max = soc_mem_index_max(unit, MPLS_ENTRYm); 1538 index_min = soc_mem_index_min(unit, MPLS_ENTRYm); 1539 alloc_size = (index_max - index_min + 1) * 1540 sizeof(mpls_entry_entry_t); 1541 buf = soc_cm_salloc(unit, alloc_size, "TR MPLS_ENTRY"); 1542 if (NULL == buf) { 1543 QOS_UNLOCK(unit); 1544 return (BCM_E_MEMORY); 1545 } 1546 rv = soc_mem_read_range(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, 1547 index_min, index_max, (void *)buf); 1548 if (rv < 0) { 1549 soc_cm_sfree(unit, buf); 1550 QOS_UNLOCK(unit); 1551 return rv; 1552 } 1553 for (index = index_min; index <= index_max; index++) { 1554 mpls_entry = soc_mem_table_idx_to_pointer(unit, MPLS_ENTRYm, 1555 mpls_entry_entry_t *, 1556 buf, index); 1557 if ((vp == soc_mem_field32_get(unit, MPLS_ENTRYm, 1558 mpls_entry, SOURCE_VPf)) && 1559 (soc_mem_field32_get(unit, MPLS_ENTRYm, 1560 mpls_entry, MPLS_ACTION_IF_BOSf) == 1) /* L2_SVP */) { 1561 break; 1562 } 1563 } 1564 if (index == index_max + 1) { 1565 soc_cm_sfree(unit, buf); 1566 QOS_UNLOCK(unit); 1567 return BCM_E_NOT_FOUND; /* VP not found */ 1568 } 1569 if (ing_map == 0) { 1570 /* Clear the existing map */ 1571 soc_MPLS_ENTRYm_field32_set(unit, mpls_entry, 1572 TRUST_OUTER_DOT1P_PTRf, 0); 1573 } else { 1574 /* Use the provided map */ 1575 if ((ing_map >> _BCM_QOS_MAP_SHIFT) != 1576 _BCM_QOS_MAP_TYPE_ING_PRI_CNG_MAP) { 1577 soc_cm_sfree(unit, buf); 1578 QOS_UNLOCK(unit); 1579 return BCM_E_PARAM; 1580 } 1581 id = ing_map & _BCM_QOS_MAP_TYPE_MASK; 1582 if (id >= _BCM_QOS_MAP_LEN_ING_PRI_CNG_MAP) { 1583 soc_cm_sfree(unit, buf); 1584 QOS_UNLOCK(unit); 1585 return BCM_E_PARAM; 1586 } 1587 if (!_BCM_QOS_ING_PRI_CNG_USED_GET(unit, id)) { 1588 soc_cm_sfree(unit, buf); 1589 QOS_UNLOCK(unit); 1590 return BCM_E_PARAM; 1591 } 1592 soc_MPLS_ENTRYm_field32_set(unit, mpls_entry, 1593 TRUST_OUTER_DOT1P_PTRf, 1594 QOS_INFO(unit)->pri_cng_hw_idx[id]); 1595 } 1596 1597 #ifdef BCM_TRIUMPH3_SUPPORT 1598 if (SOC_IS_TRIUMPH3(unit)) { 1599 soc_MPLS_ENTRYm_field32_set(unit, mpls_entry, KEY_TYPEf, 0x10); 1600 } 1601 #endif 1602 rv = WRITE_MPLS_ENTRYm(unit, MEM_BLOCK_ALL, index, mpls_entry); 1603 if (rv < 0) { 1604 soc_cm_sfree(unit, buf); 1605 QOS_UNLOCK(unit); 1606 return rv; 1607 } 1608 soc_cm_sfree(unit, buf); 1609 } 1610 if (egr_map != -1) { /* -1 means no change */ 1611 /* Can only do for physical port, not VP */ 1612 QOS_UNLOCK(unit); 1613 return BCM_E_UNAVAIL; 1614 } 1615 } 1616 } else 1617 #endif 1618 { 1619 /* Deal with physical ports */ 1620 if (BCM_GPORT_IS_SET(port)) { 1621 if (bcm_esw_port_local_get(unit, port, &port) < 0) { 1622 QOS_UNLOCK(unit); 1623 return BCM_E_PARAM; 1624 } 1625 } 1626 if (!SOC_PORT_VALID(unit, port)) { 1627 QOS_UNLOCK(unit); 1628 return BCM_E_PARAM; 1629 } 1630 if (ing_map != -1) { /* -1 means no change */ 1631 if (ing_map == 0) { 1632 /* Clear the existing map - make identity */ 1633 for (cfi = 0; cfi <= 1; cfi++) { 1634 for (pri = 0; pri <= 7; pri++){ 1635 color = _BCM_COLOR_DECODING(unit, cfi); 1636 rv = bcm_esw_port_vlan_priority_map_set 1637 (unit, port, pri, cfi, pri, color); 1638 if (BCM_FAILURE(rv)) { 1639 QOS_UNLOCK(unit); 1640 return rv; 1641 } 1642 } 1643 } 1644 } else { 1645 if ((ing_map >> _BCM_QOS_MAP_SHIFT) != 1646 _BCM_QOS_MAP_TYPE_ING_PRI_CNG_MAP) { 1647 QOS_UNLOCK(unit); 1648 return BCM_E_PARAM; 1649 } 1650 id = ing_map & _BCM_QOS_MAP_TYPE_MASK; 1651 if (id >= _BCM_QOS_MAP_LEN_ING_PRI_CNG_MAP) { 1652 QOS_UNLOCK(unit); 1653 return BCM_E_PARAM; 1654 } 1655 if (!_BCM_QOS_ING_PRI_CNG_USED_GET(unit, id)) { 1656 QOS_UNLOCK(unit); 1657 return BCM_E_PARAM; 1658 } 1659 /* Copy the corresponding chunk from ING_PRI_CNG_MAP profile 1660 * to the specific port's region */ 1661 alloc_size = 16 * sizeof(ing_pri_cng_map_entry_t); 1662 buf = soc_cm_salloc(unit, alloc_size, "TR ing pri cng map"); 1663 if (NULL == buf) { 1664 QOS_UNLOCK(unit); 1665 return (BCM_E_MEMORY); 1666 } 1667 sal_memset(buf, 0, alloc_size); 1668 index = (QOS_INFO(unit)->pri_cng_hw_idx[id] * 1669 _BCM_QOS_MAP_CHUNK_PRI_CNG); 1670 rv = soc_mem_read_range(unit, ING_PRI_CNG_MAPm, 1671 MEM_BLOCK_ANY, index, index + 15, 1672 (void *)buf); 1673 if (BCM_FAILURE(rv)) { 1674 soc_cm_sfree(unit, buf); 1675 QOS_UNLOCK(unit); 1676 return rv; 1677 } 1678 index = port << 4; 1679 rv = soc_mem_write_range(unit, ING_PRI_CNG_MAPm, MEM_BLOCK_ALL, 1680 index, index + 15, (void *)buf); 1681 if (BCM_FAILURE(rv)) { 1682 soc_cm_sfree(unit, buf); 1683 QOS_UNLOCK(unit); 1684 return rv; 1685 } 1686 soc_cm_sfree(unit, buf); 1687 } 1688 } 1689 if (egr_map != -1) { /* -1 means no change */ 1690 /* Copy the corresponding chunk from EGR_MPLS profiles to the 1691 * EGR_PRI_CNG_MAP table, which is directly indexed by port */ 1692 alloc_size = 64 * sizeof(egr_pri_cng_map_entry_t); 1693 buf = soc_cm_salloc(unit, alloc_size, "TR egr pri cng map"); 1694 if (NULL == buf) { 1695 QOS_UNLOCK(unit); 1696 return (BCM_E_MEMORY); 1697 } 1698 sal_memset(buf, 0, alloc_size); 1699 index = port << 6; 1700 if (egr_map == 0) { 1701 /* Clear the existing map - make identity */ 1702 for (idx = 0; idx < sizeof(used_colors)/sizeof(used_colors[0]); 1703 idx++) { 1704 color = used_colors[idx]; 1705 for (pri = 0; pri <= 7; pri++) { 1706 cfi = (color == bcmColorRed) ? 1 : 0; 1707 rv = bcm_esw_port_vlan_priority_unmap_set(unit, port, 1708 pri, color, pri, cfi); 1709 if (BCM_FAILURE(rv)) { 1710 soc_cm_sfree(unit, buf); 1711 QOS_UNLOCK(unit); 1712 return rv; 1713 } 1714 } 1715 } 1716 } else { 1717 if ((egr_map >> _BCM_QOS_MAP_SHIFT) != 1718 _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS) { 1719 QOS_UNLOCK(unit); 1720 return BCM_E_PARAM; 1721 } 1722 id = egr_map & _BCM_QOS_MAP_TYPE_MASK; 1723 if (!_BCM_QOS_EGR_MPLS_USED_GET(unit, id)) { 1724 QOS_UNLOCK(unit); 1725 return BCM_E_PARAM; 1726 } 1727 buf2 = soc_cm_salloc(unit, alloc_size, "TR egr mpls exp map"); 1728 if (NULL == buf2) { 1729 soc_cm_sfree(unit, buf); 1730 QOS_UNLOCK(unit); 1731 return (BCM_E_MEMORY); 1732 } 1733 sal_memset(buf2, 0, alloc_size); 1734 index = (QOS_INFO(unit)->egr_mpls_hw_idx[id] * 1735 _BCM_QOS_MAP_CHUNK_EGR_MPLS); 1736 rv = soc_mem_read_range(unit, EGR_MPLS_EXP_MAPPING_1m, 1737 MEM_BLOCK_ANY, index, index + 63, 1738 (void *)buf2); 1739 if (BCM_FAILURE(rv)) { 1740 soc_cm_sfree(unit, buf); 1741 soc_cm_sfree(unit, buf2); 1742 QOS_UNLOCK(unit); 1743 return rv; 1744 } 1745 for (index = 0; index < _BCM_QOS_MAP_CHUNK_EGR_MPLS; index++) { 1746 entries[0] = soc_mem_table_idx_to_pointer(unit, 1747 EGR_PRI_CNG_MAPm, 1748 void *, buf, index); 1749 soc_mem_field32_set(unit, EGR_PRI_CNG_MAPm, 1750 entries[0], PRIf, pri); 1751 soc_mem_field32_set(unit, EGR_PRI_CNG_MAPm, 1752 entries[0], CFIf, cfi); 1753 } 1754 index = port << 6; 1755 rv = soc_mem_write_range(unit, EGR_PRI_CNG_MAPm, MEM_BLOCK_ALL, 1756 index, index + 63, (void *)buf); 1757 if (BCM_FAILURE(rv)) { 1758 soc_cm_sfree(unit, buf); 1759 soc_cm_sfree(unit, buf2); 1760 QOS_UNLOCK(unit); 1761 return rv; 1762 } 1763 soc_cm_sfree(unit, buf2); 1764 } 1765 soc_cm_sfree(unit, buf); 1766 } 1767 } 1768 #ifdef BCM_WARM_BOOT_SUPPORT 1769 SOC_CONTROL_LOCK(unit); 1770 SOC_CONTROL(unit)->scache_dirty = 1; 1771 SOC_CONTROL_UNLOCK(unit); 1772 #endif 1773 QOS_UNLOCK(unit); 1774 return rv; 1775 } 1776 1777 /* Retrieve a QOS map attached to an Object (Gport) */ 1778 int 1779 bcm_tr_qos_port_map_get(int unit, bcm_gport_t port, 1780 int *ing_map, int *egr_map) 1781 { 1782 return BCM_E_UNAVAIL; 1783 } 1784 1785 /* bcm_tr_qos_map_multi_get */ 1786 int 1787 bcm_tr_qos_map_multi_get(int unit, uint32 flags, 1788 int map_id, int array_size, 1789 bcm_qos_map_t *array, int *array_count) 1790 { 1791 int rv = BCM_E_NONE; 1792 int num_entries, idx, id, hw_id, alloc_size, entry_size, count; 1793 uint8 *dma_buf; 1794 void *entry; 1795 soc_mem_t mem; 1796 bcm_qos_map_t *map; 1797 1798 /* ignore with_id & replace flags */ 1799 flags &= (~(BCM_QOS_MAP_WITH_ID | BCM_QOS_MAP_REPLACE)); 1800 id = map_id & _BCM_QOS_MAP_TYPE_MASK; 1801 mem = INVALIDm; 1802 hw_id = 0; 1803 num_entries = 0; 1804 entry_size = 0; 1805 QOS_LOCK(unit); 1806 switch (map_id >> _BCM_QOS_MAP_SHIFT) { 1807 case _BCM_QOS_MAP_TYPE_ING_PRI_CNG_MAP: 1808 if (id >= _BCM_QOS_MAP_LEN_ING_PRI_CNG_MAP) { 1809 rv = BCM_E_PARAM; 1810 QOS_UNLOCK(unit); 1811 BCM_IF_ERROR_RETURN(rv); 1812 } 1813 if ((flags != (BCM_QOS_MAP_L2 | BCM_QOS_MAP_INGRESS)) || 1814 (!_BCM_QOS_ING_PRI_CNG_USED_GET(unit, id))) { 1815 rv = BCM_E_PARAM; 1816 } 1817 num_entries = _BCM_QOS_MAP_CHUNK_PRI_CNG; 1818 entry_size = sizeof(ing_pri_cng_map_entry_t); 1819 hw_id = QOS_INFO(unit)->pri_cng_hw_idx[id]* _BCM_QOS_MAP_CHUNK_PRI_CNG; 1820 mem = ING_PRI_CNG_MAPm; 1821 break; 1822 case _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS: 1823 if (((flags != (BCM_QOS_MAP_L2 | BCM_QOS_MAP_EGRESS)) && 1824 (flags != (BCM_QOS_MAP_MPLS | BCM_QOS_MAP_EGRESS))) || 1825 (!_BCM_QOS_EGR_MPLS_USED_GET(unit, id))) { 1826 rv = BCM_E_PARAM; 1827 } 1828 num_entries = _BCM_QOS_MAP_CHUNK_EGR_MPLS; 1829 entry_size = sizeof(egr_mpls_pri_mapping_entry_t); 1830 hw_id = (QOS_INFO(unit)->egr_mpls_hw_idx[id] * 1831 _BCM_QOS_MAP_CHUNK_EGR_MPLS); 1832 mem = EGR_MPLS_PRI_MAPPINGm; 1833 break; 1834 case _BCM_QOS_MAP_TYPE_DSCP_TABLE: 1835 if ((flags != (BCM_QOS_MAP_L3 | BCM_QOS_MAP_INGRESS)) || 1836 (!_BCM_QOS_DSCP_TABLE_USED_GET(unit, id))) { 1837 rv = BCM_E_PARAM; 1838 } 1839 num_entries = _BCM_QOS_MAP_CHUNK_DSCP; 1840 entry_size = sizeof(dscp_table_entry_t); 1841 hw_id = QOS_INFO(unit)->dscp_hw_idx[id] * _BCM_QOS_MAP_CHUNK_DSCP; 1842 mem = DSCP_TABLEm; 1843 break; 1844 default: 1845 #if defined(INCLUDE_L3) && defined(BCM_MPLS_SUPPORT) 1846 if ((map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 1847 _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS) { 1848 /* Map created using TR mpls module */ 1849 if (flags != (BCM_QOS_MAP_MPLS | BCM_QOS_MAP_INGRESS)) { 1850 rv = BCM_E_PARAM; 1851 } 1852 id = map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_NUM_MASK; 1853 if (!_BCM_QOS_ING_MPLS_EXP_USED_GET(unit, id)) { 1854 rv = BCM_E_PARAM; 1855 } 1856 num_entries = _BCM_QOS_MAP_CHUNK_ING_MPLS_EXP; 1857 entry_size = sizeof(ing_mpls_exp_mapping_entry_t); 1858 hw_id = id; /* soc profile mem is not used. So direct hw index */ 1859 mem = ING_MPLS_EXP_MAPPINGm; 1860 } else 1861 #endif /* INCLUDE_L3 && BCM_MPLS_SUPPORT */ 1862 { 1863 rv = BCM_E_PARAM; 1864 } 1865 } 1866 QOS_UNLOCK(unit); 1867 BCM_IF_ERROR_RETURN(rv); 1868 1869 if (array_size == 0) { /* querying the size of map-chunk */ 1870 *array_count = num_entries; 1871 return BCM_E_NONE; 1872 } 1873 if (!array || !array_count) { 1874 return BCM_E_PARAM; 1875 } 1876 1877 /* Allocate memory for DMA & regular */ 1878 alloc_size = num_entries * entry_size; 1879 dma_buf = soc_cm_salloc(unit, alloc_size, "TR qos multi get DMA buf"); 1880 if (!dma_buf) { 1881 return BCM_E_MEMORY; 1882 } 1883 sal_memset(dma_buf, 0, alloc_size); 1884 1885 /* Read the profile chunk */ 1886 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, hw_id, 1887 (hw_id + num_entries - 1), dma_buf); 1888 if (BCM_FAILURE(rv)) { 1889 soc_cm_sfree(unit, dma_buf); 1890 return rv; 1891 } 1892 1893 count = 0; 1894 QOS_LOCK(unit); 1895 switch (map_id >> _BCM_QOS_MAP_SHIFT) { 1896 case _BCM_QOS_MAP_TYPE_ING_PRI_CNG_MAP: 1897 for (idx=0; ((idx<num_entries) && (count < array_size)); idx++) { 1898 map = &array[idx]; 1899 sal_memset(map, 0x0, sizeof(bcm_qos_map_t)); 1900 map->pkt_pri = ((idx & 0x1e) >> 1); 1901 map->pkt_cfi = (idx & 0x1); 1902 entry = soc_mem_table_idx_to_pointer(unit, mem, void *, 1903 dma_buf, idx); 1904 map->int_pri = soc_mem_field32_get(unit, mem, entry, PRIf); 1905 map->color = _BCM_COLOR_DECODING(unit, soc_mem_field32_get(unit, 1906 mem, entry, CNGf)); 1907 count++; 1908 } 1909 break; 1910 case _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS: 1911 for (idx=0; ((idx<num_entries) && (count < array_size)); idx++) { 1912 map = &array[idx]; 1913 sal_memset(map, 0x0, sizeof(bcm_qos_map_t)); 1914 map->int_pri = ((idx & 0x3c) >> 2); 1915 map->color = _BCM_COLOR_DECODING(unit, (idx & 0x3)); 1916 entry = soc_mem_table_idx_to_pointer(unit, mem, void *, 1917 dma_buf, idx); 1918 map->pkt_pri = soc_mem_field32_get(unit, mem, entry, NEW_PRIf); 1919 map->pkt_cfi = soc_mem_field32_get(unit, mem, entry, NEW_CFIf); 1920 count++; 1921 } 1922 break; 1923 case _BCM_QOS_MAP_TYPE_DSCP_TABLE: 1924 for (idx=0; ((idx<num_entries) && (count < array_size)); idx++) { 1925 map = &array[idx]; 1926 sal_memset(map, 0x0, sizeof(bcm_qos_map_t)); 1927 map->dscp = idx; 1928 entry = soc_mem_table_idx_to_pointer(unit, mem, void *, 1929 dma_buf, idx); 1930 map->int_pri = soc_mem_field32_get(unit, mem, entry, PRIf); 1931 map->color = _BCM_COLOR_DECODING(unit, soc_mem_field32_get(unit, 1932 mem, entry, CNGf)); 1933 count++; 1934 } 1935 break; 1936 default: 1937 #if defined(INCLUDE_L3) && defined(BCM_MPLS_SUPPORT) 1938 if ((map_id & _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_MASK) == 1939 _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS) { 1940 for (idx=0; ((idx<num_entries) && (count < array_size)); idx++) { 1941 map = &array[idx]; 1942 sal_memset(map, 0x0, sizeof(bcm_qos_map_t)); 1943 map->exp = idx; 1944 entry = soc_mem_table_idx_to_pointer(unit, mem, void *, 1945 dma_buf, idx); 1946 map->color = _BCM_COLOR_DECODING(unit,soc_mem_field32_get(unit, 1947 mem, entry, CNGf)); 1948 map->int_pri = soc_mem_field32_get(unit, mem, entry, PRIf); 1949 count++; 1950 } 1951 } else 1952 #endif /* INCLUDE_L3 && BCM_MPLS_SUPPORT */ 1953 { 1954 rv = BCM_E_INTERNAL; /* should not hit this */ 1955 } 1956 } 1957 QOS_UNLOCK(unit); 1958 soc_cm_sfree(unit, dma_buf); 1959 1960 BCM_IF_ERROR_RETURN(rv); 1961 1962 *array_count = count; 1963 return BCM_E_NONE; 1964 } 1965 1966 /* Get the list of all created Map-ids along with corresponding flags */ 1967 int 1968 bcm_tr_qos_multi_get(int unit, int array_size, int *map_ids_array, 1969 int *flags_array, int *array_count) 1970 { 1971 int rv = BCM_E_NONE; 1972 int idx, count; 1973 1974 QOS_INIT(unit); 1975 QOS_LOCK(unit); 1976 if (array_size == 0) { 1977 /* querying the number of map-ids for storage allocation */ 1978 if (array_count == NULL) { 1979 rv = BCM_E_PARAM; 1980 } 1981 if (BCM_SUCCESS(rv)) { 1982 QOS_LOCK(unit); 1983 count = 0; 1984 *array_count = 0; 1985 SHR_BITCOUNT_RANGE(QOS_INFO(unit)->ing_pri_cng_bitmap, count, 1986 0, _BCM_QOS_MAP_LEN_ING_PRI_CNG_MAP); 1987 *array_count += count; 1988 count = 0; 1989 SHR_BITCOUNT_RANGE(QOS_INFO(unit)->egr_mpls_bitmap, count, 1990 0, _BCM_QOS_MAP_LEN_EGR_MPLS_MAPS); 1991 *array_count += count; 1992 count = 0; 1993 SHR_BITCOUNT_RANGE(QOS_INFO(unit)->dscp_table_bitmap, count, 1994 0, _BCM_QOS_MAP_LEN_DSCP_TABLE); 1995 *array_count += count; 1996 #if defined(INCLUDE_L3) && defined(BCM_MPLS_SUPPORT) 1997 count = 0; 1998 SHR_BITCOUNT_RANGE(QOS_INFO(unit)->ing_mpls_exp_bitmap, count, 1999 0, _BCM_QOS_MAP_LEN_ING_MPLS_EXP_MAP); 2000 *array_count += count; 2001 #endif 2002 } 2003 } else { 2004 if ((map_ids_array == NULL) || (flags_array == NULL) || 2005 (array_count == NULL)) { 2006 rv = BCM_E_PARAM; 2007 } 2008 if (BCM_SUCCESS(rv)) { 2009 count = 0; 2010 for (idx = 0; ((idx < _BCM_QOS_MAP_LEN_ING_PRI_CNG_MAP) && 2011 (count < array_size)); idx++) { 2012 if (_BCM_QOS_ING_PRI_CNG_USED_GET(unit, idx)) { 2013 *(map_ids_array + count) = idx | 2014 (_BCM_QOS_MAP_TYPE_ING_PRI_CNG_MAP << _BCM_QOS_MAP_SHIFT); 2015 *(flags_array + count) = (BCM_QOS_MAP_L2 | 2016 BCM_QOS_MAP_INGRESS); 2017 count++; 2018 } 2019 } 2020 for (idx = 0; ((idx < _BCM_QOS_MAP_LEN_EGR_MPLS_MAPS) && 2021 (count < array_size)); idx++) { 2022 if (_BCM_QOS_EGR_MPLS_USED_GET(unit, idx)) { 2023 *(map_ids_array + count) = idx | 2024 (_BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS << _BCM_QOS_MAP_SHIFT); 2025 *(flags_array + count) = (BCM_QOS_MAP_EGRESS | 2026 (_BCM_QOS_EGR_MPLS_FLAGS_USED_GET(unit, idx)? 2027 BCM_QOS_MAP_MPLS : BCM_QOS_MAP_L2)); 2028 count++; 2029 } 2030 } 2031 for (idx = 0; ((idx < _BCM_QOS_MAP_LEN_DSCP_TABLE) && 2032 (count < array_size)); idx++) { 2033 if (_BCM_QOS_DSCP_TABLE_USED_GET(unit, idx)) { 2034 *(map_ids_array + count) = idx | 2035 (_BCM_QOS_MAP_TYPE_DSCP_TABLE << _BCM_QOS_MAP_SHIFT); 2036 *(flags_array + count) = (BCM_QOS_MAP_L3 | 2037 BCM_QOS_MAP_INGRESS); 2038 count++; 2039 } 2040 } 2041 #if defined(INCLUDE_L3) && defined(BCM_MPLS_SUPPORT) 2042 for (idx = 0; ((idx < _BCM_QOS_MAP_LEN_ING_MPLS_EXP_MAP) && 2043 (count < array_size)); idx++) { 2044 if (_BCM_QOS_ING_MPLS_EXP_USED_GET(unit, idx)) { 2045 *(map_ids_array + count) = (idx | 2046 _BCM_TR_MPLS_EXP_MAP_TABLE_TYPE_INGRESS); 2047 *(flags_array + count) = (BCM_QOS_MAP_MPLS | 2048 BCM_QOS_MAP_INGRESS); 2049 count++; 2050 } 2051 } 2052 #endif /* INCLUDE_L3 && BCM_MPLS_SUPPORT */ 2053 *array_count = count; 2054 } 2055 } 2056 QOS_UNLOCK(unit); 2057 return rv; 2058 } 2059 2060 /* Function: 2061 * _bcm_tr_qos_id2idx 2062 * Purpose: 2063 * Translate map ID into hardware table index used by API 2064 * Parameters: 2065 * Returns: 2066 * BCM_E_XXX 2067 */ 2068 int 2069 _bcm_tr_qos_id2idx(int unit, int map_id, int *hw_idx) 2070 { 2071 int id; 2072 2073 QOS_INIT(unit); 2074 2075 id = map_id & _BCM_QOS_MAP_TYPE_MASK; 2076 2077 QOS_LOCK(unit); 2078 switch (map_id >> _BCM_QOS_MAP_SHIFT) { 2079 case _BCM_QOS_MAP_TYPE_ING_PRI_CNG_MAP: 2080 if (id >= _BCM_QOS_MAP_LEN_ING_PRI_CNG_MAP) { 2081 QOS_UNLOCK(unit); 2082 return BCM_E_PARAM; 2083 } 2084 if (!_BCM_QOS_ING_PRI_CNG_USED_GET(unit, id)) { 2085 QOS_UNLOCK(unit); 2086 return BCM_E_NOT_FOUND; 2087 } else { 2088 *hw_idx = QOS_INFO(unit)->pri_cng_hw_idx[id]; 2089 } 2090 break; 2091 case _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS: 2092 if (!_BCM_QOS_EGR_MPLS_USED_GET(unit, id)) { 2093 QOS_UNLOCK(unit); 2094 return BCM_E_NOT_FOUND; 2095 } else { 2096 *hw_idx = QOS_INFO(unit)->egr_mpls_hw_idx[id]; 2097 } 2098 break; 2099 case _BCM_QOS_MAP_TYPE_DSCP_TABLE: 2100 if (!_BCM_QOS_DSCP_TABLE_USED_GET(unit, id)) { 2101 QOS_UNLOCK(unit); 2102 return BCM_E_NOT_FOUND; 2103 } else { 2104 *hw_idx = QOS_INFO(unit)->dscp_hw_idx[id]; 2105 } 2106 break; 2107 default: 2108 QOS_UNLOCK(unit); 2109 return BCM_E_NOT_FOUND; 2110 } 2111 QOS_UNLOCK(unit); 2112 return BCM_E_NONE; 2113 } 2114 2115 /* Function: 2116 * _bcm_tr_qos_id2idx 2117 * Purpose: 2118 * Translate hardware table index into map ID used by API 2119 * Parameters: 2120 * Returns: 2121 * BCM_E_XXX 2122 */ 2123 int 2124 _bcm_tr_qos_idx2id(int unit, int hw_idx, int type, int *map_id) 2125 { 2126 int id, num_map; 2127 2128 QOS_INIT(unit); 2129 2130 switch (type) { 2131 case _BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS: 2132 num_map = soc_mem_index_count(unit, EGR_MPLS_EXP_MAPPING_1m) / 64; 2133 for (id = 0; id < num_map; id++) { 2134 if (_BCM_QOS_EGR_MPLS_USED_GET(unit, id)) { 2135 if (QOS_INFO(unit)->egr_mpls_hw_idx[id] == hw_idx) { 2136 *map_id = id | (_BCM_QOS_MAP_TYPE_EGR_MPLS_MAPS 2137 << _BCM_QOS_MAP_SHIFT); 2138 return BCM_E_NONE; 2139 } 2140 } 2141 } 2142 break; 2143 case _BCM_QOS_MAP_TYPE_DSCP_TABLE: 2144 num_map = soc_mem_index_count(unit, DSCP_TABLEm) / 64; 2145 for (id = 0; id < num_map; id++) { 2146 if (_BCM_QOS_DSCP_TABLE_USED_GET(unit, id)) { 2147 if (QOS_INFO(unit)->dscp_hw_idx[id] == hw_idx) { 2148 *map_id = id | (_BCM_QOS_MAP_TYPE_DSCP_TABLE 2149 << _BCM_QOS_MAP_SHIFT); 2150 return BCM_E_NONE; 2151 } 2152 } 2153 } 2154 break; 2155 default: 2156 return BCM_E_NOT_FOUND; 2157 } 2158 return BCM_E_NOT_FOUND; 2159 } 2160 #endif