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


      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:     Tomahawk3 hash table calculation routines
      9  * Requires:
     10  */
     11 
     12 #include <shared/bsl.h>
     13 
     14 #include <soc/drv.h>
     15 #include <soc/mem.h>
     16 #include <soc/debug.h>
     17 #include <soc/hash.h>
     18 
     19 #if defined(BCM_TOMAHAWK3_SUPPORT)
     20 
     21 #include <soc/tomahawk3.h>
     22 
     23 /* Map physical to logical bank mapping for a memory
     24  *  mem         - memory
     25  *  phy_bank    - physical bank number
     26  *  log_bank    - logical bank id
     27  */
     28 STATIC int
     29 soc_tomahawk3_phy_to_log_bank_map(int unit, soc_mem_t mem, int phy_bank, int *log_bank)
     30 {
     31     uint32 hash_control_entry[4];
     32     int i, done = 0;
     33     int bank_min=0, bank_max=3;
     34     static const soc_field_t logical_to_physical_fields[] = {
     35         LOGICAL_BANK_0_PHYSICAL_BANK_LOCATIONf,
     36         LOGICAL_BANK_1_PHYSICAL_BANK_LOCATIONf,
     37         LOGICAL_BANK_2_PHYSICAL_BANK_LOCATIONf,
     38         LOGICAL_BANK_3_PHYSICAL_BANK_LOCATIONf
     39     };
     40 
     41     sal_memset(hash_control_entry, 0, sizeof(hash_control_entry));
     42 
     43     switch(mem) {
     44         case EXACT_MATCH_2m:
     45         case EXACT_MATCH_4m:
     46             bank_min = 0;
     47             bank_max = 3;
     48             break;
     49         default:
     50             *log_bank = phy_bank;
     51             done = 1;
     52     }
     53 
     54     /* Shared Banks */
     55     if (done == 0) {
     56         /* Sanity */
     57         if (phy_bank < bank_min || phy_bank > bank_max) {
     58             return SOC_E_PARAM;
     59         }
     60 
     61         SOC_IF_ERROR_RETURN(soc_mem_read(unit, EXACT_MATCH_HASH_CONTROLm, MEM_BLOCK_ALL, 0,
     62                                          hash_control_entry));
     63         for (i = bank_min; i <= bank_max; i++) {
     64             if(soc_mem_field32_get(unit, EXACT_MATCH_HASH_CONTROLm, hash_control_entry,
     65                                    logical_to_physical_fields[i]) == phy_bank) {
     66                 *log_bank = i;
     67                 break;
     68             }
     69         }
     70     }
     71 
     72     return SOC_E_NONE;
     73 }
     74 
     75 
     76 
     77 /* Map logical to physical bank mapping for a memory
     78  *  mem         - memory 
     79  *  log_bank    - logical bank number (or sequence bank number)
     80  *  phy_bank_id - Physical bank id 
     81  */
     82 int
     83 soc_tomahawk3_log_to_phy_bank_map(int unit, soc_mem_t mem, int log_bank,
     84                                  int *phy_bank_id)
     85 {
     86     int done = 0, bank_min = 0, bank_max = 3;
     87     uint32 hash_control_entry[4];
     88 
     89     static const soc_field_t logical_to_physical_fields[] = {
     90         LOGICAL_BANK_0_PHYSICAL_BANK_LOCATIONf,
     91         LOGICAL_BANK_1_PHYSICAL_BANK_LOCATIONf,
     92         LOGICAL_BANK_2_PHYSICAL_BANK_LOCATIONf,
     93         LOGICAL_BANK_3_PHYSICAL_BANK_LOCATIONf,
     94     };
     95 
     96 
     97     switch(mem) {
     98     case L2Xm:
     99     case MPLS_ENTRY_SINGLEm:
    100         bank_min = 0;
    101         bank_max = 1;
    102         done = 1;
    103         break;
    104 
    105     case L3_ENTRY_ONLY_SINGLEm:
    106     case L3_ENTRY_ONLY_DOUBLEm:
    107     case L3_ENTRY_ONLY_QUADm:
    108     case L3_ENTRY_SINGLEm:
    109     case L3_ENTRY_DOUBLEm:
    110     case L3_ENTRY_QUADm:
    111     case L3_TUNNEL_SINGLEm:
    112     case L3_TUNNEL_DOUBLEm:
    113     case L3_TUNNEL_QUADm:
    114         bank_min = 0;
    115         bank_max = 3;
    116         done = 1;
    117         break;
    118 
    119 
    120     case EXACT_MATCH_2m:
    121     case EXACT_MATCH_4m:
    122         bank_min = 0;
    123         bank_max = 3;
    124         break;
    125 
    126     default:
    127         break;
    128     }
    129 
    130     if (log_bank < bank_min || log_bank > bank_max) {
    131         return SOC_E_PARAM;
    132     }
    133 
    134     if (!done) {
    135         sal_memset(hash_control_entry, 0, sizeof(hash_control_entry));
    136         SOC_IF_ERROR_RETURN(soc_mem_read(unit, EXACT_MATCH_HASH_CONTROLm, MEM_BLOCK_ALL, 0,
    137                                      hash_control_entry));
    138         *phy_bank_id = soc_mem_field32_get(unit, EXACT_MATCH_HASH_CONTROLm, hash_control_entry,
    139                        logical_to_physical_fields[log_bank]);
    140     } else {
    141         *phy_bank_id = log_bank;
    142     }
    143 
    144     return SOC_E_NONE;
    145 }
    146 
    147 STATIC int
    148 _soc_tomahawk3_hash_entry_to_key(int unit, int bank, void *entry, uint8 *key, soc_mem_t mem,
    149                           soc_field_t *field_list)
    150 {
    151     soc_field_t field;
    152     int         index, key_index, val_index, fval_index;
    153     int         right_shift_count, left_shift_count;
    154     uint32      val[SOC_MAX_MEM_WORDS], fval[SOC_MAX_MEM_WORDS];
    155     int         bits, val_bits, fval_bits, nbits;
    156     int8        field_length[16];
    157 #ifdef SOC_ROBUST_HASH
    158     soc_robust_hash_config_t *rbh_cfg = NULL;
    159 #endif /* SOC_ROBUST_HASH */
    160 
    161     val_bits = 0;
    162     for (index = 0; field_list[index] != INVALIDf; index++) {
    163         field = field_list[index];
    164         field_length[index] = soc_mem_field_length(unit, mem, field);
    165         val_bits += field_length[index];
    166     }
    167 
    168     switch (mem) {
    169     case L2Xm:
    170         val_bits = SOC_TH3_L2_ENTRY_MAX_KEY_WIDTH;
    171         break;
    172     case L3_ENTRY_ONLY_SINGLEm:
    173     case L3_ENTRY_SINGLEm:
    174     case L3_ENTRY_DOUBLEm:
    175     case L3_ENTRY_QUADm:
    176         val_bits = SOC_TH3_L3_MAX_KEY_WIDTH;
    177         break;
    178     case L3_TUNNEL_SINGLEm:
    179     case L3_TUNNEL_DOUBLEm:
    180     case L3_TUNNEL_QUADm:
    181         val_bits = SOC_TH3_L3_TUNNEL_MAX_KEY_WIDTH;
    182         break;
    183     case MPLS_ENTRY_SINGLEm:
    184         val_bits = SOC_TH3_L3_MPLS_MAX_KEY_WIDTH;
    185         break;
    186     case EXACT_MATCH_2m:
    187     case EXACT_MATCH_4m:
    188         val_bits = SOC_TH3_EXACT_MATCH_MAX_KEY_WIDTH;
    189         break;
    190     default:
    191         break;
    192     }
    193 
    194     nbits = val_bits;
    195 
    196 #ifdef SOC_ROBUST_HASH
    197     if (soc_feature(unit, soc_feature_robust_hash)) {
    198         switch (mem) {
    199         case L2Xm:
    200             rbh_cfg = &(ROBUSTHASH(unit)->l2);
    201             break;
    202         case L3_ENTRY_ONLY_SINGLEm:
    203         case L3_ENTRY_SINGLEm:
    204         case L3_ENTRY_DOUBLEm:
    205         case L3_ENTRY_QUADm:
    206             rbh_cfg = &(ROBUSTHASH(unit)->l3);
    207             break;
    208         case EXACT_MATCH_4m:
    209         case EXACT_MATCH_2m:
    210             rbh_cfg = &(ROBUSTHASH(unit)->exact_match);
    211             break;
    212         case MPLS_ENTRY_SINGLEm:
    213             rbh_cfg = &(ROBUSTHASH(unit)->mpls_entry);
    214             break;
    215         case L3_TUNNEL_SINGLEm:
    216         case L3_TUNNEL_DOUBLEm:
    217         case L3_TUNNEL_QUADm:
    218             rbh_cfg = &(ROBUSTHASH(unit)->tunnel);
    219             break;
    220         default:
    221             break;
    222         }
    223     }
    224 
    225 #endif /* SOC_ROBUST_HASH */
    226     bits = val_bits;
    227     val_bits = 0;
    228 
    229     sal_memset(val, 0, sizeof(val));
    230     for (index = 0; field_list[index] != INVALIDf; index++) {
    231         field = field_list[index];
    232         soc_mem_field_get(unit, mem, entry, field, fval);
    233         fval_bits = field_length[index];
    234 
    235         val_index = val_bits >> 5;
    236         fval_index = 0;
    237         left_shift_count = val_bits & 0x1f;
    238         right_shift_count = 32 - left_shift_count;
    239         val_bits += fval_bits;
    240 
    241         if (left_shift_count) {
    242             for (; fval_bits > 0; fval_bits -= 32) {
    243                 val[val_index++] |= fval[fval_index] << left_shift_count;
    244                 val[val_index] |= fval[fval_index++] >> right_shift_count;
    245             }
    246         } else {
    247             for (; fval_bits > 0; fval_bits -= 32) {
    248                 val[val_index++] = fval[fval_index++];
    249             }
    250         }
    251     }
    252 
    253     key_index = 0;
    254     for (val_index = 0; val_bits > 0; val_index++) {
    255         for (right_shift_count = 0; right_shift_count < 32;
    256              right_shift_count += 8) {
    257             if (val_bits <= 0) {
    258                 break;
    259             }
    260             key[key_index++] = (val[val_index] >> right_shift_count) & 0xff;
    261             val_bits -= 8;
    262         }
    263     }
    264 
    265     if ((bits + 7) / 8 > key_index) {
    266         sal_memset(&key[key_index], 0, (bits + 7) / 8 - key_index);
    267     }
    268 
    269     bits = (((nbits - 1) / 32) + 1) * 32;
    270 
    271 #ifdef SOC_ROBUST_HASH
    272     if (soc_feature(unit, soc_feature_robust_hash)) {
    273         if (rbh_cfg) {
    274             if (rbh_cfg->enable) {
    275                 (void) soc_robust_hash_get2(unit, rbh_cfg, bank, key, nbits); /* nbits = unpadded */
    276             }
    277 
    278             bits += ROBUST_HASH_KEY_SPACE_WIDTH;
    279         }
    280     }
    281 #endif /* SOC_ROBUST_HASH */
    282 
    283     return bits;
    284 }
    285 
    286 STATIC int
    287 _soc_tomahawk3_shared_hash(int unit, int hash_offset, uint32 key_nbits, uint8 *keyA,
    288                      uint8 *keyB, uint32 result_mask, uint16 lsb, int use_lsb)
    289 {
    290    uint32 crc_hi, crc_lo;
    291    uint64 hash_vector, mask;
    292 
    293    if (use_lsb) {
    294        /* Debug Mode
    295         * Hash Vector [63:48] ->  Zero
    296         * Hash Vector [47:32] ->  Hash LSB
    297         */
    298        crc_hi = lsb;
    299    } else {
    300        crc_hi = soc_crc32b(keyB, key_nbits);
    301    }
    302 
    303    crc_lo = soc_crc32b(keyA, key_nbits);
    304 
    305    COMPILER_64_SET(hash_vector, crc_hi, crc_lo);
    306    COMPILER_64_SET(mask, 0, result_mask);
    307    COMPILER_64_SHR(hash_vector, hash_offset);
    308    COMPILER_64_AND(hash_vector, mask);
    309    return (int)COMPILER_64_LO(hash_vector);
    310 }
    311 
    312 /* Get number of banks for the hash table according to the config
    313  */
    314 int
    315 soc_tomahawk3_hash_bank_count_get(int unit, soc_mem_t mem, int *num_banks)
    316 {
    317     int count;
    318 
    319     if (NULL == num_banks) {
    320         return SOC_E_PARAM;
    321     }
    322 
    323     switch (mem) {
    324     case L2Xm:
    325         /*
    326          * 4k single wide entries in each of 2 dedicated L2 bank
    327          */
    328         *num_banks = 2;
    329         break;
    330     case L3_ENTRY_ONLY_SINGLEm:
    331     case L3_ENTRY_ONLY_DOUBLEm:
    332     case L3_ENTRY_ONLY_QUADm:
    333     case L3_ENTRY_SINGLEm:
    334     case L3_ENTRY_DOUBLEm:
    335     case L3_ENTRY_QUADm:
    336         /*
    337          * 4k single wide entries in each of 4 dedicated L3 bank
    338          */
    339         *num_banks = 4;
    340         break;
    341 
    342     case EXACT_MATCH_2m:
    343     case EXACT_MATCH_4m:
    344         /*
    345          * 16k double wide entries in each shared bank
    346          */
    347         count = soc_mem_index_count(unit, EXACT_MATCH_2m);
    348         *num_banks = count / (16 * 1024);
    349         break;
    350 
    351     case MPLS_ENTRY_SINGLEm:
    352         /*
    353          * 8k single wide entries in each shared bank
    354          */
    355         *num_banks = 2;
    356         break;
    357     case L3_TUNNEL_SINGLEm:
    358     case L3_TUNNEL_DOUBLEm:
    359     case L3_TUNNEL_QUADm:
    360         /*
    361          * 4k single wide entries in each dedicated bank
    362          */
    363         *num_banks = 4;
    364         break;
    365 
    366     default:
    367         return SOC_E_INTERNAL;
    368     }
    369 
    370     return SOC_E_NONE;
    371 }
    372 
    373 /* Map bank sequence number to physical bank number */
    374 int
    375 soc_tomahawk3_hash_bank_number_get(int unit, soc_mem_t mem, int seq_num,
    376                              int *bank_num) {
    377     int count;
    378 
    379     SOC_IF_ERROR_RETURN(soc_tomahawk3_hash_bank_count_get(unit, mem, &count));
    380     if (seq_num < 0 || seq_num >= count) {
    381         return SOC_E_CONFIG;
    382     }
    383     SOC_IF_ERROR_RETURN(soc_tomahawk3_log_to_phy_bank_map(unit, mem, seq_num,
    384                                                         bank_num));
    385 
    386     return SOC_E_NONE;
    387 }
    388 
    389 int
    390 soc_tomahawk3_hash_seq_number_get(int unit, soc_mem_t mem, int bank_num, int *seq_num)
    391 {
    392     int count;
    393 
    394     SOC_IF_ERROR_RETURN(soc_tomahawk3_phy_to_log_bank_map(unit, mem, bank_num,
    395                                                     seq_num));
    396 
    397     SOC_IF_ERROR_RETURN(soc_tomahawk3_hash_bank_count_get(unit, mem, &count));
    398     if (*seq_num < 0 || *seq_num >= count) {
    399         return SOC_E_INTERNAL;
    400     }
    401 
    402     return SOC_E_NONE;
    403 }
    404 
    405 uint32
    406 soc_tomahawk3_tunnel_hash(int unit, int bank, int hash_offset, int use_lsb,
    407                   int key_nbits, void *base_entry, uint8 *key1, uint8 *key2)
    408 {
    409     uint32 lsb_val;
    410     uint32 hash_mask;
    411     uint32 hash_bits;
    412 
    413     hash_mask = 0x3FF;
    414     hash_bits = 10;
    415 
    416     if (use_lsb && (hash_offset + hash_bits > 32)) {
    417         int key_type;
    418         key_type = soc_mem_field32_get(unit, L3_TUNNEL_SINGLEm,
    419                                           base_entry, KEY_TYPEf);
    420         switch (key_type) {
    421         case TH3_MPLS_HASH_KEY_TYPE_MPLS:
    422             lsb_val = soc_mem_field32_get(unit, L3_TUNNEL_SINGLEm, base_entry,
    423                                           MPLS__HASH_LSBf);
    424             break;
    425 
    426         case TH3_TUNNEL_HASH_KEY_TYPE_V4:
    427             lsb_val = soc_mem_field32_get(unit, L3_TUNNEL_DOUBLEm, base_entry,
    428                                           IPV4UC__HASH_LSBf);
    429             break;
    430 
    431         case TH3_TUNNEL_HASH_KEY_TYPE_V6:
    432             lsb_val = soc_mem_field32_get(unit, L3_TUNNEL_QUADm, base_entry,
    433                                           IPV6UC__HASH_LSBf);
    434             break;
    435 
    436         default:
    437             lsb_val = 0;
    438             break;
    439         }
    440     } else {
    441         lsb_val = 0;
    442     }
    443 
    444     return _soc_tomahawk3_shared_hash(unit, hash_offset, key_nbits, key1, key2,
    445                                 hash_mask, lsb_val, use_lsb);
    446 }
    447 
    448 
    449 int
    450 soc_tomahawk3_tunnel_base_entry_to_key(int unit, int bank, uint32 *entry, uint8 *key)
    451 {
    452     soc_mem_t mem;
    453     soc_field_t field_list[5];
    454 
    455     switch (soc_mem_field32_get(unit, L3_TUNNEL_SINGLEm, entry, KEY_TYPEf)) {
    456     case TH3_TUNNEL_HASH_KEY_TYPE_MPLS:
    457         mem = L3_TUNNEL_SINGLEm;
    458         field_list[0] = MPLS__KEYf;
    459         field_list[1] = INVALIDf;
    460         break;
    461     case TH3_TUNNEL_HASH_KEY_TYPE_V4:
    462         mem = L3_TUNNEL_DOUBLEm;
    463         field_list[0] = IPV4__KEY_0f;
    464         field_list[1] = IPV4__KEY_1f;
    465         field_list[2] = INVALIDf;
    466         break;
    467     case TH3_TUNNEL_HASH_KEY_TYPE_V6:
    468         mem = L3_TUNNEL_QUADm;
    469         field_list[0] = IPV6__KEY_0f;
    470         field_list[1] = IPV6__KEY_1f;
    471         field_list[2] = IPV6__KEY_2f;
    472         field_list[3] = IPV6__KEY_3f;
    473         field_list[4] = INVALIDf;
    474         break;
    475     default:
    476         return 0;
    477     }
    478     return _soc_tomahawk3_hash_entry_to_key(unit, bank, entry, key, mem, field_list);
    479 }
    480 
    481 uint32
    482 soc_tomahawk3_tunnel_entry_hash(int unit, int bank, int hash_offset, int use_lsb,
    483                       uint32 *entry)
    484 {
    485     int             key_nbits;
    486     uint8           key1[SOC_MAX_MEM_WORDS * 4] = {0};
    487     uint8           key2[SOC_MAX_MEM_WORDS * 4] = {0};
    488 
    489     /* Robust Hashed Key using Remap and Action Tables A */
    490     key_nbits = soc_tomahawk3_tunnel_base_entry_to_key(unit, 0, entry, key1);
    491     /* Robust Hashed Key using Remap and Action Tables B */
    492     key_nbits = soc_tomahawk3_tunnel_base_entry_to_key(unit, 1, entry, key2);
    493     return soc_tomahawk3_tunnel_hash(unit, bank, hash_offset, use_lsb,
    494                              key_nbits, entry, key1, key2);
    495 }
    496 
    497 uint32
    498 soc_tomahawk3_tunnel_bank_entry_hash(int unit, int bank, uint32 *entry)
    499 {
    500     int rv, hash_offset, use_lsb;
    501 
    502     rv = soc_tomahawk3_hash_offset_get(unit, L3_TUNNEL_SINGLEm, bank, &hash_offset,
    503                                 &use_lsb);
    504     if (SOC_FAILURE(rv)) {
    505         return 0;
    506     }
    507 
    508     return soc_tomahawk3_tunnel_entry_hash(unit, bank, hash_offset, use_lsb, entry);
    509 }
    510 
    511 uint32
    512 soc_tomahawk3_exact_match_hash(int unit, int bank, int hash_offset, int use_lsb,
    513                         int key_nbits, void *base_entry, uint8 *key1,
    514                         uint8 *key2)
    515 {
    516     uint32 lsb_val;
    517     uint32 hash_mask;
    518     uint32 hash_bits;
    519 
    520     hash_mask = 0x1fff; /* 4k buckets per shared bank for EXACT_MATCH_2m -> 8k base buckets for BM0 */
    521     hash_bits = 13;
    522 
    523     if (use_lsb && (hash_offset + hash_bits > 32)) {
    524         switch (soc_mem_field32_get(unit, EXACT_MATCH_2m, base_entry,
    525                                     KEY_TYPEf)) {
    526             case TH3_FPEM_HASH_KEY_TYPE_128B:
    527                 lsb_val = soc_mem_field32_get(unit, EXACT_MATCH_2m,
    528                                               base_entry, MODE128__HASH_LSBf);
    529                 break;
    530             case TH3_FPEM_HASH_KEY_TYPE_160B:
    531                 lsb_val = soc_mem_field32_get(unit, EXACT_MATCH_2m,
    532                                               base_entry, MODE160__HASH_LSBf);
    533                 break;
    534             case TH3_FPEM_HASH_KEY_TYPE_320B:
    535                 lsb_val = soc_mem_field32_get(unit, EXACT_MATCH_4m,
    536                                               base_entry, MODE320__HASH_LSBf);
    537                 break;
    538             default:
    539                 lsb_val = 0;
    540                 break;
    541         }
    542     } else {
    543         lsb_val = 0;
    544     }
    545 
    546     return _soc_tomahawk3_shared_hash(unit, hash_offset, key_nbits, key1, key2,
    547                                     hash_mask, lsb_val, use_lsb);
    548 }
    549 
    550 
    551 int
    552 soc_tomahawk3_exact_match_base_entry_to_key(int unit, int bank, uint32 *entry, uint8 *key)
    553 {
    554     soc_mem_t mem;
    555     soc_field_t field_list[5];
    556 
    557     switch (soc_mem_field32_get(unit, EXACT_MATCH_2m, entry, KEY_TYPEf)) {
    558         case TH3_FPEM_HASH_KEY_TYPE_128B:
    559             mem = EXACT_MATCH_2m;
    560             field_list[0] = MODE128__KEY_0f;
    561             field_list[1] = MODE128__KEY_1f;
    562             field_list[2] = INVALIDf;
    563             break;
    564         case TH3_FPEM_HASH_KEY_TYPE_160B:
    565             mem = EXACT_MATCH_2m;
    566             field_list[0] = MODE160__KEY_0f;
    567             field_list[1] = MODE160__KEY_1f;
    568             field_list[2] = INVALIDf;
    569             break;
    570         case TH3_FPEM_HASH_KEY_TYPE_320B:
    571             mem = EXACT_MATCH_4m;
    572             field_list[0] = MODE320__KEY_0f;
    573             field_list[1] = MODE320__KEY_1f;
    574             field_list[2] = MODE320__KEY_2f;
    575             field_list[3] = INVALIDf;
    576             break;
    577         default:
    578             return 0;
    579     }
    580     return _soc_tomahawk3_hash_entry_to_key(unit, bank, entry, key, mem, field_list);
    581 }
    582 
    583 uint32
    584 soc_tomahawk3_exact_match_entry_hash(int unit, int bank, int hash_offset,
    585                             int use_lsb, uint32 *entry)
    586 {
    587     int         key_nbits;
    588     uint8       key1[SOC_MAX_MEM_WORDS * 4] = {0};
    589     uint8       key2[SOC_MAX_MEM_WORDS * 4] = {0};
    590 
    591     /* Robust Hashed Key using Remap and Action Tables A */
    592     key_nbits = soc_tomahawk3_exact_match_base_entry_to_key(unit, 0, entry, key1);
    593     /* Robust Hashed Key using Remap and Action Tables B */
    594     key_nbits = soc_tomahawk3_exact_match_base_entry_to_key(unit, 1, entry, key2);
    595 
    596     return soc_tomahawk3_exact_match_hash(unit, bank, hash_offset, use_lsb,
    597                                     key_nbits, entry, key1, key2);
    598 }
    599 
    600 int
    601 soc_tomahawk3_mpls_base_entry_to_key(int unit, int bank, void *entry, uint8 *key) {
    602 
    603     soc_field_t field_list[2];
    604     switch (soc_mem_field32_get(unit, MPLS_ENTRY_SINGLEm, entry, KEY_TYPEf)) {
    605         case TH3_MPLS_HASH_KEY_TYPE_MPLS:
    606             
    607             field_list[0] = MPLS__KEYf;
    608             break;
    609         default:
    610             return 0;
    611     }
    612 
    613     field_list[1] = INVALIDf;
    614     return _soc_tomahawk3_hash_entry_to_key(unit, bank, entry, key,
    615                                       MPLS_ENTRY_SINGLEm, field_list);
    616 }
    617 
    618 uint32
    619 soc_tomahawk3_mpls_hash(int unit, int bank, int hash_offset, int use_lsb,
    620                   int key_nbits, void *base_entry, uint8 *key1, uint8 *key2)
    621 {
    622     uint32 lsb_val;
    623     uint32 hash_mask;
    624     uint32 hash_bits;
    625 
    626     hash_mask = 0x7FF; /* 2k buckets per shared bank of size 8k */
    627     hash_bits = 11;
    628 
    629     if (use_lsb && (hash_offset + hash_bits > 32)) {
    630         switch (soc_mem_field32_get(unit, MPLS_ENTRY_SINGLEm, base_entry,
    631                                     KEY_TYPEf)) {
    632         case TH3_MPLS_HASH_KEY_TYPE_MPLS:
    633             lsb_val = soc_mem_field32_get(unit, MPLS_ENTRY_SINGLEm, base_entry,
    634                                           MPLS__HASH_LSBf);
    635             break;
    636 
    637         default:
    638             lsb_val = 0;
    639             break;
    640         }
    641     } else {
    642         lsb_val = 0;
    643     }
    644 
    645     return _soc_tomahawk3_shared_hash(unit, hash_offset, key_nbits, key1, key2,
    646                                 hash_mask, lsb_val, use_lsb);
    647 }
    648 
    649 uint32
    650 soc_tomahawk3_mpls_entry_hash(int unit, int bank, int hash_offset,
    651                         int use_lsb, uint32 *entry)
    652 {
    653     int             key_nbits;
    654     uint8           key1[SOC_MAX_MEM_WORDS * 4] = {0};
    655     uint8           key2[SOC_MAX_MEM_WORDS * 4] = {0};
    656 
    657     /* Robust Hashed Key using Remap and Action Tables A */
    658     key_nbits = soc_tomahawk3_mpls_base_entry_to_key(unit, 0, entry, key1);
    659     /* Robust Hashed Key using Remap and Action Tables B */
    660     key_nbits = soc_tomahawk3_mpls_base_entry_to_key(unit, 1, entry, key2);
    661 
    662     return soc_tomahawk3_mpls_hash(unit, bank, hash_offset, use_lsb,
    663                              key_nbits, entry, key1, key2);
    664 }
    665 
    666 uint32
    667 soc_tomahawk3_mpls_bank_entry_hash(int unit, int bank, uint32 *entry)
    668 {
    669     int rv, hash_offset, use_lsb;
    670 
    671     rv = soc_tomahawk3_hash_offset_get(unit, MPLS_ENTRY_SINGLEm, bank, &hash_offset,
    672                                  &use_lsb);
    673     if (SOC_FAILURE(rv)) {
    674         return 0;
    675     }
    676 
    677     return soc_tomahawk3_mpls_entry_hash(unit, bank, hash_offset, use_lsb, entry);
    678 }
    679 
    680 int
    681 soc_tomahawk3_hash_bank_info_get(int unit, soc_mem_t mem, int bank,
    682                                 int *entries_per_bank, int *entries_per_row,
    683                                 int *entries_per_bucket, int *bank_base,
    684                                 int *bucket_offset)
    685 {
    686     int bank_size, row_size, bucket_size, base, offset;
    687     int seq_num = 0;
    688 
    689     /* Get logical bank number */
    690     SOC_IF_ERROR_RETURN(soc_tomahawk3_phy_to_log_bank_map(unit, mem, bank, &seq_num));
    691     bank = seq_num;
    692 
    693     /* bank_size = logical entries per bank 
    694      * row_size = logical entries per base bucket
    695      * bucket_size = logical entries per logical bucket = 4
    696      * offset = 0 since this is bank_info
    697      */
    698 
    699     switch (mem) {
    700     case L2Xm:
    701         bank_size = 4096;
    702         row_size = 4;
    703         bucket_size = 4;
    704         offset = 0;
    705         base = bank * bank_size;
    706         break;
    707 
    708     case L3_ENTRY_ONLY_SINGLEm:
    709     case L3_ENTRY_SINGLEm:
    710     case L3_ENTRY_DOUBLEm:
    711     case L3_ENTRY_QUADm:
    712         bucket_size = 4;
    713         offset = 0;
    714         if (mem == L3_ENTRY_QUADm) {
    715             row_size = 1;
    716             bank_size = 4096/4;
    717         } else if (mem == L3_ENTRY_DOUBLEm) {
    718             row_size = 2;
    719             bank_size = 4096/2;
    720         } else {
    721             row_size = 4;
    722             bank_size = 4096;
    723         }
    724         base = bank * bank_size;
    725         break;
    726 
    727     case EXACT_MATCH_2m:
    728         row_size = 2;
    729         bucket_size = 4;
    730         offset = 0;
    731         bank_size = 16384;
    732         base = bank * bank_size;
    733         break;
    734 
    735     case EXACT_MATCH_4m:
    736         row_size = 1;
    737         bucket_size = 4;
    738         offset = 0;
    739         bank_size = 8192;
    740         base = bank * bank_size;
    741         break;
    742 
    743     case L3_TUNNEL_SINGLEm:
    744     case L3_TUNNEL_DOUBLEm:
    745     case L3_TUNNEL_QUADm:
    746         bucket_size = 4;
    747         offset = 0;
    748         if (mem == L3_TUNNEL_QUADm) {
    749             row_size = 1;
    750             bank_size = 4096/4;
    751         } else if (mem == L3_TUNNEL_DOUBLEm) {
    752             row_size = 2;
    753             bank_size = 4096/2;
    754         } else {
    755             row_size = 4;
    756             bank_size = 4096;
    757         }
    758         base = bank * bank_size;
    759         break;
    760 
    761     case MPLS_ENTRY_SINGLEm:
    762         bank_size = 8192;
    763         row_size = 1;
    764         bucket_size = 4;
    765         offset = 0;
    766         base = bank_size * bank;
    767         break;
    768 
    769     default:
    770         return SOC_E_INTERNAL;
    771     }
    772 
    773     if (entries_per_bank != NULL) {
    774         *entries_per_bank = bank_size;
    775     }
    776     if (entries_per_row != NULL) {
    777         *entries_per_row = row_size;
    778     }
    779     if (entries_per_bucket != NULL) {
    780         *entries_per_bucket = bucket_size;
    781     }
    782     if (bank_base != NULL) {
    783         *bank_base = base;
    784     }
    785     if (bucket_offset != NULL) {
    786         *bucket_offset = offset;
    787     }
    788     return SOC_E_NONE;
    789 }
    790 
    791 int
    792 soc_tomahawk3_hash_offset_get(int unit, soc_mem_t mem, int bank, int *hash_offset,
    793                         int *use_lsb)
    794 {
    795     uint32 hash_control_entry[4];
    796     int is_shared = 1;
    797     soc_mem_t shared_mem = INVALIDm;
    798     soc_field_t field;
    799     static const soc_field_t uft_fields_d[] = {
    800         HASH_OFFSET_DEDICATED_BANK_0f, HASH_OFFSET_DEDICATED_BANK_1f,
    801         HASH_OFFSET_DEDICATED_BANK_2f, HASH_OFFSET_DEDICATED_BANK_3f
    802 
    803     };
    804     static const soc_field_t uft_fields_s[] = {
    805         B0_HASH_OFFSETf, B1_HASH_OFFSETf, B2_HASH_OFFSETf, B3_HASH_OFFSETf
    806     };
    807 
    808 
    809     sal_memset(hash_control_entry, 0, sizeof(hash_control_entry));
    810 
    811     switch(mem) {
    812     case L2Xm:
    813         if (bank < 0 || bank > 1) {
    814             return SOC_E_PARAM;
    815         }
    816         mem = L2_ENTRY_HASH_CONTROLm;
    817         field = uft_fields_d[bank];
    818         is_shared = 0;
    819         break;
    820     case EXACT_MATCH_2m:
    821     case EXACT_MATCH_4m:
    822         if (bank < 0 || bank > 3) {
    823             return SOC_E_PARAM;
    824         }
    825         mem = EXACT_MATCH_HASH_CONTROLm;
    826         shared_mem = UFT_SHARED_BANKS_CONTROLm;
    827         field = uft_fields_s[bank];
    828         break;
    829     case L3_TUNNEL_SINGLEm:
    830     case L3_TUNNEL_DOUBLEm:
    831     case L3_TUNNEL_QUADm:
    832         if (bank < 0 || bank > 3) {
    833             return SOC_E_PARAM;
    834         }
    835         mem = L3_TUNNEL_HASH_CONTROLm;
    836         field = uft_fields_d[bank];
    837         is_shared = 0;
    838         break;
    839     case L3_ENTRY_SINGLEm:
    840     case L3_ENTRY_DOUBLEm:
    841     case L3_ENTRY_QUADm:
    842     case L3_ENTRY_ONLYm:
    843     case L3_ENTRY_ONLY_SINGLEm:
    844         if (bank < 0 || bank > 3) {
    845             return SOC_E_PARAM;
    846         }
    847         mem = L3_ENTRY_HASH_CONTROLm;
    848         field = uft_fields_d[bank];
    849         is_shared = 0;
    850         break;
    851     case MPLS_ENTRY_SINGLEm:
    852         if (bank < 0 || bank > 1) {
    853             return SOC_E_PARAM;
    854         }
    855         mem = MPLS_ENTRY_HASH_CONTROLm;
    856         field = uft_fields_d[bank];
    857         is_shared = 0;
    858         break;
    859     default:
    860         return SOC_E_INTERNAL;
    861     }
    862 
    863     SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 0,
    864                                      hash_control_entry));
    865     if (use_lsb) {
    866         *use_lsb = soc_mem_field32_get(
    867             unit, mem, hash_control_entry, HASH_TABLE_TEST_MODEf);
    868     }
    869 
    870     /* Shared Banks */
    871     if (is_shared > 0) {
    872         sal_memset(hash_control_entry, 0, sizeof(hash_control_entry));
    873         SOC_IF_ERROR_RETURN(soc_mem_read(unit, shared_mem, MEM_BLOCK_ALL, 0,
    874                                          hash_control_entry));
    875         *hash_offset = soc_mem_field32_get(unit, shared_mem,
    876                                            hash_control_entry, field);
    877     } else {
    878         *hash_offset = soc_mem_field32_get(unit, mem, hash_control_entry, field);
    879     }
    880 
    881     return SOC_E_NONE;
    882 }
    883 
    884 int
    885 soc_tomahawk3_hash_offset_set(int unit, soc_mem_t mem, int bank, int hash_offset,
    886                         int use_lsb)
    887 {
    888     uint32 hash_control_entry[4];
    889     soc_mem_t shared_mem = INVALIDm;
    890     soc_field_t field;
    891     int is_shared = 1;
    892 
    893     static const soc_field_t uft_fields_d[] = {
    894         HASH_OFFSET_DEDICATED_BANK_0f, HASH_OFFSET_DEDICATED_BANK_1f,
    895         HASH_OFFSET_DEDICATED_BANK_2f, HASH_OFFSET_DEDICATED_BANK_3f
    896 
    897     };
    898     static const soc_field_t uft_fields_s[] = {
    899         B0_HASH_OFFSETf, B1_HASH_OFFSETf, B2_HASH_OFFSETf, B3_HASH_OFFSETf
    900     };
    901 
    902 
    903     sal_memset(hash_control_entry, 0, sizeof(hash_control_entry));
    904 
    905     switch(mem) {
    906     case L2Xm:
    907         if (bank < 0 || bank > 1) {
    908             return SOC_E_PARAM;
    909         }
    910         mem = L2_ENTRY_HASH_CONTROLm;
    911         field = uft_fields_d[bank];
    912         is_shared = 0;
    913         break;
    914     case EXACT_MATCH_2m:
    915     case EXACT_MATCH_4m:
    916         if (bank < 0 || bank > 3) {
    917             return SOC_E_PARAM;
    918         }
    919         mem = EXACT_MATCH_HASH_CONTROLm;
    920         shared_mem = UFT_SHARED_BANKS_CONTROLm;
    921         field = uft_fields_s[bank];
    922         break;
    923     case L3_TUNNEL_SINGLEm:
    924     case L3_TUNNEL_DOUBLEm:
    925     case L3_TUNNEL_QUADm:
    926         if (bank < 0 || bank > 3) {
    927             return SOC_E_PARAM;
    928         }
    929         mem = L3_TUNNEL_HASH_CONTROLm;
    930         field = uft_fields_d[bank];
    931         is_shared = 0;
    932         break;
    933     case L3_ENTRY_SINGLEm:
    934     case L3_ENTRY_DOUBLEm:
    935     case L3_ENTRY_QUADm:
    936     case L3_ENTRY_ONLYm:
    937     case L3_ENTRY_ONLY_SINGLEm:
    938         if (bank < 0 || bank > 3) {
    939             return SOC_E_PARAM;
    940         }
    941         mem = L3_ENTRY_HASH_CONTROLm;
    942         is_shared = 0;
    943         field = uft_fields_d[bank];
    944         break;
    945     case MPLS_ENTRY_SINGLEm:
    946         if (bank < 0 || bank > 1) {
    947             return SOC_E_PARAM;
    948         }
    949         mem = MPLS_ENTRY_HASH_CONTROLm;
    950         is_shared = 0;
    951         field = uft_fields_d[bank];
    952         break;
    953     default:
    954         return SOC_E_INTERNAL;
    955     }
    956 
    957     /* Shared Banks */
    958     if (is_shared > 0) {
    959         SOC_IF_ERROR_RETURN(soc_mem_read(unit, shared_mem, MEM_BLOCK_ALL, 0,
    960                                          hash_control_entry));
    961         soc_mem_field32_set(unit, shared_mem, hash_control_entry, field, hash_offset);
    962         SOC_IF_ERROR_RETURN(
    963             soc_mem_write(unit, shared_mem, MEM_BLOCK_ALL, 0, hash_control_entry));
    964     } else {
    965         SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 0,
    966                                          hash_control_entry));
    967         soc_mem_field32_set(unit, mem, hash_control_entry, HASH_TABLE_TEST_MODEf,
    968                         use_lsb);
    969         soc_mem_field32_set(unit, mem, hash_control_entry, field, hash_offset);
    970         SOC_IF_ERROR_RETURN(
    971             soc_mem_write(unit, mem, MEM_BLOCK_ALL, 0, hash_control_entry));
    972     }
    973 
    974     return SOC_E_NONE;
    975 }
    976 
    977 
    978 int
    979 soc_tomahawk3_hash_index_get(int unit, int mem, int bank, int bucket)
    980 {
    981     int rv;
    982     int index = 0;
    983     int entries_per_row, bank_base, bucket_offset, entries_per_bucket;
    984 
    985     switch(mem) {
    986     case MPLS_ENTRY_SINGLEm:
    987         rv = soc_tomahawk3_hash_bank_info_get(unit, mem, bank, NULL,
    988                                         NULL, &entries_per_bucket,
    989                                         &bank_base, &bucket_offset);
    990         if (SOC_SUCCESS(rv)) {
    991             index = bank_base + bucket * entries_per_bucket + bucket_offset;
    992         }
    993         break;
    994 
    995     default:
    996         rv = soc_tomahawk3_hash_bank_info_get(unit, mem, bank, NULL,
    997                                         &entries_per_row, NULL, &bank_base,
    998                                         &bucket_offset);
    999         if (SOC_SUCCESS(rv)) {
   1000             index = bank_base + bucket * entries_per_row + bucket_offset;
   1001             return index;
   1002         }
   1003         break;
   1004     }
   1005 
   1006     return index;
   1007 }
   1008 
   1009 
   1010 uint32
   1011 soc_tomahawk3_l2x_hash(int unit, int bank, int hash_offset, int use_lsb,
   1012                 int key_nbits, void *base_entry, uint8 *key1, uint8 *key2)
   1013 {
   1014     uint16 lsb_val;
   1015     uint32 hash_mask = 0x03FF; /* 1k buckets per dedicated L2 bank */
   1016     uint32 hash_bits = 10;
   1017 
   1018     if (use_lsb && (hash_offset + hash_bits > 32)) {
   1019         switch (soc_mem_field32_get(unit, L2Xm, base_entry, KEY_TYPEf)) {
   1020         case TH3_L2_HASH_KEY_TYPE_BRIDGE:
   1021             lsb_val =
   1022                 soc_mem_field32_get(unit, L2Xm, base_entry, L2__HASH_LSBf);
   1023             break;
   1024         default:
   1025             lsb_val = 0;
   1026             break;
   1027         }
   1028     } else {
   1029         lsb_val = 0;
   1030     }
   1031 
   1032     return _soc_tomahawk3_shared_hash(unit,
   1033             hash_offset, key_nbits, key1, key2, hash_mask, lsb_val, use_lsb);
   1034 }
   1035 
   1036 int
   1037 soc_tomahawk3_l2x_base_entry_to_key(int unit, int bank, uint32 *entry, uint8 *key)
   1038 {
   1039     soc_field_t field_list[2];
   1040 
   1041     switch (soc_mem_field32_get(unit, L2Xm, entry, KEY_TYPEf)) {
   1042     case TH3_L2_HASH_KEY_TYPE_BRIDGE:
   1043         field_list[0] = L2__KEYf;
   1044         break;
   1045     case TH3_L2_HASH_KEY_TYPE_SINGLE_CROSS_CONNECT:
   1046         field_list[0] = VLAN__KEYf;
   1047         break;
   1048     default:
   1049         return 0;
   1050     }
   1051     field_list[1] = INVALIDf;
   1052     return _soc_tomahawk3_hash_entry_to_key(unit, bank, entry, key, L2Xm, field_list);
   1053 }
   1054 
   1055 uint32
   1056 soc_tomahawk3_l2x_entry_hash(int unit, int bank, int hash_offset, int use_lsb,
   1057                        uint32 *entry)
   1058 {
   1059     int             key_nbits;
   1060     uint8           key1[SOC_MAX_MEM_WORDS * 4] = {0};
   1061     uint8           key2[SOC_MAX_MEM_WORDS * 4] = {0};
   1062 
   1063     key_nbits = soc_tomahawk3_l2x_base_entry_to_key(unit, 0, entry, key1);
   1064     key_nbits = soc_tomahawk3_l2x_base_entry_to_key(unit, 1, entry, key2);
   1065     return soc_tomahawk3_l2x_hash(
   1066         unit, bank, hash_offset, use_lsb, key_nbits, entry, key1, key2);
   1067 }
   1068 
   1069 uint32
   1070 soc_tomahawk3_l2x_bank_entry_hash(int unit, int bank, uint32 *entry)
   1071 {
   1072     int rv, hash_offset, use_lsb;
   1073 
   1074     rv = soc_tomahawk3_hash_offset_get(unit, L2Xm, bank, &hash_offset, &use_lsb);
   1075     if (SOC_FAILURE(rv)) {
   1076         return 0;
   1077     }
   1078 
   1079     return soc_tomahawk3_l2x_entry_hash(unit, bank, hash_offset, use_lsb, entry);
   1080 }
   1081 
   1082 int
   1083 soc_tomahawk3_hash_init(int unit)
   1084 {
   1085 #define KEY_ATTR_MEM_FIELD_CNT  5
   1086     int index;
   1087     int mem_idx, field_idx;
   1088     int shared_bank_offset = 0;
   1089     int num_fpem_banks = 0;
   1090     int num_dedicated_banks = 2;
   1091     int offset_base, offset_multiplier;
   1092     uint32 fields_val[KEY_ATTR_MEM_FIELD_CNT] = {0};
   1093     uint32 hash_control_entry[SOC_MAX_MEM_WORDS];
   1094     uft_shared_banks_control_entry_t shared_hash_control_entry;
   1095     static const soc_mem_t dedicated_bank_mem[][2] = {
   1096         { L2Xm,                 L2_ENTRY_HASH_CONTROLm },
   1097         { L3_ENTRY_SINGLEm,     L3_ENTRY_HASH_CONTROLm },
   1098         { MPLS_ENTRY_SINGLEm,   MPLS_ENTRY_HASH_CONTROLm },
   1099         { L3_TUNNEL_SINGLEm,    L3_TUNNEL_HASH_CONTROLm }
   1100     };
   1101     static const soc_field_t logical_to_physical_fields[] = {
   1102         LOGICAL_BANK_0_PHYSICAL_BANK_LOCATIONf,
   1103         LOGICAL_BANK_1_PHYSICAL_BANK_LOCATIONf,
   1104         LOGICAL_BANK_2_PHYSICAL_BANK_LOCATIONf,
   1105         LOGICAL_BANK_3_PHYSICAL_BANK_LOCATIONf
   1106     };
   1107     static const soc_field_t dedicated_fields[] = {
   1108         HASH_OFFSET_DEDICATED_BANK_0f, HASH_OFFSET_DEDICATED_BANK_1f,
   1109         HASH_OFFSET_DEDICATED_BANK_2f, HASH_OFFSET_DEDICATED_BANK_3f
   1110     };
   1111     static const soc_field_t shared_fields[] = {
   1112         B0_HASH_OFFSETf, B1_HASH_OFFSETf, B2_HASH_OFFSETf, B3_HASH_OFFSETf,
   1113         B4_HASH_OFFSETf, B5_HASH_OFFSETf, B6_HASH_OFFSETf, B7_HASH_OFFSETf
   1114     };
   1115 
   1116     /*            PARAMETERS FOR <xyz>_KEY_ATTRIBUTE MEMORY
   1117      *
   1118      * NOTE: 1) Each supported KEY_TYPE for the mem should have one entry.
   1119      *       2) All entries to the array should be sequential in terms of
   1120      *          the KEY_TYPE value, i.e. if a memory supports 2 keys with
   1121      *          values 0 and 2 then add three entries to the table with 2nd
   1122      *          entry as all 0's and comment as 'Not Supported'. See
   1123      *          l3_key_type_attr below as an example.
   1124      *       3) If a new KEY TYPE is defined later, please add an entry below
   1125      *
   1126      * The below defined <XYZ>_key_type_attr array declares the values
   1127      * for these five fields from the respective KEY_ATTRIBUTE memory,
   1128      * { BUCKET |KEY   |KEY       |DATA      |HASH      }
   1129      * { MODE   |WIDTH |BASEWIDTH |BASEWIDTH |LSBOFFSET }
   1130      */
   1131     static const uint8 l2x_key_type_attr[][KEY_ATTR_MEM_FIELD_CNT] = {
   1132        { 0      ,15    ,0         ,0         ,0 }, /* BRIDGE */
   1133        { 0      ,6     ,0         ,0         ,0 }  /* SINGLE X CONNECT VLAN */
   1134     };
   1135     static const uint8 l3_key_type_attr[][KEY_ATTR_MEM_FIELD_CNT] = {
   1136        { 0      ,11    ,0         ,1         ,0 }, /* IPV4UC */
   1137        { 0      ,0     ,0         ,0         ,0 }, /* Not Supported */
   1138        { 0      ,15    ,1         ,2         ,0 }, /* IPV6UC */
   1139        { 0      ,0     ,0         ,0         ,0 }, /* Not Supported */
   1140        { 0      ,22    ,0         ,1         ,0 }, /* IPV4MC */
   1141        { 0      ,23    ,2         ,1         ,0 }  /* IPV6MC */
   1142     };
   1143     static const uint8 mpls_key_type_attr[][KEY_ATTR_MEM_FIELD_CNT] = {
   1144        { 0      ,7     ,0         ,0         ,0 }  /* MPLS */
   1145     };
   1146     static const uint8 tunnel_key_type_attr[][KEY_ATTR_MEM_FIELD_CNT] = {
   1147        { 0      ,7     ,0         ,0         ,0 }, /* MPLS */
   1148        { 0      ,3     ,1         ,0         ,0 }, /* IPV4 */
   1149        { 0      ,7     ,3         ,0         ,0 }  /* IPv6 */
   1150     };
   1151     static const uint8 fpem_key_type_attr[][KEY_ATTR_MEM_FIELD_CNT] = {
   1152        { 0      ,3     ,1         ,0         ,0 }, /* MODE128 */
   1153        { 0      ,11    ,1         ,0         ,0 }, /* MODE160 */
   1154        { 0      ,21    ,2         ,1         ,0 }  /* MODE320 */
   1155     };
   1156     static const struct key_type_attr_mem_mappings_s {
   1157         soc_mem_t   mem;          /* Key Attribut Memory */
   1158         int         key_cnt;      /* KeyType Max count from the enums */
   1159         const uint8 (*map)[KEY_ATTR_MEM_FIELD_CNT]; /* key attr fields vals */
   1160     } key_attr_map[] = {
   1161         {   L2_ENTRY_KEY_ATTRIBUTESm,
   1162                 TH3_L2_HASH_KEY_TYPE_COUNT, l2x_key_type_attr          },
   1163         {   L3_ENTRY_KEY_ATTRIBUTESm,
   1164                 TH3_L3_HASH_KEY_TYPE_COUNT, l3_key_type_attr           },
   1165         {   MPLS_ENTRY_KEY_ATTRIBUTESm,
   1166                 TH3_MPLS_HASH_KEY_TYPE_COUNT, mpls_key_type_attr       },
   1167         {   L3_TUNNEL_KEY_ATTRIBUTESm,
   1168                 TH3_TUNNEL_HASH_KEY_TYPE_COUNT, tunnel_key_type_attr   },
   1169         {   EXACT_MATCH_KEY_ATTRIBUTESm,
   1170                 TH3_FPEM_HASH_KEY_TYPE_COUNT, fpem_key_type_attr       }
   1171     };
   1172     soc_field_t key_attr_mem_fields[KEY_ATTR_MEM_FIELD_CNT] = {
   1173         BUCKET_MODEf,
   1174         KEY_WIDTHf,
   1175         KEY_BASE_WIDTHf,
   1176         DATA_BASE_WIDTHf,
   1177         HASH_LSB_OFFSETf
   1178     };
   1179 
   1180 #if 0
   1181     
   1182     if (soc_mem_index_count(unit, L3_DEFIP_ALPM_IPV4m)) {
   1183         int non_alpm = num_fpem_banks + num_l3_banks +
   1184                        num_l2_banks - 2 * (num_dedicated_banks);
   1185         sal_memset(hash_control_entry, 0,
   1186                     sizeof(uft_shared_banks_control_entry_t));
   1187         SOC_IF_ERROR_RETURN
   1188         (READ_UFT_SHARED_BANKS_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   1189                                              hash_control_entry));
   1190         if ((non_alpm) && (non_alpm <= 4)) {
   1191             /* If Shared banks are used between ALPM and non-ALPM memories,
   1192              * then ALPM uses Shared Bank B2, B3, B4, B5 and non-ALPM uses
   1193              * B6, B7, B8, B9 banks
   1194              */
   1195             soc_mem_field32_set(unit, UFT_SHARED_BANKS_CONTROLm,
   1196                                  hash_control_entry, ALPM_MODEf, 1);
   1197             num_shared_alpm_banks[unit] = 4;
   1198             shared_bank_offset += 4;
   1199         } else {
   1200             soc_mem_field32_set(unit, UFT_SHARED_BANKS_CONTROLm,
   1201                                  hash_control_entry, ALPM_MODEf, 0);
   1202             num_shared_alpm_banks[unit] = 8;
   1203         }
   1204         SOC_IF_ERROR_RETURN
   1205         (WRITE_UFT_SHARED_BANKS_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   1206                                              hash_control_entry));
   1207     }
   1208 #endif
   1209 
   1210     /* Program the hash memories which has dedicated banks */
   1211     for (mem_idx = 0 ; mem_idx < COUNTOF(dedicated_bank_mem) ; mem_idx++) {
   1212         sal_memset(hash_control_entry, 0, sizeof(hash_control_entry));
   1213         SOC_IF_ERROR_RETURN(
   1214             soc_tomahawk3_hash_bank_count_get(
   1215                 unit, dedicated_bank_mem[mem_idx][0], &num_dedicated_banks));
   1216 
   1217         offset_multiplier = 64 / num_dedicated_banks;
   1218         offset_base = 64 % num_dedicated_banks;
   1219 
   1220         SOC_IF_ERROR_RETURN(
   1221             soc_mem_read(unit,
   1222                          dedicated_bank_mem[mem_idx][1],
   1223                          MEM_BLOCK_ANY, 0, hash_control_entry));
   1224         soc_mem_field32_set(
   1225             unit, dedicated_bank_mem[mem_idx][1], hash_control_entry,
   1226             HASH_TABLE_BANK_CONFIGf, ((1 << num_dedicated_banks) - 1));
   1227 
   1228         for (index = 0; index < num_dedicated_banks; index++) {
   1229             soc_mem_field32_set(
   1230                 unit, dedicated_bank_mem[mem_idx][1], hash_control_entry,
   1231                 dedicated_fields[index], offset_base+(index*offset_multiplier));
   1232         }
   1233         SOC_IF_ERROR_RETURN(
   1234             soc_mem_write(unit,
   1235                             dedicated_bank_mem[mem_idx][1],
   1236                             MEM_BLOCK_ALL, 0, hash_control_entry));
   1237     }
   1238 
   1239     /* Program the hash memories which has shared banks */
   1240     sal_memset(hash_control_entry, 0, sizeof(exact_match_hash_control_entry_t));
   1241     sal_memset(&shared_hash_control_entry, 0,
   1242                 sizeof(uft_shared_banks_control_entry_t));
   1243     SOC_IF_ERROR_RETURN
   1244         (READ_EXACT_MATCH_HASH_CONTROLm(
   1245             unit, MEM_BLOCK_ANY, 0, hash_control_entry));
   1246     SOC_IF_ERROR_RETURN
   1247         (READ_UFT_SHARED_BANKS_CONTROLm(
   1248             unit, MEM_BLOCK_ANY, 0, &shared_hash_control_entry));
   1249     SOC_IF_ERROR_RETURN
   1250         (soc_tomahawk3_hash_bank_count_get(
   1251             unit, EXACT_MATCH_2m, &num_fpem_banks));
   1252 
   1253     soc_mem_field32_set(unit, EXACT_MATCH_HASH_CONTROLm, hash_control_entry,
   1254                       HASH_TABLE_BANK_CONFIGf,
   1255                       ((1 << num_fpem_banks) - 1) << shared_bank_offset);
   1256     /* Handle case where fpem banks are set to 0 */
   1257     if (num_fpem_banks) {
   1258         offset_multiplier = 64 / num_fpem_banks;
   1259         offset_base = 64 % num_fpem_banks;
   1260     }
   1261     for (index = 0 ; index < num_fpem_banks; index++) {
   1262         soc_mem_field32_set(unit, EXACT_MATCH_HASH_CONTROLm , hash_control_entry,
   1263                           logical_to_physical_fields[index], index +
   1264                           shared_bank_offset);
   1265         soc_mem_field32_set(unit, UFT_SHARED_BANKS_CONTROLm,
   1266                             &shared_hash_control_entry,
   1267                             shared_fields[shared_bank_offset + index],
   1268                             offset_base + (index * offset_multiplier));
   1269     }
   1270 
   1271     SOC_IF_ERROR_RETURN
   1272         (WRITE_EXACT_MATCH_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   1273                                             hash_control_entry));
   1274     SOC_IF_ERROR_RETURN
   1275         (WRITE_UFT_SHARED_BANKS_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   1276                                         &shared_hash_control_entry));
   1277 
   1278     /* Program the KEY_ATTRIBUTE memories */
   1279     for (mem_idx = 0 ; mem_idx < COUNTOF(key_attr_map) ; mem_idx++) {
   1280         /* Clear the memory to begin-with */
   1281         
   1282 
   1283         /* Write the relevant entries in it */
   1284         for (index = 0 ; index < key_attr_map[mem_idx].key_cnt ; index++) {
   1285             for (field_idx=0 ; field_idx<KEY_ATTR_MEM_FIELD_CNT ; field_idx++) {
   1286                 fields_val[field_idx] =
   1287                     (key_attr_map[mem_idx].map)[index][field_idx];
   1288             }
   1289             SOC_IF_ERROR_RETURN(
   1290                 soc_mem_fields32_modify(unit, key_attr_map[mem_idx].mem, index,
   1291                       KEY_ATTR_MEM_FIELD_CNT, key_attr_mem_fields, fields_val));
   1292         }
   1293     }
   1294 #undef KEY_ATTR_MEM_FIELD_CNT
   1295 
   1296 /* Robust Hash initialization */
   1297 #ifdef SOC_ROBUST_HASH
   1298 
   1299     /* Initialize Robust Hash Global Datastructure */
   1300     if (soc_feature(unit, soc_feature_robust_hash)) {
   1301         uint32 seed = 0;
   1302         uint32 hash_control_entry[4];
   1303 
   1304         if (NULL == ROBUSTHASH(unit)) {
   1305             ROBUSTHASH(unit) = sal_alloc(sizeof(soc_robust_hash_db_t),
   1306                                          "soc_robust_hash");
   1307             if (ROBUSTHASH(unit) == NULL) {
   1308                 return SOC_E_MEMORY;
   1309             }
   1310             sal_memset(ROBUSTHASH(unit), 0, sizeof(soc_robust_hash_db_t));
   1311         }
   1312 
   1313         /* L2 Robust Hash Init */
   1314 
   1315         sal_memset(hash_control_entry, 0, sizeof(l2_entry_hash_control_entry_t));
   1316 
   1317         /* Disable robust hash for L2 - this config variable is used only
   1318          * for debug purposes*/
   1319         if ((soc_property_get(unit, "robust_hash_disable_l2", 0)) == 1) {
   1320             SOC_IF_ERROR_RETURN
   1321                 (READ_L2_ENTRY_HASH_CONTROLm
   1322                     (unit, MEM_BLOCK_ANY, 0, hash_control_entry));
   1323                 soc_mem_field32_set(unit, L2_ENTRY_HASH_CONTROLm ,
   1324                                     hash_control_entry, ROBUST_HASH_ENf, 0x0);
   1325             SOC_IF_ERROR_RETURN
   1326                 (WRITE_L2_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   1327                                                 hash_control_entry));
   1328             ROBUSTHASH(unit)->l2.enable = 0;
   1329         } else {
   1330             /* Enable robust hashing */
   1331             SOC_IF_ERROR_RETURN
   1332                 (READ_L2_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   1333                                              hash_control_entry));
   1334             soc_mem_field32_set(unit, L2_ENTRY_HASH_CONTROLm,
   1335                                 hash_control_entry, ROBUST_HASH_ENf, 0x1);
   1336             SOC_IF_ERROR_RETURN
   1337                 (WRITE_L2_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   1338                                                 hash_control_entry));
   1339             ROBUSTHASH(unit)->l2.enable = 1;
   1340 
   1341             /* Configure remap and action tables for L2 table */
   1342             ROBUSTHASH(unit)->l2.remap_tab[0] = L2_ENTRY_REMAP_TABLE_Am;
   1343             ROBUSTHASH(unit)->l2.remap_tab[1] = L2_ENTRY_REMAP_TABLE_Bm;
   1344             ROBUSTHASH(unit)->l2.action_tab[0] = L2_ENTRY_ACTION_TABLE_Am;
   1345             ROBUSTHASH(unit)->l2.action_tab[1] = L2_ENTRY_ACTION_TABLE_Bm;
   1346 
   1347             /* Initialize seed for robust hash */
   1348             seed = soc_property_get(unit, spn_ROBUST_HASH_SEED_L2, 16777213);
   1349 
   1350             SOC_IF_ERROR_RETURN
   1351                 (soc_robust_hash_table_set(unit,
   1352                                            &(ROBUSTHASH(unit)->l2),
   1353                                            seed));
   1354         }
   1355 
   1356         /* L3 Robust Hash Init */
   1357 
   1358         sal_memset(hash_control_entry, 0, sizeof(l3_entry_hash_control_entry_t));
   1359 
   1360         /* Disable robust hash for L3 - this config variable is used only
   1361          * for debug purposes*/
   1362         if ((soc_property_get(unit, "robust_hash_disable_l3", 0)) == 1) {
   1363             SOC_IF_ERROR_RETURN
   1364                 (READ_L3_ENTRY_HASH_CONTROLm
   1365                     (unit, MEM_BLOCK_ANY, 0, hash_control_entry));
   1366                 soc_mem_field32_set(unit, L3_ENTRY_HASH_CONTROLm ,
   1367                                     hash_control_entry, ROBUST_HASH_ENf, 0x0);
   1368             SOC_IF_ERROR_RETURN
   1369                 (WRITE_L3_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   1370                                                 hash_control_entry));
   1371             ROBUSTHASH(unit)->l3.enable = 0;
   1372         } else {
   1373             /* Enable robust hashing */
   1374             SOC_IF_ERROR_RETURN
   1375                 (READ_L3_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   1376                                              hash_control_entry));
   1377             soc_mem_field32_set(unit, L3_ENTRY_HASH_CONTROLm,
   1378                                 hash_control_entry, ROBUST_HASH_ENf, 0x1);
   1379             SOC_IF_ERROR_RETURN
   1380                 (WRITE_L3_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   1381                                                 hash_control_entry));
   1382             ROBUSTHASH(unit)->l3.enable = 1;
   1383 
   1384             /* Configure remap and action tables for L3 table */
   1385             ROBUSTHASH(unit)->l3.remap_tab[0] = L3_ENTRY_REMAP_TABLE_Am;
   1386             ROBUSTHASH(unit)->l3.remap_tab[1] = L3_ENTRY_REMAP_TABLE_Bm;
   1387             ROBUSTHASH(unit)->l3.action_tab[0] = L3_ENTRY_ACTION_TABLE_Am;
   1388             ROBUSTHASH(unit)->l3.action_tab[1] = L3_ENTRY_ACTION_TABLE_Bm;
   1389 
   1390             /* Initialize seed for robust hash */
   1391             seed = soc_property_get(unit, spn_ROBUST_HASH_SEED_L3, 16777213);
   1392 
   1393             SOC_IF_ERROR_RETURN
   1394                 (soc_robust_hash_table_set(unit,
   1395                                            &(ROBUSTHASH(unit)->l3),
   1396                                            seed));
   1397         }
   1398 
   1399         /* Exact Match Robust Hash Init */
   1400 
   1401         sal_memset
   1402             (hash_control_entry, 0, sizeof(exact_match_hash_control_entry_t));
   1403 
   1404         /* Disable robust hash for EM - this config variable is used only
   1405          * for debug purposes*/
   1406         if ((soc_property_get
   1407                 (unit, "robust_hash_disable_exact_match", 0)) == 1) {
   1408             SOC_IF_ERROR_RETURN
   1409                 (READ_EXACT_MATCH_HASH_CONTROLm
   1410                     (unit, MEM_BLOCK_ANY, 0, hash_control_entry));
   1411                 soc_mem_field32_set(unit, EXACT_MATCH_HASH_CONTROLm ,
   1412                                     hash_control_entry, ROBUST_HASH_ENf, 0x0);
   1413             SOC_IF_ERROR_RETURN
   1414                 (WRITE_EXACT_MATCH_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   1415                                                 hash_control_entry));
   1416             ROBUSTHASH(unit)->exact_match.enable = 0;
   1417         } else {
   1418             /* Enable robust hashing */
   1419             SOC_IF_ERROR_RETURN
   1420                 (READ_EXACT_MATCH_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   1421                                                 hash_control_entry));
   1422             soc_mem_field32_set(unit, EXACT_MATCH_HASH_CONTROLm,
   1423                                 hash_control_entry, ROBUST_HASH_ENf, 0x1);
   1424             SOC_IF_ERROR_RETURN
   1425                 (WRITE_EXACT_MATCH_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   1426                                                  hash_control_entry));
   1427             ROBUSTHASH(unit)->exact_match.enable = 1;
   1428 
   1429             /* Configure remap and action tables for EM table */
   1430             ROBUSTHASH(unit)->exact_match.remap_tab[0] = EXACT_MATCH_REMAP_TABLE_Am;
   1431             ROBUSTHASH(unit)->exact_match.remap_tab[1] = EXACT_MATCH_REMAP_TABLE_Bm;
   1432             ROBUSTHASH(unit)->exact_match.action_tab[0] = EXACT_MATCH_ACTION_TABLE_Am;
   1433             ROBUSTHASH(unit)->exact_match.action_tab[1] = EXACT_MATCH_ACTION_TABLE_Bm;
   1434 
   1435             /* Initialize seed for robust hash */
   1436             seed = soc_property_get
   1437                     (unit, spn_ROBUST_HASH_SEED_EXACT_MATCH, 16777213);
   1438 
   1439             SOC_IF_ERROR_RETURN
   1440                 (soc_robust_hash_table_set(unit,
   1441                                            &(ROBUSTHASH(unit)->exact_match),
   1442                                            seed));
   1443         }
   1444 
   1445         /* Mpls Robust Hash Init */
   1446 
   1447         sal_memset
   1448             (hash_control_entry, 0, sizeof(mpls_entry_hash_control_entry_t));
   1449 
   1450         /* Disable robust hash for mpls - this config variable is
   1451          * used only for debug purposes*/
   1452         if ((soc_property_get
   1453                 (unit, "robust_hash_disable_mpls", 0)) == 1) {
   1454             SOC_IF_ERROR_RETURN
   1455                 (READ_MPLS_ENTRY_HASH_CONTROLm
   1456                     (unit, MEM_BLOCK_ANY, 0, hash_control_entry));
   1457                 soc_mem_field32_set(unit, MPLS_ENTRY_HASH_CONTROLm ,
   1458                                     hash_control_entry, ROBUST_HASH_ENf, 0x0);
   1459             SOC_IF_ERROR_RETURN
   1460                 (WRITE_MPLS_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   1461                                                         hash_control_entry));
   1462             ROBUSTHASH(unit)->mpls_entry.enable = 0;
   1463         } else {
   1464             /* Enable robust hashing */
   1465             SOC_IF_ERROR_RETURN
   1466                 (READ_MPLS_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   1467                                                      hash_control_entry));
   1468             soc_mem_field32_set(unit, MPLS_ENTRY_HASH_CONTROLm,
   1469                                 hash_control_entry, ROBUST_HASH_ENf, 0x1);
   1470             SOC_IF_ERROR_RETURN
   1471                 (WRITE_MPLS_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   1472                                                       hash_control_entry));
   1473             ROBUSTHASH(unit)->mpls_entry.enable = 1;
   1474 
   1475             /* Configure remap and action tables for MPLS ENTRY table */
   1476             ROBUSTHASH(unit)->mpls_entry.remap_tab[0] =
   1477                                                 MPLS_ENTRY_REMAP_TABLE_Am;
   1478             ROBUSTHASH(unit)->mpls_entry.remap_tab[1] =
   1479                                                 MPLS_ENTRY_REMAP_TABLE_Bm;
   1480             ROBUSTHASH(unit)->mpls_entry.action_tab[0] =
   1481                                                 MPLS_ENTRY_ACTION_TABLE_Am;
   1482             ROBUSTHASH(unit)->mpls_entry.action_tab[1] =
   1483                                                 MPLS_ENTRY_ACTION_TABLE_Bm;
   1484 
   1485             /* Initialize seed for robust hash */
   1486             seed = soc_property_get
   1487                     (unit, spn_ROBUST_HASH_SEED_MPLS, 16777213);
   1488 
   1489             SOC_IF_ERROR_RETURN
   1490                 (soc_robust_hash_table_set(unit,
   1491                                            &(ROBUSTHASH(unit)->mpls_entry),
   1492                                            seed));
   1493         }
   1494 
   1495 
   1496         /* Tunnel Robust Hash Init */
   1497 
   1498         sal_memset
   1499             (hash_control_entry, 0, sizeof(tunnel_hash_control_entry_t));
   1500 
   1501         /* Disable robust hash for mpls - this config variable is
   1502          * used only for debug purposes*/
   1503         if ((soc_property_get
   1504                 (unit, "robust_hash_disable_mpls", 0)) == 1) {
   1505             SOC_IF_ERROR_RETURN
   1506                 (READ_L3_TUNNEL_HASH_CONTROLm
   1507                     (unit, MEM_BLOCK_ANY, 0, hash_control_entry));
   1508                 soc_mem_field32_set(unit, L3_TUNNEL_HASH_CONTROLm ,
   1509                                     hash_control_entry, ROBUST_HASH_ENf, 0x0);
   1510             SOC_IF_ERROR_RETURN
   1511                 (WRITE_L3_TUNNEL_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   1512                                                         hash_control_entry));
   1513             ROBUSTHASH(unit)->tunnel.enable = 0;
   1514         } else {
   1515             /* Enable robust hashing */
   1516             SOC_IF_ERROR_RETURN
   1517                 (READ_L3_TUNNEL_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0,
   1518                                                      hash_control_entry));
   1519             soc_mem_field32_set(unit, L3_TUNNEL_HASH_CONTROLm,
   1520                                 hash_control_entry, ROBUST_HASH_ENf, 0x1);
   1521             SOC_IF_ERROR_RETURN
   1522                 (WRITE_L3_TUNNEL_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0,
   1523                                                       hash_control_entry));
   1524             ROBUSTHASH(unit)->tunnel.enable = 1;
   1525 
   1526             /* Configure remap and action tables for L3_TUNNEL ENTRY table */
   1527             ROBUSTHASH(unit)->tunnel.remap_tab[0] =
   1528                                                 L3_TUNNEL_REMAP_TABLE_Am;
   1529             ROBUSTHASH(unit)->tunnel.remap_tab[1] =
   1530                                                 L3_TUNNEL_REMAP_TABLE_Bm;
   1531             ROBUSTHASH(unit)->tunnel.action_tab[0] =
   1532                                                 L3_TUNNEL_ACTION_TABLE_Am;
   1533             ROBUSTHASH(unit)->tunnel.action_tab[1] =
   1534                                                 L3_TUNNEL_ACTION_TABLE_Bm;
   1535 
   1536             /* Initialize seed for robust hash */
   1537             seed = soc_property_get
   1538                     (unit, spn_ROBUST_HASH_SEED_L3_TUNNEL, 16777213);
   1539 
   1540             SOC_IF_ERROR_RETURN
   1541                 (soc_robust_hash_table_set(unit,
   1542                                            &(ROBUSTHASH(unit)->tunnel),
   1543                                            seed));
   1544         }
   1545 
   1546 
   1547 
   1548     }
   1549 #endif /* SOC_ROBUST_HASH */
   1550 
   1551     return SOC_E_NONE;
   1552 }
   1553 
   1554 int
   1555 soc_tomahawk3_shared_hash_mem_bucket_read(int unit, int ent, int entry_width, int *width,
   1556                                     soc_mem_t base_mem, soc_mem_t *mem,
   1557                                     void *bkt_entry, void *entry)
   1558 {
   1559 
   1560     soc_mem_info_t meminfo;
   1561     soc_field_info_t fieldinfo;
   1562     /* Exclude HIT bit */
   1563     int entry_bits = 0, hit_bits=0;
   1564 
   1565     if (entry_width <= 0) {
   1566         return (SOC_E_PARAM);
   1567     }
   1568 
   1569     switch (base_mem) {
   1570     case L3_ENTRY_SINGLEm:
   1571     case L3_ENTRY_ONLY_SINGLEm:
   1572     case L3_ENTRY_DOUBLEm:
   1573     case L3_ENTRY_QUADm:
   1574         switch (entry_width) {
   1575         case 1:  /* 1 base_entry wide */
   1576             *width = 1;
   1577             *mem = L3_ENTRY_SINGLEm;
   1578             break;
   1579         case 2:  /* 2 base entries wide */
   1580             *width = 2;
   1581             *mem = L3_ENTRY_DOUBLEm;
   1582             break;
   1583         default:
   1584             *width = 4; /* 4 base_entries wide */
   1585             *mem = L3_ENTRY_QUADm;
   1586         }
   1587         hit_bits = *width;
   1588         break;
   1589 
   1590     case EXACT_MATCH_2m:
   1591     case EXACT_MATCH_4m:
   1592         switch (entry_width) {
   1593             case 2:
   1594                 *width = 1;
   1595                 *mem = EXACT_MATCH_2m;
   1596                 break;
   1597             case 4:
   1598             default:
   1599                 *width = 2;
   1600                 *mem = EXACT_MATCH_4m;
   1601         }
   1602         break;
   1603 
   1604     case MPLS_ENTRY_SINGLEm:
   1605         *width = 1;
   1606         *mem = MPLS_ENTRY_SINGLEm;
   1607         break;
   1608 
   1609     case L3_TUNNEL_SINGLEm:
   1610     case L3_TUNNEL_DOUBLEm:
   1611     case L3_TUNNEL_QUADm:
   1612         switch (entry_width) {
   1613         case 1:  /* 1 base_entry wide */
   1614             *width = 1;
   1615             *mem = L3_TUNNEL_SINGLEm;
   1616             break;
   1617         case 2:  /* 2 base entries wide */
   1618             *width = 2;
   1619             *mem = L3_TUNNEL_DOUBLEm;
   1620             break;
   1621         default:
   1622             *width = 4; /* 4 base_entries wide */
   1623             *mem = L3_TUNNEL_QUADm;
   1624         }
   1625         break;
   1626 
   1627     default:
   1628         return SOC_E_PARAM;
   1629     }
   1630 
   1631     entry_bits = soc_mem_entry_bits(unit, *mem) - hit_bits;
   1632 
   1633     meminfo.flags = 0;
   1634     meminfo.bytes = SOC_MEM_WORDS(unit, base_mem) * 4;
   1635     fieldinfo.flags = SOCF_LE;
   1636     fieldinfo.len = entry_bits;
   1637 
   1638     fieldinfo.bp =  entry_bits * (ent/entry_width);
   1639     (void)soc_meminfo_fieldinfo_field_get(bkt_entry, &meminfo,
   1640                                           &fieldinfo, entry);
   1641 
   1642     return SOC_E_NONE;
   1643 
   1644 }
   1645 
   1646 
   1647 int
   1648 soc_tomahawk3_hash_mem_status_get(int unit, soc_mem_t mem, void* entry, uint32 *v) {
   1649     int i;
   1650     v[0] = v[1] = v[2] = v[3] = 0;
   1651 
   1652     switch (mem) {
   1653     case L3_ENTRY_QUADm:
   1654     case L3_TUNNEL_QUADm:
   1655     case EXACT_MATCH_4m:
   1656         soc_mem_field_get(unit, mem, entry, BASE_VALID_3f, &v[3]);
   1657         soc_mem_field_get(unit, mem, entry, BASE_VALID_2f, &v[2]);
   1658         /* pass through */
   1659     case L3_ENTRY_DOUBLEm:
   1660     case L3_TUNNEL_DOUBLEm:
   1661     case EXACT_MATCH_2m:
   1662         soc_mem_field_get(unit, mem, entry, BASE_VALID_1f, &v[1]);
   1663         soc_mem_field_get(unit, mem, entry, BASE_VALID_0f, &v[0]);
   1664         break;
   1665     case L3_ENTRY_SINGLEm:
   1666     case L3_TUNNEL_SINGLEm:
   1667     case L3_ENTRY_ONLY_SINGLEm:
   1668     case MPLS_ENTRY_SINGLEm:
   1669         soc_mem_field_get(unit, mem, entry, BASE_VALIDf, &v[0]);
   1670         break;
   1671     default:
   1672         v[0] = v[1] = v[2] = v[3] = 1;
   1673         break;
   1674 
   1675     }
   1676     /* Use v[i] for constructing a valid bitmap */
   1677     for (i = 0; i < 4; i++) {
   1678         v[i] = (v[i] > 0);
   1679     }
   1680     return SOC_E_NONE;
   1681 }
   1682 
   1683 
   1684 /* Get bank bitmap for the hash table
   1685  * Required only for shared hash tables
   1686  */
   1687 int
   1688 soc_tomahawk3_hash_bank_phy_bitmap_get(int unit, soc_mem_t mem, uint32 *bitmap)
   1689 {
   1690     uint32 hash_control_entry[4];
   1691     switch(mem) {
   1692     case L2Xm:
   1693         mem = L2_ENTRY_HASH_CONTROLm;
   1694         break;
   1695     case L3_ENTRY_SINGLEm:
   1696     case L3_ENTRY_ONLY_SINGLEm:
   1697     case L3_ENTRY_DOUBLEm:
   1698     case L3_ENTRY_ONLY_DOUBLEm:
   1699     case L3_ENTRY_QUADm:
   1700     case L3_ENTRY_ONLY_QUADm:
   1701         mem = L3_ENTRY_HASH_CONTROLm;
   1702         break;
   1703     case EXACT_MATCH_2m:
   1704     case EXACT_MATCH_4m:
   1705         mem = EXACT_MATCH_HASH_CONTROLm;
   1706         break;
   1707     case MPLS_ENTRY_SINGLEm:
   1708         mem = MPLS_ENTRY_HASH_CONTROLm;
   1709         break;
   1710     case L3_TUNNEL_SINGLEm:
   1711     case L3_TUNNEL_DOUBLEm:
   1712     case L3_TUNNEL_QUADm:
   1713         mem = L3_TUNNEL_HASH_CONTROLm;
   1714         break;
   1715     default:
   1716         return SOC_E_PARAM;
   1717     }
   1718 
   1719     SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ALL, 0,
   1720                                      hash_control_entry));
   1721     *bitmap = soc_mem_field32_get(unit, mem, hash_control_entry,
   1722                                   HASH_TABLE_BANK_CONFIGf);
   1723 
   1724     return SOC_E_NONE;
   1725 }
   1726 
   1727 uint32
   1728 soc_tomahawk3_l3x_hash(int unit, int bank, int hash_offset, int use_lsb,
   1729                  int key_nbits, void *base_entry, uint8 *key1, uint8 *key2)
   1730 {
   1731     uint32 lsb_val;
   1732     uint32 hash_mask;
   1733     uint32 hash_bits;
   1734 
   1735      hash_mask = 0x3FF; /* 1k buckets per dedicated banks */
   1736      hash_bits = 10;
   1737 
   1738 
   1739     if (use_lsb && (hash_offset + hash_bits > 32)) {
   1740         switch (soc_mem_field32_get(unit, L3_ENTRY_SINGLEm, base_entry,
   1741                                     KEY_TYPEf)) {
   1742         case TH3_L3_HASH_KEY_TYPE_V4UC:
   1743         case TH3_L3_HASH_KEY_TYPE_V4MC:
   1744         case TH3_L3_HASH_KEY_TYPE_V6UC:
   1745         case TH3_L3_HASH_KEY_TYPE_V6MC:
   1746             lsb_val = soc_mem_field32_get(unit, L3_ENTRY_SINGLEm,
   1747                                           base_entry, IPV4UC__HASH_LSBf);
   1748             break;
   1749         default:
   1750             lsb_val = 0;
   1751             break;
   1752         }
   1753     } else {
   1754         lsb_val = 0;
   1755     }
   1756 
   1757     return _soc_tomahawk3_shared_hash(unit, hash_offset, key_nbits, key1, key2,
   1758                                 hash_mask, lsb_val, use_lsb);
   1759 }
   1760 
   1761 int
   1762 soc_tomahawk3_l3x_base_entry_to_key(int unit, int bank, uint32 *entry, uint8 *key)
   1763 {
   1764     soc_mem_t mem;
   1765     soc_field_t field_list[5];
   1766 
   1767     switch (soc_mem_field32_get(unit, L3_ENTRY_SINGLEm, entry, KEY_TYPEf)) {
   1768     case TH3_L3_HASH_KEY_TYPE_V4UC:
   1769         mem = L3_ENTRY_SINGLEm;
   1770         field_list[0] = IPV4UC__KEYf;
   1771         field_list[1] = INVALIDf;
   1772         break;
   1773     case TH3_L3_HASH_KEY_TYPE_V6UC:
   1774         mem = L3_ENTRY_DOUBLEm;
   1775         field_list[0] = IPV6UC__KEY_0f;
   1776         field_list[1] = IPV6UC__KEY_1f;
   1777         field_list[2] = INVALIDf;
   1778         break;
   1779     case TH3_L3_HASH_KEY_TYPE_V4MC:
   1780         mem = L3_ENTRY_DOUBLEm;
   1781         field_list[0] = IPV4MC__KEYf;
   1782         field_list[1] = INVALIDf;
   1783         break;
   1784     case TH3_L3_HASH_KEY_TYPE_V6MC:
   1785         mem = L3_ENTRY_QUADm;
   1786         field_list[0] = IPV6MC__KEY_0f;
   1787         field_list[1] = IPV6MC__KEY_1f;
   1788         field_list[2] = IPV6MC__KEY_2f;
   1789         field_list[3] = INVALIDf;
   1790         break;
   1791 
   1792     default:
   1793         return 0;
   1794     }
   1795     return _soc_tomahawk3_hash_entry_to_key(unit, bank, entry, key, mem, field_list);
   1796 }
   1797 
   1798 uint32
   1799 soc_tomahawk3_l3x_entry_hash(int unit, int bank, int hash_offset, int use_lsb,
   1800                       uint32 *entry)
   1801 {
   1802     int             key_nbits;
   1803     uint8           key1[SOC_MAX_MEM_WORDS * 4] = {0};
   1804     uint8           key2[SOC_MAX_MEM_WORDS * 4] = {0};
   1805 
   1806     /* Robust Hashed Key using Remap and Action Tables A */
   1807     key_nbits = soc_tomahawk3_l3x_base_entry_to_key(unit, 0, entry, key1);
   1808     /* Robust Hashed Key using Remap and Action Tables B */
   1809     key_nbits = soc_tomahawk3_l3x_base_entry_to_key(unit, 1, entry, key2);
   1810 
   1811     return soc_tomahawk3_l3x_hash(unit, bank, hash_offset, use_lsb, key_nbits,
   1812                             entry, key1, key2);
   1813 }
   1814 
   1815 uint32
   1816 soc_tomahawk3_l3x_bank_entry_hash(int unit, int bank, uint32 *entry)
   1817 {
   1818     int rv, hash_offset, use_lsb;
   1819 
   1820     rv = soc_tomahawk3_hash_offset_get(unit, L3_ENTRY_SINGLEm, bank, &hash_offset,
   1821                                 &use_lsb);
   1822     if (SOC_FAILURE(rv)) {
   1823         return 0;
   1824     }
   1825 
   1826     return soc_tomahawk3_l3x_entry_hash(unit, bank, hash_offset, use_lsb, entry);
   1827 }
   1828 
   1829 uint32
   1830 soc_tomahawk3_exact_match_bank_entry_hash(int unit, int bank, uint32 *entry)
   1831 {
   1832     int rv, hash_offset, use_lsb;
   1833 
   1834     rv = soc_tomahawk3_hash_offset_get(unit, EXACT_MATCH_2m, bank, &hash_offset,
   1835                                  &use_lsb);
   1836     if (SOC_FAILURE(rv)) {
   1837         return 0;
   1838     }
   1839 
   1840     return soc_tomahawk3_exact_match_entry_hash(unit, bank, hash_offset, use_lsb,
   1841                                           entry);
   1842 }
   1843 
   1844 int
   1845 soc_tomahawk3_hash_bucket_get(int unit, int mem, int bank, uint32 *entry,
   1846                         uint32 *bucket)
   1847 {
   1848     /* The bits in the indexes cannot be limited as TH3 operates in BM0 */
   1849     switch (mem) {
   1850     case L2Xm:
   1851         *bucket = soc_tomahawk3_l2x_bank_entry_hash(unit, bank, entry);
   1852         break;
   1853     case L3_ENTRY_ONLY_SINGLEm:
   1854     case L3_ENTRY_SINGLEm:
   1855     case L3_ENTRY_DOUBLEm:
   1856     case L3_ENTRY_QUADm:
   1857         *bucket = soc_tomahawk3_l3x_bank_entry_hash(unit, bank, entry);
   1858         break;
   1859     case EXACT_MATCH_2m:
   1860     case EXACT_MATCH_4m:
   1861         *bucket = soc_tomahawk3_exact_match_bank_entry_hash(unit, bank, entry);
   1862         break;
   1863     case MPLS_ENTRY_SINGLEm:
   1864         *bucket = soc_tomahawk3_mpls_bank_entry_hash(unit, bank, entry);
   1865         break;
   1866     case L3_TUNNEL_SINGLEm:
   1867     case L3_TUNNEL_DOUBLEm:
   1868     case L3_TUNNEL_QUADm:
   1869         *bucket = soc_tomahawk3_tunnel_bank_entry_hash(unit, bank, entry);
   1870         break;
   1871     default:
   1872         return SOC_E_PARAM;
   1873     }
   1874     return SOC_E_NONE;
   1875 }
   1876 
   1877 
   1878 
   1879 int
   1880 soc_tomahawk3_tbl_entries_per_sram_entry_get(int unit, soc_mem_t mem,
   1881                        int *table_entries_per_sram_entry)
   1882 {
   1883     switch (mem) {
   1884     case L2Xm:
   1885     case L2_ENTRY_SINGLEm:
   1886     case L2_ENTRY_ONLY_SINGLEm:
   1887     case L3_ENTRY_SINGLEm:
   1888     case L3_TUNNEL_SINGLEm:
   1889     case L3_ENTRY_ONLY_SINGLEm:
   1890          *table_entries_per_sram_entry = 4;
   1891          break;
   1892 
   1893     case L3_ENTRY_DOUBLEm:
   1894     case L3_TUNNEL_DOUBLEm:
   1895     case EXACT_MATCH_2m:
   1896          *table_entries_per_sram_entry = 2;
   1897          break;
   1898 
   1899     case L3_ENTRY_QUADm:
   1900     case L3_TUNNEL_QUADm:
   1901     case EXACT_MATCH_4m:
   1902          *table_entries_per_sram_entry = 1;
   1903          break;
   1904 
   1905     case MPLS_ENTRY_SINGLEm:
   1906          *table_entries_per_sram_entry = 1;
   1907          break;
   1908 
   1909     default:
   1910         return SOC_E_PARAM;
   1911     }
   1912 
   1913     return SOC_E_NONE;
   1914 }
   1915 #endif /* BCM_TOMAHAWK3_SUPPORT */
   1916