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

alpm.c (136929B)


      1 /*
      2  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      3  * 
      4  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      5  * 
      6  * File:    alpm.c
      7  * Purpose: ALPM + TCAM device dependent implementation
      8  * Requires:
      9  */
     10 
     11 /* Implementation notes:
     12  */
     13 #include <shared/bsl.h>
     14 
     15 #include <soc/mem.h>
     16 #include <soc/drv.h>
     17 #include <soc/debug.h>
     18 #include <soc/error.h>
     19 #include <soc/format.h>
     20 #include <soc/lpm.h>
     21 #include <soc/trident2.h>
     22 #include <soc/tomahawk.h>
     23 #include <soc/trident3.h>
     24 #include <shared/bsl.h>
     25 
     26 #include <shared/util.h>
     27 #include <shared/l3.h>
     28 
     29 #if defined(ALPM_ENABLE)
     30 
     31 #include <bcm/l3.h>
     32 #include <soc/alpm.h>
     33 #include <bcm_int/esw/l3.h>
     34 #include <bcm_int/esw/firebolt.h>
     35 #include <bcm_int/esw/alpm.h>
     36 #include <bcm_int/esw/alpm_util.h>
     37 
     38 #define TD3_ALPM_BKT_BITS       13
     39 
     40 #define TH_ENT_VALID_GET(u)                                     \
     41     soc_mem_field32_get(u, (mem), (ent),                        \
     42         (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? VALID_LWRf : VALIDf)
     43 #define TH_ENT_HIT_GET(u)                                       \
     44     soc_mem_field32_get(u, (mem), (ent),                        \
     45         (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? HITf :       \
     46         x ? HIT1f : HIT0f)
     47 #define TH_ENT_RPE_GET(u)                                       \
     48     soc_mem_field32_get(u, (mem), (ent),                        \
     49         (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? RPEf :       \
     50         x ? RPE1f : RPE0f)
     51 #define TH_ENT_DATA_TYPE_GET(u)                                 \
     52     soc_mem_field32_get(u, (mem), (ent),                        \
     53         (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? DATA_TYPEf : \
     54         x ? DATA_TYPE1f : DATA_TYPE0f)
     55 #define TH_ENT_ENTRY_VIEW_GET(u)                                 \
     56     soc_mem_field32_get(u, (mem), (ent),                        \
     57         (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? ENTRY_VIEWf : \
     58         x ? ENTRY_VIEW1f : ENTRY_VIEW0f)
     59 #define TH_ENT_DST_DISCARD_GET(u)                               \
     60     soc_mem_field32_get(u, (mem), (ent),                        \
     61         (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? DST_DISCARDf :\
     62         x ? DST_DISCARD1f : DST_DISCARD0f)
     63 #define TH_ENT_PRI_GET(u)                                       \
     64     soc_mem_field32_get(u, (mem), (ent),                        \
     65         (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? PRIf :       \
     66         x ? PRI1f : PRI0f)
     67 #define TH_ENT_CLASS_ID_GET(u)                                  \
     68     soc_mem_field32_get(u, (mem), (ent),                        \
     69         (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? CLASS_IDf :  \
     70         x ? CLASS_ID1f : CLASS_ID0f)
     71 
     72 /* Key & Mask */
     73 #define TH_ENT_KEY_IPADDR_GET(u, key)                       \
     74     do {                                                    \
     75         int i;                                              \
     76         if (mem == alpm_tbl[alpmTblPvtCmodeL1P128]) {       \
     77             soc_field_t _key_fld_p[] =                      \
     78                 {IP_ADDR0_LWRf, IP_ADDR1_LWRf,              \
     79                 IP_ADDR0_UPRf, IP_ADDR1_UPRf};              \
     80             for (i = 0; i < 4; i++) {                       \
     81                 key[i] = soc_mem_field32_get(u, mem, ent,   \
     82                     _key_fld_p[i]);                         \
     83             }                                               \
     84         } else {                                            \
     85             soc_field_t _key_fld[] = {IP_ADDR0f, IP_ADDR1f};\
     86             for (i = 0; i < 2-x; i++) {                     \
     87                 if (pkm == ALPM_PKM_32B &&                  \
     88                     x == 0 && i == 1) {                     \
     89                     continue;                               \
     90                 }                                           \
     91                 key[i] = soc_mem_field32_get(u, mem, ent,   \
     92                     _key_fld[(i+x)%2]);                     \
     93             }                                               \
     94         }                                                   \
     95     } while (0)
     96 
     97 #define TH_ENT_KEY_VRF_ID_GET(u, vrf_id)                    \
     98     do {                                                    \
     99         int i;                                              \
    100         uint32 key[3] = {0};                                \
    101         if (mem == alpm_tbl[alpmTblPvtCmodeL1P128]) {       \
    102             soc_field_t _key_fld_p[] =                      \
    103                 {GLOBAL_HIGHf, GLOBAL_ROUTEf,               \
    104                 VRF_ID_0_LWRf};                             \
    105             for (i = 0; i < 3; i++) {                       \
    106                 key[i] = soc_mem_field32_get(u, mem, ent,   \
    107                     _key_fld_p[i]);                         \
    108             }                                               \
    109         } else {                                            \
    110             soc_field_t _key_fld_0[] =                      \
    111                 {GLOBAL_HIGH0f, GLOBAL_ROUTE0f,             \
    112                 VRF_ID_0f};                                 \
    113             soc_field_t _key_fld_1[] =                      \
    114                 {GLOBAL_HIGH1f, GLOBAL_ROUTE1f,             \
    115                 VRF_ID_1f};                                 \
    116             for (i = 0; i < 3; i++) {                       \
    117                 key[i] = soc_mem_field32_get(u, mem, ent,   \
    118                     x ? _key_fld_1[i] : _key_fld_0[i]);     \
    119             }                                               \
    120         }                                                   \
    121         if (key[1]) {                                       \
    122             (vrf_id) = key[0] ? ALPM_VRF_ID_GHI(u) :        \
    123                         ALPM_VRF_ID_GLO(u);                 \
    124         } else {                                            \
    125             (vrf_id) = key[2];                              \
    126         }                                                   \
    127     } while (0)
    128 
    129 #define TH_ENT_KEY_KT_GET(u)                                        \
    130     soc_mem_field32_get(u, (mem), (ent),                            \
    131         (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? KEY_TYPE0_LWRf : \
    132         x ? KEY_TYPE1f : KEY_TYPE0f)
    133 #define TH_ENT_KEY_KM_GET(u)                                        \
    134     soc_mem_field32_get(u, (mem), (ent),                            \
    135         (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? KEY_MODE0_LWRf : \
    136         x ? KEY_MODE1f : KEY_MODE0f)
    137 
    138 #define TH_ENT_MASK_IPADDR_GET(u, mask)                     \
    139     do {                                                    \
    140         int i;                                              \
    141         if (mem == alpm_tbl[alpmTblPvtCmodeL1P128]) {       \
    142             soc_field_t _msk_fld_p[] =                      \
    143                 {IP_ADDR_MASK0_LWRf, IP_ADDR_MASK1_LWRf,    \
    144                 IP_ADDR_MASK0_UPRf, IP_ADDR_MASK1_UPRf};    \
    145             for (i = 0; i < 4; i++) {                       \
    146                 mask[i] = soc_mem_field32_get(u, mem, ent,  \
    147                     _msk_fld_p[i]);                         \
    148             }                                               \
    149         } else {                                            \
    150             soc_field_t _msk_fld[] =                        \
    151                 {IP_ADDR_MASK0f, IP_ADDR_MASK1f};           \
    152             for (i = 0; i < 2-x; i++) {                     \
    153                 if (pkm == ALPM_PKM_32B &&                  \
    154                     x == 0 && i == 1) {                     \
    155                     continue;                               \
    156                 }                                           \
    157                 mask[i] = soc_mem_field32_get(u, mem, ent,  \
    158                     _msk_fld[(i+x)%2]);                     \
    159             }                                               \
    160         }                                                   \
    161     } while (0)
    162 
    163 /* Destination */
    164 #define TH_ENT_DEST_GET(u, ecmp, ipmc, nh_idx)                          \
    165     do {                                                                \
    166         soc_format_t fmt = DESTINATION_FORMATfmt;                       \
    167         uint32 dt0, dt1, dv;                                            \
    168         if ((mem) == alpm_tbl[alpmTblPvtCmodeL1P128]) {                 \
    169             dv = soc_mem_field32_get(u, (mem), (ent), DESTINATIONf);    \
    170         } else {                                                        \
    171             dv = soc_mem_field32_get(u, (mem), (ent),                   \
    172                 x ? DESTINATION1f : DESTINATION0f);                     \
    173         }                                                               \
    174         dt0 = soc_format_field32_get(u, fmt, &dv, DEST_TYPE0f);         \
    175         dt1 = soc_format_field32_get(u, fmt, &dv, DEST_TYPE1f);         \
    176         if (dt0 == 3) {   /* Should check dt0 first */                  \
    177             ecmp = 0;                                                   \
    178             ipmc = 0;                                                   \
    179             nh_idx = soc_format_field32_get(u, fmt, &dv, NEXT_HOP_INDEXf);\
    180         } else if (dt1 == 1) {                                          \
    181             ecmp = 1;                                                   \
    182             ipmc = 0;                                                   \
    183             nh_idx = soc_format_field32_get(u, fmt, &dv, ECMP_GROUPf);  \
    184         } else if (dt1 == 3) {                                          \
    185             ecmp = 0;                                                   \
    186             ipmc = 1;                                                   \
    187             nh_idx = soc_format_field32_get(u, fmt, &dv, IPMC_GROUPf);  \
    188         }                                                               \
    189     } while (0)
    190 
    191 /* Bucket idx */
    192 #define TH_ENT_BKT_PTR_GET(u)                                           \
    193     soc_mem_field32_get(u, (mem), (ent),                                \
    194         (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? ALG_BKT_PTRf :       \
    195         x ? ALG_BKT_PTR1f : ALG_BKT_PTR0f)
    196 #define TH_ENT_SUB_BKT_PTR_GET(u)                                       \
    197     soc_mem_field32_get(u, (mem), (ent),                                \
    198         (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? ALG_SUB_BKT_PTRf :   \
    199         x ? ALG_SUB_BKT_PTR1f : ALG_SUB_BKT_PTR0f)
    200 #define TH_ENT_DEFAULT_MISS_GET(u)                                      \
    201     soc_mem_field32_get(u, (mem), (ent),                                \
    202         (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? DEFAULT_MISSf :      \
    203         x ? DEFAULT_MISS1f : DEFAULT_MISS0f)
    204 
    205 /* Flex counter */
    206 #define TH_ENT_FC_BASE_ID_GET(u)                            \
    207     soc_mem_field32_get(u, (mem), (ent),                    \
    208         (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? FLEX_CTR_BASE_COUNTER_IDXf : \
    209         x ? FLEX_CTR_BASE_COUNTER_IDX1f : FLEX_CTR_BASE_COUNTER_IDX0f)
    210 #define TH_ENT_FC_MODE_GET(u)                               \
    211     soc_mem_field32_get(u, (mem), (ent),                    \
    212         (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? FLEX_CTR_OFFSET_MODEf :  \
    213         x ? FLEX_CTR_OFFSET_MODE1f : FLEX_CTR_OFFSET_MODE0f)
    214 #define TH_ENT_FC_POOL_GET(u)                               \
    215     soc_mem_field32_get(u, (mem), (ent),                    \
    216         (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? FLEX_CTR_POOL_NUMBERf :  \
    217         x ? FLEX_CTR_POOL_NUMBER1f : FLEX_CTR_POOL_NUMBER0f)
    218 
    219 /* IPMC */
    220 #define TH_ENT_MC_CPU_GET(u)                                \
    221     soc_mem_field32_get(u, (mem), (ent),                    \
    222         (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPUf :  \
    223         x ? IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f : IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f)
    224 #define TH_ENT_MC_DROP_GET(u)                               \
    225     soc_mem_field32_get(u, (mem), (ent),                    \
    226         (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? IPMC_EXPECTED_L3_IIF_MISMATCH_DROPf :  \
    227         x ? IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f : IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f)
    228 #define TH_ENT_MC_IIF_GET(u)                                \
    229     soc_mem_field32_get(u, (mem), (ent),                    \
    230         (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? EXPECTED_L3_IIFf :  \
    231         x ? EXPECTED_L3_IIF1f : EXPECTED_L3_IIF0f)
    232 
    233 /* ALPM bucket entry get */
    234 #define TH_BKT_VALID_GET(u)                                \
    235     soc_format_field32_get(u, (fmt), (ent), VALIDf)
    236 #define TH_BKT_LENGTH_GET(u)                               \
    237     soc_format_field32_get(u, (fmt), (ent), LENGTHf)
    238 #define TH_BKT_KEY_GET(u, key)                             \
    239     soc_format_field_get(u, (fmt), (ent), KEYf, key)
    240 #define TH_BKT_SUB_BKT_PTR_GET(u)                          \
    241     soc_format_field32_get(u, (fmt), (ent), SUB_BKT_PTRf)
    242 #define TH_BKT_CLASS_ID_GET(u)                             \
    243     soc_format_field32_get(u, (fmt), (ent), CLASS_IDf)
    244 #define TH_BKT_DST_DISCARD_GET(u)                          \
    245     soc_format_field32_get(u, (fmt), (ent), DST_DISCARDf)
    246 #define TH_BKT_RPE_GET(u)                                  \
    247     soc_format_field32_get(u, (fmt), (ent), RPEf)
    248 #define TH_BKT_PRI_GET(u)                                  \
    249     soc_format_field32_get(u, (fmt), (ent), PRIf)
    250 
    251 #define TH_BKT_DEST_GET(u, ecmp, ipmc, nh_idx)                          \
    252     do {                                                                \
    253         soc_format_t dfmt = DESTINATION_FORMATfmt;                      \
    254         uint32 dt0, dt1, dv;                                            \
    255         dv = soc_format_field32_get(u, (fmt), (ent), DESTINATIONf);     \
    256         dt0 = soc_format_field32_get(u, dfmt, &dv, DEST_TYPE0f);        \
    257         dt1 = soc_format_field32_get(u, dfmt, &dv, DEST_TYPE1f);        \
    258         if (dt0 == 3) {   /* Should check dt0 first */                  \
    259             ecmp = 0;                                                   \
    260             ipmc = 0;                                                   \
    261             nh_idx = soc_format_field32_get(u, dfmt, &dv, NEXT_HOP_INDEXf);\
    262         } else if (dt1 == 1) {                                          \
    263             ecmp = 1;                                                   \
    264             ipmc = 0;                                                   \
    265             nh_idx = soc_format_field32_get(u, dfmt, &dv, ECMP_GROUPf); \
    266         } else if (dt1 == 3) {                                          \
    267             ecmp = 0;                                                   \
    268             ipmc = 1;                                                   \
    269             nh_idx = soc_format_field32_get(u, dfmt, &dv, IPMC_GROUPf); \
    270         }                                                               \
    271     } while (0)
    272 
    273 /* Flex counter */
    274 #define TH_BKT_FC_BASE_ID_GET(u)                           \
    275     soc_format_field32_get(u, (fmt), (ent), FLEX_CTR_BASE_COUNTER_IDXf)
    276 #define TH_BKT_FC_MODE_GET(u)                              \
    277     soc_format_field32_get(u, (fmt), (ent), FLEX_CTR_OFFSET_MODEf)
    278 #define TH_BKT_FC_POOL_GET(u)                              \
    279     soc_format_field32_get(u, (fmt), (ent), FLEX_CTR_POOL_NUMBERf)
    280 
    281 /* Default FMT */
    282 #define ALPM_FMT_PKM_32B        (1)
    283 #define ALPM_FMT_PKM_64B        (2)
    284 #define ALPM_FMT_PKM_128        (3)
    285 #define ALPM_FMT_PKM_FLEX_32B   (4)
    286 #define ALPM_FMT_PKM_FLEX_64B   (5)
    287 #define ALPM_FMT_PKM_FLEX_128   (6)
    288 
    289 static _alpm_fmt_info_t th_fmt_info[ALPM_FMT_CNT] = {
    290         {
    291         ALPM_FMT_RTE,
    292         6,      /* 6 different formats(ROUTE FORMAT) */
    293         {       /* For fmt_ent_max */
    294             0,  /* FMT=0, means we cannot put entry in this format */
    295             6,  /* IPV4 */
    296             4,  /* IPV6_64 */
    297             2,  /* IPV6_128 */
    298             4,  /* IPV4_1 */
    299             3,  /* IPV6_64_1 */
    300             2,  /* IPV6_128 */
    301             0,
    302             0,
    303             0,
    304             0,
    305             0,
    306             0,
    307         },
    308         {       /* For fmt_pfx_len */
    309             0,
    310             32,  /* ROUTE FMT1 */
    311             64,
    312             128,
    313             32,
    314             64,
    315             128,
    316             0,
    317             0,
    318             0,
    319             0,
    320             0,
    321             0,
    322         },
    323         {       /* fmt_bnk */
    324             INVALIDfmt,
    325             L3_DEFIP_ALPM_ROUTE_FMT1_FULLfmt,
    326             L3_DEFIP_ALPM_ROUTE_FMT2_FULLfmt,
    327             L3_DEFIP_ALPM_ROUTE_FMT3_FULLfmt,
    328             L3_DEFIP_ALPM_ROUTE_FMT4_FULLfmt,
    329             L3_DEFIP_ALPM_ROUTE_FMT5_FULLfmt,
    330             L3_DEFIP_ALPM_ROUTE_FMT3_FULLfmt,
    331             INVALIDfmt,
    332             INVALIDfmt,
    333             INVALIDfmt,
    334             INVALIDfmt,
    335             INVALIDfmt,
    336             INVALIDfmt
    337         },
    338         {       /* fmt_ent */
    339             INVALIDfmt,
    340             L3_DEFIP_ALPM_ROUTE_FMT1fmt,
    341             L3_DEFIP_ALPM_ROUTE_FMT2fmt,
    342             L3_DEFIP_ALPM_ROUTE_FMT3fmt,
    343             L3_DEFIP_ALPM_ROUTE_FMT4fmt,
    344             L3_DEFIP_ALPM_ROUTE_FMT5fmt,
    345             L3_DEFIP_ALPM_ROUTE_FMT3fmt,
    346             INVALIDfmt,
    347             INVALIDfmt,
    348             INVALIDfmt,
    349             INVALIDfmt,
    350             INVALIDfmt,
    351             INVALIDfmt
    352         },
    353         {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0},
    354     },  /* ROUTE fmt info */
    355     {
    356         ALPM_FMT_RTE,
    357         6,      /* 6 different formats(ROUTE FORMAT) */
    358         {       /* For fmt_ent_max */
    359             0,  /* FMT=0, means we cannot put entry in this format */
    360             6,  /* IPV4 */
    361             4,  /* IPV6_64 */
    362             2,  /* IPV6_128 */
    363             4,  /* IPV4_1 */
    364             3,  /* IPV6_64_1 */
    365             2,  /* IPV6_128 */
    366             0,
    367             0,
    368             0,
    369             0,
    370             0,
    371             0,
    372         },
    373         {       /* For fmt_pfx_len */
    374             0,
    375             32,  /* ROUTE FMT1 */
    376             64,
    377             128,
    378             32,
    379             64,
    380             128,
    381             0,
    382             0,
    383             0,
    384             0,
    385             0,
    386             0,
    387         },
    388         {       /* fmt_bnk */
    389             INVALIDfmt,
    390             L3_DEFIP_ALPM_ROUTE_FMT1_FULLfmt,
    391             L3_DEFIP_ALPM_ROUTE_FMT2_FULLfmt,
    392             L3_DEFIP_ALPM_ROUTE_FMT3_FULLfmt,
    393             L3_DEFIP_ALPM_ROUTE_FMT4_FULLfmt,
    394             L3_DEFIP_ALPM_ROUTE_FMT5_FULLfmt,
    395             L3_DEFIP_ALPM_ROUTE_FMT3_FULLfmt,
    396             INVALIDfmt,
    397             INVALIDfmt,
    398             INVALIDfmt,
    399             INVALIDfmt,
    400             INVALIDfmt,
    401             INVALIDfmt
    402         },
    403         {       /* fmt_ent */
    404             INVALIDfmt,
    405             L3_DEFIP_ALPM_ROUTE_FMT1fmt,
    406             L3_DEFIP_ALPM_ROUTE_FMT2fmt,
    407             L3_DEFIP_ALPM_ROUTE_FMT3fmt,
    408             L3_DEFIP_ALPM_ROUTE_FMT4fmt,
    409             L3_DEFIP_ALPM_ROUTE_FMT5fmt,
    410             L3_DEFIP_ALPM_ROUTE_FMT3fmt,
    411             INVALIDfmt,
    412             INVALIDfmt,
    413             INVALIDfmt,
    414             INVALIDfmt,
    415             INVALIDfmt,
    416             INVALIDfmt
    417         },
    418         {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0},
    419     },  /* ROUTE fmt info */
    420 };
    421 
    422 soc_field_t th_alpm_ent_fld[] = {
    423     ENTRY_0f, ENTRY_1f, ENTRY_2f, ENTRY_3f,
    424     ENTRY_4f, ENTRY_5f, ENTRY_6f
    425 };
    426 
    427 static soc_mem_t th_alpm_hit_tbl_mem[] = {
    428     L3_DEFIP_ALPM_HIT_ONLYm
    429 };
    430 
    431 /* Should be the same order as _alpm_tbl_t */
    432 static soc_mem_t th_alpm_tbl[] = {
    433     INVALIDm,
    434     L3_DEFIPm,
    435     L3_DEFIPm,
    436     L3_DEFIP_PAIR_128m,
    437     L3_DEFIP_PAIR_128m,
    438     L3_DEFIP_ALPM_RAWm,
    439     L3_DEFIP_ALPM_RAWm,
    440     L3_DEFIP_ALPM_RAWm,
    441     L3_DEFIP_ALPM_RAWm,
    442     INVALIDm,
    443     INVALIDm,
    444     INVALIDm,
    445     INVALIDm
    446 };
    447 
    448 static soc_mem_t *alpm_tbl;
    449 
    450 /* Combined mode Level2 Table */
    451 static _alpm_bkt_pool_conf_t th_alpm_cmode_pool_l2 = {
    452     {NULL, NULL},  /* bnk_info, to be allocated */
    453     65536,  /* 16 Banks x 4K buckets */
    454     16,     /* 16 Banks per logical bucket */
    455     alpmTblBktCmodeL2,
    456     0,
    457     1,      /* Fixed FMT */
    458     NULL,
    459     &th_fmt_info[ALPM_FMT_RTE],
    460 };
    461 
    462 /* Parallel mode Level2 Table pool for Global Routes */
    463 static _alpm_bkt_pool_conf_t th_alpm_pmode_pool_l2 = {
    464     {NULL, NULL},  /* bnk_info, to be allocated */
    465     65536,  /* 8 Banks x 8K buckets */
    466     8,      /* 8 Banks per bucket */
    467     alpmTblBktPmodeL2,
    468     0,
    469     1,      /* Fixed FMT */
    470     NULL,
    471     &th_fmt_info[ALPM_FMT_RTE],
    472 };
    473 
    474 /* uRPF configuration */
    475 static _alpm_bkt_pool_conf_t th_alpm_urpf_cmode_pool_l2 = {
    476     {NULL, NULL},  /* bnk_info, to be allocated */
    477     32768,  /* 8 Banks x 4K buckets */
    478     8,      /* 8 Banks per logical bucket */
    479     alpmTblBktCmodeL2,
    480     0,
    481     1,      /* Fixed FMT */
    482     NULL,
    483     &th_fmt_info[ALPM_FMT_RTE],
    484 };
    485 
    486 static _alpm_bkt_pool_conf_t th_alpm_urpf_pmode_pool_gbl_l2 = {
    487     {NULL, NULL},  /* bnk_info, to be allocated */
    488     16384,  /* 4 Banks x 4K buckets */
    489     4,      /* 4 Banks per bucket */
    490     alpmTblBktPmodeGblL2,
    491     0,
    492     1,      /* Fixed FMT */
    493     NULL,
    494     &th_fmt_info[ALPM_FMT_RTE],
    495 };
    496 
    497 static _alpm_bkt_pool_conf_t th_alpm_urpf_pmode_pool_prt_l2 = {
    498     {NULL, NULL},  /* bnk_info, to be allocated */
    499     16384,  /* 4 Banks x 4K buckets */
    500     4,      /* 4 Banks per bucket */
    501     alpmTblBktPmodePrtL2,
    502     0,
    503     1,      /* Fixed FMT */
    504     NULL,
    505     &th_fmt_info[ALPM_FMT_RTE],
    506 };
    507 
    508 #if defined(BCM_HELIX5_SUPPORT)
    509 static _alpm_bkt_pool_conf_t hx5_alpm_cmode_pool_l2 = {
    510     {NULL, NULL},  /* bnk_info, to be allocated */
    511     24576,  /* 12 Banks x 2K buckets */
    512     12,     /* 12 Banks per logical bucket */
    513     alpmTblBktCmodeL2,
    514     0,
    515     1,      /* Fixed FMT */
    516     NULL,
    517     &th_fmt_info[ALPM_FMT_RTE],
    518 };
    519 
    520 /* Parallel mode Level2 Table pool for Global Routes */
    521 static _alpm_bkt_pool_conf_t hx5_alpm_pmode_pool_l2 = {
    522     {NULL, NULL},  /* bnk_info, to be allocated */
    523     24576,  /* 6 Banks x 4K buckets */
    524     6,      /* 6 Banks per bucket */
    525     alpmTblBktPmodeL2,
    526     0,
    527     1,      /* Fixed FMT */
    528     NULL,
    529     &th_fmt_info[ALPM_FMT_RTE],
    530 };
    531 
    532 /* uRPF configuration */
    533 static _alpm_bkt_pool_conf_t hx5_alpm_urpf_cmode_pool_l2 = {
    534     {NULL, NULL},  /* bnk_info, to be allocated */
    535     12288,  /* 6 Banks x 2K buckets */
    536     6,      /* 6 Banks per logical bucket */
    537     alpmTblBktCmodeL2,
    538     0,
    539     1,      /* Fixed FMT */
    540     NULL,
    541     &th_fmt_info[ALPM_FMT_RTE],
    542 };
    543 
    544 static _alpm_bkt_pool_conf_t hx5_alpm_urpf_pmode_pool_gbl_l2 = {
    545     {NULL, NULL},  /* bnk_info, to be allocated */
    546     6144,  /* 3 Banks x 2K buckets */
    547     3,      /* 3 Banks per bucket */
    548     alpmTblBktPmodeGblL2,
    549     0,
    550     1,      /* Fixed FMT */
    551     NULL,
    552     &th_fmt_info[ALPM_FMT_RTE],
    553 };
    554 
    555 static _alpm_bkt_pool_conf_t hx5_alpm_urpf_pmode_pool_prt_l2 = {
    556     {NULL, NULL},  /* bnk_info, to be allocated */
    557     6144,  /* 3 Banks x 2K buckets */
    558     3,      /* 3 Banks per bucket */
    559     alpmTblBktPmodePrtL2,
    560     0,
    561     1,      /* Fixed FMT */
    562     NULL,
    563     &th_fmt_info[ALPM_FMT_RTE],
    564 };
    565 #endif
    566 
    567 static _alpm_bkt_pool_conf_t th_alpm_pool0[SOC_MAX_NUM_DEVICES];
    568 static _alpm_bkt_pool_conf_t th_alpm_pool1[SOC_MAX_NUM_DEVICES];
    569 
    570 static _alpm_cb_t th_alpm_1cb_template = {
    571     0,          /* Unit */
    572     {
    573         NULL,               /* pvt_ctl[V4] */
    574         NULL,               /* pvt_ctl[V6] */
    575     },
    576     {                   /* Pivot Tables of this block */
    577         alpmTblPvtCmodeL1,
    578         alpmTblPvtCmodeL1,
    579         alpmTblInvalid
    580     },
    581     {   /* _alpm_bnk_conf_t */
    582         {NULL, NULL}, /* bnk_pool pointer */
    583         13,     /* 8K buckets = 13 bits */
    584         1,      /* Double Wide */
    585         8,      /* 8 physical banks per bucket */
    586         3,      /* 3 bits */
    587     },
    588     0                   /* Block 0 */
    589 };
    590 
    591 static _alpm_cb_t th_alpm_1cb_template_128b = {
    592     0,          /* Unit */
    593     {
    594         NULL,               /* pvt_ctl[V4] */
    595         NULL,               /* pvt_ctl[V6] */
    596     },
    597     {                   /* Pivot Tables of this block */
    598         alpmTblPvtCmodeL1,
    599         alpmTblPvtCmodeL1P128,
    600         alpmTblPvtCmodeL1P128
    601     },
    602     {   /* _alpm_bnk_conf_t */
    603         {NULL, NULL}, /* bnk_pool pointer */
    604         13,     /* 8K buckets = 13 bits */
    605         1,      /* Double Wide */
    606         8,      /* 8 physical banks per bucket */
    607         3,      /* 3 bits */
    608     },
    609     0                   /* Block 0 */
    610 };
    611 
    612 #if defined(BCM_HELIX5_SUPPORT)
    613 static _alpm_cb_t hx5_alpm_1cb_template = {
    614     0,          /* Unit */
    615     {
    616         NULL,               /* pvt_ctl[V4] */
    617         NULL,               /* pvt_ctl[V6] */
    618     },
    619     {                   /* Pivot Tables of this block */
    620         alpmTblPvtCmodeL1,
    621         alpmTblPvtCmodeL1,
    622         alpmTblInvalid
    623     },
    624     {   /* bnk_conf */
    625         {NULL, NULL}, /* bnk_pool pointer */
    626         12,     /* 4K buckets = 12 bits */
    627         1,      /* Double Wide */
    628         6,      /* 6 physical banks per bucket */
    629         3,      /* 3 bits */
    630         },
    631     0                   /* Block 0 */
    632 };
    633 
    634 static _alpm_cb_t hx5_alpm_1cb_template_128b = {
    635     0,          /* Unit */
    636     {
    637         NULL,               /* pvt_ctl[V4] */
    638         NULL,               /* pvt_ctl[V6] */
    639     },
    640     {                   /* Pivot Tables of this block */
    641         alpmTblPvtCmodeL1,
    642         alpmTblPvtCmodeL1P128,
    643         alpmTblPvtCmodeL1P128
    644     },
    645     {   /* bnk_conf */
    646         {NULL, NULL}, /* bnk_pool pointer */
    647         12,     /* 4K buckets = 12 bits */
    648         1,      /* Double Wide */
    649         6,      /* 6 physical banks per bucket */
    650         3,      /* 3 bits */
    651         },
    652     0                   /* Block 0 */
    653 };
    654 
    655 #endif
    656 int th_alpm_bkt_hit_write(int u, int vrf_id, _alpm_cb_t *acb,
    657                           _alpm_tbl_t tbl, int ent_idx, int hit_val);
    658 int th_alpm_ent_hit_move(int u, int vrf_id, _alpm_cb_t *acb,
    659                          _alpm_tbl_t tbl, int src_ent_idx, int dst_ent_idx);
    660 int th_alpm_bnk_hit_move(int u, int vrf_id, _alpm_cb_t *acb,
    661                          _alpm_bkt_info_t *bkt_info,
    662                          _alpm_tbl_t tbl, int src_idx, int dst_idx);
    663 int th_alpm_bnk_hit_clear(int u, int vrf_id, _alpm_cb_t *acb,
    664                           _alpm_bkt_info_t *bkt_info, _alpm_tbl_t tbl, int idx);
    665 static int
    666 th_alpm_hit_tbl_idx_get(int u, _alpm_cb_t *acb, _alpm_tbl_t tbl, int idx, int ent);
    667 
    668 /* Adjust config based on dynamic configuration */
    669 static int
    670 th_alpm_cfg_adjust(int u, _alpm_cb_t *acb)
    671 {
    672     int half_banks = 0;
    673 
    674     if (SOC_URPF_STATUS_GET(u) || ALPM_MODE_CHK(u, BCM_ALPM_MODE_PARALLEL)) {
    675         ACB_BKT_DW(acb) = 0;
    676     } else {
    677         ACB_BKT_DW(acb) = 1;
    678     }
    679 
    680     if (SOC_URPF_STATUS_GET(u) || ACB_BKT_DW(acb)) {
    681         /* Adjust bucket bits for Double wide mode and uRPF */
    682         ACB_BKT_BITS(acb) -= 1;
    683     }
    684 #if defined(BCM_HELIX5_SUPPORT)
    685     if (soc_feature(u, soc_feature_alpm_addr_xlate)) {
    686         if (soc_alpm_cmn_banks_get(u) == 4) {
    687             int pid;
    688             ACB_PHY_BNK_PER_BKT(acb) = ACB_PHY_BNK_PER_BKT(acb) * 2 / 3;
    689             ACB_BNK_BITS(acb) = ACB_BNK_BITS(acb) * 2 / 3;
    690             for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) {
    691                 _alpm_bkt_pool_conf_t *bp_conf = NULL;
    692                 bp_conf = ACB_BKT_POOL(acb, pid);
    693 
    694                 if (pid > 0 && bp_conf == ACB_BKT_POOL(acb, pid - 1)) {
    695                     continue;
    696                 }
    697                 BPC_BNK_CNT(bp_conf) = BPC_BNK_CNT(bp_conf) * 2 / 3;
    698                 BPC_BNK_PER_BKT(bp_conf) = BPC_BNK_PER_BKT(bp_conf) * 2 / 3;
    699             }
    700         }
    701         return BCM_E_NONE;
    702     }
    703 #endif
    704     if (SOC_IS_TRIDENT3X(u) && soc_alpm_cmn_banks_get(u) == 4) {
    705         half_banks = 1;
    706     }
    707 
    708     /* Half banks mode */
    709     if (half_banks) {
    710         int pid;
    711         /* Adjust _alpm_cb_t */
    712         ACB_PHY_BNK_PER_BKT(acb) >>= 1;
    713         ACB_BNK_BITS(acb) -= 1;
    714 
    715         /* Adjust _alpm_bkt_pool_conf_t */
    716         for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) {
    717             _alpm_bkt_pool_conf_t *bp_conf;
    718             bp_conf = ACB_BKT_POOL(acb, pid);
    719 
    720             if (pid > 0 && bp_conf == ACB_BKT_POOL(acb, pid-1)) {
    721                 continue;
    722             }
    723             BPC_BNK_CNT(bp_conf) >>= 1;
    724             BPC_BNK_PER_BKT(bp_conf) >>= 1;
    725         }
    726         ALPMC(u)->_alpm_half_banks = 1;
    727     }
    728 
    729     return BCM_E_NONE;
    730 }
    731 
    732 #define HX5_ALPM_BKT_ENT_MAX (6)
    733 #define HX5_ALPM_PHY_BKT_BITS (12)
    734 
    735 /* Convert <bnk>|<bkt> style index to TD3 style index */
    736 #define TH_MEM_TAB_IDX_CONVERT(u, acb, tbl, index)                  \
    737     do {                                                    \
    738         if (tbl >= alpmTblBktCmodeL2) {                     \
    739             int bkt, bnk;                                   \
    740             bkt = ALPM_IDX_TO_BKT(acb, index);              \
    741             bnk = ALPM_IDX_TO_BNK(acb, index);              \
    742             bkt = (bkt << ACB_BKT_DW(acb)) +                \
    743                   bnk / ACB_PHY_BNK_PER_BKT(acb);           \
    744             bnk = bnk % ACB_PHY_BNK_PER_BKT(acb);           \
    745             index = !soc_feature(u, soc_feature_alpm_addr_xlate) ?  \
    746                     (bkt << ACB_BNK_BITS(acb) | bnk) :              \
    747                     (bnk << HX5_ALPM_PHY_BKT_BITS | bkt);               \
    748         }                                                   \
    749     } while (0)
    750 
    751 int
    752 th_mem_phy_index_get(int u, _alpm_cb_t *acb, _alpm_tbl_t tbl, int index)
    753 {
    754     int phy_index;
    755 
    756     /* Convert index to TD3 style as below
    757      * -------------------------
    758      * |       bkt     |  bnk  |
    759      * -------------------------
    760      */
    761     TH_MEM_TAB_IDX_CONVERT(u, acb, tbl, index);
    762 
    763     phy_index = index;
    764     if (SOC_URPF_STATUS_GET(u)) {
    765         switch (tbl) {
    766             case alpmTblBktPmodeGblL2:
    767             case alpmTblBktPmodeGblL3:
    768                 /* Private(Pid 0)/Global(Pid 1),
    769                  * VRF=1 means Private(Pid 0) */
    770                 if (!soc_feature(u, soc_feature_alpm_addr_xlate)) {
    771                     phy_index = index + ACB_BNK_PER_BKT(acb, 1);
    772                 } else {
    773                     int phy_bnk;
    774                     int phy_bkt;
    775                     phy_bnk = phy_index >> HX5_ALPM_PHY_BKT_BITS;
    776                     phy_bkt = phy_index & ((1 << HX5_ALPM_PHY_BKT_BITS) -1);
    777                     phy_bnk += ACB_BNK_PER_BKT(acb, 1);
    778                     phy_index = (phy_bnk << HX5_ALPM_PHY_BKT_BITS) + phy_bkt;
    779                 }
    780                 break;
    781             default:
    782                 break;
    783         }
    784     }
    785     return phy_index;
    786 }
    787 
    788 int
    789 th_mem_read(int u, _alpm_cb_t *acb, _alpm_tbl_t tbl,
    790              int index, void *entry_data, int no_cache)
    791 {
    792     int rv = BCM_E_NONE;
    793     soc_mem_t mem;
    794 
    795     mem = alpm_tbl[tbl];
    796     index = th_mem_phy_index_get(u, acb, tbl, index);
    797 
    798     if (no_cache) {
    799         rv = soc_mem_read_no_cache(u, 0, mem, 0, MEM_BLOCK_ANY,
    800                                    index, entry_data);
    801     } else {
    802         rv = soc_mem_read(u, mem, MEM_BLOCK_ANY, index, entry_data);
    803     }
    804     if (BCM_SUCCESS(rv)) {
    805         acb->acb_cnt.c_mem[tbl][0]++;
    806     }
    807 
    808     return rv;
    809 }
    810 
    811 /* WAR for TD3 only */
    812 void
    813 th_mem_urpf_pvt_flexctr_set(int u, soc_mem_t mem, void *entry)
    814 {
    815     int i;
    816     soc_field_t fc_flds[] = {
    817         FLEX_CTR_POOL_NUMBER0f,
    818         FLEX_CTR_OFFSET_MODE0f,
    819         FLEX_CTR_BASE_COUNTER_IDX0f,
    820         FLEX_CTR_POOL_NUMBER1f,
    821         FLEX_CTR_OFFSET_MODE1f,
    822         FLEX_CTR_BASE_COUNTER_IDX1f,
    823         FLEX_CTR_POOL_NUMBERf,
    824         FLEX_CTR_OFFSET_MODEf,
    825         FLEX_CTR_BASE_COUNTER_IDXf
    826     };
    827     for (i = 0; i < (sizeof(fc_flds)/sizeof(fc_flds[0])); i++) {
    828         if (soc_mem_field_valid(u, mem, fc_flds[i])) {
    829             soc_mem_field32_set(u, mem, entry, fc_flds[i], 0);
    830         }
    831     }
    832 }
    833 
    834 void
    835 th_mem_urpf_pvt_def_rte_set(int u, soc_mem_t mem, void *entry)
    836 {
    837     int i;
    838     uint32 mask;
    839     soc_field_t msk_fld[] = {
    840         IP_ADDR_MASK0f,
    841         IP_ADDR_MASK1f,
    842         IP_ADDR_MASK1_UPRf
    843     };
    844 
    845     soc_field_t dft_fld[] = {
    846         DEFAULTROUTE0f,
    847         DEFAULTROUTE1f,
    848         DEFAULTROUTEf
    849     };
    850 
    851     for (i = 0; i < (sizeof(msk_fld)/sizeof(msk_fld[0])); i++) {
    852         if (soc_mem_field_valid(u, mem, msk_fld[i])) {
    853             mask = soc_mem_field32_get(u, mem, entry, msk_fld[i]);
    854             if (!mask) {
    855                 soc_mem_field32_set(u, mem, entry, dft_fld[i], 1);
    856             }
    857         }
    858     }
    859 
    860     return;
    861 }
    862 
    863 void
    864 th_mem_urpf_pvt_bkt_ptr_set(int u, soc_mem_t mem, void *entry)
    865 {
    866     int i;
    867     uint32 bkt_ptr;
    868     uint32 urpf_offset;
    869     soc_field_t bkt_fld[] = {
    870         ALG_BKT_PTR0f,
    871         ALG_BKT_PTR1f,
    872         ALG_BKT_PTRf
    873     };
    874     urpf_offset = soc_feature(u, soc_feature_alpm_addr_xlate) ? 2048 : 4096;
    875     for (i = 0; i < (sizeof(bkt_fld)/sizeof(bkt_fld[0])); i++) {
    876         if (soc_mem_field_valid(u, mem, bkt_fld[i])) {
    877             bkt_ptr = soc_mem_field32_get(u, mem, entry, bkt_fld[i]);
    878             if (bkt_ptr != 0) {
    879                 soc_mem_field32_set(u, mem, entry, bkt_fld[i], bkt_ptr + urpf_offset);
    880             }
    881         }
    882     }
    883 
    884     return;
    885 }
    886 
    887 void
    888 th_mem_urpf_bkt_flexctr_set(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node,
    889                             int log_idx, void *entry)
    890 {
    891     int i, eid, bnk;
    892     int vrf_id;
    893     uint8 fid;
    894     _alpm_bkt_info_t *bkt_info;
    895     soc_format_t bfmt, efmt;
    896     uint32 ent[17];
    897     soc_field_t fc_flds[] = {
    898         FLEX_CTR_POOL_NUMBERf,
    899         FLEX_CTR_OFFSET_MODEf,
    900         FLEX_CTR_BASE_COUNTER_IDXf
    901     };
    902 
    903 
    904     bkt_info = &PVT_BKT_INFO(pvt_node);
    905     vrf_id   = PVT_BKT_VRF(pvt_node);
    906     bnk = ALPM_IDX_TO_BNK(acb, log_idx);
    907     fid = bkt_info->bnk_fmt[bnk];
    908 
    909     bfmt = ACB_FMT_BNK(acb, vrf_id, fid);
    910     efmt = ACB_FMT_ENT(acb, vrf_id, fid);
    911     for (eid = 0; eid < ACB_FMT_ENT_MAX(acb, vrf_id, fid); eid++) {
    912         soc_format_field_get(u, bfmt, entry, th_alpm_ent_fld[eid], ent);
    913         for (i = 0; i < (sizeof(fc_flds)/sizeof(fc_flds[0])); i++) {
    914             if (soc_format_field_valid(u, efmt, fc_flds[i])) {
    915                 soc_format_field32_set(u, efmt, ent, fc_flds[i], 0);
    916             }
    917         }
    918         /* Write entry back to bank */
    919         soc_format_field_set(u, bfmt, entry, th_alpm_ent_fld[eid], ent);
    920     }
    921 }
    922 
    923 void
    924 th_mem_urpf_bkt_def_rte_set(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node,
    925                             int log_idx, void *entry)
    926 {
    927     int eid, bnk;
    928     int vrf_id;
    929     uint8 fid;
    930     _alpm_bkt_info_t *bkt_info;
    931     soc_format_t bfmt, efmt;
    932     uint32 ent[17];
    933 
    934     bkt_info = &PVT_BKT_INFO(pvt_node);
    935     vrf_id   = PVT_BKT_VRF(pvt_node);
    936     bnk = ALPM_IDX_TO_BNK(acb, log_idx);
    937     fid = bkt_info->bnk_fmt[bnk];
    938 
    939     bfmt = ACB_FMT_BNK(acb, vrf_id, fid);
    940     efmt = ACB_FMT_ENT(acb, vrf_id, fid);
    941     for (eid = 0; eid < ACB_FMT_ENT_MAX(acb, vrf_id, fid); eid++) {
    942         soc_format_field_get(u, bfmt, entry, th_alpm_ent_fld[eid], ent);
    943         if (soc_format_field32_get(u, efmt, ent, VALIDf) &&
    944             soc_format_field32_get(u, efmt, ent, LENGTHf) == 0) {
    945             soc_format_field32_set(u, efmt, ent, DEFAULTROUTEf, 1);
    946         }
    947         /* Write entry back to bank */
    948         soc_format_field_set(u, bfmt, entry, th_alpm_ent_fld[eid], ent);
    949     }
    950 }
    951 
    952 /* pvt_node is only used for writing pivot to bucket table  */
    953 int
    954 th_mem_write(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node,
    955              _alpm_tbl_t tbl, int index, void *entry_data)
    956 {
    957     int rv = BCM_E_NONE;
    958     int phy_index;
    959     soc_mem_t mem;
    960     void *entry = entry_data;
    961 
    962     mem = alpm_tbl[tbl];
    963     if (entry == NULL) {
    964         entry = soc_mem_entry_null(u, mem);
    965     }
    966     phy_index = th_mem_phy_index_get(u, acb, tbl, index);
    967 
    968     if (ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_WRITE_CACHE_ONLY) {
    969         _soc_mem_alpm_write_cache(u, mem, MEM_BLOCK_ALL, phy_index, entry);
    970     } else {
    971         rv = soc_mem_write(u, mem, MEM_BLOCK_ALL, phy_index, entry);
    972 #if defined (BCM_TRIDENT3_SUPPORT)
    973         if (tbl >= alpmTblBktCmodeL2) {
    974             int i;
    975             int8 fmt = 0;
    976             for (i = 0; i < ALPM_BPB_MAX; i++) {
    977                 fmt |= pvt_node->bkt_info.bnk_fmt[i];
    978             }
    979             _soc_trident3_alpm2_bnk_fmt_set(u, phy_index,
    980                 entry_data == NULL ? 0 : fmt);
    981         }
    982 #endif
    983         if (SOC_URPF_STATUS_GET(u)) {
    984             int urpf_index;
    985             urpf_index = phy_index + (soc_mem_index_count(u, mem) >> 1);
    986             if (soc_feature(u, soc_feature_alpm_addr_xlate)) {
    987                 if (tbl >= alpmTblBktCmodeL2) {
    988                     int phy_bnk;
    989                     int phy_bkt;
    990                     phy_bnk = phy_index >> HX5_ALPM_PHY_BKT_BITS;
    991                     phy_bkt = phy_index & ((1 << HX5_ALPM_PHY_BKT_BITS) -1);
    992                     phy_bkt += 1 << (HX5_ALPM_PHY_BKT_BITS - 1);
    993                     urpf_index = (phy_bnk << HX5_ALPM_PHY_BKT_BITS) + phy_bkt;
    994                 }
    995             }
    996             /* Pvt Table */
    997             if (entry_data != NULL) {
    998                 if (tbl >= alpmTblBktCmodeL2) {
    999                     if (alpm_util_route_type_get(u, NULL)) {
   1000                         th_mem_urpf_bkt_flexctr_set(u, acb, pvt_node,
   1001                                                     index, entry_data);
   1002                     }
   1003                     th_mem_urpf_bkt_def_rte_set(u, acb, pvt_node,
   1004                                                 index, entry_data);
   1005                 } else {
   1006                     if (alpm_util_route_type_get(u, NULL)) {
   1007                         th_mem_urpf_pvt_flexctr_set(u, mem, entry_data);
   1008                     }
   1009                     th_mem_urpf_pvt_def_rte_set(u, mem, entry_data);
   1010                     th_mem_urpf_pvt_bkt_ptr_set(u, mem, entry_data);
   1011                 }
   1012             }
   1013             rv = soc_mem_write(u, mem, MEM_BLOCK_ALL, urpf_index, entry);
   1014 #if defined (BCM_TRIDENT3_SUPPORT)
   1015             if (tbl >= alpmTblBktCmodeL2) {
   1016                 int i;
   1017                 int8 fmt = 0;
   1018                 for (i = 0; i < ALPM_BPB_MAX; i++) {
   1019                     fmt |= pvt_node->bkt_info.bnk_fmt[i];
   1020                 }
   1021                 _soc_trident3_alpm2_bnk_fmt_set(u, phy_index,
   1022                     entry_data == NULL ? 0 : fmt);
   1023             }
   1024 #endif
   1025         }
   1026     }
   1027 
   1028     if (BCM_SUCCESS(rv)) {
   1029         acb->acb_cnt.c_mem[tbl][1]++;
   1030         if (tbl >= alpmTblBktCmodeL2) {
   1031             if (pvt_node != NULL) {
   1032                 ACB_PVT_PTR(acb, pvt_node, index) =
   1033                     entry_data ? pvt_node : NULL;
   1034             }
   1035         }
   1036     }
   1037 
   1038     return rv;
   1039 }
   1040 
   1041 int
   1042 th_mem_bulk_write(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node,
   1043                   _alpm_tbl_t tbl, int *index, uint32 **entry_data, int count)
   1044 {
   1045     int i;
   1046     int rv = BCM_E_NONE;
   1047 
   1048     for (i = 0; i < count; i++) {
   1049         rv = th_mem_write(u, acb, pvt_node, tbl, index[i], entry_data[i]);
   1050         ALPM_IER(rv);
   1051     }
   1052 
   1053     return rv;
   1054 }
   1055 
   1056 /*
   1057 int
   1058 th_mem_bulk_write(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node,
   1059                   _alpm_tbl_t tbl, int *index, uint32 **entry_data, int count)
   1060 {
   1061     int i;
   1062     int phy_index[20];
   1063     int copyno[20];
   1064     soc_mem_t bulk_mem[20];
   1065     int rv = BCM_E_NONE;
   1066 
   1067     assert(count <= 20);
   1068 
   1069     for (i = 0; i < count; i++) {
   1070         phy_index[i] = th_mem_phy_index_get(u, acb, tbl, index[i]);
   1071         copyno[i] = MEM_BLOCK_ALL;
   1072         bulk_mem[i] = alpm_tbl[tbl];
   1073     }
   1074 
   1075     if (ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_WRITE_CACHE_ONLY) {
   1076         for (i = 0; i < count; i++) {
   1077             _soc_mem_alpm_write_cache(u, bulk_mem[i], copyno[i], phy_index[i],
   1078                                       entry_data[i]);
   1079         }
   1080     } else {
   1081         if (count <= ALPMC(u)->_alpm_bulk_wr_threshold) {
   1082             for (i = 0; i < count; i++) {
   1083                 rv = soc_mem_write(u, bulk_mem[i], copyno[i], phy_index[i],
   1084                                    entry_data[i]);
   1085                 ALPM_IER(rv);
   1086             }
   1087 
   1088             if (SOC_URPF_STATUS_GET(u)) {
   1089                 for (i = 0; i < count; i++) {
   1090                     int urpf_index;
   1091                     urpf_index = phy_index[i] +
   1092                         (soc_mem_index_count(u, bulk_mem[i]) >> 1);
   1093                     rv = soc_mem_write(u, bulk_mem[i], copyno[i], urpf_index,
   1094                                        entry_data[i]);
   1095                     ALPM_IER(rv);
   1096                 }
   1097             }
   1098 
   1099         }
   1100         else {
   1101             assert(0);
   1102             rv = soc_mem_bulk_write(u, bulk_mem, phy_index,
   1103                                     copyno, entry_data, count);
   1104         }
   1105     }
   1106 
   1107     if (BCM_SUCCESS(rv)) {
   1108         for (i = 0; i < count; i++) {
   1109             acb->acb_cnt.c_mem[tbl][1]++;
   1110             acb->acb_cnt.c_bulk_mem[tbl][1]++;
   1111 
   1112             if (pvt_node != NULL) {
   1113                 ACB_PVT_PTR(acb, pvt_node, index[i]) = pvt_node;
   1114             }
   1115         }
   1116     }
   1117 
   1118     return rv;
   1119 }
   1120 */
   1121 
   1122 /* ALPM related functions */
   1123 
   1124 static int
   1125 th_alpm_cb_cnt(int u)
   1126 {
   1127     int acb_cnt, alpm_enable;
   1128     alpm_enable = soc_property_get(u, spn_L3_ALPM_ENABLE, 2);
   1129 
   1130     if (alpm_enable) {
   1131         acb_cnt = 1;                    /* 1 ALPM Control Block */
   1132     } else {
   1133         acb_cnt = 0;
   1134     }
   1135 
   1136     return acb_cnt;
   1137 }
   1138 
   1139 void
   1140 th_alpm_ctrl_deinit(int u)
   1141 {
   1142     int i, j, pid, ipt, acb_cnt;
   1143     _alpm_cb_t *acb;
   1144 
   1145     acb_cnt = th_alpm_cb_cnt(u);
   1146     for (i = 0; i < acb_cnt; i++) {
   1147         acb = ACB(u, i);
   1148         if (acb != NULL) {
   1149             /* Free Bucket pool */
   1150             for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) {
   1151                 _alpm_bkt_pool_conf_t *bp_conf;
   1152 
   1153                 bp_conf = ACB_BKT_POOL(acb, pid);
   1154                 if (bp_conf->pvt_ptr != NULL) {
   1155                     alpm_util_free(bp_conf->pvt_ptr);
   1156                     bp_conf->pvt_ptr = NULL;
   1157                 }
   1158                 for (ipt = ALPM_IPT_V4; ipt < ALPM_IPT_CNT; ipt++) {
   1159                     if (ipt > ALPM_IPT_V4 &&
   1160                         BPC_BNK_INFO(bp_conf, ipt) ==
   1161                         BPC_BNK_INFO(bp_conf, ipt - 1)) {
   1162                         continue;
   1163                     }
   1164                     if (BPC_BNK_INFO(bp_conf, ipt) != NULL) {
   1165                         alpm_util_free(BPC_BNK_INFO(bp_conf, ipt));
   1166                     }
   1167                 }
   1168                 for (ipt = ALPM_IPT_V4; ipt < ALPM_IPT_CNT; ipt++) {
   1169                     BPC_BNK_INFO(bp_conf, ipt) = NULL;
   1170                 }
   1171             }
   1172 
   1173             for (j = 0; j < ALPM_IPT_CNT; j++) {
   1174                 if (acb->pvt_ctl[j] != NULL) {
   1175                     alpm_util_free(acb->pvt_ctl[j]);
   1176                     acb->pvt_ctl[j] = NULL;
   1177                 }
   1178             }
   1179 
   1180             alpm_util_free(acb);
   1181             ACB(u, i) = NULL;
   1182         }
   1183     }
   1184 
   1185     return ;
   1186 }
   1187 
   1188 static void
   1189 th_alpm_hw_mem_clear(int u, soc_mem_t mem)
   1190 {
   1191     int i;
   1192     uint8 *mbuf;
   1193     int size;
   1194     soc_mem_t clr_mem[2] = {INVALIDm, INVALIDm};
   1195 
   1196     /* Clear table with ECC view to make sure
   1197      * both data & ecc get cleared
   1198      *
   1199      * Clear L3_DEFIP_ALPM_RAWm as well to make sure
   1200      * memory cache gets cleared as well.
   1201      */
   1202     clr_mem[0] = mem;
   1203     if (mem == L3_DEFIP_ALPM_RAWm) {
   1204         clr_mem[1] = L3_DEFIP_ALPM_ECCm;
   1205     }
   1206 
   1207     for (i = 0; i < 2; i++) {
   1208         if (clr_mem[i] == INVALIDm) {
   1209             continue;
   1210         }
   1211 
   1212         ALPM_INFO(("ALPM clearing mem %s\n", SOC_MEM_NAME(u, clr_mem[i])));
   1213 
   1214         size = SOC_MEM_TABLE_BYTES(u, clr_mem[i]);
   1215         mbuf = soc_cm_salloc(u, size, "alpm_mem");
   1216         if (mbuf == NULL) {
   1217             ALPM_ERR(("th_alpm_hw_mem_clear alloc DMA memory failed\n"));
   1218             return ;
   1219         }
   1220         sal_memset(mbuf, 0, size);
   1221 
   1222         (void)soc_mem_write_range(u, clr_mem[i], MEM_BLOCK_ALL,
   1223                                   soc_mem_index_min(u, clr_mem[i]),
   1224                                   soc_mem_index_max(u, clr_mem[i]), mbuf);
   1225         soc_cm_sfree(u, mbuf);
   1226     }
   1227 
   1228     return ;
   1229 }
   1230 
   1231 static int
   1232 th_alpm_rpf_ctrl_init(int u)
   1233 {
   1234     int         i;
   1235     uint32      rval;
   1236     soc_reg_t   reg = L3_DEFIP_RPF_CONTROLr;
   1237 
   1238 #define FLDS_CNT    3
   1239     soc_field_t flds[FLDS_CNT] = {
   1240         LPM_MODEf,
   1241         LOOKUP_MODEf,
   1242         ENABLE_DOUBLE_WIDE_BUCKETS_FOR_IPV4f
   1243     };
   1244 
   1245     uint32 vals[FLDS_CNT] = {
   1246         1,
   1247         0,
   1248         1
   1249     };
   1250 
   1251     /* Adjust LOOKUP_MODEf value */
   1252     vals[1] = ALPM_MODE(u);
   1253     SOC_IF_ERROR_RETURN(READ_L3_DEFIP_RPF_CONTROLr(u, &rval));
   1254     for (i = 0; i < FLDS_CNT; i++) {
   1255         if (SOC_REG_FIELD_VALID(u, reg, flds[i])) {
   1256             soc_reg_field_set(u, reg, &rval, flds[i], vals[i]);
   1257         }
   1258     }
   1259     SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_RPF_CONTROLr(u, rval));
   1260 
   1261     return BCM_E_NONE;
   1262 }
   1263 
   1264 static int
   1265 th_alpm_key_sel_init(int u)
   1266 {
   1267     int i, urpf_enb, lpm_128b;
   1268     uint32 rval = 0;
   1269     soc_reg_t kselr = L3_DEFIP_KEY_SELr;
   1270 
   1271     /* URPF[bit1], 128B[bit0] */
   1272     int key_sel[4] = {
   1273         2,  /* 0x00b non-URPF + lpm-64b     */
   1274         0,  /* 0x01b non-URPF + lpm-128b    */
   1275         3,  /* 0x10b uRPF + lpm-64b         */
   1276         1   /* 0x11b uRPF + lpm-128b        */
   1277     };
   1278 
   1279     urpf_enb = !!SOC_URPF_STATUS_GET(u);
   1280     lpm_128b = !!SOC_ALPM_128B_ENABLE(u);
   1281 
   1282     if (soc_reg_field_valid(u, kselr, KEY_SEL_CAM0_1f)) {
   1283         i = lpm_128b;
   1284         soc_reg_field_set(u, kselr, &rval, KEY_SEL_CAM0_1f, key_sel[i]);
   1285         soc_reg_field_set(u, kselr, &rval, KEY_SEL_CAM2_3f, key_sel[i]);
   1286         soc_reg_field_set(u, kselr, &rval, KEY_SEL_CAM4_5f, key_sel[i]);
   1287         soc_reg_field_set(u, kselr, &rval, KEY_SEL_CAM6_7f, key_sel[i]);
   1288         if (urpf_enb) {
   1289             i = (urpf_enb << 1) | lpm_128b;
   1290             soc_reg_field_set(u, kselr, &rval, KEY_SEL_CAM4_5f, key_sel[i]);
   1291             soc_reg_field_set(u, kselr, &rval, KEY_SEL_CAM6_7f, key_sel[i]);
   1292         }
   1293     } else {
   1294         if (urpf_enb) {
   1295             soc_reg_field_set(u, kselr, &rval, URPF_LOOKUP_CAM4f, 0x1);
   1296             soc_reg_field_set(u, kselr, &rval, URPF_LOOKUP_CAM5f, 0x1);
   1297             soc_reg_field_set(u, kselr, &rval, URPF_LOOKUP_CAM6f, 0x1);
   1298             soc_reg_field_set(u, kselr, &rval, URPF_LOOKUP_CAM7f, 0x1);
   1299         }
   1300     }
   1301 
   1302     BCM_IF_ERROR_RETURN(WRITE_L3_DEFIP_KEY_SELr(u, rval));
   1303     return BCM_E_NONE;
   1304 }
   1305 
   1306 static int
   1307 th_alpm_cfg_init(int u)
   1308 {
   1309     soc_reg_t creg = L3_DEFIP_ALPM_CFGr;
   1310     uint32 rval = 0;
   1311     if (ALPM_TCAM_ZONED(u)) {
   1312         if (SOC_URPF_STATUS_GET(u)) {
   1313             /* 4 DIPs, 4 SIPs */
   1314             if (soc_reg_field_valid(u, creg, CAM0_1_SELf)) {
   1315                 /* *DIP */
   1316                 soc_reg_field_set(u, creg, &rval, CAM2_3_SELf, 1);
   1317                 /* VRF SIP */
   1318                 soc_reg_field_set(u, creg, &rval, CAM4_5_SELf, 2);
   1319                 /* *SIP */
   1320                 soc_reg_field_set(u, creg, &rval, CAM6_7_SELf, 3);
   1321             } else {
   1322                 /* *DIP */
   1323                 soc_reg_field_set(u, creg, &rval, TCAM2_SELf, 1);
   1324                 soc_reg_field_set(u, creg, &rval, TCAM3_SELf, 1);
   1325                 /* VRF SIP */
   1326                 soc_reg_field_set(u, creg, &rval, TCAM4_SELf, 2);
   1327                 soc_reg_field_set(u, creg, &rval, TCAM5_SELf, 2);
   1328                 /* *SIP */
   1329                 soc_reg_field_set(u, creg, &rval, TCAM6_SELf, 3);
   1330                 soc_reg_field_set(u, creg, &rval, TCAM7_SELf, 3);
   1331             }
   1332         } else {
   1333             if (soc_reg_field_valid(u, creg, CAM0_1_SELf)) {
   1334                 soc_reg_field_set(u, creg, &rval, CAM4_5_SELf, 1);
   1335                 soc_reg_field_set(u, creg, &rval, CAM6_7_SELf, 1);
   1336             } else {
   1337                 soc_reg_field_set(u, creg, &rval, TCAM4_SELf, 1);
   1338                 soc_reg_field_set(u, creg, &rval, TCAM5_SELf, 1);
   1339                 soc_reg_field_set(u, creg, &rval, TCAM6_SELf, 1);
   1340                 soc_reg_field_set(u, creg, &rval, TCAM7_SELf, 1);
   1341             }
   1342         }
   1343     } else {
   1344         if (SOC_URPF_STATUS_GET(u)) {
   1345             /* 4 DIPs, 4 SIPs */
   1346             if (soc_reg_field_valid(u, creg, CAM0_1_SELf)) {
   1347                 soc_reg_field_set(u, creg, &rval, CAM4_5_SELf, 2);
   1348                 soc_reg_field_set(u, creg, &rval, CAM6_7_SELf, 2);
   1349             } else {
   1350                 /* DIP */
   1351                 /* VRF SIP */
   1352                 soc_reg_field_set(u, creg, &rval, TCAM4_SELf, 2);
   1353                 soc_reg_field_set(u, creg, &rval, TCAM5_SELf, 2);
   1354                 soc_reg_field_set(u, creg, &rval, TCAM6_SELf, 2);
   1355                 soc_reg_field_set(u, creg, &rval, TCAM7_SELf, 2);
   1356             }
   1357         }
   1358     }
   1359     BCM_IF_ERROR_RETURN(WRITE_L3_DEFIP_ALPM_CFGr(u, rval));
   1360 
   1361     return BCM_E_NONE;
   1362 }
   1363 
   1364 
   1365 static int
   1366 th_alpm_hw_init(int u)
   1367 {
   1368     int rv = BCM_E_NONE;
   1369 
   1370     BCM_IF_ERROR_RETURN(th_alpm_rpf_ctrl_init(u));
   1371     BCM_IF_ERROR_RETURN(th_alpm_key_sel_init(u));
   1372     BCM_IF_ERROR_RETURN(th_alpm_cfg_init(u));
   1373 
   1374     return rv;
   1375 }
   1376 
   1377 int
   1378 th_alpm_ctrl_init(int u)
   1379 {
   1380     int rv = BCM_E_NONE;
   1381     int i, j, pid, acb_cnt, vrf_id_cnt;
   1382 
   1383     int alloc_sz;
   1384 #if 0
   1385     int sf, scale_factor = 1;
   1386 #endif
   1387 
   1388     soc_mem_t mem, allmems[20] = {INVALIDm};
   1389     int m, mem_cnt = 0;
   1390 
   1391     /*
   1392      *  b2(p1)  b1(p0)  bit0(128b)
   1393      * ---------------------------
   1394      *  0       0       0       -> 2-Level (64b)
   1395      *  0       0       1       -> 2-Level (128b)
   1396      */
   1397     _alpm_cb_t *acb_template[2] = {
   1398         &th_alpm_1cb_template,
   1399         &th_alpm_1cb_template_128b,
   1400     };
   1401 
   1402     _alpm_bkt_pool_conf_t *acb_bp_conf[8] = {
   1403         &th_alpm_pool0[u],
   1404         &th_alpm_pool0[u],
   1405         &th_alpm_pool0[u],
   1406         &th_alpm_pool0[u],
   1407     };
   1408 
   1409     _alpm_bkt_pool_conf_t *acb_urpf_bp_conf[8] = {
   1410         &th_alpm_pool0[u],
   1411         &th_alpm_pool0[u],
   1412         &th_alpm_pool0[u],
   1413         &th_alpm_pool1[u],
   1414     };
   1415 
   1416     _alpm_bkt_pool_conf_t *acb_bp_conf_template[8] = {
   1417         &th_alpm_cmode_pool_l2,
   1418         &th_alpm_pmode_pool_l2,
   1419         &th_alpm_cmode_pool_l2,
   1420         &th_alpm_pmode_pool_l2
   1421     };
   1422 
   1423     _alpm_bkt_pool_conf_t *acb_urpf_bp_conf_template[8] = {
   1424         &th_alpm_urpf_cmode_pool_l2,
   1425         &th_alpm_urpf_pmode_pool_prt_l2,
   1426         &th_alpm_urpf_cmode_pool_l2,
   1427         &th_alpm_urpf_pmode_pool_gbl_l2
   1428     };
   1429 
   1430     /* assert ALPM_MEM_ENT_MAX for largest TCAM/ALPM memory entry */
   1431     assert(ALPM_MEM_ENT_MAX * sizeof(uint32)
   1432            >= sizeof(defip_pair_128_entry_t));
   1433 
   1434     if (SOC_MEM_IS_VALID(u, L3_DEFIP_ALPM_RAWm)) {
   1435         alpm_tbl = &th_alpm_tbl[0];
   1436     }
   1437 
   1438 #if defined(BCM_HELIX5_SUPPORT)
   1439     if (soc_feature(u, soc_feature_alpm_addr_xlate)) {
   1440         acb_bp_conf_template[0] = &hx5_alpm_cmode_pool_l2;
   1441         acb_bp_conf_template[1] = &hx5_alpm_pmode_pool_l2;
   1442         acb_bp_conf_template[2] = &hx5_alpm_cmode_pool_l2;
   1443         acb_bp_conf_template[3] = &hx5_alpm_pmode_pool_l2;
   1444 
   1445         acb_urpf_bp_conf_template[0] = &hx5_alpm_urpf_cmode_pool_l2;
   1446         acb_urpf_bp_conf_template[1] = &hx5_alpm_urpf_pmode_pool_prt_l2;
   1447         acb_urpf_bp_conf_template[2] = &hx5_alpm_urpf_cmode_pool_l2;
   1448         acb_urpf_bp_conf_template[3] = &hx5_alpm_urpf_pmode_pool_gbl_l2;
   1449 
   1450         acb_template[0] = &hx5_alpm_1cb_template;
   1451         acb_template[1] = &hx5_alpm_1cb_template_128b;
   1452     }
   1453 #endif
   1454     /* Load scaling factor config
   1455      * 8 means valid factors are 1,2,4,8...128
   1456      */
   1457 #if 0
   1458     scale_factor = soc_property_get(u, "l3_alpm_scaling_factor", 1);
   1459     for (sf = 0; sf < 8; sf++) {
   1460         if (scale_factor == (1 << sf)) {
   1461             break;
   1462         }
   1463     }
   1464     if (sf >= 8) {
   1465         scale_factor = 1;
   1466         sf = 0;
   1467     }
   1468 #endif
   1469 
   1470     vrf_id_cnt = ALPM_VRF_ID_CNT(u);
   1471     acb_cnt = th_alpm_cb_cnt(u);
   1472     assert((acb_cnt * ALPM_PKM_CNT) < 20);
   1473 
   1474     for (i = 0; i < acb_cnt; i++) {
   1475         int idx;
   1476         _alpm_cb_t *acb = NULL;
   1477 
   1478         alloc_sz = sizeof(_alpm_cb_t);
   1479         ALPM_ALLOC_EG(acb, alloc_sz, "alpm_cb");
   1480         idx = (acb_cnt - 1) << 1 | (ALPM_128B(u) & 1);
   1481         sal_memcpy(acb, acb_template[idx], sizeof(_alpm_cb_t));
   1482         acb->unit = u;
   1483 
   1484         /**
   1485          *  -------
   1486          *  |2|1|0|
   1487          *  -------
   1488          *  Bit 0: Zoned: Parallel/Mixed: 1, Combined: 0
   1489          *  Bit 1: Private(Pid 0)/Global(Pid 1)
   1490          *  ---------
   1491  */
   1492         for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) {
   1493             idx = pid << 1 | !!ALPM_MODE_CHK(u, BCM_ALPM_MODE_PARALLEL);
   1494             if (SOC_URPF_STATUS_GET(u)) {
   1495                 ACB_BKT_POOL(acb, pid) = acb_urpf_bp_conf[idx];
   1496                 sal_memcpy(acb_urpf_bp_conf[idx],
   1497                            acb_urpf_bp_conf_template[idx],
   1498                            sizeof(_alpm_bkt_pool_conf_t));
   1499             } else {
   1500                 ACB_BKT_POOL(acb, pid) = acb_bp_conf[idx];
   1501                 sal_memcpy(acb_bp_conf[idx],
   1502                            acb_bp_conf_template[idx],
   1503                            sizeof(_alpm_bkt_pool_conf_t));
   1504             }
   1505         }
   1506 
   1507         /* Adjust ctrl bnk conf
   1508          * BPC should NOT be adjusted because they point to
   1509          * global storage
   1510          */
   1511         ALPM_IEG(th_alpm_cfg_adjust(u, acb));
   1512 
   1513 #define _CHK_IF_CLEAR_MEM(mem)                  \
   1514     do {                                        \
   1515         for (m = 0; m < mem_cnt; m++) {         \
   1516             if (allmems[m] == (mem)) {          \
   1517                 break;                          \
   1518             }                                   \
   1519         }                                       \
   1520         if (m == mem_cnt && mem != INVALIDm &&  \
   1521             soc_mem_index_count(u, mem) > 0) {  \
   1522             th_alpm_hw_mem_clear(u, (mem));    \
   1523             allmems[mem_cnt++] = (mem);         \
   1524         }                                       \
   1525     } while (0)
   1526 
   1527         for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) {
   1528             _alpm_bkt_pool_conf_t *bp_conf = ACB_BKT_POOL(acb, pid);
   1529             if (pid > 0 && ACB_BKT_POOL(acb, pid-1) == bp_conf) {
   1530                 continue;
   1531             }
   1532 
   1533             /* Adjust bucket count based on scaling factor */
   1534             /* BPC_BNK_CNT(bp_conf) /= scale_factor; */
   1535             alloc_sz = sizeof(_alpm_bnk_info_t);
   1536             ALPM_ALLOC_EG(BPC_BNK_INFO(bp_conf, ALPM_IPT_V4),
   1537                           alloc_sz, "bnk_bmp");
   1538             if (ALPM_128B(u) && ALPM_BKT_RSVD(u) &&
   1539                 ACB_IDX(acb) == acb_cnt - 1) {
   1540                 int rsvd_v6_bnks =
   1541                     BPC_BNK_CNT(bp_conf) * ALPM_BKT_RSVD_CNT(u) / 8192;
   1542                 ALPM_ALLOC_EG(
   1543                     BPC_BNK_INFO(bp_conf, ALPM_IPT_V6), alloc_sz, "bnk_bmp");
   1544                 /* reserved v6 bnks in v4 bitmap */
   1545                 SHR_BITSET_RANGE(
   1546                     BPC_BNK_BMP(bp_conf, ALPM_IPT_V4),
   1547                     BPC_BNK_CNT(bp_conf) - rsvd_v6_bnks,
   1548                     rsvd_v6_bnks);
   1549                 BPC_BNK_RSVD(bp_conf, ALPM_IPT_V4) = rsvd_v6_bnks;
   1550                 /* reserved v4 bnks in v6 bitmap */
   1551                 SHR_BITSET_RANGE(
   1552                     BPC_BNK_BMP(bp_conf, ALPM_IPT_V6), 0,
   1553                     BPC_BNK_CNT(bp_conf) - rsvd_v6_bnks);
   1554                 BPC_BNK_RSVD(bp_conf, ALPM_IPT_V6) =
   1555                     BPC_BNK_CNT(bp_conf) - rsvd_v6_bnks;
   1556             } else {
   1557                 BPC_BNK_INFO(bp_conf, ALPM_IPT_V6) =
   1558                     BPC_BNK_INFO(bp_conf, ALPM_IPT_V4);
   1559             }
   1560 
   1561             /* Reserve bucket 0 */
   1562             SHR_BITSET_RANGE(
   1563                 BPC_BNK_BMP(bp_conf, ALPM_IPT_V4), 0,
   1564                 BPC_BNK_PER_BKT(bp_conf));
   1565 
   1566             if (!SOC_WARM_BOOT(u)) {
   1567                 mem = alpm_tbl[BPC_BKT_TBL(bp_conf)];
   1568                 _CHK_IF_CLEAR_MEM(mem);
   1569             }
   1570 
   1571             if (bp_conf->pvt_ptr == NULL) {
   1572                 alloc_sz = BPC_BNK_CNT(bp_conf);
   1573                 alloc_sz = sizeof(void *) * alloc_sz;
   1574                 ALPM_ALLOC_EG(bp_conf->pvt_ptr, alloc_sz, "pvt_ptr");
   1575             }
   1576         }
   1577 
   1578         /* Adjust bucket count based on scaling factor */
   1579         /* ALPM_IDX_BNK_SHIFT(acb) -= sf; */
   1580 
   1581         /* Per instance structure init */
   1582         alloc_sz = vrf_id_cnt * sizeof(_alpm_pvt_ctrl_t);
   1583         for (j = 0; j < ALPM_IPT_CNT; j++) {
   1584             ALPM_ALLOC_EG(
   1585                 acb->pvt_ctl[j], alloc_sz, "pvt_ctl");
   1586         }
   1587         for (j = 0; j < ALPM_PKM_CNT; j++) {
   1588             if (!SOC_WARM_BOOT(u)) {
   1589                 mem = alpm_tbl[acb->pvt_tbl[j]];
   1590                 _CHK_IF_CLEAR_MEM(mem);
   1591             }
   1592         }
   1593 
   1594         ACB(u, i) = acb;
   1595     }
   1596 
   1597     /* Obtain TCAM table skip (invalid or duplicated) per */
   1598     for (i = 0; i < ALPM_PKM_CNT; i++) {
   1599         if (alpm_tbl[ACB_TOP(u)->pvt_tbl[i]] == INVALIDm) {
   1600             ALPM_TCAM_TBL_SKIP(u, i) = TRUE; /* invalid */
   1601             continue;
   1602         } else {
   1603             ALPM_TCAM_TBL_SKIP(u, i) = FALSE;
   1604         }
   1605 
   1606         for (j = 0; j < i; j++) {
   1607             if (alpm_tbl[ACB_TOP(u)->pvt_tbl[i]] ==
   1608                 alpm_tbl[ACB_TOP(u)->pvt_tbl[j]]) {
   1609                 ALPM_TCAM_TBL_SKIP(u, j) = TRUE; /* duplicated */
   1610                 break;
   1611             }
   1612         }
   1613     }
   1614 
   1615     ALPM_TCAM_HB_IS_PTR(u) = TRUE;
   1616 
   1617     ACB_CNT(u) = acb_cnt;
   1618 
   1619     if (!SOC_WARM_BOOT(u)) {
   1620         rv = th_alpm_hw_init(u);
   1621     }
   1622 
   1623     return rv;
   1624 
   1625 bad:
   1626     th_alpm_ctrl_deinit(u);
   1627     return rv;
   1628 }
   1629 
   1630 /* ALPM ctrl cleanup (UNAVAIL for faster delete_all) */
   1631 int
   1632 th_alpm_ctrl_cleanup(int u)
   1633 {
   1634     return BCM_E_UNAVAIL;
   1635 }
   1636 
   1637 /* L3_DEFIP_ALPM_ROUTE_BANK_FMT1fmt
   1638  *   -> ENTRY0f: L3_DEFIP_ALPM_ROUTE_FMT1fmt
   1639  *        -> PREFIXf
   1640  *        -> ASSOC_DATAf: ASSOC_DATA_REDUCEDfmt
   1641  *             -> DEST_TYPEf
   1642  *             -> DESTINATIONf
   1643  *
   1644  *        -> ASSOC_DATAf: ASSOC_DATA_FULLfmt
   1645  *             -> DEST_TYPEf
   1646  *             -> DESTINATIONf
   1647  *             -> PRIf
   1648  *             -> RPEf
   1649  *             -> DST_DISCARDf
   1650  *             -> CLASS_IDf
   1651  *             -> FLEX_CTR_POOL_NUMBERf
   1652  *             -> FLEX_CTR_OFFSET_MODEf
   1653  *             -> FLEX_CTR_BASE_COUNTER_IDXf
   1654  */
   1655 
   1656 static int8
   1657 th_alpm_bnk_fmt_get(int u, _alpm_cb_t *acb,
   1658                      _alpm_bkt_info_t *bkt_info, int ent_idx)
   1659 {
   1660     int bnk_idx;
   1661 
   1662     bnk_idx = ALPM_IDX_TO_BNK(acb, ent_idx);
   1663     return bkt_info->bnk_fmt[bnk_idx];
   1664 }
   1665 
   1666 static void
   1667 th_alpm_ent_assemble(int u, _alpm_cb_t *acb,
   1668                       _alpm_pvt_node_t *pvt_node, int ent_idx,
   1669                       _bcm_defip_cfg_t *lpm_cfg, uint32 *entry)
   1670 {
   1671     int vrf_id, ipt;
   1672     int rmode, offset;
   1673     int8 fmt_tp;
   1674 
   1675     uint32 key[5] = {0};
   1676     uint32 fent[ALPM_ENT_WORDS_MAX] = {0};
   1677     soc_format_t ent_fmt, bnk_fmt;
   1678 
   1679     vrf_id  = ALPM_LPM_VRF_ID(u, lpm_cfg);
   1680     ipt     = ALPM_LPM_IPT(u, lpm_cfg);
   1681     fmt_tp  = th_alpm_bnk_fmt_get(u, acb, &PVT_BKT_INFO(pvt_node), ent_idx);
   1682     ent_fmt = ACB_FMT_ENT(acb, vrf_id, fmt_tp);
   1683 
   1684 #define _FMT32_SET(field, value) \
   1685     soc_format_field32_set(u, ent_fmt, fent, (field), (value))
   1686 
   1687     _FMT32_SET(VALIDf, 1);
   1688     /* TD3TBD */
   1689     _FMT32_SET(SUB_BKT_PTRf, 0);
   1690     /* Associated-Data */
   1691     if (soc_feature(u, soc_feature_generic_dest)) {
   1692         soc_format_t dst_fmt = DESTINATION_FORMATfmt;
   1693         uint32 dst_fmt_val = 0;
   1694         if (lpm_cfg->defip_flags & BCM_L3_MULTIPATH) {
   1695             soc_format_field32_set(u, dst_fmt, &dst_fmt_val, DEST_TYPE1f, 1);
   1696             soc_format_field32_set(u, dst_fmt, &dst_fmt_val, ECMP_GROUPf,
   1697                                    lpm_cfg->defip_ecmp_index);
   1698         } else if (!(lpm_cfg->defip_flags & BCM_L3_IPMC)) {
   1699             soc_format_field32_set(u, dst_fmt, &dst_fmt_val, DEST_TYPE0f, 3);
   1700             soc_format_field32_set(u, dst_fmt, &dst_fmt_val, NEXT_HOP_INDEXf,
   1701                                    lpm_cfg->defip_ecmp_index);
   1702         }
   1703         _FMT32_SET(DESTINATIONf, dst_fmt_val);
   1704     } else {
   1705         if (lpm_cfg->defip_flags & BCM_L3_MULTIPATH) {
   1706             _FMT32_SET(ECMPf, 1);
   1707             _FMT32_SET(ECMP_PTRf, lpm_cfg->defip_ecmp_index);
   1708         } else if (!(lpm_cfg->defip_flags & BCM_L3_IPMC)) {
   1709             _FMT32_SET(NEXT_HOP_INDEXf, lpm_cfg->defip_ecmp_index);
   1710         }
   1711     }
   1712     _FMT32_SET(PRIf, lpm_cfg->defip_prio);
   1713     _FMT32_SET(RPEf, lpm_cfg->defip_flags & BCM_L3_RPE ? 1 : 0);
   1714     _FMT32_SET(DST_DISCARDf, lpm_cfg->defip_flags & BCM_L3_DST_DISCARD ? 1 : 0);
   1715     _FMT32_SET(CLASS_IDf, lpm_cfg->defip_lookup_class);
   1716     _FMT32_SET(SUB_BKT_PTRf, PVT_SUB_BKT_IDX(pvt_node));
   1717 
   1718     /* Flex Counter */
   1719     rmode = ACB_VRF_DB_TYPE(u, acb, vrf_id, ipt);
   1720     if (rmode) {
   1721         _FMT32_SET(FLEX_CTR_POOL_NUMBERf, lpm_cfg->defip_flex_ctr_pool);
   1722         _FMT32_SET(FLEX_CTR_OFFSET_MODEf, lpm_cfg->defip_flex_ctr_mode);
   1723         _FMT32_SET(FLEX_CTR_BASE_COUNTER_IDXf, lpm_cfg->defip_flex_ctr_base_id);
   1724     }
   1725 
   1726     /* Key & Length */
   1727     /*
   1728      * 128B:
   1729      *   ip6[0]            ----          ip6[15]
   1730      *   ffff:ffff:0000:0000:0000:0000:0000:0000
   1731      *   prefix[7] prefix[6] prefix[5] prefix[4] ... prefix[0]
   1732      * 64B:
   1733      *                       ip6[0] ---- ip6[7]
   1734      *                       ffff:ffff:0000:0000
   1735      *   prefix[7] prefix[6] prefix[5] prefix[4] ... prefix[0]
   1736      * 32B:
   1737      *                                 ip_addr
   1738      *                                 c0a80101
   1739      *   prefix[7] prefix[6] prefix[5] prefix[4] ... prefix[0]
   1740      */
   1741     alpm_util_cfg_to_key(u, ipt, lpm_cfg, key);
   1742     if (ALPM_IS_IPV6(ipt)) {
   1743         if (fmt_tp == ALPM_FMT_PKM_64B || fmt_tp == ALPM_FMT_PKM_FLEX_64B) {
   1744             key[0] = key[2];
   1745             key[1] = key[3];
   1746             key[2] = key[3] = 0;
   1747         }
   1748     }
   1749 
   1750     soc_format_field_set(u, ent_fmt, fent, KEYf, key);
   1751     _FMT32_SET(LENGTHf, lpm_cfg->defip_sub_len);
   1752 
   1753     offset  = ALPM_IDX_TO_ENT(ent_idx);
   1754     bnk_fmt = ACB_FMT_BNK(acb, vrf_id, fmt_tp);
   1755     soc_format_field_set(u, bnk_fmt, entry, th_alpm_ent_fld[offset], fent);
   1756 
   1757 #undef _FMT32_SET
   1758 
   1759     return ;
   1760 
   1761 }
   1762 
   1763 int
   1764 th_alpm_ent_pfx_len_get(int u, _alpm_cb_t *acb,
   1765                          _alpm_pvt_node_t *pvt_node, int ent_idx)
   1766 {
   1767     int    rv;
   1768     int    ent_id, pfx_len = -1;
   1769     int8   fmt_tp;
   1770     uint32 bnkb[17];
   1771     uint32 entb[17] = {0};
   1772     soc_format_t bnk_fmt, ent_fmt;
   1773     _alpm_bkt_pool_conf_t *bp_conf;
   1774 
   1775     bp_conf = ACB_BKT_VRF_POOL(acb, PVT_BKT_VRF(pvt_node));
   1776     /* Get Bank data: bnkb */
   1777     rv = th_mem_read(u, acb, BPC_BKT_TBL(bp_conf),
   1778                       ALPM_TAB_IDX_GET(ent_idx), bnkb, FALSE);
   1779     if (BCM_SUCCESS(rv)) {
   1780         fmt_tp = th_alpm_bnk_fmt_get(u, acb, &PVT_BKT_INFO(pvt_node), ent_idx);
   1781         bnk_fmt = BPC_FMT_BNK(bp_conf, fmt_tp);
   1782         ent_id  = ALPM_IDX_TO_ENT(ent_idx);
   1783 
   1784         /* Get Entry data: entb */
   1785         (void)soc_format_field_get(u, bnk_fmt, bnkb,
   1786                                    th_alpm_ent_fld[ent_id], entb);
   1787         /* Get PREFIXf Field data: tmpf */
   1788         ent_fmt = BPC_FMT_ENT(bp_conf, fmt_tp);
   1789         pfx_len = soc_format_field32_get(u, ent_fmt, entb, LENGTHf);
   1790     }
   1791 
   1792     return pfx_len;
   1793 }
   1794 
   1795 void
   1796 th_alpm_ent_copy(int u, int vrf_id, _alpm_cb_t *acb, uint32 *sb_ent, uint32 *db_ent,
   1797                   _alpm_bkt_info_t *sbinfo, _alpm_bkt_info_t *dbinfo,
   1798                   uint32 src_pvt_len, uint32 dst_pvt_len,
   1799                   uint32 src_idx, uint32 dst_idx)
   1800 {
   1801     int8 src_fid, dst_fid;
   1802     uint32 src_eid, dst_eid;
   1803     uint32 se_ent[17] = {0};
   1804     uint32 de_ent[17] = {0};
   1805 
   1806     soc_format_t sb_fmt, db_fmt;
   1807 
   1808     /* Retrieve src entry */
   1809     src_fid = th_alpm_bnk_fmt_get(u, acb, sbinfo, src_idx);
   1810     src_eid = ALPM_IDX_TO_ENT(src_idx);
   1811     sb_fmt  = ACB_FMT_BNK(acb, vrf_id, src_fid);
   1812     soc_format_field_get(u, sb_fmt, sb_ent, th_alpm_ent_fld[src_eid], se_ent);
   1813 
   1814     dst_fid = th_alpm_bnk_fmt_get(u, acb, dbinfo, dst_idx);
   1815     dst_eid = ALPM_IDX_TO_ENT(dst_idx);
   1816     db_fmt  = ACB_FMT_BNK(acb, vrf_id, dst_fid);
   1817 
   1818     /* Copy entry */
   1819     if (sb_fmt != db_fmt) {
   1820         assert(0);
   1821     } else {
   1822         sal_memcpy(de_ent, se_ent, sizeof(de_ent));
   1823         if (BI_SUB_BKT_IDX(sbinfo) != BI_SUB_BKT_IDX(dbinfo)) {
   1824             soc_format_field32_set(u, ACB_FMT_ENT(acb, vrf_id, dst_fid), de_ent,
   1825                                    SUB_BKT_PTRf, BI_SUB_BKT_IDX(dbinfo));
   1826         }
   1827     }
   1828 
   1829     /* Write entry back to bank */
   1830     soc_format_field_set(u, db_fmt, db_ent, th_alpm_ent_fld[dst_eid], de_ent);
   1831 
   1832     return ;
   1833 }
   1834 
   1835 int
   1836 th_alpm_bkt_bnk_write(int u, _alpm_cb_t *acb,
   1837                        _alpm_pvt_node_t *pvt_node,
   1838                        _bcm_defip_cfg_t *lpm_cfg, int ent_idx, uint32 write_flags)
   1839 {
   1840     int rv, index;
   1841     uint32 entry[ALPM_ENT_WORDS_MAX] = {0};
   1842     _alpm_bkt_pool_conf_t *bp_conf = ACB_BKT_VRF_POOL(acb, PVT_BKT_VRF(pvt_node));
   1843 
   1844     index   = ALPM_TAB_IDX_GET(ent_idx);
   1845 
   1846     rv = th_mem_read(u, acb, BPC_BKT_TBL(bp_conf), index, entry, FALSE);
   1847     if (BCM_SUCCESS(rv)) {
   1848         th_alpm_ent_assemble(u, acb, pvt_node, ent_idx, lpm_cfg, entry);
   1849         rv = th_mem_write(u, acb, pvt_node, BPC_BKT_TBL(bp_conf), index, entry);
   1850     }
   1851 
   1852     return rv;
   1853 }
   1854 
   1855 static int
   1856 th_alpm_bkt_bnk_shrink(int u, _alpm_cb_t *acb,
   1857                         _alpm_pvt_node_t *pvt_node, uint8 sbnk,
   1858                         uint8 dbnk, _alpm_bkt_pfx_arr_t *pfx_arr)
   1859 {
   1860     int i, j, k, rv = 0;
   1861     int sepb, depb;
   1862     int vrf_id;
   1863     int8 src_fid, dst_fid;
   1864 
   1865     soc_format_t sb_fmt, db_fmt;
   1866 
   1867     uint32 tmp_idx, stab_idx, dtab_idx;
   1868     _alpm_bkt_info_t *bkt_info = NULL;
   1869 
   1870     uint32 srcbnke[17];
   1871     uint32 nullent[17];
   1872     uint32 dstbnke[17];
   1873     uint32 tempent[17];
   1874 
   1875     /* Bulk Write */
   1876     int bulk_idx[2];
   1877     uint32 *bulk_ent[2];
   1878 
   1879     _alpm_bkt_pool_conf_t *bp_conf;
   1880 
   1881     vrf_id = PVT_BKT_VRF(pvt_node);
   1882     bp_conf = ACB_BKT_VRF_POOL(acb, vrf_id);
   1883 
   1884     bkt_info = &PVT_BKT_INFO(pvt_node);
   1885     src_fid  = bkt_info->bnk_fmt[sbnk];
   1886     dst_fid  = bkt_info->bnk_fmt[dbnk];
   1887     sepb     = ACB_FMT_ENT_MAX(acb, vrf_id, src_fid);
   1888     depb     = ACB_FMT_ENT_MAX(acb, vrf_id, dst_fid);
   1889 
   1890     if (bkt_info->vet_bmp[dbnk] == 0) {
   1891         /* Move from entire from_bnk to to_bnk */
   1892         stab_idx = ALPM_TAB_IDX_GET_BI_BNK(acb, bkt_info, sbnk);
   1893         dtab_idx = ALPM_TAB_IDX_GET_BI_BNK(acb, bkt_info, dbnk);
   1894 
   1895         rv = th_mem_read(u, acb, BPC_BKT_TBL(bp_conf),
   1896                           stab_idx, srcbnke, FALSE);
   1897         ALPM_IER(rv);
   1898 
   1899         bulk_idx[0] = dtab_idx;
   1900         bulk_idx[1] = stab_idx;
   1901         bulk_ent[0] = srcbnke;
   1902         bulk_ent[1] = nullent;
   1903 
   1904         sal_memset(nullent, 0, sizeof(nullent));
   1905         rv = th_mem_bulk_write(u, acb, pvt_node, BPC_BKT_TBL(bp_conf),
   1906                                bulk_idx, bulk_ent, 2);
   1907         ALPM_IER(rv);
   1908 
   1909         sal_memset(srcbnke, 0, sizeof(srcbnke));
   1910         /* Invalidate bank from */
   1911         rv = th_mem_write(u, acb, pvt_node, BPC_BKT_TBL(bp_conf),
   1912                            stab_idx, srcbnke);
   1913         ALPM_IER(rv);
   1914 
   1915         bkt_info->vet_bmp[dbnk] = bkt_info->vet_bmp[sbnk];
   1916         bkt_info->vet_bmp[sbnk] = 0;
   1917         bkt_info->bnk_fmt[dbnk] = src_fid;
   1918 
   1919         /* Update ent_idx of prefix */
   1920         for (i = 0; i < pfx_arr->pfx_cnt; i++) {
   1921             tmp_idx = pfx_arr->pfx[i]->ent_idx;
   1922             if (ALPM_IDX_TO_BNK(acb, tmp_idx) == sbnk) {
   1923                 pfx_arr->pfx[i]->ent_idx =
   1924                     ALPM_IDX_MAKE(acb, bkt_info, dbnk,
   1925                     ALPM_IDX_TO_ENT(tmp_idx));
   1926             }
   1927         }
   1928 
   1929         ALPM_INFO(("**ACB(%d).BNK.MRG: RBBE from(%d %d %d *) to(%d %d %d *)\n",
   1930                    ACB_IDX(acb),
   1931                    PVT_ROFS(pvt_node),
   1932                    PVT_BKT_IDX(pvt_node), sbnk,
   1933                    PVT_ROFS(pvt_node),
   1934                    PVT_BKT_IDX(pvt_node), dbnk));
   1935 
   1936         return rv;
   1937     }
   1938 
   1939     /* Merge */
   1940     stab_idx = ALPM_TAB_IDX_GET_BI_BNK(acb, bkt_info, sbnk);
   1941     rv = th_mem_read(u, acb, BPC_BKT_TBL(bp_conf),
   1942                       stab_idx, srcbnke, FALSE);
   1943     ALPM_IER(rv);
   1944     dtab_idx = ALPM_TAB_IDX_GET_BI_BNK(acb, bkt_info, dbnk);
   1945     rv = th_mem_read(u, acb, BPC_BKT_TBL(bp_conf),
   1946                       dtab_idx, dstbnke, FALSE);
   1947     ALPM_IER(rv);
   1948 
   1949     sb_fmt = ACB_FMT_BNK(acb, vrf_id, src_fid);
   1950     db_fmt = ACB_FMT_BNK(acb, vrf_id, dst_fid);
   1951     for (i = 0; i < depb; i++) {
   1952         /* to entry i */
   1953         if (bkt_info->vet_bmp[dbnk] & (1 << i)) {
   1954             continue;
   1955         }
   1956         for (j = 0; j < sepb; j++) {
   1957             if (!(bkt_info->vet_bmp[sbnk] & (1 << j))) {
   1958                 continue;
   1959             }
   1960             /* from entry j */
   1961             if (sb_fmt != db_fmt) {
   1962                 uint32 src_idx, dst_idx;
   1963                 src_idx = ALPM_IDX_MAKE(acb, bkt_info, sbnk, j);
   1964                 dst_idx = ALPM_IDX_MAKE(acb, bkt_info, dbnk, i);
   1965                 th_alpm_ent_copy(u, vrf_id, acb, srcbnke, dstbnke,
   1966                             &PVT_BKT_INFO(pvt_node),
   1967                             &PVT_BKT_INFO(pvt_node),
   1968                             PVT_KEY_LEN(pvt_node),
   1969                             PVT_KEY_LEN(pvt_node),
   1970                             src_idx, dst_idx);
   1971             } else {
   1972                 sal_memset(tempent, 0, sizeof(tempent));
   1973                 (void)soc_format_field_get(u, sb_fmt, srcbnke,
   1974                                            th_alpm_ent_fld[j], tempent);
   1975                 (void)soc_format_field_set(u, db_fmt, dstbnke,
   1976                                            th_alpm_ent_fld[i], tempent);
   1977             }
   1978             /* Invalidate entry j */
   1979             sal_memset(nullent, 0, sizeof(nullent));
   1980             (void)soc_format_field_set(u, sb_fmt, srcbnke,
   1981                                        th_alpm_ent_fld[j], nullent);
   1982 
   1983             bkt_info->vet_bmp[sbnk] &= ~(1 << j);
   1984             bkt_info->vet_bmp[dbnk] |= (1 << i);
   1985 
   1986             ALPM_INFO((
   1987                 "**ACB(%d).BNK.MRG: RBBE from(%d %d %d %d) to(%d %d %d %d)\n",
   1988                 ACB_IDX(acb),
   1989                 PVT_ROFS(pvt_node), PVT_BKT_IDX(pvt_node), sbnk, j,
   1990                 PVT_ROFS(pvt_node), PVT_BKT_IDX(pvt_node), dbnk, i));
   1991 
   1992             /* Update ent_idx of prefix */
   1993             for (k = 0; k < pfx_arr->pfx_cnt; k++) {
   1994                 tmp_idx = pfx_arr->pfx[k]->ent_idx;
   1995                 if (ALPM_IDX_TO_BNK(acb, tmp_idx) == sbnk &&
   1996                     ALPM_IDX_TO_ENT(tmp_idx) == j) {
   1997                     pfx_arr->pfx[k]->ent_idx =
   1998                         ALPM_IDX_MAKE(acb, bkt_info, dbnk, i);
   1999                 }
   2000             }
   2001             break;
   2002         }
   2003     }
   2004 
   2005     bulk_idx[0] = dtab_idx;
   2006     bulk_idx[1] = stab_idx;
   2007     bulk_ent[0] = dstbnke;
   2008     bulk_ent[1] = srcbnke;
   2009     rv = th_mem_bulk_write(u, acb, pvt_node, BPC_BKT_TBL(bp_conf),
   2010                            bulk_idx, bulk_ent, 2);
   2011     return rv;
   2012 }
   2013 
   2014 int
   2015 th_alpm_bkt_pfx_copy(int u, _alpm_cb_t *acb,
   2016                        _alpm_bkt_pfx_arr_t *pfx_arr,
   2017                        _alpm_pvt_node_t *opvt_node,
   2018                        _alpm_pvt_node_t *npvt_node)
   2019 {
   2020     int i, rv = BCM_E_NONE;
   2021     int vrf_id;
   2022     uint32 src_idx, dst_idx = 0;
   2023     uint8  def_fmt;
   2024     uint16 sb_cnt[ALPM_BPB_MAX] = {0};
   2025     uint16 db_cnt[ALPM_BPB_MAX] = {0};
   2026     uint32 srcbnke[ALPM_BPB_MAX][17];
   2027     uint32 dstbnke[ALPM_BPB_MAX][17];
   2028 
   2029     int     bulk_idx[ALPM_BPB_MAX];
   2030     uint32  *bulk_ent[ALPM_BPB_MAX];
   2031     int     bulk_ent_cnt = 0;
   2032 
   2033     _alpm_bkt_info_t *src_bkt, *dst_bkt;
   2034     _alpm_bkt_pool_conf_t *bp_conf;
   2035 
   2036     src_bkt = &PVT_BKT_INFO(opvt_node);
   2037     dst_bkt = &PVT_BKT_INFO(npvt_node);
   2038     vrf_id  = PVT_BKT_VRF(opvt_node);
   2039     bp_conf = ACB_BKT_VRF_POOL(acb, vrf_id);
   2040 
   2041     for (i = 0; i < pfx_arr->pfx_cnt; i++) {
   2042         sb_cnt[ALPM_IDX_TO_BNK(acb, pfx_arr->pfx[i]->ent_idx)]++;
   2043     }
   2044 
   2045     for (i = 0; i < ALPM_BPB_MAX; i++) {
   2046         if (sb_cnt[i] == 0) {
   2047             continue;
   2048         }
   2049         rv = th_mem_read(u, acb, BPC_BKT_TBL(bp_conf),
   2050                          ALPM_TAB_IDX_GET_BI_BNK(acb, src_bkt, i),
   2051                          srcbnke[i], FALSE);
   2052         ALPM_IER(rv);
   2053     }
   2054 
   2055     def_fmt = alpm_util_bkt_def_fmt_get(u, acb, vrf_id, PVT_BKT_IPT(opvt_node));
   2056     sal_memset(dstbnke, 0, sizeof(dstbnke));
   2057     for (i = 0; i < pfx_arr->pfx_cnt; i++) {
   2058         int dst_bnk;
   2059         int offset = ACB_BKT_FIXED_FMT(acb, 1) ? 0 : PVT_KEY_LEN(npvt_node);
   2060         src_idx = pfx_arr->pfx[i]->ent_idx;
   2061         rv = alpm_bkt_ent_get_attempt(u, acb,
   2062                 ACB_BKT_VRF_POOL(acb, vrf_id),
   2063                 dst_bkt, def_fmt, pfx_arr->pfx[i]->key_len - offset,
   2064                 &dst_idx, NULL, 0);
   2065         /* We should not see a FULL here */
   2066         ALPM_IER(rv);
   2067 
   2068         dst_bnk = ALPM_IDX_TO_BNK(acb, dst_idx);
   2069         if (db_cnt[dst_bnk] == 0 && npvt_node->bkt_info.vet_bmp[dst_bnk] != 0) {
   2070             rv = th_mem_read(u, acb, BPC_BKT_TBL(bp_conf),
   2071                              ALPM_TAB_IDX_GET_BI_BNK(acb, dst_bkt, dst_bnk),
   2072                              dstbnke[dst_bnk], FALSE);
   2073             ALPM_IER(rv);
   2074         }
   2075         th_alpm_ent_copy(u, vrf_id, acb,
   2076                          srcbnke[ALPM_IDX_TO_BNK(acb, src_idx)],
   2077                          dstbnke[dst_bnk],
   2078                          src_bkt, dst_bkt,
   2079                          PVT_KEY_LEN(opvt_node),
   2080                          PVT_KEY_LEN(npvt_node),
   2081                          src_idx, dst_idx);
   2082 
   2083         db_cnt[dst_bnk]++;
   2084         pfx_arr->pfx[i]->ent_idx = dst_idx;
   2085         if (!ALPM_HIT_SKIP(u)) {
   2086             _alpm_tbl_t tbl = alpmTblInvalid;
   2087             ALPM_HIT_LOCK(u);
   2088             tbl = ACB_BKT_TBL(acb, vrf_id);
   2089             th_alpm_ent_hit_move(u, vrf_id, acb, tbl, src_idx, dst_idx);
   2090             ALPM_HIT_UNLOCK(u);
   2091         }
   2092     }
   2093 
   2094     for (i = 0; i < ALPM_BPB_MAX; i++) {
   2095         if (db_cnt[i] == 0) {
   2096             continue;
   2097         }
   2098 
   2099         bulk_idx[bulk_ent_cnt] = ALPM_TAB_IDX_GET_BI_BNK(acb, dst_bkt, i);
   2100         bulk_ent[bulk_ent_cnt] = dstbnke[i];
   2101         bulk_ent_cnt ++;
   2102     }
   2103 
   2104     rv = th_mem_bulk_write(u, acb, npvt_node,
   2105             BPC_BKT_TBL(bp_conf),
   2106             bulk_idx, bulk_ent, bulk_ent_cnt);
   2107 
   2108     ALPM_IER(rv);
   2109 
   2110     /* TD3ALPMTBD: rollback@err */
   2111     return rv;
   2112 }
   2113 
   2114 int
   2115 th_alpm_bkt_pfx_clean(int u, _alpm_cb_t *acb,
   2116                       _alpm_pvt_node_t *pvt_node,
   2117                       int count, uint32 *ent_idx)
   2118 {
   2119     int i, rv = BCM_E_NONE;
   2120     int vrf_id;
   2121     uint32 src_idx, ent_id;
   2122 
   2123     soc_format_t bnk_fmt;
   2124 
   2125     uint16 srcbnk[ALPM_BPB_MAX] = {0};
   2126     uint32 srcbnke[ALPM_BPB_MAX][17];
   2127     /* Bulk write */
   2128     int     bulk_idx[ALPM_BPB_MAX];
   2129     uint32  *bulk_ent[ALPM_BPB_MAX];
   2130     int     bulk_ent_cnt = 0;
   2131 
   2132     _alpm_bkt_pool_conf_t *bp_conf;
   2133     vrf_id = PVT_BKT_VRF(pvt_node);
   2134     bp_conf = ACB_BKT_VRF_POOL(acb, vrf_id);
   2135 
   2136     for (i = 0; i < count; i++) {
   2137         srcbnk[ALPM_IDX_TO_BNK(acb, ent_idx[i])]++;
   2138     }
   2139 
   2140     for (i = 0; i < ALPM_BPB_MAX; i++) {
   2141         if (srcbnk[i] == 0) {
   2142             continue;
   2143         }
   2144         rv = th_mem_read(u, acb, BPC_BKT_TBL(bp_conf),
   2145                 ALPM_TAB_IDX_GET_BI_BNK(acb, &PVT_BKT_INFO(pvt_node), i),
   2146                 srcbnke[i], FALSE);
   2147         ALPM_IER(rv);
   2148     }
   2149 
   2150     /* Clear corresponding entry from bank */
   2151     for (i = 0; i < count; i++) {
   2152         uint32 tmpe[17] = {0};
   2153         int8 fmt_tp;
   2154 
   2155         src_idx = ent_idx[i];
   2156         fmt_tp = th_alpm_bnk_fmt_get(u, acb, &PVT_BKT_INFO(pvt_node), src_idx);
   2157         bnk_fmt = ACB_FMT_BNK(acb, vrf_id, fmt_tp);
   2158         ent_id  = ALPM_IDX_TO_ENT(src_idx);
   2159         (void)soc_format_field_set(u, bnk_fmt,
   2160                     srcbnke[ALPM_IDX_TO_BNK(acb, src_idx)],
   2161                     th_alpm_ent_fld[ent_id], tmpe);
   2162     }
   2163 
   2164     for (i = 0; i < ALPM_BPB_MAX; i++) {
   2165         if (srcbnk[i] == 0) {
   2166             continue;
   2167         }
   2168 
   2169         bulk_idx[bulk_ent_cnt] =
   2170             ALPM_TAB_IDX_GET_BI_BNK(acb, &PVT_BKT_INFO(pvt_node), i);
   2171         bulk_ent[bulk_ent_cnt] = srcbnke[i];
   2172         bulk_ent_cnt ++;
   2173     }
   2174 
   2175     rv = th_mem_bulk_write(u, acb, pvt_node,
   2176             BPC_BKT_TBL(bp_conf),
   2177             bulk_idx, bulk_ent, bulk_ent_cnt);
   2178 
   2179     ALPM_IER(rv);
   2180 
   2181     for (i = 0; i < count; i++) {
   2182         uint32 bnk_idx;
   2183 
   2184         src_idx = ent_idx[i];
   2185         bnk_idx = ALPM_IDX_TO_BNK(acb, src_idx);
   2186         ent_id  = ALPM_IDX_TO_ENT(src_idx);
   2187         PVT_BKT_INFO(pvt_node).vet_bmp[bnk_idx] &= ~(1 << ent_id);
   2188         if (!ALPM_HIT_SKIP(u)) {
   2189             _alpm_tbl_t tbl = alpmTblInvalid;
   2190             ALPM_HIT_LOCK(u);
   2191             tbl = ACB_BKT_TBL(acb, vrf_id);
   2192             th_alpm_bkt_hit_write(u, vrf_id, acb, tbl, src_idx, 0);
   2193             ALPM_HIT_UNLOCK(u);
   2194         }
   2195     }
   2196 
   2197     return rv;
   2198 }
   2199 
   2200 /* Only do defrag inside a bucket */
   2201 int
   2202 th_alpm_bkt_pfx_shrink(int u, _alpm_cb_t *acb,
   2203                        _alpm_pvt_node_t *pvt_node,
   2204                        _alpm_bkt_pfx_arr_t *pfx_arr,
   2205                        int shrink_empty_only)
   2206 {
   2207     int tb, fb, tbnk, fbnk;
   2208     int rv = BCM_E_NONE;
   2209     int start, close, step;
   2210     int bnkpb = ACB_BNK_PER_BKT(acb, PVT_BKT_VRF(pvt_node));
   2211 
   2212     _alpm_bkt_info_t *bkt_info = NULL;
   2213 
   2214     bkt_info = &PVT_BKT_INFO(pvt_node);
   2215 
   2216     if (!ACB_BKT_WRA(acb, PVT_BKT_VRF(pvt_node)) ||
   2217         PVT_BKT_IDX(pvt_node) & 1) {
   2218         start = PVT_ROFS(pvt_node);
   2219         close = PVT_ROFS(pvt_node) + bnkpb;
   2220         step  = 1;
   2221     } else {
   2222         start = PVT_ROFS(pvt_node) + bnkpb - 1;
   2223         close = PVT_ROFS(pvt_node) - 1;
   2224         step  = -1;
   2225     }
   2226 
   2227     for (tb = start; ABS(tb-close) > 0; tb += step) {
   2228         tbnk = tb % bnkpb;
   2229         if (!BI_BNK_IS_USED(bkt_info, tbnk)) {
   2230             continue;
   2231         }
   2232         for (fb = (close - step); ABS(fb-tb) > 0; fb -= step) {
   2233             fbnk = fb % bnkpb;
   2234             /* Bank fb empty */
   2235             if (!BI_BNK_IS_USED(bkt_info, fbnk) ||
   2236                 bkt_info->vet_bmp[fbnk] == 0) {
   2237                 continue;
   2238             }
   2239 
   2240             /* Bank tb empty, Bank fb occupied */
   2241             if (bkt_info->vet_bmp[tbnk] == 0) {
   2242                 rv = th_alpm_bkt_bnk_shrink(u, acb, pvt_node, fbnk, tbnk,
   2243                                             pfx_arr);
   2244                 ALPM_IER(rv);
   2245             } else if (bkt_info->bnk_fmt[tbnk] >= bkt_info->bnk_fmt[fbnk]) {
   2246                 /* Bank tb & fb are same type and both occupied */
   2247                 rv = th_alpm_bkt_bnk_shrink(u, acb, pvt_node, fbnk,
   2248                                             tbnk, pfx_arr);
   2249                 ALPM_IER(rv);
   2250             }
   2251         }
   2252     }
   2253 
   2254     return rv;
   2255 }
   2256 
   2257 int
   2258 th_alpm_bkt_bnk_copy(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node,
   2259                      _alpm_bkt_info_t *src_bkt, _alpm_bkt_info_t *dst_bkt,
   2260                      int src_idx, int dst_idx)
   2261 {
   2262     int rv = BCM_E_NONE;
   2263     int vrf_id = -1;
   2264     uint32 ent[ALPM_ENT_WORDS_MAX] = {0};
   2265 
   2266     _alpm_tbl_t tbl = alpmTblInvalid;
   2267 
   2268     if (pvt_node != NULL) {
   2269         vrf_id = PVT_BKT_VRF(pvt_node);
   2270         tbl = BPC_BKT_TBL(ACB_BKT_VRF_POOL(acb, vrf_id));
   2271     }
   2272 
   2273 
   2274     if (tbl != alpmTblInvalid) {
   2275         ALPM_IER(th_mem_read(u, acb, tbl, src_idx, ent, FALSE));
   2276         if (BI_SUB_BKT_IDX(src_bkt) != BI_SUB_BKT_IDX(dst_bkt)) {
   2277             int eid, sbnk, dbnk, emax;
   2278             sbnk = ALPM_IDX_TO_BNK(acb, src_idx);
   2279             dbnk = ALPM_IDX_TO_BNK(acb, dst_idx);
   2280             emax = ACB_FMT_ENT_MAX(acb, vrf_id, src_bkt->bnk_fmt[sbnk]);
   2281             for (eid = 0; eid < emax; eid++) {
   2282                 if (!SHR_BITGET(&src_bkt->vet_bmp[sbnk], eid)) {
   2283                     continue;
   2284                 }
   2285 
   2286                 th_alpm_ent_copy(u, vrf_id, acb, ent, ent, src_bkt, dst_bkt, 0, 0,
   2287                     ALPM_IDX_MAKE(acb, src_bkt, sbnk, eid),
   2288                     ALPM_IDX_MAKE(acb, dst_bkt, dbnk, eid));
   2289             }
   2290         }
   2291         ALPM_IER(th_mem_write(u, acb, pvt_node, tbl, dst_idx, ent));
   2292 
   2293         if (!ALPM_HIT_SKIP(u)) {
   2294             ALPM_HIT_LOCK(u);
   2295             th_alpm_bnk_hit_move(u, vrf_id,
   2296                                  acb, &PVT_BKT_INFO(pvt_node),
   2297                                  tbl,
   2298                                  src_idx, dst_idx);
   2299             ALPM_HIT_UNLOCK(u);
   2300         }
   2301     }
   2302     return rv;
   2303 }
   2304 
   2305 int
   2306 th_alpm_bkt_bnk_clear(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node,
   2307                         int tab_idx)
   2308 {
   2309     int rv = BCM_E_NONE;
   2310     _alpm_tbl_t tbl = alpmTblInvalid;
   2311 
   2312     if (pvt_node != NULL) {
   2313         tbl = ACB_BKT_TBL(acb, PVT_BKT_VRF(pvt_node));
   2314         ALPM_IER(th_mem_write(u, acb, pvt_node, tbl, tab_idx, NULL));
   2315         if (!ALPM_HIT_SKIP(u)) {
   2316             th_alpm_bnk_hit_clear(u, PVT_BKT_VRF(pvt_node), acb,
   2317                                   &PVT_BKT_INFO(pvt_node), tbl, tab_idx);
   2318         }
   2319     }
   2320 
   2321     return rv;
   2322 }
   2323 
   2324 /* TCAM related functions */
   2325 int
   2326 th_tcam_table_sz(int u, int pkm)
   2327 {
   2328     int sz = 0;
   2329     soc_mem_t mem;
   2330     mem = alpm_tbl[ACB_TOP(u)->pvt_tbl[pkm]];
   2331 
   2332     if (mem != INVALIDm) {
   2333         sz = soc_mem_index_count(u, mem);
   2334 
   2335         if (SOC_URPF_STATUS_GET(u)) {
   2336             sz >>= 1;
   2337         }
   2338     }
   2339     return sz;
   2340 }
   2341 
   2342 /* TCAM Hw table cleanup (UNAVAIL for fast delete_all) */
   2343 int
   2344 th_tcam_hw_cleanup(int u)
   2345 {
   2346     return BCM_E_UNAVAIL;
   2347 }
   2348 
   2349 /*
   2350  * x | y
   2351  * --------------------
   2352  * 0 | 0 : entry0_to_0
   2353  * 0 | 1 : entry0_to_1
   2354  * 1 | 0 : entry1_to_0
   2355  * 1 | 1 : entry1_to_1
   2356  * src and dst can be same
   2357  */
   2358 int
   2359 th_tcam_entry_x_to_y(int u, int pkm, void *src, void *dst,
   2360                       int copy_hit, int x, int y)
   2361 {
   2362     int                 i;
   2363     uint32              val[SOC_MAX_MEM_FIELD_WORDS] = {0};
   2364     soc_mem_t           mem;
   2365     _alpm_cb_t    *acb = ACB_TOP(u);
   2366 
   2367 #define _FLD_CNT    9
   2368     soc_field_t fld[2][_FLD_CNT] =
   2369         {
   2370             {
   2371                 VALID0f,
   2372                 DATA_TYPE0f,
   2373                 ENTRY_VIEW0f,
   2374                 KEY0f,
   2375                 MASK0f,
   2376                 REPLACE_DATA0f,
   2377                 ALG_BKT_PTR0f,
   2378                 ALG_SUB_BKT_PTR0f,
   2379                 GLOBAL_HIGH0f
   2380              },
   2381             {
   2382                 VALID1f,
   2383                 DATA_TYPE1f,
   2384                 ENTRY_VIEW1f,
   2385                 KEY1f,
   2386                 MASK1f,
   2387                 REPLACE_DATA1f,
   2388                 ALG_BKT_PTR1f,
   2389                 ALG_SUB_BKT_PTR1f,
   2390                 GLOBAL_HIGH1f
   2391             }
   2392         };
   2393     soc_field_t hit[2] = {HIT0f, HIT1f};
   2394 
   2395     mem = alpm_tbl[acb->pvt_tbl[pkm]];
   2396     for (i = 0; i < _FLD_CNT; i++) {
   2397         soc_mem_field_get(u, mem, src, fld[x][i], val);
   2398         soc_mem_field_set(u, mem, dst, fld[y][i], val);
   2399     }
   2400 
   2401     if (copy_hit) {
   2402         soc_mem_field_get(u, mem, src, hit[x], val);
   2403         soc_mem_field_set(u, mem, dst, hit[y], val);
   2404     }
   2405 
   2406     return BCM_E_NONE;
   2407 }
   2408 
   2409 /* db_type: flex, non-flex */
   2410 static int
   2411 th_tcam_entry_view_get(int u, _alpm_bkt_info_t *bkt_info)
   2412 {
   2413     int i, entry_view;
   2414 
   2415     for (i = 0; i < ALPM_BPB_MAX; i++) {
   2416         if (bkt_info->bnk_fmt[i] != 0) {
   2417             break;
   2418         }
   2419     }
   2420     assert(i < ALPM_BPB_MAX);
   2421 
   2422     switch (bkt_info->bnk_fmt[i]) {
   2423         case ALPM_FMT_PKM_32B:
   2424             entry_view = 4;
   2425             break;
   2426         case ALPM_FMT_PKM_FLEX_32B:
   2427             entry_view = 3;
   2428             break;
   2429         case ALPM_FMT_PKM_64B:
   2430             entry_view = 2;
   2431             break;
   2432         case ALPM_FMT_PKM_FLEX_64B:
   2433             entry_view = 1;
   2434             break;
   2435         case ALPM_FMT_PKM_128:
   2436         case ALPM_FMT_PKM_FLEX_128:
   2437             entry_view = 0;
   2438             break;
   2439         default:
   2440             entry_view = 4;
   2441             break;
   2442     }
   2443 
   2444     return entry_view;
   2445 }
   2446 
   2447 /*
   2448  * field mapping:
   2449  *
   2450  * defip_flags
   2451  *      BCM_L3_HIT          -> HIT0f
   2452  *      BCM_L3_RPE          -> ASSOC_DATA0  -> RPE
   2453  *      BCM_L3_MULTIPATH    -> ASSOC_DATA0  -> DEST_TYPE
   2454  *      BCM_L3_DST_DISCARD  -> ASSOC_DATA0  -> DST_DISCARD
   2455  *      BCM_L3_IP6          -> KEY0         -> KEY_MODE
   2456  *                          -> KEY0         -> KEY_TYPE
   2457  * defip_prio               -> ASSOC_DATA0  -> PRI
   2458  * defip_ecmp_index         -> ASSOC_DATA0  -> DESTINATION
   2459  * defip_lookup_class       -> ASSOC_DATA0  -> CLASS_ID
   2460  * defip_vrf
   2461  *      BCM_L3_VRF_GLOBAL   -> ALPM1_DATA   -> DIRECT_ROUTE
   2462  *                          -> FIXED_DATA0  -> SUB_DB_PRIORITY
   2463  *
   2464  *      BCM_L3_VRF_OVERRIDE -> ALPM1_DATA   -> DIRECT_ROUTE
   2465  *                          -> FIXED_DATA0  -> SUB_DB_PRIORITY
   2466  *
   2467  *      other               -> KEY0         -> VRF_ID
   2468  *                          -> MASK0        -> VRF_ID
   2469  *                          -> FIXED_DATA0  -> SUB_DB_PRIORITY
   2470  *
   2471  * defip_sub_len            -> MASK0        -> IP_ADDR
   2472  * defip_ip_addr            -> KEY0         -> IP_ADDR
   2473  * defip_ip6_addr           -> KEY0         -> IP_ADDR
   2474  *
   2475  * defip_flex_ctr_base_id   -> ASSOC_DATA0  -> FLEX_CTR_BASE_COUNTER_IDX
   2476  * defip_flex_ctr_mode      -> ASSOC_DATA0  -> FLEX_CTR_OFFSET_MODE
   2477  * defip_flex_ctr_pool      -> ASSOC_DATA0  -> FLEX_CTR_POOL_NUMBER
   2478  */
   2479 int
   2480 th_tcam_entry_from_cfg(int unit, int pkm, _bcm_defip_cfg_t *lpm_cfg, void *e, int x, uint32 write_flags)
   2481 {
   2482     int             i, f, cnt = 1;
   2483     int             ipt;
   2484     uint32          key[4] = {0};
   2485     uint32          msk[4] = {0};
   2486     uint32          val;
   2487 
   2488     soc_mem_t       mem;
   2489     _alpm_cb_t      *acb = ACB_TOP(unit);
   2490     _alpm_pvt_node_t *pvt_node;
   2491     _alpm_bkt_node_t *bkt_node;
   2492 
   2493     /* Associated-Data */
   2494     soc_field_t fld_hit[] = {HIT0f, HIT1f, HITf};
   2495     soc_field_t fld_class_id[] = {CLASS_ID0f, CLASS_ID1f, CLASS_IDf};
   2496     soc_field_t fld_dst_disc[] = {DST_DISCARD0f, DST_DISCARD1f, DST_DISCARDf};
   2497     soc_field_t fld_pri[] = {PRI0f, PRI1f, PRIf};
   2498     soc_field_t fld_dest[] = {DESTINATION0f, DESTINATION1f, DESTINATIONf};
   2499     soc_field_t fld_hit_idx[] = {ALG_HIT_IDX0f, ALG_HIT_IDX1f, ALG_HIT_IDXf};
   2500     soc_field_t fld_glb_hi[] = {GLOBAL_HIGH0f, GLOBAL_HIGH1f, GLOBAL_HIGHf};
   2501     soc_field_t fld_glb_rt[] = {GLOBAL_ROUTE0f, GLOBAL_ROUTE1f, GLOBAL_ROUTEf};
   2502     soc_field_t fld_df_ms[] = {DEFAULT_MISS0f, DEFAULT_MISS1f, DEFAULT_MISSf};
   2503     soc_field_t fld_rpe[] = {RPE0f, RPE1f, RPEf};
   2504     soc_field_t fld_dt[] = {DATA_TYPE0f, DATA_TYPE1f, DATA_TYPEf};
   2505 
   2506     /* Flex Counter */
   2507     soc_field_t fld_fc_bci[] = {
   2508         FLEX_CTR_BASE_COUNTER_IDX0f,
   2509         FLEX_CTR_BASE_COUNTER_IDX1f,
   2510         FLEX_CTR_BASE_COUNTER_IDXf
   2511     };
   2512     soc_field_t fld_fc_om[] = {
   2513         FLEX_CTR_OFFSET_MODE0f,
   2514         FLEX_CTR_OFFSET_MODE1f,
   2515         FLEX_CTR_OFFSET_MODEf
   2516     };
   2517     soc_field_t fld_fc_pn[] = {
   2518         FLEX_CTR_POOL_NUMBER0f,
   2519         FLEX_CTR_POOL_NUMBER1f,
   2520         FLEX_CTR_POOL_NUMBERf
   2521     };
   2522 
   2523     /* IPMC */
   2524     soc_field_t fld_mc_cpu[] = {
   2525         IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f,
   2526         IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f,
   2527         IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPUf
   2528     };
   2529     soc_field_t fld_mc_drop[] = {
   2530         IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f,
   2531         IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f,
   2532         IPMC_EXPECTED_L3_IIF_MISMATCH_DROPf
   2533     };
   2534     soc_field_t fld_mc_iif[] =
   2535         {EXPECTED_L3_IIF0f, EXPECTED_L3_IIF1f, EXPECTED_L3_IIFf};
   2536 
   2537     /* VALID */
   2538     soc_field_t fld_vld[] = {VALID0f, VALID1f, VALID_LWRf};
   2539 
   2540     /* ALPM_DATA */
   2541     soc_field_t fld_bkt[] = {ALG_BKT_PTR0f, ALG_BKT_PTR1f, ALG_BKT_PTRf};
   2542     soc_field_t fld_sbkt[] =
   2543         {ALG_SUB_BKT_PTR0f, ALG_SUB_BKT_PTR1f, ALG_SUB_BKT_PTRf};
   2544 
   2545     soc_field_t fld_ent_vw[] = {ENTRY_VIEW0f, ENTRY_VIEW1f, ENTRY_VIEWf};
   2546 
   2547     /* Key & Mask */
   2548     soc_field_t fld_key_ip[] =
   2549         {IP_ADDR0f, IP_ADDR1f, IP_ADDR0_UPRf, IP_ADDR1_UPRf};
   2550     soc_field_t fld_key_vf[] =
   2551         {VRF_ID_0f, VRF_ID_1f, VRF_ID_0_UPRf, VRF_ID_1_UPRf};
   2552     soc_field_t fld_key_kt[] =
   2553         {KEY_TYPE0f, KEY_TYPE1f, KEY_TYPE0_UPRf, KEY_TYPE1_UPRf};
   2554     soc_field_t fld_key_km[] =
   2555         {KEY_MODE0f, KEY_MODE1f, KEY_MODE0_UPRf, KEY_MODE1_UPRf};
   2556     soc_field_t fld_msk_ip[] =
   2557         {IP_ADDR_MASK0f, IP_ADDR_MASK1f, IP_ADDR_MASK0_UPRf, IP_ADDR_MASK1_UPRf};
   2558     soc_field_t fld_msk_vf[] =
   2559         {VRF_ID_MASK0f, VRF_ID_MASK1f, VRF_ID_MASK0_UPRf, VRF_ID_MASK1_UPRf};
   2560     soc_field_t fld_msk_kt[] =
   2561         {KEY_TYPE_MASK0f, KEY_TYPE_MASK1f, KEY_TYPE_MASK0_UPRf, KEY_TYPE_MASK1_UPRf};
   2562     soc_field_t fld_msk_km[] =
   2563         {KEY_MODE_MASK0f, KEY_MODE_MASK1f, KEY_MODE_MASK0_UPRf, KEY_MODE_MASK1_UPRf};
   2564 
   2565     int _ent_view = 0;
   2566 
   2567     /* Starting here */
   2568 
   2569     mem = alpm_tbl[acb->pvt_tbl[pkm]];
   2570     if (SOC_MEM_FIELD_VALID(unit, mem, VALIDf)) {
   2571         if (pkm == ALPM_PKM_32B) {
   2572             f = !!x;
   2573             fld_key_ip[!x] = fld_key_ip[!!x];
   2574             fld_key_vf[!x] = fld_key_vf[!!x];
   2575             fld_key_kt[!x] = fld_key_kt[!!x];
   2576             fld_key_km[!x] = fld_key_km[!!x];
   2577             fld_msk_ip[!x] = fld_msk_ip[!!x];
   2578             fld_msk_vf[!x] = fld_msk_vf[!!x];
   2579             fld_msk_kt[!x] = fld_msk_kt[!!x];
   2580             fld_msk_km[!x] = fld_msk_km[!!x];
   2581         } else {
   2582             f = 0;
   2583             cnt = 2;
   2584         }
   2585     } else if (SOC_MEM_FIELD_VALID(unit, mem, VALID_LWRf)) {
   2586         fld_key_ip[0] = IP_ADDR0_LWRf;
   2587         fld_key_ip[1] = IP_ADDR1_LWRf;
   2588         fld_key_vf[0] = VRF_ID_0_LWRf;
   2589         fld_key_vf[1] = VRF_ID_1_LWRf;
   2590         fld_key_kt[0] = KEY_TYPE0_LWRf;
   2591         fld_key_kt[1] = KEY_TYPE1_LWRf;
   2592         fld_key_km[0] = KEY_MODE0_LWRf;
   2593         fld_key_km[1] = KEY_MODE1_LWRf;
   2594         fld_msk_ip[0] = IP_ADDR_MASK0_LWRf;
   2595         fld_msk_ip[1] = IP_ADDR_MASK1_LWRf;
   2596         fld_msk_vf[0] = VRF_ID_MASK0_LWRf;
   2597         fld_msk_vf[1] = VRF_ID_MASK1_LWRf;
   2598         fld_msk_kt[0] = KEY_TYPE_MASK0_LWRf;
   2599         fld_msk_kt[1] = KEY_TYPE_MASK1_LWRf;
   2600         fld_msk_km[0] = KEY_MODE_MASK0_LWRf;
   2601         fld_msk_km[1] = KEY_MODE_MASK1_LWRf;
   2602         f = 2;
   2603     } else {
   2604         f = 0;
   2605     }
   2606 
   2607 #define _MEM32_SET(field, value) \
   2608     soc_mem_field32_set(unit, mem, e, (field), (value))
   2609 
   2610 _conf:
   2611     _MEM32_SET(fld_vld[f], 1);
   2612     if (SOC_MEM_FIELD_VALID(unit, mem, VALID_LWRf)) {
   2613         _MEM32_SET(VALID_LWRf, 3);
   2614         _MEM32_SET(VALID_UPRf, 3);
   2615     }
   2616     /* HIT bits */
   2617     _MEM32_SET(fld_hit[f], !!(lpm_cfg->defip_flags & BCM_L3_HIT));
   2618     _MEM32_SET(fld_rpe[f], !!(lpm_cfg->defip_flags & BCM_L3_RPE));
   2619     _MEM32_SET(fld_dst_disc[f], !!(lpm_cfg->defip_flags & BCM_L3_DST_DISCARD));
   2620     _MEM32_SET(fld_pri[f], lpm_cfg->defip_prio);
   2621     _MEM32_SET(fld_class_id[f], lpm_cfg->defip_lookup_class);
   2622     _MEM32_SET(fld_fc_bci[f], lpm_cfg->defip_flex_ctr_base_id);
   2623     _MEM32_SET(fld_fc_om[f], lpm_cfg->defip_flex_ctr_mode);
   2624     _MEM32_SET(fld_fc_pn[f], lpm_cfg->defip_flex_ctr_pool);
   2625 
   2626     if (soc_feature(unit, soc_feature_generic_dest)) {
   2627         soc_format_t dst_fmt = DESTINATION_FORMATfmt;
   2628         uint32 dst_fmt_val = 0;
   2629         if (lpm_cfg->defip_flags & BCM_L3_MULTIPATH) {
   2630             soc_format_field32_set(unit, dst_fmt, &dst_fmt_val, DEST_TYPE1f, 1);
   2631             soc_format_field32_set(unit, dst_fmt, &dst_fmt_val, ECMP_GROUPf,
   2632                                    lpm_cfg->defip_ecmp_index);
   2633         } else if (!(lpm_cfg->defip_flags & BCM_L3_IPMC)) {
   2634             soc_format_field32_set(unit, dst_fmt, &dst_fmt_val, DEST_TYPE0f, 3);
   2635             soc_format_field32_set(unit, dst_fmt, &dst_fmt_val, NEXT_HOP_INDEXf,
   2636                                    lpm_cfg->defip_ecmp_index);
   2637         }
   2638         _MEM32_SET(fld_dest[f], dst_fmt_val);
   2639     }
   2640 
   2641     _MEM32_SET(fld_glb_hi[f], lpm_cfg->defip_vrf == BCM_L3_VRF_OVERRIDE);
   2642     _MEM32_SET(fld_glb_rt[f], lpm_cfg->defip_vrf == BCM_L3_VRF_OVERRIDE ||
   2643                               lpm_cfg->defip_vrf == BCM_L3_VRF_GLOBAL);
   2644     _MEM32_SET(fld_df_ms[f], ALPM_TCAM_ZONED(unit) &&
   2645                              lpm_cfg->default_miss == 1);
   2646     _MEM32_SET(fld_dt[f], 0);
   2647 
   2648     pvt_node = (_alpm_pvt_node_t *)lpm_cfg->pvt_node;
   2649     if (pvt_node != NULL) {
   2650         _ent_view = th_tcam_entry_view_get(unit, &PVT_BKT_INFO(pvt_node));
   2651         _MEM32_SET(fld_ent_vw[f], _ent_view);
   2652 
   2653         _MEM32_SET(fld_bkt[f], PVT_BKT_IDX(pvt_node) << ACB_BKT_DW(acb));
   2654         _MEM32_SET(fld_sbkt[f], PVT_SUB_BKT_IDX(pvt_node));
   2655 
   2656         bkt_node = PVT_BKT_DEF(pvt_node);
   2657         if (bkt_node != NULL) {
   2658             int ent, hw_idx = 0;
   2659             hw_idx = bkt_node->ent_idx;
   2660             ent = ALPM_IDX_TO_ENT(bkt_node->ent_idx);
   2661             hw_idx = th_alpm_hit_tbl_idx_get(unit, acb, alpmTblBktCmodeL2, hw_idx, ent);
   2662             _MEM32_SET(fld_hit_idx[f], hw_idx);
   2663         }
   2664     }
   2665 
   2666     if (soc_feature(unit, soc_feature_ipmc_defip) &&
   2667         (lpm_cfg->defip_flags & BCM_L3_IPMC)) {
   2668         _MEM32_SET(fld_dt[f], 2);
   2669         if (lpm_cfg->defip_mc_group > 0 &&
   2670             soc_feature(unit, soc_feature_generic_dest)) {
   2671             soc_format_t dst_fmt = DESTINATION_FORMATfmt;
   2672             uint32 dst_fmt_val = 0;
   2673             soc_format_field32_set(unit, dst_fmt, &dst_fmt_val, DEST_TYPE1f, 3);
   2674             soc_format_field32_set(unit, dst_fmt, &dst_fmt_val, IPMC_GROUPf,
   2675                                    lpm_cfg->defip_mc_group);
   2676             _MEM32_SET(fld_dest[f], dst_fmt_val);
   2677         }
   2678 
   2679         if (lpm_cfg->defip_l3a_rp != BCM_IPMC_RP_ID_INVALID) {
   2680             _MEM32_SET(fld_mc_iif[f],
   2681                        _BCM_DEFIP_IPMC_RP_SET(lpm_cfg->defip_l3a_rp));
   2682         } else if (lpm_cfg->defip_ipmc_flags & BCM_IPMC_POST_LOOKUP_RPF_CHECK &&
   2683                    lpm_cfg->defip_expected_intf != 0) {
   2684             _MEM32_SET(fld_mc_iif[f], lpm_cfg->defip_expected_intf);
   2685             _MEM32_SET(fld_mc_drop[f],
   2686                        !!(lpm_cfg->defip_ipmc_flags & BCM_IPMC_RPF_FAIL_DROP));
   2687             _MEM32_SET(fld_mc_cpu[f],
   2688                        !!(lpm_cfg->defip_ipmc_flags & BCM_IPMC_RPF_FAIL_TOCPU));
   2689         }
   2690 
   2691     }
   2692 
   2693     if (--cnt > 0) {
   2694         f = 1;
   2695         goto _conf;
   2696     }
   2697 
   2698     /* Program KEY & MASK
   2699      *
   2700      *           key[4] = {key[0], key[1], key[2], key[3]}
   2701      * ipv4:     key[4] = {IP_ADDR0f, 0, 0, 0}
   2702      * ipv6-64:  key[4] = {0, 0, IP_ADDR0f, IP_ADDR1f, }
   2703      * ipv6-128: key[4] = {IP_ADDR0_LWRf, IP_ADDR1_LWRf, IP_ADDR0_UPRf, IP_ADDR1_UPRf}
   2704      */
   2705     ipt = ALPM_PKM2IPT(pkm);
   2706     alpm_util_cfg_to_key(unit, ipt, lpm_cfg, key);
   2707     alpm_util_cfg_to_msk(unit, ipt, lpm_cfg, msk);
   2708     if (SOC_MEM_FIELD_VALID(unit, mem, VALID_LWRf)) {
   2709         cnt = 4;
   2710     } else if (pkm == ALPM_PKM_64B) {
   2711         key[1] = key[3];
   2712         key[0] = key[2];
   2713         msk[1] = msk[3];
   2714         msk[0] = msk[2];
   2715         cnt = 2;
   2716     } else {
   2717         cnt = 1;
   2718     }
   2719 
   2720     switch (pkm) {
   2721         case ALPM_PKM_32B:
   2722             val = 0;
   2723             break;
   2724         case ALPM_PKM_64B:
   2725             val = 1;
   2726             break;
   2727         case ALPM_PKM_128:
   2728             val = 3;
   2729             break;
   2730         default:
   2731             val = 0;
   2732             break;
   2733     }
   2734 
   2735     for (i = 0; i < cnt; i++) {
   2736         /* KEY & mask */
   2737         _MEM32_SET(fld_key_km[i], val);
   2738         _MEM32_SET(fld_msk_km[i], 0x3);
   2739         _MEM32_SET(fld_key_kt[i], 0);
   2740         _MEM32_SET(fld_msk_kt[i], 0xf);
   2741         _MEM32_SET(fld_key_ip[i], key[i]);
   2742         _MEM32_SET(fld_msk_ip[i], msk[i]);
   2743         if (lpm_cfg->defip_vrf >= 0) {
   2744             _MEM32_SET(fld_key_vf[i], lpm_cfg->defip_vrf);
   2745             _MEM32_SET(fld_msk_vf[i], 0xfff);
   2746         }
   2747     }
   2748 #undef _MEM32_SET
   2749 
   2750     return BCM_E_NONE;
   2751 }
   2752 
   2753 int
   2754 th_tcam_entry_to_cfg(int unit, int pkm, void *ent, int x,
   2755                       _bcm_defip_cfg_t *lpm_cfg)
   2756 {
   2757     soc_mem_t       mem;
   2758     _alpm_cb_t      *acb = ACB_TOP(unit);
   2759 
   2760     x = !!x;
   2761     mem = alpm_tbl[acb->pvt_tbl[pkm]];
   2762 
   2763     lpm_cfg->defip_flags &= BCM_L3_IP6 | BCM_L3_IPMC;
   2764     if (TH_ENT_HIT_GET(unit)) {
   2765         lpm_cfg->defip_flags |= BCM_L3_HIT;
   2766     } else {
   2767         lpm_cfg->defip_flags &= ~BCM_L3_HIT;
   2768     }
   2769 
   2770     /* ASSOC_DATAf format */
   2771     if (TH_ENT_RPE_GET(unit)) {
   2772         lpm_cfg->defip_flags |= BCM_L3_RPE;
   2773     } else {
   2774         lpm_cfg->defip_flags &= ~BCM_L3_RPE;
   2775     }
   2776 
   2777     if (soc_feature(unit, soc_feature_generic_dest)) {
   2778         int ecmp = 0, ipmc = 0;
   2779         TH_ENT_DEST_GET(unit, ecmp, ipmc, lpm_cfg->defip_ecmp_index);
   2780         if (ecmp) {
   2781             lpm_cfg->defip_flags |= BCM_L3_MULTIPATH;
   2782             lpm_cfg->defip_ecmp = 1;
   2783         } else {
   2784             lpm_cfg->defip_flags &= ~BCM_L3_MULTIPATH;
   2785             lpm_cfg->defip_ecmp = 0;
   2786             lpm_cfg->defip_ecmp_count = 0;
   2787         }
   2788         if (ipmc) {
   2789             lpm_cfg->defip_flags |= BCM_L3_IPMC;
   2790             lpm_cfg->defip_mc_group = lpm_cfg->defip_ecmp_index;
   2791         } else {
   2792             lpm_cfg->defip_flags &= ~BCM_L3_IPMC;
   2793             lpm_cfg->defip_mc_group = 0;
   2794         }
   2795     }
   2796 
   2797     if (TH_ENT_DST_DISCARD_GET(unit)) {
   2798         lpm_cfg->defip_flags |= BCM_L3_DST_DISCARD;
   2799     } else {
   2800         lpm_cfg->defip_flags &= ~BCM_L3_DST_DISCARD;
   2801     }
   2802     lpm_cfg->defip_prio = TH_ENT_PRI_GET(unit);
   2803     lpm_cfg->defip_lookup_class = TH_ENT_CLASS_ID_GET(unit);
   2804     lpm_cfg->defip_flex_ctr_base_id = TH_ENT_FC_BASE_ID_GET(unit);
   2805     lpm_cfg->defip_flex_ctr_mode = TH_ENT_FC_MODE_GET(unit);
   2806     lpm_cfg->defip_flex_ctr_pool = TH_ENT_FC_POOL_GET(unit);
   2807 
   2808     /* No need to parse the rest field because there are already in the
   2809      * lpm_cfg, part of key */
   2810 
   2811     if (soc_feature(unit, soc_feature_ipmc_defip)) {
   2812         int is_ipmc = 0;
   2813         if (TH_ENT_DATA_TYPE_GET(unit) == 2) {
   2814             is_ipmc = 1;
   2815         }
   2816 
   2817         if (is_ipmc) {
   2818             uint32 val;
   2819             lpm_cfg->defip_flags |= BCM_L3_IPMC;
   2820             if (TH_ENT_MC_DROP_GET(unit)) {
   2821                 lpm_cfg->defip_ipmc_flags |= BCM_IPMC_RPF_FAIL_DROP;
   2822             }
   2823             if (TH_ENT_MC_CPU_GET(unit)) {
   2824                 lpm_cfg->defip_ipmc_flags |= BCM_IPMC_RPF_FAIL_TOCPU;
   2825             }
   2826             val = TH_ENT_MC_IIF_GET(unit);
   2827             if (_BCM_DEFIP_IPMC_RP_IS_SET(val)) {
   2828                 lpm_cfg->defip_l3a_rp = _BCM_DEFIP_IPMC_RP_GET(val);
   2829             } else {
   2830                 lpm_cfg->defip_expected_intf = val;
   2831                 if (lpm_cfg->defip_expected_intf != 0) {
   2832                     lpm_cfg->defip_ipmc_flags |= BCM_IPMC_POST_LOOKUP_RPF_CHECK;
   2833                 }
   2834                 lpm_cfg->defip_l3a_rp = BCM_IPMC_RP_ID_INVALID;
   2835             }
   2836         } else {
   2837             lpm_cfg->defip_flags &= ~BCM_L3_IPMC;
   2838         }
   2839     }
   2840 
   2841     return BCM_E_NONE;
   2842 }
   2843 
   2844 int
   2845 th_tcam_entry_valid(int u, int pkm, void *ent, int x)
   2846 {
   2847     _alpm_cb_t  *acb = ACB_TOP(u);
   2848     soc_mem_t   mem = alpm_tbl[acb->pvt_tbl[pkm]];
   2849 
   2850     return TH_ENT_VALID_GET(u) & (1 << x) ? 1 : 0;
   2851 }
   2852 
   2853 int
   2854 th_tcam_entry_valid_set(int u, int pkm, void *ent, int x, int val)
   2855 {
   2856     soc_mem_t mem;
   2857     soc_field_t vld_fld;
   2858     _alpm_cb_t *acb = ACB_TOP(u);
   2859 
   2860     mem = alpm_tbl[acb->pvt_tbl[pkm]];
   2861     switch (pkm) {
   2862         case ALPM_PKM_32B:
   2863             vld_fld = x ? VALID1f : VALID0f;
   2864             soc_mem_field32_set(u, mem, ent, vld_fld, val ? 1 : 0);
   2865             break;
   2866         case ALPM_PKM_64B:
   2867             soc_mem_field32_set(u, mem, ent, VALIDf, val ? 3 : 0);
   2868             break;
   2869         case ALPM_PKM_128:
   2870             soc_mem_field32_set(u, mem, ent, VALID_LWRf, val ? 3 : 0);
   2871             soc_mem_field32_set(u, mem, ent, VALID_UPRf, val ? 3 : 0);
   2872             break;
   2873         default:
   2874             break;
   2875     }
   2876 
   2877     return BCM_E_NONE;
   2878 }
   2879 
   2880 static int
   2881 th_tcam_entry_to_mask_key(int u, int pkm, void *ent, int x,
   2882                             uint32 *key, int is_mask)
   2883 {
   2884     _alpm_cb_t *acb = ACB_TOP(u);
   2885     soc_mem_t   mem = alpm_tbl[acb->pvt_tbl[pkm]];
   2886 
   2887     sal_memset(key, 0, 4 * sizeof(uint32));
   2888     if (is_mask) {
   2889         TH_ENT_MASK_IPADDR_GET(u, key);
   2890     } else {
   2891         TH_ENT_KEY_IPADDR_GET(u, key);
   2892     }
   2893 
   2894     if (pkm == ALPM_PKM_64B) {
   2895         key[3] = key[1];
   2896         key[2] = key[0];
   2897         key[1] = key[0] = 0;
   2898     }
   2899 
   2900     return BCM_E_NONE;
   2901 }
   2902 
   2903 /*
   2904  *           key[4] = {key[0], key[1], key[2], key[3]}
   2905  * ipv4:     key[4] =
   2906  *               {IP_ADDR0f, 0, 0, 0}
   2907  * ipv6-64:  key[4] =
   2908  *               {0, 0, IP_ADDR0f, IP_ADDR1f, }
   2909  * ipv6-128: key[4] =
   2910  *               {IP_ADDR0_LWRf, IP_ADDR1_LWRf, IP_ADDR0_UPRf, IP_ADDR1_UPRf}
   2911  */
   2912 int
   2913 th_tcam_entry_to_key(int u, int pkm, void *ent, int x, uint32 *key)
   2914 {
   2915     return th_tcam_entry_to_mask_key(u, pkm, ent, x, key, FALSE);
   2916 }
   2917 
   2918 int
   2919 th_tcam_entry_vrf_id_get(int u, int pkm, void *ent, int x, int *vrf_id)
   2920 {
   2921     _alpm_cb_t *acb = ACB_TOP(u);
   2922     soc_mem_t mem   = alpm_tbl[acb->pvt_tbl[pkm]];
   2923 
   2924     TH_ENT_KEY_VRF_ID_GET(u, *vrf_id);
   2925 
   2926     return BCM_E_NONE;
   2927 }
   2928 
   2929 int
   2930 th_tcam_entry_pfx_len_get(int u, int pkm, void *ent, int x, int *pfx_len)
   2931 {
   2932     int         i, rv = BCM_E_NONE;
   2933     uint32      mask[4];
   2934 
   2935     *pfx_len = 0;
   2936 
   2937     /* Assuming each MASK field is correct,
   2938      * Not my duty to validate MASK here */
   2939     th_tcam_entry_to_mask_key(u, pkm, ent, x, mask, TRUE);
   2940     for (i = 0; i < 4; i++) {
   2941         *pfx_len += _shr_popcount(mask[i]);
   2942     }
   2943 
   2944     return rv;
   2945 }
   2946 
   2947 /*
   2948  * Function:
   2949  *      th_tcam_entry_mode_get
   2950  * Purpose:
   2951  *      Get TCAM valid entry KEY mode and type.
   2952  * Parameters:
   2953  *      u          - (In)Device unit
   2954  *      pk         - (In)Input TCAM packing mode table view
   2955  *      e          - (In)TCAM lpm memory entry
   2956  *      step_size  - (Out)Key mode step-size (un pair: 1 or 2, pair: 2)
   2957  *      p km       - (Out)Detected packing mode
   2958  *      ipv6       - (Out)Key Type (0:IPv4, 1:IPv6)
   2959  *      key_mode   - (Out)Key Mode (0:Half, 1:Full, 3:Double)
   2960  *      sub_idx    - (In)TCAM sub_idx (0, 1) for half-wide entries in unpair
   2961  *                       TCAM. Pair TCAM has only one sub_idx=0.
   2962  * Notes:
   2963  *      The for-loop for sub_idx is using always as below:
   2964  *        for (sub_idx = 0; sub_idx < ALPM_TCAM_SUBCNT; sub_idx += step_size)
   2965  *      where
   2966  *        ALPM_TCAM_SUBCNT is defined as 2, and
   2967  *        step_size is variable, depending on the actual TCAM entry reading.
   2968  *
   2969  * Returns:
   2970  *      BCM_E_XXX
   2971  */
   2972 int
   2973 th_tcam_entry_mode_get(int u, int pk, void *ent, int *step_size,
   2974                         int *pkm, int *ipv6, int *key_mode, int x)
   2975 {
   2976     int valid;
   2977     int is_pair_tbl = 0;
   2978     _alpm_cb_t *acb = ACB_TOP(u);
   2979     soc_mem_t mem = alpm_tbl[acb->pvt_tbl[pk]];
   2980 
   2981     if (mem == alpm_tbl[alpmTblPvtCmodeL1P128]) {
   2982         is_pair_tbl = 1;
   2983     }
   2984     *step_size = is_pair_tbl ? 2 : 1;
   2985 
   2986     valid = TH_ENT_VALID_GET(u);
   2987     valid &=  (1 << x);
   2988 
   2989     if (!valid) { /* invalid entry */
   2990         return BCM_E_NOT_FOUND;
   2991     }
   2992 
   2993     *key_mode = TH_ENT_KEY_KM_GET(u);
   2994     *ipv6     = *key_mode ? 1 : 0;
   2995     /* TD3TBD */
   2996     *pkm = (mem == alpm_tbl[alpmTblPvtCmodeL1P128]) ? ALPM_PKM_128 :
   2997                           *ipv6 ? ALPM_PKM_64B : ALPM_PKM_32B ;
   2998 
   2999     /* Wrong key_mode or key_type */
   3000     if ((!is_pair_tbl && (*key_mode > 1)) ||
   3001         (is_pair_tbl && (*key_mode != 3))) {
   3002         return BCM_E_INTERNAL;
   3003     }
   3004 
   3005    /* step_size 2 only if full-wide in un pair TCAM */
   3006    if (!is_pair_tbl && (*key_mode == 1)) {
   3007        *step_size = 2;
   3008    }
   3009    return BCM_E_NONE;
   3010 }
   3011 
   3012 /* Get ASSOC_DATA from a TCAM entry */
   3013 int
   3014 th_tcam_entry_adata_get(int u, int pkm, void *ent, int x,
   3015                          _alpm_bkt_adata_t *adata)
   3016 {
   3017     int ecmp = 0, ipmc = 0, rv = BCM_E_NONE;
   3018     _alpm_cb_t *acb = ACB_TOP(u);
   3019     soc_mem_t mem = alpm_tbl[acb->pvt_tbl[pkm]];
   3020 
   3021     TH_ENT_DEST_GET(u, ecmp, ipmc, adata->defip_ecmp_index);
   3022     ipmc |= (TH_ENT_DATA_TYPE_GET(u) == 2);
   3023     adata->defip_flags = ecmp ? BCM_L3_MULTIPATH : 0;
   3024     adata->defip_flags |= (pkm != ALPM_PKM_32B) ? BCM_L3_IP6 : 0;
   3025     adata->defip_flags |= ipmc ? BCM_L3_IPMC : 0;
   3026     adata->defip_flags |= TH_ENT_RPE_GET(u) ? BCM_L3_RPE : 0;
   3027     adata->defip_flags |= TH_ENT_DST_DISCARD_GET(u) ? BCM_L3_DST_DISCARD : 0;
   3028     adata->defip_prio = TH_ENT_PRI_GET(u);
   3029     adata->defip_lookup_class = TH_ENT_CLASS_ID_GET(u);
   3030     adata->defip_flex_ctr_base_id = TH_ENT_FC_BASE_ID_GET(u);
   3031     adata->defip_flex_ctr_mode = TH_ENT_FC_MODE_GET(u);
   3032     adata->defip_flex_ctr_pool = TH_ENT_FC_POOL_GET(u);
   3033 
   3034     return rv;
   3035 }
   3036 
   3037 /* Get ALPM_DATA entry from a TCAM entry */
   3038 int
   3039 th_tcam_entry_bdata_get(int u, int pkm, void *ent, int x, void *fent)
   3040 {
   3041     /* return entry itself */
   3042     sal_memcpy(fent, ent,
   3043                sizeof(uint32) *
   3044                soc_mem_entry_words(u, alpm_tbl[ACB_TOP(u)->pvt_tbl[pkm]]));
   3045 
   3046     return BCM_E_NONE;
   3047 }
   3048 
   3049 /***************** Bucket entry (Bank) starts from here *****************/
   3050 int
   3051 th_alpm_ent_ent_get(int u, int vrf_id, _alpm_cb_t *acb, void *ent, uint32 fmt,
   3052                      int eid, void *ftmp)
   3053 {
   3054     int rv = BCM_E_NONE;
   3055 
   3056     /* get bucket level bank format entry */
   3057     soc_format_field_get(u, ACB_FMT_BNK(acb, vrf_id, fmt), ent,
   3058                          th_alpm_ent_fld[eid], ftmp);
   3059     return rv;
   3060 }
   3061 
   3062 /* Get ALPM_Data bucket info (logic table based):
   3063    bkt_ptr, rofs, kshift, def_miss and bnkfmt[] */
   3064 static void
   3065 th_alpm_ent_binfo_get(int u, int vrf_id, int ipt, int pvt_pkm, _alpm_cb_t *acb,
   3066                       void *ent, int x, _alpm_ent_info_t *info)
   3067 {
   3068     int bnk;
   3069     soc_mem_t mem = alpm_tbl[acb->pvt_tbl[pvt_pkm]];
   3070 
   3071     info->kshift = 0;
   3072     BI_ROFS(&info->bkt_info) = 0;
   3073     BI_BKT_IDX(&info->bkt_info) = TH_ENT_BKT_PTR_GET(u) >> ACB_BKT_DW(acb);
   3074     BI_SUB_BKT_IDX(&info->bkt_info) = TH_ENT_SUB_BKT_PTR_GET(u);
   3075     info->default_miss = TH_ENT_DEFAULT_MISS_GET(u);
   3076     for (bnk = 0; bnk < ACB_BNK_PER_BKT(acb, vrf_id); bnk++) {
   3077         info->bkt_info.bnk_fmt[bnk] =
   3078             alpm_util_bkt_def_fmt_get(u, acb, vrf_id, ipt);
   3079     }
   3080 
   3081     return;
   3082 }
   3083 
   3084 /* Read and update ALPM prefix key */
   3085 int
   3086 th_alpm_bkt_pfx_get(int u, int vrf_id, _alpm_cb_t *acb, void *ent, int ent_fmt,
   3087                     uint32 *valid, uint32 *new_key, int *new_len)
   3088 {
   3089     int rv = BCM_E_NONE;
   3090     soc_format_t fmt = ACB_FMT_ENT(acb, vrf_id, ent_fmt);
   3091 
   3092     /* process Bucket Level PREFIX */
   3093     *valid = TH_BKT_VALID_GET(u);
   3094     if (*valid) {
   3095         TH_BKT_KEY_GET(u, new_key);
   3096         if (ent_fmt == ALPM_FMT_PKM_64B || ent_fmt == ALPM_FMT_PKM_FLEX_64B) {
   3097             new_key[3] = new_key[1];
   3098             new_key[2] = new_key[0];
   3099             new_key[1] = new_key[0] = 0;
   3100         }
   3101         *new_len = TH_BKT_LENGTH_GET(u);
   3102     }
   3103 
   3104     return rv;
   3105 }
   3106 
   3107 /* Read ALPM Assoc_Data */
   3108 static void
   3109 th_alpm_bkt_adata_get(int u, int vrf_id, int ipt, _alpm_cb_t *acb, void *ent,
   3110                       int ent_fmt, _alpm_ent_info_t *info)
   3111 {
   3112     int ecmp = 0, ipmc = 0;
   3113     soc_format_t fmt = ACB_FMT_ENT(acb, vrf_id, ent_fmt);
   3114      _alpm_bkt_adata_t *adata = &info->adata;
   3115 
   3116     TH_BKT_DEST_GET(u, ecmp, ipmc, adata->defip_ecmp_index);
   3117     adata->defip_flags = ecmp ? BCM_L3_MULTIPATH : 0;
   3118     adata->defip_flags = ALPM_IS_IPV6(ipt) ? BCM_L3_IP6 : 0;
   3119     adata->defip_flags |= ipmc ? BCM_L3_IPMC : 0;
   3120     adata->defip_flags |= TH_BKT_RPE_GET(u) ? BCM_L3_RPE : 0;
   3121     adata->defip_flags |= TH_BKT_DST_DISCARD_GET(u) ? BCM_L3_DST_DISCARD : 0;
   3122     adata->defip_prio = TH_BKT_PRI_GET(u);
   3123     adata->defip_lookup_class = TH_BKT_CLASS_ID_GET(u);
   3124     if (soc_format_field_valid(u, fmt, FLEX_CTR_BASE_COUNTER_IDXf)) {
   3125         adata->defip_flex_ctr_base_id = TH_BKT_FC_BASE_ID_GET(u);
   3126         adata->defip_flex_ctr_mode = TH_BKT_FC_MODE_GET(u);
   3127         adata->defip_flex_ctr_pool = TH_BKT_FC_POOL_GET(u);
   3128     }
   3129     info->bkt_info.sub_bkt_idx = TH_BKT_SUB_BKT_PTR_GET(u);
   3130 
   3131     return ;
   3132 }
   3133 
   3134 static void
   3135 th_alpm_ent_binfo_raw_get(int u, int vrf_id, _alpm_cb_t *acb, void *ent,
   3136                           int fmt, void *binfo_raw)
   3137 {
   3138     soc_format_t bnk_fmt = ACB_FMT_BNK(acb, vrf_id, fmt);
   3139     soc_field_t ent_fld = th_alpm_ent_fld[0];
   3140     uint32 ent_sz = BITS2BYTES(soc_format_field_length(u, bnk_fmt, ent_fld));
   3141     sal_memcpy(binfo_raw, ent, ent_sz);
   3142     return;
   3143 }
   3144 
   3145 /* Used for retrieving alpm info from given entry,
   3146  * Entry 'e' can be a TCAM entry or a entry entry, not bank entry */
   3147 int
   3148 th_alpm_ent_selective_get(int u, _alpm_cb_t *acb, void *ent, _alpm_ent_info_t *info)
   3149 {
   3150     int rv = BCM_E_NONE;
   3151     int ent_fmt, vrf_id, ipt, pvt_pkm;
   3152     uint32 mask = info->action_mask;
   3153 
   3154     /* ent_fmt or sub_idx */
   3155     ent_fmt = info->ent_fmt;
   3156     vrf_id  = info->vrf_id;
   3157     ipt     = info->ipt;
   3158     pvt_pkm = info->pvt_pkm;
   3159 
   3160     if (mask & (ALPM_INFO_MASK_VALID | ALPM_INFO_MASK_KEYLEN)) {
   3161         th_alpm_bkt_pfx_get(u, vrf_id, acb, ent, ent_fmt, &info->ent_valid,
   3162                             info->key, &info->key_len);
   3163     }
   3164 
   3165     if (mask & ALPM_INFO_MASK_ASSOC_DATA) {
   3166         th_alpm_bkt_adata_get(u, vrf_id, ipt, acb, ent, ent_fmt, info);
   3167     }
   3168 
   3169     if (mask & ALPM_INFO_MASK_ALPM_DATA) {
   3170         /* Here ent is TCAM entry */
   3171         th_alpm_ent_binfo_get(u, vrf_id, ipt, pvt_pkm, acb, ent, ent_fmt, info);
   3172     }
   3173 
   3174     if (mask & ALPM_INFO_MASK_ALPM_DATA_RAW) {
   3175         th_alpm_ent_binfo_raw_get(u, vrf_id, acb, ent, ent_fmt, info->alpm_data_raw);
   3176     }
   3177 
   3178     if (mask & ALPM_INFO_MASK_FIXED_DATA) {
   3179         /* For TCAM entry only */;
   3180     }
   3181 
   3182     return rv;
   3183 }
   3184 
   3185 /* Return ALPM bucket bank default (minimum) format according to DB_Type */
   3186 uint8
   3187 th_alpm_bkt_def_fmt_get(int u, _alpm_cb_t *acb, int vrf_id, int ipt)
   3188 {
   3189     int bkt_pkm;
   3190 
   3191     static uint8 def_fmt[] = {
   3192         ALPM_FMT_PKM_32B,
   3193         ALPM_FMT_PKM_FLEX_32B,
   3194         ALPM_FMT_PKM_64B,
   3195         ALPM_FMT_PKM_FLEX_64B,
   3196         ALPM_FMT_PKM_128,
   3197         ALPM_FMT_PKM_FLEX_128
   3198     };
   3199 
   3200     if (ALPM_IS_IPV6(ipt)) {
   3201         if (ALPM_128B(u)) {
   3202             bkt_pkm = ALPM_PKM_128;
   3203         } else {
   3204             bkt_pkm = ALPM_PKM_64B;
   3205         }
   3206     } else {
   3207         bkt_pkm = ALPM_PKM_32B;
   3208     }
   3209 
   3210     return def_fmt[bkt_pkm << 1 | ACB_VRF_DB_TYPE(u, acb, vrf_id, ipt)];
   3211 }
   3212 
   3213 /* Return Reduced/Full format type for a given fmt */
   3214 int16
   3215 th_alpm_bkt_fmt_type_get(int u, int vrf_id, _alpm_cb_t *acb, uint8 fmt)
   3216 {
   3217     return ACB_FMT_FULL_TYPE(acb, vrf_id, fmt);
   3218 }
   3219 
   3220 /*
   3221  * Function:
   3222  *      th_alpm_table_dump
   3223  * Purpose:
   3224  *      Dump ALPM memory tables:
   3225  *      "alpm table dump [raw|chg|all|nocache] <mem> <index> <format> [<ent>]"
   3226  * Parameters:
   3227  *      u       - Device unit #
   3228  *      mem     - ALPM Level2 or Level3 memory table
   3229  *      copyno  - mem table copy number
   3230  *      index   - ALPM bucket level logic table index
   3231  *      fmt     - Bank format (1-8 for Pivot formats, 1-12 for Route formats)
   3232  *      ent_idx - entry index (0-14), -1 for all entries.
   3233  *      flags   - Dump flags (raw, chg, all, nocache)
   3234  * Returns:
   3235  *      BCM_E_XXX
   3236  */
   3237 void
   3238 th_alpm_table_ent_dump(int u, int vrf_id, soc_mem_t mem, void *entry,
   3239                        int copyno, int index, int fmt, int ent_idx,
   3240                        int flags, char *pfx)
   3241 {
   3242     int     i, ent, ent_min, ent_max;
   3243     int     f, entry_dw;
   3244     int     first_print_flag = 0;
   3245     int     vertical = 0;
   3246     uint32  fent[ALPM_MEM_ENT_MAX];
   3247     uint32  fval[ALPM_MEM_ENT_MAX];
   3248     uint32  nfval[ALPM_MEM_ENT_MAX];
   3249     char    ctmp[ALPM_MEM_ENT_MAX * 8 + 3];
   3250     soc_field_info_t *fieldp;
   3251     soc_format_info_t *fmtp;
   3252     soc_format_t tfmt;
   3253     int fmt_ent_max[] = {0, 6, 4, 2, 4, 3, 2};
   3254 
   3255     _alpm_cb_t *acb;
   3256 
   3257     if (ent_idx >= fmt_ent_max[fmt]) {
   3258         return;
   3259     }
   3260 
   3261     acb = ACB_TOP(u);
   3262     tfmt = ACB_FMT_ENT(acb, vrf_id, fmt);
   3263 
   3264     if (ent_idx == -1) { /* all entries */
   3265         ent_min = 0;
   3266         ent_max = fmt_ent_max[fmt] - 1;
   3267     } else { /* one specific entry */
   3268         ent_min = ent_idx;
   3269         ent_max = ent_idx;
   3270     }
   3271 
   3272     sal_memset(nfval, 0, sizeof(nfval));
   3273 
   3274     for (ent = ent_min; ent <= ent_max; ent++) {
   3275         soc_format_field_get(u, ACB_FMT_BNK(acb, vrf_id, fmt), entry,
   3276                              th_alpm_ent_fld[ent], fent);
   3277         fmtp = &SOC_FORMAT_INFO(u, tfmt);
   3278 
   3279         if (flags & ALPM_DUMP_TABLE_RAW) {
   3280             cli_out("%s", pfx);
   3281             entry_dw = BITS2WORDS(fmtp->bits);
   3282             for (i = 0; i < entry_dw; i++) {
   3283                 cli_out("0x%08x ", fent[i]);
   3284             }
   3285             cli_out("\n");
   3286         } else {
   3287             /* for fields in entry format */
   3288             for (f = fmtp->nFields - 1; f >= 0; f--) {
   3289                 fieldp = &fmtp->fields[f];
   3290                 sal_memset(fval, 0, ALPM_MEM_ENT_MAX * sizeof(uint32));
   3291                 soc_format_field_get(u, tfmt, fent, fieldp->field, fval);
   3292 
   3293                 if (flags & ALPM_DUMP_TABLE_CHANGED) {
   3294                     if (sal_memcmp(fval, nfval, ALPM_MEM_ENT_MAX *
   3295                                    sizeof(uint32)) == 0) {
   3296                         continue;
   3297                     }
   3298                 }
   3299                 _shr_format_long_integer(ctmp, fval, BITS2BYTES(fieldp->len));
   3300 
   3301                 if (first_print_flag == 0) {
   3302                     cli_out("%s%s", pfx, vertical ? "" : "<");
   3303                     first_print_flag=1;
   3304                 }
   3305                 if (vertical) {
   3306                     cli_out("\n\t%30s: %s", SOC_FIELD_NAME(u, fieldp->field), ctmp);
   3307                 } else {
   3308                     cli_out("%s=%s%s", SOC_FIELD_NAME(u, fieldp->field),
   3309                             ctmp, f > 0 ? "," : "");
   3310                 }
   3311             } /* for f */
   3312 
   3313             if (first_print_flag == 1) {
   3314                 cli_out("%s\n", vertical ? "" : ">");
   3315                 first_print_flag = 0;
   3316             }
   3317         }
   3318     } /* for ent */
   3319 }
   3320 
   3321 int
   3322 th_alpm_table_dump(int u, int vrf_id, soc_mem_t mem, int copyno, int index,
   3323                    int fmt, int ent_idx, int flags)
   3324 {
   3325     int rv = BCM_E_NONE;
   3326     uint32  entry[ALPM_MEM_ENT_MAX];
   3327     char    mem_prefix[256] = {0};
   3328 
   3329     if ((fmt <= 0) || (fmt > 6)) {
   3330         cli_out("invalid or disabled bank format %d\n", fmt);
   3331         return BCM_E_INTERNAL;
   3332     }
   3333 
   3334     if (flags & ALPM_DUMP_TABLE_NOCACHE) {
   3335         rv = soc_mem_read_no_cache(u, 0, mem, 0, MEM_BLOCK_ANY, index, entry);
   3336     } else {
   3337         rv = soc_mem_read(u, mem, MEM_BLOCK_ANY, index, entry);
   3338     }
   3339 
   3340     if (BCM_SUCCESS(rv)) {
   3341         sal_sprintf(mem_prefix, "%s.%s[%d.%d]: ", SOC_MEM_UFNAME(u, mem),
   3342                     SOC_BLOCK_NAME(u, copyno), index, ent_idx);
   3343         th_alpm_table_ent_dump(u, vrf_id, mem, entry, copyno, index, fmt,
   3344                                ent_idx, flags, mem_prefix);
   3345     }
   3346 
   3347     return rv;
   3348 }
   3349 
   3350 #define ALPM_PHY_BKT_CNT(u) (SOC_IS_HELIX5(u) ? 4096 : 8192)
   3351 
   3352 /*
   3353  * Function:
   3354  *      th_alpm_cap_min
   3355  * Purpose:
   3356  *      Get the min capacity for ALPM routes from PKM
   3357  * Parameters:
   3358  *      u           - Device unit
   3359  *      mem         - hardware memory
   3360  */
   3361 int
   3362 th_alpm_cap_min(int u, soc_mem_t mem)
   3363 {
   3364 #define UTIL_33(x) ((x) / 3)
   3365 #define UTIL_66(x) ((x) * 2 / 3)
   3366 #define UTIL_85(x) ((x) * 85 / 100)
   3367 
   3368     int min_ent = 0, tcam_ent = 0, tot_rte = 0, tot_bkt = 0;
   3369     int pkm;
   3370     int urpf = SOC_URPF_STATUS_GET(u);
   3371     int tcam_alpm = 0;
   3372     int pid, fmt;
   3373     _alpm_bkt_pool_conf_t *bp_conf;
   3374     _alpm_cb_t *acb;
   3375 
   3376     acb = ACB_BTM(u);
   3377 
   3378     switch (ALPM_MODE(u)) {
   3379         case BCM_ALPM_MODE_COMBINED:
   3380         case BCM_ALPM_MODE_PARALLEL:
   3381             break;
   3382         case BCM_ALPM_MODE_TCAM_ALPM:
   3383             tcam_alpm = 1;
   3384             break;
   3385         default:
   3386             return 0;
   3387     }
   3388 
   3389     switch (mem) {
   3390     case L3_DEFIP_ALPM_IPV4m:
   3391         fmt = 1;
   3392         pkm = ALPM_PKM_32B;
   3393         break;
   3394     case L3_DEFIP_ALPM_IPV4_1m:
   3395         fmt = 4;
   3396         pkm = ALPM_PKM_32B;
   3397         break;
   3398     case L3_DEFIP_ALPM_IPV6_64m:
   3399         fmt = 2;
   3400         pkm = ALPM_PKM_64B;
   3401         break;
   3402     case L3_DEFIP_ALPM_IPV6_64_1m:
   3403         fmt = 5;
   3404         pkm = ALPM_PKM_64B;
   3405         break;
   3406     case L3_DEFIP_ALPM_IPV6_128m:
   3407         fmt = 3;
   3408         pkm = ALPM_PKM_128;
   3409         break;
   3410     default:
   3411         fmt = 1;
   3412         pkm = ALPM_PKM_32B;
   3413         break;
   3414     }
   3415 
   3416     /* include VRF private and global routes */
   3417     for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) {
   3418         int avl_bnks;
   3419         bp_conf = ACB_BKT_POOL(acb, pid);
   3420         if (pid > 0 && bp_conf == ACB_BKT_POOL(acb, pid - 1)) {
   3421             continue; /* Combined Mode uses PID=0 only */
   3422         }
   3423 
   3424         /* Exclude reserved bucket 0 */
   3425         avl_bnks = BPC_BNK_CNT(bp_conf) - BPC_BNK_PER_BKT(bp_conf);
   3426         if (ALPM_128B(u) && ALPM_BKT_RSVD(u)) {
   3427             int rsvd_v6_bnks =
   3428                 BPC_BNK_CNT(bp_conf) * ALPM_BKT_RSVD_CNT(u) / ALPM_PHY_BKT_CNT(u);
   3429             if (pkm == ALPM_PKM_128) {
   3430                 avl_bnks = rsvd_v6_bnks;
   3431             } else {
   3432                 avl_bnks -= rsvd_v6_bnks;
   3433             }
   3434         }
   3435 
   3436         tot_rte += avl_bnks * BPC_FMT_ENT_MAX(bp_conf, fmt);
   3437         tot_bkt += BPC_BNK_PER_BKT(bp_conf) ?
   3438             (avl_bnks / BPC_BNK_PER_BKT(bp_conf)) : 0;
   3439     }
   3440 
   3441     switch (mem) {
   3442     case L3_DEFIP_ALPM_IPV4m:
   3443     case L3_DEFIP_ALPM_IPV4_1m:
   3444         tcam_ent = soc_mem_index_count(u, L3_DEFIPm) * 2;
   3445         break;
   3446 
   3447     case L3_DEFIP_ALPM_IPV6_64m:
   3448     case L3_DEFIP_ALPM_IPV6_64_1m:
   3449         tcam_ent = soc_mem_index_count(u, L3_DEFIPm);
   3450         break;
   3451 
   3452     case L3_DEFIP_ALPM_IPV6_128m:
   3453         tcam_ent = soc_mem_index_count(u, L3_DEFIP_PAIR_128m);
   3454         break;
   3455 
   3456     default:
   3457         break;
   3458     }
   3459 
   3460     if (tcam_alpm) {
   3461         tcam_ent /= 2;
   3462     }
   3463 
   3464     if (tcam_ent) {
   3465         tcam_ent = tcam_ent >> urpf;
   3466 
   3467         if (tcam_ent <= tot_bkt) {
   3468             min_ent = UTIL_33(tot_rte / tot_bkt) * tcam_ent;
   3469         } else {
   3470             min_ent = UTIL_33(tot_rte / tot_bkt) * tot_bkt;
   3471         }
   3472         if (tcam_alpm) {
   3473             min_ent += tcam_ent;
   3474         }
   3475     } else {
   3476         min_ent = 0;
   3477     }
   3478 
   3479     return min_ent;
   3480 
   3481 }
   3482 
   3483 /*
   3484  * Function:
   3485  *      th_alpm_cap_max
   3486  * Purpose:
   3487  *      Get the max capacity for ALPM routes from PKM
   3488  * Parameters:
   3489  *      u           - Device unit
   3490  *      mem         - hardware memory
   3491  */
   3492 static int
   3493 th_alpm_cap_max(int u, soc_mem_t mem)
   3494 {
   3495     int pkm;
   3496     int tcam_ent = 0, tot_rte = 0, tot_bkt = 0;
   3497     int urpf = SOC_URPF_STATUS_GET(u);
   3498     int tcam_alpm = 0;
   3499     int pid, fmt;
   3500     _alpm_bkt_pool_conf_t *bp_conf;
   3501     _alpm_cb_t *acb;
   3502 
   3503     acb = ACB_BTM(u);
   3504 
   3505     switch (ALPM_MODE(u)) {
   3506         case BCM_ALPM_MODE_COMBINED:
   3507         case BCM_ALPM_MODE_PARALLEL:
   3508             break;
   3509         case BCM_ALPM_MODE_TCAM_ALPM:
   3510             tcam_alpm = 1;
   3511             break;
   3512         default:
   3513             return 0;
   3514     }
   3515 
   3516     switch (mem) {
   3517     case L3_DEFIP_ALPM_IPV4m:
   3518         pkm = ALPM_PKM_32B;
   3519         fmt = 1;
   3520         break;
   3521     case L3_DEFIP_ALPM_IPV4_1m:
   3522         pkm = ALPM_PKM_32B;
   3523         fmt = 4;
   3524         break;
   3525     case L3_DEFIP_ALPM_IPV6_64m:
   3526         pkm = ALPM_PKM_64B;
   3527         fmt = 2;
   3528         break;
   3529     case L3_DEFIP_ALPM_IPV6_64_1m:
   3530         pkm = ALPM_PKM_64B;
   3531         fmt = 5;
   3532         break;
   3533     case L3_DEFIP_ALPM_IPV6_128m:
   3534         pkm = ALPM_PKM_128;
   3535         fmt = 3;
   3536         break;
   3537     default:
   3538         pkm = ALPM_PKM_32B;
   3539         fmt = 1;
   3540         break;
   3541     }
   3542 
   3543     /* include VRF private and global routes */
   3544     for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) {
   3545         int avl_bnks;
   3546         bp_conf = ACB_BKT_POOL(acb, pid);
   3547         if (pid > 0 && bp_conf == ACB_BKT_POOL(acb, pid - 1)) {
   3548             continue; /* Combined Mode uses PID=0 only */
   3549         }
   3550 
   3551         /* Exclude reserved bucket 0 */
   3552         avl_bnks = BPC_BNK_CNT(bp_conf) - BPC_BNK_PER_BKT(bp_conf);
   3553 
   3554         if (ALPM_128B(u) && ALPM_BKT_RSVD(u)) {
   3555             int rsvd_v6_bnks =
   3556                 BPC_BNK_CNT(bp_conf) * ALPM_BKT_RSVD_CNT(u) / ALPM_PHY_BKT_CNT(u);
   3557             if (pkm == ALPM_PKM_128) {
   3558                 avl_bnks = rsvd_v6_bnks;
   3559             } else {
   3560                 avl_bnks -= rsvd_v6_bnks;
   3561             }
   3562         }
   3563 
   3564         tot_rte += avl_bnks * BPC_FMT_ENT_MAX(bp_conf, fmt);
   3565         tot_bkt += BPC_BNK_PER_BKT(bp_conf) ?
   3566             (avl_bnks / BPC_BNK_PER_BKT(bp_conf)) : 0;
   3567     }
   3568 
   3569     switch (mem) {
   3570     case L3_DEFIP_ALPM_IPV4m:
   3571     case L3_DEFIP_ALPM_IPV4_1m:
   3572         tcam_ent = soc_mem_index_count(u, L3_DEFIPm) * 2;
   3573         break;
   3574 
   3575     case L3_DEFIP_ALPM_IPV6_64m:
   3576     case L3_DEFIP_ALPM_IPV6_64_1m:
   3577         tcam_ent = soc_mem_index_count(u, L3_DEFIPm);
   3578         break;
   3579 
   3580     case L3_DEFIP_ALPM_IPV6_128m:
   3581         tcam_ent = soc_mem_index_count(u, L3_DEFIP_PAIR_128m);
   3582         break;
   3583 
   3584     default:
   3585         tot_rte = 0;
   3586         break;
   3587     }
   3588 
   3589     if (tcam_alpm) {
   3590         tcam_ent /= 2;
   3591     }
   3592 
   3593     if (tcam_ent) {
   3594         tcam_ent = tcam_ent >> urpf;
   3595 
   3596         if (tcam_ent <= tot_bkt) {
   3597             tot_rte = (tot_rte / tot_bkt) * tcam_ent;
   3598         }
   3599         if (tcam_alpm) {
   3600             tot_rte += tcam_ent;
   3601         }
   3602     } else {
   3603         tot_rte = 0;
   3604     }
   3605 
   3606     return tot_rte;
   3607 
   3608 }
   3609 
   3610 /*
   3611  * Function:
   3612  *      th_alpm_cap_get
   3613  * Purpose:
   3614  *      Get the min or max capacity for ALPM routes from tables:
   3615  * L3_DEFIP_ALPM_IPV4, L3_DEFIP_ALPM_IPV6_64, L3_DEFIP_ALPM_IPV6_128
   3616  *
   3617  * Parameters:
   3618  *      u           - Device unit
   3619  *      mem         - Legacy memory type
   3620  *      max_cnt     - Maximum result returned.
   3621  *      min_cnt     - Minimum result returned.
   3622  */
   3623 int
   3624 th_alpm_cap_get(int u, soc_mem_t mem, int *max_cnt, int *min_cnt)
   3625 {
   3626 
   3627     switch (mem) {
   3628         case L3_DEFIP_ALPM_IPV4m:
   3629         case L3_DEFIP_ALPM_IPV4_1m:
   3630         case L3_DEFIP_ALPM_IPV6_64m:
   3631         case L3_DEFIP_ALPM_IPV6_64_1m:
   3632         case L3_DEFIP_ALPM_IPV6_128m:
   3633             break;
   3634         default:
   3635             return BCM_E_UNAVAIL;
   3636     }
   3637 
   3638     if (min_cnt != NULL) {
   3639         *min_cnt = th_alpm_cap_min(u, mem);
   3640     }
   3641 
   3642     if (max_cnt != NULL) {
   3643         *max_cnt = th_alpm_cap_max(u, mem);
   3644     }
   3645 
   3646     return BCM_E_NONE;
   3647 }
   3648 
   3649 
   3650 static int
   3651 th_alpm_hit_tbl_idx_get(int u, _alpm_cb_t *acb, _alpm_tbl_t tbl, int idx, int ent)
   3652 {
   3653     int phy_idx;
   3654     phy_idx = th_mem_phy_index_get(u, acb, tbl, idx);
   3655 #if defined(BCM_HELIX5_SUPPORT)
   3656 #define HX5_ALPM_4_BANK_MODE_BANK_BITS 2
   3657     if (soc_feature(u, soc_feature_alpm_addr_xlate)) {
   3658         int phy_bnk;
   3659         int phy_bkt;
   3660         phy_bnk = phy_idx >> HX5_ALPM_PHY_BKT_BITS;
   3661         phy_bkt = phy_idx & ((1 << HX5_ALPM_PHY_BKT_BITS) - 1);
   3662         if (soc_alpm_cmn_banks_get(u) == 6) {
   3663             phy_idx = ent * HX5_ALPM_BKT_ENT_MAX + phy_bnk;
   3664             phy_idx = (phy_idx << HX5_ALPM_PHY_BKT_BITS) | phy_bkt;
   3665         } else {
   3666             phy_idx = (ent << HX5_ALPM_4_BANK_MODE_BANK_BITS) | phy_bnk;
   3667             phy_idx = (phy_idx << HX5_ALPM_PHY_BKT_BITS) | phy_bkt;
   3668         }
   3669     } else
   3670 #endif
   3671     {
   3672         phy_idx =(ent << (ACB_BNK_BITS(acb) + TD3_ALPM_BKT_BITS)) | phy_idx;
   3673     }
   3674     return phy_idx;
   3675 }
   3676 /*
   3677  * Function:
   3678  *      th_alpm_bkt_hit_get
   3679  * Purpose:
   3680  *      Get ALPM bucket entry hitbit status from hitbit table cache
   3681  *      sync with Hw. Route hitbit status is gathered from pivots
   3682  *      whose BPM is the route.
   3683  * Parameters:
   3684  *      u       - Device unit #
   3685  *      vrf_id  - VRF ID for logic hit table PID in Parallel/Mixed Mode
   3686  *      acb     - ALPM control block where hit table located
   3687  *      idx     - ALPM bucket level logic table index
   3688  *      ent     - Bucket entry ID (0-15)
   3689  * Returns:
   3690  *      Bucket entry hitbit (0 or 1)
   3691  */
   3692 int
   3693 th_alpm_bkt_hit_get(int u, int vrf_id, _alpm_cb_t *acb,
   3694                     _alpm_tbl_t tbl, int idx, int ent)
   3695 {
   3696     int rv;
   3697     int hit_hit_offset;
   3698     int hit_tab_idx;
   3699     uint32 *tbl_ent; /* bucket hit cache table entry pointer */
   3700     int i = ACB_IDX(acb);
   3701     int pid = 0;
   3702     soc_mem_t mem = ALPM_HTBL_MEM(u, i, pid);
   3703     soc_field_t hit_fld[4] = {
   3704         HIT_0f, HIT_1f, HIT_2f,  HIT_3f
   3705     };
   3706 
   3707     ALPM_HIT_LOCK(u);
   3708 
   3709     hit_tab_idx = th_alpm_hit_tbl_idx_get(u ,acb, tbl, idx, ent);
   3710 
   3711     hit_hit_offset = hit_tab_idx % 4;
   3712     hit_tab_idx /= 4;
   3713 
   3714     tbl_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 *,
   3715                                            ALPM_HTBL_CACHE(u, i, pid), hit_tab_idx);
   3716     rv = soc_mem_field32_get(u, mem, tbl_ent, hit_fld[hit_hit_offset]);
   3717 
   3718     ALPM_HIT_UNLOCK(u);
   3719     return rv;
   3720 }
   3721 
   3722 /*
   3723  * Function:
   3724  *      th_alpm_bkt_hit_set
   3725  * Purpose:
   3726  *      Set ALPM bucket entry hitbit to cache table only
   3727  * Parameters:
   3728  *      u       - Device unit #.
   3729  *      vrf_id  - VRF ID for logic hit table PID in Parallel/Mixed Mode
   3730  *      acb     - ALPM control block where hit table located
   3731  *      idx     - ALPM bucket level table index
   3732  *      ent     - Bucket entry ID (0-15)
   3733  *      hit_val - Bucket entry hit value (0/1)
   3734  * Returns:
   3735  *      BCM_E_XXX
   3736  */
   3737 int
   3738 th_alpm_bkt_hit_set(int u, int vrf_id, _alpm_cb_t *acb, _alpm_tbl_t tbl,
   3739                     int idx, int ent, int hit_val)
   3740 {
   3741     int rv = BCM_E_NONE;
   3742     int hit_bit_offset;
   3743     int hit_tab_idx;
   3744     uint32 *tbl_ent; /* bucket hit cache table entry pointer */
   3745     int i = ACB_IDX(acb);
   3746     int pid = 0;
   3747     soc_mem_t mem = ALPM_HTBL_MEM(u, i, pid);
   3748     soc_field_t hit_fld[4] = {
   3749         HIT_0f, HIT_1f, HIT_2f,  HIT_3f
   3750     };
   3751 
   3752     ALPM_HIT_LOCK(u);
   3753 
   3754     hit_tab_idx = th_alpm_hit_tbl_idx_get(u, acb, tbl, idx, ent);
   3755 
   3756     hit_bit_offset = hit_tab_idx % 4;
   3757     hit_tab_idx /= 4;
   3758 
   3759     tbl_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 *,
   3760                                            ALPM_HTBL_CACHE(u, i, pid), hit_tab_idx);
   3761     soc_mem_field32_set(u, mem, tbl_ent, hit_fld[hit_bit_offset], hit_val);
   3762 
   3763     ALPM_HIT_UNLOCK(u);
   3764     return rv;
   3765 }
   3766 
   3767 /*
   3768  * Function:
   3769  *      th_alpm_bkt_hit_write
   3770  * Purpose:
   3771  *      Set ALPM bucket entry hitbit status to hitbit table cache
   3772  *      and write to Hw (by setting Entry Move & Mask to trigger write to Hw
   3773  *      in next Dist Hitbit thread clycle).
   3774  * Parameters:
   3775  *      u       - Device unit #
   3776  *      vrf_id  - VRF ID for logic hit table PID in Parallel/Mixed Mode
   3777  *      acb     - ALPM control block where hit table located
   3778  *      ent_idx - ALPM bucket node ent_idx
   3779  *      hit_val - HITBIT value requested
   3780  * Returns:
   3781  *      BCM_E_XXX
   3782  */
   3783 int
   3784 th_alpm_bkt_hit_write(int u, int vrf_id, _alpm_cb_t *acb,
   3785                       _alpm_tbl_t tbl, int ent_idx, int hit_val)
   3786 {
   3787     int rv = BCM_E_NONE;
   3788     int idx, ent;
   3789     int hit_tab_idx;
   3790     uint32 *dst_ent; /* bucket hit cache table entry pointer */
   3791     int i = ACB_IDX(acb);
   3792     int pid = 0;
   3793     soc_mem_t mem = ALPM_HTBL_MEM(u, i, pid);
   3794     soc_field_t hit_fld[4] = {
   3795         HIT_0f, HIT_1f, HIT_2f,  HIT_3f
   3796     };
   3797 
   3798     ALPM_HIT_LOCK(u);
   3799 
   3800     ent = ALPM_IDX_TO_ENT(ent_idx);
   3801     hit_tab_idx = th_alpm_hit_tbl_idx_get(u, acb, tbl, ent_idx, ent);
   3802 
   3803     ent = hit_tab_idx % 4;
   3804     idx = hit_tab_idx / 4;
   3805 
   3806     /* Write hit_val to dst cache hit bit */
   3807     dst_ent = soc_mem_table_idx_to_pointer(u, mem, void *,
   3808                                            ALPM_HTBL_CACHE(u, i, pid), idx);
   3809     soc_mem_field32_set(u, mem, dst_ent, hit_fld[ent], hit_val);
   3810 
   3811     /* Write hit_val to dst move bit */
   3812     dst_ent = soc_mem_table_idx_to_pointer(u, mem, void *,
   3813                                            ALPM_HTBL_MOVE(u, i, pid), idx);
   3814     soc_mem_field32_set(u, mem, dst_ent, hit_fld[ent], hit_val);
   3815 
   3816     /* Set dst move mask bit */
   3817     dst_ent = soc_mem_table_idx_to_pointer(u, mem, void *,
   3818                                       ALPM_HTBL_MOVE_MASK(u, i, pid), idx);
   3819     soc_mem_field32_set(u, mem, dst_ent, hit_fld[ent], 1);
   3820 
   3821     /* declare finally hitbit entry_moved flag */
   3822     ALPM_HTBL_ENT_MOVED(u, i, pid) = TRUE;
   3823 
   3824     ALPM_HIT_UNLOCK(u);
   3825 
   3826     return rv;
   3827 }
   3828 
   3829 /* ALPM bucket hitbit entry move from bkt_node's src_ent_idx to dst_ent_idx.
   3830    Copy hit bit cache, and set properly move, move_mask and ent_moved flag.
   3831  */
   3832 int
   3833 th_alpm_ent_hit_move(int u, int vrf_id, _alpm_cb_t *acb, _alpm_tbl_t tbl,
   3834                      int src_ent_idx, int dst_ent_idx)
   3835 {
   3836     int rv = BCM_E_NONE;
   3837     int i, hit_val, idx, ent;
   3838     uint32 *src_ent, *dst_ent;
   3839     int pid = 0;
   3840     int hit_tab_idx;
   3841     soc_mem_t mem;
   3842     soc_field_t hit_fld[4] = {
   3843         HIT_0f, HIT_1f, HIT_2f,  HIT_3f
   3844     };
   3845 
   3846     ALPM_HIT_LOCK(u);
   3847 
   3848     i = ACB_IDX(acb);
   3849     mem = ALPM_HTBL_MEM(u, i, pid);
   3850 
   3851     ent = ALPM_IDX_TO_ENT(src_ent_idx);
   3852     hit_tab_idx = th_alpm_hit_tbl_idx_get(u, acb, tbl, src_ent_idx, ent);
   3853 
   3854     ent = hit_tab_idx % 4;
   3855     idx = hit_tab_idx / 4;
   3856 
   3857 
   3858     /* Save src cache hit_val and clear it */
   3859     src_ent = soc_mem_table_idx_to_pointer(u, mem, void *,
   3860                                            ALPM_HTBL_CACHE(u, i, pid), idx);
   3861     hit_val = soc_mem_field32_get(u, mem, src_ent, hit_fld[ent]);
   3862     soc_mem_field32_set(u, mem, src_ent, hit_fld[ent], 0);
   3863 
   3864     /* Clear src move bit */
   3865     src_ent = soc_mem_table_idx_to_pointer(u, mem, void *,
   3866                                            ALPM_HTBL_MOVE(u, i, pid), idx);
   3867     soc_mem_field32_set(u, mem, src_ent, hit_fld[ent], 0);
   3868 
   3869     /* Set src move mask bit */
   3870     src_ent = soc_mem_table_idx_to_pointer(u, mem, void *,
   3871                                            ALPM_HTBL_MOVE_MASK(u, i, pid), idx);
   3872     soc_mem_field32_set(u, mem, src_ent, hit_fld[ent], 1);
   3873 
   3874     /* 2) Dst */
   3875     ent = ALPM_IDX_TO_ENT(dst_ent_idx);
   3876     hit_tab_idx = th_alpm_hit_tbl_idx_get(u, acb, tbl, dst_ent_idx, ent);
   3877 
   3878     ent = hit_tab_idx % 4;
   3879     idx = hit_tab_idx / 4;
   3880 
   3881 
   3882     /* Write hit_val to dst cache hit bit */
   3883     dst_ent = soc_mem_table_idx_to_pointer(u, mem, void *,
   3884                                            ALPM_HTBL_CACHE(u, i, pid), idx);
   3885     soc_mem_field32_set(u, mem, dst_ent, hit_fld[ent], hit_val);
   3886 
   3887     /* Write hit_val to dst move bit */
   3888     dst_ent = soc_mem_table_idx_to_pointer(u, mem, void *,
   3889                                            ALPM_HTBL_MOVE(u, i, pid), idx);
   3890     soc_mem_field32_set(u, mem, dst_ent, hit_fld[ent], hit_val);
   3891 
   3892     /* Set dst move mask bit */
   3893     dst_ent = soc_mem_table_idx_to_pointer(u, mem, void *,
   3894                                       ALPM_HTBL_MOVE_MASK(u, i, pid), idx);
   3895     soc_mem_field32_set(u, mem, dst_ent, hit_fld[ent], 1);
   3896 
   3897     /* declare finally hitbit entry_moved flag */
   3898     ALPM_HTBL_ENT_MOVED(u, i, pid) = TRUE;
   3899 
   3900     ALPM_HIT_UNLOCK(u);
   3901 
   3902     return rv;
   3903 }
   3904 
   3905 /* ALPM bucket bank hitbit move from src_idx to dst_idx.
   3906    Copy hit bit cache, and set properly move, move_mask and ent_moved flag.
   3907  */
   3908 int
   3909 th_alpm_bnk_hit_move(int u, int vrf_id, _alpm_cb_t *acb,
   3910                      _alpm_bkt_info_t *bkt_info, _alpm_tbl_t tbl,
   3911                      int src_idx, int dst_idx)
   3912 {
   3913     int i;
   3914     int ent_max;
   3915     int src_ent_idx;
   3916     int dst_ent_idx;
   3917     int sbnk;
   3918     int rv = BCM_E_NONE;
   3919     sbnk = ALPM_IDX_TO_BNK(acb, src_idx);
   3920     ent_max = ACB_FMT_ENT_MAX(acb, vrf_id, bkt_info->bnk_fmt[sbnk]);
   3921     for (i = 0; i < ent_max; i++) {
   3922         src_ent_idx = (i << ALPM_IDX_ENT_SHIFT) | src_idx;
   3923         dst_ent_idx = (i << ALPM_IDX_ENT_SHIFT) | dst_idx;
   3924         rv = th_alpm_ent_hit_move(u, vrf_id, acb, tbl, src_ent_idx, dst_ent_idx);
   3925     }
   3926 
   3927     return rv;
   3928 }
   3929 
   3930 /* Clear ALPM bucket bank hitbit cache at idx.
   3931    Set properly move, move_mask and ent_moved flag.
   3932  */
   3933 int
   3934 th_alpm_bnk_hit_clear(int u, int vrf_id, _alpm_cb_t *acb,
   3935                       _alpm_bkt_info_t *bkt_info, _alpm_tbl_t tbl,
   3936                       int idx)
   3937 {
   3938     int i;
   3939     int ent_max;
   3940     int rv = BCM_E_NONE;
   3941     int ent_idx;
   3942     int bnk;
   3943     bnk = ALPM_IDX_TO_BNK(acb, idx);
   3944     ent_max = ACB_FMT_ENT_MAX(acb, vrf_id, bkt_info->bnk_fmt[bnk]);
   3945     for (i = 0; i < ent_max; i++) {
   3946         ent_idx = (i << ALPM_IDX_ENT_SHIFT) | idx;
   3947         rv = th_alpm_bkt_hit_write(u, vrf_id, acb, tbl, ent_idx, 0);
   3948     }
   3949 
   3950     return rv;
   3951 }
   3952 
   3953 /* Update hitbit for entry move on level i by
   3954  * hit_cache = (hit_cache & ~hit_move_mask) | (hit_move & hit_move_mask)
   3955  */
   3956 int
   3957 th_alpm_hit_move_update(int u, int i, int pid)
   3958 {
   3959     int rv = BCM_E_NONE;
   3960     int idx, index_cnt;
   3961     uint32 hit_cache, hit_move, hit_move_mask;
   3962     uint32 *cache_ent, *move_ent, *move_mask_ent;
   3963     soc_mem_t mem;
   3964 
   3965     if (!ALPM_HTBL_ENT_MOVED(u, i, pid)) {
   3966         return rv;
   3967     }
   3968 
   3969     mem = ALPM_HTBL_MEM(u, i, pid);
   3970     index_cnt = ALPM_HTBL_IDX_CNT(u, i, pid);
   3971 
   3972     ALPM_HTBL_ENT_MOVED_CNT(u, i, pid) = 0;
   3973     for (idx = 0; idx < index_cnt; idx++) {
   3974         move_mask_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 *,
   3975                                     ALPM_HTBL_MOVE_MASK(u, i, pid), idx);
   3976         hit_move_mask = *move_mask_ent;
   3977 
   3978         if (hit_move_mask) {
   3979             cache_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 * ,
   3980                                         ALPM_HTBL_CACHE(u, i, pid), idx);
   3981             move_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 *,
   3982                                         ALPM_HTBL_MOVE(u, i, pid), idx);
   3983             hit_cache = *cache_ent;
   3984             hit_move =  *move_ent;
   3985 
   3986             /* update cache entry */
   3987             *cache_ent = (hit_cache & ~hit_move_mask) |
   3988                             (hit_move & hit_move_mask);
   3989 
   3990             ALPM_HTBL_ENT_MOVED_CNT(u, i, pid)++;
   3991         }
   3992     }
   3993 
   3994     return rv;
   3995 }
   3996 
   3997 /* Sync ALPM non-TCAM level (i:0/1 for level 2/3) hitbit cache with Hw */
   3998 int
   3999 th_alpm_hit_cache_sync(int u, int i, int pid)
   4000 {
   4001     soc_mem_t mem;
   4002     int idx_max, offset = 0;
   4003     int rv = BCM_E_NONE;
   4004 
   4005     mem = ALPM_HTBL_MEM(u, i, pid);
   4006     idx_max = ALPM_HTBL_IDX_CNT(u, i, pid) - 1;
   4007 
   4008     rv = soc_mem_read_range(u, mem, MEM_BLOCK_ANY, offset, idx_max + offset,
   4009                             ALPM_HTBL_CACHE(u, i, pid));
   4010 
   4011     return rv;
   4012 }
   4013 
   4014 /* Write ALPM non-TCAM level (i:0/1 for level 2/3) hitbit cache to Hw */
   4015 int
   4016 th_alpm_hit_hw_write(int u, int i, int pid)
   4017 {
   4018     soc_mem_t mem;
   4019     int idx_max, offset = 0;
   4020     int rv = BCM_E_NONE;
   4021 
   4022     mem = ALPM_HTBL_MEM(u, i, pid);
   4023     idx_max = ALPM_HTBL_IDX_CNT(u, i, pid) - 1;
   4024 
   4025     rv = soc_mem_write_range(u, mem, MEM_BLOCK_ALL, offset, idx_max + offset,
   4026                              ALPM_HTBL_CACHE(u, i, pid));
   4027 
   4028     return rv;
   4029 }
   4030 
   4031 /* Get hitbit status from a TCAM entry
   4032    (it sync to Hw periodically) */
   4033 int
   4034 th_tcam_ent_hit_get(int u, int pkm, void *e, int sub_idx)
   4035 {
   4036     int         rv = BCM_E_NONE;
   4037     soc_field_t hit_fld[2] = {HIT0f, HIT1f};
   4038     _alpm_cb_t  *acb = ACB_TOP(u);
   4039     soc_mem_t mem = alpm_tbl[acb->pvt_tbl[pkm]];
   4040 
   4041     if (SOC_MEM_FIELD_VALID(u, mem, HITf)) {
   4042         hit_fld[0] = HITf;
   4043         hit_fld[1] = HITf;
   4044     }
   4045 
   4046     rv = soc_mem_field32_get(u, mem, e, hit_fld[sub_idx]);
   4047 
   4048     return rv;
   4049 }
   4050 
   4051 /* Get TCAM cached hitbit status from pvt_node's tcam_idx
   4052    (it sync to Hw periodically) */
   4053 int
   4054 th_tcam_cache_hit_get(int u, int pkm, int tcam_idx)
   4055 {
   4056     int         rv = BCM_E_NONE;
   4057     int         idx, sub_idx;
   4058     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
   4059     soc_field_t hit_fld[2] = {HIT0f, HIT1f};
   4060 
   4061     _alpm_cb_t *acb = ACB_TOP(u);
   4062     soc_mem_t mem = alpm_tbl[acb->pvt_tbl[pkm]];
   4063 
   4064     if (SOC_MEM_FIELD_VALID(u, mem, HITf)) {
   4065         hit_fld[0] = HITf;
   4066         hit_fld[1] = HITf;
   4067     }
   4068 
   4069     if (pkm == ALPM_PKM_32B) {
   4070         /* tcam_idx = idx << 1 | sub_idx */
   4071         sub_idx = tcam_idx & 1;
   4072         idx = tcam_idx >> 1;
   4073     } else {
   4074         sub_idx = 0;
   4075         idx = tcam_idx;
   4076     }
   4077 
   4078     ALPM_IER(th_mem_read(u, acb, acb->pvt_tbl[pkm], idx, e, FALSE));
   4079     rv = soc_mem_field32_get(u, mem, e, hit_fld[sub_idx]);
   4080     return rv;
   4081 }
   4082 
   4083 /* Sync TCAM hitbit cache tables with Hw */
   4084 int
   4085 th_tcam_hit_cache_sync(int u)
   4086 {
   4087     soc_mem_t mem;
   4088     _alpm_cb_t *acb = ACB_TOP(u);
   4089     int pkm, tbl_sz;
   4090     int rv = BCM_E_NONE;
   4091 
   4092     for (pkm = 0; pkm < ALPM_PKM_CNT; pkm++) {
   4093 
   4094         if (ALPM_TCAM_TBL_SKIP(u, pkm)) {
   4095             continue; /* skip duplicated or invalid TCAM table */
   4096         }
   4097 
   4098         mem = alpm_tbl[acb->pvt_tbl[pkm]];
   4099         tbl_sz = th_tcam_table_sz(u, pkm);
   4100         if (tbl_sz) {
   4101             rv = soc_mem_cache_set(u, mem, MEM_BLOCK_ANY, TRUE);
   4102         }
   4103     }
   4104 
   4105     return rv;
   4106 }
   4107 
   4108 void
   4109 th_alpm_hit_deinit(int u)
   4110 {
   4111     int i, pid;
   4112     _alpm_cb_t *acb;
   4113 
   4114     if (ALPM_HIT_SKIP(u)) {
   4115         return;
   4116     }
   4117 
   4118     /* Dist hitbit tables deinit */
   4119     if (ALPMDH(u) != NULL) {
   4120         for (i = 0; i < ACB_CNT(u); i++) {
   4121             acb = ACB(u, i);
   4122             for (pid = 0; pid < ACB_PID_CNT(acb); pid++) {
   4123                 if (ALPM_HTBL(u, i, pid)) {
   4124                     if (ALPM_HTBL_CACHE(u, i, pid)) {
   4125                         soc_cm_sfree(u, ALPM_HTBL_CACHE(u, i, pid));
   4126                         ALPM_HTBL_CACHE(u, i, pid) = NULL;
   4127                     }
   4128                     if (ALPM_HTBL_MOVE(u, i, pid)) {
   4129                         soc_cm_sfree(u, ALPM_HTBL_MOVE(u, i, pid));
   4130                         ALPM_HTBL_MOVE(u, i, pid) = NULL;
   4131                     }
   4132                     if (ALPM_HTBL_MOVE_MASK(u, i, pid)) {
   4133                         soc_cm_sfree(u, ALPM_HTBL_MOVE_MASK(u, i, pid));
   4134                         ALPM_HTBL_MOVE_MASK(u, i, pid) = NULL;
   4135                     }
   4136                     alpm_util_free(ALPM_HTBL(u, i, pid));
   4137                     ALPM_HTBL(u, i, pid) = NULL;
   4138                 }
   4139             }
   4140         }
   4141     }
   4142 
   4143     return;
   4144 }
   4145 
   4146 /* Initialize ALPM distributed hitbit */
   4147 int
   4148 th_alpm_hit_init(int u)
   4149 {
   4150     int rv = BCM_E_NONE;
   4151     int i, pid, index_cnt;
   4152     int alloc_sz;
   4153     soc_mem_t mem;
   4154     _alpm_cb_t *acb;
   4155 
   4156     if (ALPM_HIT_SKIP(u)) {
   4157         return rv;
   4158     }
   4159 
   4160     /* Initialize bucket Levels hitbit table ctrl */
   4161     for (i = 0; i < ACB_CNT(u); i++) {
   4162         acb = ACB(u, i);
   4163         mem = th_alpm_hit_tbl_mem[i];
   4164         /* Current implementation is assuming that HIT table entry
   4165            is not more than 32 bits (actaully we have as maximum 16 HITBITs).
   4166            Otherwise code has to adjust (for multiple words per entry) */
   4167         assert(soc_mem_entry_words(u, mem) == 1);
   4168 
   4169         if (!SOC_WARM_BOOT(u)) {
   4170             th_alpm_hw_mem_clear(u, mem);
   4171         }
   4172 
   4173         for (pid = 0; pid < ACB_PID_CNT(acb); pid++) {
   4174             alloc_sz = sizeof(_alpm_hit_tbl_ctrl_t);
   4175             ALPM_ALLOC_EG(ALPM_HTBL(u, i, pid), alloc_sz, "hit_tbl");
   4176 
   4177             /* logic table index counter (same for HIT table) */
   4178             index_cnt = soc_mem_index_count(u, mem);
   4179             alloc_sz = WORDS2BYTES(soc_mem_entry_words(u, mem)) * index_cnt;
   4180             ALPM_HTBL_MEM(u, i, pid) = mem;
   4181             ALPM_HTBL_IDX_CNT(u, i, pid) = index_cnt;
   4182             ALPM_HTBL_SIZE(u, i, pid) = alloc_sz;
   4183             ALPM_HTBL_ENT_MOVED(u, i, pid) = FALSE;
   4184             ALPM_DMA_ALLOC_EG(u, ALPM_HTBL_CACHE(u, i, pid),
   4185                               alloc_sz, "hit_cache");
   4186             ALPM_DMA_ALLOC_EG(u, ALPM_HTBL_MOVE(u, i, pid),
   4187                               alloc_sz, "hit_move");
   4188             ALPM_DMA_ALLOC_EG(u, ALPM_HTBL_MOVE_MASK(u, i, pid),
   4189                               alloc_sz, "hit_move_mask");
   4190         }
   4191     }
   4192 
   4193     return rv;
   4194 
   4195 bad:
   4196     th_alpm_hit_deinit(u);
   4197     return rv;
   4198 }
   4199 
   4200 /* ALPM hitbit cleanup (UNAVAIL for fast delete_all) */
   4201 int
   4202 th_alpm_hit_cleanup(int u)
   4203 {
   4204     return BCM_E_UNAVAIL;
   4205 }
   4206 
   4207 
   4208 alpm_functions_t th_alpm_driver = {
   4209     th_alpm_ctrl_init,
   4210     th_alpm_ctrl_deinit,
   4211     th_alpm_ctrl_cleanup, /* UNAVAIL */
   4212     th_alpm_bkt_bnk_copy,
   4213     th_alpm_bkt_bnk_clear,
   4214     th_alpm_bkt_pfx_copy,
   4215     th_alpm_bkt_pfx_clean,
   4216     th_alpm_bkt_pfx_shrink,
   4217     th_alpm_bkt_bnk_write,
   4218     th_alpm_bkt_def_fmt_get,
   4219     th_alpm_bkt_fmt_type_get,
   4220 
   4221     th_alpm_ent_ent_get,
   4222     th_alpm_ent_pfx_len_get,
   4223     th_alpm_ent_selective_get,
   4224 
   4225     /* TCAM */
   4226     th_tcam_table_sz,
   4227     th_tcam_hw_cleanup, /* UNAVAIL */
   4228     th_tcam_entry_x_to_y,
   4229     th_tcam_entry_from_cfg,
   4230     /* th_tcam_entry_selective_set, */
   4231     /* th_tcam_entry_selective_get, */
   4232     th_tcam_entry_to_cfg,
   4233     th_tcam_entry_valid,
   4234     th_tcam_entry_valid_set,
   4235     th_tcam_entry_vrf_id_get,
   4236     th_tcam_entry_pfx_len_get,
   4237     th_tcam_entry_to_key,
   4238 
   4239     th_tcam_entry_mode_get,
   4240     th_tcam_entry_adata_get,
   4241     th_tcam_entry_bdata_get,
   4242 
   4243     /* TCAM/ALPM */
   4244     th_mem_read,
   4245     th_mem_write,
   4246 
   4247     /* HITBIT */
   4248     th_alpm_hit_init,
   4249     th_alpm_hit_deinit,
   4250     th_alpm_hit_cleanup, /* UNAVAIL */
   4251     th_alpm_bkt_hit_get,
   4252     th_alpm_bkt_hit_set,
   4253     th_alpm_bkt_hit_write,
   4254     th_alpm_hit_move_update,
   4255     th_alpm_hit_cache_sync,
   4256     th_alpm_hit_hw_write,
   4257     th_tcam_ent_hit_get,
   4258     th_tcam_cache_hit_get,
   4259     th_tcam_hit_cache_sync,
   4260 
   4261     /* dump table */
   4262     th_alpm_table_dump,
   4263     th_alpm_cap_get,
   4264 
   4265     /* index mapping */
   4266     th_mem_phy_index_get,
   4267 };
   4268 
   4269 #endif /* ALPM_ENABLE */
   4270