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


      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:     Apache 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_APACHE_SUPPORT)
     20 
     21 #include <soc/apache.h>
     22 #include <soc/trident2.h>
     23 #include <soc/bondoptions.h>
     24 
     25 /* Get number of banks for the hash table according to the config */
     26 int
     27 soc_apache_hash_bank_count_get(int unit, soc_mem_t mem, int *num_banks)
     28 {
     29     int count;
     30 
     31     int shared_bank_size = 64;
     32 #if defined(BCM_MONTEREY_SUPPORT)
     33     if (SOC_IS_MONTEREY(unit)) { 
     34         shared_bank_size = 0;
     35     }
     36     else 
     37 #endif
     38     if (soc_feature(unit, soc_feature_untethered_otp)) {
     39         if (SOC_BOND_INFO_FEATURE_GET(unit, socBondInfoFeatureUft128k)) {
     40         shared_bank_size = 32;
     41         }
     42     }
     43     switch (mem) {
     44     case L2Xm:
     45         /*
     46          * 8k entries in each of 2 dedicated L2 bank
     47          * 64k entries in each shared bank
     48          */
     49         count = soc_mem_index_count(unit, L2Xm);
     50         if (SOC_IS_MONTEREY(unit)) { 
     51             *num_banks = 2;
     52         }  else {  
     53              *num_banks = 2 + (count - 2 * 8 * 1024) / (shared_bank_size * 1024);
     54         }
     55         break;
     56     case L3_ENTRY_ONLYm:
     57     case L3_ENTRY_IPV4_UNICASTm:
     58     case L3_ENTRY_IPV4_MULTICASTm:
     59     case L3_ENTRY_IPV6_UNICASTm:
     60     case L3_ENTRY_IPV6_MULTICASTm:
     61         /*
     62          * 1k entries in each of 4 dedicated L3 bank
     63          * 64k entries in each shared bank
     64          */
     65         count = soc_mem_index_count(unit, L3_ENTRY_ONLYm);
     66 #if defined(BCM_MONTEREY_SUPPORT)
     67         if (SOC_IS_MONTEREY(unit)) { 
     68             *num_banks = 4;
     69         } else 
     70 #endif
     71         { 
     72             *num_banks = 4 + (count - 4 * 1 * 1024) / (shared_bank_size * 1024);
     73         }
     74         break;
     75     case MPLS_ENTRYm:
     76     case VLAN_XLATEm:
     77     case VLAN_MACm:
     78     case EGR_VLAN_XLATEm:
     79     case ING_VP_VLAN_MEMBERSHIPm:
     80     case EGR_VP_VLAN_MEMBERSHIPm:
     81     case ING_DNAT_ADDRESS_TYPEm:
     82     case L2_ENDPOINT_IDm:
     83     case ENDPOINT_QUEUE_MAPm:
     84         *num_banks = 2;
     85         break;
     86     default:
     87         return SOC_E_INTERNAL;
     88     }
     89 
     90     return SOC_E_NONE;
     91 }
     92 
     93 /* Map logical to physical bank mapping for a memory
     94  *  mem         - memory 
     95  *  log_bank    - logical bank number (or sequence bank number)
     96  *  phy_bank_id - Physical bank id 
     97  */
     98 int
     99 soc_apache_log_to_phy_bank_map(int unit, soc_mem_t mem, int log_bank,
    100                                  int *phy_bank_id)
    101 {
    102     uint32 val;
    103     static const soc_field_t l2_fields[] = {
    104         L2_ENTRY_BANK_2f, L2_ENTRY_BANK_3f, L2_ENTRY_BANK_4f,
    105         L2_ENTRY_BANK_5f
    106     };
    107     static soc_field_t l3_fields[] = {
    108         L3_ENTRY_BANK_4f, L3_ENTRY_BANK_5f, L3_ENTRY_BANK_6f,
    109         L3_ENTRY_BANK_7f
    110     };
    111 
    112     switch (mem) {
    113     case L2Xm:
    114         if (log_bank < 0 || log_bank > 5) {
    115             return SOC_E_PARAM;
    116         }
    117         if (log_bank < 2) {
    118             *phy_bank_id = log_bank;
    119         } else {
    120             SOC_IF_ERROR_RETURN(READ_L2_ISS_LOG_TO_PHY_BANK_MAPr(unit, &val));
    121             /* Starts with 0 in the register which maps to Physical bank 2 */
    122             *phy_bank_id = 2 + soc_reg_field_get(unit, 
    123                                 L2_ISS_LOG_TO_PHY_BANK_MAPr, val,
    124                                 l2_fields[log_bank - 2]);
    125         }
    126         break;
    127     case L3_ENTRY_ONLYm:
    128     case L3_ENTRY_IPV4_UNICASTm:
    129     case L3_ENTRY_IPV4_MULTICASTm:
    130     case L3_ENTRY_IPV6_UNICASTm:
    131     case L3_ENTRY_IPV6_MULTICASTm:
    132         if (log_bank < 0 || log_bank > 7) {
    133             return SOC_E_PARAM;
    134         }
    135         if (log_bank < 4) {
    136             *phy_bank_id = 6 + log_bank; /* dedicated banks */
    137         } else {
    138             SOC_IF_ERROR_RETURN(READ_L3_ISS_LOG_TO_PHY_BANK_MAPr(unit, &val));
    139             /* Starts with 0 in the register which maps to Physical bank 2 */
    140             *phy_bank_id = 2 + soc_reg_field_get(unit, 
    141                                 L3_ISS_LOG_TO_PHY_BANK_MAPr, val,
    142                                 l3_fields[log_bank - 4]);
    143         }
    144         break;
    145     default:
    146         *phy_bank_id = log_bank;
    147         break;
    148     }
    149     return SOC_E_NONE;
    150 }
    151 
    152 /* Map physical to logical bank mapping for a memory
    153  *  mem         - memory
    154  *  phy_bank    - physical bank number
    155  *  log_bank    - logical bank id
    156  */
    157 int
    158 soc_apache_phy_to_log_bank_map(int unit, soc_mem_t mem, int phy_bank, int *log_bank)
    159 {
    160     uint32 val, i;
    161     static const soc_field_t l2_fields[] = {
    162         L2_ENTRY_BANK_2f, L2_ENTRY_BANK_3f, L2_ENTRY_BANK_4f,
    163         L2_ENTRY_BANK_5f
    164     };
    165     static soc_field_t l3_fields[] = {
    166         L3_ENTRY_BANK_4f, L3_ENTRY_BANK_5f, L3_ENTRY_BANK_6f,
    167         L3_ENTRY_BANK_7f
    168     };
    169 
    170     switch (mem) {
    171     case L2Xm:
    172         if (phy_bank < 0 || phy_bank > 5) {
    173             return SOC_E_PARAM;
    174         }
    175         if (phy_bank < 2) {
    176             *log_bank = phy_bank;
    177         } else {
    178             SOC_IF_ERROR_RETURN(READ_L2_ISS_LOG_TO_PHY_BANK_MAPr(unit, &val));
    179             for (i = 0; i < 4; i++) {
    180                 /* Starts with 0 in the register which maps to Physical bank 2 */
    181                 if ((soc_reg_field_get(unit, L2_ISS_LOG_TO_PHY_BANK_MAPr, val,
    182                                        l2_fields[i]) + 2) == phy_bank) {
    183                     *log_bank = 2 + i;
    184                     break;
    185                 }
    186             }
    187         }
    188         break;
    189     case L3_ENTRY_ONLYm:
    190     case L3_ENTRY_IPV4_UNICASTm:
    191     case L3_ENTRY_IPV4_MULTICASTm:
    192     case L3_ENTRY_IPV6_UNICASTm:
    193     case L3_ENTRY_IPV6_MULTICASTm:
    194         if (phy_bank < 2 || phy_bank > 9) {
    195             return SOC_E_PARAM;
    196         }
    197         if (phy_bank > 5) {
    198             *log_bank = phy_bank - 6;
    199         } else {
    200             SOC_IF_ERROR_RETURN(READ_L3_ISS_LOG_TO_PHY_BANK_MAPr(unit, &val));
    201             for (i = 0; i < 4; i++) {
    202                /* Starts with 0 in the register which maps to Physical bank 2 */
    203                 if ((soc_reg_field_get(unit, L3_ISS_LOG_TO_PHY_BANK_MAPr, val,
    204                                       l3_fields[i]) + 2) == phy_bank) {
    205                     *log_bank = 4 + i;
    206                     break;
    207                 }
    208             }
    209         }
    210         break;
    211     default:
    212         *log_bank = phy_bank;
    213         break;
    214     }
    215     return SOC_E_NONE;
    216 }
    217 
    218 /* Get bank bitmap for the hash table according to the config */
    219 int
    220 soc_apache_hash_bank_phy_bitmap_get(int unit, soc_mem_t mem, uint32 *bitmap)
    221 {
    222     uint32 physical_bitmap = 0;
    223     int count = 0;
    224     int i, phy_bank_id = 0;
    225     SOC_IF_ERROR_RETURN(soc_apache_hash_bank_count_get(unit, mem, &count));
    226     for (i = 0; i < count; i++) {
    227         SOC_IF_ERROR_RETURN(
    228             soc_apache_log_to_phy_bank_map(unit, mem, i, &phy_bank_id));
    229         physical_bitmap |= (1 << phy_bank_id);
    230     }
    231     *bitmap = physical_bitmap;
    232     return SOC_E_NONE;
    233 }
    234 
    235 /*
    236  * Map bank sequence number to bank number.
    237  *     Sequence number: 0 .. (number of bank - 1)
    238  *     bank number: bank id in hardware
    239  * This is only useful for L3 table which has non-sequential bank number,
    240  * sequence number equals to bank number for all other tables.
    241  */
    242 int
    243 soc_apache_hash_bank_number_get(int unit, soc_mem_t mem, int seq_num,
    244                                   int *bank_num)
    245 {
    246     int count;
    247 
    248     SOC_IF_ERROR_RETURN(soc_apache_hash_bank_count_get(unit, mem, &count));
    249     if (seq_num < 0 || seq_num >= count) {
    250         return SOC_E_CONFIG;
    251     }
    252     SOC_IF_ERROR_RETURN(soc_apache_log_to_phy_bank_map(unit, mem, seq_num, bank_num));
    253 
    254     return SOC_E_NONE;
    255 }
    256 
    257 /*
    258  * Map bank number to bank sequence number.
    259  *     Sequence number: 0 .. (number of bank - 1)
    260  *     bank number: bank id in hardware
    261  * This is only useful for L3 table which has non-sequential bank number,
    262  *
    263  * L3 seq_num   bank_num
    264  *          0          6
    265  *          1          7
    266  *          2          8
    267  *          3          9
    268  *          4          5
    269  *          5          4
    270  */
    271 int
    272 soc_apache_hash_seq_number_get(int unit, soc_mem_t mem, int bank_num,
    273                                  int *seq_num)
    274 {
    275     int count;
    276 
    277     SOC_IF_ERROR_RETURN(soc_apache_phy_to_log_bank_map(unit, mem, bank_num, seq_num));
    278 
    279     SOC_IF_ERROR_RETURN(soc_apache_hash_bank_count_get(unit, mem, &count));
    280     if (*seq_num < 0 || *seq_num >= count) {
    281         return SOC_E_INTERNAL;
    282     }
    283 
    284     return SOC_E_NONE;
    285 
    286 }
    287 
    288 int
    289 soc_apache_hash_bank_info_get(int unit, soc_mem_t mem, int bank,
    290                                 int *entries_per_bank, int *entries_per_row,
    291                                 int *entries_per_bucket, int *bank_base,
    292                                 int *bucket_offset)
    293 {
    294     int bank_size = 0, row_size = 0, bucket_size = 0, base = 0, offset;
    295     int seq_num = 0;
    296 
    297     int shared_bank_size = 65536;
    298 
    299 #if defined(BCM_MONTEREY_SUPPORT)
    300     if(SOC_IS_MONTEREY(unit)) {
    301         shared_bank_size = 0;
    302     }  
    303     else 
    304 #endif
    305     if (soc_feature(unit, soc_feature_untethered_otp)) {
    306         if (SOC_BOND_INFO_FEATURE_GET(unit, socBondInfoFeatureUft128k)) {
    307             shared_bank_size = 32768;
    308         }
    309     }
    310 
    311     /* Get logical bank number */
    312     SOC_IF_ERROR_RETURN(soc_apache_phy_to_log_bank_map(unit, mem, bank, &seq_num));
    313     bank = seq_num;
    314 
    315     /*
    316      * entry index for bucket b, entry e =
    317      *     bank_base + b * entries_per_row + bucket_offset + e;
    318      */
    319     switch (mem) {
    320     case L2Xm:
    321         /*
    322          * 4 entries per bucket (1 bucket per row)
    323          * bank 0: index      0-  8191 (8k entries in dedicated bank 0)
    324          * bank 1: index   8192- 16383 (8k entries in dedicated bank 1)
    325          * bank 2: index  16384- 81919 (64k entries in shared bank)
    326          * bank 3: index  81920-147455 (64k entries in shared bank)
    327          * bank 4: index 147456-212991 (64k entries in shared bank)
    328          * bank 5: index 212992-278527 (64k entries in shared bank)
    329          * each bucket has 4 entries
    330          */
    331         row_size = 4;
    332         bucket_size = 4;
    333         offset = 0;
    334         if (bank < 0 || bank > 5) {
    335             return SOC_E_INTERNAL;
    336         } else if (bank < 2) { /* 4k entries for each dedicated bank */
    337             bank_size = 8192;
    338 #if defined(BCM_MONTEREY_SUPPORT)
    339             if(SOC_IS_MONTEREY(unit)) {
    340                 bank_size = 16384;
    341             }  
    342 #endif
    343             base = bank * bank_size;
    344         } else { /* 64k entries for each shared bank */
    345             bank_size = shared_bank_size;
    346             base = 16384 + (bank - 2) * bank_size;
    347         }
    348         break;
    349     case L3_ENTRY_ONLYm:
    350     case L3_ENTRY_IPV4_UNICASTm:
    351         /*
    352          * 4 entries per bucket (1 bucket per row)
    353          * bank 0: index      0-  1023 (1k entries in dedicated bank 6)
    354          * bank 1: index   1024-  2047 (1k entries in dedicated bank 7)
    355          * bank 2: index   2048-  3071 (1k entries in dedicated bank 8)
    356          * bank 3: index   3072-  4095 (1k entries in dedicated bank 9)
    357          * bank 4: index   4096- 69631 (64k entries in shared bank)
    358          * bank 5: index  69632-135167 (64k entries in shared bank)
    359          * bank 6: index 135168-200703 (64k entries in shared bank)
    360          * bank 7: index 200704-266239 (64k entries in shared bank)
    361          * each bucket has 4 entries
    362          */
    363         row_size = 4;
    364         bucket_size = 4;
    365         offset = 0;
    366         if (bank < 0 || bank > 7) {
    367             return SOC_E_INTERNAL;
    368         } else if (bank < 4) { /* 1k entriess for each dedicated bank */
    369 #if defined(BCM_MONTEREY_SUPPORT)
    370             if (SOC_IS_MONTEREY(unit)) {
    371                 bank_size = 2048;
    372             } else 
    373 #endif
    374             {
    375                 bank_size = 1024;
    376             }
    377             base = bank * bank_size;
    378         } else { /* 64k entries for each shared bank */
    379             bank_size = shared_bank_size;
    380             base = 4096 + (bank - 4) * bank_size;
    381         }
    382         break;
    383     case L3_ENTRY_IPV4_MULTICASTm:
    384     case L3_ENTRY_IPV6_UNICASTm:
    385 #if defined(BCM_MONTEREY_SUPPORT)
    386         if (SOC_IS_MONTEREY(unit)) {
    387             row_size = 2;
    388             bucket_size = 2;
    389             offset = 0;
    390             if (bank < 0 || bank > 7) {
    391                 return SOC_E_INTERNAL;
    392             } else if (bank < 4) { /* 1k entriess for each dedicated bank */
    393                 bank_size = 1024;
    394                 base = bank * bank_size;
    395             } else { /* 64k entries for each shared bank */
    396                 bank_size = shared_bank_size;
    397                 base = 4096 + (bank - 4) * bank_size;
    398             }
    399         } else 
    400 #endif
    401        { 
    402             row_size = 4;
    403             bucket_size = 4;
    404             offset = 0;
    405             if (bank < 0 || bank > 7) {
    406                 return SOC_E_INTERNAL;
    407             } else if (bank < 4) { /* 1k entriess for each dedicated bank */
    408                 bank_size = 1024;
    409                 base = bank * bank_size;
    410             } else { /* 64k entries for each shared bank */
    411                 bank_size = shared_bank_size;
    412                 base = 4096 + (bank - 4) * bank_size;
    413             }
    414 
    415         } 
    416         break;
    417     case L3_ENTRY_IPV6_MULTICASTm:
    418 #if defined(BCM_MONTEREY_SUPPORT)
    419         if (SOC_IS_MONTEREY(unit)) {
    420             row_size = 1;
    421             bucket_size = 1;
    422             offset = 0;
    423             if (bank < 0 || bank > 7) {
    424                 return SOC_E_INTERNAL;
    425             } else if (bank < 4) { /* 1k entriess for each dedicated bank */
    426                 bank_size = 512;
    427                 base = bank * bank_size;
    428             }
    429         } else 
    430 
    431 #endif
    432         { 
    433             row_size = 4;
    434             bucket_size = 4;
    435             offset = 0;
    436             if (bank < 0 || bank > 7) {
    437                 return SOC_E_INTERNAL;
    438             } else if (bank < 4) { /* 1k entriess for each dedicated bank */
    439                 bank_size = 1024;
    440                 base = bank * bank_size;
    441             } else { /* 64k entries for each shared bank */
    442                 bank_size = shared_bank_size;
    443                 base = 4096 + (bank - 4) * bank_size;
    444             }
    445         }
    446         break;
    447     case MPLS_ENTRYm:
    448     case VLAN_XLATEm:
    449     case VLAN_MACm:
    450     case EGR_VLAN_XLATEm:
    451     case ING_VP_VLAN_MEMBERSHIPm:
    452     case EGR_VP_VLAN_MEMBERSHIPm:
    453     case ING_DNAT_ADDRESS_TYPEm:
    454     case L2_ENDPOINT_IDm:
    455     case ENDPOINT_QUEUE_MAPm:
    456         /*
    457          * first half of entries in each row are for bank 0
    458          * the other half of entries in each row are for bank 1
    459          */
    460         bank_size = soc_mem_index_count(unit, mem) / 2;
    461         row_size = 8;
    462         bucket_size = 4;
    463         base = 0;
    464         offset = bank * bucket_size;
    465         break;
    466     default:
    467         return SOC_E_INTERNAL;
    468     }
    469 
    470     if (entries_per_bank != NULL) {
    471         *entries_per_bank = bank_size;
    472     }
    473     if (entries_per_row != NULL) {
    474         *entries_per_row = row_size;
    475     }
    476     if (entries_per_bucket != NULL) {
    477         *entries_per_bucket = bucket_size;
    478     }
    479     if (bank_base != NULL) {
    480         *bank_base = base;
    481     }
    482     if (bucket_offset != NULL) {
    483         *bucket_offset = offset;
    484     }
    485     return SOC_E_NONE;
    486 }
    487 
    488 STATIC int
    489 _soc_ap_hash_entry_to_key(int unit, void *entry, uint8 *key, soc_mem_t mem,
    490                           soc_field_t *field_list)
    491 {
    492     soc_field_t field;
    493     int         index, key_index, val_index, fval_index;
    494     int         right_shift_count, left_shift_count;
    495     uint32      val[SOC_MAX_MEM_WORDS], fval[SOC_MAX_MEM_WORDS];
    496     int         bits, val_bits, fval_bits;
    497     int8        field_length[16];
    498 
    499     val_bits = 0;
    500     for (index = 0; field_list[index] != INVALIDf; index++) {
    501         field = field_list[index];
    502         field_length[index] = soc_mem_field_length(unit, mem, field);
    503         val_bits += field_length[index];
    504     }
    505 
    506     switch (mem) {
    507     case L2Xm:
    508         val_bits = soc_mem_field_length(unit, L2Xm,
    509                                         TRILL_NONUC_NETWORK_LONG__KEYf);
    510         break;
    511     case L3_ENTRY_ONLYm:
    512     case L3_ENTRY_IPV4_UNICASTm:
    513     case L3_ENTRY_IPV4_MULTICASTm:
    514     case L3_ENTRY_IPV6_UNICASTm:
    515         val_bits = soc_mem_field_length(unit, L3_ENTRY_IPV6_MULTICASTm,
    516                                         IPV6MC__KEY_0f) +
    517             soc_mem_field_length(unit, L3_ENTRY_IPV6_MULTICASTm,
    518                                  IPV6MC__KEY_1f) +
    519             soc_mem_field_length(unit, L3_ENTRY_IPV6_MULTICASTm,
    520                                  IPV6MC__KEY_2f) +
    521             soc_mem_field_length(unit, L3_ENTRY_IPV6_MULTICASTm,
    522                                  IPV6MC__KEY_3f);
    523         break;
    524     case VLAN_XLATEm:
    525     case VLAN_MACm:
    526         val_bits = soc_mem_field_length(unit, VLAN_MACm, MAC_PORT__KEYf);
    527         break;
    528     case EGR_VLAN_XLATEm:
    529         val_bits = soc_mem_field_length(unit, EGR_VLAN_XLATEm, XLATE__KEYf);
    530         break;
    531     case MPLS_ENTRYm:
    532         val_bits = soc_mem_field_length(unit, MPLS_ENTRYm, L2GRE_VPNID__KEYf);
    533         break;
    534     case L2_ENDPOINT_IDm:
    535         val_bits = soc_mem_field_length(unit, L2_ENDPOINT_IDm, L2__KEYf);
    536         break;
    537     default:
    538         break;
    539     }
    540 
    541     bits = (val_bits + 7) & ~0x7;
    542     val_bits = bits - val_bits;
    543 
    544     sal_memset(val, 0, sizeof(val));
    545     for (index = 0; field_list[index] != INVALIDf; index++) {
    546         field = field_list[index];
    547         soc_mem_field_get(unit, mem, entry, field, fval);
    548         fval_bits = field_length[index];
    549 
    550         val_index = val_bits >> 5;
    551         fval_index = 0;
    552         left_shift_count = val_bits & 0x1f;
    553         right_shift_count = 32 - left_shift_count;
    554         val_bits += fval_bits;
    555 
    556         if (left_shift_count) {
    557             for (; fval_bits > 0; fval_bits -= 32) {
    558                 val[val_index++] |= fval[fval_index] << left_shift_count;
    559                 val[val_index] |= fval[fval_index++] >> right_shift_count;
    560             }
    561         } else {
    562             for (; fval_bits > 0; fval_bits -= 32) {
    563                 val[val_index++] = fval[fval_index++];
    564             }
    565         }
    566     }
    567 
    568     key_index = 0;
    569     for (val_index = 0; val_bits > 0; val_index++) {
    570         for (right_shift_count = 0; right_shift_count < 32;
    571              right_shift_count += 8) {
    572             if (val_bits <= 0) {
    573                 break;
    574             }
    575             key[key_index++] = (val[val_index] >> right_shift_count) & 0xff;
    576             val_bits -= 8;
    577         }
    578     }
    579 
    580     if ((bits + 7) / 8 > key_index) {
    581         sal_memset(&key[key_index], 0, (bits + 7) / 8 - key_index);
    582     }
    583 
    584     return bits;
    585 }
    586 
    587 
    588 /* For UFT style hash (L2 and L3 table) */
    589 int
    590 soc_ap_hash_offset_get(int unit, soc_mem_t mem, int bank, int *hash_offset,
    591                        int *use_lsb)
    592 {
    593     uint32 rval;
    594     int is_shared = 0;
    595     soc_reg_t reg;
    596     soc_field_t field;
    597     static const soc_field_t l2_fields[] = {
    598         BANK0_HASH_OFFSETf, BANK1_HASH_OFFSETf, BANK2_HASH_OFFSETf,
    599         BANK3_HASH_OFFSETf, BANK4_HASH_OFFSETf, BANK5_HASH_OFFSETf
    600     };
    601     static const soc_field_t l3_fields[] = {
    602         BANK6_HASH_OFFSETf, BANK7_HASH_OFFSETf, BANK8_HASH_OFFSETf,
    603         BANK9_HASH_OFFSETf, BANK2_HASH_OFFSETf, BANK3_HASH_OFFSETf,
    604         BANK4_HASH_OFFSETf, BANK5_HASH_OFFSETf
    605     };
    606 
    607     if (mem == L2Xm) {
    608         if (bank < 0 || bank > 5) {
    609             return SOC_E_PARAM;
    610         }
    611         is_shared = bank > 1;
    612         reg = L2_TABLE_HASH_CONTROLr;
    613         field = l2_fields[bank];
    614     } else if (mem == L3_ENTRY_ONLYm) {
    615         if (bank < 2 || bank > 9) {
    616             return SOC_E_PARAM;
    617         }
    618         if (bank >= 6 && bank <= 9) { /* Dedicated banks */
    619             bank = bank - 6;
    620         } else if (bank >= 2 && bank <= 5) { /* Shared Banks */
    621             bank = 2 + bank;
    622             is_shared = 1;
    623         }
    624         reg = L3_TABLE_HASH_CONTROLr;
    625         field = l3_fields[bank];
    626     } else {
    627         return SOC_E_INTERNAL;
    628     }
    629 
    630     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
    631     *use_lsb = soc_reg_field_get(unit, reg, rval, HASH_ZERO_OR_LSBf);
    632 
    633     if (is_shared) {
    634         reg = SHARED_TABLE_HASH_CONTROLr;
    635         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
    636     }
    637 
    638     *hash_offset = soc_reg_field_get(unit, reg, rval, field);
    639 
    640     return SOC_E_NONE;
    641 }
    642 
    643 int
    644 soc_ap_hash_offset_set(int unit, soc_mem_t mem, int bank, int hash_offset,
    645                        int use_lsb)
    646 {
    647     uint32 rval;
    648     int is_shared = 0;
    649     soc_reg_t reg;
    650     soc_field_t field;
    651     static const soc_field_t l2_fields[] = {
    652         BANK0_HASH_OFFSETf, BANK1_HASH_OFFSETf, BANK2_HASH_OFFSETf,
    653         BANK3_HASH_OFFSETf, BANK4_HASH_OFFSETf, BANK5_HASH_OFFSETf
    654     };
    655     static const soc_field_t l3_fields[] = {
    656         BANK6_HASH_OFFSETf, BANK7_HASH_OFFSETf, BANK8_HASH_OFFSETf,
    657         BANK9_HASH_OFFSETf, BANK2_HASH_OFFSETf, BANK3_HASH_OFFSETf,
    658         BANK4_HASH_OFFSETf, BANK5_HASH_OFFSETf
    659     };
    660 
    661     if (mem == L2Xm) {
    662         if (bank < 0 || bank > 5) {
    663             return SOC_E_PARAM;
    664         }
    665         is_shared = bank > 1;
    666         reg = L2_TABLE_HASH_CONTROLr;
    667         field = l2_fields[bank];
    668     } else if (mem == L3_ENTRY_ONLYm) {
    669         if (bank < 2 || bank > 9) {
    670             return SOC_E_PARAM;
    671         }
    672         if (bank >= 6 && bank <= 9) { /* Dedicated banks */
    673             bank = bank - 6;
    674         } else if (bank >= 2 && bank <= 5) { /* Shared Banks */
    675             bank = 2 + bank;
    676             is_shared = 1;
    677         }
    678         reg = L3_TABLE_HASH_CONTROLr;
    679         field = l3_fields[bank];
    680     } else {
    681         return SOC_E_INTERNAL;
    682     }
    683 
    684     SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
    685     soc_reg_field_set(unit, reg, &rval, HASH_ZERO_OR_LSBf, use_lsb);
    686     if (!is_shared) {
    687         soc_reg_field_set(unit, reg, &rval, field, hash_offset);
    688     }
    689     SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
    690 
    691     if (is_shared) {
    692         reg = SHARED_TABLE_HASH_CONTROLr;
    693         SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval));
    694         soc_reg_field_set(unit, reg, &rval, field, hash_offset);
    695         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval));
    696     }
    697     return SOC_E_NONE;
    698 }
    699 
    700 STATIC int
    701 _soc_ap_shared_hash(int unit, int hash_offset, uint32 key_nbits, uint8 *key,
    702                     uint32 result_mask, uint16 lsb)
    703 {
    704     uint32 crc_hi, crc_lo;
    705 
    706     if (hash_offset >= 48) {
    707         if (hash_offset > 48) {
    708             lsb >>= hash_offset - 48;
    709         }
    710         return lsb & result_mask;
    711     }
    712 
    713     crc_hi = soc_crc16b(key, key_nbits) | ((uint32)lsb << 16);
    714     if (hash_offset >= 32) {
    715         if (hash_offset > 32) {
    716             crc_hi >>= hash_offset - 32;
    717         }
    718         return crc_hi & result_mask;
    719     }
    720 
    721     crc_lo = soc_crc32b(key, key_nbits);
    722     if (hash_offset > 0) {
    723         crc_lo >>= hash_offset;
    724         crc_lo |= crc_hi << (32 - hash_offset);
    725     }
    726     return crc_lo & result_mask;
    727 }
    728 
    729 uint32
    730 soc_ap_l2x_hash(int unit, int bank, int hash_offset, int use_lsb,
    731                 int key_nbits, void *base_entry, uint8 *key)
    732 {
    733     uint32 lsb_val;
    734     uint32 hash_mask;
    735     uint32 hash_bits;
    736 
    737     if (bank < 2) {
    738 
    739 #if defined(BCM_MONTEREY_SUPPORT)
    740         if (SOC_IS_MONTEREY(unit)) { 
    741             hash_mask = 0x0fff; /* 4k buckets per dedicated L2 bank */
    742         } else 
    743 #endif
    744         {
    745             hash_mask = 0x07ff; /* 2k buckets per dedicated L2 bank */
    746         }
    747         hash_bits = 11;
    748     } else {
    749         hash_mask = 0x3fff; /*16k buckets per shared bank */
    750         hash_bits = 14;
    751     }
    752 
    753     if (use_lsb && (hash_offset + hash_bits > 48)) {
    754         switch (soc_mem_field32_get(unit, L2Xm, base_entry, KEY_TYPEf)) {
    755         case TD2_L2_HASH_KEY_TYPE_BRIDGE:
    756         case TD2_L2_HASH_KEY_TYPE_VFI:
    757         case TD2_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS:
    758             lsb_val = soc_mem_field32_get(unit, L2Xm, base_entry,
    759                                           L2__HASH_LSBf);
    760             break;
    761         case TD2_L2_HASH_KEY_TYPE_SINGLE_CROSS_CONNECT:
    762         case TD2_L2_HASH_KEY_TYPE_DOUBLE_CROSS_CONNECT:
    763             lsb_val = soc_mem_field32_get(unit, L2Xm, base_entry,
    764                                           VLAN__HASH_LSBf);
    765             break;
    766         case TD2_L2_HASH_KEY_TYPE_VIF:
    767             lsb_val = soc_mem_field32_get(unit, L2Xm, base_entry,
    768                                           VIF__HASH_LSBf);
    769             break;
    770         case TD2_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG:
    771             lsb_val = soc_mem_field32_get(unit, L2Xm, base_entry,
    772                                           TRILL_NONUC_NETWORK_LONG__HASH_LSBf);
    773             break;
    774         case TD2_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT:
    775             lsb_val = soc_mem_field32_get
    776                 (unit, L2Xm, base_entry, TRILL_NONUC_NETWORK_SHORT__HASH_LSBf);
    777             break;
    778         case TD2_L2_HASH_KEY_TYPE_BFD:
    779             lsb_val = soc_mem_field32_get(unit, L2Xm, base_entry,
    780                                           BFD__HASH_LSBf);
    781             break;
    782         case TD2_L2_HASH_KEY_TYPE_PE_VID:
    783             lsb_val = soc_mem_field32_get(unit, L2Xm, base_entry,
    784                                           PE_VID__HASH_LSBf);
    785             break;
    786         case TD2_L2_HASH_KEY_TYPE_FCOE_ZONE:
    787             lsb_val = soc_mem_field32_get(unit, L2Xm, base_entry,
    788                                           FCOE_ZONE__HASH_LSBf);
    789             break;
    790         default:
    791             lsb_val = 0;
    792             break;
    793         }
    794     } else {
    795         lsb_val = 0;
    796     }
    797 
    798     return _soc_ap_shared_hash(unit, hash_offset, key_nbits, key, hash_mask,
    799                                lsb_val);
    800 }
    801 
    802 int
    803 soc_ap_l2x_base_entry_to_key(int unit, uint32 *entry, uint8 *key)
    804 {
    805     soc_field_t field_list[2];
    806 
    807     switch (soc_mem_field32_get(unit, L2Xm, entry, KEY_TYPEf)) {
    808     case TD2_L2_HASH_KEY_TYPE_BRIDGE:
    809     case TD2_L2_HASH_KEY_TYPE_VFI:
    810     case TD2_L2_HASH_KEY_TYPE_TRILL_NONUC_ACCESS:
    811         field_list[0] = L2__KEYf;
    812         break;
    813     case TD2_L2_HASH_KEY_TYPE_SINGLE_CROSS_CONNECT:
    814     case TD2_L2_HASH_KEY_TYPE_DOUBLE_CROSS_CONNECT:
    815         field_list[0] = VLAN__KEYf;
    816         break;
    817     case TD2_L2_HASH_KEY_TYPE_VIF:
    818         field_list[0] = VIF__KEYf;
    819         break;
    820     case TD2_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_LONG:
    821         field_list[0] = TRILL_NONUC_NETWORK_LONG__KEYf;
    822         break;
    823     case TD2_L2_HASH_KEY_TYPE_TRILL_NONUC_NETWORK_SHORT:
    824         field_list[0] = TRILL_NONUC_NETWORK_SHORT__KEYf;
    825         break;
    826     case TD2_L2_HASH_KEY_TYPE_BFD:
    827         field_list[0] = BFD__KEYf;
    828         break;
    829     case TD2_L2_HASH_KEY_TYPE_PE_VID:
    830         field_list[0] = PE_VID__KEYf;
    831         break;
    832     case TD2_L2_HASH_KEY_TYPE_FCOE_ZONE:
    833         field_list[0] = FCOE_ZONE__KEYf;
    834         break;
    835     default:
    836         return 0;
    837     }
    838     field_list[1] = INVALIDf;
    839     return _soc_ap_hash_entry_to_key(unit, entry, key, L2Xm, field_list);
    840 }
    841 
    842 uint32
    843 soc_ap_l2x_entry_hash(int unit, int bank, int hash_offset, int use_lsb,
    844                        uint32 *entry)
    845 {
    846     int             key_nbits;
    847     uint8           key[SOC_MAX_MEM_WORDS * 4];
    848 
    849     key_nbits = soc_ap_l2x_base_entry_to_key(unit, entry, key);
    850     return soc_ap_l2x_hash(unit, bank, hash_offset, use_lsb, key_nbits, entry,
    851                            key);
    852 }
    853 
    854 uint32
    855 soc_ap_l2x_bank_entry_hash(int unit, int bank, uint32 *entry)
    856 {
    857     int rv, hash_offset, use_lsb;
    858 
    859     rv = soc_ap_hash_offset_get(unit, L2Xm, bank, &hash_offset, &use_lsb);
    860     if (SOC_FAILURE(rv)) {
    861         return 0;
    862     }
    863 
    864     return soc_ap_l2x_entry_hash(unit, bank, hash_offset, use_lsb, entry);
    865 }
    866 
    867 uint32
    868 soc_ap_l3x_hash(int unit, int bank, int hash_offset, int use_lsb,
    869                 int key_nbits, void *base_entry, uint8 *key)
    870 {
    871     uint32 lsb_val;
    872     uint32 hash_mask;
    873     uint32 hash_bits;
    874 
    875     if (bank > 5) {
    876 #if defined(BCM_MONTEREY_SUPPORT)
    877         if (SOC_IS_MONTEREY(unit)) {  
    878             hash_mask = 0x1ff;  /* 256 buckets per dedicated L3 bank */
    879             hash_bits = 9;
    880         } else 
    881 #endif
    882         { 
    883             hash_mask = 0xff;  /* 256 buckets per dedicated L3 bank */
    884             hash_bits = 8;
    885         } 
    886  
    887     } else {
    888         hash_mask = 0x3fff; /*16k buckets per shared bank */
    889         hash_bits = 14;
    890     }
    891 
    892     if (use_lsb && (hash_offset + hash_bits > 48)) {
    893         switch (soc_mem_field32_get(unit, L3_ENTRY_ONLYm, base_entry,
    894                                     KEY_TYPEf)) {
    895         case TD2_L3_HASH_KEY_TYPE_V4UC:
    896         case TD2_L3_HASH_KEY_TYPE_V4UC_EXT:
    897         case TD2_L3_HASH_KEY_TYPE_V4MC:
    898         case TD2_L3_HASH_KEY_TYPE_V6UC:
    899         case TD2_L3_HASH_KEY_TYPE_V6UC_EXT:
    900         case TD2_L3_HASH_KEY_TYPE_V6MC:
    901         case TD2_L3_HASH_KEY_TYPE_V4L2MC: 
    902         case TD2_L3_HASH_KEY_TYPE_V4L2VPMC:
    903         case TD2_L3_HASH_KEY_TYPE_V6L2MC:
    904         case TD2_L3_HASH_KEY_TYPE_V6L2VPMC:
    905             lsb_val = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm,
    906                                           base_entry, IPV4UC__HASH_LSBf);
    907             break;
    908         case TD2_L3_HASH_KEY_TYPE_TRILL:
    909             lsb_val = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm,
    910                                           base_entry, TRILL__HASH_LSBf);
    911             break;
    912         case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN:
    913         case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT:
    914         case TD2_L3_HASH_KEY_TYPE_FCOE_HOST:
    915         case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT:
    916         case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP:
    917         case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT:
    918             lsb_val = soc_mem_field32_get(unit, L3_ENTRY_IPV4_UNICASTm,
    919                                           base_entry, FCOE__HASH_LSBf);
    920             break;
    921         case TD2_L3_HASH_KEY_TYPE_DST_NAT:
    922         case TD2_L3_HASH_KEY_TYPE_DST_NAPT:
    923             lsb_val = soc_mem_field32_get(unit, L3_ENTRY_IPV4_MULTICASTm,
    924                                           base_entry, NAT__HASH_LSBf);
    925             break;
    926         default:
    927             lsb_val = 0;
    928             break;
    929         }
    930     } else {
    931         lsb_val = 0;
    932     }
    933 
    934     return _soc_ap_shared_hash(unit, hash_offset, key_nbits, key, hash_mask,
    935                                lsb_val);
    936 }
    937 
    938 
    939 int
    940 soc_ap_l3x_base_entry_to_key(int unit, uint32 *entry, uint8 *key)
    941 {
    942     soc_mem_t mem;
    943     soc_field_t field_list[5];
    944     uint32 entry_words = 0;
    945     uint32 sanitized_entry[SOC_MAX_MEM_WORDS] = {0};
    946     void *ptr = NULL;
    947 
    948     ptr = (void *) entry;
    949 
    950     switch (soc_mem_field32_get(unit, L3_ENTRY_ONLYm, entry, KEY_TYPEf)) {
    951     case TD2_L3_HASH_KEY_TYPE_V4UC_EXT:
    952         entry_words = SOC_MEM_WORDS(unit, L3_ENTRY_IPV4_UNICASTm);
    953         sal_memcpy(&sanitized_entry, entry, entry_words * sizeof(entry_words));
    954         ptr = &sanitized_entry;
    955         soc_mem_field32_set(unit, L3_ENTRY_IPV4_UNICASTm, ptr, KEY_TYPEf,
    956                             TD2_L3_HASH_KEY_TYPE_V4UC);
    957         /* fall through */
    958     case TD2_L3_HASH_KEY_TYPE_V4UC:
    959         mem = L3_ENTRY_IPV4_UNICASTm;
    960         field_list[0] = IPV4UC__KEYf;
    961         field_list[1] = INVALIDf;
    962         break;
    963     case TD2_L3_HASH_KEY_TYPE_V6UC_EXT:
    964         entry_words = SOC_MEM_WORDS(unit, L3_ENTRY_IPV6_UNICASTm);
    965         sal_memcpy(&sanitized_entry, entry, entry_words * sizeof(entry_words));
    966         ptr = &sanitized_entry;
    967         soc_mem_field32_set(unit, L3_ENTRY_IPV6_UNICASTm, ptr, KEY_TYPE_0f,
    968                             TD2_L3_HASH_KEY_TYPE_V6UC);
    969         /* fall through */
    970     case TD2_L3_HASH_KEY_TYPE_V6UC:
    971         mem = L3_ENTRY_IPV6_UNICASTm;
    972         field_list[0] = IPV6UC__KEY_0f;
    973         field_list[1] = IPV6UC__KEY_1f;
    974         field_list[2] = INVALIDf;
    975         break;
    976     case TD2_L3_HASH_KEY_TYPE_V4MC:
    977     case TD2_L3_HASH_KEY_TYPE_V4L2MC:
    978     case TD2_L3_HASH_KEY_TYPE_V4L2VPMC:
    979         mem = L3_ENTRY_IPV4_MULTICASTm;
    980         field_list[0] = IPV4MC__KEY_0f;
    981         field_list[1] = IPV4MC__KEY_1f;
    982         field_list[2] = INVALIDf;
    983         break;
    984     case TD2_L3_HASH_KEY_TYPE_V6MC:
    985     case TD2_L3_HASH_KEY_TYPE_V6L2MC:
    986     case TD2_L3_HASH_KEY_TYPE_V6L2VPMC:
    987         mem = L3_ENTRY_IPV6_MULTICASTm;
    988         field_list[0] = IPV6MC__KEY_0f;
    989         field_list[1] = IPV6MC__KEY_1f;
    990         field_list[2] = IPV6MC__KEY_2f;
    991         field_list[3] = IPV6MC__KEY_3f;
    992         field_list[4] = INVALIDf;
    993         break;
    994     case TD2_L3_HASH_KEY_TYPE_TRILL:
    995         mem = L3_ENTRY_IPV4_UNICASTm;
    996         field_list[0] = TRILL__KEYf;
    997         field_list[1] = INVALIDf;
    998         break;
    999     case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT:
   1000         entry_words = SOC_MEM_WORDS(unit, L3_ENTRY_IPV4_UNICASTm);
   1001         sal_memcpy(&sanitized_entry, entry, entry_words * sizeof(entry_words));
   1002         ptr = &sanitized_entry;
   1003         soc_mem_field32_set(unit, L3_ENTRY_IPV4_UNICASTm, ptr, KEY_TYPEf,
   1004                             TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN);
   1005         /* fall through */
   1006     case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN:
   1007         mem = L3_ENTRY_IPV4_UNICASTm;
   1008         field_list[0] = FCOE__KEYf;
   1009         field_list[1] = INVALIDf;
   1010         break;
   1011     case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT:
   1012         entry_words = SOC_MEM_WORDS(unit, L3_ENTRY_IPV4_UNICASTm);
   1013         sal_memcpy(&sanitized_entry, entry, entry_words * sizeof(entry_words));
   1014         ptr = &sanitized_entry;
   1015         soc_mem_field32_set(unit, L3_ENTRY_IPV4_UNICASTm, ptr, KEY_TYPEf,
   1016                             TD2_L3_HASH_KEY_TYPE_FCOE_HOST);
   1017         /* fall through */
   1018     case TD2_L3_HASH_KEY_TYPE_FCOE_HOST:
   1019         mem = L3_ENTRY_IPV4_UNICASTm;
   1020         field_list[0] = FCOE__KEYf;
   1021         field_list[1] = INVALIDf;
   1022         break;
   1023     case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT:
   1024         entry_words = SOC_MEM_WORDS(unit, L3_ENTRY_IPV4_UNICASTm);
   1025         sal_memcpy(&sanitized_entry, entry, entry_words * sizeof(entry_words));
   1026         ptr = &sanitized_entry;
   1027         soc_mem_field32_set(unit, L3_ENTRY_IPV4_UNICASTm, ptr, KEY_TYPEf,
   1028                             TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP);
   1029         /* fall through */
   1030     case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP:
   1031         mem = L3_ENTRY_IPV4_UNICASTm;
   1032         field_list[0] = FCOE__KEYf;
   1033         field_list[1] = INVALIDf;
   1034         break;
   1035 
   1036 
   1037     case TD2_L3_HASH_KEY_TYPE_DST_NAT:
   1038     case TD2_L3_HASH_KEY_TYPE_DST_NAPT:
   1039         mem = L3_ENTRY_IPV4_MULTICASTm;
   1040         field_list[0] = NAT__KEY_0f;
   1041         field_list[1] = INVALIDf;
   1042         break;
   1043     default:
   1044         return 0;
   1045     }
   1046     return _soc_ap_hash_entry_to_key(unit, ptr, key, mem, field_list);
   1047 }
   1048 
   1049 uint32
   1050 soc_ap_l3x_entry_hash(int unit, int bank, int hash_offset, int use_lsb,
   1051                       uint32 *entry)
   1052 {
   1053     int             key_nbits;
   1054     uint8           key[SOC_MAX_MEM_WORDS * 4];
   1055 
   1056     key_nbits = soc_ap_l3x_base_entry_to_key(unit, entry, key);
   1057     return soc_ap_l3x_hash(unit, bank, hash_offset, use_lsb, key_nbits,                           entry, key);
   1058 }
   1059 
   1060 uint32
   1061 soc_ap_l3x_bank_entry_hash(int unit, int bank, uint32 *entry)
   1062 {
   1063     int rv, hash_offset, use_lsb;
   1064 
   1065     rv = soc_ap_hash_offset_get(unit, L3_ENTRY_ONLYm, bank, &hash_offset,
   1066                                 &use_lsb);
   1067     if (SOC_FAILURE(rv)) {
   1068         return 0;
   1069     }
   1070 
   1071     return soc_ap_l3x_entry_hash(unit, bank, hash_offset, use_lsb, entry);
   1072 }
   1073 
   1074 uint32
   1075 soc_ap_mpls_entry_hash(int unit, int hash_sel, int bank, uint32 *entry)
   1076 {
   1077     int             key_nbits;
   1078     uint8           key[SOC_MAX_MEM_WORDS * 4];
   1079     uint32          index;
   1080 
   1081     sal_memset(key, 0, sizeof(key));
   1082 
   1083     key_nbits = soc_td2_mpls_base_entry_to_key(unit, bank, entry, key);
   1084     index = soc_td2_mpls_hash(unit, hash_sel, key_nbits, entry, key);
   1085 
   1086     return index;
   1087 }
   1088 
   1089 uint32
   1090 soc_ap_mpls_bank_entry_hash(int unit, int bank, uint32 *entry)
   1091 {
   1092     int rv, hash_sel;
   1093 
   1094     rv = soc_td2_hash_sel_get(unit, MPLS_ENTRYm, bank, &hash_sel);
   1095     if (SOC_FAILURE(rv)) {
   1096         return 0;
   1097     }
   1098 
   1099     return soc_ap_mpls_entry_hash(unit, hash_sel, bank, entry);
   1100 }
   1101 
   1102 uint32
   1103 soc_ap_vlan_xlate_entry_hash(int unit, int hash_sel, int bank, uint32 *entry)
   1104 {
   1105     int             key_nbits;
   1106     uint8           key[SOC_MAX_MEM_WORDS * 4];
   1107     uint32          index;
   1108 
   1109     sal_memset(key, 0, sizeof(key));
   1110     key_nbits = soc_td2_vlan_xlate_base_entry_to_key(unit, bank, entry, key);
   1111     index = soc_td2_vlan_xlate_hash(unit, hash_sel, key_nbits, entry, key);
   1112 
   1113     return index;
   1114 }
   1115 
   1116 uint32
   1117 soc_ap_vlan_xlate_bank_entry_hash(int unit, int bank, uint32 *entry)
   1118 {
   1119     int rv, hash_sel;
   1120 
   1121     rv = soc_td2_hash_sel_get(unit, VLAN_XLATEm, bank, &hash_sel);
   1122     if (SOC_FAILURE(rv)) {
   1123         return 0;
   1124     }
   1125 
   1126     return soc_ap_vlan_xlate_entry_hash(unit, hash_sel, bank, entry);
   1127 }
   1128 
   1129 uint32
   1130 soc_ap_egr_vlan_xlate_entry_hash(int unit, int hash_sel, int bank,
   1131                                   uint32 *entry)
   1132 {
   1133     int             key_nbits;
   1134     uint8           key[SOC_MAX_MEM_WORDS * 4];
   1135     uint32          index;
   1136 
   1137     sal_memset(key, 0, sizeof(key));
   1138 
   1139     key_nbits = soc_td2_egr_vlan_xlate_base_entry_to_key(unit, bank, entry, key);
   1140     index = soc_td2_egr_vlan_xlate_hash(unit, hash_sel, key_nbits, entry, key);
   1141 
   1142     return index;
   1143 }
   1144 
   1145 uint32
   1146 soc_ap_egr_vlan_xlate_bank_entry_hash(int unit, int bank, uint32 *entry)
   1147 {
   1148     int rv, hash_sel;
   1149 
   1150     rv = soc_td2_hash_sel_get(unit, EGR_VLAN_XLATEm, bank, &hash_sel);
   1151     if (SOC_FAILURE(rv)) {
   1152         return 0;
   1153     }
   1154 
   1155     return soc_ap_egr_vlan_xlate_entry_hash(unit, hash_sel, bank, entry);
   1156 }
   1157 
   1158 uint32
   1159 soc_ap_ing_vp_vlan_member_entry_hash(int unit, int hash_sel, int bank, uint32 *entry)
   1160 {
   1161     int             key_nbits;
   1162     uint8           key[SOC_MAX_MEM_WORDS * 4];
   1163     uint32          index;
   1164 
   1165     key_nbits = soc_td2_ing_vp_vlan_member_base_entry_to_key(unit, bank, entry, key);
   1166     index = soc_td2_ing_vp_vlan_member_hash(unit, hash_sel, key_nbits, entry,
   1167                                            key);
   1168 
   1169     return index;
   1170 }
   1171 
   1172 uint32
   1173 soc_ap_ing_vp_vlan_member_bank_entry_hash(int unit, int bank, uint32 *entry)
   1174 {
   1175     int rv, hash_sel;
   1176 
   1177     rv = soc_td2_hash_sel_get(unit, ING_VP_VLAN_MEMBERSHIPm, bank, &hash_sel);
   1178     if (SOC_FAILURE(rv)) {
   1179         return 0;
   1180     }
   1181 
   1182     return soc_ap_ing_vp_vlan_member_entry_hash(unit, hash_sel, bank, entry);
   1183 }
   1184 
   1185 uint32
   1186 soc_ap_egr_vp_vlan_member_entry_hash(int unit, int hash_sel, int bank, uint32 *entry)
   1187 {
   1188     int             key_nbits;
   1189     uint8           key[SOC_MAX_MEM_WORDS * 4];
   1190     uint32          index;
   1191 
   1192     key_nbits = soc_td2_egr_vp_vlan_member_base_entry_to_key(unit, bank, entry, key);
   1193     index = soc_td2_egr_vp_vlan_member_hash(unit, hash_sel, key_nbits, entry,
   1194                                            key);
   1195 
   1196     return index;
   1197 }
   1198 
   1199 uint32
   1200 soc_ap_egr_vp_vlan_member_bank_entry_hash(int unit, int bank, uint32 *entry)
   1201 {
   1202     int rv, hash_sel;
   1203 
   1204     rv = soc_td2_hash_sel_get(unit, EGR_VP_VLAN_MEMBERSHIPm, bank, &hash_sel);
   1205     if (SOC_FAILURE(rv)) {
   1206         return 0;
   1207     }
   1208 
   1209     return soc_ap_egr_vp_vlan_member_entry_hash(unit, hash_sel, bank, entry);
   1210 }
   1211 
   1212 uint32
   1213 soc_ap_ing_dnat_address_type_entry_hash(int unit, int hash_sel,
   1214                                         int bank, uint32 *entry)
   1215 {
   1216     int             key_nbits;
   1217     uint8           key[SOC_MAX_MEM_WORDS * 4];
   1218     uint32          index;
   1219 
   1220     key_nbits = soc_td2_ing_dnat_address_type_base_entry_to_key(unit, bank,
   1221                                                                 entry, key);
   1222     index = soc_td2_ing_dnat_address_type_hash(unit, hash_sel, key_nbits,
   1223                                               entry, key);
   1224 
   1225     return index;
   1226 }
   1227 
   1228 uint32
   1229 soc_ap_ing_dnat_address_type_bank_entry_hash(int unit, int bank, uint32 *entry)
   1230 {
   1231     int rv, hash_sel;
   1232 
   1233     rv = soc_td2_hash_sel_get(unit, ING_DNAT_ADDRESS_TYPEm, bank, &hash_sel);
   1234     if (SOC_FAILURE(rv)) {
   1235         return 0;
   1236     }
   1237 
   1238     return soc_ap_ing_dnat_address_type_entry_hash(unit, hash_sel, bank, entry);
   1239 }
   1240 
   1241 uint32
   1242 soc_ap_l2_endpoint_id_entry_hash(int unit, int hash_sel, int bank, uint32 *entry)
   1243 {
   1244     int             key_nbits;
   1245     uint8           key[SOC_MAX_MEM_WORDS * 4];
   1246     uint32          index;
   1247 
   1248     key_nbits = soc_td2_l2_endpoint_id_base_entry_to_key(unit, bank, entry, key);
   1249     index = soc_td2_l2_endpoint_id_hash(unit, hash_sel, key_nbits, entry, key);
   1250 
   1251     return index;
   1252 }
   1253 
   1254 uint32
   1255 soc_ap_l2_endpoint_id_bank_entry_hash(int unit, int bank, uint32 *entry)
   1256 {
   1257     int rv, hash_sel;
   1258 
   1259     rv = soc_td2_hash_sel_get(unit, L2_ENDPOINT_IDm, bank, &hash_sel);
   1260     if (SOC_FAILURE(rv)) {
   1261         return 0;
   1262     }
   1263 
   1264     return soc_ap_l2_endpoint_id_entry_hash(unit, hash_sel, bank, entry);
   1265 }
   1266 
   1267 uint32
   1268 soc_ap_endpoint_queue_map_entry_hash(int unit, int hash_sel,
   1269                                      int bank, uint32 *entry)
   1270 {
   1271     int             key_nbits;
   1272     uint8           key[SOC_MAX_MEM_WORDS * 4];
   1273     uint32          index;
   1274 
   1275     key_nbits = soc_td2_endpoint_queue_map_base_entry_to_key(unit, bank,
   1276                                                              entry, key);
   1277     index = soc_td2_endpoint_queue_map_hash(unit, hash_sel, key_nbits, entry,
   1278                                             key);
   1279 
   1280     return index;
   1281 }
   1282 
   1283 uint32
   1284 soc_ap_endpoint_queue_map_bank_entry_hash(int unit, int bank, uint32 *entry)
   1285 {
   1286     int rv, hash_sel;
   1287 
   1288     rv = soc_td2_hash_sel_get(unit, ENDPOINT_QUEUE_MAPm, bank, &hash_sel);
   1289     if (SOC_FAILURE(rv)) {
   1290         return 0;
   1291     }
   1292 
   1293     return soc_ap_endpoint_queue_map_entry_hash(unit, hash_sel, bank, entry);
   1294 }
   1295 
   1296 int
   1297 soc_ap_hash_bucket_get(int unit, int mem, int bank, uint32 *entry, uint32 *bucket)
   1298 {
   1299     switch(mem) {
   1300     case L2Xm:
   1301         *bucket = soc_ap_l2x_bank_entry_hash(unit, bank, entry);
   1302         return SOC_E_NONE;
   1303     case L3_ENTRY_ONLYm:
   1304     case L3_ENTRY_IPV4_UNICASTm:
   1305     case L3_ENTRY_IPV4_MULTICASTm:
   1306     case L3_ENTRY_IPV6_UNICASTm:
   1307     case L3_ENTRY_IPV6_MULTICASTm:
   1308         *bucket = soc_ap_l3x_bank_entry_hash(unit, bank, entry);
   1309         return SOC_E_NONE;
   1310     case ING_VP_VLAN_MEMBERSHIPm:
   1311         *bucket = soc_ap_ing_vp_vlan_member_bank_entry_hash(unit, bank, entry);
   1312         return SOC_E_NONE;
   1313     case EGR_VP_VLAN_MEMBERSHIPm:
   1314         *bucket = soc_ap_egr_vp_vlan_member_bank_entry_hash(unit, bank, entry);
   1315         return SOC_E_NONE;
   1316     case ING_DNAT_ADDRESS_TYPEm:
   1317         *bucket = soc_ap_ing_dnat_address_type_bank_entry_hash(unit, bank, entry);
   1318         return SOC_E_NONE;
   1319     case L2_ENDPOINT_IDm:
   1320         *bucket = soc_ap_l2_endpoint_id_bank_entry_hash(unit, bank, entry);
   1321         return SOC_E_NONE;
   1322     case ENDPOINT_QUEUE_MAPm:
   1323         *bucket = soc_ap_endpoint_queue_map_bank_entry_hash(unit, bank, entry);
   1324         return SOC_E_NONE;
   1325     case VLAN_XLATEm:
   1326         *bucket = soc_ap_vlan_xlate_bank_entry_hash(unit, bank, entry);
   1327         return SOC_E_NONE;
   1328     case EGR_VLAN_XLATEm:
   1329         *bucket = soc_ap_egr_vlan_xlate_bank_entry_hash(unit, bank, entry);
   1330         return SOC_E_NONE;
   1331     case MPLS_ENTRYm:
   1332         *bucket = soc_ap_mpls_bank_entry_hash(unit, bank, entry);
   1333         return SOC_E_NONE;
   1334     default:
   1335         return SOC_E_PARAM;
   1336     }
   1337 }
   1338 
   1339 int
   1340 soc_ap_hash_index_get(int unit, int mem, int bank, int bucket)
   1341 {
   1342     int rv;
   1343     int index;
   1344     int entries_per_row, bank_base, bucket_offset;
   1345 
   1346     switch(mem) {
   1347     case L2Xm:
   1348         rv = soc_apache_hash_bank_info_get(unit, mem, bank, NULL,
   1349                                              &entries_per_row, NULL,
   1350                                              &bank_base, &bucket_offset);
   1351         if (SOC_SUCCESS(rv)) {
   1352             return bank_base + bucket * entries_per_row + bucket_offset;
   1353         }
   1354         break;
   1355     case L3_ENTRY_ONLYm:
   1356     case L3_ENTRY_IPV4_UNICASTm:
   1357     case L3_ENTRY_IPV4_MULTICASTm:
   1358     case L3_ENTRY_IPV6_UNICASTm:
   1359     case L3_ENTRY_IPV6_MULTICASTm:
   1360         rv = soc_apache_hash_bank_info_get(unit, L3_ENTRY_ONLYm, bank, NULL,
   1361                                              &entries_per_row, NULL,
   1362                                              &bank_base, &bucket_offset);
   1363         if (SOC_SUCCESS(rv)) {
   1364             index = bank_base + bucket * entries_per_row + bucket_offset;
   1365             if (mem == L3_ENTRY_IPV4_MULTICASTm || mem == L3_ENTRY_IPV6_UNICASTm) {
   1366                 return index / 2;
   1367             } else if (mem == L3_ENTRY_IPV6_MULTICASTm) {
   1368                 return index / 4;
   1369             }
   1370             return index;
   1371         }
   1372         break;
   1373     default:
   1374         break;
   1375     }
   1376 
   1377     return 0;
   1378 }
   1379 
   1380 #endif /* BCM_APACHE_SUPPORT */