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

hash.c (74927B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        hash.c
      8  * Purpose:     Implement Trident3 specific hash flex bin selection APIs.
      9  *   Trident3 enhanced the RTAG7 hash module with the flexible bin selection
     10  * logic. It can overwrite the existing fixed bin selection logic. The flexible
     11  * logic uses a 128 entry deep TCAM. Each entry consists of the key and
     12  * policy. The key uses number of flex objects defined in the dynamically loaded
     13  * Cancun CEH. User will need to use the bcm_hash_flex_field_t parameter to
     14  * pass into the API.
     15  */
     16 
     17 #include <soc/drv.h>
     18 #include <soc/scache.h>
     19 
     20 #include <shared/bsl.h>
     21 #include <assert.h>
     22 #include <bcm/types.h>
     23 #include <bcm/error.h>
     24 #include <soc/drv.h>
     25 #include <soc/format.h>
     26 #include <soc/esw/cancun.h>
     27 #include <bcm/hash.h>
     28 #include <bcm_int/esw/switch.h>
     29 #include <bcm_int/esw/hash.h>
     30 #include <bcm_int/esw_dispatch.h>
     31 
     32 #if defined(BCM_TRIDENT3_SUPPORT)
     33 
     34 /* fixed packet type's corresponding fields and value */
     35 typedef struct {
     36     int         pkt_type;
     37     soc_format_t fmt;
     38     soc_field_t fld1;
     39     int         val1;
     40     soc_field_t fld2;
     41     int         val2;
     42 } _bcm_hash_pfld_info_t;
     43 
     44 /* fixed packet status corresponding fields and value */
     45 typedef struct {
     46     int         pkt_status;
     47     soc_field_t fld_mask;
     48     soc_field_t fld;
     49     int         bit_pos;
     50     int         fld_size;
     51 } _bcm_hash_sfld_info_t;
     52 
     53 /* TD3 flex objects */
     54 typedef struct {
     55     uint64 match_id;
     56     uint16 flow_id0;
     57     uint16 flow_id1;
     58     uint16 flow_id2;
     59     uint8  hve_ctrl1;
     60     uint8  hve_ctrl2;
     61 } _bcm_hash_td3_flex_obj_t;
     62 
     63 /* Flex field ID: object and field name id */
     64 #define FIELD_OBJ_ID(_id) ((_id) >> 24)
     65 #define FIELD_NAME_ID(_id) ((_id) & 0xFFFFFF)
     66 #define FIELD_OBJ_ID_SET(_id, _obj) ((_id) |  ((_obj) << 24))
     67 
     68 /* TD3 profile mem and field */
     69 #define _BCM_HASH_TD3_NUM_BINS_PER_SET   13
     70 #define _BCM_HASH_TD3_NUM_PROF_MEM       4
     71 
     72 #define PROF_BASE(_u, _num) \
     73 	(soc_mem_index_count((_u), FLEX_BIN_HASH_PROFILE_0m) * \
     74 	_BCM_HASH_TD3_NUM_BINS_PER_SET * (_num))
     75 #define BIN_INX(_u, _mn, _ent, _bn) (PROF_BASE((_u),(_mn)) + \
     76 	(_ent) * _BCM_HASH_TD3_NUM_BINS_PER_SET + \
     77 	(_bn) % _BCM_HASH_TD3_NUM_BINS_PER_SET)
     78 
     79 #define BIN_ID_SIZE8_VALID(_id)  ((((_id) >= BCM_HASH_BIN_A_0) && \
     80 	 ((_id) <= BCM_HASH_BIN_A_MAX)) || \
     81 	(((_id) >= BCM_HASH_BIN_A_0_UPPER_HALF) && \
     82 	 ((_id) <= BCM_HASH_BIN_A_UPPER_HALF_MAX)) || \
     83 	(((_id) >= BCM_HASH_BIN_B_0) && \
     84 	 ((_id) <= BCM_HASH_BIN_B_MAX)) || \
     85 	(((_id) >= BCM_HASH_BIN_B_0_UPPER_HALF) && \
     86 	 ((_id) <= BCM_HASH_BIN_B_UPPER_HALF_MAX)))
     87 
     88 #define BIN_ID_SIZE16_VALID(_id)  ((((_id) >= BCM_HASH_BIN_A_0) && \
     89 	 ((_id) <= BCM_HASH_BIN_A_MAX)) || \
     90 	(((_id) >= BCM_HASH_BIN_B_0) && \
     91 	 ((_id) <= BCM_HASH_BIN_B_MAX)))
     92 
     93 #define BIN_ID_VALID(_cfg, _id)  ( \
     94 	((_cfg)->option & BCM_HASH_FLEX_BIN_OPTION_SIZE_8BIT) ? \
     95 	BIN_ID_SIZE8_VALID((_id)) : \
     96 	BIN_ID_SIZE16_VALID((_id)))
     97 
     98 typedef struct {
     99     soc_mem_t   mem[_BCM_HASH_TD3_NUM_PROF_MEM];
    100     soc_field_t fld[_BCM_HASH_TD3_NUM_BINS_PER_SET];
    101 } _bcm_hash_prof_info_t;
    102 
    103 
    104 STATIC _bcm_hash_prof_info_t _bcm_hash_td3_prof_info = {
    105     {FLEX_BIN_HASH_PROFILE_0m, FLEX_BIN_HASH_PROFILE_1m,
    106      FLEX_BIN_HASH_PROFILE_2m, FLEX_BIN_HASH_PROFILE_3m},
    107     {HASH_BIN_0f, HASH_BIN_1f, HASH_BIN_2f, HASH_BIN_3f,
    108      HASH_BIN_4f, HASH_BIN_5f, HASH_BIN_6f, HASH_BIN_7f,
    109      HASH_BIN_8f, HASH_BIN_9f, HASH_BIN_10f, HASH_BIN_11f,
    110      HASH_BIN_12f}
    111 };
    112 
    113 STATIC _bcm_hash_sfld_info_t _bcm_hash_td3_sfld_info[] = {
    114     {BCM_HASH_PKT_STATUS_GTP_ENDPOINT_ID, 
    115      GTP_ENDPOINT_ID_VALID_MASKf, GTP_ENDPOINT_ID_VALIDf, 0, 1},
    116 
    117     {BCM_HASH_PKT_STATUS_L3_FORWARDED, 
    118      L3_FORWARDED_MASKf, L3_FORWARDEDf, 0, 1},
    119 
    120     {BCM_HASH_PKT_STATUS_TUNNEL_TERM, 
    121      TUNNEL_TERM_STATUS_MASKf, TUNNEL_TERM_STATUSf, 0, 1},
    122 
    123     /* end marker */
    124     {BCM_HASH_PKT_STATUS_MAX, INVALIDm, INVALIDm, 0, 0},
    125 };
    126 
    127 STATIC _bcm_hash_pfld_info_t _bcm_hash_td3_pfld_info[] = {
    128     {BCM_HASH_PKT_FLOW_TYPE_FRONT_PANEL, PKT_FLOW_ID_0_FORMATfmt,
    129      MACRO_FLOW_ID_FIXEDf, 1, MICRO_FLOW_TYPE_FIXED_FRONT_PANELf, 0},
    130 
    131     {BCM_HASH_PKT_FLOW_TYPE_FRONT_PANEL_SYSTEM_HDR_PROXY, 
    132      PKT_FLOW_ID_0_FORMATfmt,
    133      MACRO_FLOW_ID_FIXEDf, 1, MICRO_FLOW_TYPE_FIXED_FRONT_PANELf, 1},
    134    
    135     {BCM_HASH_PKT_FLOW_TYPE_FRONT_PANEL_LOOPBACK_GENERIC, 
    136      PKT_FLOW_ID_0_FORMATfmt,
    137      MACRO_FLOW_ID_FIXEDf, 1, MICRO_FLOW_TYPE_FIXED_FRONT_PANELf, 6},
    138    
    139     {BCM_HASH_PKT_FLOW_TYPE_FRONT_PANEL_LOOPBACK_TUNNEL_TERM, 
    140      PKT_FLOW_ID_0_FORMATfmt,
    141      MACRO_FLOW_ID_FIXEDf, 1, MICRO_FLOW_TYPE_FIXED_FRONT_PANELf, 7},
    142    
    143     {BCM_HASH_PKT_FLOW_TYPE_SYSTEM_HDR, 
    144      PKT_FLOW_ID_0_FORMATfmt,
    145      MACRO_FLOW_ID_FIXEDf, 2, MICRO_FLOW_TYPE_FIXED_SYSTEM_HDRf, 0},
    146    
    147     {BCM_HASH_PKT_FLOW_TYPE_SYSTEM_HDR_CONTROL, 
    148      PKT_FLOW_ID_0_FORMATfmt,
    149      MACRO_FLOW_ID_FIXEDf, 2, MICRO_FLOW_TYPE_FIXED_SYSTEM_HDRf, 0},
    150    
    151     {BCM_HASH_PKT_FLOW_TYPE_SYSTEM_HDR_UNICAST, 
    152      PKT_FLOW_ID_0_FORMATfmt,
    153      MACRO_FLOW_ID_FIXEDf, 2, MICRO_FLOW_TYPE_FIXED_SYSTEM_HDRf, 1},
    154    
    155     {BCM_HASH_PKT_FLOW_TYPE_SYSTEM_HDR_FLOOD, 
    156      PKT_FLOW_ID_0_FORMATfmt,
    157      MACRO_FLOW_ID_FIXEDf, 2, MICRO_FLOW_TYPE_FIXED_SYSTEM_HDRf, 2},
    158    
    159     {BCM_HASH_PKT_FLOW_TYPE_SYSTEM_HDR_L2_MULTICAST, 
    160      PKT_FLOW_ID_0_FORMATfmt,
    161      MACRO_FLOW_ID_FIXEDf, 2, MICRO_FLOW_TYPE_FIXED_SYSTEM_HDRf, 3},
    162    
    163     {BCM_HASH_PKT_FLOW_TYPE_SYSTEM_HDR_L3_MULTICAST, 
    164      PKT_FLOW_ID_0_FORMATfmt,
    165      MACRO_FLOW_ID_FIXEDf, 2, MICRO_FLOW_TYPE_FIXED_SYSTEM_HDRf, 4},
    166    
    167     {BCM_HASH_PKT_FLOW_TYPE_TUNNEL_VXLAN, 
    168      PKT_FLOW_ID_1_FORMATfmt,
    169      MACRO_FLOW_ID_FIXEDf, 4, INVALIDf, 0},
    170    
    171     {BCM_HASH_PKT_FLOW_TYPE_TUNNEL_NVGRE, 
    172      PKT_FLOW_ID_1_FORMATfmt,
    173      MACRO_FLOW_ID_FIXEDf, 3, INVALIDf, 0},
    174    
    175     {BCM_HASH_PKT_FLOW_TYPE_TUNNEL_MIM, 
    176      PKT_FLOW_ID_1_FORMATfmt,
    177      MACRO_FLOW_ID_FIXEDf, 2, INVALIDf, 0},
    178    
    179     {BCM_HASH_PKT_FLOW_TYPE_TUNNEL_IPINIP, 
    180      PKT_FLOW_ID_1_FORMATfmt,
    181      MACRO_FLOW_ID_FIXEDf, 5, INVALIDf, 0},
    182    
    183     {BCM_HASH_PKT_FLOW_TYPE_TUNNEL_MPLS, 
    184      PKT_FLOW_ID_1_FORMATfmt,
    185      MACRO_FLOW_ID_FIXEDf, 6, INVALIDf, 0},
    186    
    187     {BCM_HASH_PKT_FLOW_TYPE_LAYER_L2, 
    188      PKT_FLOW_ID_2_FORMATfmt,
    189      MACRO_FLOW_ID_FIXEDf, 2, INVALIDf, 0},
    190    
    191     {BCM_HASH_PKT_FLOW_TYPE_LAYER_L3, 
    192      PKT_FLOW_ID_2_FORMATfmt,
    193      MACRO_FLOW_ID_FIXEDf, 3, INVALIDf, 0},
    194 
    195     /* end marker */
    196     {BCM_HASH_PKT_TYPE_MAX, INVALIDfmt, INVALIDf, 0, INVALIDf, 0},
    197 };
    198 
    199 /* TD3 flex object names */
    200 STATIC char *_bcm_hash_td3_obj_names[] = {
    201     "Z0_MATCH_ID",
    202     "Z1_MATCH_ID",
    203     "Z2_MATCH_ID",
    204     "Z3_MATCH_ID",
    205     "Z4_MATCH_ID",
    206     "PKT_FLOW_ID_0",
    207     "PKT_FLOW_ID_1",
    208     "PKT_FLOW_ID_2",
    209     "HVE_CONTROL_1",
    210     "HVE_CONTROL_2"
    211 };
    212     
    213 STATIC uint8 _bcm_hash_td3_cmd_offset[BCM_HASH_OBJ_OFFSET_MAX];
    214 STATIC uint8 _bcm_hash_td3_cmd_obj[BCM_HASH_OBJ_ID_MAX];
    215 
    216 STATIC int _bcm_hash_td3_flex_field_get(int unit, int num_fields,
    217     bcm_hash_flex_field_t *flex_field, _bcm_hash_td3_flex_obj_t *flex_obj,
    218     _bcm_hash_td3_flex_obj_t *flex_obj_mask);
    219 STATIC int _bcm_hash_td3_flex_field_add(int unit, int num_fields,
    220     bcm_hash_flex_field_t *flex_field, _bcm_hash_td3_flex_obj_t *flex_obj,
    221     _bcm_hash_td3_flex_obj_t *flex_obj_mask);
    222 STATIC int _bcm_td3_hash_flex_bin_delete_all(int unit);
    223 
    224 #ifdef BCM_WARM_BOOT_SUPPORT
    225 
    226 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1, 0)
    227 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_0
    228 
    229 /*
    230  * Function:
    231  *      _bcm_hash_td3_fbin_wb_alloc
    232  * Purpose:
    233  *      Alloc persisitent memory for Level 2 Warm Boot scache.
    234  * Parameters:
    235  *      unit - (IN) Device Unit Number.
    236  * Returns:
    237  *      BCM_E_XXX
    238  */
    239 
    240 STATIC int
    241 _bcm_hash_td3_fbin_wb_alloc (int unit)
    242 {
    243     int alloc_sz = 0, rv = BCM_E_NONE;
    244     soc_scache_handle_t scache_handle;
    245     uint8 *hash_scache_ptr = NULL;
    246     int stable_size;
    247 
    248     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
    249 
    250     if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) {
    251         return BCM_E_NONE;
    252     }
    253 
    254     alloc_sz = soc_mem_index_count(unit, FLEX_BIN_HASH_PROFILE_0m);
    255     alloc_sz *= _BCM_HASH_TD3_NUM_PROF_MEM;
    256     alloc_sz *= _BCM_HASH_TD3_NUM_BINS_PER_SET;
    257     alloc_sz *= sizeof(uint16);
    258 
    259     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_HASH, 0);
    260     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE,
    261                                  alloc_sz, (uint8**)&hash_scache_ptr,
    262                                  BCM_WB_DEFAULT_VERSION, NULL);
    263     if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
    264         return rv;
    265     }
    266 
    267     return BCM_E_NONE;
    268 }
    269 
    270 /*
    271  * Function:
    272  *      _bcm_hash_td3_fbin_wb_recover
    273  * Purpose:
    274  *      Recover hash flex bin module info for Level 2 Warm Boot from
    275  *      persisitent memory.
    276  * Parameters:
    277  *      unit - (IN) Device Unit Number.
    278  *
    279  * Returns:
    280  *      BCM_E_XXX
    281  */
    282 
    283 STATIC int
    284 _bcm_hash_td3_fbin_wb_recover (int unit)
    285 {
    286     int sz = 0, rv = BCM_E_NONE;
    287     int stable_size;
    288     uint16 recovered_ver = 0;
    289     uint8 *hash_scache_ptr = NULL;
    290     soc_scache_handle_t scache_handle;
    291     bcmi_hash_flex_bin_info_t *info;
    292 
    293     info = &bcmi_hash_flex_bin_info[unit];
    294 
    295     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
    296 
    297     /* Requires extended scache support level-2 warmboot */
    298     if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) {
    299         return BCM_E_NONE;
    300     }
    301     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_HASH, 0);
    302     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    303                                  0, &hash_scache_ptr,
    304                                  BCM_WB_DEFAULT_VERSION, &recovered_ver);
    305     if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
    306         return rv;
    307     } else if (rv == BCM_E_NOT_FOUND) {
    308         return _bcm_hash_td3_fbin_wb_alloc(unit);
    309     }
    310 
    311     if (hash_scache_ptr != NULL) {
    312         sz = soc_mem_index_count(unit, FLEX_BIN_HASH_PROFILE_0m);
    313         sz *= _BCM_HASH_TD3_NUM_PROF_MEM;
    314         sz *= _BCM_HASH_TD3_NUM_BINS_PER_SET;
    315         sz *= sizeof(uint16);
    316 
    317         /* recover bin object id array */
    318         sal_memcpy(info->bin_obj_arr, hash_scache_ptr, sz);
    319         hash_scache_ptr += sz;
    320     }
    321     return BCM_E_NONE;
    322 }
    323 
    324 /*
    325  * Function:
    326  *      _bcm_hash_td3_fbin_reinit
    327  * Purpose:
    328  *      Warm boot recovery for the hash flex bin module
    329  * Parameters:
    330  *      unit     - Device Number
    331  * Returns:
    332  *      BCM_E_XXX
    333  */
    334 
    335 STATIC int
    336 _bcm_hash_td3_fbin_reinit (int unit)
    337 {
    338     int rv;
    339     int i;
    340     int size;
    341     bcmi_hash_flex_bin_info_t *info;
    342     flex_rtag7_hash_tcam_entry_t rule_entry;
    343     soc_mem_t mem;
    344 
    345     info = &bcmi_hash_flex_bin_info[unit];
    346     mem  = FLEX_RTAG7_HASH_TCAMm;
    347 
    348     /* recover entry usage bitmap from hardware */
    349     size = soc_mem_index_count(unit, mem);
    350     for (i = 0; i < size; i++) {
    351         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, i,
    352                  &rule_entry);
    353         SOC_IF_ERROR_RETURN(rv);
    354 
    355         if (soc_mem_field32_get(unit, mem, &rule_entry, VALIDf)) {
    356             SHR_BITSET(info->entry_bmp, i);
    357         }
    358     }
    359 
    360     /* Recover L2 scache */
    361     rv = _bcm_hash_td3_fbin_wb_recover(unit);
    362     BCM_IF_ERROR_RETURN(rv);
    363 
    364     return BCM_E_NONE;
    365 }
    366 
    367 /*
    368  * Function:
    369  *      bcmi_td3_hash_flex_bin_sync
    370  * Purpose:
    371  *      Record hash flex bin module persistent info for Level 2 Warm Boot.
    372  * Parameters:
    373  *      unit - (IN) Device Unit Number.
    374  *
    375  * Returns:
    376  *      BCM_E_XXX
    377  */
    378 
    379 int
    380 bcmi_td3_hash_flex_bin_sync(int unit)
    381 {
    382     int sz = 0, rv = BCM_E_NONE;
    383     int stable_size;
    384     uint8 *hash_scache_ptr = NULL;
    385     soc_scache_handle_t scache_handle;
    386     bcmi_hash_flex_bin_info_t *info;
    387 
    388     if (!soc_feature(unit, soc_feature_hash_flex_bin)) {
    389         return BCM_E_UNAVAIL;
    390     }
    391 
    392     info = &bcmi_hash_flex_bin_info[unit];
    393 
    394     if (info->initialized == FALSE) {
    395          return BCM_E_INIT;
    396     }
    397 
    398     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
    399 
    400     /* Requires extended scache support level-2 warmboot */
    401     if ((stable_size == 0) || (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) {
    402         return BCM_E_NONE;
    403     }
    404 
    405     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_HASH, 0);
    406     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    407                                  0, &hash_scache_ptr,
    408                                  BCM_WB_DEFAULT_VERSION, NULL);
    409     if (BCM_FAILURE(rv) && (rv != BCM_E_INTERNAL)) {
    410         return rv;
    411     }
    412 
    413     if (hash_scache_ptr != NULL) {
    414         sz = soc_mem_index_count(unit, FLEX_BIN_HASH_PROFILE_0m);
    415         sz *= _BCM_HASH_TD3_NUM_PROF_MEM;
    416         sz *= _BCM_HASH_TD3_NUM_BINS_PER_SET;
    417         sz *= sizeof(uint16);
    418 
    419         /* recover bin object id array */
    420         sal_memcpy(hash_scache_ptr, info->bin_obj_arr, sz);
    421         hash_scache_ptr += sz;
    422     }
    423     return BCM_E_NONE;
    424 }
    425 
    426 #endif /*  BCM_WARM_BOOT_SUPPORT */
    427 
    428 /*
    429  * Function:
    430  *   bcmi_td3_hash_flex_bin_init
    431  * Purpose:
    432  *   Initialize the TD3 hash flex bin module. Should only be called during
    433  * initialization stage.
    434  *
    435  * Parameters:
    436  *   unit    - (IN)    Unit ID.
    437  */
    438 
    439 int bcmi_td3_hash_flex_bin_init (int unit)
    440 {
    441     bcmi_hash_flex_bin_info_t *info;
    442     uint8 *cmd_offset;
    443     uint8 *cmd_obj;
    444     int offset;
    445     int size;
    446     int rv = BCM_E_NONE;
    447 
    448     info = &bcmi_hash_flex_bin_info[unit];
    449 
    450     if (info->entry_bmp != NULL) {
    451         sal_free(info->entry_bmp);
    452          info->entry_bmp = NULL;
    453     }
    454 
    455     /* allocate the TCAM entry usage bitmap */
    456     size = soc_mem_index_count(unit, FLEX_RTAG7_HASH_TCAMm);
    457     size = SHR_BITALLOCSIZE(size);
    458     info->entry_bmp = sal_alloc(size, "Hash flex bin TCAM usage bitmap");
    459     if (info->entry_bmp == NULL) {
    460         rv = BCM_E_MEMORY;
    461         goto exit;
    462     }
    463     sal_memset(info->entry_bmp, 0, size);
    464 
    465     /* allocate buffer to record the bin command object id 
    466      * TD3 objects have overlays. Multiple objects can map to the same hardware
    467      * value. So the correct object Id cannot be retrieved from hardware.
    468      */
    469     if (info->bin_obj_arr != NULL) {
    470         sal_free(info->bin_obj_arr);
    471          info->bin_obj_arr = NULL;
    472     }
    473     size = soc_mem_index_count(unit, FLEX_BIN_HASH_PROFILE_0m);
    474     size *= _BCM_HASH_TD3_NUM_PROF_MEM;
    475     size *= _BCM_HASH_TD3_NUM_BINS_PER_SET;
    476     size *= sizeof(uint16);
    477     info->bin_obj_arr = sal_alloc(size, "Hash flex bin object id map");
    478     if (info->bin_obj_arr == NULL) {
    479         rv = BCM_E_MEMORY;
    480         goto exit;
    481     }
    482     sal_memset(info->bin_obj_arr, 0, size);
    483 
    484     /* This is TD3 specific command offset mapping */
    485     cmd_obj     = _bcm_hash_td3_cmd_obj;
    486     cmd_offset  = _bcm_hash_td3_cmd_offset; 
    487 
    488     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT0] = 0;
    489     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT4] = 1;
    490     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT8] = 2;
    491     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT12] = 3;
    492     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT16] = 4;
    493     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT20] = 5;
    494     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT24] = 6;
    495     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT28] = 7;
    496     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT32] = 8;
    497     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT36] = 9;
    498     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT40] = 10;
    499     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT44] = 11;
    500     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT48] = 12;
    501     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT52] = 13;
    502     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT56] = 14;
    503     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT60] = 15;
    504     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT64] = 16;
    505     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT68] = 17;
    506     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT72] = 18;
    507     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT76] = 19;
    508     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT80] = 20;
    509     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT84] = 21;
    510     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT88] = 22;
    511     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT92] = 23;
    512     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT96] = 24;
    513     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT100] = 25;
    514     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT104] = 26;
    515     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT108] = 27;
    516     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT112] = 28;
    517     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT116] = 29;
    518     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT120] = 30;
    519     cmd_offset[BCM_HASH_OBJ_OFFSET_BIT124] = 31;
    520 
    521     /* hash object bus container */
    522     cmd_obj[BCM_HASH_OBJ_SGPP]        = 96;
    523     cmd_obj[BCM_HASH_OBJ_SVP]         = 97;
    524     cmd_obj[BCM_HASH_OBJ_OUTER_PROTO] = 98;
    525     cmd_obj[BCM_HASH_OBJ_HG_LBID]     = 99;
    526     cmd_obj[BCM_HASH_OBJ_OUTER_SIP]   = 100;
    527     cmd_obj[BCM_HASH_OBJ_OUTER_DIP]   = 101;
    528     cmd_obj[BCM_HASH_OBJ_OUTER_SIP_NORMALIZED] = 102;
    529     cmd_obj[BCM_HASH_OBJ_OUTER_DIP_NORMALIZED] = 103;
    530     cmd_obj[BCM_HASH_OBJ_INNER_SIP]   = 104;
    531     cmd_obj[BCM_HASH_OBJ_INNER_DIP]   = 105;
    532     cmd_obj[BCM_HASH_OBJ_INNER_SIP_NORMALIZED] = 106;
    533     cmd_obj[BCM_HASH_OBJ_INNER_DIP_NORMALIZED] = 107;
    534     cmd_obj[BCM_HASH_OBJ_OUTER_L4_SRC_PORT]    = 108;
    535     cmd_obj[BCM_HASH_OBJ_OUTER_L4_DEST_PORT]   = 109;
    536     cmd_obj[BCM_HASH_OBJ_INNER_L4_SRC_PORT]    = 110;
    537     cmd_obj[BCM_HASH_OBJ_INNER_L4_DEST_PORT]   = 111;
    538     cmd_obj[BCM_HASH_OBJ_OUTER_L4_SRC_PORT_NORMALIZED]  = 112;
    539     cmd_obj[BCM_HASH_OBJ_OUTER_L4_DEST_PORT_NORMALIZED] = 113;
    540     cmd_obj[BCM_HASH_OBJ_INNER_L4_SRC_PORT_NORMALIZED]  = 114;
    541     cmd_obj[BCM_HASH_OBJ_INNER_L4_DEST_PORT_NORMALIZED] = 115;
    542     cmd_obj[BCM_HASH_OBJ_INNER_PROTO]          = 116; 
    543     cmd_obj[BCM_HASH_OBJ_MPLS_LABEL_1]         = 117; 
    544     cmd_obj[BCM_HASH_OBJ_MPLS_LABEL_2]         = 118;
    545     cmd_obj[BCM_HASH_OBJ_MPLS_LABEL_3]         = 119;
    546     cmd_obj[BCM_HASH_OBJ_MPLS_LABEL_4]         = 120;
    547     cmd_obj[BCM_HASH_OBJ_MPLS_LABEL_5]         = 121;
    548 
    549     /* field bus 1 */
    550     cmd_obj[BCM_HASH_OBJ_OUTER_MAC_SA] = 0;
    551     cmd_obj[BCM_HASH_OBJ_OUTER_MAC_DA] = 0;
    552     cmd_obj[BCM_HASH_OBJ_OUTER_VNTAG_ETAG]  = 1;
    553     cmd_obj[BCM_HASH_OBJ_OUTER_OTAG]   = 2;
    554     cmd_obj[BCM_HASH_OBJ_OUTER_ITAG]   = 3;
    555     cmd_obj[BCM_HASH_OBJ_OUTER_CNTAG]  = 4;
    556     cmd_obj[BCM_HASH_OBJ_OUTER_ETHTYPE] = 5;
    557     cmd_obj[BCM_HASH_OBJ_OUTER_IPV6_SIP]    = 6;
    558     cmd_obj[BCM_HASH_OBJ_OUTER_IPV4_HEADER] = 6;
    559     cmd_obj[BCM_HASH_OBJ_OUTER_IPV4_SIP]    = 6;
    560     cmd_obj[BCM_HASH_OBJ_OUTER_IPV6_HEADER1]    = 7;
    561     cmd_obj[BCM_HASH_OBJ_OUTER_IPV4_DIP]        = 7;
    562     cmd_obj[BCM_HASH_OBJ_OUTER_IPV6_DIP]        = 8;
    563     cmd_obj[BCM_HASH_OBJ_OUTER_IPV6_HEADER2]    = 9;
    564     cmd_obj[BCM_HASH_OBJ_OUTER_GRE_HEADER] = 10;
    565     cmd_obj[BCM_HASH_OBJ_OUTER_L4]     = 10;
    566     cmd_obj[BCM_HASH_OBJ_OUTER_L5]     = 12;
    567     cmd_obj[BCM_HASH_OBJ_OUTER_VXLAN]  = 12;
    568     cmd_obj[BCM_HASH_OBJ_OUTER_UDF0_0] = 13;
    569     cmd_obj[BCM_HASH_OBJ_OUTER_UDF0_1] = 14;
    570     cmd_obj[BCM_HASH_OBJ_OUTER_UDF0_2] = 15;
    571     cmd_obj[BCM_HASH_OBJ_OUTER_UDF0_3] = 16;
    572     cmd_obj[BCM_HASH_OBJ_OUTER_UDF0_4] = 17;
    573     cmd_obj[BCM_HASH_OBJ_OUTER_UDF0_5] = 18;
    574     cmd_obj[BCM_HASH_OBJ_OUTER_UDF0_6] = 19;
    575     cmd_obj[BCM_HASH_OBJ_OUTER_UDF0_7] = 20;
    576     cmd_obj[BCM_HASH_OBJ_OUTER_UDF1_0] = 21;
    577     cmd_obj[BCM_HASH_OBJ_OUTER_UDF1_1] = 22;
    578     cmd_obj[BCM_HASH_OBJ_OUTER_UDF1_2] = 23;
    579     cmd_obj[BCM_HASH_OBJ_OUTER_UDF1_3] = 24;
    580     cmd_obj[BCM_HASH_OBJ_OUTER_UDF1_4] = 25;
    581     cmd_obj[BCM_HASH_OBJ_OUTER_UDF1_5] = 26;
    582     cmd_obj[BCM_HASH_OBJ_OUTER_UDF1_6] = 27;
    583     cmd_obj[BCM_HASH_OBJ_OUTER_UDF1_7] = 28;
    584     cmd_obj[BCM_HASH_OBJ_OUTER_TOS] = 29;
    585     cmd_obj[BCM_HASH_OBJ_OUTER_TTL] = 30;
    586     cmd_obj[BCM_HASH_OBJ_SUBPORT_TAG] = 31;
    587     
    588     /* field bus 2  */
    589     offset = 48;
    590     cmd_obj[BCM_HASH_OBJ_INNER_MAC_SA] = (offset + 0);
    591     cmd_obj[BCM_HASH_OBJ_INNER_MAC_DA] = (offset + 0);
    592     cmd_obj[BCM_HASH_OBJ_INNER_VNTAG_ETAG]  = (offset + 1);
    593     cmd_obj[BCM_HASH_OBJ_INNER_OTAG]   = (offset + 2);
    594     cmd_obj[BCM_HASH_OBJ_INNER_ITAG]   = (offset + 3);
    595     cmd_obj[BCM_HASH_OBJ_INNER_CNTAG]  = (offset + 4);
    596     cmd_obj[BCM_HASH_OBJ_INNER_ETHTYPE] = (offset + 5);
    597     cmd_obj[BCM_HASH_OBJ_INNER_IPV6_SIP]    = (offset + 6);
    598     cmd_obj[BCM_HASH_OBJ_INNER_IPV4_HEADER] = (offset + 6);
    599     cmd_obj[BCM_HASH_OBJ_INNER_IPV4_SIP]    = (offset + 6);
    600     cmd_obj[BCM_HASH_OBJ_INNER_IPV6_HEADER1]    = (offset + 7);
    601     cmd_obj[BCM_HASH_OBJ_INNER_IPV4_DIP]        = (offset + 7);
    602     cmd_obj[BCM_HASH_OBJ_INNER_IPV6_DIP]        = (offset + 8);
    603     cmd_obj[BCM_HASH_OBJ_INNER_IPV6_HEADER2]    = (offset + 9);
    604     cmd_obj[BCM_HASH_OBJ_INNER_GRE_HEADER] = (offset + 10);
    605     cmd_obj[BCM_HASH_OBJ_INNER_L4]         = (offset + 10);  
    606     cmd_obj[BCM_HASH_OBJ_INNER_VXLAN]   = (offset + 12);
    607     cmd_obj[BCM_HASH_OBJ_INNER_L5]      = (offset + 12);
    608     cmd_obj[BCM_HASH_OBJ_INNER_UDF0_0]  = (offset + 13);
    609     cmd_obj[BCM_HASH_OBJ_INNER_UDF0_1]  = (offset + 14);
    610     cmd_obj[BCM_HASH_OBJ_INNER_UDF0_2] = (offset + 15);
    611     cmd_obj[BCM_HASH_OBJ_INNER_UDF0_3] = (offset + 16);
    612     cmd_obj[BCM_HASH_OBJ_INNER_UDF0_4] = (offset + 17);
    613     cmd_obj[BCM_HASH_OBJ_INNER_UDF0_5] = (offset + 18);
    614     cmd_obj[BCM_HASH_OBJ_INNER_UDF0_6] = (offset + 19);
    615     cmd_obj[BCM_HASH_OBJ_INNER_UDF0_7] = (offset + 20);
    616     cmd_obj[BCM_HASH_OBJ_INNER_UDF1_0] = (offset + 21);
    617     cmd_obj[BCM_HASH_OBJ_INNER_UDF1_1] = (offset + 22);
    618     cmd_obj[BCM_HASH_OBJ_INNER_UDF1_2] = (offset + 23);
    619     cmd_obj[BCM_HASH_OBJ_INNER_UDF1_3] = (offset + 24);
    620     cmd_obj[BCM_HASH_OBJ_INNER_UDF1_4] = (offset + 25);
    621     cmd_obj[BCM_HASH_OBJ_INNER_UDF1_5] = (offset + 26);
    622     cmd_obj[BCM_HASH_OBJ_INNER_UDF1_6] = (offset + 27);
    623     cmd_obj[BCM_HASH_OBJ_INNER_UDF1_7] = (offset + 28);
    624     cmd_obj[BCM_HASH_OBJ_INNER_TOS]    = (offset + 29);
    625     cmd_obj[BCM_HASH_OBJ_INNER_TTL]    = (offset + 30);
    626 
    627 #ifdef BCM_WARM_BOOT_SUPPORT
    628     if (SOC_WARM_BOOT(unit)) {
    629         rv = _bcm_hash_td3_fbin_reinit(unit);
    630         if (BCM_FAILURE(rv)) {
    631             goto exit;
    632         }
    633     } else {
    634         rv = _bcm_td3_hash_flex_bin_delete_all(unit);
    635         if (BCM_FAILURE(rv)) {
    636             goto exit;
    637         }
    638         rv = _bcm_hash_td3_fbin_wb_alloc(unit);
    639         if (BCM_FAILURE(rv)) {
    640             goto exit;
    641         }
    642     }
    643 #else
    644     rv = _bcm_td3_hash_flex_bin_delete_all(unit);
    645     if (BCM_FAILURE(rv)) {
    646         goto exit;
    647     }
    648 #endif /* BCM_WARM_BOOT_SUPPORT */
    649 
    650     info->initialized = TRUE;
    651     return BCM_E_NONE;
    652 
    653 exit:
    654     if (info->entry_bmp) {
    655         sal_free (info->entry_bmp);
    656         info->entry_bmp = NULL;
    657     }
    658     if (info->bin_obj_arr) {
    659         sal_free (info->bin_obj_arr);
    660         info->bin_obj_arr = NULL;
    661     }
    662     return rv;
    663 }
    664 
    665 /*
    666  * Function:
    667  *     bcmi_td3_hash_flex_field_id_get
    668  * Description:
    669  *     Get the field_id from the flex object's field name. In Trident3,
    670  * the flex objects are defined in the ceh.yml file. Each object defines a
    671  * list of flex fields. For example:
    672  *   Flex object:  Z1_MATCH_ID
    673  *   Field:        ETAG
    674  * The ceh.yml file is packaged and loaded in the runtime.
    675  *
    676  * Parameters:
    677  *    Unit           (IN) Unit number
    678  *    object         (IN) Flex object id
    679  *    field_name     (IN) Field name
    680  *    field_id       (OUT) field ID
    681  *
    682  * Return Value:
    683  *      BCM_E_XXX
    684  * Notes:
    685  *    This API is used for bcm_hash_flex_bin_add API's flex field.
    686  */
    687 
    688 int
    689 bcmi_td3_hash_flex_field_id_get (
    690     int unit,
    691     bcm_hash_flex_object_t object,
    692     const char *field_name,
    693     uint32 *field_id)
    694 {
    695     int rv;
    696     
    697     *field_id = 0;
    698     rv = soc_cancun_ceh_obj_field_id_get(unit, (char *)field_name, field_id);
    699     SOC_IF_ERROR_RETURN(rv);
    700 
    701     *field_id |= object << 24;
    702     return BCM_E_NONE;
    703 }
    704 
    705 /*
    706  * Function:
    707  *     bcmi_td3_hash_flex_field_name_get
    708  * Description:
    709  *     Get the flex object ID and field name from the field_id. In Trident3,
    710  * the flex objects are defined in the ceh.yml file. Each object defines a
    711  * list of flex fields. For example:
    712  *   Flex object:  Z1_MATCH_ID
    713  *   Field:        ETAG
    714  * The ceh.yml file is packaged and loaded in the runtime.
    715  *
    716  * Parameters:
    717  *    unit           (IN) Unit number
    718  *    field_id       (IN) flex field ID
    719  *    object         (OUT) Flex object id
    720  *    size           (IN) size of the field name buffer
    721  *    field_name     (OUT) Field name buffer
    722  *
    723  * Return Value:
    724  *      BCM_E_XXX
    725  * Notes:
    726  *    This API is used for bcm_hash_flex_bin_get API's flex field.
    727  */
    728 
    729 int
    730 bcmi_td3_hash_flex_field_name_get (
    731     int unit,
    732     uint32 field_id,
    733     bcm_hash_flex_object_t *object,
    734     int *size,
    735     char *field_name)
    736 {
    737     int rv;
    738    
    739     *object = FIELD_OBJ_ID(field_id);
    740     rv = soc_cancun_ceh_obj_field_name_get(unit, FIELD_NAME_ID(field_id), 
    741              size, field_name);
    742     SOC_IF_ERROR_RETURN(rv);
    743 
    744     return BCM_E_NONE;
    745 }
    746 
    747 /*
    748  * Function:
    749  *   bcmi_td3_hash_flex_bin_add
    750  * Purpose:
    751  *   Specify the flex bin selection rule and write to the TCAM entry. Higher
    752  * entry_id has high priority during TCAM lookup in case of multiple rules
    753  * are matched. If entry_id is not specified, i.e. option
    754  * BCM_HASH_FLEX_BIN_OPTION_WITH_ID is not given, then a lowest available
    755  * entry_id is automatically assigned.
    756  *
    757  * Parameters:
    758  *   unit     - (IN)    Unit ID.
    759  *   cfg      - (INOUT) Key part of selection rule and other parameters
    760  *   num_bins - (IN)   Number of bin cmds.
    761  *   bin_cmd  - (IN) Array of bin commands. Policy data part of rule.
    762  *   num_fields - (IN) Number of flex fields.
    763  *   flex_field - (IN) Array of flex fields.
    764  */
    765 
    766 int
    767 bcmi_td3_hash_flex_bin_add (int unit,
    768     bcm_hash_flex_bin_config_t *cfg,
    769     int num_bins,
    770     bcm_hash_flex_bin_cmd_t *bin_cmd,
    771     int num_fields,
    772     bcm_hash_flex_field_t *flex_field)
    773 {
    774     soc_mem_t mem;
    775     int ix,iy;
    776     int tcam_size;
    777     flex_rtag7_hash_tcam_entry_t rule_entry;
    778     flex_bin_hash_profile_0_entry_t prof_entry;
    779     flex_bin_hash_profile_0_entry_t prof_entry1;
    780     flex_bin_hash_profile_0_entry_t prof_entry2;
    781     flex_bin_hash_profile_0_entry_t prof_entry3;
    782     flex_bin_hash_profile_0_entry_t *prof[_BCM_HASH_TD3_NUM_PROF_MEM];
    783     int rv = BCM_E_UNAVAIL;
    784     uint32 data32;
    785     uint32 data1_32;
    786     uint32 flow_id0;
    787     uint32 flow_id1;
    788     uint32 flow_id2;
    789     uint32 flow_id0_mask;
    790     uint32 flow_id1_mask;
    791     uint32 flow_id2_mask;
    792     uint32 *data32_p;
    793     uint32 *data32_mask_p;
    794     _bcm_hash_td3_flex_obj_t flex_obj;
    795     _bcm_hash_td3_flex_obj_t flex_obj_mask;
    796     int fld_size;
    797     _bcm_hash_sfld_info_t *sfld_info;
    798     _bcm_hash_pfld_info_t *pfld_info;
    799     uint8 *cmd_offset;
    800     uint8 *cmd_obj;
    801     uint8 offset_val;
    802     uint8 obj_val;
    803     _bcm_hash_prof_info_t *prof_info;
    804     bcmi_hash_flex_bin_info_t *info;
    805     int tcam_inx;
    806     uint32 tmp_buf[2];
    807     int bin_num;
    808     int mem_cnt;
    809     int bin_inx;
    810 
    811     info = &bcmi_hash_flex_bin_info[unit];
    812     if (info->initialized == FALSE) {
    813          return BCM_E_INIT;
    814     }
    815     pfld_info = _bcm_hash_td3_pfld_info;
    816     sfld_info = _bcm_hash_td3_sfld_info;
    817     cmd_offset = _bcm_hash_td3_cmd_offset;
    818     cmd_obj    = _bcm_hash_td3_cmd_obj;
    819     prof_info  = &_bcm_hash_td3_prof_info;
    820     prof[0] = &prof_entry;
    821     prof[1] = &prof_entry1;
    822     prof[2] = &prof_entry2;
    823     prof[3] = &prof_entry3;
    824 
    825     mem = FLEX_RTAG7_HASH_TCAMm;
    826     tcam_size = soc_mem_index_count(unit, mem);
    827     sal_memset(&flex_obj, 0, sizeof(flex_obj));
    828     sal_memset(&flex_obj_mask, 0, sizeof(flex_obj_mask));
    829     sal_memset(&rule_entry, 0, sizeof(rule_entry));
    830     flow_id0 = 0;
    831     flow_id1 = 0;
    832     flow_id2 = 0;
    833     flow_id0_mask = 0;
    834     flow_id1_mask = 0;
    835     flow_id2_mask = 0;
    836 
    837     /* error check */
    838     if (cfg->option & BCM_HASH_FLEX_BIN_OPTION_REPLACE) {
    839         if (!(cfg->option & BCM_HASH_FLEX_BIN_OPTION_WITH_ID)) {
    840             return BCM_E_PARAM;
    841         }
    842     }
    843 
    844     /* validate bin_id */
    845     for (ix = 0; ix < num_bins; ix++) {
    846         if (!BIN_ID_VALID(cfg, bin_cmd[ix].bin_id)) {
    847             return BCM_E_PARAM;
    848         }
    849     }
    850 
    851     /* find an empty entry */
    852     if (!(cfg->option & BCM_HASH_FLEX_BIN_OPTION_WITH_ID)) {
    853         for (tcam_inx = tcam_size - 1; tcam_inx >= 0; tcam_inx--) {
    854             if (!SHR_BITGET(info->entry_bmp, tcam_inx)) {
    855                 break;
    856             }
    857         }
    858         if (tcam_inx < 0) {   /* TCAM Full */
    859             return BCM_E_FULL;
    860         }
    861         cfg->entry_id = tcam_size - 1 - tcam_inx;
    862     } else {
    863         tcam_inx = tcam_size - 1 - cfg->entry_id;
    864         if (tcam_inx < 0) {
    865             LOG_ERROR(BSL_LS_BCM_HASH, (BSL_META_U(unit,
    866                 "Entry ID %d must be less than the hardware table size: %d\n"),
    867                         cfg->entry_id, tcam_size));
    868             return BCM_E_PARAM;
    869         }
    870         if (cfg->option & BCM_HASH_FLEX_BIN_OPTION_REPLACE) {
    871             if (!SHR_BITGET(info->entry_bmp, tcam_inx)) {
    872                 return BCM_E_NOT_FOUND;
    873             }
    874         } else {
    875             if (SHR_BITGET(info->entry_bmp, tcam_inx)) {
    876                 return BCM_E_EXISTS;
    877             }
    878         }
    879     }
    880 
    881     /* handle the pkt_type */
    882     iy = 0;
    883     while (pfld_info[iy].pkt_type != BCM_HASH_PKT_TYPE_MAX) {
    884         if (BCM_HASH_PKT_TYPE_SET_TEST(cfg->tset, pfld_info[iy].pkt_type)) {
    885             if (pfld_info[iy].fmt == PKT_FLOW_ID_2_FORMATfmt) {
    886                 data32_p = &flow_id2;
    887                 data32_mask_p = &flow_id2_mask;
    888             } else if (pfld_info[iy].fmt == PKT_FLOW_ID_1_FORMATfmt) {
    889                 data32_p = &flow_id1;
    890                 data32_mask_p = &flow_id1_mask;
    891             } else if (pfld_info[iy].fmt == PKT_FLOW_ID_0_FORMATfmt) {
    892                 data32_p = &flow_id0;
    893                 data32_mask_p = &flow_id0_mask;
    894             } else {
    895                 return BCM_E_INTERNAL;
    896             } 
    897             fld_size = soc_format_field_length(unit,
    898                             pfld_info[iy].fmt, pfld_info[iy].fld1);
    899             data32 = 0;
    900             soc_format_field32_set(unit, pfld_info[iy].fmt,
    901                 &data32, pfld_info[iy].fld1, (1 << fld_size) - 1);
    902            
    903             /* indicate error if field is overlapped */
    904             if ((*data32_mask_p) & data32) { 
    905                 LOG_ERROR(BSL_LS_BCM_HASH, (BSL_META_U(unit,
    906                     "Packet flow type conflict: %d\n"),
    907                     pfld_info[iy].pkt_type));
    908                 return BCM_E_PARAM;
    909             }
    910             soc_format_field32_set(unit, pfld_info[iy].fmt,
    911                 data32_mask_p, pfld_info[iy].fld1, (1 << fld_size) - 1);
    912 
    913             soc_format_field32_set(unit, pfld_info[iy].fmt,
    914                 data32_p, pfld_info[iy].fld1, pfld_info[iy].val1);
    915 
    916             if (pfld_info[iy].fld2 != INVALIDf) {
    917                 soc_format_field32_set(unit, pfld_info[iy].fmt,
    918                      data32_p, pfld_info[iy].fld2, pfld_info[iy].val2);
    919                 fld_size = soc_format_field_length(unit,
    920                             pfld_info[iy].fmt, pfld_info[iy].fld2);
    921                 soc_format_field32_set(unit, pfld_info[iy].fmt,
    922                              data32_mask_p, pfld_info[iy].fld2, 
    923                              (1 << fld_size) - 1);
    924             }
    925         }
    926         iy++;
    927     }
    928 
    929     /* handle the pkt status */   
    930     iy = 0;
    931     while (sfld_info[iy].pkt_status != BCM_HASH_PKT_STATUS_MAX) {
    932         ix = sfld_info[iy].pkt_status;
    933         if (BCM_HASH_PKT_STATUS_SET_TEST(cfg->sset_mask, ix)) {
    934             if (sfld_info[iy].fld_size == 1) {
    935                 soc_mem_field32_set(unit, mem, &rule_entry, 
    936                     sfld_info[iy].fld_mask, 1);
    937                 soc_mem_field32_set(unit, mem, &rule_entry, 
    938                     sfld_info[iy].fld, 
    939                     BCM_HASH_PKT_STATUS_SET_TEST(cfg->sset, ix)? 1 :0);
    940             } else {
    941                 return BCM_E_INTERNAL;
    942             }
    943         }
    944         iy++;
    945     }
    946 
    947     /* handle flex objects */
    948     rv = _bcm_hash_td3_flex_field_add(unit, num_fields, flex_field, &flex_obj, 
    949         &flex_obj_mask);
    950     BCM_IF_ERROR_RETURN(rv);
    951 
    952     /* check if flex object conflicts with the fixed assignment */
    953     if (flex_obj_mask.flow_id0 & flow_id0_mask) {
    954         LOG_ERROR(BSL_LS_BCM_HASH, (BSL_META_U(unit,
    955             "Flex object flow_id_0 conflicts with packet flow type\n")));
    956         return BCM_E_PARAM;
    957     } else {
    958         flow_id0_mask |= flex_obj_mask.flow_id0;
    959         flow_id0      |= flex_obj.flow_id0;
    960     }
    961 
    962     if (flex_obj_mask.flow_id1 & flow_id1_mask) {
    963         LOG_ERROR(BSL_LS_BCM_HASH, (BSL_META_U(unit,
    964             "Flex object flow_id_1 conflicts with packet flow type\n")));
    965         return BCM_E_PARAM;
    966     } else {
    967         flow_id1_mask |= flex_obj_mask.flow_id1;
    968         flow_id1      |= flex_obj.flow_id1;
    969     }
    970 
    971     if (flex_obj_mask.flow_id2 & flow_id2_mask) {
    972         LOG_ERROR(BSL_LS_BCM_HASH, (BSL_META_U(unit,
    973             "Flex object flow_id_2 conflicts with packet flow type\n")));
    974         return BCM_E_PARAM;
    975     } else {
    976         flow_id2_mask |= flex_obj_mask.flow_id2;
    977         flow_id2      |= flex_obj.flow_id2;
    978     }
    979 
    980     /* set flow ids */
    981     if (flow_id2_mask) {
    982         soc_mem_field32_set(unit, mem, &rule_entry, PKT_FLOW_ID_2_MASKf, 
    983                         flow_id2_mask);
    984         soc_mem_field32_set(unit, mem, &rule_entry, PKT_FLOW_ID_2f, flow_id2);
    985     }
    986     if (flow_id1_mask) {
    987         soc_mem_field32_set(unit, mem, &rule_entry, PKT_FLOW_ID_1_MASKf, 
    988                         flow_id1_mask);
    989         soc_mem_field32_set(unit, mem, &rule_entry, PKT_FLOW_ID_1f, flow_id1);
    990     }
    991     if (flow_id0_mask) {
    992         soc_mem_field32_set(unit, mem, &rule_entry, PKT_FLOW_ID_0_MASKf, 
    993                         flow_id0_mask);
    994         soc_mem_field32_set(unit, mem, &rule_entry, PKT_FLOW_ID_0f, flow_id0);
    995     }
    996 
    997     /* match_id */
    998     if (!COMPILER_64_IS_ZERO(flex_obj_mask.match_id)) {
    999         sal_memcpy(tmp_buf, &flex_obj_mask.match_id, 8);
   1000         soc_mem_field_set(unit, mem, (uint32 *)&rule_entry, MATCH_ID_MASKf, 
   1001                       tmp_buf);
   1002         sal_memcpy(tmp_buf, &flex_obj.match_id, 8);
   1003         soc_mem_field_set(unit, mem, (uint32 *)&rule_entry, MATCH_IDf,
   1004                       tmp_buf);
   1005     }
   1006 
   1007     /* hve control */
   1008     if (flex_obj_mask.hve_ctrl2) {
   1009         soc_mem_field32_set(unit, mem, &rule_entry, HVE_CONTROL_2_MASKf, 
   1010                         flex_obj_mask.hve_ctrl2);
   1011         soc_mem_field32_set(unit, mem, &rule_entry, HVE_CONTROL_2f, 
   1012                         flex_obj.hve_ctrl2);
   1013     }
   1014     if (flex_obj_mask.hve_ctrl1) {
   1015         soc_mem_field32_set(unit, mem, &rule_entry, HVE_CONTROL_1_MASKf, 
   1016                         flex_obj_mask.hve_ctrl1);
   1017         soc_mem_field32_set(unit, mem, &rule_entry, HVE_CONTROL_1f, 
   1018                         flex_obj.hve_ctrl1);
   1019     }
   1020 
   1021     /* handle the control fields */
   1022     soc_mem_field32_set(unit, mem, &rule_entry, VALIDf, 3);
   1023 
   1024     soc_mem_field32_set(unit, mem, &rule_entry, VFI_HASH_CTRL_ID_MASKf, 
   1025                         cfg->vfi_ctrl_id_mask);
   1026     soc_mem_field32_set(unit, mem, &rule_entry, VFI_HASH_CTRL_IDf, 
   1027                         cfg->vfi_ctrl_id);
   1028     
   1029     soc_mem_field32_set(unit, mem, &rule_entry, VLAN_HASH_CTRL_ID_MASKf, 
   1030                             cfg->vlan_ctrl_id_mask);
   1031     soc_mem_field32_set(unit, mem, &rule_entry, VLAN_HASH_CTRL_IDf, 
   1032                             cfg->vlan_ctrl_id);
   1033     
   1034     soc_mem_field32_set(unit, mem, &rule_entry, L3_IIF_HASH_CTRL_ID_MASKf, 
   1035                             cfg->l3iif_ctrl_id_mask);
   1036     soc_mem_field32_set(unit, mem, &rule_entry, L3_IIF_HASH_CTRL_IDf, 
   1037                             cfg->l3iif_ctrl_id);
   1038     
   1039     soc_mem_field32_set(unit, mem, &rule_entry, SVP_HASH_CTRL_ID_MASKf, 
   1040                             cfg->svp_ctrl_id_mask);
   1041     soc_mem_field32_set(unit, mem, &rule_entry, SVP_HASH_CTRL_IDf, 
   1042                             cfg->svp_ctrl_id);
   1043     
   1044     soc_mem_field32_set(unit, mem, &rule_entry, SGPP_HASH_CTRL_ID_MASKf, 
   1045                             cfg->sgpp_ctrl_id_mask);
   1046     soc_mem_field32_set(unit, mem, &rule_entry, SGPP_HASH_CTRL_IDf, 
   1047                             cfg->sgpp_ctrl_id);
   1048     
   1049     soc_mem_field32_set(unit, mem, &rule_entry, 
   1050                         BIN_CONTROL_PROFILEf, tcam_inx);
   1051 
   1052     /* handle policy data command */
   1053     /* In TD3, the bin_cmd profile is 128 deep same as the TCAM. Use 
   1054      * one-to-one mapping. No need to employ profile mechanism
   1055      */
   1056 
   1057     /* TD3
   1058      * FLEX_BIN_HASH_PROFILE_0: LSB 8-bit, A-bin 0-12
   1059      * FLEX_BIN_HASH_PROFILE_1: MSB 8-bit, A-bin 0-12
   1060      * FLEX_BIN_HASH_PROFILE_2: LSB 8-bit, B-bin 0-12
   1061      * FLEX_BIN_HASH_PROFILE_3: MSB 8-bit, B-bin 0-12
   1062      */
   1063     for (ix = 0; ix < _BCM_HASH_TD3_NUM_PROF_MEM; ix++) {
   1064         sal_memset(prof[ix], 0, sizeof(prof_entry));
   1065     }
   1066     for (ix = 0; ix < num_bins; ix++) {
   1067         if (cfg->option & BCM_HASH_FLEX_BIN_OPTION_SIZE_8BIT) {
   1068             if (bin_cmd[ix].bin_id <= BCM_HASH_BIN_A_MAX) {
   1069                 bin_num = bin_cmd[ix].bin_id - BCM_HASH_BIN_A_0;
   1070             } else if (bin_cmd[ix].bin_id <= BCM_HASH_BIN_A_UPPER_HALF_MAX) {
   1071                 bin_num = bin_cmd[ix].bin_id - BCM_HASH_BIN_A_0_UPPER_HALF;
   1072                 bin_num += _BCM_HASH_TD3_NUM_BINS_PER_SET;
   1073             } else if (bin_cmd[ix].bin_id <= BCM_HASH_BIN_B_MAX) {
   1074                 bin_num = bin_cmd[ix].bin_id - BCM_HASH_BIN_B_0;
   1075                 bin_num += 2 * _BCM_HASH_TD3_NUM_BINS_PER_SET;
   1076             } else { /* bin_cmd[ix].bin_id <= BCM_HASH_BIN_B_UPPER_HALF_MAX */
   1077                 bin_num = bin_cmd[ix].bin_id - BCM_HASH_BIN_B_0_UPPER_HALF;
   1078                 bin_num += 3 * _BCM_HASH_TD3_NUM_BINS_PER_SET;
   1079             }
   1080         } else {
   1081             if (bin_cmd[ix].bin_id <= BCM_HASH_BIN_A_MAX) {
   1082                 bin_num = bin_cmd[ix].bin_id - BCM_HASH_BIN_A_0;
   1083             } else {
   1084                 bin_num = (bin_cmd[ix].bin_id - BCM_HASH_BIN_B_0);
   1085                 bin_num += _BCM_HASH_TD3_NUM_BINS_PER_SET;
   1086             }
   1087         }              
   1088        
   1089         /* save the object_id for the given bin */
   1090         if (cfg->option & BCM_HASH_FLEX_BIN_OPTION_SIZE_8BIT) {
   1091             mem_cnt = bin_num / _BCM_HASH_TD3_NUM_BINS_PER_SET;
   1092             bin_inx = BIN_INX(unit, mem_cnt, tcam_inx, bin_num);
   1093             info->bin_obj_arr[bin_inx] = bin_cmd[ix].obj_id;
   1094         } else {
   1095             mem_cnt = 2 * (bin_num / _BCM_HASH_TD3_NUM_BINS_PER_SET);
   1096             bin_inx = BIN_INX(unit, mem_cnt, tcam_inx, bin_num);
   1097             info->bin_obj_arr[bin_inx] = bin_cmd[ix].obj_id;
   1098             bin_inx = BIN_INX(unit, mem_cnt + 1, tcam_inx, bin_num);
   1099             info->bin_obj_arr[bin_inx] = bin_cmd[ix].obj_id;
   1100         }
   1101   
   1102         /* convert to TD3 specific hardware offset and object value */
   1103         offset_val = cmd_offset[bin_cmd[ix].obj_offset];
   1104         obj_val    = cmd_obj[bin_cmd[ix].obj_id];
   1105   
   1106         switch (bin_cmd[ix].obj_id) {
   1107             case BCM_HASH_OBJ_OUTER_MAC_DA:
   1108             case BCM_HASH_OBJ_INNER_MAC_DA:
   1109                 offset_val += cmd_offset[BCM_HASH_OBJ_OFFSET_BIT48];
   1110                 break;
   1111             case BCM_HASH_OBJ_OUTER_IPV4_SIP:
   1112             case BCM_HASH_OBJ_INNER_IPV4_SIP:
   1113                 offset_val += cmd_offset[BCM_HASH_OBJ_OFFSET_BIT96];
   1114                 break;
   1115             default:
   1116                 break;
   1117         }
   1118  
   1119         /* LSB 8-bit */ 
   1120         data32 = 0;
   1121         if (bin_cmd[ix].obj_id == BCM_HASH_OBJ_ID_INVALID) {
   1122             soc_format_field32_set(unit, FLEX_BIN_HASH_PROFILE_FORMATfmt,
   1123                     &data32, CMD_VALIDf, 0);
   1124         } else {
   1125             soc_format_field32_set(unit, FLEX_BIN_HASH_PROFILE_FORMATfmt,
   1126                     &data32, CMD_VALIDf, 1);
   1127             soc_format_field32_set(unit, FLEX_BIN_HASH_PROFILE_FORMATfmt,
   1128                     &data32, CMD_SRC_CONTAINER_IDf, obj_val);
   1129             soc_format_field32_set(unit, FLEX_BIN_HASH_PROFILE_FORMATfmt,
   1130                     &data32, CMD_SRC_CONTAINER_OFFSETf, offset_val);
   1131             soc_format_field32_set(unit, FLEX_BIN_HASH_PROFILE_FORMATfmt,
   1132                     &data32, CMD_MASKf, (uint8)bin_cmd[ix].bin_mask);
   1133         }
   1134 
   1135         if (!(cfg->option & BCM_HASH_FLEX_BIN_OPTION_SIZE_8BIT)) {
   1136             /* MSB 8-bit */
   1137             data1_32 = data32;
   1138             soc_format_field32_set(unit, FLEX_BIN_HASH_PROFILE_FORMATfmt,
   1139                     &data1_32, CMD_SRC_CONTAINER_OFFSETf, 
   1140                     offset_val + 2); /* TD3 4-bit gradularity */
   1141             soc_format_field32_set(unit, FLEX_BIN_HASH_PROFILE_FORMATfmt,
   1142                     &data1_32, CMD_MASKf, (uint8)(bin_cmd[ix].bin_mask >> 8));
   1143 
   1144             soc_mem_field32_set(unit, 
   1145                 prof_info->mem[2*(bin_num/_BCM_HASH_TD3_NUM_BINS_PER_SET)], 
   1146                 prof[2*(bin_num/_BCM_HASH_TD3_NUM_BINS_PER_SET)], 
   1147                 prof_info->fld[bin_num%_BCM_HASH_TD3_NUM_BINS_PER_SET], 
   1148                 data32);
   1149 
   1150             soc_mem_field32_set(unit, 
   1151                 prof_info->mem[2*(bin_num/_BCM_HASH_TD3_NUM_BINS_PER_SET) + 1], 
   1152                 prof[2*(bin_num/_BCM_HASH_TD3_NUM_BINS_PER_SET) + 1], 
   1153                 prof_info->fld[bin_num%_BCM_HASH_TD3_NUM_BINS_PER_SET], 
   1154                 data1_32);
   1155         } else {
   1156             soc_mem_field32_set(unit, 
   1157                  prof_info->mem[(bin_num/_BCM_HASH_TD3_NUM_BINS_PER_SET)], 
   1158                  prof[(bin_num/_BCM_HASH_TD3_NUM_BINS_PER_SET)], 
   1159                  prof_info->fld[bin_num%_BCM_HASH_TD3_NUM_BINS_PER_SET], 
   1160                  data32);
   1161         }
   1162     }
   1163     for (ix = 0; ix < _BCM_HASH_TD3_NUM_PROF_MEM; ix++) {
   1164         rv = soc_mem_write(unit, prof_info->mem[ix], MEM_BLOCK_ALL, 
   1165                            tcam_inx, prof[ix]);
   1166         SOC_IF_ERROR_RETURN(rv);
   1167     }
   1168 
   1169     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, tcam_inx, &rule_entry);
   1170     SHR_BITSET(info->entry_bmp, tcam_inx);
   1171     return rv;
   1172 }
   1173 
   1174 /*
   1175  * Function:
   1176  *   bcmi_td3_hash_flex_bin_delete
   1177  * Purpose:
   1178  *   Delete the given entry
   1179  * Parameters:
   1180  *   unit        - (IN)  Unit ID.
   1181  *   entry_id    - (IN)  The entry ID
   1182  */
   1183 
   1184 int bcmi_td3_hash_flex_bin_delete( int unit, int entry_id)
   1185 {
   1186     soc_mem_t mem;
   1187     flex_rtag7_hash_tcam_entry_t rule_entry;
   1188     flex_bin_hash_profile_0_entry_t prof_entry;
   1189     int rv;
   1190     int ix,iy;
   1191     _bcm_hash_prof_info_t *prof_info;
   1192     int tcam_size;
   1193     int tcam_inx;
   1194     bcmi_hash_flex_bin_info_t *info;
   1195     int bin_inx;
   1196 
   1197     info = &bcmi_hash_flex_bin_info[unit];
   1198     if (info->initialized == FALSE) {
   1199          return BCM_E_INIT;
   1200     }
   1201     mem = FLEX_RTAG7_HASH_TCAMm;
   1202     tcam_size = soc_mem_index_count(unit, mem);
   1203     tcam_inx  = tcam_size - 1 - entry_id;
   1204 
   1205     if (tcam_inx < 0) {
   1206         LOG_ERROR(BSL_LS_BCM_HASH, (BSL_META_U(unit,
   1207             "Entry ID %d must be less than the hardware table size: %d\n"),
   1208                     entry_id, tcam_size));
   1209         return BCM_E_PARAM;
   1210     }
   1211     SHR_BITCLR(info->entry_bmp, tcam_inx);
   1212     
   1213     prof_info = &_bcm_hash_td3_prof_info;
   1214     sal_memset(&rule_entry, 0, sizeof(rule_entry));
   1215     sal_memset(&prof_entry, 0, sizeof(prof_entry));
   1216 
   1217     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, tcam_inx, &rule_entry);
   1218     SOC_IF_ERROR_RETURN(rv);
   1219 
   1220     for (ix = 0; ix < _BCM_HASH_TD3_NUM_PROF_MEM; ix++) {
   1221         rv = soc_mem_write(unit, prof_info->mem[ix], MEM_BLOCK_ALL,
   1222                            tcam_inx, &prof_entry);
   1223         SOC_IF_ERROR_RETURN(rv);
   1224     }
   1225 
   1226     for (iy = 0; iy < _BCM_HASH_TD3_NUM_PROF_MEM; iy++) {
   1227         for (ix = 0; ix < _BCM_HASH_TD3_NUM_BINS_PER_SET; ix++) {
   1228             bin_inx = BIN_INX(unit, iy, tcam_inx, ix);
   1229             info->bin_obj_arr[bin_inx] = 0;
   1230         }
   1231     }
   1232 
   1233     return rv;
   1234 }
   1235 
   1236 /*
   1237  * Function:
   1238  *   bcmi_td3_hash_flex_bin_delete_all
   1239  * Purpose:
   1240  *   Delete all entries
   1241  * Parameters:
   1242  *   unit - (IN)  Unit ID.
   1243  */
   1244 
   1245 STATIC int _bcm_td3_hash_flex_bin_delete_all(int unit)
   1246 {
   1247     soc_mem_t mem;
   1248     flex_rtag7_hash_tcam_entry_t rule_entry;
   1249     flex_bin_hash_profile_0_entry_t prof_entry;
   1250     int rv;
   1251     int size;
   1252     int ix;
   1253     int iy;
   1254     _bcm_hash_prof_info_t *prof_info;
   1255     bcmi_hash_flex_bin_info_t *info;
   1256 
   1257     info = &bcmi_hash_flex_bin_info[unit];
   1258     mem = FLEX_RTAG7_HASH_TCAMm;
   1259     size = soc_mem_index_count(unit, mem);
   1260     prof_info = &_bcm_hash_td3_prof_info;
   1261     sal_memset(&rule_entry, 0, sizeof(rule_entry));
   1262     sal_memset(&prof_entry, 0, sizeof(prof_entry));
   1263 
   1264     for (ix = size - 1; ix >= 0; ix--) {
   1265         SHR_BITCLR(info->entry_bmp, ix);
   1266         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, ix, &rule_entry);
   1267         SOC_IF_ERROR_RETURN(rv);
   1268         for (iy = 0; iy < _BCM_HASH_TD3_NUM_PROF_MEM; iy++) {
   1269             rv = soc_mem_write(unit, prof_info->mem[iy], MEM_BLOCK_ALL,
   1270                            ix, &prof_entry);
   1271             SOC_IF_ERROR_RETURN(rv);
   1272         }
   1273     }
   1274 
   1275     size = soc_mem_index_count(unit, FLEX_BIN_HASH_PROFILE_0m);
   1276     size *= _BCM_HASH_TD3_NUM_PROF_MEM;
   1277     size *= _BCM_HASH_TD3_NUM_BINS_PER_SET;
   1278     size *= sizeof(uint16);
   1279     sal_memset(info->bin_obj_arr, 0, size);
   1280 
   1281     return BCM_E_NONE;
   1282 }
   1283 
   1284 int bcmi_td3_hash_flex_bin_delete_all(int unit)
   1285 {
   1286     bcmi_hash_flex_bin_info_t *info;
   1287 
   1288     info = &bcmi_hash_flex_bin_info[unit];
   1289     if (info->initialized == FALSE) {
   1290          return BCM_E_INIT;
   1291     }
   1292     return _bcm_td3_hash_flex_bin_delete_all(unit);
   1293 }
   1294 
   1295 /*
   1296  * Function:
   1297  *   bcmi_td3_hash_flex_bin_get
   1298  * Purpose:
   1299  *   Get the entry configuration parameters for the given entry_id.
   1300  * Parameters:
   1301  *   unit     - (IN)    Unit ID.
   1302  *   cfg      - (INOUT) Key part of selection rule and other parameters
   1303  *   num_bins - (IN)   Number of bin cmds.
   1304  *   bin_cmd  - (IN) Array of bin commands. Policy part of selection rule.
   1305  *   num_fields - (IN) Number of flex fields.
   1306  *   flex_field - (IN) Array of flex fields.
   1307  */
   1308 
   1309 int bcmi_td3_hash_flex_bin_get (int unit,
   1310               bcm_hash_flex_bin_config_t *cfg,
   1311               int num_bins,
   1312               bcm_hash_flex_bin_cmd_t *bin_cmd,
   1313               int num_fields,
   1314               bcm_hash_flex_field_t *flex_field)
   1315 {
   1316     soc_mem_t mem;
   1317     int ix,iy,inx;
   1318     flex_rtag7_hash_tcam_entry_t rule_entry;
   1319     flex_bin_hash_profile_0_entry_t prof_entry;
   1320     flex_bin_hash_profile_0_entry_t prof_entry1;
   1321     flex_bin_hash_profile_0_entry_t prof_entry2;
   1322     flex_bin_hash_profile_0_entry_t prof_entry3;
   1323     flex_bin_hash_profile_0_entry_t *prof[_BCM_HASH_TD3_NUM_PROF_MEM];
   1324     int rv = BCM_E_UNAVAIL;
   1325     uint32 data32;
   1326     uint32 *data32_p;
   1327     uint32 flow_id0;
   1328     uint32 flow_id1;
   1329     uint32 flow_id2;
   1330     _bcm_hash_td3_flex_obj_t flex_obj;
   1331     _bcm_hash_td3_flex_obj_t flex_obj_mask;
   1332     _bcm_hash_sfld_info_t *sfld_info;
   1333     _bcm_hash_pfld_info_t *pfld_info;
   1334     uint8 *cmd_offset;
   1335     uint8 offset_val;
   1336     _bcm_hash_prof_info_t *prof_info;
   1337     int val1;
   1338     int val2;
   1339     int val1_mask;
   1340     uint32 tmp_buf[2];
   1341     int tcam_inx;
   1342     int tcam_size;
   1343     bcmi_hash_flex_bin_info_t *info;
   1344     int num_bin_max;
   1345     int bin_inx;
   1346     int cmd_inx;
   1347 
   1348     pfld_info = _bcm_hash_td3_pfld_info;
   1349     sfld_info = _bcm_hash_td3_sfld_info;
   1350     cmd_offset = _bcm_hash_td3_cmd_offset;
   1351     prof_info  = &_bcm_hash_td3_prof_info;
   1352     prof[0] = &prof_entry;
   1353     prof[1] = &prof_entry1;
   1354     prof[2] = &prof_entry2;
   1355     prof[3] = &prof_entry3;
   1356     info = &bcmi_hash_flex_bin_info[unit];
   1357 
   1358     if (info->initialized == FALSE) {
   1359          return BCM_E_INIT;
   1360     }
   1361 
   1362     mem = FLEX_RTAG7_HASH_TCAMm;
   1363     tcam_size = soc_mem_index_count(unit, mem);
   1364     sal_memset(&flex_obj, 0, sizeof(flex_obj));
   1365     sal_memset(&flex_obj_mask, 0, sizeof(flex_obj_mask));
   1366     sal_memset(&rule_entry, 0, sizeof(rule_entry));
   1367     flow_id0 = 0;
   1368     flow_id1 = 0;
   1369     flow_id2 = 0;
   1370 
   1371     if (cfg->entry_id >= tcam_size) {
   1372         return BCM_E_PARAM;
   1373     }
   1374     tcam_inx = tcam_size - cfg->entry_id - 1;
   1375     if (tcam_inx < 0) {
   1376         LOG_ERROR(BSL_LS_BCM_HASH, (BSL_META_U(unit,
   1377             "Entry ID %d must be less than the hardware table size: %d\n"),
   1378                     cfg->entry_id, tcam_size));
   1379         return BCM_E_PARAM;
   1380     }
   1381     if (!SHR_BITGET(info->entry_bmp, tcam_inx)) {
   1382         return BCM_E_NOT_FOUND;
   1383     }
   1384 
   1385     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, tcam_inx, &rule_entry);
   1386     SOC_IF_ERROR_RETURN(rv);
   1387 
   1388     if (!soc_mem_field32_get(unit, mem, &rule_entry, VALIDf)) {
   1389         return SOC_E_NOT_FOUND;
   1390     }
   1391 
   1392     /* get flow ids */
   1393     flow_id2 = soc_mem_field32_get(unit, mem, &rule_entry, PKT_FLOW_ID_2f);
   1394     flow_id1 = soc_mem_field32_get(unit, mem, &rule_entry, PKT_FLOW_ID_1f);
   1395     flow_id0 = soc_mem_field32_get(unit, mem, &rule_entry, PKT_FLOW_ID_0f);
   1396 
   1397     /* handle the pkt_type */
   1398     for (ix = 0; ix < BCM_HASH_PKT_TYPE_MAX; ix++) {
   1399         if (pfld_info[ix].fmt == PKT_FLOW_ID_2_FORMATfmt) {
   1400             data32_p = &flow_id2;
   1401         } else if (pfld_info[ix].fmt == PKT_FLOW_ID_1_FORMATfmt) {
   1402             data32_p = &flow_id1;
   1403         } else if (pfld_info[ix].fmt == PKT_FLOW_ID_0_FORMATfmt) {
   1404             data32_p = &flow_id0;
   1405         } else {
   1406             return BCM_E_INTERNAL;
   1407         }
   1408         val2 = 0; 
   1409         val1 = soc_format_field32_get(unit, pfld_info[ix].fmt,
   1410                         data32_p, pfld_info[ix].fld1);
   1411         if (pfld_info[ix].fld2 != INVALIDf) {
   1412             val2 = soc_format_field32_get(unit, pfld_info[ix].fmt,
   1413                  data32_p, pfld_info[ix].fld2);
   1414         }
   1415         if ((val1 == pfld_info[ix].val1) && (val2 == pfld_info[ix].val2)) {
   1416             BCM_HASH_PKT_TYPE_SET_ADD(cfg->tset, pfld_info[ix].pkt_type); 
   1417         }
   1418     }
   1419 
   1420     /* handle the pkt status */   
   1421     for (iy = 0; iy < BCM_HASH_PKT_STATUS_MAX; iy++) {
   1422         if (sfld_info[iy].fld_size == 1) {
   1423             val1_mask = soc_mem_field32_get(unit, mem, &rule_entry, 
   1424                 sfld_info[iy].fld_mask);
   1425             if (val1_mask) {
   1426                 BCM_HASH_PKT_STATUS_SET_ADD(cfg->sset_mask, 
   1427                        sfld_info[iy].pkt_status);
   1428             }
   1429             val1 = soc_mem_field32_get(unit, mem, &rule_entry, 
   1430                 sfld_info[iy].fld); 
   1431             if (val1) {
   1432                 BCM_HASH_PKT_STATUS_SET_ADD(cfg->sset,sfld_info[iy].pkt_status);
   1433             }
   1434         } else {
   1435             return BCM_E_INTERNAL;
   1436         }
   1437     }
   1438 
   1439     soc_mem_field_get(unit, mem, (uint32 *)&rule_entry, MATCH_IDf, tmp_buf);
   1440     sal_memcpy(&flex_obj.match_id, tmp_buf, 8);
   1441 
   1442     soc_mem_field_get(unit, mem, (uint32 *)&rule_entry, MATCH_ID_MASKf,
   1443                       tmp_buf);
   1444     sal_memcpy(&flex_obj_mask.match_id, tmp_buf, 8);
   1445 
   1446     flex_obj_mask.flow_id0 = (uint16)soc_mem_field32_get(unit, mem,
   1447                              &rule_entry, PKT_FLOW_ID_0_MASKf);
   1448     flex_obj.flow_id0 = (uint16)soc_mem_field32_get(unit, mem,
   1449                              &rule_entry, PKT_FLOW_ID_0f);
   1450     flex_obj_mask.flow_id0 = (uint16)soc_mem_field32_get(unit, mem,
   1451                              &rule_entry, PKT_FLOW_ID_0_MASKf);
   1452     flex_obj.flow_id1 = (uint16)soc_mem_field32_get(unit, mem,
   1453                              &rule_entry, PKT_FLOW_ID_1f);
   1454     flex_obj_mask.flow_id1 = (uint16)soc_mem_field32_get(unit, mem,
   1455                              &rule_entry, PKT_FLOW_ID_1_MASKf);
   1456     flex_obj.flow_id2 = (uint16)soc_mem_field32_get(unit, mem,
   1457                              &rule_entry, PKT_FLOW_ID_2f);
   1458     flex_obj_mask.flow_id2 = (uint16)soc_mem_field32_get(unit, mem,
   1459                              &rule_entry, PKT_FLOW_ID_2_MASKf);
   1460     flex_obj.hve_ctrl1 = (uint8)soc_mem_field32_get(unit, mem,
   1461                              &rule_entry, HVE_CONTROL_1f);
   1462     flex_obj_mask.hve_ctrl1 = (uint8)soc_mem_field32_get(unit, mem,
   1463                              &rule_entry, HVE_CONTROL_1_MASKf);
   1464     flex_obj.hve_ctrl2 = (uint8)soc_mem_field32_get(unit, mem,
   1465                              &rule_entry, HVE_CONTROL_2f);
   1466     flex_obj_mask.hve_ctrl2 = (uint8)soc_mem_field32_get(unit, mem,
   1467                              &rule_entry, HVE_CONTROL_2_MASKf);
   1468 
   1469     rv = _bcm_hash_td3_flex_field_get(unit, num_fields, flex_field,
   1470              &flex_obj, &flex_obj_mask);
   1471     BCM_IF_ERROR_RETURN(rv);
   1472     
   1473     cfg->vfi_ctrl_id_mask = soc_mem_field32_get(unit, mem, &rule_entry,
   1474                                    VFI_HASH_CTRL_ID_MASKf);
   1475     cfg->vfi_ctrl_id = soc_mem_field32_get(unit, mem, &rule_entry,
   1476                                    VFI_HASH_CTRL_IDf);
   1477     cfg->vlan_ctrl_id_mask = soc_mem_field32_get(unit, mem, &rule_entry, 
   1478                                    VLAN_HASH_CTRL_ID_MASKf);
   1479     cfg->vlan_ctrl_id = soc_mem_field32_get(unit, mem, &rule_entry, 
   1480                                    VLAN_HASH_CTRL_IDf);
   1481     cfg->l3iif_ctrl_id_mask = soc_mem_field32_get(unit, mem, &rule_entry, 
   1482                                    L3_IIF_HASH_CTRL_ID_MASKf);
   1483     cfg->l3iif_ctrl_id = soc_mem_field32_get(unit, mem, &rule_entry, 
   1484                                    L3_IIF_HASH_CTRL_IDf);
   1485     cfg->svp_ctrl_id_mask = soc_mem_field32_get(unit, mem, &rule_entry, 
   1486                                    SVP_HASH_CTRL_ID_MASKf);
   1487     cfg->svp_ctrl_id = soc_mem_field32_get(unit, mem, &rule_entry, 
   1488                                    SVP_HASH_CTRL_IDf);
   1489     cfg->sgpp_ctrl_id_mask = soc_mem_field32_get(unit, mem, &rule_entry, 
   1490                                    SGPP_HASH_CTRL_ID_MASKf);
   1491     cfg->sgpp_ctrl_id = soc_mem_field32_get(unit, mem, &rule_entry, 
   1492                                    SGPP_HASH_CTRL_IDf);
   1493  
   1494     /* handle policy data command */
   1495     /* In TD3, the bin_cmd profile is 128 deep same as the TCAM. Use 
   1496      * one-to-one mapping. No need to employ profile mechanism
   1497      */
   1498     /* TD3
   1499      * FLEX_BIN_HASH_PROFILE_0: LSB 8-bit, A-bin 0-12
   1500      * FLEX_BIN_HASH_PROFILE_1: MSB 8-bit, A-bin 0-12
   1501      * FLEX_BIN_HASH_PROFILE_2: LSB 8-bit, B-bin 0-12
   1502      * FLEX_BIN_HASH_PROFILE_3: MSB 8-bit, B-bin 0-12
   1503      */
   1504     for (ix = 0; ix < _BCM_HASH_TD3_NUM_PROF_MEM; ix++) {
   1505         rv = soc_mem_read(unit, prof_info->mem[ix], MEM_BLOCK_ALL, 
   1506                            tcam_inx, prof[ix]);
   1507         SOC_IF_ERROR_RETURN(rv);
   1508     }
   1509     num_bin_max = cfg->option & BCM_HASH_FLEX_BIN_OPTION_SIZE_8BIT ?
   1510                   4 * _BCM_HASH_TD3_NUM_BINS_PER_SET:
   1511                   2 * _BCM_HASH_TD3_NUM_BINS_PER_SET;
   1512 
   1513     for (cmd_inx = 0, ix = 0; ix < num_bin_max; ix++) {
   1514 
   1515         if (cfg->option & BCM_HASH_FLEX_BIN_OPTION_SIZE_8BIT) {
   1516             inx = ix/_BCM_HASH_TD3_NUM_BINS_PER_SET;
   1517         } else {
   1518             inx = 2 * (ix/_BCM_HASH_TD3_NUM_BINS_PER_SET);
   1519         }
   1520         data32 = soc_mem_field32_get(unit, 
   1521              prof_info->mem[inx], prof[inx], 
   1522              prof_info->fld[ix%_BCM_HASH_TD3_NUM_BINS_PER_SET]);
   1523 
   1524         if (!soc_format_field32_get(unit, FLEX_BIN_HASH_PROFILE_FORMATfmt,
   1525                     &data32, CMD_VALIDf)) {
   1526             continue;
   1527         }
   1528         bin_inx = BIN_INX(unit, inx, tcam_inx, ix);
   1529         bin_cmd[cmd_inx].obj_id = info->bin_obj_arr[bin_inx];
   1530         if (cfg->option & BCM_HASH_FLEX_BIN_OPTION_SIZE_8BIT) {
   1531             if (ix < _BCM_HASH_TD3_NUM_BINS_PER_SET) {
   1532                 bin_cmd[cmd_inx].bin_id = BCM_HASH_BIN_A_0 + ix;
   1533             } else if (ix < 2*_BCM_HASH_TD3_NUM_BINS_PER_SET) {
   1534                 bin_cmd[cmd_inx].bin_id = BCM_HASH_BIN_A_0_UPPER_HALF +
   1535                     ix % _BCM_HASH_TD3_NUM_BINS_PER_SET;
   1536             } else if (ix < 3*_BCM_HASH_TD3_NUM_BINS_PER_SET) {
   1537                 bin_cmd[cmd_inx].bin_id = BCM_HASH_BIN_B_0 +
   1538                     ix % _BCM_HASH_TD3_NUM_BINS_PER_SET;
   1539             } else {
   1540                 bin_cmd[cmd_inx].bin_id = BCM_HASH_BIN_B_0_UPPER_HALF +
   1541                     ix % _BCM_HASH_TD3_NUM_BINS_PER_SET;
   1542             }
   1543         } else {
   1544             if (ix < _BCM_HASH_TD3_NUM_BINS_PER_SET) {
   1545                 bin_cmd[cmd_inx].bin_id = BCM_HASH_BIN_A_0 + ix;
   1546             } else {
   1547                 bin_cmd[cmd_inx].bin_id = BCM_HASH_BIN_B_0 + 
   1548                     ix % _BCM_HASH_TD3_NUM_BINS_PER_SET;
   1549             }
   1550         }
   1551         offset_val = soc_format_field32_get(unit, 
   1552                     FLEX_BIN_HASH_PROFILE_FORMATfmt,
   1553                     &data32, CMD_SRC_CONTAINER_OFFSETf);
   1554         switch (bin_cmd[cmd_inx].obj_id) {
   1555             case BCM_HASH_OBJ_OUTER_MAC_DA:
   1556             case BCM_HASH_OBJ_INNER_MAC_DA:
   1557                 offset_val -= cmd_offset[BCM_HASH_OBJ_OFFSET_BIT48];
   1558                 break;
   1559             case BCM_HASH_OBJ_OUTER_IPV4_SIP:
   1560             case BCM_HASH_OBJ_INNER_IPV4_SIP:
   1561                 offset_val -= cmd_offset[BCM_HASH_OBJ_OFFSET_BIT96];
   1562                 break;
   1563             default:
   1564                 break;
   1565         }
   1566         for (iy = 0; iy < BCM_HASH_OBJ_OFFSET_MAX; iy++) {
   1567             if (cmd_offset[iy] == offset_val) {
   1568                 bin_cmd[cmd_inx].obj_offset = iy;
   1569             }
   1570         }
   1571 
   1572         bin_cmd[cmd_inx].bin_mask = soc_format_field32_get(unit, 
   1573                                     FLEX_BIN_HASH_PROFILE_FORMATfmt,
   1574                                     &data32, CMD_MASKf);
   1575         if (!(cfg->option & BCM_HASH_FLEX_BIN_OPTION_SIZE_8BIT)) {
   1576             uint16 upper_mask;
   1577 
   1578             data32 = soc_mem_field32_get(unit, 
   1579                  prof_info->mem[inx+1], prof[inx+1], 
   1580                  prof_info->fld[ix%_BCM_HASH_TD3_NUM_BINS_PER_SET]);
   1581             upper_mask = soc_format_field32_get(unit, 
   1582                                     FLEX_BIN_HASH_PROFILE_FORMATfmt,
   1583                                     &data32, CMD_MASKf);
   1584             bin_cmd[cmd_inx].bin_mask |= (upper_mask << 8);
   1585         }
   1586         cmd_inx++;
   1587     }
   1588     if (cmd_inx < num_bins) {
   1589         /* mark the end if not all entries are filled */
   1590         bin_cmd[cmd_inx].obj_id = BCM_HASH_OBJ_ID_INVALID;
   1591     } 
   1592     return BCM_E_NONE;
   1593 }
   1594 
   1595 /*
   1596  * Function:
   1597  *      bcmi_td3_hash_flex_bin_traverse
   1598  * Purpose:
   1599  *      Traverse all added entries in the TCAM. 
   1600  *   Parameters:
   1601  *      unit      - (IN)  Unit ID.
   1602  *      option    - (IN)  bin_cmd for 8bit data or 16bit. Default 16bit.
   1603  *                        BCM_HASH_FLEX_BIN_OPTION_SIZE_8BIT: 8bit
   1604  *      cb        - (IN)  callback function
   1605  *      user_data - (IN)  User context data
   1606  */
   1607 
   1608 int bcmi_td3_hash_flex_bin_traverse(
   1609     int unit,
   1610     uint32 option,
   1611     bcm_hash_flex_bin_traverse_cb cb,
   1612     void *user_data)
   1613 {
   1614     int ix,iy;
   1615     int size;
   1616     int rv = BCM_E_NONE;
   1617     bcm_hash_flex_bin_config_t cfg;
   1618     bcm_hash_flex_bin_cmd_t  bin_cmd[4 * _BCM_HASH_TD3_NUM_BINS_PER_SET];
   1619     int numBins;
   1620     bcm_hash_flex_field_t flex_field[40];
   1621     int num_fields;
   1622     int inx;
   1623 
   1624     num_fields = 40;
   1625     size = soc_mem_index_count(unit, FLEX_RTAG7_HASH_TCAMm);
   1626     if (option & BCM_HASH_FLEX_BIN_OPTION_SIZE_8BIT) {
   1627         numBins = 4 * _BCM_HASH_TD3_NUM_BINS_PER_SET;
   1628     } else {
   1629         numBins = 2 * _BCM_HASH_TD3_NUM_BINS_PER_SET;
   1630     }
   1631 
   1632     for (ix = size - 1; ix >= 0; ix--) {
   1633         bcm_hash_flex_bin_config_t_init(&cfg);
   1634         cfg.option = option;
   1635         cfg.entry_id = ix;
   1636         for (iy = 0; iy < numBins; iy++) {
   1637             bin_cmd[iy].obj_id = BCM_HASH_OBJ_ID_INVALID;
   1638         }
   1639         rv = bcmi_td3_hash_flex_bin_get(unit, &cfg, numBins, bin_cmd,
   1640                  num_fields, flex_field);
   1641 
   1642         if (rv == BCM_E_NOT_FOUND) { /* for entries not exposed to user */
   1643             rv = BCM_E_NONE;
   1644             continue;
   1645         } else if (BCM_FAILURE(rv)) {
   1646             break;
   1647         }
   1648         /* find the actual number of flex field retrieved */
   1649         for (iy = 0; iy < num_fields; iy++) {
   1650             if (!flex_field[iy].field_id) {
   1651                 break;
   1652             }
   1653         }
   1654         /* find the actual number of bin_cmd entries retrieved */
   1655         for (inx = 0; inx < numBins; inx++) {
   1656             if (bin_cmd[inx].obj_id == BCM_HASH_OBJ_ID_INVALID) {
   1657                 break;
   1658             }
   1659         }
   1660         rv = cb(unit, &cfg, inx, bin_cmd, iy,
   1661                  iy? flex_field: NULL,
   1662                  user_data);
   1663         if (BCM_FAILURE(rv)) {
   1664             break;
   1665         }
   1666     }
   1667     return rv;
   1668 }
   1669 
   1670 /*
   1671  * Function:
   1672  *      _bcm_hash_td3_flex_field_add
   1673  * Purpose:
   1674  *      Process user inputed flex fields into TD3's Cancun CEH defined flex 
   1675  * objects such as match_id, flow_id and hve_control. Those objects are part
   1676  * of the TCAM's key.
   1677  */
   1678 
   1679 STATIC int _bcm_hash_td3_flex_field_add(
   1680     int unit,
   1681     int num_fields,  /* number of flex fields */
   1682     bcm_hash_flex_field_t *flex_field, /* user provided flex fields */
   1683     _bcm_hash_td3_flex_obj_t *flex_obj, /* Cancun CEH defined flex object */
   1684     _bcm_hash_td3_flex_obj_t *flex_obj_mask) /* flex object's mask */
   1685 {
   1686     soc_cancun_ceh_field_info_t fld_info;
   1687     soc_cancun_ceh_field_info_t m_zone;
   1688     char *flex_obj_name;
   1689     uint16 *flow_obj = NULL;
   1690     uint16 *flow_obj_mask = NULL;
   1691     uint8 *hve_obj = NULL;
   1692     uint8 *hve_obj_mask = NULL;
   1693     int match_obj = FALSE;
   1694     int rv;
   1695     uint32 fld_mask;
   1696     uint32 obj;
   1697     int ix;
   1698     int size;
   1699     char *field_name = NULL;
   1700     int op_flag; 
   1701     uint64 tmp64;
   1702 
   1703     for (ix = 0; ix < num_fields; ix++) {
   1704         match_obj      = FALSE;
   1705         flow_obj       = NULL;
   1706         flow_obj_mask  = NULL;
   1707         hve_obj        = NULL;
   1708         hve_obj_mask   = NULL; 
   1709 
   1710         obj = FIELD_OBJ_ID(flex_field[ix].field_id);
   1711         flex_obj_name = _bcm_hash_td3_obj_names[obj];
   1712         
   1713         if (obj == BCM_HASH_FLEX_OBJ_MATCH_ID_ZONE0) {
   1714             match_obj = TRUE;
   1715         } else if (obj == BCM_HASH_FLEX_OBJ_MATCH_ID_ZONE1) {
   1716             match_obj = TRUE;
   1717         } else if (obj == BCM_HASH_FLEX_OBJ_MATCH_ID_ZONE2) {
   1718             match_obj = TRUE;
   1719         } else if (obj == BCM_HASH_FLEX_OBJ_MATCH_ID_ZONE3) {
   1720             match_obj = TRUE;
   1721         } else if (obj == BCM_HASH_FLEX_OBJ_MATCH_ID_ZONE4) {
   1722             match_obj = TRUE;
   1723         } else if (obj == BCM_HASH_FLEX_OBJ_FLOW_ID_0) {
   1724             flow_obj = &flex_obj->flow_id0;
   1725             flow_obj_mask = &flex_obj_mask->flow_id0;
   1726         } else if (obj == BCM_HASH_FLEX_OBJ_FLOW_ID_1) {
   1727             flow_obj = &flex_obj->flow_id1;
   1728             flow_obj_mask = &flex_obj_mask->flow_id1;
   1729         } else if (obj == BCM_HASH_FLEX_OBJ_FLOW_ID_2) {
   1730             flow_obj = &flex_obj->flow_id2;
   1731             flow_obj_mask = &flex_obj_mask->flow_id2;
   1732         } else if (obj == BCM_HASH_FLEX_OBJ_HVE_CONTROL_1) {
   1733             hve_obj = &flex_obj->hve_ctrl1;
   1734             hve_obj_mask = &flex_obj_mask->hve_ctrl1;
   1735         } else if (obj == BCM_HASH_FLEX_OBJ_HVE_CONTROL_2) {
   1736             hve_obj = &flex_obj->hve_ctrl2;
   1737             hve_obj_mask = &flex_obj_mask->hve_ctrl2;
   1738         } else {
   1739             rv = BCM_E_UNAVAIL;
   1740             goto exit;
   1741         }
   1742 
   1743         /* get the field_name size first */
   1744         rv = soc_cancun_ceh_obj_field_name_get (unit,
   1745                  FIELD_NAME_ID(flex_field[ix].field_id),
   1746                  &size, NULL);
   1747         if (BCM_FAILURE(rv)) {
   1748             goto exit;
   1749         }
   1750 
   1751         field_name = sal_alloc(size, "td3_hash_flex_temp_buffer");
   1752         if (field_name == NULL) {
   1753             rv = BCM_E_MEMORY;
   1754             goto exit;
   1755         }
   1756 
   1757         /* get the field_name */
   1758         rv = soc_cancun_ceh_obj_field_name_get (unit,
   1759                  FIELD_NAME_ID(flex_field[ix].field_id),
   1760                  &size, field_name);
   1761         if (BCM_FAILURE(rv)) {
   1762             goto exit;
   1763         }
   1764 
   1765         rv = soc_cancun_ceh_obj_field_get(unit,flex_obj_name, 
   1766                  field_name, &fld_info);
   1767         if (BCM_FAILURE(rv)) {
   1768             goto exit;
   1769         }
   1770 
   1771         /* The Cancun defined Match_id overall width 50 bit. divided
   1772          * into 5 zone.
   1773          */
   1774 
   1775         if (match_obj) {
   1776             uint64 m_id;
   1777             uint64 m_id_mask;
   1778 
   1779             COMPILER_64_ZERO(m_id);
   1780             COMPILER_64_ZERO(m_id_mask);
   1781             /* Retrieve the match zone value and mask */
   1782             rv = soc_cancun_ceh_obj_field_get(unit,"MATCH_ID",flex_obj_name, 
   1783                      &m_zone);
   1784             if (BCM_FAILURE(rv)) {
   1785                 goto exit;
   1786             }
   1787             fld_mask = (1 << fld_info.width) - 1;
   1788             fld_mask = fld_mask << fld_info.offset;
   1789             COMPILER_64_SET(m_id_mask, 0, fld_mask);
   1790             COMPILER_64_SHL(m_id_mask, m_zone.offset);
   1791             COMPILER_64_SET(m_id, 0, fld_info.value);
   1792             COMPILER_64_SHL(m_id, fld_info.offset);
   1793             COMPILER_64_SHL(m_id, m_zone.offset);
   1794 
   1795             if (flex_field[ix].mask == 0 || flex_field[ix].value == 0) {
   1796                 op_flag = 0;
   1797             } else {
   1798                 op_flag = 1;
   1799             }
   1800 
   1801             /* add field, check if field collision: mask overlap */
   1802             if (op_flag) {
   1803                 COMPILER_64_COPY(tmp64, m_id_mask);
   1804                 COMPILER_64_AND(tmp64, flex_obj_mask->match_id);
   1805                 if (!COMPILER_64_IS_ZERO(tmp64)) {
   1806                     LOG_ERROR(BSL_LS_BCM_HASH, (BSL_META_U(unit,
   1807                         "Flex field conflict: %s\n"), field_name));
   1808                     rv = BCM_E_PARAM;
   1809                     goto exit;
   1810                 }
   1811                 COMPILER_64_OR(flex_obj_mask->match_id, m_id_mask);
   1812                 COMPILER_64_OR(flex_obj->match_id, m_id);
   1813             } else {
   1814                 /* clear the field */
   1815                 COMPILER_64_NOT(m_id_mask);
   1816                 COMPILER_64_AND(flex_obj_mask->match_id, m_id_mask);
   1817                 COMPILER_64_AND(flex_obj->match_id, m_id_mask);
   1818             }
   1819         } else if (flow_obj != NULL) {
   1820 
   1821             if (flex_field[ix].mask == 0 || flex_field[ix].value == 0) {
   1822                 op_flag = 0;
   1823             } else {
   1824                 op_flag = 1;
   1825             }
   1826 
   1827             fld_mask = (1 << fld_info.width) - 1;
   1828             fld_mask = fld_mask << fld_info.offset;
   1829             if (op_flag) {
   1830                 if (fld_mask & *flow_obj_mask) {
   1831                     LOG_ERROR(BSL_LS_BCM_FLOW, (BSL_META_U(unit,
   1832                         "Flex field conflict: %s\n"), field_name));
   1833                     rv = BCM_E_PARAM;
   1834                     goto exit;
   1835                 }
   1836                 *flow_obj &= (uint16)(~fld_mask); 
   1837                 *flow_obj |= (uint16)((fld_info.value << fld_info.offset) & 
   1838                           fld_mask);
   1839                 *flow_obj_mask |= fld_mask; 
   1840             } else {
   1841                 *flow_obj      &= (uint16)(~fld_mask); 
   1842                 *flow_obj_mask &= (uint16)(~fld_mask); 
   1843             }
   1844         } else if (hve_obj != NULL) {
   1845             fld_mask = (1 << fld_info.width) - 1;
   1846             fld_mask = fld_mask << fld_info.offset;
   1847             if (flex_field[ix].mask == 0) {
   1848                 *hve_obj_mask &= (uint8)(~fld_mask);
   1849                 *hve_obj      &= (uint8)(~fld_mask);
   1850             } else {
   1851                 *hve_obj_mask |= (uint8)(fld_mask);
   1852                 *hve_obj |= (uint8)((flex_field[ix].value << fld_info.offset) &
   1853                                fld_mask);
   1854             }
   1855         } else {
   1856             rv = BCM_E_INTERNAL;
   1857             goto exit;
   1858         }
   1859         sal_free(field_name);
   1860         field_name = NULL;
   1861     }
   1862     return BCM_E_NONE;
   1863 
   1864 exit:
   1865     if (field_name != NULL) {
   1866         sal_free(field_name);
   1867     }
   1868     return rv;
   1869 }
   1870 
   1871 /*
   1872  * Function:
   1873  *      _bcm_hash_td3_flex_field_get
   1874  * Purpose:
   1875  *      Retrieve data from TD3's Cancun CEH defined flex objects such as
   1876  * match_id, flow_id and hve_control. And fill the flex_field buffer array
   1877  * provided by user.
   1878  */
   1879 
   1880 STATIC int _bcm_hash_td3_flex_field_get(
   1881     int unit,
   1882     int num_fields,
   1883     bcm_hash_flex_field_t *flex_field,
   1884     _bcm_hash_td3_flex_obj_t *flex_obj,
   1885     _bcm_hash_td3_flex_obj_t *flex_obj_mask)
   1886 {
   1887     soc_cancun_ceh_field_info_t fld_info;
   1888     soc_cancun_ceh_field_info_t m_zone;
   1889     char *flex_obj_name;
   1890     uint16 *flow_obj = NULL;
   1891     uint16 *flow_obj_mask = NULL;
   1892     uint8 *hve_obj = NULL;
   1893     uint8 *hve_obj_mask = NULL;
   1894     int match_obj = FALSE;
   1895     int rv;
   1896     uint32 fld_mask;
   1897     bcm_hash_flex_object_t obj;
   1898     int ix;
   1899     int size;
   1900     char *field_name = NULL;
   1901     uint32 *id_arr = NULL;
   1902     int inx;
   1903     int fld_size;
   1904     uint32 mz_mask;
   1905     uint32 fld_value;
   1906     int buf_limit = FALSE;
   1907     uint64 m_id;
   1908     uint64 m_id_mask;
   1909     uint64 tmp64;
   1910     uint32 tmp32;
   1911 
   1912     COMPILER_64_ZERO(m_id);
   1913     COMPILER_64_ZERO(m_id_mask);
   1914     inx = 0;
   1915     for (obj = BCM_HASH_FLEX_OBJ_MATCH_ID_ZONE0; obj < BCM_HASH_FLEX_OBJ_MAX;
   1916          obj++) {
   1917 
   1918         match_obj      = FALSE;
   1919         flow_obj       = NULL;
   1920         flow_obj_mask  = NULL;
   1921         hve_obj        = NULL;
   1922         hve_obj_mask   = NULL; 
   1923         if (obj == BCM_HASH_FLEX_OBJ_MATCH_ID_ZONE0) {
   1924             match_obj = TRUE;
   1925         } else if (obj == BCM_HASH_FLEX_OBJ_MATCH_ID_ZONE1) {
   1926             match_obj = TRUE;
   1927         } else if (obj == BCM_HASH_FLEX_OBJ_MATCH_ID_ZONE2) {
   1928             match_obj = TRUE;
   1929         } else if (obj == BCM_HASH_FLEX_OBJ_MATCH_ID_ZONE3) {
   1930             match_obj = TRUE;
   1931         } else if (obj == BCM_HASH_FLEX_OBJ_MATCH_ID_ZONE4) {
   1932             match_obj = TRUE;
   1933         } else if (obj == BCM_HASH_FLEX_OBJ_FLOW_ID_0) {
   1934             flow_obj = &flex_obj->flow_id0;
   1935             flow_obj_mask = &flex_obj_mask->flow_id0;
   1936         } else if (obj == BCM_HASH_FLEX_OBJ_FLOW_ID_1) {
   1937             flow_obj = &flex_obj->flow_id1;
   1938             flow_obj_mask = &flex_obj_mask->flow_id1;
   1939         } else if (obj == BCM_HASH_FLEX_OBJ_FLOW_ID_2) {
   1940             flow_obj = &flex_obj->flow_id2;
   1941             flow_obj_mask = &flex_obj_mask->flow_id2;
   1942         } else if (obj == BCM_HASH_FLEX_OBJ_HVE_CONTROL_1) {
   1943             hve_obj = &flex_obj->hve_ctrl1;
   1944             hve_obj_mask = &flex_obj_mask->hve_ctrl1;
   1945         } else { /* (obj == BCM_HASH_FLEX_OBJ_HVE_CONTROL_2) */
   1946             hve_obj = &flex_obj->hve_ctrl2;
   1947             hve_obj_mask = &flex_obj_mask->hve_ctrl2;
   1948         }
   1949 
   1950         flex_obj_name = _bcm_hash_td3_obj_names[obj];
   1951         rv = soc_cancun_ceh_obj_field_id_list_get(unit, flex_obj_name, &size,
   1952                  NULL);
   1953         if (BCM_FAILURE(rv)) {
   1954             if (rv == SOC_E_NOT_FOUND) {
   1955                 continue;
   1956             } else {
   1957                 goto exit;
   1958             }
   1959         }
   1960    
   1961         id_arr = sal_alloc(size * sizeof(uint32), "td3_hash_flex_temp_buffer");
   1962         if (id_arr == NULL) {
   1963             rv = BCM_E_MEMORY;
   1964             goto exit;
   1965         }
   1966 
   1967         rv = soc_cancun_ceh_obj_field_id_list_get(unit, flex_obj_name, &size,
   1968                  id_arr);
   1969         if (BCM_FAILURE(rv)) {
   1970             goto exit;
   1971         }
   1972 
   1973         if (match_obj) {
   1974             COMPILER_64_ZERO(m_id);
   1975             COMPILER_64_ZERO(m_id_mask);
   1976 
   1977             /* Retrieve the match zone value and mask */
   1978             rv = soc_cancun_ceh_obj_field_get(unit,"MATCH_ID",
   1979                      flex_obj_name, &m_zone);
   1980             if (BCM_FAILURE(rv)) {
   1981                 goto exit;
   1982             }
   1983             COMPILER_64_COPY(m_id_mask, flex_obj_mask->match_id);
   1984             COMPILER_64_SHR(m_id_mask, m_zone.offset);
   1985             COMPILER_64_COPY(m_id, flex_obj->match_id);
   1986             COMPILER_64_SHR(m_id, m_zone.offset);
   1987             mz_mask = (1 << m_zone.width) - 1;
   1988             COMPILER_64_SET(tmp64, 0, mz_mask);
   1989             COMPILER_64_AND(m_id_mask, tmp64);
   1990             COMPILER_64_AND(m_id, tmp64);
   1991         }
   1992 
   1993         for (ix = 0; ix < size; ix++) {
   1994             /* get the field_name size first */
   1995             rv = soc_cancun_ceh_obj_field_name_get (unit,
   1996                      id_arr[ix], &fld_size, NULL);
   1997             if (BCM_FAILURE(rv)) {
   1998                 goto exit;
   1999             }
   2000 
   2001             field_name = sal_alloc(fld_size, "td3_hash_flex_temp_buffer");
   2002             if (field_name == NULL) {
   2003                 rv = BCM_E_MEMORY;
   2004                 goto exit;
   2005             }
   2006 
   2007             /* get the field_name */
   2008             rv = soc_cancun_ceh_obj_field_name_get (unit,
   2009                      id_arr[ix], &fld_size, field_name);
   2010             if (BCM_FAILURE(rv)) {
   2011                 goto exit;
   2012             }
   2013 
   2014             rv = soc_cancun_ceh_obj_field_get(unit,flex_obj_name, 
   2015                      field_name, &fld_info);
   2016             if (BCM_FAILURE(rv)) {
   2017                 goto exit;
   2018             }
   2019 
   2020             /* The Cancun defined Match_id overall width 50 bit. divided
   2021              * into 5 zone.
   2022              */
   2023 
   2024             if (match_obj) {
   2025                 fld_mask = (1 << fld_info.width) - 1;
   2026                 fld_mask = fld_mask << fld_info.offset;
   2027                 COMPILER_64_TO_32_LO(tmp32, m_id_mask);
   2028                 if ((fld_mask & tmp32) != fld_mask) {
   2029                     sal_free(field_name);
   2030                     field_name = NULL;
   2031                     continue;
   2032                 }
   2033                 fld_value = fld_info.value << fld_info.offset;
   2034                 COMPILER_64_TO_32_LO(tmp32, m_id);
   2035                 if (fld_value != (tmp32 & fld_mask)) {
   2036                     sal_free(field_name);
   2037                     field_name = NULL;
   2038                     continue;
   2039                 }
   2040                 /* found one. remove the mask */
   2041                 COMPILER_64_SET(tmp64, 0, ~fld_mask);
   2042                 COMPILER_64_AND(m_id_mask, tmp64);
   2043 
   2044                 if (num_fields <= inx) {
   2045                     buf_limit = TRUE;
   2046                     break;
   2047                 }
   2048                 flex_field[inx].field_id = FIELD_OBJ_ID_SET(id_arr[ix], obj);
   2049                 flex_field[inx].mask     = 1;
   2050                 flex_field[inx].value    = 1;
   2051                 inx++;
   2052             } else if (flow_obj_mask != NULL) {
   2053 
   2054                 fld_mask = (1 << fld_info.width) - 1;
   2055                 fld_mask = fld_mask << fld_info.offset;
   2056                 if ((fld_mask & (*flow_obj_mask)) != fld_mask) {
   2057                     sal_free(field_name);
   2058                     field_name = NULL;
   2059                     continue;
   2060                 }
   2061                 fld_value = fld_info.value << fld_info.offset;
   2062                 if (fld_value != ((*flow_obj) & fld_mask)) {
   2063                     sal_free(field_name);
   2064                     field_name = NULL;
   2065                     continue;
   2066                 }
   2067                 /* found one. remove the mask */
   2068                 *flow_obj_mask = (~fld_mask) & (*flow_obj_mask);
   2069 
   2070                 if (num_fields <= inx) {
   2071                     buf_limit = TRUE;
   2072                     break;
   2073                 }
   2074                 flex_field[inx].field_id = FIELD_OBJ_ID_SET(id_arr[ix], obj);
   2075                 flex_field[inx].mask     = 1;
   2076                 flex_field[inx].value    = 1;
   2077                 inx++;
   2078             } else if (hve_obj_mask != NULL) {
   2079                 fld_mask = (1 << fld_info.width) - 1;
   2080                 fld_mask = fld_mask << fld_info.offset;
   2081                 if ((fld_mask & (*hve_obj_mask)) != fld_mask) {
   2082                     sal_free(field_name);
   2083                     field_name = NULL;
   2084                     continue;
   2085                 }
   2086                 /* found one. remove the mask */
   2087                 *hve_obj_mask = (~fld_mask) & (*hve_obj_mask);
   2088 
   2089                 if (num_fields <= inx) {
   2090                     buf_limit = TRUE;
   2091                     break;
   2092                 }
   2093                 flex_field[inx].field_id = FIELD_OBJ_ID_SET(id_arr[ix], obj);
   2094                 flex_field[inx].mask     = 1;
   2095                 if ((*hve_obj) & fld_mask) {
   2096                     flex_field[inx].value    = 1;
   2097                 } else {
   2098                     flex_field[inx].value    = 0;
   2099                 }
   2100                 inx++;
   2101             } else {
   2102                 rv = BCM_E_INTERNAL;
   2103                 goto exit;
   2104             }
   2105             sal_free(field_name);
   2106             field_name = NULL;
   2107         }
   2108         if (field_name != NULL) {
   2109             sal_free(field_name);
   2110             field_name = NULL;
   2111         }
   2112         sal_free(id_arr);
   2113         id_arr = NULL;
   2114         if (buf_limit == TRUE) {
   2115             break;
   2116         }
   2117     }
   2118     /* clear the remaining buffer */
   2119     for (ix = inx; ix < num_fields; ix++) {
   2120         flex_field[inx].field_id = 0;
   2121         flex_field[inx].mask     = 0;
   2122         flex_field[inx].value    = 0;
   2123     }
   2124     return BCM_E_NONE;
   2125 
   2126 exit:
   2127     if (id_arr != NULL) {
   2128         sal_free(id_arr);
   2129     }
   2130     if (field_name != NULL) {
   2131         sal_free(field_name);
   2132     }
   2133     return rv;
   2134 }
   2135 
   2136 #endif  /* #if defined(BCM_TRIDENT3_SUPPORT) */