qos.c (37331B)
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: Greyhound 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/greyhound.h> 25 #include <bcm_int/esw/xgs3.h> 26 #include <bcm_int/esw_dispatch.h> 27 #include <bcm/qos.h> 28 29 #ifdef BCM_GREYHOUND_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_gh_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_gh_qos_bookkeeping_t; 62 63 static _bcm_gh_qos_bookkeeping_t _bcm_gh_qos_bk_info[BCM_MAX_NUM_UNITS]; 64 static int _bcm_gh_qos_initialized[BCM_MAX_NUM_UNITS] = { 0 }; 65 66 #define GH_QOS_INFO(_unit_) (&_bcm_gh_qos_bk_info[_unit_]) 67 68 #define _BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_GET(_u_, _identifier_) \ 69 SHR_BITGET(GH_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(GH_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(GH_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(GH_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(GH_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(GH_QOS_INFO((_u_))->egr_l2_vlan_etag_map, (_identifier_)) 81 82 #define QOS_LOCK(unit) \ 83 sal_mutex_take(GH_QOS_INFO(unit)->qos_mutex, sal_mutex_FOREVER); 84 #define QOS_UNLOCK(unit) \ 85 sal_mutex_give(GH_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_gh_qos_initialized[unit]) { \ 93 return BCM_E_INIT; \ 94 } \ 95 } while (0) 96 97 /* 98 * Function: 99 * _bcm_gh_qos_free_resources 100 * Purpose: 101 * Free QOS bookkeeping resources associated with a given unit. This 102 * happens either during an error initializing or during a detach operation. 103 * Parameters: 104 * unit - (IN) Unit to free resources of 105 * Returns: 106 * BCM_E_XXX 107 */ 108 STATIC void 109 _bcm_gh_qos_free_resources(int unit) 110 { 111 _bcm_gh_qos_bookkeeping_t *qos_info = GH_QOS_INFO(unit); 112 113 if (!qos_info) { 114 /* 115 * Coverity 116 * This is defencive statement. 117 */ 118 /* coverity[dead_error_line] */ 119 return; 120 } 121 if (qos_info->ing_l2_vlan_etag_map) { 122 sal_free(qos_info->ing_l2_vlan_etag_map); 123 qos_info->ing_l2_vlan_etag_map = NULL; 124 } 125 126 if (qos_info->ing_l2_vlan_etag_map_hwidx) { 127 sal_free(qos_info->ing_l2_vlan_etag_map_hwidx); 128 qos_info->ing_l2_vlan_etag_map_hwidx = NULL; 129 } 130 131 if (qos_info->egr_l2_vlan_etag_map) { 132 sal_free(qos_info->egr_l2_vlan_etag_map); 133 qos_info->egr_l2_vlan_etag_map = NULL; 134 } 135 136 if (qos_info->egr_l2_vlan_etag_map_hwidx) { 137 sal_free(qos_info->egr_l2_vlan_etag_map_hwidx); 138 qos_info->egr_l2_vlan_etag_map_hwidx = NULL; 139 } 140 141 if (qos_info->qos_mutex) { 142 sal_mutex_destroy(qos_info->qos_mutex); 143 qos_info->qos_mutex = NULL; 144 } 145 } 146 147 /* 148 * Function: 149 * bcm_gh_qos_detach 150 * Purpose: 151 * Detach the QOS module. Called when the module should de-initialize. 152 * Parameters: 153 * unit - (IN) Unit being detached. 154 * Returns: 155 * BCM_E_XXX 156 */ 157 int 158 bcm_gh_qos_detach(int unit) 159 { 160 if (_bcm_gh_qos_initialized[unit]) { 161 _bcm_gh_qos_initialized[unit] = 0; 162 _bcm_gh_qos_free_resources(unit); 163 } 164 165 return BCM_E_NONE; 166 } 167 168 /* 169 * Function: 170 * bcm_gh_qos_init 171 * Purpose: 172 * Initialize the GH QOS module. Allocate bookkeeping information. 173 * Parameters: 174 * unit - (IN) Unit being initialized 175 * Returns: 176 * BCM_E_XXX 177 */ 178 int 179 bcm_gh_qos_init(int unit) 180 { 181 _bcm_gh_qos_bookkeeping_t *qos_info = GH_QOS_INFO(unit); 182 int l2_vlan_tag_map_size = _BCM_QOS_MAX_L2_VLAN_ETAG_MAP_IDS; 183 int egr_l2_vlan_tag_map_size = _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAP_IDS; 184 185 if (_bcm_gh_qos_initialized[unit]) { 186 BCM_IF_ERROR_RETURN(bcm_gh_qos_detach(unit)); 187 } 188 189 memset(qos_info, 0, sizeof *qos_info); 190 191 /* ingress l2 vlan etag map bitmap */ 192 qos_info->ing_l2_vlan_etag_map = 193 sal_alloc(SHR_BITALLOCSIZE(l2_vlan_tag_map_size), 194 "ing_l2_vlan_etag_map"); 195 if (qos_info->ing_l2_vlan_etag_map == NULL) { 196 _bcm_gh_qos_free_resources(unit); 197 return BCM_E_MEMORY; 198 } 199 sal_memset(qos_info->ing_l2_vlan_etag_map, 0, 200 SHR_BITALLOCSIZE(l2_vlan_tag_map_size)); 201 202 /* ingress l2 vlan etag map hardware indexes */ 203 qos_info->ing_l2_vlan_etag_map_hwidx = 204 sal_alloc(sizeof(uint32) * l2_vlan_tag_map_size, 205 "ing_l2_vlan_etag_map_hwidx"); 206 if (qos_info->ing_l2_vlan_etag_map_hwidx == NULL) { 207 _bcm_gh_qos_free_resources(unit); 208 return BCM_E_MEMORY; 209 } 210 sal_memset(qos_info->ing_l2_vlan_etag_map_hwidx, 0, 211 sizeof(uint32) * l2_vlan_tag_map_size); 212 213 /* egress l2 vlan etag priority map bitmap */ 214 qos_info->egr_l2_vlan_etag_map = sal_alloc(SHR_BITALLOCSIZE(egr_l2_vlan_tag_map_size), 215 "egr_l2_vlan_etag_map"); 216 if (qos_info->egr_l2_vlan_etag_map == NULL) { 217 _bcm_gh_qos_free_resources(unit); 218 return BCM_E_MEMORY; 219 } 220 sal_memset(qos_info->egr_l2_vlan_etag_map, 0, 221 SHR_BITALLOCSIZE(egr_l2_vlan_tag_map_size)); 222 223 /* egress l2 vlan etag map hardware indexes */ 224 qos_info->egr_l2_vlan_etag_map_hwidx = 225 sal_alloc(sizeof(uint32) * egr_l2_vlan_tag_map_size, 226 "egr_l2_vlan_etag_map_hwidx"); 227 if (qos_info->egr_l2_vlan_etag_map_hwidx == NULL) { 228 _bcm_gh_qos_free_resources(unit); 229 return BCM_E_MEMORY; 230 } 231 sal_memset(qos_info->egr_l2_vlan_etag_map_hwidx, 0, 232 sizeof(uint32) * egr_l2_vlan_tag_map_size); 233 234 /* accessor mutex */ 235 qos_info->qos_mutex = sal_mutex_create("vft qos_mutex"); 236 if (qos_info->qos_mutex == NULL) { 237 _bcm_gh_qos_free_resources(unit); 238 return BCM_E_MEMORY; 239 } 240 241 _bcm_gh_qos_initialized[unit] = 1; 242 return BCM_E_NONE; 243 } 244 245 /* 246 * Function: 247 * _bcm_gh_qos_flags_sanity_check 248 * Purpose: 249 * Check that the combination of flags specified is valid. 250 * Parameters: 251 * flags - (IN) BCM_QOS_MAP_* flags (eg. ingress/egress/with_id/replace) 252 * Returns: 253 * BCM_E_XXX 254 */ 255 STATIC int 256 _bcm_gh_qos_flags_sanity_check(uint32 flags) 257 { 258 int rv = BCM_E_NONE; 259 260 /* must be ingress or egress, not both */ 261 if ((flags & BCM_QOS_MAP_INGRESS) && (flags & BCM_QOS_MAP_EGRESS)) { 262 rv = BCM_E_PARAM; 263 } 264 265 /* must be ingress or egress, not neither */ 266 if (!(flags & BCM_QOS_MAP_INGRESS) && !(flags & BCM_QOS_MAP_EGRESS)) { 267 rv = BCM_E_PARAM; 268 } 269 270 /* support BCM_QOS_MAP_L2_VLAN_ETAG */ 271 if (!(flags & BCM_QOS_MAP_L2_VLAN_ETAG)) { 272 rv = BCM_E_PARAM; 273 } 274 275 return rv; 276 } 277 278 /* 279 * Function: 280 * _bcm_gh_qos_assign_creation_table_vars 281 * Purpose: 282 * Assign the various pointers to tables and table sizes and bitmaps used 283 * for the bcm_gh_qos_map_create so that it can create the different types 284 * of maps with common logic. 285 * 286 * Assumes "flags" has already been validated. 287 * Parameters: 288 * unit - (IN) Unit to be operated on 289 * flags - (IN) BCM_QOS_MAP_* flags (eg. ingress/egress/with_id/etc) 290 * is_ingress - (OUT) 1 for ingress, 0 for egress map 291 * bitmap - (OUT) pointer to priority map's bitmap 292 * hwmap - (OUT) pointer to priority map's hwidx mapping 293 * map_type - (OUT) _BCM_QOS_MAP_TYPE_* 294 * map_size - (OUT) size of the selected map 295 * max_maps - (OUT) maximum number of maps available for the selected type 296 * Returns: 297 * None 298 */ 299 STATIC void 300 _bcm_gh_qos_assign_creation_table_vars(int unit, int flags, int *is_ingress, 301 SHR_BITDCL **bitmap, 302 uint32 **hwmap, int *map_type, 303 int *map_size, int *max_maps) 304 { 305 if (flags & BCM_QOS_MAP_INGRESS) { 306 *is_ingress = 1; 307 if (flags & BCM_QOS_MAP_L2_VLAN_ETAG) { 308 *bitmap = GH_QOS_INFO(unit)->ing_l2_vlan_etag_map; 309 *hwmap = GH_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx; 310 *map_type = _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP; 311 *map_size = _BCM_QOS_MAX_L2_VLAN_ETAG_MAP_IDS; 312 *max_maps = _BCM_QOS_MAX_L2_VLAN_ETAG_MAPS; 313 } 314 } else if (flags & BCM_QOS_MAP_EGRESS) { 315 *is_ingress = 0; 316 317 if (flags & BCM_QOS_MAP_L2_VLAN_ETAG) { 318 *bitmap = GH_QOS_INFO(unit)->egr_l2_vlan_etag_map; 319 *hwmap = GH_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx; 320 *map_type = _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP; 321 *map_size = _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAP_IDS; 322 *max_maps = _BCM_QOS_MAX_EGR_L2_VLAN_ETAG_MAPS; 323 } 324 } 325 } 326 327 /* 328 * Function: 329 * _bcm_gh_qos_count_used_maps 330 * Purpose: 331 * Count the number maps currently used in hardware. Since IDs in app-space 332 * can point to the same hardware index, count how many hardware indexes are 333 * used, ignoring duplicates. 334 * Parameters: 335 * unit - (IN) Unit to be operated on 336 * bitmap - (IN) Bitmap of used map IDs 337 * hwmap - (IN) Array that maps userspace IDs to hardware IDs 338 * Returns: 339 * integer containing the number of used hardware indexes 340 */ 341 STATIC int 342 _bcm_gh_qos_count_used_maps(int unit, SHR_BITDCL *bitmap, uint32 *hwmap, 343 int map_size, int max_maps) 344 { 345 uint8 *hw_used = sal_alloc(map_size, "gh_qos_used_maps"); 346 int total_used = 0; 347 int i = 0; 348 349 if (hw_used == NULL) { 350 return max_maps; 351 } 352 353 memset(hw_used, 0, map_size); 354 355 for (i = 0; i < map_size; i++) { 356 if (SHR_BITGET(bitmap, i) && hw_used[hwmap[i]] == 0) { 357 hw_used[hwmap[i]] = 1; 358 total_used++; 359 } 360 } 361 362 sal_free(hw_used); 363 return total_used; 364 } 365 366 /* 367 * Function: 368 * _bcm_gh_qos_map_create_with_id 369 * Purpose: 370 * Allocate a new QOS map ID where the app has specified the ID. So just 371 * check that the requested ID is available, and mark it as used. 372 * Parameters: 373 * unit - (IN) Unit to be operated on 374 * flags - (IN) Used only to test if BCM_QOS_MAP_REPLACE is set 375 * bitmap - (IN/OUT) Bitmap containing the set of used IDs 376 * map_id - (IN) The ID requested by the application 377 * is_ingress - (IN) 1=ingress map, 0=egress map 378 * Returns: 379 * BCM_E_XXX 380 */ 381 STATIC int 382 _bcm_gh_qos_map_create_with_id(int unit, int flags, SHR_BITDCL *bitmap, 383 int *map_id, int is_ingress, int max_ids) 384 { 385 int id = 0, map_type = 0, rv = BCM_E_NONE; 386 387 id = *map_id & _BCM_QOS_MAP_TYPE_MASK; 388 map_type = *map_id >> _BCM_QOS_MAP_SHIFT; 389 390 if (id < 0 || id >= max_ids) { 391 return BCM_E_BADID; 392 } 393 394 if ((map_type == _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP && is_ingress)) { 395 396 if (SHR_BITGET(bitmap, id) == 1) { 397 if (!(flags & BCM_QOS_MAP_REPLACE)) { 398 rv = BCM_E_EXISTS; 399 } 400 } 401 402 if (BCM_SUCCESS(rv)) { 403 SHR_BITSET(bitmap, id); 404 } 405 } else { 406 rv = BCM_E_PARAM; 407 } 408 409 return rv; 410 } 411 412 /* 413 * Function: 414 * _bcm_gh_qos_map_id_alloc 415 * Purpose: 416 * Allocate a new QOS map ID. The bitmap given contains bits set for 417 * existing IDs, so find the first empty one, set it, and return it. 418 * Parameters: 419 * unit - (IN) Unit to be operated on 420 * bitmap - (IN/OUT) 421 * id - (OUT) 422 * Returns: 423 * BCM_E_XXX 424 */ 425 STATIC int 426 _bcm_gh_qos_map_id_alloc(int unit, SHR_BITDCL *bitmap, int *id, 427 int map_size) 428 { 429 int i; 430 431 for (i = 0; i < map_size; i++) { 432 if (!SHR_BITGET(bitmap, i)) { 433 SHR_BITSET(bitmap, i); 434 *id = i; 435 return BCM_E_NONE; 436 } 437 } 438 439 return BCM_E_RESOURCE; 440 } 441 442 443 /* 444 * Function: 445 * bcm_gh_qos_map_create 446 * Purpose: 447 * Create a new QOS map. 448 * Parameters: 449 * unit - (IN) Unit to be operated on 450 * flags - (IN) BCM_QOS_MAP_* flags (eg. ingress/egress/with_id/replace) 451 * map_id - (IN/OUT) If BCM_QOS_MAP_WITH_ID is set, then this is the ID 452 * being requested. Otherwise, it's assigned as the ID 453 * allocated. 454 * Returns: 455 * BCM_E_XXX 456 */ 457 int 458 bcm_gh_qos_map_create(int unit, uint32 flags, int *map_id) 459 { 460 int is_ingress = 0; 461 int map_type = 0; 462 SHR_BITDCL *bitmap = NULL; 463 uint32 index = 0; 464 int rv = BCM_E_NONE; 465 int id = 0; 466 void *entries[1]; 467 uint32 *hwmap = NULL; 468 int map_size = 0; 469 int max_maps = 0; 470 471 QOS_INIT(unit); 472 QOS_LOCK(unit); 473 474 rv = _bcm_gh_qos_flags_sanity_check(flags); 475 476 if (BCM_SUCCESS(rv)) { 477 _bcm_gh_qos_assign_creation_table_vars(unit, flags, &is_ingress, 478 &bitmap, &hwmap, &map_type, 479 &map_size, &max_maps); 480 } 481 482 if (BCM_SUCCESS(rv)) { 483 if (_bcm_gh_qos_count_used_maps(unit, bitmap, hwmap, map_size, 484 max_maps) >= max_maps) { 485 rv = BCM_E_MEMORY; 486 } 487 } 488 489 if (BCM_SUCCESS(rv)) { 490 if (flags & BCM_QOS_MAP_WITH_ID) { 491 rv = _bcm_gh_qos_map_create_with_id(unit, flags, bitmap, map_id, 492 is_ingress, map_size); 493 id = *map_id & _BCM_QOS_MAP_TYPE_MASK; 494 } else { 495 rv = _bcm_gh_qos_map_id_alloc(unit, bitmap, &id, map_size); 496 if (BCM_SUCCESS(rv)) { 497 /*_BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_SET(unit, id);*/ 498 *map_id = id | (map_type << _BCM_QOS_MAP_SHIFT); 499 } 500 } 501 } 502 503 if (BCM_SUCCESS(rv)) { 504 if ((flags & BCM_QOS_MAP_INGRESS) 505 && (flags & BCM_QOS_MAP_L2_VLAN_ETAG)) { 506 ing_etag_pcp_mapping_entry_t 507 table[_BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP]; 508 memset(&table, 0, sizeof table); 509 entries[0] = &table; 510 511 rv = _bcm_ing_l2_vlan_etag_map_entry_add(unit, entries, 512 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP, 513 &index); 514 515 if (BCM_SUCCESS(rv)) { 516 GH_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[id] = index; 517 } 518 } else if ((flags & BCM_QOS_MAP_EGRESS) 519 && (flags & BCM_QOS_MAP_L2_VLAN_ETAG)) { 520 egr_etag_pcp_mapping_entry_t 521 table[_BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP]; 522 memset(&table, 0, sizeof table); 523 entries[0] = &table; 524 525 rv = _bcm_egr_l2_vlan_etag_map_entry_add(unit, entries, 526 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP, 527 &index); 528 529 if (BCM_SUCCESS(rv)) { 530 GH_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[id] = index; 531 } 532 } 533 } 534 535 QOS_UNLOCK(unit); 536 537 return rv; 538 } 539 540 /* 541 * Function: 542 * _bcm_gh_qos_map_destroy 543 * Purpose: 544 * Destroy a map ID by removing it from hardware. 545 * Parameters: 546 * unit - (IN) The unit being operated on 547 * table - (IN) Indicates either ingress or egress 548 * id - (IN) The map ID being destroyed 549 * Returns: 550 * BCM_E_XXX 551 */ 552 STATIC int 553 _bcm_gh_qos_map_destroy(int unit, int table, int id) 554 { 555 int rv = BCM_E_NONE; 556 _bcm_gh_qos_bookkeeping_t *qos_info = GH_QOS_INFO(unit); 557 558 if (table == _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP) { 559 rv = _bcm_ing_l2_vlan_etag_map_entry_del(unit, 560 qos_info->ing_l2_vlan_etag_map_hwidx[id]); 561 } else if (table == _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP) { 562 rv = _bcm_egr_l2_vlan_etag_map_entry_del(unit, 563 qos_info->egr_l2_vlan_etag_map_hwidx[id]); 564 } 565 566 return rv; 567 } 568 569 /* 570 * Function: 571 * bcm_gh_qos_map_destroy 572 * Purpose: 573 * Destroy a QOS map ID by removing it from hardware and deleting the 574 * associated software state info. 575 * Parameters: 576 * unit - (IN) Unit being operated on 577 * map_id - (IN) QOS map ID to be destroyed 578 * Returns: 579 * BCM_E_XXX 580 */ 581 int 582 bcm_gh_qos_map_destroy(int unit, int map_id) 583 { 584 int id = map_id & _BCM_QOS_MAP_TYPE_MASK; 585 int rv = BCM_E_UNAVAIL; 586 587 QOS_INIT(unit); 588 QOS_LOCK(unit); 589 590 switch (map_id >> _BCM_QOS_MAP_SHIFT) { 591 case _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP: 592 if (!_BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, id)) { 593 rv = BCM_E_NOT_FOUND; 594 } else { 595 rv = _bcm_gh_qos_map_destroy(unit, 596 _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP, id); 597 598 if (BCM_SUCCESS(rv)) { 599 _BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_CLR(unit, id); 600 } 601 } 602 break; 603 case _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP: 604 if (!_BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, id)) { 605 rv = BCM_E_NOT_FOUND; 606 } else { 607 rv = _bcm_gh_qos_map_destroy(unit, 608 _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP, id); 609 610 if (BCM_SUCCESS(rv)) { 611 _BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_CLR(unit, id); 612 } 613 } 614 break; 615 default: 616 rv = BCM_E_PARAM; 617 } 618 619 QOS_UNLOCK(unit); 620 621 return rv; 622 } 623 624 /* 625 * Function: 626 * _bcm_gh_qos_map_add_sanity_check 627 * Purpose: 628 * Check that all the paramters given to the bcm_qos_map_add() function make 629 * sense and are internally consistent. 630 * Parameters: 631 * unit - (IN) The unit being operated on 632 * flags - (IN) BCM_QOS_MAP_* flags sent in by the app 633 * map - (IN) The map structure sent in by the app 634 * map_id - (IN) The map ID sent in by the app 635 * Returns: 636 * BCM_E_XXX 637 */ 638 STATIC int 639 _bcm_gh_qos_map_add_sanity_check(int unit, uint32 flags, bcm_qos_map_t *map, 640 int map_id) 641 { 642 int map_type = map_id >> _BCM_QOS_MAP_SHIFT; 643 int id = map_id & _BCM_QOS_MAP_TYPE_MASK; 644 int rv; 645 646 rv = _bcm_gh_qos_flags_sanity_check(flags); 647 if (BCM_FAILURE(rv)) { 648 return rv; 649 } 650 651 if ((flags & BCM_QOS_MAP_INGRESS) 652 && (map_type != _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP)) { 653 return BCM_E_PARAM; 654 } 655 656 if ((flags & BCM_QOS_MAP_EGRESS) 657 && (map_type != _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP)) { 658 return BCM_E_PARAM; 659 } 660 661 if ((flags & BCM_QOS_MAP_INGRESS) 662 && (map_type == _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP) 663 && (_BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, id) == 0)) { 664 return BCM_E_BADID; 665 } 666 667 if ((flags & BCM_QOS_MAP_EGRESS) 668 && (map_type == _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP) 669 && (_BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, id) == 0)) { 670 return BCM_E_BADID; 671 } 672 673 if (!(flags & BCM_QOS_MAP_L2_VLAN_ETAG)) { 674 if (map->int_pri < 0) { 675 return BCM_E_PARAM; 676 } 677 } 678 679 if (map->pkt_pri >= _BCM_QOS_MAX_PKT_PRIORITIES) { 680 return BCM_E_PARAM; 681 } 682 683 if (flags & BCM_QOS_MAP_L2_VLAN_ETAG) { 684 if ((map->etag_pcp >= _BCM_QOS_MAX_PKT_PRIORITIES) 685 || (map->etag_de >= _BCM_QOS_MAX_PKT_DES) 686 || (map->pkt_cfi >= _BCM_QOS_MAX_PKT_DES)) { 687 return BCM_E_PARAM; 688 } 689 } 690 691 if ((flags & BCM_QOS_MAP_L2_VLAN_ETAG) 692 && (flags & BCM_QOS_MAP_EGRESS)) { 693 if (map->color != bcmColorGreen && map->color != bcmColorYellow 694 && map->color != bcmColorRed) { 695 return BCM_E_PARAM; 696 } 697 if (map->int_pri >= _BCM_QOS_MAX_INT_PRIORITIES) { 698 return BCM_E_PARAM; 699 } 700 } 701 702 return BCM_E_NONE; 703 } 704 705 /* 706 * Function: 707 * _bcm_gh_ing_qos_map_update_index 708 * Purpose: 709 * Update an existing profile (or a newly created one) in the hardware's 710 * table with a new mapping. 711 * 712 * The structure is: (1) get existing profile for this map from hardware, 713 * (2) update the profile in RAM, (3) delete the old profile from hardware, 714 * and (4) push the updated profile in RAM to hardware. 715 * Parameters: 716 * unit - (IN) The unit being operated on 717 * map - (IN) Map structure sent in by app to be applied to hardware 718 * map_id - (IN) Map ID sent in by app to be applied to hardware 719 * Returns: 720 * BCM_E_XXX 721 */ 722 STATIC int 723 _bcm_gh_ing_qos_map_update_index(int unit, bcm_qos_map_t *map, int map_id) 724 { 725 void *entries[1]; 726 int rv = BCM_E_NONE; 727 uint32 index; 728 int id = map_id & _BCM_QOS_MAP_TYPE_MASK; 729 730 if (QOS_MAP_IS_L2_VLAN_ETAG(map_id)) { 731 ing_etag_pcp_mapping_entry_t table[_BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP]; 732 index = GH_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[id]; 733 734 entries[0] = &table; 735 rv = _bcm_ing_l2_vlan_etag_map_entry_get(unit, index, 736 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP, 737 entries); 738 739 if (BCM_SUCCESS(rv)) { 740 ing_etag_pcp_mapping_entry_t *entry = 741 &table[(map->pkt_pri << 1) | map->pkt_cfi]; 742 743 soc_mem_field32_set(unit, ING_ETAG_PCP_MAPPINGm, 744 entry, PCPf, map->etag_pcp); 745 soc_mem_field32_set(unit, ING_ETAG_PCP_MAPPINGm, 746 entry, DEf, map->etag_de); 747 748 rv = _bcm_ing_l2_vlan_etag_map_entry_del(unit, (int)index); 749 } 750 751 if (BCM_SUCCESS(rv)) { 752 rv = _bcm_ing_l2_vlan_etag_map_entry_add(unit, entries, 753 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP, 754 &index); 755 GH_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[id] = index; 756 } 757 } 758 return rv; 759 } 760 761 /* 762 * Function: 763 * _bcm_gh_egr_qos_map_update_index 764 * Purpose: 765 * Update an existing profile (or a newly created one) in the hardware's 766 * table with a new mapping. 767 * 768 * The structure is: (1) get existing profile for this map from hardware, 769 * (2) update the profile in RAM, (3) delete the old profile from hardware, 770 * and (4) push the updated profile in RAM to hardware. 771 * Parameters: 772 * unit - (IN) The unit being operated on 773 * map - (IN) Map structure sent in by app to be applied to hardware 774 * map_id - (IN) Map ID sent in by app to be applied to hardware 775 * Returns: 776 * BCM_E_XXX 777 */ 778 STATIC int 779 _bcm_gh_egr_qos_map_update_index(int unit, bcm_qos_map_t *map, int map_id) 780 { 781 void *entries[1]; 782 int rv = BCM_E_NONE; 783 int cng; 784 uint32 index; 785 int id = map_id & _BCM_QOS_MAP_TYPE_MASK; 786 787 if (QOS_MAP_IS_L2_VLAN_ETAG(map_id)) { 788 egr_etag_pcp_mapping_entry_t table[_BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP]; 789 index = GH_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[id]; 790 791 entries[0] = &table; 792 rv = _bcm_egr_l2_vlan_etag_map_entry_get(unit, index, 793 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP, 794 entries); 795 if (BCM_SUCCESS(rv)) { 796 egr_etag_pcp_mapping_entry_t *entry; 797 cng = _BCM_COLOR_ENCODING(unit, map->color); 798 entry = &table[(map->int_pri << 2) | cng]; 799 800 soc_mem_field32_set(unit, EGR_ETAG_PCP_MAPPINGm, 801 entry, PCPf, map->etag_pcp); 802 soc_mem_field32_set(unit, EGR_ETAG_PCP_MAPPINGm, 803 entry, DEf, map->etag_de); 804 805 rv = _bcm_egr_l2_vlan_etag_map_entry_del(unit, (int)index); 806 } 807 808 if (BCM_SUCCESS(rv)) { 809 rv = _bcm_egr_l2_vlan_etag_map_entry_add(unit, entries, 810 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP, 811 &index); 812 GH_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[id] = index; 813 } 814 } 815 816 return rv; 817 } 818 819 /* 820 * Function: 821 * bcm_gh_qos_map_add 822 * Purpose: 823 * Add a new QOS mapping to hardware. 824 * Parameters: 825 * unit - (IN) The unit being operated on 826 * flags - (IN) BCM_QOS_MAP_* flags 827 * map - (IN) Structure containing the priorities to be mapped 828 * map_id - (IN) The ID of the map to add the new information to 829 * Returns: 830 * BCM_E_XXX 831 */ 832 int 833 bcm_gh_qos_map_add(int unit, uint32 flags, bcm_qos_map_t *map, int map_id) 834 { 835 int rv = BCM_E_NONE; 836 837 QOS_INIT(unit); 838 QOS_LOCK(unit); 839 840 rv = _bcm_gh_qos_map_add_sanity_check(unit, flags, map, map_id); 841 if (BCM_SUCCESS(rv)) { 842 if ((flags & BCM_QOS_MAP_INGRESS) 843 && (flags & BCM_QOS_MAP_L2_VLAN_ETAG)) { 844 rv = _bcm_gh_ing_qos_map_update_index(unit, map, map_id); 845 } else { 846 rv = _bcm_gh_egr_qos_map_update_index(unit, map, map_id); 847 } 848 } 849 850 QOS_UNLOCK(unit); 851 852 return rv; 853 } 854 855 /* bcm_gh_qos_map_multi_get */ 856 int 857 bcm_gh_qos_map_multi_get(int unit, uint32 flags, 858 int map_id, int array_size, 859 bcm_qos_map_t *array, int *array_count) 860 { 861 int rv = BCM_E_NONE; 862 int num_entries, idx, id, hw_id, alloc_size, entry_size, count; 863 uint8 *dma_buf; 864 void *entry; 865 soc_mem_t mem; 866 bcm_qos_map_t *map; 867 int cng = 0; 868 869 /* ignore with_id & replace flags */ 870 flags &= (~(BCM_QOS_MAP_WITH_ID | BCM_QOS_MAP_REPLACE)); 871 id = map_id & _BCM_QOS_MAP_TYPE_MASK; 872 mem = INVALIDm; 873 hw_id = 0; 874 num_entries = 0; 875 entry_size = 0; 876 QOS_LOCK(unit); 877 switch (map_id >> _BCM_QOS_MAP_SHIFT) { 878 case _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP: 879 if ((flags != (BCM_QOS_MAP_L2_VLAN_ETAG | BCM_QOS_MAP_INGRESS)) || 880 (!_BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, id))) { 881 rv = BCM_E_PARAM; 882 } 883 num_entries = _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP; 884 entry_size = sizeof(ing_etag_pcp_mapping_entry_t); 885 hw_id = GH_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[id]; 886 mem = ING_ETAG_PCP_MAPPINGm; 887 break; 888 case _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP: 889 if ((flags != (BCM_QOS_MAP_L2_VLAN_ETAG | BCM_QOS_MAP_EGRESS)) || 890 (!_BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, id))) { 891 rv = BCM_E_PARAM; 892 } 893 num_entries = _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP; 894 entry_size = sizeof(egr_etag_pcp_mapping_entry_t); 895 hw_id = GH_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[id]; 896 mem = EGR_ETAG_PCP_MAPPINGm; 897 break; 898 default: 899 rv = BCM_E_PARAM; 900 } 901 QOS_UNLOCK(unit); 902 BCM_IF_ERROR_RETURN(rv); 903 904 if (array_size == 0) { /* querying the size of map-chunk */ 905 *array_count = num_entries; 906 return BCM_E_NONE; 907 } 908 if (!array || !array_count) { 909 return BCM_E_PARAM; 910 } 911 912 /* Allocate memory for DMA & regular */ 913 alloc_size = num_entries * entry_size; 914 dma_buf = soc_cm_salloc(unit, alloc_size, "GH qos multi get DMA buf"); 915 if (!dma_buf) { 916 return BCM_E_MEMORY; 917 } 918 sal_memset(dma_buf, 0, alloc_size); 919 920 /* Read the profile chunk */ 921 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, hw_id, 922 (hw_id + num_entries - 1), dma_buf); 923 if (BCM_FAILURE(rv)) { 924 soc_cm_sfree(unit, dma_buf); 925 return rv; 926 } 927 928 count = 0; 929 QOS_LOCK(unit); 930 switch (map_id >> _BCM_QOS_MAP_SHIFT) { 931 case _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP: 932 for (idx=0; ((idx<num_entries) && (count < array_size)); idx++) { 933 map = &array[idx]; 934 sal_memset(map, 0x0, sizeof(bcm_qos_map_t)); 935 map->pkt_pri = ((idx & 0xe) >> 1); 936 map->pkt_cfi = (idx & 0x1); 937 entry = soc_mem_table_idx_to_pointer(unit, mem, void *, 938 dma_buf, idx); 939 map->etag_pcp = soc_mem_field32_get(unit, mem, entry, PCPf); 940 map->etag_de = soc_mem_field32_get(unit, mem, entry, DEf); 941 count++; 942 } 943 break; 944 case _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP: 945 for (idx=0; ((idx<num_entries) && (count < array_size)); idx++) { 946 map = &array[idx]; 947 sal_memset(map, 0x0, sizeof(bcm_qos_map_t)); 948 map->int_pri = ((idx & 0x3c) >> 2); 949 cng = (idx & 0x3); 950 map->color = _BCM_COLOR_DECODING(unit, cng); 951 entry = soc_mem_table_idx_to_pointer(unit, mem, void *, 952 dma_buf, idx); 953 map->etag_pcp = soc_mem_field32_get(unit, mem, entry, PCPf); 954 map->etag_de = soc_mem_field32_get(unit, mem, entry, DEf); 955 count++; 956 } 957 break; 958 default: 959 rv = BCM_E_INTERNAL; /* should not hit this */ 960 } 961 QOS_UNLOCK(unit); 962 soc_cm_sfree(unit, dma_buf); 963 964 BCM_IF_ERROR_RETURN(rv); 965 966 *array_count = count; 967 return BCM_E_NONE; 968 } 969 970 /* 971 * Function: 972 * bcm_gh_qos_map_delete 973 * Purpose: 974 * Delete a mapping (for example, the map from 7 to 3). This is equivalent 975 * to changing it to a map from 7 to 0, so this function maps the call into 976 * bcm_td2_qos_map_add(). 977 * Parameters: 978 * unit - (IN) The unit being operated on 979 * flags - (IN) BCM_QOS_MAP_* flags 980 * map - (IN) Structure containing the priorities to be mapped 981 * map_id - (IN) The ID of the map to add the new information to 982 * Returns: 983 * BCM_E_XXX 984 */ 985 int 986 bcm_gh_qos_map_delete(int unit, uint32 flags, bcm_qos_map_t *map, int map_id) 987 { 988 int rv = BCM_E_NONE; 989 bcm_qos_map_t clr_map; 990 991 QOS_INIT(unit); 992 993 sal_memcpy(&clr_map, map, sizeof clr_map); 994 995 rv = _bcm_gh_qos_flags_sanity_check(flags); 996 if (BCM_SUCCESS(rv)) { 997 if (flags & BCM_QOS_MAP_INGRESS) { 998 if (flags & BCM_QOS_MAP_L2_VLAN_ETAG) { 999 clr_map.etag_pcp = 0; 1000 clr_map.etag_de = 0; 1001 } 1002 } else { 1003 if(flags & BCM_QOS_MAP_L2_VLAN_ETAG) { 1004 clr_map.etag_pcp = 0; 1005 clr_map.etag_de = 0; 1006 } else { 1007 clr_map.pkt_pri = 0; 1008 } 1009 } 1010 } 1011 1012 if (BCM_SUCCESS(rv)) { 1013 rv = bcm_gh_qos_map_add(unit, flags, &clr_map, map_id); 1014 } 1015 1016 return rv; 1017 } 1018 1019 /* 1020 * Function: 1021 * _bcm_gh_qos_apply_ing_map_to_port 1022 * Purpose: 1023 * Apply a fully created ingress map to a hardware port. This is the final 1024 * step in the process, where the mapping becomes operational. 1025 * Parameters: 1026 * unit - (IN) Unit being operated on 1027 * ing_map - (IN) ID of the map to be applied 1028 * local_port - (IN) Local port number to apply map to 1029 * Returns: 1030 * BCM_E_XXX 1031 */ 1032 STATIC int 1033 _bcm_gh_qos_apply_ing_map_to_port(int unit, int ing_map, bcm_port_t local_port) 1034 { 1035 int rv = BCM_E_PARAM; 1036 int id = ing_map & _BCM_QOS_MAP_TYPE_MASK; 1037 int profile_idx = (GH_QOS_INFO(unit)->ing_l2_vlan_etag_map_hwidx[id] / 1038 _BCM_QOS_MAP_CHUNK_L2_VLAN_ETAG_MAP); 1039 1040 soc_mem_lock(unit, PORT_TABm); 1041 1042 if ((ing_map >> _BCM_QOS_MAP_SHIFT) == _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP) { 1043 rv = _bcm_tr2_port_tab_set(unit, local_port, ETAG_PCP_DE_MAPPING_PTRf, 1044 profile_idx); 1045 } 1046 1047 soc_mem_unlock(unit, PORT_TABm); 1048 1049 return rv; 1050 } 1051 1052 /* 1053 * Function: 1054 * _bcm_gh_qos_apply_egr_map_to_port 1055 * Purpose: 1056 * Apply a fully created ingress map to a hardware port. This is the final 1057 * step in the process, where the mapping becomes operational. 1058 * Parameters: 1059 * unit - (IN) Unit being operated on 1060 * ing_map - (IN) ID of the map to be applied 1061 * local_port - (IN) Local port number to apply map to 1062 * Returns: 1063 * BCM_E_XXX 1064 */ 1065 STATIC int 1066 _bcm_gh_qos_apply_egr_map_to_port(int unit, int egr_map, bcm_port_t local_port) 1067 { 1068 int rv = BCM_E_PARAM; 1069 int id = egr_map & _BCM_QOS_MAP_TYPE_MASK; 1070 int profile_idx = (GH_QOS_INFO(unit)->egr_l2_vlan_etag_map_hwidx[id] / 1071 _BCM_QOS_MAP_CHUNK_EGR_L2_VLAN_ETAG_MAP); 1072 soc_mem_lock(unit, PORT_TABm); 1073 1074 if ((egr_map >> _BCM_QOS_MAP_SHIFT) == _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP) { 1075 rv = _bcm_tr2_port_tab_set(unit, local_port, ETAG_DOT1P_MAPPING_PTRf, 1076 profile_idx); 1077 } 1078 1079 soc_mem_unlock(unit, PORT_TABm); 1080 1081 return rv; 1082 } 1083 1084 /* 1085 * Function: 1086 * bcm_gh_qos_port_map_set 1087 * Purpose: 1088 * Apply a fully created ingress and/or egress map to a given port. If 1089 * either map is given as -1 (_BCM_QOS_NO_MAP), then the parameter should be 1090 * ignored. 1091 * Parameters: 1092 * unit - (IN) The unit to be operated on 1093 * port - (IN) The port number for the map to be applied to 1094 * ing_map - (IN) The ID of an ingress map to be applied 1095 * egr_map - (IN) The ID of an egress map to be applied 1096 * Returns: 1097 * BCM_E_XXX 1098 */ 1099 int 1100 bcm_gh_qos_port_map_set(int unit, bcm_gport_t port, int ing_map, int egr_map) 1101 { 1102 int rv = BCM_E_NONE; 1103 bcm_port_t local_port; 1104 1105 QOS_INIT(unit); 1106 QOS_LOCK(unit); 1107 1108 if (!BCM_GPORT_IS_SET(port)) { 1109 rv = BCM_E_PARAM; 1110 } 1111 1112 if (BCM_SUCCESS(rv)) { 1113 rv = bcm_esw_port_local_get(unit, port, &local_port); 1114 } 1115 1116 if (BCM_SUCCESS(rv) && !SOC_PORT_VALID(unit, local_port)) { 1117 rv = BCM_E_PARAM; 1118 } 1119 1120 if (BCM_SUCCESS(rv) && ing_map != _BCM_QOS_NO_MAP) { 1121 int id = ing_map & _BCM_QOS_MAP_TYPE_MASK; 1122 1123 if ((ing_map >> _BCM_QOS_MAP_SHIFT) != 1124 _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP){ 1125 rv = BCM_E_PARAM; 1126 } 1127 1128 if (BCM_SUCCESS(rv) 1129 && (((ing_map >> _BCM_QOS_MAP_SHIFT) == 1130 _BCM_QOS_MAP_TYPE_ING_L2_VLAN_ETAG_MAP) 1131 && (!_BCM_QOS_ING_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, id)))) { 1132 rv = BCM_E_PARAM; 1133 } 1134 1135 if (BCM_SUCCESS(rv)) { 1136 rv = _bcm_gh_qos_apply_ing_map_to_port(unit, ing_map, local_port); 1137 } 1138 } 1139 1140 if (BCM_SUCCESS(rv) && egr_map != _BCM_QOS_NO_MAP) { 1141 int id = egr_map & _BCM_QOS_MAP_TYPE_MASK; 1142 1143 if ((egr_map >> _BCM_QOS_MAP_SHIFT) != 1144 _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP){ 1145 rv = BCM_E_PARAM; 1146 } 1147 1148 if (BCM_SUCCESS(rv) 1149 && (((egr_map >> _BCM_QOS_MAP_SHIFT) == 1150 _BCM_QOS_MAP_TYPE_EGR_L2_VLAN_ETAG_MAP) 1151 && (!_BCM_QOS_EGR_L2_VLAN_ETAG_MAP_TABLE_USED_GET(unit, id)))) { 1152 rv = BCM_E_PARAM; 1153 } 1154 1155 if (BCM_SUCCESS(rv)) { 1156 rv = _bcm_gh_qos_apply_egr_map_to_port(unit, egr_map, local_port); 1157 } 1158 } 1159 1160 QOS_UNLOCK(unit); 1161 1162 return rv; 1163 } 1164 1165 #endif /* BCM_GREYHOUND_SUPPORT */ 1166