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

mpls.c (18310B)


      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:        vlan.c
      8  *      
      9  * Provides:
     10  *      soc_internal_mpls_hash
     11  *      soc_internal_mpls_dual_banks
     12  *      soc_internal_mpls_entry_read
     13  *      soc_internal_mpls_entry_write
     14  *      soc_internal_mpls_entry_ins
     15  *      soc_internal_mpls_entry_del
     16  *      soc_internal_mpls_entry_lkup
     17  *      
     18  * Requires:    
     19  */
     20 
     21 #include <shared/bsl.h>
     22 
     23 #include <soc/mem.h>
     24 #include <soc/hash.h>
     25 #include <soc/drv.h>
     26 #include <soc/l2x.h>
     27 #ifdef BCM_TRIDENT2_SUPPORT
     28 #include <soc/trident2.h>
     29 #endif
     30 #ifdef BCM_TOMAHAWK3_SUPPORT
     31 #include <soc/tomahawk3.h>
     32 #endif /* BCM_TOMAHAWK3_SUPPORT */
     33 
     34 #include "pcid.h"
     35 #include "mem.h"
     36 #include "cmicsim.h"
     37 
     38 #ifdef BCM_TRIUMPH_SUPPORT
     39 
     40 int
     41 soc_internal_mpls_hash(pcid_info_t * pcid_info, 
     42                              mpls_entry_entry_t *entry, int dual)
     43 {
     44     uint32          tmp_hs[SOC_MAX_MEM_WORDS];
     45     int             hash_sel;
     46     uint8           at, key[8];
     47     int             index, bits;
     48     soc_block_t     blk;
     49 
     50     LOG_VERBOSE(BSL_LS_SOC_COMMON,
     51                 (BSL_META("MPLS_ENTRY hash\n")));
     52 
     53 #ifdef BCM_TOMAHAWK3_SUPPORT
     54     if (SOC_IS_TOMAHAWK3(pcid_info->unit)) {
     55         soc_block_t sblk;
     56         int use_lsb;
     57         uint8   acc_type;
     58         uint32  addr;
     59         int bank;
     60         static const soc_field_t fields[] = {
     61             HASH_OFFSET_DEDICATED_BANK_0f, HASH_OFFSET_DEDICATED_BANK_1f
     62         };
     63 
     64         bank = dual ? 1 : 0;
     65         blk = SOC_MEM_BLOCK_ANY(pcid_info->unit, MPLS_ENTRY_HASH_CONTROLm);
     66         sblk = SOC_BLOCK2SCH(pcid_info->unit, blk);
     67         addr = soc_mem_addr_get(pcid_info->unit, MPLS_ENTRY_HASH_CONTROLm, 0,
     68                                 blk, 0, &acc_type);
     69         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp_hs);
     70         use_lsb = soc_mem_field32_get(pcid_info->unit, MPLS_ENTRY_HASH_CONTROLm,
     71                                       tmp_hs, HASH_TABLE_TEST_MODEf);
     72         hash_sel = soc_mem_field32_get(pcid_info->unit,
     73                                        MPLS_ENTRY_HASH_CONTROLm, tmp_hs,
     74                                        fields[bank]);
     75 
     76         index = soc_tomahawk3_mpls_entry_hash(pcid_info->unit, bank, hash_sel,
     77                                         use_lsb, (uint32 *)entry);
     78 
     79         LOG_VERBOSE(BSL_LS_SOC_COMMON, (BSL_META("index %d\n"), index));
     80 
     81         return index;
     82     } else
     83 #endif /* BCM_TOMAHAWK3_SUPPORT */
     84     {
     85         soc_internal_extended_read_reg(pcid_info, blk, at,
     86               soc_reg_addr_get(pcid_info->unit, MPLS_ENTRY_HASH_CONTROLr,
     87                                REG_PORT_ANY, 0, SOC_REG_ADDR_OPTION_NONE,
     88                                &blk, &at), tmp_hs);
     89         if (dual) {
     90             hash_sel = soc_reg_field_get(pcid_info->unit, 
     91                                          MPLS_ENTRY_HASH_CONTROLr,
     92                                          tmp_hs[0], HASH_SELECT_Bf);
     93         } else {
     94             hash_sel = soc_reg_field_get(pcid_info->unit,
     95                                          MPLS_ENTRY_HASH_CONTROLr, tmp_hs[0],
     96                                          HASH_SELECT_Af);
     97         }
     98     }
     99 
    100     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    101                 (BSL_META("hash_sel%s %d\n"), dual ? "(b)" : "(a)", hash_sel));
    102 
    103 #ifdef BCM_TRIDENT2_SUPPORT
    104     if (SOC_IS_TD2_TT2(pcid_info->unit)) {
    105         bits = soc_td2_mpls_base_entry_to_key(pcid_info->unit, dual, entry, key);
    106         index = soc_td2_mpls_hash(pcid_info->unit, hash_sel, bits, entry, key);
    107     } else
    108 #endif /* BCM_TRIDENT2_SUPPORT */
    109     {
    110         bits = soc_tr_mpls_base_entry_to_key(pcid_info->unit, (uint32 *)entry,
    111                                              key);
    112         index = soc_tr_mpls_hash(pcid_info->unit, hash_sel, bits,
    113                                  (uint32 *)entry, key);
    114     }
    115 
    116     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    117                 (BSL_META("index %d\n"), index));
    118 
    119     return index;
    120 }
    121 
    122 void
    123 soc_internal_mpls_dual_banks(pcid_info_t *pcid_info, uint8 banks,
    124                                    int *dual, int *slot_min, int *slot_max)
    125 {
    126     /* Dual hash always enabled for MPLS_ENTRY */
    127     *dual = TRUE;
    128 
    129     if (*dual) {
    130         switch (banks) {
    131         case 0:
    132             return; /* Nothing to do here */
    133         case 1:
    134             *slot_min = 4;
    135             *slot_max = 7;
    136             break;
    137         case 2:
    138             *slot_min = 0;
    139             *slot_max = 3;
    140             break;
    141 #if defined(BCM_TOMAHAWK3_SUPPORT)
    142 		case 3:
    143 			if (SOC_IS_TOMAHAWK3(pcid_info->unit)) {
    144             	*slot_min = 0;
    145             	*slot_max = 7;
    146 			}
    147 			break;
    148 #endif /* BCM_TOMAHAWK3_SUPPORT */
    149         default:
    150             *slot_min = 0;
    151             *slot_max = -1;
    152             break;
    153         }
    154     }
    155 
    156     return;
    157 }
    158 
    159 int
    160 soc_internal_mpls_entry_read(pcid_info_t * pcid_info, uint32 addr,
    161                                    mpls_entry_entry_t *entry)
    162 {
    163     int index = (addr & 0x3fff);
    164     int             blk;             
    165     soc_block_t     sblk;
    166     uint8           at;
    167     uint32          address;
    168     soc_mem_t mem;
    169 
    170     mem = SOC_IS_TOMAHAWK3(pcid_info->unit) ? MPLS_ENTRY_SINGLEm : MPLS_ENTRYm;
    171 
    172     blk = SOC_MEM_BLOCK_ANY(pcid_info->unit, mem);
    173     sblk = SOC_BLOCK2SCH(pcid_info->unit, blk);
    174     address = soc_mem_addr_get(pcid_info->unit, mem, 0,
    175                                blk, index, &at);
    176 
    177     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    178                 (BSL_META("mpls_entry read addr=0x%x\n"), addr));
    179 
    180     soc_internal_extended_read_mem(pcid_info, sblk, 0, address, (uint32 *) entry);
    181 
    182     return 0;
    183 }
    184 
    185 int
    186 soc_internal_mpls_entry_write(pcid_info_t * pcid_info, uint32 addr,
    187                                     mpls_entry_entry_t *entry)
    188 {
    189     int index = (addr & 0x3fff);
    190     int             blk;             
    191     soc_block_t     sblk;
    192     uint8           at;
    193     uint32          address;
    194     soc_mem_t mem;
    195 
    196     mem = SOC_IS_TOMAHAWK3(pcid_info->unit) ? MPLS_ENTRY_SINGLEm : MPLS_ENTRYm;
    197 
    198     blk = SOC_MEM_BLOCK_ANY(pcid_info->unit, mem);
    199     sblk = SOC_BLOCK2SCH(pcid_info->unit, blk);
    200     address = soc_mem_addr_get(pcid_info->unit, mem, 0, 
    201                                blk, index, &at);
    202 
    203     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    204                 (BSL_META("mpls_entry write addr=0x%x\n"), addr));
    205 
    206     soc_internal_extended_write_mem(pcid_info, sblk, 0, address, (uint32 *) entry);
    207 
    208     return 0;
    209 }
    210 
    211 int
    212 soc_internal_mpls_entry_ins(pcid_info_t *pcid_info, uint8 banks,
    213                             mpls_entry_entry_t *entry, uint32 *result)
    214 {
    215     uint32          tmp[SOC_MAX_MEM_WORDS];
    216     int             index = 0, bucket, slot, free_index;
    217     int             slot_min = 0, slot_max = 7, dual = FALSE;
    218     int             unit = pcid_info->unit;
    219     schan_genresp_t *genresp = (schan_genresp_t *)result;
    220     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result;
    221     int             blk;
    222     soc_block_t     sblk;
    223     uint8           acc_type;
    224     uint32          addr;
    225     soc_mem_t       mem;
    226     soc_field_t     valid_fld;
    227 
    228     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    229                 (BSL_META_U(unit,
    230                             "MPLS_ENTRY Insert\n")));
    231 
    232     
    233     mem = SOC_IS_TOMAHAWK3(pcid_info->unit) ? MPLS_ENTRY_SINGLEm : MPLS_ENTRYm;
    234     
    235     valid_fld = SOC_IS_TOMAHAWK3(unit) ? BASE_VALIDf : VALIDf;
    236 
    237     bucket = soc_internal_mpls_hash(pcid_info, entry, FALSE);
    238 
    239     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    240                 (BSL_META_U(unit,
    241                             "bucket %d\n"), bucket));
    242 
    243     if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) {
    244         soc_internal_mpls_dual_banks(pcid_info, banks,
    245                                      &dual, &slot_min, &slot_max);
    246     }
    247     blk = SOC_MEM_BLOCK_ANY(unit, mem);
    248     sblk = SOC_BLOCK2SCH(unit, blk);
    249 
    250     /* Check if it should overwrite an existing entry */
    251     free_index = -1;
    252     for (slot = slot_min; slot <= slot_max; slot++) {
    253         if (dual && (slot == 4)) {
    254             bucket = soc_internal_mpls_hash(pcid_info, entry, TRUE);
    255         }
    256         index = bucket * 8 + slot;
    257         addr = soc_mem_addr_get(unit, mem, 0, blk, index, &acc_type);
    258         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp);
    259         if (soc_mem_field32_get(unit, mem, tmp, valid_fld)) {
    260             if (soc_mem_compare_key(unit, mem, entry, tmp) == 0) {
    261                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
    262                             (BSL_META_U(unit,
    263                                         "write sblk %d acc_type %d bucket %d, "
    264                                         "slot %d, index %d\n"),
    265                              sblk, acc_type, index / 8, index % 8, index));
    266 
    267                 /* Overwrite the existing entry */
    268                 soc_internal_extended_write_mem(pcid_info, sblk, acc_type,
    269                                                 addr, (uint32 *)entry);
    270 
    271                 /* Copy old entry immediately after response word */
    272                 memcpy(&result[1], tmp,
    273                        soc_mem_entry_bytes(unit, mem));
    274 
    275                 result[0] = 0;
    276                 if (soc_feature(unit, soc_feature_new_sbus_format) &&
    277                     !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    278                     genresp_v2->type = SCHAN_GEN_RESP_TYPE_REPLACED;
    279                     genresp_v2->index = index;
    280                 } else {
    281                     genresp->type = SCHAN_GEN_RESP_TYPE_REPLACED;
    282                     genresp->index = index;
    283                 }
    284                 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
    285 
    286                 return 0;
    287             }
    288         } else {
    289             if (free_index == -1) {
    290                 free_index = index;
    291             }
    292         }
    293     }
    294 
    295     /* Find first unused slot in bucket */
    296     if (free_index != -1) {
    297         index = free_index;
    298         addr = soc_mem_addr_get(unit, mem, 0, blk, index, &acc_type);
    299 
    300         LOG_VERBOSE(BSL_LS_SOC_COMMON,
    301                     (BSL_META_U(unit,
    302                                 "write sblk %d acc_type %d bucket %d, slot %d, "
    303                                 "index %d\n"),
    304                      sblk, acc_type, index / 8, index % 8, index));
    305 
    306         /* Write the new entry */
    307         soc_internal_extended_write_mem(pcid_info, sblk, acc_type, addr,
    308                                         (uint32 *)entry);
    309 
    310         result[0] = 0;
    311         if (soc_feature(unit, soc_feature_new_sbus_format) &&
    312             !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    313             genresp_v2->type = SCHAN_GEN_RESP_TYPE_INSERTED;
    314             genresp_v2->index = index;
    315         } else {
    316             genresp->type = SCHAN_GEN_RESP_TYPE_INSERTED;
    317             genresp->index = index;
    318         }
    319         PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
    320 
    321         return 0;
    322     }
    323 
    324     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    325                 (BSL_META_U(unit,
    326                             "Bucket full\n")));
    327 
    328     result[0] = 0;
    329     if (soc_feature(unit, soc_feature_new_sbus_format) &&
    330         !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    331         genresp_v2->type = SCHAN_GEN_RESP_TYPE_FULL;
    332     } else {
    333         genresp->type = SCHAN_GEN_RESP_TYPE_FULL;
    334     }
    335     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
    336 
    337     return 0;
    338 }
    339 
    340 int
    341 soc_internal_mpls_entry_del(pcid_info_t * pcid_info, uint8 banks,
    342                             mpls_entry_entry_t *entry, uint32 *result)
    343 {
    344     uint32          tmp[SOC_MAX_MEM_WORDS];
    345     int             index = 0, bucket, slot;
    346     int             slot_min = 0, slot_max = 7, dual = FALSE;
    347     int             unit = pcid_info->unit;
    348     schan_genresp_t *genresp = (schan_genresp_t *)result;
    349     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result;
    350     int             blk;
    351     soc_block_t     sblk;
    352     uint8           acc_type;
    353     uint32          addr;
    354     soc_mem_t       mem;
    355     soc_field_t     valid_fld;
    356 
    357     mem = SOC_IS_TOMAHAWK3(pcid_info->unit) ? MPLS_ENTRY_SINGLEm : MPLS_ENTRYm;
    358     
    359     valid_fld = SOC_IS_TOMAHAWK3(unit) ? BASE_VALIDf : VALIDf;
    360 
    361     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    362                 (BSL_META_U(unit,
    363                             "MPLS_ENTRY Delete\n")));
    364 
    365     bucket = soc_internal_mpls_hash(pcid_info, entry, FALSE);
    366 
    367     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    368                 (BSL_META_U(unit,
    369                             "bucket %d\n"), bucket));
    370 
    371     if (soc_feature(pcid_info->unit, soc_feature_dual_hash)) {
    372         soc_internal_mpls_dual_banks(pcid_info, banks, &dual, &slot_min,
    373                                      &slot_max);
    374     }
    375     blk = SOC_MEM_BLOCK_ANY(unit, mem);
    376     sblk = SOC_BLOCK2SCH(unit, blk);
    377 
    378     /* Check if entry exists */
    379     for (slot = slot_min; slot <= slot_max; slot++) {
    380         if (dual && (slot == 4)) {
    381             bucket = soc_internal_mpls_hash(pcid_info, entry, TRUE);
    382         }
    383         index = bucket * 8 + slot;
    384         addr = soc_mem_addr_get(unit, mem, 0, blk, index, &acc_type);
    385         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp);
    386         if (soc_mem_field32_get(unit, mem, tmp, valid_fld)) {
    387             if (soc_mem_compare_key(unit, mem, entry, tmp) == 0) {
    388                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
    389                             (BSL_META_U(unit,
    390                                         "found sblk %d acc_type %d bucket %d, "
    391                                         "slot %d, index %d\n"),
    392                              sblk, acc_type, bucket, slot, index));
    393 
    394                 /* Copy entry immediately after response word */
    395                 memcpy(&result[1], tmp,
    396                        soc_mem_entry_bytes(unit, mem));
    397 
    398                 /* Invalidate entry */
    399                 soc_mem_field32_set(unit, mem, tmp, valid_fld, 0);
    400                 soc_internal_extended_write_mem(pcid_info, sblk, acc_type,
    401                                                 addr, tmp);
    402 
    403                 result[0] = 0;
    404                 if (soc_feature(unit, soc_feature_new_sbus_format) &&
    405                     !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    406                     genresp_v2->type = SCHAN_GEN_RESP_TYPE_DELETED;
    407                     genresp_v2->index = index;
    408                 } else {
    409                     genresp->type = SCHAN_GEN_RESP_TYPE_DELETED;
    410                     genresp->index = index;
    411                 }
    412                 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
    413 
    414                 return 0;
    415             }
    416         }
    417     }
    418 
    419     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    420                 (BSL_META_U(unit,
    421                             "soc_internal_mpls_entry_del: Not found\n")));
    422 
    423     result[0] = 0;
    424     if (soc_feature(unit, soc_feature_new_sbus_format) &&
    425         !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    426         genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
    427     } else {
    428         genresp->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
    429     }
    430     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
    431 
    432     return 0;
    433 }
    434 
    435 int
    436 soc_internal_mpls_entry_lkup(pcid_info_t * pcid_info, uint8 banks,
    437                              mpls_entry_entry_t *entry, uint32 *result)
    438 {
    439     uint32          tmp[SOC_MAX_MEM_WORDS];
    440     int             index = 0, bucket, slot;
    441     int             slot_min = 0, slot_max = 7, dual = FALSE;
    442     int             unit = pcid_info->unit;
    443     schan_genresp_t *genresp = (schan_genresp_t *)result;
    444     schan_genresp_v2_t *genresp_v2 = (schan_genresp_v2_t *)result;
    445     int             blk;
    446     soc_block_t     sblk;
    447     uint8           acc_type;
    448     uint32          addr;
    449     soc_mem_t       mem;
    450     soc_field_t     valid_fld;
    451 
    452     mem = SOC_IS_TOMAHAWK3(pcid_info->unit) ? MPLS_ENTRY_SINGLEm : MPLS_ENTRYm;
    453     
    454     valid_fld = SOC_IS_TOMAHAWK3(unit) ? BASE_VALIDf : VALIDf;
    455 
    456     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    457                 (BSL_META_U(unit,
    458                             "MPLS_ENTRY Lookup\n")));
    459 
    460     bucket = soc_internal_mpls_hash(pcid_info, entry, FALSE);
    461 
    462     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    463                 (BSL_META_U(unit,
    464                             "bucket %d\n"), bucket));
    465 
    466     if (soc_feature(unit, soc_feature_dual_hash)) {
    467         soc_internal_mpls_dual_banks(pcid_info, banks, &dual, &slot_min,
    468                                      &slot_max);
    469     }
    470     blk = SOC_MEM_BLOCK_ANY(unit, mem);
    471     sblk = SOC_BLOCK2SCH(unit, blk);
    472 
    473     /* Check if entry exists */
    474     for (slot = slot_min; slot <= slot_max; slot++) {
    475         if (dual && (slot == 4)) {
    476             bucket = soc_internal_mpls_hash(pcid_info, entry, TRUE);
    477         }
    478         index = bucket * 8 + slot;
    479         addr = soc_mem_addr_get(unit, mem, 0, blk, index, &acc_type);
    480         soc_internal_extended_read_mem(pcid_info, sblk, acc_type, addr, tmp);
    481         if (soc_mem_field32_get(unit, mem, tmp, valid_fld)) {
    482             if (soc_mem_compare_key(unit, mem, entry, tmp) == 0) {
    483                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
    484                             (BSL_META_U(unit,
    485                                         "found sblk %d acc_type %d bucket %d, "
    486                                         "slot %d, index %d\n"),
    487                              sblk, acc_type, bucket, slot, index));
    488 
    489                 /* Copy entry immediately after response word */
    490                 memcpy(&result[1], tmp,
    491                        soc_mem_entry_bytes(unit, mem));
    492 
    493                 result[0] = 0;
    494                 if (soc_feature(unit, soc_feature_new_sbus_format) &&
    495                     !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    496                     genresp_v2->type = SCHAN_GEN_RESP_TYPE_FOUND;
    497                     genresp_v2->index = index;
    498                 } else {
    499                     genresp->type = SCHAN_GEN_RESP_TYPE_FOUND;
    500                     genresp->index = index;
    501                 }
    502                 PCIM(pcid_info, CMIC_SCHAN_CTRL) &= ~SC_MSG_NAK_TST;
    503 
    504                 return 0;
    505             }
    506         }
    507     }
    508 
    509     LOG_VERBOSE(BSL_LS_SOC_COMMON,
    510                 (BSL_META_U(unit,
    511                             "soc_internal_mpls_entry_lkup: Not found\n")));
    512 
    513     result[0] = 0;
    514     if (soc_feature(unit, soc_feature_new_sbus_format) &&
    515         !soc_feature(unit, soc_feature_new_sbus_old_resp) ) {
    516         genresp_v2->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
    517     } else {
    518         genresp->type = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
    519     }
    520     PCIM(pcid_info, CMIC_SCHAN_CTRL) |= SC_MSG_NAK_TST;
    521 
    522     return 0;
    523 }
    524 #endif /* BCM_TRIUMPH_SUPPORT */