qos.c (58441B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: qos.c 8 * Purpose: Tomahawk QoS functions 9 */ 10 #include <soc/mem.h> 11 #include <soc/debug.h> 12 #include <soc/cm.h> 13 #include <soc/drv.h> 14 #include <soc/register.h> 15 #include <soc/memory.h> 16 #include <soc/hash.h> 17 #include <soc/l2x.h> 18 #include <bcm/l2.h> 19 #include <bcm/error.h> 20 #include <bcm_int/esw/trx.h> 21 #include <bcm_int/esw/l2.h> 22 #include <bcm_int/esw/qos.h> 23 #include <bcm_int/esw/triumph2.h> 24 #include <bcm_int/esw/tomahawk.h> 25 #include <bcm_int/esw/xgs3.h> 26 #include <bcm_int/esw_dispatch.h> 27 #include <bcm/qos.h> 28 29 #ifdef BCM_TOMAHAWK_SUPPORT 30 31 #define _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP 16 32 #define _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP 64 33 34 #define _BCM_QOS_MAX_PKT_PRIORITIES 8 35 #define _BCM_QOS_MAX_INT_PRIORITIES 16 36 #define _BCM_QOS_MAX_PKT_DES 2 37 38 #define _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS \ 39 (soc_mem_index_count(unit, ING_ETAG_PCP_MAPPINGm)/ \ 40 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP) 41 #define _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS \ 42 (soc_mem_index_count(unit, EGR_ETAG_PCP_MAPPINGm)/ \ 43 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP) 44 45 #define _BCM_QOS_MAX_L2_VLAN_ETAG_MAP_IDS ((_BCM_QOS_MAX_L2_VLAN_ETAG_MAPS)\ 46 * _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP) 47 #define _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAP_IDS ((_BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS)\ 48 * _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP) 49 50 #define _BCM_QOS_MAP_TYPE_MASK 0x7ff 51 #define _BCM_QOS_MAP_SHIFT 11 52 53 #define _BCM_QOS_NO_MAP -1 54 55 typedef struct _bcm_th_qos_bookkeeping_s { 56 SHR_BITDCL *ing_l2_vlan_etag_map; 57 uint32 *ing_l2_vlan_etag_map_hwidx; 58 SHR_BITDCL *egr_l2_vlan_etag_map; 59 uint32 *egr_l2_vlan_etag_map_hwidx; 60 sal_mutex_t qos_mutex; 61 } _bcm_th_qos_bookkeeping_t; 62 63 static _bcm_th_qos_bookkeeping_t _bcm_th_qos_bk_info[BCM_MAX_NUM_UNITS]; 64 static int _bcm_th_qos_initialized[BCM_MAX_NUM_UNITS] = { 0 }; 65 66 #define TH_QOS_INFO(_unit_) (&_bcm_th_qos_bk_info[_unit_]) 67 68 #define _BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_GET(_u_, _identifier_) \ 69 SHR_BITGET(TH_QOS_INFO(_u_)->ing_l2_vlan_etag_map, (_identifier_)) 70 #define _BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_SET(_u_, _identifier_) \ 71 SHR_BITSET(TH_QOS_INFO((_u_))->ing_l2_vlan_etag_map, (_identifier_)) 72 #define _BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_CLR(_u_, _identifier_) \ 73 SHR_BITCLR(TH_QOS_INFO((_u_))->ing_l2_vlan_etag_map, (_identifier_)) 74 75 #define _BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_GET(_u_, _identifier_) \ 76 SHR_BITGET(TH_QOS_INFO(_u_)->egr_l2_vlan_etag_map, (_identifier_)) 77 #define _BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_SET(_u_, _identifier_) \ 78 SHR_BITSET(TH_QOS_INFO((_u_))->egr_l2_vlan_etag_map, (_identifier_)) 79 #define _BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_CLR(_u_, _identifier_) \ 80 SHR_BITCLR(TH_QOS_INFO((_u_))->egr_l2_vlan_etag_map, (_identifier_)) 81 82 #define QOS_LOCK(unit) \ 83 sal_mutex_take(TH_QOS_INFO(unit)->qos_mutex, sal_mutex_FOREVER); 84 #define QOS_UNLOCK(unit) \ 85 sal_mutex_give(TH_QOS_INFO(unit)->qos_mutex); 86 87 #define QOS_INIT(unit) \ 88 do { \ 89 if ((unit < 0) || (unit >= BCM_MAX_NUM_UNITS)) { \ 90 return BCM_E_UNIT; \ 91 } \ 92 if (!_bcm_th_qos_initialized[unit]) { \ 93 return BCM_E_INIT; \ 94 } \ 95 } while (0) 96 97 /* 98 * Function: 99 * _bcm_th_qos_map_id_alloc 100 * Purpose: 101 * Allocate a new QOS map ID. The bitmap given contains bits set for 102 * existing IDs, so find the first empty one, set it, and return it. 103 * Parameters: 104 * unit - (IN) Unit to be operated on 105 * bitmap - (IN/OUT) 106 * id - (OUT) 107 * Returns: 108 * BCM_E_XXX 109 */ 110 STATIC int 111 _bcm_th_qos_map_id_alloc(int unit, SHR_BITDCL *bitmap, int *id, 112 int map_size) 113 { 114 int i; 115 116 for (i = 0; i < map_size; i++) { 117 if (!SHR_BITGET(bitmap, i)) { 118 SHR_BITSET(bitmap, i); 119 *id = i; 120 return BCM_E_NONE; 121 } 122 } 123 124 return BCM_E_RESOURCE; 125 } 126 127 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP 128 /* 129 * Function: 130 * _bcm_th_qos_sw_dump 131 * Purpose: 132 * Displays QOS software state info 133 * Parameters: 134 * unit : (IN) Device Unit Number 135 * Returns: 136 * NONE 137 */ 138 void 139 _bcm_th_qos_sw_dump(int unit) 140 { 141 int i; 142 if (!_bcm_th_qos_initialized[unit]) { 143 LOG_CLI((BSL_META_U(unit, 144 "ERROR: QOS module not initialized on Unit:%d \n"), unit)); 145 return; 146 } 147 148 LOG_CLI((BSL_META_U(unit, 149 "QOS: ING_L2_VLAN_ETAG_MAP info \n"))); 150 for (i = 0; i < _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS; i++) { 151 if (_BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, i)) { 152 LOG_CLI((BSL_META_U(unit, 153 " map id:%4d HW index:%4d\n"), i, 154 TH_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[i])); 155 } 156 } 157 158 LOG_CLI((BSL_META_U(unit, 159 "QOS: EGR_L2_VLAN_ETAG_MAP info \n"))); 160 for (i = 0; i < _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS; i++) { 161 if (_BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, i)) { 162 LOG_CLI((BSL_META_U(unit, 163 " map id:%4d HW index:%4d\n"), i, 164 TH_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[i])); 165 } 166 } 167 } 168 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */ 169 170 #ifdef BCM_WARM_BOOT_SUPPORT 171 #define _BCM_TH_REINIT_INVALID_HW_IDX 0xff /* used as an invalid hw idx */ 172 173 /* 174 * Function: 175 * _bcm_th_qos_reinit_scache_len_get 176 * Purpose: 177 * Helper utility to determine scache details. 178 * Parameters: 179 * unit : (IN) Device Unit Number 180 * scache_len : (OUT) Total required scache length 181 * Returns: 182 * BCM_E_XXX 183 */ 184 int 185 _bcm_th_qos_reinit_scache_len_get(int unit, uint32 *scache_len) 186 { 187 if (scache_len == NULL) { 188 return BCM_E_PARAM; 189 } 190 191 *scache_len += _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS * sizeof(uint32); 192 *scache_len += _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS * sizeof(uint32); 193 194 return BCM_E_NONE; 195 } 196 197 int 198 _bcm_th_qos_reinit_from_hw_state(int unit, soc_mem_t mem, 199 soc_field_t field, uint8 map_type, 200 SHR_BITDCL *hw_idx_bmp, 201 int hw_idx_bmp_len) 202 { 203 int rv = BCM_E_NONE; 204 int idx, min_idx, max_idx, map_size, map_id, hw_prof_idx; 205 uint32 buf[SOC_MAX_MEM_FIELD_WORDS]; 206 uint32 *hw_idx_table; 207 SHR_BITDCL *map_bmp; 208 209 switch (map_type) { 210 case _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP: 211 map_bmp = TH_QOS_INFO(unit)->ing_l2_vlan_etag_map; 212 hw_idx_table = TH_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx; 213 map_size = _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS; 214 break; 215 case _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP: 216 map_bmp = TH_QOS_INFO(unit)->egr_l2_vlan_etag_map; 217 hw_idx_table = TH_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx; 218 map_size = _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS; 219 break; 220 default: 221 return BCM_E_PARAM; 222 } 223 224 min_idx = soc_mem_index_min(unit, mem); 225 max_idx = soc_mem_index_max(unit, mem); 226 227 for (idx = min_idx; idx <= max_idx; idx++) { 228 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, &buf); 229 if (SOC_FAILURE(rv)) { 230 LOG_ERROR(BSL_LS_BCM_QOS, 231 (BSL_META_U(unit, 232 "Error(%s) reading mem(%d) at " 233 "index:%d \n"), soc_errmsg(rv), mem, idx)); 234 return rv; 235 } 236 237 hw_prof_idx = soc_mem_field32_get(unit, mem, &buf, field); 238 239 if (hw_prof_idx > (hw_idx_bmp_len - 1)) { 240 LOG_ERROR(BSL_LS_BCM_QOS, 241 (BSL_META_U(unit, 242 "Invalid profile(%d) in mem(%d) " 243 "at index:%d\n"), hw_prof_idx, mem, idx)); 244 return BCM_E_INTERNAL; 245 } 246 if (hw_prof_idx && (!SHR_BITGET(hw_idx_bmp, hw_prof_idx))) { 247 /* non-zero profile id and not stored previously */ 248 BCM_IF_ERROR_RETURN(_bcm_th_qos_map_id_alloc(unit, map_bmp, &map_id, 249 map_size)); 250 if (map_id < 0) { 251 LOG_ERROR(BSL_LS_BCM_QOS, 252 (BSL_META_U(unit, 253 "Invalid profile(%d) in mem" 254 "(%d) at index:%d\n"), hw_prof_idx, mem, idx)); 255 return BCM_E_RESOURCE; 256 } 257 hw_idx_table[map_id] = hw_prof_idx; 258 SHR_BITSET(hw_idx_bmp, hw_prof_idx); 259 SHR_BITSET(map_bmp, map_id); 260 } 261 } 262 263 return rv; 264 } 265 266 /* 267 * Function: 268 * _bcm_th_qos_unsynchronized_reinit 269 * Purpose: 270 * This routine handles Level 1 Warmboot init. In this style of reinit, the 271 * map-ids allocated previously are not guaranteed to be the same. 272 * Cold-boot: Does nothing 273 * Warm-boot: The data-structures are populated by reading the HW tables. 274 * Parameters: 275 * unit : (IN) Device Unit Number 276 * Returns: 277 * BCM_E_XXX 278 */ 279 int 280 _bcm_th_qos_unsynchronized_reinit(int unit) 281 { 282 int rv = BCM_E_NONE; 283 int bmp_len; 284 SHR_BITDCL *temp_bmp; 285 286 /* read hw tables and populate the state */ 287 bmp_len = _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS; 288 temp_bmp = NULL; 289 temp_bmp = sal_alloc(SHR_BITALLOCSIZE(bmp_len), "temp_bmp"); 290 if (temp_bmp == NULL) { 291 return BCM_E_MEMORY; 292 } 293 sal_memset(temp_bmp, 0x0, SHR_BITALLOCSIZE(bmp_len)); 294 295 if (soc_mem_is_valid(unit, PORT_TABm)) { 296 rv = _bcm_th_qos_reinit_from_hw_state(unit, PORT_TABm, 297 ETAG_PCP_DE_MAPPING_PTRf, 298 _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP, 299 temp_bmp, bmp_len); 300 } 301 sal_free(temp_bmp); 302 303 /* now extract EGR_MPLS_PRI_MAPPING state */ 304 if (BCM_SUCCESS(rv)) { 305 bmp_len = _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS; 306 temp_bmp = NULL; 307 temp_bmp = sal_alloc(SHR_BITALLOCSIZE(bmp_len), "temp_bmp"); 308 if (temp_bmp == NULL) { 309 return BCM_E_MEMORY; 310 } 311 sal_memset(temp_bmp, 0x0, SHR_BITALLOCSIZE(bmp_len)); 312 if (soc_mem_field_valid(unit, PORT_TABm, 313 ETAG_DOT1P_MAPPING_PTRf)) { 314 rv = _bcm_th_qos_reinit_from_hw_state(unit, PORT_TABm, 315 ETAG_DOT1P_MAPPING_PTRf, 316 _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP, 317 temp_bmp, bmp_len); 318 } 319 sal_free(temp_bmp); 320 } 321 322 return rv; 323 } 324 325 /* 326 * Function: 327 * _bcm_th_qos_extended_reinit 328 * Purpose: 329 * This routine handles Level 2 Warmboot init. 330 * Cold-boot: scache location is allocated. 331 * Warm-boot: The data-structs are populated from recovered scache state 332 * Parameters: 333 * unit : (IN) Device Unit Number 334 * Returns: 335 * BCM_E_XXX 336 */ 337 int 338 _bcm_th_qos_extended_reinit(int unit, uint8 **scache_ptr) 339 { 340 uint32 hw_idx; 341 int idx; 342 343 for (idx = 0; idx < _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS; idx++) { 344 sal_memcpy(&hw_idx, (*scache_ptr), sizeof(uint32)); 345 (*scache_ptr) += sizeof(hw_idx); 346 if (hw_idx != _BCM_TH_REINIT_INVALID_HW_IDX) { 347 _BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_SET(unit, idx); 348 TH_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[idx] = hw_idx; 349 } 350 } 351 for (idx = 0; idx < _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS; idx++) { 352 sal_memcpy(&hw_idx, (*scache_ptr), sizeof(uint32)); 353 (*scache_ptr) += sizeof(hw_idx); 354 if (hw_idx != _BCM_TH_REINIT_INVALID_HW_IDX) { 355 _BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_SET(unit, idx); 356 TH_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[idx] = hw_idx; 357 } 358 } 359 360 return BCM_E_NONE; 361 } 362 363 /* 364 * Function: 365 * _bcm_th_qos_reinit_hw_profiles_update 366 * Purpose: 367 * Updates the shared memory profile tables reference counts 368 * Parameters: 369 * unit : (IN) Device Unit Number 370 * Returns: 371 * BCM_E_XXX 372 */ 373 int 374 _bcm_th_qos_reinit_hw_profiles_update(int unit) 375 { 376 int i; 377 378 for (i = 0; i < _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS; i++) { 379 if (_BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, i)) { 380 BCM_IF_ERROR_RETURN(_bcm_ing_l2_vlan_etag_map_entry_reference(unit, 381 ((TH_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[i]) * 382 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP), 383 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP)); 384 } 385 } 386 for (i = 0; i < _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS; i++) { 387 if (_BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, i)) { 388 BCM_IF_ERROR_RETURN(_bcm_egr_l2_vlan_etag_map_entry_reference(unit, 389 ((TH_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[i]) * 390 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP), 391 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP)); 392 } 393 } 394 395 return BCM_E_NONE; 396 } 397 398 /* 399 * Function: 400 * _bcm_th_qos_sync 401 * Purpose: 402 * This routine extracts the state that needs to be stored from the 403 * book-keeping structs and stores it in the allocated scache location 404 * Compression format: 0 - A l2_vlan_etag table 405 * A+1 - B egr_l2_vlan_etag table 406 * Parameters: 407 * unit : (IN) Device Unit Number 408 * Returns: 409 * BCM_E_XXX 410 */ 411 int 412 _bcm_th_qos_sync(int unit, uint8 **scache_ptr) 413 { 414 uint32 hw_idx; 415 int idx; 416 417 /* now store the state into the compressed format */ 418 for (idx = 0; idx < _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS; idx++) { 419 if (_BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, idx)) { 420 hw_idx = TH_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[idx]; 421 } else { 422 hw_idx = _BCM_TH_REINIT_INVALID_HW_IDX; 423 } 424 sal_memcpy((*scache_ptr), &hw_idx, sizeof(uint32)); 425 (*scache_ptr) += sizeof(hw_idx); 426 } 427 for (idx = 0; idx < _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS; idx++) { 428 if (_BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, idx)) { 429 hw_idx = TH_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[idx]; 430 } else { 431 hw_idx = _BCM_TH_REINIT_INVALID_HW_IDX; 432 } 433 sal_memcpy((*scache_ptr), &hw_idx, sizeof(uint32)); 434 (*scache_ptr) += sizeof(hw_idx); 435 } 436 437 return BCM_E_NONE; 438 } 439 #endif /* BCM_WARM_BOOT_SUPPORT */ 440 441 /* 442 * Function: 443 * _bcm_th_qos_free_resources 444 * Purpose: 445 * Free QOS bookkeeping resources associated with a given unit. This 446 * happens either during an error initializing or during a detach operation. 447 * Parameters: 448 * unit - (IN) Unit to free resources of 449 * Returns: 450 * BCM_E_XXX 451 */ 452 STATIC void 453 _bcm_th_qos_free_resources(int unit) 454 { 455 _bcm_th_qos_bookkeeping_t *qos_info = TH_QOS_INFO(unit); 456 457 if (!qos_info) { 458 /* 459 * Coverity 460 * This is defencive statement. 461 */ 462 /* coverity[dead_error_line] */ 463 return; 464 } 465 if (qos_info->ing_l2_vlan_etag_map) { 466 sal_free(qos_info->ing_l2_vlan_etag_map); 467 qos_info->ing_l2_vlan_etag_map = NULL; 468 } 469 470 if (qos_info->ing_l2_vlan_etag_map_hwidx) { 471 sal_free(qos_info->ing_l2_vlan_etag_map_hwidx); 472 qos_info->ing_l2_vlan_etag_map_hwidx = NULL; 473 } 474 475 if (qos_info->egr_l2_vlan_etag_map) { 476 sal_free(qos_info->egr_l2_vlan_etag_map); 477 qos_info->egr_l2_vlan_etag_map = NULL; 478 } 479 480 if (qos_info->egr_l2_vlan_etag_map_hwidx) { 481 sal_free(qos_info->egr_l2_vlan_etag_map_hwidx); 482 qos_info->egr_l2_vlan_etag_map_hwidx = NULL; 483 } 484 485 if (qos_info->qos_mutex) { 486 sal_mutex_destroy(qos_info->qos_mutex); 487 qos_info->qos_mutex = NULL; 488 } 489 } 490 491 /* 492 * Function: 493 * bcm_th_qos_detach 494 * Purpose: 495 * Detach the QOS module. Called when the module should de-initialize. 496 * Parameters: 497 * unit - (IN) Unit being detached. 498 * Returns: 499 * BCM_E_XXX 500 */ 501 int 502 bcm_th_qos_detach(int unit) 503 { 504 if (_bcm_th_qos_initialized[unit]) { 505 _bcm_th_qos_initialized[unit] = 0; 506 _bcm_th_qos_free_resources(unit); 507 } 508 509 return BCM_E_NONE; 510 } 511 512 /* 513 * Function: 514 * bcm_th_qos_init 515 * Purpose: 516 * Initialize the TH QOS module. Allocate bookkeeping information. 517 * Parameters: 518 * unit - (IN) Unit being initialized 519 * Returns: 520 * BCM_E_XXX 521 */ 522 int 523 bcm_th_qos_init(int unit) 524 { 525 _bcm_th_qos_bookkeeping_t *qos_info = TH_QOS_INFO(unit); 526 int l2_vlan_tag_map_size = _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS; 527 int egr_l2_vlan_tag_map_size = _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS; 528 bcm_pbmp_t all_pbmp; 529 uint32 entry[SOC_MAX_MEM_WORDS]; 530 bcm_port_t port; 531 int index; 532 533 if (_bcm_th_qos_initialized[unit]) { 534 BCM_IF_ERROR_RETURN(bcm_th_qos_detach(unit)); 535 } 536 537 memset(qos_info, 0, sizeof *qos_info); 538 539 /* ingress l2 vlan etag map bitmap */ 540 qos_info->ing_l2_vlan_etag_map = 541 sal_alloc(SHR_BITALLOCSIZE(l2_vlan_tag_map_size), 542 "ing_l2_vlan_etag_map"); 543 if (qos_info->ing_l2_vlan_etag_map == NULL) { 544 _bcm_th_qos_free_resources(unit); 545 return BCM_E_MEMORY; 546 } 547 sal_memset(qos_info->ing_l2_vlan_etag_map, 0, 548 SHR_BITALLOCSIZE(l2_vlan_tag_map_size)); 549 550 /* ingress l2 vlan etag map hardware indexes */ 551 qos_info->ing_l2_vlan_etag_map_hwidx = 552 sal_alloc(sizeof(uint32) * l2_vlan_tag_map_size, 553 "ing_l2_vlan_etag_map_hwidx"); 554 if (qos_info->ing_l2_vlan_etag_map_hwidx == NULL) { 555 _bcm_th_qos_free_resources(unit); 556 return BCM_E_MEMORY; 557 } 558 sal_memset(qos_info->ing_l2_vlan_etag_map_hwidx, 0, 559 sizeof(uint32) * l2_vlan_tag_map_size); 560 561 /* egress l2 vlan etag priority map bitmap */ 562 qos_info->egr_l2_vlan_etag_map = sal_alloc(SHR_BITALLOCSIZE(egr_l2_vlan_tag_map_size), 563 "egr_l2_vlan_etag_map"); 564 if (qos_info->egr_l2_vlan_etag_map == NULL) { 565 _bcm_th_qos_free_resources(unit); 566 return BCM_E_MEMORY; 567 } 568 sal_memset(qos_info->egr_l2_vlan_etag_map, 0, 569 SHR_BITALLOCSIZE(egr_l2_vlan_tag_map_size)); 570 571 /* egress l2 vlan etag map hardware indexes */ 572 qos_info->egr_l2_vlan_etag_map_hwidx = 573 sal_alloc(sizeof(uint32) * egr_l2_vlan_tag_map_size, 574 "egr_l2_vlan_etag_map_hwidx"); 575 if (qos_info->egr_l2_vlan_etag_map_hwidx == NULL) { 576 _bcm_th_qos_free_resources(unit); 577 return BCM_E_MEMORY; 578 } 579 sal_memset(qos_info->egr_l2_vlan_etag_map_hwidx, 0, 580 sizeof(uint32) * egr_l2_vlan_tag_map_size); 581 582 /* accessor mutex */ 583 qos_info->qos_mutex = sal_mutex_create("vft qos_mutex"); 584 if (qos_info->qos_mutex == NULL) { 585 _bcm_th_qos_free_resources(unit); 586 return BCM_E_MEMORY; 587 } 588 589 if (SOC_WARM_BOOT(unit)) { 590 /* Update reference counts for DSCP_TABLE profile*/ 591 BCM_PBMP_CLEAR(all_pbmp); 592 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 593 594 PBMP_ITER(all_pbmp, port) { 595 if (IS_LB_PORT(unit, port)) { 596 /* Loopback port base starts from 64 */ 597 continue; 598 } 599 SOC_IF_ERROR_RETURN(soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ALL, 600 port, &entry)); 601 index = soc_mem_field32_get(unit, PORT_TABm, &entry, TRUST_DSCP_PTRf); 602 SOC_IF_ERROR_RETURN(_bcm_dscp_table_entry_reference(unit, index * 64, 64)); 603 } 604 } 605 606 _bcm_th_qos_initialized[unit] = 1; 607 return BCM_E_NONE; 608 } 609 610 /* 611 * Function: 612 * _bcm_th_qos_flags_sanity_check 613 * Purpose: 614 * Check that the combination of flags specified is valid. 615 * Parameters: 616 * flags - (IN) BCM_QOS_MAP_* flags (eg. ingress/egress/with_id/replace) 617 * Returns: 618 * BCM_E_XXX 619 */ 620 STATIC int 621 _bcm_th_qos_flags_sanity_check(uint32 flags) 622 { 623 int rv = BCM_E_NONE; 624 625 /* must be ingress or egress, not both */ 626 if ((flags & BCM_QOS_MAP_INGRESS) && (flags & BCM_QOS_MAP_EGRESS)) { 627 rv = BCM_E_PARAM; 628 } 629 630 /* must be ingress or egress, not neither */ 631 if (!(flags & BCM_QOS_MAP_INGRESS) && !(flags & BCM_QOS_MAP_EGRESS)) { 632 rv = BCM_E_PARAM; 633 } 634 635 /* support BCM_QOS_MAP_L2_VLAN_ETAG */ 636 if (!(flags & BCM_QOS_MAP_L2_VLAN_ETAG)) { 637 rv = BCM_E_PARAM; 638 } 639 640 return rv; 641 } 642 643 /* 644 * Function: 645 * _bcm_th_qos_assign_creation_table_vars 646 * Purpose: 647 * Assign the various pointers to tables and table sizes and bitmaps used 648 * for the bcm_th_qos_map_create so that it can create the different types 649 * of maps with common logic. 650 * 651 * Assumes "flags" has already been validated. 652 * Parameters: 653 * unit - (IN) Unit to be operated on 654 * flags - (IN) BCM_QOS_MAP_* flags (eg. ingress/egress/with_id/etc) 655 * is_ingress - (OUT) 1 for ingress, 0 for egress map 656 * bitmap - (OUT) pointer to priority map's bitmap 657 * hwmap - (OUT) pointer to priority map's hwidx mapping 658 * map_type - (OUT) _BCM_QOS_MAP_TYPE_* 659 * map_size - (OUT) size of the selected map 660 * max_maps - (OUT) maximum number of maps available for the selected type 661 * Returns: 662 * None 663 */ 664 STATIC void 665 _bcm_th_qos_assign_creation_table_vars(int unit, int flags, int *is_ingress, 666 SHR_BITDCL **bitmap, 667 uint32 **hwmap, int *map_type, 668 int *map_size, int *max_maps) 669 { 670 if (flags & BCM_QOS_MAP_INGRESS) { 671 *is_ingress = 1; 672 if (flags & BCM_QOS_MAP_L2_VLAN_ETAG) { 673 *bitmap = TH_QOS_INFO(unit)->ing_l2_vlan_etag_map; 674 *hwmap = TH_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx; 675 *map_type = _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP; 676 *map_size = _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS; 677 *max_maps = _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS; 678 } 679 } else if (flags & BCM_QOS_MAP_EGRESS) { 680 *is_ingress = 0; 681 682 if (flags & BCM_QOS_MAP_L2_VLAN_ETAG) { 683 *bitmap = TH_QOS_INFO(unit)->egr_l2_vlan_etag_map; 684 *hwmap = TH_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx; 685 *map_type = _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP; 686 *map_size = _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS; 687 *max_maps = _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS; 688 } 689 } 690 } 691 692 /* 693 * Function: 694 * _bcm_th_qos_count_used_maps 695 * Purpose: 696 * Count the number maps currently used in hardware. Since IDs in app-space 697 * can point to the same hardware index, count how many hardware indexes are 698 * used, ignoring duplicates. 699 * Parameters: 700 * unit - (IN) Unit to be operated on 701 * bitmap - (IN) Bitmap of used map IDs 702 * hwmap - (IN) Array that maps userspace IDs to hardware IDs 703 * Returns: 704 * integer containing the number of used hardware indexes 705 */ 706 STATIC int 707 _bcm_th_qos_count_used_maps(int unit, SHR_BITDCL *bitmap, uint32 *hwmap, 708 int map_size, int max_maps) 709 { 710 uint8 *hw_used = sal_alloc(map_size, "TH_qos_used_maps"); 711 int total_used = 0; 712 int i = 0; 713 714 if (hw_used == NULL) { 715 return max_maps; 716 } 717 718 memset(hw_used, 0, map_size); 719 720 for (i = 0; i < map_size; i++) { 721 if (SHR_BITGET(bitmap, i) && hw_used[hwmap[i]] == 0) { 722 hw_used[hwmap[i]] = 1; 723 total_used++; 724 } 725 } 726 727 sal_free(hw_used); 728 return total_used; 729 } 730 731 /* 732 * Function: 733 * _bcm_th_qos_map_create_with_id 734 * Purpose: 735 * Allocate a new QOS map ID where the app has specified the ID. So just 736 * check that the requested ID is available, and mark it as used. 737 * Parameters: 738 * unit - (IN) Unit to be operated on 739 * flags - (IN) Used only to test if BCM_QOS_MAP_REPLACE is set 740 * bitmap - (IN/OUT) Bitmap containing the set of used IDs 741 * map_id - (IN) The ID requested by the application 742 * is_ingress - (IN) 1=ingress map, 0=egress map 743 * Returns: 744 * BCM_E_XXX 745 */ 746 STATIC int 747 _bcm_th_qos_map_create_with_id(int unit, int flags, SHR_BITDCL *bitmap, 748 int *map_id, int is_ingress, int max_ids) 749 { 750 int id = 0, map_type = 0, rv = BCM_E_NONE; 751 752 id = *map_id & _BCM_QOS_MAP_TYPE_MASK; 753 map_type = *map_id >> _BCM_QOS_MAP_SHIFT; 754 755 if (id < 0 || id >= max_ids) { 756 return BCM_E_BADID; 757 } 758 759 if ((map_type == _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP && is_ingress)) { 760 761 if (SHR_BITGET(bitmap, id) == 1) { 762 if (!(flags & BCM_QOS_MAP_REPLACE)) { 763 rv = BCM_E_EXISTS; 764 } 765 } 766 767 if (BCM_SUCCESS(rv)) { 768 SHR_BITSET(bitmap, id); 769 } 770 } else { 771 rv = BCM_E_PARAM; 772 } 773 774 return rv; 775 } 776 777 /* 778 * Function: 779 * bcm_th_qos_map_create 780 * Purpose: 781 * Create a new QOS map. 782 * Parameters: 783 * unit - (IN) Unit to be operated on 784 * flags - (IN) BCM_QOS_MAP_* flags (eg. ingress/egress/with_id/replace) 785 * map_id - (IN/OUT) If BCM_QOS_MAP_WITH_ID is set, then this is the ID 786 * being requested. Otherwise, it's assigned as the ID 787 * allocated. 788 * Returns: 789 * BCM_E_XXX 790 */ 791 int 792 bcm_th_qos_map_create(int unit, uint32 flags, int *map_id) 793 { 794 int is_ingress = 0; 795 int map_type = 0; 796 SHR_BITDCL *bitmap = NULL; 797 uint32 index = 0; 798 int rv = BCM_E_NONE; 799 int id = 0; 800 void *entries[1]; 801 uint32 *hwmap = NULL; 802 int map_size = 0; 803 int max_maps = 0; 804 805 QOS_INIT(unit); 806 QOS_LOCK(unit); 807 808 rv = _bcm_th_qos_flags_sanity_check(flags); 809 810 if (BCM_SUCCESS(rv)) { 811 _bcm_th_qos_assign_creation_table_vars(unit, flags, &is_ingress, 812 &bitmap, &hwmap, &map_type, 813 &map_size, &max_maps); 814 } 815 816 if (BCM_SUCCESS(rv)) { 817 if (_bcm_th_qos_count_used_maps(unit, bitmap, hwmap, map_size, 818 max_maps) >= max_maps) { 819 rv = BCM_E_MEMORY; 820 } 821 } 822 823 if (BCM_SUCCESS(rv)) { 824 if (flags & BCM_QOS_MAP_WITH_ID) { 825 rv = _bcm_th_qos_map_create_with_id(unit, flags, bitmap, map_id, 826 is_ingress, map_size); 827 id = *map_id & _BCM_QOS_MAP_TYPE_MASK; 828 } else { 829 rv = _bcm_th_qos_map_id_alloc(unit, bitmap, &id, map_size); 830 if (BCM_SUCCESS(rv)) { 831 /*_BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_SET(unit, id);*/ 832 *map_id = id | (map_type << _BCM_QOS_MAP_SHIFT); 833 } 834 } 835 } 836 837 if (BCM_SUCCESS(rv)) { 838 if ((flags & BCM_QOS_MAP_INGRESS) && 839 (flags & BCM_QOS_MAP_L2_VLAN_ETAG)) { 840 ing_etag_pcp_mapping_entry_t 841 table[_BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP]; 842 memset(&table, 0, sizeof table); 843 entries[0] = &table; 844 845 rv = _bcm_ing_l2_vlan_etag_map_entry_add(unit, entries, 846 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP, 847 &index); 848 849 if (BCM_SUCCESS(rv)) { 850 TH_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[id] = index / 851 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP; 852 } 853 } else if ((flags & BCM_QOS_MAP_EGRESS) && 854 (flags & BCM_QOS_MAP_L2_VLAN_ETAG)) { 855 egr_etag_pcp_mapping_entry_t 856 table[_BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP]; 857 memset(&table, 0, sizeof table); 858 entries[0] = &table; 859 860 rv = _bcm_egr_l2_vlan_etag_map_entry_add(unit, entries, 861 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP, 862 &index); 863 864 if (BCM_SUCCESS(rv)) { 865 TH_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[id] = index / 866 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP; 867 } 868 } 869 } 870 871 QOS_UNLOCK(unit); 872 873 return rv; 874 } 875 876 /* 877 * Function: 878 * _bcm_th_qos_map_destroy 879 * Purpose: 880 * Destroy a map ID by removing it from hardware. 881 * Parameters: 882 * unit - (IN) The unit being operated on 883 * table - (IN) Indicates either ingress or egress 884 * id - (IN) The map ID being destroyed 885 * Returns: 886 * BCM_E_XXX 887 */ 888 STATIC int 889 _bcm_th_qos_map_destroy(int unit, int table, int id) 890 { 891 int rv = BCM_E_NONE; 892 _bcm_th_qos_bookkeeping_t *qos_info = TH_QOS_INFO(unit); 893 894 if (table == _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP) { 895 rv = _bcm_ing_l2_vlan_etag_map_entry_del(unit, 896 qos_info->ing_l2_vlan_etag_map_hwidx[id] * 897 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP); 898 } else if (table == _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP) { 899 rv = _bcm_egr_l2_vlan_etag_map_entry_del(unit, 900 qos_info->egr_l2_vlan_etag_map_hwidx[id] * 901 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP); 902 } 903 904 return rv; 905 } 906 907 /* 908 * Function: 909 * bcm_th_qos_map_destroy 910 * Purpose: 911 * Destroy a QOS map ID by removing it from hardware and deleting the 912 * associated software state info. 913 * Parameters: 914 * unit - (IN) Unit being operated on 915 * map_id - (IN) QOS map ID to be destroyed 916 * Returns: 917 * BCM_E_XXX 918 */ 919 int 920 bcm_th_qos_map_destroy(int unit, int map_id) 921 { 922 int id = map_id & _BCM_QOS_MAP_TYPE_MASK; 923 int rv = BCM_E_UNAVAIL; 924 925 QOS_INIT(unit); 926 QOS_LOCK(unit); 927 928 switch (map_id >> _BCM_QOS_MAP_SHIFT) { 929 case _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP: 930 if (!_BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, id)) { 931 rv = BCM_E_NOT_FOUND; 932 } else { 933 rv = _bcm_th_qos_map_destroy(unit, 934 _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP, id); 935 936 if (BCM_SUCCESS(rv)) { 937 _BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_CLR(unit, id); 938 } 939 } 940 break; 941 case _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP: 942 if (!_BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, id)) { 943 rv = BCM_E_NOT_FOUND; 944 } else { 945 rv = _bcm_th_qos_map_destroy(unit, 946 _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP, id); 947 948 if (BCM_SUCCESS(rv)) { 949 _BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_CLR(unit, id); 950 } 951 } 952 break; 953 default: 954 rv = BCM_E_PARAM; 955 } 956 957 QOS_UNLOCK(unit); 958 959 return rv; 960 } 961 962 /* 963 * Function: 964 * _bcm_th_qos_map_add_sanity_check 965 * Purpose: 966 * Check that all the paramters given to the bcm_qos_map_add() function make 967 * sense and are internally consistent. 968 * Parameters: 969 * unit - (IN) The unit being operated on 970 * flags - (IN) BCM_QOS_MAP_* flags sent in by the app 971 * map - (IN) The map structure sent in by the app 972 * map_id - (IN) The map ID sent in by the app 973 * Returns: 974 * BCM_E_XXX 975 */ 976 STATIC int 977 _bcm_th_qos_map_add_sanity_check(int unit, uint32 flags, bcm_qos_map_t *map, 978 int map_id) 979 { 980 int map_type = map_id >> _BCM_QOS_MAP_SHIFT; 981 int id = map_id & _BCM_QOS_MAP_TYPE_MASK; 982 int rv; 983 984 rv = _bcm_th_qos_flags_sanity_check(flags); 985 if (BCM_FAILURE(rv)) { 986 return rv; 987 } 988 989 if ((flags & BCM_QOS_MAP_INGRESS) && 990 (map_type != _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP)) { 991 return BCM_E_PARAM; 992 } 993 994 if ((flags & BCM_QOS_MAP_EGRESS) && 995 (map_type != _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP)) { 996 return BCM_E_PARAM; 997 } 998 999 if ((flags & BCM_QOS_MAP_INGRESS) && 1000 (map_type == _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP) && 1001 (_BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, id) == 0)) { 1002 return BCM_E_BADID; 1003 } 1004 1005 if ((flags & BCM_QOS_MAP_EGRESS) && 1006 (map_type == _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP) && 1007 (_BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, id) == 0)) { 1008 return BCM_E_BADID; 1009 } 1010 1011 if (!(flags & BCM_QOS_MAP_L2_VLAN_ETAG)) { 1012 if (map->int_pri < 0) { 1013 return BCM_E_PARAM; 1014 } 1015 } 1016 1017 if (map->pkt_pri >= _BCM_QOS_MAX_PKT_PRIORITIES) { 1018 return BCM_E_PARAM; 1019 } 1020 1021 if (flags & BCM_QOS_MAP_L2_VLAN_ETAG) { 1022 if ((map->etag_pcp >= _BCM_QOS_MAX_PKT_PRIORITIES) 1023 || (map->etag_de >= _BCM_QOS_MAX_PKT_DES) 1024 || (map->pkt_cfi >= _BCM_QOS_MAX_PKT_DES)) { 1025 return BCM_E_PARAM; 1026 } 1027 } 1028 1029 if ((flags & BCM_QOS_MAP_L2_VLAN_ETAG) && 1030 (flags & BCM_QOS_MAP_EGRESS)) { 1031 if (map->color != bcmColorGreen && map->color != bcmColorYellow 1032 && map->color != bcmColorRed) { 1033 return BCM_E_PARAM; 1034 } 1035 if (map->int_pri >= _BCM_QOS_MAX_INT_PRIORITIES) { 1036 return BCM_E_PARAM; 1037 } 1038 } 1039 1040 return BCM_E_NONE; 1041 } 1042 1043 /* 1044 * Function: 1045 * _bcm_th_ing_qos_map_update_index 1046 * Purpose: 1047 * Update an existing profile (or a newly created one) in the hardware's 1048 * table with a new mapping. 1049 * 1050 * The structure is: (1) get existing profile for this map from hardware, 1051 * (2) update the profile in RAM, (3) delete the old profile from hardware, 1052 * and (4) push the updated profile in RAM to hardware. 1053 * Parameters: 1054 * unit - (IN) The unit being operated on 1055 * map - (IN) Map structure sent in by app to be applied to hardware 1056 * map_id - (IN) Map ID sent in by app to be applied to hardware 1057 * Returns: 1058 * BCM_E_XXX 1059 */ 1060 STATIC int 1061 _bcm_th_ing_qos_map_update_index(int unit, bcm_qos_map_t *map, int map_id) 1062 { 1063 void *entries[1]; 1064 int rv = BCM_E_NONE; 1065 uint32 index; 1066 int id = map_id & _BCM_QOS_MAP_TYPE_MASK; 1067 1068 if (QOS_MAP_IS_L2_VLAN_ETAG(map_id)) { 1069 ing_etag_pcp_mapping_entry_t table[_BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP]; 1070 index = TH_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[id] * 1071 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP; 1072 1073 entries[0] = &table; 1074 rv = _bcm_ing_l2_vlan_etag_map_entry_get(unit, index, 1075 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP, 1076 entries); 1077 1078 if (BCM_SUCCESS(rv)) { 1079 ing_etag_pcp_mapping_entry_t *entry = 1080 &table[(map->pkt_pri << 1) | map->pkt_cfi]; 1081 1082 soc_mem_field32_set(unit, ING_ETAG_PCP_MAPPINGm, 1083 entry, PCPf, map->etag_pcp); 1084 soc_mem_field32_set(unit, ING_ETAG_PCP_MAPPINGm, 1085 entry, DEf, map->etag_de); 1086 1087 rv = _bcm_ing_l2_vlan_etag_map_entry_del(unit, (int)index); 1088 } 1089 1090 if (BCM_SUCCESS(rv)) { 1091 rv = _bcm_ing_l2_vlan_etag_map_entry_add(unit, entries, 1092 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP, 1093 &index); 1094 TH_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[id] = index / 1095 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP; 1096 } 1097 } 1098 return rv; 1099 } 1100 1101 /* 1102 * Function: 1103 * _bcm_th_egr_qos_map_update_index 1104 * Purpose: 1105 * Update an existing profile (or a newly created one) in the hardware's 1106 * table with a new mapping. 1107 * 1108 * The structure is: (1) get existing profile for this map from hardware, 1109 * (2) update the profile in RAM, (3) delete the old profile from hardware, 1110 * and (4) push the updated profile in RAM to hardware. 1111 * Parameters: 1112 * unit - (IN) The unit being operated on 1113 * map - (IN) Map structure sent in by app to be applied to hardware 1114 * map_id - (IN) Map ID sent in by app to be applied to hardware 1115 * Returns: 1116 * BCM_E_XXX 1117 */ 1118 STATIC int 1119 _bcm_th_egr_qos_map_update_index(int unit, bcm_qos_map_t *map, int map_id) 1120 { 1121 void *entries[1]; 1122 int rv = BCM_E_NONE; 1123 int cng; 1124 uint32 index; 1125 int id = map_id & _BCM_QOS_MAP_TYPE_MASK; 1126 1127 if (QOS_MAP_IS_L2_VLAN_ETAG(map_id)) { 1128 egr_etag_pcp_mapping_entry_t table[_BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP]; 1129 index = TH_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[id] * 1130 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP; 1131 1132 entries[0] = &table; 1133 rv = _bcm_egr_l2_vlan_etag_map_entry_get(unit, index, 1134 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP, 1135 entries); 1136 if (BCM_SUCCESS(rv)) { 1137 egr_etag_pcp_mapping_entry_t *entry; 1138 cng = _BCM_COLOR_ENCODING(unit, map->color); 1139 entry = &table[(map->int_pri << 2) | cng]; 1140 1141 soc_mem_field32_set(unit, EGR_ETAG_PCP_MAPPINGm, 1142 entry, PCPf, map->etag_pcp); 1143 soc_mem_field32_set(unit, EGR_ETAG_PCP_MAPPINGm, 1144 entry, DEf, map->etag_de); 1145 1146 rv = _bcm_egr_l2_vlan_etag_map_entry_del(unit, (int)index); 1147 } 1148 1149 if (BCM_SUCCESS(rv)) { 1150 rv = _bcm_egr_l2_vlan_etag_map_entry_add(unit, entries, 1151 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP, 1152 &index); 1153 TH_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[id] = index / 1154 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP; 1155 } 1156 } 1157 1158 return rv; 1159 } 1160 1161 /* 1162 * Function: 1163 * bcm_th_qos_map_add 1164 * Purpose: 1165 * Add a new QOS mapping to hardware. 1166 * Parameters: 1167 * unit - (IN) The unit being operated on 1168 * flags - (IN) BCM_QOS_MAP_* flags 1169 * map - (IN) Structure containing the priorities to be mapped 1170 * map_id - (IN) The ID of the map to add the new information to 1171 * Returns: 1172 * BCM_E_XXX 1173 */ 1174 int 1175 bcm_th_qos_map_add(int unit, uint32 flags, bcm_qos_map_t *map, int map_id) 1176 { 1177 int rv = BCM_E_NONE; 1178 1179 QOS_INIT(unit); 1180 QOS_LOCK(unit); 1181 1182 rv = _bcm_th_qos_map_add_sanity_check(unit, flags, map, map_id); 1183 if (BCM_SUCCESS(rv)) { 1184 if ((flags & BCM_QOS_MAP_INGRESS) && 1185 (flags & BCM_QOS_MAP_L2_VLAN_ETAG)) { 1186 rv = _bcm_th_ing_qos_map_update_index(unit, map, map_id); 1187 } else { 1188 rv = _bcm_th_egr_qos_map_update_index(unit, map, map_id); 1189 } 1190 } 1191 1192 QOS_UNLOCK(unit); 1193 1194 return rv; 1195 } 1196 1197 /* bcm_th_qos_map_multi_get */ 1198 int 1199 bcm_th_qos_map_multi_get(int unit, uint32 flags, 1200 int map_id, int array_size, 1201 bcm_qos_map_t *array, int *array_count) 1202 { 1203 int rv = BCM_E_NONE; 1204 int num_entries, idx, id, hw_id, alloc_size, entry_size, count; 1205 uint8 *dma_buf; 1206 void *entry; 1207 soc_mem_t mem; 1208 bcm_qos_map_t *map; 1209 int cng = 0; 1210 1211 /* ignore with_id & replace flags */ 1212 flags &= (~(BCM_QOS_MAP_WITH_ID | BCM_QOS_MAP_REPLACE)); 1213 id = map_id & _BCM_QOS_MAP_TYPE_MASK; 1214 mem = INVALIDm; 1215 hw_id = 0; 1216 num_entries = 0; 1217 entry_size = 0; 1218 QOS_LOCK(unit); 1219 switch (map_id >> _BCM_QOS_MAP_SHIFT) { 1220 case _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP: 1221 if ((flags != (BCM_QOS_MAP_L2_VLAN_ETAG | BCM_QOS_MAP_INGRESS)) || 1222 (!_BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, id))) { 1223 rv = BCM_E_PARAM; 1224 } 1225 num_entries = _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP; 1226 entry_size = sizeof(ing_etag_pcp_mapping_entry_t); 1227 hw_id = TH_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[id] * 1228 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP; 1229 mem = ING_ETAG_PCP_MAPPINGm; 1230 break; 1231 case _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP: 1232 if ((flags != (BCM_QOS_MAP_L2_VLAN_ETAG | BCM_QOS_MAP_EGRESS)) || 1233 (!_BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, id))) { 1234 rv = BCM_E_PARAM; 1235 } 1236 num_entries = _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP; 1237 entry_size = sizeof(egr_etag_pcp_mapping_entry_t); 1238 hw_id = TH_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[id] * 1239 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP; 1240 mem = EGR_ETAG_PCP_MAPPINGm; 1241 break; 1242 default: 1243 rv = BCM_E_PARAM; 1244 } 1245 QOS_UNLOCK(unit); 1246 BCM_IF_ERROR_RETURN(rv); 1247 1248 if (array_size == 0) { /* querying the size of map-chunk */ 1249 *array_count = num_entries; 1250 return BCM_E_NONE; 1251 } 1252 if (!array || !array_count) { 1253 return BCM_E_PARAM; 1254 } 1255 1256 /* Allocate memory for DMA & regular */ 1257 alloc_size = num_entries * entry_size; 1258 dma_buf = soc_cm_salloc(unit, alloc_size, "TH qos multi get DMA buf"); 1259 if (!dma_buf) { 1260 return BCM_E_MEMORY; 1261 } 1262 sal_memset(dma_buf, 0, alloc_size); 1263 1264 /* Read the profile chunk */ 1265 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, hw_id, 1266 (hw_id + num_entries - 1), dma_buf); 1267 if (BCM_FAILURE(rv)) { 1268 soc_cm_sfree(unit, dma_buf); 1269 return rv; 1270 } 1271 1272 count = 0; 1273 QOS_LOCK(unit); 1274 switch (map_id >> _BCM_QOS_MAP_SHIFT) { 1275 case _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP: 1276 for (idx=0; ((idx<num_entries) && (count < array_size)); idx++) { 1277 map = &array[idx]; 1278 sal_memset(map, 0x0, sizeof(bcm_qos_map_t)); 1279 map->pkt_pri = ((idx & 0xe) >> 1); 1280 map->pkt_cfi = (idx & 0x1); 1281 entry = soc_mem_table_idx_to_pointer(unit, mem, void *, 1282 dma_buf, idx); 1283 map->etag_pcp = soc_mem_field32_get(unit, mem, entry, PCPf); 1284 map->etag_de = soc_mem_field32_get(unit, mem, entry, DEf); 1285 count++; 1286 } 1287 break; 1288 case _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP: 1289 for (idx=0; ((idx<num_entries) && (count < array_size)); idx++) { 1290 map = &array[idx]; 1291 sal_memset(map, 0x0, sizeof(bcm_qos_map_t)); 1292 map->int_pri = ((idx & 0x3c) >> 2); 1293 cng = (idx & 0x3); 1294 map->color = _BCM_COLOR_DECODING(unit, cng); 1295 entry = soc_mem_table_idx_to_pointer(unit, mem, void *, 1296 dma_buf, idx); 1297 map->etag_pcp = soc_mem_field32_get(unit, mem, entry, PCPf); 1298 map->etag_de = soc_mem_field32_get(unit, mem, entry, DEf); 1299 count++; 1300 } 1301 break; 1302 default: 1303 rv = BCM_E_INTERNAL; /* should not hit this */ 1304 } 1305 QOS_UNLOCK(unit); 1306 soc_cm_sfree(unit, dma_buf); 1307 1308 BCM_IF_ERROR_RETURN(rv); 1309 1310 *array_count = count; 1311 return BCM_E_NONE; 1312 } 1313 1314 /* 1315 * Function: 1316 * bcm_th_qos_map_delete 1317 * Purpose: 1318 * Delete a mapping (for example, the map from 7 to 3). This is equivalent 1319 * to changing it to a map from 7 to 0, so this function maps the call into 1320 * bcm_td2_qos_map_add(). 1321 * Parameters: 1322 * unit - (IN) The unit being operated on 1323 * flags - (IN) BCM_QOS_MAP_* flags 1324 * map - (IN) Structure containing the priorities to be mapped 1325 * map_id - (IN) The ID of the map to add the new information to 1326 * Returns: 1327 * BCM_E_XXX 1328 */ 1329 int 1330 bcm_th_qos_map_delete(int unit, uint32 flags, bcm_qos_map_t *map, int map_id) 1331 { 1332 int rv = BCM_E_NONE; 1333 bcm_qos_map_t clr_map; 1334 1335 QOS_INIT(unit); 1336 1337 sal_memcpy(&clr_map, map, sizeof clr_map); 1338 1339 rv = _bcm_th_qos_flags_sanity_check(flags); 1340 if (BCM_SUCCESS(rv)) { 1341 if (flags & BCM_QOS_MAP_INGRESS) { 1342 if (flags & BCM_QOS_MAP_L2_VLAN_ETAG) { 1343 clr_map.etag_pcp = 0; 1344 clr_map.etag_de = 0; 1345 } 1346 } else { 1347 if(flags & BCM_QOS_MAP_L2_VLAN_ETAG) { 1348 clr_map.etag_pcp = 0; 1349 clr_map.etag_de = 0; 1350 } else { 1351 clr_map.pkt_pri = 0; 1352 } 1353 } 1354 } 1355 1356 if (BCM_SUCCESS(rv)) { 1357 rv = bcm_th_qos_map_add(unit, flags, &clr_map, map_id); 1358 } 1359 1360 return rv; 1361 } 1362 1363 /* 1364 * Function: 1365 * _bcm_th_qos_apply_ing_map_to_port 1366 * Purpose: 1367 * Apply a fully created ingress map to a hardware port. This is the final 1368 * step in the process, where the mapping becomes operational. 1369 * Parameters: 1370 * unit - (IN) Unit being operated on 1371 * ing_map - (IN) ID of the map to be applied 1372 * local_port - (IN) Local port number to apply map to 1373 * Returns: 1374 * BCM_E_XXX 1375 */ 1376 STATIC int 1377 _bcm_th_qos_apply_ing_map_to_port(int unit, int ing_map, bcm_port_t local_port) 1378 { 1379 int rv = BCM_E_PARAM; 1380 int id = ing_map & _BCM_QOS_MAP_TYPE_MASK; 1381 int profile_idx = TH_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[id]; 1382 1383 soc_mem_lock(unit, PORT_TABm); 1384 1385 if ((ing_map >> _BCM_QOS_MAP_SHIFT) == _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP) { 1386 rv = _bcm_tr2_port_tab_set(unit, local_port, ETAG_PCP_DE_MAPPING_PTRf, 1387 profile_idx); 1388 } 1389 1390 soc_mem_unlock(unit, PORT_TABm); 1391 1392 return rv; 1393 } 1394 1395 /* 1396 * Function: 1397 * _bcm_th_qos_apply_egr_map_to_port 1398 * Purpose: 1399 * Apply a fully created ingress map to a hardware port. This is the final 1400 * step in the process, where the mapping becomes operational. 1401 * Parameters: 1402 * unit - (IN) Unit being operated on 1403 * ing_map - (IN) ID of the map to be applied 1404 * local_port - (IN) Local port number to apply map to 1405 * Returns: 1406 * BCM_E_XXX 1407 */ 1408 STATIC int 1409 _bcm_th_qos_apply_egr_map_to_port(int unit, int egr_map, bcm_port_t local_port) 1410 { 1411 int rv = BCM_E_PARAM; 1412 int id = egr_map & _BCM_QOS_MAP_TYPE_MASK; 1413 int profile_idx = TH_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[id]; 1414 soc_mem_lock(unit, PORT_TABm); 1415 1416 if ((egr_map >> _BCM_QOS_MAP_SHIFT) == _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP) { 1417 rv = _bcm_tr2_port_tab_set(unit, local_port, ETAG_DOT1P_MAPPING_PTRf, 1418 profile_idx); 1419 } 1420 1421 soc_mem_unlock(unit, PORT_TABm); 1422 1423 return rv; 1424 } 1425 1426 /* 1427 * Function: 1428 * bcm_th_qos_port_map_set 1429 * Purpose: 1430 * Apply a fully created ingress and/or egress map to a given port. If 1431 * either map is given as -1 (_BCM_QOS_NO_MAP), then the parameter should be 1432 * ignored. 1433 * Parameters: 1434 * unit - (IN) The unit to be operated on 1435 * port - (IN) The port number for the map to be applied to 1436 * ing_map - (IN) The ID of an ingress map to be applied 1437 * egr_map - (IN) The ID of an egress map to be applied 1438 * Returns: 1439 * BCM_E_XXX 1440 */ 1441 int 1442 bcm_th_qos_port_map_set(int unit, bcm_gport_t port, int ing_map, int egr_map) 1443 { 1444 int rv = BCM_E_NONE; 1445 bcm_port_t local_port; 1446 1447 QOS_INIT(unit); 1448 QOS_LOCK(unit); 1449 1450 if (!BCM_GPORT_IS_SET(port)) { 1451 rv = BCM_E_PARAM; 1452 } 1453 1454 if (BCM_SUCCESS(rv)) { 1455 rv = bcm_esw_port_local_get(unit, port, &local_port); 1456 } 1457 1458 if (BCM_SUCCESS(rv) && !SOC_PORT_VALID(unit, local_port)) { 1459 rv = BCM_E_PARAM; 1460 } 1461 1462 if (BCM_SUCCESS(rv) && ing_map != _BCM_QOS_NO_MAP) { 1463 int id = ing_map & _BCM_QOS_MAP_TYPE_MASK; 1464 1465 if ((ing_map >> _BCM_QOS_MAP_SHIFT) != 1466 _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP){ 1467 rv = BCM_E_PARAM; 1468 } 1469 1470 if (BCM_SUCCESS(rv) 1471 && (((ing_map >> _BCM_QOS_MAP_SHIFT) == 1472 _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP) 1473 && (!_BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, id)))) { 1474 rv = BCM_E_PARAM; 1475 } 1476 1477 if (BCM_SUCCESS(rv)) { 1478 rv = _bcm_th_qos_apply_ing_map_to_port(unit, ing_map, local_port); 1479 } 1480 } 1481 1482 if (BCM_SUCCESS(rv) && egr_map != _BCM_QOS_NO_MAP) { 1483 int id = egr_map & _BCM_QOS_MAP_TYPE_MASK; 1484 1485 if ((egr_map >> _BCM_QOS_MAP_SHIFT) != 1486 _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP){ 1487 rv = BCM_E_PARAM; 1488 } 1489 1490 if (BCM_SUCCESS(rv) 1491 && (((egr_map >> _BCM_QOS_MAP_SHIFT) == 1492 _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP) 1493 && (!_BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, id)))) { 1494 rv = BCM_E_PARAM; 1495 } 1496 1497 if (BCM_SUCCESS(rv)) { 1498 rv = _bcm_th_qos_apply_egr_map_to_port(unit, egr_map, local_port); 1499 } 1500 } 1501 1502 QOS_UNLOCK(unit); 1503 1504 return rv; 1505 } 1506 1507 /* 1508 * Function: 1509 * _bcm_th_qos_port_ing_profile_get 1510 * Purpose: 1511 * Retrieve a specific ingress QoS map index from given port. 1512 * Parameters: 1513 * unit - (IN) Unit being operated on 1514 * local_port - (IN) Local port number to apply map to 1515 * ing_map_type - (IN) type of the map to be retrieved 1516 * profile_idx - (OUT) Hardware index 1517 * Returns: 1518 * BCM_E_XXX 1519 */ 1520 STATIC int 1521 _bcm_th_qos_port_ing_profile_get(int unit, bcm_port_t local_port, 1522 int ing_map_type, int *profile_idx) 1523 { 1524 int rv = BCM_E_PARAM; 1525 1526 if (profile_idx == NULL) { 1527 return BCM_E_PARAM; 1528 } 1529 1530 if (ing_map_type == _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP) { 1531 rv = _bcm_esw_port_tab_get(unit, local_port, ETAG_PCP_DE_MAPPING_PTRf, 1532 profile_idx); 1533 } 1534 1535 return rv; 1536 } 1537 1538 /* 1539 * Function: 1540 * _bcm_th_qos_port_egr_profile_get 1541 * Purpose: 1542 * Retrieve a specific egress QoS map index from given port. 1543 * Parameters: 1544 * unit - (IN) Unit being operated on 1545 * local_port - (IN) Local port number to apply map to 1546 * egr_map_type - (IN) type of the map to be retrieved 1547 * profile_idx - (OUT) Hardware index 1548 * Returns: 1549 * BCM_E_XXX 1550 */ 1551 STATIC int 1552 _bcm_th_qos_port_egr_profile_get(int unit, bcm_port_t local_port, 1553 int egr_map_type, int *profile_idx) 1554 { 1555 int rv = BCM_E_PARAM; 1556 1557 if (profile_idx == NULL) { 1558 return BCM_E_PARAM; 1559 } 1560 1561 if (egr_map_type == _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP) { 1562 rv = BCM_E_UNAVAIL; 1563 } 1564 1565 return rv; 1566 } 1567 1568 1569 /* Function: 1570 * _bcm_th_qos_id2idx 1571 * Purpose: 1572 * Translate hardware table index into map ID used by API 1573 * Parameters: 1574 * Returns: 1575 * BCM_E_XXX 1576 */ 1577 int 1578 _bcm_th_qos_idx2id(int unit, int hw_idx, int type, int *map_id) 1579 { 1580 int idx; 1581 int rv = BCM_E_NOT_FOUND; 1582 1583 if (map_id == NULL) { 1584 return BCM_E_PARAM; 1585 } 1586 1587 QOS_INIT(unit); 1588 1589 switch (type) { 1590 case _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP: 1591 for (idx = 0; idx < _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS; idx++) { 1592 if (_BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, idx)) { 1593 if (TH_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[idx] 1594 == hw_idx) { 1595 *map_id = idx | (_BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP 1596 << _BCM_QOS_MAP_SHIFT); 1597 rv = BCM_E_NONE; 1598 break; 1599 } 1600 } 1601 } 1602 1603 break; 1604 1605 case _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP: 1606 for (idx = 0; idx < _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS; idx++) { 1607 if (_BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, idx)) { 1608 if (TH_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[idx] 1609 == hw_idx) { 1610 *map_id = idx | (_BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP 1611 << _BCM_QOS_MAP_SHIFT); 1612 rv = BCM_E_NONE; 1613 break; 1614 } 1615 } 1616 } 1617 1618 break; 1619 1620 default: 1621 rv = BCM_E_NOT_FOUND; 1622 } 1623 1624 return rv; 1625 } 1626 1627 /* 1628 * Function: 1629 * bcm_th_qos_port_map_type_get 1630 * Purpose: 1631 * Retrieve ingress or egress map from a given port. 1632 * Parameters: 1633 * unit - (IN) The unit to be operated on 1634 * port - (IN) The port number for the map to be retrieved from 1635 * flags - (IN) type of the map which is of interest 1636 * map_id - (OUT) The ID of map returned 1637 * Returns: 1638 * BCM_E_XXX 1639 */ 1640 int 1641 bcm_th_qos_port_map_type_get(int unit, bcm_gport_t port, uint32 flags, 1642 int *map_id) 1643 { 1644 int rv = BCM_E_NONE; 1645 bcm_port_t local_port; 1646 int map_type; 1647 int profile_idx; 1648 1649 QOS_INIT(unit); 1650 1651 if (map_id == NULL) { 1652 rv = BCM_E_PARAM; 1653 } 1654 if (!BCM_GPORT_IS_SET(port)) { 1655 rv = BCM_E_PARAM; 1656 } 1657 1658 if (BCM_SUCCESS(rv)) { 1659 rv = bcm_esw_port_local_get(unit, port, &local_port); 1660 } 1661 1662 if (BCM_SUCCESS(rv) && !SOC_PORT_VALID(unit, local_port)) { 1663 rv = BCM_E_PARAM; 1664 } 1665 1666 BCM_IF_ERROR_RETURN(rv); 1667 1668 if (flags & BCM_QOS_MAP_INGRESS) { 1669 if (flags & BCM_QOS_MAP_L2_VLAN_ETAG) { 1670 map_type = _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP; 1671 } else { 1672 rv = BCM_E_PARAM; 1673 return rv; 1674 } 1675 rv = _bcm_th_qos_port_ing_profile_get(unit, local_port, map_type, 1676 &profile_idx); 1677 } else if (flags & BCM_QOS_MAP_EGRESS) { 1678 if (flags & BCM_QOS_MAP_L2_VLAN_ETAG) { 1679 map_type = _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP; 1680 } else { 1681 rv = BCM_E_PARAM; 1682 return rv; 1683 } 1684 rv = _bcm_th_qos_port_egr_profile_get(unit, local_port, map_type, 1685 &profile_idx); 1686 } else { 1687 rv = BCM_E_PARAM; 1688 return rv; 1689 } 1690 1691 if(BCM_SUCCESS(rv)) { 1692 /* map H/W profile ID to API QoS map ID */ 1693 rv = _bcm_th_qos_idx2id(unit, profile_idx, map_type, map_id); 1694 } 1695 1696 return rv; 1697 } 1698 1699 /* Function: 1700 * bcm_th_qos_egr_etag_id2profile 1701 * Purpose: 1702 * Given a QOS map ID for a egress etag mapping profile, return the profile number 1703 * into the EGR_ETAG_PCP_MAPPING table. 1704 * Parameters: 1705 * unit - (IN) Unit being operated on 1706 * map_id - (IN) ID of the map to be retrieved 1707 * profile_num - (OUT) Hardware profile number that map_id maps to 1708 * Returns: 1709 * BCM_E_XXX 1710 */ 1711 int 1712 bcm_th_qos_egr_etag_id2profile(int unit, int map_id, int *profile_num) 1713 { 1714 int id; 1715 1716 QOS_INIT(unit); 1717 id = map_id & _BCM_QOS_MAP_TYPE_MASK; 1718 1719 QOS_LOCK(unit); 1720 if (!_BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, id)) { 1721 QOS_UNLOCK(unit); 1722 return BCM_E_NOT_FOUND; 1723 } else { 1724 *profile_num = TH_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[id]; 1725 } 1726 1727 QOS_UNLOCK(unit); 1728 return BCM_E_NONE; 1729 } 1730 1731 /* Function: 1732 * bcm_th_qos_egr_etag_profile2id 1733 * Purpose: 1734 * Given a EGR_ETAG_PCP_MAPPING table profile number, find the QOS map ID which maps to it. 1735 * Parameters: 1736 * unit - (IN) Unit being operated on 1737 * profile_num - (IN) profile number of the map to be retrieved 1738 * map_id - (OUT) Map ID that points to profile_num 1739 * Returns: 1740 * BCM_E_XXX 1741 */ 1742 int 1743 bcm_th_qos_egr_etag_profile2id(int unit, int profile_num, int *map_id) 1744 { 1745 int i; 1746 1747 QOS_INIT(unit); 1748 1749 QOS_LOCK(unit); 1750 for (i = 0; i < _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAP_IDS; i++) { 1751 if (TH_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[i] == profile_num) { 1752 *map_id = (_BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP << _BCM_QOS_MAP_SHIFT) | i; 1753 QOS_UNLOCK(unit); 1754 return BCM_E_NONE; 1755 } 1756 } 1757 1758 QOS_UNLOCK(unit); 1759 return BCM_E_BADID; 1760 } 1761 1762 int 1763 _bcm_th_qos_multi_get(int unit, int array_size, int *map_ids_array, 1764 int *flags_array, int *array_count) 1765 { 1766 /* Assume that QoS lock has been taken */ 1767 1768 int idx, count; 1769 int rv = BCM_E_NONE; 1770 1771 if (array_size == 0) { 1772 if (array_count == NULL) { 1773 rv = BCM_E_PARAM; 1774 } 1775 1776 if (BCM_SUCCESS(rv)) { 1777 *array_count = 0; 1778 count = 0; 1779 SHR_BITCOUNT_RANGE(TH_QOS_INFO(unit)->ing_l2_vlan_etag_map, count, 1780 0, _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS); 1781 *array_count += count; 1782 count = 0; 1783 SHR_BITCOUNT_RANGE(TH_QOS_INFO(unit)->egr_l2_vlan_etag_map, count, 1784 0, _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS); 1785 *array_count += count; 1786 } 1787 } else { 1788 if ((map_ids_array == NULL) || (flags_array == NULL) || 1789 (array_count == NULL)) { 1790 rv = BCM_E_PARAM; 1791 } 1792 1793 if (BCM_SUCCESS(rv)) { 1794 count = 0; 1795 for (idx = 0; ((idx < _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS) && 1796 (count < array_size)); idx++) { 1797 if (_BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, idx)) { 1798 *(map_ids_array + count) = 1799 idx | (_BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP << 1800 _BCM_QOS_MAP_SHIFT); 1801 *(flags_array + count) = BCM_QOS_MAP_L2_VLAN_ETAG | BCM_QOS_MAP_INGRESS; 1802 count++; 1803 } 1804 } 1805 for (idx = 0; ((idx < _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS) && 1806 (count < array_size)); idx++) { 1807 if (_BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, idx)) { 1808 *(map_ids_array + count) = 1809 idx | (_BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP << 1810 _BCM_QOS_MAP_SHIFT); 1811 *(flags_array + count) = BCM_QOS_MAP_L2_VLAN_ETAG | BCM_QOS_MAP_EGRESS; 1812 count++; 1813 } 1814 } 1815 1816 *array_count = count; 1817 } 1818 1819 } 1820 1821 return rv; 1822 } 1823 1824 #endif /* BCM_TOMAHAWK_SUPPORT */ 1825