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

ecn.c (55574B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * ECN - Broadcom StrataSwitch ECN API.
      8  */
      9 
     10 #include <sal/core/libc.h>
     11 #include <soc/defs.h>
     12 
     13 #include <soc/drv.h>
     14 #include <soc/mem.h>
     15 #include <bcm/error.h>
     16 
     17 #include <bcm/ecn.h>
     18 #include <bcm/debug.h>
     19 #include <bcm/error.h>
     20 #include <bcm/switch.h>
     21 #include <bcm_int/esw/ecn.h>
     22 #include <bcm_int/esw/xgs3.h>
     23 #include <bcm_int/esw/xgs5.h>
     24 #include <bcm_int/esw_dispatch.h>
     25 
     26 
     27 #if defined(BCM_GREYHOUND_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT)
     28 
     29 int
     30 _bcm_esw_ecn_init(int unit)
     31 {
     32     responsive_protocol_match_entry_t   entry_res_protocol;
     33     ip_to_int_cn_mapping_entry_t        entry_ip_int_cn;
     34     int_cn_to_mmuif_mapping_entry_t     entry_int_cn_mmuif;
     35     egr_int_cn_update_entry_t           entry_egr_int_cn_update;
     36     egr_int_cn_to_ip_mapping_entry_t    entry_egr_int_cn_ip_mapping;
     37     int count, i;
     38     uint32  fld_val;
     39     uint64  fld64_val;
     40     soc_mem_t cfg_mem = RESPONSIVE_PROTOCOL_MATCHm;
     41     int table_adj = 1;
     42 
     43     if (!SOC_WARM_BOOT(unit)) {
     44         /* Responsive Protocol Match table */
     45         /* Set TCP(0x6) to 1 */
     46         COMPILER_64_ZERO(fld64_val);
     47         COMPILER_64_SET(fld64_val, 0x0, (0x1 << 6));
     48         sal_memset(&entry_res_protocol, 0, sizeof(entry_res_protocol));
     49         soc_mem_field64_set(unit, RESPONSIVE_PROTOCOL_MATCHm, 
     50                     &entry_res_protocol, RESPONSIVEf, fld64_val);
     51         soc_mem_write(unit, RESPONSIVE_PROTOCOL_MATCHm, MEM_BLOCK_ALL,
     52                 0, (void *)&entry_res_protocol);
     53 
     54         /* 
     55          * IP_TO_INT_CN_MAPPING table
     56             Address (ECN + responsive)  :     INT_CN
     57                             0                           2'b01
     58                             1                           2'b00
     59                             2                           2'b10
     60                             3                           2'b10
     61                             4                           2'b10
     62                             5                           2'b10
     63                             6                           2'b11
     64                             7                           2'b11
     65          */
     66 #if defined(BCM_TRIDENT3_SUPPORT)
     67         if(SOC_IS_TRIDENT3X(unit)) {
     68             cfg_mem = PKT_ECN_TO_INT_CN_MAPPINGm;
     69             table_adj = 8;
     70 
     71             count = soc_mem_index_count(unit, cfg_mem);
     72             count /= table_adj;
     73             for (i = 0; i < count; i++) {
     74                 sal_memset(&entry_ip_int_cn, 0, sizeof(entry_ip_int_cn));
     75                 switch (i) {
     76                     case 0:
     77                         fld_val = _BCM_ECN_INT_CN_NON_RESPONSIVE_DROP;
     78                         break;
     79                     case 4:
     80                         fld_val = _BCM_ECN_INT_CN_RESPONSIVE_DROP;
     81                         break;
     82                     case 3:
     83                     case 7:
     84                         fld_val = _BCM_ECN_INT_CN_CONGESTION_MARK_ECN;
     85                         break;
     86                     default:
     87                         fld_val = _BCM_ECN_INT_CN_NON_CONGESTION_MARK_ECN;
     88                         break;
     89                 }
     90                 soc_mem_field32_set(unit, cfg_mem,
     91                             &entry_ip_int_cn, INT_CNf, fld_val);
     92                 soc_mem_write(unit, cfg_mem, MEM_BLOCK_ALL,
     93                     i, (void *)&entry_ip_int_cn);
     94             }
     95         } else
     96 #endif
     97         {
     98             cfg_mem = IP_TO_INT_CN_MAPPINGm;
     99             table_adj = 1;
    100 
    101             count = soc_mem_index_count(unit, cfg_mem);
    102             count /= table_adj;
    103             for (i = 0; i < count; i++) {
    104                 sal_memset(&entry_ip_int_cn, 0, sizeof(entry_ip_int_cn));
    105                 switch (i) {
    106                     case 0:
    107                         fld_val = _BCM_ECN_INT_CN_NON_RESPONSIVE_DROP;
    108                         break;
    109                     case 1:
    110                         fld_val = _BCM_ECN_INT_CN_RESPONSIVE_DROP;
    111                         break;
    112                     case 6:
    113                     case 7:
    114                         fld_val = _BCM_ECN_INT_CN_CONGESTION_MARK_ECN;
    115                         break;
    116                     default:
    117                         fld_val = _BCM_ECN_INT_CN_NON_CONGESTION_MARK_ECN;
    118                         break;
    119                 }
    120                 soc_mem_field32_set(unit, cfg_mem,
    121                             &entry_ip_int_cn, INT_CNf, fld_val);
    122                 soc_mem_write(unit, cfg_mem, MEM_BLOCK_ALL,
    123                     i, (void *)&entry_ip_int_cn);
    124             }
    125         }
    126 
    127 
    128         /* INT_CN_TO_MMUIF_MAPPING */
    129         count = soc_mem_index_count(unit, INT_CN_TO_MMUIF_MAPPINGm);
    130         for (i = 0; i < count; i++) {
    131             sal_memset(&entry_int_cn_mmuif, 0, sizeof(entry_int_cn_mmuif));
    132             switch (i) {
    133                 case _BCM_ECN_INT_CN_RESPONSIVE_DROP:
    134                     soc_mem_field32_set(unit, INT_CN_TO_MMUIF_MAPPINGm, 
    135                         &entry_int_cn_mmuif, WRED_RESPONSIVEf, 1);
    136                     soc_mem_field32_set(unit, INT_CN_TO_MMUIF_MAPPINGm, 
    137                         &entry_int_cn_mmuif, WRED_MARK_ELIGIBLEf, 0);
    138                     break;
    139                 case _BCM_ECN_INT_CN_NON_RESPONSIVE_DROP:
    140                     soc_mem_field32_set(unit, INT_CN_TO_MMUIF_MAPPINGm, 
    141                         &entry_int_cn_mmuif, WRED_RESPONSIVEf, 0);
    142                     soc_mem_field32_set(unit, INT_CN_TO_MMUIF_MAPPINGm, 
    143                         &entry_int_cn_mmuif, WRED_MARK_ELIGIBLEf, 0);
    144                     break;
    145                 case _BCM_ECN_INT_CN_CONGESTION_MARK_ECN:
    146                 case _BCM_ECN_INT_CN_NON_CONGESTION_MARK_ECN:
    147                     soc_mem_field32_set(unit, INT_CN_TO_MMUIF_MAPPINGm, 
    148                         &entry_int_cn_mmuif, WRED_RESPONSIVEf, 1);
    149                     soc_mem_field32_set(unit, INT_CN_TO_MMUIF_MAPPINGm, 
    150                         &entry_int_cn_mmuif, WRED_MARK_ELIGIBLEf, 1);
    151                     break;
    152                 default:
    153                     break;
    154             }
    155             soc_mem_write(unit, INT_CN_TO_MMUIF_MAPPINGm, MEM_BLOCK_ALL,
    156                 i, (void *)&entry_int_cn_mmuif);
    157         }
    158 
    159         /* EGR_INT_CN_UPDATE */
    160 #if defined(BCM_TRIDENT3_SUPPORT)
    161         if(SOC_IS_TRIDENT3X(unit)) {
    162             /* In TD3, CE_R & CE_Y & CE_G is replaced by CE. */
    163             count = soc_mem_index_count(unit, EGR_INT_CN_UPDATEm);
    164             for (i = 0; i < count; i++) {
    165                 sal_memset(&entry_egr_int_cn_update, 0,
    166                                     sizeof(entry_egr_int_cn_update));
    167                 if (i < 0x8) {
    168                     /* INT_CN == 0 */
    169                     soc_mem_field32_set(unit, EGR_INT_CN_UPDATEm,
    170                         &entry_egr_int_cn_update, INT_CNf,
    171                         _BCM_ECN_INT_CN_RESPONSIVE_DROP);
    172                 } else if (i < 0x10) {
    173                     /* INT_CN == 1 */
    174                     soc_mem_field32_set(unit, EGR_INT_CN_UPDATEm,
    175                         &entry_egr_int_cn_update, INT_CNf,
    176                         _BCM_ECN_INT_CN_NON_RESPONSIVE_DROP);
    177                 } else if (i < 0x18) {
    178                     /* INT_CN == 2 */
    179                     /* Change the INT_CN to 3 if local MMU is congested */
    180                     if (i & (1 << _BCM_ECN_DEQUEUE_MEM_INDEX_CE_OFFSET_TD3)) {
    181                         soc_mem_field32_set(unit, EGR_INT_CN_UPDATEm,
    182                             &entry_egr_int_cn_update, INT_CNf,
    183                             _BCM_ECN_INT_CN_CONGESTION_MARK_ECN);
    184                         soc_mem_field32_set(unit, EGR_INT_CN_UPDATEm,
    185                             &entry_egr_int_cn_update, CONGESTION_MARKEDf, 1);
    186                     } else {
    187                         soc_mem_field32_set(unit, EGR_INT_CN_UPDATEm,
    188                             &entry_egr_int_cn_update, INT_CNf,
    189                             _BCM_ECN_INT_CN_NON_CONGESTION_MARK_ECN);
    190                     }
    191                 } else {
    192                     /* INT_CN ==  3 */
    193                     soc_mem_field32_set(unit, EGR_INT_CN_UPDATEm,
    194                         &entry_egr_int_cn_update, INT_CNf,
    195                         _BCM_ECN_INT_CN_CONGESTION_MARK_ECN);
    196                 }
    197                 soc_mem_write(unit, EGR_INT_CN_UPDATEm, MEM_BLOCK_ALL,
    198                     i, (void *)&entry_egr_int_cn_update);
    199             }
    200         }else
    201 #endif
    202         {
    203             count = soc_mem_index_count(unit, EGR_INT_CN_UPDATEm);
    204             for (i = 0; i < count; i++) {
    205                 sal_memset(&entry_egr_int_cn_update, 0,
    206                                     sizeof(entry_egr_int_cn_update));
    207                 if (i < 0x20) {
    208                     /* INT_CN == 0 */
    209                     soc_mem_field32_set(unit, EGR_INT_CN_UPDATEm,
    210                         &entry_egr_int_cn_update, INT_CNf,
    211                         _BCM_ECN_INT_CN_RESPONSIVE_DROP);
    212                 } else if (i < 0x40) {
    213                     /* INT_CN == 1 */
    214                     soc_mem_field32_set(unit, EGR_INT_CN_UPDATEm,
    215                         &entry_egr_int_cn_update, INT_CNf,
    216                         _BCM_ECN_INT_CN_NON_RESPONSIVE_DROP);
    217                 } else if (i > 0x5f) {
    218                     /* INT_CN ==  3 */
    219                     soc_mem_field32_set(unit, EGR_INT_CN_UPDATEm,
    220                         &entry_egr_int_cn_update, INT_CNf,
    221                         _BCM_ECN_INT_CN_CONGESTION_MARK_ECN);
    222                 } else {
    223                     /* INT_CN == 2 */
    224                     /* Change the INT_CN to 3 if local MMU is congested */
    225                     switch (i) {
    226                         case 0x50:
    227                         case 0x54:
    228                         case 0x58:
    229                         case 0x5c:
    230                         case 0x4b:
    231                         case 0x4f:
    232                         case 0x5b:
    233                         case 0x5f:
    234                         case 0x45:
    235                         case 0x4d:
    236                         case 0x55:
    237                         case 0x5d:
    238                             soc_mem_field32_set(unit, EGR_INT_CN_UPDATEm,
    239                                 &entry_egr_int_cn_update, INT_CNf,
    240                                 _BCM_ECN_INT_CN_CONGESTION_MARK_ECN);
    241                             soc_mem_field32_set(unit, EGR_INT_CN_UPDATEm,
    242                                 &entry_egr_int_cn_update, CONGESTION_MARKEDf, 1);
    243                             break;
    244                         default:
    245                             soc_mem_field32_set(unit, EGR_INT_CN_UPDATEm,
    246                                 &entry_egr_int_cn_update, INT_CNf,
    247                                 _BCM_ECN_INT_CN_NON_CONGESTION_MARK_ECN);
    248                             break;
    249                     }
    250                 }
    251                 soc_mem_write(unit, EGR_INT_CN_UPDATEm, MEM_BLOCK_ALL,
    252                     i, (void *)&entry_egr_int_cn_update);
    253             }
    254         }
    255 
    256         /* EGR_INT_CN_TO_IP_MAPPING */
    257 #if defined(BCM_TRIDENT3_SUPPORT)
    258         if(SOC_IS_TRIDENT3X(unit)) {
    259             cfg_mem = EGR_INT_CN_TO_PKT_ECN_MAPPINGm;
    260             table_adj = 32;
    261         } else
    262 #endif
    263         {
    264             cfg_mem = EGR_INT_CN_TO_IP_MAPPINGm;
    265             table_adj = 1;
    266         }
    267         count = soc_mem_index_count(unit, cfg_mem);
    268         count /= table_adj;
    269         for (i = 0; i < count; i++) {
    270             sal_memset(&entry_egr_int_cn_ip_mapping, 0, 
    271                                 sizeof(entry_egr_int_cn_ip_mapping));
    272 
    273             /* Change the ECN value from 2'b01 or 2'b10 to 2'b11 for INT_CN is 3 */
    274             if ((i == 13) || (i == 14)) {
    275                 soc_mem_field32_set(unit, cfg_mem,
    276                     &entry_egr_int_cn_ip_mapping, CHANGE_PACKET_ECNf, 1);
    277                 soc_mem_field32_set(unit, cfg_mem,
    278                     &entry_egr_int_cn_ip_mapping, ECNf, 3);
    279                 soc_mem_field32_set(unit, cfg_mem,
    280                     &entry_egr_int_cn_ip_mapping, INCREMENT_ECN_COUNTERf, 1);
    281             }
    282             soc_mem_write(unit, cfg_mem, MEM_BLOCK_ALL,
    283                 i, (void *)&entry_egr_int_cn_ip_mapping);
    284         }
    285         /* 
    286          * Configure the int_cn of Non-IP packets to Non-Responsive Dropping. 
    287          */
    288         BCM_IF_ERROR_RETURN(
    289             bcm_esw_switch_control_set(unit, 
    290                 bcmSwitchEcnNonIpIntCongestionNotification,
    291                 _BCM_ECN_INT_CN_NON_RESPONSIVE_DROP));
    292     } 
    293 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(INCLUDE_L3)
    294     if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
    295         BCM_IF_ERROR_RETURN(bcmi_xgs5_ecn_init(unit)); 
    296     }
    297 #endif
    298     return BCM_E_NONE;
    299 }
    300 
    301 #endif /* BCM_GREYHOUND_SUPPORT || BCM_TOMAHAWK_SUPPORT */
    302 
    303 /*
    304  * Function:
    305  *      bcm_esw_ecn_responsive_protocol_get
    306  * Purpose:
    307  *      To get the value of responsive indication based on the IP protocol value.
    308  * Parameters:
    309  *      unit - (IN) Unit number.
    310  *      ip_proto - (IN) IP Protocol value.
    311  *      responsice - (OUT) Responsice indication.
    312  * Returns:
    313  *      BCM_E_XXX
    314  * Notes:
    315  */
    316 int bcm_esw_ecn_responsive_protocol_get(
    317     int unit, uint8 ip_proto, int *responsive)
    318 {
    319 
    320 #if defined(BCM_GREYHOUND_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT)
    321     uint64  fld64_val;
    322     int mem_idx, field_offset;
    323     responsive_protocol_match_entry_t   entry_res_protocol;
    324 
    325     if (!soc_feature(unit, soc_feature_ecn_wred)) {
    326         return BCM_E_UNAVAIL;
    327     }
    328 
    329     COMPILER_64_ZERO(fld64_val);
    330     mem_idx = ip_proto / 64;
    331     field_offset = ip_proto % 64;
    332 
    333     sal_memset(&entry_res_protocol, 0, sizeof(entry_res_protocol));
    334     BCM_IF_ERROR_RETURN(
    335         soc_mem_read(unit, RESPONSIVE_PROTOCOL_MATCHm, MEM_BLOCK_ALL,
    336                 mem_idx, (void *)&entry_res_protocol));
    337     soc_mem_field64_get(unit, RESPONSIVE_PROTOCOL_MATCHm, 
    338                     &entry_res_protocol, RESPONSIVEf, &fld64_val);
    339 
    340     if (COMPILER_64_BITTEST(fld64_val, field_offset)) {
    341         *responsive = TRUE;
    342     } else {
    343         *responsive = FALSE;
    344     }
    345 
    346     return BCM_E_NONE;
    347 #else /* !BCM_GREYHOUND_SUPPORT && !BCM_TOMAHAWK_SUPPORT */
    348     return BCM_E_UNAVAIL;
    349 #endif /* BCM_GREYHOUND_SUPPORT || BCM_TOMAHAWK_SUPPORT */
    350     
    351 }
    352 
    353 
    354 /*
    355  * Function:
    356  *      bcm_esw_ecn_responsive_protocol_get
    357  * Purpose:
    358  *      To configure the value of responsive indication based on the IP protocol value.
    359  * Parameters:
    360  *      unit - (IN) Unit number.
    361  *      ip_proto - (IN) IP Protocol value.
    362  *      responsice - (IN) Responsice indication.
    363  * Returns:
    364  *      BCM_E_XXX
    365  * Notes:
    366  */
    367 
    368 int bcm_esw_ecn_responsive_protocol_set(
    369     int unit, uint8 ip_proto, int responsive)
    370 {
    371 #if defined(BCM_GREYHOUND_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT)
    372     uint64  fld64_val, val64;
    373     int mem_idx, field_offset;
    374     responsive_protocol_match_entry_t   entry_res_protocol;
    375 
    376     if (!soc_feature(unit, soc_feature_ecn_wred)) {
    377         return BCM_E_UNAVAIL;
    378     }
    379     
    380     COMPILER_64_ZERO(fld64_val);
    381     mem_idx = ip_proto / 64;
    382     field_offset = ip_proto % 64;
    383 
    384     sal_memset(&entry_res_protocol, 0, sizeof(entry_res_protocol));
    385     BCM_IF_ERROR_RETURN(
    386         soc_mem_read(unit, RESPONSIVE_PROTOCOL_MATCHm, MEM_BLOCK_ALL,
    387                 mem_idx, (void *)&entry_res_protocol));
    388     soc_mem_field64_get(unit, RESPONSIVE_PROTOCOL_MATCHm, 
    389                     &entry_res_protocol, RESPONSIVEf, &fld64_val);
    390 
    391     COMPILER_64_ZERO(val64);
    392     COMPILER_64_SET(val64, 0x0, 0x1);
    393     COMPILER_64_SHL(val64, field_offset);
    394     if (responsive) {
    395         COMPILER_64_OR(fld64_val, val64);
    396     } else {
    397         COMPILER_64_NOT(val64);
    398         COMPILER_64_AND(fld64_val, val64);
    399     }
    400 
    401     soc_mem_field64_set(unit, RESPONSIVE_PROTOCOL_MATCHm, 
    402                     &entry_res_protocol, RESPONSIVEf, fld64_val);
    403     BCM_IF_ERROR_RETURN(
    404         soc_mem_write(unit, RESPONSIVE_PROTOCOL_MATCHm, MEM_BLOCK_ALL,
    405                 mem_idx, (void *)&entry_res_protocol));
    406 
    407     return BCM_E_NONE;
    408 #else /* !BCM_GREYHOUND_SUPPORT && !BCM_TOMAHAWK_SUPPORT */
    409     return BCM_E_UNAVAIL;
    410 #endif /* BCM_GREYHOUND_SUPPORT || BCM_TOMAHAWK_SUPPORT */
    411 }
    412 
    413 
    414 /*
    415  * Function:
    416  *      bcm_esw_ecn_traffic_map_get
    417  * Purpose:
    418  *      To get the mapped internal congestion notification (int_cn) value.
    419  * Parameters:
    420  *      unit - (IN) Unit number.
    421  *      map - (INOUT) Internal congestion notification map.
    422  * Returns:
    423  *      BCM_E_XXX
    424  * Notes:
    425  */
    426 
    427 int bcm_esw_ecn_traffic_map_get(
    428     int unit, bcm_ecn_traffic_map_info_t *map)
    429 {
    430 #if defined(BCM_GREYHOUND_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT)
    431     int mem_idx;
    432     ip_to_int_cn_mapping_entry_t        entry_ip_int_cn;
    433     uint32      fld_val;
    434     soc_mem_t cfg_mem = 0;
    435 
    436     if (!soc_feature(unit, soc_feature_ecn_wred)) {
    437         return BCM_E_UNAVAIL;
    438     }
    439 
    440     if (map == NULL) {
    441         return BCM_E_PARAM;
    442     }
    443 
    444     if (map->ecn > _BCM_ECN_VALUE_MAX) {
    445         return BCM_E_PARAM;
    446     }
    447 
    448     /* Check supported flag */
    449     if ((map->flags & ~BCM_ECN_TRAFFIC_MAP_RESPONSIVE) != 0) {
    450         return BCM_E_PARAM;
    451     }
    452 
    453 #if defined(BCM_TRIDENT3_SUPPORT)
    454     if (SOC_IS_TRIDENT3X(unit)){
    455         cfg_mem = PKT_ECN_TO_INT_CN_MAPPINGm;
    456         mem_idx = map->ecn;
    457         if (map->flags & BCM_ECN_TRAFFIC_MAP_RESPONSIVE) {
    458             /* mem_idx = (resp<<2) + ecn */
    459             mem_idx +=4;
    460         }
    461     } else
    462 #endif
    463     {
    464         cfg_mem = IP_TO_INT_CN_MAPPINGm;
    465         /* MEMORY INDEX : ECN + Responsive */
    466         mem_idx = (map->ecn << 1);
    467         if (map->flags & BCM_ECN_TRAFFIC_MAP_RESPONSIVE) {
    468             mem_idx++;
    469         }
    470     }
    471     sal_memset(&entry_ip_int_cn, 0, sizeof(entry_ip_int_cn));
    472 
    473     BCM_IF_ERROR_RETURN(
    474         soc_mem_read(unit, cfg_mem, MEM_BLOCK_ALL,
    475                 mem_idx, (void *)&entry_ip_int_cn));
    476 
    477     fld_val = soc_mem_field32_get(unit, cfg_mem,
    478                         &entry_ip_int_cn, INT_CNf);
    479 
    480     map->int_cn = fld_val;
    481     
    482 
    483     return BCM_E_NONE;
    484 #else /* !BCM_GREYHOUND_SUPPORT && !BCM_TOMAHAWK_SUPPORT */
    485     return BCM_E_UNAVAIL;
    486 #endif /* BCM_GREYHOUND_SUPPORT || BCM_TOMAHAWK_SUPPORT */
    487 }
    488  
    489 /*
    490  * Function:
    491  *      bcm_esw_ecn_traffic_map_set
    492  * Purpose:
    493  *      To set the mapped internal congestion notification (int_cn) value.
    494  * Parameters:
    495  *      unit - (IN) Unit number.
    496  *      map - (INOUT) Internal congestion notification map.
    497  * Returns:
    498  *      BCM_E_XXX
    499  * Notes:
    500  */
    501 int bcm_esw_ecn_traffic_map_set(
    502     int unit, bcm_ecn_traffic_map_info_t *map)
    503 {
    504 #if defined(BCM_GREYHOUND_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT)
    505     int mem_idx;
    506     ip_to_int_cn_mapping_entry_t        entry_ip_int_cn;
    507     uint32      fld_val;
    508     soc_mem_t cfg_mem = 0;
    509 
    510     if (!soc_feature(unit, soc_feature_ecn_wred)) {
    511         return BCM_E_UNAVAIL;
    512     }
    513 
    514     if (map == NULL) {
    515         return BCM_E_PARAM;
    516     }
    517 
    518     if (map->ecn > _BCM_ECN_VALUE_MAX) {
    519         return BCM_E_PARAM;
    520     }
    521 
    522     if ((map->int_cn < 0) || (map->int_cn > _BCM_ECN_INT_CN_VALUE_MAX)) {
    523         return BCM_E_PARAM;
    524     }
    525 
    526 #if defined(BCM_TRIDENT3_SUPPORT)
    527     if (SOC_IS_TRIDENT3X(unit)){
    528         cfg_mem = PKT_ECN_TO_INT_CN_MAPPINGm;
    529         mem_idx = map->ecn;
    530         if (map->flags & BCM_ECN_TRAFFIC_MAP_RESPONSIVE) {
    531             /* mem_idx =  (resp<<2) + ecn */
    532             mem_idx += 4;
    533         }
    534     } else
    535 #endif
    536     {
    537    /* MEMORY INDEX : ECN + Responsive */
    538     mem_idx = (map->ecn << 1);
    539     if (map->flags & BCM_ECN_TRAFFIC_MAP_RESPONSIVE) {
    540         mem_idx++;
    541     }
    542 
    543         cfg_mem = IP_TO_INT_CN_MAPPINGm;
    544     }
    545 
    546     sal_memset(&entry_ip_int_cn, 0, sizeof(entry_ip_int_cn));
    547 
    548     BCM_IF_ERROR_RETURN(
    549         soc_mem_read(unit, cfg_mem, MEM_BLOCK_ALL,
    550                 mem_idx, (void *)&entry_ip_int_cn));
    551 
    552     fld_val = map->int_cn;
    553     soc_mem_field32_set(unit, cfg_mem,
    554                         &entry_ip_int_cn, INT_CNf, fld_val);
    555 
    556     BCM_IF_ERROR_RETURN(
    557         soc_mem_write(unit, cfg_mem, MEM_BLOCK_ALL,
    558                 mem_idx, (void *)&entry_ip_int_cn));
    559 
    560     return BCM_E_NONE;
    561 #else /* !BCM_GREYHOUND_SUPPORT && !BCM_TOMAHAWK_SUPPORT */
    562     return BCM_E_UNAVAIL;
    563 #endif /* BCM_GREYHOUND_SUPPORT || BCM_TOMAHAWK_SUPPORT */
    564 }
    565 
    566 
    567 #if defined(BCM_GREYHOUND_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT)
    568 static int
    569 _bcm_esw_ecn_action_enqueue_get(int unit, 
    570     bcm_ecn_traffic_action_config_t *ecn_config)
    571 {
    572 
    573     int_cn_to_mmuif_mapping_entry_t     entry_int_cn_mmuif;
    574     int     mem_idx;
    575     uint32  fld_val;
    576     
    577     if ((ecn_config->int_cn < 0) || 
    578         (ecn_config->int_cn > _BCM_ECN_INT_CN_VALUE_MAX)) {
    579         return BCM_E_PARAM;
    580     }
    581 
    582     mem_idx = ecn_config->int_cn;
    583     sal_memset(&entry_int_cn_mmuif, 0, sizeof(entry_int_cn_mmuif));
    584 
    585     BCM_IF_ERROR_RETURN(
    586         soc_mem_read(unit, INT_CN_TO_MMUIF_MAPPINGm, MEM_BLOCK_ALL,
    587                 mem_idx, (void *)&entry_int_cn_mmuif));
    588 
    589     /* WRED RESPONSIVE */
    590     fld_val = soc_mem_field32_get(unit, INT_CN_TO_MMUIF_MAPPINGm, 
    591                         &entry_int_cn_mmuif, WRED_RESPONSIVEf);
    592     if (fld_val) {
    593         ecn_config->action_flags |= 
    594             BCM_ECN_TRAFFIC_ACTION_ENQUEUE_WRED_RESPONSIVE;
    595     } else {
    596         ecn_config->action_flags &= 
    597             ~BCM_ECN_TRAFFIC_ACTION_ENQUEUE_WRED_RESPONSIVE;
    598     }
    599 
    600     /* MARK ELIGIBLE */
    601     fld_val = soc_mem_field32_get(unit, INT_CN_TO_MMUIF_MAPPINGm, 
    602                         &entry_int_cn_mmuif, WRED_MARK_ELIGIBLEf);
    603     if (fld_val) {
    604         ecn_config->action_flags |= 
    605             BCM_ECN_TRAFFIC_ACTION_ENQUEUE_MARK_ELIGIBLE;
    606     } else {
    607         ecn_config->action_flags &= 
    608             ~BCM_ECN_TRAFFIC_ACTION_ENQUEUE_MARK_ELIGIBLE;
    609     }
    610 
    611     return BCM_E_NONE;
    612 }
    613 
    614 static int
    615 _bcm_esw_ecn_action_enqueue_set(int unit, 
    616     bcm_ecn_traffic_action_config_t *ecn_config)
    617 {
    618 
    619     int_cn_to_mmuif_mapping_entry_t     entry_int_cn_mmuif;
    620     int     mem_idx;
    621     uint32  fld_val;
    622     
    623     if ((ecn_config->int_cn < 0) || 
    624         (ecn_config->int_cn > _BCM_ECN_INT_CN_VALUE_MAX)) {
    625         return BCM_E_PARAM;
    626     }
    627 
    628     mem_idx = ecn_config->int_cn;
    629     sal_memset(&entry_int_cn_mmuif, 0, sizeof(entry_int_cn_mmuif));
    630 
    631     BCM_IF_ERROR_RETURN(
    632         soc_mem_read(unit, INT_CN_TO_MMUIF_MAPPINGm, MEM_BLOCK_ALL,
    633                 mem_idx, (void *)&entry_int_cn_mmuif));
    634 
    635     /* WRED RESPONSIVE */
    636     if (ecn_config->action_flags & 
    637         BCM_ECN_TRAFFIC_ACTION_ENQUEUE_WRED_RESPONSIVE) {
    638         fld_val = 1;
    639     } else {
    640         fld_val = 0;
    641     }
    642     soc_mem_field32_set(unit, INT_CN_TO_MMUIF_MAPPINGm, 
    643                         &entry_int_cn_mmuif, WRED_RESPONSIVEf, fld_val);
    644 
    645     /* MARK ELIGIBLE */
    646     if (ecn_config->action_flags & 
    647         BCM_ECN_TRAFFIC_ACTION_ENQUEUE_MARK_ELIGIBLE) {
    648         fld_val = 1;
    649     } else {
    650         fld_val = 0;
    651     }
    652     soc_mem_field32_set(unit, INT_CN_TO_MMUIF_MAPPINGm, 
    653                         &entry_int_cn_mmuif, WRED_MARK_ELIGIBLEf, fld_val);
    654 
    655     BCM_IF_ERROR_RETURN(
    656         soc_mem_write(unit, INT_CN_TO_MMUIF_MAPPINGm, MEM_BLOCK_ALL,
    657                 mem_idx, (void *)&entry_int_cn_mmuif));
    658 
    659     return BCM_E_NONE;
    660 }
    661 
    662 static int
    663 _bcm_esw_ecn_action_dequeue_get(int unit, 
    664     bcm_ecn_traffic_action_config_t *ecn_config)
    665 {
    666     int mem_idx, cng, ce_green, ce_yellow, ce_red, index_max;
    667     egr_int_cn_update_entry_t           entry_egr_int_cn_update;
    668     uint32      fld_val;
    669 #if defined(BCM_TRIDENT3_SUPPORT)
    670     int ce = 0;
    671 #endif
    672     
    673     if ((ecn_config->color != bcmColorGreen) && 
    674         (ecn_config->color != bcmColorYellow) &&
    675         (ecn_config->color != bcmColorRed)) {
    676         return BCM_E_PARAM;
    677     }
    678 
    679     if ((ecn_config->int_cn < 0) || 
    680         (ecn_config->int_cn > _BCM_ECN_INT_CN_VALUE_MAX)) {
    681         return BCM_E_PARAM;
    682     }
    683 
    684     /* 
    685      * Memory index : int_cn(2 bits)+ce_green+ce_yellow+ce_red+cng(2bit) 
    686      * Only the ce_[color] match the value of cng is meaningful.
    687  */
    688     cng = _BCM_COLOR_ENCODING(unit, ecn_config->color);
    689     index_max = soc_mem_index_max(unit, EGR_INT_CN_UPDATEm);
    690     ce_green = 0;
    691     ce_yellow = 0;
    692     ce_red = 0;
    693 
    694 #if defined(BCM_TRIDENT3_SUPPORT)
    695     if(SOC_IS_TRIDENT3X(unit)) {
    696         ce = 0;
    697         mem_idx =
    698             (ecn_config->int_cn << _BCM_ECN_DEQUEUE_MEM_INDEX_INT_CN_OFFSET_TD3)
    699             + (ce << _BCM_ECN_DEQUEUE_MEM_INDEX_CE_OFFSET_TD3)
    700             + (cng << _BCM_ECN_DEQUEUE_MEM_INDEX_CNG_OFFSET);
    701     
    702         if (mem_idx > index_max) {
    703             return BCM_E_PARAM;
    704         }
    705 
    706         sal_memset(&entry_egr_int_cn_update, 0,
    707                                     sizeof(entry_egr_int_cn_update));
    708         /* Get the updated int_cn when congestion is not exprienced */
    709         BCM_IF_ERROR_RETURN(
    710             soc_mem_read(unit, EGR_INT_CN_UPDATEm, MEM_BLOCK_ALL,
    711                     mem_idx, (void *)&entry_egr_int_cn_update));
    712         fld_val = soc_mem_field32_get(unit, EGR_INT_CN_UPDATEm,
    713                         &entry_egr_int_cn_update, INT_CNf);
    714         if (fld_val != ecn_config->int_cn) {
    715             ecn_config->action_flags |=
    716                 BCM_ECN_TRAFFIC_ACTION_DEQUEUE_NON_CONGESTION_INT_CN_UPDATE;
    717             ecn_config->non_congested_int_cn = fld_val;
    718         } else {
    719             ecn_config->action_flags &=
    720                 ~BCM_ECN_TRAFFIC_ACTION_DEQUEUE_NON_CONGESTION_INT_CN_UPDATE;
    721         }
    722     
    723         /* Get the updated int_cn when congestion is exprienced */
    724         ce = 1;
    725         mem_idx =
    726             (ecn_config->int_cn << _BCM_ECN_DEQUEUE_MEM_INDEX_INT_CN_OFFSET_TD3)
    727             + (ce << _BCM_ECN_DEQUEUE_MEM_INDEX_CE_OFFSET_TD3)
    728             + (cng << _BCM_ECN_DEQUEUE_MEM_INDEX_CNG_OFFSET);
    729 
    730         if (mem_idx > index_max) {
    731             return BCM_E_PARAM;
    732         }
    733         sal_memset(&entry_egr_int_cn_update, 0,
    734                                     sizeof(entry_egr_int_cn_update));
    735         BCM_IF_ERROR_RETURN(
    736             soc_mem_read(unit, EGR_INT_CN_UPDATEm, MEM_BLOCK_ALL,
    737                     mem_idx, (void *)&entry_egr_int_cn_update));
    738         fld_val = soc_mem_field32_get(unit, EGR_INT_CN_UPDATEm,
    739                         &entry_egr_int_cn_update, INT_CNf);
    740 
    741         if (fld_val != ecn_config->int_cn) {
    742             ecn_config->action_flags |=
    743                 BCM_ECN_TRAFFIC_ACTION_DEQUEUE_CONGESTION_INT_CN_UPDATE;
    744             ecn_config->congested_int_cn = fld_val;
    745         } else {
    746             ecn_config->action_flags &=
    747                 ~BCM_ECN_TRAFFIC_ACTION_DEQUEUE_CONGESTION_INT_CN_UPDATE;
    748         }
    749     } else
    750 #endif
    751     {
    752         mem_idx = (ecn_config->int_cn << _BCM_ECN_DEQUEUE_MEM_INDEX_INT_CN_OFFSET) +
    753             (cng << _BCM_ECN_DEQUEUE_MEM_INDEX_CNG_OFFSET);
    754 
    755         if (mem_idx > index_max) {
    756             return BCM_E_PARAM;
    757         }
    758 
    759         sal_memset(&entry_egr_int_cn_update, 0,
    760                                     sizeof(entry_egr_int_cn_update));
    761         /* Get the updated int_cn when congestion is not exprienced */
    762         BCM_IF_ERROR_RETURN(
    763             soc_mem_read(unit, EGR_INT_CN_UPDATEm, MEM_BLOCK_ALL,
    764                     mem_idx, (void *)&entry_egr_int_cn_update));
    765         fld_val = soc_mem_field32_get(unit, EGR_INT_CN_UPDATEm,
    766                         &entry_egr_int_cn_update, INT_CNf);
    767         if (fld_val != ecn_config->int_cn) {
    768             ecn_config->action_flags |=
    769                 BCM_ECN_TRAFFIC_ACTION_DEQUEUE_NON_CONGESTION_INT_CN_UPDATE;
    770             ecn_config->non_congested_int_cn = fld_val;
    771         } else {
    772             ecn_config->action_flags &=
    773                 ~BCM_ECN_TRAFFIC_ACTION_DEQUEUE_NON_CONGESTION_INT_CN_UPDATE;
    774         }
    775 
    776         /* Get the updated int_cn when congestion is exprienced */
    777         if (ecn_config->color == bcmColorGreen) {
    778             ce_green = 1;
    779         } else if (ecn_config->color == bcmColorYellow) {
    780             ce_yellow = 1;
    781         } else {
    782             /* Red */
    783             ce_red = 1;
    784         }
    785 
    786         mem_idx = (ecn_config->int_cn << _BCM_ECN_DEQUEUE_MEM_INDEX_INT_CN_OFFSET) +
    787             (ce_green << _BCM_ECN_DEQUEUE_MEM_INDEX_CE_GREEN_OFFSET) +
    788             (ce_yellow << _BCM_ECN_DEQUEUE_MEM_INDEX_CE_YELLOW_OFFSET) +
    789             (ce_red << _BCM_ECN_DEQUEUE_MEM_INDEX_CE_RED_OFFSET) +
    790             (cng << _BCM_ECN_DEQUEUE_MEM_INDEX_CNG_OFFSET);
    791 
    792 
    793         if (mem_idx > index_max) {
    794             return BCM_E_PARAM;
    795         }
    796         sal_memset(&entry_egr_int_cn_update, 0,
    797                                     sizeof(entry_egr_int_cn_update));
    798 
    799         BCM_IF_ERROR_RETURN(
    800             soc_mem_read(unit, EGR_INT_CN_UPDATEm, MEM_BLOCK_ALL,
    801                     mem_idx, (void *)&entry_egr_int_cn_update));
    802         fld_val = soc_mem_field32_get(unit, EGR_INT_CN_UPDATEm,
    803                         &entry_egr_int_cn_update, INT_CNf);
    804 
    805         if (fld_val != ecn_config->int_cn) {
    806             ecn_config->action_flags |=
    807                 BCM_ECN_TRAFFIC_ACTION_DEQUEUE_CONGESTION_INT_CN_UPDATE;
    808             ecn_config->congested_int_cn = fld_val;
    809         } else {
    810             ecn_config->action_flags &=
    811                 ~BCM_ECN_TRAFFIC_ACTION_DEQUEUE_CONGESTION_INT_CN_UPDATE;
    812         }
    813     }
    814     ecn_config->responsive = soc_mem_field32_get(unit, EGR_INT_CN_UPDATEm, 
    815                                                  &entry_egr_int_cn_update, 
    816                                                  RESPONSIVEf);    
    817     return BCM_E_NONE;
    818     
    819 }
    820 
    821 
    822 static int
    823 _bcm_esw_ecn_action_dequeue_set(int unit, 
    824     bcm_ecn_traffic_action_config_t *ecn_config)
    825 {
    826     int mem_idx, cng, ce_green, ce_yellow, ce_red, index_max;
    827     egr_int_cn_update_entry_t           entry_egr_int_cn_update;
    828     uint32      fld_val;
    829 #if defined(BCM_TRIDENT3_SUPPORT)
    830     int ce = 0;
    831 #endif
    832     
    833     if ((ecn_config->color != bcmColorGreen) && 
    834         (ecn_config->color != bcmColorYellow) &&
    835         (ecn_config->color != bcmColorRed)) {
    836         return BCM_E_PARAM;
    837     }
    838 
    839     if ((ecn_config->int_cn < 0) || 
    840         (ecn_config->int_cn > _BCM_ECN_INT_CN_VALUE_MAX)) {
    841         return BCM_E_PARAM;
    842     }
    843 
    844     /* 
    845      * Memory index : int_cn(2 bits)+ce_green+ce_yellow+ce_red+cng(2bit) 
    846      * Only the ce_[color] match the value of cng is meaningful.
    847  */
    848     cng = _BCM_COLOR_ENCODING(unit, ecn_config->color);
    849     index_max = soc_mem_index_max(unit, EGR_INT_CN_UPDATEm);
    850     ce_green = 0;
    851     ce_yellow = 0;
    852     ce_red = 0;
    853 
    854 #if defined(BCM_TRIDENT3_SUPPORT)
    855     if(SOC_IS_TRIDENT3X(unit)) {
    856         /* Update the int_cn value when congestion is not experienced */
    857         ce = 0;
    858         mem_idx =
    859             (ecn_config->int_cn << _BCM_ECN_DEQUEUE_MEM_INDEX_INT_CN_OFFSET_TD3)
    860             + (ce << _BCM_ECN_DEQUEUE_MEM_INDEX_CE_OFFSET_TD3)
    861             + (cng << _BCM_ECN_DEQUEUE_MEM_INDEX_CNG_OFFSET);
    862 
    863         if (mem_idx > index_max) {
    864             return BCM_E_PARAM;
    865         }
    866         sal_memset(&entry_egr_int_cn_update, 0,
    867                                     sizeof(entry_egr_int_cn_update));
    868         BCM_IF_ERROR_RETURN(
    869             soc_mem_read(unit, EGR_INT_CN_UPDATEm, MEM_BLOCK_ALL,
    870                     mem_idx, (void *)&entry_egr_int_cn_update));
    871         if ((ecn_config->action_flags &
    872             BCM_ECN_TRAFFIC_ACTION_DEQUEUE_NON_CONGESTION_INT_CN_UPDATE) &&
    873             (ecn_config->non_congested_int_cn != ecn_config->int_cn)) {
    874 
    875             if ((ecn_config->non_congested_int_cn < 0) ||
    876                 (ecn_config->non_congested_int_cn > _BCM_ECN_INT_CN_VALUE_MAX)) {
    877                 return BCM_E_PARAM;
    878             }
    879             fld_val = ecn_config->non_congested_int_cn;
    880         } else {
    881             fld_val = ecn_config->int_cn;
    882         }
    883         soc_mem_field32_set(unit, EGR_INT_CN_UPDATEm,
    884                             &entry_egr_int_cn_update, INT_CNf,
    885                             fld_val);
    886         soc_mem_field32_set(unit, EGR_INT_CN_UPDATEm,
    887                 &entry_egr_int_cn_update, RESPONSIVEf,
    888                 ecn_config->responsive ? 1 : 0);
    889 
    890         BCM_IF_ERROR_RETURN(
    891                 soc_mem_write(unit, EGR_INT_CN_UPDATEm, MEM_BLOCK_ALL,
    892                         mem_idx, (void *)&entry_egr_int_cn_update));
    893 
    894 
    895         /* Update the int_cn value when congestion is experienced */
    896         ce = 1;
    897         mem_idx =
    898             (ecn_config->int_cn << _BCM_ECN_DEQUEUE_MEM_INDEX_INT_CN_OFFSET_TD3)
    899             + (ce << _BCM_ECN_DEQUEUE_MEM_INDEX_CE_OFFSET_TD3)
    900             + (cng << _BCM_ECN_DEQUEUE_MEM_INDEX_CNG_OFFSET);
    901 
    902         if (mem_idx > index_max) {
    903             return BCM_E_PARAM;
    904         }
    905         sal_memset(&entry_egr_int_cn_update, 0,
    906                                     sizeof(entry_egr_int_cn_update));
    907 
    908         BCM_IF_ERROR_RETURN(
    909             soc_mem_read(unit, EGR_INT_CN_UPDATEm, MEM_BLOCK_ALL,
    910                     mem_idx, (void *)&entry_egr_int_cn_update));
    911         if ((ecn_config->action_flags &
    912             BCM_ECN_TRAFFIC_ACTION_DEQUEUE_CONGESTION_INT_CN_UPDATE) &&
    913             (ecn_config->congested_int_cn != ecn_config->int_cn)) {
    914 
    915             if ((ecn_config->congested_int_cn < 0) ||
    916                 (ecn_config->congested_int_cn > _BCM_ECN_INT_CN_VALUE_MAX)) {
    917                 return BCM_E_PARAM;
    918             }
    919             fld_val = ecn_config->congested_int_cn;
    920         } else {
    921             fld_val = ecn_config->int_cn;
    922         }
    923         soc_mem_field32_set(unit, EGR_INT_CN_UPDATEm,
    924                         &entry_egr_int_cn_update, INT_CNf, fld_val);
    925 
    926         soc_mem_field32_set(unit, EGR_INT_CN_UPDATEm,
    927                 &entry_egr_int_cn_update, RESPONSIVEf,
    928                 ecn_config->responsive ? 1 : 0);
    929 
    930         BCM_IF_ERROR_RETURN(
    931             soc_mem_write(unit, EGR_INT_CN_UPDATEm, MEM_BLOCK_ALL,
    932                     mem_idx, (void *)&entry_egr_int_cn_update));
    933     } else
    934 #endif
    935     {
    936         /* Update the int_cn value when congestion is not experienced */
    937         for (ce_green = 0; ce_green < 2; ce_green++) {
    938             if ((ecn_config->color == bcmColorGreen) && (ce_green == 1)) {
    939                 /* Bypass the congestion case */
    940                 continue;
    941             }
    942             for (ce_yellow = 0; ce_yellow < 2; ce_yellow++) {
    943                 if ((ecn_config->color == bcmColorYellow) && (ce_yellow == 1)) {
    944                     /* Bypass the congestion case */
    945                     continue;
    946                 }
    947                 for (ce_red = 0; ce_red < 2; ce_red++) {
    948                     if ((ecn_config->color == bcmColorRed) && (ce_red == 1)) {
    949                         /* Bypass the congestion case */
    950                         continue;
    951                     }
    952         mem_idx =
    953             (ecn_config->int_cn << _BCM_ECN_DEQUEUE_MEM_INDEX_INT_CN_OFFSET) +
    954             (ce_green << _BCM_ECN_DEQUEUE_MEM_INDEX_CE_GREEN_OFFSET) +
    955             (ce_yellow << _BCM_ECN_DEQUEUE_MEM_INDEX_CE_YELLOW_OFFSET) +
    956             (ce_red << _BCM_ECN_DEQUEUE_MEM_INDEX_CE_RED_OFFSET) +
    957             (cng << _BCM_ECN_DEQUEUE_MEM_INDEX_CNG_OFFSET);
    958 
    959         if (mem_idx > index_max) {
    960             return BCM_E_PARAM;
    961         }
    962         sal_memset(&entry_egr_int_cn_update, 0,
    963                                     sizeof(entry_egr_int_cn_update));
    964         BCM_IF_ERROR_RETURN(
    965             soc_mem_read(unit, EGR_INT_CN_UPDATEm, MEM_BLOCK_ALL,
    966                     mem_idx, (void *)&entry_egr_int_cn_update));
    967         if ((ecn_config->action_flags &
    968             BCM_ECN_TRAFFIC_ACTION_DEQUEUE_NON_CONGESTION_INT_CN_UPDATE) &&
    969             (ecn_config->non_congested_int_cn != ecn_config->int_cn)) {
    970 
    971             if ((ecn_config->non_congested_int_cn < 0) ||
    972                 (ecn_config->non_congested_int_cn > _BCM_ECN_INT_CN_VALUE_MAX)) {
    973                 return BCM_E_PARAM;
    974             }
    975             fld_val = ecn_config->non_congested_int_cn;
    976         } else {
    977             fld_val = ecn_config->int_cn;
    978         }
    979         soc_mem_field32_set(unit, EGR_INT_CN_UPDATEm,
    980                             &entry_egr_int_cn_update, INT_CNf, fld_val);
    981         soc_mem_field32_set(unit, EGR_INT_CN_UPDATEm,
    982                             &entry_egr_int_cn_update, RESPONSIVEf,
    983                                 ecn_config->responsive ? 1 : 0);
    984         BCM_IF_ERROR_RETURN(
    985                 soc_mem_write(unit, EGR_INT_CN_UPDATEm, MEM_BLOCK_ALL,
    986                         mem_idx, (void *)&entry_egr_int_cn_update));
    987                 }
    988             }
    989         }
    990 
    991         /* Update the int_cn value when congestion is experienced */
    992         for (ce_green = 0; ce_green < 2; ce_green++) {
    993             if ((ecn_config->color == bcmColorGreen) && (ce_green == 0)) {
    994                 /* Bypass the non-congestion case */
    995                 continue;
    996             }
    997             for (ce_yellow = 0; ce_yellow < 2; ce_yellow++) {
    998                 if ((ecn_config->color == bcmColorYellow) && (ce_yellow == 0)) {
    999                     /* Bypass the non-congestion case */
   1000                     continue;
   1001                 }
   1002                 for (ce_red = 0; ce_red < 2; ce_red++) {
   1003                     if ((ecn_config->color == bcmColorRed) && (ce_red == 0)) {
   1004                         /* Bypass the non-congestion case */
   1005                         continue;
   1006                     }
   1007         mem_idx =
   1008             (ecn_config->int_cn << _BCM_ECN_DEQUEUE_MEM_INDEX_INT_CN_OFFSET) +
   1009             (ce_green << _BCM_ECN_DEQUEUE_MEM_INDEX_CE_GREEN_OFFSET) +
   1010             (ce_yellow << _BCM_ECN_DEQUEUE_MEM_INDEX_CE_YELLOW_OFFSET) +
   1011             (ce_red << _BCM_ECN_DEQUEUE_MEM_INDEX_CE_RED_OFFSET) +
   1012             (cng << _BCM_ECN_DEQUEUE_MEM_INDEX_CNG_OFFSET);
   1013 
   1014         if (mem_idx > index_max) {
   1015             return BCM_E_PARAM;
   1016         }
   1017         sal_memset(&entry_egr_int_cn_update, 0,
   1018                                     sizeof(entry_egr_int_cn_update));
   1019 
   1020         BCM_IF_ERROR_RETURN(
   1021             soc_mem_read(unit, EGR_INT_CN_UPDATEm, MEM_BLOCK_ALL,
   1022                     mem_idx, (void *)&entry_egr_int_cn_update));
   1023         if ((ecn_config->action_flags &
   1024             BCM_ECN_TRAFFIC_ACTION_DEQUEUE_CONGESTION_INT_CN_UPDATE) &&
   1025             (ecn_config->congested_int_cn != ecn_config->int_cn)) {
   1026 
   1027             if ((ecn_config->congested_int_cn < 0) ||
   1028                 (ecn_config->congested_int_cn > _BCM_ECN_INT_CN_VALUE_MAX)) {
   1029                 return BCM_E_PARAM;
   1030             }
   1031             fld_val = ecn_config->congested_int_cn;
   1032         } else {
   1033             fld_val = ecn_config->int_cn;
   1034         }
   1035         soc_mem_field32_set(unit, EGR_INT_CN_UPDATEm,
   1036                             &entry_egr_int_cn_update, INT_CNf, fld_val);
   1037         soc_mem_field32_set(unit, EGR_INT_CN_UPDATEm, 
   1038                             &entry_egr_int_cn_update, RESPONSIVEf, 
   1039                             ecn_config->responsive ? 1 : 0);
   1040         BCM_IF_ERROR_RETURN(
   1041             soc_mem_write(unit, EGR_INT_CN_UPDATEm, MEM_BLOCK_ALL,
   1042                     mem_idx, (void *)&entry_egr_int_cn_update));
   1043                 }
   1044             }
   1045         }
   1046     }
   1047     return BCM_E_NONE;
   1048     
   1049 }
   1050 
   1051 
   1052 static int
   1053 _bcm_esw_ecn_action_egress_get(int unit, 
   1054     bcm_ecn_traffic_action_config_t *ecn_config)
   1055 {
   1056     int mem_idx, index_max;
   1057     egr_int_cn_to_ip_mapping_entry_t    entry_egr_int_cn_ip_mapping;
   1058     uint32  fld_val;
   1059     soc_mem_t cfg_mem = 0;
   1060     
   1061     if ((ecn_config->int_cn < 0) || 
   1062         (ecn_config->int_cn > _BCM_ECN_INT_CN_VALUE_MAX)) {
   1063         return BCM_E_PARAM;
   1064     }
   1065 
   1066     if (ecn_config->ecn > _BCM_ECN_VALUE_MAX) {
   1067         return BCM_E_PARAM;
   1068     }
   1069 #if defined(BCM_TRIDENT3_SUPPORT)
   1070     if(SOC_IS_TRIDENT3X(unit)){
   1071         cfg_mem = EGR_INT_CN_TO_PKT_ECN_MAPPINGm;
   1072     } else
   1073 #endif
   1074     {
   1075         cfg_mem = EGR_INT_CN_TO_IP_MAPPINGm;
   1076     }
   1077 
   1078     mem_idx = (ecn_config->int_cn << _BCM_ECN_EGRESS_MEM_INDEX_INT_CN_OFFSET) +
   1079         (ecn_config->ecn << _BCM_ECN_EGRESS_MEM_INDEX_ECN_OFFSET);
   1080     index_max = soc_mem_index_max(unit, cfg_mem);
   1081 
   1082     if (mem_idx > index_max) {
   1083         return BCM_E_PARAM;
   1084     }
   1085     sal_memset(&entry_egr_int_cn_ip_mapping, 0, 
   1086                     sizeof(entry_egr_int_cn_ip_mapping));
   1087 
   1088     BCM_IF_ERROR_RETURN(
   1089         soc_mem_read(unit, cfg_mem, MEM_BLOCK_ALL,
   1090                 mem_idx, (void *)&entry_egr_int_cn_ip_mapping));
   1091     
   1092     /* Check ECN MARKING action */
   1093     fld_val = soc_mem_field32_get(unit, cfg_mem,
   1094                     &entry_egr_int_cn_ip_mapping, 
   1095                     CHANGE_PACKET_ECNf);
   1096     
   1097     if (fld_val) {
   1098         ecn_config->action_flags |= 
   1099             BCM_ECN_TRAFFIC_ACTION_EGRESS_ECN_MARKING;
   1100         fld_val = soc_mem_field32_get(unit, cfg_mem,
   1101                     &entry_egr_int_cn_ip_mapping, ECNf);
   1102         ecn_config->new_ecn = fld_val;
   1103     } else {
   1104         ecn_config->action_flags &= 
   1105             ~BCM_ECN_TRAFFIC_ACTION_EGRESS_ECN_MARKING;
   1106     }
   1107 
   1108     /* Check Drop action */
   1109     fld_val = soc_mem_field32_get(unit, cfg_mem,
   1110                     &entry_egr_int_cn_ip_mapping, DROPf);
   1111     if (fld_val) {
   1112         ecn_config->action_flags |= 
   1113             BCM_ECN_TRAFFIC_ACTION_EGRESS_DROP;
   1114     } else {
   1115         ecn_config->action_flags &= 
   1116             ~BCM_ECN_TRAFFIC_ACTION_EGRESS_DROP;
   1117     }
   1118     
   1119     
   1120     return BCM_E_NONE;
   1121 }
   1122 
   1123 
   1124 static int
   1125 _bcm_esw_ecn_action_egress_set(int unit, 
   1126     bcm_ecn_traffic_action_config_t *ecn_config)
   1127 {
   1128     int mem_idx, index_max;
   1129     egr_int_cn_to_ip_mapping_entry_t    entry_egr_int_cn_ip_mapping;
   1130     uint32  fld_val;
   1131     soc_mem_t cfg_mem = 0;
   1132     
   1133     if ((ecn_config->int_cn < 0) || 
   1134         (ecn_config->int_cn > _BCM_ECN_INT_CN_VALUE_MAX)) {
   1135         return BCM_E_PARAM;
   1136     }
   1137 
   1138     if ((ecn_config->ecn > _BCM_ECN_VALUE_MAX) ||
   1139         (ecn_config->new_ecn > _BCM_ECN_VALUE_MAX)) {
   1140         return BCM_E_PARAM;
   1141     }
   1142 
   1143 #if defined(BCM_TRIDENT3_SUPPORT)
   1144         if(SOC_IS_TRIDENT3X(unit)){
   1145             cfg_mem = EGR_INT_CN_TO_PKT_ECN_MAPPINGm;
   1146         } else
   1147 #endif
   1148         {
   1149             cfg_mem = EGR_INT_CN_TO_IP_MAPPINGm;
   1150         }
   1151 
   1152     mem_idx = (ecn_config->int_cn << _BCM_ECN_EGRESS_MEM_INDEX_INT_CN_OFFSET) +
   1153         (ecn_config->ecn << _BCM_ECN_EGRESS_MEM_INDEX_ECN_OFFSET);
   1154     index_max = soc_mem_index_max(unit, cfg_mem);
   1155 
   1156     if (mem_idx > index_max) {
   1157         return BCM_E_PARAM;
   1158     }
   1159     sal_memset(&entry_egr_int_cn_ip_mapping, 0, 
   1160                     sizeof(entry_egr_int_cn_ip_mapping));
   1161 
   1162     BCM_IF_ERROR_RETURN(
   1163         soc_mem_read(unit, cfg_mem, MEM_BLOCK_ALL,
   1164                 mem_idx, (void *)&entry_egr_int_cn_ip_mapping));
   1165 
   1166     /* ECN Marking action */
   1167     if (ecn_config->action_flags & BCM_ECN_TRAFFIC_ACTION_EGRESS_ECN_MARKING) {
   1168 
   1169         soc_mem_field32_set(unit, cfg_mem,
   1170                     &entry_egr_int_cn_ip_mapping, 
   1171                     CHANGE_PACKET_ECNf, 1);
   1172         soc_mem_field32_set(unit, cfg_mem,
   1173                     &entry_egr_int_cn_ip_mapping, 
   1174                     INCREMENT_ECN_COUNTERf, 1);
   1175         fld_val = ecn_config->new_ecn;
   1176         soc_mem_field32_set(unit, cfg_mem,
   1177                     &entry_egr_int_cn_ip_mapping, 
   1178                     ECNf, fld_val);
   1179     } else {
   1180         soc_mem_field32_set(unit, cfg_mem,
   1181                     &entry_egr_int_cn_ip_mapping, 
   1182                     CHANGE_PACKET_ECNf, 0);
   1183         soc_mem_field32_set(unit, cfg_mem,
   1184                     &entry_egr_int_cn_ip_mapping, 
   1185                     INCREMENT_ECN_COUNTERf, 0);
   1186     }
   1187 
   1188     /* Drop action */
   1189     if (ecn_config->action_flags & BCM_ECN_TRAFFIC_ACTION_EGRESS_DROP) {
   1190         fld_val = 1;
   1191     } else {
   1192         fld_val = 0;
   1193     }
   1194     soc_mem_field32_set(unit, cfg_mem,
   1195                     &entry_egr_int_cn_ip_mapping, 
   1196                     DROPf, fld_val);
   1197 
   1198     BCM_IF_ERROR_RETURN(
   1199         soc_mem_write(unit, cfg_mem, MEM_BLOCK_ALL,
   1200                 mem_idx, (void *)&entry_egr_int_cn_ip_mapping));
   1201     
   1202     
   1203     return BCM_E_NONE;
   1204 }
   1205 #endif /* BCM_GREYHOUND_SUPPORT || BCM_TOMAHAWK_SUPPORT */
   1206 
   1207 /*
   1208  * Function:
   1209  *      bcm_esw_ecn_traffic_action_config_get
   1210  * Purpose:
   1211  *      To get the actions of the specified ECN traffic.
   1212  * Parameters:
   1213  *      unit - (IN) Unit number.
   1214  *      ecn_config - (INOUT) ECN traffic action configuration.
   1215  * Returns:
   1216  *      BCM_E_XXX
   1217  * Notes:
   1218  */
   1219 
   1220 int 
   1221 bcm_esw_ecn_traffic_action_config_get(
   1222     int unit, bcm_ecn_traffic_action_config_t *ecn_config)
   1223 {
   1224 #if defined(BCM_GREYHOUND_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT)
   1225     int rv = BCM_E_NONE;
   1226     
   1227     if (!soc_feature(unit, soc_feature_ecn_wred)) {
   1228         return BCM_E_UNAVAIL;
   1229     }
   1230 
   1231     if (ecn_config == NULL) {
   1232         return BCM_E_PARAM;
   1233     }
   1234 
   1235     switch(ecn_config->action_type) {
   1236         case BCM_ECN_TRAFFIC_ACTION_TYPE_ENQUEUE:
   1237             rv = _bcm_esw_ecn_action_enqueue_get(unit, ecn_config);
   1238             break;
   1239         case BCM_ECN_TRAFFIC_ACTION_TYPE_DEQUEUE:
   1240             rv = _bcm_esw_ecn_action_dequeue_get(unit, ecn_config);
   1241             break;
   1242         case BCM_ECN_TRAFFIC_ACTION_TYPE_EGRESS:
   1243             rv = _bcm_esw_ecn_action_egress_get(unit, ecn_config);
   1244             break;
   1245         default:
   1246             rv = BCM_E_PARAM;
   1247     }
   1248     
   1249     return rv;
   1250 #else /* !BCM_GREYHOUND_SUPPORT && !BCM_TOMAHAWK_SUPPORT */
   1251     return BCM_E_UNAVAIL;
   1252 #endif /* BCM_GREYHOUND_SUPPORT || BCM_TOMAHAWK_SUPPORT */
   1253 }
   1254 
   1255 
   1256 /*
   1257  * Function:
   1258  *      bcm_esw_ecn_traffic_action_config_set
   1259  * Purpose:
   1260  *      Assign the actions of the specified ECN traffic.
   1261  * Parameters:
   1262  *      unit - (IN) Unit number.
   1263  *      ecn_config - (IN) ECN traffic action configuration.
   1264  * Returns:
   1265  *      BCM_E_XXX
   1266  * Notes:
   1267  */
   1268 
   1269 int 
   1270 bcm_esw_ecn_traffic_action_config_set(
   1271     int unit, bcm_ecn_traffic_action_config_t *ecn_config)
   1272 {
   1273 #if defined(BCM_GREYHOUND_SUPPORT) || defined(BCM_TOMAHAWK_SUPPORT)
   1274     int rv = BCM_E_NONE;
   1275     
   1276     if (!soc_feature(unit, soc_feature_ecn_wred)) {
   1277         return BCM_E_UNAVAIL;
   1278     }
   1279 
   1280     if (ecn_config == NULL) {
   1281         return BCM_E_PARAM;
   1282     }
   1283 
   1284     if (ecn_config->action_flags &
   1285         ~(BCM_ECN_TRAFFIC_ACTION_ENQUEUE_WRED_RESPONSIVE |
   1286         BCM_ECN_TRAFFIC_ACTION_ENQUEUE_MARK_ELIGIBLE |
   1287         BCM_ECN_TRAFFIC_ACTION_DEQUEUE_CONGESTION_INT_CN_UPDATE |
   1288         BCM_ECN_TRAFFIC_ACTION_DEQUEUE_NON_CONGESTION_INT_CN_UPDATE |
   1289         BCM_ECN_TRAFFIC_ACTION_EGRESS_ECN_MARKING |
   1290         BCM_ECN_TRAFFIC_ACTION_EGRESS_DROP)) {
   1291         return BCM_E_PARAM;
   1292     }
   1293 
   1294     switch(ecn_config->action_type) {
   1295         case BCM_ECN_TRAFFIC_ACTION_TYPE_ENQUEUE:
   1296             rv = _bcm_esw_ecn_action_enqueue_set(unit, ecn_config);
   1297             break;
   1298         case BCM_ECN_TRAFFIC_ACTION_TYPE_DEQUEUE:
   1299             rv = _bcm_esw_ecn_action_dequeue_set(unit, ecn_config);
   1300             break;
   1301         case BCM_ECN_TRAFFIC_ACTION_TYPE_EGRESS:
   1302             rv = _bcm_esw_ecn_action_egress_set(unit, ecn_config);
   1303             break;
   1304         default:
   1305             rv = BCM_E_PARAM;
   1306     }
   1307 
   1308     return rv;
   1309 #else /* !BCM_GREYHOUND_SUPPORT && !BCM_TOMAHAWK_SUPPORT */
   1310     return BCM_E_UNAVAIL;
   1311 #endif /* BCM_GREYHOUND_SUPPORT || BCM_TOMAHAWK_SUPPORT */
   1312 }
   1313 #if defined(INCLUDE_L3)
   1314 /*
   1315  * Function:
   1316  *      bcm_esw_ecn_map_create
   1317  * Purpose:
   1318  *      To create an ECN mapping profile.
   1319  * Parameters:
   1320  *      unit          - (IN) Unit number.
   1321  *      flags         - (IN) ECN flags.
   1322  *      ecn_map_id    - (IN) ECN map id.
   1323  * Returns:
   1324  *      BCM_E_XXX
   1325  * Notes:
   1326  */
   1327 
   1328 int
   1329 bcm_esw_ecn_map_create(int unit, uint32 flags, int *ecn_map_id)
   1330 {
   1331     int rv = BCM_E_UNAVAIL;
   1332 #if defined(BCM_TOMAHAWK_SUPPORT)
   1333     if (soc_feature(unit, soc_feature_ecn_wred) &&  
   1334         (flags & BCM_ECN_MAP_TUNNEL_TERM)) {
   1335         rv = bcmi_xgs5_ecn_map_create(unit, flags, ecn_map_id);
   1336         return rv;
   1337     }
   1338 #endif
   1339 #if (defined(BCM_MPLS_SUPPORT) && (defined(BCM_TOMAHAWK2_SUPPORT) || \
   1340    defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)))
   1341     if (soc_feature(unit, soc_feature_mpls_ecn)) {
   1342         rv = bcmi_xgs5_mpls_ecn_map_create(unit, flags, ecn_map_id);
   1343         return rv;
   1344     }
   1345 #endif
   1346     return rv;
   1347 
   1348 }
   1349 
   1350 /*
   1351  * Function:
   1352  *      bcm_esw_ecn_map_destroy
   1353  * Purpose:
   1354  *      To destroy an ECN mapping profile.
   1355  * Parameters:
   1356  *      unit        - (IN) Unit number.
   1357  *      ecn_map_id  - (IN) ECN map id.
   1358  * Returns:
   1359  *      BCM_E_XXX
   1360  * Notes:
   1361  */
   1362 
   1363 int
   1364 bcm_esw_ecn_map_destroy(int unit, int ecn_map_id)
   1365 {
   1366     int rv = BCM_E_UNAVAIL;
   1367 #if defined(BCM_TOMAHAWK_SUPPORT)
   1368     if (soc_feature(unit, soc_feature_ecn_wred) &&  
   1369         (_BCM_XGS5_ECN_MAP_TYPE_TUNNEL_TERM == 
   1370         (ecn_map_id & _BCM_XGS5_ECN_MAP_TYPE_MASK))) {
   1371         rv = bcmi_xgs5_ecn_map_destroy(unit, ecn_map_id);
   1372         return rv;
   1373     }
   1374 #endif    
   1375 #if (defined(BCM_MPLS_SUPPORT) && (defined(BCM_TOMAHAWK2_SUPPORT) || \
   1376    defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)))
   1377     if (soc_feature(unit, soc_feature_mpls_ecn)) {
   1378         rv = bcmi_xgs5_mpls_ecn_map_destroy(unit, ecn_map_id);
   1379         return rv;
   1380     }
   1381 #endif
   1382     return rv;
   1383 }
   1384 
   1385 /*
   1386  * Function:
   1387  *      bcm_esw_ecn_map_set
   1388  * Purpose:
   1389  *      To set an ECN mapping entry in  an ECN mapping profile.
   1390  * Parameters:
   1391  *      unit         - (IN) Unit number.
   1392  *      options      - (IN) options, no used currently
   1393  *      ecn_map_id   - (IN) ECN map id.
   1394  *      ecn_map      - (IN)  ECN mapping  values
   1395  * Returns:
   1396  *      BCM_E_XXX
   1397  * Notes:
   1398  */
   1399 
   1400 int
   1401 bcm_esw_ecn_map_set(int unit, uint32 options, int ecn_map_id, 
   1402                     bcm_ecn_map_t *ecn_map)
   1403 {
   1404     int rv = BCM_E_UNAVAIL;
   1405 #if defined(BCM_TOMAHAWK_SUPPORT)
   1406     if (soc_feature(unit, soc_feature_ecn_wred) && 
   1407         (_BCM_XGS5_ECN_MAP_TYPE_TUNNEL_TERM == 
   1408         (ecn_map_id & _BCM_XGS5_ECN_MAP_TYPE_MASK))) {
   1409         rv = bcmi_xgs5_ecn_map_set(unit, ecn_map_id, ecn_map);
   1410         return rv;
   1411     }
   1412 #endif    
   1413 #if (defined(BCM_MPLS_SUPPORT) && (defined(BCM_TOMAHAWK2_SUPPORT) || \
   1414    defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)))
   1415     if (soc_feature(unit, soc_feature_mpls_ecn)) {
   1416         rv = bcmi_xgs5_mpls_ecn_map_set(unit, ecn_map_id, ecn_map);
   1417         return rv;
   1418     }
   1419 #endif
   1420     return rv;
   1421 }
   1422 
   1423 
   1424 /*
   1425  * Function:
   1426  *      bcm_esw_ecn_map_get
   1427  * Purpose:
   1428  *      To get an ECN mapping entry from  an ECN mapping profile.
   1429  * Parameters:
   1430  *      unit        - (IN) Unit number.
   1431  *      options     - (IN) options, no used currently
   1432  *      ecn_map_id  - (IN) ECN map id.
   1433  *      ecn_map     - (IN/OUT)  ECN mapping  values
   1434  * Returns:
   1435  *      BCM_E_XXX
   1436  * Notes:
   1437  */
   1438 
   1439 
   1440 int
   1441 bcm_esw_ecn_map_get(int unit, int ecn_map_id, bcm_ecn_map_t *ecn_map)
   1442 {
   1443     int rv = BCM_E_UNAVAIL;
   1444 #if defined(BCM_TOMAHAWK_SUPPORT)
   1445     if (soc_feature(unit, soc_feature_ecn_wred) && 
   1446         (_BCM_XGS5_ECN_MAP_TYPE_TUNNEL_TERM == 
   1447         (ecn_map_id & _BCM_XGS5_ECN_MAP_TYPE_MASK))) {
   1448         rv = bcmi_xgs5_ecn_map_get(unit, ecn_map_id, ecn_map);
   1449         return rv;
   1450     }
   1451 #endif    
   1452 #if (defined(BCM_MPLS_SUPPORT) && (defined(BCM_TOMAHAWK2_SUPPORT) || \
   1453    defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)))
   1454     if (soc_feature(unit, soc_feature_mpls_ecn)) {
   1455         rv = bcmi_xgs5_mpls_ecn_map_get(unit, ecn_map_id, ecn_map);
   1456         return rv;
   1457     }
   1458 #endif
   1459     return rv;
   1460 }
   1461 
   1462 /*
   1463  * Function:
   1464  *      bcm_ecn_port_map_get
   1465  * Purpose:
   1466  *      To get an ECN mapping info from a port.
   1467  * Parameters:
   1468  *      unit    - (IN) Unit number.
   1469  *      port    - (IN) gport.
   1470  *      ecn_map - (IN/OUT)  ECN mapping  info
   1471  * Returns:
   1472  *      BCM_E_XXX
   1473  * Notes:
   1474  */
   1475 
   1476 int
   1477 bcm_esw_ecn_port_map_get(int unit, bcm_gport_t port, bcm_ecn_port_map_t *ecn_map)
   1478 
   1479 {
   1480     int rv = BCM_E_UNAVAIL;
   1481 #if defined(BCM_TOMAHAWK_SUPPORT)
   1482     if (soc_feature(unit, soc_feature_ecn_wred) &&
   1483 #if defined(BCM_TOMAHAWK3_SUPPORT)
   1484         (!SOC_IS_TOMAHAWK3(unit)) &&
   1485 #endif
   1486         (BCM_ECN_INGRESS_PORT_TUNNEL_TERM_MAP & ecn_map->flags)) {
   1487         rv = bcmi_xgs5_ecn_port_map_get(unit, port, ecn_map);
   1488         return rv;
   1489     }
   1490 #endif
   1491 #if (defined(BCM_MPLS_SUPPORT) && (defined(BCM_TOMAHAWK2_SUPPORT) || \
   1492    defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)))
   1493     if (soc_feature(unit, soc_feature_mpls_ecn)) {
   1494         rv = bcmi_xgs5_mpls_ecn_port_map_get(unit, port, ecn_map);
   1495         return rv;
   1496     }
   1497 #endif
   1498     return rv;
   1499 }
   1500 
   1501 /*
   1502  * Function:
   1503  *      bcm_ecn_port_map_set
   1504  * Purpose:
   1505  *      To set an ECN mapping info from a port.
   1506  * Parameters:
   1507  *      unit    - (IN) Unit number.
   1508  *      port    - (IN) gport.
   1509  *      ecn_map - (IN)  ECN mapping  info
   1510  * Returns:
   1511  *      BCM_E_XXX
   1512  * Notes:
   1513  */
   1514 
   1515 int
   1516 bcm_esw_ecn_port_map_set(int unit, bcm_gport_t port, bcm_ecn_port_map_t *ecn_map)
   1517 
   1518 {
   1519     int rv = BCM_E_UNAVAIL;
   1520 #if defined(BCM_TOMAHAWK_SUPPORT)
   1521     if (soc_feature(unit, soc_feature_ecn_wred) &&
   1522 #if defined(BCM_TOMAHAWK3_SUPPORT)
   1523         (!SOC_IS_TOMAHAWK3(unit)) &&
   1524 #endif
   1525         (BCM_ECN_INGRESS_PORT_TUNNEL_TERM_MAP & ecn_map->flags)) {
   1526         rv = bcmi_xgs5_ecn_port_map_set(unit, port, ecn_map);
   1527         return rv;
   1528     }
   1529 #endif    
   1530 #if (defined(BCM_MPLS_SUPPORT) && (defined(BCM_TOMAHAWK2_SUPPORT) || \
   1531    defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)))
   1532     if (soc_feature(unit, soc_feature_mpls_ecn)) {
   1533         rv = bcmi_xgs5_mpls_ecn_port_map_set(unit, port, ecn_map);
   1534         return rv;
   1535     }
   1536 #endif
   1537     return rv;
   1538 }
   1539 
   1540 /*
   1541  * Function:
   1542  *      bcm_esw_ecn_map_mode_set
   1543  * Purpose:
   1544  *      To set an ECN mapping mode.
   1545  * Parameters:
   1546  *      unit    - (IN) Unit number.
   1547  *      ecn_map_mode - (IN)  ECN mapping mode info
   1548  * Returns:
   1549  *      BCM_E_XXX
   1550  * Notes:
   1551  */
   1552 
   1553 int
   1554 bcm_esw_ecn_map_mode_set(int unit,
   1555     bcm_ecn_map_mode_t *ecn_map_mode)
   1556 {
   1557     int rv            = BCM_E_UNAVAIL;
   1558 #if defined(BCM_TRIDENT2_SUPPORT)
   1559     soc_mem_t mem     = EGR_DSCP_ECN_MAPm;
   1560     soc_field_t field = ECN_MODEf;
   1561     egr_dscp_ecn_map_entry_t map_entry;
   1562     int idx_min, idx_max, idx;
   1563 
   1564     if (soc_feature(unit, soc_feature_ecn_dscp_map_mode)) {
   1565         if (ecn_map_mode == NULL) {
   1566             rv = BCM_E_PARAM;
   1567             return rv;
   1568         }
   1569 
   1570         if ((ecn_map_mode->dscp < -1) || (ecn_map_mode->dscp > 63)) {
   1571             rv = BCM_E_PARAM;
   1572             return rv;
   1573         }
   1574 
   1575         if (ecn_map_mode->dscp_map_mode >= bcmEcnDscpMapModeCount ||
   1576             ecn_map_mode->dscp_map_mode < 0) {
   1577             rv = BCM_E_PARAM;
   1578             return rv;
   1579         }
   1580 
   1581         if (ecn_map_mode->dscp == -1) {
   1582             idx_min = 0;
   1583             idx_max = 64;
   1584         } else {
   1585             idx_min = ecn_map_mode->dscp;
   1586             idx_max = idx_min+1;
   1587         }
   1588 
   1589         for (idx = idx_min; idx < idx_max; idx++) {
   1590             sal_memset(&map_entry, 0, sizeof(map_entry));
   1591             BCM_IF_ERROR_RETURN(
   1592                 soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, (void*)&map_entry));
   1593             soc_mem_field32_set(unit, mem, &map_entry, field,
   1594                 ecn_map_mode->dscp_map_mode);
   1595             BCM_IF_ERROR_RETURN(
   1596                 soc_mem_write(unit, mem, MEM_BLOCK_ALL, idx, (void*)&map_entry));
   1597         }
   1598 
   1599         rv = BCM_E_NONE;
   1600         return rv;
   1601     }
   1602 #endif /* BCM_TRIDENT2_SUPPORT */
   1603 
   1604     return rv;
   1605 }
   1606 
   1607 /*
   1608  * Function:
   1609  *      bcm_esw_ecn_map_mode_get
   1610  * Purpose:
   1611  *      To get an ECN mapping mode info.
   1612  * Parameters:
   1613  *      unit    - (IN) Unit number.
   1614  *      ecn_map_mode - (IN/OUT)  ECN mapping mode info
   1615  * Returns:
   1616  *      BCM_E_XXX
   1617  * Notes:
   1618  */
   1619 
   1620 int
   1621 bcm_esw_ecn_map_mode_get(int unit,
   1622     bcm_ecn_map_mode_t *ecn_map_mode)
   1623 {
   1624     int rv            = BCM_E_UNAVAIL;
   1625 #if defined(BCM_TRIDENT2_SUPPORT)
   1626     soc_mem_t mem     = EGR_DSCP_ECN_MAPm;
   1627     soc_field_t field = ECN_MODEf;
   1628     egr_dscp_ecn_map_entry_t map_entry;
   1629     int idx;
   1630     uint32 fldval;
   1631 
   1632     if (soc_feature(unit, soc_feature_ecn_dscp_map_mode)) {
   1633         if (ecn_map_mode == NULL) {
   1634             rv = BCM_E_PARAM;
   1635             return rv;
   1636         }
   1637         if ((ecn_map_mode->dscp < 0) || (ecn_map_mode->dscp > 63)) {
   1638             rv = BCM_E_PARAM;
   1639             return rv;
   1640         }
   1641 
   1642 
   1643         idx = ecn_map_mode->dscp;
   1644         sal_memset(&map_entry, 0, sizeof(map_entry));
   1645         BCM_IF_ERROR_RETURN(
   1646             soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, (void*)&map_entry));
   1647         fldval = soc_mem_field32_get(unit, mem, (void*)&map_entry, field);
   1648         ecn_map_mode->dscp_map_mode = fldval;
   1649 
   1650         rv = BCM_E_NONE;
   1651         return rv;
   1652     }
   1653 #endif /* BCM_TRIDENT2_SUPPORT */
   1654 
   1655     return rv;
   1656 }
   1657 
   1658 #endif /*INCLUDE_L3*/
   1659 
   1660 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP
   1661 void
   1662 _bcm_esw_ecn_sw_dump(int unit)
   1663 {
   1664 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(INCLUDE_L3)
   1665     if (SOC_IS_TOMAHAWKX(unit)) {
   1666         bcmi_xgs5_ecn_sw_dump(unit);
   1667     }
   1668 #endif
   1669 }
   1670 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */
   1671