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 (81607B)


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