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

mem.c (1190116B)


      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  * SOC Memory (Table) Utilities
      8  */
      9 
     10 #include <shared/bsl.h>
     11 
     12 #include <sal/core/libc.h>
     13 #include <soc/mem.h>
     14 #include <soc/cmic.h>
     15 #include <soc/error.h>
     16 #include <soc/register.h>
     17 #include <soc/drv.h>
     18 #include <soc/scache.h>
     19 #include <soc/enet.h>
     20 #include <soc/hash.h>
     21 #include <soc/l2x.h>
     22 #include <soc/l3x.h>
     23 #include <soc/lpm.h>
     24 #include <soc/vlan.h>
     25 #include <shared/fabric.h>
     26 #ifdef BCM_CMICM_SUPPORT
     27 #include <soc/cmicm.h>
     28 #endif
     29 #ifdef BCM_CMICX_SUPPORT
     30 #include <soc/fifodma.h>
     31 #endif
     32 #ifdef BCM_SBUSDMA_SUPPORT
     33 #include <soc/sbusdma.h>
     34 #endif
     35 #ifdef BCM_TRIUMPH3_SUPPORT
     36 #include <soc/ism.h>
     37 #include <soc/ism_hash.h>
     38 #include <soc/triumph3.h>
     39 #endif /* BCM_TRIUMPH3_SUPPORT */
     40 #if defined(BCM_HERCULES_SUPPORT)
     41 #include <soc/hercules.h>
     42 #endif
     43 #if defined(BCM_TRIUMPH_SUPPORT)
     44 #include <soc/triumph.h>
     45 #include <soc/er_tcam.h>
     46 #endif /* BCM_TRIUMPH_SUPPORT */
     47 #if defined(BCM_TRIUMPH2_SUPPORT)
     48 #include <soc/triumph2.h>
     49 #include <sal/core/dpc.h>
     50 #endif /* BCM_TRIUMPH_SUPPORT */
     51 #if defined(BCM_TRIDENT_SUPPORT)
     52 #include <soc/trident.h>
     53 #endif /* BCM_TRIDENT_SUPPORT */
     54 #if defined(BCM_TRIDENT2_SUPPORT)
     55 #include <soc/trident2.h>
     56 #endif /* BCM_TRIDENT2_SUPPORT */
     57 #if defined(BCM_KATANA_SUPPORT) && defined(BCM_CMICM_SUPPORT)
     58 #include <soc/katana.h>
     59 #endif /* BCM_KATANA_SUPPORT */
     60 #if defined(BCM_HURRICANE2_SUPPORT)
     61 #include <soc/hurricane2.h>
     62 #endif /* BCM_HURRICANE2_SUPPORT */
     63 #if defined(BCM_ENDURO_SUPPORT)
     64 #include <soc/enduro.h>
     65 #endif /* BCM_ENDURO_SUPPORT */
     66 #if defined(BCM_MONTEREY_SUPPORT)
     67 #include <soc/monterey.h>
     68 #endif /* BCM_APACHE_SUPPORT */
     69 #if defined(BCM_APACHE_SUPPORT)
     70 #include <soc/apache.h>
     71 #endif /* BCM_APACHE_SUPPORT */
     72 #if defined(BCM_TOMAHAWK_SUPPORT)
     73 #include <soc/tomahawk.h>
     74 #endif /* BCM_TOMAHAWK_SUPPORT */
     75 #if defined(BCM_TOMAHAWK3_SUPPORT)
     76 #include <soc/tomahawk3.h>
     77 #endif /* BCM_TOMAHAWK3_SUPPORT */
     78 #if defined(BCM_TRIDENT3_SUPPORT)
     79 #include <soc/trident3.h>
     80 #endif /* BCM_TRIDENT3_SUPPORT */
     81 #if defined(BCM_HELIX5_SUPPORT)
     82 #include <soc/helix5.h>
     83 #endif /* BCM_HELIX5_SUPPORT */
     84 #if defined(BCM_PETRA_SUPPORT)
     85 #include <soc/dpp/drv.h>
     86 #endif /* BCM_PETRA_SUPPORT */
     87 #if defined(BCM_DFE_SUPPORT)
     88 #include <soc/dfe/cmn/dfe_drv.h>
     89 #endif /* BCM_DFE_SUPPORT */
     90 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT)
     91 #include <soc/dcmn/dcmn_mem.h>
     92 #endif
     93 #ifdef BCM_PETRA_SUPPORT
     94 #include <soc/dpp/drv.h>
     95 #endif
     96 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT)
     97 #include <soc/sand/sand_mem.h>
     98 #endif
     99 #if defined(BCM_GREYHOUND_SUPPORT)
    100 #include <soc/greyhound.h>
    101 #endif /* BCM_GREYHOUND_SUPPORT */
    102 #if defined(BCM_KATANA2_SUPPORT)
    103 #include <soc/katana2.h>
    104 #endif /* BCM_KATANA2_SUPPORT */
    105 #if defined(BCM_SABER2_SUPPORT)
    106 #include <soc/saber2.h>
    107 #endif /* BCM_SABER2_SUPPORT */
    108 #if defined(BCM_HURRICANE3_SUPPORT)
    109 #include <soc/hurricane3.h>
    110 #endif /* BCM_HURRICANE3_SUPPORT */
    111 #if defined(BCM_GREYHOUND2_SUPPORT)
    112 #include <soc/greyhound2.h>
    113 #endif /* BCM_GREYHOUND2_SUPPORT */
    114 #include <soc/drv.h>
    115 
    116 #ifdef CRASH_RECOVERY_SUPPORT
    117 #include <soc/hwstate/hw_log.h>
    118 #include <soc/dcmn/dcmn_crash_recovery.h>
    119 #endif /* CRASH_RECOVERY_SUPPORT */
    120 
    121 #if defined(ALPM_ENABLE)
    122 #include <soc/alpm.h>
    123 #include <soc/esw/alpm_int.h>
    124 #endif
    125 
    126 #ifdef BCM_TRIDENT3_SUPPORT
    127 #include <soc/esw/flow_db.h>
    128 #endif
    129 
    130 #ifdef BCM_SAND_SUPPORT
    131 #include <soc/sand/sand_aux_access.h>
    132 #endif
    133 #ifdef BCM_DNX_SUPPORT
    134 #include <soc/dnx/legacy/drv.h>
    135 #endif
    136 #include <soc/dnxc/multithread_analyzer.h>
    137 
    138 #define LPM_INDEX_4K_ENTRIES 4096
    139 #define LPM_INDEX_2K_ENTRIES 2048
    140 #define LPM_INDEX_1K_ENTRIES 1024
    141 
    142 #ifdef BCM_WARM_BOOT_SUPPORT
    143 #define SOC_DEFIP_WARMBOOT_VERSION_1 SOC_SCACHE_VERSION(1,1)
    144 #define SOC_DEFIP_WARMBOOT_DEFAULT_VERSION SOC_DEFIP_WARMBOOT_VERSION_1
    145 #define SOC_OVERLAY_TCAM_WARMBOOT_VERSION_1 SOC_SCACHE_VERSION(1,1)
    146 #define SOC_OVERLAY_TCAM_WARMBOOT_DEFAULT_VERSION \
    147         SOC_OVERLAY_TCAM_WARMBOOT_VERSION_1
    148 #endif
    149 
    150 #ifdef USE_VALGRIND_CLIENT_REQUESTS
    151 #include "memcheck/memcheck.h"
    152 #endif /* USE_VALGRIND_CLIENT_REQUESTS */
    153 
    154 #define KATANA_L2X_VIEW_ARRAY_MAX_INDEX 4
    155 #define KATANA2_L2X_VIEW_ARRAY_MAX_INDEX 6
    156 #define TRIDENT2_L2X_VIEW_ARRAY_MAX_INDEX 10
    157 #define TRIDENT2PLUS_L2X_VIEW_ARRAY_MAX_INDEX 10
    158 #define TOMAHAWK_L2X_VIEW_ARRAY_MAX_INDEX 9
    159 
    160 #ifdef BCM_PETRA_SUPPORT
    161 /* read or write wide memory, supports ARAD only */
    162 int _soc_arad_mem_array_wide_access(int unit, uint32 flags, soc_mem_t mem, unsigned array_index, int copyno, int index, void *entry_data,
    163                    unsigned operation)  ;/* operation should be 1 for read and 0 for write */
    164 #endif
    165 
    166 /*
    167  * This function pointer must be initialized by the application.
    168  * For the standard SDK this is done in diag_shell(), and
    169  * the function will point to sal_config_set() by default.
    170  */
    171 int (*soc_mem_config_set)(char *name, char *value);
    172 
    173 #if defined(BCM_PETRA_SUPPORT)
    174 uint32 _soc_mem_entry_multicast_null[SOC_MAX_MEM_WORDS] = {0x7fffffff, 0};
    175 uint32 _soc_mem_entry_jer_mcdb_null[SOC_MAX_MEM_WORDS] = {0xffffffff, 3};
    176 uint32  _soc_mem_entry_llr_llvp_null[SOC_MAX_MEM_WORDS] = {0x90};
    177 #endif /* BCM_PETRA_SUPPORT */
    178 
    179 #if defined(BCM_ESW_SUPPORT) || \
    180     defined(BCM_SAND_SUPPORT) || defined(PORTMOD_SUPPORT)
    181 
    182 /* extra delay for quickturn */
    183 uint32 soc_mem_fifo_delay_value = 15 * MILLISECOND_USEC;
    184 
    185 #define _SOC_ENTRY_VALID_CHECK(unit, mem, valid_field)                      \
    186         if (SOC_MEM_FIELD_VALID(unit, mem, valid_field)) {                  \
    187             if (!soc_mem_field32_get(unit, mem, entry_data, valid_field)) { \
    188                 return;                                                     \
    189             }                                                               \
    190         }
    191 
    192 #define _SOC_ENTRY_PARITY_CLEAR(unit, mem, ecc_field)                       \
    193         if (SOC_MEM_FIELD_VALID(unit, mem, ecc_field)) {                    \
    194             soc_mem_field32_set(unit, mem, entry_data, ecc_field, 0);       \
    195             soc_mem_field32_set(unit, mem, entry_data_cache, ecc_field, 0); \
    196         }
    197 
    198 /*
    199  * Empty (null) table entries
    200  */
    201 uint32 _soc_mem_entry_null_zeroes[SOC_MAX_MEM_WORDS];
    202 /* First word f's, rest 0's */
    203 uint32 _soc_mem_entry_null_word0[SOC_MAX_MEM_WORDS] = { ~0, 0 };
    204 
    205 #define SOC_MEM_COMPARE_RETURN(a, b) {       \
    206         if ((a) < (b)) { return -1; }        \
    207         if ((a) > (b)) { return  1; }        \
    208 }
    209 #define CMIC_B0_DMA_READ_COMMAND   (0x7)
    210 #define CMIC_B0_DMA_WRITE_COMMAND  (0x9)
    211 
    212 #define _SOC_MEM_CHK_L2_MEM(mem) \
    213         (mem == L2Xm || mem == L2_ENTRY_1m || mem == L2_ENTRY_2m)
    214 #define _SOC_MEM_CHK_L3_MEM(mem) \
    215         (mem == L3_ENTRY_ONLYm || mem == L3_ENTRY_IPV4_UNICASTm || \
    216          mem == L3_ENTRY_IPV4_MULTICASTm || mem == L3_ENTRY_IPV6_UNICASTm || \
    217          mem == L3_ENTRY_IPV6_MULTICASTm || mem == L3_ENTRY_1m || \
    218          mem == L3_ENTRY_SINGLEm || mem == L3_ENTRY_DOUBLEm || mem == L3_ENTRY_QUADm || \
    219          mem == L3_ENTRY_2m || mem == L3_ENTRY_4m)
    220 
    221 #if defined(BCM_TOMAHAWK_SUPPORT)
    222 #define _SOC_MEM_CHK_FPEM_MEM(mem) \
    223         (mem == EXACT_MATCH_2m || \
    224          mem == EXACT_MATCH_2_PIPE0m || mem == EXACT_MATCH_2_PIPE1m || \
    225          mem == EXACT_MATCH_2_PIPE2m || mem == EXACT_MATCH_2_PIPE3m || \
    226          mem == EXACT_MATCH_4m || \
    227          mem == EXACT_MATCH_4_PIPE0m || mem == EXACT_MATCH_4_PIPE1m || \
    228          mem == EXACT_MATCH_4_PIPE2m || mem == EXACT_MATCH_4_PIPE3m)
    229 #define _SOC_MEM_CHK_IFP_TCAM(mem) \
    230         (mem == IFP_TCAMm || \
    231          mem == IFP_TCAM_PIPE0m || mem == IFP_TCAM_PIPE1m || \
    232          mem == IFP_TCAM_PIPE2m || mem == IFP_TCAM_PIPE3m)
    233 #define _SOC_MEM_CHK_IFP_TCAM_WIDE(mem) \
    234         (mem == IFP_TCAM_WIDEm || \
    235          mem == IFP_TCAM_WIDE_PIPE0m || mem == IFP_TCAM_WIDE_PIPE1m || \
    236          mem == IFP_TCAM_WIDE_PIPE2m || mem == IFP_TCAM_WIDE_PIPE3m)
    237 #endif /* BCM_TOMAHAWK_SUPPORT */
    238 
    239 #define _SOC_MEM_CHK_EGR_IP_TUNNEL(mem) \
    240         (mem == EGR_IP_TUNNELm || mem == EGR_IP_TUNNEL_MPLSm || \
    241          mem == EGR_IP_TUNNEL_IPV6m)
    242 #define _SOC_MEM_CHK_MPLS_MEM(mem) \
    243         (mem == MPLS_ENTRYm || mem == MPLS_ENTRY_1m || mem == MPLS_ENTRY_EXTDm)         
    244 #ifdef BCM_TRIDENT3_SUPPORT
    245 #define _SOC_MEM_CHK_VLAN_XLATE(mem) \
    246         (mem == VLAN_XLATE_1_SINGLEm || mem == VLAN_XLATE_1_DOUBLEm || \
    247          mem == VLAN_XLATE_2_SINGLEm || mem == VLAN_XLATE_2_DOUBLEm)
    248 #endif
    249 /* Macro to swap name to the mapped-to (actually-used) mem state name */
    250 #define _SOC_MEM_REUSE_MEM_STATE(unit, mem) {\
    251     switch(mem) {\
    252     case VLAN_XLATE_1m: mem = VLAN_XLATEm; break;\
    253     case EP_VLAN_XLATE_1m: mem = EGR_VLAN_XLATEm; break;\
    254     case MPLS_ENTRY_1m: mem = MPLS_ENTRYm; break;\
    255     case VLAN_MACm: \
    256         if (SOC_IS_TRX(unit) && !soc_feature(unit, soc_feature_ism_memory)) {\
    257             mem = VLAN_XLATEm;\
    258         }\
    259         break;\
    260     case EGR_VLANm: \
    261         if (SOC_IS_KATANA2(unit)) {\
    262             mem = VLAN_TABm;\
    263         }\
    264         break;\
    265     default: break;\
    266     }\
    267 }
    268 #define _SOC_MEM_SKIP_READING_MEM_TO_CACHE(unit, mem, skip) {\
    269     soc_mem_t skip_mem = mem;\
    270     skip = (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CACHABLE)? 0 : 1;\
    271     switch(mem) {\
    272         case RH_HGT_FLOWSETm:\
    273         case DLB_HGT_FLOWSETm:\
    274         case RH_HGT_FLOWSET_PIPE0m:\
    275         case RH_HGT_FLOWSET_PIPE1m:\
    276             if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit)) &&\
    277                 SOC_REG_IS_VALID(unit, ENHANCED_HASHING_CONTROLr)) {\
    278                 uint32 is_rh_hgt = 0;\
    279                 uint32 rval;\
    280                 READ_ENHANCED_HASHING_CONTROLr(unit, &rval);\
    281                 is_rh_hgt = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROLr, rval,\
    282                                 RH_HGT_ENABLEf);\
    283                 skip_mem = (is_rh_hgt == 1)? DLB_HGT_FLOWSETm : RH_HGT_FLOWSETm;\
    284                 skip = (skip_mem == mem)?1:0;\
    285             }\
    286             if (SOC_IS_TRIDENT3X(unit)  &&\
    287                 SOC_REG_IS_VALID(unit, ENHANCED_HASHING_CONTROL_2r)) {\
    288                 uint32 is_rh_dlb = 0;\
    289                 uint32 is_hgt_lag = 0;\
    290                 uint32 rval;\
    291                 READ_ENHANCED_HASHING_CONTROL_2r(unit, &rval);\
    292                 is_rh_dlb = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROL_2r, rval,\
    293                                 RH_DLB_SELECTIONf);\
    294                 is_hgt_lag = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROL_2r, rval,\
    295                                 HGT_LAG_FLOWSET_TABLE_CONFIGf);\
    296                 skip = (is_rh_dlb == 0)? 1 :((is_hgt_lag == 0)? 1 : 0);\
    297             }\
    298             break;\
    299        case RH_LAG_FLOWSETm:\
    300        case RH_LAG_FLOWSET_PIPE0m:\
    301        case RH_LAG_FLOWSET_PIPE1m:\
    302            if (SOC_IS_TRIDENT3X(unit)  &&\
    303                SOC_REG_IS_VALID(unit, ENHANCED_HASHING_CONTROL_2r)) {\
    304                uint32 is_rh_dlb = 0;\
    305                uint32 is_hgt_lag = 0;\
    306                uint32 rval;\
    307                READ_ENHANCED_HASHING_CONTROL_2r(unit, &rval);\
    308                is_rh_dlb = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROL_2r, rval,\
    309                                RH_DLB_SELECTIONf);\
    310                is_hgt_lag = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROL_2r, rval,\
    311                                HGT_LAG_FLOWSET_TABLE_CONFIGf);\
    312                skip = (is_rh_dlb == 0)? 1 :((is_hgt_lag == 1)? 1 : 0);\
    313             }\
    314             break;\
    315         case DLB_HGT_LAG_FLOWSETm:\
    316         case DLB_HGT_LAG_FLOWSET_PIPE0m:\
    317         case DLB_HGT_LAG_FLOWSET_PIPE1m:\
    318             if (SOC_IS_TRIDENT3X(unit)  &&\
    319                 SOC_REG_IS_VALID(unit, ENHANCED_HASHING_CONTROL_2r)) {\
    320                 uint32 is_rh_dlb = 0;\
    321                 uint32 rval;\
    322                 READ_ENHANCED_HASHING_CONTROL_2r(unit, &rval);\
    323                 is_rh_dlb = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROL_2r, rval,\
    324                                 RH_DLB_SELECTIONf);\
    325                 skip = (is_rh_dlb == 1)? 1 : 0;\
    326             }\
    327             break;\
    328         case RH_ECMP_FLOWSETm:\
    329         case RH_ECMP_FLOWSET_PIPE0m:\
    330         case RH_ECMP_FLOWSET_PIPE1m:\
    331             if (SOC_IS_TRIDENT3X(unit)  &&\
    332                 SOC_REG_IS_VALID(unit, ENHANCED_HASHING_CONTROLr)) {\
    333                 uint32 is_rh_dlb = 0;\
    334                 uint32 rval;\
    335                 READ_ENHANCED_HASHING_CONTROLr(unit, &rval);\
    336                 is_rh_dlb = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROLr, rval,\
    337                                 RH_DLB_SELECTIONf);\
    338                 skip = (is_rh_dlb == 1)? 0 : 1;\
    339             }\
    340             break;\
    341         case DLB_ECMP_FLOWSETm:\
    342         case DLB_ECMP_FLOWSET_PIPE0m:\
    343         case DLB_ECMP_FLOWSET_PIPE1m:\
    344         case DLB_ECMP_FLOWSET_MEMBER_PIPE0m:\
    345         case DLB_ECMP_FLOWSET_MEMBER_PIPE1m:\
    346         case DLB_ECMP_FLOWSET_MEMBERm:\
    347             if (SOC_IS_TRIDENT3X(unit)  &&\
    348                 SOC_REG_IS_VALID(unit, ENHANCED_HASHING_CONTROLr)) {\
    349                 uint32 is_rh_dlb = 0;\
    350                 uint32 rval;\
    351                 READ_ENHANCED_HASHING_CONTROLr(unit, &rval);\
    352                 is_rh_dlb = soc_reg_field_get(unit, ENHANCED_HASHING_CONTROLr, rval,\
    353                                 RH_DLB_SELECTIONf);\
    354                 skip = (is_rh_dlb == 1)? 1 : 0;\
    355             }\
    356             break;\
    357         default:\
    358             break;\
    359     }\
    360 }
    361 
    362 #ifdef BROADCOM_DEBUG
    363 static uint32 _soc_dma_debug_enable[SOC_MAX_NUM_DEVICES] = {0};
    364 static uint32 _soc_dma_debug_op[SOC_MAX_NUM_DEVICES] = {0};
    365 #endif /* BROADCOM_DEBUG */
    366 
    367 /* Structure for hash bank info stored during each hash move */
    368 typedef struct _soc_hash_bank_info_s {
    369     int         num_banks;
    370     int         bank_nums[11];
    371     int         banks;
    372     uint32      numb;
    373 } _soc_hash_bank_info_t;
    374 
    375 #if defined(BCM_GREYHOUND2_SUPPORT)
    376 STATIC int soc_mem_gh2_l2_sw_lookup(
    377     int unit,
    378     soc_mem_t mem,
    379     int copyno,
    380     int32 banks,
    381     void *key,
    382     void *result,
    383     int *index_ptr);
    384 #endif /* BCM_GREYHOUND2_SUPPORT */
    385 
    386 
    387 
    388 #ifdef BCM_SAND_SUPPORT
    389 STATIC int _soc_mem_array_wide_read(
    390     int unit,
    391     uint32 flags,
    392     soc_mem_t mem,
    393     unsigned array_index,
    394     int copyno,
    395     int index,
    396     void *entry_data)
    397 {
    398     int rv = SOC_E_UNAVAIL;
    399 
    400 #ifdef BCM_PETRA_SUPPORT
    401     if (SOC_IS_DPP(unit))
    402     {
    403         if (SOC_IS_ARADPLUS_AND_BELOW(unit))
    404         {
    405             SOC_DPP_ALLOW_WARMBOOT_WRITE(_soc_arad_mem_array_wide_access(unit, flags, mem, array_index, copyno, index, entry_data, 1), rv);
    406             return rv;
    407         }
    408         else
    409         {
    410             SOC_DPP_ALLOW_WARMBOOT_WRITE(dcmn_mem_array_wide_access(unit, flags, mem, array_index, copyno, index, entry_data, 1), rv);
    411             return rv;
    412         }
    413     }
    414 #endif
    415 
    416 #ifdef BCM_DFE_SUPPORT
    417     if(SOC_IS_FE3200(unit))
    418     {
    419         rv = dcmn_mem_array_wide_access(unit, flags, mem, array_index, copyno, index, entry_data, 1);
    420         return rv;
    421     }
    422 #endif
    423 
    424 #ifdef BCM_DNX_SUPPORT
    425 if (SOC_IS_DNX(unit))
    426     {
    427         SOC_DNX_ALLOW_WARMBOOT_WRITE(sand_mem_array_wide_access(unit, flags, mem, array_index, copyno, index, entry_data, 1), rv);
    428         return rv;
    429     }
    430 #endif
    431 
    432 #ifdef BCM_DNXF_SUPPORT
    433     if (SOC_IS_DNXF(unit))
    434     {
    435         rv = sand_mem_array_wide_access(unit, flags, mem, array_index, copyno, index, entry_data, 1);
    436         return rv;
    437     }
    438 #endif
    439 
    440 
    441     return rv;
    442 }
    443 
    444 
    445 
    446 STATIC int _soc_mem_array_wide_write(
    447     int unit,
    448     uint32 flags,
    449     soc_mem_t mem,
    450     unsigned array_index,
    451     int copyno,
    452     int index,
    453     void *entry_data)
    454 {
    455     int     rv = SOC_E_UNAVAIL;;
    456 
    457 #ifdef BCM_PETRA_SUPPORT
    458     if(SOC_IS_DPP(unit))
    459     {
    460         if (SOC_IS_ARADPLUS_AND_BELOW(unit))
    461         {
    462             SOC_DPP_ALLOW_WARMBOOT_WRITE(_soc_arad_mem_array_wide_access(unit, flags, mem, array_index, copyno, index, entry_data, 0), rv);
    463             return rv;
    464         }
    465         else
    466         {
    467             SOC_DPP_ALLOW_WARMBOOT_WRITE(dcmn_mem_array_wide_access(unit, flags, mem, array_index, copyno, index, entry_data, 0), rv);
    468             return rv;
    469         }
    470     }
    471 #endif
    472 
    473 #ifdef BCM_DFE_SUPPORT
    474     if (SOC_IS_FE3200(unit))
    475     {
    476         rv = dcmn_mem_array_wide_access(unit, flags, mem, array_index, copyno, index, entry_data, 0);
    477         return rv;
    478     }
    479 #endif
    480 
    481 #ifdef BCM_DNX_SUPPORT
    482 if (SOC_IS_DNX(unit))
    483     {
    484         SOC_DNX_ALLOW_WARMBOOT_WRITE(sand_mem_array_wide_access(unit, flags, mem, array_index, copyno, index, entry_data, 0), rv);
    485         return rv;
    486     }
    487 #endif
    488 
    489 #ifdef BCM_DNXF_SUPPORT
    490     if (SOC_IS_DNXF(unit))
    491     {
    492         rv = sand_mem_array_wide_access(unit, flags, mem, array_index, copyno, index, entry_data, 0);
    493         return rv;
    494     }
    495 #endif
    496 
    497     return rv;
    498 }
    499 
    500 #endif
    501 
    502 
    503 
    504 #ifdef BCM_TRIDENT3_SUPPORT
    505 /*
    506  * Function:   soc_mem_view_index_max
    507  * Purpose:    Find the max index (address range) in this memory view
    508  * Parameters:
    509  *       unit         - (IN) SOC unit number.
    510  *       mem          - (IN) Memory view
    511  * Returns:
    512  *       Returns the max index of this memory view
    513  * Note:
    514  *      Parameter mem_view must be valid before calling this function
    515  */
    516 int soc_mem_view_index_max(int unit, soc_mem_t mem_view)
    517 {
    518     soc_mem_t phy_mem = 0;
    519     int index;
    520 
    521     if (soc_feature(unit, soc_feature_flex_flow) && SOC_MEM_IS_VIEW(unit, mem_view)) {
    522         (void)soc_mem_view_phy_mem_get(unit, mem_view, &phy_mem);
    523         index = (SOC_PERSIST(unit) ? SOP_MEM_STATE(unit, phy_mem).index_max : SOC_MEM_INFO(unit, phy_mem).index_max);
    524     } else {
    525         index = (SOC_PERSIST(unit) ? SOP_MEM_STATE(unit, mem_view).index_max : SOC_MEM_INFO(unit, mem_view).index_max);
    526     }
    527     return index;
    528 }
    529 
    530 /*
    531  * Function:   soc_mem_view_index_min
    532  * Purpose:    Find the min index (address range) in this memory view
    533  * Parameters:
    534  *       unit         - (IN) SOC unit number.
    535  *       mem          - (IN) Memory view
    536  * Returns:
    537  *       Returns the min index of this memory view
    538  * Note:
    539  *      Parameter mem_view must be valid before calling this function
    540  */
    541 int soc_mem_view_index_min(int unit, soc_mem_t mem_view)
    542 {
    543     soc_mem_t phy_mem = 0;
    544     int index;
    545 
    546     if (soc_feature(unit, soc_feature_flex_flow) && SOC_MEM_IS_VIEW(unit, mem_view)) {
    547         (void)soc_mem_view_phy_mem_get(unit, mem_view, &phy_mem);
    548         index = SOC_MEM_INFO(unit, phy_mem).index_min;
    549     } else {
    550         index = SOC_MEM_INFO(unit, mem_view).index_min;
    551     }
    552     return index;
    553 }
    554 
    555 /*
    556  * Function:   soc_mem_view_index_count
    557  * Purpose:    Count the number of indexes (address range) in this memory view
    558  * Parameters:
    559  *       unit         - (IN) SOC unit number.
    560  *       mem          - (IN) Memory view
    561  * Returns:
    562  *       Count of number of memory indexes
    563  * Note:
    564  *      Parameter mem_view must be valid before calling this function
    565  */
    566 int soc_mem_view_index_count(int unit, soc_mem_t mem_view)
    567 {
    568     soc_mem_t phy_mem = 0;
    569     int count;
    570 
    571     if (soc_feature(unit, soc_feature_flex_flow) && SOC_MEM_IS_VIEW(unit, mem_view)) {
    572         (void)soc_mem_view_phy_mem_get(unit, mem_view, &phy_mem);
    573         count = (soc_mem_index_max(unit, phy_mem) - soc_mem_index_min(unit, phy_mem) + 1);
    574     } else {
    575         count = (soc_mem_index_max(unit, mem_view) - soc_mem_index_min(unit, mem_view) + 1);
    576     }
    577     return count;
    578 }
    579 
    580 /*
    581  * Function:
    582  *    soc_mem_view_entry_dump_common
    583  * Purpose:
    584  *    Debug routine to dump a formatted table entry for memory views
    585  *
    586  *    Note:  Prefix != NULL : Dump chg command
    587  *           Prefix == NULL : Dump     command
    588  *             (Actually should pass dump_chg flag but keeping for simplicity)
    589  */
    590 STATIC void
    591 _soc_mem_view_entry_dump_common(int unit, soc_mem_t mem_view_id, void *buf, char *prefix, int vertical, uint32 bsl_flags)
    592 {
    593     int i;
    594     int rv;
    595     uint32 field_id[100];
    596     uint32 cnt;
    597     int field_type;
    598     char dummy[]="";
    599     char *mem_prefix=dummy;
    600     int  first_print_flag=0;
    601 
    602 #if !defined(SOC_NO_NAMES)
    603     soc_flow_db_mem_view_field_info_t ff_info;
    604     char *field_name;
    605     uint32 *fval;
    606     uint32 *nfval;
    607     char *tmp;
    608     uint32 *buf_ptr;
    609     int alloc_size;
    610 #endif
    611 
    612 
    613     if (prefix != NULL) {
    614         mem_prefix = prefix;
    615     }
    616 
    617 #if !defined(SOC_NO_NAMES)
    618     alloc_size = (2*SOC_MAX_MEM_FIELD_WORDS) * sizeof(uint32) +
    619                  (SOC_MAX_MEM_FIELD_WORDS * 8) + 3;
    620     buf_ptr = sal_alloc(alloc_size, "Temp. buffer for soc mem dump");
    621     sal_memset((void *)buf_ptr,0,alloc_size);
    622     fval  = buf_ptr;
    623     nfval = buf_ptr + SOC_MAX_MEM_FIELD_WORDS;
    624     tmp   = (char *)(buf_ptr + 2 * SOC_MAX_MEM_FIELD_WORDS);
    625 #endif
    626 
    627     for (field_type = SOC_FLOW_DB_FIELD_TYPE_CONTROL; 
    628             field_type < SOC_FLOW_DB_FIELD_TYPE_MAX; field_type++) {
    629         rv = soc_flow_db_mem_view_field_list_get(unit, mem_view_id, field_type, 100, field_id, &cnt);
    630         if (SOC_SUCCESS(rv)) {
    631             for (i = 0; i < cnt; i++) {
    632 #if !defined(SOC_NO_NAMES)
    633                 sal_memset(fval, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
    634                 soc_mem_field_get(unit, mem_view_id, buf, field_id[i], fval);
    635 
    636                 if (mem_prefix == prefix) {
    637                     if (sal_memcmp(fval, nfval, SOC_MAX_MEM_FIELD_WORDS *
    638                                 sizeof (uint32)) == 0) {
    639                         continue;
    640                     }
    641                 }
    642                 (void) soc_flow_db_mem_view_field_info_get(unit, mem_view_id,
    643                         field_id[i], &ff_info);
    644                 _shr_format_long_integer(tmp, fval, BITS2BYTES(ff_info.width));
    645                 if (first_print_flag == 0) {
    646                     BSL_LOG(bsl_flags, (BSL_META_U(unit, "%s%s"), mem_prefix,  "<"));
    647                     first_print_flag = 1; 
    648                 }
    649                 if (field_type == SOC_FLOW_DB_FIELD_TYPE_LOGICAL_KEY ||
    650                     field_type == SOC_FLOW_DB_FIELD_TYPE_LOGICAL_POLICY_DATA ||
    651                     field_type == SOC_FLOW_DB_FIELD_TYPE_DATA_FRAGMENT) {
    652                     (void) soc_flow_db_mem_view_field_name_get(unit, mem_view_id,
    653                               field_id[i], &field_name);
    654                 }
    655                 else {
    656                     field_name = soc_fieldnames[field_id[i]];
    657                 }
    658                 if (vertical) {
    659                     BSL_LOG(bsl_flags, (BSL_META_U(unit,
    660                                     "\n\t%30s: %s"), field_name,
    661                                 tmp));
    662                 } else {
    663                     BSL_LOG(bsl_flags, (BSL_META_U(unit,
    664                                     "%s=%s%s"), field_name,
    665                                 tmp, ","));
    666                 }
    667 #endif
    668             }
    669         }
    670     }
    671 #if !defined(SOC_NO_NAMES)
    672     sal_free(buf_ptr);
    673 #endif
    674 
    675     if (first_print_flag == 1) {
    676         BSL_LOG(bsl_flags, (BSL_META_U(unit,
    677                             "%s\n"), vertical ? "" : ">"));
    678     }
    679 }
    680 #endif
    681 
    682 #if defined BCM_DNX_SUPPORT && defined DNX_EMULATION_1_CORE
    683 /* For JR2 emulator, not all memory exist */
    684 STATIC int _soc_jr2_is_2nd_core(int unit, soc_mem_t mem, int copyno)
    685 {
    686     uint32 block_type = SOC_BLOCK_TYPE(unit, SOC_MEM_BLOCK_ANY(unit, mem));
    687 
    688     if (copyno < 0) {
    689         return 0;
    690     }
    691 
    692     switch(block_type) {
    693 #ifdef JR2_REMOVE_ACCESS_TO_UNSUPPORTED_BLOCKS
    694         case SOC_BLK_FSRD:
    695             if (copyno > 2) {
    696                 return 1;
    697             }
    698             break;
    699         case SOC_BLK_FMAC:
    700             if (copyno > 5) {
    701                 return 1;
    702             }
    703             break;
    704         case SOC_BLK_CDU:
    705             if (copyno > 4) {
    706                 return 1;
    707             }
    708             break;
    709         case SOC_BLK_CDMAC:
    710             if (copyno > 11) {
    711                 return 1;
    712             }
    713             break;
    714         case SOC_BLK_CDPORT:
    715             if (copyno > 5) {
    716                 return 1;
    717             }
    718             break;
    719         case SOC_BLK_DDHA:
    720         case SOC_BLK_DDHB:
    721         case SOC_BLK_MDB:
    722 #endif /* JR2_REMOVE_ACCESS_TO_UNSUPPORTED_BLOCKS */
    723         case SOC_BLK_KAPS:
    724         case SOC_BLK_IPPA:
    725         case SOC_BLK_IPPB:
    726         case SOC_BLK_IPPC:
    727         case SOC_BLK_IPPD:
    728         case SOC_BLK_IPPE:
    729         case SOC_BLK_IPPF:
    730         case SOC_BLK_CDUM:
    731         case SOC_BLK_MACT:
    732         case SOC_BLK_TCAM:
    733         case SOC_BLK_IQM:
    734         case SOC_BLK_ITPPD:
    735         case SOC_BLK_ITPP:
    736         case SOC_BLK_ETPPA:
    737         case SOC_BLK_ETPPB:
    738         case SOC_BLK_ETPPC:
    739         case SOC_BLK_ERPP:
    740         case SOC_BLK_EDB:
    741         case SOC_BLK_DQM:
    742         case SOC_BLK_CRPS:
    743         case SOC_BLK_MRPS:
    744         case SOC_BLK_EGQ:
    745         case SOC_BLK_EPNI:
    746         case SOC_BLK_EPRE:
    747         case SOC_BLK_ECGM:
    748         case SOC_BLK_CGM:
    749         case SOC_BLK_FDR:
    750         case SOC_BLK_IDB:
    751         case SOC_BLK_MCP:
    752         case SOC_BLK_OCB:
    753         case SOC_BLK_ILE:
    754         case SOC_BLK_SCH:
    755         case SOC_BLK_IPT:
    756         case SOC_BLK_IPS:
    757         case SOC_BLK_IRE:
    758         case SOC_BLK_NMG:
    759         case SOC_BLK_EPS:
    760         case SOC_BLK_FQP:
    761         case SOC_BLK_RQP:
    762         case SOC_BLK_PQP:
    763         case SOC_BLK_SQM:
    764         case SOC_BLK_SPB:
    765         case SOC_BLK_DDP:
    766         case SOC_BLK_PDM:
    767         case SOC_BLK_BDM:
    768         case SOC_BLK_SIF:
    769             if (SOC_BLOCK_NUMBER(unit, copyno) > 0) {
    770                 return 1;
    771             }
    772             break;
    773         case SOC_BLK_PEM:
    774             if (SOC_BLOCK_NUMBER(unit, copyno) >= 4) {
    775                 return 1;
    776             }
    777             break;
    778         default:
    779             break;
    780     }
    781 
    782     return 0;
    783 }
    784 #endif /* defined BCM_DNX_SUPPORT && defined DNX_EMULATION_1_CORE */
    785 
    786 /* Check a mem has mapped-to (actually-used) mem state name or not */
    787 int soc_mem_is_mapped_mem(int unit, soc_mem_t mem) 
    788 {
    789     soc_mem_t mapped_mem = mem;
    790     
    791     _SOC_MEM_REUSE_MEM_STATE(unit, mapped_mem);
    792 
    793     if(mapped_mem == mem) {
    794         return FALSE;
    795     } else {
    796         return TRUE;    
    797     }
    798 
    799 }
    800 /* Two memory share same physical memory space, but they can't exist at the same time */
    801 int soc_mem_is_shared_mem(int unit, soc_mem_t mem) 
    802 {
    803     int skip = 0;
    804 
    805     switch(mem) {
    806         case DLB_HGT_FLOWSETm:
    807         case DLB_HGT_FLOWSET_Xm:
    808         case DLB_HGT_FLOWSET_Ym:
    809             mem = DLB_HGT_FLOWSETm;
    810             break;
    811         case DLB_ECMP_FLOWSET_MEMBERm:
    812         case DLB_ECMP_FLOWSET_MEMBER_PIPE0m:
    813         case DLB_ECMP_FLOWSET_MEMBER_PIPE1m:
    814             mem = DLB_ECMP_FLOWSET_MEMBERm;
    815             break;
    816         default:
    817             break;
    818     }
    819     _SOC_MEM_SKIP_READING_MEM_TO_CACHE(unit, mem, skip);
    820     if (skip == 1) {
    821         return TRUE;
    822     } else {
    823         return FALSE;
    824     }
    825 }
    826 
    827 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT
    828 int
    829 soc_mem_is_cache_only(int unit, soc_mem_t mem)
    830 {
    831 
    832     if (soc_feature(unit, soc_feature_l3_ecmp_protected_access)) {
    833         switch (mem) {
    834             case L3_ECMPm:
    835             case INITIAL_L3_ECMPm:
    836             case L3_ECMP_COUNTm:
    837             case INITIAL_L3_ECMP_GROUPm:
    838                 return TRUE;
    839             default:
    840                 return FALSE;
    841         }
    842     }
    843 
    844     return FALSE;
    845 }
    846 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */
    847 
    848 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT)
    849 /* get the soc broadcast block from a block type */
    850 int soc_broadcast_block_get_from_type (int unit, int block_type) {
    851     switch (block_type) {
    852     case SOC_BLK_EGQ:
    853         return SOC_INFO(unit).brdc_egq_block;
    854     case SOC_BLK_IHB:
    855         return SOC_INFO(unit).brdc_ihb_block;
    856     case SOC_BLK_IHP:
    857         return SOC_INFO(unit).brdc_ihp_block;
    858     case SOC_BLK_IPS:
    859         return SOC_INFO(unit).brdc_ips_block;
    860     case SOC_BLK_IQM:
    861         return SOC_INFO(unit).brdc_iqm_block;
    862     case SOC_BLK_CGM:
    863         return SOC_INFO(unit).brdc_cgm_block;
    864     case SOC_BLK_SCH:
    865         return SOC_INFO(unit).brdc_sch_block;
    866     case SOC_BLK_EPNI:
    867         return SOC_INFO(unit).brdc_epni_block;
    868     case SOC_BLK_MRPS:
    869         return SOC_INFO(unit).brdc_mrps_block;
    870     case SOC_BLK_MTRPS_EM:
    871         return SOC_INFO(unit).brdc_mtrps_em_block;
    872     case SOC_BLK_IPSEC_SPU_WRAPPER_TOP:
    873         return SOC_INFO(unit).brdc_ipsec_spu_wrapper_top_block;
    874     case SOC_BLK_KAPS_BBS:
    875         return SOC_INFO(unit).brdc_kaps_bbs_block;
    876 
    877     default:
    878         return 0;
    879     }
    880 }
    881 
    882 /* get the soc broadcast block from of a memory */
    883 int soc_mem_broadcast_block_get(int unit, soc_mem_t mem){
    884     switch (SOC_BLOCK_TYPE(unit, SOC_MEM_BLOCK_ANY(unit, mem))) {
    885         case SOC_BLK_EGQ:
    886             return SOC_INFO(unit).brdc_egq_block;
    887         case SOC_BLK_IHB:
    888             return SOC_INFO(unit).brdc_ihb_block;
    889         case SOC_BLK_IHP:
    890             return SOC_INFO(unit).brdc_ihp_block;
    891         case SOC_BLK_IPS:
    892             return SOC_INFO(unit).brdc_ips_block;
    893         case SOC_BLK_IQM:
    894             return SOC_INFO(unit).brdc_iqm_block;
    895         case SOC_BLK_CGM:
    896             return SOC_INFO(unit).brdc_cgm_block;
    897         case SOC_BLK_SCH:
    898             return SOC_INFO(unit).brdc_sch_block;
    899         case SOC_BLK_EPNI:
    900             return SOC_INFO(unit).brdc_epni_block;
    901         case SOC_BLK_MRPS:
    902             return SOC_INFO(unit).brdc_mrps_block;
    903         case SOC_BLK_MTRPS_EM:
    904             return SOC_INFO(unit).brdc_mtrps_em_block;
    905         case SOC_BLK_IPSEC_SPU_WRAPPER_TOP:
    906             return SOC_INFO(unit).brdc_ipsec_spu_wrapper_top_block;
    907         case SOC_BLK_KAPS_BBS:
    908             return SOC_INFO(unit).brdc_kaps_bbs_block;
    909 
    910         default:
    911             return 0;
    912     }
    913 }
    914 #endif /* BCM_PETRA_SUPPORT */
    915 
    916 /* Routine to check if this is the mem whose state is being (mapped-to) actually-used by others */
    917 int _SOC_MEM_IS_REUSED_MEM(int unit, soc_mem_t mem) {\
    918     switch(mem) {\
    919     case EGR_VLAN_XLATEm: return TRUE;\
    920     case MPLS_ENTRYm: return TRUE;\
    921     case VLAN_XLATEm:\
    922         if (SOC_IS_TRX(unit)) {\
    923             return TRUE;\
    924         }\
    925         break;\
    926     case VLAN_TABm:\
    927         if (SOC_IS_KATANA2(unit)) {\
    928             return TRUE;\
    929         }\
    930         break;\
    931     case RH_HGT_FLOWSETm:\
    932         if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit))) {\
    933            return TRUE;\
    934         }\
    935         break;\
    936     default: break;\
    937     }\
    938     return FALSE;\
    939 }
    940 
    941 /* Handle reverse mem state mapping updates - one to one or one to many */
    942 
    943 /* DLB_HGT_FLOWSETm and RH_HGT_FLOWSETm share the same physical memory table,
    944 if we write physical memory table according to format of DLB_HGT_FLOWSETm, and read the physical
    945 memory according to format of RH_HGT_FLOWSETm, there will be a lot of SER error!*/
    946 #define _SOC_MEM_SYNC_MAPPED_MEM_STATES(unit, mem) {\
    947     switch(mem) {\
    948     case EGR_VLAN_XLATEm: \
    949         SOC_MEM_STATE(unit, EP_VLAN_XLATE_1m).cache[blk] = cache;\
    950         SOC_MEM_STATE(unit, EP_VLAN_XLATE_1m).vmap[blk] = vmap;\
    951         break;\
    952     case MPLS_ENTRYm: \
    953         SOC_MEM_STATE(unit, MPLS_ENTRY_1m).cache[blk] = cache;\
    954         SOC_MEM_STATE(unit, MPLS_ENTRY_1m).vmap[blk] = vmap;\
    955         break;\
    956     case VLAN_XLATEm: \
    957         if (SOC_IS_TRX(unit)) {\
    958             if (soc_feature(unit, soc_feature_ism_memory)) {\
    959                 SOC_MEM_STATE(unit, VLAN_XLATE_1m).cache[blk] = cache;\
    960                 SOC_MEM_STATE(unit, VLAN_XLATE_1m).vmap[blk] = vmap;\
    961             } else {\
    962                 SOC_MEM_STATE(unit, VLAN_MACm).cache[blk] = cache;\
    963                 SOC_MEM_STATE(unit, VLAN_MACm).vmap[blk] = vmap;\
    964             }\
    965             break;\
    966         }\
    967     case VLAN_TABm: \
    968         if (SOC_IS_KATANA2(unit)) { \
    969             int blk_new; \
    970             SOC_MEM_BLOCK_ITER(unit, EGR_VLANm, blk_new) {\
    971                 SOC_MEM_STATE(unit, EGR_VLANm).cache[blk_new] = cache;\
    972                 SOC_MEM_STATE(unit, EGR_VLANm).vmap[blk_new] = vmap;\
    973                 break;\
    974             }\
    975         }\
    976         break;\
    977     default: break;\
    978     }\
    979 }
    980 #ifdef BCM_TRIUMPH3_SUPPORT
    981 #define _SOC_MEM_REPLACE_MEM(unit, mem) {\
    982     if (soc_feature(unit, soc_feature_ism_memory)) {\
    983         switch(mem) {\
    984         case VLAN_XLATE_1m: mem = VLAN_XLATEm; break;\
    985         case EP_VLAN_XLATE_1m: mem = EGR_VLAN_XLATEm; break;\
    986         case MPLS_ENTRY_1m: mem = MPLS_ENTRYm; break;\
    987         default: break;\
    988         }\
    989     }\
    990 }
    991 #else
    992 #define _SOC_MEM_REPLACE_MEM(unit, mem)
    993 #endif /* BCM_TRIUMPH3_SUPPORT */
    994 
    995 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_SAND_SUPPORT)
    996 soc_mem_t petra_mem_alias_to_orig(int unit, soc_mem_t mem)
    997 {
    998     soc_mem_t   alias_mem;
    999 
   1000     alias_mem = SOC_MEM_IS_VALID(unit, SOC_MEM_ALIAS_MAP(unit,mem)) ? SOC_MEM_ALIAS_MAP(unit,mem) : mem;
   1001 
   1002     /* special memory with same physical address but not be marked alias */
   1003     switch (SOC_INFO(unit).chip_type)
   1004     {
   1005         case SOC_INFO_CHIP_TYPE_QUX:
   1006         {
   1007             switch (mem)
   1008             {
   1009                 case IHB_FEC_SUPER_ENTRYm:
   1010                     alias_mem = IHB_FEC_ENTRYm;
   1011                     break;
   1012                 case PPDB_B_LARGE_EM_FORMAT_0_TYPE_0m:
   1013                     alias_mem = PPDB_B_LARGE_EM_PORT_MINE_TABLE_LAG_PORTm;
   1014                     break;
   1015                 case EPNI_PP_PCTm:
   1016                     alias_mem = EPNI_PACKETPROCESSING_PORT_CONFIGURATION_TABLEm;
   1017                     break;
   1018 
   1019                 default:
   1020                     break;
   1021             }
   1022             break;
   1023         }
   1024 
   1025         case SOC_INFO_CHIP_TYPE_QAX:
   1026         {
   1027             switch (mem)
   1028             {
   1029                 case IHB_FEC_SUPER_ENTRYm:
   1030                     alias_mem = IHB_FEC_ENTRYm;
   1031                     break;
   1032                 case PPDB_B_LARGE_EM_FORMAT_0_TYPE_0m:
   1033                     alias_mem = PPDB_B_LARGE_EM_PORT_MINE_TABLE_LAG_PORTm;
   1034                     break;
   1035                 default:
   1036                     break;
   1037             }
   1038             break;
   1039         }
   1040 
   1041         case SOC_INFO_CHIP_TYPE_QMX:
   1042         {
   1043             switch (mem)
   1044             {
   1045                 case MRPS_MCDA_PRFCFG_SHARING_DISm:
   1046                 case MRPS_MCDA_PRFCFG_SHARING_ENm:
   1047                     alias_mem = MRPS_MCDA_PRFCFG_1m;
   1048                     break;
   1049                 case PPDB_B_LARGE_EM_FORMAT_0_TYPE_0m:
   1050                     alias_mem = PPDB_B_LARGE_EM_PORT_MINE_TABLE_LAG_PORTm;
   1051                     break;
   1052                 default:
   1053                     break;
   1054             }
   1055             break;
   1056         }
   1057 
   1058         case SOC_INFO_CHIP_TYPE_JERICHO:
   1059         {
   1060             switch (mem)
   1061             {
   1062                 case MRPS_MCDA_PRFCFG_SHARING_DISm:
   1063                 case MRPS_MCDA_PRFCFG_SHARING_ENm:
   1064                     alias_mem = MRPS_MCDA_PRFCFG_1m;
   1065                     break;
   1066                 case PPDB_B_LARGE_EM_FORMAT_0_TYPE_0m:
   1067                     alias_mem = PPDB_B_LARGE_EM_PORT_MINE_TABLE_LAG_PORTm;
   1068                     break;
   1069                 default:
   1070                     break;
   1071             }
   1072             break;
   1073         }
   1074 
   1075         case SOC_INFO_CHIP_TYPE_JERICHO_PLUS:
   1076         {
   1077             switch (mem)
   1078             {
   1079                 case PPDB_B_LIF_TABLE_AC_2_EEIm:
   1080                 case PPDB_B_LIF_TABLE_AC_2_OUT_LIFm:
   1081                 case PPDB_B_LIF_TABLE_AC_MPm:
   1082                 case PPDB_B_LIF_TABLE_IP_TTm:
   1083                 case PPDB_B_LIF_TABLE_ISID_MPm:
   1084                 case PPDB_B_LIF_TABLE_ISID_P2Pm:
   1085                 case PPDB_B_LIF_TABLE_LABEL_PROTOCOL_OR_LSPm:
   1086                 case PPDB_B_LIF_TABLE_LABEL_PWE_MPm:
   1087                 case PPDB_B_LIF_TABLE_LABEL_PWE_P2Pm:
   1088                 case PPDB_B_LIF_TABLE_TRILLm:
   1089                 case PPDB_B_LIF_TABLE_DOUBLE_DATAm:
   1090                     alias_mem = PPDB_B_LIF_TABLEm;
   1091                     break;
   1092                 case PPDB_B_LARGE_EM_FORMAT_0_TYPE_0m:
   1093                     alias_mem = PPDB_B_LARGE_EM_PORT_MINE_TABLE_LAG_PORTm;
   1094                     break;
   1095                 case MRPS_MCDA_PRFCFG_SHARING_DISm:
   1096                 case MRPS_MCDA_PRFCFG_SHARING_ENm:
   1097                     alias_mem = MRPS_MCDA_PRFCFG_1m;
   1098                     break;
   1099                 default:
   1100                     break;
   1101             }
   1102             break;
   1103         }
   1104 
   1105         default:
   1106             break;
   1107     }
   1108 
   1109     return alias_mem;
   1110 }
   1111 #endif
   1112 
   1113 #ifdef BCM_ESW_SUPPORT
   1114 #define HASH_MEM_OP_RETRY_COUNT 5
   1115 #endif
   1116 
   1117 int
   1118 _soc_mem_cmp_word0(int unit, void *ent_a, void *ent_b)
   1119 {
   1120     COMPILER_REFERENCE(unit);
   1121 
   1122     /*
   1123      * Good for l3_def_ip_entry_t and l3_l3_entry_t.
   1124      * The first uint32 (IP address) is the sort key.
   1125      */
   1126 
   1127     SOC_MEM_COMPARE_RETURN(*(uint32 *)ent_a, *(uint32 *)ent_b);
   1128 
   1129     return 0;
   1130 }
   1131 
   1132 int
   1133 _soc_mem_cmp_undef(int unit, void *ent_a, void *ent_b)
   1134 {
   1135     COMPILER_REFERENCE(ent_a);
   1136     COMPILER_REFERENCE(ent_b);
   1137 
   1138     LOG_CLI((BSL_META_U(unit,
   1139                         "soc_mem_cmp: cannot compare entries of this type\n")));
   1140 
   1141     assert(0);
   1142 
   1143     return 0;
   1144 }
   1145 
   1146 int
   1147 _soc_mem_cmp_subport_id_to_sgpp_map(int unit, void *ent_a, void *ent_b)
   1148 {
   1149     uint32 val_a, val_b;
   1150 
   1151     val_a = soc_mem_field32_get(unit, SUBPORT_ID_TO_SGPP_MAPm, ent_a, SUBPORT_ID_NAMESPACEf);
   1152     val_b = soc_mem_field32_get(unit, SUBPORT_ID_TO_SGPP_MAPm, ent_b, SUBPORT_ID_NAMESPACEf);
   1153     SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1154 
   1155     val_a = soc_mem_field32_get(unit, SUBPORT_ID_TO_SGPP_MAPm, ent_a, SUBPORT_IDf);
   1156     val_b = soc_mem_field32_get(unit, SUBPORT_ID_TO_SGPP_MAPm, ent_b, SUBPORT_IDf);
   1157     SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1158 
   1159     return 0;
   1160 }
   1161 
   1162 #ifdef BCM_XGS_SWITCH_SUPPORT
   1163 
   1164 int
   1165 _soc_mem_cmp_l2x(int unit, void *ent_a, void *ent_b)
   1166 {
   1167     sal_mac_addr_t mac_a, mac_b;
   1168     vlan_id_t vlan_a, vlan_b;
   1169 
   1170     vlan_a = soc_L2Xm_field32_get(unit, ent_a, VLAN_IDf);
   1171     vlan_b = soc_L2Xm_field32_get(unit, ent_b, VLAN_IDf);
   1172     SOC_MEM_COMPARE_RETURN(vlan_a, vlan_b);
   1173 
   1174     soc_L2Xm_mac_addr_get(unit, ent_a, MAC_ADDRf, mac_a);
   1175     soc_L2Xm_mac_addr_get(unit, ent_b, MAC_ADDRf, mac_b);
   1176 
   1177     return ENET_CMP_MACADDR(mac_a, mac_b);
   1178 }
   1179 
   1180 int
   1181 _soc_mem_cmp_l2x_sync(int unit, void *ent_a, void *ent_b, int size, uint8 hit_bits)
   1182 {
   1183     l2x_entry_t     *l2x1 = (l2x_entry_t *)ent_a;
   1184     l2x_entry_t     *l2x2 = (l2x_entry_t *)ent_b;
   1185 
   1186     /* force bits that may be updated by HW to be the same */
   1187     if (SOC_IS_XGS3_SWITCH(unit) || SOC_IS_XGS3_FABRIC(unit)) {
   1188         if (!(hit_bits & L2X_SHADOW_HIT_BITS)) {
   1189             if (!(hit_bits & L2X_SHADOW_HIT_DST)) {
   1190                 soc_L2Xm_field32_set(unit, ent_a, HITDAf,
   1191                                      soc_L2Xm_field32_get(unit, ent_b,
   1192                                                           HITDAf));
   1193             }
   1194             if (!(hit_bits & L2X_SHADOW_HIT_SRC)) {
   1195                 soc_L2Xm_field32_set(unit, ent_a, HITSAf,
   1196                                      soc_L2Xm_field32_get(unit, ent_b,
   1197                                                           HITSAf));
   1198             }
   1199         }
   1200 
   1201         if (SOC_MEM_FIELD_VALID(unit, L2Xm, LOCAL_SAf)) {
   1202             soc_L2Xm_field32_set(unit, l2x1, LOCAL_SAf, 0);
   1203             soc_L2Xm_field32_set(unit, l2x2, LOCAL_SAf, 0);
   1204         }
   1205         if (SOC_MEM_FIELD_VALID(unit, L2Xm, EVEN_PARITYf)) {
   1206             soc_L2Xm_field32_set(unit, l2x1, EVEN_PARITYf, 0);
   1207             soc_L2Xm_field32_set(unit, l2x2, EVEN_PARITYf, 0);
   1208         }
   1209 #if defined(BCM_FELIX1_SUPPORT) || defined(BCM_HELIX1_SUPPORT)
   1210         if (SOC_MEM_FIELD_VALID(unit, L2Xm, ODD_PARITYf)) {
   1211             soc_L2Xm_field32_set(unit, l2x1, ODD_PARITYf, 0);
   1212             soc_L2Xm_field32_set(unit, l2x2, ODD_PARITYf, 0);
   1213         }
   1214 #endif
   1215     }
   1216 
   1217     return sal_memcmp(ent_a, ent_b, size);
   1218 }
   1219 
   1220 #ifdef BCM_TRIUMPH3_SUPPORT
   1221 int
   1222 _soc_mem_cmp_tr3_l2x_sync(int unit, void *ent_a, void *ent_b, uint8 hit_bits)
   1223 {
   1224     uint32 val;
   1225     soc_mem_t mem_type = L2_ENTRY_1m;
   1226     l2_entry_1_entry_t *l2_1_1, *l2_1_2;
   1227     l2_entry_2_entry_t *l2_2_1, *l2_2_2;
   1228 
   1229     val = soc_mem_field32_get(unit, L2_ENTRY_1m, (l2_entry_1_entry_t *)ent_a,
   1230                               KEY_TYPEf);
   1231     if ((val == SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE) ||
   1232         (val == SOC_MEM_KEY_L2_ENTRY_2_L2_VFI) ||
   1233         (val == SOC_MEM_KEY_L2_ENTRY_2_L2_TRILL_NONUC_ACCESS)) {
   1234         mem_type = L2_ENTRY_2m;
   1235     }
   1236 
   1237     if (mem_type == L2_ENTRY_1m) {
   1238         l2_1_1 = (l2_entry_1_entry_t *)ent_a;
   1239         l2_1_2 = (l2_entry_1_entry_t *)ent_b;
   1240         if (!(hit_bits & L2X_SHADOW_HIT_BITS)) {
   1241             soc_L2_ENTRY_1m_field32_set(unit, l2_1_1, HITSAf, 0);
   1242             soc_L2_ENTRY_1m_field32_set(unit, l2_1_2, HITSAf, 0);
   1243             soc_L2_ENTRY_1m_field32_set(unit, l2_1_1, HITDAf, 0);
   1244             soc_L2_ENTRY_1m_field32_set(unit, l2_1_2, HITDAf, 0);
   1245         } else {
   1246             if (!(hit_bits & L2X_SHADOW_HIT_SRC)) {
   1247                 soc_L2_ENTRY_1m_field32_set(unit, l2_1_1, HITSAf, 0);
   1248                 soc_L2_ENTRY_1m_field32_set(unit, l2_1_2, HITSAf, 0);
   1249             }
   1250             if (!(hit_bits & L2X_SHADOW_HIT_DST)) {
   1251                 soc_L2_ENTRY_1m_field32_set(unit, l2_1_1, HITDAf, 0);
   1252                 soc_L2_ENTRY_1m_field32_set(unit, l2_1_2, HITDAf, 0);
   1253             }
   1254         }
   1255         soc_L2_ENTRY_1m_field32_set(unit, l2_1_1, LOCAL_SAf, 0);
   1256         soc_L2_ENTRY_1m_field32_set(unit, l2_1_2, LOCAL_SAf, 0);
   1257         soc_L2_ENTRY_1m_field32_set(unit, l2_1_1, EVEN_PARITYf, 0);
   1258         soc_L2_ENTRY_1m_field32_set(unit, l2_1_2, EVEN_PARITYf, 0);
   1259         return sal_memcmp(ent_a, ent_b, sizeof(l2_entry_1_entry_t));
   1260     } else {
   1261         l2_2_1 = (l2_entry_2_entry_t *)ent_a;
   1262         l2_2_2 = (l2_entry_2_entry_t *)ent_b;
   1263         if (!(hit_bits & L2X_SHADOW_HIT_BITS)) {
   1264             soc_L2_ENTRY_2m_field32_set(unit, l2_2_1, HITSAf, 0);
   1265             soc_L2_ENTRY_2m_field32_set(unit, l2_2_2, HITSAf, 0);
   1266             soc_L2_ENTRY_2m_field32_set(unit, l2_2_1, HITDAf, 0);
   1267             soc_L2_ENTRY_2m_field32_set(unit, l2_2_2, HITDAf, 0);
   1268         } else {
   1269             if (!(hit_bits & L2X_SHADOW_HIT_SRC)) {
   1270                 soc_L2_ENTRY_2m_field32_set(unit, l2_2_1, HITSAf, 0);
   1271                 soc_L2_ENTRY_2m_field32_set(unit, l2_2_2, HITSAf, 0);
   1272             }
   1273             if (!(hit_bits & L2X_SHADOW_HIT_DST)) {
   1274                 soc_L2_ENTRY_2m_field32_set(unit, l2_2_1, HITDAf, 0);
   1275                 soc_L2_ENTRY_2m_field32_set(unit, l2_2_2, HITDAf, 0);
   1276             }
   1277         }
   1278         soc_L2_ENTRY_2m_field32_set(unit, l2_2_1, LOCAL_SAf, 0);
   1279         soc_L2_ENTRY_2m_field32_set(unit, l2_2_2, LOCAL_SAf, 0);
   1280         soc_L2_ENTRY_2m_field32_set(unit, l2_2_1, EVEN_PARITY_0f, 0);
   1281         soc_L2_ENTRY_2m_field32_set(unit, l2_2_2, EVEN_PARITY_0f, 0);
   1282         soc_L2_ENTRY_2m_field32_set(unit, l2_2_1, EVEN_PARITY_1f, 0);
   1283         soc_L2_ENTRY_2m_field32_set(unit, l2_2_2, EVEN_PARITY_1f, 0);
   1284         return sal_memcmp(ent_a, ent_b, sizeof(l2_entry_2_entry_t));
   1285     }
   1286 }
   1287 
   1288 int
   1289 _soc_mem_cmp_tr3_ext_l2x_1_sync(int unit, void *ent_a, void *ent_b,
   1290                                 uint8 hit_bits)
   1291 {
   1292     ext_l2_entry_1_entry_t *ext_l2_1_1, *ext_l2_1_2;
   1293     ext_l2_1_1 = (ext_l2_entry_1_entry_t *)ent_a;
   1294     ext_l2_1_2 = (ext_l2_entry_1_entry_t *)ent_b;
   1295     if (!(hit_bits & L2X_SHADOW_HIT_BITS)) {
   1296         soc_EXT_L2_ENTRY_1m_field32_set(unit, ext_l2_1_1, HITSAf, 0);
   1297         soc_EXT_L2_ENTRY_1m_field32_set(unit, ext_l2_1_2, HITSAf, 0);
   1298         soc_EXT_L2_ENTRY_1m_field32_set(unit, ext_l2_1_1, HITDAf, 0);
   1299         soc_EXT_L2_ENTRY_1m_field32_set(unit, ext_l2_1_2, HITDAf, 0);
   1300     } else {
   1301         if (!(hit_bits & L2X_SHADOW_HIT_SRC)) {
   1302             soc_EXT_L2_ENTRY_1m_field32_set(unit, ext_l2_1_1, HITSAf, 0);
   1303             soc_EXT_L2_ENTRY_1m_field32_set(unit, ext_l2_1_2, HITSAf, 0);
   1304         }
   1305         if (!(hit_bits & L2X_SHADOW_HIT_DST)) {
   1306             soc_EXT_L2_ENTRY_1m_field32_set(unit, ext_l2_1_1, HITDAf, 0);
   1307             soc_EXT_L2_ENTRY_1m_field32_set(unit, ext_l2_1_2, HITDAf, 0);
   1308         }
   1309     }
   1310     soc_EXT_L2_ENTRY_1m_field32_set(unit, ext_l2_1_1, LOCAL_SAf, 0);
   1311     soc_EXT_L2_ENTRY_1m_field32_set(unit, ext_l2_1_2, LOCAL_SAf, 0);
   1312     soc_EXT_L2_ENTRY_1m_field32_set(unit, ext_l2_1_1, EVEN_PARITYf, 0);
   1313     soc_EXT_L2_ENTRY_1m_field32_set(unit, ext_l2_1_2, EVEN_PARITYf, 0);
   1314     return sal_memcmp(ent_a, ent_b, sizeof(ext_l2_entry_1_entry_t));
   1315 }
   1316 
   1317 int
   1318 _soc_mem_cmp_tr3_ext_l2x_2_sync(int unit, void *ent_a, void *ent_b,
   1319                                 uint8 hit_bits)
   1320 {
   1321     ext_l2_entry_2_entry_t *ext_l2_2_1, *ext_l2_2_2;
   1322     ext_l2_2_1 = (ext_l2_entry_2_entry_t *)ent_a;
   1323     ext_l2_2_2 = (ext_l2_entry_2_entry_t *)ent_b;
   1324     if (!(hit_bits & L2X_SHADOW_HIT_BITS)) {
   1325         soc_EXT_L2_ENTRY_2m_field32_set(unit, ext_l2_2_1, HITSAf, 0);
   1326         soc_EXT_L2_ENTRY_2m_field32_set(unit, ext_l2_2_2, HITSAf, 0);
   1327         soc_EXT_L2_ENTRY_2m_field32_set(unit, ext_l2_2_1, HITDAf, 0);
   1328         soc_EXT_L2_ENTRY_2m_field32_set(unit, ext_l2_2_2, HITDAf, 0);
   1329     } else {
   1330         if (!(hit_bits & L2X_SHADOW_HIT_SRC)) {
   1331             soc_EXT_L2_ENTRY_2m_field32_set(unit, ext_l2_2_1, HITSAf, 0);
   1332             soc_EXT_L2_ENTRY_2m_field32_set(unit, ext_l2_2_2, HITSAf, 0);
   1333         }
   1334         if (!(hit_bits & L2X_SHADOW_HIT_DST)) {
   1335             soc_EXT_L2_ENTRY_2m_field32_set(unit, ext_l2_2_1, HITDAf, 0);
   1336             soc_EXT_L2_ENTRY_2m_field32_set(unit, ext_l2_2_2, HITDAf, 0);
   1337         }
   1338     }
   1339     soc_EXT_L2_ENTRY_2m_field32_set(unit, ext_l2_2_1, LOCAL_SAf, 0);
   1340     soc_EXT_L2_ENTRY_2m_field32_set(unit, ext_l2_2_2, LOCAL_SAf, 0);
   1341     soc_EXT_L2_ENTRY_2m_field32_set(unit, ext_l2_2_1, EVEN_PARITYf, 0);
   1342     soc_EXT_L2_ENTRY_2m_field32_set(unit, ext_l2_2_2, EVEN_PARITYf, 0);
   1343     return sal_memcmp(ent_a, ent_b, sizeof(ext_l2_entry_2_entry_t));
   1344 }
   1345 
   1346 int
   1347 _soc_mem_cmp_tr3_l2x(int unit, void *ent_a, void *ent_b)
   1348 {
   1349     uint32 val_a, val_b;
   1350     sal_mac_addr_t mac_a, mac_b;
   1351 
   1352     val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a, KEY_TYPEf);
   1353     val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b, KEY_TYPEf);
   1354     SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1355 
   1356     switch (val_a) {
   1357     case SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE: /* BRIDGE */
   1358         val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a, L2__VLAN_IDf);
   1359         val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b, L2__VLAN_IDf);
   1360         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1361 
   1362         soc_L2_ENTRY_1m_mac_addr_get(unit, ent_a, L2__MAC_ADDRf, mac_a);
   1363         soc_L2_ENTRY_1m_mac_addr_get(unit, ent_b, L2__MAC_ADDRf, mac_b);
   1364         return ENET_CMP_MACADDR(mac_a, mac_b);
   1365 
   1366     case SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE: /* BRIDGE */
   1367         val_a = soc_L2_ENTRY_2m_field32_get(unit, ent_a, L2__VLAN_IDf);
   1368         val_b = soc_L2_ENTRY_2m_field32_get(unit, ent_b, L2__VLAN_IDf);
   1369         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1370 
   1371         soc_L2_ENTRY_2m_mac_addr_get(unit, ent_a, L2__MAC_ADDRf, mac_a);
   1372         soc_L2_ENTRY_2m_mac_addr_get(unit, ent_b, L2__MAC_ADDRf, mac_b);
   1373         return ENET_CMP_MACADDR(mac_a, mac_b);
   1374 
   1375     case SOC_MEM_KEY_L2_ENTRY_1_L2_VFI: /* VFI */
   1376         val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a, L2__VFIf);
   1377         val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b, L2__VFIf);
   1378         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1379 
   1380         soc_L2_ENTRY_1m_mac_addr_get(unit, ent_a, L2__MAC_ADDRf, mac_a);
   1381         soc_L2_ENTRY_1m_mac_addr_get(unit, ent_b, L2__MAC_ADDRf, mac_b);
   1382         return ENET_CMP_MACADDR(mac_a, mac_b);
   1383 
   1384     case SOC_MEM_KEY_L2_ENTRY_2_L2_VFI: /* VFI */
   1385         val_a = soc_L2_ENTRY_2m_field32_get(unit, ent_a, L2__VFIf);
   1386         val_b = soc_L2_ENTRY_2m_field32_get(unit, ent_b, L2__VFIf);
   1387         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1388 
   1389         soc_L2_ENTRY_2m_mac_addr_get(unit, ent_a, L2__MAC_ADDRf, mac_a);
   1390         soc_L2_ENTRY_2m_mac_addr_get(unit, ent_b, L2__MAC_ADDRf, mac_b);
   1391         return ENET_CMP_MACADDR(mac_a, mac_b);
   1392 
   1393     case SOC_MEM_KEY_L2_ENTRY_1_VLAN_SINGLE_CROSS_CONNECT: /* SINGLE_CROSS_CONNECT */
   1394         val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a, VLAN__OVIDf);
   1395         val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b, VLAN__OVIDf);
   1396         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1397         return 0;
   1398 
   1399     case SOC_MEM_KEY_L2_ENTRY_1_VLAN_DOUBLE_CROSS_CONNECT: /* DOUBLE_CROSS_CONNECT */
   1400         val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a, VLAN__OVIDf);
   1401         val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b, VLAN__OVIDf);
   1402         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1403 
   1404         val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a, VLAN__IVIDf);
   1405         val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b, VLAN__IVIDf);
   1406         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1407         return 0;
   1408 
   1409     case SOC_MEM_KEY_L2_ENTRY_1_VIF_VIF: /* VIF */
   1410         val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a, VIF__NAMESPACEf);
   1411         val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b, VIF__NAMESPACEf);
   1412         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1413 
   1414         val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a, VIF__DST_VIFf);
   1415         val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b, VIF__DST_VIFf);
   1416         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1417 
   1418         val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a, VIF__Pf);
   1419         val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b, VIF__Pf);
   1420         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1421         return 0;
   1422 
   1423     case SOC_MEM_KEY_L2_ENTRY_2_L2_TRILL_NONUC_ACCESS: /* TRILL_NONUC_ACCESS */
   1424         val_a = soc_L2_ENTRY_2m_field32_get(unit, ent_a,
   1425                                             L2__VLAN_IDf);
   1426         val_b = soc_L2_ENTRY_2m_field32_get(unit, ent_b,
   1427                                             L2__VLAN_IDf);
   1428         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1429 
   1430         soc_L2_ENTRY_2m_mac_addr_get(unit, ent_a, L2__MAC_ADDRf,
   1431                                      mac_a);
   1432         soc_L2_ENTRY_2m_mac_addr_get(unit, ent_b, L2__MAC_ADDRf,
   1433                                      mac_b);
   1434         return ENET_CMP_MACADDR(mac_a, mac_b);
   1435 
   1436     case SOC_MEM_KEY_L2_ENTRY_1_TRILL_NONUC_NETWORK_LONG_TRILL_NONUC_NETWORK_LONG: /* TRILL_NONUC_NETWORK_LONG */
   1437         val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a,
   1438                                             TRILL_NONUC_NETWORK_LONG__VLAN_IDf);
   1439         val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b,
   1440                                             TRILL_NONUC_NETWORK_LONG__VLAN_IDf);
   1441         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1442 
   1443         val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a,
   1444                                             TRILL_NONUC_NETWORK_LONG__TREE_IDf);
   1445         val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b,
   1446                                             TRILL_NONUC_NETWORK_LONG__TREE_IDf);
   1447         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1448 
   1449         soc_L2_ENTRY_1m_mac_addr_get
   1450             (unit, ent_a, TRILL_NONUC_NETWORK_LONG__MAC_ADDRESSf, mac_a);
   1451         soc_L2_ENTRY_1m_mac_addr_get
   1452             (unit, ent_b, TRILL_NONUC_NETWORK_LONG__MAC_ADDRESSf, mac_b);
   1453         return ENET_CMP_MACADDR(mac_a, mac_b);
   1454 
   1455     case SOC_MEM_KEY_L2_ENTRY_1_TRILL_NONUC_NETWORK_SHORT_TRILL_NONUC_NETWORK_SHORT: /* TRILL_NONUC_NETWORK_SHORT */
   1456         val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a,
   1457                                             TRILL_NONUC_NETWORK_SHORT__VLAN_IDf);
   1458         val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b,
   1459                                             TRILL_NONUC_NETWORK_SHORT__VLAN_IDf);
   1460         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1461 
   1462         val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a,
   1463                                             TRILL_NONUC_NETWORK_SHORT__TREE_IDf);
   1464         val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b,
   1465                                             TRILL_NONUC_NETWORK_SHORT__TREE_IDf);
   1466         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1467         return 0;
   1468 
   1469     case SOC_MEM_KEY_L2_ENTRY_1_BFD_BFD: /* BFD */
   1470         val_a = soc_L2_ENTRY_1m_field32_get(unit, ent_a, BFD__YOUR_DISCRIMINATORf);
   1471         val_b = soc_L2_ENTRY_1m_field32_get(unit, ent_b, BFD__YOUR_DISCRIMINATORf);
   1472         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1473         return 0;
   1474     default:
   1475         return 1;
   1476     }
   1477 }
   1478 
   1479 int
   1480 _soc_mem_cmp_tr3_ext_l2x(int unit, void *ent_a, void *ent_b)
   1481 {
   1482     uint32 val_a, val_b;
   1483     sal_mac_addr_t mac_a, mac_b;
   1484 
   1485     val_a = soc_EXT_L2_ENTRY_1m_field32_get(unit, ent_a, KEY_TYPEf);
   1486     val_b = soc_EXT_L2_ENTRY_1m_field32_get(unit, ent_b, KEY_TYPEf);
   1487     SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1488 
   1489     if (val_a) { /* VFI */
   1490         val_a = soc_EXT_L2_ENTRY_1m_field32_get(unit, ent_a, VFIf);
   1491         val_b = soc_EXT_L2_ENTRY_1m_field32_get(unit, ent_b, VFIf);
   1492         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1493 
   1494         soc_EXT_L2_ENTRY_1m_mac_addr_get(unit, ent_a, MAC_ADDRf, mac_a);
   1495         soc_EXT_L2_ENTRY_1m_mac_addr_get(unit, ent_b, MAC_ADDRf, mac_b);
   1496         return ENET_CMP_MACADDR(mac_a, mac_b);
   1497     } else { /* BRIDGE */
   1498         val_a = soc_EXT_L2_ENTRY_1m_field32_get(unit, ent_a, VLAN_IDf);
   1499         val_b = soc_EXT_L2_ENTRY_1m_field32_get(unit, ent_b, VLAN_IDf);
   1500         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1501 
   1502         soc_EXT_L2_ENTRY_1m_mac_addr_get(unit, ent_a, MAC_ADDRf, mac_a);
   1503         soc_EXT_L2_ENTRY_1m_mac_addr_get(unit, ent_b, MAC_ADDRf, mac_b);
   1504         return ENET_CMP_MACADDR(mac_a, mac_b);
   1505     }
   1506 }
   1507 #endif /* BCM_TRIUMPH3_SUPPORT */
   1508 
   1509 #ifdef BCM_FIREBOLT_SUPPORT
   1510 int
   1511 _soc_mem_cmp_l2x2(int unit, void *ent_a, void *ent_b)
   1512 {
   1513     sal_mac_addr_t mac_a, mac_b;
   1514     uint32 val_a, val_b;
   1515     uint32 buf_a[SOC_MAX_MEM_FIELD_WORDS] = {0};
   1516     uint32 buf_b[SOC_MAX_MEM_FIELD_WORDS] = {0};
   1517 
   1518 #if defined(BCM_TOMAHAWK3_SUPPORT)
   1519     if (SOC_IS_TOMAHAWK3(unit)) {
   1520         val_a = soc_L2Xm_field32_get(unit, ent_a, KEY_TYPEf);
   1521         val_b = soc_L2Xm_field32_get(unit, ent_b, KEY_TYPEf);
   1522         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1523 
   1524         switch(val_a) {
   1525         case TH3_L2_HASH_KEY_TYPE_BRIDGE:
   1526             val_a = soc_L2Xm_field32_get(unit, ent_a, VLAN_IDf);
   1527             val_b = soc_L2Xm_field32_get(unit, ent_b, VLAN_IDf);
   1528             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1529 
   1530             soc_L2Xm_mac_addr_get(unit, ent_a, MAC_ADDRf, mac_a);
   1531             soc_L2Xm_mac_addr_get(unit, ent_b, MAC_ADDRf, mac_b);
   1532             return ENET_CMP_MACADDR(mac_a, mac_b);
   1533 
   1534         case TH3_L2_HASH_KEY_TYPE_SINGLE_CROSS_CONNECT:
   1535             val_a = soc_L2Xm_field32_get(unit, ent_a, VLAN_IDf);
   1536             val_b = soc_L2Xm_field32_get(unit, ent_b, VLAN_IDf);
   1537             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1538             return 0;
   1539 
   1540         default:
   1541             return 1;
   1542         }
   1543     } else
   1544 #endif /* BCM_TOMAHAWK3_SUPPORT */
   1545 
   1546     if ((SOC_IS_KATANA2(unit)) || (SOC_IS_SABER2(unit)) ||
   1547         (SOC_IS_KATANA(unit)) || (SOC_IS_HURRICANE3(unit)) ||
   1548         (SOC_IS_METROLITE(unit)) || (SOC_IS_GREYHOUND(unit)) ||
   1549         (SOC_IS_GREYHOUND2(unit))) {
   1550         if (SOC_MEM_FIELD_VALID(unit, L2Xm, KEY_TYPEf)) {
   1551         val_a = soc_L2Xm_field32_get(unit, ent_a, KEY_TYPEf);
   1552         val_b = soc_L2Xm_field32_get(unit, ent_b, KEY_TYPEf);
   1553         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1554 
   1555         switch (val_a) {
   1556         case 0: /* BRIDGE */
   1557             val_a = soc_L2Xm_field32_get(unit, ent_a, VLAN_IDf);
   1558             val_b = soc_L2Xm_field32_get(unit, ent_b, VLAN_IDf);
   1559             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1560 
   1561             soc_L2Xm_mac_addr_get(unit, ent_a, MAC_ADDRf, mac_a);
   1562             soc_L2Xm_mac_addr_get(unit, ent_b, MAC_ADDRf, mac_b);
   1563             return ENET_CMP_MACADDR(mac_a, mac_b);
   1564 
   1565         case 1: /* SINGLE_CROSS_CONNECT */
   1566                 if (SOC_MEM_FIELD_VALID(unit, L2Xm, VLAN__OVIDf)) {
   1567                     val_a = soc_L2Xm_field32_get(unit, ent_a, VLAN__OVIDf);
   1568                     val_b = soc_L2Xm_field32_get(unit, ent_b, VLAN__OVIDf);
   1569                 } else {
   1570             val_a = soc_L2Xm_field32_get(unit, ent_a, OVIDf);
   1571             val_b = soc_L2Xm_field32_get(unit, ent_b, OVIDf);
   1572                 }
   1573             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1574 
   1575             return 0;
   1576         case 2: /* DOUBLE_CROSS_CONNECT */
   1577                 if (SOC_MEM_FIELD_VALID(unit, L2Xm, VLAN__OVIDf)) {
   1578                     val_a = soc_L2Xm_field32_get(unit, ent_a, VLAN__OVIDf);
   1579                     val_b = soc_L2Xm_field32_get(unit, ent_b, VLAN__OVIDf);
   1580                 } else {
   1581             val_a = soc_L2Xm_field32_get(unit, ent_a, OVIDf);
   1582             val_b = soc_L2Xm_field32_get(unit, ent_b, OVIDf);
   1583                 }
   1584             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1585 
   1586                 if (SOC_MEM_FIELD_VALID(unit, L2Xm, VLAN__IVIDf)) {
   1587                     val_a = soc_L2Xm_field32_get(unit, ent_a, VLAN__IVIDf);
   1588                     val_b = soc_L2Xm_field32_get(unit, ent_b, VLAN__IVIDf);
   1589                 } else {
   1590             val_a = soc_L2Xm_field32_get(unit, ent_a, IVIDf);
   1591             val_b = soc_L2Xm_field32_get(unit, ent_b, IVIDf);
   1592                 }
   1593                 SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1594 
   1595                 return 0;
   1596 
   1597             case 3: /* VFI */
   1598                 val_a = soc_L2Xm_field32_get(unit, ent_a, VFIf);
   1599                 val_b = soc_L2Xm_field32_get(unit, ent_b, VFIf);
   1600                 SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1601 
   1602                 soc_L2Xm_mac_addr_get(unit, ent_a, MAC_ADDRf, mac_a);
   1603                 soc_L2Xm_mac_addr_get(unit, ent_b, MAC_ADDRf, mac_b);
   1604                 return ENET_CMP_MACADDR(mac_a, mac_b);
   1605 
   1606             case 4: /*  BFD */
   1607                 soc_L2Xm_field_get(unit, ent_a, BFD__KEYf, buf_a);
   1608                 soc_L2Xm_field_get(unit, ent_b, BFD__KEYf, buf_b);
   1609                 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]);
   1610                 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]);
   1611 
   1612             return 0;
   1613 
   1614             case 5: /* VIF */
   1615                 val_a = soc_L2Xm_field32_get(unit, ent_a, VIF__NAMESPACEf);
   1616                 val_b = soc_L2Xm_field32_get(unit, ent_b, VIF__NAMESPACEf);
   1617                 SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1618 
   1619                 val_a = soc_L2Xm_field32_get(unit, ent_a, VIF__DST_VIFf);
   1620                 val_b = soc_L2Xm_field32_get(unit, ent_b, VIF__DST_VIFf);
   1621                 SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1622 
   1623                 val_a = soc_L2Xm_field32_get(unit, ent_a, VIF__Pf);
   1624                 val_b = soc_L2Xm_field32_get(unit, ent_b, VIF__Pf);
   1625                 SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1626 
   1627                 return 0;
   1628 
   1629             case 6: /*  PE_VID */
   1630                 soc_L2Xm_field_get(unit, ent_a, PE_VID__KEYf, buf_a);
   1631                 soc_L2Xm_field_get(unit, ent_b, PE_VID__KEYf, buf_b);
   1632                 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]);
   1633                 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]);
   1634 
   1635                 return 0;
   1636 #if defined(BCM_GREYHOUND2_SUPPORT)
   1637             case 7: /* VFI Multicast */
   1638                 if (soc_feature(unit, soc_feature_vxlan_lite_riot)) {
   1639                     val_a = soc_L2Xm_field32_get(unit, ent_a, VFIf);
   1640                     val_b = soc_L2Xm_field32_get(unit, ent_b, VFIf);
   1641                     SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1642 
   1643                     soc_L2Xm_mac_addr_get(unit, ent_a, MAC_ADDRf, mac_a);
   1644                     soc_L2Xm_mac_addr_get(unit, ent_b, MAC_ADDRf, mac_b);
   1645                     return ENET_CMP_MACADDR(mac_a, mac_b);
   1646                 }
   1647 #endif /* BCM_GREYHOUND2_SUPPORT */
   1648             default:
   1649                 return 1;
   1650             }
   1651         }
   1652     } else {
   1653 
   1654         if (SOC_MEM_FIELD_VALID(unit, L2Xm, KEY_TYPEf)) {
   1655             val_a = soc_L2Xm_field32_get(unit, ent_a, KEY_TYPEf);
   1656             val_b = soc_L2Xm_field32_get(unit, ent_b, KEY_TYPEf);
   1657             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1658 
   1659             switch (val_a) {
   1660             case 0: /* BRIDGE */
   1661                 val_a = soc_L2Xm_field32_get(unit, ent_a, VLAN_IDf);
   1662                 val_b = soc_L2Xm_field32_get(unit, ent_b, VLAN_IDf);
   1663                 SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1664 
   1665                 soc_L2Xm_mac_addr_get(unit, ent_a, MAC_ADDRf, mac_a);
   1666                 soc_L2Xm_mac_addr_get(unit, ent_b, MAC_ADDRf, mac_b);
   1667                 return ENET_CMP_MACADDR(mac_a, mac_b);
   1668 
   1669             case 1: /* SINGLE_CROSS_CONNECT */
   1670                 if (SOC_MEM_FIELD_VALID(unit, L2Xm, VLAN__OVIDf)) {
   1671                     val_a = soc_L2Xm_field32_get(unit, ent_a, VLAN__OVIDf);
   1672                     val_b = soc_L2Xm_field32_get(unit, ent_b, VLAN__OVIDf);
   1673                 } else {
   1674                     val_a = soc_L2Xm_field32_get(unit, ent_a, OVIDf);
   1675                     val_b = soc_L2Xm_field32_get(unit, ent_b, OVIDf);
   1676                 }
   1677                 SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1678 
   1679                 return 0;
   1680             case 2: /* DOUBLE_CROSS_CONNECT */
   1681                 if (SOC_MEM_FIELD_VALID(unit, L2Xm, VLAN__OVIDf)) {
   1682                     val_a = soc_L2Xm_field32_get(unit, ent_a, VLAN__OVIDf);
   1683                     val_b = soc_L2Xm_field32_get(unit, ent_b, VLAN__OVIDf);
   1684                 } else {
   1685                     val_a = soc_L2Xm_field32_get(unit, ent_a, OVIDf);
   1686                     val_b = soc_L2Xm_field32_get(unit, ent_b, OVIDf);
   1687                 }
   1688                 SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1689 
   1690                 if (SOC_MEM_FIELD_VALID(unit, L2Xm, VLAN__IVIDf)) {
   1691                     val_a = soc_L2Xm_field32_get(unit, ent_a, VLAN__IVIDf);
   1692                     val_b = soc_L2Xm_field32_get(unit, ent_b, VLAN__IVIDf);
   1693                 } else {
   1694                     val_a = soc_L2Xm_field32_get(unit, ent_a, IVIDf);
   1695                     val_b = soc_L2Xm_field32_get(unit, ent_b, IVIDf);
   1696                 }
   1697             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1698 
   1699             return 0;
   1700 
   1701         case 3: /* VFI */
   1702             val_a = soc_L2Xm_field32_get(unit, ent_a, VFIf);
   1703             val_b = soc_L2Xm_field32_get(unit, ent_b, VFIf);
   1704             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1705 
   1706             soc_L2Xm_mac_addr_get(unit, ent_a, MAC_ADDRf, mac_a);
   1707             soc_L2Xm_mac_addr_get(unit, ent_b, MAC_ADDRf, mac_b);
   1708             return ENET_CMP_MACADDR(mac_a, mac_b);
   1709 
   1710         case 4: /* VIF */
   1711             val_a = soc_L2Xm_field32_get(unit, ent_a, VIF__NAMESPACEf);
   1712             val_b = soc_L2Xm_field32_get(unit, ent_b, VIF__NAMESPACEf);
   1713             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1714 
   1715             val_a = soc_L2Xm_field32_get(unit, ent_a, VIF__DST_VIFf);
   1716             val_b = soc_L2Xm_field32_get(unit, ent_b, VIF__DST_VIFf);
   1717             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1718 
   1719             val_a = soc_L2Xm_field32_get(unit, ent_a, VIF__Pf);
   1720             val_b = soc_L2Xm_field32_get(unit, ent_b, VIF__Pf);
   1721             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1722 
   1723             return 0;
   1724 
   1725         case 5: /* TRILL_NONUC_ACCESS */
   1726                 if (SOC_IS_TRIDENT(unit)) {
   1727             val_a = soc_L2Xm_field32_get(unit, ent_a,
   1728                                          TRILL_NONUC_ACCESS__VLAN_IDf);
   1729             val_b = soc_L2Xm_field32_get(unit, ent_b,
   1730                                          TRILL_NONUC_ACCESS__VLAN_IDf);
   1731                 } else {
   1732                     val_a = soc_L2Xm_field32_get(unit, ent_a, L2__VLAN_IDf);
   1733                     val_b = soc_L2Xm_field32_get(unit, ent_b, L2__VLAN_IDf);
   1734                 }
   1735             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1736 
   1737                 if (SOC_IS_TRIDENT(unit)) {
   1738                     soc_L2Xm_mac_addr_get(unit, ent_a,
   1739                                          TRILL_NONUC_ACCESS__MAC_ADDRf, mac_a);
   1740                     soc_L2Xm_mac_addr_get(unit, ent_b,
   1741                                          TRILL_NONUC_ACCESS__MAC_ADDRf, mac_b);
   1742                 } else {
   1743                     soc_L2Xm_mac_addr_get(unit, ent_a, L2__MAC_ADDRf, mac_a);
   1744                     soc_L2Xm_mac_addr_get(unit, ent_b, L2__MAC_ADDRf, mac_b);
   1745                 }
   1746             return ENET_CMP_MACADDR(mac_a, mac_b);
   1747 
   1748         case 6: /* TRILL_NONUC_NETWORK_LONG */
   1749             val_a = soc_L2Xm_field32_get(unit, ent_a,
   1750                                          TRILL_NONUC_NETWORK_LONG__VLAN_IDf);
   1751             val_b = soc_L2Xm_field32_get(unit, ent_b,
   1752                                          TRILL_NONUC_NETWORK_LONG__VLAN_IDf);
   1753             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1754 
   1755             val_a = soc_L2Xm_field32_get(unit, ent_a,
   1756                                          TRILL_NONUC_NETWORK_LONG__TREE_IDf);
   1757             val_b = soc_L2Xm_field32_get(unit, ent_b,
   1758                                          TRILL_NONUC_NETWORK_LONG__TREE_IDf);
   1759             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1760 
   1761             soc_L2Xm_mac_addr_get
   1762                 (unit, ent_a, TRILL_NONUC_NETWORK_LONG__MAC_ADDRESSf, mac_a);
   1763             soc_L2Xm_mac_addr_get
   1764                 (unit, ent_b, TRILL_NONUC_NETWORK_LONG__MAC_ADDRESSf, mac_b);
   1765             return ENET_CMP_MACADDR(mac_a, mac_b);
   1766 
   1767         case 7: /* TRILL_NONUC_NETWORK_SHORT */
   1768             val_a = soc_L2Xm_field32_get(unit, ent_a,
   1769                                          TRILL_NONUC_NETWORK_SHORT__VLAN_IDf);
   1770             val_b = soc_L2Xm_field32_get(unit, ent_b,
   1771                                          TRILL_NONUC_NETWORK_SHORT__VLAN_IDf);
   1772             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1773 
   1774             val_a = soc_L2Xm_field32_get(unit, ent_a,
   1775                                          TRILL_NONUC_NETWORK_SHORT__TREE_IDf);
   1776             val_b = soc_L2Xm_field32_get(unit, ent_b,
   1777                                          TRILL_NONUC_NETWORK_SHORT__TREE_IDf);
   1778             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1779 
   1780             return 0;
   1781 
   1782             case 8: /*  BFD */
   1783                 soc_L2Xm_field_get(unit, ent_a, BFD__KEYf, buf_a);
   1784                 soc_L2Xm_field_get(unit, ent_b, BFD__KEYf, buf_b);
   1785                 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]);
   1786                 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]);
   1787 
   1788                 return 0;
   1789 
   1790             case 9: /*  PE_VID */
   1791                 soc_L2Xm_field_get(unit, ent_a, PE_VID__KEYf, buf_a);
   1792                 soc_L2Xm_field_get(unit, ent_b, PE_VID__KEYf, buf_b);
   1793                 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]);
   1794                 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]);
   1795 
   1796                 return 0;
   1797 
   1798             case 10: /* FCOE_ZONE */
   1799                 soc_L2Xm_field_get(unit, ent_a, FCOE_ZONE__KEYf, buf_a);
   1800                 soc_L2Xm_field_get(unit, ent_b, FCOE_ZONE__KEYf, buf_b);
   1801                 SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]);
   1802                 SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]);
   1803                 SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]);
   1804 
   1805                 return 0;
   1806         default:
   1807             return 1;
   1808         }
   1809     }
   1810     }
   1811 
   1812     val_a = soc_L2Xm_field32_get(unit, ent_a, VLAN_IDf);
   1813     val_b = soc_L2Xm_field32_get(unit, ent_b, VLAN_IDf);
   1814     SOC_MEM_COMPARE_RETURN(val_a, val_b);
   1815 
   1816     soc_L2Xm_mac_addr_get(unit, ent_a, MAC_ADDRf, mac_a);
   1817     soc_L2Xm_mac_addr_get(unit, ent_b, MAC_ADDRf, mac_b);
   1818     return ENET_CMP_MACADDR(mac_a, mac_b);
   1819 }
   1820 
   1821 #ifdef BCM_TRIDENT3_SUPPORT
   1822 
   1823 STATIC int
   1824 _soc_td3mem_cmp_l3x2_ip6mcast(int u, void *e_a, void *e_b)
   1825 {
   1826     uint32      type_a, type_b;
   1827     uint32      a[SOC_MAX_MEM_FIELD_WORDS];
   1828     uint32      b[SOC_MAX_MEM_FIELD_WORDS];
   1829     int         i;
   1830     int         ent_words;
   1831 
   1832     type_a = soc_L3_ENTRY_QUADm_field32_get(u, e_a, IPV6MC__VLAN_IDf);
   1833     type_b = soc_L3_ENTRY_QUADm_field32_get(u, e_b, IPV6MC__VLAN_IDf);
   1834     SOC_MEM_COMPARE_RETURN(type_a, type_b);
   1835 
   1836     type_a = soc_L3_ENTRY_QUADm_field32_get(u, e_a, IPV6MC__VRF_IDf);
   1837     type_b = soc_L3_ENTRY_QUADm_field32_get(u, e_b, IPV6MC__VRF_IDf);
   1838     SOC_MEM_COMPARE_RETURN(type_a, type_b);
   1839 
   1840     type_a = soc_L3_ENTRY_QUADm_field32_get(u, e_a, KEY_TYPEf);
   1841     type_b = soc_L3_ENTRY_QUADm_field32_get(u, e_b, KEY_TYPEf);
   1842     SOC_MEM_COMPARE_RETURN(type_a, type_b);
   1843 
   1844     type_a = soc_L3_ENTRY_QUADm_field32_get(u, e_a, DATA_TYPEf);
   1845     type_b = soc_L3_ENTRY_QUADm_field32_get(u, e_b, DATA_TYPEf);
   1846     SOC_MEM_COMPARE_RETURN(type_a, type_b);
   1847 
   1848     soc_mem_field_get(u, L3_ENTRY_QUADm,
   1849                       e_a, IPV6MC__GROUP_IP_ADDR_UPR_56f, a);
   1850     soc_mem_field_get(u, L3_ENTRY_QUADm,
   1851                       e_b, IPV6MC__GROUP_IP_ADDR_UPR_56f, b);
   1852     ent_words = soc_mem_field_length(u, L3_ENTRY_QUADm,
   1853                       IPV6MC__GROUP_IP_ADDR_UPR_56f) / 32;
   1854     for (i = ent_words - 1; i >= 0; i--) {
   1855         SOC_MEM_COMPARE_RETURN(a[i], b[i]);
   1856     }
   1857 
   1858     soc_mem_field_get(u, L3_ENTRY_QUADm,
   1859                       e_a, IPV6MC__GROUP_IP_ADDR_LWR_64f, a);
   1860     soc_mem_field_get(u, L3_ENTRY_QUADm,
   1861                       e_b, IPV6MC__GROUP_IP_ADDR_LWR_64f, b);
   1862     ent_words = soc_mem_field_length(u, L3_ENTRY_QUADm,
   1863                       IPV6MC__GROUP_IP_ADDR_LWR_64f) / 32;
   1864     for (i = ent_words - 1; i >= 0; i--) {
   1865         SOC_MEM_COMPARE_RETURN(a[i], b[i]);
   1866     }
   1867 
   1868     soc_mem_field_get(u, L3_ENTRY_QUADm,
   1869                       e_a, IPV6MC__SOURCE_IP_ADDR_UPR_64f, a);
   1870     soc_mem_field_get(u, L3_ENTRY_QUADm,
   1871                       e_b, IPV6MC__SOURCE_IP_ADDR_UPR_64f, b);
   1872     ent_words = soc_mem_field_length(u, L3_ENTRY_QUADm,
   1873                       IPV6MC__SOURCE_IP_ADDR_UPR_64f) / 32;
   1874     for (i = ent_words - 1; i >= 0; i--) {
   1875         SOC_MEM_COMPARE_RETURN(a[i], b[i]);
   1876     }
   1877 
   1878     soc_mem_field_get(u, L3_ENTRY_QUADm,
   1879                       e_a, IPV6MC__SOURCE_IP_ADDR_BITS_63_32f, a);
   1880     soc_mem_field_get(u, L3_ENTRY_QUADm,
   1881                       e_b, IPV6MC__SOURCE_IP_ADDR_BITS_63_32f, b);
   1882     ent_words = soc_mem_field_length(u, L3_ENTRY_QUADm,
   1883                       IPV6MC__SOURCE_IP_ADDR_BITS_63_32f) / 32;
   1884     for (i = ent_words - 1; i >= 0; i--) {
   1885         SOC_MEM_COMPARE_RETURN(a[i], b[i]);
   1886     }
   1887 
   1888     soc_mem_field_get(u, L3_ENTRY_QUADm,
   1889                       e_a, IPV6MC__SOURCE_IP_ADDR_BITS_31_0f, a);
   1890     soc_mem_field_get(u, L3_ENTRY_QUADm,
   1891                       e_b, IPV6MC__SOURCE_IP_ADDR_BITS_31_0f, b);
   1892     ent_words = soc_mem_field_length(u, L3_ENTRY_QUADm,
   1893                       IPV6MC__SOURCE_IP_ADDR_BITS_31_0f) / 32;
   1894     for (i = ent_words - 1; i >= 0; i--) {
   1895         SOC_MEM_COMPARE_RETURN(a[i], b[i]);
   1896     }
   1897 
   1898     return(0);
   1899 }
   1900 
   1901 STATIC int
   1902 _soc_td3mem_cmp_l3x2_ip4mcast(int unit, void *ent_a, void *ent_b)
   1903 {
   1904     uint32      type_a, type_b;
   1905     ip_addr_t    a, b;
   1906     vlan_id_t    vlan_a, vlan_b;
   1907 
   1908     type_a = soc_L3_ENTRY_DOUBLEm_field32_get(unit, ent_a, IPV4MC__VRF_IDf);
   1909     type_b = soc_L3_ENTRY_DOUBLEm_field32_get(unit, ent_b, IPV4MC__VRF_IDf);
   1910     SOC_MEM_COMPARE_RETURN(type_a, type_b);
   1911 
   1912     type_a = soc_L3_ENTRY_DOUBLEm_field32_get(unit, ent_a, KEY_TYPEf);
   1913     type_b = soc_L3_ENTRY_DOUBLEm_field32_get(unit, ent_b, KEY_TYPEf);
   1914     SOC_MEM_COMPARE_RETURN(type_a, type_b);
   1915 
   1916     type_a = soc_L3_ENTRY_DOUBLEm_field32_get(unit, ent_a, DATA_TYPEf);
   1917     type_b = soc_L3_ENTRY_DOUBLEm_field32_get(unit, ent_b, DATA_TYPEf);
   1918     SOC_MEM_COMPARE_RETURN(type_a, type_b);
   1919 
   1920     a = soc_L3_ENTRY_DOUBLEm_field32_get(unit, ent_a, IPV4MC__SOURCE_IP_ADDRf);
   1921     b = soc_L3_ENTRY_DOUBLEm_field32_get(unit, ent_b, IPV4MC__SOURCE_IP_ADDRf);
   1922     SOC_MEM_COMPARE_RETURN(a, b);
   1923 
   1924     a = soc_L3_ENTRY_DOUBLEm_field32_get(unit, ent_a, IPV4MC__GROUP_IP_ADDRf);
   1925     b = soc_L3_ENTRY_DOUBLEm_field32_get(unit, ent_b, IPV4MC__GROUP_IP_ADDRf);
   1926     SOC_MEM_COMPARE_RETURN(a, b);
   1927 
   1928     vlan_a = soc_L3_ENTRY_DOUBLEm_field32_get(unit, ent_a, IPV4MC__VLAN_IDf);
   1929     vlan_b = soc_L3_ENTRY_DOUBLEm_field32_get(unit, ent_b, IPV4MC__VLAN_IDf);
   1930     SOC_MEM_COMPARE_RETURN(vlan_a, vlan_b);
   1931 
   1932     return(0);
   1933 }
   1934 
   1935 STATIC int
   1936 _soc_td3mem_cmp_l3x2_ip6ucast(int u, void *e_a, void *e_b)
   1937 {
   1938     uint32      type_a, type_b;
   1939     uint32      a[SOC_MAX_MEM_FIELD_WORDS];
   1940     uint32      b[SOC_MAX_MEM_FIELD_WORDS];
   1941     int         i;
   1942     int         ent_words;
   1943 
   1944     type_a = soc_L3_ENTRY_DOUBLEm_field32_get(u, e_a, IPV6UC__VRF_IDf);
   1945     type_b = soc_L3_ENTRY_DOUBLEm_field32_get(u, e_b, IPV6UC__VRF_IDf);
   1946     SOC_MEM_COMPARE_RETURN(type_a, type_b);
   1947 
   1948     type_a = soc_L3_ENTRY_DOUBLEm_field32_get(u, e_a, KEY_TYPEf);
   1949     type_b = soc_L3_ENTRY_DOUBLEm_field32_get(u, e_b, KEY_TYPEf);
   1950     SOC_MEM_COMPARE_RETURN(type_a, type_b);
   1951 
   1952     type_a = soc_L3_ENTRY_DOUBLEm_field32_get(u, e_a, DATA_TYPEf);
   1953     type_b = soc_L3_ENTRY_DOUBLEm_field32_get(u, e_b, DATA_TYPEf);
   1954     SOC_MEM_COMPARE_RETURN(type_a, type_b);
   1955 
   1956     soc_mem_field_get(u, L3_ENTRY_DOUBLEm, e_a,
   1957                       IPV6UC__IP_ADDR_UPR_64f, a);
   1958     soc_mem_field_get(u, L3_ENTRY_DOUBLEm, e_b,
   1959                       IPV6UC__IP_ADDR_UPR_64f, b);
   1960     ent_words = soc_mem_field_length(u, L3_ENTRY_DOUBLEm,
   1961                       IPV6UC__IP_ADDR_UPR_64f) / 32;
   1962     for (i = ent_words - 1; i >= 0; i--) {
   1963         SOC_MEM_COMPARE_RETURN(a[i], b[i]);
   1964     }
   1965 
   1966     soc_mem_field_get(u, L3_ENTRY_DOUBLEm, e_a,
   1967                       IPV6UC__IP_ADDR_LWR_64f, a);
   1968     soc_mem_field_get(u, L3_ENTRY_DOUBLEm, e_b,
   1969                       IPV6UC__IP_ADDR_LWR_64f, b);
   1970     ent_words = soc_mem_field_length(u, L3_ENTRY_DOUBLEm,
   1971                       IPV6UC__IP_ADDR_LWR_64f) / 32;
   1972     for (i = ent_words - 1; i >= 0; i--) {
   1973         SOC_MEM_COMPARE_RETURN(a[i], b[i]);
   1974     }
   1975 
   1976     return(0);
   1977 }
   1978 
   1979 STATIC int
   1980 _soc_td3mem_cmp_l3x2_ip4ucast(int unit, void *ent_a, void *ent_b)
   1981 {
   1982     uint32      type_a, type_b;
   1983     ip_addr_t    a, b;
   1984 
   1985     type_a = soc_L3_ENTRY_SINGLEm_field32_get(unit, ent_a, IPV4UC__VRF_IDf);
   1986     type_b = soc_L3_ENTRY_SINGLEm_field32_get(unit, ent_b, IPV4UC__VRF_IDf);
   1987     SOC_MEM_COMPARE_RETURN(type_a, type_b);
   1988 
   1989     type_a = soc_L3_ENTRY_SINGLEm_field32_get(unit, ent_a, KEY_TYPEf);
   1990     type_b = soc_L3_ENTRY_SINGLEm_field32_get(unit, ent_b, KEY_TYPEf);
   1991     SOC_MEM_COMPARE_RETURN(type_a, type_b);
   1992 
   1993     type_a = soc_L3_ENTRY_SINGLEm_field32_get(unit, ent_a, DATA_TYPEf);
   1994     type_b = soc_L3_ENTRY_SINGLEm_field32_get(unit, ent_b, DATA_TYPEf);
   1995     SOC_MEM_COMPARE_RETURN(type_a, type_b);
   1996 
   1997     a = soc_L3_ENTRY_SINGLEm_field32_get(unit, ent_a, IPV4UC__IP_ADDRf);
   1998     b = soc_L3_ENTRY_SINGLEm_field32_get(unit, ent_b, IPV4UC__IP_ADDRf);
   1999     SOC_MEM_COMPARE_RETURN(a, b);
   2000 
   2001     return(0);
   2002 }
   2003 
   2004 int
   2005 _soc_td3mem_cmp_l3x2(int unit, void *ent_a, void *ent_b)
   2006 {
   2007     uint32 val_a, val_b;
   2008     val_a = soc_L3_ENTRY_SINGLEm_field32_get(unit, ent_a, KEY_TYPEf);
   2009     val_b = soc_L3_ENTRY_SINGLEm_field32_get(unit, ent_b, KEY_TYPEf);
   2010     SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2011 
   2012     switch (val_a) {
   2013         case TD3_L3_HASH_KEY_TYPE_V4MC:
   2014             return _soc_td3mem_cmp_l3x2_ip4mcast(unit, ent_a, ent_b);
   2015         case TD3_L3_HASH_KEY_TYPE_V6MC:
   2016             return _soc_td3mem_cmp_l3x2_ip6mcast(unit, ent_a, ent_b);
   2017         case TD3_L3_HASH_KEY_TYPE_V4UC:
   2018             return _soc_td3mem_cmp_l3x2_ip4ucast(unit, ent_a, ent_b);
   2019         case TD3_L3_HASH_KEY_TYPE_V6UC:
   2020             return _soc_td3mem_cmp_l3x2_ip6ucast(unit, ent_a, ent_b);
   2021 
   2022         case TD3_L3_HASH_KEY_TYPE_TRILL:
   2023         case TD3_L3_HASH_KEY_TYPE_FCOE_DOMAIN:
   2024         case TD3_L3_HASH_KEY_TYPE_FCOE_HOST:
   2025         case TD3_L3_HASH_KEY_TYPE_DST_NAT:
   2026         case TD3_L3_HASH_KEY_TYPE_DST_NAPT:
   2027         default:
   2028             return 0;
   2029     }
   2030     return 1;
   2031 }
   2032 #endif /* BCM_TRIDENT3_SUPPORT */
   2033 
   2034 
   2035 int
   2036 _soc_mem_cmp_l3x2(int unit, void *ent_a, void *ent_b)
   2037 {
   2038     uint32 val_a, val_b;
   2039 
   2040 #ifdef BCM_TRIDENT3_SUPPORT
   2041     if (SOC_IS_TRIDENT3X(unit)) {
   2042         return(_soc_td3mem_cmp_l3x2(unit, ent_a, ent_b));
   2043     }
   2044 #endif /* BCM_TRIDENT3_SUPPORT */
   2045 
   2046     if (!SOC_MEM_FIELD_VALID(unit, L3_ENTRY_ONLYm, KEY_TYPEf)) {
   2047         return 0;
   2048     }
   2049 
   2050     val_a = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_a, KEY_TYPEf);
   2051     val_b = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_b, KEY_TYPEf);
   2052     SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2053 
   2054 #ifdef BCM_TRIDENT2_SUPPORT
   2055     if (SOC_IS_TD2_TT2(unit)) {
   2056         uint32 buf_a[SOC_MAX_MEM_FIELD_WORDS];
   2057         uint32 buf_b[SOC_MAX_MEM_FIELD_WORDS];
   2058         switch (val_a) {
   2059         case TD2_L3_HASH_KEY_TYPE_V4UC:
   2060             return _soc_mem_cmp_l3x2_ip4ucast(unit, ent_a, ent_b);
   2061         case TD2_L3_HASH_KEY_TYPE_V4UC_EXT:
   2062             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a,
   2063                                         KEY_TYPE_1f);
   2064             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b,
   2065                                         KEY_TYPE_1f);
   2066             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2067 
   2068             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a,
   2069                                         IPV4UC_EXT__IP_ADDRf);
   2070             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b,
   2071                                         IPV4UC_EXT__IP_ADDRf);
   2072             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2073 
   2074             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a,
   2075                                         IPV4UC_EXT__VRF_IDf);
   2076             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b,
   2077                                         IPV4UC_EXT__VRF_IDf);
   2078             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2079 
   2080             return 0;
   2081         case TD2_L3_HASH_KEY_TYPE_V4MC:
   2082         case TD2_L3_HASH_KEY_TYPE_V4L2MC:
   2083         case TD2_L3_HASH_KEY_TYPE_V4L2VPMC:
   2084             return _soc_mem_cmp_l3x2_ip4mcast(unit, ent_a, ent_b);
   2085         case TD2_L3_HASH_KEY_TYPE_V6UC:
   2086             return _soc_mem_cmp_l3x2_ip6ucast(unit, ent_a, ent_b);
   2087         case TD2_L3_HASH_KEY_TYPE_V6UC_EXT:
   2088             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV6_MULTICASTm, ent_a,
   2089                                         KEY_TYPE_1f);
   2090             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV6_MULTICASTm, ent_b,
   2091                                         KEY_TYPE_1f);
   2092             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2093 
   2094             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV6_MULTICASTm, ent_a,
   2095                                         KEY_TYPE_2f);
   2096             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV6_MULTICASTm, ent_b,
   2097                                         KEY_TYPE_2f);
   2098             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2099 
   2100             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV6_MULTICASTm, ent_a,
   2101                                         KEY_TYPE_3f);
   2102             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV6_MULTICASTm, ent_b,
   2103                                         KEY_TYPE_3f);
   2104             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2105 
   2106             soc_mem_field_get(unit, L3_ENTRY_IPV6_MULTICASTm, ent_a,
   2107                               IPV6UC_EXT__IP_ADDR_LWR_64f, buf_a);
   2108             soc_mem_field_get(unit, L3_ENTRY_IPV6_MULTICASTm, ent_b,
   2109                               IPV6UC_EXT__IP_ADDR_LWR_64f, buf_b);
   2110             SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]);
   2111             SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]);
   2112 
   2113             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV6_MULTICASTm, ent_a,
   2114                                         IPV6UC_EXT__VRF_IDf);
   2115             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV6_MULTICASTm, ent_b,
   2116                                         IPV6UC_EXT__VRF_IDf);
   2117             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2118 
   2119             soc_mem_field_get(unit, L3_ENTRY_IPV6_MULTICASTm, ent_a,
   2120                               IPV6UC_EXT__IP_ADDR_UPR_64f, buf_a);
   2121             soc_mem_field_get(unit, L3_ENTRY_IPV6_MULTICASTm, ent_b,
   2122                               IPV6UC_EXT__IP_ADDR_UPR_64f, buf_b);
   2123             SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]);
   2124             SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]);
   2125 
   2126             return 0;
   2127         case TD2_L3_HASH_KEY_TYPE_V6MC:
   2128         case TD2_L3_HASH_KEY_TYPE_V6L2MC:
   2129         case TD2_L3_HASH_KEY_TYPE_V6L2VPMC:
   2130             return _soc_mem_cmp_l3x2_ip6mcast(unit, ent_a, ent_b);
   2131 
   2132         case TD2_L3_HASH_KEY_TYPE_TRILL:
   2133             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_a,
   2134                                         TRILL__INGRESS_RBRIDGE_NICKNAMEf);
   2135             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_b,
   2136                                         TRILL__INGRESS_RBRIDGE_NICKNAMEf);
   2137             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2138 
   2139             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_a,
   2140                                         TRILL__TREE_IDf);
   2141             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_b,
   2142                                         TRILL__TREE_IDf);
   2143             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2144 
   2145             return 0;
   2146         case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN:
   2147             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_a,
   2148                                         FCOE__MASKED_D_IDf);
   2149             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_b,
   2150                                         FCOE__MASKED_D_IDf);
   2151             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2152 
   2153             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_a,
   2154                                         FCOE__VRF_IDf);
   2155             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_b,
   2156                                         FCOE__VRF_IDf);
   2157             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2158 
   2159             return 0;
   2160         case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT:
   2161             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a,
   2162                                         KEY_TYPE_1f);
   2163             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b,
   2164                                         KEY_TYPE_1f);
   2165             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2166 
   2167             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a,
   2168                                         FCOE_EXT__MASKED_D_IDf);
   2169             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b,
   2170                                         FCOE_EXT__MASKED_D_IDf);
   2171             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2172 
   2173             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a,
   2174                                         FCOE_EXT__VRF_IDf);
   2175             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b,
   2176                                         FCOE_EXT__VRF_IDf);
   2177             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2178 
   2179             return 0;
   2180         case TD2_L3_HASH_KEY_TYPE_FCOE_HOST:
   2181             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_a,
   2182                                         FCOE__D_IDf);
   2183             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_b,
   2184                                         FCOE__D_IDf);
   2185             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2186 
   2187             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_a,
   2188                                         FCOE__VRF_IDf);
   2189             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_b,
   2190                                         FCOE__VRF_IDf);
   2191             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2192 
   2193             return 0;
   2194         case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT:
   2195             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a,
   2196                                         KEY_TYPE_1f);
   2197             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b,
   2198                                         KEY_TYPE_1f);
   2199             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2200 
   2201             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm,  ent_a,
   2202                                         FCOE_EXT__D_IDf);
   2203             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm,  ent_b,
   2204                                         FCOE_EXT__D_IDf);
   2205             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2206 
   2207             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm,  ent_a,
   2208                                         FCOE_EXT__VRF_IDf);
   2209             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm,  ent_b,
   2210                                         FCOE_EXT__VRF_IDf);
   2211             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2212 
   2213             return 0;
   2214         case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP:
   2215             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_a,
   2216                                         FCOE__S_IDf);
   2217             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_b,
   2218                                         FCOE__S_IDf);
   2219             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2220 
   2221             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_a,
   2222                                         FCOE__VRF_IDf);
   2223             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm, ent_b,
   2224                                         FCOE__VRF_IDf);
   2225             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2226 
   2227             return 0;
   2228         case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT:
   2229             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a,
   2230                                         KEY_TYPE_1f);
   2231             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b,
   2232                                         KEY_TYPE_1f);
   2233             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2234 
   2235             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm,  ent_a,
   2236                                         FCOE_EXT__S_IDf);
   2237             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm,  ent_b,
   2238                                         FCOE_EXT__S_IDf);
   2239             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2240 
   2241             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm,  ent_a,
   2242                                         FCOE_EXT__VRF_IDf);
   2243             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm,  ent_b,
   2244                                         FCOE_EXT__VRF_IDf);
   2245             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2246 
   2247             return 0;
   2248         case TD2_L3_HASH_KEY_TYPE_DST_NAT:
   2249             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a,
   2250                                         KEY_TYPE_1f);
   2251             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b,
   2252                                         KEY_TYPE_1f);
   2253             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2254 
   2255             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a,
   2256                                         NAT__VRF_IDf);
   2257             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b,
   2258                                         NAT__VRF_IDf);
   2259             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2260 
   2261             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a,
   2262                                         NAT__IP_ADDRf);
   2263             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b,
   2264                                         NAT__IP_ADDRf);
   2265             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2266 
   2267             return 0;
   2268         case TD2_L3_HASH_KEY_TYPE_DST_NAPT:
   2269             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a,
   2270                                         KEY_TYPE_1f);
   2271             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b,
   2272                                         KEY_TYPE_1f);
   2273             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2274 
   2275             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a,
   2276                                         NAT__VRF_IDf);
   2277             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b,
   2278                                         NAT__VRF_IDf);
   2279             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2280 
   2281             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a,
   2282                                         NAT__IP_ADDRf);
   2283             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b,
   2284                                         NAT__IP_ADDRf);
   2285             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2286 
   2287             val_a = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_a,
   2288                                         NAT__L4_DEST_PORTf);
   2289             val_b = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm, ent_b,
   2290                                         NAT__L4_DEST_PORTf);
   2291             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2292 
   2293             return 0;
   2294         default:
   2295             return 1;
   2296         }
   2297     } else
   2298 #endif /* BCM_TRIDENT2_SUPPORT */
   2299     {
   2300     switch (val_a) {
   2301     case 0: /* IPV4_UNICAST */
   2302         return _soc_mem_cmp_l3x2_ip4ucast(unit, ent_a, ent_b);
   2303     case 1: /* IPV4_MULTICAST */
   2304         return _soc_mem_cmp_l3x2_ip4mcast(unit, ent_a, ent_b);
   2305     case 2: /* IPV6_UNICAST */
   2306         return _soc_mem_cmp_l3x2_ip6ucast(unit, ent_a, ent_b);
   2307     case 3: /* IPV6_MULTICAST */
   2308         return _soc_mem_cmp_l3x2_ip6mcast(unit, ent_a, ent_b);
   2309     case 4: /* CCM_LMEP */
   2310         val_a = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_a, LMEP__SGLPf);
   2311         val_b = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_b, LMEP__SGLPf);
   2312         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2313 
   2314         val_a = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_a, LMEP__VIDf);
   2315         val_b = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_b, LMEP__VIDf);
   2316         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2317 
   2318         return 0;
   2319     case 5: /* CCM_RMEP */
   2320         val_a = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_a, RMEP__SGLPf);
   2321         val_b = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_b, RMEP__SGLPf);
   2322         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2323 
   2324         val_a = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_a, RMEP__VIDf);
   2325         val_b = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_b, RMEP__VIDf);
   2326         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2327 
   2328         val_a = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_a, RMEP__MDLf);
   2329         val_b = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_b, RMEP__MDLf);
   2330         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2331 
   2332         val_a = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_a, RMEP__MEPIDf);
   2333         val_b = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_b, RMEP__MEPIDf);
   2334         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2335 
   2336         return 0;
   2337     case 6: /* TRILL */
   2338         val_a = soc_L3_ENTRY_ONLYm_field32_get
   2339             (unit, ent_a, TRILL__INGRESS_RBRIDGE_NICKNAMEf);
   2340         val_b = soc_L3_ENTRY_ONLYm_field32_get
   2341             (unit, ent_b, TRILL__INGRESS_RBRIDGE_NICKNAMEf);
   2342         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2343 
   2344         val_a = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_a, TRILL__TREE_IDf);
   2345         val_b = soc_L3_ENTRY_ONLYm_field32_get(unit, ent_b, TRILL__TREE_IDf);
   2346         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2347 
   2348         return 0;
   2349     default:
   2350         return 1;
   2351     }
   2352     }
   2353 }
   2354 
   2355 int
   2356 _soc_mem_cmp_l3x2_ip4ucast(int unit, void *ent_a, void *ent_b)
   2357 {
   2358     uint32      type_a, type_b;
   2359     ip_addr_t    ip_a, ip_b;
   2360 
   2361     if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_IPV4_UNICASTm, VRF_IDf)) {
   2362         type_a = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, ent_a, VRF_IDf);
   2363         type_b = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, ent_b, VRF_IDf);
   2364         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2365     }
   2366 
   2367     if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_IPV4_UNICASTm, KEY_TYPEf)) {
   2368         type_a = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, ent_a, KEY_TYPEf);
   2369         type_b = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, ent_b, KEY_TYPEf);
   2370         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2371     } else {
   2372         type_a = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, ent_a, V6f);
   2373         type_b = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, ent_b, V6f);
   2374         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2375 
   2376         type_a = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, ent_a, IPMCf);
   2377         type_b = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, ent_b, IPMCf);
   2378         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2379     }
   2380 
   2381     ip_a = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, ent_a, IP_ADDRf);
   2382     ip_b = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, ent_b, IP_ADDRf);
   2383     SOC_MEM_COMPARE_RETURN(ip_a, ip_b);
   2384 
   2385     return(0);
   2386 }
   2387 
   2388 int
   2389 _soc_mem_cmp_l3x2_ip4mcast(int unit, void *ent_a, void *ent_b)
   2390 {
   2391     uint32      type_a, type_b;
   2392     ip_addr_t    a, b;
   2393     vlan_id_t    vlan_a, vlan_b;
   2394 
   2395     if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_IPV4_MULTICASTm, VRF_IDf)) {
   2396         type_a = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_a, VRF_IDf);
   2397         type_b = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_b, VRF_IDf);
   2398         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2399     }
   2400 #if defined(BCM_TRX_SUPPORT)
   2401     if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_IPV4_MULTICASTm, KEY_TYPE_0f)) {
   2402         type_a = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_a, KEY_TYPE_0f);
   2403         type_b = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_b, KEY_TYPE_0f);
   2404         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2405 
   2406         type_a = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_a, KEY_TYPE_1f);
   2407         type_b = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_b, KEY_TYPE_1f);
   2408         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2409     } else
   2410 #endif /* BCM_TRX_SUPPORT */
   2411     {
   2412         type_a = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_a, V6f);
   2413         type_b = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_b, V6f);
   2414         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2415 
   2416         type_a = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_a, IPMCf);
   2417         type_b = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_b, IPMCf);
   2418         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2419     }
   2420 
   2421     a = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_a, SOURCE_IP_ADDRf);
   2422     b = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_b, SOURCE_IP_ADDRf);
   2423     SOC_MEM_COMPARE_RETURN(a, b);
   2424 
   2425     a = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_a, GROUP_IP_ADDRf);
   2426     b = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_b, GROUP_IP_ADDRf);
   2427     SOC_MEM_COMPARE_RETURN(a, b);
   2428 
   2429     vlan_a = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_a, VLAN_IDf);
   2430     vlan_b = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, ent_b, VLAN_IDf);
   2431     SOC_MEM_COMPARE_RETURN(vlan_a, vlan_b);
   2432 
   2433     return(0);
   2434 }
   2435 
   2436 int
   2437 _soc_mem_cmp_l3x2_ip6ucast(int unit, void *ent_a, void *ent_b)
   2438 {
   2439     uint32      type_a, type_b;
   2440     uint32      a[SOC_MAX_MEM_FIELD_WORDS];
   2441     uint32      b[SOC_MAX_MEM_FIELD_WORDS];
   2442     int         i;
   2443     int         ent_words;
   2444 
   2445 #ifdef BCM_TRIUMPH_SUPPORT
   2446     if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_IPV6_UNICASTm, VRF_IDf)) {
   2447         type_a =
   2448             soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_a, VRF_IDf);
   2449         type_b =
   2450             soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_b, VRF_IDf);
   2451         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2452     } else
   2453 #endif
   2454     if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_IPV6_UNICASTm, VRF_ID_0f)) {
   2455         type_a =
   2456             soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_a, VRF_ID_0f);
   2457         type_b =
   2458             soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_b, VRF_ID_0f);
   2459         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2460     }
   2461 #if defined(BCM_TRX_SUPPORT)
   2462     if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_IPV6_UNICASTm, KEY_TYPE_0f)) {
   2463         type_a = soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_a, KEY_TYPE_0f);
   2464         type_b = soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_b, KEY_TYPE_0f);
   2465         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2466     } else
   2467 #endif /* BCM_TRX_SUPPORT */
   2468     {
   2469         type_a = soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_a, V6_0f);
   2470         type_b = soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_b, V6_0f);
   2471         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2472 
   2473         type_a = soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_a, IPMC_0f);
   2474         type_b = soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_b, IPMC_0f);
   2475         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2476     }
   2477 
   2478     if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_IPV6_UNICASTm, VRF_ID_1f)) {
   2479         type_a =
   2480             soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_a, VRF_ID_1f);
   2481         type_b =
   2482             soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_b, VRF_ID_1f);
   2483         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2484     }
   2485 
   2486 #if defined(BCM_TRX_SUPPORT)
   2487     if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_IPV6_UNICASTm, KEY_TYPE_1f)) {
   2488         type_a = soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_a, KEY_TYPE_1f);
   2489         type_b = soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_b, KEY_TYPE_1f);
   2490         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2491     } else
   2492 #endif /* BCM_TRX_SUPPORT */
   2493     {
   2494         type_a = soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_a, V6_1f);
   2495         type_b = soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_b, V6_1f);
   2496         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2497 
   2498         type_a = soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_a, IPMC_1f);
   2499         type_b = soc_L3_ENTRY_IPV6_UNICASTm_field32_get(unit, ent_b, IPMC_1f);
   2500         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2501     }
   2502 
   2503     soc_mem_field_get(unit, L3_ENTRY_IPV6_UNICASTm, ent_a, IP_ADDR_UPR_64f, a);
   2504     soc_mem_field_get(unit, L3_ENTRY_IPV6_UNICASTm, ent_b, IP_ADDR_UPR_64f, b);
   2505     ent_words = soc_mem_field_length(unit, L3_ENTRY_IPV6_UNICASTm,
   2506                                      IP_ADDR_UPR_64f) / 32;
   2507     for (i = ent_words - 1; i >= 0; i--) {
   2508         SOC_MEM_COMPARE_RETURN(a[i], b[i]);
   2509     }
   2510     soc_mem_field_get(unit, L3_ENTRY_IPV6_UNICASTm, ent_a, IP_ADDR_LWR_64f, a);
   2511     soc_mem_field_get(unit, L3_ENTRY_IPV6_UNICASTm, ent_b, IP_ADDR_LWR_64f, b);
   2512     ent_words = soc_mem_field_length(unit, L3_ENTRY_IPV6_UNICASTm,
   2513                                      IP_ADDR_LWR_64f) / 32;
   2514     for (i = ent_words - 1; i >= 0; i--) {
   2515         SOC_MEM_COMPARE_RETURN(a[i], b[i]);
   2516     }
   2517 
   2518     return(0);
   2519 }
   2520 
   2521 int
   2522 _soc_mem_cmp_l3x2_ip6mcast(int u, void *e_a, void *e_b)
   2523 {
   2524     uint32      type_a, type_b;
   2525     vlan_id_t    vlan_a, vlan_b;
   2526     uint32      a[SOC_MAX_MEM_FIELD_WORDS];
   2527     uint32      b[SOC_MAX_MEM_FIELD_WORDS];
   2528     int         i;
   2529     int         ent_words;
   2530 
   2531 #ifdef BCM_TRIUMPH_SUPPORT
   2532     if (SOC_MEM_FIELD_VALID(u, L3_ENTRY_IPV6_MULTICASTm, VRF_IDf)) {
   2533         type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, VRF_IDf);
   2534         type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, VRF_IDf);
   2535         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2536     } else
   2537 #endif
   2538     if (SOC_MEM_FIELD_VALID(u, L3_ENTRY_IPV6_MULTICASTm, VRF_ID_0f)) {
   2539         type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, VRF_ID_0f);
   2540         type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, VRF_ID_0f);
   2541         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2542     }
   2543 #if defined(BCM_TRX_SUPPORT)
   2544     if (SOC_MEM_FIELD_VALID(u, L3_ENTRY_IPV6_MULTICASTm, KEY_TYPE_0f)) {
   2545         type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, KEY_TYPE_0f);
   2546         type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, KEY_TYPE_0f);
   2547         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2548     } else
   2549 #endif /* BCM_TRX_SUPPORT */
   2550     {
   2551         type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, V6_0f);
   2552         type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, V6_0f);
   2553         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2554 
   2555         type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, IPMC_0f);
   2556         type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, IPMC_0f);
   2557         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2558     }
   2559 
   2560     if (SOC_MEM_FIELD_VALID(u, L3_ENTRY_IPV6_MULTICASTm, VRF_ID_1f)) {
   2561         type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, VRF_ID_1f);
   2562         type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, VRF_ID_1f);
   2563         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2564     }
   2565 
   2566 #if defined(BCM_TRX_SUPPORT)
   2567     if (SOC_MEM_FIELD_VALID(u, L3_ENTRY_IPV6_MULTICASTm, KEY_TYPE_1f)) {
   2568         type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, KEY_TYPE_1f);
   2569         type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, KEY_TYPE_1f);
   2570         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2571     } else
   2572 #endif /* BCM_TRX_SUPPORT */
   2573     {
   2574         type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, V6_1f);
   2575         type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, V6_1f);
   2576         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2577 
   2578         type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, IPMC_1f);
   2579         type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, IPMC_1f);
   2580         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2581     }
   2582 
   2583     if (SOC_MEM_FIELD_VALID(u, L3_ENTRY_IPV6_MULTICASTm, VRF_ID_2f)) {
   2584         type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, VRF_ID_2f);
   2585         type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, VRF_ID_2f);
   2586         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2587     }
   2588 
   2589 #if defined(BCM_TRX_SUPPORT)
   2590     if (SOC_MEM_FIELD_VALID(u, L3_ENTRY_IPV6_MULTICASTm, KEY_TYPE_2f)) {
   2591         type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, KEY_TYPE_2f);
   2592         type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, KEY_TYPE_2f);
   2593         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2594     } else
   2595 #endif /* BCM_TRX_SUPPORT */
   2596     {
   2597         type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, V6_2f);
   2598         type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, V6_2f);
   2599         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2600 
   2601         type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, IPMC_2f);
   2602         type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, IPMC_2f);
   2603         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2604     }
   2605 
   2606     if (SOC_MEM_FIELD_VALID(u, L3_ENTRY_IPV6_MULTICASTm, VRF_ID_3f)) {
   2607         type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, VRF_ID_3f);
   2608         type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, VRF_ID_3f);
   2609         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2610     }
   2611 
   2612 #if defined(BCM_TRX_SUPPORT)
   2613     if (SOC_MEM_FIELD_VALID(u, L3_ENTRY_IPV6_MULTICASTm, KEY_TYPE_3f)) {
   2614         type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, KEY_TYPE_3f);
   2615         type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, KEY_TYPE_3f);
   2616         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2617     } else
   2618 #endif /* BCM_TRX_SUPPORT */
   2619     {
   2620         type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, V6_3f);
   2621         type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, V6_3f);
   2622         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2623 
   2624         type_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, IPMC_3f);
   2625         type_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, IPMC_3f);
   2626         SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2627     }
   2628 
   2629     soc_mem_field_get(u, L3_ENTRY_IPV6_MULTICASTm,
   2630                       e_a, SOURCE_IP_ADDR_UPR_64f, a);
   2631     soc_mem_field_get(u, L3_ENTRY_IPV6_MULTICASTm,
   2632                       e_b, SOURCE_IP_ADDR_UPR_64f, b);
   2633     ent_words = soc_mem_field_length(u, L3_ENTRY_IPV6_MULTICASTm,
   2634                                      SOURCE_IP_ADDR_UPR_64f) / 32;
   2635     for (i = ent_words - 1; i >= 0; i--) {
   2636         SOC_MEM_COMPARE_RETURN(a[i], b[i]);
   2637     }
   2638 
   2639     soc_mem_field_get(u, L3_ENTRY_IPV6_MULTICASTm,
   2640                       e_a, SOURCE_IP_ADDR_LWR_64f, a);
   2641     soc_mem_field_get(u, L3_ENTRY_IPV6_MULTICASTm,
   2642                       e_b, SOURCE_IP_ADDR_LWR_64f, b);
   2643     ent_words = soc_mem_field_length(u, L3_ENTRY_IPV6_MULTICASTm,
   2644                                      SOURCE_IP_ADDR_LWR_64f) / 32;
   2645     for (i = ent_words - 1; i >= 0; i--) {
   2646         SOC_MEM_COMPARE_RETURN(a[i], b[i]);
   2647     }
   2648 
   2649     soc_mem_field_get(u, L3_ENTRY_IPV6_MULTICASTm,
   2650                       e_a, GROUP_IP_ADDR_UPR_56f, a);
   2651     soc_mem_field_get(u, L3_ENTRY_IPV6_MULTICASTm,
   2652                       e_b, GROUP_IP_ADDR_UPR_56f, b);
   2653     ent_words = soc_mem_field_length(u, L3_ENTRY_IPV6_MULTICASTm,
   2654                                      GROUP_IP_ADDR_UPR_56f) / 32;
   2655     for (i = ent_words - 1; i >= 0; i--) {
   2656         SOC_MEM_COMPARE_RETURN(a[i], b[i]);
   2657     }
   2658 
   2659     soc_mem_field_get(u, L3_ENTRY_IPV6_MULTICASTm,
   2660                       e_a, GROUP_IP_ADDR_LWR_64f, a);
   2661     soc_mem_field_get(u, L3_ENTRY_IPV6_MULTICASTm,
   2662                       e_b, GROUP_IP_ADDR_LWR_64f, b);
   2663     ent_words = soc_mem_field_length(u, L3_ENTRY_IPV6_MULTICASTm,
   2664                                      GROUP_IP_ADDR_LWR_64f) / 32;
   2665     for (i = ent_words - 1; i >= 0; i--) {
   2666         SOC_MEM_COMPARE_RETURN(a[i], b[i]);
   2667     }
   2668 
   2669 #ifdef BCM_TRIUMPH_SUPPORT
   2670     if (SOC_MEM_FIELD_VALID(u, L3_ENTRY_IPV6_MULTICASTm, VLAN_IDf)) {
   2671         vlan_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, VLAN_IDf);
   2672         vlan_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, VLAN_IDf);
   2673         SOC_MEM_COMPARE_RETURN(vlan_a, vlan_b);
   2674     } else
   2675 #endif
   2676     {
   2677         vlan_a = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_a, VLAN_ID_0f);
   2678         vlan_b = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(u, e_b, VLAN_ID_0f);
   2679         SOC_MEM_COMPARE_RETURN(vlan_a, vlan_b);
   2680     }
   2681 
   2682     return(0);
   2683 }
   2684 
   2685 /*
   2686  * Compares both mask and address. Not a masked compare.
   2687  */
   2688 int
   2689 _soc_mem_cmp_lpm(int u, void *e_a, void *e_b)
   2690 {
   2691     uint32      a;
   2692     uint32      b;
   2693     soc_mem_t   mem = L3_DEFIPm;
   2694 
   2695     a = soc_mem_field32_get(u, mem, e_a, VALID1f);
   2696     b = soc_mem_field32_get(u, mem, e_b, VALID1f);
   2697 
   2698     if (a && b) {
   2699         a = soc_mem_field32_get(u, mem, e_a, MASK1f);
   2700         b = soc_mem_field32_get(u, mem, e_b, MASK1f);
   2701         SOC_MEM_COMPARE_RETURN(a, b);
   2702 
   2703         a = soc_mem_field32_get(u, mem, e_a, IP_ADDR1f);
   2704         b = soc_mem_field32_get(u, mem, e_b, IP_ADDR1f);
   2705         SOC_MEM_COMPARE_RETURN(a, b);
   2706 
   2707         if (SOC_MEM_FIELD_VALID(u, mem, VRF_ID_1f)) {
   2708             a = soc_mem_field32_get(u, mem, e_a, VRF_ID_1f);
   2709             b = soc_mem_field32_get(u, mem, e_b, VRF_ID_1f);
   2710             SOC_MEM_COMPARE_RETURN(a, b);
   2711         }
   2712 
   2713         a = soc_mem_field32_get(u, mem, e_a, MODE1f);
   2714         b = soc_mem_field32_get(u, mem, e_b, MODE1f);
   2715         SOC_MEM_COMPARE_RETURN(a, b);
   2716 
   2717         if (a == 0) {
   2718             return(0); /* IPV4 entry */
   2719         }
   2720     }
   2721 
   2722     a = soc_mem_field32_get(u, mem, e_a, VALID0f);
   2723     b = soc_mem_field32_get(u, mem, e_b, VALID0f);
   2724 
   2725     if (a && b) {
   2726         a = soc_mem_field32_get(u, mem, e_a, MASK0f);
   2727         b = soc_mem_field32_get(u, mem, e_b, MASK0f);
   2728         SOC_MEM_COMPARE_RETURN(a, b);
   2729 
   2730         a = soc_mem_field32_get(u, mem, e_a, IP_ADDR0f);
   2731         b = soc_mem_field32_get(u, mem, e_b, IP_ADDR0f);
   2732         SOC_MEM_COMPARE_RETURN(a, b);
   2733 
   2734         if (SOC_MEM_FIELD_VALID(u, mem, VRF_ID_0f)) {
   2735             a = soc_mem_field32_get(u, mem, e_a, VRF_ID_0f);
   2736             b = soc_mem_field32_get(u, mem, e_b, VRF_ID_0f);
   2737             SOC_MEM_COMPARE_RETURN(a, b);
   2738         }
   2739 
   2740         a = soc_mem_field32_get(u, mem, e_a, MODE0f);
   2741         b = soc_mem_field32_get(u, mem, e_b, MODE0f);
   2742         SOC_MEM_COMPARE_RETURN(a, b);
   2743         if (a == 0) {
   2744             return(0); /* IPV4 entry */
   2745         }
   2746     }
   2747 
   2748     a = soc_mem_field32_get(u, mem, e_a, VALID1f);
   2749     b = soc_mem_field32_get(u, mem, e_b, VALID1f);
   2750     SOC_MEM_COMPARE_RETURN(a, b);
   2751     a = soc_mem_field32_get(u, mem, e_a, VALID0f);
   2752     b = soc_mem_field32_get(u, mem, e_b, VALID0f);
   2753     SOC_MEM_COMPARE_RETURN(a, b);
   2754 
   2755     return (0);
   2756 }
   2757 
   2758 #endif /* BCM_FIREBOLT_SUPPORT */
   2759 
   2760 #ifdef BCM_XGS3_SWITCH_SUPPORT
   2761 int
   2762 _soc_mem_cmp_vlan_mac(int unit, void *ent_a, void *ent_b)
   2763 {
   2764     sal_mac_addr_t mac_a, mac_b;
   2765 
   2766     soc_VLAN_MACm_mac_addr_get(unit, ent_a, MAC_ADDRf, mac_a);
   2767     soc_VLAN_MACm_mac_addr_get(unit, ent_b, MAC_ADDRf, mac_b);
   2768 
   2769     return ENET_CMP_MACADDR(mac_a, mac_b);
   2770 }
   2771 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   2772 
   2773 #ifdef BCM_TRX_SUPPORT
   2774 int
   2775 _soc_mem_cmp_vlan_mac_tr(int unit, void *ent_a, void *ent_b)
   2776 {
   2777     soc_mem_t mem;
   2778     sal_mac_addr_t mac_a, mac_b;
   2779     uint32      type_a, type_b;
   2780 #ifdef BCM_TRIDENT2_SUPPORT
   2781     uint32 key_a[SOC_MAX_MEM_FIELD_WORDS], key_b[SOC_MAX_MEM_FIELD_WORDS];
   2782     sal_memset(key_a, 0, sizeof(key_a));
   2783     sal_memset(key_b, 0, sizeof(key_b));
   2784 #endif
   2785 
   2786     mem = VLAN_MACm;
   2787 
   2788 #if defined(BCM_TRIDENT3_SUPPORT)
   2789     if (soc_mem_is_valid(unit, VLAN_XLATE_2_DOUBLEm)) {
   2790         mem = VLAN_XLATE_2_DOUBLEm;
   2791     }
   2792 #endif /* BCM_TRIDENT3_SUPPORT */
   2793 
   2794     type_a = soc_mem_field32_get(unit, mem, ent_a, KEY_TYPEf);
   2795     type_b = soc_mem_field32_get(unit, mem, ent_b, KEY_TYPEf);
   2796     SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2797 
   2798     switch (type_a) {
   2799     case 3: /* VLAN_MAC */
   2800 #ifdef BCM_TRIDENT2_SUPPORT
   2801         if (SOC_IS_TD2_TT2(unit)) {
   2802 #if defined(BCM_TRIDENT3_SUPPORT)
   2803             if (mem == VLAN_XLATE_2_DOUBLEm) {
   2804                 soc_mem_field_get(unit, mem, ent_a, MAC__KEY_0f, key_a);
   2805                 soc_mem_field_get(unit, mem, ent_b, MAC__KEY_0f, key_b);
   2806             } else
   2807 #endif
   2808             {
   2809                 soc_mem_field_get(unit, mem, ent_a, MAC__KEYf, key_a);
   2810                 soc_mem_field_get(unit, mem, ent_b, MAC__KEYf, key_b);
   2811             }
   2812             return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   2813         } else
   2814 #endif
   2815         {
   2816             soc_mem_mac_addr_get(unit, mem, ent_a, MAC_ADDRf, mac_a);
   2817             soc_mem_mac_addr_get(unit, mem, ent_b, MAC_ADDRf, mac_b);
   2818             return ENET_CMP_MACADDR(mac_a, mac_b);
   2819         }
   2820 #ifdef BCM_TRIUMPH2_SUPPORT
   2821     case 7: /* HPAE (MAC_IP_BIND) */
   2822 #ifdef BCM_TRIDENT2_SUPPORT
   2823         if (SOC_IS_TD2_TT2(unit)) {
   2824 #if defined(BCM_TRIDENT3_SUPPORT)
   2825             if (mem == VLAN_XLATE_2_DOUBLEm) {
   2826                 soc_mem_field_get(unit, mem, ent_a, MAC_IP_BIND__KEY_0f, key_a);
   2827                 soc_mem_field_get(unit, mem, ent_b, MAC_IP_BIND__KEY_0f, key_b);
   2828             } else
   2829 #endif
   2830             {
   2831                 soc_mem_field_get(unit, mem, ent_a, MAC_IP_BIND__KEYf, key_a);
   2832                 soc_mem_field_get(unit, mem, ent_b, MAC_IP_BIND__KEYf, key_b);
   2833             }
   2834             return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   2835         } else
   2836 #endif
   2837         {
   2838             type_a = soc_mem_field32_get(unit, mem, ent_a, MAC_IP_BIND__SIPf);
   2839             type_b = soc_mem_field32_get(unit, mem, ent_b, MAC_IP_BIND__SIPf);
   2840             SOC_MEM_COMPARE_RETURN(type_a, type_b);
   2841 
   2842             return 0;
   2843         }
   2844 #endif /* BCM_TRIUMPH2_SUPPORT */
   2845 #ifdef BCM_TRIDENT2_SUPPORT
   2846     case 14:
   2847         if (SOC_IS_TD2_TT2(unit)) {
   2848             sal_memset(key_a, 0, sizeof(key_a));
   2849             sal_memset(key_b, 0, sizeof(key_b));
   2850 #if defined(BCM_TRIDENT3_SUPPORT)
   2851             if (mem == VLAN_XLATE_2_DOUBLEm) {
   2852                 soc_mem_field_get(unit, mem, ent_a, MAC_PORT__KEY_0f, key_a);
   2853                 soc_mem_field_get(unit, mem, ent_b, MAC_PORT__KEY_0f, key_b);
   2854             } else
   2855 #endif
   2856             {
   2857                 soc_mem_field_get(unit, mem, ent_a, MAC_PORT__KEYf, key_a);
   2858                 soc_mem_field_get(unit, mem, ent_b, MAC_PORT__KEYf, key_b);
   2859             }
   2860             return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   2861         }
   2862 #endif
   2863     default:
   2864         return 1;
   2865     }
   2866 }
   2867 
   2868 int
   2869 _soc_mem_cmp_vlan_xlate_tr(int unit, void *ent_a, void *ent_b)
   2870 {
   2871     uint32 val_a, val_b;
   2872     soc_mem_t vlan_xlate_mem = VLAN_XLATEm;
   2873 
   2874 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   2875     uint32 key_a[SOC_MAX_MEM_FIELD_WORDS], key_b[SOC_MAX_MEM_FIELD_WORDS];
   2876     sal_memset(key_a, 0, sizeof(key_a));
   2877     sal_memset(key_b, 0, sizeof(key_b));
   2878 #endif
   2879 #if defined(BCM_TRIUMPH3_SUPPORT)
   2880     if (SOC_IS_TRIUMPH3(unit)) {
   2881         soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_a, VALID_0f, &val_a);
   2882         soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_b, VALID_0f, &val_b);
   2883         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2884 
   2885         soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_a, KEY_TYPE_0f, &val_a);
   2886         soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_b, KEY_TYPE_0f, &val_b);
   2887         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2888 
   2889         switch (val_a) {
   2890             case TR3_VLXLT_X_HASH_KEY_TYPE_IVID_OVID:
   2891             case TR3_VLXLT_X_HASH_KEY_TYPE_OVID:
   2892             case TR3_VLXLT_X_HASH_KEY_TYPE_IVID:
   2893             case TR3_VLXLT_X_HASH_KEY_TYPE_OTAG:
   2894             case TR3_VLXLT_X_HASH_KEY_TYPE_ITAG:
   2895             case TR3_VLXLT_X_HASH_KEY_TYPE_PRI_CFI:
   2896             case TR3_VLXLT_X_HASH_KEY_TYPE_IVID_OVID_SVP:
   2897             case TR3_VLXLT_X_HASH_KEY_TYPE_OVID_SVP:
   2898                 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_a, VALID_1f, &val_a);
   2899                 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_b, VALID_1f, &val_b);
   2900                 SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2901 
   2902                 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_a, KEY_TYPE_1f, &val_a);
   2903                 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_b, KEY_TYPE_1f, &val_b);
   2904                 SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2905 
   2906                 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_a, XLATE__KEY_0f, key_a);
   2907                 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_b, XLATE__KEY_0f, key_b);
   2908                 return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   2909             case TR3_VLXLT_HASH_KEY_TYPE_IVID_OVID:
   2910             case TR3_VLXLT_HASH_KEY_TYPE_OVID:
   2911             case TR3_VLXLT_HASH_KEY_TYPE_IVID:
   2912             case TR3_VLXLT_HASH_KEY_TYPE_OTAG:
   2913             case TR3_VLXLT_HASH_KEY_TYPE_ITAG:
   2914             case TR3_VLXLT_HASH_KEY_TYPE_PRI_CFI:
   2915             case TR3_VLXLT_HASH_KEY_TYPE_IVID_OVID_SVP:
   2916             case TR3_VLXLT_HASH_KEY_TYPE_OVID_SVP:
   2917                 soc_mem_field_get(unit, VLAN_XLATE_1m, ent_a, XLATE__KEYf, key_a);
   2918                 soc_mem_field_get(unit, VLAN_XLATE_1m, ent_b, XLATE__KEYf, key_b);
   2919                 return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   2920             case TR3_VLXLT_HASH_KEY_TYPE_VLAN_MAC:
   2921                 soc_mem_field_get(unit, VLAN_XLATE_1m, ent_a, VLAN_MAC__KEYf, key_a);
   2922                 soc_mem_field_get(unit, VLAN_XLATE_1m, ent_b, VLAN_MAC__KEYf, key_b);
   2923                 return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   2924             case TR3_VLXLT_HASH_KEY_TYPE_VIF:
   2925             case TR3_VLXLT_HASH_KEY_TYPE_VIF_VLAN:
   2926             case TR3_VLXLT_HASH_KEY_TYPE_VIF_CVLAN:
   2927             case TR3_VLXLT_HASH_KEY_TYPE_VIF_OTAG:
   2928             case TR3_VLXLT_HASH_KEY_TYPE_VIF_ITAG:
   2929                 soc_mem_field_get(unit, VLAN_XLATE_1m, ent_a, VIF__KEYf, key_a);
   2930                 soc_mem_field_get(unit, VLAN_XLATE_1m, ent_b, VIF__KEYf, key_b);
   2931                 return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   2932             case TR3_VLXLT_HASH_KEY_TYPE_L2GRE_DIP:
   2933                 soc_mem_field_get(unit, VLAN_XLATE_1m, ent_a, L2GRE_DIP__KEYf, key_a);
   2934                 soc_mem_field_get(unit, VLAN_XLATE_1m, ent_b, L2GRE_DIP__KEYf, key_b);
   2935                 return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   2936             case TR3_VLXLT_HASH_KEY_TYPE_HPAE:
   2937                 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_a, VALID_1f, &val_a);
   2938                 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_b, VALID_1f, &val_b);
   2939                 SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2940 
   2941                 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_a, KEY_TYPE_1f, &val_a);
   2942                 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_b, KEY_TYPE_1f, &val_b);
   2943                 SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2944 
   2945                 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_a, MAC_IP_BIND__KEY_0f, key_a);
   2946                 soc_mem_field_get(unit, VLAN_XLATE_EXTDm, ent_b, MAC_IP_BIND__KEY_0f, key_b);
   2947                 return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   2948             default:
   2949                 return 1;
   2950         }
   2951     }
   2952 #endif
   2953 #if defined(BCM_TRIDENT3_SUPPORT)
   2954     if (soc_mem_is_valid(unit, VLAN_XLATE_1_DOUBLEm)) {
   2955         vlan_xlate_mem = VLAN_XLATE_1_DOUBLEm;
   2956     }
   2957 #endif /* BCM_TRIDENT3_SUPPORT */
   2958     val_a = soc_mem_field32_get(unit, vlan_xlate_mem, ent_a, KEY_TYPEf);
   2959     val_b = soc_mem_field32_get(unit, vlan_xlate_mem, ent_b, KEY_TYPEf);
   2960     SOC_MEM_COMPARE_RETURN(val_a, val_b);
   2961 #if defined(BCM_TRIDENT2_SUPPORT)
   2962     if (SOC_IS_TD2_TT2(unit)) {
   2963 #if defined(BCM_TRIDENT3_SUPPORT)
   2964         if (vlan_xlate_mem == VLAN_XLATE_1_DOUBLEm) {
   2965             switch (val_a) {
   2966             case TD3_VLXLT_HASH_KEY_TYPE_IVID_OVID:
   2967             case TD3_VLXLT_HASH_KEY_TYPE_OTAG:
   2968             case TD3_VLXLT_HASH_KEY_TYPE_ITAG:
   2969             case TD3_VLXLT_HASH_KEY_TYPE_OVID:
   2970             case TD3_VLXLT_HASH_KEY_TYPE_IVID:
   2971             case TD3_VLXLT_HASH_KEY_TYPE_PRI_CFI:
   2972             case TD3_VLXLT_HASH_KEY_TYPE_IVID_OVID_VSAN:
   2973             case TD3_VLXLT_HASH_KEY_TYPE_IVID_VSAN:
   2974             case TD3_VLXLT_HASH_KEY_TYPE_OVID_VSAN:
   2975                 soc_mem_field_get(unit, vlan_xlate_mem, ent_a, XLATE__KEY_0f, key_a);
   2976                 soc_mem_field_get(unit, vlan_xlate_mem, ent_b, XLATE__KEY_0f, key_b);
   2977                 return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   2978 
   2979             case TD3_VLXLT_HASH_KEY_TYPE_VIF:
   2980             case TD3_VLXLT_HASH_KEY_TYPE_VIF_VLAN:
   2981             case TD3_VLXLT_HASH_KEY_TYPE_VIF_CVLAN:
   2982             case TD3_VLXLT_HASH_KEY_TYPE_VIF_OTAG:
   2983             case TD3_VLXLT_HASH_KEY_TYPE_VIF_ITAG:
   2984                 soc_mem_field_get(unit, vlan_xlate_mem, ent_a, VIF__KEY_0f, key_a);
   2985                 soc_mem_field_get(unit, vlan_xlate_mem, ent_b, VIF__KEY_0f, key_b);
   2986                 return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   2987 
   2988             case TD3_VLXLT_HASH_KEY_TYPE_L2GRE_DIP:
   2989                 soc_mem_field_get(unit, vlan_xlate_mem, ent_a, L2GRE_DIP__KEY_0f, key_a);
   2990                 soc_mem_field_get(unit, vlan_xlate_mem, ent_b, L2GRE_DIP__KEY_0f, key_b);
   2991                 return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   2992 
   2993             case TD3_VLXLT_HASH_KEY_TYPE_VXLAN_DIP:
   2994                 soc_mem_field_get(unit, vlan_xlate_mem, ent_a, VXLAN_DIP__KEY_0f, key_a);
   2995                 soc_mem_field_get(unit, vlan_xlate_mem, ent_b, VXLAN_DIP__KEY_0f, key_b);
   2996                 return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   2997 
   2998             /* VLAN_MAC table */
   2999             case TD3_VLXLT_HASH_KEY_TYPE_VLAN_MAC:
   3000             case TD3_VLXLT_HASH_KEY_TYPE_HPAE:
   3001             case TD3_VLXLT_HASH_KEY_TYPE_VLAN_MAC_PORT:
   3002                 return _soc_mem_cmp_vlan_mac_tr(unit, ent_a, ent_b);
   3003 
   3004             default:
   3005                 return 1;
   3006             }
   3007         } else
   3008 #endif /* BCM_TRIDENT3_SUPPORT */
   3009         {
   3010         switch (val_a) {
   3011         case TD2_VLXLT_HASH_KEY_TYPE_IVID_OVID:
   3012         case TD2_VLXLT_HASH_KEY_TYPE_OTAG:
   3013         case TD2_VLXLT_HASH_KEY_TYPE_ITAG:
   3014         case TD2_VLXLT_HASH_KEY_TYPE_OVID:
   3015         case TD2_VLXLT_HASH_KEY_TYPE_IVID:
   3016         case TD2_VLXLT_HASH_KEY_TYPE_PRI_CFI:
   3017         case TD2_VLXLT_HASH_KEY_TYPE_IVID_OVID_VSAN:
   3018         case TD2_VLXLT_HASH_KEY_TYPE_IVID_VSAN:
   3019         case TD2_VLXLT_HASH_KEY_TYPE_OVID_VSAN:
   3020                 soc_mem_field_get(unit, vlan_xlate_mem, ent_a, XLATE__KEYf, key_a);
   3021                 soc_mem_field_get(unit, vlan_xlate_mem, ent_b, XLATE__KEYf, key_b);
   3022             return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   3023 
   3024         case TD2_VLXLT_HASH_KEY_TYPE_VIF:
   3025         case TD2_VLXLT_HASH_KEY_TYPE_VIF_VLAN:
   3026         case TD2_VLXLT_HASH_KEY_TYPE_VIF_CVLAN:
   3027         case TD2_VLXLT_HASH_KEY_TYPE_VIF_OTAG:
   3028         case TD2_VLXLT_HASH_KEY_TYPE_VIF_ITAG:
   3029                 soc_mem_field_get(unit, vlan_xlate_mem, ent_a, VIF__KEYf, key_a);
   3030                 soc_mem_field_get(unit, vlan_xlate_mem, ent_b, VIF__KEYf, key_b);
   3031             return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   3032 
   3033         case TD2_VLXLT_HASH_KEY_TYPE_L2GRE_DIP:
   3034                 soc_mem_field_get(unit, vlan_xlate_mem, ent_a, L2GRE_DIP__KEYf, key_a);
   3035                 soc_mem_field_get(unit, vlan_xlate_mem, ent_b, L2GRE_DIP__KEYf, key_b);
   3036             return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   3037 
   3038         case TD2_VLXLT_HASH_KEY_TYPE_VXLAN_DIP:
   3039                 soc_mem_field_get(unit, vlan_xlate_mem, ent_a, VXLAN_DIP__KEYf, key_a);
   3040                 soc_mem_field_get(unit, vlan_xlate_mem, ent_b, VXLAN_DIP__KEYf, key_b);
   3041             return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   3042 
   3043         /* VLAN_MAC table */
   3044         case TD2_VLXLT_HASH_KEY_TYPE_VLAN_MAC:
   3045         case TD2_VLXLT_HASH_KEY_TYPE_HPAE:
   3046         case TD2_VLXLT_HASH_KEY_TYPE_VLAN_MAC_PORT:
   3047             return _soc_mem_cmp_vlan_mac_tr(unit, ent_a, ent_b);
   3048 
   3049         default:
   3050             return 1;
   3051         }
   3052         }
   3053     } else
   3054 #endif
   3055     {
   3056         switch (val_a) {
   3057         case 3: /* VLAN_MAC */
   3058         case 7: /* HPAE (MAC_IP_BIND) */
   3059             return _soc_mem_cmp_vlan_mac_tr(unit, ent_a, ent_b);
   3060 
   3061         case 0: /* IVID_OVID */
   3062         case 1: /* OTAG */
   3063         case 2: /* ITAG */
   3064         case 4: /* OVID */
   3065         case 5: /* IVID */
   3066         case 6: /* PRI_CFI */
   3067             val_a = soc_VLAN_XLATEm_field32_get(unit, ent_a, GLPf);
   3068             val_b = soc_VLAN_XLATEm_field32_get(unit, ent_b, GLPf);
   3069             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3070 
   3071             val_a = soc_VLAN_XLATEm_field32_get(unit, ent_a, INCOMING_VIDSf);
   3072             val_b = soc_VLAN_XLATEm_field32_get(unit, ent_b, INCOMING_VIDSf);
   3073             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3074 
   3075             return 0;
   3076 
   3077         case 9: /* VIF_VLAN */
   3078             val_a = soc_VLAN_XLATEm_field32_get(unit, ent_a, VIF__VLANf);
   3079             val_b = soc_VLAN_XLATEm_field32_get(unit, ent_b, VIF__VLANf);
   3080             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3081             /* fall through to case for VIF */
   3082 
   3083         case 8: /* VIF */
   3084             val_a = soc_VLAN_XLATEm_field32_get(unit, ent_a, VIF__GLPf);
   3085             val_b = soc_VLAN_XLATEm_field32_get(unit, ent_b, VIF__GLPf);
   3086             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3087 
   3088             val_a = soc_VLAN_XLATEm_field32_get(unit, ent_a, VIF__SRC_VIFf);
   3089             val_b = soc_VLAN_XLATEm_field32_get(unit, ent_b, VIF__SRC_VIFf);
   3090             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3091 
   3092             return 0;
   3093 
   3094         default:
   3095             return 1;
   3096         }
   3097     }
   3098 }
   3099 
   3100 int
   3101 _soc_mem_cmp_egr_vlan_xlate_tr(int unit, void *ent_a, void *ent_b)
   3102 {
   3103     sal_mac_addr_t mac_a, mac_b;
   3104     uint32 val_a, val_b;
   3105 #if defined(BCM_TRIDENT2_SUPPORT)
   3106     uint32 key_a[SOC_MAX_MEM_FIELD_WORDS], key_b[SOC_MAX_MEM_FIELD_WORDS];
   3107     sal_memset(key_a, 0, sizeof(key_a));
   3108     sal_memset(key_b, 0, sizeof(key_b));
   3109 #endif
   3110     if (SOC_MEM_FIELD_VALID(unit, EGR_VLAN_XLATEm, ENTRY_TYPEf)) {
   3111         val_a = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_a, ENTRY_TYPEf);
   3112         val_b = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_b, ENTRY_TYPEf);
   3113         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3114 
   3115         switch (val_a) {
   3116         case 0: /* VLAN_XLATE */
   3117         case 1: /* VLAN_XLATE_DVP */
   3118         case 2: /* VLAN_XLATE_WLAN */
   3119 #if defined(BCM_TRIDENT2_SUPPORT)
   3120             if (SOC_IS_TD2_TT2(unit)) {
   3121                 soc_mem_field_get(unit, EGR_VLAN_XLATEm, ent_a, XLATE__KEYf, key_a);
   3122                 soc_mem_field_get(unit, EGR_VLAN_XLATEm, ent_b, XLATE__KEYf, key_b);
   3123                 return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   3124             } else
   3125 #endif
   3126             if (SOC_IS_TD_TT(unit)) {
   3127                 val_a = soc_EGR_VLAN_XLATEm_field32_get
   3128                     (unit, ent_a, DST_MODIDf);
   3129                 val_b = soc_EGR_VLAN_XLATEm_field32_get
   3130                     (unit, ent_b, DST_MODIDf);
   3131                 SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3132 
   3133                 val_a = soc_EGR_VLAN_XLATEm_field32_get
   3134                     (unit, ent_a, DST_PORTf);
   3135                 val_b = soc_EGR_VLAN_XLATEm_field32_get
   3136                     (unit, ent_b, DST_PORTf);
   3137                 SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3138             } else if (SOC_MEM_FIELD_VALID(unit, EGR_VLAN_XLATEm, DVPf)) {
   3139                 val_a = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_a, DVPf);
   3140                 val_b = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_b, DVPf);
   3141                 SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3142             } else {
   3143                 val_a = soc_EGR_VLAN_XLATEm_field32_get
   3144                     (unit, ent_a, PORT_GROUP_IDf);
   3145                 val_b = soc_EGR_VLAN_XLATEm_field32_get
   3146                     (unit, ent_b, PORT_GROUP_IDf);
   3147                 SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3148             }
   3149 
   3150             val_a = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_a, OVIDf);
   3151             val_b = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_b, OVIDf);
   3152             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3153 
   3154             val_a = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_a, IVIDf);
   3155             val_b = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_b, IVIDf);
   3156             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3157 
   3158             return 0;
   3159 
   3160         case 3: /* ISID_XLATE */
   3161         case 4: /* ISID_DVP_XLATE */
   3162             val_a = soc_EGR_VLAN_XLATEm_field32_get
   3163                 (unit, ent_a, MIM_ISID__VFIf);
   3164             val_b = soc_EGR_VLAN_XLATEm_field32_get
   3165                 (unit, ent_b, MIM_ISID__VFIf);
   3166             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3167 
   3168             val_a = soc_EGR_VLAN_XLATEm_field32_get
   3169                 (unit, ent_a, MIM_ISID__DVPf);
   3170             val_b = soc_EGR_VLAN_XLATEm_field32_get
   3171                 (unit, ent_b, MIM_ISID__DVPf);
   3172             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3173 
   3174             return 0;
   3175 
   3176         case 5: /* WLAN_SVP_TUNNEL */
   3177         case 6: /* WLAN_SVP_BSSID */
   3178 #if defined(BCM_TRIDENT2_SUPPORT)
   3179             if (SOC_IS_TD2_TT2(unit)) {
   3180                 soc_mem_field_get(unit, EGR_VLAN_XLATEm, ent_a, L2GRE_VFI__KEYf, key_a);
   3181                 soc_mem_field_get(unit, EGR_VLAN_XLATEm, ent_b, L2GRE_VFI__KEYf, key_b);
   3182                 return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   3183             } else
   3184 #endif
   3185             {
   3186                 val_a = soc_EGR_VLAN_XLATEm_field32_get
   3187                     (unit, ent_a, WLAN_SVP__RIDf);
   3188                 val_b = soc_EGR_VLAN_XLATEm_field32_get
   3189                     (unit, ent_b, WLAN_SVP__RIDf);
   3190                 SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3191 
   3192                 soc_mem_mac_addr_get
   3193                     (unit, EGR_VLAN_XLATEm, ent_a, WLAN_SVP__BSSIDf, mac_a);
   3194                 soc_mem_mac_addr_get
   3195                     (unit, EGR_VLAN_XLATEm, ent_b, WLAN_SVP__BSSIDf, mac_b);
   3196                 return ENET_CMP_MACADDR(mac_a, mac_b);
   3197             }
   3198         case 7: /* WLAN_SVP_BSSID_RID */
   3199 #if defined(BCM_TRIDENT2_SUPPORT)
   3200             if (SOC_IS_TD2_TT2(unit)) {
   3201                 soc_mem_field_get(unit, EGR_VLAN_XLATEm, ent_a, XLATE__KEYf, key_a);
   3202                 soc_mem_field_get(unit, EGR_VLAN_XLATEm, ent_b, XLATE__KEYf, key_b);
   3203                 return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   3204             } else
   3205 #endif
   3206             {
   3207                 val_a = soc_EGR_VLAN_XLATEm_field32_get
   3208                     (unit, ent_a, WLAN_SVP__RIDf);
   3209                 val_b = soc_EGR_VLAN_XLATEm_field32_get
   3210                     (unit, ent_b, WLAN_SVP__RIDf);
   3211                 SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3212 
   3213                 soc_mem_mac_addr_get
   3214                     (unit, EGR_VLAN_XLATEm, ent_a, WLAN_SVP__BSSIDf, mac_a);
   3215                 soc_mem_mac_addr_get
   3216                     (unit, EGR_VLAN_XLATEm, ent_b, WLAN_SVP__BSSIDf, mac_b);
   3217                 return ENET_CMP_MACADDR(mac_a, mac_b);
   3218             }
   3219 #ifdef BCM_TRIDENT2_SUPPORT
   3220       case 8:
   3221       case 9:
   3222           if (SOC_IS_TD2_TT2(unit)) {
   3223               soc_mem_field_get(unit, EGR_VLAN_XLATEm, ent_a, VXLAN_VFI__KEYf, key_a);
   3224               soc_mem_field_get(unit, EGR_VLAN_XLATEm, ent_b, VXLAN_VFI__KEYf, key_b);
   3225               return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   3226           }
   3227 #endif
   3228         default:
   3229             return 1;
   3230         }
   3231     }
   3232 
   3233     val_a = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_a, PORT_GROUP_IDf);
   3234     val_b = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_b, PORT_GROUP_IDf);
   3235     SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3236 
   3237     val_a = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_a, IVIDf);
   3238     val_b = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_b, IVIDf);
   3239     SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3240 
   3241     val_a = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_a, OVIDf);
   3242     val_b = soc_EGR_VLAN_XLATEm_field32_get(unit, ent_b, OVIDf);
   3243     SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3244 
   3245     return 0;
   3246 }
   3247 
   3248 #ifdef BCM_TRIUMPH_SUPPORT
   3249 int
   3250 _soc_mem_cmp_mpls_entry_tr(int unit, void *ent_a, void *ent_b)
   3251 {
   3252     uint32 val_a = 0, val_b = 0;
   3253     soc_mem_t mem;
   3254     /* Used for non-MPLS key types */
   3255     sal_mac_addr_t mac_a, mac_b;
   3256 #if defined(BCM_TRIDENT2_SUPPORT)
   3257     uint32 key_a[SOC_MAX_MEM_FIELD_WORDS], key_b[SOC_MAX_MEM_FIELD_WORDS];
   3258     sal_memset(key_a, 0, sizeof(key_a));
   3259     sal_memset(key_b, 0, sizeof(key_b));
   3260 #endif
   3261 
   3262     mem = SOC_IS_TOMAHAWK3(unit) ? MPLS_ENTRY_SINGLEm : MPLS_ENTRYm;
   3263 
   3264     if (SOC_MEM_FIELD_VALID(unit, mem, KEY_TYPEf)) {
   3265 #if defined(BCM_TOMAHAWK3_SUPPORT)
   3266         if (SOC_IS_TOMAHAWK3(unit)) {
   3267             val_a = soc_MPLS_ENTRY_SINGLEm_field32_get(unit, ent_a, KEY_TYPEf);
   3268             val_b = soc_MPLS_ENTRY_SINGLEm_field32_get(unit, ent_b, KEY_TYPEf);
   3269         } else
   3270 #endif
   3271         {
   3272         val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, KEY_TYPEf);
   3273         val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, KEY_TYPEf);
   3274         }
   3275         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3276 
   3277 #if defined(BCM_TOMAHAWK3_SUPPORT)
   3278     if (SOC_IS_TOMAHAWK3(unit)) {
   3279             switch (val_a) {
   3280             case 0: /* MPLS */
   3281                 val_a = soc_MPLS_ENTRY_SINGLEm_field32_get(unit, ent_a, PORT_NUMf);
   3282                 val_b = soc_MPLS_ENTRY_SINGLEm_field32_get(unit, ent_b, PORT_NUMf);
   3283 
   3284                 /* Note: MODULE_IDf is absent in TH3's MPLS_ENTRY_SINGLE */
   3285 
   3286                 val_a = soc_MPLS_ENTRY_SINGLEm_field32_get(unit, ent_a, Tf);
   3287                 val_b = soc_MPLS_ENTRY_SINGLEm_field32_get(unit, ent_b, Tf);
   3288 
   3289                 val_a = soc_MPLS_ENTRY_SINGLEm_field32_get(unit, ent_a, MPLS_LABELf);
   3290                 val_b = soc_MPLS_ENTRY_SINGLEm_field32_get(unit, ent_b, MPLS_LABELf);
   3291                 return 0;
   3292 
   3293             default:
   3294                 return 1;
   3295         }
   3296     }
   3297 #endif /* BCM_TOMAHAWK3_SUPPORT */
   3298 
   3299         switch (val_a) {
   3300         case 0: /* MPLS */
   3301             val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, PORT_NUMf);
   3302             val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, PORT_NUMf);
   3303             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3304 
   3305             val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, MODULE_IDf);
   3306             val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, MODULE_IDf);
   3307             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3308 
   3309             val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, Tf);
   3310             val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, Tf);
   3311             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3312 
   3313             val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, MPLS_LABELf);
   3314             val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, MPLS_LABELf);
   3315             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3316 
   3317             return 0;
   3318         case 1: /* MIM_NVP */
   3319             val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, MIM_NVP__BVIDf);
   3320             val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, MIM_NVP__BVIDf);
   3321             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3322 
   3323             soc_mem_mac_addr_get
   3324                 (unit, MPLS_ENTRYm, ent_a, MIM_NVP__BMACSAf, mac_a);
   3325             soc_mem_mac_addr_get
   3326                 (unit, MPLS_ENTRYm, ent_b, MIM_NVP__BMACSAf, mac_b);
   3327             return ENET_CMP_MACADDR(mac_a, mac_b);
   3328 
   3329         case 2: /* MIM_ISID */
   3330             val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, MIM_ISID__ISIDf);
   3331             val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, MIM_ISID__ISIDf);
   3332             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3333 
   3334             return 0;
   3335 
   3336         case 3: /* MIM_ISID_SVP */
   3337             val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, MIM_ISID__ISIDf);
   3338             val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, MIM_ISID__ISIDf);
   3339             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3340 
   3341             val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, MIM_ISID__SVPf);
   3342             val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, MIM_ISID__SVPf);
   3343             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3344 
   3345             return 0;
   3346 
   3347         case 4: /* WLAN_MAC */
   3348 #if defined(BCM_TRIDENT2_SUPPORT)
   3349             if (SOC_IS_TD2_TT2(unit)) {
   3350                 soc_mem_field_get(unit, MPLS_ENTRYm, ent_a, L2GRE_VPNID__KEYf, key_a);
   3351                 soc_mem_field_get(unit, MPLS_ENTRYm, ent_b, L2GRE_VPNID__KEYf, key_b);
   3352                 return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   3353             } else
   3354 #endif
   3355             {
   3356                 soc_mem_mac_addr_get
   3357                     (unit, MPLS_ENTRYm, ent_a, WLAN_MAC__MAC_ADDRf, mac_a);
   3358                 soc_mem_mac_addr_get
   3359                     (unit, MPLS_ENTRYm, ent_b, WLAN_MAC__MAC_ADDRf, mac_b);
   3360                 return ENET_CMP_MACADDR(mac_a, mac_b);
   3361             }
   3362 
   3363         case 5: /* TRILL */
   3364             val_a = soc_MPLS_ENTRYm_field32_get
   3365                 (unit, ent_a, TRILL__RBRIDGE_NICKNAMEf);
   3366             val_b = soc_MPLS_ENTRYm_field32_get
   3367                 (unit, ent_b, TRILL__RBRIDGE_NICKNAMEf);
   3368             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3369 
   3370             return 0;
   3371 #if defined(BCM_TRIDENT2_SUPPORT)
   3372         case 6:
   3373             if (SOC_IS_TD2_TT2(unit)) {
   3374                 soc_mem_field_get(unit, MPLS_ENTRYm, ent_a, L2GRE_SIP__KEYf, key_a);
   3375                 soc_mem_field_get(unit, MPLS_ENTRYm, ent_b, L2GRE_SIP__KEYf, key_b);
   3376                 return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   3377             }
   3378             return 1;
   3379        case 7:
   3380             if (SOC_IS_TD2_TT2(unit)) {
   3381                 soc_mem_field_get(unit, MPLS_ENTRYm, ent_a, L2GRE_VPNID__KEYf, key_a);
   3382                 soc_mem_field_get(unit, MPLS_ENTRYm, ent_b, L2GRE_VPNID__KEYf, key_b);
   3383                 return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   3384             }
   3385             return 1;
   3386        case 8:
   3387             if (SOC_IS_TD2_TT2(unit)) {
   3388                 soc_mem_field_get(unit, MPLS_ENTRYm, ent_a, VXLAN_SIP__KEYf, key_a);
   3389                 soc_mem_field_get(unit, MPLS_ENTRYm, ent_b, VXLAN_SIP__KEYf, key_b);
   3390                 return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   3391             }
   3392             return 1;
   3393        case 9:
   3394        case 10:
   3395             if (SOC_IS_TD2_TT2(unit)) {
   3396                 soc_mem_field_get(unit, MPLS_ENTRYm, ent_a, VXLAN_VN_ID__KEYf, key_a);
   3397                 soc_mem_field_get(unit, MPLS_ENTRYm, ent_b, VXLAN_VN_ID__KEYf, key_b);
   3398                 return sal_memcmp(key_a, key_b, (sizeof(key_a)));
   3399             }
   3400             return 1;
   3401 #endif
   3402         default:
   3403             return 1;
   3404         }
   3405     }
   3406 
   3407     val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, PORT_NUMf);
   3408     val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, PORT_NUMf);
   3409     SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3410 
   3411     val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, MODULE_IDf);
   3412     val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, MODULE_IDf);
   3413     SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3414 
   3415     val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, Tf);
   3416     val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, Tf);
   3417     SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3418 
   3419     val_a = soc_MPLS_ENTRYm_field32_get(unit, ent_a, MPLS_LABELf);
   3420     val_b = soc_MPLS_ENTRYm_field32_get(unit, ent_b, MPLS_LABELf);
   3421     SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3422 
   3423     return 0;
   3424 }
   3425 #endif /* BCM_TRIUMPH_SUPPORT */
   3426 
   3427 STATIC void
   3428 _soc_mem_write_range_cache_update(int unit,
   3429                         soc_mem_t mem, unsigned array_index,
   3430                         int copyno, int no_cache, 
   3431                         int index_min, int index_max, void *buffer)
   3432 {
   3433     uint32          *cache;
   3434     uint32          entry_dw;
   3435     int mem_array_vmap_offset, mem_array_cache_offset;
   3436     int i;
   3437     uint8 *vmap;
   3438     int   indices_reversed = (index_max < index_min);
   3439     int   effective_min = indices_reversed ? index_max : index_min;
   3440     int   effective_max = indices_reversed ? index_min : index_max;
   3441     int   index_limit = indices_reversed ? (index_min - 1) : (index_max + 1);
   3442 
   3443     entry_dw = soc_mem_entry_words(unit, mem);
   3444 #ifdef BCM_DNX_SUPPORT
   3445     mem_array_vmap_offset = (SOC_MEM_IS_ARRAY(unit, mem)) ?
   3446                              ((array_index - SOC_MEM_FIRST_ARRAY_INDEX(unit, mem)) * soc_mem_index_count(unit, mem)) :
   3447                              (array_index * soc_mem_index_count(unit, mem));
   3448 #else
   3449     mem_array_vmap_offset = array_index * soc_mem_index_count(unit, mem);
   3450 #endif
   3451     mem_array_cache_offset = mem_array_vmap_offset * entry_dw;
   3452 
   3453     cache = SOC_MEM_STATE(unit, mem).cache[copyno];
   3454     if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)) {
   3455         sal_memcpy(cache + mem_array_cache_offset + effective_min * entry_dw,
   3456                 buffer, (effective_max - effective_min + 1) * entry_dw * 4);
   3457 
   3458         vmap = SOC_MEM_STATE(unit, mem).vmap[copyno];
   3459         for (i = index_min; i != index_limit; indices_reversed ? i-- : i++) {
   3460             CACHE_VMAP_SET(vmap, mem_array_vmap_offset + i);
   3461         }
   3462    }
   3463 
   3464 }
   3465 
   3466 
   3467 /*
   3468  * Function: _soc_mem_aggr_cache_update
   3469  *
   3470  * Purpose:  If this mem view has several physical copies, 
   3471  *               it needs to be updated accordingly.
   3472  *
   3473  * Returns:  None
   3474  */
   3475 STATIC void
   3476 _soc_mem_aggr_cache_update(int unit, soc_mem_t mem, 
   3477                                 int blk, int no_cache, 
   3478                                 int index_min, int index_max,
   3479                                 int array_index, void *entry_data)
   3480 {
   3481     
   3482     /*
   3483      * There are 3 physical copies of MODPORT_MAP.
   3484      * Writing this table writes all three physical copies.
   3485      * The copies are MODPORT_MAP_SW, MODPORT_MAP_IM, MODPORT_MAP_EM.
   3486      */
   3487     if (soc_mem_is_aggr(unit, mem) && mem == MODPORT_MAPm) {
   3488         if (soc_mem_is_valid(unit, MODPORT_MAP_SWm)) {
   3489             _soc_mem_write_range_cache_update(unit, MODPORT_MAP_SWm, 
   3490                         array_index, blk, no_cache,
   3491                         index_min, index_max, entry_data);
   3492         }
   3493         if (soc_mem_is_valid(unit, MODPORT_MAP_IMm)) {
   3494             _soc_mem_write_range_cache_update(unit, MODPORT_MAP_IMm, 
   3495                         array_index, blk, no_cache,
   3496                         index_min, index_max, entry_data);
   3497         }
   3498         if (soc_mem_is_valid(unit, MODPORT_MAP_EMm)) {
   3499             _soc_mem_write_range_cache_update(unit, MODPORT_MAP_EMm, 
   3500                         array_index, blk, no_cache,
   3501                         index_min, index_max, entry_data);
   3502         }
   3503     }
   3504 
   3505 }
   3506 
   3507 
   3508 #endif /* BCM_TRX_SUPPORT */
   3509 
   3510 #ifdef BCM_TRIDENT2_SUPPORT
   3511 int
   3512 _soc_mem_cmp_ing_vp_vlan_membership(int unit, void *ent_a, void *ent_b)
   3513 {
   3514     uint32 val_a, val_b;
   3515 
   3516     val_a = soc_mem_field32_get(unit, ING_VP_VLAN_MEMBERSHIPm, ent_a, VLANf);
   3517     val_b = soc_mem_field32_get(unit, ING_VP_VLAN_MEMBERSHIPm, ent_b, VLANf);
   3518     SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3519 
   3520     val_a = soc_mem_field32_get(unit, ING_VP_VLAN_MEMBERSHIPm, ent_a, VPf);
   3521     val_b = soc_mem_field32_get(unit, ING_VP_VLAN_MEMBERSHIPm, ent_b, VPf);
   3522     SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3523 
   3524     return 0;
   3525 }
   3526 
   3527 int
   3528 _soc_mem_cmp_egr_vp_vlan_membership(int unit, void *ent_a, void *ent_b)
   3529 {
   3530     uint32 val_a, val_b;
   3531 
   3532     val_a = soc_mem_field32_get(unit, EGR_VP_VLAN_MEMBERSHIPm, ent_a, VLANf);
   3533     val_b = soc_mem_field32_get(unit, EGR_VP_VLAN_MEMBERSHIPm, ent_b, VLANf);
   3534     SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3535 
   3536     val_a = soc_mem_field32_get(unit, EGR_VP_VLAN_MEMBERSHIPm, ent_a, VPf);
   3537     val_b = soc_mem_field32_get(unit, EGR_VP_VLAN_MEMBERSHIPm, ent_b, VPf);
   3538     SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3539 
   3540     return 0;
   3541 }
   3542 
   3543 int
   3544 _soc_mem_cmp_ing_dnat_address_type(int unit, void *ent_a, void *ent_b)
   3545 {
   3546     uint32 val_a, val_b;
   3547 
   3548     val_a = soc_mem_field32_get(unit, ING_DNAT_ADDRESS_TYPEm, ent_a,
   3549                                 DEST_IPV4_ADDRf);
   3550     val_b = soc_mem_field32_get(unit, ING_DNAT_ADDRESS_TYPEm, ent_b,
   3551                                 DEST_IPV4_ADDRf);
   3552     SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3553 
   3554     val_a = soc_mem_field32_get(unit, ING_DNAT_ADDRESS_TYPEm, ent_a, VRFf);
   3555     val_b = soc_mem_field32_get(unit, ING_DNAT_ADDRESS_TYPEm, ent_b, VRFf);
   3556     SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3557 
   3558     return 0;
   3559 }
   3560 
   3561 int
   3562 _soc_mem_cmp_l2_endpoint_id(int unit, void *ent_a, void *ent_b)
   3563 {
   3564     sal_mac_addr_t mac_a, mac_b;
   3565     uint32 val_a, val_b;
   3566 
   3567     val_a = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_a, KEY_TYPEf);
   3568     val_b = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_b, KEY_TYPEf);
   3569     SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3570 
   3571     switch (val_a) {
   3572     case TD2_L2_HASH_KEY_TYPE_BRIDGE:
   3573         val_a = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_a,
   3574                                     L2__VLAN_IDf);
   3575         val_b = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_b,
   3576                                     L2__VLAN_IDf);
   3577         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3578 
   3579         soc_mem_mac_addr_get(unit, L2_ENDPOINT_IDm, ent_a, L2__MAC_ADDRf,
   3580                              mac_a);
   3581         soc_mem_mac_addr_get(unit, L2_ENDPOINT_IDm, ent_b, L2__MAC_ADDRf,
   3582                              mac_b);
   3583         return ENET_CMP_MACADDR(mac_a, mac_b);
   3584 
   3585     case TD2_L2_HASH_KEY_TYPE_VFI:
   3586         val_a = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_a, L2__VFIf);
   3587         val_b = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_b, L2__VFIf);
   3588         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3589 
   3590         soc_mem_mac_addr_get(unit, L2_ENDPOINT_IDm, ent_a, L2__MAC_ADDRf,
   3591                              mac_a);
   3592         soc_mem_mac_addr_get(unit, L2_ENDPOINT_IDm, ent_b, L2__MAC_ADDRf,
   3593                              mac_b);
   3594         return ENET_CMP_MACADDR(mac_a, mac_b);
   3595 
   3596     case TD2_L2_HASH_KEY_TYPE_VIF:
   3597         val_a = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_a,
   3598                                     VIF__NAMESPACEf);
   3599         val_b = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_b,
   3600                                     VIF__NAMESPACEf);
   3601         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3602 
   3603         val_a = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_a,
   3604                                     VIF__DST_VIFf);
   3605         val_b = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_b,
   3606                                     VIF__DST_VIFf);
   3607         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3608 
   3609         val_a = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_a, VIF__Pf);
   3610         val_b = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_b, VIF__Pf);
   3611         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3612 
   3613         return 0;
   3614 
   3615     case TD2_L2_HASH_KEY_TYPE_PE_VID:
   3616         val_a = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_a,
   3617                                     PE_VID__NAMESPACEf);
   3618         val_b = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_b,
   3619                                     PE_VID__NAMESPACEf);
   3620         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3621 
   3622         val_a = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_a,
   3623                                     PE_VID__ETAG_VIDf);
   3624         val_b = soc_mem_field32_get(unit, L2_ENDPOINT_IDm, ent_b,
   3625                                     PE_VID__ETAG_VIDf);
   3626         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3627 
   3628         return 0;
   3629 
   3630     default:
   3631         return 1;
   3632     }
   3633 
   3634     return 0;
   3635 }
   3636 
   3637 int
   3638 _soc_mem_cmp_endpoint_queue_map(int unit, void *ent_a, void *ent_b)
   3639 {
   3640     uint32 val_a, val_b;
   3641 
   3642     val_a = soc_mem_field32_get(unit, ENDPOINT_QUEUE_MAPm, ent_a, KEY_TYPEf);
   3643     val_b = soc_mem_field32_get(unit, ENDPOINT_QUEUE_MAPm, ent_b, KEY_TYPEf);
   3644     SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3645 
   3646     switch (val_a) {
   3647     case 0: /* endpoint queueing */
   3648         val_a = soc_mem_field32_get(unit, ENDPOINT_QUEUE_MAPm, ent_a,
   3649                                     EH_QUEUE_TAGf);
   3650         val_b = soc_mem_field32_get(unit, ENDPOINT_QUEUE_MAPm, ent_b,
   3651                                     EH_QUEUE_TAGf);
   3652         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3653 
   3654         val_a = soc_mem_field32_get(unit, ENDPOINT_QUEUE_MAPm, ent_a,
   3655                                     DEST_PORTf);
   3656         val_b = soc_mem_field32_get(unit, ENDPOINT_QUEUE_MAPm, ent_b,
   3657                                     DEST_PORTf);
   3658         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3659 
   3660         return 0;
   3661 
   3662     default:
   3663         return 1;
   3664     }
   3665 
   3666     return 0;
   3667 }
   3668 #endif /* BCM_TRIDENT2_SUPPORT */
   3669 
   3670 #ifdef BCM_TOMAHAWK_SUPPORT
   3671 int
   3672 _soc_mem_cmp_exact_match(int unit, void *ent_a, void *ent_b)
   3673 {
   3674     uint32 val_a, val_b;
   3675     uint32 buf_a[SOC_MAX_MEM_FIELD_WORDS];
   3676     uint32 buf_b[SOC_MAX_MEM_FIELD_WORDS];
   3677     soc_mem_t mem_2 = EXACT_MATCH_2m;
   3678     soc_mem_t mem_4 = EXACT_MATCH_4m;
   3679 
   3680 #ifdef BCM_TOMAHAWK3_SUPPORT
   3681     if(SOC_IS_TOMAHAWK3(unit)) {
   3682         val_a = soc_mem_field32_get(unit, EXACT_MATCH_2m, ent_a, KEY_TYPEf);
   3683         val_b = soc_mem_field32_get(unit, EXACT_MATCH_2m, ent_b, KEY_TYPEf);
   3684         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3685 
   3686         switch (val_a) {
   3687         case TH3_FPEM_HASH_KEY_TYPE_128B:
   3688             soc_mem_field_get(
   3689                     unit, EXACT_MATCH_2m, ent_a, MODE128__KEY_0_ONLYf,
   3690                               buf_a);
   3691             soc_mem_field_get(
   3692                     unit, EXACT_MATCH_2m, ent_b, MODE128__KEY_0_ONLYf,
   3693                               buf_b);
   3694             SOC_MEM_COMPARE_RETURN(buf_a[3], buf_b[3]);
   3695             SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]);
   3696             SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]);
   3697             SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]);
   3698 
   3699             val_a = soc_mem_field32_get(unit, EXACT_MATCH_2m, ent_a,
   3700                                         MODE128__KEY_1_ONLYf);
   3701             val_b = soc_mem_field32_get(unit, EXACT_MATCH_2m, ent_b,
   3702                                         MODE128__KEY_1_ONLYf);
   3703             SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3704 
   3705             return 0;
   3706 
   3707         case TH3_FPEM_HASH_KEY_TYPE_160B:
   3708             soc_mem_field_get(
   3709                     unit, EXACT_MATCH_2m, ent_a, MODE160__KEY_0_ONLYf,
   3710                               buf_a);
   3711             soc_mem_field_get(
   3712                     unit, EXACT_MATCH_2m, ent_b, MODE160__KEY_0_ONLYf,
   3713                               buf_b);
   3714             SOC_MEM_COMPARE_RETURN(buf_a[3], buf_b[3]);
   3715             SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]);
   3716             SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]);
   3717             SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]);
   3718 
   3719             soc_mem_field_get(
   3720                     unit, EXACT_MATCH_2m, ent_a, MODE160__KEY_1_ONLYf,
   3721                               buf_a);
   3722             soc_mem_field_get(
   3723                     unit, EXACT_MATCH_2m, ent_b, MODE160__KEY_1_ONLYf,
   3724                               buf_b);
   3725             SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]);
   3726             SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]);
   3727 
   3728             return 0;
   3729 
   3730         case TH3_FPEM_HASH_KEY_TYPE_320B:
   3731             soc_mem_field_get(
   3732                     unit, EXACT_MATCH_4m, ent_a, MODE320__KEY_0_ONLYf,
   3733                               buf_a);
   3734             soc_mem_field_get(
   3735                     unit, EXACT_MATCH_4m, ent_b, MODE320__KEY_0_ONLYf,
   3736                               buf_b);
   3737             SOC_MEM_COMPARE_RETURN(buf_a[3], buf_b[3]);
   3738             SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]);
   3739             SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]);
   3740             SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]);
   3741 
   3742             soc_mem_field_get(
   3743                     unit, EXACT_MATCH_4m, ent_a, MODE320__KEY_1_ONLYf,
   3744                               buf_a);
   3745             soc_mem_field_get(
   3746                     unit, EXACT_MATCH_4m, ent_b, MODE320__KEY_1_ONLYf,
   3747                               buf_b);
   3748             SOC_MEM_COMPARE_RETURN(buf_a[3], buf_b[3]);
   3749             SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]);
   3750             SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]);
   3751             SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]);
   3752 
   3753             soc_mem_field_get(
   3754                     unit, EXACT_MATCH_4m, ent_a, MODE320__KEY_2_ONLYf,
   3755                               buf_a);
   3756             soc_mem_field_get(
   3757                     unit, EXACT_MATCH_4m, ent_b, MODE320__KEY_2_ONLYf,
   3758                               buf_b);
   3759             SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]);
   3760             SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]);
   3761             SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]);
   3762 
   3763             return 0;
   3764 
   3765         default:
   3766             return 1;
   3767         }
   3768         return 0;
   3769     }
   3770 #endif /* BCM_TOMAHAWK3_SUPPORT */
   3771 
   3772 #ifdef BCM_TRIDENT3_SUPPORT
   3773     if (SOC_IS_TRIDENT3X(unit)) {
   3774         val_a = soc_mem_field32_get(unit, mem_2, ent_a, KEY_TYPEf);
   3775         val_b = soc_mem_field32_get(unit, mem_2, ent_b, KEY_TYPEf);
   3776     } else
   3777 #endif
   3778     {
   3779         val_a = soc_mem_field32_get(unit, mem_2, ent_a, KEY_TYPE_0f);
   3780         val_b = soc_mem_field32_get(unit, mem_2, ent_b, KEY_TYPE_0f);
   3781     }
   3782     SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3783 
   3784     switch (val_a) {
   3785     case TH_FPEM_HASH_KEY_TYPE_128B:
   3786         soc_mem_field_get(unit, mem_2, ent_a, MODE128__KEY_0_ONLYf,
   3787                           buf_a);
   3788         soc_mem_field_get(unit, mem_2, ent_b, MODE128__KEY_0_ONLYf,
   3789                           buf_b);
   3790         SOC_MEM_COMPARE_RETURN(buf_a[3], buf_b[3]);
   3791         SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]);
   3792         SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]);
   3793         SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]);
   3794 
   3795         val_a = soc_mem_field32_get(unit, mem_2, ent_a,
   3796                                     MODE128__KEY_1_ONLYf);
   3797         val_b = soc_mem_field32_get(unit, mem_2, ent_b,
   3798                                     MODE128__KEY_1_ONLYf);
   3799         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3800 
   3801         return 0;
   3802 
   3803     case TH_FPEM_HASH_KEY_TYPE_160B:
   3804         soc_mem_field_get(unit, mem_2, ent_a, MODE160__KEY_0_ONLYf,
   3805                           buf_a);
   3806         soc_mem_field_get(unit, mem_2, ent_b, MODE160__KEY_0_ONLYf,
   3807                           buf_b);
   3808         SOC_MEM_COMPARE_RETURN(buf_a[3], buf_b[3]);
   3809         SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]);
   3810         SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]);
   3811         SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]);
   3812 
   3813         soc_mem_field_get(unit, mem_2, ent_a, MODE160__KEY_1_ONLYf,
   3814                           buf_a);
   3815         soc_mem_field_get(unit, mem_2, ent_b, MODE160__KEY_1_ONLYf,
   3816                           buf_b);
   3817         SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]);
   3818         SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]);
   3819 
   3820         return 0;
   3821 
   3822     case TH_FPEM_HASH_KEY_TYPE_320B:
   3823         soc_mem_field_get(unit, mem_4, ent_a, MODE320__KEY_0_ONLYf,
   3824                           buf_a);
   3825         soc_mem_field_get(unit, mem_4, ent_b, MODE320__KEY_0_ONLYf,
   3826                           buf_b);
   3827         SOC_MEM_COMPARE_RETURN(buf_a[3], buf_b[3]);
   3828         SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]);
   3829         SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]);
   3830         SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]);
   3831 
   3832         soc_mem_field_get(unit, mem_4, ent_a, MODE320__KEY_1_ONLYf,
   3833                           buf_a);
   3834         soc_mem_field_get(unit, mem_4, ent_b, MODE320__KEY_1_ONLYf,
   3835                           buf_b);
   3836         SOC_MEM_COMPARE_RETURN(buf_a[3], buf_b[3]);
   3837         SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]);
   3838         SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]);
   3839         SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]);
   3840 
   3841         soc_mem_field_get(unit, mem_4, ent_a, MODE320__KEY_2_ONLYf,
   3842                           buf_a);
   3843         soc_mem_field_get(unit, mem_4, ent_b, MODE320__KEY_2_ONLYf,
   3844                           buf_b);
   3845         SOC_MEM_COMPARE_RETURN(buf_a[3], buf_b[3]);
   3846         SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]);
   3847         SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]);
   3848         SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]);
   3849 
   3850         val_a = soc_mem_field32_get(unit, mem_4, ent_a,
   3851                                     MODE320__KEY_3_ONLYf);
   3852         val_b = soc_mem_field32_get(unit, mem_4, ent_b,
   3853                                     MODE320__KEY_3_ONLYf);
   3854         SOC_MEM_COMPARE_RETURN(val_a, val_b);
   3855 
   3856         return 0;
   3857 
   3858     default:
   3859         return 1;
   3860     }
   3861 
   3862     return 0;
   3863 }
   3864 #endif /* BCM_TOMAHAWK_SUPPORT */
   3865 
   3866 int
   3867 _soc_mem_cmp_ft_key_double(int unit, void *ent_a, void *ent_b)
   3868 {
   3869     
   3870 
   3871     return 0;
   3872 }
   3873 
   3874 int
   3875 _soc_mem_cmp_ft_key_single(int unit, void *ent_a, void *ent_b)
   3876 {
   3877     
   3878 
   3879     return 0;
   3880 }
   3881 
   3882 /*
   3883  *  This function caches the info needed by the L3 key comparison, below.
   3884  */
   3885 int
   3886 _soc_mem_cmp_l3x_sync(int unit)
   3887 {
   3888     return SOC_E_NONE;
   3889 }
   3890 
   3891 int
   3892 _soc_mem_cmp_l3x_set(int unit, uint32 ipmc_config)
   3893 {
   3894     return SOC_E_NONE;
   3895 }
   3896 
   3897 int
   3898 _soc_mem_cmp_l3x(int unit, void *ent_a, void *ent_b)
   3899 {
   3900     return 0;
   3901 }
   3902 
   3903 /*
   3904  * Function:
   3905  *    soc_mem_index_limit
   3906  * Purpose:
   3907  *    Returns the maximum possible index for any dynamically extendable memory
   3908  */
   3909 int
   3910 soc_mem_index_limit(int unit, soc_mem_t mem)
   3911 {
   3912     _SOC_MEM_REPLACE_MEM(unit, mem);
   3913     
   3914     return soc_mem_index_count(unit, mem);
   3915 }
   3916 
   3917 #endif /* BCM_XGS_SWITCH_SUPPORT */
   3918 
   3919 /*
   3920  * Function:
   3921  *    soc_mem_index_last
   3922  * Purpose:
   3923  *    Compute the highest index currently occupied in a sorted table
   3924  */
   3925 
   3926 int
   3927 soc_mem_index_last(int unit, soc_mem_t mem, int copyno)
   3928 {
   3929     assert(SOC_MEM_IS_VALID(unit, mem));
   3930     assert(soc_attached(unit));
   3931     assert(soc_mem_is_sorted(unit,mem));
   3932 
   3933     if (copyno == MEM_BLOCK_ANY) {
   3934         /* coverity[overrun-local : FALSE] */
   3935         copyno = SOC_MEM_BLOCK_ANY(unit, mem);
   3936     }
   3937 
   3938     assert(SOC_MEM_BLOCK_VALID(unit, mem, copyno));
   3939     /* coverity[overrun-local : FALSE] */
   3940     return (SOC_MEM_INFO(unit, mem).index_min +
   3941                 SOP_MEM_STATE(unit, mem).count[copyno] - 1);
   3942 }
   3943 
   3944 
   3945 /*
   3946  * Function:
   3947  *    soc_mem_entry_dump
   3948  * Purpose:
   3949  *    Debug routine to dump a formatted table entry.
   3950  *
   3951  *    Note:  Prefix != NULL : Dump chg command
   3952  *           Prefix == NULL : Dump     command
   3953  *             (Actually should pass dump_chg flag but keeping for simplicity)
   3954  */
   3955 STATIC void
   3956 _soc_mem_entry_dump_common(int unit, soc_mem_t mem, void *buf, char *prefix, int vertical, char *field_names, uint32 bsl_flags)
   3957 {
   3958     soc_mem_info_t *memp;
   3959     char dummy[]="";
   3960     char *mem_prefix=dummy;
   3961     int  first_print_flag=0;
   3962 
   3963 #if !defined(SOC_NO_NAMES)
   3964     int f;
   3965     soc_field_info_t *fieldp;
   3966     char temp_field_name[80];
   3967     uint32 default_type = 0;
   3968     uint32 key_type = 0;
   3969     uint32 *fval;
   3970     uint32 *nfval;
   3971     char   *tmp;
   3972     uint32 *buf_ptr;
   3973     int alloc_size;
   3974     char   *split = NULL;
   3975     char   *save_str = NULL;
   3976     char   *dup_field_names = NULL;
   3977     uint8  match_found = 0;
   3978     uint32 dup_fld_names_len = 0;
   3979     uint32 temp_fld_name_len = 0;
   3980 #endif
   3981 
   3982     memp = &SOC_MEM_INFO(unit, mem);
   3983     if (prefix != NULL) {
   3984         mem_prefix = prefix;
   3985     }
   3986 
   3987     if (!SOC_MEM_IS_VALID(unit, mem)) {
   3988         BSL_LOG(bsl_flags, (BSL_META_U(unit,
   3989                             "<%s:%d>Memory not valid for unit\n"),mem_prefix,mem));
   3990         return;
   3991     }
   3992 #if !defined(SOC_NO_NAMES)
   3993     alloc_size = (2*SOC_MAX_MEM_FIELD_WORDS) * sizeof(uint32) +
   3994                  (SOC_MAX_MEM_FIELD_WORDS * 8) + 3;
   3995     buf_ptr = sal_alloc(alloc_size, "Temp. buffer for _soc_mem_entry_dump_common");
   3996     sal_memset((void *)buf_ptr,0,alloc_size);
   3997     fval  = buf_ptr;
   3998     nfval = buf_ptr + SOC_MAX_MEM_FIELD_WORDS;
   3999     tmp   = (char *)(buf_ptr + 2 * SOC_MAX_MEM_FIELD_WORDS);
   4000 
   4001     if ((memp->flags & SOC_MEM_FLAG_MULTIVIEW)
   4002 #if defined(BCM_SAND_SUPPORT)
   4003              && (!SOC_IS_SAND(unit))
   4004 #endif
   4005          ) {
   4006 #ifdef KEY_TYPEf
   4007         if (SOC_MEM_FIELD_VALID(unit, mem, KEY_TYPEf)) {
   4008             soc_mem_field_get(unit, mem, buf, KEY_TYPEf, &key_type);
   4009         } else if (SOC_MEM_FIELD_VALID(unit, mem, KEY_TYPE_0f)) {
   4010             soc_mem_field_get(unit, mem, buf, KEY_TYPE_0f, &key_type);
   4011         } else if (SOC_MEM_FIELD_VALID(unit, mem, VP_TYPEf)) {
   4012             soc_mem_field_get(unit, mem, buf, VP_TYPEf, &key_type);
   4013         } else if (SOC_MEM_FIELD_VALID(unit, mem, ENTRY_TYPEf)) {
   4014             soc_mem_field_get(unit, mem, buf, ENTRY_TYPEf, &key_type);
   4015         } else if (SOC_MEM_FIELD_VALID(unit, mem, MODEf)) {
   4016                 soc_mem_field_get(unit, mem, buf, MODEf, &key_type);
   4017         } else if (SOC_MEM_FIELD_VALID(unit, mem, DATA_TYPEf)) {
   4018             soc_mem_field_get(unit, mem, buf, DATA_TYPEf, &key_type);
   4019         }
   4020 #endif
   4021         default_type = 0;
   4022 #if defined(BCM_TRIUMPH2_SUPPORT)
   4023         if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) ||
   4024             SOC_IS_VALKYRIE2(unit) || SOC_IS_ENDURO(unit) ||
   4025             SOC_IS_HURRICANE(unit) || SOC_IS_TD_TT(unit) ||
   4026             SOC_IS_KATANA(unit)) {
   4027             if((mem == VLAN_MACm) ||
   4028                 (mem == L3_ENTRY_IPV4_MULTICASTm) ||
   4029                 (mem == L3_ENTRY_IPV6_UNICASTm) ||
   4030                 (mem == L3_ENTRY_IPV6_MULTICASTm) ||
   4031                (mem == EXACT_MATCH_4m) ||
   4032                (mem == EXACT_MATCH_4_ENTRY_ONLYm)) {
   4033                 default_type = key_type;
   4034             }
   4035         }
   4036 #endif /* BCM_TRIUMPH2_SUPPORT */
   4037 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT)
   4038         if ((mem == L2_BULK_MATCH_MASKm) ||
   4039             (mem == L2_BULK_REPLACE_MASKm)) {
   4040             if (SOC_IS_KATANA(unit) &&
   4041                (key_type > KATANA_L2X_VIEW_ARRAY_MAX_INDEX)) {
   4042                 key_type = KATANA_L2X_VIEW_ARRAY_MAX_INDEX;
   4043             } else if (SOC_IS_KATANA2(unit) &&
   4044                (key_type > KATANA2_L2X_VIEW_ARRAY_MAX_INDEX)) {
   4045                 key_type = KATANA2_L2X_VIEW_ARRAY_MAX_INDEX;
   4046             } else if (SOC_IS_TRIDENT2(unit) &&
   4047                (key_type > TRIDENT2_L2X_VIEW_ARRAY_MAX_INDEX)) {
   4048                 key_type = TRIDENT2_L2X_VIEW_ARRAY_MAX_INDEX;
   4049             } else if ((SOC_IS_TD2P_TT2P(unit) || SOC_IS_APACHE(unit)) &&
   4050                (key_type > TRIDENT2PLUS_L2X_VIEW_ARRAY_MAX_INDEX)) {
   4051                 key_type = TRIDENT2PLUS_L2X_VIEW_ARRAY_MAX_INDEX;
   4052             }
   4053         }
   4054 #endif
   4055 
   4056 #ifdef BCM_TOMAHAWK_SUPPORT
   4057         if (mem == L2_BULKm) {
   4058             if (SOC_IS_TOMAHAWKX(unit) &&
   4059                (key_type > TOMAHAWK_L2X_VIEW_ARRAY_MAX_INDEX)) {
   4060                 key_type = TOMAHAWK_L2X_VIEW_ARRAY_MAX_INDEX;
   4061             } else if ((SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_TRIDENT3X(unit)) &&
   4062                       (key_type > TRIDENT2PLUS_L2X_VIEW_ARRAY_MAX_INDEX)) {
   4063                 key_type = TRIDENT2PLUS_L2X_VIEW_ARRAY_MAX_INDEX;
   4064             }
   4065         }
   4066 #endif
   4067 
   4068 #ifdef BCM_TRIDENT3_SUPPORT
   4069         if (mem == L2Xm || mem == L2_ENTRY_SINGLEm || mem == L2_ENTRY_ONLY_SINGLEm) {
   4070             if (SOC_IS_TRIDENT3X(unit) &&
   4071                 (key_type > TRIDENT2PLUS_L2X_VIEW_ARRAY_MAX_INDEX)) {
   4072                 key_type = TRIDENT2PLUS_L2X_VIEW_ARRAY_MAX_INDEX;
   4073             }
   4074         }
   4075 #endif
   4076 
   4077 #ifdef BCM_TRIDENT2_SUPPORT
   4078         if (mem == L2_LEARN_INSERT_FAILUREm) {
   4079             if (SOC_IS_TRIDENT2(unit) &&
   4080                (key_type > TRIDENT2_L2X_VIEW_ARRAY_MAX_INDEX)) {
   4081                 key_type = TRIDENT2_L2X_VIEW_ARRAY_MAX_INDEX;
   4082             } if ((SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_TITAN2PLUS(unit) ||
   4083                    SOC_IS_TRIDENT3X(unit)) &&
   4084                (key_type > TRIDENT2PLUS_L2X_VIEW_ARRAY_MAX_INDEX)) {
   4085                 key_type = TRIDENT2PLUS_L2X_VIEW_ARRAY_MAX_INDEX;
   4086             } else if (SOC_IS_TOMAHAWKX(unit) &&
   4087                (key_type > TOMAHAWK_L2X_VIEW_ARRAY_MAX_INDEX)) {
   4088                 key_type = TOMAHAWK_L2X_VIEW_ARRAY_MAX_INDEX;
   4089             }
   4090         }
   4091 #endif
   4092 
   4093 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_APACHE_SUPPORT)
   4094         
   4095         if ((mem == L3_TUNNELm) || (mem == L3_TUNNEL_ONLYm)) {
   4096             if (SOC_IS_KATANA2(unit) || 
   4097                 SOC_IS_APACHE(unit)) {
   4098                 key_type++;
   4099             }
   4100         }
   4101 #endif
   4102 
   4103 #if defined(BCM_TRIUMPH3_SUPPORT)
   4104         if (SOC_IS_TRIUMPH3(unit)) {
   4105             if (mem == L3_TUNNELm) {
   4106                 if (key_type == 1) {
   4107                     /* 
   4108                      * In TR3 reg file, field names are defined for
   4109                      * "IP" view which is common for IPv6 & IPv4.
   4110                      * So, IPv6 (key type 1) entries use same field
   4111                      * names as those of IPv4 (keytype 0) entries
   4112                      */
   4113                     key_type = 0;
   4114                 }
   4115             }
   4116         }
   4117 #endif /* BCM_TRIUMPH3_SUPPORT */
   4118 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
   4119         if (SOC_IS_TOMAHAWK2(unit) || SOC_IS_TOMAHAWK3(unit)) {
   4120             if ((mem == L3_TUNNELm) || (mem == L3_TUNNEL_ONLYm)) {
   4121                 if ((key_type == 0) || (key_type == 1)) {
   4122                     /* 
   4123                      * In TH2 reg file, field names are defined for
   4124                      * "IP" view which is common for IPv6 & IPv4.
   4125                      * So, IPv6 (key type 1) entries use same field
   4126                      * names as those of IPv4 (keytype 0) entries
   4127                      */
   4128                     key_type = 0;
   4129                 } else {
   4130                     key_type++;
   4131                 }
   4132             }
   4133         }
   4134 #endif
   4135 
   4136 #if defined(BCM_GREYHOUND2_SUPPORT)
   4137         if (soc_feature(unit, soc_feature_vxlan_lite_riot)) {
   4138             if (mem == L2Xm) {
   4139                 if (key_type == GH2_L2_HASH_KEY_TYPE_VFI_MULTICAST) {
   4140                     key_type = GH2_L2_HASH_KEY_TYPE_VFI;
   4141                 }
   4142             }
   4143         }
   4144 #endif /* BCM_GREYHOUND2_SUPPORT */
   4145 
   4146         if ((key_type >= *memp->views_num) ||
   4147             (sal_strlen(memp->views[key_type]) == 0)) {
   4148             BSL_LOG(bsl_flags, (BSL_META_U(unit,
   4149                                 "<Wrong Key_type %d>\n"),key_type));
   4150             sal_free(buf_ptr);
   4151             return;
   4152         }
   4153     }
   4154 
   4155     if (NULL != field_names) {
   4156         dup_fld_names_len = sal_strlen(field_names) + 1;
   4157         dup_field_names = sal_alloc(dup_fld_names_len, "DupFieldNames");
   4158         if (NULL == dup_field_names) {
   4159             BSL_LOG(bsl_flags, (BSL_META_U(unit, "<Memory alloc failure>\n")));
   4160             sal_free(buf_ptr);
   4161             return;
   4162         }
   4163     }
   4164 
   4165     for (f = memp->nFields - 1; f >= 0; f--) {
   4166         fieldp = &memp->fields[f];
   4167         if ((memp->flags & SOC_MEM_FLAG_MULTIVIEW)
   4168 #if defined(BCM_SAND_SUPPORT)
   4169              && (!SOC_IS_SAND(unit))
   4170 #endif
   4171              ) {
   4172             if (!(strstr(soc_fieldnames[fieldp->field], memp->views[key_type]) ||
   4173                 (strcmp(memp->views[key_type], memp->views[default_type]) == 0
   4174                  && !strstr(soc_fieldnames[fieldp->field], ":"))             ||
   4175                 (fieldp->flags & SOCF_GLOBAL))) {
   4176                 continue;
   4177             }
   4178         }
   4179         if (field_names != NULL) {
   4180             save_str = NULL;
   4181             match_found = 0;
   4182 
   4183             sal_memset(temp_field_name, 0x0, sizeof(temp_field_name));
   4184             sal_strncpy(temp_field_name,
   4185                 soc_fieldnames[fieldp->field], sizeof(temp_field_name) - 1);
   4186             temp_fld_name_len = sal_strlen(temp_field_name);
   4187             sal_strncpy(dup_field_names, field_names, dup_fld_names_len);
   4188 
   4189             split = sal_strtok_r(dup_field_names, ",", &save_str);
   4190             while (split) {
   4191 
   4192                 /* Firstly, check if the field names are matching */
   4193                 if (!sal_strncmp(temp_field_name, split, temp_fld_name_len)) {
   4194                     /* Secondly, check if the field name lengths are same */
   4195                     if (temp_fld_name_len == sal_strlen(split)) {
   4196                         match_found = 1;
   4197                         break;
   4198                     }
   4199                 }
   4200                 split = sal_strtok_r(NULL, ",", &save_str);
   4201             }
   4202 
   4203             if (!match_found) {
   4204                 continue;
   4205             }
   4206         }
   4207 
   4208         sal_memset(fval, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   4209         soc_mem_field_get(unit, mem, buf, fieldp->field, fval);
   4210         if (mem_prefix == prefix) {
   4211             if (sal_memcmp(fval, nfval, SOC_MAX_MEM_FIELD_WORDS *
   4212                            sizeof (uint32)) == 0) {
   4213                 continue;
   4214             }
   4215         }
   4216         if (first_print_flag == 0) {
   4217             BSL_LOG(bsl_flags, (BSL_META_U(unit,
   4218                                 "%s%s"), mem_prefix, vertical ? "" : "<"));
   4219             first_print_flag=1;
   4220         }
   4221         if (vertical) {
   4222             _shr_format_long_integer(tmp, fval, BITS2BYTES(fieldp->len));
   4223             BSL_LOG(bsl_flags, (BSL_META_U(unit,
   4224                                 "\n\t%30s: %s"), soc_fieldnames[fieldp->field], tmp));
   4225         } else {
   4226             _shr_format_long_integer(tmp, fval, BITS2BYTES(fieldp->len));
   4227             BSL_LOG(bsl_flags, (BSL_META_U(unit,
   4228                                 "%s=%s%s"), soc_fieldnames[fieldp->field],
   4229                                 tmp, f > 0 ? "," : ""));
   4230         }
   4231     }
   4232 
   4233     if (NULL != dup_field_names) {
   4234         sal_free(dup_field_names);
   4235     }
   4236     sal_free(buf_ptr);
   4237 #endif
   4238     if (first_print_flag == 1) {
   4239         BSL_LOG(bsl_flags, (BSL_META_U(unit,
   4240                             "%s\n"), vertical ? "" : ">"));
   4241     }
   4242 }
   4243 
   4244 STATIC void
   4245 soc_mem_entry_dump_common(int unit, soc_mem_t mem, void *buf, char *prefix, int vertical, char *field_names, uint32 bsl_flags)
   4246 {
   4247 #ifdef BCM_TRIDENT3_SUPPORT
   4248     int rv;
   4249     soc_mem_t mem_view_id;
   4250     soc_mem_t flex_mem;
   4251     uint32 data_type = 0;
   4252     uint32 key_type = 0;
   4253     soc_flow_db_ctrl_field_t ctrl_field[2];
   4254     int num_ctrl_fields = 0;
   4255 #endif
   4256 
   4257     /* call memory view entry dump for all flex views */
   4258 #ifdef BCM_TRIDENT3_SUPPORT
   4259     if (soc_feature(unit, soc_feature_flex_flow)) {
   4260         if (mem == L2Xm || mem == L2_ENTRY_SINGLEm || 
   4261             mem == L2_ENTRY_ONLY_SINGLEm) {
   4262             flex_mem = L2_ENTRY_SINGLEm;   /* flex L2 memory name */
   4263         } else {
   4264             flex_mem = mem;
   4265         }
   4266         if (SOC_MEM_FIELD_VALID(unit, flex_mem, DATA_TYPE0f)) {
   4267             data_type = soc_mem_field32_get(unit, flex_mem, buf, DATA_TYPE0f);
   4268         } else if (SOC_MEM_FIELD_VALID(unit, flex_mem, DATA_TYPEf)) {
   4269             data_type = soc_mem_field32_get(unit, flex_mem, buf, DATA_TYPEf);
   4270         }
   4271         if (SOC_MEM_FIELD_VALID(unit, flex_mem, KEY_TYPE0f)) {
   4272             key_type = soc_mem_field32_get(unit, flex_mem, buf, KEY_TYPE0f);
   4273         } else if (SOC_MEM_FIELD_VALID(unit, flex_mem, KEY_TYPEf)) {
   4274             key_type = soc_mem_field32_get(unit, flex_mem, buf, KEY_TYPEf);
   4275         }
   4276         if (SOC_MEM_FIELD_VALID(unit, flex_mem, FLOW_SELECT_CTRL_IDf)) {
   4277             ctrl_field[num_ctrl_fields].field_id = FLOW_SELECT_CTRL_IDf;
   4278             ctrl_field[num_ctrl_fields].value = soc_mem_field32_get(unit, 
   4279                                flex_mem, buf, FLOW_SELECT_CTRL_IDf);
   4280             num_ctrl_fields++;
   4281         } else if (SOC_MEM_FIELD_VALID(unit, flex_mem, FLEX__FLOW_SELECT_CTRL_IDf)) {
   4282             ctrl_field[num_ctrl_fields].field_id = FLOW_SELECT_CTRL_IDf;
   4283             ctrl_field[num_ctrl_fields].value = soc_mem_field32_get(unit, 
   4284                                flex_mem, buf, FLEX__FLOW_SELECT_CTRL_IDf);
   4285             num_ctrl_fields++;
   4286         }
   4287 
   4288         if (SOC_MEM_FIELD_VALID(unit, flex_mem, EDIT_CTRL_IDf)) {
   4289             ctrl_field[num_ctrl_fields].field_id = EDIT_CTRL_IDf;
   4290             ctrl_field[num_ctrl_fields].value = soc_mem_field32_get(unit, 
   4291                                flex_mem, buf, EDIT_CTRL_IDf);
   4292             num_ctrl_fields++;
   4293         } else if (SOC_MEM_FIELD_VALID(unit, flex_mem, FLEX__EDIT_CTRL_IDf)) {
   4294             ctrl_field[num_ctrl_fields].field_id = EDIT_CTRL_IDf;
   4295             ctrl_field[num_ctrl_fields].value = soc_mem_field32_get(unit, 
   4296                                flex_mem, buf, FLEX__EDIT_CTRL_IDf);
   4297             num_ctrl_fields++;
   4298         }
   4299 
   4300         if (!key_type) {
   4301             rv = soc_flow_db_mem_to_view_id_get (unit, flex_mem, 
   4302                     SOC_FLOW_DB_KEY_TYPE_INVALID, data_type,
   4303                     num_ctrl_fields, 
   4304                     num_ctrl_fields? ctrl_field: NULL, 
   4305                     (uint32 *)&mem_view_id);
   4306         } else {
   4307             rv = soc_flow_db_mem_to_view_id_get (unit, flex_mem, key_type, 
   4308                     data_type, 
   4309                     num_ctrl_fields, 
   4310                     num_ctrl_fields? ctrl_field: NULL, 
   4311                     (uint32 *)&mem_view_id);
   4312         }
   4313 
   4314         if (SOC_SUCCESS(rv)) {
   4315             if (soc_flow_db_mem_view_is_valid(unit, mem_view_id)) {
   4316                 _soc_mem_view_entry_dump_common(unit, mem_view_id, buf, prefix, vertical, bsl_flags);
   4317                 return;
   4318             }
   4319         }
   4320     }
   4321 #endif
   4322     /* default memory entry dump for all fixed memory views */ 
   4323     _soc_mem_entry_dump_common(unit, mem, buf, prefix, vertical, field_names, bsl_flags);
   4324 }
   4325 
   4326 void
   4327 soc_mem_entry_dump_fields(int unit, soc_mem_t mem, void *buf, char *field_names)
   4328 {
   4329    soc_mem_entry_dump_common(unit, mem, buf, NULL, 0, field_names, BSL_LSS_CLI);
   4330 }
   4331 void
   4332 soc_mem_entry_dump(int unit, soc_mem_t mem, void *buf, uint32 bsl_flags)
   4333 {
   4334    soc_mem_entry_dump_common(unit, mem, buf, NULL, 0, NULL, bsl_flags);
   4335 }
   4336 void
   4337 soc_mem_entry_dump_vertical(int unit, soc_mem_t mem, void *buf)
   4338 {
   4339    soc_mem_entry_dump_common(unit, mem, buf, NULL, 1, NULL, BSL_LSS_CLI);
   4340 }
   4341 void
   4342 soc_mem_entry_dump_if_changed(int unit, soc_mem_t mem, void *buf, char *prefix)
   4343 {
   4344     soc_mem_entry_dump_common(unit, mem, buf, prefix, 0, NULL, BSL_LSS_CLI);
   4345 }
   4346 void
   4347 soc_mem_entry_dump_if_changed_fields(int unit, soc_mem_t mem, void *buf,
   4348                                      char *prefix, char *field_names)
   4349 {
   4350     soc_mem_entry_dump_common(unit, mem, buf, prefix, 0, field_names, BSL_LSS_CLI);
   4351 }
   4352 
   4353 /************************************************************************/
   4354 /* Routines for configuring the table memory caches            */
   4355 /************************************************************************/
   4356 
   4357 /*
   4358  * Function:
   4359  *    soc_mem_cache_get
   4360  * Purpose:
   4361  *    Return whether or not caching is enabled for a specified memory
   4362  *    or memories
   4363  */
   4364 
   4365 int
   4366 soc_mem_cache_get(int unit, soc_mem_t mem, int copyno)
   4367 {
   4368     int        rv;
   4369 
   4370     assert(SOC_UNIT_VALID(unit));
   4371     _SOC_MEM_REUSE_MEM_STATE(unit, mem);
   4372     SOC_MEM_ALIAS_TO_ORIG(unit,mem);
   4373     assert(SOC_MEM_IS_VALID(unit, mem));
   4374 
   4375     if (!soc_mem_is_cachable(unit, mem) || SOC_MEM_TEST_SKIP_CACHE(unit)) {
   4376         return FALSE;
   4377     }
   4378 
   4379     MEM_LOCK(unit, mem);
   4380 
   4381     if (copyno == SOC_BLOCK_ALL) {
   4382         rv = TRUE;
   4383         SOC_MEM_BLOCK_ITER(unit, mem, copyno) {
   4384             rv = (rv && (SOC_MEM_STATE(unit, mem).cache[copyno] != NULL));
   4385         }
   4386     } else {
   4387         rv = (SOC_MEM_STATE(unit, mem).cache[copyno] != NULL);
   4388     }
   4389 
   4390     MEM_UNLOCK(unit, mem);
   4391 
   4392     return rv;
   4393 }
   4394 
   4395 #if defined(BCM_TOMAHAWK_SUPPORT)
   4396 void
   4397 _soc_mem_fpem_entry_cache_entry_validate(int unit, soc_mem_t mem, uint32 *entry,
   4398                                          uint8 *vmap, int *index)
   4399 {
   4400     int vldf = VALID_0f;
   4401     int keyf = KEY_TYPE_0f;
   4402 
   4403 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
   4404     if (SOC_IS_TRIDENT3X(unit) || SOC_IS_TOMAHAWK3(unit)) {
   4405         vldf = BASE_VALID_0f;
   4406         keyf = KEY_TYPEf;
   4407     }
   4408 #endif /* BCM_TRIDENT3_SUPPORT or BCM_TOMAHAWK3_SUPPORT */
   4409     switch (mem) {
   4410     case EXACT_MATCH_2m:
   4411     case EXACT_MATCH_2_PIPE0m:
   4412     case EXACT_MATCH_2_PIPE1m:
   4413     case EXACT_MATCH_2_PIPE2m:
   4414     case EXACT_MATCH_2_PIPE3m:
   4415         if (!soc_mem_field32_get(unit, EXACT_MATCH_2m, entry,
   4416                     vldf)) {
   4417             CACHE_VMAP_CLR(vmap, *index);
   4418             break;
   4419         }
   4420         switch(soc_mem_field32_get(unit, EXACT_MATCH_2m, entry, keyf)) {
   4421         case TH_FPEM_HASH_KEY_TYPE_320B:
   4422             CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4423             CACHE_VMAP_CLR(vmap, *index);
   4424             break;
   4425         case TH_FPEM_HASH_KEY_TYPE_128B:
   4426         case TH_FPEM_HASH_KEY_TYPE_160B:
   4427             /* let vmap bit remain set */
   4428             break;
   4429         default: /* illegal key_type */
   4430             CACHE_VMAP_CLR(vmap, *index);
   4431             break;
   4432         }
   4433         break;
   4434     
   4435     case EXACT_MATCH_4m:
   4436     case EXACT_MATCH_4_PIPE0m:
   4437     case EXACT_MATCH_4_PIPE1m:
   4438     case EXACT_MATCH_4_PIPE2m:
   4439     case EXACT_MATCH_4_PIPE3m:
   4440         if (!soc_mem_field32_get(unit, EXACT_MATCH_4m, entry,
   4441                     vldf)) {
   4442             CACHE_VMAP_CLR(vmap, *index);
   4443             break;
   4444         }
   4445         if (TH_FPEM_HASH_KEY_TYPE_320B !=
   4446                 soc_mem_field32_get(unit, EXACT_MATCH_4m, entry,
   4447                                     keyf)) {
   4448             CACHE_VMAP_CLR(vmap, *index);
   4449         }
   4450         break;
   4451 
   4452     default:
   4453         break;
   4454     }
   4455 }
   4456 #endif /* BCM_TOMAHAWK_SUPPORT */
   4457 
   4458 void
   4459 _soc_mem_l3_entry_cache_entry_validate(int unit, soc_mem_t mem, uint32 *entry,
   4460                                        uint8 *vmap, int *index)
   4461 {
   4462     if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_ONLYm, KEY_TYPEf)) {
   4463 #ifdef BCM_TRIDENT2_SUPPORT
   4464         if (SOC_IS_TD2_TT2(unit)) {
   4465 #ifdef BCM_TOMAHAWK_SUPPORT
   4466             if (SOC_IS_TOMAHAWKX(unit)) {
   4467                 switch (mem) {
   4468                 case L3_ENTRY_ONLYm:
   4469                 case L3_ENTRY_IPV4_UNICASTm:
   4470                     if (!soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, VALIDf)) {
   4471                         CACHE_VMAP_CLR(vmap, *index);
   4472                         break;
   4473                     }
   4474                     switch (soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, KEY_TYPEf)) {
   4475                     case TH_L3_HASH_KEY_TYPE_V4MC:
   4476                     case TH_L3_HASH_KEY_TYPE_V4UC_EXT:
   4477                     case TH_L3_HASH_KEY_TYPE_DST_NAT:
   4478                     case TH_L3_HASH_KEY_TYPE_DST_NAPT:
   4479                     case TH_L3_HASH_KEY_TYPE_V6UC:
   4480                         CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4481                         CACHE_VMAP_CLR(vmap, *index);
   4482                         break;
   4483                     case TH_L3_HASH_KEY_TYPE_V6MC:
   4484                     case TH_L3_HASH_KEY_TYPE_V6UC_EXT:
   4485                         CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4486                         CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4487                         CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4488                         CACHE_VMAP_CLR(vmap, *index);
   4489                         break;
   4490                     case TH_L3_HASH_KEY_TYPE_V4UC:
   4491                     case TH_L3_HASH_KEY_TYPE_TRILL:
   4492                         /* let vmap bit remain set */
   4493                         break;
   4494                     default: /* illegal key_type */
   4495                         CACHE_VMAP_CLR(vmap, *index);
   4496                         break;
   4497                     }
   4498                     break;
   4499                 case L3_ENTRY_IPV4_MULTICASTm:
   4500                     if (!soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, VALIDf)) {
   4501                         CACHE_VMAP_CLR(vmap, *index);
   4502                         break;
   4503                     }
   4504                     switch (soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, KEY_TYPEf)) {
   4505                     case TH_L3_HASH_KEY_TYPE_V4UC:
   4506                     case TH_L3_HASH_KEY_TYPE_TRILL:
   4507                     case TH_L3_HASH_KEY_TYPE_V6UC:
   4508                         CACHE_VMAP_CLR(vmap, *index);
   4509                         break;
   4510                     case TH_L3_HASH_KEY_TYPE_V6MC:
   4511                     case TH_L3_HASH_KEY_TYPE_V6UC_EXT:
   4512                         CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4513                         CACHE_VMAP_CLR(vmap, *index);
   4514                         break;
   4515                     case TH_L3_HASH_KEY_TYPE_V4MC:
   4516                     case TH_L3_HASH_KEY_TYPE_V4UC_EXT:
   4517                     case TH_L3_HASH_KEY_TYPE_DST_NAT:
   4518                     case TH_L3_HASH_KEY_TYPE_DST_NAPT:
   4519                         /* let vmap bit remain set */
   4520                         break;
   4521                     default: /* illegal key_type */
   4522                         CACHE_VMAP_CLR(vmap, *index);
   4523                         break;
   4524                     }
   4525                     break;
   4526                 case L3_ENTRY_IPV6_UNICASTm:
   4527                     if (!soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, VALIDf)) {
   4528                         CACHE_VMAP_CLR(vmap, *index);
   4529                         break;
   4530                     }
   4531                     switch (soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, KEY_TYPEf)) {
   4532                     case TH_L3_HASH_KEY_TYPE_V4UC:
   4533                     case TH_L3_HASH_KEY_TYPE_TRILL:
   4534                     case TH_L3_HASH_KEY_TYPE_V4MC:
   4535                     case TH_L3_HASH_KEY_TYPE_V4UC_EXT:
   4536                     case TH_L3_HASH_KEY_TYPE_DST_NAT:
   4537                     case TH_L3_HASH_KEY_TYPE_DST_NAPT:
   4538                         CACHE_VMAP_CLR(vmap, *index);
   4539                         break;
   4540                     case TH_L3_HASH_KEY_TYPE_V6MC:
   4541                     case TH_L3_HASH_KEY_TYPE_V6UC_EXT:
   4542                         CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4543                         CACHE_VMAP_CLR(vmap, *index);
   4544                         break;
   4545                     case TH_L3_HASH_KEY_TYPE_V6UC:
   4546                         /* let vmap bit remain set */
   4547                         break;
   4548                     default: /* illegal key_type */
   4549                         CACHE_VMAP_CLR(vmap, *index);
   4550                         break;
   4551                     }
   4552                     break;
   4553                 case L3_ENTRY_IPV6_MULTICASTm:
   4554                     if (!soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, VALIDf)) {
   4555                         CACHE_VMAP_CLR(vmap, *index);
   4556                         break;
   4557                     }
   4558                     switch (soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, KEY_TYPEf)) {
   4559                     case TH_L3_HASH_KEY_TYPE_V6MC:
   4560                     case TH_L3_HASH_KEY_TYPE_V6UC_EXT:
   4561                         break;
   4562                     default:
   4563                         CACHE_VMAP_CLR(vmap, *index);
   4564                         break;
   4565                     }
   4566                     break;
   4567                 default:
   4568                     break;
   4569                 }
   4570             } else
   4571 #endif /* BCM_TOMAHAWK_SUPPORT */
   4572             {
   4573                 switch (mem) {
   4574                 case L3_ENTRY_ONLYm:
   4575                 case L3_ENTRY_IPV4_UNICASTm:
   4576                     if (!soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, VALIDf)) {
   4577                         CACHE_VMAP_CLR(vmap, *index);
   4578                         break;
   4579                     }
   4580                     switch (soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, KEY_TYPEf)) {
   4581                     case TD2_L3_HASH_KEY_TYPE_V4UC_EXT:
   4582                     case TD2_L3_HASH_KEY_TYPE_V4MC:
   4583                     case TD2_L3_HASH_KEY_TYPE_V4L2MC:
   4584                     case TD2_L3_HASH_KEY_TYPE_V4L2VPMC:
   4585                     case TD2_L3_HASH_KEY_TYPE_V6UC:
   4586                     case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT:
   4587                     case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT:
   4588                     case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT:
   4589                     case TD2_L3_HASH_KEY_TYPE_DST_NAT:
   4590                     case TD2_L3_HASH_KEY_TYPE_DST_NAPT:
   4591                         CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4592                         CACHE_VMAP_CLR(vmap, *index);
   4593                         break;
   4594                     case TD2_L3_HASH_KEY_TYPE_V6UC_EXT:
   4595                     case TD2_L3_HASH_KEY_TYPE_V6MC:
   4596                     case TD2_L3_HASH_KEY_TYPE_V6L2MC:
   4597                     case TD2_L3_HASH_KEY_TYPE_V6L2VPMC:
   4598                         CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4599                         CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4600                         CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4601                         CACHE_VMAP_CLR(vmap, *index);
   4602                         break;
   4603                     case TD2_L3_HASH_KEY_TYPE_V4UC:
   4604                     case TD2_L3_HASH_KEY_TYPE_TRILL:
   4605                     case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN:
   4606                     case TD2_L3_HASH_KEY_TYPE_FCOE_HOST:
   4607                     case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP:
   4608                         /* let vmap bit remain set */
   4609                         break;
   4610                     default: /* illegal key_type */
   4611                         CACHE_VMAP_CLR(vmap, *index);
   4612                         break;
   4613                     }
   4614                     break;
   4615                 case L3_ENTRY_IPV4_MULTICASTm:
   4616                     if (!soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, VALIDf)) {
   4617                         CACHE_VMAP_CLR(vmap, *index);
   4618                         break;
   4619                     }
   4620                     switch (soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, KEY_TYPEf)) {
   4621                     case TD2_L3_HASH_KEY_TYPE_V4UC:
   4622                     case TD2_L3_HASH_KEY_TYPE_TRILL:
   4623                     case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN:
   4624                     case TD2_L3_HASH_KEY_TYPE_FCOE_HOST:
   4625                     case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP:
   4626                     case TD2_L3_HASH_KEY_TYPE_V6UC:
   4627                         CACHE_VMAP_CLR(vmap, *index);
   4628                         break;
   4629                     case TD2_L3_HASH_KEY_TYPE_V6UC_EXT:
   4630                     case TD2_L3_HASH_KEY_TYPE_V6MC:
   4631                     case TD2_L3_HASH_KEY_TYPE_V6L2MC:
   4632                     case TD2_L3_HASH_KEY_TYPE_V6L2VPMC:
   4633                         CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4634                         CACHE_VMAP_CLR(vmap, *index);
   4635                         break;
   4636                     case TD2_L3_HASH_KEY_TYPE_V4UC_EXT:
   4637                     case TD2_L3_HASH_KEY_TYPE_V4MC:
   4638                     case TD2_L3_HASH_KEY_TYPE_V4L2MC:
   4639                     case TD2_L3_HASH_KEY_TYPE_V4L2VPMC:
   4640                     case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT:
   4641                     case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT:
   4642                     case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT:
   4643                     case TD2_L3_HASH_KEY_TYPE_DST_NAT:
   4644                     case TD2_L3_HASH_KEY_TYPE_DST_NAPT:
   4645                         /* let vmap bit remain set */
   4646                         break;
   4647                     default: /* illegal key_type */
   4648                         CACHE_VMAP_CLR(vmap, *index);
   4649                         break;
   4650                     }
   4651                     break;
   4652                 case L3_ENTRY_IPV6_UNICASTm:
   4653                     if (!soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, VALIDf)) {
   4654                         CACHE_VMAP_CLR(vmap, *index);
   4655                         break;
   4656                     }
   4657                     switch (soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, KEY_TYPEf)) {
   4658                     case TD2_L3_HASH_KEY_TYPE_V4UC:
   4659                     case TD2_L3_HASH_KEY_TYPE_TRILL:
   4660                     case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN:
   4661                     case TD2_L3_HASH_KEY_TYPE_FCOE_HOST:
   4662                     case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP:
   4663                     case TD2_L3_HASH_KEY_TYPE_V4UC_EXT:
   4664                     case TD2_L3_HASH_KEY_TYPE_V4MC:
   4665                     case TD2_L3_HASH_KEY_TYPE_V4L2MC:
   4666                     case TD2_L3_HASH_KEY_TYPE_V4L2VPMC:
   4667                     case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT:
   4668                     case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT:
   4669                     case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT:
   4670                     case TD2_L3_HASH_KEY_TYPE_DST_NAT:
   4671                     case TD2_L3_HASH_KEY_TYPE_DST_NAPT:
   4672                         CACHE_VMAP_CLR(vmap, *index);
   4673                         break;
   4674                     case TD2_L3_HASH_KEY_TYPE_V6UC_EXT:
   4675                     case TD2_L3_HASH_KEY_TYPE_V6MC:
   4676                     case TD2_L3_HASH_KEY_TYPE_V6L2MC:
   4677                     case TD2_L3_HASH_KEY_TYPE_V6L2VPMC:
   4678                         CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4679                         CACHE_VMAP_CLR(vmap, *index);
   4680                         break;
   4681                     case TD2_L3_HASH_KEY_TYPE_V6UC:
   4682                         /* let vmap bit remain set */
   4683                         break;
   4684                     default: /* illegal key_type */
   4685                         CACHE_VMAP_CLR(vmap, *index);
   4686                         break;
   4687                     }
   4688                     break;
   4689                 case L3_ENTRY_IPV6_MULTICASTm:
   4690                     if (!soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, VALIDf)) {
   4691                         CACHE_VMAP_CLR(vmap, *index);
   4692                         break;
   4693                     }
   4694                     switch (soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, KEY_TYPEf)) {
   4695                     case TD2_L3_HASH_KEY_TYPE_V6UC_EXT:
   4696                     case TD2_L3_HASH_KEY_TYPE_V6MC:
   4697                     case TD2_L3_HASH_KEY_TYPE_V6L2MC:
   4698                     case TD2_L3_HASH_KEY_TYPE_V6L2VPMC:
   4699                         /* let vmap bit remain set */
   4700                         break;
   4701                     default:
   4702                         CACHE_VMAP_CLR(vmap, *index);
   4703                         break;
   4704                     }
   4705                     break;
   4706                 default:
   4707                     break;
   4708                 }
   4709             }
   4710         } else
   4711 #endif /* BCM_TRIDENT2_SUPPORT */
   4712         {
   4713             switch (mem) {
   4714             case L3_ENTRY_ONLYm:
   4715             case L3_ENTRY_IPV4_UNICASTm:
   4716                 if (!soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, VALIDf)) {
   4717                     CACHE_VMAP_CLR(vmap, *index);
   4718                     break;
   4719                 }
   4720                 switch (soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, KEY_TYPEf)) {
   4721                 case TR_L3_HASH_KEY_TYPE_V4MC:
   4722                 case TR_L3_HASH_KEY_TYPE_V6UC:
   4723                     CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4724                     CACHE_VMAP_CLR(vmap, *index);
   4725                     break;
   4726                 case TR_L3_HASH_KEY_TYPE_V6MC:
   4727                     CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4728                     CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4729                     CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4730                     CACHE_VMAP_CLR(vmap, *index);
   4731                     break;
   4732                 default:
   4733                     break;
   4734                 }
   4735                 break;
   4736             case L3_ENTRY_IPV4_MULTICASTm:
   4737             case L3_ENTRY_IPV6_UNICASTm:
   4738                 if (!soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, VALIDf)) {
   4739                     CACHE_VMAP_CLR(vmap, *index);
   4740                     break;
   4741                 }
   4742                 switch (soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, KEY_TYPEf)) {
   4743                 case TR_L3_HASH_KEY_TYPE_V4UC:
   4744                 case TR_L3_HASH_KEY_TYPE_LMEP:
   4745                 case TR_L3_HASH_KEY_TYPE_RMEP:
   4746                 case TR_L3_HASH_KEY_TYPE_TRILL:
   4747                     CACHE_VMAP_CLR(vmap, *index);
   4748                     break;
   4749                 case TR_L3_HASH_KEY_TYPE_V4MC:
   4750                     if (mem == L3_ENTRY_IPV6_UNICASTm) {
   4751                         CACHE_VMAP_CLR(vmap, *index);
   4752                     }
   4753                     break;
   4754                 case TR_L3_HASH_KEY_TYPE_V6UC:
   4755                     if (mem == L3_ENTRY_IPV4_MULTICASTm) {
   4756                         CACHE_VMAP_CLR(vmap, *index);
   4757                     }
   4758                     break;
   4759                 case TR_L3_HASH_KEY_TYPE_V6MC:
   4760                     CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4761                     CACHE_VMAP_CLR(vmap, *index);
   4762                     break;
   4763                 default:
   4764                     break;
   4765                 }
   4766                 break;
   4767             case L3_ENTRY_IPV6_MULTICASTm:
   4768                 if (!soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, VALIDf)) {
   4769                     CACHE_VMAP_CLR(vmap, *index);
   4770                     break;
   4771                 }
   4772                 switch (soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, KEY_TYPEf)) {
   4773                 case TR_L3_HASH_KEY_TYPE_V6MC:
   4774                     break;
   4775                 default:
   4776                     CACHE_VMAP_CLR(vmap, *index);
   4777                     break;
   4778                 }
   4779                 break;
   4780             default:
   4781                 break;
   4782             }
   4783         }
   4784     }
   4785 #ifdef BCM_TRIUMPH3_SUPPORT
   4786     else if (SOC_MEM_IS_VALID(unit, L3_ENTRY_1m)) {
   4787         switch (mem) {
   4788         case L3_ENTRY_1m:
   4789             if (!soc_mem_field32_get(unit, mem, entry, VALIDf)) {
   4790                 CACHE_VMAP_CLR(vmap, *index);
   4791                 break;
   4792             }
   4793             switch (soc_mem_field32_get(unit, mem, entry, KEY_TYPEf)) {
   4794             case SOC_MEM_VIEW_L3_ENTRY_2_IPV4UC:
   4795             case SOC_MEM_VIEW_L3_ENTRY_2_IPV4MC:
   4796             case SOC_MEM_VIEW_L3_ENTRY_2_IPV6UC:
   4797                 CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4798                 CACHE_VMAP_CLR(vmap, *index);
   4799                 break;
   4800             case SOC_MEM_VIEW_L3_ENTRY_4_IPV6UC:
   4801             case SOC_MEM_VIEW_L3_ENTRY_4_IPV6MC:
   4802                 CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4803                 CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4804                 CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4805                 CACHE_VMAP_CLR(vmap, *index);
   4806                 break;
   4807             default:
   4808                 break;
   4809             }
   4810             break;
   4811         case L3_ENTRY_2m:
   4812             if (!soc_mem_field32_get(unit, mem, entry, VALID_0f)) {
   4813                 CACHE_VMAP_CLR(vmap, *index);
   4814                 break;
   4815             }
   4816             switch (soc_mem_field32_get(unit, mem, entry, KEY_TYPE_0f)) {
   4817             case SOC_MEM_VIEW_L3_ENTRY_2_IPV4UC:
   4818             case SOC_MEM_VIEW_L3_ENTRY_2_IPV4MC:
   4819             case SOC_MEM_VIEW_L3_ENTRY_2_IPV6UC:
   4820                 CACHE_VMAP_CLR(vmap, *index);
   4821                 break;
   4822             case SOC_MEM_VIEW_L3_ENTRY_4_IPV6UC:
   4823             case SOC_MEM_VIEW_L3_ENTRY_4_IPV6MC:
   4824                 CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4825                 CACHE_VMAP_CLR(vmap, *index);
   4826                 break;
   4827             default:
   4828                 break;
   4829             }
   4830             break;
   4831         case L3_ENTRY_4m:
   4832             if (!soc_mem_field32_get(unit, mem, entry, VALID_0f)) {
   4833                 CACHE_VMAP_CLR(vmap, *index);
   4834                 break;
   4835             }
   4836             switch (soc_mem_field32_get(unit, mem, entry, KEY_TYPE_0f)) {
   4837             case SOC_MEM_VIEW_L3_ENTRY_4_IPV6UC:
   4838             case SOC_MEM_VIEW_L3_ENTRY_4_IPV6MC:
   4839                 break;
   4840             default:
   4841                 CACHE_VMAP_CLR(vmap, *index);
   4842                 break;
   4843             }
   4844             break;
   4845         default:
   4846             break;
   4847         }
   4848     }
   4849 #endif /* BCM_TRIUMPH3_SUPPORT */
   4850 #ifdef BCM_TOMAHAWK3_SUPPORT
   4851     else if (SOC_IS_TOMAHAWK3(unit)) {
   4852         switch (mem) {
   4853         case L3_ENTRY_SINGLEm:
   4854         case L3_ENTRY_ONLY_SINGLEm:
   4855             if (!soc_mem_field32_get(unit, L3_ENTRY_ONLY_SINGLEm, entry, BASE_VALIDf)) {
   4856                 CACHE_VMAP_CLR(vmap, *index);
   4857                 break;
   4858             }
   4859             switch (soc_mem_field32_get(unit, L3_ENTRY_ONLY_SINGLEm, entry, KEY_TYPEf)) {
   4860             case TH3_L3_HASH_KEY_TYPE_V4MC:
   4861             case TH3_L3_HASH_KEY_TYPE_V6UC:
   4862                 CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4863                 CACHE_VMAP_CLR(vmap, *index);
   4864                 break;
   4865             case TH3_L3_HASH_KEY_TYPE_V6MC:
   4866                 CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4867                 CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4868                 CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4869                 CACHE_VMAP_CLR(vmap, *index);
   4870                 break;
   4871             case TH3_L3_HASH_KEY_TYPE_V4UC:
   4872                 /* let vmap bit remain set */
   4873                 break;
   4874             default: /* illegal key_type */
   4875                 CACHE_VMAP_CLR(vmap, *index);
   4876                 break;
   4877             }
   4878             break;
   4879         case L3_ENTRY_DOUBLEm:
   4880         case L3_ENTRY_ONLY_DOUBLEm:
   4881             if (!soc_mem_field32_get(unit, L3_ENTRY_ONLY_DOUBLEm, entry, BASE_VALID_0f)) {
   4882                 CACHE_VMAP_CLR(vmap, *index);
   4883                 break;
   4884             }
   4885             switch (soc_mem_field32_get(unit, L3_ENTRY_ONLY_DOUBLEm, entry, KEY_TYPEf)) {
   4886             case TH3_L3_HASH_KEY_TYPE_V4UC:
   4887                 CACHE_VMAP_CLR(vmap, *index);
   4888                 break;
   4889             case TH3_L3_HASH_KEY_TYPE_V6MC:
   4890                 CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4891                 CACHE_VMAP_CLR(vmap, *index);
   4892                 break;
   4893             case TH3_L3_HASH_KEY_TYPE_V4MC:
   4894             case TH3_L3_HASH_KEY_TYPE_V6UC:
   4895                 /* let vmap bit remain set */
   4896                 break;
   4897             default: /* illegal key_type */
   4898                 CACHE_VMAP_CLR(vmap, *index);
   4899                 break;
   4900             }
   4901             break;
   4902         case L3_ENTRY_QUADm:
   4903         case L3_ENTRY_ONLY_QUADm:
   4904             if (!soc_mem_field32_get(unit, L3_ENTRY_ONLY_QUADm, entry, BASE_VALID_0f)) {
   4905                 CACHE_VMAP_CLR(vmap, *index);
   4906                 break;
   4907             }
   4908             switch (soc_mem_field32_get(unit, L3_ENTRY_ONLY_QUADm, entry, KEY_TYPEf)) {
   4909             case TH3_L3_HASH_KEY_TYPE_V6MC:
   4910                 break;
   4911             default:
   4912                 CACHE_VMAP_CLR(vmap, *index);
   4913                 break;
   4914             }
   4915             break;
   4916         default:
   4917             break;
   4918         }
   4919     }
   4920 #endif
   4921 #ifdef BCM_TRIDENT3_SUPPORT
   4922     else if (SOC_MEM_IS_VALID(unit, L3_ENTRY_ONLY_SINGLEm) ||
   4923              SOC_MEM_IS_VALID(unit, L3_ENTRY_ONLY_DOUBLEm) ||
   4924              SOC_MEM_IS_VALID(unit, L3_ENTRY_ONLY_QUADm)) {
   4925             if (SOC_IS_TRIDENT3X(unit)) {
   4926                 switch (mem) {
   4927                 case L3_ENTRY_ONLY_SINGLEm:
   4928                 case L3_ENTRY_SINGLEm:
   4929                     if (!soc_mem_field32_get(unit, L3_ENTRY_ONLY_SINGLEm, entry, BASE_VALIDf)) {
   4930                         CACHE_VMAP_CLR(vmap, *index);
   4931                         break;
   4932                     }
   4933                     switch (soc_mem_field32_get(unit, L3_ENTRY_ONLY_SINGLEm, entry, KEY_TYPEf)) {
   4934                     case TD3_L3_HASH_KEY_TYPE_V4MC:
   4935                     case TD3_L3_HASH_KEY_TYPE_V6UC:
   4936                     case TD3_L3_HASH_KEY_TYPE_L2_IPV4_MULTICAST:
   4937                     case TD3_L3_HASH_KEY_TYPE_L2VP_IPV4_MULTICAST:
   4938                         CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4939                         CACHE_VMAP_CLR(vmap, *index);
   4940                         break;
   4941                     case TD3_L3_HASH_KEY_TYPE_V6MC:
   4942                     case TD3_L3_HASH_KEY_TYPE_L2_IPV6_MULTICAST:
   4943                     case TD3_L3_HASH_KEY_TYPE_L2VP_IPV6_MULTICAST:
   4944                         CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4945                         CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4946                         CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4947                         CACHE_VMAP_CLR(vmap, *index);
   4948                         break;
   4949                     case TD3_L3_HASH_KEY_TYPE_V4UC:
   4950                     case TD3_L3_HASH_KEY_TYPE_TRILL:
   4951                         /* let vmap bit remain set */
   4952                         break;
   4953                     default: /* illegal key_type */
   4954                         CACHE_VMAP_CLR(vmap, *index);
   4955                         break;
   4956                     }
   4957                     break;
   4958                 case L3_ENTRY_ONLY_DOUBLEm:
   4959                 case L3_ENTRY_DOUBLEm:
   4960                     if (!soc_mem_field32_get(unit, L3_ENTRY_ONLY_DOUBLEm, entry, BASE_VALID_0f)) {
   4961                         CACHE_VMAP_CLR(vmap, *index);
   4962                         break;
   4963                     }
   4964                     switch (soc_mem_field32_get(unit, L3_ENTRY_ONLY_DOUBLEm, entry, KEY_TYPEf)) {
   4965                     case TD3_L3_HASH_KEY_TYPE_V4UC:
   4966                     case TD3_L3_HASH_KEY_TYPE_TRILL:
   4967                         CACHE_VMAP_CLR(vmap, *index);
   4968                         break;
   4969                     case TD3_L3_HASH_KEY_TYPE_V6MC:
   4970                     case TD3_L3_HASH_KEY_TYPE_L2_IPV6_MULTICAST:
   4971                     case TD3_L3_HASH_KEY_TYPE_L2VP_IPV6_MULTICAST:
   4972                         CACHE_VMAP_CLR(vmap, *index); *index += 1;
   4973                         CACHE_VMAP_CLR(vmap, *index);
   4974                         break;
   4975                     case TD3_L3_HASH_KEY_TYPE_V4MC:
   4976                     case TD3_L3_HASH_KEY_TYPE_V6UC:
   4977                     case TD3_L3_HASH_KEY_TYPE_L2_IPV4_MULTICAST:
   4978                     case TD3_L3_HASH_KEY_TYPE_L2VP_IPV4_MULTICAST:
   4979                         /* let vmap bit remain set */
   4980                         break;
   4981                     default: /* illegal key_type */
   4982                         CACHE_VMAP_CLR(vmap, *index);
   4983                         break;
   4984                     }
   4985                     break;
   4986                 case L3_ENTRY_ONLY_QUADm:
   4987                 case L3_ENTRY_QUADm:
   4988                     if (!soc_mem_field32_get(unit, L3_ENTRY_ONLY_QUADm, entry, BASE_VALID_0f)) {
   4989                         CACHE_VMAP_CLR(vmap, *index);
   4990                         break;
   4991                     }
   4992                     switch (soc_mem_field32_get(unit, L3_ENTRY_ONLY_QUADm, entry, KEY_TYPEf)) {
   4993                     case TD3_L3_HASH_KEY_TYPE_V6MC:
   4994                     case TD3_L3_HASH_KEY_TYPE_L2_IPV6_MULTICAST:
   4995                     case TD3_L3_HASH_KEY_TYPE_L2VP_IPV6_MULTICAST:
   4996                         /* let vmap bit remain set */
   4997                         break;
   4998                     default: /* illegal key_type */
   4999                         CACHE_VMAP_CLR(vmap, *index);
   5000                         break;
   5001                     }
   5002                     break;
   5003                 default:
   5004                     break;
   5005                 }
   5006            }
   5007     }
   5008 #endif
   5009 }
   5010 
   5011 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   5012 #ifdef BCM_WARM_BOOT_SUPPORT
   5013 int
   5014 soc_mem_block_count(int unit, soc_mem_t mem, int *count)
   5015 {
   5016     int blk_count = 0, blk;
   5017 
   5018     if (NULL == count) {
   5019         return SOC_E_PARAM;
   5020     }
   5021 
   5022     SOC_MEM_BLOCK_ITER(unit, mem, blk) {
   5023         blk_count++;
   5024     }
   5025 
   5026     *count = blk_count;
   5027     return SOC_E_NONE;
   5028 }
   5029 
   5030 int
   5031 soc_control_overlay_tcam_scache_init(int unit, int blk_num)
   5032 {
   5033     soc_scache_handle_t scache_handle;
   5034     uint8 *overlay_tcam_scache_ptr;
   5035     int rv;
   5036     int stable_size, index_count = 0;
   5037     int alloc_sz;
   5038     int create = SOC_WARM_BOOT(unit) ? FALSE : TRUE;
   5039 
   5040     if (SOC_MEM_IS_VALID(unit, FP_GLOBAL_MASK_TCAMm)) {
   5041         index_count = soc_mem_index_count(unit, FP_GLOBAL_MASK_TCAMm);
   5042         alloc_sz = SHR_BITALLOCSIZE(index_count) * blk_num;
   5043     } else {
   5044         return SOC_E_UNAVAIL;
   5045     }
   5046 
   5047     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   5048     if (!stable_size) {
   5049         /* If stable not allocated, just return */
   5050         return SOC_E_NONE;
   5051     }
   5052     SOC_SCACHE_ALIGN_SIZE(alloc_sz);
   5053 
   5054     alloc_sz += SOC_WB_SCACHE_CONTROL_SIZE;
   5055 
   5056     if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
   5057         SOC_SCACHE_HANDLE_SET(scache_handle, unit,
   5058                               SOC_SCACHE_SOC_OVERLAY_TCAM_HANDLE, 0);
   5059         /* Get the pointer for the Level 2 cache */
   5060         rv = soc_extended_scache_ptr_get(unit, scache_handle, create,
   5061                                          create ? alloc_sz : 0,
   5062                                          &overlay_tcam_scache_ptr);
   5063         if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) {
   5064             return rv;
   5065         } else if (SOC_E_NOT_FOUND == rv && !create) {
   5066             /* Not yet allocated in upgrade */
   5067             rv = soc_extended_scache_ptr_get(unit, scache_handle, TRUE,
   5068                                              alloc_sz,
   5069                                              &overlay_tcam_scache_ptr);
   5070             if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) {
   5071                 return rv;
   5072             }
   5073             if (SOC_SUCCESS(rv)) {
   5074                 SOC_FP_TCAM_SCACHE_HANDLE(unit) = overlay_tcam_scache_ptr;
   5075             }
   5076         } else if (SOC_FAILURE(rv)) {
   5077             return rv;
   5078         } else {
   5079             SOC_FP_TCAM_SCACHE_HANDLE(unit) = overlay_tcam_scache_ptr;
   5080         }
   5081     }
   5082 
   5083     return SOC_E_NONE;
   5084 }
   5085 
   5086 int
   5087 soc_control_overlay_tcam_scache_sync(int unit)
   5088 {
   5089     uint8 *overlay_tcam_scache_ptr = SOC_FP_TCAM_SCACHE_HANDLE(unit);
   5090     SHR_BITDCL *overlay_tcam_bmp;
   5091     int stable_size = 0, index_count, blk, scache_size;
   5092     uint16 version = SOC_OVERLAY_TCAM_WARMBOOT_DEFAULT_VERSION;
   5093     soc_mem_t mem;
   5094     soc_memstate_t *memState;
   5095 
   5096     if (SOC_MEM_IS_VALID(unit, FP_GLOBAL_MASK_TCAMm)) {
   5097         mem = FP_GLOBAL_MASK_TCAMm;
   5098         index_count = soc_mem_index_count(unit, mem);
   5099         scache_size = SHR_BITALLOCSIZE(index_count);
   5100         memState = &SOC_MEM_STATE(unit, mem);
   5101     } else {
   5102         return SOC_E_UNAVAIL;
   5103     }
   5104 
   5105     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   5106     if (!stable_size) {
   5107         /* If stable not allocated, just return */
   5108         return SOC_E_NONE;
   5109     }
   5110     if (NULL == overlay_tcam_scache_ptr) {
   5111         return SOC_E_UNAVAIL;
   5112     }
   5113 
   5114     /* First save version */
   5115     sal_memcpy(overlay_tcam_scache_ptr, &version, sizeof(version));
   5116     overlay_tcam_scache_ptr += sizeof(version);
   5117 
   5118     /* Save overlay tcam bitmap */
   5119     SOC_MEM_BLOCK_ITER(unit, mem, blk) {
   5120         overlay_tcam_bmp = memState->OverlayTcamMap[blk];
   5121 
   5122         if (NULL == overlay_tcam_bmp) {
   5123             return SOC_E_INIT;
   5124         }
   5125         sal_memcpy(overlay_tcam_scache_ptr,
   5126                    overlay_tcam_bmp,
   5127                    scache_size);
   5128         overlay_tcam_scache_ptr += scache_size;
   5129     }
   5130     return SOC_E_NONE;
   5131 }
   5132 
   5133 int
   5134 soc_control_overlay_tcam_scache_load(int unit, void *bmp, int blk,
   5135                                      uint8 *overlay_tcam_scache_ptr)
   5136 {
   5137     SHR_BITDCL *overlay_tcam_bmp = (SHR_BITDCL *)bmp;
   5138     int index_count, scache_size, blk_count;
   5139     int stable_size = 0;
   5140 
   5141     if (SOC_MEM_IS_VALID(unit, FP_GLOBAL_MASK_TCAMm)) {
   5142         index_count = soc_mem_index_count(unit, FP_GLOBAL_MASK_TCAMm);
   5143         scache_size = SHR_BITALLOCSIZE(index_count);
   5144     } else {
   5145         return SOC_E_UNAVAIL;
   5146     }
   5147 
   5148     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   5149     if (!stable_size) {
   5150         /* If stable not allocated, just return */
   5151         return SOC_E_RESOURCE;
   5152     }
   5153 
   5154     if (NULL == overlay_tcam_scache_ptr) {
   5155         return SOC_E_UNAVAIL;
   5156     }
   5157 
   5158     if (NULL == overlay_tcam_bmp) {
   5159         return SOC_E_INIT;
   5160     }
   5161 
   5162     soc_mem_block_count(unit, FP_GLOBAL_MASK_TCAMm, &blk_count);
   5163     if (blk >= blk_count || blk < 0) {
   5164         return SOC_E_RESOURCE;
   5165     }
   5166 
   5167     if (SOC_WARM_BOOT(unit)) {
   5168         sal_memcpy(overlay_tcam_bmp,
   5169                    overlay_tcam_scache_ptr + scache_size*blk,
   5170                    scache_size);
   5171     }
   5172     return SOC_E_NONE;
   5173 }
   5174 
   5175 /*
   5176  * Function:
   5177  *    soc_mem_cache_overlay_tcam_check
   5178  * Purpose:
   5179  *    Check if the overlay tcam cache is valid. Clear the invalid entry's
   5180  *    cache and vmap.
   5181  */
   5182 int
   5183 soc_mem_cache_overlay_tcam_check(int unit, soc_mem_t mem,
   5184                          SHR_BITDCL *overlay_tcam_bmp, uint8 *vmap)
   5185 {
   5186     int idx, index_min, index_max;
   5187 
   5188     if (NULL == vmap) {
   5189         return SOC_E_PARAM;
   5190     }
   5191 
   5192     index_min = soc_mem_index_min(unit, mem);
   5193     index_max = soc_mem_index_max(unit, mem);
   5194 
   5195     if (mem != FP_GLOBAL_MASK_TCAMm &&
   5196         mem != FP_GM_FIELDSm) {
   5197         return SOC_E_NONE;
   5198     }
   5199 
   5200     if (NULL == overlay_tcam_bmp) {
   5201         return SOC_E_INIT;
   5202     }
   5203 
   5204     for (idx = index_min;
   5205          idx <= index_max;
   5206          idx++) {
   5207             if (FP_GLOBAL_MASK_TCAMm == mem) {
   5208                 if (SHR_BITGET(overlay_tcam_bmp, idx)) {
   5209                     CACHE_VMAP_CLR(vmap, idx);
   5210                 }
   5211             } else if (FP_GM_FIELDSm == mem) {
   5212                 if (!SHR_BITGET(overlay_tcam_bmp, idx)) {
   5213                     CACHE_VMAP_CLR(vmap, idx);
   5214                 }
   5215             }
   5216     }
   5217 
   5218     return SOC_E_NONE;
   5219 }
   5220 
   5221 /*
   5222  * Function:
   5223  *    soc_mem_overlay_tcam_update
   5224  * Purpose:
   5225  *    Update the overlay tcam bitmap during writing or clearing
   5226  */
   5227 void
   5228 soc_mem_overlay_tcam_update(int unit, soc_mem_t mem, int blk,
   5229                          int index_begin, int index_end)
   5230 {
   5231     int num_entries;
   5232     SHR_BITDCL *soc_overlay_tcam_bmp;
   5233     soc_memstate_t *memState;
   5234 
   5235     if (mem != FP_GLOBAL_MASK_TCAMm &&
   5236         mem != FP_GM_FIELDSm) {
   5237         return;
   5238     }
   5239 
   5240     if (index_end - index_begin < 0 ||
   5241         soc_mem_index_min(unit, mem) > index_begin ||
   5242         soc_mem_index_max(unit, mem) < index_end) {
   5243         return;
   5244     }
   5245 
   5246     memState = &SOC_MEM_STATE(unit, mem);
   5247 
   5248     soc_overlay_tcam_bmp = memState->OverlayTcamMap[blk];
   5249     if (NULL == soc_overlay_tcam_bmp) {
   5250         return;
   5251     }
   5252 
   5253     num_entries = index_end - index_begin + 1;
   5254 
   5255     if (mem == FP_GLOBAL_MASK_TCAMm) {
   5256         SHR_BITCLR_RANGE(soc_overlay_tcam_bmp, index_begin, num_entries);
   5257     } else if (mem == FP_GM_FIELDSm) {
   5258         SHR_BITSET_RANGE(soc_overlay_tcam_bmp, index_begin, num_entries);
   5259     }
   5260 }
   5261 
   5262 /*
   5263  * Function:
   5264  *    soc_mem_overlay_tcam_cache_set
   5265  * Purpose:
   5266  *    Enable or disable caching for overlay tcam memories
   5267  * Notes:
   5268  *    Set cache for FP_GLOBAL_MASK_TCAMm and FP_GM_FIELDSm
   5269  *    based on OverlayTcamMap.
   5270  */
   5271 int
   5272 soc_mem_overlay_tcam_cache_set(int unit, 
   5273                                 soc_mem_t mem, 
   5274                                 int copyno, 
   5275                                 int enable)
   5276 {
   5277     SHR_BITDCL  *OverlayTcamMap;
   5278     int alloc_sz = 0, rv = SOC_E_NONE;
   5279     int blk_count = 0, index_count = 0, valid_blk = 0, blk;
   5280     soc_memstate_t *mem_state, *mem_state_temp;
   5281     soc_mem_t fp_mem[2] = {FP_GLOBAL_MASK_TCAMm, FP_GM_FIELDSm};
   5282     uint8 *overlay_tcam_scache_ptr = NULL;
   5283     uint16 version = 0;
   5284 
   5285     if (mem != fp_mem[0] && mem != fp_mem[1]) {
   5286         return SOC_E_PARAM;
   5287     }
   5288 
   5289     index_count = soc_mem_index_count(unit, mem);
   5290     alloc_sz = SHR_BITALLOCSIZE(index_count);
   5291     soc_mem_block_count(unit, mem, &blk_count);
   5292     mem_state = &SOC_MEM_STATE(unit, mem);
   5293 
   5294     if (mem == fp_mem[0]) {
   5295         mem_state_temp = &SOC_MEM_STATE(unit, fp_mem[1]);
   5296     } else {
   5297         mem_state_temp = &SOC_MEM_STATE(unit, fp_mem[0]);
   5298     }
   5299 
   5300     /* Init FP overlay tcam bitmap scache*/
   5301     if (enable) {
   5302         rv = soc_control_overlay_tcam_scache_init(unit, blk_count);
   5303         if (SOC_FAILURE(rv)) {
   5304             if (rv == SOC_E_UNAVAIL) {
   5305                 rv = SOC_E_NONE;
   5306             }
   5307             goto _tcam_set_done;
   5308         }
   5309     }
   5310 
   5311     /*load version*/
   5312     if (SOC_WARM_BOOT(unit)) {
   5313         overlay_tcam_scache_ptr = SOC_FP_TCAM_SCACHE_HANDLE(unit);
   5314         if (overlay_tcam_scache_ptr != NULL) {
   5315             sal_memcpy(&version, overlay_tcam_scache_ptr, sizeof(version));
   5316             overlay_tcam_scache_ptr += sizeof(version);
   5317         }
   5318     }
   5319 
   5320     SOC_MEM_BLOCK_ITER(unit, mem, blk) {
   5321         if (copyno != COPYNO_ALL && copyno != blk) {
   5322             continue;
   5323         }
   5324 
   5325         /*
   5326                 *FP_GLOBAL_MASK_TCAMm and FP_GM_FIELDSm share one overlay tcam 
   5327                 *bitmap. So only destory overlay tcam bitmap one time. 
   5328                 */
   5329         if (!enable) {
   5330             if (mem_state->OverlayTcamMap[blk] != NULL) {
   5331                 sal_free(mem_state->OverlayTcamMap[blk]);
   5332                 mem_state->OverlayTcamMap[blk] = NULL;
   5333                 mem_state_temp->OverlayTcamMap[blk] = NULL;
   5334             }
   5335             continue;
   5336         }
   5337 
   5338         /*
   5339                 *Alloc overlay tcam bitmap when OverlayTcamMap for both mems equal NULL
   5340                 */
   5341         if (mem_state->OverlayTcamMap[blk] == NULL) {
   5342             if (mem_state_temp->OverlayTcamMap[blk] == NULL) {
   5343                 if ((OverlayTcamMap =
   5344                     sal_alloc(alloc_sz,
   5345                               "mem XY TCAM BITMAP")) == NULL) {
   5346                     rv = SOC_E_MEMORY;
   5347                     goto _tcam_set_done;
   5348                 }
   5349                 sal_memset(OverlayTcamMap, 0, alloc_sz);
   5350                 mem_state->OverlayTcamMap[blk] = OverlayTcamMap;
   5351 
   5352                 if (SOC_WARM_BOOT(unit)) {
   5353                     /* Recover overlay tcam bitmap from scache*/
   5354                     if (version >= SOC_OVERLAY_TCAM_WARMBOOT_VERSION_1) {
   5355                         rv = soc_control_overlay_tcam_scache_load
   5356                                (unit, OverlayTcamMap, valid_blk, overlay_tcam_scache_ptr);
   5357                     } else {
   5358                         rv = SOC_E_UNAVAIL;
   5359                     }
   5360                     if (SOC_FAILURE(rv)) {
   5361                         if (rv == SOC_E_UNAVAIL) {
   5362                             rv = SOC_E_NONE;
   5363                         }
   5364                         goto _tcam_set_done;
   5365                     }
   5366 
   5367                     /* Clear the invalid vmap based on overlay tcam bitmap*/
   5368                     rv = soc_mem_cache_overlay_tcam_check
   5369                         (unit, mem, OverlayTcamMap, mem_state->vmap[blk]);
   5370                     if (SOC_FAILURE(rv)) {
   5371                         goto _tcam_set_done;
   5372                     }
   5373 
   5374                     valid_blk++;
   5375                 }
   5376             } else {
   5377                 OverlayTcamMap = mem_state_temp->OverlayTcamMap[blk];
   5378                 mem_state->OverlayTcamMap[blk] = OverlayTcamMap;
   5379 
   5380                 if (SOC_WARM_BOOT(unit)) {
   5381                     rv = soc_mem_cache_overlay_tcam_check
   5382                         (unit, mem, OverlayTcamMap, mem_state->vmap[blk]);
   5383                     if (SOC_FAILURE(rv)) {
   5384                         goto _tcam_set_done;
   5385                     }
   5386                 }
   5387             }
   5388         }
   5389     }
   5390 _tcam_set_done:
   5391     return rv;
   5392 }
   5393 #endif
   5394 #endif
   5395 
   5396 /*
   5397  * Function:
   5398  *    soc_mem_cache_set
   5399  * Purpose:
   5400  *    Enable or disable caching for a specified memory or memories
   5401  * Notes:
   5402  *    Only tables whose contents are not modified by hardware in
   5403  *    any way are eligible for caching.
   5404  */
   5405 
   5406 int
   5407 soc_mem_cache_set(int unit, soc_mem_t mem, int copyno, int enable)
   5408 {
   5409     int blk, entry_dw, index_cnt;
   5410     int cache_size, vmap_size, numels = 1, first_array_index = 0;
   5411     uint8 *vmap;
   5412 #if ((defined BCM_XGS_SWITCH_SUPPORT ) || (defined BCM_SAND_SUPPORT))
   5413     uint8 load_cache = 1, l2 = 0;
   5414 #endif
   5415 
   5416     uint32 *cache;
   5417     soc_memstate_t *memState;
   5418     soc_stat_t *stat = SOC_STAT(unit);
   5419     soc_mem_t org_mem = mem;
   5420 
   5421 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HELIX4_SUPPORT) || \
   5422     defined(BCM_KATANA2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || \
   5423     defined(BCM_GREYHOUND_SUPPORT)
   5424     int corrupt_size = 0;
   5425     uint8 *corrupt = NULL;
   5426 #endif
   5427 #ifdef BCM_KATANA2_SUPPORT
   5428     int port_index[15]=
   5429     {1,5,9,13,17,21,25,26,27,28,30,33,37,39,41};
   5430     int port = 0;
   5431     int idx, j;
   5432 #endif /*BCM_KATANA2_SUPPORT */
   5433 #if defined(BCM_TRIDENT2_SUPPORT)
   5434     int skip = 0;
   5435 #endif
   5436 
   5437     assert(SOC_UNIT_VALID(unit));
   5438     _SOC_MEM_REUSE_MEM_STATE(unit, mem);
   5439     SOC_MEM_ALIAS_TO_ORIG(unit,mem);
   5440     assert(SOC_MEM_IS_VALID(unit, mem));
   5441 
   5442     if (!(soc_mem_is_cachable(unit, mem))) {
   5443         return (enable ? SOC_E_UNAVAIL : SOC_E_NONE);
   5444     }
   5445     memState = &SOC_MEM_STATE(unit, mem);
   5446     if (memState->lock == NULL) {
   5447         return SOC_E_NONE;
   5448     }
   5449 
   5450     if (SOC_MEM_INFO(unit,mem).flags & SOC_MEM_FLAG_IS_ARRAY) {
   5451         numels = SOC_MEM_ARRAY_INFO(unit,mem).numels;
   5452         first_array_index = SOC_MEM_ARRAY_INFO(unit,mem).first_array_index;
   5453     }
   5454 
   5455     entry_dw = soc_mem_entry_words(unit, mem);
   5456     index_cnt = soc_mem_index_count(unit, mem);
   5457     /* Change the index for particular memory in case of hole in space */
   5458     if (soc_feature(unit, soc_feature_defip_2_tcams_with_separate_rpf)
   5459        && (mem == L3_DEFIPm)) {
   5460 
   5461        index_cnt +=SOC_DEFIP_HOLE_OFFSET(unit, mem); ;
   5462     }
   5463     cache_size = numels * index_cnt * entry_dw * 4;
   5464     vmap_size = (numels * index_cnt + 7) / 8;
   5465 
   5466 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HELIX4_SUPPORT) || \
   5467     defined(BCM_KATANA2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || \
   5468     defined(BCM_GREYHOUND_SUPPORT)
   5469     /* TCAM tables have corrupt bitmap */
   5470     if((SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) &&
   5471        (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM))) {
   5472         corrupt_size = (index_cnt + 7) / 8;
   5473     }
   5474 #endif
   5475 
   5476     LOG_INFO(BSL_LS_SOC_SOCMEM,
   5477              (BSL_META_U(unit,
   5478                          "soc_mem_cache_set: unit %d memory %s.%s %sable\n"),
   5479               unit, SOC_MEM_UFNAME(unit, mem), SOC_BLOCK_NAME(unit, copyno),
   5480               enable ? "en" : "dis"));
   5481 
   5482     if (copyno != COPYNO_ALL) {
   5483         assert(SOC_MEM_BLOCK_VALID(unit, mem, copyno));
   5484     }
   5485 
   5486     MEM_LOCK(unit, mem);
   5487 
   5488 #ifdef BCM_KATANA2_SUPPORT
   5489     if (SOC_IS_KATANA2(unit) && (mem == VLAN_TABm) && (!enable) ) {
   5490         for (j = 0; j < SOC_MAX_NUM_BLKS; ++j) {
   5491             soc_control[unit]->memState[EGR_VLANm].cache[j] = NULL;
   5492             soc_control[unit]->memState[EGR_VLANm].vmap[j] = NULL;
   5493             soc_control[unit]->memState[EGR_VLANm].corrupt[j] = NULL;
   5494         }
   5495     }
   5496 #endif
   5497     SOC_MEM_BLOCK_ITER(unit, mem, blk) {
   5498         if (copyno != COPYNO_ALL && copyno != blk) {
   5499             continue;
   5500         }
   5501 #if defined(BCM_TRIUMPH3_SUPPORT)
   5502         if (SOC_IS_TRIUMPH3(unit) &&
   5503             ((mem == PORT_EHG_RX_TUNNEL_MASKm) ||
   5504              (mem == PORT_EHG_RX_TUNNEL_DATAm) ||
   5505              (mem == PORT_EHG_TX_TUNNEL_DATAm))) {
   5506             if (!_soc_tr3_port_mem_blk_enabled(unit, blk)) {
   5507                 continue;
   5508             }
   5509         }
   5510 #endif /* BCM_TRIUMPH3_SUPPORT */
   5511         /* Turn off caching if currently enabled. */
   5512         if (memState->cache[blk] != NULL) {
   5513             sal_free(memState->cache[blk]);
   5514             memState->cache[blk] = NULL;
   5515         }
   5516         if (memState->vmap[blk] != NULL) {
   5517             sal_free(memState->vmap[blk]);
   5518             memState->vmap[blk] = NULL;
   5519         }
   5520         /* If we don't so, there are dangling pointer */
   5521         if (org_mem != mem) {
   5522             /* Share the cache and vmap */
   5523             SOC_MEM_STATE(unit, org_mem).cache[blk] = NULL;
   5524             SOC_MEM_STATE(unit, org_mem).vmap[blk] = NULL;
   5525         }
   5526 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HELIX4_SUPPORT) || \
   5527     defined(BCM_KATANA2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || \
   5528     defined(BCM_GREYHOUND_SUPPORT)
   5529         if (memState->corrupt[blk] != NULL) {
   5530             sal_free(memState->corrupt[blk]);
   5531             memState->corrupt[blk] = NULL;
   5532         }
   5533 #endif
   5534 
   5535         if (!enable) {
   5536             continue;
   5537         }
   5538         /* Allocate new cache */
   5539         if ((cache = sal_alloc(cache_size, "table-cache")) == NULL) {
   5540             MEM_UNLOCK(unit, mem);
   5541             return SOC_E_MEMORY;
   5542         }
   5543         stat->mem_cache_count++;
   5544         stat->mem_cache_size += cache_size;
   5545 
   5546         if ((vmap = sal_alloc(vmap_size, "table-vmap")) == NULL) {
   5547             sal_free(cache);
   5548             MEM_UNLOCK(unit, mem);
   5549             return SOC_E_MEMORY;
   5550         }
   5551         stat->mem_cache_vmap_size += vmap_size;
   5552         LOG_VERBOSE(BSL_LS_SOC_SER,
   5553             (BSL_META_U(unit,
   5554                         "soc_mem_cache_set: WB=%0d, memory %s.%s cache_count=%0d, "
   5555                         "cache_size=%0d, vmap_size=%0d \n"),
   5556              SOC_WARM_BOOT(unit), SOC_MEM_UFNAME(unit, mem), SOC_BLOCK_NAME(unit, copyno),
   5557              stat->mem_cache_count, stat->mem_cache_size,
   5558              stat->mem_cache_vmap_size));
   5559 
   5560         sal_memset(vmap, 0, vmap_size); /* zero out all valid bits */
   5561 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HELIX4_SUPPORT) || \
   5562     defined(BCM_KATANA2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || \
   5563     defined(BCM_GREYHOUND_SUPPORT)
   5564         if((SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) &&
   5565            (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM))) {
   5566             /* Allocate corruption bitmap */
   5567             if ((corrupt = sal_alloc(corrupt_size, "corrupt indication map")) == NULL) {
   5568                 sal_free(cache);
   5569                 sal_free(vmap);
   5570                 MEM_UNLOCK(unit, mem);
   5571                 return SOC_E_MEMORY;
   5572             }
   5573             stat->tcam_corrupt_map_size += corrupt_size;
   5574             sal_memset(corrupt, 0, corrupt_size);
   5575         }
   5576 #endif
   5577 
   5578 
   5579 #if ((defined BCM_XGS_SWITCH_SUPPORT ) || (defined BCM_SAND_SUPPORT))
   5580         if (_SOC_MEM_CHK_L2_MEM(mem)) {
   5581             l2 = 1;
   5582         }
   5583         /* NOTE: This is a temporary way of enabling WB mem cache reload case
   5584          *       by case on different devices as support is being implemented.
   5585          *       Eventually this check should go away or be replaced by
   5586          *       soc_feature_mem_wb_cache_reload.
   5587          */
   5588         if (!(SOC_IS_TD_TT(unit) || SOC_IS_ENDURO(unit) || SOC_IS_KATANAX(unit) || SOC_IS_SAND(unit) ||
   5589              (SOC_IS_TRIUMPH3(unit)) || SOC_IS_TRIUMPH(unit) ||
   5590              soc_feature(unit, soc_feature_mem_wb_cache_reload))) {
   5591             
   5592             load_cache = 0;
   5593         }
   5594         /* Pre-load cache from hardware table (if quickly-doable) OR
   5595            we are doing Warm-Boot */
   5596 #ifdef BCM_PETRA_SUPPORT
   5597         if ((soc_feature(unit, soc_feature_table_dma) &&
   5598              (soc_mem_dmaable(unit, mem, blk) || SOC_IS_ARAD(unit)) &&
   5599              (SOC_CONTROL(unit)->soc_flags & SOC_F_INITED) && !l2) ||
   5600             (SOC_WARM_BOOT(unit) && load_cache &&
   5601              (SOC_CONTROL(unit)->mem_scache_ptr == NULL))) {
   5602 #else
   5603         if ((soc_feature(unit, soc_feature_table_dma) &&
   5604              soc_mem_dmaable(unit, mem, blk) &&
   5605              (SOC_CONTROL(unit)->soc_flags & SOC_F_INITED) && !l2) ||
   5606             (SOC_WARM_BOOT(unit) && load_cache &&
   5607              (SOC_CONTROL(unit)->mem_scache_ptr == NULL))) {
   5608 #endif
   5609             uint32 *table;
   5610             int index, index_max = index_cnt - 1, elem;
   5611             int index_min = soc_mem_index_min(unit, mem);
   5612             uint32 entry[SOC_MAX_MEM_WORDS];
   5613 
   5614 #if defined(BCM_TOMAHAWK_SUPPORT)
   5615             if (SOC_IS_TOMAHAWKX(unit) && !SOC_IS_TOMAHAWK3(unit)) {
   5616                 if (soc_mem_is_cam(unit, mem) &&
   5617                     SOC_TH_MEM_CHK_TCAM_GLOBAL_UNIQUE_MODE(mem)) {
   5618                     int mem_mode = _SOC_SER_MEM_MODE_GLOBAL;
   5619                     int rv = soc_th_check_hw_global_mode(unit, mem,
   5620                                                          &mem_mode);
   5621                     if (SOC_FAILURE(rv)) {
   5622                         /* can skip read for this mem */
   5623                         sal_memset(cache, 0, cache_size);
   5624                         /* valid bits will remain 0 for skipped mems */
   5625                         LOG_ERROR(BSL_LS_SOC_SER,
   5626                             (BSL_META_U(unit,
   5627                                         "soc_mem_cache_set: Will skip "
   5628                                         "WB_cache_fill for mem %s "
   5629                                         "cache=%p size=%d vmap=%p\n"),
   5630                              SOC_MEM_NAME(unit, mem),
   5631                              (void *)cache, cache_size, (void *)vmap));
   5632                         goto iter_done;
   5633                     } else if (_SOC_SER_MEM_MODE_PIPE_UNIQUE == mem_mode) {
   5634                         /* must skip read for this mem */
   5635                         sal_memset(cache, 0, cache_size);
   5636                         /* valid bits will remain 0 for skipped mems */
   5637                         LOG_VERBOSE(BSL_LS_SOC_SER,
   5638                             (BSL_META_U(unit,
   5639                                         "soc_mem_cache_set: Will skip "
   5640                                         "WB_cache_fill for mem %s "
   5641                                         "cache=%p size=%d vmap=%p\n"),
   5642                              SOC_MEM_NAME(unit, mem),
   5643                              (void *)cache, cache_size, (void *)vmap));
   5644                         goto iter_done;
   5645                     }
   5646                     /* proceed to read the mem - normal flow */
   5647                 }
   5648             }
   5649 #endif
   5650             if ((table = soc_cm_salloc(unit, cache_size/numels, "dma")) != NULL) {
   5651                 if (SOC_IS_TRIUMPH3(unit) &&
   5652                     ((mem == PORT_EHG_RX_TUNNEL_MASKm) ||
   5653                      (mem == PORT_EHG_RX_TUNNEL_DATAm) ||
   5654                      (mem == PORT_EHG_TX_TUNNEL_DATAm))) {
   5655                     
   5656                     if (blk == 12 || blk == 13) {
   5657                         index_cnt = 16;
   5658                         index_max = index_cnt - 1;
   5659                     }
   5660                 }
   5661 
   5662 #if defined(BCM_TOMAHAWK_SUPPORT)
   5663                 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   5664                     if (_SOC_MEM_CHK_IFP_TCAM(mem) ||
   5665                          _SOC_MEM_CHK_IFP_TCAM_WIDE(mem)) {
   5666 
   5667                         /* read ifp_tcam using per_slice_dma (which may skip
   5668                          * reading of slices based on width, so first cleanup
   5669                          * 'table' */
   5670                         LOG_VERBOSE(BSL_LS_SOC_SER,
   5671                             (BSL_META_U(unit,
   5672                                         "soc_mem_cache_set: "
   5673                                         "WB_cache_fill for mem %s "
   5674                                         "using soc_th_ifp_tcam_dma_read "
   5675                                         "cache=%p size=%d vmap=%p\n"),
   5676                              SOC_MEM_NAME(unit, mem),
   5677                              (void *)cache, cache_size, (void *)vmap));
   5678                         sal_memset(table, 0, cache_size/numels);
   5679                         /* Set all vmap bits valid first, will clear the invalid in
   5680                            soc_th_ifp_tcam_dma_read */
   5681                         sal_memset(&vmap[index_min / 8], 0xff,
   5682                                    (index_cnt + 7 - index_min) / 8);
   5683                         if (soc_th_ifp_tcam_dma_read(unit, mem, blk, table, 0, vmap) >= 0) {
   5684                             /* When done reading all slices */
   5685                             sal_memcpy(cache, table, cache_size);
   5686 
   5687                             /* Clear invalid bits at the left and right ends */
   5688                             vmap[index_min / 8] &= 0xff00 >> (8 - index_min % 8);
   5689                             vmap[vmap_size - 1] &= 0x00ff >> ((8 - index_cnt % 8) % 8);
   5690 
   5691                         }
   5692                         /* done with read of table, with/without error */
   5693                         soc_cm_sfree(unit, table);
   5694                         goto iter_done;
   5695                     }
   5696                 }
   5697 #endif /* BCM_TOMAHAWK_SUPPORT */
   5698 #if defined(BCM_TRIDENT2_SUPPORT)
   5699                 _SOC_MEM_SKIP_READING_MEM_TO_CACHE(unit, mem, skip);
   5700                 if (skip == 1) {
   5701                     sal_memset(cache, 0, cache_size);
   5702                     memState->vmap[blk] = vmap;
   5703                     memState->cache[blk] = cache;
   5704                     soc_cm_sfree(unit, table);
   5705                     continue;
   5706                 }
   5707 #endif
   5708                 LOG_VERBOSE(BSL_LS_SOC_SER, (BSL_META_U(unit,
   5709                     "cache_rebuild: memory %s \n"),
   5710                     SOC_MEM_NAME(unit, mem)));
   5711 
   5712                 if (numels > 1) {
   5713                     for (elem = first_array_index; elem < numels + first_array_index; elem++) {
   5714                          if (soc_mem_array_read_range(unit, mem, elem, blk, index_min, index_max,
   5715                                                &table[index_min * entry_dw]) >= 0) {
   5716                             uint32 first_read_elem = (elem - first_array_index)* index_cnt;
   5717                             uint32 not_read_elem = first_read_elem + index_cnt;
   5718                             sal_memcpy(cache + (first_read_elem * entry_dw), table, cache_size/numels);
   5719                             /* Set all vmap bits as valid */
   5720                             if (first_read_elem % 8) {
   5721                                 vmap[first_read_elem/8] |= ((uint8)(0xff >> (first_read_elem % 8)));
   5722                             }
   5723                             if (not_read_elem % 8) {
   5724                                 vmap[not_read_elem/8] |= ((uint8)(0xff << (8 - (not_read_elem % 8))));
   5725                             }
   5726                             first_read_elem = (first_read_elem + 7)/8;
   5727                             not_read_elem /= 8;
   5728 
   5729                             if (not_read_elem > first_read_elem) {
   5730                                 sal_memset(vmap + first_read_elem, 0xff, not_read_elem - first_read_elem);
   5731                             }
   5732                         }
   5733                     }
   5734                 } else if (soc_mem_read_range(unit, mem, blk, index_min, index_max,
   5735                                        &table[index_min * entry_dw]) >= 0) {
   5736 
   5737                     sal_memcpy(cache, table, cache_size);
   5738 
   5739                     /* Set all vmap bits as valid */
   5740                     sal_memset(&vmap[index_min / 8], 0xff,
   5741                                (index_cnt + 7 - index_min) / 8);
   5742 
   5743 #ifdef BCM_KATANA2_SUPPORT
   5744                     /* In case of SP memories, out of SP0, SP1, SP2 & SP3
   5745                      * only SP0 is valid i.e. only indices 0,4,8.This check
   5746                      * is avoid processing invalid indices. Issue is handled
   5747                      * for THDI memories alone. Has to be handled
   5748                      * for other SP memories in future */
   5749                     /* For PG memories, please note that for ports supporting 
   5750                      * only one PG, there is only one location on the memory,
   5751                      * eg. Port 6, Pg[0..7] will all point to a same location in the memory */
   5752                     if (SOC_IS_KATANA2(unit)) {
   5753                         if (mem == THDIEMA_THDI_PORT_SP_CONFIGm ||
   5754                                 mem == THDIEXT_THDI_PORT_SP_CONFIGm ||
   5755                                 mem == THDIQEN_THDI_PORT_SP_CONFIGm ||
   5756                                 mem == THDIRQE_THDI_PORT_SP_CONFIGm ||
   5757                                 mem == THDI_PORT_SP_CONFIGm) {
   5758                             sal_memset(&vmap[index_min / 8], 0x11,
   5759                                     (index_cnt + 7 - index_min) / 8);
   5760                         } else if ((mem == THDIEMA_THDI_PORT_PG_CONFIGm ||
   5761                                     mem == THDIEXT_THDI_PORT_PG_CONFIGm ||
   5762                                     mem == THDIQEN_THDI_PORT_PG_CONFIGm ||
   5763                                     mem == THDIRQE_THDI_PORT_PG_CONFIGm ||
   5764                                     mem == THDI_PORT_PG_CONFIGm )) {
   5765                             sal_memset(&vmap[index_min / 8], 0xff,
   5766                                     (index_cnt + 7 - index_min) / 8);
   5767                                     
   5768                             if (!SOC_IS_SABER2(unit)) {
   5769                                 index = index_min / 8;
   5770                                 idx = 0;
   5771                                 for (port = 0  ; port <= 41; port++) {
   5772                                      if (port_index[idx] == port) {
   5773                                          sal_memset(&vmap[index], 0x01,
   5774                                                 1);
   5775                                          idx++;
   5776                                      }
   5777                                      index++;
   5778                                 }
   5779                             }     
   5780                         }
   5781 
   5782                     }
   5783 #endif
   5784 
   5785                     /* Clear invalid bits at the left and right ends */
   5786                     vmap[index_min / 8] &= 0xff00 >> (8 - index_min % 8);
   5787                     vmap[vmap_size - 1] &= 0x00ff >> ((8 - index_cnt % 8) % 8);
   5788                 }
   5789                 if (SOC_IS_TD_TT(unit) && (mem == FP_GLOBAL_MASK_TCAMm) 
   5790                                   && (SOC_SWITCH_BYPASS_MODE(unit) != 
   5791                                          SOC_SWITCH_BYPASS_MODE_L3_AND_FP)) {
   5792                     /* The read of FP_GLOBAL_MASK_TCAM only returns the
   5793                      * X-pipe portions of the pbmp.  We need the Y-pipe
   5794                      * portions also to match what was available
   5795                      * during Cold Boot.  So we explicitly read the
   5796                      * Y-pipe table here and OR the bitmaps together
   5797                      * to form the complete entry that existed in
   5798                      * the Cold Boot cache.
   5799                      */
   5800                     if (soc_mem_read_range(unit, FP_GLOBAL_MASK_TCAM_Ym,
   5801                                            blk, index_min, index_max,
   5802                                        &table[index_min * entry_dw]) >= 0) {
   5803                         soc_pbmp_t pbmp_x, pbmp_y;
   5804                         uint32 *entry_x, *entry_y;
   5805                         for (index = index_min;
   5806                              index <= index_max;
   5807                              index++) {
   5808                             /* FP_GLOBAL_MASK_TCAM[_X|_Y] have the same
   5809                              * field structure, so we can use the field
   5810                              * accessors for just the base memory. */
   5811                             entry_x = cache + index * entry_dw;
   5812                             entry_y = &table[index_min * entry_dw] +
   5813                                 index * entry_dw;
   5814 
   5815                             soc_mem_pbmp_field_get(unit, mem, entry_x,
   5816                                                    IPBM_MASKf, &pbmp_x);
   5817                             SOC_PBMP_AND(pbmp_x, PBMP_XPIPE(unit));
   5818                             soc_mem_pbmp_field_get(unit, mem, entry_y,
   5819                                                    IPBM_MASKf, &pbmp_y);
   5820                             SOC_PBMP_AND(pbmp_y, PBMP_YPIPE(unit));
   5821                             SOC_PBMP_OR(pbmp_x, pbmp_y);
   5822                             soc_mem_pbmp_field_set(unit, mem, entry_x,
   5823                                                    IPBM_MASKf, &pbmp_x);
   5824 
   5825                             soc_mem_pbmp_field_get(unit, mem, entry_x,
   5826                                                    IPBMf, &pbmp_x);
   5827                             SOC_PBMP_AND(pbmp_x, PBMP_XPIPE(unit));
   5828                             soc_mem_pbmp_field_get(unit, mem, entry_y,
   5829                                                    IPBMf, &pbmp_y);
   5830                             SOC_PBMP_AND(pbmp_y, PBMP_YPIPE(unit));
   5831                             SOC_PBMP_OR(pbmp_x, pbmp_y);
   5832                             soc_mem_pbmp_field_set(unit, mem, entry_x,
   5833                                                    IPBMf, &pbmp_x);
   5834                         }
   5835                     }
   5836                 }
   5837                 soc_cm_sfree(unit, table);
   5838                 if (_SOC_MEM_CHK_L2_MEM(mem)) {
   5839                     for (index = index_min; index <= index_max; index++) {
   5840                         sal_memcpy(entry, cache + index*entry_dw, entry_dw * 4);
   5841                         if ((mem == L2_ENTRY_2m &&
   5842                             (soc_mem_field32_get(unit, mem, entry, STATIC_BIT_0f) &&
   5843                              soc_mem_field32_get(unit, mem, entry, STATIC_BIT_1f))) ||
   5844                             ((mem == L2Xm || mem == L2_ENTRY_1m) &&
   5845                              soc_mem_field32_get(unit, mem, entry, STATIC_BITf))) {
   5846                             /* Continue */
   5847                         } else {
   5848                             CACHE_VMAP_CLR(vmap, index);
   5849                         }
   5850                     }
   5851                 } else if (_SOC_MEM_CHK_L3_MEM(mem)) {
   5852                     uint32 *centry;
   5853 
   5854                     for (index = index_min; index <= index_max; index++) {
   5855                         centry = cache + index*entry_dw;
   5856                         sal_memcpy(entry, centry, entry_dw * 4);
   5857                         _soc_mem_l3_entry_cache_entry_validate(unit, mem, entry, vmap, &index);
   5858                         if (SOC_MEM_FIELD_VALID(unit, mem, HITf)) {
   5859                             soc_mem_field32_set(unit, mem, centry, HITf, 0);
   5860                         } else if (SOC_MEM_FIELD_VALID(unit, mem, HIT_1f)) {
   5861                             soc_mem_field32_set(unit, mem, centry, HIT_0f, 0);
   5862                             soc_mem_field32_set(unit, mem, centry, HIT_1f, 0);
   5863                         }
   5864                         if (SOC_MEM_FIELD_VALID(unit, mem, HIT_3f)) {
   5865                             soc_mem_field32_set(unit, mem, centry, HIT_2f, 0);
   5866                             soc_mem_field32_set(unit, mem, centry, HIT_3f, 0);
   5867                         }
   5868                     }
   5869                 }
   5870 #if defined(BCM_TOMAHAWK_SUPPORT)
   5871                 else if (_SOC_MEM_CHK_FPEM_MEM(mem)) {
   5872                     uint32 *centry;
   5873 
   5874                     for (index = index_min; index <= index_max; index++) {
   5875                         centry = cache + index*entry_dw;
   5876                         sal_memcpy(entry, centry, entry_dw * 4);
   5877                         _soc_mem_fpem_entry_cache_entry_validate(unit, mem, entry, vmap, &index);
   5878                         if (SOC_MEM_FIELD_VALID(unit, mem, HIT_0f)) {
   5879                         soc_mem_field32_set(unit, mem, centry, HIT_0f, 0);
   5880                         }
   5881                         if (SOC_MEM_FIELD_VALID(unit, mem, HIT_1f)) {
   5882                             soc_mem_field32_set(unit, mem, centry, HIT_1f, 0);
   5883                         }
   5884                     }
   5885                 }
   5886 #endif /* BCM_TOMAHAWK_SUPPORT */
   5887                 else if (_SOC_MEM_CHK_EGR_IP_TUNNEL(mem)) {
   5888                     uint32 *centry;
   5889                     soc_field_t fld = ENTRY_TYPEf;
   5890 
   5891 #ifdef BCM_TRIDENT3_SUPPORT
   5892                     if (SOC_IS_TRIDENT3X(unit)) {
   5893                         fld = DATA_TYPEf;
   5894                     }
   5895 #endif
   5896 
   5897                     for (index = index_min; index <= index_max; index++) {
   5898                         centry = cache + index*entry_dw;
   5899                         sal_memcpy(entry, centry, entry_dw * 4);
   5900                         if (soc_mem_field32_get(unit, mem, entry, fld) == 0) {
   5901                             CACHE_VMAP_CLR(vmap, index);
   5902                         }
   5903                         if (mem == EGR_IP_TUNNELm) {
   5904                             if (soc_mem_field32_get(unit, mem, entry, fld) != 1) {
   5905                                 CACHE_VMAP_CLR(vmap, index);
   5906                             }
   5907                         } else if (mem == EGR_IP_TUNNEL_MPLSm) {
   5908                             if (soc_mem_field32_get(unit, mem, entry, fld) != 3) {
   5909                                 CACHE_VMAP_CLR(vmap, index);
   5910                             }
   5911                         } else if (mem == EGR_IP_TUNNEL_IPV6m) {
   5912                             if (soc_mem_field32_get(unit, mem, entry, fld) != 2) {
   5913                                 CACHE_VMAP_CLR(vmap, index);
   5914                             }
   5915                         }
   5916                     }
   5917                 }
   5918 #ifdef BCM_TRIUMPH3_SUPPORT               
   5919                 else if (SOC_IS_TRIUMPH3(unit) && _SOC_MEM_CHK_MPLS_MEM(mem)) {
   5920                     uint32 *centry;
   5921                     
   5922                     for (index = index_min; index <= index_max; index++) {
   5923                         centry = cache + index*entry_dw;
   5924                         sal_memcpy(entry, centry, entry_dw * 4);
   5925                         if (mem == MPLS_ENTRYm || mem == MPLS_ENTRY_1m) {
   5926                             if (soc_mem_field32_get(unit, mem, entry, VALIDf) == 0) {
   5927                                 CACHE_VMAP_CLR(vmap, index);
   5928                             } else {
   5929                                 switch (soc_mem_field32_get(unit, mem, entry, KEY_TYPEf)) {
   5930                                     case 0x06: /* 0x06 = L2GRE_SIP - key = {SIP}. */
   5931                                     case 0x07: /* 0x07 = L2GRE_VPNID - key = {GRE.VPNID}. */
   5932                                     case 0x08: /* 0x08 = L2GRE_VPNID_SIP - key = {GRE.VPNID, SIP}.*/
   5933                                     case 0x10: /* 0x10 = MPLS_FIRST_PASS - key = {MPLS_LABEL, GLP}. */
   5934                                     case 0x12: /* 0x12 = MPLS_SECOND_PASS - key = {MPLS_LABEL, GLP}. */
   5935                                         break;
   5936                                     case 0x11: /* 0x11 = MPLS_FIRST_PASS - key = {MPLS_LABEL, GLP}. */
   5937                                     case 0x13: /* 0x13 = MPLS_SECOND_PASS - key = {MPLS_LABEL, GLP}. */
   5938                                     case 0x17: /* 0x17 = MIM_NVP - key = {MAC-in-MAC B-VID, B-SA}. */
   5939                                     case 0x18: /* 0x18 = MIM_ISID - key = {MAC-in-MAC ISID}. */
   5940                                     case 0x19: /* 0x19 = MIM_ISID_SVP - key = {MAC-in-MAC ISID, B-VID, B-SA}. */
   5941                                     case 0x1a: /* 0x1A = TRILL - key = {RBRIDGE_NICKNAME}.  */
   5942                                     default:
   5943                                         CACHE_VMAP_CLR(vmap, index);
   5944                                         break;
   5945                                 }
   5946                             }   
   5947                         }  else if (mem == MPLS_ENTRY_EXTDm) {
   5948                             if ((soc_mem_field32_get(unit, mem, entry, VALID_0f) == 0) ||
   5949                                 (soc_mem_field32_get(unit, mem, entry, VALID_1f) == 0)) {
   5950                                 CACHE_VMAP_CLR(vmap, index);
   5951                             } else if (soc_mem_field32_get(unit, mem, entry, KEY_TYPE_0f) !=
   5952                                           soc_mem_field32_get(unit, mem, entry, KEY_TYPE_1f)) {
   5953                                 CACHE_VMAP_CLR(vmap, index);
   5954                             } else {
   5955                                 switch (soc_mem_field32_get(unit, mem, entry, KEY_TYPE_0f)) {
   5956                                     case 0x06: /* 0x06 = L2GRE_SIP - key = {SIP}. */
   5957                                     case 0x07: /* 0x07 = L2GRE_VPNID - key = {GRE.VPNID}. */
   5958                                     case 0x08: /* 0x08 = L2GRE_VPNID_SIP - key = {GRE.VPNID, SIP}.*/
   5959                                     case 0x10: /* 0x10 = MPLS_FIRST_PASS - key = {MPLS_LABEL, GLP}. */
   5960                                     case 0x12: /* 0x12 = MPLS_SECOND_PASS - key = {MPLS_LABEL, GLP}. */
   5961                                         CACHE_VMAP_CLR(vmap, index);
   5962                                         break;
   5963                                     case 0x11: /* 0x11 = MPLS_FIRST_PASS - key = {MPLS_LABEL, GLP}. */
   5964                                     case 0x13: /* 0x13 = MPLS_SECOND_PASS - key = {MPLS_LABEL, GLP}. */
   5965                                     case 0x17: /* 0x17 = MIM_NVP - key = {MAC-in-MAC B-VID, B-SA}. */
   5966                                     case 0x18: /* 0x18 = MIM_ISID - key = {MAC-in-MAC ISID}. */
   5967                                     case 0x19: /* 0x19 = MIM_ISID_SVP - key = {MAC-in-MAC ISID, B-VID, B-SA}. */
   5968                                     case 0x1a: /* 0x1A = TRILL - key = {RBRIDGE_NICKNAME}.  */
   5969                                         break;
   5970                                     default:
   5971                                         CACHE_VMAP_CLR(vmap, index);
   5972                                         break;
   5973                                 }
   5974                             }
   5975                         }
   5976                     }
   5977                 }
   5978 #endif  /* BCM_TRIUMPH3_SUPPORT */
   5979 #ifdef BCM_TRIDENT3_SUPPORT
   5980                 /* On TD3, we always use MPLS_ENTRY not MPLS_ENTRY_SINGLE */
   5981                 else if (SOC_IS_TRIDENT3X(unit) && mem == MPLS_ENTRY_SINGLEm) {
   5982                     for (index = index_min; index <= index_max; index++) {
   5983                         CACHE_VMAP_CLR(vmap, index);
   5984                     }
   5985                 } else if(SOC_IS_TRIDENT3X(unit) && _SOC_MEM_CHK_VLAN_XLATE(mem)) {
   5986                     uint32 *centry;
   5987 
   5988                     for(index = index_min; index <= index_max; index++) {
   5989                         centry = cache + index*entry_dw;
   5990                         sal_memcpy(entry, centry, entry_dw * 4);
   5991                         if (mem == VLAN_XLATE_1_SINGLEm || 
   5992                             mem == VLAN_XLATE_2_SINGLEm) {
   5993                             switch (soc_mem_field32_get(unit, mem, entry, BASE_VALIDf)) {
   5994                                 case 1:
   5995                                     break;
   5996                                 case 3:
   5997                                 case 7:
   5998                                 default:
   5999                                     CACHE_VMAP_CLR(vmap, index);
   6000                                     break;
   6001                             }
   6002                         } else if (mem == VLAN_XLATE_1_DOUBLEm ||
   6003                                    mem == VLAN_XLATE_2_DOUBLEm) {
   6004                             switch (soc_mem_field32_get(unit, mem, entry, BASE_VALID_0f)) {
   6005                                 case 3:
   6006                                     break;
   6007                                 default:
   6008                                     CACHE_VMAP_CLR(vmap, index);
   6009                                     break;
   6010                             }
   6011                             switch (soc_mem_field32_get(unit, mem, entry, BASE_VALID_1f)) {
   6012                                 case 7:
   6013                                     break;
   6014                                 default:
   6015                                     CACHE_VMAP_CLR(vmap, index);
   6016                                     break;
   6017                             }
   6018                         }
   6019                     }
   6020                 }
   6021 #endif
   6022                  else if (SOC_MEM_SER_CORRECTION_TYPE(unit, mem) &
   6023                            SOC_MEM_FLAG_SER_WRITE_CACHE_RESTORE) {
   6024                     uint32 *centry;
   6025 
   6026                     for (index = index_min; index <= index_max; index++) {
   6027                         centry = cache + index*entry_dw;
   6028                         if (SOC_MEM_FIELD_VALID(unit, mem, HITf)) {
   6029                             soc_mem_field32_set(unit, mem, centry, HITf, 0);
   6030                         } else if (SOC_MEM_FIELD_VALID(unit, mem, HIT0f)) {
   6031                             soc_mem_field32_set(unit, mem, centry, HIT0f, 0);
   6032                         } else if (SOC_MEM_FIELD_VALID(unit, mem, HIT1f)) {
   6033                             soc_mem_field32_set(unit, mem, centry, HIT1f, 0);
   6034                         } else if (SOC_MEM_FIELD_VALID(unit, mem, HIT_0f)) {
   6035                             soc_mem_field32_set(unit, mem, centry, HIT_0f, 0);
   6036                         } else if (SOC_MEM_FIELD_VALID(unit, mem, HIT_1f)) {
   6037                             soc_mem_field32_set(unit, mem, centry, HIT_1f, 0);
   6038                         } else if (SOC_MEM_FIELD_VALID(unit, mem, HIT_2f)) {
   6039                             soc_mem_field32_set(unit, mem, centry, HIT_2f, 0);
   6040                         } else if (SOC_MEM_FIELD_VALID(unit, mem, HIT_3f)) {
   6041                             soc_mem_field32_set(unit, mem, centry, HIT_3f, 0);
   6042                         } else if (SOC_MEM_FIELD_VALID(unit, mem, HIT_BITSf)) {
   6043                             soc_mem_field32_set(unit, mem, centry, HIT_BITSf, 0);
   6044                         }
   6045                     }
   6046                 }
   6047             }
   6048         }
   6049 #endif /* BCM_XGS_SWITCH_SUPPORT */
   6050 
   6051 #ifdef BCM_TOMAHAWK_SUPPORT
   6052 iter_done:
   6053 #endif
   6054         LOG_INFO(BSL_LS_SOC_SOCMEM,
   6055                  (BSL_META_U(unit,
   6056                              "soc_mem_cache_set: cache=%p size=%d vmap=%p\n"),
   6057                   (void *)cache, cache_size, (void *)vmap));
   6058 
   6059         memState->vmap[blk] = vmap;
   6060         memState->cache[blk] = cache;
   6061 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HELIX4_SUPPORT) || \
   6062     defined(BCM_KATANA2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || \
   6063     defined(BCM_GREYHOUND_SUPPORT)
   6064         if((SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) &&
   6065            (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM))) {
   6066             memState->corrupt[blk] = corrupt;
   6067         }
   6068 #endif
   6069         if (org_mem != mem) {
   6070             /* Share the cache and vmap */
   6071             SOC_MEM_STATE(unit, org_mem).cache[blk] = cache;
   6072             SOC_MEM_STATE(unit, org_mem).vmap[blk] = vmap;
   6073         } else if (_SOC_MEM_IS_REUSED_MEM(unit, mem)) {
   6074             /* Sync the cache and vmap */
   6075             _SOC_MEM_SYNC_MAPPED_MEM_STATES(unit, mem);
   6076         }
   6077     }
   6078 
   6079 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   6080 #ifdef BCM_WARM_BOOT_SUPPORT
   6081     if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2X(unit) ||
   6082          SOC_IS_TRIDENT(unit) || SOC_IS_TITAN(unit))&&
   6083         (mem == FP_GLOBAL_MASK_TCAMm || mem == FP_GM_FIELDSm)) {
   6084         int rv;
   6085         if ((rv = soc_mem_overlay_tcam_cache_set
   6086             (unit, mem, copyno, enable)) != SOC_E_NONE) {
   6087              MEM_UNLOCK(unit, mem);
   6088              return rv;
   6089         }
   6090     }
   6091 #endif
   6092 #endif
   6093 
   6094     MEM_UNLOCK(unit, mem);
   6095 
   6096     /*
   6097      * COVERITY
   6098      *
   6099      * This is a false positive alarm.
   6100      * corrupt pointer is assigned to memState->corrupt[blk].
   6101      */
   6102     /* coverity[leaked_storage] */
   6103     return SOC_E_NONE;
   6104 }
   6105 
   6106 /*
   6107  * Function:
   6108  *    soc_mem_cache_invalidate
   6109  * Purpose:
   6110  *    Invalidate a cache entry. Forces read from the device instead
   6111  *      of from cached copy.
   6112  */
   6113 
   6114 int
   6115 soc_mem_cache_invalidate(int unit, soc_mem_t mem, int copyno, int index)
   6116 {
   6117     int blk;
   6118     uint8 *vmap;
   6119 
   6120     assert(SOC_UNIT_VALID(unit));
   6121     _SOC_MEM_REUSE_MEM_STATE(unit, mem);
   6122     SOC_MEM_ALIAS_TO_ORIG(unit,mem);
   6123     assert(SOC_MEM_IS_VALID(unit, mem));
   6124 
   6125     if (!soc_mem_is_cachable(unit, mem)) {
   6126         return SOC_E_UNAVAIL;
   6127     }
   6128 
   6129     if (index < soc_mem_index_min(unit, mem) ||
   6130     index > soc_mem_index_max(unit, mem)) {
   6131         LOG_WARN(BSL_LS_SOC_SOCMEM,
   6132                  (BSL_META_U(unit,
   6133                              "soc_mem_cache_invalidate: invalid index %d "
   6134                              "for memory %s\n"),
   6135                   index, SOC_MEM_NAME(unit, mem)));
   6136         return SOC_E_PARAM;
   6137     }
   6138 
   6139     MEM_LOCK(unit, mem);
   6140 
   6141     SOC_MEM_BLOCK_ITER(unit, mem, blk) {
   6142         if (copyno != SOC_BLOCK_ALL && copyno != blk) {
   6143             continue;
   6144         }
   6145 
   6146         if (SOC_MEM_STATE(unit, mem).cache[blk] == NULL) {
   6147             continue;
   6148         }
   6149 
   6150         /* Invalidate the cached entry */
   6151 
   6152         vmap = SOC_MEM_STATE(unit, mem).vmap[blk];
   6153         CACHE_VMAP_CLR(vmap, index);
   6154     }
   6155 
   6156     MEM_UNLOCK(unit, mem);
   6157 
   6158     return SOC_E_NONE;
   6159 }
   6160 
   6161 /*
   6162  * Function:
   6163  *      _soc_mem_bits_move_one_byte()
   6164  * Purpose:
   6165  *      same as _soc_mem_bits_move, but only for a single byte.
   6166  * Parameters:
   6167  *      dst_ptr          - (IN)  bit stream address.
   6168  *      dst_first        - (IN)  starting bit after the address pointed to by dst_ptr.
   6169  *      src              - (IN)  src byte.
   6170  *      src_first        - (IN)  starting bit in src byte.
   6171  *      nbits            - (IN)  the number of conntiguous bits to be move.
   6172  * Returns:
   6173  *      BCM_E_XXX - Function status.
   6174  * Notes:
   6175  * The following constraints are kept:
   6176  *      a. dst_first < 8
   6177  *      b. src_first < 8
   6178  *      c. dst_first + nbits <= 8
   6179  *      d. src_first + nbits <= 8
   6180  */
   6181 
   6182 static void
   6183 _soc_mem_bits_move_one_byte(uint8 *dst_ptr, int dst_first, uint8 src, int src_first, int nbits)
   6184 {
   6185     uint8 data;
   6186     uint8 mask;
   6187 
   6188     /* no need to check that dst_first == 0 and src_first == 0,
   6189        It must be becuse of the constrains */
   6190     if ((nbits) == 8) {
   6191         *(dst_ptr) = src;
   6192         return;
   6193     }
   6194     /* get the data */
   6195     data = src >> (src_first);
   6196     /* align the data to the place it may be inserted */
   6197     data <<= (dst_first);
   6198 
   6199     mask = ~0;
   6200     mask >>= 8 - nbits;
   6201     mask <<= dst_first;
   6202     data &= mask; /* clear possile bits in src above src_first + range */
   6203     *(dst_ptr) &= ~mask;
   6204     *(dst_ptr) |= data;
   6205 }
   6206 
   6207 /*
   6208  * Function:
   6209  *      soc_mem_bits_move()
   6210  * Purpose:
   6211  *      same as _soc_mem_bits_move, but only for a single byte.
   6212  * Parameters:
   6213  *      dst_ptr          - (IN)  dst bit stream address.
   6214  *      dst_first        - (IN)  starting bit after the address pointed to by dst_ptr.
   6215  *      src_ptr          - (IN)  src bit stream address.
   6216  *      src_first        - (IN)  starting bit after the address pointed to by src_ptr.
   6217  *      nbits            - (IN)  the number of conntiguous bits to be move.
   6218  * Returns:
   6219  *      BCM_E_XXX - Function status.
   6220  * Notes:
   6221  */
   6222 
   6223 static void
   6224 _soc_mem_bits_move(uint8 *dst_ptr, int dst_first, uint8 *src_ptr, int src_first, int nbits)
   6225 {
   6226     if (nbits <= 0) {
   6227         return;
   6228     }
   6229 
   6230     if ((((dst_first) & 0x7) == 0) &&
   6231         (((src_first) & 0x7) == 0) &&
   6232         (((nbits) & 0x7) == 0)) {
   6233             sal_memcpy(&((dst_ptr)[(dst_first) >> 3]),
   6234                 &((src_ptr)[(src_first) >> 3]),
   6235                 ((nbits) >> 3));
   6236     } else {
   6237         uint8 *cur_dst;
   6238         uint8 *cur_src;
   6239         int woff_src, woff_dst, wremain;
   6240 
   6241         cur_dst = (dst_ptr) + ((dst_first) >> 3);
   6242         cur_src = (src_ptr) + ((src_first) >> 3);
   6243 
   6244         woff_src = src_first & 0x7;
   6245         woff_dst = dst_first & 0x7;
   6246 
   6247         if (woff_dst >= woff_src) {
   6248             wremain = 8 - woff_dst;
   6249         } else {
   6250             wremain = 8 - woff_src;
   6251         }
   6252         if (nbits <= wremain) {
   6253             _soc_mem_bits_move_one_byte(cur_dst, woff_dst, *cur_src, woff_src, nbits);
   6254             return;
   6255         }
   6256         _soc_mem_bits_move_one_byte(cur_dst, woff_dst, *cur_src, woff_src, wremain);
   6257         nbits -= wremain;
   6258 
   6259         while (nbits >= 8) {
   6260             if (woff_dst >= woff_src) {
   6261                 ++cur_dst;
   6262                 wremain = woff_dst - woff_src;
   6263                 if(wremain > 0) {
   6264                     _soc_mem_bits_move_one_byte(cur_dst, 0, *cur_src, 8 - wremain, wremain);
   6265                 }
   6266             } else {
   6267                 ++cur_src;
   6268                 wremain = woff_src - woff_dst;
   6269                 _soc_mem_bits_move_one_byte(cur_dst, 8 - wremain, *cur_src, 0, wremain);
   6270             }
   6271             nbits -= wremain;
   6272             wremain = 8 - wremain;
   6273             if (woff_dst >= woff_src) {
   6274                 ++cur_src;
   6275                 _soc_mem_bits_move_one_byte(cur_dst, 8 - wremain, *cur_src, 0, wremain);
   6276             } else {
   6277                 ++cur_dst;
   6278                 _soc_mem_bits_move_one_byte(cur_dst,
   6279                                                 0,
   6280                                                 *cur_src,
   6281                                                 8 - wremain,
   6282                                                 wremain);
   6283             }
   6284             nbits -= wremain;
   6285         }
   6286 
   6287         if (woff_dst >= woff_src) {
   6288             ++cur_dst;
   6289             wremain = woff_dst - woff_src;
   6290             if (nbits <= wremain) {
   6291                 if(nbits > 0) {
   6292                     _soc_mem_bits_move_one_byte(cur_dst, 0, *cur_src, 8 - wremain,  nbits);
   6293                 }
   6294                 return;
   6295             }
   6296             if(wremain > 0) {
   6297                 _soc_mem_bits_move_one_byte(cur_dst, 0, *cur_src, 8 - wremain, wremain);
   6298             }
   6299         } else {
   6300             ++cur_src;
   6301             wremain = woff_src - woff_dst;
   6302             if (nbits <= wremain) {
   6303                 if(nbits > 0) {
   6304                     _soc_mem_bits_move_one_byte(cur_dst, 8 - wremain, *cur_src, 0, nbits);
   6305                 }
   6306                 return;
   6307             }
   6308             _soc_mem_bits_move_one_byte(cur_dst,
   6309                                             8 - wremain,
   6310                                             *cur_src,
   6311                                             0,
   6312                                             wremain);
   6313         }
   6314         nbits -= wremain;
   6315 
   6316         if(nbits > 0) {
   6317             wremain = 8 - wremain;
   6318             if (woff_dst >= woff_src) {
   6319                 ++cur_src;
   6320                 _soc_mem_bits_move_one_byte(cur_dst, 8 - wremain, *cur_src, 0, nbits);
   6321             } else {
   6322                 ++cur_dst;
   6323                 _soc_mem_bits_move_one_byte(cur_dst, 0, *cur_src, 8 - wremain, nbits);
   6324             }
   6325         }
   6326     }
   6327 }
   6328 
   6329 
   6330 /*
   6331  *    Move Cached old entries (block) to new location and invalidate the old entries.
   6332  *    Imitate HW Support to move block of entries.
   6333  */
   6334 int soc_mem_cache_block_move(int        unit,               /* unit of the memory */
   6335                              uint32     flags,              /* flags */
   6336                              soc_mem_t  mem,                /* Memory to be written to */
   6337                              unsigned   src_arr_index,      /* min array index to be written to, not used in memories which are not arrays */
   6338                              unsigned   dest_arr_index,     /* max array index to be written to, not used in memories which are not arrays */
   6339                              int        copyno,             /* Memory block to write to */
   6340                              int        src_index_start,    /* start memory index to read from and to invalidate */
   6341                              int        dest_index_start,    /* start memory index to write */
   6342                              int        entries_count)      /* number of entries to move (Range) */
   6343 {
   6344     int     blk, index;
   6345     int     entry_dw        = soc_mem_entry_words(unit, mem);
   6346     int     block_size_byte = WORDS2BYTES(entries_count * entry_dw);
   6347     int     src_index_end   = src_index_start + entries_count - 1;
   6348     int     dest_index_end  = dest_index_start + entries_count - 1;
   6349     int     src_mem_array_vmap_offset, src_mem_array_cache_offset;
   6350     int     dest_mem_array_vmap_offset, dest_mem_array_cache_offset;
   6351     int     invalidate_index_start, invalidate_index_end;
   6352     uint32  *cache;
   6353     uint8   *vmap;
   6354     uint8   *tmp_cache_block;
   6355     uint8   *tmp_vmap;
   6356 
   6357 
   6358     LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   6359             (BSL_META_U(unit,
   6360                     "%s: unit %d, memory %s, block %s, copyno %d, src_index_start %d, \ndest_index_start %d, entries_count %d, entry_dw=%d, \nind_min=%d, ind_max=%d\n  src_arr_index=%d, dest_arr_index=%d\n"),
   6361                     FUNCTION_NAME(), unit, SOC_MEM_UFNAME(unit, mem), SOC_BLOCK_NAME(unit, copyno),
   6362                     copyno, src_index_start, dest_index_start, entries_count, entry_dw, soc_mem_index_min(unit, mem), soc_mem_index_max(unit, mem), src_arr_index, dest_arr_index));
   6363 
   6364     if (!soc_mem_is_valid(unit, mem))
   6365     {
   6366         return SOC_E_MEMORY;
   6367     }
   6368 
   6369     if (!soc_mem_is_cachable(unit, mem))
   6370     {
   6371         /* If cache is not available just return */
   6372         return SOC_E_NONE;
   6373     }
   6374 
   6375     if ((entries_count < 0) || (entries_count > soc_mem_index_count(unit, mem)))
   6376     {
   6377         LOG_ERROR(BSL_LS_SOC_SOCMEM,
   6378                 (BSL_META_U(unit,
   6379                         "%s: invalid entries_count=%d for memory %s\n"), FUNCTION_NAME(), entries_count, SOC_MEM_NAME( unit, mem)));
   6380         return SOC_E_PARAM;
   6381     }
   6382 
   6383     if (((src_index_start < soc_mem_index_min(unit, mem))
   6384             || (src_index_end > soc_mem_index_max(unit, mem)))
   6385             || ((dest_index_start < soc_mem_index_min(unit, mem))
   6386             || (dest_index_end > soc_mem_index_max(unit, mem))))
   6387     {
   6388         LOG_ERROR(BSL_LS_SOC_SOCMEM,
   6389                 (BSL_META_U(unit, "%s: invalid index for memory %s\n"), FUNCTION_NAME(), SOC_MEM_NAME(unit, mem)));
   6390         return SOC_E_PARAM;
   6391     }
   6392 
   6393     if ((tmp_cache_block = sal_alloc(block_size_byte, "tmp_cache_block")) == NULL)
   6394     {
   6395         return SOC_E_MEMORY;
   6396     }
   6397 
   6398     src_mem_array_vmap_offset = src_arr_index * soc_mem_index_count(unit, mem);
   6399     src_mem_array_cache_offset = src_mem_array_vmap_offset * entry_dw;
   6400     dest_mem_array_vmap_offset = dest_arr_index * soc_mem_index_count(unit, mem);
   6401     dest_mem_array_cache_offset = dest_mem_array_vmap_offset * entry_dw;
   6402 
   6403     if ((tmp_vmap = sal_alloc(((src_mem_array_vmap_offset + src_index_start + entries_count + 7) / 8), "tmp_vmap")) == NULL)
   6404     {
   6405         sal_free(tmp_cache_block);
   6406         return SOC_E_MEMORY;
   6407     }
   6408 
   6409     /* Calculate the index range for invalidation */
   6410     if ((src_index_start > dest_index_start) && (src_index_start <= dest_index_end) && (src_arr_index == dest_arr_index))
   6411     {
   6412         /* overlapping move up */
   6413         invalidate_index_start  = dest_index_end + 1;
   6414         invalidate_index_end    = src_index_end;
   6415     }
   6416     else if((dest_index_start > src_index_start) && (dest_index_start <= src_index_end) && (src_arr_index == dest_arr_index))
   6417     {
   6418         /* overlapping move down */
   6419         invalidate_index_start  = src_index_start;
   6420         invalidate_index_end    = dest_index_start - 1;
   6421     }
   6422     else
   6423     {
   6424         /* not-overlapping move */
   6425         invalidate_index_start  = src_index_start;
   6426         invalidate_index_end    = src_index_end;
   6427     }
   6428 
   6429     /* Copy cache entries + invalidate old entries */
   6430     MEM_LOCK(unit, mem);
   6431 
   6432     SOC_MEM_BLOCK_ITER(unit, mem, blk)
   6433     {
   6434         if (copyno != SOC_BLOCK_ALL && copyno != blk)
   6435         {
   6436             continue;
   6437         }
   6438 
   6439         cache = SOC_MEM_STATE(unit, mem).cache[blk];
   6440         vmap = SOC_MEM_STATE(unit, mem).vmap[blk];
   6441 
   6442         if (cache == NULL)
   6443         {
   6444             continue;
   6445         }
   6446 
   6447         /* Copy cache entries from old location to new location. We are doing it in 2 copies since the blocks can overlap. */
   6448         sal_memcpy(tmp_cache_block, cache + src_mem_array_cache_offset+ (src_index_start * entry_dw), block_size_byte);
   6449         sal_memcpy(cache + dest_mem_array_cache_offset + (dest_index_start * entry_dw), tmp_cache_block, block_size_byte);
   6450 
   6451         /* Copy vmap from old location to new location. We are doing it in 2 copies since the blocks can overlap. */
   6452         sal_memcpy(tmp_vmap, vmap, ((src_mem_array_vmap_offset + src_index_start + entries_count + 7) / 8));
   6453         _soc_mem_bits_move(vmap, dest_mem_array_vmap_offset + dest_index_start, tmp_vmap, src_mem_array_vmap_offset + src_index_start, entries_count);
   6454 
   6455         /* Invalidate the cached entry */
   6456         for (index = invalidate_index_start; index <= invalidate_index_end; index++)
   6457         {
   6458             CACHE_VMAP_CLR(vmap, src_mem_array_vmap_offset + index);
   6459         }
   6460     }
   6461 
   6462     MEM_UNLOCK(unit, mem);
   6463 
   6464     sal_free(tmp_cache_block);
   6465     sal_free(tmp_vmap);
   6466 
   6467     return SOC_E_NONE;
   6468 
   6469 }
   6470 
   6471 
   6472 #ifdef BCM_WARM_BOOT_SUPPORT
   6473 
   6474 /*
   6475  *     Mem cache structure:
   6476  * +++++++++++++++++++++++++++
   6477  * |  Mem 0: Name string     | -> 128 characters
   6478  * +++++++++++++++++++++++++++
   6479  * |                         |
   6480  * |        Mem table        |
   6481  * |                         |
   6482  * |                         |
   6483  * +++++++++++++++++++++++++++
   6484  * |      Valid bitmap       |
   6485  * +++++++++++++++++++++++++++
   6486  *            ....
   6487  *            ....
   6488  *            ....
   6489  *            ....
   6490  * +++++++++++++++++++++++++++
   6491  * |  Mem n: Name string     |
   6492  * +++++++++++++++++++++++++++
   6493  * |                         |
   6494  * |        Mem table        |
   6495  * |                         |
   6496  * |                         |
   6497  * +++++++++++++++++++++++++++
   6498  * |      Valid bitmap       |
   6499  * +++++++++++++++++++++++++++
   6500  * |                         |
   6501  * |       Reg cache         |
   6502  * |                         |
   6503  * +++++++++++++++++++++++++++
   6504  */
   6505 
   6506 int
   6507 soc_mem_scache_size_get(int unit)
   6508 {
   6509     int size = 0;
   6510 #if defined(BCM_XGS_SUPPORT)
   6511     int count;
   6512     soc_ser_reg_cache_info(unit, &count, &size);
   6513 #endif
   6514     return size + SOC_STAT(unit)->mem_cache_size +
   6515            SOC_STAT(unit)->mem_cache_count*128;
   6516 }
   6517 
   6518 int
   6519 soc_mem_cache_scache_init(int unit)
   6520 {
   6521     uint32 alloc_get;
   6522     soc_scache_handle_t scache_handle;
   6523     uint8 *mem_scache_ptr;
   6524     int rv, stable_size, alloc_sz = soc_mem_scache_size_get(unit);
   6525 
   6526     /* This code is not executed for now, but will enable it in future
   6527        if required */
   6528     if (0 /*NULL == SOC_CONTROL(unit)->mem_scache_ptr*/) {
   6529         SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   6530         if ((stable_size > SOC_DEFAULT_LVL2_STABLE_SIZE) &&
   6531             !SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
   6532             SOC_SCACHE_HANDLE_SET(scache_handle, unit,
   6533                                   SOC_SCACHE_MEMCACHE_HANDLE, 0);
   6534             /* Get the pointer for the Level 2 cache */
   6535             rv = soc_scache_ptr_get(unit, scache_handle,
   6536                                     &mem_scache_ptr, &alloc_get);
   6537             if (!SOC_WARM_BOOT(unit) && (SOC_E_NOT_FOUND == rv)) {
   6538                 /* Not yet allocated in Cold Boot */
   6539                 SOC_IF_ERROR_RETURN
   6540                     (soc_scache_alloc(unit, scache_handle,
   6541                                       alloc_sz + SOC_WB_SCACHE_CONTROL_SIZE));
   6542                 rv = soc_scache_ptr_get(unit, scache_handle,
   6543                                         &mem_scache_ptr, &alloc_get);
   6544                 if (SOC_FAILURE(rv)) {
   6545                     return rv;
   6546                 } else if (alloc_get != alloc_sz +
   6547                                         SOC_WB_SCACHE_CONTROL_SIZE) {
   6548                     /* Expected size doesn't match retrieved size */
   6549                     return SOC_E_INTERNAL;
   6550                 } else if (NULL == mem_scache_ptr) {
   6551                     return SOC_E_MEMORY;
   6552                 }
   6553                 SOC_CONTROL(unit)->mem_scache_ptr = mem_scache_ptr;
   6554             }
   6555         }
   6556     }
   6557     return SOC_E_NONE;
   6558 }
   6559 
   6560 int
   6561 soc_mem_cache_scache_sync(int unit)
   6562 {
   6563     uint32 *cache;
   6564     int blk, entry_dw, index_cnt;
   6565     int cache_size, vmap_size, offset= 0;
   6566     soc_mem_t mem, tmp_mem;
   6567     uint8 *vmap, *mem_scache_ptr = SOC_CONTROL(unit)->mem_scache_ptr;
   6568 
   6569     if (NULL == mem_scache_ptr) {
   6570         return SOC_E_UNAVAIL;
   6571     }
   6572     for (mem = 0; mem < NUM_SOC_MEM; mem++) {
   6573         if (!SOC_MEM_IS_VALID(unit, mem)) {
   6574             continue;
   6575         }
   6576         if (soc_mem_index_count(unit, mem) == 0) {
   6577             continue;
   6578         }
   6579         tmp_mem = mem;
   6580         _SOC_MEM_REUSE_MEM_STATE(unit, tmp_mem);
   6581         if (tmp_mem != mem) {
   6582             continue;
   6583         }
   6584         entry_dw = soc_mem_entry_words(unit, mem);
   6585         index_cnt = soc_mem_index_count(unit, mem);
   6586         cache_size = index_cnt * entry_dw * 4;
   6587         vmap_size = (index_cnt + 7) / 8;
   6588 
   6589         MEM_LOCK(unit, mem);
   6590         SOC_MEM_BLOCK_ITER(unit, mem, blk) {
   6591             if (SOC_MEM_STATE(unit, mem).cache[blk] == NULL) {
   6592                 continue;
   6593             }
   6594             cache = SOC_MEM_STATE(unit, mem).cache[blk];
   6595             vmap = SOC_MEM_STATE(unit, mem).vmap[blk];
   6596 
   6597             sal_memcpy(mem_scache_ptr+offset, SOC_MEM_UFNAME(unit, mem),
   6598                        strlen(SOC_MEM_UFNAME(unit, mem)));
   6599             LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   6600                         (BSL_META_U(unit,
   6601                                     "Store at %d %s\n"), offset, SOC_MEM_UFNAME(unit, mem)));
   6602             offset += 128;
   6603             sal_memcpy(mem_scache_ptr+offset, cache, cache_size);
   6604             offset += cache_size;
   6605             sal_memcpy(mem_scache_ptr+offset, vmap, vmap_size);
   6606             offset += vmap_size;
   6607         }
   6608         MEM_UNLOCK(unit, mem);
   6609     }
   6610     return SOC_E_NONE;
   6611 }
   6612 
   6613 int
   6614 soc_mem_cache_scache_get(int unit)
   6615 {
   6616     uint32 alloc_get;
   6617     soc_scache_handle_t scache_handle;
   6618     uint8 *mem_scache_ptr;
   6619     int stable_size;
   6620 
   6621     /* This code is not executed for now, but will enable it in future
   6622        if required */
   6623     if (0 /*NULL == SOC_CONTROL(unit)->mem_scache_ptr*/) {
   6624         SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   6625         if ((stable_size > SOC_DEFAULT_LVL2_STABLE_SIZE) &&
   6626             !SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
   6627             SOC_SCACHE_HANDLE_SET(scache_handle, unit,
   6628                                   SOC_SCACHE_MEMCACHE_HANDLE, 0);
   6629             /* Get the pointer for the Level 2 cache */
   6630             SOC_IF_ERROR_RETURN
   6631                 (soc_scache_ptr_get(unit, scache_handle,
   6632                                     &mem_scache_ptr, &alloc_get));
   6633             if (alloc_get == 0) {
   6634                 return SOC_E_INTERNAL;
   6635             } else if (NULL == mem_scache_ptr) {
   6636                 return SOC_E_MEMORY;
   6637             }
   6638             SOC_CONTROL(unit)->mem_scache_ptr = mem_scache_ptr;
   6639         }
   6640     }
   6641     return SOC_E_NONE;
   6642 }
   6643 
   6644 int
   6645 soc_mem_cache_scache_load(int unit, soc_mem_t mem, int *offset)
   6646 {
   6647     int blk, entry_dw, index_cnt;
   6648     int cache_size, vmap_size;
   6649     uint32 *cache;
   6650     uint8 *vmap, *mem_scache_ptr = SOC_CONTROL(unit)->mem_scache_ptr;
   6651 
   6652     if (SOC_WARM_BOOT(unit) && SOC_CONTROL(unit)->mem_scache_ptr) {
   6653         entry_dw = soc_mem_entry_words(unit, mem);
   6654         index_cnt = soc_mem_index_count(unit, mem);
   6655         cache_size = index_cnt * entry_dw * 4;
   6656         vmap_size = (index_cnt + 7) / 8;
   6657 
   6658         SOC_MEM_BLOCK_ITER(unit, mem, blk) {
   6659             if (SOC_MEM_STATE(unit, mem).cache[blk] == NULL) {
   6660                 continue;
   6661             }
   6662             cache = SOC_MEM_STATE(unit, mem).cache[blk];
   6663             vmap = SOC_MEM_STATE(unit, mem).vmap[blk];
   6664             
   6665             LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   6666                         (BSL_META_U(unit,
   6667                                     "Load from %d %s to %s\n"), *offset,
   6668                          mem_scache_ptr + *offset, SOC_MEM_UFNAME(unit, mem)));
   6669             *offset += 128;
   6670             sal_memcpy(cache, mem_scache_ptr + *offset, cache_size);
   6671             *offset += cache_size;
   6672             sal_memcpy(vmap, mem_scache_ptr + *offset, vmap_size);
   6673             *offset += vmap_size;
   6674         }
   6675     }
   6676     return SOC_E_NONE;
   6677 }
   6678 
   6679 int
   6680 soc_control_defip_scache_init(int unit)
   6681 {
   6682     soc_scache_handle_t scache_handle;
   6683     uint8 *l3_defip_scache_ptr;
   6684     int rv;
   6685     int stable_size;
   6686     uint16 version = SOC_DEFIP_WARMBOOT_DEFAULT_VERSION;
   6687     int alloc_sz = sizeof(SOC_L3_DEFIP_MAX_128B_ENTRIES(unit)) +
   6688                    sizeof(version);
   6689     int create = SOC_WARM_BOOT(unit) ? FALSE : TRUE;
   6690 
   6691     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   6692     if (!stable_size) {
   6693         /* If stable not allocated, just return */
   6694         return SOC_E_NONE;
   6695     }
   6696     SOC_SCACHE_ALIGN_SIZE(alloc_sz);
   6697 
   6698     alloc_sz += SOC_WB_SCACHE_CONTROL_SIZE;
   6699 
   6700     if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
   6701         SOC_SCACHE_HANDLE_SET(scache_handle, unit,
   6702                               SOC_SCACHE_SOC_DEFIP_HANDLE, 0);
   6703         /* Get the pointer for the Level 2 cache */
   6704         rv = soc_extended_scache_ptr_get(unit, scache_handle, create,
   6705                                          create ? alloc_sz : 0,
   6706                                          &l3_defip_scache_ptr);
   6707         if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) {
   6708             return rv;
   6709         } else if (SOC_E_NOT_FOUND == rv && !create) {
   6710             /* Not yet allocated in upgrade */
   6711             rv = soc_extended_scache_ptr_get(unit, scache_handle, TRUE,
   6712                                              alloc_sz,
   6713                                              &l3_defip_scache_ptr);
   6714             if (SOC_FAILURE(rv) && (rv != SOC_E_NOT_FOUND)) {
   6715                 return rv;
   6716             }
   6717             if (SOC_SUCCESS(rv)) {
   6718                 SOC_L3_DEFIP_SCACHE_HANDLE(unit) = l3_defip_scache_ptr;
   6719             }
   6720         } else if (SOC_FAILURE(rv)) {
   6721             return rv;
   6722         } else {
   6723             SOC_L3_DEFIP_SCACHE_HANDLE(unit) = l3_defip_scache_ptr;
   6724         }
   6725     }
   6726 
   6727     return SOC_E_NONE;
   6728 }
   6729 
   6730 
   6731 int
   6732 soc_control_defip_scache_sync(int unit)
   6733 {
   6734     uint8 *l3_defip_scache_ptr = SOC_L3_DEFIP_SCACHE_HANDLE(unit);
   6735     int scache_size = sizeof(SOC_L3_DEFIP_MAX_128B_ENTRIES(unit));
   6736     int stable_size = 0;
   6737     uint16 version = SOC_DEFIP_WARMBOOT_DEFAULT_VERSION;
   6738 
   6739     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   6740     if (!stable_size) {
   6741         /* If stable not allocated, just return */
   6742         return SOC_E_NONE;
   6743     }
   6744     if (NULL == l3_defip_scache_ptr) {
   6745         return SOC_E_UNAVAIL;
   6746     }
   6747 
   6748     /* First save version */
   6749     sal_memcpy(l3_defip_scache_ptr, &version, sizeof(version));
   6750     sal_memcpy(l3_defip_scache_ptr + sizeof(version),
   6751                &SOC_L3_DEFIP_MAX_128B_ENTRIES(unit),
   6752                scache_size);
   6753     return SOC_E_NONE;
   6754 }
   6755 
   6756 int
   6757 soc_control_defip_scache_load(int unit, int *num_ipv6_128b_entries)
   6758 {
   6759     uint8 *l3_defip_scache_ptr = NULL;
   6760     int scache_size = sizeof(SOC_L3_DEFIP_MAX_128B_ENTRIES(unit));
   6761     int stable_size = 0;
   6762     uint16 version = 0;
   6763 
   6764     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   6765     if (!stable_size) {
   6766         /* If stable not allocated, just return */
   6767         return SOC_E_RESOURCE;
   6768     }
   6769 
   6770     l3_defip_scache_ptr = SOC_L3_DEFIP_SCACHE_HANDLE(unit);
   6771     if (l3_defip_scache_ptr == NULL) {
   6772         return SOC_E_RESOURCE;
   6773     }
   6774     if (SOC_WARM_BOOT(unit)) {
   6775         sal_memcpy(&version, l3_defip_scache_ptr, sizeof(version));
   6776         if (version >= SOC_DEFIP_WARMBOOT_VERSION_1) {
   6777             sal_memcpy(num_ipv6_128b_entries,
   6778                        l3_defip_scache_ptr + sizeof(version),
   6779                        scache_size);
   6780         } else {
   6781             return SOC_E_UNAVAIL;
   6782         }
   6783     }
   6784     return SOC_E_NONE;
   6785 }
   6786 #endif /* BCM_WARM_BOOT_SUPPORT */
   6787 
   6788 /************************************************************************/
   6789 /* Routines for CFAPINIT                                 */
   6790 /************************************************************************/
   6791 
   6792 #ifdef BCM_ESW_SUPPORT
   6793 /*
   6794  * Function:
   6795  *    cfapinit_write_cb (internal)
   6796  * Purpose:
   6797  *    Memory test callback routine for cfapinit
   6798  */
   6799 
   6800 static int
   6801 cfapinit_write_cb(struct soc_mem_test_s *parm,
   6802                   unsigned array_index,
   6803                   int copyno,
   6804                   int index,
   6805                   uint32 *entry_data)
   6806 {
   6807     return soc_mem_array_write(parm->unit, parm->mem, array_index, copyno,
   6808                                index, entry_data);
   6809 }
   6810 
   6811 /*
   6812  * Function:
   6813  *    cfapinit_read_cb (internal)
   6814  * Purpose:
   6815  *    Memory test callback routine for cfapinit
   6816  */
   6817 
   6818 static int
   6819 cfapinit_read_cb(struct soc_mem_test_s *parm,
   6820                  unsigned array_index,
   6821                  int copyno,
   6822                  int index,
   6823                  uint32 *entry_data)
   6824 {
   6825     return soc_mem_array_read(parm->unit, parm->mem, array_index, copyno, index,
   6826                               entry_data);
   6827 }
   6828 
   6829 /*
   6830  * Function:
   6831  *    cfapinit_miscompare_cb (internal)
   6832  * Purpose:
   6833  *    Memory test callback routine for cfapinit
   6834  */
   6835 
   6836 static int
   6837 cfapinit_miscompare_cb(struct soc_mem_test_s *parm,
   6838                        unsigned array_index,
   6839                        int copyno,
   6840                        int index,
   6841                        uint32 *read_data,
   6842                        uint32 *wrote_data,
   6843                        uint32 *mask_data)
   6844 {
   6845     uint8    *bad_list = parm->userdata;
   6846 
   6847     COMPILER_REFERENCE(array_index);
   6848     COMPILER_REFERENCE(copyno);
   6849     COMPILER_REFERENCE(read_data);
   6850     COMPILER_REFERENCE(wrote_data);
   6851     COMPILER_REFERENCE(mask_data);
   6852 
   6853     bad_list[index - parm->index_start] = 1;
   6854 
   6855     return 1;
   6856 }
   6857 
   6858 #endif /* BCM_ESW_SUPPORT */
   6859 /*
   6860  * Function:
   6861  *    soc_mem_cfap_init
   6862  * Purpose:
   6863  *    Routine to diagnose and initialize CFAP pool.
   6864  * Notes:
   6865  *    Ordinarily this routine is not used.  When the chip is reset, it
   6866  *    automatically writes the CFAP table with the correct pointer
   6867  *    data.
   6868  *
   6869  *    This routine does the same thing, except it also runs a memory
   6870  *    test and excludes bad entries in CBPHEADER/CBPDATA[0-3] from the
   6871  *    CFAP pool.
   6872  *
   6873  *    On some devices, errors in the first 63 entries can't be eliminated.
   6874  *    The routine fails if such errors are found.
   6875  */
   6876 
   6877 #ifdef BCM_ESW_SUPPORT
   6878 int
   6879 soc_mem_cfap_init(int unit)
   6880 {
   6881     soc_mem_test_t    mt;
   6882     uint8        *bad_list;
   6883     int            entry_count, bad_count, bad_count_63;
   6884     int            i, ptr, rv;
   6885     uint32        cfappoolsize;
   6886     soc_mem_t           cbpcellheader_m;
   6887     soc_mem_t           cbppktheader_start_m;
   6888     soc_mem_t           cbppktheader_end_m;
   6889     soc_mem_t           cbpdata_start_m;
   6890     soc_mem_t           cbpdata_end_m;
   6891     soc_mem_t           cfap_m;
   6892 
   6893     if (!SOC_IS_XGS_SWITCH(unit)) {
   6894         return SOC_E_NONE;
   6895     }
   6896 
   6897     if (!soc_feature(unit, soc_feature_cfap_pool)) {
   6898         return SOC_E_UNAVAIL;
   6899     }
   6900 
   6901     cbpcellheader_m      = MMU_CBPCELLHEADERm;
   6902     cbppktheader_start_m = MMU_CBPPKTHEADER0m;
   6903     cbppktheader_end_m   = MMU_CBPPKTHEADER1m;
   6904     cbpdata_start_m      = MMU_CBPDATA0m;
   6905     cbpdata_end_m        = MMU_CBPDATA15m;
   6906     cfap_m               = MMU_CFAPm;
   6907     SOC_IF_ERROR_RETURN(READ_CFAPCONFIGr(unit, &cfappoolsize));
   6908     cfappoolsize = soc_reg_field_get(unit, CFAPCONFIGr,
   6909                                      cfappoolsize, CFAPPOOLSIZEf);
   6910 
   6911     mt.unit          = unit;
   6912     mt.patterns      = soc_property_get(unit, spn_CFAP_TESTS,
   6913                                         MT_PAT_CHECKER | MT_PAT_ICHECKER);
   6914     mt.copyno        = COPYNO_ALL;
   6915     mt.index_start   = soc_mem_index_min(unit, cbpcellheader_m);
   6916     mt.index_end     = soc_mem_index_max(unit, cbpcellheader_m);
   6917     mt.index_step    = 1;
   6918     mt.read_count    = 1;
   6919     mt.status_cb     = 0;            /* No status */
   6920     mt.write_cb      = cfapinit_write_cb;
   6921     mt.read_cb       = cfapinit_read_cb;
   6922     mt.miscompare_cb = cfapinit_miscompare_cb;
   6923 
   6924     /*
   6925      * Create array of status per entry, initially with all entries
   6926      * marked good.  The test callback will mark bad entries.
   6927      */
   6928 
   6929     entry_count = mt.index_end - mt.index_start + 1;
   6930 
   6931     if ((bad_list = sal_alloc(entry_count, "bad_list")) == NULL) {
   6932         return SOC_E_MEMORY;
   6933     }
   6934 
   6935     sal_memset(bad_list, 0, entry_count);
   6936 
   6937     /*
   6938      * Test the five "parallel" memories: CBPHEADER and CBPDATA[0-3].
   6939      */
   6940 
   6941     mt.userdata = bad_list;
   6942     mt.mem = cbpcellheader_m;
   6943     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   6944                 (BSL_META_U(unit,
   6945                             "soc_mem_cfap_init: unit %d: testing CBPHEADER\n"),
   6946                  unit));
   6947 
   6948     if ((rv = soc_mem_parity_control(unit, mt.mem,
   6949                                      mt.copyno, FALSE)) < 0) {
   6950         LOG_ERROR(BSL_LS_SOC_SOCMEM,
   6951                   (BSL_META_U(unit,
   6952                               "Unable to disable parity warnings on %s\n"),
   6953                    SOC_MEM_UFNAME(unit, mt.mem)));
   6954         goto done;
   6955     }
   6956 
   6957     (void) soc_mem_test(&mt);
   6958 
   6959     if ((rv = soc_mem_parity_control(unit, mt.mem,
   6960                                      mt.copyno, TRUE)) < 0) {
   6961         LOG_ERROR(BSL_LS_SOC_SOCMEM,
   6962                   (BSL_META_U(unit,
   6963                               "Unable to disable parity warnings on %s\n"),
   6964                    SOC_MEM_UFNAME(unit, mt.mem)));
   6965         goto done;
   6966     }
   6967 
   6968     for (mt.mem = cbppktheader_start_m;
   6969          mt.mem <= cbppktheader_end_m;
   6970          mt.mem++) {
   6971         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   6972                     (BSL_META_U(unit,
   6973                                 "soc_mem_cfap_init: unit %d: testing CBPPKTHEADER%d\n"),
   6974                      unit, mt.mem - cbppktheader_start_m));
   6975 
   6976         if ((rv = soc_mem_parity_control(unit, mt.mem,
   6977                                          mt.copyno, FALSE)) < 0) {
   6978             LOG_ERROR(BSL_LS_SOC_SOCMEM,
   6979                       (BSL_META_U(unit,
   6980                                   "Unable to disable parity warnings on %s\n"),
   6981                        SOC_MEM_UFNAME(unit, mt.mem)));
   6982             goto done;
   6983         }
   6984         (void) soc_mem_test(&mt);
   6985 
   6986         if ((rv = soc_mem_parity_control(unit, mt.mem,
   6987                                          mt.copyno, TRUE)) < 0) {
   6988             LOG_ERROR(BSL_LS_SOC_SOCMEM,
   6989                       (BSL_META_U(unit,
   6990                                   "Unable to disable parity warnings on %s\n"),
   6991                        SOC_MEM_UFNAME(unit, mt.mem)));
   6992             goto done;
   6993         }
   6994     }
   6995 
   6996     for (mt.mem = cbpdata_start_m;
   6997          mt.mem <= cbpdata_end_m;
   6998          mt.mem++) {
   6999         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   7000                     (BSL_META_U(unit,
   7001                                 "soc_mem_cfap_init: unit %d: testing CBPDATA%d\n"),
   7002                      unit, mt.mem - cbpdata_start_m));
   7003 
   7004         if ((rv = soc_mem_parity_control(unit, mt.mem,
   7005                                          mt.copyno, FALSE)) < 0) {
   7006             LOG_ERROR(BSL_LS_SOC_SOCMEM,
   7007                       (BSL_META_U(unit,
   7008                                   "Unable to disable parity warnings on %s\n"),
   7009                        SOC_MEM_UFNAME(unit, mt.mem)));
   7010             goto done;
   7011         }
   7012         (void) soc_mem_test(&mt);
   7013 
   7014         if ((rv = soc_mem_parity_control(unit, mt.mem,
   7015                                          mt.copyno, TRUE)) < 0) {
   7016             LOG_ERROR(BSL_LS_SOC_SOCMEM,
   7017                       (BSL_META_U(unit,
   7018                                   "Unable to disable parity warnings on %s\n"),
   7019                        SOC_MEM_UFNAME(unit, mt.mem)));
   7020             goto done;
   7021         }
   7022     }
   7023 
   7024     /*
   7025      * Test only
   7026      for (i = 1; i < 512; i += 2) {
   7027          if (i < entry_count) {
   7028              bad_list[i] = 1;
   7029          }
   7030      }
   7031      */
   7032 
   7033     bad_count = 0;
   7034     bad_count_63 = 0;
   7035 
   7036     for (i = mt.index_start; i <= mt.index_end; i++) {
   7037         if (bad_list[i - mt.index_start]) {
   7038             bad_count++;
   7039             if (i < mt.index_start + 63) {
   7040                 bad_count_63++;
   7041             }
   7042         }
   7043     }
   7044 
   7045     if (bad_count_63 > 0) {
   7046         /*
   7047          * On some devices the first 63 entries MUST be good since they are
   7048          * allocated by the hardware on startup.
   7049          */
   7050 
   7051         LOG_CLI((BSL_META_U(unit,
   7052                             "soc_mem_cfap_init: unit %d: "
   7053                             "Chip unusable, %d error(s) in low entries\n"),
   7054                  unit, bad_count_63));
   7055         sal_free(bad_list);
   7056         return SOC_E_FAIL;
   7057     }
   7058 
   7059     if (bad_count >= entry_count / 2) {
   7060         LOG_CLI((BSL_META_U(unit,
   7061                             "soc_mem_cfap_init: unit %d: "
   7062                             "Chip unusable, too many bad entries (%d)\n"),
   7063                  unit, bad_count));
   7064         sal_free(bad_list);
   7065         return SOC_E_FAIL;
   7066     }
   7067 
   7068     /*
   7069      * For each bad entry, swap it with a good entry taken from the end
   7070      * of the list.  This puts all bad entries at the end of the table
   7071      * where they will not be used.
   7072      */
   7073 
   7074     ptr = mt.index_end + 1;
   7075 
   7076     for (i = mt.index_start; i < ptr; i++) {
   7077         uint32        e_good, e_bad;
   7078 
   7079         if (bad_list[i - mt.index_start]) {
   7080             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   7081                         (BSL_META_U(unit,
   7082                                     "soc_mem_cfap_init: unit %d: "
   7083                                     "mapping out CBP index %d\n"),
   7084                          unit, i));
   7085 
   7086             do {
   7087                 --ptr;
   7088             } while (bad_list[ptr - mt.index_start]);
   7089 
   7090             if ((rv = soc_mem_read(unit, cfap_m,
   7091                                    MEM_BLOCK_ANY, i, &e_bad)) < 0) {
   7092                 sal_free(bad_list);
   7093                 return rv;
   7094             }
   7095 
   7096             if ((rv = soc_mem_read(unit, cfap_m,
   7097                                    MEM_BLOCK_ANY, ptr, &e_good)) < 0) {
   7098                 sal_free(bad_list);
   7099                 return rv;
   7100             }
   7101 
   7102             if ((rv = soc_mem_write(unit, cfap_m,
   7103                                     MEM_BLOCK_ANY, ptr, &e_bad)) < 0) {
   7104                 sal_free(bad_list);
   7105                 return rv;
   7106             }
   7107 
   7108             if ((rv = soc_mem_write(unit, cfap_m,
   7109                                     MEM_BLOCK_ANY, i, &e_good)) < 0) {
   7110                 sal_free(bad_list);
   7111                 return rv;
   7112             }
   7113         }
   7114     }
   7115 
   7116     /*
   7117      * Write CFAPPOOLSIZE with the number of good entries (minus 1).
   7118      */
   7119 
   7120     if (bad_count > 0) {
   7121         uint32  cfap_config = 0;
   7122         uint32  val;
   7123         uint32  cfap_thresh;
   7124 
   7125         LOG_CLI((BSL_META_U(unit,
   7126                             "soc_mem_cfap_init: unit %d: "
   7127                             "detected and removed %d bad entries\n"),
   7128                  unit, bad_count));
   7129 
   7130         cfappoolsize -= bad_count;
   7131 
   7132         soc_reg_field_set(unit, CFAPCONFIGr, &cfap_config,
   7133                           CFAPPOOLSIZEf, cfappoolsize);
   7134 
   7135         if ((rv = WRITE_CFAPCONFIGr(unit, cfappoolsize)) < 0) {
   7136             sal_free(bad_list);
   7137             return rv;
   7138         }
   7139 
   7140         if ((rv = READ_CFAPFULLTHRESHOLDr(unit, &val)) < 0) {
   7141             sal_free(bad_list);
   7142             return rv;
   7143         }
   7144         cfap_thresh = soc_reg_field_get(unit, CFAPFULLTHRESHOLDr,
   7145                                         val, CFAPFULLRESETPOINTf);
   7146         cfap_thresh -= bad_count;
   7147 
   7148         soc_reg_field_set(unit, CFAPFULLTHRESHOLDr, &val,
   7149                           CFAPFULLRESETPOINTf, cfap_thresh);
   7150 
   7151         cfap_thresh = soc_reg_field_get(unit, CFAPFULLTHRESHOLDr,
   7152                                         val, CFAPFULLSETPOINTf);
   7153         cfap_thresh -= bad_count;
   7154         soc_reg_field_set(unit, CFAPFULLTHRESHOLDr, &val,
   7155                           CFAPFULLSETPOINTf, cfap_thresh);
   7156         if ((rv = WRITE_CFAPFULLTHRESHOLDr(unit, val)) < 0) {
   7157             sal_free(bad_list);
   7158             return rv;
   7159         }
   7160     }
   7161 
   7162 done:
   7163 
   7164     sal_free(bad_list);
   7165 
   7166     return SOC_E_NONE;
   7167 }
   7168 
   7169 #endif /* BCM_ESW_SUPPORT */
   7170 
   7171 
   7172 /************************************************************************/
   7173 /* Routines for Filter Mask START/COUNT Maintenance                     */
   7174 /************************************************************************/
   7175 
   7176 #if defined(BCM_XGS_SUPPORT) || \
   7177     defined(BCM_SAND_SUPPORT) ||\
   7178     defined(PORTMOD_SUPPORT)
   7179 
   7180 /************************************************************************
   7181  * Table DMA
   7182  *
   7183  *    In hardware, it shares the same buffers and registers used for ARL DMA
   7184  *    In software, it shares with ARL DMA the same semaphore and interrupt
   7185  *        handler
   7186  * Assumption
   7187  *    ARL DMA and Table DMA should not co-exist. The buffer should be
   7188  *        pre-allocated at least (index_max - index_min + 1) * sizeof (entry)
   7189  */
   7190 
   7191 #define SOC_MEM_DMA_MAX_DATA_BEATS    4
   7192 
   7193 /*
   7194  * Function:
   7195  *    soc_mem_dmaable
   7196  * Purpose:
   7197  *    Determine whether a table is DMA_able
   7198  * Returns:
   7199  *    0 if not, 1 otherwise
   7200  */
   7201 int
   7202 soc_mem_dmaable(int unit, soc_mem_t mem, int copyno)
   7203 {
   7204     if (SOC_CONTROL(unit)->tdma_enb == 0) {    /* not enabled */
   7205         return FALSE;
   7206     }
   7207 
   7208 
   7209 #if defined(BCM_RCPU_SUPPORT)
   7210     if(SOC_IS_RCPU_ONLY(unit)) {
   7211         return FALSE;
   7212     }
   7213 #endif
   7214 
   7215 #if defined(BCM_DFE_SUPPORT) || defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT)
   7216     if(SOC_IS_DFE(unit) || SOC_IS_DNXF(unit) || SOC_IS_DNX(unit)) {
   7217 #ifndef PLISIM
   7218         return TRUE;
   7219 #else
   7220         return FALSE;
   7221 #endif /* PLISIM */
   7222     }
   7223 #endif /* BCM_DFE_SUPPORT || BCM_DNXF_SUPPORT */
   7224 
   7225 #if defined(BCM_PETRA_SUPPORT)
   7226     if(SOC_IS_ARAD(unit)) {
   7227 #ifndef PLISIM
   7228         if (SOC_IS_ARADPLUS_AND_BELOW(unit) && (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_SCH)) {
   7229             return FALSE;
   7230         }
   7231 
   7232 
   7233         return TRUE;
   7234 #else
   7235         return FALSE;
   7236 #endif /* PLISIM */
   7237     }
   7238 #endif /* BCM_PETRA_SUPPORT */
   7239 
   7240     assert(SOC_MEM_IS_VALID(unit, mem)); /* some devices test id DMA is enabled per memory */
   7241 
   7242 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   7243     if (soc_feature(unit, soc_feature_field_stage_quarter_slice)
   7244         && soc_feature(unit, soc_feature_field_quarter_slice_single_tcam)
   7245         && soc_feature(unit, soc_feature_field_ingress_two_slice_types)) {
   7246         /* Do not use dma for TCAMs with holes */
   7247         if ((FP_TCAMm == mem) || (FP_GM_FIELDSm == mem)
   7248             || (FP_GLOBAL_MASK_TCAMm == mem) || (FP_GLOBAL_MASK_TCAM_Xm == mem)
   7249             || (FP_GLOBAL_MASK_TCAM_Ym == mem) || (FP_COUNTER_TABLEm == mem)) {
   7250             return FALSE;
   7251         }
   7252     }
   7253 #endif /* !BCM_TRIDENT2PLUS_SUPPORT */
   7254 
   7255 
   7256 #ifdef BCM_APACHE_SUPPORT
   7257     if (soc_feature(unit, soc_feature_field_stage_half_slice)
   7258         && soc_feature(unit, soc_feature_field_half_slice_single_tcam)
   7259         && soc_feature(unit, soc_feature_field_ingress_two_slice_types)) {
   7260         /* Do not use dma for TCAMs with holes */
   7261         if ((FP_TCAMm == mem) || (FP_GM_FIELDSm == mem)
   7262             || (FP_GLOBAL_MASK_TCAMm == mem) || (FP_GLOBAL_MASK_TCAM_Xm == mem)
   7263             || (FP_GLOBAL_MASK_TCAM_Ym == mem) || (FP_COUNTER_TABLEm == mem)) {
   7264             return FALSE;
   7265         }
   7266     }
   7267 #endif /* !BCM_APACHE_SUPPORT */
   7268 #ifdef BCM_TOMAHAWK2_SUPPORT
   7269         if (soc_feature(unit, soc_feature_field_stage_half_slice) ||
   7270             soc_feature(unit, soc_feature_field_stage_quarter_slice)) {
   7271             /* Do not use dma for TCAMs with holes */
   7272             if ((IFP_TCAMm == mem) ||
   7273                 (IFP_TCAM_PIPE0m == mem) ||(IFP_TCAM_PIPE1m == mem) ||
   7274                 (IFP_TCAM_PIPE2m == mem) || (IFP_TCAM_PIPE3m == mem) ||
   7275                 (IFP_TCAM_WIDEm == mem) ||
   7276                 (IFP_TCAM_WIDE_PIPE0m == mem) || (IFP_TCAM_WIDE_PIPE1m == mem) ||
   7277                 (IFP_TCAM_WIDE_PIPE2m == mem) || (IFP_TCAM_WIDE_PIPE3m == mem)) {
   7278                 return FALSE;
   7279             }
   7280         }
   7281 #endif /* BCM_TOMAHAWK2_SUPPORT */
   7282     /* Do not use DMA for TCAMs with holes */
   7283     if (soc_feature(unit, soc_feature_field_stage_egress_512_half_slice)) {
   7284         if ((mem == EFP_TCAMm) || (mem == EFP_POLICY_TABLEm)) {
   7285             return FALSE;
   7286         }
   7287     }
   7288     if (soc_feature(unit, soc_feature_field_stage_lookup_512_half_slice)) {
   7289         if ((mem == VFP_TCAMm) || (mem == VFP_POLICY_TABLEm)) {
   7290             return FALSE;
   7291         }
   7292     }
   7293 
   7294 #ifdef ALPM_ENABLE
   7295     if (soc_feature(unit, soc_feature_alpm) &&
   7296         (mem == L3_DEFIP_ALPM_IPV4m || mem == L3_DEFIP_ALPM_IPV4_1m ||
   7297          mem == L3_DEFIP_ALPM_IPV6_64m || mem == L3_DEFIP_ALPM_IPV6_64_1m ||
   7298          mem == L3_DEFIP_ALPM_IPV6_128m)) {
   7299         return FALSE;
   7300     }
   7301 #endif
   7302 
   7303 #if defined(BCM_FIREBOLT_SUPPORT)
   7304 #if defined(SOC_MEM_L3_DEFIP_WAR) || defined(BCM_TRIUMPH3_SUPPORT) || \
   7305     defined(BCM_ENDURO_SUPPORT) || defined(BCM_KATANA2_SUPPORT) || \
   7306     defined(BCM_KATANA_SUPPORT)
   7307     if (soc_feature(unit, soc_feature_l3_defip_map) &&
   7308         (mem == L3_DEFIPm ||
   7309          mem == L3_DEFIP_LEVEL1m ||
   7310          mem == L3_DEFIP_ONLYm ||
   7311          mem == L3_DEFIP_DATA_ONLYm ||
   7312          mem == L3_DEFIP_HIT_ONLYm ||
   7313          mem == L3_DEFIP_HIT_ONLY_Xm ||
   7314          mem == L3_DEFIP_HIT_ONLY_Ym)) {
   7315         return FALSE;   /* Could be non-contiguous */
   7316     }
   7317 #endif /* SOC_MEM_L3_DEFIP_WAR || BCM_TRIUMPH3_SUPPORT ||
   7318         * BCM_ENDURO_SUPPORT || BCM_KATANA2_SUPPORT*/
   7319 #endif /* BCM_FIREBOLT_SUPPORT */
   7320 
   7321 #ifdef BCM_TRIUMPH2_SUPPORT
   7322     if (soc_feature(unit, soc_feature_l3_defip_hole) &&
   7323         (mem == L3_DEFIPm ||
   7324          mem == L3_DEFIP_ONLYm ||
   7325          mem == L3_DEFIP_DATA_ONLYm ||
   7326          mem == L3_DEFIP_HIT_ONLYm)) {
   7327         return FALSE;
   7328     }
   7329     if ((mem == LMEPm) || (mem == LMEP_1m)) {
   7330         return FALSE;
   7331     }
   7332     if (mem == EFP_TCAMm) {
   7333         /* Do not use dma for tcams with holes */
   7334         if (soc_feature(unit, soc_feature_field_stage_half_slice)) {
   7335             if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || SOC_IS_VALKYRIE2(unit))  {
   7336                 return FALSE;
   7337             }
   7338         }
   7339      }
   7340 
   7341 #endif /* BCM_TRIUMPH2_SUPPORT */
   7342 
   7343 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA2_SUPPORT) || \
   7344     defined(BCM_KATANA_SUPPORT) 
   7345     if (soc_feature(unit, soc_feature_l3_defip_map) &&
   7346         (mem == L3_DEFIP_PAIR_128m ||
   7347          mem == L3_DEFIP_PAIR_LEVEL1m ||
   7348          mem == L3_DEFIP_PAIR_128_ONLYm ||
   7349          mem == L3_DEFIP_PAIR_128_DATA_ONLYm ||
   7350          mem == L3_DEFIP_PAIR_128_HIT_ONLYm ||
   7351          mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm ||
   7352          mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym)) {
   7353         return FALSE;
   7354     }
   7355 #endif  /* BCM_TRIUMPH3_SUPPORT  || BCM_KATANA2_SUPPORT*/
   7356 #if defined(BCM_TRIUMPH3_SUPPORT)
   7357     if (mem == PORT_EHG_RX_TUNNEL_DATAm || mem == PORT_EHG_RX_TUNNEL_MASKm ||
   7358         mem == PORT_EHG_TX_TUNNEL_DATAm) {
   7359         return FALSE;
   7360     }
   7361 #endif /* BCM_TRIUMPH3_SUPPORT*/
   7362 
   7363 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT)
   7364     if (mem == FP_GLOBAL_MASK_TCAMm || mem == FP_TCAMm || mem == EFP_TCAMm) {
   7365         /* Do not use dma for tcams with holes */
   7366         if (soc_feature(unit, soc_feature_field_stage_half_slice) ||
   7367                 soc_feature(unit, soc_feature_field_slice_size128)) {
   7368             return FALSE;
   7369         }
   7370     }
   7371 #endif /* BCM_TRIUMPH3_SUPPORT || BCM_HURRICANE2_SUPPORT*/
   7372 
   7373 #ifdef BCM_TRX_SUPPORT
   7374     if (SOC_IS_TRX(unit) && !SOC_IS_TD2_TT2(unit) && !SAL_BOOT_BCMSIM) {
   7375         if (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_MMU) {
   7376             switch (mem) {
   7377             case CTR_FLEX_COUNT_0m: case CTR_FLEX_COUNT_1m: case CTR_FLEX_COUNT_2m:
   7378             case CTR_FLEX_COUNT_3m: case CTR_FLEX_COUNT_4m: case CTR_FLEX_COUNT_5m:
   7379             case CTR_FLEX_COUNT_6m: case CTR_FLEX_COUNT_7m: case CTR_FLEX_COUNT_8m:
   7380             case CTR_FLEX_COUNT_9m: case CTR_FLEX_COUNT_10m: case CTR_FLEX_COUNT_11m:
   7381                 return TRUE;
   7382             default:
   7383                 return FALSE;
   7384             }
   7385         }
   7386     }
   7387 #endif /* BCM_TRX_SUPPORT */
   7388     if (!soc_feature(unit, soc_feature_flexible_dma_steps) &&
   7389         soc_mem_index_count(unit, mem) > 1) {
   7390 #ifdef BCM_TRIUMPH_SUPPORT
   7391         /* For DNX chips - We can't reach here, and hence the coverity defect is not relevant for DNX chips */
   7392         /* coverity[index:FALSE] */
   7393         if (soc_feature(unit, soc_feature_esm_support) &&
   7394             SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) {
   7395             int index0, index1;
   7396             soc_mem_t real_mem;
   7397 
   7398             /* On BCM56624_A0, don't do DMA for tables whose associated TCAM
   7399              * entry is wider than a single raw TCAM entry */
   7400             soc_tcam_mem_index_to_raw_index(unit, mem, 0, &real_mem, &index0);
   7401             soc_tcam_mem_index_to_raw_index(unit, mem, 1, &real_mem, &index1);
   7402             if (index1 - index0 != 1) {
   7403                 return FALSE;
   7404             }
   7405         }
   7406 #endif /* BCM_TRIUMPH_SUPPORT */
   7407     }
   7408 
   7409 #ifdef BCM_TRIDENT_SUPPORT
   7410     if (SOC_IS_TRIDENT(unit) || SOC_IS_TITAN(unit)) {
   7411         /*
   7412          * EGR_VLAN requires to combine entries from both pipe
   7413          * the single entry ISBS_PORT_TO_PIPE_MAPPING and
   7414          * ESBS_PORT_TO_PIPE_MAPPING table need data_beat size adjustment
   7415          */
   7416         if (mem == EGR_VLANm ||
   7417             mem == ISBS_PORT_TO_PIPE_MAPPINGm ||
   7418             mem == ESBS_PORT_TO_PIPE_MAPPINGm) {
   7419             return FALSE;
   7420         }
   7421     }
   7422 #endif /* BCM_TRIDENT_SUPPORT */
   7423 
   7424 #ifdef BCM_TRIUMPH3_SUPPORT
   7425     if (SOC_IS_TRIUMPH3(unit)) {
   7426         if (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_IBOD) {
   7427             return FALSE;
   7428         }
   7429 
   7430     }
   7431     if (soc_feature(unit, soc_feature_field_stage_quarter_slice)) {
   7432         /* Do not use dma for tcams with holes */
   7433         if (mem == FP_GLOBAL_MASK_TCAMm || mem == FP_TCAMm ||
   7434             mem == VFP_TCAMm || mem == EFP_TCAMm || mem == FP_COUNTER_TABLEm) {
   7435             return FALSE;
   7436         }
   7437     }
   7438 #endif /* BCM_TRIUMPH3_SUPPORT */
   7439 
   7440 #ifdef BCM_HURRICANE2_SUPPORT
   7441     if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 
   7442         SOC_IS_HURRICANE3(unit)) {
   7443         if (mem == EFP_TCAMm) {
   7444             /* Probable Non Contiguous.. Need to Investigate */
   7445             return FALSE;
   7446         }
   7447     }
   7448 #endif /* BCM_HURRICANE2_SUPPORT */
   7449 
   7450 #ifdef BCM_SHADOW_SUPPORT
   7451     if (SOC_IS_SHADOW(unit)) {
   7452         /*
   7453          * IL_STAT_MEM_x counters
   7454          */
   7455         if (mem == IL_STAT_MEM_3m ) {
   7456             return FALSE;
   7457         }
   7458     }
   7459 #endif /* BCM_SHADOW_SUPPORT */
   7460 
   7461 
   7462 #ifdef  BCM_XGS3_SWITCH_SUPPORT
   7463     if (SOC_IS_XGS3_SWITCH(unit)) {
   7464         return TRUE;
   7465     }
   7466 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   7467 
   7468     return (soc_mem_entry_words(unit, mem) <= SOC_MEM_DMA_MAX_DATA_BEATS);
   7469 }
   7470 
   7471 /*
   7472  * Function:
   7473  *    soc_mem_slamable
   7474  * Purpose:
   7475  *    Determine whether a table is SLAMable
   7476  * Returns:
   7477  *    0 if not, 1 otherwise
   7478  */
   7479 int
   7480 soc_mem_slamable(int unit, soc_mem_t mem, int copyno)
   7481 {
   7482     if (SOC_CONTROL(unit)->tslam_enb == 0) {    /* not enabled */
   7483         return FALSE;
   7484     }
   7485 
   7486 #if defined(BCM_RCPU_SUPPORT)
   7487     if(SOC_IS_RCPU_ONLY(unit)) {
   7488         return FALSE;
   7489     }
   7490 #endif
   7491 
   7492 #if defined(BCM_DFE_SUPPORT) || defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT)
   7493     if(SOC_IS_DFE(unit) || SOC_IS_DNXF(unit) || SOC_IS_DNX(unit)) {
   7494 #ifndef PLISIM
   7495         return TRUE;
   7496 #else
   7497         return FALSE;
   7498 #endif /* PLISIM */
   7499     }
   7500 #endif /* BCM_DFE_SUPPORT || BCM_DNXF_SUPPORT */
   7501 
   7502 #if defined(BCM_PETRA_SUPPORT)
   7503     if (SOC_IS_DPP(unit)) {
   7504 #ifndef PLISIM
   7505         return TRUE;
   7506 #else
   7507         return FALSE;
   7508 #endif /* PLISIM */
   7509     }
   7510 #endif /* BCM_PETRA_SUPPORT */
   7511 
   7512     assert(SOC_MEM_IS_VALID(unit, mem)); /* some devices test id DMA is enabled per memory */
   7513 
   7514 #if defined(BCM_FIREBOLT_SUPPORT)
   7515 #if defined(SOC_MEM_L3_DEFIP_WAR) || defined(BCM_TRIUMPH3_SUPPORT) || \
   7516     defined(BCM_ENDURO_SUPPORT) || defined(BCM_KATANA_SUPPORT)
   7517     if (soc_feature(unit, soc_feature_l3_defip_map) &&
   7518         (mem == L3_DEFIPm ||
   7519          mem == L3_DEFIP_LEVEL1m ||
   7520          mem == L3_DEFIP_ONLYm ||
   7521          mem == L3_DEFIP_DATA_ONLYm ||
   7522          mem == L3_DEFIP_HIT_ONLYm ||
   7523          mem == L3_DEFIP_HIT_ONLY_Xm ||
   7524          mem == L3_DEFIP_HIT_ONLY_Ym)) {
   7525         return FALSE;   /* Could be non-contiguous */
   7526     }
   7527 #endif /* SOC_MEM_L3_DEFIP_WAR || BCM_TRIUMPH3_SUPPORT || BCM_ENDURO_SUPPORT */
   7528 #endif /* BCM_FIREBOLT_SUPPORT */
   7529 
   7530 #ifdef BCM_TRIUMPH2_SUPPORT
   7531     if (soc_feature(unit, soc_feature_l3_defip_hole) &&
   7532         (mem == L3_DEFIPm ||
   7533          mem == L3_DEFIP_ONLYm ||
   7534          mem == L3_DEFIP_DATA_ONLYm ||
   7535          mem == L3_DEFIP_HIT_ONLYm)) {
   7536         return FALSE;
   7537     }
   7538     if ((mem == LMEPm) || (mem == LMEP_1m)) {
   7539         return FALSE;
   7540     }
   7541 #endif /* BCM_TRIUMPH2_SUPPORT */
   7542 
   7543 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA2_SUPPORT) || \
   7544     defined(BCM_KATANA_SUPPORT) 
   7545     if (soc_feature(unit, soc_feature_l3_defip_map) &&
   7546         (mem == L3_DEFIP_PAIR_128m ||
   7547          mem == L3_DEFIP_PAIR_LEVEL1m ||
   7548          mem == L3_DEFIP_PAIR_128_ONLYm ||
   7549          mem == L3_DEFIP_PAIR_128_DATA_ONLYm ||
   7550          mem == L3_DEFIP_PAIR_128_HIT_ONLYm ||
   7551          mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm ||
   7552          mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym)) {
   7553         return FALSE;
   7554     }
   7555 #endif /* BCM_TRIUMPH3_SUPPORT || BCM_KATANA2_SUPPORT*/
   7556 
   7557 #ifdef BCM_TRX_SUPPORT
   7558     if (SOC_IS_TRX(unit) && !SOC_IS_TD2_TT2(unit)) {
   7559         if (!SAL_BOOT_BCMSIM && SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_MMU) {
   7560             return FALSE;
   7561         }
   7562     }
   7563 #endif /* BCM_TRX_SUPPORT */
   7564 
   7565     if (!soc_feature(unit, soc_feature_flexible_dma_steps) &&
   7566         soc_mem_index_count(unit, mem) > 1) {
   7567 #ifdef BCM_TRIUMPH_SUPPORT
   7568         if (soc_feature(unit, soc_feature_esm_support) &&
   7569             SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) {
   7570             int index0, index1;
   7571             soc_mem_t real_mem;
   7572 
   7573             /* On BCM56624_A0, don't do DMA for tables whose associated TCAM
   7574              * entry is wider than a single raw TCAM entry */
   7575             soc_tcam_mem_index_to_raw_index(unit, mem, 0, &real_mem, &index0);
   7576             soc_tcam_mem_index_to_raw_index(unit, mem, 1, &real_mem, &index1);
   7577             if (index1 - index0 != 1) {
   7578                 return FALSE;
   7579             }
   7580         }
   7581 #endif /* BCM_TRIUMPH_SUPPORT */
   7582     }
   7583 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA2_SUPPORT)
   7584     if (SOC_CONTROL(unit)->l3_defip_index_remap &&
   7585         (mem == L3_DEFIP_PAIR_128m || mem == L3_DEFIPm ||
   7586          mem == L3_DEFIP_PAIR_LEVEL1m || mem == L3_DEFIP_LEVEL1m)) {
   7587         return FALSE;
   7588     }
   7589 #endif /* BCM_TRIUMPH3_SUPPORT || BCM_KATANA2_SUPPORT*/
   7590     return TRUE;
   7591 }
   7592 
   7593 /*
   7594  * Function:
   7595  *    _soc_xgs3_mem_dma
   7596  * Purpose:
   7597  *    DMA acceleration for soc_mem_read_range() on FB/ER
   7598  * Parameters:
   7599  *    buffer -- must be pointer to sufficiently large
   7600  *            DMA-able block of memory
   7601  */
   7602 STATIC int
   7603 _soc_xgs3_mem_dma(int unit, soc_mem_t mem, unsigned array_index,
   7604                   int copyno, int index_min, int index_max,
   7605                   uint32 ser_flags, void *buffer)
   7606 {
   7607     soc_control_t *soc = SOC_CONTROL(unit);
   7608     uint32        start_addr;
   7609     uint32        count;
   7610     uint32        data_beats;
   7611     uint32        spacing;
   7612     int           rv = SOC_E_NONE;
   7613     uint32        cfg, rval;
   7614     soc_mem_t     cmd_mem = INVALIDm;
   7615     uint8         at;
   7616 #if (defined  BCM_CMICM_SUPPORT)
   7617     int cmc = SOC_PCI_CMC(unit);
   7618 #endif
   7619 
   7620     /* coverity[var_tested_neg] */
   7621     LOG_INFO(BSL_LS_SOC_DMA,
   7622              (BSL_META_U(unit,
   7623                          "_soc_xgs3_mem_dma: unit %d"
   7624                          " mem %s.%s index %d-%d buffer %p\n"),
   7625               unit, SOC_MEM_UFNAME(unit, mem), SOC_BLOCK_NAME(unit, copyno),
   7626               index_min, index_max, buffer));
   7627 
   7628     data_beats = soc_mem_entry_words(unit, mem);
   7629 
   7630     count = index_max - index_min + 1;
   7631     if (count < 1) {
   7632         return SOC_E_NONE;
   7633     }
   7634 
   7635     if (cmd_mem != INVALIDm) {
   7636         MEM_LOCK(unit, cmd_mem);
   7637     }
   7638 
   7639     TABLE_DMA_LOCK(unit);
   7640 
   7641 #if defined(BCM_TRIUMPH3_SUPPORT)
   7642     if (soc_feature(unit, soc_feature_esm_correction) &&
   7643           ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
   7644          (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
   7645         SOC_ESM_LOCK(unit);
   7646     }
   7647 #endif
   7648 
   7649     /* coverity[negative_returns : FALSE] */
   7650     start_addr = soc_mem_addr_get(unit, mem, array_index,
   7651                                   copyno, index_min, &at);
   7652 
   7653 #if defined(BCM_XGS3_SWITCH_SUPPORT)
   7654     if (0 != (ser_flags & _SOC_SER_FLAG_MULTI_PIPE)) {
   7655         uint32 acc_type = ser_flags & _SOC_SER_FLAG_ACC_TYPE_MASK;
   7656         if (0 != acc_type) {
   7657             /* Override ACC_TYPE in address */
   7658             start_addr &= ~(_SOC_MEM_ADDR_ACC_TYPE_MASK <<
   7659                             _SOC_MEM_ADDR_ACC_TYPE_SHIFT);
   7660             start_addr |= (acc_type & _SOC_MEM_ADDR_ACC_TYPE_MASK) <<
   7661                             _SOC_MEM_ADDR_ACC_TYPE_SHIFT;
   7662         }
   7663     }
   7664 #endif /* BCM_XGS3_SWITCH_SUPPORT */
   7665 
   7666 #if (defined  BCM_CMICM_SUPPORT)
   7667     if(soc_feature(unit, soc_feature_cmicm)) {
   7668         soc_pci_write(unit, CMIC_CMCx_TABLE_DMA_PCIMEM_START_ADDR_OFFSET(cmc),
   7669                       soc_cm_l2p(unit, buffer));
   7670         soc_pci_write(unit, CMIC_CMCx_TABLE_DMA_SBUS_START_ADDR_OFFSET(cmc),
   7671                       start_addr);
   7672         rval = 0;
   7673         soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_ENTRY_COUNTr, &rval,
   7674                           COUNTf, count);
   7675         soc_pci_write(unit, CMIC_CMCx_TABLE_DMA_ENTRY_COUNT_OFFSET(cmc), rval);
   7676     } else
   7677 #endif /* CMICM Support */
   7678     {
   7679 
   7680         WRITE_CMIC_TABLE_DMA_PCIMEM_START_ADDRr(unit,
   7681                                                 soc_cm_l2p(unit, buffer));
   7682         WRITE_CMIC_TABLE_DMA_SBUS_START_ADDRr(unit, start_addr);
   7683         rval = 0;
   7684         soc_reg_field_set(unit, CMIC_TABLE_DMA_ENTRY_COUNTr, &rval,
   7685                           COUNTf, count);
   7686         if (soc_feature(unit, soc_feature_flexible_dma_steps) &&
   7687             soc_mem_index_count(unit, mem) > 1) {
   7688 #if defined(BCM_TRIUMPH_SUPPORT)
   7689             if (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) {
   7690                 int index0, index1, increment;
   7691                 soc_mem_t real_mem;
   7692 
   7693                 soc_tcam_mem_index_to_raw_index(unit, mem, 0,
   7694                                                 &real_mem, &index0);
   7695                 soc_tcam_mem_index_to_raw_index(unit, mem, 1,
   7696                                                 &real_mem, &index1);
   7697                 increment = _shr_popcount(index1 - index0 - 1);
   7698                 soc_reg_field_set(unit, CMIC_TABLE_DMA_ENTRY_COUNTr, &rval,
   7699                                   SBUS_ADDR_INCREMENT_STEPf, increment);
   7700             }
   7701 #endif /* BCM_TRIUMPH_SUPPORT */
   7702 #if defined(BCM_TRIUMPH3_SUPPORT)
   7703             if (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU) {
   7704                 int index0, index1, increment;
   7705                 soc_mem_t real_mem;
   7706 
   7707                 soc_tcam_mem_index_to_raw_index(unit, mem, 0,
   7708                                                 &real_mem, &index0);
   7709                 soc_tcam_mem_index_to_raw_index(unit, mem, 1,
   7710                                                 &real_mem, &index1);
   7711                 increment = _shr_popcount(index1 - index0 - 1);
   7712                 soc_reg_field_set(unit, CMIC_TABLE_DMA_ENTRY_COUNTr, &rval,
   7713                                   SBUS_ADDR_INCREMENT_STEPf, increment);
   7714             }
   7715 #endif /* BCM_TRIUMPH3_SUPPORT */
   7716         }
   7717         WRITE_CMIC_TABLE_DMA_ENTRY_COUNTr(unit, rval);
   7718     }
   7719     LOG_INFO(BSL_LS_SOC_DMA,
   7720              (BSL_META_U(unit,
   7721                          "_soc_xgs3_mem_dma: table dma of %d entries "
   7722                          "of %d beats from 0x%x\n"),
   7723               count, data_beats, start_addr));
   7724 
   7725     soc_cm_sflush(unit, buffer, WORDS2BYTES(data_beats) * count);
   7726     /* Set beats. Clear table DMA abort,done and error bit. Start DMA */
   7727 #if (defined  BCM_CMICM_SUPPORT)
   7728     if(soc_feature(unit, soc_feature_cmicm)) {
   7729         /* For CMICm retain Endianess etc... */
   7730         cfg = soc_pci_read(unit, CMIC_CMCx_TABLE_DMA_CFG_OFFSET(cmc));
   7731         soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_CFGr, &cfg,
   7732                             BEATSf, data_beats);
   7733         soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_CFGr, &cfg, ABORTf, 0);
   7734         soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_CFGr, &cfg, ENf, 0);
   7735         soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_CFGr, &cfg,
   7736                           ENABLE_MULTIPLE_SBUS_CMDSf, 0);
   7737         soc_pci_write(unit, CMIC_CMCx_TABLE_DMA_CFG_OFFSET(cmc), cfg);
   7738         /* Clearing EN clears stats */
   7739 
   7740         
   7741 #ifdef BCM_EXTND_SBUS_SUPPORT
   7742         if (soc_feature(unit, soc_feature_new_sbus_format)) {
   7743             rval = 0;
   7744             /* Use TR3 style sbus access */
   7745             soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_SBUS_CMD_CONFIGr,
   7746                               &rval, EN_TR3_SBUS_STYLEf, 1);
   7747             soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_SBUS_CMD_CONFIGr,
   7748                               &rval,
   7749                               SBUS_BLOCKIDf, SOC_BLOCK2SCH(unit, copyno));
   7750             soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_SBUS_CMD_CONFIGr,
   7751                               &rval,
   7752                               SBUS_ACCTYPEf,
   7753                               SOC_MEM_ACC_TYPE(unit, mem));
   7754             WRITE_CMIC_CMC0_TABLE_DMA_SBUS_CMD_CONFIGr(unit, rval);
   7755         }
   7756 #endif
   7757     } else
   7758 #endif
   7759     {
   7760         cfg = 0;
   7761         soc_reg_field_set(unit, CMIC_TABLE_DMA_CFGr, &cfg,
   7762                             BEATSf, data_beats);
   7763     }
   7764     if (soc_feature(unit, soc_feature_multi_sbus_cmds)) {
   7765         
   7766         if (soc->sbusCmdSpacing < 0) {
   7767             spacing = data_beats > 7 ? data_beats + 1 : 8;
   7768         } else {
   7769             spacing = soc->sbusCmdSpacing;
   7770         }
   7771         if ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
   7772             (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_XQPORT) ||
   7773             (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_GXPORT) ||
   7774             (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_SPORT) ||
   7775             (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_GPORT) ||
   7776             (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_QGPORT) ||
   7777             (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_LLS) ||
   7778             (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_MMU)) {
   7779             spacing = 0;
   7780         }
   7781 
   7782 #ifdef BCM_KATANA_SUPPORT
   7783        if (SOC_IS_KATANA(unit)) {
   7784            /* disable MOR for EFP_TCAM and EGR_VLAN_XLATE */
   7785            if (mem == EFP_TCAMm || mem == EGR_VLAN_XLATEm) {
   7786                spacing = 0;
   7787            }
   7788        }
   7789 #endif
   7790 
   7791         if (spacing) {
   7792 #if (defined  BCM_CMICM_SUPPORT)
   7793             if(soc_feature(unit, soc_feature_cmicm)) {
   7794                 soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_CFGr, &cfg,
   7795                                   MULTIPLE_SBUS_CMD_SPACINGf, spacing);
   7796                 soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_CFGr, &cfg,
   7797                                   ENABLE_MULTIPLE_SBUS_CMDSf, 1);
   7798 
   7799             } else
   7800 #endif
   7801             {
   7802                 soc_reg_field_set(unit, CMIC_TABLE_DMA_CFGr, &cfg,
   7803                                   MULTIPLE_SBUS_CMD_SPACINGf, spacing);
   7804                 soc_reg_field_set(unit, CMIC_TABLE_DMA_CFGr, &cfg,
   7805                                   ENABLE_MULTIPLE_SBUS_CMDSf, 1);
   7806             }
   7807         }
   7808     }
   7809 #if (defined  BCM_CMICM_SUPPORT)
   7810     if(soc_feature(unit, soc_feature_cmicm)) {
   7811         soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_CFGr, &cfg, ENf, 1);
   7812         soc_pci_write(unit, CMIC_CMCx_TABLE_DMA_CFG_OFFSET(cmc), cfg);
   7813     } else
   7814 #endif
   7815     {
   7816         soc_reg_field_set(unit, CMIC_TABLE_DMA_CFGr, &cfg, ENf, 1);
   7817         WRITE_CMIC_TABLE_DMA_CFGr(unit, cfg);
   7818     }
   7819     rv = SOC_E_TIMEOUT;
   7820     if (soc->tableDmaIntrEnb) {
   7821 #if (defined  BCM_CMICM_SUPPORT)
   7822         if(soc_feature(unit, soc_feature_cmicm)) {
   7823             soc_cmicm_intr0_enable(unit, IRQ_CMCx_TDMA_DONE);
   7824             if (TABLE_DMA_INTR_WAIT(unit, soc->tableDmaTimeout) < 0) {
   7825                 rv = SOC_E_TIMEOUT;
   7826             }
   7827             soc_cmicm_intr0_disable(unit, IRQ_CMCx_TDMA_DONE);
   7828 
   7829             cfg = soc_pci_read(unit, CMIC_CMCx_TABLE_DMA_STAT_OFFSET(cmc));
   7830             if (soc_reg_field_get(unit, CMIC_CMC0_TABLE_DMA_STATr,
   7831                                                         cfg, DONEf)) {
   7832                 rv = SOC_E_NONE;
   7833                 if (soc_reg_field_get(unit, CMIC_CMC0_TABLE_DMA_STATr,
   7834                                                         cfg, ERRORf)) {
   7835                     rv = SOC_E_FAIL;
   7836                 }
   7837             }
   7838         } else
   7839 #endif
   7840         {
   7841             soc_intr_enable(unit, IRQ_TDMA_DONE);
   7842             if (TABLE_DMA_INTR_WAIT(unit, soc->tableDmaTimeout) < 0) {
   7843                 rv = SOC_E_TIMEOUT;
   7844             }
   7845             soc_intr_disable(unit, IRQ_TDMA_DONE);
   7846 
   7847             READ_CMIC_TABLE_DMA_CFGr(unit, &cfg);
   7848             if (soc_reg_field_get(unit, CMIC_TABLE_DMA_CFGr,
   7849                     cfg, DONEf)) {
   7850                 rv = SOC_E_NONE;
   7851                 if (soc_reg_field_get(unit, CMIC_TABLE_DMA_CFGr,
   7852                         cfg, ERRORf)) {
   7853                     rv = SOC_E_FAIL;
   7854                 }
   7855             }
   7856         }
   7857     } else {
   7858         soc_timeout_t to;
   7859 
   7860         soc_timeout_init(&to, soc->tableDmaTimeout, 10000);
   7861 
   7862         do {
   7863 #if (defined  BCM_CMICM_SUPPORT)
   7864             if(soc_feature(unit, soc_feature_cmicm)) {
   7865                 cfg = soc_pci_read(unit, CMIC_CMCx_TABLE_DMA_STAT_OFFSET(cmc));
   7866                 if (soc_reg_field_get(unit, CMIC_CMC0_TABLE_DMA_STATr,
   7867                                                         cfg, DONEf)) {
   7868                     rv = SOC_E_NONE;
   7869                     if (soc_reg_field_get(unit, CMIC_CMC0_TABLE_DMA_STATr,
   7870                                                         cfg, ERRORf)) {
   7871                         rv = SOC_E_FAIL;
   7872                     }
   7873                     break;
   7874                 }
   7875             } else
   7876 #endif
   7877             {
   7878                 READ_CMIC_TABLE_DMA_CFGr(unit, &cfg);
   7879                 if (soc_reg_field_get(unit, CMIC_TABLE_DMA_CFGr,
   7880                         cfg, DONEf)) {
   7881                     rv = SOC_E_NONE;
   7882                     if (soc_reg_field_get(unit, CMIC_TABLE_DMA_CFGr,
   7883                             cfg, ERRORf)) {
   7884                         rv = SOC_E_FAIL;
   7885                     }
   7886                     break;
   7887                 }
   7888              }
   7889         } while(!(soc_timeout_check(&to)));
   7890     }
   7891 
   7892     if (rv < 0) {
   7893         if (rv != SOC_E_TIMEOUT) {
   7894             LOG_ERROR(BSL_LS_SOC_SOCMEM,
   7895                       (BSL_META_U(unit,
   7896                                   "%s.%s failed(NAK)\n"),
   7897                        SOC_MEM_UFNAME(unit, mem),
   7898                        SOC_BLOCK_NAME(unit, copyno)));
   7899 #ifdef BCM_TRIUMPH2_SUPPORT
   7900             if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) ||
   7901                 SOC_IS_VALKYRIE2(unit)) {
   7902                 /* SCHAN nack */
   7903                 sal_dpc(soc_triumph2_mem_nack, INT_TO_PTR(unit),
   7904                         INT_TO_PTR(start_addr), 0, 0, 0);
   7905             }
   7906 #endif /* BCM_TRIUMPH2_SUPPORT */
   7907         } else {
   7908             soc_timeout_t to;
   7909 
   7910             LOG_ERROR(BSL_LS_SOC_SOCMEM,
   7911                       (BSL_META_U(unit,
   7912                                   "TableDmaTimeOut: %s.%s %s timeout\n"),
   7913                        SOC_MEM_UFNAME(unit, mem),
   7914                        SOC_BLOCK_NAME(unit, copyno),
   7915                        soc->tableDmaIntrEnb ? "interrupt" : "polling"));
   7916 
   7917 #if (defined  BCM_CMICM_SUPPORT)
   7918             if(soc_feature(unit, soc_feature_cmicm)) {
   7919                 /* Abort Table DMA */
   7920                 cfg = soc_pci_read(unit, CMIC_CMCx_TABLE_DMA_CFG_OFFSET(cmc));
   7921                 soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_CFGr, &cfg, ENf, 0);
   7922                 soc_reg_field_set(unit, CMIC_CMC0_TABLE_DMA_CFGr, &cfg, ABORTf, 1);
   7923                 soc_pci_write(unit, CMIC_CMCx_TABLE_DMA_CFG_OFFSET(cmc), cfg);
   7924 
   7925                 /* Check the done bit to confirm */
   7926                 soc_timeout_init(&to, soc->tableDmaTimeout, 0);
   7927                 while (1) {
   7928                     cfg = soc_pci_read(unit, CMIC_CMCx_TABLE_DMA_STAT_OFFSET(cmc));
   7929                     if (soc_reg_field_get(unit, CMIC_CMC0_TABLE_DMA_STATr, cfg, DONEf)) {
   7930                         break;
   7931                     }
   7932                     if (soc_timeout_check(&to)) {
   7933                         LOG_ERROR(BSL_LS_SOC_SOCMEM,
   7934                                   (BSL_META_U(unit,
   7935                                               "TableDmaTimeOut:_soc_xgs3_mem_dma, Abort Failed\n")));
   7936                         break;
   7937                     }
   7938                 }
   7939             } else
   7940 #endif
   7941             {
   7942                 /* Abort Table DMA */
   7943                 READ_CMIC_TABLE_DMA_CFGr(unit, &cfg);
   7944                 soc_reg_field_set(unit, CMIC_TABLE_DMA_CFGr, &cfg, ENf, 0);
   7945                 soc_reg_field_set(unit, CMIC_TABLE_DMA_CFGr, &cfg, ABORTf, 1);
   7946                 soc_reg_field_set(unit, CMIC_TABLE_DMA_CFGr, &cfg, DONEf, 0);
   7947                 soc_reg_field_set(unit, CMIC_TABLE_DMA_CFGr, &cfg, ERRORf, 0);
   7948                 WRITE_CMIC_TABLE_DMA_CFGr(unit, cfg);
   7949 
   7950                 /* Check the done bit to confirm */
   7951                 soc_timeout_init(&to, soc->tableDmaTimeout, 0);
   7952                 while (1) {
   7953                     READ_CMIC_TABLE_DMA_CFGr(unit, &cfg);
   7954                     if (soc_reg_field_get(unit, CMIC_TABLE_DMA_CFGr, cfg, DONEf)) {
   7955                         break;
   7956                     }
   7957                     if (soc_timeout_check(&to)) {
   7958                         LOG_ERROR(BSL_LS_SOC_SOCMEM,
   7959                                   (BSL_META_U(unit,
   7960                                               "TableDmaTimeOut:_soc_xgs3_mem_dma, Abort Failed\n")));
   7961                         break;
   7962                     }
   7963                 }
   7964             }
   7965         }
   7966     }
   7967 
   7968     soc_cm_sinval(unit, (void *)buffer, WORDS2BYTES(data_beats) * count);
   7969 
   7970 #if defined(BCM_TRIUMPH3_SUPPORT)
   7971     if (soc_feature(unit, soc_feature_esm_correction) &&
   7972           ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
   7973          (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
   7974         SOC_ESM_UNLOCK(unit);
   7975     }
   7976 #endif
   7977 
   7978     TABLE_DMA_UNLOCK(unit);
   7979 
   7980     if (cmd_mem != INVALIDm) {
   7981         MEM_UNLOCK(unit, cmd_mem);
   7982     }
   7983 
   7984     return rv;
   7985 }
   7986 
   7987 /*
   7988  * Function:
   7989  *    _soc_xgs3_mem_slam
   7990  * Purpose:
   7991  *    DMA acceleration for soc_mem_write_range() on FB/ER
   7992  * Parameters:
   7993  *    buffer -- must be pointer to sufficiently large
   7994  *            DMA-able block of memory
   7995  *      index_begin <= index_end - Forward direction
   7996  *      index_begin >  index_end - Reverse direction
   7997  */
   7998 
   7999 STATIC int
   8000 _soc_xgs3_mem_slam(int unit, uint32 flags, soc_mem_t mem, unsigned array_index, int copyno,
   8001                    int index_begin, int index_end, void *buffer)
   8002 {
   8003     soc_control_t *soc = SOC_CONTROL(unit);
   8004     uint32        start_addr;
   8005     uint32        count;
   8006     uint32        data_beats;
   8007     uint32        spacing;
   8008     int           rv = SOC_E_NONE;
   8009     uint32        cfg, rval;
   8010     uint8         at;
   8011 #if (defined  BCM_CMICM_SUPPORT)
   8012     int cmc = SOC_PCI_CMC(unit);
   8013 #endif
   8014 
   8015     LOG_INFO(BSL_LS_SOC_DMA,
   8016              (BSL_META_U(unit,
   8017                          "_soc_xgs3_mem_slam: unit %d"
   8018                          " mem %s.%s index %d-%d buffer %p\n"),
   8019               unit, SOC_MEM_UFNAME(unit, mem), SOC_BLOCK_NAME(unit, copyno),
   8020               index_begin, index_end, buffer));
   8021 
   8022     data_beats = soc_mem_entry_words(unit, mem);
   8023 
   8024     if (index_begin > index_end) {
   8025         /* coverity[negative_returns : FALSE] */
   8026         start_addr = soc_mem_addr_get(unit, mem, array_index, copyno, index_end, &at);
   8027         count = index_begin - index_end + 1;
   8028     } else {
   8029         /* coverity[negative_returns : FALSE] */
   8030         start_addr = soc_mem_addr_get(unit, mem, array_index, copyno, index_begin, &at);
   8031         count = index_end - index_begin + 1;
   8032     }
   8033 
   8034     if (!flags || (flags & SOC_MEM_WRITE_SET_ONLY)) {
   8035 
   8036     #if (defined  BCM_CMICM_SUPPORT)
   8037         if(soc_feature(unit, soc_feature_cmicm)) {
   8038             /* For CMICm retain Endianess etc... */
   8039             cfg = soc_pci_read(unit, CMIC_CMCx_SLAM_DMA_CFG_OFFSET(cmc));
   8040             soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_CFGr, &cfg, ABORTf, 0);
   8041             soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_CFGr, &cfg, ENf, 0);
   8042             soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_CFGr, &cfg,
   8043                               ENABLE_MULTIPLE_SBUS_CMDSf, 0);
   8044             soc_pci_write(unit, CMIC_CMCx_SLAM_DMA_CFG_OFFSET(cmc), cfg);  /* Clearing EN clears the stats */
   8045 
   8046             /* Set beats. Clear tslam DMA abort,done and error bit. Start DMA */
   8047             soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_CFGr, &cfg, BEATSf, data_beats);
   8048 
   8049 #if defined(BCM958525)
   8050             /* Modulo count for 128B payload size */
   8051             soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_CFGr, &cfg,
   8052                               REV_MODULO_COUNTf, (count % (32 / data_beats)));
   8053 #else
   8054             soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_CFGr, &cfg,
   8055                               REV_MODULO_COUNTf, (count % (64 / data_beats)));
   8056 #endif
   8057             soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_CFGr, &cfg,
   8058                                 ORDERf, (index_begin > index_end) ? 1:0);
   8059 
   8060     #ifdef BCM_EXTND_SBUS_SUPPORT
   8061             if (soc_feature(unit, soc_feature_new_sbus_format)) {
   8062                 rval = 0;
   8063                 /* Use TR3 style sbus access */
   8064                 soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_SBUS_CMD_CONFIGr, &rval,
   8065                                   EN_TR3_SBUS_STYLEf, 1);
   8066                 soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_SBUS_CMD_CONFIGr, &rval,
   8067                                   SBUS_BLOCKIDf, SOC_BLOCK2SCH(unit, copyno));
   8068                 soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_SBUS_CMD_CONFIGr, &rval,
   8069                                   SBUS_ACCTYPEf, SOC_MEM_ACC_TYPE(unit, mem));
   8070                 WRITE_CMIC_CMC0_SLAM_DMA_SBUS_CMD_CONFIGr(unit, rval);
   8071             }
   8072     #endif
   8073         } else
   8074     #endif
   8075         {
   8076             /* Set beats. Clear tslam DMA abort,done and error bit. Start DMA */
   8077             cfg = 0;
   8078     #if defined(BCM958525)
   8079             /* Modulo count for 128B payload size */
   8080             soc_reg_field_set(unit, CMIC_SLAM_DMA_CFGr, &cfg, REV_MODULO_COUNTf,
   8081                               (count % (32 / data_beats)));
   8082     #else
   8083             soc_reg_field_set(unit, CMIC_SLAM_DMA_CFGr, &cfg, REV_MODULO_COUNTf,
   8084                               (count % (64 / data_beats)));
   8085     #endif
   8086             soc_reg_field_set(unit, CMIC_SLAM_DMA_CFGr, &cfg, BEATSf, data_beats);
   8087             soc_reg_field_set(unit, CMIC_SLAM_DMA_CFGr, &cfg,
   8088                                 ORDERf, (index_begin > index_end) ? 1:0);
   8089         }
   8090         if (soc_feature(unit, soc_feature_multi_sbus_cmds)) {
   8091             
   8092             if (soc->sbusCmdSpacing < 0) {
   8093                 spacing = data_beats > 7 ? data_beats + 1 : 8;
   8094             } else {
   8095                 spacing = soc->sbusCmdSpacing;
   8096             }
   8097             if ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
   8098                 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_XQPORT) ||
   8099                 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_GXPORT) ||
   8100                 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_XLPORT) ||
   8101                 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_SPORT) ||
   8102                 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_GPORT) ||
   8103                 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_QGPORT) ||
   8104                 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_LLS) ||
   8105                 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_MMU)) {
   8106                 spacing = 0;
   8107             }
   8108 
   8109     #ifdef BCM_KATANA_SUPPORT
   8110            if (SOC_IS_KATANA(unit)) {
   8111                /* disable MOR for EFP_TCAM and EGR_VLAN_XLATE */
   8112                if (mem == EFP_TCAMm || mem == EGR_VLAN_XLATEm) {
   8113                    spacing = 0;
   8114                }
   8115            }
   8116     #endif
   8117 
   8118             if (spacing) {
   8119     #if (defined  BCM_CMICM_SUPPORT)
   8120                 if(soc_feature(unit, soc_feature_cmicm)) {
   8121                     soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_CFGr, &cfg,
   8122                                       MULTIPLE_SBUS_CMD_SPACINGf, spacing);
   8123                     soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_CFGr, &cfg,
   8124                                       ENABLE_MULTIPLE_SBUS_CMDSf, 1);
   8125                 } else
   8126     #endif
   8127                 {
   8128                     soc_reg_field_set(unit, CMIC_SLAM_DMA_CFGr, &cfg,
   8129                                       MULTIPLE_SBUS_CMD_SPACINGf, spacing);
   8130                     soc_reg_field_set(unit, CMIC_SLAM_DMA_CFGr, &cfg,
   8131                                       ENABLE_MULTIPLE_SBUS_CMDSf, 1);
   8132                 }
   8133             }
   8134         }
   8135 
   8136         LOG_INFO(BSL_LS_SOC_DMA,
   8137                  (BSL_META_U(unit,
   8138                              "_soc_xgs3_mem_slam: tslam dma of %d entries "
   8139                              "of %d beats from 0x%x to index %d-%d\n"),
   8140                   count, data_beats, start_addr, index_begin, index_end));
   8141 
   8142         TSLAM_DMA_LOCK(unit);
   8143 #if defined(BCM_TRIUMPH3_SUPPORT)
   8144         if (soc_feature(unit, soc_feature_esm_correction) &&
   8145               ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
   8146              (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
   8147             SOC_ESM_LOCK(unit);
   8148         }
   8149 #endif
   8150         soc_cm_sflush(unit, buffer, WORDS2BYTES(data_beats) * count);
   8151     #if (defined  BCM_CMICM_SUPPORT)
   8152         if(soc_feature(unit, soc_feature_cmicm)) {
   8153             soc_pci_write(unit, CMIC_CMCx_SLAM_DMA_PCIMEM_START_ADDR_OFFSET(cmc),
   8154                           soc_cm_l2p(unit, buffer));
   8155             soc_pci_write(unit, CMIC_CMCx_SLAM_DMA_SBUS_START_ADDR_OFFSET(cmc), start_addr);
   8156             rval = 0;
   8157             soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_ENTRY_COUNTr, &rval, COUNTf, count);
   8158             soc_pci_write(unit, CMIC_CMCx_SLAM_DMA_ENTRY_COUNT_OFFSET(cmc), rval);
   8159             soc_pci_write(unit, CMIC_CMCx_SLAM_DMA_CFG_OFFSET(cmc), cfg);
   8160         } else
   8161     #endif
   8162         {
   8163             WRITE_CMIC_SLAM_DMA_PCIMEM_START_ADDRr(unit, soc_cm_l2p(unit, buffer));
   8164             WRITE_CMIC_SLAM_DMA_SBUS_START_ADDRr(unit, start_addr);
   8165             rval = 0;
   8166             soc_reg_field_set(unit, CMIC_SLAM_DMA_ENTRY_COUNTr, &rval, COUNTf, count);
   8167             if (soc_feature(unit, soc_feature_flexible_dma_steps) &&
   8168                 soc_mem_index_count(unit, mem) > 1) {
   8169     #if defined(BCM_TRIUMPH_SUPPORT)
   8170                 if (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) {
   8171                     int index0, index1, increment;
   8172                     soc_mem_t real_mem;
   8173 
   8174                     soc_tcam_mem_index_to_raw_index(unit, mem, 0, &real_mem, &index0);
   8175                     soc_tcam_mem_index_to_raw_index(unit, mem, 1, &real_mem, &index1);
   8176                     increment = _shr_popcount(index1 - index0 - 1);
   8177                     soc_reg_field_set(unit, CMIC_SLAM_DMA_ENTRY_COUNTr, &rval,
   8178                                       SBUS_ADDR_INCREMENT_STEPf, increment);
   8179                 }
   8180     #endif /* BCM_TRIUMPH_SUPPORT */
   8181     #if defined(BCM_TRIUMPH3_SUPPORT)
   8182                 if (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU) {
   8183                     int index0, index1, increment;
   8184                     soc_mem_t real_mem;
   8185 
   8186                     soc_tcam_mem_index_to_raw_index(unit, mem, 0, &real_mem, &index0);
   8187                     soc_tcam_mem_index_to_raw_index(unit, mem, 1, &real_mem, &index1);
   8188                     increment = _shr_popcount(index1 - index0 - 1);
   8189                     soc_reg_field_set(unit, CMIC_SLAM_DMA_ENTRY_COUNTr, &rval,
   8190                                       SBUS_ADDR_INCREMENT_STEPf, increment);
   8191                 }
   8192     #endif /* BCM_TRIUMPH3_SUPPORT */
   8193             }
   8194             WRITE_CMIC_SLAM_DMA_ENTRY_COUNTr(unit, rval);
   8195             WRITE_CMIC_SLAM_DMA_CFGr(unit, cfg);
   8196         }
   8197     }
   8198 
   8199     if (!flags || (flags & SOC_MEM_WRITE_COMMIT_ONLY)) {
   8200         cfg = 0;
   8201         /* write ENf bit to SLAM_DMA_CFG register */
   8202         #if (defined  BCM_CMICM_SUPPORT)
   8203         if(soc_feature(unit, soc_feature_cmicm)) {
   8204             cfg = soc_pci_read(unit, CMIC_CMCx_SLAM_DMA_CFG_OFFSET(cmc));
   8205             soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_CFGr, &cfg, ENf, 1);
   8206             soc_pci_write(unit, CMIC_CMCx_SLAM_DMA_CFG_OFFSET(cmc), cfg);
   8207         } else
   8208     #endif
   8209         {
   8210             READ_CMIC_SLAM_DMA_CFGr(unit, &cfg);
   8211             soc_reg_field_set(unit, CMIC_SLAM_DMA_CFGr, &cfg, ENf, 1);
   8212             WRITE_CMIC_SLAM_DMA_CFGr(unit, cfg);
   8213         }
   8214     }
   8215 
   8216     if (!flags || (flags & SOC_MEM_WRITE_STATUS_ONLY)) {
   8217 
   8218         rv = SOC_E_TIMEOUT;
   8219         if (soc->tslamDmaIntrEnb) {
   8220 
   8221     #if (defined  BCM_CMICM_SUPPORT)
   8222             if(soc_feature(unit, soc_feature_cmicm)) {
   8223                 soc_cmicm_intr0_enable(unit, IRQ_CMCx_TSLAM_DONE);
   8224                 if (TSLAM_DMA_INTR_WAIT(unit, soc->tslamDmaTimeout) < 0) {
   8225                     rv = SOC_E_TIMEOUT;
   8226                 }
   8227                 soc_cmicm_intr0_disable(unit, IRQ_CMCx_TSLAM_DONE);
   8228 
   8229                 cfg = soc_pci_read(unit, CMIC_CMCx_SLAM_DMA_STAT_OFFSET(cmc));
   8230                 if (soc_reg_field_get(unit, CMIC_CMC0_SLAM_DMA_STATr, cfg, DONEf)) {
   8231                     rv = SOC_E_NONE;
   8232                 }
   8233                 if (soc_reg_field_get(unit, CMIC_CMC0_SLAM_DMA_STATr, cfg, ERRORf)) {
   8234                     rv = SOC_E_FAIL;
   8235                 }
   8236             } else
   8237     #endif
   8238             {
   8239                 soc_intr_enable(unit, IRQ_TSLAM_DONE);
   8240                 if (TSLAM_DMA_INTR_WAIT(unit, soc->tslamDmaTimeout) < 0) {
   8241                     rv = SOC_E_TIMEOUT;
   8242                 }
   8243                 soc_intr_disable(unit, IRQ_TSLAM_DONE);
   8244 
   8245                 READ_CMIC_SLAM_DMA_CFGr(unit, &cfg);
   8246                 if (soc_reg_field_get(unit, CMIC_SLAM_DMA_CFGr, cfg, DONEf)) {
   8247                     rv = SOC_E_NONE;
   8248                 }
   8249                 if (soc_reg_field_get(unit, CMIC_SLAM_DMA_CFGr, cfg, ERRORf)) {
   8250                     rv = SOC_E_FAIL;
   8251                 }
   8252             }
   8253         } else {
   8254             soc_timeout_t to;
   8255 
   8256             soc_timeout_init(&to, soc->tslamDmaTimeout, 10000);
   8257 
   8258             do {
   8259     #if (defined  BCM_CMICM_SUPPORT)
   8260                 if(soc_feature(unit, soc_feature_cmicm)) {
   8261                     cfg = soc_pci_read(unit, CMIC_CMCx_SLAM_DMA_STAT_OFFSET(cmc));
   8262                     if (soc_reg_field_get(unit, CMIC_CMC0_SLAM_DMA_STATr, cfg, ERRORf)) {
   8263                         rv = SOC_E_FAIL;
   8264                         break;
   8265                     }
   8266                     if (soc_reg_field_get(unit, CMIC_CMC0_SLAM_DMA_STATr, cfg, DONEf)) {
   8267                         rv = SOC_E_NONE;
   8268                         break;
   8269                     }
   8270                 } else
   8271     #endif
   8272                 {
   8273                     READ_CMIC_SLAM_DMA_CFGr(unit, &cfg);
   8274                     if (soc_reg_field_get(unit, CMIC_SLAM_DMA_CFGr, cfg, ERRORf)) {
   8275                         rv = SOC_E_FAIL;
   8276                         break;
   8277                     }
   8278                     if (soc_reg_field_get(unit, CMIC_SLAM_DMA_CFGr, cfg, DONEf)) {
   8279                         rv = SOC_E_NONE;
   8280                         break;
   8281                     }
   8282                 }
   8283             } while (!(soc_timeout_check(&to)));
   8284         }
   8285 
   8286         if (rv < 0) {
   8287             if (rv != SOC_E_TIMEOUT) {
   8288                 LOG_ERROR(BSL_LS_SOC_SOCMEM,
   8289                           (BSL_META_U(unit,
   8290                                       "%s.%s failed(NAK)\n"),
   8291                            SOC_MEM_UFNAME(unit, mem),
   8292                            SOC_BLOCK_NAME(unit, copyno)));
   8293     #ifdef BCM_TRIUMPH2_SUPPORT
   8294                 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) ||
   8295                     SOC_IS_VALKYRIE2(unit)) {
   8296                     /* SCHAN nack */
   8297                     soc_triumph2_mem_nack(INT_TO_PTR(unit),
   8298                             INT_TO_PTR(start_addr), 0, 0, 0);
   8299                 }
   8300     #endif /* BCM_TRIUMPH2_SUPPORT */
   8301             } else {
   8302                 soc_timeout_t to;
   8303 
   8304                 LOG_ERROR(BSL_LS_SOC_SOCMEM,
   8305                           (BSL_META_U(unit,
   8306                                       "SlamDmaTimeOut:%s.%s %s timeout\n"),
   8307                            SOC_MEM_UFNAME(unit, mem),
   8308                            SOC_BLOCK_NAME(unit, copyno),
   8309                            soc->tslamDmaIntrEnb ? "interrupt" : "polling"));
   8310 
   8311     #if (defined  BCM_CMICM_SUPPORT)
   8312                 if(soc_feature(unit, soc_feature_cmicm)) {
   8313                     /* Abort Tslam DMA */
   8314                     cfg = soc_pci_read(unit, CMIC_CMCx_SLAM_DMA_CFG_OFFSET(cmc));
   8315                     soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_CFGr, &cfg, ENf, 0);
   8316                     soc_reg_field_set(unit, CMIC_CMC0_SLAM_DMA_CFGr, &cfg, ABORTf, 1);
   8317                     soc_pci_write(unit, CMIC_CMCx_SLAM_DMA_CFG_OFFSET(cmc), cfg);
   8318 
   8319                     /* Check the done bit to confirm */
   8320                     soc_timeout_init(&to, soc->tslamDmaTimeout, 10000);
   8321                     while (1) {
   8322                         cfg = soc_pci_read(unit, CMIC_CMCx_SLAM_DMA_STAT_OFFSET(cmc));
   8323                         if (soc_reg_field_get(unit, CMIC_CMC0_SLAM_DMA_STATr, cfg, DONEf)) {
   8324                             break;
   8325                         }
   8326                         if (soc_timeout_check(&to)) {
   8327                             LOG_ERROR(BSL_LS_SOC_SOCMEM,
   8328                                       (BSL_META_U(unit,
   8329                                                   "SlamDmaTimeOut:_soc_xgs3_mem_slam, Abort Failed\n")));
   8330                             break;
   8331                         }
   8332                     }
   8333                 } else
   8334     #endif
   8335                 {
   8336                     /* Abort Tslam DMA */
   8337                     READ_CMIC_SLAM_DMA_CFGr(unit, &cfg);
   8338                     soc_reg_field_set(unit, CMIC_SLAM_DMA_CFGr, &cfg, ENf, 0);
   8339                     soc_reg_field_set(unit, CMIC_SLAM_DMA_CFGr, &cfg, ABORTf, 1);
   8340                     soc_reg_field_set(unit, CMIC_SLAM_DMA_CFGr, &cfg, DONEf, 0);
   8341                     soc_reg_field_set(unit, CMIC_SLAM_DMA_CFGr, &cfg, ERRORf, 0);
   8342                     WRITE_CMIC_SLAM_DMA_CFGr(unit, cfg);
   8343 
   8344                     /* Check the done bit to confirm */
   8345                     soc_timeout_init(&to, soc->tslamDmaTimeout, 10000);
   8346                     while (1) {
   8347                         READ_CMIC_SLAM_DMA_CFGr(unit, &cfg);
   8348                         if (soc_reg_field_get(unit, CMIC_SLAM_DMA_CFGr, cfg, DONEf)) {
   8349                             break;
   8350                         }
   8351                         if (soc_timeout_check(&to)) {
   8352                             LOG_ERROR(BSL_LS_SOC_SOCMEM,
   8353                                       (BSL_META_U(unit,
   8354                                                   "SlamDmaTimeOut:_soc_xgs3_mem_slam, Abort Failed\n")));
   8355                             break;
   8356                         }
   8357                     }
   8358                 }
   8359             }
   8360         }
   8361 #if defined(BCM_TRIUMPH3_SUPPORT)
   8362     if (soc_feature(unit, soc_feature_esm_correction) &&
   8363           ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
   8364          (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
   8365         SOC_ESM_UNLOCK(unit);
   8366     }
   8367 #endif
   8368         TSLAM_DMA_UNLOCK(unit);
   8369     }
   8370 
   8371     return rv;
   8372 }
   8373 
   8374 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \
   8375     || defined(BCM_HURRICANE2_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)
   8376 
   8377 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   8378 STATIC void
   8379 _soc_mem_tcam_shift(int unit, uint32 *f1, uint32 *ipbm)
   8380 {
   8381     uint32 ipbm_105bit;
   8382     uint32 f1_49bit;
   8383     uint32 carrybit;
   8384     uint32 value;
   8385     uint32 next_carry;
   8386     int word;
   8387 
   8388     f1_49bit    = (f1[ 1 ] >> 17) & 0x1;
   8389     ipbm_105bit = (ipbm[ 3 ] >> 9 ) & 0x1;
   8390     /*clear ipbm 105th bit*/
   8391     ipbm[ 3 ] &= ((1 << 9) - 1);
   8392     /*clear f1 49 bit*/
   8393     f1[ 1 ] &= ((1 << 17) - 1);
   8394     /*update f1 49th bit*/
   8395     f1 [ 1 ] |= (ipbm_105bit << 17);
   8396 
   8397     carrybit = f1_49bit;
   8398     for ( word = 0; word < 4; word++ ) {
   8399         value = ipbm[ word ];
   8400         next_carry = (value & (1<<31)) ? 1 : 0 ;
   8401         ipbm[ word ] = (value << 1) | carrybit;
   8402         carrybit = next_carry;
   8403     }
   8404 }
   8405 
   8406 STATIC void
   8407 _soc_mem_fp_global_mask_tcam_shift(int unit, soc_mem_t mem, uint32 *xy_entry, 
   8408                                    int index_min, int index_max)
   8409 {
   8410     int index, count;
   8411     void *buf;
   8412     uint32 f1[SOC_MAX_MEM_FIELD_WORDS], ipbm[SOC_MAX_MEM_FIELD_WORDS];
   8413     
   8414     if (soc_feature(unit, soc_feature_tcam_shift) &&
   8415         ((mem == FP_GLOBAL_MASK_TCAMm) ||
   8416 	       (mem == FP_GLOBAL_MASK_TCAM_Xm) ||
   8417 	       (mem == FP_GLOBAL_MASK_TCAM_Ym))) {
   8418 	      count = 0;
   8419         for (index = index_min; index <= index_max; index++, count++) {
   8420             buf = soc_mem_table_idx_to_pointer(unit, mem, void *,
   8421                                                xy_entry, count);
   8422             sal_memset(f1, 0, sizeof(f1));
   8423             sal_memset(ipbm, 0, sizeof(ipbm));
   8424 
   8425             /*update key part*/
   8426             soc_mem_field_get(unit, mem, buf, F1f, f1);
   8427             soc_mem_field_get(unit, mem, buf, IPBMf, ipbm);
   8428 
   8429             _soc_mem_tcam_shift(unit, f1, ipbm);
   8430 
   8431             soc_mem_field_set(unit, mem, buf, F1f, f1);
   8432             soc_mem_field_set(unit, mem, buf, IPBMf, ipbm);
   8433 
   8434             /*update mask part*/
   8435             soc_mem_field_get(unit, mem, buf, F1_MASKf, f1);
   8436             soc_mem_field_get(unit, mem, buf, IPBM_MASKf, ipbm);
   8437 
   8438             _soc_mem_tcam_shift(unit, f1, ipbm);
   8439 
   8440             soc_mem_field_set(unit, mem, buf, F1_MASKf, f1);
   8441             soc_mem_field_set(unit, mem, buf, IPBM_MASKf, ipbm);
   8442         }
   8443     }
   8444 }
   8445 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   8446 
   8447 void
   8448 _soc_mem_tcam_xy_to_dm(int unit, soc_mem_t mem, int count,
   8449                        uint32 *xy_entry, uint32 *dm_entry)
   8450 {
   8451     uint32 key[SOC_MAX_MEM_FIELD_WORDS], mask[SOC_MAX_MEM_FIELD_WORDS];
   8452     uint32 converted_key, converted_mask;
   8453     uint32 xor_value;
   8454     soc_field_t key_field[4], mask_field[4];
   8455     int bit_length[4], word_length[4], field_count;
   8456     int index, i, word, data_words, data_bytes;
   8457     soc_pbmp_t pbmp;
   8458     int xy_lpt;
   8459 
   8460     xor_value = soc_feature(unit, soc_feature_xy_tcam_28nm) ? 0 : 0xffffffff;
   8461     xy_lpt = soc_feature(unit, soc_feature_xy_tcam_lpt) &&
   8462              (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_TCAM_ENCODING_LPT);
   8463 
   8464     if (mem == L3_DEFIPm || mem == L3_DEFIP_Xm || mem == L3_DEFIP_Ym ||
   8465         mem == L3_DEFIP_ONLYm || mem == L3_DEFIP_LEVEL1m ||
   8466         mem == L3_DEFIP_TCAM_LEVEL1m
   8467         ) {
   8468         if (SOC_MEM_FIELD_VALID(unit, mem, KEY0f)) {
   8469             key_field[0] = KEY0f;
   8470             key_field[1] = KEY1f;
   8471             mask_field[0] = MASK0f;
   8472             mask_field[1] = MASK1f;
   8473             field_count = 2;
   8474         } else {
   8475             key_field[0] = KEYf;
   8476             mask_field[0] = MASKf;
   8477             field_count = 1;
   8478         }
   8479 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT) || \
   8480     defined(BCM_TRIDENT2_SUPPORT)
   8481     } else if (mem == L3_DEFIP_PAIR_128m || mem == L3_DEFIP_PAIR_128_ONLYm ||
   8482                mem == L3_DEFIP_PAIR_LEVEL1m) {
   8483             if (SOC_IS_TOMAHAWK3(unit)) {
   8484                 key_field[0] = UPR_KEY0f;
   8485                 key_field[1] = UPR_KEY1f;
   8486                 key_field[2] = LWR_KEY0f;
   8487                 key_field[3] = LWR_KEY1f;
   8488                 mask_field[0] = UPR_MASK0f;
   8489                 mask_field[1] = UPR_MASK1f;
   8490                 mask_field[2] = LWR_MASK0f;
   8491                 mask_field[3] = LWR_MASK1f;
   8492                 field_count = 4;
   8493             } else {
   8494         key_field[0] = KEY0_UPRf;
   8495         key_field[1] = KEY1_UPRf;
   8496         key_field[2] = KEY0_LWRf;
   8497         key_field[3] = KEY1_LWRf;
   8498         mask_field[0] = MASK0_UPRf;
   8499         mask_field[1] = MASK1_UPRf;
   8500         mask_field[2] = MASK0_LWRf;
   8501         mask_field[3] = MASK1_LWRf;
   8502         field_count = 4;
   8503             }
   8504 #endif
   8505     } else {
   8506         if (SOC_MEM_FIELD_VALID(unit, mem, FULL_KEYf)) {
   8507             key_field[0] = FULL_KEYf;
   8508             mask_field[0] = FULL_MASKf;
   8509         } else {
   8510             key_field[0] = KEYf;
   8511             mask_field[0] = MASKf;
   8512         }
   8513         field_count = 1;
   8514 #ifdef BCM_SABER2_SUPPORT
   8515         if (SOC_IS_SABER2(unit) && (mem == FP_TCAMm) &&
   8516              soc_feature(unit, soc_feature_xy_tcam_28nm) &&
   8517              !SOC_MEM_FIELD_VALID(unit, mem, FULL_KEYf)) {
   8518 
   8519             /* Key field doesn't include F4 and double wide mode fields */
   8520             if (SOC_MEM_FIELD_VALID(unit, mem, F4f)) {
   8521                 key_field[field_count] = F4f;
   8522                 mask_field[field_count] = F4_MASKf;
   8523                 field_count += 1;
   8524             }
   8525 
   8526             if (SOC_MEM_FIELD_VALID(unit, mem, DOUBLE_WIDE_MODEf)) {
   8527                 key_field[field_count] = DOUBLE_WIDE_MODEf;
   8528                 mask_field[field_count] = DOUBLE_WIDE_MODE_MASKf;
   8529                 field_count += 1;
   8530             }
   8531         }
   8532 #endif
   8533     }
   8534     for (i = 0; i < field_count; i++) {
   8535         bit_length[i] = soc_mem_field_length(unit, mem, key_field[i]);
   8536         word_length[i] = (bit_length[i] + 31) / 32;
   8537     }
   8538     data_words = soc_mem_entry_words(unit, mem);
   8539     data_bytes = data_words * sizeof(uint32);
   8540     for (index = 0; index < count; index++) {
   8541         if (dm_entry != xy_entry) {
   8542             sal_memcpy(dm_entry, xy_entry, data_bytes);
   8543         }
   8544         for (i = 0; i < field_count; i++) {
   8545             soc_mem_field_get(unit, mem, xy_entry, key_field[i], key);
   8546             soc_mem_field_get(unit, mem, xy_entry, mask_field[i], mask);
   8547             for (word = 0; word < word_length[i]; word++) {
   8548                 /*
   8549                  * LPT -> XY
   8550                  * xy_x[1:0] = {(lpt_y[0] & lpt_x[0]), (lpt_y[1] & lpt_y[0])}
   8551                  * xy_y[1:0] = {(lpt_y[1] & lpt_x[1]), (lpt_x[1] & lpt_x[0])}
   8552                  */
   8553                 if (xy_lpt) {
   8554                     converted_key = (((key[word] & mask[word]) << 1) & 0xaaaaaaaa) |
   8555                                     ((mask[word] & (mask[word] >> 1)) & 0x55555555);
   8556                     converted_mask = ((key[word] & mask[word]) & 0xaaaaaaaa) |
   8557                                      ((key[word] & (key[word] >> 1)) & 0x55555555);
   8558                     key[word] = converted_key;
   8559                     mask[word] = converted_mask;
   8560                 }
   8561                 /*
   8562                  * 40nm:
   8563                  *    Encode: K0 = MASK & KEY
   8564                  *            K1 = ~MASK | KEY
   8565                  *    Decode: KEY = K0
   8566                  *            MASK = K0 | ~K1
   8567                  *              (encode)  (decode)
   8568                  *    KEY MASK   K0  K1   KEY MASK
   8569                  *    --------   ------   --------
   8570                  *     0   0     0   1     0   0
   8571                  *     1   0     0   1     0   0  =====> info loss
   8572                  *     0   1     0   0     0   1
   8573                  *     1   1     1   1     1   1
   8574                  * 28nm:
   8575                  *     Encode: K0 = MASK & KEY
   8576                  *             K1 = MASK & ~KEY
   8577                  *     Decode: KEY = K0
   8578                  *             MASK = K0 | K1
   8579                  *     KEY MASK   K0  K1   KEY MASK
   8580                  *     --------   ------   --------
   8581                  *      0   0     0   0     0   0
   8582                  *      1   0     0   0     0   0  =====> info loss
   8583                  *      0   1     0   1     0   1
   8584                  *      1   1     1   0     1   1
   8585                  * Notes:
   8586                  *     - Mask value of 1 means to compare against key
   8587                  *     - K0 is in KEY field of the entry
   8588                  *     - K1 is in MASK field of the entry
   8589                  */
   8590                 mask[word] = key[word] | (mask[word] ^ xor_value);
   8591             }
   8592             if ((bit_length[i] & 0x1f) != 0) {
   8593                 if (xy_lpt) {
   8594                     key[word - 1] &= (1 << (bit_length[i] & 0x1f)) - 1;
   8595                 }
   8596                 mask[word - 1] &= (1 << (bit_length[i] & 0x1f)) - 1;
   8597             }
   8598             if (xy_lpt) {
   8599                 soc_mem_field_set(unit, mem, dm_entry, key_field[i], key);
   8600             }
   8601             soc_mem_field_set(unit, mem, dm_entry, mask_field[i], mask);
   8602         }
   8603 
   8604         /* Filter out the bits that is not implemented in the hardware,
   8605          * hardware returns X=0 Y=0 which is D=0 M=1 after above conversion
   8606          * following code will force such bits to D=0 M=0 */
   8607         if (SOC_IS_TD_TT(unit) &&
   8608             (mem == FP_GLOBAL_MASK_TCAM_Xm ||
   8609              mem == FP_GLOBAL_MASK_TCAM_Ym)) {
   8610             soc_mem_pbmp_field_get(unit, mem, dm_entry, IPBM_MASKf, &pbmp);
   8611             if (mem == FP_GLOBAL_MASK_TCAM_Xm) {
   8612                 SOC_PBMP_AND(pbmp, PBMP_XPIPE(unit));
   8613             } else {
   8614                 SOC_PBMP_AND(pbmp, PBMP_YPIPE(unit));
   8615             }
   8616             soc_mem_pbmp_field_set(unit, mem, dm_entry, IPBM_MASKf, &pbmp);
   8617         }
   8618 
   8619         xy_entry += data_words;
   8620         dm_entry += data_words;
   8621     }
   8622 }
   8623 
   8624 void
   8625 _soc_mem_tcam_dm_to_xy(int unit, soc_mem_t mem, int count,
   8626                        uint32 *dm_entry, uint32 *xy_entry,
   8627                        uint32 *cache_entry)
   8628 {
   8629     uint32 key[SOC_MAX_MEM_FIELD_WORDS], mask[SOC_MAX_MEM_FIELD_WORDS];
   8630     uint32 xor_value;
   8631     uint32 converted_key, converted_mask;
   8632     soc_field_t key_field[4], mask_field[4];
   8633     int bit_length[4], word_length[4], field_count;
   8634     int index, i, word, data_words, data_bytes;
   8635     int no_trans = FALSE;
   8636     int xy_lpt;
   8637 
   8638     if (!soc_feature(unit, soc_feature_xy_tcam_direct)) {
   8639         /* Only clear the "don't care" key bits */
   8640         no_trans = TRUE;
   8641     }
   8642     xor_value = soc_feature(unit, soc_feature_xy_tcam_28nm) ? 0xffffffff : 0;
   8643     xy_lpt = soc_feature(unit, soc_feature_xy_tcam_lpt) &&
   8644              (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_TCAM_ENCODING_LPT);
   8645 
   8646     if (mem == L3_DEFIPm || mem == L3_DEFIP_Xm || mem == L3_DEFIP_Ym ||
   8647         mem == L3_DEFIP_ONLYm || mem == L3_DEFIP_LEVEL1m ||
   8648         mem == L3_DEFIP_TCAM_LEVEL1m
   8649         ) {
   8650         if (SOC_MEM_FIELD_VALID(unit, mem, KEY0f)) {
   8651             key_field[0] = KEY0f;
   8652             key_field[1] = KEY1f;
   8653             mask_field[0] = MASK0f;
   8654             mask_field[1] = MASK1f;
   8655             field_count = 2;
   8656         } else {
   8657             key_field[0] = KEYf;
   8658             mask_field[0] = MASKf;
   8659             field_count = 1;
   8660         }
   8661 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT) || \
   8662     defined(BCM_TRIDENT2_SUPPORT)
   8663     } else if (mem == L3_DEFIP_PAIR_128m || mem == L3_DEFIP_PAIR_128_ONLYm ||
   8664                mem == L3_DEFIP_PAIR_LEVEL1m) {
   8665             if (SOC_IS_TOMAHAWK3(unit)) {
   8666                 key_field[0] = UPR_KEY0f;
   8667                 key_field[1] = UPR_KEY1f;
   8668                 key_field[2] = LWR_KEY0f;
   8669                 key_field[3] = LWR_KEY1f;
   8670                 mask_field[0] = UPR_MASK0f;
   8671                 mask_field[1] = UPR_MASK1f;
   8672                 mask_field[2] = LWR_MASK0f;
   8673                 mask_field[3] = LWR_MASK1f;
   8674                 field_count = 4;
   8675             } else {
   8676         key_field[0] = KEY0_UPRf;
   8677         key_field[1] = KEY1_UPRf;
   8678         key_field[2] = KEY0_LWRf;
   8679         key_field[3] = KEY1_LWRf;
   8680         mask_field[0] = MASK0_UPRf;
   8681         mask_field[1] = MASK1_UPRf;
   8682         mask_field[2] = MASK0_LWRf;
   8683         mask_field[3] = MASK1_LWRf;
   8684         field_count = 4;
   8685             }
   8686 #endif
   8687     } else {
   8688         if (SOC_MEM_FIELD_VALID(unit, mem, FULL_KEYf)) {
   8689             key_field[0] = FULL_KEYf;
   8690             mask_field[0] = FULL_MASKf;
   8691         } else {
   8692             key_field[0] = KEYf;
   8693             mask_field[0] = MASKf;
   8694         }
   8695         field_count = 1;
   8696 #ifdef BCM_SABER2_SUPPORT
   8697         if (SOC_IS_SABER2(unit) && (mem == FP_TCAMm) &&
   8698              soc_feature(unit, soc_feature_xy_tcam_28nm) &&
   8699              !SOC_MEM_FIELD_VALID(unit, mem, FULL_KEYf)) {
   8700 
   8701             /* Key field doesn't include F4 and double wide mode fields */
   8702             if (SOC_MEM_FIELD_VALID(unit, mem, F4f)) {
   8703                 key_field[field_count] = F4f;
   8704                 mask_field[field_count] = F4_MASKf;
   8705                 field_count += 1;
   8706             }
   8707 
   8708             if (SOC_MEM_FIELD_VALID(unit, mem, DOUBLE_WIDE_MODEf)) {
   8709                 key_field[field_count] = DOUBLE_WIDE_MODEf;
   8710                 mask_field[field_count] = DOUBLE_WIDE_MODE_MASKf;
   8711                 field_count += 1;
   8712             }
   8713         }
   8714 #endif
   8715     }
   8716     for (i = 0; i < field_count; i++) {
   8717         bit_length[i] = soc_mem_field_length(unit, mem, key_field[i]);
   8718         word_length[i] = (bit_length[i] + 31) / 32;
   8719     }
   8720     data_words = soc_mem_entry_words(unit, mem);
   8721     data_bytes = data_words * sizeof(uint32);
   8722     for (index = 0; index < count; index++) {
   8723         if (xy_entry != dm_entry) {
   8724             sal_memcpy(xy_entry, dm_entry, data_bytes);
   8725         }
   8726         if (cache_entry) {
   8727             sal_memcpy(cache_entry, dm_entry, data_bytes);
   8728         }
   8729         for (i = 0; i < field_count; i++) {
   8730             soc_mem_field_get(unit, mem, dm_entry, key_field[i], key);
   8731             soc_mem_field_get(unit, mem, dm_entry, mask_field[i], mask);
   8732             if (cache_entry) {
   8733                 for (word = 0; word < word_length[i]; word++) {
   8734                     key[word] &= mask[word];
   8735                 }
   8736                 soc_mem_field_set(unit, mem, cache_entry, key_field[i], key);
   8737             }
   8738             for (word = 0; word < word_length[i]; word++) {
   8739                 /*
   8740                  * 40nm:
   8741                  *    Encode: K0 = MASK & KEY
   8742                  *            K1 = ~MASK | KEY
   8743                  *    Decode: KEY = K0
   8744                  *            MASK = K0 | ~K1
   8745                  *              (encode)  (decode)
   8746                  *    KEY MASK   K0  K1   KEY MASK
   8747                  *    --------   ------   --------
   8748                  *     0   0     0   1     0   0
   8749                  *     1   0     0   1     0   0  =====> info loss
   8750                  *     0   1     0   0     0   1
   8751                  *     1   1     1   1     1   1
   8752                  * 28nm:
   8753                  *     Encode: K0 = MASK & KEY
   8754                  *             K1 = MASK & ~KEY
   8755                  *     Decode: KEY = K0
   8756                  *             MASK = K0 | K1
   8757                  *     KEY MASK   K0  K1   KEY MASK
   8758                  *     --------   ------   --------
   8759                  *      0   0     0   0     0   0
   8760                  *      1   0     0   0     0   0  =====> info loss
   8761                  *      0   1     0   1     0   1
   8762                  *      1   1     1   0     1   1
   8763                  * Notes:
   8764                  *     - Mask value of 1 means to compare against key
   8765                  *     - K0 is in KEY field of the entry
   8766                  *     - K1 is in MASK field of the entry
   8767                  */
   8768                 converted_key = key[word] & mask[word];
   8769                 if (!no_trans) {
   8770                     converted_mask = (key[word] | ~mask[word]) ^ xor_value;
   8771                     mask[word] = converted_mask;
   8772                 }
   8773                 key[word] = converted_key;
   8774                 /*
   8775                  * XY -> LPT
   8776                  * lpt_x[1:0] = {(xy_y[1] | xy_y[0]), (xy_x[1] | xy_y[0])}
   8777                  * lpt_y[1:0] = {(xy_y[1] | xy_x[0]), (xy_x[1] | xy_x[0])}
   8778                  */
   8779                 if (xy_lpt) {
   8780                     converted_key = ((mask[word] | (mask[word] << 1)) & 0xaaaaaaaa) |
   8781                                     ((mask[word] | (key[word] >> 1)) & 0x55555555);
   8782                     converted_mask = ((mask[word] | (key[word] << 1)) & 0xaaaaaaaa) |
   8783                                      ((key[word] | (key[word] >> 1)) & 0x55555555);
   8784                     key[word] = converted_key;
   8785                     mask[word] = converted_mask;
   8786                 }
   8787             }
   8788             if ((bit_length[i] & 0x1f) != 0) {
   8789                 if (xy_lpt) {
   8790                     key[word - 1] &= (1 << (bit_length[i] & 0x1f)) - 1;
   8791                 }
   8792                 mask[word - 1] &= (1 << (bit_length[i] & 0x1f)) - 1;
   8793             }
   8794             soc_mem_field_set(unit, mem, xy_entry, key_field[i], key);
   8795             soc_mem_field_set(unit, mem, xy_entry, mask_field[i], mask);
   8796         }
   8797         dm_entry += data_words;
   8798         xy_entry += data_words;
   8799         if (cache_entry) {
   8800             cache_entry += data_words;
   8801         }
   8802     }
   8803 }
   8804 
   8805 STATIC void
   8806 _soc_mem_read_defip_index_map(int unit, soc_mem_t mem, int index, int *index2);
   8807 
   8808 STATIC int
   8809 _soc_mem_defip_index_is_invalid(int unit, soc_mem_t mem, int index);
   8810 
   8811 #define MAX_TCAM_PROTECT_RANGES 32
   8812 STATIC int
   8813 _soc_mem_tcam_entry_preserve(int unit, soc_mem_t mem, int copyno, int index,
   8814                              int count, void *entry, soc_mem_t *aggr_mem,
   8815                              void **buffer)
   8816 {
   8817     int rv = SOC_E_NONE;
   8818     int blk, entry_words, data_words, data_bytes, alloc_size, word_idx, i;
   8819     int num_tcam_protect_ranges;
   8820     int *index_min = NULL, *index_max = NULL, *split_count = NULL;
   8821     uint32 *read_buf = NULL, *entry_ptr;
   8822     int field_count, field_idx, idx, is_l3_defip = 0, wide = 0;
   8823     soc_field_t fields[4];
   8824     int incr;
   8825 
   8826     switch (mem) {
   8827      case FP_GLOBAL_MASK_TCAMm:
   8828      case FP_GLOBAL_MASK_TCAM_Xm:
   8829      case FP_GLOBAL_MASK_TCAM_Ym:
   8830      case FP_GM_FIELDSm:
   8831      case FP_TCAMm:
   8832      case FP_UDF_TCAMm:
   8833      case EFP_TCAMm:
   8834      case VFP_TCAMm:
   8835 #if defined BCM_TOMAHAWK_SUPPORT
   8836      case IFP_TCAMm:
   8837      case IFP_TCAM_PIPE0m:
   8838      case IFP_TCAM_PIPE1m:
   8839      case IFP_TCAM_PIPE2m:
   8840      case IFP_TCAM_PIPE3m:
   8841      case IFP_TCAM_WIDEm:
   8842      case IFP_TCAM_WIDE_PIPE0m:
   8843      case IFP_TCAM_WIDE_PIPE1m:
   8844      case IFP_TCAM_WIDE_PIPE2m:
   8845      case IFP_TCAM_WIDE_PIPE3m:
   8846      case FP_UDF_TCAM_PIPE0m:
   8847      case FP_UDF_TCAM_PIPE1m:
   8848      case FP_UDF_TCAM_PIPE2m:
   8849      case FP_UDF_TCAM_PIPE3m:
   8850      case IFP_LOGICAL_TABLE_SELECTm:
   8851      case IFP_LOGICAL_TABLE_SELECT_PIPE0m:
   8852      case IFP_LOGICAL_TABLE_SELECT_PIPE1m:
   8853      case IFP_LOGICAL_TABLE_SELECT_PIPE2m:
   8854      case IFP_LOGICAL_TABLE_SELECT_PIPE3m:
   8855      case IFP_LOGICAL_TABLE_SELECT_TCAM_ONLYm:
   8856      case IFP_LOGICAL_TABLE_SELECT_TCAM_ONLY_PIPE0m:
   8857      case IFP_LOGICAL_TABLE_SELECT_TCAM_ONLY_PIPE1m:
   8858      case IFP_LOGICAL_TABLE_SELECT_TCAM_ONLY_PIPE2m:
   8859      case IFP_LOGICAL_TABLE_SELECT_TCAM_ONLY_PIPE3m:
   8860      case EXACT_MATCH_LOGICAL_TABLE_SELECTm:
   8861      case EXACT_MATCH_LOGICAL_TABLE_SELECT_PIPE0m:
   8862      case EXACT_MATCH_LOGICAL_TABLE_SELECT_PIPE1m:
   8863      case EXACT_MATCH_LOGICAL_TABLE_SELECT_PIPE2m:
   8864      case EXACT_MATCH_LOGICAL_TABLE_SELECT_PIPE3m:
   8865      case EXACT_MATCH_LOGICAL_TABLE_SELECT_TCAM_ONLYm:
   8866      case EXACT_MATCH_LOGICAL_TABLE_SELECT_TCAM_ONLY_PIPE0m:
   8867      case EXACT_MATCH_LOGICAL_TABLE_SELECT_TCAM_ONLY_PIPE1m:
   8868      case EXACT_MATCH_LOGICAL_TABLE_SELECT_TCAM_ONLY_PIPE2m:
   8869      case EXACT_MATCH_LOGICAL_TABLE_SELECT_TCAM_ONLY_PIPE3m:
   8870 #endif /* BCM_TOMAHAWK_SUPPORT */
   8871         return SOC_E_NONE;
   8872     case CPU_COS_MAP_ONLYm:
   8873         *aggr_mem = CPU_COS_MAPm;
   8874         break;
   8875     case L2_USER_ENTRY_ONLYm:
   8876         *aggr_mem = L2_USER_ENTRYm;
   8877         break;
   8878     case L3_DEFIP_128_ONLYm:
   8879         *aggr_mem = L3_DEFIP_128m; /* will miss hit bit from one pipe */
   8880         break;
   8881 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT)
   8882     case L3_DEFIP_PAIR_128_ONLYm:
   8883         *aggr_mem = L3_DEFIP_PAIR_128m; /* will miss hit bit from one pipe */
   8884         break;
   8885 #endif
   8886     case L3_DEFIP_ONLYm:
   8887         *aggr_mem = L3_DEFIPm; /* will miss hit bit from one pipe */
   8888         break;
   8889     case MY_STATION_TCAM_ENTRY_ONLYm:
   8890         *aggr_mem = MY_STATION_TCAMm;
   8891         break;
   8892     case VLAN_SUBNET_ONLYm:
   8893         *aggr_mem = VLAN_SUBNETm;
   8894         break;
   8895     default:
   8896         *aggr_mem = mem;
   8897         break;
   8898     }
   8899 
   8900     if (*aggr_mem != mem && count > 1) {
   8901         /* Can't support DMA multiple entries on tcam only table */
   8902         return SOC_E_NONE;
   8903     }
   8904 
   8905     if (copyno == COPYNO_ALL) {
   8906         SOC_MEM_BLOCK_ITER(unit, *aggr_mem, blk) {
   8907             copyno = blk;
   8908             break;
   8909         }
   8910     }
   8911 
   8912     /* Check if any valid entry will be overwritten */
   8913     if (SOC_MEM_FIELD_VALID(unit, mem, VALIDf)) {
   8914         fields[0] = VALIDf;
   8915         field_count = 1;
   8916     } else if (SOC_MEM_FIELD_VALID(unit, mem, VALID0f)) {
   8917         fields[0] = VALID0f;
   8918         fields[1] = VALID1f;
   8919         field_count = 2;
   8920     } else if (SOC_MEM_FIELD_VALID(unit, mem, VALID0_LWRf)) {
   8921         fields[0] = VALID0_LWRf;
   8922         fields[1] = VALID1_LWRf;
   8923         fields[2] = VALID0_UPRf;
   8924         fields[3] = VALID1_UPRf;
   8925         field_count = 4;
   8926     } else {
   8927         field_count = 0;
   8928     }
   8929 
   8930     num_tcam_protect_ranges = (SOC_CONTROL(unit)->l3_defip_max_tcams);
   8931 
   8932     alloc_size = MAX_TCAM_PROTECT_RANGES * sizeof(int);
   8933     index_min =   (int *)sal_alloc(alloc_size, "index_min buffer");
   8934     index_max =   (int *)sal_alloc(alloc_size, "index_max buffer");
   8935     split_count = (int *)sal_alloc(alloc_size, "split_count buffer");
   8936     read_buf = (uint32 *)sal_alloc(SOC_MAX_MEM_WORDS * sizeof(uint32),
   8937                                    "read buffer");
   8938     if (NULL == index_min || NULL == index_max ||
   8939         NULL == split_count || NULL == read_buf) {
   8940         rv = SOC_E_MEMORY;
   8941         goto cleanup;
   8942     }
   8943 
   8944     sal_memset(index_min, -1, alloc_size);
   8945     sal_memset(index_max, -1, alloc_size);
   8946     sal_memset(split_count, 0, alloc_size);
   8947     data_words = soc_mem_entry_words(unit, *aggr_mem);
   8948     data_bytes = data_words * sizeof(uint32);
   8949     if (mem == L3_DEFIPm || mem == L3_DEFIP_LEVEL1m || mem == L3_DEFIP_ONLYm) {
   8950         is_l3_defip = 1;
   8951     }
   8952 
   8953 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT)
   8954     if (mem == L3_DEFIP_PAIR_128m || mem == L3_DEFIP_PAIR_LEVEL1m ||
   8955         mem == L3_DEFIP_PAIR_128_ONLYm) {
   8956         is_l3_defip = 1;
   8957         wide = 1;
   8958     }
   8959 #endif
   8960     incr = soc_mem_index_count(unit, mem) / (num_tcam_protect_ranges >> wide);
   8961     for (i = 0; i < count; i++) {
   8962         if (is_l3_defip) {
   8963             idx = (index + i) / incr;
   8964         } else {
   8965             idx = 0;
   8966             split_count[idx] = count;
   8967             index_min[idx] = index;
   8968             index_max[idx] = soc_mem_index_max(unit, *aggr_mem);
   8969             break;
   8970         }
   8971         if (idx >= (num_tcam_protect_ranges >> wide)) {
   8972             rv = SOC_E_INTERNAL;
   8973             goto cleanup;
   8974         }
   8975 
   8976         split_count[idx]++;
   8977 
   8978         if (index_min[idx] != -1) {
   8979             continue;
   8980         }
   8981 
   8982         index_min[idx] = index + i;
   8983         index_max[idx] = (idx + 1) * incr - 1;
   8984 
   8985         _soc_mem_read_defip_index_map(unit, mem, index_min[idx], &index_min[idx]);
   8986         _soc_mem_read_defip_index_map(unit, mem, index_max[idx], &index_max[idx]);
   8987     }
   8988 
   8989     entry_words = soc_mem_entry_words(unit, mem);
   8990     entry_ptr = entry;
   8991     for (idx = 0; idx < num_tcam_protect_ranges; idx++) {
   8992         if (index_min[idx] == -1) {
   8993             continue;
   8994         }
   8995 
   8996         alloc_size = (index_max[idx] - index_min[idx] + 1) * data_bytes;
   8997         buffer[idx] = soc_cm_salloc(unit, alloc_size + data_bytes, "shift buffer");
   8998         if (buffer[idx] == NULL) {
   8999             rv = SOC_E_MEMORY;
   9000             goto cleanup;
   9001         }
   9002 
   9003         /* After split, l3_defip tcam tables are good to use dma */
   9004 #ifdef BCM_SBUSDMA_SUPPORT
   9005         if (soc_feature(unit, soc_feature_sbusdma)) {
   9006             rv = _soc_mem_sbusdma_read(unit, *aggr_mem, copyno, index_min[idx],
   9007                                        index_max[idx], 0, buffer[idx]);
   9008         } else
   9009 #endif
   9010         {
   9011             rv = _soc_xgs3_mem_dma(unit, *aggr_mem, 0, copyno, index_min[idx],
   9012                                    index_max[idx], 0, buffer[idx]);
   9013         }
   9014         if (SOC_FAILURE(rv)) {
   9015             goto cleanup;
   9016         }
   9017 
   9018         /* Zero the last entry */
   9019         _soc_mem_tcam_dm_to_xy(unit, *aggr_mem, 1,
   9020                                soc_mem_entry_null(unit, *aggr_mem),
   9021                                &((uint32 *)buffer[idx])
   9022                                [alloc_size / sizeof(uint32)], NULL);
   9023 
   9024         for (i = 0; i < split_count[idx]; i++) {
   9025             /* Get the original entry */
   9026             sal_memcpy(read_buf, ((uint32 *)buffer[idx]) + (data_words * i),
   9027                        WORDS2BYTES(entry_words));
   9028 
   9029             /* Bit-wise 'and' the original entry with new entry */
   9030             for (word_idx = 0; word_idx < entry_words; word_idx++) {
   9031                 read_buf[word_idx] &= entry_ptr[word_idx];
   9032             }
   9033             /* Find if original and new entry are both valid */
   9034             for (field_idx = 0; field_idx < field_count; field_idx++) {
   9035                 if (soc_mem_field32_get(unit, *aggr_mem, read_buf,
   9036                                         fields[field_idx])) {
   9037                     break;
   9038                 }
   9039             }
   9040             if (field_idx != field_count) {
   9041                 break;
   9042             }
   9043             entry_ptr += entry_words;
   9044         }
   9045         if (i == split_count[idx]) {
   9046             /* don't need to preserve entry */
   9047             soc_cm_sfree(unit, buffer[idx]);
   9048             buffer[idx] = NULL;
   9049             continue;
   9050         }
   9051 
   9052 #ifdef BCM_SBUSDMA_SUPPORT
   9053         if (soc_feature(unit, soc_feature_sbusdma)) {
   9054             rv = _soc_mem_sbusdma_write(unit, *aggr_mem, copyno, index_max[idx] + 1,
   9055                                         index_min[idx] + 1, buffer[idx], FALSE, -1);
   9056         } else
   9057 #endif
   9058         {
   9059             rv = _soc_xgs3_mem_slam(unit, 0, *aggr_mem, 0, copyno, index_max[idx] + 1,
   9060                                     index_min[idx] + 1, buffer[idx]);
   9061         }
   9062 
   9063         if (SOC_FAILURE(rv)) {
   9064             goto cleanup;
   9065         }
   9066 
   9067     }
   9068 
   9069     rv =  SOC_E_NONE;
   9070 
   9071 cleanup:
   9072     if (SOC_FAILURE(rv)) {
   9073     for (idx = 0; idx < num_tcam_protect_ranges; idx++) {
   9074         if (buffer[idx]) {
   9075             soc_cm_sfree(unit, buffer[idx]);
   9076             buffer[idx] = NULL;
   9077         }
   9078     }
   9079     }
   9080     if (index_min) {
   9081         sal_free(index_min);
   9082         index_min = NULL;
   9083     }
   9084     if (index_max) {
   9085         sal_free(index_max);
   9086         index_max = NULL;
   9087     }
   9088     if (split_count) {
   9089         sal_free(split_count);
   9090         split_count = NULL;
   9091     }
   9092     if (read_buf) {
   9093         sal_free(read_buf);
   9094         read_buf = NULL;
   9095     }
   9096     return rv;
   9097 }
   9098 
   9099 STATIC int
   9100 _soc_mem_tcam_entry_restore(int unit, soc_mem_t mem, int copyno, int index,
   9101                             int count, void **buffer)
   9102 {
   9103     int rv, rv2 = SOC_E_NONE;
   9104     int blk, data_words;
   9105     uint32 *buf_ptr;
   9106     int num_tcam_protect_ranges;
   9107     int index_min[MAX_TCAM_PROTECT_RANGES], index_max[MAX_TCAM_PROTECT_RANGES];
   9108     int split_count[MAX_TCAM_PROTECT_RANGES];
   9109     int i, idx, is_l3_defip = 0, wide = 0, incr;
   9110 
   9111     num_tcam_protect_ranges = (SOC_CONTROL(unit)->l3_defip_max_tcams);
   9112 
   9113     for (idx = 0; idx < num_tcam_protect_ranges; idx++) {
   9114         if (buffer[idx]) {
   9115             break;
   9116         }
   9117     }
   9118     if (idx == num_tcam_protect_ranges) {
   9119         return SOC_E_NONE;
   9120     }
   9121 
   9122     if (copyno == COPYNO_ALL) {
   9123         SOC_MEM_BLOCK_ITER(unit, mem, blk) {
   9124             copyno = blk;
   9125             break;
   9126         }
   9127     }
   9128 
   9129     data_words = soc_mem_entry_words(unit, mem);
   9130     sal_memset(index_min, -1, sizeof(index_min));
   9131     sal_memset(index_max, -1, sizeof(index_max));
   9132     sal_memset(split_count, 0, sizeof(split_count));
   9133 
   9134     if (mem == L3_DEFIPm || mem == L3_DEFIP_LEVEL1m || mem == L3_DEFIP_ONLYm) {
   9135         is_l3_defip = 1;
   9136     }
   9137 
   9138 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT)
   9139     if (mem == L3_DEFIP_PAIR_128m || mem == L3_DEFIP_PAIR_LEVEL1m ||
   9140         mem == L3_DEFIP_PAIR_128_ONLYm) {
   9141         is_l3_defip = 1;
   9142         wide = 1;
   9143     }
   9144 #endif
   9145 
   9146     incr = soc_mem_index_count(unit, mem) / (num_tcam_protect_ranges >> wide);
   9147     for (i = 0; i < count; i++) {
   9148         if (is_l3_defip) {
   9149             idx = (index + i) / incr;
   9150         } else {
   9151             idx = 0;
   9152             split_count[idx] = count;
   9153             index_min[idx] = index;
   9154             index_max[idx] = soc_mem_index_max(unit, mem);
   9155             break;
   9156         }
   9157         if (idx >= (num_tcam_protect_ranges >> wide)) {
   9158             return SOC_E_INTERNAL;
   9159         }
   9160 
   9161         split_count[idx]++;
   9162 
   9163         if (index_min[idx] != -1) {
   9164             continue;
   9165         }
   9166 
   9167         index_min[idx] = index + i;
   9168         index_max[idx] = (idx + 1) * incr - 1;
   9169 
   9170         _soc_mem_read_defip_index_map(unit, mem, index_min[idx], &index_min[idx]);
   9171         _soc_mem_read_defip_index_map(unit, mem, index_max[idx], &index_max[idx]);
   9172     }
   9173 
   9174     for (idx = 0; idx < num_tcam_protect_ranges; idx++) {
   9175         if (index_min[idx] == -1) {
   9176             continue;
   9177         }
   9178         if (buffer[idx] == NULL) {
   9179             continue;
   9180         }
   9181         buf_ptr = &((uint32 *)buffer[idx])[split_count[idx] * data_words];
   9182 
   9183 #ifdef BCM_SBUSDMA_SUPPORT
   9184         if (soc_feature(unit, soc_feature_sbusdma)) {
   9185             /* coverity[negative_returns] */
   9186             rv = _soc_mem_sbusdma_write(unit, mem, copyno, index_min[idx] + split_count[idx],
   9187                                         index_max[idx] + 1, buf_ptr, FALSE, -1);
   9188         } else
   9189 #endif
   9190         {
   9191             /* coverity[negative_returns] */
   9192             rv = _soc_xgs3_mem_slam(unit, 0, mem, 0, copyno, index_min[idx] + split_count[idx],
   9193                                     index_max[idx] + 1, buf_ptr);
   9194         }
   9195         LOG_INFO(BSL_LS_SOC_SOCMEM,
   9196                  (BSL_META_U(unit,
   9197                              "Restore mem:%d from min+count:%-5d+%-2d to max:%-5d\n"),
   9198                   mem,index_min[idx], split_count[idx], index_max[idx]));
   9199         soc_cm_sfree(unit, buffer[idx]);
   9200         if (rv < 0) { /* Don't stop if rv < 0, but record rv. */
   9201             rv2 = rv;
   9202         }
   9203     }
   9204 
   9205     return rv2;
   9206 }
   9207 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */
   9208 
   9209 /*
   9210  * Function:
   9211  *     _soc_mem_dma_read
   9212  * Purpose:
   9213  *     DMA acceleration for soc_mem_read_range()
   9214  *     With multiple CMC/channel support
   9215  * Parameters:
   9216  *     buffer -- must be pointer to sufficiently large
   9217  *               DMA-able block of memory
   9218  */
   9219 STATIC int
   9220 _soc_mem_dma_read(int unit, soc_mem_t mem, unsigned array_index, int copyno,
   9221                   int index_min, int index_max, uint32 ser_flags,
   9222                   void *buffer, int vchan)
   9223 {
   9224     /* Remove assertions from here, because they are checked in calling
   9225      * functions or intentionally excepted for SER correction
   9226      * and Warm Boot.
   9227      */
   9228 
   9229 #if defined BCM_DNX_SUPPORT && defined DNX_EMULATION_1_CORE
   9230     if (SOC_IS_JERICHO_2_ONLY(unit) && soc_sand_is_emulation_system(unit) && _soc_jr2_is_2nd_core(unit, mem, copyno)) {
   9231         /* for JR2 emulator, read from the first instance if the instance does not exist in emulation */
   9232         copyno = SOC_MEM_BLOCK_MIN(unit, mem);
   9233     }
   9234 #endif
   9235 
   9236 #ifdef BCM_SBUSDMA_SUPPORT
   9237     if (soc_feature(unit, soc_feature_sbusdma)) {
   9238         SOC_IF_ERROR_RETURN
   9239             (_soc_mem_array_sbusdma_read(unit, mem, array_index,
   9240                                          copyno, index_min, index_max,
   9241                                          ser_flags, buffer, vchan));
   9242     } else
   9243 #endif
   9244     {
   9245         SOC_IF_ERROR_RETURN
   9246             (_soc_xgs3_mem_dma(unit, mem, array_index, copyno, index_min,
   9247                                index_max, ser_flags, buffer));
   9248     }
   9249 
   9250     if (0 != (ser_flags & _SOC_SER_FLAG_XY_READ)) {
   9251         /* SER memscan logic must have the raw entries */
   9252         return SOC_E_NONE;
   9253     }
   9254 
   9255 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \
   9256     || defined(BCM_HURRICANE2_SUPPORT)
   9257     if (soc_feature(unit, soc_feature_xy_tcam_direct) &&
   9258         (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) &&
   9259         (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM))) {
   9260 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   9261         _soc_mem_fp_global_mask_tcam_shift(unit, mem, buffer, index_min, index_max);
   9262 #endif
   9263         _soc_mem_tcam_xy_to_dm(unit, mem, index_max - index_min + 1,
   9264                                buffer, buffer);
   9265     }
   9266 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */
   9267 
   9268     return SOC_E_NONE;
   9269 }
   9270 
   9271 /*
   9272  * Function:
   9273  *     _soc_mem_dma_write
   9274  * Purpose:
   9275  *     DMA acceleration for soc_mem_write_range()
   9276  * Parameters:
   9277  *     buffer -- must be pointer to sufficiently large
   9278  *               DMA-able block of memory
   9279  *     index_begin <= index_end - Forward direction
   9280  *     index_begin >  index_end - Reverse direction
   9281  */
   9282 STATIC int
   9283 _soc_mem_dma_write(int unit, uint32 flags, soc_mem_t mem, unsigned array_index, int copyno,
   9284                    int index_begin, int index_end, void *buffer, void *cache_buffer,
   9285                    int vchan)
   9286 {
   9287     int           rv;
   9288     void          *buffer_ptr;
   9289 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \
   9290     || defined(BCM_HURRICANE2_SUPPORT)
   9291     int           count, alloc_size;
   9292     soc_mem_t     aggr_mem = INVALIDm;
   9293     void          *shift_buffer[MAX_TCAM_PROTECT_RANGES] = {NULL};
   9294 #endif
   9295 
   9296     if (SOC_HW_ACCESS_DISABLE(unit)) {
   9297         return SOC_E_NONE;
   9298     }
   9299 
   9300     SOC_MEM_ALIAS_TO_ORIG(unit,mem);
   9301 
   9302 #if defined BCM_DNX_SUPPORT && defined DNX_EMULATION_1_CORE
   9303     if (SOC_IS_JERICHO_2_ONLY(unit) && soc_sand_is_emulation_system(unit) && _soc_jr2_is_2nd_core(unit, mem, copyno)) {
   9304         LOG_WARN(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, "_soc_mem_dma_write: mem instance %s.%s not in emulation, ignoring write\n"),
   9305                  SOC_MEM_NAME(unit,mem), SOC_BLOCK_NAME(unit, copyno)));
   9306             return SOC_E_NONE;
   9307     }
   9308 #endif
   9309     assert(SOC_MEM_BLOCK_VALID(unit, mem, copyno));
   9310 
   9311 #ifndef BCM_WARM_BOOT_SUPPORT
   9312     assert(soc_mem_index_valid(unit, mem, index_begin));
   9313     assert(soc_mem_index_valid(unit, mem, index_end));
   9314 #endif
   9315 
   9316 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \
   9317     || defined(BCM_HURRICANE2_SUPPORT)
   9318     if (soc_feature(unit, soc_feature_xy_tcam) &&
   9319         (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) &&
   9320         (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM))) {
   9321         if (index_begin > index_end) {
   9322             count = index_begin - index_end + 1;
   9323         } else {
   9324             count = index_end - index_begin + 1;
   9325         }
   9326         alloc_size = count * soc_mem_entry_words(unit, mem) * sizeof(uint32);
   9327         buffer_ptr = soc_cm_salloc(unit, alloc_size, "converted buffer");
   9328         if (buffer_ptr == NULL) {
   9329             return SOC_E_MEMORY;
   9330         }
   9331         _soc_mem_tcam_dm_to_xy(unit, mem, count, buffer, buffer_ptr,
   9332                                cache_buffer);
   9333 
   9334         if (index_begin <= index_end &&
   9335             SOC_CONTROL(unit)->tcam_protect_write) {
   9336             rv = _soc_mem_tcam_entry_preserve(unit, mem, copyno, index_begin,
   9337                                               count, buffer_ptr, &aggr_mem,
   9338                                               shift_buffer);
   9339             if (SOC_FAILURE(rv)) {
   9340                 soc_cm_sfree(unit, buffer_ptr);
   9341                 return rv;
   9342             }
   9343         }
   9344     } else
   9345 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */
   9346     {
   9347         buffer_ptr = buffer;
   9348     }
   9349 
   9350 #ifdef BCM_SBUSDMA_SUPPORT
   9351     if (soc_feature(unit, soc_feature_sbusdma)) {
   9352         rv = _soc_mem_array_sbusdma_write(unit, flags, mem, array_index,
   9353                                           array_index, copyno, index_begin,
   9354                                           index_end, buffer_ptr, FALSE, -1,
   9355                                           vchan);
   9356     } else
   9357 #endif
   9358     {
   9359         rv = _soc_xgs3_mem_slam(unit, flags, mem, array_index, copyno, index_begin,
   9360                                 index_end, buffer_ptr);
   9361     }
   9362 
   9363     if (SOC_E_FAIL == rv &&
   9364         soc_feature(unit, soc_feature_efp_meter_table_write_ignore_nack)) {
   9365         if ((mem == EFP_METER_TABLEm ||
   9366              mem == EFP_METER_TABLE_PIPE0m ||
   9367              mem == EFP_METER_TABLE_PIPE1m ||
   9368              mem == EFP_METER_TABLE_PIPE2m ||
   9369              mem == EFP_METER_TABLE_PIPE3m ||
   9370              mem == EFP_METER_TABLE_Xm ||
   9371              mem == EFP_METER_TABLE_Ym)) {
   9372             /*
   9373              * Ignore the unexpected NACK during writing to EFP_METER_TABLExxx
   9374              * since the error is not in the writen indexes and the write op can go through
   9375              * successfully.
   9376              */
   9377             rv = SOC_E_NONE;
   9378         }
   9379     }
   9380 
   9381 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \
   9382     || defined(BCM_HURRICANE2_SUPPORT)
   9383     if (soc_feature(unit, soc_feature_xy_tcam) &&
   9384         (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) &&
   9385         (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM))) {
   9386 #ifdef INCLUDE_MEM_SCAN
   9387         if (NULL != cache_buffer) {
   9388             /* Update memscan TCAM cache if necessary */
   9389             soc_mem_scan_tcam_cache_update(unit, mem,
   9390                                            index_begin, index_end,
   9391                                            buffer_ptr);
   9392         }
   9393 #endif /* INCLUDE_MEM_SCAN */
   9394 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   9395 #ifdef BCM_WARM_BOOT_SUPPORT
   9396         if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2X(unit) ||
   9397             SOC_IS_TRIDENT(unit) || SOC_IS_TITAN(unit)) {
   9398             int blk;
   9399 
   9400             SOC_MEM_BLOCK_ITER(unit, mem, blk) {
   9401                 if (copyno != COPYNO_ALL && copyno != blk) {
   9402                     continue;
   9403                 }
   9404                 soc_mem_overlay_tcam_update(unit, mem, blk,
   9405                                             index_begin, index_end);
   9406             }
   9407         }
   9408 #endif
   9409 #endif
   9410         soc_cm_sfree(unit, buffer_ptr);
   9411         if (index_begin <= index_end &&
   9412             SOC_CONTROL(unit)->tcam_protect_write) {
   9413             SOC_IF_ERROR_RETURN
   9414                 (_soc_mem_tcam_entry_restore(unit, aggr_mem, copyno,
   9415                                              index_begin,
   9416                                              index_end - index_begin + 1,
   9417                                              shift_buffer));
   9418         }
   9419     }
   9420 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */
   9421 
   9422     return rv;
   9423 }
   9424 
   9425 
   9426 
   9427 
   9428 #if defined(BCM_FIREBOLT_SUPPORT)
   9429 /*
   9430  * Function:
   9431  *      _soc_xgs3_mem_clear_slam
   9432  * Purpose:
   9433  *    soc_mem_clear acceleration using table DMA write (slam)
   9434  */
   9435 STATIC int
   9436 _soc_xgs3_mem_clear_slam(int unit, soc_mem_t mem,
   9437                          int copyno, void *null_entry)
   9438 {
   9439     int       rv, chunk_size, chunk_entries, mem_size, entry_words;
   9440     int       index, index_end, index_min, index_max;
   9441     uint32    *buf;
   9442 
   9443     if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)) {
   9444         return SOC_E_NONE;
   9445     }
   9446 #ifdef BCM_SBUSDMA_SUPPORT
   9447     if (soc_feature(unit, soc_feature_sbusdma)) {
   9448         uint32 *null_ptr;
   9449 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \
   9450     || defined(BCM_HURRICANE2_SUPPORT)
   9451         uint32 null_buf[SOC_MAX_MEM_WORDS];
   9452         if (soc_feature(unit, soc_feature_xy_tcam) &&
   9453             (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) &&
   9454             (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM))) {
   9455             null_ptr = null_buf;
   9456             _soc_mem_tcam_dm_to_xy(unit, mem, 1, null_entry, null_ptr, NULL);
   9457         } else
   9458 #endif /* defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) */
   9459         {
   9460             null_ptr = null_entry;
   9461         }
   9462         return _soc_mem_sbusdma_clear(unit, mem, copyno, null_ptr);
   9463     }
   9464 #endif
   9465     chunk_size = SOC_MEM_CLEAR_CHUNK_SIZE_GET(unit);
   9466     index_min = soc_mem_index_min(unit, mem);
   9467     index_max = soc_mem_index_max(unit, mem);
   9468     entry_words = soc_mem_entry_words(unit, mem);
   9469     mem_size = (index_max - index_min + 1) * entry_words * 4;
   9470     if (mem_size < chunk_size) {
   9471         chunk_size = mem_size;
   9472     }
   9473 
   9474     buf = soc_cm_salloc(unit, chunk_size, "mem_clear_buf");
   9475     if (buf == NULL) {
   9476         return SOC_E_MEMORY;
   9477     }
   9478 
   9479     chunk_entries = chunk_size / (entry_words * 4);
   9480 
   9481     if (null_entry == _soc_mem_entry_null_zeroes) {
   9482         sal_memset(buf, 0, chunk_size);
   9483     } else {
   9484         for (index = 0; index < chunk_entries; index++) {
   9485             sal_memcpy(buf + (index * entry_words),
   9486                        null_entry, entry_words * 4);
   9487         }
   9488     }
   9489 
   9490     rv = SOC_E_NONE;
   9491     for (index = index_min; index <= index_max; index += chunk_entries) {
   9492         index_end = index + chunk_entries - 1;
   9493         if (index_end > index_max) {
   9494             index_end = index_max;
   9495         }
   9496 
   9497         rv = soc_mem_write_range(unit, mem, copyno, index, index_end, buf);
   9498         if (rv < 0) {
   9499             LOG_ERROR(BSL_LS_SOC_SOCMEM,
   9500                       (BSL_META_U(unit,
   9501                                   "soc_mem_write_range: "
   9502                                   "write %s.%s[%d-%d] failed: %s\n"),
   9503                        SOC_MEM_UFNAME(unit, mem),
   9504                        SOC_BLOCK_NAME(unit, copyno),
   9505                        index, index_end, soc_errmsg(rv)));
   9506             break;
   9507         }
   9508     }
   9509 
   9510     soc_cm_sfree(unit, buf);
   9511     return rv;
   9512 }
   9513 
   9514 /*
   9515  * Function:
   9516  *      _soc_xgs3_mem_clear_pipe
   9517  * Purpose:
   9518  *    soc_mem_clear acceleration using pipeline table clear logic.
   9519  *    Much faster than table slam.  Exists on XGS3.
   9520  */
   9521 STATIC int
   9522 _soc_xgs3_mem_clear_pipe(int unit, soc_mem_t mem, int blk, void *null_entry)
   9523 {
   9524     int rv, mementries, to_usec, to_rv;
   9525     uint32 hwreset1, hwreset2, membase, memoffset, memstage;
   9526     soc_timeout_t to;
   9527 #ifdef BCM_EXTND_SBUS_SUPPORT
   9528     uint32 memnum;
   9529 #endif /* BCM_EXTND_SBUS_SUPPORT */
   9530 
   9531 #ifdef BCM_XGS_SUPPORT
   9532     if (SOC_IS_XGS(unit)) {
   9533         if (!SOC_MEM_CLEAR_HW_ACC(unit)) {
   9534             return SOC_E_UNAVAIL;
   9535         }
   9536     }
   9537 #endif /* BCM_XGS_SUPPORT */
   9538     if (null_entry != _soc_mem_entry_null_zeroes) {
   9539         return SOC_E_UNAVAIL;
   9540     }
   9541 
   9542     /* Tomahawk cannot clear the vlan table with pipe for some reasons
   9543      * Use DMA clear for now
   9544      */
   9545     if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
   9546         switch (mem) {
   9547             case VLAN_TABm:
   9548             case VLAN_XLATEm:
   9549             case EGR_VLAN_XLATEm:
   9550 #ifdef BCM_TRIDENT3_SUPPORT
   9551             case VLAN_XLATE_1_SINGLEm:
   9552             case VLAN_XLATE_2_SINGLEm:
   9553             case VLAN_XLATE_1_DOUBLEm:
   9554             case VLAN_XLATE_2_DOUBLEm:
   9555             case EGR_VLAN_XLATE_1_SINGLEm:
   9556             case EGR_VLAN_XLATE_2_SINGLEm:
   9557             case EGR_VLAN_XLATE_1_DOUBLEm:
   9558             case EGR_VLAN_XLATE_2_DOUBLEm:
   9559 #endif
   9560             return SOC_E_UNAVAIL;
   9561         }
   9562     }
   9563 
   9564     if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) || SOC_HW_ACCESS_DISABLE(unit)) {
   9565         return SOC_E_NONE;
   9566     }
   9567     if (SAL_BOOT_PLISIM) {
   9568         if (SAL_BOOT_BCMSIM || SAL_BOOT_XGSSIM) {
   9569             if (!(SOC_IS_TRIUMPH3(unit) || SOC_IS_TD2_TT2(unit))) {
   9570                 /* h/w acceleration is not implemented in some models */
   9571                 return SOC_E_UNAVAIL;
   9572             }
   9573         } else {
   9574             return SOC_E_UNAVAIL;
   9575         }
   9576     }
   9577 
   9578     if (!SOC_REG_IS_VALID(unit, ING_HW_RESET_CONTROL_1r)) {
   9579         return SOC_E_UNAVAIL;
   9580     }
   9581 
   9582 
   9583 #ifdef BCM_TRIUMPH_SUPPORT
   9584     if (SOC_IS_TRIUMPH(unit) || SOC_IS_VALKYRIE(unit)) {
   9585         switch (mem) {
   9586         case ING_PW_TERM_COUNTERSm:
   9587         case EGR_IPFIX_SESSION_TABLEm:
   9588         case EGR_IPFIX_EXPORT_FIFOm:
   9589             return SOC_E_UNAVAIL;
   9590         default:
   9591             break;
   9592         }
   9593     }
   9594 #if defined(BCM_TRIUMPH2_SUPPORT)
   9595     else if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) ||
   9596              SOC_IS_VALKYRIE2(unit)) {
   9597         if (mem == LMEPm) {
   9598             return SOC_E_UNAVAIL;
   9599         }
   9600         if (soc_feature(unit, soc_feature_ser_parity)) {
   9601             SOC_IF_ERROR_RETURN
   9602                 (soc_triumph2_ser_mem_clear(unit, mem));
   9603         }
   9604     }
   9605 #endif /* BCM_TRIUMPH2_SUPPORT */
   9606 #if defined(BCM_ENDURO_SUPPORT)
   9607     else if (SOC_IS_ENDURO(unit)) {
   9608         if (mem == LMEPm || mem == LMEP_1m) {
   9609             return SOC_E_UNAVAIL;
   9610         }
   9611     }
   9612 #endif /* BCM_ENDURO_SUPPORT */
   9613 #if defined(BCM_TRIDENT_SUPPORT)
   9614     else if (SOC_IS_TRIDENT(unit) || SOC_IS_TITAN(unit)) {
   9615         if ((SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) ||
   9616             (SOC_MEM_INFO(unit, mem).index_max == 0)) {
   9617             return SOC_E_UNAVAIL;
   9618         }
   9619         switch (mem) {
   9620         case EGR_VLANm:
   9621             return SOC_E_UNAVAIL;
   9622         default:
   9623         break;
   9624         }
   9625     }
   9626 #endif /* BCM_TRIDENT_SUPPORT */
   9627 #ifdef BCM_TRIUMPH3_SUPPORT
   9628     else if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TD2_TT2(unit)) {
   9629         if ((SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) ||
   9630             (SOC_MEM_INFO(unit, mem).index_max == 0)) {
   9631             return SOC_E_UNAVAIL;
   9632         }
   9633         if (SOC_IS_TRIUMPH3(unit)) {
   9634             if (mem == EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm ||
   9635                 mem == ING_DVP_2_TABLEm) {
   9636                 return SOC_E_UNAVAIL;
   9637             }
   9638         }
   9639     }
   9640 #endif /* BCM_TRIUMPH3_SUPPORT */
   9641 #ifdef BCM_KATANA2_SUPPORT
   9642     else if (SOC_IS_KATANA2(unit)) {
   9643         switch(mem) {
   9644         /* WORK-AROUND:SDK-48233
   9645            KT2 SW WAR: IP HW Mem Reset does not reset
   9646            IARB_ING_PHYSICAL_PORT table  */
   9647         case IARB_ING_PHYSICAL_PORTm:
   9648             return SOC_E_UNAVAIL;
   9649         default:
   9650             break;
   9651         }
   9652         if (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) {
   9653             return SOC_E_UNAVAIL;
   9654         }
   9655     }
   9656 #endif /* BCM_KATANA2_SUPPORT */
   9657 #ifdef BCM_KATANA_SUPPORT
   9658     else if (SOC_IS_KATANA(unit)) {
   9659         if (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) {
   9660             return SOC_E_UNAVAIL;
   9661         }
   9662     }
   9663 #endif
   9664 #ifdef BCM_HURRICANE2_SUPPORT
   9665     else if (SOC_IS_HURRICANE2(unit)) {
   9666         switch(mem) {
   9667         case VLAN_SUBNETm:
   9668         case VLAN_SUBNET_ONLYm:
   9669             return SOC_E_UNAVAIL;
   9670         default:
   9671             break;
   9672         }
   9673 
   9674         if (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) {
   9675             SOC_IF_ERROR_RETURN
   9676                 (soc_hurricane2_ser_mem_clear(unit, mem));
   9677         }
   9678     }
   9679 #endif /* BCM_HURRICANE2_SUPPORT */
   9680 
   9681 #ifdef BCM_GREYHOUND_SUPPORT
   9682     else if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
   9683             SOC_IS_GREYHOUND2(unit)) {
   9684         if (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) {
   9685             SOC_IF_ERROR_RETURN
   9686                 (soc_greyhound_ser_mem_clear(unit, mem));
   9687         }
   9688     }
   9689 #endif /* BCM_GREYHOUND_SUPPORT */
   9690 
   9691 #ifdef BCM_SABER2_SUPPORT
   9692     if (SOC_IS_SABER2(unit)) {
   9693         if (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) {
   9694             SOC_IF_ERROR_RETURN
   9695                 (soc_saber2_ser_mem_clear(unit, mem));
   9696         }
   9697     }
   9698 #endif /* BCM_SABER2_SUPPORT */
   9699 
   9700 #endif /* BCM_TRIUMPH_SUPPORT */
   9701 
   9702     if (SAL_BOOT_SIMULATION) {
   9703         to_usec = 10000000;
   9704     } else {
   9705         to_usec = 50000;
   9706     }
   9707 #ifdef BCM_SHADOW_SUPPORT
   9708     if (SOC_IS_SHADOW(unit) && (mem == ING_VLAN_TAG_ACTION_PROFILEm)) {
   9709        return SOC_E_UNAVAIL;
   9710     }
   9711 
   9712     if (SOC_IS_SHADOW(unit)) {
   9713         /* Reset HW Reset Control */
   9714         SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_2r(unit, 0));
   9715         SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_1r(unit, 0));
   9716     }
   9717 #endif
   9718 
   9719     rv = SOC_E_NONE;
   9720     to_rv = SOC_E_NONE;
   9721     membase = SOC_MEM_BASE(unit, mem);
   9722     mementries = soc_mem_index_count(unit, mem);
   9723 #ifdef BCM_EXTND_SBUS_SUPPORT
   9724     memnum = 0;
   9725     if (soc_feature(unit, soc_feature_new_sbus_format)) {
   9726         if (SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_IPIPE) {
   9727             memnum = SOC_MEM_ADDR_NUM_EXTENDED(membase);
   9728             /* For KATANA2: ING_HW_RESET_CONTROL_1:: OFFSET
   9729              26-bit starting offset of table for memory.
   9730              This is {8-bit MEMSEL, 18-bit MEMIDX}
   9731              Believe below condition should be out of "if BLK_IPIPE" condition
   9732              */
   9733             if (SOC_IS_KATANA2(unit)) {
   9734                 memoffset = SOC_MEM_ADDR_OFFSET_EXTENDED(membase);
   9735             } else {
   9736                 memoffset = SOC_MEM_ADDR_OFFSET_EXTENDED_IPIPE(membase);
   9737             }
   9738         } else {
   9739             memoffset = SOC_MEM_ADDR_OFFSET_EXTENDED(membase);
   9740         }
   9741         memstage = SOC_MEM_ADDR_STAGE_EXTENDED(membase);
   9742     } else
   9743 #endif
   9744     {
   9745         memoffset = SOC_MEM_ADDR_OFFSET(membase);
   9746         memstage = SOC_MEM_ADDR_STAGE(membase);
   9747     }
   9748 
   9749     switch (SOC_BLOCK_TYPE(unit, blk)) {
   9750     case SOC_BLK_IPIPE:
   9751     case SOC_BLK_IPIPE_HI:
   9752         hwreset1 = 0;
   9753 #ifdef BCM_EXTND_SBUS_SUPPORT
   9754         if (soc_reg_field_valid(unit, ING_HW_RESET_CONTROL_1r,
   9755                                 MEMORY_NUMBERf)) {
   9756             soc_reg_field_set(unit, ING_HW_RESET_CONTROL_1r, &hwreset1,
   9757                   MEMORY_NUMBERf, memnum);
   9758         }
   9759 #endif
   9760 
   9761          soc_reg_field_set(unit, ING_HW_RESET_CONTROL_1r, &hwreset1,
   9762                    OFFSETf, memoffset);
   9763          soc_reg_field_set(unit, ING_HW_RESET_CONTROL_1r, &hwreset1,
   9764                    STAGE_NUMBERf, memstage);
   9765          hwreset2 = 0;
   9766          soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &hwreset2,
   9767                    COUNTf, mementries);
   9768          soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &hwreset2,
   9769                    VALIDf, 1);
   9770 
   9771          rv = WRITE_ING_HW_RESET_CONTROL_1r(unit, hwreset1);
   9772          if (rv < 0) {
   9773              break;
   9774          }
   9775          rv = WRITE_ING_HW_RESET_CONTROL_2r(unit, hwreset2);
   9776          if (rv < 0) {
   9777              break;
   9778          }
   9779 
   9780          soc_timeout_init(&to, to_usec, 100);
   9781          for (;;) {
   9782              rv = READ_ING_HW_RESET_CONTROL_2r(unit, &hwreset2);
   9783              if (rv < 0) {
   9784                  break;
   9785              }
   9786              if (soc_reg_field_get(unit, ING_HW_RESET_CONTROL_2r, hwreset2,
   9787                                    DONEf)) {
   9788                  break;
   9789              }
   9790              if (soc_timeout_check(&to)) {
   9791                  to_rv = SOC_E_TIMEOUT;
   9792                  break;
   9793              }
   9794          }
   9795         hwreset2 = 0;
   9796         if (soc_reg_field_valid(unit, ING_HW_RESET_CONTROL_2r, CMIC_REQ_ENABLEf)) {
   9797             soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &hwreset2,
   9798                               CMIC_REQ_ENABLEf, 1);
   9799         }
   9800         rv = WRITE_ING_HW_RESET_CONTROL_2r(unit, hwreset2);
   9801         if (rv < 0) {
   9802             break;
   9803         }
   9804         rv = WRITE_ING_HW_RESET_CONTROL_1r(unit, 0);
   9805         break;
   9806 
   9807     case SOC_BLK_EPIPE:
   9808     case SOC_BLK_EPIPE_HI:
   9809         hwreset1 = 0;
   9810         soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_0r, &hwreset1,
   9811                   START_ADDRESSf, memoffset);
   9812         soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_0r, &hwreset1,
   9813                   STAGE_NUMBERf, memstage);
   9814         hwreset2 = 0;
   9815         soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &hwreset2,
   9816                   COUNTf, mementries);
   9817         soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &hwreset2,
   9818                   VALIDf, 1);
   9819 
   9820         rv = WRITE_EGR_HW_RESET_CONTROL_0r(unit, hwreset1);
   9821         if (rv < 0) {
   9822             break;
   9823         }
   9824         rv = WRITE_EGR_HW_RESET_CONTROL_1r(unit, hwreset2);
   9825         if (rv < 0) {
   9826             break;
   9827         }
   9828 
   9829         soc_timeout_init(&to, to_usec, 100);
   9830         for (;;) {
   9831             rv = READ_EGR_HW_RESET_CONTROL_1r(unit, &hwreset2);
   9832             if (rv < 0) {
   9833                 break;
   9834             }
   9835             if (soc_reg_field_get(unit, EGR_HW_RESET_CONTROL_1r, hwreset2,
   9836                                   DONEf)) {
   9837                 break;
   9838             }
   9839             if (soc_timeout_check(&to)) {
   9840                 to_rv = SOC_E_TIMEOUT;
   9841                 break;
   9842             }
   9843         }
   9844 
   9845         rv = WRITE_EGR_HW_RESET_CONTROL_1r(unit, 0);
   9846         if (rv < 0) {
   9847             break;
   9848         }
   9849         rv = WRITE_EGR_HW_RESET_CONTROL_0r(unit, 0);
   9850         break;
   9851 
   9852     case SOC_BLK_ISM:
   9853         hwreset1 = 0;
   9854         soc_reg_field_set(unit, ISM_HW_RESET_CONTROL_0r, &hwreset1,
   9855                   START_ADDRESSf, memoffset);
   9856         soc_reg_field_set(unit, ISM_HW_RESET_CONTROL_0r, &hwreset1,
   9857                   TABLE_IDf, memstage);
   9858         hwreset2 = 0;
   9859         soc_reg_field_set(unit, ISM_HW_RESET_CONTROL_1r, &hwreset2,
   9860                   COUNTf, mementries);
   9861         soc_reg_field_set(unit, ISM_HW_RESET_CONTROL_1r, &hwreset2,
   9862                   VALIDf, 1);
   9863 
   9864         rv = WRITE_ISM_HW_RESET_CONTROL_0r(unit, hwreset1);
   9865         if (rv < 0) {
   9866             break;
   9867         }
   9868         rv = WRITE_ISM_HW_RESET_CONTROL_1r(unit, hwreset2);
   9869         if (rv < 0) {
   9870             break;
   9871         }
   9872 
   9873         soc_timeout_init(&to, to_usec, 100);
   9874         for (;;) {
   9875             rv = READ_ISM_HW_RESET_CONTROL_1r(unit, &hwreset2);
   9876             if (rv < 0) {
   9877                 break;
   9878             }
   9879             if (soc_reg_field_get(unit, ISM_HW_RESET_CONTROL_1r, hwreset2,
   9880                                   DONEf)) {
   9881                 break;
   9882             }
   9883             if (soc_timeout_check(&to)) {
   9884                 to_rv = SOC_E_TIMEOUT;
   9885                 break;
   9886             }
   9887         }
   9888 
   9889         rv = WRITE_ISM_HW_RESET_CONTROL_1r(unit, 0);
   9890         if (rv < 0) {
   9891             break;
   9892         }
   9893         rv = WRITE_ISM_HW_RESET_CONTROL_0r(unit, 0);
   9894         break;
   9895 
   9896     default:
   9897         rv = SOC_E_UNAVAIL;
   9898         break;
   9899     }
   9900 
   9901     return rv == SOC_E_NONE ? to_rv : rv;
   9902 }
   9903 #endif /* defined(BCM_FIREBOLT_SUPPORT) */
   9904 
   9905 #endif /* defined(BCM_XGS_SUPPORT) ... */
   9906 
   9907 /************************************************************************/
   9908 /* Routines for reading/writing all tables (except no write to ARL)    */
   9909 /************************************************************************/
   9910 
   9911 /*
   9912  * Function: _soc_mem_read_tcam_is_invalid
   9913  *
   9914  * Purpose: Called from within _soc_mem_read.  If the read is attempting to
   9915  *          read from a tcam that makes no sense, we return without reading.
   9916  *          This is for cases like when a tcam is set to 512 width but the read
   9917  *          is misconfigured to read only the 2nd 256 bytes instead of the full
   9918  *          record.
   9919  *
   9920  * Returns: TRUE if the read call should terminate and return no data
   9921  *          FALSE if the read seems to be valid (and not a no-op tcam read)
   9922  */
   9923 STATIC int
   9924 _soc_mem_read_tcam_is_invalid(int unit, soc_mem_t mem, int index)
   9925 {
   9926     if (soc_feature(unit, soc_feature_field_stage_ingress_256_half_slice)) {
   9927         if (mem == FP_GLOBAL_MASK_TCAMm ||  mem == FP_TCAMm) {
   9928             if ((index / 64) % 2) {
   9929                return TRUE;
   9930             }
   9931         }
   9932     }
   9933 
   9934 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   9935     if (soc_feature(unit, soc_feature_field_stage_quarter_slice)
   9936         && soc_feature(unit, soc_feature_field_quarter_slice_single_tcam)
   9937         && soc_feature(unit, soc_feature_field_ingress_two_slice_types)) {
   9938         if ((FP_TCAMm == mem) || (FP_GM_FIELDSm == mem)
   9939             || (FP_GLOBAL_MASK_TCAMm == mem)
   9940             || (FP_GLOBAL_MASK_TCAM_Xm == mem)
   9941             || (FP_GLOBAL_MASK_TCAM_Ym == mem)) {
   9942             if (index < (soc_mem_index_count(unit, mem) / 2)) {
   9943                 /* Slices of 2K entries. */
   9944                 if (((index / 1024) % 2) || ((index / 512) % 2)) {
   9945                     return (TRUE);
   9946                 }
   9947             } else {
   9948                 /* Slices of 1K entries. */
   9949                 if (((index / 512) % 2) || ((index / 256) % 2)) {
   9950                     return (TRUE);
   9951                 }
   9952             }
   9953         }
   9954     }
   9955 #endif /* !BCM_TRIDENT2PLUS_SUPPORT */
   9956 
   9957 #ifdef BCM_APACHE_SUPPORT
   9958     if (soc_feature(unit, soc_feature_field_stage_half_slice)
   9959         && soc_feature(unit, soc_feature_field_half_slice_single_tcam)
   9960         && soc_feature(unit, soc_feature_field_ingress_two_slice_types)) {
   9961         if ((FP_TCAMm == mem) || (FP_GM_FIELDSm == mem)
   9962             || (FP_GLOBAL_MASK_TCAMm == mem)
   9963             || (FP_GLOBAL_MASK_TCAM_Xm == mem)
   9964             || (FP_GLOBAL_MASK_TCAM_Ym == mem)) {
   9965             if (index < (soc_mem_index_count(unit, mem) / 2)) {
   9966                 /* Slices of 1K entries. */
   9967                 if ((index / 512) % 2) {
   9968                     return (TRUE);
   9969                 }
   9970             } else {
   9971                 /* Slices of 512 entries. */
   9972                 if ((index / 256) % 2) {
   9973                     return (TRUE);
   9974                 }
   9975             }
   9976         }
   9977     }
   9978 #endif /* !BCM_APACHE_SUPPORT */
   9979 #ifdef BCM_TOMAHAWK2_SUPPORT
   9980         if (soc_feature(unit, soc_feature_field_stage_half_slice)) {
   9981             if ((IFP_TCAMm == mem) ||
   9982                 (IFP_TCAM_PIPE0m == mem) ||(IFP_TCAM_PIPE1m == mem) ||
   9983                 (IFP_TCAM_PIPE2m == mem) || (IFP_TCAM_PIPE3m == mem)) {
   9984                 if ((index / 256) % 2) {
   9985                     return TRUE;
   9986                 } else {
   9987                   return FALSE;
   9988                 }
   9989             }
   9990             if ((IFP_TCAM_WIDEm == mem) ||
   9991                 (IFP_TCAM_WIDE_PIPE0m == mem) ||(IFP_TCAM_WIDE_PIPE1m == mem) ||
   9992                 (IFP_TCAM_WIDE_PIPE2m == mem) || (IFP_TCAM_WIDE_PIPE3m == mem)) {
   9993                 if ((index / 128) % 2) {
   9994                     return TRUE;
   9995                 } else {
   9996                   return FALSE;
   9997                 }
   9998             }
   9999         }
  10000         if (soc_feature(unit, soc_feature_field_stage_quarter_slice)) {
  10001             if ((IFP_TCAMm == mem) ||
  10002                 (IFP_TCAM_PIPE0m == mem) ||(IFP_TCAM_PIPE1m == mem) ||
  10003                 (IFP_TCAM_PIPE2m == mem) || (IFP_TCAM_PIPE3m == mem)) {
  10004                 if ((index / 128) % 4) {
  10005                     return TRUE;
  10006                 } else {
  10007                   return FALSE;
  10008                 }
  10009             }
  10010             if ((IFP_TCAM_WIDEm == mem) ||
  10011                 (IFP_TCAM_WIDE_PIPE0m == mem) ||(IFP_TCAM_WIDE_PIPE1m == mem) ||
  10012                 (IFP_TCAM_WIDE_PIPE2m == mem) || (IFP_TCAM_WIDE_PIPE3m == mem)) {
  10013                 if ((index / 64) % 4) {
  10014                     return TRUE;
  10015                 } else {
  10016                   return FALSE;
  10017                 }
  10018             }
  10019         }
  10020 
  10021 #endif /* BCM_TOMAHAWK2_SUPPORT*/
  10022     if (soc_feature(unit, soc_feature_field_ingress_two_slice_types)
  10023         && soc_feature(unit, soc_feature_field_stage_ingress_512_half_slice)){
  10024         if (mem == FP_GLOBAL_MASK_TCAMm ||  mem == FP_TCAMm) {
  10025             if (index < (soc_mem_index_count(unit, mem) / 2)) {
  10026                 if ((index / 256) % 2) {
  10027                     return TRUE;
  10028                 }
  10029             }
  10030         }
  10031     }
  10032 
  10033     if (soc_feature(unit, soc_feature_field_ingress_two_slice_types)
  10034         && soc_feature(unit, soc_feature_field_slices8)) {
  10035         if (mem == FP_GLOBAL_MASK_TCAMm ||  mem == FP_TCAMm) {
  10036             if (index >= (soc_mem_index_count(unit, mem) * 3 / 4)) {
  10037                 return TRUE;
  10038             }
  10039         }
  10040     }
  10041 
  10042     if (soc_feature(unit, soc_feature_field_stage_egress_256_half_slice)) {
  10043         if (mem == EFP_TCAMm) {
  10044             if ((index / 128) % 2) {
  10045                 return TRUE;
  10046             }
  10047         }
  10048     }
  10049 
  10050     if (soc_feature(unit, soc_feature_field_stage_egress_512_half_slice)) {
  10051         if (mem == EFP_TCAMm) {
  10052             if ((index / 256) % 2) {
  10053                 return TRUE;
  10054             }
  10055         }
  10056     }
  10057 
  10058 
  10059 
  10060     if (soc_feature(unit, soc_feature_field_stage_lookup_512_half_slice)) {
  10061         if (mem == VFP_TCAMm) {
  10062             if ((index / 128) % 2) {
  10063                 return TRUE;
  10064             }
  10065         }
  10066     }
  10067 
  10068     if (soc_feature(unit, soc_feature_field_stage_lookup_256_half_slice)) {
  10069         if (mem == VFP_TCAMm) {
  10070             if ((index / 64) % 2) {
  10071                 return TRUE;
  10072             }
  10073         }
  10074     }
  10075 
  10076     if (!(soc_feature(unit,
  10077                       soc_feature_field_stage_lookup_512_half_slice) ||
  10078           soc_feature(unit,
  10079                       soc_feature_field_stage_lookup_256_half_slice) ||
  10080           soc_feature(unit,
  10081                       soc_feature_field_stage_egress_256_half_slice) ||
  10082           soc_feature(unit,
  10083                       soc_feature_field_stage_ingress_256_half_slice))) {
  10084 
  10085         if (!soc_feature(unit, soc_feature_field_stage_quarter_slice)) {
  10086             if (mem == FP_GLOBAL_MASK_TCAMm || mem == FP_TCAMm) {
  10087                 /* Do not access h/w for tcam index mapping to the holes */
  10088                 if (soc_feature(unit, soc_feature_field_stage_half_slice)
  10089                     && (!soc_feature(unit, soc_feature_field_half_slice_single_tcam))) {
  10090                     if ((index/128) % 2) {
  10091                         return TRUE;
  10092                     }
  10093                 } else if (soc_feature(unit,
  10094                                        soc_feature_field_slice_size128)) {
  10095                     if ((index/64) % 2) {
  10096                         return TRUE;
  10097                     }
  10098                 }
  10099             } else if (mem == EFP_TCAMm) {
  10100                 /* Do not access h/w for tcam index mapping to the holes */
  10101                 if (soc_feature(unit, soc_feature_field_stage_half_slice)) {
  10102                     if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) ||
  10103                         SOC_IS_VALKYRIE2(unit))  {
  10104                         if ((index/128) % 2) {
  10105                             return TRUE;
  10106                         }
  10107                     }
  10108                 }
  10109             }
  10110         }
  10111     }
  10112 
  10113     if (soc_feature(unit, soc_feature_field_stage_quarter_slice)) {
  10114         /* Do not access h/w for tcam index mapping to the holes */
  10115         if (mem == EFP_TCAMm) {
  10116             if ((SOC_IS_TRIUMPH3(unit)) && ((index/128) % 2)) {
  10117                 return TRUE;
  10118             }
  10119         } else if (mem == FP_GLOBAL_MASK_TCAMm || mem == FP_TCAMm ||
  10120                    mem == VFP_TCAMm) {
  10121              if ((SOC_IS_TRIUMPH3(unit)) && (((index/128) % 2) ||
  10122                  ((index/64) % 2))) {
  10123                  return TRUE;
  10124              }
  10125         }
  10126     }
  10127 
  10128     return FALSE;
  10129 }
  10130 
  10131 /*
  10132  * Function: _soc_mem_read_tr3_tunnel_is_invalid
  10133  *
  10134  * Purpose: Called from within _soc_mem_read.  On Triumph3, if attempting to
  10135  *          read from certain RX/TX tunnels in the XLPORT/XWPORT at index
  10136  *          16 or above, return an indication that the read is invalid.
  10137  *
  10138  * Returns: TRUE if the read request is invalid and should return no data
  10139  *          FALSE if the read request seems okay and should continue on
  10140  */
  10141 STATIC int
  10142 _soc_mem_read_tr3_tunnel_is_invalid(int unit, soc_mem_t mem, int index, int copyno)
  10143 {
  10144 #if defined(BCM_TRIUMPH3_SUPPORT)
  10145     if (SOC_IS_TRIUMPH3(unit)) {
  10146         if (mem == PORT_EHG_RX_TUNNEL_DATAm || mem == PORT_EHG_RX_TUNNEL_MASKm ||
  10147             mem == PORT_EHG_TX_TUNNEL_DATAm) {
  10148             if ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_XLPORT) ||
  10149                 (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_XWPORT)) {
  10150                 if (index > 15) {
  10151                     return TRUE;
  10152                 }
  10153             }
  10154         }
  10155     }
  10156 #endif /* BCM_TRIUMPH3_SUPPORT */
  10157 
  10158     return FALSE;
  10159 }
  10160 
  10161 /*
  10162  * Function: _soc_mem_read_hercules
  10163  *
  10164  * Purpose: Called by _soc_mem_read.  If the unit is a hercules, redirect the
  10165  *          request to the hercules mem read handler.
  10166  *
  10167  * Returns: TRUE if the request was intercepted and handled by hercules
  10168  *          FALSE if the request should proceed normally
  10169  */
  10170 STATIC int
  10171 _soc_mem_read_hercules(int unit, soc_mem_t mem, int copyno, int index,
  10172                        void *entry_data, int *rv)
  10173 {
  10174 #ifdef BCM_HERCULES_SUPPORT
  10175     /* Handle Hercules' word read tables separately */
  10176     if (SOC_IS_HERCULES(unit) &&
  10177         (soc_mem_flags(unit, mem) & SOC_MEM_FLAG_WORDADR)) {
  10178         *rv = soc_hercules_mem_read(unit, mem, copyno, index, entry_data);
  10179         return TRUE;
  10180     }
  10181 #endif /* BCM_HERCULES_SUPPORT */
  10182 
  10183     return FALSE;
  10184 }
  10185 
  10186 /*
  10187  * Function: _soc_mem_read_tr3_esm_unlock
  10188  *
  10189  * Purpose: Called by _soc_mem_read.  On Triumph3, if ESM correction is enabled
  10190  *          and reading from the ESM or ETU blocks,  release the ESM lock.
  10191  */
  10192 STATIC void
  10193 _soc_mem_read_tr3_esm_unlock(int unit, int copyno)
  10194 {
  10195 #if defined(BCM_TRIUMPH3_SUPPORT)
  10196     if (soc_feature(unit, soc_feature_esm_correction) &&
  10197           ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  10198          (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  10199 
  10200         SOC_ESM_UNLOCK(unit);
  10201     }
  10202 #endif
  10203 }
  10204 
  10205 /*
  10206  * Function: _soc_mem_read_tr3_esm_lock
  10207  *
  10208  * Purpose: Called by _soc_mem_read.  On Triumph3, if ESM correction is enabled
  10209  *          and reading from the ESM or ETU blocks, take the ESM lock.
  10210  */
  10211 STATIC void
  10212 _soc_mem_read_tr3_esm_lock(int unit, int copyno)
  10213 {
  10214 #if defined(BCM_TRIUMPH3_SUPPORT)
  10215     if (soc_feature(unit, soc_feature_esm_correction) &&
  10216           (copyno != COPYNO_ALL) && ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  10217          (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  10218 
  10219         SOC_ESM_LOCK(unit);
  10220     }
  10221 #endif
  10222 }
  10223 
  10224 /*
  10225  * Function: _soc_mem_read_cache_attempt
  10226  *
  10227  * Purpose: Called from within _soc_mem_read.  If this memory is cached and
  10228  *          it makes sense to serve the read from the cache, then do so.  Also
  10229  *          sets the variable cache_consistency_check=1 if the cache should be
  10230  *          checked at the end of the read for consistency.
  10231  *
  10232  * Returns: TRUE if the read was served from the cache
  10233  *          FALSE if it was not
  10234  */
  10235 int
  10236 _soc_mem_read_cache_attempt(int unit, uint32 flags, soc_mem_t mem, int copyno,
  10237                             int index, int array_index, void *entry_data,
  10238                             uint32 *entry_data_cache,
  10239                             uint32 *cache_consistency_check)
  10240 {
  10241     uint32 *cache;
  10242     uint8  *vmap;
  10243     int force_cache = 0;
  10244     int entry_dw = soc_mem_entry_words(unit, mem);
  10245 #ifdef BCM_DNX_SUPPORT
  10246     int mem_array_vmap_offset = (SOC_MEM_IS_ARRAY(unit, mem)) ?
  10247                                ((array_index - SOC_MEM_FIRST_ARRAY_INDEX(unit, mem)) * soc_mem_index_count(unit, mem))
  10248                                 : (array_index * soc_mem_index_count(unit, mem));
  10249 
  10250 #else
  10251     int mem_array_vmap_offset = array_index * soc_mem_index_count(unit, mem);
  10252 #endif
  10253     int mem_array_cache_offset = mem_array_vmap_offset * entry_dw;
  10254 
  10255     if ((flags & SOC_MEM_DONT_USE_CACHE) ||
  10256         (flags & SOC_MEM_DONT_MAP_INDEX)) {
  10257         return FALSE;
  10258     }
  10259 
  10260 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT
  10261     force_cache = soc_mem_is_cache_only(unit, mem);
  10262 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */
  10263 
  10264     /* Return data from cache if active */
  10265     cache = SOC_MEM_STATE(unit, mem).cache[copyno];
  10266     vmap = SOC_MEM_STATE(unit, mem).vmap[copyno];
  10267 
  10268     if (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_SER_WRITE_CACHE_RESTORE) &&
  10269         (cache != NULL) && CACHE_VMAP_TST(vmap, index + mem_array_vmap_offset)
  10270         && !SOC_MEM_TEST_SKIP_CACHE(unit)) {
  10271 #ifdef INCLUDE_TCL
  10272         /* Check contents of cache match device table */
  10273         if ((SOC_IS_TD_TT(unit) &&
  10274              (mem == FP_GLOBAL_MASK_TCAMm || mem == FP_GM_FIELDSm)) ||
  10275              (!SOC_MEM_CACHE_COHERENCY_CHECK(unit)) ||
  10276              (flags & SOC_MEM_DONT_CONVERT_XY2DM)) {
  10277             *cache_consistency_check = 0;
  10278         } else if (force_cache) {
  10279             *cache_consistency_check = 0;
  10280         } else {
  10281             *cache_consistency_check = 1;
  10282         }
  10283 
  10284         if (*cache_consistency_check) {
  10285             sal_memcpy(entry_data_cache, cache + mem_array_cache_offset +
  10286                        index * entry_dw, entry_dw * 4);
  10287         } else
  10288 #endif
  10289         {
  10290             sal_memcpy(entry_data, cache + mem_array_cache_offset +
  10291                        index * entry_dw, entry_dw * 4);
  10292             if (force_cache || (!SOC_CONTROL(unit)->force_read_through)) {
  10293                 return TRUE;
  10294             }
  10295         }
  10296     }
  10297 
  10298     return FALSE;
  10299 }
  10300 
  10301 int
  10302 _soc_mem_alpm_read_cache(int unit, soc_mem_t mem, int copyno,
  10303                          int index, void *entry_data)
  10304 {
  10305     int rv = SOC_E_NONE;
  10306     uint32 *cache;
  10307     uint8  *vmap;
  10308     int entry_dw = soc_mem_entry_words(unit, mem);
  10309 
  10310     if (copyno == MEM_BLOCK_ANY || copyno == SOC_CORE_ALL) {
  10311         copyno = SOC_MEM_BLOCK_ANY(unit, mem);
  10312     }
  10313 
  10314     MEM_LOCK(unit, mem);
  10315 
  10316     /* Return data from cache if active */
  10317     cache = SOC_MEM_STATE(unit, mem).cache[copyno];
  10318     vmap = SOC_MEM_STATE(unit, mem).vmap[copyno];
  10319 
  10320     if (cache != NULL
  10321         && CACHE_VMAP_TST(vmap, index)) {
  10322         sal_memcpy(entry_data, cache + index * entry_dw, entry_dw * 4);
  10323         rv = SOC_E_NONE;
  10324     } else {
  10325         rv = SOC_E_DISABLED;
  10326     }
  10327 
  10328     MEM_UNLOCK(unit, mem);
  10329 
  10330     return rv;
  10331 }
  10332 
  10333 /*
  10334  * Function: _soc_mem_read_tr3_read_attempt
  10335  *
  10336  * Purpose:  Called from within _soc_mem_read.  On Triumph devices with the
  10337  *           "always drive dbus" feature, add special case handling to reads
  10338  *           from the ESM block.
  10339  *
  10340  * Returns: TRUE if the read was handled by this function
  10341  *          FALSE if this function did nothing
  10342  */
  10343 STATIC int
  10344 _soc_mem_read_tr3_read_attempt(int unit, soc_mem_t mem, int index, int copyno,
  10345                                void *entry_data, int *rv)
  10346 {
  10347 #ifdef BCM_TRIUMPH_SUPPORT
  10348     if (soc_feature(unit, soc_feature_always_drive_dbus) &&
  10349         SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM &&
  10350         soc_mem_is_cam(unit, mem)) {
  10351 
  10352         static const soc_field_t field_mask[] =
  10353             {TMW0f, TMW1f, TMW2f, TMW3f, TMW4f, TMW5f};
  10354         static const soc_field_t field_data[] =
  10355             {TDW0f, TDW1f, TDW2f, TDW3f, TDW4f, TDW5f};
  10356 
  10357         uint32 tmp_entry[SOC_MAX_MEM_WORDS];
  10358         uint32  sdata[SOC_MAX_MEM_WORDS], src_hit, dst_hit;
  10359         soc_mem_t real_mem, defip_data_mem, src_hit_mem, dst_hit_mem, mask_mem;
  10360         int raw_index, valid;
  10361         int tcam_width, i;
  10362         uint32 mask[4], data[4];
  10363 
  10364         *rv = soc_tcam_mem_index_to_raw_index(unit, mem, index, &real_mem,
  10365                                               &raw_index);
  10366         if (SOC_FAILURE(*rv)) {
  10367             return TRUE;
  10368         }
  10369         switch (mem) {
  10370         case EXT_ACL360_TCAM_DATAm:
  10371         case EXT_ACL360_TCAM_DATA_IPV6_SHORTm:
  10372             mask_mem = EXT_ACL360_TCAM_MASKm;
  10373             break;
  10374         case EXT_ACL432_TCAM_DATAm:
  10375         case EXT_ACL432_TCAM_DATA_IPV6_LONGm:
  10376         case EXT_ACL432_TCAM_DATA_L2_IPV4m:
  10377         case EXT_ACL432_TCAM_DATA_L2_IPV6m:
  10378             mask_mem = EXT_ACL432_TCAM_MASKm;
  10379             break;
  10380         default:
  10381             mask_mem = INVALIDm;
  10382             break;
  10383         }
  10384 
  10385         defip_data_mem = INVALIDm;
  10386         src_hit_mem = INVALIDm;
  10387         dst_hit_mem = INVALIDm;
  10388         switch (real_mem) {
  10389         case EXT_IPV4_DEFIPm:
  10390             defip_data_mem = EXT_DEFIP_DATA_IPV4m;
  10391             src_hit_mem = EXT_SRC_HIT_BITS_IPV4m;
  10392             dst_hit_mem = EXT_DST_HIT_BITS_IPV4m;
  10393             tcam_width = 1;
  10394             break;
  10395         case EXT_IPV6_64_DEFIPm:
  10396             defip_data_mem = EXT_DEFIP_DATA_IPV6_64m;
  10397             src_hit_mem = EXT_SRC_HIT_BITS_IPV6_64m;
  10398             dst_hit_mem = EXT_DST_HIT_BITS_IPV6_64m;
  10399             tcam_width = 1;
  10400             break;
  10401         case EXT_IPV6_128_DEFIPm:
  10402             defip_data_mem = EXT_DEFIP_DATA_IPV6_128m;
  10403             src_hit_mem = EXT_SRC_HIT_BITS_IPV6_128m;
  10404             dst_hit_mem = EXT_DST_HIT_BITS_IPV6_128m;
  10405             tcam_width = 2;
  10406             break;
  10407         case EXT_L2_ENTRY_TCAMm:
  10408         case EXT_IPV4_DEFIP_TCAMm:
  10409         case EXT_IPV6_64_DEFIP_TCAMm:
  10410             tcam_width = 1;
  10411             break;
  10412         case EXT_IPV6_128_DEFIP_TCAMm:
  10413         case EXT_ACL144_TCAMm:
  10414             tcam_width = 2;
  10415             break;
  10416         case EXT_ACL288_TCAMm:
  10417             tcam_width = 4;
  10418             break;
  10419         case EXT_ACL360_TCAM_DATAm:
  10420             tcam_width = 5;
  10421             break;
  10422         case EXT_ACL432_TCAM_DATAm:
  10423             tcam_width = 6;
  10424             break;
  10425         case EXT_L2_ENTRYm:
  10426         default:
  10427             tcam_width = 0;
  10428             break;
  10429         }
  10430 
  10431         sal_memcpy(entry_data, soc_mem_entry_null(unit, real_mem),
  10432                    soc_mem_entry_words(unit, real_mem) * sizeof(uint32));
  10433 
  10434         if (defip_data_mem != INVALIDm) {
  10435             *rv = soc_mem_read(unit, defip_data_mem, copyno, index, tmp_entry);
  10436             if (SOC_FAILURE(*rv)) {
  10437                 return TRUE;
  10438             }
  10439             soc_mem_field_get(unit, defip_data_mem, tmp_entry, SDATAf, sdata);
  10440             soc_mem_field_set(unit, real_mem, entry_data, SDATAf, sdata);
  10441         }
  10442         if (src_hit_mem != INVALIDm) {
  10443             *rv = soc_mem_read(unit, src_hit_mem, copyno, index >> 5,
  10444                               tmp_entry);
  10445             if (SOC_FAILURE(*rv)) {
  10446                 return TRUE;
  10447             }
  10448             src_hit = (soc_mem_field32_get(unit, src_hit_mem, tmp_entry,
  10449                                            SRC_HITf) >> (index & 0x1f)) & 1;
  10450             soc_mem_field32_set(unit, real_mem, entry_data, SRC_HITf, src_hit);
  10451         }
  10452         if (dst_hit_mem != INVALIDm) {
  10453             *rv = soc_mem_read(unit, dst_hit_mem, copyno, index >> 5,
  10454                               tmp_entry);
  10455             if (SOC_FAILURE(*rv)) {
  10456                 return TRUE;
  10457             }
  10458             dst_hit = (soc_mem_field32_get(unit, dst_hit_mem, tmp_entry,
  10459                                            DST_HITf) >> (index & 0x1f)) & 1;
  10460             soc_mem_field32_set(unit, real_mem, entry_data, DST_HITf, dst_hit);
  10461         }
  10462         if (mask_mem != INVALIDm) {
  10463             sal_memcpy(tmp_entry, soc_mem_entry_null(unit, mask_mem),
  10464                        soc_mem_entry_words(unit, mask_mem) * sizeof(uint32));
  10465         }
  10466         if (tcam_width) {
  10467             for (i = 0; i < tcam_width; i++) {
  10468                 *rv = soc_tcam_read_entry(unit, TCAM_PARTITION_RAW,
  10469                                          raw_index + i, mask, data, &valid);
  10470                 if (SOC_FAILURE(*rv)) {
  10471                     return TRUE;
  10472                 }
  10473                 mask[0] = mask[3];
  10474                 mask[3] = mask[1];
  10475                 mask[1] = mask[2];
  10476                 mask[2] = mask[3];
  10477                 if (mask_mem == INVALIDm) {
  10478                     soc_mem_field_set(unit, real_mem, entry_data,
  10479                                       field_mask[i], mask);
  10480                 } else {
  10481                     soc_mem_field_set(unit, mask_mem, tmp_entry,
  10482                                       field_mask[i], mask);
  10483                 }
  10484                 data[0] = data[3];
  10485                 data[3] = data[1];
  10486                 data[1] = data[2];
  10487                 data[2] = data[3];
  10488                 soc_mem_field_set(unit, real_mem, entry_data, field_data[i],
  10489                                   data);
  10490             }
  10491             if (mask_mem != INVALIDm) {
  10492                 *rv = soc_mem_write(unit, mask_mem, copyno, 0, tmp_entry);
  10493             }
  10494             return TRUE;
  10495         }
  10496     }
  10497 #endif /* BCM_TRIUMPH_SUPPORT */
  10498 
  10499     return FALSE;
  10500 }
  10501 
  10502 /*
  10503  * Function: _soc_mem_read_td2_xpipe_tbl_attempt
  10504  *
  10505  * Purpose:  Called within _soc_mem_read.  On Trident2, intercept reads from
  10506  *           the X/Y pipes and serve them from memory.
  10507  *
  10508  * Returns:  TRUE if this function handled the read request
  10509  *           FALSE if it did not.
  10510  */
  10511 STATIC int
  10512 _soc_mem_read_td2_xpipe_tbl_attempt(int unit, soc_mem_t mem, int index,
  10513                                     void *entry_data, int *rv)
  10514 {
  10515 #ifdef BCM_TRIDENT2_SUPPORT
  10516     /* For MMU_INTFI_X/YPIPE_FC_MAP_TBL0/1, do not read hardware table. */
  10517     if (SOC_IS_TRIDENT2(unit)) {
  10518         if (mem == MMU_INTFI_XPIPE_FC_MAP_TBL0m ||
  10519             mem == MMU_INTFI_XPIPE_FC_MAP_TBL1m ||
  10520             mem == MMU_INTFI_YPIPE_FC_MAP_TBL0m ||
  10521             mem == MMU_INTFI_YPIPE_FC_MAP_TBL1m){
  10522 
  10523             *rv = soc_trident2_fc_map_shadow_entry_get(unit, mem, index,
  10524                                                        entry_data);
  10525             return TRUE;
  10526         }
  10527     }
  10528 #endif
  10529 
  10530     return FALSE;
  10531 }
  10532 
  10533 /*
  10534  * Function: _soc_mem_read_defip_index_map
  10535  *
  10536  * Purpose:  Called from within _soc_mem_read and write.  On many devices, we
  10537  *           have to DEFIP table access, converting the requested index
  10538  *           into the actual hardware value "index2."
  10539  *
  10540  * Returns: nothing, but index2 is set as output.
  10541  */
  10542 STATIC void
  10543 _soc_mem_read_defip_index_map(int unit, soc_mem_t mem, int index, int *index2)
  10544 {
  10545     *index2 = index;
  10546 
  10547 #if defined(BCM_FIREBOLT_SUPPORT)
  10548 #if defined(SOC_MEM_L3_DEFIP_WAR) || defined(BCM_TRIUMPH3_SUPPORT) || \
  10549     defined(BCM_ENDURO_SUPPORT)|| defined(BCM_KATANA2_SUPPORT) || \
  10550     defined(BCM_KATANA_SUPPORT)
  10551     if (soc_feature(unit, soc_feature_l3_defip_map) &&
  10552         (mem == L3_DEFIPm ||
  10553          mem == L3_DEFIP_LEVEL1m ||
  10554          mem == L3_DEFIP_ONLYm ||
  10555          mem == L3_DEFIP_DATA_ONLYm ||
  10556          mem == L3_DEFIP_HIT_ONLY_Xm ||
  10557          mem == L3_DEFIP_HIT_ONLY_Ym ||
  10558          mem == L3_DEFIP_HIT_ONLYm)) {
  10559 #ifdef BCM_TRIUMPH3_SUPPORT
  10560         if ((SOC_IS_TRIUMPH3(unit)) || ((SOC_IS_HELIX4(unit)) &&
  10561             (!soc_feature(unit, soc_feature_l3_256_defip_table))) ) {
  10562             *index2 = soc_tr3_l3_defip_index_map(unit, mem, index);
  10563         } else
  10564 #endif /* BCM_TRIUMPH3_SUPPORT */
  10565 #ifdef BCM_KATANA_SUPPORT
  10566         if (SOC_IS_KATANA(unit)) {
  10567             *index2 = soc_kt_l3_defip_index_map(unit, mem, index);
  10568         } else
  10569 #endif /* BCM_KATANA_SUPPORT */
  10570 #ifdef BCM_KATANA2_SUPPORT
  10571         if (SOC_IS_KATANA2(unit)) {
  10572             *index2 = soc_kt2_l3_defip_index_map(unit, mem, index);
  10573         } else
  10574 #endif /* BCM_KATANA2_SUPPORT */
  10575 #if defined(BCM_TRIDENT2_SUPPORT)
  10576         if (SOC_IS_TD2_TT2(unit)) {
  10577             *index2 = soc_trident2_l3_defip_index_map(unit, mem, index);
  10578         } else
  10579 #endif /* BCM_TRIDENT2_SUPPORT */
  10580 #if defined(BCM_ENDURO_SUPPORT)
  10581         if (SOC_IS_ENDURO(unit)) {
  10582             *index2 = soc_enduro_l3_defip_index_map(unit, mem, index);
  10583         } else
  10584 #endif /* BCM_ENDURO_SUPPORT */
  10585         {
  10586 #ifdef SOC_MEM_L3_DEFIP_WAR
  10587             *index2 = soc_fb_l3_defip_index_map(unit, index);
  10588 #endif /* SOC_MEM_L3_DEFIP_WAR */
  10589         }
  10590     }
  10591 #endif /* SOC_MEM_L3_DEFIP_WAR || BCM_TRIUMPH3_SUPPORT */
  10592 #endif /* BCM_FIREBOLT_SUPPORT */
  10593 
  10594 #ifdef BCM_TRIUMPH2_SUPPORT
  10595     if (soc_feature(unit, soc_feature_l3_defip_hole) &&
  10596         (mem == L3_DEFIPm ||
  10597          mem == L3_DEFIP_ONLYm ||
  10598          mem == L3_DEFIP_DATA_ONLYm ||
  10599          mem == L3_DEFIP_HIT_ONLYm)) {
  10600         *index2 = soc_tr2_l3_defip_index_map(unit, index);
  10601     }
  10602 #endif /* BCM_TRIUMPH2_SUPPORT */
  10603 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA2_SUPPORT) || \
  10604     defined(BCM_KATANA_SUPPORT)
  10605     if (soc_feature(unit, soc_feature_l3_defip_map) &&
  10606         (mem == L3_DEFIP_PAIR_128m ||
  10607          mem == L3_DEFIP_PAIR_LEVEL1m ||
  10608          mem == L3_DEFIP_PAIR_128_ONLYm ||
  10609          mem == L3_DEFIP_PAIR_128_DATA_ONLYm ||
  10610          mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm ||
  10611          mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym ||
  10612          mem == L3_DEFIP_PAIR_128_HIT_ONLYm)) {
  10613 #if defined(BCM_TRIUMPH3_SUPPORT)
  10614         if ((SOC_IS_TRIUMPH3(unit)) || ((SOC_IS_HELIX4(unit)) &&
  10615             (!soc_feature(unit, soc_feature_l3_256_defip_table))) ) {
  10616             *index2 = soc_tr3_l3_defip_index_map(unit, mem, index);
  10617         }
  10618 #endif /* BCM_TRIUMPH3_SUPPORT */
  10619 #if defined(BCM_TRIDENT2_SUPPORT)
  10620         if SOC_IS_TD2_TT2(unit) {
  10621             *index2 = soc_trident2_l3_defip_index_map(unit, mem, index);
  10622         }
  10623 #endif /* BCM_TRIDENT2_SUPPORT */
  10624 #ifdef BCM_KATANA_SUPPORT
  10625         if (SOC_IS_KATANA(unit)) {
  10626             *index2 = soc_kt_l3_defip_index_map(unit, mem, index);
  10627         }
  10628 #endif /* BCM_KATANA_SUPPORT */
  10629 #ifdef BCM_KATANA2_SUPPORT
  10630         if (SOC_IS_KATANA2(unit)) {
  10631             *index2 = soc_kt2_l3_defip_index_map(unit, mem, index);
  10632         }
  10633 #endif /* BCM_KATANA2_SUPPORT */
  10634     }
  10635 #endif /* BCM_TRIUMPH3_SUPPORT || BCM_KATANA2_SUPPORT*/
  10636 }
  10637 
  10638 
  10639 /*
  10640  * Function: _soc_mem_defip_index_is_invalid
  10641  *
  10642  * Purpose:  Called from within _soc_mem_read and write.  This function is used to check
  10643  *               if this physical index is invalid for this mem view.
  10644  *
  10645  * Returns: TRUE if the index is invalid
  10646  *          FALSE if the index is valid
  10647  */
  10648 STATIC int
  10649 _soc_mem_defip_index_is_invalid(int unit, soc_mem_t mem, int index)
  10650 {
  10651     int index_max = soc_mem_index_max(unit, mem);
  10652     int index_for_check = index;
  10653     soc_mem_t defip_mem = L3_DEFIPm, defip_pair_mem = L3_DEFIP_PAIR_128m;
  10654 
  10655     if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) {
  10656         defip_mem = L3_DEFIP_LEVEL1m;
  10657         defip_pair_mem = L3_DEFIP_PAIR_LEVEL1m;
  10658     }
  10659 
  10660     if (soc_feature(unit, soc_feature_l3_defip_map)) {
  10661         if (mem == defip_mem ||
  10662 #ifdef BCM_TOMAHAWK3_SUPPORT
  10663             mem == L3_DEFIP_LEVEL1_HIT_ONLYm ||
  10664 #endif
  10665             mem == L3_DEFIP_ONLYm ||
  10666             mem == L3_DEFIP_DATA_ONLYm ||
  10667             mem == L3_DEFIP_HIT_ONLY_Xm ||
  10668             mem == L3_DEFIP_HIT_ONLY_Ym ||
  10669             mem == L3_DEFIP_HIT_ONLYm) {
  10670             index_max = soc_mem_index_count(unit, defip_mem) +
  10671                         soc_mem_index_count(unit, defip_pair_mem) * 2 - 1;
  10672 
  10673             if (soc_feature(unit, soc_feature_l3_1k_defip_table)) {
  10674                 int tcam_size = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit);
  10675                 int num_tcams =  soc_mem_index_count(unit, defip_pair_mem) ? 1 : 0;
  10676 
  10677                 index_max = soc_mem_index_count(unit, defip_mem) +
  10678                             num_tcams * 2 * tcam_size;
  10679             }
  10680         } else if (mem == defip_pair_mem ||
  10681             mem == L3_DEFIP_PAIR_128_ONLYm ||
  10682             mem == L3_DEFIP_PAIR_128_DATA_ONLYm ||
  10683             mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm ||
  10684             mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym ||
  10685             mem == L3_DEFIP_PAIR_128_HIT_ONLYm) {
  10686             index_max = soc_mem_index_count(unit, defip_mem) / 2 +
  10687                         soc_mem_index_count(unit, defip_pair_mem);
  10688             index_max--;
  10689         }
  10690     }
  10691 
  10692     if (index_for_check < 0 || index_for_check > index_max) {
  10693         if (!(SOC_DEFIP_HOLE_RANGE_CHECK(unit, mem, index))) {
  10694         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  10695                   (BSL_META_U(unit,
  10696                               "invalid index %d for memory %s\n"),
  10697                    index_for_check, SOC_MEM_NAME(unit, mem)));
  10698         return TRUE;
  10699     }
  10700     }
  10701 
  10702     return FALSE;
  10703 }
  10704 
  10705 /*
  10706  * Function: _soc_mem_read_tr_response_word_update
  10707  *
  10708  * Purpose:  Called from within _soc_mem_read.  When reading certain tables on
  10709  *           TRIUMPH devices with ESM support, the schan response will have a
  10710  *           response word in it.  If so, set the resp_word variable.
  10711  *
  10712  * Returns: nothing, but resp_word may be updated
  10713  *
  10714  * Note:
  10715  *  We probably should invent SOC_MEM_FLAG_HAS_RESP_WORD in regsfile
  10716  *  for such tables (or define a bit in S-chan message header if
  10717  *  hardware can do that)
  10718  */
  10719 STATIC void
  10720 _soc_mem_read_tr_response_word_update(int unit, soc_mem_t mem,
  10721                                       int *resp_word)
  10722 {
  10723 #ifdef BCM_TRIUMPH_SUPPORT
  10724     if ((!SAL_BOOT_PLISIM || SAL_BOOT_BCMSIM) &&
  10725         soc_feature(unit, soc_feature_esm_support)) {
  10726         switch (mem) {
  10727         case EXT_L2_ENTRYm:
  10728         case EXT_L2_ENTRY_TCAMm:
  10729         case EXT_L2_ENTRY_DATAm:
  10730         case EXT_DEFIP_DATAm:
  10731         case EXT_IPV4_DEFIP_TCAMm:
  10732         case EXT_IPV4_DEFIPm:
  10733         case EXT_IPV6_64_DEFIP_TCAMm:
  10734         case EXT_IPV6_64_DEFIPm:
  10735         case EXT_IPV6_128_DEFIP_TCAMm:
  10736         case EXT_IPV6_128_DEFIPm:
  10737         case EXT_FP_POLICYm:
  10738         case EXT_FP_CNTRm:
  10739         case EXT_FP_CNTR8m:
  10740         case EXT_ACL144_TCAMm:
  10741         case EXT_ACL288_TCAMm:
  10742         case EXT_ACL360_TCAM_DATAm: /* not for MASK portion */
  10743         case EXT_ACL432_TCAM_DATAm: /* not for MASK portion */
  10744         /* and following software invented tables as well */
  10745         case EXT_DEFIP_DATA_IPV4m:
  10746         case EXT_DEFIP_DATA_IPV6_64m:
  10747         case EXT_DEFIP_DATA_IPV6_128m:
  10748         case EXT_FP_POLICY_ACL288_L2m:
  10749         case EXT_FP_POLICY_ACL288_IPV4m:
  10750         case EXT_FP_POLICY_ACL360_IPV6_SHORTm:
  10751         case EXT_FP_POLICY_ACL432_IPV6_LONGm:
  10752         case EXT_FP_POLICY_ACL144_L2m:
  10753         case EXT_FP_POLICY_ACL144_IPV4m:
  10754         case EXT_FP_POLICY_ACL144_IPV6m:
  10755         case EXT_FP_POLICY_ACL432_L2_IPV4m:
  10756         case EXT_FP_POLICY_ACL432_L2_IPV6m:
  10757         case EXT_FP_CNTR_ACL288_L2m:
  10758         case EXT_FP_CNTR_ACL288_IPV4m:
  10759         case EXT_FP_CNTR_ACL360_IPV6_SHORTm:
  10760         case EXT_FP_CNTR_ACL432_IPV6_LONGm:
  10761         case EXT_FP_CNTR_ACL144_L2m:
  10762         case EXT_FP_CNTR_ACL144_IPV4m:
  10763         case EXT_FP_CNTR_ACL144_IPV6m:
  10764         case EXT_FP_CNTR_ACL432_L2_IPV4m:
  10765         case EXT_FP_CNTR_ACL432_L2_IPV6m:
  10766         case EXT_FP_CNTR8_ACL288_L2m:
  10767         case EXT_FP_CNTR8_ACL288_IPV4m:
  10768         case EXT_FP_CNTR8_ACL360_IPV6_SHORTm:
  10769         case EXT_FP_CNTR8_ACL432_IPV6_LONGm:
  10770         case EXT_FP_CNTR8_ACL144_L2m:
  10771         case EXT_FP_CNTR8_ACL144_IPV4m:
  10772         case EXT_FP_CNTR8_ACL144_IPV6m:
  10773         case EXT_FP_CNTR8_ACL432_L2_IPV4m:
  10774         case EXT_FP_CNTR8_ACL432_L2_IPV6m:
  10775         case EXT_ACL288_TCAM_L2m:
  10776         case EXT_ACL288_TCAM_IPV4m:
  10777         case EXT_ACL360_TCAM_DATA_IPV6_SHORTm:
  10778         case EXT_ACL432_TCAM_DATA_IPV6_LONGm:
  10779         case EXT_ACL144_TCAM_L2m:
  10780         case EXT_ACL144_TCAM_IPV4m:
  10781         case EXT_ACL144_TCAM_IPV6m:
  10782         case EXT_ACL432_TCAM_DATA_L2_IPV4m:
  10783         case EXT_ACL432_TCAM_DATA_L2_IPV6m:
  10784 #ifdef BCM_TRIUMPH3_SUPPORT
  10785             if (SOC_IS_TRIUMPH3(unit)) {
  10786                 break;
  10787             }
  10788 #endif /* BCM_TRIUMPH3_SUPPORT */
  10789             *resp_word = 1;
  10790             break;
  10791         default:
  10792             break;
  10793         }
  10794     }
  10795 #endif /* BCM_TRIUMPH_SUPPORT */
  10796 }
  10797 
  10798 STATIC void 
  10799 _soc_mem_acc_type_swap(int unit, schan_header_t *header) {
  10800     int acc_type_swap = 0, acc_type_old = 0;
  10801 
  10802     if (soc_feature(unit, soc_feature_sbus_format_v4)) {
  10803         acc_type_old = header->v4.acc_type;
  10804     } else if (soc_feature(unit, soc_feature_new_sbus_format)) {
  10805         acc_type_old = header->v3.acc_type;
  10806     } else {
  10807         acc_type_old = header->v2.src_blk;
  10808     }
  10809 
  10810     if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
  10811         if (acc_type_old == _SOC_MEM_ADDR_ACC_TYPE_PIPE_1) {
  10812             acc_type_swap = _SOC_MEM_ADDR_ACC_TYPE_PIPE_0;
  10813         } else {
  10814             acc_type_swap = _SOC_MEM_ADDR_ACC_TYPE_PIPE_1;
  10815         }
  10816     } else {
  10817         if (acc_type_old == _SOC_MEM_ADDR_ACC_TYPE_PIPE_Y) {
  10818             acc_type_swap = _SOC_MEM_ADDR_ACC_TYPE_PIPE_X;
  10819         } else {
  10820             acc_type_swap = _SOC_MEM_ADDR_ACC_TYPE_PIPE_Y;
  10821         }
  10822     }
  10823 
  10824     if (soc_feature(unit, soc_feature_sbus_format_v4)) {
  10825         header->v4.acc_type = acc_type_swap;
  10826     } else if (soc_feature(unit, soc_feature_new_sbus_format)) {
  10827         header->v3.acc_type = acc_type_swap;
  10828     } else {
  10829         header->v2.src_blk = acc_type_swap;
  10830     }
  10831 }
  10832 
  10833 /*
  10834  * Function: _soc_mem_read_ser_correct
  10835  *
  10836  * Purpose:  Called from within _soc_mem_read.  If there was a error reading,
  10837  *           try to use SER to correct it.
  10838  *
  10839  * Returns:  TRUE if the error was corrected,
  10840  *           FALSE if it was not.
  10841  */
  10842 STATIC int
  10843 _soc_mem_read_ser_correct(int unit, uint32 flags, soc_mem_t mem, int copyno,
  10844                           int index, void *entry_data,
  10845                           schan_msg_t *schan_msg, schan_msg_t *schan_msg_cpy,
  10846                           int resp_word, int *rv, int *all_done)
  10847 {
  10848     uint32 *cache = SOC_MEM_STATE(unit, mem).cache[copyno];
  10849     uint8  *vmap  = SOC_MEM_STATE(unit, mem).vmap[copyno];
  10850     int entry_dw = soc_mem_entry_words(unit, mem);
  10851     int allow_intr = SOC_IS_SAND(unit) ? 1 : 0;
  10852 
  10853     if (!SOC_SER_CORRECTION_SUPPORT(unit)) {
  10854         return FALSE;
  10855     }
  10856 
  10857 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HELIX4_SUPPORT) || \
  10858         defined(BCM_KATANA2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || \
  10859         defined(BCM_GREYHOUND_SUPPORT)
  10860     do {
  10861         uint8 *corrupt = NULL;
  10862 
  10863         /* Record error index for TCAM table */
  10864         if((SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) &&
  10865            (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM))) {
  10866             corrupt = SOC_MEM_STATE(unit, mem).corrupt[copyno];
  10867             if (corrupt != NULL) {
  10868                 TCAM_CORRUPT_MAP_SET(corrupt, index);
  10869                 LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
  10870                             (BSL_META_U(unit,
  10871                                 "Mem[%s] index[%d] "
  10872                                 "TCAM parity error indicating bit is set.\n"),
  10873                              SOC_MEM_NAME(unit, mem), index));
  10874             }
  10875         }
  10876     } while (0);
  10877 #endif
  10878 
  10879     if (flags & SOC_MEM_SCHAN_ERR_RETURN) {
  10880         return FALSE;
  10881     }
  10882 
  10883     if (cache != NULL && CACHE_VMAP_TST(vmap, index)
  10884         && !SOC_MEM_TEST_SKIP_CACHE(unit)) {
  10885         sal_memcpy(entry_data, cache + index * entry_dw, entry_dw * 4);
  10886         LOG_VERBOSE(BSL_LS_SOC_COMMON,
  10887                     (BSL_META_U(unit,
  10888                                 "Unit:%d Mem[%s] index[%d] "
  10889                                 "Force fetch data from cache.\n"),
  10890                      unit, SOC_MEM_NAME(unit, mem), index));
  10891     } else if (SOC_IS_TD2_TT2(unit) &&
  10892         soc_feature(unit, soc_feature_two_ingress_pipes) &&
  10893         (mem == L3_DEFIP_ALPM_IPV4m || mem == L3_DEFIP_ALPM_IPV4_1m ||
  10894          mem == L3_DEFIP_ALPM_IPV6_64m || mem == L3_DEFIP_ALPM_IPV6_64_1m ||
  10895          mem == L3_DEFIP_ALPM_IPV6_128m || mem == L3_DEFIPm ||
  10896          mem == L3_DEFIP_PAIR_128m ||
  10897          mem == L3_DEFIP_LEVEL1m ||
  10898          mem == L3_DEFIP_PAIR_LEVEL1m ||
  10899          mem == L3_DEFIP_ALPM_LEVEL2m ||
  10900          mem == L3_DEFIP_ALPM_LEVEL3m)) {
  10901         /* Fetch data from other pipe */
  10902         _soc_mem_acc_type_swap(unit, &(schan_msg_cpy->readcmd.header));
  10903 
  10904         *rv = soc_schan_op(unit, schan_msg_cpy, 2, 1 + entry_dw + resp_word, allow_intr);
  10905         if (SOC_FAILURE(*rv)) {
  10906             return TRUE;
  10907         }
  10908 
  10909         sal_memcpy(schan_msg, schan_msg_cpy, sizeof(*schan_msg));
  10910         LOG_VERBOSE(BSL_LS_SOC_COMMON,
  10911                     (BSL_META_U(unit,
  10912                                 "Unit:%d Mem[%s] index[%d] "
  10913                                 "Force fetch data from other pipe.\n"),
  10914                      unit, SOC_MEM_NAME(unit, mem), index));
  10915         return TRUE;
  10916     } else {
  10917         void *null_entry = soc_mem_entry_null(unit, mem);
  10918         sal_memcpy(entry_data, null_entry, entry_dw * 4);
  10919         LOG_VERBOSE(BSL_LS_SOC_COMMON,
  10920                     (BSL_META_U(unit,
  10921                                 "Unit:%d Mem[%s] index[%d] "
  10922                                 "Force fetch null data.\n"),
  10923                      unit, SOC_MEM_NAME(unit, mem), index));
  10924         return TRUE;
  10925     }
  10926 
  10927     return FALSE;
  10928 }
  10929 
  10930 /*
  10931  * Function: _soc_mem_read_td_tt_byte_len_update
  10932  *
  10933  * Purpose:  Called within _soc_mem_read.  On Trident/titan chips, the expected
  10934  *           data length from certain memories has to be set as a special case.
  10935  *
  10936  * Returns:  Nothing, but may alter the data_byte_len variable if necessary.
  10937  */
  10938 STATIC void
  10939 _soc_mem_read_td_tt_byte_len_update(int unit, soc_mem_t mem, int entry_dw,
  10940                                    int *data_byte_len)
  10941 {
  10942 #ifdef BCM_TRIDENT_SUPPORT
  10943     if (SOC_IS_TD_TT(unit)) {
  10944         if (mem == ESBS_PORT_TO_PIPE_MAPPINGm ||
  10945             mem == ISBS_PORT_TO_PIPE_MAPPINGm) {
  10946             *data_byte_len = entry_dw * 4;
  10947         }
  10948     }
  10949 #endif /* BCM_TRIDENT_SUPPORT */
  10950 }
  10951 
  10952 /*
  10953  * Function: soc_mem_dst_blk_update
  10954  *
  10955  * Purpose:  Called within _soc_mem_read/write.  In certain configurations, the
  10956  *           destination block for schan requests must be calculated as a
  10957  *           special case and not read directly from the regsfile.
  10958  *
  10959  * Returns:  Nothing, but may alter the dst_blk variable if necessary.
  10960  */
  10961 void
  10962 soc_mem_dst_blk_update(int unit, int copyno, int maddr, int *dst_blk)
  10963 {
  10964     *dst_blk = 0;
  10965 
  10966 #if defined(BCM_EXTND_SBUS_SUPPORT) || defined(BCM_SAND_SUPPORT)
  10967 
  10968     if (soc_feature(unit, soc_feature_new_sbus_format)) {
  10969         *dst_blk = SOC_BLOCK2SCH(unit, copyno);
  10970     } else
  10971 
  10972 #endif
  10973     {
  10974 #if defined(BCM_XGS3_SWITCH_SUPPORT) ||\
  10975     defined(BCM_SAND_SUPPORT)
  10976         /* required on XGS3. Optional on other devices */
  10977         *dst_blk = ((maddr >> SOC_BLOCK_BP) & 0xf) |
  10978             (((maddr >> SOC_BLOCK_MSB_BP) & 0x3) << 4);
  10979 #endif /* BCM_XGS3_SWITCH_SUPPORT || BCM_SAND_SUPPORT */
  10980     }
  10981 }
  10982 
  10983 #ifdef HR3LITE_LPM_WAR
  10984 /*
  10985  * Function: _soc_mem_hr3_lpm_hit_shadow_update
  10986  *
  10987  * Purpose:  Called by _soc_mem_read_schan_msg_send(). 
  10988  *          This function is used to sync-up the correct LPM-HIT entry on 
  10989  *          HR3-Lite device. LPM table in HR3-Lite support 64 entries only, 
  10990  *          but LPM-TCAM on entry between 32~63 can only be hit with 
  10991  *          LPM-DATA on entry between 512~543 and the hit status is updated  
  10992  *          by HW on LPM-HIT entry 512~543 as well.
  10993  *
  10994  * Returns:  SOC_E_xxx
  10995  */
  10996 
  10997 STATIC int
  10998 _soc_mem_hr3_lpm_hit_shadow_update(int unit, soc_mem_t mem, int copyno,
  10999                     int index, void *lpm_entry_data, unsigned array_index)
  11000 {
  11001     defip_entry_t *lpm_entry;
  11002     defip_hit_only_entry_t lpm_hit_entry;
  11003     int defip_hit_size = 0;
  11004     int lpm_hit_shadow_index = -1;
  11005     schan_msg_t schan_msg;
  11006     int opcode, err;
  11007     int resp_word = 0;
  11008     int entry_dw = soc_mem_entry_words(unit, L3_DEFIP_HIT_ONLYm);
  11009     int rv = SOC_E_NONE;
  11010     int src_blk, dst_blk, acc_type, data_byte_len;
  11011     uint32 maddr;
  11012     uint8 at;
  11013     uint32 new_hit = 0, old_hit = 0;
  11014 
  11015     if (soc_feature(unit, soc_feature_hr3_lite_lpm_shadow_hit)) {
  11016         if ((NEED_HR3LITE_LPM_SHADOW(mem)) && (mem != L3_DEFIP_DATA_ONLYm)) {
  11017             lpm_hit_shadow_index = HR3LITE_LPM_HIT_INDEX2(index);
  11018         }
  11019     }
  11020 
  11021     if (lpm_hit_shadow_index == -1) {
  11022         /* no sync-up process is required */
  11023         return SOC_E_NONE;
  11024     }
  11025 
  11026     LOG_INFO(BSL_LS_SOC_LPM, (BSL_META_U(unit,
  11027             "HR3-Lite LPM_WAR:update LPM(%s,idx=%d) HIT from entry(%d)!\n"),
  11028             SOC_MEM_NAME(unit, mem),index, lpm_hit_shadow_index));
  11029     /* init entry data buf */
  11030     defip_hit_size = sizeof(defip_hit_only_entry_t);
  11031     sal_memset(&lpm_hit_entry, 0, defip_hit_size);
  11032 
  11033     sal_memset(&schan_msg, 0, sizeof(schan_msg_t));
  11034 
  11035     /* Setup S-Channel command packet */
  11036     schan_msg_clear(&schan_msg);
  11037     src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit));
  11038     acc_type = SOC_MEM_ACC_TYPE(unit, L3_DEFIP_HIT_ONLYm);
  11039     data_byte_len = 4;
  11040 
  11041     maddr = soc_mem_addr_get(unit, L3_DEFIP_HIT_ONLYm, array_index, 
  11042             copyno, lpm_hit_shadow_index, &at);
  11043     schan_msg.readcmd.address = maddr;
  11044 
  11045     soc_mem_dst_blk_update(unit, copyno, maddr, &dst_blk);
  11046     _soc_mem_read_tr_response_word_update(unit, mem, &resp_word);
  11047 
  11048     soc_schan_header_cmd_set(unit, &schan_msg.header, READ_MEMORY_CMD_MSG,
  11049                              dst_blk, src_blk, acc_type, data_byte_len, 0, 0);
  11050 
  11051     /*
  11052      * Write onto S-Channel "memory read" command packet consisting of header
  11053      * word + address word, and read back header word + entry_dw data words.
  11054      */
  11055     if (2 + entry_dw > CMIC_SCHAN_WORDS(unit)) {
  11056         LOG_WARN(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  11057                 "soc_mem_read: assert will fail for memory %s\n"),
  11058                 SOC_MEM_NAME(unit, L3_DEFIP_HIT_ONLYm)));
  11059     }
  11060 
  11061     rv = soc_schan_op(unit, &schan_msg, 2, 1 + entry_dw + resp_word, 0);
  11062 
  11063     soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL,
  11064                                 &err, NULL, NULL);
  11065     if (opcode != READ_MEMORY_ACK_MSG || err != 0) {
  11066         LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  11067                 "soc_mem_read: Mem(%s) invalid S-Channel reply, "
  11068                 "expected READ_MEMORY_ACK:, opcode %d\n"), 
  11069                 SOC_MEM_NAME(unit,L3_DEFIP_HIT_ONLYm), opcode));
  11070         soc_schan_dump(unit, &schan_msg, 1 + entry_dw + resp_word);
  11071         rv = SOC_E_INTERNAL;
  11072         return rv;
  11073     }
  11074 
  11075     sal_memcpy(&lpm_hit_entry,
  11076                resp_word ? schan_msg.genresp.data : schan_msg.readresp.data,
  11077                entry_dw * sizeof (uint32));
  11078 
  11079     /* sync-up hit field */
  11080     new_hit = soc_L3_DEFIP_HIT_ONLYm_field32_get(unit, &lpm_hit_entry, HITf);
  11081     if (mem == L3_DEFIP_HIT_ONLYm) {
  11082         old_hit = soc_L3_DEFIP_HIT_ONLYm_field32_get(unit, lpm_entry_data, HITf);
  11083         /* sync-up the HIT field */
  11084         sal_memcpy(lpm_entry_data, &lpm_hit_entry, entry_dw * sizeof (uint32));
  11085     } else if (mem == L3_DEFIPm) {
  11086         lpm_entry = lpm_entry_data;
  11087         old_hit = soc_L3_DEFIPm_field32_get(unit, lpm_entry, HITf);
  11088         /* sync-up the HIT field */
  11089         soc_L3_DEFIPm_field32_set(unit, lpm_entry, HITf, new_hit);
  11090     }
  11091     LOG_INFO(BSL_LS_SOC_LPM, (BSL_META_U(unit,
  11092             "HR3-Lite LPM_WAR:update LPM(%s,idx=%d) new_hit=%d, old_hit=%d\n"),
  11093             SOC_MEM_NAME(unit, mem),index, new_hit, old_hit));
  11094 
  11095     return rv;
  11096 }
  11097 #endif  /* HR3LITE_LPM_WAR */
  11098 
  11099 #ifdef BCM_TOMAHAWK3_SUPPORT
  11100 /*
  11101  * Function: _soc_th3_mem_read_schan_msg_send
  11102  *
  11103  * Purpose:  Called within _soc_mem_read.  Construct and send a schan message
  11104  *           holding the read requests, and parse the response.  If an error
  11105  *           happens, try to correct with SER.
  11106  *
  11107  * Returns:  Standard BCM_E_* code
  11108  */
  11109 STATIC int
  11110 _soc_th3_mem_read_schan_msg_send(int unit, uint32 flags, soc_mem_t mem, int copyno,
  11111                              int index, void *entry_data, unsigned array_index,
  11112                              int remapped_index, int acc_type)
  11113 {
  11114     schan_msg_t schan_msg, schan_msg_cpy;
  11115     int opcode, err;
  11116     int resp_word = 0;
  11117     int entry_dw = soc_mem_entry_words(unit, mem);
  11118     int rv = SOC_E_NONE;
  11119     int allow_intr = 0;
  11120     int src_blk, dst_blk, data_byte_len;
  11121     uint32 maddr;
  11122     uint8 at;
  11123     sal_memset(&schan_msg, 0, sizeof(schan_msg_t));
  11124 
  11125     /* Setup S-Channel command packet */
  11126     schan_msg_clear(&schan_msg);
  11127     src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit));
  11128     data_byte_len = 4;
  11129 
  11130     maddr = soc_mem_addr_get(unit, mem, array_index, copyno, remapped_index,
  11131                              &at);
  11132     schan_msg.readcmd.address = maddr;
  11133 
  11134     _soc_mem_read_td_tt_byte_len_update(unit, mem, entry_dw, &data_byte_len);
  11135     soc_mem_dst_blk_update(unit, copyno, maddr, &dst_blk);
  11136     _soc_mem_read_tr_response_word_update(unit, mem, &resp_word);
  11137 
  11138     soc_schan_header_cmd_set(unit, &schan_msg.header, READ_MEMORY_CMD_MSG,
  11139                              dst_blk, src_blk, acc_type, data_byte_len, 0, 0);
  11140 
  11141     /*
  11142      * Write onto S-Channel "memory read" command packet consisting of header
  11143      * word + address word, and read back header word + entry_dw data words.
  11144      */
  11145     if (2 + entry_dw > CMIC_SCHAN_WORDS(unit)) {
  11146        LOG_WARN(BSL_LS_SOC_SOCMEM,
  11147                 (BSL_META_U(unit,
  11148                             "soc_mem_read: assert will fail for memory %s\n"),
  11149                  SOC_MEM_NAME(unit, mem)));
  11150     }
  11151 
  11152     rv = soc_schan_op(unit, &schan_msg, 2, 1 + entry_dw + resp_word, allow_intr);
  11153     if (SOC_FAILURE(rv)) {
  11154         int all_done = FALSE;
  11155         _soc_mem_read_ser_correct(unit, flags, mem, copyno, index, entry_data,
  11156                                   &schan_msg, &schan_msg_cpy, resp_word, &rv,
  11157                                   &all_done);
  11158         if (SOC_FAILURE(rv) || all_done) {
  11159             return rv;
  11160         }
  11161     }
  11162 
  11163     soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL,
  11164                                 &err, NULL, NULL);
  11165     if (opcode != READ_MEMORY_ACK_MSG || err != 0) {
  11166         {
  11167             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  11168                       (BSL_META_U(unit,
  11169                                   "soc_mem_read: "
  11170                                   "Mem(%s) "
  11171                                   "invalid S-Channel reply, expected READ_MEMORY_ACK:, opcode %d\n"),
  11172                                   SOC_MEM_NAME(unit,mem), opcode));
  11173             soc_schan_dump(unit, &schan_msg, 1 + entry_dw + resp_word);
  11174             rv = SOC_E_INTERNAL;
  11175             return rv;
  11176         }
  11177     }
  11178     sal_memcpy(entry_data,
  11179                resp_word ? schan_msg.genresp.data : schan_msg.readresp.data,
  11180                entry_dw * sizeof (uint32));
  11181 #ifdef USE_VALGRIND_CLIENT_REQUESTS
  11182                VALGRIND_MAKE_MEM_DEFINED(entry_data, entry_dw * sizeof (uint32));
  11183 #endif /* USE_VALGRIND_CLIENT_REQUESTS */
  11184 
  11185     return rv;
  11186 }
  11187 #endif
  11188 /*
  11189  * Function: _soc_mem_read_schan_msg_send
  11190  *
  11191  * Purpose:  Called within _soc_mem_read.  Construct and send a schan message
  11192  *           holding the read requests, and parse the response.  If an error
  11193  *           happens, try to correct with SER.
  11194  *
  11195  * Returns:  Standard BCM_E_* code
  11196  */
  11197 STATIC int
  11198 _soc_mem_read_schan_msg_send(int unit, uint32 flags, soc_mem_t mem, int copyno,
  11199                              int index, void *entry_data, unsigned array_index,
  11200                              int remapped_index)
  11201 {
  11202     schan_msg_t schan_msg, schan_msg_cpy;
  11203     int opcode, err;
  11204     int resp_word = 0;
  11205     int entry_dw = soc_mem_entry_words(unit, mem);
  11206     int rv = SOC_E_NONE;
  11207     int allow_intr = SOC_IS_SAND(unit) ? 1 : 0;
  11208     int src_blk, dst_blk, acc_type, data_byte_len;
  11209     uint32 maddr;
  11210     uint8 at;
  11211 
  11212     sal_memset(&schan_msg, 0, sizeof(schan_msg_t));
  11213 
  11214     /* Setup S-Channel command packet */
  11215     schan_msg_clear(&schan_msg);
  11216     src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit));
  11217     acc_type = SOC_MEM_ACC_TYPE(unit, mem);
  11218     data_byte_len = 4;
  11219 
  11220     maddr = soc_mem_addr_get(unit, mem, array_index, copyno, remapped_index,
  11221                              &at);
  11222     schan_msg.readcmd.address = maddr;
  11223 
  11224     _soc_mem_read_td_tt_byte_len_update(unit, mem, entry_dw, &data_byte_len);
  11225     soc_mem_dst_blk_update(unit, copyno, maddr, &dst_blk);
  11226     _soc_mem_read_tr_response_word_update(unit, mem, &resp_word);
  11227 
  11228     soc_schan_header_cmd_set(unit, &schan_msg.header, READ_MEMORY_CMD_MSG,
  11229                              dst_blk, src_blk, acc_type, data_byte_len, 0, 0);
  11230 
  11231     /*
  11232      * Write onto S-Channel "memory read" command packet consisting of header
  11233      * word + address word, and read back header word + entry_dw data words.
  11234      */
  11235     if (2 + entry_dw > CMIC_SCHAN_WORDS(unit)) {
  11236        LOG_WARN(BSL_LS_SOC_SOCMEM,
  11237                 (BSL_META_U(unit,
  11238                             "soc_mem_read: assert will fail for memory %s\n"),
  11239                  SOC_MEM_NAME(unit, mem)));
  11240     }
  11241 
  11242     if (soc_feature(unit, soc_feature_two_ingress_pipes)) {
  11243         sal_memcpy(&schan_msg_cpy, &schan_msg, sizeof(schan_msg));
  11244     }
  11245     rv = soc_schan_op(unit, &schan_msg, 2, 1 + entry_dw + resp_word, allow_intr);
  11246     if (SOC_FAILURE(rv)) {
  11247         int all_done = FALSE;
  11248         _soc_mem_read_ser_correct(unit, flags, mem, copyno, index, entry_data,
  11249                                   &schan_msg, &schan_msg_cpy, resp_word, &rv,
  11250                                   &all_done);
  11251         if (SOC_FAILURE(rv) || all_done) {
  11252             return rv;
  11253         }
  11254     }
  11255 
  11256     soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL,
  11257                                 &err, NULL, NULL);
  11258     if (opcode != READ_MEMORY_ACK_MSG || err != 0) {
  11259         {
  11260             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  11261                       (BSL_META_U(unit,
  11262                                   "soc_mem_read: "
  11263                                   "Mem(%s) "
  11264                                   "invalid S-Channel reply, expected READ_MEMORY_ACK:, opcode %d\n"),SOC_MEM_NAME(unit,mem), opcode));
  11265             soc_schan_dump(unit, &schan_msg, 1 + entry_dw + resp_word);
  11266             rv = SOC_E_INTERNAL;
  11267             return rv;
  11268         }
  11269     }
  11270     sal_memcpy(entry_data,
  11271                resp_word ? schan_msg.genresp.data : schan_msg.readresp.data,
  11272                entry_dw * sizeof (uint32));
  11273 #ifdef USE_VALGRIND_CLIENT_REQUESTS
  11274                VALGRIND_MAKE_MEM_DEFINED(entry_data, entry_dw * sizeof (uint32));
  11275 #endif /* USE_VALGRIND_CLIENT_REQUESTS */
  11276 
  11277 #ifdef HR3LITE_LPM_WAR
  11278     /* if target table is HR3-Lite's LPM, HIT bit is updated by HW from  
  11279      * LPM-HIT table and for HR3-Lite's LPM entry 32~63 this HIT bit needs 
  11280      * WAR to sync-up correct HIT from LPM-HIT entry 512~543.
  11281      */
  11282     if (soc_feature(unit, soc_feature_hr3_lite_lpm_shadow_hit) && 
  11283             NEED_HR3LITE_LPM_SHADOW(mem)) {
  11284         rv = _soc_mem_hr3_lpm_hit_shadow_update(unit, 
  11285                 mem, copyno, index, entry_data, array_index);
  11286     }
  11287 #endif  /* HR3LITE_LPM_WAR */
  11288 
  11289     return rv;
  11290 }
  11291 
  11292 /*
  11293  * Function: _soc_mem_read_tcam_to_dm_format
  11294  *
  11295  * Purpose:  On certain devices, data from TCAMs and the ETU block has to be
  11296  *           converted from X-Y format to D-M format.
  11297  */
  11298 STATIC void _soc_mem_read_tcam_to_dm_format(int unit, soc_mem_t mem, int copyno,
  11299                                             soc_mem_info_t *meminfo, uint32 flags,
  11300                                             void *entry_data)
  11301 {
  11302 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \
  11303     || defined(BCM_HURRICANE2_SUPPORT)
  11304     if (soc_feature(unit, soc_feature_xy_tcam_direct) &&
  11305         (meminfo->flags & SOC_MEM_FLAG_CAM) &&
  11306         (!(meminfo->flags & SOC_MEM_FLAG_EXT_CAM)) &&
  11307         (!(flags & SOC_MEM_DONT_CONVERT_XY2DM))) {
  11308 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 
  11309         _soc_mem_fp_global_mask_tcam_shift(unit, mem, entry_data, 0, 0);
  11310 #endif
  11311         _soc_mem_tcam_xy_to_dm(unit, mem, 1, entry_data, entry_data);
  11312     }
  11313 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */
  11314 
  11315 #ifdef BCM_TRIUMPH3_SUPPORT
  11316     /* convert X-Y data of esm external tcam table reads to D-M format */
  11317     if (soc_feature(unit, soc_feature_etu_support) &&
  11318         SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU) {
  11319 
  11320         uint32 key[SOC_MAX_MEM_FIELD_WORDS], mask[SOC_MAX_MEM_FIELD_WORDS];
  11321         soc_field_t key_field[4], mask_field[4];
  11322         int field_count=0, bit_length, word_length, i, word;
  11323 
  11324         switch (mem) {
  11325         case EXT_L2_ENTRY_TCAMm:
  11326         case EXT_L2_ENTRY_TCAM_WIDEm:
  11327         case EXT_IPV4_TCAMm:
  11328         case EXT_IPV6_64_TCAMm:
  11329         case EXT_IPV4_DEFIPm:
  11330         case EXT_IPV4_DEFIP_TCAMm:
  11331         case EXT_IPV4_UCASTm:
  11332         case EXT_IPV4_UCAST_TCAMm:
  11333         case EXT_IPV4_UCAST_WIDEm:
  11334         case EXT_IPV4_UCAST_WIDE_TCAMm:
  11335         case EXT_IPV6_64_DEFIPm:
  11336         case EXT_IPV6_64_DEFIP_TCAMm:
  11337         case EXT_ACL80_TCAMm:
  11338             key_field[0] = TDW0f;
  11339             mask_field[0] = TMW0f;
  11340             field_count = 1;
  11341             break;
  11342 
  11343         case EXT_IPV6_128_TCAMm:
  11344         case EXT_IPV6_128_DEFIPm:
  11345         case EXT_IPV6_128_DEFIP_TCAMm:
  11346         case EXT_IPV6_128_UCASTm:
  11347         case EXT_IPV6_128_UCAST_TCAMm:
  11348         case EXT_IPV6_128_UCAST_WIDEm:
  11349         case EXT_IPV6_128_UCAST_WIDE_TCAMm:
  11350         case EXT_ACL160_TCAMm:
  11351         case EXT_ACL144_TCAM_L2m:
  11352         case EXT_ACL144_TCAM_IPV4m:
  11353         case EXT_ACL144_TCAM_IPV6m:
  11354             key_field[0] = TDW0f;
  11355             key_field[1] = TDW1f;
  11356             mask_field[0] = TMW0f;
  11357             mask_field[1] = TMW1f;
  11358             field_count = 2;
  11359             break;
  11360 
  11361         case EXT_ACL288_TCAM_L2m:
  11362         case EXT_ACL288_TCAM_IPV4m:
  11363         case EXT_ACL432_TCAM_DATA_L2_IPV4m:
  11364         case EXT_ACL320_TCAMm:
  11365             key_field[0] = TDW0f;
  11366             key_field[1] = TDW1f;
  11367             key_field[2] = TDW2f;
  11368             key_field[3] = TDW3f;
  11369             mask_field[0] = TMW0f;
  11370             mask_field[1] = TMW1f;
  11371             mask_field[2] = TMW2f;
  11372             mask_field[3] = TMW3f;
  11373             field_count = 4;
  11374             break;
  11375 
  11376         
  11377 #ifdef fix_later
  11378         case EXT_ACL360_TCAM_DATA_IPV6_SHORTm:
  11379         case EXT_ACL432_TCAM_DATA_IPV6_LONGm:
  11380         case EXT_ACL432_TCAM_DATA_L2_IPV6m:
  11381         case EXT_ACL432_TCAM_MASKm:
  11382         case EXT_ACL360_TCAM_MASK_IPV6_SHORTm:
  11383         case EXT_ACL432_TCAM_MASK_IPV6_LONGm:
  11384         case EXT_ACL432_TCAM_MASK_L2_IPV6m:
  11385         case EXT_ACL480_TCAM_DATAm:
  11386         case EXT_ACL480_TCAM_MASKm:
  11387             key_field[0] = TDW0f;
  11388             key_field[1] = TDW1f;
  11389             key_field[2] = TDW2f;
  11390             key_field[3] = TDW3f;
  11391             mask_field[0] = TMW0f;
  11392             mask_field[1] = TMW1f;
  11393             mask_field[2] = TMW2f;
  11394             mask_field[3] = TMW3f;
  11395             field_count = 6;
  11396             break;
  11397 #endif
  11398         }
  11399         for (i = 0; i < field_count; i++) {
  11400             soc_mem_field_get(unit, mem, entry_data, key_field[i], key);
  11401             soc_mem_field_get(unit, mem, entry_data, mask_field[i], mask);
  11402             bit_length = soc_mem_field_length(unit, mem, key_field[i]);
  11403             word_length = (bit_length + 31) / 32;
  11404             for (word = 0; word < word_length; word++) {
  11405                 /* save data word first */
  11406                 mask[word] = ~(key[word] | mask[word]);
  11407             }
  11408             if ((bit_length & 0x1f) != 0) {
  11409                 mask[word - 1] &= (1 << (bit_length & 0x1f)) - 1;
  11410             }
  11411             soc_mem_field_set(unit, mem, entry_data, mask_field[i], mask);
  11412             soc_mem_field_set(unit, mem, entry_data, key_field[i], key);
  11413         }
  11414     }
  11415 #endif /* BCM_TRIUMPH3_SUPPORT */
  11416 
  11417 }
  11418 
  11419 void soc_mem_parity_field_clear(int unit, int mem,
  11420                             void* entry_data, void *entry_data_cache)
  11421 {
  11422     /* Heuristic to clear parity/ecc bits */
  11423     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITYf);
  11424     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITYf);
  11425     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_0f);
  11426     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_1f);
  11427     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_2f);
  11428     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_3f);
  11429     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_Af);
  11430     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_Bf);
  11431     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_LOWERf);
  11432     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_UPPERf);
  11433     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_P0f);
  11434     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_P1f);
  11435     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_P2f);
  11436     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_P3f);
  11437     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PBM_PARITY_P0f);
  11438     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PBM_PARITY_P1f);
  11439     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PBM_PARITY_P2f);
  11440     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PBM_PARITY_P3f);
  11441     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_EGR_VLAN_STG_PARITY_P0f);
  11442     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_EGR_VLAN_STG_PARITY_P1f);
  11443     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_EGR_VLAN_STG_PARITY_P2f);
  11444     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_EGR_VLAN_STG_PARITY_P3f);
  11445     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCf);
  11446     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_FIELDf);
  11447     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_0f);
  11448     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_1f);
  11449     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_2f);
  11450     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_3f);
  11451     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_4f);
  11452     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCPf);
  11453     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP0f);
  11454     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP1f);
  11455     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP2f);
  11456     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP3f);
  11457     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP4f);
  11458     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP5f);
  11459     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP6f);
  11460     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP7f);
  11461     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_0f);
  11462     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_1f);
  11463     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_2f);
  11464     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_3f);
  11465     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_4f);
  11466     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC0f);
  11467     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC1f);
  11468     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC2f);
  11469     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC3f);
  11470     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY0f);
  11471     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY1f);
  11472     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY2f);
  11473     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY3f);
  11474     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_0f);
  11475     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_1f);
  11476     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_2f);
  11477     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_3f);
  11478     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_4f);
  11479     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PBM_PARITY_P0f);
  11480     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PBM_PARITY_P1f);
  11481     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PBM_PARITY_P2f);
  11482     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PBM_PARITY_P3f);
  11483     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_P0f);
  11484     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_P1f);
  11485     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_P2f);
  11486     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_PARITY_P3f);
  11487     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_EGR_VLAN_STG_PARITY_P0f);
  11488     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_EGR_VLAN_STG_PARITY_P1f);
  11489     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_EGR_VLAN_STG_PARITY_P2f);
  11490     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EVEN_EGR_VLAN_STG_PARITY_P3f);
  11491     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_P0f);
  11492     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_P1f);
  11493     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_P2f);
  11494     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_P3f);
  11495     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_P4f);
  11496     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_P5f);
  11497     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_P6f);
  11498     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_P7f);
  11499     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_P0f);
  11500     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_P1f);
  11501     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_P2f);
  11502     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_P3f);
  11503     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_P4f);
  11504     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_P5f);
  11505     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_P6f);
  11506     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_P7f);
  11507     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_P0f);
  11508     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_P1f);
  11509     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_P2f);
  11510     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_P3f);
  11511     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_P4f);
  11512     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_P5f);
  11513     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_P6f);
  11514     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_P7f);
  11515     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_PBM_0f);
  11516     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_PBM_1f);
  11517     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_PBM_2f);
  11518     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_PBM_3f);
  11519     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_PBM_0f);
  11520     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_PBM_1f);
  11521     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_PBM_2f);
  11522     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_PBM_3f);
  11523     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_PBM_0f);
  11524     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_PBM_1f);
  11525     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_PBM_2f);
  11526     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_PBM_3f);
  11527     _SOC_ENTRY_PARITY_CLEAR(unit, mem, TCAM_PARITY_KEYf);
  11528     _SOC_ENTRY_PARITY_CLEAR(unit, mem, TCAM_PARITY_MASKf);
  11529     _SOC_ENTRY_PARITY_CLEAR(unit, mem, TCAM_PARITY_MASK_UPRf);
  11530     _SOC_ENTRY_PARITY_CLEAR(unit, mem, TCAM_PARITY_MASK_LWRf);
  11531     _SOC_ENTRY_PARITY_CLEAR(unit, mem, TCAM_PARITY_KEY_UPRf);
  11532     _SOC_ENTRY_PARITY_CLEAR(unit, mem, TCAM_PARITY_KEY_LWRf);
  11533     _SOC_ENTRY_PARITY_CLEAR(unit, mem, TCAM_PARITY_KEY1f);
  11534     _SOC_ENTRY_PARITY_CLEAR(unit, mem, TCAM_PARITY_KEY0f);
  11535     _SOC_ENTRY_PARITY_CLEAR(unit, mem, TCAM_PARITY_MASK1f);
  11536     _SOC_ENTRY_PARITY_CLEAR(unit, mem, TCAM_PARITY_MASK0f);
  11537     _SOC_ENTRY_PARITY_CLEAR(unit, mem, LWR_ECC0f);
  11538     _SOC_ENTRY_PARITY_CLEAR(unit, mem, LWR_ECC1f);
  11539     _SOC_ENTRY_PARITY_CLEAR(unit, mem, LWR_ECCP0f);
  11540     _SOC_ENTRY_PARITY_CLEAR(unit, mem, LWR_ECCP1f);
  11541     _SOC_ENTRY_PARITY_CLEAR(unit, mem, LWR_PARITY0f);
  11542     _SOC_ENTRY_PARITY_CLEAR(unit, mem, LWR_PARITY1f);
  11543     _SOC_ENTRY_PARITY_CLEAR(unit, mem, LWR_TCAM_PARITY_MASKf);
  11544     _SOC_ENTRY_PARITY_CLEAR(unit, mem, LWR_TCAM_PARITY_KEYf);
  11545     _SOC_ENTRY_PARITY_CLEAR(unit, mem, UPR_TCAM_PARITY_MASKf);
  11546     _SOC_ENTRY_PARITY_CLEAR(unit, mem, UPR_TCAM_PARITY_KEYf);
  11547 
  11548     /* Clear hit bits */
  11549     _SOC_ENTRY_PARITY_CLEAR(unit, mem, HITf);
  11550     _SOC_ENTRY_PARITY_CLEAR(unit, mem, HIT0f);
  11551     _SOC_ENTRY_PARITY_CLEAR(unit, mem, HIT1f);
  11552     _SOC_ENTRY_PARITY_CLEAR(unit, mem, HIT_0f);
  11553     _SOC_ENTRY_PARITY_CLEAR(unit, mem, HIT_1f);
  11554     _SOC_ENTRY_PARITY_CLEAR(unit, mem, HIT_2f);
  11555     _SOC_ENTRY_PARITY_CLEAR(unit, mem, HIT_3f);
  11556     _SOC_ENTRY_PARITY_CLEAR(unit, mem, HITDA_0f);
  11557     _SOC_ENTRY_PARITY_CLEAR(unit, mem, HITDA_1f);
  11558     _SOC_ENTRY_PARITY_CLEAR(unit, mem, HITDA_2f);
  11559     _SOC_ENTRY_PARITY_CLEAR(unit, mem, HITDA_3f);
  11560     _SOC_ENTRY_PARITY_CLEAR(unit, mem, HITSA_0f);
  11561     _SOC_ENTRY_PARITY_CLEAR(unit, mem, HITSA_1f);
  11562     _SOC_ENTRY_PARITY_CLEAR(unit, mem, HITSA_2f);
  11563     _SOC_ENTRY_PARITY_CLEAR(unit, mem, HITSA_3f);
  11564     _SOC_ENTRY_PARITY_CLEAR(unit, mem, HITDAf);
  11565     _SOC_ENTRY_PARITY_CLEAR(unit, mem, HITSAf); 
  11566     _SOC_ENTRY_PARITY_CLEAR(unit, mem, B0_HITf); 
  11567     _SOC_ENTRY_PARITY_CLEAR(unit, mem, B1_HITf); 
  11568     _SOC_ENTRY_PARITY_CLEAR(unit, mem, L3_HIT_DCMf); 
  11569     _SOC_ENTRY_PARITY_CLEAR(unit, mem, L3_HIT_PMf);
  11570     _SOC_ENTRY_PARITY_CLEAR(unit, mem, HIT_BITSf);
  11571     _SOC_ENTRY_PARITY_CLEAR(unit, mem, LWR_HIT0f);
  11572     _SOC_ENTRY_PARITY_CLEAR(unit, mem, LWR_HIT1f);
  11573     /* Clear hardware-modified fields in meter tables  */
  11574     _SOC_ENTRY_PARITY_CLEAR(unit, mem, BUCKETCOUNTf);
  11575     _SOC_ENTRY_PARITY_CLEAR(unit, mem, REFRESHCOUNTf);
  11576     
  11577     /* Clear parity/ecc bits on svm_meter_table */
  11578     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_EXCESSf);
  11579     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_EXCESSf);
  11580     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_EXCESSf);
  11581     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_COMMITTEDf);
  11582     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_COMMITTEDf);
  11583     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_COMMITTEDf);
  11584     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_LRNf);
  11585     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_LRNf);
  11586     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_LRNf);
  11587     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECCP_CONFIGf);
  11588     _SOC_ENTRY_PARITY_CLEAR(unit, mem, PARITY_CONFIGf);
  11589     _SOC_ENTRY_PARITY_CLEAR(unit, mem, ECC_CONFIGf);
  11590     /* Clear hardware-modified fields in svm_meter_table */
  11591     _SOC_ENTRY_PARITY_CLEAR(unit, mem, LRNf);         /* LAST_REFRESH_NUMBERf */
  11592     _SOC_ENTRY_PARITY_CLEAR(unit, mem, COMMITTEDf);   /* COMMITTED_BUCKETCOUNTf */
  11593     _SOC_ENTRY_PARITY_CLEAR(unit, mem, EXCESSf);      /* EXCESS_BUCKETCOUNTf */
  11594 }
  11595 
  11596 /*
  11597  * Function: _soc_mem_read_cache_check_clear
  11598  *
  11599  * Purpose:  Called from _soc_mem_read.  After a read has accessed the cache,
  11600  *           some cleanup may be necessary.  Perform that here.
  11601  */
  11602 STATIC void
  11603 _soc_mem_read_cache_check_clear(int unit, int mem, int index, int copyno,
  11604                                 void *entry_data, void *entry_data_cache)
  11605 {
  11606 #ifdef INCLUDE_TCL
  11607     int entry_dw = soc_mem_entry_words(unit, mem);
  11608 #ifdef BCM_TOMAHAWK3_SUPPORT
  11609     uint16 dev_id;
  11610     uint8  rev_id;
  11611 
  11612     soc_cm_get_id(unit, &dev_id, &rev_id);
  11613     if (dev_id == BCM56983_DEVICE_ID) {
  11614         return;
  11615     }
  11616 #endif
  11617     /* Some exceptions */
  11618     if ((SOC_IS_KATANA2(unit) || SOC_IS_TD_TT(unit) ||
  11619         SOC_IS_TD2_TT2(unit)) && (mem == EGR_VLANm)) {
  11620         return;
  11621     }
  11622 
  11623     /* Heuristic to check if entry is valid */
  11624     _SOC_ENTRY_VALID_CHECK(unit, mem, VALIDf);
  11625     _SOC_ENTRY_VALID_CHECK(unit, mem, VALID_0f);
  11626     _SOC_ENTRY_VALID_CHECK(unit, mem, BASE_VALIDf);
  11627     _SOC_ENTRY_VALID_CHECK(unit, mem, BASE_VALID_0f);
  11628 
  11629     soc_mem_parity_field_clear(unit, mem, entry_data, entry_data_cache);
  11630 
  11631     if (sal_memcmp(entry_data_cache, entry_data,
  11632                    entry_dw * sizeof (uint32)) != 0) {
  11633         if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityError, unit)) {
  11634             LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  11635                                 "soc_mem_read unit %d: %s.%s[%d]: cache: "),
  11636                      unit, SOC_MEM_NAME(unit, mem),
  11637                      SOC_BLOCK_NAME(unit, copyno), index));
  11638             soc_mem_entry_dump(unit, mem, entry_data_cache,
  11639                                BSL_ERROR|BSL_LS_SOC_SOCMEM);
  11640 
  11641             LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  11642                                 "\n")));
  11643             LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  11644                                 "soc_mem_read unit %d: %s.%s[%d]: Device: "),
  11645                      unit, SOC_MEM_NAME(unit, mem),
  11646                      SOC_BLOCK_NAME(unit, copyno), index));
  11647             soc_mem_entry_dump(unit, mem, entry_data, BSL_ERROR|BSL_LS_SOC_SOCMEM);
  11648             LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  11649                                 "\n")));
  11650         }
  11651 
  11652     }
  11653 #endif
  11654 }
  11655 
  11656 
  11657 /*
  11658  * Function:
  11659  *    _soc_mem_read
  11660  * Purpose:
  11661  *    Read a memory internal to the SOC.
  11662  * Notes:
  11663  *    GBP/CBP memory should only accessed when MMU is in DEBUG mode.
  11664  */
  11665 STATIC int
  11666 _soc_mem_read(int unit, uint32 flags, soc_mem_t mem,
  11667               /* in memory arrays this is the element index in the array, otherwise 0 */
  11668               unsigned array_index,
  11669               int copyno, int index, void *entry_data)
  11670 {
  11671     soc_mem_info_t *meminfo;
  11672     int index2;
  11673     int rv, rv2 = SOC_E_NONE;
  11674     uint32 entry_data_cache[SOC_MAX_MEM_FIELD_WORDS];
  11675     uint32 cache_consistency_check = 0;
  11676     int ok = TRUE;
  11677     int entry_num_max = 0;
  11678 #ifdef BCM_TOMAHAWK3_SUPPORT
  11679     int j = 0, k = 0, l = 0;
  11680     uint16 dev_id;
  11681     uint8 rev_id;
  11682     int acc_type;
  11683     int dw = 0;
  11684     uint32 *entry = NULL;
  11685     void *entry_data1;
  11686     int entry_size;
  11687 #endif
  11688     SOC_MEM_ALIAS_TO_ORIG(unit,mem);
  11689 
  11690     if (!soc_mem_is_valid(unit, mem)) {
  11691         return SOC_E_MEMORY;
  11692     }
  11693 
  11694 #ifdef BCM_SAND_SUPPORT
  11695     /*
  11696      * Write onto S-Channel "memory read" command packet consisting of header
  11697      * word + address word, and read back header word + soc_mem_entry_words() data words.
  11698      */
  11699     if (soc_mem_entry_words(unit, mem) + 2 > CMIC_SCHAN_WORDS(unit)) {
  11700         if (SOC_IS_SAND(unit))
  11701         {
  11702             rv = _soc_mem_array_wide_read(unit, flags, mem, array_index, copyno, index, entry_data);
  11703                 return rv;
  11704             }
  11705         }
  11706 #endif
  11707 
  11708     if (mem == FP_GLOBAL_MASK_TCAMm ||  mem == FP_TCAMm ||
  11709         mem == EFP_TCAMm || mem == VFP_TCAMm ||
  11710         mem == FP_GLOBAL_MASK_TCAM_Xm || mem == FP_GLOBAL_MASK_TCAM_Ym ||
  11711         mem == FP_GM_FIELDSm) {
  11712         if (_soc_mem_read_tcam_is_invalid(unit, mem, index) == TRUE) {
  11713             return SOC_E_NONE;
  11714         }
  11715     }
  11716 
  11717     meminfo = &SOC_MEM_INFO(unit, mem);
  11718 
  11719     if (copyno == MEM_BLOCK_ANY || copyno == SOC_CORE_ALL) {
  11720         copyno = SOC_MEM_BLOCK_ANY(unit, mem);
  11721     }
  11722 
  11723     if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) {
  11724         LOG_WARN(BSL_LS_SOC_SOCMEM,
  11725                  (BSL_META_U(unit,
  11726                              "soc_mem_read: invalid block %d for memory %s\n"),
  11727                   copyno, SOC_MEM_NAME(unit, mem)));
  11728         return SOC_E_PARAM;
  11729     }
  11730 
  11731     if (_soc_mem_read_tr3_tunnel_is_invalid(unit, mem, index, copyno) == TRUE) {
  11732         return SOC_E_NONE;
  11733     }
  11734 
  11735     /*
  11736      * When checking index, check for 0 instead of soc_mem_index_min.
  11737      * Diagnostics need to read/write index 0 of Strata ARL and GIRULE.
  11738      */
  11739     if ((flags & SOC_MEM_DONT_MAP_INDEX) &&
  11740         (mem == L3_DEFIPm ||
  11741          mem == L3_DEFIP_LEVEL1m ||
  11742          mem == L3_DEFIP_ONLYm ||
  11743          mem == L3_DEFIP_DATA_ONLYm ||
  11744          mem == L3_DEFIP_HIT_ONLY_Xm ||
  11745          mem == L3_DEFIP_HIT_ONLY_Ym ||
  11746          mem == L3_DEFIP_HIT_ONLYm ||
  11747          mem == L3_DEFIP_PAIR_128m ||
  11748          mem == L3_DEFIP_PAIR_LEVEL1m ||
  11749          mem == L3_DEFIP_PAIR_128_ONLYm ||
  11750          mem == L3_DEFIP_PAIR_128_DATA_ONLYm ||
  11751          mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm ||
  11752          mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym ||
  11753          mem == L3_DEFIP_PAIR_128_HIT_ONLYm)) {
  11754         if (_soc_mem_defip_index_is_invalid(unit, mem, index) == TRUE) {
  11755             return SOC_E_PARAM;
  11756         }
  11757     } else {
  11758         entry_num_max = soc_mem_index_max(unit, mem);
  11759 
  11760         if (index < 0 || index > entry_num_max) {
  11761             if (!(SOC_DEFIP_HOLE_RANGE_CHECK(unit, mem, index))) {
  11762             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  11763                       (BSL_META_U(unit,
  11764                                   "soc_mem_read: invalid index %d for memory %s\n"),
  11765                        index, SOC_MEM_NAME(unit, mem)));
  11766             return SOC_E_PARAM;
  11767         }
  11768     }
  11769     }
  11770 
  11771     if (_soc_mem_read_hercules(unit, mem, copyno, index,
  11772                                entry_data, &rv) == TRUE) {
  11773         return rv;
  11774     }
  11775 
  11776     rv = SOC_E_NONE;
  11777 
  11778 #ifdef ALPM_ENABLE
  11779     if (mem == L3_DEFIP_ALPM_ECCm || mem == L3_DEFIP_ALPM_IPV4m ||
  11780         mem == L3_DEFIP_ALPM_IPV4_1m || mem == L3_DEFIP_ALPM_IPV6_64m ||
  11781         mem == L3_DEFIP_ALPM_IPV6_128m || mem == L3_DEFIP_ALPM_IPV6_64_1m ||
  11782         mem == L3_DEFIP_ALPM_RAWm) {
  11783         SOC_ALPM_LPM_LOCK(unit);
  11784     } else
  11785 #endif
  11786     {
  11787     MEM_LOCK(unit, mem);
  11788     }
  11789     _soc_mem_read_tr3_esm_lock(unit, copyno);
  11790 
  11791     if (_soc_mem_read_cache_attempt(unit, flags, mem, copyno, index,
  11792                                     array_index, entry_data,
  11793                                     entry_data_cache,
  11794                                     &cache_consistency_check)) {
  11795         ok = FALSE;
  11796     }
  11797 #ifdef CRASH_RECOVERY_SUPPORT
  11798 /*     Use crash recovery defined callback for access*/
  11799     if (BCM_UNIT_DO_HW_READ_WRITE(unit))
  11800     {
  11801         if(Hw_Log_List[unit].Access_cb.mem_read)
  11802         {
  11803             if(ok && Hw_Log_List[unit].Access_cb.mem_read(unit, mem,
  11804                                                                        array_index, copyno,
  11805                                                                        index, entry_data)) {
  11806             ok = FALSE;
  11807             }
  11808         }
  11809     }
  11810     /* enable hw reads and writes */
  11811 #endif /* CRASH_RECOVERY_SUPPORT */
  11812 
  11813     if (ok && _soc_mem_read_tr3_read_attempt(unit, mem, index, copyno,
  11814                                              entry_data, &rv) == TRUE) {
  11815         ok = FALSE;
  11816     }
  11817 
  11818     if (ok && _soc_mem_read_td2_xpipe_tbl_attempt(unit, mem, index, entry_data,
  11819                                                   &rv) == TRUE) {
  11820         ok = FALSE;
  11821     }
  11822 
  11823     if (ok) {
  11824         index2 = index;
  11825         if (!(flags & SOC_MEM_DONT_MAP_INDEX)) {
  11826             _soc_mem_read_defip_index_map(unit, mem, index, &index2);
  11827         }
  11828 
  11829 #ifdef BCM_TOMAHAWK3_SUPPORT
  11830         /* For 56983 Lower die SKU, the data split is converted into 4 unique
  11831            reads and the data is ORed to get the final read value
  11832          */
  11833         soc_cm_get_id (unit, &dev_id, &rev_id);
  11834         acc_type =  SOC_MEM_ACC_TYPE(unit, mem);
  11835         if (acc_type == 14 && (dev_id == BCM56983_DEVICE_ID)) {
  11836             dw = soc_mem_entry_words(unit, mem);
  11837             entry_size = dw * sizeof(uint32);
  11838             entry = sal_alloc(entry_size, "entry_size");
  11839             sal_memset((void *)entry, 0, sizeof(uint32) * dw);
  11840             sal_memset(entry_data, 0, sizeof(uint32) * dw);
  11841             entry_data1 = entry;
  11842             l = sizeof(uint32);
  11843             for (j = 0; j < 4; j++) {
  11844                 switch(j) {
  11845                     case 0 : acc_type = 0;
  11846                              break;
  11847                     case 1 : acc_type = 1;
  11848                              break;
  11849                     case 2 : acc_type = 6;
  11850                              break;
  11851                     case 3 : acc_type = 7;
  11852                              break;
  11853                 }
  11854                 rv2 = _soc_th3_mem_read_schan_msg_send(unit, flags, mem, copyno, index,
  11855                                                   entry_data1, array_index, index2, acc_type);
  11856                 if (SOC_SUCCESS(rv2)) {
  11857                     _soc_mem_read_tcam_to_dm_format(unit, mem, copyno, meminfo, flags,
  11858                                                     entry_data1);
  11859                 }
  11860                 for (k = 0; k < dw; k++) {
  11861                     *(uint32 *)((uint8 *)entry_data + l*k) =
  11862                             *(uint32 *)((uint8 *)entry_data + l*k) |
  11863                             *(uint32 *)((uint8 *)entry_data1 + l*k);
  11864                     *(uint32 *) ((uint8 *)entry_data1 + l*k) = 0;
  11865                 }
  11866             }
  11867           
  11868             if (entry) {
  11869                 sal_free(entry);
  11870             }
  11871         } else
  11872 #endif
  11873         {
  11874 
  11875             rv2 = _soc_mem_read_schan_msg_send(unit, flags, mem, copyno, index,
  11876                                               entry_data, array_index, index2);
  11877             if (SOC_SUCCESS(rv2)) {
  11878                 _soc_mem_read_tcam_to_dm_format(unit, mem, copyno, meminfo, flags,
  11879                                                 entry_data);
  11880             }
  11881         }
  11882     }
  11883 
  11884     /* All done.  Cleanup time. */
  11885 
  11886     _soc_mem_read_tr3_esm_unlock(unit, copyno);
  11887 #ifdef ALPM_ENABLE
  11888     if (mem == L3_DEFIP_ALPM_ECCm || mem == L3_DEFIP_ALPM_IPV4m ||
  11889         mem == L3_DEFIP_ALPM_IPV4_1m || mem == L3_DEFIP_ALPM_IPV6_64m ||
  11890         mem == L3_DEFIP_ALPM_IPV6_128m || mem == L3_DEFIP_ALPM_IPV6_64_1m ||
  11891         mem == L3_DEFIP_ALPM_RAWm) {
  11892         SOC_ALPM_LPM_UNLOCK(unit);
  11893     } else
  11894 #endif
  11895     {
  11896     MEM_UNLOCK(unit, mem);
  11897     }
  11898 
  11899 
  11900     if (cache_consistency_check) {
  11901         _soc_mem_read_cache_check_clear(unit, mem, index, copyno, entry_data,
  11902                                         entry_data_cache);
  11903     }
  11904 
  11905     if (NULL != meminfo->snoop_cb) {
  11906         if (SOC_MEM_SNOOP_READ & meminfo->snoop_flags) {
  11907             meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_READ,
  11908                               copyno, index, index, entry_data,
  11909                               meminfo->snoop_user_data);
  11910         }
  11911         if (SOC_MEM_SNOOP_READ_COUNT & meminfo->snoop_flags) {
  11912             meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_READ_COUNT,
  11913                               copyno, index, index, entry_data,
  11914                               meminfo->snoop_user_data);
  11915         }
  11916     }
  11917 
  11918     if (bsl_check(bslLayerSoc, bslSourceMem, bslSeverityNormal, unit)) {
  11919         LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  11920                             "soc_mem_read unit %d: %s.%s[%d]: "),
  11921                  unit, SOC_MEM_NAME(unit, mem),
  11922                  SOC_BLOCK_NAME(unit, copyno), index));
  11923         soc_mem_entry_dump(unit, mem, entry_data, BSL_INFO|BSL_LS_SOC_SOCMEM);
  11924         LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  11925                             "\n")));
  11926     }
  11927 
  11928     if (ok && (flags & SOC_MEM_SCHAN_ERR_RETURN)) {
  11929         return rv2; /* we executed _soc_mem_read_schan_msg_send and we need to
  11930                        return NACK in case of failure */
  11931     } else {
  11932         if ((SOC_FAILURE(rv2)) && cache_consistency_check) {
  11933             sal_memcpy(entry_data, entry_data_cache,
  11934                        soc_mem_entry_words(unit, mem) * sizeof (uint32));
  11935         }
  11936         /* we did not execute _soc_mem_read_schan_msg_send */
  11937         return rv;
  11938     }
  11939 }
  11940 
  11941 /* Wrapper routine with a 'flags' param for better access control */
  11942 int
  11943 soc_mem_read_extended(int unit, uint32 flags, soc_mem_t mem,
  11944                       /* in memory arrays this is the element index in the array, otherwise 0 */
  11945                       unsigned array_index, int copyno,
  11946                       int index, void *entry_data)
  11947 {
  11948     DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE));
  11949 
  11950     return _soc_mem_read(unit, flags, mem, array_index, copyno, index,
  11951                          entry_data);
  11952 }
  11953 
  11954 /*
  11955  * Function:
  11956  *    soc_mem_pipe_select_read
  11957  * Purpose:
  11958  *    Read a memory internal to the SOC.
  11959  * Notes:
  11960  *    GBP/CBP memory should only accessed when MMU is in DEBUG mode.
  11961  */
  11962 int
  11963 soc_mem_pipe_select_read(int unit,
  11964                          uint32 flags,
  11965                          soc_mem_t mem,
  11966                          int copyno,
  11967                          int acc_type,
  11968                          int index,
  11969                          void *entry_data)
  11970 {
  11971     schan_msg_t schan_msg;
  11972     int entry_dw = soc_mem_entry_words(unit, mem);
  11973     soc_mem_info_t *meminfo;
  11974     int index_valid;
  11975     uint8 at;
  11976     int index2;
  11977     uint32 maddr;
  11978     int rv, allow_intr = 0;
  11979     int resp_word = 0;
  11980     int src_blk, dst_blk, data_byte_len;
  11981     int opcode, err;
  11982 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HELIX4_SUPPORT) || \
  11983     defined(BCM_KATANA2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || \
  11984     defined(BCM_GREYHOUND_SUPPORT)
  11985     uint8 *corrupt = NULL;
  11986 #endif
  11987     int entry_num_max = 0;
  11988 
  11989     if (!soc_feature(unit, soc_feature_two_ingress_pipes)) {
  11990         /* Not a relevant device */
  11991         return SOC_E_UNAVAIL;
  11992     }
  11993 
  11994     if (!soc_mem_is_valid(unit, mem)) {
  11995         return SOC_E_MEMORY;
  11996     }
  11997 
  11998     meminfo = &SOC_MEM_INFO(unit, mem);
  11999 
  12000     DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE));
  12001 
  12002     if (copyno == MEM_BLOCK_ANY) {
  12003         copyno = SOC_MEM_BLOCK_ANY(unit, mem);
  12004     }
  12005 
  12006     if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) {
  12007         LOG_WARN(BSL_LS_SOC_SOCMEM,
  12008                  (BSL_META_U(unit,
  12009                              "soc_mem_pipe_select_read: invalid block %d for memory %s\n"),
  12010                   copyno, SOC_MEM_NAME(unit, mem)));
  12011         return SOC_E_PARAM;
  12012     }
  12013 
  12014     /*
  12015      * When checking index, check for 0 instead of soc_mem_index_min.
  12016      * Diagnostics need to read/write index 0 of Strata ARL and GIRULE.
  12017      */
  12018     if ((flags & SOC_MEM_DONT_MAP_INDEX) &&
  12019         (mem == L3_DEFIPm ||
  12020          mem == L3_DEFIP_LEVEL1m ||
  12021          mem == L3_DEFIP_ONLYm ||
  12022          mem == L3_DEFIP_DATA_ONLYm ||
  12023          mem == L3_DEFIP_HIT_ONLY_Xm ||
  12024          mem == L3_DEFIP_HIT_ONLY_Ym ||
  12025          mem == L3_DEFIP_HIT_ONLYm ||
  12026          mem == L3_DEFIP_PAIR_128m ||
  12027          mem == L3_DEFIP_PAIR_LEVEL1m ||
  12028          mem == L3_DEFIP_PAIR_128_ONLYm ||
  12029          mem == L3_DEFIP_PAIR_128_DATA_ONLYm ||
  12030          mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm ||
  12031          mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym ||
  12032          mem == L3_DEFIP_PAIR_128_HIT_ONLYm)) {
  12033         if (_soc_mem_defip_index_is_invalid(unit, mem, index) == TRUE) {
  12034             return SOC_E_PARAM;
  12035         }
  12036     } else {
  12037         entry_num_max = soc_mem_index_max(unit, mem);
  12038 
  12039         index_valid = (index >= 0 &&
  12040                    index <= entry_num_max);
  12041 
  12042         if (!index_valid) {
  12043             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  12044                       (BSL_META_U(unit,
  12045                                   "soc_mem_pipe_select_read: invalid index %d for memory %s acc_type %d\n"),
  12046                        index, SOC_MEM_NAME(unit, mem), acc_type));
  12047             return SOC_E_PARAM;
  12048         }
  12049     }
  12050 
  12051 #ifdef BCM_TRIDENT2PLUS_SUPPORT
  12052     if (SOC_IS_TD2P_TT2P(unit)) {
  12053         if ((FP_TCAMm == mem) || (FP_GM_FIELDSm == mem)
  12054             || (FP_GLOBAL_MASK_TCAMm == mem)
  12055             || (FP_GLOBAL_MASK_TCAM_Xm == mem)
  12056             || (FP_GLOBAL_MASK_TCAM_Ym == mem)) {
  12057             if (_soc_mem_read_tcam_is_invalid(unit, mem, index) == TRUE) {
  12058                 return SOC_E_NONE;
  12059             }
  12060         }
  12061     }
  12062 #endif
  12063 
  12064     rv = SOC_E_NONE;
  12065 
  12066 #ifdef ALPM_ENABLE
  12067     if (mem == L3_DEFIP_ALPM_ECCm || mem == L3_DEFIP_ALPM_IPV4m ||
  12068         mem == L3_DEFIP_ALPM_IPV4_1m || mem == L3_DEFIP_ALPM_IPV6_64m ||
  12069         mem == L3_DEFIP_ALPM_IPV6_128m || mem == L3_DEFIP_ALPM_IPV6_64_1m ||
  12070         mem == L3_DEFIP_ALPM_RAWm) {
  12071         SOC_ALPM_LPM_LOCK(unit);
  12072     } else
  12073 #endif
  12074     {
  12075     MEM_LOCK(unit, mem);
  12076     }
  12077 
  12078     /* Setup S-Channel command packet */
  12079     schan_msg_clear(&schan_msg);
  12080 
  12081     src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit));
  12082     data_byte_len = 4;
  12083 #ifdef BCM_TRIDENT_SUPPORT
  12084     if (SOC_IS_TD_TT(unit)) {
  12085         if (mem == ESBS_PORT_TO_PIPE_MAPPINGm ||
  12086             mem == ISBS_PORT_TO_PIPE_MAPPINGm) {
  12087             data_byte_len = entry_dw * 4;
  12088         }
  12089     }
  12090 #endif /* BCM_TRIDENT_SUPPORT */
  12091 
  12092     index2 = index;
  12093 
  12094     
  12095 #if defined(BCM_TRIDENT2_SUPPORT)
  12096         if (SOC_IS_TD2_TT2(unit) &&
  12097             soc_feature(unit, soc_feature_l3_defip_map) &&
  12098             (mem == L3_DEFIPm ||
  12099              mem == L3_DEFIP_LEVEL1m ||
  12100              mem == L3_DEFIP_ONLYm ||
  12101              mem == L3_DEFIP_DATA_ONLYm ||
  12102              mem == L3_DEFIP_HIT_ONLY_Xm ||
  12103              mem == L3_DEFIP_HIT_ONLY_Ym ||
  12104              mem == L3_DEFIP_HIT_ONLYm ||
  12105              mem == L3_DEFIP_PAIR_128m ||
  12106              mem == L3_DEFIP_PAIR_LEVEL1m ||
  12107              mem == L3_DEFIP_PAIR_128_ONLYm ||
  12108              mem == L3_DEFIP_PAIR_128_DATA_ONLYm ||
  12109              mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm ||
  12110              mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym ||
  12111              mem == L3_DEFIP_PAIR_128_HIT_ONLYm)) {
  12112             if (!(flags & SOC_MEM_DONT_MAP_INDEX)) {
  12113                 index2 = soc_trident2_l3_defip_index_map(unit, mem, index);
  12114             }
  12115         }
  12116 #endif /* BCM_TRIDENT2_SUPPORT */
  12117     maddr = soc_mem_addr_get(unit, mem, 0, copyno, index2, &at);
  12118 #if defined(BCM_EXTND_SBUS_SUPPORT)
  12119     if (!soc_feature(unit, soc_feature_new_sbus_format) &&
  12120         (acc_type != 0)) {
  12121         /* Override ACC_TYPE in address */
  12122         maddr &= ~(_SOC_MEM_ADDR_ACC_TYPE_MASK <<
  12123                         _SOC_MEM_ADDR_ACC_TYPE_SHIFT);
  12124         maddr |= (acc_type & _SOC_MEM_ADDR_ACC_TYPE_MASK) <<
  12125             _SOC_MEM_ADDR_ACC_TYPE_SHIFT;
  12126     }
  12127 #endif /* BCM_EXTND_SBUS_SUPPORT */
  12128     schan_msg.readcmd.address = maddr;
  12129 
  12130     dst_blk = 0;
  12131 #if defined(BCM_EXTND_SBUS_SUPPORT)
  12132     if (soc_feature(unit, soc_feature_new_sbus_format)) {
  12133         dst_blk = SOC_BLOCK2SCH(unit, copyno);
  12134     } else
  12135 #endif
  12136     {
  12137 #if defined(BCM_XGS3_SWITCH_SUPPORT)
  12138         /* required on XGS3. Optional on other devices */
  12139         dst_blk = ((maddr >> SOC_BLOCK_BP) & 0xf) |
  12140             (((maddr >> SOC_BLOCK_MSB_BP) & 0x1) << 4);
  12141 #endif /* BCM_XGS3_SWITCH_SUPPORT */
  12142     }
  12143 
  12144     soc_schan_header_cmd_set(unit, &schan_msg.header, READ_MEMORY_CMD_MSG,
  12145                              dst_blk, src_blk, acc_type, data_byte_len, 0, 0);
  12146 
  12147     /*
  12148      * Write onto S-Channel "memory read" command packet consisting of header
  12149      * word + address word, and read back header word + entry_dw data words.
  12150      */
  12151     if (2 + entry_dw > CMIC_SCHAN_WORDS(unit)) {
  12152        LOG_WARN(BSL_LS_SOC_SOCMEM,
  12153                 (BSL_META_U(unit,
  12154                             "soc_mem_read: assert will fail for memory %s\n"),
  12155                  SOC_MEM_NAME(unit, mem)));
  12156     }
  12157     rv = soc_schan_op(unit, &schan_msg, 2, 1 + entry_dw + resp_word, allow_intr);
  12158     if (SOC_FAILURE(rv)) {
  12159 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_HELIX4_SUPPORT) || \
  12160     defined(BCM_KATANA2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) || \
  12161     defined(BCM_GREYHOUND_SUPPORT)
  12162         if (SOC_SER_CORRECTION_SUPPORT(unit)) {
  12163             /* Record error index for TCAM table */
  12164             if((SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) &&
  12165                (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM))) {
  12166                 corrupt = SOC_MEM_STATE(unit, mem).corrupt[copyno];
  12167                 if (corrupt != NULL) {
  12168                     TCAM_CORRUPT_MAP_SET(corrupt, index);
  12169                     LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
  12170                                 (BSL_META_U(unit,
  12171                                             "Mem[%s] index[%d] "
  12172                                             "TCAM parity error indicating bit is set.\n"),
  12173                                  SOC_MEM_NAME(unit, mem), index));
  12174                 }
  12175             }
  12176         }
  12177 #endif
  12178         goto done;
  12179     }
  12180 
  12181     soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL,
  12182                                 &err, NULL, NULL);
  12183     if (opcode != READ_MEMORY_ACK_MSG || err != 0) {
  12184         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  12185                   (BSL_META_U(unit,
  12186                               "soc_mem_pipe_select_read: Mem(%s) "
  12187                               "invalid S-Channel reply, expected READ_MEMORY_ACK:, opcode %d\n"),
  12188                               SOC_MEM_NAME(unit, mem), opcode));
  12189         soc_schan_dump(unit, &schan_msg, 1 + entry_dw + resp_word);
  12190         rv = SOC_E_INTERNAL;
  12191         goto done;
  12192     }
  12193 
  12194     sal_memcpy(entry_data,
  12195                resp_word ? schan_msg.genresp.data : schan_msg.readresp.data,
  12196                entry_dw * sizeof (uint32));
  12197 
  12198 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT)
  12199     if (soc_feature(unit, soc_feature_xy_tcam_direct) &&
  12200         (meminfo->flags & SOC_MEM_FLAG_CAM) &&
  12201         (!(meminfo->flags & SOC_MEM_FLAG_EXT_CAM)) &&
  12202         (!(flags & SOC_MEM_DONT_CONVERT_XY2DM))) {
  12203 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  12204         _soc_mem_fp_global_mask_tcam_shift(unit, mem, entry_data, 0, 0);
  12205 #endif
  12206         _soc_mem_tcam_xy_to_dm(unit, mem, 1, entry_data, entry_data);
  12207     }
  12208 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */
  12209 
  12210 done:
  12211 
  12212 #ifdef ALPM_ENABLE
  12213     if (mem == L3_DEFIP_ALPM_ECCm || mem == L3_DEFIP_ALPM_IPV4m ||
  12214         mem == L3_DEFIP_ALPM_IPV4_1m || mem == L3_DEFIP_ALPM_IPV6_64m ||
  12215         mem == L3_DEFIP_ALPM_IPV6_128m || mem == L3_DEFIP_ALPM_IPV6_64_1m ||
  12216         mem == L3_DEFIP_ALPM_RAWm) {
  12217         SOC_ALPM_LPM_UNLOCK(unit);
  12218     } else
  12219 #endif
  12220     {
  12221     MEM_UNLOCK(unit, mem);
  12222     }
  12223 
  12224     if (NULL != meminfo->snoop_cb) {
  12225         if (SOC_MEM_SNOOP_READ & meminfo->snoop_flags) {
  12226             meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_READ,
  12227                               copyno, index, index, entry_data,
  12228                               meminfo->snoop_user_data);
  12229         }
  12230         if (SOC_MEM_SNOOP_READ_COUNT & meminfo->snoop_flags) {
  12231             meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_READ_COUNT,
  12232                               copyno, index, index, entry_data,
  12233                               meminfo->snoop_user_data);
  12234         }
  12235     }
  12236 
  12237     if (bsl_check(bslLayerSoc, bslSourceMem, bslSeverityNormal, unit)) {
  12238         LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  12239                             "soc_mem_read unit %d: %s.%s[%d]: "),
  12240                  unit, SOC_MEM_NAME(unit, mem),
  12241                  SOC_BLOCK_NAME(unit, copyno), index));
  12242         soc_mem_entry_dump(unit, mem, entry_data, BSL_INFO|BSL_LS_SOC_SOCMEM);
  12243         LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  12244                             "\n")));
  12245     }
  12246 
  12247     return rv;
  12248 }
  12249 
  12250 #ifdef BCM_KATANA2_SUPPORT
  12251 STATIC int
  12252 _soc_mem_read_kt2(int unit,
  12253                   soc_mem_t mem,
  12254                   int copyno,
  12255                   int index,
  12256                   void *entry_data)
  12257 {
  12258     int rv = SOC_E_FAIL;
  12259 
  12260     uint32 rval;
  12261     uint16 dev_id;
  12262     uint8 rev_id;
  12263 
  12264     soc_cm_get_id(unit, &dev_id, &rev_id);
  12265     if (SOC_IS_KATANA2(unit) &&
  12266         (rev_id == BCM56450_B1_REV_ID) &&
  12267         (SOC_CONTROL(unit)->soc_flags & SOC_F_ALL_MODULES_INITED) &&
  12268         (mem == ING_PHYSICAL_PORT_TABLEm)) {
  12269 
  12270         READ_ING_Q_BEGINr(unit, &rval);
  12271         soc_reg_field_set(unit, ING_Q_BEGINr, &rval,
  12272                           ING_PHYSICAL_PORT_SBUS_WITH_PKT_DISABLEf, 1);
  12273         WRITE_ING_Q_BEGINr(unit, rval);
  12274         LOG_VERBOSE(BSL_LS_SOC_COMMON,
  12275                     (BSL_META_U(unit, "READ PKT_DISABLE=1\n")));
  12276 
  12277         rv = soc_mem_array_read(unit, mem, 0, copyno, index, entry_data);
  12278         soc_reg_field_set(unit, ING_Q_BEGINr, &rval,
  12279                           ING_PHYSICAL_PORT_SBUS_WITH_PKT_DISABLEf, 0);
  12280         WRITE_ING_Q_BEGINr(unit, rval);
  12281         LOG_VERBOSE(BSL_LS_SOC_COMMON,
  12282                     (BSL_META_U(unit, "READ PKT_DISABLE=0\n")));
  12283     } else {
  12284         return soc_mem_array_read(unit, mem, 0, copyno, index, entry_data);
  12285     }
  12286 
  12287     return rv;
  12288 }
  12289 #endif
  12290 
  12291 int
  12292 soc_mem_read(int unit, soc_mem_t mem, int copyno, int index, void *entry_data)
  12293 {
  12294     int rv;
  12295 #ifdef BCM_TRIDENT3_SUPPORT
  12296     soc_mem_t phy_mem;
  12297 #endif
  12298 
  12299 #ifdef BCM_TRIDENT3_SUPPORT
  12300     if (soc_feature(unit, soc_feature_flex_flow)) {
  12301         if (SOC_MEM_IS_VIEW(unit, mem)) {
  12302             rv = soc_mem_view_phy_mem_get(unit, mem, &phy_mem);
  12303             if (rv != SOC_E_NONE) {
  12304                 return rv;
  12305             }
  12306             mem = phy_mem;
  12307         }
  12308     }
  12309 #endif
  12310 
  12311     DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE));
  12312 
  12313     _SOC_MEM_REPLACE_MEM(unit, mem);
  12314 
  12315 #ifdef BCM_KATANA2_SUPPORT
  12316     if (SOC_IS_KATANA2(unit)) {
  12317         rv = _soc_mem_read_kt2(unit, mem, copyno, index, entry_data);
  12318     } else
  12319 #endif
  12320     {
  12321         rv = soc_mem_array_read(unit, mem, 0, copyno, index, entry_data);
  12322     }
  12323 
  12324     return rv;
  12325 }
  12326 
  12327 int
  12328 soc_mem_read_no_cache(int unit,
  12329                                uint32 flags,
  12330                                soc_mem_t mem,
  12331                                unsigned array_index,
  12332                                int copyno,
  12333                                int index,
  12334                                void *entry_data)
  12335 {
  12336     int rv;
  12337 
  12338     _SOC_MEM_REPLACE_MEM(unit, mem);
  12339     flags |= SOC_MEM_DONT_USE_CACHE;
  12340 
  12341     DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE));
  12342 
  12343     MEM_LOCK(unit, mem);
  12344     rv = soc_mem_array_read_flags(unit, mem, array_index, copyno,
  12345                                   index, entry_data, flags);
  12346     MEM_UNLOCK(unit, mem);
  12347 
  12348     return rv;
  12349 }
  12350 
  12351 STATIC int
  12352 _soc_mem_trident_egr_vlan_read(int unit, soc_mem_t mem, unsigned array_index,
  12353                                int copyno, int index, void *entry_data, int *rv)
  12354 {
  12355 #ifdef BCM_TRIDENT_SUPPORT
  12356     uint32 entry_data_y[SOC_MAX_MEM_WORDS];
  12357     soc_pbmp_t pbmp_x, pbmp_y;
  12358 
  12359     if (!SOC_IS_TRIDENT(unit) && !SOC_IS_TITAN(unit)) {
  12360         return FALSE;
  12361     }
  12362 
  12363     if (mem != EGR_VLANm) {
  12364         return FALSE;
  12365     }
  12366 
  12367     soc_trident_pipe_select(unit, TRUE, 1); /* Y pipe */
  12368     *rv = _soc_mem_read(unit, 0, mem, array_index, copyno, index, entry_data_y);
  12369     if (SOC_FAILURE(*rv)) {
  12370         return TRUE;
  12371     }
  12372 
  12373     soc_trident_pipe_select(unit, TRUE, 0); /* X pipe */
  12374     *rv = _soc_mem_read(unit, 0, mem, array_index, copyno, index, entry_data);
  12375     if (SOC_FAILURE(*rv)) {
  12376         return TRUE;
  12377     }
  12378 
  12379     soc_mem_pbmp_field_get(unit, mem, entry_data, PORT_BITMAPf, &pbmp_x);
  12380     soc_mem_pbmp_field_get(unit, mem, entry_data_y, PORT_BITMAPf, &pbmp_y);
  12381     SOC_PBMP_OR(pbmp_x, pbmp_y);
  12382     soc_mem_pbmp_field_set(unit, mem, entry_data, PORT_BITMAPf, &pbmp_x);
  12383     soc_mem_pbmp_field_get(unit, mem, entry_data, UT_PORT_BITMAPf, &pbmp_x);
  12384     soc_mem_pbmp_field_get(unit, mem, entry_data_y, UT_PORT_BITMAPf, &pbmp_y);
  12385     SOC_PBMP_OR(pbmp_x, pbmp_y);
  12386     soc_mem_pbmp_field_set(unit, mem, entry_data, UT_PORT_BITMAPf, &pbmp_x);
  12387 
  12388     return TRUE;
  12389 #endif /* BCM_TRIDENT_SUPPORT */
  12390 
  12391     return FALSE;
  12392 }
  12393 
  12394 int
  12395 soc_mem_array_read_extended(int unit, uint32 flags, 
  12396                                   soc_mem_t mem, unsigned array_index,
  12397                                   int copyno, int index, void *entry_data)
  12398 {
  12399     int rv = SOC_E_NONE;
  12400 
  12401     /* Use user defined callback for access */
  12402     if (SOC_INFO(unit).reg_access.mem_read) {
  12403         return SOC_INFO(unit).reg_access.mem_read(unit, mem, array_index,
  12404                                                   copyno, index, entry_data);
  12405     }
  12406 
  12407     if (_soc_mem_trident_egr_vlan_read(unit, mem, array_index, copyno, index,
  12408                                        entry_data, &rv) == TRUE) {
  12409         return rv;
  12410     }
  12411 
  12412     return _soc_mem_read(unit, flags, mem, array_index, copyno, index, entry_data);
  12413 }
  12414 
  12415 int
  12416 soc_mem_read_physical_index(int unit, uint32 flags, soc_mem_t mem,
  12417                             int copyno, int index, void *entry_data)
  12418 {
  12419     int rv;
  12420 
  12421     _SOC_MEM_REPLACE_MEM(unit, mem);
  12422 
  12423     DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE));
  12424 
  12425 #ifdef BCM_KATANA2_SUPPORT
  12426     if (SOC_IS_KATANA2(unit)) {
  12427         rv = _soc_mem_read_kt2(unit, mem, copyno, index, entry_data);
  12428     } else
  12429 #endif
  12430     {
  12431         rv = soc_mem_array_read_extended(unit, flags, mem, 0, copyno,
  12432                                                index, entry_data);
  12433     }
  12434 
  12435     return rv;
  12436 }
  12437 
  12438 /*
  12439  * Function:    soc_mem_array_read
  12440  * Purpose:     Read a memory array internal to the SOC.
  12441  */
  12442 int
  12443 soc_mem_array_read(int unit, soc_mem_t mem, unsigned array_index,
  12444                    int copyno, int index, void *entry_data)
  12445 {
  12446 	int rv = SOC_E_NONE;
  12447 
  12448     DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE));
  12449 
  12450     /* Use user defined callback for access */
  12451     if (SOC_INFO(unit).reg_access.mem_read) {
  12452         return SOC_INFO(unit).reg_access.mem_read(unit, mem, array_index,
  12453                                                   copyno, index, entry_data);
  12454     }
  12455 
  12456     if (_soc_mem_trident_egr_vlan_read(unit, mem, array_index, copyno, index,
  12457                                        entry_data, &rv) == TRUE) {
  12458         return rv;
  12459     }
  12460 
  12461     return _soc_mem_read(unit, 0, mem, array_index, copyno, index, entry_data);
  12462 }
  12463 
  12464 /*
  12465  * Function:
  12466  *    soc_mem_read_range
  12467  * Purpose:
  12468  *    Read a range of chip's memory
  12469  */
  12470 
  12471 int
  12472 soc_mem_read_range(int unit, soc_mem_t mem, int copyno,
  12473                    int index_min, int index_max, void *buffer)
  12474 {
  12475     int rv;
  12476 
  12477     DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE));
  12478 
  12479     rv = soc_mem_read_range_multi_cmc(unit, mem, copyno, index_min, index_max, buffer, -1);
  12480 
  12481     return rv;
  12482 }
  12483 
  12484 /*
  12485  * Function:
  12486  *    soc_mem_read_range_multi_cmc
  12487  * Purpose:
  12488  *    Read a range of chip's memory
  12489  *    With multiple CMC/channel support
  12490  * Parameters:
  12491  *    buffer -- Pointer to block of sufficiently large memory.
  12492  * Notes:
  12493  *    Table DMA only works on tables whose entry is less than
  12494  *    SOC_MEM_DMA_MAX_DATA_BEATS words long.
  12495  *
  12496  *    Table DMA has a minimum transaction size of 4 words, so if the
  12497  *    table entry is 1 or 2 words, then the count of words is modified
  12498  *    to keep this alignment.  For the remainder of the entries, this
  12499  *    function reads in the remainder of the data through mem_read
  12500  *    without using DMA.
  12501  */
  12502 
  12503 int
  12504 soc_mem_read_range_multi_cmc(int unit, soc_mem_t mem, int copyno,
  12505                              int index_min, int index_max, void *buffer,
  12506                              int vchan)
  12507 {
  12508     int rc;
  12509     int force_cache = 0;
  12510 
  12511 #ifdef SOC_MEM_DEBUG_SPEED
  12512     int count = (index_max > index_min) ?
  12513       (index_max - index_min + 1) :
  12514       (index_min - index_max + 1);
  12515 
  12516     sal_usecs_t start_time;
  12517     int diff_time;
  12518 
  12519     start_time = sal_time_usecs();
  12520 #endif
  12521 
  12522 #ifdef SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT
  12523     force_cache = soc_mem_is_cache_only(unit, mem);
  12524 #endif /* SOC_L3_ECMP_PROTECTED_ACCESS_SUPPORT */
  12525 
  12526     /* COVERITY: Intentional, stack use of 4064 bytes */
  12527     /* coverity[stack_use_callee_max : FALSE] */
  12528     /* coverity[stack_use_return : FALSE] */
  12529 
  12530     DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE));
  12531 
  12532     if ((SOC_WARM_BOOT(unit) && SOC_CONTROL(unit)->dma_from_mem_cache) ||
  12533         (force_cache && !SOC_MEM_TEST_SKIP_CACHE(unit))) {
  12534         uint32 *cache;
  12535         uint8 *vmap;
  12536         int entry_dw, entry_sz, start, indexes;
  12537 
  12538         if (copyno == MEM_BLOCK_ANY) {
  12539             copyno = SOC_MEM_BLOCK_ANY(unit, mem);
  12540         }
  12541         cache = SOC_MEM_STATE(unit, mem).cache[copyno];
  12542         vmap = SOC_MEM_STATE(unit, mem).vmap[copyno];
  12543         if ((cache != NULL && force_cache) ||
  12544             (cache != NULL && CACHE_VMAP_TST(vmap, 0) &&
  12545             !_SOC_MEM_CHK_L2_MEM(mem) && !SOC_MEM_TEST_SKIP_CACHE(unit))) {
  12546             entry_dw = soc_mem_entry_words(unit, mem);
  12547             entry_sz = entry_dw * sizeof(uint32);
  12548             start = index_min > index_max ? index_max : index_min;
  12549             indexes = (index_max > index_min) ?
  12550                        (index_max - index_min + 1) : (index_min - index_max + 1);
  12551             sal_memcpy(buffer, cache + (start * entry_dw), indexes * entry_sz);
  12552             LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
  12553                         (BSL_META_U(unit,
  12554                                     "Mem[%s] "
  12555                                     "DMA data from cache.\n"),
  12556                          SOC_MEM_NAME(unit, mem)));
  12557             return SOC_E_NONE;
  12558         }
  12559     }
  12560     rc = soc_mem_array_read_range_multi_cmc(unit, mem, 0, copyno, index_min,
  12561                                             index_max, buffer, vchan);
  12562 #ifdef SOC_MEM_DEBUG_SPEED
  12563     diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time);
  12564     LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
  12565                 (BSL_META_U(unit,
  12566                             "Total dma read time: %d usecs, [%d nsecs per op]\n"),
  12567                  diff_time, diff_time*1000/count));
  12568 #endif
  12569     return rc;
  12570 }
  12571 
  12572 /*
  12573  * Function:
  12574  *    soc_mem_array_read_range
  12575  * Purpose:
  12576  *    Read a range of chip's memory
  12577  * Parameters:
  12578  *    buffer -- Pointer to block of sufficiently large memory.
  12579  *                  For Draco DMA operations, this memory must be
  12580  *                  DMA-able
  12581  * Notes:
  12582  *    Table DMA only works on tables whose entry is less than
  12583  *    SOC_MEM_DMA_MAX_DATA_BEATS words long.
  12584  *
  12585  *    Table DMA has a minimum transaction size of 4 words, so if the
  12586  *    table entry is 1 or 2 words, then the count of words is modified
  12587  *    to keep this alignment.  For the remainder of the entries, this
  12588  *    function reads in the remainder of the data through mem_read
  12589  *    without using DMA.
  12590  */
  12591 
  12592 int
  12593 soc_mem_array_read_range(int unit, soc_mem_t mem, unsigned array_index,
  12594                          int copyno, int index_min, int index_max, void *buffer)
  12595 {
  12596     int rv;
  12597 
  12598     DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE));
  12599 
  12600     rv = soc_mem_array_read_range_multi_cmc(unit, mem, array_index,
  12601                                             copyno, index_min, index_max, buffer, -1);
  12602 
  12603     return rv;
  12604 }
  12605 
  12606 #ifdef BROADCOM_DEBUG
  12607 
  12608 static int soc_dma_debug_property_get(int unit)
  12609 {
  12610     if (0 == _soc_dma_debug_op[unit]) {
  12611         _soc_dma_debug_enable[unit] =
  12612             soc_property_get(unit, "dma_mem_debug_enable", 0);
  12613         _soc_dma_debug_op[unit] = 1;
  12614     }
  12615     return _soc_dma_debug_enable[unit];
  12616 }
  12617 
  12618 #endif
  12619 
  12620 /*
  12621  * Function:
  12622  *    soc_mem_array_read_range_multi_cmc
  12623  * Purpose:
  12624  *    Read a range of chip's memory
  12625  *    With multiple CMC/channel support
  12626  */
  12627 
  12628 int
  12629 soc_mem_array_read_range_multi_cmc(int unit, soc_mem_t mem, unsigned array_index,
  12630                                    int copyno, int index_min, int index_max, void *buffer, int vchan)
  12631 {
  12632     int index;
  12633     int count;
  12634     void *buf;
  12635     uint16  dev_id;
  12636     uint8 rev_id;
  12637 #ifdef BROADCOM_DEBUG
  12638     shared_block_t *p = NULL;
  12639     int            length = 0;
  12640 #endif
  12641 #if defined(BCM_SAND_SUPPORT) && !defined(ADAPTER_SERVER_MODE)
  12642     int       rv;
  12643     int       entry_dw;
  12644     entry_dw = soc_mem_entry_words(unit, mem);
  12645 #endif
  12646 
  12647     if (!soc_mem_is_valid(unit, mem)) {
  12648         return SOC_E_MEMORY;
  12649     }
  12650 
  12651     if (copyno == MEM_BLOCK_ANY) {
  12652         copyno = SOC_MEM_BLOCK_ANY(unit, mem);
  12653     }
  12654     if (copyno == COPYNO_ALL) {
  12655         return SOC_E_INTERNAL;
  12656     }
  12657 
  12658     soc_cm_get_id(unit, &dev_id, &rev_id);
  12659 
  12660     DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE));
  12661 
  12662     assert(SOC_MEM_BLOCK_VALID(unit, mem, copyno));
  12663     assert(soc_mem_index_valid(unit, mem, index_min));
  12664 
  12665     if ((SOC_IS_DEFIP_HOLE_MEM(unit, mem))) {
  12666         assert(soc_r2p_defip_mem_index_valid(unit, mem, index_max));
  12667     } else {
  12668     assert(soc_mem_index_valid(unit, mem, index_max));
  12669     }
  12670 
  12671     assert(index_min <= index_max);
  12672     assert(buffer != NULL);
  12673 #ifdef BROADCOM_DEBUG
  12674     if (soc_dma_debug_property_get(unit)) {
  12675         p = (shared_block_t *) (((char*)buffer) -
  12676             ( (((char*)&(((shared_block_t*)0)->user_data[0]))) - ((char*)(shared_block_t*)0) ));
  12677         if (soc_cm_shared_good_range(unit, p)) {
  12678             if (SHARED_GOOD_START(p)  && SHARED_GOOD_END_DEBUG(p)) {
  12679                 length = WORDS2BYTES(soc_mem_entry_words(unit, mem)) *
  12680                          (index_max - index_min + 1);
  12681                 if (length > p->size) {
  12682                     LOG_WARN(BSL_LS_SOC_SOCMEM,
  12683                              (BSL_META_U(unit,
  12684                                          "Suspicious DMA length: "
  12685                                          "Desc:%s: Size:%u: length:%u\n"),
  12686                               p->description, p->size, length));
  12687                 }
  12688             }
  12689         } else if (soc_mem_dmaable(unit, mem, copyno)) {
  12690             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  12691                       (BSL_META_U(unit,
  12692                                   "ERROR:ATTN: Address:%p:"
  12693                                   "probably not in shared memory region \n"),
  12694                        p));
  12695         }
  12696     }
  12697 #endif
  12698 
  12699     count = 0;
  12700 
  12701     /* coverity[var_tested_neg : FALSE] */
  12702     LOG_INFO(BSL_LS_SOC_SOCMEM,
  12703              (BSL_META_U(unit,
  12704                          "soc_mem_array_read_range: unit %d memory %s.%s [%d:%d]\n"),
  12705               unit, SOC_MEM_UFNAME(unit, mem),
  12706               SOC_BLOCK_NAME(unit, copyno),
  12707               index_min, index_max));
  12708 
  12709     /* If device is gone fill buffer with null entries. */
  12710     if (SOC_IS_DETACHING(unit)) {
  12711         buf = buffer;
  12712         for (index = index_min; index <= index_max; index++, count++) {
  12713             buf = soc_mem_table_idx_to_pointer(unit, mem, void *,
  12714                                                buffer, count);
  12715             sal_memcpy(buf, soc_mem_entry_null(unit, mem),
  12716                        soc_mem_entry_bytes(unit, mem));
  12717         }
  12718         return (SOC_E_NONE);
  12719     }
  12720 
  12721 #if defined(BCM_SAND_SUPPORT) && !defined(ADAPTER_SERVER_MODE)
  12722     /*
  12723      * Write onto S-Channel "memory read" command packet consisting of header
  12724      * word + address word, and read back header word + entry_dw data words.
  12725      */
  12726     if ((SOC_IS_SAND(unit)) && (entry_dw + 2 > CMIC_SCHAN_WORDS(unit)))
  12727     {
  12728         buf = buffer;
  12729         for (index = index_min; index <= index_max; index++, count++)
  12730         {
  12731             buf = soc_mem_table_idx_to_pointer(unit, mem, void*, buffer, count);
  12732             rv = _soc_mem_array_wide_read(unit, SOC_MEM_NO_FLAGS, mem, array_index, MEM_BLOCK_ALL, index, buf);
  12733             if (SOC_FAILURE(rv)) {
  12734                 LOG_ERROR(BSL_LS_SOC_COMMON,
  12735                                 (BSL_META_U(unit,
  12736                                             "Read mem %s[%d][%d] error.\n"),
  12737                                  SOC_MEM_NAME(unit, mem), array_index, index));
  12738             }
  12739         }
  12740         return (SOC_E_NONE);
  12741     }
  12742 #endif
  12743 
  12744 #if defined(BCM_XGS_SWITCH_SUPPORT) ||\
  12745     defined(BCM_SAND_SUPPORT)
  12746     /* coverity[negative_returns : FALSE] */
  12747     if (soc_mem_dmaable(unit, mem, copyno) && (dev_id != BCM56983_DEVICE_ID)) {
  12748 #if defined (BCM_XGS3_SWITCH_SUPPORT) ||\
  12749     defined(BCM_SAND_SUPPORT)
  12750 
  12751         if (SOC_IS_XGS3_SWITCH(unit) ||
  12752             SOC_IS_SAND(unit)) {
  12753             int rv;
  12754             soc_mem_info_t  *meminfo;
  12755 
  12756             meminfo = &SOC_MEM_INFO(unit, mem);
  12757             rv = _soc_mem_dma_read(unit, mem, array_index, copyno, index_min,
  12758                                    index_max, 0, buffer, vchan);
  12759 
  12760             if (SOC_FAILURE(rv)) {
  12761                 if (rv == SOC_E_FAIL && SOC_SER_CORRECTION_SUPPORT(unit)) {
  12762                     LOG_VERBOSE(BSL_LS_SOC_COMMON,
  12763                                 (BSL_META_U(unit,
  12764                                             "Mem[%s] "
  12765                                             "DMA fallback to pio.\n"),
  12766                                  SOC_MEM_NAME(unit, mem)));
  12767                     goto _dma_fall_back_pio;
  12768                 }
  12769                 return rv;
  12770             }
  12771 
  12772             if (NULL != meminfo->snoop_cb) {
  12773                 if (SOC_MEM_SNOOP_READ & meminfo->snoop_flags) {
  12774                     meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_READ,
  12775                                       copyno, index_min, index_max, buffer,
  12776                                       meminfo->snoop_user_data);
  12777                 }
  12778                 if (SOC_MEM_SNOOP_READ_COUNT & meminfo->snoop_flags) {
  12779                     meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_READ_COUNT,
  12780                                       copyno, index_min, index_max, buffer,
  12781                                       meminfo->snoop_user_data);
  12782                 }
  12783             }
  12784             return SOC_E_NONE;
  12785         }
  12786 #endif /* BCM_XGS3_SWITCH_SUPPORT ||
  12787           defined(BCM_88750_SUPPORT) */
  12788     }
  12789 _dma_fall_back_pio:
  12790 #endif /* (BCM_XGS_SWITCH_SUPPORT) ||
  12791           defined(BCM_88750_SUPPORT) ||
  12792           defined(BCM_PETRA_SUPPORT) */
  12793     /* For the rest of entries, do direct read */
  12794     for (index = index_min; index <= index_max; index++, count++) {
  12795 
  12796         if (SOC_DEFIP_HOLE_INDEX_RANGE(unit, mem, index)) {
  12797             /* This is not valid index to be read */
  12798             continue;
  12799         }
  12800 
  12801         buf = soc_mem_table_idx_to_pointer(unit, mem, void *,
  12802                                            buffer, count);
  12803         SOC_IF_ERROR_RETURN(soc_mem_array_read(unit, mem, array_index, copyno,
  12804                                                index, buf));
  12805     }
  12806 
  12807     return SOC_E_NONE;
  12808 }
  12809 
  12810 int soc_mem_array_read_flags(int unit, soc_mem_t mem, unsigned array_index,
  12811                              int copyno, int index, void *entry_data, int flags)
  12812 {
  12813     int rv, orig_flag;
  12814 
  12815     if (!soc_mem_is_valid(unit, mem)) {
  12816         return SOC_E_MEMORY;
  12817     }
  12818 
  12819     DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE));
  12820 
  12821     orig_flag = SOC_MEM_FORCE_READ_THROUGH(unit);
  12822 
  12823     if(flags & SOC_MEM_DONT_USE_CACHE) {
  12824         SOC_MEM_FORCE_READ_THROUGH_SET(unit, 1);
  12825     }
  12826 
  12827     rv = soc_mem_array_read_extended(unit, flags, mem, array_index,
  12828                                            copyno, index, entry_data);
  12829 
  12830     SOC_MEM_FORCE_READ_THROUGH_SET(unit, orig_flag);
  12831 
  12832     return rv;
  12833 }
  12834 
  12835 /*
  12836  * Function:
  12837  *    soc_mem_ser_read_range
  12838  * Purpose:
  12839  *    Read a range of chip's memory for SER detection
  12840  * Parameters:
  12841  *    buffer -- Pointer to block of sufficiently large memory.
  12842  * Notes:
  12843  *    Table DMA only works on tables whose entry is less than
  12844  *    SOC_MEM_DMA_MAX_DATA_BEATS words long.
  12845  *
  12846  *    Table DMA has a minimum transaction size of 4 words, so if the
  12847  *    table entry is 1 or 2 words, then the count of words is modified
  12848  *    to keep this alignment.  For the remainder of the entries, this
  12849  *    function reads in the remainder of the data through mem_read
  12850  *    without using DMA.
  12851  */
  12852 int
  12853 soc_mem_ser_read_range(int unit, soc_mem_t mem, int copyno,
  12854                        int index_min, int index_max, uint32 ser_flags,
  12855                        void *buffer)
  12856 {
  12857     int rv, index, pipe_acc, count;
  12858     void *buf;
  12859     if (!soc_mem_is_valid(unit, mem)) {
  12860         return SOC_E_MEMORY;
  12861     }
  12862 
  12863     if (copyno == MEM_BLOCK_ANY) {
  12864         copyno = SOC_MEM_BLOCK_ANY(unit, mem);
  12865     }
  12866     if (copyno == COPYNO_ALL) {
  12867         return SOC_E_INTERNAL;
  12868     }
  12869 
  12870     DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE));
  12871 
  12872     /* Skip assertions here because they should have been checked
  12873      * during mem scan init. */
  12874     assert(buffer != NULL);
  12875 
  12876     if (0 == (ser_flags & _SOC_SER_FLAG_NO_DMA)) {
  12877         rv = _soc_mem_dma_read(unit, mem, 0, copyno, index_min,
  12878                                index_max, ser_flags, buffer, -1);
  12879     } else {
  12880         /* Trigger the slow path iteration below */
  12881         rv = SOC_E_FAIL;
  12882     }
  12883 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  12884     if (SOC_E_NONE == rv) {
  12885         _soc_mem_fp_global_mask_tcam_shift(unit, mem, buffer, 0, 
  12886                                            index_max - index_min);
  12887     }
  12888 #endif
  12889     
  12890     if (SOC_E_FAIL == rv) {
  12891         if (ser_flags & _SOC_SER_FLAG_DMA_ERR_RETURN) {
  12892             return rv;
  12893         }
  12894         /* Scan the table by individual reads to trigger SER correction */
  12895         pipe_acc = (ser_flags & _SOC_SER_FLAG_ACC_TYPE_MASK);
  12896         count = 0;
  12897         for (index = index_min; index <= index_max; index++, count++) {
  12898 
  12899             buf = soc_mem_table_idx_to_pointer(unit, mem, void *,
  12900                                                buffer, count);
  12901             if (0 != (ser_flags & _SOC_SER_FLAG_MULTI_PIPE)) {
  12902                 /* For multiple-pipe devices, soc_mem_pipe_select_read
  12903                  * expects a non-zero acc_type parameter.
  12904                  * If _SOC_MEM_ADDR_ACC_TYPE_PIPE_Y is not configured,
  12905                  * A default acc_type should be specified.
  12906                  */
  12907                 if ((pipe_acc == 0) &&
  12908                     !(soc_feature(unit,
  12909                                   soc_feature_unique_acc_type_access))) {
  12910 
  12911                     pipe_acc = SOC_MEM_ACC_TYPE(unit, mem);
  12912                 }
  12913                 if (0 != (ser_flags & _SOC_SER_FLAG_XY_READ)) {
  12914                     rv = soc_mem_pipe_select_read(unit, SOC_MEM_DONT_CONVERT_XY2DM,
  12915                                                   mem, copyno, pipe_acc, index, buf);
  12916                 } else {
  12917                     rv = soc_mem_pipe_select_read(unit, SOC_MEM_NO_FLAGS,
  12918                                                   mem, copyno, pipe_acc, index, buf);
  12919                 }
  12920 
  12921             } else {
  12922 #ifdef BCM_TRIDENT_SUPPORT
  12923                 if ((SOC_IS_TRIDENT(unit) || SOC_IS_TITAN(unit)) &&
  12924                       (mem == EGR_VLANm)) {
  12925                     rv = soc_mem_array_read(unit, mem, 0, copyno, index, buf);
  12926                 } else
  12927 #endif
  12928                 {
  12929                     if (0 != (ser_flags & _SOC_SER_FLAG_XY_READ)) {
  12930                         rv = soc_mem_read_extended(unit,
  12931                                 SOC_MEM_DONT_CONVERT_XY2DM | SOC_MEM_DONT_USE_CACHE,
  12932                                 mem, 0, copyno, index, buf);
  12933                     } else {
  12934                         rv = soc_mem_read_extended(unit, SOC_MEM_DONT_USE_CACHE,
  12935                                                    mem, 0, copyno, index, buf);
  12936                     }
  12937                 }
  12938             }
  12939             if (SOC_E_FAIL == rv) {
  12940                 /* We're expecting this to fail, that triggers the
  12941                  * correction logic. */
  12942                 rv = SOC_E_NONE;
  12943             } else if (SOC_FAILURE(rv)) {
  12944                 return rv;
  12945             }
  12946 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  12947         _soc_mem_fp_global_mask_tcam_shift(unit, mem, buf, 0, 0);
  12948 #endif
  12949         }
  12950         rv = SOC_E_NONE;
  12951     }
  12952 
  12953     return rv;
  12954 }
  12955 
  12956 #ifdef BCM_ESW_SUPPORT
  12957 /*
  12958  * Function:
  12959  *    soc_mem_is_dynamic
  12960  * Purpose:
  12961  *    Determine if a memory contains fields that will be updated by hardware.
  12962  * Parameters:
  12963  * Notes:
  12964  *    N/A
  12965  */
  12966 int
  12967 soc_mem_is_dynamic(int unit, soc_mem_t mem)
  12968 {
  12969     if (SOC_MEM_FIELD_VALID(unit, mem, PARITYf)||
  12970         SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITYf)||
  12971         SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITY_0f)||
  12972         SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITY_1f)||
  12973         SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITY_2f)||
  12974         SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITY_3f)||
  12975         SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITY_Af)||
  12976         SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITY_Bf)||
  12977         SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITY_LOWERf)||
  12978         SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITY_UPPERf)||
  12979         SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITY_P0f)||
  12980         SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITY_P1f)||
  12981         SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITY_P2f)||
  12982         SOC_MEM_FIELD_VALID(unit, mem, EVEN_PARITY_P3f)||
  12983         SOC_MEM_FIELD_VALID(unit, mem, EVEN_PBM_PARITY_P0f)||
  12984         SOC_MEM_FIELD_VALID(unit, mem, EVEN_PBM_PARITY_P1f)||
  12985         SOC_MEM_FIELD_VALID(unit, mem, EVEN_PBM_PARITY_P2f)||
  12986         SOC_MEM_FIELD_VALID(unit, mem, EVEN_PBM_PARITY_P3f)||
  12987         SOC_MEM_FIELD_VALID(unit, mem, EVEN_EGR_VLAN_STG_PARITY_P0f)||
  12988         SOC_MEM_FIELD_VALID(unit, mem, EVEN_EGR_VLAN_STG_PARITY_P1f)||
  12989         SOC_MEM_FIELD_VALID(unit, mem, EVEN_EGR_VLAN_STG_PARITY_P2f)||
  12990         SOC_MEM_FIELD_VALID(unit, mem, EVEN_EGR_VLAN_STG_PARITY_P3f)||
  12991         SOC_MEM_FIELD_VALID(unit, mem, ECCf)||
  12992         SOC_MEM_FIELD_VALID(unit, mem, ECC_FIELDf)||
  12993         SOC_MEM_FIELD_VALID(unit, mem, ECC_0f)||
  12994         SOC_MEM_FIELD_VALID(unit, mem, ECC_1f)||
  12995         SOC_MEM_FIELD_VALID(unit, mem, ECC_2f)||
  12996         SOC_MEM_FIELD_VALID(unit, mem, ECC_3f)||
  12997         SOC_MEM_FIELD_VALID(unit, mem, ECC_4f)||
  12998         SOC_MEM_FIELD_VALID(unit, mem, ECCPf)||
  12999         SOC_MEM_FIELD_VALID(unit, mem, ECCP0f)||
  13000         SOC_MEM_FIELD_VALID(unit, mem, ECCP1f)||
  13001         SOC_MEM_FIELD_VALID(unit, mem, ECCP2f)||
  13002         SOC_MEM_FIELD_VALID(unit, mem, ECCP3f)||
  13003         SOC_MEM_FIELD_VALID(unit, mem, ECCP4f)||
  13004         SOC_MEM_FIELD_VALID(unit, mem, ECCP5f)||
  13005         SOC_MEM_FIELD_VALID(unit, mem, ECCP7f) ||
  13006         SOC_MEM_FIELD_VALID(unit, mem, ECCP_0f) ||
  13007         SOC_MEM_FIELD_VALID(unit, mem, ECCP_1f) ||
  13008         SOC_MEM_FIELD_VALID(unit, mem, ECCP_2f) ||
  13009         SOC_MEM_FIELD_VALID(unit, mem, ECCP_3f) ||
  13010         SOC_MEM_FIELD_VALID(unit, mem, ECCP_4f) ||
  13011         SOC_MEM_FIELD_VALID(unit, mem, ECC0f) ||
  13012         SOC_MEM_FIELD_VALID(unit, mem, ECC1f) ||
  13013         SOC_MEM_FIELD_VALID(unit, mem, ECC2f) ||
  13014         SOC_MEM_FIELD_VALID(unit, mem, ECC3f) ||
  13015         SOC_MEM_FIELD_VALID(unit, mem, PARITY0f) ||
  13016         SOC_MEM_FIELD_VALID(unit, mem, PARITY1f) ||
  13017         SOC_MEM_FIELD_VALID(unit, mem, PARITY2f) ||
  13018         SOC_MEM_FIELD_VALID(unit, mem, PARITY3f) ||
  13019         SOC_MEM_FIELD_VALID(unit, mem, PARITY_0f) ||
  13020         SOC_MEM_FIELD_VALID(unit, mem, PARITY_1f) ||
  13021         SOC_MEM_FIELD_VALID(unit, mem, PARITY_2f) ||
  13022         SOC_MEM_FIELD_VALID(unit, mem, PARITY_3f) ||
  13023         SOC_MEM_FIELD_VALID(unit, mem, PARITY_4f) ||
  13024         SOC_MEM_FIELD_VALID(unit, mem, HITf) ||
  13025         SOC_MEM_FIELD_VALID(unit, mem, HIT0f) ||
  13026         SOC_MEM_FIELD_VALID(unit, mem, HIT1f) ||
  13027         SOC_MEM_FIELD_VALID(unit, mem, HIT_0f) ||
  13028         SOC_MEM_FIELD_VALID(unit, mem, HIT_1f) ||
  13029         SOC_MEM_FIELD_VALID(unit, mem, HIT_2f) ||
  13030         SOC_MEM_FIELD_VALID(unit, mem, HIT_3f) ||
  13031         SOC_MEM_FIELD_VALID(unit, mem, HITDA_0f) ||
  13032         SOC_MEM_FIELD_VALID(unit, mem, HITDA_1f) ||
  13033         SOC_MEM_FIELD_VALID(unit, mem, HITDA_2f) ||
  13034         SOC_MEM_FIELD_VALID(unit, mem, HITDA_3f) ||
  13035         SOC_MEM_FIELD_VALID(unit, mem, HITSA_0f) ||
  13036         SOC_MEM_FIELD_VALID(unit, mem, HITSA_1f) ||
  13037         SOC_MEM_FIELD_VALID(unit, mem, HITSA_2f) ||
  13038         SOC_MEM_FIELD_VALID(unit, mem, HITSA_3f) ||
  13039         SOC_MEM_FIELD_VALID(unit, mem, HITSAf) ||
  13040         SOC_MEM_FIELD_VALID(unit, mem, HITDAf) ||
  13041         SOC_MEM_FIELD_VALID(unit, mem, B0_HITf) ||
  13042         SOC_MEM_FIELD_VALID(unit, mem, B1_HITf) ||
  13043         SOC_MEM_FIELD_VALID(unit, mem, L3_HIT_DCMf) ||
  13044         SOC_MEM_FIELD_VALID(unit, mem, L3_HIT_PMf) ||
  13045         SOC_MEM_FIELD_VALID(unit, mem, HIT_BITSf) ||
  13046         SOC_MEM_FIELD_VALID(unit, mem, BUCKETCOUNTf) ||
  13047         SOC_MEM_FIELD_VALID(unit, mem, REFRESHCOUNTf) ||
  13048         SOC_MEM_FIELD_VALID(unit, mem, ECCP_P0f) ||
  13049         SOC_MEM_FIELD_VALID(unit, mem, ECCP_P1f) ||
  13050         SOC_MEM_FIELD_VALID(unit, mem, ECCP_P2f) ||
  13051         SOC_MEM_FIELD_VALID(unit, mem, ECCP_P3f) ||
  13052         SOC_MEM_FIELD_VALID(unit, mem, ECC_P0f)||
  13053         SOC_MEM_FIELD_VALID(unit, mem, ECC_P1f)||
  13054         SOC_MEM_FIELD_VALID(unit, mem, ECC_P2f)||
  13055         SOC_MEM_FIELD_VALID(unit, mem, ECC_P3f)||
  13056         SOC_MEM_FIELD_VALID(unit, mem, PARITY_P0f) ||
  13057         SOC_MEM_FIELD_VALID(unit, mem, PARITY_P1f) ||
  13058         SOC_MEM_FIELD_VALID(unit, mem, PARITY_P2f) ||
  13059         SOC_MEM_FIELD_VALID(unit, mem, PARITY_P3f) ||
  13060         SOC_MEM_FIELD_VALID(unit, mem, ECCP_PBM_0f) ||
  13061         SOC_MEM_FIELD_VALID(unit, mem, ECCP_PBM_1f) ||
  13062         SOC_MEM_FIELD_VALID(unit, mem, ECCP_PBM_2f) ||
  13063         SOC_MEM_FIELD_VALID(unit, mem, ECCP_PBM_3f) ||
  13064         SOC_MEM_FIELD_VALID(unit, mem, ECC_PBM_0f) ||
  13065         SOC_MEM_FIELD_VALID(unit, mem, ECC_PBM_1f) ||
  13066         SOC_MEM_FIELD_VALID(unit, mem, ECC_PBM_2f) ||
  13067         SOC_MEM_FIELD_VALID(unit, mem, ECC_PBM_3f) ||
  13068         SOC_MEM_FIELD_VALID(unit, mem, PARITY_PBM_0f) ||
  13069         SOC_MEM_FIELD_VALID(unit, mem, PARITY_PBM_1f) ||
  13070         SOC_MEM_FIELD_VALID(unit, mem, PARITY_PBM_2f) ||
  13071         SOC_MEM_FIELD_VALID(unit, mem, PARITY_PBM_3f)) {
  13072         return TRUE;
  13073     }
  13074     return FALSE;
  13075 }
  13076 #endif
  13077 
  13078 #if defined(BCM_XGS3_SWITCH_SUPPORT)
  13079 #ifdef BCM_WARM_BOOT_SUPPORT
  13080 /*
  13081  * Function:
  13082  *    soc_scache_mem_read_range
  13083  * Purpose:
  13084  *    Read a range of chip's memory used for L2 Warm Boot
  13085  * Parameters:
  13086  *    buffer -- Pointer to block of sufficiently large memory.
  13087  *                  For DMA operations, this memory must be
  13088  *                  DMA-able
  13089  * Notes:
  13090  *    This function is only used for DMA'ing the scache from the
  13091  *      chip's internal memory.
  13092  */
  13093 
  13094 STATIC int
  13095 soc_scache_mem_read_range(int unit, soc_mem_t mem, int copyno,
  13096                           int index_min, int index_max, void *buffer)
  13097 {
  13098     int index;
  13099     int count;
  13100     void *buf;
  13101     soc_mem_info_t  *meminfo;
  13102     unsigned int array_index = 0;
  13103 
  13104     if (!soc_mem_is_valid(unit, mem)) {
  13105         return SOC_E_MEMORY;
  13106     }
  13107 
  13108     if (copyno == MEM_BLOCK_ANY) {
  13109         copyno = SOC_MEM_BLOCK_ANY(unit, mem);
  13110     }
  13111     if (copyno == COPYNO_ALL) {
  13112         return SOC_E_INTERNAL;
  13113     }
  13114 
  13115     assert(SOC_MEM_BLOCK_VALID(unit, mem, copyno));
  13116     assert(buffer != NULL);
  13117 
  13118     meminfo = &SOC_MEM_INFO(unit, mem);
  13119     count = 0;
  13120 
  13121     /* coverity[var_tested_neg : FALSE] */
  13122     LOG_INFO(BSL_LS_SOC_SOCMEM,
  13123              (BSL_META_U(unit,
  13124                          "soc_scache_mem_read_range: unit %d memory %s.%s [%d:%d]\n"),
  13125               unit, SOC_MEM_UFNAME(unit, mem),
  13126               SOC_BLOCK_NAME(unit, copyno),
  13127               index_min, index_max));
  13128 
  13129     /* If device is gone fill buffer with null entries. */
  13130     if (SOC_IS_DETACHING(unit)) {
  13131         buf = buffer;
  13132         for (index = index_min; index <= index_max; index++, count++) {
  13133             buf = soc_mem_table_idx_to_pointer(unit, mem, void *,
  13134                                                buffer, count);
  13135             sal_memcpy(buf, soc_mem_entry_null(unit, mem),
  13136                        soc_mem_entry_bytes(unit, mem));
  13137         }
  13138         return (SOC_E_NONE);
  13139     }
  13140 
  13141     /* coverity[negative_returns : FALSE] */
  13142     if (soc_mem_dmaable(unit, mem, copyno)) {
  13143         if (SOC_IS_XGS3_SWITCH(unit)) {
  13144 
  13145             SOC_IF_ERROR_RETURN
  13146                 (_soc_mem_dma_read(unit, mem, array_index, copyno,
  13147                                    index_min, index_max, 0, buffer, -1));
  13148 
  13149             if (NULL != meminfo->snoop_cb) {
  13150                 if (SOC_MEM_SNOOP_READ & meminfo->snoop_flags) {
  13151                     meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_READ,
  13152                                       copyno, index_min, index_max, buffer,
  13153                                       meminfo->snoop_user_data);
  13154                 }
  13155                 if (SOC_MEM_SNOOP_READ_COUNT & meminfo->snoop_flags) {
  13156                     meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_READ_COUNT,
  13157                                       copyno, index_min, index_max, buffer,
  13158                                       meminfo->snoop_user_data);
  13159                 }
  13160             }
  13161         }
  13162     }
  13163     return SOC_E_NONE;
  13164 }
  13165 
  13166 /*
  13167  * Function:
  13168  *    soc_scache_mem_write_range
  13169  * Purpose:
  13170  *    Write a range of chip's memory used for L2 Warm Boot
  13171  * Parameters:
  13172  *    buffer -- Pointer to block of sufficiently large memory.
  13173  *                For slam operations, this memory must be
  13174  *                slammable
  13175  * Notes:
  13176  *    This function is only used for slamming the scache to the
  13177  *      chip's internal memory.
  13178  */
  13179 STATIC int
  13180 soc_scache_mem_write_range(int unit, soc_mem_t mem, int copyno,
  13181                            int index_min, int index_max, void *buffer)
  13182 {
  13183     uint32          entry_dw;
  13184     int             i, rv = SOC_E_NONE;
  13185     soc_mem_info_t  *meminfo;
  13186     void            *cache_buffer = NULL;
  13187 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \
  13188     || defined(BCM_HURRICANE2_SUPPORT)
  13189     int             count, alloc_size;
  13190 #endif
  13191     uint32          *cache;
  13192 
  13193     if (!soc_mem_is_valid(unit, mem)) {
  13194         return SOC_E_MEMORY;
  13195     }
  13196 
  13197     meminfo = &SOC_MEM_INFO(unit, mem);
  13198     entry_dw = soc_mem_entry_words(unit, mem);
  13199 
  13200     LOG_INFO(BSL_LS_SOC_SOCMEM,
  13201              (BSL_META_U(unit,
  13202                          "soc_scache_mem_write_range: unit %d memory %s.%s [%d:%d]\n"),
  13203               unit, SOC_MEM_UFNAME(unit, mem),
  13204               SOC_BLOCK_NAME(unit, copyno),
  13205               index_min, index_max));
  13206 
  13207     /*    coverity[negative_returns : FALSE]    */
  13208     if (SOC_IS_XGS3_SWITCH(unit) && soc_mem_slamable(unit, mem, copyno)) {
  13209         int blk;
  13210 
  13211         if (copyno == COPYNO_ALL) {
  13212             SOC_MEM_BLOCK_ITER(unit, mem, blk) {
  13213                 copyno = blk;
  13214                 break;
  13215             }
  13216         }
  13217         if (copyno == COPYNO_ALL) {
  13218             return SOC_E_INTERNAL;
  13219         }
  13220         cache = SOC_MEM_STATE(unit, mem).cache[copyno];
  13221 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \
  13222     || defined(BCM_HURRICANE2_SUPPORT)
  13223         if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit) &&
  13224             (soc_feature(unit, soc_feature_xy_tcam) &&
  13225             (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) &&
  13226             (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM)))) {
  13227             if (index_min > index_max) {
  13228                 count = index_min - index_max + 1;
  13229             } else {
  13230                 count = index_max - index_min + 1;
  13231             }
  13232             alloc_size = count * entry_dw * sizeof(uint32);
  13233             cache_buffer = sal_alloc(alloc_size, "cache buffer");
  13234             if (cache_buffer == NULL) {
  13235                 return SOC_E_MEMORY;
  13236             }
  13237         }
  13238 #endif
  13239         MEM_LOCK(unit, mem);
  13240         rv = _soc_mem_dma_write(unit, 0, mem, 0, copyno, index_min, index_max,
  13241                                 buffer, cache_buffer, -1);
  13242         if (rv >= 0) {
  13243             uint8 *vmap, *vmap1 = NULL;
  13244                /* coverity[negative_returns : FALSE]    */
  13245                /* coverity[negative_returns] */
  13246             vmap = SOC_MEM_STATE(unit, mem).vmap[copyno];
  13247             if (_SOC_MEM_CHK_L2_MEM(mem)) {
  13248                 if (mem == L2_ENTRY_1m) {
  13249                     vmap1 = SOC_MEM_STATE(unit, L2_ENTRY_2m).vmap[copyno];
  13250                 } else if (mem == L2_ENTRY_2m) {
  13251                     vmap1 = SOC_MEM_STATE(unit, L2_ENTRY_1m).vmap[copyno];
  13252                 }
  13253             }
  13254 
  13255             if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)) {
  13256                 sal_memcpy(cache + index_min * entry_dw, cache_buffer ?
  13257                            cache_buffer : buffer,
  13258                            (index_max - index_min + 1) * entry_dw * 4);
  13259                 for (i = index_min; i <= index_max; i++) {
  13260                     if (vmap1) {
  13261                         CACHE_VMAP_CLR(vmap, i);
  13262                         if (mem == L2_ENTRY_1m) {
  13263                             CACHE_VMAP_CLR(vmap1, i/2);
  13264                         } else {
  13265                             CACHE_VMAP_CLR(vmap1, i*2);
  13266                             CACHE_VMAP_CLR(vmap1, i*2 + 1);
  13267                         }
  13268                     } else {
  13269                         CACHE_VMAP_SET(vmap, i);
  13270                     }
  13271                 }
  13272 #ifdef BCM_TRX_SUPPORT
  13273                 _soc_mem_aggr_cache_update(unit, mem, copyno, 0,
  13274                     index_min, index_max, 0, buffer);
  13275 #endif /* BCM_TRX_SUPPORT */                
  13276             }
  13277         }
  13278         MEM_UNLOCK(unit, mem);
  13279         if (NULL != meminfo->snoop_cb) {
  13280             if (SOC_MEM_SNOOP_WRITE & meminfo->snoop_flags) {
  13281                 meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_WRITE,
  13282                                   copyno, index_min, index_max, buffer,
  13283                                   meminfo->snoop_user_data);
  13284             }
  13285             if (SOC_MEM_SNOOP_WRITE_COUNT & meminfo->snoop_flags) {
  13286                 meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_WRITE_COUNT,
  13287                                   copyno, index_min, index_max, buffer,
  13288                                   meminfo->snoop_user_data);
  13289             }
  13290         }
  13291 
  13292         if (cache_buffer) {
  13293             sal_free(cache_buffer);
  13294         }
  13295     }
  13296     return rv;
  13297 }
  13298 
  13299 int
  13300 soc_scache_esw_nh_mem_write(int unit, uint8 *buf, int offset, int nbytes)
  13301 {
  13302     int num_entries, bytes2,  rv = SOC_E_NONE;
  13303     int stable_size;
  13304     uint32 stable_index_max, stable_index_min;
  13305     int i, j, bufptr;
  13306     uint8 *buf2;
  13307     int start, end;
  13308     int scache_offset;
  13309     uint8 mask[SOC_MAX_MEM_BYTES];
  13310     uint32 l3_next_hop_size = soc_mem_entry_bytes(unit, EGR_L3_NEXT_HOPm) *
  13311         soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
  13312 
  13313     SOC_IF_ERROR_RETURN(
  13314         soc_stable_tmp_access(unit, sf_index_min, &stable_index_min, TRUE));
  13315     SOC_IF_ERROR_RETURN(
  13316         soc_stable_tmp_access(unit, sf_index_max, &stable_index_max, TRUE));
  13317     SOC_IF_ERROR_RETURN(
  13318         soc_stable_size_get(unit, &stable_size));
  13319 
  13320     bytes2 = soc_mem_entry_words(unit, EGR_L3_NEXT_HOPm) * sizeof(uint32);
  13321     num_entries = stable_index_max - stable_index_min + 1;
  13322 
  13323     start = stable_index_min + offset / (bytes2);
  13324 
  13325     scache_offset = offset % (bytes2);
  13326     end = start + (nbytes + scache_offset + bytes2 - 1) / (bytes2);
  13327     if (stable_index_max < end) {
  13328         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  13329                   (BSL_META_U(unit,
  13330                               "Stable max index(%d) is less than buffer end(%d)\n"),
  13331                    stable_index_max, end));   
  13332         return SOC_E_INTERNAL;
  13333     }
  13334     if (stable_size > l3_next_hop_size) {
  13335         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  13336                   (BSL_META_U(unit,
  13337                               "Stable size(%d) is larger than size of memory EGR_L3_NEXT_HOPm(%d)\n"),
  13338                    stable_size, l3_next_hop_size)); 
  13339         return SOC_E_INTERNAL;
  13340     }
  13341     buf2 = NULL;
  13342     /* Allocate slammable memory */
  13343     buf2 = soc_cm_salloc(unit, bytes2 * num_entries, "EGR_L3_NEXT_HOP buffer");
  13344     if (NULL == buf2) {
  13345         rv = SOC_E_MEMORY;
  13346         goto cleanup;
  13347     }
  13348     sal_memset(buf2, 0, bytes2 * num_entries);
  13349 
  13350     /* Copy the buffer to the individual memories */
  13351     bufptr = 0;
  13352     sal_memset(mask, 0, SOC_MAX_MEM_BYTES);
  13353     soc_mem_datamask_get(unit, EGR_L3_NEXT_HOPm, (uint32 *)mask);
  13354 
  13355     SOC_IF_ERROR_RETURN
  13356         (soc_scache_mem_read_range(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY,
  13357                                    start, start, buf2));
  13358     if (start != end) {
  13359         SOC_IF_ERROR_RETURN
  13360             (soc_scache_mem_read_range(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY,
  13361                                        end, end, buf2 + end * bytes2));
  13362     }
  13363 
  13364     for (i = 0; i <= (end - start); i++) {
  13365         if (bufptr < stable_size) {
  13366             for (j = (i == 0) ? scache_offset : 0; j < SOC_MAX_MEM_BYTES; j++) {
  13367                 if (mask[j] != 0xff) {
  13368                     continue;
  13369                 }
  13370                 /*
  13371                 sal_memcpy(buf2 + (i - stable_index_min) * bytes2 + j,
  13372                            (buf + bufptr), 1);
  13373                 */
  13374                 *(buf2 + i * bytes2 + j) = *(buf + bufptr);
  13375                 bufptr++;
  13376             }
  13377         }
  13378     }
  13379 
  13380     rv = soc_scache_mem_write_range(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL,
  13381                                     start, end, buf2);
  13382 cleanup:
  13383     if (buf2 != NULL) {
  13384         soc_cm_sfree(unit, buf2);
  13385     }
  13386     return rv;
  13387 }
  13388 
  13389 int
  13390 soc_scache_esw_nh_mem_read(int unit, uint8 *buf, int offset, int nbytes)
  13391 {
  13392     int i, num_entries, bytes2, rv = SOC_E_NONE;
  13393     int j, bufptr;
  13394     int stable_size;
  13395     uint32 stable_index_min, stable_index_max;
  13396     uint8 *buf2;
  13397     int start, end;
  13398     int scache_offset;
  13399     uint8 mask[SOC_MAX_MEM_BYTES];
  13400     uint32 l3_next_hop_size = soc_mem_entry_bytes(unit, EGR_L3_NEXT_HOPm) *
  13401         soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
  13402 
  13403     SOC_IF_ERROR_RETURN(
  13404         soc_stable_tmp_access(unit, sf_index_min, &stable_index_min, TRUE));
  13405     SOC_IF_ERROR_RETURN(
  13406         soc_stable_tmp_access(unit, sf_index_max, &stable_index_max, TRUE));
  13407     SOC_IF_ERROR_RETURN(
  13408         soc_stable_size_get(unit, &stable_size));
  13409 
  13410     bytes2 = soc_mem_entry_words(unit, EGR_L3_NEXT_HOPm) * sizeof(uint32);
  13411     num_entries = stable_index_max - stable_index_min + 1;
  13412 
  13413     buf2 = NULL;
  13414     start = stable_index_min + offset / (bytes2);
  13415 
  13416     scache_offset = offset % (bytes2);
  13417     end = start + (nbytes + scache_offset + bytes2 - 1) / (bytes2);
  13418     if (stable_index_max < end) {
  13419         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  13420                   (BSL_META_U(unit,
  13421                               "Stable max index(%d) is less than buffer end(%d)\n"),
  13422                    stable_index_max, end));   
  13423         return SOC_E_INTERNAL;
  13424     }
  13425     if (stable_size > l3_next_hop_size) {
  13426         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  13427                   (BSL_META_U(unit,
  13428                               "Stable size(%d) is larger than size of memory EGR_L3_NEXT_HOPm(%d)\n"),
  13429                    stable_size, l3_next_hop_size)); 
  13430         return SOC_E_INTERNAL;
  13431     }
  13432     /* Allocate DMA'able memory */
  13433     buf2 = soc_cm_salloc(unit, bytes2 * num_entries, "EGR_L3_NEXT_HOP buffer");
  13434     if (NULL == buf2) {
  13435         rv = SOC_E_MEMORY;
  13436         goto cleanup;
  13437     }
  13438     sal_memset(buf2, 0, bytes2 * num_entries);
  13439 
  13440     /* DMA the tables */
  13441     rv = soc_scache_mem_read_range(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY,
  13442                                    stable_index_min, stable_index_max, buf2);
  13443 
  13444     /* Copy out the individual buffers to the scache buffer */
  13445     bufptr = 0;
  13446     sal_memset(mask, 0, SOC_MAX_MEM_BYTES);
  13447     soc_mem_datamask_get(unit, EGR_L3_NEXT_HOPm, (uint32 *)mask);
  13448     for (i = 0; i <= (end - start); i++) {
  13449         if (bufptr < stable_size) {
  13450             for (j = (i == 0) ? scache_offset : 0; j < SOC_MAX_MEM_BYTES; j++) {
  13451                 if (mask[j] != 0xff) {
  13452                     continue;
  13453                 }
  13454                 /*
  13455                 sal_memcpy((buf + offset + bufptr),
  13456                             buf2 + (i - stable_index_min) * bytes2 + j, 1);
  13457                 */
  13458                 *(buf + bufptr) = *(buf2 + i * bytes2 + j);
  13459                 bufptr++;
  13460             }
  13461         }
  13462     }
  13463 cleanup:
  13464     if (buf2 != NULL) {
  13465         soc_cm_sfree(unit, buf2);
  13466     }
  13467     return rv;
  13468 }
  13469 #endif /* BCM_WARM_BOOT_SUPPORT */
  13470 #endif /* defined(BCM_XGS3_SWITCH_SUPPORT) */
  13471 
  13472 /*
  13473  * Function: _soc_mem_write_ext_cache_set
  13474  *
  13475  * Purpose:  Called by _soc_mem_write_extended().  Check for the no-cache flag
  13476  *           and set no_cache and index accordingly.
  13477  *
  13478  * Returns:  Nothing, but sets no_cache and may alter index
  13479  */
  13480 STATIC void
  13481 _soc_mem_write_ext_cache_set(uint32 flags, int *index, int *no_cache)
  13482 {
  13483     if ((flags & SOC_MEM_DONT_USE_CACHE) == SOC_MEM_DONT_USE_CACHE) {
  13484         *no_cache = 1;
  13485     } else {
  13486         *no_cache = 0;
  13487     }
  13488 
  13489     /*Legacy  nocache handling*/
  13490     if (*index < 0) {
  13491         *no_cache = 1;
  13492         *index = -*index;
  13493     }
  13494 }
  13495 
  13496 /*
  13497  * Function: _soc_mem_hercules_write_attempt
  13498  *
  13499  * Purpose: Called by _soc_mem_write_extended().  If the unit is a hercules,
  13500  *          redirect the request to the hercules mem write handler.
  13501  *
  13502  * Returns: TRUE if the request was intercepted and handled by hercules
  13503  *          FALSE if the request should proceed normally
  13504  */
  13505 STATIC int
  13506 _soc_mem_hercules_write_attempt(int unit, soc_mem_t mem, int copyno, int index,
  13507                                 void *entry_data, int *rv)
  13508 {
  13509 #ifdef BCM_HERCULES_SUPPORT
  13510     /* Handle Hercules' word read tables separately */
  13511     if (SOC_IS_HERCULES(unit) &&
  13512         (soc_mem_flags(unit, mem) & SOC_MEM_FLAG_WORDADR)) {
  13513         *rv = soc_hercules_mem_write(unit, mem, copyno, index, entry_data);
  13514         return TRUE;
  13515     }
  13516 #endif /* BCM_HERCULES_SUPPORT */
  13517 
  13518     return FALSE;
  13519 }
  13520 
  13521 void *
  13522 soc_mem_write_tcam_to_hw_format(int unit, soc_mem_t mem, void *entry_data,
  13523                                  uint32 *cache_entry_data,
  13524                                  uint32 *converted_entry_data)
  13525 {
  13526     void *entry_data_ptr = entry_data;
  13527 
  13528 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \
  13529     || defined(BCM_HURRICANE2_SUPPORT)
  13530 
  13531     soc_mem_info_t *meminfo = &SOC_MEM_INFO(unit, mem);
  13532     if (soc_feature(unit, soc_feature_xy_tcam) &&
  13533         (meminfo->flags & SOC_MEM_FLAG_CAM) &&
  13534         (!(meminfo->flags & SOC_MEM_FLAG_EXT_CAM))) {
  13535 
  13536         entry_data_ptr = converted_entry_data;
  13537         _soc_mem_tcam_dm_to_xy(unit, mem, 1, entry_data, entry_data_ptr,
  13538                                cache_entry_data);
  13539     }
  13540 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */
  13541 
  13542     return entry_data_ptr;
  13543 }
  13544 
  13545 /*
  13546  * Function: _soc_mem_write_sanity_check
  13547  *
  13548  * Purpose:  Called by _soc_mem_write_extended().  Check mem/index parameters
  13549  *           for basic validity.
  13550  *
  13551  * Returns:  SOC_E_xxx
  13552  */
  13553 STATIC int
  13554 _soc_mem_write_sanity_check(int unit, uint32 flags, soc_mem_t mem,
  13555                                       int index)
  13556 {
  13557     soc_mem_info_t *meminfo = &SOC_MEM_INFO(unit, mem);
  13558     int entry_num_max = 0;
  13559 
  13560     if (!soc_mem_is_valid(unit, mem)) {
  13561         return SOC_E_MEMORY;
  13562     }
  13563 
  13564     /*
  13565      * When checking index, check for 0 instead of soc_mem_index_min.
  13566      * Diagnostics need to read/write index 0 of Strata ARL and GIRULE.
  13567      */
  13568 
  13569     if (!(flags & SOC_MEM_DONT_CHECK_INDEX)) {
  13570         if ((flags & SOC_MEM_DONT_MAP_INDEX) &&
  13571             (mem == L3_DEFIPm ||
  13572              mem == L3_DEFIP_LEVEL1m ||
  13573              mem == L3_DEFIP_ONLYm ||
  13574              mem == L3_DEFIP_DATA_ONLYm ||
  13575              mem == L3_DEFIP_HIT_ONLY_Xm ||
  13576              mem == L3_DEFIP_HIT_ONLY_Ym ||
  13577              mem == L3_DEFIP_HIT_ONLYm ||
  13578              mem == L3_DEFIP_PAIR_128m ||
  13579              mem == L3_DEFIP_PAIR_LEVEL1m ||
  13580              mem == L3_DEFIP_PAIR_128_ONLYm ||
  13581              mem == L3_DEFIP_PAIR_128_DATA_ONLYm ||
  13582              mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm ||
  13583              mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym ||
  13584              mem == L3_DEFIP_PAIR_128_HIT_ONLYm)) {
  13585             if (_soc_mem_defip_index_is_invalid(unit, mem, index) == TRUE) {
  13586                 return SOC_E_PARAM;
  13587             }
  13588         } else {
  13589             entry_num_max = soc_mem_index_max(unit, mem);
  13590 
  13591             if (index < 0 || index > entry_num_max) {
  13592                 if (!(SOC_DEFIP_HOLE_RANGE_CHECK(unit, mem, index))) {
  13593                 LOG_WARN(BSL_LS_SOC_SOCMEM,
  13594                          (BSL_META_U(unit,
  13595                                      "soc_mem_write: invalid index %d for memory %s\n"),
  13596                           index, SOC_MEM_NAME(unit, mem)));
  13597                 return SOC_E_PARAM;
  13598                 }
  13599             }
  13600         }
  13601     }
  13602 
  13603     if (_soc_mem_read_tcam_is_invalid(unit, mem, index) == TRUE) {
  13604         LOG_WARN(BSL_LS_SOC_SOCMEM,
  13605                  (BSL_META_U(unit,
  13606                              "soc_mem_write: invalid index %d for memory %s\n"),
  13607                   index, SOC_MEM_NAME(unit, mem)));
  13608         return SOC_E_PARAM;
  13609     }
  13610 
  13611     if (meminfo->flags & SOC_MEM_FLAG_READONLY) {
  13612         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  13613                   (BSL_META_U(unit,
  13614                              "soc_mem_write: attempt to write R/O memory %s\n"),
  13615                    SOC_MEM_NAME(unit, mem)));
  13616         return SOC_E_INTERNAL;
  13617     }
  13618 
  13619     return SOC_E_NONE;
  13620 }
  13621 
  13622 /*
  13623  * soc_mem_write_copyno_update
  13624  *
  13625  * Called from within soc_mem_write.  When writing to Arad, the writer must
  13626  * select which core is being written to.  If SOC_CORE_ALL or COPYNO_ALL is
  13627  * selected, then override the copyno variable to use broadcast registers
  13628  * instead of iterating and writing to each separately.
  13629  *
  13630  * Returns SOC_E_xxx
  13631  */
  13632 int
  13633 soc_mem_write_copyno_update(int unit, soc_mem_t mem, int *copyno,
  13634                              int *copyno_override)
  13635 {
  13636     int rv = SOC_E_NONE;
  13637 
  13638 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT)
  13639     /* Use core broadcast writes when possible for more efficient writes */
  13640     if ((SOC_IS_ARAD(unit) || SOC_IS_DNX(unit) || SOC_IS_DNXF(unit)) 
  13641              && (*copyno == SOC_CORE_ALL || *copyno == COPYNO_ALL || SOC_BLOCK_IS_BROADCAST(unit, *copyno))) {
  13642         *copyno_override = soc_mem_broadcast_block_get(unit, mem);
  13643         if (*copyno_override == SOC_CORE_ALL) {
  13644             *copyno_override = 0;
  13645         }
  13646         if (!*copyno_override) {
  13647             *copyno = COPYNO_ALL;
  13648         }
  13649     } else
  13650 #endif /* BCM_PETRA_SUPPORT */
  13651 
  13652     if (*copyno == SOC_CORE_ALL) {
  13653         *copyno = COPYNO_ALL;
  13654     } else if (*copyno != COPYNO_ALL) {
  13655         if (!SOC_MEM_BLOCK_VALID(unit, mem, *copyno)) {
  13656             LOG_WARN(BSL_LS_SOC_SOCMEM,
  13657                      (BSL_META_U(unit,
  13658                                  "soc_mem_write: invalid block %d for memory %s\n"),
  13659                       *copyno, SOC_MEM_NAME(unit, mem)));
  13660             rv = SOC_E_PARAM;
  13661         }
  13662     }
  13663 
  13664     return rv;
  13665 }
  13666 
  13667 #ifdef BCM_TRIDENT_SUPPORT
  13668 /*
  13669  * Function: _soc_mem_write_instances_cache_update
  13670  *
  13671  * Purpose:  If this mem view has several physical instances, 
  13672  *               they need to be updated accordingly.
  13673  *
  13674  * Returns:  None
  13675  */
  13676 STATIC void
  13677 _soc_mem_write_instances_cache_update(int unit, soc_mem_t mem, 
  13678                                       int blk, int no_cache, 
  13679                                       int index_min, int index_max,
  13680                                       int array_index, void *entry_data)
  13681 {
  13682     soc_mem_t mem_cp[SOC_MEM_CP_MAX_NUM];
  13683     int i;
  13684 
  13685     /* Tomahawk 3 has shadow memories that are updated when the main memory
  13686      * is updated. Since these memories are automatically updated, we also
  13687      * need to update the cache for these memories
  13688      */
  13689     if (SOC_IS_TOMAHAWK3(unit)) {
  13690         if (mem == MMU_THDO_CONFIG_UC_QGROUP0m) {
  13691             mem_cp[0] = MMU_THDO_CONFIG_UC_QGROUP1m;
  13692             mem_cp[1] = MMU_THDO_CONFIG_UC_QGROUP2m;
  13693             mem_cp[2] = INVALIDm;
  13694 
  13695             for (i = 0; mem_cp[i] != INVALIDm; i++) {
  13696                 _soc_mem_write_range_cache_update(unit, mem_cp[i],
  13697                                             array_index, blk, no_cache,
  13698                                             index_min, index_max,
  13699                                             entry_data);
  13700             }
  13701         }
  13702     }
  13703     /*
  13704      * There are 2 physical instances of THDO_OFFSET_0 on TD+.
  13705      * Writing this table writes all two physical instances.
  13706      * The instances are THDO_OFFSET_0A, THDO_OFFSET_0B.
  13707      */
  13708     if (SOC_IS_TRIDENT(unit)) {
  13709         int r = SOC_E_NONE;
  13710 
  13711         r = soc_trident_mem_cp_get(unit, mem, mem_cp);
  13712         if (SOC_FAILURE(r)) {
  13713             return;
  13714         }
  13715 
  13716         for (i = 0; i < SOC_MEM_CP_MAX_NUM; i++) {
  13717             if (soc_mem_is_valid(unit, mem_cp[i])) {
  13718                 _soc_mem_write_range_cache_update(unit, mem_cp[i],
  13719                                                   array_index, blk, no_cache,
  13720                                                   index_min, index_max,
  13721                                                   entry_data);
  13722             }
  13723         }
  13724     }
  13725 }
  13726 #endif /* BCM_TRIDENT_SUPPORT */
  13727 
  13728 /*
  13729  * Function: _soc_mem_write_cache_update
  13730  *
  13731  * Purpose:  Called by soc_mem_write_extended().  After a successful write,
  13732  *           update the cache to hold the new data (if applicable).
  13733  *
  13734  * Returns:  Nothing
  13735  */
  13736 void
  13737 _soc_mem_write_cache_update(int unit, soc_mem_t mem, int blk, int no_cache,
  13738                             int index, int array_index, void *entry_data,
  13739                             void *entry_data_ptr, uint32 *cache_entry_data,
  13740                             uint32 *converted_entry_data)
  13741 {
  13742     /* Write back to cache if active */
  13743     uint32 *cache;
  13744     uint8 *vmap;
  13745     int entry_dw;
  13746     int mem_array_vmap_offset;
  13747     int mem_array_cache_offset;
  13748 
  13749     SOC_MEM_ALIAS_TO_ORIG(unit,mem);
  13750     cache = SOC_MEM_STATE(unit, mem).cache[blk];
  13751     vmap = SOC_MEM_STATE(unit, mem).vmap[blk];
  13752     entry_dw = soc_mem_entry_words(unit, mem);
  13753 #ifdef BCM_DNX_SUPPORT
  13754     mem_array_vmap_offset = (SOC_MEM_IS_ARRAY(unit, mem)) ?
  13755                              ((array_index - SOC_MEM_FIRST_ARRAY_INDEX(unit, mem)) * soc_mem_index_count(unit, mem)) :
  13756                               (array_index * soc_mem_index_count(unit, mem));
  13757 
  13758 #else
  13759     mem_array_vmap_offset = array_index * soc_mem_index_count(unit, mem);
  13760 #endif
  13761     mem_array_cache_offset = mem_array_vmap_offset * entry_dw;
  13762 
  13763     if (cache != NULL && !no_cache && !SOC_MEM_TEST_SKIP_CACHE(unit)) {
  13764         if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ||
  13765             SOC_HW_ACCESS_DISABLE(unit)) {
  13766             if (!SOC_WARM_BOOT(unit)) {
  13767                 CACHE_VMAP_CLR(vmap, mem_array_vmap_offset + index);
  13768             }
  13769         } else if (_SOC_MEM_CHK_L2_MEM(mem)) {
  13770             soc_field_t fld_vld = VALIDf;
  13771             if (soc_feature(unit, soc_feature_base_valid)) {
  13772                 fld_vld = BASE_VALIDf;
  13773             }
  13774             /* If an invalid entry is being written then clear the cache */
  13775             if (((mem == L2_ENTRY_2m &&
  13776                  soc_L2_ENTRY_2m_field32_get(unit, entry_data, VALID_0f) &&
  13777                  soc_L2_ENTRY_2m_field32_get(unit, entry_data, VALID_1f)) ||
  13778                  ((mem == L2Xm || mem == L2_ENTRY_1m) &&
  13779                   soc_mem_field32_get(unit, mem, entry_data, fld_vld))) &&
  13780                  ((mem == L2_ENTRY_2m &&
  13781                   (soc_mem_field32_get(unit, mem, entry_data, STATIC_BIT_0f) &&
  13782                    soc_mem_field32_get(unit, mem, entry_data, STATIC_BIT_1f))) ||
  13783                    ((mem == L2Xm || mem == L2_ENTRY_1m) &&
  13784                     soc_mem_field32_get(unit, mem, entry_data, STATIC_BITf)))) {
  13785 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT)
  13786                 sal_memcpy(cache + index * entry_dw,
  13787                            (entry_data_ptr == converted_entry_data) ?
  13788                            cache_entry_data : entry_data, entry_dw * 4);
  13789 #else
  13790                 sal_memcpy(cache + index * entry_dw, entry_data, entry_dw * 4);
  13791 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */
  13792                 CACHE_VMAP_SET(vmap, index);
  13793             } else {
  13794                 CACHE_VMAP_CLR(vmap, index);
  13795             }
  13796             if (mem == L2_ENTRY_1m) {
  13797                 vmap = SOC_MEM_STATE(unit, L2_ENTRY_2m).vmap[blk];
  13798                 CACHE_VMAP_CLR(vmap, index/2);
  13799             } else if (mem == L2_ENTRY_2m) {
  13800                 vmap = SOC_MEM_STATE(unit, L2_ENTRY_1m).vmap[blk];
  13801                 CACHE_VMAP_CLR(vmap, index*2);
  13802                 CACHE_VMAP_CLR(vmap, index*2 + 1);
  13803             }
  13804         } else {
  13805             if (SOC_IS_SAND(unit)) {
  13806                 /* DPP devices should use this write even if they are compiled with trident devices. */
  13807                 sal_memcpy(cache + mem_array_cache_offset + index * entry_dw,
  13808                            entry_data, entry_dw * 4);
  13809             } else {
  13810 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \
  13811         || defined(BCM_HURRICANE2_SUPPORT)
  13812                 if (entry_data_ptr == converted_entry_data) {
  13813                     sal_memcpy(cache + index * entry_dw,
  13814                                cache_entry_data, entry_dw * 4);
  13815 #if defined(INCLUDE_MEM_SCAN)
  13816                     /* Update memscan TCAM cache if necessary */
  13817                     soc_mem_scan_tcam_cache_update(unit, mem,
  13818                                                    index, index,
  13819                                                    entry_data_ptr);
  13820 #endif /* INCLUDE_MEM_SCAN */
  13821 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
  13822 #ifdef BCM_WARM_BOOT_SUPPORT
  13823                     if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2X(unit) ||
  13824                         SOC_IS_TRIDENT(unit) || SOC_IS_TITAN(unit)) {
  13825                         soc_mem_overlay_tcam_update(unit, mem, blk,
  13826                                                     index, index);
  13827                     }
  13828 #endif
  13829 #endif
  13830                 } else {
  13831                     sal_memcpy(cache + index * entry_dw,
  13832                                entry_data, entry_dw * 4);
  13833                 }
  13834 #else
  13835                 sal_memcpy(cache + mem_array_cache_offset + index * entry_dw,
  13836                            entry_data, entry_dw * 4);
  13837 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */
  13838             }
  13839             CACHE_VMAP_SET(vmap, (mem_array_vmap_offset + index));
  13840 
  13841             /* Clear VMAP index in cache when tunnel info is null entry */
  13842             if (_SOC_MEM_CHK_EGR_IP_TUNNEL(mem) &&
  13843                     SOC_MEM_IS_VALID(unit, mem)) {
  13844                 if (sal_memcmp(entry_data, soc_mem_entry_null(unit, mem),
  13845                                        soc_mem_entry_words(unit, mem) * sizeof(uint32)) == 0) {
  13846                     CACHE_VMAP_CLR(vmap, index);
  13847                 }
  13848             }
  13849 
  13850 #ifdef BCM_TRIDENT_SUPPORT
  13851             _soc_mem_write_instances_cache_update(unit, mem, blk,
  13852                                                   no_cache, index, index,
  13853                                                   array_index, entry_data);
  13854 #endif /* BCM_TRIDENT_SUPPORT */
  13855         }
  13856     }
  13857 }
  13858 
  13859 void
  13860 _soc_mem_alpm_write_cache(int unit, soc_mem_t mem, int copyno,
  13861                           int index, void *entry_data)
  13862 {
  13863     /* Write back to cache if active */
  13864     int blk;
  13865     uint32 *cache;
  13866     uint8 *vmap;
  13867     int entry_dw;
  13868     uint32 converted_entry_data[SOC_MAX_MEM_WORDS];
  13869     uint32 cache_entry_data[SOC_MAX_MEM_WORDS];
  13870     void *entry_data_ptr;
  13871 
  13872     /* Currently only apply to LPM tables */
  13873     switch (mem) {
  13874         case L3_DEFIPm:
  13875         case L3_DEFIP_PAIR_128m:
  13876         case L3_DEFIP_LEVEL1m:
  13877         case L3_DEFIP_PAIR_LEVEL1m:
  13878         case L3_DEFIP_ALPM_LEVEL2m:
  13879         case L3_DEFIP_ALPM_LEVEL3m:
  13880         case L3_DEFIP_ALPM_LEVEL2_HIT_ONLYm: /* TH3TBD need? */
  13881         case L3_DEFIP_ALPM_LEVEL3_HIT_ONLYm:
  13882         case L3_DEFIP_AUX_TABLEm:
  13883         case L3_DEFIP_ALPM_RAWm:
  13884         case L3_DEFIP_ALPM_IPV4m:
  13885         case L3_DEFIP_ALPM_IPV4_1m:
  13886         case L3_DEFIP_ALPM_IPV6_64m:
  13887         case L3_DEFIP_ALPM_IPV6_64_1m:
  13888         case L3_DEFIP_ALPM_IPV6_128m:
  13889             break;
  13890         default:
  13891             return ;
  13892     }
  13893 
  13894     entry_data_ptr = soc_mem_write_tcam_to_hw_format(unit, mem, entry_data,
  13895                                                       cache_entry_data,
  13896                                                       converted_entry_data);
  13897     MEM_LOCK(unit, mem);
  13898 
  13899     SOC_MEM_ALIAS_TO_ORIG(unit,mem);
  13900 
  13901     SOC_MEM_BLOCK_ITER(unit, mem, blk) {
  13902         if (copyno != COPYNO_ALL && copyno != blk) {
  13903             continue;
  13904         }
  13905 
  13906         cache = SOC_MEM_STATE(unit, mem).cache[blk];
  13907         vmap = SOC_MEM_STATE(unit, mem).vmap[blk];
  13908         entry_dw = soc_mem_entry_words(unit, mem);
  13909 
  13910         if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)) {
  13911             if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ||
  13912                 SOC_HW_ACCESS_DISABLE(unit)) {
  13913                 if (!SOC_WARM_BOOT(unit)) {
  13914                     CACHE_VMAP_CLR(vmap, index);
  13915                 }
  13916             } else {
  13917                 if (entry_data_ptr == converted_entry_data) {
  13918                     sal_memcpy(cache + index * entry_dw,
  13919                                cache_entry_data, entry_dw * 4);
  13920 #if defined(INCLUDE_MEM_SCAN)
  13921                     /* Update memscan TCAM cache if necessary */
  13922                     soc_mem_scan_tcam_cache_update(unit, mem,
  13923                                                    index, index,
  13924                                                    entry_data_ptr);
  13925 #endif /* INCLUDE_MEM_SCAN */
  13926                 } else {
  13927                     sal_memcpy(cache + index * entry_dw,
  13928                                entry_data, entry_dw * 4);
  13929                 }
  13930                 CACHE_VMAP_SET(vmap, index);
  13931             }
  13932         }
  13933     }
  13934 
  13935     MEM_UNLOCK(unit, mem);
  13936 
  13937 }
  13938 
  13939 #ifdef BCM_ESW_SUPPORT
  13940 STATIC uint32
  13941 _soc_l2mode_fifo_enable_memwr_field_get(int unit)
  13942 {
  13943     uint32 rval = 0, memwr = 0;
  13944     if (SOC_IS_TRIDENT2X(unit)) {
  13945         if (READ_AUX_ARB_CONTROLr(unit, &rval) < 0) {
  13946             return 0;
  13947         }
  13948         memwr = soc_reg_field_get(unit, AUX_ARB_CONTROLr,
  13949                                   rval,
  13950                                   L2_MOD_FIFO_ENABLE_MEMWRf);
  13951     }
  13952     return memwr;
  13953 }
  13954 
  13955 STATIC int
  13956 _soc_l2mode_fifo_enable_memwr_field_set(int unit, int enable)
  13957 {
  13958     uint32 rval = 0;
  13959     uint32 ena = (enable==0)?0:1;
  13960 
  13961     if (SOC_IS_TRIDENT2X(unit)) {
  13962         SOC_IF_ERROR_RETURN(
  13963                 READ_AUX_ARB_CONTROLr(unit, &rval));
  13964         soc_reg_field_set(unit, AUX_ARB_CONTROLr, &rval,
  13965                         L2_MOD_FIFO_ENABLE_MEMWRf, ena);
  13966         SOC_IF_ERROR_RETURN(
  13967                 WRITE_AUX_ARB_CONTROLr(unit, rval));
  13968     }
  13969     return SOC_E_NONE;
  13970 }
  13971 
  13972 #if defined(BCM_TRIUMPH3_SUPPORT)
  13973 STATIC uint32
  13974 _soc_l2mode_fifo_enable_delete_field_get(int unit)
  13975 {
  13976     uint32 rval = 0, l2_delete = 0;
  13977     int i;
  13978     soc_reg_t fifo_reg[] = {
  13979         L2_MOD_FIFO_ENABLEr, 
  13980         AUX_ARB_CONTROLr
  13981     };
  13982     soc_reg_t fifo_fld[] = {
  13983         L2_DELETEf,
  13984         L2_MOD_FIFO_ENABLE_L2_DELETEf
  13985     };
  13986 
  13987     for (i = 0; i < sizeof(fifo_fld) / sizeof(fifo_fld[0]); i++) {
  13988         if (SOC_REG_FIELD_VALID(unit, fifo_reg[i], fifo_fld[i])) {
  13989             if (soc_reg32_get(unit, fifo_reg[i], REG_PORT_ANY, 0, &rval) < 0) {
  13990                 return 0;
  13991             }
  13992             l2_delete = soc_reg_field_get(unit, fifo_reg[i], rval, fifo_fld[i]);
  13993             break;
  13994         }
  13995     }
  13996     return l2_delete;
  13997 
  13998 }
  13999 
  14000 STATIC int
  14001 _soc_l2mode_fifo_enable_delete_field_set(int unit, uint32 enable)
  14002 {
  14003     uint32 rval = 0;
  14004     int i;
  14005     soc_reg_t fifo_reg[] = {
  14006         L2_MOD_FIFO_ENABLEr,
  14007         AUX_ARB_CONTROLr
  14008     };
  14009     soc_reg_t fifo_fld[] = {
  14010         L2_DELETEf,
  14011         L2_MOD_FIFO_ENABLE_L2_DELETEf
  14012     };
  14013 
  14014     for (i = 0; i < sizeof(fifo_fld) / sizeof(fifo_fld[0]); i++) {
  14015         if (SOC_REG_FIELD_VALID(unit, fifo_reg[i], fifo_fld[i])) {
  14016             SOC_IF_ERROR_RETURN(
  14017                 soc_reg32_get(unit, fifo_reg[i], REG_PORT_ANY, 0, &rval));
  14018             soc_reg_field_set(unit, fifo_reg[i], &rval, fifo_fld[i], enable);
  14019             SOC_IF_ERROR_RETURN(
  14020                 soc_reg32_set(unit, fifo_reg[i], REG_PORT_ANY, 0, rval));
  14021             break;
  14022         }
  14023     }
  14024 
  14025     return SOC_E_NONE;
  14026 }
  14027 
  14028 STATIC uint32
  14029 _soc_l2mode_fifo_enable_insert_field_get(int unit)
  14030 {
  14031     uint32 rval = 0, l2_insert = 0;
  14032     int i;
  14033     soc_reg_t fifo_reg[] = {
  14034         L2_MOD_FIFO_ENABLEr,
  14035         AUX_ARB_CONTROLr
  14036     };
  14037     soc_reg_t fifo_fld[] = {
  14038         L2_INSERTf,
  14039         L2_MOD_FIFO_ENABLE_L2_INSERTf
  14040     };
  14041 
  14042     for (i = 0; i < sizeof(fifo_fld) / sizeof(fifo_fld[0]); i++) {
  14043         if (SOC_REG_FIELD_VALID(unit, fifo_reg[i], fifo_fld[i])) {
  14044             if (soc_reg32_get(unit, fifo_reg[i], REG_PORT_ANY, 0, &rval) < 0) {
  14045                 return 0;
  14046             }
  14047             l2_insert = soc_reg_field_get(unit, fifo_reg[i], rval, fifo_fld[i]);
  14048             break;
  14049         }
  14050     }
  14051     return l2_insert;
  14052 
  14053 }
  14054 
  14055 STATIC int
  14056 _soc_l2mode_fifo_enable_insert_field_set(int unit, uint32 enable)
  14057 {
  14058     uint32 rval = 0;
  14059     int i;
  14060     soc_reg_t fifo_reg[] = {
  14061         L2_MOD_FIFO_ENABLEr,
  14062         AUX_ARB_CONTROLr
  14063     };
  14064     soc_reg_t fifo_fld[] = {
  14065         L2_INSERTf,
  14066         L2_MOD_FIFO_ENABLE_L2_INSERTf
  14067     };
  14068 
  14069     for (i = 0; i < sizeof(fifo_fld) / sizeof(fifo_fld[0]); i++) {
  14070         if (SOC_REG_FIELD_VALID(unit, fifo_reg[i], fifo_fld[i])) {
  14071             SOC_IF_ERROR_RETURN(
  14072                 soc_reg32_get(unit, fifo_reg[i], REG_PORT_ANY, 0, &rval));
  14073             soc_reg_field_set(unit, fifo_reg[i], &rval, fifo_fld[i], enable);
  14074             SOC_IF_ERROR_RETURN(
  14075                 soc_reg32_set(unit, fifo_reg[i], REG_PORT_ANY, 0, rval));
  14076             break;
  14077         }
  14078     }
  14079 
  14080     return SOC_E_NONE;
  14081 }
  14082 
  14083 #endif /* defined(BCM_TRIUMPH3_SUPPORT) */
  14084 
  14085 /* When L2 entries are corrected, l2mode_fifo memwr field must be '0'.
  14086 * Reason1: We need not to produce the memwr event to L2mode_fifo
  14087 * during soc_ser_sram_correction.
  14088 * Reason2: If l2mode_fifo is full and memwr_field is '1', it will lead to recursion.
  14089 * soc_ser_sram_correction -> _soc_mem_write_schan_msg_send -> soc_ser_sram_correction
  14090 * _soc_mem_write_schan_msg_send -> .......
  14091 */
  14092 STATIC void
  14093 _soc_ser_sram_correction_pre(int unit, soc_mem_t mem, uint32 mem_val)
  14094 {
  14095     switch(mem) {
  14096         case L2Xm:
  14097             if (mem_val) {
  14098                 (void)_soc_l2mode_fifo_enable_memwr_field_set(unit, 0);
  14099             }
  14100             break;
  14101         default:
  14102             return;
  14103     }
  14104 }
  14105 
  14106 STATIC void
  14107 _soc_ser_sram_correction_post(int unit, soc_mem_t mem, uint32 mem_val)
  14108 {
  14109     switch(mem) {
  14110         case L2Xm:
  14111             if (mem_val) {
  14112                 (void)_soc_l2mode_fifo_enable_memwr_field_set(unit, 1);
  14113             }
  14114             break;
  14115         default:
  14116             return;
  14117     }
  14118 }
  14119 
  14120 STATIC void
  14121 _soc_ser_sram_correction_init(int unit, soc_mem_t mem, uint32 *mem_val)
  14122 {
  14123     switch(mem) {
  14124         case L2Xm:
  14125             *mem_val = _soc_l2mode_fifo_enable_memwr_field_get(unit);
  14126             break;
  14127         default:
  14128             return ;
  14129     }
  14130     return ;
  14131 }
  14132 #endif /* BCM_ESW_SUPPORT */
  14133 
  14134 /*
  14135  * Function: _soc_mem_write_schan_msg_send
  14136  *
  14137  * Purpose:  Called by soc_mem_write_extended().  Send the requested
  14138  *           schan_msg_t.  On ESW chips, retry errors.  If SER is available,
  14139  *           try to use it to correct errors.
  14140  *
  14141  * Returns:  SOC_E_xxx
  14142  */
  14143 STATIC int
  14144 _soc_mem_write_schan_msg_send(int unit, schan_msg_t *schan_msg, soc_mem_t mem,
  14145                               int blk, int index2)
  14146 {
  14147     int rv;
  14148     int allow_intr = SOC_IS_SAND(unit);
  14149     int entry_dw = soc_mem_entry_words(unit, mem);
  14150 
  14151 #ifdef BCM_ESW_SUPPORT
  14152     uint32 retries_remaining = HASH_MEM_OP_RETRY_COUNT;
  14153     int rv1 = SOC_E_NONE, rv2 = SOC_E_NONE;
  14154     uint32 need_retry = 0;
  14155     int pipe = 0;
  14156     int acc_type;
  14157     uint32 entry[SOC_MAX_MEM_WORDS];
  14158 #ifdef BCM_TOMAHAWK3_SUPPORT
  14159     uint16 dev_id;
  14160     uint8 rev_id;
  14161     
  14162     soc_cm_get_id(unit, &dev_id, &rev_id);
  14163 #endif
  14164     do {
  14165         rv = soc_schan_op(unit, schan_msg, 2 + entry_dw, 0, allow_intr);
  14166 
  14167         if (SOC_E_FAIL == rv &&
  14168             soc_feature(unit, soc_feature_efp_meter_table_write_ignore_nack)) {
  14169             if ((mem == EFP_METER_TABLEm ||
  14170                  mem == EFP_METER_TABLE_PIPE0m ||
  14171                  mem == EFP_METER_TABLE_PIPE1m ||
  14172                  mem == EFP_METER_TABLE_PIPE2m ||
  14173                  mem == EFP_METER_TABLE_PIPE3m ||
  14174                  mem == EFP_METER_TABLE_Xm ||
  14175                  mem == EFP_METER_TABLE_Ym) && ((index2 % 2) == 1)) {
  14176                 /*
  14177                  * Ignore the unexpected NACK during writing to EFP_METER_TABLExxx
  14178                  * since the real error is in the pair index instead of writen index and
  14179                  * the write op can go through successfully
  14180                  */
  14181                 rv = SOC_E_NONE;
  14182                 break;
  14183             }
  14184         }
  14185 
  14186         if (SOC_E_FAIL == rv && soc_feature(unit, soc_feature_shared_hash_mem)) {
  14187             if (retries_remaining == HASH_MEM_OP_RETRY_COUNT) {
  14188                 _soc_ser_sram_correction_init(unit, mem, &need_retry);
  14189             }
  14190             _soc_ser_sram_correction_pre(unit, mem, need_retry);
  14191 
  14192             if (need_retry){
  14193                 rv2 = soc_schan_op(unit, schan_msg, 2 + entry_dw, 0, allow_intr);
  14194             }
  14195             /* If rv2==SOC_E_FAIL, the failure of soc_schan_op is not due to L2_mode_fifo is filled,
  14196             * because we diable memwr fifo events, so we need to correct the memory.
  14197             */
  14198             if (rv2 == SOC_E_FAIL || need_retry == 0) {
  14199                 /* For multiple pipe devices, SER error is attempted from alternative pipe
  14200                  * before attempting for inline correction.
  14201                  * For single pipe devices, inline SER correction is done
  14202                  */
  14203 
  14204                 if (NUM_PIPE(unit) > 1) {
  14205                     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
  14206 #ifdef BCM_TOMAHAWK3_SUPPORT
  14207                         if ((pipe == 2 || pipe == 3 || pipe == 4 || pipe ==5)
  14208                                     && (dev_id == BCM56983_DEVICE_ID)) {
  14209                             continue;
  14210                         }
  14211 #endif
  14212                         /* determine 1st pipe which has the problem */
  14213                         if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
  14214                             acc_type = (pipe == 0)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_0 :
  14215                                        (pipe == 1)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_1 :
  14216                                        (pipe == 2)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_2 :
  14217                                        (pipe == 3)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_3 :
  14218                                        (pipe == 4)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_4 :
  14219                                        (pipe == 5)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_5 :
  14220                                        (pipe == 6)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_6 :
  14221                                                     _SOC_MEM_ADDR_ACC_TYPE_PIPE_7;
  14222                         } else if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2X(unit)) {
  14223                             acc_type = (pipe == 0) ? _SOC_MEM_ADDR_ACC_TYPE_PIPE_X:
  14224                                 _SOC_MEM_ADDR_ACC_TYPE_PIPE_Y;
  14225                         } else {
  14226                             return SOC_E_UNAVAIL;
  14227                         }
  14228 
  14229                         LOG_VERBOSE(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  14230                                   "unit %d: inline ALPM correction LOOP: pipe:%d index %d\n"),
  14231                                    unit, pipe, index2));
  14232                         rv = soc_mem_pipe_select_read(unit, SOC_MEM_NO_FLAGS, mem, MEM_BLOCK_ANY,
  14233                                                       acc_type, index2, entry);
  14234                         if (SOC_E_FAIL == rv) {
  14235                             LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  14236                                       "unit %d: inline ALPM correction: will try ser_correction for pipe %d, index %d\n"),
  14237                                       unit, pipe, index2));
  14238                             break;
  14239                         }
  14240                     }
  14241                 }
  14242                 if (pipe >=0 && pipe < NUM_PIPE(unit)) {
  14243                     rv1 = soc_ser_sram_correction(unit, pipe,
  14244                                                   schan_msg->writecmd.header.v2.dst_blk,
  14245                                                   schan_msg->writecmd.address, mem,
  14246                                                   blk, index2, NULL);
  14247                 }
  14248             } 
  14249             _soc_ser_sram_correction_post(unit, mem, need_retry);
  14250 
  14251             if (rv1 == SOC_E_NONE && retries_remaining > 0) {
  14252                 retries_remaining--;
  14253             } else {
  14254                 retries_remaining = 0; /* Don't try if the correction fails */
  14255             }
  14256         } else if (SOC_E_FAIL == rv && soc_feature(unit, soc_feature_ignore_mem_write_nak)){
  14257             /*
  14258              * In bcm53400 and bcm56160 series, when parity error happened in
  14259              * FP_METER_TABLE/EFP_METER_TABLE, sometimes will always get SOC_E_FAIL.
  14260              * Add retries here to avoid infinite loop.
  14261              */
  14262             if ((mem == EFP_METER_TABLEm) || (mem == FP_METER_TABLEm)) {
  14263                 retries_remaining--;
  14264             }
  14265         } else if (SOC_FAILURE(rv)) {
  14266             retries_remaining--;
  14267         }
  14268     } while (SOC_FAILURE(rv) && retries_remaining > 0);
  14269 
  14270 #else
  14271     rv = soc_schan_op(unit, schan_msg, 2 + entry_dw, 0, allow_intr);
  14272 #endif /* BCM_ESW_SUPPORT */
  14273 
  14274     return rv;
  14275 }
  14276 
  14277 #ifdef ALPM_ENABLE
  14278 void
  14279 _soc_mem_write_alpm2_bnk_fmt_set(int unit, int index, soc_mem_t mem)
  14280 {
  14281 #if defined(BCM_TRIDENT3_SUPPORT)
  14282     int8 fmt;
  14283     int bucket_bank;
  14284 
  14285     bucket_bank = index % soc_mem_index_count(unit, L3_DEFIP_ALPM_RAWm);
  14286     switch (mem) {
  14287         case L3_DEFIP_ALPM_IPV4m:
  14288             fmt = 1;
  14289             break;
  14290         case L3_DEFIP_ALPM_IPV6_64m:
  14291             fmt = 2;
  14292             break;
  14293         case L3_DEFIP_ALPM_IPV6_128m:
  14294             fmt = 3;
  14295             break;
  14296         case L3_DEFIP_ALPM_IPV4_1m:
  14297             fmt = 4;
  14298             break;
  14299         case L3_DEFIP_ALPM_IPV6_64_1m:
  14300             fmt = 5;
  14301             break;
  14302         default:
  14303             fmt = 0;
  14304             break;
  14305     }
  14306 
  14307     _soc_trident3_alpm2_bnk_fmt_set(unit, bucket_bank, fmt);
  14308 #endif
  14309     return;
  14310 }
  14311 #endif
  14312 
  14313 /*
  14314  * Function: _soc_mem_write_alpm_bkt_view_set
  14315  *
  14316  * Purpose:  Called by soc_mem_write_extended().  If writing to the ALPM
  14317  *           memories, add special processing to update the bucket view map.
  14318  *
  14319  * Returns:  Nothing
  14320  */
  14321 STATIC void
  14322 _soc_mem_write_alpm_bkt_view_set(int unit, soc_mem_t mem, int index,
  14323                                  void *entry_data)
  14324 {
  14325 #ifdef ALPM_ENABLE
  14326     if (mem == L3_DEFIP_ALPM_IPV4m || mem == L3_DEFIP_ALPM_IPV4_1m ||
  14327         mem == L3_DEFIP_ALPM_IPV6_64m || mem == L3_DEFIP_ALPM_IPV6_64_1m ||
  14328         mem == L3_DEFIP_ALPM_IPV6_128m) {
  14329         if (soc_mem_field32_get(unit, mem, entry_data, VALIDf)) {
  14330             if (soc_feature(unit, soc_feature_alpm2)) {
  14331                 _soc_mem_write_alpm2_bnk_fmt_set(unit, index, mem);
  14332             } else {
  14333                 if (SOC_IS_TRIDENT2(unit) || SOC_IS_TRIDENT2PLUS(unit)) {
  14334                     _soc_trident2_alpm_bkt_view_set(unit, index, mem);
  14335                 }
  14336 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT) || \
  14337                 defined(BCM_TRIDENT3_SUPPORT)
  14338                 else {
  14339                     soc_alpm_cmn_bkt_view_set(unit, index, mem);
  14340                 }
  14341 #endif
  14342             }
  14343         }
  14344     }
  14345 #endif /* ALPM_ENABLE */
  14346 }
  14347 
  14348 STATIC void
  14349 _soc_mem_write_lpm_view_set(int unit, soc_mem_t mem, int index,
  14350                                  void *entry_data)
  14351 {
  14352 #if defined(BCM_TOMAHAWK_SUPPORT)
  14353 
  14354     int valid = 0;
  14355     soc_mem_t defip_mem = L3_DEFIPm, defip_pair_mem = L3_DEFIP_PAIR_128m;
  14356 
  14357 #if defined(BCM_TOMAHAWK3_SUPPORT)
  14358     if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) {
  14359         defip_mem = L3_DEFIP_LEVEL1m;
  14360         defip_pair_mem = L3_DEFIP_PAIR_LEVEL1m;
  14361     }
  14362 #endif
  14363 
  14364 
  14365     if (SOC_IS_TOMAHAWKX(unit) &&
  14366         soc_feature(unit, soc_feature_l3_defip_map) &&
  14367         (mem == defip_mem ||
  14368          mem == L3_DEFIP_ONLYm)) {
  14369          valid = soc_mem_field32_get(unit, mem, entry_data, VALID0f) ||
  14370                  soc_mem_field32_get(unit, mem, entry_data, VALID1f);
  14371 
  14372         mem = valid ? mem : INVALIDm;
  14373 #if defined(BCM_TOMAHAWK3_SUPPORT)
  14374     if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) {
  14375         _soc_th3_lpm_view_set(unit, index, mem, 0);
  14376     } else
  14377 #endif
  14378         _soc_th_lpm_view_set(unit, index, mem, 0);
  14379     }
  14380     if (SOC_IS_TOMAHAWKX(unit) &&
  14381         soc_feature(unit, soc_feature_l3_defip_map) &&
  14382         (mem == defip_pair_mem ||
  14383          mem == L3_DEFIP_PAIR_128_ONLYm)) {
  14384 
  14385 #if defined(BCM_TOMAHAWK3_SUPPORT)
  14386         if (mem == L3_DEFIP_PAIR_LEVEL1m) {
  14387          valid = soc_mem_field32_get(unit, mem, entry_data, LWR_VALID0f) ||
  14388                  soc_mem_field32_get(unit, mem, entry_data, LWR_VALID1f) ||
  14389                  soc_mem_field32_get(unit, mem, entry_data, UPR_VALID0f) ||
  14390                  soc_mem_field32_get(unit, mem, entry_data, UPR_VALID1f);
  14391          mem = valid ? mem : INVALIDm;
  14392          _soc_th3_lpm_view_set(unit, index, mem, 1);
  14393         } else
  14394 #endif
  14395         {
  14396          valid = soc_mem_field32_get(unit, mem, entry_data, VALID0_LWRf) ||
  14397                  soc_mem_field32_get(unit, mem, entry_data, VALID1_LWRf) ||
  14398                  soc_mem_field32_get(unit, mem, entry_data, VALID0_UPRf) ||
  14399                  soc_mem_field32_get(unit, mem, entry_data, VALID1_UPRf);
  14400         mem = valid ? mem : INVALIDm;
  14401         _soc_th_lpm_view_set(unit, index, mem, 1);
  14402     }
  14403     }
  14404 #endif
  14405 }
  14406 /*
  14407  * Function: _soc_mem_write_td2_shadow_entry_set
  14408  *
  14409  * Purpose:  Called by soc_mem_write_extended().  On TD2, if writing to the
  14410  *           X or Y pipe map tables, update the shadow entry for them.
  14411  *
  14412  * Returns:  SOC_E_xxx
  14413  */
  14414 STATIC int
  14415 _soc_mem_write_td2_shadow_entry_set(int unit, soc_mem_t mem, int index,
  14416                                     void *entry_data)
  14417 {
  14418     int rv = SOC_E_NONE;
  14419 
  14420 #ifdef BCM_TRIDENT2_SUPPORT
  14421     /* For MMU_INTFI_X/YPIPE_FC_MAP_TBL0/1, update software shadow table. */
  14422     if (SOC_IS_TRIDENT2(unit)) {
  14423         if (mem == MMU_INTFI_XPIPE_FC_MAP_TBL0m ||
  14424             mem == MMU_INTFI_XPIPE_FC_MAP_TBL1m ||
  14425             mem == MMU_INTFI_YPIPE_FC_MAP_TBL0m ||
  14426             mem == MMU_INTFI_YPIPE_FC_MAP_TBL1m){
  14427             rv = soc_trident2_fc_map_shadow_entry_set(unit, mem, index,
  14428                                                       entry_data);
  14429         }
  14430     }
  14431 #endif
  14432 
  14433     return rv;
  14434 }
  14435  
  14436 #ifdef HR3LITE_LPM_WAR
  14437 /*
  14438  * Function: _soc_mem_hr3_lpm_duplicate
  14439  *
  14440  * Purpose:  Called by _soc_mem_write_schan_msg_create(). 
  14441  *          This function is used to duplicate a LPM-DATA entry on 
  14442  *          HR3-Lite device. LPM table in HR3-Lite support 64 entries 
  14443  *          only but this LPM TCAM for LPM entry between 32~63 can only 
  14444  *          be hit with LPM-DATA in entry between 512~543.
  14445  *
  14446  * Returns:  SOC_E_xxx
  14447  */
  14448 STATIC int
  14449 _soc_mem_hr3_lpm_duplicate(int unit, soc_mem_t mem, int blk,
  14450             int copyno, int array_index, void *in_entry_data, int index)
  14451 {
  14452     defip_entry_t *lpm_entry = NULL;
  14453     defip_data_only_entry_t lpm_data_entry;
  14454     defip_hit_only_entry_t lpm_hit_entry;
  14455     int lpm_shadow_size = 0;
  14456     void *entry_data = in_entry_data;
  14457     void *lpm_showdow_entry;
  14458     schan_msg_t schan_msg;
  14459     int entry_dw = 0, data_byte_len = 0;
  14460     int src_blk = 0, dst_blk = 0, acc_type = 0;
  14461     int copyno_override = 0; /* If non-zero, will override copyno */
  14462     uint32 maddr;
  14463     uint8 at;
  14464     soc_mem_t lpm_shadow[] = {L3_DEFIP_DATA_ONLYm, L3_DEFIP_HIT_ONLYm};
  14465     soc_mem_t update_mem = INVALIDm;
  14466     int mem_update_cnt = 0;
  14467     int mem_update_id = -1;
  14468     int i;
  14469     uint32  buf;
  14470     soc_mem_info_t      *m;
  14471     soc_field_info_t    *fld;
  14472 
  14473     if (!soc_feature(unit, soc_feature_hr3_lite_lpm_shadow_hit)) {
  14474         return SOC_E_NONE;
  14475     }
  14476 
  14477     mem_update_id = 0;
  14478     if (mem == L3_DEFIPm) {
  14479         mem_update_cnt = 2;
  14480         lpm_entry = entry_data;
  14481     } else {
  14482         mem_update_cnt = 1;
  14483         if (mem == L3_DEFIP_HIT_ONLYm) {
  14484             mem_update_id = 1;
  14485         }
  14486     }
  14487 
  14488     for (i = mem_update_id; mem_update_cnt > 0; mem_update_cnt--, i++) {
  14489         
  14490         /* 
  14491         * L3_DEFIPm in HW view is constucted with three tables of 
  14492         * LPM-TCAM, LPM-DATA and LPM_HTI.
  14493         *  - This WAR is to duplicate LPM-DATA and LPM-HIT entry.
  14494         */
  14495         update_mem = lpm_shadow[i];
  14496         LOG_INFO(BSL_LS_SOC_LPM, (BSL_META_U(unit, "HR3-Lite LPM_WAR :"
  14497                 "updateing mem=%s,index=%d\n"), 
  14498                 SOC_MEM_NAME(unit,update_mem), index));
  14499         if (lpm_entry != NULL) {
  14500             m = &SOC_MEM_INFO(unit, update_mem);
  14501             if (update_mem == L3_DEFIP_DATA_ONLYm) {
  14502                 lpm_shadow_size = sizeof(defip_data_only_entry_t);
  14503                 lpm_showdow_entry = &lpm_data_entry;
  14504             } else {
  14505                 lpm_shadow_size = sizeof(defip_hit_only_entry_t);
  14506                 lpm_showdow_entry = &lpm_hit_entry;
  14507             }
  14508             sal_memset(lpm_showdow_entry, 0, lpm_shadow_size);
  14509             for (fld = &m->fields[0]; fld < &m->fields[m->nFields]; fld++) {
  14510                 
  14511                 buf = soc_L3_DEFIPm_field32_get(unit, lpm_entry, fld->field);
  14512                 soc_mem_field32_set(unit, update_mem, 
  14513                         lpm_showdow_entry, fld->field, buf);
  14514             }
  14515             /* assign processing entry_data to this updating LPM shadow entry */
  14516             entry_data = lpm_showdow_entry;
  14517         }
  14518         
  14519         /* start the LPM shadow update */
  14520         mem = update_mem;
  14521 
  14522         if (bsl_check(bslLayerSoc, bslSourceMem, bslSeverityNormal, unit)) {
  14523             LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  14524                                 "soc_mem_write unit %d: %s.%s[%d]: "),
  14525                     unit, SOC_MEM_NAME(unit, mem),
  14526                     SOC_BLOCK_NAME(unit, copyno), index));
  14527             soc_mem_entry_dump(unit, mem, entry_data, BSL_INFO|BSL_LS_SOC_SOCMEM);
  14528             LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  14529                                 "\n")));
  14530         }
  14531         /* start on LPM-DATAm duplication */
  14532         entry_dw = soc_mem_entry_words(unit, mem);
  14533         data_byte_len = entry_dw * sizeof (uint32);
  14534     
  14535         schan_msg_clear(&schan_msg);
  14536         acc_type = SOC_MEM_ACC_TYPE(unit, mem);
  14537         src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit));
  14538     
  14539         sal_memcpy(schan_msg.writecmd.data, entry_data, data_byte_len);
  14540         soc_mem_write_copyno_update(unit, mem, &copyno, &copyno_override);
  14541     
  14542         maddr = soc_mem_addr_get(unit, mem, array_index, blk, index, &at);
  14543         schan_msg.writecmd.address = maddr;
  14544     
  14545         soc_mem_dst_blk_update(unit, blk, maddr, &dst_blk);
  14546     
  14547         soc_schan_header_cmd_set(unit, &schan_msg.header, WRITE_MEMORY_CMD_MSG,
  14548                 dst_blk, src_blk, acc_type, data_byte_len, 0, 0);
  14549         SOC_IF_ERROR_RETURN(_soc_mem_write_schan_msg_send(unit, 
  14550                 &schan_msg, mem, blk, index));
  14551         LOG_INFO(BSL_LS_SOC_LPM, (BSL_META_U(unit, "HR3-Lite LPM_WAR :"
  14552                 "mem=%s(%d) duplicated\n"), 
  14553                 SOC_MEM_NAME(unit,update_mem), index));
  14554     }
  14555 
  14556     return SOC_E_NONE;
  14557 }
  14558 #endif 
  14559 #ifdef BCM_TOMAHAWK3_SUPPORT
  14560 /*
  14561  * Function: _soc_th3_mem_write_schan_msg_create
  14562  *
  14563  * Purpose:  Called by soc_mem_write_extended().  Create the schan_msg_t struct
  14564  *           and send it down the line using _soc_mem_write_schan_msg_send().
  14565  *           Set copyno=COPYNO_ALL for all copies of the memory.
  14566  *
  14567  * Returns:  SOC_E_xxx
  14568  */
  14569 STATIC int
  14570 _soc_th3_mem_write_schan_msg_create(int unit, uint32 flags,
  14571                                 soc_mem_t mem, int copyno,
  14572                                 int array_index, void *entry_data_ptr,
  14573                                 void *entry_data,
  14574                                 uint32 *cache_entry_data,
  14575                                 uint32 *converted_entry_data,
  14576                                 int index, int no_cache, int acc_type)
  14577 {
  14578     int blk;
  14579     int index2;
  14580     schan_msg_t schan_msg;
  14581     int src_blk, dst_blk;
  14582     int copyno_override = 0; /* If non-zero, will override copyno */
  14583     uint32 maddr;
  14584     uint8 at;
  14585     int entry_dw = soc_mem_entry_words(unit, mem);
  14586     int data_byte_len = entry_dw * sizeof (uint32);
  14587     soc_mem_t mem_for_write = mem;
  14588 
  14589     /*
  14590      * Setup S-Channel command packet
  14591      *
  14592      * NOTE: the datalen field matters only for the Write Memory and
  14593      * Write Register commands, where it is used only by the CMIC to
  14594      * determine how much data to send, and is in units of bytes.
  14595      */
  14596     schan_msg_clear(&schan_msg);
  14597     src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit));
  14598 
  14599     sal_memcpy(schan_msg.writecmd.data, entry_data_ptr,
  14600                entry_dw * sizeof(uint32));
  14601 
  14602     soc_mem_write_copyno_update(unit, mem_for_write, &copyno, &copyno_override);
  14603 
  14604     if (bsl_check(bslLayerSoc, bslSourceMem, bslSeverityNormal, unit)) {
  14605         LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  14606                             "soc_mem_write unit %d: %s.%s[%d]: "),
  14607                  unit, SOC_MEM_NAME(unit, mem),
  14608                  SOC_BLOCK_NAME(unit, copyno), index));
  14609         soc_mem_entry_dump(unit, mem, entry_data_ptr, BSL_INFO|BSL_LS_SOC_SOCMEM);
  14610         LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  14611                             "\n")));
  14612     }
  14613 
  14614     /* Write to one or all copies of the memory */
  14615     SOC_MEM_BLOCK_ITER(unit, mem_for_write, blk) {
  14616         if (copyno_override) {
  14617             blk = copyno = copyno_override;
  14618         } else if (copyno != COPYNO_ALL && copyno != blk) {
  14619             continue;
  14620         }
  14621 
  14622         index2 = index;
  14623         if (!(flags & SOC_MEM_DONT_MAP_INDEX)) {
  14624             _soc_mem_read_defip_index_map(unit, mem, index, &index2);
  14625         }
  14626 
  14627         if ((flags & SOC_MEM_DONT_MAP_INDEX) &&
  14628             (mem == L3_DEFIPm ||
  14629              mem == L3_DEFIP_ONLYm ||
  14630              mem == L3_DEFIP_DATA_ONLYm ||
  14631              mem == L3_DEFIP_HIT_ONLY_Xm ||
  14632              mem == L3_DEFIP_HIT_ONLY_Ym ||
  14633              mem == L3_DEFIP_HIT_ONLYm ||
  14634              mem == L3_DEFIP_PAIR_128m ||
  14635              mem == L3_DEFIP_PAIR_128_ONLYm ||
  14636              mem == L3_DEFIP_PAIR_128_DATA_ONLYm ||
  14637              mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm ||
  14638              mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym ||
  14639              mem == L3_DEFIP_PAIR_128_HIT_ONLYm)) {
  14640             /* Don`t update cache when writing L3_DEFIP with physical index */
  14641             no_cache = 1;
  14642         }
  14643         maddr = soc_mem_addr_get(unit, mem_for_write, array_index, blk, index2, &at);
  14644         schan_msg.writecmd.address = maddr;
  14645 
  14646         soc_mem_dst_blk_update(unit, blk, maddr, &dst_blk);
  14647   
  14648         soc_schan_header_cmd_set(unit, &schan_msg.header, WRITE_MEMORY_CMD_MSG,
  14649                                      dst_blk, src_blk, acc_type, data_byte_len, 0,
  14650                                      0);
  14651 
  14652         /* Write header + address + entry_dw data DWORDs */
  14653         /* Note: The hardware does not send WRITE_MEMORY_ACK_MSG. */
  14654         if (2 + entry_dw > CMIC_SCHAN_WORDS(unit)) {
  14655            LOG_WARN(BSL_LS_SOC_SOCMEM,
  14656                     (BSL_META_U(unit,
  14657                         "soc_mem_write: assert will fail for memory %s\n"),
  14658                     SOC_MEM_NAME(unit, mem)));
  14659         }
  14660 
  14661 #ifdef CRASH_RECOVERY_SUPPORT
  14662         if (!(BCM_UNIT_DO_HW_READ_WRITE(unit))){
  14663             SOC_IF_ERROR_RETURN(_soc_mem_write_schan_msg_send(unit, &schan_msg, mem_for_write,
  14664                                                           blk, index2));
  14665         }
  14666 #else
  14667             SOC_IF_ERROR_RETURN(_soc_mem_write_schan_msg_send(unit, &schan_msg, mem_for_write,
  14668                                                           blk, index2));
  14669 #endif /* CRASH_RECOVERY_SUPPORT */
  14670 
  14671         if (copyno_override)
  14672             break;
  14673 
  14674         /* we dont cache in case block is a broadcast_block*/
  14675         _soc_mem_write_cache_update(unit, mem, blk, no_cache, index,
  14676                                     array_index, entry_data, entry_data_ptr,
  14677                                     cache_entry_data, converted_entry_data);
  14678 
  14679         /* Update the cache for other memory copies of this memory view */
  14680 #ifdef BCM_TRX_SUPPORT
  14681         _soc_mem_aggr_cache_update(unit, mem, blk, no_cache,
  14682                                 index, index,
  14683                                 array_index, entry_data);
  14684 #endif /* BCM_TRX_SUPPORT */
  14685     }
  14686     if (copyno_override) {
  14687         /* if block is a broadcast_block we cach seperatly for each block*/
  14688         SOC_MEM_BLOCK_ITER(unit, mem, blk) {
  14689             _soc_mem_write_cache_update(unit, mem, blk, no_cache, index,
  14690                                         array_index, entry_data, entry_data_ptr,
  14691                                         cache_entry_data, converted_entry_data);
  14692         }
  14693 
  14694     }
  14695 
  14696     _soc_mem_write_lpm_view_set(unit, mem, index2, entry_data);
  14697 
  14698     return SOC_E_NONE;
  14699 }
  14700 #endif
  14701 /*
  14702  * Function: _soc_mem_write_schan_msg_create
  14703  *
  14704  * Purpose:  Called by soc_mem_write_extended().  Create the schan_msg_t struct
  14705  *           and send it down the line using _soc_mem_write_schan_msg_send().
  14706  *           Set copyno=COPYNO_ALL for all copies of the memory.
  14707  *
  14708  * Returns:  SOC_E_xxx
  14709  */
  14710 STATIC int
  14711 _soc_mem_write_schan_msg_create(int unit, uint32 flags, 
  14712                                 soc_mem_t mem, int copyno,
  14713                                 int array_index, void *entry_data_ptr,
  14714                                 void *entry_data,
  14715                                 uint32 *cache_entry_data,
  14716                                 uint32 *converted_entry_data,
  14717                                 int index, int no_cache)
  14718 {
  14719     int blk;
  14720     int index2;
  14721     schan_msg_t schan_msg;
  14722     int src_blk, dst_blk, acc_type;
  14723     int copyno_override = 0; /* If non-zero, will override copyno */
  14724     uint32 maddr;
  14725     uint8 at;
  14726     int entry_dw = soc_mem_entry_words(unit, mem);
  14727     int data_byte_len = entry_dw * sizeof (uint32);
  14728     soc_mem_t mem_for_write = mem;
  14729 #ifdef HR3LITE_LPM_WAR
  14730     int     lpm_data_shadow_index = -1;
  14731 #endif
  14732 
  14733 #if defined(BCM_TOMAHAWK_SUPPORT)
  14734     /*
  14735     * MEMWR to MPLS_ENTRY uses Read-Modify-Write, when a double-bit error is detected
  14736     * during read, the corrupt data will be used to compute LP control word. As a result, LP
  14737     * control word get corrupted and cannot be recovered in current SER logic. So when
  14738     * launching MEMWR to MPLS_ENTRY, we translate it to MEMWR to MPLS_ENTRY_ECC
  14739     * on TH,TH+.
  14740     */
  14741     if ((SOC_IS_TOMAHAWK(unit) || SOC_IS_TOMAHAWKPLUS(unit)) &&
  14742         (MPLS_ENTRYm == mem)) {
  14743         mem_for_write = MPLS_ENTRY_ECCm;
  14744     }
  14745 #endif
  14746 
  14747     /*
  14748      * Setup S-Channel command packet
  14749      *
  14750      * NOTE: the datalen field matters only for the Write Memory and
  14751      * Write Register commands, where it is used only by the CMIC to
  14752      * determine how much data to send, and is in units of bytes.
  14753      */
  14754     schan_msg_clear(&schan_msg);
  14755     acc_type = SOC_MEM_ACC_TYPE(unit, mem_for_write);
  14756     src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit));
  14757 
  14758     sal_memcpy(schan_msg.writecmd.data, entry_data_ptr,
  14759                entry_dw * sizeof(uint32));
  14760 
  14761     soc_mem_write_copyno_update(unit, mem_for_write, &copyno, &copyno_override);
  14762 
  14763     if (bsl_check(bslLayerSoc, bslSourceMem, bslSeverityNormal, unit)) {
  14764         LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  14765                             "soc_mem_write unit %d: %s.%s[%d]: "),
  14766                  unit, SOC_MEM_NAME(unit, mem),
  14767                  SOC_BLOCK_NAME(unit, copyno), index));
  14768         soc_mem_entry_dump(unit, mem, entry_data_ptr, BSL_INFO|BSL_LS_SOC_SOCMEM);
  14769         LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  14770                             "\n")));
  14771     }
  14772 
  14773 #ifdef HR3LITE_LPM_WAR
  14774     if (soc_feature(unit, soc_feature_hr3_lite_lpm_shadow_hit) && 
  14775             NEED_HR3LITE_LPM_SHADOW(mem)) {
  14776         lpm_data_shadow_index = HR3LITE_LPM_HIT_INDEX2(index);
  14777     }
  14778 #endif  /* HR3LITE_LPM_WAR */
  14779 
  14780     /* Write to one or all copies of the memory */
  14781     SOC_MEM_BLOCK_ITER(unit, mem_for_write, blk) {
  14782         if (copyno_override) {
  14783             blk = copyno = copyno_override;
  14784         } else if (copyno != COPYNO_ALL && copyno != blk) {
  14785             continue;
  14786         }
  14787 
  14788         index2 = index;
  14789         if (!(flags & SOC_MEM_DONT_MAP_INDEX)) {
  14790             _soc_mem_read_defip_index_map(unit, mem, index, &index2);
  14791         }
  14792 
  14793         if ((flags & SOC_MEM_DONT_MAP_INDEX) &&
  14794             (mem == L3_DEFIPm ||
  14795              mem == L3_DEFIP_ONLYm ||
  14796              mem == L3_DEFIP_DATA_ONLYm ||
  14797              mem == L3_DEFIP_HIT_ONLY_Xm ||
  14798              mem == L3_DEFIP_HIT_ONLY_Ym ||
  14799              mem == L3_DEFIP_HIT_ONLYm ||
  14800              mem == L3_DEFIP_PAIR_128m ||
  14801              mem == L3_DEFIP_PAIR_128_ONLYm ||
  14802              mem == L3_DEFIP_PAIR_128_DATA_ONLYm ||
  14803              mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm ||
  14804              mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym ||
  14805              mem == L3_DEFIP_PAIR_128_HIT_ONLYm)) {
  14806             /* Don`t update cache when writing L3_DEFIP with physical index */
  14807             no_cache = 1;
  14808         }
  14809         maddr = soc_mem_addr_get(unit, mem_for_write, array_index, blk, index2, &at);
  14810         schan_msg.writecmd.address = maddr;
  14811 
  14812         soc_mem_dst_blk_update(unit, blk, maddr, &dst_blk);
  14813 
  14814         soc_schan_header_cmd_set(unit, &schan_msg.header, WRITE_MEMORY_CMD_MSG,
  14815                                  dst_blk, src_blk, acc_type, data_byte_len, 0,
  14816                                  0);
  14817 
  14818         /* Write header + address + entry_dw data DWORDs */
  14819         /* Note: The hardware does not send WRITE_MEMORY_ACK_MSG. */
  14820         if (2 + entry_dw > CMIC_SCHAN_WORDS(unit)) {
  14821            LOG_WARN(BSL_LS_SOC_SOCMEM,
  14822                     (BSL_META_U(unit,
  14823                         "soc_mem_write: assert will fail for memory %s\n"),
  14824                     SOC_MEM_NAME(unit, mem)));
  14825         }
  14826 
  14827 #ifdef CRASH_RECOVERY_SUPPORT
  14828         if (!(BCM_UNIT_DO_HW_READ_WRITE(unit))){
  14829             SOC_IF_ERROR_RETURN(_soc_mem_write_schan_msg_send(unit, &schan_msg, mem_for_write,
  14830                                                           blk, index2));
  14831         }
  14832 #else
  14833             SOC_IF_ERROR_RETURN(_soc_mem_write_schan_msg_send(unit, &schan_msg, mem_for_write,
  14834                                                           blk, index2));
  14835 #endif /* CRASH_RECOVERY_SUPPORT */
  14836 
  14837 #ifdef HR3LITE_LPM_WAR
  14838         if (lpm_data_shadow_index != -1) {
  14839             LOG_INFO(BSL_LS_SOC_LPM, (BSL_META_U(unit, "HR3-Lite LPM_WAR :"
  14840                     "request mem=%s(%d) duplicate on LPM DATA/HIT entry(%d)\n"), 
  14841                     SOC_MEM_NAME(unit,mem), index, lpm_data_shadow_index));
  14842             /* coverity[stack_use_overflow] */
  14843             SOC_IF_ERROR_RETURN(_soc_mem_hr3_lpm_duplicate(unit, mem, blk, 
  14844                     copyno, array_index, entry_data, lpm_data_shadow_index));
  14845         }
  14846 #endif  /* HR3LITE_LPM_WAR */
  14847 
  14848         if (copyno_override)
  14849             break;
  14850 
  14851         /* we dont cache in case block is a broadcast_block*/
  14852         _soc_mem_write_cache_update(unit, mem, blk, no_cache, index,
  14853                                     array_index, entry_data, entry_data_ptr,
  14854                                     cache_entry_data, converted_entry_data);
  14855 
  14856         /* Update the cache for other memory copies of this memory view */
  14857 #ifdef BCM_TRX_SUPPORT
  14858         _soc_mem_aggr_cache_update(unit, mem, blk, no_cache,
  14859                                 index, index,
  14860                                 array_index, entry_data);
  14861 #endif /* BCM_TRX_SUPPORT */
  14862     }
  14863     if (copyno_override) {
  14864         /* if block is a broadcast_block we cach seperatly for each block*/
  14865         SOC_MEM_BLOCK_ITER(unit, mem, blk) {
  14866             _soc_mem_write_cache_update(unit, mem, blk, no_cache, index,
  14867                                         array_index, entry_data, entry_data_ptr,
  14868                                         cache_entry_data, converted_entry_data);
  14869         }
  14870 
  14871     }
  14872 
  14873     _soc_mem_write_lpm_view_set(unit, mem, index2, entry_data);
  14874 
  14875     return SOC_E_NONE;
  14876 }
  14877 
  14878 /*
  14879  * Function:
  14880  *    _soc_mem_write_extended
  14881  * Purpose:
  14882  *    Write a memory internal to the SOC.
  14883  * Notes:
  14884  *    GBP/CBP memory should only accessed when MMU is in DEBUG mode.
  14885  */
  14886 STATIC int
  14887 _soc_mem_write_extended(int unit, uint32 flags, soc_mem_t mem,
  14888                /* in memory arrays this is the element index in the array, otherwise 0 */
  14889                unsigned array_index,
  14890                int copyno, /* Use COPYNO_ALL for all */
  14891                int index, void *entry_data)
  14892 {
  14893     soc_mem_info_t *meminfo = &SOC_MEM_INFO(unit, mem);
  14894     int no_cache;
  14895     int rv = SOC_E_NONE;
  14896     void *entry_data_ptr;
  14897     uint32 converted_entry_data[SOC_MAX_MEM_WORDS];
  14898     uint32 cache_entry_data[SOC_MAX_MEM_WORDS];
  14899 #ifdef BCM_TOMAHAWK3_SUPPORT
  14900     int acc_type = 0, j = 0;
  14901     uint16 dev_id;
  14902     uint8 rev_id;
  14903 #endif
  14904 #ifdef CRASH_RECOVERY_SUPPORT
  14905 /* Use crash recovery defined callback for access */
  14906     if (BCM_UNIT_DO_HW_READ_WRITE(unit))
  14907     {
  14908         if(Hw_Log_List[unit].Access_cb.mem_write)
  14909         {
  14910             Hw_Log_List[unit].Access_cb.mem_write(unit, mem, array_index, copyno, index, entry_data);
  14911         }
  14912     }
  14913 #endif /* CRASH_RECOVERY_SUPPORT */
  14914 
  14915     SOC_IF_ERROR_RETURN(_soc_mem_write_sanity_check(unit, flags, mem, index));
  14916 
  14917     _soc_mem_write_ext_cache_set(flags, &index, &no_cache);
  14918     if (_soc_mem_hercules_write_attempt(unit, mem, copyno, index, entry_data,
  14919                                         &rv)) {
  14920         return rv;
  14921     }
  14922 
  14923     entry_data_ptr = soc_mem_write_tcam_to_hw_format(unit, mem, entry_data,
  14924                                                       cache_entry_data,
  14925                                                       converted_entry_data);
  14926 #ifdef BCM_TOMAHAWK3_SUPPORT
  14927     if (SOC_MEM_IS_VALID(unit, mem)) {
  14928         acc_type = SOC_MEM_ACC_TYPE(unit, mem);
  14929     }
  14930     soc_cm_get_id(unit, &dev_id, &rev_id);
  14931 #endif
  14932 
  14933 #ifdef ALPM_ENABLE
  14934     if (mem == L3_DEFIP_ALPM_ECCm || mem == L3_DEFIP_ALPM_IPV4m ||
  14935         mem == L3_DEFIP_ALPM_IPV4_1m || mem == L3_DEFIP_ALPM_IPV6_64m ||
  14936         mem == L3_DEFIP_ALPM_IPV6_128m || mem == L3_DEFIP_ALPM_IPV6_64_1m ||
  14937         mem == L3_DEFIP_ALPM_RAWm) {
  14938         SOC_ALPM_LPM_LOCK(unit);
  14939     } else
  14940 #endif
  14941     {
  14942     MEM_LOCK(unit, mem);
  14943     }
  14944     _soc_mem_read_tr3_esm_lock(unit, copyno);
  14945 
  14946 #ifdef BCM_TOMAHAWK3_SUPPORT
  14947     if (((acc_type == 9 || acc_type == 14) && (dev_id == BCM56983_DEVICE_ID))) {
  14948         for (j = 0; j < 4; j++) {
  14949             switch(j) {
  14950                 case 0 : acc_type = 0;
  14951                          break;
  14952                 case 1 : acc_type = 1;
  14953                          break;
  14954                 case 2 : acc_type = 6;
  14955                          break;
  14956                 case 3 : acc_type = 7;
  14957                          break;
  14958             }
  14959 
  14960             /* coverity[stack_use_overflow] */
  14961             rv = _soc_th3_mem_write_schan_msg_create(unit, flags, mem, copyno, array_index,
  14962                                                  entry_data_ptr, entry_data,
  14963                                                  cache_entry_data, converted_entry_data,
  14964                                                  index, no_cache, acc_type);
  14965         }
  14966     } else if (acc_type == 16 && (dev_id == BCM56983_DEVICE_ID)) {
  14967         acc_type = 0;
  14968         /* coverity[stack_use_overflow] */
  14969         rv = _soc_th3_mem_write_schan_msg_create(unit, flags, mem, copyno, array_index,
  14970                                              entry_data_ptr, entry_data,
  14971                                              cache_entry_data, converted_entry_data,
  14972                                              index, no_cache, acc_type);
  14973     }
  14974 #if 0
  14975 SDK-166723 fix : Commenting this code as it causes invalid nxt hop mac to be updated
  14976    into dst mac of the packet
  14977       else if (acc_type == 15 && (dev_id == BCM56983_DEVICE_ID)) {
  14978         for (j = 0; j < 2; j++) {
  14979             switch(j) {
  14980                 case 0 : acc_type = 0;
  14981                         break;
  14982                 case 1 : acc_type = 6;
  14983                         break;
  14984             }
  14985             /* coverity[stack_use_overflow] */
  14986             rv = _soc_th3_mem_write_schan_msg_create(unit, flags, mem, copyno, array_index,
  14987                                              entry_data_ptr, entry_data,
  14988                                              cache_entry_data, converted_entry_data,                                                               index, no_cache, acc_type);
  14989         }
  14990     }
  14991 #endif
  14992 else
  14993 #endif
  14994     {
  14995         /* coverity[stack_use_overflow] */
  14996         rv = _soc_mem_write_schan_msg_create(unit, flags, mem, copyno, array_index,
  14997                                              entry_data_ptr, entry_data,
  14998                                              cache_entry_data, converted_entry_data,
  14999                                              index, no_cache);
  15000     }
  15001     if (SOC_SUCCESS(rv)) {
  15002         _soc_mem_write_alpm_bkt_view_set(unit, mem, index, entry_data);
  15003         rv = _soc_mem_write_td2_shadow_entry_set(unit, mem, index, entry_data);
  15004     }
  15005 
  15006     _soc_mem_read_tr3_esm_unlock(unit, copyno);
  15007 #ifdef ALPM_ENABLE
  15008     if (mem == L3_DEFIP_ALPM_ECCm || mem == L3_DEFIP_ALPM_IPV4m ||
  15009         mem == L3_DEFIP_ALPM_IPV4_1m || mem == L3_DEFIP_ALPM_IPV6_64m ||
  15010         mem == L3_DEFIP_ALPM_IPV6_128m || mem == L3_DEFIP_ALPM_IPV6_64_1m ||
  15011         mem == L3_DEFIP_ALPM_RAWm) {
  15012         SOC_ALPM_LPM_UNLOCK(unit);
  15013     } else
  15014 #endif
  15015     {
  15016     MEM_UNLOCK(unit, mem);
  15017     }
  15018 
  15019     if (NULL != meminfo->snoop_cb) {
  15020         if (SOC_MEM_SNOOP_WRITE & meminfo->snoop_flags) {
  15021             meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_WRITE,
  15022                               copyno, index, index, entry_data_ptr,
  15023                               meminfo->snoop_user_data);
  15024         }
  15025         if (SOC_MEM_SNOOP_WRITE_COUNT & meminfo->snoop_flags) {
  15026             meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_WRITE_COUNT,
  15027                               copyno, index, index, entry_data_ptr,
  15028                               meminfo->snoop_user_data);
  15029         }
  15030     }
  15031 
  15032     return rv;
  15033 }
  15034 
  15035 #ifdef BCM_TRIUMPH2_SUPPORT
  15036 STATIC int
  15037 _soc_mem_write(int unit, soc_mem_t mem,
  15038                /* in memory arrays this is the element index in the array, otherwise 0 */
  15039                unsigned array_index,
  15040                int copyno,    /* Use COPYNO_ALL for all */
  15041                int index, void *entry_data)
  15042 {
  15043     return _soc_mem_write_extended(unit, SOC_MEM_NO_FLAGS, mem,
  15044                                    array_index, copyno, index, entry_data);
  15045 }
  15046 #endif /* BCM_TRIUMPH2_SUPPORT */
  15047 
  15048 /*
  15049  * Function:
  15050  *    soc_mem_pipe_select_write
  15051  * Purpose:
  15052  *    Write a memory internal to the SOC with pipe selection.
  15053  * Notes:
  15054  *    GBP/CBP memory should only accessed when MMU is in DEBUG mode.
  15055  */
  15056 
  15057 int
  15058 soc_mem_pipe_select_write(int unit,
  15059                           uint32 flags,
  15060                           soc_mem_t mem,
  15061                           int copyno,    /* Use COPYNO_ALL for all */
  15062                           int acc_type,
  15063                           int index,
  15064                           void *entry_data)
  15065 {
  15066     schan_msg_t schan_msg;
  15067     int blk;
  15068     soc_mem_info_t *meminfo; 
  15069     int entry_dw;
  15070     uint32 *cache;
  15071     uint32 maddr;
  15072     uint8 at, *vmap;
  15073     int no_cache;
  15074     int index2, allow_intr=0;
  15075     int rv;
  15076     int src_blk, dst_blk, data_byte_len;
  15077     void *entry_data_ptr;
  15078 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT)
  15079     uint32 converted_entry_data[SOC_MAX_MEM_WORDS];
  15080     uint32 cache_entry_data[SOC_MAX_MEM_WORDS];
  15081 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */
  15082 #ifdef BCM_ESW_SUPPORT
  15083     uint8  write_retry_attempt = 0;
  15084     int rv1 = SOC_E_NONE, rv2 = SOC_E_NONE;
  15085     int pipe = SOC_PIPE_ANY;
  15086     uint32 need_retry = 0;
  15087 #endif
  15088     int entry_num_max = 0;
  15089 
  15090     SOC_MEM_ALIAS_TO_ORIG(unit,mem);
  15091     entry_dw = soc_mem_entry_words(unit, mem);
  15092 
  15093     if (!soc_feature(unit, soc_feature_two_ingress_pipes)) {
  15094         /* Not a relevant device */
  15095         return SOC_E_UNAVAIL;
  15096     }
  15097 
  15098     if (!soc_mem_is_valid(unit, mem)) {
  15099         return SOC_E_MEMORY;
  15100     }
  15101     meminfo = &SOC_MEM_INFO(unit, mem);
  15102 
  15103     DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, TRUE));
  15104 
  15105     if ((flags & SOC_MEM_DONT_USE_CACHE) == SOC_MEM_DONT_USE_CACHE) {
  15106         no_cache = 1;
  15107     } else {
  15108         no_cache = 0;
  15109     }
  15110 
  15111     if (meminfo->flags & SOC_MEM_FLAG_READONLY) {
  15112         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  15113                   (BSL_META_U(unit,
  15114                               "soc_mem_write: attempt to write R/O memory %s\n"),
  15115                    SOC_MEM_NAME(unit, mem)));
  15116         return SOC_E_INTERNAL;
  15117     }
  15118 
  15119 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT)
  15120     if (soc_feature(unit, soc_feature_xy_tcam) &&
  15121         (meminfo->flags & SOC_MEM_FLAG_CAM) &&
  15122         (!(meminfo->flags & SOC_MEM_FLAG_EXT_CAM))) {
  15123         entry_data_ptr = converted_entry_data;
  15124         _soc_mem_tcam_dm_to_xy(unit, mem, 1, entry_data, entry_data_ptr,
  15125                                cache_entry_data);
  15126     } else
  15127 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */
  15128     {
  15129         entry_data_ptr = entry_data;
  15130     }
  15131 
  15132     /*
  15133      * Setup S-Channel command packet
  15134      *
  15135      * NOTE: the datalen field matters only for the Write Memory and
  15136      * Write Register commands, where it is used only by the CMIC to
  15137      * determine how much data to send, and is in units of bytes.
  15138      */
  15139 
  15140     schan_msg_clear(&schan_msg);
  15141     data_byte_len = entry_dw * sizeof (uint32);
  15142     src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit));
  15143     sal_memcpy(schan_msg.writecmd.data,
  15144                entry_data_ptr,
  15145                entry_dw * sizeof (uint32));
  15146 
  15147     if (copyno != COPYNO_ALL) {
  15148         if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) {
  15149             LOG_WARN(BSL_LS_SOC_SOCMEM,
  15150                      (BSL_META_U(unit,
  15151                                  "soc_mem_write: invalid block %d for memory %s\n"),
  15152                       copyno, SOC_MEM_NAME(unit, mem)));
  15153             return SOC_E_PARAM;
  15154         }
  15155     }
  15156 
  15157     /*
  15158      * When checking index, check for 0 instead of soc_mem_index_min.
  15159      * Diagnostics need to read/write index 0 of Strata ARL and GIRULE.
  15160      */
  15161     if ((flags & SOC_MEM_DONT_MAP_INDEX) &&
  15162         (mem == L3_DEFIPm ||
  15163          mem == L3_DEFIP_LEVEL1m ||
  15164          mem == L3_DEFIP_ONLYm ||
  15165          mem == L3_DEFIP_DATA_ONLYm ||
  15166          mem == L3_DEFIP_HIT_ONLY_Xm ||
  15167          mem == L3_DEFIP_HIT_ONLY_Ym ||
  15168          mem == L3_DEFIP_HIT_ONLYm ||
  15169          mem == L3_DEFIP_PAIR_128m ||
  15170          mem == L3_DEFIP_PAIR_LEVEL1m ||
  15171          mem == L3_DEFIP_PAIR_128_ONLYm ||
  15172          mem == L3_DEFIP_PAIR_128_DATA_ONLYm ||
  15173          mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm ||
  15174          mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym ||
  15175          mem == L3_DEFIP_PAIR_128_HIT_ONLYm)) {
  15176         if (_soc_mem_defip_index_is_invalid(unit, mem, index) == TRUE) {
  15177             return SOC_E_PARAM;
  15178         }
  15179         /* Don`t update cache when writing L3_DEFIP with physical index */
  15180         no_cache = 1;
  15181     } else {
  15182         entry_num_max = soc_mem_index_max(unit, mem);
  15183 
  15184         if (index < 0 || index > entry_num_max) {
  15185             LOG_WARN(BSL_LS_SOC_SOCMEM,
  15186                      (BSL_META_U(unit,
  15187                                  "soc_mem_pipe_select_write: invalid index %d for memory %s acc_type %d\n"),
  15188                       index, SOC_MEM_NAME(unit, mem), acc_type));
  15189             return SOC_E_PARAM;
  15190         }
  15191     }
  15192 
  15193     if (_soc_mem_read_tcam_is_invalid(unit, mem, index) == TRUE) {
  15194         LOG_WARN(BSL_LS_SOC_SOCMEM,
  15195                  (BSL_META_U(unit,
  15196                              "soc_mem_pipe_select_write: invalid index %d for memory %s\n"),
  15197                   index, SOC_MEM_NAME(unit, mem)));
  15198         return SOC_E_PARAM;
  15199     }
  15200 
  15201     if (bsl_check(bslLayerSoc, bslSourceMem, bslSeverityNormal, unit)) {
  15202         LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  15203                             "soc_mem_pipe_select_write unit %d: %s.%s[%d]: "),
  15204                  unit, SOC_MEM_NAME(unit, mem),
  15205                  SOC_BLOCK_NAME(unit, copyno), index));
  15206         soc_mem_entry_dump(unit, mem, entry_data_ptr, BSL_INFO|BSL_LS_SOC_SOCMEM);
  15207         LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  15208                             "\n")));
  15209     }
  15210 
  15211     /* Write to one or all copies of the memory */
  15212 
  15213     rv = SOC_E_NONE;
  15214 
  15215 #ifdef ALPM_ENABLE
  15216     if (mem == L3_DEFIP_ALPM_ECCm || mem == L3_DEFIP_ALPM_IPV4m ||
  15217         mem == L3_DEFIP_ALPM_IPV4_1m || mem == L3_DEFIP_ALPM_IPV6_64m ||
  15218         mem == L3_DEFIP_ALPM_IPV6_128m || mem == L3_DEFIP_ALPM_IPV6_64_1m ||
  15219         mem == L3_DEFIP_ALPM_RAWm) {
  15220         SOC_ALPM_LPM_LOCK(unit);
  15221     } else
  15222 #endif
  15223     {
  15224     MEM_LOCK(unit, mem);
  15225     }
  15226 #if defined(BCM_TRIUMPH3_SUPPORT)
  15227     if (soc_feature(unit, soc_feature_esm_correction)) {
  15228         if (copyno == MEM_BLOCK_ANY) {
  15229             copyno = SOC_MEM_BLOCK_ANY(unit, mem);
  15230         }
  15231         if ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  15232             (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU)) {
  15233             SOC_ESM_LOCK(unit);
  15234         }
  15235     }
  15236 #endif
  15237     SOC_MEM_BLOCK_ITER(unit, mem, blk) {
  15238         if (copyno != COPYNO_ALL && copyno != blk) {
  15239             continue;
  15240         }
  15241 
  15242         index2 = index;
  15243 
  15244     
  15245 #if defined(BCM_TRIDENT2_SUPPORT)
  15246         if (SOC_IS_TD2_TT2(unit) &&
  15247             soc_feature(unit, soc_feature_l3_defip_map) &&
  15248             (mem == L3_DEFIPm ||
  15249              mem == L3_DEFIP_LEVEL1m ||
  15250              mem == L3_DEFIP_ONLYm ||
  15251              mem == L3_DEFIP_DATA_ONLYm ||
  15252              mem == L3_DEFIP_HIT_ONLY_Xm ||
  15253              mem == L3_DEFIP_HIT_ONLY_Ym ||
  15254              mem == L3_DEFIP_HIT_ONLYm ||
  15255              mem == L3_DEFIP_PAIR_128m ||
  15256              mem == L3_DEFIP_PAIR_LEVEL1m ||
  15257              mem == L3_DEFIP_PAIR_128_ONLYm ||
  15258              mem == L3_DEFIP_PAIR_128_DATA_ONLYm ||
  15259              mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm ||
  15260              mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym ||
  15261              mem == L3_DEFIP_PAIR_128_HIT_ONLYm)) {
  15262             if (!(flags & SOC_MEM_DONT_MAP_INDEX)) {
  15263                 index2 = soc_trident2_l3_defip_index_map(unit, mem, index);
  15264             }
  15265         }
  15266 #endif /* BCM_TRIDENT2_SUPPORT */
  15267         maddr = soc_mem_addr_get(unit, mem, 0, blk, index2, &at);
  15268 #if defined(BCM_EXTND_SBUS_SUPPORT)
  15269         if (!soc_feature(unit, soc_feature_new_sbus_format)) {
  15270             /* Override ACC_TYPE in address */
  15271             maddr &= ~(_SOC_MEM_ADDR_ACC_TYPE_MASK <<
  15272                             _SOC_MEM_ADDR_ACC_TYPE_SHIFT);
  15273             maddr |= (acc_type & _SOC_MEM_ADDR_ACC_TYPE_MASK) <<
  15274                             _SOC_MEM_ADDR_ACC_TYPE_SHIFT;
  15275         }
  15276 #endif /* BCM_EXTND_SBUS_SUPPORT */
  15277         schan_msg.writecmd.address = maddr;
  15278         dst_blk = 0;
  15279 #if defined(BCM_EXTND_SBUS_SUPPORT)
  15280         if (soc_feature(unit, soc_feature_new_sbus_format)) {
  15281             dst_blk = SOC_BLOCK2SCH(unit, blk);
  15282         } else
  15283 #endif /* BCM_EXTND_SBUS_SUPPORT */
  15284         {
  15285 #if defined(BCM_XGS3_SWITCH_SUPPORT)
  15286             /* required on XGS3. Optional on other devices */
  15287             dst_blk = ((maddr >> SOC_BLOCK_BP)
  15288                  & 0xf) | (((maddr >> SOC_BLOCK_MSB_BP) & 0x3) << 4);
  15289 #endif /* BCM_XGS3_SWITCH_SUPPORT */
  15290         }
  15291 
  15292         soc_schan_header_cmd_set(unit, &schan_msg.header, WRITE_MEMORY_CMD_MSG,
  15293                                  dst_blk, src_blk, acc_type, data_byte_len, 0,
  15294                                  0);
  15295 
  15296         /* Write header + address + entry_dw data DWORDs */
  15297         /* Note: The hardware does not send WRITE_MEMORY_ACK_MSG. */
  15298         if (2 + entry_dw > CMIC_SCHAN_WORDS(unit)) {
  15299            LOG_WARN(BSL_LS_SOC_SOCMEM,
  15300                     (BSL_META_U(unit,
  15301                                 "soc_mem_pipe_select_write: assert will fail for memory %s\n"), SOC_MEM_NAME(unit, mem)));
  15302         }
  15303 #ifdef BCM_ESW_SUPPORT
  15304 _retry_op:
  15305 #endif /* BCM_ESW_SUPPORT */
  15306         rv = soc_schan_op(unit, &schan_msg,
  15307                            2 + entry_dw, 0, allow_intr);
  15308         if (SOC_E_FAIL == rv) {
  15309 #ifdef BCM_ESW_SUPPORT
  15310             if (soc_feature(unit, soc_feature_shared_hash_mem)) {
  15311 
  15312                 if (0 == write_retry_attempt) {
  15313                     _soc_ser_sram_correction_init(unit, mem, &need_retry);
  15314                 }
  15315                 _soc_ser_sram_correction_pre(unit, mem, need_retry);
  15316 
  15317                 if (need_retry){
  15318                     rv2 = soc_schan_op(unit, &schan_msg, 2 + entry_dw, 0, allow_intr);
  15319                 }
  15320                 /* If rv2==SOC_E_FAIL, the failure of soc_schan_op is not due to L2_mode_fifo is filled,
  15321                 * because we diable memwr fifo events, so we need to correct the memory.
  15322                 */
  15323                 if (rv2 == SOC_E_FAIL || need_retry == 0) {
  15324                     if (SOC_IS_TOMAHAWKX(unit)) {
  15325                         pipe = (acc_type == _SOC_MEM_ADDR_ACC_TYPE_PIPE_0) ? 0 :
  15326                                (acc_type == _SOC_MEM_ADDR_ACC_TYPE_PIPE_1) ? 1 :
  15327                                (acc_type == _SOC_MEM_ADDR_ACC_TYPE_PIPE_2) ? 2 :
  15328                                (acc_type == _SOC_MEM_ADDR_ACC_TYPE_PIPE_3) ? 3 :
  15329                                (acc_type == _SOC_MEM_ADDR_ACC_TYPE_PIPE_4) ? 4 :
  15330                                (acc_type == _SOC_MEM_ADDR_ACC_TYPE_PIPE_5) ? 5 :
  15331                                (acc_type == _SOC_MEM_ADDR_ACC_TYPE_PIPE_6) ? 6 :
  15332                                                                              7;
  15333                     } else if (SOC_IS_TRIDENT2X(unit)) {
  15334                         pipe = (acc_type == _SOC_MEM_ADDR_ACC_TYPE_PIPE_X) ? 0 :
  15335                                                                              1;
  15336                     } else if (SOC_IS_TRIDENT3X(unit)){
  15337                         pipe = (acc_type == _SOC_MEM_ADDR_ACC_TYPE_PIPE_0) ? 0 :
  15338                                                                              1;
  15339                     } else {
  15340                         pipe = -1;
  15341                     }
  15342                     rv1 = soc_ser_sram_correction(unit, pipe,
  15343                                                   schan_msg.writecmd.header.v2.dst_blk,
  15344                                                   schan_msg.writecmd.address, mem,
  15345                                                   blk, index2, NULL);
  15346                 }
  15347                 _soc_ser_sram_correction_post(unit, mem, need_retry);
  15348 
  15349                 if (rv1 == SOC_E_NONE) {
  15350                     if (write_retry_attempt < HASH_MEM_OP_RETRY_COUNT) {
  15351                         write_retry_attempt++;
  15352                         goto _retry_op;
  15353                     }
  15354                 }
  15355             }
  15356 #endif /* BCM_ESW_SUPPORT */
  15357             goto done;
  15358         }
  15359 
  15360         /* Write back to cache if active */
  15361         cache = SOC_MEM_STATE(unit, mem).cache[blk];
  15362         vmap = SOC_MEM_STATE(unit, mem).vmap[blk];
  15363 
  15364         if (cache != NULL && !no_cache && !SOC_MEM_TEST_SKIP_CACHE(unit)) {
  15365             if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ||
  15366                 SOC_HW_ACCESS_DISABLE(unit)) {
  15367                 if (!SOC_WARM_BOOT(unit)) {
  15368                     CACHE_VMAP_CLR(vmap, index);
  15369                 }
  15370             } else if (_SOC_MEM_CHK_L2_MEM(mem)) {
  15371                 soc_field_t fld_vld = VALIDf;
  15372                 if (soc_feature(unit, soc_feature_base_valid)) {
  15373                     fld_vld = BASE_VALIDf;
  15374                 }
  15375                 /* If an invalid entry is being written then clear the cache */
  15376                 if (((mem == L2_ENTRY_2m &&
  15377                      soc_L2_ENTRY_2m_field32_get(unit, entry_data, VALID_0f) &&
  15378                      soc_L2_ENTRY_2m_field32_get(unit, entry_data, VALID_1f)) ||
  15379                      ((mem == L2Xm || mem == L2_ENTRY_1m) &&
  15380                       soc_mem_field32_get(unit, mem, entry_data, fld_vld))) &&
  15381                      ((mem == L2_ENTRY_2m &&
  15382                       (soc_mem_field32_get(unit, mem, entry_data, STATIC_BIT_0f) &&
  15383                        soc_mem_field32_get(unit, mem, entry_data, STATIC_BIT_1f))) ||
  15384                        ((mem == L2Xm || mem == L2_ENTRY_1m) &&
  15385                         soc_mem_field32_get(unit, mem, entry_data, STATIC_BITf)))) {
  15386 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT)
  15387                     sal_memcpy(cache + index * entry_dw,
  15388                                (entry_data_ptr == converted_entry_data) ?
  15389                                cache_entry_data : entry_data, entry_dw * 4);
  15390 #else
  15391                     sal_memcpy(cache + index * entry_dw, entry_data, entry_dw * 4);
  15392 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */
  15393                     CACHE_VMAP_SET(vmap, index);
  15394                 } else {
  15395                     CACHE_VMAP_CLR(vmap, index);
  15396                 }
  15397                 if (mem == L2_ENTRY_1m) {
  15398                     vmap = SOC_MEM_STATE(unit, L2_ENTRY_2m).vmap[blk];
  15399                     CACHE_VMAP_CLR(vmap, index/2);
  15400                 } else if (mem == L2_ENTRY_2m) {
  15401                     vmap = SOC_MEM_STATE(unit, L2_ENTRY_1m).vmap[blk];
  15402                     CACHE_VMAP_CLR(vmap, index*2);
  15403                     CACHE_VMAP_CLR(vmap, index*2 + 1);
  15404                 }
  15405             } else {
  15406 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT)
  15407                 sal_memcpy(cache + index * entry_dw,
  15408                            (entry_data_ptr == converted_entry_data) ?
  15409                            cache_entry_data : entry_data, entry_dw * 4);
  15410 #else
  15411                 sal_memcpy(cache + index * entry_dw, entry_data, entry_dw * 4);
  15412 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */
  15413                 CACHE_VMAP_SET(vmap, index);
  15414             }
  15415         }
  15416     }
  15417 
  15418 done:
  15419 #if defined(BCM_TRIUMPH3_SUPPORT)
  15420     if (soc_feature(unit, soc_feature_esm_correction)) {
  15421         if (copyno == MEM_BLOCK_ANY) {
  15422             copyno = SOC_MEM_BLOCK_ANY(unit, mem);
  15423         }
  15424         if ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  15425             (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU)) {
  15426             SOC_ESM_UNLOCK(unit);
  15427         }
  15428     }
  15429 #endif
  15430 #ifdef ALPM_ENABLE
  15431     if (mem == L3_DEFIP_ALPM_ECCm || mem == L3_DEFIP_ALPM_IPV4m ||
  15432         mem == L3_DEFIP_ALPM_IPV4_1m || mem == L3_DEFIP_ALPM_IPV6_64m ||
  15433         mem == L3_DEFIP_ALPM_IPV6_128m || mem == L3_DEFIP_ALPM_IPV6_64_1m ||
  15434         mem == L3_DEFIP_ALPM_RAWm) {
  15435         SOC_ALPM_LPM_UNLOCK(unit);
  15436     } else
  15437 #endif
  15438     {
  15439     MEM_UNLOCK(unit, mem);
  15440     }
  15441 
  15442     if (NULL != meminfo->snoop_cb) {
  15443         if (SOC_MEM_SNOOP_WRITE & meminfo->snoop_flags) {
  15444             meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_WRITE,
  15445                               copyno, index, index, entry_data_ptr,
  15446                               meminfo->snoop_user_data);
  15447         }
  15448         if (SOC_MEM_SNOOP_WRITE_COUNT & meminfo->snoop_flags) {
  15449             meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_WRITE_COUNT,
  15450                               copyno, index, index, entry_data_ptr,
  15451                               meminfo->snoop_user_data);
  15452         }
  15453     }
  15454 
  15455     return rv;
  15456 }
  15457 
  15458 #ifdef BCM_TRIUMPH2_SUPPORT
  15459 STATIC int
  15460 _soc_mem_op_cpu_tdm(int unit, int enable)
  15461 {
  15462     if (enable) {
  15463         soc_IARB_TDM_TABLEm_field32_set(unit,
  15464                                        &(SOC_CONTROL(unit)->iarb_tdm),
  15465                                        PORT_NUMf, 0);
  15466     } else {
  15467         soc_IARB_TDM_TABLEm_field32_set(unit,
  15468                                        &(SOC_CONTROL(unit)->iarb_tdm),
  15469                                        PORT_NUMf, 63);
  15470     }
  15471     return _soc_mem_write(unit, IARB_TDM_TABLEm, 0, SOC_BLOCK_ALL,
  15472                           SOC_CONTROL(unit)->iarb_tdm_idx,
  15473                           &(SOC_CONTROL(unit)->iarb_tdm));
  15474 }
  15475 #endif /* BCM_TRIUMPH2_SUPPORT */
  15476 
  15477 #ifdef BCM_HURRICANE2_SUPPORT
  15478 STATIC int
  15479 _soc_mem_hr2_parity_generate(int unit, soc_mem_t mem, void *entry_data)
  15480 {
  15481     uint8   *data8_buf, data8_val;
  15482     int     num_bytes, i;
  15483     uint32   parity, rval;
  15484 
  15485     SOC_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval));
  15486     if (soc_reg_field_get(unit, MISCCONFIGr, rval, PARITY_CHECK_ENf) == 0) {
  15487         return SOC_E_NONE;
  15488     }
  15489     if ((mem == MMU_IPMC_VLAN_TBLm) || (mem == MMU_IPMC_GROUP_TBL0m)
  15490         || (mem == MMU_IPMC_GROUP_TBL1m)) {
  15491         data8_buf = (uint8 *)entry_data;
  15492         num_bytes = soc_mem_entry_bytes(unit,mem);
  15493 
  15494         /* Reset the parity value */
  15495         parity = 0;
  15496         soc_mem_field32_set(unit, mem, entry_data, PARITYf, parity);
  15497 
  15498         /* Calculate the parity value */
  15499         for (i = 0; i < num_bytes; i++) {
  15500             data8_val = data8_buf[i];
  15501             while (data8_val > 0) {
  15502                 if (data8_val & 0x1) {
  15503                     parity++;
  15504                 }
  15505                 data8_val = data8_val >> 1;
  15506             }
  15507         }
  15508 
  15509         /* Set parity value */
  15510         parity &= 0x1;
  15511         soc_mem_field32_set(unit, mem, entry_data, PARITYf, parity);
  15512     }
  15513     return SOC_E_NONE;
  15514 }
  15515 #endif /* BCM_HURRICANE2_SUPPORT */
  15516 
  15517 #ifdef BCM_KATANA2_SUPPORT
  15518 STATIC int
  15519 _soc_mem_write_kt2(int unit, soc_mem_t mem, int copyno, int index,
  15520                    void *entry_data)
  15521 {
  15522     int rv = SOC_E_FAIL;
  15523 
  15524     uint32 rval;
  15525     uint16 dev_id;
  15526     uint8 rev_id;
  15527 
  15528     soc_cm_get_id(unit, &dev_id, &rev_id);
  15529     if ((rev_id == BCM56450_B1_REV_ID) &&
  15530         (SOC_CONTROL(unit)->soc_flags & SOC_F_ALL_MODULES_INITED) &&
  15531         (mem == ING_PHYSICAL_PORT_TABLEm)) {
  15532 
  15533         READ_ING_Q_BEGINr(unit,&rval);
  15534         soc_reg_field_set(unit, ING_Q_BEGINr, &rval,
  15535                           ING_PHYSICAL_PORT_SBUS_WITH_PKT_DISABLEf , 1);
  15536         WRITE_ING_Q_BEGINr(unit,rval);
  15537         LOG_VERBOSE(BSL_LS_SOC_COMMON,
  15538                     (BSL_META_U(unit, "WRITE PKT_DISABLE=1\n")));
  15539 
  15540         rv = soc_mem_array_write(unit, mem, 0, copyno, index, entry_data);
  15541         soc_reg_field_set(unit, ING_Q_BEGINr, &rval,
  15542                           ING_PHYSICAL_PORT_SBUS_WITH_PKT_DISABLEf , 0);
  15543         WRITE_ING_Q_BEGINr(unit,rval);
  15544         LOG_VERBOSE(BSL_LS_SOC_COMMON,
  15545                     (BSL_META_U(unit, "WRITE PKT_DISABLE=0\n")));
  15546     } else {
  15547         return soc_mem_array_write(unit, mem, 0, copyno, index, entry_data);
  15548     }
  15549 
  15550     return rv;
  15551 }
  15552 #endif
  15553 
  15554 void
  15555 soc_mem_watch_set(int unit, int value)
  15556 {
  15557     SOC_CONTROL(unit)->soc_mem_watch = value;
  15558     LOG_CLI((BSL_META("memwatch delta %s\n"),
  15559              value ? "on" : "off"));
  15560 }
  15561 
  15562 /*
  15563  * Function:
  15564  *    soc_mem_write
  15565  * Purpose:
  15566  *    Write a memory internal to the SOC.
  15567  * Notes:
  15568  *    GBP/CBP memory should only accessed when MMU is in DEBUG mode.
  15569  */
  15570 int
  15571 soc_mem_write(int unit,
  15572               soc_mem_t mem,
  15573               int copyno,  /* Use COPYNO_ALL for all */
  15574               int index,
  15575               void *entry_data)
  15576 {
  15577     int rv;
  15578 #ifdef BCM_TRIDENT3_SUPPORT
  15579     soc_mem_t phy_mem;
  15580 #endif
  15581 
  15582     DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE));
  15583 
  15584     if (SOC_CONTROL(unit)->soc_mem_watch) {
  15585         if (SOC_CONTROL(unit)->prev_mem != mem) {
  15586             LOG_CLI((BSL_META_U(unit, "%d:%s MEM: %s[%d]\n"),
  15587                      unit, BSL_FUNC, SOC_MEM_NAME(unit, mem),
  15588                      index));
  15589             SOC_CONTROL(unit)->prev_mem = mem;
  15590         }
  15591     }
  15592 
  15593 #ifdef BCM_TRIDENT3_SUPPORT
  15594     if (soc_feature(unit, soc_feature_flex_flow)) {
  15595         if (SOC_MEM_IS_VIEW(unit, mem)) {
  15596             rv = soc_mem_view_phy_mem_get(unit, mem, &phy_mem);
  15597             if (rv != SOC_E_NONE) {
  15598                 return rv;
  15599             }
  15600             mem = phy_mem;
  15601         }
  15602     }
  15603 #endif
  15604     _SOC_MEM_REPLACE_MEM(unit, mem);
  15605 
  15606 #ifdef BCM_KATANA2_SUPPORT
  15607     if (SOC_IS_KATANA2(unit)) {
  15608         rv = _soc_mem_write_kt2(unit, mem, copyno, index, entry_data);
  15609     } else
  15610 #endif
  15611     {
  15612         rv = soc_mem_array_write(unit, mem, 0, copyno, index, entry_data);
  15613     }
  15614 
  15615     return rv;
  15616 }
  15617 
  15618 int
  15619 soc_mem_write_extended(int unit, uint32 flags,
  15620                          soc_mem_t mem,
  15621                          int copyno, /* COPYNO_ALL allowed */
  15622                          int index,
  15623                          void *entry_data)
  15624 {
  15625     int rv;
  15626 
  15627     _SOC_MEM_REPLACE_MEM(unit, mem);
  15628 #ifdef BCM_KATANA2_SUPPORT
  15629     if (SOC_IS_KATANA2(unit)) {
  15630         rv = _soc_mem_write_kt2(unit, mem, copyno, index, entry_data);
  15631     } else
  15632 #endif
  15633     {
  15634         rv = soc_mem_array_write_extended(unit, flags, mem, 0, copyno,
  15635                                             index, entry_data);
  15636     }
  15637 
  15638     return rv;
  15639 }
  15640 
  15641 /*
  15642  * Function:    soc_mem_array_write
  15643  * Purpose:     Write a memory array internal to the SOC.
  15644  */
  15645 int
  15646 soc_mem_array_write(int unit, soc_mem_t mem, unsigned array_index, int copyno,/* Use COPYNO_ALL for all */
  15647               int index, void *entry_data)
  15648 {
  15649     return soc_mem_array_write_extended(unit, SOC_MEM_NO_FLAGS, mem,
  15650               array_index, copyno, index, entry_data);
  15651 }
  15652 
  15653 int
  15654 soc_mem_array_write_extended(int unit, uint32 flags,
  15655               soc_mem_t mem, unsigned array_index,
  15656               int copyno,/* Use COPYNO_ALL for all */
  15657               int index, void *entry_data)
  15658 {
  15659     int rv;
  15660 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \
  15661     || defined(BCM_HURRICANE2_SUPPORT)
  15662     soc_mem_t     aggr_mem = INVALIDm;
  15663     void          *shift_buffer[MAX_TCAM_PROTECT_RANGES] = {NULL};
  15664 #endif
  15665 #ifdef BCM_HURRICANE2_SUPPORT
  15666     uint32 try_cnt = 0, val = 0;
  15667     int     entry_len = 0, skip_cache = 0;
  15668     void    *entry_tmp = NULL; /* the copy for written entry */
  15669     void    *gp_entry_chk = NULL; /* for read check */
  15670     void    *xp_entry_chk = NULL; /* for read check */
  15671 #endif /* BCM_HURRICANE2_SUPPORT */
  15672 #ifdef BCM_SAND_SUPPORT
  15673     int       entry_dw;
  15674 #endif
  15675 #ifdef BCM_GREYHOUND_SUPPORT
  15676     uint32 ori_val = 0, new_val = 0, field_val = 0;
  15677     int disable_hw_learn = FALSE;
  15678 #endif /* BCM_GREYHOUND_SUPPORT */
  15679 
  15680     /* Use user defined callback for access */
  15681     if(SOC_INFO(unit).reg_access.mem_write) {
  15682         return SOC_INFO(unit).reg_access.mem_write(unit, mem, array_index, copyno, index, entry_data);
  15683     }
  15684 
  15685     /* if reloading, don't write to register */
  15686     if (SOC_IS_RELOADING(unit)){
  15687         return SOC_E_NONE;
  15688     }
  15689 
  15690 #ifdef BCM_SAND_SUPPORT
  15691     entry_dw = soc_mem_entry_words(unit, mem);
  15692 
  15693     /* Write header + address + entry_dw data DWORDs */
  15694     if ((entry_dw + 2 > CMIC_SCHAN_WORDS(unit)))
  15695     {
  15696         if (SOC_IS_SAND(unit))
  15697         {
  15698             rv = _soc_mem_array_wide_write(unit, flags, mem, array_index, copyno, index, entry_data);
  15699             return rv;
  15700         }
  15701     }
  15702 #endif
  15703 
  15704 #ifdef BCM_TRIUMPH2_SUPPORT
  15705     if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) ||
  15706         SOC_IS_VALKYRIE2(unit) || SOC_IS_ENDURO(unit)) {
  15707         if ((mem == LMEPm) || (mem == LMEP_1m)) {
  15708             /* Disable CPU slot from TDM */
  15709             /* coverity[stack_use_overflow] */
  15710             SOC_IF_ERROR_RETURN(_soc_mem_op_cpu_tdm(unit, 0));
  15711         }
  15712     }
  15713 #endif /* BCM_TRIUMPH2_SUPPORT */
  15714 
  15715 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \
  15716     || defined(BCM_HURRICANE2_SUPPORT)
  15717     if (soc_feature(unit, soc_feature_xy_tcam) &&
  15718         SOC_CONTROL(unit)->tcam_protect_write &&
  15719         (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) &&
  15720         (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM))) {
  15721         SOC_IF_ERROR_RETURN
  15722             (_soc_mem_tcam_entry_preserve(unit, mem, copyno, index, 1,
  15723                                           entry_data, &aggr_mem,
  15724                                           shift_buffer));
  15725     }
  15726 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */
  15727 
  15728 #ifdef BCM_GREYHOUND_SUPPORT
  15729     /*
  15730      * To pause L2 hardware learning when IPIPE tables are being written
  15731      * after all modules are initialized.
  15732      */
  15733     if (SOC_CONTROL(unit)->soc_flags & SOC_F_ALL_MODULES_INITED) {
  15734         /* This soc info will be updated when soc attached for a device. */
  15735         if (SOC_CONTROL(unit)->l2x_learn_pause_on_table_write &&
  15736             SOC_BLOCK_IS_CMP(unit, SOC_MEM_BLOCK_MIN(unit, mem),
  15737                              SOC_BLK_IPIPE)) {
  15738             SOC_IF_ERROR_RETURN(READ_ING_MISC_CONFIG2r(unit, &ori_val));
  15739 
  15740             new_val = ori_val;
  15741             soc_reg_field_set(unit, ING_MISC_CONFIG2r, &new_val,
  15742                               CML_OVERRIDE_ENABLE_NEWf, 0x1);
  15743             soc_reg_field_set(unit, ING_MISC_CONFIG2r, &new_val,
  15744                               CML_OVERRIDE_ENABLE_MOVEf, 0x1);
  15745             field_val = soc_reg_field_get(unit, ING_MISC_CONFIG2r,
  15746                                           new_val, CML_OVERRIDE_NEWf);
  15747             field_val &= ~0x8;
  15748             soc_reg_field_set(unit, ING_MISC_CONFIG2r, &new_val,
  15749                               CML_OVERRIDE_NEWf, field_val);
  15750 
  15751             field_val = soc_reg_field_get(unit, ING_MISC_CONFIG2r,
  15752                                           new_val, CML_OVERRIDE_MOVEf);
  15753             field_val &= ~0x8;
  15754             soc_reg_field_set(unit, ING_MISC_CONFIG2r, &new_val,
  15755                               CML_OVERRIDE_MOVEf, field_val);
  15756 
  15757             if (new_val != ori_val) {
  15758                 SOC_IF_ERROR_RETURN
  15759                     (WRITE_ING_MISC_CONFIG2r(unit, new_val));
  15760                 disable_hw_learn = TRUE;
  15761             }
  15762         }
  15763     }
  15764 #endif /* BCM_GREYHOUND_SUPPORT */
  15765 
  15766 #ifdef BCM_HURRICANE2_SUPPORT
  15767     if (SOC_IS_HURRICANE2(unit)) {
  15768         SOC_IF_ERROR_RETURN
  15769             (_soc_mem_hr2_parity_generate(unit, mem, entry_data));
  15770     }
  15771     if (SOC_IS_HURRICANE2(unit) && mem == MMU_IPMC_VLAN_TBLm) {
  15772         entry_len = soc_mem_entry_words(unit, mem) * sizeof(uint32);
  15773         entry_tmp = sal_alloc(entry_len, "ipmc_vlan_entry_copy");
  15774         gp_entry_chk = sal_alloc(entry_len, "ipmc_vlan_gpentry_check");
  15775         xp_entry_chk = sal_alloc(entry_len, "ipmc_vlan_xpentry_check");
  15776         if (entry_tmp == NULL || gp_entry_chk == NULL ||
  15777                 xp_entry_chk == NULL) {
  15778             rv = SOC_E_MEMORY;
  15779             goto hr2_war_done;
  15780         }
  15781         sal_memcpy(entry_tmp, entry_data, entry_len);
  15782         sal_memset(gp_entry_chk, 0, entry_len);
  15783         sal_memset(xp_entry_chk, 0, entry_len);
  15784     }
  15785 #endif  /* BCM_HURRICANE2_SUPPORT */
  15786 
  15787     rv = _soc_mem_write_extended(unit, flags,mem, array_index, copyno, index,
  15788                                  entry_data);
  15789 
  15790 #ifdef BCM_HURRICANE2_SUPPORT
  15791     /* SDK-50996: HR2 WAR for sbus issue while writing to IPMC_VLAN */
  15792     if (SOC_IS_HURRICANE2(unit) && mem == MMU_IPMC_VLAN_TBLm) {
  15793 
  15794         /* Skip cache */
  15795         skip_cache = SOC_MEM_TEST_SKIP_CACHE(unit);
  15796         SOC_MEM_TEST_SKIP_CACHE_SET(unit, TRUE);
  15797 
  15798         do {
  15799             if (++try_cnt > 10) {
  15800                 rv = SOC_E_INTERNAL;
  15801                 goto hr2_war_done;
  15802             }
  15803             if (try_cnt > 1){
  15804                 sal_memcpy(entry_data, entry_tmp, entry_len);
  15805                 if ((rv = _soc_mem_write_extended(unit, flags, mem,
  15806                         array_index, copyno, index, entry_data)) < 0) {
  15807                     goto hr2_war_done;
  15808                 }
  15809             }
  15810 
  15811             /* Force the read on XPORT's IPMC_VLANm */
  15812             if ((rv = READ_MISCCONFIGr(unit, &val)) < 0) {
  15813                 goto hr2_war_done;
  15814             }
  15815             soc_reg_field_set(unit, MISCCONFIGr, &val,
  15816                               IPMC_VLAN_TBL_RD_SELf, 1);
  15817             if ((rv = WRITE_MISCCONFIGr(unit, val)) < 0) {
  15818                 goto hr2_war_done;
  15819             }
  15820             sal_memset(xp_entry_chk, 0, entry_len);
  15821             if ((rv = soc_mem_array_read(unit, mem,
  15822                     array_index, copyno, index, xp_entry_chk)) < 0) {
  15823                 goto hr2_war_done;
  15824             }
  15825 
  15826             /* Force the read on GPORT's IPMC_VLANm */
  15827             if ((rv = READ_MISCCONFIGr(unit, &val)) < 0) {
  15828                 goto hr2_war_done;
  15829             }
  15830             soc_reg_field_set(unit, MISCCONFIGr, &val,
  15831                               IPMC_VLAN_TBL_RD_SELf, 0);
  15832             if ((rv = WRITE_MISCCONFIGr(unit, val)) < 0) {
  15833                 goto hr2_war_done;
  15834             }
  15835             sal_memset(gp_entry_chk, 0, entry_len);
  15836             if ((rv = soc_mem_array_read(unit, mem,
  15837                     array_index, copyno, index, gp_entry_chk)) < 0) {
  15838                 goto hr2_war_done;
  15839             }
  15840         } while(sal_memcmp(gp_entry_chk, entry_tmp, entry_len) ||
  15841                 sal_memcmp(xp_entry_chk, entry_tmp, entry_len));
  15842 
  15843         /* free the allocated memory */
  15844 hr2_war_done :
  15845         if (entry_tmp) {
  15846             sal_free(entry_tmp);
  15847         }
  15848         if (gp_entry_chk) {
  15849             sal_free(gp_entry_chk);
  15850         }
  15851         if (xp_entry_chk) {
  15852             sal_free(xp_entry_chk);
  15853         }
  15854 
  15855         SOC_MEM_TEST_SKIP_CACHE_SET(unit, skip_cache);
  15856         /* return once the WAR got error return */
  15857         if (SOC_FAILURE(rv)){
  15858             return rv;
  15859         }
  15860     }
  15861 #endif  /* BCM_HURRICANE2_SUPPORT */
  15862 
  15863 #ifdef BCM_GREYHOUND_SUPPORT
  15864     /*
  15865      * Restore original L2 hardware learn setting after table write
  15866      * operation completes.
  15867      */
  15868     if (disable_hw_learn) {
  15869         SOC_IF_ERROR_RETURN(WRITE_ING_MISC_CONFIG2r(unit, ori_val));
  15870     }
  15871 #endif /* BCM_GREYHOUND_SUPPORT */
  15872 
  15873 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \
  15874     || defined(BCM_HURRICANE2_SUPPORT)
  15875     if (soc_feature(unit, soc_feature_xy_tcam) &&
  15876         SOC_CONTROL(unit)->tcam_protect_write &&
  15877         (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) &&
  15878         (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM))) {
  15879             SOC_IF_ERROR_RETURN
  15880                 (_soc_mem_tcam_entry_restore(unit, aggr_mem, copyno, index, 1,
  15881                                              shift_buffer));
  15882     }
  15883 #endif /* BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT */
  15884 
  15885     SOC_IF_ERROR_RETURN(rv);
  15886 
  15887 #ifdef BCM_TRIUMPH2_SUPPORT
  15888     if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) ||
  15889         SOC_IS_VALKYRIE2(unit) || SOC_IS_ENDURO(unit)) {
  15890         if ((mem == LMEPm) || (mem == LMEP_1m)) {
  15891             /* Enable CPU slot from TDM */
  15892             SOC_IF_ERROR_RETURN(_soc_mem_op_cpu_tdm(unit, 1));
  15893         }
  15894     }
  15895 #endif /* BCM_TRIUMPH2_SUPPORT */
  15896 
  15897     return rv;
  15898 }
  15899 
  15900 /*
  15901  * Function:
  15902  *    soc_mem_write_range
  15903  * Purpose:
  15904  *    Write a range of chip's memory with multiple entries
  15905  */
  15906 int
  15907 soc_mem_write_range(int unit, soc_mem_t mem, int copyno,
  15908                     int index_min, int index_max, void *buffer)
  15909 {
  15910     int rc;
  15911 
  15912     rc = soc_mem_write_range_multi_cmc(unit, mem, copyno,
  15913                                        index_min, index_max, buffer, -1);
  15914     return rc;
  15915 }
  15916 
  15917 /*
  15918  * Function:
  15919  *    soc_mem_write_range_multi_cmc
  15920  * Purpose:
  15921  *    Write a range of chip's memory with multiple entries
  15922  *    With multiple CMC/channel support
  15923  */
  15924 int
  15925 soc_mem_write_range_multi_cmc(int unit, soc_mem_t mem, int copyno,
  15926                               int index_min, int index_max, void *buffer,
  15927                               int vchan)
  15928 {
  15929     int rc;
  15930 
  15931 #ifdef SOC_MEM_DEBUG_SPEED
  15932 
  15933     sal_usecs_t start_time;
  15934     int diff_time, count = (index_max > index_min) ?
  15935                            (index_max - index_min + 1) :
  15936                            (index_min - index_max + 1);
  15937 
  15938     start_time = sal_time_usecs();
  15939 #endif
  15940 
  15941     rc = soc_mem_array_write_range_multi_cmc(unit, 0, mem, 0, copyno, index_min,
  15942                                             index_max, buffer, vchan);
  15943 
  15944 #ifdef SOC_MEM_DEBUG_SPEED
  15945     diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time);
  15946     LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
  15947                 (BSL_META_U(unit,
  15948                             "Total dma write time: %d usecs, [%d nsecs per op]\n"),
  15949                  diff_time, diff_time*1000/count));
  15950 #endif
  15951  return rc;
  15952 }
  15953 
  15954 /*
  15955  * Function:
  15956  *    soc_mem_array_write_range
  15957  * Purpose:
  15958  *    Write a range of chip's memory with multiple entries
  15959  */
  15960 
  15961 int
  15962 soc_mem_array_write_range(int unit, uint32 flags, soc_mem_t mem, unsigned array_index,
  15963                           int copyno, int index_min, int index_max, void *buffer)
  15964 {
  15965     int rv;
  15966     rv = soc_mem_array_write_range_multi_cmc(unit, flags, mem, array_index,
  15967                                              copyno, index_min, index_max, buffer, -1);
  15968     return rv;
  15969 }
  15970 
  15971 /*
  15972  * Function:
  15973  *    soc_mem_array_write_range_multi_cmc
  15974  * Purpose:
  15975  *    Write a range of chip's memory with multiple entries
  15976  */
  15977 
  15978 int
  15979 soc_mem_array_write_range_multi_cmc(int unit, uint32 flags, soc_mem_t mem, unsigned array_index,
  15980                                     int copyno, int index_min, int index_max, void *buffer,
  15981                                     int vchan)
  15982 {
  15983     int                   rv = SOC_E_NONE;
  15984     uint32          entry_dw;
  15985     int mem_array_vmap_offset, mem_array_cache_offset;
  15986     int             i;
  15987     soc_mem_info_t  *meminfo;
  15988     void            *cache_buffer = NULL;
  15989     int             blk, cache_copyno = copyno;
  15990     int             copyno_override = 0; /* If non-zero, will override copyno */
  15991 #ifdef BROADCOM_DEBUG
  15992     shared_block_t *p = NULL;
  15993     int            length = 0;
  15994 #endif
  15995 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) \
  15996     || defined(BCM_HURRICANE2_SUPPORT)
  15997 
  15998     int             count, alloc_size;
  15999 #endif
  16000     uint32          *cache;
  16001     int             indices_reversed = (index_max < index_min);
  16002     int             effective_min = indices_reversed ? index_max : index_min;
  16003     int             effective_max = indices_reversed ? index_min : index_max;
  16004     int             index_limit = indices_reversed ? (index_min - 1) : (index_max + 1);
  16005 
  16006     uint16 dev_id;
  16007     uint8 rev_id;
  16008 
  16009 
  16010     /* if reloading, don't write to register
  16011        and write to H/W is not allowed during Warm boot */
  16012     if (SOC_IS_RELOADING(unit) || SOC_WARM_BOOT(unit))
  16013     {
  16014         return SOC_E_NONE;
  16015     }
  16016 
  16017     SOC_MEM_ALIAS_TO_ORIG(unit,mem);
  16018 
  16019     if (!soc_mem_is_valid(unit, mem)) {
  16020         return SOC_E_MEMORY;
  16021     }
  16022 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT)
  16023     if (SOC_IS_ARAD(unit) || SOC_IS_DNX(unit) || SOC_IS_DNXF(unit)){
  16024         soc_mem_write_copyno_update(unit, mem, &copyno, &copyno_override);
  16025         if ((copyno == COPYNO_ALL || copyno == SOC_CORE_ALL) && copyno_override){
  16026             copyno = copyno_override;
  16027         }
  16028         if (cache_copyno == copyno_override) {
  16029             cache_copyno = COPYNO_ALL;
  16030         }
  16031     } else
  16032 #endif
  16033     if (copyno == COPYNO_ALL) {
  16034         copyno = SOC_MEM_BLOCK_ANY(unit, mem);
  16035         if (copyno == COPYNO_ALL) {
  16036             return SOC_E_INTERNAL;
  16037         }
  16038     }
  16039 #ifdef BROADCOM_DEBUG
  16040     if (soc_dma_debug_property_get(unit)) {
  16041         p = (shared_block_t *) (((char*)buffer) -
  16042             ( (((char*)&(((shared_block_t*)0)->user_data[0]))) - ((char*)(shared_block_t*)0) ));
  16043         if (soc_cm_shared_good_range(unit, p)) {
  16044             if (SHARED_GOOD_START(p)  && SHARED_GOOD_END_DEBUG(p)) {
  16045                 length = WORDS2BYTES(soc_mem_entry_words(unit, mem)) *
  16046                          (effective_max - effective_min + 1);
  16047                 if (length > p->size) {
  16048                     LOG_WARN(BSL_LS_SOC_SOCMEM,
  16049                              (BSL_META_U(unit,
  16050                                          "Suspicious DMA length: "
  16051                                          "Desc:%s: Size:%u: length:%u\n"),
  16052                               p->description, p->size, length));
  16053                 }
  16054             }
  16055         } else if (soc_mem_dmaable(unit, mem, copyno)) {
  16056             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  16057                       (BSL_META_U(unit,
  16058                                   "ERROR:ATTN: Address:%p:"
  16059                                   "probably not in shared memory region \n"),
  16060                        p));
  16061         }
  16062     }
  16063 #endif
  16064 
  16065     soc_cm_get_id(unit, &dev_id, &rev_id);
  16066     meminfo = &SOC_MEM_INFO(unit, mem);
  16067     entry_dw = soc_mem_entry_words(unit, mem);
  16068 #ifdef BCM_DNX_SUPPORT
  16069     mem_array_vmap_offset = (SOC_MEM_IS_ARRAY(unit, mem)) ?
  16070                              ((array_index - SOC_MEM_FIRST_ARRAY_INDEX(unit, mem)) * soc_mem_index_count(unit, mem))
  16071                              : (array_index * soc_mem_index_count(unit, mem));
  16072 
  16073 #else
  16074     mem_array_vmap_offset = array_index * soc_mem_index_count(unit, mem);
  16075 #endif
  16076     mem_array_cache_offset = mem_array_vmap_offset * entry_dw;
  16077 
  16078     LOG_INFO(BSL_LS_SOC_SOCMEM,
  16079              (BSL_META_U(unit,
  16080                          "soc_mem_array_write_range: unit %d memory %s.%s [%d:%d]\n"),
  16081               unit, SOC_MEM_UFNAME(unit, mem),
  16082               SOC_BLOCK_NAME(unit, copyno),
  16083               index_min, index_max));
  16084 
  16085 #ifdef BCM_SAND_SUPPORT
  16086     /* Write header + address + entry_dw data DWORDs */
  16087     /*    coverity[negative_returns : FALSE]    */
  16088     if (soc_mem_slamable(unit, mem, copyno) && !(entry_dw + 2 > CMIC_SCHAN_WORDS(unit))) {
  16089 #else
  16090     /*    coverity[negative_returns : FALSE]    */
  16091     if (soc_mem_slamable(unit, mem, copyno) && (dev_id != BCM56983_DEVICE_ID)) {
  16092 #endif
  16093         cache = SOC_MEM_STATE(unit, mem).cache[copyno];
  16094 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT)
  16095         if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)
  16096             && (soc_feature(unit, soc_feature_xy_tcam) &&
  16097             (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) &&
  16098             (!(SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_EXT_CAM)))) {
  16099             count = effective_max - effective_min + 1;
  16100             alloc_size = count * entry_dw * sizeof(uint32);
  16101             cache_buffer = sal_alloc(alloc_size, "cache buffer");
  16102             if (cache_buffer == NULL) {
  16103                 return SOC_E_MEMORY;
  16104             }
  16105         }
  16106 #endif
  16107 
  16108         MEM_LOCK(unit, mem);
  16109 
  16110         /* Write to one or all copies of the memory */
  16111         SOC_MEM_BLOCK_ITER(unit, mem, blk) {
  16112             if (copyno_override) {
  16113                 blk = copyno_override;
  16114             } else if (copyno != COPYNO_ALL && copyno != blk) {
  16115                 continue;
  16116             }
  16117 
  16118             rv = _soc_mem_dma_write(unit, flags, mem, array_index, blk, index_min,
  16119                 index_max, buffer, cache_buffer, vchan);
  16120             if (copyno_override) break;
  16121         }
  16122 
  16123         if (rv >= 0) {
  16124             uint8 *vmap, *vmap1 = NULL;
  16125 
  16126             SOC_MEM_BLOCK_ITER(unit, mem, blk) {
  16127                 if ((cache_copyno != COPYNO_ALL) && (cache_copyno != blk)) {
  16128                     continue;
  16129                 }
  16130                 cache = SOC_MEM_STATE(unit, mem).cache[blk];
  16131                 vmap = SOC_MEM_STATE(unit, mem).vmap[blk];
  16132             if (_SOC_MEM_CHK_L2_MEM(mem)) {
  16133                 if (mem == L2_ENTRY_1m) {
  16134                     vmap1 = SOC_MEM_STATE(unit, L2_ENTRY_2m).vmap[copyno];
  16135                 } else if (mem == L2_ENTRY_2m) {
  16136                     vmap1 = SOC_MEM_STATE(unit, L2_ENTRY_1m).vmap[copyno];
  16137                 }
  16138             }
  16139             if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)) {
  16140                 sal_memcpy(cache + mem_array_cache_offset + index_min * entry_dw, cache_buffer ?
  16141                            cache_buffer : buffer,
  16142                            (index_max - index_min + 1) * entry_dw * 4);
  16143                 for (i = index_min; i <= index_max; i++) {
  16144                     if (vmap1) {
  16145                         CACHE_VMAP_CLR(vmap, i);
  16146                         if (mem == L2_ENTRY_1m) {
  16147                             CACHE_VMAP_CLR(vmap1, i/2);
  16148                         } else {
  16149                             CACHE_VMAP_CLR(vmap1, i*2);
  16150                             CACHE_VMAP_CLR(vmap1, i*2 + 1);
  16151                         }
  16152                     } else {
  16153                         CACHE_VMAP_SET(vmap, mem_array_vmap_offset + i);
  16154                     }
  16155                 }
  16156            }
  16157            }
  16158 
  16159 #ifdef BCM_TRX_SUPPORT
  16160            _soc_mem_aggr_cache_update(unit, mem, copyno, 0,
  16161                     index_min, index_max, array_index, buffer);
  16162 #endif /* BCM_TRX_SUPPORT */
  16163 
  16164         }
  16165         MEM_UNLOCK(unit, mem);
  16166         if (NULL != meminfo->snoop_cb) {
  16167             if (SOC_MEM_SNOOP_WRITE & meminfo->snoop_flags) {
  16168                 meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_WRITE,
  16169                                   copyno, effective_min, effective_max, buffer,
  16170                                   meminfo->snoop_user_data);
  16171             }
  16172             if (SOC_MEM_SNOOP_WRITE_COUNT & meminfo->snoop_flags) {
  16173                 meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_WRITE_COUNT,
  16174                                   copyno, effective_min, effective_max, buffer,
  16175                                   meminfo->snoop_user_data);
  16176             }
  16177         }
  16178 
  16179         if (cache_buffer) {
  16180             sal_free(cache_buffer);
  16181         }
  16182         return rv;
  16183     }
  16184 
  16185     for (i = index_min; i != index_limit; indices_reversed ? i-- : i++) {
  16186         SOC_IF_ERROR_RETURN(soc_mem_array_write(unit, mem, array_index, copyno,
  16187                                                 i, buffer));
  16188         buffer = ((uint32 *)buffer + entry_dw);
  16189     }
  16190     return SOC_E_NONE;
  16191 }
  16192 
  16193 
  16194 
  16195 
  16196 /*
  16197  *    Efficiently write a range of chip's memory with the same memory entry.
  16198  *    When SLAM DMA is available, it is used, and the buffer must be allocated using soc_cm_salloc().
  16199  */
  16200 int soc_mem_array_fill_range(
  16201     int unit,              /* unit of the memory */
  16202     uint32 flags,          /* flags */
  16203     soc_mem_t mem,         /* Memory to be written to */
  16204     unsigned min_ar_index, /* min array index to be written to, not used in memories which are not arrays */
  16205     unsigned max_ar_index, /* max array index to be written to, not used in memories which are not arrays */
  16206     int copyno,            /* Memory block to write to */
  16207     int index_min,         /* first memory index to write to */
  16208     int index_max,         /* last memory index to write to */
  16209     const void *buffer)    /* buffer of the entry to write. If the memory can be written to by SLAM DMA,
  16210                               then the buffer must be allocated using soc_cm_salloc(). */
  16211 {
  16212     uint32          entry_dw;
  16213     int             i, tmp;
  16214     unsigned        a_ind;
  16215     soc_mem_info_t  *meminfo;
  16216     int             blk, copyno_override = 0; /* If non-zero, will override copyno */
  16217     int             rv = SOC_E_NONE, is_slam_allowed;
  16218 
  16219     uint32         *cache, *cache_cp;
  16220     int            mem_array_vmap_offset, mem_array_cache_offset;
  16221 
  16222 
  16223     /* if reloading, don't write to register */
  16224     if (SOC_IS_RELOADING(unit) || SOC_HW_ACCESS_DISABLE(unit))
  16225     {
  16226         return SOC_E_NONE;
  16227     }
  16228 
  16229     SOC_MEM_ALIAS_TO_ORIG(unit,mem);
  16230 
  16231     if (!soc_mem_is_valid(unit, mem)) {
  16232         return SOC_E_MEMORY;
  16233     }
  16234 
  16235     meminfo = &SOC_MEM_INFO(unit, mem);
  16236     entry_dw = soc_mem_entry_words(unit, mem);
  16237 
  16238     /* get legal values for indices, if too small/big use the memory's boundaries */
  16239     tmp = soc_mem_index_min(unit, mem);
  16240     if (index_min < tmp) {
  16241       index_min = tmp;
  16242     }
  16243     if (index_max < index_min) {
  16244         index_max = index_min;
  16245     } else {
  16246          tmp = soc_mem_index_max(unit, mem);
  16247          if (index_max > tmp) {
  16248              index_max = tmp;
  16249          }
  16250     }
  16251 
  16252     if (SOC_MEM_IS_ARRAY(unit, mem)) {
  16253         soc_mem_array_info_t *maip = SOC_MEM_ARRAY_INFOP(unit, mem);
  16254         if (maip) {
  16255             if (max_ar_index >= maip->numels + maip->first_array_index) {
  16256                 max_ar_index = (maip->numels - 1) + maip->first_array_index;
  16257             } else if (min_ar_index < maip->first_array_index) {
  16258                 min_ar_index = maip->first_array_index;
  16259             }
  16260         }
  16261     } else {
  16262         min_ar_index = max_ar_index = 0;
  16263     }
  16264 
  16265     /* use copyno_override for a broadcast write block */
  16266     soc_mem_write_copyno_update(unit, mem, &copyno, &copyno_override);
  16267 
  16268     LOG_INFO(BSL_LS_SOC_SOCMEM,
  16269              (BSL_META_U(unit,
  16270                          "memory %s[%u:%u].%s [%d:%d]\n"),
  16271               SOC_MEM_UFNAME(unit, mem),
  16272               min_ar_index, max_ar_index, SOC_BLOCK_NAME(unit, copyno), index_min, index_max));
  16273 
  16274     is_slam_allowed = !(flags & 1);
  16275 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT)
  16276     /* Write header + address + entry_dw data DWORDs */
  16277     /*    coverity[negative_returns : FALSE]    */
  16278     if (is_slam_allowed && soc_mem_slamable(unit, mem, copyno) && !(entry_dw + 2 > CMIC_SCHAN_WORDS(unit))) {
  16279 #else
  16280     /*    coverity[negative_returns : FALSE]    */
  16281     if (is_slam_allowed && soc_mem_slamable(unit, mem, copyno)) {
  16282 #endif
  16283 
  16284 #ifdef BROADCOM_DEBUG
  16285     if (soc_dma_debug_property_get(unit)) {
  16286         shared_block_t *p = (shared_block_t *) (((char*)buffer) -
  16287             ( (((char*)&(((shared_block_t*)0)->user_data[0]))) - ((char*)(shared_block_t*)0) ));
  16288         int            length = 0;
  16289         if (soc_cm_shared_good_range(unit, p)) {
  16290             if (SHARED_GOOD_START(p)  && SHARED_GOOD_END_DEBUG(p)) {
  16291                 length = WORDS2BYTES(soc_mem_entry_words(unit, mem)) *
  16292                          (index_max - index_min + 1);
  16293                 if (length > p->size) {
  16294                     LOG_WARN(BSL_LS_SOC_SOCMEM,
  16295                              (BSL_META_U(unit,
  16296                                          "Some problem in calling: Desc:%s: Size:%u: length:%d\n"),
  16297                               p->description, p->size, soc_mem_entry_bytes(unit, mem)));
  16298                 }
  16299             }
  16300         } else {
  16301             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  16302                       (BSL_META_U(unit,
  16303                                   "ERROR:ATTN: Address:%p: probably not in shared memory region\n"),
  16304                        p));
  16305         }
  16306 	}
  16307 #endif
  16308 
  16309         MEM_LOCK(unit, mem);
  16310 
  16311 #ifdef BCM_SBUSDMA_SUPPORT
  16312         if (soc_feature(unit, soc_feature_sbusdma)) {
  16313             /* Loop over the block instances and write to each one using SLAM DMA */
  16314             SOC_MEM_BLOCK_ITER(unit, mem, blk) {
  16315                 if (copyno_override) {
  16316                     blk = copyno_override;
  16317                 } else if (copyno != COPYNO_ALL && copyno != blk) {
  16318                     continue;
  16319                 }
  16320 #if defined BCM_DNX_SUPPORT && defined DNX_EMULATION_1_CORE
  16321                 if (SOC_IS_JERICHO_2_ONLY(unit) && soc_sand_is_emulation_system(unit) &&
  16322                     _soc_jr2_is_2nd_core(unit, mem, blk)) {
  16323                     break; /* No need to write the reset of the (non existing) instances in emulation */
  16324                 }
  16325 #endif
  16326 
  16327                 if ((rv = _soc_mem_array_sbusdma_write(unit, 0, mem, min_ar_index,
  16328                                               max_ar_index, blk, index_min,
  16329                                           index_max, (void*)buffer, TRUE,
  16330                                               1, -1)) != SOC_E_NONE) {
  16331                     break;
  16332                 }
  16333 
  16334                 if (copyno_override) break;
  16335             }
  16336 
  16337             /* for petra, NOT update cache if vmap is not set when dma operation. */
  16338 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT)
  16339             if (rv == SOC_E_NONE) {
  16340                 uint8 *vmap;
  16341                 int cache_copyno;
  16342 
  16343                 cache_copyno = copyno;
  16344                 if ((copyno_override) && (copyno_override == soc_mem_broadcast_block_get(unit, mem))) {
  16345                     cache_copyno = COPYNO_ALL;
  16346                 }
  16347                 /* Loop over the block instances ignoring broadcast write block, and update cache */
  16348                 SOC_MEM_BLOCK_ITER(unit, mem, blk) {
  16349                     if (cache_copyno != COPYNO_ALL && cache_copyno != blk) {
  16350                         continue;
  16351                     }
  16352                     cache = SOC_MEM_STATE(unit, mem).cache[blk];
  16353                     /* coverity[negative_returns : FALSE]	*/
  16354                     /* coverity[negative_returns] */
  16355                     vmap = SOC_MEM_STATE(unit, mem).vmap[blk];
  16356                     if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)) {
  16357                         if (!SOC_MEM_IS_ARRAY(unit, mem)) {
  16358                             min_ar_index = max_ar_index = 0;
  16359                         }
  16360                         for (a_ind = min_ar_index; a_ind <= max_ar_index; ++a_ind) {
  16361 #ifdef BCM_DNX_SUPPORT
  16362                             mem_array_vmap_offset = (SOC_MEM_IS_ARRAY(unit, mem)) ?
  16363                                                      ((a_ind - SOC_MEM_FIRST_ARRAY_INDEX(unit, mem)) * soc_mem_index_count(unit, mem))
  16364                                                       : (a_ind * soc_mem_index_count(unit, mem));
  16365 #else
  16366 
  16367                             mem_array_vmap_offset = a_ind * soc_mem_index_count(unit, mem);
  16368 #endif
  16369                             mem_array_cache_offset = mem_array_vmap_offset * entry_dw;
  16370                             cache_cp = cache;
  16371                             cache_cp +=  mem_array_cache_offset + (index_min * entry_dw);
  16372                             for (i = index_min; i <= index_max; i++) { /* update cache */
  16373                                 sal_memcpy(cache_cp, buffer, entry_dw * 4);
  16374                                 cache_cp += entry_dw;
  16375                                 CACHE_VMAP_SET(vmap, mem_array_vmap_offset + i);
  16376                             }
  16377                         }
  16378                     }
  16379                 }
  16380             }
  16381 #endif
  16382         } else
  16383 #endif
  16384         {
  16385             /**
  16386              * the code above is intended for non-slambles dma, 
  16387              * so we write the array table by table 
  16388  */
  16389             int j;
  16390             int       chunk_size, chunk_entries, mem_size, entry_words;
  16391             int       index, index_end;
  16392             uint32    *buf;
  16393 
  16394             chunk_size = 2*1024*1024; /* 2MB: max DMA buffer size to allocate */
  16395             entry_words = soc_mem_entry_words(unit, mem);
  16396             mem_size = (index_max - index_min + 1) * entry_words * 4;
  16397             if (mem_size < chunk_size) {
  16398                 chunk_size = mem_size;
  16399             }
  16400 
  16401             buf = soc_cm_salloc(unit, chunk_size, "fill_table_using_table_dma");
  16402             if (buf == NULL) {
  16403                 MEM_UNLOCK(unit, mem);
  16404                 return SOC_E_MEMORY;
  16405             }
  16406 
  16407             chunk_entries = chunk_size / (entry_words * 4);
  16408 
  16409             for (index = 0; index < chunk_entries; index++) {
  16410                 sal_memcpy(buf + (index * entry_words),
  16411                            buffer, entry_words * 4);
  16412             }
  16413 
  16414             /* Loop over the block instances and write to each one using table DMA */
  16415             SOC_MEM_BLOCK_ITER(unit, mem, blk) {
  16416                 if (copyno_override) {
  16417                     blk = copyno_override;
  16418                 } else if (copyno != COPYNO_ALL && copyno != blk) {
  16419                     continue;
  16420                 }
  16421 
  16422                 for (j=min_ar_index; j <= max_ar_index && rv == SOC_E_NONE; j++) {
  16423                 for (index = index_min; index <= index_max; index += chunk_entries) {
  16424                     index_end = index + chunk_entries - 1;
  16425                     if (index_end > index_max) {
  16426                         index_end = index_max;
  16427                     }
  16428 
  16429                         rv = soc_mem_array_write_range(unit, 0, mem, j, blk, index, index_end, buf);
  16430                         if (rv != SOC_E_NONE) {
  16431                         LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, "soc_mem_write_range: " "write %s.%s[%d-%d] failed: %s\n"),
  16432                                                           SOC_MEM_UFNAME(unit, mem), SOC_BLOCK_NAME(unit, blk), index, index_end, soc_errmsg(rv)));
  16433                         break;
  16434                     }
  16435                 }
  16436                 }
  16437 
  16438                 if (copyno_override || rv != SOC_E_NONE) break;
  16439             }
  16440             soc_cm_sfree(unit, buf);
  16441         }
  16442         /* Cache have been updated for petra device */
  16443 #if !(defined(BCM_PETRA_SUPPORT) || defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT))
  16444        if (rv == SOC_E_NONE) {
  16445             uint8 *vmap;
  16446 
  16447             /* Loop over the block instances ignoring broadcast write block, and update cache */
  16448             SOC_MEM_BLOCK_ITER(unit, mem, blk) {
  16449                 if (copyno != COPYNO_ALL && copyno != blk) {
  16450                     continue;
  16451                 }
  16452 
  16453                 cache = SOC_MEM_STATE(unit, mem).cache[blk];
  16454 
  16455                 /*    coverity[negative_returns : FALSE]    */
  16456                 /* coverity[negative_returns] */
  16457                 vmap = SOC_MEM_STATE(unit, mem).vmap[blk];
  16458 
  16459                 if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)) {
  16460                     if (!SOC_MEM_IS_ARRAY(unit, mem)) {
  16461                         min_ar_index = max_ar_index = 0;
  16462                     }
  16463                     for (a_ind = min_ar_index; a_ind <= max_ar_index; ++a_ind) {
  16464                         int bytes_to_copy = entry_dw * 4;
  16465 #ifdef BCM_DNX_SUPPORT
  16466                         mem_array_vmap_offset = (SOC_MEM_IS_ARRAY(unit, mem)) ?
  16467                                                 ((a_ind - SOC_MEM_FIRST_ARRAY_INDEX(unit, mem)) * soc_mem_index_count(unit, mem))
  16468                                                  : (a_ind * soc_mem_index_count(unit, mem));
  16469 #else
  16470                         mem_array_vmap_offset = a_ind * soc_mem_index_count(unit, mem);
  16471 #endif
  16472                         mem_array_cache_offset = mem_array_vmap_offset * entry_dw;
  16473                         cache_cp = cache;
  16474                         cache_cp +=  mem_array_cache_offset + (index_min * entry_dw);
  16475                         for (i = index_min; i <= index_max; i++) { /* update cache */
  16476                             sal_memcpy(cache_cp, buffer, bytes_to_copy);
  16477                             cache_cp += entry_dw;
  16478                             CACHE_VMAP_SET(vmap, mem_array_vmap_offset + i);
  16479                         }
  16480                     }
  16481                 }
  16482             }
  16483         }
  16484 
  16485 #endif
  16486         MEM_UNLOCK(unit, mem);
  16487         if (NULL != meminfo->snoop_cb) {
  16488             if (SOC_MEM_SNOOP_WRITE & meminfo->snoop_flags) {
  16489                 meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_WRITE,
  16490                                   copyno, index_min, index_max, (void*)buffer,
  16491                                   meminfo->snoop_user_data);
  16492             }
  16493             if (SOC_MEM_SNOOP_WRITE_COUNT & meminfo->snoop_flags) {
  16494                 meminfo->snoop_cb(unit, mem, SOC_MEM_SNOOP_WRITE_COUNT,
  16495                                   copyno, index_min, index_max, (void*)buffer,
  16496                                   meminfo->snoop_user_data);
  16497             }
  16498         }
  16499     } else {
  16500         /* Loop over the block instances ignoring broadcast write block, fill the table per entry */
  16501         SOC_MEM_BLOCK_ITER(unit, mem, blk) {
  16502             if (copyno != COPYNO_ALL && copyno != blk) {
  16503                 continue;
  16504     }
  16505 
  16506     for (a_ind = min_ar_index; a_ind <= max_ar_index; ++a_ind) {
  16507         for (i = index_min; i <= index_max; i++) {
  16508                     SOC_IF_ERROR_RETURN(soc_mem_array_write(unit, mem, a_ind, blk, i, (void*)buffer));
  16509         }
  16510     }
  16511         }
  16512     }
  16513     return rv;
  16514 }
  16515 
  16516 /*
  16517  *    Efficiently write to a whole memory with a repeating entry.
  16518  *    When SLAM DMA is available, it is used, and the buffer must be allocated using soc_cm_salloc().
  16519  */
  16520 
  16521 int
  16522 soc_mem_fill(
  16523     int unit,           /* unit of the memory */
  16524     soc_mem_t mem,      /* Memory to be written to */
  16525     int copyno,         /* Memory block to write to */
  16526     const void *buffer) /* buffer of the entry to repeatedly write. If the memory can be written to by SLAM DMA,
  16527                            then the buffer must be allocated using soc_cm_salloc(). */
  16528 {
  16529     int rc;
  16530     unsigned max_array_index = 0;
  16531     unsigned min_array_index = 0;
  16532 #ifdef SOC_MEM_DEBUG_SPEED
  16533     sal_usecs_t start_time = sal_time_usecs();
  16534     int diff_time;
  16535 #endif
  16536 
  16537     if (!soc_mem_is_valid(unit, mem)) {
  16538         return SOC_E_MEMORY;
  16539     }
  16540     if (SOC_MEM_IS_ARRAY(unit, mem)) {
  16541         soc_mem_array_info_t *maip = SOC_MEM_ARRAY_INFOP(unit, mem);
  16542         if (maip) {
  16543             max_array_index = (maip->numels - 1) + maip->first_array_index;
  16544             min_array_index = maip->first_array_index;
  16545         }
  16546     }
  16547     rc = soc_mem_array_fill_range(unit, 0, mem, min_array_index, max_array_index, copyno, soc_mem_index_min(unit, mem), soc_mem_index_max(unit, mem), buffer);
  16548 
  16549 #ifdef SOC_MEM_DEBUG_SPEED
  16550     diff_time = SAL_USECS_SUB(sal_time_usecs(), start_time);
  16551     LOG_VERBOSE(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit, "Total dma write time: %d usecs\n"), diff_time));
  16552 #endif
  16553  return rc;
  16554 }
  16555 
  16556 #ifdef BCM_TRIDENT_SUPPORT
  16557 STATIC int _soc_mem_clear_require_pipe_select(int unit, soc_mem_t mem)
  16558 {
  16559     if (!(soc_mem_is_valid(unit, mem))) {
  16560         return FALSE;
  16561     } else {
  16562         switch (mem) {
  16563         case L3_ENTRY_HIT_ONLYm:
  16564         case L3_DEFIP_HIT_ONLYm:
  16565         case FP_COUNTER_TABLEm:
  16566         case FP_STORM_CONTROL_METERSm:
  16567         case ING_PW_TERM_SEQ_NUMm:
  16568         case ING_VINTF_COUNTER_TABLEm:
  16569         case ING_SERVICE_COUNTER_TABLEm:
  16570         case TRILL_DROP_STATSm:
  16571         case DLB_HGT_GROUP_CONTROLm:
  16572         case DLB_HGT_GROUP_STATSm:
  16573         case DLB_HGT_FLOWSET_TIMESTAMP_PAGEm:
  16574         case DLB_HGT_OPTIMAL_CANDIDATEm:
  16575         case DLB_HGT_FLOWSET_PORTm:
  16576         case DLB_HGT_FLOWSET_TIMESTAMPm:
  16577         case EGR_FRAGMENT_ID_TABLEm:
  16578         case EFP_METER_TABLEm:
  16579         case EGR_PW_INIT_COUNTERSm:
  16580         case EFP_COUNTER_TABLEm:
  16581         case EGR_PERQ_XMT_COUNTERSm:
  16582         case EGR_VINTF_COUNTER_TABLEm:
  16583         case EGR_SERVICE_COUNTER_TABLEm:
  16584         case EGR_PORT_REQUESTSm:
  16585         case EGR_MMU_REQUESTSm:
  16586         case EGR_MAX_USED_ENTRIESm:
  16587             return TRUE;
  16588         default:
  16589             return FALSE;
  16590         }
  16591     }
  16592 }
  16593 #endif
  16594 
  16595 /************************************************************************
  16596  * Routines for reading/writing sorted tables except ARL,        *
  16597  * and searching sorted tables including the ARL.            *
  16598  * Sorted tables are:  IRULE, L3, MCAST, PVLAN                *
  16599  */
  16600 
  16601 #if defined(BCM_TRIDENT2_SUPPORT)
  16602 STATIC int
  16603 _soc_mem_clear_tcam_protect_clear_restore(int unit,
  16604                                           soc_mem_t mem,
  16605                                           int clear_restore, /* 0:clear, 1:restore*/
  16606                                           int *tcam_protect_write,
  16607                                           int *config_128b_entries)
  16608 {
  16609     soc_mem_t defip_mem = L3_DEFIPm;
  16610     soc_mem_t defip_pair_mem = L3_DEFIP_PAIR_128m;
  16611     int qualified =
  16612         soc_feature(unit, soc_feature_l3_defip_map) &&
  16613         (mem == L3_DEFIPm ||
  16614          mem == L3_DEFIP_LEVEL1m ||
  16615          mem == L3_DEFIP_ONLYm ||
  16616          mem == L3_DEFIP_DATA_ONLYm ||
  16617          mem == L3_DEFIP_HIT_ONLY_Xm ||
  16618          mem == L3_DEFIP_HIT_ONLY_Ym ||
  16619          mem == L3_DEFIP_HIT_ONLYm ||
  16620          mem == L3_DEFIP_PAIR_128m ||
  16621          mem == L3_DEFIP_PAIR_LEVEL1m ||
  16622          mem == L3_DEFIP_PAIR_128_ONLYm ||
  16623          mem == L3_DEFIP_PAIR_128_DATA_ONLYm ||
  16624          mem == L3_DEFIP_PAIR_128_HIT_ONLY_Xm ||
  16625          mem == L3_DEFIP_PAIR_128_HIT_ONLY_Ym ||
  16626          mem == L3_DEFIP_PAIR_128_HIT_ONLYm);
  16627 
  16628     if (!qualified) {
  16629         return SOC_E_NONE;
  16630     }
  16631 
  16632     if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) {
  16633         defip_mem = L3_DEFIP_LEVEL1m;
  16634         defip_pair_mem = L3_DEFIP_PAIR_LEVEL1m;
  16635     }
  16636 
  16637     if (clear_restore == 0) { /* clear */
  16638         *tcam_protect_write = SOC_CONTROL(unit)->tcam_protect_write;
  16639         SOC_CONTROL(unit)->tcam_protect_write = FALSE;
  16640         if (*tcam_protect_write) {
  16641             if (soc_mem_index_count(unit, defip_mem)) {
  16642                 SOP_MEM_STATE(unit, defip_mem).index_max += 8;
  16643                 SOC_CONTROL(unit)->l3_defip_tcam_size++;
  16644             }
  16645             if (soc_mem_index_count(unit, defip_pair_mem)) {
  16646                 SOP_MEM_STATE(unit, defip_pair_mem).index_max += 4;
  16647                 SOC_CONTROL(unit)->l3_defip_tcam_size++;
  16648             }
  16649             *config_128b_entries = SOC_L3_DEFIP_MAX_128B_ENTRIES(unit) + 4;
  16650 
  16651             SOC_CONTROL(unit)->l3_defip_index_remap =
  16652                 soc_mem_index_count(unit, defip_pair_mem);
  16653             return soc_l3_defip_indexes_init(unit, *config_128b_entries);
  16654         }
  16655     } else {  /* restore */
  16656         SOC_CONTROL(unit)->tcam_protect_write = *tcam_protect_write;
  16657         if (*tcam_protect_write) {
  16658             if (soc_mem_index_count(unit, defip_mem)) {
  16659                 SOP_MEM_STATE(unit, defip_mem).index_max -= 8;
  16660                 SOC_CONTROL(unit)->l3_defip_tcam_size--;
  16661             }
  16662             if (soc_mem_index_count(unit, defip_pair_mem)) {
  16663                 SOP_MEM_STATE(unit, defip_pair_mem).index_max -= 4;
  16664                 SOC_CONTROL(unit)->l3_defip_tcam_size--;
  16665             }
  16666             SOC_CONTROL(unit)->l3_defip_index_remap =
  16667                 soc_mem_index_count(unit, defip_pair_mem);
  16668             *config_128b_entries -= 4;
  16669             return soc_l3_defip_indexes_init(unit, *config_128b_entries);
  16670         }
  16671     }
  16672     return SOC_E_NONE;
  16673 }
  16674 #endif /* BCM_TRIDENT2_SUPPORT */
  16675 
  16676 /*
  16677  * Function:
  16678  *    soc_mem_clearable_on_reset
  16679  * Purpose:
  16680  *    Determine whether a table can be cleared during resetting
  16681  * Returns:
  16682  *    0 if not, 1 otherwise
  16683  */
  16684 
  16685 int
  16686 soc_mem_clearable_on_reset(int unit, soc_mem_t mem, int copyno)
  16687 {
  16688     int blk;
  16689 #ifdef BCM_TOMAHAWK_SUPPORT
  16690     if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
  16691         if (soc_mem_is_readonly(unit, mem)) {
  16692             return FALSE;
  16693         }
  16694         switch (mem) {
  16695         /* L3_MTU_VALUESm should always be cleared during initialization.
  16696          * After clearing, the MTU_SIZEf was set to default value (0x3fff).
  16697          * After "init soc;init misc", the MTU_SIZEf was set to zero.
  16698          * Zero will cause L3 cases failure.
  16699          */
  16700         case L3_MTU_VALUESm:
  16701         case IS_TDM_CALENDAR0m:
  16702         case IS_TDM_CALENDAR1m:
  16703         case IS_TDM_CALENDAR0_PIPE0m:
  16704         case IS_TDM_CALENDAR0_PIPE1m:
  16705         case IS_TDM_CALENDAR0_PIPE2m:
  16706         case IS_TDM_CALENDAR0_PIPE3m:
  16707         case IS_TDM_CALENDAR1_PIPE0m:
  16708         case IS_TDM_CALENDAR1_PIPE1m:
  16709         case IS_TDM_CALENDAR1_PIPE2m:
  16710         case IS_TDM_CALENDAR1_PIPE3m:
  16711         case LINK_STATUSm:
  16712 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT)
  16713         case PKT_SCH_CALENDAR0_PIPE0m:
  16714         case PKT_SCH_CALENDAR0_PIPE1m:
  16715         case PKT_SCH_CALENDAR1_PIPE0m:
  16716         case PKT_SCH_CALENDAR1_PIPE1m:
  16717 #endif
  16718 #if defined(BCM_TOMAHAWK2_SUPPORT)
  16719         case PKT_SCH_CALENDAR0_PIPE2m:
  16720         case PKT_SCH_CALENDAR0_PIPE3m:
  16721         case PKT_SCH_CALENDAR1_PIPE2m:
  16722         case PKT_SCH_CALENDAR1_PIPE3m:
  16723 #endif
  16724             return FALSE;
  16725         default:
  16726             break;
  16727         }
  16728         SOC_MEM_BLOCK_ITER(unit, mem, blk) {
  16729             if (copyno != COPYNO_ALL && copyno != blk) {
  16730                 continue;
  16731             }
  16732             switch (SOC_BLOCK_TYPE(unit, blk)) {
  16733             case SOC_BLK_IPIPE:
  16734             case SOC_BLK_EPIPE:
  16735                 return TRUE;
  16736             default:
  16737                 break;
  16738             }
  16739         }
  16740     } else
  16741 #endif
  16742     {
  16743         COMPILER_REFERENCE(unit);
  16744         COMPILER_REFERENCE(mem);
  16745         COMPILER_REFERENCE(copyno);
  16746         COMPILER_REFERENCE(blk);
  16747     }
  16748 
  16749     return FALSE;
  16750 }
  16751 
  16752 /*
  16753  * Function:
  16754  *    soc_mem_clear
  16755  * Purpose:
  16756  *    Clears a memory.
  16757  *    Operates on all copies of the table if copyno is COPYNO_ALL.
  16758  * Notes:
  16759  *    For non-sorted tables, all entries are cleared.  For sorted
  16760  *    tables, only the entries known to contain data are cleared,
  16761  *    unless the force_all flag is on, in which case all entries
  16762  *    are cleared.  The force_all flag is mainly intended for the first
  16763  *    initialization after a chip reset.
  16764  */
  16765 
  16766 int
  16767 soc_mem_clear(int unit,
  16768               soc_mem_t mem,
  16769               int copyno,
  16770               int force_all)
  16771 {
  16772     int           rv = SOC_E_NONE;
  16773 #if defined(BCM_ESW_SUPPORT)
  16774     int           blk, index_min, index_max, index;
  16775 #endif
  16776 #if defined(BCM_FIREBOLT_SUPPORT)
  16777     uint8         *vmap, *vmap1 = NULL;
  16778     uint32        entry_dw, *cache;
  16779     void          *null_entry = soc_mem_entry_null(unit, mem);
  16780     uint32        empty_entry[SOC_MAX_MEM_WORDS] = {0};
  16781 #if defined(INCLUDE_MEM_SCAN) && \
  16782     (defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT))
  16783     uint32        xy_null_entry[SOC_MAX_MEM_WORDS] = {0};
  16784 #endif /* INCLUDE_MEM_SCAN && (BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT) */
  16785 #endif /* BCM_FIREBOLT_SUPPORT */
  16786 
  16787 #ifdef BCM_TRIDENT_SUPPORT
  16788     int(*pipe_select)(int, int, int) = NULL;
  16789     int           require_pipe_select = FALSE;
  16790 #ifdef BCM_TRIDENT2_SUPPORT
  16791     uint8         acc_type = 0;
  16792     int           tcam_protect_write = 0;
  16793     int           config_128b_entries = 0;
  16794 #endif
  16795     if (SOC_IS_TRIDENT(unit) || SOC_IS_TITAN(unit)) {
  16796         pipe_select = soc_trident_pipe_select;
  16797         require_pipe_select = _soc_mem_clear_require_pipe_select(unit, mem);
  16798     }
  16799 #ifdef BCM_TRIDENT2_SUPPORT
  16800     else if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2X(unit)) {
  16801         pipe_select = soc_trident2_pipe_select;
  16802         acc_type = SOC_MEM_ACC_TYPE(unit, mem);
  16803         require_pipe_select = (acc_type == _SOC_ACC_TYPE_PIPE_SBS) ? TRUE : FALSE;
  16804     }
  16805 #endif
  16806     else {
  16807         pipe_select = NULL;
  16808     }
  16809 #endif
  16810     _SOC_MEM_REPLACE_MEM(unit, mem);
  16811     if (soc_mem_index_count(unit, mem) == 0) {
  16812         return SOC_E_NONE;
  16813     }
  16814 
  16815     DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, TRUE));
  16816 
  16817     if (SOC_HW_RESET(unit) &&
  16818         soc_mem_clearable_on_reset(unit, mem, copyno)) {
  16819         return SOC_E_NONE;
  16820     }
  16821 
  16822 /* DISABLE_SBUS_MEMWR_PARITY_CHECK bit has to been cleared before return */
  16823 #if defined(BCM_TRIDENT2_SUPPORT)
  16824     if (SOC_IS_TD2_TT2(unit) && (!SOC_IS_TOMAHAWKX(unit))) {
  16825         soc_trident2_l3_memwr_parity_check(unit, mem, TRUE);
  16826     }
  16827     _soc_mem_clear_tcam_protect_clear_restore(unit, mem, 0,
  16828         &tcam_protect_write, &config_128b_entries);
  16829 #endif /* BCM_TRIDENT2_SUPPORT */
  16830 #if defined(BCM_TRIDENT3_SUPPORT)
  16831     if (SOC_IS_TRIDENT3X(unit)) {
  16832         (void)soc_trident3_l3_memwr_parity_check(unit, mem, TRUE);
  16833     }
  16834 #endif
  16835 
  16836 #if defined(BCM_FIREBOLT_SUPPORT)
  16837     if (SOC_IS_FBX(unit)) {
  16838         if (!null_entry) {
  16839             null_entry = empty_entry;
  16840         }
  16841         MEM_LOCK(unit, mem);
  16842         SOC_MEM_BLOCK_ITER(unit, mem, blk) {
  16843             if (copyno != COPYNO_ALL && copyno != blk) {
  16844                 continue;
  16845             }
  16846             index_min = soc_mem_index_min(unit, mem);
  16847             index_max = soc_mem_index_max(unit, mem);
  16848             if (SOC_MEM_CLEAR_USE_DMA(unit)) {
  16849                 rv = _soc_xgs3_mem_clear_pipe(unit, mem, blk, null_entry);
  16850                 if (rv == SOC_E_UNAVAIL) {
  16851                     if (soc_mem_slamable(unit, mem, blk)) {
  16852                         rv = _soc_xgs3_mem_clear_slam(unit, mem, blk, null_entry);
  16853                         if (rv < 0) {
  16854                             goto check_cache;
  16855                         }
  16856 #ifdef BCM_TRIDENT_SUPPORT
  16857                         if ((SOC_IS_TD_TT(unit) && !SOC_IS_TOMAHAWKX(unit)) && 
  16858                         	  (require_pipe_select == TRUE) && (pipe_select != NULL)) {
  16859                             IP_ARBITER_LOCK(unit);
  16860                             /* Switch to Y-pipe */
  16861                             (void)pipe_select(unit, TRUE, 1);
  16862                             (void)pipe_select(unit, FALSE, 1);
  16863                             rv = _soc_xgs3_mem_clear_slam(unit, mem, blk, null_entry);
  16864                             /* Restore to X-pipe */
  16865                             (void)pipe_select(unit, TRUE, 0);
  16866                             (void)pipe_select(unit, FALSE, 0);
  16867                             IP_ARBITER_UNLOCK(unit);
  16868                             if (rv < 0) {
  16869                                 goto check_cache;
  16870                             }
  16871                         }
  16872 #endif
  16873                     } else {
  16874                         goto _clear_use_pio;
  16875                     }
  16876                 }
  16877                 if (rv < 0) {
  16878                     goto check_cache;
  16879                 }
  16880             } else {
  16881 _clear_use_pio:
  16882                 for (index = index_min; index <= index_max; index++) {
  16883                     /* Clear only index which are valid */
  16884                     if (_soc_mem_read_tcam_is_invalid(unit, mem, index) == FALSE) {
  16885                     if ((rv = soc_mem_write(unit, mem, blk, index,
  16886                                             null_entry)) < 0) {
  16887                         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  16888                                   (BSL_META_U(unit,
  16889                                               "soc_mem_clear: "
  16890                                               "write %s.%s[%d] failed: %s\n"),
  16891                                    SOC_MEM_UFNAME(unit, mem),
  16892                                    SOC_BLOCK_NAME(unit, blk),
  16893                                    index, soc_errmsg(rv)));
  16894                         goto done;
  16895                     }
  16896                 }
  16897                 }
  16898 #ifdef BCM_TRIDENT_SUPPORT
  16899                 if ((SOC_IS_TD_TT(unit) && !SOC_IS_TOMAHAWKX(unit)) && 
  16900                     (require_pipe_select == TRUE) && (pipe_select != NULL)) {
  16901                     IP_ARBITER_LOCK(unit);
  16902                     /* Switch to Y-pipe */
  16903                     (void)pipe_select(unit, TRUE, 1);
  16904                     (void)pipe_select(unit, FALSE, 1);
  16905                     for (index = index_min; index <= index_max; index++) {
  16906                         /* Clear only index which are valid */
  16907                         if (_soc_mem_read_tcam_is_invalid(unit, mem, index) == FALSE) {
  16908                         if ((rv = soc_mem_write(unit, mem, blk, index,
  16909                                                 null_entry)) < 0) {
  16910                             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  16911                                   (BSL_META_U(unit,
  16912                                               "soc_mem_clear: "
  16913                                               "write %s.%s[%d] failed: %s\n"),
  16914                                    SOC_MEM_UFNAME(unit, mem),
  16915                                    SOC_BLOCK_NAME(unit, blk),
  16916                                    index, soc_errmsg(rv)));
  16917                             /* Restore to X-pipe */
  16918                             (void)pipe_select(unit, TRUE, 0);
  16919                             (void)pipe_select(unit, FALSE, 0);
  16920                             IP_ARBITER_UNLOCK(unit);
  16921                             goto done;
  16922                         }
  16923                     }
  16924                     }
  16925                     /* Restore to X-pipe */
  16926                     (void)pipe_select(unit, TRUE, 0);
  16927                     (void)pipe_select(unit, FALSE, 0);
  16928                     IP_ARBITER_UNLOCK(unit);
  16929                 }
  16930 #endif
  16931             }
  16932 check_cache:
  16933             /* Update cache if active */
  16934             cache = SOC_MEM_STATE(unit, mem).cache[blk];
  16935             vmap = SOC_MEM_STATE(unit, mem).vmap[blk];
  16936             if (_SOC_MEM_CHK_L2_MEM(mem)) {
  16937                 if (mem == L2_ENTRY_1m) {
  16938                     vmap1 = SOC_MEM_STATE(unit, L2_ENTRY_2m).vmap[blk];
  16939                 } else if (mem == L2_ENTRY_2m) {
  16940                     vmap1 = SOC_MEM_STATE(unit, L2_ENTRY_1m).vmap[blk];
  16941                 }
  16942             }
  16943             entry_dw = soc_mem_entry_words(unit, mem);
  16944             if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit) &&
  16945                 !SOC_WARM_BOOT(unit)) {
  16946 #if defined(INCLUDE_MEM_SCAN) && \
  16947     (defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT))
  16948                 if (soc_feature(unit, soc_feature_xy_tcam) &&
  16949                     (SOC_MEM_INFO(unit, mem).flags & SOC_MEM_FLAG_CAM) &&
  16950                     (!(SOC_MEM_INFO(unit, mem).flags &
  16951                                SOC_MEM_FLAG_EXT_CAM))) {
  16952                     _soc_mem_tcam_dm_to_xy(unit, mem, 1, null_entry,
  16953                                            xy_null_entry, NULL);
  16954                 }
  16955 #endif /* INCLUDE_MEM_SCAN && (BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT) */
  16956                 for (index = index_min; index <= index_max; index++) {
  16957                     if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit) ||
  16958                         SOC_HW_ACCESS_DISABLE(unit)) {
  16959                         CACHE_VMAP_CLR(vmap, index);
  16960                     } else if (vmap1) {
  16961                         CACHE_VMAP_CLR(vmap, index);
  16962                         if (mem == L2_ENTRY_1m) {
  16963                             CACHE_VMAP_CLR(vmap1, index/2);
  16964                         } else {
  16965                             CACHE_VMAP_CLR(vmap1, index*2);
  16966                             CACHE_VMAP_CLR(vmap1, index*2 + 1);
  16967                         }
  16968                     } else {
  16969                         sal_memcpy(cache + index * entry_dw, null_entry,
  16970                                    entry_dw * 4);
  16971                         CACHE_VMAP_CLR(vmap, index);
  16972 #if defined(INCLUDE_MEM_SCAN) && \
  16973     (defined(BCM_TRIDENT_SUPPORT) || defined(BCM_SHADOW_SUPPORT))
  16974                         if (soc_feature(unit, soc_feature_xy_tcam) &&
  16975                             (SOC_MEM_INFO(unit, mem).flags &
  16976                              SOC_MEM_FLAG_CAM) &&
  16977                             (!(SOC_MEM_INFO(unit, mem).flags &
  16978                                SOC_MEM_FLAG_EXT_CAM))) {
  16979                             /* Update memscan TCAM cache if necessary */
  16980                             soc_mem_scan_tcam_cache_update(unit, mem,
  16981                                                            index, index,
  16982                                                            xy_null_entry);
  16983                         }
  16984 #endif /* INCLUDE_MEM_SCAN && (BCM_TRIDENT_SUPPORT || BCM_SHADOW_SUPPORT) */
  16985 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
  16986 #ifdef BCM_WARM_BOOT_SUPPORT
  16987                         if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2X(unit) ||
  16988                             SOC_IS_TRIDENT(unit) || SOC_IS_TITAN(unit)) {
  16989                             soc_mem_overlay_tcam_update(unit, mem, blk,
  16990                                                         index, index);
  16991                         }
  16992 #endif
  16993 #endif
  16994                     }
  16995                 }
  16996             }
  16997         }
  16998 #ifdef BCM_TRIDENT2_SUPPORT
  16999     /* For MMU_INTFI_X/YPIPE_FC_MAP_TBL0/1, update software shadow table. */
  17000     if (SOC_IS_TRIDENT2(unit)) {
  17001         if (mem == MMU_INTFI_XPIPE_FC_MAP_TBL0m ||
  17002             mem == MMU_INTFI_XPIPE_FC_MAP_TBL1m ||
  17003             mem == MMU_INTFI_YPIPE_FC_MAP_TBL0m ||
  17004             mem == MMU_INTFI_YPIPE_FC_MAP_TBL1m){
  17005             rv = soc_trident2_fc_map_shadow_clear(unit, mem);
  17006             goto done;
  17007         }
  17008     }
  17009 #endif
  17010         goto done; /* Required if block iter does not execute even once */
  17011     }
  17012 #endif /* BCM_FIREBOLT_SUPPORT */
  17013 
  17014 #if defined(BCM_XGS12_FABRIC_SUPPORT)
  17015     if (copyno != COPYNO_ALL) {
  17016         assert(SOC_MEM_BLOCK_VALID(unit, mem, copyno));
  17017     }
  17018 
  17019     MEM_LOCK(unit, mem);
  17020 
  17021     SOC_MEM_BLOCK_ITER(unit, mem, blk) {
  17022         if (copyno != COPYNO_ALL && copyno != blk) {
  17023             continue;
  17024         }
  17025 
  17026         index_min = soc_mem_index_min(unit, mem);
  17027         index_max = soc_mem_index_max(unit, mem);
  17028 
  17029         switch (mem) {
  17030 #if defined(BCM_XGS_SWITCH_SUPPORT)
  17031         case L3_IPMCm:
  17032 #endif
  17033 #ifdef BCM_XGS12_FABRIC_SUPPORT
  17034         case MEM_UCm:
  17035         case MEM_MCm:
  17036         case MEM_VIDm:
  17037         case MEM_IPMCm:
  17038 #ifdef BCM_HERCULES15_SUPPORT
  17039         case MEM_EGR_MODMAPm:
  17040         case MEM_ING_MODMAPm:
  17041         case MEM_ING_SRCMODBLKm:
  17042         case MEM_TRUNK_PORT_POOLm:
  17043 #endif /* BCM_HERCULES15_SUPPORT */
  17044 #endif /* BCM_XGS12_FABRIC_SUPPORT */
  17045 #ifdef BCM_XGS_SWITCH_SUPPORT
  17046         case EGR_MASKm:
  17047         case MAC_BLOCKm:
  17048         case PORT_TABm:
  17049         case STG_TABm:
  17050         case TRUNK_GROUPm:
  17051         case TRUNK_BITMAPm:
  17052         case TRUNK_EGR_MASKm:
  17053         case VLAN_TABm:
  17054 #endif /* BCM_XGS_SWITCH_SUPPORT */
  17055             /* NOTE: fall through from above */
  17056             /* Tables where all entries should be cleared to null value */
  17057             for (index = index_min; index <= index_max; index++) {
  17058                 if ((rv = soc_mem_write(unit, mem, blk, index,
  17059                                         soc_mem_entry_null(unit, mem))) < 0) {
  17060                     LOG_ERROR(BSL_LS_SOC_SOCMEM,
  17061                               (BSL_META_U(unit,
  17062                                           "soc_mem_clear: "
  17063                                           "write %s.%s[%d] failed: %s\n"),
  17064                                SOC_MEM_UFNAME(unit, mem),
  17065                                SOC_BLOCK_NAME(unit, blk),
  17066                                index, soc_errmsg(rv)));
  17067                     goto done;
  17068                 }
  17069             }
  17070             break;
  17071 #if defined(BCM_5690) || defined(BCM_5665)
  17072         case GFILTER_FFPCOUNTERSm:
  17073         case GFILTER_FFPPACKETCOUNTERSm:
  17074 #if defined(BCM_5695)
  17075         case GFILTER_FFP_IN_PROFILE_COUNTERSm:
  17076         case GFILTER_FFP_OUT_PROFILE_COUNTERSm:
  17077 #endif
  17078         case GFILTER_METERINGm:
  17079 #endif
  17080 #if defined(BCM_5673) || defined(BCM_5674)
  17081         case XFILTER_FFPCOUNTERSm:
  17082         case XFILTER_FFPOPPACKETCOUNTERSm:
  17083         case XFILTER_FFPIPPACKETCOUNTERSm:
  17084         case XFILTER_FFPOPBYTECOUNTERSm:
  17085         case XFILTER_FFPIPBYTECOUNTERSm:
  17086         case XFILTER_METERINGm:
  17087 #endif
  17088 #if defined(BCM_5690) || defined(BCM_5665) || \
  17089     defined(BCM_5673) || defined(BCM_5674)
  17090             if (soc_feature(unit, soc_feature_filter_metering)) {
  17091                 /* NOTE: fall through from above */
  17092                 /* Tables where all entries should be cleared to null value */
  17093                 for (index = index_min; index <= index_max; index++) {
  17094                     if ((rv = soc_mem_write(unit, mem, blk, index,
  17095                                             soc_mem_entry_null(unit,
  17096                                                                mem))) < 0) {
  17097                         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  17098                                   (BSL_META_U(unit,
  17099                                               "soc_mem_clear: "
  17100                                               "write %s.%s[%d] failed: %s\n"),
  17101                                    SOC_MEM_UFNAME(unit, mem),
  17102                                    SOC_BLOCK_NAME(unit, blk),
  17103                                    index, soc_errmsg(rv)));
  17104                         goto done;
  17105                     }
  17106                 }
  17107                 break;
  17108             } /* else fall thru to default */
  17109 #endif /* BCM_XGS_SWITCH_SUPPORT */
  17110         default:
  17111             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  17112                       (BSL_META_U(unit,
  17113                                   "soc_mem_clear: don't know how to clear %s\n"),
  17114                        SOC_MEM_UFNAME(unit, mem)));
  17115             rv = SOC_E_PARAM;
  17116             goto done;
  17117         }
  17118     }
  17119 #endif /* XGS12_FABRIC */
  17120 
  17121     rv = SOC_E_NONE;
  17122     goto done;
  17123 
  17124 done:
  17125     MEM_UNLOCK(unit, mem);
  17126 
  17127 /* DISABLE_SBUS_MEMWR_PARITY_CHECK bit has to be cleared before return */
  17128 #if defined(BCM_TRIDENT2_SUPPORT)
  17129     if (SOC_IS_TD2_TT2(unit) && (!SOC_IS_TOMAHAWKX(unit))) {
  17130         soc_trident2_l3_memwr_parity_check(unit, mem, FALSE);
  17131     }
  17132     _soc_mem_clear_tcam_protect_clear_restore(unit, mem, 1,
  17133         &tcam_protect_write, &config_128b_entries);
  17134 #endif /* BCM_TRIDENT2_SUPPORT */
  17135 #if defined(BCM_TRIDENT3_SUPPORT)
  17136     if (SOC_IS_TRIDENT3X(unit)) {
  17137         (void)soc_trident3_l3_memwr_parity_check(unit, mem, FALSE);
  17138     }
  17139 #endif
  17140 
  17141     LOG_INFO(BSL_LS_SOC_SOCMEM,
  17142              (BSL_META_U(unit,
  17143                          "soc_mem_clear: unit %d memory %s.%s returns %s\n"),
  17144               unit, SOC_MEM_UFNAME(unit, mem),
  17145               SOC_BLOCK_NAME(unit, copyno), soc_errmsg(rv)));
  17146 
  17147     return rv;
  17148 }
  17149 
  17150 /*
  17151  * Function:
  17152  *      _soc_mem_search
  17153  * Purpose:
  17154  *      Helper function for soc_mem_search.  Does the raw search
  17155  *      without worrying about special memory cases.
  17156  * Parameters:
  17157  *      See soc_mem_search, below.
  17158  * Returns:
  17159  *  SOC_E_NOT_FOUND
  17160  *  Entry not found:  in this case, if
  17161  *                           table is sorted, then index_ptr gets the
  17162  *                           location in which the entry should be
  17163  *                           inserted.
  17164  *  SOC_E_NONE       Entry is found:  index_ptr gets location
  17165  *  SOC_E_XXX        If internal error occurs
  17166  * Notes:
  17167  *  See soc_mem_search, below.
  17168  */
  17169 
  17170 STATIC int
  17171 _soc_mem_search(int unit,
  17172                soc_mem_t mem,
  17173                int copyno,
  17174                int *index_ptr,
  17175                void *key_data,
  17176                void *entry_data,
  17177                int lowest_match)
  17178 {
  17179     int base, count, mid, last_read = -1;
  17180     int rv, r;
  17181 
  17182     /*
  17183      * Establish search range within table.  For filter, optimize using
  17184      * cached start/count of rule set for mask specified by FSEL.  Note
  17185      * that all rules using a given FSEL are necessarily contiguous.
  17186      */
  17187     base = soc_mem_index_min(unit, mem);
  17188     count = soc_mem_entries(unit, mem, copyno);
  17189 
  17190     while (count > 0) {
  17191         mid = base + count / 2;
  17192 
  17193         if ((rv = soc_mem_read(unit, mem, copyno, mid, entry_data)) < 0) {
  17194             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  17195                       (BSL_META_U(unit,
  17196                                   "soc_mem_search: read %s.%s[%d] failed\n"),
  17197                        SOC_MEM_UFNAME(unit, mem),
  17198                        SOC_BLOCK_NAME(unit, copyno), mid));
  17199             return rv;
  17200         }
  17201 
  17202         last_read = mid;
  17203 
  17204         r = soc_mem_compare_key(unit, mem, key_data, entry_data);
  17205 
  17206         if (r == 0) {
  17207             if (lowest_match) {
  17208                 count = count / 2;      /* Must treat same as < 0 */
  17209             } else {
  17210                 if (index_ptr != NULL) {
  17211                     *index_ptr = mid;   /* Don't care if it's lowest match */
  17212                 }
  17213                 return SOC_E_NONE;              /* Found */
  17214             }
  17215         } else if (r < 0) {
  17216             count = count / 2;
  17217         } else {
  17218             base = mid + 1;
  17219             count = (count - 1) / 2;
  17220         }
  17221     }
  17222 
  17223     *index_ptr = base;
  17224 
  17225     /*
  17226      * base is the expected position of the entry (insertion point).
  17227      * If lowest_match is true, we may have actually found it, and
  17228      * we have to check again here.
  17229      */
  17230 
  17231     if (lowest_match && base <= soc_mem_index_max(unit, mem)) {
  17232         if (last_read != base &&        /* Optimize out read if possible */
  17233             (rv = soc_mem_read(unit, mem, copyno, base, entry_data)) < 0) {
  17234             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  17235                       (BSL_META_U(unit,
  17236                                   "soc_mem_search: read %s.%s[%d] failed\n"),
  17237                        SOC_MEM_UFNAME(unit, mem),
  17238                        SOC_BLOCK_NAME(unit, copyno), base));
  17239             return rv;
  17240         }
  17241 
  17242         if (soc_mem_compare_key(unit, mem, key_data, entry_data) == 0) {
  17243             return SOC_E_NONE;                  /* Found */
  17244         }
  17245     }
  17246 
  17247     /* If bitmap conflict found, return SOC_E_CONFIG */
  17248     return SOC_E_NOT_FOUND;       /* No error; not found */
  17249 }
  17250 
  17251 /* Special hash mem lookup routine used only in context of generic lookup failure
  17252    due to parity/ecc error in order to do bank specific lookups or accelerate
  17253    mem cache indexing by fetching bucket index from h/w */
  17254 STATIC int
  17255 _soc_mem_bank_lookup(int unit, soc_mem_t mem, int copyno, int32 banks,
  17256                      void *key, void *result, int *index_ptr)
  17257 {
  17258     schan_msg_t schan_msg;
  17259     int         rv, entry_dw, allow_intr=0;
  17260     uint8       at;
  17261     int         type, index, err_info=0;
  17262     uint32      *data;
  17263     int         src_blk, dst_blk, acc_type, data_byte_len;
  17264     int         opcode, nack;
  17265     uint32      bank_ignore_mask;
  17266 
  17267     entry_dw = soc_mem_entry_words(unit, mem);
  17268 
  17269     schan_msg_clear(&schan_msg);
  17270     acc_type  = SOC_MEM_ACC_TYPE(unit, mem);
  17271     src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit));
  17272     dst_blk = SOC_BLOCK2SCH(unit, copyno);
  17273     if ((soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) ||
  17274         (soc_feature(unit, soc_feature_shared_hash_mem) && ((mem == L2Xm) ||
  17275          (mem == L3_ENTRY_ONLYm) || (mem == L3_ENTRY_IPV4_UNICASTm) ||
  17276          (mem == L3_ENTRY_IPV4_MULTICASTm) || (mem == L3_ENTRY_IPV6_UNICASTm) ||
  17277          (mem == L3_ENTRY_IPV6_MULTICASTm)
  17278 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  17279          || (mem == L3_ENTRY_SINGLEm) || (mem == L3_ENTRY_DOUBLEm)
  17280          || (mem == L3_ENTRY_QUADm) || (mem == MPLS_ENTRY_SINGLEm)
  17281 #endif
  17282 #if defined(BCM_TOMAHAWK3_SUPPORT)
  17283          || (mem == L3_TUNNEL_SINGLEm) || (mem == L3_TUNNEL_DOUBLEm)
  17284          || (mem == L3_TUNNEL_QUADm)
  17285 #endif
  17286 #if defined(BCM_TOMAHAWK_SUPPORT)
  17287          || _SOC_MEM_CHK_FPEM_MEM(mem)
  17288 #endif
  17289        ))) {
  17290         /* don't set bank id in cos */
  17291         bank_ignore_mask = 0;
  17292     } else {
  17293         bank_ignore_mask = banks & 0x3;
  17294     }
  17295     data_byte_len = entry_dw * 4;
  17296 
  17297     schan_msg.gencmd.address = soc_mem_addr_get(unit, mem, 0, copyno, 0, &at);
  17298     if ((soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) ||
  17299         (soc_feature(unit, soc_feature_shared_hash_mem) && ((mem == L2Xm) ||
  17300          (mem == L3_ENTRY_ONLYm) || (mem == L3_ENTRY_IPV4_UNICASTm) ||
  17301          (mem == L3_ENTRY_IPV4_MULTICASTm) || (mem == L3_ENTRY_IPV6_UNICASTm) ||
  17302          (mem == L3_ENTRY_IPV6_MULTICASTm)
  17303 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  17304          || (mem == L3_ENTRY_SINGLEm) || (mem == L3_ENTRY_DOUBLEm)
  17305          || (mem == L3_ENTRY_QUADm) || (mem == MPLS_ENTRY_SINGLEm)
  17306 #endif
  17307 #if defined(BCM_TOMAHAWK3_SUPPORT)
  17308          || (mem == L3_TUNNEL_SINGLEm) || (mem == L3_TUNNEL_DOUBLEm)
  17309          || (mem == L3_TUNNEL_QUADm)
  17310 #endif
  17311 #if defined(BCM_TOMAHAWK_SUPPORT)
  17312          || _SOC_MEM_CHK_FPEM_MEM(mem)
  17313 #endif
  17314        ))) {
  17315         /* set bank ignore mask in lower 20 bits */
  17316         if (banks && banks != SOC_MEM_HASH_BANK_ALL) {
  17317             if (soc_feature(unit, soc_feature_shared_hash_mem)) {
  17318                 schan_msg.gencmd.address |= (~banks & SOC_HASH_BANK_MASK_SHARED);
  17319             } else {
  17320 #ifdef BCM_TRIUMPH3_SUPPORT
  17321                 uint32 phy_banks = soc_ism_get_phy_bank_mask(unit, banks);
  17322                 schan_msg.gencmd.address |= (~phy_banks & SOC_HASH_BANK_MASK_ISM);
  17323 #endif /* BCM_TRIUMPH3_SUPPORT */
  17324             }
  17325         }
  17326     }
  17327 
  17328     soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_LOOKUP_CMD_MSG,
  17329                              dst_blk, src_blk, acc_type, data_byte_len, 0,
  17330                              bank_ignore_mask);
  17331 
  17332     /* Fill in entry data */
  17333     sal_memcpy(schan_msg.gencmd.data, key, entry_dw * 4);
  17334 
  17335     if (SOC_IS_SAND(unit)) {
  17336         allow_intr = 1;
  17337     }
  17338 
  17339     /*
  17340      * Execute S-Channel "lookup insert" command packet consisting of
  17341      * (header word + address word + entry_dw), and read back
  17342      * (header word + response word + entry_dw) data words.
  17343      */
  17344 
  17345     rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr);
  17346 
  17347     /* Check result */
  17348     soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL,
  17349                                 NULL, NULL, &nack);
  17350     if (opcode != TABLE_LOOKUP_DONE_MSG) {
  17351         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  17352                   (BSL_META_U(unit,
  17353                               "soc_mem_bank_lookup: "
  17354                               "invalid S-Channel reply, expected TABLE_LOOKUP_DONE_MSG:\n")));
  17355         soc_schan_dump(unit, &schan_msg, entry_dw + 2);
  17356         return SOC_E_INTERNAL;
  17357     }
  17358 
  17359     if (soc_feature(unit, soc_feature_new_sbus_format) &&
  17360         !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
  17361         type = schan_msg.genresp_v2.response.type;
  17362         err_info = schan_msg.genresp_v2.response.err_info;
  17363         index = schan_msg.genresp_v2.response.index;
  17364         data = schan_msg.genresp_v2.data;
  17365     } else {
  17366         type = schan_msg.genresp.response.type;
  17367         index = schan_msg.genresp.response.index;
  17368         data = schan_msg.genresp.data;
  17369     }
  17370     if ((nack != 0) || (rv == SOC_E_FAIL)) {
  17371         if (type == SCHAN_GEN_RESP_TYPE_NOT_FOUND) {
  17372             rv = SOC_E_NOT_FOUND;
  17373         } else {
  17374             rv = SOC_E_FAIL;
  17375             
  17376             if (!(SOC_IS_TRIUMPH3(unit) || (SOC_IS_TRIDENT2(unit)
  17377                 || (SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_TITAN2PLUS(unit)))
  17378                 || (SOC_IS_TOMAHAWKX(unit)) || SOC_IS_APACHE(unit)
  17379                 || SOC_IS_TRIDENT3X(unit))) {
  17380                 index = schan_msg.dwords[2] & 0xffff;
  17381             }
  17382             if (err_info == SCHAN_GEN_RESP_ERR_INFO_ERROR_IN_LP_TABLE) {
  17383                 LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  17384                     "_soc_mem_bank_lookup: Encountered error on LP table "
  17385                     "for memory %s, banks[0x%0x], err_rsp_index[%d] !!\n"),
  17386                     SOC_MEM_NAME(unit, mem), banks, index));
  17387 #if defined(BCM_TOMAHAWK_SUPPORT)
  17388                 if (SOC_IS_TOMAHAWKX(unit)) {
  17389                     if (SOC_FAILURE(soc_th_lp_to_fv_index_remap(unit, mem, &index))) {
  17390                         return SOC_E_INTERNAL; 
  17391                     }
  17392                 }
  17393 #endif
  17394             }
  17395         }
  17396     } else {
  17397         if (result != NULL) {
  17398             sal_memcpy(result, data, entry_dw * sizeof(uint32));
  17399         }
  17400     }
  17401     *index_ptr = index;
  17402 
  17403     if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) {
  17404         LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  17405                             "Bank lookup table[%s]: banks=%d"), SOC_MEM_NAME(unit, mem),
  17406                  banks));
  17407         if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) {
  17408             soc_mem_entry_dump(unit, mem, data, BSL_VERBOSE|BSL_LS_SOC_COMMON);
  17409         }
  17410         if (SOC_FAILURE(rv)) {
  17411             if (type == SCHAN_GEN_RESP_TYPE_NOT_FOUND) {
  17412                 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  17413                                     " Not found\n")));
  17414             } else {
  17415                 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  17416                                     " Fail, bkt:%d\n"), index));
  17417             }
  17418         } else {
  17419             LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  17420                                 " (index=%d)\n"), index));
  17421         }
  17422     }
  17423 
  17424     return rv;
  17425 }
  17426 
  17427 #ifdef BCM_TRIDENT2_SUPPORT
  17428 STATIC INLINE int
  17429 _soc_mem_shared_hash_entries_per_bkt(int unit, soc_mem_t mem)
  17430 {
  17431 #if defined(BCM_TRIDENT3_SUPPORT)
  17432     if (SOC_IS_TRIDENT3X(unit)) {
  17433         return 4;
  17434     }
  17435 #endif /* defined(BCM_TRIDENT3_SUPPORT) */
  17436     switch(mem) {
  17437     case L2Xm:
  17438     case L3_ENTRY_ONLYm:
  17439     case L3_ENTRY_IPV4_UNICASTm:
  17440     case L3_ENTRY_SINGLEm:
  17441     case L3_TUNNEL_SINGLEm:
  17442     case L3_ENTRY_ONLY_SINGLEm:
  17443     case VLAN_XLATE_1_SINGLEm:
  17444     case VLAN_XLATE_2_SINGLEm:
  17445     case VLAN_XLATE_1_DOUBLEm:
  17446     case VLAN_XLATE_2_DOUBLEm:
  17447     case EGR_VLAN_XLATE_1_SINGLEm:
  17448     case EGR_VLAN_XLATE_2_SINGLEm:
  17449     case EGR_VLAN_XLATE_1_DOUBLEm:
  17450     case EGR_VLAN_XLATE_2_DOUBLEm:
  17451     case MPLS_ENTRY_SINGLEm:
  17452         return 4;
  17453     case L3_ENTRY_IPV6_UNICASTm:
  17454     case L3_ENTRY_IPV4_MULTICASTm:
  17455     case MPLS_ENTRYm:
  17456         return 2;
  17457     case L3_ENTRY_IPV6_MULTICASTm:
  17458         return 1;
  17459     case L3_ENTRY_DOUBLEm:
  17460     case L3_TUNNEL_DOUBLEm:
  17461     case EXACT_MATCH_2m:
  17462     case EXACT_MATCH_2_PIPE0m:
  17463     case EXACT_MATCH_2_PIPE1m:
  17464     case EXACT_MATCH_2_PIPE2m:
  17465     case EXACT_MATCH_2_PIPE3m:        
  17466 #ifdef BCM_TOMAHAWK3_SUPPORT
  17467         if (SOC_IS_TOMAHAWK3(unit)) {
  17468             return 2;
  17469         } else
  17470 #endif
  17471         {
  17472             return 4;
  17473         }
  17474 
  17475     case EXACT_MATCH_4m:
  17476     case EXACT_MATCH_4_PIPE0m:
  17477     case EXACT_MATCH_4_PIPE1m:
  17478     case EXACT_MATCH_4_PIPE2m:
  17479     case EXACT_MATCH_4_PIPE3m:        
  17480     case L3_ENTRY_QUADm:
  17481     case L3_TUNNEL_QUADm:
  17482 #ifdef BCM_TOMAHAWK3_SUPPORT
  17483         if (SOC_IS_TOMAHAWK3(unit)) {
  17484             return 1;
  17485         } else
  17486 #endif
  17487         {
  17488         return 4;         
  17489         }
  17490     default:
  17491         return 4;
  17492     }
  17493 }
  17494 #endif /* BCM_TRIDENT2_SUPPORT */
  17495 
  17496 STATIC int
  17497 _soc_mem_hash_entries_per_bkt(int unit, soc_mem_t mem)
  17498 {
  17499     if (soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) {
  17500         if (mem == L2_ENTRY_2m || mem == L3_ENTRY_2m || mem == VLAN_XLATE_EXTDm
  17501             || mem == MPLS_ENTRY_EXTDm) {
  17502             return 2;
  17503         } else if (mem == L3_ENTRY_4m) {
  17504             return 1;
  17505         } else {
  17506             return 4;
  17507         }
  17508     }
  17509 #if defined(BCM_HURRICANE2_SUPPORT) || defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
  17510     else if (soc_feature(unit, soc_feature_hr2_dual_hash) ||
  17511              SOC_IS_KATANA2(unit) || SOC_IS_TRIDENT(unit)) {
  17512         switch (mem) {
  17513             case L3_ENTRY_ONLYm:
  17514             case L3_ENTRY_IPV4_UNICASTm:
  17515                 return 8;
  17516             case L2Xm:
  17517             case L3_ENTRY_IPV6_UNICASTm:
  17518             case L3_ENTRY_IPV4_MULTICASTm:
  17519                 return 4;
  17520             case L3_ENTRY_IPV6_MULTICASTm:
  17521                 return 2;
  17522             default:
  17523                 return 4;
  17524         }
  17525     }
  17526 #endif /* BCM_HURRICANE2_SUPPORT */
  17527 #ifdef BCM_TRIDENT2_SUPPORT
  17528     else {
  17529         return _soc_mem_shared_hash_entries_per_bkt(unit, mem);
  17530     }
  17531 #endif /* BCM_TRIDENT2_SUPPORT */
  17532     return 4;
  17533 }
  17534 
  17535 STATIC int
  17536 _soc_hash_mem_entry_base_get(int unit, soc_mem_t mem, int bank, int base_index,
  17537                              int num_entries)
  17538 {
  17539     if (soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) {
  17540         return base_index * num_entries;
  17541     } else if (soc_feature(unit, soc_feature_shared_hash_mem)) {
  17542          if (((mem == L2Xm) ||
  17543              (mem == L3_ENTRY_ONLYm) || (mem == L3_ENTRY_IPV4_UNICASTm) ||
  17544              (mem == L3_ENTRY_IPV4_MULTICASTm) || (mem == L3_ENTRY_IPV6_UNICASTm) ||
  17545              (mem == L3_ENTRY_IPV6_MULTICASTm))) {
  17546             return base_index * num_entries;
  17547          } else {
  17548             return (base_index/num_entries) * num_entries;
  17549          }
  17550     } else {
  17551         num_entries *= 2;
  17552         if (bank) {
  17553             return ((base_index * num_entries ) + 4);
  17554         } else {
  17555             return base_index * num_entries;
  17556         }
  17557     }
  17558 }
  17559 
  17560 STATIC void
  17561 _soc_mem_entry_get_key(int unit, soc_mem_t mem, void *entry, void *key)
  17562 {
  17563 #ifdef BCM_ISM_SUPPORT
  17564     if (soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) {
  17565         /* Use ism routines */
  17566         (void)soc_gen_key_from_entry(unit, mem, entry, key);
  17567     } else
  17568 #endif /* BCM_ISM_SUPPORT */
  17569     {
  17570         /* Else use key field */
  17571         if (SOC_MEM_FIELD_VALID(unit, mem, KEYf)) {
  17572             uint32 key_buff[SOC_MAX_MEM_FIELD_WORDS];
  17573             soc_mem_field_get(unit, mem, entry, KEYf, key_buff);
  17574             soc_mem_field_set(unit, mem, key, KEYf, key_buff);
  17575         } else {
  17576             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  17577                       (BSL_META_U(unit,
  17578                                   "Unable to retreive key for %s.\n"),
  17579                        SOC_MEM_NAME(unit, mem)));
  17580         }
  17581     }
  17582 }
  17583 
  17584 
  17585 /* NOTE: index1 is used for legacy dual hash only */
  17586 STATIC int
  17587 _soc_mem_cache_lookup(int unit, soc_mem_t mem, int copyno, int32 banks,
  17588                       void *key, void *result, int index0, int index1,
  17589                       int *index_ptr, uint32 *cache, uint8 *vmap)
  17590 {
  17591     int i, rc;
  17592     uint32 bmap = 0;
  17593     uint32 *entry_ptr, match_key[SOC_MAX_MEM_WORDS];
  17594     uint32 entry_dw = soc_mem_entry_words(unit, mem);
  17595 #ifdef BCM_ISM_SUPPORT
  17596     _soc_ism_mem_banks_t ism_banks;
  17597 #endif /* BCM_ISM_SUPPORT */
  17598 
  17599 #ifdef BCM_ISM_SUPPORT
  17600     if (soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) {
  17601         rc = soc_ism_get_banks_for_mem(unit, mem, ism_banks.banks,
  17602                                        ism_banks.bank_size, &ism_banks.count);
  17603         if (SOC_FAILURE(rc) || ism_banks.count == 0) {
  17604             if (index_ptr) {
  17605                 *index_ptr = -1;
  17606             }
  17607             return SOC_E_NOT_FOUND;
  17608         }
  17609         for (i = 0; i < ism_banks.count; i++) {
  17610             bmap |= 1 << ism_banks.banks[i];
  17611         }
  17612         bmap &= banks;
  17613     } else
  17614 #endif /* BCM_ISM_SUPPORT */
  17615 #ifdef BCM_TRIDENT2_SUPPORT
  17616     if (soc_feature(unit, soc_feature_shared_hash_mem) && ((mem == L2Xm) ||
  17617          (mem == L3_ENTRY_ONLYm) || (mem == L3_ENTRY_IPV4_UNICASTm) ||
  17618          (mem == L3_ENTRY_IPV4_MULTICASTm) || (mem == L3_ENTRY_IPV6_UNICASTm) ||
  17619          (mem == L3_ENTRY_IPV6_MULTICASTm)
  17620 #if defined(BCM_TOMAHAWK_SUPPORT)
  17621          || _SOC_MEM_CHK_FPEM_MEM(mem)
  17622 #endif
  17623 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  17624         || (mem == L3_ENTRY_SINGLEm) || (mem == L3_ENTRY_DOUBLEm) ||
  17625         (mem == L3_ENTRY_QUADm)
  17626 #endif
  17627        )) {
  17628 #ifdef BCM_APACHE_SUPPORT
  17629         if (SOC_IS_APACHE(unit)) {
  17630             SOC_IF_ERROR_RETURN
  17631                 (soc_apache_hash_bank_phy_bitmap_get(unit, mem, &bmap));
  17632         } else
  17633 #endif /* BCM_APACHE_SUPPORT */
  17634 #ifdef BCM_TOMAHAWK_SUPPORT
  17635         if (SOC_IS_TOMAHAWKX(unit)) {
  17636 #ifdef BCM_TOMAHAWK3_SUPPORT
  17637             if (SOC_IS_TOMAHAWK3(unit)) {
  17638                 SOC_IF_ERROR_RETURN
  17639                     (soc_tomahawk3_hash_bank_phy_bitmap_get(unit, mem, &bmap));
  17640             } else
  17641 #endif /* BCM_TOMAHAWK3_SUPPORT */
  17642             {
  17643             SOC_IF_ERROR_RETURN
  17644                 (soc_tomahawk_hash_bank_phy_bitmap_get(unit, mem, &bmap));
  17645             }
  17646         } else
  17647 #endif /* BCM_TOMAHAWK_SUPPORT */
  17648 #ifdef BCM_HELIX5_SUPPORT
  17649         if (SOC_IS_HELIX5(unit)) {
  17650             SOC_IF_ERROR_RETURN
  17651                 (soc_hx5_hash_bank_phy_bitmap_get(unit, mem, &bmap));
  17652         } else
  17653 #endif /* BCM_HELIX5_SUPPORT */
  17654 #ifdef BCM_TRIDENT3_SUPPORT
  17655         if (SOC_IS_TRIDENT3X(unit)) {
  17656             SOC_IF_ERROR_RETURN
  17657                 (soc_td3_hash_bank_phy_bitmap_get(unit, mem, &bmap));
  17658         } else
  17659 #endif /* BCM_TRIDENT3_SUPPORT */
  17660         {
  17661             SOC_IF_ERROR_RETURN
  17662                 (soc_trident2_hash_bank_bitmap_get(unit, mem, &bmap));
  17663         }
  17664         /* For L2X and L3_ENTRY tables, if banks is zero, it means all banks
  17665          * banks should be either specific bank bitmap or an indication that
  17666          * specifying all banks.
  17667          */
  17668         (banks) ? bmap &= banks : bmap;
  17669     } else
  17670 #endif /* BCM_TRIDENT2_SUPPORT */
  17671     { /* Dual hash */
  17672         bmap = 0x3;
  17673         (banks) ? bmap &= banks : bmap;
  17674     }
  17675     /* Issue lookups on all specified & applicable banks */
  17676     if (bmap) {
  17677         int e, entries, entry_base, match, index = -1;
  17678 
  17679         entries = _soc_mem_hash_entries_per_bkt(unit, mem);
  17680         for (i = 0; i < 32; i++) {
  17681             if (bmap & (1 << i)) {
  17682                 if (index1 == -1) {
  17683                     rc = _soc_mem_bank_lookup(unit, mem, copyno, 1 << i, key,
  17684                                               result, &index);
  17685                 } else { /* Legacy dual hash: bucket indexes are already known */
  17686                     index = i ? index1 : index0;
  17687                     rc = SOC_E_FAIL;
  17688                 }
  17689                 if (SOC_FAILURE(rc)) { /* Case where correction has not yet happened */
  17690                     if (rc == SOC_E_NOT_FOUND) {
  17691                         continue;
  17692                     } else if (rc == SOC_E_INTERNAL) {
  17693                         return rc;
  17694                     } else if (rc == SOC_E_FAIL) {
  17695                         /* Check and compare key with all entries in the bucket */
  17696                         if (!SOC_IS_TD2_TT2(unit)) {
  17697                             /* All other devices return the bucket */
  17698                             LOG_VERBOSE(BSL_LS_SOC_COMMON,
  17699                                         (BSL_META_U(unit,
  17700                                                     "Check in bucket: %d\n"),
  17701                                          index));
  17702                             entry_base = _soc_hash_mem_entry_base_get(unit, mem, i,
  17703                                                                       index, entries);
  17704                         } else {
  17705                             /* TD and TD2 return the index */
  17706                             if (mem == L3_ENTRY_IPV4_MULTICASTm || mem == L3_ENTRY_IPV6_UNICASTm
  17707 #if defined(BCM_TOMAHAWK_SUPPORT)
  17708                                 || mem == EXACT_MATCH_2m
  17709                                 || mem == EXACT_MATCH_2_PIPE0m
  17710                                 || mem == EXACT_MATCH_2_PIPE1m
  17711                                 || mem == EXACT_MATCH_2_PIPE2m
  17712                                 || mem == EXACT_MATCH_2_PIPE3m
  17713 #endif /* BCM_TOMAHAWK_SUPPORT */
  17714 #if defined(BCM_TRIDENT3_SUPPORT)
  17715                                 || mem == VLAN_XLATE_1_DOUBLEm
  17716                                 || mem == VLAN_XLATE_2_DOUBLEm
  17717                                 || mem == EGR_VLAN_XLATE_1_DOUBLEm
  17718                                 || mem == EGR_VLAN_XLATE_2_DOUBLEm
  17719 #endif
  17720 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  17721                                 || mem == L3_ENTRY_DOUBLEm
  17722 #endif /* BCM_TRIDENT3_SUPPORT */
  17723                                ) {
  17724                                 index = index/2;
  17725                             } else if (mem == L3_ENTRY_IPV6_MULTICASTm
  17726 #if defined(BCM_TOMAHAWK_SUPPORT)
  17727                                 || mem == EXACT_MATCH_4m
  17728                                 || mem == EXACT_MATCH_4_PIPE0m
  17729                                 || mem == EXACT_MATCH_4_PIPE1m
  17730                                 || mem == EXACT_MATCH_4_PIPE2m
  17731                                 || mem == EXACT_MATCH_4_PIPE3m
  17732 #endif /* BCM_TOMAHAWK_SUPPORT */
  17733 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  17734                                 || mem == L3_ENTRY_QUADm
  17735 #endif
  17736                                ) {
  17737                                 index = index/4;
  17738                             } else if (SOC_IS_TRIDENT3X(unit)&&
  17739                                        (mem == SUBPORT_ID_TO_SGPP_MAPm ||
  17740                                         mem == ING_DNAT_ADDRESS_TYPEm ||
  17741                                         mem == ING_VP_VLAN_MEMBERSHIPm ||
  17742                                         mem == EGR_VP_VLAN_MEMBERSHIPm)) {
  17743                                 /*
  17744                                 * When SER error exist on thers memories on TD3
  17745                                 * SBUS lookup will return ECC view index in RSP_WRD
  17746                                 */
  17747                                 index *= 2;
  17748                             }
  17749                             LOG_VERBOSE(BSL_LS_SOC_COMMON,
  17750                                         (BSL_META_U(unit,
  17751                                                     "Check at index: %d\n"),
  17752                                          index));
  17753                             entry_base = index;
  17754                         }
  17755                         LOG_VERBOSE(BSL_LS_SOC_COMMON,
  17756                                     (BSL_META_U(unit,
  17757                                                 "Base entry: %d\n"), entry_base));
  17758                         for (e = 0; e < entries; e++) {
  17759                             /* Try with only cached entries */
  17760                             if (CACHE_VMAP_TST(vmap, entry_base+e)) {
  17761                                 match = 0;
  17762                                 entry_ptr = cache + ((entry_base+e) * entry_dw);
  17763                                 sal_memset(match_key, 0, sizeof(match_key));
  17764                                 /* If match found then return else continue */
  17765                                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
  17766                                             (BSL_META_U(unit,
  17767                                                         "Check cached entry at "
  17768                                                         "index: %d\n"), entry_base+e));
  17769                                 if (soc_feature(unit, soc_feature_ism_memory) &&
  17770                                     soc_mem_is_mview(unit, mem) && !(mem == L2_ENTRY_1m ||
  17771                                     mem == L2_ENTRY_2m)) { /* L2 key compare routine exists for TR3 */
  17772                                     uint32 entry_key[SOC_MAX_MEM_WORDS];
  17773 
  17774                                     sal_memset(entry_key, 0, sizeof(entry_key));
  17775                                     _soc_mem_entry_get_key(unit, mem, entry_ptr, match_key);
  17776                                     _soc_mem_entry_get_key(unit, mem, key, entry_key);
  17777                                     if (sal_memcmp(entry_key, match_key, entry_dw * 4)) {
  17778                                         continue;
  17779                                     } else {
  17780                                         match = 1;
  17781                                     }
  17782                                 } else if (soc_mem_cmp_fn(unit, mem)) {
  17783                                     if (soc_mem_compare_key(unit, mem, entry_ptr, key)) {
  17784                                         continue;
  17785                                     } else {
  17786                                         match = 1;
  17787                                     }
  17788                                 } else {
  17789                                     uint32 entry_key[SOC_MAX_MEM_WORDS];
  17790 
  17791                                     sal_memset(entry_key, 0, sizeof(entry_key));
  17792                                     _soc_mem_entry_get_key(unit, mem, entry_ptr, match_key);
  17793                                     _soc_mem_entry_get_key(unit, mem, key, entry_key);
  17794                                     if (sal_memcmp(entry_key, match_key, entry_dw * 4)) {
  17795                                         continue;
  17796                                     } else {
  17797                                         match = 1;
  17798                                     }
  17799                                 }
  17800                                 if (match) {
  17801                                     if (result) {
  17802                                         sal_memcpy(result, entry_ptr, entry_dw * 4);
  17803                                     }
  17804                                     if (index_ptr) {
  17805                                         *index_ptr = entry_base+e;
  17806                                     }
  17807                                     return SOC_E_NONE;
  17808                                 }
  17809                             }
  17810                         }
  17811                     }
  17812                 } else { /* Case where correction completes before this routine */
  17813                     if (index_ptr) {
  17814                         *index_ptr = index;
  17815                     }
  17816                     return SOC_E_NONE;
  17817                 }
  17818             }
  17819         }
  17820     }
  17821     if (index_ptr) {
  17822         *index_ptr = -1;
  17823     }
  17824     return SOC_E_NOT_FOUND;
  17825 }
  17826 
  17827 /*
  17828  * Function:
  17829  *      soc_mem_generic_lookup
  17830  * Purpose:
  17831  *      Send a lookup message over the S-Channel and receive the response.
  17832  * Parameters:
  17833  *      unit - StrataSwitch unit #
  17834  *      banks - For dual hashing, which halves are selected (inverted)
  17835  *              Note: used to create a bitmap for ISM mems. (All banks: -1)
  17836  *      key - entry to look up
  17837  *      result - entry to receive entire found entry
  17838  *      index_ptr (OUT) - If found, receives table index where found
  17839  * Returns:
  17840  *      SOC_E_INTERNAL if retries exceeded or other internal error
  17841  *      SOC_E_NOT_FOUND if the entry is not found.
  17842  *      SOC_E_NONE (0) on success (entry found):
  17843  */
  17844 
  17845 int
  17846 soc_mem_generic_lookup(int unit, soc_mem_t mem, int copyno, int32 banks,
  17847                        void *key, void *result, int *index_ptr)
  17848 {
  17849     schan_msg_t schan_msg;
  17850     int         rv, entry_dw, allow_intr=0;
  17851     uint8       at;
  17852     int         type, index, index_valid, err_info=0;
  17853     uint32      *data;
  17854     int         src_blk, dst_blk, acc_type, data_byte_len;
  17855     int         opcode, nack;
  17856     uint32      bank_ignore_mask;
  17857 #ifdef BCM_TRIUMPH_SUPPORT
  17858     int         rv1 = SOC_E_NONE;
  17859 #endif
  17860 #ifdef BCM_TRIDENT3_SUPPORT
  17861     soc_mem_t phy_mem;
  17862 #endif
  17863 #if defined(BCM_GREYHOUND2_SUPPORT)
  17864     uint32 key_type = 0;
  17865 #endif /* BCM_GREYHOUND2_SUPPORT */
  17866 #ifdef BCM_TOMAHAWK3_SUPPORT 
  17867     int j = 0, k = 0, l = 0;
  17868     schan_msg_t schan_msg_dupl;
  17869     uint16 dev_id;
  17870     uint8 rev_id;
  17871     int dw = 0;
  17872     uint32 *entry = NULL;
  17873     void *entry_data1;
  17874     int entry_size;
  17875 
  17876     soc_cm_get_id(unit, &dev_id, &rev_id);
  17877 #endif
  17878 #ifdef BCM_TRIDENT3_SUPPORT
  17879     if (soc_feature(unit, soc_feature_flex_flow)) {
  17880         if (SOC_MEM_IS_VIEW(unit, mem)) {
  17881             rv = soc_mem_view_phy_mem_get(unit, mem, &phy_mem);
  17882             if (rv != SOC_E_NONE) {
  17883                 return rv;
  17884             }
  17885             mem = phy_mem;
  17886         }
  17887     }
  17888 #endif
  17889 
  17890     _SOC_MEM_REPLACE_MEM(unit, mem);
  17891     SOC_MEM_ALIAS_TO_ORIG(unit,mem);
  17892     assert(SOC_MEM_IS_VALID(unit, mem));
  17893     assert(soc_attached(unit));
  17894 
  17895     if (copyno == MEM_BLOCK_ANY) {
  17896         /* coverity[overrun-local : FALSE] */
  17897         copyno = SOC_MEM_BLOCK_ANY(unit, mem);
  17898     }
  17899     if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) {
  17900         LOG_WARN(BSL_LS_SOC_SOCMEM,
  17901                  (BSL_META_U(unit,
  17902                              "soc_mem_generic_lookup: invalid block %d for memory %s\n"),
  17903                   copyno, SOC_MEM_NAME(unit, mem)));
  17904         return SOC_E_PARAM;
  17905     }
  17906 
  17907 #if defined(BCM_GREYHOUND2_SUPPORT)
  17908     if (soc_feature(unit, soc_feature_vxlan_lite_riot) && (mem == L2Xm)) {
  17909         key_type = soc_mem_field32_get(unit, mem, key, KEY_TYPEf);
  17910         /* Use SW to lookup a L2 entry when key_type is VFI_MULTICAST */
  17911         if (key_type == GH2_L2_HASH_KEY_TYPE_VFI_MULTICAST) {
  17912             return soc_mem_gh2_l2_sw_lookup(unit, mem, copyno, banks,
  17913                                             key, result, index_ptr);
  17914         }
  17915     }
  17916 #endif /* BCM_GREYHOUND2_SUPPORT */
  17917 
  17918     entry_dw = soc_mem_entry_words(unit, mem);
  17919 
  17920     MEM_LOCK(unit, mem);
  17921 #if defined(BCM_TRIUMPH3_SUPPORT)
  17922     if (soc_feature(unit, soc_feature_esm_correction) &&
  17923           ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  17924          (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  17925         SOC_ESM_LOCK(unit);
  17926     }
  17927 #endif
  17928     schan_msg_clear(&schan_msg);
  17929     acc_type = SOC_MEM_ACC_TYPE(unit, mem);
  17930     src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit));
  17931     dst_blk = SOC_BLOCK2SCH(unit, copyno);
  17932     if ((soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) ||
  17933         (soc_feature(unit, soc_feature_shared_hash_mem) && ((mem == L2Xm) ||
  17934          (mem == L3_ENTRY_ONLYm) || (mem == L3_ENTRY_IPV4_UNICASTm) ||
  17935          (mem == L3_ENTRY_IPV4_MULTICASTm) || (mem == L3_ENTRY_IPV6_UNICASTm) ||
  17936          (mem == L3_ENTRY_IPV6_MULTICASTm)
  17937 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  17938          || (mem == L3_ENTRY_SINGLEm) || (mem == L3_ENTRY_DOUBLEm)
  17939          || (mem == L3_ENTRY_QUADm) || (mem == MPLS_ENTRY_SINGLEm)
  17940 #endif
  17941 #if defined(BCM_TOMAHAWK3_SUPPORT)
  17942          || (mem == L3_TUNNEL_SINGLEm) || (mem == L3_TUNNEL_DOUBLEm)
  17943          || (mem == L3_TUNNEL_QUADm)
  17944 #endif
  17945 #if defined(BCM_TRIDENT3_SUPPORT)
  17946          || (mem == VLAN_XLATE_1_SINGLEm)
  17947          || (mem == VLAN_XLATE_1_DOUBLEm)
  17948          || (mem == EGR_VLAN_XLATE_1_SINGLEm)
  17949          || (mem == EGR_VLAN_XLATE_1_DOUBLEm)
  17950          || (mem == VLAN_XLATE_2_SINGLEm)
  17951          || (mem == VLAN_XLATE_2_DOUBLEm)
  17952          || (mem == EGR_VLAN_XLATE_2_SINGLEm)
  17953          || (mem == EGR_VLAN_XLATE_2_DOUBLEm)
  17954 #endif
  17955 #if defined(BCM_TOMAHAWK_SUPPORT)
  17956          || _SOC_MEM_CHK_FPEM_MEM(mem)
  17957 #endif
  17958        ))) {
  17959         /* don't set bank id in cos */
  17960         bank_ignore_mask = 0;
  17961     } else {
  17962         bank_ignore_mask = banks & 0x3;
  17963     }
  17964     data_byte_len = entry_dw * 4;
  17965 
  17966     schan_msg.gencmd.address = soc_mem_addr_get(unit, mem, 0, copyno, 0, &at);
  17967     if ((soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) ||
  17968         (soc_feature(unit, soc_feature_shared_hash_mem) && ((mem == L2Xm) ||
  17969          (mem == L3_ENTRY_ONLYm) || (mem == L3_ENTRY_IPV4_UNICASTm) ||
  17970          (mem == L3_ENTRY_IPV4_MULTICASTm) || (mem == L3_ENTRY_IPV6_UNICASTm) ||
  17971          (mem == L3_ENTRY_IPV6_MULTICASTm)
  17972 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  17973          || (mem == L3_ENTRY_SINGLEm) || (mem == L3_ENTRY_DOUBLEm)
  17974          || (mem == L3_ENTRY_QUADm) || (mem == MPLS_ENTRY_SINGLEm)
  17975 #endif
  17976 #if defined(BCM_TOMAHAWK3_SUPPORT)
  17977          || (mem == L3_TUNNEL_SINGLEm) || (mem == L3_TUNNEL_DOUBLEm)
  17978          || (mem == L3_TUNNEL_QUADm)
  17979 #endif
  17980 #if defined(BCM_TRIDENT3_SUPPORT)
  17981          || (mem == VLAN_XLATE_1_SINGLEm)
  17982          || (mem == VLAN_XLATE_1_DOUBLEm)
  17983          || (mem == EGR_VLAN_XLATE_1_SINGLEm)
  17984          || (mem == EGR_VLAN_XLATE_1_DOUBLEm)
  17985          || (mem == VLAN_XLATE_2_SINGLEm)
  17986          || (mem == VLAN_XLATE_2_DOUBLEm)
  17987          || (mem == EGR_VLAN_XLATE_2_SINGLEm)
  17988          || (mem == EGR_VLAN_XLATE_2_DOUBLEm)
  17989          || (mem == MPLS_ENTRYm)
  17990 #endif
  17991 #if defined(BCM_TOMAHAWK_SUPPORT)
  17992          || _SOC_MEM_CHK_FPEM_MEM(mem)
  17993 #endif
  17994        ))) {
  17995         /* set bank ignore mask in lower 20 bits */
  17996         if (banks && banks != SOC_MEM_HASH_BANK_ALL) {
  17997             if (soc_feature(unit, soc_feature_shared_hash_mem)) {
  17998                 schan_msg.gencmd.address |= (~banks & SOC_HASH_BANK_MASK_SHARED);
  17999             } else {
  18000 #ifdef BCM_TRIUMPH3_SUPPORT
  18001                 uint32 phy_banks = soc_ism_get_phy_bank_mask(unit, banks);
  18002                 schan_msg.gencmd.address |= (~phy_banks & SOC_HASH_BANK_MASK_ISM);
  18003 #endif /* BCM_TRIUMPH3_SUPPORT */
  18004             }
  18005         }
  18006     }
  18007 
  18008     /* BCM56960 supports 2 different modes for lookup
  18009      * Any width match mode - Bit 17 of SBUS address set to 0
  18010      * Exact width match mode - Bit 17 of SBUS address set to 1
  18011      * Below code sets lookup mode to exact width match mode for BCM56960
  18012      */
  18013     if (soc_feature(unit, soc_feature_exact_width_match_mode)) {
  18014         if ((mem == L3_ENTRY_IPV4_UNICASTm)   ||
  18015             (mem == L3_ENTRY_IPV4_MULTICASTm) ||
  18016             (mem == L3_ENTRY_IPV6_UNICASTm)   ||
  18017             (mem == L3_ENTRY_IPV6_MULTICASTm)
  18018 #if defined(BCM_TOMAHAWK_SUPPORT)
  18019             || _SOC_MEM_CHK_FPEM_MEM(mem)
  18020 #endif
  18021            ) {
  18022             /* Set bit 17 of SBUS address to select exact width match mode */
  18023             schan_msg.gencmd.address |= (1 << 17);
  18024         }
  18025     }
  18026 #ifdef BCM_TOMAHAWK3_SUPPORT
  18027     if (dev_id == BCM56983_DEVICE_ID) {
  18028         sal_memcpy(&schan_msg_dupl, &schan_msg, sizeof(schan_msg));
  18029         dw = soc_mem_entry_words(unit, mem);
  18030         entry_size = dw * sizeof(uint32);
  18031         entry = sal_alloc(entry_size, "entry_size");
  18032         sal_memset((void *)entry, 0, sizeof(uint32) * dw);
  18033         entry_data1 = entry;
  18034         l = sizeof(uint32);
  18035         if ((acc_type == 9 || acc_type == 14)) {
  18036             for (j = 0; j < 4; j++) {
  18037                 switch(j) {
  18038                     case 0 : acc_type = 0;
  18039                              break;
  18040                     case 1 : acc_type = 1;
  18041                              break;
  18042                     case 2 : acc_type = 6;
  18043                              break;
  18044                     case 3 : acc_type = 7;
  18045                              break;
  18046                 }
  18047                 sal_memcpy(&schan_msg, &schan_msg_dupl, sizeof(schan_msg));
  18048                 soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_LOOKUP_CMD_MSG,
  18049                                          dst_blk, src_blk, acc_type, data_byte_len, 0,
  18050                                          bank_ignore_mask);
  18051  
  18052                 /* Fill in entry data */
  18053                 sal_memcpy(schan_msg.gencmd.data, key, entry_dw * 4);
  18054 
  18055                 /*
  18056                  * Execute S-Channel "lookup insert" command packet consisting of
  18057                  * (header word + address word + entry_dw), and read back
  18058                  * (header word + response word + entry_dw) data words.
  18059                  */
  18060  
  18061                 rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr);
  18062                 for (k = 0; k < dw; k++) {
  18063                     *(uint32 *)((uint8 *)entry_data1 + l*k) =
  18064                             *(uint32 *)((uint8 *)schan_msg.genresp_v2.data + l*k) |
  18065                             *(uint32 *)((uint8 *)entry_data1 + l*k);
  18066                 }
  18067 
  18068                 /* Check result */
  18069                 soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL,
  18070                                             NULL, NULL, &nack);
  18071                 if (opcode != TABLE_LOOKUP_DONE_MSG) {
  18072                     LOG_ERROR(BSL_LS_SOC_SOCMEM,
  18073                               (BSL_META_U(unit,
  18074                                           "soc_mem_generic_lookup: "
  18075                                           "invalid S-Channel reply, expected TABLE_LOOKUP_DONE_MSG:\n")));
  18076                     soc_schan_dump(unit, &schan_msg, entry_dw + 2);
  18077 #if defined(BCM_TRIUMPH3_SUPPORT)
  18078                     if (soc_feature(unit, soc_feature_esm_correction) &&
  18079                           ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  18080                          (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  18081                         SOC_ESM_UNLOCK(unit);
  18082                     }
  18083 #endif
  18084                     MEM_UNLOCK(unit, mem);
  18085                     return SOC_E_INTERNAL;
  18086                 }
  18087                 if (rv != SOC_E_NONE) {
  18088                     break;
  18089                 }
  18090             }
  18091             sal_memcpy(schan_msg.genresp_v2.data, entry_data1, entry_dw * 4);
  18092             goto resume;
  18093         } else if (acc_type == 15) {
  18094             sal_memcpy(&schan_msg_dupl, &schan_msg, sizeof(schan_msg));
  18095             for (j = 0; j < 2; j++) {
  18096                 switch(j) {
  18097                     case 0 : acc_type = 0;
  18098                              break;
  18099                     case 1 : acc_type = 6;
  18100                              break;
  18101                 }
  18102                 sal_memcpy(&schan_msg, &schan_msg_dupl, sizeof(schan_msg));
  18103                 soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_LOOKUP_CMD_MSG,
  18104                                          dst_blk, src_blk, acc_type, data_byte_len, 0,
  18105                                          bank_ignore_mask);
  18106 
  18107                 /* Fill in entry data */
  18108                 sal_memcpy(schan_msg.gencmd.data, key, entry_dw * 4);
  18109 
  18110                 /*
  18111                  * Execute S-Channel "lookup insert" command packet consisting of
  18112                  * (header word + address word + entry_dw), and read back
  18113                  * (header word + response word + entry_dw) data words.
  18114                  */
  18115 
  18116                 rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr);
  18117                 for (k = 0; k < dw; k++) {
  18118                     *(uint32 *)((uint8 *)entry_data1 + l*k) =
  18119                             *(uint32 *)((uint8 *)schan_msg.genresp_v2.data + l*k) |
  18120                             *(uint32 *)((uint8 *)entry_data1 + l*k);
  18121                 }
  18122                 /* Check result */
  18123                 soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL,
  18124                                             NULL, NULL, &nack);
  18125 
  18126                 if (opcode != TABLE_LOOKUP_DONE_MSG) {
  18127                     LOG_ERROR(BSL_LS_SOC_SOCMEM,
  18128                               (BSL_META_U(unit,
  18129                                           "soc_mem_generic_lookup: "
  18130                                           "invalid S-Channel reply, expected TABLE_LOOKUP_DONE_MSG:\n")));
  18131                     soc_schan_dump(unit, &schan_msg, entry_dw + 2);
  18132 #if defined(BCM_TRIUMPH3_SUPPORT)
  18133                     if (soc_feature(unit, soc_feature_esm_correction) &&
  18134                           ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  18135                          (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  18136                         SOC_ESM_UNLOCK(unit);
  18137                     }
  18138 #endif
  18139                     MEM_UNLOCK(unit, mem);
  18140                     return SOC_E_INTERNAL;
  18141                 }
  18142                 if (rv != SOC_E_NONE) {
  18143                     break;
  18144                 }
  18145             }
  18146             sal_memcpy(schan_msg.genresp_v2.data, entry_data1, entry_dw * 4);
  18147             goto resume;
  18148         } else if (acc_type == 16) {
  18149             acc_type = 0;
  18150         }
  18151     }
  18152 #endif
  18153     soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_LOOKUP_CMD_MSG,
  18154                              dst_blk, src_blk, acc_type, data_byte_len, 0,
  18155                              bank_ignore_mask);
  18156 
  18157     /* Fill in entry data */
  18158     sal_memcpy(schan_msg.gencmd.data, key, entry_dw * 4);
  18159 
  18160     if (SOC_IS_SAND(unit)) {
  18161         allow_intr = 1;
  18162     }
  18163 
  18164     /*
  18165      * Execute S-Channel "lookup insert" command packet consisting of
  18166      * (header word + address word + entry_dw), and read back
  18167      * (header word + response word + entry_dw) data words.
  18168      */
  18169 
  18170     rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr);
  18171 
  18172     /* Check result */
  18173     soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL,
  18174                                 NULL, NULL, &nack);
  18175     if (opcode != TABLE_LOOKUP_DONE_MSG) {
  18176         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  18177                   (BSL_META_U(unit,
  18178                               "soc_mem_generic_lookup: "
  18179                               "invalid S-Channel reply, expected TABLE_LOOKUP_DONE_MSG:\n")));
  18180         soc_schan_dump(unit, &schan_msg, entry_dw + 2);
  18181 #if defined(BCM_TRIUMPH3_SUPPORT)
  18182         if (soc_feature(unit, soc_feature_esm_correction) &&
  18183               ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  18184              (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  18185             SOC_ESM_UNLOCK(unit);
  18186         }
  18187 #endif
  18188         MEM_UNLOCK(unit, mem);
  18189         return SOC_E_INTERNAL;
  18190     }
  18191 #ifdef BCM_TOMAHAWK3_SUPPORT
  18192 resume:
  18193 #endif
  18194 
  18195     if (soc_feature(unit, soc_feature_new_sbus_format) &&
  18196         !soc_feature(unit, soc_feature_new_sbus_old_resp)) {
  18197         type = schan_msg.genresp_v2.response.type;
  18198         err_info = schan_msg.genresp_v2.response.err_info;
  18199         index = schan_msg.genresp_v2.response.index;
  18200         data = schan_msg.genresp_v2.data;
  18201     } else {
  18202         type = schan_msg.genresp.response.type;
  18203         index = schan_msg.genresp.response.index;
  18204         data = schan_msg.genresp.data;
  18205     }
  18206     if ((nack != 0) || (rv == SOC_E_FAIL)) {
  18207         if (index_ptr) {
  18208             *index_ptr = -1;
  18209         }
  18210         if (type == SCHAN_GEN_RESP_TYPE_NOT_FOUND) {
  18211             rv = SOC_E_NOT_FOUND;
  18212 #if defined(BCM_TRIDENT2_SUPPORT)
  18213             if (soc_feature(unit, soc_feature_shared_hash_ins) &&
  18214                 (mem == L3_ENTRY_IPV4_MULTICASTm || mem == L3_ENTRY_IPV6_UNICASTm)) {
  18215                 /* Check for banks != 'All' to distinguish from normal lookup.
  18216                  * The special handling code always passes unique bank numbers.
  18217                  */
  18218                 if (index_ptr && (banks != SOC_MEM_HASH_BANK_ALL)) {
  18219                     *index_ptr = schan_msg.genresp.response.index;
  18220                 }
  18221             }
  18222 #endif /* BCM_TRIDENT2_SUPPORT */
  18223         } else {
  18224             if (SOC_SER_CORRECTION_SUPPORT(unit)) {
  18225                 uint32 *cache;
  18226                 uint8 *vmap;
  18227                 LOG_VERBOSE(BSL_LS_SOC_SER,(BSL_META_U(unit,
  18228                     "soc_mem_generic_lookup: rv=%d, nack=%d, type=%d, index=%d\n"),
  18229                     rv, nack, type, index));
  18230                 if (err_info == SCHAN_GEN_RESP_ERR_INFO_ERROR_IN_LP_TABLE) {
  18231                     LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  18232                         "soc_mem_generic_lookup: Encountered error on LP table "
  18233                         "for memory %s, banks[0x%0x], err_rsp_index[%d] !!\n"),
  18234                         SOC_MEM_NAME(unit, mem), banks, index));
  18235 #if defined(BCM_TOMAHAWK_SUPPORT)
  18236                     if (SOC_IS_TOMAHAWKX(unit)) {
  18237                         if (SOC_FAILURE(soc_th_lp_to_fv_index_remap(unit, mem, &index))) {
  18238                             MEM_UNLOCK(unit, mem);
  18239                             return SOC_E_INTERNAL; 
  18240                         }
  18241                     }
  18242 #endif
  18243                 }
  18244                 cache = SOC_MEM_STATE(unit, mem).cache[copyno];
  18245                 vmap = SOC_MEM_STATE(unit, mem).vmap[copyno];
  18246                 if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)) {
  18247                     int index0 = index, index1 = -1;
  18248                     if (SOC_IS_TRIDENT(unit) || SOC_IS_TRIUMPH2(unit)
  18249                          || SOC_IS_KATANA2(unit)) {
  18250                         
  18251                         index0 = schan_msg.dwords[2] & 0xffff;
  18252                         index1 = schan_msg.dwords[2] >> 16;
  18253                     }
  18254                     rv = _soc_mem_cache_lookup(unit, mem, copyno, banks, key,
  18255                                                result, index0, index1,
  18256                                                index_ptr, cache, vmap);
  18257                 }
  18258             } else {
  18259                 rv = SOC_E_FAIL;
  18260             }
  18261         }
  18262     } else {
  18263         if (result != NULL) {
  18264             sal_memcpy(result, data, entry_dw * sizeof(uint32));
  18265         }
  18266 #ifdef BCM_TRIUMPH_SUPPORT
  18267         if (soc_feature(unit, soc_feature_etu_support) &&
  18268             mem == EXT_L2_ENTRY_2m) {
  18269             soc_mem_t ext_mem;
  18270             int ext_index;
  18271 
  18272             rv1 = soc_tcam_raw_index_to_mem_index(unit, index,
  18273                                 &ext_mem, &ext_index);
  18274             if (SOC_FAILURE(rv1)) {
  18275 #if defined(BCM_TRIUMPH3_SUPPORT)
  18276                 if (soc_feature(unit, soc_feature_esm_correction) &&
  18277                       ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  18278                      (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  18279                     SOC_ESM_UNLOCK(unit);
  18280                 }
  18281 #endif
  18282                 MEM_UNLOCK(unit, mem);
  18283                 return rv1;
  18284             }
  18285             if (mem != ext_mem) {
  18286 #if defined(BCM_TRIUMPH3_SUPPORT)
  18287                 if (soc_feature(unit, soc_feature_esm_correction) &&
  18288                       ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  18289                      (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  18290                     SOC_ESM_UNLOCK(unit);
  18291                 }
  18292 #endif
  18293                 MEM_UNLOCK(unit, mem);
  18294                 return SOC_E_INTERNAL;
  18295             }
  18296             index = ext_index;
  18297         }
  18298 #endif /* BCM_TRIUMPH_SUPPORT */
  18299         if (index_ptr != NULL) {
  18300             *index_ptr = index;
  18301         }
  18302         index_valid = (index >= 0 &&
  18303                            index <= soc_mem_index_max(unit, mem));
  18304         if (!index_valid) {
  18305 #if defined(BCM_HURRICANE3_SUPPORT)
  18306             if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) &&
  18307                 (mem == L2Xm)) {
  18308                 if (index & SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit)) {
  18309                     /* Check whether the entry is located at L2_OVERFLOW_ENTRY */
  18310                     if ((index & ~SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit)) <=
  18311                         soc_mem_index_max(unit, L2_ENTRY_OVERFLOWm)) {
  18312                         rv = SOC_E_NONE;
  18313                     }
  18314                 }
  18315             } else 
  18316 #endif /* BCM_HURRICANE3_SUPPORT */
  18317             {
  18318                 LOG_ERROR(BSL_LS_SOC_SOCMEM,
  18319                       (BSL_META_U(unit,
  18320                                   "soc_mem_generic_lookup: "
  18321                                   "invalid index %d for memory %s\n"),
  18322                        index, SOC_MEM_NAME(unit, mem)));
  18323                 rv = SOC_E_INTERNAL;
  18324             }
  18325         }
  18326     }
  18327     if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) {
  18328         LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  18329                             "Lookup table[%s]: banks=%d"), SOC_MEM_NAME(unit, mem),
  18330                  banks));
  18331         if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) {
  18332             soc_mem_entry_dump(unit, mem, data, BSL_VERBOSE|BSL_LS_SOC_COMMON);
  18333         }
  18334         if (SOC_FAILURE(rv)) {
  18335             if (type == SCHAN_GEN_RESP_TYPE_NOT_FOUND) {
  18336                 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  18337                                     " Not found\n")));
  18338             } else {
  18339                 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  18340                                     " Fail\n")));
  18341             }
  18342         } else {
  18343             LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  18344                                 " (index=%d)\n"), index));
  18345         }
  18346     }
  18347 #if defined(BCM_TRIUMPH3_SUPPORT)
  18348     if (soc_feature(unit, soc_feature_esm_correction) &&
  18349         ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  18350          (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  18351         SOC_ESM_UNLOCK(unit);
  18352     }
  18353 #endif
  18354     MEM_UNLOCK(unit, mem);
  18355     return rv;
  18356 }
  18357 
  18358 #ifdef ALPM_ENABLE
  18359 #define _SOC_ALPM_MEM_OP_RETRY_TO          1000000
  18360 #define _SOC_ALPM_MEM_OP_RETRY_COUNT       5
  18361 
  18362 STATIC int
  18363 _soc_mem_alpm_ser_correction(int unit, soc_mem_t mem, int blk,
  18364                              int addr, int copyno, int index,
  18365                              int bkt_ptr)
  18366 {
  18367     int rv, pipe;
  18368     int bank = 0, ent = 0;
  18369     int acc_type = 0;
  18370     uint32 entry[SOC_MAX_MEM_WORDS];
  18371     int ent_cnt = 1, bank_cnt = 1;
  18372 #if defined (BCM_TRIDENT2_SUPPORT)
  18373     int len = 0;
  18374     uint32 value = 0;
  18375     _soc_ser_sram_info_t sram_info;
  18376 
  18377     _soc_sram_info_init(unit, &sram_info);
  18378 #endif
  18379 
  18380     if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) {
  18381 #ifdef BCM_TOMAHAWK3_SUPPORT
  18382         if (SOC_IS_TOMAHAWK3(unit)) {
  18383             mem = L3_DEFIP_ALPM_LEVEL3_ECCm;
  18384         } else
  18385 #endif
  18386         {
  18387         mem = L3_DEFIP_ALPM_ECCm;
  18388         }
  18389         bkt_ptr = -1;
  18390     } else if (SOC_IS_TRIDENT2PLUS(unit)) {
  18391         mem = L3_DEFIP_ALPM_ECCm;
  18392     } else if (SOC_IS_APACHE(unit)) {
  18393         mem = L3_DEFIP_ALPM_ECCm;
  18394         bkt_ptr = -1;
  18395     }
  18396 
  18397 #if defined(BCM_TOMAHAWK_SUPPORT)
  18398     if (SOC_IS_TOMAHAWK(unit) || SOC_IS_TOMAHAWKPLUS(unit) ||
  18399         SOC_IS_TOMAHAWK2(unit)) {
  18400         SOC_IF_ERROR_RETURN
  18401             (soc_tomahawk_mem_sram_info_get(unit, mem, index, &sram_info));
  18402     } else
  18403 #endif /* BCM_TOMAHAWK_SUPPORT */
  18404 #if defined (BCM_TRIDENT2_SUPPORT)
  18405     if (SOC_IS_TRIDENT2(unit) || SOC_IS_TRIDENT2PLUS(unit)) {
  18406         SOC_IF_ERROR_RETURN
  18407             (_soc_trident2_mem_sram_info_get(unit, mem, index, &sram_info));
  18408     }
  18409 #endif /* BCM_TRIDENT2_SUPPORT */
  18410 
  18411     if (bkt_ptr != -1) {
  18412         /* Need traverse to find actual parity error index*/
  18413         switch (mem) {
  18414         case L3_DEFIP_ALPM_ECCm:
  18415         case L3_DEFIP_ALPM_IPV4_1m:
  18416         case L3_DEFIP_ALPM_IPV6_64m:
  18417             ent_cnt  = 4;
  18418             break;
  18419         case L3_DEFIP_ALPM_IPV6_64_1m:
  18420             ent_cnt  = 3;
  18421             break;
  18422         case L3_DEFIP_ALPM_IPV6_128m:
  18423             ent_cnt  = 2;
  18424             break;
  18425         case L3_DEFIP_ALPM_IPV4m:
  18426         default:
  18427             ent_cnt  = 6;
  18428             break;
  18429         }
  18430         bank_cnt = 4;
  18431     }
  18432 
  18433     for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
  18434         /* determine 1st pipe which has the problem */
  18435         if (NUM_PIPE(unit) == 4 || SOC_IS_TRIDENT3X(unit)) {
  18436             acc_type = (pipe == 0)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_0 :
  18437                        (pipe == 1)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_1 :
  18438                        (pipe == 2)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_2 :
  18439                                     _SOC_MEM_ADDR_ACC_TYPE_PIPE_3;
  18440         } else if (NUM_PIPE(unit) == 2) {
  18441             acc_type = (pipe == 0) ? _SOC_MEM_ADDR_ACC_TYPE_PIPE_X:
  18442                 _SOC_MEM_ADDR_ACC_TYPE_PIPE_Y;
  18443         } else if (NUM_PIPE(unit) == 8) {
  18444             acc_type = (pipe == 0)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_0 :
  18445                        (pipe == 1)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_1 :
  18446                        (pipe == 2)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_2 :
  18447                        (pipe == 3)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_3 :
  18448                        (pipe == 4)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_4 :
  18449                        (pipe == 5)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_5 :
  18450                        (pipe == 6)? _SOC_MEM_ADDR_ACC_TYPE_PIPE_6 :
  18451                                     _SOC_MEM_ADDR_ACC_TYPE_PIPE_7;
  18452         }
  18453 
  18454         for (ent = 0; ent < ent_cnt; ent++) {
  18455             for (bank = 0; bank < bank_cnt; bank ++) {
  18456                 if (bkt_ptr != -1) {
  18457                     index = (ent << 16) | (bkt_ptr << 2) | (bank);
  18458                 }
  18459                 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  18460                           "unit %d: inline ALPM correction LOOP: pipe:%d index %d\n"),
  18461                            unit, pipe, index));
  18462                 /* Only multi-pipe need to confirm which pipe has the parity error */
  18463                 if (NUM_PIPE(unit) > 1) {
  18464                     rv = soc_mem_pipe_select_read(unit, SOC_MEM_NO_FLAGS, mem, copyno,
  18465                                                   acc_type, index, entry);
  18466 
  18467 #if defined (BCM_TRIDENT2_SUPPORT) /* Check XOR bank */
  18468                     if (rv != SOC_E_FAIL &&
  18469                         (SOC_IS_TRIDENT2(unit) || SOC_IS_TRIDENT2PLUS(unit) ||
  18470                          SOC_IS_TOMAHAWK(unit) || SOC_IS_TOMAHAWKPLUS(unit) ||
  18471                          SOC_IS_TOMAHAWK2(unit))) {
  18472                         if (SOC_REG_IS_VALID(unit, sram_info.force_reg)) {
  18473                             LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  18474                                   "unit %d: inline ALPM correction: will read "
  18475                                   "pipe %d, index %d again with "
  18476                                   "forcing XOR generation\n"),
  18477                                   unit, pipe, index));
  18478                             len = soc_reg_field_length(unit, sram_info.force_reg,
  18479                                                        sram_info.force_field);
  18480                             value = (1 << len) - 1;
  18481                             soc_reg_field32_modify(unit, sram_info.force_reg,
  18482                                                    REG_PORT_ANY,
  18483                                                    sram_info.force_field, value);
  18484                             rv = soc_mem_pipe_select_read(unit, SOC_MEM_NO_FLAGS,
  18485                                                           mem, copyno,
  18486                                                           acc_type, index, entry);
  18487                             soc_reg_field32_modify(unit, sram_info.force_reg,
  18488                                                    REG_PORT_ANY,
  18489                                                    sram_info.force_field, 0);
  18490                         }
  18491                     }
  18492 #endif
  18493                     if (SOC_E_FAIL == rv) {
  18494                         LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  18495                                   "unit %d: inline ALPM correction: will try ser_correction for pipe %d, index %d\n"),
  18496                                   unit, pipe, index));
  18497 
  18498                         /* Once we found the bad pipe on TD2, restore the entire bucket
  18499                          * across 4 banks. This could be done via call soc_ser_sram_correction
  18500                          * 4 times with 4 indexes on 4 banks.
  18501                          */
  18502                         if (SOC_IS_TRIDENT2X(unit)) {
  18503                             for (bank = 0; bank < 4; bank ++) {
  18504                                 index = (index & (~0x3)) | (bank);
  18505                                 rv = soc_ser_sram_correction(unit, pipe, blk, addr, mem, copyno,
  18506                                                              index, NULL);
  18507                             }
  18508                         } else {
  18509                             rv = soc_ser_sram_correction(unit, pipe, blk, addr, mem, copyno,
  18510                                                          index, NULL);
  18511                         }
  18512                         if (SOC_FAILURE(rv)) {
  18513                             LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  18514                                 "unit %d: inline ALPM correction: ser_correction FAILED for pipe %d, index %d\n"),
  18515                                 unit, pipe, index));
  18516                         } else {
  18517                             LOG_VERBOSE(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  18518                                 "unit %d: inline ALPM correction: ser_correction passed for pipe %d, index %d\n"),
  18519                                 unit, pipe, index));
  18520                         }
  18521                         return rv;
  18522                     } else if (SOC_SUCCESS(rv)) {
  18523                         /*
  18524                         * IPRC_NACK is only set on MEMRD if a 2-bit error is detected.
  18525                         * If a 1-bit error is detected, NACK is not set, and corrected data is returned
  18526                         * So if soc_mem_pipe_select_read returns success, we don't know if there
  18527                         * is 1b error or not, the best choice is to correct all pipes one by one
  18528                         */
  18529                         int pipe_tmp, bank_tmp, index_tmp;
  18530                         index_tmp = index;
  18531                         if (pipe == (NUM_PIPE(unit) - 1)) {
  18532                             LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  18533                                   "unit %d: inline ALPM correction: MEMRD of "
  18534                                   "index %d from all pipes return success,"
  18535                                   "it should be 1-bit error!"
  18536                                   "Correct all pipes for now!\n"),unit, index));
  18537                             /*
  18538                             * Recover all pipes in increasing pipe num order
  18539                             */
  18540                             for (pipe_tmp = 0;
  18541                                  pipe_tmp < NUM_PIPE(unit);
  18542                                  pipe_tmp++) {
  18543                                 if (SOC_IS_TRIDENT2X(unit)) {
  18544                                     for (bank_tmp = 0;
  18545                                          bank_tmp < 4;
  18546                                          bank_tmp ++) {
  18547                                         index_tmp = (index_tmp & (~0x3)) |
  18548                                                      (bank_tmp);
  18549                                         (void)soc_ser_sram_correction(unit,
  18550                                                                       pipe_tmp,
  18551                                                                       blk, addr,
  18552                                                                       mem,
  18553                                                                       copyno,
  18554                                                                       index_tmp,
  18555                                                                       NULL);
  18556                                     }
  18557                                 } else if (SOC_IS_TOMAHAWKX(unit) ||
  18558                                            SOC_IS_TRIDENT3X(unit)) {
  18559                                     (void)soc_ser_sram_correction(unit,
  18560                                                                   pipe_tmp,
  18561                                                                   blk, addr,
  18562                                                                   mem,
  18563                                                                   copyno,
  18564                                                                   index_tmp,
  18565                                                                   NULL);
  18566                                 }
  18567                              }
  18568                         }
  18569                     }
  18570                 }else {
  18571                     rv = soc_ser_sram_correction(unit, pipe, blk, addr, mem, copyno,
  18572                                                  index, NULL);
  18573                     if (SOC_FAILURE(rv)) {
  18574                         LOG_ERROR(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  18575                             "unit %d: inline ALPM correction: ser_correction FAILED for pipe %d, index %d\n"),
  18576                             unit, pipe, index));
  18577                     } else {
  18578                         LOG_VERBOSE(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  18579                             "unit %d: inline ALPM correction: ser_correction passed for pipe %d, index %d\n"),
  18580                             unit, pipe, index));
  18581                     }
  18582                     return rv;
  18583                 }
  18584             }
  18585         }
  18586     }
  18587     /* Means we could not find any pipe which had problem
  18588      * Should not happen, just let caller retry operation */
  18589     LOG_WARN(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  18590         "unit %d: inline ALPM correction: ser_correction illegal pipe %d for index %d !! \n"),
  18591         unit, pipe, index));
  18592     return SOC_E_NONE;
  18593 }
  18594 
  18595 /*
  18596  * Function:
  18597  *      soc_mem_alpm_lookup
  18598  * Purpose:
  18599  *      Send a lookup message over the S-Channel and receive the response
  18600  *      from ALPM memories. ALPM memories have special needs bcoz the entries
  18601  *      are not hashed.
  18602  * Parameters:
  18603  *      unit - StrataSwitch unit #
  18604  *      banks - Banks
  18605  *              Note: used to create a bitmap for ISM mems. (All banks: -1)
  18606  *      key - entry to look up
  18607  *      result - entry to receive entire found entry
  18608  *      index_ptr (OUT) - If found, receives table index where found
  18609  * Returns:
  18610  *      SOC_E_INTERNAL if retries exceeded or other internal error
  18611  *      SOC_E_NOT_FOUND if the entry is not found.
  18612  *      SOC_E_NONE (0) on success (entry found):
  18613  */
  18614 
  18615 int
  18616 soc_mem_alpm_lookup(int unit, soc_mem_t mem, int bucket_index,
  18617                     int copyno, uint32 banks_disable,
  18618                     void *key, void *result, int *index_ptr)
  18619 {
  18620     schan_msg_t schan_msg;
  18621     uint8       at;
  18622     uint32      *data;
  18623     int         rv, entry_dw, allow_intr=0;
  18624     int         type, index;
  18625     int         _soc_alpm_lookup_retry = 0;
  18626     int         src_blk, dst_blk, acc_type, data_byte_len;
  18627     int         opcode, nack;
  18628     uint32      bank_ignore_mask;
  18629     int         bkt_ptr = -1;
  18630 
  18631     assert(SOC_MEM_IS_VALID(unit, mem));
  18632     assert(soc_attached(unit));
  18633 
  18634     if (SAL_BOOT_SIMULATION) {
  18635 #if defined(ALPM_ENABLE)
  18636 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT)
  18637         if (index_ptr) {
  18638             *index_ptr = bucket_index << (soc_alpm_cmn_banks_get(unit) / 2);
  18639         }
  18640 #endif
  18641 #endif
  18642         return SOC_E_NOT_FOUND;
  18643     }
  18644 
  18645     /* Only applicable to ALPM memories */
  18646     if ((mem != L3_DEFIP_ALPM_IPV6_128m) &&
  18647         (mem != L3_DEFIP_ALPM_IPV6_64m) &&
  18648         (mem != L3_DEFIP_ALPM_IPV6_64_1m) &&
  18649         (mem != L3_DEFIP_ALPM_IPV4m) &&
  18650         (mem != L3_DEFIP_ALPM_IPV4_1m)) {
  18651         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  18652                   (BSL_META_U(unit,
  18653                               "soc_mem_alpm_lookup: not supported non-ALPM memories %s\n"),
  18654                    SOC_MEM_NAME(unit, mem)));
  18655         return SOC_E_PARAM;
  18656     }
  18657 
  18658     if (copyno == MEM_BLOCK_ANY) {
  18659         copyno = SOC_MEM_BLOCK_ANY(unit, mem);
  18660     }
  18661     if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) {
  18662         LOG_WARN(BSL_LS_SOC_SOCMEM,
  18663                  (BSL_META_U(unit,
  18664                              "soc_mem_alpm_lookup: invalid block %d for memory %s\n"),
  18665                   copyno, SOC_MEM_NAME(unit, mem)));
  18666         return SOC_E_PARAM;
  18667     }
  18668 
  18669     entry_dw = soc_mem_entry_words(unit, mem);
  18670 
  18671     SOC_CONTROL_LOCK(unit);
  18672     SHR_BITSET(&(SOC_CONTROL(unit)->alpm_mem_ops), _SOC_ALPM_LOOKUP);
  18673     SOC_CONTROL_UNLOCK(unit);
  18674 _retry:
  18675     schan_msg_clear(&schan_msg);
  18676     acc_type = SOC_MEM_ACC_TYPE(unit, mem);
  18677     src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit));
  18678     dst_blk = SOC_BLOCK2SCH(unit, copyno);
  18679 #ifdef BCM_ISM_SUPPORT
  18680     if (soc_feature(unit, soc_feature_ism_memory)) {
  18681         /* don't set bank id in cos */
  18682         bank_ignore_mask = 0;
  18683     } else
  18684 #endif /* BCM_ISM_SUPPORT */
  18685     {
  18686         bank_ignore_mask = banks_disable & 0x3;
  18687     }
  18688     data_byte_len = entry_dw * 4;
  18689 
  18690     /* ALPM entries are not hashed */
  18691     schan_msg.gencmd.address = soc_mem_addr_get(unit, mem, 0, copyno, 0, &at);
  18692     /* Address contains bank disable, and bucket pointer */
  18693     /* Bucket index and bank disable
  18694      * addr[TD2: 13:0,  TH: 12:0,  TH2: 13:0]   - bucket
  18695      * addr[TD2: 17:14, TH: 16:13, TH2: 17:14]  - bank disable[3:0]
  18696      */
  18697 #if defined(BCM_TOMAHAWK_SUPPORT)
  18698     if (SOC_IS_TOMAHAWK(unit)) {
  18699         schan_msg.gencmd.address &= ~(0x0001ffff);
  18700         schan_msg.gencmd.address |=
  18701             (((banks_disable & 0xf) << 13) | (bucket_index & ALPM_CTRL(unit).bkt_mask));
  18702     } else if (SOC_IS_TRIDENT3X(unit)) {
  18703         /* TD3 only has 4 bits for bank disable bitmap */
  18704         schan_msg.gencmd.address &= ~(0x0001ffff);
  18705         schan_msg.gencmd.address |=
  18706             (((banks_disable & 0xf) << 13) | (bucket_index & ALPM_CTRL(unit).bkt_mask));
  18707     } else
  18708 #endif /* BCM_TOMAHAWK_SUPPORT */
  18709     {
  18710         schan_msg.gencmd.address &= ~(0x0003ffff);
  18711         schan_msg.gencmd.address |= 
  18712             (((banks_disable & 0xf) << 14) | (bucket_index & SOC_TD2_ALPM_BKT_MASK));
  18713     }
  18714 
  18715     soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_LOOKUP_CMD_MSG,
  18716                              dst_blk, src_blk, acc_type, data_byte_len, 0,
  18717                              bank_ignore_mask);
  18718 
  18719     /* Fill in entry data */
  18720     sal_memcpy(schan_msg.gencmd.data, key, entry_dw * 4);
  18721 
  18722     if (SOC_IS_SAND(unit)) {
  18723         allow_intr = 1;
  18724     }
  18725 
  18726     /*
  18727      * Execute S-Channel "lookup insert" command packet consisting of
  18728      * (header word + address word + entry_dw), and read back
  18729      * (header word + response word + entry_dw) data words.
  18730      */
  18731     rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr);
  18732 
  18733     /* Check result */
  18734     soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL,
  18735                                 NULL, NULL, &nack);
  18736     if (opcode != TABLE_LOOKUP_DONE_MSG) {
  18737         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  18738                   (BSL_META_U(unit,
  18739                               "soc_mem_generic_lookup: "
  18740                               "invalid S-Channel reply, expected TABLE_LOOKUP_DONE_MSG:\n")));
  18741         soc_schan_dump(unit, &schan_msg, entry_dw + 2);
  18742         return SOC_E_INTERNAL;
  18743     }
  18744 
  18745     type = schan_msg.genresp_v2.response.type;
  18746     index = schan_msg.genresp_v2.response.index;
  18747     data = schan_msg.genresp_v2.data;
  18748 
  18749     if ((nack != 0) || (rv == SOC_E_FAIL)) {
  18750         if (index_ptr) {
  18751             *index_ptr = -1;
  18752         }
  18753         if (type == SCHAN_GEN_RESP_TYPE_NOT_FOUND) {
  18754             rv = SOC_E_NOT_FOUND;
  18755         } else {
  18756             LOG_WARN(BSL_LS_SOC_SOCMEM,
  18757                      (BSL_META_U(unit,
  18758                                  "unit %d: ALPM lookup operation[%s] encountered "
  18759                                  "parity error !! Resp_type %d Resp_index %d\n"),
  18760                                  unit, SOC_MEM_NAME(unit, mem), type, index));
  18761             _soc_alpm_lookup_retry++;
  18762             if (type == SCHAN_GEN_RESP_TYPE_FOUND) {
  18763                 bkt_ptr = bucket_index;
  18764             }
  18765             if (SOC_CONTROL(unit)->alpm_lookup_retry) {
  18766                 (void)_soc_mem_alpm_ser_correction(unit,
  18767                                                    mem,
  18768                                                    schan_msg.gencmd.header.v2.dst_blk,
  18769                                                    schan_msg.gencmd.address,
  18770                                                    copyno, index,
  18771                                                    bkt_ptr);
  18772                 
  18773 
  18774                 if (_soc_alpm_lookup_retry < _SOC_ALPM_MEM_OP_RETRY_COUNT) {
  18775                     if (sal_sem_take(SOC_CONTROL(unit)->alpm_lookup_retry,
  18776                                      _SOC_ALPM_MEM_OP_RETRY_TO) < 0) {
  18777                         LOG_WARN(BSL_LS_SOC_SOCMEM,
  18778                                  (BSL_META_U(unit,
  18779                                              "unit %d: Retry ALPM lookup operation..\n"), unit));
  18780                         goto _retry;
  18781                     } else {
  18782                         LOG_WARN(BSL_LS_SOC_SOCMEM,
  18783                                  (BSL_META_U(unit,
  18784                                              "unit %d: Retry ALPM lookup operation..\n"), unit));
  18785                         goto _retry;
  18786                     }
  18787                 } else {
  18788                     LOG_ERROR(BSL_LS_SOC_SOCMEM,
  18789                               (BSL_META_U(unit,
  18790                                           "unit %d: Aborting ALPM lookup operation "
  18791                                           "due to un-correctable error !!\n"), unit));
  18792                     rv = SOC_E_INTERNAL;
  18793                 }
  18794             } else {
  18795                 rv = SOC_E_INTERNAL;
  18796             }
  18797         }
  18798     } else {
  18799         if (result != NULL) {
  18800             sal_memcpy(result, data, entry_dw * sizeof(uint32));
  18801         }
  18802         if (index_ptr != NULL) {
  18803             *index_ptr = index;
  18804         }
  18805     }
  18806     SOC_CONTROL_LOCK(unit);
  18807     SHR_BITCLR(&(SOC_CONTROL(unit)->alpm_mem_ops), _SOC_ALPM_LOOKUP);
  18808     SOC_CONTROL_UNLOCK(unit);
  18809 
  18810     if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) {
  18811         LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  18812                             "Lookup table[%s]: banks=%d"), SOC_MEM_NAME(unit, mem),
  18813                  banks_disable));
  18814         if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) {
  18815             soc_mem_entry_dump(unit, mem, data, BSL_VERBOSE|BSL_LS_SOC_COMMON);
  18816         }
  18817         if (SOC_FAILURE(rv)) {
  18818             if (type == SCHAN_GEN_RESP_TYPE_NOT_FOUND) {
  18819                 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  18820                                     " Not found\n")));
  18821             } else {
  18822                 LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  18823                                     " Fail\n")));
  18824             }
  18825         } else {
  18826             LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  18827                                 " (index=%d)\n"), index));
  18828         }
  18829     }
  18830 
  18831     return rv;
  18832 }
  18833 
  18834 /*
  18835  * Function:
  18836  *      soc_mem_alpm_insert
  18837  * Purpose:
  18838  *      Insert an entry into ALPM memory.
  18839  * Parameters:
  18840  *      unit - StrataSwitch unit #
  18841  *      banks - For dual hashing, which halves are selected (inverted)
  18842  *              Note: used to create a bitmap for ISM mems. (All banks: -1)
  18843  *      entry - entry to insert
  18844  *      old_entry - old entry if existing entry was replaced
  18845  * Returns:
  18846  *      SOC_E_NONE - success
  18847  *      SOC_E_EXISTS - existing entry was replaced
  18848  *      SOC_E_FULL - full
  18849  *      SOC_E_BUSY - modfifo full
  18850  * Notes:
  18851  *      Uses hardware insertion; sends an INSERT message over the
  18852  *      S-Channel.
  18853  */
  18854 
  18855 int
  18856 soc_mem_alpm_insert(int unit, soc_mem_t mem, int bucket,
  18857                     int copyno, int32 banks_disable,
  18858                     void *entry, void *old_entry, int *index_ptr)
  18859 {
  18860     schan_msg_t schan_msg;
  18861     uint8       at, *vmap;
  18862     uint32      *data, *cache;
  18863     int         rv, entry_dw, index_valid;
  18864     int         type, index, allow_intr=0;
  18865     int         _soc_alpm_insert_retry = 0;
  18866     int         src_blk, dst_blk, acc_type, data_byte_len;
  18867     int         opcode, nack;
  18868     int         type2 = -1, index2 = 0;
  18869     uint32      data2[CMIC_SCHAN_WORDS_ALLOC - 2];
  18870     int         bkt_ptr = -1;
  18871     uint8       _alpm_lock = 0;
  18872 
  18873     SOC_MEM_ALIAS_TO_ORIG(unit,mem);
  18874     assert(SOC_MEM_IS_VALID(unit, mem));
  18875     assert(soc_attached(unit));
  18876 
  18877     if (SAL_BOOT_SIMULATION) {
  18878 #if defined(ALPM_ENABLE)
  18879 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT)
  18880         if (index_ptr) {
  18881             *index_ptr = bucket << (soc_alpm_cmn_banks_get(unit) / 2);
  18882         }
  18883 #endif
  18884 #endif
  18885 
  18886         return SOC_E_NONE;
  18887     }
  18888 
  18889     /* Only applicable to ALPM memories */
  18890     if ((mem != L3_DEFIP_ALPM_IPV6_128m) &&
  18891         (mem != L3_DEFIP_ALPM_IPV6_64m) &&
  18892         (mem != L3_DEFIP_ALPM_IPV6_64_1m) &&
  18893         (mem != L3_DEFIP_ALPM_IPV4m) &&
  18894         (mem != L3_DEFIP_ALPM_IPV4_1m)) {
  18895         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  18896                   (BSL_META_U(unit,
  18897                               "soc_mem_alpm_insert: not supported non-ALPM memories %s\n"),
  18898                    SOC_MEM_NAME(unit, mem)));
  18899         return SOC_E_PARAM;
  18900     }
  18901 
  18902     if (copyno == MEM_BLOCK_ANY) {
  18903         copyno = SOC_MEM_BLOCK_ANY(unit, mem);
  18904     }
  18905     if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) {
  18906         LOG_WARN(BSL_LS_SOC_SOCMEM,
  18907                  (BSL_META_U(unit,
  18908                              "soc_mem_alpm_insert: invalid block %d for memory %s\n"),
  18909                   copyno, SOC_MEM_NAME(unit, mem)));
  18910         return SOC_E_PARAM;
  18911     }
  18912 
  18913     if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) {
  18914         LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  18915                             "Insert table[%s]: banks=%d"), SOC_MEM_NAME(unit, mem),
  18916                  banks_disable));
  18917         if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) {
  18918             soc_mem_entry_dump(unit, mem, entry, BSL_VERBOSE|BSL_LS_SOC_COMMON);
  18919         }
  18920         LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  18921                             "\n")));
  18922     }
  18923 
  18924     entry_dw = soc_mem_entry_words(unit, mem);
  18925 
  18926     SOC_CONTROL_LOCK(unit);
  18927     SHR_BITSET(&(SOC_CONTROL(unit)->alpm_mem_ops), _SOC_ALPM_INSERT);
  18928     SOC_CONTROL_UNLOCK(unit);
  18929 
  18930 _retry:
  18931     schan_msg_clear(&schan_msg);
  18932     acc_type = SOC_MEM_ACC_TYPE(unit, mem);
  18933     src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit));
  18934     dst_blk = SOC_BLOCK2SCH(unit, copyno);
  18935     data_byte_len = entry_dw * 4;
  18936 
  18937     schan_msg.gencmd.address = soc_mem_addr_get(unit, mem, 0, copyno, 0, &at);
  18938     /* Address contains bank disable, and bucket pointer */
  18939     /* Bucket index and bank disable
  18940      * addr[TD2: 13:0,  TH: 12:0,  TH2: 13:0]   - bucket
  18941      * addr[TD2: 17:14, TH: 16:13, TH2: 17:14]  - bank disable[3:0]
  18942      */
  18943 #if defined(BCM_TOMAHAWK_SUPPORT)
  18944     if (SOC_IS_TOMAHAWK(unit)) {
  18945         schan_msg.gencmd.address &= ~(0x0001ffff);
  18946         schan_msg.gencmd.address |=
  18947             (((banks_disable & 0xf) << 13) | (bucket & ALPM_CTRL(unit).bkt_mask));
  18948     } else if (SOC_IS_TRIDENT3X(unit)) {
  18949         /* TD3 only has 4 bits for bank disable bitmap */
  18950         schan_msg.gencmd.address &= ~(0x0001ffff);
  18951         schan_msg.gencmd.address |=
  18952             (((banks_disable & 0xf) << 13) | (bucket & ALPM_CTRL(unit).bkt_mask));
  18953     } else
  18954 #endif
  18955     {
  18956         schan_msg.gencmd.address &= ~(0x0003ffff);
  18957         schan_msg.gencmd.address |= 
  18958             (((banks_disable & 0xf) << 14) | (bucket & SOC_TD2_ALPM_BKT_MASK));
  18959     }
  18960 
  18961     soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_INSERT_CMD_MSG,
  18962                              dst_blk, src_blk, acc_type, data_byte_len, 0, 0);
  18963 
  18964     /* Fill in packet data */
  18965     sal_memcpy(schan_msg.gencmd.data, entry, entry_dw * 4);
  18966 
  18967     /* Only lock one time */
  18968     if (0 == _alpm_lock) {
  18969         SOC_ALPM_LPM_LOCK(unit);
  18970         _alpm_lock = 1;
  18971     }
  18972 
  18973     /*
  18974      * Execute S-Channel "table insert" command packet consisting of
  18975      * (header word + address word + entry_dw), and read back
  18976      * (header word + response word + entry_dw) data words.
  18977      */
  18978     rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr);
  18979 
  18980     soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL,
  18981                                 NULL, NULL, &nack);
  18982     if (opcode != TABLE_INSERT_DONE_MSG) {
  18983         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  18984                   (BSL_META_U(unit,
  18985                               "soc_mem_alpm_insert: "
  18986                               "invalid S-Channel reply, expected TABLE_INSERT_DONE_MSG:\n")));
  18987         soc_schan_dump(unit, &schan_msg, 1);
  18988         SOC_ALPM_LPM_UNLOCK(unit);
  18989         return SOC_E_INTERNAL;
  18990     }
  18991     type = schan_msg.genresp_v2.response.type;
  18992     index = schan_msg.genresp_v2.response.index;
  18993     data = schan_msg.genresp_v2.data;
  18994 
  18995     LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
  18996                (BSL_META_U(unit,
  18997                           "SBUS INSERT: nack:%d rv:%d type:%d index:%d \n "),
  18998                            nack, rv, type, index));
  18999 
  19000     if (_soc_alpm_insert_retry && (nack == 0 && rv == SOC_E_NONE)) {
  19001         if (type == SCHAN_GEN_RESP_TYPE_REPLACED) {
  19002             LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
  19003                       (BSL_META_U(unit,
  19004                       "SBUS INSERT failed, replaced at retry %d \n"),
  19005                       _soc_alpm_insert_retry));
  19006             /* After SER actions, the entry in bad pipe could be
  19007              * inserted/replaced, we too consider that as success.
  19008              */
  19009             if (type2 == SCHAN_GEN_RESP_TYPE_INSERTED ||
  19010                 type2 == SCHAN_GEN_RESP_TYPE_REPLACED) {
  19011                 /* recover the values needed for success ops */
  19012                 type  = type2;
  19013                 index = index2;
  19014                 if (type == SCHAN_GEN_RESP_TYPE_REPLACED) {
  19015                     data  = data2;
  19016                 }
  19017             } else {
  19018                 /* SBUS fails at the first time (type is error).
  19019                  * We still get index, but lose info of being inserted/replaced
  19020                  * and old entry if it's replaced.
  19021                  */
  19022                 LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
  19023                            (BSL_META_U(unit,
  19024                            "SBUS INSERT fails 1st with error. The old entry is lost \n ")));
  19025             }
  19026         }
  19027     }
  19028     if ((nack != 0) || (rv == SOC_E_FAIL)) {
  19029         if (index_ptr) {
  19030             *index_ptr = -1;
  19031         }
  19032         if (type == SCHAN_GEN_RESP_TYPE_FULL) {
  19033             LOG_INFO(BSL_LS_SOC_SOCMEM,
  19034                      (BSL_META_U(unit,
  19035                                  "Insert table[%s]: hash bucket full\n"),
  19036                       SOC_MEM_NAME(unit, mem)));
  19037             rv = SOC_E_FULL;
  19038         } else if (type == SCHAN_GEN_RESP_TYPE_ERROR ||
  19039                    type == SCHAN_GEN_RESP_TYPE_INSERTED ||
  19040                    type == SCHAN_GEN_RESP_TYPE_REPLACED) {
  19041             LOG_WARN(BSL_LS_SOC_SOCMEM,
  19042                      (BSL_META_U(unit,
  19043                                  "unit %d: ALPM insert operation[%s] encountered "
  19044                                  "parity error !! Resp_type %d Resp_index %d\n"),
  19045                                  unit, SOC_MEM_NAME(unit, mem), type, index));
  19046             _soc_alpm_insert_retry++;
  19047             if (type == SCHAN_GEN_RESP_TYPE_INSERTED ||
  19048                 type == SCHAN_GEN_RESP_TYPE_REPLACED) {
  19049                 type2  = type;
  19050                 index2 = index;
  19051                 if (type == SCHAN_GEN_RESP_TYPE_REPLACED) {
  19052                     sal_memcpy(data2, schan_msg.genresp_v2.data, entry_dw * 4);
  19053                 }
  19054                 bkt_ptr = bucket;
  19055             }
  19056 
  19057             if (SOC_CONTROL(unit)->alpm_insert_retry) {
  19058                 (void)_soc_mem_alpm_ser_correction(unit,
  19059                                                    mem,
  19060                                                    schan_msg.gencmd.header.v2.dst_blk,
  19061                                                    schan_msg.gencmd.address,
  19062                                                    copyno, index,
  19063                                                    bkt_ptr);
  19064                 if (_soc_alpm_insert_retry < _SOC_ALPM_MEM_OP_RETRY_COUNT) {
  19065                     
  19066                     if (sal_sem_take(SOC_CONTROL(unit)->alpm_insert_retry,
  19067                                  _SOC_ALPM_MEM_OP_RETRY_TO) < 0) {
  19068                         LOG_WARN(BSL_LS_SOC_SOCMEM,
  19069                                  (BSL_META_U(unit,
  19070                                              "unit %d: Retry ALPM insert operation..\n"), unit));
  19071                         goto _retry;
  19072                     } else {
  19073                         LOG_WARN(BSL_LS_SOC_SOCMEM,
  19074                                  (BSL_META_U(unit,
  19075                                              "unit %d: Retry ALPM insert operation..\n"), unit));
  19076                         goto _retry;
  19077                     }
  19078                 } else {
  19079                     LOG_ERROR(BSL_LS_SOC_SOCMEM,
  19080                               (BSL_META_U(unit,
  19081                                           "unit %d: Aborting ALPM insert operation "
  19082                                           "due to un-correctable error !!\n"), unit));
  19083                     rv = SOC_E_INTERNAL;
  19084                 }
  19085             } else {
  19086                 rv = SOC_E_INTERNAL;
  19087             }
  19088         } else {
  19089             rv = SOC_E_FAIL;
  19090         }
  19091     } else {
  19092         if (index_ptr != NULL) {
  19093             *index_ptr = index;
  19094         }
  19095         /*
  19096         First insertion will write H/W data even if SER error exists, then second insertion will
  19097         return success with SCHAN_GEN_RESP_TYPE_REPLACED response type.
  19098         We should treat this case as success.
  19099         */
  19100         if (type == SCHAN_GEN_RESP_TYPE_REPLACED && !_soc_alpm_insert_retry) {
  19101             if (old_entry != NULL) {
  19102                 sal_memcpy(old_entry, data, entry_dw * sizeof(uint32));
  19103             }
  19104             rv = SOC_E_EXISTS;
  19105         }
  19106         /* Update cache if active */
  19107         cache = SOC_MEM_STATE(unit, mem).cache[copyno];
  19108         vmap = SOC_MEM_STATE(unit, mem).vmap[copyno];
  19109         index_valid = (index >= 0 &&
  19110                        index <= soc_mem_index_max(unit, mem));
  19111         if (index_valid && cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)) {
  19112             sal_memcpy(cache + index * entry_dw, entry, entry_dw * 4);
  19113             CACHE_VMAP_SET(vmap, index);
  19114         }
  19115     }
  19116     SOC_ALPM_LPM_UNLOCK(unit);
  19117 
  19118     if (!SOC_FAILURE(rv) || (rv == SOC_E_EXISTS)) {
  19119         if (SOC_IS_TRIDENT2(unit) || SOC_IS_TRIDENT2PLUS(unit)) {
  19120             _soc_trident2_alpm_bkt_view_set(unit, index, mem);
  19121         }
  19122 #if defined(ALPM_ENABLE)
  19123 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT)
  19124         else {
  19125             soc_alpm_cmn_bkt_view_set(unit, index, mem);
  19126         }
  19127 #endif
  19128 #endif
  19129     }
  19130     SOC_CONTROL_LOCK(unit);
  19131     SHR_BITCLR(&(SOC_CONTROL(unit)->alpm_mem_ops), _SOC_ALPM_INSERT);
  19132     SOC_CONTROL_UNLOCK(unit);
  19133 
  19134     return rv;
  19135 }
  19136 
  19137 /*
  19138  * Function:
  19139  *      soc_mem_alpm_delete
  19140  * Purpose:
  19141  *      Delete an ALPM entry
  19142  * Parameters:
  19143  *      unit - StrataSwitch unit #
  19144  *      banks - For dual hashing, which halves are selected (inverted)
  19145  *              Note: used to create a bitmap for ISM mems. (All banks: -1)
  19146  *      entry - entry to delete
  19147  *      old_entry - old entry if entry was found and deleted
  19148  * Returns:
  19149  *      SOC_E_NONE - success
  19150  *      SOC_E_NOT_FOUND - full
  19151  *      SOC_E_BUSY - modfifo full
  19152  * Notes:
  19153  *      Uses hardware deletion; sends an DELETE message over the
  19154  *      S-Channel.
  19155  */
  19156 
  19157 int
  19158 soc_mem_alpm_delete(int unit, soc_mem_t mem, int bucket,
  19159                     int copyno, int32 banks_disable,
  19160                     void *entry, void *old_entry, int *index_ptr)
  19161 {
  19162     schan_msg_t schan_msg;
  19163     uint8       at, *vmap;
  19164     uint32      *data, *cache;
  19165     int         rv, entry_dw, index_valid;
  19166     int         type, index, allow_intr=0;
  19167     int         _soc_alpm_delete_retry = 0;
  19168     void        *null_entry = soc_mem_entry_null(unit, mem);
  19169     int         src_blk, dst_blk, acc_type, data_byte_len;
  19170     int         opcode, nack;
  19171     uint32      bank_ignore_mask;
  19172     int         type2 = -1, index2 = 0;
  19173     uint32      data2[CMIC_SCHAN_WORDS_ALLOC - 2];
  19174     int         bkt_ptr = -1;
  19175     uint8       _alpm_lock = 0;
  19176 
  19177     SOC_MEM_ALIAS_TO_ORIG(unit,mem);
  19178     assert(SOC_MEM_IS_VALID(unit, mem));
  19179     assert(soc_attached(unit));
  19180 
  19181     if (SAL_BOOT_SIMULATION) {
  19182 #if defined(ALPM_ENABLE)
  19183 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT)
  19184         if (index_ptr) {
  19185             *index_ptr = bucket << (soc_alpm_cmn_banks_get(unit) / 2);
  19186         }
  19187 #endif
  19188 #endif
  19189         return SOC_E_NONE;
  19190     }
  19191 
  19192     /* Only applicable to ALPM memories */
  19193     if ((mem != L3_DEFIP_ALPM_IPV6_128m) &&
  19194         (mem != L3_DEFIP_ALPM_IPV6_64m) &&
  19195         (mem != L3_DEFIP_ALPM_IPV6_64_1m) &&
  19196         (mem != L3_DEFIP_ALPM_IPV4m) &&
  19197         (mem != L3_DEFIP_ALPM_IPV4_1m)) {
  19198         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  19199                   (BSL_META_U(unit,
  19200                               "soc_mem_alpm_delete: not supported non-ALPM memories %s\n"),
  19201                    SOC_MEM_NAME(unit, mem)));
  19202         return SOC_E_PARAM;
  19203     }
  19204 
  19205     if (copyno == MEM_BLOCK_ANY) {
  19206         copyno = SOC_MEM_BLOCK_ANY(unit, mem);
  19207     }
  19208     if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) {
  19209         LOG_WARN(BSL_LS_SOC_SOCMEM,
  19210                  (BSL_META_U(unit,
  19211                              "soc_mem_alpm_delete: invalid block %d for memory %s\n"),
  19212                   copyno, SOC_MEM_NAME(unit, mem)));
  19213         return SOC_E_PARAM;
  19214     }
  19215 
  19216     if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) {
  19217         LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  19218                             "Delete table[%s]: banks=%d"), SOC_MEM_NAME(unit, mem),
  19219                  banks_disable));
  19220         if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) {
  19221             soc_mem_entry_dump(unit, mem, entry, BSL_VERBOSE|BSL_LS_SOC_COMMON);
  19222         }
  19223         LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  19224                             "\n")));
  19225     }
  19226 
  19227     entry_dw = soc_mem_entry_words(unit, mem);
  19228 
  19229     SOC_CONTROL_LOCK(unit);
  19230     SHR_BITSET(&(SOC_CONTROL(unit)->alpm_mem_ops), _SOC_ALPM_DELETE);
  19231     SOC_CONTROL_UNLOCK(unit);
  19232 
  19233 _retry:
  19234     schan_msg_clear(&schan_msg);
  19235     acc_type = SOC_MEM_ACC_TYPE(unit, mem);
  19236     src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit));
  19237     dst_blk = SOC_BLOCK2SCH(unit, copyno);
  19238 #ifdef BCM_ISM_SUPPORT
  19239     if (soc_feature(unit, soc_feature_ism_memory)) {
  19240         /* don't set bank id in cos */
  19241         bank_ignore_mask = 0;
  19242     } else
  19243 #endif /* BCM_ISM_SUPPORT */
  19244     {
  19245         bank_ignore_mask = banks_disable & 0x3;
  19246     }
  19247     data_byte_len = entry_dw * 4;
  19248 
  19249     schan_msg.gencmd.address = soc_mem_addr_get(unit, mem, 0, copyno, 0, &at);
  19250 
  19251     /* Address contains bank disable, and bucket pointer */
  19252     /* Bucket index and bank disable
  19253      * addr[TD2: 13:0,  TH: 12:0,  TH2: 13:0]   - bucket
  19254      * addr[TD2: 17:14, TH: 16:13, TH2: 17:14]  - bank disable[3:0]
  19255      */
  19256 #if defined(BCM_TOMAHAWK_SUPPORT)
  19257     if (SOC_IS_TOMAHAWK(unit)) {
  19258         schan_msg.gencmd.address &= ~(0x0001ffff);
  19259         schan_msg.gencmd.address |=
  19260             (((banks_disable & 0xf) << 13) | (bucket & ALPM_CTRL(unit).bkt_mask));
  19261     } else if (SOC_IS_TRIDENT3X(unit)) {
  19262         /* TD3 only has 4 bits for bank disable bitmap */
  19263         schan_msg.gencmd.address &= ~(0x0001ffff);
  19264         schan_msg.gencmd.address |=
  19265             (((banks_disable & 0xf) << 13) | (bucket & ALPM_CTRL(unit).bkt_mask));
  19266     } else
  19267 #endif
  19268     {
  19269         schan_msg.gencmd.address &= ~(0x0003ffff);
  19270         schan_msg.gencmd.address |= 
  19271             (((banks_disable & 0xf) << 14) | (bucket & SOC_TD2_ALPM_BKT_MASK));
  19272     }    
  19273    
  19274     soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_DELETE_CMD_MSG,
  19275                              dst_blk, src_blk, acc_type, data_byte_len, 0,
  19276                              bank_ignore_mask);
  19277 
  19278     /* Fill in packet data */
  19279     sal_memcpy(schan_msg.gencmd.data, entry, entry_dw * 4);
  19280 
  19281     if (SOC_IS_SAND(unit)) {
  19282         allow_intr = 1;
  19283     }
  19284 
  19285     /* Only lock one time */
  19286     if (0 == _alpm_lock) {
  19287         SOC_ALPM_LPM_LOCK(unit);
  19288         _alpm_lock = 1;
  19289     }
  19290 
  19291     /*
  19292      * Execute S-Channel "table delete" command packet consisting of
  19293      * (header word + address word + entry_dw), and read back
  19294      * (header word + response word + entry_dw) data words.
  19295      */
  19296     rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr);
  19297 
  19298     soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL,
  19299                                 NULL, NULL, &nack);
  19300     if (opcode != TABLE_DELETE_DONE_MSG) {
  19301         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  19302                   (BSL_META_U(unit,
  19303                               "soc_mem_generic_delete: "
  19304                               "invalid S-Channel reply, expected TABLE_DELETE_DONE_MSG:\n")));
  19305         soc_schan_dump(unit, &schan_msg, 1);
  19306         SOC_ALPM_LPM_UNLOCK(unit);
  19307         return SOC_E_INTERNAL;
  19308     }
  19309 
  19310     type = schan_msg.genresp_v2.response.type;
  19311     index = schan_msg.genresp_v2.response.index;
  19312     data = schan_msg.genresp_v2.data;
  19313 
  19314     LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
  19315               (BSL_META_U(unit,
  19316                           "SBUS DELETE: nack:%d rv:%d type:%d index:%d \n"),
  19317                           nack, rv, type, index));
  19318 
  19319     if (_soc_alpm_delete_retry && (nack != 0 || rv == SOC_E_FAIL)) {
  19320         if (type == SCHAN_GEN_RESP_TYPE_NOT_FOUND) {
  19321             LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
  19322                       (BSL_META_U(unit,
  19323                       "SBUS DELETE failed, not found at retry %d \n"),
  19324                       _soc_alpm_delete_retry));
  19325             /* After SER actions, the entry in bad pipe could be deleted.
  19326              * We too consider that as success.
  19327              */
  19328             nack = 0;
  19329             rv = SOC_E_NONE;
  19330             if (type2 == SCHAN_GEN_RESP_TYPE_DELETED) {
  19331                 /* recover the values needed for success ops */
  19332                 type  = type2;
  19333                 index = index2;
  19334                 data  = data2;
  19335             } else {
  19336                 /* SBUS fails at the first time (type is error).
  19337                  * We lose the deleted entry's contect and its index.
  19338                  */
  19339                 LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
  19340                           (BSL_META_U(unit,
  19341                           "SBUS INSERT fails 1st with error. The deleted index"
  19342                           " and old entry is lost \n")));
  19343             }
  19344         }
  19345     }
  19346     if ((nack != 0) || (rv == SOC_E_FAIL)) {
  19347         if (index_ptr) {
  19348             *index_ptr = -1;
  19349         }
  19350         if (type == SCHAN_GEN_RESP_TYPE_NOT_FOUND) {
  19351             LOG_INFO(BSL_LS_SOC_SOCMEM,
  19352                      (BSL_META_U(unit,
  19353                                  "Delete table[%s]: Not found\n"),
  19354                       SOC_MEM_NAME(unit, mem)));
  19355             rv = SOC_E_NOT_FOUND;
  19356         } else if (type == SCHAN_GEN_RESP_TYPE_ERROR ||
  19357                    type == SCHAN_GEN_RESP_TYPE_DELETED) {
  19358             LOG_WARN(BSL_LS_SOC_SOCMEM,
  19359                      (BSL_META_U(unit,
  19360                                  "unit %d: ALPM delete operation[%s] encountered "
  19361                                  "parity error !! Resp_type %d Resp_index %d\n"),
  19362                                  unit, SOC_MEM_NAME(unit, mem), type, index));
  19363             _soc_alpm_delete_retry++;
  19364             if (type == SCHAN_GEN_RESP_TYPE_DELETED) {
  19365                 type2  = type;
  19366                 index2 = index;
  19367                 sal_memcpy(data2, schan_msg.genresp_v2.data, entry_dw * 4);
  19368                 bkt_ptr = bucket;
  19369             }
  19370             if (SOC_CONTROL(unit)->alpm_delete_retry) {
  19371                 (void)_soc_mem_alpm_ser_correction(unit,
  19372                                                    mem,
  19373                                                    schan_msg.gencmd.header.v2.dst_blk,
  19374                                                    schan_msg.gencmd.address,
  19375                                                    copyno, index,
  19376                                                    bkt_ptr);
  19377                 if (_soc_alpm_delete_retry < _SOC_ALPM_MEM_OP_RETRY_COUNT) {
  19378                     
  19379                     if (sal_sem_take(SOC_CONTROL(unit)->alpm_delete_retry,
  19380                                      _SOC_ALPM_MEM_OP_RETRY_TO) < 0) {
  19381                         LOG_WARN(BSL_LS_SOC_SOCMEM,
  19382                                  (BSL_META_U(unit,
  19383                                              "unit %d: Retry ALPM delete operation..\n"), unit));
  19384                         goto _retry;
  19385                     } else {
  19386                         LOG_WARN(BSL_LS_SOC_SOCMEM,
  19387                                  (BSL_META_U(unit,
  19388                                              "unit %d: Retry ALPM delete operation..\n"), unit));
  19389                         goto _retry;
  19390                     }
  19391                 } else {
  19392                     LOG_ERROR(BSL_LS_SOC_SOCMEM,
  19393                               (BSL_META_U(unit,
  19394                                           "unit %d: Aborting ALPM delete operation "
  19395                                           "due to un-correctable error !!\n"), unit));
  19396                     rv = SOC_E_INTERNAL;
  19397                 }
  19398             } else {
  19399                 rv = SOC_E_INTERNAL;
  19400             }
  19401         } else {
  19402             rv = SOC_E_FAIL;
  19403         }
  19404     } else {
  19405         if (old_entry != NULL) {
  19406             sal_memcpy(old_entry, data, entry_dw * sizeof(uint32));
  19407         }
  19408         if (index_ptr != NULL) {
  19409             *index_ptr = index;
  19410         }
  19411         /* Update cache if active */
  19412         cache = SOC_MEM_STATE(unit, mem).cache[copyno];
  19413         vmap = SOC_MEM_STATE(unit, mem).vmap[copyno];
  19414         index_valid = (index >= 0 &&
  19415                        index <= soc_mem_index_max(unit, mem));
  19416 
  19417         if (index_valid && cache != NULL && CACHE_VMAP_TST(vmap, index)
  19418             && !SOC_MEM_TEST_SKIP_CACHE(unit)) {
  19419             sal_memcpy(cache + index * entry_dw, null_entry, entry_dw * 4);
  19420             CACHE_VMAP_SET(vmap, index);
  19421         }
  19422     }
  19423     SOC_ALPM_LPM_UNLOCK(unit);
  19424     SOC_CONTROL_LOCK(unit);
  19425     SHR_BITCLR(&(SOC_CONTROL(unit)->alpm_mem_ops), _SOC_ALPM_DELETE);
  19426     SOC_CONTROL_UNLOCK(unit);
  19427 
  19428     return rv;
  19429 }
  19430 #endif /* ALPM_ENABLE */
  19431 
  19432 #ifdef BCM_TRX_SUPPORT
  19433 #define HASH_DUAL   0
  19434 #define HASH_SHARED 1
  19435 #define HASH_MULTI  2
  19436 STATIC int
  19437 _soc_mem_dual_hash_get(int unit, soc_mem_t mem, int hash_sel, int bank,
  19438                        void *entry_data);
  19439 
  19440 STATIC int
  19441 soc_hash_mem_bank_type_get (int unit, soc_mem_t mem, uint32* type)
  19442 {
  19443 #ifdef BCM_TRX_SUPPORT
  19444     if (SOC_IS_TRX(unit)) {
  19445         _SOC_MEM_REPLACE_MEM(unit, mem);
  19446         switch (mem) {
  19447             /* Intentional fall through */
  19448             /* coverity[unterminated_case] */
  19449             case MPLS_ENTRYm:
  19450                 if (SOC_IS_SC_CQ(unit)) {
  19451                     return SOC_E_UNAVAIL;
  19452                 }
  19453             case VLAN_XLATEm:
  19454             /* Intentional fall through */
  19455             /* coverity[unterminated_case] */
  19456             case EGR_VLAN_XLATEm:
  19457 #ifdef BCM_ISM_SUPPORT
  19458                 if (soc_feature(unit, soc_feature_ism_memory) &&
  19459                       soc_mem_is_mview(unit, mem)) {
  19460                     *type = HASH_MULTI;
  19461                     return SOC_E_NONE;
  19462                 }
  19463 #endif
  19464             case VLAN_MACm:
  19465             case AXP_WRX_WCDm:
  19466             case AXP_WRX_SVP_ASSIGNMENTm:
  19467 #ifdef BCM_TRIDENT2_SUPPORT
  19468             case ING_VP_VLAN_MEMBERSHIPm:
  19469             case EGR_VP_VLAN_MEMBERSHIPm:
  19470             case ING_DNAT_ADDRESS_TYPEm:
  19471             case L2_ENDPOINT_IDm:
  19472             case ENDPOINT_QUEUE_MAPm:
  19473 #endif
  19474 #ifdef BCM_TRIDENT3_SUPPORT
  19475         case SUBPORT_ID_TO_SGPP_MAPm:
  19476 #endif
  19477 #ifdef BCM_KATANA2_SUPPORT
  19478             case EGR_MP_GROUPm:
  19479 #endif 
  19480 #ifdef BCM_SABER2_SUPPORT
  19481             case MP_GROUPm:
  19482 #endif
  19483                 *type = HASH_DUAL;
  19484                 return SOC_E_NONE;
  19485 #ifdef BCM_ISM_SUPPORT
  19486             case L2_ENTRY_1m:
  19487             case L2_ENTRY_2m:
  19488             case L3_ENTRY_1m:
  19489             case L3_ENTRY_2m:
  19490             case L3_ENTRY_4m:
  19491             case VLAN_XLATE_EXTDm:
  19492             case MPLS_ENTRY_EXTDm:
  19493                 if (soc_feature(unit, soc_feature_ism_memory) &&
  19494                       soc_mem_is_mview(unit, mem)) {
  19495                     *type = HASH_MULTI;
  19496                     return SOC_E_NONE;
  19497                 }
  19498                 break;
  19499 #endif /* BCM_ISM_SUPPORT */
  19500             default:
  19501                 break;
  19502             }
  19503         }
  19504 #endif /* BCM_TRX_SUPPORT */
  19505 
  19506 #ifdef BCM_FIREBOLT_SUPPORT
  19507     if (SOC_IS_FBX(unit)) {
  19508         switch (mem) {
  19509         case L2Xm:
  19510 #ifdef BCM_TRIDENT2_SUPPORT
  19511             if (soc_feature(unit, soc_feature_shared_hash_mem)) {
  19512                 *type = HASH_SHARED;
  19513                 return SOC_E_NONE;
  19514             }
  19515 #endif /* BCM_TRIDENT2_SUPPORT */
  19516 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) || \
  19517     defined(BCM_TRX_SUPPORT)
  19518             if (soc_feature(unit, soc_feature_dual_hash)) {
  19519                 *type = HASH_DUAL;
  19520                 return SOC_E_NONE;
  19521             }
  19522 #endif
  19523             /* Insert via ARL_INSERT_CMD_MSG, not TABLE_INSERT_CMD_MSG */
  19524             break;
  19525 #if defined(INCLUDE_L3)
  19526         case L3_ENTRY_ONLYm:
  19527         case L3_ENTRY_IPV4_UNICASTm:
  19528         case L3_ENTRY_IPV4_MULTICASTm:
  19529         case L3_ENTRY_IPV6_UNICASTm:
  19530         case L3_ENTRY_IPV6_MULTICASTm:
  19531 #ifdef BCM_TRIDENT2_SUPPORT
  19532             if (soc_feature(unit, soc_feature_shared_hash_mem)) {
  19533                 *type = HASH_SHARED;
  19534                 return SOC_E_NONE;
  19535             }
  19536 #endif /* BCM_TRIDENT2_SUPPORT */
  19537 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) || \
  19538     defined(BCM_RAVEN_SUPPORT)
  19539             if (soc_feature(unit, soc_feature_dual_hash)) {
  19540                 *type = HASH_DUAL;
  19541                 return SOC_E_NONE;
  19542             }
  19543 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT || BCM_TRX_SUPPORT */
  19544 #endif /* INCLUDE_L3 */
  19545             /* Insert via L3_INSERT_CMD_MSG, not TABLE_INSERT_CMD_MSG */
  19546             break;
  19547         case VLAN_MACm:
  19548 #if defined(BCM_RAVEN_SUPPORT)
  19549             if (soc_feature(unit, soc_feature_dual_hash) &&
  19550                 (SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit))) {
  19551                 *type = HASH_DUAL;
  19552                 return SOC_E_NONE;
  19553             } else
  19554 #endif
  19555             {
  19556                 /* Via memory read/write */
  19557             }
  19558             break;
  19559 #if defined(BCM_TOMAHAWK_SUPPORT)
  19560         case EXACT_MATCH_2m:
  19561         case EXACT_MATCH_2_PIPE0m:
  19562         case EXACT_MATCH_2_PIPE1m:
  19563         case EXACT_MATCH_2_PIPE2m:
  19564         case EXACT_MATCH_2_PIPE3m:
  19565         case EXACT_MATCH_4m:
  19566         case EXACT_MATCH_4_PIPE0m:
  19567         case EXACT_MATCH_4_PIPE1m:
  19568         case EXACT_MATCH_4_PIPE2m:
  19569         case EXACT_MATCH_4_PIPE3m:
  19570 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  19571         case L3_ENTRY_SINGLEm:
  19572         case L3_ENTRY_DOUBLEm:
  19573         case L3_ENTRY_QUADm:
  19574         case VLAN_XLATE_1_SINGLEm:
  19575         case VLAN_XLATE_2_SINGLEm:
  19576         case VLAN_XLATE_1_DOUBLEm:
  19577         case VLAN_XLATE_2_DOUBLEm:
  19578         case EGR_VLAN_XLATE_1_SINGLEm:
  19579         case EGR_VLAN_XLATE_2_SINGLEm:
  19580         case EGR_VLAN_XLATE_1_DOUBLEm:
  19581         case EGR_VLAN_XLATE_2_DOUBLEm:
  19582         case MPLS_ENTRY_SINGLEm:
  19583         case L3_TUNNEL_SINGLEm:
  19584         case L3_TUNNEL_DOUBLEm:
  19585         case L3_TUNNEL_QUADm:
  19586 #endif
  19587             if (soc_feature(unit, soc_feature_shared_hash_mem)) {
  19588                 *type = HASH_SHARED;
  19589                 return SOC_E_NONE;
  19590             }
  19591 #endif
  19592         default:
  19593             break;
  19594         }
  19595     }
  19596 #endif
  19597 #ifdef BCM_ISM_SUPPORT
  19598         if (soc_feature(unit, soc_feature_ism_memory) &&
  19599               soc_mem_is_hashed(unit, mem) &&
  19600             soc_mem_is_mview(unit, mem)) {
  19601             *type = HASH_MULTI;
  19602             return SOC_E_NONE;
  19603         }
  19604 #endif /* BCM_ISM_SUPPORT */
  19605 
  19606     return SOC_E_INTERNAL;
  19607 }
  19608 
  19609 
  19610 STATIC int
  19611 soc_hash_mem_dual_hash_info_get (int unit, soc_mem_t mem, dual_hash_info_t *hash_info)
  19612 {
  19613     int rv = SOC_E_INTERNAL;
  19614 
  19615     switch (mem) {
  19616     case L2Xm:
  19617         SOC_IF_ERROR_RETURN
  19618             (soc_fb_l2x_entry_bank_hash_sel_get(unit, 0,
  19619                                                 &(hash_info->hash_sel0)));
  19620         SOC_IF_ERROR_RETURN
  19621             (soc_fb_l2x_entry_bank_hash_sel_get(unit, 1,
  19622                                                 &(hash_info->hash_sel1)));
  19623         hash_info->bucket_size = SOC_L2X_BUCKET_SIZE;
  19624         hash_info->base_mem = mem;
  19625         rv = SOC_E_NONE;
  19626         break;
  19627 #ifdef BCM_TRX_SUPPORT
  19628     case VLAN_XLATEm:
  19629 #ifdef BCM_TRIDENT3_SUPPORT
  19630         case SUBPORT_ID_TO_SGPP_MAPm:
  19631 #endif
  19632         if (!SOC_IS_TRX(unit)) {
  19633             break;
  19634         }
  19635 #endif
  19636 #if defined(BCM_RAVEN_SUPPORT) || defined(BCM_TRX_SUPPORT)
  19637     case VLAN_MACm:
  19638         if (SOC_IS_FIREBOLT2(unit)) {
  19639             break;
  19640         }
  19641 #ifdef BCM_TRX_SUPPORT
  19642 #ifdef BCM_TRIDENT2_SUPPORT
  19643         if (SOC_IS_TD2_TT2(unit)) {
  19644             SOC_IF_ERROR_RETURN
  19645                 (soc_td2_hash_sel_get(unit, mem, 0, &hash_info->hash_sel0));
  19646             SOC_IF_ERROR_RETURN
  19647                 (soc_td2_hash_sel_get(unit, mem, 1, &hash_info->hash_sel1));
  19648             hash_info->bucket_size = SOC_VLAN_XLATE_BUCKET_SIZE;
  19649             hash_info->base_mem = mem;
  19650             rv = SOC_E_NONE;
  19651         } else
  19652 #endif
  19653         {
  19654             if (mem == VLAN_XLATEm) {
  19655                 SOC_IF_ERROR_RETURN
  19656                     (soc_tr_hash_sel_get(unit, mem, 0, &hash_info->hash_sel0));
  19657                 SOC_IF_ERROR_RETURN
  19658                     (soc_tr_hash_sel_get(unit, mem, 1, &hash_info->hash_sel1));
  19659                 hash_info->bucket_size = SOC_VLAN_XLATE_BUCKET_SIZE;
  19660                 hash_info->base_mem = mem;
  19661                 rv = SOC_E_NONE;
  19662             } else
  19663 #endif
  19664             {
  19665                 SOC_IF_ERROR_RETURN
  19666                     (soc_fb_rv_vlanmac_hash_sel_get(unit, 0, &(hash_info->hash_sel0)));
  19667 
  19668                 SOC_IF_ERROR_RETURN
  19669                     (soc_fb_rv_vlanmac_hash_sel_get(unit, 1, &(hash_info->hash_sel1)));
  19670                 hash_info->bucket_size = SOC_VLAN_MAC_BUCKET_SIZE;
  19671                 hash_info->base_mem = mem;
  19672                 rv = SOC_E_NONE;
  19673             }
  19674         }
  19675         break;
  19676 #endif
  19677 
  19678 #if defined(BCM_TRX_SUPPORT)
  19679     case MPLS_ENTRYm:
  19680         SOC_IF_ERROR_RETURN
  19681             (soc_tr_hash_sel_get(unit, mem, 0, &hash_info->hash_sel0));
  19682         SOC_IF_ERROR_RETURN
  19683             (soc_tr_hash_sel_get(unit, mem, 1, &hash_info->hash_sel1));
  19684         hash_info->bucket_size = SOC_MPLS_ENTRY_BUCKET_SIZE;
  19685         hash_info->base_mem = mem;
  19686         rv = SOC_E_NONE;
  19687         break;
  19688     case EGR_VLAN_XLATEm:
  19689         SOC_IF_ERROR_RETURN
  19690             (soc_tr_hash_sel_get(unit, mem, 0, &hash_info->hash_sel0));
  19691         SOC_IF_ERROR_RETURN
  19692             (soc_tr_hash_sel_get(unit, mem, 1, &hash_info->hash_sel1));
  19693         hash_info->bucket_size = SOC_EGR_VLAN_XLATE_BUCKET_SIZE;
  19694         hash_info->base_mem = mem;
  19695         rv = SOC_E_NONE;
  19696         break;
  19697     case AXP_WRX_WCDm:
  19698     case AXP_WRX_SVP_ASSIGNMENTm:
  19699         SOC_IF_ERROR_RETURN
  19700             (soc_tr_hash_sel_get(unit, mem, 0, &hash_info->hash_sel0));
  19701         SOC_IF_ERROR_RETURN
  19702             (soc_tr_hash_sel_get(unit, mem, 1, &hash_info->hash_sel1));
  19703         hash_info->bucket_size = SOC_WLAN_BUCKET_SIZE;
  19704         hash_info->base_mem = mem;
  19705         rv = SOC_E_NONE;
  19706         break;
  19707 #ifdef BCM_TRIDENT2_SUPPORT
  19708     case ING_VP_VLAN_MEMBERSHIPm:
  19709         SOC_IF_ERROR_RETURN
  19710             (soc_td2_hash_sel_get(unit, mem, 0, &hash_info->hash_sel0));
  19711         SOC_IF_ERROR_RETURN
  19712             (soc_td2_hash_sel_get(unit, mem, 1, &hash_info->hash_sel1));
  19713         hash_info->bucket_size = SOC_ING_VP_VLAN_MEMBER_BUCKET_SIZE;
  19714         hash_info->base_mem = mem;
  19715         rv = SOC_E_NONE;
  19716         break;
  19717     case EGR_VP_VLAN_MEMBERSHIPm:
  19718         SOC_IF_ERROR_RETURN
  19719             (soc_td2_hash_sel_get(unit, mem, 0, &hash_info->hash_sel0));
  19720         SOC_IF_ERROR_RETURN
  19721             (soc_td2_hash_sel_get(unit, mem, 1, &hash_info->hash_sel1));
  19722         hash_info->bucket_size = SOC_EGR_VP_VLAN_MEMBER_BUCKET_SIZE;
  19723         hash_info->base_mem = mem;
  19724         rv = SOC_E_NONE;
  19725         break;
  19726     case ING_DNAT_ADDRESS_TYPEm:
  19727         SOC_IF_ERROR_RETURN
  19728             (soc_td2_hash_sel_get(unit, mem, 0, &hash_info->hash_sel0));
  19729         SOC_IF_ERROR_RETURN
  19730             (soc_td2_hash_sel_get(unit, mem, 1, &hash_info->hash_sel1));
  19731         hash_info->bucket_size = SOC_ING_DNAT_ADDRESS_TYPE_BUCKET_SIZE;
  19732         hash_info->base_mem = mem;
  19733         rv = SOC_E_NONE;
  19734         break;
  19735     case L2_ENDPOINT_IDm:
  19736         SOC_IF_ERROR_RETURN
  19737             (soc_td2_hash_sel_get(unit, mem, 0, &hash_info->hash_sel0));
  19738         SOC_IF_ERROR_RETURN
  19739             (soc_td2_hash_sel_get(unit, mem, 1, &hash_info->hash_sel1));
  19740         hash_info->bucket_size = SOC_L2_ENDPOINT_ID_BUCKET_SIZE;
  19741         hash_info->base_mem = mem;
  19742         rv = SOC_E_NONE;
  19743         break;
  19744     case ENDPOINT_QUEUE_MAPm:
  19745         SOC_IF_ERROR_RETURN
  19746             (soc_td2_hash_sel_get(unit, mem, 0, &hash_info->hash_sel0));
  19747         SOC_IF_ERROR_RETURN
  19748             (soc_td2_hash_sel_get(unit, mem, 1, &hash_info->hash_sel1));
  19749         hash_info->bucket_size = SOC_ENDPOINT_QUEUE_MAP_BUCKET_SIZE;
  19750         hash_info->base_mem = mem;
  19751         rv = SOC_E_NONE;
  19752         break;
  19753     
  19754 #endif
  19755 #ifdef BCM_KATANA2_SUPPORT
  19756     case EGR_MP_GROUPm:
  19757         
  19758         SOC_IF_ERROR_RETURN
  19759             (soc_tr_hash_sel_get(unit, mem, 0, &hash_info->hash_sel0));
  19760         SOC_IF_ERROR_RETURN
  19761             (soc_tr_hash_sel_get(unit, mem, 1, &hash_info->hash_sel1));
  19762         hash_info->bucket_size = SOC_EGR_MP_GROUP_BUCKET_SIZE;
  19763         hash_info->base_mem = mem;
  19764         rv = SOC_E_NONE;
  19765         break;
  19766 #endif
  19767 #ifdef BCM_SABER2_SUPPORT
  19768     case MP_GROUPm:
  19769         
  19770         SOC_IF_ERROR_RETURN
  19771             (soc_tr_hash_sel_get(unit, mem, 0, &hash_info->hash_sel0));
  19772         SOC_IF_ERROR_RETURN
  19773             (soc_tr_hash_sel_get(unit, mem, 1, &hash_info->hash_sel1));
  19774         hash_info->bucket_size = SOC_EGR_MP_GROUP_BUCKET_SIZE;
  19775         hash_info->base_mem = mem;
  19776         rv = SOC_E_NONE;
  19777         break;
  19778 #endif
  19779 #endif /* BCM_TRX_SUPPORT */
  19780 #if defined(INCLUDE_L3)
  19781     case L3_ENTRY_ONLYm:
  19782     case L3_ENTRY_IPV4_UNICASTm:
  19783     case L3_ENTRY_IPV4_MULTICASTm:
  19784     case L3_ENTRY_IPV6_UNICASTm:
  19785     case L3_ENTRY_IPV6_MULTICASTm:
  19786 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) || \
  19787     defined(BCM_RAVEN_SUPPORT)
  19788         if (soc_feature(unit, soc_feature_dual_hash)) {
  19789             SOC_IF_ERROR_RETURN
  19790                 (soc_fb_l3x_entry_bank_hash_sel_get(unit, 0,
  19791                                             &(hash_info->hash_sel0)));
  19792             SOC_IF_ERROR_RETURN
  19793                 (soc_fb_l3x_entry_bank_hash_sel_get(unit, 1,
  19794                                             &(hash_info->hash_sel1)));
  19795             hash_info->bucket_size = SOC_L3X_BUCKET_SIZE(unit);
  19796             hash_info->base_mem = L3_ENTRY_IPV4_UNICASTm;
  19797 #if defined(BCM_HURRICANE2_SUPPORT) || defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
  19798             if (soc_feature(unit, soc_feature_hr2_dual_hash) ||
  19799                 SOC_IS_KATANA2(unit) || SOC_IS_TRIDENT(unit)) {
  19800                 hash_info->bucket_size =
  19801                     _soc_mem_hash_entries_per_bkt(unit, mem);
  19802             }
  19803 #endif /* BCM_HURRICANE2_SUPPORT */
  19804             rv = SOC_E_NONE;
  19805         }
  19806 #endif
  19807         break;
  19808 #endif
  19809     default:
  19810         break;
  19811     }
  19812     return rv;
  19813 }
  19814 
  19815 STATIC int
  19816 soc_ser_hash_mem_bank_correction(int unit, soc_mem_t mem, schan_msg_t* schan_msg,
  19817                                  uint32 base_index, uint32 size)
  19818 {
  19819     int i, rv;
  19820     uint32 recovery_view_index;
  19821     _soc_ser_correct_info_t spci;
  19822     sal_memset(&spci, 0, sizeof(spci));
  19823 
  19824     spci.flags = SOC_SER_SRC_MEM | SOC_SER_REG_MEM_KNOWN;
  19825     /* If one entry has parity error, mem access in other
  19826      * entry of same bucket will trigger SBUS NACK. So
  19827      * all entties need to be corrected. */
  19828     spci.flags |= SOC_SER_SKIP_HARD_FALT_CHECK;
  19829     spci.reg = INVALIDr;
  19830     spci.mem = mem;
  19831     spci.pipe_num = SOC_PIPE_ANY;
  19832     spci.blk_type = SOC_BLOCK_ANY;
  19833     spci.sblk = 0;
  19834     spci.addr = schan_msg->gencmd.address;
  19835     recovery_view_index = base_index;
  19836 
  19837 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT)
  19838     if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_APACHE(unit)) {
  19839         switch (mem) {
  19840         case L3_ENTRY_ONLYm:
  19841         case L3_ENTRY_IPV4_UNICASTm:
  19842             spci.mem = L3_ENTRY_ONLY_ECCm;
  19843             recovery_view_index = base_index;
  19844             break;
  19845         case L3_ENTRY_IPV4_MULTICASTm:
  19846         case L3_ENTRY_IPV6_UNICASTm:
  19847             spci.mem = L3_ENTRY_ONLY_ECCm;
  19848             recovery_view_index = base_index * 2;
  19849             break;
  19850         case L3_ENTRY_IPV6_MULTICASTm:
  19851             spci.mem = L3_ENTRY_ONLY_ECCm;
  19852             recovery_view_index = base_index * 4;
  19853             break;
  19854         case L2Xm:
  19855 #ifdef BCM_TOMAHAWK3_SUPPORT
  19856             if (SOC_IS_TOMAHAWK3(unit)) {
  19857                 spci.mem = L2_ENTRY_ECCm;
  19858             } else
  19859 #endif
  19860             {
  19861             spci.mem = L2_ENTRY_ONLY_ECCm;
  19862             }
  19863             recovery_view_index = base_index;
  19864             break;
  19865         case VLAN_MACm:
  19866         case VLAN_XLATEm:
  19867             spci.mem = VLAN_XLATE_ECCm;
  19868             recovery_view_index = base_index;
  19869             break;
  19870         case EGR_VLAN_XLATEm:
  19871             spci.mem = EGR_VLAN_XLATE_ECCm;
  19872             recovery_view_index = base_index;
  19873             break;
  19874         case MPLS_ENTRYm:
  19875             spci.mem = MPLS_ENTRY_ECCm;
  19876             recovery_view_index = base_index;
  19877 #ifdef BCM_APACHE_SUPPORT
  19878             if (SOC_IS_APACHE(unit)) {
  19879                 /* No ECC view for MPLS_ENTRY */
  19880                 spci.mem = MPLS_ENTRYm;
  19881                 recovery_view_index = base_index;
  19882             }
  19883 #endif
  19884             break;
  19885         case EXACT_MATCH_2m:
  19886 #ifdef BCM_TOMAHAWK3_SUPPORT
  19887             if (SOC_IS_TOMAHAWK3(unit)) {
  19888                 spci.mem = EXACT_MATCH_ECCm;
  19889                 recovery_view_index = base_index*2;
  19890             } else
  19891 #endif
  19892             {
  19893             spci.mem = FPEM_ECCm;
  19894             recovery_view_index = base_index/2;
  19895             }
  19896             break;
  19897         case EXACT_MATCH_2_PIPE0m:
  19898             spci.pipe_num = 0;
  19899             spci.mem = FPEM_ECCm;
  19900             recovery_view_index = base_index/2;
  19901             break;
  19902         case EXACT_MATCH_2_PIPE1m:
  19903             spci.pipe_num = 1;
  19904             spci.mem = FPEM_ECCm;
  19905             recovery_view_index = base_index/2;
  19906             break;
  19907         case EXACT_MATCH_2_PIPE2m:
  19908             spci.pipe_num = 2;
  19909             spci.mem = FPEM_ECCm;
  19910             recovery_view_index = base_index/2;
  19911             break;
  19912         case EXACT_MATCH_2_PIPE3m:
  19913             spci.pipe_num = 3;
  19914             spci.mem = FPEM_ECCm;
  19915             recovery_view_index = base_index/2;
  19916             break;
  19917         case EXACT_MATCH_4m:
  19918 #ifdef BCM_TOMAHAWK3_SUPPORT
  19919             if (SOC_IS_TOMAHAWK3(unit)) {
  19920                 spci.mem = EXACT_MATCH_ECCm;
  19921                 recovery_view_index = base_index*4;
  19922             } else
  19923 #endif
  19924             {
  19925             spci.mem = FPEM_ECCm;
  19926             recovery_view_index = base_index/4;
  19927             }
  19928             break;
  19929         case EXACT_MATCH_4_PIPE0m:
  19930             spci.pipe_num = 0;
  19931             spci.mem = FPEM_ECCm;
  19932             recovery_view_index = base_index/4;
  19933             break;
  19934         case EXACT_MATCH_4_PIPE1m:
  19935             spci.pipe_num = 1;
  19936             spci.mem = FPEM_ECCm;
  19937             recovery_view_index = base_index/4;
  19938             break;
  19939         case EXACT_MATCH_4_PIPE2m:
  19940             spci.pipe_num = 2;
  19941             spci.mem = FPEM_ECCm;
  19942             recovery_view_index = base_index/4;
  19943             break;
  19944         case EXACT_MATCH_4_PIPE3m:
  19945             spci.pipe_num = 3;
  19946             spci.mem = FPEM_ECCm;
  19947             recovery_view_index = base_index/4;
  19948             break;
  19949 #ifdef BCM_TOMAHAWK3_SUPPORT
  19950         case L3_ENTRY_SINGLEm:
  19951             if (SOC_IS_TOMAHAWK3(unit)) {
  19952                 spci.mem = L3_ENTRY_ECCm;
  19953                 recovery_view_index = base_index;
  19954             }
  19955             break;
  19956         case L3_ENTRY_DOUBLEm:
  19957             if (SOC_IS_TOMAHAWK3(unit)) {
  19958                 spci.mem = L3_ENTRY_ECCm;
  19959                 recovery_view_index = base_index * 2;
  19960             }
  19961             break;
  19962         case L3_ENTRY_QUADm:
  19963             if (SOC_IS_TOMAHAWK3(unit)) {
  19964                 spci.mem = L3_ENTRY_ECCm;
  19965                 recovery_view_index = base_index * 4;
  19966             }
  19967             break;
  19968         case L3_TUNNEL_SINGLEm:
  19969             if (SOC_IS_TOMAHAWK3(unit)) {
  19970                 spci.mem = L3_TUNNEL_ECCm;
  19971                 recovery_view_index = base_index;
  19972             }
  19973             break;
  19974         case L3_TUNNEL_DOUBLEm:
  19975             if (SOC_IS_TOMAHAWK3(unit)) {
  19976                 spci.mem = L3_TUNNEL_ECCm;
  19977                 recovery_view_index = base_index * 2;
  19978             }
  19979             break;
  19980         case L3_TUNNEL_QUADm:
  19981             if (SOC_IS_TOMAHAWK3(unit)) {
  19982                 spci.mem = L3_TUNNEL_ECCm;
  19983                 recovery_view_index = base_index * 4;
  19984             }
  19985             break;
  19986         case MPLS_ENTRY_SINGLEm:
  19987             if (SOC_IS_TOMAHAWK3(unit)) {
  19988                 spci.mem = MPLS_ENTRY_ECCm;
  19989                 recovery_view_index = base_index;
  19990             }
  19991             break;
  19992 #endif
  19993         default:
  19994             break;
  19995         }
  19996     } else
  19997 #endif
  19998     {
  19999         switch (mem) {
  20000         case L3_ENTRY_ONLYm:
  20001         case L3_ENTRY_IPV4_UNICASTm:
  20002             spci.mem = L3_ENTRY_ONLYm;
  20003             recovery_view_index = base_index;
  20004             break;
  20005         case L3_ENTRY_IPV4_MULTICASTm:
  20006         case L3_ENTRY_IPV6_UNICASTm:
  20007             spci.mem = L3_ENTRY_ONLYm;
  20008             recovery_view_index = base_index * 2;
  20009             break;
  20010         case L3_ENTRY_IPV6_MULTICASTm:
  20011             spci.mem = L3_ENTRY_ONLYm;
  20012             recovery_view_index = base_index * 4;
  20013             break;
  20014 #if defined(BCM_TRIDENT3_SUPPORT)
  20015         case VLAN_XLATE_1_SINGLEm:
  20016         case VLAN_XLATE_1_DOUBLEm:
  20017             if (SOC_IS_TRIDENT3X(unit)) {
  20018                 spci.mem = VLAN_XLATE_1_ECCm;
  20019                 recovery_view_index = base_index;
  20020             }
  20021             break;
  20022         case VLAN_XLATE_2_SINGLEm:
  20023         case VLAN_XLATE_2_DOUBLEm:
  20024             if (SOC_IS_TRIDENT3X(unit)) {
  20025                 spci.mem = VLAN_XLATE_2_ECCm;
  20026                 recovery_view_index = base_index;
  20027             }
  20028             break;
  20029         case EGR_VLAN_XLATE_1_SINGLEm:
  20030         case EGR_VLAN_XLATE_1_DOUBLEm:
  20031             if (SOC_IS_TRIDENT3X(unit)) {
  20032                 spci.mem = EGR_VLAN_XLATE_1_ECCm;
  20033                 recovery_view_index = base_index;
  20034             }
  20035             break;
  20036         case EGR_VLAN_XLATE_2_SINGLEm:
  20037         case EGR_VLAN_XLATE_2_DOUBLEm:
  20038             if (SOC_IS_TRIDENT3X(unit)) {
  20039                 spci.mem = EGR_VLAN_XLATE_2_ECCm;
  20040                 recovery_view_index = base_index;
  20041             }
  20042             break;
  20043         case ING_VP_VLAN_MEMBERSHIPm:
  20044             if (SOC_IS_TRIDENT3X(unit)) {
  20045                 spci.mem = ING_VP_VLAN_MEMBERSHIP_ECCm;
  20046                 recovery_view_index = base_index/2;
  20047                 size /= 2;
  20048             }
  20049             break;
  20050         case EGR_VP_VLAN_MEMBERSHIPm:
  20051             if (SOC_IS_TRIDENT3X(unit)) {
  20052                 spci.mem = EGR_VP_VLAN_MEMBERSHIP_ECCm;
  20053                 recovery_view_index = base_index/2;
  20054                 size /= 2;
  20055             }
  20056             break;
  20057         case ING_DNAT_ADDRESS_TYPEm:
  20058             if (SOC_IS_TRIDENT3X(unit)) {
  20059                 spci.mem = ING_DNAT_ADDRESS_TYPE_ECCm;
  20060                 recovery_view_index = base_index/2;
  20061                 size /= 2;
  20062             }
  20063             break;
  20064         case SUBPORT_ID_TO_SGPP_MAPm:
  20065             if (SOC_IS_TRIDENT3X(unit)) {
  20066                 spci.mem = SUBPORT_ID_TO_SGPP_MAP_ECCm;
  20067                 recovery_view_index = base_index/2;
  20068                 size /= 2;
  20069             }
  20070             break;
  20071         case EXACT_MATCH_4m:
  20072             if (SOC_IS_TRIDENT3X(unit)) {
  20073                 spci.mem = EXACT_MATCH_ECCm;
  20074                 recovery_view_index = base_index*4;
  20075             }
  20076             break;
  20077         case EXACT_MATCH_2m:
  20078             if (SOC_IS_TRIDENT3X(unit)) {
  20079                 spci.mem = EXACT_MATCH_ECCm;
  20080                 recovery_view_index = base_index*2;
  20081             }
  20082             break;
  20083         case EXACT_MATCH_4_PIPE0m:
  20084             if (SOC_IS_TRIDENT3X(unit)) {
  20085                 spci.pipe_num = 0;
  20086                 spci.mem = EXACT_MATCH_ECC_PIPE0m;
  20087                 recovery_view_index = base_index*4;
  20088             }
  20089             break;
  20090         case EXACT_MATCH_2_PIPE0m:
  20091             if (SOC_IS_TRIDENT3X(unit)) {
  20092                 spci.pipe_num = 0;
  20093                 spci.mem = EXACT_MATCH_ECC_PIPE0m;
  20094                 recovery_view_index = base_index*2;
  20095             }
  20096             break;
  20097         case EXACT_MATCH_4_PIPE1m:
  20098             if (SOC_IS_TRIDENT3X(unit)) {
  20099                 spci.pipe_num = 1;
  20100                 spci.mem = EXACT_MATCH_ECC_PIPE1m;
  20101                 recovery_view_index = base_index*4;
  20102             }
  20103             break;
  20104         case EXACT_MATCH_2_PIPE1m:
  20105             if (SOC_IS_TRIDENT3X(unit)) {
  20106                 spci.pipe_num = 1;
  20107                 spci.mem = EXACT_MATCH_ECC_PIPE1m;
  20108                 recovery_view_index = base_index*2;
  20109             }
  20110             break;
  20111         case L3_ENTRY_SINGLEm:
  20112             if (SOC_IS_TRIDENT3X(unit)) {
  20113                 spci.mem = L3_ENTRY_ECCm;
  20114                 recovery_view_index = base_index;
  20115             }
  20116             break;
  20117         case L3_ENTRY_DOUBLEm:
  20118             if (SOC_IS_TRIDENT3X(unit)) {
  20119                 spci.mem = L3_ENTRY_ECCm;
  20120                 recovery_view_index = base_index * 2;
  20121             }
  20122             break;
  20123         case L3_ENTRY_QUADm:
  20124             if (SOC_IS_TRIDENT3X(unit)) {
  20125                 spci.mem = L3_ENTRY_ECCm;
  20126                 recovery_view_index = base_index * 4;
  20127             }
  20128             break;
  20129 #endif
  20130         case VLAN_MACm:
  20131             if (SOC_IS_TRIDENT2PLUS(unit)) {
  20132                 spci.mem = VLAN_XLATE_ECCm;
  20133                 recovery_view_index = base_index;
  20134             }
  20135             break;
  20136         default:
  20137             break;
  20138         }
  20139     }
  20140 
  20141     for (i = 0; i < size; i++) {
  20142         spci.index = recovery_view_index + i;
  20143         rv = soc_ser_correction(unit, &spci);
  20144         if (SOC_FAILURE(rv)) {
  20145             /* Report failed to correct event flag to
  20146              * application */
  20147             soc_event_generate(unit,
  20148                                SOC_SWITCH_EVENT_PARITY_ERROR,
  20149                                SOC_SWITCH_EVENT_DATA_ERROR_FAILEDTOCORRECT,
  20150                                spci.mem,
  20151                                spci.index);
  20152             return rv;
  20153         }
  20154     }
  20155     return SOC_E_NONE;
  20156 }
  20157 
  20158 
  20159 STATIC int
  20160 soc_hash_mem_inline_recovery(int unit, soc_mem_t mem, schan_msg_t* schan_msg,
  20161                              int32 bank, void *entry)
  20162 {
  20163     uint32 type, bank_idx, bucket_index;
  20164     int half_bucket, hash_sel, hash_base;
  20165 #if defined(BCM_TRIDENT2_SUPPORT)
  20166     uint32 bucket = 0;
  20167     int index, num_banks, bank_ids[7];
  20168 #endif
  20169 #ifdef BCM_ISM_SUPPORT
  20170     int ism_index;
  20171     uint8  num_ent;
  20172     uint32 result;
  20173     _soc_ism_mem_banks_t mem_banks;
  20174 #endif
  20175     dual_hash_info_t hash_info = {0};
  20176 
  20177     SOC_IF_ERROR_RETURN(soc_hash_mem_bank_type_get(unit, mem, &type));
  20178 
  20179     switch (type) {
  20180     case HASH_DUAL:
  20181 #ifdef BCM_TRIDENT3_SUPPORT
  20182         if (SOC_IS_TRIDENT3X(unit)) {
  20183             for (bank_idx = 0; bank_idx < 2; bank_idx++) {
  20184                 SOC_IF_ERROR_RETURN
  20185                     (soc_td3_hash_bucket_get(unit, mem, bank_idx,
  20186                                              entry, &bucket));
  20187                 index = soc_td3_hash_index_get(unit, mem, bank_idx,
  20188                                                bucket);
  20189                 SOC_IF_ERROR_RETURN(soc_ser_hash_mem_bank_correction(unit, mem,
  20190                                                      schan_msg, index, 4));
  20191             }
  20192         } else
  20193 #endif /* BCM_TRIDENT3_SUPPORT */
  20194         {
  20195             SOC_IF_ERROR_RETURN(soc_hash_mem_dual_hash_info_get(unit, mem, &hash_info));
  20196             half_bucket = hash_info.bucket_size / 2;
  20197             /* For dual bank hash table, one entry may be located in one of two
  20198              * different hash buckets, thus different entry index in two banks,
  20199              * any parity error in these two buckets will cause insert/delete fail.
  20200              * We have to restore both buckets.
  20201              */
  20202             for (bank_idx = 0; bank_idx < 2; bank_idx++) {
  20203                 hash_sel = (bank_idx == 0) ? hash_info.hash_sel0 : hash_info.hash_sel1;
  20204                 hash_base = _soc_mem_dual_hash_get(unit, mem, hash_sel, bank_idx,
  20205                                                    entry);
  20206                 if (hash_base == -1) {
  20207                     return SOC_E_INTERNAL;
  20208                 }
  20209                 bucket_index = hash_base * hash_info.bucket_size + bank_idx * half_bucket;
  20210                 SOC_IF_ERROR_RETURN(soc_ser_hash_mem_bank_correction(unit, mem,
  20211                                                          schan_msg, bucket_index,
  20212                                                          half_bucket));
  20213             }
  20214         }
  20215         break;
  20216     case HASH_SHARED:
  20217 #if defined(BCM_TRIDENT2_SUPPORT)
  20218 
  20219 #ifdef BCM_APACHE_SUPPORT
  20220         if (SOC_IS_APACHE(unit)) {
  20221             SOC_IF_ERROR_RETURN
  20222                 (soc_apache_hash_bank_count_get(unit, mem, &num_banks));
  20223         } else
  20224 #endif /* APACHE_SUPPORT */
  20225 #ifdef BCM_TOMAHAWK_SUPPORT
  20226         if (SOC_IS_TOMAHAWKX(unit)) {
  20227 #ifdef BCM_TOMAHAWK3_SUPPORT
  20228             if (SOC_IS_TOMAHAWK3(unit)) {
  20229                 SOC_IF_ERROR_RETURN
  20230                     (soc_tomahawk3_hash_bank_count_get(unit, mem, &num_banks));
  20231             } else
  20232 #endif /* BCM_TOMAHAWK3_SUPPORT */
  20233             {
  20234             SOC_IF_ERROR_RETURN
  20235                 (soc_tomahawk_hash_bank_count_get(unit, mem, &num_banks));
  20236             }
  20237         } else
  20238 #endif /* BCM_TOMAHAWK_SUPPORT */
  20239 #ifdef BCM_HELIX5_SUPPORT
  20240         if (SOC_IS_HELIX5(unit)) {
  20241             SOC_IF_ERROR_RETURN
  20242                 (soc_helix5_hash_bank_count_get(unit, mem, &num_banks));
  20243         } else
  20244 #endif /* BCM_HELIX5_SUPPORT */
  20245 #ifdef BCM_TRIDENT3_SUPPORT
  20246         if (SOC_IS_TRIDENT3X(unit)) {
  20247             SOC_IF_ERROR_RETURN
  20248                 (soc_trident3_hash_bank_count_get(unit, mem, &num_banks));
  20249         } else
  20250 #endif /* BCM_TRIDENT3_SUPPORT */
  20251         {
  20252             SOC_IF_ERROR_RETURN
  20253                 (soc_trident2_hash_bank_count_get(unit, mem, &num_banks));
  20254         }
  20255         for (bank_idx = 0; bank_idx < num_banks; bank_idx++) {
  20256 
  20257 #ifdef BCM_APACHE_SUPPORT
  20258             if (SOC_IS_APACHE(unit)) {
  20259                 SOC_IF_ERROR_RETURN
  20260                     (soc_apache_hash_bank_number_get(unit, mem, bank_idx,
  20261                                                        &bank_ids[bank_idx]));
  20262                 SOC_IF_ERROR_RETURN
  20263                     (soc_ap_hash_bucket_get(unit, mem, bank_ids[bank_idx],
  20264                                             entry, &bucket));
  20265                 index = soc_ap_hash_index_get(unit, mem, bank_ids[bank_idx], bucket);
  20266             } else
  20267 #endif /* BCM_APACHE_SUPPORT */
  20268 #ifdef BCM_TOMAHAWK_SUPPORT
  20269             if (SOC_IS_TOMAHAWKX(unit)) {
  20270 #ifdef BCM_TOMAHAWK3_SUPPORT
  20271                 if (SOC_IS_TOMAHAWK3(unit)) {
  20272                     SOC_IF_ERROR_RETURN
  20273                         (soc_tomahawk3_hash_bank_number_get(unit, mem, bank_idx,
  20274                                                            &bank_ids[bank_idx]));
  20275                     SOC_IF_ERROR_RETURN
  20276                         (soc_tomahawk3_hash_bucket_get(unit, mem, bank_ids[bank_idx],
  20277                                                 entry, &bucket));
  20278                     index = soc_tomahawk3_hash_index_get(unit, mem, bank_ids[bank_idx], bucket);
  20279                 } else
  20280 #endif /* BCM_TOMAHAWK3_SUPPORT */
  20281                 {
  20282                 SOC_IF_ERROR_RETURN
  20283                     (soc_tomahawk_hash_bank_number_get(unit, mem, bank_idx,
  20284                                                        &bank_ids[bank_idx]));
  20285                 SOC_IF_ERROR_RETURN
  20286                     (soc_th_hash_bucket_get(unit, mem, bank_ids[bank_idx],
  20287                                             entry, &bucket));
  20288                 index = soc_th_hash_index_get(unit, mem, bank_ids[bank_idx], bucket);
  20289                 }
  20290             } else
  20291 #endif /* BCM_TOMAHAWK_SUPPORT */
  20292 #ifdef BCM_HELIX5_SUPPORT
  20293             if (SOC_IS_HELIX5(unit)) {
  20294                 SOC_IF_ERROR_RETURN
  20295                     (soc_hx5_hash_bank_number_get(unit, mem, bank_idx,
  20296                                                   &bank_ids[bank_idx]));
  20297                 SOC_IF_ERROR_RETURN
  20298                     (soc_hx5_hash_bucket_get(unit, mem, bank_ids[bank_idx],
  20299                                              entry, &bucket));
  20300                 index = soc_hx5_hash_index_get(unit, mem, bank_ids[bank_idx],
  20301                                                bucket);
  20302             } else
  20303 #endif /* BCM_HELIX5_SUPPORT */
  20304 #ifdef BCM_TRIDENT3_SUPPORT
  20305             if (SOC_IS_TRIDENT3X(unit)) {
  20306                 SOC_IF_ERROR_RETURN
  20307                     (soc_td3_hash_bank_number_get(unit, mem, bank_idx,
  20308                                                   &bank_ids[bank_idx]));
  20309                 SOC_IF_ERROR_RETURN
  20310                     (soc_td3_hash_bucket_get(unit, mem, bank_ids[bank_idx],
  20311                                              entry, &bucket));
  20312                 index = soc_td3_hash_index_get(unit, mem, bank_ids[bank_idx],
  20313                                                bucket);
  20314             } else
  20315 #endif /* BCM_TRIDENT3_SUPPORT */
  20316             {
  20317                 SOC_IF_ERROR_RETURN
  20318                     (soc_trident2_hash_bank_number_get(unit, mem, bank_idx,
  20319                                                        &bank_ids[bank_idx]));
  20320                 SOC_IF_ERROR_RETURN
  20321                     (soc_hash_bucket_get(unit, mem, bank_ids[bank_idx],
  20322                                          entry, &bucket));
  20323                 index = soc_hash_index_get(unit, mem, bank_ids[bank_idx], bucket);
  20324             }
  20325             SOC_IF_ERROR_RETURN(soc_ser_hash_mem_bank_correction(unit, mem,
  20326                                                      schan_msg, index, 4));
  20327         }
  20328 #endif
  20329         break;
  20330     case HASH_MULTI:
  20331 #ifdef BCM_ISM_SUPPORT
  20332         sal_memset(&mem_banks, 0, sizeof(mem_banks));
  20333         SOC_IF_ERROR_RETURN(soc_ism_get_banks_for_mem(unit, mem, mem_banks.banks,
  20334                                        mem_banks.bank_size, &mem_banks.count));
  20335         for (bank_idx = 0; bank_idx < mem_banks.count; bank_idx++) {
  20336             bank = (uint32)1 << mem_banks.banks[bank_idx];
  20337             SOC_IF_ERROR_RETURN(soc_generic_hash(unit, mem, entry, bank, 0, &ism_index,
  20338                                                  &result, &bucket_index, &num_ent));
  20339             SOC_IF_ERROR_RETURN(soc_ser_hash_mem_bank_correction(unit, mem,
  20340                                                      schan_msg, bucket_index * num_ent,
  20341                                                      num_ent));
  20342         }
  20343 #endif
  20344         break;
  20345     default:
  20346         return SOC_E_FAIL;
  20347     }
  20348     return SOC_E_NONE;
  20349 }
  20350 #endif
  20351 
  20352 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT)
  20353 /* TH:
  20354  * For insert, delete operations to all hash tables, SER event could be only for 
  20355  * functional view (fv). rsp_word indicates index to _ECC view and not to funct
  20356  * view - and ser_correction should be invoked with correct _ECC view.
  20357  */
  20358 STATIC int
  20359 _soc_inline_ser_mem_remap(int unit, soc_mem_t *mem, int *pipe, int *iratio)
  20360 {
  20361     int out_pipe = SOC_PIPE_ANY, out_iratio = 1;
  20362     soc_mem_t out_mem = FPEM_ECCm;
  20363 
  20364     if (NULL == mem || NULL == pipe || NULL == iratio) {
  20365         return SOC_E_PARAM;
  20366     }
  20367 
  20368 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  20369     if (SOC_IS_TRIDENT3X(unit) || SOC_IS_TOMAHAWK3(unit)) {
  20370        out_mem = EXACT_MATCH_ECCm;
  20371     }
  20372 #endif
  20373 
  20374     switch (*mem) {
  20375     case L3_ENTRY_IPV4_UNICASTm:
  20376     case L3_ENTRY_ONLYm:
  20377         out_mem = L3_ENTRY_ONLY_ECCm;
  20378         break;
  20379     case L3_ENTRY_IPV4_MULTICASTm:
  20380     case L3_ENTRY_IPV6_UNICASTm:
  20381         out_mem = L3_ENTRY_ONLY_ECCm;
  20382         out_iratio = 2;
  20383         break;
  20384     case L3_ENTRY_IPV6_MULTICASTm:
  20385         out_mem = L3_ENTRY_ONLY_ECCm;
  20386         out_iratio = 4;
  20387         break;
  20388 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  20389     case L3_ENTRY_SINGLEm:
  20390         out_mem = L3_ENTRY_ECCm;
  20391         break;
  20392     case L3_ENTRY_DOUBLEm:
  20393         out_mem = L3_ENTRY_ECCm;
  20394         out_iratio = 2;
  20395         break;
  20396     case L3_ENTRY_QUADm:
  20397         out_mem = L3_ENTRY_ECCm;
  20398         out_iratio = 4;
  20399         break;
  20400     case L3_TUNNEL_SINGLEm:
  20401         out_mem = L3_TUNNEL_ECCm;
  20402         break;
  20403     case L3_TUNNEL_DOUBLEm:
  20404         out_mem = L3_TUNNEL_ECCm;
  20405         out_iratio = 2;
  20406         break;
  20407     case L3_TUNNEL_QUADm:
  20408         out_mem = L3_TUNNEL_ECCm;
  20409         out_iratio = 4;
  20410         break;
  20411 #endif
  20412     case L2Xm:
  20413 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  20414         if (SOC_IS_TRIDENT3X(unit) || SOC_IS_TOMAHAWK3(unit)) {
  20415             out_mem = L2_ENTRY_ECCm;
  20416         } else
  20417 #endif
  20418         {
  20419             out_mem = L2_ENTRY_ONLY_ECCm;
  20420         }
  20421         break;
  20422     case VLAN_MACm:
  20423     case VLAN_XLATEm:
  20424         out_mem = VLAN_XLATE_ECCm;
  20425         break;
  20426     case EGR_VLAN_XLATEm:
  20427         out_mem = EGR_VLAN_XLATE_ECCm;
  20428         break;
  20429     case MPLS_ENTRYm:
  20430 #if defined(BCM_TOMAHAWK3_SUPPORT)
  20431     case MPLS_ENTRY_SINGLEm:
  20432 #endif
  20433         out_mem = MPLS_ENTRY_ECCm;
  20434 #if defined(BCM_APACHE_SUPPORT)
  20435         if (SOC_IS_APACHE(unit)) {
  20436             /* No ECC view for MPLS_ENTRY */
  20437             out_mem = MPLS_ENTRYm;
  20438         }
  20439 #endif
  20440         break;
  20441     case EXACT_MATCH_2m:
  20442         out_iratio = 2;
  20443         break;
  20444     case EXACT_MATCH_2_PIPE0m:
  20445         out_iratio = 2;
  20446         out_pipe = 0;
  20447         break;
  20448     case EXACT_MATCH_2_PIPE1m:
  20449         out_iratio = 2;
  20450         out_pipe = 1;
  20451         break;
  20452     case EXACT_MATCH_2_PIPE2m:
  20453         out_iratio = 2;
  20454         out_pipe = 2;
  20455         break;
  20456     case EXACT_MATCH_2_PIPE3m:
  20457         out_iratio = 2;
  20458         out_pipe = 3;
  20459         break;
  20460     case EXACT_MATCH_4m:
  20461         out_iratio = 4;
  20462         break;
  20463     case EXACT_MATCH_4_PIPE0m:
  20464         out_iratio = 4;
  20465         out_pipe = 0;
  20466         break;
  20467     case EXACT_MATCH_4_PIPE1m:
  20468         out_iratio = 4;
  20469         out_pipe = 1;
  20470         break;
  20471     case EXACT_MATCH_4_PIPE2m:
  20472         out_iratio = 4;
  20473         out_pipe = 2;
  20474         break;
  20475     case EXACT_MATCH_4_PIPE3m:
  20476         out_iratio = 4;
  20477         out_pipe = 3;
  20478         break;
  20479     case ING_DNAT_ADDRESS_TYPEm:
  20480         out_mem = ING_DNAT_ADDRESS_TYPE_ECCm;
  20481         break;
  20482     case ING_VP_VLAN_MEMBERSHIPm:
  20483         out_mem = ING_VP_VLAN_MEMBERSHIP_ECCm;
  20484         break;
  20485     case EGR_VP_VLAN_MEMBERSHIPm:
  20486         out_mem = EGR_VP_VLAN_MEMBERSHIP_ECCm;
  20487         break;
  20488     case SUBPORT_ID_TO_SGPP_MAPm:
  20489         out_mem = SUBPORT_ID_TO_SGPP_MAP_ECCm;
  20490         break;
  20491     default:
  20492         out_mem = *mem;
  20493         break;
  20494     }
  20495     *mem = out_mem;
  20496     *pipe = out_pipe;
  20497     *iratio = out_iratio;
  20498 
  20499     return SOC_E_NONE;
  20500 }
  20501 #endif /* BCM_TOMAHAWK_SUPPORT */
  20502 
  20503 #if defined(BCM_GREYHOUND2_SUPPORT)
  20504 /*
  20505  * Function:
  20506  *      soc_mem_gh2_l2_sw_lookup
  20507  * Purpose:
  20508  *      Use software method to lookup a L2 entry for GH2-B0
  20509  * Parameters:
  20510  *      unit      - StrataSwitch unit #
  20511  *      mem       - L2 memory table
  20512  *      copyno    - Which copy to search (if multiple copies)
  20513  *      banks     - For dual hashing, which halves are selected (inverted)
  20514  *      key       - entry to look up
  20515  *      result    - entry to receive entire found entry
  20516  *      index_ptr - (OUT) If found, receives table index where found
  20517  * Returns:
  20518  *      SOC_E_INTERNAL if retries exceeded or other internal error
  20519  *      SOC_E_NOT_FOUND if the entry is not found.
  20520  *      SOC_E_NONE (0) on success (entry found):
  20521  * Notes:
  20522  *      Uses software lookup without using an LOOKUP message over the
  20523  *      S-Channel.
  20524  */
  20525 STATIC int
  20526 soc_mem_gh2_l2_sw_lookup(
  20527     int unit,
  20528     soc_mem_t mem,
  20529     int copyno,
  20530     int32 banks,
  20531     void *key,
  20532     void *result,
  20533     int *index_ptr)
  20534 {
  20535     int rv;
  20536     l2x_entry_t l2ent;
  20537     bcm_vlan_t new_vid, old_vid;
  20538     bcm_mac_t new_mac, old_mac;
  20539     int cf_hit;
  20540     int bank, min_bank, max_bank;
  20541     int bucket, slot, index;
  20542     int entries_per_row, entries_per_bucket;
  20543     int bucket_offset;
  20544     uint32 valid = 0, fval = 0;
  20545     int index_valid;
  20546 
  20547     if (mem != L2Xm) {
  20548         return SOC_E_INTERNAL;
  20549     }
  20550 
  20551     if (index_ptr) {
  20552         *index_ptr = -1;
  20553     }
  20554 
  20555     if (banks == SOC_MEM_HASH_BANK0_ONLY) {
  20556         min_bank = max_bank = 0;
  20557     } else if (banks == SOC_MEM_HASH_BANK1_ONLY) {
  20558         min_bank = max_bank = 1;
  20559     } else {
  20560         min_bank = 0;
  20561         max_bank = 1;
  20562     }
  20563 
  20564     cf_hit = -1;
  20565 
  20566     entries_per_row = SOC_L2X_BUCKET_SIZE;
  20567     entries_per_bucket = entries_per_row / 2;
  20568 
  20569     MEM_LOCK(unit, mem);
  20570     for (bank = min_bank; bank <= max_bank; bank++) {
  20571         bucket_offset = bank * entries_per_bucket;
  20572         bucket = soc_tr_l2x_bank_entry_hash(unit, bank, (uint32 *)key);
  20573         for (slot = 0; slot < entries_per_bucket; slot++) {
  20574             index = (bucket * entries_per_row) + bucket_offset + slot;
  20575             rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &l2ent);
  20576             if (SOC_FAILURE(rv)) {
  20577                 MEM_UNLOCK(unit, mem);
  20578                 return rv;
  20579             }
  20580 
  20581             valid = soc_L2Xm_field32_get(unit, &l2ent, VALIDf);
  20582             if (!valid) {
  20583                 continue;
  20584             }
  20585 
  20586             fval = soc_L2Xm_field32_get(unit, &l2ent, KEY_TYPEf);
  20587             if (fval != GH2_L2_HASH_KEY_TYPE_VFI_MULTICAST) {
  20588                 continue;
  20589             }
  20590 
  20591             /* Get existing L2 entry */
  20592             soc_L2Xm_mac_addr_get(unit, &l2ent, MAC_ADDRf, old_mac);
  20593             old_vid = soc_L2Xm_field32_get(unit, &l2ent, VLAN_IDf);
  20594 
  20595             /* Get lookup L2 entry */
  20596             soc_L2Xm_mac_addr_get(unit, (l2x_entry_t *)key,
  20597                                   MAC_ADDRf, new_mac);
  20598             new_vid = soc_L2Xm_field32_get(unit, (l2x_entry_t *)key,
  20599                                            VLAN_IDf);
  20600 
  20601             if ((sal_memcmp(old_mac, new_mac, sizeof(bcm_mac_t)) == 0) &&
  20602                 (new_vid == old_vid)) {
  20603                 /* Found entry */
  20604                 cf_hit = index;
  20605                 break;
  20606             }
  20607         }
  20608 
  20609         if (cf_hit != -1) {
  20610             break;
  20611         }
  20612     }
  20613 
  20614     if (cf_hit >= 0) {
  20615         index = cf_hit; /* Found entry index */
  20616         if (result != NULL) {
  20617             sal_memcpy(result, &l2ent, sizeof(l2x_entry_t));
  20618         }
  20619     } else {
  20620         /* Entry not found */
  20621         LOG_INFO(BSL_LS_SOC_SOCMEM,
  20622                  (BSL_META_U(unit,
  20623                              "Lookup table[%s]: Not found\n"),
  20624                   SOC_MEM_NAME(unit, mem)));
  20625         MEM_UNLOCK(unit, mem);
  20626         return SOC_E_NOT_FOUND;
  20627     }
  20628 
  20629     if (index_ptr != NULL) {
  20630         *index_ptr = index;
  20631     }
  20632 
  20633     index_valid = (index >= 0 &&
  20634                    index <= soc_mem_index_max(unit, mem));
  20635     if (!index_valid) {
  20636         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  20637                   (BSL_META_U(unit,
  20638                               "soc_mem_generic_lookup: "
  20639                               "invalid index %d for memory %s\n"),
  20640                    index, SOC_MEM_NAME(unit, mem)));
  20641         rv = SOC_E_INTERNAL;
  20642     }
  20643 
  20644     LOG_INFO(BSL_LS_SOC_SOCMEM,
  20645              (BSL_META_U(unit,
  20646                          "Lookup table[%s]: bank=%d (index=%d)\n"),
  20647               SOC_MEM_NAME(unit, mem), bank, index));
  20648 
  20649     MEM_UNLOCK(unit, mem);
  20650     return rv;
  20651 
  20652 }
  20653 
  20654 /*
  20655  * Function:
  20656  *      soc_mem_gh2_l2_sw_insert
  20657  * Purpose:
  20658  *      Use software method to insert a L2 entry for GH2-B0
  20659  * Parameters:
  20660  *      unit      - StrataSwitch unit #
  20661  *      mem       - L2 memory table
  20662  *      copyno    - Which copy to search (if multiple copies)
  20663  *      banks     - For dual hashing, which halves are selected (inverted)
  20664  *      entry     - entry to insert
  20665  *      old_entry - old entry if existing entry was replaced
  20666  *      index_ptr - (OUT) If entry found gets the location of the entry.
  20667  *                  If not found, and table is sorted, gets the
  20668  *                  location of the insertion point.
  20669  *                  CAN NO LONGER BE NULL.
  20670  * Returns:
  20671  *      SOC_E_NONE - success
  20672  *      SOC_E_EXISTS - existing entry was replaced
  20673  *      SOC_E_FULL - full
  20674  * Notes:
  20675  *      Uses software insertion without using an INSERT message over the
  20676  *      S-Channel.
  20677  */
  20678 STATIC int
  20679 soc_mem_gh2_l2_sw_insert(
  20680     int unit,
  20681     soc_mem_t mem,
  20682     int copyno,
  20683     int32 banks,
  20684     void *entry,
  20685     void *old_entry,
  20686     int *index_ptr)
  20687 {
  20688     int rv;
  20689     l2x_entry_t l2ent;
  20690     bcm_vlan_t new_vid, old_vid;
  20691     bcm_mac_t new_mac, old_mac;
  20692     int cf_hit, cf_unhit;
  20693     int bank, min_bank, max_bank;
  20694     int bucket, slot, index;
  20695     int entries_per_row, entries_per_bucket;
  20696     int bucket_offset;
  20697     uint32 valid = 0, fval = 0;
  20698     int entry_dw = 0, index_valid;
  20699     uint8 *vmap;
  20700     uint32 *cache;
  20701 
  20702     if (mem != L2Xm) {
  20703         return SOC_E_INTERNAL;
  20704     }
  20705 
  20706     entry_dw = soc_mem_entry_words(unit, mem);
  20707 
  20708     if (index_ptr) {
  20709         *index_ptr = -1;
  20710     }
  20711 
  20712     if (banks == SOC_MEM_HASH_BANK0_ONLY) {
  20713         min_bank = max_bank = 0;
  20714     } else if (banks == SOC_MEM_HASH_BANK1_ONLY) {
  20715         min_bank = max_bank = 1;
  20716     } else {
  20717         min_bank = 0;
  20718         max_bank = 1;
  20719     }
  20720 
  20721     cf_hit = cf_unhit = -1;
  20722 
  20723     entries_per_row = SOC_L2X_BUCKET_SIZE;
  20724     entries_per_bucket = entries_per_row / 2;
  20725 
  20726     MEM_LOCK(unit, mem);
  20727     for (bank = min_bank; bank <= max_bank; bank++) {
  20728         bucket_offset = bank * entries_per_bucket;
  20729         bucket = soc_tr_l2x_bank_entry_hash(unit, bank, (uint32 *)entry);
  20730         for (slot = 0; slot < entries_per_bucket; slot++) {
  20731             index = (bucket * entries_per_row) + bucket_offset + slot;
  20732             rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &l2ent);
  20733             if (SOC_FAILURE(rv)) {
  20734                 MEM_UNLOCK(unit, mem);
  20735                 return rv;
  20736             }
  20737 
  20738             valid = soc_L2Xm_field32_get(unit, &l2ent, VALIDf);
  20739             if (!valid) {
  20740                 /* Found invalid entry - stop the search victim found */
  20741                 cf_unhit = index;
  20742                 break;
  20743             }
  20744 
  20745             fval = soc_L2Xm_field32_get(unit, &l2ent, KEY_TYPEf);
  20746             if (fval != GH2_L2_HASH_KEY_TYPE_VFI_MULTICAST) {
  20747                 continue;
  20748             }
  20749 
  20750             /* Get existing L2 entry */
  20751             soc_L2Xm_mac_addr_get(unit, &l2ent, MAC_ADDRf, old_mac);
  20752             old_vid = soc_L2Xm_field32_get(unit, &l2ent, VLAN_IDf);
  20753 
  20754             /* Get new insert L2 entry */
  20755             soc_L2Xm_mac_addr_get(unit, (l2x_entry_t *)entry,
  20756                                   MAC_ADDRf, new_mac);
  20757             new_vid = soc_L2Xm_field32_get(unit, (l2x_entry_t *)entry,
  20758                                            VLAN_IDf);
  20759 
  20760             if ((sal_memcmp(old_mac, new_mac, sizeof(bcm_mac_t)) == 0) &&
  20761                 (new_vid == old_vid)) {
  20762                 /* Found existing entry */
  20763                 cf_hit = index;
  20764                 break;
  20765             }
  20766         }
  20767 
  20768         if ((cf_unhit != -1) || (cf_hit != -1)) {
  20769             break;
  20770         }
  20771     }
  20772 
  20773     if (cf_unhit >= 0) {
  20774         index = cf_unhit; /* take first hit invalid entry */
  20775     } else if (cf_hit >= 0) {
  20776         index = cf_hit; /* or first hit with the same entry */
  20777     } else {
  20778         /* no slot to insert */
  20779         LOG_INFO(BSL_LS_SOC_SOCMEM,
  20780                  (BSL_META_U(unit,
  20781                              "Insert table[%s]: hash bucket full\n"),
  20782                   SOC_MEM_NAME(unit, mem)));
  20783         MEM_UNLOCK(unit, mem);
  20784         return SOC_E_FULL;
  20785     }
  20786 
  20787     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, entry);
  20788     if (SOC_FAILURE(rv)) {
  20789         MEM_UNLOCK(unit, mem);
  20790         return rv;
  20791     }
  20792 
  20793     if (index_ptr != NULL) {
  20794         *index_ptr = index;
  20795     }
  20796 
  20797     if (cf_hit >= 0) {
  20798         if (old_entry != NULL) {
  20799             sal_memcpy(old_entry, &l2ent, sizeof(l2x_entry_t));
  20800         }
  20801         rv = SOC_E_EXISTS;
  20802     }
  20803 
  20804     SOP_MEM_STATE(unit, mem).count[copyno]++;
  20805 
  20806     /* Update cache if active */
  20807     cache = SOC_MEM_STATE(unit, mem).cache[copyno];
  20808     vmap = SOC_MEM_STATE(unit, mem).vmap[copyno];
  20809     index_valid = (index >= 0 &&
  20810                    index <= soc_mem_index_max(unit, mem));
  20811     if (!index_valid) {
  20812         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  20813                   (BSL_META_U(unit,
  20814                               "soc_mem_generic_insert: "
  20815                               "invalid index %d for memory %s\n"),
  20816                    index, SOC_MEM_NAME(unit, mem)));
  20817         rv = SOC_E_INTERNAL;
  20818     } else if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)) {
  20819         /* If an invalid or non-static entry is being written then clear the cache */
  20820         if ((soc_L2Xm_field32_get(unit, entry, VALIDf)) &&
  20821             (soc_L2Xm_field32_get(unit, entry, STATIC_BITf))) {
  20822             sal_memcpy(cache + index * entry_dw, entry, entry_dw * 4);
  20823             CACHE_VMAP_SET(vmap, index);
  20824         } else {
  20825             CACHE_VMAP_CLR(vmap, index);
  20826         }
  20827     }
  20828 
  20829     MEM_UNLOCK(unit, mem);
  20830     return rv;
  20831 
  20832 }
  20833 
  20834 /*
  20835  * Function:
  20836  *      soc_mem_gh2_l2_sw_delete
  20837  * Purpose:
  20838  *      Use software method to delete a L2 entry for GH2-B0
  20839  * Parameters:
  20840  *      unit      - StrataSwitch unit #
  20841  *      mem       - L2 memory table
  20842  *      copyno    - Which copy to search (if multiple copies)
  20843  *      banks     - For dual hashing, which halves are selected (inverted)
  20844  *      entry     - entry to delete
  20845  *      old_entry - old entry if existing entry was found
  20846  *      index_ptr - (OUT) If entry found gets the location of the entry.
  20847  * Returns:
  20848  *      SOC_E_NONE - success
  20849  *      SOC_E_NOT_FOUND - fail
  20850  * Notes:
  20851  *      Uses software deletion without using an DELETE message over the
  20852  *      S-Channel.
  20853  */
  20854 STATIC int
  20855 soc_mem_gh2_l2_sw_delete(
  20856     int unit,
  20857     soc_mem_t mem,
  20858     int copyno,
  20859     int32 banks,
  20860     void *entry,
  20861     void *old_entry,
  20862     int *index_ptr)
  20863 {
  20864     int rv;
  20865     l2x_entry_t l2ent, null_l2ent;
  20866     bcm_vlan_t new_vid, old_vid;
  20867     bcm_mac_t new_mac, old_mac;
  20868     int cf_hit;
  20869     int bank, min_bank, max_bank;
  20870     int bucket, slot, index;
  20871     int entries_per_row, entries_per_bucket;
  20872     int bucket_offset;
  20873     uint32 valid = 0, fval = 0;
  20874     int index_valid;
  20875     uint8 *vmap;
  20876     uint32 *cache;
  20877 
  20878     if (mem != L2Xm) {
  20879         return SOC_E_INTERNAL;
  20880     }
  20881 
  20882     if (index_ptr) {
  20883         *index_ptr = -1;
  20884     }
  20885 
  20886     if (banks == SOC_MEM_HASH_BANK0_ONLY) {
  20887         min_bank = max_bank = 0;
  20888     } else if (banks == SOC_MEM_HASH_BANK1_ONLY) {
  20889         min_bank = max_bank = 1;
  20890     } else {
  20891         min_bank = 0;
  20892         max_bank = 1;
  20893     }
  20894 
  20895     cf_hit = -1;
  20896 
  20897     entries_per_row = SOC_L2X_BUCKET_SIZE;
  20898     entries_per_bucket = entries_per_row / 2;
  20899 
  20900     MEM_LOCK(unit, mem);
  20901     for (bank = min_bank; bank <= max_bank; bank++) {
  20902         bucket_offset = bank * entries_per_bucket;
  20903         bucket = soc_tr_l2x_bank_entry_hash(unit, bank, (uint32 *)entry);
  20904         for (slot = 0; slot < entries_per_bucket; slot++) {
  20905             index = (bucket * entries_per_row) + bucket_offset + slot;
  20906             rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &l2ent);
  20907             if (SOC_FAILURE(rv)) {
  20908                 MEM_UNLOCK(unit, mem);
  20909                 return rv;
  20910             }
  20911 
  20912             valid = soc_L2Xm_field32_get(unit, &l2ent, VALIDf);
  20913             if (!valid) {
  20914                 continue;
  20915             }
  20916 
  20917             fval = soc_L2Xm_field32_get(unit, &l2ent, KEY_TYPEf);
  20918             if (fval != GH2_L2_HASH_KEY_TYPE_VFI_MULTICAST) {
  20919                 continue;
  20920             }
  20921 
  20922             /* Get existing L2 entry */
  20923             soc_L2Xm_mac_addr_get(unit, &l2ent, MAC_ADDRf, old_mac);
  20924             old_vid = soc_L2Xm_field32_get(unit, &l2ent, VLAN_IDf);
  20925 
  20926             /* Get deleted L2 entry */
  20927             soc_L2Xm_mac_addr_get(unit, (l2x_entry_t *)entry,
  20928                                   MAC_ADDRf, new_mac);
  20929             new_vid = soc_L2Xm_field32_get(unit, (l2x_entry_t *)entry,
  20930                                            VLAN_IDf);
  20931 
  20932             if ((sal_memcmp(old_mac, new_mac, sizeof(bcm_mac_t)) == 0) &&
  20933                 (new_vid == old_vid)) {
  20934                 /* Found entry */
  20935                 cf_hit = index;
  20936                 break;
  20937             }
  20938         }
  20939 
  20940         if (cf_hit != -1) {
  20941             break;
  20942         }
  20943     }
  20944 
  20945     if (cf_hit >= 0) {
  20946         index = cf_hit; /* Found entry index */
  20947     } else {
  20948         /* Entry not found */
  20949         LOG_INFO(BSL_LS_SOC_SOCMEM,
  20950                  (BSL_META_U(unit,
  20951                              "Delete table[%s]: Not found\n"),
  20952                   SOC_MEM_NAME(unit, mem)));
  20953         MEM_UNLOCK(unit, mem);
  20954         return SOC_E_NOT_FOUND;
  20955     }
  20956 
  20957     sal_memcpy(&null_l2ent, soc_mem_entry_null(unit, mem),
  20958                sizeof(l2x_entry_t));
  20959     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, (uint32 *)&null_l2ent);
  20960     if (SOC_FAILURE(rv)) {
  20961         MEM_UNLOCK(unit, mem);
  20962         return rv;
  20963     }
  20964 
  20965     if (index_ptr != NULL) {
  20966         *index_ptr = index;
  20967     }
  20968 
  20969     if (cf_hit >= 0) {
  20970         if (old_entry != NULL) {
  20971             sal_memcpy(old_entry, &l2ent, sizeof(l2x_entry_t));
  20972         }
  20973         rv = SOC_E_NONE;
  20974     }
  20975 
  20976     SOP_MEM_STATE(unit, mem).count[copyno]--;
  20977 
  20978     if (!SOC_WARM_BOOT(unit)) {
  20979         /* Update cache if active */
  20980         cache = SOC_MEM_STATE(unit, mem).cache[copyno];
  20981         vmap = SOC_MEM_STATE(unit, mem).vmap[copyno];
  20982         index_valid = (index >= 0 &&
  20983                        index <= soc_mem_index_max(unit, mem));
  20984         if (!index_valid) {
  20985             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  20986                   (BSL_META_U(unit,
  20987                               "soc_mem_generic_delete: "
  20988                               "invalid index %d for memory %s\n"),
  20989                    index, SOC_MEM_NAME(unit, mem)));
  20990             MEM_UNLOCK(unit, mem);
  20991             return SOC_E_INTERNAL;
  20992         }
  20993 
  20994         if (index_valid && cache != NULL && CACHE_VMAP_TST(vmap, index) &&
  20995             !SOC_MEM_TEST_SKIP_CACHE(unit)) {
  20996             CACHE_VMAP_CLR(vmap, index);
  20997         }
  20998     }
  20999 
  21000     MEM_UNLOCK(unit, mem);
  21001     return rv;
  21002 
  21003 }
  21004 #endif /* BCM_GREYHOUND2_SUPPORT */
  21005 
  21006 /*
  21007  * Function:
  21008  *      soc_mem_generic_insert
  21009  * Purpose:
  21010  *      Insert an entry
  21011  * Parameters:
  21012  *      unit - StrataSwitch unit #
  21013  *      banks - For dual hashing, which halves are selected (inverted)
  21014  *              Note: used to create a bitmap for ISM mems. (All banks: -1)
  21015  *      entry - entry to insert
  21016  *      old_entry - old entry if existing entry was replaced
  21017  * Returns:
  21018  *      SOC_E_NONE - success
  21019  *      SOC_E_EXISTS - existing entry was replaced
  21020  *      SOC_E_FULL - full
  21021  *      SOC_E_BUSY - modfifo full
  21022  * Notes:
  21023  *      Uses hardware insertion; sends an INSERT message over the
  21024  *      S-Channel.
  21025  */
  21026 
  21027 int
  21028 soc_mem_generic_insert(int unit, soc_mem_t mem, int copyno, int32 banks,
  21029                        void *entry, void *old_entry, int *index_ptr)
  21030 {
  21031     schan_msg_t schan_msg;
  21032 #ifdef BCM_ESW_SUPPORT
  21033     schan_msg_t schan_msg_cpy;
  21034 #endif /* BCM_ESW_SUPPORT */
  21035     int         rv, index_valid;
  21036     int         entry_dw = 0;
  21037     uint8       at, *vmap;
  21038     int         type, err_info, index, allow_intr=0;
  21039     uint32      *data, *cache;
  21040     int         src_blk, dst_blk, acc_type, data_byte_len;
  21041     int         opcode, nack;
  21042     uint32      bank_ignore_mask;
  21043 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  21044     int         rv1 = SOC_E_NONE;
  21045 #endif
  21046 
  21047 #ifdef BCM_ESW_SUPPORT
  21048     uint8       insert_retry_attempt = 0;
  21049 #endif
  21050 #ifdef BCM_TRX_SUPPORT
  21051     uint8       insert_retry = 0;
  21052 #endif
  21053 
  21054 #ifdef BCM_TRIDENT2PLUS_SUPPORT
  21055     uint8       insert_full_retry_attempt = 0;
  21056 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
  21057 
  21058 #if defined(BCM_TRIUMPH3_SUPPORT)
  21059     int             ins_disable = FALSE, try_one_time = 1;
  21060     uint32          l2_insert = 0;
  21061 #endif
  21062 
  21063 #if defined(BCM_HURRICANE3_SUPPORT)
  21064     uint32      overflow_index = 0;
  21065 #endif /* BCM_HURRICANE3_SUPPORT */
  21066 #if defined(BCM_GREYHOUND2_SUPPORT)
  21067     uint32 key_type = 0;
  21068 #endif /* BCM_GREYHOUND2_SUPPORT */
  21069 
  21070 #ifdef BCM_TOMAHAWK3_SUPPORT
  21071     int j;
  21072     uint16 dev_id;
  21073     uint8 rev_id;
  21074     schan_msg_t schan_msg_dupl;
  21075 #endif
  21076 
  21077     _SOC_MEM_REPLACE_MEM(unit, mem);
  21078     SOC_MEM_ALIAS_TO_ORIG(unit,mem);
  21079     assert(SOC_MEM_IS_VALID(unit, mem));
  21080     assert(soc_attached(unit));
  21081 #ifdef BCM_TOMAHAWK3_SUPPORT
  21082     soc_cm_get_id(unit, &dev_id, &rev_id);
  21083 #endif
  21084 
  21085     if (copyno == MEM_BLOCK_ANY) {
  21086         copyno = SOC_MEM_BLOCK_ANY(unit, mem);
  21087     }
  21088     if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) {
  21089         LOG_WARN(BSL_LS_SOC_SOCMEM,
  21090                  (BSL_META_U(unit,
  21091                              "soc_mem_generic_insert: invalid block %d for memory %s\n"),
  21092                   copyno, SOC_MEM_NAME(unit, mem)));
  21093         return SOC_E_PARAM;
  21094     }
  21095 
  21096     if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) {
  21097         LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  21098                             "Insert table[%s]: banks=%d"), SOC_MEM_NAME(unit, mem),
  21099                  banks));
  21100         if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) {
  21101             soc_mem_entry_dump(unit, mem, entry, BSL_VERBOSE|BSL_LS_SOC_COMMON);
  21102         }
  21103         LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  21104                             "\n")));
  21105     }
  21106 
  21107     entry_dw = soc_mem_entry_words(unit, mem);
  21108 
  21109 
  21110 #if defined(BCM_TRIDENT2_SUPPORT)
  21111     if (soc_feature(unit, soc_feature_shared_hash_ins) &&
  21112         !SOC_IS_TOMAHAWKX(unit) && !SOC_IS_TRIDENT3X(unit) &&
  21113         (mem == L3_ENTRY_IPV4_MULTICASTm || mem == L3_ENTRY_IPV6_UNICASTm)) {
  21114         int ok = 0, index, bix;
  21115         int num_banks, bank_ids[7];
  21116         int bank_indexes[7] = {-1, -1, -1, -1, -1, -1, -1};
  21117 
  21118         /* Retreive applicable bank map and first try replace on each */
  21119 
  21120         {
  21121             SOC_IF_ERROR_RETURN
  21122                 (soc_trident2_hash_bank_count_get(unit, mem, &num_banks));
  21123         }
  21124 
  21125         if (banks != SOC_MEM_HASH_BANK_ALL) {
  21126             num_banks = 1;
  21127         }
  21128         MEM_LOCK(unit, mem);
  21129         for (bix = 0; bix < num_banks; bix++) {
  21130             int32 bid;
  21131 
  21132             {
  21133                 rv1 = (soc_trident2_hash_bank_number_get(unit, mem, bix,
  21134                                                          &bank_ids[bix]));
  21135             }
  21136             if (SOC_FAILURE(rv1)) {
  21137                 MEM_UNLOCK(unit, mem);
  21138                 return rv1;
  21139             }
  21140             bid = 1 << bank_ids[bix];
  21141             if (banks != SOC_MEM_HASH_BANK_ALL) {
  21142                 bid = banks;
  21143             }
  21144             rv1 = soc_mem_generic_lookup(unit, mem, copyno, bid,
  21145                                          entry, NULL, &index);
  21146             LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
  21147                         (BSL_META_U(unit,
  21148                                     "Sh-Ins-Lukp: bank[%d] "
  21149                                     "rv[%d] index[%d]\n"),
  21150                          bid, rv1, index));
  21151             if (SOC_FAILURE(rv1)) {
  21152                 if (rv1 == SOC_E_NOT_FOUND) {
  21153                     /* Entry not found. Save index and move on to the next bank */
  21154                     bank_indexes[bix] = index;
  21155                     continue;
  21156                 } else {
  21157                     MEM_UNLOCK(unit, mem);
  21158                     return rv1;
  21159                 }
  21160             }
  21161             /* Replace entry */
  21162             if (old_entry) {
  21163                 rv1 = soc_mem_read(unit, mem, copyno, index, old_entry);
  21164                 if (SOC_FAILURE(rv1)) {
  21165                     MEM_UNLOCK(unit, mem);
  21166                     return rv1;
  21167                 }
  21168             }
  21169             rv1 = soc_mem_write(unit, mem, copyno, index, entry);
  21170             if (SOC_FAILURE(rv1)) {
  21171                 MEM_UNLOCK(unit, mem);
  21172                 return rv1;
  21173             }
  21174             if (index_ptr) {
  21175                 *index_ptr = index;
  21176             }
  21177             ok = 1; 
  21178            /* rv = SOC_E_EXISTS; Overwritten later. Coverity complains */
  21179             LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
  21180                         (BSL_META_U(unit,
  21181                                     "Sh-Ins-Lukp: "
  21182                                     "replace at index:%d\n"), index));
  21183             break;
  21184         }
  21185         if (!ok) {
  21186             /* If replace did not happen then try a fresh insert */
  21187             for (bix = 0; bix < num_banks; bix++) {
  21188                 uint32 bkt[SOC_MAX_MEM_WORDS];
  21189 
  21190                 index = bank_indexes[bix];
  21191                 if (index < 0) {
  21192                     continue;
  21193                 }
  21194                 rv1 = soc_mem_read(unit, L3_ENTRY_IPV6_MULTICASTm, copyno,
  21195                                    index, bkt);
  21196                 if (SOC_FAILURE(rv1)) {
  21197                     MEM_UNLOCK(unit, mem);
  21198                     return rv1;
  21199                 } else {
  21200                     uint32 v0, v1;
  21201 
  21202                     soc_mem_field_get(unit, L3_ENTRY_IPV6_MULTICASTm, bkt,
  21203                                       VALID_0f, &v0);
  21204                     soc_mem_field_get(unit, L3_ENTRY_IPV6_MULTICASTm, bkt,
  21205                                       VALID_1f, &v1);
  21206                     if ((v0 == 0) && (v1 == 0)) {
  21207                         index *= 2;
  21208                         rv1 = soc_mem_write(unit, mem, copyno, index, entry);
  21209                         if (SOC_FAILURE(rv1)) {
  21210                             MEM_UNLOCK(unit, mem);
  21211                             return rv1;
  21212                         }
  21213                         if (index_ptr) {
  21214                             *index_ptr = index;
  21215                         }
  21216                         ok = 1; rv = SOC_E_NONE;
  21217                         LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
  21218                                     (BSL_META_U(unit,
  21219                                                 "Sh-Ins-Lukp: "
  21220                                                 "insert at index:%d\n"), index));
  21221                         break;
  21222                     } else {
  21223                         soc_mem_field_get(unit, L3_ENTRY_IPV6_MULTICASTm, bkt,
  21224                                           VALID_2f, &v0);
  21225                         soc_mem_field_get(unit, L3_ENTRY_IPV6_MULTICASTm, bkt,
  21226                                           VALID_3f, &v1);
  21227                         if ((v0 == 0) && (v1 == 0)) {
  21228                             index = index*2 + 1;
  21229                             rv1 = soc_mem_write(unit, mem, copyno, index, entry);
  21230                             if (SOC_FAILURE(rv1)) {
  21231                                 MEM_UNLOCK(unit, mem);
  21232                                 return rv1;
  21233                             }
  21234                             if (index_ptr) {
  21235                                 *index_ptr = index;
  21236                             }
  21237                             ok = 1; rv = SOC_E_NONE;
  21238                             LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
  21239                                         (BSL_META_U(unit,
  21240                                                     "Sh-Ins-Lukp: "
  21241                                                     "insert at index:%d\n"), index));
  21242                             break;
  21243                         }
  21244                     }
  21245                 }
  21246             }
  21247         }
  21248         if (!ok) {
  21249             MEM_UNLOCK(unit, mem);
  21250             return SOC_E_FULL;
  21251         }
  21252 
  21253         SOP_MEM_STATE(unit, mem).count[copyno]++;
  21254 
  21255         /* Update cache if active */
  21256         cache = SOC_MEM_STATE(unit, mem).cache[copyno];
  21257         vmap = SOC_MEM_STATE(unit, mem).vmap[copyno];
  21258         index_valid = (index >= 0 &&
  21259                        index <= soc_mem_index_max(unit, mem));
  21260         if (!index_valid) {
  21261             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  21262                       (BSL_META_U(unit,
  21263                                   "soc_mem_generic_insert: "
  21264                                   "invalid index %d for memory %s\n"),
  21265                        index, SOC_MEM_NAME(unit, mem)));
  21266             rv = SOC_E_INTERNAL;
  21267         } else if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)) {
  21268             sal_memcpy(cache + index * entry_dw, entry, entry_dw * 4);
  21269             CACHE_VMAP_SET(vmap, index);
  21270         }
  21271         MEM_UNLOCK(unit, mem);
  21272         return SOC_E_NONE;
  21273     }
  21274 #endif /* BCM_TRIDENT2_SUPPORT */
  21275 
  21276 #if defined(BCM_GREYHOUND2_SUPPORT)
  21277     if (soc_feature(unit, soc_feature_vxlan_lite_riot) && (mem == L2Xm)) {
  21278         key_type = soc_mem_field32_get(unit, mem, entry, KEY_TYPEf);
  21279         /* Use SW to insert a L2 entry when key_type is VFI_MULTICAST */
  21280         if (key_type == GH2_L2_HASH_KEY_TYPE_VFI_MULTICAST) {
  21281             return soc_mem_gh2_l2_sw_insert(unit, mem, copyno, banks,
  21282                                             entry, old_entry, index_ptr);
  21283         }
  21284     }
  21285 #endif /* BCM_GREYHOUND2_SUPPORT */
  21286 
  21287     MEM_LOCK(unit, mem);
  21288 #if defined(BCM_TRIUMPH3_SUPPORT)
  21289     if (soc_feature(unit, soc_feature_esm_correction) &&
  21290           ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  21291          (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  21292         SOC_ESM_LOCK(unit);
  21293     }
  21294 #endif
  21295     schan_msg_clear(&schan_msg);
  21296     acc_type = SOC_MEM_ACC_TYPE(unit, mem);
  21297     src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit));
  21298     dst_blk = SOC_BLOCK2SCH(unit, copyno);
  21299     if ((soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) ||
  21300         (soc_feature(unit, soc_feature_shared_hash_mem) && ((mem == L2Xm) ||
  21301          (mem == L3_ENTRY_ONLYm) || (mem == L3_ENTRY_IPV4_UNICASTm) ||
  21302          (mem == L3_ENTRY_IPV4_MULTICASTm) || (mem == L3_ENTRY_IPV6_UNICASTm) ||
  21303          (mem == L3_ENTRY_IPV6_MULTICASTm)
  21304 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  21305          || (mem == L3_ENTRY_SINGLEm) || (mem == L3_ENTRY_DOUBLEm)
  21306          || (mem == L3_ENTRY_QUADm) || (mem == MPLS_ENTRY_SINGLEm)
  21307 #endif
  21308 #if defined(BCM_TOMAHAWK3_SUPPORT)
  21309          || (mem == L3_TUNNEL_SINGLEm) || (mem == L3_TUNNEL_DOUBLEm)
  21310          || (mem == L3_TUNNEL_QUADm)
  21311 #endif
  21312 #if defined(BCM_TRIDENT3_SUPPORT)
  21313          || (mem == VLAN_XLATE_1_SINGLEm)
  21314          || (mem == VLAN_XLATE_1_DOUBLEm)
  21315          || (mem == EGR_VLAN_XLATE_1_SINGLEm)
  21316          || (mem == EGR_VLAN_XLATE_1_DOUBLEm)
  21317          || (mem == VLAN_XLATE_2_SINGLEm)
  21318          || (mem == VLAN_XLATE_2_DOUBLEm)
  21319          || (mem == EGR_VLAN_XLATE_2_SINGLEm)
  21320          || (mem == EGR_VLAN_XLATE_2_DOUBLEm)
  21321 #endif
  21322 #if defined(BCM_TOMAHAWK_SUPPORT)
  21323          || _SOC_MEM_CHK_FPEM_MEM(mem)
  21324 #endif
  21325        ))) {
  21326         /* don't set bank id in cos */
  21327         bank_ignore_mask = 0;
  21328     } else {
  21329         bank_ignore_mask = banks & 0x3;
  21330     }
  21331     data_byte_len = entry_dw * 4;
  21332 
  21333     schan_msg.gencmd.address = soc_mem_addr_get(unit, mem, 0, copyno, 0, &at);
  21334     if ((soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) ||
  21335         (soc_feature(unit, soc_feature_shared_hash_mem) && ((mem == L2Xm) ||
  21336          (mem == L3_ENTRY_ONLYm) || (mem == L3_ENTRY_IPV4_UNICASTm) ||
  21337          (mem == L3_ENTRY_IPV4_MULTICASTm) || (mem == L3_ENTRY_IPV6_UNICASTm) ||
  21338          (mem == L3_ENTRY_IPV6_MULTICASTm)
  21339 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  21340          || (mem == L3_ENTRY_SINGLEm) || (mem == L3_ENTRY_DOUBLEm)
  21341          || (mem == L3_ENTRY_QUADm) || (mem == MPLS_ENTRY_SINGLEm)
  21342 #endif
  21343 #if defined(BCM_TOMAHAWK3_SUPPORT)
  21344          || (mem == L3_TUNNEL_SINGLEm) || (mem == L3_TUNNEL_DOUBLEm)
  21345          || (mem == L3_TUNNEL_QUADm)
  21346 #endif
  21347 #if defined(BCM_TRIDENT3_SUPPORT)
  21348          || (mem == VLAN_XLATE_1_SINGLEm)
  21349          || (mem == VLAN_XLATE_1_DOUBLEm)
  21350          || (mem == EGR_VLAN_XLATE_1_SINGLEm)
  21351          || (mem == EGR_VLAN_XLATE_1_DOUBLEm)
  21352          || (mem == VLAN_XLATE_2_SINGLEm)
  21353          || (mem == VLAN_XLATE_2_DOUBLEm)
  21354          || (mem == EGR_VLAN_XLATE_2_SINGLEm)
  21355          || (mem == EGR_VLAN_XLATE_2_DOUBLEm)
  21356          || (mem == MPLS_ENTRYm)
  21357 #endif
  21358 #if defined(BCM_TOMAHAWK_SUPPORT)
  21359          || _SOC_MEM_CHK_FPEM_MEM(mem)
  21360 #endif
  21361        ))) {
  21362         /* set bank ignore mask in lower 20 bits */
  21363         if (banks && banks != SOC_MEM_HASH_BANK_ALL) {
  21364             if (soc_feature(unit, soc_feature_shared_hash_mem)) {
  21365                 schan_msg.gencmd.address |= (~banks & SOC_HASH_BANK_MASK_SHARED);
  21366             } else {
  21367 #ifdef BCM_TRIUMPH3_SUPPORT
  21368                 uint32 phy_banks = soc_ism_get_phy_bank_mask(unit, banks);
  21369                 schan_msg.gencmd.address |= (~phy_banks & SOC_HASH_BANK_MASK_ISM);
  21370 #endif /* BCM_TRIUMPH3_SUPPORT */
  21371             }
  21372         }
  21373     }
  21374 #ifdef BCM_TOMAHAWK3_SUPPORT
  21375     if (acc_type == 16 && (dev_id == BCM56983_DEVICE_ID)) {
  21376         acc_type = 0;
  21377     } else if ((acc_type == 14 || acc_type == 9) && (dev_id == BCM56983_DEVICE_ID)) {
  21378         sal_memcpy(&schan_msg_dupl, &schan_msg, sizeof(schan_msg));
  21379   
  21380   
  21381         /*
  21382          * Execute S-Channel "table insert" command packet consisting of
  21383          * (header word + address word + entry_dw), and read back
  21384          * (header word + response word + entry_dw) data words.
  21385          */
  21386         if (2 + entry_dw > CMIC_SCHAN_WORDS(unit)) {
  21387             LOG_WARN(BSL_LS_SOC_SOCMEM,
  21388                     (BSL_META_U(unit,
  21389                                "soc_mem_generic_insert: assert will fail for memory %s\n"),
  21390                                 SOC_MEM_NAME(unit, mem)));
  21391         }
  21392         for (j = 0; j < 4 ; j++) {
  21393             switch(j) {
  21394                 case 0 : acc_type = 0;
  21395                          break;
  21396                 case 1 : acc_type = 1;
  21397                          break;
  21398                 case 2 : acc_type = 6;
  21399                          break;
  21400                 case 3 : acc_type = 7;
  21401                          break;
  21402             }
  21403             sal_memcpy(&schan_msg, &schan_msg_dupl, sizeof(schan_msg));
  21404             soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_INSERT_CMD_MSG,
  21405                                      dst_blk, src_blk, acc_type, data_byte_len, 0,
  21406                                      bank_ignore_mask);
  21407 
  21408             /* Fill in packet data */
  21409             sal_memcpy(schan_msg.gencmd.data, entry, entry_dw * 4);
  21410 
  21411 
  21412 #ifdef BCM_ESW_SUPPORT
  21413             if (soc_feature(unit, soc_feature_shared_hash_mem) ||
  21414                   soc_feature(unit, soc_feature_dual_hash) ||
  21415                   soc_feature(unit, soc_feature_ism_memory)) {
  21416                 sal_memcpy(&schan_msg_cpy, &schan_msg, sizeof(schan_msg));
  21417             }
  21418 #endif /* BCM_ESW_SUPPORT */
  21419             rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr);
  21420 
  21421             soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL,
  21422                                         NULL, NULL, &nack);
  21423             if (opcode != TABLE_INSERT_DONE_MSG) {
  21424                 LOG_ERROR(BSL_LS_SOC_SOCMEM,
  21425                           (BSL_META_U(unit,
  21426                                       "soc_mem_generic_insert: "
  21427                                       "invalid S-Channel reply, expected TABLE_INSERT_DONE_MSG:\n")));
  21428                 soc_schan_dump(unit, &schan_msg, 1);
  21429 #if defined(BCM_TRIUMPH3_SUPPORT)
  21430                 if (soc_feature(unit, soc_feature_esm_correction) &&
  21431                     ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  21432                      (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  21433                     SOC_ESM_UNLOCK(unit);
  21434                 }
  21435 #endif
  21436 #if defined(BCM_TRIUMPH3_SUPPORT)
  21437                 if (ins_disable) {
  21438                     _soc_l2mode_fifo_enable_insert_field_set(unit, l2_insert);
  21439                     ins_disable = FALSE;
  21440                 }
  21441 #endif
  21442                 MEM_UNLOCK(unit, mem);
  21443                 return SOC_E_INTERNAL;
  21444             }
  21445 
  21446 
  21447         }
  21448         goto resume;
  21449     } else if (acc_type == 15 && (dev_id == BCM56983_DEVICE_ID)) {
  21450         sal_memcpy(&schan_msg_dupl, &schan_msg, sizeof(schan_msg));
  21451         /*
  21452          * Execute S-Channel "table insert" command packet consisting of
  21453          * (header word + address word + entry_dw), and read back
  21454          * (header word + response word + entry_dw) data words.
  21455         */
  21456         if (2 + entry_dw > CMIC_SCHAN_WORDS(unit)) {
  21457             LOG_WARN(BSL_LS_SOC_SOCMEM,
  21458                     (BSL_META_U(unit,
  21459                                "soc_mem_generic_insert: assert will fail for memory %s\n"),
  21460                                 SOC_MEM_NAME(unit, mem)));
  21461         }
  21462    
  21463         for (j = 0; j < 2 ; j++) {
  21464             switch(j) {
  21465                 case 0 : acc_type = 0;
  21466                          break;
  21467                 case 1 : acc_type = 6;
  21468                          break;
  21469             }
  21470             sal_memcpy(&schan_msg, &schan_msg_dupl, sizeof(schan_msg));
  21471             soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_INSERT_CMD_MSG,
  21472                                      dst_blk, src_blk, acc_type, data_byte_len, 0,
  21473                                      bank_ignore_mask);
  21474 
  21475             /* Fill in packet data */
  21476             sal_memcpy(schan_msg.gencmd.data, entry, entry_dw * 4);
  21477 
  21478 #ifdef BCM_ESW_SUPPORT
  21479             if (soc_feature(unit, soc_feature_shared_hash_mem) ||
  21480                   soc_feature(unit, soc_feature_dual_hash) ||
  21481                   soc_feature(unit, soc_feature_ism_memory)) {
  21482                 sal_memcpy(&schan_msg_cpy, &schan_msg, sizeof(schan_msg));
  21483             }
  21484 #endif /* BCM_ESW_SUPPORT */
  21485             rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr);
  21486  
  21487             soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL,
  21488                                         NULL, NULL, &nack);
  21489             if (opcode != TABLE_INSERT_DONE_MSG) {
  21490                 LOG_ERROR(BSL_LS_SOC_SOCMEM,
  21491                           (BSL_META_U(unit,
  21492                                       "soc_mem_generic_insert: "
  21493                                       "invalid S-Channel reply, expected TABLE_INSERT_DONE_MSG:\n")));
  21494                 soc_schan_dump(unit, &schan_msg, 1);
  21495 #if defined(BCM_TRIUMPH3_SUPPORT)
  21496                 if (soc_feature(unit, soc_feature_esm_correction) &&
  21497                     ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  21498                      (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  21499                     SOC_ESM_UNLOCK(unit);
  21500                 }
  21501 #endif
  21502 #if defined(BCM_TRIUMPH3_SUPPORT)
  21503                 if (ins_disable) {
  21504                     _soc_l2mode_fifo_enable_insert_field_set(unit, l2_insert);
  21505                     ins_disable = FALSE;
  21506                 }
  21507 #endif
  21508                 MEM_UNLOCK(unit, mem);
  21509                 return SOC_E_INTERNAL;
  21510             }
  21511 
  21512 
  21513         }
  21514         goto resume;
  21515     }
  21516 #endif
  21517     soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_INSERT_CMD_MSG,
  21518                              dst_blk, src_blk, acc_type, data_byte_len, 0,
  21519                              bank_ignore_mask);
  21520 
  21521     /* Fill in packet data */
  21522     sal_memcpy(schan_msg.gencmd.data, entry, entry_dw * 4);
  21523 
  21524     if (SOC_IS_SAND(unit)) {
  21525         allow_intr = 1;
  21526     }
  21527 
  21528     /*
  21529      * Execute S-Channel "table insert" command packet consisting of
  21530      * (header word + address word + entry_dw), and read back
  21531      * (header word + response word + entry_dw) data words.
  21532      */
  21533     if (2 + entry_dw > CMIC_SCHAN_WORDS(unit)) {
  21534        LOG_WARN(BSL_LS_SOC_SOCMEM,
  21535                 (BSL_META_U(unit,
  21536                             "soc_mem_generic_insert: assert will fail for memory %s\n"),
  21537                  SOC_MEM_NAME(unit, mem)));
  21538     }
  21539 #ifdef BCM_ESW_SUPPORT
  21540     if (soc_feature(unit, soc_feature_shared_hash_mem) ||
  21541           soc_feature(unit, soc_feature_dual_hash) ||
  21542           soc_feature(unit, soc_feature_ism_memory)) {
  21543         sal_memcpy(&schan_msg_cpy, &schan_msg, sizeof(schan_msg));
  21544     }
  21545 _retry_op:
  21546 #endif /* BCM_ESW_SUPPORT */
  21547     rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr);
  21548 
  21549     soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL,
  21550                                 NULL, NULL, &nack);
  21551     if (opcode != TABLE_INSERT_DONE_MSG) {
  21552         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  21553                   (BSL_META_U(unit,
  21554                               "soc_mem_generic_insert: "
  21555                               "invalid S-Channel reply, expected TABLE_INSERT_DONE_MSG:\n")));
  21556         soc_schan_dump(unit, &schan_msg, 1);
  21557 #if defined(BCM_TRIUMPH3_SUPPORT)
  21558         if (soc_feature(unit, soc_feature_esm_correction) &&
  21559             ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  21560              (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  21561             SOC_ESM_UNLOCK(unit);
  21562         }
  21563 #endif
  21564 #if defined(BCM_TRIUMPH3_SUPPORT)
  21565         if (ins_disable) {
  21566             _soc_l2mode_fifo_enable_insert_field_set(unit, l2_insert);
  21567             ins_disable = FALSE;
  21568         }
  21569 #endif
  21570         MEM_UNLOCK(unit, mem);
  21571       return SOC_E_INTERNAL;
  21572     }
  21573 
  21574 #ifdef BCM_TOMAHAWK3_SUPPORT
  21575 resume:
  21576 #endif
  21577     if (soc_feature(unit, soc_feature_new_sbus_format) &&
  21578         !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
  21579         type = schan_msg.genresp_v2.response.type;
  21580         err_info = schan_msg.genresp_v2.response.err_info;
  21581         index = schan_msg.genresp_v2.response.index;
  21582         data = schan_msg.genresp_v2.data;
  21583     } else {
  21584         type = schan_msg.genresp.response.type;
  21585         err_info = schan_msg.genresp.response.err_info;
  21586         index = schan_msg.genresp.response.index;
  21587         data = schan_msg.genresp.data;
  21588     }
  21589     
  21590 #if defined(BCM_TRIUMPH3_SUPPORT)
  21591     if (ins_disable) {
  21592         _soc_l2mode_fifo_enable_insert_field_set(unit, l2_insert);
  21593         ins_disable = FALSE;
  21594         if (type == SCHAN_GEN_RESP_TYPE_INSERTED) {
  21595             if (SOC_IS_TRIUMPH3(unit)) {
  21596                 soc_l2_entry_callback(unit, 0, mem, NULL, entry);
  21597             }
  21598         }
  21599     }
  21600 #endif
  21601 
  21602     if ((nack != 0) || (rv == SOC_E_FAIL)) {
  21603         if (index_ptr) {
  21604             *index_ptr = -1;
  21605         }
  21606 #if defined(BCM_TRIUMPH3_SUPPORT)
  21607         if ((SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT(unit) ||
  21608              SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) &&
  21609             ((type == SCHAN_GEN_RESP_TYPE_L2_FIFO_FULL) ||
  21610              (type == SCHAN_GEN_RESP_L2_MOD_FIFO_FULL))) {
  21611             /*This is a Software Workaround for L2_MOD_FIFO. Sometimes an entry may be
  21612               unable to be inserted into L2 table when L2_MOD_FIFO is too busy. In this situation
  21613               the L2_INSERT field in L2_MOD_FIFO_ENABLE will be disabled and retry the insert
  21614               operation. After the insertion the L2_INSERT field will be enabled.*/
  21615             if (SOC_IS_TRIUMPH3(unit) && (type == SCHAN_GEN_RESP_L2_MOD_FIFO_FULL)) {
  21616                 l2_insert = _soc_l2mode_fifo_enable_insert_field_get(unit);
  21617                 _soc_l2mode_fifo_enable_insert_field_set(unit, 0);
  21618                 ins_disable = TRUE;
  21619                 if (l2_insert && try_one_time) {
  21620                     sal_memcpy(&schan_msg, &schan_msg_cpy, sizeof(schan_msg));
  21621                     LOG_INFO(BSL_LS_SOC_SOCMEM,
  21622                              (BSL_META_U(unit,
  21623                                          "L2_MOD_FIFO may be full,"
  21624                                          "error type [%d], will insert again!\n"),
  21625                                          type));
  21626                     try_one_time--;
  21627                     goto _retry_op;
  21628                 } else {
  21629                     _soc_l2mode_fifo_enable_insert_field_set(unit, l2_insert);
  21630                 }
  21631             } else if ((SOC_IS_TRIDENT(unit) &&
  21632                         (type == SCHAN_GEN_RESP_TYPE_L2_FIFO_FULL)) ||
  21633                         ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) &&
  21634                           (type == SCHAN_GEN_RESP_L2_MOD_FIFO_FULL))) {
  21635                 LOG_INFO(BSL_LS_SOC_SOCMEM,
  21636                          (BSL_META_U(unit,
  21637                                      "L2_MOD_FIFO is full, error type [%d]"),
  21638                                      type));
  21639                 rv = SOC_E_FULL;
  21640                 MEM_UNLOCK(unit, mem);
  21641                 return rv;
  21642             }
  21643         }
  21644 #endif
  21645 #if defined(BCM_ISM_SUPPORT)
  21646         if ((type == SCHAN_GEN_RESP_MAC_LIMIT_THRESHOLD) ||
  21647             (type == SCHAN_GEN_RESP_MAC_LIMIT_DELETE) ||
  21648             (type == SCHAN_GEN_RESP_L2_MOD_FIFO_FULL)) {
  21649             LOG_INFO(BSL_LS_SOC_SOCMEM,
  21650                      (BSL_META_U(unit,
  21651                                  "Insert table[%s]: hash bucket full\n"),
  21652                       SOC_MEM_NAME(unit, mem)));
  21653 
  21654             rv = SOC_E_FULL;
  21655         }  else {
  21656 #endif
  21657 #ifdef BCM_TRIDENT2PLUS_SUPPORT
  21658             if (soc_feature(unit, soc_feature_td2p_a0_sw_war) &&
  21659                 ((mem == EGR_VLAN_XLATEm) || (mem == VLAN_XLATEm)) &&
  21660                 (type == SCHAN_GEN_RESP_TYPE_FULL)) {
  21661                 if (insert_full_retry_attempt < HASH_MEM_OP_RETRY_COUNT) {
  21662                     insert_full_retry_attempt++;
  21663                     sal_memcpy(&schan_msg, &schan_msg_cpy, sizeof(schan_msg));
  21664                     goto _retry_op;
  21665                 }
  21666             }
  21667 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
  21668             if ((type == SCHAN_GEN_RESP_TYPE_FULL) ||
  21669                 (type == SCHAN_GEN_RESP_TYPE_L2_FIFO_FULL) ||
  21670                 (type == SCHAN_GEN_RESP_TYPE_MAC_LIMIT_THRE) ||
  21671                 (type == SCHAN_GEN_RESP_TYPE_MAC_LIMIT_DEL)) {
  21672                 LOG_INFO(BSL_LS_SOC_SOCMEM,
  21673                          (BSL_META_U(unit,
  21674                                      "Insert table[%s]: hash bucket full\n"),
  21675                           SOC_MEM_NAME(unit, mem)));
  21676                 rv = SOC_E_FULL;
  21677             } else if (type == SCHAN_GEN_RESP_TYPE_ERROR) {
  21678 #ifdef BCM_ESW_SUPPORT
  21679                 LOG_VERBOSE(BSL_LS_SOC_SER,(BSL_META_U(unit,
  21680                     " soc_mem_generic_insert: rv=%d, nack=%d, type=%d, index=%d\n"),
  21681                     rv, nack, type, index));
  21682                 if (soc_feature(unit, soc_feature_shared_hash_mem)) {
  21683                     int i, rv1 = SOC_E_NONE, index1 = index, ir1 = 1,
  21684                         pipe1 = SOC_PIPE_ANY;
  21685                     soc_mem_t mem1 = mem;
  21686 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT)
  21687                     if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit) || SOC_IS_APACHE(unit)) {
  21688                         (void)_soc_inline_ser_mem_remap(unit, &mem1, &pipe1,
  21689                                                         &ir1);
  21690                         index1 = (index / ir1) * ir1; /* base_index for entry */
  21691                     }
  21692 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_APACHE_SUPPORT */
  21693                     for (i = 0; i < ir1; i++) {
  21694                         rv1 = soc_ser_sram_correction(unit, pipe1,
  21695                                                   schan_msg.gencmd.header.v2.dst_blk,
  21696                                                       schan_msg.gencmd.address, mem1,
  21697                                                       copyno, index1 + i, NULL);
  21698                         if (SOC_FAILURE(rv1)) {
  21699                             break;
  21700                         }
  21701                     }
  21702                     if (rv1 == SOC_E_NONE) {
  21703                         if (insert_retry_attempt < HASH_MEM_OP_RETRY_COUNT) {
  21704                             insert_retry_attempt++;
  21705                             sal_memcpy(&schan_msg, &schan_msg_cpy,
  21706                                        sizeof(schan_msg));
  21707                             goto _retry_op;
  21708                         }
  21709                     }
  21710                 }
  21711 #endif /* BCM_ESW_SUPPORT */
  21712                 if (err_info == SCHAN_GEN_RESP_ERROR_BUSY) {
  21713                     LOG_INFO(BSL_LS_SOC_SOCMEM,
  21714                              (BSL_META_U(unit,
  21715                                          "Insert table[%s]: Modfifo full\n"),
  21716                               SOC_MEM_NAME(unit, mem)));
  21717                     rv = SOC_E_BUSY;
  21718                 } else if (err_info == SCHAN_GEN_RESP_ERROR_PARITY) {
  21719                     LOG_ERROR(BSL_LS_SOC_SOCMEM,
  21720                               (BSL_META_U(unit,
  21721                                           "Insert table[%s]: Parity Error Index %d\n"),
  21722                                SOC_MEM_NAME(unit, mem), index));
  21723                     rv = SOC_E_INTERNAL;
  21724                 }
  21725 #if defined(BCM_TRX_SUPPORT)
  21726                 /* Hash table response with SCHAN_GEN_RESP_TYPE_ERROR */
  21727                 if (SOC_IS_TRX(unit) && (soc_mem_is_hashed(unit, mem))) {
  21728                     /* Try to recover */
  21729                     rv = soc_hash_mem_inline_recovery(unit, mem, &schan_msg,
  21730                                                         banks, entry);
  21731                     if (rv == SOC_E_NONE) {
  21732                         if (insert_retry < HASH_MEM_OP_RETRY_COUNT) {
  21733                             insert_retry++;
  21734                             sal_memcpy(&schan_msg, &schan_msg_cpy, sizeof(schan_msg));
  21735                             LOG_WARN(BSL_LS_SOC_SOCMEM,
  21736                                      (BSL_META_U(unit,
  21737                                                  "unit %d: Retry Hash insert operation..\n"),
  21738                                       unit));
  21739                             goto _retry_op;
  21740                         }
  21741 
  21742                     } else {
  21743                         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  21744                                   (BSL_META_U(unit,
  21745                                               "unit %d, table[%s]: Parity error recovery failed, return value: %d\n"),
  21746                                    unit, SOC_MEM_NAME(unit, mem), rv));
  21747                     }
  21748                 }
  21749 #endif
  21750             } else {
  21751 #if defined(BCM_TRIDENT2_SUPPORT)
  21752                 if (SOC_IS_TD2_TT2(unit) && soc_mem_is_hashed(unit, mem) &&
  21753                     (type == SCHAN_GEN_RESP_TYPE_INSERTED ||
  21754                     type == SCHAN_GEN_RESP_TYPE_REPLACED)) {
  21755                     rv = soc_hash_mem_inline_recovery(unit, mem, &schan_msg,
  21756                                                         banks, entry);
  21757                     if (rv == SOC_E_NONE) {
  21758                         if (insert_retry_attempt < HASH_MEM_OP_RETRY_COUNT) {
  21759                             insert_retry_attempt++;
  21760                             sal_memcpy(&schan_msg, &schan_msg_cpy, sizeof(schan_msg));
  21761                             LOG_WARN(BSL_LS_SOC_SOCMEM,
  21762                                      (BSL_META_U(unit,
  21763                                                  "unit %d: Retry Hash insert operation..\n"),
  21764                                       unit));
  21765                             goto _retry_op;
  21766                         }
  21767                     } else {
  21768                         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  21769                                   (BSL_META_U(unit,
  21770                                               "unit %d, table[%s]: Parity error recovery failed, return value: %d\n"),
  21771                                    unit, SOC_MEM_NAME(unit, mem), rv));
  21772                     }
  21773                 }
  21774 #endif
  21775                 rv = SOC_E_FAIL;
  21776             }
  21777 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(BCM_ISM_SUPPORT)
  21778         }
  21779 #endif
  21780     } else {
  21781 #ifdef BCM_TRIUMPH_SUPPORT
  21782         if (soc_feature(unit, soc_feature_etu_support) &&
  21783             mem == EXT_L2_ENTRY_2m) {
  21784             soc_mem_t ext_mem;
  21785             int ext_index;
  21786 
  21787             rv1 = soc_tcam_raw_index_to_mem_index(unit, index,
  21788                                 &ext_mem, &ext_index);
  21789             if (SOC_FAILURE(rv1)) {
  21790 #if defined(BCM_TRIUMPH3_SUPPORT)
  21791                 if (soc_feature(unit, soc_feature_esm_correction) &&
  21792                       ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  21793                      (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  21794                     SOC_ESM_UNLOCK(unit);
  21795                 }
  21796 #endif
  21797                 MEM_UNLOCK(unit, mem);
  21798                 return rv1;
  21799             }
  21800             if (mem != ext_mem) {
  21801 #if defined(BCM_TRIUMPH3_SUPPORT)
  21802                 if (soc_feature(unit, soc_feature_esm_correction) &&
  21803                       ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  21804                      (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  21805                     SOC_ESM_UNLOCK(unit);
  21806                 }
  21807 #endif
  21808                 MEM_UNLOCK(unit, mem);
  21809                 return SOC_E_INTERNAL;
  21810             }
  21811             index = ext_index;
  21812         }
  21813 #endif /* BCM_TRIUMPH_SUPPORT */
  21814         if (index_ptr != NULL) {
  21815             *index_ptr = index;
  21816         }
  21817         if (type == SCHAN_GEN_RESP_TYPE_REPLACED) {
  21818             if (old_entry != NULL) {
  21819                 /* coverity[overrun-buffer-arg] */
  21820                 sal_memcpy(old_entry, data, entry_dw * sizeof(uint32));
  21821             }
  21822             rv = SOC_E_EXISTS;
  21823         }
  21824         SOP_MEM_STATE(unit, mem).count[copyno]++;
  21825 #if defined(BCM_TRIUMPH_SUPPORT)
  21826         if (mem == EXT_L2_ENTRYm) {
  21827             rv1 = soc_triumph_ext_l2_entry_update(unit, index, entry);
  21828             if (SOC_FAILURE(rv1)) {
  21829 #if defined(BCM_TRIUMPH3_SUPPORT)
  21830                 if (soc_feature(unit, soc_feature_esm_correction) &&
  21831                       ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  21832                      (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  21833                     SOC_ESM_UNLOCK(unit);
  21834                 }
  21835 #endif
  21836                 MEM_UNLOCK(unit, mem);
  21837                 return rv1;
  21838             }
  21839         }
  21840 #endif /* BCM_TRIUMPH_SUPPORT */
  21841 #if defined(BCM_TRIUMPH3_SUPPORT)
  21842         if (mem == EXT_L2_ENTRY_1m || mem == EXT_L2_ENTRY_2m) {
  21843             rv1 = soc_triumph3_ext_l2_entry_update(unit, mem, index, entry);
  21844             if (SOC_FAILURE(rv1)) {
  21845 #if defined(BCM_TRIUMPH3_SUPPORT)
  21846                 if (soc_feature(unit, soc_feature_esm_correction) &&
  21847                       ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  21848                      (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  21849                     SOC_ESM_UNLOCK(unit);
  21850                 }
  21851 #endif
  21852                 MEM_UNLOCK(unit, mem);
  21853                 return rv1;
  21854             }
  21855         }
  21856 #endif /* BCM_TRIUMPH3_SUPPORT */
  21857         /* Update cache if active */
  21858         cache = SOC_MEM_STATE(unit, mem).cache[copyno];
  21859         vmap = SOC_MEM_STATE(unit, mem).vmap[copyno];
  21860         index_valid = (index >= 0 &&
  21861                        index <= soc_mem_index_max(unit, mem));
  21862         if (!index_valid) {
  21863 #if defined(BCM_HURRICANE3_SUPPORT)
  21864             if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) &&
  21865                 (mem == L2Xm) && 
  21866                 (index & SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit))) {
  21867                 overflow_index =
  21868                     (index & ~SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit));
  21869                 /* Check whether the entry is located at L2_OVERFLOW_ENTRY */
  21870                 if ((overflow_index) <=
  21871                     soc_mem_index_max(unit, L2_ENTRY_OVERFLOWm)) {
  21872                     rv = SOC_E_NONE;
  21873                     /* update cache */
  21874                     cache = SOC_MEM_STATE(unit, 
  21875                                     L2_ENTRY_OVERFLOWm).cache[copyno];
  21876                     vmap = SOC_MEM_STATE(unit, 
  21877                                     L2_ENTRY_OVERFLOWm).vmap[copyno];
  21878                     if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)) {
  21879                         /* 
  21880                          * If an invalid or non-static entry 
  21881                           * is being written then clear the cache 
  21882                           */
  21883                         if (soc_mem_field32_get(unit, mem, entry, VALIDf) &&
  21884                            soc_mem_field32_get(unit, mem, entry, STATIC_BITf)) {
  21885                             sal_memcpy(cache + overflow_index * entry_dw, 
  21886                                 entry, entry_dw * 4);
  21887                             CACHE_VMAP_SET(vmap, overflow_index);
  21888                          } else {
  21889                             CACHE_VMAP_CLR(vmap, overflow_index);
  21890                          }
  21891                     }
  21892                 } else {
  21893                     LOG_ERROR(BSL_LS_SOC_SOCMEM, 
  21894                         (BSL_META_U(unit, "soc_mem_generic_insert: "
  21895                                           "invalid index %d for memory "
  21896                                           "L2_ENTRY_OVERFLOW\n"),
  21897                          overflow_index));
  21898                     rv = SOC_E_INTERNAL;
  21899                 }
  21900             } else 
  21901 #endif /* BCM_HURRICANE3_SUPPORT */
  21902             {            
  21903                 LOG_ERROR(BSL_LS_SOC_SOCMEM,
  21904                       (BSL_META_U(unit,
  21905                                   "soc_mem_generic_insert: "
  21906                                   "invalid index %d for memory %s\n"),
  21907                        index, SOC_MEM_NAME(unit, mem)));
  21908                 rv = SOC_E_INTERNAL;
  21909             }
  21910         } else if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit)) {
  21911             if (_SOC_MEM_CHK_L2_MEM(mem)) {
  21912                 soc_field_t fld_vld = VALIDf;
  21913                 if (soc_feature(unit, soc_feature_base_valid)) {
  21914                     fld_vld = BASE_VALIDf;
  21915                 }
  21916                 /* If an invalid or non-static entry is being written then clear the cache */
  21917                 if (((mem == L2_ENTRY_2m &&
  21918                      soc_L2_ENTRY_2m_field32_get(unit, entry, VALID_0f) &&
  21919                      soc_L2_ENTRY_2m_field32_get(unit, entry, VALID_1f)) ||
  21920                      ((mem == L2Xm || mem == L2_ENTRY_1m) &&
  21921                       soc_mem_field32_get(unit, mem, entry, fld_vld))) &&
  21922                      (((mem == L2Xm || mem == L2_ENTRY_1m) &&
  21923                        soc_mem_field32_get(unit, mem, entry, STATIC_BITf)) ||
  21924                      (mem == L2_ENTRY_2m &&
  21925                       (soc_mem_field32_get(unit, mem, entry, STATIC_BIT_0f) &&
  21926                        soc_mem_field32_get(unit, mem, entry, STATIC_BIT_1f))))) {
  21927                     sal_memcpy(cache + index * entry_dw, entry, entry_dw * 4);
  21928                     CACHE_VMAP_SET(vmap, index);
  21929                     if (mem == L2_ENTRY_1m) {
  21930                         vmap = SOC_MEM_STATE(unit, L2_ENTRY_2m).vmap[copyno];
  21931                         CACHE_VMAP_CLR(vmap, index/2);
  21932                     } else if (mem == L2_ENTRY_2m) {
  21933                         vmap = SOC_MEM_STATE(unit, L2_ENTRY_1m).vmap[copyno];
  21934                         CACHE_VMAP_CLR(vmap, index*2);
  21935                         CACHE_VMAP_CLR(vmap, index*2 + 1);
  21936                     }
  21937                 } else {
  21938                     CACHE_VMAP_CLR(vmap, index);
  21939                 }
  21940             } else {
  21941                 sal_memcpy(cache + index * entry_dw, entry, entry_dw * 4);
  21942                 CACHE_VMAP_SET(vmap, index);
  21943             }
  21944         }
  21945     }
  21946 #if defined(BCM_TRIUMPH3_SUPPORT)
  21947     if (soc_feature(unit, soc_feature_esm_correction) &&
  21948                       ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  21949                      (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  21950         SOC_ESM_UNLOCK(unit);
  21951     }
  21952 #endif
  21953     MEM_UNLOCK(unit, mem);
  21954 
  21955     return rv;
  21956 }
  21957 
  21958 /*
  21959  * Function:
  21960  *      soc_mem_generic_delete
  21961  * Purpose:
  21962  *      Delete an entry
  21963  * Parameters:
  21964  *      unit - StrataSwitch unit #
  21965  *      banks - For dual hashing, which halves are selected (inverted)
  21966  *              Note: used to create a bitmap for ISM mems. (All banks: -1)
  21967  *      entry - entry to delete
  21968  *      old_entry - old entry if entry was found and deleted
  21969  * Returns:
  21970  *      SOC_E_NONE - success
  21971  *      SOC_E_NOT_FOUND - full
  21972  *      SOC_E_BUSY - modfifo full
  21973  * Notes:
  21974  *      Uses hardware deletion; sends an DELETE message over the
  21975  *      S-Channel.
  21976  */
  21977 
  21978 int
  21979 soc_mem_generic_delete(int unit, soc_mem_t mem, int copyno, int32 banks,
  21980                        void *entry, void *old_entry, int *index_ptr)
  21981 {
  21982     schan_msg_t schan_msg;
  21983 #ifdef BCM_ESW_SUPPORT
  21984     schan_msg_t schan_msg_cpy;
  21985 #endif /* BCM_ESW_SUPPORT */
  21986     int         rv, entry_dw, index_valid;
  21987     uint8       at, *vmap;
  21988     int         type, err_info, index, allow_intr=0;
  21989     uint32      *data, *cache;
  21990     void        *null_entry;
  21991     int         src_blk, dst_blk, acc_type, data_byte_len;
  21992     int         opcode, nack;
  21993     uint32      bank_ignore_mask;
  21994 #if defined(BCM_TRIUMPH_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  21995     int         rv1 = SOC_E_NONE;
  21996 #endif
  21997 #if defined(BCM_TRX_SUPPORT)
  21998 #if defined(BCM_TRIDENT2_SUPPORT)
  21999     uint8       delete_retry_attempt = 0;
  22000 #endif
  22001     uint8       delete_retry = 0;
  22002 #endif
  22003 #if defined(BCM_TRIUMPH3_SUPPORT)
  22004     int             del_disable = FALSE, try_one_time = 1;
  22005     uint32          l2_delete = 0;
  22006 #endif
  22007 
  22008 #if defined(BCM_HURRICANE3_SUPPORT)
  22009     uint32      overflow_index = 0;
  22010 #endif /* BCM_HURRICANE3_SUPPORT */
  22011 #if defined(BCM_GREYHOUND2_SUPPORT)
  22012     uint32 key_type = 0;
  22013 #endif /* BCM_GREYHOUND2_SUPPORT */
  22014 
  22015 #ifdef BCM_TOMAHAWK3_SUPPORT
  22016     int j = 0;
  22017     uint16 dev_id;
  22018     uint8 rev_id;
  22019     schan_msg_t schan_msg_dupl; 
  22020     soc_cm_get_id(unit, &dev_id, &rev_id);
  22021 #endif
  22022     _SOC_MEM_REPLACE_MEM(unit, mem);
  22023     SOC_MEM_ALIAS_TO_ORIG(unit,mem);
  22024     null_entry = soc_mem_entry_null(unit, mem);
  22025 
  22026     assert(SOC_MEM_IS_VALID(unit, mem));
  22027     assert(soc_attached(unit));
  22028 
  22029     if (copyno == MEM_BLOCK_ANY) {
  22030         /* coverity[overrun-local : FALSE] */
  22031         copyno = SOC_MEM_BLOCK_ANY(unit, mem);
  22032     }
  22033     if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) {
  22034         LOG_WARN(BSL_LS_SOC_SOCMEM,
  22035                  (BSL_META_U(unit,
  22036                              "soc_mem_generic_delete: invalid block %d for memory %s\n"),
  22037                   copyno, SOC_MEM_NAME(unit, mem)));
  22038         return SOC_E_PARAM;
  22039     }
  22040 
  22041     if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) {
  22042         LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  22043                             "Delete table[%s]: banks=%d"), SOC_MEM_NAME(unit, mem),
  22044                  banks));
  22045         if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) {
  22046             soc_mem_entry_dump(unit, mem, entry, BSL_VERBOSE|BSL_LS_SOC_COMMON);
  22047         }
  22048         LOG_INFO(BSL_LS_SOC_SOCMEM, (BSL_META_U(unit,
  22049                             "\n")));
  22050     }
  22051 
  22052 #if defined(BCM_GREYHOUND2_SUPPORT)
  22053     if (soc_feature(unit, soc_feature_vxlan_lite_riot) && (mem == L2Xm)) {
  22054         key_type = soc_mem_field32_get(unit, mem, entry, KEY_TYPEf);
  22055         /* Use SW to delete a L2 entry when key_type is VFI_MULTICAST */
  22056         if (key_type == GH2_L2_HASH_KEY_TYPE_VFI_MULTICAST) {
  22057             return soc_mem_gh2_l2_sw_delete(unit, mem, copyno, banks,
  22058                                             entry, old_entry, index_ptr);
  22059         }
  22060     }
  22061 #endif /* BCM_GREYHOUND2_SUPPORT */
  22062 
  22063     entry_dw = soc_mem_entry_words(unit, mem);
  22064 
  22065     MEM_LOCK(unit, mem);
  22066 #if defined(BCM_TRIUMPH3_SUPPORT)
  22067     if (soc_feature(unit, soc_feature_esm_correction) &&
  22068           ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  22069          (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  22070         SOC_ESM_LOCK(unit);
  22071     }
  22072 #endif
  22073     schan_msg_clear(&schan_msg);
  22074     acc_type = SOC_MEM_ACC_TYPE(unit, mem);
  22075     src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit));
  22076     dst_blk = SOC_BLOCK2SCH(unit, copyno);
  22077     if ((soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) ||
  22078         (soc_feature(unit, soc_feature_shared_hash_mem) && ((mem == L2Xm) ||
  22079          (mem == L3_ENTRY_ONLYm) || (mem == L3_ENTRY_IPV4_UNICASTm) ||
  22080          (mem == L3_ENTRY_IPV4_MULTICASTm) || (mem == L3_ENTRY_IPV6_UNICASTm) ||
  22081          (mem == L3_ENTRY_IPV6_MULTICASTm)
  22082 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  22083          || (mem == L3_ENTRY_SINGLEm) || (mem == L3_ENTRY_DOUBLEm)
  22084          || (mem == L3_ENTRY_QUADm) || (mem == MPLS_ENTRY_SINGLEm)
  22085 #endif
  22086 #if defined(BCM_TOMAHAWK3_SUPPORT)
  22087          || (mem == L3_TUNNEL_SINGLEm) || (mem == L3_TUNNEL_DOUBLEm)
  22088          || (mem == L3_TUNNEL_QUADm)
  22089 #endif
  22090 #if defined(BCM_TRIDENT3_SUPPORT)
  22091          || (mem == VLAN_XLATE_1_SINGLEm)
  22092          || (mem == VLAN_XLATE_1_DOUBLEm)
  22093          || (mem == EGR_VLAN_XLATE_1_SINGLEm)
  22094          || (mem == EGR_VLAN_XLATE_1_DOUBLEm)
  22095          || (mem == VLAN_XLATE_2_SINGLEm)
  22096          || (mem == VLAN_XLATE_2_DOUBLEm)
  22097          || (mem == EGR_VLAN_XLATE_2_SINGLEm)
  22098          || (mem == EGR_VLAN_XLATE_2_DOUBLEm)
  22099 #endif
  22100 #if defined(BCM_TOMAHAWK_SUPPORT)
  22101          || _SOC_MEM_CHK_FPEM_MEM(mem)
  22102 #endif
  22103        ))) {
  22104         /* don't set bank id in cos */
  22105         bank_ignore_mask = 0;
  22106     } else {
  22107         bank_ignore_mask = banks & 0x3;
  22108     }
  22109     data_byte_len = entry_dw * 4;
  22110 
  22111     schan_msg.gencmd.address = soc_mem_addr_get(unit, mem, 0, copyno, 0, &at);
  22112     if ((soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) ||
  22113         (soc_feature(unit, soc_feature_shared_hash_mem) && ((mem == L2Xm) ||
  22114          (mem == L3_ENTRY_ONLYm) || (mem == L3_ENTRY_IPV4_UNICASTm) ||
  22115          (mem == L3_ENTRY_IPV4_MULTICASTm) || (mem == L3_ENTRY_IPV6_UNICASTm) ||
  22116          (mem == L3_ENTRY_IPV6_MULTICASTm)
  22117 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  22118          || (mem == L3_ENTRY_SINGLEm) || (mem == L3_ENTRY_DOUBLEm)
  22119          || (mem == L3_ENTRY_QUADm) || (mem == MPLS_ENTRY_SINGLEm)
  22120 #endif
  22121 #if defined(BCM_TOMAHAWK3_SUPPORT)
  22122          || (mem == L3_TUNNEL_SINGLEm) || (mem == L3_TUNNEL_DOUBLEm)
  22123          || (mem == L3_TUNNEL_QUADm)
  22124 #endif
  22125 #if defined(BCM_TRIDENT3_SUPPORT)
  22126          || (mem == VLAN_XLATE_1_SINGLEm)
  22127          || (mem == VLAN_XLATE_1_DOUBLEm)
  22128          || (mem == EGR_VLAN_XLATE_1_SINGLEm)
  22129          || (mem == EGR_VLAN_XLATE_1_DOUBLEm)
  22130          || (mem == VLAN_XLATE_2_SINGLEm)
  22131          || (mem == VLAN_XLATE_2_DOUBLEm)
  22132          || (mem == EGR_VLAN_XLATE_2_SINGLEm)
  22133          || (mem == EGR_VLAN_XLATE_2_DOUBLEm)
  22134          || (mem == MPLS_ENTRYm)
  22135 #endif
  22136 #if defined(BCM_TOMAHAWK_SUPPORT)
  22137          || _SOC_MEM_CHK_FPEM_MEM(mem)
  22138 #endif
  22139        ))) {
  22140         /* set bank ignore mask in lower 20 bits */
  22141         if (banks && banks != SOC_MEM_HASH_BANK_ALL) {
  22142             if (soc_feature(unit, soc_feature_shared_hash_mem)) {
  22143                 schan_msg.gencmd.address |= (~banks & SOC_HASH_BANK_MASK_SHARED);
  22144             } else {
  22145 #ifdef BCM_TRIUMPH3_SUPPORT
  22146                 uint32 phy_banks = soc_ism_get_phy_bank_mask(unit, banks);
  22147                 schan_msg.gencmd.address |= (~phy_banks & SOC_HASH_BANK_MASK_ISM);
  22148 #endif /* BCM_TRIUMPH3_SUPPORT */
  22149             }
  22150         }
  22151     }
  22152 #ifdef BCM_TOMAHAWK3_SUPPORT
  22153     /* For 56983 Lower die SKU, we are converting data split and unique into 4 unique
  22154        delete commands */
  22155     if ((acc_type == 14 || acc_type == 9) && (dev_id == BCM56983_DEVICE_ID)) {
  22156         sal_memcpy(&schan_msg_dupl, &schan_msg, sizeof(schan_msg));
  22157         for (j = 0; j < 4; j++) {
  22158             switch(j) {
  22159                 case 0 : acc_type = 0;
  22160                          break;
  22161                 case 1 : acc_type = 1;
  22162                          break;
  22163                 case 2 : acc_type = 6;
  22164                          break;
  22165                 case 3 : acc_type = 7;
  22166                          break;
  22167             }
  22168             sal_memcpy(&schan_msg, &schan_msg_dupl, sizeof(schan_msg));
  22169             soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_DELETE_CMD_MSG,
  22170                                      dst_blk, src_blk, acc_type, data_byte_len, 0,
  22171                                      bank_ignore_mask);
  22172             /* Fill in packet data */
  22173             sal_memcpy(schan_msg.gencmd.data, entry, entry_dw * 4);
  22174 #ifdef BCM_ESW_SUPPORT
  22175             if (soc_feature(unit, soc_feature_shared_hash_mem) ||
  22176                   soc_feature(unit, soc_feature_dual_hash) ||
  22177                   soc_feature(unit, soc_feature_ism_memory)) {
  22178                 sal_memcpy(&schan_msg_cpy, &schan_msg, sizeof(schan_msg));
  22179             }
  22180 #endif
  22181             rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr);                        soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL,
  22182                                             NULL, NULL, &nack);
  22183             if (opcode != TABLE_DELETE_DONE_MSG) {
  22184                 LOG_ERROR(BSL_LS_SOC_SOCMEM,
  22185                           (BSL_META_U(unit,
  22186                                       "soc_mem_generic_delete: "
  22187                                       "invalid S-Channel reply, expected TABLE_DELETE_DONE_MSG:\n")));
  22188                 soc_schan_dump(unit, &schan_msg, 1);
  22189 #if defined(BCM_TRIUMPH3_SUPPORT)
  22190                 if (soc_feature(unit, soc_feature_esm_correction) &&
  22191                       ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  22192                      (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  22193                     SOC_ESM_UNLOCK(unit);
  22194                 }
  22195 #endif
  22196 #if defined(BCM_TRIUMPH3_SUPPORT)
  22197                 if (del_disable) {
  22198                     _soc_l2mode_fifo_enable_delete_field_set(unit, l2_delete);
  22199                     del_disable = FALSE;
  22200                 }
  22201 #endif
  22202                 MEM_UNLOCK(unit, mem);
  22203                 return SOC_E_INTERNAL;
  22204             }
  22205         }
  22206      } else if (acc_type == 15 && (dev_id == BCM56983_DEVICE_ID)) {
  22207         sal_memcpy(&schan_msg_dupl, &schan_msg, sizeof(schan_msg));
  22208         for (j = 0; j < 2; j++) {
  22209             switch(j) {
  22210                 case 0 : acc_type = 0;
  22211                          break;
  22212                 case 1 : acc_type = 6;
  22213                          break;
  22214             }
  22215             sal_memcpy(&schan_msg, &schan_msg_dupl, sizeof(schan_msg));
  22216             soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_DELETE_CMD_MSG,
  22217                                      dst_blk, src_blk, acc_type, data_byte_len, 0,
  22218                                      bank_ignore_mask);
  22219             /* Fill in packet data */
  22220             sal_memcpy(schan_msg.gencmd.data, entry, entry_dw * 4);
  22221 #ifdef BCM_ESW_SUPPORT
  22222             if (soc_feature(unit, soc_feature_shared_hash_mem) ||
  22223                   soc_feature(unit, soc_feature_dual_hash) ||
  22224                   soc_feature(unit, soc_feature_ism_memory)) {
  22225                 sal_memcpy(&schan_msg_cpy, &schan_msg, sizeof(schan_msg));
  22226             }
  22227 #endif
  22228             rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr);                        soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL,
  22229                                             NULL, NULL, &nack);
  22230             if (opcode != TABLE_DELETE_DONE_MSG) {
  22231                 LOG_ERROR(BSL_LS_SOC_SOCMEM,
  22232                           (BSL_META_U(unit,
  22233                                       "soc_mem_generic_delete: "
  22234                                       "invalid S-Channel reply, expected TABLE_DELETE_DONE_MSG:\n")));
  22235                 soc_schan_dump(unit, &schan_msg, 1);
  22236 #if defined(BCM_TRIUMPH3_SUPPORT)
  22237                 if (soc_feature(unit, soc_feature_esm_correction) &&
  22238                       ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  22239                      (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  22240                     SOC_ESM_UNLOCK(unit);
  22241                 }
  22242 #endif
  22243 #if defined(BCM_TRIUMPH3_SUPPORT)
  22244                 if (del_disable) {
  22245                     _soc_l2mode_fifo_enable_delete_field_set(unit, l2_delete);
  22246                     del_disable = FALSE;
  22247                 }
  22248 #endif
  22249                 MEM_UNLOCK(unit, mem);
  22250                 return SOC_E_INTERNAL;
  22251             }
  22252         }
  22253      } else
  22254 #endif
  22255      {
  22256 #ifdef BCM_TOMAHAWK3_SUPPORT
  22257         if (acc_type == 16 && (dev_id == BCM56983_DEVICE_ID)) {
  22258             acc_type = 0;
  22259         }
  22260 #endif
  22261         soc_schan_header_cmd_set(unit, &schan_msg.header, TABLE_DELETE_CMD_MSG,
  22262                                  dst_blk, src_blk, acc_type, data_byte_len, 0,
  22263                                  bank_ignore_mask);
  22264 
  22265         /* Fill in packet data */
  22266         sal_memcpy(schan_msg.gencmd.data, entry, entry_dw * 4);
  22267 
  22268         if (SOC_IS_SAND(unit)) {
  22269             allow_intr = 1;
  22270         }
  22271 
  22272         /*
  22273         * Execute S-Channel "table delete" command packet consisting of
  22274         * (header word + address word + entry_dw), and read back
  22275         * (header word + response word + entry_dw) data words.
  22276         */
  22277 #ifdef BCM_ESW_SUPPORT
  22278         if (soc_feature(unit, soc_feature_shared_hash_mem) ||
  22279               soc_feature(unit, soc_feature_dual_hash) ||
  22280               soc_feature(unit, soc_feature_ism_memory)) {
  22281             sal_memcpy(&schan_msg_cpy, &schan_msg, sizeof(schan_msg));
  22282         }
  22283 #endif
  22284 #if defined(BCM_TRX_SUPPORT)
  22285 _retry_op_delete:
  22286 #endif
  22287         rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 2, allow_intr);
  22288  
  22289         soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL,
  22290                                     NULL, NULL, &nack);
  22291         if (opcode != TABLE_DELETE_DONE_MSG) {
  22292             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  22293                       (BSL_META_U(unit,
  22294                                   "soc_mem_generic_delete: "
  22295                                   "invalid S-Channel reply, expected TABLE_DELETE_DONE_MSG:\n")));
  22296             soc_schan_dump(unit, &schan_msg, 1);
  22297 #if defined(BCM_TRIUMPH3_SUPPORT)
  22298             if (soc_feature(unit, soc_feature_esm_correction) &&
  22299                   ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  22300                  (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  22301                 SOC_ESM_UNLOCK(unit);
  22302             }
  22303 #endif
  22304 #if defined(BCM_TRIUMPH3_SUPPORT)
  22305             if (del_disable) {
  22306                 _soc_l2mode_fifo_enable_delete_field_set(unit, l2_delete);
  22307                 del_disable = FALSE;
  22308             }
  22309 #endif
  22310             MEM_UNLOCK(unit, mem);
  22311             return SOC_E_INTERNAL;
  22312         }
  22313 
  22314     }
  22315     if (soc_feature(unit, soc_feature_new_sbus_format) &&
  22316         !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
  22317         type = schan_msg.genresp_v2.response.type;
  22318         err_info = schan_msg.genresp_v2.response.err_info;
  22319         index = schan_msg.genresp_v2.response.index;
  22320         data = schan_msg.genresp_v2.data;
  22321     } else {
  22322         type = schan_msg.genresp.response.type;
  22323         err_info = schan_msg.genresp.response.err_info;
  22324         index = schan_msg.genresp.response.index;
  22325         data = schan_msg.genresp.data;
  22326     }
  22327 #if defined(BCM_TRIUMPH3_SUPPORT)
  22328     if (del_disable) {
  22329         _soc_l2mode_fifo_enable_delete_field_set(unit, l2_delete);
  22330         del_disable = FALSE;
  22331         if (type == SCHAN_GEN_RESP_TYPE_DELETED) {        
  22332             if (SOC_IS_TRIUMPH3(unit)) {
  22333                 soc_l2_entry_callback(unit, 0, mem, entry, NULL);
  22334             }
  22335         }
  22336     }
  22337 #endif
  22338 
  22339     if ((nack != 0) || (rv == SOC_E_FAIL)) {
  22340         if (index_ptr) {
  22341             *index_ptr = -1;
  22342         }
  22343         if (type == SCHAN_GEN_RESP_TYPE_NOT_FOUND) {
  22344             LOG_INFO(BSL_LS_SOC_SOCMEM,
  22345                      (BSL_META_U(unit,
  22346                                  "Delete table[%s]: Not found\n"),
  22347                       SOC_MEM_NAME(unit, mem)));
  22348             rv = SOC_E_NOT_FOUND;
  22349         } else if (type == SCHAN_GEN_RESP_TYPE_ERROR) {
  22350                 LOG_VERBOSE(BSL_LS_SOC_SER,(BSL_META_U(unit,
  22351                     ">>>>> soc_mem_generic_delete: rv=%d, nack=%d, type=%d, index=%d\n"),
  22352                     rv, nack, type, index));
  22353 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT)
  22354                 if (soc_feature(unit, soc_feature_shared_hash_mem) &&
  22355                     (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit) || SOC_IS_APACHE(unit))) {
  22356                     int i, rv1 = SOC_E_NONE, index1 = index, ir1 = 1,
  22357                         pipe1 = SOC_PIPE_ANY;
  22358                     soc_mem_t mem1 = mem;
  22359 
  22360                     (void)_soc_inline_ser_mem_remap(unit, &mem1, &pipe1, &ir1);
  22361                     index1 = (index / ir1) * ir1; /* base_index for entry */
  22362 
  22363                     for (i = 0; i < ir1; i++) { 
  22364                         rv1 = soc_ser_sram_correction(unit, pipe1,
  22365                                                       schan_msg.gencmd.header.v2.dst_blk,
  22366                                                       schan_msg.gencmd.address, mem1,
  22367                                                       copyno, index1 + i, NULL);
  22368                         if (SOC_FAILURE(rv1)) {
  22369                             break;
  22370                         }
  22371                     }
  22372                     if (rv1 == SOC_E_NONE) {
  22373                         if (delete_retry_attempt < HASH_MEM_OP_RETRY_COUNT) {
  22374                             delete_retry_attempt++;
  22375                             sal_memcpy(&schan_msg, &schan_msg_cpy,
  22376                                        sizeof(schan_msg));
  22377                             goto _retry_op_delete;
  22378                         }
  22379                     }
  22380                 }
  22381 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_APACHE_SUPPORT */
  22382             if (err_info == SCHAN_GEN_RESP_ERROR_BUSY) {
  22383                 LOG_INFO(BSL_LS_SOC_SOCMEM,
  22384                          (BSL_META_U(unit,
  22385                                      "Delete table[%s]: Modfifo full\n"),
  22386                           SOC_MEM_NAME(unit, mem)));
  22387                 rv = SOC_E_BUSY;
  22388             } else if (err_info == SCHAN_GEN_RESP_ERROR_PARITY) {
  22389                 LOG_ERROR(BSL_LS_SOC_SOCMEM,
  22390                           (BSL_META_U(unit,
  22391                                       "Delete table[%s]: Parity Error Index %d\n"),
  22392                            SOC_MEM_NAME(unit, mem), index));
  22393                 rv = SOC_E_INTERNAL;
  22394             }
  22395             /* For Trident2, type is SCHAN_GEN_RESP_TYPE_ERROR, err_info is 0 */
  22396 #if defined(BCM_TRX_SUPPORT)
  22397             if (SOC_IS_TRX(unit) && (soc_mem_is_hashed(unit, mem))) {
  22398                 /* Try to recover */
  22399                 rv = soc_hash_mem_inline_recovery(unit, mem, &schan_msg,
  22400                                                     banks, entry);
  22401                 if (rv == SOC_E_NONE) {
  22402                       if (delete_retry < HASH_MEM_OP_RETRY_COUNT) {
  22403                           delete_retry++;
  22404                           if (soc_mem_generic_lookup(unit, mem, copyno, banks,
  22405                                                      entry, NULL, index_ptr) ==
  22406                                                      SOC_E_NOT_FOUND) {
  22407                             rv = SOC_E_NONE;
  22408                         } else {
  22409                             sal_memcpy(&schan_msg, &schan_msg_cpy, sizeof(schan_msg));
  22410                             LOG_WARN(BSL_LS_SOC_SOCMEM,
  22411                                      (BSL_META_U(unit,
  22412                                                  "unit %d: Retry Hash delete operation..\n"),
  22413                                       unit));
  22414                             goto _retry_op_delete;
  22415                         }
  22416                       }
  22417                 } else {
  22418                     LOG_ERROR(BSL_LS_SOC_SOCMEM,
  22419                               (BSL_META_U(unit,
  22420                                           "unit %d, table[%s]: Parity error recovery failed, return value: %d\n"),
  22421                                unit, SOC_MEM_NAME(unit, mem), rv));
  22422                 }
  22423             }
  22424 #endif
  22425         } else {
  22426 
  22427             rv = SOC_E_FAIL;
  22428 #if defined(BCM_TRIDENT2_SUPPORT)
  22429             if (SOC_IS_TD2_TT2(unit) && soc_mem_is_hashed(unit, mem) &&
  22430                 (type == SCHAN_GEN_RESP_TYPE_DELETED)) {
  22431                 rv = soc_hash_mem_inline_recovery(unit, mem, &schan_msg,
  22432                                                   banks, entry);
  22433                 if (rv == SOC_E_NONE) {
  22434                     if (delete_retry_attempt < HASH_MEM_OP_RETRY_COUNT) {
  22435                         delete_retry_attempt++;
  22436                         if (soc_mem_generic_lookup(unit, mem, copyno, banks,
  22437                                                      entry, NULL, index_ptr) ==
  22438                                                      SOC_E_NOT_FOUND) {
  22439                             rv = SOC_E_NONE;
  22440                         } else {
  22441                             sal_memcpy(&schan_msg, &schan_msg_cpy, sizeof(schan_msg));
  22442                             LOG_WARN(BSL_LS_SOC_SOCMEM,
  22443                                      (BSL_META_U(unit,
  22444                                                  "unit %d: Retry Hash delete operation..\n"),
  22445                                       unit));
  22446                             goto _retry_op_delete;
  22447                         }
  22448                     }
  22449                 } else {
  22450                     LOG_ERROR(BSL_LS_SOC_SOCMEM,
  22451                               (BSL_META_U(unit,
  22452                                           "unit %d, table[%s]: Parity error recovery failed, return value: %d\n"),
  22453                                unit, SOC_MEM_NAME(unit, mem), rv));
  22454                 }
  22455             }
  22456 #endif
  22457 #if defined(BCM_TRIUMPH3_SUPPORT)
  22458             if ((SOC_IS_TRIUMPH3(unit) || SOC_IS_TRIDENT(unit) ||
  22459                   SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) &&
  22460                  ((type == SCHAN_GEN_RESP_TYPE_L2_FIFO_FULL) ||
  22461                   (type == SCHAN_GEN_RESP_L2_MOD_FIFO_FULL))) {
  22462                 /*This is a Software Workaround for L2_MOD_FIFO. Sometimes an entry may be
  22463                   unable to be deleted when L2_MOD_FIFO is too busy. In this situation
  22464                   the L2_DELETE field in L2_MOD_FIFO_ENABLE will be disabled and retry the delete
  22465                   operation. After the deletion the L2_DELETE field will be enabled.*/
  22466                 if ((SOC_IS_TRIUMPH3(unit)) &&
  22467                      (type == SCHAN_GEN_RESP_L2_MOD_FIFO_FULL)) {
  22468                     if (soc_mem_generic_lookup(unit, mem, copyno, banks,
  22469                                                entry, NULL, index_ptr) ==
  22470                                                SOC_E_NOT_FOUND) {
  22471                         rv = SOC_E_NONE;
  22472                     } else {
  22473                         l2_delete = _soc_l2mode_fifo_enable_delete_field_get(unit);
  22474                         _soc_l2mode_fifo_enable_delete_field_set(unit, 0);
  22475                         del_disable = TRUE;
  22476                         sal_memcpy(&schan_msg, &schan_msg_cpy, sizeof(schan_msg));
  22477                         if (l2_delete && try_one_time) {
  22478                             LOG_INFO(BSL_LS_SOC_SOCMEM,
  22479                                      (BSL_META_U(unit,
  22480                                                  "L2_MOD_FIFO may be full,"
  22481                                                  "error type [%d],"
  22482                                                  "will delete again!\n"),
  22483                                                  type));
  22484                             try_one_time--;
  22485                             goto _retry_op_delete;
  22486                         } else {
  22487                             _soc_l2mode_fifo_enable_delete_field_set(unit, l2_delete);
  22488                         }
  22489                     }
  22490                 } else if ((SOC_IS_TRIDENT(unit) &&
  22491                         (type == SCHAN_GEN_RESP_TYPE_L2_FIFO_FULL)) ||
  22492                         ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) &&
  22493                           (type == SCHAN_GEN_RESP_L2_MOD_FIFO_FULL))) {
  22494                     LOG_INFO(BSL_LS_SOC_SOCMEM,
  22495                              (BSL_META_U(unit,
  22496                                          "L2_MOD_FIFO is full, error type [%d]"),
  22497                                          type));
  22498                     rv = SOC_E_FULL;
  22499                     MEM_UNLOCK(unit, mem);
  22500                     return rv;
  22501                 }
  22502             }
  22503 #endif
  22504         }
  22505     } else {
  22506         if (old_entry != NULL) {
  22507             sal_memcpy(old_entry, data, entry_dw * sizeof(uint32));
  22508         }
  22509 #ifdef BCM_TRIUMPH_SUPPORT
  22510         if (soc_feature(unit, soc_feature_etu_support) &&
  22511             mem == EXT_L2_ENTRY_2m) {
  22512             soc_mem_t ext_mem;
  22513             int ext_index;
  22514 
  22515             rv1 = soc_tcam_raw_index_to_mem_index(unit, index,
  22516                                                 &ext_mem, &ext_index);
  22517             if (SOC_FAILURE(rv1)) {
  22518 #if defined(BCM_TRIUMPH3_SUPPORT)
  22519                 if (soc_feature(unit, soc_feature_esm_correction) &&
  22520                       ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  22521                      (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  22522                     SOC_ESM_UNLOCK(unit);
  22523                 }
  22524 #endif
  22525                 MEM_UNLOCK(unit, mem);
  22526                 return rv1;
  22527             }
  22528             if (mem != ext_mem) {
  22529 #if defined(BCM_TRIUMPH3_SUPPORT)
  22530                 if (soc_feature(unit, soc_feature_esm_correction) &&
  22531                       ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  22532                      (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  22533                     SOC_ESM_UNLOCK(unit);
  22534                 }
  22535 #endif
  22536                 MEM_UNLOCK(unit, mem);
  22537                 return SOC_E_INTERNAL;
  22538             }
  22539             index = ext_index;
  22540         }
  22541 #endif /* BCM_TRIUMPH_SUPPORT */
  22542         if (index_ptr != NULL) {
  22543             *index_ptr = index;
  22544         }
  22545         SOP_MEM_STATE(unit, mem).count[copyno]--;
  22546 #if defined(BCM_TRIUMPH_SUPPORT)
  22547         if (mem == EXT_L2_ENTRYm) {
  22548             rv1 = soc_triumph_ext_l2_entry_update(unit, index, NULL);
  22549             if (SOC_FAILURE(rv1)) {
  22550 #if defined(BCM_TRIUMPH3_SUPPORT)
  22551                 if (soc_feature(unit, soc_feature_esm_correction) &&
  22552                       ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  22553                      (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  22554                     SOC_ESM_UNLOCK(unit);
  22555                 }
  22556 #endif
  22557                 MEM_UNLOCK(unit, mem);
  22558                 return rv1;
  22559             }
  22560         }
  22561 #endif /* BCM_TRIUMPH_SUPPORT */
  22562 #if defined(BCM_TRIUMPH3_SUPPORT)
  22563         if (mem == EXT_L2_ENTRY_1m || mem == EXT_L2_ENTRY_2m) {
  22564             rv1 = soc_triumph3_ext_l2_entry_update(unit, mem, index, NULL);
  22565             if (SOC_FAILURE(rv1)) {
  22566 #if defined(BCM_TRIUMPH3_SUPPORT)
  22567                 if (soc_feature(unit, soc_feature_esm_correction) &&
  22568                       ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  22569                      (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  22570                     SOC_ESM_UNLOCK(unit);
  22571                 }
  22572 #endif
  22573                 MEM_UNLOCK(unit, mem);
  22574                 return rv1;
  22575             }
  22576         }
  22577 #endif /* BCM_TRIUMPH3_SUPPORT */
  22578         if (!SOC_WARM_BOOT(unit)) {
  22579             /* Update cache if active */
  22580             cache = SOC_MEM_STATE(unit, mem).cache[copyno];
  22581             vmap = SOC_MEM_STATE(unit, mem).vmap[copyno];
  22582             index_valid = (index >= 0 &&
  22583                            index <= soc_mem_index_max(unit, mem));
  22584             if (!index_valid) {
  22585 #if defined(BCM_HURRICANE3_SUPPORT)
  22586                 if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) && 
  22587                     (mem == L2Xm) && 
  22588                     (index & SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit))) {
  22589                     overflow_index =
  22590                         (index & ~SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit));
  22591                     /* Check whether the entry is located at L2_OVERFLOW_ENTRY */
  22592                     if ((overflow_index) <=
  22593                         soc_mem_index_max(unit, L2_ENTRY_OVERFLOWm)) {
  22594                         /* update cache */
  22595                         cache =
  22596                             SOC_MEM_STATE(unit,
  22597                                         L2_ENTRY_OVERFLOWm).cache[copyno];
  22598                         vmap =
  22599                             SOC_MEM_STATE(unit,
  22600                                         L2_ENTRY_OVERFLOWm).vmap[copyno];
  22601                         if (cache != NULL && !SOC_MEM_TEST_SKIP_CACHE(unit) &&
  22602                             CACHE_VMAP_TST(vmap, overflow_index)) {
  22603                             CACHE_VMAP_CLR(vmap, index);
  22604                         }
  22605                         MEM_UNLOCK(unit, mem);
  22606                         return rv;
  22607                     } else {
  22608                         LOG_ERROR(BSL_LS_SOC_SOCMEM, 
  22609                             (BSL_META_U(unit, 
  22610                              "soc_mem_generic_delete: "
  22611                                               "invalid index %d for memory "
  22612                                               "L2_ENTRY_OVERFLOW\n"),
  22613                              overflow_index));
  22614                     }
  22615                 } else 
  22616 #endif /* BCM_HURRICANE3_SUPPORT */ 
  22617                 {                
  22618                     LOG_ERROR(BSL_LS_SOC_SOCMEM,
  22619                           (BSL_META_U(unit,
  22620                                       "soc_mem_generic_delete: "
  22621                                       "invalid index %d for memory %s\n"),
  22622                            index, SOC_MEM_NAME(unit, mem)));
  22623                 }
  22624 #if defined(BCM_TRIUMPH3_SUPPORT)
  22625                 if (soc_feature(unit, soc_feature_esm_correction) &&
  22626                       ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  22627                      (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  22628                     SOC_ESM_UNLOCK(unit);
  22629                 }
  22630 #endif
  22631                 MEM_UNLOCK(unit, mem);
  22632                 return SOC_E_INTERNAL;
  22633             }
  22634             if (index_valid && cache != NULL && CACHE_VMAP_TST(vmap, index)
  22635                 && !SOC_MEM_TEST_SKIP_CACHE(unit)) {
  22636                 if (_SOC_MEM_CHK_L2_MEM(mem)) {
  22637                     CACHE_VMAP_CLR(vmap, index);
  22638                     if (mem == L2_ENTRY_1m) {
  22639                         vmap = SOC_MEM_STATE(unit, L2_ENTRY_2m).vmap[copyno];
  22640                         CACHE_VMAP_CLR(vmap, index/2);
  22641                     } else if (mem == L2_ENTRY_2m) {
  22642                         vmap = SOC_MEM_STATE(unit, L2_ENTRY_1m).vmap[copyno];
  22643                         CACHE_VMAP_CLR(vmap, index*2);
  22644                         CACHE_VMAP_CLR(vmap, index*2 + 1);
  22645                     }
  22646                 } else {
  22647                     sal_memcpy(cache + index * entry_dw, null_entry, entry_dw * 4);
  22648                     CACHE_VMAP_CLR(vmap, index);
  22649                 }
  22650             }
  22651         }
  22652     }
  22653 #if defined(BCM_TRIUMPH3_SUPPORT)
  22654     if (soc_feature(unit, soc_feature_esm_correction) &&
  22655         ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  22656          (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ETU))) {
  22657         SOC_ESM_UNLOCK(unit);
  22658     }
  22659 #endif
  22660     MEM_UNLOCK(unit, mem);
  22661     return rv;
  22662 }
  22663 
  22664 /*
  22665  * Function:
  22666  *      soc_mem_search
  22667  * Purpose:
  22668  *      Search a memory for a key.
  22669  * Parameters:
  22670  *      mem               Memory to search
  22671  *      copyno               Which copy to search (if multiple copies)
  22672  *      index_ptr            OUT:
  22673  *                           If entry found gets the location of the entry.
  22674  *                           If not found, and table is sorted, gets the
  22675  *                           location of the insertion point.
  22676  *                           CAN NO LONGER BE NULL.
  22677  *      key_data                IN:  Data to search for
  22678  *      entry_data,             OUT: Data if found
  22679  *                           CAN NO LONGER BE NULL.  Must be big enough
  22680  *                           to handle the appropriate data.
  22681  *      lowest_match         IN:  For sorted tables only.
  22682  *                           If there are duplicate entries in the
  22683  *                           table, and lowest_match is 1, then the
  22684  *                           matching entry at the lowest index is
  22685  *                           returned.  If lowest_match is 0, then any
  22686  *                           of the matching entries may be picked at
  22687  *                           random, which can be faster.
  22688  * Returns:
  22689  *    SOC_E_NOT_FOUND
  22690  *                 Entry not found:  in this case, if
  22691  *                           table is sorted, then index_ptr gets the
  22692  *                           location in which the entry should be
  22693  *                           inserted.
  22694  *    SOC_E_NONE         Entry is found:  index_ptr gets location
  22695  *    SOC_E_XXX         If internal error occurs
  22696  * Notes:
  22697  *    A binary search is performed for a matching table entry.
  22698  *        The appropriate field(s) of entry_data are used for the key.
  22699  *        All other fields in entry_data are ignored.
  22700  *
  22701  *    If found, the index is stored in index_ptr, and if entry_data is
  22702  *        non-NULL, the contents of the found entry are written into it,
  22703  *        and 1 is returned.
  22704  *    If not found, the index of a correct insertion point for the
  22705  *        entry is stored in index_ptr and 0 is returned (unless this
  22706  *        is a hashed table).
  22707  *    If a table read error occurs, SOC_E_XXX is returned.
  22708  *
  22709  *    For the ARL table, all entries are searched.  On revision GSL and
  22710  *        higher, a hardware lookup feature is used.  For earlier
  22711  *        revisions, a software search is used, which is not
  22712  *        recommended since the ARL table may be under constant
  22713  *        update by the hardware.  For hardware lookup, the index_ptr
  22714  *        is written with -1.
  22715  *    For non-ARL sorted tables, only the entries known to contain data
  22716  *        are searched:
  22717  *        (index_min <= search_index < index_min + memInfo.count).
  22718  */
  22719 
  22720 int
  22721 soc_mem_search(int unit,
  22722                soc_mem_t mem,
  22723                int copyno,
  22724                int *index_ptr,
  22725                void *key_data,
  22726                void *entry_data,
  22727                int lowest_match)
  22728 {
  22729     int rv = 0;
  22730 #ifdef BCM_TRIDENT3_SUPPORT
  22731     soc_mem_t phy_mem;
  22732 #endif
  22733 
  22734     COMPILER_REFERENCE(rv);
  22735 
  22736 #ifdef BCM_TRIDENT3_SUPPORT
  22737     if (soc_feature(unit, soc_feature_flex_flow)) {
  22738         if (SOC_MEM_IS_VIEW(unit, mem)) {
  22739             rv = soc_mem_view_phy_mem_get(unit, mem, &phy_mem);
  22740             if (rv != SOC_E_NONE) {
  22741                 return rv;
  22742             }
  22743             mem = phy_mem;
  22744         }
  22745     }
  22746 #endif
  22747 
  22748     assert(soc_mem_is_sorted(unit, mem) ||
  22749            soc_mem_is_hashed(unit, mem) ||
  22750            soc_mem_is_cam(unit, mem) ||
  22751            soc_mem_is_cmd(unit, mem));
  22752     assert(entry_data);
  22753     assert(index_ptr);
  22754 
  22755     if (copyno == MEM_BLOCK_ANY) {
  22756         copyno = SOC_MEM_BLOCK_ANY(unit, mem);
  22757     }
  22758     assert(SOC_MEM_BLOCK_VALID(unit, mem, copyno));
  22759 
  22760 #ifdef BCM_TRX_SUPPORT
  22761     if (soc_feature(unit, soc_feature_generic_table_ops)) {
  22762         int32 banks = 0;
  22763         _SOC_MEM_REPLACE_MEM(unit, mem);
  22764         switch (mem) {
  22765         case L2Xm:
  22766         case L3_ENTRY_IPV4_UNICASTm:
  22767         case L3_ENTRY_IPV4_MULTICASTm:
  22768         case L3_ENTRY_IPV6_UNICASTm:
  22769         case L3_ENTRY_IPV6_MULTICASTm:
  22770         case EXACT_MATCH_2m:
  22771         case EXACT_MATCH_2_PIPE0m:
  22772         case EXACT_MATCH_2_PIPE1m:
  22773         case EXACT_MATCH_2_PIPE2m:
  22774         case EXACT_MATCH_2_PIPE3m:
  22775         case EXACT_MATCH_4m:
  22776         case EXACT_MATCH_4_PIPE0m:
  22777         case EXACT_MATCH_4_PIPE1m:
  22778         case EXACT_MATCH_4_PIPE2m:
  22779         case EXACT_MATCH_4_PIPE3m:
  22780 #ifdef BCM_ISM_SUPPORT
  22781         case L2_ENTRY_1m:
  22782         case L2_ENTRY_2m:
  22783         case L3_ENTRY_1m:
  22784         case L3_ENTRY_2m:
  22785         case L3_ENTRY_4m:
  22786         case VLAN_XLATE_EXTDm:
  22787         case MPLS_ENTRY_EXTDm:
  22788 #endif /* BCM_ISM_SUPPORT */
  22789         case EGR_VLAN_XLATEm:
  22790         case VLAN_XLATEm:
  22791         case MPLS_ENTRYm:
  22792         /* passthru */
  22793         /* coverity[fallthrough: FALSE] */
  22794 #ifdef BCM_TRIUMPH3_SUPPORT
  22795         case AXP_WRX_WCDm:
  22796         case AXP_WRX_SVP_ASSIGNMENTm:
  22797         case EXT_L2_ENTRY_1m:
  22798         case EXT_L2_ENTRY_2m:
  22799         case FT_SESSIONm:
  22800         case FT_SESSION_IPV6m:
  22801 #endif /* BCM_TRIUMPH3_SUPPORT */
  22802         case VLAN_MACm:
  22803 #ifdef BCM_TRIDENT2_SUPPORT
  22804         case ING_VP_VLAN_MEMBERSHIPm:
  22805         case EGR_VP_VLAN_MEMBERSHIPm:
  22806         case ING_DNAT_ADDRESS_TYPEm:
  22807         case L2_ENDPOINT_IDm:
  22808         case ENDPOINT_QUEUE_MAPm:
  22809 #endif /* BCM_TRIDENT2_SUPPORT */
  22810 #ifdef BCM_KATANA2_SUPPORT
  22811         case EGR_MP_GROUPm:
  22812 #endif
  22813 #ifdef BCM_SABER2_SUPPORT
  22814         case MP_GROUPm:
  22815 #endif
  22816 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  22817         case L3_ENTRY_SINGLEm:
  22818         case L3_ENTRY_DOUBLEm:
  22819         case L3_ENTRY_QUADm:
  22820         case MPLS_ENTRY_SINGLEm:
  22821         case VLAN_XLATE_1_SINGLEm:
  22822         case VLAN_XLATE_1_DOUBLEm:
  22823         case VLAN_XLATE_2_SINGLEm:
  22824         case VLAN_XLATE_2_DOUBLEm:
  22825         case EGR_VLAN_XLATE_1_SINGLEm:
  22826         case EGR_VLAN_XLATE_1_DOUBLEm:
  22827         case EGR_VLAN_XLATE_2_SINGLEm:
  22828         case EGR_VLAN_XLATE_2_DOUBLEm:
  22829         case SUBPORT_ID_TO_SGPP_MAPm:
  22830 #endif
  22831 #if defined(BCM_TOMAHAWK3_SUPPORT)
  22832         case L3_TUNNEL_SINGLEm:
  22833         case L3_TUNNEL_DOUBLEm:
  22834         case L3_TUNNEL_QUADm:
  22835 #endif
  22836 #ifdef BCM_HELIX5_SUPPORT
  22837         case FT_KEY_SINGLEm:
  22838         case FT_KEY_DOUBLEm:
  22839 #endif
  22840         case EXT_L2_ENTRYm:
  22841             if (soc_feature(unit, soc_feature_ism_memory) &&
  22842                 soc_mem_is_mview(unit, mem)) {
  22843                 banks = -1;
  22844             }
  22845             return soc_mem_generic_lookup(unit, mem, copyno, banks,
  22846                                           key_data, entry_data, index_ptr);
  22847         default:
  22848             break;
  22849         }
  22850     }
  22851 #endif /* BCM_TRX_SUPPORT */
  22852 
  22853 #ifdef BCM_FIREBOLT_SUPPORT
  22854     if (SOC_IS_FBX(unit)) {
  22855         switch (mem) {
  22856         case L2Xm:
  22857             return soc_fb_l2x_lookup(unit, key_data,
  22858                                      entry_data, index_ptr);
  22859 #if defined(INCLUDE_L3)
  22860         case L3_DEFIPm:
  22861         case L3_DEFIP_LEVEL1m:
  22862             return soc_fb_lpm_match(unit, key_data, entry_data, index_ptr);
  22863         case L3_ENTRY_IPV4_UNICASTm:
  22864         case L3_ENTRY_IPV4_MULTICASTm:
  22865         case L3_ENTRY_IPV6_UNICASTm:
  22866         case L3_ENTRY_IPV6_MULTICASTm:
  22867             return soc_fb_l3x_lookup(unit, key_data, entry_data, index_ptr);
  22868 #endif /* INCLUDE_L3 */
  22869         case VLAN_MACm:
  22870             return soc_fb_vlanmac_entry_lkup(unit, key_data, entry_data, index_ptr);
  22871         default:
  22872             break;
  22873         }
  22874     }
  22875 #endif /* BCM_FIREBOLT_SUPPORT */
  22876 
  22877     return _soc_mem_search(unit, mem, copyno, index_ptr, key_data,
  22878                            entry_data, lowest_match);
  22879 }
  22880 
  22881 
  22882 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) \
  22883          || defined(BCM_RAVEN_SUPPORT) || defined(BCM_HAWKEYE_SUPPORT)
  22884 
  22885 /*
  22886  * Function:
  22887  *    soc_mem_bank_insert
  22888  * Purpose:
  22889  *    Do a single insert to a banked hash table with bank selection
  22890  */
  22891 int
  22892 soc_mem_bank_insert(int unit,
  22893                     soc_mem_t mem,
  22894                     int32 banks,
  22895                     int copyno,
  22896                     void *entry_data,
  22897                     void *old_entry_data)
  22898 {
  22899     if (SOC_CONTROL(unit)->soc_mem_watch) {
  22900         if (SOC_CONTROL(unit)->prev_mem != mem) {
  22901             LOG_CLI((BSL_META_U(unit, "%d:%s MEM: %s\n"),
  22902                      unit, BSL_FUNC, SOC_MEM_NAME(unit, mem)));
  22903             SOC_CONTROL(unit)->prev_mem = mem;
  22904         }
  22905     }
  22906     if (soc_feature(unit, soc_feature_generic_table_ops)) {
  22907         return soc_mem_generic_insert(unit, mem, MEM_BLOCK_ANY,
  22908                                       banks, entry_data, old_entry_data, 0);
  22909     }
  22910 
  22911     switch (mem) {
  22912     case L2Xm:
  22913         return soc_fb_l2x_bank_insert(unit, banks,
  22914                                       (l2x_entry_t *)entry_data);
  22915 #if defined(INCLUDE_L3)
  22916     case L3_ENTRY_IPV4_UNICASTm:
  22917     case L3_ENTRY_IPV4_MULTICASTm:
  22918     case L3_ENTRY_IPV6_UNICASTm:
  22919     case L3_ENTRY_IPV6_MULTICASTm:
  22920         return soc_fb_l3x_bank_insert(unit, banks,
  22921                         (l3_entry_ipv6_multicast_entry_t *)entry_data);
  22922 #endif
  22923 #if defined(BCM_RAVEN_SUPPORT)
  22924     case VLAN_MACm:
  22925     if (SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit)) {
  22926         return soc_fb_vlanmac_entry_bank_ins(unit, banks,
  22927             (vlan_mac_entry_t *)entry_data);
  22928     } else {
  22929         return SOC_E_UNAVAIL;
  22930     }
  22931 #endif
  22932     default:
  22933         break;
  22934     }
  22935 
  22936     return SOC_E_UNAVAIL;
  22937 }
  22938 
  22939 int soc_fb_vlanmac_entry_bank_delete(int unit,
  22940                                      int32 banks,
  22941                                      vlan_mac_entry_t *entry_data)
  22942 {
  22943     return soc_fb_vlanmac_entry_del(unit, (vlan_mac_entry_t *)entry_data);
  22944 }
  22945 
  22946 /*
  22947  * Function:
  22948  *      soc_mem_bank_delete
  22949  * Purpose:
  22950  *      Do a single delete to a banked hash table with bank selection
  22951  * Parameters:
  22952  *      unit - StrataSwitch unit #
  22953  *      mem -  Memory in which the entry has to be deleted.
  22954  *      banks - For dual hashing, which halves are selected (inverted)
  22955  *      copyno - Specific copy of table/memory or all if -1.
  22956  *      entry_data - entry to be deleted.
  22957  *      old_entry_data (OUT) - If found, receives table index where
  22958  *                  entry was deleted.
  22959  * Returns:
  22960  *      SOC_E_INTERNAL if retries exceeded or other internal error
  22961  *      SOC_E_NOT_FOUND if the entry is not found.
  22962  *      SOC_E_NONE (0) on success (entry found):
  22963  */
  22964 int
  22965 soc_mem_bank_delete(int unit,
  22966                     soc_mem_t mem,
  22967                     int32 banks,
  22968                     int copyno,
  22969                     void *entry_data,
  22970                     void *old_entry_data)
  22971 {
  22972     if (soc_feature(unit, soc_feature_generic_table_ops)) {
  22973         return soc_mem_generic_delete(unit, mem, MEM_BLOCK_ANY,
  22974                                       banks, entry_data, old_entry_data, 0);
  22975     }
  22976 
  22977     switch (mem) {
  22978     case L2Xm:
  22979         return soc_fb_l2x_bank_delete(unit, banks,
  22980                                       (l2x_entry_t *)entry_data);
  22981 #if defined(INCLUDE_L3)
  22982     case L3_ENTRY_IPV4_UNICASTm:
  22983     case L3_ENTRY_IPV4_MULTICASTm:
  22984     case L3_ENTRY_IPV6_UNICASTm:
  22985     case L3_ENTRY_IPV6_MULTICASTm:
  22986         return soc_fb_l3x_bank_delete(unit, banks,
  22987                         (l3_entry_ipv6_multicast_entry_t *)entry_data);
  22988 #endif
  22989 #if defined(BCM_RAVEN_SUPPORT)
  22990     case VLAN_MACm:
  22991     if (SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit)) {
  22992         return soc_fb_vlanmac_entry_bank_delete(unit, banks,
  22993             (vlan_mac_entry_t *)entry_data);
  22994     } else {
  22995         return SOC_E_UNAVAIL;
  22996     }
  22997 #endif
  22998     default:
  22999         break;
  23000     }
  23001 
  23002     return SOC_E_UNAVAIL;
  23003 }
  23004 
  23005 
  23006 /*
  23007  * Function:
  23008  *    soc_mem_bank_search
  23009  * Purpose:
  23010  *    Search a banked hash table with bank selection
  23011  */
  23012 int
  23013 soc_mem_bank_search(int unit,
  23014                     soc_mem_t mem,
  23015                     uint8 banks,
  23016                     int copyno,
  23017                     int *index_ptr,
  23018                     void *key_data,
  23019                     void *entry_data)
  23020 {
  23021     switch (mem) {
  23022     case L2Xm:
  23023         return soc_fb_l2x_bank_lookup(unit, banks, (l2x_entry_t *)key_data,
  23024                                       (l2x_entry_t *)entry_data, index_ptr);
  23025 #if defined(INCLUDE_L3)
  23026     case L3_ENTRY_IPV4_UNICASTm:
  23027     case L3_ENTRY_IPV4_MULTICASTm:
  23028     case L3_ENTRY_IPV6_UNICASTm:
  23029     case L3_ENTRY_IPV6_MULTICASTm:
  23030         return soc_fb_l3x_bank_lookup(unit, banks,
  23031                         (l3_entry_ipv6_multicast_entry_t *)key_data,
  23032                         (l3_entry_ipv6_multicast_entry_t *)entry_data,
  23033                                         index_ptr);
  23034 #endif
  23035     default:
  23036         break;
  23037     }
  23038 
  23039     return SOC_E_UNAVAIL;
  23040 }
  23041 
  23042 /*
  23043  * Function:
  23044  *    _soc_mem_dual_hash_get
  23045  * Purpose:
  23046  *    Calcualte hash for dual hashed memories
  23047  */
  23048 
  23049 STATIC int
  23050 _soc_mem_dual_hash_get(int unit, soc_mem_t mem, int hash_sel, int bank,
  23051                        void *entry_data)
  23052 {
  23053     switch (mem) {
  23054     case L2Xm:
  23055 #if defined(BCM_TRX_SUPPORT)
  23056     if (SOC_IS_TRX(unit)) {
  23057         return soc_tr_l2x_entry_hash(unit, hash_sel, entry_data);
  23058     } else
  23059 #endif
  23060     {
  23061         return soc_fb_l2x_entry_hash(unit, hash_sel, entry_data);
  23062     }
  23063 #if defined(INCLUDE_L3)
  23064     case L3_ENTRY_IPV4_UNICASTm:
  23065     case L3_ENTRY_IPV4_MULTICASTm:
  23066     case L3_ENTRY_IPV6_UNICASTm:
  23067     case L3_ENTRY_IPV6_MULTICASTm:
  23068         return soc_fb_l3x_entry_hash(unit, hash_sel, entry_data);
  23069 #endif /* INCLUDE_L3 */
  23070 #if defined(BCM_RAVEN_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT)
  23071     case VLAN_MACm:
  23072 #if defined(BCM_TRIDENT2_SUPPORT)
  23073         if (SOC_IS_TD2_TT2(unit)) {
  23074             return soc_td2_vlan_xlate_entry_hash(unit, hash_sel, bank, entry_data);
  23075         } else
  23076 #endif
  23077         if (SOC_IS_RAVEN(unit)  || SOC_IS_HAWKEYE(unit)) {
  23078             return soc_fb_vlan_mac_entry_hash(unit, hash_sel, entry_data);
  23079         } else {
  23080             return -1;
  23081         }
  23082 #endif
  23083 
  23084 #if defined(BCM_TRX_SUPPORT)
  23085     case VLAN_XLATEm:
  23086 #if defined(BCM_TRIDENT2_SUPPORT)
  23087         if (SOC_IS_TD2_TT2(unit)) {
  23088 #ifdef BCM_APACHE_SUPPORT
  23089             if (SOC_IS_APACHE(unit)) {
  23090                 return soc_ap_vlan_xlate_entry_hash(unit, hash_sel, bank,
  23091                                                     entry_data);
  23092             } else
  23093 #endif /* BCM_APACHE_SUPPORT */
  23094 #ifdef BCM_TOMAHAWK_SUPPORT
  23095             if (SOC_IS_TOMAHAWKX(unit)) {
  23096                 return soc_th_vlan_xlate_entry_hash(unit, hash_sel, bank,
  23097                                                     entry_data);
  23098             } else
  23099 #endif /* BCM_TOMAHAWK_SUPPORT */
  23100             {
  23101                 return soc_td2_vlan_xlate_entry_hash(unit, hash_sel, bank,
  23102                                                      entry_data);
  23103             }
  23104         } else
  23105 #endif /* BCM_TRIDENT2_SUPPORT */
  23106         if (SOC_IS_TRX(unit)) {
  23107             return soc_tr_vlan_xlate_entry_hash(unit, hash_sel, entry_data);
  23108         }
  23109         return -1;
  23110 
  23111     case MPLS_ENTRYm:
  23112 #if defined(BCM_TRIDENT2_SUPPORT)
  23113         if (SOC_IS_TD2_TT2(unit)) {
  23114  #ifdef BCM_APACHE_SUPPORT
  23115             if (SOC_IS_APACHE(unit)) {
  23116                 return soc_ap_mpls_entry_hash(unit, hash_sel, bank,
  23117                                               entry_data);
  23118             } else
  23119 #endif /* BCM_APACHE_SUPPORT */
  23120  #ifdef BCM_TOMAHAWK_SUPPORT
  23121             if (SOC_IS_TOMAHAWKX(unit)) {
  23122 #ifdef BCM_TOMAHAWK3_SUPPORT
  23123                 if (SOC_IS_TOMAHAWK3(unit)) {
  23124                     return soc_tomahawk3_mpls_bank_entry_hash(unit, bank,
  23125                                                   entry_data);
  23126                 } else
  23127 #endif /* BCM_TOMAHAWK3_SUPPORT */
  23128                 {
  23129                 return soc_th_mpls_entry_hash(unit, hash_sel, bank,
  23130                                               entry_data);
  23131                 }
  23132             } else
  23133 #endif /* BCM_TOMAHAWK_SUPPORT */
  23134             {
  23135                 return soc_td2_mpls_entry_hash(unit, hash_sel, bank, entry_data);
  23136             }
  23137         } else
  23138 #endif /* BCM_TRIDENT2_SUPPORT */
  23139         if (SOC_IS_TR_VL(unit)) {
  23140             return soc_tr_mpls_entry_hash(unit, hash_sel, entry_data);
  23141         }
  23142         return -1;
  23143 
  23144     case EGR_VLAN_XLATEm:
  23145 #if defined(BCM_TRIDENT2_SUPPORT)
  23146         if (SOC_IS_TD2_TT2(unit)) {
  23147 #ifdef BCM_APACHE_SUPPORT
  23148             if (SOC_IS_APACHE(unit)) {
  23149                 return soc_ap_egr_vlan_xlate_entry_hash(unit, hash_sel,
  23150                                                         bank, entry_data);
  23151             } else
  23152 #endif /* BCM_APACHE_SUPPORT */
  23153 #ifdef BCM_TOMAHAWK_SUPPORT
  23154             if (SOC_IS_TOMAHAWKX(unit)) {
  23155                 return soc_th_egr_vlan_xlate_entry_hash(unit, hash_sel,
  23156                                                         bank, entry_data);
  23157             } else
  23158 #endif /* BCM_TOMAHAWK_SUPPORT */
  23159             {
  23160                 return soc_td2_egr_vlan_xlate_entry_hash(unit, hash_sel,
  23161                                                          bank, entry_data);
  23162             }
  23163         } else
  23164 #endif /* BCM_TRIDENT2_SUPPORT */
  23165         if (SOC_IS_TRX(unit)) {
  23166             return soc_tr_egr_vlan_xlate_entry_hash(unit, hash_sel, entry_data);
  23167         }
  23168         return -1;
  23169 #endif
  23170 
  23171 #ifdef BCM_TRIUMPH3_SUPPORT
  23172     case AXP_WRX_WCDm:
  23173     case AXP_WRX_SVP_ASSIGNMENTm:
  23174         if (SOC_IS_TRIUMPH3(unit)) {
  23175             return soc_tr3_wlan_entry_hash(unit, mem, hash_sel, entry_data);
  23176         }
  23177         return -1;
  23178     case FT_SESSIONm:
  23179     case FT_SESSION_IPV6m:
  23180         if (SOC_IS_TRIUMPH3(unit)) {
  23181             return soc_tr3_ft_session_entry_hash(unit, mem, hash_sel, entry_data);
  23182         }
  23183         return -1;
  23184 #endif /* BCM_TRIUMPH3_SUPPORT */
  23185 
  23186 #ifdef BCM_TRIDENT2_SUPPORT
  23187     case ING_VP_VLAN_MEMBERSHIPm:
  23188         if (SOC_IS_TD2_TT2(unit)) {
  23189 #ifdef BCM_HELIX5_SUPPORT
  23190             if (SOC_IS_HELIX5(unit)) {
  23191                 return soc_hx5_ing_vp_vlan_member_bank_entry_hash(unit, bank,
  23192                                                              entry_data);
  23193             } else
  23194 #endif /* BCM_HELIX5_SUPPORT */
  23195 #ifdef BCM_TRIDENT3_SUPPORT
  23196             if (SOC_IS_TRIDENT3X(unit)) {
  23197                 return soc_td3_ing_vp_vlan_member_bank_entry_hash(unit, bank,
  23198                                                              entry_data);
  23199             } else
  23200 #endif /* BCM_TRIDENT3_SUPPORT */
  23201             {
  23202             return soc_td2_ing_vp_vlan_member_entry_hash(unit, hash_sel, bank,
  23203                                                          entry_data);
  23204         }
  23205         }
  23206         return -1;
  23207     case EGR_VP_VLAN_MEMBERSHIPm:
  23208         if (SOC_IS_TD2_TT2(unit)) {
  23209 #ifdef BCM_HELIX5_SUPPORT
  23210             if (SOC_IS_HELIX5(unit)) {
  23211                 return soc_hx5_egr_vp_vlan_member_bank_entry_hash(unit, bank,
  23212                                                                   entry_data);
  23213             } else
  23214 #endif /* BCM_HELIX5_SUPPORT */
  23215 #ifdef BCM_TRIDENT3_SUPPORT
  23216             if (SOC_IS_TRIDENT3X(unit)) {
  23217                 return soc_td3_egr_vp_vlan_member_bank_entry_hash(unit, bank,
  23218                                                                   entry_data);
  23219             } else
  23220 #endif /* BCM_TRIDENT3_SUPPORT */
  23221             {
  23222             return soc_td2_egr_vp_vlan_member_entry_hash(unit, hash_sel, bank,
  23223                                                          entry_data);
  23224         }
  23225         }
  23226         return -1;
  23227     case ING_DNAT_ADDRESS_TYPEm:
  23228         if (SOC_IS_TD2_TT2(unit)) {
  23229 #ifdef BCM_TRIDENT3_SUPPORT
  23230             if (SOC_IS_TRIDENT3X(unit)) {
  23231                 return soc_td3_ing_dnat_address_type_bank_entry_hash(unit, bank,
  23232                                                                      entry_data);
  23233             } else
  23234 #endif /* BCM_TRIDENT3_SUPPORT */
  23235             {
  23236             return soc_td2_ing_dnat_address_type_entry_hash(unit, hash_sel, bank,
  23237                                                             entry_data);
  23238         }
  23239         }
  23240         return -1;
  23241     case L2_ENDPOINT_IDm:
  23242         if (SOC_IS_TD2_TT2(unit)) {
  23243 #ifdef BCM_APACHE_SUPPORT
  23244             if (SOC_IS_APACHE(unit)) {
  23245                 return soc_ap_l2_endpoint_id_entry_hash(unit, hash_sel, bank,
  23246                         entry_data);
  23247             } else
  23248 #endif /* BCM_APACHE_SUPPORT */
  23249             {
  23250                 return soc_td2_l2_endpoint_id_entry_hash(unit, hash_sel, bank,
  23251                         entry_data);
  23252             }
  23253         }
  23254         return -1;
  23255     case ENDPOINT_QUEUE_MAPm:
  23256         if (SOC_IS_TD2_TT2(unit)) {
  23257 #ifdef BCM_APACHE_SUPPORT
  23258             if (SOC_IS_APACHE(unit)) {
  23259                 return soc_ap_endpoint_queue_map_entry_hash(unit, hash_sel,
  23260                         bank, entry_data);
  23261             } else
  23262 #endif /* BCM_APACHE_SUPPORT */
  23263             {
  23264                 return soc_td2_endpoint_queue_map_entry_hash(unit, hash_sel,
  23265                         bank, entry_data);
  23266             }
  23267         }
  23268         return -1;
  23269 #endif /* BCM_TRIDENT2_SUPPORT */
  23270     case SUBPORT_ID_TO_SGPP_MAPm:
  23271 #ifdef BCM_TRIDENT3_SUPPORT
  23272         if (SOC_IS_TRIDENT3X(unit)) {
  23273             return soc_td3_subport_id_to_sgpp_map_bank_entry_hash(unit, bank,
  23274                                                                   entry_data);
  23275         }
  23276 #endif /* BCM_TRIDENT3_SUPPORT */
  23277         return -1;
  23278 
  23279     default:
  23280         return -1;
  23281     }
  23282 }
  23283 
  23284 /*
  23285  * Function:
  23286  *    _soc_mem_dual_hash_move
  23287  * Purpose:
  23288  *    Recursive move routine for dual hash auto-move inserts
  23289  *      Assumes feature already checked, mem locks taken.
  23290  */
  23291 
  23292 STATIC int
  23293 _soc_mem_dual_hash_move(int unit, soc_mem_t mem, /* Assumes memory locked */
  23294                         uint8 banks, int copyno, void *entry_data,
  23295                         dual_hash_info_t *hash_info,
  23296                         SHR_BITDCL *bucket_trace, int recurse_depth,
  23297                         int recurse_in )
  23298 {
  23299     int hash_base, cur_index = -1, base_index, bucket_index;
  23300     int dest_hash_base, dest_bucket_index = -1;
  23301     int half_bucket, hw_war = 0, trace_size = 0;
  23302     SHR_BITDCL *trace;               /* Buckets involved in recursion.   */
  23303     int rv = SOC_E_NONE, bix, i, found = FALSE;
  23304     uint8 this_bank_bit, this_bank_only, that_bank_only, this_hash, that_hash;
  23305     uint32 move_entry[SOC_MAX_MEM_WORDS];
  23306     int recurse = recurse_in;
  23307 
  23308     if (recurse_depth < 0) {
  23309         return SOC_E_FULL;
  23310     }
  23311     if (((SOC_IS_TRIUMPH(unit) || SOC_IS_VALKYRIE(unit) ||
  23312           SOC_IS_SCORPION(unit) || SOC_IS_ENDURO(unit)) &&
  23313          (mem == EGR_VLAN_XLATEm)) ||
  23314          soc_feature(unit, soc_feature_hr2_dual_hash)) {
  23315         /* Handle h/w limitation for this memory */
  23316         hw_war = TRUE;
  23317     }
  23318     /* Stack variables initialization & memory allocations.*/
  23319     half_bucket = hash_info->bucket_size / 2;
  23320 
  23321     /* Keep back trace of all buckets affected by recursion. */
  23322     if (NULL == bucket_trace) {
  23323         trace_size =
  23324             SHR_BITALLOCSIZE(soc_mem_index_count(unit, hash_info->base_mem)/
  23325                              half_bucket);
  23326         trace =  sal_alloc(trace_size, "Dual hash");
  23327         if (NULL == trace) {
  23328             return (SOC_E_MEMORY);
  23329         }
  23330         recurse = 0;
  23331     } else {
  23332         trace = bucket_trace;
  23333         recurse++;
  23334     }
  23335 
  23336     /* Iterate over banks. */
  23337     for (bix = 0; bix < 2; bix++) {
  23338         this_bank_bit =
  23339             (bix == 0) ? SOC_MEM_HASH_BANK0_BIT : SOC_MEM_HASH_BANK1_BIT;
  23340         this_bank_only =
  23341             (bix == 0) ? SOC_MEM_HASH_BANK0_ONLY : SOC_MEM_HASH_BANK1_ONLY;
  23342         that_bank_only =
  23343             (bix == 0) ? SOC_MEM_HASH_BANK1_ONLY : SOC_MEM_HASH_BANK0_ONLY;
  23344         this_hash = (bix == 0) ? hash_info->hash_sel0 : hash_info->hash_sel1;
  23345         that_hash = (bix == 0) ? hash_info->hash_sel1 : hash_info->hash_sel0;
  23346 
  23347         if (banks & this_bank_bit) {
  23348             /* Not this bank */
  23349             continue;
  23350         }
  23351         hash_base = _soc_mem_dual_hash_get(unit, mem, this_hash, bix,
  23352                                            entry_data);
  23353         if (hash_base == -1) {
  23354             rv = SOC_E_INTERNAL;
  23355             break;
  23356         }
  23357 
  23358         /* Bucket half is based on bank id.      */
  23359         bucket_index = hash_base * hash_info->bucket_size + bix * half_bucket;
  23360 
  23361         /* Recursion trace initialization. */
  23362         if (NULL == bucket_trace) {
  23363             sal_memset(trace, 0, trace_size);
  23364         }
  23365         SHR_BITSET(trace, bucket_index/half_bucket);
  23366 
  23367         /* Iterate over entries in the half-bucket.. */
  23368         for (i = 0; i < (hash_info->bucket_size / 2); i++) {
  23369             cur_index = base_index = bucket_index + i;
  23370             /* Read bucket entry. */
  23371             rv = soc_mem_read(unit, hash_info->base_mem, copyno,
  23372                               base_index, move_entry);
  23373             if (SOC_FAILURE(rv)) {
  23374                 rv = SOC_E_MEMORY;
  23375                 break;
  23376             }
  23377             /* Is this an exception mem OR
  23378                Are we already in recursion or will we be in recursion */
  23379             if (hw_war || recurse || recurse_depth) {
  23380                 /* Calculate destination entry hash value. */
  23381                 dest_hash_base = _soc_mem_dual_hash_get(unit, mem, that_hash,
  23382                                                         !bix, move_entry);
  23383                 if (dest_hash_base == -1) {
  23384                     rv = SOC_E_INTERNAL;
  23385                     break;
  23386                 }
  23387                 dest_bucket_index =
  23388                     dest_hash_base * hash_info->bucket_size + (!bix) * half_bucket;
  23389 
  23390                 /* Make sure we are not touching buckets in bucket trace. */
  23391                 if(SHR_BITGET(trace, dest_bucket_index/half_bucket)) {
  23392                     continue;
  23393                 }
  23394             }
  23395 
  23396             /* Attempt to insert it into the other bank. */
  23397             if (hw_war) {
  23398                 int e, notfound = TRUE;
  23399                 uint32 tmp_entry[SOC_MAX_MEM_WORDS];
  23400 
  23401                 for (e = 0; e < (hash_info->bucket_size / 2); e++) {
  23402                     rv = soc_mem_read(unit, mem, copyno,
  23403                                       dest_bucket_index + e, tmp_entry);
  23404                     if (SOC_FAILURE(rv)) {
  23405                         rv = SOC_E_MEMORY;
  23406                         break;
  23407                     }
  23408                     if (soc_mem_field32_get(unit, mem, tmp_entry, VALIDf)) {
  23409                         continue;
  23410                     } else {
  23411                         rv = soc_mem_write(unit, mem, copyno, dest_bucket_index + e,
  23412                                            move_entry);
  23413                         if (SOC_FAILURE(rv)) {
  23414                             rv = SOC_E_MEMORY;
  23415                             break;
  23416                         }
  23417                         notfound = FALSE;
  23418                         break;
  23419                     }
  23420                 }
  23421                 if ((rv != SOC_E_MEMORY) && (notfound == TRUE)) {
  23422                     rv = SOC_E_FULL;
  23423                 }
  23424             } else {
  23425                 rv = soc_mem_bank_insert(unit, mem, that_bank_only,
  23426                                          copyno, move_entry, NULL);
  23427             }
  23428             if (SOC_FAILURE(rv)) {
  23429                 if (rv != SOC_E_FULL) {
  23430                     if ((rv == SOC_E_EXISTS) &&
  23431                         bsl_check(bslLayerSoc, bslSourceCommon,
  23432                                   bslSeverityVerbose, unit)) {
  23433                         soc_mem_entry_dump(unit, mem, move_entry,
  23434                                            BSL_VERBOSE|BSL_LS_SOC_COMMON);
  23435                     }
  23436                     break;
  23437                 }
  23438                 /* Recursive call - attempt to create a slot
  23439                    in other bank bucket. */
  23440                 rv = _soc_mem_dual_hash_move(unit, mem, that_bank_only,
  23441                                              copyno, move_entry, hash_info,
  23442                                              trace, recurse_depth - 1,
  23443                                              recurse);
  23444                 if (SOC_FAILURE(rv)) {
  23445                     if (rv != SOC_E_FULL) {
  23446                         if ((rv == SOC_E_EXISTS) &&
  23447                             bsl_check(bslLayerSoc, bslSourceCommon,
  23448                                       bslSeverityVerbose, unit)) {
  23449                             soc_mem_entry_dump(unit, mem, move_entry,
  23450                                                BSL_VERBOSE|BSL_LS_SOC_COMMON);
  23451                         }
  23452                         break;
  23453                     }
  23454                     continue;
  23455                 }
  23456             }
  23457             /* Entry was moved successfully. */
  23458             found = TRUE;
  23459             /* Delete old entry from original location */
  23460             if (hw_war) {
  23461                 /* A entry clear is not needed as the entry is written over later on.
  23462                    soc_mem_field32_set(unit, mem, &move_entry, VALIDf, 0);
  23463                    rv = soc_mem_write(unit, mem, copyno, cur_index, move_entry);
  23464                 */
  23465                 /*
  23466                  * For L2Xm, the related Limit count (System, Port/Trunk and
  23467                  * VLAN/VFI mac count) will be updated automatically through
  23468                  * normal L2 insert operation, the Limit count will not be
  23469                  * updated by calling soc_mem_write().
  23470                  */
  23471                 if (soc_feature(unit, soc_feature_hr2_dual_hash) &&
  23472                     (mem == L2Xm)) {
  23473                     /* Clear the move_entry before L2 insert */
  23474                     soc_mem_field32_set(unit, mem, &move_entry, VALIDf, 0);
  23475                     rv = soc_mem_write(unit, mem, copyno,
  23476                                        cur_index, move_entry);
  23477                 }
  23478             } else {
  23479                 rv = soc_mem_bank_delete(unit, mem, this_bank_only, MEM_BLOCK_ANY,
  23480                                             move_entry, NULL);
  23481             }
  23482             break;
  23483         }  /* Bucket iteration loop. */
  23484 
  23485         if (found || ((rv < 0) && (rv != SOC_E_FULL))) {
  23486             break;
  23487         }
  23488     } /* Bank iteration loop. */
  23489 
  23490     if ((rv < 0) && (rv != SOC_E_FULL)) {
  23491         if (NULL == bucket_trace) sal_free(trace);
  23492         return rv;
  23493     }
  23494 
  23495     if (!found) {
  23496         if (NULL == bucket_trace) sal_free(trace);
  23497         return SOC_E_FULL;
  23498     }
  23499     if (hw_war) {
  23500         if (soc_feature(unit, soc_feature_hr2_dual_hash) &&
  23501             (mem == L2Xm)) {
  23502             /*
  23503              * For L2Xm, the related Limit count (System, Port/Trunk and
  23504              * VLAN/VFI mac count) will be updated automatically through
  23505              * normal L2 insert operation, the Limit count will not be
  23506              * updated by calling soc_mem_write().
  23507              */
  23508             rv = soc_mem_bank_insert(unit, mem, this_bank_only, copyno,
  23509                                      entry_data, NULL);
  23510         } else {
  23511         rv = soc_mem_write(unit, mem, copyno, cur_index, entry_data);
  23512         }
  23513     } else {
  23514             rv = soc_mem_bank_insert(unit, mem, this_bank_only,copyno,
  23515                                         entry_data, NULL);
  23516     }
  23517     if (NULL == bucket_trace) sal_free(trace);
  23518     return (rv);
  23519 }
  23520 
  23521 /*
  23522  * Function:
  23523  *    _soc_mem_dual_hash_insert
  23524  * Purpose:
  23525  *    Dual hash auto-move inserts
  23526  *      Assumes feature already checked
  23527  */
  23528 
  23529 int
  23530 _soc_mem_dual_hash_insert(int unit,
  23531                           soc_mem_t mem,     /* Assumes memory locked */
  23532                           int copyno,
  23533                           void *entry_data,
  23534                           void *old_entry_data,
  23535                           int recurse_depth)
  23536 {
  23537     int rv = SOC_E_NONE;
  23538     dual_hash_info_t hash_info = {0};
  23539 #ifdef BCM_TRIUMPH3_SUPPORT
  23540     uint32 regval;
  23541 #endif /* BCM_TRIUMPH3_SUPPORT */
  23542 
  23543     switch (mem) {
  23544     case L2Xm:
  23545         rv = soc_mem_bank_insert(unit, mem, 0, copyno,
  23546                                  entry_data, old_entry_data);
  23547         if (rv != SOC_E_FULL || recurse_depth == 0) {
  23548             return rv;
  23549         }
  23550         SOC_IF_ERROR_RETURN
  23551             (soc_fb_l2x_entry_bank_hash_sel_get(unit, 0,
  23552                                                 &(hash_info.hash_sel0)));
  23553         SOC_IF_ERROR_RETURN
  23554             (soc_fb_l2x_entry_bank_hash_sel_get(unit, 1,
  23555                                                 &(hash_info.hash_sel1)));
  23556         if (hash_info.hash_sel0 == hash_info.hash_sel1) {
  23557             /* Can't juggle the entries */
  23558             return SOC_E_FULL;
  23559         }
  23560         hash_info.bucket_size = SOC_L2X_BUCKET_SIZE;
  23561         hash_info.base_mem = mem;
  23562 
  23563         /* Time to shuffle the entries */
  23564         SOC_IF_ERROR_RETURN(soc_l2x_freeze(unit));
  23565         rv = _soc_mem_dual_hash_move(unit, mem, SOC_MEM_HASH_BANK_BOTH,
  23566                                      copyno, entry_data, &hash_info,
  23567                                      NULL, recurse_depth - 1,0);
  23568         SOC_IF_ERROR_RETURN(soc_l2x_thaw(unit));
  23569         return rv;
  23570 #ifdef BCM_TRX_SUPPORT
  23571     case VLAN_XLATEm:
  23572         if (!SOC_IS_TRX(unit)) {
  23573             break;
  23574         }
  23575         /* Fall thru for TRX (VLAN_XLATE & VLAN_MAC are a shared table) */
  23576 #endif /* BCM_TRX_SUPPORT */
  23577 #if defined(BCM_RAVEN_SUPPORT) || defined(BCM_TRX_SUPPORT)
  23578     case VLAN_MACm:
  23579         if (SOC_IS_FIREBOLT2(unit)) {
  23580             break;
  23581         }
  23582     rv = soc_mem_bank_insert(unit, mem, 0, copyno,
  23583                                  entry_data, old_entry_data);
  23584         if (rv != SOC_E_FULL || recurse_depth == 0) {
  23585             return rv;
  23586         }
  23587 #ifdef BCM_TRX_SUPPORT
  23588         if (mem == VLAN_XLATEm) {
  23589             SOC_IF_ERROR_RETURN
  23590                 (soc_tr_hash_sel_get(unit, mem, 0, &hash_info.hash_sel0));
  23591             SOC_IF_ERROR_RETURN
  23592                 (soc_tr_hash_sel_get(unit, mem, 1, &hash_info.hash_sel1));
  23593             hash_info.bucket_size = SOC_VLAN_XLATE_BUCKET_SIZE;
  23594         } else
  23595 #endif /* BCM_TRX_SUPPORT */
  23596         {
  23597             SOC_IF_ERROR_RETURN
  23598                 (soc_fb_rv_vlanmac_hash_sel_get(unit, 0, &(hash_info.hash_sel0)));
  23599 
  23600             SOC_IF_ERROR_RETURN
  23601                 (soc_fb_rv_vlanmac_hash_sel_get(unit, 1, &(hash_info.hash_sel1)));
  23602             hash_info.bucket_size = SOC_VLAN_MAC_BUCKET_SIZE;
  23603         }
  23604         if (hash_info.hash_sel0 == hash_info.hash_sel1) {
  23605             /* Can't juggle the entries */
  23606             return SOC_E_FULL;
  23607         }
  23608         hash_info.base_mem = mem;
  23609         /* Time to shuffle the entries */
  23610         if (SOC_IS_TRX(unit)) {
  23611             soc_mem_lock(unit, VLAN_XLATEm);
  23612         }
  23613         soc_mem_lock(unit, VLAN_MACm);
  23614         rv = _soc_mem_dual_hash_move(unit, mem, SOC_MEM_HASH_BANK_BOTH,
  23615                                      copyno, entry_data, &hash_info,
  23616                                      NULL, recurse_depth - 1,0);
  23617         soc_mem_unlock(unit, VLAN_MACm);
  23618         if (SOC_IS_TRX(unit)) {
  23619             soc_mem_unlock(unit, VLAN_XLATEm);
  23620         }
  23621         return rv;
  23622 #endif /* BCM_RAVEN_SUPPORT || BCM_TRX_SUPPORT */
  23623 #if defined(INCLUDE_L3)
  23624     case L3_ENTRY_ONLYm:
  23625     case L3_ENTRY_IPV4_UNICASTm:
  23626     case L3_ENTRY_IPV4_MULTICASTm:
  23627     case L3_ENTRY_IPV6_UNICASTm:
  23628     case L3_ENTRY_IPV6_MULTICASTm:
  23629         return soc_fb_l3x_insert(unit, entry_data);
  23630 #if defined(BCM_TOMAHAWK3_SUPPORT)
  23631     case L3_TUNNEL_SINGLEm:
  23632     case L3_TUNNEL_DOUBLEm:
  23633     case L3_TUNNEL_QUADm:
  23634         hash_info.bucket_size = SOC_L3_TUNNEL_BUCKET_SIZE;
  23635         break;
  23636 #endif /* BCM_TOMAHAWK3_SUPPORT */
  23637 #endif /* INCLUDE_L3 */
  23638 #if defined(BCM_TRX_SUPPORT)
  23639     case MPLS_ENTRYm:
  23640         hash_info.bucket_size = SOC_MPLS_ENTRY_BUCKET_SIZE;
  23641         break;
  23642     case EGR_VLAN_XLATEm:
  23643         hash_info.bucket_size = SOC_EGR_VLAN_XLATE_BUCKET_SIZE;
  23644         break;
  23645     case AXP_WRX_WCDm:
  23646     case AXP_WRX_SVP_ASSIGNMENTm:
  23647         hash_info.bucket_size = SOC_WLAN_BUCKET_SIZE;
  23648         break;
  23649 #ifdef BCM_TRIUMPH3_SUPPORT
  23650     case FT_SESSIONm:
  23651     case FT_SESSION_IPV6m:
  23652         SOC_IF_ERROR_RETURN(READ_FT_CONFIGr(unit, &regval));
  23653         hash_info.bucket_size = 1 << soc_reg_field_get(unit,
  23654                                             FT_CONFIGr, regval, TABLE_SIZEf);
  23655         break;
  23656 #endif /* BCM_TRIUMPH3_SUPPORT */
  23657 #ifdef BCM_TRIDENT2_SUPPORT
  23658     case ING_VP_VLAN_MEMBERSHIPm:
  23659         hash_info.bucket_size = SOC_ING_VP_VLAN_MEMBER_BUCKET_SIZE;
  23660         break;
  23661     case EGR_VP_VLAN_MEMBERSHIPm:
  23662         hash_info.bucket_size = SOC_EGR_VP_VLAN_MEMBER_BUCKET_SIZE;
  23663         break;
  23664     case ING_DNAT_ADDRESS_TYPEm:
  23665         hash_info.bucket_size = SOC_ING_DNAT_ADDRESS_TYPE_BUCKET_SIZE;
  23666         break;
  23667     case L2_ENDPOINT_IDm:
  23668         hash_info.bucket_size = SOC_L2_ENDPOINT_ID_BUCKET_SIZE;
  23669         break;
  23670     case ENDPOINT_QUEUE_MAPm:
  23671         hash_info.bucket_size = SOC_ENDPOINT_QUEUE_MAP_BUCKET_SIZE;
  23672         break;
  23673 #ifdef BCM_TRIDENT3_SUPPORT
  23674     case SUBPORT_ID_TO_SGPP_MAPm:
  23675         hash_info.bucket_size = SOC_SUBPORT_ID_TO_SGPP_MAP_BUCKET_SIZE;
  23676         break;
  23677 #endif /* BCM_TRIDENT3_SUPPORT */
  23678 #endif /* BCM_TRIDENT2_SUPPORT */
  23679 #ifdef BCM_KATANA2_SUPPORT
  23680     case EGR_MP_GROUPm:
  23681         hash_info.bucket_size = SOC_EGR_MP_GROUP_BUCKET_SIZE;
  23682         break;
  23683 #endif
  23684 #ifdef BCM_SABER2_SUPPORT
  23685     case MP_GROUPm:
  23686         hash_info.bucket_size = SOC_EGR_MP_GROUP_BUCKET_SIZE;
  23687         break;
  23688 #endif
  23689 #endif /* BCM_TRX_SUPPORT */
  23690     default:
  23691         return SOC_E_UNAVAIL;
  23692     }
  23693 
  23694 #if defined(BCM_TRX_SUPPORT)
  23695     /*
  23696      * If a block of physical memory is not shared by multiple table and
  23697      * it is not modified by hardware, we should be able to use general case
  23698      * for dual hash insert
  23699      */
  23700     rv = soc_mem_bank_insert(unit, mem, 0, copyno, entry_data, old_entry_data);
  23701 
  23702     if (rv != SOC_E_FULL || recurse_depth == 0) {
  23703         return rv;
  23704     }
  23705 
  23706 #ifdef BCM_TRIDENT2_SUPPORT
  23707     if (SOC_IS_TD2_TT2(unit)) {
  23708         if ((!SOC_IS_TRIDENT3X(unit)) && (!SOC_IS_TOMAHAWK3(unit))) {
  23709         SOC_IF_ERROR_RETURN
  23710             (soc_td2_hash_sel_get(unit, mem, 0, &hash_info.hash_sel0));
  23711         SOC_IF_ERROR_RETURN
  23712             (soc_td2_hash_sel_get(unit, mem, 1, &hash_info.hash_sel1));
  23713         }
  23714     } else
  23715 #endif /* BCM_TRIDENT2_SUPPORT */
  23716     {
  23717         SOC_IF_ERROR_RETURN
  23718             (soc_tr_hash_sel_get(unit, mem, 0, &hash_info.hash_sel0));
  23719         SOC_IF_ERROR_RETURN
  23720             (soc_tr_hash_sel_get(unit, mem, 1, &hash_info.hash_sel1));
  23721     }
  23722     if (hash_info.hash_sel0 == hash_info.hash_sel1) {
  23723         /* Can't juggle the entries */
  23724         return SOC_E_FULL;
  23725     }
  23726 #if defined(BCM_TRIUMPH3_SUPPORT)
  23727     if (mem == FT_SESSIONm || mem == FT_SESSION_IPV6m) {
  23728         /* Can't juggle the entries - FT_SESSION entries don't move */
  23729         return SOC_E_FULL;
  23730     }
  23731 #endif /* BCM_TRIUMPH3_SUPPORT */
  23732     hash_info.base_mem = mem;
  23733     /* Time to shuffle the entries */
  23734     soc_mem_lock(unit, mem);
  23735     rv = _soc_mem_dual_hash_move(unit, mem, SOC_MEM_HASH_BANK_BOTH, copyno,
  23736                                  entry_data, &hash_info, NULL,
  23737                                  recurse_depth - 1,0);
  23738     soc_mem_unlock(unit, mem);
  23739 #endif /* BCM_TRX_SUPPORT */
  23740 
  23741     return rv;
  23742 }
  23743 
  23744 #ifdef BCM_ISM_SUPPORT
  23745 /*
  23746  * Function:
  23747  *    _soc_mem_multi_hash_insert
  23748  * Purpose:
  23749  *    N hash auto-move inserts
  23750  *      Assumes feature already checked
  23751  */
  23752 
  23753 STATIC int
  23754 _soc_mem_multi_hash_insert(int unit, soc_mem_t mem, int copyno,
  23755                            void *entry_data, void *old_entry_data,
  23756                            int recurse_depth)
  23757 {
  23758     int rv = SOC_E_NONE;
  23759     rv = soc_mem_bank_insert(unit, mem, SOC_MEM_HASH_BANK_ALL, copyno,
  23760                              entry_data, old_entry_data);
  23761     if (rv != SOC_E_FULL) {
  23762         return rv;
  23763     }
  23764     /* Time to shuffle the entries */
  23765     soc_mem_lock(unit, mem);
  23766     rv = soc_mem_multi_hash_move(unit, mem, SOC_MEM_HASH_BANK_ALL, copyno,
  23767                                  entry_data, NULL, NULL, recurse_depth-1);
  23768     soc_mem_unlock(unit, mem);
  23769     return rv;
  23770 }
  23771 #endif /* BCM_ISM_SUPPORT */
  23772 
  23773 #ifdef BCM_TRIDENT2_SUPPORT
  23774 /*Function declaration */
  23775 
  23776 #define NUM_ENT        4
  23777 #define NUM_ENT_TD3    16
  23778 
  23779 typedef struct _soc_breadth_bucket2_s {
  23780     int8 src_bix;
  23781     int8 level;
  23782     uint8 status;           /* l3 only */
  23783     uint8 src_ent;
  23784 
  23785     uint8 width[NUM_ENT];   /* l3 only */
  23786     soc_mem_t mem[NUM_ENT]; /*l3 only */
  23787     uint32 bucket;
  23788     uint32 p_bucket;        /* l3 only */
  23789     uint32 s_bucket;
  23790     int    n_bucket;
  23791     union {
  23792         l2x_entry_t l2[4];
  23793 #ifdef BCM_TRIDENT3_SUPPORT
  23794         vlan_xlate_1_single_entry_t vlan[4];
  23795         egr_vlan_xlate_1_single_entry_t egr_vlan[4];
  23796 #endif /* BCM_TRIDENT3_SUPPORT */
  23797 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  23798         l3_entry_only_single_entry_t l3_single[4];
  23799         mpls_entry_single_entry_t mpls[4];
  23800 #endif /* BCM_TRIDENT3_SUPPORT || BCM_TOMAHAWK3_SUPPORT */
  23801 #ifdef BCM_TOMAHAWK3_SUPPORT
  23802         mpls_entry_single_entry_t mpls_1[4];
  23803 #endif /* BCM_TOMAHAWK3_SUPPORT */
  23804         l3_entry_only_entry_t l3[4];
  23805         exact_match_2_entry_t em_2[4];
  23806         exact_match_4_entry_t em_4[4];
  23807     } e;
  23808 } _soc_breadth_bucket2_t;
  23809 
  23810 typedef struct _soc_breadth_bucket_s {
  23811     soc_mem_t src_mem;
  23812     uint8 src_bix;
  23813     uint8 status;
  23814     uint8 src_width;
  23815     uint8 src_ent;
  23816     uint32 src_bkt_idx;
  23817     uint32 bucket;
  23818     union {
  23819         l2x_entry_t l2[4];
  23820 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  23821         l3_entry_only_single_entry_t l3_single[4];
  23822         l3_entry_quad_entry_t           l3_quad[4];
  23823         mpls_entry_single_entry_t mpls[4];
  23824 #endif /* BCM_TRIDENT3_SUPPORT || BCM_TOMAHAWK3_SUPPORT */
  23825 #ifdef BCM_TRIDENT3_SUPPORT
  23826         vlan_xlate_1_single_entry_t vlan[4];
  23827         egr_vlan_xlate_1_single_entry_t egr_vlan[4];
  23828 #endif
  23829 #ifdef BCM_TOMAHAWK3_SUPPORT
  23830         tunnel_quad_entry_t tunnel_quad[4];
  23831 #endif
  23832         l3_entry_only_entry_t l3[4];
  23833         exact_match_2_entry_t em_2[4];
  23834         exact_match_4_entry_t em_4[4];
  23835     } e;
  23836 } _soc_breadth_bucket_t;
  23837 
  23838 STATIC INLINE int
  23839 _soc_mem_shared_hash_init(int unit, soc_mem_t mem,
  23840                           SHR_BITDCL **trace,
  23841                           _soc_hash_bank_info_t *bank_info,
  23842                           int num_levels,
  23843                           _soc_breadth_bucket_t **buckets,
  23844                           _soc_breadth_bucket2_t **buckets2);
  23845 
  23846 STATIC int
  23847 _soc_mem_shared_hash_incr_per_entry(int unit, soc_mem_t mem, void *old_entry,
  23848                                     void *new_entry)
  23849 {
  23850     if (mem == L2Xm) {
  23851         return 1;
  23852     } else {
  23853         int oi = 1;
  23854         if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_ONLYm, KEY_TYPEf)) {
  23855             int key_type;
  23856 
  23857             key_type = soc_mem_field32_get(unit, L3_ENTRY_ONLYm,
  23858                                            old_entry, KEY_TYPEf);
  23859             switch (key_type) {
  23860             case TD2_L3_HASH_KEY_TYPE_V4UC:
  23861             case TD2_L3_HASH_KEY_TYPE_TRILL:
  23862             case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN:
  23863             case TD2_L3_HASH_KEY_TYPE_FCOE_HOST:
  23864             case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP:
  23865                 oi = 1;
  23866                 break;
  23867             case TD2_L3_HASH_KEY_TYPE_V4UC_EXT:
  23868             case TD2_L3_HASH_KEY_TYPE_V4MC:
  23869             case TD2_L3_HASH_KEY_TYPE_V4L2MC:
  23870             case TD2_L3_HASH_KEY_TYPE_V4L2VPMC:
  23871             case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT:
  23872             case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT:
  23873             case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT:
  23874             case TD2_L3_HASH_KEY_TYPE_DST_NAT:
  23875             case TD2_L3_HASH_KEY_TYPE_DST_NAPT:
  23876             case TD2_L3_HASH_KEY_TYPE_V6UC:
  23877                 oi = 2;
  23878                 break;
  23879             case TD2_L3_HASH_KEY_TYPE_V6UC_EXT:
  23880             case TD2_L3_HASH_KEY_TYPE_V6MC:
  23881             case TD2_L3_HASH_KEY_TYPE_V6L2MC:
  23882             case TD2_L3_HASH_KEY_TYPE_V6L2VPMC:
  23883                 oi = 4;
  23884                 break;
  23885             default:
  23886                 oi = 1;
  23887             }
  23888             key_type = soc_mem_field32_get(unit, L3_ENTRY_ONLYm,
  23889                                            new_entry, KEY_TYPEf);
  23890             switch (key_type) {
  23891             case TD2_L3_HASH_KEY_TYPE_V4UC:
  23892             case TD2_L3_HASH_KEY_TYPE_TRILL:
  23893             case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN:
  23894             case TD2_L3_HASH_KEY_TYPE_FCOE_HOST:
  23895             case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP:
  23896                 return oi;
  23897             case TD2_L3_HASH_KEY_TYPE_V4UC_EXT:
  23898             case TD2_L3_HASH_KEY_TYPE_V4MC:
  23899             case TD2_L3_HASH_KEY_TYPE_V4L2MC:
  23900             case TD2_L3_HASH_KEY_TYPE_V4L2VPMC:
  23901             case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT:
  23902             case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT:
  23903             case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT:
  23904             case TD2_L3_HASH_KEY_TYPE_DST_NAT:
  23905             case TD2_L3_HASH_KEY_TYPE_DST_NAPT:
  23906             case TD2_L3_HASH_KEY_TYPE_V6UC:
  23907                 return (oi > 2) ? 2 : 1;
  23908             case TD2_L3_HASH_KEY_TYPE_V6UC_EXT:
  23909             case TD2_L3_HASH_KEY_TYPE_V6MC:
  23910             case TD2_L3_HASH_KEY_TYPE_V6L2MC:
  23911             case TD2_L3_HASH_KEY_TYPE_V6L2VPMC:
  23912                 return 1;
  23913             default:
  23914                 return (oi > 1) ? oi : 1;
  23915             }
  23916         } else {
  23917             return 1;
  23918         }
  23919     }
  23920 }
  23921 
  23922 /* return values:
  23923  *   0: equals,
  23924  *   1, 2, 4, wider times, old_entry>new_entry .
  23925  *   -1, old_entry<new_entry
  23926  */
  23927 STATIC int
  23928 _soc_mem_shared_hash_entry_wide_cmp(int unit, soc_mem_t mem, void *old_entry,
  23929                                 void *new_entry, soc_mem_t *wider_mem)
  23930 {
  23931     int oi = 1;
  23932     int ni = 1;
  23933 
  23934     *wider_mem = mem;
  23935     if (mem == L2Xm) {
  23936         return 0;
  23937     } 
  23938 
  23939     if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_ONLYm, KEY_TYPEf)) {
  23940         int key_type, key_type2;
  23941 
  23942         key_type = soc_mem_field32_get(unit, L3_ENTRY_ONLYm,
  23943                                        old_entry, KEY_TYPEf);
  23944         switch (key_type) {
  23945         case TD2_L3_HASH_KEY_TYPE_V4UC:
  23946         case TD2_L3_HASH_KEY_TYPE_TRILL:
  23947         case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN:
  23948         case TD2_L3_HASH_KEY_TYPE_FCOE_HOST:
  23949         case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP:
  23950             oi = 1;
  23951             break;
  23952         case TD2_L3_HASH_KEY_TYPE_V4UC_EXT:
  23953         case TD2_L3_HASH_KEY_TYPE_V4MC:
  23954         case TD2_L3_HASH_KEY_TYPE_V4L2MC:
  23955         case TD2_L3_HASH_KEY_TYPE_V4L2VPMC:
  23956         case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT:
  23957         case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT:
  23958         case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT:
  23959         case TD2_L3_HASH_KEY_TYPE_DST_NAT:
  23960         case TD2_L3_HASH_KEY_TYPE_DST_NAPT:
  23961         case TD2_L3_HASH_KEY_TYPE_V6UC:
  23962             oi = 2;
  23963             break;
  23964         case TD2_L3_HASH_KEY_TYPE_V6UC_EXT:
  23965         case TD2_L3_HASH_KEY_TYPE_V6MC:
  23966         case TD2_L3_HASH_KEY_TYPE_V6L2MC:
  23967         case TD2_L3_HASH_KEY_TYPE_V6L2VPMC:
  23968             oi = 4;
  23969             break;
  23970         default:
  23971             oi = 1;
  23972         }
  23973         key_type2 = soc_mem_field32_get(unit, L3_ENTRY_ONLYm,
  23974                                        new_entry, KEY_TYPEf);
  23975         switch (key_type2) {
  23976         case TD2_L3_HASH_KEY_TYPE_V4UC:
  23977         case TD2_L3_HASH_KEY_TYPE_TRILL:
  23978         case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN:
  23979         case TD2_L3_HASH_KEY_TYPE_FCOE_HOST:
  23980         case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP:
  23981             ni = 1;
  23982             break;
  23983         case TD2_L3_HASH_KEY_TYPE_V4UC_EXT:
  23984         case TD2_L3_HASH_KEY_TYPE_V4MC:
  23985         case TD2_L3_HASH_KEY_TYPE_V4L2MC:
  23986         case TD2_L3_HASH_KEY_TYPE_V4L2VPMC:
  23987         case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT:
  23988         case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT:
  23989         case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT:
  23990         case TD2_L3_HASH_KEY_TYPE_DST_NAT:
  23991         case TD2_L3_HASH_KEY_TYPE_DST_NAPT:
  23992         case TD2_L3_HASH_KEY_TYPE_V6UC:
  23993             ni = 2;
  23994             break;
  23995         case TD2_L3_HASH_KEY_TYPE_V6UC_EXT:
  23996         case TD2_L3_HASH_KEY_TYPE_V6MC:
  23997         case TD2_L3_HASH_KEY_TYPE_V6L2MC:
  23998         case TD2_L3_HASH_KEY_TYPE_V6L2VPMC:
  23999             ni = 4;
  24000             break;
  24001         default:
  24002             ni = 1;
  24003         }
  24004 
  24005         if (oi == ni) {
  24006             return 0;
  24007         } else if (oi < ni) {
  24008             return -1;
  24009         } else { /* (oi > ni) */
  24010             if (oi == 2) {
  24011                 *wider_mem = L3_ENTRY_IPV4_MULTICASTm;
  24012             } else if (oi == 4) {
  24013                 *wider_mem = L3_ENTRY_IPV6_MULTICASTm;
  24014             }
  24015             return oi / ni;
  24016         }
  24017     }
  24018 
  24019     return 0;
  24020 }
  24021 
  24022 STATIC int
  24023 _soc_mem_shared_hash_narrower_move_allowed(int v0, int v1, int v2, int v3,
  24024                                         soc_mem_t *mem, int *index, int offset)
  24025 {
  24026     int entry_num = v0 + v1 + v2 + v3;
  24027     int double_wide_upper_num = v0 + v1;
  24028     int double_wide_lower_num = v2 + v3;
  24029     soc_mem_t ori_mem = *mem;
  24030     int ori_idx = *index + offset;
  24031     int index_offset = 0;
  24032 
  24033     switch (ori_mem) {
  24034     case L3_ENTRY_IPV6_MULTICASTm:
  24035         if (entry_num == 1) {
  24036             index_offset = v0 ? 0 : (v1 ? 1 : (v2 ? 2 : (v3 ? 3 : 0)));
  24037             *mem = L3_ENTRY_IPV4_UNICASTm;
  24038             *index = ori_idx * 4 + index_offset;
  24039             return 1;
  24040         } else if (entry_num == 2) {
  24041             if (double_wide_upper_num == 2 || double_wide_lower_num == 2) {
  24042                 index_offset = double_wide_upper_num ? 0 : 1;
  24043                 /* L3_ENTRY_IPV4_UNICASTm can be treated as V4_MULTICAST */
  24044                 *mem = L3_ENTRY_IPV4_MULTICASTm;
  24045                 *index = ori_idx * 2 + index_offset;
  24046                 return 1;
  24047             }
  24048         }
  24049         break;
  24050     case L3_ENTRY_IPV6_UNICASTm:
  24051     case L3_ENTRY_IPV4_MULTICASTm:
  24052         if (entry_num == 1) {
  24053             index_offset = v0 ? 0 : 1;
  24054             *mem = L3_ENTRY_IPV4_UNICASTm;
  24055             *index = ori_idx * 2 + index_offset;
  24056             return 1;
  24057         }
  24058         break;
  24059     default:
  24060         /* no entry narrower than L3_ENTRY_IPV4_UNICASTm */
  24061         return 0;
  24062     }
  24063 
  24064     return 0;
  24065 }
  24066 
  24067 STATIC int
  24068 _soc_mem_shared_hash_move(int unit, soc_mem_t mem, int32 banks, int copyno,
  24069                           void *entry, SHR_BITDCL *bucket_trace,
  24070                           int recurse_depth,_soc_hash_bank_info_t *bank_info)
  24071 {
  24072     SHR_BITDCL *trace = NULL;
  24073     _soc_hash_bank_info_t bank_inf = {0};
  24074     uint8 num_ent = 0;
  24075     int32 nbix, cbix;
  24076     int rv = SOC_E_NONE, cmp_rv, index, ori_index;
  24077     uint8 i, bix, found = 0, cb = 0;
  24078     uint32 db, dest_bucket;
  24079     uint32 bucket, move_entry[SOC_MAX_MEM_WORDS];
  24080     soc_mem_t wider_mem, ori_mem = mem;
  24081     int banks_seq_num = 0;
  24082 
  24083     if (recurse_depth < 0) {
  24084         return SOC_E_FULL;
  24085     }
  24086     /* Get the entry number per each bucket */
  24087     num_ent = _soc_mem_shared_hash_entries_per_bkt(unit, mem);
  24088 
  24089     /* Stack variables initialization & memory allocations */
  24090     if (NULL == bucket_trace) {
  24091         SOC_IF_ERROR_RETURN(
  24092             _soc_mem_shared_hash_init(unit, mem, &trace, &bank_inf, 0, NULL, NULL));
  24093     } else {
  24094         trace = bucket_trace;
  24095         if (NULL != bank_info) {
  24096             sal_memcpy(&bank_inf, bank_info, sizeof(_soc_hash_bank_info_t));
  24097         } else {
  24098             rv = SOC_E_INTERNAL;
  24099             goto clean_up;
  24100         }
  24101     }
  24102 
  24103     if (banks != SOC_MEM_HASH_BANK_ALL) {
  24104 #ifdef BCM_APACHE_SUPPORT
  24105         if (SOC_IS_APACHE(unit)) {
  24106             rv = soc_apache_hash_seq_number_get(unit, mem, banks,
  24107                                                   &banks_seq_num);
  24108         } else 
  24109 #endif /* BCM_APACHE_SUPPORT */
  24110 #ifdef BCM_TOMAHAWK_SUPPORT
  24111         if (SOC_IS_TOMAHAWKX(unit)) {
  24112 #ifdef BCM_TOMAHAWK3_SUPPORT
  24113             if (SOC_IS_TOMAHAWK3(unit)) {
  24114                 rv = soc_tomahawk3_hash_seq_number_get(unit, mem, banks,
  24115                                                       &banks_seq_num);
  24116             } else
  24117 #endif /* BCM_TOMAHAWK3_SUPPORT */
  24118             {
  24119             rv = soc_tomahawk_hash_seq_number_get(unit, mem, banks,
  24120                                                   &banks_seq_num);
  24121             }
  24122         } else 
  24123 #endif /* BCM_TOMAHAWK_SUPPORT */
  24124 #ifdef BCM_HELIX5_SUPPORT
  24125         if (SOC_IS_HELIX5(unit)) {
  24126             rv = soc_hx5_hash_seq_number_get(unit, mem, banks, &banks_seq_num);
  24127         } else
  24128 #endif /* BCM_HELIX5_SUPPORT */
  24129 #ifdef BCM_TRIDENT3_SUPPORT
  24130         if (SOC_IS_TRIDENT3X(unit)) {
  24131             rv = soc_td3_hash_seq_number_get(unit, mem, banks, &banks_seq_num);
  24132         } else
  24133 #endif /* BCM_TRIDENT3_SUPPORT */
  24134         {
  24135             rv = soc_trident2_hash_seq_number_get(unit, mem, banks,
  24136                                                   &banks_seq_num);
  24137         }
  24138         if (SOC_FAILURE(rv)) {
  24139             goto clean_up;
  24140         }
  24141     } else {
  24142         /* Make sure we will try from the first bank */
  24143         banks_seq_num = -1;
  24144     }
  24145 
  24146     /* Iterate over banks. */
  24147     for (bix = 0; bix < bank_inf.num_banks; bix++) {
  24148         /* if banks is present, try interate from next bank */
  24149         cbix = banks_seq_num + bix + 1;
  24150         cbix = cbix % bank_inf.num_banks;
  24151         cb = bank_inf.bank_nums[cbix];
  24152         if (banks == cb) {
  24153             /* Not this bank */
  24154             continue;
  24155         }
  24156         nbix = (cbix + 1) % bank_inf.num_banks; /* next bank index */
  24157         db = bank_inf.bank_nums[nbix]; /* next destination bank */
  24158 #ifdef BCM_APACHE_SUPPORT
  24159         if (SOC_IS_APACHE(unit)) {
  24160             rv = soc_ap_hash_bucket_get(unit, mem, cb, entry, &bucket);
  24161         } else
  24162 #endif /* BCM_APACHE_SUPPORT */
  24163 #ifdef BCM_TOMAHAWK_SUPPORT
  24164         if (SOC_IS_TOMAHAWKX(unit)) {
  24165 #ifdef BCM_TOMAHAWK3_SUPPORT
  24166             if (SOC_IS_TOMAHAWK3(unit)) {
  24167                 rv = soc_tomahawk3_hash_bucket_get(unit, mem, cb, entry, &bucket);
  24168             } else
  24169 #endif /* BCM_TOMAHAWK3_SUPPORT */
  24170             {
  24171             rv = soc_th_hash_bucket_get(unit, mem, cb, entry, &bucket);
  24172             }
  24173         } else
  24174 #endif /* BCM_TOMAHAWK_SUPPORT */
  24175 #ifdef BCM_HELIX5_SUPPORT
  24176         if (SOC_IS_HELIX5(unit)) {
  24177             rv = soc_hx5_hash_bucket_get(unit, mem, cb, entry, &bucket);
  24178         } else
  24179 #endif /* BCM_HELIX5_SUPPORT */
  24180 #ifdef BCM_TRIDENT3_SUPPORT
  24181         if (SOC_IS_TRIDENT3X(unit)) {
  24182             rv = soc_td3_hash_bucket_get(unit, mem, cb, entry, &bucket);
  24183         } else
  24184 #endif /* BCM_TRIDENT3_SUPPORT */
  24185         {
  24186             rv = soc_hash_bucket_get(unit, mem, cb, entry, &bucket);
  24187         }
  24188         if (SOC_FAILURE(rv)) {
  24189             break;
  24190         }
  24191         SHR_BITSET(trace, (bank_inf.numb * cbix) + bucket);
  24192 #ifdef BCM_APACHE_SUPPORT
  24193         if (SOC_IS_APACHE(unit)) {
  24194             index = soc_ap_hash_index_get(unit, mem, cb, bucket);
  24195         } else
  24196 #endif /* BCM_APACHE_SUPPORT */
  24197 #ifdef BCM_TOMAHAWK_SUPPORT
  24198         if (SOC_IS_TOMAHAWKX(unit)) {
  24199 #ifdef BCM_TOMAHAWK3_SUPPORT
  24200             if (SOC_IS_TOMAHAWK3(unit)) {
  24201                 index = soc_tomahawk3_hash_index_get(unit, mem, cb, bucket);
  24202             } else
  24203 #endif /* BCM_TOMAHAWK3_SUPPORT */
  24204             {
  24205             index = soc_th_hash_index_get(unit, mem, cb, bucket);
  24206             }
  24207         } else
  24208 #endif /* BCM_TOMAHAWK_SUPPORT */
  24209 #ifdef BCM_HELIX5_SUPPORT
  24210         if (SOC_IS_HELIX5(unit)) {
  24211             index = soc_hx5_hash_index_get(unit, mem, cb, bucket);
  24212         } else
  24213 #endif /* BCM_HELIX5_SUPPORT */
  24214 #ifdef BCM_TRIDENT3_SUPPORT
  24215         if (SOC_IS_TRIDENT3X(unit)) {
  24216             index = soc_td3_hash_index_get(unit, mem, cb, bucket);
  24217         } else
  24218 #endif /* BCM_TRIDENT3_SUPPORT */
  24219         {
  24220             index = soc_hash_index_get(unit, mem, cb, bucket);
  24221         }
  24222         ori_index = index;
  24223         for (i = 0; i < num_ent;) {
  24224             uint32 v0, v1, v2, v3;
  24225             soc_field_t fld_vld = VALIDf;
  24226             if (mem == L2Xm &&
  24227                 soc_feature(unit, soc_feature_base_valid)) {
  24228                 fld_vld = BASE_VALIDf;
  24229             }
  24230             rv = soc_mem_read(unit, mem, copyno, index+i, move_entry);
  24231             if (SOC_FAILURE(rv)) {
  24232                 rv = SOC_E_MEMORY;
  24233                 break;
  24234             }
  24235 
  24236             /* Could be an empty slot here */
  24237             v0 = v1 = v2 = v3 = 0;
  24238             switch (mem) {
  24239             case L3_ENTRY_IPV6_MULTICASTm:
  24240                 soc_mem_field_get(unit, mem, move_entry, VALID_3f, &v3);
  24241                 soc_mem_field_get(unit, mem, move_entry, VALID_2f, &v2);
  24242                 /* pass through */
  24243             case L3_ENTRY_IPV6_UNICASTm:
  24244             case L3_ENTRY_IPV4_MULTICASTm:
  24245                 soc_mem_field_get(unit, mem, move_entry, VALID_1f, &v1);
  24246                 soc_mem_field_get(unit, mem, move_entry, VALID_0f, &v0);
  24247                 break;
  24248             case L3_ENTRY_IPV4_UNICASTm:
  24249             case L3_ENTRY_ONLYm:
  24250             case L2Xm:
  24251                 soc_mem_field_get(unit, mem, move_entry, fld_vld, &v0);
  24252                 break;
  24253             default:
  24254                 v0 = v1 = v2 = v3 = 1;
  24255                 break;
  24256             }
  24257             LOG_VERBOSE(BSL_LS_SOC_COMMON,
  24258                         (BSL_META_U(unit,
  24259                                     "Depth %d, 1st read %d index %d from bank %d bucket %d(%d %d %d %d)\n"),
  24260                          recurse_depth, mem, index+i, cb, bucket,
  24261                          v0, v1, v2, v3));
  24262 
  24263             if (!(v0 || v1 || v2 || v3)) {
  24264                 found = TRUE;
  24265                 break;
  24266             }
  24267 
  24268             cmp_rv = _soc_mem_shared_hash_entry_wide_cmp(unit, mem, move_entry,
  24269                                                          entry, &wider_mem);
  24270             if (cmp_rv == 0) {
  24271                 /* Are we already in recursion or will we be in recursion */
  24272                 if (recurse_depth) {
  24273                     /* Calculate destination entry hash value. */
  24274 #ifdef BCM_APACHE_SUPPORT
  24275                     if (SOC_IS_APACHE(unit)) {
  24276                         (void)soc_ap_hash_bucket_get(unit, mem, db, move_entry,
  24277                                                     &dest_bucket);
  24278                     } else
  24279 #endif /* BCM_APACHE_SUPPORT */
  24280 #ifdef BCM_TOMAHAWK_SUPPORT
  24281                     if (SOC_IS_TOMAHAWKX(unit)) {
  24282 #ifdef BCM_TOMAHAWK3_SUPPORT
  24283                         if (SOC_IS_TOMAHAWK3(unit)) {
  24284                             (void)soc_tomahawk3_hash_bucket_get(unit, mem, db, move_entry,
  24285                                                         &dest_bucket);
  24286                         } else
  24287 #endif /* BCM_TOMAHAWK3_SUPPORT */
  24288                         {
  24289                         (void)soc_th_hash_bucket_get(unit, mem, db, move_entry,
  24290                                                     &dest_bucket);
  24291                         }
  24292                     } else
  24293 #endif /* BCM_TOMAHAWK_SUPPORT */
  24294 #ifdef BCM_HELIX5_SUPPORT 
  24295                     if (SOC_IS_HELIX5(unit)) {
  24296                         (void)soc_hx5_hash_bucket_get(unit, mem, db, move_entry,
  24297                                                       &dest_bucket);
  24298                     } else
  24299 #endif /* BCM_HELIX5_SUPPORT */
  24300 #ifdef BCM_TRIDENT3_SUPPORT
  24301                     if (SOC_IS_TRIDENT3X(unit)) {
  24302                         (void)soc_td3_hash_bucket_get(unit, mem, db, move_entry,
  24303                                                       &dest_bucket);
  24304                     } else
  24305 #endif /* BCM_TRIDENT3_SUPPORT */
  24306                     {
  24307                         (void)soc_hash_bucket_get(unit, mem, db, move_entry, &dest_bucket);
  24308                     }
  24309 
  24310                     if (SHR_BITGET(trace, (bank_inf.numb * nbix) + dest_bucket)) {
  24311                         /* Try next entry in the same bucket */
  24312                         i++;
  24313                         LOG_VERBOSE(BSL_LS_SOC_COMMON,
  24314                                     (BSL_META_U(unit,
  24315                                                 "  Skip(1) bank %d bucket %d, go to bank %d index %d\n"),
  24316                                      db, dest_bucket, cb, index+i));
  24317                         continue;
  24318                     }
  24319                 }
  24320             }
  24321 
  24322             if (cmp_rv < 0) {
  24323                 if (_soc_mem_shared_hash_narrower_move_allowed(v0, v1, v2, v3,
  24324                                                             &mem, &index, i)) {
  24325                     if (SOC_FAILURE(soc_mem_read(unit, mem, copyno, index,
  24326                                                  move_entry))) {
  24327                         rv = SOC_E_MEMORY;
  24328                         mem = ori_mem;
  24329                         break;
  24330                     }
  24331                     LOG_VERBOSE(BSL_LS_SOC_COMMON,
  24332                                 (BSL_META_U(unit,
  24333                                             "Depth %d, L-2nd read %d index %d from bank %d bucket %d\n"),
  24334                                  recurse_depth, mem, index, cb, bucket));
  24335                     /* Are we already in recursion or will we be in recursion */
  24336                     if (recurse_depth) {
  24337                         /* Calculate destination entry hash value. */
  24338 #ifdef BCM_APACHE_SUPPORT
  24339                         if (SOC_IS_APACHE(unit)) {
  24340                             (void)soc_ap_hash_bucket_get(unit, mem, db, move_entry,
  24341                                                          &dest_bucket);
  24342                         } else
  24343 #endif /* BCM_APACHE_SUPPORT */
  24344 #ifdef BCM_TOMAHAWK_SUPPORT
  24345                         if (SOC_IS_TOMAHAWKX(unit)) {
  24346 #ifdef BCM_TOMAHAWK3_SUPPORT
  24347                             if (SOC_IS_TOMAHAWK3(unit)) {
  24348                                 (void)soc_tomahawk3_hash_bucket_get(unit, mem, db, move_entry,
  24349                                                              &dest_bucket);
  24350                             } else
  24351 #endif /* BCM_TOMAHAWK3_SUPPORT */
  24352                             {
  24353                             (void)soc_th_hash_bucket_get(unit, mem, db, move_entry,
  24354                                                          &dest_bucket);
  24355                             }
  24356                         } else
  24357 #endif /* BCM_TOMAHAWK_SUPPORT */
  24358 #ifdef BCM_HELIX5_SUPPORT
  24359                         if (SOC_IS_HELIX5(unit)) {
  24360                             (void)soc_hx5_hash_bucket_get(unit, mem, db,
  24361                                                     move_entry, &dest_bucket);
  24362                         } else
  24363 #endif /* BCM_HELIX5_SUPPORT */
  24364 #ifdef BCM_TRIDENT3_SUPPORT
  24365                         if (SOC_IS_TRIDENT3X(unit)) {
  24366                             (void)soc_td3_hash_bucket_get(unit, mem, db,
  24367                                                     move_entry, &dest_bucket);
  24368                         } else
  24369 #endif /* BCM_TRIDENT3_SUPPORT */
  24370                         {
  24371                             (void)soc_hash_bucket_get(unit, mem, db, move_entry,
  24372                                                       &dest_bucket);
  24373                         }
  24374                         if (SHR_BITGET(trace, (bank_inf.numb * nbix) + dest_bucket)) {
  24375                             /* Try next entry in the same bucket in original
  24376                              * memory view */
  24377                             mem = ori_mem;
  24378                             index = ori_index;
  24379                             i++;
  24380                             LOG_VERBOSE(BSL_LS_SOC_COMMON,
  24381                                         (BSL_META_U(unit,
  24382                                                     "  Skip(2) bank %d bucket %d, go to mem %d " \
  24383                                                     "bank %d index %d \n"),
  24384                                          db, dest_bucket, mem, i >= num_ent ? db : cb,
  24385                                          i >= num_ent ? -1 : (index+i)));
  24386                             continue;
  24387                         }
  24388                     }
  24389                 } else {
  24390                     LOG_VERBOSE(BSL_LS_SOC_COMMON,
  24391                                 (BSL_META_U(unit,
  24392                                             "Depth %d, Existing entry width is narrower, but can't move\n"),
  24393                                  recurse_depth));
  24394                     rv = SOC_E_NONE;
  24395                     break;
  24396                 }
  24397             }
  24398 
  24399             /* wider entry */
  24400             if (cmp_rv > 0) {
  24401                 mem = wider_mem;
  24402                 index = (index + i) / cmp_rv;
  24403                 rv = soc_mem_read(unit, mem, copyno, index, move_entry);
  24404                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
  24405                             (BSL_META_U(unit,
  24406                                         "Depth %d, G-2nd read %d index %d from bank %d bucket %d\n"),
  24407                              recurse_depth, mem, index, cb, bucket));
  24408                 if (SOC_FAILURE(rv)) {
  24409                     rv = SOC_E_MEMORY;
  24410                     mem = ori_mem;
  24411                     break;
  24412                 }
  24413                 /* Are we already in recursion or will we be in recursion */
  24414                 if (recurse_depth) {
  24415                     /* Calculate destination entry hash value. */
  24416 #ifdef BCM_APACHE_SUPPORT
  24417                     if (SOC_IS_APACHE(unit)) {
  24418                         (void)soc_ap_hash_bucket_get(unit, mem, db, move_entry,
  24419                                                      &dest_bucket);
  24420                     } else
  24421 #endif /* BCM_APACHE_SUPPORT */
  24422 #ifdef BCM_TOMAHAWK_SUPPORT
  24423                     if (SOC_IS_TOMAHAWKX(unit)) {
  24424 #ifdef BCM_TOMAHAWK3_SUPPORT
  24425                         if (SOC_IS_TOMAHAWK3(unit)) {
  24426                             (void)soc_tomahawk3_hash_bucket_get(unit, mem, db, move_entry,
  24427                                                          &dest_bucket);
  24428                         } else
  24429 #endif /* BCM_TOMAHAWK3_SUPPORT */
  24430                         {
  24431                         (void)soc_th_hash_bucket_get(unit, mem, db, move_entry,
  24432                                                      &dest_bucket);
  24433                         }
  24434                     } else
  24435 #endif /* BCM_TOMAHAWK_SUPPORT */
  24436 #ifdef BCM_HELIX5_SUPPORT
  24437                     if (SOC_IS_HELIX5(unit)) {
  24438                         (void)soc_hx5_hash_bucket_get(unit, mem, db, move_entry,
  24439                                                       &dest_bucket);
  24440                     } else
  24441 #endif /* BCM_HELIX5_SUPPORT */
  24442 #ifdef BCM_TRIDENT3_SUPPORT
  24443                     if (SOC_IS_TRIDENT3X(unit)) {
  24444                         (void)soc_td3_hash_bucket_get(unit, mem, db, move_entry,
  24445                                                       &dest_bucket);
  24446                     } else
  24447 #endif /* BCM_TRIDENT3_SUPPORT */
  24448                     {
  24449                         (void)soc_hash_bucket_get(unit, mem, db, move_entry,
  24450                                                   &dest_bucket);
  24451                     }
  24452                     if (SHR_BITGET(trace, (bank_inf.numb * nbix) + dest_bucket)) {
  24453                         /* Determine bucket offset increment based upon
  24454                          * existing entry type/size */
  24455                         mem = ori_mem;
  24456                         index = ori_index;
  24457                         i += _soc_mem_shared_hash_incr_per_entry(unit, mem,
  24458                                                          move_entry, entry);
  24459                         LOG_VERBOSE(BSL_LS_SOC_COMMON,
  24460                                     (BSL_META_U(unit,
  24461                                                 "  Skip(3) bank %d bucket %d, go to bank %d index %d\n"),
  24462                                      db, dest_bucket, cb, index+i));
  24463                         continue;
  24464                     }
  24465                 }
  24466             }
  24467 
  24468             /* Attempt to insert it into the other bank. */
  24469             rv = soc_mem_bank_insert(unit, mem, (uint32)1<<db, copyno, move_entry, NULL);
  24470             LOG_VERBOSE(BSL_LS_SOC_COMMON,
  24471                         (BSL_META_U(unit,
  24472                                     "Depth %d, trying to insert %d index %d to bank %d\n"),
  24473                          recurse_depth, mem, index, db));
  24474             if (SOC_FAILURE(rv)) {
  24475                 if (rv != SOC_E_FULL) {
  24476                     LOG_VERBOSE(BSL_LS_SOC_COMMON,
  24477                                 (BSL_META_U(unit,
  24478                                             "  But failed, rv %s, ori_mem %d\n"), soc_errmsg(rv), ori_mem));
  24479                     mem = ori_mem;
  24480                     break;
  24481                 }
  24482                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
  24483                             (BSL_META_U(unit,
  24484                                         "  But bank is full, insert failed, will do recurse\n")));
  24485                 /* Recursive call - attempt to create a slot
  24486                    in another bank's bucket. */
  24487                 rv = _soc_mem_shared_hash_move(unit, mem, cb, copyno,
  24488                                                move_entry, trace,
  24489                                                recurse_depth - 1,&bank_inf);
  24490                 if (SOC_FAILURE(rv)) {
  24491                     if (rv != SOC_E_FULL) {
  24492                         break;
  24493                     }
  24494                     mem = ori_mem;
  24495                     index = ori_index;
  24496                     i += _soc_mem_shared_hash_incr_per_entry(unit, mem,
  24497                                                             move_entry, entry);
  24498                     continue;
  24499                 }
  24500             }
  24501             LOG_VERBOSE(BSL_LS_SOC_COMMON,
  24502                         (BSL_META_U(unit,
  24503                                     "  Insert successfully\n")));
  24504             /* Entry was moved successfully. */
  24505             found = TRUE;
  24506             /* Delete old entry from original location */
  24507             LOG_VERBOSE(BSL_LS_SOC_COMMON,
  24508                         (BSL_META_U(unit,
  24509                                     "Depth %d, trying to delete %d index %d from bank %d\n"),
  24510                          recurse_depth, mem, index, cb));
  24511             rv = soc_mem_generic_delete(unit, mem, MEM_BLOCK_ANY, (uint32)1<<cb,
  24512                                         move_entry, NULL, NULL);
  24513             mem = ori_mem;
  24514             break;
  24515         }  /* Bucket iteration loop. */
  24516         if (found || ((rv < 0) && (rv != SOC_E_FULL))) {
  24517             break;
  24518         }
  24519     } /* Bank iteration loop. */
  24520     if ((rv < 0) && (rv != SOC_E_FULL)) {
  24521         if (NULL == bucket_trace) {
  24522             sal_free(trace);
  24523         }
  24524         return rv;
  24525     }
  24526     if (!found) {
  24527         if (NULL == bucket_trace) {
  24528             sal_free(trace);
  24529         }
  24530         return SOC_E_FULL;
  24531     }
  24532     rv = soc_mem_generic_insert(unit, mem, copyno, (uint32)1<<cb, entry, entry, NULL);
  24533     if (rv) {
  24534         LOG_VERBOSE(BSL_LS_SOC_COMMON,
  24535                     (BSL_META_U(unit,
  24536                                 "Insert entry: %d\n"), rv));
  24537     }
  24538 clean_up:
  24539     if (NULL == bucket_trace) {
  24540         sal_free(trace);
  24541     }
  24542     return rv;
  24543 }
  24544 
  24545 
  24546 STATIC INLINE void
  24547 _soc_mem_shared_hash_l3_bucket_read(int unit, int ent, int key_type, int *width,
  24548                                     soc_mem_t *mem, void *bkt_entry, void *entry)
  24549 {
  24550 
  24551     soc_mem_info_t meminfo;
  24552     soc_field_info_t fieldinfo;
  24553     /* Exclude HIT bit */
  24554     int entry_bits;
  24555 
  24556     switch (key_type) {
  24557     case TD2_L3_HASH_KEY_TYPE_V4UC:
  24558     case TD2_L3_HASH_KEY_TYPE_TRILL:
  24559     case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN:
  24560     case TD2_L3_HASH_KEY_TYPE_FCOE_HOST:
  24561     case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP:
  24562         *width = 1;
  24563         *mem = L3_ENTRY_IPV4_UNICASTm;
  24564         break;
  24565     case TD2_L3_HASH_KEY_TYPE_V4UC_EXT:
  24566     case TD2_L3_HASH_KEY_TYPE_V4MC:
  24567     case TD2_L3_HASH_KEY_TYPE_V4L2MC:
  24568     case TD2_L3_HASH_KEY_TYPE_V4L2VPMC:
  24569     case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT:
  24570     case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT:
  24571     case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT:
  24572     case TD2_L3_HASH_KEY_TYPE_DST_NAT:
  24573     case TD2_L3_HASH_KEY_TYPE_DST_NAPT:
  24574     case TD2_L3_HASH_KEY_TYPE_V6UC:
  24575         *width = 2;
  24576         *mem = L3_ENTRY_IPV4_MULTICASTm;
  24577         break;
  24578     case TD2_L3_HASH_KEY_TYPE_V6UC_EXT:
  24579     case TD2_L3_HASH_KEY_TYPE_V6MC:
  24580     case TD2_L3_HASH_KEY_TYPE_V6L2MC:
  24581     case TD2_L3_HASH_KEY_TYPE_V6L2VPMC:
  24582     default:
  24583         *width = 4;
  24584         *mem = L3_ENTRY_IPV6_MULTICASTm;
  24585         sal_memcpy(entry, bkt_entry, sizeof(l3_entry_ipv6_multicast_entry_t));
  24586         return;
  24587     }
  24588     entry_bits = (soc_mem_entry_bits(unit, L3_ENTRY_IPV4_UNICASTm) - 1) * (*width);
  24589 
  24590     meminfo.flags = 0;
  24591     meminfo.bytes = SOC_MEM_WORDS(unit, L3_ENTRY_IPV6_MULTICASTm) * 4;
  24592     fieldinfo.flags = SOCF_LE;
  24593     fieldinfo.bp =  entry_bits * (ent / *width);
  24594     fieldinfo.len = entry_bits;
  24595 
  24596     (void)soc_meminfo_fieldinfo_field_get(bkt_entry, &meminfo,
  24597                                           &fieldinfo, entry);
  24598 
  24599 }
  24600 
  24601 #define SRAM_ENTRIES_PER_BUCKET 2
  24602 #define SRAM_ENTRIES_PER_BUCKET_EM_2 2
  24603 #define SRAM_ENTRIES_PER_BUCKET_EM_4 4
  24604 
  24605 #define MEM_IS_EXACT_MATCH_2(mem) (EXACT_MATCH_2m == mem || \
  24606                              EXACT_MATCH_2_PIPE0m == mem || \
  24607                              EXACT_MATCH_2_PIPE1m == mem || \
  24608                              EXACT_MATCH_2_PIPE2m == mem || \
  24609                              EXACT_MATCH_2_PIPE3m == mem)
  24610 #define MEM_IS_EXACT_MATCH_4(mem) (EXACT_MATCH_4m == mem || \
  24611                              EXACT_MATCH_4_PIPE0m == mem || \
  24612                              EXACT_MATCH_4_PIPE1m == mem || \
  24613                              EXACT_MATCH_4_PIPE2m == mem || \
  24614                              EXACT_MATCH_4_PIPE3m == mem)                              
  24615 
  24616 #define MEM_IS_L3_ENTRY_SINGLE(mem) (L3_ENTRY_SINGLEm == mem)
  24617 #define MEM_IS_L3_ENTRY_DOUBLE(mem) (L3_ENTRY_DOUBLEm == mem)
  24618 #define MEM_IS_L3_ENTRY_QUAD(mem)   (L3_ENTRY_QUADm == mem)
  24619 
  24620 #define MEM_IS_VLAN_XLATE(mem) (VLAN_XLATE_1_SINGLEm == mem || \
  24621                              VLAN_XLATE_1_DOUBLEm == mem || \
  24622                              VLAN_XLATE_2_SINGLEm == mem || \
  24623                              VLAN_XLATE_2_DOUBLEm == mem)
  24624 
  24625 #define MEM_IS_EGR_VLAN_XLATE(mem) (EGR_VLAN_XLATE_1_SINGLEm == mem || \
  24626                              EGR_VLAN_XLATE_1_DOUBLEm == mem || \
  24627                              EGR_VLAN_XLATE_2_SINGLEm == mem || \
  24628                              EGR_VLAN_XLATE_2_DOUBLEm == mem)
  24629 
  24630 #define MEM_IS_MPLS(mem) (MPLS_ENTRYm == mem || MPLS_ENTRY_SINGLEm == mem)
  24631 
  24632 #if defined(BCM_TOMAHAWK3_SUPPORT)
  24633 #define MEM_IS_L3_TUNNEL_SINGLE(mem) (L3_TUNNEL_SINGLEm == mem)
  24634 #define MEM_IS_L3_TUNNEL_DOUBLE(mem) (L3_TUNNEL_DOUBLEm == mem)
  24635 #define MEM_IS_L3_TUNNEL_QUAD(mem)   (L3_TUNNEL_QUADm == mem)
  24636 #endif
  24637 
  24638 
  24639 #if defined(BCM_TOMAHAWK_SUPPORT)
  24640 STATIC INLINE void
  24641 _soc_mem_shared_hash_exact_match_bucket_read(int unit, int ent, int key_type, int *width,
  24642                                     soc_mem_t *mem, void *bkt_entry, void *entry, int pipenum)
  24643 {
  24644     soc_mem_info_t meminfo;
  24645     soc_field_info_t fieldinfo;
  24646     /* Exclude HIT bit */
  24647     int entry_bits;
  24648     int table_entries_per_sram_entry = 0;
  24649     switch (key_type) {
  24650     case TH_FPEM_HASH_KEY_TYPE_128B:
  24651     case TH_FPEM_HASH_KEY_TYPE_160B:
  24652         *width = 1;
  24653         table_entries_per_sram_entry = 2;
  24654         switch (pipenum) {
  24655         case 0:
  24656             *mem = EXACT_MATCH_2_PIPE0m;
  24657             break;
  24658         case 1:
  24659             *mem = EXACT_MATCH_2_PIPE1m;
  24660             break;
  24661         case 2:
  24662             *mem = EXACT_MATCH_2_PIPE2m;
  24663             break;
  24664         case 3:
  24665             *mem = EXACT_MATCH_2_PIPE3m;
  24666             break;
  24667         default:
  24668             *mem = EXACT_MATCH_2m;
  24669             break;            
  24670         }
  24671         break;
  24672     case TH_FPEM_HASH_KEY_TYPE_320B:
  24673     default:
  24674         table_entries_per_sram_entry = 1;
  24675         switch (pipenum) {
  24676         case 0:
  24677             *mem = EXACT_MATCH_4_PIPE0m;
  24678             break;
  24679         case 1:
  24680             *mem = EXACT_MATCH_4_PIPE1m;
  24681             break;
  24682         case 2:
  24683             *mem = EXACT_MATCH_4_PIPE2m;
  24684             break;
  24685         case 3:
  24686             *mem = EXACT_MATCH_4_PIPE3m;
  24687             break;
  24688         default:
  24689             *mem = EXACT_MATCH_4m;
  24690             break;            
  24691         }        
  24692         *width = 2;
  24693     }
  24694     entry_bits = (soc_mem_entry_bits(unit, EXACT_MATCH_2m) - 1) * (*width);
  24695 
  24696     meminfo.flags = 0;
  24697     meminfo.bytes = SOC_MEM_WORDS(unit, EXACT_MATCH_4m) * 4;
  24698     fieldinfo.flags = SOCF_LE;
  24699     fieldinfo.bp =  entry_bits * ((ent % table_entries_per_sram_entry) / *width);
  24700     fieldinfo.len = entry_bits;
  24701 
  24702     (void)soc_meminfo_fieldinfo_field_get((uint32 *)bkt_entry, &meminfo,
  24703                                           &fieldinfo, entry);
  24704 }
  24705 #endif
  24706 
  24707 
  24708 #define _SOC_MEM_SHARED_HASH_STATUS_CHECK(free, mem, status)\
  24709     switch(mem) {                                           \
  24710     case L3_ENTRY_IPV6_MULTICASTm:                          \
  24711     case L3_ENTRY_QUADm:                                    \
  24712     case L3_TUNNEL_QUADm:                                   \
  24713     case EXACT_MATCH_4m:                                    \
  24714         free = (status == 0x0);                             \
  24715         break;                                              \
  24716     case L3_ENTRY_IPV6_UNICASTm:                            \
  24717     case L3_ENTRY_IPV4_MULTICASTm:                          \
  24718     case L3_ENTRY_DOUBLEm:                                  \
  24719     case L3_TUNNEL_DOUBLEm:                                 \
  24720     case EXACT_MATCH_2m:                                    \
  24721         free = (status & 0x3) == 0 || (status >> 2) == 0;   \
  24722         break;                                              \
  24723     case MPLS_ENTRYm:                                       \
  24724     case VLAN_XLATE_1_DOUBLEm:                              \
  24725     case VLAN_XLATE_2_DOUBLEm:                              \
  24726     case EGR_VLAN_XLATE_1_DOUBLEm:                          \
  24727     case EGR_VLAN_XLATE_2_DOUBLEm:                          \
  24728         free = (status & 0x3) == 0;                         \
  24729         break;                                              \
  24730     case MPLS_ENTRY_SINGLEm:                                \
  24731     case VLAN_XLATE_1_SINGLEm:                              \
  24732     case VLAN_XLATE_2_SINGLEm:                              \
  24733     case EGR_VLAN_XLATE_1_SINGLEm:                          \
  24734     case EGR_VLAN_XLATE_2_SINGLEm:                          \
  24735         free = ((status&3) != 0x3);                         \
  24736         break;                                              \
  24737     case L2Xm:                                              \
  24738     case L3_ENTRY_ONLYm:                                    \
  24739     case L3_ENTRY_IPV4_UNICASTm:                            \
  24740     case L3_ENTRY_ONLY_SINGLEm:                             \
  24741     case L3_ENTRY_SINGLEm:                                  \
  24742     case L3_TUNNEL_SINGLEm:                                 \
  24743     default:                                                \
  24744         free = (status != 0xf);                             \
  24745         break;                                              \
  24746     }
  24747 
  24748 /*
  24749  * Function:
  24750  *    _soc_mem_shared_hash_bucket
  24751  * Purpose:
  24752  *   get the global bucket index
  24753  * Parameters:  unit - device
  24754  *              mem (IN) - mem
  24755  *              bank (IN) - physical bank num
  24756  *              entry(IN) - entry_data
  24757  *
  24758  * Returns:
  24759  *    global bucket index
  24760  */
  24761 
  24762 STATIC INLINE int
  24763 _soc_mem_shared_hash_bucket(int unit, int mem, int bank, uint32 *entry)
  24764 {
  24765     int index;
  24766     uint32 bucket;
  24767     /* Get the local bucket index in a bank */
  24768 #ifdef BCM_APACHE_SUPPORT
  24769     if (SOC_IS_APACHE(unit)) {
  24770         (void)soc_ap_hash_bucket_get(unit, mem, bank, entry, &bucket);
  24771     } else
  24772 #endif /* BCM_APACHE_SUPPORT */
  24773 #ifdef BCM_TOMAHAWK_SUPPORT
  24774     if (SOC_IS_TOMAHAWKX(unit)) {
  24775 #ifdef BCM_TOMAHAWK3_SUPPORT
  24776         if (SOC_IS_TOMAHAWK3(unit)) {
  24777             (void)soc_tomahawk3_hash_bucket_get(unit, mem, bank, entry, &bucket);
  24778         } else
  24779 #endif /* BCM_TOMAHAWK3_SUPPORT */
  24780         {
  24781         (void)soc_th_hash_bucket_get(unit, mem, bank, entry, &bucket);
  24782         }
  24783     } else
  24784 #endif /* BCM_TOMAHAWK_SUPPORT */
  24785 #ifdef BCM_HELIX5_SUPPORT
  24786     if (SOC_IS_HELIX5(unit)) {
  24787         (void)soc_hx5_hash_bucket_get(unit, mem, bank, entry, &bucket);
  24788     } else
  24789 #endif /* BCM_HELIX5_SUPPORT */
  24790 #ifdef BCM_TRIDENT3_SUPPORT
  24791     if (SOC_IS_TRIDENT3X(unit)) {
  24792         (void)soc_td3_hash_bucket_get(unit, mem, bank, entry, &bucket);
  24793     } else
  24794 #endif /* BCM_TRIDENT3_SUPPORT */
  24795     {
  24796         (void)soc_hash_bucket_get(unit, mem, bank, entry, &bucket);
  24797     }
  24798     /* Get global table index for the first entry in the bucket*/
  24799 #ifdef BCM_APACHE_SUPPORT
  24800     if (SOC_IS_APACHE(unit)) {
  24801         index = soc_ap_hash_index_get(unit, mem, bank, bucket);
  24802     } else
  24803 #endif /* BCM_APACHE_SUPPORT */
  24804 #ifdef BCM_TOMAHAWK_SUPPORT
  24805     if (SOC_IS_TOMAHAWKX(unit)) {
  24806 #ifdef BCM_TOMAHAWK3_SUPPORT
  24807         if (SOC_IS_TOMAHAWK3(unit)) {
  24808             index = soc_tomahawk3_hash_index_get(unit, mem, bank, bucket);
  24809         } else
  24810 #endif /* BCM_TOMAHAWK3_SUPPORT */
  24811         {
  24812         index = soc_th_hash_index_get(unit, mem, bank, bucket);
  24813         }
  24814     } else
  24815 #endif /* BCM_TOMAHAWK_SUPPORT */
  24816 #ifdef BCM_HELIX5_SUPPORT
  24817     if (SOC_IS_HELIX5(unit)) {
  24818         index = soc_hx5_hash_index_get(unit, mem, bank, bucket);
  24819     } else
  24820 #endif /* BCM_HELIX5_SUPPORT */
  24821 #ifdef BCM_TRIDENT3_SUPPORT
  24822     if (SOC_IS_TRIDENT3X(unit)) {
  24823         index = soc_td3_hash_index_get(unit, mem, bank, bucket);
  24824     } else
  24825 #endif /* BCM_TRIDENT3_SUPPORT */
  24826     {
  24827         index = soc_hash_index_get(unit, mem, bank, bucket);
  24828     }
  24829 
  24830     return (index / _soc_mem_shared_hash_entries_per_bkt(unit, mem));
  24831 }
  24832 
  24833 STATIC soc_mem_t
  24834 _soc_mem_hash_base_mem_get(int unit, soc_mem_t mem) {
  24835     switch (mem) {
  24836         case L3_ENTRY_SINGLEm:
  24837         case L3_ENTRY_ONLY_SINGLEm:
  24838         case L3_ENTRY_DOUBLEm:
  24839         case L3_ENTRY_ONLY_DOUBLEm:
  24840         case L3_ENTRY_QUADm:
  24841         case L3_ENTRY_ONLY_QUADm:
  24842             return L3_ENTRY_QUADm;
  24843         case L3_TUNNEL_SINGLEm:
  24844         case L3_TUNNEL_DOUBLEm:
  24845         case L3_TUNNEL_QUADm:
  24846             return L3_TUNNEL_QUADm;
  24847         case L3_ENTRY_IPV4_UNICASTm:
  24848         case L3_ENTRY_IPV4_MULTICASTm:
  24849         case L3_ENTRY_IPV6_UNICASTm:
  24850         case L3_ENTRY_IPV6_MULTICASTm:
  24851             return L3_ENTRY_IPV6_MULTICASTm;
  24852         case EXACT_MATCH_2m:
  24853         case EXACT_MATCH_4m:
  24854         case EXACT_MATCH_4_PIPE0m:
  24855         case EXACT_MATCH_4_PIPE1m:
  24856         case EXACT_MATCH_4_PIPE2m:
  24857         case EXACT_MATCH_4_PIPE3m:
  24858         case EXACT_MATCH_2_PIPE0m:
  24859         case EXACT_MATCH_2_PIPE1m:
  24860         case EXACT_MATCH_2_PIPE2m:
  24861         case EXACT_MATCH_2_PIPE3m:
  24862             if (SOC_IS_TRIDENT3X(unit)) {
  24863                if (mem == EXACT_MATCH_2_PIPE0m || mem == EXACT_MATCH_4_PIPE0m) {
  24864                   return EXACT_MATCH_4_PIPE0m;
  24865                } else if (mem == EXACT_MATCH_2_PIPE1m || mem == EXACT_MATCH_4_PIPE1m) {
  24866                   return EXACT_MATCH_4_PIPE1m;
  24867                }
  24868             }
  24869             return EXACT_MATCH_4m;
  24870         case VLAN_XLATE_1_SINGLEm:
  24871         case VLAN_XLATE_1_DOUBLEm:
  24872             return VLAN_XLATE_1_DOUBLEm;
  24873         case VLAN_XLATE_2_SINGLEm:
  24874         case VLAN_XLATE_2_DOUBLEm:
  24875             return VLAN_XLATE_2_DOUBLEm;
  24876         case MPLS_ENTRY_SINGLEm:
  24877             return MPLS_ENTRY_SINGLEm;
  24878         case MPLS_ENTRYm:
  24879             return MPLS_ENTRYm;
  24880         case EGR_VLAN_XLATE_1_SINGLEm:
  24881         case EGR_VLAN_XLATE_1_DOUBLEm:
  24882             return EGR_VLAN_XLATE_1_DOUBLEm;
  24883         case EGR_VLAN_XLATE_2_SINGLEm:
  24884         case EGR_VLAN_XLATE_2_DOUBLEm:
  24885             return EGR_VLAN_XLATE_2_DOUBLEm;
  24886         default:
  24887             return INVALIDm;
  24888     }
  24889 }
  24890 
  24891 STATIC int
  24892 _soc_mem_hash_mem_width_get(int unit, soc_mem_t mem) {
  24893     switch (mem) {
  24894         case L3_ENTRY_SINGLEm:
  24895         case L3_ENTRY_ONLY_SINGLEm:
  24896         case L3_ENTRY_IPV4_UNICASTm:
  24897         case VLAN_XLATE_1_SINGLEm:
  24898         case VLAN_XLATE_2_SINGLEm:
  24899         case MPLS_ENTRY_SINGLEm:
  24900         case EGR_VLAN_XLATE_1_SINGLEm:
  24901         case EGR_VLAN_XLATE_2_SINGLEm:
  24902             return 1;
  24903         case EXACT_MATCH_2m:
  24904         case EXACT_MATCH_2_PIPE0m:
  24905         case EXACT_MATCH_2_PIPE1m:
  24906         case EXACT_MATCH_2_PIPE2m:
  24907         case EXACT_MATCH_2_PIPE3m:
  24908 #ifdef BCM_TOMAHAWK3_SUPPORT
  24909             if (SOC_IS_TOMAHAWK3(unit)) {
  24910                return 2;
  24911             } else
  24912 #endif
  24913             return (SOC_IS_TRIDENT3X(unit) ? 2 : 1);
  24914         case L3_ENTRY_DOUBLEm:
  24915         case L3_ENTRY_ONLY_DOUBLEm:
  24916         case L3_ENTRY_IPV4_MULTICASTm:
  24917         case L3_ENTRY_IPV6_UNICASTm:
  24918         case VLAN_XLATE_1_DOUBLEm:
  24919         case VLAN_XLATE_2_DOUBLEm:
  24920         case MPLS_ENTRYm:
  24921         case EGR_VLAN_XLATE_1_DOUBLEm:
  24922         case EGR_VLAN_XLATE_2_DOUBLEm:
  24923             return 2;
  24924         case EXACT_MATCH_4m:
  24925         case EXACT_MATCH_4_PIPE0m:
  24926         case EXACT_MATCH_4_PIPE1m:
  24927         case EXACT_MATCH_4_PIPE2m:
  24928         case EXACT_MATCH_4_PIPE3m:
  24929 #ifdef BCM_TOMAHAWK3_SUPPORT
  24930             if (SOC_IS_TOMAHAWK3(unit)) {
  24931                return 4;
  24932             } else
  24933 #endif
  24934             return (SOC_IS_TRIDENT3X(unit) ? 4 : 1);
  24935         case L3_ENTRY_QUADm:
  24936         case L3_ENTRY_ONLY_QUADm:
  24937         case L3_ENTRY_IPV6_MULTICASTm:
  24938             return 4;
  24939         default:
  24940             return -1;
  24941     }
  24942 
  24943 }
  24944 
  24945 #define INVALID_BUCKET      -1
  24946 
  24947 /*
  24948  * this breadth algorithm works as backup as it uses fixed memory which
  24949  * will be less than the default one when depth exceeds a threshold
  24950  */
  24951 
  24952 STATIC int
  24953 _soc_mem_shared_hash_breadth_l2_move2(int unit, soc_mem_t mem, int copyno,
  24954                                      void *entry, int num_levels)
  24955 {
  24956     _soc_breadth_bucket2_t *buckets = NULL;
  24957     _soc_breadth_bucket2_t *cb, *cbi, *pbi, *pb, *sb;
  24958     SHR_BITDCL *bkt_trace = NULL;
  24959     _soc_hash_bank_info_t bi = {0};
  24960     int rv;
  24961     int job_done = 0;
  24962     int bank_num, ibank_num = 0;
  24963     int bix, cbix, num_banks;
  24964     int free = 0;
  24965     int ent, sent, bucket;
  24966     int curr_bucket;
  24967     void *se, *me;
  24968 
  24969     if (num_levels <= 0) {
  24970         return SOC_E_FULL;
  24971     }
  24972 
  24973     SOC_IF_ERROR_RETURN(_soc_mem_shared_hash_init
  24974         (unit, mem, &bkt_trace, &bi, 0, NULL, &buckets));
  24975 
  24976     /* the last bucket, which is also the head */
  24977     curr_bucket = bi.numb;
  24978     pb = &buckets[curr_bucket];
  24979     pb->bucket      = curr_bucket;
  24980     pb->src_bix     = -1;
  24981     pb->level       = -1;
  24982     pb->n_bucket    = -1;
  24983 
  24984     do {
  24985         /* This bucket's entries have been tried to move */
  24986         cb = &buckets[curr_bucket];
  24987 
  24988         /* all levels have been tried */
  24989         if (cb->level == num_levels - 1) {
  24990             goto done;
  24991         }
  24992 
  24993         /* now generate the sub buckets under this bucket
  24994          * and try to move the sub buckets' entries
  24995          */
  24996 
  24997         if (curr_bucket == bi.numb) {
  24998             num_banks = bi.num_banks;
  24999         } else {
  25000             num_banks = bi.num_banks - 1;
  25001         }
  25002 
  25003         for (ent = 0; ent < NUM_ENT; ent++) {
  25004             if (curr_bucket == bi.numb) {
  25005                 se = entry;
  25006             } else {
  25007                 se = &cb->e.l2[ent];
  25008             }
  25009             for (bix = 0; bix < num_banks; bix++) {
  25010                 cbix = cb->src_bix + bix + 1;
  25011                 cbix = cbix % bi.num_banks;
  25012 
  25013                 bank_num = bi.bank_nums[cbix];
  25014                 bucket = _soc_mem_shared_hash_bucket(unit, mem,
  25015                                                      bank_num, se);
  25016 
  25017                 /* do not visit a bucket twice */
  25018                 if (SHR_BITGET(bkt_trace, bucket)) {
  25019                     continue;
  25020                 }
  25021 
  25022                 sb = &buckets[bucket];
  25023                 SHR_BITSET(bkt_trace, bucket);
  25024                 sb->level     = cb->level + 1;
  25025                 sb->src_ent   = ent;
  25026                 sb->bucket    = bucket;
  25027                 sb->s_bucket  = curr_bucket;
  25028                 sb->src_bix   = cbix;
  25029 
  25030                 /* connect */
  25031                 pb->n_bucket  = bucket;
  25032                 sb->n_bucket  = INVALID_BUCKET;
  25033 
  25034                 /* loop sub bucket's entries and try move */
  25035                 for (sent = 0; sent < NUM_ENT; sent++) {
  25036                     me = &sb->e.l2[sent];
  25037                     rv = soc_mem_read(unit, mem, copyno, (bucket << 2) + sent, me);
  25038                     if (SOC_FAILURE(rv)) {
  25039                         goto cleanup;
  25040                     }
  25041 
  25042                     rv = soc_mem_generic_insert(unit, mem, copyno,
  25043                                                 bi.banks & ~(1 << bank_num),
  25044                                                 me, NULL, NULL);
  25045 
  25046                     free = 0;
  25047                     if (SOC_SUCCESS(rv)) {
  25048 
  25049                         rv = soc_mem_generic_delete(unit, mem, MEM_BLOCK_ANY,
  25050                                                     1 << bank_num, me, NULL, NULL);
  25051                         if (SOC_FAILURE(rv)) {
  25052                             goto cleanup;
  25053                         }
  25054                         free = 1;
  25055 
  25056                     }
  25057 
  25058                     /* sb is not freed, try move next entry in sb */
  25059                     if (!free) {
  25060                         continue;
  25061                     }
  25062 
  25063                     /* now sb is freed.
  25064                      * cb's entry can be moved now. move it and
  25065                      * more if possible
  25066                      */
  25067                     ibank_num = bank_num;
  25068                     pbi = sb;
  25069                     while (pbi->s_bucket != bi.numb) {
  25070                         cbi = pbi;
  25071                         pbi = &buckets[pbi->s_bucket];
  25072                         me = &pbi->e.l2[cbi->src_ent];
  25073                         rv = soc_mem_generic_insert(unit, mem, copyno,
  25074                                                     (1 << ibank_num),
  25075                                                     me, NULL, NULL);
  25076                         if (SOC_FAILURE(rv)) {
  25077                             goto cleanup;
  25078                         }
  25079 
  25080                         ibank_num = bi.bank_nums[pbi->src_bix];
  25081 
  25082                         rv = soc_mem_generic_delete(unit, mem,
  25083                                                     MEM_BLOCK_ANY,
  25084                                                     (1 << ibank_num),
  25085                                                     me, NULL, NULL);
  25086                         if (SOC_FAILURE(rv)) {
  25087                             goto cleanup;
  25088                         }
  25089                     }
  25090 
  25091                     job_done = 1;
  25092                     goto done;
  25093                 } /* sub bucket loop and move done. */
  25094 
  25095                 pb = sb;
  25096             }
  25097         }
  25098         curr_bucket = cb->n_bucket;
  25099     } while (curr_bucket != INVALID_BUCKET);
  25100 
  25101 done:
  25102     if (job_done) {
  25103         rv = soc_mem_generic_insert(unit, mem, copyno, 1 << ibank_num,
  25104                                     entry, entry, NULL);
  25105     } else {
  25106         rv = SOC_E_FULL;
  25107     }
  25108 
  25109 cleanup:
  25110     if (bkt_trace) {
  25111         sal_free(bkt_trace);
  25112     }
  25113 
  25114     if (buckets) {
  25115         sal_free(buckets);
  25116     }
  25117 
  25118     if (SOC_FAILURE(rv)) {
  25119         LOG_VERBOSE(BSL_LS_SOC_COMMON,
  25120                     (BSL_META_U(unit,
  25121                                 "Insert entry: %d\n"), rv));
  25122     }
  25123 
  25124     return rv;
  25125 }
  25126 
  25127 STATIC int
  25128 _soc_mem_shared_hash_breadth_mix_move2(int unit, soc_mem_t mem, int copyno,
  25129                                       void *entry, int num_levels)
  25130 {
  25131     _soc_breadth_bucket2_t *buckets = NULL;
  25132     _soc_breadth_bucket2_t *cb, *nb, *cbi = NULL, *pbi, *pb, *sb, *ib;
  25133     SHR_BITDCL *bkt_trace = NULL;
  25134     _soc_hash_bank_info_t bi = {0};
  25135     uint32 bkt_entry[NUM_ENT][SOC_MAX_MEM_WORDS];
  25136     uint32 v[NUM_ENT], k[NUM_ENT];
  25137     int rv;
  25138     int job_done = 0;
  25139     int bank_num, ibank_num = 0;
  25140     int bix, cbix, num_banks;
  25141     int move_bkt;
  25142     int free = 0;
  25143     int ent, ent_incr, sent, sent_incr, bucket;
  25144     uint8 skip = 0, src_width;
  25145     soc_mem_t orig_mem, base_mem, src_mem;
  25146     int curr_bucket;
  25147     int vld_fld_0 = VALID_0f, vld_fld_1 = VALID_1f;
  25148     int vld_fld_2 = VALID_2f, vld_fld_3 = VALID_3f;
  25149     int key_type_0 = KEY_TYPE_0f, key_type_1 = KEY_TYPE_1f;
  25150     int key_type_2 = KEY_TYPE_2f, key_type_3 = KEY_TYPE_3f;
  25151     void *se, *me;
  25152 #if defined(BCM_TOMAHAWK_SUPPORT)
  25153     int pipenum = -1;
  25154 #endif
  25155 
  25156     if (num_levels <= 0) {
  25157         return SOC_E_FULL;
  25158     }
  25159 
  25160     base_mem = _soc_mem_hash_base_mem_get(unit, mem);
  25161 #if defined(BCM_TOMAHAWK_SUPPORT)
  25162     if (base_mem == EXACT_MATCH_4m) {
  25163         switch (mem) {
  25164         case EXACT_MATCH_4_PIPE0m:
  25165         case EXACT_MATCH_2_PIPE0m:
  25166             base_mem = EXACT_MATCH_4_PIPE0m;
  25167             pipenum = 0;
  25168             break;
  25169         case EXACT_MATCH_4_PIPE1m:
  25170         case EXACT_MATCH_2_PIPE1m:
  25171             base_mem = EXACT_MATCH_4_PIPE1m;
  25172             pipenum = 1;
  25173             break;
  25174         case EXACT_MATCH_4_PIPE2m:
  25175         case EXACT_MATCH_2_PIPE2m:
  25176             base_mem = EXACT_MATCH_4_PIPE2m;
  25177             pipenum = 2;
  25178             break;
  25179         case EXACT_MATCH_4_PIPE3m:
  25180         case EXACT_MATCH_2_PIPE3m:
  25181             base_mem = EXACT_MATCH_4_PIPE3m;
  25182             pipenum = 3;
  25183             break;
  25184         default:
  25185             break;
  25186         }
  25187     }  
  25188 #endif
  25189 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  25190     if (SOC_IS_TRIDENT3X(unit) || SOC_IS_TOMAHAWK3(unit)) {
  25191         vld_fld_0 = BASE_VALID_0f;
  25192         vld_fld_1 = BASE_VALID_1f;
  25193         vld_fld_2 = BASE_VALID_2f;
  25194         vld_fld_3 = BASE_VALID_3f;
  25195         key_type_0 = KEY_TYPEf;
  25196         key_type_1 = KEY_TYPEf;
  25197         key_type_2 = KEY_TYPEf;
  25198         key_type_3 = KEY_TYPEf;
  25199     }
  25200 #endif
  25201     SOC_IF_ERROR_RETURN(_soc_mem_shared_hash_init
  25202         (unit, base_mem, &bkt_trace, &bi, 0, NULL, &buckets));
  25203 
  25204     /* the last bucket, which is also the head */
  25205     curr_bucket = bi.numb;
  25206     pb = &buckets[curr_bucket];
  25207     pb->bucket      = curr_bucket;
  25208     pb->status      = 0x1;
  25209     pb->src_bix     = -1;
  25210     pb->level       = -1;
  25211     pb->n_bucket    = -1;
  25212     pb->mem[0]      = mem;
  25213 
  25214     do {
  25215         /* This bucket's entries have been tried to move */
  25216         cb = &buckets[curr_bucket];
  25217 
  25218         /* all levels have been tried */
  25219         if (cb->level == num_levels - 1) {
  25220             goto done;
  25221         }
  25222 
  25223         /* now generate the sub buckets under this bucket
  25224          * and try to move the sub buckets' entries
  25225          */
  25226 
  25227         if (curr_bucket == bi.numb) {
  25228             num_banks = bi.num_banks;
  25229         } else {
  25230             num_banks = bi.num_banks - 1;
  25231         }
  25232 
  25233         for (ent = 0; ent < NUM_ENT; ent += ent_incr) {
  25234             if (!(cb->status & (1 << ent))) {
  25235                 ent_incr = 1;
  25236                 continue;
  25237             }
  25238 
  25239             if (curr_bucket == bi.numb) {
  25240                 se        = entry;
  25241                 ent_incr  = NUM_ENT;
  25242             } else
  25243 #ifdef BCM_TOMAHAWK_SUPPORT            
  25244             if (MEM_IS_EXACT_MATCH_4(mem)) {
  25245                 se = &cb->e.em_4[ent];
  25246                 ent_incr  = cb->width[ent];
  25247             } else if (MEM_IS_EXACT_MATCH_2(mem)) {
  25248                 se = &cb->e.em_2[ent];
  25249                 ent_incr  = cb->width[ent];
  25250             } else
  25251 #ifdef BCM_TOMAHAWK3_SUPPORT
  25252             if (SOC_IS_TOMAHAWK3(unit) && MEM_IS_MPLS(mem)) {
  25253                 se        = &cb->e.mpls_1[ent];
  25254                 ent_incr  = cb->width[ent];
  25255             } else
  25256 #endif /* BCM_TOMAHAWK3_SUPPORT */
  25257 #endif /* BCM_TOMAHAWK_SUPPORT */
  25258 #ifdef BCM_TRIDENT3_SUPPORT
  25259             if (MEM_IS_VLAN_XLATE(mem)) {
  25260                 se        = &cb->e.vlan[ent];
  25261                 ent_incr  = cb->width[ent];
  25262             } else if (MEM_IS_EGR_VLAN_XLATE(mem)) {
  25263                 se        = &cb->e.egr_vlan[ent];
  25264                 ent_incr  = cb->width[ent];
  25265             } else if (MEM_IS_MPLS(mem)) {
  25266                 se        = &cb->e.mpls[ent];
  25267                 ent_incr  = cb->width[ent];
  25268             } else if (SOC_IS_TRIDENT3X(unit)) {
  25269                 se = &cb->e.l3_single[ent];
  25270                 ent_incr = cb->width[ent];
  25271             } else 
  25272 #endif /* BCM_TRIDENT3_SUPPORT */
  25273             {
  25274                 se        = &cb->e.l3[ent];
  25275                 ent_incr  = cb->width[ent];
  25276             }
  25277 
  25278             src_mem = cb->mem[ent];
  25279             skip = 0;
  25280             for (bix = 0; bix < num_banks; bix++) {
  25281                 cbix = cb->src_bix + bix + 1;
  25282                 cbix = cbix % bi.num_banks;
  25283 
  25284                 bank_num = bi.bank_nums[cbix];
  25285                 bucket = _soc_mem_shared_hash_bucket(unit, src_mem, bank_num, se);
  25286 
  25287                 /* do not visit a bucket twice */
  25288                 if (SHR_BITGET(bkt_trace, bucket)) {
  25289                     continue;
  25290                 }
  25291 
  25292                 sb = &buckets[bucket];
  25293                 SHR_BITSET(bkt_trace, bucket);
  25294                 sb->level     = cb->level + 1;
  25295                 sb->src_ent   = ent;
  25296                 sb->bucket    = bucket;
  25297                 sb->s_bucket  = curr_bucket;
  25298                 sb->src_bix   = cbix;
  25299 
  25300                 /* connect */
  25301                 pb->n_bucket  = bucket;
  25302                 sb->p_bucket  = pb->bucket;
  25303                 sb->n_bucket  = INVALID_BUCKET;
  25304                 if (MEM_IS_EXACT_MATCH_4(mem) ||
  25305                     (SOC_IS_TRIDENT3X(unit) && MEM_IS_EXACT_MATCH_2(mem))) {
  25306                     rv = soc_mem_read(unit, base_mem, copyno, 
  25307                                       bucket * SRAM_ENTRIES_PER_BUCKET_EM_4, bkt_entry[0]);
  25308                     if (SOC_FAILURE(rv)) {
  25309                         goto cleanup;
  25310                     }
  25311                     rv = soc_mem_read(unit, base_mem, copyno, 
  25312                                       bucket * SRAM_ENTRIES_PER_BUCKET_EM_4 + 1, 
  25313                                       bkt_entry[1]);
  25314                     if (SOC_FAILURE(rv)) {
  25315                         goto cleanup;
  25316                     }
  25317                     rv = soc_mem_read(unit, base_mem, copyno, 
  25318                                       bucket * SRAM_ENTRIES_PER_BUCKET_EM_4 + 2, 
  25319                                       bkt_entry[2]);
  25320                     if (SOC_FAILURE(rv)) {
  25321                         goto cleanup;
  25322                     }
  25323                     rv = soc_mem_read(unit, base_mem, copyno, 
  25324                                       bucket * SRAM_ENTRIES_PER_BUCKET_EM_4 + 3, 
  25325                                       bkt_entry[3]);
  25326                     if (SOC_FAILURE(rv)) {
  25327                         goto cleanup;
  25328                     }                
  25329                     soc_mem_field_get(unit, base_mem, bkt_entry[3], vld_fld_0, &v[3]);
  25330                     soc_mem_field_get(unit, base_mem, bkt_entry[2], vld_fld_0, &v[2]);
  25331                     soc_mem_field_get(unit, base_mem, bkt_entry[1], vld_fld_0, &v[1]);
  25332                     soc_mem_field_get(unit, base_mem, bkt_entry[0], vld_fld_0, &v[0]);
  25333                     soc_mem_field_get(unit, base_mem, bkt_entry[3], key_type_0, &k[3]);
  25334                     soc_mem_field_get(unit, base_mem, bkt_entry[2], key_type_0, &k[2]);
  25335                     soc_mem_field_get(unit, base_mem, bkt_entry[1], key_type_0, &k[1]);
  25336                     soc_mem_field_get(unit, base_mem, bkt_entry[0], key_type_0, &k[0]);
  25337 
  25338                 } else if (MEM_IS_EXACT_MATCH_2(mem)) {
  25339                     rv = soc_mem_read(unit, base_mem, copyno, 
  25340                                       bucket * SRAM_ENTRIES_PER_BUCKET_EM_2, bkt_entry[0]);
  25341                     if (SOC_FAILURE(rv)) {
  25342                         goto cleanup;
  25343                     }
  25344                     rv = soc_mem_read(unit, base_mem, copyno, 
  25345                                       bucket * SRAM_ENTRIES_PER_BUCKET_EM_2 + 1, 
  25346                                       bkt_entry[1]);
  25347                     if (SOC_FAILURE(rv)) {
  25348                         goto cleanup;
  25349                     }            
  25350                     soc_mem_field_get(unit, base_mem, bkt_entry[1], vld_fld_2, &v[3]);
  25351                     soc_mem_field_get(unit, base_mem, bkt_entry[1], vld_fld_0, &v[2]);
  25352                     soc_mem_field_get(unit, base_mem, bkt_entry[0], vld_fld_2, &v[1]);
  25353                     soc_mem_field_get(unit, base_mem, bkt_entry[0], vld_fld_0, &v[0]);
  25354                     soc_mem_field_get(unit, base_mem, bkt_entry[1], key_type_2, &k[3]);
  25355                     soc_mem_field_get(unit, base_mem, bkt_entry[1], key_type_0, &k[2]);
  25356                     soc_mem_field_get(unit, base_mem, bkt_entry[0], key_type_2, &k[1]);
  25357                     soc_mem_field_get(unit, base_mem, bkt_entry[0], key_type_0, &k[0]);
  25358 
  25359                 } else {
  25360                 /* loop sub bucket's entries and try move */
  25361                     rv = soc_mem_read(unit, base_mem, copyno, bucket, bkt_entry[0]);
  25362                 if (SOC_FAILURE(rv)) {
  25363                     goto cleanup;
  25364                 }
  25365 
  25366 #ifdef BCM_HELIX5_SUPPORT
  25367                     if (SOC_IS_HELIX5(unit)) {
  25368                         soc_hx5_hash_mem_status_get(unit, base_mem, bkt_entry[0], v);
  25369                         soc_mem_field_get(unit, base_mem, bkt_entry[0], KEY_TYPEf, &k[0]);
  25370                         k[3] = k[2] = k[1] = k[0];
  25371                     } else
  25372 #endif /* BCM_HELIX5_SUPPORT */
  25373 #ifdef BCM_TRIDENT3_SUPPORT
  25374                     if (SOC_IS_TRIDENT3X(unit)) {
  25375                         soc_td3_hash_mem_status_get(unit, base_mem, bkt_entry[0], v);
  25376                         soc_mem_field_get(unit, base_mem, bkt_entry[0], KEY_TYPEf, &k[0]);
  25377                         k[3] = k[2] = k[1] = k[0];
  25378                     } else
  25379 #endif /* BCM_TRIDENT3_SUPPORT */
  25380 #ifdef BCM_TOMAHAWK3_SUPPORT
  25381                     if (SOC_IS_TOMAHAWK3(unit)) {
  25382                         soc_tomahawk3_hash_mem_status_get(unit, base_mem, bkt_entry[0], v);
  25383                         soc_mem_field_get(unit, base_mem, bkt_entry[0], KEY_TYPEf, &k[0]);
  25384                         k[3] = k[2] = k[1] = k[0];
  25385                     } else
  25386 #endif /* BCM_TOMAHAWK3_SUPPORT */
  25387                     {
  25388                         soc_mem_field_get(unit, base_mem, bkt_entry[0], vld_fld_3, &v[3]);
  25389                         soc_mem_field_get(unit, base_mem, bkt_entry[0], vld_fld_2, &v[2]);
  25390                         soc_mem_field_get(unit, base_mem, bkt_entry[0], vld_fld_1, &v[1]);
  25391                         soc_mem_field_get(unit, base_mem, bkt_entry[0], vld_fld_0, &v[0]);
  25392                         soc_mem_field_get(unit, base_mem, bkt_entry[0], key_type_3, &k[3]);
  25393                         soc_mem_field_get(unit, base_mem, bkt_entry[0], key_type_2, &k[2]);
  25394                         soc_mem_field_get(unit, base_mem, bkt_entry[0], key_type_1, &k[1]);
  25395                         soc_mem_field_get(unit, base_mem, bkt_entry[0], key_type_0, &k[0]);
  25396                     }
  25397                 }
  25398           
  25399                 sb->status = (v[3]? (1 << 3) : 0) | (v[2]? (1 << 2) : 0) | 
  25400                              (v[1]? (1 << 1) : 0) | (v[0]? 1 : 0);
  25401 
  25402                 /* loop sub bucket's entries and try insert */
  25403                 for (sent = 0; sent < NUM_ENT; sent += sent_incr) {
  25404                     if (!v[sent]) {
  25405                         sent_incr = 1;
  25406                         continue;
  25407                     }
  25408 #ifdef BCM_TOMAHAWK_SUPPORT                    
  25409                     if (MEM_IS_EXACT_MATCH_4(mem)) {
  25410                         me = &sb->e.em_4[sent];                        
  25411                     } else if (MEM_IS_EXACT_MATCH_2(mem)) {
  25412                         me = &sb->e.em_2[sent];
  25413                     } else
  25414 #ifdef BCM_TOMAHAWK3_SUPPORT
  25415                     if (MEM_IS_MPLS(mem)) {
  25416                         me = &sb->e.mpls_1[sent];
  25417                     } else
  25418 #endif /* BCM_TOMAHAWK3_SUPPORT */
  25419 #endif /* BCM_TOMAHAWK_SUPPORT */
  25420 #ifdef BCM_TRIDENT3_SUPPORT
  25421                     if (MEM_IS_VLAN_XLATE(mem)) {
  25422                         me = &sb->e.vlan[sent];
  25423                     } else if (MEM_IS_EGR_VLAN_XLATE(mem)) {
  25424                         me = &sb->e.egr_vlan[sent];
  25425                     } else if (MEM_IS_MPLS(mem)) {
  25426                         me = &sb->e.mpls[sent];
  25427                     } else if (SOC_IS_TRIDENT3X(unit)) {
  25428                         me = &sb->e.l3_single[sent];
  25429                     } else 
  25430 #endif /* BCM_TRIDENT3_SUPPORT */
  25431                     {
  25432                     me = &sb->e.l3[sent];
  25433                     }
  25434 
  25435 #ifdef BCM_HELIX5_SUPPORT
  25436                     if (SOC_IS_HELIX5(unit)) {
  25437                         SOC_IF_ERROR_RETURN(soc_hx5_shared_hash_mem_bucket_read
  25438                                         (unit, sent, k[sent], &sent_incr,
  25439                                          base_mem, &orig_mem, bkt_entry[sent / SRAM_ENTRIES_PER_BUCKET], me));
  25440                     } else
  25441 #endif /* BCM_HELIX5_SUPPORT */
  25442 #ifdef BCM_TRIDENT3_SUPPORT
  25443                     if (SOC_IS_TRIDENT3X(unit)) {
  25444                         if (MEM_IS_EXACT_MATCH_2(mem) ||
  25445                             MEM_IS_EXACT_MATCH_4(mem)) {
  25446                             SOC_IF_ERROR_RETURN(soc_td3_shared_hash_mem_bucket_read
  25447                                         (unit, sent, k[sent], &sent_incr, base_mem,
  25448                                          &orig_mem, bkt_entry[sent], me));
  25449                         }
  25450                     } else 
  25451 #endif /* BCM_TRIDENT3_SUPPORT */
  25452                     {
  25453 #if defined(BCM_TOMAHAWK_SUPPORT)
  25454 #if defined(BCM_TOMAHAWK3_SUPPORT)
  25455                     if (SOC_IS_TOMAHAWK3(unit)) {
  25456                         if (MEM_IS_EXACT_MATCH_2(mem) ||
  25457                             MEM_IS_EXACT_MATCH_4(mem)) {
  25458                             SOC_IF_ERROR_RETURN(soc_tomahawk3_shared_hash_mem_bucket_read
  25459                                         (unit, sent, k[sent], &sent_incr, base_mem,
  25460                                          &orig_mem, bkt_entry[sent], me));
  25461                         }
  25462                     } else
  25463 #endif /* BCM_TOMAHAWK3_SUPPORT */
  25464                         if (MEM_IS_EXACT_MATCH_4(mem)) {
  25465                             me = &sb->e.em_4[sent];
  25466                             _soc_mem_shared_hash_exact_match_bucket_read(unit, sent, k[sent],
  25467                                     &sent_incr, &orig_mem, bkt_entry[sent], me, pipenum);                        
  25468                         } else if (MEM_IS_EXACT_MATCH_2(mem)) {
  25469                             me = &sb->e.em_2[sent];
  25470                             _soc_mem_shared_hash_exact_match_bucket_read(unit, sent, k[sent],
  25471                                     &sent_incr, &orig_mem, bkt_entry[sent / SRAM_ENTRIES_PER_BUCKET_EM_2], me, pipenum); 
  25472                         } else 
  25473 #endif
  25474                         {
  25475                     _soc_mem_shared_hash_l3_bucket_read(unit, sent, k[sent],
  25476                                 &sent_incr, &orig_mem, bkt_entry[0], me);
  25477                     }
  25478                     }
  25479                     sb->width[sent] = sent_incr;
  25480                     sb->mem[sent] = orig_mem;
  25481 
  25482                     rv = soc_mem_generic_insert(unit, orig_mem, copyno,
  25483                                                 bi.banks & ~(1 << bank_num),
  25484                                                 me, NULL, &move_bkt);
  25485 
  25486                     free = 0;
  25487                     if (SOC_SUCCESS(rv)) {
  25488 
  25489                         /* modifying a visited a bucket may
  25490                          * corrupt the structure (entry, status ...)
  25491                          */
  25492                         move_bkt /= _soc_mem_shared_hash_entries_per_bkt(unit, orig_mem);
  25493                         if (SHR_BITGET(bkt_trace, move_bkt)) {
  25494                             rv = soc_mem_generic_delete(unit, orig_mem, MEM_BLOCK_ANY,
  25495                                                         bi.banks & ~(1 << bank_num),
  25496                                                         me, NULL, NULL);
  25497 
  25498                             if (SOC_FAILURE(rv)) {
  25499                                 goto cleanup;
  25500                             }
  25501                         } else {
  25502                             rv = soc_mem_generic_delete(unit, orig_mem, MEM_BLOCK_ANY,
  25503                                                         1 << bank_num, me, NULL, NULL);
  25504                             if (SOC_FAILURE(rv)) {
  25505                                 goto cleanup;
  25506                             }
  25507                             sb->status &= ~(((1 << sent_incr) - 1) << sent);
  25508 
  25509                             _SOC_MEM_SHARED_HASH_STATUS_CHECK(free, src_mem, sb->status);
  25510                         }
  25511                     }
  25512                     /* sb is not freed, try move next entry in sb */
  25513                     if (!free) {
  25514                         continue;
  25515                     }
  25516 
  25517                     /* now sb is freed.
  25518                      * cb's entry can be moved now. move it and
  25519                      * more if possible
  25520                      */
  25521                     ibank_num = bank_num;
  25522                     pbi = sb;
  25523 
  25524                     while (free && pbi->s_bucket != bi.numb) {
  25525                         cbi = pbi;
  25526                         pbi = &buckets[pbi->s_bucket];
  25527 #ifdef BCM_TOMAHAWK_SUPPORT                        
  25528                         if (MEM_IS_EXACT_MATCH_4(mem)) {
  25529                             me = &pbi->e.em_4[cbi->src_ent];
  25530                         } else if (MEM_IS_EXACT_MATCH_2(mem)) {
  25531                             me = &pbi->e.em_2[cbi->src_ent];
  25532                         } else
  25533 #ifdef BCM_TOMAHAWK3_SUPPORT
  25534                         if (MEM_IS_MPLS(mem)) {
  25535                             me = &sb->e.mpls_1[cbi->src_ent];
  25536                         } else
  25537 #endif /* BCM_TOMAHAWK3_SUPPORT */
  25538 #endif /* BCM_TOMAHAWK_SUPPORT */
  25539 #ifdef BCM_TRIDENT3_SUPPORT
  25540                         if (MEM_IS_VLAN_XLATE(mem)) {
  25541                             me = &pbi->e.vlan[cbi->src_ent];
  25542                         } else if (MEM_IS_EGR_VLAN_XLATE(mem)) {
  25543                             me = &pbi->e.egr_vlan[cbi->src_ent];
  25544                         } else if (MEM_IS_MPLS(mem)) {
  25545                             me = &pbi->e.mpls[cbi->src_ent];
  25546                         } else if (SOC_IS_TRIDENT3X(unit)) {
  25547                             me = &pbi->e.l3_single[cbi->src_ent];
  25548                         } else 
  25549 #endif /* BCM_TRIDENT3_SUPPORT */
  25550                         {
  25551                         me = &pbi->e.l3[cbi->src_ent];
  25552                         }
  25553 
  25554                         orig_mem = pbi->mem[cbi->src_ent];
  25555                         rv = soc_mem_generic_insert(unit, orig_mem, copyno,
  25556                                                     (1 << ibank_num),
  25557                                                     me, NULL, NULL);
  25558                         if (SOC_FAILURE(rv)) {
  25559                             goto cleanup;
  25560                         }
  25561 
  25562                         ibank_num = bi.bank_nums[pbi->src_bix];
  25563 
  25564                         rv = soc_mem_generic_delete(unit, orig_mem,
  25565                                                     MEM_BLOCK_ANY,
  25566                                                     (1 << ibank_num),
  25567                                                     me, NULL, NULL);
  25568                         if (SOC_FAILURE(rv)) {
  25569                             goto cleanup;
  25570                         }
  25571 
  25572                         src_width = _soc_mem_hash_mem_width_get(unit, mem);
  25573                         pbi->status &= ~(((1 << src_width) - 1) << cbi->src_ent);
  25574 
  25575                         _SOC_MEM_SHARED_HASH_STATUS_CHECK(free,
  25576                             buckets[pbi->s_bucket].mem[pbi->src_ent], pbi->status);
  25577                     }
  25578 
  25579                     if (free) {
  25580                         job_done = 1;
  25581                         goto done;
  25582                     } else {
  25583                         /* re-connect, because some of sbs which are linked
  25584                          * just now, may need to be removed from the link.
  25585                          */
  25586 
  25587                         /* taking care of the sub buckets at next level */
  25588                         while (pb->level == sb->level) {
  25589                             ib = pb;
  25590                             while (ib->level > cbi->level) {
  25591                                 ib = &buckets[ib->s_bucket];
  25592                             }
  25593                             if (ib->s_bucket != cbi->s_bucket ||
  25594                                 ib->src_ent != cbi->src_ent) {
  25595                                 break;
  25596                             }
  25597                             /* this could be further optimized to clear
  25598                              * those skipped sbs and free the bucket.
  25599                              */
  25600                             pb = &buckets[pb->p_bucket];
  25601                         }
  25602 
  25603                         /* taking care of the current buckets at this level */
  25604                         if (pbi == cb) {
  25605                             /* moved 1 entry. entry of cb is moved, but cb is
  25606                              * still not freed. continue next entry's sub bucket
  25607                              */
  25608                             skip = 1;
  25609                             /* assert (cb->level == cbi->level - 1); */
  25610                         } else {
  25611 
  25612                             /* moved at least 2 entries, now it's time
  25613                              * to advance current bucket.
  25614                              */
  25615 
  25616                             /* assert (cb->level >= cbi->level); */
  25617                             skip = 2;
  25618 
  25619                             nb = &buckets[cb->n_bucket];
  25620                             while (nb->level != sb->level) {
  25621                                 ib = nb;
  25622                                 while (ib->level > cbi->level) {
  25623                                     ib = &buckets[ib->s_bucket];
  25624                                 }
  25625                                 if (ib->s_bucket != cbi->s_bucket ||
  25626                                     ib->src_ent != cbi->src_ent) {
  25627                                     break;
  25628                                 }
  25629                                 nb = &buckets[nb->n_bucket];
  25630                             }
  25631 
  25632                             cb = &buckets[nb->p_bucket];
  25633                         }
  25634                         break;
  25635                     }
  25636                 } /* sub bucket loop and move done. */
  25637                 if (skip) {
  25638                     break;
  25639                 }
  25640                 pb = sb;
  25641             }
  25642             if (skip == 2) {
  25643                 break;
  25644             }
  25645         }
  25646         curr_bucket = cb->n_bucket;
  25647     } while (curr_bucket != INVALID_BUCKET);
  25648 
  25649 done:
  25650     if (job_done) {
  25651         rv = soc_mem_generic_insert(unit, mem, copyno, 1 << ibank_num,
  25652                                     entry, entry, NULL);
  25653     } else {
  25654         rv = SOC_E_FULL;
  25655     }
  25656 
  25657 cleanup:
  25658     if (bkt_trace) {
  25659         sal_free(bkt_trace);
  25660     }
  25661 
  25662     if (buckets) {
  25663         sal_free(buckets);
  25664     }
  25665 
  25666     if (SOC_FAILURE(rv)) {
  25667         LOG_VERBOSE(BSL_LS_SOC_COMMON,
  25668                     (BSL_META_U(unit,
  25669                                 "Insert entry: %d\n"), rv));
  25670     }
  25671 
  25672     return rv;
  25673 }
  25674 
  25675 /*
  25676  * this breadth algorithm is the default one which is faster and
  25677  * consume less memory.
  25678  */
  25679 #define MAX_MIX_LEVELS  4
  25680 #define MAX_L2_LEVELS  6
  25681 
  25682 STATIC int
  25683 _soc_mem_shared_hash_breadth_l2_move(int unit, soc_mem_t mem, int copyno,
  25684                                      void *entry, int num_levels)
  25685 {
  25686     SHR_BITDCL *bkt_trace = NULL;
  25687     _soc_breadth_bucket_t *buckets[MAX_L2_LEVELS + 1] = {0};
  25688     _soc_breadth_bucket_t *cb, *tb, *cbi = NULL, *pbi;
  25689     uint32 *se;
  25690     int rv;
  25691     int level, job_done = 0;
  25692     int bank_num, ibank_num = 0;
  25693     int bix, cbix;
  25694     int bkt_idx;
  25695     int nl_bkt_idx, num_cl_bkts;
  25696     int ent, bucket;
  25697     int i;
  25698     _soc_hash_bank_info_t bi = {0};
  25699 
  25700     if (num_levels <= 0) {
  25701         return SOC_E_FULL;
  25702     } else if (num_levels > MAX_L2_LEVELS) {
  25703         return _soc_mem_shared_hash_breadth_l2_move2(unit, mem, copyno,
  25704                                                      entry, num_levels);
  25705     }
  25706 
  25707     SOC_IF_ERROR_RETURN(_soc_mem_shared_hash_init
  25708         (unit, mem, &bkt_trace, &bi, num_levels, &buckets[0], NULL));
  25709 
  25710     num_cl_bkts = bi.num_banks;
  25711 
  25712     for (level = 0; level < num_levels; level++) {
  25713         if (level + 1 < num_levels) {
  25714             buckets[level + 1] = buckets[level] + num_cl_bkts;
  25715         } else {
  25716             buckets[level + 1] = 0;
  25717         }
  25718         for (bkt_idx = 0; bkt_idx < num_cl_bkts; bkt_idx++) {
  25719             cb = &buckets[level][bkt_idx];
  25720             if (level == 0) {
  25721                 cb->src_bix = bkt_idx;
  25722                 cb->src_mem  = mem;
  25723                 se = entry;
  25724             } else {
  25725                 se = (uint32 *)&buckets[level - 1][cb->src_bkt_idx].e.l2[cb->src_ent];
  25726             }
  25727 
  25728             if (cb->src_mem == 0) {
  25729                 continue;
  25730             }
  25731 
  25732             bank_num = bi.bank_nums[cb->src_bix];
  25733             bucket = _soc_mem_shared_hash_bucket(unit, cb->src_mem, bank_num, se);
  25734 
  25735             if (SHR_BITGET(bkt_trace, bucket)) {
  25736                 continue;
  25737             }
  25738             SHR_BITSET(bkt_trace, bucket);
  25739             cb->bucket = bucket;
  25740 
  25741             for (ent = 0; ent < NUM_ENT; ent++) {
  25742                 /* Read current entry */
  25743                 rv = soc_mem_read(unit, mem, copyno, (bucket << 2) + ent, &cb->e.l2[ent]);
  25744                 if (SOC_FAILURE(rv)) {
  25745                     goto cleanup;
  25746                 }
  25747 
  25748                 /* Try insert */
  25749                 rv = soc_mem_generic_insert(unit, mem, copyno,
  25750                                             bi.banks & ~(1 << bank_num),
  25751                                             &cb->e.l2[ent], NULL, NULL);
  25752 
  25753                 if (SOC_SUCCESS(rv)) {
  25754                     rv = soc_mem_generic_delete(unit, mem, MEM_BLOCK_ANY,
  25755                                                 (uint32)1<<bank_num,
  25756                                                 &cb->e.l2[ent], NULL, NULL);
  25757                     if (SOC_FAILURE(rv)) {
  25758                         goto cleanup;
  25759                     }
  25760                     break;
  25761                 }
  25762 
  25763                 /* Construct buckets in next level under this entry */
  25764                 nl_bkt_idx = bkt_idx * (bi.num_banks - 1) * NUM_ENT +
  25765                                  ent * (bi.num_banks - 1);
  25766 
  25767                 for (bix = 0; bix < bi.num_banks && buckets[level + 1]; bix++) {
  25768                     cbix = cb->src_bix + bix + 1;
  25769                     cbix = cbix % bi.num_banks;
  25770                     if (bank_num == bi.bank_nums[cbix]) {
  25771                         continue;
  25772                     }
  25773 
  25774                     tb = &buckets[level + 1][nl_bkt_idx++];
  25775                     tb->src_bkt_idx   = bkt_idx;
  25776                     tb->src_bix  = cbix;
  25777                     tb->src_mem  = mem;
  25778                     tb->src_ent  = ent;
  25779                 }
  25780             }
  25781 
  25782             if (ent < NUM_ENT) {
  25783                 ibank_num = bank_num;
  25784                 pbi = cb;
  25785                 for (i = level; i > 0; i--) {
  25786                     cbi = pbi;
  25787                     pbi = &buckets[i - 1][cbi->src_bkt_idx];
  25788 
  25789                     rv = soc_mem_bank_insert(unit, cbi->src_mem,
  25790                                              (1 << ibank_num), copyno,
  25791                                              &pbi->e.l2[cbi->src_ent], NULL);
  25792                     if (SOC_FAILURE(rv)) {
  25793                         goto cleanup;
  25794                     }
  25795 
  25796                     ibank_num = bi.bank_nums[pbi->src_bix];
  25797 
  25798                     rv = soc_mem_generic_delete(unit, cbi->src_mem, MEM_BLOCK_ANY,
  25799                                                 (1 << ibank_num),
  25800                                                 &pbi->e.l2[cbi->src_ent], NULL, NULL);
  25801                     if (SOC_FAILURE(rv)) {
  25802                         goto cleanup;
  25803                     }
  25804                 }
  25805                 job_done = 1;
  25806                 goto done;
  25807             }
  25808         }
  25809         num_cl_bkts *= (bi.num_banks - 1) * NUM_ENT;
  25810     }
  25811 
  25812 done:
  25813     if (job_done) {
  25814         rv = soc_mem_generic_insert(unit, mem, copyno, 1 << ibank_num,
  25815                                     entry, entry, NULL);
  25816     } else {
  25817         rv = SOC_E_FULL;
  25818     }
  25819 
  25820 cleanup:
  25821     if (bkt_trace) {
  25822         sal_free(bkt_trace);
  25823     }
  25824 
  25825     if (buckets[0]) {
  25826         sal_free(buckets[0]);
  25827     }
  25828 
  25829     if (SOC_FAILURE(rv)) {
  25830         LOG_VERBOSE(BSL_LS_SOC_COMMON,
  25831                     (BSL_META_U(unit,
  25832                                 "Insert entry: %d\n"), rv));
  25833     }
  25834 
  25835     return rv;
  25836 }
  25837 
  25838 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  25839 #define ENTRIES_PER_BKT_TD3 4
  25840 typedef struct _soc_breadth_bucket_td3_s {
  25841     soc_mem_t src_mem;
  25842     uint8 src_bix;
  25843     uint8 td3_status[ENTRIES_PER_BKT_TD3];
  25844     uint8 src_width;
  25845     uint8 src_ent;
  25846     uint32 src_bkt_idx;
  25847     uint32 bucket;
  25848     union {
  25849         l2x_entry_t*                     l2[NUM_ENT_TD3];
  25850         l3_entry_quad_entry_t*           l3_quad[NUM_ENT_TD3];
  25851         exact_match_2_entry_t*           em_2[NUM_ENT_TD3];
  25852         exact_match_4_entry_t*           em_4[NUM_ENT_TD3];
  25853         vlan_xlate_1_double_entry_t*     vlan[NUM_ENT_TD3];
  25854         egr_vlan_xlate_1_double_entry_t* egr_vlan[NUM_ENT_TD3];
  25855         mpls_entry_entry_t*              mpls[NUM_ENT_TD3];
  25856         mpls_entry_single_entry_t*       mpls_1[NUM_ENT_TD3];
  25857         l3_entry_only_entry_t*           l3[NUM_ENT_TD3];
  25858 #ifdef BCM_TOMAHAWK3_SUPPORT
  25859         tunnel_quad_entry_t*             tunnel_quad[NUM_ENT_TD3];
  25860 #endif
  25861     } e;
  25862 } _soc_breadth_bucket_td3_t;
  25863 
  25864 static INLINE int
  25865 _soc_mem_shared_hash_init_td3(int unit,
  25866                               int num_banks,
  25867                               int num_levels,
  25868                               _soc_breadth_bucket_td3_t **buckets,
  25869                               int *total_buckets)
  25870 {
  25871     static int td3_prev_num_levels = 0;
  25872     static int td3_prev_tot_bkts   = 0;
  25873     static int td3_prev_num_banks  = 0;
  25874     static _soc_breadth_bucket_td3_t *td3_prev_bkt = NULL;
  25875     int alloc_size = 0;
  25876     int num_cl_buckets;
  25877     int level;
  25878 
  25879     if (!buckets) return (SOC_E_INTERNAL);
  25880     if ((td3_prev_num_levels == num_levels) &&
  25881         (td3_prev_num_banks == num_banks)) {
  25882         *buckets = td3_prev_bkt;
  25883         *total_buckets = td3_prev_tot_bkts;
  25884         return (SOC_E_NONE);
  25885     }
  25886 
  25887     if (td3_prev_bkt != NULL) {
  25888         sal_free(td3_prev_bkt);
  25889     }
  25890 
  25891     num_cl_buckets = num_banks;
  25892     for (level = 0; level < num_levels; level++) {
  25893         alloc_size += num_cl_buckets;
  25894         num_cl_buckets *= (num_banks - 1) * NUM_ENT_TD3;
  25895     }
  25896     *total_buckets = alloc_size;
  25897     alloc_size *= sizeof(_soc_breadth_bucket_td3_t);
  25898 
  25899     *buckets = sal_alloc(alloc_size, "Buckets");
  25900     if (*buckets == NULL) {
  25901         return SOC_E_MEMORY;
  25902     }
  25903     sal_memset(*buckets, 0, alloc_size);
  25904 
  25905     td3_prev_bkt        = *buckets;
  25906     td3_prev_num_levels = num_levels;
  25907     td3_prev_num_banks  = num_banks;
  25908     td3_prev_tot_bkts   = *total_buckets;
  25909 
  25910     return SOC_E_NONE;
  25911 }
  25912 
  25913 STATIC void*
  25914 _soc_mem_hash_entry_buffer_get(int unit, int mem, _soc_breadth_bucket_td3_t *bkt, int ent)
  25915 {
  25916     void *se;
  25917     if ((mem == L2Xm) ||
  25918         (mem == L2_ENTRY_SINGLEm) ||
  25919         (mem == L2_ENTRY_ONLY_SINGLEm)) {
  25920         if (!bkt->e.l2[ent]) {
  25921             bkt->e.l2[ent] = (l2x_entry_t*)sal_alloc(sizeof(l2x_entry_t), "Buckets L2X");
  25922             sal_memset(bkt->e.l2[ent], 0, sizeof(l2x_entry_t));
  25923         }
  25924         se = bkt->e.l2[ent];
  25925     } else if (MEM_IS_EXACT_MATCH_2(mem) || MEM_IS_EXACT_MATCH_4(mem)) {
  25926         if (!bkt->e.em_4[ent]) {
  25927             bkt->e.em_4[ent] = sal_alloc(sizeof(exact_match_4_entry_t), "Buckets EM Quad");
  25928             sal_memset(bkt->e.em_4[ent], 0, sizeof(exact_match_4_entry_t));
  25929         }
  25930         se = bkt->e.em_4[ent];
  25931     } else if (MEM_IS_VLAN_XLATE(mem)) {
  25932         if (!bkt->e.vlan[ent]) {
  25933             bkt->e.vlan[ent] = sal_alloc(sizeof(vlan_xlate_1_double_entry_t), "Buckets L2E");
  25934             sal_memset(bkt->e.vlan[ent], 0, sizeof(vlan_xlate_1_double_entry_t));
  25935         }
  25936         se = bkt->e.vlan[ent];
  25937     } else if (MEM_IS_EGR_VLAN_XLATE(mem)) {
  25938         if (!bkt->e.egr_vlan[ent]) {
  25939             bkt->e.egr_vlan[ent] = sal_alloc(sizeof(egr_vlan_xlate_1_double_entry_t), "Buckets EGR Vlan");
  25940             sal_memset(bkt->e.egr_vlan[ent], 0, sizeof(egr_vlan_xlate_1_double_entry_t));
  25941         }
  25942         se = bkt->e.egr_vlan[ent];
  25943     } else if (MEM_IS_MPLS(mem)) {
  25944         if (SOC_IS_TOMAHAWK3(unit)) {
  25945             if (!bkt->e.mpls_1[ent]) {
  25946                 bkt->e.mpls_1[ent] = sal_alloc(sizeof(mpls_entry_single_entry_t), "Buckets MPLS Single");
  25947                 sal_memset(bkt->e.mpls_1[ent], 0, sizeof(mpls_entry_single_entry_t));
  25948             }
  25949             se = bkt->e.mpls_1[ent];
  25950         } else {
  25951             if (!bkt->e.mpls[ent]) {
  25952                 bkt->e.mpls[ent] = sal_alloc(sizeof(mpls_entry_entry_t), "Buckets MPLS");
  25953                 sal_memset(bkt->e.mpls[ent], 0, sizeof(mpls_entry_entry_t));
  25954             }
  25955             se = bkt->e.mpls[ent];
  25956         }
  25957     } else if (MEM_IS_L3_ENTRY_SINGLE(mem) ||
  25958                MEM_IS_L3_ENTRY_DOUBLE(mem) ||
  25959                MEM_IS_L3_ENTRY_QUAD(mem)) {
  25960         if (!bkt->e.l3_quad[ent]) {
  25961             bkt->e.l3_quad[ent] = sal_alloc(sizeof(l3_entry_quad_entry_t), "Buckets L3 QUAD");
  25962             sal_memset(bkt->e.l3_quad[ent], 0, sizeof(l3_entry_quad_entry_t));
  25963         }
  25964         se = bkt->e.l3_quad[ent];
  25965     } else 
  25966 #ifdef BCM_TOMAHAWK3_SUPPORT
  25967     if (MEM_IS_L3_TUNNEL_SINGLE(mem) ||
  25968         MEM_IS_L3_TUNNEL_DOUBLE(mem) ||
  25969         MEM_IS_L3_TUNNEL_QUAD(mem)) {
  25970         if (!bkt->e.tunnel_quad[ent]) {
  25971             bkt->e.tunnel_quad[ent] = sal_alloc(sizeof(tunnel_quad_entry_t), "Buckets L3 Tunnel QUAD");
  25972             sal_memset(bkt->e.tunnel_quad[ent], 0, sizeof(tunnel_quad_entry_t));
  25973         }
  25974         se = bkt->e.tunnel_quad[ent];
  25975     } else 
  25976 #endif
  25977     {
  25978         if (!bkt->e.l3[ent]) {
  25979             bkt->e.l3[ent] = sal_alloc(sizeof(l3_entry_only_entry_t), "Buckets L3");
  25980             sal_memset(bkt->e.l3[ent], 0, sizeof(l3_entry_only_entry_t));
  25981         }
  25982         se = bkt->e.l3[ent];
  25983     }
  25984     return (se);
  25985 }
  25986 
  25987 extern int soc_td3_tbl_entries_per_sram_entry_get(int unit, soc_mem_t mem,
  25988                        int *table_entries_per_sram_entry);
  25989 
  25990 #define MAX_MIX_LEVELS_TD3  6
  25991 #define TD3_ENTRIES_PER_BUCKET 4
  25992 /***************************************************************************************
  25993  * _soc_mem_shared_hash_td3_breadth_mix_move                                           *
  25994  *                                                                                     *
  25995  * S/W re-order algorithm to enhance the efficiency of UAT/UFT HASH tables.            *
  25996  * TD3 - a bucket has 4 entries irrespective of Single Double or Quad wide.            *
  25997  *                                                                                     *
  25998  * TD3 uses similar algorithm as used in TH. In TH - number of entries in a bucket     *
  25999  * could be 1 quad or 4 single or a mix.., A maximum of 4 entries per bucket. In TD3   *
  26000  * there could be a maximum of 16 entries in a quad based bucket. So NUM_ENT_TD3 is 16 *
  26001  *                                                                                     *
  26002  * If source entry is single wide - 1 quad wide entry represents a bucket.             *
  26003  *    so 1 quad wide entry will be attempted to move to other banks in every level.    *
  26004  *                                                                                     *
  26005  * If source entry is double wide - 2 quad wide entry represents a bucket.             *
  26006  *    so 2 quad wide entries will be attempted to move to other banks in level-1.      *
  26007  *    only 1 quad wide entry will be attempted to move to other banks in all levels.   *
  26008  *                                                                                     *
  26009  * If source entry is quad wide - 4 quad wide entry represents a bucket.               *
  26010  *    so 4 quad wide entries will be attempted to move to other banks in level-1.      *
  26011  *    only 1 quad wide entry will be attempted to move to other banks in all levels.   *
  26012  */
  26013 sal_mutex_t td3_hash_mutex[SOC_MAX_NUM_DEVICES] = {NULL};
  26014 
  26015 int
  26016 soc_td3_hash_mutex_init (int unit)
  26017 {
  26018     if (unit >= SOC_MAX_NUM_DEVICES) {
  26019         return (SOC_E_INTERNAL);
  26020     }
  26021     if (td3_hash_mutex[unit] != NULL) {
  26022         sal_mutex_destroy(td3_hash_mutex[unit]);
  26023     }
  26024     td3_hash_mutex[unit] = sal_mutex_create("td3_hash_mutex");
  26025     return (SOC_E_NONE);
  26026 }
  26027 
  26028 #define TD3_HASH_LOCK(unit)    sal_mutex_take(td3_hash_mutex[unit], sal_mutex_FOREVER);
  26029 #define TD3_HASH_UNLOCK(unit)  sal_mutex_give(td3_hash_mutex[unit]);
  26030 
  26031 STATIC int
  26032 _soc_mem_shared_hash_td3_breadth_mix_move(int unit, soc_mem_t mem, int copyno,
  26033                                      void *entry, int num_levels)
  26034 {
  26035     SHR_BITDCL *bkt_trace = NULL;
  26036     _soc_breadth_bucket_td3_t *buckets[MAX_MIX_LEVELS_TD3 + 1] = {0};
  26037     _soc_breadth_bucket_td3_t *cb, *tb, *cbi = NULL, *pbi;
  26038     uint32 bkt_entry[ENTRIES_PER_BKT_TD3][SOC_MAX_MEM_WORDS];
  26039     uint32 v[NUM_ENT_TD3], w[NUM_ENT_TD3];
  26040     void *se, *me;
  26041     int rv;
  26042     int level, job_done = 0;
  26043     int move_bkt;
  26044     int bank_num, ibank_num = 0;
  26045     int bix, cbix;
  26046     int free = 0, moved = 0;
  26047     int bkt_idx, bkt_idx1 = 0, bkt_idx2 = 0;
  26048     int nl_bkt_idx, num_cl_bkts, total_buckets;
  26049     int wide_entry;
  26050     uint32 bucket, base_mem_bkt = 0;
  26051     int ent, ent_incr, max_entries_per_row = 4;
  26052     int num = 0, tbl_entries_per_sram_entry = 0;
  26053     int i, j, sok, num_rows_per_bkt, row_idx;
  26054     _soc_hash_bank_info_t bi = {0};
  26055     soc_mem_t src_mem, base_mem;
  26056     int vld_flds[5] = {BASE_VALID_0f, BASE_VALID_1f, BASE_VALID_2f, BASE_VALID_3f, BASE_VALIDf};
  26057 
  26058     if (num_levels <= 0) {
  26059         return SOC_E_FULL;
  26060     }
  26061     if (num_levels > MAX_MIX_LEVELS_TD3) {
  26062         LOG_VERBOSE(BSL_LS_SOC_COMMON,
  26063                     (BSL_META_U(unit,
  26064                         "ERROR: Invalid Level %d (max=%d)\n"),
  26065                          num_levels, MAX_MIX_LEVELS_TD3));
  26066         return SOC_E_FULL;
  26067     }
  26068 
  26069     /*
  26070      * UFT provides single, double and quad table entries.
  26071      * UAT provides single and double table entries only.
  26072      * wide_entry represents quad entry for UFT and double entry for UAT.
  26073      */
  26074 #if defined (BCM_TOMAHAWK3_SUPPORT)
  26075     if (SOC_IS_TOMAHAWK3(unit)) {
  26076         if (MEM_IS_MPLS(mem)) {
  26077             max_entries_per_row = 1;
  26078         }
  26079     } else
  26080 #endif /* BCM_TOMAHAWK3_SUPPORT */
  26081     if (MEM_IS_MPLS(mem) || MEM_IS_VLAN_XLATE(mem) ||
  26082         MEM_IS_EGR_VLAN_XLATE(mem)) {
  26083         max_entries_per_row = 2;
  26084     }
  26085 
  26086     base_mem = _soc_mem_hash_base_mem_get(unit, mem);
  26087 
  26088     TD3_HASH_LOCK(unit);
  26089     SOC_IF_ERROR_RETURN(_soc_mem_shared_hash_init
  26090         (unit, base_mem, &bkt_trace, &bi, num_levels, NULL, NULL));
  26091 
  26092     /*
  26093      * Based on the number of banks, curb the num_levels, otherwise
  26094      * memory usage will be over blown.
  26095      *
  26096      * For instance number of banks is 10.., then the buckets to be
  26097      * allocated for level 1 is 16 * 9 = 144. For level 2 it will be
  26098      * 144 * 144.  For level 6 it will be 144^6.  This is not practical.
  26099      * System will run out of memory. So the following rule will be applied.
  26100      *
  26101      * if num_banks >4 ==> num_levels will be limited to 2.
  26102      * if num_banks >= 2 and <= 4 ==> num_levels will be limited to 4.
  26103      * else num_levels will be MAX_MIX_LEVELS_TD3.
  26104      */
  26105     if (bi.num_banks > 4) {
  26106         if (num_levels > 2) {
  26107             num_levels = 2;
  26108             LOG_VERBOSE(BSL_LS_SOC_COMMON,
  26109                     (BSL_META_U(unit,
  26110                         "WARNING: Level is limited to %d \n"), num_levels));
  26111         }
  26112     } else if ((bi.num_banks >= 3) && (bi.num_banks <= 4)) {
  26113         if (num_levels > 4) {
  26114             num_levels = 4;
  26115             LOG_VERBOSE(BSL_LS_SOC_COMMON,
  26116                     (BSL_META_U(unit,
  26117                         "WARNING: Level is limited to %d \n"), num_levels));
  26118         }
  26119     }
  26120 
  26121     rv = _soc_mem_shared_hash_init_td3(unit,
  26122                               bi.num_banks, num_levels,
  26123                               &buckets[0], &total_buckets);
  26124     if (SOC_FAILURE(rv)) {
  26125         if (bkt_trace) {
  26126             sal_free(bkt_trace);
  26127         }
  26128         return (rv);
  26129     }
  26130 
  26131     num_cl_bkts = bi.num_banks;
  26132 
  26133     for (level = 0; level < num_levels; level++) {
  26134         if (level + 1 < num_levels) {
  26135             buckets[level + 1] = buckets[level] + num_cl_bkts;
  26136         } else {
  26137             buckets[level + 1] = 0;
  26138         }
  26139 
  26140         /*
  26141          * Loop here for the number of buckets in a given level.
  26142          *
  26143          * Level 0 : entry can be added to all banks. Bucket has 4 entries.
  26144          *           Level 0 - entry has (num_of_banks * 4) locations to insert.
  26145          *
  26146          * Level 1 : Every entry from level 0 has (num_of_banks-1 *4) locations
  26147          *           to insert. (total num_of_banks*4)*(num_of_banks-1)*4.
  26148          *
  26149          * Level 2 : Recursive iteration as level 1. Every entry from level 1 has
  26150          *           (num_of_banks-1)*4 locations in level 2.
  26151          *
  26152          * num_cl_bkts represents the number of buckets for the given level
  26153          * as per the iterative calculation described above.
  26154          */
  26155         for (bkt_idx = 0; bkt_idx < num_cl_bkts; bkt_idx++) {
  26156             cb = &buckets[level][bkt_idx];
  26157             if (level == 0) {
  26158                 cb->src_bix = bkt_idx;
  26159                 cb->src_mem  = mem;
  26160                 cb->src_width = _soc_mem_hash_mem_width_get(unit, cb->src_mem);
  26161                 se = entry;
  26162             } else {
  26163                 if (cb->src_mem == 0) {
  26164                     continue;
  26165                 }
  26166                 se = _soc_mem_hash_entry_buffer_get(unit, cb->src_mem,
  26167                           &buckets[level-1][cb->src_bkt_idx], cb->src_ent);
  26168             }
  26169 
  26170             /*
  26171              * Clear the valid array and entry width array.
  26172              *
  26173              * UFT: Every quad entry can hold,
  26174              *         4 single entries, 2 double entries, 1 quad entry.
  26175              *         2 single entries and 1 double entries,
  26176              *         There could be locations with no valid entry too.
  26177              *
  26178              * V[4] : represents if there is a valid entry in the 4 base entries(single).
  26179              * w[4] : represents the width of the valid entries in the quad wide entry.
  26180              *        Entry width is 1 for Single entry, 2 for Double and 4 for Quad entry.
  26181              *
  26182              * For instance a Quad wide Row has | Single | No Entry | DOUBLE ENTRY |
  26183              * Valid bits will be represented as V[4] = {1,0,1,1}
  26184              * Width bits will be represented as W[4] = {1,0,0,2}
  26185              *
  26186              * UFT: Every double entry can hold,
  26187              *         2 single entries, 1 double entries
  26188              *         There could be locations with no valid entry too (one single entry).
  26189              *
  26190              * V : represents if there is a valid entry in the 2 base entries(single).
  26191              * w : represents the width of the valid entries in the double wide entry.
  26192              *        Entry width is 1 for Single entry, 2 for Double entry.
  26193              *
  26194              * For instance a Double wide Row has | Single | No Entry |
  26195              * Valid bits will be represented as V[2] = {1,0}
  26196              * Width bits will be represented as W[2] = {1,0}
  26197              *
  26198              * For instance a Double wide Row has | Double Entry |
  26199              * Valid bits will be represented as V[2] = {1,1}
  26200              * Width bits will be represented as W[2] = {2,0}
  26201              */
  26202             for (i = 0; i < NUM_ENT_TD3; i++) {
  26203                 w[i]=0; /* entry width */
  26204                 v[i]=0; /* entry valid */
  26205             }
  26206 
  26207             bank_num = bi.bank_nums[cb->src_bix];
  26208             bucket   = _soc_mem_shared_hash_bucket(unit, cb->src_mem, bank_num, se);
  26209 
  26210             rv = SOC_E_UNAVAIL;
  26211 
  26212 #ifdef BCM_TOMAHAWK3_SUPPORT
  26213             if (SOC_IS_TOMAHAWK3(unit)) {
  26214                 rv = soc_tomahawk3_tbl_entries_per_sram_entry_get(unit, cb->src_mem,
  26215                            &tbl_entries_per_sram_entry);
  26216             } else
  26217 #endif
  26218             {
  26219 #ifdef BCM_TRIDENT3_SUPPORT
  26220                 rv = soc_td3_tbl_entries_per_sram_entry_get(unit, cb->src_mem,
  26221                        &tbl_entries_per_sram_entry);
  26222 #endif
  26223             }
  26224 
  26225             if (SOC_FAILURE(rv)) {
  26226                 if (bkt_trace) {
  26227                     sal_free(bkt_trace);
  26228                 }
  26229                 return (rv);
  26230             }
  26231 
  26232             /*
  26233              * In order to identify if the entry is a single, double or Quad,
  26234              * a quad wide entry has to be read. So all buckets are read as
  26235              * Quad wide entry.
  26236              *
  26237              * num_rows_per_bkt : represents the number of quad wide entries
  26238              *                    required to represent a bucket.
  26239              *                    1 for single, 2 for double and 4 for quad.
  26240              */
  26241 #if defined(BCM_TOMAHAWK3_SUPPORT)
  26242             if (SOC_IS_TOMAHAWK3(unit)) {
  26243                 if (MEM_IS_MPLS(cb->src_mem)) {
  26244                     num_rows_per_bkt = 4/tbl_entries_per_sram_entry;
  26245                     bucket *=
  26246                         _soc_mem_shared_hash_entries_per_bkt(unit, cb->src_mem);
  26247                 } else {
  26248                     num_rows_per_bkt = 1;
  26249                 }
  26250 
  26251                 if (SHR_BITGET(bkt_trace, bucket)) {
  26252                     continue;
  26253                 }
  26254                 SHR_BITSET(bkt_trace, bucket);
  26255             } else
  26256 #endif /* BCM_TOMAHAWK3_SUPPORT */
  26257             {
  26258                 num_rows_per_bkt  =  4/tbl_entries_per_sram_entry;
  26259 
  26260                 base_mem_bkt = bucket/tbl_entries_per_sram_entry;
  26261                 if (SHR_BITGET(bkt_trace, base_mem_bkt)) {
  26262                     continue;
  26263                 }
  26264                 SHR_BITSET(bkt_trace, base_mem_bkt);
  26265             }
  26266 
  26267 
  26268             if (tbl_entries_per_sram_entry == 4) {
  26269                 row_idx = bucket & 3;
  26270             } else if (tbl_entries_per_sram_entry == 2) {
  26271                 row_idx = (bucket & 1)*2;
  26272             } else {
  26273                 row_idx = 0;
  26274             }
  26275 
  26276             cb->bucket = bucket;
  26277 
  26278             /* Read all entries in a bucket */
  26279             memset(bkt_entry, 0, sizeof(bkt_entry));
  26280             for (wide_entry = 0; wide_entry < num_rows_per_bkt; wide_entry++) {
  26281 #if defined(BCM_TOMAHAWK3_SUPPORT)
  26282                 if (SOC_IS_TOMAHAWK3(unit)) {
  26283                     rv = soc_mem_read(unit, base_mem, copyno,
  26284                                       bucket + wide_entry,
  26285                                       bkt_entry[wide_entry]);
  26286                 } else
  26287 #endif /* BCM_TOMAHAWK3_SUPPORT */
  26288                 {
  26289                     rv = soc_mem_read(unit, base_mem, copyno,
  26290                                       (base_mem_bkt * 4) + row_idx + wide_entry,
  26291                                       bkt_entry[wide_entry]);
  26292                 }
  26293                 if (SOC_FAILURE(rv)) {
  26294                     goto cleanup;
  26295                 }
  26296 
  26297                 /* Read all base_valid information for the given entry */
  26298                 for (i = 0; i < max_entries_per_row; i++) {
  26299                     if (soc_mem_field_valid(unit, base_mem, vld_flds[i])) {
  26300                         soc_mem_field_get (unit, base_mem, bkt_entry[wide_entry],
  26301                                            vld_flds[i],
  26302                                            &v[(wide_entry*max_entries_per_row)+i]);
  26303                     } else if (soc_mem_field_valid(unit, base_mem, vld_flds[4])) {
  26304                         soc_mem_field_get (unit, base_mem, bkt_entry[wide_entry],
  26305                                            vld_flds[4],
  26306                                            &v[(wide_entry*max_entries_per_row)+i]);
  26307                     }
  26308                     
  26309                 }
  26310 
  26311                 /*
  26312                  * A valid entry starts with a start_of_key (sok).
  26313                  * To identify the type of entry, we need to identify the sok
  26314                  * and traverse to the next entries.
  26315                  *
  26316                  * In TD3, every single entry wide may not have Key_type information.
  26317                  * So only base valid fields should be used to identify if the entry
  26318                  * is single, double or quad wide.
  26319                  *
  26320                  * For Instance:
  26321                  *     Single Wide Entry : BASE_VALID_0 : 1
  26322                  *     Double Wide Entry : BASE_VALID_1 : 4, BASE_VALID_0 : 3
  26323                  *     Quad   Wide Entry : BASE_VALID_1 : 6, BASE_VALID_0 : 5
  26324                  *     Quad   Wide Entry : BASE_VALID_3 : 7, BASE_VALID_2 : 6
  26325                  *
  26326                  *     BASE Valid value of 1,3,5 represent start of key.
  26327                  *     Base Valid value of 4,6   represent key+data (extension).
  26328                  *     Base Valid value of 7     represent data only(extension).
  26329                  */
  26330                 sok=-1; /* start of key */
  26331                 for (i = 0; i < max_entries_per_row; i++) {
  26332                     if (!v[wide_entry*max_entries_per_row + i]) {
  26333                         w[wide_entry*max_entries_per_row + i]=0;
  26334                         sok = -1;
  26335                     } else if ((v[wide_entry*max_entries_per_row + i] != 7) &&
  26336                                (v[wide_entry*max_entries_per_row + i] & 1)) {
  26337                         w[wide_entry*max_entries_per_row + i]= 1;
  26338                         sok = wide_entry*max_entries_per_row + i;
  26339                     } else {
  26340                         if (sok == -1)
  26341                            w[wide_entry*max_entries_per_row + i] = 0;
  26342                         else {
  26343                            w[sok] += 1;
  26344                         }
  26345                     }
  26346                 }
  26347 
  26348                 /* Once width is identified, make valid array a bit representation */
  26349                 for (i = 0; i < max_entries_per_row; i++) {
  26350                     v[wide_entry*max_entries_per_row + i] =
  26351                                  v[wide_entry*max_entries_per_row + i] ? 1 : 0;
  26352                 }
  26353                 cb->td3_status[wide_entry] = 0;
  26354                 for (i = 0; i < max_entries_per_row; i++) {
  26355                     cb->td3_status[wide_entry] |=
  26356                              (v[(wide_entry*max_entries_per_row)+i] << i);
  26357                 }
  26358             }
  26359 
  26360             /*
  26361              * For UFT: a Quad entry bucket has 4 quad entries and it could have
  26362              *          upto 16 valid single entries in the quad bucket.
  26363              * For UAT: a Double entry bucket has 4 double entries and it could have
  26364              *          upto 8 valid single entries in the quad bucket.
  26365              *
  26366              * num_rows_per_bkt*max_entries_per_row gives possible number of
  26367              * valid single entries in the bucket. So traverse through all possible
  26368              * valid entries..,
  26369              */
  26370             for (ent = 0; ent < (num_rows_per_bkt*max_entries_per_row); ent++) {
  26371                 if (!w[ent]) {
  26372                     continue;
  26373                 }
  26374 
  26375                 me = _soc_mem_hash_entry_buffer_get(unit, cb->src_mem, cb, ent);
  26376 
  26377                 rv = SOC_E_UNAVAIL;
  26378 #ifdef BCM_TOMAHAWK3_SUPPORT
  26379                 if (SOC_IS_TOMAHAWK3(unit)) {
  26380                     rv = soc_tomahawk3_shared_hash_mem_bucket_read (unit,
  26381                           ent%max_entries_per_row, w[ent], &ent_incr, base_mem,
  26382                           &src_mem, bkt_entry[ent/max_entries_per_row], me);
  26383                 } else
  26384 #endif
  26385                 {
  26386 #ifdef BCM_TRIDENT3_SUPPORT
  26387                     rv = soc_td3_shared_hash_mem_bucket_read (unit,
  26388                           ent%max_entries_per_row, w[ent], &ent_incr, base_mem,
  26389                           &src_mem, bkt_entry[ent/max_entries_per_row], me);
  26390 #endif
  26391                 }
  26392                 if (SOC_FAILURE(rv)) {
  26393                     goto cleanup;
  26394                 }
  26395                 ent_incr = w[ent];
  26396 
  26397                 rv = soc_mem_generic_insert(unit, src_mem, copyno,
  26398                                             bi.banks & ~(1 << bank_num),
  26399                                             me, NULL, &move_bkt);
  26400                 moved = 0;
  26401                 free = 0;
  26402 
  26403                 if (SOC_SUCCESS(rv)) {
  26404 
  26405                     /* TD3 every bucket has 4 entries. Divide index by 4 to get bucket # */
  26406 #if defined(BCM_TOMAHAWK3_SUPPORT)
  26407                     if (SOC_IS_TOMAHAWK3(unit)) {
  26408                         move_bkt /= tbl_entries_per_sram_entry;
  26409                     } else
  26410 #endif /* BCM_TOMAHAWK3_SUPPORT */
  26411                     {
  26412                         move_bkt /= TD3_ENTRIES_PER_BUCKET;
  26413                     }
  26414 
  26415                     if (SHR_BITGET(bkt_trace, move_bkt)) {
  26416                         rv = soc_mem_generic_delete(unit, src_mem,
  26417                                                     MEM_BLOCK_ANY,
  26418                                                     bi.banks & ~(1 << bank_num),
  26419                                                     me, NULL, NULL);
  26420                         if (SOC_FAILURE(rv)) {
  26421                             goto cleanup;
  26422                         }
  26423                     } else {
  26424                         rv = soc_mem_generic_delete(unit, src_mem,
  26425                                                     MEM_BLOCK_ANY,
  26426                                                     1 << bank_num, me,
  26427                                                     NULL, NULL);
  26428                         if (SOC_FAILURE(rv)) {
  26429                             goto cleanup;
  26430                         }
  26431                         moved = 1;
  26432                         cb->td3_status[ent/max_entries_per_row] &=
  26433                                       ~(((1 << ent_incr) - 1) <<
  26434                                          (ent%max_entries_per_row));
  26435 
  26436                         _SOC_MEM_SHARED_HASH_STATUS_CHECK(free, cb->src_mem,
  26437                                     cb->td3_status[ent/max_entries_per_row]);
  26438                     }
  26439                 }
  26440 
  26441                 if (!free) {
  26442                     if (!moved) {
  26443                         /* Construct buckets in next level for this entry */
  26444                         nl_bkt_idx = bkt_idx * (bi.num_banks-1) * NUM_ENT_TD3 +
  26445                                          (ent) * (bi.num_banks-1);
  26446 
  26447                         for (bix = 0; bix < bi.num_banks && buckets[level + 1]; bix++) {
  26448                             cbix = cb->src_bix + bix + 1;
  26449                             cbix = cbix % bi.num_banks;
  26450                             if (bank_num == bi.bank_nums[cbix]) {
  26451                                 continue;
  26452                             }
  26453                             tb = &buckets[level + 1][nl_bkt_idx++];
  26454                             tb->src_bkt_idx = bkt_idx;
  26455                             tb->src_bix  = cbix;
  26456                             tb->src_mem  = src_mem;
  26457                             tb->src_width= ent_incr;
  26458                             tb->src_ent  = ent;
  26459                         }
  26460                     }
  26461                     continue;
  26462                 }
  26463 
  26464                 ibank_num = bank_num;
  26465                 pbi = cb;
  26466                 for (i = level; i > 0; i--) {
  26467                     cbi = pbi;
  26468                     pbi = &buckets[i - 1][cbi->src_bkt_idx];
  26469 
  26470                     me = _soc_mem_hash_entry_buffer_get(unit, cbi->src_mem,
  26471                                                         pbi, cbi->src_ent);
  26472 
  26473                     rv = soc_mem_bank_insert(unit, cbi->src_mem,
  26474                                              (1 << ibank_num), copyno,
  26475                                              me, NULL);
  26476                     if (SOC_FAILURE(rv)) {
  26477                         goto cleanup;
  26478                     }
  26479 
  26480                     ibank_num = bi.bank_nums[pbi->src_bix];
  26481 
  26482                     rv = soc_mem_generic_delete(unit, cbi->src_mem,
  26483                                                 MEM_BLOCK_ANY,
  26484                                                 (1 << ibank_num),
  26485                                                 me, NULL, NULL);
  26486                     if (SOC_FAILURE(rv)) {
  26487                         goto cleanup;
  26488                     }
  26489 
  26490                     pbi->td3_status[cbi->src_ent/max_entries_per_row] &=
  26491                                        ~(((1 << cbi->src_width) - 1) <<
  26492                                           (cbi->src_ent%max_entries_per_row));
  26493 
  26494                     _SOC_MEM_SHARED_HASH_STATUS_CHECK(free, pbi->src_mem,
  26495                             pbi->td3_status[cbi->src_ent/max_entries_per_row]);
  26496 
  26497                     if (!free) {
  26498                         break;
  26499                     }
  26500                 }
  26501 
  26502                 /* now i is the toppest level with free slot available */
  26503 
  26504                 if (free) {
  26505                     job_done = 1;
  26506                     goto done;
  26507                 } else {
  26508                     /* cbi --> level i; pbi --> level i - 1.
  26509                      * cbi is the toppest bucket with entry moved.
  26510                      * pbi is the bucket with entry removed.
  26511                      * Entire sub tree of pbi's removed entry needs be skipped.
  26512                      */
  26513                     for (j = i; j <= level; j++) {
  26514                         if (j == i) {
  26515                             num      = (bi.num_banks - 1);
  26516                             bkt_idx1 = (cbi->src_bkt_idx * ((bi.num_banks - 1) * NUM_ENT_TD3)) +
  26517                                        ((cbi->src_ent) * (bi.num_banks - 1));
  26518                             bkt_idx2 = bkt_idx1 + (cbi->src_width * (bi.num_banks - 1));
  26519                         } else {
  26520                             num      *= (bi.num_banks - 1) * NUM_ENT_TD3;
  26521                             bkt_idx1 *= (bi.num_banks - 1) * NUM_ENT_TD3;
  26522                             bkt_idx2 *= (bi.num_banks - 1) * NUM_ENT_TD3;
  26523                         }
  26524                     }
  26525 
  26526                     /* assert (bkt_idx2 > bkt_idx && bkt_idx >= bkt_idx1); */
  26527                     if (buckets[j]) {
  26528                         num      *= (bi.num_banks - 1) * NUM_ENT_TD3;
  26529                         bkt_idx1 *= (bi.num_banks - 1) * NUM_ENT_TD3;
  26530                         sal_memset(&buckets[j][bkt_idx1], 0,
  26531                                    num * sizeof(_soc_breadth_bucket_td3_t));
  26532                     }
  26533                     bkt_idx = bkt_idx2 - 1;
  26534                     break;
  26535                 }
  26536             }
  26537         }
  26538         num_cl_bkts *= (bi.num_banks - 1) * NUM_ENT_TD3;
  26539     }
  26540 
  26541 done:
  26542     if (job_done) {
  26543         rv = soc_mem_generic_insert(unit, mem, copyno, 1 << ibank_num,
  26544                                     entry, entry, NULL);
  26545     } else {
  26546         rv = SOC_E_FULL;
  26547     }
  26548 
  26549 cleanup:
  26550     if (bkt_trace) {
  26551         sal_free(bkt_trace);
  26552     }
  26553 
  26554     if (buckets[0]) {
  26555         cb = buckets[0];
  26556         for (i = 0; i < total_buckets; i++, cb++){
  26557             if (cb->src_mem) {
  26558                 for (ent = 0; ent < NUM_ENT_TD3; ent++){
  26559                     if (cb->e.l2[ent]) {
  26560                         sal_free(cb->e.l2[ent]);
  26561                         cb->e.l2[ent] = NULL;
  26562                     }
  26563                 }
  26564                 memset(cb, 0, sizeof(_soc_breadth_bucket_td3_t));
  26565             }
  26566         }
  26567     }
  26568 
  26569     TD3_HASH_UNLOCK(unit);
  26570     if (SOC_FAILURE(rv)) {
  26571         LOG_VERBOSE(BSL_LS_SOC_COMMON,
  26572                     (BSL_META_U(unit,
  26573                                 "Insert entry: %d\n"), rv));
  26574     }
  26575     return rv;
  26576 }
  26577 #endif /* defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) */
  26578 
  26579 #ifdef BCM_TOMAHAWK3_SUPPORT
  26580 int
  26581 soc_tomahawk3_hash_mutex_init (int unit)
  26582 {
  26583     return soc_td3_hash_mutex_init(unit);
  26584 }
  26585 
  26586 STATIC int
  26587 _soc_mem_shared_hash_tomahawk3_breadth_mix_move(int unit, soc_mem_t mem, int copyno,
  26588                                      void *entry, int num_levels)
  26589 {
  26590     return _soc_mem_shared_hash_td3_breadth_mix_move(unit, mem, copyno, entry, num_levels);
  26591 }
  26592 
  26593 #endif /* BCM_TOMAHAWK3_SUPPORT */
  26594 
  26595 STATIC int
  26596 _soc_mem_shared_hash_breadth_mix_move(int unit, soc_mem_t mem, int copyno,
  26597                                      void *entry, int num_levels)
  26598 {
  26599     SHR_BITDCL *bkt_trace = NULL;
  26600     _soc_breadth_bucket_t *buckets[MAX_MIX_LEVELS + 1] = {0};
  26601     _soc_breadth_bucket_t *cb, *tb, *cbi = NULL, *pbi;
  26602     uint32 bkt_entry[NUM_ENT][SOC_MAX_MEM_WORDS];
  26603     uint32 v[NUM_ENT], k[NUM_ENT];
  26604     void *se, *me;
  26605     int rv;
  26606     int level, job_done = 0;
  26607     int move_bkt;
  26608     int bank_num, ibank_num = 0;
  26609     int bix, cbix;
  26610     int free = 0, moved = 0;
  26611     int bkt_idx, bkt_idx1 = 0, bkt_idx2 = 0;
  26612     int nl_bkt_idx, num_cl_bkts;
  26613     int ent, ent_incr, bucket;
  26614     int num = 0;
  26615     int i, j;
  26616     int vld_fld_0 = VALID_0f;
  26617     int key_type_0 = KEY_TYPE_0f; 
  26618     _soc_hash_bank_info_t bi = {0};
  26619     soc_mem_t src_mem, base_mem;
  26620 #if defined(BCM_TOMAHAWK_SUPPORT)
  26621     int pipenum = -1;
  26622 #endif
  26623     if (num_levels <= 0) {
  26624         return SOC_E_FULL;
  26625     } else if (num_levels > MAX_MIX_LEVELS) {
  26626         return _soc_mem_shared_hash_breadth_mix_move2(unit, mem, copyno,
  26627                                                      entry, num_levels);
  26628     }
  26629 
  26630     base_mem = _soc_mem_hash_base_mem_get(unit, mem);
  26631 #if defined(BCM_TOMAHAWK_SUPPORT)
  26632     if (base_mem == EXACT_MATCH_4m) {
  26633         switch (mem) {
  26634         case EXACT_MATCH_4_PIPE0m:
  26635         case EXACT_MATCH_2_PIPE0m:
  26636             base_mem = EXACT_MATCH_4_PIPE0m;
  26637             pipenum = 0;
  26638             break;
  26639         case EXACT_MATCH_4_PIPE1m:
  26640         case EXACT_MATCH_2_PIPE1m:
  26641             base_mem = EXACT_MATCH_4_PIPE1m;
  26642             pipenum = 1;
  26643             break;
  26644         case EXACT_MATCH_4_PIPE2m:
  26645         case EXACT_MATCH_2_PIPE2m:
  26646             base_mem = EXACT_MATCH_4_PIPE2m;
  26647             pipenum = 2;
  26648             break;
  26649         case EXACT_MATCH_4_PIPE3m:
  26650         case EXACT_MATCH_2_PIPE3m:
  26651             base_mem = EXACT_MATCH_4_PIPE3m;
  26652             pipenum = 3;
  26653             break;
  26654         default:
  26655             break;
  26656         }
  26657     }
  26658 #endif
  26659 
  26660     SOC_IF_ERROR_RETURN(_soc_mem_shared_hash_init
  26661         (unit, base_mem, &bkt_trace, &bi, num_levels, &buckets[0], NULL));
  26662 
  26663     num_cl_bkts = bi.num_banks;
  26664 
  26665     for (level = 0; level < num_levels; level++) {
  26666         if (level + 1 < num_levels) {
  26667             buckets[level + 1] = buckets[level] + num_cl_bkts;
  26668         } else {
  26669             buckets[level + 1] = 0;
  26670         }
  26671 
  26672         for (bkt_idx = 0; bkt_idx < num_cl_bkts; bkt_idx++) {
  26673             cb = &buckets[level][bkt_idx];
  26674             if (level == 0) {
  26675                 cb->src_bix = bkt_idx;
  26676                 cb->src_mem  = mem;
  26677                 cb->src_width = _soc_mem_hash_mem_width_get(unit, mem);
  26678                 se = entry;
  26679             } else {
  26680                 if (cb->src_mem == 0) {
  26681                     continue;
  26682                 }
  26683 #ifdef BCM_TOMAHAWK_SUPPORT
  26684                 if (MEM_IS_EXACT_MATCH_4(mem)) {
  26685                     se = &buckets[level - 1][cb->src_bkt_idx].e.em_4[cb->src_ent];
  26686                 } else if (MEM_IS_EXACT_MATCH_2(mem)) {
  26687                     se = &buckets[level - 1][cb->src_bkt_idx].e.em_2[cb->src_ent];
  26688                 } else 
  26689 #endif
  26690                 {
  26691                 se = &buckets[level - 1][cb->src_bkt_idx].e.l3[cb->src_ent];
  26692             }
  26693             }
  26694 
  26695             bank_num = bi.bank_nums[cb->src_bix];
  26696             bucket = _soc_mem_shared_hash_bucket(unit, cb->src_mem, bank_num, se);          
  26697             if (SHR_BITGET(bkt_trace, bucket)) {
  26698                 continue;
  26699             }
  26700             SHR_BITSET(bkt_trace, bucket);
  26701             cb->bucket = bucket;
  26702             if (MEM_IS_EXACT_MATCH_4(mem)) {
  26703                 rv = soc_mem_read(unit, base_mem, copyno, 
  26704                                   bucket * SRAM_ENTRIES_PER_BUCKET_EM_4, bkt_entry[0]);
  26705                 if (SOC_FAILURE(rv)) {
  26706                     goto cleanup;
  26707                 }
  26708                 rv = soc_mem_read(unit, base_mem, copyno, 
  26709                                   bucket * SRAM_ENTRIES_PER_BUCKET_EM_4 + 1, 
  26710                                   bkt_entry[1]);
  26711                 if (SOC_FAILURE(rv)) {
  26712                     goto cleanup;
  26713                 }
  26714                 rv = soc_mem_read(unit, base_mem, copyno, 
  26715                                   bucket * SRAM_ENTRIES_PER_BUCKET_EM_4 + 2, 
  26716                                   bkt_entry[2]);
  26717                 if (SOC_FAILURE(rv)) {
  26718                     goto cleanup;
  26719                 }
  26720                 rv = soc_mem_read(unit, base_mem, copyno, 
  26721                                   bucket * SRAM_ENTRIES_PER_BUCKET_EM_4 + 3, 
  26722                                   bkt_entry[3]);
  26723                 if (SOC_FAILURE(rv)) {
  26724                     goto cleanup;
  26725                 }                
  26726                 soc_mem_field_get(unit, base_mem, bkt_entry[3], vld_fld_0, &v[3]);
  26727                 soc_mem_field_get(unit, base_mem, bkt_entry[2], vld_fld_0, &v[2]);
  26728                 soc_mem_field_get(unit, base_mem, bkt_entry[1], vld_fld_0, &v[1]);
  26729                 soc_mem_field_get(unit, base_mem, bkt_entry[0], vld_fld_0, &v[0]);
  26730                 soc_mem_field_get(unit, base_mem, bkt_entry[3], key_type_0, &k[3]);
  26731                 soc_mem_field_get(unit, base_mem, bkt_entry[2], key_type_0, &k[2]);
  26732                 soc_mem_field_get(unit, base_mem, bkt_entry[1], key_type_0, &k[1]);
  26733                 soc_mem_field_get(unit, base_mem, bkt_entry[0], key_type_0, &k[0]);
  26734 
  26735             } else if (MEM_IS_EXACT_MATCH_2(mem)){
  26736                 rv = soc_mem_read(unit, base_mem, copyno, 
  26737                                   bucket * SRAM_ENTRIES_PER_BUCKET_EM_2, bkt_entry[0]);
  26738                 if (SOC_FAILURE(rv)) {
  26739                     goto cleanup;
  26740                 }
  26741                 rv = soc_mem_read(unit, base_mem, copyno, 
  26742                                   bucket * SRAM_ENTRIES_PER_BUCKET_EM_2 + 1, 
  26743                                   bkt_entry[1]);
  26744                 if (SOC_FAILURE(rv)) {
  26745                     goto cleanup;
  26746                 }
  26747 
  26748                 soc_mem_field_get(unit, base_mem, bkt_entry[1], VALID_2f, &v[3]);
  26749                 soc_mem_field_get(unit, base_mem, bkt_entry[1], VALID_0f, &v[2]);
  26750                 soc_mem_field_get(unit, base_mem, bkt_entry[0], VALID_2f, &v[1]);
  26751                 soc_mem_field_get(unit, base_mem, bkt_entry[0], VALID_0f, &v[0]);
  26752                 soc_mem_field_get(unit, base_mem, bkt_entry[1], KEY_TYPE_2f, &k[3]);
  26753                 soc_mem_field_get(unit, base_mem, bkt_entry[1], KEY_TYPE_0f, &k[2]);
  26754                 soc_mem_field_get(unit, base_mem, bkt_entry[0], KEY_TYPE_2f, &k[1]);
  26755                 soc_mem_field_get(unit, base_mem, bkt_entry[0], KEY_TYPE_0f, &k[0]);
  26756 
  26757             } else {
  26758                 rv = soc_mem_read(unit, base_mem, copyno, bucket, bkt_entry[0]);
  26759                 if (SOC_FAILURE(rv)) {
  26760                     goto cleanup;
  26761                 }
  26762                 soc_mem_field_get(unit, base_mem, bkt_entry[0], VALID_3f, &v[3]);
  26763                 soc_mem_field_get(unit, base_mem, bkt_entry[0], VALID_2f, &v[2]);
  26764                 soc_mem_field_get(unit, base_mem, bkt_entry[0], VALID_1f, &v[1]);
  26765                 soc_mem_field_get(unit, base_mem, bkt_entry[0], VALID_0f, &v[0]);
  26766                 soc_mem_field_get(unit, base_mem, bkt_entry[0], KEY_TYPE_3f, &k[3]);
  26767                 soc_mem_field_get(unit, base_mem, bkt_entry[0], KEY_TYPE_2f, &k[2]);
  26768                 soc_mem_field_get(unit, base_mem, bkt_entry[0], KEY_TYPE_1f, &k[1]);
  26769                 soc_mem_field_get(unit, base_mem, bkt_entry[0], KEY_TYPE_0f, &k[0]);
  26770 
  26771             }
  26772 
  26773             cb->status = (v[3] << 3) | (v[2] << 2) | (v[1] << 1) | (v[0] << 0);
  26774 
  26775             for (ent = 0; ent < NUM_ENT; ent += ent_incr) {
  26776                 if (!v[ent]) {
  26777                     ent_incr = 1;
  26778                     continue;
  26779                 }
  26780 #ifdef BCM_TOMAHAWK_SUPPORT                
  26781                 if (MEM_IS_EXACT_MATCH_4(mem)) {
  26782                     me = &cb->e.em_4[ent];
  26783                 } else if (MEM_IS_EXACT_MATCH_2(mem)) {
  26784                     me = &cb->e.em_2[ent];
  26785                 } else 
  26786 #endif                
  26787                 {
  26788                 me = &cb->e.l3[ent];
  26789                 }
  26790 
  26791 #if defined(BCM_TOMAHAWK_SUPPORT)
  26792                 if (MEM_IS_EXACT_MATCH_4(mem)) {
  26793                     me = &cb->e.em_4[ent];
  26794                     _soc_mem_shared_hash_exact_match_bucket_read(unit, ent, k[ent],
  26795                                                                  &ent_incr, &src_mem,
  26796                                                                  bkt_entry[ent],
  26797                                                                  me, pipenum);
  26798                 } else if (MEM_IS_EXACT_MATCH_2(mem)) {
  26799                     me = &cb->e.em_2[ent];
  26800                     _soc_mem_shared_hash_exact_match_bucket_read(unit, ent, k[ent],
  26801                                                                  &ent_incr, &src_mem,
  26802                                                                  bkt_entry[ent / SRAM_ENTRIES_PER_BUCKET_EM_2],
  26803                                                                  me, pipenum);
  26804                 } else
  26805 #endif
  26806                 {
  26807                     _soc_mem_shared_hash_l3_bucket_read(unit, ent, k[ent],
  26808                             &ent_incr, &src_mem, bkt_entry[0], me);
  26809                 }
  26810 
  26811                 rv = soc_mem_generic_insert(unit, src_mem, copyno,
  26812                                             bi.banks & ~(1 << bank_num),
  26813                                             me, NULL, &move_bkt);
  26814                 moved = 0;
  26815                 free = 0;
  26816                 if (SOC_SUCCESS(rv)) {
  26817 
  26818                     move_bkt /= _soc_mem_shared_hash_entries_per_bkt(unit, src_mem);
  26819                     if (SHR_BITGET(bkt_trace, move_bkt)) {
  26820                         rv = soc_mem_generic_delete(unit, src_mem, MEM_BLOCK_ANY,
  26821                                                     bi.banks & ~(1 << bank_num),
  26822                                                     me, NULL, NULL);
  26823 
  26824                         if (SOC_FAILURE(rv)) {
  26825                             goto cleanup;
  26826                         }
  26827                     } else {
  26828                         rv = soc_mem_generic_delete(unit, src_mem, MEM_BLOCK_ANY,
  26829                                                     1 << bank_num, me, NULL, NULL);
  26830                         if (SOC_FAILURE(rv)) {
  26831                             goto cleanup;
  26832                         }
  26833                         moved = 1;
  26834                         cb->status &= ~(((1 << ent_incr) - 1) << ent);
  26835 
  26836                         _SOC_MEM_SHARED_HASH_STATUS_CHECK(free, cb->src_mem, cb->status);
  26837 
  26838                     }
  26839                 }
  26840 
  26841                 if (!free) {
  26842                     if (!moved) {
  26843                         /* Construct buckets in next level for this entry */
  26844                         nl_bkt_idx = bkt_idx * (bi.num_banks - 1) * NUM_ENT +
  26845                                          ent * (bi.num_banks - 1);
  26846 
  26847                         for (bix = 0; bix < bi.num_banks && buckets[level + 1]; bix++) {
  26848                             cbix = cb->src_bix + bix + 1;
  26849                             cbix = cbix % bi.num_banks;
  26850                             if (bank_num == bi.bank_nums[cbix]) {
  26851                                 continue;
  26852                             }
  26853 
  26854                             tb = &buckets[level + 1][nl_bkt_idx++];
  26855                             tb->src_bkt_idx = bkt_idx;
  26856                             tb->src_bix  = cbix;
  26857                             tb->src_mem  = src_mem;
  26858                             tb->src_width= ent_incr;
  26859                             tb->src_ent  = ent;
  26860                         }
  26861                     }
  26862                     continue;
  26863                 }
  26864 
  26865                 ibank_num = bank_num;
  26866                 pbi = cb;
  26867                 for (i = level; i > 0; i--) {
  26868                     cbi = pbi;
  26869                     pbi = &buckets[i - 1][cbi->src_bkt_idx];
  26870 #ifdef BCM_TOMAHAWK_SUPPORT                    
  26871                     if (MEM_IS_EXACT_MATCH_4(mem)) {
  26872                         me = &pbi->e.em_4[cbi->src_ent];
  26873                     } else if (MEM_IS_EXACT_MATCH_2(mem)) {
  26874                         me = &pbi->e.em_2[cbi->src_ent];
  26875                     } else 
  26876 #endif                    
  26877                     {
  26878                     me = &pbi->e.l3[cbi->src_ent];
  26879                     }
  26880 
  26881                     rv = soc_mem_bank_insert(unit, cbi->src_mem,
  26882                                              (1 << ibank_num), copyno,
  26883                                              me, NULL);
  26884                     if (SOC_FAILURE(rv)) {
  26885                         goto cleanup;
  26886                     }
  26887 
  26888                     ibank_num = bi.bank_nums[pbi->src_bix];
  26889 
  26890                     rv = soc_mem_generic_delete(unit, cbi->src_mem,
  26891                                                 MEM_BLOCK_ANY,
  26892                                                 (1 << ibank_num),
  26893                                                 me, NULL, NULL);
  26894                     if (SOC_FAILURE(rv)) {
  26895                         goto cleanup;
  26896                     }
  26897 
  26898                     pbi->status &= ~(((1 << cbi->src_width) - 1) << cbi->src_ent);
  26899 
  26900                     _SOC_MEM_SHARED_HASH_STATUS_CHECK(free, pbi->src_mem, pbi->status);
  26901 
  26902                     if (!free) {
  26903                         break;
  26904                     }
  26905                 }
  26906 
  26907                 /* now i is the toppest level with free slot available */
  26908 
  26909                 if (free) {
  26910                     job_done = 1;
  26911                     goto done;
  26912                 } else {
  26913                     /* cbi --> level i; pbi --> level i - 1.
  26914                      * cbi is the toppest bucket with entry moved.
  26915                      * pbi is the bucket with entry removed.
  26916                      * Entire sub tree of pbi's removed entry needs be skipped.
  26917                      */
  26918                     for (j = i; j <= level; j++) {
  26919                         if (j == i) {
  26920                             num      = (bi.num_banks - 1);
  26921                             bkt_idx1 = (cbi->src_bkt_idx * ((bi.num_banks - 1) * NUM_ENT)) +
  26922                                        (cbi->src_ent * (bi.num_banks - 1));
  26923                             bkt_idx2 = bkt_idx1 + (cbi->src_width * (bi.num_banks - 1));
  26924                         } else {
  26925                             num      *= (bi.num_banks - 1) * NUM_ENT;
  26926                             bkt_idx1 *= (bi.num_banks - 1) * NUM_ENT;
  26927                             bkt_idx2 *= (bi.num_banks - 1) * NUM_ENT;
  26928                         }
  26929                     }
  26930 
  26931                     /* assert (bkt_idx2 > bkt_idx && bkt_idx >= bkt_idx1); */
  26932                     if (buckets[j]) {
  26933                         num      *= (bi.num_banks - 1) * NUM_ENT;
  26934                         bkt_idx1 *= (bi.num_banks - 1) * NUM_ENT;
  26935                         sal_memset(&buckets[j][bkt_idx1], 0,
  26936                                    num * sizeof(_soc_breadth_bucket_t));
  26937                     }
  26938                     bkt_idx = bkt_idx2 - 1;
  26939                     break;
  26940                 }
  26941             }
  26942         }
  26943         num_cl_bkts *= (bi.num_banks - 1) * NUM_ENT;
  26944     }
  26945 
  26946 done:
  26947     if (job_done) {
  26948         rv = soc_mem_generic_insert(unit, mem, copyno, 1 << ibank_num,
  26949                                     entry, entry, NULL);
  26950     } else {
  26951         rv = SOC_E_FULL;
  26952     }
  26953 
  26954 cleanup:
  26955     if (bkt_trace) {
  26956         sal_free(bkt_trace);
  26957     }
  26958 
  26959     if (buckets[0]) {
  26960         sal_free(buckets[0]);
  26961     }
  26962 
  26963     if (SOC_FAILURE(rv)) {
  26964         LOG_VERBOSE(BSL_LS_SOC_COMMON,
  26965                     (BSL_META_U(unit,
  26966                                 "Insert entry: %d\n"), rv));
  26967     }
  26968 
  26969     return rv;
  26970 }
  26971 
  26972 
  26973 STATIC int
  26974 _soc_mem_shared_hash_depth_move(int unit, soc_mem_t mem,
  26975                                 int32 bank_num_start, int copyno,
  26976                                 void *entry, int recurse_depth,
  26977                                 _soc_hash_bank_info_t *bi_ptr,
  26978                                 SHR_BITDCL *trace)
  26979 {
  26980     _soc_hash_bank_info_t bi;
  26981     SHR_BITDCL *bkt_trace = NULL;
  26982     SHR_BITDCL *bkt_trace2 = NULL;
  26983     soc_mem_t l3_mem = L3_ENTRY_IPV6_MULTICASTm;
  26984     soc_mem_t em_mem = EXACT_MATCH_4m;
  26985     soc_mem_t orig_mem = 0;
  26986     uint32 orig_entry[NUM_ENT][SOC_MAX_MEM_WORDS];
  26987     uint32 bkt_entry[NUM_ENT][SOC_MAX_MEM_WORDS];
  26988     uint32 v[NUM_ENT] = {0, 0, 0, 0};
  26989     uint32 k[NUM_ENT] = {0, 0, 0, 0};
  26990     int bank_num = 0;
  26991     int cbix, bix;
  26992     int rv = SOC_E_NONE;
  26993     int vld_fld_0 = VALID_0f, vld_fld_2=VALID_2f;
  26994     int key_type_0 = KEY_TYPE_0f, key_type_2=KEY_TYPE_2f;
  26995     int ent, ent_incr, bucket, retry;
  26996     int found = 0, status = 0, moved, move_bkt;
  26997     int buckets[7] = {0}, mark = 0;
  26998 
  26999 #if defined(BCM_TOMAHAWK_SUPPORT)
  27000     int pipenum = -1;
  27001     if (MEM_IS_EXACT_MATCH_2(mem) || MEM_IS_EXACT_MATCH_4(mem)) {
  27002         switch (mem) {
  27003         case EXACT_MATCH_4_PIPE0m:
  27004         case EXACT_MATCH_2_PIPE0m:
  27005             pipenum = 0;
  27006             break;
  27007         case EXACT_MATCH_4_PIPE1m:
  27008         case EXACT_MATCH_2_PIPE1m:
  27009             pipenum = 1;
  27010             break;
  27011         case EXACT_MATCH_4_PIPE2m:
  27012         case EXACT_MATCH_2_PIPE2m:
  27013             pipenum = 2;
  27014             break;
  27015         case EXACT_MATCH_4_PIPE3m:
  27016         case EXACT_MATCH_2_PIPE3m:
  27017             pipenum = 3;
  27018             break;
  27019         default:
  27020             break;
  27021         }
  27022     }  
  27023 #endif
  27024 
  27025 #ifdef BCM_TRIDENT3_SUPPORT
  27026     if (SOC_IS_TRIDENT3X(unit)) {
  27027         vld_fld_0 = BASE_VALID_0f;
  27028         vld_fld_2 = BASE_VALID_2f;
  27029         key_type_0 = KEY_TYPEf;
  27030         key_type_2 = KEY_TYPEf;
  27031     }
  27032 #endif
  27033     sal_memset(&bi, 0, sizeof(bi));
  27034     if (bank_num_start == SOC_MEM_HASH_BANK_ALL) {
  27035         if (recurse_depth < 0) {
  27036             return SOC_E_FULL;
  27037         }
  27038         SOC_IF_ERROR_RETURN(
  27039             _soc_mem_shared_hash_init(unit, mem, &bkt_trace,
  27040                                       &bi, 0, NULL, NULL));
  27041     } else {
  27042         if (trace) {
  27043             bkt_trace = trace;
  27044         } else {
  27045             return SOC_E_INTERNAL;
  27046         }
  27047 
  27048         if (bi_ptr) {
  27049             sal_memcpy(&bi, bi_ptr, sizeof(_soc_hash_bank_info_t));
  27050         } else {
  27051             sal_free(bkt_trace);
  27052             return SOC_E_INTERNAL;
  27053         }
  27054     }
  27055 
  27056     bkt_trace2 = bkt_trace;
  27057 
  27058     if (SOC_MULTI_HASH_MOVE_ALGORITHM(unit) == MULTI_MOVE_MODE_DEPTH_FAST) {
  27059         bkt_trace2 = bkt_trace + _SHR_BITDCLSIZE(bi.numb);
  27060     }
  27061 
  27062     for (bix = 0; bix < bi.num_banks; bix++) {
  27063         cbix = bix % bi.num_banks;
  27064         bank_num = bi.bank_nums[cbix];
  27065         if (bank_num_start == bank_num) {
  27066             continue;
  27067         }
  27068 
  27069         bucket = _soc_mem_shared_hash_bucket(unit, mem, bank_num, entry);
  27070 
  27071         if (SHR_BITGET(bkt_trace, bucket)) {
  27072             continue;
  27073         }
  27074         SHR_BITSET(bkt_trace, bucket);
  27075         SHR_BITSET(bkt_trace2, bucket);
  27076         buckets[mark++] = bucket;
  27077 
  27078         if (mem != L2Xm) {
  27079             if (mem == L3_ENTRY_ONLYm || 
  27080                 mem == L3_ENTRY_IPV4_UNICASTm || 
  27081                 mem == L3_ENTRY_IPV4_MULTICASTm || 
  27082                 mem == L3_ENTRY_IPV6_UNICASTm ||
  27083                 mem == L3_ENTRY_IPV6_MULTICASTm) {
  27084                 rv = soc_mem_read(unit, l3_mem, copyno, bucket, bkt_entry[0]);
  27085             if (SOC_FAILURE(rv)) {
  27086                 goto cleanup;
  27087             }
  27088 #ifdef BCM_TRIDENT3_SUPPORT
  27089                 if (SOC_IS_TRIDENT3(unit)) {
  27090                     soc_td3_hash_mem_status_get(unit, mem, bkt_entry[0], v);
  27091                     soc_mem_field_get(unit, l3_mem, bkt_entry[0], KEY_TYPEf, &k[0]);
  27092                     k[3] = k[2] = k[1] = k[0];
  27093                 } else
  27094 #endif /* BCM_TRIDENT3_SUPPORT */
  27095 #ifdef BCM_HELIX5_SUPPORT
  27096                 if (SOC_IS_HELIX5(unit)) {
  27097                     soc_hx5_hash_mem_status_get(unit, mem, bkt_entry[0], v);
  27098                     soc_mem_field_get(unit, l3_mem, bkt_entry[0], KEY_TYPEf, &k[0]);
  27099                     k[3] = k[2] = k[1] = k[0];
  27100                 } else
  27101 #endif /* BCM_HELIX5_SUPPORT */
  27102 #ifdef BCM_TOMAHAWK3_SUPPORT
  27103                 if (SOC_IS_TOMAHAWK3(unit)) {
  27104                     soc_tomahawk3_hash_mem_status_get(unit, mem, bkt_entry[0], v);
  27105                     soc_mem_field_get(unit, l3_mem, bkt_entry[0], KEY_TYPEf, &k[0]);
  27106                     k[3] = k[2] = k[1] = k[0];
  27107                 } else
  27108 #endif /* BCM_TOMAHAWK3_SUPPORT */
  27109                 {
  27110                     v[3] = soc_mem_field32_get(unit, l3_mem, bkt_entry[0], VALID_3f);
  27111                     v[2] = soc_mem_field32_get(unit, l3_mem, bkt_entry[0], VALID_2f);
  27112                     v[1] = soc_mem_field32_get(unit, l3_mem, bkt_entry[0], VALID_1f);
  27113                     v[0] = soc_mem_field32_get(unit, l3_mem, bkt_entry[0], VALID_0f);
  27114                     k[3] = soc_mem_field32_get(unit, l3_mem, bkt_entry[0], KEY_TYPE_3f);
  27115                     k[2] = soc_mem_field32_get(unit, l3_mem, bkt_entry[0], KEY_TYPE_2f);
  27116                     k[1] = soc_mem_field32_get(unit, l3_mem, bkt_entry[0], KEY_TYPE_1f);
  27117                     k[0] = soc_mem_field32_get(unit, l3_mem, bkt_entry[0], KEY_TYPE_0f);
  27118                 }
  27119             } else if ((MEM_IS_EXACT_MATCH_4(mem)) ||
  27120                        (SOC_IS_TRIDENT3X(unit) && (MEM_IS_EXACT_MATCH_2(mem)))) {
  27121                 rv = soc_mem_read(unit, em_mem, copyno, 
  27122                                   bucket * SRAM_ENTRIES_PER_BUCKET_EM_4, bkt_entry[0]);
  27123                 if (SOC_FAILURE(rv)) {
  27124                     goto cleanup;
  27125                 }
  27126                 rv = soc_mem_read(unit, em_mem, copyno, 
  27127                                   bucket * SRAM_ENTRIES_PER_BUCKET_EM_4 + 1, 
  27128                                   bkt_entry[1]);
  27129                 if (SOC_FAILURE(rv)) {
  27130                     goto cleanup;
  27131                 }
  27132                 rv = soc_mem_read(unit, em_mem, copyno, 
  27133                                   bucket * SRAM_ENTRIES_PER_BUCKET_EM_4 + 2, 
  27134                                   bkt_entry[2]);
  27135                 if (SOC_FAILURE(rv)) {
  27136                     goto cleanup;
  27137                 }
  27138                 rv = soc_mem_read(unit, em_mem, copyno, 
  27139                                   bucket * SRAM_ENTRIES_PER_BUCKET_EM_4 + 3, 
  27140                                   bkt_entry[3]);
  27141                 if (SOC_FAILURE(rv)) {
  27142                     goto cleanup;
  27143                 }                
  27144                 v[3] = soc_mem_field32_get(unit, em_mem, &bkt_entry[3], vld_fld_0);
  27145                 v[2] = soc_mem_field32_get(unit, em_mem, &bkt_entry[2], vld_fld_0);
  27146                 v[1] = soc_mem_field32_get(unit, em_mem, &bkt_entry[1], vld_fld_0);
  27147                 v[0] = soc_mem_field32_get(unit, em_mem, &bkt_entry[0], vld_fld_0);
  27148                 k[3] = soc_mem_field32_get(unit, em_mem, &bkt_entry[3], key_type_0);
  27149                 k[2] = soc_mem_field32_get(unit, em_mem, &bkt_entry[2], key_type_0);
  27150                 k[1] = soc_mem_field32_get(unit, em_mem, &bkt_entry[1], key_type_0);
  27151                 k[0] = soc_mem_field32_get(unit, em_mem, &bkt_entry[0], key_type_0);
  27152             } else if ((MEM_IS_EXACT_MATCH_2(mem))){
  27153                 rv = soc_mem_read(unit, em_mem, copyno, 
  27154                                   bucket * SRAM_ENTRIES_PER_BUCKET_EM_2, bkt_entry[0]);
  27155                 if (SOC_FAILURE(rv)) {
  27156                     goto cleanup;
  27157                 }
  27158                 rv = soc_mem_read(unit, em_mem, copyno, 
  27159                                   bucket * SRAM_ENTRIES_PER_BUCKET_EM_2 + 1, 
  27160                                   bkt_entry[1]);
  27161                 if (SOC_FAILURE(rv)) {
  27162                     goto cleanup;
  27163                 }
  27164                 v[3] = soc_mem_field32_get(unit, em_mem, &bkt_entry[1], vld_fld_2);
  27165                 v[2] = soc_mem_field32_get(unit, em_mem, &bkt_entry[1], vld_fld_0);
  27166                 v[1] = soc_mem_field32_get(unit, em_mem, &bkt_entry[0], vld_fld_2);
  27167                 v[0] = soc_mem_field32_get(unit, em_mem, &bkt_entry[0], vld_fld_0);
  27168                 k[3] = soc_mem_field32_get(unit, em_mem, &bkt_entry[1], key_type_2);
  27169                 k[2] = soc_mem_field32_get(unit, em_mem, &bkt_entry[1], key_type_0);
  27170                 k[1] = soc_mem_field32_get(unit, em_mem, &bkt_entry[0], key_type_2);
  27171                 k[0] = soc_mem_field32_get(unit, em_mem, &bkt_entry[0], key_type_0);
  27172             }
  27173             status = (v[3]? 1 << 3 : 0) | (v[2]? 1 << 2 : 0) | 
  27174                      (v[1]? 1 << 1 : 0) | (v[0]? 1 : 0);
  27175         }
  27176 
  27177         ent_incr = 1;
  27178         retry = 0;
  27179         for (ent = 0; ent < NUM_ENT; ent += ent_incr) {
  27180             if (retry) {
  27181                 retry = 0;
  27182             } else {
  27183                 if (mem == L2Xm) {
  27184                     rv = soc_mem_read(unit, mem, copyno,
  27185                                       (bucket << 2) + ent, &orig_entry[ent]);
  27186                     if (SOC_FAILURE(rv)) {
  27187                         goto cleanup;
  27188                     }
  27189                     orig_mem = mem;
  27190                     ent_incr = 1;
  27191                 } else if (mem == L3_ENTRY_ONLYm || 
  27192                            mem == L3_ENTRY_IPV4_UNICASTm || 
  27193                            mem == L3_ENTRY_IPV4_MULTICASTm || 
  27194                            mem == L3_ENTRY_IPV6_UNICASTm ||
  27195                            mem == L3_ENTRY_IPV6_MULTICASTm) {
  27196                     if (!v[ent]) {
  27197                         ent_incr = 1;
  27198                         continue;
  27199                     }
  27200 #ifdef BCM_HELIX5_SUPPORT
  27201                     if (SOC_IS_HELIX5(unit)) {
  27202                         rv = soc_hx5_shared_hash_mem_bucket_read
  27203                                         (unit, ent, k[ent], &ent_incr, l3_mem,
  27204                                          &orig_mem, bkt_entry[0], &orig_entry[ent]);
  27205 						if (SOC_FAILURE(rv)) {
  27206 							goto cleanup;
  27207 						}
  27208                     } else
  27209 #endif /* BCM_HELIX5_SUPPORT */
  27210 #ifdef BCM_TRIDENT3_SUPPORT
  27211                     if (SOC_IS_TRIDENT3X(unit)) {
  27212                         rv = soc_td3_shared_hash_mem_bucket_read
  27213                                 (unit, ent, k[ent], &ent_incr, l3_mem,
  27214                                  &orig_mem, bkt_entry[0], &orig_entry[ent]);
  27215                         if (SOC_FAILURE(rv)) {
  27216                             goto cleanup;
  27217                         }
  27218                     } else 
  27219 #endif /* BCM_TRIDENT3_SUPPORT */
  27220 #ifdef BCM_TOMAHAWK3_SUPPORT
  27221                     if (SOC_IS_TOMAHAWK3(unit)) {
  27222                         rv = soc_tomahawk3_shared_hash_mem_bucket_read
  27223                                 (unit, ent, k[ent], &ent_incr, l3_mem,
  27224                                  &orig_mem, bkt_entry[0], &orig_entry[ent]);
  27225                         if (SOC_FAILURE(rv)) {
  27226                             goto cleanup;
  27227                         }
  27228                     } else
  27229 #endif /* BCM_TOMAHAWK3_SUPPORT */
  27230                     {
  27231                     _soc_mem_shared_hash_l3_bucket_read(unit, ent, k[ent],
  27232                                 &ent_incr, &orig_mem, bkt_entry[0],
  27233                                 &orig_entry[ent]);
  27234                     }
  27235                 } else {
  27236 #if defined(BCM_TOMAHAWK_SUPPORT) 
  27237                     if (!v[ent]) {
  27238                         ent_incr = 1;
  27239                         continue;
  27240                     }
  27241 #ifdef BCM_HELIX5_SUPPORT
  27242                         if (SOC_IS_HELIX5(unit)) {
  27243                             if (MEM_IS_EXACT_MATCH_2(mem) ||
  27244                                     MEM_IS_EXACT_MATCH_4(mem)) {
  27245                                 rv = soc_hx5_shared_hash_mem_bucket_read
  27246                                     (unit, ent, k[ent], &ent_incr, em_mem,
  27247                                      &orig_mem, bkt_entry[0], &orig_entry[ent]);
  27248                                 if (SOC_FAILURE(rv)) {
  27249                                     goto cleanup;
  27250                                 }
  27251                             }
  27252                         } else
  27253 #endif /* BCM_HELIX5_SUPPORT */
  27254 #ifdef BCM_TRIDENT3_SUPPORT
  27255                     if (SOC_IS_TRIDENT3X(unit)) {
  27256                         if (MEM_IS_EXACT_MATCH_2(mem) ||
  27257                             MEM_IS_EXACT_MATCH_4(mem)) {
  27258                             rv = soc_td3_shared_hash_mem_bucket_read
  27259                                         (unit, ent, k[ent], &ent_incr, em_mem,
  27260                                          &orig_mem, bkt_entry[ent], &orig_entry[ent]);
  27261                             if (SOC_FAILURE(rv)) {
  27262                                 goto cleanup;
  27263                             }
  27264                         }
  27265                     } else
  27266 #endif /* BCM_TRIDENT3_SUPPORT */
  27267 #ifdef BCM_TOMAHAWK3_SUPPORT
  27268                     if (SOC_IS_TOMAHAWK3(unit)) {
  27269                         if (MEM_IS_EXACT_MATCH_2(mem) ||
  27270                             MEM_IS_EXACT_MATCH_4(mem)) {
  27271                             rv = soc_tomahawk3_shared_hash_mem_bucket_read
  27272                                         (unit, ent, k[ent], &ent_incr, em_mem,
  27273                                          &orig_mem, bkt_entry[ent], &orig_entry[ent]);
  27274                             if (SOC_FAILURE(rv)) {
  27275                                 goto cleanup;
  27276                             }
  27277                         }
  27278                     } else
  27279 #endif /* BCM_TOMAHAWK3_SUPPORT */
  27280                     if (MEM_IS_EXACT_MATCH_2(mem)) {
  27281                     _soc_mem_shared_hash_exact_match_bucket_read(unit, ent, k[ent],
  27282                               &ent_incr, &orig_mem, bkt_entry[ent / SRAM_ENTRIES_PER_BUCKET_EM_2], 
  27283                           &orig_entry[ent], pipenum);
  27284                     } else if (MEM_IS_EXACT_MATCH_4(mem)) {
  27285                         _soc_mem_shared_hash_exact_match_bucket_read(unit, ent, k[ent],
  27286                               &ent_incr, &orig_mem, bkt_entry[ent], 
  27287                               &orig_entry[ent], pipenum);
  27288                     }
  27289 #endif /* BCM_TOMAHAWK_SUPPORT */                   
  27290                 }
  27291             }
  27292 
  27293             rv = soc_mem_generic_insert(unit, orig_mem, copyno,
  27294                                         bi.banks & ~(1 << bank_num),
  27295                                         orig_entry[ent], NULL, &move_bkt);
  27296 
  27297             moved = 0;
  27298             if (SOC_SUCCESS(rv)) {
  27299                 move_bkt /= _soc_mem_shared_hash_entries_per_bkt(unit, orig_mem);
  27300                 if (SHR_BITGET(bkt_trace2, move_bkt)) {
  27301                     rv = soc_mem_generic_delete(unit, orig_mem, MEM_BLOCK_ANY,
  27302                                                 bi.banks & ~(1 << bank_num),
  27303                                                 orig_entry[ent], NULL, NULL);
  27304                     if (SOC_FAILURE(rv)) {
  27305                         goto cleanup;
  27306                     }
  27307                 } else {
  27308                     rv = soc_mem_generic_delete(unit, orig_mem, MEM_BLOCK_ANY,
  27309                                                 (uint32)1<<bank_num,
  27310                                                 orig_entry[ent], NULL, NULL);
  27311                     if (SOC_FAILURE(rv)) {
  27312                         goto cleanup;
  27313                     }
  27314                     moved = 1;
  27315 
  27316                     if (mem == L2Xm) {
  27317                         found = 1;
  27318                         break;
  27319                     } else {
  27320                         status &= ~(((1 << ent_incr) - 1) << ent);
  27321                         _SOC_MEM_SHARED_HASH_STATUS_CHECK(found, mem, status);
  27322                     }
  27323                 }
  27324             }
  27325 
  27326             if (found) {
  27327                 break;
  27328             } else if (!moved && recurse_depth) {
  27329 
  27330                 rv = _soc_mem_shared_hash_depth_move(unit, orig_mem,
  27331                                                      bank_num, copyno,
  27332                                                      orig_entry[ent],
  27333                                                      recurse_depth - 1,
  27334                                                      &bi, bkt_trace);
  27335                 if (SOC_SUCCESS(rv)) {
  27336                     /* Deeper entry is moved, try again */
  27337                     retry = 1;
  27338                     ent -= ent_incr;
  27339                 } else if (rv != SOC_E_FULL) {
  27340                     goto cleanup;
  27341                 }
  27342             }
  27343         }
  27344         if (found) {
  27345             break;
  27346         }
  27347     }
  27348 
  27349     if (!found) {
  27350         rv = SOC_E_FULL;
  27351     }
  27352 
  27353     if (bank_num_start == SOC_MEM_HASH_BANK_ALL) {
  27354         if (found) {
  27355             rv = soc_mem_generic_insert(unit, mem, copyno, (uint32)1<<bank_num,
  27356                                         entry, entry, NULL);
  27357         }
  27358         if (rv) {
  27359             LOG_VERBOSE(BSL_LS_SOC_COMMON,
  27360                         (BSL_META_U(unit,
  27361                                     "Insert entry: %d\n"), rv));
  27362         }
  27363     }
  27364 
  27365 cleanup:
  27366     for (ent_incr = 0; ent_incr < mark; ent_incr++) {
  27367         SHR_BITCLR(bkt_trace2, buckets[ent_incr]);
  27368     }
  27369     if (bank_num_start == SOC_MEM_HASH_BANK_ALL) {
  27370         sal_free(bkt_trace);
  27371     }
  27372     return rv;
  27373 }
  27374 
  27375 
  27376 /*
  27377  * Function:
  27378  *    _soc_mem_shared_hash_init
  27379  * Purpose:
  27380  *    Stack variables initialization & memory allocations for recursion algorithm
  27381  * Param:
  27382  *    mem  -  memory for new insert
  27383  *    *num_ent   -  how may entries in each bucket
  27384  *    **trace    -  bucket bitmap used to trace which buckets have been moved during recursion
  27385  *    bank_info  -  bank properties
  27386  *          num_bkt   -  how may buckets we need trace in recursion
  27387  *          num_banks -  how may banks for this type of entry
  27388  *          bank_ids  -  mapping for logical bank id to physical bank id for insert mem
  27389  *          bank_bmp  -  physical bank id bitmap for this kind of mem table
  27390  * Notes:
  27391  *    None.
  27392  */
  27393 
  27394 STATIC INLINE int
  27395 _soc_mem_shared_hash_init(int unit, soc_mem_t mem,
  27396                           SHR_BITDCL **trace,
  27397                           _soc_hash_bank_info_t *bank_info,
  27398                           int num_levels,
  27399                           _soc_breadth_bucket_t **buckets,
  27400                           _soc_breadth_bucket2_t **buckets2)
  27401 {
  27402     uint8 bix;
  27403     int alloc_size;
  27404     SHR_BITDCL *bkt_trace = NULL;
  27405 
  27406     if (NULL == bank_info) {
  27407         return SOC_E_PARAM;
  27408     }
  27409 
  27410     /* Get the bank number of this mem table */
  27411 #ifdef BCM_APACHE_SUPPORT
  27412     if (SOC_IS_APACHE(unit)) {
  27413         SOC_IF_ERROR_RETURN
  27414             (soc_apache_hash_bank_count_get(unit, mem, &bank_info->num_banks));
  27415     } else
  27416 #endif /* BCM_APACHE_SUPPORT */
  27417 #ifdef BCM_TOMAHAWK_SUPPORT
  27418     if (SOC_IS_TOMAHAWKX(unit)) {
  27419 #ifdef BCM_TOMAHAWK3_SUPPORT
  27420         if (SOC_IS_TOMAHAWK3(unit)) {
  27421             SOC_IF_ERROR_RETURN
  27422                 (soc_tomahawk3_hash_bank_count_get(unit, mem, &bank_info->num_banks));
  27423         } else
  27424 #endif /* BCM_TOMAHAWK3_SUPPORT */
  27425         {
  27426         SOC_IF_ERROR_RETURN
  27427             (soc_tomahawk_hash_bank_count_get(unit, mem, &bank_info->num_banks));
  27428         }
  27429     } else
  27430 #endif /* BCM_TOMAHAWK_SUPPORT */
  27431 #ifdef BCM_HELIX5_SUPPORT
  27432     if (SOC_IS_HELIX5(unit)) {
  27433         SOC_IF_ERROR_RETURN
  27434             (soc_helix5_hash_bank_count_get(unit, mem, &bank_info->num_banks));
  27435     } else
  27436 #endif /* BCM_HELIX5_SUPPORT */
  27437 #ifdef BCM_TRIDENT3_SUPPORT
  27438     if (SOC_IS_TRIDENT3X(unit)) {
  27439         SOC_IF_ERROR_RETURN
  27440             (soc_trident3_hash_bank_count_get(unit, mem, &bank_info->num_banks));
  27441     } else
  27442 #endif /* BCM_TRIDENT3_SUPPORT */
  27443     {
  27444         SOC_IF_ERROR_RETURN
  27445             (soc_trident2_hash_bank_count_get(unit, mem, &bank_info->num_banks));
  27446     }
  27447 
  27448     /* Clear banks bitmap. */
  27449     bank_info->banks = 0;
  27450 
  27451     for (bix = 0; bix < bank_info->num_banks; bix++) {
  27452 #ifdef BCM_APACHE_SUPPORT
  27453         if (SOC_IS_APACHE(unit)) {
  27454             SOC_IF_ERROR_RETURN
  27455                 (soc_apache_hash_bank_number_get(unit, mem, bix,
  27456                                                    &bank_info->bank_nums[bix]));
  27457         } else
  27458 #endif /* BCM_APACHE_SUPPORT */
  27459 #ifdef BCM_TOMAHAWK_SUPPORT
  27460         if (SOC_IS_TOMAHAWKX(unit)) {
  27461 #ifdef BCM_TOMAHAWK3_SUPPORT
  27462             if (SOC_IS_TOMAHAWK3(unit)) {
  27463                 SOC_IF_ERROR_RETURN
  27464                     (soc_tomahawk3_hash_bank_number_get(unit, mem, bix,
  27465                                                        &bank_info->bank_nums[bix]));
  27466             } else
  27467 #endif /* BCM_TOMAHAWK3_SUPPORT */
  27468             {
  27469             SOC_IF_ERROR_RETURN
  27470                 (soc_tomahawk_hash_bank_number_get(unit, mem, bix,
  27471                                                    &bank_info->bank_nums[bix]));
  27472             }
  27473         } else
  27474 #endif /* BCM_TOMAHAWK_SUPPORT */
  27475 #ifdef BCM_HELIX5_SUPPORT
  27476         if (SOC_IS_HELIX5(unit)) {
  27477             SOC_IF_ERROR_RETURN
  27478                 (soc_hx5_hash_bank_number_get(unit, mem, bix,
  27479                                                 &bank_info->bank_nums[bix]));
  27480         } else
  27481 #endif /* BCM_TRIDENT3_SUPPORT */
  27482 #ifdef BCM_TRIDENT3_SUPPORT
  27483         if (SOC_IS_TRIDENT3X(unit)) {
  27484             SOC_IF_ERROR_RETURN
  27485                 (soc_td3_hash_bank_number_get(unit, mem, bix,
  27486                                                 &bank_info->bank_nums[bix]));
  27487         } else
  27488 #endif /* BCM_TRIDENT3_SUPPORT */
  27489         {
  27490             SOC_IF_ERROR_RETURN
  27491                 (soc_trident2_hash_bank_number_get(unit, mem, bix,
  27492                                                    &bank_info->bank_nums[bix]));
  27493         }
  27494 
  27495         /* Get the all banks bitmap for hash insert. */
  27496         bank_info->banks |= 1 << bank_info->bank_nums[bix];
  27497     }
  27498 
  27499     if (SOC_MULTI_HASH_MOVE_ALGORITHM(unit) == MULTI_MOVE_MODE_LEGACY ||
  27500         SOC_MULTI_HASH_MOVE_ALGORITHM(unit) == MULTI_MOVE_MODE_MIX)  {
  27501         bank_info->numb = 65536;
  27502         /* Keep back trace of all buckets affected by recursion. */
  27503         alloc_size = SHR_BITALLOCSIZE(bank_info->numb * 10);
  27504         /* For simplicity, allocate same number of bits for buckets per bank */
  27505     } else {
  27506         bank_info->numb = soc_mem_index_count(unit, mem) >> (L2Xm == mem ? 2 : 0);
  27507 #ifdef BCM_TOMAHAWK3_SUPPORT
  27508         if (SOC_IS_TOMAHAWK3(unit)) {
  27509             int tbl_entries_per_sram_entry, rv;
  27510             rv = soc_tomahawk3_tbl_entries_per_sram_entry_get(unit, mem,
  27511                        &tbl_entries_per_sram_entry);
  27512             if (SOC_FAILURE(rv)){
  27513                 return (rv);
  27514             }
  27515             bank_info->numb *= 4/tbl_entries_per_sram_entry;
  27516         }
  27517 #endif
  27518         alloc_size = SHR_BITALLOCSIZE(bank_info->numb);
  27519         if (SOC_MULTI_HASH_MOVE_ALGORITHM(unit) ==
  27520             MULTI_MOVE_MODE_DEPTH_FAST) {
  27521             alloc_size *= 2;
  27522         }
  27523     }
  27524 
  27525     bkt_trace = sal_alloc(alloc_size, "Shared hash");
  27526     if (NULL == bkt_trace) {
  27527         return SOC_E_MEMORY;
  27528     }
  27529     sal_memset(bkt_trace, 0, alloc_size);
  27530     *trace = bkt_trace;
  27531 
  27532 
  27533     if (buckets) {
  27534         int num_cl_buckets;
  27535         int level;
  27536 
  27537         alloc_size = 0;
  27538         num_cl_buckets = bank_info->num_banks;
  27539         for (level = 0; level < num_levels; level++) {
  27540             alloc_size += num_cl_buckets;
  27541             num_cl_buckets *= (bank_info->num_banks - 1) * 4;
  27542         }
  27543         alloc_size *= sizeof(_soc_breadth_bucket_t);
  27544 
  27545         *buckets = sal_alloc(alloc_size, "Buckets");
  27546         if (*buckets == NULL) {
  27547             sal_free(bkt_trace);
  27548             return SOC_E_MEMORY;
  27549         }
  27550         sal_memset(*buckets, 0, alloc_size);
  27551     }
  27552 
  27553     if (buckets2) {
  27554         alloc_size = (bank_info->numb + 1) * sizeof(_soc_breadth_bucket2_t);
  27555         *buckets2 = sal_alloc(alloc_size, "Buckets");
  27556         if (*buckets2 == NULL) {
  27557             sal_free(bkt_trace);
  27558             if (buckets && *buckets) {
  27559                 sal_free(*buckets);
  27560             }
  27561             return SOC_E_MEMORY;
  27562         }
  27563         sal_memset(*buckets2, 0, alloc_size);
  27564     }
  27565 
  27566     return SOC_E_NONE;
  27567 }
  27568 
  27569 /*
  27570  * Function:
  27571  *    _soc_mem_shared_hash_move_entry_resolve
  27572  * Purpose:
  27573  *    Resolve the move mem and entry from current slot/index(with new mem view),
  27574  *    1. If there is enough space for new mem insert (!(v0 || v1 || v2 || v3)),
  27575  *        return free_slot = TRUE directly.
  27576  *    2. If there is no enough space, resolve the move mem type and
  27577  *        entry content for hash move.
  27578  * Param:
  27579  *    mem    -  memory for new insert
  27580  *    copyno -  copy number
  27581  *    index  -  Hash calculated HW index for this mem view in current bank
  27582  *    *free_slot  -  If have enough spaces for hash move return TRUE; else FALSE
  27583  *    *move_mem   -  mem type which will be moved.
  27584  *    *move_entry -  mem entry which will be moved.
  27585  * Notes:
  27586  *    None.
  27587  */
  27588 
  27589 STATIC INLINE int
  27590 _soc_mem_shared_hash_move_entry_resolve(int unit, soc_mem_t mem, int copyno,
  27591                                         int index, int *free_slot,
  27592                                         soc_mem_t *move_mem, void *move_entry)
  27593 {
  27594     int rv;
  27595     uint32 v0, v1, v2, v3, k0, k1, k2, k3;
  27596     soc_mem_t old_mem;
  27597     int key_type, offset, l3_entry_only_index;
  27598     soc_field_t fld_vld = VALIDf;
  27599     if (mem == L2Xm &&
  27600         soc_feature(unit, soc_feature_base_valid)) {
  27601         fld_vld = BASE_VALIDf;
  27602     }
  27603 
  27604     /* Read entry information from current slot/index with new mem view */
  27605     rv = soc_mem_read(unit, mem, copyno, index, move_entry);
  27606     if (SOC_FAILURE(rv)) {
  27607         return SOC_E_MEMORY;
  27608     }
  27609     /* Could be an empty slot here */
  27610     v0 = v1 = v2 = v3 = 0;
  27611     k0 = k1 = k2 = k3 = 0;
  27612     *free_slot = FALSE;
  27613 
  27614     switch (mem) {
  27615     case L3_ENTRY_IPV6_MULTICASTm:
  27616         soc_mem_field_get(unit, mem, move_entry, VALID_3f, &v3);
  27617         soc_mem_field_get(unit, mem, move_entry, VALID_2f, &v2);
  27618         soc_mem_field_get(unit, mem, move_entry, KEY_TYPE_3f, &k3);
  27619         soc_mem_field_get(unit, mem, move_entry, KEY_TYPE_2f, &k2);
  27620         /* pass through */
  27621     case L3_ENTRY_IPV6_UNICASTm:
  27622     case L3_ENTRY_IPV4_MULTICASTm:
  27623         soc_mem_field_get(unit, mem, move_entry, VALID_1f, &v1);
  27624         soc_mem_field_get(unit, mem, move_entry, VALID_0f, &v0);
  27625         soc_mem_field_get(unit, mem, move_entry, KEY_TYPE_1f, &k1);
  27626         soc_mem_field_get(unit, mem, move_entry, KEY_TYPE_0f, &k0);
  27627         break;
  27628     case L3_ENTRY_IPV4_UNICASTm:
  27629     case L3_ENTRY_ONLYm:
  27630     case L2Xm:
  27631         soc_mem_field_get(unit, mem, move_entry, fld_vld, &v0);
  27632         soc_mem_field_get(unit, mem, move_entry, KEY_TYPEf, &k0);
  27633         break;
  27634     default:
  27635         v0 = v1 = v2 = v3 = 1;
  27636         break;
  27637     }
  27638 
  27639     LOG_VERBOSE(BSL_LS_SOC_COMMON,
  27640                 (BSL_META_U(unit,
  27641                             "Read %s from index %d (%d %d %d %d)\n"),
  27642                  SOC_MEM_NAME(unit, mem), index, v0, v1, v2, v3));
  27643 
  27644     /* If it is an emty bucket or there are enough spaces for hash insert,
  27645      * v0, v1, v2, v3 are all zero. */
  27646     if (!(v0 || v1 || v2 || v3)) {
  27647         *free_slot = TRUE;
  27648         return SOC_E_NONE;
  27649     }
  27650 
  27651     /* If no enough spaces, resolve move mem and move entry */
  27652     if (mem == L2Xm) {
  27653         *move_mem = L2Xm;
  27654     } else {
  27655         /* what is the key_type of old entry */
  27656         key_type = v0 ? k0 : (v1 ? k1 : (v2 ? k2 : (v3 ? k3 : 0)));
  27657 
  27658         /* what is the mem table type of old entry */
  27659         switch (key_type) {
  27660         case TD2_L3_HASH_KEY_TYPE_V4UC:
  27661         case TD2_L3_HASH_KEY_TYPE_TRILL:
  27662         case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN:
  27663         case TD2_L3_HASH_KEY_TYPE_FCOE_HOST:
  27664         case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP:
  27665             old_mem = L3_ENTRY_IPV4_UNICASTm;
  27666             break;
  27667         case TD2_L3_HASH_KEY_TYPE_V4UC_EXT:
  27668         case TD2_L3_HASH_KEY_TYPE_V4MC:
  27669         case TD2_L3_HASH_KEY_TYPE_V4L2MC:
  27670         case TD2_L3_HASH_KEY_TYPE_V4L2VPMC:
  27671         case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT:
  27672         case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT:
  27673         case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT:
  27674         case TD2_L3_HASH_KEY_TYPE_DST_NAT:
  27675         case TD2_L3_HASH_KEY_TYPE_DST_NAPT:
  27676             old_mem = L3_ENTRY_IPV4_MULTICASTm;
  27677             break;
  27678         case TD2_L3_HASH_KEY_TYPE_V6UC:
  27679             old_mem = L3_ENTRY_IPV6_UNICASTm;
  27680             break;
  27681         case TD2_L3_HASH_KEY_TYPE_V6UC_EXT:
  27682         case TD2_L3_HASH_KEY_TYPE_V6MC:
  27683         case TD2_L3_HASH_KEY_TYPE_V6L2MC:
  27684         case TD2_L3_HASH_KEY_TYPE_V6L2VPMC:
  27685             old_mem = L3_ENTRY_IPV6_MULTICASTm;
  27686             break;
  27687         default:
  27688             return SOC_E_INTERNAL;
  27689         }
  27690 
  27691         /* If different mem table, re-calculate the index and re-read the move entry */
  27692         if (mem != old_mem) {
  27693             /* coverity[dead_error_line] */
  27694             offset = v0 ? 0 : (v1 ? 1 : (v2 ? 2 : (v3 ? 3 : 0)));
  27695             switch (mem) {
  27696             case L3_ENTRY_IPV6_MULTICASTm:
  27697                 l3_entry_only_index = index * 4 + offset;
  27698                 break;
  27699             case L3_ENTRY_IPV6_UNICASTm:
  27700             case L3_ENTRY_IPV4_MULTICASTm:
  27701                 l3_entry_only_index = index * 2 + offset;
  27702                 break;
  27703             case L3_ENTRY_IPV4_UNICASTm:
  27704             default:
  27705                 l3_entry_only_index = index + offset;
  27706                 break;
  27707             }
  27708             /* re-calculate the move entry index */
  27709             switch (old_mem) {
  27710             case L3_ENTRY_IPV6_MULTICASTm:
  27711                 index = l3_entry_only_index / 4;
  27712                 break;
  27713             case L3_ENTRY_IPV6_UNICASTm:
  27714             case L3_ENTRY_IPV4_MULTICASTm:
  27715                 index = l3_entry_only_index / 2;
  27716                 break;
  27717             case L3_ENTRY_IPV4_UNICASTm:
  27718             default:
  27719                 index = l3_entry_only_index;
  27720                 break;
  27721             }
  27722             /* re-read the move entry */
  27723             rv = soc_mem_read(unit, old_mem, copyno, index, move_entry);
  27724             if (SOC_FAILURE(rv)) {
  27725                 return SOC_E_MEMORY;
  27726             }
  27727         }
  27728 
  27729         /* return move mem table type */
  27730         *move_mem = old_mem;
  27731     }
  27732 
  27733     return SOC_E_NONE;
  27734 }
  27735 
  27736 /*
  27737  * Function:
  27738  *    _soc_mem_shared_hash_breadth_move
  27739  * Purpose:
  27740  *    Breadth recursion algorithm for shared hash move
  27741  * Notes:
  27742  *    None.
  27743  */
  27744 
  27745 STATIC int
  27746 _soc_mem_shared_hash_breadth_move(int unit, soc_mem_t mem,
  27747                                   int32 banks, int copyno,
  27748                                   void *entry, SHR_BITDCL *bucket_trace,
  27749                                   int recurse, int recurse_depth,
  27750                                   _soc_hash_bank_info_t *bank_info)
  27751 {
  27752     SHR_BITDCL *trace = NULL;
  27753     _soc_hash_bank_info_t bank_inf = {0};
  27754     uint8 num_ent = 0;
  27755     int nbix, cbix;
  27756     int rv = SOC_E_NONE, index;
  27757     uint8 i, bix, found = FALSE, cb = 0;
  27758     uint32 db, dest_bucket, dbs;
  27759     uint32 bucket, move_entry[SOC_MAX_MEM_WORDS];
  27760     soc_mem_t ori_mem = mem;
  27761     int banks_seq_num = 0;
  27762 
  27763     if (recurse_depth < 0) {
  27764         return SOC_E_FULL;
  27765     }
  27766     /* Get the entry number per each bucket */
  27767     num_ent = _soc_mem_shared_hash_entries_per_bkt(unit, mem);
  27768 
  27769     /* Stack variables initialization & memory allocations */
  27770     if (NULL == bucket_trace) {
  27771         SOC_IF_ERROR_RETURN(
  27772             _soc_mem_shared_hash_init(unit, mem, &trace, &bank_inf, 0, NULL, NULL));
  27773     } else {
  27774         trace = bucket_trace;
  27775         if (NULL != bank_info) {
  27776             sal_memcpy(&bank_inf, bank_info, sizeof(_soc_hash_bank_info_t));
  27777         } else {
  27778             rv = SOC_E_INTERNAL;
  27779             goto clean_up;
  27780         }
  27781     }
  27782     if (banks != SOC_MEM_HASH_BANK_ALL) {
  27783 #ifdef BCM_APACHE_SUPPORT
  27784         if (SOC_IS_APACHE(unit)) {
  27785             rv = soc_apache_hash_seq_number_get(unit, mem, banks,
  27786                                                   &banks_seq_num);
  27787         } else
  27788 #endif /* BCM_APACHE_SUPPORT */
  27789 #ifdef BCM_TOMAHAWK_SUPPORT
  27790         if (SOC_IS_TOMAHAWKX(unit)) {
  27791 #ifdef BCM_TOMAHAWK3_SUPPORT
  27792             if (SOC_IS_TOMAHAWK3(unit)) {
  27793                 rv = soc_tomahawk3_hash_seq_number_get(unit, mem, banks,
  27794                                                       &banks_seq_num);
  27795             } else
  27796 #endif /* BCM_TOMAHAWK3_SUPPORT */
  27797             {
  27798             rv = soc_tomahawk_hash_seq_number_get(unit, mem, banks,
  27799                                                   &banks_seq_num);
  27800             }
  27801         } else
  27802 #endif /* BCM_TOMAHAWK_SUPPORT */
  27803 #ifdef BCM_HELIX5_SUPPORT
  27804         if (SOC_IS_HELIX5(unit)) {
  27805             rv = soc_hx5_hash_seq_number_get(unit, mem, banks, &banks_seq_num);
  27806         } else 
  27807 #endif /* BCM_HELIX5_SUPPORT */
  27808 #ifdef BCM_TRIDENT3_SUPPORT
  27809         if (SOC_IS_TRIDENT3X(unit)) {
  27810             rv = soc_td3_hash_seq_number_get(unit, mem, banks, &banks_seq_num);
  27811         } else 
  27812 #endif /* BCM_TRIDENT3_SUPPORT */
  27813         {
  27814             rv = soc_trident2_hash_seq_number_get(unit, mem, banks,
  27815                                                   &banks_seq_num);
  27816         }
  27817         if (SOC_FAILURE(rv)) {
  27818             goto clean_up;
  27819         }
  27820     } else {
  27821         /* Make sure we will try from the first bank */
  27822         banks_seq_num = -1;
  27823     }
  27824     /* Iterate over banks. */
  27825     for (bix = 0; bix < bank_inf.num_banks; bix++) {
  27826         /* if banks is present, try interate from next bank */
  27827         cbix = banks_seq_num + bix + 1;
  27828         cbix = cbix % bank_inf.num_banks;
  27829         cb = bank_inf.bank_nums[cbix];
  27830         if (banks == cb) {
  27831             /* Not this bank */
  27832             continue;
  27833         }
  27834 #ifdef BCM_APACHE_SUPPORT
  27835         if (SOC_IS_APACHE(unit)) {
  27836             rv = soc_ap_hash_bucket_get(unit, mem, cb, entry, &bucket);
  27837         } else
  27838 #endif /* BCM_APACHE_SUPPORT */
  27839 #ifdef BCM_TOMAHAWK_SUPPORT
  27840         if (SOC_IS_TOMAHAWKX(unit)) {
  27841 #ifdef BCM_TOMAHAWK3_SUPPORT
  27842             if (SOC_IS_TOMAHAWK3(unit)) {
  27843                 rv = soc_tomahawk3_hash_bucket_get(unit, mem, cb, entry, &bucket);
  27844             } else
  27845 #endif /* BCM_TOMAHAWK3_SUPPORT */
  27846             {
  27847             rv = soc_th_hash_bucket_get(unit, mem, cb, entry, &bucket);
  27848             }
  27849         } else
  27850 #endif /* BCM_TOMAHAWK_SUPPORT */
  27851 #ifdef BCM_HELIX5_SUPPORT
  27852         if (SOC_IS_HELIX5(unit)) {
  27853             rv = soc_hx5_hash_bucket_get(unit, mem, cb, entry, &bucket);
  27854         } else 
  27855 #endif /* BCM_HELIX5_SUPPORT */
  27856 #ifdef BCM_TRIDENT3_SUPPORT
  27857         if (SOC_IS_TRIDENT3X(unit)) {
  27858             rv = soc_td3_hash_bucket_get(unit, mem, cb, entry, &bucket);
  27859         } else 
  27860 #endif /* BCM_TRIDENT3_SUPPORT */
  27861         {
  27862             rv = soc_hash_bucket_get(unit, mem, cb, entry, &bucket);
  27863         }
  27864 
  27865         if (SOC_FAILURE(rv)) {
  27866             break;
  27867         }
  27868         nbix = (cbix + 1) % bank_inf.num_banks; /* next bank index */
  27869         db = bank_inf.bank_nums[nbix]; /* next destination bank */
  27870         /* For simplicity, use dbs instead of db for hash move.
  27871         * The dbs only used in breadth iteration loop */
  27872         dbs = bank_inf.banks & ~(1 << cb);
  27873         /* Only record the buckets in breadth iteration loop */
  27874         if (!recurse) {
  27875             /* If this bucket was already iterated, Try next */
  27876             if (SHR_BITGET(trace, (bank_inf.numb * cbix) + bucket)) {
  27877                 continue;
  27878             }
  27879             SHR_BITSET(trace, (bank_inf.numb * cbix) + bucket);
  27880         }
  27881 #ifdef BCM_APACHE_SUPPORT
  27882         if (SOC_IS_APACHE(unit)) {
  27883             index = soc_ap_hash_index_get(unit, mem, cb, bucket);
  27884         } else
  27885 #endif /* BCM_APACHE_SUPPORT */
  27886 #ifdef BCM_TOMAHAWK_SUPPORT
  27887         if (SOC_IS_TOMAHAWKX(unit)) {
  27888 #ifdef BCM_TOMAHAWK3_SUPPORT
  27889             if (SOC_IS_TOMAHAWK3(unit)) {
  27890                 index = soc_tomahawk3_hash_index_get(unit, mem, cb, bucket);
  27891             } else
  27892 #endif /* BCM_TOMAHAWK3_SUPPORT */
  27893             {
  27894             index = soc_th_hash_index_get(unit, mem, cb, bucket);
  27895             }
  27896         } else
  27897 #endif /* BCM_TOMAHAWK_SUPPORT */
  27898 #ifdef BCM_HELIX5_SUPPORT
  27899         if (SOC_IS_HELIX5(unit)) {
  27900             index = soc_hx5_hash_index_get(unit, mem, cb, bucket);
  27901         } else
  27902 #endif /* BCM_HELIX5_SUPPORT */
  27903 #ifdef BCM_TRIDENT3_SUPPORT
  27904         if (SOC_IS_TRIDENT3X(unit)) {
  27905             index = soc_td3_hash_index_get(unit, mem, cb, bucket);
  27906         } else
  27907 #endif /* BCM_TRIDENT3_SUPPORT */
  27908         {
  27909             index = soc_hash_index_get(unit, mem, cb, bucket);
  27910         }
  27911         for (i = 0; i < num_ent;) {
  27912             int free_slot = FALSE;
  27913             /* Is there free slot to insert this new entry?
  27914                If no, resolve the move_mem and move_entry from current index */
  27915             rv = _soc_mem_shared_hash_move_entry_resolve(unit, mem, copyno,
  27916                                                          index + i, &free_slot,
  27917                                                          &mem, move_entry);
  27918             if (SOC_FAILURE(rv)) {
  27919                 break;
  27920             }
  27921             /* If have free slot for move entry, insert directly */
  27922             if (free_slot) {
  27923                 found = TRUE;
  27924                 break;
  27925             }
  27926 
  27927             /* Are we already in recursion */
  27928             if (recurse) {
  27929                 /* Will we be in recursion */
  27930                 if (recurse_depth) {
  27931                     /* Calculate destination entry hash value. */
  27932 #ifdef BCM_APACHE_SUPPORT
  27933                     if (SOC_IS_APACHE(unit)) {
  27934                         (void)soc_ap_hash_bucket_get(unit, mem, db, move_entry,
  27935                                                      &dest_bucket);
  27936                     } else
  27937 #endif /* BCM_APACHE_SUPPORT */
  27938 #ifdef BCM_TOMAHAWK_SUPPORT
  27939                     if (SOC_IS_TOMAHAWKX(unit)) {
  27940 #ifdef BCM_TOMAHAWK3_SUPPORT
  27941                         if (SOC_IS_TOMAHAWK3(unit)) {
  27942                             (void)soc_tomahawk3_hash_bucket_get(unit, mem, db, move_entry,
  27943                                                          &dest_bucket);
  27944                         } else
  27945 #endif /* BCM_TOMAHAWK3_SUPPORT */
  27946                         {
  27947                         (void)soc_th_hash_bucket_get(unit, mem, db, move_entry,
  27948                                                      &dest_bucket);
  27949                         }
  27950                     } else
  27951 #endif /* BCM_TOMAHAWK_SUPPORT */
  27952 #ifdef BCM_HELIX5_SUPPORT
  27953                     if (SOC_IS_HELIX5(unit)) {
  27954                         (void)soc_hx5_hash_bucket_get(unit, mem, db, move_entry,
  27955                                                       &dest_bucket);
  27956                     } else
  27957 #endif /* BCM_HELIX5_SUPPORT */
  27958 #ifdef BCM_TRIDENT3_SUPPORT
  27959                     if (SOC_IS_TRIDENT3X(unit)) {
  27960                         (void)soc_td3_hash_bucket_get(unit, mem, db, move_entry,
  27961                                                       &dest_bucket);
  27962                     } else
  27963 #endif /* BCM_TRIDENT3_SUPPORT */
  27964                     {
  27965                         (void)soc_hash_bucket_get(unit, mem, db, move_entry,
  27966                                                   &dest_bucket);
  27967                     }
  27968                     if (SHR_BITGET(trace, (bank_inf.numb * nbix) + dest_bucket)) {
  27969                         /* Try next entry in the same bucket in original
  27970                          * memory view */
  27971                         mem = ori_mem;
  27972                         i += _soc_mem_shared_hash_incr_per_entry(unit, mem,
  27973                                                                  move_entry,
  27974                                                                  entry);
  27975                         LOG_VERBOSE(BSL_LS_SOC_COMMON,
  27976                                     (BSL_META_U(unit,
  27977                                                 "  Skip bank %d bucket %d\n"),
  27978                                      db, dest_bucket));
  27979                         continue;
  27980                     }
  27981                 }
  27982 
  27983                 /* Recursive call - attempt to create a slot
  27984                    in another bank's bucket. */
  27985                 rv = _soc_mem_shared_hash_breadth_move(unit, mem, cb, copyno,
  27986                                                        move_entry, trace, FALSE,
  27987                                                        recurse_depth - 1,
  27988                                                        &bank_inf);
  27989             } else {
  27990                 /* Attempt to insert it into the other banks. Use dbs instead of db. */
  27991                 rv = soc_mem_bank_insert(unit, mem, dbs, copyno,
  27992                                          move_entry, NULL);
  27993             }
  27994 
  27995             if (SOC_FAILURE(rv)) {
  27996                 if (rv != SOC_E_FULL) {
  27997                     break;
  27998                 }
  27999                 mem = ori_mem;
  28000                 i += _soc_mem_shared_hash_incr_per_entry(unit, mem,
  28001                                                          move_entry, entry);
  28002                 continue;
  28003             }
  28004             /* Delete old entry from original location */
  28005             rv = soc_mem_generic_delete(unit, mem, MEM_BLOCK_ANY, (uint32)1<<cb,
  28006                                         move_entry, NULL, NULL);
  28007             mem = ori_mem;
  28008             if ((rv < 0) && (rv != SOC_E_FULL)) {
  28009                 break;
  28010             }
  28011         }  /* Bucket iteration loop. */
  28012 
  28013         if (found || ((rv < 0) && (rv != SOC_E_FULL))) {
  28014             break;
  28015         }
  28016     }
  28017 
  28018     if (!recurse && !found && (rv == SOC_E_NONE || rv == SOC_E_FULL)) {
  28019         /* Recursive call - attempt to go deeper in the hierarchy. */
  28020         rv = _soc_mem_shared_hash_breadth_move(unit, mem, banks, copyno, entry,
  28021                                                trace, TRUE, recurse_depth,
  28022                                                &bank_inf);
  28023         if (SOC_SUCCESS(rv)) {
  28024             goto clean_up;
  28025         }
  28026     }
  28027 
  28028     /* Bank iteration loop. */
  28029     if ((rv < 0) && (rv != SOC_E_FULL)) {
  28030         goto clean_up;
  28031     }
  28032     if (!found) {
  28033         rv = SOC_E_FULL;
  28034         goto clean_up;
  28035     }
  28036 
  28037     rv = soc_mem_generic_insert(unit, mem, copyno, (uint32)1<<cb,
  28038                                 entry, entry, NULL);
  28039     if (rv) {
  28040         LOG_VERBOSE(BSL_LS_SOC_COMMON,
  28041                     (BSL_META_U(unit,
  28042                                 "Insert entry: %d\n"), rv));
  28043     }
  28044 
  28045 clean_up:
  28046     if (NULL == bucket_trace) {
  28047         sal_free(trace);
  28048     }
  28049 
  28050     return rv;
  28051 }
  28052 
  28053 
  28054 STATIC int
  28055 _soc_mem_shared_hash_insert(int unit, soc_mem_t mem, int copyno,
  28056                             void *entry_data, void *old_entry_data,
  28057                             int recurse_depth)
  28058 {
  28059     int rv = SOC_E_NONE;
  28060     rv = soc_mem_bank_insert(unit, mem, SOC_MEM_HASH_BANK_ALL, copyno,
  28061                              entry_data, old_entry_data);
  28062     if (rv != SOC_E_FULL) {
  28063         return rv;
  28064     }
  28065  
  28066     /* Time to shuffle the entries */
  28067     soc_mem_lock(unit, mem);
  28068     switch (SOC_MULTI_HASH_MOVE_ALGORITHM(unit)) {
  28069         case MULTI_MOVE_MODE_LEGACY:
  28070             rv = _soc_mem_shared_hash_move(unit, mem, SOC_MEM_HASH_BANK_ALL,
  28071                                            copyno, entry_data, NULL,
  28072                                            recurse_depth - 1, NULL);
  28073             break;
  28074         case MULTI_MOVE_MODE_MIX:
  28075             rv = _soc_mem_shared_hash_breadth_move(unit, mem, SOC_MEM_HASH_BANK_ALL,
  28076                                                    copyno, entry_data, NULL, 0,
  28077                                                    recurse_depth - 1, NULL);
  28078             break;
  28079         case MULTI_MOVE_MODE_DEPTH_FAST:
  28080         case MULTI_MOVE_MODE_DEPTH:
  28081             rv = _soc_mem_shared_hash_depth_move(unit, mem, SOC_MEM_HASH_BANK_ALL,
  28082                                                  copyno, entry_data,
  28083                                                  recurse_depth - 1, NULL, NULL);
  28084             break;
  28085         default:
  28086             if (mem == L2Xm) {
  28087                 rv = _soc_mem_shared_hash_breadth_l2_move(unit, mem, copyno,
  28088                                                           entry_data, recurse_depth);
  28089             } else {
  28090 #ifdef BCM_TRIDENT3_SUPPORT
  28091                 if (SOC_IS_TRIDENT3X(unit)) {
  28092                     rv = _soc_mem_shared_hash_td3_breadth_mix_move(unit, mem, copyno,
  28093                                                            entry_data, recurse_depth);
  28094                 } else
  28095 #endif /* BCM_TRIDENT3_SUPPORT */
  28096 #ifdef BCM_TOMAHAWK3_SUPPORT
  28097                 if (SOC_IS_TOMAHAWK3(unit)) {
  28098                     rv = _soc_mem_shared_hash_tomahawk3_breadth_mix_move(unit, mem, copyno,
  28099                                                            entry_data, recurse_depth);
  28100                 } else
  28101 #endif /* BCM_TOMAHAWK3_SUPPORT */
  28102                 {
  28103                     rv = _soc_mem_shared_hash_breadth_mix_move(unit, mem, copyno,
  28104                                                            entry_data, recurse_depth);
  28105                 }
  28106             }
  28107             break;
  28108     }
  28109     soc_mem_unlock(unit, mem);
  28110 
  28111     return rv;
  28112 }
  28113 #endif /* BCM_TRIDENT2_SUPPORT */
  28114 
  28115 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT \
  28116           || BCM_RAVEN_SUPPORT */
  28117 
  28118 /*
  28119  * Function:
  28120  *    _soc_mem_insert
  28121  * Purpose:
  28122  *    Helper routine for soc_mem_insert
  28123  */
  28124 
  28125 STATIC int
  28126 _soc_mem_insert(int unit,
  28127                 soc_mem_t mem,        /* Assumes memory locked */
  28128                 int copyno,
  28129                 void *entry_data)
  28130 {
  28131     uint32        entry_tmp[SOC_MAX_MEM_WORDS];
  28132     int            max, ins_index, index, last, rv;
  28133 
  28134     max = soc_mem_index_max(unit, mem);
  28135     last = soc_mem_index_last(unit, mem, copyno);
  28136 
  28137     rv = soc_mem_search(unit, mem, copyno,
  28138                         &ins_index, entry_data, entry_tmp, 0);
  28139 
  28140     if (rv == SOC_E_NONE) {
  28141         /* If entry with matching key already exists, overwrite it. */
  28142 
  28143         if ((rv = soc_mem_write(unit, mem, copyno,
  28144                                 ins_index, entry_data)) < 0) {
  28145             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  28146                       (BSL_META_U(unit,
  28147                                   "soc_mem_insert: write %s.%s[%d] failed\n"),
  28148                        SOC_MEM_UFNAME(unit, mem),
  28149                        SOC_BLOCK_NAME(unit, copyno), ins_index));
  28150             return rv;
  28151         }
  28152 
  28153         return SOC_E_NONE;
  28154     }
  28155 
  28156     if (rv != SOC_E_NOT_FOUND) {
  28157         return rv;
  28158     }
  28159 
  28160     /* Point to first unused entry; fail if table is already full. */
  28161 
  28162     if ((index = last + 1) > max) {
  28163         return SOC_E_FULL;
  28164     }
  28165 
  28166     while (index > ins_index) {
  28167         /* Move up one entry */
  28168 
  28169         if ((rv = soc_mem_read(unit, mem, copyno,
  28170                                index - 1, entry_tmp)) < 0) {
  28171             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  28172                       (BSL_META_U(unit,
  28173                                   "soc_mem_insert: read %s.%s[%d] failed\n"),
  28174                        SOC_MEM_UFNAME(unit, mem),
  28175                        SOC_BLOCK_NAME(unit, copyno), index - 1));
  28176             return rv;
  28177         }
  28178 
  28179         if ((rv = soc_mem_write(unit, mem, copyno,
  28180                                 index, entry_tmp)) < 0) {
  28181             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  28182                       (BSL_META_U(unit,
  28183                                   "soc_mem_insert: write %s.%s[%d] failed\n"),
  28184                        SOC_MEM_UFNAME(unit, mem),
  28185                        SOC_BLOCK_NAME(unit, copyno), index));
  28186             return rv;
  28187         }
  28188 
  28189         index--;
  28190     }
  28191 
  28192     /* Write entry data at insertion point */
  28193 
  28194     if ((rv = soc_mem_write(unit, mem, copyno,
  28195                             ins_index, entry_data)) < 0) {
  28196         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  28197                   (BSL_META_U(unit,
  28198                               "soc_mem_insert: write %s.%s[%d] failed\n"),
  28199                    SOC_MEM_UFNAME(unit, mem),
  28200                    SOC_BLOCK_NAME(unit, copyno), ins_index));
  28201         return rv;
  28202     }
  28203     _SOC_MEM_REUSE_MEM_STATE(unit, mem);
  28204     SOP_MEM_STATE(unit, mem).count[copyno]++;
  28205 
  28206     return SOC_E_NONE;
  28207 }
  28208 
  28209 /*
  28210  * Function:
  28211  *    soc_mem_insert
  28212  * Purpose:
  28213  *    Insert an entry into a structured table based on key.
  28214  * Returns:
  28215  *    SOC_E_NONE - insertion succeeded
  28216  *    SOC_E_FULL - table full
  28217  *    SOC_E_XXX - other error
  28218  * Notes:
  28219  *      Tables may be binary, hashed, CAM, or command.
  28220  *
  28221  *      Binary tables:
  28222  *    A binary search is made for the entry, and if a matching key is
  28223  *    found, the entry is overwritten with new data, and 0 is returned.
  28224  *    If key is not found:
  28225  *    Starting with the last entry (kept in soc_control_t structure),
  28226  *    entries are moved down until a space is made for the required
  28227  *    index.   The moving process results in temporary duplicates but not
  28228  *    temporarily-out-of-order entries.
  28229  *    Fails if the table is already full before the insert.
  28230  *
  28231  *      Hashed tables:
  28232  *      The entry is passed to the hardware, which performs a hash
  28233  *      calculation on the key.  The entry will be added to the
  28234  *      corresponding hash bucket, if an available slot exists.
  28235  *      Fails if the hash bucket for that key is full.
  28236  *
  28237  *      CAM tables:
  28238  *      Entries are added to the CAM based on the device's
  28239  *      implementation-specific algorithm.
  28240  *      Fails if table resources are exhausted.
  28241  *
  28242  *      Command supported tables:
  28243  *      Uses memory command hardware support to handle table state,
  28244  *      based on the entry key.
  28245  *      Fails if hardware insert operation is unsuccessful.
  28246  *
  28247  *    If COPYNO_ALL is specified, the insertion is repeated for each
  28248  *    copy of the table.
  28249  */
  28250 
  28251 int
  28252 soc_mem_insert(int unit,
  28253                soc_mem_t mem,
  28254                int copyno,
  28255                void *entry_data)
  28256 {
  28257     int rv = SOC_E_NONE;
  28258 
  28259 #ifdef BCM_TRIDENT3_SUPPORT
  28260     soc_mem_t phy_mem;
  28261 #endif
  28262 
  28263 #ifdef BCM_TRIDENT3_SUPPORT
  28264     if (soc_feature(unit, soc_feature_flex_flow)) {
  28265         if (SOC_MEM_IS_VIEW(unit, mem)) {
  28266             rv = soc_mem_view_phy_mem_get(unit, mem, &phy_mem);
  28267             if (rv != SOC_E_NONE) {
  28268                 return rv;
  28269             }
  28270             mem = phy_mem;
  28271         }
  28272     }
  28273 #endif
  28274 
  28275     DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, TRUE));
  28276 
  28277     assert(soc_mem_is_sorted(unit, mem) ||
  28278            soc_mem_is_hashed(unit, mem) ||
  28279            soc_mem_is_cam(unit, mem) ||
  28280            soc_mem_is_cmd(unit, mem));
  28281     assert(entry_data);
  28282 
  28283     if (copyno == COPYNO_ALL) {
  28284 
  28285 #ifdef BCM_TRX_SUPPORT
  28286         if (SOC_IS_TRX(unit)) {
  28287             _SOC_MEM_REPLACE_MEM(unit, mem);
  28288             switch (mem) {
  28289             case MPLS_ENTRYm:
  28290                 if (SOC_IS_SC_CQ(unit) || SOC_IS_TRIDENT3X(unit)) {
  28291                     break;
  28292                 }
  28293             case VLAN_XLATEm:
  28294             case EGR_VLAN_XLATEm:
  28295 #ifdef BCM_ISM_SUPPORT
  28296                 if (soc_feature(unit, soc_feature_ism_memory)) {
  28297                     break;
  28298                 }
  28299 #endif /* BCM_ISM_SUPPORT */
  28300             case VLAN_MACm:
  28301             case AXP_WRX_WCDm:
  28302             case AXP_WRX_SVP_ASSIGNMENTm:
  28303 #ifdef BCM_TRIUMPH3_SUPPORT
  28304             case FT_SESSIONm:
  28305             case FT_SESSION_IPV6m:
  28306 #endif /* BCM_TRIUMPH3_SUPPORT */
  28307 #ifdef BCM_TRIDENT2_SUPPORT
  28308             case ING_VP_VLAN_MEMBERSHIPm:
  28309             case EGR_VP_VLAN_MEMBERSHIPm:
  28310             case ING_DNAT_ADDRESS_TYPEm:
  28311             case L2_ENDPOINT_IDm:
  28312             case ENDPOINT_QUEUE_MAPm:
  28313 #ifdef BCM_TRIDENT3_SUPPORT
  28314             case SUBPORT_ID_TO_SGPP_MAPm:
  28315 #endif /* BCM_TRIDENT3_SUPPORT */
  28316 #endif /* BCM_TRIDENT2_SUPPORT */
  28317 #ifdef BCM_KATANA2_SUPPORT
  28318             case EGR_MP_GROUPm:
  28319 #endif
  28320 #ifdef BCM_SABER2_SUPPORT
  28321             case MP_GROUPm:
  28322 #endif
  28323                 return _soc_mem_dual_hash_insert(unit, mem, copyno,
  28324                                                  entry_data, NULL,
  28325                            soc_dual_hash_recurse_depth_get(unit, mem));
  28326             default:
  28327                 break;
  28328             }
  28329         }
  28330 #endif /* BCM_TRX_SUPPORT */
  28331 
  28332 #ifdef BCM_FIREBOLT_SUPPORT
  28333         if (SOC_IS_FBX(unit)) {
  28334             switch (mem) {
  28335             case L2Xm:
  28336 #ifdef BCM_TRIDENT2_SUPPORT
  28337                 if (soc_feature(unit, soc_feature_shared_hash_mem)) {
  28338                     return _soc_mem_shared_hash_insert(unit, mem, copyno,
  28339                                                        entry_data, NULL,
  28340                                soc_multi_hash_recurse_depth_get(unit, mem));
  28341                 }
  28342 #endif /* BCM_TRIDENT2_SUPPORT */
  28343                 return soc_fb_l2x_insert(unit, entry_data);
  28344 #if defined(INCLUDE_L3)
  28345             case L3_DEFIPm:
  28346             case L3_DEFIP_LEVEL1m:
  28347                 return soc_fb_lpm_insert(unit, entry_data);
  28348             case MPLS_ENTRYm:
  28349                 /* If TD3 then pass through */
  28350                 if (!SOC_IS_TRIDENT3X(unit)) {
  28351                     break;
  28352                 }
  28353             case L3_ENTRY_ONLYm:
  28354             case L3_ENTRY_IPV4_UNICASTm:
  28355             case L3_ENTRY_IPV4_MULTICASTm:
  28356             case L3_ENTRY_IPV6_UNICASTm:
  28357             case L3_ENTRY_IPV6_MULTICASTm:
  28358             case EXACT_MATCH_2m:
  28359             case EXACT_MATCH_2_PIPE0m:
  28360             case EXACT_MATCH_2_PIPE1m:
  28361             case EXACT_MATCH_2_PIPE2m:
  28362             case EXACT_MATCH_2_PIPE3m:
  28363             case EXACT_MATCH_4m:
  28364 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  28365             case L3_ENTRY_SINGLEm:
  28366             case L3_ENTRY_DOUBLEm:
  28367             case L3_ENTRY_QUADm:
  28368             case L3_TUNNEL_SINGLEm:
  28369             case L3_TUNNEL_DOUBLEm:
  28370             case L3_TUNNEL_QUADm:
  28371             case MPLS_ENTRY_SINGLEm:
  28372             case VLAN_XLATE_1_SINGLEm:
  28373             case VLAN_XLATE_1_DOUBLEm:
  28374             case VLAN_XLATE_2_SINGLEm:
  28375             case VLAN_XLATE_2_DOUBLEm:
  28376             case EGR_VLAN_XLATE_1_SINGLEm:
  28377             case EGR_VLAN_XLATE_1_DOUBLEm:
  28378             case EGR_VLAN_XLATE_2_SINGLEm:
  28379             case EGR_VLAN_XLATE_2_DOUBLEm:
  28380 #endif
  28381             case EXACT_MATCH_4_PIPE0m:
  28382             case EXACT_MATCH_4_PIPE1m:
  28383             case EXACT_MATCH_4_PIPE2m:
  28384             case EXACT_MATCH_4_PIPE3m:
  28385 #ifdef BCM_HELIX5_SUPPORT
  28386             case FT_KEY_SINGLEm:
  28387             case FT_KEY_DOUBLEm:
  28388 #endif
  28389 #ifdef BCM_TRIDENT2_SUPPORT
  28390                 if (soc_feature(unit, soc_feature_shared_hash_mem)) {
  28391                     return _soc_mem_shared_hash_insert(unit, mem, copyno,
  28392                                                        entry_data, NULL,
  28393                                soc_multi_hash_recurse_depth_get(unit, mem));
  28394                 }
  28395 #endif /* BCM_TRIDENT2_SUPPORT */
  28396                 return soc_fb_l3x_insert(unit, entry_data);
  28397 #endif /* INCLUDE_L3 */
  28398             case VLAN_MACm:
  28399 #if defined(BCM_RAVEN_SUPPORT)
  28400                 if (soc_feature(unit, soc_feature_dual_hash) &&
  28401                     (SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit))) {
  28402                    return _soc_mem_dual_hash_insert(unit, mem, copyno,
  28403                                                     entry_data, NULL,
  28404                               soc_dual_hash_recurse_depth_get(unit, mem));
  28405                 } else
  28406 #endif
  28407             {
  28408                 return soc_fb_vlanmac_entry_ins(unit, entry_data);
  28409             }
  28410 #ifdef BCM_TRIUMPH3_SUPPORT
  28411             case EXT_L2_ENTRY_1m:
  28412             case EXT_L2_ENTRY_2m:
  28413                return soc_mem_generic_insert(unit, mem, copyno, -1,
  28414                                               entry_data, NULL, NULL);
  28415 #endif /* BCM_TRIUMPH3_SUPPORT */
  28416             default:
  28417                 break;
  28418             }
  28419         }
  28420 #endif /* BCM_FIREBOLT_SUPPORT */
  28421 
  28422 #ifdef BCM_ISM_SUPPORT
  28423         if (soc_feature(unit, soc_feature_ism_memory) &&
  28424             soc_mem_is_mview(unit, mem)) {
  28425             return _soc_mem_multi_hash_insert(unit, mem, copyno, entry_data,
  28426                        NULL, soc_multi_hash_recurse_depth_get(unit, mem));
  28427         }
  28428 #endif /* BCM_ISM_SUPPORT */
  28429 
  28430         MEM_LOCK(unit, mem);
  28431         SOC_MEM_BLOCK_ITER(unit, mem, copyno) {
  28432             if ((rv = _soc_mem_insert(unit, mem, copyno, entry_data)) < 0) {
  28433                 break;
  28434             }
  28435         }
  28436     } else {
  28437         assert(SOC_MEM_BLOCK_VALID(unit, mem, copyno));
  28438         MEM_LOCK(unit, mem);
  28439         rv = _soc_mem_insert(unit, mem, copyno, entry_data);
  28440     }
  28441 
  28442     MEM_UNLOCK(unit, mem);
  28443 
  28444     return rv;
  28445 }
  28446 
  28447 /*
  28448  * Function:
  28449  *    soc_mem_insert_return_old
  28450  * Purpose:
  28451  *      Same as soc_mem_insert() with the additional feature
  28452  *      that if an exiting entry was replaced, the old entry data
  28453  *      is returned back.
  28454  * Returns:
  28455  *    SOC_E_NONE - insertion succeeded
  28456  *    SOC_E_EXISTS - insertion succeeded, old_entry_data is valid
  28457  *    SOC_E_FULL - table full
  28458  *    SOC_E_UNAVAIL - not supported on the specified unit, mem
  28459  *    SOC_E_XXX - other error
  28460  */
  28461 int
  28462 soc_mem_insert_return_old(int unit,
  28463                           soc_mem_t mem,
  28464                           int copyno,
  28465                           void *entry_data,
  28466                           void *old_entry_data)
  28467 {
  28468 #ifdef BCM_TRIDENT3_SUPPORT
  28469     int rv = SOC_E_NONE;
  28470     soc_mem_t phy_mem;
  28471 #endif
  28472 
  28473 #ifdef BCM_TRIDENT3_SUPPORT
  28474     if (soc_feature(unit, soc_feature_flex_flow)) {
  28475         if (SOC_MEM_IS_VIEW(unit, mem)) {
  28476             rv = soc_mem_view_phy_mem_get(unit, mem, &phy_mem);
  28477             if (rv != SOC_E_NONE) {
  28478                 return rv;
  28479             }
  28480             mem = phy_mem;
  28481         }
  28482     }
  28483 #endif
  28484 #ifdef BCM_TRX_SUPPORT
  28485     if (SOC_IS_TRX(unit)) {
  28486         _SOC_MEM_REPLACE_MEM(unit, mem);
  28487         switch (mem) {
  28488         case L2Xm: /* Note: the order of the case statements should be
  28489                             changed with care */
  28490 #if defined(INCLUDE_L3)
  28491         case L3_ENTRY_ONLYm:
  28492         case L3_ENTRY_IPV4_UNICASTm:
  28493         case L3_ENTRY_IPV4_MULTICASTm:
  28494         case L3_ENTRY_IPV6_UNICASTm:
  28495         case L3_ENTRY_IPV6_MULTICASTm:
  28496 #endif /* INCLUDE_L3 */
  28497         case EXACT_MATCH_2m:
  28498         case EXACT_MATCH_2_PIPE0m:
  28499         case EXACT_MATCH_2_PIPE1m:
  28500         case EXACT_MATCH_2_PIPE2m:
  28501         case EXACT_MATCH_2_PIPE3m:
  28502         case EXACT_MATCH_4m:
  28503         case EXACT_MATCH_4_PIPE0m:
  28504         case EXACT_MATCH_4_PIPE1m:
  28505         case EXACT_MATCH_4_PIPE2m:
  28506         case EXACT_MATCH_4_PIPE3m:
  28507 #if  defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  28508         case L3_ENTRY_SINGLEm:
  28509         case L3_ENTRY_DOUBLEm:
  28510         case L3_ENTRY_QUADm:
  28511         case MPLS_ENTRY_SINGLEm:
  28512         case VLAN_XLATE_1_SINGLEm:
  28513         case VLAN_XLATE_1_DOUBLEm:
  28514         case VLAN_XLATE_2_SINGLEm:
  28515         case VLAN_XLATE_2_DOUBLEm:
  28516         case EGR_VLAN_XLATE_1_SINGLEm:
  28517         case EGR_VLAN_XLATE_1_DOUBLEm:
  28518         case EGR_VLAN_XLATE_2_SINGLEm:
  28519         case EGR_VLAN_XLATE_2_DOUBLEm:
  28520 #endif
  28521 #ifdef BCM_TRIDENT2_SUPPORT
  28522             if (soc_feature(unit, soc_feature_shared_hash_mem)) {
  28523                 return _soc_mem_shared_hash_insert(unit, mem, copyno, entry_data,
  28524                            NULL, soc_multi_hash_recurse_depth_get(unit, mem));
  28525             } else
  28526 #endif /* BCM_TRIDENT2_SUPPORT */
  28527             {
  28528                 return _soc_mem_dual_hash_insert(unit, mem, copyno,
  28529                                                  entry_data, old_entry_data,
  28530                            soc_dual_hash_recurse_depth_get(unit, mem));
  28531             }
  28532         case MPLS_ENTRYm: /* Note: the order of the case statements should be
  28533                                    changed with care */
  28534             if (SOC_IS_SC_CQ(unit)) {
  28535                 break;
  28536             }
  28537         /* passthru */
  28538         /* coverity[fallthrough: FALSE] */
  28539         case EGR_VLAN_XLATEm:
  28540         case VLAN_XLATEm:
  28541         case VLAN_MACm:
  28542         case AXP_WRX_WCDm:
  28543         case AXP_WRX_SVP_ASSIGNMENTm:
  28544 #ifdef BCM_TRIUMPH3_SUPPORT
  28545         case FT_SESSIONm:
  28546         case FT_SESSION_IPV6m:
  28547 #endif /* BCM_TRIUMPH3_SUPPORT */
  28548 #ifdef BCM_TRIDENT2_SUPPORT
  28549         case ING_VP_VLAN_MEMBERSHIPm:
  28550         case EGR_VP_VLAN_MEMBERSHIPm:
  28551         case ING_DNAT_ADDRESS_TYPEm:
  28552         case L2_ENDPOINT_IDm:
  28553         case ENDPOINT_QUEUE_MAPm:
  28554 #endif /* BCM_TRIDENT2_SUPPORT */
  28555 #ifdef BCM_ISM_SUPPORT
  28556             if (soc_feature(unit, soc_feature_ism_memory) &&
  28557                 soc_mem_is_mview(unit, mem)) {
  28558                 return _soc_mem_multi_hash_insert(unit, mem, copyno,
  28559                                                   entry_data, old_entry_data,
  28560                            soc_multi_hash_recurse_depth_get(unit, mem));
  28561             } else
  28562 #endif /* BCM_ISM_SUPPORT */
  28563             {
  28564                 return _soc_mem_dual_hash_insert(unit, mem, copyno,
  28565                                                  entry_data, old_entry_data,
  28566                            soc_dual_hash_recurse_depth_get(unit, mem));
  28567             }
  28568 #ifdef BCM_TRIUMPH3_SUPPORT
  28569         case EXT_L2_ENTRY_1m:
  28570         case EXT_L2_ENTRY_2m:
  28571             return soc_mem_generic_insert(unit, mem, copyno, -1,
  28572                                           entry_data, old_entry_data, NULL);
  28573 #endif /* BCM_TRIUMPH3_SUPPORT */
  28574 #ifdef BCM_ISM_SUPPORT
  28575         case L2_ENTRY_1m:
  28576         case L2_ENTRY_2m:
  28577         case L3_ENTRY_1m:
  28578         case L3_ENTRY_2m:
  28579         case L3_ENTRY_4m:
  28580         case VLAN_XLATE_EXTDm:
  28581         case MPLS_ENTRY_EXTDm:
  28582             return _soc_mem_multi_hash_insert(unit, mem, copyno,
  28583                                               entry_data, old_entry_data,
  28584                        soc_multi_hash_recurse_depth_get(unit, mem));
  28585 #endif /* BCM_ISM_SUPPORT */
  28586             break;
  28587         }
  28588     }
  28589 #endif
  28590     return SOC_E_UNAVAIL;
  28591 }
  28592 
  28593 /*
  28594  * Function:
  28595  *    _soc_mem_delete_index
  28596  * Purpose:
  28597  *    Helper function for soc_mem_delete and soc_mem_delete_index.
  28598  */
  28599 
  28600 STATIC int
  28601 _soc_mem_delete_index(int unit,
  28602                       soc_mem_t mem,        /* Assumes memory locked */
  28603                       int copyno,
  28604                       int del_index)
  28605 {
  28606     uint32        entry_tmp[SOC_MAX_MEM_WORDS];
  28607     int            min, index, eot_index, rv;
  28608 
  28609     /* eot_index points one past last entry in use */
  28610 
  28611     if (soc_mem_is_cam(unit, mem)) {
  28612         index = del_index;
  28613     } else {
  28614         min = soc_mem_index_min(unit, mem);
  28615         eot_index = soc_mem_index_last(unit, mem, copyno) + 1;
  28616 
  28617         if (del_index < min || del_index >= eot_index) {
  28618             return SOC_E_NOT_FOUND;
  28619         }
  28620 
  28621         for (index = del_index; index + 1 < eot_index; index++) {
  28622             /* Move down one entry */
  28623 
  28624             if ((rv = soc_mem_read(unit, mem, copyno,
  28625                                    index + 1, entry_tmp)) < 0) {
  28626                 LOG_ERROR(BSL_LS_SOC_SOCMEM,
  28627                           (BSL_META_U(unit,
  28628                                       "soc_mem_delete_index: "
  28629                                       "read %s.%s[%d] failed\n"),
  28630                            SOC_MEM_UFNAME(unit, mem),
  28631                            SOC_BLOCK_NAME(unit, copyno), index + 1));
  28632                 return rv;
  28633             }
  28634 
  28635             if ((rv = soc_mem_write(unit, mem, copyno,
  28636                                     index, entry_tmp)) < 0) {
  28637                 LOG_ERROR(BSL_LS_SOC_SOCMEM,
  28638                           (BSL_META_U(unit,
  28639                                       "soc_mem_delete_index: "
  28640                                       "write %s.%s[%d] failed\n"),
  28641                            SOC_MEM_UFNAME(unit, mem),
  28642                            SOC_BLOCK_NAME(unit, copyno), index));
  28643                 return rv;
  28644             }
  28645         }
  28646     }
  28647 
  28648     if ((rv = soc_mem_write(unit, mem, copyno, index,
  28649                             soc_mem_entry_null(unit, mem))) < 0) {
  28650         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  28651                   (BSL_META_U(unit,
  28652                               "soc_mem_delete_index: "
  28653                               "write %s.%s[%d] failed\n"),
  28654                    SOC_MEM_UFNAME(unit, mem),
  28655                    SOC_BLOCK_NAME(unit, copyno), index + 1));
  28656         return rv;
  28657     }
  28658     _SOC_MEM_REUSE_MEM_STATE(unit, mem);
  28659     SOP_MEM_STATE(unit, mem).count[copyno]--;
  28660 
  28661     return SOC_E_NONE;
  28662 }
  28663 
  28664 /*
  28665  * Function:
  28666  *    soc_mem_delete_index
  28667  * Purpose:
  28668  *    Delete an entry from a sorted table based on index,
  28669  *    moving up all successive entries.
  28670  * Notes:
  28671  *    If COPYNO_ALL is specified, the deletion is repeated for each
  28672  *    copy of the table.
  28673  *
  28674  *    For deletes from the ARL, reads the entry and requests hardware
  28675  *    deletion by key.  This shouldn't generally be done, because the
  28676  *    hardware may change the ARL table at any time.
  28677  */
  28678 
  28679 int
  28680 soc_mem_delete_index(int unit,
  28681                      soc_mem_t mem,
  28682                      int copyno,
  28683                      int index)
  28684 {
  28685     int rv = SOC_E_NONE;
  28686 
  28687     assert(soc_mem_is_sorted(unit, mem) ||
  28688            soc_mem_is_hashed(unit, mem) ||
  28689            soc_mem_is_cam(unit, mem) ||
  28690            soc_mem_is_cmd(unit, mem));
  28691 
  28692     DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE));
  28693 
  28694 #ifdef BCM_TRX_SUPPORT
  28695     if (soc_feature(unit, soc_feature_generic_table_ops)) {
  28696         uint32 entry_tmp[SOC_MAX_MEM_WORDS];
  28697         _SOC_MEM_REPLACE_MEM(unit, mem);
  28698         switch (mem) {
  28699         case L2Xm:
  28700         case L3_ENTRY_IPV4_UNICASTm:
  28701         case L3_ENTRY_IPV4_MULTICASTm:
  28702         case L3_ENTRY_IPV6_UNICASTm:
  28703         case L3_ENTRY_IPV6_MULTICASTm:
  28704         case EXACT_MATCH_2m:
  28705         case EXACT_MATCH_2_PIPE0m:
  28706         case EXACT_MATCH_2_PIPE1m:
  28707         case EXACT_MATCH_2_PIPE2m:
  28708         case EXACT_MATCH_2_PIPE3m:
  28709         case EXACT_MATCH_4m:
  28710         case EXACT_MATCH_4_PIPE0m:
  28711         case EXACT_MATCH_4_PIPE1m:
  28712         case EXACT_MATCH_4_PIPE2m:
  28713         case EXACT_MATCH_4_PIPE3m:
  28714         case EGR_VLAN_XLATEm:
  28715         case VLAN_XLATEm:
  28716 #if  defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  28717         case L3_ENTRY_SINGLEm:
  28718         case L3_ENTRY_DOUBLEm:
  28719         case L3_ENTRY_QUADm:
  28720         case VLAN_XLATE_1_SINGLEm:
  28721         case VLAN_XLATE_2_SINGLEm:
  28722         case VLAN_XLATE_1_DOUBLEm:
  28723         case VLAN_XLATE_2_DOUBLEm:
  28724         case EGR_VLAN_XLATE_1_SINGLEm:
  28725         case EGR_VLAN_XLATE_2_SINGLEm:
  28726         case EGR_VLAN_XLATE_1_DOUBLEm:
  28727         case EGR_VLAN_XLATE_2_DOUBLEm:
  28728         case MPLS_ENTRY_SINGLEm:
  28729         case SUBPORT_ID_TO_SGPP_MAPm:
  28730 #endif
  28731         case VLAN_MACm:
  28732         case MPLS_ENTRYm:
  28733         case AXP_WRX_WCDm:
  28734         case AXP_WRX_SVP_ASSIGNMENTm:
  28735 #ifdef BCM_TRIDENT2_SUPPORT
  28736         case ING_VP_VLAN_MEMBERSHIPm:
  28737         case EGR_VP_VLAN_MEMBERSHIPm:
  28738         case ING_DNAT_ADDRESS_TYPEm:
  28739         case L2_ENDPOINT_IDm:
  28740         case ENDPOINT_QUEUE_MAPm:
  28741 #endif /* BCM_TRIDENT2_SUPPORT */
  28742         case EXT_L2_ENTRYm:
  28743 #ifdef BCM_ISM_SUPPORT
  28744         case L2_ENTRY_1m:
  28745         case L2_ENTRY_2m:
  28746         case L3_ENTRY_1m:
  28747         case L3_ENTRY_2m:
  28748         case L3_ENTRY_4m:
  28749         case VLAN_XLATE_EXTDm:
  28750         case MPLS_ENTRY_EXTDm:
  28751 #endif /* BCM_ISM_SUPPORT */
  28752 #ifdef BCM_TRIUMPH3_SUPPORT
  28753         case EXT_L2_ENTRY_1m:
  28754         case EXT_L2_ENTRY_2m:
  28755         case FT_SESSIONm:
  28756         case FT_SESSION_IPV6m:
  28757 #endif /* BCM_TRIUMPH3_SUPPORT */
  28758 #if defined(BCM_KATANA2_SUPPORT)
  28759         case EGR_MP_GROUPm:
  28760 #endif
  28761 #ifdef BCM_SABER2_SUPPORT
  28762         case MP_GROUPm:
  28763 #endif
  28764             SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY,
  28765                                              index, entry_tmp));
  28766             return soc_mem_delete(unit, mem, copyno, entry_tmp);
  28767         default:
  28768             break;
  28769         }
  28770     }
  28771 #endif /* BCM_TRX_SUPPORT */
  28772 
  28773 #ifdef BCM_FIREBOLT_SUPPORT
  28774     if (SOC_IS_FBX(unit)) {
  28775         uint32 entry_tmp[SOC_MAX_MEM_WORDS];
  28776 
  28777         switch (mem) {
  28778         case L3_ENTRY_IPV4_UNICASTm:
  28779         case L3_ENTRY_IPV4_MULTICASTm:
  28780         case L3_ENTRY_IPV6_UNICASTm:
  28781         case L3_ENTRY_IPV6_MULTICASTm:
  28782         case L2Xm:
  28783         case VLAN_MACm:
  28784             SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY,
  28785                                              index, entry_tmp));
  28786             return soc_mem_delete(unit, mem, copyno, entry_tmp);
  28787         case L3_DEFIPm:
  28788         default:
  28789             return (SOC_E_UNAVAIL);
  28790         }
  28791     }
  28792 #endif /* BCM_FIREBOLT_SUPPORT */
  28793 
  28794     if (copyno != COPYNO_ALL){
  28795         assert(SOC_MEM_BLOCK_VALID(unit, mem, copyno));
  28796         MEM_LOCK(unit, mem);
  28797         rv = _soc_mem_delete_index(unit, mem, copyno, index);
  28798     }
  28799 
  28800     MEM_UNLOCK(unit, mem);
  28801 
  28802     return rv;
  28803 }
  28804 
  28805 /*
  28806  * Function:
  28807  *    soc_mem_delete
  28808  * Purpose:
  28809  *    Delete an entry from a sorted table based on key,
  28810  *    moving up all successive entries.
  28811  * Returns:
  28812  *    0 on success (whether or not entry was found),
  28813  *    SOC_E_XXX on read or write error.
  28814  * Notes:
  28815  *    A binary search for the key is performed.  If the key is found,
  28816  *    the entry is deleted by moving up successive entries until
  28817  *    the last entry is moved up.  The previously last entry is
  28818  *    overwritten with the null key.
  28819  *
  28820  *    If COPYNO_ALL is specified, the deletion is repeated for each copy
  28821  *    of the table.
  28822  */
  28823 
  28824 int
  28825 soc_mem_delete(int unit,
  28826                soc_mem_t mem,
  28827                int copyno,
  28828                void *key_data)
  28829 {
  28830     int            index, rv;
  28831     uint32        entry_tmp[SOC_MAX_MEM_WORDS];
  28832 #ifdef BCM_TRIDENT3_SUPPORT
  28833     soc_mem_t phy_mem;
  28834 #endif
  28835 
  28836 #ifdef BCM_TRIDENT3_SUPPORT
  28837     if (soc_feature(unit, soc_feature_flex_flow)) {
  28838         if (SOC_MEM_IS_VIEW(unit, mem)) {
  28839             rv = soc_mem_view_phy_mem_get(unit, mem, &phy_mem);
  28840             if (rv != SOC_E_NONE) {
  28841                 return rv;
  28842             }
  28843             mem = phy_mem;
  28844         }
  28845     }
  28846 #endif
  28847 
  28848     assert(soc_mem_is_sorted(unit, mem) ||
  28849            soc_mem_is_hashed(unit, mem) ||
  28850            soc_mem_is_cam(unit, mem) ||
  28851            soc_mem_is_cmd(unit, mem));
  28852     assert(key_data);
  28853 
  28854     DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, FALSE));
  28855 
  28856 #ifdef BCM_TRX_SUPPORT
  28857     if (soc_feature(unit, soc_feature_generic_table_ops)) {
  28858         int32 banks = 0;
  28859         _SOC_MEM_REPLACE_MEM(unit, mem);
  28860         switch (mem) {
  28861         case L2Xm:
  28862         case L3_ENTRY_IPV4_UNICASTm:
  28863         case L3_ENTRY_IPV4_MULTICASTm:
  28864         case L3_ENTRY_IPV6_UNICASTm:
  28865         case L3_ENTRY_IPV6_MULTICASTm:
  28866         case EXACT_MATCH_2m:
  28867         case EXACT_MATCH_2_PIPE0m:
  28868         case EXACT_MATCH_2_PIPE1m:
  28869         case EXACT_MATCH_2_PIPE2m:
  28870         case EXACT_MATCH_2_PIPE3m:
  28871         case EXACT_MATCH_4m:
  28872         case EXACT_MATCH_4_PIPE0m:
  28873         case EXACT_MATCH_4_PIPE1m:
  28874         case EXACT_MATCH_4_PIPE2m:
  28875         case EXACT_MATCH_4_PIPE3m:
  28876 #ifdef BCM_ISM_SUPPORT
  28877         case L2_ENTRY_1m:
  28878         case L2_ENTRY_2m:
  28879         case L3_ENTRY_1m:
  28880         case L3_ENTRY_2m:
  28881         case L3_ENTRY_4m:
  28882         case VLAN_XLATE_EXTDm:
  28883         case MPLS_ENTRY_EXTDm:
  28884 #endif /* BCM_ISM_SUPPORT */
  28885         case EGR_VLAN_XLATEm:
  28886         case VLAN_XLATEm:
  28887 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  28888         case L3_ENTRY_SINGLEm:
  28889         case L3_ENTRY_DOUBLEm:
  28890         case L3_ENTRY_QUADm:
  28891         case VLAN_XLATE_1_SINGLEm:
  28892         case VLAN_XLATE_2_SINGLEm:
  28893         case VLAN_XLATE_1_DOUBLEm:
  28894         case VLAN_XLATE_2_DOUBLEm:
  28895         case EGR_VLAN_XLATE_1_SINGLEm:
  28896         case EGR_VLAN_XLATE_2_SINGLEm:
  28897         case EGR_VLAN_XLATE_1_DOUBLEm:
  28898         case EGR_VLAN_XLATE_2_DOUBLEm:
  28899         case MPLS_ENTRY_SINGLEm:
  28900         case L3_TUNNEL_SINGLEm:
  28901         case SUBPORT_ID_TO_SGPP_MAPm:
  28902 #endif
  28903         case MPLS_ENTRYm:
  28904         /* passthru */
  28905         /* coverity[fallthrough: FALSE] */
  28906 #ifdef BCM_TRIUMPH3_SUPPORT
  28907         case AXP_WRX_WCDm:
  28908         case AXP_WRX_SVP_ASSIGNMENTm:
  28909         case EXT_L2_ENTRY_1m:
  28910         case EXT_L2_ENTRY_2m:
  28911         case FT_SESSIONm:
  28912         case FT_SESSION_IPV6m:
  28913 #endif /* BCM_TRIUMPH3_SUPPORT */
  28914         case VLAN_MACm:
  28915 #ifdef BCM_TRIDENT2_SUPPORT
  28916         case ING_VP_VLAN_MEMBERSHIPm:
  28917         case EGR_VP_VLAN_MEMBERSHIPm:
  28918         case ING_DNAT_ADDRESS_TYPEm:
  28919         case L2_ENDPOINT_IDm:
  28920         case ENDPOINT_QUEUE_MAPm:
  28921 #endif /* BCM_TRIDENT2_SUPPORT */
  28922 #if defined(BCM_KATANA2_SUPPORT)
  28923         case EGR_MP_GROUPm:
  28924 #endif
  28925 #ifdef BCM_SABER2_SUPPORT
  28926         case MP_GROUPm:
  28927 #endif
  28928         case EXT_L2_ENTRYm:
  28929 #ifdef BCM_HELIX5_SUPPORT
  28930             case FT_KEY_SINGLEm:
  28931             case FT_KEY_DOUBLEm:
  28932 #endif
  28933             if (soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) {
  28934                 banks = -1;
  28935             }
  28936             return soc_mem_generic_delete(unit, mem, MEM_BLOCK_ANY,
  28937                                           banks, key_data, NULL, 0);
  28938         default:
  28939             break;
  28940         }
  28941     }
  28942 #endif /* BCM_TRX_SUPPORT */
  28943 
  28944 #ifdef BCM_FIREBOLT_SUPPORT
  28945     if (SOC_IS_FBX(unit)) {
  28946         switch (mem) {
  28947         case L2Xm:
  28948             return soc_fb_l2x_delete(unit, key_data);
  28949 #if defined(INCLUDE_L3)
  28950         case L3_DEFIPm:
  28951         case L3_DEFIP_LEVEL1m:
  28952             return soc_fb_lpm_delete(unit, key_data);
  28953         case L3_ENTRY_IPV4_UNICASTm:
  28954         case L3_ENTRY_IPV4_MULTICASTm:
  28955         case L3_ENTRY_IPV6_UNICASTm:
  28956         case L3_ENTRY_IPV6_MULTICASTm:
  28957             return soc_fb_l3x_delete(unit, key_data);
  28958 #endif
  28959         case VLAN_MACm:
  28960             return soc_fb_vlanmac_entry_del(unit, key_data);
  28961         default:
  28962             break;
  28963         }
  28964     }
  28965 #endif /* BCM_FIREBOLT_SUPPORT */
  28966 
  28967     rv = SOC_E_NONE;
  28968     if (copyno == COPYNO_ALL) {
  28969         MEM_LOCK(unit, mem);
  28970         SOC_MEM_BLOCK_ITER(unit, mem, copyno) {
  28971             if ((rv = soc_mem_search(unit, mem, copyno,
  28972                                      &index, key_data, entry_tmp, 0)) < 0) {
  28973                 break;
  28974             }
  28975             if ((rv = soc_mem_delete_index(unit, mem, copyno, index)) < 0) {
  28976                 break;
  28977             }
  28978         }
  28979     } else {
  28980         assert(SOC_MEM_BLOCK_VALID(unit, mem, copyno));
  28981         MEM_LOCK(unit, mem);
  28982         rv = soc_mem_search(unit, mem, copyno, &index, key_data, entry_tmp, 0);
  28983         if (rv >= 0) {
  28984             rv = soc_mem_delete_index(unit, mem, copyno, index);
  28985         }
  28986     }
  28987 
  28988     MEM_UNLOCK(unit, mem);
  28989 
  28990     return rv;
  28991 }
  28992 
  28993 /*
  28994  * Function:
  28995  *      soc_mem_delete_return_old
  28996  * Purpose:
  28997  *      Same as soc_mem_delete() with the additional feature
  28998  *      that if an exiting entry was deleted, the old entry data
  28999  *      is returned back.
  29000  * Returns:
  29001  *      SOC_E_NONE - delete succeeded
  29002  *      SOC_E_UNAVAIL - not supported on the specified unit, mem
  29003  *      SOC_E_XXX - other error
  29004  */
  29005 int
  29006 soc_mem_delete_return_old(int unit,
  29007                           soc_mem_t mem,
  29008                           int copyno,
  29009                           void *key_data,
  29010                           void *old_entry_data)
  29011 {
  29012 #ifdef BCM_TRX_SUPPORT
  29013     if (SOC_IS_TRX(unit)) {
  29014         int32 banks = 0;
  29015         _SOC_MEM_REPLACE_MEM(unit, mem);
  29016         switch (mem) {
  29017         case MPLS_ENTRYm: /* Note: the order of the case statements should
  29018                                    be changed with care */
  29019             if (SOC_IS_SC_CQ(unit)) {
  29020                 break;
  29021             }
  29022         /* passthru */
  29023         /* coverity[fallthrough: FALSE] */
  29024         case L2Xm:
  29025         case L3_ENTRY_ONLYm:
  29026         case L3_ENTRY_IPV4_UNICASTm:
  29027         case L3_ENTRY_IPV4_MULTICASTm:
  29028         case L3_ENTRY_IPV6_UNICASTm:
  29029         case L3_ENTRY_IPV6_MULTICASTm:
  29030         case EXACT_MATCH_2m:
  29031         case EXACT_MATCH_2_PIPE0m:
  29032         case EXACT_MATCH_2_PIPE1m:
  29033         case EXACT_MATCH_2_PIPE2m:
  29034         case EXACT_MATCH_2_PIPE3m:
  29035         case EXACT_MATCH_4m:
  29036         case EXACT_MATCH_4_PIPE0m:
  29037         case EXACT_MATCH_4_PIPE1m:
  29038         case EXACT_MATCH_4_PIPE2m:
  29039         case EXACT_MATCH_4_PIPE3m:
  29040 #ifdef BCM_ISM_SUPPORT
  29041         case L2_ENTRY_1m:
  29042         case L2_ENTRY_2m:
  29043         case L3_ENTRY_1m:
  29044         case L3_ENTRY_2m:
  29045         case L3_ENTRY_4m:
  29046         case VLAN_XLATE_EXTDm:
  29047         case MPLS_ENTRY_EXTDm:
  29048 #endif /* BCM_ISM_SUPPORT */
  29049         case EGR_VLAN_XLATEm:
  29050         case VLAN_XLATEm:
  29051 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
  29052         case L3_ENTRY_SINGLEm:
  29053         case L3_ENTRY_DOUBLEm:
  29054         case L3_ENTRY_QUADm:
  29055         case MPLS_ENTRY_SINGLEm:
  29056 #endif
  29057 #ifdef BCM_TRIDENT3_SUPPORT
  29058         case VLAN_XLATE_1_SINGLEm:
  29059         case VLAN_XLATE_2_SINGLEm:
  29060         case VLAN_XLATE_1_DOUBLEm:
  29061         case VLAN_XLATE_2_DOUBLEm:
  29062         case EGR_VLAN_XLATE_1_SINGLEm:
  29063         case EGR_VLAN_XLATE_2_SINGLEm:
  29064         case EGR_VLAN_XLATE_1_DOUBLEm:
  29065         case EGR_VLAN_XLATE_2_DOUBLEm:
  29066         case SUBPORT_ID_TO_SGPP_MAPm:
  29067 #endif
  29068         /* passthru */
  29069         /* coverity[fallthrough: FALSE] */
  29070 #ifdef BCM_TRIUMPH3_SUPPORT
  29071         case AXP_WRX_WCDm:
  29072         case AXP_WRX_SVP_ASSIGNMENTm:
  29073         case EXT_L2_ENTRY_1m:
  29074         case EXT_L2_ENTRY_2m:
  29075         case FT_SESSIONm:
  29076         case FT_SESSION_IPV6m:
  29077 #endif /* BCM_TRIUMPH3_SUPPORT */
  29078         case VLAN_MACm:
  29079 #ifdef BCM_TRIDENT2_SUPPORT
  29080         case ING_VP_VLAN_MEMBERSHIPm:
  29081         case EGR_VP_VLAN_MEMBERSHIPm:
  29082         case ING_DNAT_ADDRESS_TYPEm:
  29083         case L2_ENDPOINT_IDm:
  29084         case ENDPOINT_QUEUE_MAPm:
  29085 #endif /* BCM_TRIDENT2_SUPPORT */
  29086 #ifdef BCM_TRIDENT2PLUS_SUPPORT
  29087             if (soc_feature(unit, soc_feature_td2p_a0_sw_war) &&
  29088                 ((mem == EGR_VLAN_XLATEm) || (mem == VLAN_XLATEm))) {
  29089                 int rv, index;
  29090                 rv = soc_mem_generic_lookup(unit, mem, copyno, banks, key_data,
  29091                                             old_entry_data, &index);
  29092                 if (rv == SOC_E_NONE) {
  29093                     rv = soc_mem_write(unit, mem, copyno, index,
  29094                                        soc_mem_entry_null(unit, mem));
  29095                 }
  29096                 return rv;
  29097             }
  29098 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
  29099             if (soc_feature(unit, soc_feature_ism_memory) && soc_mem_is_mview(unit, mem)) {
  29100                 banks = -1;
  29101             }
  29102             return soc_mem_generic_delete(unit, mem, MEM_BLOCK_ANY,
  29103                                           banks, key_data, old_entry_data, 0);
  29104         }
  29105     }
  29106 #endif
  29107     return SOC_E_UNAVAIL;
  29108 
  29109 }
  29110 
  29111 #if defined(BCM_TRX_SUPPORT)
  29112 /*
  29113  * Function:
  29114  *    _soc_mem_pop
  29115  * Purpose:
  29116  *    Helper function for soc_mem_pop.
  29117  */
  29118 STATIC int
  29119 _soc_mem_pop(int unit, soc_mem_t mem, int copyno, void *entry_data)
  29120 {
  29121     schan_msg_t schan_msg;
  29122     int         rv, entry_dw, allow_intr=0;
  29123     uint8       at;
  29124     int         src_blk, dst_blk, acc_type;
  29125     int         opcode, nack;
  29126     int         data_len = 0;
  29127 
  29128     assert(SOC_MEM_IS_VALID(unit, mem));
  29129     assert(soc_attached(unit));
  29130 
  29131     if (copyno == MEM_BLOCK_ANY) {
  29132         /* Overrun of "mem_block_any" is not possible as it is of MAX "mem" value NUM_SOC_MEM */
  29133         /* coverity[overrun-local : FALSE] */
  29134         copyno = SOC_MEM_BLOCK_ANY(unit, mem);
  29135     }
  29136     if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) {
  29137         LOG_WARN(BSL_LS_SOC_SOCMEM,
  29138                  (BSL_META_U(unit,
  29139                              "soc_mem_pop: invalid block %d for memory %s\n"),
  29140                   copyno, SOC_MEM_NAME(unit, mem)));
  29141         return SOC_E_PARAM;
  29142     }
  29143 
  29144     entry_dw = soc_mem_entry_words(unit, mem);
  29145 
  29146     schan_msg_clear(&schan_msg);
  29147     acc_type = SOC_MEM_ACC_TYPE(unit, mem);
  29148     src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit));
  29149     dst_blk = SOC_BLOCK2SCH(unit, copyno);
  29150 
  29151     schan_msg.gencmd.address = soc_mem_addr_get(unit, mem, 0, copyno, 0, &at);
  29152 
  29153 #ifdef BCM_TOMAHAWK3_SUPPORT
  29154     if (SOC_IS_TOMAHAWK3(unit)) {
  29155         data_len = 4;
  29156     }
  29157 #endif
  29158     soc_schan_header_cmd_set(unit, &schan_msg.header, FIFO_POP_CMD_MSG,
  29159                              dst_blk, src_blk, acc_type, data_len, 0, 0);
  29160 
  29161     if (SOC_IS_SAND(unit)) {
  29162         allow_intr = 1;
  29163     }
  29164 
  29165     /*
  29166      * Execute S-Channel "fifo pop" command packet consisting of
  29167      * (header word + address word), and read back
  29168      * (header word + entry_dw) data words.
  29169      */
  29170 
  29171     rv = soc_schan_op(unit, &schan_msg, 2, entry_dw + 1, allow_intr);
  29172 
  29173     /* Check result */
  29174     soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL,
  29175                                 NULL, NULL, &nack);
  29176     if (opcode != FIFO_POP_DONE_MSG) {
  29177         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  29178                   (BSL_META_U(unit,
  29179                               "soc_mem_pop: "
  29180                               "invalid S-Channel reply, expected FIFO_POP_DONE_MSG:\n")));
  29181         soc_schan_dump(unit, &schan_msg, entry_dw + 2);
  29182         return SOC_E_INTERNAL;
  29183     }
  29184 
  29185     if (rv == SOC_E_NONE) {
  29186         if (nack != 0) {
  29187             rv = SOC_E_NOT_FOUND;
  29188         } else {
  29189             sal_memcpy(entry_data, schan_msg.popresp.data, entry_dw * 4);
  29190         }
  29191     }
  29192 
  29193     if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) {
  29194         LOG_INFO(BSL_LS_SOC_SOCMEM,
  29195                  (BSL_META_U(unit,
  29196                              "Fifo pop: ")));
  29197         soc_mem_entry_dump(unit, mem, entry_data, BSL_INFO|BSL_LS_SOC_SOCMEM);
  29198     }
  29199 
  29200     return rv;
  29201 }
  29202 
  29203 
  29204 /*
  29205  * Function:
  29206  *    _soc_mem_push
  29207  * Purpose:
  29208  *    Helper function for soc_mem_push.
  29209  */
  29210 
  29211 STATIC int
  29212 _soc_mem_push(int unit, soc_mem_t mem, int copyno, void *entry_data)
  29213 {
  29214     schan_msg_t schan_msg;
  29215     int         rv, entry_dw, allow_intr=0;
  29216     uint8       at;
  29217     int         src_blk, dst_blk, acc_type, data_byte_len;
  29218     int         opcode, nack;
  29219 
  29220     assert(SOC_MEM_IS_VALID(unit, mem));
  29221     assert(soc_attached(unit));
  29222 
  29223     if (copyno == MEM_BLOCK_ANY) {
  29224         /* Overrun of "mem_block_any" is not possible as it is of MAX "mem" value NUM_SOC_MEM */
  29225         /* coverity[overrun-local : FALSE] */
  29226         copyno = SOC_MEM_BLOCK_ANY(unit, mem);
  29227     }
  29228     if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) {
  29229         LOG_WARN(BSL_LS_SOC_SOCMEM,
  29230                  (BSL_META_U(unit,
  29231                              "soc_mem_push: invalid block %d for memory %s\n"),
  29232                   copyno, SOC_MEM_NAME(unit, mem)));
  29233         return SOC_E_PARAM;
  29234     }
  29235 
  29236     entry_dw = soc_mem_entry_words(unit, mem);
  29237 
  29238     schan_msg_clear(&schan_msg);
  29239     acc_type = SOC_MEM_ACC_TYPE(unit, mem);
  29240     src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit));
  29241     dst_blk = SOC_BLOCK2SCH(unit, copyno);
  29242     data_byte_len = entry_dw * 4;
  29243 
  29244     schan_msg.gencmd.address = soc_mem_addr_get(unit, mem, 0, copyno, 0, &at);
  29245 
  29246     /* Fill in packet data */
  29247     sal_memcpy(schan_msg.pushcmd.data, entry_data, data_byte_len);
  29248 
  29249     soc_schan_header_cmd_set(unit, &schan_msg.header, FIFO_PUSH_CMD_MSG,
  29250                          dst_blk, src_blk, acc_type, 0, 0, 0);
  29251 
  29252     if(SOC_IS_SAND(unit)) {
  29253         allow_intr = 1;
  29254     }
  29255 
  29256     /*
  29257      * Execute S-Channel "fifo push" command packet consisting of
  29258      * (header word + address word + entry_dw), and read back
  29259      * (header word + entry_dw) data words.
  29260      */
  29261 
  29262     rv = soc_schan_op(unit, &schan_msg, entry_dw + 2, entry_dw + 1, allow_intr);
  29263 
  29264     /* Check result */
  29265     soc_schan_header_status_get(unit, &schan_msg.header, &opcode, NULL, NULL,
  29266                                 NULL, NULL, &nack);
  29267     if (opcode != FIFO_PUSH_DONE_MSG) {
  29268         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  29269                   (BSL_META_U(unit,
  29270                               "soc_mem_push: "
  29271                               "invalid S-Channel reply, expected FIFO_PUSH_DONE_MSG:\n")));
  29272         soc_schan_dump(unit, &schan_msg, entry_dw + 2);
  29273         return SOC_E_INTERNAL;
  29274     }
  29275 
  29276     if ((rv == SOC_E_NONE) && (nack != 0)) {
  29277         rv = SOC_E_FULL;
  29278     }
  29279 
  29280     if (bsl_check(bslLayerSoc, bslSourceSocmem, bslSeverityNormal, unit)) {
  29281         LOG_INFO(BSL_LS_SOC_SOCMEM,
  29282                  (BSL_META_U(unit,
  29283                              "Fifo push: ")));
  29284         soc_mem_entry_dump(unit, mem, entry_data, BSL_INFO|BSL_LS_SOC_SOCMEM);
  29285     }
  29286 
  29287     return rv;
  29288 }
  29289 
  29290 #endif /* defined(BCM_TRX_SUPPORT)  */
  29291 
  29292 #if defined(BCM_TRX_SUPPORT)
  29293 
  29294 static const struct {
  29295     soc_reg_t   cfg;
  29296     soc_reg_t   sbus_addr;
  29297     soc_reg_t   hostmem_addr;
  29298     soc_reg_t   read_ptr;
  29299     soc_reg_t   write_ptr;
  29300     soc_reg_t   threshold;
  29301     soc_field_t overflow_fld;
  29302     int         overflow_bit;
  29303 } _soc_mem_fifo_dma[] = {
  29304     {
  29305         CMIC_FIFO_CH0_RD_DMA_CFGr,
  29306         CMIC_FIFO_CH0_RD_DMA_SBUS_START_ADDRESSr,
  29307         CMIC_FIFO_CH0_RD_DMA_HOSTMEM_START_ADDRESSr,
  29308         CMIC_FIFO_CH0_RD_DMA_HOSTMEM_READ_PTRr,
  29309         CMIC_FIFO_CH0_RD_DMA_HOSTMEM_WRITE_PTRr,
  29310         CMIC_FIFO_CH0_RD_DMA_HOSTMEM_THRESHOLDr,
  29311         FIFO_CH0_DMA_HOSTMEM_OVERFLOWf,
  29312         0,
  29313     },
  29314     {
  29315         CMIC_FIFO_CH1_RD_DMA_CFGr,
  29316         CMIC_FIFO_CH1_RD_DMA_SBUS_START_ADDRESSr,
  29317         CMIC_FIFO_CH1_RD_DMA_HOSTMEM_START_ADDRESSr,
  29318         CMIC_FIFO_CH1_RD_DMA_HOSTMEM_READ_PTRr,
  29319         CMIC_FIFO_CH1_RD_DMA_HOSTMEM_WRITE_PTRr,
  29320         CMIC_FIFO_CH1_RD_DMA_HOSTMEM_THRESHOLDr,
  29321         FIFO_CH1_DMA_HOSTMEM_OVERFLOWf,
  29322         2,
  29323     },
  29324     {
  29325         CMIC_FIFO_CH2_RD_DMA_CFGr,
  29326         CMIC_FIFO_CH2_RD_DMA_SBUS_START_ADDRESSr,
  29327         CMIC_FIFO_CH2_RD_DMA_HOSTMEM_START_ADDRESSr,
  29328         CMIC_FIFO_CH2_RD_DMA_HOSTMEM_READ_PTRr,
  29329         CMIC_FIFO_CH2_RD_DMA_HOSTMEM_WRITE_PTRr,
  29330         CMIC_FIFO_CH2_RD_DMA_HOSTMEM_THRESHOLDr,
  29331         FIFO_CH2_DMA_HOSTMEM_OVERFLOWf,
  29332         4,
  29333     },
  29334     {
  29335         CMIC_FIFO_CH3_RD_DMA_CFGr,
  29336         CMIC_FIFO_CH3_RD_DMA_SBUS_START_ADDRESSr,
  29337         CMIC_FIFO_CH3_RD_DMA_HOSTMEM_START_ADDRESSr,
  29338         CMIC_FIFO_CH3_RD_DMA_HOSTMEM_READ_PTRr,
  29339         CMIC_FIFO_CH3_RD_DMA_HOSTMEM_WRITE_PTRr,
  29340         CMIC_FIFO_CH3_RD_DMA_HOSTMEM_THRESHOLDr,
  29341         FIFO_CH3_DMA_HOSTMEM_OVERFLOWf,
  29342         6,
  29343     },
  29344 };
  29345 STATIC int
  29346 _soc_mem_fifo_dma_start(int unit, int chan, soc_mem_t mem, int copyno,
  29347                         int host_entries, void *host_buf)
  29348 {
  29349     soc_control_t  *soc = SOC_CONTROL(unit);
  29350     soc_reg_t cfg_reg;
  29351     uint32 addr, rval, data_beats, sel, spacing;
  29352     uint8 at;
  29353 
  29354     if (chan < 0 || chan > 3 || host_buf == NULL) {
  29355         return SOC_E_PARAM;
  29356     }
  29357 
  29358     cfg_reg = _soc_mem_fifo_dma[chan].cfg;
  29359 
  29360     switch (host_entries) {
  29361     case 64:    sel = 0; break;
  29362     case 128:   sel = 1; break;
  29363     case 256:   sel = 2; break;
  29364     case 512:   sel = 3; break;
  29365     case 1024:  sel = 4; break;
  29366     case 2048:  sel = 5; break;
  29367     case 4096:  sel = 6; break;
  29368     case 8192:  sel = 7; break;
  29369     case 16384: sel = 8; break;
  29370     case 32768: sel = 9; break;
  29371     case 65536: sel = 10; break;
  29372     default:
  29373         return SOC_E_PARAM;
  29374     }
  29375 
  29376     if (mem != ING_IPFIX_EXPORT_FIFOm && mem != EGR_IPFIX_EXPORT_FIFOm &&
  29377         mem != EXT_L2_MOD_FIFOm && mem != L2_MOD_FIFOm ) {
  29378         return SOC_E_BADID;
  29379     }
  29380 
  29381     if (copyno == MEM_BLOCK_ANY) {
  29382         copyno = SOC_MEM_BLOCK_ANY(unit, mem);
  29383     }
  29384 
  29385     data_beats = soc_mem_entry_words(unit, mem);
  29386 
  29387     addr = soc_reg_addr(unit, _soc_mem_fifo_dma[chan].sbus_addr, REG_PORT_ANY,
  29388                         0);
  29389     rval = soc_mem_addr_get(unit, mem, 0, copyno, 0, &at);
  29390     soc_pci_write(unit, addr, rval);
  29391 
  29392     addr = soc_reg_addr(unit, _soc_mem_fifo_dma[chan].hostmem_addr,
  29393                         REG_PORT_ANY, 0);
  29394     rval = soc_cm_l2p(unit, host_buf);
  29395     soc_pci_write(unit, addr, rval);
  29396 
  29397     addr = soc_reg_addr(unit, _soc_mem_fifo_dma[chan].read_ptr, REG_PORT_ANY,
  29398                         0);
  29399     soc_pci_write(unit, addr, rval);
  29400 
  29401     addr = soc_reg_addr(unit, _soc_mem_fifo_dma[chan].threshold, REG_PORT_ANY,
  29402                         0);
  29403     rval = 0;
  29404     soc_reg_field_set(unit, _soc_mem_fifo_dma[chan].threshold, &rval, ADDRESSf,
  29405                       host_entries / 16 * data_beats * sizeof(uint32));
  29406     soc_pci_write(unit, addr, rval);
  29407 
  29408     addr = soc_reg_addr(unit, cfg_reg, REG_PORT_ANY, 0);
  29409     rval = 0;
  29410     soc_reg_field_set(unit, cfg_reg, &rval, BEAT_COUNTf, data_beats);
  29411     soc_reg_field_set(unit, cfg_reg, &rval, HOST_NUM_ENTRIES_SELf, sel);
  29412     soc_reg_field_set(unit, cfg_reg, &rval, TIMEOUT_COUNTf, 200);
  29413     if (soc_feature(unit, soc_feature_multi_sbus_cmds)) {
  29414         
  29415         if (soc->sbusCmdSpacing < 0) {
  29416             spacing = data_beats > 7 ? data_beats + 1 : 8;
  29417         } else {
  29418             spacing = soc->sbusCmdSpacing;
  29419         }
  29420         if ((SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_ESM) ||
  29421             (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_XQPORT) ||
  29422             (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_GXPORT) ||
  29423             (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_SPORT) ||
  29424             (SOC_BLOCK_TYPE(unit, copyno) == SOC_BLK_GPORT)) {
  29425             spacing = 0;
  29426         }
  29427         if (spacing) {
  29428             soc_reg_field_set(unit, cfg_reg, &rval,
  29429                               MULTIPLE_SBUS_CMD_SPACINGf, spacing);
  29430             soc_reg_field_set(unit, cfg_reg, &rval,
  29431                               ENABLE_MULTIPLE_SBUS_CMDSf, 1);
  29432         }
  29433     }
  29434     soc_pci_write(unit, addr, rval);
  29435 
  29436     soc_reg_field_set(unit, cfg_reg, &rval, ENABLEf, 1);
  29437     soc_reg_field_set(unit, cfg_reg, &rval, ENABLE_VALf, 1);
  29438     soc_pci_write(unit, addr, rval);
  29439 
  29440     return SOC_E_NONE;
  29441 }
  29442 
  29443 STATIC int
  29444 _soc_mem_fifo_dma_stop(int unit, int chan)
  29445 {
  29446     uint32 addr, rval;
  29447 
  29448     if (chan < 0 || chan > 3) {
  29449         return SOC_E_PARAM;
  29450     }
  29451 
  29452     addr = soc_reg_addr(unit, _soc_mem_fifo_dma[chan].cfg, REG_PORT_ANY, 0);
  29453     rval = 0;
  29454     soc_reg_field_set(unit, _soc_mem_fifo_dma[chan].cfg, &rval, ENABLEf, 1);
  29455     soc_pci_write(unit, addr, rval);
  29456 
  29457     return SOC_E_NONE;
  29458 }
  29459 
  29460 STATIC int
  29461 _soc_mem_fifo_dma_get_read_ptr(int unit, int chan, void **host_ptr, int *count)
  29462 {
  29463     soc_reg_t cfg_reg;
  29464     int host_entries, data_beats;
  29465     uint32 addr, rval, debug, hostmem_addr, read_ptr, write_ptr;
  29466 
  29467     if (chan < 0 || chan > 3 || host_ptr == NULL) {
  29468         return SOC_E_PARAM;
  29469     }
  29470 
  29471     /* read CFG reg first so that write pointer is valid later on */
  29472     cfg_reg = _soc_mem_fifo_dma[chan].cfg;
  29473     addr = soc_reg_addr(unit, cfg_reg, REG_PORT_ANY, 0);
  29474     soc_pci_getreg(unit, addr, &rval);
  29475 
  29476     addr = soc_reg_addr(unit, _soc_mem_fifo_dma[chan].read_ptr, REG_PORT_ANY,
  29477                         0);
  29478     soc_pci_getreg(unit, addr, &read_ptr);
  29479 
  29480     addr = soc_reg_addr(unit, _soc_mem_fifo_dma[chan].write_ptr, REG_PORT_ANY,
  29481                         0);
  29482     soc_pci_getreg(unit, addr, &write_ptr);
  29483 
  29484     if (write_ptr == 0 ||
  29485         (soc_feature(unit, soc_feature_fifo_dma_active) &&
  29486          !soc_reg_field_get(unit, cfg_reg, rval, ACTIVEf))) {
  29487         return SOC_E_EMPTY;
  29488     }
  29489 
  29490     if (read_ptr == write_ptr) {
  29491         addr = soc_reg_addr(unit, CMIC_FIFO_RD_DMA_DEBUGr, REG_PORT_ANY, 0);
  29492         soc_pci_getreg(unit, addr, &debug);
  29493         if (!soc_reg_field_get(unit, CMIC_FIFO_RD_DMA_DEBUGr,
  29494                                debug, _soc_mem_fifo_dma[chan].overflow_fld)) {
  29495             return SOC_E_EMPTY;
  29496         }
  29497         /* Re-read write pointer */
  29498         addr = soc_reg_addr(unit, _soc_mem_fifo_dma[chan].write_ptr,
  29499                             REG_PORT_ANY, 0);
  29500         soc_pci_getreg(unit, addr, &write_ptr);
  29501     }
  29502 
  29503     addr = soc_reg_addr(unit, _soc_mem_fifo_dma[chan].hostmem_addr,
  29504                         REG_PORT_ANY, 0);
  29505     soc_pci_getreg(unit, addr, &hostmem_addr);
  29506 
  29507     data_beats = soc_reg_field_get(unit, cfg_reg, rval, BEAT_COUNTf);
  29508     if (data_beats <= 0) {
  29509         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  29510                   (BSL_META_U(unit,
  29511                               "Invalid BEAT_COUNT (%d) in "
  29512                               "CMIC_FIFO_CH%d_RD_DMA_CFG \n"), data_beats, chan));
  29513         return SOC_E_CONFIG;
  29514     }
  29515 
  29516     switch (soc_reg_field_get(unit, cfg_reg, rval, HOST_NUM_ENTRIES_SELf)) {
  29517     case 0:  host_entries = 64;    break;
  29518     case 1:  host_entries = 128;   break;
  29519     case 2:  host_entries = 256;   break;
  29520     case 3:  host_entries = 512;   break;
  29521     case 4:  host_entries = 1024;  break;
  29522     case 5:  host_entries = 2048;  break;
  29523     case 6:  host_entries = 4096;  break;
  29524     case 7:  host_entries = 8192;  break;
  29525     case 8:  host_entries = 16384; break;
  29526     case 9:  host_entries = 32768; break;
  29527     case 10: host_entries = 65536; break;
  29528     default: return SOC_E_CONFIG;
  29529     }
  29530 
  29531     *host_ptr = soc_cm_p2l(unit, read_ptr);
  29532     if (read_ptr >= write_ptr) {
  29533         *count = host_entries -
  29534             (read_ptr - hostmem_addr) / data_beats / sizeof(uint32);
  29535     } else {
  29536         *count = (write_ptr - read_ptr) / data_beats / sizeof(uint32);
  29537     }
  29538 
  29539     if (SAL_BOOT_QUICKTURN) {
  29540         /* Delay to ensure PCI DMA tranfer to host memory completes */
  29541         sal_usleep(soc_mem_fifo_delay_value);
  29542     }
  29543     return (*count) ? SOC_E_NONE : SOC_E_EMPTY;
  29544 }
  29545 
  29546 STATIC int
  29547 _soc_mem_fifo_dma_advance_read_ptr(int unit, int chan, int count)
  29548 {
  29549     soc_reg_t cfg_reg;
  29550     int host_entries, data_beats;
  29551     uint32 addr, rval, debug;
  29552     uint32 *host_buf, *read_ptr;
  29553 
  29554     if (chan < 0 || chan > 3) {
  29555         return SOC_E_PARAM;
  29556     }
  29557 
  29558     cfg_reg = _soc_mem_fifo_dma[chan].cfg;
  29559 
  29560     addr = soc_reg_addr(unit, cfg_reg, REG_PORT_ANY, 0);
  29561     soc_pci_getreg(unit, addr, &rval);
  29562     data_beats = soc_reg_field_get(unit, cfg_reg, rval, BEAT_COUNTf);
  29563 
  29564     switch (soc_reg_field_get(unit, cfg_reg, rval, HOST_NUM_ENTRIES_SELf)) {
  29565     case 0:  host_entries = 64;    break;
  29566     case 1:  host_entries = 128;   break;
  29567     case 2:  host_entries = 256;   break;
  29568     case 3:  host_entries = 512;   break;
  29569     case 4:  host_entries = 1024;  break;
  29570     case 5:  host_entries = 2048;  break;
  29571     case 6:  host_entries = 4096;  break;
  29572     case 7:  host_entries = 8192;  break;
  29573     case 8:  host_entries = 16384; break;
  29574     case 9:  host_entries = 32768; break;
  29575     case 10: host_entries = 65536; break;
  29576     default: return SOC_E_CONFIG;
  29577     }
  29578 
  29579     if (count < 0 || count >= host_entries) {
  29580         return SOC_E_PARAM;
  29581     }
  29582 
  29583     /* Clear threshold overflow bit */
  29584     addr = soc_reg_addr(unit, CMIC_FIFO_RD_DMA_DEBUGr, REG_PORT_ANY, 0);
  29585     debug = 0;
  29586     soc_reg_field_set(unit, CMIC_FIFO_RD_DMA_DEBUGr,
  29587                       &debug, BIT_POSf, _soc_mem_fifo_dma[chan].overflow_bit);
  29588     soc_pci_write(unit, addr, debug);
  29589 
  29590     addr = soc_reg_addr(unit, _soc_mem_fifo_dma[chan].hostmem_addr,
  29591                         REG_PORT_ANY, 0);
  29592     soc_pci_getreg(unit, addr, &rval);
  29593     host_buf = soc_cm_p2l(unit, rval);
  29594 
  29595     addr = soc_reg_addr(unit, _soc_mem_fifo_dma[chan].read_ptr, REG_PORT_ANY,
  29596                         0);
  29597     soc_pci_getreg(unit, addr, &rval);
  29598     read_ptr = soc_cm_p2l(unit, rval);
  29599 
  29600     read_ptr += count * data_beats;
  29601     if (read_ptr >= &host_buf[host_entries * data_beats]) {
  29602         read_ptr -= host_entries * data_beats;
  29603     }
  29604     rval = soc_cm_l2p(unit, read_ptr);
  29605     soc_pci_write(unit, addr, rval);
  29606 
  29607     return SOC_E_NONE;
  29608 }
  29609 
  29610 #endif /* BCM_TRX_SUPPORT */
  29611 
  29612 /*
  29613  * Function:
  29614  *      soc_mem_pop
  29615  * Purpose:
  29616  *      Pop an entry from a FIFO.
  29617  * Parameters:
  29618  *      mem               Memory to search
  29619  *      copyno               Which copy to search (if multiple copies)
  29620  *      entry_data              OUT: Data if found
  29621  *                           CAN NO LONGER BE NULL.  Must be big enough
  29622  *                           to handle the appropriate data.
  29623  * Returns:
  29624  *    SOC_E_NOT_FOUND      Entry not found: Fifo is empty
  29625  *    SOC_E_NONE         Entry is found
  29626  *    SOC_E_XXX         If internal error occurs
  29627  */
  29628 
  29629 int
  29630 soc_mem_pop(int unit,
  29631             soc_mem_t mem,
  29632             int copyno,
  29633             void *entry_data)
  29634 {
  29635 #ifdef BCM_TRX_SUPPORT
  29636     if (soc_feature(unit, soc_feature_mem_push_pop)) {
  29637         switch (mem) {
  29638         case ING_IPFIX_EXPORT_FIFOm:
  29639         case EGR_IPFIX_EXPORT_FIFOm:
  29640         case EXT_L2_MOD_FIFOm:
  29641         case L2_MOD_FIFOm:
  29642 #ifdef BCM_TRIUMPH3_SUPPORT
  29643         case ING_SER_FIFOm:
  29644         case ING_SER_FIFO_Xm:
  29645         case ING_SER_FIFO_Ym:
  29646         case EGR_SER_FIFOm:
  29647         case EGR_SER_FIFO_Xm:
  29648         case EGR_SER_FIFO_Ym:
  29649         case ISM_SER_FIFOm:
  29650 #endif /* BCM_TRIUMPH3_SUPPORT */
  29651 #ifdef BCM_TOMAHAWK_SUPPORT
  29652             case ING_SER_FIFO_PIPE0m:
  29653             case ING_SER_FIFO_PIPE1m:
  29654             case ING_SER_FIFO_PIPE2m:
  29655             case ING_SER_FIFO_PIPE3m:
  29656             case EGR_SER_FIFO_PIPE0m:
  29657             case EGR_SER_FIFO_PIPE1m:
  29658             case EGR_SER_FIFO_PIPE2m:
  29659             case EGR_SER_FIFO_PIPE3m:
  29660             case L2_MGMT_SER_FIFOm:
  29661             case MMU_GCFG_MEM_FAIL_ADDR_64m:
  29662             case MMU_XCFG_MEM_FAIL_ADDR_64m:
  29663             case MMU_XCFG_MEM_FAIL_ADDR_64_XPE0m:
  29664             case MMU_XCFG_MEM_FAIL_ADDR_64_XPE1m:
  29665             case MMU_XCFG_MEM_FAIL_ADDR_64_XPE2m:
  29666             case MMU_XCFG_MEM_FAIL_ADDR_64_XPE3m:
  29667             case MMU_SCFG_MEM_FAIL_ADDR_64m:
  29668             case MMU_SCFG_MEM_FAIL_ADDR_64_SC0m:
  29669             case MMU_SCFG_MEM_FAIL_ADDR_64_SC1m:
  29670             case CENTRAL_CTR_EVICTION_FIFOm:
  29671 #endif /* BCM_TOMAHAWK_SUPPORT */
  29672 #ifdef BCM_TOMAHAWK2_SUPPORT
  29673         case MMU_SEDCFG_MEM_FAIL_ADDR_64_SC0m:
  29674         case MMU_SEDCFG_MEM_FAIL_ADDR_64_SC1m:
  29675 #endif /* BCM_TOMAHAWK2_SUPPORT */
  29676 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK2_SUPPORT)
  29677         case MMU_SEDCFG_MEM_FAIL_ADDR_64m:
  29678 #endif
  29679 #ifdef BCM_TOMAHAWK3_SUPPORT
  29680         case ING_SER_FIFO_PIPE4m:
  29681         case ING_SER_FIFO_PIPE5m:
  29682         case ING_SER_FIFO_PIPE6m:
  29683         case ING_SER_FIFO_PIPE7m:
  29684         case EGR_SER_FIFO_PIPE4m:
  29685         case EGR_SER_FIFO_PIPE5m:
  29686         case EGR_SER_FIFO_PIPE6m:
  29687         case EGR_SER_FIFO_PIPE7m:
  29688         case EDB_SER_FIFOm:
  29689         case EDB_SER_FIFO_PIPE0m:
  29690         case EDB_SER_FIFO_PIPE1m:
  29691         case EDB_SER_FIFO_PIPE2m:
  29692         case EDB_SER_FIFO_PIPE3m:
  29693         case EDB_SER_FIFO_PIPE4m:
  29694         case EDB_SER_FIFO_PIPE5m:
  29695         case EDB_SER_FIFO_PIPE6m:
  29696         case EDB_SER_FIFO_PIPE7m:
  29697         case EGR_SER_FIFO_2m:
  29698         case EGR_SER_FIFO_2_PIPE0m:
  29699         case EGR_SER_FIFO_2_PIPE1m:
  29700         case EGR_SER_FIFO_2_PIPE2m:
  29701         case EGR_SER_FIFO_2_PIPE3m:
  29702         case EGR_SER_FIFO_2_PIPE4m:
  29703         case EGR_SER_FIFO_2_PIPE5m:
  29704         case EGR_SER_FIFO_2_PIPE6m:
  29705         case EGR_SER_FIFO_2_PIPE7m:
  29706         case MMU_GLBCFG_MEM_FAIL_ADDR_64m:
  29707         case MMU_ITMCFG_MEM_FAIL_ADDR_64m:
  29708         case MMU_ITMCFG_MEM_FAIL_ADDR_64_ITM0m:
  29709         case MMU_ITMCFG_MEM_FAIL_ADDR_64_ITM1m:
  29710         case MMU_EBCFG_MEM_FAIL_ADDR_64m:
  29711         case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE0m:
  29712         case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE1m:
  29713         case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE2m:
  29714         case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE3m:
  29715         case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE4m:
  29716         case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE5m:
  29717         case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE6m:
  29718         case MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE7m:
  29719         case DLB_ECMP_SER_FIFOm:
  29720 #endif
  29721             return _soc_mem_pop(unit, mem, copyno, entry_data);
  29722         default:
  29723             return SOC_E_BADID;
  29724             break;
  29725         }
  29726     }
  29727 #endif /* BCM_TRX_SUPPORT */
  29728 
  29729     return SOC_E_UNAVAIL;
  29730 }
  29731 
  29732 /*
  29733  * Function:
  29734  *      soc_mem_push
  29735  * Purpose:
  29736  *      Push an entry to a FIFO.
  29737  * Parameters:
  29738  *      mem                  Memory to search
  29739  *      copyno               Which copy to search (if multiple copies)
  29740  *      entry_data           In: Data to be pushed
  29741  *
  29742  * Returns:
  29743  *      SOC_E_FULL           Fifo is full
  29744  *      SOC_E_NONE           Entry is pushed successfully
  29745  *      SOC_E_XXX            If internal error occurs
  29746  */
  29747 
  29748 int
  29749 soc_mem_push(int unit,
  29750              soc_mem_t mem,
  29751              int copyno,
  29752              void *entry_data)
  29753 {
  29754 #ifdef BCM_TRX_SUPPORT
  29755     if (soc_feature(unit, soc_feature_mem_push_pop)) {
  29756         switch (mem) {
  29757         case ING_IPFIX_EXPORT_FIFOm:
  29758         case EGR_IPFIX_EXPORT_FIFOm:
  29759         case EXT_L2_MOD_FIFOm:
  29760         case L2_MOD_FIFOm:
  29761             return _soc_mem_push(unit, mem, copyno, entry_data);
  29762         default:
  29763             return SOC_E_BADID;
  29764             break;
  29765         }
  29766     }
  29767 #endif /* BCM_TRX_SUPPORT */
  29768 
  29769     return SOC_E_UNAVAIL;
  29770 }
  29771 
  29772 int
  29773 soc_mem_fifo_dma_start(int unit, int chan, soc_mem_t mem, int copyno,
  29774                        int host_entries, void *host_buf)
  29775 {
  29776 #if defined(BCM_KATANA_SUPPORT) && defined(BCM_CMICM_SUPPORT)
  29777     if (SOC_IS_KATANA(unit) && soc_feature(unit, soc_feature_cmicm)) {
  29778         return _soc_mem_kt_fifo_dma_start(unit, chan, mem, copyno,
  29779                                           host_entries, host_buf);
  29780     }
  29781 #endif
  29782 #ifdef BCM_CMICX_SUPPORT
  29783     if (soc_feature(unit, soc_feature_cmicx) &&
  29784         soc_feature(unit, soc_feature_fifo_dma)) {
  29785         return soc_fifodma_start(unit, chan, TRUE, mem, 0, copyno, 0,
  29786                                             host_entries, host_buf);
  29787     }
  29788 #endif /* BCM_CMICX_SUPPORT */
  29789 #ifdef BCM_CMICM_SUPPORT
  29790     if (soc_feature(unit, soc_feature_cmicm)) {
  29791         return _soc_mem_sbus_fifo_dma_start(unit, chan, mem, copyno,
  29792                                             host_entries, host_buf);
  29793     }
  29794 #endif /* BCM_CMICM_SUPPORT */
  29795 #if defined(BCM_TRX_SUPPORT)
  29796     if (soc_feature(unit, soc_feature_fifo_dma)) {
  29797         return _soc_mem_fifo_dma_start(unit, chan, mem, copyno,
  29798                                        host_entries, host_buf);
  29799     }
  29800 #endif /* BCM_TRX_SUPPORT */
  29801 
  29802     return SOC_E_UNAVAIL;
  29803 }
  29804 
  29805 int
  29806 soc_mem_fifo_dma_stop(int unit, int chan)
  29807 {
  29808 #if defined(BCM_KATANA_SUPPORT) && defined(BCM_CMICM_SUPPORT)
  29809     if (SOC_IS_KATANA(unit) && soc_feature(unit, soc_feature_cmicm)) {
  29810         return _soc_mem_kt_fifo_dma_stop(unit, chan);
  29811     }
  29812 #endif
  29813 #ifdef BCM_CMICX_SUPPORT
  29814     if (soc_feature(unit, soc_feature_cmicx) &&
  29815         soc_feature(unit, soc_feature_fifo_dma)) {
  29816         return soc_fifodma_stop(unit, chan);
  29817     }
  29818 #endif /* BCM_CMICX_SUPPORT */
  29819 #ifdef BCM_CMICM_SUPPORT
  29820     if (soc_feature(unit, soc_feature_cmicm)) {
  29821         return _soc_mem_sbus_fifo_dma_stop(unit, chan);
  29822     }
  29823 #endif /* BCM_CMICM_SUPPORT */
  29824 #if defined(BCM_TRX_SUPPORT)
  29825     if (soc_feature(unit, soc_feature_fifo_dma)) {
  29826         return _soc_mem_fifo_dma_stop(unit, chan);
  29827     }
  29828 #endif /* BCM_TRX_SUPPORT */
  29829 
  29830     return SOC_E_UNAVAIL;
  29831 }
  29832 
  29833 int
  29834 soc_mem_fifo_dma_get_read_ptr(int unit, int chan, void **host_ptr, int *count)
  29835 {
  29836 
  29837 #if defined(BCM_HURRICANE2_SUPPORT) && defined(BCM_CMICM_SUPPORT)
  29838     if (soc_feature(unit, soc_feature_cmicm) &&
  29839             soc_feature(unit, soc_feature_fifo_dma_hu2)) {
  29840         return _soc_mem_hu2_fifo_dma_get_read_ptr(unit, chan, host_ptr, count);
  29841     }
  29842 #endif
  29843 #ifdef BCM_CMICX_SUPPORT
  29844     if (soc_feature(unit, soc_feature_cmicx) &&
  29845         soc_feature(unit, soc_feature_fifo_dma)) {
  29846         return soc_fifodma_get_read_ptr(unit, chan, host_ptr, count);
  29847     }
  29848 #endif /* BCM_CMICX_SUPPORT */
  29849 #if defined(BCM_KATANA_SUPPORT) && defined(BCM_CMICM_SUPPORT)
  29850     if (soc_feature(unit, soc_feature_cmicm)) {
  29851         return _soc_mem_kt_fifo_dma_get_read_ptr(unit, chan, host_ptr, count);
  29852     }
  29853 #endif
  29854 #if defined(BCM_TRX_SUPPORT)
  29855     if (soc_feature(unit, soc_feature_fifo_dma)) {
  29856         return _soc_mem_fifo_dma_get_read_ptr(unit, chan, host_ptr, count);
  29857     }
  29858 #endif /* BCM_TRX_SUPPORT */
  29859 
  29860     return SOC_E_UNAVAIL;
  29861 }
  29862 
  29863 int
  29864 soc_mem_fifo_dma_advance_read_ptr(int unit, int chan, int count)
  29865 {
  29866 
  29867 #if defined(BCM_HURRICANE2_SUPPORT) && defined(BCM_CMICM_SUPPORT)
  29868     if (soc_feature(unit, soc_feature_cmicm) && SOC_IS_HURRICANE2(unit)) {
  29869         return _soc_mem_hu2_fifo_dma_advance_read_ptr(unit, chan, count);
  29870     }
  29871 #endif
  29872 #ifdef BCM_CMICX_SUPPORT
  29873     if (soc_feature(unit, soc_feature_cmicx) &&
  29874         soc_feature(unit, soc_feature_fifo_dma)) {
  29875         return soc_fifodma_advance_read_ptr(unit, chan, count);
  29876     }
  29877 #endif /* BCM_CMICX_SUPPORT */
  29878 #if defined(BCM_KATANA_SUPPORT) && defined(BCM_CMICM_SUPPORT)
  29879     if (soc_feature(unit, soc_feature_cmicm)) {
  29880         return _soc_mem_kt_fifo_dma_advance_read_ptr(unit, chan, count);
  29881     }
  29882 #endif
  29883 #if defined(BCM_TRX_SUPPORT)
  29884     if (soc_feature(unit, soc_feature_fifo_dma)) {
  29885         return _soc_mem_fifo_dma_advance_read_ptr(unit, chan, count);
  29886     }
  29887 #endif /* BCM_TRX_SUPPORT */
  29888     return SOC_E_UNAVAIL;
  29889 }
  29890 
  29891 int
  29892 soc_mem_fifo_dma_get_num_entries(int unit, int chan, int *count)
  29893 {
  29894 #ifdef BCM_CMICM_SUPPORT
  29895     if (soc_feature(unit, soc_feature_cmicm)) {
  29896         return _soc_mem_sbus_fifo_dma_get_num_entries(unit, chan, count);
  29897     }
  29898 #endif /* BCM_CMICM_SUPPORT */
  29899     return SOC_E_UNAVAIL;
  29900 }
  29901 
  29902 int
  29903 soc_mem_fifo_dma_set_entries_read(int unit, int chan, uint32 num)
  29904 {
  29905 #ifdef BCM_CMICM_SUPPORT
  29906     if (soc_feature(unit, soc_feature_cmicm)) {
  29907         return _soc_mem_sbus_fifo_dma_set_entries_read(unit, chan, num);
  29908     }
  29909 #endif /* BCM_CMICM_SUPPORT */
  29910     return SOC_E_UNAVAIL;
  29911 }
  29912 
  29913 #ifdef BCM_XGS_SWITCH_SUPPORT
  29914 
  29915 /*
  29916  * Function:
  29917  *    soc_vlan_entries
  29918  * Purpose:
  29919  *    Return the number of entries in VLAN_TAB with the VALID bit set.
  29920  */
  29921 
  29922 STATIC int
  29923 soc_vlan_entries(int unit)
  29924 {
  29925     int            index_min, index_max, index;
  29926     vlan_tab_entry_t    ve;
  29927     int            total;
  29928 
  29929     index_min = soc_mem_index_min(unit, VLAN_TABm);
  29930     index_max = soc_mem_index_max(unit, VLAN_TABm);
  29931 
  29932     total = 0;
  29933 
  29934     for (index = index_min; index <= index_max; index++) {
  29935         SOC_IF_ERROR_RETURN
  29936             (soc_mem_read(unit, VLAN_TABm, MEM_BLOCK_ANY, index, &ve));
  29937 
  29938         total += soc_VLAN_TABm_field32_get(unit, &ve, VALIDf);
  29939     }
  29940 
  29941     return total;
  29942 }
  29943 
  29944 #endif /* BCM_XGS_SWITCH_SUPPORT */
  29945 
  29946 /*
  29947  * Function:
  29948  *    soc_mem_entries
  29949  * Purpose:
  29950  *    Return the number of entries in a sorted table.
  29951  * Notes:
  29952  *    Performs special functions for some tables.
  29953  */
  29954 
  29955 int
  29956 soc_mem_entries(int unit,
  29957                 soc_mem_t mem,
  29958                 int copyno)
  29959 {
  29960     int            entries = 0;
  29961     assert(SOC_MEM_IS_VALID(unit, mem));
  29962     assert(soc_attached(unit));
  29963     assert(soc_mem_is_sorted(unit, mem) ||
  29964            soc_mem_is_hashed(unit, mem) ||
  29965            soc_mem_is_cam(unit, mem) ||
  29966            soc_mem_is_cmd(unit, mem) ||
  29967            mem == VLAN_TABm);
  29968     if (copyno == MEM_BLOCK_ANY) {
  29969         /* Overrun of "mem_block_any" is not possible as it is of MAX "mem" value NUM_SOC_MEM */
  29970         /* coverity[overrun-local : FALSE] */
  29971         copyno = SOC_MEM_BLOCK_ANY(unit, mem);
  29972     }
  29973     if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) {
  29974         LOG_WARN(BSL_LS_SOC_SOCMEM,
  29975                  (BSL_META_U(unit,
  29976                              "soc_mem_entries: invalid block %d for memory %s\n"),
  29977                   copyno, SOC_MEM_NAME(unit, mem)));
  29978         return SOC_E_PARAM;
  29979     }
  29980 
  29981     switch (mem) {
  29982 #ifdef BCM_XGS_SWITCH_SUPPORT
  29983     case VLAN_TABm:
  29984         entries = soc_vlan_entries(unit);    /* Warning: very slow */
  29985         break;
  29986 #endif
  29987 
  29988     default:
  29989         _SOC_MEM_REUSE_MEM_STATE(unit, mem);
  29990         entries = SOP_MEM_STATE(unit, mem).count[copyno];
  29991         break;
  29992     }
  29993 
  29994     return entries;
  29995 }
  29996 
  29997 /*
  29998  * Function:
  29999  *    soc_mem_debug_set
  30000  * Purpose:
  30001  *    Enable or disable MMU debug mode.
  30002  * Returns:
  30003  *    Previous enable state, or SOC_E_XXX on error.
  30004  */
  30005 
  30006 int
  30007 soc_mem_debug_set(int unit, int enable)
  30008 {
  30009     schan_msg_t schan_msg;
  30010     int    msg, rv = SOC_E_NONE, old_enable, allow_intr=0;
  30011     int    dst_blk, src_blk;
  30012 
  30013     old_enable = SOC_PERSIST(unit)->debugMode;
  30014 
  30015     if (enable && !old_enable) {
  30016         msg = ENTER_DEBUG_MODE_MSG;
  30017     } else if (!enable && old_enable) {
  30018         msg = EXIT_DEBUG_MODE_MSG;
  30019     } else {
  30020         msg = -1;
  30021     }
  30022 
  30023     if (msg >= 0) {
  30024         schan_msg_clear(&schan_msg);
  30025 
  30026         dst_blk = SOC_BLOCK2SCH(unit, MMU_BLOCK(unit));
  30027         src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit));
  30028 
  30029         soc_schan_header_cmd_set(unit, &schan_msg.header, msg, dst_blk,
  30030                                  src_blk, 0, 0, 0, 0);
  30031 
  30032         if (SOC_IS_SAND(unit)) {
  30033             allow_intr = 1;
  30034         }
  30035 
  30036         if ((rv = soc_schan_op(unit, &schan_msg, 1, 0, allow_intr)) >= 0) {
  30037             SOC_PERSIST(unit)->debugMode = enable;
  30038         }
  30039 
  30040         if (!enable) {
  30041             /* Allow packet transfers in progress to drain */
  30042             sal_usleep(100000);
  30043         }
  30044     }
  30045 
  30046     return (rv < 0) ? rv : old_enable;
  30047 }
  30048 
  30049 /*
  30050  * Function:
  30051  *    soc_mem_debug_get
  30052  * Purpose:
  30053  *    Return current MMU debug mode status
  30054  */
  30055 
  30056 int
  30057 soc_mem_debug_get(int unit, int *enable)
  30058 {
  30059     *enable = SOC_PERSIST(unit)->debugMode;
  30060     return SOC_E_NONE;
  30061 }
  30062 
  30063 /*
  30064  * Function:
  30065  *    soc_mem_iterate
  30066  * Purpose:
  30067  *    Iterate over all the valid memories and call user
  30068  *    passed callback function (do_it) for each valid memory.
  30069  */
  30070 int
  30071 soc_mem_iterate(int unit, soc_mem_iter_f do_it, void *data)
  30072 {
  30073     soc_mem_t mem, mem_iter;
  30074     int       rv = SOC_E_NONE;
  30075 
  30076     if (!do_it) {
  30077         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  30078                   (BSL_META_U(unit,
  30079                               "soc_mem_iterate: Callback function is NULL")));
  30080         return SOC_E_PARAM;
  30081     }
  30082 
  30083     for (mem_iter = 0; mem_iter < NUM_SOC_MEM; mem_iter++) {
  30084         mem = mem_iter;
  30085         _SOC_MEM_REPLACE_MEM(unit, mem);
  30086         if (!SOC_MEM_IS_VALID(unit, mem)) {
  30087             continue;
  30088         }
  30089 
  30090 #if defined(BCM_HAWKEYE_SUPPORT)
  30091         if (SOC_IS_HAWKEYE(unit) && (soc_mem_index_max(unit, mem) <= 0)) {
  30092             continue;
  30093         }
  30094 #endif /* BCM_HAWKEYE_SUPPORT */
  30095 
  30096         /*
  30097          * Call user provided callback function.
  30098          */
  30099         if ((rv = do_it(unit, mem, data)) < 0) {
  30100             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  30101                       (BSL_META_U(unit,
  30102                                   "soc_mem_iterate: Failed on memory (%s)\n"),
  30103                        SOC_MEM_NAME(unit, mem)));
  30104            /* break; */
  30105         }
  30106     }
  30107     return rv;
  30108 }
  30109 
  30110 #ifdef BCM_CMICM_SUPPORT
  30111 /*
  30112  * Function:   soc_host_ccm_copy
  30113  * Purpose:    Copy a range of memory from one host location to another
  30114  *             Primarily for Cross-Coupled Memories.
  30115  * Parameters:
  30116  *       unit      - (IN) SOC unit number.
  30117  *       srcbuf   - (IN) Source Buffer.
  30118  *       dstbuf   - (IN) Destination Buffer.
  30119  *       count    - (IN) Number of dwords to transfer.
  30120  *       flags    - (IN)
  30121  *                  0x01  Source and destination endian to be changed.
  30122  *                  0x02  Source is PCI
  30123  * Returns:
  30124  *       SOC_E_XXX
  30125  */
  30126 int
  30127 soc_host_ccm_copy(int unit, void *srcbuf, void *dstbuf,
  30128                   int count, int flags)
  30129 {
  30130     int rv;
  30131 
  30132     rv = soc_host_ccm_copy_multi_cmc(unit, srcbuf, dstbuf,
  30133                                      count, flags, SOC_PCI_CMC(unit));
  30134     return rv;
  30135 }
  30136 
  30137 /*
  30138  * Function:   soc_host_ccm_copy_multi_cmc
  30139  * Purpose:    Copy a range of memory from one host location to another
  30140  *             Primarily for Cross-Coupled Memories.
  30141  *             With multiple CMC/channel support
  30142  * Parameters:
  30143  *       unit      - (IN) SOC unit number.
  30144  *       srcbuf   - (IN) Source Buffer.
  30145  *       dstbuf   - (IN) Destination Buffer.
  30146  *       count    - (IN) Number of dwords to transfer.
  30147  *       flags    - (IN)
  30148  *                  0x01  Source and destination endian to be changed.
  30149  *                  0x02  Source is PCI
  30150  *       cmc      - (IN) CMC to be used.
  30151  * Returns:
  30152  *       SOC_E_XXX
  30153  */
  30154 int
  30155 soc_host_ccm_copy_multi_cmc(int unit, void *srcbuf, void *dstbuf,
  30156                             int count, int flags, int cmc)
  30157 {
  30158     int i, rv;
  30159     soc_control_t *soc = SOC_CONTROL(unit);
  30160     uint32 *srcptr = (uint32 *)srcbuf;
  30161     uint32 *dstptr = (uint32 *)dstbuf;
  30162     uint32 reg, reg2;
  30163     assert (srcptr && dstptr);
  30164 
  30165     if (SOC_CONTROL(unit)->ccmDmaMutex[cmc] == 0) {
  30166         /* If DMA not enabled, or short length use PIO to copy */
  30167         for (i = 0; i < count; i ++ ) {
  30168             if (flags & 2) {            /* Read from PCI */
  30169                 reg = soc_pci_mcs_read(unit, PTR_TO_INT(srcptr));
  30170             } else {
  30171                 reg = *srcptr;
  30172             }
  30173 
  30174             if (flags & 1) {
  30175                 reg = ((reg & 0xff000000) >> 24) |
  30176                     ((reg & 0x00ff0000) >> 8) |
  30177                     ((reg & 0x0000ff00) << 8) |
  30178                     ((reg & 0x000000ff) << 24);
  30179             }
  30180 
  30181             if (flags & 2) {
  30182                 *dstptr = reg;
  30183             } else {
  30184                 soc_pci_mcs_write(unit, PTR_TO_INT(dstptr), reg);
  30185                 reg2 = soc_pci_mcs_read(unit, PTR_TO_INT(dstptr));
  30186                 if (reg2 != reg) {
  30187                     LOG_ERROR(BSL_LS_SOC_SOCMEM,
  30188                               (BSL_META_U(unit,
  30189                                           "ccm_dma: compare error %x (%x %x)\n"),
  30190                                PTR_TO_INT(dstptr), reg, reg2));
  30191                 }
  30192             }
  30193 
  30194             dstptr++;
  30195             srcptr++;
  30196         }
  30197         return SOC_E_NONE;
  30198     }
  30199 
  30200     CCM_DMA_LOCK(unit, cmc);
  30201 
  30202     soc_pci_write(unit, CMIC_CMCx_CCM_DMA_HOST0_MEM_START_ADDR_OFFSET(cmc), soc_cm_l2p(unit, srcbuf));
  30203     soc_pci_write(unit, CMIC_CMCx_CCM_DMA_HOST1_MEM_START_ADDR_OFFSET(cmc), soc_cm_l2p(unit, dstbuf));
  30204     soc_pci_write(unit, CMIC_CMCx_CCM_DMA_ENTRY_COUNT_OFFSET(cmc), count);
  30205     /* Keep endianess default... */
  30206     reg = soc_pci_read(unit, CMIC_CMCx_CCM_DMA_CFG_OFFSET(cmc));
  30207     soc_reg_field_set(unit, CMIC_CMC0_CCM_DMA_CFGr, &reg, ABORTf, 0);
  30208     soc_reg_field_set(unit, CMIC_CMC0_CCM_DMA_CFGr, &reg, ENf, 0);
  30209     soc_pci_write(unit, CMIC_CMCx_CCM_DMA_CFG_OFFSET(cmc), reg);  /* Clearing EN clears stats */
  30210     /* Start DMA */
  30211     soc_reg_field_set(unit, CMIC_CMC0_CCM_DMA_CFGr, &reg, ENf, 1);
  30212     soc_pci_write(unit, CMIC_CMCx_CCM_DMA_CFG_OFFSET(cmc), reg);
  30213 
  30214     rv = SOC_E_TIMEOUT;
  30215     if (soc->ccmDmaIntrEnb) {
  30216             (void)soc_cmicm_cmcx_intr0_enable(unit, cmc, IRQ_CMCx_CCMDMA_DONE);
  30217             if (sal_sem_take(soc->ccmDmaIntr[cmc], soc->ccmDmaTimeout) < 0) {
  30218                 rv = SOC_E_TIMEOUT;
  30219             }
  30220            (void)soc_cmicm_cmcx_intr0_disable(unit, cmc, IRQ_CMCx_CCMDMA_DONE);
  30221 
  30222             reg = soc_pci_read(unit, CMIC_CMCx_CCM_DMA_STAT_OFFSET(cmc));
  30223             if (soc_reg_field_get(unit, CMIC_CMC0_CCM_DMA_STATr,
  30224                                                         reg, DONEf)) {
  30225                 rv = SOC_E_NONE;
  30226                 if (soc_reg_field_get(unit, CMIC_CMC0_CCM_DMA_STATr,
  30227                                                         reg, ERRORf)) {
  30228                     rv = SOC_E_FAIL;
  30229                 }
  30230             }
  30231     } else {
  30232         soc_timeout_t to;
  30233         LOG_WARN(BSL_LS_SOC_SOCMEM,
  30234                  (BSL_META_U(unit,
  30235                              "using Polling mode for CCM DMA\n")));
  30236         soc_timeout_init(&to, soc->ccmDmaTimeout, 10000);
  30237         do {
  30238             reg = soc_pci_read(unit, CMIC_CMCx_CCM_DMA_STAT_OFFSET(cmc));
  30239             if (soc_reg_field_get(unit, CMIC_CMC0_CCM_DMA_STATr,
  30240                                                     reg, DONEf)) {
  30241                 rv = SOC_E_NONE;
  30242                 if (soc_reg_field_get(unit, CMIC_CMC0_CCM_DMA_STATr,
  30243                                                     reg, ERRORf)) {
  30244                     rv = SOC_E_FAIL;
  30245                 }
  30246                 break;
  30247             }
  30248         } while(!(soc_timeout_check(&to)));
  30249     }
  30250 
  30251     if (rv == SOC_E_TIMEOUT) {
  30252         LOG_ERROR(BSL_LS_SOC_SOCMEM,
  30253                   (BSL_META_U(unit,
  30254                               "CcmDmaTimeout: unit %d, ccm_dma timeout\n"), unit));
  30255 
  30256         /* Abort CCM DMA */
  30257 
  30258         /* Dummy read to allow abort to finish */
  30259 
  30260         /* Disable CCM DMA */
  30261 
  30262         /* Clear ccm DMA abort bit */
  30263     }
  30264 
  30265     CCM_DMA_UNLOCK(unit, cmc);
  30266     return rv;
  30267 }
  30268 #endif
  30269 
  30270 /*
  30271  * @name   - _soc_l3_defip_urpf_index_remap
  30272  * @param  - unit: unit number
  30273  * @param  - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128
  30274  * @param  - index: Physical index
  30275  *
  30276  * @purpose - Remap physical index to logical index
  30277  */
  30278 STATIC int
  30279 _soc_l3_defip_urpf_index_remap(int unit, int wide, int index)
  30280 {
  30281     int new_index = index;
  30282     int num_tcams = 0;
  30283     int tcam_size = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit);
  30284     int entries_left_in_paired_tcam = 0;
  30285     int soc_defip_index_remap = SOC_L3_DEFIP_INDEX_REMAP_GET(unit) / 2;
  30286     int half_defip_size;
  30287     int max_tcams = SOC_L3_DEFIP_MAX_TCAMS_GET(unit);
  30288     int half_defip_index = (max_tcams * tcam_size) /2;
  30289 
  30290     if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) {
  30291         half_defip_size = soc_mem_index_count(unit, L3_DEFIP_LEVEL1m) / 2;
  30292     } else {
  30293         half_defip_size = soc_mem_index_count(unit, L3_DEFIPm) / 2;
  30294     }
  30295 
  30296     if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) {
  30297         return index;
  30298     }
  30299 
  30300     assert(tcam_size);
  30301 
  30302     if (wide == 0) {
  30303         num_tcams = soc_defip_index_remap / tcam_size;
  30304         entries_left_in_paired_tcam = tcam_size -
  30305             (soc_defip_index_remap % tcam_size);
  30306         new_index = index - (num_tcams * 2 * tcam_size);
  30307 
  30308         if (new_index >= half_defip_index) {
  30309             new_index = new_index - half_defip_index;
  30310         }
  30311 
  30312         if (new_index - (soc_defip_index_remap % tcam_size) <
  30313             entries_left_in_paired_tcam) {
  30314             new_index = new_index - (soc_defip_index_remap % tcam_size);
  30315         } else {
  30316             new_index = new_index - ((soc_defip_index_remap % tcam_size) * 2);
  30317         }
  30318 
  30319         if (index >= half_defip_index) {
  30320             new_index = new_index + half_defip_size;
  30321         }
  30322         return new_index;
  30323     }
  30324 
  30325     new_index = index;
  30326     if (index >= (half_defip_index / 2)) {
  30327         new_index = index - (half_defip_index / 2) + soc_defip_index_remap;
  30328     }
  30329     return new_index;
  30330 }
  30331 
  30332 /*
  30333  * @name   - soc_l3_defip_urpf_index_remap
  30334  * @param  - unit: unit number
  30335  * @param  - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128
  30336  * @param  - index: Physical index
  30337  *
  30338  * @purpose - Remap physical index to logical index
  30339  */
  30340 int
  30341 soc_l3_defip_urpf_index_remap(int unit, int wide, int index)
  30342 {
  30343     if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) {
  30344         return index;
  30345     }
  30346 
  30347     assert(SOC_L3_DEFIP_INDEX_INIT(unit));
  30348     if (wide == 0) {
  30349         return SOC_L3_DEFIP_URPF_PHY_TO_LOG_INDEX(unit, index);
  30350     }
  30351     return SOC_L3_DEFIP_PAIR_URPF_PHY_TO_LOG_INDEX(unit, index);
  30352 }
  30353 
  30354 /*
  30355  * @name   - _soc_l3_defip_index_remap
  30356  * @param  - unit: unit number
  30357  * @param  - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128
  30358  * @param  - index: Physical index
  30359  *
  30360  * @purpose - Remap physical index to logical index
  30361  */
  30362 
  30363 STATIC int
  30364 _soc_l3_defip_index_remap(int unit, int wide, int index)
  30365 {
  30366     int new_index = index;
  30367     int num_tcams = 0;
  30368     int tcam_size = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit);
  30369     int entries_left_in_paired_tcam = 0;
  30370     int soc_defip_index_remap = SOC_L3_DEFIP_INDEX_REMAP_GET(unit);
  30371 
  30372     if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) {
  30373         return index;
  30374     }
  30375 
  30376     assert(tcam_size);
  30377 
  30378     if (wide == 0) {
  30379         if (soc_feature(unit, soc_feature_l3_1k_defip_table)) {
  30380             num_tcams = soc_defip_index_remap > 0 ? 1 : 0;
  30381             new_index = index - num_tcams * 2 * tcam_size;
  30382         } else {
  30383         num_tcams = soc_defip_index_remap / tcam_size;
  30384         entries_left_in_paired_tcam = tcam_size -
  30385             (soc_defip_index_remap % tcam_size);
  30386         if (index - (num_tcams * 2 * tcam_size) -
  30387             (soc_defip_index_remap % tcam_size) < entries_left_in_paired_tcam) {
  30388             new_index = index - (num_tcams * 2 * tcam_size) -
  30389                         (soc_defip_index_remap % tcam_size);
  30390         } else {
  30391             new_index = index - (num_tcams * 2 * tcam_size) -
  30392                         ((soc_defip_index_remap % tcam_size) * 2);
  30393         }
  30394         }
  30395         return new_index;
  30396     }
  30397     return new_index;
  30398 }
  30399 
  30400 /*
  30401  * @name   - _soc_th3_l3_defip_index_remap
  30402  * @param  - unit: unit number
  30403  * @param  - wide: 0 - L3_DEFIP_LEVEL1, 1 - L3_DEFIP_PAIR_LEVEL1
  30404  * @param  - index: Physical index
  30405  *
  30406  * @purpose - Remap physical index to logical index
  30407  *          - (Only for TH3 ALPM2 Parallel/Mix IPv6-128b modes)
  30408  *                       -------------- 0
  30409  * L3_DEFIP_PAIR_LEVEL1  |  DB0 (v6)  |     BLOCK_0 (TCAM0/1)
  30410  *                       |------------| Private
  30411  *      L3_DEFIP_LEVEL1  |  DB0 (v4)  |     BLOCK_1 (TCAM2/3)
  30412  *                       |------------|
  30413  * L3_DEFIP_PAIR_LEVEL1  |  DB1 (v6)  |     BLOCK_2 (TCAM4/5)
  30414  *                       |------------| Public
  30415  *      L3_DEFIP_LEVEL1  |  DB1 (v4)  |     BLOCK_3 (TCAM6/7)
  30416  *                       -------------- 1023
  30417  */
  30418 
  30419 STATIC int
  30420 _soc_th3_l3_defip_index_remap(int unit, int wide, int index)
  30421 {
  30422     int new_index;
  30423     int num_tcams;
  30424     int tcam_size = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit);
  30425     int entries_left_in_paired_tcam;
  30426     int entries_left_in_tcam;
  30427     int soc_defip_index_remap = SOC_L3_DEFIP_INDEX_REMAP_GET(unit);
  30428     /* DB0: Private, DB1: Public */
  30429     int per_db_pair_entries = soc_defip_index_remap / 2;
  30430 
  30431     num_tcams = per_db_pair_entries / tcam_size;
  30432     entries_left_in_paired_tcam = tcam_size - (per_db_pair_entries % tcam_size);
  30433     entries_left_in_tcam = 2 * tcam_size - per_db_pair_entries;
  30434 
  30435     if (wide == 0) {
  30436         if (index - (num_tcams * 2 * tcam_size) -
  30437             (per_db_pair_entries % tcam_size) < entries_left_in_paired_tcam) {
  30438             new_index = index - (num_tcams * 2 * tcam_size) -
  30439                         (per_db_pair_entries % tcam_size);
  30440         } else if (index - (num_tcams * 2 * tcam_size) -
  30441             2 * (per_db_pair_entries % tcam_size) < 2 * entries_left_in_tcam) {
  30442             new_index = index - (num_tcams * 2 * tcam_size) -
  30443                         2 * (per_db_pair_entries % tcam_size);
  30444         } else if (index - 2 * (num_tcams * 2 * tcam_size) -
  30445             3 * (per_db_pair_entries % tcam_size) <
  30446             2 * entries_left_in_tcam + entries_left_in_paired_tcam) {
  30447             new_index = index - 2 * (num_tcams * 2 * tcam_size) -
  30448                         3 * (per_db_pair_entries % tcam_size);
  30449         } else {
  30450             new_index = index - 2 * (num_tcams * 2 * tcam_size) -
  30451                         4 * (per_db_pair_entries % tcam_size);
  30452         }
  30453     } else { /* wide = 1 */
  30454         if (index < per_db_pair_entries) {
  30455             new_index = index;
  30456         } else {
  30457             new_index = index - entries_left_in_tcam;
  30458         }
  30459     }
  30460 
  30461     return new_index;
  30462 }
  30463 /*
  30464  * @name   - soc_l3_defip_index_remap
  30465  * @param  - unit: unit number
  30466  * @param  - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128
  30467  * @param  - index: Physical index
  30468  *
  30469  * @purpose - Remap physical index to logical index
  30470  */
  30471 int
  30472 soc_l3_defip_index_remap(int unit, int wide, int index)
  30473 {
  30474     if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) {
  30475         return index;
  30476     }
  30477 
  30478     assert(SOC_L3_DEFIP_INDEX_INIT(unit));
  30479     if (wide == 0) {
  30480         return SOC_L3_DEFIP_PHY_TO_LOG_INDEX(unit, index);
  30481     }
  30482     return SOC_L3_DEFIP_PAIR_PHY_TO_LOG_INDEX(unit, index);
  30483 }
  30484 
  30485 /*
  30486  * @name   - _soc_l3_reduced_defip_urpf_index_map
  30487  * @param  - unit: unit number
  30488  * @param  - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128
  30489  * @param  - index: logical index
  30490  *
  30491  * @purpose - Map logical to physical index
  30492  */
  30493 
  30494 STATIC int
  30495 _soc_l3_reduced_defip_urpf_index_map(int unit, int wide, int index)
  30496 {
  30497     int new_index = index;
  30498     int num_tcams = 0;
  30499     int tcam_size = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit);
  30500     int entries_left_in_paired_tcam = 0;
  30501     int soc_defip_index_remap = SOC_L3_DEFIP_INDEX_REMAP_GET(unit) / 2;
  30502     int half_table_size = (SOC_CONTROL(unit)->l3_defip_max_tcams *
  30503                            tcam_size) / 2;
  30504     int half_defip_size;
  30505 
  30506     if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) {
  30507         half_defip_size = soc_mem_index_count(unit, L3_DEFIP_LEVEL1m) / 2;
  30508     } else {
  30509         half_defip_size = soc_mem_index_count(unit, L3_DEFIPm) / 2;
  30510     }
  30511 
  30512     if (wide == 0) {
  30513         num_tcams = soc_defip_index_remap / tcam_size;
  30514         entries_left_in_paired_tcam = tcam_size -
  30515                                       (soc_defip_index_remap % tcam_size);
  30516         if (index < entries_left_in_paired_tcam) {
  30517             new_index = index + (num_tcams * 2 * tcam_size) +
  30518                         (soc_defip_index_remap % tcam_size);
  30519         } else {
  30520             if (index < half_defip_size) {
  30521                 /* Apollo 2 has 6 tcams so the v6 rpf tcams will be last two.
  30522                  * Therefore we will setup the defip indexes contiguous
  30523                  */
  30524                 new_index = index + (num_tcams * 2 * tcam_size) +
  30525                             ((soc_defip_index_remap % tcam_size) * 2);
  30526             } else {
  30527                 if ((index - half_defip_size) < tcam_size) {
  30528                     new_index = half_table_size + (index - half_defip_size);
  30529                 } else if ((index - half_defip_size - tcam_size) < entries_left_in_paired_tcam) {
  30530                     new_index = half_table_size + (index - half_defip_size) +
  30531                         (soc_defip_index_remap % tcam_size);
  30532                 } else {
  30533                     new_index = half_table_size + (index - half_defip_size) +
  30534                         ((soc_defip_index_remap % tcam_size) * 2);
  30535                 }
  30536            }
  30537         }
  30538         return new_index;
  30539     }
  30540 
  30541     new_index = index;
  30542     if (index >= soc_defip_index_remap) {
  30543         new_index = index + LPM_INDEX_2K_ENTRIES - soc_defip_index_remap;
  30544     }
  30545     return new_index;
  30546 }
  30547 
  30548 /*
  30549  * @name   - _soc_l3_defip_urpf_index_map
  30550  * @param  - unit: unit number
  30551  * @param  - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128
  30552  * @param  - index: Logical index
  30553  *
  30554  * @purpose - Map logical index to physical index
  30555  */
  30556 STATIC int
  30557 _soc_l3_defip_urpf_index_map(int unit, int wide, int index)
  30558 {
  30559     int new_index = index;
  30560     int num_tcams = 0;
  30561     int tcam_size = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit);
  30562     int max_tcams = SOC_L3_DEFIP_MAX_TCAMS_GET(unit);
  30563     int entries_left_in_paired_tcam = 0;
  30564     int soc_defip_index_remap = SOC_L3_DEFIP_INDEX_REMAP_GET(unit) / 2;
  30565     int half_defip_size;
  30566     int half_defip_index = (max_tcams * tcam_size) / 2;
  30567 
  30568     if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) {
  30569         half_defip_size = soc_mem_index_count(unit, L3_DEFIP_LEVEL1m) / 2;
  30570     } else {
  30571         half_defip_size = soc_mem_index_count(unit, L3_DEFIPm) / 2;
  30572     }
  30573 
  30574     if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) {
  30575         return index;
  30576     }
  30577 
  30578     assert(tcam_size);
  30579 
  30580     if (wide == 0) {
  30581         num_tcams = soc_defip_index_remap / tcam_size;
  30582         entries_left_in_paired_tcam = tcam_size -
  30583                                       (soc_defip_index_remap % tcam_size);
  30584         if (index < entries_left_in_paired_tcam) {
  30585             new_index = index + (num_tcams * 2 * tcam_size) +
  30586                         (soc_defip_index_remap % tcam_size);
  30587         } else if (index >= (half_defip_size)) {
  30588             if ((index - half_defip_size)  < entries_left_in_paired_tcam) {
  30589                 new_index = (index - half_defip_size) +
  30590                             (num_tcams * 2 * tcam_size) +
  30591                             (soc_defip_index_remap % tcam_size) +
  30592                             half_defip_index;
  30593             } else {
  30594                 new_index = (index - half_defip_size) +
  30595                             (num_tcams * 2 * tcam_size) +
  30596                             ((soc_defip_index_remap % tcam_size) * 2) +
  30597                             half_defip_index;
  30598             }
  30599         } else {
  30600             new_index = index + (num_tcams * 2 * tcam_size) +
  30601                         ((soc_defip_index_remap % tcam_size) * 2);
  30602         }
  30603         return new_index;
  30604     }
  30605 
  30606     new_index = index;
  30607     if (index >= soc_defip_index_remap) {
  30608         new_index = index + (half_defip_index / 2) - soc_defip_index_remap;
  30609     }
  30610     return new_index;
  30611 }
  30612 
  30613 /*
  30614  * @name   - _soc_l3_reduced_defip_urpf_index_remap
  30615  * @param  - unit: unit number
  30616  * @param  - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128
  30617  * @param  - index: Physical index
  30618  *
  30619  * @purpose - Remap physical index to logical index
  30620  */
  30621 STATIC int
  30622 _soc_l3_reduced_defip_urpf_index_remap(int unit, int wide, int index)
  30623 {
  30624     int new_index = index;
  30625     int num_tcams = 0;
  30626     int tcam_size = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit);
  30627     int entries_left_in_paired_tcam = 0;
  30628     int soc_defip_index_remap = SOC_L3_DEFIP_INDEX_REMAP_GET(unit) / 2;
  30629 
  30630     if (wide == 0) {
  30631         num_tcams = soc_defip_index_remap / tcam_size;
  30632         entries_left_in_paired_tcam = tcam_size -
  30633             (soc_defip_index_remap % tcam_size);
  30634         new_index = index - (num_tcams * 2 * tcam_size);
  30635 
  30636         if (new_index < LPM_INDEX_4K_ENTRIES) {
  30637 
  30638             if (new_index - (soc_defip_index_remap % tcam_size) <
  30639                 entries_left_in_paired_tcam) {
  30640                 new_index = new_index - (soc_defip_index_remap % tcam_size);
  30641             } else {
  30642                 new_index = new_index - ((soc_defip_index_remap % tcam_size) * 2);
  30643             }
  30644         } else {
  30645             new_index = index - LPM_INDEX_4K_ENTRIES;
  30646             if (new_index - (soc_defip_index_remap % tcam_size) <
  30647                 entries_left_in_paired_tcam) {
  30648                 new_index = new_index - ((soc_defip_index_remap % tcam_size) * 3) ;
  30649             } else {
  30650                 new_index = new_index - ((soc_defip_index_remap % tcam_size) * 4);
  30651             }
  30652             new_index += LPM_INDEX_4K_ENTRIES;
  30653         }
  30654         return new_index;
  30655     }
  30656 
  30657     new_index = index;
  30658     if (index >= LPM_INDEX_2K_ENTRIES) {
  30659         new_index = index - LPM_INDEX_2K_ENTRIES + soc_defip_index_remap;
  30660     }
  30661     return new_index;
  30662 }
  30663 
  30664 /*
  30665  * @name   - soc_l3_defip_urpf_index_map
  30666  * @param  - unit: unit number
  30667  * @param  - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128
  30668  * @param  - index: Logical index
  30669  *
  30670  * @purpose - Map logical index to physical index
  30671  */
  30672 
  30673 int
  30674 soc_l3_defip_urpf_index_map(int unit, int wide, int index)
  30675 {
  30676     if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) {
  30677         return index;
  30678     }
  30679 
  30680     assert(SOC_L3_DEFIP_INDEX_INIT(unit));
  30681 
  30682     if (wide == 0) {
  30683         return SOC_L3_DEFIP_URPF_LOG_TO_PHY_INDEX(unit, index);
  30684     }
  30685     return SOC_L3_DEFIP_PAIR_URPF_LOG_TO_PHY_INDEX(unit, index);
  30686 }
  30687 
  30688 /*
  30689  * @name   - _soc_l3_defip_index_map
  30690  * @param  - unit: unit number
  30691  * @param  - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128
  30692  * @param  - index: Logical index
  30693  *
  30694  * @purpose - Map logical index to physical index
  30695  */
  30696 STATIC int
  30697 _soc_l3_defip_index_map(int unit, int wide, int index)
  30698 {
  30699     int new_index = index;
  30700     int num_tcams = 0;
  30701     int tcam_size = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit);
  30702     int entries_left_in_paired_tcam = 0;
  30703     int soc_defip_index_remap = SOC_L3_DEFIP_INDEX_REMAP_GET(unit);
  30704 
  30705     if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) {
  30706         return index;
  30707     }
  30708     if (wide == 0) {
  30709         if (soc_feature(unit, soc_feature_l3_1k_defip_table)) {
  30710             num_tcams = soc_defip_index_remap > 0 ? 1: 0;
  30711             new_index = index + num_tcams * 2 * tcam_size;
  30712         } else {
  30713         num_tcams = soc_defip_index_remap / tcam_size;
  30714         entries_left_in_paired_tcam = tcam_size -
  30715             (soc_defip_index_remap % tcam_size);
  30716         if (index < entries_left_in_paired_tcam) {
  30717             new_index = index + (num_tcams * 2 * tcam_size) +
  30718                         soc_defip_index_remap % tcam_size;
  30719         } else {
  30720             new_index = index + (num_tcams * 2 * tcam_size) +
  30721                         ((soc_defip_index_remap % tcam_size) * 2);
  30722         }
  30723         }
  30724         return new_index;
  30725     }
  30726     return index;
  30727 }
  30728 
  30729 /*
  30730  * @name   - _soc_th3_l3_defip_index_map
  30731  * @param  - unit: unit number
  30732  * @param  - wide: 0 - L3_DEFIP_LEVEL1, 1 - L3_DEFIP_PAIR_LEVEL1
  30733  * @param  - index: Logical index
  30734  *
  30735  * @purpose - Map logical index to physical index
  30736  *          - (only for TH3 ALPM2 Parallel/Mix IPv6-128b modes)
  30737  *                       -------------- 0
  30738  * L3_DEFIP_PAIR_LEVEL1  |  DB0 (v6)  |     BLOCK_0 (TCAM0/1)
  30739  *                       |------------| Private
  30740  *      L3_DEFIP_LEVEL1  |  DB0 (v4)  |     BLOCK_1 (TCAM2/3)
  30741  *                       |------------|
  30742  * L3_DEFIP_PAIR_LEVEL1  |  DB1 (v6)  |     BLOCK_2 (TCAM4/5)
  30743  *                       |------------| Public
  30744  *      L3_DEFIP_LEVEL1  |  DB1 (v4)  |     BLOCK_3 (TCAM6/7)
  30745  *                       -------------- 1023
  30746  */
  30747 STATIC int
  30748 _soc_th3_l3_defip_index_map(int unit, int wide, int index)
  30749 {
  30750     int new_index;
  30751     int num_tcams;
  30752     int tcam_size = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit);
  30753     int entries_left_in_paired_tcam;
  30754     int entries_left_in_tcam;
  30755     int soc_defip_index_remap = SOC_L3_DEFIP_INDEX_REMAP_GET(unit);
  30756     /* DB0: Private, DB1: Public */
  30757     int per_db_pair_entries = soc_defip_index_remap / 2;
  30758 
  30759     num_tcams = per_db_pair_entries / tcam_size;
  30760     entries_left_in_paired_tcam = tcam_size - (per_db_pair_entries % tcam_size);
  30761     entries_left_in_tcam = 2 * tcam_size - per_db_pair_entries;
  30762 
  30763     if (wide == 0) {
  30764         if (index < entries_left_in_paired_tcam) {
  30765             new_index = index + (num_tcams * 2 * tcam_size) +
  30766                         (per_db_pair_entries % tcam_size);
  30767         } else if (index < 2 * entries_left_in_tcam) {
  30768             new_index = index + (num_tcams * 2 * tcam_size) +
  30769                         2 * (per_db_pair_entries % tcam_size);
  30770         } else if (index < 2 * entries_left_in_tcam +
  30771                    entries_left_in_paired_tcam) {
  30772             new_index = index + 2 * (num_tcams * 2 * tcam_size) +
  30773                         3 * (per_db_pair_entries % tcam_size);
  30774         } else {
  30775             new_index = index + 2 * (num_tcams * 2 * tcam_size) +
  30776                         4 * (per_db_pair_entries % tcam_size);
  30777         }
  30778     } else { /* wide = 1 */
  30779         if (index < per_db_pair_entries) {
  30780             new_index = index;
  30781         } else {
  30782             new_index = index + entries_left_in_tcam;
  30783         }
  30784     }
  30785     return new_index;
  30786 }
  30787 
  30788 
  30789 /*
  30790  * @name   - soc_l3_defip_index_map
  30791  * @param  - unit: unit number
  30792  * @param  - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128
  30793  * @param  - index: Logical index
  30794  *
  30795  * @purpose - Map logical index to physical index
  30796  */
  30797 int
  30798 soc_l3_defip_index_map(int unit, int wide, int index)
  30799 {
  30800     if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) {
  30801         return index;
  30802     }
  30803 
  30804     assert(SOC_L3_DEFIP_INDEX_INIT(unit));
  30805     if (wide == 0) {
  30806         return SOC_L3_DEFIP_LOG_TO_PHY_INDEX(unit, index);
  30807     }
  30808     return SOC_L3_DEFIP_PAIR_LOG_TO_PHY_INDEX(unit, index);
  30809 }
  30810 
  30811 /*
  30812  * @name   - _soc_l3_defip_alpm_urpf_index_remap
  30813  * @param  - unit: unit number
  30814  * @param  - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128
  30815  * @param  - index: Physical index
  30816  *
  30817  * @purpose - Remap physical index to logical index
  30818  */
  30819 STATIC int
  30820 _soc_l3_defip_alpm_urpf_index_remap(int unit, int wide, int index)
  30821 {
  30822     uint32 tcam_size = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit);
  30823     uint32 num_chunks, chunk_offset;
  30824     int max_tcams = SOC_L3_DEFIP_MAX_TCAMS_GET(unit);
  30825     int defip128_tbl_sz = SOC_CONTROL(unit)->l3_defip_index_remap;
  30826     soc_mem_t mem = L3_DEFIPm;
  30827 
  30828     if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) {
  30829         mem = L3_DEFIP_LEVEL1m;
  30830     }
  30831 
  30832     if (wide) {
  30833         num_chunks = index / tcam_size;
  30834         chunk_offset = index % tcam_size;
  30835         return num_chunks * defip128_tbl_sz / (max_tcams / 2) +
  30836                chunk_offset;
  30837     }
  30838     num_chunks = index / tcam_size;
  30839     chunk_offset = index % tcam_size;
  30840     chunk_offset -= (defip128_tbl_sz / (max_tcams / 2));
  30841 
  30842     return num_chunks * soc_mem_index_count(unit, mem) / max_tcams + chunk_offset;
  30843 }
  30844 
  30845 
  30846 /*
  30847  * @name   - soc_l3_defip_alpm_urpf_index_remap
  30848  * @param  - unit: unit number
  30849  * @param  - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128
  30850  * @param  - index: Physical index
  30851  *
  30852  * @purpose - Remap physical index to logical index
  30853  */
  30854 int
  30855 soc_l3_defip_alpm_urpf_index_remap(int unit, int wide, int index)
  30856 {
  30857     assert(SOC_L3_DEFIP_INDEX_INIT(unit));
  30858     if (wide == 0) {
  30859         return SOC_L3_DEFIP_ALPM_URPF_PHY_TO_LOG_INDEX(unit, index);
  30860     }
  30861     return SOC_L3_DEFIP_PAIR_ALPM_URPF_PHY_TO_LOG_INDEX(unit, index);
  30862 }
  30863 /*
  30864  * @name   - _soc_l3_defip_alpm_urpf_index_map
  30865  * @param  - unit: unit number
  30866  * @param  - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128
  30867  * @param  - index: Logical index
  30868  *
  30869  * @purpose - Map logical index to physical index
  30870  */
  30871 STATIC int
  30872 _soc_l3_defip_alpm_urpf_index_map(int unit, int wide, int index)
  30873 {
  30874     uint32 tcam_size = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit);
  30875     uint32 tcam_num, tcam_idx;
  30876     int max_tcams = SOC_L3_DEFIP_MAX_TCAMS_GET(unit);
  30877     uint32 incr;
  30878     int defip128_tbl_sz = SOC_CONTROL(unit)->l3_defip_index_remap;
  30879     soc_mem_t mem = L3_DEFIPm;
  30880 
  30881     if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) {
  30882         mem = L3_DEFIP_LEVEL1m;
  30883     }
  30884 
  30885     if (wide) {
  30886         incr = defip128_tbl_sz / (max_tcams / 2);
  30887         tcam_num = index / incr;
  30888         tcam_idx = index % incr;
  30889         return tcam_num * tcam_size + tcam_idx;
  30890     }
  30891     incr = soc_mem_index_count(unit, mem) / (max_tcams / 2);
  30892 
  30893     incr = incr / 2;
  30894     tcam_num = index / incr;
  30895     tcam_idx = index % incr;
  30896     return tcam_num * tcam_size + tcam_idx + defip128_tbl_sz / (max_tcams / 2);
  30897 }
  30898 
  30899 
  30900 /*
  30901  * @name   - soc_l3_defip_alpm_urpf_index_map
  30902  * @param  - unit: unit number
  30903  * @param  - wide: 0 - L3_DEFIP, 1 - L3_DEFIP_PAIR_128
  30904  * @param  - index: Logical index
  30905  *
  30906  * @purpose - Map logical index to physical index
  30907  */
  30908 
  30909 int
  30910 soc_l3_defip_alpm_urpf_index_map(int unit, int wide, int index)
  30911 {
  30912     assert(SOC_L3_DEFIP_INDEX_INIT(unit));
  30913 
  30914     if (wide == 0) {
  30915         return SOC_L3_DEFIP_ALPM_URPF_LOG_TO_PHY_INDEX(unit, index);
  30916     }
  30917     return SOC_L3_DEFIP_PAIR_ALPM_URPF_LOG_TO_PHY_INDEX(unit, index);
  30918 }
  30919 
  30920 /*
  30921  * @name   - soc_l3_defip_index_mem_map
  30922  * @param  - unit: unit number
  30923  * @param  - index: physical index
  30924  * @param  - (OUT)mem: name of the tcam
  30925  *
  30926  * @purpose - Map L3_DEFIP view using physical index
  30927  */
  30928 
  30929 int
  30930 soc_l3_defip_index_mem_map(int unit, int index, soc_mem_t* mem)
  30931 {
  30932     int logical_index =  -1;
  30933     int defip_pair_index = -1;
  30934     int cam_size = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit);
  30935     soc_mem_t rtn_mem = L3_DEFIPm, rtn_pair_mem = L3_DEFIP_PAIR_128m;
  30936 
  30937     if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) {
  30938         rtn_mem = L3_DEFIP_LEVEL1m;
  30939         rtn_pair_mem = L3_DEFIP_PAIR_LEVEL1m;
  30940     }
  30941 
  30942     *mem = rtn_mem;
  30943 
  30944     if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) {
  30945         return index;
  30946     }
  30947 
  30948     if (SOC_CONTROL(unit)->l3_defip_urpf &&
  30949         !soc_feature(unit, soc_feature_l3_defip_advanced_lookup)) {
  30950         logical_index = soc_l3_defip_urpf_index_remap(unit, 0, index);
  30951 
  30952         if (logical_index != -1) {
  30953             *mem = rtn_mem;
  30954         } else {
  30955             *mem = rtn_pair_mem;
  30956             defip_pair_index = ((index / (cam_size * 2)) * cam_size) +
  30957                                (index % cam_size);
  30958             logical_index = soc_l3_defip_urpf_index_remap(unit, 1,
  30959                                                           defip_pair_index);
  30960         }
  30961         return logical_index;
  30962     }
  30963 
  30964     logical_index = soc_l3_defip_index_remap(unit, 0, index);
  30965 
  30966     if (logical_index != -1) {
  30967         *mem = rtn_mem;
  30968     } else {
  30969         *mem = rtn_pair_mem;
  30970         defip_pair_index = ((index / (cam_size * 2)) * cam_size) +
  30971                            (index % cam_size);
  30972         logical_index = soc_l3_defip_index_remap(unit, 1, defip_pair_index);
  30973     }
  30974 
  30975     return logical_index;
  30976 }
  30977 
  30978 int
  30979 soc_l3_defip_indexes_deinit(int unit)
  30980 {
  30981     if (SOC_L3_DEFIP_INDEX_INIT(unit) == NULL) {
  30982         return SOC_E_NONE;
  30983     }
  30984 
  30985     if (SOC_L3_DEFIP_LOG_TO_PHY_ARRAY(unit)) {
  30986         sal_free(SOC_L3_DEFIP_LOG_TO_PHY_ARRAY(unit));
  30987         SOC_L3_DEFIP_LOG_TO_PHY_ARRAY(unit) = NULL;
  30988     }
  30989 
  30990     if (SOC_L3_DEFIP_URPF_LOG_TO_PHY_ARRAY(unit)) {
  30991         sal_free(SOC_L3_DEFIP_URPF_LOG_TO_PHY_ARRAY(unit));
  30992         SOC_L3_DEFIP_URPF_LOG_TO_PHY_ARRAY(unit) = NULL;
  30993     }
  30994 
  30995     if (SOC_L3_DEFIP_PHY_TO_LOG_ARRAY(unit)) {
  30996         sal_free(SOC_L3_DEFIP_PHY_TO_LOG_ARRAY(unit));
  30997         SOC_L3_DEFIP_PHY_TO_LOG_ARRAY(unit) = NULL;
  30998     }
  30999 
  31000     if (SOC_L3_DEFIP_URPF_PHY_TO_LOG_ARRAY(unit)) {
  31001         sal_free(SOC_L3_DEFIP_URPF_PHY_TO_LOG_ARRAY(unit));
  31002         SOC_L3_DEFIP_URPF_PHY_TO_LOG_ARRAY(unit) = NULL;
  31003     }
  31004 
  31005     if (SOC_L3_DEFIP_PAIR_LOG_TO_PHY_ARRAY(unit)) {
  31006         sal_free(SOC_L3_DEFIP_PAIR_LOG_TO_PHY_ARRAY(unit));
  31007         SOC_L3_DEFIP_PAIR_LOG_TO_PHY_ARRAY(unit) = NULL;
  31008     }
  31009 
  31010     if (SOC_L3_DEFIP_PAIR_URPF_LOG_TO_PHY_ARRAY(unit)) {
  31011         sal_free(SOC_L3_DEFIP_PAIR_URPF_LOG_TO_PHY_ARRAY(unit));
  31012         SOC_L3_DEFIP_PAIR_URPF_LOG_TO_PHY_ARRAY(unit) = NULL;
  31013     }
  31014 
  31015     if (SOC_L3_DEFIP_PAIR_PHY_TO_LOG_ARRAY(unit)) {
  31016         sal_free(SOC_L3_DEFIP_PAIR_PHY_TO_LOG_ARRAY(unit));
  31017         SOC_L3_DEFIP_PAIR_PHY_TO_LOG_ARRAY(unit) = NULL;
  31018     }
  31019 
  31020     if (SOC_L3_DEFIP_PAIR_URPF_PHY_TO_LOG_ARRAY(unit)) {
  31021         sal_free(SOC_L3_DEFIP_PAIR_URPF_PHY_TO_LOG_ARRAY(unit));
  31022         SOC_L3_DEFIP_PAIR_URPF_PHY_TO_LOG_ARRAY(unit) = NULL;
  31023     }
  31024 
  31025     if (SOC_L3_DEFIP_ALPM_URPF_LOG_TO_PHY_ARRAY(unit)) {
  31026         sal_free(SOC_L3_DEFIP_ALPM_URPF_LOG_TO_PHY_ARRAY(unit));
  31027         SOC_L3_DEFIP_ALPM_URPF_LOG_TO_PHY_ARRAY(unit) = NULL;
  31028     }
  31029     if (SOC_L3_DEFIP_ALPM_URPF_PHY_TO_LOG_ARRAY(unit)) {
  31030         sal_free(SOC_L3_DEFIP_ALPM_URPF_PHY_TO_LOG_ARRAY(unit));
  31031         SOC_L3_DEFIP_ALPM_URPF_PHY_TO_LOG_ARRAY(unit) = NULL;
  31032     }
  31033     if (SOC_L3_DEFIP_PAIR_ALPM_URPF_LOG_TO_PHY_ARRAY(unit)) {
  31034         sal_free(SOC_L3_DEFIP_PAIR_ALPM_URPF_LOG_TO_PHY_ARRAY(unit));
  31035         SOC_L3_DEFIP_PAIR_ALPM_URPF_LOG_TO_PHY_ARRAY(unit) = NULL;
  31036     }
  31037     if (SOC_L3_DEFIP_PAIR_ALPM_URPF_PHY_TO_LOG_ARRAY(unit)) {
  31038         sal_free(SOC_L3_DEFIP_PAIR_ALPM_URPF_PHY_TO_LOG_ARRAY(unit));
  31039         SOC_L3_DEFIP_PAIR_ALPM_URPF_PHY_TO_LOG_ARRAY(unit) = NULL;
  31040     }
  31041 
  31042     if (SOC_L3_DEFIP_INDEX_INIT(unit)) {
  31043         sal_free(SOC_L3_DEFIP_INDEX_INIT(unit));
  31044         SOC_L3_DEFIP_INDEX_INIT(unit) = NULL;
  31045     }
  31046 
  31047     return SOC_E_NONE;
  31048 }
  31049 
  31050 /*
  31051  * @name   - soc_l3_defip_indexes_init
  31052  * @param  - unit: unit number
  31053  * @returns -  SOC_E_MEMORY, SOC_E_NONE
  31054  *
  31055  * @purpose - generate a map of logical to physical and
  31056  *            physical to logical indexes
  31057  */
  31058 int
  31059 soc_l3_defip_indexes_init(int unit, int config_ipv6_entries)
  31060 {
  31061     int log_index;
  31062     int phy_index;
  31063     int temp_index;
  31064 
  31065     int max_index = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit) *
  31066                     SOC_L3_DEFIP_MAX_TCAMS_GET(unit);
  31067     soc_mem_t mem = L3_DEFIPm, memp = L3_DEFIP_PAIR_128m;
  31068 
  31069     int defip_max_index;
  31070     int size;
  31071     int defip_table_present;
  31072     int defip_pair_128_table_present;
  31073     int th3_defip_map = 0;
  31074 
  31075 #ifdef BCM_TOMAHAWK3_SUPPORT
  31076     if (SOC_IS_TOMAHAWK3(unit)) {
  31077         mem  = L3_DEFIP_LEVEL1m;
  31078         memp = L3_DEFIP_PAIR_LEVEL1m;
  31079 #ifdef ALPM_ENABLE
  31080         if (soc_property_get(unit, spn_IPV6_LPM_128B_ENABLE, 1) &&
  31081             (soc_alpm_cmn_mode_get(unit) == SOC_ALPM_MODE_PARALLEL ||
  31082              soc_alpm_cmn_mode_get(unit) == SOC_ALPM_MODE_TCAM_ALPM)) {
  31083             th3_defip_map = 1;
  31084         }
  31085 #endif
  31086     }
  31087 #endif
  31088 
  31089     defip_max_index = soc_mem_index_count(unit, mem);
  31090 
  31091     if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) {
  31092         SOC_L3_DEFIP_MAX_128B_ENTRIES(unit) = config_ipv6_entries;
  31093         return SOC_E_NONE;
  31094     }
  31095 
  31096     assert(SOC_L3_DEFIP_TCAM_DEPTH_GET(unit));
  31097     assert(SOC_L3_DEFIP_MAX_TCAMS_GET(unit));
  31098 
  31099     SOC_IF_ERROR_RETURN(soc_l3_defip_indexes_deinit(unit));
  31100 
  31101     SOC_L3_DEFIP_INDEX_INIT(unit) =
  31102         sal_alloc(sizeof(_soc_l3_defip_index_table_t), "defip map table");
  31103     if (SOC_L3_DEFIP_INDEX_INIT(unit) == NULL) {
  31104         return SOC_E_MEMORY;
  31105     }
  31106 
  31107     sal_memset(SOC_L3_DEFIP_INDEX_INIT(unit), 0x0,
  31108                                        sizeof(_soc_l3_defip_index_table_t));
  31109     defip_table_present =
  31110         soc_mem_index_count(unit, mem) ? 1 : 0;
  31111 
  31112     if (defip_table_present) {
  31113         size = defip_max_index * sizeof(int);
  31114         SOC_L3_DEFIP_LOG_TO_PHY_ARRAY(unit) =
  31115                                 sal_alloc(size, "defip log to phy index mapping");
  31116         if (SOC_L3_DEFIP_LOG_TO_PHY_ARRAY(unit) == NULL) {
  31117             return SOC_E_MEMORY;
  31118         }
  31119         sal_memset(SOC_L3_DEFIP_LOG_TO_PHY_ARRAY(unit), -1, size);
  31120 
  31121         /* required also for non-URPF ALPM Parallel/Mixed modes */
  31122         SOC_L3_DEFIP_URPF_LOG_TO_PHY_ARRAY(unit) =
  31123                              sal_alloc(size, "urpf defip log to phy index mapping");
  31124         if (SOC_L3_DEFIP_URPF_LOG_TO_PHY_ARRAY(unit) == NULL) {
  31125             return SOC_E_MEMORY;
  31126         }
  31127         sal_memset(SOC_L3_DEFIP_URPF_LOG_TO_PHY_ARRAY(unit), -1, size);
  31128 
  31129         if (soc_feature(unit, soc_feature_urpf)) {
  31130         SOC_L3_DEFIP_ALPM_URPF_LOG_TO_PHY_ARRAY(unit) =
  31131                  sal_alloc(size, "alpm urpf defip log to phy index mapping");
  31132         if (SOC_L3_DEFIP_ALPM_URPF_LOG_TO_PHY_ARRAY(unit) == NULL) {
  31133             return SOC_E_MEMORY;
  31134         }
  31135         sal_memset(SOC_L3_DEFIP_ALPM_URPF_LOG_TO_PHY_ARRAY(unit), -1, size);
  31136         }
  31137         size = max_index * sizeof(int);
  31138         SOC_L3_DEFIP_PHY_TO_LOG_ARRAY(unit) =
  31139                               sal_alloc(size, "defip phy to log index mapping");
  31140         if (SOC_L3_DEFIP_PHY_TO_LOG_ARRAY(unit) == NULL) {
  31141             return SOC_E_MEMORY;
  31142         }
  31143         sal_memset(SOC_L3_DEFIP_PHY_TO_LOG_ARRAY(unit), -1, size);
  31144 
  31145         /* required also for non-URPF ALPM Parallel/Mixed modes */
  31146         SOC_L3_DEFIP_URPF_PHY_TO_LOG_ARRAY(unit) =
  31147                                  sal_alloc(size, "defip phy to log index mapping");
  31148         if (SOC_L3_DEFIP_URPF_PHY_TO_LOG_ARRAY(unit) == NULL) {
  31149             return SOC_E_MEMORY;
  31150         }
  31151         sal_memset(SOC_L3_DEFIP_URPF_PHY_TO_LOG_ARRAY(unit), -1, size);
  31152 
  31153         if (soc_feature(unit, soc_feature_urpf)) {
  31154         SOC_L3_DEFIP_ALPM_URPF_PHY_TO_LOG_ARRAY(unit) =
  31155                  sal_alloc(size, "alpm urpf defip phy to log index mapping");
  31156         if (SOC_L3_DEFIP_ALPM_URPF_PHY_TO_LOG_ARRAY(unit) == NULL) {
  31157             return SOC_E_MEMORY;
  31158         }
  31159         sal_memset(SOC_L3_DEFIP_ALPM_URPF_PHY_TO_LOG_ARRAY(unit), -1, size);
  31160     }
  31161     }
  31162 
  31163     defip_pair_128_table_present =
  31164         soc_mem_index_count(unit, memp) ? 1 : 0;
  31165 
  31166     if (defip_pair_128_table_present) {
  31167         size = soc_mem_index_count(unit, memp) * sizeof(int);
  31168         SOC_L3_DEFIP_PAIR_LOG_TO_PHY_ARRAY(unit) =
  31169                                 sal_alloc(size, "defip log to phy index mapping");
  31170         if (SOC_L3_DEFIP_PAIR_LOG_TO_PHY_ARRAY(unit) == NULL) {
  31171             return SOC_E_MEMORY;
  31172         }
  31173         sal_memset(SOC_L3_DEFIP_PAIR_LOG_TO_PHY_ARRAY(unit), -1, size);
  31174 
  31175         /* required also for non-URPF ALPM Parallel/Mixed modes */
  31176         SOC_L3_DEFIP_PAIR_URPF_LOG_TO_PHY_ARRAY(unit) =
  31177                              sal_alloc(size, "urpf defip log to phy index mapping");
  31178         if (SOC_L3_DEFIP_PAIR_URPF_LOG_TO_PHY_ARRAY(unit) == NULL) {
  31179             return SOC_E_MEMORY;
  31180         }
  31181         sal_memset(SOC_L3_DEFIP_PAIR_URPF_LOG_TO_PHY_ARRAY(unit), -1, size);
  31182 
  31183         if (soc_feature(unit, soc_feature_urpf)) {
  31184         SOC_L3_DEFIP_PAIR_ALPM_URPF_LOG_TO_PHY_ARRAY(unit) =
  31185                  sal_alloc(size, "alpm urpf defip log to phy index mapping");
  31186         if (SOC_L3_DEFIP_PAIR_ALPM_URPF_LOG_TO_PHY_ARRAY(unit) == NULL) {
  31187             return SOC_E_MEMORY;
  31188         }
  31189         sal_memset(SOC_L3_DEFIP_PAIR_ALPM_URPF_LOG_TO_PHY_ARRAY(unit), -1, size);
  31190         }
  31191         size = max_index * sizeof(int);
  31192         SOC_L3_DEFIP_PAIR_PHY_TO_LOG_ARRAY(unit) =
  31193                               sal_alloc(size, "defip phy to log index mapping");
  31194         if (SOC_L3_DEFIP_PAIR_PHY_TO_LOG_ARRAY(unit) == NULL) {
  31195             return SOC_E_MEMORY;
  31196         }
  31197         sal_memset(SOC_L3_DEFIP_PAIR_PHY_TO_LOG_ARRAY(unit), -1, size);
  31198 
  31199         /* required also for non-URPF ALPM Parallel/Mixed modes */
  31200         SOC_L3_DEFIP_PAIR_URPF_PHY_TO_LOG_ARRAY(unit) =
  31201                                  sal_alloc(size, "defip phy to log index mapping");
  31202         if (SOC_L3_DEFIP_PAIR_URPF_PHY_TO_LOG_ARRAY(unit) == NULL) {
  31203             return SOC_E_MEMORY;
  31204         }
  31205         sal_memset(SOC_L3_DEFIP_PAIR_URPF_PHY_TO_LOG_ARRAY(unit), -1, size);
  31206 
  31207         if (soc_feature(unit, soc_feature_urpf)) {
  31208         SOC_L3_DEFIP_PAIR_ALPM_URPF_PHY_TO_LOG_ARRAY(unit) =
  31209                  sal_alloc(size, "alpm urpf defip phy to log index mapping");
  31210         if (SOC_L3_DEFIP_PAIR_ALPM_URPF_PHY_TO_LOG_ARRAY(unit) == NULL) {
  31211             return SOC_E_MEMORY;
  31212         }
  31213         sal_memset(SOC_L3_DEFIP_PAIR_ALPM_URPF_PHY_TO_LOG_ARRAY(unit), -1, size);
  31214     }
  31215     }
  31216 
  31217     for (log_index = 0; log_index < defip_max_index; log_index++) {
  31218 
  31219         if (th3_defip_map) {
  31220             phy_index = _soc_th3_l3_defip_index_map(unit, 0, log_index);
  31221         } else {
  31222         phy_index = _soc_l3_defip_index_map(unit, 0, log_index);
  31223         }
  31224         SOC_L3_DEFIP_LOG_TO_PHY_INDEX(unit, log_index) = phy_index;
  31225 
  31226         if (th3_defip_map) {
  31227             temp_index = _soc_th3_l3_defip_index_remap(unit, 0, phy_index);
  31228         } else {
  31229         temp_index = _soc_l3_defip_index_remap(unit, 0, phy_index);
  31230         }
  31231         SOC_L3_DEFIP_PHY_TO_LOG_INDEX(unit, phy_index) = temp_index;
  31232         if (log_index != temp_index || phy_index >= max_index) {
  31233             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  31234                       (BSL_META_U(unit,
  31235                                   "defip map/remap failed 1: "
  31236                                   "lidx %d tidx %d pidx %d midx:%d\n"),
  31237                                   log_index, temp_index, phy_index, max_index));
  31238         }
  31239 
  31240         /* required also for non-URPF ALPM Parallel/Mixed modes */
  31241         if (SOC_IS_TRIUMPH3(unit) &&
  31242                soc_feature(unit, soc_feature_l3_reduced_defip_table)) {
  31243             phy_index = _soc_l3_reduced_defip_urpf_index_map(unit, 0, log_index);
  31244             SOC_L3_DEFIP_URPF_LOG_TO_PHY_INDEX(unit, log_index) = phy_index;
  31245             temp_index = _soc_l3_reduced_defip_urpf_index_remap(unit, 0, phy_index);
  31246             SOC_L3_DEFIP_URPF_PHY_TO_LOG_INDEX(unit, phy_index) = temp_index;
  31247         } else {
  31248             phy_index = _soc_l3_defip_urpf_index_map(unit, 0, log_index);
  31249             SOC_L3_DEFIP_URPF_LOG_TO_PHY_INDEX(unit, log_index) = phy_index;
  31250             temp_index = _soc_l3_defip_urpf_index_remap(unit, 0, phy_index);
  31251             SOC_L3_DEFIP_URPF_PHY_TO_LOG_INDEX(unit, phy_index) = temp_index;
  31252         }
  31253         if (log_index != temp_index || phy_index >= max_index) {
  31254             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  31255                       (BSL_META_U(unit,
  31256                                   "defip map/remap failed 2: "
  31257                                   "lidx %d tidx %d pidx %d midx:%d\n"),
  31258                                   log_index, temp_index, phy_index, max_index));
  31259         }
  31260 
  31261         if (!soc_feature(unit, soc_feature_urpf)) {
  31262             continue;
  31263         }
  31264 
  31265         if (SOC_CONTROL(unit)->l3_defip_index_remap % 4 ||
  31266             SOC_L3_DEFIP_MAX_TCAMS_GET(unit) % 4 ||
  31267             !soc_feature(unit, soc_feature_alpm)) {
  31268             /* alpm urpf will not be used */
  31269             continue;
  31270         }
  31271 
  31272         phy_index = _soc_l3_defip_alpm_urpf_index_map(unit, 0, log_index);
  31273         SOC_L3_DEFIP_ALPM_URPF_LOG_TO_PHY_INDEX(unit, log_index) = phy_index;
  31274         temp_index = _soc_l3_defip_alpm_urpf_index_remap(unit, 0, phy_index);
  31275         SOC_L3_DEFIP_ALPM_URPF_PHY_TO_LOG_INDEX(unit, phy_index) = temp_index;
  31276         if (log_index != temp_index || phy_index >= max_index) {
  31277             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  31278                       (BSL_META_U(unit,
  31279                                   "defip map/remap failed 3: "
  31280                                   "lidx %d tidx %d pidx %d midx:%d\n"),
  31281                                   log_index, temp_index, phy_index, max_index));
  31282         }
  31283     }
  31284 
  31285     defip_max_index = soc_mem_index_count(unit, memp);
  31286     for (log_index = 0; log_index < defip_max_index; log_index++) {
  31287 
  31288         if (th3_defip_map) {
  31289             phy_index = _soc_th3_l3_defip_index_map(unit, 1, log_index);
  31290         } else {
  31291         phy_index = _soc_l3_defip_index_map(unit, 1, log_index);
  31292         }
  31293         SOC_L3_DEFIP_PAIR_LOG_TO_PHY_INDEX(unit, log_index) = phy_index;
  31294 
  31295         if (th3_defip_map) {
  31296             temp_index = _soc_th3_l3_defip_index_remap(unit, 1, phy_index);
  31297         } else {
  31298         temp_index = _soc_l3_defip_index_remap(unit, 1, phy_index);
  31299         }
  31300         SOC_L3_DEFIP_PAIR_PHY_TO_LOG_INDEX(unit, phy_index) = temp_index;
  31301         if (log_index != temp_index || phy_index >= max_index) {
  31302             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  31303                       (BSL_META_U(unit,
  31304                                   "defip map/remap failed 4: "
  31305                                   "lidx %d tidx %d pidx %d midx:%d\n"),
  31306                                   log_index, temp_index, phy_index, max_index));
  31307         }
  31308 
  31309         /* required also for non-URPF ALPM Parallel/Mixed modes */
  31310         if (SOC_IS_TRIUMPH3(unit) &&
  31311                soc_feature(unit, soc_feature_l3_reduced_defip_table)) {
  31312             phy_index = _soc_l3_reduced_defip_urpf_index_map(unit, 1, log_index);
  31313             SOC_L3_DEFIP_PAIR_URPF_LOG_TO_PHY_INDEX(unit, log_index) = phy_index;
  31314             temp_index = _soc_l3_reduced_defip_urpf_index_remap(unit, 1, phy_index);
  31315             SOC_L3_DEFIP_PAIR_URPF_PHY_TO_LOG_INDEX(unit, phy_index) = temp_index;
  31316         } else {
  31317             phy_index = _soc_l3_defip_urpf_index_map(unit, 1, log_index);
  31318             SOC_L3_DEFIP_PAIR_URPF_LOG_TO_PHY_INDEX(unit, log_index) = phy_index;
  31319             temp_index = _soc_l3_defip_urpf_index_remap(unit, 1, phy_index);
  31320             SOC_L3_DEFIP_PAIR_URPF_PHY_TO_LOG_INDEX(unit, phy_index) = temp_index;
  31321         }
  31322         if (log_index != temp_index || phy_index >= max_index) {
  31323             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  31324                       (BSL_META_U(unit,
  31325                                   "defip map/remap failed 5: "
  31326                                   "lidx %d tidx %d pidx %d midx:%d\n"),
  31327                                   log_index, temp_index, phy_index, max_index));
  31328         }
  31329 
  31330         if (!soc_feature(unit, soc_feature_urpf)) {
  31331             continue;
  31332         }
  31333 
  31334         if (SOC_CONTROL(unit)->l3_defip_index_remap % 4 ||
  31335             SOC_L3_DEFIP_MAX_TCAMS_GET(unit) % 4 ||
  31336             !soc_feature(unit, soc_feature_alpm)) {
  31337             /* alpm urpf will not be used */
  31338             continue;
  31339         }
  31340 
  31341         phy_index = _soc_l3_defip_alpm_urpf_index_map(unit, 1, log_index);
  31342         SOC_L3_DEFIP_PAIR_ALPM_URPF_LOG_TO_PHY_INDEX(unit, log_index) = phy_index;
  31343         temp_index = _soc_l3_defip_alpm_urpf_index_remap(unit, 1, phy_index);
  31344         SOC_L3_DEFIP_PAIR_ALPM_URPF_PHY_TO_LOG_INDEX(unit, phy_index) = temp_index;
  31345         if (log_index != temp_index || phy_index >= max_index) {
  31346             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  31347                       (BSL_META_U(unit,
  31348                                   "defip map/remap failed 6: "
  31349                                   "lidx %d tidx %d pidx %d midx:%d\n"),
  31350                                   log_index, temp_index, phy_index, max_index));
  31351         }
  31352     }
  31353 
  31354     SOC_L3_DEFIP_MAX_128B_ENTRIES(unit) = config_ipv6_entries;
  31355     return SOC_E_NONE;
  31356 }
  31357 
  31358 /*
  31359  * This function assumes that the lock to L3_DEFIP and
  31360  * L3_DEFIP_PAIR_128 tables are already taken
  31361 */
  31362 int
  31363 soc_defip_tables_resize(int unit, int num_ipv6_128b_entries)
  31364 {
  31365     soc_persist_t *sop;
  31366     int config_v6_entries = 0;
  31367     int num_defip_entries = 0;
  31368     int max_tcams = 0, tcam_size = 0;
  31369 
  31370     soc_mem_t mem = L3_DEFIPm, pair_mem = L3_DEFIP_PAIR_128m;
  31371 
  31372     if (SOC_MEM_IS_VALID(unit, L3_DEFIP_LEVEL1m)) {
  31373         mem = L3_DEFIP_LEVEL1m;
  31374         pair_mem = L3_DEFIP_PAIR_LEVEL1m;
  31375     }
  31376 
  31377     num_ipv6_128b_entries = num_ipv6_128b_entries +
  31378                             (num_ipv6_128b_entries % 2);
  31379 
  31380 #if defined(BCM_TRIDENT2_SUPPORT)
  31381     if (soc_feature(unit, soc_feature_alpm) &&
  31382         (soc_trident2_alpm_mode_get(unit) == 1 ||
  31383          soc_trident2_alpm_mode_get(unit) == 3)) {
  31384         num_ipv6_128b_entries = (num_ipv6_128b_entries + 3) / 4 * 4;
  31385     }
  31386 #endif /* BCM_TRIDENT2_SUPPORT */
  31387 
  31388     if (SOC_CONTROL(unit)->tcam_protect_write) {
  31389         num_ipv6_128b_entries = (num_ipv6_128b_entries + 3) / 4 * 4;
  31390     }
  31391     config_v6_entries = num_ipv6_128b_entries;
  31392 
  31393     max_tcams = SOC_L3_DEFIP_MAX_TCAMS_GET(unit);
  31394     tcam_size = SOC_CONTROL(unit)->l3_defip_tcam_size;
  31395     if (SOC_CONTROL(unit)->tcam_protect_write) {
  31396         if (soc_mem_index_count(unit, pair_mem)) {
  31397             tcam_size++;
  31398         }
  31399         if (soc_mem_index_count(unit, mem)) {
  31400             tcam_size++;
  31401         }
  31402     }
  31403 
  31404     if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) {
  31405         num_ipv6_128b_entries = 0;
  31406     }
  31407 
  31408     num_defip_entries = (max_tcams * tcam_size) -
  31409                         (num_ipv6_128b_entries * 2);
  31410     if (SOC_CONTROL(unit)->tcam_protect_write) {
  31411         if (num_defip_entries) {
  31412             num_defip_entries -= SOC_CONTROL(unit)->l3_defip_max_tcams;
  31413             /* Don't use up all entries as protect entries */
  31414             if (num_defip_entries <= 0) {
  31415                 return SOC_E_CONFIG;
  31416             }
  31417             tcam_size--;
  31418         }
  31419         if (num_ipv6_128b_entries) {
  31420             num_ipv6_128b_entries -= SOC_CONTROL(unit)->l3_defip_max_tcams/2;
  31421             /* Don't use up all entries as protect entries */
  31422             if (num_ipv6_128b_entries <= 0) {
  31423                 return SOC_E_CONFIG;
  31424             }
  31425             tcam_size--;
  31426         }
  31427         if (config_v6_entries) {
  31428             config_v6_entries -= SOC_CONTROL(unit)->l3_defip_max_tcams/2;
  31429             if (config_v6_entries < 0) {
  31430                 return SOC_E_CONFIG;
  31431             }
  31432         }
  31433     }
  31434     SOC_CONTROL(unit)->l3_defip_tcam_size = tcam_size;
  31435 
  31436     if (soc_feature(unit, soc_feature_l3_lpm_scaling_enable)) {
  31437         if(!soc_feature(unit, soc_feature_l3_lpm_128b_entries_reserved)) {
  31438             config_v6_entries = ((config_v6_entries /
  31439                                    SOC_CONTROL(unit)->l3_defip_tcam_size) +
  31440                                    ((config_v6_entries %
  31441                                    SOC_CONTROL(unit)->l3_defip_tcam_size)
  31442                               ? 1 : 0)) * SOC_CONTROL(unit)->l3_defip_tcam_size;
  31443         }
  31444         SOC_L3_DEFIP_MAX_128B_ENTRIES(unit) = config_v6_entries;
  31445         return SOC_E_NONE;
  31446     }
  31447 
  31448     sop = SOC_PERSIST(unit);
  31449     sop->memState[pair_mem].index_max =
  31450                                              num_ipv6_128b_entries - 1;
  31451     sop->memState[L3_DEFIP_PAIR_128_ONLYm].index_max =
  31452                                   num_ipv6_128b_entries - 1;
  31453     sop->memState[L3_DEFIP_PAIR_128_DATA_ONLYm].index_max =
  31454                                       num_ipv6_128b_entries - 1;
  31455     sop->memState[L3_DEFIP_PAIR_128_HIT_ONLYm].index_max =
  31456                                       num_ipv6_128b_entries - 1;
  31457     sop->memState[L3_DEFIP_PAIR_128_HIT_ONLY_Xm].index_max =
  31458                                       num_ipv6_128b_entries - 1;
  31459     sop->memState[L3_DEFIP_PAIR_128_HIT_ONLY_Ym].index_max =
  31460                                       num_ipv6_128b_entries - 1;
  31461     sop->memState[mem].index_max = num_defip_entries - 1;
  31462 
  31463     if (soc_feature(unit, soc_feature_l3_1k_defip_table)) {
  31464         sop->memState[mem].index_max = 1023;
  31465     }
  31466 
  31467     sop->memState[L3_DEFIP_ONLYm].index_max =
  31468                                   sop->memState[mem].index_max;
  31469     sop->memState[L3_DEFIP_DATA_ONLYm].index_max =
  31470                                   sop->memState[mem].index_max;
  31471     sop->memState[L3_DEFIP_HIT_ONLYm].index_max =
  31472                                   sop->memState[mem].index_max;
  31473     sop->memState[L3_DEFIP_HIT_ONLY_Xm].index_max =
  31474                                   sop->memState[mem].index_max;
  31475     sop->memState[L3_DEFIP_HIT_ONLY_Ym].index_max =
  31476                                   sop->memState[mem].index_max;
  31477     SOC_CONTROL(unit)->l3_defip_index_remap = num_ipv6_128b_entries;
  31478     return soc_l3_defip_indexes_init(unit, config_v6_entries);
  31479 }
  31480 /*
  31481  * This function makes config variables unit specific and
  31482  * either updates config.bcm or display on the terminal
  31483 */
  31484 void
  31485 soc_mem_config_save(int unit, char *config_str, char *config_value)
  31486 {
  31487      char local_config_str[80];
  31488      sal_sprintf(local_config_str,"%s.%d",config_str,unit);
  31489 
  31490      if (soc_mem_config_set != NULL) {
  31491          soc_mem_config_set(local_config_str,config_value);
  31492      } else {
  31493          if (config_value != NULL) {
  31494              LOG_CLI((BSL_META_U(unit,
  31495                                  "%s=%s #Add in config.bcm\n"),
  31496                       local_config_str,config_value));
  31497          }
  31498      }
  31499 }
  31500 
  31501 #if defined(BCM_TRIUMPH3_SUPPORT)
  31502 /*
  31503  * Function:
  31504  *    soc_mem_field_clear_all
  31505  * Purpose:
  31506  *    Clears a field in all entries for a memory .
  31507  *    Operates on all copies of the table if copyno is COPYNO_ALL.
  31508  * Notes:
  31509  */
  31510 
  31511 int
  31512 soc_mem_field_clear_all(int unit,
  31513                         soc_mem_t mem,
  31514                         soc_field_t field,
  31515                         int copyno,
  31516                         int force_all)
  31517 {
  31518     int           rv = SOC_E_NONE;
  31519     int       chunk_size, chunk_entries, mem_size, entry_words;
  31520     int       index, index_end, index_min, index_max;
  31521     uint32    *buf;
  31522     uint32    fval[SOC_MAX_MEM_FIELD_WORDS];
  31523     int       i;
  31524 
  31525 
  31526     /* Implemented for TR3 and HX4 */
  31527     if (!(SOC_IS_TRIUMPH3(unit) || SOC_IS_HELIX4(unit))) {
  31528         return SOC_E_UNAVAIL;
  31529     }
  31530 
  31531     if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)) {
  31532         return SOC_E_NONE;
  31533     }
  31534 
  31535     _SOC_MEM_REPLACE_MEM(unit, mem);
  31536     if (soc_mem_index_count(unit, mem) == 0) {
  31537         return SOC_E_NONE;
  31538     }
  31539 
  31540     sal_memset(fval, 0, sizeof (fval));
  31541 
  31542     /* check is the field is valid */
  31543     if (!SOC_MEM_FIELD_VALID(unit, mem, field)) {
  31544         return SOC_E_PARAM;
  31545     }
  31546 
  31547     DNXC_MTA(dnxc_multithread_analyzer_log_resource_use(unit, MTA_RESOURCE_MEM, mem, TRUE));
  31548 
  31549     chunk_size = SOC_MEM_CLEAR_CHUNK_SIZE_GET(unit);
  31550     index_min = soc_mem_index_min(unit, mem);
  31551     index_max = soc_mem_index_max(unit, mem);
  31552     entry_words = soc_mem_entry_words(unit, mem);
  31553     mem_size = (index_max - index_min + 1) * entry_words * 4;
  31554 
  31555     if (mem_size < chunk_size) {
  31556         chunk_size = mem_size;
  31557     }
  31558 
  31559     buf = soc_cm_salloc(unit, chunk_size, "mem_clear_buf");
  31560     if (buf == NULL) {
  31561         return SOC_E_MEMORY;
  31562     }
  31563 
  31564     chunk_entries = chunk_size / (entry_words * 4);
  31565 
  31566     rv = SOC_E_NONE;
  31567     MEM_LOCK(unit, mem);
  31568     for (index = index_min; index <= index_max; index += chunk_entries) {
  31569         index_end = index + chunk_entries - 1;
  31570         if (index_end > index_max) {
  31571             LOG_CLI((BSL_META_U(unit,
  31572                                 "index_end = %d\n"), index_end));
  31573             index_end = index_max;
  31574         }
  31575 
  31576         /* read a chunk of data from mem */
  31577         rv = soc_mem_read_range(unit, mem, copyno, index, index_end, buf);
  31578         if (rv < 0) {
  31579             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  31580                       (BSL_META_U(unit,
  31581                                   "soc_mem_read_range: "
  31582                                   "read %s.%s[%d-%d] failed: %s\n"),
  31583                        SOC_MEM_UFNAME(unit, mem),
  31584                        SOC_BLOCK_NAME(unit, copyno),
  31585                        index, index_end, soc_errmsg(rv)));
  31586             break;
  31587         }
  31588 
  31589 
  31590         /* Clear the field in each entry */
  31591         for (i = 0; i < chunk_entries; i++) {
  31592              soc_mem_field_set(unit, mem, &buf[i * entry_words],
  31593                                field, fval);
  31594         }
  31595 
  31596         /* Write back the entries to mem */
  31597         rv = soc_mem_write_range(unit, mem, copyno, index, index_end, buf);
  31598         if (rv < 0) {
  31599             LOG_ERROR(BSL_LS_SOC_SOCMEM,
  31600                       (BSL_META_U(unit,
  31601                                   "soc_mem_write_range: "
  31602                                   "write %s.%s[%d-%d] failed: %s\n"),
  31603                        SOC_MEM_UFNAME(unit, mem),
  31604                        SOC_BLOCK_NAME(unit, copyno),
  31605                        index, index_end, soc_errmsg(rv)));
  31606             break;
  31607         }
  31608     }
  31609 
  31610     MEM_UNLOCK(unit, mem);
  31611     soc_cm_sfree(unit, buf);
  31612     return rv;
  31613 }
  31614 #endif /* BCM_TRIUMPH3_SUPPORT */
  31615 
  31616 /* to setup L3_IIF default entries */
  31617 #if defined(BCM_HURRICANE3_SUPPORT)
  31618 int
  31619 _soc_hr3_l3iif_hw_mem_init(int unit, int force_init_all) 
  31620 {
  31621     schan_msg_t schan_msg;
  31622     int src_blk, dst_blk, blk, acc_type;
  31623     iif_entry_t def_entry;
  31624     uint8 at;
  31625     uint32 maddr;
  31626     int entry_dw, data_byte_len, idx;
  31627     int bit_num = 0, val = 0x3f;
  31628     int rv = SOC_E_NONE;
  31629 
  31630     /* 
  31631      * GH2 leverage design from HR3 with the same L3_IIFm design.
  31632      *  - both L3_IIFm size are 512 only.
  31633      */
  31634     if (!(SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) || 
  31635             !(SOC_MEM_IS_VALID(unit, L3_IIFm))) { 
  31636         return SOC_E_UNAVAIL;
  31637     }
  31638     sal_memcpy(&def_entry,  soc_mem_entry_null(unit, L3_IIFm),
  31639                sizeof(iif_entry_t));
  31640 
  31641     entry_dw = soc_mem_entry_words(unit, L3_IIFm);
  31642     data_byte_len = entry_dw * sizeof (uint32);
  31643     
  31644     /* 
  31645      * set default L3_IIFm.TRUST_DSCP_PTRf to maximum to prevent the 
  31646      * internal priority been changed unexpectedly.
  31647      *  - The L3_IIFm.TRUST_DSCP_PTRf in different ESW 
  31648      */
  31649     bit_num = soc_mem_field_length(unit, L3_IIFm, TRUST_DSCP_PTRf);
  31650     switch (bit_num) {
  31651         case 6:
  31652             val= 0x3f;
  31653             break;
  31654         case 7:
  31655             val = 0x7f;
  31656             break;
  31657         default :
  31658             break;
  31659     }
  31660 
  31661     soc_mem_field32_set(
  31662         unit, L3_IIFm, (uint32 *)&def_entry, TRUST_DSCP_PTRf, val);
  31663 
  31664     /* 
  31665      * Performing the low level mem write operation to avoid MEM and index 
  31666      * validation. In many HR3 SKUs, L3_IIFm is valid but entry count is 0.
  31667      * - that means "index_max" in SOC info for L3_IIFm will be -1
  31668      * - soc_mem_index_max() for this case can't report HW table size.
  31669      */
  31670     schan_msg_clear(&schan_msg);
  31671     acc_type = SOC_MEM_ACC_TYPE(unit, L3_IIFm);
  31672     src_blk = SOC_BLOCK2SCH(unit, CMIC_BLOCK(unit));
  31673     sal_memcpy(
  31674         schan_msg.writecmd.data, &def_entry, entry_dw * sizeof(uint32));
  31675 
  31676     LOG_INFO(BSL_LS_SOC_L3, 
  31677         (BSL_META_U(unit, "Installing default L3_IIFm entry..\n")));
  31678 
  31679     MEM_LOCK(unit, L3_IIFm);
  31680     if (SOC_IS_HURRICANE3(unit) &&
  31681         soc_feature(unit, soc_feature_l3) &&
  31682         soc_feature(unit, soc_feature_l3_iif_under_4k) == 0) {
  31683     for (idx = 0; idx < HR3_L3_IIF_HW_SIZE; idx ++){
  31684         /* Write to one or all copies of the memory */
  31685         SOC_MEM_BLOCK_ITER(unit, L3_IIFm, blk) {
  31686     
  31687             maddr = soc_mem_addr_get(unit, L3_IIFm, 0, blk, idx, &at);
  31688             schan_msg.writecmd.address = maddr;
  31689     
  31690                 soc_mem_dst_blk_update(unit, blk, maddr, &dst_blk);
  31691     
  31692                 soc_schan_header_cmd_set(
  31693                     unit, &schan_msg.header, WRITE_MEMORY_CMD_MSG,
  31694                     dst_blk, src_blk, acc_type, data_byte_len, 0, 0);
  31695     
  31696             /* Write header + address + entry_dw data DWORDs */
  31697             /* Note: The hardware does not send WRITE_MEMORY_ACK_MSG. */
  31698             if (2 + entry_dw > CMIC_SCHAN_WORDS(unit)) {
  31699                 LOG_WARN(BSL_LS_SOC_SOCMEM,
  31700                              (BSL_META_U(
  31701                                 unit, "soc_mem_write: "
  31702                                       "assert will fail for memory %s\n"),
  31703                         SOC_MEM_NAME(unit, L3_IIFm)));
  31704             }
  31705     
  31706                 rv = _soc_mem_write_schan_msg_send(
  31707                         unit, &schan_msg, L3_IIFm, blk, idx);
  31708             if (SOC_FAILURE(rv)) {
  31709                 break;
  31710             }
  31711         }
  31712         if (!force_init_all) {
  31713             break;
  31714         }
  31715     }
  31716     } else {
  31717         for (idx = 0; idx <= soc_mem_index_max(unit, L3_IIFm); idx++) {
  31718             rv = soc_mem_field32_modify(
  31719                     unit, L3_IIFm, idx, TRUST_DSCP_PTRf, val);
  31720         }
  31721     }
  31722     MEM_UNLOCK(unit, L3_IIFm);
  31723 
  31724     LOG_INFO(BSL_LS_SOC_L3, (BSL_META_U(unit, 
  31725             "L3_IIFm %d entries is installed(rv=%d)!\n") , idx, rv));
  31726 
  31727     return rv;
  31728 }
  31729 #endif  /* BCM_HURRICANE3_SUPPORT */
  31730 
  31731 #if defined(BCM_TOMAHAWK3_SUPPORT)
  31732 int
  31733 _soc_mem_cmp_l3_tunnel(int unit, void *ent_a, void *ent_b)
  31734 {
  31735     uint32 val_a, val_b;
  31736     uint32 buf_a[SOC_MAX_MEM_FIELD_WORDS];
  31737     uint32 buf_b[SOC_MAX_MEM_FIELD_WORDS];
  31738 
  31739     val_a = soc_mem_field32_get(unit, L3_TUNNEL_SINGLEm, ent_a, KEY_TYPEf);
  31740     val_b = soc_mem_field32_get(unit, L3_TUNNEL_SINGLEm, ent_b, KEY_TYPEf);
  31741     SOC_MEM_COMPARE_RETURN(val_a, val_b);
  31742 
  31743     switch (val_a) {
  31744     case TH3_TUNNEL_HASH_KEY_TYPE_MPLS:
  31745         val_a = soc_mem_field32_get(unit, L3_TUNNEL_SINGLEm, ent_a, MPLS__KEYf);
  31746         val_b = soc_mem_field32_get(unit, L3_TUNNEL_SINGLEm, ent_b, MPLS__KEYf);
  31747         
  31748         SOC_MEM_COMPARE_RETURN(val_a, val_b);
  31749 
  31750         return 0;
  31751 
  31752     case TH3_TUNNEL_HASH_KEY_TYPE_V4:
  31753         soc_mem_field_get(unit, L3_TUNNEL_DOUBLEm, ent_a, IPV4__KEY_0f, buf_a);
  31754         soc_mem_field_get(unit, L3_TUNNEL_DOUBLEm, ent_b, IPV4__KEY_0f, buf_b);
  31755         SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]);
  31756         SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]);
  31757         
  31758         SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]);
  31759 
  31760         soc_mem_field_get(unit, L3_TUNNEL_DOUBLEm, ent_a, IPV4__KEY_1f, buf_a);
  31761         soc_mem_field_get(unit, L3_TUNNEL_DOUBLEm, ent_b, IPV4__KEY_1f, buf_b);
  31762         SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]);
  31763 
  31764         return 0;
  31765 
  31766     case TH3_TUNNEL_HASH_KEY_TYPE_V6:
  31767         soc_mem_field_get(unit, L3_TUNNEL_QUADm, ent_a, IPV6__KEY_0f, buf_a);
  31768         soc_mem_field_get(unit, L3_TUNNEL_QUADm, ent_b, IPV6__KEY_0f, buf_b);
  31769         SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]);
  31770         SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]);
  31771         
  31772         SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]);
  31773 
  31774 
  31775         soc_mem_field_get(unit, L3_TUNNEL_QUADm, ent_a, IPV6__KEY_1f, buf_a);
  31776         soc_mem_field_get(unit, L3_TUNNEL_QUADm, ent_b, IPV6__KEY_1f, buf_b);
  31777         SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]);
  31778         SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]);
  31779         SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]);
  31780 
  31781         soc_mem_field_get(unit, L3_TUNNEL_QUADm, ent_a, IPV6__KEY_2f, buf_a);
  31782         soc_mem_field_get(unit, L3_TUNNEL_QUADm, ent_b, IPV6__KEY_2f, buf_b);
  31783         SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]);
  31784         SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]);
  31785 
  31786         soc_mem_field_get(unit, L3_TUNNEL_QUADm, ent_a, IPV6__KEY_3f, buf_a);
  31787         soc_mem_field_get(unit, L3_TUNNEL_QUADm, ent_b, IPV6__KEY_3f, buf_b);
  31788         SOC_MEM_COMPARE_RETURN(buf_a[2], buf_b[2]);
  31789         SOC_MEM_COMPARE_RETURN(buf_a[1], buf_b[1]);
  31790         SOC_MEM_COMPARE_RETURN(buf_a[0], buf_b[0]);
  31791 
  31792         return 0;
  31793 
  31794     default:
  31795         return 1;
  31796     }
  31797 
  31798     return 0;
  31799 }
  31800 #endif /* BCM_TOMAHAWK3_SUPPORT */
  31801 
  31802 
  31803 
  31804 void
  31805 soc_mem_field_acc_mode_get(
  31806     int unit,
  31807     soc_mem_t mem,
  31808     soc_field_t field,
  31809     uint32 *is_read_only,
  31810     uint32 *is_write_only)
  31811 {
  31812     soc_field_info_t *finfop;
  31813 
  31814     *is_read_only = 0;
  31815     *is_write_only = 0;
  31816 
  31817     if (!SOC_MEM_IS_VALID(unit, mem))
  31818     {
  31819 #if !defined(SOC_NO_NAMES)
  31820         LOG_CLI((BSL_META_U(unit, "msm %s is invalid\n"), soc_mem_name[mem]));
  31821 #endif
  31822         assert(SOC_MEM_IS_VALID(unit, mem));
  31823     }
  31824 
  31825     SOC_FIND_FIELD(field, SOC_MEM_INFO(unit, mem).fields, SOC_MEM_INFO(unit, mem).nFields, finfop);
  31826     if (finfop == NULL)
  31827     {
  31828 #if !defined(SOC_NO_NAMES)
  31829         LOG_CLI((BSL_META_U(unit, "mem %s field %s is invalid\n"), soc_mem_name[mem], soc_fieldnames[field]));
  31830 #endif
  31831         assert(finfop);
  31832     }
  31833 
  31834     if (finfop->flags & SOCF_RO)
  31835     {
  31836         *is_read_only = 1;
  31837     }
  31838 
  31839     if (finfop->flags & SOCF_WO)
  31840     {
  31841         *is_write_only = 1;
  31842     }
  31843 
  31844 }
  31845 
  31846 #endif /* defined(BCM_ESW_SUPPORT) || defined(BCM_SAND_SUPPORT) */