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

ism.c (133225B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * ISM management routines
      8  */
      9 
     10 #include <shared/bsl.h>
     11 
     12 #include <assert.h>
     13 
     14 #include <sal/types.h>
     15 
     16 #include <soc/drv.h>
     17 #include <soc/error.h>
     18 #include <soc/util.h>
     19 #include <soc/mem.h>
     20 #include <soc/debug.h>
     21 #include <soc/cm.h>
     22 
     23 #ifdef BCM_ISM_SUPPORT
     24 
     25 typedef struct {
     26     uint8 index;
     27     uint8 bank;
     28 } _soc_ism_bank_trace_t;
     29 
     30 _soc_ism_t _soc_ism_info[SOC_MAX_NUM_DEVICES];
     31 _soc_ism_hash_t _soc_ism_hash_info[SOC_MAX_NUM_DEVICES];
     32 /* track bank usage by mem, set dynamically - used by pcid as well */
     33 uint32 _soc_ism_bank_avail[SOC_MAX_NUM_DEVICES][_SOC_ISM_MAX_BANKS];
     34 
     35 /* Physical stage/bank constructs */ 
     36 uint32 _soc_ism_bank_raw_sizes[] = {
     37     _SOC_ISM_BANK0_SIZE, _SOC_ISM_BANK1_SIZE,
     38     _SOC_ISM_BANK2_SIZE, _SOC_ISM_BANK3_SIZE, 
     39     _SOC_ISM_BANK4_SIZE,
     40     _SOC_ISM_BANK0_SIZE, _SOC_ISM_BANK1_SIZE,
     41     _SOC_ISM_BANK2_SIZE, _SOC_ISM_BANK3_SIZE, 
     42     _SOC_ISM_BANK4_SIZE,
     43     _SOC_ISM_BANK0_SIZE, _SOC_ISM_BANK1_SIZE,
     44     _SOC_ISM_BANK2_SIZE, _SOC_ISM_BANK3_SIZE, 
     45     _SOC_ISM_BANK4_SIZE,
     46     _SOC_ISM_BANK0_SIZE, _SOC_ISM_BANK1_SIZE,
     47     _SOC_ISM_BANK2_SIZE, _SOC_ISM_BANK3_SIZE, 
     48     _SOC_ISM_BANK4_SIZE
     49 };
     50 
     51 uint32 _soc_ism_bank_raw_sizes_256[] = {
     52     _SOC_ISM_256_BANK0_SIZE, _SOC_ISM_256_BANK1_SIZE,
     53     _SOC_ISM_256_BANK2_SIZE, _SOC_ISM_256_BANK3_SIZE, 
     54     _SOC_ISM_256_BANK4_SIZE,
     55     _SOC_ISM_256_BANK0_SIZE, _SOC_ISM_256_BANK1_SIZE,
     56     _SOC_ISM_256_BANK2_SIZE, _SOC_ISM_256_BANK3_SIZE, 
     57     _SOC_ISM_256_BANK4_SIZE,
     58     _SOC_ISM_256_BANK0_SIZE, _SOC_ISM_256_BANK1_SIZE,
     59     _SOC_ISM_256_BANK2_SIZE, _SOC_ISM_256_BANK3_SIZE, 
     60     _SOC_ISM_256_BANK4_SIZE,
     61     _SOC_ISM_256_BANK0_SIZE, _SOC_ISM_256_BANK1_SIZE,
     62     _SOC_ISM_256_BANK2_SIZE, _SOC_ISM_256_BANK3_SIZE, 
     63     _SOC_ISM_256_BANK4_SIZE
     64 };
     65 
     66 uint32 _soc_ism_bank_raw_sizes_256_176[] = {
     67     _SOC_ISM_256_176_BANK0_SIZE, _SOC_ISM_256_176_BANK1_SIZE,
     68     _SOC_ISM_256_176_BANK2_SIZE, _SOC_ISM_256_176_BANK3_SIZE,
     69     _SOC_ISM_256_176_BANK0_SIZE, _SOC_ISM_256_176_BANK1_SIZE,
     70     _SOC_ISM_256_176_BANK2_SIZE, _SOC_ISM_256_176_BANK3_SIZE,
     71     _SOC_ISM_256_176_BANK0_SIZE, _SOC_ISM_256_176_BANK1_SIZE,
     72     _SOC_ISM_256_176_BANK2_SIZE, _SOC_ISM_256_176_BANK3_SIZE,
     73     _SOC_ISM_256_176_BANK0_SIZE, _SOC_ISM_256_176_BANK1_SIZE,
     74     _SOC_ISM_256_176_BANK2_SIZE, _SOC_ISM_256_176_BANK3_SIZE
     75 };
     76 
     77 uint32 _soc_ism_bank_raw_sizes_256_96[] = {
     78     _SOC_ISM_256_96_BANK1_SIZE, _SOC_ISM_256_96_BANK2_SIZE, 
     79     _SOC_ISM_256_96_BANK3_SIZE, _SOC_ISM_256_96_BANK4_SIZE,
     80     _SOC_ISM_256_96_BANK1_SIZE, _SOC_ISM_256_96_BANK2_SIZE, 
     81     _SOC_ISM_256_96_BANK3_SIZE, _SOC_ISM_256_96_BANK4_SIZE,
     82     _SOC_ISM_256_96_BANK1_SIZE, _SOC_ISM_256_96_BANK2_SIZE, 
     83     _SOC_ISM_256_96_BANK3_SIZE, _SOC_ISM_256_96_BANK4_SIZE,
     84     _SOC_ISM_256_96_BANK1_SIZE, _SOC_ISM_256_96_BANK2_SIZE, 
     85     _SOC_ISM_256_96_BANK3_SIZE, _SOC_ISM_256_96_BANK4_SIZE
     86 };
     87 
     88 uint32 _soc_ism_bank_raw_sizes_256_80[] = {
     89     _SOC_ISM_256_80_BANK1_SIZE, _SOC_ISM_256_80_BANK2_SIZE, 
     90     _SOC_ISM_256_80_BANK3_SIZE, _SOC_ISM_256_80_BANK4_SIZE,
     91     _SOC_ISM_256_80_BANK1_SIZE, _SOC_ISM_256_80_BANK2_SIZE, 
     92     _SOC_ISM_256_80_BANK3_SIZE, _SOC_ISM_256_80_BANK4_SIZE,
     93     _SOC_ISM_256_80_BANK1_SIZE, _SOC_ISM_256_80_BANK2_SIZE, 
     94     _SOC_ISM_256_80_BANK3_SIZE, _SOC_ISM_256_80_BANK4_SIZE,
     95     _SOC_ISM_256_80_BANK1_SIZE, _SOC_ISM_256_80_BANK2_SIZE, 
     96     _SOC_ISM_256_80_BANK3_SIZE, _SOC_ISM_256_80_BANK4_SIZE
     97 };
     98 
     99 /* raw to real bank map */
    100 _soc_ism_real_bank_map_t _soc_ism_real_bank_map[] = {
    101         {8, {0, 1, 2, 3, 4, 5, 6, 7}},
    102         {4, {8, 9, 10, 11}},
    103         {2, {12, 13}},
    104         {1, {14}},
    105         {1, {15}},
    106         {8, {16, 17, 18, 19, 20, 21, 22, 23}},
    107         {4, {24, 25, 26, 27}},
    108         {2, {28, 29}},
    109         {1, {30}},
    110         {1, {31}},
    111         {8, {32, 33, 34, 35, 36, 37, 38, 39}},
    112         {4, {40, 41, 42, 43}},
    113         {2, {44, 45}},
    114         {1, {46}},
    115         {1, {47}},
    116         {8, {48, 49, 50, 51, 52, 53, 54, 55}},
    117         {4, {56, 57, 58, 59}},
    118         {2, {60, 61}},
    119         {1, {62}},
    120         {1, {63}}
    121 };
    122 
    123 _soc_ism_real_bank_map_t _soc_ism_real_bank_map_176[] = {
    124         {4, {0, 1, 2, 3}},
    125         {4, {8, 9, 10, 11}},
    126         {2, {12, 13}},
    127         {1, {14}},
    128         {4, {16, 17, 18, 19}},
    129         {4, {24, 25, 26, 27}},
    130         {2, {28, 29}},
    131         {1, {30}},
    132         {4, {32, 33, 34, 35}},
    133         {4, {40, 41, 42, 43}},
    134         {2, {44, 45}},
    135         {1, {46}},
    136         {4, {48, 49, 50, 51}},
    137         {4, {56, 57, 58, 59}},
    138         {2, {60, 61}},
    139         {1, {62}}
    140 };
    141 
    142 _soc_ism_real_bank_map_t _soc_ism_real_bank_map_96[] = {
    143         {2, {8, 9}},
    144         {2, {12, 13}},
    145         {1, {14}},
    146         {1, {15}},
    147         {2, {24, 25}},
    148         {2, {28, 29}},
    149         {1, {30}},
    150         {1, {31}},
    151         {2, {40, 41}},
    152         {2, {44, 45}},
    153         {1, {46}},
    154         {1, {47}},
    155         {2, {56, 57}},
    156         {2, {60, 61}},
    157         {1, {62}},
    158         {1, {63}}
    159 };
    160 
    161 _soc_ism_real_bank_map_t _soc_ism_real_bank_map_80[] = {
    162         {2, {8, 9}},
    163         {1, {12}},
    164         {1, {14}},
    165         {1, {15}},
    166         {2, {24, 25}},
    167         {1, {28}},
    168         {1, {30}},
    169         {1, {31}},
    170         {2, {40, 41}},
    171         {1, {44}},
    172         {1, {46}},
    173         {1, {47}},
    174         {2, {56, 57}},
    175         {1, {60}},
    176         {1, {62}},
    177         {1, {63}}
    178 };
    179 
    180 STATIC _soc_ism_table_index_t mem_info_entry[] = {
    181     { "VLAN_XLATE", SOC_ISM_MEM_VLAN_XLATE, 0, 2 },
    182     { "L2_ENTRY", SOC_ISM_MEM_L2_ENTRY, 1, 2 },
    183     { "L3_ENTRY", SOC_ISM_MEM_L3_ENTRY, 2, 1 },
    184     { "EP_VLAN_XLATE", SOC_ISM_MEM_EP_VLAN_XLATE, 3, 4 },
    185     { "MPLS", SOC_ISM_MEM_MPLS, 4, 2 },
    186     { "ESM_L2", SOC_ISM_MEM_ESM_L2, 5, 1 },
    187     { "ESM_L3", SOC_ISM_MEM_ESM_L3, 6, 1 },
    188     { "ESM_ACL", SOC_ISM_MEM_ESM_ACL, 7, 1 }
    189 };
    190 
    191 /* Populated dynamically */
    192 STATIC uint32 _soc_ism_table_bank_count[SOC_MAX_NUM_DEVICES]
    193                                        [_SOC_ISM_MAX_TABLES];
    194 
    195 /* Populated dynamically */
    196 STATIC uint8 _soc_ism_table_bank_config[SOC_MAX_NUM_DEVICES]
    197                   [_SOC_ISM_MAX_TABLES][_SOC_ISM_MAX_BANKS];
    198 
    199 /* Populated dynamically */
    200 STATIC uint32 _soc_ism_table_raw_bank_count[SOC_MAX_NUM_DEVICES]
    201                                            [_SOC_ISM_MAX_TABLES];
    202 
    203 /* Populated dynamically */
    204 STATIC uint32 _soc_ism_log_to_phy_map[SOC_MAX_NUM_DEVICES]
    205                 [_SOC_ISM_MAX_TABLES][_SOC_ISM_TOTAL_BANKS];
    206 
    207 /* Power Down structures */
    208 _soc_ism_pd_t _soc_ism_pd[_SOC_ISM_MAX_STAGES][_SOC_ISM_BANKS_PER_STAGE] = {
    209     {
    210         {
    211             {
    212                 { STAGE0_MEMORY_CONTROL_0r, { BANK0_PDA0f, BANK0_PDA1f, INVALIDf } },
    213                 { STAGE0_MEMORY_CONTROL_1r, { BANK0_PDA2f, BANK0_PDA3f, INVALIDf } },
    214                 { STAGE0_MEMORY_CONTROL_2r, { BANK0_PDA4f, BANK0_PDA5f, INVALIDf } },
    215                 { STAGE0_MEMORY_CONTROL_3r, { BANK0_PDA6f, BANK0_PDA7f, INVALIDf } },
    216                 { STAGE0_MEMORY_CONTROL_4r, { BANK0_PDA8f, BANK0_PDA9f, INVALIDf } },
    217                 { STAGE0_MEMORY_CONTROL_5r, { BANK0_PDA10f, BANK0_PDA11f, INVALIDf } },
    218                 { INVALIDr }
    219             },
    220             {
    221                 { STAGE0_MEMORY_CONTROL_23r, { BANK0_HIT_PDA0f, BANK0_HIT_PDA1f, INVALIDf } },
    222                 { INVALIDr }
    223             }
    224         },   
    225         {
    226             {    
    227                 { STAGE0_MEMORY_CONTROL_10r, { BANK1_PDA0f, BANK1_PDA1f, INVALIDf } },
    228                 { STAGE0_MEMORY_CONTROL_11r, { BANK1_PDA2f, BANK1_PDA3f, INVALIDf } },
    229                 { STAGE0_MEMORY_CONTROL_12r, { BANK1_PDA4f, BANK1_PDA5f, INVALIDf } },
    230                 { INVALIDr }
    231             },
    232             {
    233                 { STAGE0_MEMORY_CONTROL_25r, { BANK1_HIT_PDA0f, INVALIDf } },
    234                 { INVALIDr }
    235             }
    236         },
    237         {
    238             {
    239                 { STAGE0_MEMORY_CONTROL_15r, { BANK2_PDA0f, BANK2_PDA1f, BANK2_PDA2f, 
    240                                                BANK2_PDA3f, INVALIDf } },
    241                 { STAGE0_MEMORY_CONTROL_16r, { BANK2_PDA4f, BANK2_PDA5f, INVALIDf } },
    242                 { INVALIDr }
    243             },
    244             {
    245                 { STAGE0_MEMORY_CONTROL_26r, { BANK2_HIT_PDA0f, INVALIDf } },
    246                 { INVALIDr }
    247             }
    248         },
    249         {
    250             {
    251                 { STAGE0_MEMORY_CONTROL_19r, { BANK3_PDA0f, BANK3_PDA1f, INVALIDf } },
    252                 { INVALIDr }
    253             },
    254             {
    255                 { STAGE0_MEMORY_CONTROL_27r, { BANK3_HIT_PDA0f, INVALIDf } },
    256                 { INVALIDr }
    257             }
    258         },
    259         {
    260             {
    261                 { STAGE0_MEMORY_CONTROL_21r, { BANK4_PDA0f, BANK4_PDA1f, INVALIDf } },
    262                 { INVALIDr }
    263             },
    264             {
    265                 { STAGE0_MEMORY_CONTROL_27r, { BANK4_HIT_PDA0f, INVALIDf } },
    266                 { INVALIDr }
    267             }
    268         }
    269     },
    270     {
    271         {
    272             {
    273                 { STAGE1_MEMORY_CONTROL_0r, { BANK0_PDA0f, BANK0_PDA1f, INVALIDf } },
    274                 { STAGE1_MEMORY_CONTROL_1r, { BANK0_PDA2f, BANK0_PDA3f, INVALIDf } },
    275                 { STAGE1_MEMORY_CONTROL_2r, { BANK0_PDA4f, BANK0_PDA5f, INVALIDf } },
    276                 { STAGE1_MEMORY_CONTROL_3r, { BANK0_PDA6f, BANK0_PDA7f, INVALIDf } },
    277                 { STAGE1_MEMORY_CONTROL_4r, { BANK0_PDA8f, BANK0_PDA9f, INVALIDf } },
    278                 { STAGE1_MEMORY_CONTROL_5r, { BANK0_PDA10f, BANK0_PDA11f, INVALIDf } },
    279                 { INVALIDr }
    280             },
    281             {
    282                 { STAGE1_MEMORY_CONTROL_23r, { BANK0_HIT_PDA0f, BANK0_HIT_PDA1f, INVALIDf } },
    283                 { INVALIDr }
    284             }
    285         },   
    286         {
    287             {    
    288                 { STAGE1_MEMORY_CONTROL_10r, { BANK1_PDA0f, BANK1_PDA1f, INVALIDf } },
    289                 { STAGE1_MEMORY_CONTROL_11r, { BANK1_PDA2f, BANK1_PDA3f, INVALIDf } },
    290                 { STAGE1_MEMORY_CONTROL_12r, { BANK1_PDA4f, BANK1_PDA5f, INVALIDf } },
    291                 { INVALIDr }
    292             },
    293             {
    294                 { STAGE1_MEMORY_CONTROL_25r, { BANK1_HIT_PDA0f, INVALIDf } },
    295                 { INVALIDr }
    296             }
    297         },
    298         {
    299             {
    300                 { STAGE1_MEMORY_CONTROL_15r, { BANK2_PDA0f, BANK2_PDA1f, BANK2_PDA2f, 
    301                                                BANK2_PDA3f, INVALIDf } },
    302                 { STAGE1_MEMORY_CONTROL_16r, { BANK2_PDA4f, BANK2_PDA5f, INVALIDf } },
    303                 { INVALIDr }
    304             },
    305             {
    306                 { STAGE1_MEMORY_CONTROL_26r, { BANK2_HIT_PDA0f, INVALIDf } },
    307                 { INVALIDr }
    308             }
    309         },
    310         {
    311             {
    312                 { STAGE1_MEMORY_CONTROL_19r, { BANK3_PDA0f, BANK3_PDA1f, INVALIDf } },
    313                 { INVALIDr }
    314             },
    315             {
    316                 { STAGE1_MEMORY_CONTROL_27r, { BANK3_HIT_PDA0f, INVALIDf } },
    317                 { INVALIDr }
    318             }
    319         },
    320         {
    321             {
    322                 { STAGE1_MEMORY_CONTROL_21r, { BANK4_PDA0f, BANK4_PDA1f, INVALIDf } },
    323                 { INVALIDr }
    324             },
    325             {
    326                 { STAGE1_MEMORY_CONTROL_27r, { BANK4_HIT_PDA0f, INVALIDf } },
    327                 { INVALIDr }
    328             }
    329         }
    330     },
    331     {
    332         {
    333             {
    334                 { STAGE2_MEMORY_CONTROL_0r, { BANK0_PDA0f, BANK0_PDA1f, INVALIDf } },
    335                 { STAGE2_MEMORY_CONTROL_1r, { BANK0_PDA2f, BANK0_PDA3f, INVALIDf } },
    336                 { STAGE2_MEMORY_CONTROL_2r, { BANK0_PDA4f, BANK0_PDA5f, INVALIDf } },
    337                 { STAGE2_MEMORY_CONTROL_3r, { BANK0_PDA6f, BANK0_PDA7f, INVALIDf } },
    338                 { STAGE2_MEMORY_CONTROL_4r, { BANK0_PDA8f, BANK0_PDA9f, INVALIDf } },
    339                 { STAGE2_MEMORY_CONTROL_5r, { BANK0_PDA10f, BANK0_PDA11f, INVALIDf } },
    340                 { INVALIDr }
    341             },
    342             {
    343                 { STAGE2_MEMORY_CONTROL_23r, { BANK0_HIT_PDA0f, BANK0_HIT_PDA1f, INVALIDf } },
    344                 { INVALIDr }
    345             }
    346         },   
    347         {
    348             {    
    349                 { STAGE2_MEMORY_CONTROL_10r, { BANK1_PDA0f, BANK1_PDA1f, INVALIDf } },
    350                 { STAGE2_MEMORY_CONTROL_11r, { BANK1_PDA2f, BANK1_PDA3f, INVALIDf } },
    351                 { STAGE2_MEMORY_CONTROL_12r, { BANK1_PDA4f, BANK1_PDA5f, INVALIDf } },
    352                 { INVALIDr }
    353             },
    354             {
    355                 { STAGE2_MEMORY_CONTROL_25r, { BANK1_HIT_PDA0f, INVALIDf } },
    356                 { INVALIDr }
    357             }
    358         },
    359         {
    360             {
    361                 { STAGE2_MEMORY_CONTROL_15r, { BANK2_PDA0f, BANK2_PDA1f, BANK2_PDA2f, 
    362                                                BANK2_PDA3f, INVALIDf } },
    363                 { STAGE2_MEMORY_CONTROL_16r, { BANK2_PDA4f, BANK2_PDA5f, INVALIDf } },
    364                 { INVALIDr }
    365             },
    366             {
    367                 { STAGE2_MEMORY_CONTROL_26r, { BANK2_HIT_PDA0f, INVALIDf } },
    368                 { INVALIDr }
    369             }
    370         },
    371         {
    372             {
    373                 { STAGE2_MEMORY_CONTROL_19r, { BANK3_PDA0f, BANK3_PDA1f, INVALIDf } },
    374                 { INVALIDr }
    375             },
    376             {
    377                 { STAGE2_MEMORY_CONTROL_27r, { BANK3_HIT_PDA0f, INVALIDf } },
    378                 { INVALIDr }
    379             }
    380         },
    381         {
    382             {
    383                 { STAGE2_MEMORY_CONTROL_21r, { BANK4_PDA0f, BANK4_PDA1f, INVALIDf } },
    384                 { INVALIDr }
    385             },
    386             {
    387                 { STAGE2_MEMORY_CONTROL_27r, { BANK4_HIT_PDA0f, INVALIDf } },
    388                 { INVALIDr }
    389             }
    390         }
    391     },
    392     {
    393         {
    394             {
    395                 { STAGE3_MEMORY_CONTROL_0r, { BANK0_PDA0f, BANK0_PDA1f, INVALIDf } },
    396                 { STAGE3_MEMORY_CONTROL_1r, { BANK0_PDA2f, BANK0_PDA3f, INVALIDf } },
    397                 { STAGE3_MEMORY_CONTROL_2r, { BANK0_PDA4f, BANK0_PDA5f, INVALIDf } },
    398                 { STAGE3_MEMORY_CONTROL_3r, { BANK0_PDA6f, BANK0_PDA7f, INVALIDf } },
    399                 { STAGE3_MEMORY_CONTROL_4r, { BANK0_PDA8f, BANK0_PDA9f, INVALIDf } },
    400                 { STAGE3_MEMORY_CONTROL_5r, { BANK0_PDA10f, BANK0_PDA11f, INVALIDf } },
    401                 { INVALIDr }
    402             },
    403             {
    404                 { STAGE3_MEMORY_CONTROL_23r, { BANK0_HIT_PDA0f, BANK0_HIT_PDA1f, INVALIDf } },
    405                 { INVALIDr }
    406             }
    407         },   
    408         {
    409             {    
    410                 { STAGE3_MEMORY_CONTROL_10r, { BANK1_PDA0f, BANK1_PDA1f, INVALIDf } },
    411                 { STAGE3_MEMORY_CONTROL_11r, { BANK1_PDA2f, BANK1_PDA3f, INVALIDf } },
    412                 { STAGE3_MEMORY_CONTROL_12r, { BANK1_PDA4f, BANK1_PDA5f, INVALIDf } },
    413                 { INVALIDr }
    414             },
    415             {
    416                 { STAGE3_MEMORY_CONTROL_25r, { BANK1_HIT_PDA0f, INVALIDf } },
    417                 { INVALIDr }
    418             }
    419         },
    420         {
    421             {
    422                 { STAGE3_MEMORY_CONTROL_15r, { BANK2_PDA0f, BANK2_PDA1f, BANK2_PDA2f, 
    423                                                BANK2_PDA3f, INVALIDf } },
    424                 { STAGE3_MEMORY_CONTROL_16r, { BANK2_PDA4f, BANK2_PDA5f, INVALIDf } },
    425                 { INVALIDr }
    426             },
    427             {
    428                 { STAGE3_MEMORY_CONTROL_26r, { BANK2_HIT_PDA0f, INVALIDf } },
    429                 { INVALIDr }
    430             }
    431         },
    432         {
    433             {
    434                 { STAGE3_MEMORY_CONTROL_19r, { BANK3_PDA0f, BANK3_PDA1f, INVALIDf } },
    435                 { INVALIDr }
    436             },
    437             {
    438                 { STAGE3_MEMORY_CONTROL_27r, { BANK3_HIT_PDA0f, INVALIDf } },
    439                 { INVALIDr }
    440             }
    441         },
    442         {
    443             {
    444                 { STAGE3_MEMORY_CONTROL_21r, { BANK4_PDA0f, BANK4_PDA1f, INVALIDf } },
    445                 { INVALIDr }
    446             },
    447             {
    448                 { STAGE3_MEMORY_CONTROL_27r, { BANK4_HIT_PDA0f, INVALIDf } },
    449                 { INVALIDr }
    450             }
    451         }
    452     }
    453 };
    454 
    455 /*
    456  * Macro used by memory accessor functions to fix order
    457  */
    458 #define FIX_MEM_ORDER_E(v,m) (((m)->flags & SOC_MEM_FLAG_BE) ? \
    459                                 BYTES2WORDS((m)->bytes)-1-(v) : \
    460                                 (v))
    461 
    462 /* helper routine */
    463 int
    464 soc_ism_get_hash_mem_idx(int unit, soc_mem_t mem)
    465 {
    466     int8 i;
    467     for (i = 0; i < _SOC_ISM_MAX_ISM_MEMS; i++) {
    468          if (mem == _SOC_ISM_MEMS(unit)[i].mem) {
    469              return i;
    470          }
    471     }
    472     return SOC_E_PARAM;
    473 }
    474 
    475 /* helper routine */
    476 int 
    477 soc_ism_table_to_index(uint32 mem) 
    478 {
    479     int i, idx = -1;
    480     for (i = 0; i < COUNTOF(mem_info_entry); i++) {
    481         if (mem == mem_info_entry[i].mem) {
    482             idx = mem_info_entry[i].index;
    483             break;
    484         }
    485     }
    486     return idx;
    487 }
    488 
    489 /* helper routine */
    490 char *
    491 soc_ism_table_to_name(uint32 mem)
    492 {
    493     int i;
    494     for (i = 0; i < COUNTOF(mem_info_entry); i++) {
    495         if (mem == mem_info_entry[i].mem) {
    496             return mem_info_entry[i].name;
    497             break;
    498         }
    499     }
    500     return NULL;
    501 }
    502 
    503 /* Fill _soc_ism_log_to_phy_map based upon _soc_ism_table_bank_config */
    504 STATIC int
    505 soc_ism_log_to_phy_fill(int unit)
    506 {
    507     int32 tab, b, c, r;
    508     int8 bank;
    509     for (tab = 0; tab < _SOC_ISM_MAX_TABLES; tab++) {
    510         r = 0;
    511         for (b = 0; b < SOC_ISM_INFO(unit)->max_banks; b++) {
    512             bank = ((b%_SOC_ISM_MAX_STAGES) * 
    513                     SOC_ISM_INFO(unit)->banks_per_stage) + 
    514                    (b/_SOC_ISM_MAX_STAGES);
    515             if (_soc_ism_table_bank_config[unit][tab][bank]) {
    516                 for (c = 0; c < 
    517                      SOC_ISM_INFO(unit)->real_bank_map[bank].count; c++) {
    518                     _soc_ism_log_to_phy_map[unit][tab][r] = 
    519                        SOC_ISM_INFO(unit)->real_bank_map[bank].index[c];
    520                     r++;
    521                 }
    522                 _soc_ism_table_raw_bank_count[unit][tab] += 
    523                     SOC_ISM_INFO(unit)->real_bank_map[bank].count;
    524                 if (_soc_ism_table_raw_bank_count[unit][tab] >
    525                     SOC_ISM_INFO(unit)->total_banks) {
    526                     return SOC_E_PARAM;
    527                 } 
    528             }
    529         }
    530     }
    531     return SOC_E_NONE;
    532 }
    533 
    534 STATIC soc_mem_t _ism_log_to_phy_mem[] = {
    535     TABLE0_LOG_TO_PHY_MAPm, TABLE1_LOG_TO_PHY_MAPm,
    536     TABLE2_LOG_TO_PHY_MAPm, TABLE3_LOG_TO_PHY_MAPm,
    537     TABLE4_LOG_TO_PHY_MAPm
    538 };
    539 
    540 /* Write _soc_ism_log_to_phy_map to TABLEx_LOG_TO_PHY_MAPm */
    541 STATIC int
    542 soc_ism_log_to_phy_set(int unit)
    543 {
    544     int tab, bank;
    545     uint32 entry[SOC_MAX_MEM_WORDS];
    546     for (tab = 0; tab < _SOC_ISM_MAX_TABLES; tab++) {
    547         LOG_INFO(BSL_LS_SOC_SOCMEM,
    548                  (BSL_META_U(unit,
    549                              "Table: %d\n"), tab));
    550         for (bank = 0; bank < SOC_ISM_INFO(unit)->total_banks; bank++) {
    551             LOG_INFO(BSL_LS_SOC_SOCMEM,
    552                      (BSL_META_U(unit,
    553                                  "[%d]-%d "), bank, 
    554                       _soc_ism_log_to_phy_map[unit][tab][bank]));
    555             sal_memset(&entry, 0, sizeof(entry));
    556             soc_mem_field32_set(unit, _ism_log_to_phy_mem[tab], entry,
    557                                 LOG_TO_PHY_MAPf, 
    558                                 _soc_ism_log_to_phy_map[unit][tab][bank]);
    559             /* Write to TABLEx_LOG_TO_PHY_MAPm memory */
    560             SOC_IF_ERROR_RETURN
    561                 (soc_mem_write(unit, _ism_log_to_phy_mem[tab], 
    562                                MEM_BLOCK_ALL, bank, &entry));
    563         }        
    564         LOG_INFO(BSL_LS_SOC_SOCMEM,
    565                  (BSL_META_U(unit,
    566                              "\n")));
    567     }
    568     return SOC_E_NONE;
    569 }
    570 
    571 soc_reg_t _ism_table_bank_cfg_reg[] = {
    572     TABLE0_BANK_CONFIGr, TABLE1_BANK_CONFIGr,
    573     TABLE2_BANK_CONFIGr, TABLE3_BANK_CONFIGr,
    574     TABLE4_BANK_CONFIGr
    575 };
    576 
    577 soc_field_t _ism_table_bank_cfg_fld[] = {
    578     STAGE0_BANKSf, STAGE1_BANKSf,
    579     STAGE2_BANKSf, STAGE3_BANKSf
    580 };
    581 
    582 /* Write _soc_ism_table_bank_config to TABLEx_BANK_CONFIG registers */
    583 STATIC int 
    584 soc_ism_table_bank_set(int unit)
    585 {
    586     int tab, stg, bank, offset;
    587     uint32 rval, val;
    588     for (tab = 0; tab < _SOC_ISM_MAX_TABLES; tab++) {
    589         if (!_soc_ism_table_bank_count[unit][tab]) {
    590             continue;
    591         }
    592         LOG_INFO(BSL_LS_SOC_SOCMEM,
    593                  (BSL_META_U(unit,
    594                              "Table: %d\n"), tab));
    595         SOC_IF_ERROR_RETURN
    596         (soc_reg32_get(unit, _ism_table_bank_cfg_reg[tab], REG_PORT_ANY, 
    597                        0, &rval));
    598         for (stg = 0; stg < _SOC_ISM_MAX_STAGES; stg++) {
    599             val = 0;
    600             /* Take disabled bank into account */
    601             offset = ((SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_96) || 
    602                       (SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_80)) ? 
    603                       ((SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_64) ? 2 : 1) : 0;
    604             for (bank = 0; bank < SOC_ISM_INFO(unit)->banks_per_stage; bank++) {
    605                 val |= _soc_ism_table_bank_config[unit][tab]
    606                       [(stg*SOC_ISM_INFO(unit)->banks_per_stage)+bank] << (bank + offset);
    607             }
    608             LOG_INFO(BSL_LS_SOC_SOCMEM,
    609                      (BSL_META_U(unit,
    610                                  "stage: %d - bmask: %x "), stg, val));
    611             
    612             soc_reg_field_set(unit, _ism_table_bank_cfg_reg[tab], 
    613                               &rval, _ism_table_bank_cfg_fld[stg],
    614                               val);
    615         }
    616         if (SOC_ISM_INFO(unit)->ism_mode != _ISM_SIZE_MODE_512) {
    617             soc_reg_field_set(unit, _ism_table_bank_cfg_reg[tab], 
    618                               &rval, MAPPING_MODEf, 1);
    619         }
    620         /* Write to TABLEx_BANK_CONFIG register */
    621         SOC_IF_ERROR_RETURN
    622             (soc_reg32_set(unit, _ism_table_bank_cfg_reg[tab], 
    623                            REG_PORT_ANY, 0, rval));
    624         LOG_INFO(BSL_LS_SOC_SOCMEM,
    625                  (BSL_META_U(unit,
    626                              "\n")));
    627     }
    628     return SOC_E_NONE;
    629 }
    630 
    631 /* helper routine to sort and prioritize mem types based upon allocation rules */
    632 STATIC void
    633 _soc_ism_sort_mems(soc_ism_mem_size_config_t *i_mem_cfg, int count,
    634                       soc_ism_mem_size_config_t *o_mem_cfg)
    635 {
    636     int i, j, esm = 0, ism = 0;
    637     soc_ism_mem_size_config_t tmp;
    638     soc_ism_mem_size_config_t arr[SOC_ISM_MEM_TOTAL];
    639     
    640     sal_memset(o_mem_cfg, 0, 
    641                sizeof(soc_ism_mem_size_config_t) * SOC_ISM_MEM_TOTAL);
    642     sal_memcpy(o_mem_cfg, i_mem_cfg, 
    643                sizeof(soc_ism_mem_size_config_t) * count);
    644     if (count == 1) {
    645         return;
    646     }
    647     /* Search for and fetch ESM mems */
    648     for (i = 0; i < count; i++) {
    649         if (i_mem_cfg[i].mem >= SOC_ISM_MEM_MAX) {
    650             arr[esm] = i_mem_cfg[i];
    651             esm++;
    652         }
    653     }
    654     if (esm) {
    655         /* sort esm mems */
    656         for (i = 0; i < esm; i++) {
    657             for (j = 0; j < esm - i - 1; j++) {
    658                 if (arr[j].size < arr[j+1].size) {
    659                     sal_memcpy(&tmp, &arr[j], 
    660                                sizeof(soc_ism_mem_size_config_t));
    661                     sal_memcpy(&arr[j], &arr[j+1],
    662                                sizeof(soc_ism_mem_size_config_t));
    663                     sal_memcpy(&arr[j+1], &tmp,
    664                                sizeof(soc_ism_mem_size_config_t));
    665                 }
    666             }
    667         }
    668         /* copy back sorted esm mems */
    669         sal_memcpy(o_mem_cfg, arr, 
    670                    sizeof(soc_ism_mem_size_config_t) * esm);
    671         if ((count - esm) == 0) {
    672             return;
    673         }
    674     }
    675     /* Search for and fetch ISM mems */
    676     for (i = 0; i < count; i++) {
    677         if (i_mem_cfg[i].mem < SOC_ISM_MEM_MAX) {
    678             arr[ism] = i_mem_cfg[i];
    679             ism++;
    680         }
    681     }
    682     if (ism) {
    683         /* sort ism mems */
    684         for (i = 0; i < ism; i++) {
    685             for (j = 0; j < ism - i - 1; j++) {
    686                 if (arr[j].size < arr[j+1].size) {
    687                     sal_memcpy(&tmp, &arr[j], 
    688                                sizeof(soc_ism_mem_size_config_t));
    689                     sal_memcpy(&arr[j], &arr[j+1],
    690                                sizeof(soc_ism_mem_size_config_t));
    691                     sal_memcpy(&arr[j+1], &tmp,
    692                                sizeof(soc_ism_mem_size_config_t));
    693                 }
    694             }
    695         }
    696         /* copy back sorted esm mems */
    697         sal_memcpy(&o_mem_cfg[esm], arr, 
    698                    sizeof(soc_ism_mem_size_config_t) * ism);
    699     }
    700 }
    701 
    702 uint32
    703 _soc_ism_bank_total(int unit)
    704 {
    705     uint8 i;
    706     uint32 total = 0;
    707     for (i = 0; i < SOC_ISM_INFO(unit)->max_banks; i++) {
    708         total += SOC_ISM_INFO(unit)->bank_raw_sizes[i];
    709     }
    710     return total;
    711 }
    712 
    713 /* helper routine to sort and prioritize mem types based upon allocation rules */
    714 STATIC void
    715 _soc_ism_sort_mems_with_banks(int unit, soc_ism_mem_size_config_t *i_mem_cfg, int count,
    716                       soc_ism_mem_size_config_t *o_mem_cfg)
    717 {
    718     int i, j, esm = 0, ism = 0, ism_banks = 0;
    719     soc_ism_mem_size_config_t tmp;
    720     soc_ism_mem_size_config_t arr[SOC_ISM_MEM_TOTAL];
    721     int c_midx = -1, n_midx = -1;
    722     int c_epb, n_epb;
    723 
    724     sal_memset(o_mem_cfg, 0,
    725                sizeof(soc_ism_mem_size_config_t) * SOC_ISM_MEM_TOTAL);
    726     if (count == 1) {
    727         sal_memcpy(o_mem_cfg, i_mem_cfg,
    728                    sizeof(soc_ism_mem_size_config_t) * count);
    729         return;
    730     }
    731     /* Search for and fetch ESM mems */
    732     for (i = 0; i < count; i++) {
    733         if (i_mem_cfg[i].mem >= SOC_ISM_MEM_MAX) {
    734             arr[esm] = i_mem_cfg[i];
    735             esm++;
    736         }
    737     }
    738     if (esm) {
    739         /* sort esm mems */
    740         for (i = 0; i < esm; i++) {
    741             for (j = 0; j < esm - i - 1; j++) {
    742                 if (arr[j].size < arr[j+1].size) {
    743                     sal_memcpy(&tmp, &arr[j],
    744                                sizeof(soc_ism_mem_size_config_t));
    745                     sal_memcpy(&arr[j], &arr[j+1],
    746                                sizeof(soc_ism_mem_size_config_t));
    747                     sal_memcpy(&arr[j+1], &tmp,
    748                                sizeof(soc_ism_mem_size_config_t));
    749                 }
    750             }
    751         }
    752         /* copy back sorted esm mems */
    753         sal_memcpy(o_mem_cfg, arr,
    754                    sizeof(soc_ism_mem_size_config_t) * esm);
    755         if ((count - esm) == 0) {
    756             return;
    757         }
    758     }
    759     /* Search for and fetch ISM mems with banks */
    760     for (i = 0; i < count; i++) {
    761         if ((i_mem_cfg[i].mem < SOC_ISM_MEM_MAX) &&
    762                 i_mem_cfg[i].banks) {
    763             arr[ism_banks] = i_mem_cfg[i];
    764             ism_banks++;
    765         }
    766     }
    767     if (ism_banks) {
    768         /* sort ism mems with banks */
    769         for (i = 0; i < ism_banks; i++) {
    770             for (j = 0; j < ism_banks - i - 1; j++) {
    771                 c_midx = soc_ism_table_to_index(arr[j].mem);
    772                 n_midx = soc_ism_table_to_index(arr[j + 1].mem);
    773                 if ((c_midx >= 0) && (n_midx >= 0)) {
    774                     c_epb = mem_info_entry[c_midx].epb;
    775                     n_epb = mem_info_entry[n_midx].epb;
    776                 } else {
    777                     c_epb = n_epb = 1;
    778                 }
    779                 if ((arr[j].size / c_epb) < (arr[j+1].size / n_epb)) {
    780                     sal_memcpy(&tmp, &arr[j],
    781                                sizeof(soc_ism_mem_size_config_t));
    782                     sal_memcpy(&arr[j], &arr[j+1],
    783                                sizeof(soc_ism_mem_size_config_t));
    784                     sal_memcpy(&arr[j+1], &tmp,
    785                                sizeof(soc_ism_mem_size_config_t));
    786                 }
    787             }
    788         }
    789         /* copy back sorted ism mems with banks */
    790         sal_memcpy(&o_mem_cfg[esm], arr,
    791                    sizeof(soc_ism_mem_size_config_t) * ism_banks);
    792         if ((count - esm - ism_banks) == 0) {
    793             return;
    794         }
    795     }
    796     /* Search for and fetch ISM mems */
    797     for (i = 0; i < count; i++) {
    798         if ((i_mem_cfg[i].mem < SOC_ISM_MEM_MAX) &&
    799                 !i_mem_cfg[i].banks) {
    800             arr[ism] = i_mem_cfg[i];
    801             ism++;
    802         }
    803     }
    804     if (ism) {
    805         /* sort ism mems */
    806         for (i = 0; i < ism; i++) {
    807             for (j = 0; j < ism - i - 1; j++) {
    808                 c_midx = soc_ism_table_to_index(arr[j].mem);
    809                 n_midx = soc_ism_table_to_index(arr[j + 1].mem);
    810                 if ((c_midx >= 0) && (n_midx >= 0)) {
    811                     c_epb = mem_info_entry[c_midx].epb;
    812                     n_epb = mem_info_entry[n_midx].epb;
    813                 } else {
    814                     c_epb = n_epb = 1;
    815                 }
    816                 if ((arr[j].size / c_epb) < (arr[j+1].size / n_epb)) {
    817                     sal_memcpy(&tmp, &arr[j],
    818                                sizeof(soc_ism_mem_size_config_t));
    819                     sal_memcpy(&arr[j], &arr[j+1],
    820                                sizeof(soc_ism_mem_size_config_t));
    821                     sal_memcpy(&arr[j+1], &tmp,
    822                                sizeof(soc_ism_mem_size_config_t));
    823                 }
    824             }
    825         }
    826         /* copy back sorted ism mems */
    827         sal_memcpy(&o_mem_cfg[esm + ism_banks], arr,
    828                    sizeof(soc_ism_mem_size_config_t) * ism);
    829     }
    830 }
    831 
    832 STATIC int
    833 _soc_ism_mem_allocation_log(int unit, soc_ism_mem_size_config_t *ism_hash_tables, int count)
    834 {
    835     int tab, idx, bank = 0;
    836     int midx;
    837     uint32 mem;
    838     for (tab = 0; tab < count && tab < SOC_ISM_MEM_TOTAL; tab++) {
    839         mem = ism_hash_tables[tab].mem;
    840         midx = soc_ism_table_to_index(mem);
    841         if (midx == -1) {
    842             return SOC_E_PARAM;
    843         }
    844         for (idx = 0; idx < SOC_ISM_INFO(unit)->max_banks; idx++) {
    845             bank = ((idx%_SOC_ISM_MAX_STAGES) *
    846                     SOC_ISM_INFO(unit)->banks_per_stage) +
    847                     (idx/_SOC_ISM_MAX_STAGES);
    848             if (mem == _soc_ism_bank_avail[unit][bank]) {
    849                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
    850                         (BSL_META_U(unit,
    851                                   "Allocated bank %d for ISM mem:[%s], size:%d banksize :%d\n"),
    852                          bank,
    853                          soc_ism_table_to_name(ism_hash_tables[tab].mem),
    854                          ism_hash_tables[tab].size,
    855                          SOC_ISM_INFO(unit)->bank_raw_sizes[bank]));
    856             }
    857         }
    858     }
    859     return SOC_E_NONE;
    860 
    861 }
    862 
    863 int
    864 soc_ism_mem_config_with_banks(int unit, soc_ism_mem_size_config_t *mem_cfg, int count)
    865 {
    866     int tab, idx, bank = 0, next_bank;
    867     int midx, size, rem;
    868     uint32 mem;
    869     uint8 avail, undo_flag = FALSE, i;
    870     soc_ism_mem_size_config_t ism_hash_tables[SOC_ISM_MEM_TOTAL];
    871     soc_persist_t *sop = SOC_PERSIST(unit);
    872     uint32 total_size = 0, min_bank_size;
    873     uint32 total_banks = 0;
    874     _soc_ism_bank_trace_t bank_trace[SOC_ISM_MEM_TOTAL][_SOC_ISM_MAX_BANKS];
    875     uint32 orig_mem_size[SOC_ISM_MEM_TOTAL];
    876 
    877     total_banks = soc_property_get(unit, spn_VLAN_XLATE_MEM_BANKS, 0) +
    878                   soc_property_get(unit, spn_L2_MEM_BANKS, 0) +
    879                   soc_property_get(unit, spn_L3_MEM_BANKS, 0) +
    880                   soc_property_get(unit, spn_EGR_VLAN_XLATE_MEM_BANKS, 0) +
    881                   soc_property_get(unit, spn_MPLS_MEM_BANKS, 0);
    882     if (total_banks > SOC_ISM_INFO(unit)->max_banks) {
    883         LOG_ERROR(BSL_LS_SOC_COMMON,
    884                 (BSL_META_U(unit,
    885                             "Total requested banks[R:%d A:%d]\n"),
    886                             total_banks, SOC_ISM_INFO(unit)->max_banks));
    887         return SOC_E_PARAM;
    888     }
    889 
    890 
    891     _soc_ism_sort_mems_with_banks(unit, mem_cfg, count, ism_hash_tables);
    892 
    893     /* Get the min bank size available
    894      * Last bank is the smallest bank
    895      */
    896     bank = SOC_ISM_INFO(unit)->max_banks - 1;
    897     min_bank_size = SOC_ISM_INFO(unit)->bank_raw_sizes[bank];
    898 
    899     for (tab = 0; tab < count && tab < SOC_ISM_MEM_TOTAL; tab++) {
    900         mem = ism_hash_tables[tab].mem;
    901         midx = soc_ism_table_to_index(mem);
    902         if (midx == -1) {
    903             return SOC_E_PARAM;
    904         }
    905         /* Normalize mem entries */
    906         size = ism_hash_tables[tab].size / mem_info_entry[midx].epb;
    907         rem = size % _SOC_ISM_ENTRY_SIZE_QUANTA;
    908         if (rem) {
    909             size = size + (_SOC_ISM_ENTRY_SIZE_QUANTA - rem);
    910             LOG_VERBOSE(BSL_LS_SOC_COMMON,
    911                         (BSL_META_U(unit,
    912                                 "Updated size %s: %d\n"),
    913                          soc_ism_table_to_name(mem), size * mem_info_entry[midx].epb));
    914         }
    915         ism_hash_tables[tab].size = size * mem_info_entry[midx].epb;
    916         /* Requested avg bank size should be atleast min bank size */
    917         if (ism_hash_tables[tab].banks &&
    918             ((size / ism_hash_tables[tab].banks) < min_bank_size)) {
    919             LOG_ERROR(BSL_LS_SOC_COMMON,
    920                     (BSL_META_U(unit,
    921                                 "Avg size bank[%d] should be atleast min bank size[%d] for mem: %s\n"),
    922                      (size / ism_hash_tables[tab].banks), min_bank_size,
    923                      soc_ism_table_to_name(mem)));
    924             return SOC_E_PARAM;
    925         }
    926         total_size += size;
    927         orig_mem_size[tab] = ism_hash_tables[tab].size;
    928         LOG_VERBOSE(BSL_LS_SOC_COMMON,
    929                     (BSL_META_U(unit,
    930                                 "ISM Normalized mem: [%s], size: %d\n"),
    931                      soc_ism_table_to_name(ism_hash_tables[tab].mem),
    932                      ism_hash_tables[tab].size));
    933     }
    934 
    935     /* Sanity check */
    936     if (total_size > _soc_ism_bank_total(unit)) {
    937         LOG_ERROR(BSL_LS_SOC_COMMON,
    938                 (BSL_META_U(unit,
    939                             "Total requested size is more than available[R:%d A:%d\n"),
    940                             total_size, _soc_ism_bank_total(unit)));
    941         return SOC_E_PARAM;
    942     }
    943 
    944     avail = SOC_ISM_INFO(unit)->max_banks;
    945     tab = 0;
    946     idx = 0;
    947     sal_memset(bank_trace, 0, sizeof(_soc_ism_bank_trace_t) * SOC_ISM_MEM_TOTAL *_SOC_ISM_MAX_BANKS);
    948 
    949     while (tab < count && tab < SOC_ISM_MEM_TOTAL) {
    950         mem = ism_hash_tables[tab].mem;
    951         midx = soc_ism_table_to_index(mem);
    952         if (midx == -1) {
    953             return SOC_E_PARAM;
    954         }
    955 
    956         if (!ism_hash_tables[tab].size) {
    957             tab++;
    958             continue;
    959         }
    960 
    961         size = ism_hash_tables[tab].size / mem_info_entry[midx].epb;
    962         if (undo_flag && ism_hash_tables[tab].allocated_banks) {
    963             /* Update remaining size based on previous allocation */
    964             for (i = 0; i < ism_hash_tables[tab].allocated_banks ; i++) {
    965                 bank = bank_trace[tab][i].bank;
    966                 size -= SOC_ISM_INFO(unit)->bank_raw_sizes[bank];
    967             }
    968             undo_flag = FALSE;
    969             idx = bank_trace[tab][ism_hash_tables[tab].allocated_banks - 1].index;
    970             bank = bank_trace[tab][ism_hash_tables[tab].allocated_banks - 1].bank;
    971             ism_hash_tables[tab].allocated_banks--;
    972             _soc_ism_bank_avail[unit][bank] = 0;
    973             /* ISM mem only */
    974             if (mem < SOC_ISM_MEM_MAX) {
    975                 _soc_ism_table_bank_count[unit][midx]--;
    976                 _soc_ism_table_bank_config[unit][midx][bank] = 0;
    977             }
    978             size += SOC_ISM_INFO(unit)->bank_raw_sizes[bank];
    979             idx++;
    980             avail++;
    981             /* Find next bank size is other than rolled back value */
    982             while( idx < SOC_ISM_INFO(unit)->max_banks) {
    983                 next_bank = ((idx%_SOC_ISM_MAX_STAGES) *
    984                         SOC_ISM_INFO(unit)->banks_per_stage) + (idx/_SOC_ISM_MAX_STAGES);
    985 
    986                 if (!(_soc_ism_bank_avail[unit][next_bank] ||
    987                             (SOC_ISM_INFO(unit)->bank_raw_sizes[bank] == SOC_ISM_INFO(unit)->bank_raw_sizes[next_bank]))) {
    988                     break;
    989                 }
    990                 idx++;
    991             }
    992         }
    993         do {
    994             for (; idx < SOC_ISM_INFO(unit)->max_banks; idx++) {
    995                 bank = ((idx%_SOC_ISM_MAX_STAGES) *
    996                         SOC_ISM_INFO(unit)->banks_per_stage) + (idx/_SOC_ISM_MAX_STAGES);
    997 
    998                 if (_soc_ism_bank_avail[unit][bank]) {
    999                     continue;
   1000                 }
   1001 
   1002                 /* Rule: ESM stuff can only be in banks >= 4k in size */
   1003                 if (mem >= SOC_ISM_MEM_MAX &&
   1004                         SOC_ISM_INFO(unit)->bank_raw_sizes[bank] < 1024*4) {
   1005                     continue;
   1006                 }
   1007 
   1008                 /* Skip if size and required banks criteria NOT meet */
   1009                 if ((size == SOC_ISM_INFO(unit)->bank_raw_sizes[bank]) &&
   1010                         (ism_hash_tables[tab].banks >
   1011                          (ism_hash_tables[tab].allocated_banks + 1))) {
   1012                     continue;
   1013                 }
   1014 
   1015                 /* Free bank found */
   1016                 if (size >= SOC_ISM_INFO(unit)->bank_raw_sizes[bank]) {
   1017                     /* populate trace info */
   1018                     bank_trace[tab][ism_hash_tables[tab].allocated_banks].index = idx;
   1019                     bank_trace[tab][ism_hash_tables[tab].allocated_banks].bank = bank;
   1020 
   1021                     size -= SOC_ISM_INFO(unit)->bank_raw_sizes[bank];
   1022                     ism_hash_tables[tab].allocated_banks++;
   1023                     _soc_ism_bank_avail[unit][bank] = mem;
   1024 
   1025                     /* ISM mem only */
   1026                     if (mem < SOC_ISM_MEM_MAX) {
   1027                         _soc_ism_table_bank_count[unit][midx]++;
   1028                         if (_soc_ism_table_bank_count[unit][midx] >
   1029                                 SOC_ISM_INFO(unit)->max_banks) {
   1030                             return SOC_E_PARAM;
   1031                         }
   1032                         _soc_ism_table_bank_config[unit][midx][bank] = 1;
   1033                     }
   1034                     avail--;
   1035                 }
   1036 
   1037                 /* When required size is allocated check and
   1038                  * required number of banks are also allocated
   1039                  */
   1040                 if (!size && (!ism_hash_tables[tab].banks ||
   1041                             (ism_hash_tables[tab].banks <=
   1042                              ism_hash_tables[tab].allocated_banks))) {
   1043                     break;
   1044                 }
   1045             }
   1046 
   1047             /* Either required banks or size certiera not meet
   1048              * using trace roll bank and go for next best fit bank
   1049              */
   1050             if (size && ism_hash_tables[tab].allocated_banks) {
   1051                 /* No Free banks remaining.
   1052                  * Reordering can't be done for this memory
   1053                  */
   1054                 if (!avail) {
   1055                     break;
   1056                 }
   1057                 idx = bank_trace[tab][ism_hash_tables[tab].allocated_banks - 1].index;
   1058                 bank = bank_trace[tab][ism_hash_tables[tab].allocated_banks - 1].bank;
   1059                 ism_hash_tables[tab].allocated_banks--;
   1060                 _soc_ism_bank_avail[unit][bank] = 0;
   1061                 /* ISM mem only */
   1062                 if (mem < SOC_ISM_MEM_MAX) {
   1063                     _soc_ism_table_bank_count[unit][midx]--;
   1064                     _soc_ism_table_bank_config[unit][midx][bank] = 0;
   1065                 }
   1066                 size += SOC_ISM_INFO(unit)->bank_raw_sizes[bank];
   1067                 idx++;
   1068                 avail++;
   1069                 /* Find next bank size is other than rolled back value */
   1070                 while( idx < SOC_ISM_INFO(unit)->max_banks) {
   1071                     next_bank = ((idx%_SOC_ISM_MAX_STAGES) *
   1072                             SOC_ISM_INFO(unit)->banks_per_stage) + (idx/_SOC_ISM_MAX_STAGES);
   1073 
   1074                     if (!(_soc_ism_bank_avail[unit][next_bank] ||
   1075                                 (SOC_ISM_INFO(unit)->bank_raw_sizes[bank] == SOC_ISM_INFO(unit)->bank_raw_sizes[next_bank]))) {
   1076                         break;
   1077                     }
   1078                     idx++;
   1079                 }
   1080             } else if (size &&
   1081                     (idx >= SOC_ISM_INFO(unit)->max_banks)) {
   1082                 /* Bump up num of entries to allocate the next bigger bank
   1083                  * At this point all previsously allocated banks
   1084                  * have been rolled back
   1085                  */
   1086                 size += _SOC_ISM_ENTRY_SIZE_QUANTA;
   1087                 ism_hash_tables[tab].size += (_SOC_ISM_ENTRY_SIZE_QUANTA *  mem_info_entry[midx].epb);
   1088                 idx = 0;
   1089                 if (size  > _soc_ism_bank_total(unit)) {
   1090                     break;
   1091                 }
   1092             }
   1093         } while (size && avail);
   1094 
   1095         if (size) {
   1096             /* Roll back if any previous table was allocated */
   1097             if (tab) {
   1098                 /* Roll back all the allocations in the current table and
   1099                  * last allocation in previous table
   1100                  */
   1101                 for (i = ism_hash_tables[tab].allocated_banks ; i > 0 ; i--) {
   1102                     bank = bank_trace[tab][ism_hash_tables[tab].allocated_banks - 1].bank;
   1103                     _soc_ism_bank_avail[unit][bank] = 0;
   1104                     /* ISM mem only */
   1105                     if (mem < SOC_ISM_MEM_MAX) {
   1106                         _soc_ism_table_bank_count[unit][midx]--;
   1107                         _soc_ism_table_bank_config[unit][midx][bank] = 0;
   1108                     }
   1109                     avail++;
   1110                     ism_hash_tables[tab].allocated_banks--;
   1111                 }
   1112                 /* Restore orignial mem size to undo size bump for this memory */
   1113                 ism_hash_tables[tab].size = orig_mem_size[tab];
   1114                 tab--;
   1115                 /* Skip ESM memories or zero size memories */
   1116                 while((tab >= 0) && (!ism_hash_tables[tab].size ||
   1117                             (ism_hash_tables[tab].mem >= SOC_ISM_MEM_MAX))) {
   1118                     tab--;
   1119                 }
   1120                 if (tab < 0) {
   1121                     return SOC_E_PARAM;
   1122                 }
   1123                 idx = 0;
   1124                 /* Set flag, so that last allocated bank will be undo
   1125                  * at the start of the next loop
   1126                  */
   1127                 if (ism_hash_tables[tab].allocated_banks) {
   1128                     undo_flag = TRUE;
   1129                 }
   1130             } else {
   1131                 LOG_ERROR(BSL_LS_SOC_COMMON,
   1132                         (BSL_META_U(unit,
   1133                                     "Could not allocate banks for mem: %s\n"),
   1134                          soc_ism_table_to_name(mem)));
   1135                 return SOC_E_PARAM;
   1136             }
   1137         } else {
   1138             idx = 0;
   1139             size = ism_hash_tables[tab].size;
   1140             switch (mem) {
   1141                 case SOC_ISM_MEM_VLAN_XLATE:
   1142                     sop->memState[VLAN_XLATEm].index_max += (size * 2);
   1143                     sop->memState[VLAN_XLATE_1m].index_max += (size * 2);
   1144                     sop->memState[VLAN_XLATE_1_HIT_ONLYm].index_max += (size * 2);
   1145                     sop->memState[VLAN_XLATE_EXTDm].index_max += size;
   1146                     sop->memState[VLAN_XLATE_2_HIT_ONLYm].index_max += size;
   1147                     break;
   1148                 case SOC_ISM_MEM_L2_ENTRY:
   1149                     sop->memState[L2_ENTRY_1m].index_max += (size * 2) ;
   1150                     sop->memState[L2_ENTRY_1_HIT_ONLYm].index_max += (size * 2) ;
   1151                     sop->memState[L2_ENTRY_2m].index_max += size ;
   1152                     sop->memState[L2_ENTRY_2_HIT_ONLYm].index_max += size ;
   1153                     break;
   1154                 case SOC_ISM_MEM_L3_ENTRY:
   1155                     sop->memState[L3_ENTRY_1m].index_max += (size * 4);
   1156                     sop->memState[L3_ENTRY_1_HIT_ONLYm].index_max += (size * 4);
   1157                     sop->memState[L3_ENTRY_2m].index_max += (size * 2);
   1158                     sop->memState[L3_ENTRY_2_HIT_ONLYm].index_max += (size * 2);
   1159                     sop->memState[L3_ENTRY_4m].index_max += size;
   1160                     sop->memState[L3_ENTRY_4_HIT_ONLYm].index_max += size;
   1161                     break;
   1162                 case SOC_ISM_MEM_EP_VLAN_XLATE:
   1163                     sop->memState[EGR_VLAN_XLATEm].index_max += size;
   1164                     sop->memState[EP_VLAN_XLATE_1m].index_max += size;
   1165                     sop->memState[EP_VLAN_XLATE_1_HIT_ONLYm].index_max += size;
   1166                     break;
   1167                 case SOC_ISM_MEM_MPLS:
   1168                     sop->memState[MPLS_ENTRYm].index_max += (size * 2);
   1169                     sop->memState[MPLS_ENTRY_1m].index_max += (size * 2);
   1170                     sop->memState[MPLS_ENTRY_1_HIT_ONLYm].index_max += (size * 2);
   1171                     sop->memState[MPLS_ENTRY_EXTDm].index_max += size;
   1172                     sop->memState[MPLS_ENTRY_2_HIT_ONLYm].index_max += size;
   1173                     break;
   1174                 case SOC_ISM_MEM_ESM_L2:
   1175                 case SOC_ISM_MEM_ESM_L3:
   1176                 case SOC_ISM_MEM_ESM_ACL:
   1177                     break;
   1178                 default: return SOC_E_PARAM;
   1179             }
   1180             tab++;
   1181         }
   1182     }
   1183     _soc_ism_mem_allocation_log(unit, ism_hash_tables, count);
   1184 
   1185     return SOC_E_NONE;
   1186 }
   1187 
   1188 /* Support simple, sequential configuration for now and
   1189    fill _soc_ism_table_bank_config based upon driver memory config */ 
   1190 int
   1191 soc_ism_mem_config(int unit, soc_ism_mem_size_config_t *mem_cfg, int count)
   1192 {
   1193     int rv, tab, idx, bank;
   1194     int midx, size;
   1195     uint16 dev_id;
   1196     uint8 rev_id;
   1197     uint32 mem, _ism_total = 0;
   1198     soc_ism_mem_size_config_t ism_hash_tables[SOC_ISM_MEM_TOTAL];
   1199     soc_persist_t *sop = SOC_PERSIST(unit);
   1200     SOC_ISM_INFO(unit) = &_soc_ism_info[unit];
   1201     SOC_ISM_HASH_INFO(unit) = &_soc_ism_hash_info[unit];
   1202     
   1203     sal_memset(&_soc_ism_bank_avail[unit], 0, 
   1204                 sizeof(uint32) * _SOC_ISM_MAX_BANKS);
   1205     sal_memset(&_soc_ism_table_bank_count[unit], 0, 
   1206                 sizeof(uint32) * _SOC_ISM_MAX_TABLES);
   1207     sal_memset(&_soc_ism_table_bank_config[unit], 0, 
   1208                 sizeof(uint8) * _SOC_ISM_MAX_TABLES * _SOC_ISM_MAX_BANKS);
   1209     sal_memset(&_soc_ism_table_raw_bank_count[unit], 0, 
   1210                 sizeof(uint32) * _SOC_ISM_MAX_TABLES);
   1211     sal_memset(&_soc_ism_log_to_phy_map[unit], 0, 
   1212                 sizeof(uint32) * _SOC_ISM_MAX_TABLES * _SOC_ISM_TOTAL_BANKS);
   1213     
   1214     soc_cm_get_id(unit, &dev_id, &rev_id);
   1215     switch (dev_id) {
   1216     case BCM56640_DEVICE_ID:
   1217     case BCM56643_DEVICE_ID:
   1218     case BCM56644_DEVICE_ID:
   1219         SOC_ISM_INFO(unit)->ism_mode = _ISM_SIZE_MODE_512;
   1220         break;
   1221     case BCM56648_DEVICE_ID:
   1222     case BCM56649_DEVICE_ID:
   1223     case BCM56540_DEVICE_ID:
   1224     case BCM56541_DEVICE_ID:
   1225     case BCM56542_DEVICE_ID:
   1226     case BCM56544_DEVICE_ID:
   1227     case BCM56545_DEVICE_ID:
   1228     case BCM56546_DEVICE_ID:
   1229         SOC_ISM_INFO(unit)->ism_mode = _ISM_SIZE_MODE_176;
   1230         break;
   1231     case BCM56543_DEVICE_ID:
   1232         SOC_ISM_INFO(unit)->ism_mode = _ISM_SIZE_MODE_256;
   1233         break;
   1234     case BCM56044_DEVICE_ID:
   1235     case BCM56045_DEVICE_ID:
   1236     case BCM56046_DEVICE_ID:
   1237         SOC_ISM_INFO(unit)->ism_mode = _ISM_SIZE_MODE_80;
   1238         break;
   1239 #ifdef BCM_HELIX4_SUPPORT
   1240     case BCM56548H_DEVICE_ID:
   1241     case BCM56548_DEVICE_ID:
   1242     case BCM56547_DEVICE_ID:
   1243     case BCM56344_DEVICE_ID:
   1244     case BCM56342_DEVICE_ID:
   1245     case BCM56340_DEVICE_ID:
   1246         SOC_ISM_INFO(unit)->ism_mode = _ISM_SIZE_MODE_96;
   1247         break;
   1248     case BCM56042_DEVICE_ID:
   1249     case BCM56041_DEVICE_ID:
   1250     case BCM56040_DEVICE_ID:
   1251     case BCM56049_DEVICE_ID:
   1252     case BCM56048_DEVICE_ID:
   1253     case BCM56047_DEVICE_ID:        
   1254     case BCM56346_DEVICE_ID:
   1255     case BCM56345_DEVICE_ID:
   1256         SOC_ISM_INFO(unit)->ism_mode = _ISM_SIZE_MODE_80;
   1257         break;
   1258 #endif
   1259     default:
   1260          return SOC_E_PARAM;
   1261     }
   1262     
   1263     switch (SOC_ISM_INFO(unit)->ism_mode) {
   1264     case _ISM_SIZE_MODE_512:
   1265         SOC_ISM_INFO(unit)->bank_raw_sizes = _soc_ism_bank_raw_sizes;
   1266         SOC_ISM_INFO(unit)->banks_per_stage = _SOC_ISM_BANKS_PER_STAGE;
   1267         SOC_ISM_INFO(unit)->max_banks = _SOC_ISM_MAX_BANKS;
   1268         SOC_ISM_INFO(unit)->total_banks = _SOC_ISM_TOTAL_BANKS;
   1269         SOC_ISM_INFO(unit)->total_entries = _SOC_ISM_ENTRIES_PER_BKT *
   1270                                             _soc_ism_bank_total(unit);
   1271         SOC_ISM_INFO(unit)->max_raw_banks = _SOC_ISM_MAX_RAW_BANKS;
   1272         SOC_ISM_INFO(unit)->real_bank_map = _soc_ism_real_bank_map;
   1273         break;
   1274     case _ISM_SIZE_MODE_256:
   1275         SOC_ISM_INFO(unit)->bank_raw_sizes = _soc_ism_bank_raw_sizes_256;
   1276         SOC_ISM_INFO(unit)->banks_per_stage = _SOC_ISM_BANKS_PER_STAGE;
   1277         SOC_ISM_INFO(unit)->max_banks = _SOC_ISM_MAX_BANKS;
   1278         SOC_ISM_INFO(unit)->total_banks = _SOC_ISM_TOTAL_BANKS;
   1279         SOC_ISM_INFO(unit)->total_entries = _SOC_ISM_ENTRIES_PER_BKT *
   1280                                             _soc_ism_bank_total(unit);
   1281         SOC_ISM_INFO(unit)->max_raw_banks = _SOC_ISM_MAX_RAW_BANKS;
   1282         SOC_ISM_INFO(unit)->real_bank_map = _soc_ism_real_bank_map;
   1283         break;
   1284     case _ISM_SIZE_MODE_176:
   1285         SOC_ISM_INFO(unit)->bank_raw_sizes = _soc_ism_bank_raw_sizes_256_176;
   1286         SOC_ISM_INFO(unit)->banks_per_stage = _SOC_ISM_BANKS_PER_STAGE_176;
   1287         SOC_ISM_INFO(unit)->max_banks = _SOC_ISM_MAX_BANKS_176;
   1288         SOC_ISM_INFO(unit)->total_banks = _SOC_ISM_TOTAL_BANKS_176;
   1289         SOC_ISM_INFO(unit)->total_entries = _SOC_ISM_ENTRIES_PER_BKT *
   1290                                             _soc_ism_bank_total(unit);
   1291         SOC_ISM_INFO(unit)->max_raw_banks = _SOC_ISM_MAX_RAW_BANKS;
   1292         SOC_ISM_INFO(unit)->real_bank_map = _soc_ism_real_bank_map_176;
   1293         break;
   1294     case _ISM_SIZE_MODE_96:
   1295         SOC_ISM_INFO(unit)->bank_raw_sizes = _soc_ism_bank_raw_sizes_256_96;
   1296         SOC_ISM_INFO(unit)->banks_per_stage = _SOC_ISM_BANKS_PER_STAGE_96;
   1297         SOC_ISM_INFO(unit)->max_banks = _SOC_ISM_MAX_BANKS_96;
   1298         SOC_ISM_INFO(unit)->total_banks = _SOC_ISM_TOTAL_BANKS_96;
   1299         SOC_ISM_INFO(unit)->total_entries = _SOC_ISM_ENTRIES_PER_BKT *
   1300                                             _soc_ism_bank_total(unit);
   1301         SOC_ISM_INFO(unit)->max_raw_banks = _SOC_ISM_MAX_RAW_BANKS;
   1302         SOC_ISM_INFO(unit)->real_bank_map = _soc_ism_real_bank_map_96;
   1303         break;
   1304     case _ISM_SIZE_MODE_80:
   1305         SOC_ISM_INFO(unit)->bank_raw_sizes = _soc_ism_bank_raw_sizes_256_80;
   1306         SOC_ISM_INFO(unit)->banks_per_stage = _SOC_ISM_BANKS_PER_STAGE_80;
   1307         SOC_ISM_INFO(unit)->max_banks = _SOC_ISM_MAX_BANKS_80;
   1308         SOC_ISM_INFO(unit)->total_banks = _SOC_ISM_TOTAL_BANKS_80;
   1309         SOC_ISM_INFO(unit)->total_entries = _SOC_ISM_ENTRIES_PER_BKT *
   1310                                             _soc_ism_bank_total(unit);
   1311         SOC_ISM_INFO(unit)->max_raw_banks = _SOC_ISM_MAX_RAW_BANKS;
   1312         SOC_ISM_INFO(unit)->real_bank_map = _soc_ism_real_bank_map_80;
   1313         break;
   1314     default:
   1315          return SOC_E_PARAM;
   1316     }
   1317     
   1318     /* Attach the hash cfg structures based upon chip type 
   1319        (currently only one type; will change to use if-else in the future) */
   1320     _SOC_ISM_BANKS(unit) = _soc_ism_shb[unit];
   1321     _SOC_ISM_SETS(unit) = _soc_ism_shms;
   1322     _SOC_ISM_MEMS(unit) = _soc_ism_shm;
   1323     _SOC_ISM_VIEWS(unit) = _soc_ism_shmv;
   1324     _SOC_ISM_KEYS(unit) = _soc_ism_shk;
   1325     
   1326     sop->memState[VLAN_XLATEm].index_max = -1;
   1327     sop->memState[VLAN_XLATE_1m].index_max = -1;
   1328     sop->memState[VLAN_XLATE_1_HIT_ONLYm].index_max = -1;
   1329     sop->memState[VLAN_XLATE_EXTDm].index_max = -1;
   1330     sop->memState[VLAN_XLATE_2_HIT_ONLYm].index_max = -1;
   1331     sop->memState[L2_ENTRY_1m].index_max = -1;
   1332     sop->memState[L2_ENTRY_1_HIT_ONLYm].index_max = -1;
   1333     sop->memState[L2_ENTRY_2m].index_max = -1;
   1334     sop->memState[L2_ENTRY_2_HIT_ONLYm].index_max = -1;
   1335     sop->memState[L3_ENTRY_1m].index_max = -1;
   1336     sop->memState[L3_ENTRY_1_HIT_ONLYm].index_max = -1;
   1337     sop->memState[L3_ENTRY_2m].index_max = -1;
   1338     sop->memState[L3_ENTRY_2_HIT_ONLYm].index_max = -1;
   1339     sop->memState[L3_ENTRY_4m].index_max = -1;
   1340     sop->memState[L3_ENTRY_4_HIT_ONLYm].index_max = -1;
   1341     sop->memState[EGR_VLAN_XLATEm].index_max = -1;
   1342     sop->memState[EP_VLAN_XLATE_1m].index_max = -1;
   1343     sop->memState[EP_VLAN_XLATE_1_HIT_ONLYm].index_max = -1;
   1344     sop->memState[MPLS_ENTRYm].index_max = -1;
   1345     sop->memState[MPLS_ENTRY_1m].index_max = -1;
   1346     sop->memState[MPLS_ENTRY_1_HIT_ONLYm].index_max = -1;
   1347     sop->memState[MPLS_ENTRY_EXTDm].index_max = -1;
   1348     sop->memState[MPLS_ENTRY_2_HIT_ONLYm].index_max = -1;
   1349     if (soc_property_get(unit, spn_VLAN_XLATE_MEM_BANKS, 0) ||
   1350             soc_property_get(unit, spn_L2_MEM_BANKS, 0) ||
   1351             soc_property_get(unit, spn_L3_MEM_BANKS, 0) ||
   1352             soc_property_get(unit, spn_EGR_VLAN_XLATE_MEM_BANKS, 0) ||
   1353             soc_property_get(unit, spn_MPLS_MEM_BANKS, 0)) {
   1354         rv = soc_ism_mem_config_with_banks(unit, mem_cfg, count);
   1355         if (SOC_FAILURE(rv)) {
   1356             return rv;
   1357         }
   1358     } else {
   1359         /* Sort the memories in decreasing order of sizes and allocation priority */
   1360         _soc_ism_sort_mems(mem_cfg, count, ism_hash_tables);
   1361 
   1362         for (tab = 0; tab < count && tab < SOC_ISM_MEM_TOTAL; tab++) {
   1363             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1364                         (BSL_META_U(unit,
   1365                                     "ISM mem: [%s], size: %d\n"),
   1366                          soc_ism_table_to_name(ism_hash_tables[tab].mem),
   1367                          ism_hash_tables[tab].size));
   1368         }
   1369         for (tab = 0; tab < count && tab < SOC_ISM_MEM_TOTAL; tab++) {
   1370             uint8 avail;
   1371             int rem;
   1372             mem = ism_hash_tables[tab].mem;
   1373             midx = soc_ism_table_to_index(mem);
   1374             if (midx == -1) {
   1375                 return SOC_E_PARAM;
   1376             }
   1377             if (ism_hash_tables[tab].size <= 0 ) {
   1378                 continue;
   1379             }
   1380             size = ism_hash_tables[tab].size;
   1381             rem = size % _SOC_ISM_ENTRY_SIZE_QUANTA;
   1382             if (rem) {
   1383                 size = size + (_SOC_ISM_ENTRY_SIZE_QUANTA - rem);
   1384                 LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1385                             (BSL_META_U(unit,
   1386                                         "Updated size %s: %d\n"), 
   1387                              soc_ism_table_to_name(mem), size));
   1388             }
   1389             ism_hash_tables[tab].size = size;
   1390             do {
   1391                 /* convert to num of buckets */ 
   1392                 size = size / mem_info_entry[midx].epb; 
   1393                 avail = 0;
   1394                 for (idx = 0; idx < SOC_ISM_INFO(unit)->max_banks; idx++) {
   1395                     bank = ((idx%_SOC_ISM_MAX_STAGES) * 
   1396                             SOC_ISM_INFO(unit)->banks_per_stage) +
   1397                            (idx/_SOC_ISM_MAX_STAGES);
   1398                     if (_soc_ism_bank_avail[unit][bank]) {
   1399                         continue;
   1400                     }
   1401                     avail++;
   1402                     /* Rule: ESM stuff can only be in banks >= 4k in size */
   1403                     if (mem >= SOC_ISM_MEM_MAX && 
   1404                         SOC_ISM_INFO(unit)->bank_raw_sizes[bank] < 1024*4) {
   1405                         continue;
   1406                     }
   1407                     if (size >= SOC_ISM_INFO(unit)->bank_raw_sizes[bank]) {
   1408                         _ism_total += SOC_ISM_INFO(unit)->bank_raw_sizes[bank] * \
   1409                                       _SOC_ISM_ENTRIES_PER_BKT;
   1410                         size -= SOC_ISM_INFO(unit)->bank_raw_sizes[bank];
   1411                         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1412                                     (BSL_META_U(unit,
   1413                                                 "bank: %d\n"), bank));
   1414                         _soc_ism_bank_avail[unit][bank] = mem;
   1415                         if (mem < SOC_ISM_MEM_MAX) {
   1416                             _soc_ism_table_bank_count[unit][midx]++;
   1417                             if (_soc_ism_table_bank_count[unit][midx] > 
   1418                                 SOC_ISM_INFO(unit)->max_banks) {
   1419                                 return SOC_E_PARAM;
   1420                             } 
   1421                             _soc_ism_table_bank_config[unit][midx][bank] = 1; 
   1422                         }
   1423                     }
   1424                     if (!size) {
   1425                         goto next_mem;
   1426                     }
   1427                 }
   1428                 if (size) {
   1429                     /* Bump up num of entries to allocate the next bigger bank */
   1430                     size = size * mem_info_entry[midx].epb + _SOC_ISM_ENTRY_SIZE_QUANTA;
   1431                     ism_hash_tables[tab].size += _SOC_ISM_ENTRY_SIZE_QUANTA;
   1432                 } 
   1433             } while (size && avail); /* Keep trying */
   1434             if (size) {
   1435                 LOG_ERROR(BSL_LS_SOC_COMMON,
   1436                           (BSL_META_U(unit,
   1437                                       "Could not allocate banks for mem: %s\n"),
   1438                            soc_ism_table_to_name(mem)));
   1439                 return SOC_E_PARAM;
   1440             }
   1441 next_mem:
   1442             size = ism_hash_tables[tab].size;
   1443             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1444                         (BSL_META_U(unit,
   1445                                     "Final size %s: %d\n"), 
   1446                          soc_ism_table_to_name(mem), size));
   1447             switch (mem) {
   1448                 case SOC_ISM_MEM_VLAN_XLATE:
   1449                     sop->memState[VLAN_XLATEm].index_max += (size * 2);
   1450                     sop->memState[VLAN_XLATE_1m].index_max += (size * 2);
   1451                     sop->memState[VLAN_XLATE_1_HIT_ONLYm].index_max += (size * 2);
   1452                     sop->memState[VLAN_XLATE_EXTDm].index_max += size;
   1453                     sop->memState[VLAN_XLATE_2_HIT_ONLYm].index_max += size;
   1454                     break;
   1455                 case SOC_ISM_MEM_L2_ENTRY:
   1456                     sop->memState[L2_ENTRY_1m].index_max += (size * 2) ;
   1457                     sop->memState[L2_ENTRY_1_HIT_ONLYm].index_max += (size * 2) ;
   1458                     sop->memState[L2_ENTRY_2m].index_max += size ;
   1459                     sop->memState[L2_ENTRY_2_HIT_ONLYm].index_max += size ;
   1460                     break;
   1461                 case SOC_ISM_MEM_L3_ENTRY:
   1462                     sop->memState[L3_ENTRY_1m].index_max += (size * 4);
   1463                     sop->memState[L3_ENTRY_1_HIT_ONLYm].index_max += (size * 4);
   1464                     sop->memState[L3_ENTRY_2m].index_max += (size * 2);
   1465                     sop->memState[L3_ENTRY_2_HIT_ONLYm].index_max += (size * 2);
   1466                     sop->memState[L3_ENTRY_4m].index_max += size;
   1467                     sop->memState[L3_ENTRY_4_HIT_ONLYm].index_max += size;
   1468                     break;
   1469                 case SOC_ISM_MEM_EP_VLAN_XLATE:
   1470                     sop->memState[EGR_VLAN_XLATEm].index_max += size;
   1471                     sop->memState[EP_VLAN_XLATE_1m].index_max += size;
   1472                     sop->memState[EP_VLAN_XLATE_1_HIT_ONLYm].index_max += size;
   1473                     break;
   1474                 case SOC_ISM_MEM_MPLS:
   1475                     sop->memState[MPLS_ENTRYm].index_max += (size * 2);
   1476                     sop->memState[MPLS_ENTRY_1m].index_max += (size * 2);
   1477                     sop->memState[MPLS_ENTRY_1_HIT_ONLYm].index_max += (size * 2);
   1478                     sop->memState[MPLS_ENTRY_EXTDm].index_max += size;
   1479                     sop->memState[MPLS_ENTRY_2_HIT_ONLYm].index_max += size;
   1480                     break;
   1481                 case SOC_ISM_MEM_ESM_L2:
   1482                 case SOC_ISM_MEM_ESM_L3:
   1483                 case SOC_ISM_MEM_ESM_ACL:
   1484                     break;
   1485                 default: return SOC_E_PARAM;
   1486             }
   1487             continue;
   1488         }
   1489         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1490                     (BSL_META_U(unit,
   1491                                 "ISM used total: %d k of %d k\n"), 
   1492                      _ism_total/_SOC_ISM_ENTRY_SIZE_QUANTA, 
   1493                      SOC_ISM_INFO(unit)->total_entries/_SOC_ISM_ENTRY_SIZE_QUANTA));
   1494         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1495                     (BSL_META_U(unit,
   1496                                 "ISM remaining : %d k\n"), 
   1497                      SOC_ISM_INFO(unit)->total_entries/_SOC_ISM_ENTRY_SIZE_QUANTA - 
   1498                      (_ism_total/_SOC_ISM_ENTRY_SIZE_QUANTA)));
   1499 
   1500         if (_ism_total/_SOC_ISM_ENTRY_SIZE_QUANTA > 
   1501             SOC_ISM_INFO(unit)->total_entries/_SOC_ISM_ENTRY_SIZE_QUANTA) {
   1502             LOG_ERROR(BSL_LS_SOC_COMMON,
   1503                       (BSL_META_U(unit,
   1504                                   "Over-allocation of ISM resources !!\n")));
   1505             return SOC_E_PARAM;
   1506         }
   1507         _soc_ism_mem_allocation_log(unit, ism_hash_tables, count);
   1508     }
   1509 
   1510     rv = soc_ism_log_to_phy_fill(unit);
   1511     if (SOC_FAILURE(rv)) {
   1512         return rv; 
   1513     }
   1514     rv = soc_ism_hash_init(unit);
   1515     if (SOC_FAILURE(rv)) {
   1516         return rv; 
   1517     }
   1518     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1519                 (BSL_META_U(unit,
   1520                             "ISM configured.\n")));
   1521     return SOC_E_NONE;
   1522 }
   1523 
   1524 /* Internel helper routine */
   1525 STATIC int
   1526 _soc_ism_get_sorted_bank_list(int unit, soc_mem_t *mems, int *banks) 
   1527 {
   1528     int32 i, j, count = 0;
   1529     uint8 done, bank, tmp;
   1530     /* go through banks to get sorted base_entry's */ 
   1531     for (i = 0; i < SOC_ISM_INFO(unit)->max_banks; i++) {
   1532         bank = ((i%_SOC_ISM_MAX_STAGES) * SOC_ISM_INFO(unit)->banks_per_stage) + 
   1533                (i/_SOC_ISM_MAX_STAGES);
   1534         if (!_soc_ism_bank_avail[unit][bank]) {
   1535             continue;
   1536         }
   1537         done = 0; 
   1538         for (j = 0; j < count; j++) {
   1539             if (mems[j] == _soc_ism_bank_avail[unit][bank]) {
   1540                 done = 1;
   1541                 break;
   1542             } 
   1543         }
   1544         if (done) {
   1545             continue;
   1546         } else {
   1547             banks[count] = bank;
   1548             mems[count++] = _soc_ism_bank_avail[unit][bank];
   1549         }
   1550         for (j = i+1; j < SOC_ISM_INFO(unit)->max_banks; j++) {
   1551             tmp = ((j%_SOC_ISM_MAX_STAGES) * 
   1552                    SOC_ISM_INFO(unit)->banks_per_stage) + 
   1553                   (j/_SOC_ISM_MAX_STAGES);
   1554             if (_soc_ism_bank_avail[unit][bank] == 
   1555                 _soc_ism_bank_avail[unit][tmp]) {
   1556                 banks[count] = tmp;
   1557                 mems[count++] = _soc_ism_bank_avail[unit][tmp];
   1558             }
   1559         } 
   1560     }
   1561     return count;
   1562 }
   1563 
   1564 /* Initializes and links various hash structures */
   1565 int
   1566 soc_ism_hash_init(int unit)
   1567 {
   1568     int i, j, k, count = 0;
   1569     soc_mem_t mems[_SOC_ISM_MAX_BANKS];
   1570     int banks[_SOC_ISM_MAX_BANKS];
   1571     int bits_aligned;
   1572 
   1573 
   1574     sal_memset(_SOC_ISM_BANKS(unit), 0, sizeof(soc_hash_bank_t));
   1575     sal_memset(mems, 0, COUNTOF(mems) * sizeof(soc_mem_t));
   1576     for (i = 0; i < SOC_MEM_SET_MAX; i++) {
   1577         _SOC_ISM_SETS(unit)[i].num_banks = 0;
   1578     }
   1579     count = _soc_ism_get_sorted_bank_list(unit, mems, banks);
   1580     LOG_INFO(BSL_LS_SOC_SOCMEM,
   1581              (BSL_META_U(unit,
   1582                          "Used banks: %d\n"), count));
   1583     for (i = 0; i < count; i++) {
   1584         if (mems[i] >= SOC_ISM_MEM_MAX) {
   1585             continue;
   1586         }
   1587         _SOC_ISM_BANKS(unit)[i].num_bkts = 
   1588                                    SOC_ISM_INFO(unit)->bank_raw_sizes[banks[i]];
   1589         _SOC_ISM_BANKS(unit)[i].bkt_size = 4; /* could be configurable */
   1590         _SOC_ISM_BANKS(unit)[i].num_entries = _SOC_ISM_BANKS(unit)[i].num_bkts * 
   1591                                               _SOC_ISM_BANKS(unit)[i].bkt_size;
   1592         _SOC_ISM_BANKS(unit)[i].my_id = banks[i];
   1593         for (j = 0; j < SOC_MEM_SET_MAX; j++) {
   1594             if (mems[i] == _SOC_ISM_SETS(unit)[j].mem_set) {
   1595                _SOC_ISM_BANKS(unit)[i].hms = &_SOC_ISM_SETS(unit)[j];
   1596                if (_SOC_ISM_SETS(unit)[j].num_banks == 0) {
   1597                    _SOC_ISM_SETS(unit)[j].shb = &_SOC_ISM_BANKS(unit)[i];
   1598                    _SOC_ISM_BANKS(unit)[i].base_entry = 0;
   1599                } else {
   1600                    _SOC_ISM_BANKS(unit)[i].base_entry = 
   1601                    _SOC_ISM_SETS(unit)[j].shb[_SOC_ISM_SETS(unit)[j].num_banks-1].base_entry 
   1602                    + _SOC_ISM_SETS(unit)[j].shb[_SOC_ISM_SETS(unit)[j].num_banks-1].num_entries;
   1603                }
   1604                _SOC_ISM_SETS(unit)[j].num_banks++;               
   1605                break;
   1606             }
   1607         }
   1608         LOG_INFO(BSL_LS_SOC_SOCMEM,
   1609                  (BSL_META_U(unit,
   1610                              "Bank: %d, base: %d, mem: [%s], buckets: %d, entries: %d "
   1611                              "hash offset: %d\n"), banks[i], 
   1612                   _SOC_ISM_BANKS(unit)[i].base_entry, 
   1613                   soc_ism_table_to_name(_SOC_ISM_BANKS(unit)[i].hms->mem_set),
   1614                   _SOC_ISM_BANKS(unit)[i].num_bkts, 
   1615                   _SOC_ISM_BANKS(unit)[i].num_entries,
   1616                   _SOC_ISM_BANKS(unit)[i].hash_offset));
   1617     }
   1618     /* Just for sanity */
   1619     for (i = 0; i < SOC_MEM_SET_MAX; i++) {
   1620         LOG_INFO(BSL_LS_SOC_SOCMEM,
   1621                  (BSL_META_U(unit,
   1622                              "Set: %s, num mems: %d, banks: %d, zero_lsb: %d, \n"), 
   1623                   soc_ism_table_to_name(_SOC_ISM_SETS(unit)[i].mem_set),
   1624                   _SOC_ISM_SETS(unit)[i].num_mems, 
   1625                   _SOC_ISM_SETS(unit)[i].num_banks,
   1626                   _SOC_ISM_SETS(unit)[i].zero_lsb));
   1627         for (j = 0; j < _SOC_ISM_SETS(unit)[i].num_mems; j++) {
   1628             LOG_INFO(BSL_LS_SOC_SOCMEM,
   1629                      (BSL_META_U(unit,
   1630                                  "Num views: %d\n"),
   1631                       _SOC_ISM_SETS(unit)[i].shm[j].num_views));
   1632             for (k = 0; k < _SOC_ISM_SETS(unit)[i].shm[j].num_views; k++) {
   1633                 LOG_INFO(BSL_LS_SOC_SOCMEM,
   1634                          (BSL_META_U(unit,
   1635                                      "key width: %d\n"),
   1636                           _SOC_ISM_SETS(unit)[i].shm[j].hmv[k].key_size));
   1637             }
   1638         }
   1639 
   1640         /* the key bufer size is related to max_key_bits (which is defined in _soc_ism_shms array), need to check it  */
   1641         bits_aligned = (_SOC_ISM_SETS(unit)[i].max_key_bits + 7) & (~0x7);
   1642         if ((bits_aligned/8) > SOC_HASH_MEM_MAX_KEY_BUFFER_SIZE_BYTES)
   1643         {
   1644             LOG_ERROR(BSL_LS_SOC_COMMON,
   1645                 (BSL_META_U(unit,
   1646                          "The key buffer is two small, please adjust SOC_HASH_MEM_MAX_KEY_BUFFER_SIZE_BYTES!!\n")));
   1647             return SOC_E_CONFIG;
   1648         }
   1649     }
   1650     return SOC_E_NONE;
   1651 }
   1652 
   1653 /* write to h/w */
   1654 int
   1655 soc_ism_hw_config(int unit)
   1656 {
   1657     int i, r, f, stg, bank, len;
   1658     int j, offset = 0, lbpd = 0, rv = SOC_E_NONE;
   1659     uint32 pd_val, rval;
   1660     _soc_ism_pd_t *pd;
   1661 
   1662     assert(SOC_ISM_INFO(unit));
   1663     if (SAL_BOOT_SIMULATION) {
   1664         uint32 rval = 0;
   1665         if (SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_176) {
   1666             soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK0_SIZE_LIMITf,
   1667                               _ISM_BANK_SIZE_QUARTER);
   1668             soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK1_SIZE_LIMITf,
   1669                               _ISM_BANK_SIZE_HALF);
   1670             soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK2_SIZE_LIMITf,
   1671                               _ISM_BANK_SIZE_HALF);
   1672             soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK3_SIZE_LIMITf,
   1673                               _ISM_BANK_SIZE_HALF);
   1674             soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK4_SIZE_LIMITf,
   1675                               _ISM_BANK_SIZE_DISABLED);
   1676             SOC_IF_ERROR_RETURN(WRITE_STAGE0_BANK_SIZEr(unit, rval));
   1677             SOC_IF_ERROR_RETURN(WRITE_STAGE1_BANK_SIZEr(unit, rval));
   1678             SOC_IF_ERROR_RETURN(WRITE_STAGE2_BANK_SIZEr(unit, rval));
   1679             SOC_IF_ERROR_RETURN(WRITE_STAGE3_BANK_SIZEr(unit, rval));
   1680         } else if (SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_96) {
   1681             soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK0_SIZE_LIMITf,
   1682                               _ISM_BANK_SIZE_DISABLED);
   1683             soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK1_SIZE_LIMITf,
   1684                               _ISM_BANK_SIZE_QUARTER);
   1685             soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK2_SIZE_LIMITf,
   1686                               _ISM_BANK_SIZE_HALF);
   1687             soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK3_SIZE_LIMITf,
   1688                               _ISM_BANK_SIZE_HALF);
   1689             soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK4_SIZE_LIMITf,
   1690                               _ISM_BANK_SIZE_HALF);
   1691             SOC_IF_ERROR_RETURN(WRITE_STAGE0_BANK_SIZEr(unit, rval));
   1692             SOC_IF_ERROR_RETURN(WRITE_STAGE1_BANK_SIZEr(unit, rval));
   1693             SOC_IF_ERROR_RETURN(WRITE_STAGE2_BANK_SIZEr(unit, rval));
   1694             SOC_IF_ERROR_RETURN(WRITE_STAGE3_BANK_SIZEr(unit, rval));
   1695         } else if (SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_80) {
   1696             soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK0_SIZE_LIMITf,
   1697                               _ISM_BANK_SIZE_DISABLED);
   1698             soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK1_SIZE_LIMITf,
   1699                               _ISM_BANK_SIZE_QUARTER);
   1700             soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK2_SIZE_LIMITf,
   1701                               _ISM_BANK_SIZE_QUARTER);
   1702             soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK3_SIZE_LIMITf,
   1703                               _ISM_BANK_SIZE_HALF);
   1704             soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK4_SIZE_LIMITf,
   1705                               _ISM_BANK_SIZE_HALF);
   1706             SOC_IF_ERROR_RETURN(WRITE_STAGE0_BANK_SIZEr(unit, rval));
   1707             SOC_IF_ERROR_RETURN(WRITE_STAGE1_BANK_SIZEr(unit, rval));
   1708             SOC_IF_ERROR_RETURN(WRITE_STAGE2_BANK_SIZEr(unit, rval));
   1709             SOC_IF_ERROR_RETURN(WRITE_STAGE3_BANK_SIZEr(unit, rval));
   1710         }
   1711         /* Note: handle other modes as needed in the future */
   1712     }
   1713     rv = soc_ism_table_bank_set(unit);
   1714     if (SOC_FAILURE(rv)) {
   1715         return rv; 
   1716     }
   1717     rv = soc_ism_log_to_phy_set(unit);
   1718     if (SOC_FAILURE(rv)) {
   1719         return rv; 
   1720     }
   1721     if ((SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_96) ||
   1722         (SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_80)) {
   1723         offset = 1; /* First bank is not available */
   1724     } else if (SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_176) {
   1725         lbpd = 1; /* Last bank is not available */
   1726     }
   1727     /* Power down unused banks.
   1728      * Note: This works on the actual banks of the base device not the banks 
   1729      *       based upon the ISM mode.
   1730      */
   1731     for (i = 0; i < _SOC_ISM_MAX_BANKS; i++) {
   1732         if (!_soc_ism_bank_avail[unit][i]) {
   1733             if (offset || lbpd) {
   1734                 j = i + offset + i/4;
   1735                 if (j >= _SOC_ISM_MAX_BANKS) {
   1736                     return SOC_E_NONE;
   1737                 }
   1738             } else {
   1739                 j = i;
   1740             }
   1741             stg = j / _SOC_ISM_BANKS_PER_STAGE;
   1742             bank = j % _SOC_ISM_BANKS_PER_STAGE;
   1743             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1744                         (BSL_META_U(unit,
   1745                                     "Powering down stage[%d] bank[%d]\n"),
   1746                          stg, bank));
   1747             pd = &_soc_ism_pd[stg][bank];
   1748             r = 0;
   1749             while (pd->reg_field[r].pdr != INVALIDr) {
   1750                 SOC_IF_ERROR_RETURN
   1751                     (soc_reg32_get(unit, pd->reg_field[r].pdr, REG_PORT_ANY, 
   1752                                    0, &rval));
   1753                 f = 0;
   1754                 while (pd->reg_field[r].pdf[f] != INVALIDf) {
   1755                     len = soc_reg_field_length(unit, pd->reg_field[r].pdr, 
   1756                                                pd->reg_field[r].pdf[f]);
   1757                     pd_val = ((1 << len) - 1);
   1758                     soc_reg_field_set(unit, pd->reg_field[r].pdr, &rval, 
   1759                                       pd->reg_field[r].pdf[f], pd_val);
   1760                     f++;
   1761                 }
   1762                 SOC_IF_ERROR_RETURN
   1763                     (soc_reg32_set(unit, pd->reg_field[r].pdr, REG_PORT_ANY, 
   1764                                    0, rval));
   1765                 r++;
   1766             }
   1767         } else if (_soc_ism_bank_avail[unit][i] >= SOC_ISM_MEM_ESM_L2) {
   1768             if (offset || lbpd) {
   1769                 j = i + offset + i/4;
   1770                 if (j >= _SOC_ISM_MAX_BANKS) {
   1771                     return SOC_E_NONE;
   1772                 }
   1773             } else {
   1774                 j = i;
   1775             }
   1776             stg = j / _SOC_ISM_BANKS_PER_STAGE;
   1777             bank = j % _SOC_ISM_BANKS_PER_STAGE;
   1778             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   1779                         (BSL_META_U(unit,
   1780                                     "Powering down hit-bit rams for stage[%d] bank[%d]\n"),
   1781                          stg, bank));
   1782             pd = &_soc_ism_pd[stg][bank];
   1783             r = 0;
   1784             while (pd->hit_reg_field[r].pdr != INVALIDr) {
   1785                 SOC_IF_ERROR_RETURN
   1786                     (soc_reg32_get(unit, pd->hit_reg_field[r].pdr, REG_PORT_ANY, 
   1787                                    0, &rval));
   1788                 f = 0;
   1789                 while (pd->hit_reg_field[r].pdf[f] != INVALIDf) {
   1790                     len = soc_reg_field_length(unit, pd->hit_reg_field[r].pdr, 
   1791                                                pd->hit_reg_field[r].pdf[f]);
   1792                     pd_val = ((1 << len) - 1);
   1793                     soc_reg_field_set(unit, pd->hit_reg_field[r].pdr, &rval, 
   1794                                       pd->hit_reg_field[r].pdf[f], pd_val);
   1795                     f++;
   1796                 }
   1797                 SOC_IF_ERROR_RETURN
   1798                     (soc_reg32_set(unit, pd->hit_reg_field[r].pdr, REG_PORT_ANY, 
   1799                                    0, rval));
   1800                 r++;
   1801             }
   1802         }
   1803     }
   1804     return SOC_E_NONE;
   1805 }
   1806 
   1807 soc_reg_t _ism_stage_hash_cfg_reg[] = {
   1808     STAGE0_HASH_OFFSETr, STAGE1_HASH_OFFSETr,
   1809     STAGE2_HASH_OFFSETr, STAGE3_HASH_OFFSETr
   1810 };
   1811 
   1812 soc_field_t _ism_stage_hash_cfg_fld[] = {
   1813     BANK0_HASH_OFFSETf, BANK1_HASH_OFFSETf,
   1814     BANK2_HASH_OFFSETf, BANK3_HASH_OFFSETf,
   1815     BANK4_HASH_OFFSETf
   1816 };
   1817 
   1818 /* Configure hash offset per bank */
   1819 int 
   1820 soc_ism_hash_offset_config(int unit, uint8 bank, uint8 offset)
   1821 {
   1822     uint8 i, b, stage, set_idx, found = 0;
   1823     uint32 rval;
   1824     int disabled_banks = 0;
   1825 
   1826     if ((bank >= SOC_ISM_INFO(unit)->max_banks) || (offset > 63)) {
   1827         return SOC_E_PARAM;
   1828     }
   1829     if ((!_soc_ism_bank_avail[unit][bank]) || 
   1830         (_soc_ism_bank_avail[unit][bank] >= SOC_ISM_MEM_MAX)) {
   1831         return SOC_E_PARAM;
   1832     }
   1833     stage = bank/SOC_ISM_INFO(unit)->banks_per_stage;
   1834     disabled_banks = ((SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_96) ||
   1835               (SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_80)) ?
   1836               ((SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_64) ? 2 : 1) : 0;
   1837     b = (bank%SOC_ISM_INFO(unit)->banks_per_stage) + disabled_banks;
   1838     
   1839     SOC_IF_ERROR_RETURN
   1840         (soc_reg32_get(unit, _ism_stage_hash_cfg_reg[stage], REG_PORT_ANY, 
   1841                        0, &rval));
   1842     soc_reg_field_set(unit, _ism_stage_hash_cfg_reg[stage], 
   1843                       &rval, _ism_stage_hash_cfg_fld[b], offset);
   1844     SOC_IF_ERROR_RETURN
   1845         (soc_reg32_set(unit, _ism_stage_hash_cfg_reg[stage], REG_PORT_ANY, 
   1846                        0, rval));
   1847     set_idx = _soc_ism_bank_avail[unit][bank] - 1;
   1848     for (i = 0; i < _SOC_ISM_SETS(unit)[set_idx].num_banks; i++) {
   1849         if (_SOC_ISM_SETS(unit)[set_idx].shb[i].my_id == bank) {
   1850             _SOC_ISM_SETS(unit)[set_idx].shb[i].hash_offset = offset;
   1851             found = 1;
   1852             break;
   1853         }
   1854     }
   1855     if (!found) {
   1856         LOG_ERROR(BSL_LS_SOC_COMMON,
   1857                   (BSL_META_U(unit,
   1858                               "No memory mapped to bank: %d\n"), bank));
   1859         return SOC_E_INTERNAL;
   1860     }
   1861     return SOC_E_NONE;
   1862 }
   1863 
   1864 /* Get max allowed offset value that can be used for any bank */
   1865 int
   1866 soc_ism_hash_max_offset_get(int unit, int *offset)
   1867 {
   1868     if (offset) {
   1869         *offset = 64;
   1870     }
   1871     return SOC_E_NONE;
   1872 }
   1873 
   1874 /* Configure hash offset per mem */
   1875 int 
   1876 soc_ism_hash_mem_offset_config(int unit, soc_mem_t mem, uint8 count, 
   1877                                uint8 *offset)
   1878 {
   1879     return SOC_E_NONE;
   1880 }
   1881 
   1882 /* Get hash offset per bank */
   1883 int 
   1884 soc_ism_hash_offset_config_get(int unit, uint8 bank, uint8 *offset)
   1885 {
   1886     uint8 i, set_idx, found = 0;
   1887 
   1888     if (bank >= SOC_ISM_INFO(unit)->max_banks) {
   1889         return SOC_E_PARAM;
   1890     }    
   1891     set_idx = _soc_ism_bank_avail[unit][bank] - 1;
   1892     
   1893 #ifdef BCM_WARM_BOOT_SUPPORT
   1894     if (SOC_WARM_BOOT(unit)) {
   1895         uint8 b, stage;
   1896         uint32 rval, val;
   1897         int disabled_banks = 0;
   1898     
   1899         if (bank >= SOC_ISM_INFO(unit)->max_banks) {
   1900             return SOC_E_PARAM;
   1901         }
   1902         if ((!_soc_ism_bank_avail[unit][bank]) || 
   1903             (_soc_ism_bank_avail[unit][bank] >= SOC_ISM_MEM_MAX)) {
   1904             return SOC_E_PARAM;
   1905         }
   1906         stage = bank/SOC_ISM_INFO(unit)->banks_per_stage;
   1907         disabled_banks = ((SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_96) ||
   1908                    (SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_80)) ?
   1909                    ((SOC_ISM_INFO(unit)->ism_mode == 
   1910                                             _ISM_SIZE_MODE_64) ? 2 : 1) : 0;
   1911         b = (bank%SOC_ISM_INFO(unit)->banks_per_stage) + disabled_banks;
   1912         
   1913         SOC_IF_ERROR_RETURN
   1914             (soc_reg32_get(unit, _ism_stage_hash_cfg_reg[stage], REG_PORT_ANY, 
   1915                            0, &rval));
   1916         val = soc_reg_field_get(unit, _ism_stage_hash_cfg_reg[stage], 
   1917                                 rval, _ism_stage_hash_cfg_fld[b]);
   1918         for (i = 0; i < _SOC_ISM_SETS(unit)[set_idx].num_banks; i++) {
   1919             if (_SOC_ISM_SETS(unit)[set_idx].shb[i].my_id == bank) {
   1920                 *offset = val;
   1921                 _SOC_ISM_SETS(unit)[set_idx].shb[i].hash_offset = val;
   1922                 found = 1;
   1923                 break;
   1924             }
   1925         }
   1926     } else 
   1927 #endif /* BCM_WARM_BOOT_SUPPORT */
   1928     {    
   1929         for (i = 0; i < _SOC_ISM_SETS(unit)[set_idx].num_banks; i++) {
   1930             if (_SOC_ISM_SETS(unit)[set_idx].shb[i].my_id == bank) {
   1931                 *offset = _SOC_ISM_SETS(unit)[set_idx].shb[i].hash_offset;
   1932                 found = 1;
   1933                 break;
   1934             }
   1935         }
   1936     }
   1937     if (!found) {
   1938         LOG_ERROR(BSL_LS_SOC_COMMON,
   1939                   (BSL_META_U(unit,
   1940                               "No memory mapped to bank: %d\n"), bank));
   1941         return SOC_E_INTERNAL;
   1942     }
   1943     return SOC_E_NONE;
   1944 }
   1945  
   1946 /* Get hash offset per table */
   1947 int 
   1948 soc_ism_hash_table_offset_config_get(int unit, soc_ism_mem_type_t table, 
   1949                                      uint8 *offset, uint8 *count)
   1950 {
   1951     int i, rv;
   1952     uint8 banks[_SOC_ISM_MAX_BANKS];
   1953     uint32 bank_size[_SOC_ISM_MAX_BANKS];
   1954     
   1955     rv = soc_ism_get_banks(unit, table, banks, bank_size, count);
   1956     for (i = 0; i < *count; i++) {
   1957         rv |= soc_ism_hash_offset_config_get(unit, banks[i], &offset[i]);
   1958     }
   1959     return SOC_E_NONE;
   1960 }
   1961 
   1962 /* Get hash offset per mem */
   1963 int 
   1964 soc_ism_hash_mem_offset_config_get(int unit, soc_mem_t mem, uint8 *offset, 
   1965                                    uint8 *count)
   1966 {
   1967     int8 memidx;
   1968     
   1969     if ((memidx = soc_ism_get_hash_mem_idx(unit, mem)) < 0) {
   1970         return SOC_E_PARAM;
   1971     }
   1972     return soc_ism_hash_table_offset_config_get(unit, _SOC_ISM_MEMS(unit)[memidx].shms->mem_set,
   1973                                                 offset, count);
   1974 }
   1975 
   1976 /* Configure hash type per table */
   1977 int 
   1978 soc_ism_table_hash_config(int unit, soc_ism_mem_type_t table, uint8 zero_lsb)
   1979 {
   1980     uint32 rval;
   1981     if (!table || table >= SOC_ISM_MEM_MAX) {
   1982         return SOC_E_PARAM;
   1983     }
   1984     SOC_IF_ERROR_RETURN
   1985         (soc_reg32_get(unit, _ism_table_bank_cfg_reg[table-1], REG_PORT_ANY, 
   1986                        0, &rval));
   1987     soc_reg_field_set(unit, _ism_table_bank_cfg_reg[table-1], 
   1988                       &rval, HASH_ZERO_OR_LSBf, zero_lsb);
   1989     SOC_IF_ERROR_RETURN
   1990         (soc_reg32_set(unit, _ism_table_bank_cfg_reg[table-1], REG_PORT_ANY, 
   1991                        0, rval));
   1992     _SOC_ISM_SETS(unit)[table-1].zero_lsb = zero_lsb;
   1993     return SOC_E_NONE;
   1994 }
   1995 
   1996 /* Configure hash type per mem */
   1997 int 
   1998 soc_ism_mem_hash_config(int unit, soc_mem_t mem, uint8 zero_lsb)
   1999 {
   2000     int8 memidx;
   2001     if ((memidx = soc_ism_get_hash_mem_idx(unit, mem)) < 0) {
   2002         return SOC_E_PARAM;
   2003     }
   2004     return soc_ism_table_hash_config(unit, _SOC_ISM_MEMS(unit)[memidx].shms->mem_set, 
   2005                                      zero_lsb);
   2006 }
   2007 
   2008 /* Get hash type per table */
   2009 int 
   2010 soc_ism_table_hash_config_get(int unit, soc_ism_mem_type_t table, uint8 *zero_lsb)
   2011 {
   2012     if (!table || table >= SOC_ISM_MEM_MAX) {
   2013         return SOC_E_PARAM;
   2014     }
   2015 #ifdef BCM_WARM_BOOT_SUPPORT
   2016     if (SOC_WARM_BOOT(unit)) {
   2017         uint32 rval, val;
   2018         SOC_IF_ERROR_RETURN
   2019         (soc_reg32_get(unit, _ism_table_bank_cfg_reg[table-1], REG_PORT_ANY, 
   2020                        0, &rval));
   2021         val = soc_reg_field_get(unit, _ism_table_bank_cfg_reg[table-1], 
   2022                                 rval, HASH_ZERO_OR_LSBf);
   2023         *zero_lsb = val;
   2024         _SOC_ISM_SETS(unit)[table-1].zero_lsb = val;
   2025     } else 
   2026 #endif /* BCM_WARM_BOOT_SUPPORT */
   2027     {
   2028         *zero_lsb = _SOC_ISM_SETS(unit)[table-1].zero_lsb;
   2029     }
   2030     return SOC_E_NONE;
   2031 }
   2032 
   2033 /* Get hash type per mem */
   2034 int 
   2035 soc_ism_mem_hash_config_get(int unit, soc_mem_t mem, uint8 *zero_lsb)
   2036 {
   2037     int8 memidx;
   2038     if ((memidx = soc_ism_get_hash_mem_idx(unit, mem)) < 0) {
   2039         return SOC_E_PARAM;
   2040     }
   2041     return soc_ism_table_hash_config_get(unit, _SOC_ISM_MEMS(unit)[memidx].shms->mem_set, 
   2042                                          zero_lsb);
   2043 }
   2044 
   2045 /* Get key length per mem */
   2046 int 
   2047 soc_ism_mem_max_key_bits_get(int unit, soc_mem_t mem)
   2048 {
   2049     int8 memidx;
   2050     if ((memidx = soc_ism_get_hash_mem_idx(unit, mem)) < 0) {
   2051         return SOC_E_PARAM;
   2052     }
   2053     return _SOC_ISM_MEMS(unit)[memidx].shms->max_key_bits; 
   2054 }
   2055 
   2056 int
   2057 soc_ism_get_total_banks(int unit, int *count)
   2058 {
   2059     if (count) {
   2060         *count = SOC_ISM_INFO(unit)->max_banks;
   2061     }
   2062     return SOC_E_NONE;
   2063 }
   2064 
   2065 /* Get configured banks and count per table */
   2066 int 
   2067 soc_ism_get_banks(int unit, soc_ism_mem_type_t table, uint8 *banks, 
   2068                   uint32 *bank_size, uint8 *count)
   2069 {
   2070     uint8 i;
   2071     if (count) {
   2072         *count = 0;
   2073     } else {
   2074         return SOC_E_PARAM;
   2075     }
   2076     for (i = 0; i < SOC_ISM_INFO(unit)->max_banks; i++) {
   2077         if (_soc_ism_bank_avail[unit][i] == table) {
   2078             if (banks) {
   2079                 banks[*count] = i;
   2080             }
   2081             if (bank_size) {
   2082                 bank_size[*count] = SOC_ISM_INFO(unit)->bank_raw_sizes[i];
   2083             }
   2084             (*count)++;
   2085         }
   2086     }
   2087     return SOC_E_NONE;
   2088 }
   2089 
   2090 /* Get configured banks and count per mem */
   2091 int
   2092 soc_ism_get_banks_for_mem(int unit, soc_mem_t mem, uint8 *banks, 
   2093                           uint32 *bank_size, uint8 *count)
   2094 {
   2095     int8 memidx;
   2096     if ((memidx = soc_ism_get_hash_mem_idx(unit, mem)) < 0) {
   2097         return SOC_E_PARAM;
   2098     }
   2099     if (_SOC_ISM_MEMS(unit)[memidx].shms->num_banks) {
   2100         return soc_ism_get_banks(unit, _SOC_ISM_MEMS(unit)[memidx].shms->mem_set, 
   2101                                  banks, bank_size, count);
   2102     } else {
   2103         *count = 0;
   2104         return SOC_E_NONE;
   2105     }
   2106 }
   2107 
   2108 uint32
   2109 soc_ism_get_phy_bank_mask(int unit, uint32 bank_mask)
   2110 {
   2111     uint32 offset = 1, bank = 0;
   2112     if (-1 == bank_mask || 0 == bank_mask) {
   2113         return bank_mask;
   2114     }
   2115     
   2116     if ((SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_96) ||
   2117         (SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_80) ||
   2118         (SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_176)) {
   2119         int i;
   2120         
   2121         for (i=0; i<32; i++) {
   2122             if (bank_mask & (1<<i)) {
   2123                 bank = i;
   2124                 break;
   2125             }
   2126         }
   2127         if ((SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_96) ||
   2128             (SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_80)) {
   2129             /* First bank is not available */
   2130         } else if (SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_176) {
   2131             /* Last bank is not available */
   2132             offset = 0;
   2133         }
   2134         /* Coverity 
   2135          * Number of ism banks do not exceed 16.
   2136          */
   2137         /* coverity[large_shift : FALSE] */
   2138         return 1 << (bank + offset + bank/4);
   2139     } else {
   2140         return bank_mask;
   2141     }
   2142 }
   2143 
   2144 /* Get key and lsb fields and count from a mem entry */
   2145 int 
   2146 soc_generic_get_hash_key(int unit, soc_mem_t mem, void *entry, 
   2147                          soc_field_t *keyf, soc_field_t *lsbf, uint8 *num_flds)
   2148 {
   2149     int i, j, f = 0, found;
   2150     int key_type; 
   2151     if (SOC_MEM_FIELD_VALID(unit, mem, KEY_TYPEf)) {
   2152         key_type = soc_mem_field32_get(unit, mem, entry, KEY_TYPEf);
   2153     } else {
   2154         key_type = soc_mem_field32_get(unit, mem, entry, KEY_TYPE_0f);
   2155     }
   2156     i = soc_ism_get_hash_mem_idx(unit, mem);
   2157     if (i < 0) {
   2158         LOG_ERROR(BSL_LS_SOC_COMMON,
   2159                   (BSL_META_U(unit,
   2160                               "Invalid hash memory !!\n")));
   2161         return SOC_E_PARAM;
   2162     }
   2163     found = 0;
   2164     for (j = 0; j < _SOC_ISM_MEMS(unit)[i].shms->num_keys; j++) {
   2165         if (key_type == _SOC_ISM_MEMS(unit)[i].shms->shk[j].key_type) {
   2166             LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   2167                         (BSL_META_U(unit,
   2168                                     "Retreived key_type: %d for mem: %s\n"), 
   2169                          key_type, SOC_MEM_NAME(unit, mem)));
   2170             found = 1;
   2171             break;
   2172         }  
   2173     }
   2174     if (!found) {
   2175         return SOC_E_INTERNAL;
   2176     }
   2177     while (_SOC_ISM_MEMS(unit)[i].shms->shk[j].hmv->key_fields[f] != -1) { 
   2178         keyf[f] = _SOC_ISM_MEMS(unit)[i].shms->shk[j].hmv->key_fields[f];
   2179         f++;
   2180         *num_flds = f; 
   2181     }
   2182     *lsbf = _SOC_ISM_MEMS(unit)[i].shms->shk[j].hmv->lsb_field;
   2183     return SOC_E_NONE;
   2184 }
   2185 
   2186 /* helper routine */
   2187 STATIC uint32
   2188 _soc_crc32b(uint8 *data, int data_nbits)
   2189 {
   2190     uint32 rv;
   2191     rv = _shr_crc32b(0, data, data_nbits);
   2192     rv = _shr_bit_rev_by_byte_word32(rv);
   2193     return rv;
   2194 }
   2195 
   2196 /* helper routine */
   2197 STATIC uint16
   2198 _soc_crc16b(uint8 *data, int data_nbits)
   2199 {
   2200     uint16 rv;
   2201     rv = _shr_crc16b(0, data, data_nbits);
   2202     rv = _shr_bit_rev16(rv);
   2203     return rv;
   2204 }
   2205 
   2206 /* Generate hash value from key using lsb or crc based upon config and offset */
   2207 int
   2208 soc_generic_gen_hash(int unit, uint32 zero_lsb, uint32 num_bits, 
   2209                      uint32 offset, uint32 mask, uint8 *key, uint16 lsb)
   2210 {
   2211     uint64 val, tmp;
   2212     uint32 crc_lo;
   2213     uint16 crc_hi;
   2214     int32 i, j = 0;
   2215     LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   2216                 (BSL_META_U(unit,
   2217                             "Num bits: %d, zero_lsb: %d, lsb: %x, offset: %d, "
   2218                             "mask: %x\n"), num_bits, zero_lsb, lsb, offset, mask));
   2219     /* mask bit 0 of key */
   2220     key[0] &= 0xfe;
   2221     LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   2222                 (BSL_META_U(unit,
   2223                             "Key: [")));
   2224     for (i = num_bits; i > 0; i-=8) {
   2225         LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   2226                     (BSL_META_U(unit,
   2227                                 "%0x"), key[j++]));
   2228     }
   2229     LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   2230                 (BSL_META_U(unit,
   2231                             "]\n")));
   2232     if (offset >= 48) {
   2233         if (!zero_lsb) {
   2234             LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   2235                         (BSL_META_U(unit,
   2236                                     "Hash(zero)\n")));
   2237             return 0;
   2238         } else {
   2239             if (offset > 48) {
   2240                 lsb = lsb >> (offset-48);
   2241             }
   2242             lsb &= mask;
   2243             LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   2244                         (BSL_META_U(unit,
   2245                                     "Hash(lsb): %d\n"), lsb));
   2246             return lsb & mask;
   2247         }
   2248     } else {
   2249         crc_lo = _soc_crc32b(key, num_bits);
   2250         crc_hi = _soc_crc16b(key, num_bits);
   2251         LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   2252                     (BSL_META_U(unit,
   2253                                 "crc32: %x\n"), crc_lo));
   2254         LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   2255                     (BSL_META_U(unit,
   2256                                 "crc16: %x\n"), crc_hi));
   2257         COMPILER_64_SET(val, crc_hi, crc_lo);
   2258         if (offset) {
   2259             COMPILER_64_SHR(val, offset);
   2260         }
   2261         COMPILER_64_SET(tmp, 0, mask);
   2262         COMPILER_64_AND(val, tmp);
   2263         COMPILER_64_TO_32_LO(crc_lo, val);
   2264         LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   2265                     (BSL_META_U(unit,
   2266                                 "Hash(crc): %d\n"), crc_lo));
   2267         return crc_lo & mask;
   2268     }
   2269     return SOC_E_NONE;
   2270 }
   2271 
   2272 /* return mask based upon bank size */
   2273 int
   2274 soc_ism_get_hash_bucket_mask(int buckets)
   2275 {
   2276     switch (buckets) {
   2277     case 1024: return 0x3ff;
   2278     case 2048: return 0x7ff;
   2279     case 4096: return 0xfff;
   2280     case 8192: return 0x1fff;
   2281     case 16384: return 0x3fff;
   2282     default: return SOC_E_PARAM;
   2283     }
   2284 }
   2285 
   2286 /* return num of bits based upon bank size */
   2287 int 
   2288 soc_ism_get_hash_bits(int buckets)
   2289 {
   2290     switch (buckets) {
   2291     case 1024: return 10;
   2292     case 2048: return 11;
   2293     case 4096: return 12;
   2294     case 8192: return 13;
   2295     case 16384: return 14;
   2296     default: return SOC_E_PARAM;
   2297     }
   2298 }
   2299 
   2300 /* helper routine */
   2301 STATIC void
   2302 _soc_hash_check_and_swap(_soc_ism_sbo_t *lx, _soc_ism_sbo_t *ly, int x, int y)
   2303 {
   2304     _soc_ism_sbo_t t;
   2305     if (x > y) {
   2306         t = *lx;
   2307         *lx = *ly;
   2308         *ly = t;
   2309     }
   2310 }
   2311 
   2312 /* helper routine */
   2313 STATIC void
   2314 _soc_sort_bank_on_criteria(_soc_ism_sbo_t *list, uint8 size, uint8 criteria)
   2315 {
   2316     uint8 x, y;
   2317     for (x=0; x < size-1; x++) {
   2318         for (y=0; y < size-x-1; y++) {
   2319             switch (criteria) {
   2320             case _CRITERIA_ENTRY: _soc_hash_check_and_swap(&list[y], &list[y+1], 
   2321                                                            list[y].entry, 
   2322                                                            list[y+1].entry);
   2323                 break;
   2324             case _CRITERIA_STAGE: _soc_hash_check_and_swap(&list[y], &list[y+1], 
   2325                                                            list[y].stage, 
   2326                                                            list[y+1].stage);
   2327                 break;
   2328             case _CRITERIA_BANK: _soc_hash_check_and_swap(&list[y], &list[y+1], 
   2329                                                           list[y].bank, 
   2330                                                           list[y+1].bank);
   2331                 break;
   2332             }
   2333         }
   2334     }
   2335 }
   2336 
   2337 /* determine the best entry index from multiple banks using various criterias */
   2338 void
   2339 soc_ism_resolve_entry_index(_soc_ism_sbo_t *sbo, uint8 num_banks)
   2340 {
   2341     uint8 b, tie=0;
   2342     _soc_sort_bank_on_criteria(sbo, num_banks, _CRITERIA_ENTRY);
   2343     /* determine if there is a tie and sort further */
   2344     for (b = 0; b < num_banks - 1; b++) {
   2345         if (sbo[b].entry == sbo[b+1].entry) {
   2346             tie++;
   2347         } else {
   2348             break;
   2349         }
   2350     }
   2351     if (!tie) {
   2352         return;
   2353     }
   2354     _soc_sort_bank_on_criteria(sbo, tie, _CRITERIA_BANK);
   2355     num_banks = tie;
   2356     tie=0;
   2357     /* determine if there is a tie and sort further */
   2358     for (b = 0; b < num_banks - 1; b++) {
   2359         if (sbo[b].bank == sbo[b+1].bank) {
   2360             tie++;
   2361         } else {
   2362             break;
   2363         }
   2364     }
   2365     if (!tie) {
   2366         return;
   2367     }
   2368     num_banks = tie;
   2369     tie=0;
   2370     /* determine if there is a tie and sort further */
   2371     _soc_sort_bank_on_criteria(sbo, num_banks, _CRITERIA_STAGE);
   2372 }
   2373 
   2374 /* helper function: It has specific memory names and logic but that is only to 
   2375    make it work as fast as possible */
   2376 uint8
   2377 soc_ism_get_bucket_offset(int unit, soc_mem_t mem, int8 midx, void *new_entry, 
   2378                           void *existing_entry)
   2379 {
   2380     uint8 i, incr = 1, kts;
   2381     uint32 new_kt, existing_kt;
   2382     soc_hash_mem_set_t *shms;
   2383     soc_hash_mem_t *shm;
   2384     
   2385     if (midx < 0) {
   2386         midx = soc_ism_get_hash_mem_idx(unit, mem);
   2387     }
   2388     shms = _SOC_ISM_MEMS(unit)[midx].shms;
   2389     if (shms->num_mems == 1) {
   2390         return incr;
   2391     }
   2392     if ((mem == L2_ENTRY_1m) || (mem == L2_ENTRY_2m)) {
   2393         if (soc_mem_field32_get(unit, L2_ENTRY_1m, existing_entry, WIDEf)) {
   2394             return 2;
   2395         } else {
   2396             if (soc_mem_field32_get(unit, L2_ENTRY_1m, new_entry, WIDEf)) {
   2397                 return 2;
   2398             }
   2399             return incr;
   2400         }
   2401     }
   2402     if (SOC_MEM_FIELD_VALID(unit, mem, KEY_TYPEf)) {
   2403         new_kt = soc_mem_field32_get(unit, mem, new_entry, KEY_TYPEf);
   2404     } else {
   2405         new_kt = soc_mem_field32_get(unit, mem, new_entry, KEY_TYPE_0f);
   2406     }
   2407     if (SOC_MEM_FIELD_VALID(unit, mem, KEY_TYPEf)) {
   2408         existing_kt = soc_mem_field32_get(unit, mem, existing_entry, KEY_TYPEf);
   2409     } else {
   2410         existing_kt = soc_mem_field32_get(unit, mem, existing_entry, KEY_TYPE_0f);
   2411     }
   2412     kts = shms->num_keys;
   2413     for (i=0; i<kts; i++) {
   2414         if (shms->shk[i].key_type == existing_kt) {
   2415             shm = shms->shk[i].hmv->shm;
   2416             if (shm->mem == VLAN_XLATEm || shm->mem == L3_ENTRY_1m || 
   2417                 shm->mem == MPLS_ENTRYm) {
   2418                 break;
   2419             } else if (shm->mem == VLAN_XLATE_EXTDm || shm->mem == L3_ENTRY_2m || 
   2420                        shm->mem == MPLS_ENTRY_EXTDm) {
   2421                 incr = 2;
   2422                 break;
   2423             } else {
   2424                 return 4;
   2425             }
   2426         }
   2427     }
   2428     /* Need to check new entry's size and return index increment appropriately */
   2429     for (i=0; i<kts; i++) {
   2430         if (shms->shk[i].key_type == new_kt) {
   2431             shm = shms->shk[i].hmv->shm;
   2432             if (shm->mem == VLAN_XLATEm || shm->mem == L3_ENTRY_1m || 
   2433                 shm->mem == MPLS_ENTRYm) {
   2434                 return (incr > 1) ? incr : 1;
   2435             } else if (shm->mem == VLAN_XLATE_EXTDm || shm->mem == L3_ENTRY_2m || 
   2436                        shm->mem == MPLS_ENTRY_EXTDm) {
   2437                 return 2;
   2438             } else {
   2439                 return 4;
   2440             }
   2441         }
   2442     }
   2443     return incr;
   2444 }
   2445 
   2446 /* helper function */
   2447 STATIC void
   2448 _soc_append_mem_field_to_data(soc_mem_info_t *meminfo, uint8 *key, uint16 offset, 
   2449                               uint32 *fldbuf, uint16 size, uint8 lendian)
   2450 {
   2451     int32 len;
   2452     uint32 mask, i, wp, bp;
   2453     uint32 *entbuf = (uint32 *)key;
   2454 
   2455     LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   2456                 (BSL_META("offset: %d, size: %d\n"), offset, size));
   2457     if (lendian) {
   2458         wp = offset / 32;
   2459         bp = offset & (32 - 1);
   2460         i = 0;
   2461         for (len = size; len > 0; len -= 32) {
   2462             if (bp) {
   2463                 if (len < 32) {
   2464                     mask = (1 << len) - 1;
   2465                 } else {
   2466                     mask = -1;
   2467                 }
   2468 
   2469                 entbuf[FIX_MEM_ORDER_E(wp, meminfo)] &= ~(mask << bp);
   2470                 entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] |= fldbuf[i] << bp;
   2471                 if (len > (32 - bp)) {
   2472                     entbuf[FIX_MEM_ORDER_E(wp, meminfo)] &= ~(mask >> (32 - bp));
   2473                     entbuf[FIX_MEM_ORDER_E(wp, meminfo)] |=
   2474                         fldbuf[i] >> (32 - bp) & ((1 << bp) - 1);
   2475                 }
   2476             } else {
   2477                 if (len < 32) {
   2478                     mask = (1 << len) - 1;
   2479                     entbuf[FIX_MEM_ORDER_E(wp, meminfo)] &= ~mask;
   2480                     entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] |= fldbuf[i] << bp;
   2481                 } else {
   2482                     entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] = fldbuf[i];
   2483                 }
   2484             }
   2485             i++;
   2486         }
   2487     } else {
   2488         bp = offset;
   2489         len = size;
   2490         while (len > 0) {
   2491             len--;
   2492             entbuf[FIX_MEM_ORDER_E(bp / 32, meminfo)] &= ~(1 << (bp & (32-1)));
   2493             entbuf[FIX_MEM_ORDER_E(bp / 32, meminfo)] |=
   2494                 (fldbuf[len / 32] >> (len & (32-1)) & 1) << (bp & (32-1));
   2495             bp++;
   2496         }
   2497     }
   2498 }
   2499 
   2500 /* Create final key by concatenating various key fields from a mem entry */
   2501 void
   2502 soc_ism_gen_key_from_keyfields(int unit, soc_mem_t mem, void *entry, 
   2503                                soc_field_t *keyflds, uint8 *key, uint8 num_flds)
   2504 {
   2505     int16 i;
   2506     uint8 j = 0;
   2507     uint32 val[SOC_MAX_MEM_WORDS];
   2508     uint16 offset = 0, len;
   2509     soc_mem_info_t *meminfo;
   2510     soc_field_info_t *fieldinfo;
   2511     meminfo = &SOC_MEM_INFO(unit, mem);
   2512 
   2513     for (i = 0; i < num_flds; i++) {
   2514         SOC_FIND_FIELD(keyflds[i], meminfo->fields, meminfo->nFields,
   2515                        fieldinfo);
   2516         if (NULL == fieldinfo) {
   2517             LOG_CLI((BSL_META_U(unit,
   2518                                 "mem %s field %s is invalid\n"),
   2519                      SOC_MEM_NAME(unit, mem), SOC_FIELD_NAME(unit, keyflds[i])));
   2520             assert(fieldinfo);
   2521         }
   2522         soc_mem_field_get(unit, mem, entry, keyflds[i], val);
   2523         len = soc_mem_field_length(unit, mem, keyflds[i]);
   2524         _soc_append_mem_field_to_data(meminfo, key, offset, val, len,
   2525                                       fieldinfo->flags & SOCF_LE);
   2526         offset += len;
   2527     }
   2528     LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   2529                 (BSL_META_U(unit,
   2530                             "Combined Key: ")));
   2531     for (i = offset; i > 0; i-=8) {
   2532         LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   2533                     (BSL_META_U(unit,
   2534                                 "%0x "), key[j++]));
   2535     }
   2536     LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   2537                 (BSL_META_U(unit,
   2538                             "\n")));
   2539 }
   2540 
   2541 /* Create key to be used in crc calculation by concatenating various key fields 
   2542    from a mem entry and taking care of padding, alignment etc */
   2543 void
   2544 soc_ism_gen_crc_key_from_keyfields(int unit, soc_mem_t mem, void *entry, 
   2545                                    soc_field_t *keyflds, uint8 *key, 
   2546                                    uint8 num_flds, uint16 *bit_count)
   2547 {
   2548     uint8 i;
   2549     soc_field_t field;
   2550     uint16 key_index, val_index, fval_index;
   2551     uint16 right_shift_count, left_shift_count;
   2552     uint32 val[SOC_MAX_MEM_WORDS], fval[SOC_MAX_MEM_WORDS];
   2553     int16 val_bits = *bit_count, fval_bits;
   2554     uint16 bits, field_length[16];
   2555     int key_type;
   2556     
   2557     for (i = 0; i < num_flds; i++) {
   2558         field = keyflds[i];
   2559         field_length[i] = soc_mem_field_length(unit, mem, field);
   2560     }
   2561     
   2562     bits = (val_bits + 7) & ~0x7;
   2563     sal_memset(val, 0, sizeof(val));
   2564     val_bits = bits - val_bits;
   2565     for (i = 0; i < num_flds; i++) {
   2566         field = keyflds[i];
   2567         soc_mem_field_get(unit, mem, entry, field, fval);
   2568         
   2569         /* For TR3, only key_types that support regular/extended entries should
   2570            force key_type[0] to 0 for the hash calculation. These memories are
   2571            handled below */
   2572 
   2573         if(SOC_IS_TRIUMPH3(unit)) {
   2574 
   2575             if (SOC_MEM_FIELD_VALID(unit, mem, KEY_TYPEf)) {
   2576                 key_type = soc_mem_field32_get(unit, mem, entry, KEY_TYPEf);
   2577             } else {
   2578                 key_type = soc_mem_field32_get(unit, mem, entry, KEY_TYPE_0f);
   2579             }
   2580 
   2581             if (mem == L2_ENTRY_1m) {
   2582                 if ((key_type == SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE) ||
   2583                     (key_type == SOC_MEM_KEY_L2_ENTRY_1_L2_VFI)) {
   2584                         fval[0] &= ~1;
   2585                 }
   2586             } else  if (mem == L2_ENTRY_2m) {
   2587                 if ((key_type == SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE) ||
   2588                     (key_type == SOC_MEM_KEY_L2_ENTRY_2_L2_VFI)) {
   2589                         fval[0] &= ~1;
   2590                 }
   2591             } else if (mem == VLAN_XLATE_EXTDm) {
   2592                 if ((key_type == SOC_MEM_KEY_VLAN_XLATE_2_XLATE_IVID_OVID) ||
   2593                     (key_type == SOC_MEM_KEY_VLAN_XLATE_2_XLATE_OVID) ||
   2594                     (key_type == SOC_MEM_KEY_VLAN_XLATE_2_XLATE_IVID) ||
   2595                     (key_type == SOC_MEM_KEY_VLAN_XLATE_2_XLATE_OTAG) ||
   2596                     (key_type == SOC_MEM_KEY_VLAN_XLATE_2_XLATE_ITAG) ||
   2597                     (key_type == SOC_MEM_KEY_VLAN_XLATE_2_XLATE_PRI_CFI) ||
   2598                     (key_type == SOC_MEM_KEY_VLAN_XLATE_2_XLATE_IVID_OVID_SVP) ||
   2599                     (key_type == SOC_MEM_KEY_VLAN_XLATE_2_XLATE_OVID_SVP)) {
   2600                         fval[0] &= ~1;
   2601                 }
   2602             } else if (mem == L3_ENTRY_2m) {
   2603                 if (key_type == SOC_MEM_KEY_L3_ENTRY_2_IPV4UC_IPV4_UNICAST) {
   2604                         fval[0] &= ~1;
   2605                 }
   2606             } else if (mem == L3_ENTRY_4m) {
   2607                 if(key_type == SOC_MEM_KEY_L3_ENTRY_4_IPV6UC_IPV6_UNICAST) {
   2608                         fval[0] &= ~1;
   2609                 }
   2610             } else if (mem == MPLS_ENTRY_EXTDm) {
   2611                 if ((key_type == SOC_MEM_KEY_MPLS_ENTRY_2_MPLS_MPLS_FIRST_PASS) ||
   2612                     (key_type == SOC_MEM_KEY_MPLS_ENTRY_2_MPLS_MPLS_SECOND_PASS)) {
   2613                         fval[0] &= ~1;
   2614                 }
   2615             }
   2616         } else {
   2617             fval[0] &= ~1;
   2618         }
   2619         
   2620         fval_bits = field_length[i];
   2621 
   2622         val_index = val_bits >> 5;
   2623         fval_index = 0;
   2624         left_shift_count = val_bits & 0x1f;
   2625         right_shift_count = 32 - left_shift_count;
   2626         val_bits += fval_bits;
   2627 
   2628         if (left_shift_count) {
   2629             for (; fval_bits > 0; fval_bits -= 32) {
   2630                 val[val_index++] |= fval[fval_index] << left_shift_count;
   2631                 val[val_index] |= fval[fval_index++] >> right_shift_count;
   2632             }
   2633         } else {
   2634             for (; fval_bits > 0; fval_bits -= 32) {
   2635                 val[val_index++] = fval[fval_index++];
   2636             }
   2637         }
   2638     }
   2639 
   2640     key_index = 0;
   2641     for (val_index = 0; val_bits > 0; val_index++) {
   2642         for (right_shift_count = 0; right_shift_count < 32;
   2643              right_shift_count += 8) {
   2644             if (val_bits <= 0) {
   2645                 break;
   2646             }
   2647             key[key_index++] = (val[val_index] >> right_shift_count) & 0xff;
   2648             val_bits -= 8;
   2649         }
   2650     }
   2651 
   2652     if ((bits + 7) / 8 > key_index) {
   2653         sal_memset(&key[key_index], 0, (bits + 7) / 8 - key_index);
   2654     }
   2655     *bit_count = bits;
   2656 }
   2657 
   2658 /* Create a valid memory entry from a compacted key */
   2659 int
   2660 soc_gen_entry_from_key(int unit, soc_mem_t mem, uint8 *key, void *entry)
   2661 {
   2662     int8 i, j, f = 0, found = 0;
   2663     uint16 len, num_flds = 0;
   2664     uint32 keyf[4] = {0};
   2665     uint16 minb = 0, maxb;
   2666     uint32 fvalue[SOC_MAX_MEM_WORDS] = {0};
   2667     int key_type; 
   2668     
   2669     if (SOC_MEM_FIELD_VALID(unit, mem, KEY_TYPEf)) {
   2670         len = soc_mem_field_length(unit, mem, KEY_TYPEf);
   2671         soc_bits_get((uint32*)&key[0], 0, len-1, fvalue);
   2672         key_type = fvalue[0];
   2673     } else {
   2674         len = soc_mem_field_length(unit, mem, KEY_TYPE_0f);
   2675         soc_bits_get((uint32*)&key[0], 0, len-1, fvalue);
   2676         key_type = fvalue[0];
   2677     }
   2678     i = soc_ism_get_hash_mem_idx(unit, mem);
   2679     if (i < 0) {
   2680         LOG_ERROR(BSL_LS_SOC_COMMON,
   2681                   (BSL_META_U(unit,
   2682                               "Invalid hash memory !!\n")));
   2683         return SOC_E_PARAM;
   2684     }
   2685     for (j = 0; j < _SOC_ISM_MEMS(unit)[i].shms->num_keys; j++) {
   2686         if (_SOC_ISM_MEMS(unit)[i].shms->shk[j].hmv->shm->mem == mem) {
   2687             if (key_type == _SOC_ISM_MEMS(unit)[i].shms->shk[j].key_type) {
   2688                 found = 1;
   2689                 LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   2690                             (BSL_META_U(unit,
   2691                                         "Input key_type: %d found for mem: %s\n"), 
   2692                              key_type, SOC_MEM_NAME(unit, mem)));
   2693                 break;
   2694             }
   2695         }  
   2696     }
   2697     if (!found) {
   2698         LOG_CLI((BSL_META_U(unit,
   2699                             "Key type not found for this memory !!\n")));
   2700         return SOC_E_INTERNAL;
   2701     }
   2702     while (_SOC_ISM_MEMS(unit)[i].shms->shk[j].hmv->key_fields[f] != -1) { 
   2703         keyf[f] = _SOC_ISM_MEMS(unit)[i].shms->shk[j].hmv->key_fields[f];
   2704         f++;
   2705         num_flds = f; 
   2706     }
   2707     for (i=0; i<num_flds; i++) {
   2708         len = soc_mem_field_length(unit, mem, keyf[i]);
   2709         maxb = minb+len-1;
   2710         /*LOG_CLI((BSL_META_U(unit,
   2711                               "Min: %d, Max: %d\n"), minb, maxb));*/
   2712         soc_bits_get((uint32*)&key[0], minb, maxb, fvalue);
   2713         soc_mem_field_set(unit, mem, entry, keyf[i], fvalue);
   2714         minb = maxb+1;
   2715     }
   2716     /* Make the entry valid and properly sized */
   2717     if (SOC_MEM_FIELD_VALID(unit, mem, VALIDf)) {
   2718         soc_mem_field32_set(unit, mem, entry, VALIDf, 1);
   2719     } else {
   2720         soc_mem_field32_set(unit, mem, entry, VALID_0f, 1);
   2721         soc_mem_field32_set(unit, mem, entry, VALID_1f, 1);
   2722         if (SOC_MEM_FIELD_VALID(unit, mem, VALID_2f)) {
   2723             soc_mem_field32_set(unit, mem, entry, VALID_2f, 1);
   2724             soc_mem_field32_set(unit, mem, entry, VALID_3f, 1);
   2725         }
   2726     }
   2727     if (SOC_MEM_FIELD_VALID(unit, mem, WIDE_0f)) {
   2728         soc_mem_field32_set(unit, mem, entry, WIDE_0f, 1);
   2729         soc_mem_field32_set(unit, mem, entry, WIDE_1f, 1);
   2730     }
   2731     return SOC_E_NONE;
   2732 }
   2733 
   2734 /* Generate entry with key fields set, used for direct comparision */
   2735 int
   2736 soc_gen_key_from_entry(int unit, soc_mem_t mem, void *entry, void *key)
   2737 {
   2738     uint8 i, num_flds;
   2739     uint32 val[SOC_MAX_MEM_WORDS];
   2740     soc_field_t keyflds[MAX_FIELDS], lsbfld;
   2741     soc_mem_info_t *meminfo;
   2742     soc_field_info_t *fieldinfo;    
   2743     int32 memidx = soc_ism_get_hash_mem_idx(unit, mem);
   2744     
   2745     if (memidx < 0) {
   2746         LOG_ERROR(BSL_LS_SOC_COMMON,
   2747                   (BSL_META_U(unit,
   2748                               "Invalid hash memory: %s !!\n"), 
   2749                    SOC_MEM_NAME(unit, mem)));
   2750         return SOC_E_PARAM;
   2751     }
   2752     meminfo = &SOC_MEM_INFO(unit, mem);
   2753     
   2754     if (soc_generic_get_hash_key(unit, mem, entry, keyflds, &lsbfld, 
   2755                                  &num_flds) == SOC_E_NONE) {
   2756         for (i = 0; i < num_flds; i++) {
   2757             SOC_FIND_FIELD(keyflds[i], meminfo->fields, meminfo->nFields,
   2758                            fieldinfo);
   2759             if (NULL == fieldinfo) {
   2760                 LOG_CLI((BSL_META_U(unit,
   2761                                     "mem %s field %s is invalid\n"),
   2762                          SOC_MEM_NAME(unit, mem), SOC_FIELD_NAME(unit, keyflds[i])));
   2763                 assert(fieldinfo);
   2764             }
   2765             soc_mem_field_get(unit, mem, entry, keyflds[i], val);
   2766             soc_mem_field_set(unit, mem, key, keyflds[i], val);
   2767             /* Make the entry valid and properly sized */
   2768             if (SOC_MEM_FIELD_VALID(unit, mem, VALIDf)) {
   2769                 soc_mem_field32_set(unit, mem, key, VALIDf, 1);
   2770             } else {
   2771                 soc_mem_field32_set(unit, mem, key, VALID_0f, 1);
   2772                 soc_mem_field32_set(unit, mem, key, VALID_1f, 1);
   2773                 if (SOC_MEM_FIELD_VALID(unit, mem, VALID_2f)) {
   2774                     soc_mem_field32_set(unit, mem, key, VALID_2f, 1);
   2775                     soc_mem_field32_set(unit, mem, key, VALID_3f, 1);
   2776                 }
   2777             }
   2778             if (SOC_MEM_FIELD_VALID(unit, mem, WIDE_0f)) {
   2779                 soc_mem_field32_set(unit, mem, key, WIDE_0f, 1);
   2780                 soc_mem_field32_set(unit, mem, key, WIDE_1f, 1);
   2781             }
   2782         }
   2783         return SOC_E_NONE;
   2784     }
   2785     return SOC_E_INTERNAL;
   2786 }
   2787 
   2788 /* 
   2789  * Main hash execution routine. 
   2790  * NOTE: Heavily overloaded, modify with care.
   2791  * Returns index, result and optionally the last accessed bucket,
   2792  * number of entries in a bucket for the memory.
   2793  */
   2794 int
   2795 soc_generic_hash(int unit, soc_mem_t mem, void *entry, int32 banks, 
   2796                  uint8 op, int *index, uint32 *result, uint32 *base_idx,
   2797                  uint8 *num_entries)
   2798 {
   2799     int rv;
   2800     soc_hash_bank_t *shbank;
   2801     uint16 lsb, midx, num_bits;
   2802     int32 bits, memidx, bucket = 0;
   2803     uint32 tmp_hs[SOC_MAX_MEM_WORDS];
   2804     uint32 idx, bidx = 0, zero_lsb, offset, mask;
   2805     uint8 idxinc = 1, num_flds, num_banks = 0;
   2806     uint8 found = 0, key[SOC_HASH_MEM_MAX_KEY_BUFFER_SIZE_BYTES], tmp_key[SOC_HASH_MEM_MAX_KEY_BUFFER_SIZE_BYTES], crc_key[SOC_HASH_MEM_MAX_KEY_BUFFER_SIZE_BYTES];
   2807     _soc_ism_sbo_t sbo[_SOC_ISM_MAX_BANKS]; /* Dynamically created bank info based upon
   2808                                                requested banks used for final
   2809                                                bucket/index calculation */
   2810     soc_field_t keyflds[MAX_FIELDS], lsbfld, vf = VALIDf;
   2811 
   2812     memidx = soc_ism_get_hash_mem_idx(unit, mem);
   2813     if (memidx < 0) {
   2814         LOG_ERROR(BSL_LS_SOC_COMMON,
   2815                   (BSL_META_U(unit,
   2816                               "Invalid hash memory !!\n")));
   2817         return SOC_E_PARAM;
   2818     }
   2819     if (!_SOC_ISM_MEMS(unit)[memidx].shms->num_banks) {
   2820         return SOC_E_PARAM;
   2821     }
   2822     if (soc_generic_get_hash_key(unit, mem, entry, keyflds, &lsbfld, 
   2823                                  &num_flds) == SOC_E_NONE) {
   2824         LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   2825                     (BSL_META_U(unit,
   2826                                 "Key field(s): ")));
   2827         for (idx = 0; idx < num_flds; idx++) {
   2828             LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   2829                         (BSL_META_U(unit,
   2830                                     "%d, "), keyflds[idx]));
   2831         }
   2832         LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   2833                     (BSL_META_U(unit,
   2834                                 "\nLsb field: %d\n"), lsbfld));
   2835         sal_memset(key, 0, sizeof(key));
   2836         sal_memset(crc_key, 0, sizeof(crc_key));
   2837         soc_ism_gen_key_from_keyfields(unit, mem, entry, keyflds, key, num_flds);
   2838         num_bits = _SOC_ISM_MEMS(unit)[memidx].shms->max_key_bits;
   2839         soc_ism_gen_crc_key_from_keyfields(unit, mem, entry, keyflds, crc_key, 
   2840                                            num_flds, &num_bits);
   2841         lsb = soc_mem_field32_get(unit, mem, entry, lsbfld);
   2842     } else {
   2843         LOG_CLI((BSL_META_U(unit,
   2844                             "Key field not found !!\n")));
   2845         return -1;
   2846     } 
   2847     shbank = _SOC_ISM_MEMS(unit)[memidx].shms->shb;
   2848     bits = soc_mem_entry_bits(unit, mem);
   2849     if (bits > (_SOC_ISM_ENTRY_BITS * 2)) {
   2850         idxinc = 4;
   2851     } else if (bits > _SOC_ISM_ENTRY_BITS) {
   2852         idxinc = 2;
   2853     }
   2854     zero_lsb = _SOC_ISM_SETS(unit)[_SOC_ISM_MEMS(unit)[memidx].shms->mem_set-1].zero_lsb;
   2855     sal_memset(sbo, 0, sizeof(sbo));
   2856     for (idx = 0; idx < _SOC_ISM_MEMS(unit)[memidx].shms->num_banks; idx++) {
   2857         if (banks != -1) {
   2858             /* only use the indicated bank */
   2859             if (!((((int32)1) << shbank[idx].my_id) & banks)) {
   2860                 continue;
   2861             }
   2862             num_banks++;
   2863         } else {
   2864             num_banks++;
   2865         }
   2866         sbo[bidx].mode = -1;
   2867         sbo[bidx].bidx = bidx;
   2868         mask = soc_ism_get_hash_bucket_mask(shbank[idx].num_bkts);
   2869         offset = shbank[idx].hash_offset;
   2870         bucket = soc_generic_gen_hash(unit, zero_lsb, num_bits, offset, 
   2871                                       mask, crc_key, lsb);
   2872         sbo[bidx].index = bucket;
   2873         LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   2874                     (BSL_META_U(unit,
   2875                                 "Bank[%d]: bucket:%d\n"), bidx, bucket));
   2876         if (base_idx) {
   2877             *base_idx = sbo[bidx].index;
   2878         }
   2879         if (num_entries) {
   2880             *num_entries = shbank[idx].bkt_size/idxinc;
   2881         }
   2882         sbo[bidx].index = (shbank[idx].base_entry/idxinc) + 
   2883                          (sbo[bidx].index * (shbank[idx].bkt_size/idxinc));
   2884         if (op == 0) { /* Special bucket seek op */
   2885             *index = sbo[bidx].index;
   2886             return SOC_E_NONE;
   2887         }
   2888         for (midx = 0; midx < shbank[idx].bkt_size/idxinc;) {
   2889             rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, sbo[bidx].index+midx, 
   2890                               tmp_hs);
   2891             if (SOC_FAILURE(rv)) {
   2892                 return rv;
   2893             } 
   2894             if (!SOC_MEM_FIELD_VALID(unit, mem, VALIDf)) {
   2895                 vf = VALID_0f; 
   2896             }
   2897             if (soc_mem_field32_get(unit, mem, tmp_hs, vf)) {
   2898                 sal_memset(tmp_key, 0, sizeof(tmp_key));
   2899                 /* compare key */
   2900                 soc_ism_gen_key_from_keyfields(unit, mem, tmp_hs, keyflds, 
   2901                                                tmp_key, num_flds);
   2902                 if (!sal_memcmp(key, tmp_key, sizeof(key))) {
   2903                     found++;
   2904                     sbo[bidx].entry = midx;
   2905                     sbo[bidx].stage = shbank[idx].my_id / SOC_ISM_INFO(unit)->banks_per_stage;
   2906                     sbo[bidx].bank = shbank[idx].my_id % SOC_ISM_INFO(unit)->banks_per_stage;
   2907                     sbo[bidx].mode = 1;
   2908                     LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   2909                                 (BSL_META_U(unit,
   2910                                             "Existing mem index: %d\n"), 
   2911                                  sbo[bidx].index+sbo[bidx].entry));
   2912                     if (op != TABLE_INSERT_CMD_MSG) {
   2913                         *index = sbo[bidx].index + midx;
   2914                         if (op == TABLE_LOOKUP_CMD_MSG) { 
   2915                             *result = SCHAN_GEN_RESP_TYPE_FOUND;
   2916                         } else {
   2917                             *result = SCHAN_GEN_RESP_TYPE_DELETED;
   2918                         }
   2919                         return SOC_E_NONE;
   2920                     }
   2921                     break;
   2922                 }
   2923             } else if (op == TABLE_INSERT_CMD_MSG) {
   2924                 found++;
   2925                 sbo[bidx].entry = midx;
   2926                 sbo[bidx].stage = shbank[idx].my_id / SOC_ISM_INFO(unit)->banks_per_stage;
   2927                 sbo[bidx].bank = shbank[idx].my_id % SOC_ISM_INFO(unit)->banks_per_stage;
   2928                 sbo[bidx].mode = 0;
   2929                 LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   2930                             (BSL_META_U(unit,
   2931                                         "New mem index: %d\n"), 
   2932                              sbo[bidx].index+sbo[bidx].entry));
   2933                 break;
   2934             }
   2935             /* Determine bucket offset increment based upon existing entry type/size */
   2936             midx += soc_ism_get_bucket_offset(unit, mem, memidx, entry, tmp_hs);
   2937         }
   2938         bidx++;
   2939     }
   2940     if (!found) {
   2941         if (op == TABLE_INSERT_CMD_MSG) {
   2942             *result = SCHAN_GEN_RESP_TYPE_FULL;
   2943         } else {
   2944             *result = SCHAN_GEN_RESP_TYPE_NOT_FOUND;
   2945             return SOC_E_NONE;
   2946         }
   2947     }
   2948     /* Get the lowest valid/empty index of the lowest bank-id of the lowest stage-id */
   2949     if (found > 1) {
   2950         soc_ism_resolve_entry_index(sbo, num_banks); 
   2951     }
   2952     for (idx = 0; idx < num_banks; idx++) {
   2953         if (sbo[idx].mode >= 0) {
   2954             *index = sbo[idx].index + sbo[idx].entry;
   2955             if (sbo[idx].mode) {
   2956                 *result = SCHAN_GEN_RESP_TYPE_REPLACED;
   2957             } else {
   2958                 *result = SCHAN_GEN_RESP_TYPE_INSERTED;
   2959             }
   2960             break;
   2961         }
   2962     }
   2963     return SOC_E_NONE;
   2964 }
   2965 
   2966 /* 
   2967  * Normalize memory based on the key type:
   2968  *
   2969  * Move entry may be of different Key type and may have been inserted with
   2970  * different memory view. Hence the need to normalize the memory view name
   2971  * with respect to move_entry. The mem field is not the view used to insert
   2972  * the entry, to make space for the incoming entry, existing entries are moved.
   2973  * The move need to happen with respect to the memory view used to insert the 
   2974  * the already existing entry.
   2975  */
   2976 STATIC void 
   2977 soc_mem_multi_hash_norm_mem(int unit, soc_mem_t mem, void *entry, soc_mem_t *norm_mem)
   2978 {
   2979     int s, k, key_type;
   2980     *norm_mem = mem;
   2981     
   2982     if (SOC_MEM_FIELD_VALID(unit, mem, KEY_TYPEf)) {
   2983         key_type = soc_mem_field32_get(unit, mem, entry, KEY_TYPEf);
   2984     } else {
   2985         key_type = soc_mem_field32_get(unit, mem, entry, KEY_TYPE_0f);
   2986     }
   2987     s = soc_ism_get_hash_mem_idx(unit, mem);
   2988     for (k = 0; k < _SOC_ISM_MEMS(unit)[s].shms->num_keys; k++) {
   2989         if (key_type == _SOC_ISM_MEMS(unit)[s].shms->shk[k].key_type) {
   2990             *norm_mem = _SOC_ISM_MEMS(unit)[s].shms->shk[k].hmv->shm->mem;
   2991             LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   2992                         (BSL_META_U(unit,
   2993                                     "Normalized for key_type: %d mem: %s\n"), 
   2994                          key_type, SOC_MEM_NAME(unit, *norm_mem)));
   2995             break;
   2996         }  
   2997     }
   2998 }
   2999 
   3000 /*
   3001  * Function:
   3002  *      _soc_mem_multi_hash_big_to_small_move_chk 
   3003  * Purpose:
   3004  *      Checks if bigger entry can be moved into 
   3005  *      smaller entry.
   3006  * Parameters:
   3007  *      v0, v1, v2, v3   -  (IN) valid bits for entry.
   3008  *      mem              -  (IN/OUT) memory.
   3009  *      index            -  (IN/OUT) index of entry
   3010  *      offset           -  (IN) offset of entry
   3011  *      old_mem          -  (IN) the old memory type
   3012  * Returns:
   3013  *      1 = moe allowed, 0 = move not allowed 
   3014  */
   3015 STATIC int
   3016 _soc_mem_multi_hash_big_to_small_move_chk(int v0, int v1, int v2, int v3,
   3017                                         soc_mem_t *mem, int *index, int offset, soc_mem_t old_mem)
   3018 {
   3019     int entry_num = v0 + v1 + v2 + v3;
   3020     int double_wide_upper_num = v0 + v1;
   3021     int double_wide_lower_num = v2 + v3;
   3022     soc_mem_t orig_mem = *mem;
   3023     int orig_idx = *index + offset;
   3024     int index_offset = 0;
   3025 
   3026     switch (orig_mem) {
   3027     case L3_ENTRY_4m:
   3028         if (entry_num == 1) {
   3029             index_offset = v0 ? 0 : (v1 ? 1 : (v2 ? 2 : (v3 ? 3 : 0)));
   3030             *mem = L3_ENTRY_1m;
   3031             *index = orig_idx * 4 + index_offset;
   3032             return 1;
   3033         } else if (entry_num == 2) {
   3034             if ((double_wide_upper_num == 2 || double_wide_lower_num == 2) &&
   3035                 (old_mem == L3_ENTRY_2m)) {
   3036                 index_offset = double_wide_upper_num ? 0 : 1;
   3037                 *mem = L3_ENTRY_2m;
   3038                 *index = orig_idx * 2 + index_offset;
   3039                 return 1;
   3040             }
   3041         }
   3042         break;
   3043     case L3_ENTRY_2m:
   3044         if (entry_num == 1) {
   3045             index_offset = v0 ? 0 : 1;
   3046             *mem = L3_ENTRY_1m;
   3047             *index = orig_idx * 2 + index_offset;
   3048             return 1;
   3049         }
   3050         break;
   3051     case L2_ENTRY_2m:
   3052         if (entry_num == 1) {
   3053             index_offset = v0 ? 0 : 1;
   3054             *mem = L2_ENTRY_1m;
   3055             *index = orig_idx * 2 + index_offset;
   3056             return 1;
   3057         }
   3058         break;
   3059     default:
   3060         /* no entry narrower than L3_ENTRY_1m/L2_ENTRY_1m */
   3061         return 0;
   3062     }
   3063     return 0;
   3064 }
   3065 
   3066 /*
   3067  * Function:
   3068  *      _soc_mem_multi_hash_entry_cmp
   3069  * Purpose:
   3070  *      Compares various entry types and return size diffs.
   3071  * Parameters:
   3072  *      unit     -  (IN)SOC unit number.
   3073  *      new_mem  -  (IN) memory to compare
   3074  *      old_mem  -  (IN) other memory to compare
   3075  * Returns:
   3076  *      compare result 
   3077  */
   3078 STATIC int
   3079 _soc_mem_multi_hash_entry_cmp(int unit, soc_mem_t new_mem, soc_mem_t old_mem)
   3080 {
   3081     int o_sz = 1;
   3082     int n_sz = 1;
   3083     /*
   3084      * Different memories may require different size entries.
   3085      * When moving the entries we need to see the width of 
   3086      * entries in the process of movement to make sure we dont
   3087      * corrupt different sized entry.
   3088      * e.g. L3_ENTRY_4 takes 4 h/w entries and L3_ENTRY_2 takes 2.
   3089      */
   3090     /* L3 memories */
   3091     o_sz = (old_mem == L3_ENTRY_4m) ? 4 : ((old_mem == L3_ENTRY_2m) ? 2 : o_sz);
   3092     n_sz = (new_mem == L3_ENTRY_4m) ? 4 : ((new_mem == L3_ENTRY_2m) ? 2 : n_sz);
   3093 
   3094     /* L2 memories */
   3095     o_sz = (old_mem == L2_ENTRY_2m) ? 2 : ((old_mem == L2_ENTRY_1m) ? 1 : o_sz);
   3096     n_sz = (new_mem == L2_ENTRY_2m) ? 2 : ((new_mem == L2_ENTRY_1m) ? 1 : n_sz);
   3097 
   3098     /* return width differences */
   3099     if (o_sz < n_sz) {
   3100         return -1;
   3101     } else if (o_sz > n_sz) {
   3102         return o_sz / n_sz;
   3103     }
   3104     return 0;
   3105 }
   3106 
   3107 /*
   3108  * Function:
   3109  *      _soc_mem_multi_hash_get_valid_entries
   3110  * Purpose:
   3111  *      Gets the valid entries based on a memory.
   3112  * Parameters:
   3113  *      unit           -  (IN)  SOC unit number.
   3114  *      mem            -  (IN)  memory type
   3115  *      move_entry     -  (IN)  memory to read
   3116  *      vo,v1,v2,v3    -  (OUT) valid bits
   3117  * Returns:
   3118  *      valid bit count 
   3119  */
   3120 STATIC int 
   3121 _soc_mem_multi_hash_get_valid_entries(int unit, soc_mem_t mem, uint32 *move_entry, 
   3122                                       uint32 *v0, uint32 *v1, 
   3123                                       uint32 *v2, uint32 *v3) 
   3124 {
   3125     /* Initialize all of these to 0.*/
   3126     *v0 = *v1 = *v2 = *v3 = 0;
   3127     switch (mem) {
   3128     case L3_ENTRY_4m:
   3129         /* Get v2,v3 and fall through to next case to get v0,v1.*/
   3130         /* coverity[fallthrough] */
   3131         *v3 = soc_mem_field32_get(unit, mem, move_entry, VALID_3f);
   3132         *v2 = soc_mem_field32_get(unit, mem, move_entry, VALID_2f);
   3133     case L3_ENTRY_2m:
   3134     case L2_ENTRY_2m:
   3135         *v1 = soc_mem_field32_get(unit, mem, move_entry, VALID_1f);
   3136         *v0 = soc_mem_field32_get(unit, mem, move_entry, VALID_0f);
   3137         break;
   3138     case L3_ENTRY_1m:
   3139     case L2_ENTRY_1m:
   3140         *v0 = soc_mem_field32_get(unit, mem, move_entry, VALIDf);
   3141         break;
   3142     default:
   3143         *v0 = *v1 = *v2 = *v3 = 1;   
   3144         break;
   3145     }
   3146     return (*v0 + *v1 + *v2 + *v3);
   3147 }
   3148 
   3149 int
   3150 soc_mem_multi_hash_move(int unit, soc_mem_t mem, int32 banks, int copyno,
   3151                         void *entry, SHR_BITDCL *bucket_trace, 
   3152                         _soc_ism_mem_banks_t *banks_info, int recurse_depth)
   3153 {
   3154     SHR_BITDCL *trace;
   3155     int32 nbix;
   3156     int rv = SOC_E_NONE, cmp_rv, index, orig_index;
   3157     _soc_ism_mem_banks_t *mem_banks;
   3158     uint8 i, bix, num_ent, found = 0;
   3159     uint32 cb=0, db, dest_bucket_index, result, trace_size = 0;
   3160     uint32 bucket_index, move_entry[SOC_MAX_MEM_WORDS];
   3161     soc_mem_t orig_mem = mem;
   3162     soc_mem_t norm_mem = INVALIDm;
   3163     static uint32 numb = 0;
   3164     uint32 v0, v1, v2, v3;
   3165     uint8 orig_mem_offset, norm_mem_offset;
   3166     uint8 banks_count, max_banks_count;
   3167     
   3168     if (recurse_depth < 0) {
   3169         return SOC_E_FULL;
   3170     }
   3171     /* Stack variables initialization & memory allocations */
   3172     if (NULL == bucket_trace) {
   3173         /* For simplicity, allocate same/max number of bits for buckets for all banks */
   3174         numb = _SOC_ISM_BANK0_SIZE;
   3175         /* Keep back trace of all buckets affected by recursion. */
   3176         trace_size = SHR_BITALLOCSIZE(numb * _SOC_ISM_MAX_BANKS);
   3177         trace =  sal_alloc(trace_size, "N hash");
   3178         if (NULL == trace) {
   3179             return (SOC_E_MEMORY);
   3180         }
   3181         sal_memset(trace, 0, trace_size);
   3182         mem_banks = sal_alloc(sizeof(_soc_ism_mem_banks_t), "N hash banks");
   3183         if (NULL == mem_banks) {
   3184             sal_free(trace);
   3185             return (SOC_E_MEMORY);
   3186         }
   3187         sal_memset(mem_banks, 0, sizeof(_soc_ism_mem_banks_t));
   3188         /* Get mems bank info */
   3189         rv = soc_ism_get_banks_for_mem(unit, mem, mem_banks->banks, 
   3190                                        mem_banks->bank_size, &mem_banks->count);
   3191         if (SOC_FAILURE(rv)) {
   3192             sal_free(trace);
   3193             sal_free(mem_banks);
   3194             return rv;
   3195         }
   3196         if (mem_banks->count == 1) {
   3197             sal_free(trace);
   3198             sal_free(mem_banks);
   3199             return SOC_E_FULL;
   3200         }
   3201     } else {
   3202         trace = bucket_trace;
   3203         mem_banks = banks_info;
   3204     }
   3205 
   3206     if (banks != SOC_MEM_HASH_BANK_ALL) {
   3207         /* current should be selected same as banks */
   3208         for (bix = 0; bix < mem_banks->count; bix++) {
   3209             cb = (uint32)1 << mem_banks->banks[bix];
   3210             if (cb == banks) {
   3211                 break;
   3212             }
   3213         }
   3214         if (mem_banks->count == bix) {
   3215             rv = SOC_E_FULL;
   3216             goto cleanup;
   3217         }
   3218         max_banks_count = 1;
   3219     } else {
   3220         bix = 0;
   3221         max_banks_count = mem_banks->count;
   3222     }
   3223 
   3224     /* Iterate over banks. */
   3225     for (banks_count = 0; banks_count < max_banks_count; banks_count++) {
   3226 
   3227         if (banks_count > 0) {
   3228             bix++;
   3229             if (bix >= mem_banks->count) {
   3230                 bix = 0;
   3231             }
   3232         }
   3233 
   3234         cb = (uint32)1 << mem_banks->banks[bix]; /* current bank */
   3235 
   3236         rv = soc_generic_hash(unit, mem, entry, cb, 0, &index, &result, 
   3237                               &bucket_index, &num_ent);
   3238         if (SOC_FAILURE(rv)) {
   3239             break;
   3240         }
   3241 
   3242         /* Skip if bucket was previous visited */
   3243         if (SHR_BITGET(trace, (numb * bix) + bucket_index)) {
   3244             continue;
   3245         }
   3246 
   3247         SHR_BITSET(trace, (numb * bix) + bucket_index);
   3248         /* keep bcakup for fall back */
   3249         orig_index = index; 
   3250         orig_mem   = mem;
   3251 
   3252         /* For each current bank iterate over other possible destination banks. */
   3253         for (nbix = 0; nbix < mem_banks->count; nbix++) {
   3254             if (bix == nbix) {
   3255                 continue;
   3256             }
   3257 
   3258             db = (uint32)1 << mem_banks->banks[nbix]; /* next destination bank */
   3259 
   3260             index = orig_index;
   3261             mem = orig_mem;
   3262 
   3263             /* Iterate over un-visited entries in the bucket */
   3264             for (i = 0; i < num_ent;) {
   3265                 rv = soc_mem_read(unit, mem, copyno, index+i,
   3266                                   move_entry);
   3267                 if (SOC_FAILURE(rv)) {
   3268                     rv = SOC_E_MEMORY;
   3269                     break;
   3270                 }
   3271                 /* check if we have have found a free entry */
   3272                 if(!(_soc_mem_multi_hash_get_valid_entries(unit, mem, move_entry,
   3273                                                            &v0, &v1, &v2, &v3))){
   3274                     found = TRUE;
   3275                     break;
   3276                 }
   3277 
   3278                 /* Normalize memory based on the key type */
   3279                 soc_mem_multi_hash_norm_mem(unit, mem, move_entry, &norm_mem);
   3280                 /* Compare memories to see width differences */
   3281                 cmp_rv = _soc_mem_multi_hash_entry_cmp(unit, mem, norm_mem);
   3282                 if (cmp_rv == 0) {
   3283                     /* Calculate destination entry hash value. */
   3284                     rv = soc_generic_hash(unit, mem, move_entry, db,
   3285                                           0, &index, &result,
   3286                                           &dest_bucket_index, NULL);
   3287                     if (SOC_FAILURE(rv)) {
   3288                         mem = orig_mem;
   3289                         break;
   3290                     }
   3291 
   3292                     if (SHR_BITGET(trace, (numb * nbix) + dest_bucket_index)) {
   3293                         /* Try next entry in the same bucket */
   3294                         mem = orig_mem;
   3295                         index = orig_index;
   3296                         /* Mem and norm_mem has same entry wide
   3297                          * Try next entry in the same bucket by incrementing i */
   3298                         i++;
   3299                         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   3300                             (BSL_META_U(unit,
   3301                             "Skip(1) bank %d bucket %d, go to bank %d index %d\n"),
   3302                             db, dest_bucket_index, cb, index+i));
   3303                         continue;
   3304                     }
   3305                 } else if (cmp_rv < 0) {
   3306                     if (_soc_mem_multi_hash_big_to_small_move_chk(v0, v1, v2, v3,
   3307                                                                 &mem, &index, i, norm_mem)) {
   3308                         if (SOC_FAILURE(soc_mem_read(unit, mem, copyno, index,
   3309                                                      move_entry))) {
   3310                             rv = SOC_E_MEMORY;
   3311                             mem = orig_mem;
   3312                             break;
   3313                         }
   3314                         /* Calculate destination entry hash value. */
   3315                         rv = soc_generic_hash(unit, mem, move_entry, db,
   3316                                               0, &index, &result,
   3317                                               &dest_bucket_index, NULL);
   3318                         if (SOC_FAILURE(rv)) {
   3319                             mem = orig_mem;
   3320                             break;
   3321                         }
   3322                         if (SHR_BITGET(trace, (numb * nbix) + dest_bucket_index)) {
   3323                             /* Try next entry in the same bucket in original 
   3324                              * memory view */
   3325                             mem = orig_mem;
   3326                             index = orig_index;
   3327                             /* Mem is wider than norm_mem.
   3328                              * Try next entry in the same bucket by incrementing i */
   3329                             i++;
   3330                             LOG_VERBOSE(BSL_LS_SOC_COMMON,
   3331                                         (BSL_META_U(unit,
   3332                                         "Skip(2) bank %d bucket %d, go to mem %d " \
   3333                                         "bank %d index %d \n"),
   3334                                         db, dest_bucket_index, mem, i >= num_ent ? db : cb,
   3335                                         i >= num_ent ? -1 : (index+i)));
   3336                             continue;
   3337                         }
   3338                     } else {
   3339                         i++;
   3340                         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   3341                                     (BSL_META_U(unit,
   3342                                      "Depth %d, Existing entry width is narrower, but can't move." \
   3343                                      "Trying other entry in the bucket \n"),
   3344                                      recurse_depth));
   3345                         rv = SOC_E_NONE;
   3346                         continue;
   3347                     }
   3348                 } else {
   3349                     /* wider entry */
   3350                     mem = norm_mem;
   3351                     index = (index + i) / cmp_rv;
   3352                     rv = soc_mem_read(unit, mem, copyno, index, move_entry);
   3353                     LOG_VERBOSE(BSL_LS_SOC_COMMON,
   3354                                 (BSL_META_U(unit,
   3355                                  "Depth %d, G-2nd read %d index %d from bank %d bucket %d\n"),
   3356                                  recurse_depth, mem, index, cb, bucket_index));
   3357                     if (SOC_FAILURE(rv)) {
   3358                         rv = SOC_E_MEMORY;
   3359                         mem = orig_mem;
   3360                         break;
   3361                     }
   3362                     /* Calculate destination entry hash value. */
   3363                     rv = soc_generic_hash(unit, mem, move_entry, db,
   3364                                           0, &index, &result,
   3365                                           &dest_bucket_index, NULL);
   3366                     if (SOC_FAILURE(rv)) {
   3367                         mem = orig_mem;
   3368                         break;
   3369                     }
   3370 
   3371                     if (SHR_BITGET(trace, (numb * nbix) + dest_bucket_index)) {
   3372                         mem = orig_mem;
   3373                         index = orig_index;
   3374                         /* Determine bucket offset increment based upon existing
   3375                          * entry type/size  when orig_mem is single/double wide mode and
   3376                          * norm_mem is double/quad mode,
   3377                          * otherwise increment by 1 is sufficent */
   3378                         orig_mem_offset = soc_ism_get_bucket_offset(unit, mem, -1,
   3379                                                                     entry, move_entry);
   3380                         norm_mem_offset = soc_ism_get_bucket_offset(unit, norm_mem, -1,
   3381                                                                     entry, move_entry);
   3382                         if (orig_mem_offset >= norm_mem_offset) {
   3383                             i++;
   3384                         } else {
   3385                             /* coverity[divide_by_zero] */
   3386                             i += (norm_mem_offset / orig_mem_offset);
   3387                         }
   3388                         LOG_VERBOSE(BSL_LS_SOC_COMMON,
   3389                                     (BSL_META_U(unit,
   3390                                      "Skip(3) bank %d bucket %d, go to bank %d index %d\n"),
   3391                                      db, dest_bucket_index, cb, index+i));
   3392                         continue;
   3393                     }
   3394                 }
   3395 
   3396                 /* Attempt to insert it into the other bank. */
   3397                 rv = soc_mem_bank_insert(unit, mem, db, copyno, move_entry, NULL);
   3398                 if (SOC_FAILURE(rv)) {
   3399                     if (rv != SOC_E_FULL) {
   3400                         mem = orig_mem;
   3401                         break;
   3402                     }
   3403                     /* Recursive call - attempt to create a slot
   3404                        in another bank's bucket. */
   3405                     rv = soc_mem_multi_hash_move(unit, mem, db, copyno,
   3406                                                  move_entry, trace, mem_banks,
   3407                                                  recurse_depth - 1);
   3408                     if (SOC_FAILURE(rv)) {
   3409                         mem = orig_mem;
   3410                         if (rv != SOC_E_FULL) {
   3411                             break;
   3412                         }
   3413                         index = orig_index;
   3414                         /* Determine bucket offset increment based upon existing
   3415                          * entry type/size  when orig_mem is single/double wide mode and
   3416                          * norm_mem is double/quad mode,
   3417                          * otherwise increment by 1 is sufficent */
   3418                         orig_mem_offset = soc_ism_get_bucket_offset(unit, mem, -1,
   3419                                                                     entry, move_entry);
   3420                         norm_mem_offset = soc_ism_get_bucket_offset(unit, norm_mem, -1,
   3421                                                                     entry, move_entry);
   3422                         if (orig_mem_offset >= norm_mem_offset) {
   3423                             i++;
   3424                         } else {
   3425                             /* coverity[divide_by_zero] */
   3426                             i += (norm_mem_offset / orig_mem_offset);
   3427                         }
   3428                         continue;
   3429                     }
   3430                 }
   3431                 /* Entry was moved successfully. */
   3432                 found = TRUE;
   3433                 /* Delete old entry from original location */
   3434                 rv = soc_mem_generic_delete(unit, mem, MEM_BLOCK_ANY, cb, move_entry,
   3435                                             NULL, NULL);
   3436                 mem = orig_mem;
   3437                 break;
   3438             }  /* Bucket iteration loop. */
   3439             if (found || ((rv < 0) && (rv != SOC_E_FULL))) {
   3440                 break;
   3441             }
   3442         } /* Destination Bank iteration loop. */
   3443         if (found || ((rv < 0) && (rv != SOC_E_FULL))) {
   3444             break;
   3445         }
   3446     } /* Bank iteration loop. */
   3447     if ((rv < 0) && (rv != SOC_E_FULL)) {
   3448         if (NULL == bucket_trace) { 
   3449             sal_free(trace);
   3450             sal_free(mem_banks);
   3451         }
   3452         return rv;
   3453     }
   3454     if (!found) {
   3455         if (NULL == bucket_trace) {
   3456             sal_free(trace);
   3457             sal_free(mem_banks);
   3458         }
   3459         return SOC_E_FULL;
   3460     }
   3461     rv = soc_mem_generic_insert(unit, mem, copyno, cb, entry, entry, NULL);
   3462     if (rv) {
   3463         LOG_VERBOSE(BSL_LS_SOC_SOCMEM,
   3464                     (BSL_META_U(unit,
   3465                                 "Insert entry: %d\n"), rv));
   3466     }
   3467 cleanup:
   3468     if (NULL == bucket_trace) {
   3469         sal_free(trace);
   3470         sal_free(mem_banks);
   3471     }
   3472     return rv;
   3473 }
   3474 
   3475 #endif /* BCM_ISM_SUPPORT */
   3476