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


      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/soc_mem_bulk.h>
     22 #include <soc/trident2.h>
     23 #include <soc/tomahawk.h>
     24 #include <soc/tomahawk3.h>
     25 #include <shared/bsl.h>
     26 
     27 #include <shared/util.h>
     28 #include <shared/l3.h>
     29 
     30 #if defined(ALPM_ENABLE)
     31 #include <soc/alpm.h>
     32 
     33 #include <bcm/l3.h>
     34 
     35 #include <bcm_int/esw/l3.h>
     36 #include <bcm_int/esw/firebolt.h>
     37 #include <bcm_int/esw/tomahawk3.h>
     38 #include <bcm_int/esw/alpm.h>
     39 #include <bcm_int/esw/alpm_util.h>
     40 #include <bcm_int/esw/alpm_th3_acc.h>
     41 
     42 
     43 #define TH3_FMT_DECLARE(fmt_name)          \
     44     uint32 fmt_name##_fld = 0;             \
     45     th3_fmt_##fmt_name##_t fmt_name##_fmt;
     46 
     47 #define TH3_FMT_FIELD_CHECK(u, fmt_name, fld_name, fld_width)       \
     48     do {                                                            \
     49         uint32 fld_value;                                           \
     50         assert(fld_width <= 32);                                    \
     51         sal_memset(&fmt_name##_fmt, 0, sizeof(fmt_name##_fmt));     \
     52         fld_value = ((sal_rand() & 0x3) << 30) | (sal_rand() << 15) | sal_rand(); \
     53         fld_value = (fld_width == 32) ? fld_value : (fld_value % (1 << fld_width)); \
     54         fmt_name##_fmt.fld_name = fld_value; \
     55         soc_format_field_get(u, fmt_name##fmt, (uint32 *)&fmt_name##_fmt, fld_name##f, &fmt_name##_fld);    \
     56         if (bsl_check(bslLayerBcm, bslSourceAlpm, bslSeverityVerbose, u)) { \
     57             cli_out("FMT CHECK: %s.%s set 0x%x get 0x%x\n", SOC_FORMAT_NAME(u, fmt_name##fmt), SOC_FIELD_NAME(u, fld_name##f), fld_value, fmt_name##_fld); \
     58         }   \
     59         if (fld_value != fmt_name##_fld) {            \
     60             assert(0);                                              \
     61         }                                                           \
     62     } while (0)
     63 
     64 #define TH3_FMT_FIELD_SPLIT_CHECK(u, fmt_name, fld_name, fld_width, split_fld_name1, split_fld_width1, split_fld_name2, split_fld_width2)       \
     65     do {                                                            \
     66         uint32 fld_value;                                           \
     67         assert(fld_width == (split_fld_width1 + split_fld_width2)); \
     68         assert(fld_width <= 32);                                    \
     69         sal_memset(&fmt_name##_fmt, 0, sizeof(fmt_name##_fmt));     \
     70         fld_value = ((sal_rand() & 0x3) << 30) | (sal_rand() << 15) | sal_rand(); \
     71         fld_value = (fld_width == 32) ? fld_value : (fld_value % (1 << fld_width)); \
     72         fmt_name##_fmt.split_fld_name1 = fld_value & ((1 << split_fld_width1) - 1); \
     73         fmt_name##_fmt.split_fld_name2 = (fld_value >> split_fld_width1) & ((1 << split_fld_width2) - 1); \
     74         soc_format_field_get(u, fmt_name##fmt, (uint32 *)&fmt_name##_fmt, fld_name##f, &fmt_name##_fld);    \
     75         if (bsl_check(bslLayerBcm, bslSourceAlpm, bslSeverityVerbose, u)) { \
     76             cli_out("FMT SPLIT CHECK: %s.%s set 0x%x get 0x%x\n", SOC_FORMAT_NAME(u, fmt_name##fmt), SOC_FIELD_NAME(u, fld_name##f), fld_value, fmt_name##_fld); \
     77         } \
     78         if (fld_value != fmt_name##_fld) {                          \
     79             assert(0);                                              \
     80         }                                                           \
     81     } while (0)
     82 
     83 static void th3_fmt_test(int u)
     84 {
     85     sal_srand(sal_time());
     86 
     87     {
     88         TH3_FMT_DECLARE(ASSOC_DATA_FULL);
     89         TH3_FMT_FIELD_CHECK(u, ASSOC_DATA_FULL, DEST_TYPE, 1);
     90         TH3_FMT_FIELD_CHECK(u, ASSOC_DATA_FULL, DESTINATION, 15);
     91         TH3_FMT_FIELD_CHECK(u, ASSOC_DATA_FULL, PRI, 4);
     92         TH3_FMT_FIELD_CHECK(u, ASSOC_DATA_FULL, RPE, 1);
     93         TH3_FMT_FIELD_CHECK(u, ASSOC_DATA_FULL, DST_DISCARD, 1);
     94         TH3_FMT_FIELD_CHECK(u, ASSOC_DATA_FULL, CLASS_ID, 6);
     95         TH3_FMT_FIELD_CHECK(u, ASSOC_DATA_FULL, FLEX_CTR_POOL_NUMBER, 4);
     96         TH3_FMT_FIELD_CHECK(u, ASSOC_DATA_FULL, FLEX_CTR_OFFSET_MODE, 2);
     97         TH3_FMT_FIELD_CHECK(u, ASSOC_DATA_FULL, FLEX_CTR_BASE_COUNTER_IDX, 12);
     98     }
     99     {
    100         TH3_FMT_DECLARE(ASSOC_DATA_REDUCED);
    101         TH3_FMT_FIELD_CHECK(u, ASSOC_DATA_REDUCED, DEST_TYPE, 1);
    102         TH3_FMT_FIELD_CHECK(u, ASSOC_DATA_REDUCED, DESTINATION, 15);
    103     }
    104     {
    105         TH3_FMT_DECLARE(FIXED_DATA);
    106         TH3_FMT_FIELD_CHECK(u, FIXED_DATA, SUB_DB_PRIORITY, 2);
    107     }
    108     {
    109         TH3_FMT_DECLARE(L3_DEFIP_TCAM_KEY);
    110         TH3_FMT_FIELD_CHECK(u, L3_DEFIP_TCAM_KEY, KEY_MODE, 2);
    111         TH3_FMT_FIELD_CHECK(u, L3_DEFIP_TCAM_KEY, KEY_TYPE, 1);
    112         TH3_FMT_FIELD_SPLIT_CHECK(u, L3_DEFIP_TCAM_KEY, IP_ADDR, 32, IP_ADDR_0_28, 29, IP_ADDR_29_31, 3);
    113         TH3_FMT_FIELD_CHECK(u, L3_DEFIP_TCAM_KEY, VRF_ID, 12);
    114     }
    115     {
    116         TH3_FMT_DECLARE(ALPM1_DATA);
    117         TH3_FMT_FIELD_CHECK(u, ALPM1_DATA, DEFAULT_MISS, 1);
    118         TH3_FMT_FIELD_CHECK(u, ALPM1_DATA, DIRECT_ROUTE, 1);
    119         TH3_FMT_FIELD_CHECK(u, ALPM1_DATA, BKT_PTR, 10);
    120         TH3_FMT_FIELD_CHECK(u, ALPM1_DATA, KSHIFT, 7);
    121         TH3_FMT_FIELD_CHECK(u, ALPM1_DATA, ROFS, 3);
    122         TH3_FMT_FIELD_CHECK(u, ALPM1_DATA, FMT0, 4);
    123         TH3_FMT_FIELD_CHECK(u, ALPM1_DATA, FMT1, 4);
    124         TH3_FMT_FIELD_SPLIT_CHECK(u, ALPM1_DATA, FMT2, 4, FMT2_0_1, 2, FMT2_2_3, 2);
    125         TH3_FMT_FIELD_CHECK(u, ALPM1_DATA, FMT3, 4);
    126         TH3_FMT_FIELD_CHECK(u, ALPM1_DATA, FMT4, 4);
    127     }
    128     {
    129         TH3_FMT_DECLARE(ALPM2_DATA);
    130         TH3_FMT_FIELD_CHECK(u, ALPM2_DATA, DEFAULT_MISS, 1);
    131         TH3_FMT_FIELD_CHECK(u, ALPM2_DATA, BKT_PTR, 13);
    132         TH3_FMT_FIELD_CHECK(u, ALPM2_DATA, KSHIFT, 7);
    133         TH3_FMT_FIELD_CHECK(u, ALPM2_DATA, ROFS, 3);
    134         TH3_FMT_FIELD_CHECK(u, ALPM2_DATA, FMT0, 4);
    135         TH3_FMT_FIELD_CHECK(u, ALPM2_DATA, FMT1, 4);
    136         TH3_FMT_FIELD_CHECK(u, ALPM2_DATA, FMT2, 4);
    137         TH3_FMT_FIELD_CHECK(u, ALPM2_DATA, FMT3, 4);
    138         TH3_FMT_FIELD_CHECK(u, ALPM2_DATA, FMT4, 4);
    139         TH3_FMT_FIELD_CHECK(u, ALPM2_DATA, FMT5, 4);
    140         TH3_FMT_FIELD_CHECK(u, ALPM2_DATA, FMT6, 4);
    141         TH3_FMT_FIELD_CHECK(u, ALPM2_DATA, FMT7, 4);
    142     }
    143 }
    144 
    145 #define TH3_MEM_DECLARE(mem_name)          \
    146     uint32 mem_name##_fld = 0;             \
    147     th3_mem_##mem_name##_t mem_name##_mem;
    148 
    149 #define TH3_MEM_FIELD_CHECK(u, mem_name, fld_name, fld_width)       \
    150     do {                                                            \
    151         uint32 fld_value;                                           \
    152         assert(fld_width <= 32);                                    \
    153         sal_memset(&mem_name##_mem, 0, sizeof(mem_name##_mem));     \
    154         fld_value = ((sal_rand() & 0x3) << 30) | (sal_rand() << 15) | sal_rand(); \
    155         fld_value = (fld_width == 32) ? fld_value : (fld_value % (1 << fld_width)); \
    156         mem_name##_mem.fld_name = fld_value; \
    157         soc_mem_field_get(u, mem_name##m, (uint32 *)&mem_name##_mem, fld_name##f, &mem_name##_fld);    \
    158         if (bsl_check(bslLayerBcm, bslSourceAlpm, bslSeverityVerbose, u)) { \
    159             cli_out("MEM CHECK: %s.%s set 0x%x get 0x%x\n", SOC_MEM_NAME(u, mem_name##m), SOC_FIELD_NAME(u, fld_name##f), fld_value, mem_name##_fld); \
    160         }   \
    161         if (fld_value != mem_name##_fld) {            \
    162             assert(0);                                              \
    163         }                                                           \
    164     } while (0)
    165 
    166 #define TH3_MEM_FIELD_SPLIT_CHECK(u, mem_name, fld_name, fld_width, split_fld_name1, split_fld_width1, split_fld_name2, split_fld_width2)       \
    167     do {                                                            \
    168         uint32 fld_value;                                           \
    169         assert(fld_width == (split_fld_width1 + split_fld_width2)); \
    170         assert(fld_width <= 32);                                    \
    171         sal_memset(&mem_name##_mem, 0, sizeof(mem_name##_mem));     \
    172         fld_value = ((sal_rand() & 0x3) << 30) | (sal_rand() << 15) | sal_rand(); \
    173         fld_value = (fld_width == 32) ? fld_value : (fld_value % (1 << fld_width)); \
    174         mem_name##_mem.split_fld_name1 = fld_value & ((1 << split_fld_width1) - 1); \
    175         mem_name##_mem.split_fld_name2 = (fld_value >> split_fld_width1) & ((1 << split_fld_width2) - 1); \
    176         soc_mem_field_get(u, mem_name##m, (uint32 *)&mem_name##_mem, fld_name##f, &mem_name##_fld);    \
    177         if (bsl_check(bslLayerBcm, bslSourceAlpm, bslSeverityVerbose, u)) { \
    178             cli_out("MEM SPLIT CHECK: %s.%s set 0x%x get 0x%x\n", SOC_MEM_NAME(u, mem_name##m), SOC_FIELD_NAME(u, fld_name##f), fld_value, mem_name##_fld); \
    179         } \
    180         if (fld_value != mem_name##_fld) {                          \
    181             assert(0);                                              \
    182         }                                                           \
    183     } while (0)
    184 
    185 static void th3_mem_test(int u)
    186 {
    187     sal_srand(sal_time());
    188 
    189     {
    190         TH3_MEM_DECLARE(ING_L3_NEXT_HOP);
    191         TH3_MEM_FIELD_CHECK(u, ING_L3_NEXT_HOP, VLAN_ID, 12);
    192         TH3_MEM_FIELD_CHECK(u, ING_L3_NEXT_HOP, PORT_NUM, 8);
    193         TH3_MEM_FIELD_CHECK(u, ING_L3_NEXT_HOP, COPY_TO_CPU, 1);
    194         TH3_MEM_FIELD_CHECK(u, ING_L3_NEXT_HOP, DROP, 1);
    195         TH3_MEM_FIELD_CHECK(u, ING_L3_NEXT_HOP, ENTRY_TYPE, 2);
    196         TH3_MEM_FIELD_CHECK(u, ING_L3_NEXT_HOP, T, 1);
    197     }
    198     {
    199         TH3_MEM_DECLARE(EGR_L3_NEXT_HOP);
    200         TH3_MEM_FIELD_CHECK(u, EGR_L3_NEXT_HOP, ENTRY_TYPE, 2);
    201         TH3_MEM_FIELD_CHECK(u, EGR_L3_NEXT_HOP, L3__CLASS_ID, 7);
    202         TH3_MEM_FIELD_CHECK(u, EGR_L3_NEXT_HOP, IFP_ACTIONS__L3_UC_DA_DISABLE, 1);
    203         TH3_MEM_FIELD_CHECK(u, EGR_L3_NEXT_HOP, IFP_ACTIONS__L3_UC_SA_DISABLE, 1);
    204         TH3_MEM_FIELD_CHECK(u, EGR_L3_NEXT_HOP, IFP_ACTIONS__L3_UC_TTL_DISABLE, 1);
    205         TH3_MEM_FIELD_CHECK(u, EGR_L3_NEXT_HOP, IFP_ACTIONS__L3_UC_VLAN_DISABLE, 1);
    206 
    207         TH3_MEM_FIELD_CHECK(u, EGR_L3_NEXT_HOP, L3__L3_UC_DA_DISABLE, 1);
    208         TH3_MEM_FIELD_CHECK(u, EGR_L3_NEXT_HOP, L3__L3_UC_SA_DISABLE, 1);
    209         TH3_MEM_FIELD_CHECK(u, EGR_L3_NEXT_HOP, L3__L3_UC_TTL_DISABLE, 1);
    210         TH3_MEM_FIELD_CHECK(u, EGR_L3_NEXT_HOP, L3__L3_UC_VLAN_DISABLE, 1);
    211         TH3_MEM_FIELD_CHECK(u, EGR_L3_NEXT_HOP, MPLS__MAC_DA_PROFILE_INDEX, 9);
    212         TH3_MEM_FIELD_SPLIT_CHECK(u, EGR_L3_NEXT_HOP, MPLS__MPLS_LABEL, 20, MPLS__MPLS_LABEL_0_1, 2, MPLS__MPLS_LABEL_2_19, 18);
    213     }
    214     {
    215         TH3_MEM_DECLARE(EGR_L3_NEXT_HOP_2);
    216         TH3_MEM_FIELD_CHECK(u, EGR_L3_NEXT_HOP_2, INTF_NUM, 13);
    217     }
    218 }
    219 
    220 /* Default FMT */
    221 #define ALPM_FMT_DEF_PVT_REDUCED    (1)
    222 #define ALPM_FMT_DEF_PVT_FULL       (6)
    223 #define ALPM_FMT_DEF_RTE_REDUCED    (1)
    224 #define ALPM_FMT_DEF_RTE_FULL      (10)
    225 
    226 static _alpm_fmt_info_t th3_fmt_info[ALPM_FMT_CNT + 1] = {
    227     {
    228         ALPM_FMT_PVT,
    229         8,      /* 8 different formats(PIVOT FORMAT) */
    230         {       /* For fmt_ent_max */
    231             0,  /* FMT=0, means we cannot put entry in this format */
    232             6,  /* allow 6 entires in PIVOT FMT1 */
    233             5,
    234             4,
    235             3,
    236             2,
    237             4,
    238             3,
    239             2,  /* allow 2 entries in PIVOT FMT8 */
    240             0,
    241             0,
    242             0,
    243             0
    244         },
    245         {       /* For fmt_pfx_len */
    246             0,
    247             7,  /* PIVOT FMT1 */
    248             23,
    249             47,
    250             87,
    251             128,
    252             17,
    253             57,
    254             128,/* PIVOT FMT8 */
    255             0,
    256             0,
    257             0,
    258             0
    259         },
    260         {       /* fmt_bnk */
    261             INVALIDfmt,
    262             L3_DEFIP_ALPM_PIVOT_FMT1_FULLfmt,
    263             L3_DEFIP_ALPM_PIVOT_FMT2_FULLfmt,
    264             L3_DEFIP_ALPM_PIVOT_FMT3_FULLfmt,
    265             L3_DEFIP_ALPM_PIVOT_FMT4_FULLfmt,
    266             L3_DEFIP_ALPM_PIVOT_FMT5_FULLfmt,
    267             L3_DEFIP_ALPM_PIVOT_FMT6_FULLfmt,
    268             L3_DEFIP_ALPM_PIVOT_FMT7_FULLfmt,
    269             L3_DEFIP_ALPM_PIVOT_FMT8_FULLfmt,
    270             INVALIDfmt,
    271             INVALIDfmt,
    272             INVALIDfmt,
    273             INVALIDfmt
    274         },
    275         {       /* fmt_ent */
    276             INVALIDfmt,
    277             L3_DEFIP_ALPM_PIVOT_FMT1fmt,
    278             L3_DEFIP_ALPM_PIVOT_FMT2fmt,
    279             L3_DEFIP_ALPM_PIVOT_FMT3fmt,
    280             L3_DEFIP_ALPM_PIVOT_FMT4fmt,
    281             L3_DEFIP_ALPM_PIVOT_FMT5fmt,
    282             L3_DEFIP_ALPM_PIVOT_FMT6fmt,
    283             L3_DEFIP_ALPM_PIVOT_FMT7fmt,
    284             L3_DEFIP_ALPM_PIVOT_FMT8fmt,
    285             INVALIDfmt,
    286             INVALIDfmt,
    287             INVALIDfmt,
    288             INVALIDfmt
    289         },
    290         {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0},
    291     },  /* PIVOT fmt info */
    292     {
    293         ALPM_FMT_RTE,
    294         12,     /* 12 different formats(ROUTE FORMAT) */
    295         {       /* For fmt_ent_max */
    296             0,  /* FMT=0, means we cannot put entry in this format */
    297             15, /* allow 15 entires in ROUTE FMT1 */
    298             12,
    299             10,
    300             8,
    301             7,
    302             6,
    303             5,
    304             4,
    305             3,
    306             6,
    307             4,
    308             2   /* allow 2 entries in ROUTE FMT12 */
    309         },
    310         {       /* For fmt_pfx_len */
    311             0,
    312             15, /* ROUTE FMT1 */
    313             23,
    314             31,
    315             39,
    316             47,
    317             63,
    318             79,
    319             103,
    320             128,
    321             33,
    322             73,
    323             128  /* ROUTE FMT12 */
    324         },
    325         {       /* fmt_bnk */
    326             INVALIDfmt,
    327             L3_DEFIP_ALPM_ROUTE_FMT1_FULLfmt,
    328             L3_DEFIP_ALPM_ROUTE_FMT2_FULLfmt,
    329             L3_DEFIP_ALPM_ROUTE_FMT3_FULLfmt,
    330             L3_DEFIP_ALPM_ROUTE_FMT4_FULLfmt,
    331             L3_DEFIP_ALPM_ROUTE_FMT5_FULLfmt,
    332             L3_DEFIP_ALPM_ROUTE_FMT6_FULLfmt,
    333             L3_DEFIP_ALPM_ROUTE_FMT7_FULLfmt,
    334             L3_DEFIP_ALPM_ROUTE_FMT8_FULLfmt,
    335             L3_DEFIP_ALPM_ROUTE_FMT9_FULLfmt,
    336             L3_DEFIP_ALPM_ROUTE_FMT10_FULLfmt,
    337             L3_DEFIP_ALPM_ROUTE_FMT11_FULLfmt,
    338             L3_DEFIP_ALPM_ROUTE_FMT12_FULLfmt
    339         },
    340         {       /* fmt_ent */
    341             INVALIDfmt,
    342             L3_DEFIP_ALPM_ROUTE_FMT1fmt,
    343             L3_DEFIP_ALPM_ROUTE_FMT2fmt,
    344             L3_DEFIP_ALPM_ROUTE_FMT3fmt,
    345             L3_DEFIP_ALPM_ROUTE_FMT4fmt,
    346             L3_DEFIP_ALPM_ROUTE_FMT5fmt,
    347             L3_DEFIP_ALPM_ROUTE_FMT6fmt,
    348             L3_DEFIP_ALPM_ROUTE_FMT7fmt,
    349             L3_DEFIP_ALPM_ROUTE_FMT8fmt,
    350             L3_DEFIP_ALPM_ROUTE_FMT9fmt,
    351             L3_DEFIP_ALPM_ROUTE_FMT10fmt,
    352             L3_DEFIP_ALPM_ROUTE_FMT11fmt,
    353             L3_DEFIP_ALPM_ROUTE_FMT12fmt
    354         },
    355         {0,
    356          0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1},
    357     },  /* ROUTE fmt info */
    358     {
    359         ALPM_FMT_CNT,
    360         0,      /* 0 different formats */
    361         {       /* For fmt_ent_max */
    362             0,  /* FMT=0, means we cannot put entry in this format */
    363             0,
    364             0,
    365             0,
    366             0,
    367             0,
    368             0,
    369             0,
    370             0,
    371             0,
    372             0,
    373             0,
    374             0
    375         },
    376         {       /* For fmt_pfx_len */
    377             0,
    378             0,
    379             0,
    380             0,
    381             0,
    382             0,
    383             0,
    384             0,
    385             0,
    386             0,
    387             0,
    388             0,
    389             0
    390         },
    391         {       /* fmt_bnk */
    392             INVALIDfmt,
    393             INVALIDfmt,
    394             INVALIDfmt,
    395             INVALIDfmt,
    396             INVALIDfmt,
    397             INVALIDfmt,
    398             INVALIDfmt,
    399             INVALIDfmt,
    400             INVALIDfmt,
    401             INVALIDfmt,
    402             INVALIDfmt,
    403             INVALIDfmt,
    404             INVALIDfmt
    405         },
    406         {       /* fmt_ent */
    407             INVALIDfmt,
    408             INVALIDfmt,
    409             INVALIDfmt,
    410             INVALIDfmt,
    411             INVALIDfmt,
    412             INVALIDfmt,
    413             INVALIDfmt,
    414             INVALIDfmt,
    415             INVALIDfmt,
    416             INVALIDfmt,
    417             INVALIDfmt,
    418             INVALIDfmt,
    419             INVALIDfmt
    420         },
    421         {0,
    422          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    423     },
    424 };
    425 
    426 soc_field_t th3_alpm_ent_fld[] = {
    427     ENTRY_0f, ENTRY_1f, ENTRY_2f, ENTRY_3f,
    428     ENTRY_4f, ENTRY_5f, ENTRY_6f, ENTRY_7f,
    429     ENTRY_8f, ENTRY_9f, ENTRY_10f,ENTRY_11f,
    430     ENTRY_12f,ENTRY_13f,ENTRY_14f,ENTRY_15f,
    431 };
    432 
    433 soc_field_t th3_alpm_bnk_fld[] = {
    434     FMT0f, FMT1f, FMT2f, FMT3f,
    435     FMT4f, FMT5f, FMT6f, FMT7f
    436 };
    437 
    438 static soc_mem_t th3_alpm_hit_tbl_mem[] = {
    439     L3_DEFIP_ALPM_LEVEL2_HIT_ONLYm,
    440     L3_DEFIP_ALPM_LEVEL3_HIT_ONLYm
    441 };
    442 
    443 /* Should be the same order as _alpm_tbl_t */
    444 static soc_mem_t th3_alpm_tbl[] = {
    445     INVALIDm,
    446     L3_DEFIP_LEVEL1m,
    447     L3_DEFIP_LEVEL1m,
    448     L3_DEFIP_PAIR_LEVEL1m,
    449     L3_DEFIP_PAIR_LEVEL1m,
    450     L3_DEFIP_ALPM_LEVEL2m,
    451     L3_DEFIP_ALPM_LEVEL2m,
    452     L3_DEFIP_ALPM_LEVEL2m,
    453     L3_DEFIP_ALPM_LEVEL2m,
    454     L3_DEFIP_ALPM_LEVEL3m,
    455     L3_DEFIP_ALPM_LEVEL3m,
    456     L3_DEFIP_ALPM_LEVEL3m,
    457     INVALIDm
    458 };
    459 
    460 static soc_mem_t *alpm_tbl;
    461 
    462 /* Combined mode Level2 Table */
    463 static _alpm_bkt_pool_conf_t th3_alpm_cmode_pool_l2 = {
    464     {NULL, NULL},  /* bnk_info, to be allocated */
    465     5120,   /* 5 Banks x 1K buckets */
    466     5,      /* 5 Banks per bucket */
    467     alpmTblBktCmodeL2,
    468     1,      /* Wrap around bucket */
    469     0,      /* Not Fixed FMT */
    470     NULL,
    471     &th3_fmt_info[ALPM_FMT_PVT],
    472 };
    473 
    474 /* Combined mode Level3 Table */
    475 static _alpm_bkt_pool_conf_t th3_alpm_cmode_pool_l3 = {
    476     {NULL, NULL},  /* bnk_info, to be allocated */
    477     65536,  /* 8 Banks x 8K buckets */
    478     8,      /* 8 Banks per bucket */
    479     alpmTblBktCmodeL3,
    480     1,
    481     0,      /* Not Fixed FMT */
    482     NULL,
    483     &th3_fmt_info[ALPM_FMT_RTE],
    484 };
    485 
    486 /* Parallel mode Level2 Table pool for Global Routes */
    487 static _alpm_bkt_pool_conf_t th3_alpm_pmode_pool_gbl_l2 = {
    488     {NULL, NULL},  /* bnk_info, to be allocated */
    489     2048,   /* 2 Banks x 1K buckets */
    490     2,      /* 2 Banks per bucket */
    491     alpmTblBktPmodeGblL2,
    492     1,
    493     0,      /* Not Fixed FMT */
    494     NULL,
    495     &th3_fmt_info[ALPM_FMT_PVT],
    496 };
    497 
    498 /* Parallel mode Level2 Table pool for Private Routes */
    499 static _alpm_bkt_pool_conf_t th3_alpm_pmode_pool_prt_l2 = {
    500     {NULL, NULL},  /* bnk_info, to be allocated */
    501     3072,   /* 3 Banks x 1K buckets */
    502     3,      /* 3 Banks per bucket */
    503     alpmTblBktPmodePrtL2,
    504     1,
    505     0,      /* Not Fixed FMT */
    506     NULL,
    507     &th3_fmt_info[ALPM_FMT_PVT],
    508 };
    509 
    510 /* Parallel mode Level3 Table pool for Global Routes */
    511 static _alpm_bkt_pool_conf_t th3_alpm_pmode_pool_gbl_l3 = {
    512     {NULL, NULL},  /* bnk_info, to be allocated */
    513     32768,  /* 4 Banks x 8K buckets */
    514     4,      /* 4 Banks per bucket */
    515     alpmTblBktPmodeGblL3,
    516     1,
    517     0,      /* Not Fixed FMT */
    518     NULL,
    519     &th3_fmt_info[ALPM_FMT_RTE],
    520 };
    521 
    522 /* Parallel mode Level3 Table pool for Private Routes */
    523 static _alpm_bkt_pool_conf_t th3_alpm_pmode_pool_prt_l3 = {
    524     {NULL, NULL},  /* bnk_info, to be allocated */
    525     32768,  /* 4 Banks x 8K buckets */
    526     4,      /* 4 Banks per bucket */
    527     alpmTblBktPmodePrtL3,
    528     1,
    529     0,      /* Not Fixed FMT */
    530     NULL,
    531     &th3_fmt_info[ALPM_FMT_RTE],
    532 };
    533 
    534 static _alpm_bkt_pool_conf_t *th3_alpm_pool0_l2[SOC_MAX_NUM_DEVICES] = {NULL};
    535 static _alpm_bkt_pool_conf_t *th3_alpm_pool1_l2[SOC_MAX_NUM_DEVICES] = {NULL};
    536 static _alpm_bkt_pool_conf_t *th3_alpm_pool0_l3[SOC_MAX_NUM_DEVICES] = {NULL};
    537 static _alpm_bkt_pool_conf_t *th3_alpm_pool1_l3[SOC_MAX_NUM_DEVICES] = {NULL};
    538 
    539 static _alpm_cb_t th3_alpm_1cb_template = {
    540     0,          /* Unit */
    541     {
    542         NULL,               /* pvt_ctl[V4] */
    543         NULL,               /* pvt_ctl[V6] */
    544     },
    545     {                   /* Pivot Tables of this block */
    546         alpmTblPvtCmodeL1,
    547         alpmTblPvtCmodeL1,
    548         alpmTblInvalid
    549     },
    550     {   /* _alpm_bnk_conf_t */
    551         {NULL, NULL}, /* bnk_pool pointer */
    552         10,     /* 1K buckets = 10 bits */
    553         0,      /* Single Wide */
    554         5,      /* 5 physical banks per bucket */
    555         3,      /* 3 bits */
    556     },
    557     0                   /* Block 0 */
    558 };
    559 
    560 static _alpm_cb_t th3_alpm_1cb_template_128b = {
    561     0,          /* Unit */
    562     {
    563         NULL,               /* pvt_ctl[V4] */
    564         NULL,               /* pvt_ctl[V6] */
    565     },
    566     {                   /* Pivot Tables of this block */
    567         alpmTblPvtCmodeL1,
    568         alpmTblPvtCmodeL1P128,
    569         alpmTblPvtCmodeL1P128
    570     },
    571     {   /* _alpm_bnk_conf_t */
    572         {NULL, NULL}, /* bnk_pool pointer */
    573         10,     /* 1K buckets = 10 bits */
    574         0,      /* Single Wide */
    575         5,      /* 5 physical banks per bucket */
    576         3,      /* 3 bits */
    577     },
    578     0                   /* Block 0 */
    579 };
    580 
    581 static _alpm_cb_t th3_alpm_2cb_template_p0 = {
    582     0,          /* Unit */
    583     {
    584         NULL,               /* pvt_ctl[V4] */
    585         NULL,               /* pvt_ctl[V6] */
    586     },
    587     {                   /* Pivot Tables of this block */
    588         alpmTblPvtCmodeL1,
    589         alpmTblPvtCmodeL1,
    590         alpmTblInvalid
    591     },
    592     {   /* _alpm_bnk_conf_t */
    593         {NULL, NULL}, /* bnk_pool pointer */
    594         10,     /* 1K buckets = 10 bits */
    595         0,      /* Single Wide */
    596         5,      /* 5 physical banks per bucket */
    597         3,      /* 3 bits */
    598     },
    599     0                   /* ALPM block 0 */
    600 };
    601 
    602 static _alpm_cb_t th3_alpm_2cb_template_p0_128b = {
    603     0,          /* Unit */
    604     {
    605         NULL,               /* pvt_ctl[V4] */
    606         NULL,               /* pvt_ctl[V6] */
    607     },
    608     {                   /* Pivot Tables of this block */
    609         alpmTblPvtCmodeL1,
    610         alpmTblPvtCmodeL1P128,
    611         alpmTblPvtCmodeL1P128
    612     },
    613     {   /* _alpm_bnk_conf_t */
    614         {NULL, NULL}, /* bnk_pool pointer */
    615         10,     /* 1K buckets = 10 bits */
    616         0,      /* Single Wide */
    617         5,      /* 5 physical banks per bucket */
    618         3,      /* 3 bits */
    619     },
    620     0                   /* Block 0 */
    621 };
    622 
    623 static _alpm_cb_t th3_alpm_2cb_template_p1 = {
    624     0,          /* Unit */
    625     {
    626         NULL,               /* pvt_ctl[V4] */
    627         NULL,               /* pvt_ctl[V6] */
    628     },
    629     {                   /* Pivot Tables of this block */
    630         alpmTblInvalid,
    631         alpmTblInvalid,
    632         alpmTblInvalid
    633     },
    634     {   /* _alpm_bnk_conf_t */
    635         {NULL, NULL}, /* bnk_pool pointer */
    636         13,     /* 8K buckets = 13 bits */
    637         0,      /* Single Wide */
    638         8,      /* 8 physical banks per bucket */
    639         3,      /* 3 bits */
    640     },
    641     1                   /* Block 1 */
    642 };
    643 
    644 /* local used functions */
    645 int th3_alpm_bkt_hit_write(int u, int vrf_id, _alpm_cb_t *acb,
    646                            _alpm_tbl_t tbl, int ent_idx, int hit_val);
    647 int th3_alpm_ent_hit_move(int u, int vrf_id, _alpm_cb_t *acb,
    648                           int src_ent_idx, int dst_ent_idx);
    649 int th3_alpm_bnk_hit_move(int u, int vrf_id, _alpm_cb_t *acb,
    650                           int src_idx, int dst_idx);
    651 int th3_alpm_bnk_hit_clear(int u, int vrf_id, _alpm_cb_t *acb, int idx);
    652 int8 th3_alpm_bnk_fmt_get(int u, _alpm_cb_t *acb, _alpm_bkt_info_t *bkt_info,
    653                           int ent_idx);
    654 int th3_alpm_table_dump_3level(int u, soc_mem_t mem, int idx, int sub_idx,
    655                                int lvl_cnt, int flags);
    656 
    657 /* TH3 ALPM mis-fowarding check for memory write */
    658 int
    659 th3_mem_write_check(int u, soc_mem_t mem, int phy_index, void *entry)
    660 {
    661     static int tot_err = 0; /* 0 for invalid hw route check */
    662     int rv = BCM_E_NONE;
    663 
    664     if (ALPMTR_SANITY_EN(u) && ALPMTR_CNT(u) == ALPMTR_SANITY_START(u)) {
    665         if (mem == L3_DEFIP_ALPM_LEVEL2m || (mem == L3_DEFIP_ALPM_LEVEL3m)) {
    666             cli_out("w %s %d 1 ", SOC_MEM_NAME(u, mem), phy_index);
    667             soc_mem_entry_dump(u, mem, entry, BSL_LSS_CLI);
    668         } else {
    669             cli_out("mod %s %d 1 ", SOC_MEM_NAME(u, mem), phy_index);
    670             soc_mem_entry_dump_if_changed(u, mem, entry, "");
    671             th3_alpm_table_dump_3level(u, mem, phy_index, 0, 3, 0);
    672         }
    673         if (!tot_err && mem != L3_DEFIP_ALPM_LEVEL3m) {
    674             (void)alpm_pfx_hw_route_sanity(u, &tot_err);
    675         }
    676     }
    677     return rv;
    678 }
    679 
    680 static int
    681 th3_mem_phy_index_get(int u, _alpm_cb_t *acb, _alpm_tbl_t tbl, int index)
    682 {
    683     int phy_index;
    684     /* Remapping index for actual memory in Parallel/Mixed mode */
    685     switch (tbl) {
    686         case alpmTblBktPmodeGblL2:
    687         case alpmTblBktPmodeGblL3:
    688             phy_index = index + ACB_BNK_PER_BKT(acb, 1) * ACB_BKT_CNT(acb);
    689             break;
    690         default:
    691             phy_index = index;
    692             break;
    693     }
    694 
    695     if (ACB_HLF_BNK_MD(acb)) {
    696         phy_index += (1 << ACB_BNK_BITS(acb)) * ACB_BKT_CNT(acb);
    697     }
    698 
    699     return phy_index;
    700 }
    701 
    702 int
    703 th3_mem_read(int u, _alpm_cb_t *acb, _alpm_tbl_t tbl,
    704              int index, void *entry_data, int no_cache)
    705 {
    706     int rv = BCM_E_NONE;
    707     soc_mem_t mem;
    708 
    709     mem = alpm_tbl[tbl];
    710     index = th3_mem_phy_index_get(u, acb, tbl, index);
    711     if (no_cache && !(ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_WRITE_CACHE_ONLY)) {
    712         rv = soc_mem_read_no_cache(u, 0, mem, 0, MEM_BLOCK_ANY,
    713                                    index, entry_data);
    714     } else {
    715         rv = soc_mem_read(u, mem, MEM_BLOCK_ANY, index, entry_data);
    716     }
    717     if (BCM_SUCCESS(rv)) {
    718         acb->acb_cnt.c_mem[tbl][0]++;
    719     }
    720 
    721     return rv;
    722 }
    723 
    724 int
    725 th3_mem_write(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node,
    726               _alpm_tbl_t tbl, int index, void *entry_data)
    727 {
    728     int rv = BCM_E_NONE;
    729     int phy_index;
    730     soc_mem_t mem;
    731     void *entry = entry_data;
    732 
    733     mem = alpm_tbl[tbl];
    734     if (entry == NULL) {
    735         entry = soc_mem_entry_null(u, mem);
    736     }
    737 
    738     phy_index = th3_mem_phy_index_get(u, acb, tbl, index);
    739     if (ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_WRITE_CACHE_ONLY) {
    740         _soc_mem_alpm_write_cache(u, mem, MEM_BLOCK_ALL, phy_index, entry);
    741     } else {
    742         rv = soc_mem_write(u, mem, MEM_BLOCK_ALL, phy_index, entry);
    743 
    744         /* Mis-forwarding check
    745            (void)th3_mem_write_check(u, mem, phy_index, entry); */
    746     }
    747 
    748     if (BCM_SUCCESS(rv)) {
    749         acb->acb_cnt.c_mem[tbl][1]++;
    750         if (pvt_node != NULL) {
    751             if (entry_data != NULL) {
    752                 ACB_PVT_PTR(acb, pvt_node, index) = pvt_node;
    753             } else {
    754                 ACB_PVT_PTR(acb, pvt_node, index) = NULL;
    755             }
    756         }
    757      }
    758 
    759     return rv;
    760 }
    761 
    762 int
    763 th3_mem_bulk_write(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node,
    764                    _alpm_tbl_t tbl, int *index, uint32 **entry_data, int count)
    765 {
    766     int i;
    767     int phy_index[20];  /* 20 = Local max count */
    768     int copyno[20];
    769     soc_mem_t mem;
    770     soc_mem_t bulk_mem[20];
    771     int rv = BCM_E_NONE;
    772 
    773     assert(count <= 20);
    774 
    775     mem = alpm_tbl[tbl];
    776     for (i = 0; i < count; i++) {
    777         phy_index[i] = th3_mem_phy_index_get(u, acb, tbl, index[i]);
    778         copyno[i] = MEM_BLOCK_ALL;
    779         bulk_mem[i] = mem;
    780     }
    781 
    782     if (ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_WRITE_CACHE_ONLY) {
    783         for (i = 0; i < count; i++) {
    784             _soc_mem_alpm_write_cache(u, mem, MEM_BLOCK_ALL, phy_index[i],
    785                                       entry_data[i]);
    786         }
    787     } else {
    788         if (count <= ALPMC(u)->_alpm_bulk_wr_threshold ||
    789             SAL_BOOT_PLISIM || SAL_BOOT_BCMSIM) {
    790             for (i = 0; i < count; i++) {
    791                 rv = soc_mem_write(u, mem, MEM_BLOCK_ALL, phy_index[i],
    792                                    entry_data[i]);
    793 
    794                 /* Mis-forwarding check
    795                    (void)th3_mem_write_check(u, mem, phy_index[i], entry_data[i]); */
    796 
    797                 ALPM_IER(rv);
    798             }
    799         } else {
    800             rv = soc_mem_bulk_write(u, bulk_mem, phy_index, copyno,
    801                                     entry_data, count);
    802         }
    803     }
    804 
    805     if (BCM_SUCCESS(rv)) {
    806         for (i = 0; i < count; i++) {
    807             acb->acb_cnt.c_mem[tbl][1]++;
    808             if (pvt_node != NULL) {
    809                 ACB_PVT_PTR(acb, pvt_node, index[i]) = pvt_node;
    810             }
    811         }
    812     }
    813 
    814     return rv;
    815 }
    816 
    817 /* ALPM related functions */
    818 
    819 static int
    820 th3_alpm_cb_cnt(int u)
    821 {
    822     int acb_cnt, alpm_enable, alpm_level;
    823     alpm_enable = soc_property_get(u, spn_L3_ALPM_ENABLE, 2);
    824     alpm_level  = soc_property_get(u, "l3_alpm2_level", 3);
    825 
    826     if (alpm_enable) {
    827         acb_cnt = alpm_level - 1;      /* 1 or 2 ALPM Control Blocks */
    828         if (acb_cnt < 1) {
    829             acb_cnt = ALPM_CB_CNT;
    830         }
    831     } else {
    832         acb_cnt = 0;                   /* 0 ALPM Control Block */
    833     }
    834 
    835     if (acb_cnt > ALPM_CB_CNT) {
    836         acb_cnt = ALPM_CB_CNT;
    837     }
    838 
    839     return acb_cnt;
    840 }
    841 
    842 void
    843 th3_alpm_ctrl_deinit(int u)
    844 {
    845     int i, j, pid, ipt, acb_cnt;
    846     _alpm_cb_t *acb;
    847 
    848     acb_cnt = th3_alpm_cb_cnt(u);
    849     for (i = 0; i < acb_cnt; i++) {
    850         acb = ACB(u, i);
    851         if (acb != NULL) {
    852             /* Free Bucket pool */
    853             for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) {
    854                 _alpm_bkt_pool_conf_t *bp_conf;
    855 
    856                 bp_conf = ACB_BKT_POOL(acb, pid);
    857                 if (bp_conf->pvt_ptr != NULL) {
    858                     alpm_util_free(bp_conf->pvt_ptr);
    859                     bp_conf->pvt_ptr = NULL;
    860                 }
    861 
    862                 for (ipt = ALPM_IPT_V4; ipt < ALPM_IPT_CNT; ipt++) {
    863                     if (ipt > ALPM_IPT_V4 &&
    864                         BPC_BNK_INFO(bp_conf, ipt) ==
    865                         BPC_BNK_INFO(bp_conf, ipt - 1)) {
    866                         continue;
    867                     }
    868                     if (BPC_BNK_INFO(bp_conf, ipt) != NULL) {
    869                         alpm_util_free(BPC_BNK_INFO(bp_conf, ipt));
    870                     }
    871                 }
    872                 for (ipt = ALPM_IPT_V4; ipt < ALPM_IPT_CNT; ipt++) {
    873                     BPC_BNK_INFO(bp_conf, ipt) = NULL;
    874                 }
    875             }
    876 
    877             for (j = 0; j < ALPM_IPT_CNT; j++) {
    878                 if (acb->pvt_ctl[j] != NULL) {
    879                     alpm_util_free(acb->pvt_ctl[j]);
    880                     acb->pvt_ctl[j] = NULL;
    881                 }
    882             }
    883 
    884             alpm_util_free(acb);
    885             ACB(u, i) = NULL;
    886         }
    887     }
    888 
    889     alpm_util_free(th3_alpm_pool0_l2[u]);
    890     th3_alpm_pool0_l2[u] = NULL;
    891     alpm_util_free(th3_alpm_pool1_l2[u]);
    892     th3_alpm_pool1_l2[u] = NULL;
    893     alpm_util_free(th3_alpm_pool0_l3[u]);
    894     th3_alpm_pool0_l3[u] = NULL;
    895     alpm_util_free(th3_alpm_pool1_l3[u]);
    896     th3_alpm_pool1_l3[u] = NULL;
    897 
    898     return ;
    899 }
    900 
    901 /* Adjust config based on dynamic configuration */
    902 /*
    903  *     Matrix of fmt_info usage:
    904  * ---------------------------------------------------------------
    905  * | Lvl_cnt | Banks | ALPM_mode | DB_type | Cur_lvl | fmt_type |
    906  * ---------------------------------------------------------------
    907  * | 2       | 5     | Combined  | DB0(P,G)| 2       | RTE      |
    908  * | 2       | 5     | Parallel  | DB0(P)  | 2       | RTE      |
    909  * | 2       | 5     | Parallel  | DB1(G)  | 2       | RTE      |
    910  * | 2       | 5     | Mixed     | DB0(G)  | 2       | RTE      |
    911  * | 2       | 5     | Mixed     | DB1(G)  | N/A     | N/A      |
    912  * ---------------------------------------------------------------
    913  * | 3       | 4/8   | Combined  | DB0(P,G)| 2       | PVT      |
    914  * | 3       | 4/8   | Combined  | DB0(P,G)| 3       | RTE      |
    915  * | 3       | 4     | Parallel  | DB0(P)  | 2       | PVT      |
    916  * | 3       | 4     | Parallel  | DB0(P)  | 3       | RTE      |
    917  * | 3       | 4     | Parallel  | DB1(G)  | 2       | RTE*     |
    918  * | 3       | 8     | Parallel  | DB0(P)  | 2       | PVT      |
    919  * | 3       | 8     | Parallel  | DB0(P)  | 3       | RTE      |
    920  * | 3       | 8     | Parallel  | DB1(G)  | 2       | PVT      |
    921  * | 3       | 8     | Parallel  | DB1(G)  | 3       | RTE      |
    922  * | 3       | 4/8   | Mixed     | DB0(P)  | 2       | PVT      |
    923  * | 3       | 4/8   | Mixed     | DB0(P)  | 3       | RTE      |
    924  * | 3       | 4/8   | Mixed     | DB1(G)  | N/A     | N/A      |
    925  * ---------------------------------------------------------------
    926  *
    927  * if (Cur_lvl == Lvl_cnt) {
    928  *     fmt_type = RTE;
    929  * } else {
    930  *     if (levels(DB) == (Lvl_cnt - 1)) {
    931  *         e.g.: (Banks==4 && Parallel && DB1)
    932  *         fmt_type = RTE;
    933  *     } else {
    934  *         fmt_type = PVT;
    935  *     }
    936  * }
    937  */
    938 static int
    939 th3_alpm_cfg_adjust(int u, int acb_cnt, _alpm_cb_t *acb)
    940 {
    941     int i, half_banks = 0;
    942     int vrf_id = ALPM_VRF_ID_GLO(u);
    943 
    944     if (soc_th3_get_alpm_banks(u) == 4) {
    945         half_banks = 1;
    946         ALPMC(u)->_alpm_half_banks = 1;
    947     }
    948 
    949     if (acb_cnt > 1 && acb->acb_idx > 0) {
    950         /* Half banks mode */
    951         if (half_banks) {
    952             int pid;
    953             /* Adjust _alpm_cb_t */
    954             ACB_PHY_BNK_PER_BKT(acb) >>= 1;
    955             ACB_BNK_BITS(acb) -= 1;
    956 
    957             /* Adjust _alpm_bkt_pool_conf_t */
    958             /* For Parallel mode, Global Low routes go to Level 2 only */
    959             if (ALPM_MODE_CHK(u, BCM_ALPM_MODE_PARALLEL)) {
    960                 _alpm_bkt_pool_conf_t *bp_conf;
    961                 bp_conf = ACB_BKT_VRF_POOL(acb, ALPM_VRF_ID_GLO(u));
    962                 BPC_BNK_CNT(bp_conf) = 0;
    963                 BPC_BNK_PER_BKT(bp_conf) = 1;
    964             } else {
    965                 for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) {
    966                     _alpm_bkt_pool_conf_t *bp_conf;
    967                     bp_conf = ACB_BKT_POOL(acb, pid);
    968 
    969                     if (pid > 0 && bp_conf == ACB_BKT_POOL(acb, pid-1)) {
    970                         continue;
    971                     }
    972                     BPC_BNK_CNT(bp_conf) >>= 1;
    973                     BPC_BNK_PER_BKT(bp_conf) >>= 1;
    974                 }
    975             }
    976         }
    977     }
    978 
    979     /* Adjust fmt_info */
    980     if (ACB_IDX(acb) == acb_cnt - 1) {
    981         for (i = 0; i < ALPM_BKT_PID_CNT; i++) {
    982             ACB_BKT_POOL(acb, i)->fmt_info = &th3_fmt_info[ALPM_FMT_RTE];
    983             if (acb_cnt < 2) {
    984                 ALPMC(u)->_alpm_btm_cb_idx[i] = acb_cnt - 1;
    985             }
    986         }
    987         if (ALPM_GLO_VRF_IN_HLF_PMODE(u, vrf_id)) {
    988             ACB_VRF_POOL_FMT_INFO(acb, vrf_id) =
    989                 &th3_fmt_info[ALPM_FMT_CNT];
    990         }
    991     } else {
    992         /* When reach here: more than 2 acbs, non-last acb */
    993         for (i = 0; i < ALPM_BKT_PID_CNT; i++) {
    994             ACB_POOL_FMT_INFO(acb, i) = &th3_fmt_info[ALPM_FMT_PVT];
    995             ALPMC(u)->_alpm_btm_cb_idx[i] = acb_cnt - 1;
    996         }
    997         if (ALPM_GLO_VRF_IN_HLF_PMODE(u, vrf_id)) {
    998             ACB_VRF_POOL_FMT_INFO(acb, vrf_id) =
    999                 &th3_fmt_info[ALPM_FMT_RTE];
   1000             ALPMC(u)->_alpm_btm_cb_idx[ALPM_VRF_ID_TO_BPC_PID(u, vrf_id)] =
   1001                 acb_cnt - 2;
   1002         }
   1003     }
   1004 
   1005     return BCM_E_NONE;
   1006 }
   1007 
   1008 static void
   1009 th3_alpm_hw_mem_clear(int u, soc_mem_t mem)
   1010 {
   1011     uint8 *mbuf;
   1012     int size, offset = 0;
   1013 
   1014     ALPM_INFO(("ALPM clearing mem %s\n", SOC_MEM_NAME(u, mem)));
   1015 
   1016     size = SOC_MEM_TABLE_BYTES(u, mem);
   1017     /* skip first 4 shared UFT banks for EM */
   1018     if ((soc_th3_get_alpm_banks(u) == 4) &&
   1019         (mem == L3_DEFIP_ALPM_LEVEL3m ||
   1020          mem == L3_DEFIP_ALPM_LEVEL3_HIT_ONLYm)) {
   1021         offset = (soc_mem_index_count(u, mem) >> 1);
   1022         size >>= 1;
   1023     }
   1024     mbuf = soc_cm_salloc(u, size, "alpm_mem");
   1025     if (mbuf != NULL) {
   1026         sal_memset(mbuf, 0, size);
   1027         (void)soc_mem_write_range(u, mem, MEM_BLOCK_ANY,
   1028                                   soc_mem_index_min(u, mem) + offset,
   1029                                   soc_mem_index_max(u, mem), mbuf);
   1030         soc_cm_sfree(u, mbuf);
   1031     } else {
   1032         ALPM_ERR(("alpm_hw_mem_clear alloc DMA memory failed\n"));
   1033     }
   1034 
   1035     return ;
   1036 }
   1037 
   1038 static int
   1039 th3_alpm_hw_init(int u)
   1040 {
   1041 
   1042 #define LVLS            3
   1043 #define MODES           3
   1044 #define PAIRS           5
   1045 #define CNTOF(arr) (sizeof(arr)/sizeof(arr[0]))
   1046 
   1047     int i, mde, lvl, prs, rv = BCM_E_NONE;
   1048     soc_mem_t mem = LPM_IP_CONTROLm;
   1049     lpm_ip_control_entry_t entry;
   1050 
   1051     /* Field definitions */
   1052     soc_field_t db_sel_f[8] = {
   1053         LEVEL1_DATABASE_SEL_BLOCK_0f,
   1054         LEVEL1_DATABASE_SEL_BLOCK_1f,
   1055         LEVEL1_DATABASE_SEL_BLOCK_2f,
   1056         LEVEL1_DATABASE_SEL_BLOCK_3f,
   1057         LEVEL2_DATABASE_SEL_BLOCK_0f,
   1058         LEVEL2_DATABASE_SEL_BLOCK_1f,
   1059         LEVEL3_DATABASE_SEL_BLOCK_0f,
   1060         LEVEL3_DATABASE_SEL_BLOCK_1f
   1061     };
   1062 
   1063     soc_field_t ki_sel_f[8] = {
   1064         LEVEL1_KEY_INPUT_SEL_BLOCK_0f,
   1065         LEVEL1_KEY_INPUT_SEL_BLOCK_1f,
   1066         LEVEL1_KEY_INPUT_SEL_BLOCK_2f,
   1067         LEVEL1_KEY_INPUT_SEL_BLOCK_3f,
   1068         LEVEL2_KEY_INPUT_SEL_BLOCK_0f,
   1069         LEVEL2_KEY_INPUT_SEL_BLOCK_1f,
   1070         LEVEL3_KEY_INPUT_SEL_BLOCK_0f,
   1071         LEVEL3_KEY_INPUT_SEL_BLOCK_1f
   1072     };
   1073 
   1074     soc_field_t bnk_cf_f[4] = {
   1075         LEVEL2_BANK_CONFIG_BLOCK_0f,
   1076         LEVEL2_BANK_CONFIG_BLOCK_1f,
   1077         LEVEL3_BANK_CONFIG_BLOCK_0f,
   1078         LEVEL3_BANK_CONFIG_BLOCK_1f
   1079     };
   1080 
   1081     soc_field_t db_mod_f[2] = {
   1082         DB0_MODEf,
   1083         DB1_MODEf
   1084     };
   1085 
   1086     soc_field_t dt_sel_f[2] = {
   1087         DATA0_SELf,
   1088         DATA1_SELf
   1089     };
   1090 
   1091     /* Value definitions */
   1092     /* DB0: 0, Disable: 4 */
   1093     uint32 db_sel_v[MODES][PAIRS][8] = {
   1094         {   /* Combined */
   1095             {0, 0, 0, 0, 0, 0, 0, 0},   /* 0 block  paired */
   1096             {0, 0, 0, 0, 0, 0, 0, 0},   /* 1 block  paired */
   1097             {0, 0, 0, 0, 0, 0, 0, 0},   /* 2 blocks paired */
   1098             {0, 0, 0, 0, 0, 0, 0, 0},   /* 3 blocks paired */
   1099             {0, 0, 0, 0, 0, 0, 0, 0}    /* 4 blocks paired */
   1100         },
   1101         {   /* Parallel */
   1102             {0, 0, 1, 1, 0, 1, 0, 1},
   1103             {0, 0, 1, 1, 0, 1, 0, 1},
   1104             {0, 0, 1, 1, 0, 1, 0, 1},
   1105             {0, 0, 1, 1, 0, 1, 0, 1},
   1106             {0, 0, 1, 1, 0, 1, 0, 1}
   1107         },
   1108         {   /* Mixed */
   1109             {0, 0, 1, 1, 0, 0, 0, 0},
   1110             {0, 0, 1, 1, 0, 0, 0, 0},
   1111             {0, 0, 1, 1, 0, 0, 0, 0},
   1112             {0, 0, 1, 1, 0, 0, 0, 0},
   1113             {0, 0, 1, 1, 0, 0, 0, 0}
   1114         }
   1115     };
   1116 
   1117     /* IPv6: K0(0), 128bits; K1(1), 64bits */
   1118     uint32 ki_sel_v[MODES][PAIRS][8] = {
   1119         {   /* Combined */
   1120             {1, 1, 1, 1, 0, 0, 0, 0},   /* 0 block  paired */
   1121             {0, 1, 1, 1, 0, 0, 0, 0},   /* 1 block  paired */
   1122             {0, 0, 1, 1, 0, 0, 0, 0},   /* 2 blocks paired */
   1123             {0, 0, 0, 1, 0, 0, 0, 0},   /* 3 blocks paired */
   1124             {0, 0, 0, 0, 0, 0, 0, 0}    /* 4 blocks paired */
   1125         },
   1126         {   /* Parallel */
   1127             {1, 1, 1, 1, 0, 0, 0, 0},   /* 0 block  paired */
   1128             {0, 1, 0, 1, 0, 0, 0, 0},   /* 1 block  paired (invalid, use 2 blk paired setting) */
   1129             {0, 1, 0, 1, 0, 0, 0, 0},   /* 2 block  paired */
   1130             {0, 0, 0, 0, 0, 0, 0, 0},   /* 3 block  paired (invalid, use 4 blk paired setting) */
   1131             {0, 0, 0, 0, 0, 0, 0, 0}    /* 4 block  paired */
   1132         },
   1133         {   /* Mixed */
   1134             {1, 1, 1, 1, 0, 0, 0, 0},   /* 0 block  paired */
   1135             {0, 1, 0, 1, 0, 0, 0, 0},   /* 1 block  paired (invalid, use 2 blk paired setting) */
   1136             {0, 1, 0, 1, 0, 0, 0, 0},   /* 2 block  paired */
   1137             {0, 0, 0, 0, 0, 0, 0, 0},   /* 3 block  paired (invalid, use 4 blk paired setting) */
   1138             {0, 0, 0, 0, 0, 0, 0, 0}    /* 4 block  paired */
   1139         }
   1140     };
   1141 
   1142     /* Bank Config: bitmap */
   1143     uint32 bnk_cf_v[MODES][LVLS][4] = {
   1144         {   /* Combined */
   1145             {0, 0, 0, 0},             /* 1Level */
   1146             {0x7, 0x18, 0, 0},        /* 2Level */
   1147             {0x7, 0x18, 0xf, 0xf0}    /* 3Level */
   1148         },
   1149         {   /* Parallel */
   1150             {0, 0, 0, 0},
   1151             {0x7, 0x18, 0, 0},
   1152             {0x7, 0x18, 0xf, 0xf0}
   1153         },
   1154         {   /* Mixed */
   1155             {0, 0, 0, 0},
   1156             {0x7, 0x18, 0, 0},
   1157             {0x7, 0x18, 0xf, 0xf0}
   1158         }
   1159     };
   1160 
   1161     /* DB_MODE: 1Level(1), 2Level(2), 3Level(3), Disable(0) */
   1162     uint32 db_mod_v[MODES][LVLS][2] = {
   1163         {   /* Combined */
   1164             {1, 0},                     /* 1Level */
   1165             {2, 0},                     /* 2Level */
   1166             {3, 0}                      /* 3Level */
   1167         },
   1168         {   /* Parallel */
   1169             {1, 1},
   1170             {2, 2},
   1171             {3, 3}
   1172         },
   1173         {   /* Mixed */
   1174             {1, 1},
   1175             {2, 1},
   1176             {3, 1}
   1177         }
   1178     };
   1179 
   1180     /* DATA_SEL: DB0(0), DB1(1), Disable(4) */
   1181     uint32 dt_sel_v[MODES][2] = {
   1182         {0, 4},
   1183         {0, 1},
   1184         {0, 1}
   1185     };
   1186 
   1187     if (!soc_mem_is_valid(u, LPM_IP_CONTROLm)) {
   1188         return rv;
   1189     }
   1190 
   1191     mde = ALPM_MODE(u);
   1192     lvl = ACB_CNT(u);
   1193     prs = ALPM_TCAM_PAIR_BLK_CNT(u);
   1194 
   1195     sal_memset(&entry, 0, sizeof(entry));
   1196 
   1197     /* Adjust DATABASE_SEL values based on Level count */
   1198     for (i = 2; i > lvl; i--) {
   1199         db_sel_v[mde][prs][2*i+2] = 4; /* 4: Disable */
   1200         db_sel_v[mde][prs][2*i+3] = 4;
   1201     }
   1202 
   1203     if (soc_th3_get_alpm_banks(u) == 4) {
   1204         /* Set LEVEL3_DATABASE_SEL_BLOCK_0 to 4: Disable in half banks mode */
   1205         db_sel_v[mde][prs][6] = 4;
   1206         db_sel_v[mde][prs][7] = 0;
   1207         /* Set LEVEL3_BANK_CONFIG_BLOCK_0 to 0: UFT banks 0-3 for EM */
   1208         bnk_cf_v[mde][2][2] = 0;
   1209         if (ALPM_MODE_CHK(u, BCM_ALPM_MODE_PARALLEL) && (lvl == 2)) {
   1210             db_mod_v[mde][lvl][1] = 2; /* Public DB in Parallel mode goes to Level2 only */
   1211         }
   1212     }
   1213 
   1214     /* DATABASE_SEL fields */
   1215     for (i = 0; i < CNTOF(db_sel_f); i++) {
   1216         soc_mem_field32_set(u, mem, &entry, db_sel_f[i], db_sel_v[mde][prs][i]);
   1217     }
   1218 
   1219     /* KEY_INPUT_SEL fields */
   1220     for (i = 0; i < CNTOF(ki_sel_f); i++) {
   1221         soc_mem_field32_set(u, mem, &entry, ki_sel_f[i], ki_sel_v[mde][prs][i]);
   1222     }
   1223 
   1224     /* BANK_CONFIG fields */
   1225     for (i = 0; i < CNTOF(bnk_cf_f); i++) {
   1226         soc_mem_field32_set(u, mem, &entry, bnk_cf_f[i], bnk_cf_v[mde][lvl][i]);
   1227     }
   1228 
   1229     /* DB_MODE fields */
   1230     for (i = 0; i < CNTOF(db_mod_f); i++) {
   1231         soc_mem_field32_set(u, mem, &entry, db_mod_f[i], db_mod_v[mde][lvl][i]);
   1232     }
   1233 
   1234     /* DATA_SEL fields */
   1235     for (i = 0; i < CNTOF(dt_sel_f); i++) {
   1236         soc_mem_field32_set(u, mem, &entry, dt_sel_f[i], dt_sel_v[mde][i]);
   1237     }
   1238 
   1239     soc_mem_write(u, mem, COPYNO_ALL, 0, &entry);
   1240 
   1241     return rv;
   1242 }
   1243 
   1244 /* Initialize pivot and bkt bank mem and states.
   1245    allocate: TRUE when th3_alpm_ctrl_init,
   1246    FALSE when th3_alpm_ctrl_cleanup */
   1247 int
   1248 th3_alpm_ctrl_mem_init(int u, int allocate)
   1249 {
   1250     int rv = BCM_E_NONE;
   1251     int i, j, pid, acb_cnt, vrf_id, vrf_id_cnt;
   1252     uint8 def_mode, db_type;
   1253     int alloc_sz;
   1254     int scale_factor = 1;
   1255     int sf = 0;
   1256 
   1257     soc_mem_t mem, allmems[20] = {INVALIDm};
   1258     int m, mem_cnt = 0;
   1259 
   1260 
   1261     if (SOC_MEM_IS_VALID(u, L3_DEFIP_ALPM_LEVEL2m)) {
   1262         alpm_tbl = &th3_alpm_tbl[0];
   1263     }
   1264 
   1265     /* Default route data mode = Full (1) */
   1266     def_mode = soc_property_get(u, spn_L3_ALPM2_DEFAULT_ROUTE_DATA_MODE, 1);
   1267 
   1268     if (allocate) { /* for cleanup only scale_factor=1, sf=0 */
   1269         /* Load scaling factor config
   1270          * 8 means valid factors are 1,2,4,8...128
   1271          */
   1272         scale_factor = soc_property_get(u, "l3_alpm2_scaling_factor", 1);
   1273         for (sf = 0; sf < 8; sf++) {
   1274             if (scale_factor == (1 << sf)) {
   1275                 break;
   1276             }
   1277         }
   1278         if (sf >= 8) {
   1279             scale_factor = 1;
   1280             sf = 0;
   1281         }
   1282     }
   1283 
   1284     vrf_id_cnt = ALPM_VRF_ID_CNT(u);
   1285     acb_cnt = ACB_CNT(u);
   1286 
   1287     for (i = 0; i < acb_cnt; i++) {
   1288         _alpm_cb_t *acb = ACB(u, i);
   1289 
   1290 #define _CHK_IF_CLEAR_MEM(mem)                  \
   1291     do {                                        \
   1292         for (m = 0; m < mem_cnt; m++) {         \
   1293             if (allmems[m] == (mem)) {          \
   1294                 break;                          \
   1295             }                                   \
   1296         }                                       \
   1297         if (m == mem_cnt && mem != INVALIDm &&  \
   1298             soc_mem_index_count(u, mem) > 0) {  \
   1299             th3_alpm_hw_mem_clear(u, (mem));    \
   1300             allmems[mem_cnt++] = (mem);         \
   1301         }                                       \
   1302     } while (0)
   1303 
   1304         for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) {
   1305             _alpm_bkt_pool_conf_t *bp_conf = ACB_BKT_POOL(acb, pid);
   1306             if (pid > 0 && ACB_BKT_POOL(acb, pid-1) == bp_conf) {
   1307                 continue;
   1308             }
   1309 
   1310             /* Adjust bucket count based on scaling factor */
   1311             BPC_BNK_CNT(bp_conf) /= scale_factor;
   1312             alloc_sz = sizeof(_alpm_bnk_info_t);
   1313             ALPM_REALLOC_EG(BPC_BNK_INFO(bp_conf, ALPM_IPT_V4),
   1314                           alloc_sz, "bnk_bmp");
   1315             if (ALPM_128B(u) && ALPM_BKT_RSVD(u)) {
   1316                 int rsvd_v6_bnks =
   1317                     BPC_BNK_CNT(bp_conf) * ALPM_BKT_RSVD_CNT(u) / 8192;
   1318                 ALPM_REALLOC_EG(
   1319                     BPC_BNK_INFO(bp_conf, ALPM_IPT_V6), alloc_sz, "bnk_bmp");
   1320                 /* reserved v6 bnks in v4 bitmap */
   1321                 SHR_BITSET_RANGE(
   1322                     BPC_BNK_BMP(bp_conf, ALPM_IPT_V4),
   1323                     BPC_BNK_CNT(bp_conf) - rsvd_v6_bnks,
   1324                     rsvd_v6_bnks);
   1325                 BPC_BNK_RSVD(bp_conf, ALPM_IPT_V4) = rsvd_v6_bnks;
   1326                 /* reserved v4 bnks in v6 bitmap */
   1327                 SHR_BITSET_RANGE(
   1328                     BPC_BNK_BMP(bp_conf, ALPM_IPT_V6), 0,
   1329                     BPC_BNK_CNT(bp_conf) - rsvd_v6_bnks);
   1330                 BPC_BNK_RSVD(bp_conf, ALPM_IPT_V6) =
   1331                     BPC_BNK_CNT(bp_conf) - rsvd_v6_bnks;
   1332             } else {
   1333                 BPC_BNK_INFO(bp_conf, ALPM_IPT_V6) =
   1334                     BPC_BNK_INFO(bp_conf, ALPM_IPT_V4);
   1335             }
   1336 
   1337             if (!SOC_WARM_BOOT(u)) {
   1338                 mem = alpm_tbl[BPC_BKT_TBL(bp_conf)];
   1339                 _CHK_IF_CLEAR_MEM(mem);
   1340             }
   1341 
   1342             if (bp_conf->pvt_ptr == NULL) {
   1343                 alloc_sz = BPC_BNK_CNT(bp_conf);
   1344                 alloc_sz = sizeof(void *) * alloc_sz;
   1345                 ALPM_REALLOC_EG(bp_conf->pvt_ptr, alloc_sz, "pvt_ptr");
   1346             }
   1347         }
   1348 
   1349         /* Adjust bucket count based on scaling factor */
   1350         ALPM_IDX_BNK_SHIFT(acb) -= sf;
   1351 
   1352         /* Per instance structure init */
   1353         alloc_sz = vrf_id_cnt * sizeof(_alpm_pvt_ctrl_t);
   1354         for (j = 0; j < ALPM_IPT_CNT; j++) {
   1355             ALPM_REALLOC_EG(
   1356                 acb->pvt_ctl[j], alloc_sz, "pvt_ctl");
   1357             /* Initialize all VRF db_type with default route data mode */
   1358             for (vrf_id = 0; vrf_id < vrf_id_cnt; vrf_id++) {
   1359                 if (ALPM_VRF_ID_HAS_BKT(u, vrf_id)) {
   1360                     db_type = def_mode;
   1361                 } else {
   1362                     db_type = 1; /* DIRECT_ROUTE is always Full mode */
   1363                 }
   1364                 ACB_VRF_DB_TYPE_SET(u, acb, vrf_id, j, db_type);
   1365             }
   1366         }
   1367 
   1368         for (j = 0; j < ALPM_PKM_CNT; j++) {
   1369             if (!SOC_WARM_BOOT(u)) {
   1370                 mem = alpm_tbl[acb->pvt_tbl[j]];
   1371                 _CHK_IF_CLEAR_MEM(mem);
   1372             }
   1373         }
   1374     }
   1375 
   1376 bad:
   1377     return rv;
   1378 }
   1379 
   1380 int
   1381 th3_alpm_ctrl_init(int u)
   1382 {
   1383     int rv = BCM_E_NONE;
   1384     int i, j, pid, acb_cnt;
   1385     int alloc_sz;
   1386 
   1387     /*
   1388      *  b2(p1)  b1(p0)  bit0(128b)
   1389      * ---------------------------
   1390      *  0       0       0       -> 2-Level (64b)
   1391      *  0       0       1       -> 2-Level (128b)
   1392      *  0       1       0       -> 3-Level (p0-64b)
   1393      *  0       1       1       -> 3-Level (p0-128b)
   1394      *  1       0       0       -> 3-Level (p1-64b)
   1395      *  1       0       1       -> 3-Level (p1-128b)
   1396      */
   1397     _alpm_cb_t *acb_template[6] = {
   1398         &th3_alpm_1cb_template,
   1399         &th3_alpm_1cb_template_128b,
   1400         &th3_alpm_2cb_template_p0,
   1401         &th3_alpm_2cb_template_p0_128b,
   1402         &th3_alpm_2cb_template_p1,
   1403         &th3_alpm_2cb_template_p1
   1404     };
   1405 
   1406 #define ACB_BP_CONF_NUM    8
   1407     _alpm_bkt_pool_conf_t *acb_bp_conf[ACB_BP_CONF_NUM];
   1408 
   1409     _alpm_bkt_pool_conf_t *acb_bp_conf_template[ACB_BP_CONF_NUM] = {
   1410         &th3_alpm_cmode_pool_l2,
   1411         &th3_alpm_cmode_pool_l3,
   1412         &th3_alpm_pmode_pool_prt_l2,
   1413         &th3_alpm_pmode_pool_prt_l3,
   1414         &th3_alpm_cmode_pool_l2,
   1415         &th3_alpm_cmode_pool_l3,
   1416         &th3_alpm_pmode_pool_gbl_l2,
   1417         &th3_alpm_pmode_pool_gbl_l3
   1418     };
   1419 
   1420     alloc_sz = sizeof(_alpm_bkt_pool_conf_t);
   1421     ALPM_ALLOC_EG(th3_alpm_pool0_l2[u], alloc_sz, "th3_alpm_pool0_l2");
   1422     ALPM_ALLOC_EG(th3_alpm_pool1_l2[u], alloc_sz, "th3_alpm_pool1_l2");
   1423     ALPM_ALLOC_EG(th3_alpm_pool0_l3[u], alloc_sz, "th3_alpm_pool0_l3");
   1424     ALPM_ALLOC_EG(th3_alpm_pool1_l3[u], alloc_sz, "th3_alpm_pool1_l3");
   1425 
   1426     acb_bp_conf[0] = th3_alpm_pool0_l2[u];
   1427     acb_bp_conf[1] = th3_alpm_pool0_l3[u];
   1428     acb_bp_conf[2] = th3_alpm_pool0_l2[u];
   1429     acb_bp_conf[3] = th3_alpm_pool0_l3[u];
   1430     acb_bp_conf[4] = th3_alpm_pool0_l2[u];
   1431     acb_bp_conf[5] = th3_alpm_pool0_l3[u];
   1432     acb_bp_conf[6] = th3_alpm_pool1_l2[u];
   1433     acb_bp_conf[7] = th3_alpm_pool1_l3[u];
   1434 
   1435     /* assert ALPM_MEM_ENT_MAX for largest TCAM/ALPM memory entry */
   1436     assert(ALPM_MEM_ENT_MAX * sizeof(uint32)
   1437            >= sizeof(defip_pair_level1_entry_t));
   1438 
   1439     if (SOC_MEM_IS_VALID(u, L3_DEFIP_ALPM_LEVEL2m)) {
   1440         alpm_tbl = &th3_alpm_tbl[0];
   1441     }
   1442     acb_cnt = th3_alpm_cb_cnt(u);
   1443     assert((acb_cnt * ALPM_PKM_CNT) < 20);
   1444 
   1445     if (acb_cnt > 1 && (soc_th3_get_alpm_banks(u) == 0)) {
   1446         ALPM_ERR(("There is no UFT bank available for 3-Level ALPM\n"));
   1447         ALPM_IEG(BCM_E_CONFIG);
   1448     }
   1449 
   1450     for (i = 0; i < acb_cnt; i++) {
   1451         int idx;
   1452         _alpm_cb_t *acb = NULL;
   1453 
   1454         alloc_sz = sizeof(_alpm_cb_t);
   1455         ALPM_ALLOC_EG(acb, alloc_sz, "alpm_cb");
   1456         idx = (i + acb_cnt - 1) << 1 | (ALPM_128B(u) & 1);
   1457         sal_memcpy(acb, acb_template[idx], sizeof(_alpm_cb_t));
   1458         acb->unit = u;
   1459 
   1460         /**
   1461          *  -------
   1462          *  |2|1|0|
   1463          *  -------
   1464          *  Bit 0: acb_idx: acb0, acb1
   1465          *  Bit 1: Parallel: 1, Mixed/Combined: 0
   1466          *  Bit 2: Private(Pid 0)/Global(Pid 1)
   1467          *  ---------
   1468  */
   1469         for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) {
   1470             idx = pid << 2 | (!!ALPM_MODE_CHK(u, BCM_ALPM_MODE_PARALLEL) << 1) | i;
   1471             ACB_BKT_POOL(acb, pid) = acb_bp_conf[idx];
   1472             sal_memcpy(acb_bp_conf[idx], acb_bp_conf_template[idx],
   1473                        sizeof(_alpm_bkt_pool_conf_t));
   1474         }
   1475 
   1476         /* Adjust ctrl bnk conf
   1477          * BPC should NOT be adjusted because they point to
   1478          * global storage
   1479          */
   1480         ALPM_IEG(th3_alpm_cfg_adjust(u, acb_cnt, acb));
   1481 
   1482         ACB(u, i) = acb;
   1483     }
   1484 
   1485     ACB_CNT(u) = acb_cnt;
   1486 
   1487     /* Init pvt/bkt bank mem and ctrl (with allocate=TRUE) */
   1488     ALPM_IEG(th3_alpm_ctrl_mem_init(u, TRUE));
   1489 
   1490     /* Obtain TCAM table skip (invalid or duplicated) per */
   1491     for (i = 0; i < ALPM_PKM_CNT; i++) {
   1492 
   1493         if (alpm_tbl[ACB_TOP(u)->pvt_tbl[i]] == INVALIDm) {
   1494             ALPM_TCAM_TBL_SKIP(u, i) = TRUE; /* invalid */
   1495              continue;
   1496         } else {
   1497             ALPM_TCAM_TBL_SKIP(u, i) = FALSE;
   1498         }
   1499 
   1500         for (j = 0; j < i; j++) {
   1501             if (alpm_tbl[ACB_TOP(u)->pvt_tbl[i]] ==
   1502                 alpm_tbl[ACB_TOP(u)->pvt_tbl[j]]) {
   1503                 ALPM_TCAM_TBL_SKIP(u, j) = TRUE; /* duplicated */
   1504                 break;
   1505             }
   1506         }
   1507     }
   1508 
   1509     if (!SOC_WARM_BOOT(u)) {
   1510         rv = th3_alpm_hw_init(u);
   1511     }
   1512 
   1513     th3_fmt_test(u);
   1514     th3_mem_test(u);
   1515 
   1516     return rv;
   1517 
   1518 bad:
   1519     th3_alpm_ctrl_deinit(u);
   1520     return rv;
   1521 }
   1522 
   1523 /* TH3 ALPM ctrl cleanup (for faster delete_all) */
   1524 int
   1525 th3_alpm_ctrl_cleanup(int u)
   1526 {
   1527     /* Cleanup only bank mem and ctrl state,
   1528        but keep statistics (with allocate=FALSE) */
   1529     return (th3_alpm_ctrl_mem_init(u, FALSE));
   1530 }
   1531 
   1532 /* L3_DEFIP_ALPM_ROUTE_BANK_FMT1fmt
   1533  *   -> ENTRY0f: L3_DEFIP_ALPM_ROUTE_FMT1fmt
   1534  *        -> PREFIXf
   1535  *        -> ASSOC_DATAf: ASSOC_DATA_REDUCEDfmt
   1536  *             -> DEST_TYPEf
   1537  *             -> DESTINATIONf
   1538  *
   1539  *        -> ASSOC_DATAf: ASSOC_DATA_FULLfmt
   1540  *             -> DEST_TYPEf
   1541  *             -> DESTINATIONf
   1542  *             -> PRIf
   1543  *             -> RPEf
   1544  *             -> DST_DISCARDf
   1545  *             -> CLASS_IDf
   1546  *             -> FLEX_CTR_POOL_NUMBERf
   1547  *             -> FLEX_CTR_OFFSET_MODEf
   1548  *             -> FLEX_CTR_BASE_COUNTER_IDXf
   1549  */
   1550 
   1551 int8
   1552 th3_alpm_bnk_fmt_get(int u, _alpm_cb_t *acb,
   1553                      _alpm_bkt_info_t *bkt_info, int ent_idx)
   1554 {
   1555     int bnk_idx;
   1556 
   1557     bnk_idx = ALPM_IDX_TO_BNK(acb, ent_idx);
   1558 
   1559     return bkt_info->bnk_fmt[bnk_idx];
   1560 
   1561 }
   1562 
   1563 static void
   1564 th3_alpm_ent_1bit_encoding(int u, uint32 *pfx, int fmt_len, int pfx_len)
   1565 {
   1566     SHR_BITSET(pfx, fmt_len - pfx_len);
   1567 }
   1568 
   1569 static void
   1570 th3_alpm_ent_1bit_decoding(int u, uint32 *pfx, int fmt_len, int *pfx_len)
   1571 {
   1572     int bp = 0; /* Bit pos */
   1573 #if 0
   1574     for (bp = 0; bp <= fmt_len; bp++) {
   1575         if (SHR_BITGET(pfx, bp)) {
   1576             break;
   1577         }
   1578     }
   1579 #else
   1580     static int fbit[16] = {
   1581        -1, /* 0b0000 */
   1582         0, /* 0b0001 */
   1583         1, /* 0b0010 */
   1584         0, /* 0b0011 */
   1585         2, /* 0b0100 */
   1586         0, /* 0b0101 */
   1587         1, /* 0b0110 */
   1588         0, /* 0b0111 */
   1589         3, /* 0b1000 */
   1590         0, /* 0b1001 */
   1591         1, /* 0b1010 */
   1592         0, /* 0b1011 */
   1593         2, /* 0b1100 */
   1594         0, /* 0b1101 */
   1595         1, /* 0b1110 */
   1596         0, /* 0b1111 */
   1597     };
   1598 
   1599     while (bp < fmt_len) {
   1600         uint32 tmp;
   1601         if (*pfx != 0) {
   1602             tmp = *pfx;
   1603             while (tmp > 0) {
   1604                 if (tmp & 0xf) {
   1605                     bp += fbit[tmp & 0xf];
   1606                     break;
   1607                 }
   1608                 bp += 4;
   1609                 tmp = tmp >> 4;
   1610             }
   1611             break;
   1612         } else {
   1613             pfx ++;
   1614             bp += 32;
   1615         }
   1616     }
   1617 #endif
   1618     *pfx_len = fmt_len - bp;
   1619 }
   1620 
   1621 static void
   1622 th3_alpm_ent_assemble(int u, _alpm_cb_t *acb,
   1623                       _alpm_pvt_node_t *pvt_node, int ent_idx,
   1624                       _bcm_defip_cfg_t *lpm_cfg, uint32 *entry, uint32 write_flags)
   1625 {
   1626     int b, vrf_id, ipt;
   1627     int ofst, key_len;
   1628     int dst_sbit, src_sbit; /* Source start bit and Dest start bit */
   1629     int fmt_len, cpy_len, max_pfx_len[] = {32, 128};
   1630     int8 fmt_tp;
   1631 
   1632     uint32 fmt[6] = {0};
   1633     uint32 key[8] = {0};
   1634     uint32 pfx[5] = {0};
   1635     uint32 fent[ALPM_ENT_WORDS_MAX] = {0};
   1636     soc_format_t ent_fmt, bnk_fmt;
   1637 
   1638     _alpm_bkt_info_t      *bkt_info = NULL;
   1639     _alpm_bkt_pool_conf_t *bp_conf = NULL;
   1640 
   1641     th3_fmt_ASSOC_DATA_FULL_t       *fmt_adf = NULL;
   1642     th3_fmt_ASSOC_DATA_REDUCED_t    *fmt_adr = NULL;
   1643     th3_fmt_ALPM2_DATA_t            fmt_a2d;
   1644 
   1645     vrf_id = ALPM_LPM_VRF_ID(u, lpm_cfg);
   1646     ipt    = ALPM_LPM_IPT(u, lpm_cfg);
   1647 
   1648     fmt_tp  = th3_alpm_bnk_fmt_get(u, acb, &PVT_BKT_INFO(pvt_node), ent_idx);
   1649     ent_fmt = ACB_FMT_ENT(acb, vrf_id, fmt_tp);
   1650     bnk_fmt = ACB_FMT_BNK(acb, vrf_id, fmt_tp);
   1651     ofst    = ALPM_IDX_TO_ENT(ent_idx);
   1652 
   1653     if (write_flags != ALPM_PVT_UPDATE_ALL) {
   1654         soc_format_field_get(u, bnk_fmt, entry, th3_alpm_ent_fld[ofst], fent);
   1655     }
   1656 
   1657     /* Assoc DATA update */
   1658     if (write_flags & ALPM_PVT_UPDATE_ASSOC_DATA) {
   1659         if (ACB_VRF_DB_TYPE(u, acb, vrf_id, ipt)) {
   1660             fmt_adf = (th3_fmt_ASSOC_DATA_FULL_t *)fmt;
   1661             fmt_adf->DEST_TYPE = lpm_cfg->defip_flags & BCM_L3_MULTIPATH ? 1 : 0;
   1662             fmt_adf->DESTINATION = lpm_cfg->defip_ecmp_index;
   1663             fmt_adf->PRI = lpm_cfg->defip_prio;
   1664             fmt_adf->RPE = lpm_cfg->defip_flags & BCM_L3_RPE ? 1 : 0;
   1665             fmt_adf->DST_DISCARD = lpm_cfg->defip_flags & BCM_L3_DST_DISCARD ? 1 : 0;
   1666             fmt_adf->CLASS_ID = lpm_cfg->defip_lookup_class;
   1667             fmt_adf->FLEX_CTR_POOL_NUMBER = lpm_cfg->defip_flex_ctr_pool;
   1668             fmt_adf->FLEX_CTR_OFFSET_MODE = lpm_cfg->defip_flex_ctr_mode;
   1669             fmt_adf->FLEX_CTR_BASE_COUNTER_IDX = lpm_cfg->defip_flex_ctr_base_id;
   1670         } else {
   1671             fmt_adr = (th3_fmt_ASSOC_DATA_REDUCED_t *)fmt;
   1672             fmt_adr->DEST_TYPE = lpm_cfg->defip_flags & BCM_L3_MULTIPATH ? 1 : 0;
   1673             fmt_adr->DESTINATION = lpm_cfg->defip_ecmp_index;
   1674         }
   1675         soc_format_field_set(u, ent_fmt, fent, ASSOC_DATAf, fmt);
   1676     }
   1677 
   1678     if (write_flags & ALPM_PVT_UPDATE_PREFIX) {
   1679         key_len = PVT_KEY_LEN(pvt_node);
   1680         fmt_len = ACB_FMT_PFX_LEN(acb, vrf_id, fmt_tp);
   1681         /*
   1682          * 128B:
   1683          *   ip6[0]            ----          ip6[15]
   1684          *   ffff:ffff:0000:0000:0000:0000:0000:0000
   1685          *   prefix[7] prefix[6] prefix[5] prefix[4] ... prefix[0]
   1686          * 64B:
   1687          *                       ip6[0] ---- ip6[7]
   1688          *                       ffff:ffff:0000:0000
   1689          *   prefix[7] prefix[6] prefix[5] prefix[4] ... prefix[0]
   1690          * 32B:
   1691          *                                 ip_addr
   1692          *                                 c0a80101
   1693          *   prefix[7] prefix[6] prefix[5] prefix[4] ... prefix[0]
   1694          */
   1695         alpm_util_cfg_to_key(u, ipt, lpm_cfg, &key[4]);
   1696         if (max_pfx_len[ipt] < fmt_len) {
   1697             src_sbit = 128;
   1698             cpy_len = max_pfx_len[ipt] - key_len;
   1699             dst_sbit = 1 + fmt_len - cpy_len;
   1700         } else {
   1701             src_sbit = 128 + max_pfx_len[ipt] - key_len - fmt_len;
   1702             cpy_len = fmt_len;
   1703             dst_sbit = 1;
   1704         }
   1705         SHR_BITCOPY_RANGE(pfx, dst_sbit, key, src_sbit, cpy_len);
   1706         /* 1bit Length Encoding */
   1707         th3_alpm_ent_1bit_encoding(u, pfx, fmt_len,
   1708                                    lpm_cfg->defip_sub_len - key_len);
   1709         soc_format_field_set(u, ent_fmt, fent, PREFIXf, pfx);
   1710     }
   1711 
   1712     if ((write_flags & ALPM_PVT_UPDATE_ALPM_DATA) && ACB_HAS_PVT(acb, vrf_id)) {
   1713         /* Pivot level ALPM data update */
   1714         sal_memset(&fmt_a2d, 0, sizeof(fmt_a2d));
   1715         bkt_info = (_alpm_bkt_info_t *)lpm_cfg->bkt_info;
   1716         if (bkt_info != NULL) {
   1717             int offset = 0;
   1718             _alpm_tbl_t tbl;
   1719 
   1720             bp_conf = ACB_BKT_VRF_POOL(ACB_DWN(u, acb), PVT_BKT_VRF(pvt_node));
   1721             tbl = BPC_BKT_TBL(bp_conf);
   1722             switch (tbl) {
   1723                 case alpmTblBktPmodeGblL2:
   1724                 case alpmTblBktPmodeGblL3:
   1725                     offset = ACB_BNK_PER_BKT(ACB_DWN(u, acb), 1);
   1726                     break;
   1727                 default:
   1728                     break;
   1729             }
   1730 
   1731             if (ALPM_HLF_BNKS(u)) {
   1732                 offset = 4;
   1733             }
   1734 
   1735             fmt_a2d.KSHIFT = lpm_cfg->bkt_kshift;
   1736             fmt_a2d.ROFS = bkt_info->rofs + offset;
   1737             fmt_a2d.BKT_PTR = bkt_info->bkt_idx;
   1738             if (ALPM_TCAM_ZONED(u) && lpm_cfg->default_miss == 1) {
   1739                 /* TH3TBD, Parallel & Mixed ALPM need to set DEFAULT_MISS to 1
   1740                  * if assoc_data is NOT set, in case of missing default */
   1741                 fmt_a2d.DEFAULT_MISS = 1;
   1742             }
   1743             for (b = 0; b < BPC_BNK_PER_BKT(bp_conf); b++) {
   1744                 soc_field_t bnk_fld;
   1745                 if (bkt_info->bnk_fmt[b] == 0) {
   1746                     continue;
   1747                 }
   1748 
   1749                 bnk_fld = th3_alpm_bnk_fld[b+offset];
   1750                 switch (bnk_fld) {
   1751                     case FMT0f:
   1752                         fmt_a2d.FMT0 = bkt_info->bnk_fmt[b];
   1753                         break;
   1754                     case FMT1f:
   1755                         fmt_a2d.FMT1 = bkt_info->bnk_fmt[b];
   1756                         break;
   1757                     case FMT2f:
   1758                         fmt_a2d.FMT2 = bkt_info->bnk_fmt[b];
   1759                         break;
   1760                     case FMT3f:
   1761                         fmt_a2d.FMT3 = bkt_info->bnk_fmt[b];
   1762                         break;
   1763                     case FMT4f:
   1764                         fmt_a2d.FMT4 = bkt_info->bnk_fmt[b];
   1765                         break;
   1766                     case FMT5f:
   1767                         fmt_a2d.FMT5 = bkt_info->bnk_fmt[b];
   1768                         break;
   1769                     case FMT6f:
   1770                         fmt_a2d.FMT6 = bkt_info->bnk_fmt[b];
   1771                         break;
   1772                     case FMT7f:
   1773                         fmt_a2d.FMT7 = bkt_info->bnk_fmt[b];
   1774                         break;
   1775                     default:
   1776                         break;
   1777                 }
   1778             }
   1779             soc_format_field_set(u, ent_fmt, fent, ALPM2_DATAf, (uint32 *)&fmt_a2d);
   1780         }
   1781     }
   1782 
   1783     soc_format_field_set(u, bnk_fmt, entry, th3_alpm_ent_fld[ofst], fent);
   1784 
   1785     return ;
   1786 
   1787 }
   1788 
   1789 int
   1790 th3_alpm_ent_pfx_len_get(int u, _alpm_cb_t *acb,
   1791                          _alpm_pvt_node_t *pvt_node, int ent_idx)
   1792 {
   1793     int    rv;
   1794     int    ent_id, pfx_len = -1;
   1795     int8   fmt_tp;
   1796     int16  fmt_len;
   1797     uint32 bnkb[17];
   1798     uint32 entb[17] = {0};
   1799     uint32 fldb[17] = {0};
   1800     soc_format_t bnk_fmt, ent_fmt;
   1801     _alpm_bkt_pool_conf_t *bp_conf;
   1802 
   1803     bp_conf = ACB_BKT_VRF_POOL(acb, PVT_BKT_VRF(pvt_node));
   1804     /* Get Bank data: bnkb */
   1805     rv = th3_mem_read(u, acb, BPC_BKT_TBL(bp_conf),
   1806                       ALPM_TAB_IDX_GET(ent_idx), bnkb, FALSE);
   1807     if (BCM_SUCCESS(rv)) {
   1808         fmt_tp = th3_alpm_bnk_fmt_get(u, acb, &PVT_BKT_INFO(pvt_node), ent_idx);
   1809         bnk_fmt = BPC_FMT_BNK(bp_conf, fmt_tp);
   1810         ent_id  = ALPM_IDX_TO_ENT(ent_idx);
   1811 
   1812         /* Get Entry data: entb */
   1813         (void)soc_format_field_get(u, bnk_fmt, bnkb,
   1814                                    th3_alpm_ent_fld[ent_id], entb);
   1815         /* Get PREFIXf Field data: tmpf */
   1816         ent_fmt = BPC_FMT_ENT(bp_conf, fmt_tp);
   1817         (void)soc_format_field_get(u, ent_fmt, entb, PREFIXf, fldb);
   1818 
   1819         /* 1bit Length Decoding */
   1820         fmt_len = BPC_FMT_PFX_LEN(bp_conf, fmt_tp);
   1821         th3_alpm_ent_1bit_decoding(u, fldb, fmt_len, &pfx_len);
   1822     }
   1823 
   1824     return pfx_len;
   1825 }
   1826 
   1827 void
   1828 th3_alpm_ent_copy(int u, int vrf_id, _alpm_cb_t *acb, uint32 *sb_ent, uint32 *db_ent,
   1829                   _alpm_bkt_info_t *sbinfo, _alpm_bkt_info_t *dbinfo,
   1830                   uint32 src_pvt_len, uint32 dst_pvt_len,
   1831                   uint32 src_idx, uint32 dst_idx)
   1832 {
   1833     int src_pfx_len, dst_pfx_len;
   1834 
   1835     int8 src_fid, dst_fid;
   1836     int16 src_fmt_len, dst_fmt_len;
   1837     uint32 src_eid, dst_eid;
   1838     uint32 se_ent[17] = {0};
   1839     uint32 de_ent[17] = {0};
   1840 
   1841     uint32 tmpf[17] = {0};
   1842     uint32 dstf[17] = {0};
   1843 
   1844     soc_format_t sb_fmt, db_fmt;
   1845     soc_format_t se_fmt, de_fmt;
   1846 
   1847     assert(dst_pvt_len >= src_pvt_len);
   1848 
   1849     /* Retrieve src entry */
   1850     src_fid = th3_alpm_bnk_fmt_get(u, acb, sbinfo, src_idx);
   1851     src_eid = ALPM_IDX_TO_ENT(src_idx);
   1852     sb_fmt  = ACB_FMT_BNK(acb, vrf_id, src_fid);
   1853     se_fmt  = ACB_FMT_ENT(acb, vrf_id, src_fid);
   1854     soc_format_field_get(u, sb_fmt, sb_ent, th3_alpm_ent_fld[src_eid], se_ent);
   1855 
   1856     dst_fid = th3_alpm_bnk_fmt_get(u, acb, dbinfo, dst_idx);
   1857     dst_eid = ALPM_IDX_TO_ENT(dst_idx);
   1858     db_fmt  = ACB_FMT_BNK(acb, vrf_id, dst_fid);
   1859     de_fmt  = ACB_FMT_ENT(acb, vrf_id, dst_fid);
   1860 
   1861     /* Copy ASSOC_DATA and ALPM2_DATA field */
   1862     if (sb_fmt != db_fmt) {
   1863         sal_memset(tmpf, 0, sizeof(tmpf));
   1864         soc_format_field_get(u, se_fmt, se_ent, ASSOC_DATAf, tmpf);
   1865         soc_format_field_set(u, de_fmt, de_ent, ASSOC_DATAf, tmpf);
   1866         if (ACB_HAS_PVT(acb, vrf_id)) {
   1867             sal_memset(tmpf, 0, sizeof(tmpf));
   1868             soc_format_field_get(u, se_fmt, se_ent, ALPM2_DATAf, tmpf);
   1869             soc_format_field_set(u, de_fmt, de_ent, ALPM2_DATAf, tmpf);
   1870         }
   1871     } else {
   1872         sal_memcpy(de_ent, se_ent, sizeof(de_ent));
   1873     }
   1874 
   1875     /* Copy PREFIX field */
   1876     sal_memset(tmpf, 0, sizeof(tmpf));
   1877     soc_format_field_get(u, se_fmt, se_ent, PREFIXf, tmpf);
   1878     src_fmt_len = ACB_FMT_PFX_LEN(acb, vrf_id, src_fid);
   1879     dst_fmt_len = ACB_FMT_PFX_LEN(acb, vrf_id, dst_fid);
   1880 
   1881     /* 1bit Length Decoding */
   1882     th3_alpm_ent_1bit_decoding(u, tmpf, src_fmt_len, &src_pfx_len);
   1883     dst_pfx_len = src_pfx_len - (dst_pvt_len - src_pvt_len);
   1884     if (dst_pfx_len > dst_fmt_len) {
   1885         assert(0);
   1886     } else {
   1887         /* Copy only prefix part, src/dst offsets need jump after
   1888            1bit encoding and do 1bit encoding after copy */
   1889         SHR_BITCOPY_RANGE(dstf, dst_fmt_len - dst_pfx_len + 1,
   1890             tmpf, src_fmt_len - src_pfx_len + 1, dst_pfx_len);
   1891     }
   1892 
   1893     /* 1bit Length Encoding */
   1894     th3_alpm_ent_1bit_encoding(u, dstf, dst_fmt_len, dst_pfx_len);
   1895 
   1896     soc_format_field_set(u, de_fmt, de_ent, PREFIXf, dstf);
   1897 
   1898     /* Write entry back to bank */
   1899     soc_format_field_set(u, db_fmt, db_ent, th3_alpm_ent_fld[dst_eid], de_ent);
   1900 
   1901     return ;
   1902 }
   1903 
   1904 int
   1905 th3_alpm_bkt_bnk_write(int u, _alpm_cb_t *acb,
   1906                        _alpm_pvt_node_t *pvt_node,
   1907                        _bcm_defip_cfg_t *lpm_cfg, int ent_idx, uint32 write_flags)
   1908 {
   1909     int rv = BCM_E_NONE, index, vrf_id;
   1910     uint32 entry[ALPM_ENT_WORDS_MAX];
   1911     _alpm_tbl_t tbl;
   1912     uint32 vet_bmp;
   1913 
   1914     vrf_id = PVT_BKT_VRF(pvt_node);
   1915     index  = ALPM_TAB_IDX_GET(ent_idx);
   1916     tbl    = BPC_BKT_TBL(ACB_BKT_VRF_POOL(acb, vrf_id));
   1917 
   1918     vet_bmp = PVT_BKT_INFO(pvt_node).vet_bmp[ALPM_IDX_TO_BNK(acb, ent_idx)];
   1919 
   1920     if (vet_bmp & ~(1 << ALPM_IDX_TO_ENT(ent_idx))) {
   1921         rv = th3_mem_read(u, acb, tbl, index, entry, FALSE);
   1922     } else {
   1923         /* If it was empty bank then there is no need to do read */
   1924         sal_memset(entry, 0, sizeof(entry));
   1925     }
   1926 
   1927     if (BCM_SUCCESS(rv)) {
   1928         th3_alpm_ent_assemble(u, acb, pvt_node, ent_idx, lpm_cfg, entry, write_flags);
   1929         rv = th3_mem_write(u, acb, pvt_node, tbl, index, entry);
   1930 
   1931         /* write route HITBIT to cache & Hw */
   1932         if (!ALPM_HIT_SKIP(u)) {
   1933             if (BCM_SUCCESS(rv) && ACB_HAS_RTE(acb, vrf_id)) {
   1934                 th3_alpm_bkt_hit_write(u, PVT_BKT_VRF(pvt_node), acb, tbl, ent_idx,
   1935                                  (lpm_cfg->defip_flags & BCM_L3_HIT ? 1 : 0));
   1936             }
   1937         }
   1938     }
   1939 
   1940     return rv;
   1941 }
   1942 
   1943 static int
   1944 th3_alpm_bkt_bnk_shrink(int u, _alpm_cb_t *acb,
   1945                         _alpm_pvt_node_t *pvt_node, uint8 sbnk,
   1946                         uint8 dbnk, _alpm_bkt_pfx_arr_t *pfx_arr)
   1947 {
   1948     int i, j, k, rv = 0;
   1949     int sepb, depb;
   1950     int vrf_id;
   1951     int8 src_fid, dst_fid;
   1952 
   1953     soc_format_t sb_fmt, db_fmt;
   1954 
   1955     uint32 tmp_idx, stab_idx, dtab_idx;
   1956     _alpm_bkt_info_t *bkt_info = NULL;
   1957 
   1958     uint32 srcbnke[17];
   1959     uint32 nullent[17];
   1960     uint32 dstbnke[17];
   1961     uint32 tempent[17];
   1962 
   1963     /* Bulk Write */
   1964     int bulk_idx[2];
   1965     uint32 *bulk_ent[2];
   1966     int bulk_cnt;
   1967 
   1968     _alpm_bkt_pool_conf_t *bp_conf;
   1969 
   1970     vrf_id  = PVT_BKT_VRF(pvt_node);
   1971     bp_conf = ACB_BKT_VRF_POOL(acb, vrf_id);
   1972 
   1973     bkt_info = &PVT_BKT_INFO(pvt_node);
   1974     src_fid  = bkt_info->bnk_fmt[sbnk];
   1975     dst_fid  = bkt_info->bnk_fmt[dbnk];
   1976     sepb     = ACB_FMT_ENT_MAX(acb, vrf_id, src_fid);
   1977     depb     = ACB_FMT_ENT_MAX(acb, vrf_id, dst_fid);
   1978 
   1979     if (bkt_info->vet_bmp[dbnk] == 0) {
   1980         /* Copy from entire from_bnk to to_bnk and don't invalidate
   1981            from_bnk until upper level pivot changed. Invalidate
   1982            from_bnk is optional after pivot changed. */
   1983         stab_idx = ALPM_TAB_IDX_GET_BI_BNK(acb, bkt_info, sbnk);
   1984         dtab_idx = ALPM_TAB_IDX_GET_BI_BNK(acb, bkt_info, dbnk);
   1985 
   1986         rv = th3_mem_read(u, acb, BPC_BKT_TBL(bp_conf),
   1987                           stab_idx, srcbnke, FALSE);
   1988         ALPM_IER(rv);
   1989 
   1990         rv = th3_mem_write(u, acb, pvt_node, BPC_BKT_TBL(bp_conf),
   1991                            dtab_idx, srcbnke);
   1992 
   1993         ALPM_IER(rv);
   1994 
   1995         bkt_info->vet_bmp[dbnk] = bkt_info->vet_bmp[sbnk];
   1996         bkt_info->vet_bmp[sbnk] = 0;
   1997         bkt_info->bnk_fmt[dbnk] = src_fid;
   1998 
   1999         /* Update ent_idx of prefix */
   2000         for (i = 0; i < pfx_arr->pfx_cnt; i++) {
   2001             tmp_idx = pfx_arr->pfx[i]->ent_idx;
   2002             if (ALPM_IDX_TO_BNK(acb, tmp_idx) == sbnk) {
   2003                 pfx_arr->pfx[i]->ent_idx =
   2004                     ALPM_IDX_MAKE(acb, bkt_info, dbnk,
   2005                     ALPM_IDX_TO_ENT(tmp_idx));
   2006             }
   2007         }
   2008 
   2009         ALPM_INFO(("**ACB(%d).BNK.MRG: RBBE from(%d %d %d *) to(%d %d %d *)\n",
   2010                    ACB_IDX(acb),
   2011                    PVT_ROFS(pvt_node),
   2012                    PVT_BKT_IDX(pvt_node), sbnk,
   2013                    PVT_ROFS(pvt_node),
   2014                    PVT_BKT_IDX(pvt_node), dbnk));
   2015 
   2016         return rv;
   2017     }
   2018 
   2019     /* Merge */
   2020     stab_idx = ALPM_TAB_IDX_GET_BI_BNK(acb, bkt_info, sbnk);
   2021     rv = th3_mem_read(u, acb, BPC_BKT_TBL(bp_conf),
   2022                       stab_idx, srcbnke, FALSE);
   2023     ALPM_IER(rv);
   2024     dtab_idx = ALPM_TAB_IDX_GET_BI_BNK(acb, bkt_info, dbnk);
   2025     rv = th3_mem_read(u, acb, BPC_BKT_TBL(bp_conf),
   2026                       dtab_idx, dstbnke, FALSE);
   2027     ALPM_IER(rv);
   2028 
   2029     sb_fmt = ACB_FMT_BNK(acb, vrf_id, src_fid);
   2030     db_fmt = ACB_FMT_BNK(acb, vrf_id, dst_fid);
   2031     for (i = 0; i < depb; i++) {
   2032         /* to entry i */
   2033         if (bkt_info->vet_bmp[dbnk] & (1 << i)) {
   2034             continue;
   2035         }
   2036         for (j = 0; j < sepb; j++) {
   2037             if (!(bkt_info->vet_bmp[sbnk] & (1 << j))) {
   2038                 continue;
   2039             }
   2040             /* from entry j */
   2041             if (sb_fmt != db_fmt) {
   2042                 uint32 src_idx, dst_idx;
   2043                 src_idx = ALPM_IDX_MAKE(acb, bkt_info, sbnk, j);
   2044                 dst_idx = ALPM_IDX_MAKE(acb, bkt_info, dbnk, i);
   2045                 th3_alpm_ent_copy(u, vrf_id, acb, srcbnke, dstbnke,
   2046                             &PVT_BKT_INFO(pvt_node),
   2047                             &PVT_BKT_INFO(pvt_node),
   2048                             PVT_KEY_LEN(pvt_node),
   2049                             PVT_KEY_LEN(pvt_node),
   2050                             src_idx, dst_idx);
   2051             } else {
   2052                 sal_memset(tempent, 0, sizeof(tempent));
   2053                 (void)soc_format_field_get(u, sb_fmt, srcbnke,
   2054                                            th3_alpm_ent_fld[j], tempent);
   2055                 (void)soc_format_field_set(u, db_fmt, dstbnke,
   2056                                            th3_alpm_ent_fld[i], tempent);
   2057             }
   2058             /* Invalidate entry j */
   2059             sal_memset(nullent, 0, sizeof(nullent));
   2060             (void)soc_format_field_set(u, sb_fmt, srcbnke,
   2061                                        th3_alpm_ent_fld[j], nullent);
   2062 
   2063             bkt_info->vet_bmp[sbnk] &= ~(1 << j);
   2064             bkt_info->vet_bmp[dbnk] |= (1 << i);
   2065 
   2066             ALPM_INFO((
   2067                 "**ACB(%d).BNK.MRG: RBBE from(%d %d %d %d) to(%d %d %d %d)\n",
   2068                 ACB_IDX(acb),
   2069                 PVT_ROFS(pvt_node), PVT_BKT_IDX(pvt_node), sbnk, j,
   2070                 PVT_ROFS(pvt_node), PVT_BKT_IDX(pvt_node), dbnk, i));
   2071 
   2072             /* Update ent_idx of prefix */
   2073             for (k = 0; k < pfx_arr->pfx_cnt; k++) {
   2074                 tmp_idx = pfx_arr->pfx[k]->ent_idx;
   2075                 if (ALPM_IDX_TO_BNK(acb, tmp_idx) == sbnk &&
   2076                     ALPM_IDX_TO_ENT(tmp_idx) == j) {
   2077                     pfx_arr->pfx[k]->ent_idx =
   2078                         ALPM_IDX_MAKE(acb, bkt_info, dbnk, i);
   2079                 }
   2080             }
   2081             break;
   2082         }
   2083     }
   2084 
   2085     bulk_idx[0] = dtab_idx;
   2086     bulk_ent[0] = dstbnke;
   2087     bulk_cnt = 1;
   2088     if (bkt_info->vet_bmp[sbnk]) {
   2089         bulk_idx[1] = stab_idx;
   2090         bulk_ent[1] = srcbnke;
   2091         bulk_cnt ++;
   2092     }
   2093     rv = th3_mem_bulk_write(u, acb, pvt_node, BPC_BKT_TBL(bp_conf),
   2094                             bulk_idx, bulk_ent, bulk_cnt);
   2095 
   2096     return rv;
   2097 }
   2098 
   2099 int
   2100 th3_alpm_bkt_pfx_copy(int u, _alpm_cb_t *acb,
   2101                        _alpm_bkt_pfx_arr_t *pfx_arr,
   2102                        _alpm_pvt_node_t *opvt_node,
   2103                        _alpm_pvt_node_t *npvt_node)
   2104 {
   2105     int i, rv = BCM_E_NONE;
   2106     int vrf_id;
   2107     uint32 src_idx, dst_idx = 0;
   2108     uint8  def_fmt;
   2109     uint16 sb_cnt[ALPM_BPB_MAX] = {0};
   2110     uint16 db_cnt[ALPM_BPB_MAX] = {0};
   2111     uint32 srcbnke[ALPM_BPB_MAX][17];
   2112     uint32 dstbnke[ALPM_BPB_MAX][17];
   2113 
   2114     int     bulk_idx[ALPM_BPB_MAX];
   2115     uint32  *bulk_ent[ALPM_BPB_MAX];
   2116     int     bulk_ent_cnt = 0;
   2117 
   2118     _alpm_bkt_info_t *src_bkt, *dst_bkt;
   2119     _alpm_bkt_pool_conf_t *bp_conf;
   2120 
   2121     vrf_id  = PVT_BKT_VRF(opvt_node);
   2122     src_bkt = &PVT_BKT_INFO(opvt_node);
   2123     dst_bkt = &PVT_BKT_INFO(npvt_node);
   2124     bp_conf = ACB_BKT_VRF_POOL(acb, vrf_id);
   2125 
   2126     for (i = 0; i < pfx_arr->pfx_cnt; i++) {
   2127         sb_cnt[ALPM_IDX_TO_BNK(acb, pfx_arr->pfx[i]->ent_idx)]++;
   2128     }
   2129 
   2130     for (i = 0; i < ALPM_BPB_MAX; i++) {
   2131         if (sb_cnt[i] == 0) {
   2132             continue;
   2133         }
   2134         rv = th3_mem_read(u, acb, BPC_BKT_TBL(bp_conf),
   2135                           ALPM_TAB_IDX_GET_BI_BNK(acb, src_bkt, i),
   2136                           srcbnke[i], FALSE);
   2137         ALPM_IER(rv);
   2138     }
   2139 
   2140     def_fmt = alpm_util_bkt_def_fmt_get(u, acb, vrf_id, PVT_BKT_IPT(opvt_node));
   2141     sal_memset(dstbnke, 0, sizeof(dstbnke));
   2142     for (i = 0; i < pfx_arr->pfx_cnt; i++) {
   2143         src_idx = pfx_arr->pfx[i]->ent_idx;
   2144         rv = alpm_bkt_ent_get_attempt(u, acb,
   2145                 ACB_BKT_VRF_POOL(acb, vrf_id),
   2146                 dst_bkt, def_fmt,
   2147                 pfx_arr->pfx[i]->key_len - PVT_KEY_LEN(npvt_node),
   2148                 &dst_idx, NULL, 0);
   2149         /* We should not see a FULL here */
   2150         ALPM_IER(rv);
   2151 
   2152         th3_alpm_ent_copy(u, vrf_id,  acb,
   2153                           srcbnke[ALPM_IDX_TO_BNK(acb, src_idx)],
   2154                           dstbnke[ALPM_IDX_TO_BNK(acb, dst_idx)],
   2155                           src_bkt, dst_bkt,
   2156                           PVT_KEY_LEN(opvt_node),
   2157                           PVT_KEY_LEN(npvt_node),
   2158                           src_idx, dst_idx);
   2159 
   2160         db_cnt[ALPM_IDX_TO_BNK(acb, dst_idx)]++;
   2161         pfx_arr->pfx[i]->ent_idx = dst_idx;
   2162         if (!ALPM_HIT_SKIP(u)) {
   2163             th3_alpm_ent_hit_move(u, vrf_id, acb, src_idx, dst_idx);
   2164         }
   2165     }
   2166 
   2167     for (i = 0; i < ALPM_BPB_MAX; i++) {
   2168         if (db_cnt[i] == 0) {
   2169             continue;
   2170         }
   2171 
   2172         bulk_idx[bulk_ent_cnt] = ALPM_TAB_IDX_GET_BI_BNK(acb, dst_bkt, i);
   2173         bulk_ent[bulk_ent_cnt] = dstbnke[i];
   2174         bulk_ent_cnt ++;
   2175     }
   2176 
   2177     rv = th3_mem_bulk_write(u, acb, npvt_node,
   2178             BPC_BKT_TBL(bp_conf),
   2179             bulk_idx, bulk_ent, bulk_ent_cnt);
   2180 
   2181     ALPM_IER(rv);
   2182 
   2183     /* TH3TBD: rollback@err */
   2184     return rv;
   2185 }
   2186 
   2187 int
   2188 th3_alpm_bkt_pfx_clean(int u, _alpm_cb_t *acb,
   2189                         _alpm_pvt_node_t *pvt_node,
   2190                         int count, uint32 *ent_idx)
   2191 {
   2192     int i, rv = BCM_E_NONE;
   2193     int vrf_id;
   2194     uint32 src_idx, ent_id;
   2195     /* Bulk write */
   2196     int     bulk_idx[ALPM_BPB_MAX];
   2197     uint32  *bulk_ent[ALPM_BPB_MAX];
   2198     int     bulk_ent_cnt = 0;
   2199 
   2200     soc_format_t bnk_fmt;
   2201 
   2202     uint16 srcbnk[ALPM_BPB_MAX] = {0};
   2203     uint32 srcbnke[ALPM_BPB_MAX][17];
   2204 
   2205     _alpm_bkt_pool_conf_t *bp_conf;
   2206 
   2207     vrf_id = PVT_BKT_VRF(pvt_node);
   2208     bp_conf = ACB_BKT_VRF_POOL(acb, vrf_id);
   2209 
   2210     for (i = 0; i < count; i++) {
   2211         srcbnk[ALPM_IDX_TO_BNK(acb, ent_idx[i])]++;
   2212     }
   2213 
   2214     for (i = 0; i < ALPM_BPB_MAX; i++) {
   2215         if (srcbnk[i] == 0) {
   2216             continue;
   2217         }
   2218         rv = th3_mem_read(u, acb, BPC_BKT_TBL(bp_conf),
   2219                 ALPM_TAB_IDX_GET_BI_BNK(acb, &PVT_BKT_INFO(pvt_node), i),
   2220                 srcbnke[i], FALSE);
   2221         ALPM_IER(rv);
   2222     }
   2223 
   2224     /* Clear corresponding entry from bank */
   2225     for (i = 0; i < count; i++) {
   2226         uint32 *vet_bmp;
   2227         uint32 tmpe[17] = {0};
   2228         int8 fmt_tp;
   2229         int bnk_idx;
   2230 
   2231         src_idx = ent_idx[i];
   2232         bnk_idx = ALPM_IDX_TO_BNK(acb, src_idx);
   2233         fmt_tp = th3_alpm_bnk_fmt_get(u, acb, &PVT_BKT_INFO(pvt_node), src_idx);
   2234         bnk_fmt = BPC_FMT_BNK(bp_conf, fmt_tp);
   2235         ent_id  = ALPM_IDX_TO_ENT(src_idx);
   2236         vet_bmp = &(PVT_BKT_INFO(pvt_node).vet_bmp[bnk_idx]);
   2237         *vet_bmp = (*vet_bmp) & ~(1 << ent_id);
   2238         if (*vet_bmp) {
   2239             (void)soc_format_field_set(u, bnk_fmt,
   2240                         srcbnke[bnk_idx],
   2241                         th3_alpm_ent_fld[ent_id], tmpe);
   2242         } else {
   2243             srcbnk[bnk_idx] = 0;
   2244         }
   2245     }
   2246 
   2247     for (i = 0; i < ALPM_BPB_MAX; i++) {
   2248         if (srcbnk[i] == 0) {
   2249             continue;
   2250         }
   2251 
   2252         bulk_idx[bulk_ent_cnt] =
   2253             ALPM_TAB_IDX_GET_BI_BNK(acb, &PVT_BKT_INFO(pvt_node), i);
   2254         bulk_ent[bulk_ent_cnt] = srcbnke[i];
   2255         bulk_ent_cnt ++;
   2256     }
   2257 
   2258     rv = th3_mem_bulk_write(u, acb, pvt_node,
   2259             BPC_BKT_TBL(bp_conf),
   2260             bulk_idx, bulk_ent, bulk_ent_cnt);
   2261 
   2262     ALPM_IER(rv);
   2263 
   2264     if (!ALPM_HIT_SKIP(u)) {
   2265         for (i = 0; i < count; i++) {
   2266             _alpm_tbl_t tbl = alpmTblInvalid;
   2267             src_idx = ent_idx[i];
   2268             tbl = ACB_BKT_TBL(acb, vrf_id);
   2269             th3_alpm_bkt_hit_write(u, vrf_id, acb, tbl, src_idx, 0);
   2270         }
   2271     }
   2272 
   2273     return rv;
   2274 }
   2275 
   2276 /* Only do defrag inside a bucket */
   2277 int
   2278 th3_alpm_bkt_pfx_shrink(int u, _alpm_cb_t *acb,
   2279                         _alpm_pvt_node_t *pvt_node,
   2280                         _alpm_bkt_pfx_arr_t *pfx_arr,
   2281                         int shrink_empty_only)
   2282 {
   2283     int tb, fb, tbnk, fbnk;
   2284     int rv = BCM_E_NONE;
   2285     int start, close, step;
   2286     int bnkpb = ACB_BNK_PER_BKT(acb, PVT_BKT_VRF(pvt_node));
   2287 
   2288     _alpm_bkt_info_t *bkt_info = NULL;
   2289 
   2290     bkt_info = &PVT_BKT_INFO(pvt_node);
   2291 
   2292 #if 0 /* TH3TBD ??? */
   2293     if (bkt_info->bkt_idx == 0) {
   2294         return rv;
   2295     }
   2296 #endif
   2297 
   2298     if (bkt_info->reverse == 0) {
   2299         start = BI_ROFS(bkt_info);
   2300         close = BI_ROFS(bkt_info) + bnkpb;
   2301         step  = 1;
   2302     } else {
   2303         start = BI_ROFS(bkt_info) + bnkpb - 1;
   2304         close = BI_ROFS(bkt_info) - 1;
   2305         step  = -1;
   2306     }
   2307 
   2308     for (tb = start; ABS(tb-close) > 0; tb += step) {
   2309         tbnk = tb % bnkpb;
   2310         /* Found a used tbnk */
   2311         if (!BI_BNK_IS_USED(bkt_info, tbnk)) {
   2312             continue;
   2313         }
   2314         for (fb = (close - step); ABS(fb-tb) > 0; fb -= step) {
   2315             fbnk = fb % bnkpb;
   2316             /* Bank fb empty */
   2317             if (!BI_BNK_IS_USED(bkt_info, fbnk) ||
   2318                 bkt_info->vet_bmp[fbnk] == 0) {
   2319                 continue;
   2320             }
   2321 
   2322             /* Bank tb empty, Bank fb occupied */
   2323             if (bkt_info->vet_bmp[tbnk] == 0) {
   2324                 rv = th3_alpm_bkt_bnk_shrink(u, acb, pvt_node, fbnk, tbnk,
   2325                                              pfx_arr);
   2326                 ALPM_IER(rv);
   2327             } else if (bkt_info->bnk_fmt[tbnk] >= bkt_info->bnk_fmt[fbnk]) {
   2328                 /* Bank tb & fb are same type and both occupied */
   2329                 if (!shrink_empty_only) {
   2330                     rv = th3_alpm_bkt_bnk_shrink(u, acb, pvt_node, fbnk,
   2331                                                  tbnk, pfx_arr);
   2332                     ALPM_IER(rv);
   2333                 }
   2334             }
   2335         }
   2336     }
   2337 
   2338     return rv;
   2339 }
   2340 
   2341 int
   2342 th3_alpm_bkt_bnk_copy(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node,
   2343                       _alpm_bkt_info_t *src_bkt, _alpm_bkt_info_t *dst_bkt,
   2344                       int src_idx, int dst_idx)
   2345 {
   2346     int rv = BCM_E_NONE;
   2347     uint32 ent[ALPM_ENT_WORDS_MAX] = {0};
   2348 
   2349     _alpm_tbl_t tbl = alpmTblInvalid;
   2350 
   2351     if (pvt_node != NULL) {
   2352         tbl = BPC_BKT_TBL(ACB_BKT_VRF_POOL(acb, PVT_BKT_VRF(pvt_node)));
   2353     }
   2354 
   2355     if (tbl != alpmTblInvalid) {
   2356         ALPM_IER(
   2357             th3_mem_read(u, acb, tbl, src_idx, ent, FALSE));
   2358         ALPM_IER(
   2359             th3_mem_write(u, acb, pvt_node, tbl, dst_idx, ent));
   2360 
   2361         if (!ALPM_HIT_SKIP(u)) {
   2362             th3_alpm_bnk_hit_move(u, PVT_BKT_VRF(pvt_node),
   2363                                   acb, src_idx, dst_idx);
   2364         }
   2365     }
   2366 
   2367     return rv;
   2368 }
   2369 
   2370 int
   2371 th3_alpm_bkt_bnk_clear(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node,
   2372                         int tab_idx)
   2373 {
   2374     int rv = BCM_E_NONE;
   2375     _alpm_tbl_t tbl = alpmTblInvalid;
   2376 
   2377     if (pvt_node != NULL) {
   2378         tbl = ACB_BKT_TBL(acb, PVT_BKT_VRF(pvt_node));
   2379         ALPM_IER(th3_mem_write(u, acb, pvt_node, tbl, tab_idx, NULL));
   2380 
   2381         if (!ALPM_HIT_SKIP(u)) {
   2382             th3_alpm_bnk_hit_clear(u, PVT_BKT_VRF(pvt_node), acb, tab_idx);
   2383         }
   2384     }
   2385 
   2386     return rv;
   2387 }
   2388 
   2389 /* TCAM related functions */
   2390 int
   2391 th3_tcam_table_sz(int u, int pkm)
   2392 {
   2393     int sz = 0;
   2394     soc_mem_t mem;
   2395     mem = alpm_tbl[ACB_TOP(u)->pvt_tbl[pkm]];
   2396 
   2397     if (mem != INVALIDm) {
   2398         sz = soc_mem_index_count(u, mem);
   2399 
   2400         if (SOC_URPF_STATUS_GET(u)) {
   2401             sz >>= 1;
   2402         }
   2403     }
   2404     return sz;
   2405 }
   2406 
   2407 /* TCAM Hw table cleanup (fast delete_all) */
   2408 int
   2409 th3_tcam_hw_cleanup(int u)
   2410 {
   2411     soc_mem_t mem;
   2412     _alpm_cb_t *acb = ACB_TOP(u);
   2413     int pkm, tbl_sz;
   2414     int rv = BCM_E_NONE;
   2415 
   2416     for (pkm = 0; pkm < ALPM_PKM_CNT; pkm++) {
   2417 
   2418         if (ALPM_TCAM_TBL_SKIP(u, pkm)) {
   2419             continue; /* skip duplicated or invalid TCAM table */
   2420         }
   2421 
   2422         mem = alpm_tbl[acb->pvt_tbl[pkm]];
   2423         tbl_sz = th3_tcam_table_sz(u, pkm);
   2424         if (tbl_sz) {
   2425             th3_alpm_hw_mem_clear(u, mem);
   2426         }
   2427     }
   2428 
   2429     return rv;
   2430 }
   2431 
   2432 /*
   2433  * x | y
   2434  * --------------------
   2435  * 0 | 0 : entry0_to_0
   2436  * 0 | 1 : entry0_to_1
   2437  * 1 | 0 : entry1_to_0
   2438  * 1 | 1 : entry1_to_1
   2439  * src and dst can be same
   2440  */
   2441 int
   2442 th3_tcam_entry_x_to_y(int u, int pkm, void *src, void *dst,
   2443                       int copy_hit, int x, int y)
   2444 {
   2445     int                 i;
   2446     uint32              val[SOC_MAX_MEM_FIELD_WORDS] = {0};
   2447     soc_mem_t           mem;
   2448     _alpm_cb_t    *acb = ACB_TOP(u);
   2449 
   2450 #define _FLD_CNT    6
   2451     soc_field_t fld[2][_FLD_CNT] =
   2452         {
   2453             {
   2454                 VALID0f,
   2455                 KEY0f,
   2456                 MASK0f,
   2457                 ASSOC_DATA0f,
   2458                 ALPM1_DATA0f,
   2459                 FIXED_DATA0f
   2460              },
   2461             {
   2462                 VALID1f,
   2463                 KEY1f,
   2464                 MASK1f,
   2465                 ASSOC_DATA1f,
   2466                 ALPM1_DATA1f,
   2467                 FIXED_DATA1f
   2468             }
   2469         };
   2470     soc_field_t hit[2] = {HIT0f, HIT1f};
   2471 
   2472     mem = alpm_tbl[acb->pvt_tbl[pkm]];
   2473     for (i = 0; i < _FLD_CNT; i++) {
   2474         soc_mem_field_get(u, mem, src, fld[x][i], val);
   2475         soc_mem_field_set(u, mem, dst, fld[y][i], val);
   2476     }
   2477 
   2478     if (copy_hit) {
   2479         soc_mem_field_get(u, mem, src, hit[x], val);
   2480         soc_mem_field_set(u, mem, dst, hit[y], val);
   2481     }
   2482 
   2483     return BCM_E_NONE;
   2484 }
   2485 
   2486 /*
   2487  * field mapping:
   2488  *
   2489  * defip_flags
   2490  *      BCM_L3_HIT          -> HIT0f
   2491  *      BCM_L3_RPE          -> ASSOC_DATA0  -> RPE
   2492  *      BCM_L3_MULTIPATH    -> ASSOC_DATA0  -> DEST_TYPE
   2493  *      BCM_L3_DST_DISCARD  -> ASSOC_DATA0  -> DST_DISCARD
   2494  *      BCM_L3_IP6          -> KEY0         -> KEY_MODE
   2495  *                          -> KEY0         -> KEY_TYPE
   2496  * defip_prio               -> ASSOC_DATA0  -> PRI
   2497  * defip_ecmp_index         -> ASSOC_DATA0  -> DESTINATION
   2498  * defip_lookup_class       -> ASSOC_DATA0  -> CLASS_ID
   2499  * defip_vrf
   2500  *      BCM_L3_VRF_GLOBAL   -> ALPM1_DATA   -> DIRECT_ROUTE
   2501  *                          -> FIXED_DATA0  -> SUB_DB_PRIORITY
   2502  *
   2503  *      BCM_L3_VRF_OVERRIDE -> ALPM1_DATA   -> DIRECT_ROUTE
   2504  *                          -> FIXED_DATA0  -> SUB_DB_PRIORITY
   2505  *
   2506  *      other               -> KEY0         -> VRF_ID
   2507  *                          -> MASK0        -> VRF_ID
   2508  *                          -> FIXED_DATA0  -> SUB_DB_PRIORITY
   2509  *
   2510  * defip_sub_len            -> MASK0        -> IP_ADDR
   2511  * defip_ip_addr            -> KEY0         -> IP_ADDR
   2512  * defip_ip6_addr           -> KEY0         -> IP_ADDR
   2513  *
   2514  * defip_flex_ctr_base_id   -> ASSOC_DATA0  -> FLEX_CTR_BASE_COUNTER_IDX
   2515  * defip_flex_ctr_mode      -> ASSOC_DATA0  -> FLEX_CTR_OFFSET_MODE
   2516  * defip_flex_ctr_pool      -> ASSOC_DATA0  -> FLEX_CTR_POOL_NUMBER
   2517  */
   2518 int
   2519 th3_tcam_entry_from_cfg(int u, int pkm, _bcm_defip_cfg_t *lpm_cfg, void *e, int x, uint32 write_flags)
   2520 {
   2521     int             i, b, cnt = 2;
   2522     uint32          key[4] = {0};
   2523     uint32          msk[4] = {0};
   2524     uint32          val;
   2525 
   2526     soc_mem_t       mem;
   2527     _alpm_cb_t      *acb = ACB_TOP(u);
   2528     _alpm_pvt_node_t *pvt_node;
   2529     _alpm_bkt_pool_conf_t *bp_conf;
   2530 
   2531     soc_field_t hit_fld[] = {HIT0f, HIT1f};
   2532     soc_field_t asd_fld[] = {ASSOC_DATA0f, ASSOC_DATA1f};
   2533     soc_field_t fix_fld[] = {FIXED_DATA0f, FIXED_DATA1f};
   2534     soc_field_t bkt_fld[] = {ALPM1_DATA0f, ALPM1_DATA1f};
   2535     soc_field_t vld_fld[] = {VALID0f, VALID1f};
   2536     soc_field_t key_fld[] = {KEY0f, KEY1f, KEY0_UPRf, KEY1_UPRf};
   2537     soc_field_t msk_fld[] = {MASK0f, MASK1f, MASK0_UPRf, MASK1_UPRf};
   2538 
   2539     th3_fmt_FIXED_DATA_t fmt_fd;
   2540     th3_fmt_ASSOC_DATA_FULL_t fmt_asf;
   2541     th3_fmt_L3_DEFIP_TCAM_KEY_t fmt_tk;
   2542     th3_fmt_ALPM1_DATA_t fmt_a1d;
   2543 
   2544     mem = alpm_tbl[acb->pvt_tbl[pkm]];
   2545     if (SOC_MEM_FIELD_VALID(u, mem, ASSOC_DATA0f)) {
   2546         if (pkm == ALPM_PKM_32B) {
   2547             hit_fld[!x] = hit_fld[!!x];
   2548             asd_fld[!x] = asd_fld[!!x];
   2549             fix_fld[!x] = fix_fld[!!x];
   2550             bkt_fld[!x] = bkt_fld[!!x];
   2551             vld_fld[!x] = vld_fld[!!x];
   2552             key_fld[!x] = key_fld[!!x];
   2553             msk_fld[!x] = msk_fld[!!x];
   2554             cnt = 1;
   2555         }
   2556     } else {
   2557         hit_fld[0] = LWR_HIT0f;
   2558         hit_fld[1] = LWR_HIT1f;
   2559         asd_fld[0] = LWR_ASSOC_DATA0f;
   2560         asd_fld[1] = LWR_ASSOC_DATA1f;
   2561         fix_fld[0] = LWR_FIXED_DATA0f;
   2562         fix_fld[1] = LWR_FIXED_DATA1f;
   2563         bkt_fld[0] = LWR_ALPM1_DATA0f;
   2564         bkt_fld[1] = LWR_ALPM1_DATA1f;
   2565         vld_fld[0] = LWR_VALID0f;
   2566         vld_fld[1] = LWR_VALID1f;
   2567         key_fld[0] = KEY0_LWRf;
   2568         key_fld[1] = KEY1_LWRf;
   2569         msk_fld[0] = MASK0_LWRf;
   2570         msk_fld[1] = MASK1_LWRf;
   2571     }
   2572 
   2573     for (i = 0; i < cnt; i++) {
   2574         if (write_flags & ALPM_PVT_UPDATE_PREFIX) {
   2575             soc_mem_field32_set(u, mem, e, vld_fld[i], 1);
   2576             if (lpm_cfg->defip_flags & BCM_L3_HIT) {
   2577                 soc_mem_field32_set(u, mem, e, hit_fld[i], 1);
   2578             }
   2579         }
   2580 
   2581         /* ASSOC_DATAf format */
   2582         if (write_flags & ALPM_PVT_UPDATE_ASSOC_DATA) {
   2583             sal_memset(&fmt_asf, 0, sizeof(fmt_asf));
   2584             fmt_asf.RPE = lpm_cfg->defip_flags & BCM_L3_RPE ? 1 : 0;
   2585             fmt_asf.DEST_TYPE = lpm_cfg->defip_flags & BCM_L3_MULTIPATH ? 1 : 0;
   2586             fmt_asf.DESTINATION = lpm_cfg->defip_ecmp_index;
   2587             fmt_asf.DST_DISCARD = lpm_cfg->defip_flags & BCM_L3_DST_DISCARD ? 1 : 0;
   2588             fmt_asf.PRI = lpm_cfg->defip_prio;
   2589             fmt_asf.CLASS_ID = lpm_cfg->defip_lookup_class;
   2590             fmt_asf.FLEX_CTR_BASE_COUNTER_IDX = lpm_cfg->defip_flex_ctr_base_id;
   2591             fmt_asf.FLEX_CTR_OFFSET_MODE = lpm_cfg->defip_flex_ctr_mode;
   2592             fmt_asf.FLEX_CTR_POOL_NUMBER = lpm_cfg->defip_flex_ctr_pool;
   2593             soc_mem_field_set(u, mem, e, asd_fld[i], (uint32 *)&fmt_asf);
   2594         }
   2595 
   2596         /* FIXED_DATAf format */
   2597         if (write_flags & ALPM_PVT_UPDATE_PREFIX) {
   2598             sal_memset(&fmt_fd, 0, sizeof(fmt_fd));
   2599             switch (lpm_cfg->defip_vrf) {
   2600                 case BCM_L3_VRF_GLOBAL:
   2601                     val = 2;
   2602                     break;
   2603                 case BCM_L3_VRF_OVERRIDE:
   2604                     val = 0;
   2605                     break;
   2606                 default:
   2607                     val = 1;
   2608                     break;
   2609             }
   2610             fmt_fd.SUB_DB_PRIORITY = val;
   2611             soc_mem_field_set(u, mem, e, fix_fld[i], (uint32 *)&fmt_fd);
   2612         }
   2613 
   2614         /* ALPM1_DATAf format */
   2615         if (write_flags & ALPM_PVT_UPDATE_ALPM_DATA) {
   2616             sal_memset(&fmt_a1d, 0, sizeof(fmt_a1d));
   2617 
   2618             fmt_a1d.DIRECT_ROUTE = ALPM_LPM_DIRECT_RTE(u, lpm_cfg);
   2619             if (ALPM_TCAM_ZONED(u) && lpm_cfg->default_miss == 1) {
   2620                 /* TH3TBD, Parallel & Mixed ALPM need to set DEFAULT_MISS to 1
   2621                  * if assoc_data is NOT set, in case of missing default */
   2622                 fmt_a1d.DEFAULT_MISS = 1;
   2623             }
   2624             pvt_node = (_alpm_pvt_node_t *)lpm_cfg->pvt_node;
   2625             if (pvt_node != NULL) {
   2626                 int offset = 0;
   2627                 _alpm_tbl_t tbl;
   2628                 _alpm_bkt_info_t *bkt_info = &PVT_BKT_INFO(pvt_node);
   2629 
   2630                 bp_conf = ACB_BKT_VRF_POOL(acb, PVT_BKT_VRF(pvt_node));
   2631                 tbl = BPC_BKT_TBL(bp_conf);
   2632                 switch (tbl) {
   2633                     case alpmTblBktPmodeGblL2:
   2634                     case alpmTblBktPmodeGblL3:
   2635                         offset = ACB_BNK_PER_BKT(acb, 1);
   2636                         break;
   2637                     default:
   2638                         break;
   2639                 }
   2640                 fmt_a1d.KSHIFT = PVT_KEY_LEN(pvt_node);
   2641                 fmt_a1d.ROFS = PVT_ROFS(pvt_node) + offset;
   2642                 fmt_a1d.BKT_PTR = PVT_BKT_IDX(pvt_node);
   2643                 for (b = 0; b < BPC_BNK_PER_BKT(bp_conf); b++) {
   2644                     soc_field_t bnk_fld;
   2645                      if (!BI_BNK_IS_USED(bkt_info, b)) {
   2646                         continue;
   2647                      }
   2648                      bnk_fld = th3_alpm_bnk_fld[b+offset];
   2649                      switch (bnk_fld) {
   2650                         case FMT0f:
   2651                             fmt_a1d.FMT0 = bkt_info->bnk_fmt[b];
   2652                             break;
   2653                         case FMT1f:
   2654                             fmt_a1d.FMT1 = bkt_info->bnk_fmt[b];
   2655                             break;
   2656                         case FMT2f:
   2657                             fmt_a1d.FMT2_0_1 = bkt_info->bnk_fmt[b] & 0x3;
   2658                             fmt_a1d.FMT2_2_3 = (bkt_info->bnk_fmt[b] >> 2) & 0x3;
   2659                             break;
   2660                         case FMT3f:
   2661                             fmt_a1d.FMT3 = bkt_info->bnk_fmt[b];
   2662                             break;
   2663                         case FMT4f:
   2664                             fmt_a1d.FMT4 = bkt_info->bnk_fmt[b];
   2665                             break;
   2666                         default:
   2667                             break;
   2668                      }
   2669                 }
   2670             }
   2671             soc_mem_field_set(u, mem, e, bkt_fld[i], (uint32 *)&fmt_a1d);
   2672         } /* if (write_flags & ALPM_PVT_UPDATE_ASSOC_DATA) */
   2673     }
   2674 
   2675     if (hit_fld[0] == LWR_HIT0f) {
   2676         soc_mem_field32_set(u, mem, e, UPR_VALIDf, 3);
   2677     }
   2678 
   2679     if (write_flags & ALPM_PVT_UPDATE_PREFIX) {
   2680         /* Program KEY & MASK
   2681          *
   2682          *           key[4] = {key[0], key[1], key[2], key[3]}
   2683          * ipv4:     key[4] =
   2684          *      {IP_ADDR0f, 0, 0, 0}
   2685          * ipv6-64:  key[4] =
   2686          *      {IP_ADDR0f, IP_ADDR1f, 0, 0}
   2687          * ipv6-128: key[4] =
   2688          *      {IP_ADDR0_LWRf, IP_ADDR1_LWRf, IP_ADDR0_UPRf, IP_ADDR1_UPRf}
   2689          */
   2690         alpm_util_cfg_to_key(u, ALPM_PKM2IPT(pkm), lpm_cfg, key);
   2691         alpm_util_cfg_to_msk(u, ALPM_PKM2IPT(pkm), lpm_cfg, msk);
   2692         if (hit_fld[0] == LWR_HIT0f) {
   2693             cnt = 4;
   2694         }
   2695 
   2696         switch (pkm) {
   2697             case ALPM_PKM_32B:
   2698                 val = 0;
   2699                 break;
   2700             case ALPM_PKM_64B:
   2701                 key[1] = key[3];
   2702                 key[0] = key[2];
   2703                 msk[1] = msk[3];
   2704                 msk[0] = msk[2];
   2705                 val = 1;
   2706                 break;
   2707             case ALPM_PKM_128:
   2708                 val = 3;
   2709                 break;
   2710             default:
   2711                 val = 0;
   2712                 break;
   2713         }
   2714 
   2715         for (i = 0; i < cnt; i++) {
   2716             /* KEY */
   2717             sal_memset(&fmt_tk, 0, sizeof(fmt_tk));
   2718             fmt_tk.KEY_MODE = val;
   2719             fmt_tk.KEY_TYPE = (lpm_cfg->defip_flags & BCM_L3_IP6) ? 1 : 0;
   2720             fmt_tk.IP_ADDR_0_28 = key[i] & 0x1fffffff;
   2721             fmt_tk.IP_ADDR_29_31 = (key[i] >> 29) & 0x7;
   2722             fmt_tk.VRF_ID = lpm_cfg->defip_vrf >= 0 ? lpm_cfg->defip_vrf : 0;
   2723             soc_mem_field_set(u, mem, e, key_fld[i], (uint32 *)&fmt_tk);
   2724 
   2725             /* MASK */
   2726             sal_memset(&fmt_tk, 0, sizeof(fmt_tk));
   2727             fmt_tk.KEY_MODE = 0x3;
   2728             fmt_tk.KEY_TYPE = 0x1;
   2729             fmt_tk.IP_ADDR_0_28 = msk[i] & 0x1fffffff;
   2730             fmt_tk.IP_ADDR_29_31 = (msk[i] >> 29) & 0x7;
   2731             fmt_tk.VRF_ID = lpm_cfg->defip_vrf >= 0 ? 0xfff : 0;
   2732             soc_mem_field_set(u, mem, e, msk_fld[i], (uint32 *)&fmt_tk);
   2733         }
   2734     }
   2735 
   2736     return BCM_E_NONE;
   2737 }
   2738 
   2739 int
   2740 th3_tcam_entry_to_cfg(int u, int pkm, void *e, int x,
   2741                       _bcm_defip_cfg_t *lpm_cfg)
   2742 {
   2743     uint32              val;
   2744     soc_mem_t           mem;
   2745     th3_fmt_ASSOC_DATA_FULL_t fmte;
   2746     _alpm_cb_t          *acb = ACB_TOP(u);
   2747 
   2748     soc_field_t hit_fld[] = {HIT0f, HIT1f};
   2749     soc_field_t asd_fld[] = {ASSOC_DATA0f, ASSOC_DATA1f};
   2750     soc_field_t fix_fld[] = {FIXED_DATA0f, FIXED_DATA1f};
   2751     soc_field_t bkt_fld[] = {ALPM1_DATA0f, ALPM1_DATA1f};
   2752 
   2753     mem = alpm_tbl[acb->pvt_tbl[pkm]];
   2754     if (SOC_MEM_FIELD_VALID(u, mem, ASSOC_DATA0f)) {
   2755         if (pkm == ALPM_PKM_32B) {
   2756             hit_fld[!x] = hit_fld[!!x];
   2757             asd_fld[!x] = asd_fld[!!x];
   2758             fix_fld[!x] = fix_fld[!!x];
   2759             bkt_fld[!x] = bkt_fld[!!x];
   2760         }
   2761     } else {
   2762         hit_fld[0] = LWR_HIT0f;
   2763         asd_fld[0] = LWR_ASSOC_DATA0f;
   2764         fix_fld[0] = LWR_FIXED_DATA0f;
   2765         bkt_fld[0] = LWR_ALPM1_DATA0f;
   2766     }
   2767 
   2768 #define _LPM_DEFIP_FLAGS_SET(val, flag)     \
   2769     do {                                    \
   2770         if (val) {                          \
   2771             lpm_cfg->defip_flags |= flag;   \
   2772         } else {                            \
   2773             lpm_cfg->defip_flags &= ~flag;  \
   2774         }                                   \
   2775     } while (0)
   2776 
   2777     val = soc_mem_field32_get(u, mem, e, hit_fld[0]);
   2778     _LPM_DEFIP_FLAGS_SET(val, BCM_L3_HIT);
   2779 
   2780     /* ASSOC_DATAf format */
   2781     soc_mem_field_get(u, mem, e, asd_fld[0], (uint32 *)&fmte);
   2782     val = fmte.RPE;
   2783     _LPM_DEFIP_FLAGS_SET(val, BCM_L3_RPE);
   2784 
   2785     val = fmte.DEST_TYPE;
   2786     _LPM_DEFIP_FLAGS_SET(val, BCM_L3_MULTIPATH);
   2787     if (val) {
   2788         lpm_cfg->defip_ecmp = 1;
   2789     } else {
   2790         lpm_cfg->defip_ecmp = 0;
   2791         lpm_cfg->defip_ecmp_count = 0;
   2792     }
   2793 
   2794     lpm_cfg->defip_ecmp_index = fmte.DESTINATION;
   2795 
   2796     val = fmte.DST_DISCARD;
   2797     _LPM_DEFIP_FLAGS_SET(val, BCM_L3_DST_DISCARD);
   2798 
   2799     lpm_cfg->defip_prio = fmte.PRI;
   2800     lpm_cfg->defip_lookup_class = fmte.CLASS_ID;
   2801     lpm_cfg->defip_flex_ctr_base_id = fmte.FLEX_CTR_BASE_COUNTER_IDX;
   2802     lpm_cfg->defip_flex_ctr_mode = fmte.FLEX_CTR_OFFSET_MODE;
   2803     lpm_cfg->defip_flex_ctr_pool = fmte.FLEX_CTR_POOL_NUMBER;
   2804 
   2805     /* No need to parse the rest field because there are already in the
   2806      * lpm_cfg, part of key */
   2807 
   2808     return BCM_E_NONE;
   2809 }
   2810 
   2811 int
   2812 th3_tcam_entry_valid(int u, int pkm, void *e, int sub_idx)
   2813 {
   2814     int vld_val;
   2815     soc_mem_t mem;
   2816     soc_field_t vld_fld = VALIDf;
   2817     _alpm_cb_t *acb = ACB_TOP(u);
   2818 
   2819     mem = alpm_tbl[acb->pvt_tbl[pkm]];
   2820     if (SOC_MEM_FIELD_VALID(u, mem, VALIDf)) {
   2821         vld_fld = VALIDf;
   2822     } else {
   2823         vld_fld = LWR_VALIDf;
   2824     }
   2825 
   2826     vld_val = soc_mem_field32_get(u, mem, e, vld_fld);
   2827 
   2828     return vld_val & (1 << sub_idx) ? 1 : 0;
   2829 }
   2830 
   2831 int
   2832 th3_tcam_entry_valid_set(int u, int pkm, void *e, int sub_idx, int val)
   2833 {
   2834     soc_mem_t mem;
   2835     soc_field_t vld_fld;
   2836     _alpm_cb_t *acb = ACB_TOP(u);
   2837 
   2838     mem = alpm_tbl[acb->pvt_tbl[pkm]];
   2839     switch (pkm) {
   2840         case ALPM_PKM_32B:
   2841             vld_fld = sub_idx ? VALID1f : VALID0f;
   2842             soc_mem_field32_set(u, mem, e, vld_fld, val ? 1 : 0);
   2843             break;
   2844         case ALPM_PKM_64B:
   2845             soc_mem_field32_set(u, mem, e, VALIDf, val ? 3 : 0);
   2846             break;
   2847         case ALPM_PKM_128:
   2848             soc_mem_field32_set(u, mem, e, LWR_VALIDf, val ? 3 : 0);
   2849             soc_mem_field32_set(u, mem, e, UPR_VALIDf, val ? 3 : 0);
   2850             break;
   2851         default:
   2852             break;
   2853     }
   2854 
   2855     return BCM_E_NONE;
   2856 }
   2857 
   2858 static void
   2859 th3_tcam_key_fields_get(int u, soc_mem_t mem, void *e, soc_field_t fmt,
   2860                         int fld_cnt, soc_field_t *flds, uint32 *vals)
   2861 {
   2862     int         i;
   2863     th3_fmt_L3_DEFIP_TCAM_KEY_t fmt_tk;
   2864 
   2865     for (i = 0; i < fld_cnt; i++) {
   2866         soc_mem_field_get(u, mem, e, fmt, (uint32 *)&fmt_tk);
   2867         switch(flds[i]) {
   2868             case KEY_MODEf:
   2869                 vals[i] = fmt_tk.KEY_MODE;
   2870                 break;
   2871             case KEY_TYPEf:
   2872                 vals[i] = fmt_tk.KEY_TYPE;
   2873                 break;
   2874             case VRF_IDf:
   2875                 vals[i] = fmt_tk.VRF_ID;
   2876                 break;
   2877             case IP_ADDRf:
   2878                 vals[i] = (fmt_tk.IP_ADDR_29_31 << 29) | fmt_tk.IP_ADDR_0_28;
   2879                 break;
   2880             default:
   2881                 break;
   2882         }
   2883     }
   2884 
   2885     return ;
   2886 }
   2887 
   2888 static int
   2889 th3_tcam_entry_to_mask_key(int u, int pkm, void *e, int sub_idx,
   2890                             uint32 *key, int is_mask)
   2891 {
   2892     int         i, fld_cnt;
   2893     soc_mem_t   mem;
   2894     soc_field_t _msk_fld[] = {MASK0f, MASK1f};
   2895     soc_field_t _key_fld[] = {KEY0f, KEY1f};
   2896     soc_field_t _msk_fld_p[] = {MASK0_LWRf, MASK1_LWRf, MASK0_UPRf, MASK1_UPRf};
   2897     soc_field_t _key_fld_p[] = {KEY0_LWRf, KEY1_LWRf, KEY0_UPRf, KEY1_UPRf};
   2898     soc_field_t key_fld = IP_ADDRf;
   2899 
   2900     soc_field_t *_fld, *_fld_p, *fmt;
   2901     _alpm_cb_t *acb = ACB_TOP(u);
   2902 
   2903     if (is_mask) {
   2904         _fld = _msk_fld;
   2905         _fld_p = _msk_fld_p;
   2906     } else {
   2907         _fld = _key_fld;
   2908         _fld_p = _key_fld_p;
   2909     }
   2910 
   2911     mem = alpm_tbl[acb->pvt_tbl[pkm]];
   2912     if (SOC_MEM_FIELD_VALID(u, mem, ASSOC_DATA0f)) {
   2913         if (pkm == ALPM_PKM_32B) {
   2914             fld_cnt = 1;
   2915             _fld[0] = _fld[sub_idx];
   2916         } else {
   2917             fld_cnt = 2;
   2918         }
   2919         fmt = _fld;
   2920     } else {
   2921         fld_cnt = 4;
   2922         fmt = _fld_p;
   2923     }
   2924 
   2925     sal_memset(key, 0, 4 * sizeof(uint32));
   2926     for (i = 0; i < fld_cnt; i++) {
   2927         th3_tcam_key_fields_get(u, mem, e, fmt[i], 1, &key_fld, &key[i]);
   2928     }
   2929 
   2930     if (pkm == ALPM_PKM_64B) {
   2931         key[3] = key[1];
   2932         key[2] = key[0];
   2933         key[1] = key[0] = 0;
   2934     }
   2935 
   2936     return BCM_E_NONE;
   2937 
   2938 }
   2939 
   2940 /*
   2941  *           key[4] = {key[0], key[1], key[2], key[3]}
   2942  * ipv4:     key[4] =
   2943  *               {IP_ADDR0f, 0, 0, 0}
   2944  * ipv6-64:  key[4] =
   2945  *               {0, 0, IP_ADDR0f, IP_ADDR1f, }
   2946  * ipv6-128: key[4] =
   2947  *               {IP_ADDR0_LWRf, IP_ADDR1_LWRf, IP_ADDR0_UPRf, IP_ADDR1_UPRf}
   2948  */
   2949 int
   2950 th3_tcam_entry_to_key(int u, int pkm, void *e, int sub_idx, uint32 *key)
   2951 {
   2952     return th3_tcam_entry_to_mask_key(u, pkm, e, sub_idx, key, FALSE);
   2953 }
   2954 
   2955 int
   2956 th3_tcam_entry_vrf_id_get(int u, int pkm, void *e, int sub_idx, int *vrf_id)
   2957 {
   2958     uint32      fld_val;
   2959     soc_mem_t   mem;
   2960     soc_field_t _glb_fld[]      = {FIXED_DATA0f, FIXED_DATA1f};
   2961     soc_field_t _glb_fld_p[]    = {LWR_FIXED_DATA0f, LWR_FIXED_DATA1f};
   2962     soc_field_t _vrf_fld[]      = {KEY0f, KEY1f};
   2963     soc_field_t _vrf_fld_p[]    = {KEY0_LWRf, KEY1_LWRf};
   2964     soc_field_t *glb_fmt, *vrf_fmt;
   2965     soc_field_t key_fld = VRF_IDf;
   2966     _alpm_cb_t *acb = ACB_TOP(u);
   2967 
   2968     th3_fmt_FIXED_DATA_t fmt_fd;
   2969 
   2970     mem = alpm_tbl[acb->pvt_tbl[pkm]];
   2971     if (SOC_MEM_FIELD_VALID(u, mem, ASSOC_DATA0f)) {
   2972         if (pkm == ALPM_PKM_32B) {
   2973             _glb_fld[0] = _glb_fld[sub_idx];
   2974             _vrf_fld[0] = _vrf_fld[sub_idx];
   2975         }
   2976         glb_fmt = _glb_fld;
   2977         vrf_fmt = _vrf_fld;
   2978     } else {
   2979         glb_fmt = _glb_fld_p;
   2980         vrf_fmt = _vrf_fld_p;
   2981     }
   2982 
   2983     /* To distinguish Global/Private route */
   2984     soc_mem_field_get(u, mem, e, glb_fmt[0], (uint32 *)&fmt_fd);
   2985     fld_val = fmt_fd.SUB_DB_PRIORITY;
   2986     if (fld_val == 0) {
   2987         /* Global High */
   2988         *vrf_id = ALPM_VRF_ID_GHI(u);
   2989     } else if (fld_val == 2) {
   2990         /* Global Low */
   2991         *vrf_id = ALPM_VRF_ID_GLO(u);
   2992     } else {
   2993         /* Private routes */
   2994         th3_tcam_key_fields_get(u, mem, e, vrf_fmt[0], 1, &key_fld,
   2995                                 (uint32 *)vrf_id);
   2996     }
   2997 
   2998 
   2999     return BCM_E_NONE;
   3000 }
   3001 
   3002 int
   3003 th3_tcam_entry_pfx_len_get(int u, int pkm, void *e, int sub_idx, int *pfx_len)
   3004 {
   3005     int         i, rv = BCM_E_NONE;
   3006     uint32      mask[4];
   3007 
   3008     /* Assuming each MASK field is correct,
   3009      * Not my duty to validate MASK here */
   3010     rv = th3_tcam_entry_to_mask_key(u, pkm, e, sub_idx, mask, TRUE);
   3011     *pfx_len = 0;
   3012     for (i = 0; i < 4; i++) {
   3013         *pfx_len += _shr_popcount(mask[i]);
   3014     }
   3015 
   3016     return rv;
   3017 }
   3018 
   3019 int
   3020 th3_tcam_entry_mode_get_by_mem(int u, soc_mem_t mem, void *e, int *step_size,
   3021                                int *pkm, int *ipv6, int *key_mode, int sub_idx)
   3022 {
   3023     soc_field_t _key_fld[] = {KEY0f, KEY1f};
   3024     soc_field_t key_fld = KEY0f, vld_fld = VALIDf;
   3025     int valid, v6, km;
   3026 
   3027     th3_fmt_L3_DEFIP_TCAM_KEY_t fmt_tk;
   3028 
   3029     if (SOC_MEM_FIELD_VALID(u, mem, VALIDf)) {
   3030         key_fld = _key_fld[sub_idx];
   3031         vld_fld = VALIDf;
   3032         if (step_size) {
   3033             *step_size = 1; /* default step_size for un pair TCAM */
   3034         }
   3035     } else {
   3036         key_fld = KEY0_LWRf;
   3037         vld_fld = LWR_VALIDf;
   3038         if (step_size) {
   3039             *step_size = 2; /* default step_size for pair TCAM*/
   3040         }
   3041     }
   3042 
   3043     valid = soc_mem_field32_get(u, mem, e, vld_fld);
   3044     valid &=  (1 << sub_idx);
   3045 
   3046     if (!valid) { /* invalid entry */
   3047         return BCM_E_NOT_FOUND;
   3048     }
   3049 
   3050     soc_mem_field_get(u, mem, e, key_fld, (uint32 *)&fmt_tk);
   3051     km = fmt_tk.KEY_MODE;
   3052     if (key_mode) {
   3053         *key_mode = km;
   3054     }
   3055     v6 = fmt_tk.KEY_TYPE;
   3056     if (ipv6) {
   3057         *ipv6 = v6;
   3058     }
   3059 
   3060     /* TH3TBD */
   3061     if (pkm) {
   3062         *pkm = (key_fld == KEY0_LWRf) ? ALPM_PKM_128 :
   3063                                     v6 ? ALPM_PKM_64B : ALPM_PKM_32B;
   3064     }
   3065 
   3066     /* Wrong key_mode or key_type */
   3067     if ((key_fld != KEY0_LWRf && (km > 1)) ||
   3068         (key_fld == KEY0_LWRf && (km != 3)) ||
   3069         (key_fld == KEY0_LWRf && (v6 == 0))) {
   3070         return BCM_E_INTERNAL;
   3071     }
   3072 
   3073    /* step_size 2 only if full-wide in un pair TCAM */
   3074    if (step_size) {
   3075        if (key_fld != KEY0_LWRf && (km == 1)) {
   3076            *step_size = 2;
   3077        }
   3078    }
   3079    return BCM_E_NONE;
   3080 }
   3081 
   3082 /*
   3083  * Function:
   3084  *      th3_tcam_entry_mode_get
   3085  * Purpose:
   3086  *      Get TCAM valid entry KEY mode and type.
   3087  * Parameters:
   3088  *      u          - (In)Device unit
   3089  *      pk         - (In)Input TCAM packing mode table view
   3090  *      e          - (In)TCAM lpm memory entry
   3091  *      step_size  - (Out)Key mode step-size (un pair: 1 or 2, pair: 2)
   3092  *      p km       - (Out)Detected packing mode
   3093  *      ipv6       - (Out)Key Type (0:IPv4, 1:IPv6)
   3094  *      key_mode   - (Out)Key Mode (0:Half, 1:Full, 3:Double)
   3095  *      sub_idx    - (In)TCAM sub_idx (0, 1) for half-wide entries in unpair
   3096  *                       TCAM. Pair TCAM has only one sub_idx=0.
   3097  * Notes:
   3098  *      The for-loop for sub_idx is using always as below:
   3099  *        for (sub_idx = 0; sub_idx < ALPM_TCAM_SUBCNT; sub_idx += step_size)
   3100  *      where
   3101  *        ALPM_TCAM_SUBCNT is defined as 2, and
   3102  *        step_size is variable, depending on the actual TCAM entry reading.
   3103  *
   3104  * Returns:
   3105  *      BCM_E_XXX
   3106  */
   3107 int
   3108 th3_tcam_entry_mode_get(int u, int pk, void *e, int *step_size,
   3109                         int *pkm, int *ipv6, int *key_mode, int sub_idx)
   3110 {
   3111     _alpm_cb_t *acb = ACB_TOP(u);
   3112     soc_mem_t mem = alpm_tbl[acb->pvt_tbl[pk]];
   3113     return th3_tcam_entry_mode_get_by_mem(u, mem, e, step_size, pkm,
   3114                                           ipv6, key_mode, sub_idx);
   3115 }
   3116 
   3117 /* Get ASSOC_DATA from a TCAM entry */
   3118 int
   3119 th3_tcam_entry_adata_get(int u, int pkm, void *e, int sub_idx,
   3120                           _alpm_bkt_adata_t *adata)
   3121 {
   3122     int rv = BCM_E_NONE;
   3123     soc_field_t fldv;
   3124     _alpm_cb_t *acb = ACB_TOP(u);
   3125     soc_mem_t mem = alpm_tbl[acb->pvt_tbl[pkm]];
   3126     th3_fmt_ASSOC_DATA_FULL_t fmt_adf;
   3127 
   3128     if (SOC_MEM_FIELD_VALID(u, mem, ASSOC_DATA0f)) {
   3129         fldv = (sub_idx == 0 ? ASSOC_DATA0f : ASSOC_DATA1f);
   3130     } else {
   3131         fldv = (sub_idx == 0 ? LWR_ASSOC_DATA0f : LWR_ASSOC_DATA1f);
   3132     }
   3133     soc_mem_field_get(u, mem, e, fldv, (uint32 *)&fmt_adf);
   3134 
   3135     adata->defip_flags = fmt_adf.DEST_TYPE ? BCM_L3_MULTIPATH : 0;
   3136     adata->defip_ecmp_index = fmt_adf.DESTINATION;
   3137     adata->defip_flags |= fmt_adf.RPE ? BCM_L3_RPE : 0;
   3138     adata->defip_flags |= fmt_adf.DST_DISCARD ? BCM_L3_DST_DISCARD : 0;
   3139     adata->defip_prio = fmt_adf.PRI;
   3140     adata->defip_lookup_class = fmt_adf.CLASS_ID;
   3141     adata->defip_flex_ctr_base_id = fmt_adf.FLEX_CTR_BASE_COUNTER_IDX;
   3142     adata->defip_flex_ctr_mode = fmt_adf.FLEX_CTR_OFFSET_MODE;
   3143     adata->defip_flex_ctr_pool = fmt_adf.FLEX_CTR_POOL_NUMBER;
   3144 
   3145     return rv;
   3146 }
   3147 
   3148 /* Get ALPM_DATA entry from a TCAM entry */
   3149 int
   3150 th3_tcam_entry_bdata_get(int u, int pkm, void *e, int sub_idx, void *fent)
   3151 {
   3152     int rv = BCM_E_NONE;
   3153     soc_field_t fldv;
   3154     _alpm_cb_t *acb = ACB_TOP(u);
   3155     soc_mem_t mem = alpm_tbl[acb->pvt_tbl[pkm]];
   3156 
   3157     if (SOC_MEM_FIELD_VALID(u, mem, ALPM1_DATA0f)) {
   3158         fldv = (sub_idx == 0 ? ALPM1_DATA0f : ALPM1_DATA1f);
   3159     } else {
   3160         fldv = (sub_idx == 0 ? LWR_ALPM1_DATA0f : LWR_ALPM1_DATA1f);
   3161     }
   3162     soc_mem_field_get(u, mem, e, fldv, fent);
   3163     return rv;
   3164 }
   3165 
   3166 /***************** Bucket entry (Bank) starts from here *****************/
   3167 int
   3168 th3_alpm_ent_ent_get(int u, int vrf_id, _alpm_cb_t *acb, void *e, uint32 fmt,
   3169                      int eid, void *ftmp)
   3170 {
   3171     int rv = BCM_E_NONE;
   3172 
   3173     /* get bucket level bank format entry */
   3174     soc_format_field_get(u, ACB_FMT_BNK(acb, vrf_id, fmt), e,
   3175                          th3_alpm_ent_fld[eid], ftmp);
   3176     return rv;
   3177 }
   3178 
   3179 /* Get ALPM_Data bucket info (logic table based):
   3180    bkt_ptr, rofs, kshift, def_miss and bnkfmt[] */
   3181 static void
   3182 th3_alpm_ent_binfo_get(int u, int vrf_id, _alpm_cb_t *acb, void *e,
   3183                        _alpm_ent_info_t *info)
   3184 {
   3185     int bnk, offset = 0;
   3186     th3_fmt_ALPM1_DATA_t *fmt_a1d = NULL;
   3187     th3_fmt_ALPM2_DATA_t *fmt_a2d = NULL;
   3188 
   3189     uint8  bnk_fmt[ALPM_BPB_MAX] = {0};
   3190     uint16 bkt_idx;
   3191     int    kshift;
   3192     int    default_miss;
   3193     uint8  rofs;
   3194 
   3195     if (ACB_HAS_TCAM(acb)) {
   3196         fmt_a1d = e;
   3197         bkt_idx = fmt_a1d->BKT_PTR;
   3198         kshift  = fmt_a1d->KSHIFT;
   3199         default_miss = fmt_a1d->DEFAULT_MISS;
   3200         rofs    = fmt_a1d->ROFS;
   3201         bnk_fmt[0] = fmt_a1d->FMT0;
   3202         bnk_fmt[1] = fmt_a1d->FMT1;
   3203         bnk_fmt[2] = (fmt_a1d->FMT2_2_3 << 2) | fmt_a1d->FMT2_0_1;
   3204         bnk_fmt[3] = fmt_a1d->FMT3;
   3205         bnk_fmt[4] = fmt_a1d->FMT4;
   3206     } else {
   3207         fmt_a2d = e;
   3208         bkt_idx = fmt_a2d->BKT_PTR;
   3209         kshift  = fmt_a2d->KSHIFT;
   3210         default_miss = fmt_a2d->DEFAULT_MISS;
   3211         rofs    = fmt_a2d->ROFS;
   3212         bnk_fmt[0] = fmt_a2d->FMT0;
   3213         bnk_fmt[1] = fmt_a2d->FMT1;
   3214         bnk_fmt[2] = fmt_a2d->FMT2;
   3215         bnk_fmt[3] = fmt_a2d->FMT3;
   3216         bnk_fmt[4] = fmt_a2d->FMT4;
   3217         bnk_fmt[5] = fmt_a2d->FMT5;
   3218         bnk_fmt[6] = fmt_a2d->FMT6;
   3219         bnk_fmt[7] = fmt_a2d->FMT7;
   3220     }
   3221 
   3222     info->bkt_info.bkt_idx = bkt_idx;
   3223     info->kshift = kshift;
   3224     info->default_miss = default_miss;
   3225 
   3226     switch (ACB_BKT_TBL(acb, vrf_id)) {
   3227         case alpmTblBktPmodeGblL2:
   3228         case alpmTblBktPmodeGblL3:
   3229             offset = ACB_BNK_PER_BKT(acb, 1);
   3230             break;
   3231         default:
   3232             break;
   3233     }
   3234 
   3235     if (ACB_HLF_BNK_MD(acb) && ALPM_HLF_BNKS(u)) {
   3236         offset = 4;
   3237     }
   3238 
   3239     info->bkt_info.rofs = rofs - offset;
   3240     for (bnk = 0; bnk < ACB_BNK_PER_BKT(acb, vrf_id); bnk++) {
   3241         soc_field_t bnk_fld;
   3242         bnk_fld = th3_alpm_bnk_fld[bnk+offset];
   3243         switch (bnk_fld) {
   3244             case FMT0f:
   3245                 info->bkt_info.bnk_fmt[bnk] = bnk_fmt[0];
   3246                 break;
   3247             case FMT1f:
   3248                 info->bkt_info.bnk_fmt[bnk] = bnk_fmt[1];
   3249                 break;
   3250             case FMT2f:
   3251                 info->bkt_info.bnk_fmt[bnk] = bnk_fmt[2];
   3252                 break;
   3253             case FMT3f:
   3254                 info->bkt_info.bnk_fmt[bnk] = bnk_fmt[3];
   3255                 break;
   3256             case FMT4f:
   3257                 info->bkt_info.bnk_fmt[bnk] = bnk_fmt[4];
   3258                 break;
   3259             case FMT5f:
   3260                 info->bkt_info.bnk_fmt[bnk] = bnk_fmt[5];
   3261                 break;
   3262             case FMT6f:
   3263                 info->bkt_info.bnk_fmt[bnk] = bnk_fmt[6];
   3264                 break;
   3265             case FMT7f:
   3266                 info->bkt_info.bnk_fmt[bnk] = bnk_fmt[7];
   3267                 break;
   3268             default:
   3269                 break;
   3270         }
   3271     }
   3272 
   3273     return;
   3274 }
   3275 
   3276 /* Read and update ALPM prefix key using 1bit length decoding */
   3277 int
   3278 th3_alpm_bkt_pfx_get(int u, int vrf_id, _alpm_cb_t *acb, void *e, uint32 fmt, uint32 *valid,
   3279                      uint32 *new_key, int *new_len)
   3280 {
   3281     int rv = BCM_E_NONE;
   3282     int fmt_len = ACB_FMT_PFX_LEN(acb, vrf_id, fmt);
   3283     uint32 pfx[5] = {0};
   3284 
   3285     /* process Bucket Level PREFIX */
   3286     soc_format_field_get(u, ACB_FMT_ENT(acb, vrf_id, fmt),
   3287                          e, PREFIXf, pfx);
   3288     *valid = pfx[0] | pfx[1] | pfx[2] | pfx[3] | pfx[4];
   3289 
   3290     /* pfx with all zero is invalid */
   3291     if (*valid) {
   3292         th3_alpm_ent_1bit_decoding(u, pfx, fmt_len, new_len);
   3293         SHR_BITCOPY_RANGE(new_key, 0, pfx, fmt_len - (*new_len) + 1, *new_len);
   3294     }
   3295 
   3296     return rv;
   3297 }
   3298 
   3299 /* Read ALPM Assoc_Data */
   3300 static void
   3301 th3_alpm_bkt_adata_get(int u, int vrf_id, int ipt, _alpm_cb_t *acb,
   3302                        void *e, int ent_fmt, _alpm_bkt_adata_t *adata)
   3303 {
   3304     uint32 fval[ALPM_MEM_ENT_MAX];
   3305     th3_fmt_ASSOC_DATA_REDUCED_t *fmt_adr = NULL;
   3306     th3_fmt_ASSOC_DATA_FULL_t *fmt_adf = NULL;
   3307 
   3308     soc_format_field_get(u, ACB_FMT_ENT(acb, vrf_id, ent_fmt),
   3309                          e, ASSOC_DATAf, fval);
   3310 
   3311     adata->defip_flags = ALPM_IS_IPV4(ipt) ? 0 : BCM_L3_IP6;
   3312     if (ACB_FMT_FULL_TYPE(acb, vrf_id, ent_fmt)) {
   3313         fmt_adf = (th3_fmt_ASSOC_DATA_FULL_t *)fval;
   3314         adata->defip_flags |= fmt_adf->DEST_TYPE ? BCM_L3_MULTIPATH : 0;
   3315         adata->defip_ecmp_index = fmt_adf->DESTINATION;
   3316         adata->defip_flags |= fmt_adf->RPE ? BCM_L3_RPE : 0;
   3317         adata->defip_flags |= fmt_adf->DST_DISCARD ? BCM_L3_DST_DISCARD : 0;
   3318         adata->defip_prio = fmt_adf->PRI;
   3319         adata->defip_lookup_class = fmt_adf->CLASS_ID;
   3320         adata->defip_flex_ctr_base_id = fmt_adf->FLEX_CTR_BASE_COUNTER_IDX;
   3321         adata->defip_flex_ctr_mode = fmt_adf->FLEX_CTR_OFFSET_MODE;
   3322         adata->defip_flex_ctr_pool = fmt_adf->FLEX_CTR_POOL_NUMBER;
   3323     } else {
   3324         fmt_adr = (th3_fmt_ASSOC_DATA_REDUCED_t *)fval;
   3325         adata->defip_flags |= fmt_adr->DEST_TYPE ? BCM_L3_MULTIPATH : 0;
   3326         adata->defip_ecmp_index = fmt_adr->DESTINATION;
   3327         adata->defip_prio = 0;
   3328         adata->defip_lookup_class = 0;
   3329         adata->defip_flex_ctr_base_id = 0;
   3330         adata->defip_flex_ctr_mode = 0;
   3331         adata->defip_flex_ctr_pool = 0;
   3332     }
   3333 
   3334     return ;
   3335 }
   3336 
   3337 static void
   3338 th3_alpm_ent_binfo_raw_get(int u, int vrf_id, _alpm_cb_t *acb, void *ent,
   3339                            int fmt, void *binfo_raw)
   3340 {
   3341     soc_format_field_get(u, ACB_FMT_ENT(acb, vrf_id, fmt),
   3342                          ent, ALPM2_DATAf, binfo_raw);
   3343 }
   3344 
   3345 /* Used for retrieving alpm info from given entry,
   3346  * Entry 'e' can be a TCAM entry or a entry entry, not bank entry */
   3347 int
   3348 th3_alpm_ent_selective_get(int u, _alpm_cb_t *acb, void *ent, _alpm_ent_info_t *info)
   3349 {
   3350     int rv = BCM_E_NONE;
   3351     int ent_fmt, vrf_id, ipt;
   3352     uint32 mask = info->action_mask;
   3353 
   3354     ent_fmt = info->ent_fmt;
   3355     vrf_id  = info->vrf_id;
   3356     ipt     = info->ipt;
   3357 
   3358     if (mask & (ALPM_INFO_MASK_VALID | ALPM_INFO_MASK_KEYLEN)) {
   3359         th3_alpm_bkt_pfx_get(u, vrf_id, acb, ent, ent_fmt, &info->ent_valid,
   3360                              info->key, &info->key_len);
   3361     }
   3362 
   3363     if (mask & ALPM_INFO_MASK_ASSOC_DATA) {
   3364         th3_alpm_bkt_adata_get(u, vrf_id, ipt, acb, ent, ent_fmt, &info->adata);
   3365     }
   3366 
   3367     if (mask & ALPM_INFO_MASK_ALPM_DATA) {
   3368         /* Here ent is ALPM_DATA/ALPM2_DATA format */
   3369         th3_alpm_ent_binfo_get(u, vrf_id, acb, ent, info);
   3370     }
   3371 
   3372     if (mask & ALPM_INFO_MASK_ALPM_DATA_RAW) {
   3373         th3_alpm_ent_binfo_raw_get(u, vrf_id, acb, ent, ent_fmt,
   3374                                    info->alpm_data_raw);
   3375     }
   3376 
   3377     if (mask & ALPM_INFO_MASK_FIXED_DATA) {
   3378         /* For TCAM entry only */;
   3379     }
   3380 
   3381     return rv;
   3382 }
   3383 
   3384 /* Return ALPM bucket bank default (minimum) format according to DB_Type */
   3385 uint8
   3386 th3_alpm_bkt_def_fmt_get(int u, _alpm_cb_t *acb, int vrf_id, int ipt)
   3387 {
   3388     static uint8 def_fmt[ALPM_FMT_CNT][2] = {
   3389         { ALPM_FMT_DEF_PVT_REDUCED, ALPM_FMT_DEF_PVT_FULL },
   3390         { ALPM_FMT_DEF_RTE_REDUCED, ALPM_FMT_DEF_RTE_FULL },
   3391     };
   3392 
   3393     return def_fmt[ACB_FMT_TYPE(acb, vrf_id)][ACB_VRF_DB_TYPE(u, acb, vrf_id, ipt)];
   3394 }
   3395 
   3396 /* Return Reduced/Full format type for a given fmt */
   3397 int16
   3398 th3_alpm_bkt_fmt_type_get(int u, int vrf_id, _alpm_cb_t *acb, uint8 fmt)
   3399 {
   3400     return ACB_FMT_FULL_TYPE(acb, vrf_id, fmt);
   3401 }
   3402 
   3403 static int
   3404 th3_alpm_table_dump_3level_bkt(int u, int vrf_id, int ipt, _alpm_cb_t *acb,
   3405                                uint32 *key, int key_len,
   3406                                _alpm_bkt_info_t *bkt_info,
   3407                                int lvl_cnt, int flags,
   3408                                int *count)
   3409 {
   3410     int i, bnk;
   3411     int idx1, eid;
   3412     int has_next = 1;
   3413     uint32 fmt, valid;
   3414 
   3415     char ip_str[128] = {0};
   3416     uint32 bkt_ent[ALPM_MEM_ENT_MAX];
   3417     uint32 ftmp[ALPM_MEM_ENT_MAX];
   3418     uint32 fent1[ALPM_MEM_ENT_MAX];
   3419 
   3420     uint32 hw_key[4];
   3421     int hw_len;
   3422 
   3423     _alpm_bkt_adata_t adata;
   3424     _alpm_bkt_info_t bkt_info1;
   3425     _bcm_defip_cfg_t lpm_cfg;
   3426 
   3427     if (lvl_cnt < 1) {
   3428         return BCM_E_NONE;
   3429     }
   3430 
   3431     for (bnk = 0; bnk < ACB_BNK_PER_BKT(acb, vrf_id); bnk++) {
   3432         fmt = bkt_info->bnk_fmt[bnk];
   3433         if ((fmt == 0) || (fmt > ACB_FMT_CNT(acb, vrf_id))) {
   3434             continue;
   3435         }
   3436 
   3437         /**** Bucket Level ****/
   3438         idx1 = ALPM_TAB_IDX_GET_BKT_BNK(acb, BI_ROFS(bkt_info),
   3439                                         BI_BKT_IDX(bkt_info), bnk);
   3440         if (flags & ALPM_DUMP_TABLE_NOCACHE) {
   3441             ALPM_IER(alpm_bkt_entry_read_no_cache(u,
   3442                      ACB_BKT_TBL(acb, vrf_id), acb, bkt_ent, idx1));
   3443         } else {
   3444             ALPM_IER(alpm_bkt_entry_read(u,
   3445                      ACB_BKT_TBL(acb, vrf_id), acb, bkt_ent, idx1));
   3446         }
   3447         for (eid = 0; eid < ACB_FMT_ENT_MAX(acb, vrf_id, fmt); eid++) {
   3448             uint32 key2[4] = {0};
   3449             int len2 = 0;
   3450             int phy_idx;
   3451 
   3452             /* process bucket entry Prefix */
   3453             alpm_util_ent_ent_get(u, vrf_id, acb, bkt_ent, fmt, eid, ftmp);
   3454             alpm_util_bkt_pfx_get(u, vrf_id, acb, ftmp, fmt, key2, &len2, &valid);
   3455             if (!valid) {
   3456                 continue;
   3457             }
   3458             alpm_util_bkt_adata_get(u, vrf_id, ipt, acb, ftmp, fmt, &adata, NULL);
   3459             alpm_util_pfx_cat(u, ipt, key, key_len, key2, len2, hw_key, &hw_len);
   3460             sal_memset(&lpm_cfg, 0, sizeof(lpm_cfg));
   3461             alpm_util_key_to_cfg(u, ipt, hw_key, &lpm_cfg);
   3462             if (ALPM_IS_IPV6(ipt)) {
   3463                 alpm_util_fmt_ip6addr(ip_str, lpm_cfg.defip_ip6_addr);
   3464             } else {
   3465                 alpm_util_fmt_ipaddr(ip_str, lpm_cfg.defip_ip_addr);
   3466             }
   3467             if (ACB_HAS_RTE(acb, vrf_id)) {
   3468                 has_next = 0;
   3469             }
   3470             for (i = 0; i <= acb->acb_idx; i++) {
   3471                 cli_out("\t");
   3472             }
   3473             phy_idx = th3_mem_phy_index_get(u, acb,
   3474                             ACB_BKT_TBL(acb, vrf_id), idx1);
   3475             cli_out("L%d-[%-5d] | f%-2db%de%-2d %-3d | %s/%d : %s %d %s\n",
   3476                     acb->acb_idx + 2, phy_idx, fmt, bnk, eid,
   3477                     has_next ? 0 : *count, ip_str, hw_len,
   3478                     (adata.defip_flags & BCM_L3_MULTIPATH) ? "ECMP" : "NH",
   3479                     adata.defip_ecmp_index, has_next ? "->" : "" );
   3480             if (!has_next) {
   3481                 *count += 1;
   3482                 continue;
   3483             }
   3484             alpm_util_ent_data_get(u, vrf_id, ipt, acb, ftmp, fmt, fent1);
   3485             alpm_util_bkt_info_get(u, vrf_id, ipt, ipt, ACB_DWN(u, acb), fent1, 0,
   3486                                    &bkt_info1, NULL, NULL);
   3487             ALPM_IER(th3_alpm_table_dump_3level_bkt(u, vrf_id,
   3488                      ipt, ACB_DWN(u, acb), hw_key, hw_len,
   3489                      &bkt_info1, lvl_cnt - 1, flags, count));
   3490         }
   3491     }
   3492 
   3493     return BCM_E_NONE;
   3494 }
   3495 
   3496 static int
   3497 th3_alpm_table_dump_3level_index(int u, soc_mem_t mem,
   3498                                  int idx, int sub_idx, int lvl_cnt, int flags)
   3499 {
   3500     int rv;
   3501     int ipt, pkm, ipv6, vrf_id;
   3502     int use_alpm;
   3503     int key_len;
   3504     int count = 0;
   3505 
   3506     char ip_str[128] = {0};
   3507     uint32 ent[ALPM_MEM_ENT_MAX] = {0};
   3508     uint32 bdata_ent[ALPM_MEM_ENT_MAX];
   3509     uint32 key[4];
   3510 
   3511     _alpm_bkt_adata_t adata0;
   3512     _alpm_bkt_info_t bkt_info;
   3513     _bcm_defip_cfg_t lpm_cfg;
   3514 
   3515     if (mem == L3_DEFIP_PAIR_LEVEL1m) {
   3516         pkm = ALPM_PKM_128;
   3517     } else {
   3518         pkm = ALPM_PKM_32B;
   3519     }
   3520 
   3521     if (flags & ALPM_DUMP_TABLE_NOCACHE) {
   3522         ALPM_IER(tcam_entry_read_no_cache(u, pkm, ent, idx, idx));
   3523     } else {
   3524         ALPM_IER(tcam_entry_read(u, pkm, ent, idx, idx));
   3525     }
   3526 
   3527     rv = th3_tcam_entry_mode_get_by_mem(u, mem, ent, NULL, &pkm,
   3528                                         &ipv6, NULL, sub_idx);
   3529     if (BCM_FAILURE(rv)) {
   3530         return rv;
   3531     }
   3532 
   3533     if (pkm == ALPM_PKM_64B && sub_idx == 1) {
   3534         return BCM_E_NONE;
   3535     }
   3536     ipt = ALPM_PKM2IPT(pkm);
   3537 
   3538     tcam_entry_vrf_id_get(u, pkm, ent, sub_idx, &vrf_id);
   3539     /* Get Pre-pivot key IP_ADDR and prefix length (mask) */
   3540     sal_memset(key, 0, sizeof(key));
   3541     key_len = 0;
   3542     tcam_entry_to_key(u, pkm, ent, sub_idx, key);
   3543     tcam_entry_pfx_len_get(u, pkm, ent, sub_idx, &key_len);
   3544     tcam_entry_adata_get(u, pkm, ent, sub_idx, &adata0);
   3545     tcam_entry_bdata_get(u, pkm, ent, sub_idx, bdata_ent);
   3546 
   3547     use_alpm = !(adata0.defip_flags & BCM_L3_IPMC) &&
   3548                ALPM_VRF_ID_HAS_BKT(u, vrf_id);
   3549     sal_memset(&lpm_cfg, 0, sizeof(lpm_cfg));
   3550     alpm_util_key_to_cfg(u, ipt, key, &lpm_cfg);
   3551     if (ipv6) {
   3552         alpm_util_fmt_ip6addr(ip_str, lpm_cfg.defip_ip6_addr);
   3553     } else {
   3554         alpm_util_fmt_ipaddr(ip_str, lpm_cfg.defip_ip_addr);
   3555     }
   3556 
   3557     if (ALPM_VRF_ID_IS_GBL(u, vrf_id)) {
   3558         cli_out("L1-[%4d.%d] | vrf-%-4s ", idx, sub_idx,
   3559             vrf_id == ALPM_VRF_ID_GHI(u) ? "GHi" : "GLo");
   3560     } else {
   3561         cli_out("L1-[%4d.%d] | vrf-%-4d ", idx, sub_idx, vrf_id);
   3562     }
   3563     cli_out("| %s/%d : %s %d %s\n", ip_str, key_len,
   3564             (adata0.defip_flags & BCM_L3_MULTIPATH) ? "ECMP" : "NH",
   3565             adata0.defip_ecmp_index, use_alpm ? "->" : "" );
   3566     if (!use_alpm) {
   3567         rv = BCM_E_NONE;
   3568         goto end;
   3569     }
   3570 
   3571     /* process ALPM_DATA level recursively from top to bottom */
   3572     alpm_util_bkt_info_get(u, vrf_id, ipt, pkm, ACB_TOP(u), bdata_ent,
   3573                            sub_idx, &bkt_info, NULL, NULL);
   3574     th3_alpm_table_dump_3level_bkt(u, vrf_id, ipt, ACB_TOP(u),
   3575                                    key, key_len, &bkt_info,
   3576                                    lvl_cnt - 1, flags, &count);
   3577 end:
   3578     return rv;
   3579 }
   3580 
   3581 int
   3582 th3_alpm_table_dump_3level(int u, soc_mem_t mem,
   3583                            int idx, int sub_idx, int lvl_cnt, int flags)
   3584 {
   3585     int rv = BCM_E_NONE;
   3586     int i, j, idx_min, idx_max, sub_idx_min, sub_idx_max;
   3587     int pkm;
   3588 
   3589     if (idx < 0) {
   3590         idx_min = 0;
   3591         if (mem == L3_DEFIP_LEVEL1m) {
   3592             pkm = ALPM_PKM_32B;
   3593         } else {
   3594             pkm = ALPM_PKM_128;
   3595         }
   3596         idx_max = tcam_table_size(u, pkm) - 1;
   3597         sub_idx_min = 0;
   3598         sub_idx_max = (pkm == ALPM_PKM_32B) ? 1 : 0;
   3599     } else {
   3600         idx_min = idx_max = idx;
   3601         sub_idx_min = sub_idx_max = (sub_idx < 0) ? 0 : sub_idx;
   3602     }
   3603 
   3604     /* Levels are going to be printed */
   3605     if (lvl_cnt < 1 || lvl_cnt > 3) {
   3606         lvl_cnt = 3;
   3607     }
   3608 
   3609     for (i = idx_min; i <= idx_max; i++) {
   3610         for (j = sub_idx_min; j <= sub_idx_max; j++) {
   3611             rv = th3_alpm_table_dump_3level_index(u, mem, i, j, lvl_cnt, flags);
   3612             if (BCM_FAILURE(rv)) {
   3613                 if (rv == BCM_E_NOT_FOUND) {
   3614                     if (idx_min == idx_max) {
   3615                         cli_out("Entry %d.%d is invalid\n", i, j);
   3616                     }
   3617                     continue;
   3618                 }
   3619                 break;
   3620             }
   3621         }
   3622     }
   3623 
   3624     return rv;
   3625 }
   3626 
   3627 /*
   3628  * Function:
   3629  *      th3_alpm_table_dump
   3630  * Purpose:
   3631  *      Dump TH3 ALPM Level2 and Level3 memory tables:
   3632  *      "alpm table dump [raw|chg|all|nocache] <mem> <index> <format> [<ent>]"
   3633  * Parameters:
   3634  *      u       - Device unit #
   3635  *      mem     - ALPM Level2 or Level3 memory table
   3636  *      copyno  - mem table copy number
   3637  *      index   - ALPM bucket level logic table index
   3638  *      fmt     - Bank format (1-8 for Pivot formats, 1-12 for Route formats)
   3639  *      ent_idx - entry index (0-14), -1 for all entries.
   3640  *      flags   - Dump flags (raw, chg, all, nocache)
   3641  * Returns:
   3642  *      BCM_E_XXX
   3643  */
   3644 int
   3645 th3_alpm_table_dump(int u, int vrf_id, soc_mem_t mem, int copyno, int index,
   3646                     int fmt, int ent_idx, int flags)
   3647 {
   3648     int     rv;
   3649     int     i, ent, ent_min, ent_max;
   3650     int     f, f1, entry_dw;
   3651     int     first_print_flag = 0;
   3652     int     vertical = 0;
   3653     uint32  entry[ALPM_MEM_ENT_MAX];
   3654     uint32  fent[ALPM_MEM_ENT_MAX];
   3655     uint32  fval[ALPM_MEM_ENT_MAX];
   3656     uint32  fval1[ALPM_MEM_ENT_MAX];
   3657     uint32  nfval[ALPM_MEM_ENT_MAX];
   3658     char    ctmp[ALPM_MEM_ENT_MAX * 8 + 3];
   3659     char    mem_prefix[256];
   3660     _alpm_cb_t *acb = (mem == L3_DEFIP_ALPM_LEVEL2m ?
   3661                        ACB_TOP(u) : ACB_VRF_BTM(u, vrf_id));
   3662     soc_field_info_t *fieldp;
   3663     soc_field_info_t *fieldp1;
   3664     soc_format_info_t *fmtp;
   3665     soc_format_info_t *fmtp1;
   3666     soc_format_t tfmt;
   3667     soc_format_t tfmt1;
   3668 
   3669     if (mem == L3_DEFIP_LEVEL1m || mem == L3_DEFIP_PAIR_LEVEL1m) {
   3670         /* Use fmt to store Level count */
   3671         return th3_alpm_table_dump_3level(u, mem, index, ent_idx, fmt, flags);
   3672     }
   3673 
   3674     if ((fmt <= 0) || (fmt > ACB_FMT_CNT(acb, vrf_id))) {
   3675         cli_out("invalid or disabled bank format %d\n", fmt);
   3676         return BCM_E_INTERNAL;
   3677     }
   3678     tfmt = ACB_FMT_ENT(acb, vrf_id, fmt);
   3679 
   3680     if (ent_idx == -1) { /* all entries */
   3681         ent_min = 0;
   3682         ent_max = ACB_FMT_ENT_MAX(acb, vrf_id, fmt);
   3683     } else if (ent_idx >= ACB_FMT_ENT_MAX(acb, vrf_id, fmt)) {
   3684         cli_out("invalid entry idx %d\n", ent_idx);
   3685         return BCM_E_INTERNAL;
   3686     } else { /* one specific entry */
   3687         ent_min = ent_idx;
   3688         ent_max = ent_idx + 1;
   3689     }
   3690 
   3691     sal_memset(nfval, 0, sizeof(nfval));
   3692 
   3693     if (flags & ALPM_DUMP_TABLE_NOCACHE) {
   3694         rv = soc_mem_read_no_cache(u, 0, mem, 0, MEM_BLOCK_ANY, index, entry);
   3695     } else {
   3696         rv = soc_mem_read(u, mem, MEM_BLOCK_ANY, index, entry);
   3697     }
   3698 
   3699     if (BCM_FAILURE(rv)) {
   3700         cli_out("Read ERROR: table %s.%s[%d]: %s\n",
   3701                 SOC_MEM_UFNAME(u, mem),
   3702                 SOC_BLOCK_NAME(u, copyno), index, soc_errmsg(rv));
   3703         return BCM_E_INTERNAL;
   3704     }
   3705 
   3706     for (ent = ent_min; ent < ent_max; ent++) {
   3707         soc_format_field_get(u, ACB_FMT_BNK(acb, vrf_id, fmt), entry,
   3708                              th3_alpm_ent_fld[ent], fent);
   3709         fmtp = &SOC_FORMAT_INFO(u, tfmt);
   3710 
   3711         sal_sprintf(mem_prefix, "%s.%s[%d.%d]: ", SOC_MEM_UFNAME(u, mem),
   3712                     SOC_BLOCK_NAME(u, copyno), index, ent);
   3713 
   3714         if (flags & ALPM_DUMP_TABLE_RAW) {
   3715             cli_out("%s", mem_prefix);
   3716             entry_dw = BITS2WORDS(fmtp->bits);
   3717             for (i = 0; i < entry_dw; i++) {
   3718                 cli_out("0x%08x ", fent[i]);
   3719             }
   3720             cli_out("\n");
   3721         } else {
   3722             /* for fields in entry format */
   3723             for (f = fmtp->nFields - 1; f >= 0; f--) {
   3724                 fieldp = &fmtp->fields[f];
   3725                 sal_memset(fval, 0, ALPM_MEM_ENT_MAX * sizeof(uint32));
   3726                 soc_format_field_get(u, tfmt, fent, fieldp->field, fval);
   3727 
   3728                 if (flags & ALPM_DUMP_TABLE_CHANGED) {
   3729                     if (sal_memcmp(fval, nfval, ALPM_MEM_ENT_MAX *
   3730                                    sizeof(uint32)) == 0) {
   3731                         continue;
   3732                     }
   3733                 }
   3734 
   3735                 /* for fields in format-in-format (ALPM2_DATA or ASSOC_DATA) */
   3736                 tfmt1 = INVALIDfmt;
   3737                 if (fieldp->field == ALPM2_DATAf) {
   3738                     tfmt1 = ALPM2_DATAfmt;
   3739                 } else if (fieldp->field == ASSOC_DATAf) {
   3740                     tfmt1 = ACB_FMT_FULL_TYPE(acb, vrf_id, fmt) ?
   3741                             ASSOC_DATA_FULLfmt : ASSOC_DATA_REDUCEDfmt;
   3742                 }
   3743                 if (tfmt1 != INVALIDfmt) {
   3744                     fmtp1 = &SOC_FORMAT_INFO(u, tfmt1);
   3745                     for (f1 = fmtp1->nFields - 1; f1 >= 0; f1--) {
   3746                         fieldp1 = &fmtp1->fields[f1];
   3747                         sal_memset(fval1, 0, ALPM_MEM_ENT_MAX * sizeof(uint32));
   3748                         soc_format_field_get(u, tfmt1, fval, fieldp1->field, fval1);
   3749 
   3750                         if (flags & ALPM_DUMP_TABLE_CHANGED) {
   3751                             if (sal_memcmp(fval1, nfval, ALPM_MEM_ENT_MAX *
   3752                                            sizeof(uint32)) == 0) {
   3753                                 continue;
   3754                             }
   3755                         }
   3756                         _shr_format_long_integer(ctmp, fval1, BITS2BYTES(fieldp1->len));
   3757 
   3758                         if (first_print_flag == 0) {
   3759                             cli_out("%s%s", mem_prefix, vertical ? "" : "<");
   3760                             first_print_flag=1;
   3761                         }
   3762                         if (vertical) {
   3763                             cli_out("\n\t%30s: %s", SOC_FIELD_NAME(u, fieldp1->field), ctmp);
   3764                         } else {
   3765                             cli_out("%s=%s,", SOC_FIELD_NAME(u, fieldp1->field), ctmp);
   3766                         }
   3767                     } /* for f1 */
   3768                 }
   3769 
   3770                 _shr_format_long_integer(ctmp, fval, BITS2BYTES(fieldp->len));
   3771 
   3772                 if (first_print_flag == 0) {
   3773                     cli_out("%s%s", mem_prefix, vertical ? "" : "<");
   3774                     first_print_flag=1;
   3775                 }
   3776                 if (vertical) {
   3777                     cli_out("\n\t%30s: %s", SOC_FIELD_NAME(u, fieldp->field), ctmp);
   3778                 } else {
   3779                     cli_out("%s=%s%s", SOC_FIELD_NAME(u, fieldp->field),
   3780                             ctmp, f > 0 ? "," : "");
   3781                 }
   3782             } /* for f */
   3783 
   3784             if (first_print_flag == 1) {
   3785                 cli_out("%s\n", vertical ? "" : ">");
   3786                 first_print_flag = 0;
   3787             }
   3788         }
   3789     } /* for ent */
   3790 
   3791     return BCM_E_NONE;
   3792 }
   3793 
   3794 /*
   3795  * Function:
   3796  *      th3_alpm_cap_min
   3797  * Purpose:
   3798  *      Get the min capacity for ALPM routes from PKM
   3799  * Parameters:
   3800  *      u           - Device unit
   3801  *      pkm         - Packing mode
   3802  */
   3803 int
   3804 th3_alpm_cap_min(int u, int pkm)
   3805 {
   3806     int tcam_ent = 0;
   3807     int min_bkt_cnt, min_bkt_ent;
   3808     int i, fmt, vrf_id;
   3809     _alpm_bkt_pool_conf_t *bp_conf;
   3810     _alpm_cb_t *acb;
   3811 
   3812     /* Start from TCAM restriction */
   3813     switch (pkm) {
   3814     case ALPM_PKM_32B:
   3815         tcam_ent = soc_mem_index_count(u, L3_DEFIP_LEVEL1m) * 2;
   3816         break;
   3817     case ALPM_PKM_64B:
   3818         tcam_ent = soc_mem_index_count(u, L3_DEFIP_LEVEL1m);
   3819         break;
   3820     case ALPM_PKM_128:
   3821         tcam_ent = soc_mem_index_count(u, L3_DEFIP_PAIR_LEVEL1m);
   3822         break;
   3823     default:
   3824         return 0;
   3825     }
   3826 
   3827     min_bkt_ent = (ALPM_TCAM_ZONED(u) ? tcam_ent / 2 : tcam_ent);
   3828 
   3829     /* Consider only for private DB */
   3830     vrf_id = 1;
   3831     for (i = 0; i < ACB_CNT(u); i++) {
   3832         int avl_bnks, min_bnks;
   3833         acb = ACB(u, i);
   3834         bp_conf = ACB_BKT_POOL(acb, ALPM_VRF_ID_TO_BPC_PID(u, vrf_id));
   3835 
   3836         /* avl_bnks starts with all, then check ALPM_BKT_RSVD */
   3837         avl_bnks = BPC_BNK_CNT(bp_conf);
   3838         if (ALPM_128B(u) && ALPM_BKT_RSVD(u)) {
   3839             int rsvd_v6_bnks =
   3840                 BPC_BNK_CNT(bp_conf) * ALPM_BKT_RSVD_CNT(u) / 8192;
   3841             if (pkm == ALPM_PKM_128) {
   3842                 avl_bnks = rsvd_v6_bnks;
   3843             } else {
   3844                 avl_bnks -= rsvd_v6_bnks;
   3845             }
   3846         }
   3847 
   3848         /* compare upper min_bkt_ent and bkt_cnt at current level */
   3849         min_bkt_cnt = (ACB_BKT_CNT(acb) < min_bkt_ent ? ACB_BKT_CNT(acb) : min_bkt_ent);
   3850         min_bnks = min_bkt_cnt * BPC_BNK_PER_BKT(bp_conf);
   3851 
   3852         /* update avl_bnks comapring to min_bnks */
   3853         if (min_bnks < avl_bnks ) {
   3854             avl_bnks = min_bnks;
   3855         }
   3856 
   3857         if (ACB_HAS_RTE(acb, vrf_id)) {
   3858             /* Route (full) format whose prefix length fits almost the full PKM length */
   3859             fmt = (pkm == ALPM_PKM_32B ? 10 :       /* FMT10 (33b) */
   3860                    pkm == ALPM_PKM_64B ? 11 : 12);  /* FMT11 (73b), FMT12 (128b) */
   3861         } else {
   3862             /* Pivot (full) format whose prefix length
   3863                fits almost the remaining pivot length */
   3864             fmt = 6; /* FMT6 (17b) */
   3865         }
   3866 
   3867         /* considering 33% on bucket split utlization */
   3868         min_bkt_ent = avl_bnks * ACB_FMT_ENT_MAX(acb, vrf_id, fmt) / 3;
   3869     }
   3870 
   3871     return min_bkt_ent;
   3872 }
   3873 
   3874 /*
   3875  * Function:
   3876  *      th3_alpm_cap_max
   3877  * Purpose:
   3878  *      Get the max capacity for ALPM routes from PKM
   3879  * Parameters:
   3880  *      u           - Device unit
   3881  *      pkm         - Packing mode
   3882  */
   3883 int
   3884 th3_alpm_cap_max(int u, int pkm)
   3885 {
   3886     int tcam_ent = 0;
   3887     int min_bkt_cnt, max_bkt_ent;
   3888     int i, fmt, vrf_id, pid;
   3889     _alpm_bkt_pool_conf_t *bp_conf;
   3890     _alpm_cb_t *acb;
   3891 
   3892     /* Start from TCAM restriction */
   3893     switch (pkm) {
   3894     case ALPM_PKM_32B:
   3895         tcam_ent = soc_mem_index_count(u, L3_DEFIP_LEVEL1m) * 2;
   3896         break;
   3897     case ALPM_PKM_64B:
   3898         tcam_ent = soc_mem_index_count(u, L3_DEFIP_LEVEL1m);
   3899         break;
   3900     case ALPM_PKM_128:
   3901         tcam_ent = soc_mem_index_count(u, L3_DEFIP_PAIR_LEVEL1m);
   3902         break;
   3903     default:
   3904         return 0;
   3905     }
   3906 
   3907     /* Include private/global ALPM routes (exclude TCAM direct routes) */
   3908     /* TCAM mode private VRF has half TCAM entries */
   3909     max_bkt_ent = (ALPM_MODE_CHK(u, BCM_ALPM_MODE_TCAM_ALPM) ? tcam_ent / 2 : tcam_ent);
   3910 
   3911     /* Route or Pivot (reduced) FMT1 with maximum entries per bank */
   3912     fmt = 1;
   3913 
   3914     for (i = 0; i < ACB_CNT(u); i++) {
   3915         int avl_bnks, min_bnks;
   3916         acb = ACB(u, i);
   3917         /* compare upper max_bkt_ent and bkt_cnt at current level */
   3918         min_bkt_cnt = (ACB_BKT_CNT(acb) < max_bkt_ent ? ACB_BKT_CNT(acb) : max_bkt_ent);
   3919 
   3920         max_bkt_ent = 0;
   3921         /* consider both private and global routes */
   3922         for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) {
   3923             bp_conf = ACB_BKT_POOL(acb, pid);
   3924             vrf_id = ALPM_BPC_PID_TO_VRF_ID(u, pid);
   3925 
   3926             if (pid > 0 && bp_conf == ACB_BKT_POOL(acb, pid - 1)) {
   3927                 continue; /* Combined Mode uses PID=0 only */
   3928             }
   3929 
   3930             /* avl_bnks starts with all, then check ALPM_BKT_RSVD */
   3931             avl_bnks = BPC_BNK_CNT(bp_conf);
   3932             if (ALPM_128B(u) && ALPM_BKT_RSVD(u)) {
   3933                 int rsvd_v6_bnks =
   3934                     BPC_BNK_CNT(bp_conf) * ALPM_BKT_RSVD_CNT(u) / 8192;
   3935                 if (pkm == ALPM_PKM_128) {
   3936                     avl_bnks = rsvd_v6_bnks;
   3937                 } else {
   3938                     avl_bnks -= rsvd_v6_bnks;
   3939                 }
   3940             }
   3941 
   3942             min_bnks = min_bkt_cnt * BPC_BNK_PER_BKT(bp_conf);
   3943 
   3944             /* update avl_bnks comapring to min_bnks */
   3945             if (min_bnks < avl_bnks ) {
   3946                 avl_bnks = min_bnks;
   3947             }
   3948 
   3949             max_bkt_ent += avl_bnks * ACB_FMT_ENT_MAX(acb, vrf_id, fmt);
   3950         }
   3951     }
   3952 
   3953     return max_bkt_ent;
   3954 }
   3955 
   3956 /*
   3957  * Function:
   3958  *      th3_alpm_cap_get
   3959  * Purpose:
   3960  *      Get the min or max capacity for ALPM routes from legacy tables:
   3961  * L3_DEFIP_ALPM_IPV4, L3_DEFIP_ALPM_IPV6_64, L3_DEFIP_ALPM_IPV6_128
   3962  *
   3963  * Parameters:
   3964  *      u           - Device unit
   3965  *      mem         - Legacy memory type
   3966  *      max_cnt     - Maximum result returned.
   3967  *      min_cnt     - Minimum result returned.
   3968  */
   3969 int
   3970 th3_alpm_cap_get(int u, soc_mem_t mem, int *max_cnt, int *min_cnt)
   3971 {
   3972     int pkm;
   3973     switch (mem) {
   3974         case L3_DEFIP_ALPM_IPV4m:
   3975         case L3_DEFIP_ALPM_IPV4_1m:
   3976             pkm = ALPM_PKM_32B;
   3977             break;
   3978         case L3_DEFIP_ALPM_IPV6_64m:
   3979         case L3_DEFIP_ALPM_IPV6_64_1m:
   3980             pkm = ALPM_PKM_64B;
   3981             break;
   3982     case L3_DEFIP_ALPM_IPV6_128m:
   3983             pkm = ALPM_PKM_128;
   3984             break;
   3985         default:
   3986             return BCM_E_UNAVAIL;
   3987     }
   3988 
   3989     if (min_cnt != NULL) {
   3990         *min_cnt = th3_alpm_cap_min(u, pkm);
   3991     }
   3992 
   3993     if (max_cnt != NULL) {
   3994         *max_cnt = th3_alpm_cap_max(u, pkm);
   3995     }
   3996 
   3997     return BCM_E_NONE;
   3998 }
   3999 
   4000 /*
   4001  * Function:
   4002  *      th3_alpm_bkt_hit_get
   4003  * Purpose:
   4004  *      Get ALPM bucket entry hitbit status from hitbit table cache
   4005  *      sync with Hw. Route hitbit status is gathered from pivots
   4006  *      whose BPM is the route.
   4007  * Parameters:
   4008  *      u       - Device unit #
   4009  *      vrf_id  - VRF ID for logic hit table PID in Parallel/Mixed Mode
   4010  *      acb     - ALPM control block where hit table located
   4011  *      idx     - ALPM bucket level logic table index
   4012  *      ent     - Bucket entry ID (0-15)
   4013  * Returns:
   4014  *      Bucket entry hitbit (0 or 1)
   4015  */
   4016 int
   4017 th3_alpm_bkt_hit_get(int u, int vrf_id, _alpm_cb_t *acb,
   4018                      _alpm_tbl_t tbl, int idx, int ent)
   4019 {
   4020     int rv;
   4021     uint32 *tbl_ent; /* bucket hit cache table entry pointer */
   4022     int i = ACB_IDX(acb);
   4023     int pid = ACB_BKT_VRF_PID(acb, vrf_id);
   4024     soc_mem_t mem = ALPM_HTBL_MEM(u, i, pid);
   4025     soc_field_t hit_fld[16] = {
   4026         HIT_0f, HIT_1f, HIT_2f,  HIT_3f,  HIT_4f,  HIT_5f,  HIT_6f,  HIT_7f,
   4027         HIT_8f, HIT_9f, HIT_10f, HIT_11f, HIT_12f, HIT_13f, HIT_14f, HIT_15f
   4028     };
   4029 
   4030     tbl_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 *,
   4031                                            ALPM_HTBL_CACHE(u, i, pid), idx);
   4032     rv = soc_mem_field32_get(u, mem, tbl_ent, hit_fld[ent]);
   4033 
   4034     return rv;
   4035 }
   4036 
   4037 /*
   4038  * Function:
   4039  *      th3_alpm_bkt_hit_set
   4040  * Purpose:
   4041  *      Set ALPM bucket entry hitbit to cache table only
   4042  * Parameters:
   4043  *      u       - Device unit #.
   4044  *      vrf_id  - VRF ID for logic hit table PID in Parallel/Mixed Mode
   4045  *      acb     - ALPM control block where hit table located
   4046  *      idx     - ALPM bucket level table index
   4047  *      ent     - Bucket entry ID (0-15)
   4048  *      hit_val - Bucket entry hit value (0/1)
   4049  * Returns:
   4050  *      BCM_E_XXX
   4051  */
   4052 int
   4053 th3_alpm_bkt_hit_set(int u, int vrf_id, _alpm_cb_t *acb, _alpm_tbl_t tbl,
   4054                      int idx, int ent, int hit_val)
   4055 {
   4056     int rv = BCM_E_NONE;
   4057     uint32 *tbl_ent; /* bucket hit cache table entry pointer */
   4058     int i = ACB_IDX(acb);
   4059     int pid = ACB_BKT_VRF_PID(acb, vrf_id);
   4060     soc_mem_t mem = ALPM_HTBL_MEM(u, i, pid);
   4061     soc_field_t hit_fld[16] = {
   4062         HIT_0f, HIT_1f, HIT_2f,  HIT_3f,  HIT_4f,  HIT_5f,  HIT_6f,  HIT_7f,
   4063         HIT_8f, HIT_9f, HIT_10f, HIT_11f, HIT_12f, HIT_13f, HIT_14f, HIT_15f
   4064     };
   4065 
   4066     tbl_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 *,
   4067                                            ALPM_HTBL_CACHE(u, i, pid), idx);
   4068     soc_mem_field32_set(u, mem, tbl_ent, hit_fld[ent], hit_val);
   4069 
   4070     return rv;
   4071 }
   4072 
   4073 /*
   4074  * Function:
   4075  *      th3_alpm_bkt_hit_write
   4076  * Purpose:
   4077  *      Set ALPM bucket entry hitbit status to hitbit table cache
   4078  *      and write to Hw (by setting Entry Move & Mask to trigger write to Hw
   4079  *      in next Dist Hitbit thread clycle).
   4080  * Parameters:
   4081  *      u       - Device unit #
   4082  *      vrf_id  - VRF ID for logic hit table PID in Parallel/Mixed Mode
   4083  *      acb     - ALPM control block where hit table located
   4084  *      ent_idx - ALPM bucket node ent_idx
   4085  *      hit_val - HITBIT value requested
   4086  * Returns:
   4087  *      BCM_E_XXX
   4088  */
   4089 int
   4090 th3_alpm_bkt_hit_write(int u, int vrf_id, _alpm_cb_t *acb,
   4091                        _alpm_tbl_t tbl, int ent_idx, int hit_val)
   4092 {
   4093     int rv = BCM_E_NONE;
   4094     int idx, ent;
   4095     uint32 *dst_ent; /* bucket hit cache table entry pointer */
   4096     int i = ACB_IDX(acb);
   4097     int pid = ACB_BKT_VRF_PID(acb, vrf_id);
   4098     soc_mem_t mem = ALPM_HTBL_MEM(u, i, pid);
   4099     soc_field_t hit_fld[16] = {
   4100         HIT_0f, HIT_1f, HIT_2f,  HIT_3f,  HIT_4f,  HIT_5f,  HIT_6f,  HIT_7f,
   4101         HIT_8f, HIT_9f, HIT_10f, HIT_11f, HIT_12f, HIT_13f, HIT_14f, HIT_15f
   4102     };
   4103 
   4104     ALPM_HIT_LOCK(u);
   4105 
   4106     ent = ALPM_IDX_TO_ENT(ent_idx);
   4107     idx = ALPM_TAB_IDX_GET(ent_idx);
   4108 
   4109     /* Write hit_val to dst cache hit bit */
   4110     dst_ent = soc_mem_table_idx_to_pointer(u, mem, void *,
   4111                                            ALPM_HTBL_CACHE(u, i, pid), idx);
   4112     soc_mem_field32_set(u, mem, dst_ent, hit_fld[ent], hit_val);
   4113 
   4114     /* Write hit_val to dst move bit */
   4115     dst_ent = soc_mem_table_idx_to_pointer(u, mem, void *,
   4116                                            ALPM_HTBL_MOVE(u, i, pid), idx);
   4117     soc_mem_field32_set(u, mem, dst_ent, hit_fld[ent], hit_val);
   4118 
   4119     /* Set dst move mask bit */
   4120     dst_ent = soc_mem_table_idx_to_pointer(u, mem, void *,
   4121                                       ALPM_HTBL_MOVE_MASK(u, i, pid), idx);
   4122     soc_mem_field32_set(u, mem, dst_ent, hit_fld[ent], 1);
   4123 
   4124     /* declare finally hitbit entry_moved flag */
   4125     ALPM_HTBL_ENT_MOVED(u, i, pid) = TRUE;
   4126 
   4127     ALPM_HIT_UNLOCK(u);
   4128 
   4129     return rv;
   4130 }
   4131 
   4132 /* ALPM bucket hitbit entry move from bkt_node's src_ent_idx to dst_ent_idx.
   4133    Copy hit bit cache, and set properly move, move_mask and ent_moved flag.
   4134  */
   4135 int
   4136 th3_alpm_ent_hit_move(int u, int vrf_id, _alpm_cb_t *acb, int src_ent_idx, int dst_ent_idx)
   4137 {
   4138     int rv = BCM_E_NONE;
   4139     int i, hit_val, idx, ent;
   4140     uint32 *src_ent, *dst_ent;
   4141     int pid = ACB_BKT_VRF_PID(acb, vrf_id);
   4142     soc_mem_t mem;
   4143     soc_field_t hit_fld[16] = {
   4144         HIT_0f, HIT_1f, HIT_2f,  HIT_3f,  HIT_4f,  HIT_5f,  HIT_6f,  HIT_7f,
   4145         HIT_8f, HIT_9f, HIT_10f, HIT_11f, HIT_12f, HIT_13f, HIT_14f, HIT_15f
   4146     };
   4147 
   4148     ALPM_HIT_LOCK(u);
   4149 
   4150     i = ACB_IDX(acb);
   4151     mem = ALPM_HTBL_MEM(u, i, pid);
   4152 
   4153     /* 1) Src */
   4154     ent = ALPM_IDX_TO_ENT(src_ent_idx);
   4155     idx = ALPM_TAB_IDX_GET(src_ent_idx);
   4156 
   4157     /* Save src cache hit_val and clear it */
   4158     src_ent = soc_mem_table_idx_to_pointer(u, mem, void *,
   4159                                            ALPM_HTBL_CACHE(u, i, pid), idx);
   4160     hit_val = soc_mem_field32_get(u, mem, src_ent, hit_fld[ent]);
   4161     soc_mem_field32_set(u, mem, src_ent, hit_fld[ent], 0);
   4162 
   4163     /* Clear src move bit */
   4164     src_ent = soc_mem_table_idx_to_pointer(u, mem, void *,
   4165                                            ALPM_HTBL_MOVE(u, i, pid), idx);
   4166     soc_mem_field32_set(u, mem, src_ent, hit_fld[ent], 0);
   4167 
   4168     /* Set src move mask bit */
   4169     src_ent = soc_mem_table_idx_to_pointer(u, mem, void *,
   4170                                            ALPM_HTBL_MOVE_MASK(u, i, pid), idx);
   4171     soc_mem_field32_set(u, mem, src_ent, hit_fld[ent], 1);
   4172 
   4173     /* 2) Dst */
   4174     ent = ALPM_IDX_TO_ENT(dst_ent_idx);
   4175     idx = ALPM_TAB_IDX_GET(dst_ent_idx);
   4176 
   4177     /* Write hit_val to dst cache hit bit */
   4178     dst_ent = soc_mem_table_idx_to_pointer(u, mem, void *,
   4179                                            ALPM_HTBL_CACHE(u, i, pid), idx);
   4180     soc_mem_field32_set(u, mem, dst_ent, hit_fld[ent], hit_val);
   4181 
   4182     /* Write hit_val to dst move bit */
   4183     dst_ent = soc_mem_table_idx_to_pointer(u, mem, void *,
   4184                                            ALPM_HTBL_MOVE(u, i, pid), idx);
   4185     soc_mem_field32_set(u, mem, dst_ent, hit_fld[ent], hit_val);
   4186 
   4187     /* Set dst move mask bit */
   4188     dst_ent = soc_mem_table_idx_to_pointer(u, mem, void *,
   4189                                       ALPM_HTBL_MOVE_MASK(u, i, pid), idx);
   4190     soc_mem_field32_set(u, mem, dst_ent, hit_fld[ent], 1);
   4191 
   4192     /* declare finally hitbit entry_moved flag */
   4193     ALPM_HTBL_ENT_MOVED(u, i, pid) = TRUE;
   4194 
   4195     ALPM_HIT_UNLOCK(u);
   4196 
   4197     return rv;
   4198 }
   4199 
   4200 /* ALPM bucket bank hitbit move from src_idx to dst_idx.
   4201    Copy hit bit cache, and set properly move, move_mask and ent_moved flag.
   4202  */
   4203 int
   4204 th3_alpm_bnk_hit_move(int u, int vrf_id, _alpm_cb_t *acb, int src_idx, int dst_idx)
   4205 {
   4206     int rv = BCM_E_NONE;
   4207     int i;
   4208     uint32 src_cache;
   4209     uint32 *cache_ent, *move_ent, *move_mask_ent;
   4210     int pid = ACB_BKT_VRF_PID(acb, vrf_id);
   4211     soc_mem_t mem;
   4212 
   4213     ALPM_HIT_LOCK(u);
   4214 
   4215     i = ACB_IDX(acb);
   4216     mem = ALPM_HTBL_MEM(u, i, pid);
   4217 
   4218     /* 1) Src bank */
   4219     cache_ent = soc_mem_table_idx_to_pointer(u, mem, void *,
   4220                                          ALPM_HTBL_CACHE(u, i, pid), src_idx);
   4221     move_ent = soc_mem_table_idx_to_pointer(u, mem, void *,
   4222                                           ALPM_HTBL_MOVE(u, i, pid), src_idx);
   4223     move_mask_ent = soc_mem_table_idx_to_pointer(u, mem, void *,
   4224                                      ALPM_HTBL_MOVE_MASK(u, i, pid), src_idx);
   4225     src_cache = *cache_ent; /* save src_cache value */
   4226     *cache_ent = 0; /* clear src cache */
   4227     *move_ent = 0; /* clear src move */
   4228     *move_mask_ent = ALPM_MAX_HIT_ENT_MASK; /* Set src mask for all 16 bits */
   4229 
   4230     /* 2) Dst bank */
   4231     cache_ent = soc_mem_table_idx_to_pointer(u, mem, void *,
   4232                                          ALPM_HTBL_CACHE(u, i, pid), dst_idx);
   4233     move_ent = soc_mem_table_idx_to_pointer(u, mem, void *,
   4234                                           ALPM_HTBL_MOVE(u, i, pid), dst_idx);
   4235     move_mask_ent = soc_mem_table_idx_to_pointer(u, mem, void *,
   4236                                      ALPM_HTBL_MOVE_MASK(u, i, pid), dst_idx);
   4237     *cache_ent = src_cache; /* copy saved src_cache value to dst cache */
   4238     *move_ent = src_cache; /* copy same to dst move */
   4239     *move_mask_ent = ALPM_MAX_HIT_ENT_MASK; /* Set dst mask for all 16 bits */
   4240 
   4241     /* declare finally hitbit entry_moved flag */
   4242     ALPM_HTBL_ENT_MOVED(u, i, pid) = TRUE;
   4243 
   4244     ALPM_HIT_UNLOCK(u);
   4245     return rv;
   4246 }
   4247 
   4248 /* Clear ALPM bucket bank hitbit cache at idx.
   4249    Set properly move, move_mask and ent_moved flag.
   4250  */
   4251 int
   4252 th3_alpm_bnk_hit_clear(int u, int vrf_id, _alpm_cb_t *acb, int idx)
   4253 {
   4254     int rv = BCM_E_NONE;
   4255     int i;
   4256     uint32 *entry;
   4257     int pid = ACB_BKT_VRF_PID(acb, vrf_id);
   4258     soc_mem_t mem;
   4259 
   4260     ALPM_HIT_LOCK(u);
   4261 
   4262     i = ACB_IDX(acb);
   4263     mem = ALPM_HTBL_MEM(u, i, pid);
   4264 
   4265     entry = soc_mem_table_idx_to_pointer(u, mem, void *,
   4266                                          ALPM_HTBL_CACHE(u, i, pid), idx);
   4267     *entry = 0; /* clear cache */
   4268 
   4269     entry = soc_mem_table_idx_to_pointer(u, mem, void *,
   4270                                          ALPM_HTBL_MOVE(u, i, pid), idx);
   4271     *entry = 0; /* clear move */
   4272 
   4273     entry = soc_mem_table_idx_to_pointer(u, mem, void *,
   4274                                          ALPM_HTBL_MOVE_MASK(u, i, pid), idx);
   4275     *entry = ALPM_MAX_HIT_ENT_MASK; /* set move mask */
   4276 
   4277     /* declare finally hitbit entry_moved flag */
   4278     ALPM_HTBL_ENT_MOVED(u, i, pid) = TRUE;
   4279 
   4280     ALPM_HIT_UNLOCK(u);
   4281     return rv;
   4282 }
   4283 
   4284 /* Update hitbit for entry move on level i by
   4285  * hit_cache = (hit_cache & ~hit_move_mask) | (hit_move & hit_move_mask)
   4286  */
   4287 int
   4288 th3_alpm_hit_move_update(int u, int i, int pid)
   4289 {
   4290     int rv = BCM_E_NONE;
   4291     int idx, index_cnt;
   4292     uint32 hit_cache, hit_move, hit_move_mask;
   4293     uint32 *cache_ent, *move_ent, *move_mask_ent;
   4294     soc_mem_t mem;
   4295 
   4296     if (!ALPM_HTBL_ENT_MOVED(u, i, pid)) {
   4297         return rv;
   4298     }
   4299 
   4300     mem = ALPM_HTBL_MEM(u, i, pid);
   4301     index_cnt = ALPM_HTBL_IDX_CNT(u, i, pid);
   4302 
   4303     ALPM_HTBL_ENT_MOVED_CNT(u, i, pid) = 0;
   4304     for (idx = 0; idx < index_cnt; idx++) {
   4305         move_mask_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 *,
   4306                                     ALPM_HTBL_MOVE_MASK(u, i, pid), idx);
   4307         hit_move_mask = *move_mask_ent;
   4308 
   4309         if (hit_move_mask) {
   4310             cache_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 * ,
   4311                                         ALPM_HTBL_CACHE(u, i, pid), idx);
   4312             move_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 *,
   4313                                         ALPM_HTBL_MOVE(u, i, pid), idx);
   4314             hit_cache = *cache_ent;
   4315             hit_move =  *move_ent;
   4316 
   4317             /* update cache entry */
   4318             *cache_ent = (hit_cache & ~hit_move_mask) |
   4319                             (hit_move & hit_move_mask);
   4320 
   4321             ALPM_HTBL_ENT_MOVED_CNT(u, i, pid)++;
   4322         }
   4323     }
   4324 
   4325     return rv;
   4326 }
   4327 
   4328 /* Sync ALPM non-TCAM level (i:0/1 for level 2/3) hitbit cache with Hw */
   4329 int
   4330 th3_alpm_hit_cache_sync(int u, int i, int pid)
   4331 {
   4332     soc_mem_t mem;
   4333     int idx_max, offset = 0;
   4334     int rv = BCM_E_NONE;
   4335     _alpm_cb_t *acb = (i == 0 ? ACB_TOP(u) : ACB_BTM(u));
   4336 
   4337     if (ALPM_HTBL_IDX_CNT(u, i, pid) == 0) {
   4338         return rv;
   4339     }
   4340 
   4341     mem = ALPM_HTBL_MEM(u, i, pid);
   4342     idx_max = ALPM_HTBL_IDX_CNT(u, i, pid) - 1;
   4343 
   4344     if (pid == ALPM_BKT_GLB_PID) { /* adjust physical mem table offset */
   4345         offset = ALPM_HTBL_IDX_CNT(u, i, ALPM_BKT_PRT_PID);
   4346     }
   4347 
   4348     if (ACB_HLF_BNK_MD(acb) && ALPM_HLF_BNKS(u)) {
   4349         offset = ALPM_HTBL_IDX_CNT(u, i, ALPM_BKT_PRT_PID);
   4350     }
   4351 
   4352     rv = soc_mem_read_range(u, mem, MEM_BLOCK_ANY, offset, idx_max + offset,
   4353                             ALPM_HTBL_CACHE(u, i, pid));
   4354 
   4355     return rv;
   4356 }
   4357 
   4358 /* Write ALPM non-TCAM level (i:0/1 for level 2/3) hitbit cache to Hw */
   4359 int
   4360 th3_alpm_hit_hw_write(int u, int i, int pid)
   4361 {
   4362     soc_mem_t mem;
   4363     int idx, idx_max, index, offset = 0;
   4364     uint32 hit_move, hit_move_mask, entry_data;
   4365     uint32 *cache_ent, *move_ent, *move_mask_ent;
   4366     int rv = BCM_E_NONE;
   4367     _alpm_cb_t *acb = (i == 0 ? ACB_TOP(u) : ACB_BTM(u));
   4368 
   4369     if (ALPM_HTBL_IDX_CNT(u, i, pid) == 0) {
   4370         return rv;
   4371     }
   4372 
   4373     mem = ALPM_HTBL_MEM(u, i, pid);
   4374     idx_max = ALPM_HTBL_IDX_CNT(u, i, pid) - 1;
   4375 
   4376     if (pid == ALPM_BKT_GLB_PID) { /* adjust physical mem table offset */
   4377         offset = ALPM_HTBL_IDX_CNT(u, i, ALPM_BKT_PRT_PID);
   4378     }
   4379 
   4380     if (ACB_HLF_BNK_MD(acb) && ALPM_HLF_BNKS(u)) {
   4381         offset = ALPM_HTBL_IDX_CNT(u, i, ALPM_BKT_PRT_PID);
   4382     }
   4383 
   4384     /* use DMA write for whole HIT table */
   4385     if (ALPM_HTBL_ENT_MOVED_CNT(u, i, pid) >= ALPM_HIT_DMA_THRESHOLD) {
   4386 
   4387         rv = soc_mem_write_range(u, mem, MEM_BLOCK_ALL, offset, idx_max + offset,
   4388                                  ALPM_HTBL_CACHE(u, i, pid));
   4389     } else { /* use HIT mem_read and mem_write per moved entry */
   4390 
   4391         for (idx = 0; idx <= idx_max; idx++) {
   4392 
   4393             move_mask_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 *,
   4394                                         ALPM_HTBL_MOVE_MASK(u, i, pid), idx);
   4395             hit_move_mask = *move_mask_ent;
   4396 
   4397             if (hit_move_mask) {
   4398                 move_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 *,
   4399                                             ALPM_HTBL_MOVE(u, i, pid), idx);
   4400                 hit_move =  *move_ent;
   4401 
   4402                 index = idx + offset; /* HIT entry physical index */
   4403                 /* read from Hw HIT entry data */
   4404                 rv = soc_mem_read_no_cache(u, 0, mem, 0, MEM_BLOCK_ANY,
   4405                                            index, (void *)&entry_data);
   4406                 entry_data = (entry_data & ~hit_move_mask) |
   4407                                 (hit_move & hit_move_mask);
   4408                 /* write to cache & Hw updated HIT entry data */
   4409                 rv = soc_mem_write(u, mem, MEM_BLOCK_ALL, index, (void *)&entry_data);
   4410 
   4411                 /* update again cache entry */
   4412                 cache_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 * ,
   4413                                             ALPM_HTBL_CACHE(u, i, pid), idx);
   4414                 *cache_ent = entry_data;
   4415             }
   4416         }
   4417     }
   4418 
   4419     return rv;
   4420 }
   4421 
   4422 /* Get hitbit status from a TCAM entry
   4423    (it sync to Hw periodically) */
   4424 int
   4425 th3_tcam_ent_hit_get(int u, int pkm, void *e, int sub_idx)
   4426 {
   4427     int         rv = BCM_E_NONE;
   4428     soc_field_t hit_fld[2] = {HIT0f, HIT1f};
   4429     _alpm_cb_t  *acb = ACB_TOP(u);
   4430     soc_mem_t mem = alpm_tbl[acb->pvt_tbl[pkm]];
   4431 
   4432     if (SOC_MEM_FIELD_VALID(u, mem, LWR_HIT0f)) {
   4433         hit_fld[0] = LWR_HIT0f;
   4434         hit_fld[1] = LWR_HIT1f;
   4435     }
   4436     rv = soc_mem_field32_get(u, mem, e, hit_fld[sub_idx]);
   4437 
   4438     return rv;
   4439 }
   4440 
   4441 /* Get TCAM cached hitbit status from pvt_node's tcam_idx
   4442    (it sync to Hw periodically) */
   4443 int
   4444 th3_tcam_cache_hit_get(int u, int pkm, int tcam_idx)
   4445 {
   4446     int         rv = BCM_E_NONE;
   4447     int         idx, sub_idx;
   4448     uint32      e[SOC_MAX_MEM_FIELD_WORDS];
   4449     soc_field_t hit_fld[2] = {HIT0f, HIT1f};
   4450 
   4451     _alpm_cb_t *acb = ACB_TOP(u);
   4452     soc_mem_t mem = alpm_tbl[acb->pvt_tbl[pkm]];
   4453 
   4454     if (SOC_MEM_FIELD_VALID(u, mem, LWR_HIT0f)) {
   4455         hit_fld[0] = LWR_HIT0f;
   4456         hit_fld[1] = LWR_HIT1f;
   4457     }
   4458 
   4459     if (pkm == ALPM_PKM_32B) {
   4460         /* tcam_idx = idx << 1 | sub_idx */
   4461         sub_idx = tcam_idx & 1;
   4462         idx = tcam_idx >> 1;
   4463     } else {
   4464         sub_idx = 0;
   4465         idx = tcam_idx;
   4466     }
   4467 
   4468     ALPM_IER(th3_mem_read(u, acb, acb->pvt_tbl[pkm], idx, e, FALSE));
   4469     rv = soc_mem_field32_get(u, mem, e, hit_fld[sub_idx]);
   4470     return rv;
   4471 }
   4472 
   4473 /* Sync TCAM hitbit cache tables with Hw */
   4474 int
   4475 th3_tcam_hit_cache_sync(int u)
   4476 {
   4477     soc_mem_t mem;
   4478     _alpm_cb_t *acb = ACB_TOP(u);
   4479     int pkm, tbl_sz;
   4480     int rv = BCM_E_NONE;
   4481 
   4482     for (pkm = 0; pkm < ALPM_PKM_CNT; pkm++) {
   4483 
   4484         if (ALPM_TCAM_TBL_SKIP(u, pkm)) {
   4485             continue; /* skip duplicated or invalid TCAM table */
   4486         }
   4487 
   4488         mem = alpm_tbl[acb->pvt_tbl[pkm]];
   4489         tbl_sz = th3_tcam_table_sz(u, pkm);
   4490         if (tbl_sz) {
   4491             rv = soc_mem_cache_set(u, mem, MEM_BLOCK_ANY, TRUE);
   4492         }
   4493     }
   4494 
   4495     return rv;
   4496 }
   4497 
   4498 void
   4499 th3_alpm_hit_deinit(int u)
   4500 {
   4501     int i, pid;
   4502     _alpm_cb_t *acb;
   4503 
   4504     if (ALPM_HIT_SKIP(u)) {
   4505         return;
   4506     }
   4507 
   4508     /* Dist hitbit tables deinit */
   4509     if (ALPMDH(u) != NULL) {
   4510         for (i = 0; i < ACB_CNT(u); i++) {
   4511             acb = ACB(u, i);
   4512             for (pid = 0; pid < ACB_PID_CNT(acb); pid++) {
   4513                 if (ALPM_HTBL(u, i, pid)) {
   4514                     if (ALPM_HTBL_CACHE(u, i, pid)) {
   4515                         soc_cm_sfree(u, ALPM_HTBL_CACHE(u, i, pid));
   4516                         ALPM_HTBL_CACHE(u, i, pid) = NULL;
   4517                     }
   4518                     if (ALPM_HTBL_MOVE(u, i, pid)) {
   4519                         soc_cm_sfree(u, ALPM_HTBL_MOVE(u, i, pid));
   4520                         ALPM_HTBL_MOVE(u, i, pid) = NULL;
   4521                     }
   4522                     if (ALPM_HTBL_MOVE_MASK(u, i, pid)) {
   4523                         soc_cm_sfree(u, ALPM_HTBL_MOVE_MASK(u, i, pid));
   4524                         ALPM_HTBL_MOVE_MASK(u, i, pid) = NULL;
   4525                     }
   4526                     alpm_util_free(ALPM_HTBL(u, i, pid));
   4527                     ALPM_HTBL(u, i, pid) = NULL;
   4528                 }
   4529             }
   4530         }
   4531     }
   4532 
   4533     return;
   4534 }
   4535 
   4536 /* Initialize TH3 ALPM distributed hitbit */
   4537 int
   4538 th3_alpm_hit_init(int u)
   4539 {
   4540     int rv = BCM_E_NONE;
   4541     int i, pid, index_cnt;
   4542     int alloc_sz;
   4543     soc_mem_t mem;
   4544     _alpm_cb_t *acb;
   4545 
   4546     if (ALPM_HIT_SKIP(u)) {
   4547         return rv;
   4548     }
   4549 
   4550     /* Initialize bucket Levels hitbit table ctrl */
   4551     for (i = 0; i < ACB_CNT(u); i++) {
   4552         acb = ACB(u, i);
   4553         mem = th3_alpm_hit_tbl_mem[i];
   4554         /* Current implementation is assuming that HIT table entry
   4555            is not more than 32 bits (actaully we have as maximum 16 HITBITs).
   4556            Otherwise code has to adjust (for multiple words per entry) */
   4557         assert(soc_mem_entry_words(u, mem) == 1);
   4558 
   4559         if (!SOC_WARM_BOOT(u)) {
   4560             th3_alpm_hw_mem_clear(u, mem);
   4561         }
   4562 
   4563         for (pid = 0; pid < ACB_PID_CNT(acb); pid++) {
   4564             alloc_sz = sizeof(_alpm_hit_tbl_ctrl_t);
   4565             ALPM_ALLOC_EG(ALPM_HTBL(u, i, pid), alloc_sz, "hit_tbl");
   4566 
   4567             /* logic table index counter (same for HIT table) */
   4568             index_cnt = ACB_PID_BNK_CNT(acb, pid);
   4569             alloc_sz = WORDS2BYTES(soc_mem_entry_words(u, mem)) * index_cnt;
   4570             ALPM_HTBL_MEM(u, i, pid) = mem;
   4571             ALPM_HTBL_IDX_CNT(u, i, pid) = index_cnt;
   4572             ALPM_HTBL_SIZE(u, i, pid) = alloc_sz;
   4573             ALPM_HTBL_ENT_MOVED(u, i, pid) = FALSE;
   4574             ALPM_DMA_ALLOC_EG(u, ALPM_HTBL_CACHE(u, i, pid),
   4575                               alloc_sz, "hit_cache");
   4576             ALPM_DMA_ALLOC_EG(u, ALPM_HTBL_MOVE(u, i, pid),
   4577                               alloc_sz, "hit_move");
   4578             ALPM_DMA_ALLOC_EG(u, ALPM_HTBL_MOVE_MASK(u, i, pid),
   4579                               alloc_sz, "hit_move_mask");
   4580         }
   4581     }
   4582 
   4583     return rv;
   4584 
   4585 bad:
   4586     th3_alpm_hit_deinit(u);
   4587     return rv;
   4588 }
   4589 
   4590 /* TH3 ALPM hitbit cleanup */
   4591 int
   4592 th3_alpm_hit_cleanup(int u)
   4593 {
   4594     int rv = BCM_E_NONE;
   4595     int i, pid;
   4596     int alloc_sz;
   4597     soc_mem_t mem;
   4598     _alpm_cb_t *acb;
   4599 
   4600     if (ALPM_HIT_SKIP(u)) {
   4601         return rv;
   4602     }
   4603 
   4604     for (i = 0; i < ACB_CNT(u); i++) {
   4605         acb = ACB(u, i);
   4606         mem = th3_alpm_hit_tbl_mem[i];
   4607 
   4608         if (!SOC_WARM_BOOT(u)) {
   4609             th3_alpm_hw_mem_clear(u, mem);
   4610         }
   4611 
   4612         for (pid = 0; pid < ACB_PID_CNT(acb); pid++) {
   4613 
   4614             alloc_sz = ALPM_HTBL_SIZE(u, i, pid);
   4615             sal_memset(ALPM_HTBL_CACHE(u, i, pid), 0, alloc_sz);
   4616             sal_memset(ALPM_HTBL_MOVE(u, i, pid), 0, alloc_sz);
   4617             sal_memset(ALPM_HTBL_MOVE_MASK(u, i, pid), 0, alloc_sz);
   4618 
   4619             ALPM_HTBL_ENT_MOVED(u, i, pid) = FALSE;
   4620             ALPM_HTBL_ENT_MOVED_CNT(u, i, pid) = 0;
   4621         }
   4622     }
   4623 
   4624     return rv;
   4625 }
   4626 
   4627 alpm_functions_t th3_alpm_driver = {
   4628     th3_alpm_ctrl_init,
   4629     th3_alpm_ctrl_deinit,
   4630     th3_alpm_ctrl_cleanup,
   4631     th3_alpm_bkt_bnk_copy,
   4632     th3_alpm_bkt_bnk_clear,
   4633     th3_alpm_bkt_pfx_copy,
   4634     th3_alpm_bkt_pfx_clean,
   4635     th3_alpm_bkt_pfx_shrink,
   4636     th3_alpm_bkt_bnk_write,
   4637     th3_alpm_bkt_def_fmt_get,
   4638     th3_alpm_bkt_fmt_type_get,
   4639 
   4640     th3_alpm_ent_ent_get,
   4641     th3_alpm_ent_pfx_len_get,
   4642     th3_alpm_ent_selective_get,
   4643 
   4644     /* TCAM */
   4645     th3_tcam_table_sz,
   4646     th3_tcam_hw_cleanup,
   4647     th3_tcam_entry_x_to_y,
   4648     th3_tcam_entry_from_cfg,
   4649     th3_tcam_entry_to_cfg,
   4650     th3_tcam_entry_valid,
   4651     th3_tcam_entry_valid_set,
   4652     th3_tcam_entry_vrf_id_get,
   4653     th3_tcam_entry_pfx_len_get,
   4654     th3_tcam_entry_to_key,
   4655 
   4656     th3_tcam_entry_mode_get,
   4657     th3_tcam_entry_adata_get,
   4658     th3_tcam_entry_bdata_get,
   4659 
   4660     /* TCAM/ALPM */
   4661     th3_mem_read,
   4662     th3_mem_write,
   4663 
   4664     /* HITBIT */
   4665     th3_alpm_hit_init,
   4666     th3_alpm_hit_deinit,
   4667     th3_alpm_hit_cleanup,
   4668     th3_alpm_bkt_hit_get,
   4669     th3_alpm_bkt_hit_set,
   4670     th3_alpm_bkt_hit_write,
   4671     th3_alpm_hit_move_update,
   4672     th3_alpm_hit_cache_sync,
   4673     th3_alpm_hit_hw_write,
   4674     th3_tcam_ent_hit_get,
   4675     th3_tcam_cache_hit_get,
   4676     th3_tcam_hit_cache_sync,
   4677 
   4678     /* dump table */
   4679     th3_alpm_table_dump,
   4680     th3_alpm_cap_get,
   4681 
   4682     /* index mapping */
   4683     th3_mem_phy_index_get,
   4684 };
   4685 
   4686 #endif /* ALPM_ENABLE */
   4687