openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

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