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

l2x.c (48872B)


      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:        l2x.c
      8  *      
      9  * Provides:
     10  *      soc_internal_l2x_read
     11  *      soc_internal_l2x_write
     12  *      soc_internal_l2x_lkup
     13  *      soc_internal_l2x_init
     14  *      soc_internal_l2x_del
     15  *      soc_internal_l2x_ins
     16  *      
     17  * Requires:    
     18  */
     19 
     20 #include <shared/bsl.h>
     21 
     22 #include <soc/mem.h>
     23 #include <soc/hash.h>
     24 #include <soc/drv.h>
     25 #include <soc/l2x.h>
     26 #ifdef BCM_TRIDENT2_SUPPORT
     27 #include <soc/trident2.h>
     28 #endif /* BCM_TRIDENT2_SUPPORT */
     29 #ifdef BCM_TOMAHAWK_SUPPORT
     30 #include <soc/tomahawk.h>
     31 #endif /* BCM_TOMAHAWK_SUPPORT */
     32 #ifdef BCM_TOMAHAWK3_SUPPORT
     33 #include <soc/tomahawk3.h>
     34 #endif /* BCM_TOMAHAWK3_SUPPORT */
     35 #ifdef BCM_APACHE_SUPPORT
     36 #include <soc/apache.h>
     37 #endif /* BCM_APACHE_SUPPORT */
     38 #ifdef BCM_MONTEREY_SUPPORT
     39 #include <soc/apache.h>
     40 #endif /* BCM_MONTEREY_SUPPORT */
     41 
     42 #include "pcid.h"
     43 #include "mem.h"
     44 #include "cmicsim.h"
     45 
     46 #ifdef BCM_XGS_SWITCH_SUPPORT
     47 #ifdef BCM_FIREBOLT_SUPPORT
     48 int
     49 soc_internal_l2x2_hash(pcid_info_t * pcid_info, l2x_entry_t *entry, int dual)
     50 {
     51     uint32          tmp_hs[SOC_MAX_MEM_WORDS];
     52     int             hash_sel;
     53     uint8           at, key[8];
     54     int             index;
     55     soc_block_t     blk;
     56 
     57     LOG_VERBOSE(BSL_LS_SOC_COMMON,
     58                 (BSL_META("L2X2 hash\n")));
     59 
     60     if (dual) {
     61         soc_internal_extended_read_reg(pcid_info, blk, at,
     62                 soc_reg_addr_get(pcid_info->unit, L2_AUX_HASH_CONTROLr,
     63                                  REG_PORT_ANY, 0,
     64                                  SOC_REG_ADDR_OPTION_NONE, &blk, &at),
     65                 tmp_hs);
     66         hash_sel = soc_reg_field_get(pcid_info->unit, L2_AUX_HASH_CONTROLr,
     67                                      tmp_hs[0], HASH_SELECTf);
     68     } else {
     69         soc_internal_extended_read_reg(pcid_info, blk, at,
     70                 soc_reg_addr_get(pcid_info->unit, HASH_CONTROLr, REG_PORT_ANY, 
     71                                  0, SOC_REG_ADDR_OPTION_NONE, &blk, &at), 
     72                 tmp_hs);
     73         hash_sel = soc_reg_field_get(pcid_info->unit, HASH_CONTROLr,
     74                                      tmp_hs[0], L2_AND_VLAN_MAC_HASH_SELECTf);
     75     }
     76 
     77     LOG_VERBOSE(BSL_LS_SOC_COMMON,
     78                 (BSL_META("hash_sel%s %d\n"), dual ? "" : "(aux)", hash_sel));
     79 
     80     soc_draco_l2x_base_entry_to_key(pcid_info->unit, entry, key);
     81 
     82     index = soc_fb_l2_hash(pcid_info->unit, hash_sel, key);
     83 
     84     if (SOC_IS_FIREBOLT2(pcid_info->unit)) {
     85         uint32 addr_mask;
     86         soc_internal_read_reg(pcid_info,
     87               soc_reg_addr(pcid_info->unit, L2_ENTRY_ADDR_MASKr,
     88                            REG_PORT_ANY, 0),
     89               tmp_hs);
     90         addr_mask = soc_reg_field_get(pcid_info->unit, L2_ENTRY_ADDR_MASKr,
     91                                       tmp_hs[0], MASKf);
     92         index &= addr_mask;
     93     }
     94 
     95     LOG_VERBOSE(BSL_LS_SOC_COMMON,
     96                 (BSL_META("index %d\n"), index));
     97 
     98     return index;
     99 }
    100 
    101 void
    102 soc_internal_l2x2_dual_banks(pcid_info_t *pcid_info, uint8 banks,
    103                              int *dual, int *slot_min, int *slot_max)
    104 {
    105     uint32          tmp[SOC_MAX_MEM_WORDS];
    106     soc_block_t     blk;
    107     uint8           at;
    108 
    109     soc_internal_extended_read_reg(pcid_info, blk, at,
    110                                    soc_reg_addr_get(pcid_info->unit, 
    111                                     L2_AUX_HASH_CONTROLr,
    112                                     REG_PORT_ANY, 0,
    113                                     SOC_REG_ADDR_OPTION_NONE, &blk, &at),
    114                                    tmp);
    115     *dual = soc_reg_field_get(pcid_info->unit, L2_AUX_HASH_CONTROLr,
    116                               tmp[0], ENABLEf);
    117 
    118     if (*dual) {
    119         switch (banks) {
    120         case 0:
    121             return; /* Nothing to do here */
    122         case 1:
    123             *slot_min = 4;
    124             *slot_max = 7;
    125             break;
    126         case 2:
    127             *slot_min = 0;
    128             *slot_max = 3;
    129             break;
    130         default:
    131             *slot_min = 0;
    132             *slot_max = -1;
    133             break;
    134         }
    135     }
    136 
    137     return;
    138 }
    139 
    140 int
    141 soc_internal_l2x2_entry_ins(pcid_info_t *pcid_info, uint8 banks,
    142                 l2x_entry_t *entry, uint32 *result)
    143 {
    144     uint32 tmp[SOC_MAX_MEM_WORDS];
    145     int    index = 0, bucket, slot, free_index;
    146     int    slot_min = 0, slot_max = 7, dual = FALSE;
    147     int    unit = pcid_info->unit; 
    148     int    op_fail_pos;
    149     uint8  at; 
    150 
    151     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    152                 (BSL_META_U(unit,
    153                             "l2_entry Insert\n")));
    154 
    155     bucket = soc_internal_l2x2_hash(pcid_info, entry, FALSE);
    156 
    157     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    158                 (BSL_META_U(unit,
    159                             "bucket %d\n"), bucket));
    160 
    161     if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) {
    162         soc_internal_l2x2_dual_banks(pcid_info, banks,
    163                                      &dual, &slot_min, &slot_max);
    164     }
    165 
    166     /* Check if it should overwrite an existing entry */
    167     free_index = -1;
    168     for (slot = slot_min; slot <= slot_max; slot++) {
    169         if (dual && (slot == 4)) {
    170             bucket = soc_internal_l2x2_hash(pcid_info, entry, TRUE);
    171         }
    172         index = bucket * 8 + slot;
    173         soc_internal_extended_read_mem(pcid_info, 
    174                                        SOC_MEM_BLOCK_ANY(unit, L2Xm), at, 
    175                                        soc_mem_addr_get(unit, L2Xm, 0,
    176                                         SOC_MEM_BLOCK_ANY(unit, L2Xm),
    177                                         index, &at), 
    178                                        tmp);
    179         if (soc_mem_field32_get(unit, L2Xm, tmp, VALIDf)) {
    180             if (soc_mem_compare_key(unit, L2Xm, entry, tmp) == 0) {
    181                 /* Overwrite the existing entry */
    182                 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
    183 
    184                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
    185                             (BSL_META_U(unit,
    186                                         "write bucket %d, slot %d, index %d\n"),
    187                              index / 8, index % 8, index));
    188                 soc_internal_extended_write_mem(pcid_info, 
    189                                                 SOC_MEM_BLOCK_ANY(unit, L2Xm), at,
    190                                                 soc_mem_addr_get(unit, L2Xm, 0, 
    191                                                  SOC_MEM_BLOCK_ANY(unit, L2Xm),
    192                                                  index, &at), 
    193                                                 (uint32 *)entry);
    194 
    195                 result[3] = 0x000;
    196                 return 0;
    197             }
    198         } else {
    199             if (free_index == -1) {
    200                 free_index = index;
    201             }
    202         }
    203     }
    204 
    205     /* Find first unused slot in bucket */
    206     if (free_index != -1) {
    207         index = free_index;
    208 
    209         /* Write the existing entry */
    210         result[3] = 0x000;
    211         PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
    212 
    213         LOG_VERBOSE(BSL_LS_SOC_COMMON,
    214                     (BSL_META_U(unit,
    215                                 "write bucket %d, slot %d, index %d\n"),
    216                      index / 8, index % 8, index));
    217         soc_internal_extended_write_mem(pcid_info, 
    218                                         SOC_MEM_BLOCK_ANY(unit, L2Xm), at, 
    219                                         soc_mem_addr_get(unit, L2Xm, 0, 
    220                                          SOC_MEM_BLOCK_ANY(unit, L2Xm),
    221                                          index, &at), 
    222                                         (uint32 *)entry);
    223         return 0;
    224     }
    225 
    226     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    227                 (BSL_META_U(unit,
    228                             "Bucket full\n")));
    229 
    230     /*
    231      * =============================================================
    232      * | PERR_PBM | MFIFO_FULL | OP_FAIL | Index  | L2x entry data |
    233      * =============================================================
    234      */
    235     op_fail_pos = SOC_L2X_OP_FAIL_POS(unit);
    236 
    237     result[3] = (1 << op_fail_pos);
    238     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
    239     return 0;
    240 }
    241 
    242 int
    243 soc_internal_l2x2_entry_del(pcid_info_t * pcid_info, uint8 banks,
    244                 l2x_entry_t *entry, uint32 *result)
    245 {
    246     uint32          tmp[SOC_MAX_MEM_WORDS];
    247     int             op_fail_pos;
    248     int             index = 0, bucket, slot;
    249     int             slot_min = 0, slot_max = 7, dual = FALSE;
    250     int             unit = pcid_info->unit;
    251 
    252     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    253                 (BSL_META_U(unit,
    254                             "l2_entry Delete\n")));
    255 
    256     bucket = soc_internal_l2x2_hash(pcid_info, entry, FALSE);
    257 
    258     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    259                 (BSL_META_U(unit,
    260                             "bucket %d\n"), bucket));
    261 
    262     /*
    263      * =============================================================
    264      * | PERR_PBM | MFIFO_FULL | OP_FAIL | Index  | L2x entry data |
    265      * =============================================================
    266      */
    267     op_fail_pos = SOC_L2X_OP_FAIL_POS(unit);
    268 
    269     result[3] = (1 << op_fail_pos);
    270 
    271     if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) {
    272         soc_internal_l2x2_dual_banks(pcid_info, banks,
    273                                      &dual, &slot_min, &slot_max);
    274     }
    275 
    276     /* Check if entry exists */
    277     for (slot = slot_min; slot <= slot_max; slot++) {
    278         if (dual && (slot == 4)) {
    279             bucket = soc_internal_l2x2_hash(pcid_info, entry, TRUE);
    280         }
    281         index = bucket * 8 + slot;
    282         soc_internal_read_mem(pcid_info, soc_mem_addr(unit, L2Xm, 0, 
    283                                          SOC_MEM_BLOCK_ANY(unit, L2Xm),
    284                                          index), tmp);
    285         if (soc_mem_field32_get(unit, L2Xm, tmp, VALIDf)) {
    286             if (soc_mem_compare_key(unit, L2Xm, entry, tmp) == 0) {
    287                 result[3] = 0x000;
    288 
    289                 /* Invalidate entry */
    290                 soc_mem_field32_set(unit, L2Xm, tmp, VALIDf, 0);
    291                 soc_internal_write_mem(pcid_info,
    292                                        soc_mem_addr(unit, L2Xm, 0, 
    293                                        SOC_MEM_BLOCK_ANY(unit, L2Xm),
    294                                        index), (uint32 *)tmp);
    295             }
    296         } 
    297     }
    298 
    299     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    300                 (BSL_META_U(unit,
    301                             "Not found\n")));
    302 
    303     return 0;
    304 }
    305 
    306 /* 
    307  * soc_internal_l2x2_entry_lkup
    308  *
    309  *   Note: entry_lookup and entry_result may overlap.
    310  */
    311 
    312 int
    313 soc_internal_l2x2_entry_lkup(pcid_info_t * pcid_info, uint8 banks,
    314                              l2x_entry_t *entry_lookup, uint32 *result)
    315 {
    316     uint32 tmp[SOC_MAX_MEM_WORDS];
    317     int    op_fail_pos;
    318     int    index = 0, bucket, slot;
    319     int    slot_min = 0, slot_max = 7, dual = FALSE;
    320     int    unit = pcid_info->unit; 
    321     uint8  at;
    322 
    323     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    324                 (BSL_META_U(unit,
    325                             "l2_entry Lookup\n")));
    326 
    327     bucket = soc_internal_l2x2_hash(pcid_info, entry_lookup, FALSE);
    328 
    329     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    330                 (BSL_META_U(unit,
    331                             "bucket %d\n"), bucket));
    332 
    333     /*
    334      * =============================================================
    335      * | PERR_PBM | MFIFO_FULL | OP_FAIL | Index  | L2x entry data |
    336      * =============================================================
    337      */
    338     op_fail_pos = SOC_L2X_OP_FAIL_POS(unit);
    339 
    340     result[3] = (1 << op_fail_pos);
    341    
    342 
    343     if (soc_feature(unit, soc_feature_dual_hash)) {
    344         soc_internal_l2x2_dual_banks(pcid_info, banks,
    345                                      &dual, &slot_min, &slot_max);
    346     }
    347 
    348     /* Check if entry exists */
    349     for (slot = slot_min; slot <= slot_max; slot++) {
    350         if (dual && (slot == 4)) {
    351             bucket = soc_internal_l2x2_hash(pcid_info, entry_lookup, TRUE);
    352         }
    353         index = bucket * 8 + slot;
    354         soc_internal_extended_read_mem(pcid_info,
    355                                        SOC_MEM_BLOCK_ANY(unit, L2Xm), at, 
    356                                        soc_mem_addr_get(unit, L2Xm, 0, 
    357                                         SOC_MEM_BLOCK_ANY(unit, L2Xm),
    358                                         index, &at), 
    359                                        tmp);
    360         if (soc_mem_field32_get(unit, L2Xm, tmp, VALIDf)) {
    361             if (soc_mem_compare_key(unit, L2Xm, entry_lookup, tmp) == 0) {
    362                 int nbits; /* Data Bits in last word */
    363 
    364                 nbits = soc_mem_entry_bits(unit, L2Xm) % 32;
    365 
    366                 result[0] = tmp[0];
    367                 result[1] = tmp[1];
    368                 if (nbits) {
    369                     result[2] = (tmp[2] & ((1 << nbits) - 1)) |
    370                                 ((index & ((1 << (32 - nbits)) - 1)) << nbits);
    371                     result[3] = (index >> (32 - nbits)) &
    372                                 ((soc_mem_index_max(unit, L2Xm)) >> (32 - nbits));
    373                 } else {
    374                     result[2] = index;
    375                     result[3] = 0;
    376                 }
    377                 return 0;
    378             }
    379         } 
    380     }
    381 
    382     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    383                 (BSL_META_U(unit,
    384                             "Not found\n")));
    385 
    386     return 0;
    387 }
    388 #endif /* BCM_FIREBOLT_SUPPORT */
    389 
    390 #ifdef BCM_TRX_SUPPORT
    391 STATIC int
    392 soc_internal_l2_tr_bucket_get(pcid_info_t *pcid_info, int bank, void *entry)
    393 {
    394     uint32  rval[SOC_MAX_MEM_WORDS];
    395     int     bucket, hash_sel;
    396     int     unit = pcid_info->unit;
    397     int     blk;
    398     uint8   acc_type;
    399     uint32  addr;
    400 
    401 #if defined(BCM_TOMAHAWK3_SUPPORT)
    402     if (SOC_IS_TOMAHAWK3(pcid_info->unit)) {
    403         soc_block_t sblk;
    404         int use_lsb;
    405         static const soc_field_t fields[] = {
    406             HASH_OFFSET_DEDICATED_BANK_0f, HASH_OFFSET_DEDICATED_BANK_1f
    407         };
    408         if (bank < 0 || bank > 1) {
    409             return -1;
    410         }
    411         blk = SOC_MEM_BLOCK_ANY(unit, L2_ENTRY_HASH_CONTROLm);
    412         sblk = SOC_BLOCK2SCH(unit, blk);
    413         addr = soc_mem_addr_get(
    414                     unit, L2_ENTRY_HASH_CONTROLm, 0, blk, 0, &acc_type);
    415         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, rval);
    416         use_lsb = soc_mem_field32_get(
    417                     unit, L2_ENTRY_HASH_CONTROLm, rval, HASH_TABLE_TEST_MODEf);
    418         hash_sel = soc_mem_field32_get(
    419                     unit, L2_ENTRY_HASH_CONTROLm, rval, fields[bank]);
    420         bucket = soc_tomahawk3_l2x_entry_hash(unit, bank, hash_sel, use_lsb, entry);
    421     } else
    422 #endif /* BCM_TOMAHAWK3_SUPPORT */
    423 #ifdef BCM_TRIDENT2_SUPPORT
    424     if (SOC_IS_TD2_TT2(unit)) {
    425         int hash_offset, use_lsb, index;
    426         soc_reg_t reg;
    427         static const soc_field_t fields[] = {
    428             BANK0_HASH_OFFSETf, BANK1_HASH_OFFSETf, BANK2_HASH_OFFSETf,
    429             BANK3_HASH_OFFSETf, BANK4_HASH_OFFSETf, BANK5_HASH_OFFSETf
    430         };
    431         int is_shared_bank;
    432         uint32 (*entry_hash_proc)(int unit, int bank, int hash_offset,
    433                                   int use_lsb, uint32 *entry);
    434 
    435 #if defined(BCM_TOMAHAWK_SUPPORT) 
    436         if (SOC_IS_TOMAHAWKX(unit)) {
    437             static const soc_field_t l2_fields[] = {
    438                 L2_ENTRY_BANK_2f, L2_ENTRY_BANK_3f, L2_ENTRY_BANK_4f,
    439                 L2_ENTRY_BANK_5f
    440             };
    441             entry_hash_proc = soc_th_l2x_entry_hash;
    442             if (bank < 2) {
    443                 is_shared_bank = FALSE;
    444                 index = bank;
    445             } else {
    446                 is_shared_bank = TRUE;
    447                 addr = soc_reg_addr_get(unit, ISS_LOG_TO_PHY_BANK_MAPr,
    448                                         REG_PORT_ANY, 0,
    449                                         SOC_REG_ADDR_OPTION_NONE,
    450                                         &blk, &acc_type);
    451                 soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr,
    452                                                rval);
    453                 index = soc_reg_field_get(unit, ISS_LOG_TO_PHY_BANK_MAPr,
    454                                           rval[0], l2_fields[bank - 2]) + 2;
    455             }
    456         } else
    457 #endif  /* BCM_TOMAHAWK_SUPPORT */  
    458 #if defined(BCM_APACHE_SUPPORT)
    459         if (SOC_IS_APACHE(unit)) {
    460             static const soc_field_t l2_fields[] = {
    461                 L2_ENTRY_BANK_2f, L2_ENTRY_BANK_3f, L2_ENTRY_BANK_4f,
    462                 L2_ENTRY_BANK_5f
    463             };
    464             entry_hash_proc = soc_ap_l2x_entry_hash;
    465 
    466             if (bank < 2) {
    467                 is_shared_bank = FALSE;
    468                 index = bank;
    469             } else {
    470                 is_shared_bank = TRUE;
    471                 addr = soc_reg_addr_get(unit, ISS_LOG_TO_PHY_BANK_MAPr,
    472                                         REG_PORT_ANY, 0,
    473                                         SOC_REG_ADDR_OPTION_NONE,
    474                                         &blk, &acc_type);
    475                 soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr,
    476                                                rval);
    477                 index = soc_reg_field_get(unit, ISS_LOG_TO_PHY_BANK_MAPr,
    478                                           rval[0], l2_fields[bank - 2]) + 2;
    479             }
    480 
    481 
    482 
    483 
    484         } else
    485 #endif /* BCM_APACHE_SUPPORT */
    486         {
    487             entry_hash_proc = soc_td2_l2x_entry_hash;
    488             is_shared_bank = bank > 1;
    489             index = bank;
    490         }
    491 
    492         reg = L2_TABLE_HASH_CONTROLr;
    493         addr = soc_reg_addr_get(unit, reg, REG_PORT_ANY, 0,
    494                                 SOC_REG_ADDR_OPTION_NONE, &blk, &acc_type);
    495         soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr, rval);
    496         use_lsb = soc_reg_field_get(unit, reg, rval[0], HASH_ZERO_OR_LSBf);
    497 
    498         if (is_shared_bank) {
    499             reg = SHARED_TABLE_HASH_CONTROLr;
    500             addr = soc_reg_addr_get(unit, reg, REG_PORT_ANY, 0,
    501                                     SOC_REG_ADDR_OPTION_NONE, &blk, &acc_type);
    502             soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr,
    503                                            rval);
    504         }
    505         hash_offset = soc_reg_field_get(unit, reg, rval[0], fields[index]);
    506         bucket = entry_hash_proc(unit, bank, hash_offset, use_lsb, entry);
    507     } else
    508 #endif /* BCM_TRIDENT2_SUPPORT */
    509     {
    510         hash_sel = -1;
    511         if (bank == 1) {
    512             addr = soc_reg_addr_get(unit, L2_AUX_HASH_CONTROLr, REG_PORT_ANY,
    513                                     0, SOC_REG_ADDR_OPTION_NONE,
    514                                     &blk, &acc_type);
    515             soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr,
    516                                            rval);
    517             if (soc_reg_field_get(unit, L2_AUX_HASH_CONTROLr, rval[0],
    518                                   ENABLEf)) {
    519                 hash_sel = soc_reg_field_get(unit, L2_AUX_HASH_CONTROLr,
    520                                              rval[0], HASH_SELECTf);
    521             }
    522         }
    523         if (hash_sel == -1) {
    524             addr = soc_reg_addr_get(unit, HASH_CONTROLr, REG_PORT_ANY, 0,
    525                                     SOC_REG_ADDR_OPTION_NONE, &blk, &acc_type);
    526             soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr,
    527                                            rval);
    528             hash_sel = soc_reg_field_get(unit, HASH_CONTROLr, rval[0],
    529                                          L2_AND_VLAN_MAC_HASH_SELECTf);
    530         }
    531 
    532         bucket = soc_tr_l2x_entry_hash(unit, hash_sel, entry);
    533     }
    534 
    535     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    536                 (BSL_META_U(unit,
    537                             "bank %d bucket %d\n"), bank, bucket));
    538 
    539     return bucket;
    540 }
    541 
    542 STATIC void
    543 soc_internal_l2_tr_bank_map_get(pcid_info_t *pcid_info, uint32 *bank_map,
    544                                 int *bank_start, int *bank_inc,
    545                                 int *do_first_fit)
    546 {
    547     uint32 rval[SOC_MAX_MEM_WORDS];
    548     int    unit = pcid_info->unit;
    549     int    blk;
    550     uint8  acc_type;
    551     uint32 addr;
    552 
    553 #if defined(BCM_TOMAHAWK3_SUPPORT) || defined(BCM_MONTEREY_SUPPORT)
    554     if (SOC_IS_TOMAHAWK3(pcid_info->unit) || SOC_IS_MONTEREY(pcid_info->unit)) {
    555         
    556         *bank_map = 0x3;
    557         *bank_start = 0;
    558         *bank_inc = 1;
    559         if (do_first_fit != NULL) {
    560             *do_first_fit = FALSE;
    561         }
    562     } else
    563 #endif /* BCM_TOMAHAWK_SUPPORT3 or BCM_MONTEREY_SUPPORT*/
    564 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_APACHE_SUPPORT)
    565     if (SOC_IS_TOMAHAWKX(pcid_info->unit) || SOC_IS_APACHE(pcid_info->unit)) {
    566         uint32 shared_bank_map;
    567         int bit_count;
    568 #ifdef BCM_APACHE_SUPPORT
    569         if (SOC_IS_APACHE(pcid_info->unit)) {
    570             addr = soc_reg_addr_get(unit, L2_ISS_BANK_CONFIGr, REG_PORT_ANY, 0,
    571                                     FALSE, &blk, &acc_type);
    572             soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr, rval);
    573             shared_bank_map = soc_reg_field_get(unit, L2_ISS_BANK_CONFIGr,
    574                                                 rval[0], L2_ENTRY_BANK_CONFIGf);
    575         } else
    576 
    577 #endif /* BCM_APACHE_SUPPORT */
    578         {
    579 
    580         addr = soc_reg_addr_get(unit, ISS_BANK_CONFIGr, REG_PORT_ANY, 0,
    581                                 SOC_REG_ADDR_OPTION_NONE, &blk, &acc_type);
    582         soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr, rval);
    583         shared_bank_map = soc_reg_field_get(unit, ISS_BANK_CONFIGr,
    584                                             rval[0], L2_ENTRY_BANK_CONFIGf);
    585         }
    586         /* calculate number of 1's in shared_bank_map */
    587         bit_count = shared_bank_map - ((shared_bank_map >> 1) & 0x5);
    588         bit_count = ((bit_count & 0xc) >> 2) + (bit_count & 0x3);
    589 
    590         *bank_map = (1 << (bit_count + 2)) - 1;
    591         *bank_start = 0;
    592         *bank_inc = 1;
    593         if (do_first_fit != NULL) {
    594             *do_first_fit = FALSE;
    595         }
    596     } else
    597 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_APACHE_SUPPORT */
    598 #ifdef BCM_TRIDENT2_SUPPORT
    599     if (SOC_IS_TD2_TT2(pcid_info->unit)) {
    600         int    mode;
    601 
    602         addr = soc_reg_addr_get(unit, L2_TABLE_HASH_CONTROLr, REG_PORT_ANY, 0,
    603                                 SOC_REG_ADDR_OPTION_NONE, &blk, &acc_type);
    604         soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr, rval);
    605         mode = soc_reg_field_get(unit, L2_TABLE_HASH_CONTROLr, rval[0], MODEf);
    606         switch (mode) {
    607         case 0:
    608             *bank_map = 0x3f;
    609             break;
    610         case 1:
    611             *bank_map = 0x1f;
    612             break;
    613         case 2:
    614             *bank_map = 0xf;
    615             break;
    616         case 3:
    617             *bank_map = 0x7;
    618             break;
    619         default:
    620             *bank_map = 0x3;
    621         }
    622         *bank_start = 0;
    623         *bank_inc = 1;
    624         if (do_first_fit != NULL) {
    625             *do_first_fit = FALSE;
    626         }
    627     } else
    628 #endif /* BCM_TRIDENT2_SUPPORT */
    629     {
    630         *bank_map = 0x3;
    631         *bank_start = 0;
    632         *bank_inc = 1;
    633 
    634         addr = soc_reg_addr_get(unit, L2_AUX_HASH_CONTROLr, REG_PORT_ANY, 0,
    635                                 SOC_REG_ADDR_OPTION_NONE, &blk, &acc_type);
    636         soc_internal_extended_read_reg(pcid_info, blk, acc_type, addr, rval);
    637         if (do_first_fit != NULL) {
    638             *do_first_fit =
    639                 soc_reg_field_get(unit, L2_AUX_HASH_CONTROLr, rval[0],
    640                                   INSERT_LEAST_FULL_HALFf) ? FALSE : TRUE;
    641         }
    642     }
    643 }
    644 
    645 STATIC void
    646 soc_internal_l2_tr_bank_size_get(pcid_info_t *pcid_info, int bank,
    647                                  int *entries_per_bank, int *entries_per_row,
    648                                  int *entries_per_bucket, int *bank_base,
    649                                  int *bucket_offset)
    650 {
    651     /*
    652      * entry index =
    653      *     bank_base + bucket * entries_per_row + bucket_offest + slot;
    654      */
    655 
    656 #if defined(BCM_TOMAHAWK3_SUPPORT)
    657     if (SOC_IS_TOMAHAWK3(pcid_info->unit)) {
    658         (void)soc_tomahawk3_hash_bank_info_get(pcid_info->unit, L2Xm,
    659                                             bank, entries_per_bank,
    660                                             entries_per_row,
    661                                             entries_per_bucket,
    662                                             bank_base, bucket_offset);
    663     } else
    664 #endif /* BCM_TOMAHAWK3_SUPPORT */
    665 #ifdef BCM_APACHE_SUPPORT
    666     if (SOC_IS_APACHE(pcid_info->unit)) {
    667         (void)soc_apache_hash_bank_info_get(pcid_info->unit, L2Xm,
    668                                             bank, entries_per_bank,
    669                                             entries_per_row,
    670                                             entries_per_bucket,
    671                                             bank_base, bucket_offset);
    672     } else
    673 #endif /* BCM_TOMAHAWK_SUPPORT */
    674 
    675 #ifdef BCM_TOMAHAWK_SUPPORT
    676     if (SOC_IS_TOMAHAWKX(pcid_info->unit)) {
    677         (void)soc_tomahawk_hash_bank_info_get(pcid_info->unit, L2Xm,
    678                                               bank, entries_per_bank,
    679                                               entries_per_row,
    680                                               entries_per_bucket,
    681                                               bank_base, bucket_offset);
    682     } else
    683 #endif /* BCM_TOMAHAWK_SUPPORT */
    684 #ifdef BCM_TRIDENT2_SUPPORT
    685     if (SOC_IS_TD2_TT2(pcid_info->unit)) {
    686         (void)soc_trident2_hash_bank_info_get(pcid_info->unit, L2Xm,
    687                                               bank, entries_per_bank,
    688                                               entries_per_row,
    689                                               entries_per_bucket,
    690                                               bank_base, bucket_offset);
    691     } else
    692 #endif /* BCM_TRIDENT2_SUPPORT */
    693     {
    694         /*
    695          * 8 entries per bucket
    696          * first half of entries (slot 0) in each bucket are for bank 0
    697          * the other half of entries (slot 1) in each bucket are for bank 1
    698          */
    699         if (entries_per_bank != NULL) {
    700             *entries_per_bank = soc_mem_index_count(pcid_info->unit, L2Xm) / 2;
    701         }
    702         *entries_per_row = 8;
    703         *entries_per_bucket = *entries_per_row / 2;
    704         *bank_base = 0;
    705         *bucket_offset = bank * *entries_per_bucket;
    706     }
    707 }
    708 
    709 int
    710 soc_internal_l2_tr_entry_ins(pcid_info_t *pcid_info, uint32 inv_bank_map,
    711                              void *entry, uint32 *result)
    712 {
    713     uint32          tmp[SOC_MAX_MEM_WORDS];
    714     uint32          bank_map;
    715     int             bank, entries_per_bank, bank_start, bank_inc, free_bank;
    716     int             bucket, entries_per_row, bank_base, free_bucket;
    717     int             slot, entries_per_bucket, bucket_offset, free_slot;
    718     int             index, free_index;
    719     int             first_free_slot, free_slot_count, do_first_fit;
    720     int             best_free_slot_count, best_entries_per_bank;
    721     int             unit = pcid_info->unit;
    722     schan_genresp_t *genresp = (schan_genresp_t *) result;
    723     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *) result;
    724     int             blk;
    725     soc_block_t     sblk;
    726     uint8           acc_type;
    727     uint32          addr;
    728     soc_field_t     vld_fld;
    729 #ifdef BCM_HURRICANE3_SUPPORT    
    730     uint32          l2_entry_overflow_count;
    731 #endif /* BCM_HURRICANE3_SUPPORT */
    732     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    733                 (BSL_META_U(unit,
    734                             "L2X Insert\n")));
    735 
    736     blk = SOC_MEM_BLOCK_ANY(unit, L2Xm);
    737     sblk = SOC_BLOCK2SCH(unit, blk);
    738 
    739     vld_fld = SOC_IS_TOMAHAWK3(unit) ? BASE_VALIDf : VALIDf;
    740 
    741     free_index = -1;
    742 
    743     soc_internal_l2_tr_bank_map_get(pcid_info, &bank_map, &bank_start,
    744                                     &bank_inc, &do_first_fit);
    745     bank_map &= ~inv_bank_map;
    746 
    747     best_free_slot_count = 0;
    748     for (bank = bank_start; bank_map != 0; bank += bank_inc) {
    749         if (!(bank_map & (1 << bank))) {
    750             continue;
    751         }
    752         bank_map &= ~(1 << bank);
    753 
    754         soc_internal_l2_tr_bank_size_get(pcid_info, bank, &entries_per_bank,
    755                                          &entries_per_row, &entries_per_bucket,
    756                                          &bank_base, &bucket_offset);
    757         bucket = soc_internal_l2_tr_bucket_get(pcid_info, bank, entry);
    758         free_slot_count = 0;
    759         first_free_slot = -1;
    760         for (slot = 0; slot < entries_per_bucket; slot++) {
    761             index = bank_base + bucket * entries_per_row + bucket_offset +
    762                 slot;
    763             addr = soc_mem_addr_get(unit, L2Xm, 0, blk, index, &acc_type);
    764             soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr,
    765                                            tmp);
    766             if (soc_mem_field32_get(unit, L2Xm, tmp, vld_fld)) {
    767                 if (soc_mem_compare_key(unit, L2Xm, entry, tmp) == 0) {
    768                     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    769                                 (BSL_META_U(unit,
    770                                             "write sblk %d acc_type %d bank %d "
    771                                             "bucket %d, slot %d, index %d\n"),
    772                                  sblk, acc_type, bank, bucket, slot, index));
    773 
    774                     /* Overwrite the existing entry */
    775                     soc_internal_extended_write_mem(pcid_info, sblk, acc_type,
    776                                                     addr, (uint32 *)entry);
    777 
    778                     /* Copy old entry immediately after response word */
    779                     memcpy(&result[1], tmp, soc_mem_entry_bytes(unit, L2Xm));
    780 
    781                     result[0] = 0;
    782                     if (soc_feature(unit, soc_feature_new_sbus_format) &&
    783                         !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    784                         genresp_v2->type = SCHAN_GEN_RESP_TYPE_REPLACED;
    785                         genresp_v2->index = index;
    786                     } else {
    787                         genresp->type = SCHAN_GEN_RESP_TYPE_REPLACED;
    788                         genresp->index = index;
    789                     }
    790                     PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
    791 
    792                     return 0;
    793                 }
    794             } else {
    795                 free_slot_count++;
    796                 if (first_free_slot == -1) {
    797                     first_free_slot = slot;
    798                 }
    799             }
    800         }
    801         if (free_slot_count > 0) {
    802             if (do_first_fit) {
    803                 if (free_index != -1) {
    804                     continue;
    805                 }
    806             } else {
    807                 if (free_slot_count < best_free_slot_count) {
    808                     continue;
    809                 } else if (free_slot_count == best_free_slot_count) {
    810                     if (entries_per_bank < best_entries_per_bank) {
    811                         continue;
    812                     } else if (entries_per_bank == best_entries_per_bank) {
    813                         if (free_index != -1 && bank > free_bank) {
    814                             continue;
    815                         }
    816                     }
    817                 }
    818                 best_free_slot_count = free_slot_count;
    819                 best_entries_per_bank = entries_per_bank;
    820             }
    821             free_index = index + 1 - entries_per_bucket + first_free_slot;
    822             free_bank = bank;
    823             free_bucket = bucket;
    824             free_slot = first_free_slot;
    825         }
    826     }
    827 
    828     /* Find first unused slot in bucket */
    829     if (free_index != -1) {
    830         index = free_index;
    831         addr = soc_mem_addr_get(unit, L2Xm, 0, blk, index, &acc_type);
    832 
    833         LOG_VERBOSE(BSL_LS_SOC_COMMON,
    834                     (BSL_META_U(unit,
    835                                 "write sblk %d acc_type %d bank %d bucket %d, "
    836                                 "slot %d, index %d\n"),
    837                      sblk, acc_type, free_bank, free_bucket, free_slot, index));
    838 
    839         /* Write the entry */
    840         soc_internal_extended_write_mem(pcid_info, sblk, acc_type, addr,
    841                                         entry);
    842 
    843         result[0] = 0;
    844         if (soc_feature(unit, soc_feature_new_sbus_format) &&
    845             !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    846             genresp_v2->type = SCHAN_GEN_RESP_TYPE_INSERTED;
    847             genresp_v2->index = index;
    848         } else {
    849             genresp->type = SCHAN_GEN_RESP_TYPE_INSERTED;
    850             genresp->index = index;
    851         }
    852         PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
    853 
    854         return 0;
    855     }
    856 
    857 #ifdef BCM_HURRICANE3_SUPPORT
    858     if (SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
    859         /* Check L2_ENTRY_OVERFLOW */
    860         l2_entry_overflow_count = soc_mem_index_count(unit, L2_ENTRY_OVERFLOWm);
    861         blk = SOC_MEM_BLOCK_ANY(unit, L2_ENTRY_OVERFLOWm);
    862         sblk = SOC_BLOCK2SCH(unit, blk);
    863         for (index = 0; index < l2_entry_overflow_count; index++) {
    864             
    865             addr = soc_mem_addr_get(unit, L2_ENTRY_OVERFLOWm, 0, blk, 
    866                 index, &acc_type);
    867             soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr,
    868                                                tmp);
    869             if (soc_mem_field32_get(unit, L2_ENTRY_OVERFLOWm, tmp, VALIDf)) {
    870                 if (soc_mem_compare_key(unit, L2_ENTRY_OVERFLOWm, entry, tmp) 
    871                             == 0) {
    872                     LOG_VERBOSE(BSL_LS_SOC_COMMON, 
    873                         (BSL_META_U(unit, "write sblk %d acc_type %d bank %d "
    874                          "bucket %d, slot %d, index %d in L2_ENTRY_OVERFLOW\n"),
    875                           sblk, acc_type, bank, bucket, slot, index));
    876 
    877                     /* Overwrite the existing entry */
    878                     soc_internal_extended_write_mem(pcid_info, sblk, acc_type,
    879                                                     addr, (uint32 *)entry);
    880 
    881                     /* Copy old entry immediately after response word */
    882                     memcpy(&result[1], tmp, 
    883                         soc_mem_entry_bytes(unit, L2_ENTRY_OVERFLOWm));
    884 
    885                     result[0] = 0;
    886                     if (soc_feature(unit, soc_feature_new_sbus_format) &&
    887                         !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    888                         genresp_v2->type = SCHAN_GEN_RESP_TYPE_REPLACED;
    889                         genresp_v2->index = index;
    890                         genresp_v2->index |=
    891                             SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit);
    892                     } else {
    893                         genresp->type = SCHAN_GEN_RESP_TYPE_REPLACED;
    894                         genresp->index = index;
    895                     }
    896                     PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
    897 
    898                     return 0;
    899                 }
    900             } else {
    901                 if (free_index == -1) {
    902                     free_index = index;
    903                 }
    904             }
    905         }
    906 
    907         /* Find first unused entry in L2_ENTRY_OVERFLOW */
    908         if (free_index != -1) {
    909             index = free_index;
    910             addr = soc_mem_addr_get(unit, L2_ENTRY_OVERFLOWm, 0, 
    911                 blk, index, &acc_type);
    912 
    913             LOG_VERBOSE(BSL_LS_SOC_COMMON, 
    914                 (BSL_META_U(unit,"write sblk %d acc_type %d bank %d bucket %d,"
    915                 " slot %d, index %d in L2_ENTRY_OVERFLOW\n"),
    916                    sblk, acc_type, free_bank, free_bucket, free_slot, index));
    917 
    918             /* Write the entry */
    919             soc_internal_extended_write_mem(pcid_info, sblk, acc_type, addr,
    920                                             entry);
    921 
    922             result[0] = 0;
    923             if (soc_feature(unit, soc_feature_new_sbus_format) &&
    924                 !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    925                 genresp_v2->type = SCHAN_GEN_RESP_TYPE_INSERTED;
    926                 genresp_v2->index = index;
    927                 genresp_v2->index |= SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit);
    928             } else {
    929                 genresp->type = SCHAN_GEN_RESP_TYPE_INSERTED;
    930                 genresp->index = index;
    931                 genresp->index |= SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit);
    932             }
    933             PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
    934 
    935             return 0;
    936         }
    937     }
    938 #endif /* BCM_HURRICANE3_SUPPORT */    
    939 
    940     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    941                 (BSL_META_U(unit,
    942                             "Bucket full\n")));
    943     result[0] = 0;
    944     if (soc_feature(unit, soc_feature_new_sbus_format) &&
    945         !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    946         genresp_v2->type = SCHAN_GEN_RESP_TYPE_FULL;
    947     } else {
    948         genresp->type = SCHAN_GEN_RESP_TYPE_FULL;
    949     }
    950     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
    951 
    952     return 0;
    953 }
    954 
    955 int
    956 soc_internal_l2_tr_entry_del(pcid_info_t *pcid_info, uint32 inv_bank_map,
    957                              void *entry, uint32 *result)
    958 {
    959     uint32          tmp[SOC_MAX_MEM_WORDS];
    960     uint32          bank_map;
    961     int             bank, bank_start, bank_inc, bank_base;
    962     int             bucket, entries_per_row;
    963     int             slot, entries_per_bucket, bucket_offset;
    964     int             index;
    965     int             unit = pcid_info->unit;
    966     schan_genresp_t *genresp = (schan_genresp_t *) result;
    967     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *) result;
    968     int             blk;
    969     soc_block_t     sblk;
    970     uint8           acc_type;
    971     uint32          addr;
    972     soc_field_t     vld_fld;
    973 #ifdef BCM_HURRICANE3_SUPPORT    
    974     uint32          l2_entry_overflow_count;
    975 #endif /* BCM_HURRICANE3_SUPPORT */
    976 
    977     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    978                 (BSL_META_U(unit,
    979                             "L2X Delete\n")));
    980 
    981     vld_fld = SOC_IS_TOMAHAWK3(unit) ? BASE_VALIDf : VALIDf;
    982     blk = SOC_MEM_BLOCK_ANY(unit, L2Xm);
    983     sblk = SOC_BLOCK2SCH(unit, blk);
    984 
    985     soc_internal_l2_tr_bank_map_get(pcid_info, &bank_map, &bank_start,
    986                                     &bank_inc, NULL);
    987     bank_map &= ~inv_bank_map;
    988 
    989     for (bank = bank_start; bank_map != 0; bank += bank_inc) {
    990         if (!(bank_map & (1 << bank))) {
    991             continue;
    992         }
    993         bank_map &= ~(1 << bank);
    994 
    995         soc_internal_l2_tr_bank_size_get(pcid_info, bank, NULL,
    996                                          &entries_per_row, &entries_per_bucket,
    997                                          &bank_base, &bucket_offset);
    998         bucket = soc_internal_l2_tr_bucket_get(pcid_info, bank, entry);
    999 
   1000         for (slot = 0; slot < entries_per_bucket; slot++) {
   1001             index = bank_base + bucket * entries_per_row + bucket_offset +
   1002                 slot;
   1003             addr = soc_mem_addr_get(unit, L2Xm, 0, blk, index, &acc_type);
   1004             soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr,
   1005                                            tmp);
   1006             if (soc_mem_field32_get(unit, L2Xm, tmp, vld_fld)) {
   1007                 if (soc_mem_compare_key(unit, L2Xm, entry, tmp) == 0) {
   1008                     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1009                                 (BSL_META_U(unit,
   1010                                             "delete sblk %d acc_type %d bank %d "
   1011                                             "bucket %d, slot %d, index %d\n"),
   1012                                  sblk, acc_type, bank, bucket, slot, index));
   1013 
   1014                     /* Copy entry immediately after response word */
   1015                     memcpy(&result[1], tmp, soc_mem_entry_bytes(unit, L2Xm));
   1016 
   1017                     /* Invalidate entry */
   1018                     soc_mem_field32_set(unit, L2Xm, tmp, vld_fld, 0);
   1019                     soc_internal_extended_write_mem(pcid_info, sblk, acc_type,
   1020                                                     addr, (uint32 *)tmp);
   1021 
   1022                     result[0] = 0;
   1023                     if (soc_feature(unit, soc_feature_new_sbus_format) &&
   1024                         !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
   1025                         genresp_v2->type = SCHAN_GEN_RESP_TYPE_DELETED;
   1026                         genresp_v2->index = index;
   1027                     } else {
   1028                         genresp->type = SCHAN_GEN_RESP_TYPE_DELETED;
   1029                         genresp->index = index;
   1030                     }
   1031                     PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
   1032 
   1033                     return 0;
   1034                 }
   1035             }
   1036         }
   1037     }
   1038 
   1039 #ifdef BCM_HURRICANE3_SUPPORT
   1040     if (SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   1041         /* Check L2_ENTRY_OVERFLOW */
   1042         l2_entry_overflow_count = soc_mem_index_count(unit, L2_ENTRY_OVERFLOWm);
   1043         blk = SOC_MEM_BLOCK_ANY(unit, L2_ENTRY_OVERFLOWm);
   1044         sblk = SOC_BLOCK2SCH(unit, blk);
   1045         for (index = 0; index < l2_entry_overflow_count; index++) {
   1046             
   1047             addr = soc_mem_addr_get(unit, L2_ENTRY_OVERFLOWm, 0, blk, 
   1048                 index, &acc_type);
   1049             soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr,
   1050                                                tmp);
   1051             if (soc_mem_field32_get(unit, L2_ENTRY_OVERFLOWm, tmp, VALIDf)) {
   1052                 if (soc_mem_compare_key(unit, L2_ENTRY_OVERFLOWm, 
   1053                                                 entry, tmp) == 0) {
   1054                     LOG_VERBOSE(BSL_LS_SOC_COMMON, 
   1055                         (BSL_META_U(unit, "delete sblk %d acc_type %d bank %d "
   1056                          "bucket %d, slot %d, index %d in L2_ENTRY_OVERFLOW\n"),
   1057                          sblk, acc_type, bank, bucket, slot, index));
   1058 
   1059                     /* Copy entry immediately after response word */
   1060                     memcpy(&result[1], tmp, soc_mem_entry_bytes(unit, 
   1061                         L2_ENTRY_OVERFLOWm));
   1062 
   1063                     /* Invalidate entry */
   1064                     soc_mem_field32_set(unit, L2_ENTRY_OVERFLOWm, 
   1065                                                         tmp, VALIDf, 0);
   1066                     soc_internal_extended_write_mem(pcid_info, sblk, acc_type,
   1067                                                     addr, (uint32 *)tmp);
   1068 
   1069                     result[0] = 0;
   1070                     if (soc_feature(unit, soc_feature_new_sbus_format) &&
   1071                         !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
   1072                         genresp_v2->type = SCHAN_GEN_RESP_TYPE_DELETED;
   1073                         genresp_v2->index = index;
   1074                         genresp_v2->index |=
   1075                             SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit);
   1076                     } else {
   1077                         genresp->type = SCHAN_GEN_RESP_TYPE_DELETED;
   1078                         genresp->index = index;
   1079                         genresp->index |=
   1080                             SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit);
   1081                     }
   1082                     PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
   1083 
   1084                     return 0;
   1085                 }
   1086             }
   1087         }
   1088     }
   1089 #endif /* BCM_HURRICANE3_SUPPORT */    
   1090 
   1091     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1092                 (BSL_META_U(unit,
   1093                             "soc_internal_l2_tr_entry_del: Not found\n")));
   1094 
   1095     result[0] = 0;
   1096     if (soc_feature(unit, soc_feature_new_sbus_format) &&
   1097         !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
   1098         genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
   1099     } else {
   1100         genresp->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
   1101     }
   1102     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
   1103 
   1104     return 0;
   1105 }
   1106 
   1107 /*
   1108  * soc_internal_l2_tr_entry_lkup
   1109  *
   1110  *   Note: entry_lookup and entry_result may overlap.
   1111  */
   1112 
   1113 int
   1114 soc_internal_l2_tr_entry_lkup(pcid_info_t *pcid_info, uint32 inv_bank_map,
   1115                               void *entry, uint32 *result)
   1116 {
   1117     uint32          tmp[SOC_MAX_MEM_WORDS];
   1118     uint32          bank_map;
   1119     int             bank, bank_start, bank_inc, bank_base;
   1120     int             bucket, entries_per_row;
   1121     int             slot, entries_per_bucket, bucket_offset;
   1122     int             index;
   1123     int             unit = pcid_info->unit;
   1124     schan_genresp_t *genresp = (schan_genresp_t *) result;
   1125     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *) result;
   1126     int             blk;
   1127     soc_block_t     sblk;
   1128     uint8           acc_type;
   1129     uint32          addr;
   1130     soc_field_t     vld_fld;
   1131 #ifdef BCM_HURRICANE3_SUPPORT    
   1132     uint32          l2_entry_overflow_count;
   1133 #endif /* BCM_HURRICANE3_SUPPORT */
   1134 
   1135     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1136                 (BSL_META_U(unit,
   1137                             "L2X Lookup\n")));
   1138 
   1139     vld_fld = SOC_IS_TOMAHAWK3(unit) ? BASE_VALIDf : VALIDf;
   1140     blk = SOC_MEM_BLOCK_ANY(unit, L2Xm);
   1141     sblk = SOC_BLOCK2SCH(unit, blk);
   1142 
   1143     soc_internal_l2_tr_bank_map_get(pcid_info, &bank_map, &bank_start,
   1144                                     &bank_inc, NULL);
   1145     bank_map &= ~inv_bank_map;
   1146 
   1147     for (bank = bank_start; bank_map != 0; bank += bank_inc) {
   1148         if (!(bank_map & (1 << bank))) {
   1149             continue;
   1150         }
   1151         bank_map &= ~(1 << bank);
   1152 
   1153         soc_internal_l2_tr_bank_size_get(pcid_info, bank, NULL,
   1154                                          &entries_per_row, &entries_per_bucket,
   1155                                          &bank_base, &bucket_offset);
   1156         bucket = soc_internal_l2_tr_bucket_get(pcid_info, bank, entry);
   1157 
   1158         for (slot = 0; slot < entries_per_bucket; slot++) {
   1159             index = bank_base + bucket * entries_per_row + bucket_offset +
   1160                 slot;
   1161             addr = soc_mem_addr_get(unit, L2Xm, 0, blk, index, &acc_type);
   1162             soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr,
   1163                                            tmp);
   1164             if (soc_mem_field32_get(unit, L2Xm, tmp, vld_fld)) {
   1165                 if (soc_mem_compare_key(unit, L2Xm, entry, tmp) == 0) {
   1166                     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1167                                 (BSL_META_U(unit,
   1168                                             "found sblk %d acc_type %d bank %d "
   1169                                             "bucket %d, slot %d, index %d\n"),
   1170                                  sblk, acc_type, bank, bucket, slot, index));
   1171 
   1172                     /* Copy entry immediately after response word */
   1173                     memcpy(&result[1], tmp, soc_mem_entry_bytes(unit, L2Xm));
   1174 
   1175                     result[0] = 0;
   1176                     if (soc_feature(unit, soc_feature_new_sbus_format) &&
   1177                         !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
   1178                         genresp_v2->type = SCHAN_GEN_RESP_TYPE_FOUND;
   1179                         genresp_v2->index = index;
   1180                     } else {
   1181                         genresp->type = SCHAN_GEN_RESP_TYPE_FOUND;
   1182                         genresp->index = index;
   1183                     }
   1184                     PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
   1185 
   1186                     return 0;
   1187                 }
   1188             }
   1189         }
   1190     }
   1191 
   1192 #ifdef BCM_HURRICANE3_SUPPORT
   1193     if (SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   1194         /* Check L2_ENTRY_OVERFLOW */
   1195         l2_entry_overflow_count = soc_mem_index_count(unit, L2_ENTRY_OVERFLOWm);
   1196         blk = SOC_MEM_BLOCK_ANY(unit, L2_ENTRY_OVERFLOWm);
   1197         sblk = SOC_BLOCK2SCH(unit, blk);
   1198         for (index = 0; index < l2_entry_overflow_count; index++) {
   1199             
   1200             addr = soc_mem_addr_get(unit, L2_ENTRY_OVERFLOWm, 0, blk, 
   1201                 index, &acc_type);
   1202             soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr,
   1203                                                tmp);
   1204             if (soc_mem_field32_get(unit, L2_ENTRY_OVERFLOWm, tmp, VALIDf)) {
   1205                 if (soc_mem_compare_key(unit, L2_ENTRY_OVERFLOWm, 
   1206                         entry, tmp) == 0) {
   1207                     LOG_VERBOSE(BSL_LS_SOC_COMMON, 
   1208                         (BSL_META_U(unit, "found sblk %d acc_type %d bank %d "
   1209                          "bucket %d, slot %d, index %d in L2_ENTRY_OVERFLOW\n"),
   1210                          sblk, acc_type, bank, bucket, slot, index));
   1211 
   1212                     /* Copy entry immediately after response word */
   1213                     memcpy(&result[1], tmp, 
   1214                         soc_mem_entry_bytes(unit, L2_ENTRY_OVERFLOWm));
   1215 
   1216                     result[0] = 0;
   1217                     if (soc_feature(unit, soc_feature_new_sbus_format) &&
   1218                         !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
   1219                         genresp_v2->type = SCHAN_GEN_RESP_TYPE_FOUND;
   1220                         genresp_v2->index = index;
   1221                         genresp_v2->index |=
   1222                             SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit);
   1223                     } else {
   1224                         genresp->type = SCHAN_GEN_RESP_TYPE_FOUND;
   1225                         genresp->index = index;
   1226                         genresp->index |=
   1227                             SOC_L2X_GEN_RESP_INDEX_L2_OVERFLOW(unit);
   1228                     }
   1229                     PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
   1230 
   1231                     return 0;
   1232                 }
   1233             }
   1234         }
   1235     }
   1236 #endif /* BCM_HURRICANE3_SUPPORT */    
   1237 
   1238     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1239                 (BSL_META_U(unit,
   1240                             "soc_internal_l2_tr_entry_lkup: Not found\n")));
   1241 
   1242     result[0] = 0;
   1243     if (soc_feature(unit, soc_feature_new_sbus_format) &&
   1244         !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
   1245         genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
   1246     } else {
   1247         genresp->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
   1248     }
   1249     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
   1250 
   1251     return 0;
   1252 }
   1253 #endif /* BCM_TRX_SUPPORT */
   1254 #endif