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

field.c (582443B)


      1 /* 
      2  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      3  * 
      4  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      5  *
      6  * File:        field.c
      7  * Purpose:     BCM56504 Field Processor installation functions.
      8  */
      9 #include <shared/bsl.h>
     10 
     11 #include <soc/drv.h>
     12 #include <soc/scache.h>
     13 
     14 #include <bcm/error.h>
     15 
     16 #include <bcm/field.h>
     17 #include <bcm/mirror.h>
     18 
     19 #include <bcm_int/esw_dispatch.h>
     20 #if defined(BCM_FIREBOLT_SUPPORT)
     21 #include <bcm_int/esw/firebolt.h>
     22 #endif
     23 #if defined(BCM_TRIUMPH_SUPPORT)
     24 #include <bcm_int/esw/triumph.h>
     25 #endif
     26 #if defined(BCM_TRX_SUPPORT)
     27 #include <bcm_int/esw/trx.h>
     28 #endif
     29 #if defined(BCM_HURRICANE2_SUPPORT)
     30 #include <bcm_int/esw/hurricane2.h>
     31 #endif
     32 #include <bcm_int/esw/field.h>
     33 #include <bcm_int/esw/mirror.h>
     34 #if defined(BCM_KATANA_SUPPORT)
     35 #include <bcm_int/esw/katana.h>
     36 #endif
     37 #if defined(BCM_KATANA2_SUPPORT)
     38 #include <bcm_int/esw/katana2.h>
     39 #endif
     40 #if defined(BCM_TOMAHAWK_SUPPORT)
     41 #include <bcm_int/esw/tomahawk.h>
     42 #endif
     43 #if defined(BCM_TRIDENT3_SUPPORT)
     44 #include <bcm_int/esw/trident3.h>
     45 #endif
     46 
     47 #if defined(BCM_FIREBOLT_SUPPORT) && defined(BCM_FIELD_SUPPORT)
     48 
     49 /* local/static function prototypes */
     50 STATIC void _field_fb_functions_init(int unit, _field_funct_t *functions);
     51 STATIC int _field_fb_detach(int unit, _field_control_t *fc);
     52 STATIC int _field_fb_hw_clear(int unit, _field_stage_t *stage_fc);
     53 
     54 STATIC int _field_fb_tcam_policy_install(int unit, _field_entry_t *f_ent,
     55                                          int tcam_idx);
     56 STATIC int _field_fb_tcam_policy_reinstall(int unit, _field_entry_t *f_ent,
     57                                          int tcam_idx);
     58 STATIC int _field_fb_tcam_get(int unit, _field_entry_t *f_ent,
     59                                soc_mem_t mem, uint32 *buf);
     60 STATIC int _field_fb_action_get(int unit, soc_mem_t mem, 
     61                                 _field_entry_t *f_ent, int tcam_idx, 
     62                                 _field_action_t *fa, uint32 *buf);
     63 
     64 #ifdef BROADCOM_DEBUG
     65 STATIC char *_field_fb_action_name(bcm_field_action_t action);
     66 #endif /* BROADCOM_DEBUG */
     67 
     68 static soc_field_t _fb_ing_f4_reg[16] =   {
     69     SLICE_0_F4f, SLICE_1_F4f,
     70     SLICE_2_F4f, SLICE_3_F4f,
     71     SLICE_4_F4f, SLICE_5_F4f,
     72     SLICE_6_F4f, SLICE_7_F4f,
     73     SLICE_8_F4f, SLICE_9_F4f,
     74     SLICE_10_F4f, SLICE_11_F4f,
     75     SLICE_12_F4f, SLICE_13_F4f,
     76     SLICE_14_F4f, SLICE_15_F4f};
     77 
     78 #if defined(BCM_FIREBOLT2_SUPPORT) 
     79 static soc_field_t _fb2_ifp_double_wide_key[16] = {
     80     SLICE0_DOUBLE_WIDE_KEY_SELECTf,
     81     SLICE1_DOUBLE_WIDE_KEY_SELECTf,
     82     SLICE2_DOUBLE_WIDE_KEY_SELECTf,
     83     SLICE3_DOUBLE_WIDE_KEY_SELECTf, 
     84     SLICE4_DOUBLE_WIDE_KEY_SELECTf, 
     85     SLICE5_DOUBLE_WIDE_KEY_SELECTf, 
     86     SLICE6_DOUBLE_WIDE_KEY_SELECTf, 
     87     SLICE7_DOUBLE_WIDE_KEY_SELECTf, 
     88     SLICE8_DOUBLE_WIDE_KEY_SELECTf,
     89     SLICE9_DOUBLE_WIDE_KEY_SELECTf,
     90     SLICE10_DOUBLE_WIDE_KEY_SELECTf,
     91     SLICE11_DOUBLE_WIDE_KEY_SELECTf, 
     92     SLICE12_DOUBLE_WIDE_KEY_SELECTf, 
     93     SLICE13_DOUBLE_WIDE_KEY_SELECTf, 
     94     SLICE14_DOUBLE_WIDE_KEY_SELECTf, 
     95     SLICE15_DOUBLE_WIDE_KEY_SELECTf};      
     96 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
     97 
     98 static soc_field_t _fb_field_tbl[16][3] = {
     99     {SLICE0_F1f, SLICE0_F2f, SLICE0_F3f},
    100     {SLICE1_F1f, SLICE1_F2f, SLICE1_F3f},
    101     {SLICE2_F1f, SLICE2_F2f, SLICE2_F3f},
    102     {SLICE3_F1f, SLICE3_F2f, SLICE3_F3f},
    103     {SLICE4_F1f, SLICE4_F2f, SLICE4_F3f},
    104     {SLICE5_F1f, SLICE5_F2f, SLICE5_F3f},
    105     {SLICE6_F1f, SLICE6_F2f, SLICE6_F3f},
    106     {SLICE7_F1f, SLICE7_F2f, SLICE7_F3f},
    107     {SLICE8_F1f, SLICE8_F2f, SLICE8_F3f},
    108     {SLICE9_F1f, SLICE9_F2f, SLICE9_F3f},
    109     {SLICE10_F1f, SLICE10_F2f, SLICE10_F3f},
    110     {SLICE11_F1f, SLICE11_F2f, SLICE11_F3f},
    111     {SLICE12_F1f, SLICE12_F2f, SLICE12_F3f},
    112     {SLICE13_F1f, SLICE13_F2f, SLICE13_F3f},
    113     {SLICE14_F1f, SLICE14_F2f, SLICE14_F3f},
    114     {SLICE15_F1f, SLICE15_F2f, SLICE15_F3f}};
    115 static soc_field_t _fb_ing_slice_mode_field[16] = {
    116     SLICE_0_MODEf,   SLICE_1_MODEf,
    117     SLICE_2_MODEf,   SLICE_3_MODEf,
    118     SLICE_4_MODEf,   SLICE_5_MODEf,
    119     SLICE_6_MODEf,   SLICE_7_MODEf,
    120     SLICE_8_MODEf,   SLICE_9_MODEf,
    121     SLICE_10_MODEf,  SLICE_11_MODEf,
    122     SLICE_12_MODEf,  SLICE_13_MODEf,
    123     SLICE_14_MODEf,  SLICE_15_MODEf};
    124 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
    125 static soc_field_t _vfp_slice_wide_mode_field[4] = {
    126     SLICE_0_DOUBLE_WIDE_MODEf,
    127     SLICE_1_DOUBLE_WIDE_MODEf,
    128     SLICE_2_DOUBLE_WIDE_MODEf,
    129     SLICE_3_DOUBLE_WIDE_MODEf};
    130 static soc_field_t _vfp_slice_pairing_field[2] = {
    131     SLICE1_0_PAIRINGf,   SLICE3_2_PAIRINGf};
    132 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
    133 #if defined (BCM_FIREBOLT2_SUPPORT)
    134 static soc_field_t _fb2_slice_pairing_field[8] = {
    135     SLICE1_0_PAIRINGf,   SLICE3_2_PAIRINGf,
    136     SLICE5_4_PAIRINGf,   SLICE7_6_PAIRINGf,
    137     SLICE9_8_PAIRINGf,   SLICE11_10_PAIRINGf,
    138     SLICE13_12_PAIRINGf, SLICE15_14_PAIRINGf};
    139 static soc_field_t _fb2_slice_wide_mode_field[16] = {
    140     SLICE0_DOUBLE_WIDE_MODEf, 
    141     SLICE1_DOUBLE_WIDE_MODEf,
    142     SLICE2_DOUBLE_WIDE_MODEf,
    143     SLICE3_DOUBLE_WIDE_MODEf,
    144     SLICE4_DOUBLE_WIDE_MODEf,
    145     SLICE5_DOUBLE_WIDE_MODEf,
    146     SLICE6_DOUBLE_WIDE_MODEf,
    147     SLICE7_DOUBLE_WIDE_MODEf,
    148     SLICE8_DOUBLE_WIDE_MODEf,
    149     SLICE9_DOUBLE_WIDE_MODEf,
    150     SLICE10_DOUBLE_WIDE_MODEf,
    151     SLICE11_DOUBLE_WIDE_MODEf,
    152     SLICE12_DOUBLE_WIDE_MODEf,
    153     SLICE13_DOUBLE_WIDE_MODEf,
    154     SLICE14_DOUBLE_WIDE_MODEf,
    155     SLICE15_DOUBLE_WIDE_MODEf};
    156 static soc_field_t _efp_slice_mode[] = {
    157     SLICE_0_MODEf, SLICE_1_MODEf,
    158     SLICE_2_MODEf, SLICE_3_MODEf};
    159 static soc_field_t _vfp_field_tbl[4][2] = {
    160     {SLICE_0_F2f, SLICE_0_F3f},
    161     {SLICE_1_F2f, SLICE_1_F3f},
    162     {SLICE_2_F2f, SLICE_2_F3f},
    163     {SLICE_3_F2f, SLICE_3_F3f}};
    164 #endif /* BCM_FIREBOLT2_SUPPORT */
    165 
    166 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT)       \
    167     || defined(BCM_TRX_SUPPORT) && defined(BCM_WARM_BOOT_SUPPORT)
    168 static uint32 virtual_to_physical_map[] = {
    169         VIRTUAL_SLICE_0_PHYSICAL_SLICE_NUMBERf,
    170         VIRTUAL_SLICE_1_PHYSICAL_SLICE_NUMBERf,
    171         VIRTUAL_SLICE_2_PHYSICAL_SLICE_NUMBERf,
    172         VIRTUAL_SLICE_3_PHYSICAL_SLICE_NUMBERf,
    173         VIRTUAL_SLICE_4_PHYSICAL_SLICE_NUMBERf,
    174         VIRTUAL_SLICE_5_PHYSICAL_SLICE_NUMBERf,
    175         VIRTUAL_SLICE_6_PHYSICAL_SLICE_NUMBERf,
    176         VIRTUAL_SLICE_7_PHYSICAL_SLICE_NUMBERf
    177 #if defined(BCM_RAVEN_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT)        \
    178     || defined(BCM_TRX_SUPPORT) && defined(BCM_WARM_BOOT_SUPPORT)
    179         ,
    180         VIRTUAL_SLICE_8_PHYSICAL_SLICE_NUMBERf,
    181         VIRTUAL_SLICE_9_PHYSICAL_SLICE_NUMBERf,
    182         VIRTUAL_SLICE_10_PHYSICAL_SLICE_NUMBERf,
    183         VIRTUAL_SLICE_11_PHYSICAL_SLICE_NUMBERf,
    184         VIRTUAL_SLICE_12_PHYSICAL_SLICE_NUMBERf,
    185         VIRTUAL_SLICE_13_PHYSICAL_SLICE_NUMBERf,
    186         VIRTUAL_SLICE_14_PHYSICAL_SLICE_NUMBERf,
    187         VIRTUAL_SLICE_15_PHYSICAL_SLICE_NUMBERf
    188 #endif /* BCM_RAVEN_SUPPORT || BCM_FIREBOLT2_SUPPORT
    189           || BCM_TRX_SUPPORT && BCM_WARM_BOOT_SUPPORT */
    190     };
    191 static uint32 virtual_to_group_map[] = {
    192         VIRTUAL_SLICE_0_VIRTUAL_SLICE_GROUPf,
    193         VIRTUAL_SLICE_1_VIRTUAL_SLICE_GROUPf,
    194         VIRTUAL_SLICE_2_VIRTUAL_SLICE_GROUPf,
    195         VIRTUAL_SLICE_3_VIRTUAL_SLICE_GROUPf,
    196         VIRTUAL_SLICE_4_VIRTUAL_SLICE_GROUPf,
    197         VIRTUAL_SLICE_5_VIRTUAL_SLICE_GROUPf,
    198         VIRTUAL_SLICE_6_VIRTUAL_SLICE_GROUPf,
    199         VIRTUAL_SLICE_7_VIRTUAL_SLICE_GROUPf
    200 #if defined(BCM_RAVEN_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT)        \
    201     || defined(BCM_TRX_SUPPORT) && defined(BCM_WARM_BOOT_SUPPORT)
    202         ,
    203         VIRTUAL_SLICE_8_VIRTUAL_SLICE_GROUPf,
    204         VIRTUAL_SLICE_9_VIRTUAL_SLICE_GROUPf,
    205         VIRTUAL_SLICE_10_VIRTUAL_SLICE_GROUPf,
    206         VIRTUAL_SLICE_11_VIRTUAL_SLICE_GROUPf,
    207         VIRTUAL_SLICE_12_VIRTUAL_SLICE_GROUPf,
    208         VIRTUAL_SLICE_13_VIRTUAL_SLICE_GROUPf,
    209         VIRTUAL_SLICE_14_VIRTUAL_SLICE_GROUPf,
    210         VIRTUAL_SLICE_15_VIRTUAL_SLICE_GROUPf
    211 #endif /* BCM_RAVEN_SUPPORT || BCM_FIREBOLT2_SUPPORT
    212           || BCM_TRX_SUPPORT && BCM_WARM_BOOT_SUPPORT */
    213     };
    214 #endif /* BCM_RAPTOR_SUPPORT || BCM_FIREBOLT2_SUPPORT
    215           || BCM_TRX_SUPPORT && BCM_WARM_BOOT_SUPPORT */
    216 
    217 #ifdef BCM_WARM_BOOT_SUPPORT
    218 
    219 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT) || \
    220     defined(BCM_TRX_SUPPORT)
    221 int
    222 _field_slice_expanded_status_get(int unit, _field_control_t *fc, _field_stage_t *stage_fc,
    223                                  int *expanded, int *slice_master_idx)
    224 {
    225     int i, vslice, slice_idx = 0, vgroup = -1, max = -1, slice_num = 0;
    226     fp_slice_map_entry_t map_entry;
    227     soc_field_t fld;
    228 #if defined(BCM_TRX_SUPPORT)
    229     uint32 map_val;
    230 #endif
    231     uint8 *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0];
    232     uint8 vmap;
    233 
    234     if (fc->l2warm) {
    235     }
    236 
    237     if (!soc_feature(unit, soc_feature_field_multi_pipe_support)) {
    238         BCM_IF_ERROR_RETURN(READ_FP_SLICE_MAPm(unit, MEM_BLOCK_ANY, 0, &map_entry));
    239         slice_num = SOC_IS_HAWKEYE(unit)? 4 : 16;
    240         if (SOC_IS_SC_CQ(unit)) {
    241             slice_num = 12;
    242         }
    243     }
    244     if ((stage_fc->stage_id == _BCM_FIELD_STAGE_EGRESS) || 
    245         (stage_fc->stage_id == _BCM_FIELD_STAGE_LOOKUP)) {
    246         slice_num = 4;
    247     }
    248 
    249     /* Iterate over virtual slices to get physical slices and virtual groups */
    250     for (vslice = 0; vslice < slice_num; vslice++) {
    251         switch (stage_fc->stage_id) {
    252         case _BCM_FIELD_STAGE_INGRESS:
    253             fld = virtual_to_physical_map[vslice];
    254             slice_idx = soc_FP_SLICE_MAPm_field32_get(unit, &map_entry, fld);
    255             /* Now get virtual group for this virtual slice */
    256             fld = virtual_to_group_map[vslice];
    257             vgroup = soc_FP_SLICE_MAPm_field32_get(unit, &map_entry, fld);
    258             break;
    259 #if defined(BCM_TRX_SUPPORT)
    260         case _BCM_FIELD_STAGE_EGRESS:
    261             BCM_IF_ERROR_RETURN(READ_EFP_SLICE_MAPr(unit, &map_val));
    262             fld = virtual_to_physical_map[vslice];
    263             slice_idx = soc_reg_field_get(unit, EFP_SLICE_MAPr, map_val, fld);
    264             /* Now get virtual group for this virtual slice */
    265             fld = virtual_to_group_map[vslice];
    266             vgroup = soc_reg_field_get(unit, EFP_SLICE_MAPr, map_val, fld);
    267             break;
    268         case _BCM_FIELD_STAGE_LOOKUP:
    269             BCM_IF_ERROR_RETURN(READ_VFP_SLICE_MAPr(unit, &map_val));
    270             fld = virtual_to_physical_map[vslice];
    271             slice_idx = soc_reg_field_get(unit, VFP_SLICE_MAPr, map_val, fld);
    272             /* Now get virtual group for this virtual slice */
    273             fld = virtual_to_group_map[vslice];
    274             vgroup = soc_reg_field_get(unit, VFP_SLICE_MAPr, map_val, fld);
    275             break;
    276 #endif
    277         default:
    278             break; /* Should never happen */
    279         }
    280         /* Phys slice_idx <=> virtual vslice <=> vgroup */
    281         stage_fc->vmap[_FP_DEF_INST][0][vslice].vmap_key = slice_idx;
    282         stage_fc->vmap[_FP_DEF_INST][0][vslice].virtual_group = vgroup;
    283         stage_fc->vmap[_FP_DEF_INST][0][vslice].priority = vgroup;
    284         
    285     }
    286 
    287     /* See if virtual slice is the highest number in the virtual group */
    288     for (vslice = 0; vslice < slice_num; vslice++) {
    289         max = -1;
    290         for (i = 0; i < slice_num; i++) {
    291            if ((stage_fc->vmap[_FP_DEF_INST][0][vslice].virtual_group == 
    292                 stage_fc->vmap[_FP_DEF_INST][0][i].virtual_group)) {
    293                 if (i > max) {
    294                     max = i;
    295                 }
    296             }
    297         }
    298         if (!((fc->l2warm)
    299               && ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_8))) {
    300             if ((max != vslice) && (max != -1)) {
    301                 expanded[stage_fc->vmap[_FP_DEF_INST][0][vslice].vmap_key] = 1;
    302             }
    303         }
    304     }
    305 
    306     /* Software mantains 3 MAPS, make them identical if only 1 map is present */
    307     if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) {
    308         for (vmap = 1; vmap < _FP_VMAP_CNT; ++vmap) {
    309             for (vslice = 0; vslice < slice_num; vslice++) {
    310                 stage_fc->vmap[_FP_DEF_INST][vmap][vslice] =
    311                                         stage_fc->vmap[_FP_DEF_INST][0][vslice];
    312             }
    313         }
    314     }
    315 
    316     if ((fc->l2warm)
    317         && ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_8)) {
    318         for (i = 0; i < slice_num; i++) {
    319             expanded[i] = buf[fc->scache_pos] & 0x1;
    320             slice_master_idx[i] = buf[fc->scache_pos] >> 1;
    321             fc->scache_pos++;
    322         }
    323     }
    324 
    325     return BCM_E_NONE;
    326 }
    327 
    328 int 
    329 _field_physical_to_virtual(int unit, int inst, int slice_idx,
    330                            _field_stage_t *stage_fc)
    331 {
    332     int vslice, slice_num;
    333     slice_num = SOC_IS_HAWKEYE(unit) ? 4 : (SOC_IS_KATANAX(unit) ? 12 : 16);
    334     for (vslice = 0; vslice < slice_num; vslice++) {
    335         if (stage_fc->vmap[inst][0][vslice].vmap_key == slice_idx) {
    336             return vslice;
    337         }
    338     }
    339     return -1;
    340 }
    341 #endif 
    342 
    343 /* Function: _mask_is_set(_bcm_field_qual_offset_t *offset, uint32 *buf)
    344  * Returns:  1 if any bit of buf is set between offset->offset and 
    345  *             offset->offset + offset->width
    346  *           0 otherwise
    347  */
    348 int
    349 _mask_is_set(int unit, _bcm_field_qual_offset_t *offset, uint32 *buf, 
    350              _field_stage_id_t stage_id) 
    351 {
    352     int len = offset->width[0], bp = offset->offset[0];
    353     uint32 temp;
    354     /*    coverity[forward_null : FALSE]    */
    355     soc_mem_info_t *meminfo = NULL;
    356 
    357     switch (stage_id) {
    358         case _BCM_FIELD_STAGE_INGRESS:
    359             meminfo = &SOC_MEM_INFO(unit, FP_TCAMm);
    360             break;
    361         case _BCM_FIELD_STAGE_EGRESS:
    362             meminfo = &SOC_MEM_INFO(unit, EFP_TCAMm);
    363             break;
    364         case _BCM_FIELD_STAGE_LOOKUP:
    365             meminfo = &SOC_MEM_INFO(unit, VFP_TCAMm);
    366             break;
    367         default:
    368             /* Should never happen */
    369             return (FALSE);
    370     }
    371 #define FIX_MEM_ORDER_E(v,m) (((m)->flags & SOC_MEM_FLAG_BE) ? \
    372                                 BYTES2WORDS((m)->bytes)-1-(v) : \
    373                                 (v))
    374     while (len > 0) {
    375         temp = 0;
    376         do {
    377             /* coverity [forward_null] */
    378             temp =
    379                 (temp << 1) |
    380                 ((buf[FIX_MEM_ORDER_E(bp / 32, meminfo)] >>
    381                   (bp & (32 - 1))) & 1);
    382             if (temp > 0) {
    383                 return TRUE;
    384             }
    385             len--;
    386             bp++;
    387         } while (len & (32 - 1));
    388     }
    389     return FALSE;
    390 }
    391 
    392 int
    393 _field_fb_counter_recover(int unit, _field_entry_t *f_ent, uint32 ctr_mode, 
    394                           uint32 ctr_idx, int part, bcm_field_stat_t sid)
    395 {
    396     _field_group_t *fg;
    397     _field_stage_t *stage_fc;
    398     _field_stage_id_t stage_id;
    399     _field_control_t *fc;
    400     _field_slice_t *fs;
    401     _field_stat_t *f_st = NULL;
    402     _field_entry_stat_t *f_ent_st;
    403     int rv, idx, stat_id, found;
    404     uint32 sub_mode = 0, ent_st_flags = 0;
    405     bcm_field_stat_t stat_arr[2];
    406     uint8 nstat = 1;
    407     uint8 hw_entry_count = 1;
    408 
    409     fg = f_ent->group;
    410     fs = f_ent[part].fs;
    411 
    412     sal_memset(stat_arr, 0, sizeof(stat_arr));
    413 
    414     /* Get field control and stage control */
    415     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
    416     stage_id = f_ent->group->stage_id;
    417     rv = _field_stage_control_get(unit, stage_id, &stage_fc);      
    418     BCM_IF_ERROR_RETURN(rv);
    419 
    420     /* Search if counter has already been detected */
    421     /* Go over the counter in the slice */
    422     if (stage_id == _BCM_FIELD_STAGE_INGRESS) {
    423         sub_mode = ctr_mode & ~BCM_FIELD_COUNTER_MODE_BYTES;
    424         if ((sub_mode == BCM_FIELD_COUNTER_MODE_RED) || 
    425             (sub_mode == BCM_FIELD_COUNTER_MODE_YELLOW) || 
    426             (sub_mode == BCM_FIELD_COUNTER_MODE_GREEN) ||
    427             (sub_mode == BCM_FIELD_COUNTER_MODE_YES_NO) ||
    428             (sub_mode == BCM_FIELD_COUNTER_MODE_DEFAULT)) {
    429             hw_entry_count = 1;
    430         } else {
    431             hw_entry_count = 2;
    432         }
    433     } else if (fg->stage_id == _BCM_FIELD_STAGE_EGRESS) {
    434         hw_entry_count = 1;
    435     }
    436     if (((_FP_COUNTER_BMP_TEST(fs->counter_bmp, 2 * ctr_idx)) && 
    437         (_FP_COUNTER_BMP_TEST(fs->counter_bmp, 2 * ctr_idx + 1)) && 
    438         (2 == hw_entry_count)) ||
    439         ((_FP_COUNTER_BMP_TEST(fs->counter_bmp, 2 * ctr_idx)) && 
    440         (hw_entry_count == 1) && (ctr_mode % 2 == 0)) ||
    441         ((_FP_COUNTER_BMP_TEST(fs->counter_bmp, 2 * ctr_idx + 1)) && 
    442         (hw_entry_count == 1) && (ctr_mode % 2))) {
    443         /* Counter has been detected - increment reference count */ 
    444         /* Happens when counter is shared by different entries */
    445         /* Search the hash to match against the HW index */
    446         found = 0;
    447         for (idx = 0; idx < _FP_HASH_SZ(fc); idx++) {
    448             f_st = fc->stat_hash[idx];
    449             while (f_st != NULL) {
    450                 if ((f_st->hw_index == ctr_idx) && 
    451                     (f_st->pool_index == fs->slice_number) &&
    452                     (f_st->hw_mode == ctr_mode) &&
    453                     (f_st->stage_id == stage_id)) {
    454                     found = 1;
    455                     break;
    456                 }
    457                 f_st = f_st->next;
    458             }
    459             if (found) {
    460                 break;
    461             }
    462         }
    463         if (!found) {
    464             return BCM_E_INTERNAL;
    465         }
    466         f_st->hw_ref_count++;
    467         f_st->sw_ref_count++;
    468         f_ent_st = &f_ent->statistic;
    469     } else {
    470         /* Allocate new stat object */
    471         if (fc->l2warm) {
    472             stat_id = sid;
    473         } else {
    474             BCM_IF_ERROR_RETURN(_bcm_field_stat_id_alloc(unit, &stat_id));
    475         }
    476         _FP_XGS3_ALLOC(f_st, sizeof (_field_stat_t), "Field stat entity");
    477         if (NULL == f_st) {
    478             return (BCM_E_MEMORY);
    479         }
    480         ent_st_flags |= _FP_ENTRY_STAT_INSTALLED;
    481         f_st->sw_ref_count = 2;
    482         f_st->hw_ref_count = 1;
    483         f_st->pool_index = fs->slice_number;
    484         f_st->hw_index = ctr_idx;
    485         f_st->sid = stat_id;
    486         f_st->stage_id = fg->stage_id;
    487         f_st->gid = fg->gid;
    488         f_st->hw_mode = ctr_mode;
    489         f_ent_st = &f_ent->statistic;
    490         if (fg->stage_id == _BCM_FIELD_STAGE_INGRESS) {
    491             switch (sub_mode) {
    492                 case (0x1):
    493                 case (0x2):
    494                     stat_arr[0] = bcmFieldStatPackets;
    495                     nstat = 1;
    496                     break;
    497                 case (0x9):
    498                 case (0xa):
    499                     stat_arr[0] = bcmFieldStatBytes;
    500                     nstat = 1;
    501                     break;
    502                 case (0x3):
    503                     stat_arr[0] = bcmFieldStatRedPackets;
    504                     stat_arr[1] = bcmFieldStatNotRedPackets;
    505                     nstat = 2;
    506                     break;
    507                 case (0xb):
    508                     stat_arr[0] = bcmFieldStatRedBytes;
    509                     stat_arr[1] = bcmFieldStatNotRedBytes;
    510                     nstat = 2;
    511                     break;
    512                 case (0x4):                                                                     
    513                     stat_arr[0] = bcmFieldStatGreenPackets;
    514                     stat_arr[1] = bcmFieldStatNotGreenPackets;
    515                     nstat = 2;
    516                     break;
    517                 case (0xc):
    518                     stat_arr[0] = bcmFieldStatGreenBytes;
    519                     stat_arr[1] = bcmFieldStatNotGreenBytes;
    520                     nstat = 2;
    521                     break;
    522                 case (0x5):
    523                     stat_arr[0] = bcmFieldStatGreenPackets;
    524                     stat_arr[1] = bcmFieldStatRedPackets;
    525                     nstat = 2;
    526                     break;
    527                 case (0xd):
    528                     stat_arr[0] = bcmFieldStatGreenBytes;
    529                     stat_arr[1] = bcmFieldStatRedBytes;
    530                     nstat = 2;
    531                     break;
    532                 case (0x6):
    533                     stat_arr[0] = bcmFieldStatGreenPackets;
    534                     stat_arr[1] = bcmFieldStatYellowPackets;
    535                     nstat = 2;
    536                     break;
    537                 case (0xe):
    538                     stat_arr[0] = bcmFieldStatGreenBytes;
    539                     stat_arr[1] = bcmFieldStatYellowBytes;
    540                     nstat = 2;
    541                     break;                                                                       
    542                 case (0x7):
    543                     stat_arr[0] = bcmFieldStatRedPackets;
    544                     stat_arr[1] = bcmFieldStatYellowPackets;
    545                     nstat = 2;
    546                     break;
    547                 case (0xf):
    548                     stat_arr[0] = bcmFieldStatRedBytes;
    549                     stat_arr[1] = bcmFieldStatYellowBytes;
    550                     nstat = 2;
    551                     break;                                                        
    552                 default:
    553                     break;
    554             }
    555         } else if (fg->stage_id == _BCM_FIELD_STAGE_EGRESS) {
    556             stat_arr[0] = bcmFieldStatPackets;      
    557         }
    558         rv = _bcm_field_stat_array_init(unit, fc, f_st, nstat, stat_arr);
    559         if (BCM_FAILURE(rv)) {
    560             sal_free(f_st);
    561             return rv;
    562         }
    563 
    564         /* Assume counter was created using the stat_create API */
    565         if (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) {
    566             if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
    567                 if ((part == 2) || (part == 3)) {
    568                     f_ent->flags |= _FP_ENTRY_STAT_IN_SECONDARY_SLICE;
    569                 }
    570             } else {
    571                 if (part == 1) {
    572                     f_ent->flags |= _FP_ENTRY_STAT_IN_SECONDARY_SLICE;
    573                 }
    574             }
    575         }
    576         _FP_HASH_INSERT(fc->stat_hash, f_st, 
    577                         (stat_id & _FP_HASH_INDEX_MASK(fc)));
    578         fc->stat_count++;
    579         /* Mark as used in the slice */
    580         if (2 == f_st->hw_entry_count) {
    581             _FP_COUNTER_BMP_ADD(fs->counter_bmp, 2 * ctr_idx);
    582             _FP_COUNTER_BMP_ADD(fs->counter_bmp, 2 * ctr_idx + 1);
    583         } else {
    584             if (ctr_mode % 2) {
    585                 _FP_COUNTER_BMP_ADD(fs->counter_bmp, 2 * ctr_idx + 1);
    586             } else {
    587                 _FP_COUNTER_BMP_ADD(fs->counter_bmp, 2 * ctr_idx);
    588             }
    589         }
    590         fg->group_status.counter_count =
    591              fg->group_status.counter_count + f_st->hw_entry_count;
    592     }
    593 
    594     /* Associate the stat object with the entry */
    595     f_ent_st->flags |= (_FP_ENTRY_STAT_VALID | ent_st_flags);
    596     f_ent_st->sid = f_st->sid;
    597 
    598     return BCM_E_NONE;
    599 }
    600 
    601 /*
    602  * Function:
    603  *    _field_fb_meter_index_in_use
    604  * Purpose:
    605  *    Returns success if meter index/meter pair is in use.
    606  * Parameters:
    607  *     unit             - (IN) BCM device number.
    608  *     fs               - (IN) Slice where meter resides.
    609  *     meter_pair_mode  - (IN) Meter mode.
    610  *     meter_offset     - (IN) Odd/Even meter offset value.
    611  *     idx              - (IN) Meter pair index.
    612  * Returns:
    613  *     BCM_E_XXX
    614  */
    615 STATIC
    616 int _field_fb_meter_index_in_use(int unit,
    617                                  _field_slice_t *fs,
    618                                  uint32 meter_pair_mode,
    619                                  uint32 meter_offset,
    620                                  int idx)
    621 {
    622     /* Input parameter check. */
    623     if (NULL == fs) {
    624         return (BCM_E_INTERNAL);
    625     }
    626 
    627     /* Meters are per-slice resource. */
    628     if (meter_pair_mode == BCM_FIELD_METER_MODE_FLOW
    629         && _FP_METER_BMP_TEST(fs->meter_bmp, ((idx * 2) + meter_offset))) {
    630         /* Flow mode meter index in use. */
    631         return (BCM_E_NONE);
    632     } else if (_FP_METER_BMP_TEST(fs->meter_bmp, (idx * 2))
    633                && _FP_METER_BMP_TEST(fs->meter_bmp, ((idx * 2) + 1))) {
    634         /* Non-Flow mode meter pair index in use. */
    635         return (BCM_E_NONE);
    636     }
    637     return (BCM_E_NOT_FOUND);
    638 }
    639 
    640 int
    641 _field_fb_meter_recover(int unit, _field_entry_t *f_ent, 
    642                         _meter_config_t *meter_conf, int part, 
    643                         bcm_policer_t pid)
    644 {
    645     _field_group_t *fg;
    646     _field_stage_t *stage_fc;
    647     _field_stage_id_t stage_id;
    648     _field_control_t *fc;
    649     _field_slice_t *fs;
    650     _field_policer_t *f_pl = NULL;
    651     _field_entry_policer_t *f_ent_pl;
    652     int rv, idx, policer_id, found, mem_idx, meter_offset = 0;
    653     uint32 ent[SOC_MAX_MEM_FIELD_WORDS], ent_pl_flags = 0;
    654     uint32 refresh_count, bucket_count;
    655 #ifdef BCM_FIREBOLT2_SUPPORT
    656     uint32 bucket_size;
    657 #endif /* BCM_FIREBOLT2_SUPPORT */
    658 
    659     if ((meter_conf->meter_mode == 0) && (meter_conf->meter_idx == 0)) {
    660         return BCM_E_NONE;
    661     }
    662 
    663     fg = f_ent->group;
    664     fs = f_ent[part].fs;
    665 
    666     /* Get field control and stage control */
    667     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
    668     stage_id = f_ent->group->stage_id;
    669     rv = _field_stage_control_get(unit, stage_id, &stage_fc);      
    670     BCM_IF_ERROR_RETURN(rv);
    671 
    672 #ifdef BCM_FIREBOLT2_SUPPORT
    673     if ((meter_conf->meter_mode == 4) && 
    674         (stage_id == _BCM_FIELD_STAGE_EGRESS)) {
    675         return BCM_E_NONE;
    676     } 
    677 #endif
    678 
    679     if (BCM_FIELD_METER_MODE_FLOW == meter_conf->meter_mode) {
    680         meter_offset = (meter_conf->meter_update_even
    681                         && meter_conf->meter_test_even) ? 0 : 1;
    682     }
    683 
    684     if (BCM_SUCCESS(_field_fb_meter_index_in_use(unit, fs,
    685             meter_conf->meter_mode, meter_offset, meter_conf->meter_idx))) {
    686         found = 0;
    687         for (idx = 0; idx < _FP_HASH_SZ(fc); idx++) {
    688             f_pl = fc->policer_hash[idx];
    689             while (f_pl != NULL) {
    690                 if ((f_pl->hw_index == meter_conf->meter_idx) && 
    691                     (f_pl->pool_index == fs->slice_number) &&
    692                     (f_pl->stage_id == stage_id)) {
    693                         if (meter_conf->meter_mode ==
    694                              BCM_FIELD_METER_MODE_FLOW) {
    695                             if (((meter_offset == 1) &&
    696                                  (_FP_POLICER_EXCESS_HW_METER(f_pl))) ||
    697                                 ((meter_offset == 0) &&
    698                                  !(_FP_POLICER_EXCESS_HW_METER(f_pl)))) {
    699                                 f_pl = f_pl->next;
    700                                 continue;
    701                             } else {
    702                                found =1;
    703                                 break;
    704                             }
    705                         } else {
    706                             found = 1;
    707                             break;
    708                         }
    709                 }
    710                 f_pl = f_pl->next;
    711             }
    712             if (found) {
    713                 break;
    714             }
    715         }
    716         if (!found) {
    717             return BCM_E_INTERNAL;
    718         }
    719         f_pl->hw_ref_count++;
    720         f_pl->sw_ref_count++;
    721     } else {
    722         /* Allocate new policer object */
    723         if (fc->l2warm) {
    724             policer_id = pid;
    725         } else {
    726             BCM_IF_ERROR_RETURN(_field_policer_id_alloc(unit, &policer_id));
    727         }
    728         _FP_XGS3_ALLOC(f_pl, sizeof (_field_policer_t), "Field policer entity");
    729         if (NULL == f_pl) {
    730             return (BCM_E_MEMORY);
    731         }
    732         ent_pl_flags |= _FP_POLICER_INSTALLED;
    733         f_pl->sw_ref_count = 2;
    734         f_pl->hw_ref_count = 1;
    735         f_pl->pool_index = fs->slice_number;
    736         f_pl->hw_index = meter_conf->meter_idx;
    737         f_pl->pid = policer_id;
    738         f_pl->stage_id = fg->stage_id;
    739 
    740         switch (meter_conf->meter_mode) {
    741             case BCM_FIELD_METER_MODE_DEFAULT: /* 0 */
    742                 f_pl->cfg.mode = bcmPolicerModeGreen;
    743                 break;
    744             case BCM_FIELD_METER_MODE_FLOW: /* 1 */
    745                 f_pl->cfg.mode = bcmPolicerModeCommitted;
    746 
    747                 if (meter_offset) {
    748                     /* Flow mode using committed hardware meter. */
    749                     _FP_POLICER_EXCESS_HW_METER_CLEAR(f_pl);
    750                 } else {
    751                     /* Flow mode using excess hardware meter. */
    752                     _FP_POLICER_EXCESS_HW_METER_SET(f_pl);
    753                 }
    754 
    755                 mem_idx =
    756                 stage_fc->slices[_FP_DEF_INST][f_pl->pool_index].start_tcam_idx
    757                             + (2 * f_pl->hw_index) + meter_offset;
    758                 rv = soc_mem_read(unit, FP_METER_TABLEm, MEM_BLOCK_ANY,
    759                                   mem_idx, ent);
    760                 if (BCM_FAILURE(rv)) {
    761                     sal_free(f_pl);
    762                     return rv;
    763                 }
    764                 refresh_count = soc_mem_field32_get(unit, FP_METER_TABLEm, ent,
    765                                                     REFRESHCOUNTf);
    766                 bucket_count = soc_mem_field32_get(unit, FP_METER_TABLEm, ent,
    767                                                    BUCKETCOUNTf);
    768                 
    769                 f_pl->cfg.ckbits_sec = refresh_count * _FP_POLICER_REFRESH_RATE;
    770 #ifdef BCM_FIREBOLT2_SUPPORT
    771                 bucket_size = soc_mem_field32_get(unit, FP_METER_TABLEm, ent,
    772                                                   BUCKETSIZEf);
    773                 if (SOC_IS_FIREBOLT2(unit)) {
    774                     f_pl->cfg.ckbits_burst
    775                         = _bcm_fb2_bucket_encoding_to_kbits(bucket_size, TRUE);
    776                 } else
    777 #endif
    778                 {
    779                     f_pl->cfg.ckbits_burst = bucket_count / 2 / 1024;
    780                     /* Refer to _field_fb_bucket_calc */
    781                 }
    782                 break;
    783             case BCM_FIELD_METER_MODE_trTCM_COLOR_BLIND: /* 2 */
    784                 f_pl->cfg.flags |= BCM_POLICER_COLOR_BLIND;
    785                 /* Fall through */
    786             case BCM_FIELD_METER_MODE_trTCM_COLOR_AWARE: /* 3 */
    787                 f_pl->cfg.mode = bcmPolicerModeTrTcm;
    788                 /* Get the peak attributes */
    789                 mem_idx =
    790                 stage_fc->slices[_FP_DEF_INST][f_pl->pool_index].start_tcam_idx
    791                             + (2 * f_pl->hw_index);
    792                 rv = soc_mem_read(unit, FP_METER_TABLEm, MEM_BLOCK_ANY,
    793                                   mem_idx, ent);
    794                 if (BCM_FAILURE(rv)) {
    795                     sal_free(f_pl);
    796                     return rv;
    797                 }
    798                 refresh_count = soc_mem_field32_get(unit, FP_METER_TABLEm, ent,
    799                                                     REFRESHCOUNTf);
    800                 bucket_count = soc_mem_field32_get(unit, FP_METER_TABLEm, ent,
    801                                                    BUCKETCOUNTf);
    802                 f_pl->cfg.pkbits_sec = refresh_count * _FP_POLICER_REFRESH_RATE;
    803 #ifdef BCM_FIREBOLT2_SUPPORT
    804                 bucket_size = soc_mem_field32_get(unit, FP_METER_TABLEm, ent,
    805                                                   BUCKETSIZEf);
    806                 if (SOC_IS_FIREBOLT2(unit)) {
    807                     f_pl->cfg.pkbits_burst =
    808                        _bcm_fb2_bucket_encoding_to_kbits(bucket_size, TRUE);
    809                 } else
    810 #endif
    811                 {
    812                     f_pl->cfg.pkbits_burst = bucket_count / 2 / 1024;
    813                     /* Refer to _field_fb_bucket_calc */
    814                 }
    815                 /* Get the committed attributes */
    816                 mem_idx =
    817                 stage_fc->slices[_FP_DEF_INST][f_pl->pool_index].start_tcam_idx
    818                             + (2 * f_pl->hw_index) + 1;
    819                 rv = soc_mem_read(unit, FP_METER_TABLEm, MEM_BLOCK_ANY,
    820                                   mem_idx, ent);
    821                 if (BCM_FAILURE(rv)) {
    822                     sal_free(f_pl);
    823                     return rv;
    824                 }
    825                 refresh_count = soc_mem_field32_get(unit, FP_METER_TABLEm, ent,
    826                                                     REFRESHCOUNTf);
    827                 bucket_count = soc_mem_field32_get(unit, FP_METER_TABLEm, ent,
    828                                                    BUCKETCOUNTf);
    829                 f_pl->cfg.ckbits_sec = refresh_count * _FP_POLICER_REFRESH_RATE;
    830 #ifdef BCM_FIREBOLT2_SUPPORT
    831                 bucket_size = soc_mem_field32_get(unit, FP_METER_TABLEm, ent,
    832                                                   BUCKETSIZEf);
    833                 if (SOC_IS_FIREBOLT2(unit)) {
    834                     f_pl->cfg.ckbits_burst = 
    835                        _bcm_fb2_bucket_encoding_to_kbits(bucket_size, TRUE);
    836                 } else
    837 #endif
    838                 {
    839                     f_pl->cfg.ckbits_burst = bucket_count / 2 / 1024;
    840                     /* Refer to _field_fb_bucket_calc */
    841                 }
    842                 break;
    843             case 4:
    844                 if (fg->stage_id == _BCM_FIELD_STAGE_EGRESS) {
    845                     f_pl->cfg.mode = bcmPolicerModePassThrough;
    846                 }
    847                 break;
    848             case 5:
    849                 break;
    850             case BCM_FIELD_METER_MODE_srTCM_COLOR_BLIND: /* 6 */
    851                 f_pl->cfg.flags |= BCM_POLICER_COLOR_BLIND;
    852                 /* Fall through */
    853             case BCM_FIELD_METER_MODE_srTCM_COLOR_AWARE: /* 7 */
    854                 f_pl->cfg.mode = bcmPolicerModeSrTcm;
    855                 /* Get the peak attributes */
    856                 mem_idx =
    857                 stage_fc->slices[_FP_DEF_INST][f_pl->pool_index].start_tcam_idx
    858                             + (2 * f_pl->hw_index);
    859                 rv = soc_mem_read(unit, FP_METER_TABLEm, MEM_BLOCK_ANY,
    860                                   mem_idx, ent);
    861                 if (BCM_FAILURE(rv)) {
    862                     sal_free(f_pl);
    863                     return rv;
    864                 }
    865                 refresh_count = soc_mem_field32_get(unit, FP_METER_TABLEm, ent,
    866                                                     REFRESHCOUNTf);
    867                 bucket_count = soc_mem_field32_get(unit, FP_METER_TABLEm, ent,
    868                                                    BUCKETCOUNTf);
    869                 f_pl->cfg.pkbits_sec = refresh_count * _FP_POLICER_REFRESH_RATE;
    870 #ifdef BCM_FIREBOLT2_SUPPORT
    871                 bucket_size = soc_mem_field32_get(unit, FP_METER_TABLEm, ent,
    872                                                   BUCKETSIZEf);
    873                 if (SOC_IS_FIREBOLT2(unit)) {
    874                     f_pl->cfg.pkbits_burst = 
    875                        _bcm_fb2_bucket_encoding_to_kbits(bucket_size, TRUE);
    876                 } else
    877 #endif
    878                 {
    879                     f_pl->cfg.pkbits_burst = bucket_count / 2 / 1024;
    880                     /* Refer to _field_fb_bucket_calc */
    881                 }
    882                 /* Get the committed attributes */
    883                 mem_idx =
    884                 stage_fc->slices[_FP_DEF_INST][f_pl->pool_index].start_tcam_idx
    885                             + (2 * f_pl->hw_index) + 1;
    886                 rv = soc_mem_read(unit, FP_METER_TABLEm, MEM_BLOCK_ANY,
    887                                   mem_idx, ent);
    888                 if (BCM_FAILURE(rv)) {
    889                     sal_free(f_pl);
    890                     return rv;
    891                 }
    892                 refresh_count = soc_mem_field32_get(unit, FP_METER_TABLEm, ent,
    893                                                     REFRESHCOUNTf);
    894                 bucket_count = soc_mem_field32_get(unit, FP_METER_TABLEm, ent,
    895                                                    BUCKETCOUNTf);
    896                 f_pl->cfg.ckbits_sec = refresh_count * _FP_POLICER_REFRESH_RATE;
    897 #ifdef BCM_FIREBOLT2_SUPPORT
    898                 bucket_size = soc_mem_field32_get(unit, FP_METER_TABLEm, ent,
    899                                                   BUCKETSIZEf);
    900                 if (SOC_IS_FIREBOLT2(unit)) {
    901                     f_pl->cfg.ckbits_burst = 
    902                        _bcm_fb2_bucket_encoding_to_kbits(bucket_size, TRUE);
    903                 } else
    904 #endif
    905                 {
    906                     f_pl->cfg.ckbits_burst = bucket_count / 2 / 1024;
    907                     /* Refer to _field_fb_bucket_calc */
    908                 }
    909                 break;
    910             default:
    911                 break;
    912         }
    913 
    914         /* Assume policer was created using the policer_create API */
    915         if (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) {
    916             if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
    917                 if ((part == 2) || (part == 3)) {
    918                     f_ent->flags |= _FP_ENTRY_POLICER_IN_SECONDARY_SLICE;
    919                 }
    920             } else {
    921                 if (part == 1) {
    922                     f_ent->flags |= _FP_ENTRY_POLICER_IN_SECONDARY_SLICE;
    923                 }
    924             }
    925         }
    926         _FP_HASH_INSERT(fc->policer_hash, f_pl, 
    927                         (policer_id & _FP_HASH_INDEX_MASK(fc)));
    928         fc->policer_count++;
    929         /* Mark as used in the slice */
    930         if (!_FP_POLICER_IS_FLOW_MODE(f_pl)) {
    931             _FP_METER_BMP_ADD(fs->meter_bmp, (f_pl->hw_index * 2));
    932             _FP_METER_BMP_ADD(fs->meter_bmp, ((f_pl->hw_index * 2) + 1));
    933         } else {
    934             _FP_METER_BMP_ADD(fs->meter_bmp, ((f_pl->hw_index * 2) + meter_offset));
    935         }
    936         fg->group_status.meter_count++;
    937     }
    938 
    939     /* Associate the policer object with the entry */
    940     f_ent_pl = &f_ent->policer[0];
    941     f_ent_pl->flags |= (_FP_POLICER_VALID | ent_pl_flags);
    942     f_ent_pl->pid = f_pl->pid;
    943 
    944     return BCM_E_NONE;
    945 }
    946 
    947 STATIC int
    948 _field_fb_actions_recover_action_add(int                unit,
    949                                       _field_entry_t     *f_ent,
    950                                       bcm_field_action_t action,
    951                                       uint32             param0,
    952                                       uint32             param1,
    953                                       uint32             param2,
    954                                       uint32             param3,
    955                                       uint32             hw_index
    956                                       )
    957 {
    958     int             rv;
    959     _field_action_t *fa = NULL;
    960 
    961     rv = _field_action_alloc(unit, action,
    962              param0, param1, param2, param3, 0, 0, &fa);
    963     if (BCM_FAILURE(rv)) {
    964         return rv;
    965     }
    966 
    967     fa->hw_index = hw_index;
    968 
    969     fa->flags &= ~_FP_ACTION_DIRTY; /* Mark action as installed. */
    970 
    971     /* Add action to front of entry's linked-list. */
    972     fa->next = f_ent->actions;
    973     f_ent->actions  = fa;
    974 
    975     return (BCM_E_NONE);                                            
    976 }
    977 
    978 int
    979 _field_fb_actions_recover(int unit, uint32 *policy_entry, 
    980                            _field_entry_t *f_ent, int part, soc_mem_t mem,
    981                            _field_entry_wb_info_t *f_ent_wb_info)
    982 {
    983     soc_field_t fld;                    /* Policy table field */
    984     uint32 fldval, param0, param1, append; /* Field value and action params */
    985     uint32 ctr_mode, ctr_idx;           /* Counter mode and index */
    986     _field_action_t *fa = NULL;         /* Action details */
    987     bcm_field_action_t action;          /* Action type */
    988     int rv, i, num_fields;              /* Number of policy table fields */
    989     _meter_config_t meter_conf;         /* Meter config info */
    990     egr_l3_next_hop_entry_t egr_l3_next_hop_entry; /* Egress Next Hop table
    991                                                     * entry info */
    992     sal_mac_addr_t mac_addr;             /* MAC address info */
    993     uint32 mac_addr_words[2];            /* MAC address info for Param[0],
    994                                           * Param[1] */
    995     uint16 vlan_id;                      /* VLAN ID info */
    996     uint32 hw_index;                     /* Policy table index info */
    997     int action_sync = 1;
    998 
    999     if (f_ent_wb_info == NULL) {
   1000         return BCM_E_INTERNAL;
   1001     }
   1002 
   1003     num_fields = SOC_MEM_INFO(unit, mem).nFields;
   1004     if (f_ent_wb_info->action_bmp == NULL || f_ent_wb_info->action_bmp->w == NULL) {
   1005        action_sync = 0;
   1006     }
   1007 
   1008     for (i = 0; i < num_fields; i++) {
   1009         fld = SOC_MEM_INFO(unit, mem).fields[i].field;
   1010         fldval = PolicyGet(unit, mem, policy_entry, fld);
   1011         action = param0 = param1 = append = 0;
   1012         switch (fld) {
   1013         case GREEN_TO_PIDf:
   1014             if (fldval) {
   1015                 f_ent->flags |= _FP_ENTRY_COLOR_INDEPENDENT;
   1016             }
   1017             break;
   1018         case ECN_CNGf:
   1019             if (fldval) {
   1020                 action = bcmFieldActionEcnNew;
   1021                 append = 1;
   1022             }
   1023             break;
   1024         case CHANGE_PRIORITYf:
   1025             if (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) {
   1026                 if (fldval) {
   1027                     action = bcmFieldActionOuterVlanPrioNew;
   1028                     param0 = PolicyGet(unit, mem, policy_entry, 
   1029                                        NEW_PRIORITYf);
   1030                     append = 1;
   1031                 }
   1032             } else {
   1033                 switch (fldval) {
   1034                     case 1:
   1035                         action = bcmFieldActionCosQNew;
   1036                         param0 = PolicyGet(unit, mem, policy_entry, 
   1037                                            NEWPRIf);
   1038                         append = 1;
   1039                         break;
   1040                     case 2:
   1041                         action = bcmFieldActionCosQCpuNew;
   1042                         param0 = PolicyGet(unit, mem, policy_entry, 
   1043                                            NEWPRIf);
   1044                         append = 1;
   1045                         break;
   1046                     case 4:
   1047                         action = bcmFieldActionPrioPktAndIntCopy;
   1048                         append = 1;
   1049                         break;
   1050                     case 5:
   1051                         action = bcmFieldActionPrioPktAndIntNew;
   1052                         param0 = PolicyGet(unit, mem, policy_entry, 
   1053                                            NEWPRIf);
   1054                         append = 1;
   1055                         break;
   1056                     case 6:
   1057                         action = bcmFieldActionPrioPktAndIntTos;
   1058                         append = 1;
   1059                         break;
   1060                     case 7:
   1061                         action = bcmFieldActionPrioPktAndIntCancel;
   1062                         append = 1;
   1063                         break;
   1064                     case 8:
   1065                         action = bcmFieldActionPrioPktCopy;
   1066                         append = 1;
   1067                         break;
   1068                     case 9:
   1069                         action = bcmFieldActionPrioPktNew;
   1070                         param0 = PolicyGet(unit, mem, policy_entry, 
   1071                                            NEWPRIf);
   1072                         append = 1;
   1073                         break;
   1074                     case 10:
   1075                         action = bcmFieldActionPrioPktTos;
   1076                         append = 1;
   1077                         break;
   1078                     case 11:
   1079                         action = bcmFieldActionPrioPktCancel;
   1080                         append = 1;
   1081                         break;
   1082                     case 12:
   1083                         action = bcmFieldActionPrioIntCopy;
   1084                         append = 1;
   1085                         break;
   1086                     case 13:
   1087                         action = bcmFieldActionPrioIntNew;
   1088                         param0 = PolicyGet(unit, mem, policy_entry, 
   1089                                            NEWPRIf);
   1090                         append = 1;
   1091                         break;
   1092                     case 14:
   1093                         action = bcmFieldActionPrioIntTos;
   1094                         append = 1;
   1095                         break;
   1096                     case 15:
   1097                         action = bcmFieldActionPrioIntCancel;
   1098                         append = 1;
   1099                         break;
   1100                     default:
   1101                         break; /* Do nothing */
   1102                 }
   1103             }
   1104             break;
   1105         case CHANGE_DSCP_TOSf:
   1106             switch (fldval) {
   1107                 case 1:
   1108                     action = bcmFieldActionTosNew;
   1109                     param0 = PolicyGet(unit, mem, policy_entry, NEWDSCP_TOSf);
   1110                     append = 1;
   1111                     break;
   1112                 case 2:
   1113                     action = bcmFieldActionTosCopy;
   1114                     append = 1;
   1115                     break;
   1116                 case 3:
   1117                     action = bcmFieldActionDscpNew;
   1118                     param0 = PolicyGet(unit, mem, policy_entry, NEWDSCP_TOSf);
   1119                     append = 1;
   1120                     break;
   1121                 case 4:
   1122                     action = bcmFieldActionDscpCancel;
   1123                     append = 1;
   1124                     break;
   1125                 default:
   1126                     break; /* Do nothing */
   1127             }
   1128             break;
   1129         case RP_CHANGE_DSCPf:
   1130             switch (fldval) {
   1131                 case 1:
   1132                     action = bcmFieldActionRpDscpNew;
   1133                     param0 = PolicyGet(unit, mem, policy_entry, RP_DSCPf);
   1134                     append = 1;
   1135                     break;
   1136                 default:
   1137                     break; /* Do nothing */
   1138             }
   1139             break;
   1140         case YP_CHANGE_DSCPf:
   1141             switch (fldval) {
   1142                 case 1:
   1143                     action = bcmFieldActionYpDscpNew;
   1144                     param0 = PolicyGet(unit, mem, policy_entry, YP_DSCPf);
   1145                     append = 1;
   1146                     break;
   1147                 default:
   1148                     break; /* Do nothing */
   1149             }
   1150             break;
   1151         case COPY_TO_CPUf:
   1152             if (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) {
   1153                 if (fldval) {
   1154                     action = bcmFieldActionCopyToCpu;
   1155                     param0 = 1;
   1156                     append = 1;
   1157                 }
   1158             } else {
   1159                 switch (fldval) {
   1160                     case 1:
   1161                         action = bcmFieldActionCopyToCpu;
   1162                         param1 = PolicyGet(unit, mem, policy_entry, 
   1163                                            MATCHED_RULEf);
   1164                         if (param1 != 0) {
   1165                             param0 = 1;
   1166                         }
   1167                         append = 1;
   1168                         break;
   1169                     case 2:
   1170                         action = bcmFieldActionCopyToCpuCancel;
   1171                         append = 1;
   1172                         break;
   1173                     case 3:
   1174                         action = bcmFieldActionSwitchToCpuCancel;
   1175                         append = 1;
   1176                         break;
   1177                     default:
   1178                         break; /* Do nothing */
   1179                 }
   1180             }
   1181             break;
   1182         case YP_COPY_TO_CPUf:
   1183             switch (fldval) {
   1184                 case 1:
   1185                     action = bcmFieldActionYpCopyToCpu;
   1186                     param1 = PolicyGet(unit, mem, policy_entry, MATCHED_RULEf);
   1187                     if (param1 != 0) {
   1188                         param0 = 1;
   1189                     }
   1190                     append = 1;
   1191                     break;
   1192                 case 2:
   1193                     action = bcmFieldActionYpCopyToCpuCancel;
   1194                     append = 1;
   1195                     break;
   1196                 default:
   1197                     break; /* Do nothing */
   1198             }
   1199             break;
   1200         case RP_COPY_TO_CPUf:
   1201             switch (fldval) {
   1202                 case 1:
   1203                     action = bcmFieldActionRpCopyToCpu;
   1204                     param1 = PolicyGet(unit, mem, policy_entry, MATCHED_RULEf);
   1205                     if (param1 != 0) {
   1206                         param0 = 1;
   1207                     }
   1208                     append = 1;
   1209                     break;
   1210                 case 2:
   1211                     action = bcmFieldActionRpCopyToCpuCancel;
   1212                     append = 1;
   1213                     break;
   1214                 case 3:
   1215                     action = bcmFieldActionRpSwitchToCpuCancel;
   1216                     append = 1;
   1217                     break;
   1218                 default:
   1219                     break; /* Do nothing */
   1220             }
   1221             break;
   1222         case PACKET_REDIRECTIONf:
   1223             switch (fldval) {
   1224                 case 1:
   1225                     if (PolicyGet(unit, mem, policy_entry, 
   1226                                   REDIRECTIONf) & 0x20) {
   1227                         action = bcmFieldActionRedirectTrunk;
   1228                         param0 = PolicyGet(unit, mem, policy_entry, 
   1229                                            REDIRECTIONf) & 0x1f;
   1230                     } else {
   1231                         action = bcmFieldActionRedirect;
   1232                         param0 = PolicyGet(unit, mem, policy_entry, 
   1233                                            REDIRECTIONf) >> 6;
   1234                         param1 = PolicyGet(unit, mem, policy_entry, 
   1235                                            REDIRECTIONf) & 0x3f;
   1236                     }
   1237                     append = 1;
   1238                     break;
   1239                 case 2:
   1240                     action = bcmFieldActionRedirectCancel;
   1241                     append = 1;
   1242                     break;
   1243                 case 3:
   1244                     action = bcmFieldActionRedirectPbmp;
   1245                     param0 = PolicyGet(unit, mem, policy_entry, REDIRECTIONf);
   1246                     append = 1;
   1247                     break;
   1248                 case 4:
   1249                     action = bcmFieldActionEgressMask;
   1250                     param0 = PolicyGet(unit, mem, policy_entry, REDIRECTIONf);
   1251                     append = 1;
   1252                     break;
   1253                 default:
   1254                     break; /* Do nothing */
   1255             }
   1256             break;
   1257         case DROPf:
   1258             switch (fldval) {
   1259                 case 1:
   1260                     action = bcmFieldActionDrop;
   1261                     append = 1;
   1262                     break;
   1263                 case 2:
   1264                     action = bcmFieldActionDropCancel;
   1265                     append = 1;
   1266                     break;
   1267                 default:
   1268                     break; /* Do nothing */
   1269             }
   1270             break;
   1271         case YP_DROPf:
   1272             switch (fldval) {
   1273                 case 1:
   1274                     action = bcmFieldActionYpDrop;
   1275                     append = 1;
   1276                     break;
   1277                 case 2:
   1278                     action = bcmFieldActionYpDropCancel;
   1279                     append = 1;
   1280                     break;
   1281                 default:
   1282                     break; /* Do nothing */
   1283             }
   1284             break;
   1285         case RP_DROPf:
   1286             switch (fldval) {
   1287                 case 1:
   1288                     action = bcmFieldActionRpDrop;
   1289                     append = 1;
   1290                     break;
   1291                 case 2:
   1292                     action = bcmFieldActionRpDropCancel;
   1293                     append = 1;
   1294                     break;
   1295                 default:
   1296                     break; /* Do nothing */
   1297             }
   1298             break;
   1299         case GP_DROPf:
   1300             switch (fldval) {
   1301                 case 1:
   1302                     action = bcmFieldActionGpDrop;
   1303                     append = 1;
   1304                     break;
   1305                 case 2:
   1306                     action = bcmFieldActionGpDropCancel;
   1307                     append = 1;
   1308                     break;
   1309                 default:
   1310                     break; /* Do nothing */
   1311             }
   1312             break;
   1313         case MIRROR_OVERRIDEf:
   1314             if (fldval) {
   1315                 action = bcmFieldActionMirrorOverride;
   1316                 append = 1;
   1317             }
   1318             break;
   1319         case MIRRORf:
   1320             if (fldval & 0x1) {
   1321                 uint32 im_entry[SOC_MAX_MEM_FIELD_WORDS];
   1322                 action = bcmFieldActionMirrorIngress;
   1323                 rv = _field_action_alloc(unit, action,
   1324                          param0, param1, 0, 0, 0, 0, &fa);
   1325                 fa->flags &= ~_FP_ACTION_DIRTY; /* Mark action as installed. */
   1326                 if (BCM_FAILURE(rv)) {
   1327                     return rv;
   1328                 }
   1329                 fa->hw_index = PolicyGet(unit, mem, policy_entry, 
   1330                                          IM_MTP_INDEXf);
   1331                 rv = soc_mem_read(unit, IM_MTP_INDEXm, MEM_BLOCK_ANY, 
   1332                                   fa->hw_index, &im_entry);
   1333                 if (BCM_FAILURE(rv)) {
   1334                     sal_free(fa);
   1335                     return rv;
   1336                 }
   1337                 fa->param[0] = soc_IM_MTP_INDEXm_field32_get(unit, im_entry, 
   1338                                                              MODULE_IDf);
   1339                 fa->param[1] = soc_IM_MTP_INDEXm_field32_get(unit, im_entry, 
   1340                                                              PORT_TGIDf);
   1341                 /* Add action to front of entry's linked-list. */
   1342                 fa->next = f_ent->actions;
   1343                 f_ent->actions  = fa;
   1344             }
   1345             if (fldval & 0x2) {
   1346                 uint32 em_entry[SOC_MAX_MEM_FIELD_WORDS];
   1347                 action = bcmFieldActionMirrorEgress;
   1348                 rv = _field_action_alloc(unit, action,
   1349                          param0, param1, 0, 0, 0, 0, &fa);
   1350                 fa->flags &= ~_FP_ACTION_DIRTY; /* Mark action as installed. */
   1351                 if (BCM_FAILURE(rv)) {
   1352                     return rv;
   1353                 }
   1354                 fa->hw_index = PolicyGet(unit, mem, policy_entry, 
   1355                                          EM_MTP_INDEXf);
   1356                 rv = soc_mem_read(unit, EM_MTP_INDEXm, MEM_BLOCK_ANY, 
   1357                                   fa->hw_index, &em_entry);
   1358                 if (BCM_FAILURE(rv)) {
   1359                     sal_free(fa);
   1360                     return rv;
   1361                 }
   1362                 fa->param[0] = soc_EM_MTP_INDEXm_field32_get(unit, em_entry, 
   1363                                                              MODULE_IDf);
   1364                 fa->param[1] = soc_EM_MTP_INDEXm_field32_get(unit, em_entry, 
   1365                                                              PORT_TGIDf);
   1366                 /* Add action to front of entry's linked-list. */
   1367                 fa->next = f_ent->actions;
   1368                 f_ent->actions  = fa;
   1369             }
   1370             break;
   1371         case L3SW_CHANGE_MACDA_OR_VLANf:
   1372             switch (fldval) {
   1373                 int ecmp_paths, nh_ecmp;
   1374                 case 1:
   1375                     action = bcmFieldActionL3ChangeVlan;
   1376                     if (PolicyGet(unit, mem, policy_entry, ECMPf)) {
   1377                         ecmp_paths = PolicyGet(unit, mem, 
   1378                                                policy_entry, ECMP_COUNTf) + 1;
   1379                         nh_ecmp = PolicyGet(unit, mem, 
   1380                                             policy_entry, ECMP_PTRf);
   1381                         param0 = _FP_L3_ACTION_PACK_ECMP(nh_ecmp, ecmp_paths);
   1382                     } else {
   1383                         nh_ecmp = PolicyGet(unit, mem, 
   1384                                             policy_entry, NEXT_HOP_INDEXf);
   1385                         param0 = _FP_L3_ACTION_PACK_NEXT_HOP(nh_ecmp);
   1386                     }
   1387                     append = 1;
   1388                     
   1389                     if (PolicyGet(unit, mem, policy_entry, ECMPf) == 0) {
   1390 
   1391                         /* Get the Next Hop Index value */
   1392                         hw_index = PolicyGet(unit, mem, policy_entry,
   1393                                         NEXT_HOP_INDEXf);
   1394 
   1395                         /* Read Next Hop information into entry */
   1396                         rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm,
   1397                                 MEM_BLOCK_ANY, hw_index,
   1398                                 egr_l3_next_hop_entry.entry_data);
   1399                         if (BCM_FAILURE(rv)) {
   1400                             return (rv);
   1401                         }
   1402 
   1403                         /* Get the VLAN ID infomation */
   1404                         vlan_id = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
   1405                                         egr_l3_next_hop_entry.entry_data,
   1406                                         INTF_NUMf);
   1407 
   1408                         /* Re-Create bcmFieldActionOuterVlanNew action for the
   1409                          * FP entry */
   1410                         rv = _field_fb_actions_recover_action_add(unit,
   1411                                 f_ent, bcmFieldActionOuterVlanNew, vlan_id, 0,
   1412                                 0, 0, hw_index);
   1413                         if (BCM_FAILURE(rv)) {
   1414                             return (rv);
   1415                         }
   1416                     }
   1417                     break;
   1418                 case 2:
   1419                     action = bcmFieldActionL3ChangeVlanCancel;
   1420                     append = 1;
   1421                     break;
   1422                 case 3:
   1423                 /*recover fabricQueue action*/
   1424                 if ((action_sync == 1) &&
   1425                      SHR_BITGET(f_ent_wb_info->action_bmp->w,
   1426                                  _bcmFieldActionNoParamFabricQueue)) {
   1427                     action = bcmFieldActionFabricQueue;
   1428                     append = 1;
   1429                     param0 = f_ent_wb_info->action_fabricQueue_wb.cosq_gport;
   1430                 }
   1431                 break;
   1432                 case 4:
   1433                     action = bcmFieldActionL3ChangeMacDa;
   1434                     if (PolicyGet(unit, mem, policy_entry, ECMPf)) {
   1435                         ecmp_paths = PolicyGet(unit, mem, 
   1436                                                policy_entry, ECMP_COUNTf) + 1;
   1437                         nh_ecmp = PolicyGet(unit, mem, 
   1438                                             policy_entry, ECMP_PTRf);
   1439                         param0 = _FP_L3_ACTION_PACK_ECMP(nh_ecmp, ecmp_paths);
   1440                     } else {
   1441                         nh_ecmp = PolicyGet(unit, mem, 
   1442                                             policy_entry, NEXT_HOP_INDEXf);
   1443                         param0 = _FP_L3_ACTION_PACK_NEXT_HOP(nh_ecmp);
   1444                     }
   1445                     append = 1;
   1446 
   1447                     if (PolicyGet(unit, mem, policy_entry, ECMPf) == 0) {
   1448 
   1449                         /* Get the Next Hop Index value */
   1450                         hw_index = PolicyGet(unit, mem, policy_entry,
   1451                                         NEXT_HOP_INDEXf);
   1452 
   1453                         /* Read Next Hop information into entry */
   1454                         rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm,
   1455                                 MEM_BLOCK_ANY, hw_index,
   1456                                 egr_l3_next_hop_entry.entry_data);
   1457                         if (BCM_FAILURE(rv)) {
   1458                             return (rv);
   1459                         }
   1460 
   1461                         /* Get the DA/DMAC infomation */
   1462                         soc_mem_mac_addr_get(unit, EGR_L3_NEXT_HOPm,
   1463                             egr_l3_next_hop_entry.entry_data,
   1464                             MAC_ADDRESSf, mac_addr);
   1465                         SAL_MAC_ADDR_TO_UINT32(mac_addr, mac_addr_words);
   1466 
   1467                         /* Re-Create bcmFieldActionDstMacNew action for the
   1468                          * FP entry */
   1469                         rv = _field_fb_actions_recover_action_add(unit,
   1470                                 f_ent, bcmFieldActionDstMacNew,
   1471                                 mac_addr_words[0], mac_addr_words[1], 0, 0,
   1472                                 hw_index);
   1473                         if (BCM_FAILURE(rv)) {
   1474                             return (rv);
   1475                         }
   1476                     }
   1477                     break;
   1478                 case 5:
   1479                     action = bcmFieldActionL3ChangeMacDaCancel;
   1480                     append = 1;
   1481                     break;
   1482                 case 6:
   1483 #ifdef INCLUDE_L3
   1484                     action = bcmFieldActionL3Switch;
   1485                     if (PolicyGet(unit, mem, policy_entry, ECMPf)) {
   1486                         ecmp_paths = PolicyGet(unit, mem, 
   1487                                                policy_entry, ECMP_COUNTf) + 1;
   1488                         nh_ecmp = PolicyGet(unit, mem, 
   1489                                             policy_entry, ECMP_PTRf);
   1490                         param0 = (nh_ecmp) +
   1491                             (BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit));
   1492                     } else {
   1493                         nh_ecmp = PolicyGet(unit, mem, 
   1494                                             policy_entry, NEXT_HOP_INDEXf);
   1495                         param0 = (nh_ecmp) +
   1496                             (BCM_XGS3_EGRESS_IDX_MIN(unit));
   1497                     }
   1498                     append = 1;
   1499 #endif /* INCLUDE_L3 */
   1500                     break;
   1501                 case 7:
   1502                     action = bcmFieldActionL3SwitchCancel;
   1503                     append = 1;
   1504                     break;
   1505                 default:
   1506                     break; /* Do nothing */
   1507             }
   1508             break;
   1509         case DROP_PRECEDENCEf:
   1510             if (fldval) {
   1511                 action = bcmFieldActionDropPrecedence;
   1512                 param0 = fldval;
   1513                 append = 1;
   1514             }
   1515             break;
   1516         case RP_DROP_PRECEDENCEf:
   1517             if (fldval) {
   1518                 action = bcmFieldActionRpDropPrecedence;
   1519                 param0 = fldval;
   1520                 append = 1;
   1521             }
   1522             break;
   1523         case YP_DROP_PRECEDENCEf:
   1524             if (fldval) {
   1525                 action = bcmFieldActionYpDropPrecedence;
   1526                 param0 = fldval;
   1527                 append = 1;
   1528             }
   1529             break;
   1530         case COUNTER_MODEf:
   1531             if (fldval) {
   1532                 ctr_mode = fldval;
   1533                 ctr_idx = PolicyGet(unit, mem, policy_entry, 
   1534                                     COUNTER_INDEXf);
   1535                 BCM_IF_ERROR_RETURN
   1536                    (_field_fb_counter_recover(unit, f_ent, ctr_mode, 
   1537                                                ctr_idx, part, f_ent_wb_info->sid));
   1538             }
   1539             break;
   1540         case METER_PAIR_MODEf:
   1541             meter_conf.meter_mode = fldval;
   1542             meter_conf.meter_mode_modifier
   1543                 = soc_mem_field_valid(unit, mem, METER_PAIR_MODE_MODIFIERf)
   1544                 ? PolicyGet(unit, mem, policy_entry, METER_PAIR_MODE_MODIFIERf)
   1545                 : 0;
   1546             meter_conf.meter_idx = PolicyGet(unit, mem, 
   1547                                              policy_entry, 
   1548                                              METER_INDEX_EVENf);
   1549             meter_conf.meter_update_odd = PolicyGet(unit, mem, 
   1550                                                     policy_entry, 
   1551                                                     METER_UPDATE_ODDf);
   1552             meter_conf.meter_test_odd = PolicyGet(unit, mem, 
   1553                                                   policy_entry, 
   1554                                                   METER_TEST_ODDf);
   1555             meter_conf.meter_update_even = PolicyGet(unit, mem, 
   1556                                                      policy_entry, 
   1557                                                      METER_UPDATE_EVENf);
   1558             meter_conf.meter_test_even = PolicyGet(unit, mem, 
   1559                                                    policy_entry, 
   1560                                                    METER_TEST_EVENf);
   1561             BCM_IF_ERROR_RETURN
   1562                 (_field_fb_meter_recover(unit, f_ent, &meter_conf, part, f_ent_wb_info->pid));
   1563             break;
   1564         case PID_REPLACE_INNER_VIDf:
   1565             if (fldval) {
   1566                 action = bcmFieldActionInnerVlanNew;
   1567                 param0 = PolicyGet(unit, mem, policy_entry, PID_NEW_INNER_VIDf);
   1568                 append = 1;
   1569             }
   1570             break;
   1571         case PID_REPLACE_INNER_PRIf:
   1572             if (fldval) {
   1573                 action = bcmFieldActionInnerVlanPrioNew;
   1574                 param0 = PolicyGet(unit, mem, policy_entry, PID_NEW_INNER_PRIf);
   1575                 append = 1;
   1576             }
   1577             break;
   1578         case PID_REPLACE_OUTER_VIDf:
   1579             if (fldval) {
   1580                 action = bcmFieldActionOuterVlanNew;
   1581                 param0 = PolicyGet(unit, mem, policy_entry, PID_NEW_OUTER_VIDf);
   1582                 append = 1;
   1583             }
   1584             break;
   1585         case PID_REPLACE_OUTER_TPIDf:
   1586             if (fldval) {
   1587                 uint32 mode;
   1588                 uint16 tpid;
   1589                 action = bcmFieldActionInnerVlanPrioNew;
   1590                 mode = PolicyGet(unit, mem, policy_entry, PID_TPID_INDEXf);
   1591                 BCM_IF_ERROR_RETURN
   1592                     (_field_tpid_hw_decode(unit, mode, &tpid));
   1593                 param0 = tpid;
   1594                 append = 1;
   1595             }
   1596             break;
   1597         case RP_CHANGE_DOT1Pf:
   1598             if (fldval) {
   1599                 action = bcmFieldActionRpOuterVlanPrioNew;
   1600                 param0 = PolicyGet(unit, mem, policy_entry, RP_NEW_DOT1Pf);
   1601                 append = 1;
   1602             }
   1603             break;
   1604         case YP_CHANGE_DOT1Pf:
   1605             if (fldval) {
   1606                 action = bcmFieldActionYpOuterVlanPrioNew;
   1607                 param0 = PolicyGet(unit, mem, policy_entry, YP_NEW_DOT1Pf);
   1608                 append = 1;
   1609             }
   1610             break;
   1611         case GP_CHANGE_DOT1Pf:
   1612             if (fldval) {
   1613                 action = bcmFieldActionGpOuterVlanPrioNew;
   1614                 param0 = PolicyGet(unit, mem, policy_entry, GP_NEW_DOT1Pf);
   1615                 append = 1;
   1616             }
   1617             break;
   1618         case PID_INCR_COUNTERf:
   1619             if (fldval) {
   1620                 ctr_mode = fldval;
   1621                 ctr_idx = PolicyGet(unit, mem, policy_entry, 
   1622                                     PID_COUNTER_INDEXf);
   1623                 BCM_IF_ERROR_RETURN
   1624                    (_field_fb_counter_recover(unit, f_ent, ctr_mode, 
   1625                                                ctr_idx, part, f_ent_wb_info->sid));
   1626             }
   1627             break;
   1628         case CHANGE_VLANf:
   1629             switch (fldval) {
   1630                 case 1:
   1631                     action = bcmFieldActionVlanAdd;
   1632                     param0 = PolicyGet(unit, mem, policy_entry, NEW_VLANf);
   1633                     append = 1;
   1634                     break;
   1635                 case 2:
   1636                     action = bcmFieldActionOuterVlanNew;
   1637                     param0 = PolicyGet(unit, mem, policy_entry, NEW_VLANf);
   1638                     append = 1;
   1639                     break;
   1640                 default:
   1641                     break; /* Do nothing */
   1642             }
   1643             break;
   1644         case USE_VFP_CLASS_IDf:
   1645             if (fldval) {
   1646                 action = bcmFieldActionClassSet;
   1647                 param0 = PolicyGet(unit, mem, policy_entry, VFP_CLASS_IDf);
   1648                 append = 1;
   1649             }
   1650             break;
   1651         case USE_VFP_VRF_IDf:
   1652             if (fldval) {
   1653                 action = bcmFieldActionVrfSet;
   1654                 param0 = PolicyGet(unit, mem, policy_entry, VFP_VRF_IDf);
   1655                 append = 1;
   1656             }
   1657             break;
   1658         default:
   1659             break; /* Do nothing */
   1660         }
   1661         if (append) {
   1662             rv = _field_action_alloc(unit, action,
   1663                      param0, param1, 0, 0, 0, 0, &fa);
   1664             fa->flags &= ~_FP_ACTION_DIRTY; /* Mark action as installed. */
   1665             if (BCM_FAILURE(rv)) {
   1666                 return rv;
   1667             }
   1668             /* Add action to front of entry's linked-list. */
   1669             fa->next = f_ent->actions;
   1670             f_ent->actions  = fa;
   1671         }
   1672     }
   1673     return BCM_E_NONE;
   1674 }
   1675 
   1676 int 
   1677 _field_group_info_retrieve(int               unit,
   1678                            bcm_port_t        port,
   1679                            int               inst,
   1680                            bcm_field_group_t *gid, 
   1681                            int               *priority,
   1682                            int               *action_res_id,
   1683                            bcm_pbmp_t        *group_pbmp,
   1684                            int8              *efp_key_info,
   1685                            int               *group_flags,
   1686                            bcm_field_qset_t  *qset,
   1687                            _field_control_t  *fc
   1688                            )
   1689 {
   1690 
   1691     _field_slice_group_info_t *current;
   1692     current = fc->group_arr;
   1693     while (current) {
   1694         if (current->found) {
   1695             *gid = -1; /* GID has already been copied */
   1696             if(!(current = current->next)) {
   1697                 return BCM_E_NONE; /* Will detect it later */
   1698             }
   1699             continue;
   1700         }
   1701         if (((port == -1) || (BCM_PBMP_MEMBER(current->pbmp, port))) &&
   1702             (current->instance == inst)) {
   1703             *gid = current->gid;
   1704             *priority = current->priority;
   1705             *group_flags = current->flags;
   1706             *action_res_id = current->action_res_id;
   1707             if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_21) {
   1708                 SOC_PBMP_ASSIGN(*group_pbmp, current->pbmp);
   1709             }
   1710 
   1711             if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit) ||
   1712                         soc_feature(unit, soc_feature_field_multi_pipe_support)) &&
   1713                     efp_key_info) {
   1714                 efp_key_info[0] = current->efp_pri_key;
   1715                 efp_key_info[1] = current->efp_sec_key;
   1716             }
   1717             sal_memcpy(qset, &current->qset, sizeof(bcm_field_qset_t));
   1718             current->found = 1;
   1719             return BCM_E_NONE;
   1720         } else if (!current->next) {
   1721             *gid = -1; /* Will detect it later */
   1722             return BCM_E_NONE;
   1723         }
   1724         current = current->next;
   1725     }
   1726     return BCM_E_NOT_FOUND;
   1727 }
   1728 
   1729 /* Retrieve all GIDs from a slice during Level 2 warm boot */
   1730 int
   1731 _field_scache_slice_group_recover(int unit, _field_control_t *fc, 
   1732                                       int slice_num, int *multigroup)
   1733 {
   1734     int i, slice_idx;
   1735     int next_group_valid = 1, rv = BCM_E_NONE;
   1736     int qset_count;
   1737     int qset;
   1738     bcm_field_group_t gid;
   1739     bcm_port_t port;
   1740     uint8 *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0];
   1741     uint8 *buf1 = fc->scache_ptr[_FIELD_SCACHE_PART_1];
   1742     _field_slice_group_info_t *new_grp = NULL;
   1743     int priority;
   1744     int action_res_id;
   1745     soc_pbmp_t group_pbmp;
   1746     uint8  udf_count = 0;
   1747     uint8 udf_idx = 0;
   1748 
   1749     /* Parse the scache buffer to recover GIDs and QSETs */
   1750     /* To be used in stage reinit */
   1751     slice_idx = buf[fc->scache_pos] >> 1;
   1752     LOG_VERBOSE(BSL_LS_BCM_FP,
   1753                 (BSL_META_U(unit,
   1754                             "Read slice index %d @ byte %d\n"),
   1755                  slice_idx, fc->scache_pos));
   1756     if (multigroup) {
   1757         *multigroup = buf[fc->scache_pos] & 0x1;
   1758     }
   1759     fc->scache_pos++;
   1760     if (slice_idx != slice_num) {
   1761         /* No groups stored for this slice */
   1762         fc->scache_pos--;
   1763         return BCM_E_NOT_FOUND;
   1764     }
   1765     fc->group_arr = NULL;
   1766 
   1767     /* Parse all the group data for this slice */
   1768     while (next_group_valid) {
   1769         SOC_PBMP_CLEAR(group_pbmp);
   1770         gid = 0;
   1771         if (fc->flags & _FP_STABLE_SAVE_LONG_IDS) {
   1772             /* Read full GID */
   1773 
   1774             gid |= buf[fc->scache_pos];
   1775             fc->scache_pos++;
   1776             gid |= buf[fc->scache_pos] << 8;
   1777             fc->scache_pos++;
   1778             gid |= buf[fc->scache_pos] << 16;
   1779             fc->scache_pos++;
   1780             gid |= buf[fc->scache_pos] << 24;
   1781             fc->scache_pos++;
   1782 
   1783             port = buf[fc->scache_pos];
   1784             fc->scache_pos++;
   1785         } else {
   1786             /* Read compact GID */
   1787 
   1788             gid |= buf[fc->scache_pos]; /* GID */
   1789             fc->scache_pos++;
   1790             port = 0;
   1791             port |= buf[fc->scache_pos] & 0xF; /* Rep_port_lo */
   1792             fc->scache_pos++;
   1793             port |= (buf[fc->scache_pos] & 0x3) << 4; /* Rep_port_hi */
   1794             fc->scache_pos++;
   1795         }
   1796 
   1797         LOG_VERBOSE(BSL_LS_BCM_FP,
   1798                     (BSL_META_U(unit,
   1799                                 "Read group id %d @ %d.\n"),
   1800                      gid, fc->scache_pos - 3));
   1801         if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_21) {
   1802             int i = 0;
   1803             for (i = 0; i < _SHR_PBMP_WORD_MAX; i++) {
   1804                 group_pbmp.pbits[i] = buf[fc->scache_pos];
   1805                 fc->scache_pos++;
   1806                 group_pbmp.pbits[i] |= buf[fc->scache_pos] << 8;
   1807                 fc->scache_pos++;
   1808                 group_pbmp.pbits[i] |= buf[fc->scache_pos] << 16;
   1809                 fc->scache_pos++;
   1810                 group_pbmp.pbits[i] |= buf[fc->scache_pos] << 24;
   1811                 fc->scache_pos++;
   1812             }
   1813         }
   1814         /* Read group priority */
   1815         priority = 0;
   1816         priority |= buf[fc->scache_pos];
   1817         fc->scache_pos++;
   1818         priority |= buf[fc->scache_pos] << 8;
   1819         fc->scache_pos++;
   1820         priority |= buf[fc->scache_pos] << 16;
   1821         fc->scache_pos++;
   1822         priority |= buf[fc->scache_pos] << 24;
   1823         fc->scache_pos++;
   1824 
   1825         /* Read group action res id */
   1826         action_res_id = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT;
   1827         if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_8) {
   1828             action_res_id = 0;
   1829             action_res_id |= buf[fc->scache_pos];
   1830             fc->scache_pos++;
   1831             action_res_id |= buf[fc->scache_pos] << 8;
   1832             fc->scache_pos++;
   1833             action_res_id |= buf[fc->scache_pos] << 16;
   1834             fc->scache_pos++;
   1835             action_res_id |= buf[fc->scache_pos] << 24;
   1836             fc->scache_pos++;
   1837         }
   1838 
   1839         /* Add group info to temp linked list */
   1840         new_grp = NULL;
   1841         _FP_XGS3_ALLOC(new_grp, sizeof(_field_slice_group_info_t), 
   1842                        "Temp group info");
   1843         new_grp->gid = gid;
   1844         new_grp->priority = priority;
   1845         new_grp->action_res_id = action_res_id;
   1846         if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_21) {
   1847             SOC_PBMP_ASSIGN(new_grp->pbmp, group_pbmp);
   1848         }
   1849         BCM_PBMP_PORT_ADD(new_grp->pbmp, port);
   1850         new_grp->next = fc->group_arr;
   1851         fc->group_arr = new_grp;
   1852         qset_count = buf[fc->scache_pos]; /* QSET_count */
   1853         fc->scache_pos++;
   1854 
   1855         LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1856                  "Before Read qset count %d @ s_pos=%d s_pos1=%d\n"),
   1857                  qset_count, fc->scache_pos, fc->scache_pos1));
   1858 
   1859         for (i = 0; i < qset_count; i++) {
   1860             qset = 0;
   1861             qset |= buf[fc->scache_pos];
   1862             fc->scache_pos++;
   1863             if(NULL != buf1) {
   1864                 qset |= buf1[fc->scache_pos1] << 8;
   1865                 fc->scache_pos1++;
   1866             } 
   1867             BCM_FIELD_QSET_ADD(new_grp->qset, qset);
   1868 
   1869             LOG_VERBOSE(BSL_LS_BCM_FP,
   1870                         (BSL_META_U(unit,
   1871                                     "Read qualifier id %d @ %d.\n"),
   1872                          qset, fc->scache_pos - 1));
   1873         }
   1874 
   1875         LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1876                  "After Read qset count %d @ s_pos=%d s_pos1=%d\n"),
   1877                  qset_count, fc->scache_pos, fc->scache_pos1));
   1878 
   1879         if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_10) {
   1880             qset_count = buf[fc->scache_pos]; /* Internal QSET_count */
   1881             fc->scache_pos++;
   1882 
   1883             LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1884                             "Internal Qset count %d @ s_pos=%d s_pos1=%d\n"),
   1885                         qset_count, fc->scache_pos - 1, fc->scache_pos1));
   1886 
   1887             for (i = 0; i < qset_count; i++) {
   1888                 qset = 0;
   1889                 qset |= buf[fc->scache_pos];
   1890                 fc->scache_pos++;
   1891                 if(NULL != buf1) {
   1892                     qset |= buf1[fc->scache_pos1] << 8;
   1893                     fc->scache_pos1++;
   1894                 }
   1895                 qset += bcmFieldQualifyCount;
   1896                 BCM_FIELD_QSET_ADD(new_grp->qset, qset);
   1897 
   1898                 LOG_VERBOSE(BSL_LS_BCM_FP,
   1899                         (BSL_META_U(unit,
   1900                                     "Read internal qualifier %d @ %d.\n"),
   1901                          qset, fc->scache_pos - 1));
   1902             }
   1903 
   1904             LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1905                             "After Read qset count %d @ s_pos=%d s_pos1=%d\n"),
   1906                         qset_count, fc->scache_pos, fc->scache_pos1));
   1907 
   1908             udf_count = buf[fc->scache_pos];
   1909             LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1910                             "Read udf count %d @ s_pos=%d\n"),
   1911                         udf_count, fc->scache_pos));
   1912             fc->scache_pos++;
   1913             for (i = 0; i < udf_count; i++) {
   1914                 udf_idx = buf[fc->scache_pos];
   1915                 fc->scache_pos++;
   1916                 SHR_BITSET(new_grp->qset.udf_map, udf_idx);
   1917                 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1918                                 "Read UDF idx %d  @ byte %d.\n"),
   1919                             udf_idx, fc->scache_pos - 1));
   1920             }
   1921         }
   1922 
   1923         /*
   1924          * In this byte, 
   1925          * bit 0 --  to indicate wheather next group 
   1926          *           in this slice is valid or not 
   1927          * bit 1,2 -- contains group's instance.
   1928          * bit 5 --  to indicate group lookup enable status.
   1929          * bit 6 --  to indicate group is WLAN.
   1930          * bit 7 --  to indicate group auto expansion status.
   1931          */
   1932 
   1933         next_group_valid =  buf[fc->scache_pos] & _FIELD_GROUP_NEXT_GROUP_VALID;
   1934 
   1935         if (buf[fc->scache_pos] & _FIELD_GROUP_AUTO_EXPANSION) {
   1936             new_grp->flags = new_grp->flags | _FP_GROUP_SELECT_AUTO_EXPANSION;
   1937         }
   1938 
   1939         if (buf[fc->scache_pos] & _FIELD_GROUP_LOOKUP_ENABLED) {
   1940             new_grp->flags = new_grp->flags | _FP_GROUP_LOOKUP_ENABLED;
   1941         }
   1942 
   1943         if (buf[fc->scache_pos] & _FIELD_GROUP_WLAN) {
   1944             new_grp->flags = new_grp->flags | _FP_GROUP_WLAN;
   1945         }
   1946 
   1947         new_grp->instance = ((buf[fc->scache_pos] >> 1) & 0x3);
   1948         fc->scache_pos++;
   1949     }
   1950     /* The pointer has now advanced to the "entries" section */
   1951 
   1952     LOG_VERBOSE(BSL_LS_BCM_FP,
   1953                 (BSL_META_U(unit,
   1954                             "Done reading slice @ %d.\n"),
   1955                  fc->scache_pos));
   1956     return rv;
   1957 }
   1958 
   1959 int
   1960 _field_entry_info_retrieve(int unit, _field_control_t *fc, _field_stage_t *stage_fc,
   1961                            int multigroup, int *prev_prio,
   1962                            _field_entry_wb_info_t *f_ent_wb_info)
   1963 {
   1964     uint8 stat_present, pol_present, prio_ctrl;
   1965     uint8 *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0];
   1966     uint8  part_index = 0;
   1967     uint8  part_count = 0;
   1968     _bcmFieldActionNoParam_t ingress_mirror_actions[] = {
   1969                                     _bcmFieldActionNoParamMirrorIngress,
   1970                                     _bcmFieldActionNoParamMirrorIngress1,
   1971                                     _bcmFieldActionNoParamMirrorIngress2,
   1972                                     _bcmFieldActionNoParamMirrorIngress3};
   1973     _bcmFieldActionNoParam_t egress_mirror_actions[] = {
   1974                                     _bcmFieldActionNoParamMirrorEgress,
   1975                                     _bcmFieldActionNoParamMirrorEgress1,
   1976                                     _bcmFieldActionNoParamMirrorEgress2,
   1977                                     _bcmFieldActionNoParamMirrorEgress3};
   1978 
   1979     if (f_ent_wb_info == NULL) {
   1980         return BCM_E_INTERNAL;
   1981     }
   1982 
   1983     f_ent_wb_info->eid = f_ent_wb_info->sid = f_ent_wb_info->pid = 0;
   1984 
   1985     f_ent_wb_info->color_independent = (fc->flags & _FP_COLOR_INDEPENDENT) ? 1 : 0;
   1986 
   1987     if (fc->flags & _FP_STABLE_SAVE_LONG_IDS) {
   1988         /* Read long EID and flags  */
   1989 
   1990         f_ent_wb_info->eid |=  buf[fc->scache_pos];
   1991         fc->scache_pos++;
   1992         f_ent_wb_info->eid |=  buf[fc->scache_pos] << 8;
   1993         fc->scache_pos++;
   1994         f_ent_wb_info->eid |=  buf[fc->scache_pos] << 16;
   1995         fc->scache_pos++;
   1996         f_ent_wb_info->eid |=  buf[fc->scache_pos] << 24;
   1997         fc->scache_pos++;
   1998 
   1999         prio_ctrl    = buf[fc->scache_pos] & 1;
   2000         stat_present = (buf[fc->scache_pos] >> 1) & 1;
   2001         pol_present  = (buf[fc->scache_pos] >> 2) & 1;
   2002         fc->scache_pos++;
   2003     } else {
   2004         /* Read compact EID and flags */
   2005 
   2006         f_ent_wb_info->eid |=  buf[fc->scache_pos]; /* EID_lo */
   2007         fc->scache_pos++;
   2008         f_ent_wb_info->eid |= (buf[fc->scache_pos] & 0xF) << 8; /* EID_hi */
   2009         prio_ctrl = (buf[fc->scache_pos] >> 4) & 0x1;
   2010         stat_present = (buf[fc->scache_pos] >> 5) & 0x1;
   2011         pol_present = (buf[fc->scache_pos] >> 6) & 0x1;
   2012         fc->scache_pos++;
   2013     }
   2014 
   2015     LOG_VERBOSE(BSL_LS_BCM_FP,
   2016                 (BSL_META_U(unit,
   2017                             "Read entry id %d @ byte %d.\n"),
   2018                  f_ent_wb_info->eid, fc->scache_pos - 2));
   2019 
   2020     if (multigroup) {
   2021         fc->scache_pos += (fc->flags & _FP_STABLE_SAVE_LONG_IDS) ? 4 : 2; /* Skip over GID */
   2022     }
   2023 
   2024     if (prio_ctrl) {
   2025         f_ent_wb_info->prio = 0;
   2026         f_ent_wb_info->prio |= buf[fc->scache_pos];
   2027         fc->scache_pos++;
   2028         f_ent_wb_info->prio |= buf[fc->scache_pos] << 8;
   2029         fc->scache_pos++;
   2030         f_ent_wb_info->prio |= buf[fc->scache_pos] << 16;
   2031         fc->scache_pos++;
   2032         f_ent_wb_info->prio |= buf[fc->scache_pos] << 24;
   2033         fc->scache_pos++;
   2034         *prev_prio = f_ent_wb_info->prio;
   2035     } else {
   2036         f_ent_wb_info->prio = *prev_prio;
   2037     }
   2038 
   2039     if (fc->flags & _FP_STABLE_SAVE_LONG_IDS) {
   2040         /* Read long policer and stat ids, if present */
   2041 
   2042         if (pol_present) {
   2043             f_ent_wb_info->pid |= buf[fc->scache_pos];
   2044             fc->scache_pos++;
   2045             f_ent_wb_info->pid |= buf[fc->scache_pos] << 8;
   2046             fc->scache_pos++;
   2047             f_ent_wb_info->pid |= buf[fc->scache_pos] << 16;
   2048             fc->scache_pos++;
   2049             f_ent_wb_info->pid |= buf[fc->scache_pos] << 24;
   2050             fc->scache_pos++;
   2051         }
   2052 
   2053         if (stat_present) {
   2054             f_ent_wb_info->sid |= buf[fc->scache_pos];
   2055             fc->scache_pos++;
   2056             f_ent_wb_info->sid |= buf[fc->scache_pos] << 8;
   2057             fc->scache_pos++;
   2058             f_ent_wb_info->sid |= buf[fc->scache_pos] << 16;
   2059             fc->scache_pos++;
   2060             f_ent_wb_info->sid |= buf[fc->scache_pos] << 24;
   2061             fc->scache_pos++;
   2062         }
   2063     } else {
   2064         /* Read compact policer and stat ids, if present */
   2065 
   2066         if (pol_present) {
   2067             f_ent_wb_info->pid |= buf[fc->scache_pos]; /* PID_lo */
   2068             fc->scache_pos++;
   2069         }
   2070         if (stat_present) {
   2071             f_ent_wb_info->sid |= buf[fc->scache_pos] & 0xF; /* SID_lo */
   2072             if (pol_present) {
   2073                 f_ent_wb_info->pid |= (buf[fc->scache_pos] & 0xF0) << 4; /* PID_hi */
   2074             }
   2075             fc->scache_pos++;
   2076             f_ent_wb_info->sid |= (buf[fc->scache_pos] << 4); /* SID_hi */
   2077             fc->scache_pos++;
   2078         } else if (pol_present) {
   2079             f_ent_wb_info->pid |= (buf[fc->scache_pos] & 0xF0) << 4; /* PID_hi */
   2080             fc->scache_pos++;
   2081         }
   2082     }
   2083 
   2084     /* Retrieve Entry part count */
   2085     if (((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_18) &&
   2086             ((stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) ||
   2087              (stage_fc->stage_id == _BCM_FIELD_STAGE_EGRESS) ||
   2088              (stage_fc->stage_id == _BCM_FIELD_STAGE_LOOKUP))) {
   2089         part_count = buf[fc->scache_pos];
   2090         fc->scache_pos++;
   2091     } else {
   2092         part_count = 0;
   2093     }
   2094 
   2095     /* Retrieve DVP_tpe */
   2096     if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_6) {
   2097         f_ent_wb_info->dvp_type[0] =  buf[fc->scache_pos];
   2098         fc->scache_pos++;
   2099         part_index = 1;
   2100         if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_18) {
   2101             for (; part_index < part_count; part_index++) {
   2102                 f_ent_wb_info->dvp_type[part_index] =  buf[fc->scache_pos];
   2103                 fc->scache_pos++;
   2104             }
   2105         }
   2106         for (; part_index < _FP_MAX_ENTRY_WIDTH; part_index++) {
   2107             f_ent_wb_info->dvp_type[part_index] = f_ent_wb_info->dvp_type[0];
   2108         }
   2109     }
   2110 
   2111     /* Retrieve SVP_type */
   2112     if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_16) {
   2113         f_ent_wb_info->svp_type[0] =  buf[fc->scache_pos];
   2114         fc->scache_pos++;
   2115         part_index = 1;
   2116         if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_18) {
   2117             for (; part_index < part_count; part_index++) {
   2118                 f_ent_wb_info->svp_type[part_index] =  buf[fc->scache_pos];
   2119                 fc->scache_pos++;
   2120             }
   2121         }
   2122         for (; part_index < _FP_MAX_ENTRY_WIDTH; part_index++) {
   2123             f_ent_wb_info->svp_type[part_index] = f_ent_wb_info->svp_type[0];
   2124         }
   2125     }
   2126 
   2127     /*Retrieve Color Indpendent info*/
   2128     if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_13) {
   2129         f_ent_wb_info->color_independent = (buf[fc->scache_pos] >> 7) & 1;
   2130         fc->scache_pos++;
   2131     }
   2132 
   2133     /* Retrieve Action bitmap */
   2134     if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) {
   2135           if(f_ent_wb_info->action_bmp->w == NULL) {
   2136              return BCM_E_PARAM;
   2137           }
   2138 
   2139           LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2140                 "Read action bitmap[0x%x] @ byte %d.\n"),
   2141                 buf[fc->scache_pos], fc->scache_pos));
   2142 
   2143           f_ent_wb_info->action_bmp->w[0] = buf[fc->scache_pos];
   2144           fc->scache_pos++;
   2145           f_ent_wb_info->action_bmp->w[0] |= buf[fc->scache_pos] << 8;
   2146           fc->scache_pos++;
   2147           f_ent_wb_info->action_bmp->w[0] |= buf[fc->scache_pos] << 16;
   2148           fc->scache_pos++;
   2149           f_ent_wb_info->action_bmp->w[0] |= buf[fc->scache_pos] << 24;
   2150           fc->scache_pos++;
   2151           if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_19) {
   2152              f_ent_wb_info->action_bmp->w[1] = buf[fc->scache_pos];
   2153              fc->scache_pos++;
   2154              f_ent_wb_info->action_bmp->w[1] |= buf[fc->scache_pos] << 8;
   2155              fc->scache_pos++;
   2156              f_ent_wb_info->action_bmp->w[1] |= buf[fc->scache_pos] << 16;
   2157              fc->scache_pos++;
   2158              f_ent_wb_info->action_bmp->w[1] |= buf[fc->scache_pos] << 24;
   2159              fc->scache_pos++;
   2160           }
   2161     
   2162           if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_16) {
   2163              /* Recover IngressGportType Entry Action. */
   2164              f_ent_wb_info->ing_gport_type = buf[fc->scache_pos];
   2165              fc->scache_pos++;
   2166           }
   2167 
   2168           if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_20) {
   2169               uint8 index, max_index = 1;
   2170               if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_21) {
   2171                   max_index = 4;
   2172               }
   2173               for (index = 0 ; index < max_index ; index++) {
   2174                   if (SHR_BITGET(f_ent_wb_info->action_bmp->w, ingress_mirror_actions[index])) {
   2175                       f_ent_wb_info->ingress_mirror[index] = buf[fc->scache_pos];
   2176                       fc->scache_pos++;
   2177                       f_ent_wb_info->ingress_mirror[index] |= buf[fc->scache_pos] << 8;
   2178                       fc->scache_pos++;
   2179                       f_ent_wb_info->ingress_mirror[index] |= buf[fc->scache_pos] << 16;
   2180                       fc->scache_pos++;
   2181                       f_ent_wb_info->ingress_mirror[index] |= buf[fc->scache_pos] << 24;
   2182                       fc->scache_pos++;
   2183                   }
   2184               }
   2185               for (index = 0 ; index < max_index ; index++) {
   2186                   if (SHR_BITGET(f_ent_wb_info->action_bmp->w, egress_mirror_actions[index])) {
   2187                       f_ent_wb_info->egress_mirror[index] = buf[fc->scache_pos];
   2188                       fc->scache_pos++;
   2189                       f_ent_wb_info->egress_mirror[index] |= buf[fc->scache_pos] << 8;
   2190                       fc->scache_pos++;
   2191                       f_ent_wb_info->egress_mirror[index] |= buf[fc->scache_pos] << 16;
   2192                       fc->scache_pos++;
   2193                       f_ent_wb_info->egress_mirror[index] |= buf[fc->scache_pos] << 24;
   2194                       fc->scache_pos++;
   2195                   }
   2196               }
   2197               if ( SHR_BITGET(f_ent_wb_info->action_bmp->w,
   2198                     _bcmFieldActionNoParamFabricQueue)) {
   2199                   (f_ent_wb_info->action_fabricQueue_wb.cosq_gport) =
   2200                         buf[fc->scache_pos];
   2201                   fc->scache_pos++;
   2202                   (f_ent_wb_info->action_fabricQueue_wb.cosq_gport) |=
   2203                         buf[fc->scache_pos] << 8;
   2204                   fc->scache_pos++;
   2205                   (f_ent_wb_info->action_fabricQueue_wb.cosq_gport) |=
   2206                         buf[fc->scache_pos] << 16;
   2207                   fc->scache_pos++;
   2208                   (f_ent_wb_info->action_fabricQueue_wb.cosq_gport) |=
   2209                         buf[fc->scache_pos] << 24;
   2210                   fc->scache_pos++;
   2211               }
   2212           }
   2213     }  
   2214 
   2215     LOG_VERBOSE(BSL_LS_BCM_FP,
   2216                 (BSL_META_U(unit,
   2217                             "Done reading entry @ %d.\n"),
   2218                  fc->scache_pos));
   2219 
   2220     return BCM_E_NONE;
   2221 }
   2222 
   2223 /* Free the slice-specific group information after we're done with it */
   2224 void
   2225 _field_scache_slice_group_free(int unit, _field_control_t *fc, 
   2226                                    int slice_num)
   2227 {
   2228     _field_slice_group_info_t *current = NULL;
   2229     current = fc->group_arr;
   2230     while (current) {
   2231         fc->group_arr = current->next;
   2232         sal_free(current);
   2233         current = fc->group_arr;
   2234     }
   2235     fc->group_arr = NULL;
   2236     return;
   2237 }
   2238 
   2239 #if defined(BCM_FIREBOLT2_SUPPORT)
   2240 STATIC int 
   2241 _field_fb2_group_construct(int unit, _field_hw_qual_info_t *hw_sel, 
   2242                            int intraslice, int paired, _field_control_t *fc,
   2243                            bcm_port_t port, _field_stage_id_t stage_id,
   2244                            int slice_idx)
   2245 {
   2246     int i, j, k, idx, size, selector_match, parts_count = 1, rv = BCM_E_NONE;
   2247     _field_group_t *fg_ptr = fc->groups;
   2248     bcm_field_group_t gid;
   2249     int               priority;
   2250     int               group_flags;
   2251     _bcm_field_qual_info_t *f_qual_arr = NULL;
   2252     _field_stage_t *stage_fc;
   2253     _bcm_field_qual_offset_t *q_offset_arr = NULL;
   2254     uint16 *qid_arr = NULL;
   2255     bcm_field_qset_t qset;
   2256     int action_res_id = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT;
   2257     bcm_pbmp_t group_pbmp ;
   2258 
   2259     bcm_field_qset_t_init(&qset);
   2260 
   2261     /* Get the stage control structure */
   2262     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, stage_id, &stage_fc));
   2263 
   2264     /* Iterate over groups and compare all selectors - IFP */
   2265     fg_ptr = fc->groups;
   2266     while (fg_ptr != NULL) {
   2267         if (intraslice && !(fg_ptr->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) {
   2268             fg_ptr = fg_ptr->next;
   2269             continue;
   2270         }
   2271         if (!intraslice && (fg_ptr->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) {
   2272             fg_ptr = fg_ptr->next;
   2273             continue;
   2274         }
   2275         if (paired && (fg_ptr->flags & _FP_GROUP_SPAN_SINGLE_SLICE)) {
   2276             fg_ptr = fg_ptr->next;
   2277             continue;
   2278         } 
   2279         if (!paired && (fg_ptr->flags & _FP_GROUP_SPAN_DOUBLE_SLICE)) {
   2280             fg_ptr = fg_ptr->next;
   2281             continue;
   2282         }
   2283         /* Check for primary slice numbers - there may be groups with the same
   2284            QSET but residing in different slices */
   2285         if (slice_idx != fg_ptr->slices[0].slice_number) {
   2286             fg_ptr = fg_ptr->next;
   2287             continue;
   2288         }
   2289         /* Compare primary slice selectors */
   2290         if ((fg_ptr->sel_codes[0].fpf1 != hw_sel->pri_slice[0].fpf1) ||
   2291             (fg_ptr->sel_codes[0].fpf2 != hw_sel->pri_slice[0].fpf2) ||
   2292             (fg_ptr->sel_codes[0].fpf3 != hw_sel->pri_slice[0].fpf3) ||
   2293             (fg_ptr->sel_codes[0].fpf4 != hw_sel->pri_slice[0].fpf4)) {
   2294             fg_ptr = fg_ptr->next;
   2295             continue;
   2296         }
   2297         if (intraslice && (fg_ptr->sel_codes[1].fpf2 != 
   2298             hw_sel->pri_slice[1].fpf2)) {
   2299             fg_ptr = fg_ptr->next;
   2300             continue;
   2301         }
   2302         /* Compare secondary slice if paired */
   2303         if (paired) {
   2304             if ((fg_ptr->sel_codes[2].fpf1 != hw_sel->sec_slice[0].fpf1) ||
   2305                 (fg_ptr->sel_codes[2].fpf2 != hw_sel->sec_slice[0].fpf2) ||
   2306                 (fg_ptr->sel_codes[2].fpf3 != hw_sel->sec_slice[0].fpf3) ||
   2307                 (fg_ptr->sel_codes[2].fpf4 != hw_sel->sec_slice[0].fpf4)) {
   2308                 fg_ptr = fg_ptr->next;
   2309                 continue;
   2310             }
   2311             if (intraslice && (fg_ptr->sel_codes[3].fpf2 != 
   2312                 hw_sel->sec_slice[1].fpf2)) {
   2313                 fg_ptr = fg_ptr->next;
   2314                 continue;
   2315             }
   2316         }
   2317 
   2318         /* Found a match - add port to group pbmp */
   2319         BCM_PBMP_PORT_ADD(fg_ptr->pbmp, port);
   2320         BCM_PBMP_OR(fg_ptr->slices[0].pbmp, fg_ptr->pbmp);
   2321         if (paired) {
   2322             BCM_PBMP_OR(fg_ptr->slices[1].pbmp, fg_ptr->pbmp);
   2323         }
   2324 
   2325         group_flags = 0;
   2326         if (fc->l2warm) {
   2327             /* Get stored group ID and QSET for Level 2 */
   2328             BCM_IF_ERROR_RETURN
   2329                 (_field_group_info_retrieve(unit, port, _FP_DEF_INST, &gid,
   2330                                             &priority, &action_res_id, &group_pbmp, NULL,
   2331                                             &group_flags, &qset, fc));
   2332             if (gid != -1) {
   2333                 sal_memcpy(&fg_ptr->qset, &qset, sizeof(bcm_field_qset_t));
   2334                 fg_ptr->gid      = gid;
   2335                 fg_ptr->priority = priority;
   2336                 fg_ptr->action_res_id = action_res_id;
   2337                 if (group_flags & _FP_GROUP_SELECT_AUTO_EXPANSION) {
   2338                     fg_ptr->flags = fg_ptr->flags | 
   2339                                          _FP_GROUP_SELECT_AUTO_EXPANSION;
   2340                 }
   2341 
   2342             }
   2343         }
   2344         break;
   2345     }
   2346     if (fg_ptr == NULL) {
   2347         /* No match - create a new group and populate the group structure */
   2348         _FP_XGS3_ALLOC(fg_ptr, sizeof(_field_group_t), "field group");
   2349         if (NULL == fg_ptr) {
   2350             return BCM_E_MEMORY;
   2351         }
   2352 
   2353         /* Initialize action res id and VMAP group to default */
   2354         action_res_id = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT;
   2355         for (idx = 0; idx < _FP_PAIR_MAX; idx++) {
   2356             fg_ptr->vmap_group[idx] = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT;
   2357         }
   2358 
   2359         group_flags = 0;
   2360         if (fc->l2warm) {
   2361             /* Get stored group ID and QSET for Level 2 */
   2362             rv = _field_group_info_retrieve(unit, port, _FP_DEF_INST, &gid,
   2363                                             &priority, &action_res_id, &group_pbmp, NULL,
   2364                                             &group_flags, &qset, fc);
   2365             if (gid != -1) {
   2366                 sal_memcpy(&fg_ptr->qset, &qset, sizeof(bcm_field_qset_t));
   2367             }
   2368             else {
   2369                 sal_free(fg_ptr);
   2370                 return rv;
   2371             }
   2372         } else { 
   2373             /* Generate group ID (a ++ operation) for Level 1 */
   2374             rv = _bcm_field_group_id_generate(unit, &gid);
   2375             priority = slice_idx;
   2376         }
   2377         if (BCM_FAILURE(rv)) {
   2378             sal_free(fg_ptr);
   2379             return rv;
   2380         }
   2381         fg_ptr->gid = gid;
   2382         fg_ptr->priority = priority;
   2383         fg_ptr->action_res_id = action_res_id;
   2384         if (group_flags & _FP_GROUP_SELECT_AUTO_EXPANSION) {
   2385             fg_ptr->flags = fg_ptr->flags | _FP_GROUP_SELECT_AUTO_EXPANSION;
   2386         }
   2387         fg_ptr->stage_id = stage_id;
   2388         fg_ptr->sel_codes[0].fpf1 = hw_sel->pri_slice[0].fpf1;
   2389         fg_ptr->sel_codes[0].fpf2 = hw_sel->pri_slice[0].fpf2;
   2390         fg_ptr->sel_codes[0].fpf3 = hw_sel->pri_slice[0].fpf3;
   2391         fg_ptr->sel_codes[0].fpf4 = hw_sel->pri_slice[0].fpf4;
   2392         fg_ptr->sel_codes[0].inner_vlan_overlay = 
   2393             hw_sel->pri_slice[0].inner_vlan_overlay;
   2394         if (port != -1) {
   2395             BCM_PBMP_PORT_ADD(fg_ptr->pbmp, port);
   2396         } else {
   2397             SOC_PBMP_ASSIGN(fg_ptr->pbmp, PBMP_ALL(unit));
   2398         }
   2399         if (intraslice) {
   2400             fg_ptr->flags |= _FP_GROUP_INTRASLICE_DOUBLEWIDE;
   2401             fg_ptr->sel_codes[1].fpf2 = hw_sel->pri_slice[1].fpf2;
   2402             fg_ptr->sel_codes[1].fpf4 = hw_sel->pri_slice[1].fpf4;
   2403             fg_ptr->sel_codes[1].intraslice = 1;
   2404             fg_ptr->sel_codes[1].inner_vlan_overlay = 
   2405                 hw_sel->pri_slice[1].inner_vlan_overlay;
   2406         }
   2407         if (paired) {
   2408             parts_count = 2;
   2409             fg_ptr->flags |= _FP_GROUP_SPAN_DOUBLE_SLICE;
   2410             fg_ptr->sel_codes[2].fpf1 = hw_sel->sec_slice[0].fpf1;
   2411             fg_ptr->sel_codes[2].fpf2 = hw_sel->sec_slice[0].fpf2;
   2412             fg_ptr->sel_codes[2].fpf3 = hw_sel->sec_slice[0].fpf3;
   2413             fg_ptr->sel_codes[2].fpf4 = hw_sel->sec_slice[0].fpf4;
   2414             fg_ptr->sel_codes[2].inner_vlan_overlay = 
   2415                 hw_sel->sec_slice[0].inner_vlan_overlay;
   2416             if (intraslice) {
   2417                 parts_count = 4;
   2418                 fg_ptr->sel_codes[3].fpf2 = hw_sel->sec_slice[1].fpf2;
   2419                 fg_ptr->sel_codes[3].fpf4 = hw_sel->sec_slice[1].fpf4;
   2420                 fg_ptr->sel_codes[3].intraslice = 1;
   2421                 fg_ptr->sel_codes[3].inner_vlan_overlay = 
   2422                     hw_sel->sec_slice[1].inner_vlan_overlay;
   2423             }
   2424         } else {
   2425             fg_ptr->flags |= _FP_GROUP_SPAN_SINGLE_SLICE;
   2426         }
   2427         /* Determine the QSET based on selector values */
   2428         for (i = 0; i < parts_count; i++) {
   2429             for (idx = 0; idx < _bcmFieldQualifyCount; idx++) {
   2430                 f_qual_arr = stage_fc->f_qual_arr[idx];
   2431                 if (f_qual_arr == NULL) {
   2432                     continue; /* Qualifier does not exist in this stage */
   2433                 }
   2434                 if (fc->l2warm && !BCM_FIELD_QSET_TEST(fg_ptr->qset, idx)) {
   2435                     continue; /* Qualifier not present in the group */
   2436                 }
   2437                 /* Go over the API level qualifier's configuration info */
   2438                 for (j = 0; j < f_qual_arr->conf_sz; j++) {
   2439                     selector_match = 0;
   2440                     /* Check if it matches F1's value */
   2441                     if ((f_qual_arr->conf_arr[j].selector.pri_sel == 
   2442                          _bcmFieldSliceSelFpf1) && 
   2443                         (f_qual_arr->conf_arr[j].selector.pri_sel_val == 
   2444                          fg_ptr->sel_codes[i].fpf1)) {
   2445                         /* Qualifier found - add to group's qset and group
   2446                            qualifier info */
   2447                         /* Tentatively add to fg->qual_arr[i] */
   2448                         if (stage_id == _BCM_FIELD_STAGE_INGRESS) {
   2449                             if ((fg_ptr->sel_codes[i].fpf1 != 3) && 
   2450                                 (fg_ptr->sel_codes[i].fpf1 != 6)) {
   2451                                 selector_match = 1; 
   2452                             } else {
   2453                                 /* Deal with inner_vlan_overlay */
   2454                                 if ((idx == bcmFieldQualifyInnerVlan) || 
   2455                                     (idx == bcmFieldQualifyInnerVlanId) ||
   2456                                     (idx == bcmFieldQualifyInnerVlanPri) ||
   2457                                     (idx == bcmFieldQualifyInnerVlanCfi)) {
   2458                                     if (fg_ptr->sel_codes[i].inner_vlan_overlay
   2459                                         == 0) {
   2460                                         selector_match = 1; 
   2461                                     }
   2462                                 } else if ((idx == bcmFieldQualifyVrf) ||
   2463                                      (idx == bcmFieldQualifyDstClassField) ||
   2464                                      (idx == bcmFieldQualifySrcClassL2)) {
   2465                                     if (fg_ptr->sel_codes[i].inner_vlan_overlay
   2466                                         == 1) {
   2467                                         selector_match = 1; 
   2468                                     }
   2469                                 } else {
   2470                                     selector_match = 1; 
   2471                                 }
   2472                             }
   2473                         } else {
   2474                             selector_match = 1; 
   2475                         }
   2476                     }
   2477                     /* Check if it matches F2's value */
   2478                     if ((f_qual_arr->conf_arr[j].selector.pri_sel == 
   2479                          _bcmFieldSliceSelFpf2) && 
   2480                         (f_qual_arr->conf_arr[j].selector.pri_sel_val == 
   2481                          fg_ptr->sel_codes[i].fpf2)) {
   2482                         /* Qualifier found - add to group's qset and group
   2483                            qualifier info */
   2484                         /* Tentatively add to fg->qual_arr[i] */
   2485                         selector_match = 1; 
   2486                     }
   2487                     /* Check if it matches F3's value */
   2488                     if ((f_qual_arr->conf_arr[j].selector.pri_sel == 
   2489                          _bcmFieldSliceSelFpf3) && 
   2490                         (f_qual_arr->conf_arr[j].selector.pri_sel_val == 
   2491                          fg_ptr->sel_codes[i].fpf3)) {
   2492                         /* Qualifier found - add to group's qset and group
   2493                            qualifier info */
   2494                         /* Tentatively add to fg->qual_arr[i] */
   2495                         selector_match = 1; 
   2496                     }
   2497                     /* Check if it matches F4's value */
   2498                     if ((f_qual_arr->conf_arr[j].selector.pri_sel == 
   2499                          _bcmFieldSliceSelFpf4) && 
   2500                         (f_qual_arr->conf_arr[j].selector.pri_sel_val == 
   2501                          fg_ptr->sel_codes[i].fpf4)) {
   2502                         /* Qualifier found - add to group's qset and group
   2503                            qualifier info */
   2504                         /* Tentatively add to fg->qual_arr[i] */
   2505                         selector_match = 1; 
   2506                     }
   2507                     if (selector_match) {
   2508                         BCM_FIELD_QSET_ADD(fg_ptr->qset, idx);
   2509                         /* Allocate memory for this qualfier and its
   2510                            associated offset information if not already added 
   2511                            to fg->qual_arr[i] */
   2512                         /* May change later depending on the mask */
   2513                         for (k = 0; k < fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size; k++) {
   2514                             if (fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr[k] == idx) {
   2515                                 break; /* Qualifier already added */
   2516                             }
   2517                         }
   2518                         if (k == fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size) {
   2519                             size = fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size + 1;
   2520                             qid_arr = NULL;
   2521                             _FP_XGS3_ALLOC(qid_arr, size * sizeof (uint16), 
   2522                                            "Group qual id");
   2523                             if (NULL == qid_arr) {
   2524                                 sal_free (fg_ptr);
   2525                                 return (BCM_E_MEMORY);
   2526                             }              
   2527                             q_offset_arr = NULL;              
   2528                             _FP_XGS3_ALLOC(q_offset_arr, size * 
   2529                                            sizeof (_bcm_field_qual_offset_t), 
   2530                                            "Group qual offset");
   2531                             if (NULL == q_offset_arr) {
   2532                                 sal_free (fg_ptr);
   2533                                 sal_free (qid_arr);
   2534                                 return (BCM_E_MEMORY);
   2535                             }
   2536                             if (size) {
   2537                                 sal_memcpy(qid_arr, fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr,
   2538                                            fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size * 
   2539                                            sizeof (uint16));
   2540                                 sal_memcpy(q_offset_arr, 
   2541                                            fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr, 
   2542                                            fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size * 
   2543                                            sizeof (_bcm_field_qual_offset_t));
   2544                                 if (fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size) {
   2545                                     sal_free(fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr);
   2546                                     sal_free(fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr);
   2547                                 }
   2548                             }
   2549                             fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr = qid_arr;
   2550                             fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr = q_offset_arr;
   2551                             fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr[size - 1] = idx;
   2552                             fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr[size - 1].field = 
   2553                                 f_qual_arr->conf_arr[j].offset.field;
   2554 
   2555                             sal_memcpy(&fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr[size - 1],
   2556                                 &f_qual_arr->conf_arr[j].offset, sizeof(f_qual_arr->conf_arr[j].offset));
   2557 
   2558                             fg_ptr->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size = size;
   2559 
   2560                             _field_qset_udf_bmap_reinit(unit,
   2561                                                         stage_fc,
   2562                                                         &fg_ptr->qset,
   2563                                                         idx
   2564                                                         );
   2565 
   2566                             break; /* Just added the qualifier */
   2567                         }
   2568                     }
   2569                 }
   2570             }
   2571         }
   2572         /* Associate slice(s) to group */
   2573         if (fg_ptr->slices == NULL) {
   2574             fg_ptr->slices = stage_fc->slices[_FP_DEF_INST] + slice_idx;
   2575             if (intraslice) {
   2576                 fg_ptr->slices->group_flags |= _FP_GROUP_INTRASLICE_DOUBLEWIDE;
   2577                 if (paired) {
   2578                     fg_ptr->slices[1].group_flags |= 
   2579                                                _FP_GROUP_INTRASLICE_DOUBLEWIDE;
   2580                 }
   2581             }
   2582         }
   2583 
   2584         BCM_PBMP_OR(fg_ptr->slices[0].pbmp, fg_ptr->pbmp);
   2585         if (paired) {
   2586             BCM_PBMP_OR(fg_ptr->slices[1].pbmp, fg_ptr->pbmp);
   2587         }
   2588 
   2589         /* Initialize group default ASET list. */
   2590         rv = _field_group_default_aset_set(unit, fg_ptr);
   2591         if (BCM_FAILURE(rv)) {
   2592             return (rv);
   2593         }
   2594 
   2595         if (fc->l2warm
   2596                 && ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15)) {
   2597             if (group_flags & _FP_GROUP_LOOKUP_ENABLED) {
   2598                 fg_ptr->flags = fg_ptr->flags | _FP_GROUP_LOOKUP_ENABLED;
   2599             }
   2600             if (group_flags & _FP_GROUP_WLAN) {
   2601                 fg_ptr->flags = fg_ptr->flags | _FP_GROUP_WLAN;
   2602             }
   2603         } else {
   2604             fg_ptr->flags |= _FP_GROUP_LOOKUP_ENABLED;
   2605         }
   2606 
   2607         fg_ptr->next = fc->groups;
   2608         fc->groups = fg_ptr;
   2609     }
   2610     return rv;
   2611 }
   2612 
   2613 int
   2614 _field_fb2_stage_ingress_reinit(int unit, _field_control_t *fc, 
   2615                                 _field_stage_t *stage_fc)
   2616 {
   2617     int idx, idx1, slice_idx, vslice_idx,index_min, index_max, ratio, rv = BCM_E_NONE;
   2618     int entries_per_slice, group_found, mem_sz, parts_count, qual_idx;
   2619     int i, j, k, pri_tcam_idx, part_index, slice_number, expanded[16], slice_master_idx[16];
   2620     int prev_prio, multigroup, max, master_slice;
   2621     char *fp_tcam_buf = NULL; /* Buffer to read the FP_TCAM table */
   2622     char *fp_pfs_buf = NULL; /* Buffer to read the FP_PORT_FIELD_SEL table */
   2623     char *fp_policy_buf = NULL; /* Buffer to read the FP_POLICY table */
   2624     uint32 pbm, rval, paired, intraslice, dbl_wide_key, dbl_wide_key_sec;
   2625     uint32 f4_sel_val, qualified, inner_vlan_overlay;
   2626     uint32 *tcam_entry_buf, temp;
   2627     soc_field_t fld;
   2628     bcm_port_t port;
   2629     fp_port_field_sel_entry_t *pfs_entry;
   2630     fp_tcam_entry_t *tcam_entry;
   2631     fp_policy_table_entry_t *policy_entry;
   2632     _field_hw_qual_info_t hw_sels;
   2633     _field_slice_t *fs;
   2634     _field_group_t *fg = NULL, *group = NULL;
   2635     _field_entry_t *f_ent = NULL;
   2636     bcm_pbmp_t entry_pbmp, temp_pbmp;
   2637     _bcm_field_qual_info_t *f_qual_arr = NULL;
   2638     _field_sel_t *sel_ptr;
   2639     uint8 *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0];
   2640     uint8 *buf1 = fc->scache_ptr[_FIELD_SCACHE_PART_1];
   2641     uint8 old_physical_slice, slice_num;
   2642     uint32 entry_flags;
   2643     _field_slice_t *fs_temp = NULL;
   2644     _field_action_bmp_t action_bmp;
   2645     _field_entry_wb_info_t f_ent_wb_info;
   2646 
   2647     soc_field_t en_flds[16] = 
   2648                      {FP_SLICE_ENABLE_SLICE_0f, FP_SLICE_ENABLE_SLICE_1f,
   2649                       FP_SLICE_ENABLE_SLICE_2f, FP_SLICE_ENABLE_SLICE_3f,
   2650                       FP_SLICE_ENABLE_SLICE_4f, FP_SLICE_ENABLE_SLICE_5f,
   2651                       FP_SLICE_ENABLE_SLICE_6f, FP_SLICE_ENABLE_SLICE_7f,
   2652                       FP_SLICE_ENABLE_SLICE_8f, FP_SLICE_ENABLE_SLICE_9f,
   2653                       FP_SLICE_ENABLE_SLICE_10f, FP_SLICE_ENABLE_SLICE_11f,
   2654                       FP_SLICE_ENABLE_SLICE_12f, FP_SLICE_ENABLE_SLICE_13f,
   2655                       FP_SLICE_ENABLE_SLICE_14f, FP_SLICE_ENABLE_SLICE_15f};
   2656     soc_field_t lk_en_flds[16] = 
   2657                      {FP_LOOKUP_ENABLE_SLICE_0f, FP_LOOKUP_ENABLE_SLICE_1f,
   2658                       FP_LOOKUP_ENABLE_SLICE_2f, FP_LOOKUP_ENABLE_SLICE_3f,
   2659                       FP_LOOKUP_ENABLE_SLICE_4f, FP_LOOKUP_ENABLE_SLICE_5f,
   2660                       FP_LOOKUP_ENABLE_SLICE_6f, FP_LOOKUP_ENABLE_SLICE_7f,
   2661                       FP_LOOKUP_ENABLE_SLICE_8f, FP_LOOKUP_ENABLE_SLICE_9f,
   2662                       FP_LOOKUP_ENABLE_SLICE_10f, FP_LOOKUP_ENABLE_SLICE_11f,
   2663                       FP_LOOKUP_ENABLE_SLICE_12f, FP_LOOKUP_ENABLE_SLICE_13f,
   2664                       FP_LOOKUP_ENABLE_SLICE_14f, FP_LOOKUP_ENABLE_SLICE_15f};
   2665 
   2666     
   2667     fc->scache_pos = 0;
   2668     fc->scache_pos1 = 0;
   2669 
   2670     /* Reset Action bitmap to NULL. */
   2671     action_bmp.w = NULL;
   2672 
   2673     if (fc->l2warm) {
   2674         if ((fc->wb_recovered_version) > (fc->wb_current_version)) {
   2675             /* Notify the application with an event */
   2676             /* The application will then need to reconcile the 
   2677                version differences using the documented behavioral
   2678                differences on per module (handle) basis */
   2679             SOC_IF_ERROR_RETURN
   2680                 (soc_event_generate(unit, SOC_SWITCH_EVENT_WARM_BOOT_DOWNGRADE, 
   2681                                     BCM_MODULE_FIELD, (fc->wb_recovered_version), 
   2682                                     (fc->wb_current_version)));        
   2683         }
   2684 
   2685         fc->scache_pos += SOC_WB_SCACHE_CONTROL_SIZE;
   2686 
   2687         if(NULL != fc->scache_ptr[_FIELD_SCACHE_PART_1]) {
   2688             if ((fc->wb_recovered_version) > (fc->wb_current_version)) {
   2689                 /* Notify the application with an event */
   2690                 /* The application will then need to reconcile the
   2691                    version differences using the documented behavioral
   2692                    differences on per module (handle) basis */
   2693                 SOC_IF_ERROR_RETURN
   2694                     (soc_event_generate(unit,
   2695                                      SOC_SWITCH_EVENT_WARM_BOOT_DOWNGRADE,
   2696                                      BCM_MODULE_FIELD, (fc->wb_recovered_version),
   2697                                      (fc->wb_current_version)));
   2698             }
   2699 
   2700             fc->scache_pos1 += SOC_WB_SCACHE_CONTROL_SIZE;
   2701         }
   2702 
   2703 
   2704     }
   2705 
   2706     SOC_PBMP_CLEAR(entry_pbmp);
   2707     sal_memset(expanded, 0, 16 * sizeof(int));
   2708     sal_memset(slice_master_idx, 0, 16 * sizeof(int));
   2709 
   2710     if (fc->l2warm) {
   2711         rv = _field_scache_stage_hdr_chk(fc, _FIELD_IFP_DATA_START);
   2712         if (BCM_FAILURE(rv)) {
   2713             return (rv);
   2714         }
   2715     }
   2716 
   2717     /* DMA various tables */
   2718     fp_tcam_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, FP_TCAMm), 
   2719                                 "FP TCAM buffer");
   2720     if (NULL == fp_tcam_buf) {
   2721         return BCM_E_MEMORY;
   2722     }
   2723     index_min = soc_mem_index_min(unit, FP_TCAMm);
   2724     index_max = soc_mem_index_max(unit, FP_TCAMm);
   2725     if ((rv = soc_mem_read_range(unit, FP_TCAMm, MEM_BLOCK_ALL,
   2726                                  index_min, index_max, fp_tcam_buf)) < 0 ) {
   2727         goto cleanup;
   2728     }
   2729     fp_pfs_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, 
   2730                                FP_PORT_FIELD_SELm), 
   2731                                "FP PORT_FIELD_SEL buffer");
   2732     if (NULL == fp_pfs_buf) {
   2733         rv = BCM_E_MEMORY;
   2734         goto cleanup;
   2735     }
   2736     index_min = soc_mem_index_min(unit, FP_PORT_FIELD_SELm);
   2737     index_max = soc_mem_index_max(unit, FP_PORT_FIELD_SELm);
   2738     if ((rv = soc_mem_read_range(unit, FP_PORT_FIELD_SELm, MEM_BLOCK_ALL,
   2739                                  index_min, index_max, fp_pfs_buf)) < 0 ) {
   2740         goto cleanup;
   2741     }
   2742     fp_policy_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES
   2743                                   (unit, FP_POLICY_TABLEm), 
   2744                                   "FP POLICY TABLE buffer");
   2745     if (NULL == fp_policy_buf) {
   2746         rv = BCM_E_MEMORY;
   2747         goto cleanup;
   2748     }
   2749     index_min = soc_mem_index_min(unit, FP_POLICY_TABLEm);
   2750     index_max = soc_mem_index_max(unit, FP_POLICY_TABLEm);
   2751     if ((rv = soc_mem_read_range(unit, FP_POLICY_TABLEm, MEM_BLOCK_ALL,
   2752                                index_min, index_max, fp_policy_buf)) < 0 ) {
   2753         goto cleanup;
   2754     }
   2755 
   2756     entries_per_slice = 256;
   2757 
   2758     if ((rv = READ_FP_F4_SELECTr(unit, &f4_sel_val)) < 0) {
   2759         goto cleanup;
   2760     }
   2761 
   2762     /* Recover range checkers */
   2763     rv = _field_range_check_reinit(unit, stage_fc, fc);
   2764     if (BCM_FAILURE(rv)) {
   2765         goto cleanup;
   2766     }
   2767 
   2768     /* Recover data qualifiers */
   2769     rv = _field_data_qual_recover(unit, fc, stage_fc);
   2770     if (BCM_FAILURE(rv)) {
   2771         goto cleanup;
   2772     }
   2773 
   2774     /* Get per-device selectors */
   2775     if ((rv = READ_ING_MISC_CONFIG2r(unit, &rval)) < 0) {
   2776         goto cleanup;
   2777     }
   2778     inner_vlan_overlay = soc_reg_field_get(unit, ING_MISC_CONFIG2r, rval, 
   2779                                            FP_INNER_VLAN_OVERLAY_ENABLEf);
   2780 
   2781     /* Get slice expansion status and virtual map */
   2782     if ((rv = _field_slice_expanded_status_get(unit, fc, stage_fc,
   2783                                                expanded, slice_master_idx)) < 0) {
   2784         goto cleanup;
   2785     }
   2786 
   2787     /* Iterate over the slices */
   2788     if ((rv = READ_FP_SLICE_ENABLEr(unit, &rval)) < 0) {
   2789         goto cleanup;
   2790     }
   2791     for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) {
   2792         /* Ignore disabled slice */
   2793         if ((soc_reg_field_get
   2794              (unit, FP_SLICE_ENABLEr, rval, en_flds[slice_idx]) == 0) || 
   2795             (soc_reg_field_get
   2796              (unit, FP_SLICE_ENABLEr, rval, lk_en_flds[slice_idx]) == 0)) {
   2797             continue;
   2798         }
   2799         /* Ignore secondary slice in paired mode */
   2800         pfs_entry = soc_mem_table_idx_to_pointer(unit, FP_PORT_FIELD_SELm, 
   2801                                                 fp_port_field_sel_entry_t *, 
   2802                                                 fp_pfs_buf, 0);
   2803         fld = _fb2_slice_pairing_field[slice_idx / 2];
   2804         paired = soc_FP_PORT_FIELD_SELm_field32_get(unit, 
   2805                                                     pfs_entry, fld);
   2806         fld = _fb2_slice_wide_mode_field[slice_idx];
   2807         intraslice = soc_FP_PORT_FIELD_SELm_field32_get(unit, 
   2808                                                         pfs_entry, fld);
   2809         if (paired && (slice_idx % 2)) {
   2810             continue;
   2811         }
   2812 
   2813         /* Don't need to read selectors for expanded slice */
   2814         if (expanded[slice_idx]) {
   2815             continue; 
   2816         }
   2817 
   2818         /* Skip if slice has no valid groups and entries */
   2819         fs = stage_fc->slices[_FP_DEF_INST] + slice_idx;
   2820         for (idx = 0; idx < fs->entry_count; idx++) {
   2821             tcam_entry = soc_mem_table_idx_to_pointer(unit, FP_TCAMm, 
   2822                                                       fp_tcam_entry_t *, 
   2823                                                       fp_tcam_buf, idx + 
   2824                                                       entries_per_slice * 
   2825                                                       slice_idx);
   2826             if (soc_FP_TCAMm_field32_get(unit, tcam_entry, VALIDf) != 0) {
   2827                 break;
   2828             }
   2829         }
   2830         if ((idx == fs->entry_count) && !fc->l2warm) {
   2831             continue;
   2832         }
   2833 
   2834         /* If Level 2, retrieve the GIDs in this slice */
   2835         if (fc->l2warm) {
   2836             rv = _field_scache_slice_group_recover(unit, fc, slice_idx, 
   2837                                                        &multigroup);
   2838             if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   2839                 fc->l2warm = 0;
   2840                 goto cleanup;
   2841             }
   2842             if (rv == BCM_E_NOT_FOUND) {
   2843                 rv = BCM_E_NONE;
   2844                 continue;
   2845             }
   2846         }
   2847 
   2848         /* Iterate over FP_PORT_FIELD_SEL for all ports and this slice 
   2849          * to identify bins for selectors (also groups for level 1) */
   2850         PBMP_ALL_ITER(unit, port) {
   2851             sal_memset(&hw_sels, 0, sizeof(_field_hw_qual_info_t));
   2852             pfs_entry = soc_mem_table_idx_to_pointer
   2853                             (unit, FP_PORT_FIELD_SELm, 
   2854                              fp_port_field_sel_entry_t *, fp_pfs_buf, port);
   2855             /* Get primary slice's selectors */
   2856             hw_sels.pri_slice[0].fpf1 = soc_FP_PORT_FIELD_SELm_field32_get(unit,  
   2857                                      pfs_entry, _fb_field_tbl[slice_idx][0]);
   2858             hw_sels.pri_slice[0].fpf2 = soc_FP_PORT_FIELD_SELm_field32_get(unit,  
   2859                                      pfs_entry, _fb_field_tbl[slice_idx][1]);
   2860             hw_sels.pri_slice[0].fpf3 = soc_FP_PORT_FIELD_SELm_field32_get(unit,  
   2861                                      pfs_entry, _fb_field_tbl[slice_idx][2]);
   2862             hw_sels.pri_slice[0].fpf4 = soc_reg_field_get(unit, 
   2863                                             FP_F4_SELECTr, f4_sel_val, 
   2864                                             _fb_ing_f4_reg[slice_idx]);
   2865             hw_sels.pri_slice[0].inner_vlan_overlay = inner_vlan_overlay;
   2866             /* If intraslice, get double-wide key - only 2 options */
   2867             if (intraslice) {
   2868                 dbl_wide_key = soc_FP_PORT_FIELD_SELm_field32_get(unit, 
   2869                             pfs_entry, _fb2_ifp_double_wide_key[slice_idx]);
   2870                 hw_sels.pri_slice[1].intraslice = 1;
   2871                 hw_sels.pri_slice[1].fpf2 = dbl_wide_key;
   2872                 hw_sels.pri_slice[1].fpf4 = dbl_wide_key;
   2873                 hw_sels.pri_slice[1].inner_vlan_overlay = inner_vlan_overlay;
   2874             }
   2875             /* If paired, get secondary slice's selectors */
   2876             if (paired) {
   2877                 hw_sels.sec_slice[0].fpf1 = soc_FP_PORT_FIELD_SELm_field32_get
   2878                                          (unit, pfs_entry, 
   2879                                           _fb_field_tbl[slice_idx + 1][0]);
   2880                 hw_sels.sec_slice[0].fpf2 = soc_FP_PORT_FIELD_SELm_field32_get
   2881                                          (unit, pfs_entry, 
   2882                                           _fb_field_tbl[slice_idx + 1][1]);
   2883                 hw_sels.sec_slice[0].fpf3 = soc_FP_PORT_FIELD_SELm_field32_get
   2884                                          (unit, pfs_entry, 
   2885                                           _fb_field_tbl[slice_idx + 1][2]);                                  hw_sels.sec_slice[0].fpf4 = soc_reg_field_get(unit, 
   2886                                              FP_F4_SELECTr, f4_sel_val, 
   2887                                              _fb_ing_f4_reg[slice_idx + 1]);
   2888                 hw_sels.sec_slice[0].inner_vlan_overlay = inner_vlan_overlay;
   2889                 if (intraslice) {
   2890                     dbl_wide_key_sec = soc_FP_PORT_FIELD_SELm_field32_get
   2891                      (unit, pfs_entry, _fb2_ifp_double_wide_key[slice_idx]);
   2892                     hw_sels.sec_slice[1].intraslice = 1;
   2893                     hw_sels.sec_slice[1].fpf2 = dbl_wide_key_sec;
   2894                     hw_sels.sec_slice[1].fpf4 = dbl_wide_key_sec;
   2895                     hw_sels.sec_slice[1].inner_vlan_overlay = inner_vlan_overlay;
   2896                 }
   2897             }
   2898             /* Create a group based on HW qualifiers (or find existing) */
   2899             rv = _field_fb2_group_construct(unit, &hw_sels, intraslice, 
   2900                                             paired, fc, port, 
   2901                                             _BCM_FIELD_STAGE_INGRESS,
   2902                                             slice_idx);
   2903             if (BCM_FAILURE(rv)) {
   2904                 goto cleanup;
   2905             }
   2906         }
   2907         /* Now go over the entries in this slice */
   2908         fs = stage_fc->slices[_FP_DEF_INST] + slice_idx;
   2909         if (fs->group_flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
   2910             ratio = 2;
   2911             fs->free_count >>= 1;
   2912         } else {
   2913             ratio = 1;
   2914         }
   2915         prev_prio = -1;
   2916         for (idx = 0; idx < fs->entry_count / ratio; idx++) {
   2917             group_found = 0;
   2918             tcam_entry = soc_mem_table_idx_to_pointer(unit, FP_TCAMm, 
   2919                                                       fp_tcam_entry_t *, 
   2920                                                       fp_tcam_buf, idx + 
   2921                                                       entries_per_slice * 
   2922                                                       slice_idx);
   2923             if (soc_FP_TCAMm_field32_get(unit, tcam_entry, VALIDf) == 0) {
   2924                 continue;
   2925             }
   2926             /* Check which ports are applicable to this entry */
   2927             SOC_PBMP_CLEAR(entry_pbmp);
   2928             if ((soc_FP_TCAMm_field32_get(unit, tcam_entry, IPBM_SELf)) && 
   2929                 (soc_FP_TCAMm_field32_get(unit, tcam_entry, 
   2930                                           IPBM_SEL_MASKf))) {
   2931                 pbm = soc_FP_TCAMm_field32_get(unit, tcam_entry, F1f) & 
   2932                       soc_FP_TCAMm_field32_get(unit, tcam_entry, F1_MASKf);
   2933                 SOC_PBMP_WORD_SET(entry_pbmp, 0, pbm);
   2934             } else if ((f4_sel_val == 0) && 
   2935                        soc_FP_TCAMm_field32_get(unit, tcam_entry, F4_MASKf)) {
   2936                 pbm = soc_FP_TCAMm_field32_get(unit, tcam_entry, F4f) & 
   2937                       soc_FP_TCAMm_field32_get(unit, tcam_entry, F4_MASKf);
   2938                 SOC_PBMP_PORT_ADD(entry_pbmp, pbm);
   2939             } else {
   2940                 SOC_PBMP_ASSIGN(entry_pbmp, PBMP_ALL(unit));
   2941             }
   2942             /* Search groups to find match */
   2943             fg = fc->groups;
   2944             while (fg != NULL) {
   2945                 /* Check if group is in this slice */
   2946                 fs = &fg->slices[0];
   2947                 if (fs->slice_number != slice_idx) {
   2948                     fg = fg->next;
   2949                     continue;
   2950                 }
   2951                 /* Check if entry_pbmp is a subset of group pbmp */
   2952                 SOC_PBMP_ASSIGN(temp_pbmp, fg->pbmp);
   2953                 SOC_PBMP_OR(temp_pbmp, PBMP_LB(unit));
   2954                 SOC_PBMP_AND(temp_pbmp, entry_pbmp);
   2955                 if (SOC_PBMP_EQ(temp_pbmp, entry_pbmp)) {
   2956                     group_found = 1;
   2957                     break;
   2958                 }
   2959                 fg = fg->next;
   2960             }
   2961             if (!group_found) {
   2962                 return BCM_E_INTERNAL; /* Should never happen */
   2963             }
   2964             /* Allocate memory for the entry */
   2965             rv = _bcm_field_entry_tcam_parts_count(unit, fg->stage_id,
   2966                                                    fg->flags, &parts_count);
   2967             if (BCM_FAILURE(rv)) {
   2968                 goto cleanup;
   2969             }
   2970             mem_sz = parts_count * sizeof (_field_entry_t);
   2971             _FP_XGS3_ALLOC(f_ent, mem_sz, "field entry");
   2972             if (f_ent == NULL) {
   2973                 rv = BCM_E_MEMORY;
   2974                 goto cleanup;
   2975             }
   2976             for (idx1 = 0; idx1 < _FP_POLICER_LEVEL_COUNT; idx1++) {
   2977                  f_ent->policer[idx1].pid = _FP_INVALID_INDEX;
   2978             }
   2979 
   2980             sal_memset(&f_ent_wb_info, 0, sizeof(_field_entry_wb_info_t));
   2981             f_ent_wb_info.sid = f_ent_wb_info.pid = -1;
   2982             if (fc->l2warm) {
   2983                 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) {
   2984                    action_bmp.w = NULL;
   2985                    _FP_XGS3_ALLOC(action_bmp.w,
   2986                              SHR_BITALLOCSIZE(_bcmFieldActionNoParamCount),
   2987                              "Action No Param Bitmap");
   2988                    if (action_bmp.w == NULL) {
   2989                        rv = BCM_E_MEMORY;
   2990                        sal_free(f_ent);
   2991                        goto cleanup;
   2992                    }
   2993                 }
   2994                 f_ent_wb_info.action_bmp = &action_bmp;
   2995 
   2996                 rv = _field_entry_info_retrieve(unit, fc, stage_fc,
   2997                                                 multigroup, &prev_prio,
   2998                                                 &f_ent_wb_info);
   2999                 
   3000                 if (BCM_FAILURE(rv)) {
   3001                     sal_free(f_ent);
   3002                     goto cleanup;
   3003                 }
   3004             } else {
   3005                 _bcm_field_last_alloc_eid_incr(unit);
   3006             }
   3007             vslice_idx = _field_physical_to_virtual(unit, _FP_DEF_INST,
   3008                                                    slice_idx, stage_fc);
   3009             if (vslice_idx == -1) {
   3010                 rv = BCM_E_INTERNAL;
   3011                 sal_free(f_ent);
   3012                 goto cleanup;
   3013             }
   3014             pri_tcam_idx = idx + entries_per_slice * slice_idx;
   3015             for (i = 0; i < parts_count; i++) {
   3016                 if (fc->l2warm) {
   3017                     /* Use retrieved EID */
   3018                     f_ent[i].eid = f_ent_wb_info.eid;
   3019                     /* Set retrieved dvp_type and svp_type */
   3020                     f_ent[i].dvp_type = f_ent_wb_info.dvp_type[i];
   3021                     f_ent[i].svp_type = f_ent_wb_info.svp_type[i];
   3022                     f_ent[i].prio = f_ent_wb_info.prio;
   3023                 } else {
   3024                     f_ent[i].eid = _bcm_field_last_alloc_eid_get(unit);
   3025                     f_ent[i].prio = (vslice_idx << 10) | (entries_per_slice - idx);
   3026                 }
   3027                 f_ent[i].group = fg;
   3028                 rv = _bcm_field_tcam_part_to_entry_flags(unit, i, fg,
   3029                                                          &f_ent[i].flags);
   3030                 if (BCM_FAILURE(rv)) {
   3031                     sal_free(f_ent);
   3032                     goto cleanup;
   3033                 }
   3034                 if (f_ent_wb_info.color_independent) {
   3035                     f_ent[i].flags |= _FP_ENTRY_COLOR_INDEPENDENT;
   3036                 }
   3037                 rv = _bcm_field_entry_part_tcam_idx_get(unit, f_ent, 
   3038                                                         pri_tcam_idx,
   3039                                                         i, &part_index);
   3040                 if (BCM_FAILURE(rv)) {
   3041                     sal_free(f_ent);
   3042                     goto cleanup;
   3043                 }
   3044                 rv = _bcm_field_tcam_idx_to_slice_offset(unit, stage_fc,
   3045                                                          _FP_DEF_INST,
   3046                                                          part_index, 
   3047                                                          &slice_number,
   3048                                                 (int *)&f_ent[i].slice_idx);
   3049                 if (BCM_FAILURE(rv)) {
   3050                     sal_free(f_ent);
   3051                     goto cleanup;
   3052                 }
   3053                 f_ent[i].fs = stage_fc->slices[_FP_DEF_INST] + slice_number;
   3054                 BCM_PBMP_OR(f_ent[i].fs->pbmp, fg->pbmp);
   3055                 if (0 == (f_ent[i].flags & _FP_ENTRY_SECOND_HALF)) {
   3056                     /* Decrement slice free entry count for primary 
   3057                        entries. */
   3058                     f_ent[i].fs->free_count--;
   3059                 }
   3060                 /* Assign entry to a slice */
   3061                 f_ent[i].fs->entries[f_ent[i].slice_idx] = f_ent + i;
   3062                 f_ent[i].flags |= _FP_ENTRY_INSTALLED;
   3063     
   3064                 if (soc_FP_TCAMm_field32_get(unit, tcam_entry, VALIDf) == 3) {
   3065                     f_ent[i].flags |= _FP_ENTRY_ENABLED;
   3066                 }
   3067 
   3068                 /* tcam_entry_buf must point to the entry part */
   3069                 tcam_entry_buf = (uint32 *)soc_mem_table_idx_to_pointer
   3070                                              (unit, FP_TCAMm, 
   3071                                               fp_tcam_entry_t *, 
   3072                                               fp_tcam_buf, part_index);
   3073 
   3074                 /* Use this part to determine fg->qual_arr[i] */
   3075                 /* Iterate over the HW qualifiers and match offsets with
   3076                    the non-zero masks */
   3077                 for (j = 0; j < fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size; j++) {
   3078                     qual_idx = fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr[j];
   3079                     f_qual_arr = stage_fc->f_qual_arr[qual_idx];
   3080                     /* Loop over configurations of this qualifier */
   3081                     for (k = 0; k < f_qual_arr->conf_sz; k++) {
   3082                         if (_mask_is_set(unit, &f_qual_arr->conf_arr[k].offset,
   3083                                 tcam_entry_buf, _BCM_FIELD_STAGE_INGRESS)) {
   3084                             qualified = 0;
   3085                             sel_ptr = NULL;
   3086                             switch (i) {
   3087                             case 0:
   3088                                 sel_ptr = &hw_sels.pri_slice[0];
   3089                                 break;
   3090                             case 1:
   3091                                 if (fs->group_flags & 
   3092                                     _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
   3093                                     sel_ptr = &hw_sels.pri_slice[1];
   3094                                 } else {
   3095                                     sel_ptr = &hw_sels.sec_slice[0];
   3096                                 }
   3097                                 break;
   3098                             case 2:
   3099                                 sel_ptr = &hw_sels.sec_slice[0];
   3100                                 break;
   3101                             case 3:
   3102                                 sel_ptr = &hw_sels.sec_slice[1];
   3103                                 break;
   3104                             default:
   3105                                 break;
   3106                             }
   3107                             if (((f_qual_arr->conf_arr[k].selector.pri_sel == 
   3108                                  _bcmFieldSliceSelFpf1) && 
   3109                                 (f_qual_arr->conf_arr[k].selector.pri_sel_val 
   3110                                  == sel_ptr->fpf1)) || 
   3111                                 ((f_qual_arr->conf_arr[k].selector.pri_sel == 
   3112                                  _bcmFieldSliceSelFpf2) && 
   3113                                 (f_qual_arr->conf_arr[k].selector.pri_sel_val 
   3114                                  == sel_ptr->fpf2)) ||
   3115                                 ((f_qual_arr->conf_arr[k].selector.pri_sel == 
   3116                                  _bcmFieldSliceSelFpf3) && 
   3117                                 (f_qual_arr->conf_arr[k].selector.pri_sel_val 
   3118                                  == sel_ptr->fpf3)) ||
   3119                                 ((f_qual_arr->conf_arr[k].selector.pri_sel == 
   3120                                  _bcmFieldSliceSelFpf4) && 
   3121                                 (f_qual_arr->conf_arr[k].selector.pri_sel_val 
   3122                                  == sel_ptr->fpf4))) {
   3123                                 qualified = 1;
   3124                             }
   3125                             if (qualified) {
   3126                                 sal_memcpy(&fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr[j],
   3127                                            &f_qual_arr->conf_arr[k].offset,
   3128                                            sizeof(f_qual_arr->conf_arr[k].offset));
   3129                             }
   3130                             break;
   3131                         } 
   3132                     }
   3133                 }
   3134                 /* Get the actions associated with this part of the entry */
   3135                 policy_entry = soc_mem_table_idx_to_pointer
   3136                                                 (unit, FP_POLICY_TABLEm, 
   3137                                                  fp_policy_table_entry_t *, 
   3138                                                  fp_policy_buf, part_index);
   3139                 rv = _field_fb_actions_recover(unit, (uint32 *)policy_entry,  
   3140                                                f_ent, i, FP_POLICY_TABLEm,
   3141                                                &f_ent_wb_info);
   3142                 if (BCM_FAILURE(rv)) {
   3143                     sal_free(f_ent);
   3144                     goto cleanup;
   3145                 }
   3146                 if (action_bmp.w != NULL) {
   3147                    _FP_ACTION_BMP_FREE(action_bmp);
   3148                    action_bmp.w = NULL;
   3149                 }
   3150             }
   3151             /* Add to the group */
   3152             rv = _field_group_entry_add(unit, fg, f_ent);
   3153             if (BCM_FAILURE(rv)) {
   3154                 sal_free(f_ent);
   3155                 goto cleanup;
   3156             }
   3157             f_ent = NULL;
   3158         }
   3159         /* Free up the temporary slice group info */
   3160         if (fc->l2warm) {
   3161             _field_scache_slice_group_free(unit, fc, slice_idx);
   3162         }
   3163     }
   3164 
   3165     /* Now go over the expanded slices */
   3166     for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) {
   3167         if (!expanded[slice_idx]) {
   3168             continue;
   3169         }
   3170         /* Skip if slice has no valid groups and entries */
   3171         fs = stage_fc->slices[_FP_DEF_INST] + slice_idx;
   3172         for (idx = 0; idx < fs->entry_count; idx++) {
   3173             tcam_entry = soc_mem_table_idx_to_pointer(unit, FP_TCAMm, 
   3174                                                       fp_tcam_entry_t *, 
   3175                                                       fp_tcam_buf, idx + 
   3176                                                       entries_per_slice * 
   3177                                                       slice_idx);
   3178             if (soc_FP_TCAMm_field32_get(unit, tcam_entry, VALIDf) != 0) {
   3179                 break;
   3180             }
   3181         }
   3182         if (idx == fs->entry_count){
   3183             continue;
   3184         }
   3185         /* If Level 2, retrieve the GIDs in this slice */
   3186         if (fc->l2warm) {
   3187             rv = _field_scache_slice_group_recover(unit, fc, slice_idx, 
   3188                                                        &multigroup);
   3189             if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   3190                 fc->l2warm = 0;
   3191                 goto cleanup;
   3192             }
   3193             if (rv == BCM_E_NOT_FOUND) {
   3194                 rv = BCM_E_NONE;
   3195                 continue;
   3196             }
   3197         }
   3198         /* Now find the master slice for this virtual group */
   3199         vslice_idx = _field_physical_to_virtual(unit, _FP_DEF_INST,
   3200                                                 slice_idx, stage_fc);
   3201         if (vslice_idx == -1) {
   3202             /* vslice_idx - Must be a valid hardware slice index value */
   3203             rv = BCM_E_INTERNAL;
   3204             goto cleanup;
   3205         }
   3206 
   3207         if (fc->l2warm
   3208                 && ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_8)) {
   3209             master_slice = slice_master_idx[slice_idx];
   3210         } else {
   3211         max = -1;
   3212         for (i = 0; i < stage_fc->tcam_slices; i++) {
   3213             if ((stage_fc->vmap[_FP_DEF_INST][0][vslice_idx].virtual_group == 
   3214                 stage_fc->vmap[_FP_DEF_INST][0][i].virtual_group) && (i != vslice_idx)) {
   3215                 if (i > max) {
   3216                     max = i;
   3217                 }
   3218             } 
   3219         }
   3220 
   3221         /* max - Must be a valid hardware slice index value */
   3222         if (-1 == max) {
   3223             rv = BCM_E_INTERNAL;
   3224             goto cleanup;
   3225         }
   3226 
   3227         master_slice = stage_fc->vmap[_FP_DEF_INST][0][max].vmap_key;
   3228         }
   3229         /* See which group is in this slice - can be only one */
   3230         fg = fc->groups;
   3231         while (fg != NULL) {
   3232             /* Check if group is in this slice */
   3233             fs = &fg->slices[0];
   3234             if ((fg->stage_id == stage_fc->stage_id)
   3235                     && (fs->slice_number == master_slice)) {
   3236                 break;
   3237             }
   3238             fg = fg->next;
   3239         }
   3240         if (fg == 0) {
   3241             rv = BCM_E_INTERNAL;
   3242             goto cleanup;
   3243         }
   3244 
   3245         /* Get number of entry parts for the group. */
   3246         rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
   3247                                                 fg->flags, &parts_count);
   3248         BCM_IF_ERROR_RETURN(rv);
   3249 
   3250         old_physical_slice = fs->slice_number;
   3251 
   3252         /* Set up the new physical slice parameters in Software */
   3253         for(part_index = parts_count - 1; part_index >= 0; part_index--) {
   3254             /* Get entry flags. */
   3255             rv = _bcm_field_tcam_part_to_entry_flags(unit, part_index, fg, &entry_flags);
   3256             BCM_IF_ERROR_RETURN(rv);
   3257 
   3258             /* Get slice id for entry part */
   3259             rv = _bcm_field_tcam_part_to_slice_number(unit, part_index,
   3260                                                       fg, &slice_num);
   3261             BCM_IF_ERROR_RETURN(rv);
   3262 
   3263             /* Get slice pointer. */
   3264             fs = stage_fc->slices[_FP_DEF_INST] + slice_idx
   3265                     + slice_num;
   3266 
   3267             if (0 == (entry_flags & _FP_ENTRY_SECOND_HALF)) {
   3268                 /* Set per slice configuration &  number of free entries in the slice.*/
   3269                 fs->free_count = fs->entry_count;
   3270                 if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
   3271                     fs->free_count >>= 1;
   3272                 }
   3273                 /* Set group flags in in slice.*/
   3274                 fs->group_flags = fg->flags & _FP_GROUP_STATUS_MASK;
   3275 
   3276                 /* Add slice to slices linked list . */
   3277                 fs_temp = stage_fc->slices[_FP_DEF_INST] + old_physical_slice + slice_num;
   3278                 /* To handle more than one auto expanded slice in a group */
   3279                 while (fs_temp->next != NULL) {
   3280                     fs_temp = fs_temp->next;
   3281                 }
   3282                 fs_temp->next = fs;
   3283                 fs->prev = fs_temp;
   3284             }
   3285         }
   3286 
   3287         /* Now go over the entries in this slice */
   3288         fs = stage_fc->slices[_FP_DEF_INST] + slice_idx;
   3289         if (fs->group_flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
   3290             ratio = 2;
   3291         } else {
   3292             ratio = 1;
   3293         }
   3294         prev_prio = -1;
   3295         for (idx = 0; idx < fs->entry_count / ratio; idx++) {
   3296             group_found = 0;
   3297             tcam_entry = soc_mem_table_idx_to_pointer(unit, FP_TCAMm, 
   3298                                                       fp_tcam_entry_t *, 
   3299                                                       fp_tcam_buf, idx + 
   3300                                                       entries_per_slice * 
   3301                                                       slice_idx);
   3302             if (soc_FP_TCAMm_field32_get(unit, tcam_entry, VALIDf) == 0) {
   3303                 continue;
   3304             }
   3305             /* Check which ports are applicable to this entry */
   3306             SOC_PBMP_CLEAR(entry_pbmp);
   3307             if ((soc_FP_TCAMm_field32_get(unit, tcam_entry, IPBM_SELf)) && 
   3308                 (soc_FP_TCAMm_field32_get(unit, tcam_entry, 
   3309                                           IPBM_SEL_MASKf))) {
   3310                 pbm = soc_FP_TCAMm_field32_get(unit, tcam_entry, F1f) & 
   3311                       soc_FP_TCAMm_field32_get(unit, tcam_entry, F1_MASKf);
   3312                 SOC_PBMP_WORD_SET(entry_pbmp, 0, pbm);
   3313             } else if ((f4_sel_val == 0) && 
   3314                        soc_FP_TCAMm_field32_get(unit, tcam_entry, F4_MASKf)) {
   3315                 pbm = soc_FP_TCAMm_field32_get(unit, tcam_entry, F4f) & 
   3316                       soc_FP_TCAMm_field32_get(unit, tcam_entry, F4_MASKf);
   3317                 SOC_PBMP_PORT_ADD(entry_pbmp, pbm);
   3318             } else {
   3319                 SOC_PBMP_ASSIGN(entry_pbmp, PBMP_ALL(unit));
   3320             }
   3321             /* Search groups to find match */
   3322             fg = fc->groups;
   3323             while (fg != NULL) {
   3324                 /* Check if group is in this slice */
   3325                 fs = &fg->slices[0];
   3326                 if ((fg->stage_id != stage_fc->stage_id)
   3327                         || (fs->slice_number != master_slice)) {
   3328                     fg = fg->next;
   3329                     continue;
   3330                 }
   3331                 /* Check if entry_pbmp is a subset of group pbmp */
   3332                 SOC_PBMP_ASSIGN(temp_pbmp, fg->pbmp);
   3333                 SOC_PBMP_OR(temp_pbmp, PBMP_LB(unit));
   3334                 SOC_PBMP_AND(temp_pbmp, entry_pbmp);
   3335                 if (SOC_PBMP_EQ(temp_pbmp, entry_pbmp)) {
   3336                     group_found = 1;
   3337                     break;
   3338                 }
   3339                 fg = fg->next;
   3340             }
   3341             if (!group_found) {
   3342                 return BCM_E_INTERNAL; /* Should never happen */
   3343             }
   3344             /* Allocate memory for the entry */
   3345             /*    coverity[forward_null : FALSE]    */
   3346             rv = _bcm_field_entry_tcam_parts_count(unit, fg->stage_id,
   3347                                                    fg->flags, &parts_count);
   3348             if (BCM_FAILURE(rv)) {
   3349                 goto cleanup;
   3350             }
   3351             mem_sz = parts_count * sizeof (_field_entry_t);
   3352             _FP_XGS3_ALLOC(f_ent, mem_sz, "field entry");
   3353             if (f_ent == NULL) {
   3354                 rv = BCM_E_MEMORY;
   3355                 goto cleanup;
   3356             }
   3357             for (idx1 = 0; idx1 < _FP_POLICER_LEVEL_COUNT; idx1++) {
   3358                  f_ent->policer[idx1].pid = _FP_INVALID_INDEX;
   3359             }
   3360 
   3361             sal_memset(&f_ent_wb_info, 0, sizeof(_field_entry_wb_info_t));
   3362             f_ent_wb_info.sid = f_ent_wb_info.pid = -1;
   3363             if (fc->l2warm) {
   3364                 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) {
   3365                    action_bmp.w = NULL;
   3366                    _FP_XGS3_ALLOC(action_bmp.w,
   3367                              SHR_BITALLOCSIZE(_bcmFieldActionNoParamCount),
   3368                              "Action No Param Bitmap");
   3369                    if (action_bmp.w == NULL) {
   3370                        rv = BCM_E_MEMORY;
   3371                        sal_free(f_ent);
   3372                        goto cleanup;
   3373                    }
   3374                 }
   3375                 f_ent_wb_info.action_bmp = &action_bmp;
   3376 
   3377                 rv = _field_entry_info_retrieve(unit, fc, stage_fc,
   3378                                                 multigroup, &prev_prio,
   3379                                                 &f_ent_wb_info);
   3380                 
   3381                 if (BCM_FAILURE(rv)) {
   3382                     sal_free(f_ent);
   3383                     goto cleanup;
   3384                 }
   3385             } else {
   3386                 _bcm_field_last_alloc_eid_incr(unit);
   3387             }
   3388             pri_tcam_idx = idx + entries_per_slice * slice_idx;
   3389             for (i = 0; i < parts_count; i++) {
   3390                 if (fc->l2warm) {
   3391                     /* Use retrieved EID */
   3392                     f_ent[i].eid = f_ent_wb_info.eid;
   3393                     /* Set retrieved dvp_type and svp_type */
   3394                     f_ent[i].dvp_type = f_ent_wb_info.dvp_type[i];
   3395                     f_ent[i].svp_type = f_ent_wb_info.svp_type[i];
   3396                     f_ent[i].prio = f_ent_wb_info.prio;
   3397                 } else {
   3398                     f_ent[i].eid = _bcm_field_last_alloc_eid_get(unit);
   3399                     f_ent[i].prio = (vslice_idx << 10) | (entries_per_slice - idx);
   3400                 }
   3401                 f_ent[i].group = fg;
   3402                 rv = _bcm_field_tcam_part_to_entry_flags(unit, i, fg,
   3403                                                          &f_ent[i].flags);
   3404                 if (BCM_FAILURE(rv)) {
   3405                     sal_free(f_ent);
   3406                     goto cleanup;
   3407                 }
   3408                 if (f_ent_wb_info.color_independent) {
   3409                     f_ent[i].flags |= _FP_ENTRY_COLOR_INDEPENDENT;
   3410                 }
   3411                 rv = _bcm_field_entry_part_tcam_idx_get(unit, f_ent, 
   3412                                                         pri_tcam_idx,
   3413                                                         i, &part_index);
   3414                 if (BCM_FAILURE(rv)) {
   3415                     sal_free(f_ent);
   3416                     goto cleanup;
   3417                 }
   3418                 rv = _bcm_field_tcam_idx_to_slice_offset(unit, stage_fc,
   3419                                                          _FP_DEF_INST,
   3420                                                          part_index, 
   3421                                                          &slice_number,
   3422                                                 (int *)&f_ent[i].slice_idx);
   3423                 if (BCM_FAILURE(rv)) {
   3424                     sal_free(f_ent);
   3425                     goto cleanup;
   3426                 }
   3427                 f_ent[i].fs = stage_fc->slices[_FP_DEF_INST] + slice_number;
   3428                 BCM_PBMP_OR(f_ent[i].fs->pbmp, fg->pbmp);
   3429                 if (0 == (f_ent[i].flags & _FP_ENTRY_SECOND_HALF)) {
   3430                     /* Decrement slice free entry count for primary 
   3431                        entries. */
   3432                     f_ent[i].fs->free_count--;
   3433                 }
   3434                 /* Assign entry to a slice */
   3435                 f_ent[i].fs->entries[f_ent[i].slice_idx] = f_ent + i;
   3436                 f_ent[i].flags |= _FP_ENTRY_INSTALLED;
   3437 
   3438                 if (soc_FP_TCAMm_field32_get(unit, tcam_entry, VALIDf) == 3) {
   3439                     f_ent[i].flags |= _FP_ENTRY_ENABLED;
   3440                 }
   3441 
   3442                 /* tcam_entry_buf must point to the entry part */
   3443                 tcam_entry_buf = (uint32 *)soc_mem_table_idx_to_pointer
   3444                                              (unit, FP_TCAMm, 
   3445                                               fp_tcam_entry_t *, 
   3446                                               fp_tcam_buf, part_index);
   3447 
   3448                 /* Use this part to determine fg->qual_arr[i] */
   3449                 /* Iterate over the HW qualifiers and match offsets with
   3450                    the non-zero masks */
   3451                 for (j = 0; j < fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size; j++) {
   3452                     qual_idx = fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr[j];
   3453                     f_qual_arr = stage_fc->f_qual_arr[qual_idx];
   3454                     /* Loop over configurations of this qualifier */
   3455                     for (k = 0; k < f_qual_arr->conf_sz; k++) {
   3456                         if (_mask_is_set(unit, &f_qual_arr->conf_arr[k].offset,
   3457                                 tcam_entry_buf, _BCM_FIELD_STAGE_INGRESS)) {
   3458                             qualified = 0;
   3459                             sel_ptr = NULL;
   3460                             switch (i) {
   3461                             case 0:
   3462                                 sel_ptr = &hw_sels.pri_slice[0];
   3463                                 break;
   3464                             case 1:
   3465                                 if (fs->group_flags & 
   3466                                     _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
   3467                                     sel_ptr = &hw_sels.pri_slice[1];
   3468                                 } else {
   3469                                     sel_ptr = &hw_sels.sec_slice[0];
   3470                                 }
   3471                                 break;
   3472                             case 2:
   3473                                 sel_ptr = &hw_sels.sec_slice[0];
   3474                                 break;
   3475                             case 3:
   3476                                 sel_ptr = &hw_sels.sec_slice[1];
   3477                                 break;
   3478                             default:
   3479                                 break;
   3480                             }
   3481                             if (((f_qual_arr->conf_arr[k].selector.pri_sel == 
   3482                                  _bcmFieldSliceSelFpf1) && 
   3483                                 (f_qual_arr->conf_arr[k].selector.pri_sel_val 
   3484                                  == sel_ptr->fpf1)) || 
   3485                                 ((f_qual_arr->conf_arr[k].selector.pri_sel == 
   3486                                  _bcmFieldSliceSelFpf2) && 
   3487                                 (f_qual_arr->conf_arr[k].selector.pri_sel_val 
   3488                                  == sel_ptr->fpf2)) ||
   3489                                 ((f_qual_arr->conf_arr[k].selector.pri_sel == 
   3490                                  _bcmFieldSliceSelFpf3) && 
   3491                                 (f_qual_arr->conf_arr[k].selector.pri_sel_val 
   3492                                  == sel_ptr->fpf3)) ||
   3493                                 ((f_qual_arr->conf_arr[k].selector.pri_sel == 
   3494                                  _bcmFieldSliceSelFpf4) && 
   3495                                 (f_qual_arr->conf_arr[k].selector.pri_sel_val 
   3496                                  == sel_ptr->fpf4))) {
   3497                                 qualified = 1;
   3498                             }
   3499                             if (qualified) {
   3500                                 sal_memcpy(&fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr[j],
   3501                                            &f_qual_arr->conf_arr[k].offset.field,
   3502                                            sizeof(f_qual_arr->conf_arr[k].offset.field));
   3503                             }
   3504                             break;
   3505                         } 
   3506                     }
   3507                 }
   3508                 /* Get the actions associated with this part of the entry */
   3509                 policy_entry = soc_mem_table_idx_to_pointer
   3510                                                 (unit, FP_POLICY_TABLEm, 
   3511                                                  fp_policy_table_entry_t *, 
   3512                                                  fp_policy_buf, part_index);
   3513                 rv = _field_fb_actions_recover(unit, (uint32 *)policy_entry,  
   3514                                                f_ent, i, FP_POLICY_TABLEm,
   3515                                                &f_ent_wb_info);
   3516                 if (BCM_FAILURE(rv)) {
   3517                     sal_free(f_ent);
   3518                     goto cleanup;
   3519                 }
   3520                 if (action_bmp.w != NULL) {
   3521                    _FP_ACTION_BMP_FREE(action_bmp);
   3522                    action_bmp.w = NULL;
   3523                 }
   3524             }
   3525             /* Add to the group */
   3526             rv = _field_group_entry_add(unit, fg, f_ent);
   3527             if (BCM_FAILURE(rv)) {
   3528                 sal_free(f_ent);
   3529                 goto cleanup;
   3530             }
   3531             f_ent = NULL;
   3532         }
   3533         /* Free up the temporary slice group info */
   3534         if (fc->l2warm) {
   3535             _field_scache_slice_group_free(unit, fc, slice_idx);
   3536         }
   3537     }
   3538 
   3539     /* To set per port flags */
   3540     group = fc->groups;
   3541     while (group != NULL) {
   3542            if (group->stage_id == _BCM_FIELD_STAGE_INGRESS) {
   3543                if (!BCM_PBMP_EQ(PBMP_ALL(unit), group->pbmp)) {
   3544                    /* Update Group Flags to denote Port based Group */
   3545                    group->flags |= _FP_GROUP_PER_PORT_OR_PBMP;
   3546                }
   3547            }
   3548            group = group->next;
   3549     }
   3550 
   3551     if (fc->l2warm) {
   3552 
   3553         /* Mark end of Slice Info */
   3554         if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) {
   3555             fc->scache_pos++;
   3556         }
   3557 
   3558         /* Group Slice Selectors */
   3559         if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) { 
   3560             rv = _field_group_slice_selectors_recover(unit,
   3561                         &buf[fc->scache_pos], stage_fc->stage_id);
   3562             if (BCM_FAILURE(rv)) {
   3563                 goto cleanup;
   3564             }
   3565         }
   3566 
   3567         temp = 0;
   3568         temp |= buf[fc->scache_pos];
   3569         fc->scache_pos++;
   3570         temp |= buf[fc->scache_pos] << 8;
   3571         fc->scache_pos++;
   3572         temp |= buf[fc->scache_pos] << 16;
   3573         fc->scache_pos++;
   3574         temp |= buf[fc->scache_pos] << 24;
   3575         fc->scache_pos++;
   3576         if (temp != _FIELD_IFP_DATA_END) {
   3577             fc->l2warm = 0;
   3578             rv = BCM_E_INTERNAL;
   3579         }
   3580         if (NULL != buf1) {
   3581             temp = 0;
   3582             temp |= buf1[fc->scache_pos1];
   3583             fc->scache_pos1++;
   3584             temp |= buf1[fc->scache_pos1] << 8;
   3585             fc->scache_pos1++;
   3586             temp |= buf1[fc->scache_pos1] << 16;
   3587             fc->scache_pos1++;
   3588             temp |= buf1[fc->scache_pos1] << 24;
   3589             fc->scache_pos1++;
   3590             if (temp != _FIELD_IFP_DATA_END) {
   3591                 fc->l2warm = 0;
   3592                 rv = BCM_E_INTERNAL;
   3593             }
   3594         }
   3595 
   3596     }
   3597 
   3598     if (BCM_SUCCESS(rv)) {
   3599         _field_group_slice_vmap_recovery(unit, fc, stage_fc);
   3600     }
   3601 
   3602 cleanup:
   3603     if (fp_tcam_buf) {
   3604         soc_cm_sfree(unit, fp_tcam_buf);
   3605     }
   3606     if (fp_pfs_buf) {
   3607         soc_cm_sfree(unit, fp_pfs_buf);
   3608     }
   3609     if (fp_policy_buf) {
   3610         soc_cm_sfree(unit, fp_policy_buf);
   3611     }
   3612     if (action_bmp.w != NULL) {
   3613         _FP_ACTION_BMP_FREE(action_bmp);
   3614         action_bmp.w = NULL;
   3615     }
   3616 
   3617     return rv;
   3618 }
   3619 
   3620 static uint16 list_key1[22] = {bcmFieldQualifyIpFrag, bcmFieldQualifyTcpControl,
   3621                       bcmFieldQualifyL4DstPort, bcmFieldQualifyL4SrcPort,
   3622                       bcmFieldQualifyTtl, bcmFieldQualifyIpProtocol,
   3623                       bcmFieldQualifyDstIp, bcmFieldQualifySrcIp,
   3624                       bcmFieldQualifyIpType, bcmFieldQualifyTos,
   3625                       bcmFieldQualifyInPort, bcmFieldQualifyL3Routable,
   3626                       bcmFieldQualifyMirrorCopy, bcmFieldQualifyOuterVlan,
   3627                       bcmFieldQualifyOuterVlanId, bcmFieldQualifyOuterVlanCfi,
   3628                       bcmFieldQualifyOuterVlanPri, bcmFieldQualifyVlanFormat,
   3629                       bcmFieldQualifyDstHiGig, bcmFieldQualifyInterfaceClassPort,
   3630                       bcmFieldQualifyOutPort, bcmFieldQualifyIp4};
   3631 
   3632 static uint16 list_key2[16] = {bcmFieldQualifyIpProtocol, bcmFieldQualifySrcIp6,
   3633                       bcmFieldQualifyIpType, bcmFieldQualifyDSCP,
   3634                       bcmFieldQualifyInPort, bcmFieldQualifyL3Routable,
   3635                       bcmFieldQualifyMirrorCopy, bcmFieldQualifyOuterVlan,
   3636                       bcmFieldQualifyOuterVlanId, bcmFieldQualifyOuterVlanCfi,
   3637                       bcmFieldQualifyOuterVlanPri, bcmFieldQualifyVlanFormat,
   3638                       bcmFieldQualifyDstHiGig, bcmFieldQualifyInterfaceClassPort,
   3639                       bcmFieldQualifyOutPort, bcmFieldQualifyIp6};
   3640 
   3641 static uint16 list_key3[7] = {bcmFieldQualifyIpFrag, bcmFieldQualifyTcpControl,
   3642                       bcmFieldQualifyL4DstPort, bcmFieldQualifyL4SrcPort,
   3643                       bcmFieldQualifyTtl, bcmFieldQualifyDstIp6,
   3644                       bcmFieldQualifyDstIp6};
   3645 
   3646 static uint16 list_key4[19] = {bcmFieldQualifyL2Format, bcmFieldQualifyEtherType,
   3647                       bcmFieldQualifySrcMac, bcmFieldQualifyDstMac,
   3648                       bcmFieldQualifyInnerVlan, bcmFieldQualifyInnerVlanId,
   3649                       bcmFieldQualifyInnerVlanCfi, bcmFieldQualifyInnerVlanPri,
   3650                       bcmFieldQualifyInPort, bcmFieldQualifyL3Routable,
   3651                       bcmFieldQualifyMirrorCopy, bcmFieldQualifyOuterVlan,
   3652                       bcmFieldQualifyOuterVlanId, bcmFieldQualifyOuterVlanCfi,
   3653                       bcmFieldQualifyOuterVlanPri, bcmFieldQualifyVlanFormat,
   3654                       bcmFieldQualifyDstHiGig, bcmFieldQualifyInterfaceClassPort,
   3655                       bcmFieldQualifyOutPort};
   3656 
   3657 int
   3658 _field_fb2_stage_egress_reinit(int unit, _field_control_t *fc, 
   3659                                _field_stage_t *stage_fc)
   3660 {
   3661     int idx, idx1, slice_idx, index_min, index_max, rv = BCM_E_NONE;
   3662     int entries_per_slice, mem_sz, qual_idx, parts_count = 1;
   3663     int i, j, k, pri_tcam_idx, part_index, slice_number;
   3664     int size, list_size[2], prev_prio;
   3665     uint16 *list_arr[2];
   3666     char *efp_tcam_buf = NULL; /* Buffer to read the EFP_TCAM table */
   3667     char *efp_policy_buf = NULL; /* Buffer to read the EFP_POLICY table */
   3668     uint32 rval, efp_slice_mode, key_match_type, temp;
   3669     uint32 *efp_tcam_entry_buf;
   3670     bcm_field_group_t gid;
   3671     int               priority;
   3672     int               group_flags;
   3673     efp_tcam_entry_t *efp_tcam_entry;
   3674     efp_policy_table_entry_t *efp_policy_entry;
   3675     _field_slice_t *fs;
   3676     _field_group_t *fg = NULL;
   3677     _field_entry_t *f_ent = NULL;
   3678     _bcm_field_qual_info_t *f_qual_arr = NULL;
   3679     _bcm_field_qual_offset_t *q_offset_arr = NULL;
   3680     uint16 *qid_arr = NULL;
   3681     uint8 *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0];
   3682     uint8 *buf1 = fc->scache_ptr[_FIELD_SCACHE_PART_1];
   3683     bcm_field_qset_t qset;
   3684     int action_res_id;
   3685     bcm_pbmp_t  group_pbmp;
   3686     _field_entry_wb_info_t f_ent_wb_info;
   3687     soc_field_t efp_en_flds[4] = {SLICE_ENABLE_SLICE_0f, SLICE_ENABLE_SLICE_1f,
   3688                                   SLICE_ENABLE_SLICE_2f, SLICE_ENABLE_SLICE_3f};
   3689 
   3690     soc_field_t efp_lk_en_flds[4] = 
   3691                      {LOOKUP_ENABLE_SLICE_0f, LOOKUP_ENABLE_SLICE_1f,
   3692                       LOOKUP_ENABLE_SLICE_2f, LOOKUP_ENABLE_SLICE_3f};
   3693     _field_action_bmp_t action_bmp;
   3694 
   3695     /* Reset Action bitmap to NULL. */
   3696     action_bmp.w = NULL;
   3697 
   3698     if (fc->l2warm) {
   3699         rv = _field_scache_stage_hdr_chk(fc, _FIELD_EFP_DATA_START);
   3700         if (BCM_FAILURE(rv)) {
   3701             return (rv);
   3702         }
   3703     }
   3704 
   3705     /* DMA various tables */
   3706     efp_tcam_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES
   3707                                  (unit, EFP_TCAMm), 
   3708                                  "EFP TCAM buffer");
   3709     if (NULL == efp_tcam_buf) {
   3710         return BCM_E_MEMORY;
   3711     }
   3712     index_min = soc_mem_index_min(unit, EFP_TCAMm);
   3713     index_max = soc_mem_index_max(unit, EFP_TCAMm);
   3714     if ((rv = soc_mem_read_range(unit, EFP_TCAMm, MEM_BLOCK_ALL,
   3715                                  index_min, index_max, 
   3716                                  efp_tcam_buf)) < 0 ) {
   3717         goto cleanup;
   3718     }
   3719     efp_policy_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES
   3720                                   (unit, EFP_POLICY_TABLEm), 
   3721                                   "EFP POLICY TABLE buffer");
   3722     if (NULL == efp_policy_buf) {
   3723         return BCM_E_MEMORY;
   3724     }
   3725     index_min = soc_mem_index_min(unit, EFP_POLICY_TABLEm);
   3726     index_max = soc_mem_index_max(unit, EFP_POLICY_TABLEm);
   3727     if ((rv = soc_mem_read_range(unit, EFP_POLICY_TABLEm, MEM_BLOCK_ALL,
   3728                                  index_min, index_max, 
   3729                                  efp_policy_buf)) < 0 ) {
   3730         goto cleanup;
   3731     }
   3732     entries_per_slice = 128;
   3733 
   3734     /* Iterate over the slices */
   3735     if ((rv = READ_EFP_SLICE_CONTROLr(unit, &rval)) < 0) {
   3736         goto cleanup;
   3737     }
   3738     for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) {
   3739         /* Ignore disabled slice */
   3740         if ((soc_reg_field_get(unit, EFP_SLICE_CONTROLr, rval, 
   3741                                efp_en_flds[slice_idx]) == 0) || 
   3742             (soc_reg_field_get(unit, EFP_SLICE_CONTROLr, rval, 
   3743                                efp_lk_en_flds[slice_idx]) == 0)) {
   3744             continue;
   3745         }
   3746 
   3747         efp_slice_mode = soc_reg_field_get(unit, EFP_SLICE_CONTROLr, rval, 
   3748                                            _efp_slice_mode[slice_idx]);
   3749         /* Skip if slice has no valid entries */
   3750         fs = stage_fc->slices[_FP_DEF_INST] + slice_idx;
   3751         for (idx = 0; idx < fs->entry_count; idx++) {
   3752             efp_tcam_entry = soc_mem_table_idx_to_pointer
   3753                                  (unit, EFP_TCAMm, efp_tcam_entry_t *, 
   3754                                   efp_tcam_buf, idx + 
   3755                                   entries_per_slice * slice_idx);
   3756             if (soc_EFP_TCAMm_field32_get(unit, efp_tcam_entry, 
   3757                                           VALIDf) != 0) {
   3758                 /* Get KEY_MATCH_TYPE from first valid entry */
   3759                 /* 
   3760                  * COVERITY 
   3761                  *
   3762                  * Call to _field_extract is taken care in all the flows
   3763                  * by not setting the width mrore than 32.
   3764                  */
   3765                  /* coverity[callee_ptr_arith] */
   3766                 _field_extract((uint32 *)efp_tcam_entry, 181 + 2, 3, 
   3767                                 &key_match_type); 
   3768                 break;
   3769             }
   3770         }
   3771         if ((idx == fs->entry_count) && !fc->l2warm) {
   3772             continue;
   3773         }
   3774         /* Skip second part of slice pair */
   3775         if ((efp_slice_mode == _BCM_FIELD_EGRESS_SLICE_MODE_DOUBLE) &&
   3776             (slice_idx % 2)) {
   3777             continue;
   3778         }
   3779         fg = NULL;
   3780         if (efp_slice_mode != 3) { /* Invalid value */
   3781             /* If Level 2, retrieve the GIDs in this slice */
   3782             if (fc->l2warm) {
   3783                 rv = _field_scache_slice_group_recover(unit, fc, slice_idx, 
   3784                                                            NULL);
   3785                 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   3786                     fc->l2warm = 0;
   3787                     goto cleanup;
   3788                 }
   3789                 if (rv == BCM_E_NOT_FOUND) {
   3790                     rv = BCM_E_NONE;
   3791                     continue;
   3792                 }
   3793             }
   3794             /* Create a new group - one group per slice */
   3795             _FP_XGS3_ALLOC(fg, sizeof(_field_group_t), "field group");
   3796             if (NULL == fg) {
   3797                 goto cleanup;
   3798             } 
   3799 
   3800             /* Initialize action res id and VMAP group to default */
   3801             action_res_id = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT;
   3802             for (idx = 0; idx < _FP_PAIR_MAX; idx++) {
   3803                 fg->vmap_group[idx] = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT;
   3804             }
   3805 
   3806             group_flags = 0; 
   3807             if (fc->l2warm) {
   3808                 /* Get stored group ID and QSET for Level 2 */
   3809                 rv = _field_group_info_retrieve(unit, -1, _FP_DEF_INST, &gid,
   3810                                                 &priority, &action_res_id, &group_pbmp, NULL,
   3811                                                 &group_flags, &qset, fc);
   3812                 if (gid != -1) {
   3813                     sal_memcpy(&fg->qset, &qset, sizeof(bcm_field_qset_t));
   3814                 } else {
   3815                     sal_free(fg);
   3816                     goto cleanup;
   3817                 }
   3818             } else {
   3819                 rv = _bcm_field_group_id_generate(unit, &gid);
   3820                 priority = slice_idx;
   3821             }
   3822             if (BCM_FAILURE(rv)) {
   3823                 sal_free(fg);
   3824                 goto cleanup;
   3825             }
   3826             fg->gid = gid;
   3827             fg->priority = priority;
   3828             fg->action_res_id = action_res_id;
   3829             if (group_flags & _FP_GROUP_SELECT_AUTO_EXPANSION) {
   3830                 fg->flags = fg->flags | _FP_GROUP_SELECT_AUTO_EXPANSION;
   3831             }
   3832 
   3833             fg->stage_id = stage_fc->stage_id;
   3834             list_arr[0] = list_arr[1] = NULL;
   3835             switch (efp_slice_mode) {
   3836                 case _BCM_FIELD_EGRESS_SLICE_MODE_SINGLE_L2:
   3837                     fg->flags |= _FP_GROUP_SPAN_SINGLE_SLICE;
   3838                     fg->sel_codes[0].fpf3 = _BCM_FIELD_EFP_KEY4;
   3839                     parts_count = 1;
   3840                     list_size[0] = 19;
   3841                     list_arr[0] = list_key4;
   3842                     break;
   3843                 case _BCM_FIELD_EGRESS_SLICE_MODE_SINGLE_L3:
   3844                     fg->flags |= _FP_GROUP_SPAN_SINGLE_SLICE;
   3845                     fg->sel_codes[0].fpf3 = _BCM_FIELD_EFP_KEY1;
   3846                     parts_count = 1;
   3847                     list_size[0] = 22;
   3848                     list_arr[0] = list_key1;
   3849                     break;
   3850                 case _BCM_FIELD_EGRESS_SLICE_MODE_DOUBLE:
   3851                     fg->flags |= _FP_GROUP_SPAN_DOUBLE_SLICE;
   3852                     if (key_match_type == 
   3853                         _BCM_FIELD_EFP_KEY2_KEY3_MATCH_TYPE) {
   3854                         fg->sel_codes[0].fpf3 = _BCM_FIELD_EFP_KEY3;
   3855                         fg->sel_codes[1].fpf3 = _BCM_FIELD_EFP_KEY2;
   3856                         list_size[0] = 7; 
   3857                         list_size[1] = 16;    
   3858                         list_arr[0] = list_key3;  
   3859                         list_arr[1] = list_key2;            
   3860                     } else { /* _BCM_FIELD_EFP_KEY1_KEY4_MATCH_TYPE */
   3861                         fg->sel_codes[0].fpf3 = _BCM_FIELD_EFP_KEY1;
   3862                         fg->sel_codes[1].fpf3 = _BCM_FIELD_EFP_KEY4;
   3863                         list_size[0] = 22; 
   3864                         list_size[1] = 19;
   3865                         list_arr[0] = list_key1;  
   3866                         list_arr[1] = list_key4; 
   3867                     }
   3868                     parts_count = 2;
   3869                     break;
   3870                 default:
   3871                     /* slice mode must be a valid value. */
   3872                     sal_free(fg);
   3873                     rv = BCM_E_INTERNAL;
   3874                     goto cleanup;
   3875             }
   3876             /* Determine QSET based on selector values */
   3877             /* Add the appropriate list of qualifiers */
   3878             BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyStageEgress);
   3879             for (i = 0; i < parts_count; i++) {
   3880                 for (j = 0; j < list_size[i]; j++) {
   3881                     if (fc->l2warm && !BCM_FIELD_QSET_TEST(fg->qset, 
   3882                                                        list_arr[i][j])) {  
   3883                         continue;
   3884                     }
   3885                     BCM_FIELD_QSET_ADD(fg->qset, list_arr[i][j]);
   3886                     f_qual_arr = stage_fc->f_qual_arr[list_arr[i][j]];
   3887                     for (k = 0; k < f_qual_arr->conf_sz; k++) {
   3888                         if ((f_qual_arr->conf_arr[k].selector.pri_sel_val == 
   3889                              fg->sel_codes[i].fpf3)) {
   3890                             break;
   3891                         }
   3892                     }
   3893                     /* Allocate memory for this qualfier and its
   3894                        associated ofset information if not already added 
   3895                        to fg->qual_arr[i] */
   3896                     size = fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size + 1;
   3897                     qid_arr = NULL;
   3898                     _FP_XGS3_ALLOC(qid_arr, size * sizeof (uint16), 
   3899                                    "Group qual id");
   3900                     if (NULL == qid_arr) {
   3901                         goto cleanup;
   3902                     }              
   3903                     q_offset_arr = NULL;              
   3904                     _FP_XGS3_ALLOC(q_offset_arr, size * 
   3905                                    sizeof (_bcm_field_qual_offset_t), 
   3906                                    "Group qual offset");
   3907                     if (NULL == q_offset_arr) {
   3908                         sal_free (qid_arr);
   3909                         goto cleanup;
   3910                     }
   3911                     if (size) {
   3912                         sal_memcpy(qid_arr, fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr,
   3913                                    fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size * 
   3914                                    sizeof (uint16));
   3915                         sal_memcpy(q_offset_arr, 
   3916                                    fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr, 
   3917                                    fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size * 
   3918                                    sizeof (_bcm_field_qual_offset_t));
   3919                         if (fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size) {
   3920                             sal_free(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr);
   3921                             sal_free(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr);
   3922                         }
   3923                     }
   3924                     fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr = qid_arr;
   3925                     fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr = q_offset_arr;
   3926                     fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr[size - 1] = list_arr[i][j];
   3927 
   3928                     sal_memcpy(&fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr[size - 1],
   3929                                &f_qual_arr->conf_arr[k].offset,
   3930                                sizeof(f_qual_arr->conf_arr[k].offset));
   3931 
   3932                     fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size = size;
   3933                 }
   3934             }
   3935             /* Associate slice(s) to group */
   3936             fg->slices = stage_fc->slices[_FP_DEF_INST] + slice_idx;
   3937             SOC_PBMP_ASSIGN(fg->pbmp, PBMP_ALL(unit));
   3938             BCM_PBMP_OR(fs->pbmp, fg->pbmp);
   3939 
   3940             /* Initialize group default ASET list. */
   3941             rv = _field_group_default_aset_set(unit, fg);
   3942             if (BCM_FAILURE(rv)) {
   3943                 /* Free group's qualifier and offset array memories. */
   3944                 for (i = 0; i < parts_count; i++) {
   3945                     if (NULL != fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr) {
   3946                         sal_free(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr);
   3947                         fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr = NULL;
   3948                     }
   3949                     if (NULL != fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr) {
   3950                         sal_free(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr);
   3951                         fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr = NULL;
   3952                     }
   3953                 }
   3954 
   3955                 /* Free group's memory*/
   3956                 sal_free(fg);
   3957                 goto cleanup;
   3958             }
   3959 
   3960             if (fc->l2warm
   3961                     && ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15)) {
   3962                 if (group_flags & _FP_GROUP_LOOKUP_ENABLED) {
   3963                     fg->flags = fg->flags | _FP_GROUP_LOOKUP_ENABLED;
   3964                 }
   3965                 if (group_flags & _FP_GROUP_WLAN) {
   3966                     fg->flags = fg->flags | _FP_GROUP_WLAN;
   3967                 }
   3968             } else {
   3969                 fg->flags |= _FP_GROUP_LOOKUP_ENABLED;
   3970             }
   3971 
   3972             fg->next = fc->groups;
   3973             fc->groups = fg;
   3974 
   3975             /* Now go over the entries in this slice */
   3976             prev_prio = -1;
   3977             for (idx = 0; idx < fs->entry_count; idx++) {
   3978                 efp_tcam_entry = soc_mem_table_idx_to_pointer
   3979                                      (unit, EFP_TCAMm, efp_tcam_entry_t *, 
   3980                                       efp_tcam_buf, idx + 
   3981                                       entries_per_slice * slice_idx);
   3982                 if (soc_EFP_TCAMm_field32_get(unit, efp_tcam_entry, 
   3983                                               VALIDf) == 0) {
   3984                     continue;
   3985                 }
   3986                 /* Allocate memory for this entry */
   3987                 mem_sz = parts_count * sizeof (_field_entry_t);
   3988                 _FP_XGS3_ALLOC(f_ent, mem_sz, "field entry");
   3989                 if (f_ent == NULL) {
   3990                     rv = BCM_E_MEMORY;
   3991                     goto cleanup;
   3992                 }
   3993 
   3994                 for (idx1 = 0; idx1 < _FP_POLICER_LEVEL_COUNT; idx1++) {
   3995                      f_ent->policer[idx1].pid = _FP_INVALID_INDEX;
   3996                 }
   3997 
   3998                 sal_memset(&f_ent_wb_info, 0, sizeof(_field_entry_wb_info_t));
   3999                 f_ent_wb_info.sid = f_ent_wb_info.pid = -1;
   4000                 if (fc->l2warm) {
   4001                     if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) {
   4002                        action_bmp.w = NULL;
   4003                        _FP_XGS3_ALLOC(action_bmp.w,
   4004                              SHR_BITALLOCSIZE(_bcmFieldActionNoParamCount),
   4005                              "Action No Param Bitmap");
   4006                        if (action_bmp.w == NULL) {
   4007                           rv = BCM_E_MEMORY;
   4008                           sal_free(f_ent);
   4009                           goto cleanup;
   4010                        }
   4011                     }
   4012                     f_ent_wb_info.action_bmp = &action_bmp;
   4013 
   4014                     rv = _field_entry_info_retrieve(unit, fc, stage_fc,
   4015                                                     0, &prev_prio, 
   4016                                                     &f_ent_wb_info);
   4017                     
   4018                     if (BCM_FAILURE(rv)) {
   4019                         sal_free(f_ent);
   4020                         goto cleanup;
   4021                     }
   4022                 } else {
   4023                     _bcm_field_last_alloc_eid_incr(unit);
   4024                 }
   4025                 pri_tcam_idx = idx + entries_per_slice * slice_idx;
   4026                 for (i = 0; i < parts_count; i++) {
   4027                     if (fc->l2warm) {
   4028                         f_ent[i].eid = f_ent_wb_info.eid;
   4029                         /* Set retrieved dvp_type and svp_type */
   4030                         f_ent[i].dvp_type = f_ent_wb_info.dvp_type[i];
   4031                         f_ent[i].svp_type = f_ent_wb_info.svp_type[i];
   4032                     } else {
   4033                         f_ent[i].eid = _bcm_field_last_alloc_eid_get(unit);
   4034                     }
   4035                     f_ent[i].group = fg;
   4036                     rv = _bcm_field_tcam_part_to_entry_flags(unit, i, fg,
   4037                                                              &f_ent[i].flags);
   4038                     if (BCM_FAILURE(rv)) {
   4039                         sal_free(f_ent);
   4040                         goto cleanup;
   4041                     }
   4042                     if (f_ent_wb_info.color_independent) {
   4043                         f_ent[i].flags |= _FP_ENTRY_COLOR_INDEPENDENT;
   4044                     }
   4045                     rv = _bcm_field_entry_part_tcam_idx_get(unit, f_ent, 
   4046                                                             pri_tcam_idx,
   4047                                                             i, &part_index);
   4048                     if (BCM_FAILURE(rv)) {
   4049                         sal_free(f_ent);
   4050                         goto cleanup;
   4051                     }
   4052                     rv = _bcm_field_tcam_idx_to_slice_offset(unit, stage_fc,
   4053                                                              _FP_DEF_INST,
   4054                                                              part_index, 
   4055                                                              &slice_number,
   4056                                                 (int *)&f_ent[i].slice_idx);
   4057                     if (BCM_FAILURE(rv)) {
   4058                         sal_free(f_ent);
   4059                         goto cleanup;
   4060                     }
   4061                     f_ent[i].fs = stage_fc->slices[_FP_DEF_INST] + slice_number;
   4062                     if (0 == (f_ent[i].flags & _FP_ENTRY_SECOND_HALF)) {
   4063                         /* Decrement slice free entry count for primary 
   4064                            entries. */
   4065                         f_ent[i].fs->free_count--;
   4066                     }
   4067                     /* Assign entry to a slice */
   4068                     f_ent[i].fs->entries[f_ent[i].slice_idx] = f_ent + i;
   4069                     f_ent[i].flags |= _FP_ENTRY_INSTALLED;
   4070 
   4071                     if (soc_EFP_TCAMm_field32_get(unit, efp_tcam_entry, VALIDf) == 3) {
   4072                         f_ent[i].flags |= _FP_ENTRY_ENABLED;
   4073                     }
   4074 
   4075                     /* efp_tcam_entry_buf must point to the entry part */
   4076                     efp_tcam_entry_buf = (uint32 *)
   4077                                           soc_mem_table_idx_to_pointer
   4078                                                  (unit, EFP_TCAMm, 
   4079                                                   efp_tcam_entry_t *, 
   4080                                                   efp_tcam_buf, part_index);
   4081 
   4082                     /* Use this part to determine fg->qual_arr[i] */
   4083                     /* Iterate over the HW qualifiers and match offsets with
   4084                        the non-zero masks */
   4085                     for (j = 0; j < fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size; j++) {
   4086                         qual_idx = fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr[j];
   4087                         f_qual_arr = stage_fc->f_qual_arr[qual_idx];
   4088                         /* Loop over configurations of this qualifier */
   4089                         for (k = 0; k < f_qual_arr->conf_sz; k++) {
   4090                             if (_mask_is_set(unit, 
   4091                                           &f_qual_arr->conf_arr[k].offset,
   4092                                           efp_tcam_entry_buf, 
   4093                                           _BCM_FIELD_STAGE_EGRESS)) {
   4094                                 sal_memcpy(&fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr[j].field,
   4095                                            &f_qual_arr->conf_arr[k].offset,
   4096                                            sizeof(f_qual_arr->conf_arr[k].offset));
   4097                                 break;
   4098                             } 
   4099                         }
   4100                     }
   4101                     /* Get the actions associated with this entry part */
   4102                     efp_policy_entry = soc_mem_table_idx_to_pointer
   4103                                                (unit, EFP_POLICY_TABLEm, 
   4104                                                 efp_policy_table_entry_t *, 
   4105                                                 efp_policy_buf, part_index);
   4106                     rv = _field_fb_actions_recover(unit, (uint32 *)
   4107                                                    efp_policy_entry, f_ent, 
   4108                                                    i, EFP_POLICY_TABLEm,
   4109                                                    &f_ent_wb_info);
   4110                     if (BCM_FAILURE(rv)) {
   4111                         sal_free(f_ent);
   4112                         goto cleanup;
   4113                     }
   4114                     if (action_bmp.w != NULL) {
   4115                        _FP_ACTION_BMP_FREE(action_bmp);
   4116                        action_bmp.w = NULL;
   4117                     }
   4118                 }
   4119                 /* Add to the group */
   4120                 rv = _field_group_entry_add(unit, fg, f_ent);
   4121                 if (BCM_FAILURE(rv)) {
   4122                     sal_free(f_ent);
   4123                     goto cleanup;
   4124                 }
   4125                 f_ent = NULL;
   4126             }
   4127         }
   4128         /* Free up the temporary slice group info */
   4129         if (fc->l2warm) {
   4130             _field_scache_slice_group_free(unit, fc, slice_idx);
   4131         }
   4132     }
   4133 
   4134     if (fc->l2warm) {
   4135 
   4136         /* Mark end of Slice Info */
   4137         if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) {
   4138             fc->scache_pos++;
   4139         }
   4140 
   4141         /* Group Slice Selectors */
   4142         if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) {
   4143             rv = (_field_group_slice_selectors_recover(unit,
   4144                         &buf[fc->scache_pos], stage_fc->stage_id));
   4145             if (BCM_FAILURE(rv)) {
   4146                 goto cleanup;
   4147             }
   4148         }
   4149 
   4150         temp = 0;
   4151         temp |= buf[fc->scache_pos];
   4152         fc->scache_pos++;
   4153         temp |= buf[fc->scache_pos] << 8;
   4154         fc->scache_pos++;
   4155         temp |= buf[fc->scache_pos] << 16;
   4156         fc->scache_pos++;
   4157         temp |= buf[fc->scache_pos] << 24;
   4158         fc->scache_pos++;
   4159         if (temp != _FIELD_EFP_DATA_END) {
   4160             fc->l2warm = 0;
   4161             rv = BCM_E_INTERNAL;
   4162         }
   4163 
   4164         if (NULL != buf1) {
   4165             temp = 0;
   4166             temp |= buf1[fc->scache_pos1];
   4167             fc->scache_pos1++;
   4168             temp |= buf1[fc->scache_pos1] << 8;
   4169             fc->scache_pos1++;
   4170             temp |= buf1[fc->scache_pos1] << 16;
   4171             fc->scache_pos1++;
   4172             temp |= buf1[fc->scache_pos1] << 24;
   4173             fc->scache_pos1++;
   4174             if (temp != _FIELD_EFP_DATA_END) {
   4175                 fc->l2warm = 0;
   4176                 rv = BCM_E_INTERNAL;
   4177             }
   4178         }
   4179     }
   4180 cleanup:
   4181     if (efp_tcam_buf) {
   4182         soc_cm_sfree(unit, efp_tcam_buf);
   4183     }
   4184     if (efp_policy_buf) {
   4185         soc_cm_sfree(unit, efp_policy_buf);
   4186     }
   4187     if (fg != NULL) {
   4188        sal_free(fg);
   4189     }
   4190     if (action_bmp.w != NULL) {
   4191         _FP_ACTION_BMP_FREE(action_bmp);
   4192         action_bmp.w = NULL;
   4193     }
   4194     return rv;
   4195 }
   4196 
   4197 int
   4198 _field_fb2_stage_lookup_reinit(int unit, _field_control_t *fc, 
   4199                                _field_stage_t *stage_fc)
   4200 {
   4201     int idx, idx1, slice_idx, index_min, index_max, ratio, rv = BCM_E_NONE;
   4202     int entries_per_slice, group_found, mem_sz, parts_count, qual_idx;
   4203     int i, j, k, pri_tcam_idx, part_index, slice_number, prev_prio;
   4204     char *vfp_tcam_buf = NULL; /* Buffer to read the VFP_TCAM table */
   4205     char *vfp_policy_buf = NULL; /* Buffer to read the VFP_POLICY table */
   4206     uint32 rval, paired, intraslice, dbl_wide_key, dbl_wide_key_sec;
   4207     uint32 vfp_key, temp;
   4208     uint32 *vfp_tcam_entry_buf;
   4209     soc_field_t fld;
   4210     vfp_tcam_entry_t *vfp_tcam_entry;
   4211     vfp_policy_table_entry_t *vfp_policy_entry;
   4212     _field_hw_qual_info_t hw_sels;
   4213     _field_slice_t *fs;
   4214     _field_group_t *fg;
   4215     _field_entry_t *f_ent = NULL;
   4216     bcm_pbmp_t entry_pbmp, temp_pbmp;
   4217     _bcm_field_qual_info_t *f_qual_arr = NULL;
   4218     uint8 *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0];
   4219     uint8 *buf1 = fc->scache_ptr[_FIELD_SCACHE_PART_1];
   4220     _field_entry_wb_info_t f_ent_wb_info;
   4221 
   4222     soc_field_t vfp_en_flds[4] = {SLICE_ENABLE_SLICE_0f, SLICE_ENABLE_SLICE_1f,
   4223                                   SLICE_ENABLE_SLICE_2f, SLICE_ENABLE_SLICE_3f};
   4224 
   4225     soc_field_t vfp_lk_en_flds[4] = 
   4226                      {LOOKUP_ENABLE_SLICE_0f, LOOKUP_ENABLE_SLICE_1f,
   4227                       LOOKUP_ENABLE_SLICE_2f, LOOKUP_ENABLE_SLICE_3f};
   4228     _field_action_bmp_t action_bmp;
   4229 
   4230     /* Reset Action bitmap to NULL. */
   4231     action_bmp.w = NULL;
   4232 
   4233     SOC_PBMP_CLEAR(entry_pbmp);
   4234 
   4235     if (fc->l2warm) {
   4236         rv = _field_scache_stage_hdr_chk(fc, _FIELD_VFP_DATA_START);
   4237         if (BCM_FAILURE(rv)) {
   4238             return (rv);
   4239         }
   4240     }
   4241 
   4242     /* DMA various tables */
   4243     vfp_tcam_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES
   4244                                  (unit, VFP_TCAMm), 
   4245                                  "VFP TCAM buffer");
   4246     if (NULL == vfp_tcam_buf) {
   4247         return BCM_E_MEMORY;
   4248     }
   4249     index_min = soc_mem_index_min(unit, VFP_TCAMm);
   4250     index_max = soc_mem_index_max(unit, VFP_TCAMm);
   4251     if ((rv = soc_mem_read_range(unit, VFP_TCAMm, MEM_BLOCK_ALL,
   4252                                  index_min, index_max, 
   4253                                  vfp_tcam_buf)) < 0 ) {
   4254         goto cleanup;
   4255     }
   4256     vfp_policy_buf = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES
   4257                                   (unit, VFP_POLICY_TABLEm), 
   4258                                   "VFP POLICY TABLE buffer");
   4259     if (NULL == vfp_policy_buf) {
   4260         return BCM_E_MEMORY;
   4261     }
   4262     index_min = soc_mem_index_min(unit, VFP_POLICY_TABLEm);
   4263     index_max = soc_mem_index_max(unit, VFP_POLICY_TABLEm);
   4264     if ((rv = soc_mem_read_range(unit, VFP_POLICY_TABLEm, MEM_BLOCK_ALL,
   4265                                  index_min, index_max, 
   4266                                  vfp_policy_buf)) < 0 ) {
   4267         goto cleanup;
   4268     }
   4269     entries_per_slice = 256;
   4270 
   4271     /* Iterate over the slices */
   4272     if ((rv = READ_VFP_SLICE_CONTROLr(unit, &rval)) < 0) {
   4273         goto cleanup;
   4274     }
   4275     if ((rv = READ_VFP_KEY_CONTROLr(unit, &vfp_key)) < 0) {
   4276         goto cleanup;
   4277     }
   4278     for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) {
   4279         /* Ignore disabled slice */
   4280         if ((soc_reg_field_get(unit, VFP_SLICE_CONTROLr, rval, 
   4281                                vfp_en_flds[slice_idx]) == 0) || 
   4282             (soc_reg_field_get(unit, VFP_SLICE_CONTROLr, rval, 
   4283                                vfp_lk_en_flds[slice_idx]) == 0)) {
   4284             continue;
   4285         }
   4286         /* Ignore secondary slice in paired mode */
   4287         fld = _vfp_slice_pairing_field[slice_idx / 2];
   4288         paired = soc_reg_field_get(unit, VFP_KEY_CONTROLr, vfp_key, fld);
   4289         fld = _vfp_slice_wide_mode_field[slice_idx];
   4290         intraslice = soc_reg_field_get(unit, VFP_KEY_CONTROLr, vfp_key, fld);
   4291         if (paired && (slice_idx % 2)) {
   4292             continue;
   4293         }
   4294         /* Skip if slice has no valid groups and entries */
   4295         fs = stage_fc->slices[_FP_DEF_INST] + slice_idx;
   4296         for (idx = 0; idx < fs->entry_count; idx++) {
   4297             vfp_tcam_entry = soc_mem_table_idx_to_pointer
   4298                                  (unit, VFP_TCAMm, vfp_tcam_entry_t *, 
   4299                                   vfp_tcam_buf, idx + 
   4300                                   entries_per_slice * slice_idx);
   4301             if (soc_VFP_TCAMm_field32_get(unit, vfp_tcam_entry, 
   4302                                           VALIDf) != 0) {
   4303                 break;
   4304             }
   4305         }
   4306         if ((idx == fs->entry_count) && !fc->l2warm) {
   4307             continue;
   4308         }
   4309         /* If Level 2, retrieve the GIDs in this slice */
   4310         if (fc->l2warm) {
   4311             rv = _field_scache_slice_group_recover(unit, fc, slice_idx, 
   4312                                                        NULL);
   4313             if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   4314                 fc->l2warm = 0;
   4315                 goto cleanup;
   4316             }
   4317             if (rv == BCM_E_NOT_FOUND) {
   4318                 rv = BCM_E_NONE;
   4319                 continue;
   4320             }
   4321         }
   4322         /* Construct the group based on HW selector values */
   4323         sal_memset(&hw_sels, 0, sizeof(_field_hw_qual_info_t));
   4324         /* Get primary slice's selectors */
   4325         hw_sels.pri_slice[0].fpf2 = soc_reg_field_get(unit, VFP_KEY_CONTROLr, 
   4326                                     vfp_key, _vfp_field_tbl[slice_idx][0]);
   4327         hw_sels.pri_slice[0].fpf3 = soc_reg_field_get(unit, VFP_KEY_CONTROLr, 
   4328                                     vfp_key, _vfp_field_tbl[slice_idx][1]);
   4329         /* If intraslice, get double-wide key - only 2 options */
   4330         if (intraslice) {
   4331             dbl_wide_key = soc_reg_field_get(unit, VFP_KEY_CONTROLr, vfp_key, 
   4332                                      _vfp_slice_wide_mode_field[slice_idx]);
   4333             hw_sels.pri_slice[1].intraslice = 1;
   4334             hw_sels.pri_slice[1].fpf2 = dbl_wide_key;
   4335             hw_sels.pri_slice[1].fpf3 = 0;
   4336         }
   4337         /* If paired, get secondary slice's selectors */
   4338         if (paired) {
   4339             hw_sels.sec_slice[0].fpf2 = soc_reg_field_get(unit, 
   4340                                                           VFP_KEY_CONTROLr,
   4341                                                           vfp_key, 
   4342                                           _vfp_field_tbl[slice_idx + 1][0]);
   4343             hw_sels.sec_slice[0].fpf3 = soc_reg_field_get(unit, 
   4344                                                           VFP_KEY_CONTROLr, 
   4345                                                           vfp_key, 
   4346                                           _vfp_field_tbl[slice_idx + 1][1]); 
   4347             if (intraslice) {
   4348                 dbl_wide_key_sec = soc_reg_field_get(unit, VFP_KEY_CONTROLr,
   4349                             vfp_key, _vfp_slice_wide_mode_field[slice_idx + 1]);
   4350                 hw_sels.sec_slice[1].intraslice = 1;
   4351                 hw_sels.sec_slice[1].fpf2 = dbl_wide_key_sec;
   4352                 hw_sels.sec_slice[1].fpf3 = 0;                
   4353             }
   4354         }
   4355         /* Create a group based on HW qualifiers (or find existing) */
   4356         rv = _field_fb2_group_construct(unit, &hw_sels, intraslice, 
   4357                                         paired, fc, -1, 
   4358                                         _BCM_FIELD_STAGE_LOOKUP,
   4359                                         slice_idx);
   4360         if (BCM_FAILURE(rv)) {
   4361             goto cleanup;
   4362         }
   4363         /* Now go over the entries */
   4364         fs = stage_fc->slices[_FP_DEF_INST] + slice_idx;
   4365         if (fs->group_flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
   4366             ratio = 2;
   4367         } else {
   4368             ratio = 1;
   4369         }
   4370         prev_prio = -1;
   4371         for (idx = 0; idx < fs->entry_count / ratio; idx++) {
   4372             group_found = 0;
   4373             vfp_tcam_entry = soc_mem_table_idx_to_pointer
   4374                                  (unit, VFP_TCAMm, vfp_tcam_entry_t *, 
   4375                                   vfp_tcam_buf, idx + 
   4376                                   entries_per_slice * slice_idx);
   4377             if (soc_VFP_TCAMm_field32_get(unit, vfp_tcam_entry, 
   4378                                           VALIDf) == 0) {
   4379                 continue;
   4380             }
   4381             /* All ports are applicable to this entry */
   4382             SOC_PBMP_ASSIGN(entry_pbmp, PBMP_ALL(unit));
   4383             /* Search groups to find match */
   4384             fg = fc->groups;
   4385             while (fg != NULL) {
   4386                 /* Check if group is in this slice */
   4387                 fs = &fg->slices[0];
   4388                 if (fs->slice_number != slice_idx) {
   4389                     fg = fg->next;
   4390                     continue;
   4391                 }
   4392                 /* Check if entry_pbmp is a subset of group pbmp */
   4393                 SOC_PBMP_ASSIGN(temp_pbmp, fg->pbmp);
   4394                 SOC_PBMP_AND(temp_pbmp, entry_pbmp); 
   4395                 if (SOC_PBMP_EQ(temp_pbmp, entry_pbmp)) {
   4396                     group_found = 1;
   4397                     break;
   4398                 }
   4399                 fg = fg->next;
   4400             }
   4401             if (!group_found) {
   4402                 return BCM_E_INTERNAL; /* Should never happen */
   4403             }
   4404             /* Allocate memory for the entry */
   4405             rv = _bcm_field_entry_tcam_parts_count(unit, fg->stage_id,
   4406                                                    fg->flags, &parts_count);
   4407             if (BCM_FAILURE(rv)) {
   4408                 goto cleanup;
   4409             }
   4410             mem_sz = parts_count * sizeof (_field_entry_t);
   4411             _FP_XGS3_ALLOC(f_ent, mem_sz, "field entry");
   4412             if (f_ent == NULL) {
   4413                 rv = BCM_E_MEMORY;
   4414                 goto cleanup;
   4415             }
   4416             for (idx1 = 0; idx1 < _FP_POLICER_LEVEL_COUNT; idx1++) {
   4417                  f_ent->policer[idx1].pid = _FP_INVALID_INDEX;
   4418             }
   4419 
   4420             sal_memset(&f_ent_wb_info, 0, sizeof(_field_entry_wb_info_t));
   4421             f_ent_wb_info.sid = f_ent_wb_info.pid = -1;
   4422 
   4423             if (fc->l2warm) {
   4424                 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) {
   4425                    action_bmp.w = NULL;
   4426                    _FP_XGS3_ALLOC(action_bmp.w,
   4427                              SHR_BITALLOCSIZE(_bcmFieldActionNoParamCount),
   4428                              "Action No Param Bitmap");
   4429                    if (action_bmp.w == NULL) {
   4430                        rv = BCM_E_MEMORY;
   4431                        sal_free(f_ent);
   4432                        goto cleanup;
   4433                    }
   4434                 }
   4435                 f_ent_wb_info.action_bmp = &action_bmp;
   4436                 rv = _field_entry_info_retrieve(unit, fc, stage_fc,
   4437                                                 0, &prev_prio,
   4438                                                 &f_ent_wb_info);
   4439                 
   4440                 if (BCM_FAILURE(rv)) {
   4441                     sal_free(f_ent);
   4442                     goto cleanup;
   4443                 }
   4444             } else {
   4445                 _bcm_field_last_alloc_eid_incr(unit);
   4446             }
   4447             pri_tcam_idx = idx + entries_per_slice * slice_idx;
   4448             for (i = 0; i < parts_count; i++) {
   4449                 if (fc->l2warm) {
   4450                     /* Use retrieved EID */
   4451                     f_ent[i].eid = f_ent_wb_info.eid;
   4452                     /* Set retrieved dvp_type and svp_type */
   4453                     f_ent[i].dvp_type = f_ent_wb_info.dvp_type[i];
   4454                     f_ent[i].svp_type = f_ent_wb_info.svp_type[i];
   4455                     f_ent[i].prio = f_ent_wb_info.prio;
   4456                 } else {
   4457                     f_ent[i].eid = _bcm_field_last_alloc_eid_get(unit);
   4458                     f_ent[i].prio = (slice_idx << 10) | (entries_per_slice - idx);
   4459                 }
   4460                 f_ent[i].group = fg;
   4461                 rv = _bcm_field_tcam_part_to_entry_flags(unit, i, fg,
   4462                                                          &f_ent[i].flags);
   4463                 if (BCM_FAILURE(rv)) {
   4464                     sal_free(f_ent);
   4465                     goto cleanup;
   4466                 }
   4467                 if (f_ent_wb_info.color_independent) {
   4468                     f_ent[i].flags |= _FP_ENTRY_COLOR_INDEPENDENT;
   4469                 }
   4470                 rv = _bcm_field_entry_part_tcam_idx_get(unit, f_ent, 
   4471                                                         pri_tcam_idx,
   4472                                                         i, &part_index);
   4473                 if (BCM_FAILURE(rv)) {
   4474                     sal_free(f_ent);
   4475                     goto cleanup;
   4476                 }
   4477                 rv = _bcm_field_tcam_idx_to_slice_offset(unit, stage_fc,
   4478                                                          _FP_DEF_INST,
   4479                                                          part_index, 
   4480                                                          &slice_number,
   4481                                                 (int *)&f_ent[i].slice_idx);
   4482                 if (BCM_FAILURE(rv)) {
   4483                     sal_free(f_ent);
   4484                     goto cleanup;
   4485                 }
   4486                 f_ent[i].fs = stage_fc->slices[_FP_DEF_INST] + slice_number;
   4487                 if (0 == (f_ent[i].flags & _FP_ENTRY_SECOND_HALF)) {
   4488                     /* Decrement slice free entry count for primary 
   4489                        entries. */
   4490                     f_ent[i].fs->free_count--;
   4491                 }
   4492                 /* Assign entry to a slice */
   4493                 f_ent[i].fs->entries[f_ent[i].slice_idx] = f_ent + i;
   4494                 BCM_PBMP_OR(f_ent[i].fs->pbmp, fg->pbmp);
   4495                 f_ent[i].flags |= _FP_ENTRY_INSTALLED;
   4496 
   4497                 if (soc_VFP_TCAMm_field32_get(unit, vfp_tcam_entry, VALIDf) == 3) {
   4498                     f_ent[i].flags |= _FP_ENTRY_ENABLED;
   4499                 }
   4500 
   4501                 /* tcam_entry_buf must point to the entry part */
   4502                 vfp_tcam_entry_buf = (uint32 *)soc_mem_table_idx_to_pointer
   4503                                              (unit, VFP_TCAMm, 
   4504                                               vfp_tcam_entry_t *, 
   4505                                               vfp_tcam_buf, part_index);
   4506 
   4507                 /* Use this part to determine fg->qual_arr[i] */
   4508                 /* Iterate over the HW qualifiers and match offsets with
   4509                    the non-zero masks */
   4510                 for (j = 0; j < fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].size; j++) {
   4511                     qual_idx = fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].qid_arr[j];
   4512                     f_qual_arr = stage_fc->f_qual_arr[qual_idx];
   4513                     /* Loop over configurations of this qualifier */
   4514                     for (k = 0; k < f_qual_arr->conf_sz; k++) {
   4515                         if (_mask_is_set(unit, &f_qual_arr->conf_arr[k].offset,
   4516                              vfp_tcam_entry_buf, _BCM_FIELD_STAGE_LOOKUP)) {
   4517                             sal_memcpy(&fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][i].offset_arr[j],
   4518                                        &f_qual_arr->conf_arr[k].offset,
   4519                                        sizeof(f_qual_arr->conf_arr[k].offset));
   4520                             break;
   4521                         } 
   4522                     }
   4523                 }
   4524                 /* Get the actions associated with this part of the entry */
   4525                 vfp_policy_entry = soc_mem_table_idx_to_pointer
   4526                                                 (unit, VFP_POLICY_TABLEm, 
   4527                                                  vfp_policy_table_entry_t *, 
   4528                                                  vfp_policy_buf, part_index);
   4529                 rv = _field_fb_actions_recover(unit, (uint32 *)vfp_policy_entry,  
   4530                                                f_ent, i, VFP_POLICY_TABLEm,
   4531                                                &f_ent_wb_info);
   4532                 if (BCM_FAILURE(rv)) {
   4533                     sal_free(f_ent);
   4534                     goto cleanup;
   4535                 }
   4536                 if (action_bmp.w != NULL) {
   4537                    _FP_ACTION_BMP_FREE(action_bmp);
   4538                    action_bmp.w = NULL;
   4539                 }
   4540             }
   4541             /* Add to the group */
   4542             rv = _field_group_entry_add(unit, fg, f_ent);
   4543             if (BCM_FAILURE(rv)) {
   4544                 sal_free(f_ent);
   4545                 goto cleanup;
   4546             }
   4547             f_ent = NULL;
   4548         }
   4549         /* Free up the temporary slice group info */
   4550         if (fc->l2warm) {
   4551             _field_scache_slice_group_free(unit, fc, slice_idx);
   4552         }
   4553     }
   4554 
   4555     if (fc->l2warm) {
   4556 
   4557         /* Mark end of Slice Info */
   4558         if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) {
   4559             fc->scache_pos++;
   4560         }
   4561 
   4562         /* Group Slice Selectors */
   4563         if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) {
   4564             rv = (_field_group_slice_selectors_recover(unit,
   4565                         &buf[fc->scache_pos], stage_fc->stage_id));
   4566             if (BCM_FAILURE(rv)) {
   4567                 goto cleanup;
   4568             }
   4569         }
   4570 
   4571         temp = 0;
   4572         temp |= buf[fc->scache_pos];
   4573         fc->scache_pos++;
   4574         temp |= buf[fc->scache_pos] << 8;
   4575         fc->scache_pos++;
   4576         temp |= buf[fc->scache_pos] << 16;
   4577         fc->scache_pos++;
   4578         temp |= buf[fc->scache_pos] << 24;
   4579         fc->scache_pos++;
   4580         if (temp != _FIELD_VFP_DATA_END) {
   4581             fc->l2warm = 0;
   4582             rv = BCM_E_INTERNAL;
   4583         }
   4584 
   4585         if (NULL != buf1) {
   4586             temp = 0;
   4587             temp |= buf1[fc->scache_pos1];
   4588             fc->scache_pos1++;
   4589             temp |= buf1[fc->scache_pos1] << 8;
   4590             fc->scache_pos1++;
   4591             temp |= buf1[fc->scache_pos1] << 16;
   4592             fc->scache_pos1++;
   4593             temp |= buf1[fc->scache_pos1] << 24;
   4594             fc->scache_pos1++;
   4595             if (temp != _FIELD_VFP_DATA_END) {
   4596                 fc->l2warm = 0;
   4597                 rv = BCM_E_INTERNAL;
   4598             }
   4599         }
   4600 
   4601     }
   4602 cleanup:
   4603     if (vfp_tcam_buf) {
   4604         soc_cm_sfree(unit, vfp_tcam_buf);
   4605     }
   4606     if (vfp_policy_buf) {
   4607         soc_cm_sfree(unit, vfp_policy_buf);
   4608     }
   4609     if (action_bmp.w != NULL) {
   4610         _FP_ACTION_BMP_FREE(action_bmp);
   4611         action_bmp.w = NULL;
   4612     }
   4613     return rv;
   4614 }
   4615 #endif /* BCM_FIREBOLT2_SUPPORT */
   4616 #else
   4617 #define _field_fb_stage_reinit (NULL)
   4618 #endif /* BCM_WARM_BOOT_SUPPORT */
   4619 
   4620 #ifdef BCM_WARM_BOOT_SUPPORT
   4621 typedef enum
   4622 {
   4623     _fieldFBSliceModeSingle = 0,
   4624     _fieldFBSliceModeDouble = 1,
   4625     _fieldFBSliceModeTriple = 2,
   4626     _fieldFBSliceModeCount
   4627 } _field_fb_slice_mode_t;
   4628 
   4629 typedef struct
   4630 {
   4631     int8 fpf1;
   4632     int8 fpf2;
   4633     int8 fpf3;
   4634     int8 fpf4;
   4635 } _field_fb_sel_codes_t;
   4636 
   4637 STATIC int _field_fb_group_construct(int unit, _field_control_t *fc,
   4638     uint32 slice_mode, _field_stage_id_t stage_id, int slice_index,
   4639     bcm_port_t port, _field_fb_sel_codes_t *hw_sel_codes)
   4640 {
   4641     int rv;
   4642     _field_stage_t *stage_fc;
   4643     _field_group_t *fg_p;
   4644     int part_index;
   4645     bcm_field_group_t group_id;
   4646     int               priority = 0;
   4647     int               group_flags = 0;
   4648     uint16 qualifier_id;
   4649     _bcm_field_qual_info_t *stage_qualifier_p;
   4650     int config_index;
   4651     _bcm_field_qual_conf_t *config_p = NULL;
   4652     _bcm_field_selector_t selector;
   4653     int qualifier_id_index;
   4654     _bcm_field_group_qual_t *part_qualifier_p;
   4655     int old_qualifier_count;
   4656     int new_qualifier_count;
   4657     uint16 *qualifier_ids_p;
   4658     _bcm_field_qual_offset_t *qualifier_offsets_p;
   4659     _bcm_field_qual_offset_t *offset_p;
   4660     bcm_field_qset_t qset;
   4661     int action_res_id = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT;
   4662     int idx;
   4663     bcm_pbmp_t  group_pbmp;
   4664 
   4665     bcm_field_qset_t_init(&qset);
   4666 
   4667     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, stage_id, &stage_fc));
   4668 
   4669     for (fg_p = fc->groups; fg_p != NULL; fg_p = fg_p->next)
   4670     {
   4671         if (((slice_mode == _fieldFBSliceModeSingle) &&
   4672                 ((fg_p->flags & _FP_GROUP_SPAN_SINGLE_SLICE) == 0)) ||
   4673             ((slice_mode == _fieldFBSliceModeDouble) &&
   4674                 ((fg_p->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) == 0)) ||
   4675             ((slice_mode == _fieldFBSliceModeTriple) &&
   4676                 ((fg_p->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) == 0)))
   4677         {
   4678             /* This group isn't the same width as the one
   4679                we're reconstructing */
   4680 
   4681             continue;
   4682         }
   4683 
   4684         /* Check for primary slice numbers - there may be groups with the same
   4685            QSET but residing in different slices */
   4686         if (slice_index != fg_p->slices[0].slice_number) {
   4687             continue;
   4688         }
   4689 
   4690         /* See if selector codes match */
   4691 
   4692         for (part_index = 0; part_index <= slice_mode; ++part_index)
   4693         {
   4694             if ((fg_p->sel_codes[part_index].fpf1 !=
   4695                     hw_sel_codes[part_index].fpf1) ||
   4696                 (fg_p->sel_codes[part_index].fpf2 !=
   4697                     hw_sel_codes[part_index].fpf2) ||
   4698                 (fg_p->sel_codes[part_index].fpf3 !=
   4699                     hw_sel_codes[part_index].fpf3) ||
   4700                 (fg_p->sel_codes[part_index].fpf4 !=
   4701                     hw_sel_codes[part_index].fpf4))
   4702             {
   4703                 /* Selectors don't match */
   4704 
   4705                 break;
   4706             }
   4707         }
   4708 
   4709         if (part_index <= slice_mode)
   4710         {
   4711             /* Found a mismatch */
   4712 
   4713             continue;
   4714         }
   4715 
   4716         /*
   4717          * If we've gotten this far, everything matches, so add
   4718          * the port to the group's PBMP
   4719          */
   4720         BCM_PBMP_PORT_ADD(fg_p->pbmp, port);
   4721         BCM_PBMP_OR(fg_p->slices[0].pbmp, fg_p->pbmp);
   4722 
   4723             group_flags = 0;
   4724         if (fc->l2warm)
   4725         {
   4726             /* Get stored group ID and qset for level 2 */
   4727 
   4728             BCM_IF_ERROR_RETURN(_field_group_info_retrieve(unit, port,
   4729                                                            _FP_DEF_INST,
   4730                                                            &group_id,
   4731                                                            &priority,
   4732                                                            &action_res_id,
   4733                                                            &group_pbmp,
   4734                                                            NULL,
   4735                                                            &group_flags,
   4736                                                            &qset,
   4737                                                            fc
   4738                                                            )
   4739                                 );
   4740 
   4741             if (group_id != -1)
   4742             {
   4743                 sal_memcpy(&fg_p->qset, &qset, sizeof(bcm_field_qset_t));
   4744 
   4745                 fg_p->gid      = group_id;
   4746                 fg_p->priority = priority;
   4747                 fg_p->action_res_id = action_res_id;
   4748                 if (group_flags & _FP_GROUP_SELECT_AUTO_EXPANSION) {
   4749                     fg_p->flags = fg_p->flags | 
   4750                                        _FP_GROUP_SELECT_AUTO_EXPANSION;
   4751                 }
   4752             }
   4753         }
   4754 
   4755         return BCM_E_NONE;
   4756     }
   4757 
   4758     /* No existing groups match; create a new one */
   4759 
   4760     _FP_XGS3_ALLOC(fg_p, sizeof(_field_group_t), "field group");
   4761 
   4762     if (fg_p == NULL)
   4763     {
   4764         return BCM_E_MEMORY;
   4765     }
   4766 
   4767 
   4768     /* Initialize action res id and VMAP group to default */
   4769     action_res_id = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT;
   4770     for (idx = 0; idx < _FP_PAIR_MAX; idx++) {
   4771         fg_p->vmap_group[idx] = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT;
   4772     }
   4773 
   4774         group_flags = 0;
   4775         if (fc->l2warm)
   4776         {
   4777                 /* Get stored group ID and QSET */
   4778 
   4779             rv = _field_group_info_retrieve(unit, port, _FP_DEF_INST,
   4780                                             &group_id,
   4781                                             &priority,
   4782                                             &action_res_id,
   4783                                             &group_pbmp,
   4784                                             NULL,
   4785                                             &group_flags,
   4786                                             &qset,
   4787                                             fc
   4788                                             );
   4789 
   4790         if (group_id != -1)
   4791         {
   4792             sal_memcpy(&fg_p->qset, &qset, sizeof(bcm_field_qset_t));
   4793         } else {
   4794             sal_free(fg_p);
   4795             return rv;
   4796         }
   4797         }
   4798         else
   4799         {
   4800                 rv = _bcm_field_group_id_generate(unit, &group_id);
   4801                 priority = slice_index;
   4802         }
   4803 
   4804     if (BCM_FAILURE(rv))
   4805     {
   4806         sal_free(fg_p);
   4807 
   4808         return rv;
   4809     }
   4810 
   4811     fg_p->gid = group_id;
   4812     fg_p->priority = priority;
   4813     fg_p->action_res_id = action_res_id;
   4814     if (group_flags & _FP_GROUP_SELECT_AUTO_EXPANSION) {
   4815         fg_p->flags = fg_p->flags | _FP_GROUP_SELECT_AUTO_EXPANSION;
   4816     }
   4817     fg_p->stage_id = stage_id;
   4818 
   4819     BCM_PBMP_PORT_ADD(fg_p->pbmp, port);
   4820 
   4821     for (part_index = 0; part_index <= slice_mode; ++part_index)
   4822     {
   4823         fg_p->sel_codes[part_index].fpf1 = hw_sel_codes[part_index].fpf1;
   4824         fg_p->sel_codes[part_index].fpf2 = hw_sel_codes[part_index].fpf2;
   4825         fg_p->sel_codes[part_index].fpf3 = hw_sel_codes[part_index].fpf3;
   4826         fg_p->sel_codes[part_index].fpf4 = hw_sel_codes[part_index].fpf4;
   4827     }
   4828 
   4829     switch (slice_mode)
   4830     {
   4831     case _fieldFBSliceModeSingle:
   4832         fg_p->flags |= _FP_GROUP_SPAN_SINGLE_SLICE;
   4833         break;
   4834 
   4835     case _fieldFBSliceModeDouble:
   4836         fg_p->flags |= _FP_GROUP_SPAN_DOUBLE_SLICE;
   4837         break;
   4838 
   4839     case _fieldFBSliceModeTriple:
   4840         fg_p->flags |= _FP_GROUP_SPAN_TRIPLE_SLICE;
   4841         break;
   4842 
   4843     }
   4844 
   4845     /* Build qset from selectors */
   4846 
   4847     for (part_index = 0; part_index <= slice_mode; ++part_index)
   4848     {
   4849         for (qualifier_id = 0; qualifier_id < _bcmFieldQualifyCount;
   4850             ++qualifier_id)
   4851         {
   4852             stage_qualifier_p = stage_fc->f_qual_arr[qualifier_id];
   4853 
   4854             if (stage_qualifier_p == NULL)
   4855             {
   4856                 /* Qualifier does not exist in this stage */
   4857 
   4858                 continue;
   4859             }
   4860 
   4861             for (config_index = 0; config_index < stage_qualifier_p->conf_sz;
   4862                 ++config_index)
   4863             {
   4864                 config_p = stage_qualifier_p->conf_arr + config_index;
   4865 
   4866                 selector = config_p->selector;
   4867 
   4868                 /* Check for F1 match */
   4869 
   4870                 if ((selector.pri_sel == _bcmFieldSliceSelFpf1) &&
   4871                     (selector.pri_sel_val ==
   4872                         fg_p->sel_codes[part_index].fpf1))
   4873                 {
   4874                     break;
   4875                 }
   4876 
   4877                 /* Check for F2 match */
   4878 
   4879                 if ((selector.pri_sel == _bcmFieldSliceSelFpf2) &&
   4880                     (selector.pri_sel_val ==
   4881                         fg_p->sel_codes[part_index].fpf2))
   4882                 {
   4883                     break;
   4884                 }
   4885 
   4886                 /* Check for F3 match */
   4887 
   4888                 if ((selector.pri_sel == _bcmFieldSliceSelFpf3) &&
   4889                     (selector.pri_sel_val ==
   4890                         fg_p->sel_codes[part_index].fpf3))
   4891                 {
   4892                     break;
   4893                 }
   4894 
   4895                 /* Check for F4 match */
   4896 
   4897                 if ((selector.pri_sel == _bcmFieldSliceSelFpf4) &&
   4898                     (selector.pri_sel_val ==
   4899                         fg_p->sel_codes[part_index].fpf4))
   4900                 {
   4901                     break;
   4902                 }
   4903             }
   4904 
   4905             if (config_index < stage_qualifier_p->conf_sz)
   4906             {
   4907                 /* Found a match; add the qualifier to the qset */
   4908 
   4909                 BCM_FIELD_QSET_ADD(fg_p->qset, qualifier_id);
   4910 
   4911                 part_qualifier_p = &(fg_p->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part_index]);
   4912 
   4913                 for (qualifier_id_index = 0;
   4914                     qualifier_id_index < part_qualifier_p->size;
   4915                     ++qualifier_id_index)
   4916                 {
   4917                     if (part_qualifier_p->qid_arr[qualifier_id_index] ==
   4918                         qualifier_id)
   4919                     {
   4920                         /* Qualifier already in the qset */
   4921 
   4922                         break;
   4923                     }
   4924                 }
   4925 
   4926                 if (qualifier_id_index == part_qualifier_p->size)
   4927                 {
   4928                     /* Qualifier not already in the qset; add it */
   4929 
   4930                     old_qualifier_count = part_qualifier_p->size;
   4931                     new_qualifier_count = old_qualifier_count + 1;
   4932 
   4933                     qualifier_ids_p = NULL;
   4934                     qualifier_offsets_p = NULL;
   4935 
   4936                     _FP_XGS3_ALLOC(qualifier_ids_p, new_qualifier_count *
   4937                         sizeof (uint16), "Group qualifier ids");
   4938 
   4939                     if (qualifier_ids_p == NULL)
   4940                     {
   4941                         sal_free(fg_p);
   4942                         return BCM_E_MEMORY;
   4943                     }
   4944 
   4945                     _FP_XGS3_ALLOC(qualifier_offsets_p, new_qualifier_count *
   4946                         sizeof (_bcm_field_qual_offset_t),
   4947                         "Group qual offsets");
   4948 
   4949                     if (qualifier_offsets_p == NULL)
   4950                     {
   4951                         sal_free(fg_p);
   4952                         sal_free(qualifier_ids_p);
   4953                         return BCM_E_MEMORY;
   4954                     }
   4955 
   4956                     if (old_qualifier_count > 0)
   4957                     {
   4958                         /* Copy existing data */
   4959 
   4960                         sal_memcpy(qualifier_ids_p, part_qualifier_p->qid_arr,
   4961                             old_qualifier_count * sizeof (uint16));
   4962 
   4963                         sal_memcpy(qualifier_offsets_p,
   4964                             part_qualifier_p->offset_arr,
   4965                             old_qualifier_count *
   4966                                 sizeof (_bcm_field_qual_offset_t));
   4967 
   4968                         sal_free(part_qualifier_p->qid_arr);
   4969                         sal_free(part_qualifier_p->offset_arr);
   4970                     }
   4971 
   4972                     part_qualifier_p->qid_arr = qualifier_ids_p;
   4973                     part_qualifier_p->offset_arr = qualifier_offsets_p;
   4974 
   4975                     part_qualifier_p->qid_arr[old_qualifier_count] =
   4976                         qualifier_id;
   4977 
   4978                     offset_p = part_qualifier_p->offset_arr +
   4979                         old_qualifier_count;
   4980 
   4981                     sal_memcpy(offset_p, &config_p->offset,
   4982                                sizeof(config_p->offset));
   4983 
   4984                     part_qualifier_p->size = new_qualifier_count;
   4985 
   4986                     _field_qset_udf_bmap_reinit(unit,
   4987                                                 stage_fc,
   4988                                                 &fg_p->qset,
   4989                                                 qualifier_id
   4990                                                 );
   4991                 }
   4992             }
   4993         }
   4994     }
   4995 
   4996     /* Associate slice with group */
   4997 
   4998     if (fg_p->slices == NULL)
   4999     {
   5000         fg_p->slices = stage_fc->slices[_FP_DEF_INST] + slice_index;
   5001     }
   5002 
   5003     BCM_PBMP_OR(fg_p->slices[0].pbmp, fg_p->pbmp);
   5004 
   5005     if (fc->l2warm
   5006             && ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15)) {
   5007         if (group_flags & _FP_GROUP_LOOKUP_ENABLED) {
   5008             fg_p->flags = fg_p->flags | _FP_GROUP_LOOKUP_ENABLED;
   5009         }
   5010         if (group_flags & _FP_GROUP_WLAN) {
   5011             fg_p->flags = fg_p->flags | _FP_GROUP_WLAN;
   5012         }
   5013     } else {
   5014         fg_p->flags |= _FP_GROUP_LOOKUP_ENABLED;
   5015     }
   5016 
   5017     fg_p->next = fc->groups;
   5018     fc->groups = fg_p;
   5019 
   5020     return BCM_E_NONE;
   5021 }
   5022 
   5023 int _field_fb_slice_is_primary(int unit, int slice_index,
   5024     int *is_primary_p, int *slice_mode_p)
   5025 {
   5026     uint32 fp_slice_config_val;
   5027 
   5028     soc_field_t slice_mode_fields[16] =
   5029     {
   5030         SLICE_0_MODEf, SLICE_1_MODEf, SLICE_2_MODEf, SLICE_3_MODEf,
   5031         SLICE_4_MODEf, SLICE_5_MODEf, SLICE_6_MODEf, SLICE_7_MODEf,
   5032         SLICE_8_MODEf, SLICE_9_MODEf, SLICE_10_MODEf, SLICE_11_MODEf,
   5033         SLICE_12_MODEf, SLICE_13_MODEf, SLICE_14_MODEf, SLICE_15_MODEf
   5034     };
   5035 
   5036     BCM_IF_ERROR_RETURN(READ_FP_SLICE_CONFIGr(unit, &fp_slice_config_val));
   5037 
   5038     *slice_mode_p = soc_reg_field_get(unit, FP_SLICE_CONFIGr,
   5039         fp_slice_config_val, slice_mode_fields[slice_index]);
   5040 
   5041     if ((*slice_mode_p == _fieldFBSliceModeDouble && slice_index % 2 != 0) ||
   5042         (*slice_mode_p == _fieldFBSliceModeTriple && slice_index %4 != 0))
   5043     {
   5044         *is_primary_p = 0;
   5045     }
   5046     else
   5047     {
   5048         *is_primary_p = 1;
   5049     }
   5050 
   5051     return BCM_E_NONE;
   5052 }
   5053 
   5054 #define _FP_FB_IF_FAILURE_CLEANUP(op) \
   5055     rv = (op); if (BCM_FAILURE(rv)) goto cleanup;
   5056 
   5057 int _field_fb_stage_reinit(int unit, _field_control_t *fc,
   5058     _field_stage_t *stage_fc)
   5059 {
   5060     int rv, idx1;
   5061     int temp;
   5062     char *fp_tcam_buffer = NULL;
   5063     char *fp_port_field_sel_buffer = NULL;
   5064     int slice_index;
   5065     int slice_mode;
   5066     _field_slice_t *fs_p;
   5067     int entry_index;
   5068     bcm_port_t port;
   5069     _field_fb_sel_codes_t sel_codes[_fieldFBSliceModeCount];
   5070     _field_fb_sel_codes_t *sel_codes_p;
   5071     uint32 fp_f4_select_value;
   5072     char *fp_policy_table_buffer = NULL;
   5073     fp_tcam_entry_t *fp_tcam_entry_p;
   5074     bcm_pbmp_t entry_pbmp;
   5075     _field_group_t *fg_p;
   5076     _field_slice_t *group_slice_p;
   5077     int part_count;
   5078     _field_entry_t *entries_p;
   5079     int primary_tcam_index;
   5080     int part_slice_index;
   5081     int part_tcam_index;
   5082     int part_index;
   5083     fp_port_field_sel_entry_t *port_field_sel_entry_p;
   5084     _field_entry_t *entry_p = NULL;
   5085     _bcm_field_group_qual_t *part_qualifier_p;
   5086     int group_qualifier_index;
   5087     int qualifier_id;
   5088     _bcm_field_qual_info_t *stage_qualifier_p;
   5089     int config_index;
   5090     _bcm_field_qual_offset_t *config_offset_p;
   5091     _bcm_field_qual_offset_t *group_qualifier_offset_p;
   5092     fp_policy_table_entry_t *policy_entry_p;
   5093     uint32 ipbm_sel_value, pbm;
   5094     _bcm_field_selector_t config_selector;
   5095     int selector;
   5096     uint8 selector_value;
   5097     int multigroup;
   5098     int prev_prio;
   5099     int slice_is_primary;
   5100     uint8 *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0];
   5101     uint8 *buf1 = fc->scache_ptr[_FIELD_SCACHE_PART_1];
   5102     bcm_pbmp_t temp_pbmp;
   5103     _field_action_bmp_t action_bmp;
   5104     _field_entry_wb_info_t f_ent_wb_info;
   5105 
   5106     soc_field_t slice_f1_fields[16] =
   5107     {
   5108         SLICE0_F1f, SLICE1_F1f, SLICE2_F1f, SLICE3_F1f,
   5109         SLICE4_F1f, SLICE5_F1f, SLICE6_F1f, SLICE7_F1f,
   5110         SLICE8_F1f, SLICE9_F1f, SLICE10_F1f, SLICE11_F1f,
   5111         SLICE12_F1f, SLICE13_F1f, SLICE14_F1f, SLICE15_F1f,
   5112     };
   5113 
   5114     soc_field_t slice_f2_fields[16] =
   5115     {
   5116         SLICE0_F2f, SLICE1_F2f, SLICE2_F2f, SLICE3_F2f,
   5117         SLICE4_F2f, SLICE5_F2f, SLICE6_F2f, SLICE7_F2f,
   5118         SLICE8_F2f, SLICE9_F2f, SLICE10_F2f, SLICE11_F2f,
   5119         SLICE12_F2f, SLICE13_F2f, SLICE14_F2f, SLICE15_F2f,
   5120     };
   5121 
   5122     soc_field_t slice_f3_fields[16] =
   5123     {
   5124         SLICE0_F3f, SLICE1_F3f, SLICE2_F3f, SLICE3_F3f,
   5125         SLICE4_F3f, SLICE5_F3f, SLICE6_F3f, SLICE7_F3f,
   5126         SLICE8_F3f, SLICE9_F3f, SLICE10_F3f, SLICE11_F3f,
   5127         SLICE12_F3f, SLICE13_F3f, SLICE14_F3f, SLICE15_F3f,
   5128     };
   5129 
   5130     soc_field_t slice_f4_fields[16] =
   5131     {
   5132         SLICE_0_F4f, SLICE_1_F4f, SLICE_2_F4f, SLICE_3_F4f,
   5133         SLICE_4_F4f, SLICE_5_F4f, SLICE_6_F4f, SLICE_7_F4f,
   5134         SLICE_8_F4f, SLICE_9_F4f, SLICE_10_F4f, SLICE_11_F4f,
   5135         SLICE_12_F4f, SLICE_13_F4f, SLICE_14_F4f, SLICE_15_F4f,
   5136     };
   5137 
   5138     
   5139     /* Clear selector codes, set as invalid */
   5140     sal_memset(&sel_codes, (int8)_FP_SELCODE_DONT_CARE,
   5141         sizeof(_field_fb_sel_codes_t));
   5142 
   5143     /* Reset Action bitmap to NULL. */
   5144     action_bmp.w = NULL;
   5145 
   5146     fc->scache_pos = 0;
   5147     fc->scache_pos1 = 0;
   5148 
   5149     if (fc->l2warm) {
   5150         if ((fc->wb_recovered_version) > (fc->wb_current_version)) {
   5151             /* Notify the application with an event */
   5152             /* The application will then need to reconcile the 
   5153                version differences using the documented behavioral
   5154                differences on per module (handle) basis */
   5155             SOC_IF_ERROR_RETURN
   5156                 (soc_event_generate(unit, SOC_SWITCH_EVENT_WARM_BOOT_DOWNGRADE, 
   5157                                     BCM_MODULE_FIELD, (fc->wb_recovered_version), 
   5158                                     (fc->wb_current_version)));        
   5159         }
   5160 
   5161         fc->scache_pos += SOC_WB_SCACHE_CONTROL_SIZE;
   5162 
   5163         if(NULL != fc->scache_ptr[_FIELD_SCACHE_PART_1]) {
   5164             if ((fc->wb_recovered_version) > (fc->wb_current_version)) {
   5165                 /* Notify the application with an event */
   5166                 /* The application will then need to reconcile the
   5167                    version differences using the documented behavioral
   5168                    differences on per module (handle) basis */
   5169                 SOC_IF_ERROR_RETURN
   5170                     (soc_event_generate(unit, 
   5171                                         SOC_SWITCH_EVENT_WARM_BOOT_DOWNGRADE,
   5172                                         BCM_MODULE_FIELD, (fc->wb_recovered_version),
   5173                                         (fc->wb_current_version)));
   5174             }
   5175 
   5176             fc->scache_pos1 += SOC_WB_SCACHE_CONTROL_SIZE;
   5177         }
   5178     }
   5179 
   5180     if (stage_fc->stage_id != _BCM_FIELD_STAGE_INGRESS)
   5181     {
   5182         return BCM_E_PARAM;
   5183     }
   5184 
   5185     LOG_DEBUG(BSL_LS_BCM_FP,
   5186               (BSL_META_U(unit,
   5187                           "Beginning ingress stage recovery.\n")));
   5188 
   5189     if (fc->l2warm) {
   5190         rv = _field_scache_stage_hdr_chk(fc, _FIELD_IFP_DATA_START);
   5191         if (BCM_FAILURE(rv)) {
   5192             return (rv);
   5193         }
   5194     }
   5195 
   5196     /* Read TCAM into memory */
   5197 
   5198     _FP_FB_IF_FAILURE_CLEANUP(_field_table_read(unit, FP_TCAMm,
   5199         &fp_tcam_buffer, "FP_TCAM buffer"));
   5200 
   5201     /* Read FP_PORT_FIELD_SEL into memory */
   5202 
   5203     _FP_FB_IF_FAILURE_CLEANUP(_field_table_read(unit,
   5204         FP_PORT_FIELD_SELm, &fp_port_field_sel_buffer,
   5205         "FP_PORT_FIELD_SEL buffer"));
   5206 
   5207     /* Read FP_POLICY_TABLE table into memory */
   5208 
   5209     _FP_FB_IF_FAILURE_CLEANUP(_field_table_read(unit,
   5210         FP_POLICY_TABLEm, &fp_policy_table_buffer,
   5211         "FP_POLICY_TABLE"));
   5212 
   5213     /* Read F4 selectors */
   5214 
   5215     _FP_FB_IF_FAILURE_CLEANUP(READ_FP_F4_SELECTr(unit, &fp_f4_select_value));
   5216 
   5217     /* Recover range checkers */
   5218     rv = _field_range_check_reinit(unit, stage_fc, fc);
   5219     if (BCM_FAILURE(rv)) {
   5220         goto cleanup;
   5221     }
   5222 
   5223     /* Recover data qualifiers */
   5224     rv = _field_data_qual_recover(unit, fc, stage_fc);
   5225     if (BCM_FAILURE(rv)) {
   5226         goto cleanup;
   5227     }
   5228 
   5229     for (slice_index = 0; slice_index < stage_fc->tcam_slices; ++slice_index)
   5230     {
   5231         LOG_DEBUG(BSL_LS_BCM_FP,
   5232                   (BSL_META_U(unit,
   5233                               "  Checking slice %d...\n"),
   5234                    slice_index));
   5235 
   5236         _FP_FB_IF_FAILURE_CLEANUP(_field_fb_slice_is_primary(unit,
   5237             slice_index, &slice_is_primary, &slice_mode));
   5238 
   5239         if (!slice_is_primary)
   5240         {
   5241             /* Don't need selectors for second slice of double or for
   5242                second and third slices of triple */
   5243 
   5244             LOG_DEBUG(BSL_LS_BCM_FP,
   5245                       (BSL_META_U(unit,
   5246                                   "    Not a primary slice.\n")));
   5247 
   5248             continue;
   5249         }
   5250 
   5251         /* Check if the slice has any valid entries */
   5252 
   5253         fs_p = stage_fc->slices[_FP_DEF_INST] + slice_index;
   5254 
   5255         for (entry_index = 0; entry_index < fs_p->entry_count; ++entry_index)
   5256         {
   5257             fp_tcam_entry_p = soc_mem_table_idx_to_pointer(unit, FP_TCAMm,
   5258                 fp_tcam_entry_t *, fp_tcam_buffer,
   5259                 entry_index + fs_p->entry_count * slice_index);
   5260 
   5261             if (soc_FP_TCAMm_field32_get(unit, fp_tcam_entry_p, VALIDf) != 0)
   5262             {
   5263                /* There's at least one valid entry in the slice */
   5264 
   5265                 break;
   5266             }
   5267         }
   5268 
   5269         if ((entry_index == fs_p->entry_count) && !fc->l2warm)
   5270         {
   5271             /* No valid groups and entries in the slice */
   5272 
   5273             LOG_DEBUG(BSL_LS_BCM_FP,
   5274                       (BSL_META_U(unit,
   5275                                   "    No valid groups and entries in slice.\n")));
   5276 
   5277             continue;
   5278         }
   5279 
   5280         if (fc->l2warm)
   5281         {
   5282             /* Retrieve the group IDs in this slice */
   5283 
   5284             rv = _field_scache_slice_group_recover(unit, fc,
   5285                 slice_index, &multigroup);
   5286 
   5287             if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   5288                 fc->l2warm = 0;
   5289                 goto cleanup;
   5290             }
   5291             if (rv == BCM_E_NOT_FOUND) {
   5292                 rv = BCM_E_NONE;
   5293                 continue;
   5294             }
   5295         }
   5296 
   5297         PBMP_ALL_ITER(unit, port)
   5298         {
   5299             port_field_sel_entry_p = soc_mem_table_idx_to_pointer(
   5300                 unit, FP_PORT_FIELD_SELm, fp_port_field_sel_entry_t *,
   5301                 fp_port_field_sel_buffer, port);
   5302 
   5303             for (part_index = 0; part_index < COUNTOF(sel_codes); ++part_index) {
   5304                 sel_codes[part_index].fpf1 = _FP_SELCODE_DONT_CARE;
   5305                 sel_codes[part_index].fpf2 = _FP_SELCODE_DONT_CARE;
   5306                 sel_codes[part_index].fpf3 = _FP_SELCODE_DONT_CARE;
   5307                 sel_codes[part_index].fpf4 = _FP_SELCODE_DONT_CARE;
   5308             }
   5309 
   5310             for (part_index = 0; part_index <= slice_mode; ++part_index)
   5311             {
   5312                 sel_codes_p = sel_codes + part_index;
   5313 
   5314                 sel_codes_p->fpf1 = soc_FP_PORT_FIELD_SELm_field32_get(
   5315                     unit, port_field_sel_entry_p,
   5316                         slice_f1_fields[slice_index + part_index]);
   5317 
   5318                 sel_codes_p->fpf2 = soc_FP_PORT_FIELD_SELm_field32_get(
   5319                     unit, port_field_sel_entry_p,
   5320                         slice_f2_fields[slice_index + part_index]);
   5321 
   5322                 sel_codes_p->fpf3 = soc_FP_PORT_FIELD_SELm_field32_get(
   5323                     unit, port_field_sel_entry_p,
   5324                         slice_f3_fields[slice_index + part_index]);
   5325 
   5326                 sel_codes_p->fpf4 = soc_reg_field_get(unit, FP_F4_SELECTr,
   5327                     fp_f4_select_value, slice_f4_fields[slice_index +
   5328                         part_index]);
   5329             }
   5330 
   5331             _FP_FB_IF_FAILURE_CLEANUP(_field_fb_group_construct(unit,
   5332                 fc, slice_mode, stage_fc->stage_id, slice_index, port,
   5333                     sel_codes));
   5334         }
   5335 
   5336         /* Recover entries in this slice */
   5337 
   5338         fs_p = stage_fc->slices[_FP_DEF_INST] + slice_index;
   5339         prev_prio = -1;
   5340 
   5341         for (entry_index = 0; entry_index < fs_p->entry_count; ++entry_index)
   5342         {
   5343             fp_tcam_entry_p = soc_mem_table_idx_to_pointer(unit, FP_TCAMm,
   5344                 fp_tcam_entry_t *, fp_tcam_buffer, entry_index +
   5345                     slice_index * fs_p->entry_count);
   5346 
   5347             if (soc_FP_TCAMm_field32_get(unit, fp_tcam_entry_p, VALIDf) == 0)
   5348             {
   5349                 /* Skip empty entry */
   5350 
   5351                 continue;
   5352             }
   5353 
   5354             LOG_DEBUG(BSL_LS_BCM_FP,
   5355                       (BSL_META_U(unit,
   5356                                   "      Checking entry %d...\n"),
   5357                        entry_index));
   5358 
   5359             /* Determine pbmp for this entry */
   5360 
   5361             ipbm_sel_value =
   5362                 soc_FP_TCAMm_field32_get(unit, fp_tcam_entry_p, IPBM_SELf);
   5363             SOC_PBMP_CLEAR(entry_pbmp);
   5364 
   5365             if ((soc_FP_TCAMm_field32_get(unit, fp_tcam_entry_p,
   5366                 IPBM_SEL_MASKf) != 0) && (ipbm_sel_value != 0))
   5367             {
   5368                 SOC_PBMP_WORD_SET(entry_pbmp, 0, ipbm_sel_value);
   5369             }
   5370             else if ((fp_f4_select_value == 0) && 
   5371                      soc_FP_TCAMm_field32_get(unit, fp_tcam_entry_p, F4_MASKf)) 
   5372             {
   5373                 pbm = soc_FP_TCAMm_field32_get(unit, fp_tcam_entry_p, F4f) & 
   5374                       soc_FP_TCAMm_field32_get(unit, fp_tcam_entry_p, F4_MASKf);
   5375                 SOC_PBMP_PORT_ADD(entry_pbmp, pbm);
   5376             } 
   5377             else
   5378             {
   5379                 SOC_PBMP_ASSIGN(entry_pbmp, PBMP_ALL(unit));
   5380             }
   5381 
   5382             /* Find a matching group */
   5383 
   5384             for (fg_p = fc->groups; fg_p != NULL; fg_p = fg_p->next)
   5385             {
   5386                 group_slice_p = fg_p->slices;
   5387 
   5388                 if (group_slice_p->slice_number != slice_index)
   5389                 {
   5390                     /* Not this slice */
   5391 
   5392                     continue;
   5393                 }
   5394 
   5395                 SOC_PBMP_CLEAR(temp_pbmp);
   5396                 SOC_PBMP_ASSIGN(temp_pbmp, fg_p->pbmp);
   5397                 SOC_PBMP_OR(temp_pbmp, PBMP_LB(unit));
   5398                 SOC_PBMP_AND(temp_pbmp, entry_pbmp); 
   5399                 if (SOC_PBMP_EQ(temp_pbmp, entry_pbmp))
   5400                 {
   5401                     /* Found a match */
   5402 
   5403                     break;
   5404                 }
   5405 
   5406                 /* Check if entry pbmp is a subset of the group pbmp */
   5407 
   5408                 SOC_PBMP_ITER(entry_pbmp, port)
   5409                 {
   5410                     if (SOC_PBMP_MEMBER(fg_p->pbmp, port) == 0)
   5411                     {
   5412                         break;
   5413                     }
   5414                 }
   5415 
   5416                 if (port == SOC_PBMP_PORT_MAX)
   5417                 {
   5418                     /* Got all the way through with no mismatches */
   5419 
   5420                     break;
   5421                 }
   5422             }
   5423 
   5424             if (fg_p == NULL)
   5425             {
   5426                 /* This should never happen */
   5427 
   5428                 LOG_ERROR(BSL_LS_BCM_FP,
   5429                           (BSL_META_U(unit,
   5430                                       "Could not find a matching group for entry %d.\n"),
   5431                            entry_index));
   5432 
   5433                 return BCM_E_INTERNAL;
   5434             }
   5435 
   5436             /* Allocate the entry */
   5437 
   5438             _FP_FB_IF_FAILURE_CLEANUP(
   5439                 _bcm_field_entry_tcam_parts_count(unit, fg_p->stage_id,
   5440                                                   fg_p->flags, &part_count));
   5441 
   5442             entries_p = NULL;
   5443 
   5444             _FP_XGS3_ALLOC(entries_p, part_count * sizeof (_field_entry_t),
   5445                 "field entry");
   5446 
   5447             if (entries_p == NULL)
   5448             {
   5449                 rv = BCM_E_MEMORY;
   5450 
   5451                 goto cleanup;
   5452             }
   5453 
   5454             for (idx1 = 0; idx1 < _FP_POLICER_LEVEL_COUNT; idx1++) {
   5455                  entries_p->policer[idx1].pid = _FP_INVALID_INDEX;
   5456             }
   5457 
   5458 
   5459             LOG_DEBUG(BSL_LS_BCM_FP,
   5460                       (BSL_META_U(unit,
   5461                                   "        Entry matches group %d.\n"),
   5462                        fg_p->gid));
   5463 
   5464             sal_memset(&f_ent_wb_info, 0, sizeof(_field_entry_wb_info_t));
   5465             f_ent_wb_info.sid = -1;
   5466             f_ent_wb_info.pid = -1;
   5467 
   5468             if (fc->l2warm)
   5469             {
   5470                 if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) {
   5471                    action_bmp.w = NULL;
   5472                    _FP_XGS3_ALLOC(action_bmp.w,
   5473                              SHR_BITALLOCSIZE(_bcmFieldActionNoParamCount),
   5474                              "Action No Param Bitmap");
   5475                    if (action_bmp.w == NULL) {
   5476                        rv = BCM_E_MEMORY;
   5477                        sal_free(entries_p);
   5478                        goto cleanup;
   5479                    }
   5480                 }
   5481                 f_ent_wb_info.action_bmp = &action_bmp;
   5482 
   5483                 rv = _field_entry_info_retrieve(unit, fc, stage_fc,
   5484                     multigroup, &prev_prio, &f_ent_wb_info);
   5485 
   5486                 if (BCM_FAILURE(rv))
   5487                 {
   5488                     LOG_ERROR(BSL_LS_BCM_FP,
   5489                               (BSL_META_U(unit,
   5490                                           "Failed to retrieve entry info.")));
   5491 
   5492                     sal_free(entries_p);
   5493 
   5494                     goto cleanup;
   5495                 }
   5496                 if (action_bmp.w != NULL) {
   5497                    _FP_ACTION_BMP_FREE(action_bmp);
   5498                    action_bmp.w = NULL;
   5499                 }
   5500 
   5501             }
   5502             else
   5503             {
   5504                 _bcm_field_last_alloc_eid_incr(unit);
   5505 
   5506                 f_ent_wb_info.eid = _bcm_field_last_alloc_eid_get(unit);
   5507             }
   5508 
   5509             primary_tcam_index =
   5510                 slice_index * fs_p->entry_count + entry_index;
   5511 
   5512             for (part_index = 0; part_index < part_count; ++part_index)
   5513             {
   5514                 entry_p = entries_p + part_index;
   5515 
   5516                 entry_p->eid = f_ent_wb_info.eid;
   5517                 entry_p->group = fg_p;
   5518                 /* Set retrieved dvp_type and svp_type */
   5519                 entry_p->dvp_type = f_ent_wb_info.dvp_type[part_index];
   5520                 entry_p->svp_type = f_ent_wb_info.svp_type[part_index];
   5521 
   5522                 /* Set entry flags */
   5523                 rv = _bcm_field_tcam_part_to_entry_flags(unit, part_index,
   5524                         fg_p, &entry_p->flags);
   5525                 if (BCM_FAILURE(rv)) {
   5526                     sal_free(entries_p);
   5527                     goto cleanup;
   5528                 }
   5529 
   5530                 if (f_ent_wb_info.color_independent)
   5531                 {
   5532                     entry_p->flags |= _FP_ENTRY_COLOR_INDEPENDENT;
   5533                 }
   5534 
   5535                 /* Get index of entry in tcam */
   5536 
   5537                 rv = _bcm_field_entry_part_tcam_idx_get(unit, entries_p,
   5538                         primary_tcam_index, part_index, &part_tcam_index);
   5539                 if (BCM_FAILURE(rv)) {
   5540                     sal_free(entries_p);
   5541                     goto cleanup;
   5542                 }
   5543 
   5544                 /* Get slice and index within the slice */
   5545 
   5546                 rv = _bcm_field_tcam_idx_to_slice_offset(unit, stage_fc,
   5547                         _FP_DEF_INST, part_tcam_index, &part_slice_index,
   5548                         (int *) (&entry_p->slice_idx));
   5549                 if (BCM_FAILURE(rv)) {
   5550                     sal_free(entries_p);
   5551                     goto cleanup;
   5552                 }
   5553 
   5554                 /* Point the entry to its slice */
   5555 
   5556                 entry_p->fs = stage_fc->slices[_FP_DEF_INST] + part_slice_index;
   5557                 --entry_p->fs->free_count;
   5558 
   5559                 /* Set the slice pbmp */
   5560 
   5561                 BCM_PBMP_OR(entry_p->fs->pbmp, fg_p->pbmp);
   5562 
   5563                 /* Assign entry to slice */
   5564 
   5565                 entry_p->fs->entries[entry_p->slice_idx] = entry_p;
   5566                 entry_p->flags |= _FP_ENTRY_INSTALLED;
   5567 
   5568                 if (soc_FP_TCAMm_field32_get(unit, fp_tcam_entry_p, VALIDf) == 3) {
   5569                     entry_p->flags |= _FP_ENTRY_ENABLED;
   5570                 }
   5571                 /* Skip empty entry */
   5572                 fp_tcam_entry_p =
   5573                     (fp_tcam_entry_t *) soc_mem_table_idx_to_pointer(unit,
   5574                     FP_TCAMm, fp_tcam_entry_t *, fp_tcam_buffer,
   5575                     part_tcam_index);
   5576 
   5577                 part_qualifier_p = &(fg_p->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part_index]);
   5578 
   5579                 for (group_qualifier_index = 0;
   5580                     group_qualifier_index < part_qualifier_p->size;
   5581                     ++group_qualifier_index)
   5582                 {
   5583                     qualifier_id =
   5584                         part_qualifier_p->qid_arr[group_qualifier_index];
   5585 
   5586                     stage_qualifier_p = stage_fc->f_qual_arr[qualifier_id];
   5587 
   5588                     for (config_index = 0;
   5589                         config_index < stage_qualifier_p->conf_sz;
   5590                         ++config_index)
   5591                     {
   5592                         config_offset_p = &((stage_qualifier_p->conf_arr +
   5593                             config_index)->offset);
   5594 
   5595                         group_qualifier_offset_p =
   5596                             part_qualifier_p->offset_arr +
   5597                                 group_qualifier_index;
   5598 
   5599                         if (_mask_is_set(unit, config_offset_p,
   5600                             (uint32 *) fp_tcam_entry_p,
   5601                                 stage_fc->stage_id) != 0)
   5602                         {
   5603                             config_selector = stage_qualifier_p->
   5604                                 conf_arr[config_index].selector;
   5605 
   5606                             selector = config_selector.pri_sel;
   5607                             selector_value = config_selector.pri_sel_val;
   5608 
   5609                             if ((selector == _bcmFieldSliceSelFpf1 &&
   5610                                 selector_value == sel_codes[part_index].fpf1) ||
   5611                                 (selector == _bcmFieldSliceSelFpf2 &&
   5612                                 selector_value == sel_codes[part_index].fpf2) ||
   5613                                 (selector == _bcmFieldSliceSelFpf3 &&
   5614                                 selector_value == sel_codes[part_index].fpf3) ||
   5615                                 (selector == _bcmFieldSliceSelFpf4 &&
   5616                                 selector_value == sel_codes[part_index].fpf4))
   5617                             {
   5618                                 /* This qualifier exists in this entry */
   5619 
   5620                                 *group_qualifier_offset_p = *config_offset_p;
   5621 
   5622                                 /* No need to check more configs */
   5623 
   5624                                 break;
   5625                             }
   5626                         }
   5627                     }
   5628                 }
   5629 
   5630                 /* Get the actions for this part of the entry */
   5631 
   5632                 policy_entry_p = soc_mem_table_idx_to_pointer(unit,
   5633                     FP_POLICY_TABLEm, fp_policy_table_entry_t *,
   5634                     fp_policy_table_buffer, part_tcam_index);
   5635 
   5636                 rv = _field_fb_actions_recover(unit,
   5637                     (uint32 *)policy_entry_p, entries_p, part_index,
   5638                     FP_POLICY_TABLEm, &f_ent_wb_info);
   5639                 if (BCM_FAILURE(rv)) {
   5640                     sal_free(entries_p);
   5641                     goto cleanup;
   5642                 }
   5643 
   5644                 entry_p->prio = fc->l2warm ? f_ent_wb_info.prio :
   5645                     (slice_index << 10) | (fs_p->entry_count - entry_index);
   5646 
   5647             }
   5648             LOG_DEBUG(BSL_LS_BCM_FP,
   5649                       (BSL_META_U(unit,
   5650                                   "        Entry id = %d, priority = %d.\n"),
   5651                        entries_p->eid,
   5652                        entries_p->prio));
   5653 
   5654             /* Add the entry to the group */
   5655 
   5656             rv = _field_group_entry_add(unit, fg_p, entries_p);
   5657             
   5658             if (rv != BCM_E_NONE) {
   5659                 sal_free(entries_p);
   5660             
   5661                 goto cleanup;
   5662             }
   5663         }
   5664 
   5665         if (fc->l2warm)
   5666         {
   5667             _field_scache_slice_group_free(unit, fc, slice_index);
   5668         }
   5669     }
   5670 
   5671     if (fc->l2warm) {
   5672 
   5673         /* Mark end of Slice Info */
   5674         if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) {
   5675             fc->scache_pos++;
   5676         }
   5677 
   5678         /* Group Slice Selectors */
   5679         if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_15) {
   5680             rv = (_field_group_slice_selectors_recover(unit,
   5681                         &buf[fc->scache_pos], stage_fc->stage_id));
   5682             if (BCM_FAILURE(rv)) {
   5683                 goto cleanup;
   5684             }
   5685         }
   5686 
   5687         temp = 0;
   5688         temp |= buf[fc->scache_pos];
   5689         fc->scache_pos++;
   5690         temp |= buf[fc->scache_pos] << 8;
   5691         fc->scache_pos++;
   5692         temp |= buf[fc->scache_pos] << 16;
   5693         fc->scache_pos++;
   5694         temp |= buf[fc->scache_pos] << 24;
   5695         fc->scache_pos++;
   5696         if (temp != _FIELD_IFP_DATA_END) {
   5697             fc->l2warm = 0;
   5698             rv = BCM_E_INTERNAL;
   5699         }
   5700 
   5701         if (NULL != buf1) {
   5702             temp = 0;
   5703             temp |= buf1[fc->scache_pos1];
   5704             fc->scache_pos1++;
   5705             temp |= buf1[fc->scache_pos1] << 8;
   5706             fc->scache_pos1++;
   5707             temp |= buf1[fc->scache_pos1] << 16;
   5708             fc->scache_pos1++;
   5709             temp |= buf1[fc->scache_pos1] << 24;
   5710             fc->scache_pos1++;
   5711             if (temp != _FIELD_IFP_DATA_END) {
   5712                 fc->l2warm = 0;
   5713                 rv = BCM_E_INTERNAL;
   5714             }
   5715         }
   5716     }
   5717 
   5718     LOG_DEBUG(BSL_LS_BCM_FP,
   5719               (BSL_META_U(unit,
   5720                           "Ingress stage recovery complete.\n")));
   5721 
   5722 cleanup:
   5723     if (fp_tcam_buffer != NULL)
   5724     {
   5725         soc_cm_sfree(unit, fp_tcam_buffer);
   5726     }
   5727     if (fp_port_field_sel_buffer != NULL) 
   5728     {
   5729         soc_cm_sfree(unit, fp_port_field_sel_buffer);
   5730     }
   5731     if (fp_policy_table_buffer != NULL) 
   5732     {
   5733         soc_cm_sfree(unit, fp_policy_table_buffer);
   5734     }
   5735     if (action_bmp.w != NULL) {
   5736         _FP_ACTION_BMP_FREE(action_bmp);
   5737         action_bmp.w = NULL;
   5738     }
   5739 
   5740     LOG_DEBUG(BSL_LS_BCM_FP,
   5741               (BSL_META_U(unit,
   5742                           "Leaving ingress stage recovery.\n")));
   5743 
   5744     return rv;
   5745 }
   5746 #else
   5747 #define _field_fb_stage_reinit (NULL)
   5748 #endif /* BCM_WARM_BOOT_SUPPORT */
   5749 
   5750 /*
   5751  * Function:
   5752  *     _field_fb_tcam_policy_mem_get
   5753  *
   5754  * Purpose:
   5755  *     Get tcam & policy memories for a specific chip pipeline stage.
   5756  *
   5757  * Parameters:
   5758  *     unit       -   (IN)BCM device number.
   5759  *     stage_id   -   (IN)FP stage pipeline id. 
   5760  *     tcam_mem   -   (IN)Tcam  memory id.
   5761  *     policy_mem -   (IN)Policy memory id.
   5762  *     
   5763  * Returns:
   5764  *     BCM_E_XXX
   5765  */
   5766 int
   5767 _field_fb_tcam_policy_mem_get(int unit, _field_stage_id_t stage_id, 
   5768                               soc_mem_t *tcam_mem, soc_mem_t *policy_mem)
   5769 {
   5770 
   5771     /* Input parameters check. */
   5772     if ((NULL == tcam_mem) || (NULL == policy_mem)) {
   5773         return (BCM_E_PARAM);
   5774     }
   5775 
   5776     if (_BCM_FIELD_STAGE_INGRESS == stage_id) {
   5777         *tcam_mem = FP_TCAMm;
   5778         *policy_mem= FP_POLICY_TABLEm;
   5779 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
   5780     } else if (soc_feature(unit, soc_feature_field_multi_stage)) {
   5781         if (_BCM_FIELD_STAGE_EGRESS == stage_id) {
   5782             *tcam_mem = EFP_TCAMm;
   5783             *policy_mem = EFP_POLICY_TABLEm;
   5784         } else if (_BCM_FIELD_STAGE_LOOKUP== stage_id) {
   5785             *tcam_mem = VFP_TCAMm;
   5786             *policy_mem = VFP_POLICY_TABLEm;
   5787         } else {
   5788             /* Unknown stage specified */
   5789             (*policy_mem) = (*tcam_mem) = INVALIDm; 
   5790             return (BCM_E_PARAM);
   5791         }
   5792 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
   5793     } else {
   5794         /* Not ingress stage specified while multi stage is not enabled */
   5795         (*policy_mem) = (*tcam_mem) = INVALIDm; 
   5796         return (BCM_E_UNAVAIL);
   5797     }
   5798     return (BCM_E_NONE);
   5799 }
   5800 
   5801 #ifdef BCM_FIREBOLT2_SUPPORT 
   5802 /*
   5803  * Function:
   5804  *     _field_fb2_lookup_qualifiers_init
   5805  * Purpose:
   5806  *     Initialize device stage lookup qaualifiers 
   5807  *     select codes & offsets
   5808  * Parameters:
   5809  *     unit       - (IN) BCM device number.
   5810  *     stage_fc   - (IN) Field Processor stage control structure. 
   5811  *
   5812  * Returns:
   5813  *     BCM_E_NONE
   5814  */
   5815 STATIC int
   5816 _field_fb2_lookup_qualifiers_init(int unit, _field_stage_t *stage_fc)
   5817 {
   5818     int           rv;              /* Operation return status.  */
   5819     _FP_QUAL_DECL;
   5820     _key_fld_ = KEYf;
   5821 
   5822     /* Input parameters check. */
   5823     if (NULL == stage_fc) {
   5824         return (BCM_E_PARAM);
   5825     }
   5826 
   5827     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyStageLookup,
   5828                  _bcmFieldSliceSelDisable, 0, 0, 0);
   5829     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIp4,
   5830                  _bcmFieldSliceSelDisable, 0, 0, 0);
   5831     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIp6,
   5832                  _bcmFieldSliceSelDisable, 0, 0, 0);
   5833 
   5834     /*
   5835      *  Enable the overlay of Sender Ethernet Address onto 
   5836      *  MACSA on ARP/RARP packets.
   5837      */
   5838     rv = soc_reg_field32_modify(unit, ING_CONFIGr, REG_PORT_ANY,
   5839                                 ARP_VALIDATION_ENf, 1);
   5840     BCM_IF_ERROR_RETURN(rv);
   5841 
   5842     /* FPF3 */
   5843     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerTpid,
   5844                  _bcmFieldSliceSelFpf3, 0, 0, 2);
   5845     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterTpid,
   5846                  _bcmFieldSliceSelFpf3, 0, 0, 2);
   5847     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2Format,
   5848                  _bcmFieldSliceSelFpf3, 0, 4, 2);
   5849     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyHiGigProxy,
   5850                  _bcmFieldSliceSelFpf3, 0, 6, 1);
   5851     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyHiGig,
   5852                  _bcmFieldSliceSelFpf3, 0, 7, 1);
   5853     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyEtherType,
   5854                  _bcmFieldSliceSelFpf3, 0, 8, 16);
   5855 
   5856     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerTpid,
   5857                  _bcmFieldSliceSelFpf3, 1, 0, 2);
   5858     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterTpid,
   5859                  _bcmFieldSliceSelFpf3, 1, 0, 2);
   5860     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2Format,
   5861                  _bcmFieldSliceSelFpf3, 1, 4, 2);
   5862     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyHiGigProxy,
   5863                  _bcmFieldSliceSelFpf3, 1, 6, 1);
   5864     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyHiGig,
   5865                  _bcmFieldSliceSelFpf3, 1, 7, 1);
   5866     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4SrcPort,
   5867                  _bcmFieldSliceSelFpf3, 1, 8, 16);
   5868 
   5869     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerTpid,
   5870                  _bcmFieldSliceSelFpf3, 2, 0, 2);
   5871     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterTpid,
   5872                  _bcmFieldSliceSelFpf3, 2, 0, 2);
   5873     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2Format,
   5874                  _bcmFieldSliceSelFpf3, 2, 4, 2);
   5875     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyHiGigProxy,
   5876                  _bcmFieldSliceSelFpf3, 2, 6, 1);
   5877     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyHiGig,
   5878                  _bcmFieldSliceSelFpf3, 2, 7, 1);
   5879     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort,
   5880                  _bcmFieldSliceSelFpf3, 2, 8, 16);
   5881 
   5882     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerTpid,
   5883                  _bcmFieldSliceSelFpf3, 3, 0, 2);
   5884     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterTpid,
   5885                  _bcmFieldSliceSelFpf3, 3, 0, 2);
   5886     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2Format,
   5887                  _bcmFieldSliceSelFpf3, 3, 4, 2);
   5888     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyHiGigProxy,
   5889                  _bcmFieldSliceSelFpf3, 3, 6, 1);
   5890     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyHiGig,
   5891                  _bcmFieldSliceSelFpf3, 3, 7, 1);
   5892     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlan,
   5893                  _bcmFieldSliceSelFpf3, 3, 8, 16);
   5894     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanPri,
   5895                  _bcmFieldSliceSelFpf3, 3, 8, 3);
   5896     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanCfi,
   5897                  _bcmFieldSliceSelFpf3, 3, 11, 1);
   5898     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanId,
   5899                  _bcmFieldSliceSelFpf3, 3, 12, 12);
   5900 
   5901     /* FPF2 */
   5902     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTtl,
   5903                  _bcmFieldSliceSelFpf2, 0, 24, 8);
   5904     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTcpControl,
   5905                  _bcmFieldSliceSelFpf2, 0, 32, 6);
   5906     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpFrag,
   5907                  _bcmFieldSliceSelFpf2, 0, 38, 2);
   5908     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP,
   5909                  _bcmFieldSliceSelFpf2, 0, 40, 8);
   5910     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort,
   5911                  _bcmFieldSliceSelFpf2, 0, 48, 16);
   5912     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4SrcPort,
   5913                  _bcmFieldSliceSelFpf2, 0, 64, 16);
   5914     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol,
   5915                  _bcmFieldSliceSelFpf2, 0, 80, 8);
   5916     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp,
   5917                  _bcmFieldSliceSelFpf2, 0, 88, 32);
   5918     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp,
   5919                  _bcmFieldSliceSelFpf2, 0, 120, 32);
   5920 
   5921     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp6,
   5922                  _bcmFieldSliceSelFpf2, 1, 24, 128);
   5923 
   5924     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp6,
   5925                  _bcmFieldSliceSelFpf2, 2, 24, 128);
   5926 
   5927     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyEtherType,
   5928                  _bcmFieldSliceSelFpf2, 3, 40, 16);
   5929     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcMac,
   5930                  _bcmFieldSliceSelFpf2, 3, 56, 48);
   5931     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstMac,
   5932                  _bcmFieldSliceSelFpf2, 3, 104, 48);
   5933 
   5934     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP,
   5935                  _bcmFieldSliceSelFpf2, 4, 24, 8);
   5936     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol,
   5937                  _bcmFieldSliceSelFpf2, 4, 32, 8);
   5938     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp,
   5939                  _bcmFieldSliceSelFpf2, 4, 40, 32);
   5940     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp,
   5941                  _bcmFieldSliceSelFpf2, 4, 72, 32);
   5942     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcMac,
   5943                  _bcmFieldSliceSelFpf2, 4, 104, 48);
   5944 
   5945     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP,
   5946                  _bcmFieldSliceSelFpf2, 5, 24, 8);
   5947     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol,
   5948                  _bcmFieldSliceSelFpf2, 5, 32, 8);
   5949     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp,
   5950                  _bcmFieldSliceSelFpf2, 5, 40, 32);
   5951     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp,
   5952                  _bcmFieldSliceSelFpf2, 5, 72, 32);
   5953     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstMac,
   5954                  _bcmFieldSliceSelFpf2, 5, 104, 48);
   5955 
   5956     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp6High,
   5957                  _bcmFieldSliceSelFpf2, 6, 24, 64);
   5958     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp6High,
   5959                  _bcmFieldSliceSelFpf2, 6, 88, 64);
   5960 
   5961     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySnap,
   5962                  _bcmFieldSliceSelFpf2, 7, 88, 40);
   5963     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyLlc,
   5964                  _bcmFieldSliceSelFpf2, 7, 128, 24);
   5965     /* FPF1 */
   5966     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocolCommon,
   5967                  _bcmFieldSliceSelFpf1, 0, 152, 3);
   5968     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan,
   5969                  _bcmFieldSliceSelFpf1, 0, 155, 16);
   5970     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri,
   5971                  _bcmFieldSliceSelFpf1, 0, 155, 3);
   5972     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi,
   5973                  _bcmFieldSliceSelFpf1, 0, 158, 1);
   5974     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId,
   5975                  _bcmFieldSliceSelFpf1, 0, 159, 12);
   5976     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyVlanFormat,
   5977                  _bcmFieldSliceSelFpf1, 0, 171, 2);
   5978     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInPort,
   5979                  _bcmFieldSliceSelFpf1, 0, 173, 5);
   5980     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInterfaceClassPort,
   5981                  _bcmFieldSliceSelFpf1, 0, 178, 4);
   5982     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpType,
   5983                  _bcmFieldSliceSelFpf1, 0, 182, 2);
   5984 
   5985     _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyDSCP,
   5986                      _bcmFieldDevSelIntrasliceVfpKey, 0,
   5987                      _bcmFieldSliceSelFpf2, 0, 
   5988                      _bcmFieldSliceSelDisable, 0, 1,
   5989                      0, 8, 0, 0, 0, 0, 0);
   5990     _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort,
   5991                      _bcmFieldDevSelIntrasliceVfpKey, 0,
   5992                      _bcmFieldSliceSelFpf2, 0, 
   5993                      _bcmFieldSliceSelDisable, 0, 1,
   5994                      8, 16, 0, 0, 0, 0, 0);
   5995     _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyTtl,
   5996                      _bcmFieldDevSelIntrasliceVfpKey, 0,
   5997                      _bcmFieldSliceSelFpf2, 0, 
   5998                      _bcmFieldSliceSelDisable, 0, 1,
   5999                      24, 8, 0, 0, 0, 0, 0);
   6000     _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyTcpControl,
   6001                      _bcmFieldDevSelIntrasliceVfpKey, 0,
   6002                      _bcmFieldSliceSelFpf2, 0, 
   6003                      _bcmFieldSliceSelDisable, 0, 1,
   6004                      32, 6, 0, 0, 0, 0, 0);
   6005     _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyIpFrag,
   6006                      _bcmFieldDevSelIntrasliceVfpKey, 0,
   6007                      _bcmFieldSliceSelFpf2, 0, 
   6008                      _bcmFieldSliceSelDisable, 0, 1,
   6009                      38, 2, 0, 0, 0, 0, 0);
   6010     _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyL4SrcPort,
   6011                      _bcmFieldDevSelIntrasliceVfpKey, 0,
   6012                      _bcmFieldSliceSelFpf2, 0, 
   6013                      _bcmFieldSliceSelDisable, 0, 1,
   6014                      64, 16, 0, 0, 0, 0, 0);
   6015     _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol,
   6016                      _bcmFieldDevSelIntrasliceVfpKey, 0,
   6017                      _bcmFieldSliceSelFpf2, 0, 
   6018                      _bcmFieldSliceSelDisable, 0, 1,
   6019                      80, 8, 0, 0, 0, 0, 0);
   6020     _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyDstIp,
   6021                      _bcmFieldDevSelIntrasliceVfpKey, 0,
   6022                      _bcmFieldSliceSelFpf2, 0, 
   6023                      _bcmFieldSliceSelDisable, 0, 1,
   6024                      88, 32, 0, 0, 0, 0, 0);
   6025     _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifySrcIp,
   6026                      _bcmFieldDevSelIntrasliceVfpKey, 0,
   6027                      _bcmFieldSliceSelFpf2, 0, 
   6028                      _bcmFieldSliceSelDisable, 0, 1,
   6029                      120, 32, 0, 0, 0, 0, 0);
   6030     _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyEtherType,
   6031                      _bcmFieldDevSelIntrasliceVfpKey, 0,
   6032                      _bcmFieldSliceSelFpf2, 0, 
   6033                      _bcmFieldSliceSelDisable, 0, 1,
   6034                      152, 16, 0, 0, 0, 0, 0);
   6035 
   6036     _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyDSCP,
   6037                      _bcmFieldDevSelIntrasliceVfpKey, 1,
   6038                      _bcmFieldSliceSelFpf2, 1, 
   6039                      _bcmFieldSliceSelDisable, 0, 1,
   6040                      0, 8, 0, 0, 0, 0, 0);
   6041     _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort,
   6042                      _bcmFieldDevSelIntrasliceVfpKey, 1,
   6043                      _bcmFieldSliceSelFpf2, 1, 
   6044                      _bcmFieldSliceSelDisable, 0, 1,
   6045                      8, 16, 0, 0, 0, 0, 0);
   6046     _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifySrcIp6,
   6047                      _bcmFieldDevSelIntrasliceVfpKey, 1,
   6048                      _bcmFieldSliceSelFpf2, 1, 
   6049                      _bcmFieldSliceSelDisable, 0, 1,
   6050                      24, 128, 0, 0, 0, 0, 0);
   6051     _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyEtherType,
   6052                      _bcmFieldDevSelIntrasliceVfpKey, 1,
   6053                      _bcmFieldSliceSelFpf2, 1, 
   6054                      _bcmFieldSliceSelDisable, 0, 1,
   6055                      152, 16, 0, 0, 0, 0, 0);
   6056     _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol,
   6057                      _bcmFieldDevSelIntrasliceVfpKey, 1,
   6058                      _bcmFieldSliceSelFpf2, 1, 
   6059                      _bcmFieldSliceSelDisable, 0, 1,
   6060                      168, 8, 0, 0, 0, 0, 0);
   6061     _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyTtl,
   6062                      _bcmFieldDevSelIntrasliceVfpKey, 1,
   6063                      _bcmFieldSliceSelFpf2, 1, 
   6064                      _bcmFieldSliceSelDisable, 0, 1,
   6065                      176, 8, 0, 0, 0, 0, 0);
   6066     return (BCM_E_NONE);
   6067 }
   6068 
   6069 /*
   6070  * Function:
   6071  *     _field_fb2_egress_qualifiers_init
   6072  * Purpose:
   6073  *     Initialize device stage egress qaualifiers 
   6074  *     select codes & offsets
   6075  * Parameters:
   6076  *     unit       - (IN) BCM device number.
   6077  *     stage_fc   - (IN) Field Processor stage control structure. 
   6078  *
   6079  * Returns:
   6080  *     BCM_E_NONE
   6081  */
   6082 STATIC int
   6083 _field_fb2_egress_qualifiers_init(int unit, _field_stage_t *stage_fc)
   6084 {
   6085     _FP_QUAL_DECL;
   6086     _key_fld_ = KEYf;
   6087 
   6088     /* Input parameters check. */
   6089     if (NULL == stage_fc) {
   6090         return (BCM_E_PARAM);
   6091     }
   6092 
   6093     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyStageEgress,
   6094                  _bcmFieldSliceSelDisable, 0, 0, 0);
   6095 
   6096     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2Format,
   6097                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 0, 2);
   6098     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyEtherType,
   6099                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 2, 16);
   6100     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcMac,
   6101                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 18, 48);
   6102     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstMac,
   6103                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 66, 48);
   6104     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlan,
   6105                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 114, 16);
   6106     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanId,
   6107                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 114, 12);
   6108     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanCfi,
   6109                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 126, 1);
   6110     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanPri,
   6111                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 127, 3);
   6112     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInPort,
   6113                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 146, 5);
   6114     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3Routable,
   6115                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 151, 1);
   6116     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMirrorCopy,
   6117                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 152, 1);
   6118     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan,
   6119                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 153, 16);
   6120     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId,
   6121                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 153, 12);
   6122     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi,
   6123                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 165, 1);
   6124     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri,
   6125                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 166, 3);
   6126     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyVlanFormat,
   6127                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 169, 2);
   6128     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstHiGig,
   6129                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 171, 1);
   6130     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInterfaceClassPort,
   6131                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 172, 4);
   6132     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOutPort,
   6133                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY4, 176, 5);
   6134 
   6135     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpFrag,
   6136                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 0, 2);
   6137     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTcpControl,
   6138                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 2, 6);
   6139     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort,
   6140                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 8, 16);
   6141     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4SrcPort,
   6142                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 24, 16);
   6143     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTtl,
   6144                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 40, 8);
   6145     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol,
   6146                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 61, 8);
   6147     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp,
   6148                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 69, 32);
   6149     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp,
   6150                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 101, 32);
   6151     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpType,
   6152                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 133, 1);
   6153     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTos,
   6154                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 134, 8);
   6155     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInPort,
   6156                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 146, 5);
   6157     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3Routable,
   6158                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 151, 1);
   6159     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMirrorCopy,
   6160                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 152, 1);
   6161     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan,
   6162                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 153, 16);
   6163     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId,
   6164                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 153, 12);
   6165     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi,
   6166                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 165, 1);
   6167     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri,
   6168                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 166, 3);
   6169     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyVlanFormat,
   6170                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 169, 2);
   6171     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstHiGig,
   6172                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 171, 1);
   6173     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInterfaceClassPort,
   6174                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 172, 4);
   6175     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOutPort,
   6176                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 176, 5);
   6177     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIp4,
   6178                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY1, 0, 0);
   6179 
   6180     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol,
   6181                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 0, 8);
   6182     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp6,
   6183                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 8, 128);
   6184     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpType,
   6185                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 136, 1);
   6186     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP,
   6187                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 137, 8);
   6188     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInPort,
   6189                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 146, 5);
   6190     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3Routable,
   6191                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 151, 1);
   6192     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMirrorCopy,
   6193                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 152, 1);
   6194     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan,
   6195                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 153, 16);
   6196     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId,
   6197                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 153, 12);
   6198     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi,
   6199                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 165, 1);
   6200     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri,
   6201                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 166, 3);
   6202     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyVlanFormat,
   6203                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 169, 2);
   6204     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstHiGig,
   6205                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 171, 1);
   6206     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInterfaceClassPort,
   6207                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 172, 4);
   6208     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOutPort,
   6209                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 176, 5);
   6210     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIp6,
   6211                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY2, 0, 0);
   6212 
   6213     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpFrag,
   6214                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY3, 0, 2);
   6215     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTcpControl,
   6216                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY3, 2, 6);
   6217     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort,
   6218                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY3, 8, 16);
   6219     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4SrcPort,
   6220                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY3, 24, 16);
   6221     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTtl,
   6222                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY3, 40, 8);
   6223     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp6,
   6224                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY3, 48, 128);
   6225     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp6,
   6226                  _bcmFieldSliceSelFpf3, _BCM_FIELD_EFP_KEY3, 0, 0);
   6227 
   6228     return (BCM_E_NONE);
   6229 }
   6230 #endif /*BCM_FIREBOLT2_SUPPORT */
   6231 
   6232 
   6233 /*
   6234  * Function:
   6235  *     _field_fb_ingress_qualifiers_init
   6236  * Purpose:
   6237  *     Initialize device stage ingress qaualifiers 
   6238  *     select codes & offsets
   6239  * Parameters:
   6240  *     unit       - (IN) BCM device number.
   6241  *     stage_fc   - (IN) Field Processor stage control structure. 
   6242  *
   6243  * Returns:
   6244  *     BCM_E_NONE
   6245  */
   6246 STATIC int
   6247 _field_fb_ingress_qualifiers_init(int unit, _field_stage_t *stage_fc)
   6248 {
   6249     soc_mem_t     tcam_mem;        /* TCAM memory id.           */
   6250     soc_mem_t     policy_mem;      /* Policy table memory id .  */
   6251     int           offset;          /* Tcam field offset.        */
   6252     int           rv;              /* Operation return status.  */
   6253     _FP_QUAL_DECL;
   6254 
   6255     /* Input parameters check. */
   6256     if (NULL == stage_fc) {
   6257         return (BCM_E_PARAM);
   6258     }
   6259 
   6260     rv = _field_fb_tcam_policy_mem_get(unit, stage_fc->stage_id, 
   6261                                        &tcam_mem, &policy_mem);
   6262     BCM_IF_ERROR_RETURN(rv);
   6263 
   6264     _key_fld_ = F4f;
   6265     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInPort,
   6266                  _bcmFieldSliceSelFpf4, 0, 0, 5);
   6267 
   6268     if (soc_feature(unit, soc_feature_field_qual_drop)) {
   6269         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpType,
   6270                      _bcmFieldSliceSelFpf4, 1, 0, 2);
   6271         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2Format,
   6272                      _bcmFieldSliceSelFpf4, 1, 2, 2);
   6273         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDrop,
   6274                      _bcmFieldSliceSelFpf4, 1, 4, 1);
   6275     }
   6276 
   6277     _key_fld_ = KEYf;
   6278     offset = 0;
   6279 
   6280     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyStage,
   6281                  _bcmFieldSliceSelDisable, 0, 0, 0);
   6282     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyStageIngress,
   6283                  _bcmFieldSliceSelDisable, 0, 0, 0);
   6284     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIp4,
   6285                  _bcmFieldSliceSelDisable, 0, 0, 0);
   6286     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIp6,
   6287                  _bcmFieldSliceSelDisable, 0, 0, 0);
   6288     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyHiGig,
   6289                  _bcmFieldSliceSelDisable, 0, 0, 0);
   6290     if (SOC_IS_FIREBOLT2(unit)) {
   6291         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDrop,
   6292                      _bcmFieldSliceSelDisable, 0, 0, 0);
   6293 
   6294     }
   6295 
   6296 
   6297     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2Format,
   6298                  _bcmFieldSliceSelFpf3, 0, 0, 2);
   6299     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyVlanFormat,
   6300                  _bcmFieldSliceSelFpf3, 0, 2, 2);
   6301     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpType,
   6302                  _bcmFieldSliceSelFpf3, 0, 4, 2);
   6303     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMHOpcode,
   6304                  _bcmFieldSliceSelFpf3, 0, 6, 3);
   6305     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyPacketRes,
   6306                  _bcmFieldSliceSelFpf3, 0, 9, 4);
   6307     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpInfo,
   6308                  _bcmFieldSliceSelFpf3, 0, 13, 3);
   6309 
   6310 #if defined(BCM_BRADLEY_SUPPORT)
   6311     if (SOC_IS_HB_GW(unit)) {
   6312         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcPort,
   6313                      _bcmFieldSliceSelFpf3, 1, 0, 14);
   6314         if (soc_feature(unit, soc_feature_field_wide)) {
   6315             _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMHOpcode,
   6316                          _bcmFieldSliceSelFpf3, 1, 14, 3);
   6317         }
   6318     } else 
   6319 #endif /* BCM_BRADLEY_SUPPORT */
   6320     {
   6321         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcPort,
   6322                      _bcmFieldSliceSelFpf3, 1, 0, 12);
   6323         if (soc_feature(unit, soc_feature_field_wide)) {
   6324             _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMHOpcode,
   6325                          _bcmFieldSliceSelFpf3, 1, 12, 3);
   6326         }
   6327     }
   6328 
   6329     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcTrunk,
   6330                  _bcmFieldSliceSelFpf3, 1, 0, 8);
   6331 
   6332 
   6333 #if defined(BCM_BRADLEY_SUPPORT)
   6334     if (SOC_IS_HB_GW(unit)) {
   6335         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstPort,
   6336                      _bcmFieldSliceSelFpf3, 2, 0, 14);
   6337         if (soc_feature(unit, soc_feature_field_wide)) {
   6338             _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMHOpcode,
   6339                          _bcmFieldSliceSelFpf3, 2, 14, 3);
   6340         }
   6341     } else 
   6342 #endif /* BCM_BRADLEY_SUPPORT */
   6343     {
   6344         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstPort,
   6345                      _bcmFieldSliceSelFpf3, 2, 0, 12);
   6346         if (soc_feature(unit, soc_feature_field_wide)) {
   6347             _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMHOpcode,
   6348                          _bcmFieldSliceSelFpf3, 2, 12, 3);
   6349         }
   6350     }
   6351 
   6352     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstTrunk,
   6353                  _bcmFieldSliceSelFpf3, 2, 0, 8);
   6354 
   6355     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTunnelTerminated,
   6356                  _bcmFieldSliceSelFpf3, 3, 0, 1);
   6357     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyVlanTranslationHit,
   6358                  _bcmFieldSliceSelFpf3, 3, 1, 1);
   6359     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyForwardingVlanValid,
   6360                  _bcmFieldSliceSelFpf3, 3, 2, 1);
   6361     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIngressStpState,
   6362                  _bcmFieldSliceSelFpf3, 3, 3, 2);
   6363     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2SrcHit,
   6364                  _bcmFieldSliceSelFpf3, 3, 5, 1);
   6365     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2SrcStatic,
   6366                  _bcmFieldSliceSelFpf3, 3, 6, 1);
   6367     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2DestHit,
   6368                  _bcmFieldSliceSelFpf3, 3, 7, 1);
   6369     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3Routable,
   6370                  _bcmFieldSliceSelFpf3, 3, 8, 1);
   6371     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2CacheHit,
   6372                  _bcmFieldSliceSelFpf3, 3, 9, 1);
   6373     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3SrcHostHit,
   6374                  _bcmFieldSliceSelFpf3, 3, 10, 1);
   6375     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3DestHostHit,
   6376                  _bcmFieldSliceSelFpf3, 3, 11, 1);
   6377     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpmcStarGroupHit,
   6378                  _bcmFieldSliceSelFpf3, 3, 12, 1);
   6379     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3DestRouteHit,
   6380                  _bcmFieldSliceSelFpf3, 3, 13, 1);
   6381     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2StationMove,
   6382                  _bcmFieldSliceSelFpf3, 3, 14, 1);
   6383     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDosAttack,
   6384                  _bcmFieldSliceSelFpf3, 3, 15, 1);
   6385 
   6386     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTcpControl,
   6387                  _bcmFieldSliceSelFpf3, 4, 0, 6);
   6388     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP,
   6389                  _bcmFieldSliceSelFpf3, 4, 6, 8);
   6390 
   6391     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan,
   6392                  _bcmFieldSliceSelFpf3, 5, 0, 16);
   6393     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId,
   6394                  _bcmFieldSliceSelFpf3, 5, 0, 12);
   6395     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi,
   6396                  _bcmFieldSliceSelFpf3, 5, 12, 1);
   6397     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri,
   6398                  _bcmFieldSliceSelFpf3, 5, 13, 3);
   6399 
   6400     if (soc_feature(unit, soc_feature_field_wide)) {
   6401         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP,
   6402                      _bcmFieldSliceSelFpf3, 6, 0, 8);
   6403         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol,
   6404                      _bcmFieldSliceSelFpf3, 6, 8, 8);
   6405         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyRangeCheck,
   6406                      _bcmFieldSliceSelFpf3, 7, 0, 16);
   6407     } 
   6408 
   6409     /* FPF2 */
   6410     offset += _FIELD_MEM_FIELD_LENGTH(unit, tcam_mem, F3f);
   6411 
   6412     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTtl,
   6413                  _bcmFieldSliceSelFpf2, 0, offset, 8);
   6414     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTcpControl,
   6415                  _bcmFieldSliceSelFpf2, 0, (offset + 8), 6);
   6416     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpFlags,
   6417                  _bcmFieldSliceSelFpf2, 0, (offset + 14), 2);
   6418     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP,
   6419                  _bcmFieldSliceSelFpf2, 0, (offset + 16), 8);
   6420     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort,
   6421                  _bcmFieldSliceSelFpf2, 0, (offset + 24), 16);
   6422     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4SrcPort,
   6423                  _bcmFieldSliceSelFpf2, 0, (offset + 40), 16);
   6424     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol,
   6425                  _bcmFieldSliceSelFpf2, 0, (offset + 56), 8);
   6426     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp,
   6427                  _bcmFieldSliceSelFpf2, 0, (offset + 64), 32);
   6428     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp,
   6429                  _bcmFieldSliceSelFpf2, 0, (offset + 96), 32);
   6430 
   6431     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTtl,
   6432                  _bcmFieldSliceSelFpf2, 1, offset, 8);
   6433     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTcpControl,
   6434                  _bcmFieldSliceSelFpf2, 1, (offset + 8), 6);
   6435     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpFlags,
   6436                  _bcmFieldSliceSelFpf2, 1, (offset + 14), 2);
   6437     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP,
   6438                  _bcmFieldSliceSelFpf2, 1, (offset + 16), 8);
   6439     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort,
   6440                  _bcmFieldSliceSelFpf2, 1, (offset + 24), 16);
   6441     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyRangeCheck,
   6442                  _bcmFieldSliceSelFpf2, 1, (offset + 40), 16);
   6443     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol,
   6444                  _bcmFieldSliceSelFpf2, 1, (offset + 56), 8);
   6445     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp,
   6446                  _bcmFieldSliceSelFpf2, 1, (offset + 64), 32);
   6447     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp,
   6448                  _bcmFieldSliceSelFpf2, 1, (offset + 96), 32);
   6449 
   6450     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTtl,
   6451                  _bcmFieldSliceSelFpf2, 2, offset, 8);
   6452     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTcpControl,
   6453                  _bcmFieldSliceSelFpf2, 2, (offset + 8), 6);
   6454     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpFlags,
   6455                  _bcmFieldSliceSelFpf2, 2, (offset + 14), 2);
   6456     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP,
   6457                  _bcmFieldSliceSelFpf2, 2, (offset + 16), 8);
   6458     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4SrcPort,
   6459                  _bcmFieldSliceSelFpf2, 2, (offset + 24), 16);
   6460     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyRangeCheck,
   6461                  _bcmFieldSliceSelFpf2, 2, (offset + 40), 16);
   6462     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol,
   6463                  _bcmFieldSliceSelFpf2, 2, (offset + 56), 8);
   6464     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp,
   6465                  _bcmFieldSliceSelFpf2, 2, (offset + 64), 32);
   6466     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp,
   6467                  _bcmFieldSliceSelFpf2, 2, (offset + 96), 32);
   6468 
   6469     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp6,
   6470                  _bcmFieldSliceSelFpf2, 3, offset, 128);
   6471 
   6472     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp6,
   6473                  _bcmFieldSliceSelFpf2, 4, offset, 128);
   6474 
   6475     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTcpControl,
   6476                  _bcmFieldSliceSelFpf2, 5, offset, 6);
   6477     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTtl,
   6478                  _bcmFieldSliceSelFpf2, 5, (offset + 6), 8);
   6479     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIp6FlowLabel,
   6480                  _bcmFieldSliceSelFpf2, 5, (offset + 14), 20);
   6481     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP,
   6482                  _bcmFieldSliceSelFpf2, 5, (offset + 34), 8);
   6483     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol,
   6484                  _bcmFieldSliceSelFpf2, 5, (offset + 42), 8);
   6485     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp6High,
   6486                  _bcmFieldSliceSelFpf2, 5, (offset + 50), 64);
   6487 
   6488     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan,
   6489                  _bcmFieldSliceSelFpf2, 6, offset, 16);
   6490     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId,
   6491                  _bcmFieldSliceSelFpf2, 6, offset, 12);
   6492     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi,
   6493                  _bcmFieldSliceSelFpf2, 6, (offset + 12), 1);
   6494     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri,
   6495                  _bcmFieldSliceSelFpf2, 6, (offset + 13), 3);
   6496     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyEtherType,
   6497                  _bcmFieldSliceSelFpf2, 6, (offset + 16), 16);
   6498     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcMac,
   6499                  _bcmFieldSliceSelFpf2, 6, (offset + 32), 48);
   6500     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstMac,
   6501                  _bcmFieldSliceSelFpf2, 6, (offset + 80), 48);
   6502 
   6503 
   6504     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan,
   6505                  _bcmFieldSliceSelFpf2, 7, offset, 16);
   6506     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId,
   6507                  _bcmFieldSliceSelFpf2, 7, offset, 12);
   6508     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi,
   6509                  _bcmFieldSliceSelFpf2, 7, (offset + 12), 1);
   6510     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri,
   6511                  _bcmFieldSliceSelFpf2, 7, (offset + 13), 3);
   6512     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyEtherType,
   6513                  _bcmFieldSliceSelFpf2, 7, (offset + 16), 16);
   6514     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp,
   6515                  _bcmFieldSliceSelFpf2, 7, (offset + 32), 32);
   6516     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcMac,
   6517                  _bcmFieldSliceSelFpf2, 7, (offset + 64), 48);
   6518 
   6519     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan,
   6520                  _bcmFieldSliceSelFpf2, 8, offset, 16);
   6521     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId,
   6522                  _bcmFieldSliceSelFpf2, 8, offset, 12);
   6523     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi,
   6524                  _bcmFieldSliceSelFpf2, 8, (offset + 12), 1);
   6525     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri,
   6526                  _bcmFieldSliceSelFpf2, 8, (offset + 13), 3);
   6527     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyEtherType,
   6528                  _bcmFieldSliceSelFpf2, 8, (offset + 16), 16);
   6529     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp,
   6530                  _bcmFieldSliceSelFpf2, 8, (offset + 32), 32);
   6531     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstMac,
   6532                  _bcmFieldSliceSelFpf2, 8, (offset + 64), 48);
   6533 
   6534     _FP_QUAL_ADD(unit, stage_fc, _bcmFieldQualifyData0,
   6535                  _bcmFieldSliceSelFpf2, 9, offset, 128);
   6536 
   6537     _FP_QUAL_ADD(unit, stage_fc, _bcmFieldQualifyData1,
   6538                  _bcmFieldSliceSelFpf2, 0xA, offset, 128);
   6539 
   6540     if (soc_feature(unit, soc_feature_field_qual_Ip6High)) {
   6541         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp6High,
   6542                      _bcmFieldSliceSelFpf2, 0xb, offset + 64, 64);
   6543         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp6High,
   6544                      _bcmFieldSliceSelFpf2, 0xb, offset, 64);
   6545     }
   6546 
   6547 
   6548 #ifdef BCM_FIREBOLT2_SUPPORT
   6549     if (SOC_IS_FIREBOLT2(unit)) { 
   6550         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTtl,
   6551                      _bcmFieldSliceSelFpf2, 0xc, offset, 8);
   6552         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTcpControl,
   6553                      _bcmFieldSliceSelFpf2, 0xc, (offset + 8), 6);
   6554         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpFrag,
   6555                      _bcmFieldSliceSelFpf2, 0xc, (offset + 14), 2);
   6556         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP,
   6557                      _bcmFieldSliceSelFpf2, 0xc, (offset + 16), 8);
   6558         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort,
   6559                      _bcmFieldSliceSelFpf2, 0xc, (offset + 24), 16);
   6560         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4SrcPort,
   6561                      _bcmFieldSliceSelFpf2, 0xc, (offset + 40), 16);
   6562         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol,
   6563                      _bcmFieldSliceSelFpf2, 0xc, (offset + 56), 8);
   6564         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp,
   6565                      _bcmFieldSliceSelFpf2, 0xc, (offset + 64), 32);
   6566         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp,
   6567                      _bcmFieldSliceSelFpf2, 0xc, (offset + 96), 32);
   6568 
   6569         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTtl,
   6570                      _bcmFieldSliceSelFpf2, 0xd, offset, 8);
   6571         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTcpControl,
   6572                      _bcmFieldSliceSelFpf2, 0xd, (offset + 8), 6);
   6573         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpFrag,
   6574                      _bcmFieldSliceSelFpf2, 0xd, (offset + 14), 2);
   6575         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP,
   6576                      _bcmFieldSliceSelFpf2, 0xd, (offset + 16), 8);
   6577         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort,
   6578                      _bcmFieldSliceSelFpf2, 0xd, (offset + 24), 16);
   6579         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyRangeCheck,
   6580                      _bcmFieldSliceSelFpf2, 0xd, (offset + 40), 16);
   6581         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol,
   6582                      _bcmFieldSliceSelFpf2, 0xd, (offset + 56), 8);
   6583         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp,
   6584                      _bcmFieldSliceSelFpf2, 0xd, (offset + 64), 32);
   6585         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp,
   6586                      _bcmFieldSliceSelFpf2, 0xd, (offset + 96), 32);
   6587 
   6588         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTtl,
   6589                      _bcmFieldSliceSelFpf2, 0xe, offset, 8);
   6590         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTcpControl,
   6591                      _bcmFieldSliceSelFpf2, 0xe, (offset + 8), 6);
   6592         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpFrag,
   6593                      _bcmFieldSliceSelFpf2, 0xe, (offset + 14), 2);
   6594         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP,
   6595                      _bcmFieldSliceSelFpf2, 0xe, (offset + 16), 8);
   6596         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4SrcPort,
   6597                      _bcmFieldSliceSelFpf2, 0xe, (offset + 24), 16);
   6598         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyRangeCheck,
   6599                      _bcmFieldSliceSelFpf2, 0xe, (offset + 40), 16);
   6600         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol,
   6601                      _bcmFieldSliceSelFpf2, 0xe, (offset + 56), 8);
   6602         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstIp,
   6603                      _bcmFieldSliceSelFpf2, 0xe, (offset + 64), 32);
   6604         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcIp,
   6605                      _bcmFieldSliceSelFpf2, 0xe, (offset + 96), 32);
   6606 
   6607     }
   6608 
   6609 #endif /* BCM_FIREBOLT2_SUPPORT */
   6610 
   6611     /* FPF1 */
   6612     offset += _FIELD_MEM_FIELD_LENGTH(unit, tcam_mem, F2f);
   6613 
   6614 #if defined (BCM_BRADLEY_SUPPORT)
   6615     if (SOC_IS_HB_GW(unit)) {
   6616         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInPorts,
   6617                      _bcmFieldSliceSelFpf1, 0, offset, 21);
   6618         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpType,
   6619                      _bcmFieldSliceSelFpf1, 0, (offset + 21), 2);
   6620     } else 
   6621 #endif /* BCM_BRADLEY_SUPPORT */
   6622     {
   6623         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInPorts,
   6624                      _bcmFieldSliceSelFpf1, 0, offset, 29);
   6625         if (soc_feature(unit, soc_feature_field_wide)) {
   6626             _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpType,
   6627                          _bcmFieldSliceSelFpf1, 0, (offset + 29), 2);
   6628 
   6629         }
   6630 #ifdef BCM_FIREBOLT2_SUPPORT
   6631         if (SOC_IS_FIREBOLT2(unit)) {
   6632             _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3Routable,
   6633                          _bcmFieldSliceSelFpf1, 0, (offset + 31), 1);
   6634         }
   6635 #endif /* BCM_FIREBOLT2_SUPPORT */
   6636     }
   6637 
   6638 #if defined (BCM_BRADLEY_SUPPORT)
   6639     if (SOC_IS_HB_GW(unit)) {
   6640         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstTrunk,
   6641                      _bcmFieldSliceSelFpf1, 1, offset, 8);
   6642         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstPort,
   6643                      _bcmFieldSliceSelFpf1, 1, offset, 14);
   6644         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcTrunk,
   6645                      _bcmFieldSliceSelFpf1, 1, (offset + 14), 8);
   6646         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcPort,
   6647                      _bcmFieldSliceSelFpf1, 1, (offset + 14), 14);
   6648         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMHOpcode,
   6649                      _bcmFieldSliceSelFpf1, 1, (offset + 28), 3);
   6650     } else 
   6651 #endif /* BCM_BRADLEY_SUPPORT */
   6652 
   6653     {
   6654         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstTrunk,
   6655                      _bcmFieldSliceSelFpf1, 1, offset, 8);
   6656         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstPort,
   6657                      _bcmFieldSliceSelFpf1, 1, offset, 12);
   6658         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcTrunk,
   6659                      _bcmFieldSliceSelFpf1, 1, (offset + 12), 8);
   6660         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcPort,
   6661                      _bcmFieldSliceSelFpf1, 1, (offset + 12), 12);
   6662         if (soc_feature(unit, soc_feature_field_wide)) {
   6663             _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMHOpcode,
   6664                          _bcmFieldSliceSelFpf1, 1, (offset + 24), 3);
   6665         }
   6666     }
   6667 
   6668     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort,
   6669                  _bcmFieldSliceSelFpf1, 2, offset, 16);
   6670     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4SrcPort,
   6671                  _bcmFieldSliceSelFpf1, 2, (offset + 16), 16);
   6672 
   6673 #if defined(BCM_FIREBOLT2_SUPPORT)
   6674     if (SOC_IS_FIREBOLT2(unit)) {
   6675         _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlan,
   6676                          _bcmFieldDevSelInnerVlanOverlay, 0,
   6677                          _bcmFieldSliceSelFpf1, 3, 
   6678                          _bcmFieldSliceSelDisable, 0, 0,
   6679                          offset, 16, 0, 0, 0, 0, 0);
   6680         _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanId,
   6681                          _bcmFieldDevSelInnerVlanOverlay, 0,
   6682                          _bcmFieldSliceSelFpf1, 3, 
   6683                          _bcmFieldSliceSelDisable, 0, 0,
   6684                          offset, 12, 0, 0, 0, 0, 0);
   6685         _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanCfi,
   6686                          _bcmFieldDevSelInnerVlanOverlay, 0,
   6687                          _bcmFieldSliceSelFpf1, 3, 
   6688                          _bcmFieldSliceSelDisable, 0, 0,
   6689                          (offset + 12), 1, 0, 0, 0, 0, 0);
   6690         _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanPri,
   6691                          _bcmFieldDevSelInnerVlanOverlay, 0,
   6692                          _bcmFieldSliceSelFpf1, 3, 
   6693                          _bcmFieldSliceSelDisable, 0, 0,
   6694                          (offset + 13), 3, 0, 0, 0, 0, 0);
   6695         _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyVrf,
   6696                          _bcmFieldDevSelInnerVlanOverlay, 1,
   6697                          _bcmFieldSliceSelFpf1, 3, 
   6698                          _bcmFieldSliceSelDisable, 0, 0,
   6699                          offset, 6, 0, 0, 0, 0, 0);
   6700         _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyDstClassField,
   6701                          _bcmFieldDevSelInnerVlanOverlay, 1,
   6702                          _bcmFieldSliceSelFpf1, 3, 
   6703                          _bcmFieldSliceSelDisable, 0, 0,
   6704                          (offset + 6), 5, 0, 0, 0, 0, 0);
   6705         _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifySrcClassL2,
   6706                          _bcmFieldDevSelInnerVlanOverlay, 1,
   6707                          _bcmFieldSliceSelFpf1, 3, 
   6708                          _bcmFieldSliceSelDisable, 0, 0,
   6709                          (offset + 11), 5, 0, 0, 0, 0, 0);
   6710     } else 
   6711 #endif /* BCM_FIREBOLT2_SUPPORT */
   6712         if (soc_feature(unit, soc_feature_src_mac_group)) {
   6713             _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlan,
   6714                              _bcmFieldDevSelInnerVlanOverlay, 0,
   6715                              _bcmFieldSliceSelFpf1, 3, 
   6716                              _bcmFieldSliceSelDisable, 0, 0,
   6717                              offset, 16, 0, 0, 0, 0, 0);
   6718             _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanId,
   6719                              _bcmFieldDevSelInnerVlanOverlay, 0,
   6720                              _bcmFieldSliceSelFpf1, 3, 
   6721                              _bcmFieldSliceSelDisable, 0, 0,
   6722                              offset, 12, 0, 0, 0, 0, 0);
   6723             _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanCfi,
   6724                              _bcmFieldDevSelInnerVlanOverlay, 0,
   6725                              _bcmFieldSliceSelFpf1, 3, 
   6726                              _bcmFieldSliceSelDisable, 0, 0,
   6727                              (offset + 12), 1, 0, 0, 0, 0, 0);
   6728             _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanPri,
   6729                              _bcmFieldDevSelInnerVlanOverlay, 0,
   6730                              _bcmFieldSliceSelFpf1, 3, 
   6731                              _bcmFieldSliceSelDisable, 0, 0,
   6732                              (offset + 13), 3, 0, 0, 0, 0, 0);
   6733 
   6734             _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifySrcClassL2,
   6735                              _bcmFieldDevSelInnerVlanOverlay, 1,
   6736                              _bcmFieldSliceSelFpf1, 3, 
   6737                              _bcmFieldSliceSelDisable, 0, 0,
   6738                              (offset + 12), 4, 0, 0, 0, 0, 0);
   6739         } else {
   6740             _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlan,
   6741                          _bcmFieldSliceSelFpf1, 3, offset, 16);
   6742             _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanId,
   6743                          _bcmFieldSliceSelFpf1, 3, offset, 12);
   6744             _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanCfi,
   6745                          _bcmFieldSliceSelFpf1, 3, (offset + 12), 1);
   6746             _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanPri,
   6747                          _bcmFieldSliceSelFpf1, 3, (offset + 13), 3);
   6748 
   6749         }
   6750 
   6751     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan,
   6752                  _bcmFieldSliceSelFpf1, 3, (offset + 16), 16);
   6753     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId,
   6754                  _bcmFieldSliceSelFpf1, 3, (offset + 16), 12);
   6755     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi,
   6756                  _bcmFieldSliceSelFpf1, 3, (offset + 28), 1);
   6757     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri,
   6758                  _bcmFieldSliceSelFpf1, 3, (offset + 29), 3);
   6759 
   6760 
   6761     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan,
   6762                  _bcmFieldSliceSelFpf1, 4, offset, 16);
   6763     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId,
   6764                  _bcmFieldSliceSelFpf1, 4, offset, 12);
   6765     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi,
   6766                  _bcmFieldSliceSelFpf1, 4, (offset + 12), 1);
   6767     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri,
   6768                  _bcmFieldSliceSelFpf1, 4, (offset + 13), 3);
   6769     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyEtherType,
   6770                  _bcmFieldSliceSelFpf1, 4, (offset + 16), 16);
   6771 
   6772     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol,
   6773                  _bcmFieldSliceSelFpf1, 5, offset, 8);
   6774     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyEtherType,
   6775                  _bcmFieldSliceSelFpf1, 5, (offset + 8), 16);
   6776 
   6777     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTunnelTerminated,
   6778                  _bcmFieldSliceSelFpf1, 6, offset, 1);
   6779     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyVlanTranslationHit,
   6780                  _bcmFieldSliceSelFpf1, 6, (offset + 1), 1);
   6781     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyForwardingVlanValid,
   6782                  _bcmFieldSliceSelFpf1, 6, (offset + 2), 1);
   6783     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIngressStpState,
   6784                  _bcmFieldSliceSelFpf1, 6, (offset + 3), 2);
   6785     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2SrcHit,
   6786                  _bcmFieldSliceSelFpf1, 6, (offset + 5), 1);
   6787     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2SrcStatic,
   6788                  _bcmFieldSliceSelFpf1, 6, (offset + 6), 1);
   6789     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2DestHit,
   6790                  _bcmFieldSliceSelFpf1, 6, (offset + 7), 1);
   6791     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3Routable,
   6792                  _bcmFieldSliceSelFpf1, 6, (offset + 8), 1);
   6793     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2CacheHit,
   6794                  _bcmFieldSliceSelFpf1, 6, (offset + 9), 1);
   6795     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3SrcHostHit,
   6796                  _bcmFieldSliceSelFpf1, 6, (offset + 10), 1);
   6797     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3DestHostHit,
   6798                  _bcmFieldSliceSelFpf1, 6, (offset + 11), 1);
   6799     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpmcStarGroupHit,
   6800                  _bcmFieldSliceSelFpf1, 6, (offset + 12), 1);
   6801     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3DestRouteHit,
   6802                  _bcmFieldSliceSelFpf1, 6, (offset + 13), 1);
   6803     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2StationMove,
   6804                  _bcmFieldSliceSelFpf1, 6, (offset + 14), 1);
   6805     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDosAttack,
   6806                  _bcmFieldSliceSelFpf1, 6, (offset + 15), 1);
   6807 #if defined(BCM_FIREBOLT2_SUPPORT) 
   6808     if (SOC_IS_FIREBOLT2(unit)) {
   6809         _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlan,
   6810                          _bcmFieldDevSelInnerVlanOverlay, 0,
   6811                          _bcmFieldSliceSelFpf1, 6, 
   6812                          _bcmFieldSliceSelDisable, 0, 0,
   6813                          (offset + 16), 16, 0, 0, 0, 0, 0);
   6814         _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanId,
   6815                          _bcmFieldDevSelInnerVlanOverlay, 0,
   6816                          _bcmFieldSliceSelFpf1, 6, 
   6817                          _bcmFieldSliceSelDisable, 0, 0,
   6818                          (offset + 16), 12, 0, 0, 0, 0, 0);
   6819         _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanCfi,
   6820                          _bcmFieldDevSelInnerVlanOverlay, 0,
   6821                          _bcmFieldSliceSelFpf1, 6, 
   6822                          _bcmFieldSliceSelDisable, 0, 0,
   6823                          (offset + 28), 1, 0, 0, 0, 0, 0);
   6824         _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanPri,
   6825                          _bcmFieldDevSelInnerVlanOverlay, 0,
   6826                          _bcmFieldSliceSelFpf1, 6, 
   6827                          _bcmFieldSliceSelDisable, 0, 0,
   6828                          (offset + 29), 3, 0, 0, 0, 0, 0);
   6829         _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyVrf,
   6830                          _bcmFieldDevSelInnerVlanOverlay, 1,
   6831                          _bcmFieldSliceSelFpf1, 6, 
   6832                          _bcmFieldSliceSelDisable, 0, 0,
   6833                          (offset + 16), 6, 0, 0, 0, 0, 0);
   6834         _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyDstClassField,
   6835                          _bcmFieldDevSelInnerVlanOverlay, 1,
   6836                          _bcmFieldSliceSelFpf1, 6, 
   6837                          _bcmFieldSliceSelDisable, 0, 0,
   6838                          (offset + 22), 5, 0, 0, 0, 0, 0);
   6839         _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifySrcClassL2,
   6840                          _bcmFieldDevSelInnerVlanOverlay, 1,
   6841                          _bcmFieldSliceSelFpf1, 6, 
   6842                          _bcmFieldSliceSelDisable, 0, 0,
   6843                          (offset + 27), 5, 0, 0, 0, 0, 0);
   6844     } else 
   6845 #endif /* BCM_FIREBOLT2_SUPPORT */
   6846         if (soc_feature(unit, soc_feature_src_mac_group)) {
   6847             _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlan,
   6848                              _bcmFieldDevSelInnerVlanOverlay, 0,
   6849                              _bcmFieldSliceSelFpf1, 6, 
   6850                              _bcmFieldSliceSelDisable, 0, 0,
   6851                              (offset + 16), 16, 0, 0, 0, 0, 0);
   6852             _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanId,
   6853                              _bcmFieldDevSelInnerVlanOverlay, 0,
   6854                              _bcmFieldSliceSelFpf1, 6, 
   6855                              _bcmFieldSliceSelDisable, 0, 0,
   6856                              (offset + 16), 12, 0, 0, 0, 0, 0);
   6857             _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanCfi,
   6858                              _bcmFieldDevSelInnerVlanOverlay, 0,
   6859                              _bcmFieldSliceSelFpf1, 6, 
   6860                              _bcmFieldSliceSelDisable, 0, 0,
   6861                              (offset + 28), 1, 0, 0, 0, 0, 0);
   6862             _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanPri,
   6863                              _bcmFieldDevSelInnerVlanOverlay, 0,
   6864                              _bcmFieldSliceSelFpf1, 6, 
   6865                              _bcmFieldSliceSelDisable, 0, 0,
   6866                              (offset + 29), 3, 0, 0, 0, 0, 0);
   6867             _FP_QUAL_EXT_ADD(unit, stage_fc, bcmFieldQualifySrcClassL2,
   6868                              _bcmFieldDevSelInnerVlanOverlay, 1,
   6869                              _bcmFieldSliceSelFpf1, 6, 
   6870                              _bcmFieldSliceSelDisable, 0, 0,
   6871                              (offset + 28), 4, 0, 0, 0, 0, 0);
   6872         } else {
   6873             _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlan,
   6874                          _bcmFieldSliceSelFpf1, 6, (offset + 16), 16);
   6875             _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanId,
   6876                          _bcmFieldSliceSelFpf1, 6, (offset + 16), 12);
   6877             _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanCfi,
   6878                          _bcmFieldSliceSelFpf1, 6, (offset + 28), 1);
   6879             _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyInnerVlanPri,
   6880                          _bcmFieldSliceSelFpf1, 6, (offset + 29), 3);
   6881         }
   6882 
   6883     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan,
   6884                  _bcmFieldSliceSelFpf1, 7, offset, 16);
   6885     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId,
   6886                  _bcmFieldSliceSelFpf1, 7, offset, 12);
   6887     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi,
   6888                  _bcmFieldSliceSelFpf1, 7, (offset + 12), 1);
   6889     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri,
   6890                  _bcmFieldSliceSelFpf1, 7, (offset + 13), 3);
   6891     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2Format,
   6892                  _bcmFieldSliceSelFpf1, 7, (offset + 16), 2);
   6893     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyVlanFormat,
   6894                  _bcmFieldSliceSelFpf1, 7, (offset + 18), 2);
   6895     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpType,
   6896                  _bcmFieldSliceSelFpf1, 7, (offset + 20), 2);
   6897     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMHOpcode,
   6898                  _bcmFieldSliceSelFpf1, 7, (offset + 22), 3);
   6899     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyPacketRes,
   6900                  _bcmFieldSliceSelFpf1, 7, (offset + 25), 4);
   6901     _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpInfo,
   6902                  _bcmFieldSliceSelFpf1, 7, (offset + 29), 3);
   6903 
   6904 
   6905 #ifdef BCM_FIREBOLT2_SUPPORT
   6906     if (SOC_IS_FIREBOLT2(unit)) {
   6907         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan,
   6908                      _bcmFieldSliceSelFpf1, 0xc, offset, 16);
   6909         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId,
   6910                      _bcmFieldSliceSelFpf1, 0xc, offset, 12);
   6911         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi,
   6912                      _bcmFieldSliceSelFpf1, 0xc, (offset + 12), 1);
   6913         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri,
   6914                      _bcmFieldSliceSelFpf1, 0xc, (offset + 13), 3);
   6915         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyVrf,
   6916                      _bcmFieldSliceSelFpf1, 0xc, (offset + 16), 6);
   6917         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstClassField,
   6918                      _bcmFieldSliceSelFpf1, 0xc, (offset + 22), 5);
   6919         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpType,
   6920                      _bcmFieldSliceSelFpf1, 0xc, (offset + 29), 2);
   6921         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3Routable,
   6922                      _bcmFieldSliceSelFpf1, 0xc, (offset + 31), 1);
   6923 
   6924         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol,
   6925                      _bcmFieldSliceSelFpf1, 0xd, offset , 8);
   6926         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyVrf,
   6927                      _bcmFieldSliceSelFpf1, 0xd, (offset + 8) , 6);
   6928         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDstClassField,
   6929                      _bcmFieldSliceSelFpf1, 0xd, (offset + 14) , 5);
   6930         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpType,
   6931                      _bcmFieldSliceSelFpf1, 0xd, (offset + 21) , 2);
   6932         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3Routable,
   6933                      _bcmFieldSliceSelFpf1, 0xd, (offset + 23) , 1);
   6934         _FP_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDSCP,
   6935                      _bcmFieldSliceSelFpf1, 0xd, (offset + 24) , 8);
   6936 
   6937         /* Intraslice. */
   6938         _key_fld_ = DATAf;
   6939 
   6940         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyDSCP,
   6941                                 _bcmFieldSliceSelFpf2, 0,
   6942                                 _bcmFieldSliceSelDisable, 0, 8, 8);
   6943         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol,
   6944                                 _bcmFieldSliceSelFpf2, 0,
   6945                                 _bcmFieldSliceSelDisable, 0, 16, 8);
   6946         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyTtl,
   6947                                 _bcmFieldSliceSelFpf2, 0,
   6948                                 _bcmFieldSliceSelDisable, 0, 24, 8);
   6949         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyTcpControl,
   6950                                 _bcmFieldSliceSelFpf2, 0,
   6951                                 _bcmFieldSliceSelDisable, 0, 32, 6);
   6952         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyIpFrag,
   6953                                 _bcmFieldSliceSelFpf2, 0,
   6954                                 _bcmFieldSliceSelDisable, 0, 38, 2);
   6955         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc,
   6956                                 bcmFieldQualifyTunnelTerminated,
   6957                                 _bcmFieldSliceSelFpf2, 0,
   6958                                 _bcmFieldSliceSelDisable, 0, 40, 1);
   6959         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc,
   6960                                 bcmFieldQualifyVlanTranslationHit,
   6961                                 _bcmFieldSliceSelFpf2, 0,
   6962                                 _bcmFieldSliceSelDisable, 0, 41, 1);
   6963         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc,
   6964                                 bcmFieldQualifyForwardingVlanValid,
   6965                                 _bcmFieldSliceSelFpf2, 0,
   6966                                 _bcmFieldSliceSelDisable, 0, 42, 1);
   6967         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc,
   6968                                 bcmFieldQualifyIngressStpState,
   6969                                 _bcmFieldSliceSelFpf2, 0,
   6970                                 _bcmFieldSliceSelDisable, 0, 43, 2);
   6971         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyL2SrcHit,
   6972                                 _bcmFieldSliceSelFpf2, 0,
   6973                                 _bcmFieldSliceSelDisable, 0, 45, 1);
   6974         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyL2SrcStatic,
   6975                                 _bcmFieldSliceSelFpf2, 0,
   6976                                 _bcmFieldSliceSelDisable, 0, 46, 1);
   6977         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyL2DestHit,
   6978                                 _bcmFieldSliceSelFpf2, 0,
   6979                                 _bcmFieldSliceSelDisable, 0, 47, 1);
   6980         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyL3Routable,
   6981                                 _bcmFieldSliceSelFpf2, 0,
   6982                                 _bcmFieldSliceSelDisable, 0, 48, 1);
   6983         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyL2CacheHit,
   6984                                 _bcmFieldSliceSelFpf2, 0,
   6985                                 _bcmFieldSliceSelDisable, 0, 49, 1);
   6986         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc,
   6987                                 bcmFieldQualifyL3SrcHostHit,
   6988                                 _bcmFieldSliceSelFpf2, 0,
   6989                                 _bcmFieldSliceSelDisable, 0, 50, 1);
   6990         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc,
   6991                                 bcmFieldQualifyL3DestHostHit,
   6992                                 _bcmFieldSliceSelFpf2, 0,
   6993                                 _bcmFieldSliceSelDisable, 0, 51, 1);
   6994         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc,
   6995                                 bcmFieldQualifyIpmcStarGroupHit,
   6996                                 _bcmFieldSliceSelFpf2, 0,
   6997                                 _bcmFieldSliceSelDisable, 0, 52, 1);
   6998         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc,
   6999                                 bcmFieldQualifyL3DestRouteHit,
   7000                                 _bcmFieldSliceSelFpf2, 0,
   7001                                 _bcmFieldSliceSelDisable, 0, 53, 1);
   7002         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc,
   7003                                 bcmFieldQualifyL2StationMove,
   7004                                 _bcmFieldSliceSelFpf2, 0,
   7005                                 _bcmFieldSliceSelDisable, 0, 54, 1);
   7006         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyDosAttack,
   7007                                 _bcmFieldSliceSelFpf2, 0,
   7008                                 _bcmFieldSliceSelDisable, 0, 55, 1);
   7009         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyOuterVlan,
   7010                                 _bcmFieldSliceSelFpf2, 0,
   7011                                 _bcmFieldSliceSelDisable, 0, 56, 16);
   7012         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanId,
   7013                                 _bcmFieldSliceSelFpf2, 0,
   7014                                 _bcmFieldSliceSelDisable, 0, 56, 12);
   7015         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanCfi,
   7016                                 _bcmFieldSliceSelFpf2, 0,
   7017                                 _bcmFieldSliceSelDisable, 0, 68, 1);
   7018         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyOuterVlanPri,
   7019                                 _bcmFieldSliceSelFpf2, 0,
   7020                                 _bcmFieldSliceSelDisable, 0, 69, 3);
   7021         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyRangeCheck,
   7022                                 _bcmFieldSliceSelFpf2, 0,
   7023                                 _bcmFieldSliceSelDisable, 0, 72, 16);
   7024         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyDstIp,
   7025                                 _bcmFieldSliceSelFpf2, 0,
   7026                                 _bcmFieldSliceSelDisable, 0, 88, 32);
   7027         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifySrcIp,
   7028                                 _bcmFieldSliceSelFpf2, 0,
   7029                                 _bcmFieldSliceSelDisable, 0, 120, 32);
   7030         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort,
   7031                                 _bcmFieldSliceSelFpf2, 0,
   7032                                 _bcmFieldSliceSelDisable, 0, 152, 16);
   7033         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyL4SrcPort,
   7034                                 _bcmFieldSliceSelFpf2, 0,
   7035                                 _bcmFieldSliceSelDisable, 0, 168, 16);
   7036 
   7037         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyTcpControl,
   7038                                 _bcmFieldSliceSelFpf2, 1,
   7039                                 _bcmFieldSliceSelDisable, 0, 0, 6);
   7040         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyDSCP,
   7041                                 _bcmFieldSliceSelFpf2, 1,
   7042                                 _bcmFieldSliceSelDisable, 0, 8, 8);
   7043         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyIpProtocol,
   7044                                 _bcmFieldSliceSelFpf2, 1,
   7045                                 _bcmFieldSliceSelDisable, 0, 16, 8);
   7046         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifySrcIp6,
   7047                                 _bcmFieldSliceSelFpf2, 1,
   7048                                 _bcmFieldSliceSelDisable, 0, 24, 128);
   7049         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyL4DstPort,
   7050                                 _bcmFieldSliceSelFpf2, 1,
   7051                                 _bcmFieldSliceSelDisable, 0, 152, 16);
   7052         _FP_QUAL_INTRASLICE_ADD(unit, stage_fc, bcmFieldQualifyL4SrcPort,
   7053                                 _bcmFieldSliceSelFpf2, 1,
   7054                                 _bcmFieldSliceSelDisable, 0, 168, 16);
   7055     }
   7056 #endif /* BCM_FIREBOLT2_SUPPORT */
   7057     return (BCM_E_NONE);
   7058 }
   7059 
   7060 /*
   7061  * Function:
   7062  *     _field_fb_qualifiers_init
   7063  * Purpose:
   7064  *     Initialize device qaualifiers select codes & offsets
   7065  * Parameters:
   7066  *     unit       - (IN) BCM device number.
   7067  *     stage_fc   - (IN) Field Processor stage control structure. 
   7068  *
   7069  * Returns:
   7070  *     BCM_E_NONE
   7071  * Notes:
   7072  */
   7073 STATIC int
   7074 _field_fb_qualifiers_init(int unit, _field_stage_t *stage_fc)
   7075 {
   7076     int rv;           /* Operation return status. */
   7077 
   7078     /* Input parameters check. */
   7079     if (NULL == stage_fc) {
   7080         return (BCM_E_PARAM);
   7081     }
   7082 
   7083     /* Allocated stage qualifiers configuration array. */
   7084     _FP_XGS3_ALLOC(stage_fc->f_qual_arr, 
   7085                    (_bcmFieldQualifyCount * sizeof(_bcm_field_qual_info_t *)), 
   7086                    "Field qualifiers");
   7087     if (NULL == stage_fc->f_qual_arr) {
   7088         return (BCM_E_MEMORY);
   7089     }
   7090     
   7091     switch (stage_fc->stage_id) {
   7092       case _BCM_FIELD_STAGE_INGRESS:
   7093           rv = _field_fb_ingress_qualifiers_init(unit, stage_fc);
   7094           break;
   7095 #if defined (BCM_FIREBOLT2_SUPPORT)
   7096       case _BCM_FIELD_STAGE_LOOKUP:
   7097           if (SOC_IS_FIREBOLT2(unit)) {
   7098               rv = _field_fb2_lookup_qualifiers_init(unit, stage_fc);
   7099           } else {
   7100               rv = (BCM_E_NONE);
   7101           } 
   7102           break;
   7103       case _BCM_FIELD_STAGE_EGRESS:
   7104           if (SOC_IS_FIREBOLT2(unit)) {
   7105               rv = _field_fb2_egress_qualifiers_init(unit, stage_fc);
   7106           } else {
   7107               rv = (BCM_E_NONE);
   7108           } 
   7109           break;
   7110 #endif /* BCM_FIREBOLT2_SUPPORT */
   7111       default: 
   7112           sal_free(stage_fc->f_qual_arr);
   7113           return (BCM_E_PARAM);
   7114     }
   7115     return (rv);
   7116 }
   7117 
   7118 /*
   7119  * Function:
   7120  *     _field_fb_init
   7121  * Purpose:
   7122  *     Perform initializations that are specific to BCM56504. This
   7123  *     includes initializing the FP field select bit offset tables for FPF[1-3]
   7124  *     for every stage. 
   7125  * Parameters:
   7126  *     unit       - (IN) BCM device number.
   7127  *     fc         - (IN) Field Processor control structure. 
   7128  *
   7129  * Returns:
   7130  *     BCM_E_NONE
   7131  * Notes:
   7132  */
   7133 int
   7134 _bcm_field_fb_init(int unit, _field_control_t *fc) 
   7135 {
   7136     _field_stage_t *stage_p; /* Stages iteration pointer */
   7137 
   7138     /* Input parameters check. */
   7139     if (NULL == fc) {
   7140         return (BCM_E_PARAM);
   7141     }
   7142 
   7143     stage_p = fc->stages;
   7144     while (stage_p) {
   7145         /* Clear hardware table */
   7146         BCM_IF_ERROR_RETURN(_field_fb_hw_clear(unit, stage_p));
   7147 
   7148         /* Initialize qualifiers info. */
   7149         BCM_IF_ERROR_RETURN(_field_fb_qualifiers_init(unit, stage_p));
   7150 
   7151         /* Goto next stage */
   7152         stage_p = stage_p->next;
   7153     }
   7154 
   7155     if (!SOC_WARM_BOOT(unit)) {
   7156         /* Enable filter processor */
   7157         BCM_IF_ERROR_RETURN(_field_port_filter_enable_set(unit, fc, TRUE));
   7158 
   7159         /* Enable meter refresh */
   7160         BCM_IF_ERROR_RETURN(_field_meter_refresh_enable_set(unit, fc, TRUE));
   7161         if (SOC_IS_FIREBOLT(unit) && 
   7162             !soc_feature(unit, soc_feature_field_wide)) {
   7163             BCM_IF_ERROR_RETURN
   7164                 (soc_reg_field32_modify(unit, FP_CAM_CONTROL_UPPERr,
   7165                                                        REG_PORT_ANY, 
   7166                                                        SECRET_CHAIN_MODEf,1));
   7167         }
   7168     }
   7169 
   7170     /* Initialize the function pointers */
   7171     _field_fb_functions_init(unit, &fc->functions);;
   7172 
   7173     return (BCM_E_NONE);
   7174 }
   7175 
   7176 /*
   7177  * Function:
   7178  *     _field_fb_hw_clear
   7179  * Purpose:
   7180  *     Clear hardware memory of requested stage. 
   7181  * Parameters:
   7182  *     unit       - (IN) BCM device number.
   7183  *     stage_fc   - (IN) Field Processor stage control structure. 
   7184  *
   7185  * Returns:
   7186  *     BCM_E_NONE
   7187  * Notes:
   7188  */
   7189 STATIC int
   7190 _field_fb_hw_clear(int unit, _field_stage_t *stage_fc)
   7191 {
   7192     if (SOC_WARM_BOOT(unit)) {
   7193         return (BCM_E_NONE);
   7194     }
   7195 
   7196     if (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) {
   7197         BCM_IF_ERROR_RETURN
   7198             (soc_mem_clear((unit), FP_UDF_OFFSETm, COPYNO_ALL, TRUE));  
   7199         BCM_IF_ERROR_RETURN
   7200             (soc_mem_clear((unit), FP_RANGE_CHECKm, COPYNO_ALL, TRUE));  
   7201         BCM_IF_ERROR_RETURN
   7202             (soc_mem_clear((unit), FP_TCAMm, COPYNO_ALL, TRUE));  
   7203         BCM_IF_ERROR_RETURN
   7204             (soc_mem_clear((unit), FP_POLICY_TABLEm, COPYNO_ALL, TRUE));  
   7205         BCM_IF_ERROR_RETURN
   7206             (soc_mem_clear((unit), FP_METER_TABLEm, COPYNO_ALL, TRUE));  
   7207         if (SOC_MEM_IS_VALID(unit, FP_COUNTER_TABLEm)) {              
   7208             BCM_IF_ERROR_RETURN
   7209                 (soc_mem_clear((unit), FP_COUNTER_TABLEm, COPYNO_ALL, TRUE));
   7210         }  
   7211 #if defined(BCM_SCORPION_SUPPORT)
   7212         if (SOC_MEM_IS_VALID(unit, FP_COUNTER_TABLE_Xm)) {              
   7213             BCM_IF_ERROR_RETURN
   7214                 (soc_mem_clear((unit), FP_COUNTER_TABLE_Xm, COPYNO_ALL, TRUE));
   7215         }  
   7216         if (SOC_MEM_IS_VALID(unit, FP_COUNTER_TABLE_Ym)) {              
   7217             BCM_IF_ERROR_RETURN
   7218                 (soc_mem_clear((unit), FP_COUNTER_TABLE_Ym, COPYNO_ALL, TRUE));
   7219         }
   7220 #endif  /* BCM_SCORPION_SUPPORT */
   7221         BCM_IF_ERROR_RETURN
   7222             (soc_mem_clear((unit), FP_PORT_FIELD_SELm, COPYNO_ALL, TRUE));  
   7223         if (SOC_MEM_IS_VALID(unit, IFP_PORT_FIELD_SELm)) {              
   7224             BCM_IF_ERROR_RETURN
   7225                 (soc_mem_clear(unit, IFP_PORT_FIELD_SELm, COPYNO_ALL, TRUE));
   7226         } 
   7227 #if defined(BCM_TRX_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT) || \
   7228     defined(BCM_RAPTOR_SUPPORT) 
   7229         if (SOC_MEM_IS_VALID(unit, FP_SLICE_MAPm)) {              
   7230             BCM_IF_ERROR_RETURN
   7231                 (soc_mem_clear(unit, FP_SLICE_MAPm, COPYNO_ALL, TRUE));
   7232         }
   7233 #endif /* RAPTOR || TRX || FB2 */
   7234 #ifdef BCM_FIREBOLT2_SUPPORT 
   7235     } else if (soc_feature(unit, soc_feature_field_multi_stage)) {
   7236 
   7237         if (_BCM_FIELD_STAGE_LOOKUP == stage_fc->stage_id) { 
   7238             BCM_IF_ERROR_RETURN
   7239                 (soc_mem_clear((unit), VFP_TCAMm, COPYNO_ALL, TRUE));  
   7240             BCM_IF_ERROR_RETURN
   7241                 (soc_mem_clear((unit), VFP_POLICY_TABLEm, COPYNO_ALL, TRUE));  
   7242         
   7243         } else if (_BCM_FIELD_STAGE_EGRESS == stage_fc->stage_id) {
   7244 
   7245             BCM_IF_ERROR_RETURN
   7246                 (soc_mem_clear((unit), EFP_TCAMm, COPYNO_ALL, TRUE));  
   7247             BCM_IF_ERROR_RETURN
   7248                 (soc_mem_clear((unit), EFP_POLICY_TABLEm, COPYNO_ALL, TRUE));  
   7249             BCM_IF_ERROR_RETURN
   7250                 (soc_mem_clear((unit), EFP_METER_TABLEm, COPYNO_ALL, TRUE));  
   7251             BCM_IF_ERROR_RETURN
   7252                 (soc_mem_clear((unit), EFP_COUNTER_TABLEm, COPYNO_ALL, TRUE));  
   7253         }
   7254 #endif /*  BCM_FIREBOLT2_SUPPORT  */
   7255     } else {
   7256         return (BCM_E_UNAVAIL);
   7257     }
   7258 
   7259     return (BCM_E_NONE);
   7260 }
   7261 
   7262 /*
   7263  * Function:
   7264  *     _field_fb_detach
   7265  *
   7266  * Purpose:
   7267  *     Deallocates BCM5650x's field tables.
   7268  *
   7269  * Parameters:
   7270  *     unit - BCM device number
   7271  *
   7272  * Returns:
   7273  *     BCM_E_NONE
   7274  */
   7275 STATIC int
   7276 _field_fb_detach(int unit, _field_control_t *fc)
   7277 {
   7278     _field_stage_t   *stage_p;  /* Stage iteration pointer. */
   7279 
   7280     stage_p = fc->stages;
   7281 
   7282     while (stage_p) { 
   7283        /* Clear the hardware tables */
   7284         BCM_IF_ERROR_RETURN(_field_fb_hw_clear(unit, stage_p));
   7285       
   7286         /* Goto next stage */
   7287         stage_p = stage_p->next; 
   7288     }
   7289     
   7290     /* Clear udf match criteria registers. */
   7291     BCM_IF_ERROR_RETURN(_bcm_field_fb_udf_ipprotocol_delete_all(unit));
   7292     BCM_IF_ERROR_RETURN(_bcm_field_fb_udf_ethertype_delete_all(unit));
   7293 
   7294     /* Don't disable port controls during Warmboot or Reloading state */
   7295     if (0 == SOC_HW_ACCESS_DISABLE(unit)) {
   7296         /* Clear the Filter Enable flags in the port table */
   7297         BCM_IF_ERROR_RETURN (_field_port_filter_enable_set(unit, fc, FALSE));
   7298     }
   7299 
   7300     BCM_IF_ERROR_RETURN (_field_meter_refresh_enable_set(unit, fc, FALSE));
   7301  
   7302     return (BCM_E_NONE);
   7303 }
   7304 
   7305 #ifdef BROADCOM_DEBUG
   7306 /*
   7307  * Function:
   7308  *     _field_fb_action_name
   7309  * Purpose:
   7310  *     Return text name of indicated action enum value.
   7311  */
   7312 STATIC char *
   7313 _field_fb_action_name(bcm_field_action_t action)
   7314 {
   7315     /* Text names of Actions. These are used for debugging output and CLIs.
   7316      * Note that the order needs to match the bcm_field_action_t enum order.
   7317      */
   7318     static char *action_text[] = BCM_FIELD_ACTION_STRINGS;
   7319     assert(COUNTOF(action_text) == bcmFieldActionCount);
   7320     return (action >= bcmFieldActionCount ? "??" : action_text[action]);
   7321 }
   7322 
   7323 #endif /* BROADCOM_DEBUG*/
   7324 
   7325 #if defined(BCM_FIREBOLT2_SUPPORT) 
   7326 /*
   7327  * Function:
   7328  *     _field_fb_egress_selcode_get
   7329  * Purpose:
   7330  *     Finds a select encodings that will satisfy the
   7331  *     requested qualifier set (Qset).
   7332  * Parameters:
   7333  *     unit      - (IN) BCM unit number.
   7334  *     stage_fc  - (IN) Stage Field control structure.
   7335  *     qset_req  - (IN) Client qualifier set.
   7336  *     fg        - (IN/OUT)Select code information filled into the group.  
   7337  * 
   7338  * Returns:
   7339  *     BCM_E_XXX
   7340  */
   7341 STATIC int
   7342 _field_fb_egress_selcode_get(int unit, _field_stage_t *stage_fc, 
   7343                                bcm_field_qset_t *qset_req,
   7344                                _field_group_t *fg)
   7345 {
   7346     int             rv;          /* Operation return status. */
   7347 
   7348     /* Input parameters check. */
   7349     if ((NULL == fg) || (NULL == qset_req) || (NULL == stage_fc)) {
   7350         return (BCM_E_PARAM);
   7351     }
   7352 
   7353     if  (fg->flags & _FP_GROUP_SPAN_SINGLE_SLICE) {
   7354         /* Attempt _BCM_FIELD_EFP_KEY4  (L2 key). */
   7355         rv = _bcm_field_egress_key_attempt(unit, stage_fc, qset_req, 
   7356                                            _BCM_FIELD_EFP_KEY4, 0, fg);
   7357         if (BCM_SUCCESS(rv) || (BCM_FAILURE(rv) && (rv != BCM_E_RESOURCE))) {
   7358             return rv;
   7359         }
   7360 
   7361         /* Attempt _BCM_FIELD_EFP_KEY1  (IPv4 key). */
   7362         if (BCM_FIELD_QSET_TEST(*qset_req, bcmFieldQualifyIp4)) {
   7363             rv = _bcm_field_egress_key_attempt(unit, stage_fc, qset_req, 
   7364                     _BCM_FIELD_EFP_KEY1, 0, fg);
   7365             if (BCM_SUCCESS(rv) || (BCM_FAILURE(rv) && (rv != BCM_E_RESOURCE))) {
   7366                 return rv;
   7367             }
   7368         }
   7369 
   7370         /* Attempt _BCM_FIELD_EFP_KEY2  (IPv6 key). */
   7371         if (BCM_FIELD_QSET_TEST(*qset_req, bcmFieldQualifyIp6)) {
   7372             rv = _bcm_field_egress_key_attempt(unit, stage_fc, qset_req, 
   7373                     _BCM_FIELD_EFP_KEY2, 0, fg);
   7374             if (BCM_SUCCESS(rv) || (BCM_FAILURE(rv) && (rv != BCM_E_RESOURCE))) {
   7375                 return rv;
   7376             }
   7377         }
   7378     }  else  {
   7379         /* IPv6 double wide predefined key. */
   7380         if (BCM_FIELD_QSET_TEST(*qset_req, bcmFieldQualifyIp6)) {
   7381             rv = _bcm_field_egress_key_attempt(unit, stage_fc, qset_req, 
   7382                     _BCM_FIELD_EFP_KEY3,
   7383                     _BCM_FIELD_EFP_KEY2, fg);
   7384             if (BCM_SUCCESS(rv) || (BCM_FAILURE(rv) && (rv != BCM_E_RESOURCE))) {
   7385                 return rv;
   7386             }
   7387         }
   7388 
   7389         /* L2 + L3 double wide predefined key. */
   7390         if (BCM_FIELD_QSET_TEST(*qset_req, bcmFieldQualifyIp4)) {
   7391             rv = _bcm_field_egress_key_attempt(unit, stage_fc, qset_req, 
   7392                     _BCM_FIELD_EFP_KEY1,
   7393                     _BCM_FIELD_EFP_KEY4, fg);
   7394             if (BCM_SUCCESS(rv) || (BCM_FAILURE(rv) && (rv != BCM_E_RESOURCE))) {
   7395                 return rv;
   7396             }
   7397         }
   7398     }
   7399     return (BCM_E_RESOURCE);
   7400 }
   7401 #endif /* BCM_FIREBOLT2_SUPPORT */
   7402 
   7403 
   7404 /*
   7405  * Function:
   7406  *     _bcm_field_fb_group_inner_vlan_overlay_get
   7407  * Purpose:
   7408  *     Returns inner vlan overlay for a group.
   7409  * Parameters:
   7410  *     uint    - (IN) BCM unit number.
   7411  *     value   - (OUT) Inner vlan overlay value.
   7412  * 
   7413  * Returns:
   7414  *     BCM_E_XXX
   7415  * Note:
   7416  */
   7417 int
   7418 _bcm_field_fb_group_inner_vlan_overlay_get (int unit, int *value)
   7419 {
   7420     _field_control_t *fc;    /* field control structure. */
   7421     _field_group_t   *fg;    /* field group structure.   */
   7422 
   7423     if (NULL == value) {
   7424         return (BCM_E_PARAM);
   7425     }
   7426 
   7427     /* Get field control strucutre.*/
   7428     BCM_IF_ERROR_RETURN(_field_control_get (unit, &fc));
   7429 
   7430     /* Iterate over all the groups to check for conflicts. */
   7431     fg = fc->groups;
   7432 
   7433     while (NULL != fg) {
   7434         if ((fg->stage_id == _BCM_FIELD_STAGE_INGRESS) && 
   7435             (_FP_SELCODE_DONT_CARE != fg->sel_codes[0].inner_vlan_overlay)) { 
   7436             *value = fg->sel_codes[0].inner_vlan_overlay;
   7437             break;
   7438         }
   7439         fg = fg->next;
   7440     }
   7441 
   7442     if (NULL == fg) {
   7443         *value = _FP_SELCODE_DONT_CARE;
   7444     }
   7445     return (BCM_E_NONE);
   7446 }
   7447 #if defined (BCM_FIREBOLT2_SUPPORT)
   7448 /*
   7449  * Function:
   7450  *     _bcm_field_vfp_doublewide_key_select_get
   7451  * Purpose:
   7452  *     Returns vfp doublewide key selection on FB2
   7453  * Parameters:
   7454  *     uint    - (IN) BCM unit number.
   7455  *     value   - (OUT) Inner vlan overlay value.
   7456  * 
   7457  * Returns:
   7458  *     BCM_E_RESOURCE - Conflict observed inside the group.
   7459  *     BCM_E_NONE     - otherwise
   7460  * Note:
   7461  */
   7462 int
   7463 _bcm_field_vfp_doublewide_key_select_get(int unit, int *value)
   7464 {
   7465     _field_control_t *fc;    /* field control structure. */
   7466     _field_group_t   *fg;    /* field group structure.   */
   7467 
   7468     if (NULL == value) {
   7469         return (BCM_E_PARAM);
   7470     }
   7471 
   7472     if (0 == SOC_IS_FIREBOLT2(unit)) {
   7473         *value = _FP_SELCODE_DONT_CARE; 
   7474         return (BCM_E_NONE);
   7475     }
   7476 
   7477     /* Get field control strucutre.*/
   7478     BCM_IF_ERROR_RETURN(_field_control_get (unit, &fc));
   7479 
   7480     /* Iterate over all the groups to check for conflicts. */
   7481     fg = fc->groups;
   7482 
   7483     while (NULL != fg) {
   7484         if ((fg->stage_id == _BCM_FIELD_STAGE_LOOKUP) && 
   7485             (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) &&
   7486             (_FP_SELCODE_DONT_CARE != fg->sel_codes[0].intraslice_vfp_sel)) { 
   7487             *value = fg->sel_codes[0].intraslice_vfp_sel;
   7488             break;
   7489         }
   7490         fg = fg->next;
   7491     }
   7492 
   7493     if (NULL == fg) {
   7494         *value = _FP_SELCODE_DONT_CARE;
   7495     }
   7496     return (BCM_E_NONE);
   7497 }
   7498 #endif /* BCM_FIREBOLT2_SUPPORT */
   7499 
   7500 
   7501 /*
   7502  * Function:
   7503  *     _field_fb_tcam_policy_clear
   7504  *
   7505  * Purpose:
   7506  *     Writes a null entry into the TCAM plus Policy table.
   7507  *
   7508  * Parameters:
   7509  *     unit      -   (IN)BCM device number.
   7510  *     stage_id  -   (IN)FP stage pipeline id. 
   7511  *     tcam_idx  -   (IN)Entry tcam index.
   7512  *     
   7513  * Returns:
   7514  *     BCM_E_XXX
   7515  *
   7516  * Note:
   7517  *     Unit lock should be held by calling function.
   7518  */
   7519 int
   7520 _field_fb_tcam_policy_clear(int unit, _field_entry_t *f_ent,
   7521                             _field_stage_id_t stage_id, int tcam_idx)
   7522 {
   7523     soc_mem_t tcam_mem;                 /* TCAM memory id.                    */
   7524     soc_mem_t policy_mem;               /* Policy table memory id .           */
   7525 
   7526     BCM_IF_ERROR_RETURN
   7527         (_field_fb_tcam_policy_mem_get(unit, stage_id, &tcam_mem, &policy_mem));
   7528     
   7529     /* Memory index sanity check. */
   7530     if (tcam_idx > soc_mem_index_max(unit, tcam_mem)) {
   7531         return (BCM_E_PARAM);
   7532     }  
   7533 
   7534     /* Write the TCAM & Policy Tables */
   7535     SOC_IF_ERROR_RETURN
   7536         (soc_mem_write(unit, tcam_mem, MEM_BLOCK_ALL, tcam_idx,
   7537                        soc_mem_entry_null(unit, tcam_mem)));
   7538     SOC_IF_ERROR_RETURN
   7539         (soc_mem_write(unit, policy_mem, MEM_BLOCK_ALL, tcam_idx,
   7540                        soc_mem_entry_null(unit, policy_mem)));
   7541 #ifdef BCM_TRIDENT2_SUPPORT
   7542     if (SOC_IS_TRIDENT2(unit) || SOC_IS_TITAN2(unit) || SOC_IS_TD2P_TT2P(unit)) {
   7543         if ((SOC_MEM_IS_VALID(unit, FP_GM_FIELDSm)) &&
   7544             (stage_id == _BCM_FIELD_STAGE_INGRESS) &&
   7545             (f_ent != NULL) && (f_ent->flags & _FP_ENTRY_SECONDARY)) {
   7546                 SOC_IF_ERROR_RETURN
   7547                     (soc_mem_write(unit, FP_GM_FIELDSm,
   7548                                    MEM_BLOCK_ALL, tcam_idx,
   7549                                    soc_mem_entry_null(unit, FP_GM_FIELDSm)));
   7550         } else if ((SOC_MEM_IS_VALID(unit, FP_GLOBAL_MASK_TCAMm)) &&
   7551                    (stage_id == _BCM_FIELD_STAGE_INGRESS)) {
   7552             SOC_IF_ERROR_RETURN
   7553                 (soc_mem_write(unit, FP_GLOBAL_MASK_TCAMm,
   7554                                MEM_BLOCK_ALL, tcam_idx,
   7555                                soc_mem_entry_null
   7556                                    (unit, FP_GLOBAL_MASK_TCAMm)));
   7557         }
   7558     } else
   7559 #endif
   7560 #if defined(BCM_TRIUMPH_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT)
   7561         if ((SOC_MEM_IS_VALID(unit, FP_GLOBAL_MASK_TCAMm)) && 
   7562             (stage_id == _BCM_FIELD_STAGE_INGRESS)) {
   7563             SOC_IF_ERROR_RETURN (soc_mem_write(unit, FP_GLOBAL_MASK_TCAMm,
   7564                                                MEM_BLOCK_ALL, tcam_idx,
   7565                                                soc_mem_entry_null(unit, FP_GLOBAL_MASK_TCAMm)));
   7566         }
   7567 #endif /* BCM_TRIUMPH_SUPPORT */
   7568 
   7569 #if defined(BCM_SCORPION_SUPPORT)
   7570         if ((SOC_IS_SC_CQ(unit)) && (stage_id == _BCM_FIELD_STAGE_INGRESS)) {
   7571             SOC_IF_ERROR_RETURN
   7572                 (soc_mem_write(unit, FP_TCAM_Ym,
   7573                                MEM_BLOCK_ALL, tcam_idx,
   7574                                soc_mem_entry_null(unit, FP_TCAM_Ym)));
   7575         }
   7576 #endif /* BCM_SCORPION_SUPPORT */
   7577 
   7578     return (BCM_E_NONE);
   7579 }
   7580 
   7581 
   7582 /*
   7583  * Function:
   7584  *     _bcm_field_fb_counter_adjust_wide_mode
   7585  * Purpose:
   7586  *     For wide mode entries, 
   7587  *     if there is movement across slices,
   7588  *     handle the counter mode and index
   7589  * Parameters:
   7590  *     unit - BCM unit
   7591  *     policy_mem - policy memory
   7592  *     f_st - Statistics collection entity. 
   7593  *     f_ent_pri - PRI entry
   7594  *     f_ent_sec - SEC entry
   7595  *     p_entry_pri - policy table for PRI entry
   7596  *     p_entry_sec - policy table for SEC entry
   7597  * Returns:
   7598  *     none
   7599  * Notes:
   7600  *     FOUR cases are to be handled 
   7601  *     1. previously counter in PRI slice, now in PRI slice
   7602  *     2. previously counter in PRI slice, now in SEC slice
   7603  *     3. previously counter in SEC slice, now in PRI slice
   7604  *     4. previously counter in SEC slice, now in SEC slice
   7605  */
   7606 void
   7607 _bcm_field_fb_counter_adjust_wide_mode(int unit, 
   7608                                    soc_mem_t policy_mem,
   7609                                    _field_stat_t *f_st,
   7610                                    _field_entry_t *f_ent_pri, 
   7611                                    _field_entry_t *f_ent_sec, 
   7612                                    int new_slice_numb,
   7613                                    uint32 p_entry_pri[],
   7614                                    uint32 p_entry_sec[])
   7615 {
   7616     int mode;
   7617 
   7618     if ((mode = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_pri, 
   7619                                     COUNTER_MODEf)) != 0) {
   7620         if (new_slice_numb == f_st->pool_index) {
   7621             soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri,
   7622                                 COUNTER_INDEXf, f_st->hw_index);
   7623             soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri,
   7624                                 COUNTER_MODEf, f_st->hw_mode);
   7625         } else if ((new_slice_numb + 1) == f_st->pool_index) {
   7626             soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri, 
   7627                                 COUNTER_MODEf, 0);
   7628             soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec, 
   7629                                 COUNTER_MODEf, f_st->hw_mode);
   7630             soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec,
   7631                                 COUNTER_INDEXf, f_st->hw_index);
   7632         }
   7633     } else if ((mode = soc_mem_field32_get(unit, policy_mem, 
   7634                 (uint32 *) p_entry_sec, COUNTER_MODEf)) != 0) {
   7635         if (new_slice_numb == f_st->pool_index) {
   7636             soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri, 
   7637                                 COUNTER_MODEf, f_st->hw_mode);
   7638             soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri,
   7639                                 COUNTER_INDEXf, f_st->hw_index);
   7640             soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec, 
   7641                                 COUNTER_MODEf, 0);
   7642         } else if ((new_slice_numb + 1) == f_st->pool_index) {
   7643             soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec,
   7644                                 COUNTER_INDEXf, f_st->hw_index);
   7645             soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec, 
   7646                                 COUNTER_MODEf, f_st->hw_mode);
   7647         }
   7648     }
   7649 }
   7650 
   7651 /*
   7652  * Function:
   7653  *     _bcm_field_fb_meter_adjust_wide_mode
   7654  * Purpose:
   7655  *     For wide mode entries, 
   7656  *     if there is movement across slices,
   7657  *     handle the meter mode, index, update & valid bits
   7658  * Parameters:
   7659  *     unit - BCM unit
   7660  *     policy_mem - policy memory
   7661  *     f_ent_pri - PRI entry
   7662  *     f_ent_sec - SEC entry
   7663  *     p_entry_pri - policy table for PRI entry
   7664  *     p_entry_sec - policy table for SEC entry
   7665  * Returns:
   7666  *     none
   7667  * Notes:
   7668  *     FOUR cases are to be handled 
   7669  *     1. previously meter in PRI slice, now in PRI slice
   7670  *     2. previously meter in PRI slice, now in SEC slice
   7671  *     3. previously meter in SEC slice, now in PRI slice
   7672  *     4. previously meter in SEC slice, now in SEC slice
   7673  *     MUST BE CALLED AFTER COUNTER ADJUST.
   7674  */
   7675 void
   7676 _bcm_field_fb_meter_adjust_wide_mode(int unit, 
   7677                                      soc_mem_t policy_mem,
   7678                                      _field_policer_t *f_pl,
   7679                                      _field_entry_t *f_ent_pri, 
   7680                                      _field_entry_t *f_ent_sec, 
   7681                                      uint32 p_entry_pri[],
   7682                                      uint32 p_entry_sec[])
   7683 {
   7684     uint32 counter_mode_pri;
   7685     uint32 counter_mode_sec;
   7686     uint32 counter_idx_pri;
   7687     uint32 counter_idx_sec;
   7688     int mode; 
   7689     int restore_counter = FALSE; 
   7690 
   7691 
   7692     /* Preserve counter mode. */
   7693     if (f_pl->stage_id == _BCM_FIELD_STAGE_EGRESS ) {
   7694         counter_mode_pri = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_pri, PID_COUNTER_MODEf);
   7695         counter_idx_pri = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_pri, PID_COUNTER_INDEXf);
   7696         counter_mode_sec = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_sec, PID_COUNTER_MODEf);
   7697         counter_idx_sec = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_sec, PID_COUNTER_INDEXf);
   7698     } else if (f_pl->stage_id == _BCM_FIELD_STAGE_LOOKUP) {
   7699         counter_mode_pri = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_pri, USE_VINTF_CTR_IDXf);
   7700         counter_idx_pri = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_pri, VINTF_CTR_IDXf);
   7701         counter_mode_sec = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_sec, USE_VINTF_CTR_IDXf);
   7702         counter_idx_sec = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_sec, VINTF_CTR_IDXf);
   7703     } else {
   7704         counter_mode_pri = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_pri, COUNTER_MODEf);
   7705         counter_idx_pri = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_pri, COUNTER_INDEXf);
   7706         counter_mode_sec = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_sec, COUNTER_MODEf);
   7707         counter_idx_sec = soc_mem_field32_get(unit, policy_mem, (uint32 *) p_entry_sec, COUNTER_INDEXf);
   7708     }
   7709     /* if meter to be moved is from primary slice*/
   7710     if ((mode = soc_mem_field32_get(unit, policy_mem, 
   7711          (uint32 *) p_entry_pri, METER_PAIR_MODEf)) != 0) {
   7712         if ((f_pl->stage_id == _BCM_FIELD_STAGE_EGRESS) &&
   7713             (SOC_IS_TRIDENT2PLUS(unit))) {
   7714             /* if the destination entry is allocated from primar slice,
   7715              * even or odd meter mode should be managed accordingly
   7716              */
   7717             if (!(f_ent_pri->flags & _FP_ENTRY_ALLOC_FROM_SECONDARY_SLICE)) {
   7718                 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri,
   7719                                 METER_INDEX_EVENf, f_pl->hw_index);
   7720                 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri,
   7721                                 METER_INDEX_ODDf, f_pl->hw_index);
   7722                 if (_FP_POLICER_EXCESS_HW_METER(f_pl)) {
   7723                    /* Excess meter - even index. */
   7724                    soc_mem_field32_set(unit, policy_mem,
   7725                                        (uint32 *) p_entry_pri,
   7726                                         METER_TEST_ODDf, 0);
   7727                    if (SOC_IS_KATANA2(unit) &&
   7728                        (f_pl->cfg.flags & BCM_POLICER_AS_PACKET_COUNTER)) {
   7729                        soc_mem_field32_set(unit, policy_mem,
   7730                                             (uint32 *) p_entry_pri,
   7731                                             METER_TEST_EVENf, 0);
   7732                    } else {
   7733                        soc_mem_field32_set(unit, policy_mem,
   7734                                             (uint32 *) p_entry_pri,
   7735                                             METER_TEST_EVENf, 1);
   7736                    }
   7737                    soc_mem_field32_set(unit, policy_mem,
   7738                                         (uint32 *) p_entry_pri,
   7739                                          METER_UPDATE_ODDf, 0);
   7740                    soc_mem_field32_set(unit, policy_mem,
   7741                                         (uint32 *) p_entry_pri,
   7742                                         METER_UPDATE_EVENf, 1);
   7743                 } else if (_FP_POLICER_COMMITTED_HW_METER(f_pl)) {
   7744                    /* Committed meter - odd index. */
   7745                     if (SOC_IS_KATANA2(unit) &&
   7746                         (f_pl->cfg.flags & BCM_POLICER_AS_PACKET_COUNTER)) {
   7747                         soc_mem_field32_set(unit, policy_mem,
   7748                                              (uint32 *) p_entry_pri,
   7749                                               METER_TEST_ODDf, 0);
   7750                     } else {
   7751                         soc_mem_field32_set(unit, policy_mem,
   7752                                              (uint32 *) p_entry_pri,
   7753                                              METER_TEST_ODDf, 1);
   7754                     }
   7755                     soc_mem_field32_set(unit, policy_mem,
   7756                                          (uint32 *) p_entry_pri,
   7757                                          METER_TEST_EVENf, 0);
   7758                     soc_mem_field32_set(unit, policy_mem,
   7759                                          (uint32 *) p_entry_pri,
   7760                                           METER_UPDATE_ODDf, 1);
   7761                     soc_mem_field32_set(unit, policy_mem,
   7762                                          (uint32 *) p_entry_pri,
   7763                                          METER_UPDATE_EVENf, 0);
   7764                 } else if (f_pl->cfg.mode == bcmPolicerModePassThrough) {
   7765                     soc_mem_field32_set(unit, policy_mem,
   7766                                          (uint32 *) p_entry_pri,
   7767                                          METER_TEST_EVENf, 1);
   7768                 }
   7769 #if defined(BCM_TRIDENT2_SUPPORT)
   7770                 else if (f_pl->cfg.mode == bcmPolicerModeSrTcmModified
   7771                         && (SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit))) {
   7772                     soc_mem_field32_set(unit, policy_mem,
   7773                                     (uint32 *) p_entry_pri,
   7774                                     METER_MODE_MODIFIERf, 1);
   7775                 }
   7776 #endif
   7777             } else {
   7778                 sal_memcpy(p_entry_sec, p_entry_pri,
   7779                       soc_mem_entry_words(unit, policy_mem)*sizeof(uint32));
   7780                 sal_memset(p_entry_pri, 0,
   7781                       soc_mem_entry_words(unit, policy_mem)*sizeof(uint32));
   7782                 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec,
   7783                                 METER_PAIR_MODEf, mode);
   7784                 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec,
   7785                                 METER_INDEX_EVENf, f_pl->hw_index);
   7786                 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec,
   7787                                 METER_INDEX_ODDf, f_pl->hw_index);
   7788                 restore_counter = TRUE;
   7789                 if (_FP_POLICER_EXCESS_HW_METER(f_pl)) {
   7790                    /* Excess meter - even index. */
   7791                    soc_mem_field32_set(unit, policy_mem,
   7792                                        (uint32 *) p_entry_sec,
   7793                                         METER_TEST_ODDf, 0);
   7794                    if (SOC_IS_KATANA2(unit) &&
   7795                        (f_pl->cfg.flags & BCM_POLICER_AS_PACKET_COUNTER)) {
   7796                        soc_mem_field32_set(unit, policy_mem,
   7797                                             (uint32 *) p_entry_sec,
   7798                                             METER_TEST_EVENf, 0);
   7799                    } else {
   7800                        soc_mem_field32_set(unit, policy_mem,
   7801                                             (uint32 *) p_entry_sec,
   7802                                             METER_TEST_EVENf, 1);
   7803                    }
   7804                    soc_mem_field32_set(unit, policy_mem,
   7805                                         (uint32 *) p_entry_sec,
   7806                                          METER_UPDATE_ODDf, 0);
   7807                    soc_mem_field32_set(unit, policy_mem,
   7808                                         (uint32 *) p_entry_sec,
   7809                                         METER_UPDATE_EVENf, 1);
   7810                 } else if (_FP_POLICER_COMMITTED_HW_METER(f_pl)) {
   7811                    /* Committed meter - odd index. */
   7812                     if (SOC_IS_KATANA2(unit) &&
   7813                         (f_pl->cfg.flags & BCM_POLICER_AS_PACKET_COUNTER)) {
   7814                         soc_mem_field32_set(unit, policy_mem,
   7815                                              (uint32 *) p_entry_sec,
   7816                                               METER_TEST_ODDf, 0);
   7817                     } else {
   7818                         soc_mem_field32_set(unit, policy_mem,
   7819                                              (uint32 *) p_entry_sec,
   7820                                              METER_TEST_ODDf, 1);
   7821                     }
   7822                     soc_mem_field32_set(unit, policy_mem,
   7823                                          (uint32 *) p_entry_sec,
   7824                                          METER_TEST_EVENf, 0);
   7825                     soc_mem_field32_set(unit, policy_mem,
   7826                                          (uint32 *) p_entry_sec,
   7827                                           METER_UPDATE_ODDf, 1);
   7828                     soc_mem_field32_set(unit, policy_mem,
   7829                                          (uint32 *) p_entry_sec,
   7830                                          METER_UPDATE_EVENf, 0);
   7831                 } else if (f_pl->cfg.mode == bcmPolicerModePassThrough) {
   7832                     soc_mem_field32_set(unit, policy_mem,
   7833                                          (uint32 *) p_entry_sec,
   7834                                          METER_TEST_EVENf, 1);
   7835                 }
   7836 #if defined(BCM_TRIDENT2_SUPPORT)
   7837                 else if (f_pl->cfg.mode == bcmPolicerModeSrTcmModified
   7838                         && (SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit))) {
   7839                     soc_mem_field32_set(unit, policy_mem,
   7840                                     (uint32 *) p_entry_sec,
   7841                                     METER_MODE_MODIFIERf, 1);
   7842                 }
   7843 #endif
   7844             }
   7845         } else {
   7846             if (f_ent_pri->fs->slice_number == f_pl->pool_index) {
   7847                 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri,
   7848                                     METER_INDEX_EVENf, f_pl->hw_index);
   7849                 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri,
   7850                                 METER_INDEX_ODDf, f_pl->hw_index);
   7851             
   7852             } else if (f_ent_sec->fs->slice_number == f_pl->pool_index) {
   7853                 sal_memcpy(p_entry_sec, p_entry_pri,
   7854                       soc_mem_entry_words(unit, policy_mem)*sizeof(uint32));
   7855                 sal_memset(p_entry_pri, 0,
   7856                        soc_mem_entry_words(unit, policy_mem)*sizeof(uint32));
   7857                 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec,
   7858                                 METER_PAIR_MODEf, mode);
   7859                 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec,
   7860                                 METER_INDEX_EVENf, f_pl->hw_index);
   7861                 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec,
   7862                                 METER_INDEX_ODDf, f_pl->hw_index);
   7863                 restore_counter = TRUE;
   7864             }
   7865         }
   7866     /* if source entry is allocated from secondary slice */
   7867     } else if ((mode = soc_mem_field32_get(unit, policy_mem, 
   7868                 (uint32 *) p_entry_sec, METER_PAIR_MODEf)) != 0) {
   7869 
   7870         if ((f_pl->stage_id == _BCM_FIELD_STAGE_EGRESS) &&
   7871             (SOC_IS_TRIDENT2PLUS(unit))) {
   7872             if (!(f_ent_pri->flags & _FP_ENTRY_ALLOC_FROM_SECONDARY_SLICE)) {
   7873                 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri,
   7874                                 METER_INDEX_EVENf, f_pl->hw_index);
   7875                 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri,
   7876                                 METER_INDEX_ODDf, f_pl->hw_index);
   7877                 if (_FP_POLICER_EXCESS_HW_METER(f_pl)) {
   7878                    /* Excess meter - even index. */
   7879                    soc_mem_field32_set(unit, policy_mem,
   7880                                        (uint32 *) p_entry_pri,
   7881                                         METER_TEST_ODDf, 0);
   7882                    if (SOC_IS_KATANA2(unit) &&
   7883                        (f_pl->cfg.flags & BCM_POLICER_AS_PACKET_COUNTER)) {
   7884                        soc_mem_field32_set(unit, policy_mem,
   7885                                             (uint32 *) p_entry_pri,
   7886                                             METER_TEST_EVENf, 0);
   7887                    } else {
   7888                        soc_mem_field32_set(unit, policy_mem,
   7889                                             (uint32 *) p_entry_pri,
   7890                                             METER_TEST_EVENf, 1);
   7891                    }
   7892                    soc_mem_field32_set(unit, policy_mem,
   7893                                         (uint32 *) p_entry_pri,
   7894                                          METER_UPDATE_ODDf, 0);
   7895                    soc_mem_field32_set(unit, policy_mem,
   7896                                         (uint32 *) p_entry_pri,
   7897                                         METER_UPDATE_EVENf, 1);
   7898                 } else if (_FP_POLICER_COMMITTED_HW_METER(f_pl)) {
   7899                    /* Committed meter - odd index. */
   7900                     if (SOC_IS_KATANA2(unit) &&
   7901                         (f_pl->cfg.flags & BCM_POLICER_AS_PACKET_COUNTER)) {
   7902                         soc_mem_field32_set(unit, policy_mem,
   7903                                              (uint32 *) p_entry_pri,
   7904                                               METER_TEST_ODDf, 0);
   7905                     } else {
   7906                         soc_mem_field32_set(unit, policy_mem,
   7907                                              (uint32 *) p_entry_pri,
   7908                                              METER_TEST_ODDf, 1);
   7909                     }
   7910                     soc_mem_field32_set(unit, policy_mem,
   7911                                          (uint32 *) p_entry_pri,
   7912                                          METER_TEST_EVENf, 0);
   7913                     soc_mem_field32_set(unit, policy_mem,
   7914                                          (uint32 *) p_entry_pri,
   7915                                           METER_UPDATE_ODDf, 1);
   7916                     soc_mem_field32_set(unit, policy_mem,
   7917                                          (uint32 *) p_entry_pri,
   7918                                          METER_UPDATE_EVENf, 0);
   7919                 } else if (f_pl->cfg.mode == bcmPolicerModePassThrough) {
   7920                     soc_mem_field32_set(unit, policy_mem,
   7921                                          (uint32 *) p_entry_pri,
   7922                                          METER_TEST_EVENf, 1);
   7923                 }
   7924 #if defined(BCM_TRIDENT2_SUPPORT)
   7925                 else if (f_pl->cfg.mode == bcmPolicerModeSrTcmModified
   7926                         && (SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit))) {
   7927                     soc_mem_field32_set(unit, policy_mem,
   7928                                     (uint32 *) p_entry_pri,
   7929                                     METER_MODE_MODIFIERf, 1);
   7930                 }
   7931 #endif
   7932             } else {
   7933                 sal_memcpy(p_entry_sec, p_entry_pri,
   7934                       soc_mem_entry_words(unit, policy_mem)*sizeof(uint32));
   7935                 sal_memset(p_entry_pri, 0,
   7936                        soc_mem_entry_words(unit, policy_mem)*sizeof(uint32));
   7937                 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec,
   7938                                 METER_PAIR_MODEf, mode);
   7939                 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec,
   7940                                 METER_INDEX_EVENf, f_pl->hw_index);
   7941                 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec,
   7942                                 METER_INDEX_ODDf, f_pl->hw_index);
   7943                 restore_counter = TRUE;
   7944                 if (_FP_POLICER_EXCESS_HW_METER(f_pl)) {
   7945                    /* Excess meter - even index. */
   7946                    soc_mem_field32_set(unit, policy_mem,
   7947                                        (uint32 *) p_entry_sec,
   7948                                         METER_TEST_ODDf, 0);
   7949                    if (SOC_IS_KATANA2(unit) &&
   7950                        (f_pl->cfg.flags & BCM_POLICER_AS_PACKET_COUNTER)) {
   7951                        soc_mem_field32_set(unit, policy_mem,
   7952                                             (uint32 *) p_entry_sec,
   7953                                             METER_TEST_EVENf, 0);
   7954                    } else {
   7955                        soc_mem_field32_set(unit, policy_mem,
   7956                                             (uint32 *) p_entry_sec,
   7957                                             METER_TEST_EVENf, 1);
   7958                    }
   7959                    soc_mem_field32_set(unit, policy_mem,
   7960                                         (uint32 *) p_entry_sec,
   7961                                          METER_UPDATE_ODDf, 0);
   7962                    soc_mem_field32_set(unit, policy_mem,
   7963                                         (uint32 *) p_entry_sec,
   7964                                         METER_UPDATE_EVENf, 1);
   7965                 } else if (_FP_POLICER_COMMITTED_HW_METER(f_pl)) {
   7966                    /* Committed meter - odd index. */
   7967                     if (SOC_IS_KATANA2(unit) &&
   7968                         (f_pl->cfg.flags & BCM_POLICER_AS_PACKET_COUNTER)) {
   7969                         soc_mem_field32_set(unit, policy_mem,
   7970                                              (uint32 *) p_entry_sec,
   7971                                               METER_TEST_ODDf, 0);
   7972                     } else {
   7973                         soc_mem_field32_set(unit, policy_mem,
   7974                                              (uint32 *) p_entry_sec,
   7975                                              METER_TEST_ODDf, 1);
   7976                     }
   7977                     soc_mem_field32_set(unit, policy_mem,
   7978                                          (uint32 *) p_entry_sec,
   7979                                          METER_TEST_EVENf, 0);
   7980                     soc_mem_field32_set(unit, policy_mem,
   7981                                          (uint32 *) p_entry_sec,
   7982                                           METER_UPDATE_ODDf, 1);
   7983                     soc_mem_field32_set(unit, policy_mem,
   7984                                          (uint32 *) p_entry_sec,
   7985                                          METER_UPDATE_EVENf, 0);
   7986                 } else if (f_pl->cfg.mode == bcmPolicerModePassThrough) {
   7987                     soc_mem_field32_set(unit, policy_mem,
   7988                                          (uint32 *) p_entry_sec,
   7989                                          METER_TEST_EVENf, 1);
   7990                 }
   7991 #if defined(BCM_TRIDENT2_SUPPORT)
   7992                 else if (f_pl->cfg.mode == bcmPolicerModeSrTcmModified
   7993                         && (SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit))) {
   7994                     soc_mem_field32_set(unit, policy_mem,
   7995                                     (uint32 *) p_entry_sec,
   7996                                     METER_MODE_MODIFIERf, 1);
   7997                 }
   7998 #endif
   7999             }
   8000         } else {
   8001             if (f_ent_pri->fs->slice_number == f_pl->pool_index) {
   8002                 sal_memcpy(p_entry_pri, p_entry_sec,
   8003                      soc_mem_entry_words(unit, policy_mem)*sizeof(uint32));
   8004                 sal_memset(p_entry_sec, 0,
   8005                       soc_mem_entry_words(unit, policy_mem)*sizeof(uint32));
   8006                 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri,
   8007                                 METER_PAIR_MODEf, mode);
   8008                 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri,
   8009                                 METER_INDEX_EVENf, f_pl->hw_index);
   8010                 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri,
   8011                                 METER_INDEX_ODDf, f_pl->hw_index);
   8012                 restore_counter = TRUE;
   8013             } else if (f_ent_sec->fs->slice_number == f_pl->pool_index) {
   8014                 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec,
   8015                                 METER_INDEX_EVENf, f_pl->hw_index);
   8016                 soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec,
   8017                                 METER_INDEX_ODDf, f_pl->hw_index);
   8018             }
   8019         }
   8020     }
   8021 
   8022     if (restore_counter) {
   8023         if (f_pl->stage_id == _BCM_FIELD_STAGE_EGRESS ) {
   8024             soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec,
   8025                                 PID_COUNTER_INDEXf, counter_idx_sec);
   8026             soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec,
   8027                                 PID_COUNTER_MODEf, counter_mode_sec);
   8028             soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri,
   8029                                 PID_COUNTER_INDEXf, counter_idx_pri);
   8030             soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri,
   8031                                 PID_COUNTER_MODEf, counter_mode_pri);
   8032         } if (f_pl->stage_id == _BCM_FIELD_STAGE_LOOKUP ) {
   8033             soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec,
   8034                                 VINTF_CTR_IDXf, counter_idx_sec);
   8035             soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec,
   8036                                 USE_VINTF_CTR_IDXf, counter_mode_sec);
   8037             soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri,
   8038                                 VINTF_CTR_IDXf, counter_idx_pri);
   8039             soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri,
   8040                                 USE_VINTF_CTR_IDXf, counter_mode_pri);
   8041         } else {
   8042             soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec,
   8043                                 COUNTER_INDEXf, counter_idx_sec);
   8044             soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_sec,
   8045                                 COUNTER_MODEf, counter_mode_sec);
   8046             soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri,
   8047                                 COUNTER_INDEXf, counter_idx_pri);
   8048             soc_mem_field32_set(unit, policy_mem, (uint32 *) p_entry_pri,
   8049                                 COUNTER_MODEf, counter_mode_pri);
   8050         }
   8051     }
   8052 }
   8053 
   8054 /*
   8055  * Function:
   8056  *     _bcm_field_fb_entry_move
   8057  * Purpose:
   8058  *     Copy an entry from one TCAM index to another. It copies the values in
   8059  *     hardware from the old index to the new index. 
   8060  *     IT IS ASSUMED THAT THE NEW INDEX IS EMPTY (VALIDf=00) IN HARDWARE.
   8061  *     The old Hardware index is cleared at the end.
   8062  * Parameters:
   8063  *     unit           - (IN) BCM device number. 
   8064  *     f_ent          - (IN) Entry to move
   8065  *     parts_count    - (IN) Field entry parts count.
   8066  *     tcam_idx_old   - (IN) Source entry tcam index.
   8067  *     tcam_idx_new   - (IN) Destination entry tcam index.
   8068  *                          
   8069  * Returns:
   8070  *     BCM_E_XXX
   8071  */
   8072 int
   8073 _bcm_field_fb_entry_move(int unit, _field_entry_t *f_ent, int parts_count,
   8074                          int *tcam_idx_old, int *tcam_idx_new)
   8075 {
   8076     static uint32 e_buf[BCM_MAX_NUM_UNITS][25];
   8077                                         /* For TCAM                           */
   8078     static uint32 p_buf[BCM_MAX_NUM_UNITS][_FP_MAX_ENTRY_WIDTH][25];
   8079                                         /* For policies                       */
   8080     int new_slice_numb = 0;             /* Entry new slice number.            */
   8081     int new_slice_idx = 0;              /* Entry new offset in the slice      */
   8082     soc_mem_t tcam_mem;                 /* TCAM memory id.                    */
   8083     soc_mem_t policy_mem;               /* Policy table memory id .           */
   8084     int tcam_idx_max;                   /* TCAM memory max index.             */
   8085     int tcam_idx_min;                   /* TCAM memory min index.             */
   8086     _field_stage_t *stage_fc;           /* Stage field control structure.     */
   8087     _field_stage_id_t stage_id;         /* Field pipeline stage id.           */
   8088     int idx;                            /* Iteration index.                   */
   8089     _field_policer_t *f_pl = NULL;      /* Field policer descriptor.          */
   8090     _field_stat_t    *f_st = NULL;      /* Field statistics descriptor.       */
   8091     _field_group_t   *fg;               /* Field group structure.             */
   8092     int              rv;                /* Operation return status.           */
   8093     int      is_backup_entry = 0;       /* Flag ,checks the entry is backup entry or not*/
   8094 #ifdef BCM_TRIUMPH_SUPPORT
   8095     fp_global_mask_tcam_entry_t ipbm_entry[_FP_MAX_ENTRY_WIDTH]; /* Always in PRI entry, 1st half */
   8096 #endif /* BCM_TRIUMPH_SUPPORT */
   8097 #ifdef BCM_TRIDENT_SUPPORT
   8098     fp_global_mask_tcam_x_entry_t fp_global_mask_x[_FP_MAX_ENTRY_WIDTH];
   8099     fp_global_mask_tcam_y_entry_t fp_global_mask_y[_FP_MAX_ENTRY_WIDTH];
   8100     fp_global_mask_tcam_entry_t fp_global_mask[_FP_MAX_ENTRY_WIDTH];
   8101     fp_gm_fields_entry_t fp_gm_fields[_FP_MAX_ENTRY_WIDTH];
   8102     bcm_pbmp_t pbmp_x, pbmp_y;
   8103 #endif /* !BCM_TRIDENT_SUPPORT */
   8104 
   8105 
   8106     /* Input parameters check. */
   8107     if ((NULL == f_ent) || (NULL == tcam_idx_old) || (NULL == tcam_idx_new)) {
   8108         return (BCM_E_PARAM);
   8109     }
   8110 
   8111     fg = f_ent->group;
   8112 
   8113     /* Get field stage control . */
   8114     stage_id = f_ent->group->stage_id;
   8115     rv = _field_stage_control_get(unit, stage_id, &stage_fc);      
   8116     BCM_IF_ERROR_RETURN(rv);
   8117 
   8118     /* Get entry tcam and actions. */
   8119     rv = _field_fb_tcam_policy_mem_get(unit, stage_id, &tcam_mem, &policy_mem);
   8120     BCM_IF_ERROR_RETURN(rv);
   8121 
   8122     tcam_idx_max = soc_mem_index_max(unit, tcam_mem);
   8123     tcam_idx_min = soc_mem_index_min(unit, tcam_mem);
   8124 
   8125     /* Update policy entry if moving across the slices. */
   8126     if (((NULL != f_ent->ent_copy) && 
   8127                 (f_ent->ent_copy->eid ==  _FP_INTERNAL_RESERVED_ID))) {
   8128         is_backup_entry = 1;
   8129     }
   8130 
   8131     for (idx = 0; idx < parts_count; idx++) {
   8132         /* Index sanity check. */
   8133         if ((tcam_idx_old[idx] < tcam_idx_min) || (tcam_idx_old[idx] > tcam_idx_max) ||
   8134             (tcam_idx_new[idx] < tcam_idx_min) || (tcam_idx_new[idx] > tcam_idx_max)) {
   8135             LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
   8136               "Invalid index range from %d to %d."),
   8137               tcam_idx_old[idx], tcam_idx_new[idx]));
   8138 
   8139             rv = BCM_E_PARAM;
   8140             /* coverity[dead_error_line:FALSE] */
   8141             BCM_IF_ERROR_RETURN(rv);
   8142         }
   8143 
   8144         /* Read policy entry from current tcam index. */
   8145         rv = soc_mem_read(unit, policy_mem, MEM_BLOCK_ANY, tcam_idx_old[idx],
   8146                           p_buf[unit][idx]);
   8147         BCM_IF_ERROR_RETURN(rv);
   8148 
   8149 #ifdef BCM_TRIDENT_SUPPORT
   8150         /*
   8151          * On Trident, VALIDf of FP_GLOBAL_MASK_TCAMm must be set
   8152          * for all parts of an wide/paired mode entry.
   8153          * This bit would have been set during entry install.
   8154          * Read this value from all parts of an entry while moving.
   8155          * Otherwise, actions related to this entry would not work.
   8156          */
   8157         if (SOC_IS_TD_TT(unit) && (stage_id == _BCM_FIELD_STAGE_INGRESS)) {
   8158             if ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE)
   8159                 && (0x1 & idx)) {
   8160                 rv = READ_FP_GM_FIELDSm(unit, MEM_BLOCK_ANY,
   8161                         tcam_idx_old[idx], &fp_gm_fields[idx]);
   8162                 BCM_IF_ERROR_RETURN(rv);
   8163             } else {
   8164                 rv = READ_FP_GLOBAL_MASK_TCAMm(unit, MEM_BLOCK_ANY,
   8165                         tcam_idx_old[idx], &fp_global_mask[idx]);
   8166                 BCM_IF_ERROR_RETURN(rv);
   8167             }
   8168         } else
   8169 #endif /* !BCM_TRIDENT_SUPPORT */
   8170 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   8171         if ((SOC_IS_KATANAX(unit)
   8172             || SOC_IS_TRIUMPH3(unit))
   8173             && (stage_id == _BCM_FIELD_STAGE_INGRESS)) {
   8174             rv = READ_FP_GLOBAL_MASK_TCAMm(unit, MEM_BLOCK_ANY,
   8175                     tcam_idx_old[idx], &ipbm_entry[idx]);
   8176             BCM_IF_ERROR_RETURN(rv);
   8177         } else
   8178 #endif /* BCM_KATANA_SUPPORT */       
   8179 #if defined(BCM_TRIUMPH_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT)
   8180         {
   8181             if ((SOC_MEM_IS_VALID(unit, FP_GLOBAL_MASK_TCAMm))
   8182                 && (stage_id == _BCM_FIELD_STAGE_INGRESS)) {
   8183                 rv = READ_FP_GLOBAL_MASK_TCAMm(unit, MEM_BLOCK_ANY,
   8184                         tcam_idx_old[idx], &ipbm_entry[idx]);
   8185                 BCM_IF_ERROR_RETURN(rv);
   8186             }
   8187         }
   8188 #endif /* BCM_TRIUMPH_SUPPORT || BCM_TRIUMPH2_SUPPORT */
   8189     }
   8190 
   8191     /* Calculate primary entry new slice & offset in the slice. */
   8192     rv = _bcm_field_tcam_idx_to_slice_offset(unit, stage_fc, _FP_DEF_INST, 
   8193                                              tcam_idx_new[0],
   8194                                              &new_slice_numb, &new_slice_idx);
   8195     BCM_IF_ERROR_RETURN(rv);
   8196 
   8197     /* Update policy entry if moving across the slices. */
   8198     if ((1 != is_backup_entry) && (f_ent->fs->slice_number != new_slice_numb)) {
   8199         /* Get policer associated with the entry. */
   8200         if ((0 == (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)) &&
   8201             (f_ent->policer[0].flags & _FP_POLICER_INSTALLED)) {
   8202              rv = _bcm_field_policer_get(unit,
   8203                                          f_ent->policer[0].pid, 
   8204                                          &f_pl);
   8205              BCM_IF_ERROR_RETURN(rv);
   8206         }
   8207         /* Get statistics entity associated with the entry. */
   8208         if ((0 == (stage_fc->flags & _FP_STAGE_GLOBAL_COUNTERS)) &&
   8209             (0 == (stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS)) &&
   8210             (f_ent->statistic.flags & _FP_ENTRY_STAT_INSTALLED)) {
   8211             rv = _bcm_field_stat_get(unit,
   8212                                      f_ent->statistic.sid, 
   8213                                      &f_st);
   8214             BCM_IF_ERROR_RETURN(rv);
   8215         }
   8216         if (fg->flags & (_FP_GROUP_SPAN_SINGLE_SLICE | 
   8217                          _FP_GROUP_INTRASLICE_DOUBLEWIDE)) {
   8218             /*
   8219              * For _FP_GROUP_INTRASLICE_DOUBLEWIDE, *even* if it is  
   8220              *     _FP_GROUP_SPAN_DOUBLE_SLICE, we do this.
   8221              *     This is because in intraslice double-wide, the PRI 
   8222              *     slice has tcam_slice_sz/2 entries, and same number
   8223              *     of counter/meter pairs.
   8224              *         Thus, counter/meter will always be allocated in the 
   8225              *         PRI slice.
   8226              */
   8227             if (NULL != f_st) {
   8228                 /* 
   8229                  * Set the index of the counter for entry in new slice
   8230                  * The new index has already been calculated in 
   8231                  * _field_entry_move
   8232                  */
   8233 
   8234                 if (stage_id == _BCM_FIELD_STAGE_EGRESS ) {
   8235                     soc_mem_field32_set(unit, policy_mem, p_buf[unit][0],
   8236                                         PID_COUNTER_INDEXf, f_st->hw_index);
   8237                     soc_mem_field32_set(unit, policy_mem, p_buf[unit][0],
   8238                                         PID_COUNTER_MODEf, f_st->hw_mode);
   8239                 } else if (stage_id == _BCM_FIELD_STAGE_LOOKUP ) {
   8240                     soc_mem_field32_set(unit, policy_mem, p_buf[unit][0],
   8241                                         VINTF_CTR_IDXf, f_st->hw_index);
   8242                     soc_mem_field32_set(unit, policy_mem, p_buf[unit][0],
   8243                                         USE_VINTF_CTR_IDXf, f_st->hw_mode);
   8244                 } else {
   8245                     soc_mem_field32_set(unit, policy_mem, p_buf[unit][0],
   8246                                         COUNTER_INDEXf, f_st->hw_index);
   8247                     soc_mem_field32_set(unit, policy_mem, p_buf[unit][0],
   8248                                         COUNTER_MODEf, f_st->hw_mode);
   8249                 }
   8250             }
   8251             if (NULL != f_pl) {
   8252                 /* 
   8253                  * Set the index of the meter for entry in new slice
   8254                  * The new index has already been calculated in 
   8255                  * _field_entry_move
   8256                  */
   8257                 soc_mem_field32_set(unit, policy_mem, p_buf[unit][0],
   8258                                     METER_INDEX_EVENf, f_pl->hw_index);
   8259                 soc_mem_field32_set(unit, policy_mem, p_buf[unit][0],
   8260                                     METER_INDEX_ODDf, f_pl->hw_index);
   8261             }
   8262         } else {
   8263             if (NULL != f_st) {
   8264                 _bcm_field_fb_counter_adjust_wide_mode(unit, policy_mem, 
   8265                                                        f_st, f_ent, 
   8266                                                        f_ent + 1, 
   8267                                                        new_slice_numb,
   8268                                                        p_buf[unit][0],
   8269                                                        p_buf[unit][1]);
   8270             }
   8271             if (NULL != f_pl) {
   8272                 _bcm_field_fb_meter_adjust_wide_mode(unit, policy_mem,
   8273                                                      f_pl, f_ent, f_ent + 1, 
   8274                                                      p_buf[unit][0],
   8275                                                      p_buf[unit][1]);
   8276             }
   8277         } 
   8278     }
   8279 
   8280     /* 
   8281      * Write entry to the destination
   8282      * ORDER is important
   8283      */ 
   8284     for (idx = parts_count - 1; idx >= 0; idx--) {
   8285 
   8286         /* Write duplicate  policy entry to new tcam index. */
   8287         rv = soc_mem_write(unit, policy_mem, MEM_BLOCK_ALL, tcam_idx_new[idx],
   8288                            p_buf[unit][idx]);
   8289         BCM_IF_ERROR_RETURN(rv);
   8290 #ifdef BCM_TRIDENT_SUPPORT
   8291         if ((SOC_IS_TD_TT(unit)) && (stage_id == _BCM_FIELD_STAGE_INGRESS)) {
   8292             if ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE)
   8293                 && (0x1 & idx)) {
   8294                 rv = WRITE_FP_GM_FIELDSm(unit, MEM_BLOCK_ALL,
   8295                         tcam_idx_new[idx], &fp_gm_fields[idx]);
   8296                 BCM_IF_ERROR_RETURN(rv);
   8297             } else {
   8298                 rv = READ_FP_GLOBAL_MASK_TCAM_Xm(unit, MEM_BLOCK_ANY,
   8299                         tcam_idx_old[idx], &fp_global_mask_x[idx]);
   8300                 BCM_IF_ERROR_RETURN(rv);
   8301                 rv = READ_FP_GLOBAL_MASK_TCAM_Ym(unit, MEM_BLOCK_ANY,
   8302                         tcam_idx_old[idx], &fp_global_mask_y[idx]);
   8303                 BCM_IF_ERROR_RETURN(rv);
   8304 
   8305                 soc_mem_pbmp_field_get(unit, FP_GLOBAL_MASK_TCAM_Xm, &fp_global_mask_x[idx],
   8306                                        IPBMf, &pbmp_x);
   8307                 soc_mem_pbmp_field_get(unit, FP_GLOBAL_MASK_TCAM_Ym, &fp_global_mask_y[idx],
   8308                                        IPBMf, &pbmp_y); 
   8309                 BCM_PBMP_OR(pbmp_x, pbmp_y); 
   8310 
   8311                 soc_mem_pbmp_field_set(unit,
   8312                                        FP_GLOBAL_MASK_TCAMm,
   8313                                        &fp_global_mask[idx],
   8314                                        IPBMf,
   8315                                        &pbmp_x
   8316                                        );
   8317 
   8318                 soc_mem_pbmp_field_get(unit, FP_GLOBAL_MASK_TCAM_Xm, &fp_global_mask_x[idx],
   8319                                        IPBM_MASKf, &pbmp_x);
   8320                 soc_mem_pbmp_field_get(unit, FP_GLOBAL_MASK_TCAM_Ym, &fp_global_mask_y[idx],
   8321                                        IPBM_MASKf, &pbmp_y);
   8322                 BCM_PBMP_OR(pbmp_x, pbmp_y);
   8323 
   8324                 soc_mem_pbmp_field_set(unit,
   8325                                        FP_GLOBAL_MASK_TCAMm,
   8326                                        &fp_global_mask[idx],
   8327                                        IPBM_MASKf,
   8328                                        &pbmp_x
   8329                                        );
   8330 
   8331 
   8332                 rv = WRITE_FP_GLOBAL_MASK_TCAMm(unit, MEM_BLOCK_ALL,
   8333                         tcam_idx_new[idx], &fp_global_mask[idx]);
   8334                 BCM_IF_ERROR_RETURN(rv);
   8335             }
   8336         } else
   8337 #endif
   8338 #if defined (BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
   8339         if ((SOC_IS_KATANAX(unit)
   8340              || SOC_IS_TRIUMPH3(unit))
   8341             && (stage_id == _BCM_FIELD_STAGE_INGRESS)) {
   8342             rv = WRITE_FP_GLOBAL_MASK_TCAMm(unit, MEM_BLOCK_ALL, 
   8343                 tcam_idx_new[idx], &ipbm_entry[idx]);
   8344             BCM_IF_ERROR_RETURN(rv);
   8345         } else
   8346 #endif /* BCM_KATANA_SUPPORT */            
   8347 #ifdef BCM_TRIUMPH_SUPPORT
   8348         {
   8349             if ((SOC_IS_TR_VL(unit)) && 
   8350                 (stage_id == _BCM_FIELD_STAGE_INGRESS)) {
   8351                 rv = WRITE_FP_GLOBAL_MASK_TCAMm(unit, MEM_BLOCK_ALL, 
   8352                         tcam_idx_new[idx], &ipbm_entry[idx]);
   8353                 BCM_IF_ERROR_RETURN(rv);
   8354             }
   8355         }
   8356 #endif /* BCM_TRIUMPH_SUPPORT */
   8357 
   8358 #ifdef BCM_SCORPION_SUPPORT
   8359         /*
   8360          * Writing IPBMf value into FP_TCAMm sets IPBMf in FP_TCAM_Xm
   8361          * and FP_TCAM_Ym but clears IPBM_MASKf in FP_TCAM_Ym unexpectedly. 
   8362          * Similarly setting IPBM_MASKf in FP_TCAMm sets IPBM_MASKf in 
   8363          * FP_TCAM_Xm and FP_TCAM_Ym but clears IPBMf in FP_TCAM_Ym unexpectedly.
   8364          * On scorpion family, read and write entries only from FP_TCAM_Xm and 
   8365          * FP_TCAM_Ym. Avoid Read/Write into FP_TCAMm while moving entries.
   8366          * Read is also not good on FP_TCAMm, as Read operation returns values 
   8367          * from FP_TCAM_Xm only.
   8368          */
   8369         if ((SOC_IS_SC_CQ(unit)) && (stage_id == _BCM_FIELD_STAGE_INGRESS)) {
   8370             rv = soc_mem_read(unit, FP_TCAM_Xm, MEM_BLOCK_ANY,
   8371                               tcam_idx_old[idx], e_buf[unit]);
   8372             BCM_IF_ERROR_RETURN(rv);
   8373 
   8374             rv = soc_mem_write(unit, FP_TCAM_Xm, MEM_BLOCK_ALL,
   8375                                tcam_idx_new[idx], e_buf[unit]);
   8376             BCM_IF_ERROR_RETURN(rv);
   8377 
   8378             rv = soc_mem_read(unit, FP_TCAM_Ym, MEM_BLOCK_ANY,
   8379                               tcam_idx_old[idx], e_buf[unit]);
   8380             BCM_IF_ERROR_RETURN(rv);
   8381 
   8382             rv = soc_mem_write(unit, FP_TCAM_Ym, MEM_BLOCK_ALL,
   8383                                tcam_idx_new[idx], e_buf[unit]);
   8384             BCM_IF_ERROR_RETURN(rv);
   8385 
   8386         } else 
   8387 #endif /* BCM_SCORPION_SUPPORT */
   8388         {
   8389             /* Read tcam entry from current tcam index. */
   8390             rv = soc_mem_read(unit, tcam_mem, MEM_BLOCK_ANY,
   8391                               tcam_idx_old[idx], e_buf[unit]);
   8392             BCM_IF_ERROR_RETURN(rv);
   8393 
   8394             /* Write duplicate  tcam entry to new tcam index. */
   8395             rv = soc_mem_write(unit, tcam_mem, MEM_BLOCK_ALL,
   8396                                tcam_idx_new[idx], e_buf[unit]);
   8397             BCM_IF_ERROR_RETURN(rv);
   8398         }
   8399     }
   8400 
   8401 
   8402 
   8403     /*    
   8404      * fp_entry_move is invoked even for backup entry create 
   8405      * to copy TCAM and FP_POLICY_TABLE tables. In this case
   8406      * TCAM and FP_POLICY_TABLEs should not be erased for
   8407      * original entry.
   8408      */
   8409     if (1 != is_backup_entry) {
   8410         /*
   8411          * Clear old location 
   8412          * ORDER is important
   8413          */
   8414         for (idx = 0; idx < parts_count; idx++) {
   8415             rv = _field_fb_tcam_policy_clear(unit, NULL, stage_id, tcam_idx_old[idx]);
   8416             BCM_IF_ERROR_RETURN(rv);
   8417         }
   8418     }
   8419     return (BCM_E_NONE);
   8420 }
   8421 
   8422 /*
   8423  * Function:
   8424  *     _field_fb_stat_action_set
   8425  *
   8426  * Purpose:
   8427  *     Get counter portion of Policy Table.
   8428  *
   8429  * Parameters:
   8430  *     unit      - (IN)BCM device number. 
   8431  *     f_ent     - (IN)Software entry structure to get tcam info from.
   8432  *     mem       - (IN)Policy table memory. 
   8433  *     buf       - (IN/OUT)Hardware policy entry
   8434  *
   8435  * Returns:
   8436  *     BCM_E_XXX
   8437  */
   8438 STATIC int
   8439 _field_fb_stat_action_set(int unit, _field_entry_t *f_ent,
   8440                        soc_mem_t mem, uint32 *buf)
   8441 {
   8442     _field_stat_t    *f_st;    /* Field policer descriptor. */  
   8443     int mode;              /* Counter hw mode.          */                    
   8444     int idx;               /* Counter index.            */
   8445 
   8446     /* Input parameter check. */
   8447     if ((NULL == f_ent) || (NULL == buf))  {
   8448         return (BCM_E_PARAM);
   8449     }
   8450     if (NULL == f_ent->group) {
   8451         return (BCM_E_PARAM);
   8452     }
   8453 
   8454 #if defined(BCM_FIREBOLT2_SUPPORT)
   8455     /* VFP doesn't have counters. */
   8456     if ((_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id)) {
   8457         return (BCM_E_NONE);
   8458     }
   8459 #endif /* BCM_FIREBOLT2_SUPPORT */
   8460 
   8461 
   8462     /* Disable counting if counter was not attached to the entry. */
   8463     if ((0 == (f_ent->statistic.flags & _FP_ENTRY_STAT_INSTALLED)) ||
   8464         ((f_ent->flags & _FP_ENTRY_PRIMARY) && 
   8465          (f_ent->flags & _FP_ENTRY_STAT_IN_SECONDARY_SLICE))) {
   8466         idx = 0;
   8467         mode = 0;
   8468     } else {
   8469         /* Get statistics entity description structure. */
   8470         BCM_IF_ERROR_RETURN(_bcm_field_stat_get(unit, f_ent->statistic.sid, &f_st));
   8471         idx = f_st->hw_index;
   8472         mode = f_st->hw_mode;
   8473         /* Adjust counter hw mode for COUNTER_MODE_YES_NO/NO_YES */
   8474         if (f_ent->statistic.flags & _FP_ENTRY_STAT_USE_ODD) {
   8475             mode++;
   8476         }
   8477     }
   8478 
   8479 #if defined(BCM_FIREBOLT2_SUPPORT)
   8480     if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) {
   8481         PolicySet(unit, mem, buf, PID_INCR_COUNTERf, (mode) ? 1 : 0);
   8482         PolicySet(unit, mem, buf, PID_COUNTER_INDEXf, idx);
   8483     } else 
   8484 #endif /* BCM_FIREBOLT2_SUPPORT */
   8485     { 
   8486         PolicySet(unit, mem, buf, COUNTER_INDEXf, idx);
   8487         PolicySet(unit, mem, buf, COUNTER_MODEf, mode);
   8488     }
   8489     return (BCM_E_NONE);
   8490 }
   8491 
   8492 /*
   8493  * Function:
   8494  *     _field_fb_tcam_policy_reinstall
   8495  *
   8496  * Purpose:
   8497  *     Write entry into the chip's memory. 
   8498  *
   8499  * Parameters:
   8500  *     unit     -   BCM Unit
   8501  *     f_ent    -   Physical entry structure to be installed 
   8502  *     tcam_idx - location in TCAM
   8503  *
   8504  * Returns:
   8505  *     BCM_E_XXX        On TCAM read/write errors
   8506  *     BCM_E_NONE
   8507  *
   8508  * Note:
   8509  *     Unit lock should be held by calling function.
   8510  */
   8511 STATIC int
   8512 _field_fb_tcam_policy_reinstall(int unit, _field_entry_t *f_ent, int tcam_idx)
   8513 {
   8514     uint32  e[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to fill Policy & TCAM entry.*/
   8515     soc_mem_t        tcam_mem;          /* tcAM memory id.                    */
   8516     soc_mem_t        policy_mem;        /* Policy table memory id .           */
   8517     _field_action_t  *fa;               /* Actions iterator.                  */
   8518 
   8519 
   8520     /* Input parameters check. */
   8521     if (NULL == f_ent) {
   8522         return (BCM_E_PARAM);
   8523     }
   8524 
   8525     if (NULL == f_ent->fs) {
   8526         return (BCM_E_PARAM);
   8527     }
   8528 
   8529     BCM_IF_ERROR_RETURN
   8530         (_field_fb_tcam_policy_mem_get(unit, f_ent->fs->stage_id, 
   8531                                        &tcam_mem, &policy_mem));
   8532 
   8533     if ((tcam_idx < soc_mem_index_min(unit, tcam_mem)) ||
   8534         (tcam_idx > soc_mem_index_max(unit, tcam_mem))) {
   8535         return (BCM_E_PARAM);
   8536     }
   8537 
   8538     /* Reset buffer. */
   8539     sal_memset(e, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   8540 
   8541     /* Extract the policy info from the entry structure. */
   8542     for (fa = f_ent->actions;
   8543             ((fa != NULL) && (_FP_ACTION_VALID & fa->flags)); fa = fa->next) {
   8544         BCM_IF_ERROR_RETURN(
   8545             _field_fb_action_get(unit, policy_mem, f_ent, tcam_idx, fa, e));
   8546     }
   8547 
   8548     /* Handle color dependence/independence */
   8549     if (soc_mem_field_valid(unit, policy_mem, GREEN_TO_PIDf)) {
   8550         soc_mem_field32_set(unit, policy_mem, e, GREEN_TO_PIDf, 
   8551                         (f_ent->flags & _FP_ENTRY_COLOR_INDEPENDENT) ? 1 : 0);
   8552     }
   8553 
   8554     /* Install meter */
   8555     BCM_IF_ERROR_RETURN(_bcm_field_fb_meter_action_set(unit, f_ent, 
   8556                                                        policy_mem, e));
   8557 
   8558     /* Install counter */
   8559     BCM_IF_ERROR_RETURN(_field_fb_stat_action_set(unit, f_ent, policy_mem, e));
   8560 
   8561     /* Write policy entry. */
   8562     SOC_IF_ERROR_RETURN
   8563         (soc_mem_write(unit, policy_mem, MEM_BLOCK_ALL, tcam_idx, e));
   8564  
   8565     return BCM_E_NONE;
   8566 }
   8567 
   8568 /*
   8569  * Function:
   8570  *     _field_fb_tcam_policy_install
   8571  *
   8572  * Purpose:
   8573  *     Write entry into the chip's memory. 
   8574  *
   8575  * Parameters:
   8576  *     unit     -   BCM Unit
   8577  *     f_ent    -   Physical entry structure to be installed 
   8578  *     tcam_idx - location in TCAM
   8579  *
   8580  * Returns:
   8581  *     BCM_E_XXX        On TCAM read/write errors
   8582  *     BCM_E_NONE
   8583  *
   8584  * Note:
   8585  *     Unit lock should be held by calling function.
   8586  */
   8587 STATIC int
   8588 _field_fb_tcam_policy_install(int unit, _field_entry_t *f_ent, int tcam_idx)
   8589 {
   8590     uint32  e[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to fill Policy & TCAM entry.*/
   8591     soc_mem_t        tcam_mem;          /* tcAM memory id.                    */
   8592     soc_mem_t        policy_mem;        /* Policy table memory id .           */
   8593     _field_action_t  *fa;               /* Actions iterator.                  */
   8594 
   8595 
   8596     /* Input parameters check. */
   8597     if (NULL == f_ent) {
   8598         return (BCM_E_PARAM);
   8599     }
   8600 
   8601     if (NULL == f_ent->fs) {
   8602         return (BCM_E_PARAM);
   8603     }
   8604 
   8605     BCM_IF_ERROR_RETURN
   8606         (_field_fb_tcam_policy_mem_get(unit, f_ent->fs->stage_id, 
   8607                                        &tcam_mem, &policy_mem));
   8608 
   8609     if ((tcam_idx < soc_mem_index_min(unit, tcam_mem)) ||
   8610         (tcam_idx > soc_mem_index_max(unit, tcam_mem))) {
   8611         return (BCM_E_PARAM);
   8612     }
   8613 
   8614     /* Reset buffer. */
   8615     sal_memset(e, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   8616 
   8617     /* Extract the policy info from the entry structure. */
   8618     for (fa = f_ent->actions;
   8619         ((fa != NULL) && (_FP_ACTION_VALID & fa->flags)); fa = fa->next) {
   8620         BCM_IF_ERROR_RETURN(
   8621             _field_fb_action_get(unit, policy_mem, f_ent, tcam_idx, fa, e));
   8622     }
   8623 
   8624     /* Handle color dependence/independence */
   8625     if (soc_mem_field_valid(unit, policy_mem, GREEN_TO_PIDf)) {
   8626         soc_mem_field32_set(unit, policy_mem, e, GREEN_TO_PIDf, 
   8627                         (f_ent->flags & _FP_ENTRY_COLOR_INDEPENDENT) ? 1 : 0);
   8628     }
   8629 
   8630     /* Install meter */
   8631     BCM_IF_ERROR_RETURN(_bcm_field_fb_meter_action_set(unit, f_ent, 
   8632                                                        policy_mem, e));
   8633 
   8634     /* Install counter */
   8635     BCM_IF_ERROR_RETURN(_field_fb_stat_action_set(unit, f_ent, policy_mem, e));
   8636 
   8637     /* Write policy entry. */
   8638     SOC_IF_ERROR_RETURN
   8639         (soc_mem_write(unit, policy_mem, MEM_BLOCK_ALL, tcam_idx, e));
   8640  
   8641     /* Reset buffer. */
   8642     sal_memset(e, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   8643 
   8644     /* Extract the qualifier info from the entry structure. */
   8645     BCM_IF_ERROR_RETURN(
   8646         _field_fb_tcam_get(unit, f_ent, tcam_mem, e));
   8647 
   8648     /* Write tcam entry. */
   8649     SOC_IF_ERROR_RETURN
   8650         (soc_mem_write(unit, tcam_mem, MEM_BLOCK_ALL, tcam_idx, e));
   8651  
   8652     return BCM_E_NONE;
   8653 }
   8654 
   8655 /*
   8656  * Function:
   8657  *     _field_fb_tcam_get
   8658  *
   8659  * Purpose:
   8660  *     Write entry into the chip's memory.
   8661  *
   8662  * Parameters:
   8663  *     unit      -  (IN)BCM device number.  
   8664  *     f_ent     -  (IN)Entry structure to get tcam info from.
   8665  *     mem       -  (IN)Tcam memory.  
   8666  *     buf       - (OUT) TCAM hardware entry
   8667  *
   8668  * Returns:
   8669  *     BCM_E_NONE  - Success
   8670  *
   8671  * Note:
   8672  *     Unit lock should be held by calling function.
   8673  */
   8674 STATIC int
   8675 _field_fb_tcam_get(int unit, _field_entry_t *f_ent,
   8676                    soc_mem_t mem, uint32 *buf)
   8677 {
   8678     _field_tcam_t       *tcam; 
   8679     _field_group_t      *fg;
   8680     uint8               ent_part;
   8681     int                 test_var;
   8682 
   8683     if ((NULL == f_ent) || (NULL == buf)) {
   8684         return (BCM_E_PARAM);
   8685     }
   8686 
   8687     tcam = &f_ent->tcam;
   8688     fg = f_ent->group;
   8689 
   8690     if (_BCM_FIELD_STAGE_INGRESS == fg->stage_id) {
   8691         soc_mem_field32_set(unit, mem, buf, VALIDf, 
   8692                             (fg->flags & _FP_GROUP_LOOKUP_ENABLED) ? 3 : 2);
   8693         if (f_ent->flags & _FP_ENTRY_SECOND_HALF) {
   8694             /* Intra-slice double wide key */
   8695 #ifdef BCM_FIREBOLT2_SUPPORT
   8696             if (SOC_IS_FIREBOLT2(unit)) {
   8697                 soc_mem_field_set(unit, mem, buf, DATAf, tcam->key);
   8698                 soc_mem_field_set(unit, mem, buf, DATA_MASKf, tcam->mask);
   8699             }
   8700 #endif /* BCM_FIREBOLT2_SUPPORT */
   8701         } else {
   8702             /* Single wide key */
   8703             soc_mem_field_set(unit, mem, buf, KEYf, tcam->key);
   8704             soc_mem_field_set(unit, mem, buf, MASKf, tcam->mask);
   8705 
   8706             /* 
   8707              * Notes:
   8708              *     1. SOURCE_PORT_NUMBER is same as F4.0
   8709              *     2. DROP is part of F4.1
   8710              *     3. PORT_FIELD_SEL_INDEX is same as F4.2 (not implemented
   8711              *                                                  2006.01.18)
   8712              */
   8713             if ((BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInPort)) &&
   8714                 (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_PORT_NUMBERf))) {
   8715                 soc_mem_field32_set(unit, mem, buf, SOURCE_PORT_NUMBERf, 
   8716                                     tcam->f4);
   8717                 soc_mem_field32_set(unit, mem, buf, SOURCE_PORT_NUMBER_MASKf, 
   8718                                     tcam->f4_mask);
   8719             } else if (SOC_MEM_FIELD_VALID(unit, mem, F4f)) {
   8720                 soc_mem_field32_set(unit, mem, buf, F4f, tcam->f4);
   8721                 soc_mem_field32_set(unit, mem, buf, F4_MASKf, tcam->f4_mask);
   8722             }
   8723 
   8724             /* 
   8725              * Check if IPBM_SEL needs to be set
   8726              *     Will be set if fpf1.0 is selected
   8727              * First find out the part of the group, entry resides in
   8728              *     Then check the corresponding sel_codes
   8729              */ 
   8730             BCM_IF_ERROR_RETURN
   8731                 (_bcm_field_entry_flags_to_tcam_part (unit, f_ent->flags,
   8732                                                       fg,
   8733                                                       &ent_part));
   8734             test_var = (fg->sel_codes[ent_part].fpf1 == 0) ? 1 : 0;
   8735 
   8736             soc_mem_field32_set(unit, mem, buf, IPBM_SELf, test_var);
   8737             soc_mem_field32_set(unit, mem, buf, IPBM_SEL_MASKf, test_var);
   8738 
   8739             /*
   8740              * Qualify on HiGig packets.
   8741              */
   8742             test_var =  
   8743                 (BCM_FIELD_QSET_TEST(fg->qset,
   8744                                      bcmFieldQualifyHiGig) && tcam->higig) ? 1 : 0; 
   8745             soc_mem_field32_set(unit, mem, buf, PKT_TYPEf, test_var);
   8746 
   8747             test_var =  
   8748                 (BCM_FIELD_QSET_TEST(fg->qset,
   8749                                      bcmFieldQualifyHiGig) && tcam->higig_mask) ? 1 : 0;
   8750             soc_mem_field32_set(unit, mem, buf, PKT_TYPE_MASKf, test_var);
   8751 #ifdef BCM_FIREBOLT2_SUPPORT 
   8752             /*
   8753              * Qualify on Drop.
   8754              */
   8755             if (SOC_IS_FIREBOLT2(unit)) {
   8756                 test_var =  
   8757                     (BCM_FIELD_QSET_TEST(fg->qset,
   8758                                          bcmFieldQualifyDrop) && tcam->drop) ? 1 : 0; 
   8759 
   8760                 soc_mem_field32_set(unit, mem, buf, DROPf, test_var);
   8761 
   8762                 test_var =  
   8763                     (BCM_FIELD_QSET_TEST(fg->qset,
   8764                                          bcmFieldQualifyDrop) && tcam->drop_mask) ? 1 : 0;
   8765                 soc_mem_field32_set(unit, mem, buf, DROP_MASKf, test_var);
   8766             }
   8767 #endif
   8768         }
   8769 #ifdef BCM_FIREBOLT2_SUPPORT
   8770     } else if (soc_feature(unit, soc_feature_field_multi_stage)) {
   8771         soc_field_t mask_field;
   8772         if (_BCM_FIELD_STAGE_LOOKUP == fg->stage_id) {
   8773             mask_field = MASKf;
   8774         } else if (_BCM_FIELD_STAGE_EGRESS == fg->stage_id){
   8775             mask_field = KEY_MASKf;
   8776         } else {
   8777             return (BCM_E_PARAM);
   8778         }
   8779         soc_mem_field_set(unit, mem, buf, KEYf, tcam->key);
   8780         soc_mem_field_set(unit, mem, buf, mask_field, tcam->mask);
   8781         soc_mem_field32_set(unit, mem, buf, VALIDf, 
   8782                             (fg->flags & _FP_GROUP_LOOKUP_ENABLED) ? 3 : 2);
   8783 #endif
   8784     } else {
   8785         return (BCM_E_INTERNAL);
   8786     }
   8787 
   8788     return (BCM_E_NONE);
   8789 }
   8790 
   8791 /*
   8792  * Function:
   8793  *     _bcm_field_fb_meter_action_set
   8794  *
   8795  * Purpose:
   8796  *     Get metering portion of Policy Table.
   8797  *
   8798  * Parameters:
   8799  *     unit      - (IN)BCM device number. 
   8800  *     f_ent     - (IN)Software entry structure to get tcam info from.
   8801  *     mem       - (IN)Policy table memory. 
   8802  *     buf       - (IN/OUT)Hardware policy entry
   8803  *
   8804  * Returns:
   8805  *     BCM_E_NONE  - Success
   8806  *
   8807  * Note:
   8808  *     Unit lock should be held by calling function.
   8809  */
   8810 int
   8811 _bcm_field_fb_meter_action_set(int unit, _field_entry_t *f_ent,
   8812                                soc_mem_t mem, uint32 *buf)
   8813 {
   8814     _field_policer_t *f_pl;             /* Field policer descriptor. */  
   8815     uint32           meter_pair_mode;   /* Meter usage.              */ 
   8816 
   8817     /* Input parameter check. */
   8818     if ((NULL == f_ent) || (NULL == buf))  {
   8819         return (BCM_E_PARAM);
   8820     }
   8821     if (NULL == f_ent->group) {
   8822         return (BCM_E_PARAM);
   8823     }
   8824 
   8825 #if defined(BCM_FIREBOLT2_SUPPORT) 
   8826     /* VFP doesn't have meters. */
   8827     if ((_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id)) {
   8828         return (BCM_E_NONE);
   8829     }
   8830 #endif /* BCM_FIREBOLT2_SUPPORT */
   8831     
   8832 
   8833     if ((0 == (f_ent->policer[0].flags & _FP_POLICER_INSTALLED)) ||
   8834         ((f_ent->flags & _FP_ENTRY_PRIMARY) && 
   8835          (f_ent->flags & _FP_ENTRY_POLICER_IN_SECONDARY_SLICE))) {
   8836         /* If no meter, install default meter pair mode.
   8837          * Default meter pair mode doesn't need to burn a real meter.
   8838          */
   8839         soc_mem_field32_set(unit, mem, buf, METER_PAIR_MODEf, 0);
   8840         soc_mem_field32_set(unit, mem, buf, METER_TEST_EVENf, 1);
   8841 
   8842 #if defined(BCM_FIREBOLT2_SUPPORT)
   8843         if ((SOC_IS_FIREBOLT2(unit) && 
   8844              _BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id)) {
   8845             soc_mem_field32_set(unit, mem, buf, METER_PAIR_MODEf, 4);
   8846         }
   8847 #endif /* BCM_FIREBOLT2_SUPPORT */
   8848         return (BCM_E_NONE);
   8849     }
   8850 
   8851     /* Get policer description structure. */
   8852     BCM_IF_ERROR_RETURN(_bcm_field_policer_get(unit, f_ent->policer[0].pid, 
   8853                                                &f_pl));
   8854     /* Get the even and odd indexes from the entry. The even and odd
   8855      * meter indices are the same.
   8856      */
   8857     soc_mem_field32_set(unit, mem, buf, METER_INDEX_EVENf, 
   8858                         f_pl->hw_index);
   8859     soc_mem_field32_set(unit, mem, buf, METER_INDEX_ODDf, 
   8860                         f_pl->hw_index);
   8861 
   8862 
   8863     /* Get hw encoding for meter mode. */
   8864     BCM_IF_ERROR_RETURN
   8865         (_bcm_field_meter_pair_mode_get(unit, f_pl, &meter_pair_mode));
   8866 
   8867     /* 
   8868      * Flow mode is the only one that cares about the test and update bits.
   8869      * Even = BCM_FIELD_METER_PEAK
   8870      * Odd = BCM_FIELD_METER_COMMITTED
   8871      */
   8872     if (_FP_POLICER_EXCESS_HW_METER(f_pl)) {
   8873         soc_mem_field32_set(unit, mem, buf, METER_TEST_ODDf, 0);
   8874         soc_mem_field32_set(unit, mem, buf, METER_TEST_EVENf, 1);
   8875         soc_mem_field32_set(unit, mem, buf, METER_UPDATE_ODDf, 0);
   8876         soc_mem_field32_set(unit, mem, buf, METER_UPDATE_EVENf, 1);
   8877     } else if (_FP_POLICER_COMMITTED_HW_METER(f_pl)) {
   8878         soc_mem_field32_set(unit, mem, buf, METER_TEST_ODDf, 1);
   8879         soc_mem_field32_set(unit, mem, buf, METER_TEST_EVENf, 0);
   8880         soc_mem_field32_set(unit, mem, buf, METER_UPDATE_ODDf, 1);
   8881         soc_mem_field32_set(unit, mem, buf, METER_UPDATE_EVENf, 0);
   8882     } else if (f_pl->cfg.mode == bcmPolicerModePassThrough) {
   8883         if (SOC_MEM_FIELD_VALID(unit, mem, METER_PAIR_MODE_MODIFIERf)) {
   8884             soc_mem_field32_set(unit, mem, buf, METER_PAIR_MODE_MODIFIERf, 1);
   8885         } 
   8886         soc_mem_field32_set(unit, mem, buf, METER_TEST_EVENf, 1);
   8887     }
   8888 
   8889     soc_mem_field32_set(unit, mem, buf, METER_PAIR_MODEf, meter_pair_mode);
   8890     return (BCM_E_NONE);
   8891 }
   8892 
   8893 /*
   8894  * Function:
   8895  *     _field_fb_ingress_selcodes_install
   8896  *
   8897  * Purpose:
   8898  *     Writes the field select codes (ie. FPFx).
   8899  *
   8900  * Parameters:
   8901  *     unit          - (IN) BCM device number.
   8902  *     fg            - (IN) Field group.
   8903  *     slice_numb    - (IN) Slice number group installed in. 
   8904  *     pbmp          - (IN) Group  active port bit map.
   8905  *     selcode_index - (IN) Index into select codes array.
   8906  *     fs    - slice that needs its select codes written
   8907  *
   8908  * Returns:
   8909  *     BCM_E_XXX
   8910  */
   8911 STATIC int
   8912 _field_fb_ingress_selcodes_install(int unit, _field_group_t *fg, 
   8913                                   uint8 slice_numb, bcm_pbmp_t pbmp, 
   8914                                   int selcode_index)
   8915 {
   8916     bcm_port_t                  port;
   8917     fp_port_field_sel_entry_t   pfs_entry;
   8918     ifp_port_field_sel_entry_t  ipfs_entry;
   8919     soc_field_t                 f1_field, f2_field, f3_field;
   8920     uint32                      fpf4;
   8921     int                         i_write_flag;
   8922     _field_sel_t                *sel = NULL;
   8923     int                         rv;
   8924 #if defined(BCM_FIREBOLT2_SUPPORT) 
   8925     soc_field_t  dw_fld;
   8926     bcm_pbmp_t   all_pbmp;
   8927 #endif /* BCM_FIREBOLT2_SUPPORT */
   8928 
   8929     /* Input parameters check. */
   8930     if (NULL == fg) {
   8931         return (BCM_E_PARAM);
   8932     } 
   8933 
   8934     sel = &fg->sel_codes[selcode_index];
   8935 
   8936     if (slice_numb >= 16) {
   8937         return (BCM_E_PARAM);
   8938     }
   8939 
   8940 
   8941     if ((fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) && 
   8942         ((selcode_index == 1) || (selcode_index == 3))) {
   8943 #if defined(BCM_FIREBOLT2_SUPPORT) 
   8944         if (SOC_IS_FIREBOLT2(unit)) {
   8945 
   8946             /* Write appropriate values in FP_DOUBLE_WIDE_F4_SELECTr and */
   8947             /* FP_PORT_FIELD_SELm for an intra-slice double wide group */
   8948             /* V4 key => F4 should be FP_PORT_FIELD_SEL_INDEX: sel->fpf2 = 0 */
   8949             /* V6 key => F4 should be TCP flags: sel->fpf2 = 1*/
   8950             dw_fld = _fb_ing_f4_reg[slice_numb];
   8951             if ((sel->fpf2 != _FP_SELCODE_DONT_CARE) &&
   8952                 SOC_REG_FIELD_VALID(unit, FP_DOUBLE_WIDE_F4_SELECTr, dw_fld)) { 
   8953                 rv = soc_reg_field32_modify(unit, FP_DOUBLE_WIDE_F4_SELECTr, 
   8954                                             REG_PORT_ANY, dw_fld,  sel->fpf2);
   8955                 BCM_IF_ERROR_RETURN(rv);
   8956             }
   8957 
   8958             /* Read device port configuration. */ 
   8959             rv = _bcm_field_valid_pbmp_get(unit, &all_pbmp); 
   8960             BCM_IF_ERROR_RETURN(rv);
   8961 
   8962             dw_fld = _fb2_ifp_double_wide_key[slice_numb]; 
   8963             if ((sel->fpf2 != _FP_SELCODE_DONT_CARE) &&
   8964                 SOC_MEM_FIELD_VALID(unit, FP_PORT_FIELD_SELm, dw_fld)) {
   8965                 /* Do the same thing for each entry in FP_PORT_FIELD_SEL table */
   8966                 BCM_PBMP_ITER(all_pbmp, port) {
   8967                     rv = READ_FP_PORT_FIELD_SELm(unit, MEM_BLOCK_ANY, port, &pfs_entry); 
   8968                     BCM_IF_ERROR_RETURN(rv);
   8969 
   8970                     soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, 
   8971                                                        dw_fld, sel->fpf2);
   8972                     rv = WRITE_FP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL, port, &pfs_entry);
   8973                     BCM_IF_ERROR_RETURN(rv);
   8974 
   8975                     if (_FIELD_NEED_I_WRITE(unit, port, IFP_PORT_FIELD_SELm)) {
   8976                         rv = READ_IFP_PORT_FIELD_SELm(unit, MEM_BLOCK_ANY, 
   8977                                                       port, &pfs_entry);
   8978                         BCM_IF_ERROR_RETURN(rv);
   8979 
   8980                         soc_IFP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, 
   8981                                                             dw_fld, sel->fpf2);
   8982 
   8983                         rv = WRITE_IFP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL, 
   8984                                                        port, &pfs_entry);
   8985                         BCM_IF_ERROR_RETURN(rv);
   8986                     }
   8987                 }
   8988             }
   8989         }
   8990 #endif /* BCM_FIREBOLT2_SUPPORT */
   8991     } else {
   8992 
   8993         /* Determine which 3 fields will be modified */
   8994         f1_field = _fb_field_tbl[slice_numb][0];
   8995         f2_field = _fb_field_tbl[slice_numb][1];
   8996         f3_field = _fb_field_tbl[slice_numb][2];
   8997 
   8998         /* Iterate over all ports */
   8999         PBMP_ITER(pbmp, port) {
   9000             i_write_flag = _FIELD_NEED_I_WRITE(unit, port,
   9001                                                IFP_PORT_FIELD_SELm);
   9002             /* Read Port's current entry in FP_PORT_FIELD_SEL table */
   9003             rv = READ_FP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL,
   9004                                          port, &pfs_entry);
   9005             BCM_IF_ERROR_RETURN(rv);
   9006             if (i_write_flag) {
   9007                 rv = READ_IFP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL,
   9008                                               port, &ipfs_entry);
   9009                 BCM_IF_ERROR_RETURN(rv);
   9010             }
   9011 
   9012             /* modify 0-3 fields depending on state of SELCODE_INVALID */
   9013             if (sel->fpf1 != _FP_SELCODE_DONT_CARE) {
   9014                 soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry,
   9015                                                    f1_field, sel->fpf1);
   9016                 if (i_write_flag) {
   9017                     soc_IFP_PORT_FIELD_SELm_field32_set(unit, &ipfs_entry, 
   9018                                                         f1_field, sel->fpf1);
   9019                 }
   9020             }
   9021 
   9022             if (sel->fpf2 != _FP_SELCODE_DONT_CARE) {
   9023                 soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry,
   9024                                                    f2_field,
   9025                                                    sel->fpf2);
   9026                 if (i_write_flag) {
   9027                     soc_IFP_PORT_FIELD_SELm_field32_set(unit, &ipfs_entry,
   9028                                                         f2_field,
   9029                                                         sel->fpf2);
   9030                 }
   9031             }
   9032 
   9033             if (sel->fpf3 != _FP_SELCODE_DONT_CARE) {
   9034                 soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry,
   9035                                                    f3_field,
   9036                                                    sel->fpf3);
   9037                 if (i_write_flag) {
   9038                     soc_IFP_PORT_FIELD_SELm_field32_set(unit, &ipfs_entry, 
   9039                                                         f3_field,
   9040                                                         sel->fpf3);
   9041                 }
   9042             }
   9043 
   9044             /* Write each port's new entry */
   9045             rv = WRITE_FP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL,
   9046                                           port, &pfs_entry);
   9047             BCM_IF_ERROR_RETURN(rv);
   9048             if (i_write_flag) {
   9049                 rv = WRITE_IFP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL,
   9050                                                port, &ipfs_entry);
   9051                 BCM_IF_ERROR_RETURN(rv);
   9052             }
   9053         }
   9054 
   9055         /* If the device supports it, write the F4 select code. */
   9056         if (soc_feature(unit, soc_feature_field_qual_drop)) {
   9057             fpf4 = (sel->fpf4 == _FP_SELCODE_DONT_CARE) ? 0 : sel->fpf4;
   9058             rv = soc_reg_field32_modify(unit, FP_F4_SELECTr, REG_PORT_ANY, 
   9059                                         _fb_ing_f4_reg[slice_numb], fpf4);
   9060             BCM_IF_ERROR_RETURN(rv);
   9061         }
   9062 
   9063         /* Set inner vlan overlay config. */
   9064         if (_FP_SELCODE_DONT_CARE != fg->sel_codes[0].inner_vlan_overlay) {
   9065 #if defined(BCM_FIREBOLT2_SUPPORT)  || defined(BCM_RAVEN_SUPPORT)
   9066             if (SOC_REG_FIELD_VALID(unit, ING_MISC_CONFIG2r, 
   9067                                     FP_INNER_VLAN_OVERLAY_ENABLEf)) {
   9068                 rv = soc_reg_field32_modify(unit, ING_MISC_CONFIG2r, REG_PORT_ANY,
   9069                                             FP_INNER_VLAN_OVERLAY_ENABLEf,
   9070                                             fg->sel_codes[0].inner_vlan_overlay);
   9071                 BCM_IF_ERROR_RETURN(rv);
   9072             } else 
   9073 #endif  /* BCM_FIREBOLT2_SUPPORT  || BCM_RAVEN_SUPPORT */
   9074                 if (SOC_REG_FIELD_VALID(unit, ING_CONFIGr, MAC_BLOCK_INDEX_OVERLAYf)) {
   9075                     rv = soc_reg_field32_modify(unit, ING_CONFIGr, REG_PORT_ANY,
   9076                                                 MAC_BLOCK_INDEX_OVERLAYf,
   9077                                                 fg->sel_codes[0].inner_vlan_overlay);
   9078                     BCM_IF_ERROR_RETURN(rv);
   9079                 }
   9080         }
   9081     }
   9082     return (BCM_E_NONE);
   9083 }
   9084 
   9085 /*
   9086  * Function:
   9087  *     _field_fb_ingress_slice_clear
   9088  *
   9089  * Purpose:
   9090  *     Resets the IFP field slice configuration.
   9091  *
   9092  * Parameters:
   9093  *     unit       - (IN) BCM device number.
   9094  *     slice_numb - (IN) Field slice number.
   9095  *
   9096  * Returns:
   9097  *     BCM_E_XXX
   9098  */
   9099 STATIC int
   9100 _field_fb_ingress_slice_clear(int unit, uint8 slice_numb)
   9101 {
   9102     bcm_port_t                  port;
   9103     fp_port_field_sel_entry_t   pfs_entry;
   9104     ifp_port_field_sel_entry_t  ipfs_entry;
   9105     bcm_pbmp_t                  all_pbmp;
   9106     soc_field_t                 f1_field, f2_field, f3_field;
   9107     int                         i_write_flag;
   9108     int                         rv;
   9109 #if defined (BCM_FIREBOLT2_SUPPORT)
   9110     soc_field_t                 dw_fld;
   9111 #endif /* BCM_FIREBOLT2_SUPPORT */
   9112 
   9113     f1_field = _fb_field_tbl[slice_numb][0];
   9114     f2_field = _fb_field_tbl[slice_numb][1];
   9115     f3_field = _fb_field_tbl[slice_numb][2];
   9116 
   9117     /* Read device port configuration. */ 
   9118     BCM_PBMP_CLEAR(all_pbmp);
   9119     BCM_IF_ERROR_RETURN(_bcm_field_valid_pbmp_get(unit, &all_pbmp));
   9120 
   9121     /* Iterate over all ports */
   9122     BCM_PBMP_ITER(all_pbmp, port) {
   9123         i_write_flag = _FIELD_NEED_I_WRITE(unit, port, IFP_PORT_FIELD_SELm);
   9124 #if defined (BCM_RAVEN_SUPPORT)
   9125         /* IFP_PORT_FIELD_SEL table will be automatically updated by the 
   9126            hardware when FP_FIELD_PORT_SEL table is configured for hg ports.
   9127            So configuring IFP_PORT_FIELD_SEL table again from software is  
   9128            not required. However, when cpu port is configured in higig mode 
   9129            (PORT_TAB.HIGIG_PACKET) software has to update this table */
   9130         if (SOC_IS_RAVEN(unit) && !IS_CPU_PORT(unit, port)) {
   9131            i_write_flag = 0;
   9132         }
   9133 #endif
   9134         /* Read Port's current entry in FP_PORT_FIELD_SEL table */
   9135         rv = READ_FP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL, 
   9136                                      port, &pfs_entry);
   9137         BCM_IF_ERROR_RETURN(rv);
   9138 
   9139         if (i_write_flag) {
   9140             rv = READ_IFP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL,
   9141                                           port, &ipfs_entry);
   9142             BCM_IF_ERROR_RETURN(rv);
   9143         }
   9144 
   9145         soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry,
   9146                                            f1_field, 0);
   9147         if (i_write_flag) {
   9148             soc_IFP_PORT_FIELD_SELm_field32_set(unit, &ipfs_entry, 
   9149                                                 f1_field, 0);
   9150         }
   9151 
   9152         soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry,
   9153                                            f2_field, 0);
   9154         if (i_write_flag) {
   9155             soc_IFP_PORT_FIELD_SELm_field32_set(unit, &ipfs_entry,
   9156                                                 f2_field, 0);
   9157         }
   9158 
   9159         soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry,
   9160                                            f3_field, 0);
   9161         if (i_write_flag) {
   9162             soc_IFP_PORT_FIELD_SELm_field32_set(unit, &ipfs_entry, 
   9163                                                 f3_field, 0);
   9164         }
   9165 
   9166 #if defined (BCM_FIREBOLT2_SUPPORT)
   9167         dw_fld = _fb2_ifp_double_wide_key[slice_numb]; 
   9168         if (SOC_MEM_FIELD_VALID(unit, FP_PORT_FIELD_SELm, dw_fld)) {
   9169             soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, 
   9170                                                dw_fld, 0);
   9171             if (i_write_flag) {
   9172                 soc_IFP_PORT_FIELD_SELm_field32_set(unit, &ipfs_entry, 
   9173                                                     dw_fld, 0);
   9174             }
   9175         }
   9176 
   9177         dw_fld = _fb2_slice_wide_mode_field[slice_numb];
   9178         if (SOC_MEM_FIELD_VALID(unit, FP_PORT_FIELD_SELm, dw_fld)) {
   9179             soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, dw_fld, 0);
   9180             if (i_write_flag) {
   9181                 soc_IFP_PORT_FIELD_SELm_field32_set(unit, &ipfs_entry,
   9182                                                     dw_fld, 0);
   9183             }
   9184         }
   9185 
   9186         dw_fld = _fb2_slice_pairing_field[slice_numb / 2];
   9187         if (SOC_MEM_FIELD_VALID(unit, FP_PORT_FIELD_SELm, dw_fld)) {
   9188             soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, dw_fld, 0);
   9189             if (i_write_flag) {
   9190                 soc_IFP_PORT_FIELD_SELm_field32_set(unit, &ipfs_entry,
   9191                                                     dw_fld, 0);
   9192             }
   9193         }
   9194 #endif /* BCM_FIREBOLT2_SUPPORT */
   9195 
   9196         rv = WRITE_FP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL, port,
   9197                                       &pfs_entry);
   9198         BCM_IF_ERROR_RETURN(rv);
   9199 
   9200         if (i_write_flag) {
   9201             rv = WRITE_IFP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL, port,
   9202                                           &ipfs_entry);
   9203             BCM_IF_ERROR_RETURN(rv);
   9204         }
   9205     }
   9206 
   9207     if (SOC_REG_FIELD_VALID(unit, FP_SLICE_CONFIGr, 
   9208                             _fb_ing_slice_mode_field[slice_numb])) {
   9209         rv = soc_reg_field32_modify(unit, FP_SLICE_CONFIGr, REG_PORT_ANY,
   9210                                     _fb_ing_slice_mode_field[slice_numb], 0);
   9211         BCM_IF_ERROR_RETURN(rv);
   9212     }
   9213 
   9214     /* If the device supports it, write the F4 select code. */
   9215     if (SOC_REG_FIELD_VALID(unit, FP_F4_SELECTr, _fb_ing_f4_reg[slice_numb])) {
   9216         rv = soc_reg_field32_modify(unit, FP_F4_SELECTr, REG_PORT_ANY,
   9217                                     _fb_ing_f4_reg[slice_numb],0);
   9218         BCM_IF_ERROR_RETURN(rv);
   9219     }
   9220 #if defined (BCM_FIREBOLT2_SUPPORT)
   9221     dw_fld = _fb_ing_f4_reg[slice_numb];
   9222     if (SOC_REG_FIELD_VALID(unit, FP_DOUBLE_WIDE_F4_SELECTr, dw_fld)) {
   9223         rv = soc_reg_field32_modify(unit, FP_DOUBLE_WIDE_F4_SELECTr,
   9224                                     REG_PORT_ANY, dw_fld,  0);
   9225         BCM_IF_ERROR_RETURN(rv);
   9226     }
   9227 #endif /* BCM_FIREBOLT2_SUPPORT */
   9228     return (BCM_E_NONE);
   9229 }
   9230 
   9231 #if defined(BCM_FIREBOLT2_SUPPORT) 
   9232 
   9233 /*
   9234  * Function:
   9235  *     _field_fb_lookup_selcodes_install
   9236  *
   9237  * Purpose:
   9238  *     Writes the field select codes (ie. FPFx).
   9239  *     for VFP (_BCM_FIELD_STAGE_LOOKUP) lookup stage.
   9240  *
   9241  * Parameters:
   9242  *     unit  - BCM device number
   9243  *     fs    - slice that needs its select codes written
   9244  *
   9245  * Returns:
   9246  *     BCM_E_INTERNAL - On read/write errors
   9247  *     BCM_E_NONE     - Success
   9248  *
   9249  * Note:
   9250  *     Unit lock should be held by calling function.
   9251  */
   9252 STATIC int
   9253 _field_fb_lookup_selcodes_install(int unit, _field_group_t *fg, 
   9254                                   uint8 slice_numb, int selcode_index)
   9255 {
   9256     uint32        reg_val;
   9257     _field_sel_t  *sel;
   9258 
   9259     sel = &fg->sel_codes[selcode_index];
   9260 
   9261 
   9262     SOC_IF_ERROR_RETURN(READ_VFP_KEY_CONTROLr(unit, &reg_val)); 
   9263     if ((fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) && 
   9264         (selcode_index % 2)) {
   9265         if (sel->fpf2 != _FP_SELCODE_DONT_CARE) {
   9266             soc_reg_field_set(unit, VFP_KEY_CONTROLr, &reg_val,
   9267                               DOUBLE_WIDE_KEY_SELECTf, sel->fpf2);
   9268         }
   9269     } else {
   9270         /* FPF1 is fixed in Firebolt2 VFP */
   9271         if (sel->fpf2 != _FP_SELCODE_DONT_CARE) {
   9272             soc_reg_field_set(unit, VFP_KEY_CONTROLr, &reg_val,
   9273                               _vfp_field_tbl[slice_numb][0], sel->fpf2);
   9274         }
   9275         if (sel->fpf3 != _FP_SELCODE_DONT_CARE) {
   9276             soc_reg_field_set(unit, VFP_KEY_CONTROLr, &reg_val,
   9277                               _vfp_field_tbl[slice_numb][1], sel->fpf3); 
   9278         }
   9279     }
   9280     SOC_IF_ERROR_RETURN(WRITE_VFP_KEY_CONTROLr(unit, reg_val));
   9281     return (BCM_E_NONE);
   9282 }
   9283 
   9284 /*
   9285  * Function:
   9286  *     _field_fb_lookup_slice_clear
   9287  *
   9288  * Purpose:
   9289  *     Reset slice configuraton on group deletion event. 
   9290  *
   9291  * Parameters:
   9292  *     unit  - BCM device number
   9293  *     fs    - slice that needs its select codes written
   9294  *
   9295  * Returns:
   9296  *     BCM_E_NONE     - Success
   9297  *
   9298  * Note:
   9299  *     Unit lock should be held by calling function.
   9300  */
   9301 STATIC int
   9302 _field_fb_lookup_slice_clear(int unit, uint8 slice_numb)
   9303 {
   9304     uint32        reg_val;
   9305 
   9306     SOC_IF_ERROR_RETURN(READ_VFP_KEY_CONTROLr(unit, &reg_val)); 
   9307     soc_reg_field_set(unit, VFP_KEY_CONTROLr, &reg_val,
   9308                       DOUBLE_WIDE_KEY_SELECTf, 0);
   9309     soc_reg_field_set(unit, VFP_KEY_CONTROLr, &reg_val,
   9310                       _vfp_field_tbl[slice_numb][0], 0);
   9311     soc_reg_field_set(unit, VFP_KEY_CONTROLr, &reg_val,
   9312                       _vfp_field_tbl[slice_numb][1], 0); 
   9313     soc_reg_field_set(unit, VFP_KEY_CONTROLr, &reg_val,
   9314                       _vfp_slice_pairing_field[slice_numb / 2], 0);
   9315     soc_reg_field_set(unit, VFP_KEY_CONTROLr, &reg_val,
   9316                       _vfp_slice_wide_mode_field[slice_numb], 0);
   9317     SOC_IF_ERROR_RETURN(WRITE_VFP_KEY_CONTROLr(unit, reg_val));
   9318     return (BCM_E_NONE);
   9319 }
   9320 #endif /* BCM_FIREBOLT2_SUPPORT */
   9321 
   9322 /*
   9323  * Function:
   9324  *     _field_fb_ingress_mode_set
   9325  *
   9326  * Purpose:
   9327  *     Helper function to _bcm_field_fb_mode_install that sets the mode of a
   9328  *     slice in a register value that is to be used for FP_SLICE_CONFIGr.
   9329  *
   9330  * Parameters:
   9331  *     unit       - (IN) BCM device number. 
   9332  *     slice_numb - (IN) Slice number to set mode for.
   9333  *     fg         - (IN) Installed group structure. 
   9334  *     flags      - (IN) New group/slice mode.
   9335  *
   9336  * Returns:
   9337  *     BCM_E_XXX
   9338  */
   9339 int 
   9340 _field_fb_ingress_mode_set(int unit, uint8 slice_numb, 
   9341                            _field_group_t *fg, uint8 flags)
   9342 {
   9343     int     mode;
   9344 #if defined(BCM_FIREBOLT2_SUPPORT)
   9345     bcm_pbmp_t  all_pbmp;
   9346     int paired, dbl_wide;
   9347     soc_field_t fld;
   9348 #endif /* BCM_FIREBOLT2_SUPPORT */
   9349 
   9350     if (slice_numb >= COUNTOF(_fb_ing_slice_mode_field)) {
   9351         return BCM_E_PARAM;
   9352     }
   9353 
   9354 
   9355 #if defined(BCM_FIREBOLT2_SUPPORT)
   9356     if (soc_feature(unit, soc_feature_field_intraslice_double_wide)) {
   9357         int port;
   9358         fp_port_field_sel_entry_t pfs_entry;
   9359 
   9360         /* Read device port configuration. */ 
   9361         BCM_PBMP_CLEAR(all_pbmp);
   9362         BCM_IF_ERROR_RETURN(_bcm_field_valid_pbmp_get(unit, &all_pbmp));
   9363 
   9364         /* Do the same thing for each port (index) in FP_PORT_FIELD_SEL table */
   9365         BCM_PBMP_ITER(all_pbmp, port) {
   9366 
   9367             BCM_IF_ERROR_RETURN
   9368                 (READ_FP_PORT_FIELD_SELm(unit, MEM_BLOCK_ANY, port, &pfs_entry));
   9369 
   9370             fld = _fb2_slice_wide_mode_field[slice_numb];
   9371             if (SOC_MEM_FIELD_VALID(unit, FP_PORT_FIELD_SELm, fld)) {
   9372                 dbl_wide = (flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) ? 1 : 0;
   9373 
   9374                 soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, fld,
   9375                                                    dbl_wide);
   9376             }
   9377 
   9378             paired = (flags & _FP_GROUP_SPAN_DOUBLE_SLICE) ? 1 : 0;
   9379             fld = _fb2_slice_pairing_field[slice_numb / 2];
   9380             soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, fld, paired);
   9381 
   9382             BCM_IF_ERROR_RETURN
   9383                 (WRITE_FP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL, port, &pfs_entry));
   9384 
   9385             if (_FIELD_NEED_I_WRITE(unit, port, IFP_PORT_FIELD_SELm)) {
   9386 
   9387                 BCM_IF_ERROR_RETURN
   9388                     (READ_IFP_PORT_FIELD_SELm(unit, MEM_BLOCK_ANY, port, &pfs_entry));
   9389 
   9390                 fld = _fb2_slice_wide_mode_field[slice_numb];
   9391                 if (SOC_MEM_FIELD_VALID(unit, IFP_PORT_FIELD_SELm, fld)) {
   9392                     dbl_wide = (flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) ? 1 : 0;
   9393                     soc_IFP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, fld,
   9394                                                         dbl_wide);
   9395                 }
   9396 
   9397                 paired = (flags & _FP_GROUP_SPAN_DOUBLE_SLICE) ? 1 : 0;
   9398                 fld = _fb2_slice_pairing_field[slice_numb / 2];
   9399                 soc_IFP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry, fld,
   9400                                                     paired);
   9401 
   9402                 BCM_IF_ERROR_RETURN
   9403                     (WRITE_IFP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL, port,
   9404                                                &pfs_entry));
   9405             }
   9406 
   9407         }
   9408     } else 
   9409 #endif /* BCM_FIREBOLT2_SUPPORT */
   9410     {
   9411         if (flags & _FP_GROUP_SPAN_SINGLE_SLICE) {
   9412             mode = 0;
   9413         } else if (flags & _FP_GROUP_SPAN_DOUBLE_SLICE) {
   9414             mode = 1;
   9415         } else if (flags & _FP_GROUP_SPAN_TRIPLE_SLICE) {
   9416             mode = 2; 
   9417         } else {
   9418             return (BCM_E_PARAM);
   9419         }
   9420 
   9421         BCM_IF_ERROR_RETURN
   9422             (soc_reg_field32_modify(unit, FP_SLICE_CONFIGr, REG_PORT_ANY,
   9423                                     _fb_ing_slice_mode_field[slice_numb],
   9424                                     mode));
   9425     }
   9426     return (BCM_E_NONE);
   9427 }
   9428 
   9429 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
   9430 /*
   9431  * Function:
   9432  *     _bcm_field_fb_lookup_mode_set
   9433  *
   9434  * Purpose:
   9435  *     Helper function to _bcm_field_fb_mode_install that sets the mode of a
   9436  *     slice in a register value that is to be used for VFP_KEY_CONTROLr.
   9437  *
   9438  * Parameters:
   9439  *     unit       - (IN) BCM device number. 
   9440  *     slice_numb - (IN) Slice number to set mode for.
   9441  *     fg         - (IN) Filed group structure.
   9442  *     flags      - (IN) New group/slice mode.
   9443  *
   9444  * Returns:
   9445  *     BCM_E_XXX
   9446  */
   9447 int 
   9448 _bcm_field_fb_lookup_mode_set(int unit, uint8 slice_numb, 
   9449                               _field_group_t *fg, uint8 flags) 
   9450 {
   9451     int paired,dbl_wide;
   9452     uint32  reg_val;
   9453     if (slice_numb >= COUNTOF(_vfp_slice_wide_mode_field)) {
   9454         return (BCM_E_PARAM);
   9455     }
   9456     SOC_IF_ERROR_RETURN(READ_VFP_KEY_CONTROLr(unit, &reg_val));
   9457 
   9458     paired = (flags & _FP_GROUP_SPAN_DOUBLE_SLICE) ? 1 : 0; 
   9459     soc_reg_field_set(unit, VFP_KEY_CONTROLr, &reg_val,
   9460                       _vfp_slice_pairing_field[slice_numb / 2], paired);
   9461 
   9462     dbl_wide = (flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) ? 1 : 0;
   9463     soc_reg_field_set(unit, VFP_KEY_CONTROLr, &reg_val,
   9464                       _vfp_slice_wide_mode_field[slice_numb], dbl_wide);
   9465     
   9466     SOC_IF_ERROR_RETURN(WRITE_VFP_KEY_CONTROLr(unit, reg_val));
   9467     return (BCM_E_NONE);
   9468 }
   9469 
   9470 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT*/
   9471 
   9472 #if defined(BCM_FIREBOLT2_SUPPORT) 
   9473 /*
   9474  * Function:
   9475  *     _field_fb_egress_mode_set
   9476  *
   9477  * Purpose:
   9478  *     Helper function to _bcm_field_fb_mode_install that sets the mode of a
   9479  *     slice in a register value that is to be used for FP_SLICE_CONFIGr.
   9480  *
   9481  * Parameters:
   9482  *     unit       - (IN) BCM device number. 
   9483  *     slice_numb - (IN) Slice number to set mode for.
   9484  *     fg         - (IN) Installed group structure. 
   9485  *     flags      - (IN) New group/slice mode.
   9486  *
   9487  * Returns:
   9488  *     BCM_E_XXX
   9489  */
   9490 STATIC int
   9491 _field_fb_egress_mode_set(int unit, uint8 slice_numb, 
   9492                           _field_group_t *fg, uint8 flags)
   9493 {
   9494     int                mode_val;
   9495 
   9496     /* Input parameters check. */
   9497     if ((NULL == fg) || (slice_numb >= COUNTOF(_efp_slice_mode))) {
   9498         return (BCM_E_PARAM);
   9499     }
   9500 
   9501     if (flags & _FP_GROUP_SPAN_DOUBLE_SLICE) {
   9502         BCM_IF_ERROR_RETURN
   9503             (soc_reg_field32_modify(unit, EFP_SLICE_CONTROLr, REG_PORT_ANY,
   9504                                     _efp_slice_mode[slice_numb],
   9505                                     _BCM_FIELD_EGRESS_SLICE_MODE_DOUBLE));
   9506     } else {
   9507         mode_val = (3 == fg->sel_codes[0].fpf3) ?
   9508             _BCM_FIELD_EGRESS_SLICE_MODE_SINGLE_L2 :
   9509             _BCM_FIELD_EGRESS_SLICE_MODE_SINGLE_L3;
   9510         BCM_IF_ERROR_RETURN
   9511             (soc_reg_field32_modify(unit, EFP_SLICE_CONTROLr, REG_PORT_ANY,
   9512                                     _efp_slice_mode[slice_numb], mode_val));
   9513     }
   9514     return (BCM_E_NONE);
   9515 }
   9516 /*
   9517  * Function:
   9518  *     _field_fb_egress_slice_clear
   9519  *
   9520  * Purpose:
   9521  *     Reset slice configuraton on group deletion event. 
   9522  *
   9523  * Parameters:
   9524  *     unit       - (IN) BCM device number. 
   9525  *     slice_numb - (IN) Slice number to set mode for.
   9526  *
   9527  * Returns:
   9528  *     BCM_E_XXX
   9529  */
   9530 STATIC int
   9531 _field_fb_egress_slice_clear(int unit, uint8 slice_numb)
   9532 {
   9533     int rv; 
   9534 
   9535     /* Input parameters check. */
   9536     if (slice_numb >= COUNTOF(_efp_slice_mode)) {
   9537         return (BCM_E_PARAM);
   9538     }
   9539 
   9540     rv = soc_reg_field32_modify(unit, EFP_SLICE_CONTROLr, REG_PORT_ANY,
   9541                                 _efp_slice_mode[slice_numb], 0);
   9542     return rv;
   9543 }
   9544 #endif /* BCM_FIREBOLT2_SUPPORT */
   9545 
   9546 
   9547 /*
   9548  * Function:
   9549  *     _bcm_field_fb_mode_set
   9550  *
   9551  * Purpose:
   9552  *    Auxiliary routine used to set group pairing mode.
   9553  * Parameters:
   9554  *     unit       - (IN) BCM device number. 
   9555  *     slice_numb - (IN) Slice number to set mode for.
   9556  *     fg         - (IN) Installed group structure. 
   9557  *     flags      - (IN) New group/slice mode.
   9558  *
   9559  * Returns:
   9560  *     BCM_E_XXX
   9561  */
   9562 int 
   9563 _bcm_field_fb_mode_set(int unit, uint8 slice_numb, _field_group_t *fg, uint8 flags) 
   9564 {
   9565     int rv;     /* Operation return status. */
   9566 
   9567     /* Input parameter check. */
   9568     if (NULL == fg) {
   9569         return (BCM_E_PARAM);
   9570     }
   9571 
   9572     if (!soc_feature(unit, soc_feature_field_wide)) {
   9573         if (flags & _FP_GROUP_SPAN_SINGLE_SLICE) {
   9574             return (BCM_E_NONE);
   9575         }
   9576         return (BCM_E_UNAVAIL);
   9577     }
   9578 
   9579     switch (fg->stage_id) {
   9580       case _BCM_FIELD_STAGE_INGRESS:
   9581           rv = _field_fb_ingress_mode_set(unit, slice_numb, fg, flags);
   9582           break;
   9583 #if defined(BCM_FIREBOLT2_SUPPORT) 
   9584       case _BCM_FIELD_STAGE_LOOKUP:
   9585           rv  = _bcm_field_fb_lookup_mode_set(unit, slice_numb, fg, flags);
   9586           break;
   9587       case _BCM_FIELD_STAGE_EGRESS:
   9588           rv = _field_fb_egress_mode_set(unit, slice_numb, fg, flags);
   9589           break;
   9590 #endif /* BCM_FIREBOLT2_SUPPORT */
   9591       default: 
   9592           rv = BCM_E_PARAM;
   9593     }
   9594     return (rv);
   9595 }
   9596 
   9597 
   9598 /*
   9599  * Function:
   9600  *     _field_selcodes_install
   9601  *
   9602  * Purpose:
   9603  *     Writes the field select codes (ie. FPFx).
   9604  *
   9605  * Parameters:
   9606  *     unit  - BCM device number
   9607  *     fs    - slice that needs its select codes written
   9608  *
   9609  * Returns:
   9610  *     BCM_E_INTERNAL - On read/write errors
   9611  *     BCM_E_NONE     - Success
   9612  *
   9613  * Note:
   9614  *     Unit lock should be held by calling function.
   9615  */
   9616 STATIC int
   9617 _field_selcodes_install(int unit, _field_group_t *fg, 
   9618                            uint8 slice_numb, bcm_pbmp_t pbmp, 
   9619                            int selcode_index)
   9620 {
   9621     int rv;    /* Operation return status. */
   9622 
   9623     /* Input parameters check. */
   9624     if (NULL == fg) {
   9625         return (BCM_E_PARAM);
   9626     }
   9627     
   9628 
   9629     /* Set slice mode. Single/Double/Triple, Intraslice */
   9630     rv = _bcm_field_fb_mode_set(unit, slice_numb, fg, fg->flags);
   9631     BCM_IF_ERROR_RETURN(rv);
   9632 
   9633     switch (fg->stage_id) {
   9634       case _BCM_FIELD_STAGE_INGRESS: 
   9635           rv = _field_fb_ingress_selcodes_install(unit, fg, slice_numb,
   9636                                                   pbmp, selcode_index);
   9637           break;
   9638 #if defined(BCM_FIREBOLT2_SUPPORT) 
   9639       case _BCM_FIELD_STAGE_LOOKUP:
   9640           rv = _field_fb_lookup_selcodes_install(unit, fg, slice_numb,
   9641                                                  selcode_index);
   9642           break;
   9643       case _BCM_FIELD_STAGE_EGRESS:
   9644           rv = (BCM_E_NONE);
   9645           break;
   9646 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
   9647       default:
   9648           rv = (BCM_E_PARAM);
   9649     }
   9650     return (rv);
   9651 }
   9652 
   9653 /*
   9654  * Function:
   9655  *     _bcm_field_fb_group_install
   9656  *
   9657  * Purpose:
   9658  *     Writes the Group's mode and field select codes into hardware. This
   9659  *     should be called both at group creation time and any time the select
   9660  *     codes change (i.e. bcm_field_group_set calls).
   9661  *
   9662  * Parameters:
   9663  *     unit  - BCM device number
   9664  *     fg    - group to install
   9665  *
   9666  * Returns:
   9667  *     BCM_E_INTERNAL - On read/write errors
   9668  *     BCM_E_NONE     - Success
   9669  *
   9670  * Note:
   9671  *     Unit lock should be held by calling function.
   9672  */
   9673 int
   9674 _bcm_field_fb_group_install(int unit, _field_group_t *fg) 
   9675 {
   9676     _field_slice_t *fs;        /* Slice pointer.           */
   9677     uint8  slice_number;       /* Slices iterator.         */
   9678     int    parts_count;        /* Number of entry parts.   */
   9679     int    idx;                /* Iteration index.         */
   9680     int    rv;                 /* Operation return status. */
   9681 
   9682     if (NULL == fg) {
   9683         return (BCM_E_PARAM);
   9684     }
   9685 
   9686     /* Get number of entry parts. */
   9687     rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
   9688                                             fg->flags, &parts_count);
   9689     BCM_IF_ERROR_RETURN(rv);
   9690 
   9691     for (idx = 0; idx < parts_count;  idx++) {
   9692 
   9693         /* Get slice id for entry part */
   9694         rv = _bcm_field_tcam_part_to_slice_number(unit, idx, fg,
   9695                                                   &slice_number);
   9696         BCM_IF_ERROR_RETURN(rv);
   9697 
   9698         /* Get slice pointer. */
   9699         fs = fg->slices + slice_number;
   9700 
   9701 #if defined(BCM_TOMAHAWK_SUPPORT)
   9702         if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
   9703             rv = _bcm_field_th_selcodes_install (unit, fg, fs->slice_number,
   9704                                                   fg->pbmp, idx);
   9705         } else
   9706 #endif 
   9707 #if defined(BCM_TRX_SUPPORT)
   9708         if (SOC_IS_TRX(unit) && !(SOC_IS_HURRICANE2(unit) ||
   9709             SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
   9710             SOC_IS_GREYHOUND2(unit))) {
   9711             rv = _bcm_field_trx_selcodes_install (unit, fg, fs->slice_number, 
   9712                                                   fg->pbmp, idx);
   9713         } else
   9714 #if defined(BCM_HURRICANE2_SUPPORT)
   9715         if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
   9716             SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
   9717             rv = _bcm_field_hu2_selcodes_install (unit, fg, fs->slice_number,
   9718                                                   fg->pbmp, idx);
   9719         } else
   9720 #endif  /* BCM_HURRICANE2_SUPPORT */
   9721 #endif /* BCM_TRX_SUPPORT */
   9722         {
   9723             rv = _field_selcodes_install(unit, fg, fs->slice_number, fg->pbmp, idx);
   9724         }
   9725         BCM_IF_ERROR_RETURN(rv);
   9726     }
   9727     return (BCM_E_NONE);
   9728 }
   9729 
   9730 /*
   9731  * Function:
   9732  *     _bcm_field_fb_slice_clear
   9733  *
   9734  * Purpose:
   9735  *     Clear slice configuration on group removal
   9736  *
   9737  * Parameters:
   9738  *     unit  - BCM device number
   9739  *     fg    - Field group slice belongs to
   9740  *     fs    - Field slice structure.
   9741  *
   9742  * Returns:
   9743  *     BCM_E_XXX
   9744  */
   9745 int
   9746 _bcm_field_fb_slice_clear(int unit, _field_group_t *fg, _field_slice_t *fs) 
   9747 {
   9748     int rv;
   9749 
   9750     switch (fs->stage_id) {
   9751       case _BCM_FIELD_STAGE_INGRESS:
   9752           rv = _field_fb_ingress_slice_clear(unit, fs->slice_number);
   9753           break;
   9754 #if defined(BCM_FIREBOLT2_SUPPORT) 
   9755       case _BCM_FIELD_STAGE_LOOKUP:
   9756           rv = _field_fb_lookup_slice_clear(unit, fs->slice_number);
   9757           break;
   9758       case _BCM_FIELD_STAGE_EGRESS:
   9759           rv = _field_fb_egress_slice_clear(unit, fs->slice_number);
   9760           break;
   9761 #endif /* BCM_FIREBOLT2_SUPPORT */
   9762       default: 
   9763           rv = BCM_E_INTERNAL;
   9764     }
   9765 
   9766     return (rv);
   9767 }
   9768 
   9769 /*
   9770  * Function:
   9771  *     _bcm_field_fb_entry_remove
   9772  * Purpose:
   9773  *     Remove a previously installed physical entry.
   9774  * Parameters:
   9775  *     unit   - BCM device number
   9776  *     f_ent  - Physical entry data
   9777  * Returns:
   9778  *     BCM_E_XXX
   9779  *     BCM_E_NONE
   9780  * Notes:
   9781  *     FP unit lock should be held by calling function.
   9782  */
   9783 int
   9784 _bcm_field_fb_entry_remove(int unit, _field_entry_t *f_ent, int tcam_idx)
   9785 {
   9786 #ifdef BCM_KATANA_SUPPORT
   9787     uint32 param0 = 0, param1 = 0, in_flags = 0;
   9788     int queue_id = 0;
   9789     ing_queue_map_entry_t ing_queue_entry;
   9790     int referenceCount = 0;
   9791     _field_action_t *fa = NULL;
   9792 #endif
   9793 #ifdef BCM_KATANA2_SUPPORT
   9794     int rv = BCM_E_NONE;
   9795 #endif
   9796 
   9797     if (NULL == f_ent) {
   9798         return (BCM_E_PARAM);
   9799     }
   9800 
   9801     if (NULL == f_ent->fs) {
   9802         return (BCM_E_PARAM);
   9803     }
   9804 
   9805 
   9806     BCM_IF_ERROR_RETURN
   9807         (_field_fb_tcam_policy_clear(unit, f_ent, f_ent->fs->stage_id, tcam_idx));
   9808 
   9809 #if defined(BCM_KATANA_SUPPORT)
   9810     if (SOC_IS_KATANAX(unit)) {
   9811         if ((f_ent->fs->stage_id == _BCM_FIELD_STAGE_INGRESS) &&
   9812             (!(f_ent->flags & _FP_ENTRY_DIRTY)) ) {
   9813 
   9814             for (fa = f_ent->actions; fa != NULL; fa = fa->next) {
   9815                 if (fa->action == bcmFieldActionFabricQueue) {
   9816                     sal_memset(&ing_queue_entry, 0,
   9817                                sizeof(ing_queue_map_entry_t));
   9818                     param0 = fa->param[0];
   9819                     param1 = fa->param[1];
   9820                     /* For Katana if param1 BCM_FABRIC_QUEUE_xxx
   9821                      * flags are set then param0 is
   9822                      * ucast/ucast_subscriber group cosq gport */
   9823                     if ((param1 & BCM_FABRIC_QUEUE_DEST_OFFSET) ||
   9824                         (param1 & BCM_FABRIC_QUEUE_CUSTOMER)) {
   9825                         if(BCM_GPORT_IS_UCAST_QUEUE_GROUP(param0) ||
   9826                            BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(param0) ||
   9827                            BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(param0)) {
   9828 #if defined(BCM_KATANA2_SUPPORT)
   9829                             if (SOC_IS_KATANA2(unit)) {
   9830                                 queue_id = -1;
   9831                                 rv = _bcm_kt2_cosq_index_resolve(
   9832                                       unit, param0, 0,
   9833                                       _BCM_KT_COSQ_INDEX_STYLE_BUCKET,
   9834                                       NULL, &queue_id, NULL);
   9835                                 if (BCM_FAILURE(rv) &&
   9836                                      (rv != BCM_E_NOT_FOUND)) {
   9837                                     return rv;
   9838                                 }
   9839                             } else
   9840 #endif
   9841                             {
   9842                                 if (SOC_IS_KATANA(unit)) {
   9843                                     BCM_IF_ERROR_RETURN(
   9844                                         _bcm_kt_cosq_index_resolve(
   9845                                           unit, param0, 0,
   9846                                           _BCM_KT_COSQ_INDEX_STYLE_BUCKET,
   9847                                           NULL, &queue_id, NULL));
   9848                                 }
   9849                             }
   9850                         } else {
   9851                             queue_id = param0 & 0xffff;
   9852                         }
   9853                         in_flags = param1;
   9854                     } else {
   9855                         queue_id = param0 & 0xffff;
   9856                         in_flags = param0;
   9857                     }
   9858 
   9859                     if (in_flags & BCM_FABRIC_QUEUE_DEST_OFFSET) {
   9860                         if (queue_id != -1) {
   9861                             BCM_IF_ERROR_RETURN(
   9862                               _bcm_field_fabricQueue_action_node_delete (unit,
   9863                                   queue_id, param1, &referenceCount));
   9864                             if(referenceCount == 0) {
   9865                                BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_WRITE(unit,
   9866                                             ING_QUEUE_MAPm,
   9867                                             queue_id, &ing_queue_entry));
   9868                             }
   9869                             fa->flags = fa->flags | _FP_ACTION_DIRTY;
   9870                         }
   9871                     }
   9872                 }
   9873             }
   9874         }
   9875     }   
   9876 #endif
   9877     f_ent->flags |= _FP_ENTRY_DIRTY; /* Mark entry as not installed */
   9878 
   9879     return (BCM_E_NONE);
   9880 }
   9881 #ifdef INCLUDE_L3
   9882 /*
   9883  * Function:
   9884  *     _bcm_field_policy_set_l3_info
   9885  * Purpose:
   9886  *     Install l3 forwarding policy entry.  
   9887  * Parameters:
   9888  *     unit      - (IN) BCM device number
   9889  *     mem       - (IN) Policy table memory. 
   9890  *     value     - (IN) Egress object id or combined next hop information.
   9891  *     buf       - (IN/OUT) Hw entry buffer to write.
   9892  * Returns:
   9893  *     BCM_E_XXX
   9894  */
   9895 
   9896 int
   9897 _bcm_field_policy_set_l3_info(int unit, soc_mem_t mem, int value, uint32 *buf)
   9898 {
   9899     uint32 flags;         /* L3 forwarding flags           */ 
   9900     int nh_ecmp_id;       /* Next hop/Ecmp group id.       */
   9901     int max_ecmp_paths;   /* Maximum number of ecmp paths. */
   9902     int retval;           /* Operation return value.       */ 
   9903     
   9904     /* Resove next hop /ecmp group id. */
   9905     retval = _bcm_field_policy_set_l3_nh_resolve(unit,  value,
   9906                                                  &flags, &nh_ecmp_id);
   9907     BCM_IF_ERROR_RETURN(retval);
   9908 
   9909     if (flags & BCM_L3_MULTIPATH) {              
   9910         PolicySet(unit, mem, buf, ECMPf, 1);
   9911         PolicySet(unit, mem, buf, ECMP_PTRf, nh_ecmp_id);
   9912         BCM_IF_ERROR_RETURN(bcm_xgs3_max_ecmp_get(unit, &max_ecmp_paths));
   9913         PolicySet(unit, mem, buf, ECMP_COUNTf, max_ecmp_paths - 1);
   9914     } else {
   9915         PolicySet(unit, mem, buf, ECMPf, 0);
   9916         PolicySet(unit, mem, buf, NEXT_HOP_INDEXf, nh_ecmp_id);
   9917     }
   9918     return (BCM_E_NONE);
   9919 }
   9920 #endif /* INCLUDE_L3 */
   9921 /*
   9922  * Function:
   9923  *     _field_fb_action_copy_to_cpu
   9924  * Purpose:
   9925  *     Install copy to cpu action in policy table.
   9926  * Parameters:
   9927  *     unit     - (IN) BCM device number
   9928  *     mem      - (IN) Policy table memory
   9929  *     f_ent    - (IN) Field entry structure to get policy info from
   9930  *     fa       - (IN  Field action 
   9931  *     buf      - (OUT) Field Policy table entry
   9932  * Returns:
   9933  *     BCM_E_XXX
   9934  */
   9935 STATIC int
   9936 _field_fb_action_copy_to_cpu(int unit, soc_mem_t mem, _field_entry_t *f_ent, 
   9937                              _field_action_t *fa, uint32 *buf)
   9938 {
   9939     if (NULL == f_ent || NULL == fa || NULL == buf) {
   9940         return (BCM_E_PARAM);
   9941     }
   9942 
   9943     if ((fa->param[0] != 0) && (fa->param[1] >= (1 << 8))) {
   9944         LOG_ERROR(BSL_LS_BCM_FP,
   9945                   (BSL_META_U(unit,
   9946                               "FP(unit %d) Error: param1=%d out of range for CopyToCpu.\n"),
   9947                    unit, fa->param[1]));
   9948         return (BCM_E_PARAM);
   9949     }
   9950 
   9951     switch (fa->action) {
   9952       case bcmFieldActionCopyToCpu:
   9953 #if defined(BCM_FIREBOLT2_SUPPORT)
   9954           if (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) {
   9955               PolicySet(unit, mem, buf, COPY_TO_CPUf, 0x1);
   9956           } else 
   9957 #endif /* BCM_FIREBOLT2_SUPPORT */
   9958           {
   9959               PolicySet(unit, mem, buf, RP_COPY_TO_CPUf, 0x1);
   9960               PolicySet(unit, mem, buf, YP_COPY_TO_CPUf, 0x1);
   9961               PolicySet(unit, mem, buf, COPY_TO_CPUf, 0x1);
   9962           }
   9963           break;
   9964       case bcmFieldActionRpCopyToCpu:
   9965           PolicySet(unit, mem, buf, RP_COPY_TO_CPUf, 0x1);
   9966           break;
   9967       case bcmFieldActionYpCopyToCpu:
   9968           PolicySet(unit, mem, buf, YP_COPY_TO_CPUf, 0x1);
   9969           break;
   9970       case bcmFieldActionGpCopyToCpu:
   9971           PolicySet(unit, mem, buf, COPY_TO_CPUf, 0x1);
   9972           break;
   9973 
   9974       default:
   9975           return (BCM_E_INTERNAL);
   9976     }
   9977 
   9978     if (fa->param[0] != 0) {
   9979         if (SOC_MEM_FIELD_VALID(unit, mem, MATCHED_RULEf)) {
   9980             PolicySet(unit, mem, buf, MATCHED_RULEf, fa->param[1]);
   9981         }
   9982     }
   9983     return (BCM_E_NONE);
   9984 }
   9985 
   9986 
   9987 /*
   9988  * Function:
   9989  *     _field_fb_action_get
   9990  * Purpose:
   9991  *     Install an action into the hardware tables.
   9992  * Parameters:
   9993  *     unit     - BCM device number
   9994  *     mem      - Policy table memory.
   9995  *     tcam_idx - index into TCAM
   9996  *     fa       - field action 
   9997  *     buf      - (OUT) Field TCAM plus Policy table entry
   9998  * Returns:
   9999  *     BCM_E_NONE
  10000  *     BCM_E_PARAM - Action parameter out-of-range or unrecognized action.
  10001  * Notes:
  10002  *     This is a simple read/modify/write pattern.
  10003  *     FP unit lock should be held by calling function.
  10004  */
  10005 STATIC int
  10006 _field_fb_action_get(int unit, soc_mem_t mem, _field_entry_t *f_ent, 
  10007                      int tcam_idx, _field_action_t *fa, uint32 *buf)
  10008 {
  10009 #if defined (BCM_FIREBOLT2_SUPPORT)
  10010     uint32                          mode;
  10011 #endif /* BCM_FIREBOLT2_SUPPORT */
  10012     uint32                          redir_field = 0;
  10013 
  10014     if (NULL == f_ent || NULL == fa || NULL == buf) {
  10015         return (BCM_E_PARAM);
  10016     }
  10017 
  10018     LOG_DEBUG(BSL_LS_BCM_FP,
  10019               (BSL_META_U(unit,
  10020                           "FP(unit %d) vverb: BEGIN _field_fb_action_get(eid=%d, tcam_idx=0x%x, "),
  10021                unit, f_ent->eid, tcam_idx));
  10022 #ifdef BROADCOM_DEBUG
  10023     LOG_DEBUG(BSL_LS_BCM_FP,
  10024               (BSL_META_U(unit,
  10025                           "action={%s,%d,%d})\n"),
  10026                _field_fb_action_name(fa->action),
  10027                fa->param[0], fa->param[1]));
  10028 #endif
  10029 
  10030     switch (fa->action) {
  10031     case bcmFieldActionCosQNew:
  10032         PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 1);
  10033         PolicySet(unit, mem, buf, NEWPRIf, fa->param[0]);
  10034         break;
  10035     case bcmFieldActionCosQCpuNew:
  10036         PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 2);
  10037         PolicySet(unit, mem, buf, NEWPRIf, fa->param[0]);
  10038         break;
  10039     case bcmFieldActionPrioPktAndIntCopy:
  10040         PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 4);
  10041         break;
  10042     case bcmFieldActionPrioPktAndIntNew:
  10043         PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 5);
  10044         PolicySet(unit, mem, buf, NEWPRIf, fa->param[0]);
  10045         break;
  10046     case bcmFieldActionPrioPktAndIntTos:
  10047         PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 6);
  10048         break;
  10049     case bcmFieldActionPrioPktAndIntCancel:
  10050         PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 7);
  10051         break;
  10052     case bcmFieldActionPrioPktCopy:
  10053         PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 8);
  10054         break;
  10055     case bcmFieldActionPrioPktNew:
  10056         PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 9);
  10057         PolicySet(unit, mem, buf, NEWPRIf, fa->param[0]);
  10058         break;
  10059     case bcmFieldActionPrioPktTos:
  10060         PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 10);
  10061         break;
  10062     case bcmFieldActionPrioPktCancel:
  10063         PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 11);
  10064         break;
  10065     case bcmFieldActionPrioIntCopy:
  10066         PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 12);
  10067         break;
  10068     case bcmFieldActionPrioIntNew:
  10069         PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 13);
  10070         PolicySet(unit, mem, buf, NEWPRIf, fa->param[0]);
  10071         break;
  10072     case bcmFieldActionPrioIntTos:
  10073         PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 14);
  10074         break;
  10075     case bcmFieldActionPrioIntCancel:
  10076         PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 15);
  10077         break;
  10078     case bcmFieldActionTosNew:
  10079         PolicySet(unit, mem, buf, CHANGE_DSCP_TOSf, 1);
  10080         PolicySet(unit, mem, buf, NEWDSCP_TOSf, fa->param[0]);
  10081         break;
  10082     case bcmFieldActionTosCopy:
  10083         PolicySet(unit, mem, buf, CHANGE_DSCP_TOSf, 2);
  10084         break;
  10085     case bcmFieldActionDscpNew:
  10086 #if defined(BCM_FIREBOLT2_SUPPORT) 
  10087         if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) {
  10088                         PolicySet(unit, mem, buf, RP_CHANGE_DSCPf, 1);
  10089                         PolicySet(unit, mem, buf, YP_CHANGE_DSCPf, 1);
  10090                         PolicySet(unit, mem, buf, GP_CHANGE_DSCPf, 1);
  10091             PolicySet(unit, mem, buf, RP_NEW_DSCPf, fa->param[0]);
  10092             PolicySet(unit, mem, buf, YP_NEW_DSCPf, fa->param[0]);
  10093             PolicySet(unit, mem, buf, GP_NEW_DSCPf, fa->param[0]);
  10094         } else 
  10095 #endif /* BCM_FIREBOLT2_SUPPORT */
  10096         {
  10097             PolicySet(unit, mem, buf, CHANGE_DSCP_TOSf, 3);
  10098             PolicySet(unit, mem, buf, NEWDSCP_TOSf, fa->param[0]);
  10099             PolicySet(unit, mem, buf, RP_CHANGE_DSCPf, 1);
  10100             PolicySet(unit, mem, buf, RP_DSCPf, fa->param[0]);
  10101             PolicySet(unit, mem, buf, YP_CHANGE_DSCPf, 1);
  10102             PolicySet(unit, mem, buf, YP_DSCPf, fa->param[0]);
  10103         }
  10104         break;
  10105     case bcmFieldActionTosCancel:
  10106         PolicySet(unit, mem, buf, CHANGE_DSCP_TOSf, 4);
  10107         break;
  10108     case bcmFieldActionDscpCancel:
  10109         PolicySet(unit, mem, buf, CHANGE_DSCP_TOSf, 4);
  10110         break;
  10111     case bcmFieldActionCopyToCpu:
  10112     case bcmFieldActionRpCopyToCpu:
  10113     case bcmFieldActionYpCopyToCpu:
  10114     case bcmFieldActionGpCopyToCpu:
  10115         BCM_IF_ERROR_RETURN
  10116             (_field_fb_action_copy_to_cpu(unit, mem, f_ent, fa, buf));
  10117         break;
  10118     case bcmFieldActionGpCopyToCpuCancel:
  10119         PolicySet(unit, mem, buf, COPY_TO_CPUf, 2);
  10120         break;
  10121     case bcmFieldActionCopyToCpuCancel:
  10122         PolicySet(unit, mem, buf, COPY_TO_CPUf, 2);
  10123         PolicySet(unit, mem, buf, YP_COPY_TO_CPUf, 2);
  10124         PolicySet(unit, mem, buf, RP_COPY_TO_CPUf, 2);
  10125         break;
  10126     case bcmFieldActionSwitchToCpuCancel:
  10127         PolicySet(unit, mem, buf, COPY_TO_CPUf, 3);
  10128         break;
  10129     case bcmFieldActionRedirect:    /* param0=modid, param1=port/tgid */
  10130         PolicySet(unit, mem, buf, PACKET_REDIRECTIONf, 1);
  10131         PolicySet(unit, mem, buf, REDIRECTIONf, 
  10132                   (fa->param[0] << 6) | fa->param[1]);
  10133         break;
  10134     case bcmFieldActionRedirectTrunk:    /* param0 = trunk ID */
  10135         if (soc_property_get(unit, spn_TRUNK_EXTEND, 1)) {
  10136             redir_field = ((fa->param[0] & 0x60) << 1) | (fa->param[0] & 0x1f);
  10137         } else {
  10138             redir_field = fa->param[0] & 0x1f;
  10139         }
  10140         redir_field |= 0x20; 
  10141         PolicySet(unit, mem, buf, PACKET_REDIRECTIONf, 1);
  10142         PolicySet(unit, mem, buf, REDIRECTIONf, redir_field);
  10143         break;
  10144     case bcmFieldActionRedirectCancel:
  10145         PolicySet(unit, mem, buf, PACKET_REDIRECTIONf, 2);
  10146         break;
  10147     case bcmFieldActionRedirectPbmp:
  10148         PolicySet(unit, mem, buf, PACKET_REDIRECTIONf, 3);
  10149         PolicySet(unit, mem, buf, REDIRECTIONf, fa->param[0]);
  10150         break;
  10151     case bcmFieldActionEgressMask:
  10152         PolicySet(unit, mem, buf, PACKET_REDIRECTIONf, 4);
  10153         PolicySet(unit, mem, buf, REDIRECTIONf, fa->param[0]);
  10154         break;
  10155     case bcmFieldActionDrop:
  10156 #if defined (BCM_FIREBOLT2_SUPPORT)
  10157                 if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) {
  10158                         PolicySet(unit, mem, buf, RP_DROPf, 1);
  10159                         PolicySet(unit, mem, buf, YP_DROPf, 1);
  10160                         PolicySet(unit, mem, buf, GP_DROPf, 1);
  10161                 } else if (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) {
  10162                         PolicySet(unit, mem, buf, DROPf, 1);
  10163         } else 
  10164 #endif /* BCM_FIREBOLT2_SUPPORT */
  10165                 {
  10166                         PolicySet(unit, mem, buf, RP_DROPf, 1);
  10167                         PolicySet(unit, mem, buf, YP_DROPf, 1);
  10168                         PolicySet(unit, mem, buf, DROPf, 1);
  10169                 }
  10170                 break;
  10171         case bcmFieldActionDropCancel:
  10172 #if defined (BCM_FIREBOLT2_SUPPORT)
  10173                 if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) {
  10174                         PolicySet(unit, mem, buf, RP_DROPf, 2);
  10175                         PolicySet(unit, mem, buf, YP_DROPf, 2);
  10176                         PolicySet(unit, mem, buf, GP_DROPf, 2);
  10177                 } else if (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) {
  10178                         PolicySet(unit, mem, buf, DROPf, 2);
  10179                 } else 
  10180 #endif /* BCM_FIREBOLT2_SUPPORT */
  10181                 {
  10182                         PolicySet(unit, mem, buf, RP_DROPf, 2);
  10183                         PolicySet(unit, mem, buf, YP_DROPf, 2);
  10184                         PolicySet(unit, mem, buf, DROPf, 2);
  10185                 }
  10186                 break;
  10187     case bcmFieldActionMirrorOverride:
  10188         if (soc_feature(unit, soc_feature_field_mirror_ovr)) {
  10189             PolicySet(unit, mem, buf, MIRROR_OVERRIDEf, 1);
  10190         } else {
  10191             return BCM_E_PARAM;
  10192         }
  10193         break;
  10194     case bcmFieldActionMirrorIngress:    /* param0=modid, param1=port/tgid */
  10195         PolicySet(unit, mem, buf, IM_MTP_INDEXf, fa->hw_index);
  10196         PolicySet(unit, mem, buf, MIRRORf, 
  10197                   PolicyGet(unit, mem, buf, MIRRORf) | 0x1);
  10198         if (soc_feature(unit, soc_feature_field_mirror_pkts_ctl)) {
  10199             BCM_IF_ERROR_RETURN
  10200                 (soc_reg_field32_modify(unit, ING_CONFIGr, REG_PORT_ANY,
  10201                                         ENABLE_FP_FOR_MIRROR_PKTSf, 1));
  10202         }
  10203         break;
  10204     case bcmFieldActionMirrorEgress:     /* param0=modid, param1=port/tgid */
  10205         PolicySet(unit, mem, buf, EM_MTP_INDEXf, fa->hw_index);
  10206         PolicySet(unit, mem, buf, MIRRORf, 
  10207                   PolicyGet(unit, mem, buf, MIRRORf) | 2);
  10208         if (soc_feature(unit, soc_feature_field_mirror_pkts_ctl)) {
  10209             BCM_IF_ERROR_RETURN
  10210                 (soc_reg_field32_modify(unit, ING_CONFIGr, REG_PORT_ANY,
  10211                                         ENABLE_FP_FOR_MIRROR_PKTSf, 1));
  10212         }
  10213         break;
  10214 #ifdef INCLUDE_L3 
  10215     case bcmFieldActionL3ChangeVlan:
  10216         PolicySet(unit, mem, buf, L3SW_CHANGE_MACDA_OR_VLANf, 1);
  10217         BCM_IF_ERROR_RETURN
  10218             (_bcm_field_policy_set_l3_info(unit, mem, fa->param[0], buf)); 
  10219         break;
  10220     case bcmFieldActionL3ChangeVlanCancel:
  10221         PolicySet(unit, mem, buf, L3SW_CHANGE_MACDA_OR_VLANf, 2);
  10222         break;
  10223     case bcmFieldActionL3ChangeMacDa:
  10224         PolicySet(unit, mem, buf, L3SW_CHANGE_MACDA_OR_VLANf, 4);
  10225         BCM_IF_ERROR_RETURN
  10226             (_bcm_field_policy_set_l3_info(unit, mem,  fa->param[0], buf)); 
  10227         break;
  10228     case bcmFieldActionSrcMacNew: 
  10229     case bcmFieldActionDstMacNew:
  10230         PolicySet(unit, mem, buf, ECMPf, 0);
  10231         PolicySet(unit, mem, buf, L3SW_CHANGE_MACDA_OR_VLANf, 0x4);
  10232         PolicySet(unit, mem, buf, NEXT_HOP_INDEXf, fa->hw_index);
  10233         break;
  10234     case bcmFieldActionL3ChangeMacDaCancel:
  10235         PolicySet(unit, mem, buf, L3SW_CHANGE_MACDA_OR_VLANf, 5);
  10236         break;
  10237     case bcmFieldActionL3Switch:
  10238         PolicySet(unit, mem, buf, L3SW_CHANGE_MACDA_OR_VLANf, 6);
  10239         BCM_IF_ERROR_RETURN
  10240             (_bcm_field_policy_set_l3_info(unit, mem, fa->param[0], buf)); 
  10241         break;
  10242     case bcmFieldActionL3SwitchCancel:
  10243         PolicySet(unit, mem, buf, L3SW_CHANGE_MACDA_OR_VLANf, 7);
  10244         break;
  10245 #endif /* INCLUDE_L3 */
  10246     case bcmFieldActionAddClassTag:
  10247         PolicySet(unit, mem, buf, L3SW_CHANGE_MACDA_OR_VLANf, 3);
  10248         PolicySet(unit, mem, buf, CLASSIFICATION_TAGf, fa->param[0]);
  10249         break;
  10250     case bcmFieldActionEcnNew:
  10251         /* Ecn in tos byte will be forced to a Drop Precedence value. */ 
  10252         PolicySet(unit, mem, buf, ECN_CNGf, 0x1);
  10253         /* coverity[MISSING_BREAK : FALSE] */
  10254         /* passthru */
  10255     case bcmFieldActionDropPrecedence:
  10256         PolicySet(unit, mem, buf, RP_DROP_PRECEDENCEf, fa->param[0]);
  10257         PolicySet(unit, mem, buf, YP_DROP_PRECEDENCEf, fa->param[0]);
  10258         PolicySet(unit, mem, buf, DROP_PRECEDENCEf, fa->param[0]);
  10259         break;
  10260     case bcmFieldActionGpDropPrecedence:
  10261         PolicySet(unit, mem, buf, DROP_PRECEDENCEf, fa->param[0]);
  10262         break;
  10263     case bcmFieldActionRpDrop:
  10264         PolicySet(unit, mem, buf, RP_DROPf, 1);
  10265         break;
  10266     case bcmFieldActionRpDropCancel:
  10267         PolicySet(unit, mem, buf, RP_DROPf, 2);
  10268         break;
  10269     case bcmFieldActionRpDropPrecedence:
  10270         PolicySet(unit, mem, buf, RP_DROP_PRECEDENCEf, fa->param[0]);
  10271         break;
  10272     case bcmFieldActionRpCopyToCpuCancel:
  10273         PolicySet(unit, mem, buf, RP_COPY_TO_CPUf, 2);
  10274         break;
  10275     case bcmFieldActionRpDscpNew:
  10276         PolicySet(unit, mem, buf, RP_CHANGE_DSCPf, 1);
  10277 #if defined(BCM_FIREBOLT2_SUPPORT) 
  10278         if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) {
  10279             PolicySet(unit, mem, buf, RP_NEW_DSCPf, fa->param[0]);
  10280         } else 
  10281 #endif /* BCM_FIREBOLT2_SUPPORT */
  10282         {
  10283             PolicySet(unit, mem, buf, RP_DSCPf, fa->param[0]);
  10284         }
  10285         break;
  10286     case bcmFieldActionYpDrop:
  10287         PolicySet(unit, mem, buf, YP_DROPf, 1);
  10288         break;
  10289     case bcmFieldActionYpDropCancel:
  10290         PolicySet(unit, mem, buf, YP_DROPf, 2);
  10291         break;
  10292     case bcmFieldActionYpDropPrecedence:
  10293         PolicySet(unit, mem, buf, YP_DROP_PRECEDENCEf, fa->param[0]);
  10294         break;
  10295     case bcmFieldActionYpCopyToCpuCancel:
  10296         PolicySet(unit, mem, buf, YP_COPY_TO_CPUf, 2);
  10297         break;
  10298     case bcmFieldActionYpDscpNew:
  10299         PolicySet(unit, mem, buf, YP_CHANGE_DSCPf, 1);
  10300 #if defined(BCM_FIREBOLT2_SUPPORT) 
  10301         if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) {
  10302             PolicySet(unit, mem, buf, YP_NEW_DSCPf, fa->param[0]);
  10303         } else 
  10304 #endif /* BCM_FIREBOLT2_SUPPORT */
  10305         {
  10306             PolicySet(unit, mem, buf, YP_DSCPf, fa->param[0]);
  10307         }
  10308         break;
  10309     case bcmFieldActionGpDrop:
  10310 #if defined (BCM_FIREBOLT2_SUPPORT)
  10311         if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) {
  10312             PolicySet(unit, mem, buf, GP_DROPf, 1);
  10313         } else 
  10314 #endif /* BCM_FIREBOLT2_SUPPORT */
  10315         {
  10316             PolicySet(unit, mem, buf, DROPf, 1);
  10317         } 
  10318         break;
  10319     case bcmFieldActionGpDropCancel:
  10320 #if defined (BCM_FIREBOLT2_SUPPORT)
  10321         if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) {
  10322             PolicySet(unit, mem, buf, GP_DROPf, 2);
  10323         } else 
  10324 #endif /* BCM_FIREBOLT2_SUPPORT */
  10325         {
  10326             PolicySet(unit, mem, buf, DROPf, 2);
  10327         } 
  10328         break;
  10329     case bcmFieldActionGpDscpNew:
  10330 #if defined(BCM_FIREBOLT2_SUPPORT) 
  10331         if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) {
  10332                         PolicySet(unit, mem, buf, GP_CHANGE_DSCPf, 1);
  10333             PolicySet(unit, mem, buf, GP_NEW_DSCPf, fa->param[0]);
  10334         } else 
  10335 #endif /* BCM_FIREBOLT2_SUPPORT */
  10336         {
  10337             PolicySet(unit, mem, buf, CHANGE_DSCP_TOSf, 3);
  10338             PolicySet(unit, mem, buf, NEWDSCP_TOSf, fa->param[0]);
  10339         } 
  10340         break;
  10341 #if defined(BCM_FIREBOLT2_SUPPORT) 
  10342     case bcmFieldActionRpOuterVlanPrioNew:
  10343         PolicySet(unit, mem, buf, RP_CHANGE_DOT1Pf, 1);
  10344         PolicySet(unit, mem, buf, RP_NEW_DOT1Pf, fa->param[0]);
  10345         break;
  10346     case bcmFieldActionYpOuterVlanPrioNew:
  10347         PolicySet(unit, mem, buf, YP_CHANGE_DOT1Pf, 1);
  10348         PolicySet(unit, mem, buf, YP_NEW_DOT1Pf, fa->param[0]);
  10349         break;
  10350     case bcmFieldActionGpOuterVlanPrioNew:
  10351         PolicySet(unit, mem, buf, GP_CHANGE_DOT1Pf, 1);
  10352         PolicySet(unit, mem, buf, GP_NEW_DOT1Pf, fa->param[0]);
  10353         break;
  10354     case bcmFieldActionClassSet:
  10355         PolicySet(unit, mem, buf, USE_VFP_CLASS_IDf, 1);
  10356         PolicySet(unit, mem, buf, VFP_CLASS_IDf, fa->param[0]); 
  10357         break;
  10358     case bcmFieldActionVrfSet:
  10359         PolicySet(unit, mem, buf, USE_VFP_VRF_IDf, 1);
  10360         PolicySet(unit, mem, buf, VFP_VRF_IDf, fa->param[0]); 
  10361         break;
  10362     case bcmFieldActionVlanAdd:
  10363         PolicySet(unit, mem, buf, CHANGE_VLANf, 1);
  10364         PolicySet(unit, mem, buf, NEW_VLANf, fa->param[0]);
  10365         break;
  10366     case bcmFieldActionInnerVlanNew:
  10367         PolicySet(unit, mem, buf, PID_REPLACE_INNER_VIDf, 1);
  10368         PolicySet(unit, mem, buf, PID_NEW_INNER_VIDf, fa->param[0]);
  10369         break;
  10370     case bcmFieldActionInnerVlanPrioNew:
  10371         PolicySet(unit, mem, buf, PID_REPLACE_INNER_PRIf, 1);
  10372         PolicySet(unit, mem, buf, PID_NEW_INNER_PRIf, fa->param[0]);
  10373         break;
  10374     case bcmFieldActionOuterVlanPrioNew:
  10375         if (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) {
  10376             PolicySet(unit, mem, buf, CHANGE_PRIORITYf, 1);
  10377             PolicySet(unit, mem, buf, NEW_PRIORITYf, fa->param[0]);
  10378         } else if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 
  10379             PolicySet(unit, mem, buf, RP_CHANGE_DOT1Pf, 1);
  10380             PolicySet(unit, mem, buf, RP_NEW_DOT1Pf, fa->param[0]);
  10381             PolicySet(unit, mem, buf, YP_CHANGE_DOT1Pf, 1);
  10382             PolicySet(unit, mem, buf, YP_NEW_DOT1Pf, fa->param[0]);
  10383             PolicySet(unit, mem, buf, GP_CHANGE_DOT1Pf, 1);
  10384             PolicySet(unit, mem, buf, GP_NEW_DOT1Pf, fa->param[0]);
  10385         }
  10386         break;
  10387     case bcmFieldActionOuterTpidNew:
  10388         BCM_IF_ERROR_RETURN(_bcm_field_tpid_hw_encode(unit, fa->param[0], &mode));
  10389         PolicySet(unit, mem, buf, PID_REPLACE_OUTER_TPIDf, 1);
  10390         PolicySet(unit, mem, buf, PID_TPID_INDEXf, mode);
  10391         break;
  10392     case bcmFieldActionRpSwitchToCpuCancel:
  10393         PolicySet(unit, mem, buf, RP_COPY_TO_CPUf, 0x3);
  10394         break;
  10395 #endif /* BCM_FIREBOLT2_SUPPORT */
  10396     case bcmFieldActionOuterVlanNew:
  10397 #if defined(BCM_FIREBOLT2_SUPPORT) 
  10398         if (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) {
  10399             PolicySet(unit, mem, buf, CHANGE_VLANf, 2);
  10400             PolicySet(unit, mem, buf, NEW_VLANf, fa->param[0]);
  10401         }
  10402         else if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) {
  10403             PolicySet(unit, mem, buf, PID_REPLACE_OUTER_VIDf, 1);
  10404             PolicySet(unit, mem, buf, PID_NEW_OUTER_VIDf, fa->param[0]);
  10405         } else
  10406 #endif /* BCM_FIREBOLT2_SUPPORT */
  10407         {
  10408             PolicySet(unit, mem, buf, ECMPf, 0);
  10409             PolicySet(unit, mem, buf, L3SW_CHANGE_MACDA_OR_VLANf, 0x1);
  10410             PolicySet(unit, mem, buf, NEXT_HOP_INDEXf, fa->hw_index);
  10411         }
  10412         break;
  10413     default:
  10414         LOG_ERROR(BSL_LS_BCM_FP,
  10415                   (BSL_META_U(unit,
  10416                               "FP(unit %d) Error: Unknown action (%d)\n"),
  10417                    unit, (uint32)fa->action));
  10418         return BCM_E_PARAM;
  10419     }
  10420 
  10421     fa->flags &= ~_FP_ACTION_DIRTY; /* Mark action as installed. */
  10422 
  10423     LOG_DEBUG(BSL_LS_BCM_FP,
  10424               (BSL_META_U(unit,
  10425                           "FP(unit %d) vverb: END _field_fb_action_get()\n"),
  10426                unit));
  10427     return BCM_E_NONE;
  10428 }
  10429 
  10430 /*
  10431  * Function:
  10432  *     _field_fb_action_params_check
  10433  * Purpose:
  10434  *     Check field action parameters.
  10435  * Parameters:
  10436  *     unit     - BCM device number
  10437  *     f_ent    - Field entry structure.
  10438  *     fa       - field action 
  10439  * Returns:
  10440  *     BCM_E_XXX
  10441  */
  10442 STATIC int
  10443 _field_fb_action_params_check(int unit,_field_entry_t *f_ent, 
  10444                              _field_action_t *fa)
  10445 {
  10446     uint32  redir_field = 0; /* Redirection field value.*/
  10447 #if defined(INCLUDE_L3)
  10448     uint32 flags;            /* L3 forwarding flags.    */ 
  10449     int nh_ecmp_id;          /* Next hop/Ecmp group id. */
  10450 #endif /* INCLUDE_L3 */
  10451     soc_mem_t mem;           /* Policy table memory id. */
  10452     soc_mem_t tcam_mem;      /* Tcam memory id.         */
  10453     int rv;                  /* Operation return value. */ 
  10454 
  10455 
  10456     /* Input parameters check. */
  10457     if ((NULL == f_ent) || (fa == NULL)){
  10458         return (BCM_E_PARAM);
  10459     }
  10460 
  10461     rv = _field_fb_tcam_policy_mem_get(unit, f_ent->group->stage_id, 
  10462                                        &tcam_mem, &mem);
  10463     BCM_IF_ERROR_RETURN(rv);
  10464 
  10465     switch (fa->action) {
  10466       case bcmFieldActionCosQNew:
  10467           PolicyCheck(unit, mem, NEWPRIf, fa->param[0]);
  10468           break;
  10469       case bcmFieldActionCosQCpuNew:
  10470           PolicyCheck(unit, mem, NEWPRIf, fa->param[0]);
  10471           break;
  10472       case bcmFieldActionPrioPktAndIntNew:
  10473           PolicyCheck(unit, mem, NEWPRIf, fa->param[0]);
  10474           break;
  10475       case bcmFieldActionPrioPktNew:
  10476           PolicyCheck(unit, mem, NEWPRIf, fa->param[0]);
  10477           break;
  10478       case bcmFieldActionPrioIntNew:
  10479           PolicyCheck(unit, mem, NEWPRIf, fa->param[0]);
  10480           break;
  10481       case bcmFieldActionTosNew:
  10482           PolicyCheck(unit, mem, NEWDSCP_TOSf, fa->param[0]);
  10483           break;
  10484       case bcmFieldActionDscpNew:
  10485 #if defined(BCM_FIREBOLT2_SUPPORT) 
  10486           if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) {
  10487               PolicyCheck(unit, mem, RP_NEW_DSCPf, fa->param[0]);
  10488               PolicyCheck(unit, mem, YP_NEW_DSCPf, fa->param[0]);
  10489               PolicyCheck(unit, mem, GP_NEW_DSCPf, fa->param[0]);
  10490           } else 
  10491 #endif /* BCM_FIREBOLT2_SUPPORT */
  10492           {
  10493               PolicyCheck(unit, mem, NEWDSCP_TOSf, fa->param[0]);
  10494               PolicyCheck(unit, mem, RP_DSCPf, fa->param[0]);
  10495               PolicyCheck(unit, mem, YP_DSCPf, fa->param[0]);
  10496           }
  10497           break;
  10498       case bcmFieldActionCopyToCpu:
  10499       case bcmFieldActionRpCopyToCpu:
  10500       case bcmFieldActionYpCopyToCpu:
  10501       case bcmFieldActionGpCopyToCpu:
  10502           if (fa->param[0]) {
  10503               PolicyCheck(unit, mem, MATCHED_RULEf, fa->param[1]);
  10504           }
  10505           break;
  10506       case bcmFieldActionRedirect:    /* param0 = modid, param1 = port/tgid */
  10507           rv = _bcm_field_action_dest_check(unit, fa);
  10508           BCM_IF_ERROR_RETURN(rv);
  10509 
  10510           if (fa->param[0] > 0x3f || fa->param[1] > 0x3f) {
  10511               return BCM_E_PARAM;
  10512           }
  10513           PolicyCheck(unit, mem, REDIRECTIONf, 
  10514                       (fa->param[0] << 6) | fa->param[1]);
  10515           break;
  10516       case bcmFieldActionRedirectTrunk:    /* param0 = trunk ID */
  10517           if (soc_property_get(unit, spn_TRUNK_EXTEND, 1)) {
  10518               redir_field = ((fa->param[0] & 0x60) << 1) | (fa->param[0] & 0x1f);
  10519           } else {
  10520               redir_field = fa->param[0] & 0x1f;
  10521           }
  10522           redir_field |= 0x20; 
  10523           PolicyCheck(unit, mem, REDIRECTIONf, redir_field);
  10524           break;
  10525       case bcmFieldActionRedirectPbmp:
  10526           PolicyCheck(unit, mem, REDIRECTIONf, fa->param[0]);
  10527           break;
  10528       case bcmFieldActionEgressMask:
  10529           PolicyCheck(unit, mem, REDIRECTIONf, fa->param[0]);
  10530           break;
  10531       case bcmFieldActionMirrorIngress:
  10532       case bcmFieldActionMirrorEgress:
  10533           rv = _bcm_field_action_dest_check(unit, fa);
  10534           BCM_IF_ERROR_RETURN(rv);
  10535           break;
  10536 #ifdef INCLUDE_L3 
  10537       case bcmFieldActionL3ChangeVlan:
  10538       case bcmFieldActionL3ChangeMacDa:
  10539       case bcmFieldActionL3Switch:
  10540           rv = _bcm_field_policy_set_l3_nh_resolve(unit,  fa->param[0],
  10541                                                    &flags, &nh_ecmp_id);
  10542           BCM_IF_ERROR_RETURN(rv);
  10543           if (flags & BCM_L3_MULTIPATH) {
  10544               PolicyCheck(unit, mem, ECMP_PTRf, nh_ecmp_id);
  10545           } else {
  10546               PolicyCheck(unit, mem, NEXT_HOP_INDEXf, nh_ecmp_id);
  10547           }
  10548           break;
  10549 #endif /* INCLUDE_L3 */
  10550       case bcmFieldActionAddClassTag:
  10551           PolicyCheck(unit, mem, CLASSIFICATION_TAGf, fa->param[0]);
  10552           break;
  10553       case bcmFieldActionDropPrecedence:
  10554           PolicyCheck(unit, mem, RP_DROP_PRECEDENCEf, fa->param[0]);
  10555           PolicyCheck(unit, mem, YP_DROP_PRECEDENCEf, fa->param[0]);
  10556           PolicyCheck(unit, mem, DROP_PRECEDENCEf, fa->param[0]);
  10557           break;
  10558       case bcmFieldActionGpDropPrecedence:
  10559           PolicyCheck(unit, mem, DROP_PRECEDENCEf, fa->param[0]);
  10560           break;
  10561       case bcmFieldActionRpDropPrecedence:
  10562           PolicyCheck(unit, mem, RP_DROP_PRECEDENCEf, fa->param[0]);
  10563           break;
  10564       case bcmFieldActionRpDscpNew:
  10565 #if defined(BCM_FIREBOLT2_SUPPORT) 
  10566           if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) {
  10567               PolicyCheck(unit, mem, RP_NEW_DSCPf, fa->param[0]);
  10568           } else 
  10569 #endif /* BCM_FIREBOLT2_SUPPORT */
  10570           {
  10571               PolicyCheck(unit, mem, RP_DSCPf, fa->param[0]);
  10572           }
  10573           break;
  10574       case bcmFieldActionYpDropPrecedence:
  10575           PolicyCheck(unit, mem, YP_DROP_PRECEDENCEf, fa->param[0]);
  10576           break;
  10577       case bcmFieldActionYpDscpNew:
  10578 #if defined(BCM_FIREBOLT2_SUPPORT) 
  10579           if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) {
  10580               PolicyCheck(unit, mem, YP_NEW_DSCPf, fa->param[0]);
  10581           } else 
  10582 #endif /* BCM_FIREBOLT2_SUPPORT */
  10583           {
  10584               PolicyCheck(unit, mem, YP_DSCPf, fa->param[0]);
  10585           }
  10586           break;
  10587 #if defined(BCM_FIREBOLT2_SUPPORT) 
  10588       case bcmFieldActionRpOuterVlanPrioNew:
  10589           PolicyCheck(unit, mem, RP_NEW_DOT1Pf, fa->param[0]);
  10590           break;
  10591       case bcmFieldActionYpOuterVlanPrioNew:
  10592           PolicyCheck(unit, mem, YP_NEW_DOT1Pf, fa->param[0]);
  10593           break;
  10594       case bcmFieldActionGpOuterVlanPrioNew:
  10595           PolicyCheck(unit, mem, GP_NEW_DOT1Pf, fa->param[0]);
  10596           break;
  10597       case bcmFieldActionClassSet:
  10598           PolicyCheck(unit, mem, VFP_CLASS_IDf, fa->param[0]); 
  10599           break;
  10600       case bcmFieldActionVrfSet:
  10601           if (fa->param[0] > SOC_VRF_MAX(unit)) {
  10602               return BCM_E_PARAM;
  10603           }
  10604           PolicyCheck(unit, mem, VFP_VRF_IDf, fa->param[0]);
  10605           break;
  10606       case bcmFieldActionVlanAdd:
  10607           PolicyCheck(unit, mem, NEW_VLANf, fa->param[0]);
  10608           break;
  10609       case bcmFieldActionGpDscpNew:
  10610 #if defined(BCM_FIREBOLT2_SUPPORT) 
  10611           if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) {
  10612               PolicyCheck(unit, mem, GP_NEW_DSCPf, fa->param[0]);
  10613           } else 
  10614 #endif /* BCM_FIREBOLT2_SUPPORT */
  10615           {
  10616               PolicyCheck(unit, mem, NEWDSCP_TOSf, fa->param[0]);
  10617           }
  10618           break;
  10619       case bcmFieldActionInnerVlanNew:
  10620           PolicyCheck(unit, mem, PID_NEW_INNER_VIDf, fa->param[0]);
  10621           break;
  10622       case bcmFieldActionInnerVlanPrioNew:
  10623           PolicyCheck(unit, mem, PID_NEW_INNER_PRIf, fa->param[0]);
  10624           break;
  10625       case bcmFieldActionOuterVlanPrioNew:
  10626           if (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) {
  10627               PolicyCheck(unit, mem, NEW_PRIORITYf, fa->param[0]);
  10628           } else if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) { 
  10629               PolicyCheck(unit, mem, RP_NEW_DOT1Pf, fa->param[0]);
  10630               PolicyCheck(unit, mem, YP_NEW_DOT1Pf, fa->param[0]);
  10631               PolicyCheck(unit, mem, GP_NEW_DOT1Pf, fa->param[0]);
  10632           }
  10633           break;
  10634       case bcmFieldActionOuterVlanNew:
  10635           if (_BCM_FIELD_STAGE_LOOKUP== f_ent->group->stage_id) {
  10636               PolicyCheck(unit, mem, NEW_VLANf, fa->param[0]);
  10637           }
  10638           else if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) {
  10639               PolicyCheck(unit, mem, PID_NEW_OUTER_VIDf, fa->param[0]);
  10640           }
  10641           break;
  10642 #endif /* BCM_FIREBOLT2_SUPPORT */
  10643       default:
  10644           return BCM_E_NONE;
  10645     }
  10646     return BCM_E_NONE;
  10647 }
  10648 
  10649 #define BCM_FB_BITS_IN_4_KBYTES   (1 << 15) /* (4 * 1024 * 8) 4K bytes */
  10650 /*
  10651  * Function: 
  10652  *     _field_fb_bucket_calc
  10653  * Purpose:
  10654  *     Lookup the proper meter bucket size encoding.
  10655  */
  10656 
  10657 STATIC int 
  10658 _field_fb_bucket_calc(int unit, uint32 burst, 
  10659                       uint32 *bucket_size, uint32 *bucket_count)
  10660 {
  10661     uint32 b_size;
  10662 
  10663     /* Input  parameters check. */  
  10664     if ((NULL == bucket_size) || (NULL == bucket_count)) {
  10665         return (BCM_E_PARAM);
  10666     }
  10667 
  10668     /* If requested rate is 0 -> set size & count to 0 */
  10669     if (0 == burst) {
  10670         *bucket_size = *bucket_count = 0;
  10671         return (BCM_E_NONE);
  10672     }
  10673 
  10674 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  10675     if (SOC_IS_FIREBOLT2(unit) || SOC_IS_SC_CQ(unit))
  10676     {
  10677         int linear_mode = TRUE;
  10678         uint32 max_bucket_size;
  10679 
  10680         /* Bucket size is in 4 KBytes granularity */
  10681         b_size = _bcm_fb2_kbits_to_bucket_encoding(burst, linear_mode);
  10682 
  10683         /* Verify that value fits into hw field. */
  10684         max_bucket_size =  
  10685             (1 << soc_mem_field_length(unit, FP_METER_TABLEm, BUCKETSIZEf)) - 1;
  10686         if (b_size > max_bucket_size) {
  10687             return (BCM_E_PARAM);
  10688         }
  10689 
  10690         *bucket_size = b_size;
  10691         /* Bucket count is in 1/2 bit granularity and bucket size is
  10692          * in 4 KByte granularity.
  10693          */ 
  10694         *bucket_count = 2 * b_size * BCM_FB_BITS_IN_4_KBYTES;
  10695     } else
  10696 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  10697     {
  10698         uint8               b_code;
  10699        
  10700         /* Bucket size is encoded as follow 
  10701          *            Bucket Size
  10702          * 4'd0     : 4 K - 1
  10703          * 4'd1     : 8 K - 1
  10704          * 4'd2     : 16 K - 1
  10705          * 4'd3     : 32 K - 1
  10706          * 4'd4     : 64 K - 1
  10707          * 4'd5     : 128 K - 1
  10708          * 4'd6     : 256 K - 1
  10709          * 4'd7     : 512 K - 1
  10710          * 4'd8     : 1 M - 1
  10711          * 4'd9     : 2 M - 1
  10712          * 4'd10    : 4 M - 1
  10713          * 4'd11    : 8 M - 1
  10714          * 4'd12    : 16 M - 1
  10715          */
  10716 #define BCM_FB_BUCKET_SIZE_MAX (12)
  10717         b_size = BCM_FB_BITS_IN_4_KBYTES;
  10718         burst = burst * 1000; /* Convert KBits to bits */
  10719         for (b_code = 0; b_code <= BCM_FB_BUCKET_SIZE_MAX; b_code++) {
  10720             if (burst < b_size) {
  10721                 break;
  10722             }
  10723             b_size *= 2;
  10724         }
  10725         *bucket_size  = b_code;
  10726         if (*bucket_size >  BCM_FB_BUCKET_SIZE_MAX) {
  10727             return (BCM_E_PARAM);
  10728         }
  10729 #undef BCM_FB_BUCKET_SIZE_MAX 
  10730 
  10731         /* Bucket count is in 1/2 of a bit granularity */
  10732         *bucket_count = 2 * b_size;
  10733     }
  10734     LOG_DEBUG(BSL_LS_BCM_FP,
  10735               (BSL_META_U(unit,
  10736                           "FP(unit %d) vverb: _field_fb_bucket_calc  rate=%d, bucket_count=%d, "
  10737                            "bucket_size=%d\n"), unit, burst, *bucket_count, *bucket_size));
  10738     return (BCM_E_NONE);
  10739 }
  10740 #undef BCM_FB_BITS_IN_4_KBYTES
  10741 
  10742 int
  10743 _field_fb_policer_mem_get(int unit, _field_entry_t *f_ent,
  10744                           soc_mem_t *mem)
  10745 {
  10746     _field_group_t  *fg;              /* Field group structure. */
  10747     soc_mem_t meter_table = INVALIDm; /* Hw meter table.        */
  10748 
  10749     /* Input parameters check. */
  10750     if ((NULL == f_ent) || (NULL == mem)) {
  10751         return (BCM_E_PARAM);
  10752     }
  10753 
  10754     fg = f_ent->group;
  10755     if (NULL == fg) {
  10756         return (BCM_E_INTERNAL);
  10757     }
  10758 
  10759     if (_BCM_FIELD_STAGE_INGRESS == fg->stage_id) {
  10760 #ifdef BCM_HB_GW_SUPPORT
  10761         if (SOC_IS_HB_GW(unit)) {
  10762             meter_table = FP_METER_TABLE_Xm; 
  10763         } else
  10764 #endif /* BCM_BRADLEY_SUPPORT */
  10765         { 
  10766             meter_table = FP_METER_TABLEm;
  10767         }
  10768 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  10769     } if (soc_feature(unit, soc_feature_field_multi_stage)) {
  10770         if (_BCM_FIELD_STAGE_EGRESS == fg->stage_id) {
  10771             meter_table = EFP_METER_TABLEm;
  10772         }
  10773 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  10774     }
  10775     if (INVALIDm == meter_table) {
  10776         return (BCM_E_INTERNAL);
  10777     } 
  10778     *mem = meter_table;
  10779     return (BCM_E_NONE);
  10780 }
  10781 
  10782 STATIC int
  10783 _field_fb_policer_hw_update(int unit, _field_entry_t  *f_ent,
  10784                             _field_policer_t *f_pl, uint8 index_mtr,
  10785                             uint32 bucket_size, uint32 bucket_count, 
  10786                             uint32 refresh_count)
  10787 {
  10788     _field_stage_t    *stage_fc;    /* Stage field control.       */
  10789     int               meter_offset; /* HW buffer for meter entry. */
  10790     uint32            meter_entry[SOC_MAX_MEM_FIELD_WORDS];
  10791     int               mem_field_width;
  10792     soc_mem_t         mem;          /* Meter table memory.        */
  10793     int               meter_hw_idx; /* Meter memory entry index.  */
  10794 
  10795     if ((NULL == f_pl) || (NULL == f_ent)) {
  10796         return (BCM_E_PARAM);
  10797     }
  10798 
  10799     /* Get meter table memory. */
  10800     BCM_IF_ERROR_RETURN(_field_fb_policer_mem_get(unit, f_ent, &mem));
  10801     
  10802     /* Get stage control structure. */
  10803     BCM_IF_ERROR_RETURN
  10804         (_field_stage_control_get(unit, f_ent->group->stage_id, &stage_fc));
  10805 
  10806     mem_field_width = soc_mem_field_length(unit, mem, REFRESHCOUNTf); 
  10807     if (refresh_count > (uint32)((1 << mem_field_width) - 1)) {
  10808         return (BCM_E_PARAM);
  10809     }
  10810  
  10811     meter_offset = (BCM_FIELD_METER_PEAK == index_mtr) ? 0 : 1;
  10812 
  10813     if (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) {
  10814         meter_hw_idx = (2 * f_pl->pool_index *
  10815             stage_fc->meter_pool[_FP_DEF_INST][f_pl->pool_index]->pool_size) +
  10816                         (2 * f_pl->hw_index) + meter_offset;
  10817     } else {
  10818         meter_hw_idx = 
  10819             stage_fc->slices[_FP_DEF_INST][f_pl->pool_index].start_tcam_idx + \
  10820             (2 * f_pl->hw_index) + meter_offset;
  10821     }
  10822 
  10823     if (meter_hw_idx < soc_mem_index_min(unit, mem) ||
  10824         meter_hw_idx > soc_mem_index_max(unit, mem)) {
  10825         return (BCM_E_INTERNAL);
  10826     }
  10827 
  10828     SOC_IF_ERROR_RETURN
  10829         (soc_mem_read(unit, mem, MEM_BLOCK_ANY,
  10830                       meter_hw_idx, &meter_entry));
  10831  
  10832     soc_mem_field32_set(unit, mem, &meter_entry, REFRESHCOUNTf,
  10833                         refresh_count);
  10834     soc_mem_field32_set(unit, mem, &meter_entry, BUCKETSIZEf,
  10835                         bucket_size);
  10836     soc_mem_field32_set(unit, mem, &meter_entry, BUCKETCOUNTf,
  10837                         bucket_count);
  10838 
  10839     /* Refresh mode is only set to 1 for Single Rate. Other modes get 0 */
  10840      
  10841     if (f_pl->cfg.mode  == bcmPolicerModeSrTcm) {
  10842         soc_mem_field32_set(unit, mem, &meter_entry, REFRESH_MODEf, 1);
  10843     } else {
  10844         soc_mem_field32_set(unit, mem, &meter_entry, REFRESH_MODEf, 0);
  10845     }
  10846 
  10847 #if defined(BCM_TRX_SUPPORT) 
  10848     if (((stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) ||
  10849         (stage_fc->stage_id == _BCM_FIELD_STAGE_EXTERNAL)) &&
  10850         (SOC_MEM_FIELD_VALID(unit, mem, METER_GRANf))) {
  10851         soc_mem_field32_set(unit, mem, &meter_entry, METER_GRANf, 3);
  10852     }
  10853 #endif /* BCM_TRX_SUPPORT) */
  10854 
  10855     BCM_IF_ERROR_RETURN
  10856         (soc_mem_write(unit, mem, MEM_BLOCK_ALL,
  10857                        meter_hw_idx, meter_entry));
  10858 
  10859 #ifdef BCM_HB_GW_SUPPORT
  10860     if (SOC_IS_HB_GW(unit)) {
  10861         BCM_IF_ERROR_RETURN
  10862             (soc_mem_write(unit, FP_METER_TABLE_Ym, MEM_BLOCK_ALL,
  10863                            meter_hw_idx, meter_entry));
  10864     }
  10865 #endif /* BCM_BRADLEY_SUPPORT */ 
  10866 
  10867     return (BCM_E_NONE);
  10868 }
  10869 
  10870 /*
  10871  * Function:
  10872  *     _bcm_field_fb_policer_install
  10873  * Purpose:
  10874  *     Install a policer pair into the hardware tables.
  10875  * Parameters:
  10876  *     unit   - (IN) BCM device number
  10877  *     f_ent  - (IN) Field entry structure.
  10878  *     f_pl   - (IN) Field policer descriptor.
  10879  * Returns:
  10880  *     BCM_E_XXX
  10881  */
  10882 int
  10883 _bcm_field_fb_policer_install(int unit, _field_entry_t *f_ent, 
  10884                               _field_policer_t *f_pl)
  10885 {
  10886     uint32                       bucket_size = 0;
  10887     uint32                       refresh_count = 0;
  10888     uint32                       bucket_count = 0;
  10889 
  10890     if ((NULL == f_ent) || (NULL == f_pl)) {
  10891         return (BCM_E_PARAM);
  10892     }
  10893 
  10894     if (NULL == f_ent->group || NULL == f_ent->fs) {
  10895         return (BCM_E_INTERNAL);
  10896     }
  10897 
  10898     if (0 == (f_pl->hw_flags & _FP_POLICER_DIRTY)) {
  10899         return (BCM_E_NONE);
  10900     }
  10901 
  10902     /* lookup bucket size from tables */
  10903     if (f_pl->hw_flags & _FP_POLICER_COMMITTED_DIRTY) {
  10904         BCM_IF_ERROR_RETURN
  10905             (_field_fb_bucket_calc(unit, f_pl->cfg.ckbits_burst,
  10906                                    &bucket_size, &bucket_count));
  10907 
  10908         /* A value of one in the REFRESHCOUNT is 64 kbits/sec */
  10909         refresh_count = f_pl->cfg.ckbits_sec / _FP_POLICER_REFRESH_RATE;
  10910 
  10911         BCM_IF_ERROR_RETURN
  10912             (_field_fb_policer_hw_update(unit, f_ent, f_pl,   
  10913                                          BCM_FIELD_METER_COMMITTED,
  10914                                          bucket_size, bucket_count,
  10915                                          refresh_count));
  10916 
  10917         LOG_DEBUG(BSL_LS_BCM_FP,
  10918                   (BSL_META_U(unit,
  10919                               "FP(unit %d) vverb: commited-> bucket_size=%u, bucket_count=%u, "
  10920                                "refresh_count=%u\n"), unit, bucket_size, bucket_count, 
  10921                    refresh_count)); 
  10922         f_pl->hw_flags &= ~_FP_POLICER_COMMITTED_DIRTY;
  10923     }
  10924 
  10925     if (f_pl->hw_flags & _FP_POLICER_PEAK_DIRTY) {
  10926         if (_FP_POLICER_EXCESS_HW_METER(f_pl)) {
  10927             /*
  10928              * Rates are always set in committed variables, for flow meters.
  10929              */
  10930             f_pl->cfg.pkbits_sec = f_pl->cfg.ckbits_sec;
  10931             f_pl->cfg.pkbits_burst = f_pl->cfg.ckbits_burst;
  10932         }
  10933 
  10934         BCM_IF_ERROR_RETURN
  10935             (_field_fb_bucket_calc(unit, f_pl->cfg.pkbits_burst, 
  10936                                    &bucket_size, &bucket_count));
  10937 
  10938         refresh_count  = f_pl->cfg.pkbits_sec / _FP_POLICER_REFRESH_RATE;
  10939 
  10940         BCM_IF_ERROR_RETURN
  10941             (_field_fb_policer_hw_update(unit, f_ent, f_pl,
  10942                                          BCM_FIELD_METER_PEAK,
  10943                                          bucket_size, bucket_count,
  10944                                          refresh_count));
  10945 
  10946         LOG_DEBUG(BSL_LS_BCM_FP,
  10947                   (BSL_META_U(unit,
  10948                               "FP(unit %d) vverb: commited-> bucket_size=%u, bucket_count=%u, "
  10949                                "refresh_count=%u\n"), unit, bucket_size, bucket_count, 
  10950                    refresh_count)); 
  10951 
  10952         f_pl->hw_flags &= ~_FP_POLICER_PEAK_DIRTY;
  10953 
  10954         if (_FP_POLICER_EXCESS_HW_METER(f_pl)) {
  10955             /*
  10956              * Reset rates in peak meter variables.
  10957              */
  10958             f_pl->cfg.pkbits_sec = 0;
  10959             f_pl->cfg.pkbits_burst = 0;
  10960         }
  10961     }
  10962     return BCM_E_NONE;
  10963 }
  10964 #undef _FP_POLICER_REFRESH_RATE
  10965 
  10966 #if defined(BCM_FIREBOLT2_SUPPORT) 
  10967 /*
  10968  * Function:
  10969  *     _field_fb2_key_match_type_set
  10970  *
  10971  * Purpose:
  10972  *     Set key match type based on entry group.
  10973  *     NOTE: For double wide entries key type must be the same for 
  10974  *           both parts of the entry.   
  10975  * Parameters:
  10976  *     unit   - (IN) BCM device number
  10977  *     f_ent  - (IN) Slice number to enable
  10978  * Returns:
  10979  *     BCM_E_XXX
  10980  */
  10981 STATIC int
  10982 _field_fb2_key_match_type_set(int unit, _field_entry_t *f_ent)
  10983 {
  10984     _field_group_t           *fg;   /* Field group entry belongs to. */
  10985     uint32                   data;  /* Key match type.               */         
  10986     uint32                   mask;  /* Key match type mask.          */         
  10987                                     /* Key match type offset.        */
  10988     _bcm_field_qual_offset_t q_offset; 
  10989     {
  10990        sal_memset(&q_offset, 0, sizeof(q_offset));
  10991        q_offset.field = KEYf;
  10992        q_offset.num_offsets = 1;
  10993        q_offset.offset[0] = 181;
  10994        q_offset.width[0] = 3;    
  10995     }
  10996 
  10997     /* Input parameters check. */ 
  10998     if (NULL == f_ent) {
  10999         return (BCM_E_PARAM);
  11000     } 
  11001     if (NULL == (fg = f_ent->group)) {
  11002         return (BCM_E_PARAM);
  11003     }
  11004  
  11005     if (fg->flags & _FP_GROUP_SPAN_SINGLE_SLICE) {
  11006         switch (fg->sel_codes[0].fpf3) {
  11007           case _BCM_FIELD_EFP_KEY1:
  11008               data = _BCM_FIELD_EFP_KEY1_MATCH_TYPE;
  11009               break;
  11010           case _BCM_FIELD_EFP_KEY2:
  11011               data = _BCM_FIELD_EFP_KEY2_MATCH_TYPE;
  11012               break;
  11013           case _BCM_FIELD_EFP_KEY4:
  11014               data = _BCM_FIELD_EFP_KEY4_MATCH_TYPE;
  11015               break;
  11016           default:
  11017               return (BCM_E_INTERNAL);
  11018         } 
  11019     } else {
  11020         switch (fg->sel_codes[1].fpf3) {
  11021           case _BCM_FIELD_EFP_KEY2:
  11022               data = _BCM_FIELD_EFP_KEY2_KEY3_MATCH_TYPE;
  11023               break;
  11024           case _BCM_FIELD_EFP_KEY4:
  11025               data = _BCM_FIELD_EFP_KEY1_KEY4_MATCH_TYPE;
  11026               break;
  11027           default:
  11028               return (BCM_E_INTERNAL);
  11029         }
  11030     }
  11031    mask = 0x7;
  11032    /*
  11033     * COVERITY 
  11034     * 
  11035     *This flow takes care of the  Out-of-bounds access issue as 
  11036     * the offset that is being passed is defined.
  11037     */ 
  11038     /* coverity[callee_ptr_arith] */
  11039    return _bcm_field_qual_value_set(unit, &q_offset, f_ent, &data, &mask);
  11040 }
  11041 #endif /* BCM_FIREBOLT2_SUPPORT */
  11042 
  11043 /*
  11044  * Function:
  11045  *     _bcm_field_fb_write_slice_map
  11046  *
  11047  * Purpose:
  11048  *     Write the FP_SLICE_MAP
  11049  *
  11050  * Parameters:
  11051  *     unit
  11052  *     stage_fc - pointer to stage control block
  11053  *     fg       - Reference to Field Group Structure.
  11054  *
  11055  * Returns:
  11056  *     nothing
  11057  *     
  11058  * Notes:
  11059  */
  11060 int
  11061 _bcm_field_fb_write_slice_map(int unit, _field_stage_t *stage_fc,
  11062                               _field_group_t *fg)
  11063 {
  11064     int rv = BCM_E_NONE;
  11065 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT)
  11066     int idx;
  11067     fp_slice_map_entry_t map_entry;
  11068     soc_field_t field;
  11069     int vmap_size;
  11070     uint32 value;
  11071 
  11072     /* Calculate virtual map size. */
  11073     rv = _bcm_field_virtual_map_size_get(unit, stage_fc, &vmap_size); 
  11074     BCM_IF_ERROR_RETURN(rv);
  11075 
  11076     rv = READ_FP_SLICE_MAPm(unit, MEM_BLOCK_ANY, 0, &map_entry);
  11077     BCM_IF_ERROR_RETURN(rv);
  11078 
  11079     for (idx = 0; idx < vmap_size; idx++) {
  11080         value = (stage_fc->vmap[_FP_DEF_INST][0][idx]).vmap_key;
  11081         field = virtual_to_physical_map[idx];
  11082         soc_FP_SLICE_MAPm_field32_set(unit, &map_entry, field, value);
  11083 
  11084         value = (stage_fc->vmap[_FP_DEF_INST][0][idx]).virtual_group;
  11085         field = virtual_to_group_map[idx];
  11086         soc_FP_SLICE_MAPm_field32_set(unit, &map_entry, field, value);
  11087     }
  11088 
  11089     rv = WRITE_FP_SLICE_MAPm(unit, MEM_BLOCK_ALL, 0, &map_entry);
  11090 #endif /* BCM_RAPTOR_SUPPORT || BCM_FIREBOLT2_SUPPORT */
  11091     return (rv);
  11092 }
  11093 
  11094 /*
  11095  * Function:
  11096  *     _field_fb_qualify_ip_type
  11097  * Purpose:
  11098  *     Install ip type qualifier into TCAM
  11099  * Parameters:
  11100  *     unit  - (IN) BCM device number
  11101  *     entry - (IN) Field entry index
  11102  *     type  - (IN) Ip Type. 
  11103  *     qual  - (IN) Qualifier(IpType)
  11104  * Returns:
  11105  *     BCM_E_XXX
  11106  * Notes:
  11107  */
  11108 #define BCM_FIELD_IPTYPE_BAD 0xff
  11109 STATIC int
  11110 _field_fb_qualify_ip_type(int unit, bcm_field_entry_t entry, 
  11111                               bcm_field_IpType_t type, 
  11112                               bcm_field_qualify_t qual) 
  11113 {
  11114     _field_group_t      *fg;
  11115     _field_entry_t      *f_ent;
  11116     uint32              data = BCM_FIELD_IPTYPE_BAD,
  11117                         mask = BCM_FIELD_IPTYPE_BAD;
  11118 
  11119     BCM_IF_ERROR_RETURN
  11120          (_field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent));
  11121 
  11122     fg = f_ent->group;
  11123     if (NULL == fg) {
  11124         return (BCM_E_INTERNAL);
  11125     }
  11126 
  11127     /*
  11128      * Devices with a separate PacketFormat and IpType use different hardware
  11129      * encodings for IpType. 
  11130      */
  11131     if (soc_feature(unit, soc_feature_field_qual_IpType)) {
  11132         if (fg->stage_id == _BCM_FIELD_STAGE_INGRESS) {
  11133             switch (type) {
  11134               case bcmFieldIpTypeAny:
  11135                   data = 0x0;
  11136                   mask = 0x0;
  11137                   break;
  11138               case bcmFieldIpTypeNonIp:
  11139                   data = 0x0;
  11140                   mask = 0x3;
  11141                   break;
  11142               case bcmFieldIpTypeIpv4Not:
  11143                   data = 0x0;
  11144                   mask = 0x1;
  11145                   break;
  11146               case bcmFieldIpTypeIpv4NoOpts:
  11147                   data = 0x1;
  11148                   mask = 0x3;
  11149                   break;
  11150               case bcmFieldIpTypeIpv4WithOpts:
  11151                   data = 0x3;
  11152                   mask = 0x3;
  11153                   break;
  11154               case bcmFieldIpTypeIpv4Any:
  11155                   data = 0x1;
  11156                   mask = 0x1;
  11157                   break;
  11158               case bcmFieldIpTypeIpv6:
  11159                   data = 0x2;
  11160                   mask = 0x3;
  11161                   break;
  11162               default:
  11163                   break;
  11164             }
  11165         }
  11166 #ifdef BCM_FIREBOLT2_SUPPORT 
  11167         else if (fg->stage_id == _BCM_FIELD_STAGE_LOOKUP) {
  11168             switch (type) {
  11169               case bcmFieldIpTypeNonIp:
  11170                   data = 0x2;
  11171                   mask = 0x2;
  11172                   break; 
  11173               case bcmFieldIpTypeIpv4Any:
  11174                   data = 0x0;
  11175                   mask = 0x3;
  11176                   break;
  11177               case bcmFieldIpTypeIpv6:
  11178                   data = 0x1;
  11179                   mask = 0x3;
  11180                   break;
  11181               case bcmFieldIpTypeIp:
  11182                   data = 0x0;
  11183                   mask = 0x2;
  11184                   break;
  11185               case bcmFieldIpTypeArp:
  11186                   data = 0x2;
  11187                   mask = 0x3;
  11188                   break; 
  11189               default:
  11190                   break;
  11191             }
  11192         } else if (fg->stage_id == _BCM_FIELD_STAGE_EGRESS) {
  11193             switch (type) {
  11194               case bcmFieldIpTypeIpv4WithOpts:
  11195                   data = 0x1;
  11196                   mask = 0x1;
  11197                   break; 
  11198               case bcmFieldIpTypeIpv4NoOpts:
  11199                   data = 0x0;
  11200                   mask = 0x1;
  11201                   break;
  11202               case bcmFieldIpTypeIpv4Any:
  11203                   if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyIp4)) {
  11204                       return (BCM_E_NONE);
  11205                   } 
  11206                   return (BCM_E_UNAVAIL);
  11207               case bcmFieldIpTypeIpv6:
  11208                   if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyIp6)) {
  11209                       return (BCM_E_NONE);
  11210                   } 
  11211                   return (BCM_E_UNAVAIL);
  11212               default:
  11213                   return (BCM_E_UNAVAIL);
  11214             }
  11215         }
  11216 #endif /* BCM_FIREBOLT2_SUPPORT */ 
  11217     } else { /* Devices without separate IpType field. */
  11218         switch (type) {
  11219           case bcmFieldIpTypeAny:
  11220               data = 0x0;
  11221               mask = 0x0;
  11222               break;
  11223           case bcmFieldIpTypeNonIp:
  11224               data = 0x0;
  11225               mask = 0x3;
  11226               break;
  11227           case bcmFieldIpTypeIpv4Not:
  11228               data = 0x0;
  11229               mask = 0x1;
  11230               break;
  11231           case bcmFieldIpTypeIpv4Any:
  11232               data = 0x1;
  11233               mask = 0x3;
  11234               break;
  11235           case bcmFieldIpTypeIpv6:
  11236               data = 0x2;
  11237               mask = 0x3;
  11238               break;
  11239           case bcmFieldIpTypeIpv6Not:
  11240               data = 0x0;
  11241               mask = 0x2;
  11242               break;
  11243           default:
  11244               break;
  11245         }
  11246     }
  11247 
  11248     LOG_DEBUG(BSL_LS_BCM_FP,
  11249               (BSL_META_U(unit,
  11250                           "FP(unit %d) vverb: entry=%d qualifying on Iptype, data=%#x, mask=%#x\n"),
  11251                unit, f_ent->eid, data, mask));
  11252 
  11253     if ((data == BCM_FIELD_IPTYPE_BAD) ||
  11254         (mask == BCM_FIELD_IPTYPE_BAD)) {
  11255         return (BCM_E_UNAVAIL);
  11256     }
  11257     return _field_qualify32(unit, f_ent->eid, qual,
  11258                             data, mask);
  11259 }
  11260 #undef BCM_FIELD_IPTYPE_BAD
  11261 
  11262 /*
  11263  * Function:
  11264  *     _field_fb_qualify_ip_type_get
  11265  * Purpose:
  11266  *     Read ip type qualifier match criteria from the HW.
  11267  * Parameters:
  11268  *     unit  - (IN) BCM device number
  11269  *     entry - (IN) Field entry index
  11270  *     type  - (OUT) Ip Type. 
  11271  *     qual  - (IN) Qualifier(IpType)
  11272  * Returns:
  11273  *     BCM_E_XXX
  11274  * Notes:
  11275  */
  11276 STATIC int
  11277 _field_fb_qualify_ip_type_get(int unit, bcm_field_entry_t entry, 
  11278                               bcm_field_IpType_t *type,
  11279                               bcm_field_qualify_t qual) 
  11280 {
  11281     _field_group_t *fg;      /* Field group structure.      */
  11282     _field_entry_t *f_ent;   /* Field Entry structure.      */
  11283     uint32 hw_data;          /* HW encoded qualifier data.  */
  11284     uint32 hw_mask;          /* HW encoding qualifier mask. */
  11285     int rv;                  /* Operation return status.    */
  11286 
  11287     /* Input parameters checks. */
  11288     if (NULL == type) {
  11289         return (BCM_E_PARAM);
  11290     }
  11291 
  11292     BCM_IF_ERROR_RETURN
  11293          (_field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent));
  11294 
  11295     fg = f_ent->group;
  11296     if (NULL == fg) {
  11297         return (BCM_E_INTERNAL);
  11298     }
  11299 
  11300     /* Read qualifier match value and mask. */
  11301     rv = _bcm_field_entry_qualifier_uint32_get(unit, f_ent->eid,
  11302                                                qual,
  11303                                                &hw_data, &hw_mask);
  11304     BCM_IF_ERROR_RETURN(rv);
  11305 
  11306     /* Read IpType encoding for qualifier data and mask */
  11307     rv = _bcm_field_fb_qualify_ip_type_encode_get(unit, fg, hw_data,
  11308                                                   hw_mask, type);
  11309 
  11310     return rv;
  11311 }
  11312 /*
  11313  * Function:
  11314  *     _bcm_field_fb_qualify_ip_type_encode_get
  11315  * Purpose:
  11316  *     Get ip type qualifier encode value for given data and mask.
  11317  * Parameters:
  11318  *     unit     - (IN) BCM device number
  11319  *     fg       - (IN) Field group
  11320  *     data     - (IN) qualifier data.
  11321  *     mask     - (IN) qualifier mask.
  11322  *     type     - (OUT) Ip Type.
  11323  * Returns:
  11324  *     BCM_E_XXX
  11325  * Notes:
  11326  */
  11327 
  11328 int
  11329 _bcm_field_fb_qualify_ip_type_encode_get(int unit, _field_group_t *fg,
  11330                                          uint32 hw_data, uint32 hw_mask,
  11331                                          bcm_field_IpType_t *type)
  11332 {
  11333     /*
  11334      * Devices with a separate PacketFormat and IpType use different hardware
  11335      * encodings for IpType.
  11336      */
  11337     if (soc_feature(unit, soc_feature_field_qual_IpType)) {
  11338         if (fg->stage_id == _BCM_FIELD_STAGE_INGRESS) {
  11339             if ((hw_data == 0) && (hw_mask == 0)) {
  11340                 *type = bcmFieldIpTypeAny;
  11341             } else if ((hw_data == 0) && (hw_mask == 3)) {
  11342                 *type = bcmFieldIpTypeNonIp;
  11343             } else if ((hw_data == 0) && (hw_mask == 1)) {
  11344                 *type = bcmFieldIpTypeIpv4Not;
  11345             } else if ((hw_data == 1) && (hw_mask == 3)) {
  11346                 *type = bcmFieldIpTypeIpv4NoOpts;
  11347             } else if ((hw_data == 3) && (hw_mask == 3)) {
  11348                 *type = bcmFieldIpTypeIpv4WithOpts;
  11349             } else if ((hw_data == 1) && (hw_mask == 1)) {
  11350                 *type = bcmFieldIpTypeIpv4Any;
  11351             } else if ((hw_data == 2) && (hw_mask == 3)) {
  11352                 *type = bcmFieldIpTypeIpv6;
  11353             } else {
  11354                 return (BCM_E_INTERNAL);
  11355             }
  11356         }
  11357 #ifdef BCM_FIREBOLT2_SUPPORT
  11358         else if (fg->stage_id == _BCM_FIELD_STAGE_LOOKUP) {
  11359             if ((hw_data == 2) && (hw_mask == 2)) {
  11360                 *type = bcmFieldIpTypeNonIp;
  11361             } else if ((hw_data == 0) && (hw_mask == 3)) {
  11362                 *type = bcmFieldIpTypeIpv4Any;
  11363             } else if ((hw_data == 1) && (hw_mask == 3)) {
  11364                 *type = bcmFieldIpTypeIpv6;
  11365             } else if ((hw_data == 0) && (hw_mask == 2)) {
  11366                 *type = bcmFieldIpTypeIp;
  11367             } else if ((hw_data == 2) && (hw_mask == 3)) {
  11368                 *type = bcmFieldIpTypeArp;
  11369             } else {
  11370                 return (BCM_E_INTERNAL);
  11371             }
  11372         } else if (fg->stage_id == _BCM_FIELD_STAGE_EGRESS) {
  11373             if ((hw_data == 1) && (hw_mask == 1)) {
  11374                 *type = bcmFieldIpTypeIpv4WithOpts;
  11375             } else if ((hw_data == 0) && (hw_mask == 1)) {
  11376                 *type = bcmFieldIpTypeIpv4NoOpts;
  11377             } else if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyIp4)) {
  11378                 *type = bcmFieldIpTypeIpv4Any;
  11379             } else if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyIp6)) {
  11380                 *type = bcmFieldIpTypeIpv6;
  11381             } else {
  11382                 return (BCM_E_INTERNAL);
  11383             }
  11384         }
  11385 #endif /* BCM_FIREBOLT2_SUPPORT */
  11386     } else { /* Devices without separate IpType field. */
  11387         if ((hw_data == 0) && (hw_mask == 0)) {
  11388             *type = bcmFieldIpTypeAny;
  11389         } else if ((hw_data == 0) && (hw_mask == 3)) {
  11390             *type = bcmFieldIpTypeNonIp;
  11391         } else if ((hw_data == 0) && (hw_mask == 1)) {
  11392             *type = bcmFieldIpTypeIpv4Not;
  11393         } else if ((hw_data == 1) && (hw_mask == 3)) {
  11394             *type = bcmFieldIpTypeIpv4Any;
  11395         } else if ((hw_data == 2) && (hw_mask == 3)) {
  11396             *type = bcmFieldIpTypeIpv6;
  11397         } else if ((hw_data == 0) && (hw_mask == 2)) {
  11398             *type = bcmFieldIpTypeIpv6Not;
  11399         } else {
  11400             return (BCM_E_INTERNAL);
  11401         }
  11402     }
  11403     return (BCM_E_NONE);
  11404  }
  11405 
  11406 /*
  11407  * Function:
  11408  *     _field_fb_action_conflict_check
  11409  *
  11410  * Purpose:
  11411  *     Check if two action conflict (occupy the same field in FP policy table)
  11412  *
  11413  * Parameters:
  11414  *     unit    -(IN)BCM device number
  11415  *     f_ent   -(IN)Field entry structure.  
  11416  *     action -(IN) Action to check(bcmFieldActionXXX)
  11417  *     action1 -(IN) Action to check(bcmFieldActionXXX)
  11418  *
  11419  * Returns:
  11420  *     BCM_E_CONFIG - if actions do conflict
  11421  *     BCM_E_NONE   - if there is no conflict
  11422  */
  11423 STATIC int
  11424 _field_fb_action_conflict_check(int unit, _field_entry_t *f_ent,
  11425                                bcm_field_action_t action1, 
  11426                                bcm_field_action_t action)
  11427 {
  11428     /* Input parameters check */
  11429     if (NULL == f_ent) {
  11430         return (BCM_E_PARAM);
  11431     }
  11432     if (NULL == f_ent->group) {
  11433         return (BCM_E_PARAM);
  11434     }
  11435 
  11436     /* Two identical actions are forbidden. */
  11437     _FP_ACTIONS_CONFLICT(action1);
  11438 
  11439 #ifdef BCM_FIREBOLT2_SUPPORT 
  11440     if (SOC_IS_FIREBOLT2(unit)) {
  11441         if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) {
  11442             switch (action1) {
  11443               case bcmFieldActionDrop:
  11444                   _FP_ACTIONS_CONFLICT(bcmFieldActionDropCancel);
  11445                   _FP_ACTIONS_CONFLICT(bcmFieldActionRpDropCancel);
  11446                   _FP_ACTIONS_CONFLICT(bcmFieldActionYpDropCancel);
  11447                   _FP_ACTIONS_CONFLICT(bcmFieldActionGpDropCancel);
  11448                   break;
  11449               case bcmFieldActionDropCancel:
  11450                   _FP_ACTIONS_CONFLICT(bcmFieldActionDrop);
  11451                   _FP_ACTIONS_CONFLICT(bcmFieldActionRpDrop);
  11452                   _FP_ACTIONS_CONFLICT(bcmFieldActionYpDrop);
  11453                   _FP_ACTIONS_CONFLICT(bcmFieldActionGpDrop);
  11454                   break;
  11455               case bcmFieldActionRpDrop:
  11456                   _FP_ACTIONS_CONFLICT(bcmFieldActionDropCancel);
  11457                   _FP_ACTIONS_CONFLICT(bcmFieldActionRpDropCancel);
  11458                   break;
  11459               case bcmFieldActionRpDropCancel:
  11460                   _FP_ACTIONS_CONFLICT(bcmFieldActionDrop);
  11461                   _FP_ACTIONS_CONFLICT(bcmFieldActionRpDrop);
  11462                   break;
  11463               case bcmFieldActionYpDrop:
  11464                   _FP_ACTIONS_CONFLICT(bcmFieldActionDropCancel);
  11465                   _FP_ACTIONS_CONFLICT(bcmFieldActionYpDropCancel);
  11466                   break;
  11467               case bcmFieldActionYpDropCancel:
  11468                   _FP_ACTIONS_CONFLICT(bcmFieldActionDrop);
  11469                   _FP_ACTIONS_CONFLICT(bcmFieldActionYpDrop);
  11470                   break;
  11471               case bcmFieldActionGpDrop:
  11472                   _FP_ACTIONS_CONFLICT(bcmFieldActionDropCancel);
  11473                   _FP_ACTIONS_CONFLICT(bcmFieldActionGpDropCancel);
  11474                   break;
  11475               case bcmFieldActionGpDropCancel:
  11476                   _FP_ACTIONS_CONFLICT(bcmFieldActionDrop);
  11477                   _FP_ACTIONS_CONFLICT(bcmFieldActionGpDrop);
  11478                   break;
  11479               case bcmFieldActionDscpNew:
  11480                   _FP_ACTIONS_CONFLICT(bcmFieldActionRpDscpNew);
  11481                   _FP_ACTIONS_CONFLICT(bcmFieldActionYpDscpNew);
  11482                   _FP_ACTIONS_CONFLICT(bcmFieldActionGpDscpNew);
  11483                   break;
  11484               case bcmFieldActionRpDscpNew:
  11485               case bcmFieldActionYpDscpNew:
  11486               case bcmFieldActionGpDscpNew:
  11487                   _FP_ACTIONS_CONFLICT(bcmFieldActionDscpNew);
  11488                   break;
  11489               case bcmFieldActionRpOuterVlanPrioNew:
  11490               case bcmFieldActionYpOuterVlanPrioNew:
  11491               case bcmFieldActionGpOuterVlanPrioNew:
  11492                   _FP_ACTIONS_CONFLICT(bcmFieldActionOuterVlanPrioNew);
  11493                   break;
  11494               case bcmFieldActionOuterVlanPrioNew:
  11495                   _FP_ACTIONS_CONFLICT(bcmFieldActionRpOuterVlanPrioNew);
  11496                   _FP_ACTIONS_CONFLICT(bcmFieldActionYpOuterVlanPrioNew);
  11497                   _FP_ACTIONS_CONFLICT(bcmFieldActionGpOuterVlanPrioNew);
  11498                   break;
  11499               case bcmFieldActionInnerVlanPrioNew:
  11500               case bcmFieldActionInnerVlanNew:
  11501               case bcmFieldActionOuterVlanNew:
  11502               case bcmFieldActionOuterTpidNew:
  11503                   break;
  11504               default:
  11505                   break;
  11506             }
  11507             return (BCM_E_NONE);
  11508         }
  11509         if (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) {
  11510             switch (action1) {
  11511               case bcmFieldActionDrop:
  11512                   _FP_ACTIONS_CONFLICT(bcmFieldActionDropCancel);
  11513                   break;
  11514               case bcmFieldActionDropCancel:
  11515                   _FP_ACTIONS_CONFLICT(bcmFieldActionDrop);
  11516                   break;
  11517               case bcmFieldActionOuterVlanNew:
  11518               case bcmFieldActionVlanAdd:
  11519               case bcmFieldActionOuterVlanPrioNew:
  11520               case bcmFieldActionCopyToCpu:
  11521               case bcmFieldActionVrfSet:
  11522               case bcmFieldActionClassSet:
  11523                   break;
  11524               default:
  11525                   break;
  11526             }
  11527             return (BCM_E_NONE);
  11528         }
  11529     }
  11530 #endif /* BCM_FIREBOLT2_SUPPORT */
  11531 
  11532     switch (action1) {
  11533       case bcmFieldActionCosQNew:
  11534       case bcmFieldActionCosQCpuNew:
  11535       case bcmFieldActionPrioPktAndIntCopy:
  11536       case bcmFieldActionPrioPktAndIntNew:
  11537       case bcmFieldActionPrioPktAndIntTos:
  11538       case bcmFieldActionPrioPktAndIntCancel:
  11539       case bcmFieldActionPrioPktCopy:
  11540       case bcmFieldActionPrioPktNew:
  11541       case bcmFieldActionPrioPktTos:
  11542       case bcmFieldActionPrioPktCancel:
  11543       case bcmFieldActionPrioIntCopy:
  11544       case bcmFieldActionPrioIntNew:
  11545       case bcmFieldActionPrioIntTos:
  11546       case bcmFieldActionPrioIntCancel:
  11547           _FP_ACTIONS_CONFLICT(bcmFieldActionCosQNew);
  11548           _FP_ACTIONS_CONFLICT(bcmFieldActionCosQCpuNew);
  11549           _FP_ACTIONS_CONFLICT(bcmFieldActionPrioPktAndIntCopy);
  11550           _FP_ACTIONS_CONFLICT(bcmFieldActionPrioPktAndIntNew);
  11551           _FP_ACTIONS_CONFLICT(bcmFieldActionPrioPktAndIntTos);
  11552           _FP_ACTIONS_CONFLICT(bcmFieldActionPrioPktAndIntCancel);
  11553           _FP_ACTIONS_CONFLICT(bcmFieldActionPrioPktCopy);
  11554           _FP_ACTIONS_CONFLICT(bcmFieldActionPrioPktNew);
  11555           _FP_ACTIONS_CONFLICT(bcmFieldActionPrioPktTos);
  11556           _FP_ACTIONS_CONFLICT(bcmFieldActionPrioPktCancel);
  11557           _FP_ACTIONS_CONFLICT(bcmFieldActionPrioIntCopy);
  11558           _FP_ACTIONS_CONFLICT(bcmFieldActionPrioIntNew);
  11559           _FP_ACTIONS_CONFLICT(bcmFieldActionPrioIntTos);
  11560           _FP_ACTIONS_CONFLICT(bcmFieldActionPrioIntCancel);
  11561           break;
  11562       case bcmFieldActionTosNew:
  11563       case bcmFieldActionTosCopy:
  11564       case bcmFieldActionTosCancel:
  11565           _FP_ACTIONS_CONFLICT(bcmFieldActionEcnNew);
  11566           _FP_ACTIONS_CONFLICT(bcmFieldActionDscpNew);
  11567           _FP_ACTIONS_CONFLICT(bcmFieldActionDscpCancel);
  11568           _FP_ACTIONS_CONFLICT(bcmFieldActionRpDscpNew);
  11569           _FP_ACTIONS_CONFLICT(bcmFieldActionYpDscpNew);
  11570           _FP_ACTIONS_CONFLICT(bcmFieldActionGpDscpNew);
  11571           break;
  11572       case bcmFieldActionDscpNew:
  11573       case bcmFieldActionDscpCancel:
  11574           _FP_ACTIONS_CONFLICT(bcmFieldActionTosNew);
  11575           _FP_ACTIONS_CONFLICT(bcmFieldActionTosCopy);
  11576           _FP_ACTIONS_CONFLICT(bcmFieldActionTosCancel);
  11577           _FP_ACTIONS_CONFLICT(bcmFieldActionRpDscpNew);
  11578           _FP_ACTIONS_CONFLICT(bcmFieldActionYpDscpNew);
  11579           _FP_ACTIONS_CONFLICT(bcmFieldActionGpDscpNew);
  11580           break;
  11581       case bcmFieldActionRpDscpNew:
  11582           _FP_ACTIONS_CONFLICT(bcmFieldActionRpDscpNew);
  11583           _FP_ACTIONS_CONFLICT(bcmFieldActionRpDscpCancel);
  11584           _FP_ACTIONS_CONFLICT(bcmFieldActionDscpNew);
  11585           _FP_ACTIONS_CONFLICT(bcmFieldActionDscpCancel);
  11586           _FP_ACTIONS_CONFLICT(bcmFieldActionTosNew);
  11587           _FP_ACTIONS_CONFLICT(bcmFieldActionTosCopy);
  11588           _FP_ACTIONS_CONFLICT(bcmFieldActionTosCancel);
  11589           break;
  11590       case bcmFieldActionYpDscpNew:
  11591           _FP_ACTIONS_CONFLICT(bcmFieldActionYpDscpNew);
  11592           _FP_ACTIONS_CONFLICT(bcmFieldActionYpDscpCancel);
  11593           _FP_ACTIONS_CONFLICT(bcmFieldActionDscpNew);
  11594           _FP_ACTIONS_CONFLICT(bcmFieldActionDscpCancel);
  11595           _FP_ACTIONS_CONFLICT(bcmFieldActionTosNew);
  11596           _FP_ACTIONS_CONFLICT(bcmFieldActionTosCopy);
  11597           _FP_ACTIONS_CONFLICT(bcmFieldActionTosCancel);
  11598           break;
  11599       case bcmFieldActionGpDscpNew:
  11600           _FP_ACTIONS_CONFLICT(bcmFieldActionGpDscpNew);
  11601           _FP_ACTIONS_CONFLICT(bcmFieldActionGpDscpCancel);
  11602           _FP_ACTIONS_CONFLICT(bcmFieldActionDscpNew);
  11603           _FP_ACTIONS_CONFLICT(bcmFieldActionDscpCancel);
  11604           _FP_ACTIONS_CONFLICT(bcmFieldActionTosNew);
  11605           _FP_ACTIONS_CONFLICT(bcmFieldActionTosCopy);
  11606           _FP_ACTIONS_CONFLICT(bcmFieldActionTosCancel);
  11607           break;
  11608       case bcmFieldActionEcnNew:
  11609           _FP_ACTIONS_CONFLICT(bcmFieldActionTosNew);
  11610           _FP_ACTIONS_CONFLICT(bcmFieldActionTosCopy);
  11611           _FP_ACTIONS_CONFLICT(bcmFieldActionTosCancel);
  11612           break;
  11613 
  11614       case bcmFieldActionCopyToCpu:
  11615       case bcmFieldActionCopyToCpuCancel:
  11616       case bcmFieldActionSwitchToCpuCancel:
  11617           _FP_ACTIONS_CONFLICT(bcmFieldActionCopyToCpu);
  11618           _FP_ACTIONS_CONFLICT(bcmFieldActionCopyToCpuCancel);
  11619           _FP_ACTIONS_CONFLICT(bcmFieldActionSwitchToCpuCancel);
  11620           _FP_ACTIONS_CONFLICT(bcmFieldActionRpCopyToCpu);
  11621           _FP_ACTIONS_CONFLICT(bcmFieldActionRpCopyToCpuCancel);
  11622           _FP_ACTIONS_CONFLICT(bcmFieldActionYpCopyToCpu);
  11623           _FP_ACTIONS_CONFLICT(bcmFieldActionYpCopyToCpuCancel);
  11624           _FP_ACTIONS_CONFLICT(bcmFieldActionGpCopyToCpu);
  11625           _FP_ACTIONS_CONFLICT(bcmFieldActionGpCopyToCpuCancel);
  11626           _FP_ACTIONS_CONFLICT(bcmFieldActionRpSwitchToCpuCancel);
  11627           break;
  11628       case bcmFieldActionRpCopyToCpu:
  11629       case bcmFieldActionRpCopyToCpuCancel:
  11630       case bcmFieldActionRpSwitchToCpuCancel:  
  11631           _FP_ACTIONS_CONFLICT(bcmFieldActionCopyToCpu);
  11632           _FP_ACTIONS_CONFLICT(bcmFieldActionCopyToCpuCancel);
  11633           _FP_ACTIONS_CONFLICT(bcmFieldActionSwitchToCpuCancel);
  11634           _FP_ACTIONS_CONFLICT(bcmFieldActionRpCopyToCpu);
  11635           _FP_ACTIONS_CONFLICT(bcmFieldActionRpCopyToCpuCancel);
  11636           _FP_ACTIONS_CONFLICT(bcmFieldActionRpSwitchToCpuCancel);
  11637           break;
  11638       case bcmFieldActionYpCopyToCpu:
  11639       case bcmFieldActionYpCopyToCpuCancel:
  11640           _FP_ACTIONS_CONFLICT(bcmFieldActionCopyToCpu);
  11641           _FP_ACTIONS_CONFLICT(bcmFieldActionCopyToCpuCancel);
  11642           _FP_ACTIONS_CONFLICT(bcmFieldActionSwitchToCpuCancel);
  11643           _FP_ACTIONS_CONFLICT(bcmFieldActionYpCopyToCpu);
  11644           _FP_ACTIONS_CONFLICT(bcmFieldActionYpCopyToCpuCancel);
  11645           break;
  11646       case bcmFieldActionGpCopyToCpu:
  11647       case bcmFieldActionGpCopyToCpuCancel:
  11648           _FP_ACTIONS_CONFLICT(bcmFieldActionCopyToCpu);
  11649           _FP_ACTIONS_CONFLICT(bcmFieldActionCopyToCpuCancel);
  11650           _FP_ACTIONS_CONFLICT(bcmFieldActionSwitchToCpuCancel);
  11651           _FP_ACTIONS_CONFLICT(bcmFieldActionGpCopyToCpu);
  11652           _FP_ACTIONS_CONFLICT(bcmFieldActionGpCopyToCpuCancel);
  11653           break;
  11654       case bcmFieldActionDrop:
  11655       case bcmFieldActionDropCancel:
  11656           _FP_ACTIONS_CONFLICT(bcmFieldActionDrop);
  11657           _FP_ACTIONS_CONFLICT(bcmFieldActionDropCancel);
  11658           _FP_ACTIONS_CONFLICT(bcmFieldActionRpDrop);
  11659           _FP_ACTIONS_CONFLICT(bcmFieldActionRpDropCancel);
  11660           _FP_ACTIONS_CONFLICT(bcmFieldActionYpDrop);
  11661           _FP_ACTIONS_CONFLICT(bcmFieldActionYpDropCancel);
  11662           _FP_ACTIONS_CONFLICT(bcmFieldActionGpDrop);
  11663           _FP_ACTIONS_CONFLICT(bcmFieldActionGpDropCancel);
  11664           break;
  11665       case bcmFieldActionRpDrop:
  11666       case bcmFieldActionRpDropCancel:
  11667           _FP_ACTIONS_CONFLICT(bcmFieldActionDrop);
  11668           _FP_ACTIONS_CONFLICT(bcmFieldActionDropCancel);
  11669           _FP_ACTIONS_CONFLICT(bcmFieldActionRpDrop);
  11670           _FP_ACTIONS_CONFLICT(bcmFieldActionRpDropCancel);
  11671           break;
  11672       case bcmFieldActionYpDrop:
  11673       case bcmFieldActionYpDropCancel:
  11674           _FP_ACTIONS_CONFLICT(bcmFieldActionDrop);
  11675           _FP_ACTIONS_CONFLICT(bcmFieldActionDropCancel);
  11676           _FP_ACTIONS_CONFLICT(bcmFieldActionYpDrop);
  11677           _FP_ACTIONS_CONFLICT(bcmFieldActionYpDropCancel);
  11678           break;
  11679       case bcmFieldActionGpDrop:
  11680       case bcmFieldActionGpDropCancel:
  11681           _FP_ACTIONS_CONFLICT(bcmFieldActionDrop);
  11682           _FP_ACTIONS_CONFLICT(bcmFieldActionDropCancel);
  11683           _FP_ACTIONS_CONFLICT(bcmFieldActionGpDrop);
  11684           _FP_ACTIONS_CONFLICT(bcmFieldActionGpDropCancel);
  11685           break;
  11686       case bcmFieldActionRedirect:
  11687       case bcmFieldActionRedirectTrunk:
  11688       case bcmFieldActionRedirectCancel:
  11689       case bcmFieldActionRedirectPbmp:
  11690       case bcmFieldActionEgressMask:
  11691           _FP_ACTIONS_CONFLICT(bcmFieldActionRedirect);
  11692           _FP_ACTIONS_CONFLICT(bcmFieldActionRedirectTrunk);
  11693           _FP_ACTIONS_CONFLICT(bcmFieldActionRedirectCancel);
  11694           _FP_ACTIONS_CONFLICT(bcmFieldActionRedirectPbmp);
  11695           _FP_ACTIONS_CONFLICT(bcmFieldActionEgressMask);
  11696           break;
  11697       case bcmFieldActionMirrorIngress:
  11698           _FP_ACTIONS_CONFLICT(bcmFieldActionMirrorIngress);
  11699           _FP_ACTIONS_CONFLICT(bcmFieldActionMirrorOverride);
  11700           break;
  11701       case bcmFieldActionMirrorEgress:
  11702           _FP_ACTIONS_CONFLICT(bcmFieldActionMirrorOverride);
  11703           _FP_ACTIONS_CONFLICT(bcmFieldActionMirrorEgress);
  11704           break;
  11705       case bcmFieldActionMirrorOverride:
  11706           _FP_ACTIONS_CONFLICT(bcmFieldActionMirrorIngress);
  11707           _FP_ACTIONS_CONFLICT(bcmFieldActionMirrorEgress);
  11708           break;
  11709       case bcmFieldActionL3ChangeVlan:
  11710       case bcmFieldActionL3ChangeVlanCancel:
  11711       case bcmFieldActionL3ChangeMacDa:
  11712       case bcmFieldActionL3ChangeMacDaCancel:
  11713       case bcmFieldActionL3Switch:
  11714       case bcmFieldActionL3SwitchCancel:
  11715       case bcmFieldActionAddClassTag:
  11716           _FP_ACTIONS_CONFLICT(bcmFieldActionAddClassTag);
  11717           _FP_ACTIONS_CONFLICT(bcmFieldActionL3ChangeVlan);
  11718           _FP_ACTIONS_CONFLICT(bcmFieldActionL3ChangeVlanCancel);
  11719           _FP_ACTIONS_CONFLICT(bcmFieldActionL3ChangeMacDa);
  11720           _FP_ACTIONS_CONFLICT(bcmFieldActionL3ChangeMacDaCancel);
  11721           _FP_ACTIONS_CONFLICT(bcmFieldActionL3Switch);
  11722           _FP_ACTIONS_CONFLICT(bcmFieldActionL3SwitchCancel);
  11723           _FP_ACTIONS_CONFLICT(bcmFieldActionSrcMacNew);
  11724           _FP_ACTIONS_CONFLICT(bcmFieldActionDstMacNew);
  11725           _FP_ACTIONS_CONFLICT(bcmFieldActionOuterVlanNew);
  11726           break;
  11727       case bcmFieldActionOuterVlanNew:
  11728       case bcmFieldActionSrcMacNew:
  11729       case bcmFieldActionDstMacNew:
  11730           _FP_ACTIONS_CONFLICT(bcmFieldActionL3ChangeVlan);
  11731           _FP_ACTIONS_CONFLICT(bcmFieldActionL3ChangeVlanCancel);
  11732           _FP_ACTIONS_CONFLICT(bcmFieldActionL3ChangeMacDa);
  11733           _FP_ACTIONS_CONFLICT(bcmFieldActionL3ChangeMacDaCancel);
  11734           _FP_ACTIONS_CONFLICT(bcmFieldActionL3Switch);
  11735           _FP_ACTIONS_CONFLICT(bcmFieldActionL3SwitchCancel);
  11736           break;
  11737       case bcmFieldActionDropPrecedence:
  11738           _FP_ACTIONS_CONFLICT(bcmFieldActionRpDropPrecedence);
  11739           _FP_ACTIONS_CONFLICT(bcmFieldActionYpDropPrecedence);
  11740           _FP_ACTIONS_CONFLICT(bcmFieldActionGpDropPrecedence);
  11741           break;
  11742       case bcmFieldActionRpDropPrecedence:
  11743           _FP_ACTIONS_CONFLICT(bcmFieldActionDropPrecedence);
  11744           _FP_ACTIONS_CONFLICT(bcmFieldActionRpDropPrecedence);
  11745           break;
  11746       case bcmFieldActionYpDropPrecedence:
  11747           _FP_ACTIONS_CONFLICT(bcmFieldActionDropPrecedence);
  11748           _FP_ACTIONS_CONFLICT(bcmFieldActionYpDropPrecedence);
  11749           break;
  11750       case bcmFieldActionGpDropPrecedence:
  11751           _FP_ACTIONS_CONFLICT(bcmFieldActionDropPrecedence);
  11752           _FP_ACTIONS_CONFLICT(bcmFieldActionGpDropPrecedence);
  11753           break;
  11754       case bcmFieldActionColorIndependent:
  11755           break;
  11756       default:
  11757           break;
  11758     }
  11759 
  11760     return (BCM_E_NONE);
  11761 }
  11762 
  11763 
  11764 /*
  11765  * Function:
  11766  *     _field_fb_action_support_check
  11767  *
  11768  * Purpose:
  11769  *     Check if action is supported by device.
  11770  *
  11771  * Parameters:
  11772  *     unit   -(IN)BCM device number
  11773  *     f_ent  -(IN)Field entry structure.  
  11774  *     action -(IN) Action to check(bcmFieldActionXXX)
  11775  *     result -(OUT)
  11776  *               TRUE   - action is supported by device
  11777  *               FALSE  - action is NOT supported by device
  11778  *
  11779  * Returns:
  11780  *     BCM_E_XXX   
  11781  */
  11782 STATIC int
  11783 _field_fb_action_support_check(int unit, _field_entry_t *f_ent,
  11784                                bcm_field_action_t action, int *result)
  11785 {
  11786     /* Input parameters check */
  11787     if ((NULL == f_ent) || (NULL == result)) {
  11788         return (BCM_E_PARAM);
  11789     }
  11790     if (NULL == f_ent->group) {
  11791         return (BCM_E_PARAM);
  11792     }
  11793 
  11794 #ifdef BCM_FIREBOLT2_SUPPORT 
  11795     if (SOC_IS_FIREBOLT2(unit)) {
  11796         if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) {
  11797             switch (action) {
  11798               case bcmFieldActionDrop:
  11799               case bcmFieldActionDropCancel:
  11800               case bcmFieldActionDscpNew:
  11801               case bcmFieldActionRpDrop:
  11802               case bcmFieldActionYpDrop:
  11803               case bcmFieldActionGpDrop:
  11804               case bcmFieldActionRpDropCancel:
  11805               case bcmFieldActionYpDropCancel:
  11806               case bcmFieldActionGpDropCancel:
  11807               case bcmFieldActionRpDscpNew:
  11808               case bcmFieldActionYpDscpNew:
  11809               case bcmFieldActionGpDscpNew:
  11810               case bcmFieldActionRpOuterVlanPrioNew:
  11811               case bcmFieldActionYpOuterVlanPrioNew:
  11812               case bcmFieldActionGpOuterVlanPrioNew:
  11813               case bcmFieldActionInnerVlanPrioNew:
  11814               case bcmFieldActionOuterVlanPrioNew:
  11815               case bcmFieldActionInnerVlanNew:
  11816               case bcmFieldActionOuterVlanNew:
  11817               case bcmFieldActionOuterTpidNew:
  11818                   *result = TRUE;
  11819                   break;
  11820               default:
  11821                   *result = FALSE;
  11822             }
  11823             return (BCM_E_NONE);
  11824         }
  11825         if (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) {
  11826             switch (action) {
  11827               case bcmFieldActionOuterVlanNew:
  11828               case bcmFieldActionVlanAdd:
  11829               case bcmFieldActionOuterVlanPrioNew:
  11830               case bcmFieldActionDrop:
  11831               case bcmFieldActionDropCancel:
  11832               case bcmFieldActionCopyToCpu:
  11833               case bcmFieldActionVrfSet:
  11834               case bcmFieldActionClassSet:
  11835                   *result = TRUE;
  11836                   break;
  11837               default:
  11838                   *result = FALSE;
  11839             }
  11840             return (BCM_E_NONE);
  11841         }
  11842     }
  11843 #endif /* BCM_FIREBOLT2_SUPPORT */
  11844 
  11845     switch (action) {
  11846         case bcmFieldActionCosQNew:
  11847         case bcmFieldActionCosQCpuNew:
  11848         case bcmFieldActionColorIndependent:
  11849             *result = 
  11850                 (soc_feature(unit, soc_feature_field_wide)) ? TRUE : FALSE;
  11851             break;
  11852         case bcmFieldActionMirrorOverride:
  11853             *result = (soc_feature(unit, soc_feature_field_mirror_ovr)) ? \
  11854                                                 TRUE : FALSE;
  11855             break;
  11856         case bcmFieldActionSrcMacNew: 
  11857             *result = FALSE;
  11858             break;
  11859         case bcmFieldActionDstMacNew: 
  11860         case bcmFieldActionOuterVlanNew: 
  11861 #if defined(INCLUDE_L3) /* INCLUDE_L3 */
  11862             *result = (soc_feature(unit, soc_feature_field_action_l2_change) &&
  11863                        soc_feature(unit, soc_feature_l3)) ? \
  11864                             TRUE : FALSE;
  11865 #else 
  11866             *result = FALSE;
  11867 #endif /* !INCLUDE_L3 */
  11868             break;
  11869         case bcmFieldActionPrioPktAndIntCopy:
  11870         case bcmFieldActionPrioPktAndIntNew:
  11871         case bcmFieldActionPrioPktAndIntTos:
  11872         case bcmFieldActionPrioPktAndIntCancel:
  11873         case bcmFieldActionPrioPktCopy:
  11874         case bcmFieldActionPrioPktNew:
  11875         case bcmFieldActionPrioPktTos:
  11876         case bcmFieldActionPrioPktCancel:
  11877         case bcmFieldActionPrioIntCopy:
  11878         case bcmFieldActionPrioIntNew:
  11879         case bcmFieldActionPrioIntTos:
  11880         case bcmFieldActionPrioIntCancel:
  11881         case bcmFieldActionTosNew:
  11882         case bcmFieldActionTosCopy:
  11883         case bcmFieldActionTosCancel:
  11884         case bcmFieldActionDscpNew:
  11885         case bcmFieldActionDscpCancel:
  11886         case bcmFieldActionCopyToCpu:
  11887         case bcmFieldActionCopyToCpuCancel:
  11888         case bcmFieldActionSwitchToCpuCancel:
  11889         case bcmFieldActionRedirect:
  11890         case bcmFieldActionRedirectTrunk:
  11891         case bcmFieldActionRedirectCancel:
  11892         case bcmFieldActionRedirectPbmp:
  11893         case bcmFieldActionEgressMask:
  11894         case bcmFieldActionDrop:
  11895         case bcmFieldActionDropCancel:
  11896         case bcmFieldActionMirrorIngress:
  11897         case bcmFieldActionMirrorEgress:
  11898         case bcmFieldActionL3ChangeVlan:
  11899         case bcmFieldActionL3ChangeVlanCancel:
  11900         case bcmFieldActionL3ChangeMacDa:
  11901         case bcmFieldActionL3ChangeMacDaCancel:
  11902         case bcmFieldActionL3Switch:
  11903         case bcmFieldActionL3SwitchCancel:
  11904         case bcmFieldActionAddClassTag:
  11905         case bcmFieldActionDropPrecedence:
  11906         case bcmFieldActionRpDrop:
  11907         case bcmFieldActionRpDropCancel:
  11908         case bcmFieldActionRpDropPrecedence:
  11909         case bcmFieldActionRpCopyToCpu:
  11910         case bcmFieldActionRpCopyToCpuCancel:
  11911         case bcmFieldActionRpDscpNew:
  11912         case bcmFieldActionYpDrop:
  11913         case bcmFieldActionYpDropCancel:
  11914         case bcmFieldActionYpDropPrecedence:
  11915         case bcmFieldActionYpCopyToCpu:
  11916         case bcmFieldActionYpCopyToCpuCancel:
  11917         case bcmFieldActionYpDscpNew:
  11918         case bcmFieldActionGpDrop:
  11919         case bcmFieldActionGpDropCancel:
  11920         case bcmFieldActionGpDropPrecedence:
  11921         case bcmFieldActionGpCopyToCpu:
  11922         case bcmFieldActionGpCopyToCpuCancel:
  11923         case bcmFieldActionGpDscpNew:
  11924             *result = TRUE;
  11925             break;
  11926 #if defined(BCM_FIREBOLT2_SUPPORT)
  11927         case bcmFieldActionRpSwitchToCpuCancel:
  11928             *result = (SOC_IS_FIREBOLT2(unit)) ? TRUE: FALSE;
  11929             break;
  11930 #endif
  11931         case bcmFieldActionEcnNew:
  11932             *result = (SOC_MEM_FIELD_VALID(unit, FP_POLICY_TABLEm, ECN_CNGf)) ?
  11933                 TRUE : FALSE;
  11934             break;
  11935         default:
  11936             *result = FALSE;
  11937     }
  11938 
  11939     return (BCM_E_NONE);
  11940 }
  11941 
  11942 /*
  11943  * Function: 
  11944  *   _bcm_field_fb_stat_hw_mode_to_bmap 
  11945  *
  11946  * Description:
  11947  *      HW counter mode to statistics bitmap. 
  11948  * Parameters:
  11949  *      unit           - (IN) BCM device number.
  11950  *      mode           - (IN) HW counter mode.
  11951  *      stage_id       - (IN) Stage id.
  11952  *      hw_bmap        - (OUT) Statistics bitmap. 
  11953  *      hw_entry_count - (OUT) Number of counters required.
  11954  * Returns:
  11955  *      BCM_E_XXX
  11956  */
  11957 int 
  11958 _bcm_field_fb_stat_hw_mode_to_bmap(int unit, uint16 mode, 
  11959                                    _field_stage_id_t stage_id, 
  11960                                    uint32 *hw_bmap, uint8 *hw_entry_count)
  11961 {
  11962     uint32 value = 0;
  11963     /* Input parameters check. */
  11964     if ((NULL == hw_bmap) || (NULL == hw_entry_count)) {
  11965         return (BCM_E_PARAM);
  11966     }
  11967 
  11968 #if defined (BCM_FIREBOLT2_SUPPORT)
  11969     if (_BCM_FIELD_STAGE_EGRESS == stage_id) {
  11970         if (1 == mode) {
  11971             value |= (1 << (int)bcmFieldStatPackets);
  11972             *hw_entry_count = 1;
  11973         }
  11974         *hw_bmap = value;
  11975         return (BCM_E_NONE);
  11976     }
  11977 #endif /* BCM_FIREBOLT2_SUPPORT */
  11978 
  11979     /*
  11980      *   4 -bit value h/w encoding
  11981      *   The msb indicates if the counter should be incremented by one or be
  11982      *   increased by the packet byte count.
  11983      *
  11984      *   The next 3 bits indicate how and when to update one of the two counters
  11985      *   in the pair.
  11986      *   MODE    UPPER_COUNTER_UPDATE    LOWER_COUNTER_UPDATE
  11987      *   3b000    NO                        NO
  11988      *   3b001    NO                        YES
  11989      *   3b010    YES                       NO
  11990      *   3b011    IF RED                    IF NOT RED
  11991      *   3b100    IF GREEN                  IF NOT GREEN
  11992      *   3b101    IF GREEN                  IF RED
  11993      *   3b110    IF GREEN                  IF YELLOW
  11994      *   3b111    IF RED                    IF YELLOW
  11995      */
  11996     switch (mode) {
  11997       case (0x1):
  11998       case (0x2):
  11999           value |= (1 << (int)bcmFieldStatPackets);
  12000           *hw_entry_count = 1;
  12001           break;
  12002       case (0x9):
  12003       case (0xa):
  12004           value |= (1 << (int)bcmFieldStatBytes);
  12005           *hw_entry_count = 1;
  12006           break;
  12007       case (0x3):
  12008           value |= (1 << (int)bcmFieldStatRedPackets);
  12009           value |= (1 << (int)bcmFieldStatNotRedPackets);
  12010           *hw_entry_count = 2;
  12011           break;
  12012       case (0xb):
  12013           value |= (1 << (int)bcmFieldStatRedBytes);
  12014           value |= (1 << (int)bcmFieldStatNotRedBytes);
  12015           *hw_entry_count = 2;
  12016           break;
  12017       case (0x4):
  12018           value |= (1 << (int)bcmFieldStatGreenPackets);
  12019           value |= (1 << (int)bcmFieldStatNotGreenPackets);
  12020           *hw_entry_count = 2;
  12021           break;
  12022       case (0xc):
  12023           value |= (1 << (int)bcmFieldStatGreenBytes);
  12024           value |= (1 << (int)bcmFieldStatNotGreenBytes);
  12025           *hw_entry_count = 2;
  12026           break;
  12027       case (0x5):
  12028           value |= (1 << (int)bcmFieldStatGreenPackets);
  12029           value |= (1 << (int)bcmFieldStatRedPackets);
  12030           value |= (1 << (int)bcmFieldStatNotYellowPackets);
  12031           *hw_entry_count = 2;
  12032           break;
  12033       case (0xd):
  12034           value |= (1 << (int)bcmFieldStatGreenBytes);
  12035           value |= (1 << (int)bcmFieldStatRedBytes);
  12036           value |= (1 << (int)bcmFieldStatNotYellowBytes);
  12037           *hw_entry_count = 2;
  12038           break;
  12039       case (0x6):
  12040           value |= (1 << (int)bcmFieldStatGreenPackets);
  12041           value |= (1 << (int)bcmFieldStatYellowPackets);
  12042           value |= (1 << (int)bcmFieldStatNotRedPackets);
  12043           *hw_entry_count = 2;
  12044           break;
  12045       case (0xe):
  12046           value |= (1 << (int)bcmFieldStatGreenBytes);
  12047           value |= (1 << (int)bcmFieldStatYellowBytes);
  12048           value |= (1 << (int)bcmFieldStatNotRedBytes);
  12049           *hw_entry_count = 2;
  12050           break;
  12051       case (0x7):
  12052           value |= (1 << (int)bcmFieldStatRedPackets);
  12053           value |= (1 << (int)bcmFieldStatYellowPackets);
  12054           value |= (1 << (int)bcmFieldStatNotGreenPackets);
  12055           *hw_entry_count = 2;
  12056           break;
  12057       case (0xf):
  12058           value |= (1 << (int)bcmFieldStatRedBytes);
  12059           value |= (1 << (int)bcmFieldStatYellowBytes);
  12060           value |= (1 << (int)bcmFieldStatNotGreenBytes);
  12061           *hw_entry_count = 2;
  12062           break;
  12063       default:
  12064           *hw_entry_count = 0;
  12065     }
  12066     *hw_bmap = value;
  12067     return (BCM_E_NONE);
  12068 }
  12069 
  12070 #if defined(BCM_BRADLEY_SUPPORT)
  12071 /*
  12072  * Function:
  12073  *     _field_br_counter_write
  12074  * Purpose:
  12075  *     Update accumulated sw counter and return current counter value.
  12076  * Parameters:
  12077  *   unit          - (IN)  BCM device number.
  12078  *   stage_fc      - (IN)  Stage field control. 
  12079  *   counter_x_mem - (IN)  HW memory name.
  12080  *   mem_x_buf     - (IN)  Memory table entry.
  12081  *   counter_y_mem - (IN)  HW memory name.
  12082  *   mem_y_buf     - (IN)  Memory table entry.
  12083  *   idx           - (IN)  Counter index.
  12084  *   packet_count  - (OUT) Packet Counter value
  12085  *   byte_count    - (OUT) Byte Counter value
  12086  * Returns:
  12087  *    BCM_E_XXX
  12088  */
  12089 STATIC int
  12090 _field_br_counter_write(int unit, soc_mem_t mem, int idx, uint32 *buf,
  12091                       _field_counter64_collect_t *cntrs64_buf,
  12092                       uint64 *value)
  12093 {
  12094     uint32  hw_val[2];     /* Parsed field counter value.*/
  12095 
  12096     /* Set accumulated SW counter. */
  12097     COMPILER_64_ZERO(cntrs64_buf->accumulated_counter);
  12098     COMPILER_64_OR(cntrs64_buf->accumulated_counter, (*value));
  12099     COMPILER_64_SET(cntrs64_buf->last_hw_value, 
  12100                     COMPILER_64_HI(*value) & 0xf, COMPILER_64_LO(*value));
  12101 
  12102     /* 36 LSB set as a last hw value. */
  12103     hw_val[0] = COMPILER_64_LO(cntrs64_buf->last_hw_value);
  12104     hw_val[1] = COMPILER_64_HI(cntrs64_buf->last_hw_value);
  12105     soc_mem_field_set(unit, mem, buf, COUNTERf, hw_val);
  12106     return soc_mem_write(unit, mem, MEM_BLOCK_ALL, idx, buf);
  12107 }
  12108 
  12109 
  12110 /*
  12111  * Function:
  12112  *     _field_br_counter_set
  12113  * Purpose:
  12114  *     Set accumulated sw & hw counters. 
  12115  * Parameters:
  12116  *   unit          - (IN)  BCM device number.
  12117  *   stage_fc      - (IN)  Stage field control. 
  12118  *   counter_x_mem - (IN)  HW memory name.
  12119  *   mem_x_buf     - (IN)  Memory table entry.
  12120  *   counter_y_mem - (IN)  HW memory name.
  12121  *   mem_y_buf     - (IN)  Memory table entry.
  12122  *   idx           - (IN)  Counter index.
  12123  *   packet_count  - (OUT) Packet Counter value
  12124  *   byte_count    - (OUT) Byte Counter value
  12125  * Returns:
  12126  *    BCM_E_XXX
  12127  */
  12128 STATIC int
  12129 _field_br_counter_set(int unit, _field_stage_t *stage_fc,
  12130                       soc_mem_t counter_x_mem, uint32 *mem_x_buf,
  12131                       soc_mem_t counter_y_mem, uint32 *mem_y_buf,
  12132                       int idx, uint64 *packet_count, uint64 *byte_count)
  12133 {
  12134     _field_counter64_collect_t *cntrs64_buf;  /* Sw packet counter value    */
  12135     uint64                     *value;        /* Counter accumulated value. */
  12136     int                        rv;            /* Operation return status.   */
  12137 
  12138     /* Input parameters check. */
  12139     if (NULL == stage_fc) {
  12140         return (BCM_E_PARAM);
  12141     }
  12142 
  12143     value = (NULL == packet_count) ? byte_count : packet_count;
  12144 
  12145     /* Write X pipeline counter value. */
  12146     if (NULL != mem_x_buf) {
  12147         cntrs64_buf = &stage_fc->_field_x64_counters[idx];
  12148         rv = _field_br_counter_write(unit, counter_x_mem, idx, mem_x_buf,
  12149                                      cntrs64_buf, value);
  12150         BCM_IF_ERROR_RETURN(rv);
  12151     }
  12152 
  12153     /* Extract Y pipeline counter value. */
  12154     if (NULL != mem_y_buf) {
  12155         COMPILER_64_ZERO(*value);
  12156         cntrs64_buf = &stage_fc->_field_y64_counters[idx];
  12157         rv = _field_br_counter_write(unit, counter_y_mem, idx, mem_y_buf,
  12158                                      cntrs64_buf, value);
  12159         BCM_IF_ERROR_RETURN(rv);
  12160     }
  12161     return (BCM_E_NONE);
  12162 }
  12163 /*
  12164  * Function:
  12165  *     _field_br_counter_read
  12166  * Purpose:
  12167  *     Update accumulated sw counter and return current counter value.
  12168  * Parameters:
  12169  *   unit          - (IN)  BCM device number.
  12170  *   stage_fc      - (IN)  Stage field control. 
  12171  *   counter_x_mem - (IN)  HW memory name.
  12172  *   mem_x_buf     - (IN)  Memory table entry.
  12173  *   counter_y_mem - (IN)  HW memory name.
  12174  *   mem_y_buf     - (IN)  Memory table entry.
  12175  *   idx           - (IN)  Counter index.
  12176  *   packet_count  - (OUT) Packet Counter value
  12177  *   byte_count    - (OUT) Byte Counter value
  12178  * Returns:
  12179  *    BCM_E_XXX
  12180  */
  12181 STATIC int
  12182 _field_br_counter_read(int unit, soc_memacc_t *memacc, uint32 *buf,
  12183                       _field_counter64_collect_t *cntrs64_buf,
  12184                       uint64 *count)
  12185 {
  12186     uint32  hw_val[2];     /* Parsed field counter value.*/
  12187 
  12188     /* Byte counter. */
  12189     hw_val[0] = hw_val[1] = 0;
  12190     soc_memacc_field_get(memacc, buf, hw_val);
  12191 
  12192     _bcm_field_36bit_counter_update(unit, hw_val, cntrs64_buf);
  12193     if (NULL != count) {
  12194         COMPILER_64_ADD_64(*count, cntrs64_buf->accumulated_counter);
  12195     }
  12196     return (BCM_E_NONE);
  12197 }
  12198 
  12199 
  12200 /*
  12201  * Function:
  12202  *     _field_br_counter_get
  12203  * Purpose:
  12204  *     Update accumulated sw counter and return current counter value.
  12205  * Parameters:
  12206  *   unit          - (IN)  BCM device number.
  12207  *   stage_fc      - (IN)  Stage field control. 
  12208  *   counter_x_mem - (IN)  HW memory name.
  12209  *   mem_x_buf     - (IN)  Memory table entry.
  12210  *   counter_y_mem - (IN)  HW memory name.
  12211  *   mem_y_buf     - (IN)  Memory table entry.
  12212  *   idx           - (IN)  Counter index.
  12213  *   packet_count  - (OUT) Packet Counter value
  12214  *   byte_count    - (OUT) Byte Counter value
  12215  * Returns:
  12216  *    BCM_E_XXX
  12217  */
  12218 STATIC int
  12219 _field_br_counter_get(int unit, _field_stage_t *stage_fc,
  12220                       soc_mem_t counter_x_mem, uint32 *mem_x_buf,
  12221                       soc_mem_t counter_y_mem, uint32 *mem_y_buf,
  12222                       int idx, uint64 *packet_count, uint64 *byte_count)
  12223 {
  12224     _field_counter64_collect_t *cntrs64_buf;  /* Sw packet counter value    */
  12225     uint64                     value;         /* Counter accumulated value. */
  12226     soc_memacc_t *memacc_x, *memacc_y;        /* Memory access cache.   */
  12227 
  12228     /* Input parameters check. */
  12229     if (NULL == stage_fc) {
  12230         return (BCM_E_PARAM);
  12231     }
  12232 
  12233     sal_memset(&value, 0, sizeof(uint64));
  12234 
  12235     /* Extract X pipeline counter value. */
  12236     if (NULL != mem_x_buf) {
  12237         cntrs64_buf = &stage_fc->_field_x64_counters[idx];
  12238         memacc_x =
  12239             &(stage_fc->_field_memacc_counters[_FIELD_COUNTER_MEMACC_COUNTER]);
  12240         SOC_IF_ERROR_RETURN
  12241             (_field_br_counter_read(unit, memacc_x, mem_x_buf,
  12242                                     cntrs64_buf, &value));
  12243     }
  12244 
  12245     /* Extract Y pipeline counter value. */
  12246     if (NULL != mem_y_buf) {
  12247         cntrs64_buf = &stage_fc->_field_y64_counters[idx];
  12248         memacc_y =
  12249             &(stage_fc->_field_memacc_counters[_FIELD_COUNTER_MEMACC_COUNTER_Y]);
  12250         SOC_IF_ERROR_RETURN
  12251             (_field_br_counter_read(unit, memacc_y, mem_y_buf,
  12252                                     cntrs64_buf, &value));
  12253     }
  12254 
  12255     /* Return accumulated value to the caller routine. */
  12256     if (NULL != packet_count) {
  12257         COMPILER_64_OR(*packet_count, value);
  12258     }
  12259     if (NULL != byte_count) {
  12260         COMPILER_64_OR(*byte_count, value);
  12261     }
  12262     return (BCM_E_NONE);
  12263 }
  12264 #endif /* BCM_BRADLEY_SUPPORT */
  12265 
  12266 
  12267 /*
  12268  * Function:
  12269  *     _bcm_field_fb_counter_set
  12270  * Purpose:
  12271  *     Set accumulated sw & hw counters.
  12272  * Parameters:
  12273  *   unit          - (IN)  BCM device number.
  12274  *   stage_fc      - (IN)  Stage field control. 
  12275  *   counter_x_mem - (IN)  HW memory name.
  12276  *   mem_x_buf     - (IN)  Memory table entry.
  12277  *   counter_y_mem - (IN)  HW memory name.
  12278  *   mem_y_buf     - (IN)  Memory table entry.
  12279  *   idx           - (IN)  Counter index.
  12280  *   packet_count  - (OUT) Packet Counter value
  12281  *   byte_count    - (OUT) Byte Counter value
  12282  * Returns:
  12283  *    BCM_E_XXX
  12284  */
  12285 int
  12286 _bcm_field_fb_counter_set(int unit, _field_stage_t *stage_fc,
  12287                           soc_mem_t counter_x_mem, uint32 *mem_x_buf,
  12288                           soc_mem_t counter_y_mem, uint32 *mem_y_buf,
  12289                           int idx, uint64 *packet_count, uint64 *byte_count)
  12290 {
  12291     _field_counter32_collect_t *cntrs32_buf;  /* Sw packet counter value    */
  12292     uint32                     hw_val[2];     /* Parsed field counter value.*/
  12293     uint64                     *value;        /* Programmed value.          */
  12294 
  12295     /* Input parameters check. */
  12296     if ((NULL == mem_x_buf) || (INVALIDm == counter_x_mem) || \
  12297         (NULL == stage_fc)) {
  12298         return (BCM_E_PARAM);
  12299     }
  12300 
  12301     hw_val[0] = hw_val[1] = 0;
  12302     /* Set accumulated sw counter. */
  12303     value = (NULL == packet_count) ? byte_count : packet_count;
  12304     cntrs32_buf = &stage_fc->_field_x32_counters[idx];
  12305     COMPILER_64_ZERO(cntrs32_buf->accumulated_counter);
  12306     COMPILER_64_OR(cntrs32_buf->accumulated_counter, *value);
  12307     COMPILER_64_TO_32_LO(cntrs32_buf->last_hw_value, *value);
  12308     cntrs32_buf->last_hw_value &= 0x1fffffff; /* 29 bits */
  12309 
  12310     /* Set lsb hw counter. */
  12311     hw_val[0] = cntrs32_buf->last_hw_value;
  12312     hw_val[1] = 0;
  12313     soc_mem_field_set(unit, counter_x_mem, mem_x_buf, COUNTERf, hw_val);
  12314     return soc_mem_write(unit, counter_x_mem, MEM_BLOCK_ALL, idx, mem_x_buf);
  12315 }
  12316 
  12317 
  12318 /*
  12319  * Function:
  12320  *     _bcm_field_fb_counter_get
  12321  * Purpose:
  12322  *     Update accumulated sw counter and return current counter value.
  12323  * Parameters:
  12324  *   unit          - (IN)  BCM device number.
  12325  *   stage_fc      - (IN)  Stage field control. 
  12326  *   counter_x_mem - (IN)  HW memory name.
  12327  *   mem_x_buf     - (IN)  Memory table entry.
  12328  *   counter_y_mem - (IN)  HW memory name.
  12329  *   mem_y_buf     - (IN)  Memory table entry.
  12330  *   idx           - (IN)  Counter index.
  12331  *   packet_count  - (OUT) Packet Counter value
  12332  *   byte_count    - (OUT) Byte Counter value
  12333  * Returns:
  12334  *    BCM_E_XXX
  12335  */
  12336 int
  12337 _bcm_field_fb_counter_get(int unit, _field_stage_t *stage_fc,
  12338                           soc_mem_t counter_x_mem, uint32 *mem_x_buf,
  12339                           soc_mem_t counter_y_mem, uint32 *mem_y_buf,
  12340                           int idx, uint64 *packet_count, uint64 *byte_count)
  12341 {
  12342     _field_counter32_collect_t *cntrs32_buf;  /* Sw packet counter value    */
  12343     soc_memacc_t *memacc;                     /* Memory access cache.   */
  12344     uint32                     hw_val[2];     /* Parsed field counter value.*/
  12345 
  12346     /* Input parameters check. */
  12347     if ((NULL == mem_x_buf) || (INVALIDm == counter_x_mem) || \
  12348         (NULL == stage_fc)) {
  12349         return (BCM_E_PARAM);
  12350     }
  12351 
  12352     hw_val[0] = hw_val[1] = 0;
  12353     cntrs32_buf = &stage_fc->_field_x32_counters[idx];
  12354     memacc =
  12355         &(stage_fc->_field_memacc_counters[_FIELD_COUNTER_MEMACC_COUNTER]);
  12356     soc_memacc_field_get(memacc, mem_x_buf, hw_val);
  12357     _bcm_field_32bit_counter_update(unit, hw_val, cntrs32_buf);
  12358     /* Return counter value to caller if (out) pointer was provided. */ 
  12359     if (NULL != byte_count) {
  12360         COMPILER_64_OR(*byte_count, cntrs32_buf->accumulated_counter);
  12361     }
  12362     if (NULL != packet_count) {
  12363         COMPILER_64_OR(*packet_count, cntrs32_buf->accumulated_counter);
  12364     }
  12365     return (BCM_E_NONE);
  12366 }
  12367 
  12368 /*
  12369  * Function:
  12370  *     _bcm_field_fb_counter_get
  12371  * Purpose:
  12372  *      Get hw indexes and flags needed to compose requested statistic.
  12373  *     
  12374  * Parameters:
  12375  *   unit          - (IN)  BCM device number.
  12376  *   f_st          - (IN)  Field statistics entity.
  12377  *   stat          - (IN)  Counter type.
  12378  *   idx1          - (OUT)  Primary counter index.
  12379  *   idx2          - (OUT)  Secondary counter index.
  12380  *   out_flags     - (OUT)  Counter flags.
  12381  * Returns:
  12382  *    BCM_E_XXX
  12383  */
  12384 int
  12385 _bcm_field_fb_stat_index_get(int unit, _field_stat_t *f_st, 
  12386                              bcm_field_stat_t stat,
  12387                              int *idx1, int *idx2, int *idx3, uint32 *out_flags)
  12388 {
  12389     _field_stage_t *stage_fc;        /* Stage field control structure. */
  12390     int            rv;               /* Operation return status.       */
  12391     uint32         flags = 0;        /* _FP_STAT_XXX flags.            */
  12392     uint32         counter_tbl_idx;  /* Counter table index.           */
  12393     int            index1  = _FP_INVALID_INDEX;
  12394     int            index2  = _FP_INVALID_INDEX;
  12395 
  12396     /* Input parameters check. */
  12397     if ((NULL == idx1) || (NULL == idx2) || (NULL == idx3) ||
  12398         (NULL == out_flags) || (NULL == f_st)) {
  12399         return (BCM_E_PARAM);
  12400     }
  12401 
  12402     /* Stat entity indexes are adjusted for policy table counter pairs. */
  12403 #if defined (BCM_FIREBOLT2_SUPPORT) 
  12404     if (SOC_IS_FIREBOLT2(unit) && (_BCM_FIELD_STAGE_EGRESS == f_st->stage_id)) {
  12405         /* 5651x doesn't have counter pairs on stage egress. */
  12406         counter_tbl_idx = f_st->hw_index;
  12407     } else 
  12408 #endif /* BCM_FIREBOLT2_SUPPORT */
  12409     {
  12410         counter_tbl_idx = f_st->hw_index << 1;
  12411     }
  12412 
  12413     switch ((int)stat) {
  12414       case bcmFieldStatBytes:
  12415           flags |= _FP_STAT_BYTES;
  12416           /* passthru */
  12417           /* coverity[MISSING_BREAK: FALSE] */
  12418       case bcmFieldStatPackets:
  12419           switch (f_st->hw_mode) {
  12420             case (0x2):
  12421             case (0xa):
  12422                 index1 = counter_tbl_idx + 1;
  12423                 break;
  12424             case (0x1):
  12425             case (0x9):
  12426                 index1 = counter_tbl_idx; 
  12427                 break;
  12428             default:
  12429                 return (BCM_E_INTERNAL);
  12430           }
  12431           break;
  12432       case bcmFieldStatGreenBytes:
  12433           switch (f_st->hw_mode) {
  12434             case (0xc):
  12435             case (0xd):
  12436             case (0xe):
  12437                 index1 = counter_tbl_idx + 1;   /* Green bytes. */
  12438                 break;
  12439             default:
  12440                 return (BCM_E_INTERNAL);
  12441           }
  12442           flags |= _FP_STAT_BYTES;
  12443           break;
  12444       case bcmFieldStatGreenPackets:
  12445           switch (f_st->hw_mode) {
  12446             case (0x4):
  12447             case (0x5):
  12448             case (0x6):
  12449                 index1 = counter_tbl_idx + 1;   /* Green packets. */
  12450                 break;
  12451             default:
  12452                 return (BCM_E_INTERNAL);
  12453           }
  12454           break;
  12455       case bcmFieldStatYellowBytes:
  12456           switch (f_st->hw_mode) {
  12457             case (0xe):
  12458             case (0xf):
  12459                 index1 = counter_tbl_idx;   /* Yellow bytes. */
  12460                 break;
  12461             default:
  12462                 return (BCM_E_INTERNAL);
  12463           }
  12464           flags |= _FP_STAT_BYTES;
  12465           break;
  12466       case bcmFieldStatYellowPackets:
  12467           switch (f_st->hw_mode) {
  12468             case (0x6):
  12469             case (0x7):
  12470                 index1 = counter_tbl_idx;   /* Yellow packets. */
  12471                 break;
  12472             default:
  12473                 return (BCM_E_INTERNAL);
  12474           }
  12475           break;
  12476       case bcmFieldStatRedBytes:
  12477           switch (f_st->hw_mode) {
  12478             case (0xb):
  12479             case (0xf):
  12480                 index1 = counter_tbl_idx + 1;     /* Red bytes. */
  12481                 break;
  12482             case (0xd):
  12483                 index1 = counter_tbl_idx;         /* Red bytes. */
  12484                 break;
  12485             default:
  12486                 return (BCM_E_INTERNAL);
  12487           }
  12488           flags |= _FP_STAT_BYTES;
  12489           break;
  12490       case bcmFieldStatRedPackets:
  12491           switch (f_st->hw_mode) {
  12492             case (0x3):
  12493             case (0x7):
  12494                 index1 = counter_tbl_idx + 1;     /* Red packets. */
  12495                 break;
  12496             case (0x5):
  12497                 index1 = counter_tbl_idx;         /* Red packets. */
  12498                 break;
  12499             default:
  12500                 return (BCM_E_INTERNAL);
  12501           }
  12502           break;
  12503       case bcmFieldStatNotGreenBytes:
  12504           switch (f_st->hw_mode) {
  12505             case (0xc):
  12506                 index1 = counter_tbl_idx;   /* Not Green bytes. */
  12507                 break;
  12508             case (0xf):
  12509                 index1 = counter_tbl_idx + 1;    /* Red bytes.    */
  12510                 index2 = counter_tbl_idx;        /* Yellow bytes. */
  12511                 flags |= _FP_STAT_ADD;
  12512                 break;
  12513             default:
  12514                 return (BCM_E_INTERNAL);
  12515           }
  12516           flags |= _FP_STAT_BYTES;
  12517           break;
  12518       case bcmFieldStatNotGreenPackets:
  12519           switch (f_st->hw_mode) {
  12520             case (0x4):
  12521                 index1 = counter_tbl_idx;        /* Green packets. */
  12522                 break;
  12523             case (0x7):
  12524                 index1 = counter_tbl_idx + 1;   /*  Red packets.    */
  12525                 index2 = counter_tbl_idx;       /*  Yellow packets. */
  12526                 flags |= _FP_STAT_ADD;
  12527                 break;
  12528             default:
  12529                 return (BCM_E_INTERNAL);
  12530           }
  12531           break;
  12532       case bcmFieldStatNotYellowBytes:
  12533           switch (f_st->hw_mode) {
  12534             case (0xd):
  12535                 index1 = counter_tbl_idx;           /* Green bytes. */
  12536                 index2 = counter_tbl_idx + 1;       /* Red bytes.   */
  12537                 flags |= _FP_STAT_ADD;
  12538                 break;
  12539             default:
  12540                 return (BCM_E_INTERNAL);
  12541           }
  12542           flags |= _FP_STAT_BYTES;
  12543           break;
  12544       case bcmFieldStatNotYellowPackets:
  12545           switch (f_st->hw_mode) {
  12546             case (0x5):
  12547                 index1 = counter_tbl_idx + 1;      /* Green packets. */
  12548                 index2 = counter_tbl_idx;          /* Red packets.   */
  12549                 flags |= _FP_STAT_ADD;
  12550                 break;
  12551             default:
  12552                 return (BCM_E_INTERNAL);
  12553           }
  12554           break;
  12555       case bcmFieldStatNotRedBytes:
  12556           switch (f_st->hw_mode) {
  12557             case (0xb):
  12558                 index1 = counter_tbl_idx;         /* Not red bytes. */
  12559                 break;
  12560             case (0xe):
  12561                 index1 = counter_tbl_idx + 1;     /* Yellow bytes.  */
  12562                 index2 = counter_tbl_idx;         /* Green bytes.   */
  12563                 flags |= _FP_STAT_ADD;
  12564                 break;
  12565             default:
  12566                 return (BCM_E_INTERNAL);
  12567           }
  12568           flags |= _FP_STAT_BYTES;
  12569           break;
  12570       case bcmFieldStatNotRedPackets:
  12571           switch (f_st->hw_mode) {
  12572             case (0x3):
  12573                 index1 = counter_tbl_idx;         /* Not red packets. */
  12574                 break;
  12575             case (0x6):
  12576                 index1 = counter_tbl_idx;         /* Yellow packets.  */
  12577                 index2 = counter_tbl_idx + 1;     /* Green packets.   */
  12578                 flags |= _FP_STAT_ADD;
  12579                 break;
  12580             default:
  12581                 return (BCM_E_INTERNAL);
  12582           }
  12583           break;
  12584       default:
  12585           return (BCM_E_INTERNAL);
  12586     }
  12587 
  12588     /* Get stage field control structure. */
  12589     rv = _field_stage_control_get(unit, f_st->stage_id, &stage_fc);
  12590     BCM_IF_ERROR_RETURN(rv);
  12591 
  12592     /* Calculate  counter table entry index. */
  12593     if (_FP_INVALID_INDEX != index1) {
  12594 #if defined (BCM_FIREBOLT2_SUPPORT)
  12595         if (SOC_IS_FIREBOLT2(unit) && (_BCM_FIELD_STAGE_EGRESS == stage_fc->stage_id)) {
  12596             *idx1 = index1;
  12597         } else 
  12598 #endif /* BCM_FIREBOLT2_SUPPORT */
  12599         {
  12600             *idx1 =
  12601             stage_fc->slices[_FP_DEF_INST][f_st->pool_index].start_tcam_idx
  12602                 + index1;
  12603         }
  12604     } else {
  12605         *idx1 = _FP_INVALID_INDEX;
  12606     }
  12607 
  12608     if (_FP_INVALID_INDEX != index2) {
  12609         *idx2 =
  12610         stage_fc->slices[_FP_DEF_INST][f_st->pool_index].start_tcam_idx
  12611             + index2;
  12612     } else {
  12613         *idx2 = _FP_INVALID_INDEX;
  12614     }
  12615     *idx3 = _FP_INVALID_INDEX;
  12616     *out_flags = flags;
  12617     return (BCM_E_NONE);
  12618 }
  12619 
  12620 #if defined(BCM_FIREBOLT2_SUPPORT) 
  12621 /*
  12622  * Function: _bcm_field_fb2_qualify_ttl
  12623  *
  12624  * Purpose:
  12625  *     Add a field qualification to a filter entry.
  12626  *
  12627  * Parameters:
  12628  *     unit  - BCM device number
  12629  *     entry - Field entry array.
  12630  *     data - Data to qualify with 
  12631  *     mask - Mask to qualify with
  12632  *
  12633  * Returns:
  12634  *     BCM_E_XXX        Other errors
  12635  */
  12636 int
  12637 _bcm_field_fb2_qualify_ttl(int unit, bcm_field_entry_t entry,
  12638                            uint8 data, uint8 mask)
  12639 {
  12640     _field_entry_t *f_ent;
  12641     _field_group_t *fg = NULL;
  12642     uint8 result;
  12643     int rv;   
  12644 
  12645     rv = _bcm_field_entry_get_by_id(unit, entry, &f_ent);
  12646     BCM_IF_ERROR_RETURN(rv);
  12647 
  12648     fg = f_ent->group;   
  12649     /* Check if ttl is part of group qset. */
  12650     rv = _bcm_field_qset_test(bcmFieldQualifyTtl, &fg->qset, &result);
  12651     BCM_IF_ERROR_RETURN(rv);
  12652 
  12653     if (result) {
  12654         return _field_qualify32(unit, entry, bcmFieldQualifyTtl, data, mask);
  12655     }
  12656 
  12657     /* Only intraslice groups support encoded TTL values. */
  12658     if (0 == (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) {
  12659         return BCM_E_PARAM;
  12660     }
  12661 
  12662     /* bcmFieldQualifyTtl not present, use TTL_ENCODE (if present) */
  12663     switch (data & mask) {
  12664       case 0:
  12665           data = 0x0;
  12666           mask &= 0x3;
  12667           break;
  12668       case 1:
  12669           data = 0x1;
  12670           mask &= 0x3;
  12671           break;
  12672       case 255:
  12673           data = 0x3;
  12674           mask &= 0x3;
  12675           break;
  12676       default:
  12677           data = 0x2;
  12678           mask &= 0x3;    
  12679     }
  12680     /* Write the TTL_ENCODE data and mask - only for FB 2 */
  12681     rv = _bcm_field_qual_tcam_key_mask_get(unit, f_ent + 1);
  12682     BCM_IF_ERROR_RETURN(rv);
  12683 
  12684     f_ent[1].tcam.key[0] &= ~(mask << 6);
  12685     f_ent[1].tcam.key[0] |= data << 6;
  12686 
  12687     f_ent[1].tcam.mask[0] &= ~(mask << 6);
  12688     f_ent[1].tcam.mask[0] |= mask << 6;
  12689     f_ent[1].flags |= _FP_ENTRY_DIRTY;
  12690     return BCM_E_NONE;
  12691 }
  12692 
  12693 /*
  12694  * Function: _bcm_field_fb2_qualify_ttl_get
  12695  *
  12696  * Purpose:
  12697  *     Add a field qualification to a filter entry.
  12698  *
  12699  * Parameters:
  12700  *     unit  - BCM device number
  12701  *     entry - Field entry array.
  12702  *     data - Data to qualify with 
  12703  *     mask - Mask to qualify with
  12704  *
  12705  * Returns:
  12706  *     BCM_E_XXX        Other errors
  12707  */
  12708 int
  12709 _bcm_field_fb2_qualify_ttl_get(int unit, bcm_field_entry_t entry,
  12710                            uint8 *data, uint8 *mask)
  12711 {
  12712     _field_entry_t *f_ent;
  12713     _field_group_t *fg = NULL;
  12714     uint8 free_tcam = FALSE;
  12715     uint8 result;
  12716     int rv;   
  12717 
  12718     rv = _bcm_field_entry_get_by_id(unit, entry, &f_ent);
  12719     BCM_IF_ERROR_RETURN(rv);
  12720 
  12721     fg = f_ent->group;   
  12722     /* Check if ttl is part of group qset. */
  12723     rv = _bcm_field_qset_test(bcmFieldQualifyTtl, &fg->qset, &result);
  12724     BCM_IF_ERROR_RETURN(rv);
  12725 
  12726     if (result) {
  12727         return _bcm_field_entry_qualifier_uint8_get(unit, entry, 
  12728                                                     bcmFieldQualifyTtl, 
  12729                                                     data, mask);
  12730     }
  12731 
  12732     /* Only intraslice groups support encoded TTL values. */
  12733     if (0 == (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) {
  12734         return BCM_E_PARAM;
  12735     }
  12736 
  12737     if (NULL == f_ent[1].tcam.key) {
  12738         free_tcam = TRUE;
  12739     }
  12740 
  12741     /* Read  the TTL_ENCODE data and mask - only for FB 2 */
  12742     rv = _bcm_field_qual_tcam_key_mask_get(unit, f_ent + 1);
  12743     BCM_IF_ERROR_RETURN(rv);
  12744 
  12745     /* bcmFieldQualifyTtl not present, use TTL_ENCODE (if present) */
  12746     switch ((f_ent[1].tcam.key[0] >> 6) & 0x3) {
  12747       case 0:
  12748           *data = 0x0;
  12749           *mask = 0xff;
  12750           break;
  12751       case 1:
  12752           *data = 0x1;
  12753           *mask &= 0xff;
  12754           break;
  12755       case 3:
  12756           *data = 0xff;
  12757           *mask &= 0xff;
  12758           break;
  12759       default:
  12760           return (BCM_E_UNAVAIL);
  12761     }
  12762     if (free_tcam) {
  12763         _bcm_field_qual_tcam_key_mask_free(unit, f_ent + 1);
  12764     }
  12765     return BCM_E_NONE;
  12766 }
  12767 #endif /* BCM_FIREBOLT2_SUPPORT */
  12768 
  12769 /*
  12770  * Function:
  12771  *     _bcm_field_fb_selcode_get
  12772  * Purpose:
  12773  *     Finds a 4-tuple of select encodings that will satisfy the
  12774  *     requested qualifier set (Qset).
  12775  * Parameters:
  12776  *     unit      - (IN) BCM unit number.
  12777  *     stage_fc  - (IN) Stage Field control structure.
  12778  *     qset_req  - (IN) Client qualifier set.
  12779  *     fg        - (IN/OUT)Select code information filled into the group.  
  12780  * 
  12781  * Returns:
  12782  *     BCM_E_XXX
  12783  */
  12784 int
  12785 _bcm_field_fb_selcode_get(int unit, _field_stage_t *stage_fc, 
  12786                       bcm_field_qset_t *qset_req,
  12787                       _field_group_t *fg)
  12788 {
  12789     int  rv;                     /* Operation return status. */
  12790 
  12791     /* Input parameters check. */
  12792     if ((NULL == fg) || (NULL == qset_req) || (NULL == stage_fc)) {
  12793         return (BCM_E_PARAM);
  12794     }
  12795 
  12796     /* Egress qualifiers are selected based on Key. */
  12797     switch (stage_fc->stage_id) {
  12798 #if defined(BCM_FIREBOLT2_SUPPORT) 
  12799       case _BCM_FIELD_STAGE_EGRESS:
  12800           rv =  _field_fb_egress_selcode_get(unit, stage_fc, qset_req, fg);
  12801           break;
  12802 #endif /* BCM_FIREBOLT2_SUPPORT */
  12803       default:
  12804           rv =  _bcm_field_selcode_get(unit, stage_fc, qset_req, fg);
  12805     }
  12806     return (rv);
  12807 }
  12808 
  12809 /*
  12810  * Function: _bcm_field_fb_udf_ipprotocol_delete_all
  12811  *
  12812  * Purpose:
  12813  *     Delete all the UDF ip protocol match values.
  12814  *
  12815  * Parameters:
  12816  *     unit      - (IN) BCM device number
  12817  * Returns:
  12818  *     BCM_E_XXX
  12819  */
  12820 int
  12821 _bcm_field_fb_udf_ipprotocol_delete_all(int unit)
  12822 {
  12823     int index;
  12824 
  12825     if (0 == SOC_REG_IS_VALID(unit, UDF_IPPROTO_MATCHr)) {
  12826         return (BCM_E_NONE);
  12827     }
  12828 
  12829     for (index = 0; index < _FP_DATA_IP_PROTOCOL_MAX; index++) {
  12830         SOC_IF_ERROR_RETURN(WRITE_UDF_IPPROTO_MATCHr(unit, index, 0));
  12831     }
  12832     return (BCM_E_NONE);
  12833 }
  12834 
  12835 /*
  12836  * Function: _bcm_field_fb_udf_ip_protocol_set
  12837  *
  12838  * Purpose:
  12839  *     Set the UDF Ip Protocol match value.
  12840  *
  12841  * Parameters:
  12842  *     unit      - (IN) BCM device number
  12843  *     index     - (IN) 0->7, Ethertype match index
  12844  *     flags     - (IN) IP version match is enabled
  12845  *     proto     - (IN) IP protocol id.
  12846  *
  12847  * Returns:
  12848  *     BCM_E_XXX
  12849  */
  12850 int
  12851 _bcm_field_fb_udf_ipprotocol_set(int unit, int index, uint32 flags, uint8 proto)
  12852 {
  12853     uint32 reg_val = 0;
  12854     uint32 ip4_enable = 0;
  12855     uint32 ip6_enable = 0;
  12856     uint32 protocol = 0;
  12857 
  12858     if (0 == SOC_REG_IS_VALID(unit, UDF_IPPROTO_MATCHr)) {
  12859         return (BCM_E_UNAVAIL); 
  12860     }
  12861 
  12862     /* Range check index. */
  12863     if (index < 0 || (_FP_DATA_IP_PROTOCOL_MAX <= index)) {
  12864         return (BCM_E_PARAM);
  12865     }
  12866 
  12867     protocol = proto;
  12868     switch (flags) {
  12869       case 0:
  12870           break;
  12871       case BCM_FIELD_DATA_FORMAT_IP4:
  12872           ip4_enable = TRUE;
  12873           break;
  12874       case BCM_FIELD_DATA_FORMAT_IP6:
  12875           ip6_enable = TRUE;
  12876           break;
  12877       case (BCM_FIELD_DATA_FORMAT_IP4 | BCM_FIELD_DATA_FORMAT_IP6):
  12878           ip4_enable = ip6_enable = TRUE;
  12879           break;
  12880       default: 
  12881           return (BCM_E_PARAM);
  12882     }
  12883 
  12884     /*  Update UDF_IPPROTO_MATCHr register. */
  12885     SOC_IF_ERROR_RETURN(READ_UDF_IPPROTO_MATCHr(unit, index, &reg_val));
  12886     soc_reg_field_set(unit, UDF_IPPROTO_MATCHr, &reg_val, IPV4ENABLEf, ip4_enable);
  12887     soc_reg_field_set(unit, UDF_IPPROTO_MATCHr, &reg_val, IPV6ENABLEf, ip6_enable);
  12888     soc_reg_field_set(unit, UDF_IPPROTO_MATCHr, &reg_val, PROTOCOLf, protocol); 
  12889     SOC_IF_ERROR_RETURN(WRITE_UDF_IPPROTO_MATCHr(unit, index, reg_val));
  12890 
  12891     return (BCM_E_NONE);
  12892 }
  12893 
  12894 /*
  12895  * Function: _bcm_field_fb_udf_ip_protocol_get
  12896  *
  12897  * Purpose:
  12898  *     Get the UDF Ip Protocol match value.
  12899  *
  12900  * Parameters:
  12901  *     unit      - (IN) BCM device number
  12902  *     index     - (IN) 0->7, Ethertype match index
  12903  *     flags     - (OUT) IP version match is enabled
  12904  *     proto     - (OUT) IP protocol id.
  12905  * Returns:
  12906  *     BCM_E_XXX
  12907  */
  12908 int
  12909 _bcm_field_fb_udf_ipprotocol_get(int unit, int index, uint32 *flags, uint8 *proto)
  12910 {
  12911     uint32              reg_val = 0;
  12912 
  12913     /* Input parameters check. */
  12914     if ((NULL == flags) || (NULL == proto)) {
  12915         return (BCM_E_PARAM);
  12916     }
  12917 
  12918     if (0 == SOC_REG_IS_VALID(unit, UDF_IPPROTO_MATCHr)) {
  12919         return (BCM_E_UNAVAIL); 
  12920     }
  12921 
  12922     /* Range check index. */
  12923     if (index < 0 || (_FP_DATA_IP_PROTOCOL_MAX <= index)) {
  12924         return (BCM_E_PARAM);
  12925     }
  12926 
  12927     SOC_IF_ERROR_RETURN(READ_UDF_IPPROTO_MATCHr(unit, index, &reg_val));
  12928 
  12929     *flags = 0;
  12930     if (soc_reg_field_get(unit, UDF_IPPROTO_MATCHr, reg_val, IPV4ENABLEf)) {
  12931         *flags |= BCM_FIELD_DATA_FORMAT_IP4;
  12932     }
  12933     if (soc_reg_field_get(unit, UDF_IPPROTO_MATCHr, reg_val, IPV6ENABLEf)) {
  12934         *flags |= BCM_FIELD_DATA_FORMAT_IP6;
  12935     }
  12936 
  12937     *proto = soc_reg_field_get(unit, UDF_IPPROTO_MATCHr, reg_val, PROTOCOLf);
  12938 
  12939     return (BCM_E_NONE);
  12940 }
  12941 
  12942 /*
  12943  * Function: _bcm_field_fb_udf_ethertype_delete_all
  12944  *
  12945  * Purpose:
  12946  *     Delete all the UDF ethertype match values.
  12947  *
  12948  * Parameters:
  12949  *     unit      - (IN) BCM device number
  12950  * Returns:
  12951  *     BCM_E_XXX
  12952  */
  12953 int
  12954 _bcm_field_fb_udf_ethertype_delete_all(int unit)
  12955 {
  12956     int index;
  12957 
  12958     if (0 == SOC_REG_IS_VALID(unit, UDF_ETHERTYPE_MATCHr)) {
  12959         return (BCM_E_NONE);
  12960     }
  12961 
  12962     for (index = 0; index < _FP_DATA_ETHERTYPE_MAX; index++) {
  12963         SOC_IF_ERROR_RETURN(WRITE_UDF_ETHERTYPE_MATCHr(unit, index, 0));
  12964     }
  12965     return (BCM_E_NONE);
  12966 }
  12967 
  12968 /*
  12969  * Function: _bcm_field_fb_udf_ethertype_set
  12970  *
  12971  * Purpose:
  12972  *     Set the UDF Ethertype match value.
  12973  *
  12974  * Parameters:
  12975  *     unit      - (IN) BCM device number
  12976  *     index     - (IN) 0->7, Ethertype match index
  12977  *     frametype - (IN) BCM_FIELD_DATA_FORMAT_L2_XXX
  12978  *     ethertype - (IN) Ethertype value to match
  12979  *
  12980  * Returns:
  12981  *     BCM_E_XXX
  12982  */
  12983 int
  12984 _bcm_field_fb_udf_ethertype_set(int unit, int index,
  12985                          bcm_port_frametype_t frametype,
  12986                          bcm_port_ethertype_t ethertype) 
  12987 {
  12988     uint32 reg_val;
  12989     uint32 enable;
  12990     uint32 frame_type;
  12991 
  12992     if (0 == SOC_REG_IS_VALID(unit, UDF_ETHERTYPE_MATCHr)) {
  12993         return (BCM_E_UNAVAIL);
  12994     }
  12995 
  12996     /* Range check index. */
  12997     if (index < 0 || (_FP_DATA_ETHERTYPE_MAX  <= index)) {
  12998         return (BCM_E_PARAM);
  12999     }
  13000 
  13001     switch (frametype) {
  13002       case 0:
  13003           enable = FALSE;
  13004           ethertype = 0;
  13005           frame_type = 0;
  13006           break;
  13007       case BCM_PORT_FRAMETYPE_ETHER2:
  13008           frame_type = 0;
  13009           enable = TRUE;
  13010           break;
  13011       case BCM_PORT_FRAMETYPE_SNAP:
  13012           frame_type = 1;
  13013           enable = TRUE;
  13014           break;
  13015       case BCM_PORT_FRAMETYPE_LLC:
  13016           frame_type = 2;
  13017           enable = TRUE;
  13018           break;
  13019       default:
  13020           return (BCM_E_PARAM);
  13021     }
  13022 
  13023     /*  Update UDF_ETHERTYPE_MATCHr register. */
  13024     SOC_IF_ERROR_RETURN(READ_UDF_ETHERTYPE_MATCHr(unit, index, &reg_val));
  13025     soc_reg_field_set(unit, UDF_ETHERTYPE_MATCHr, &reg_val, ENABLEf, enable);
  13026     soc_reg_field_set(unit, UDF_ETHERTYPE_MATCHr, &reg_val, L2_PACKET_FORMATf, 
  13027                       frame_type);
  13028     soc_reg_field_set(unit, UDF_ETHERTYPE_MATCHr, &reg_val, ETHERTYPEf, 
  13029                       (uint32)ethertype);
  13030     SOC_IF_ERROR_RETURN(WRITE_UDF_ETHERTYPE_MATCHr(unit, index, reg_val));
  13031     return (BCM_E_NONE);
  13032 }
  13033 
  13034 /*
  13035  * Function: _bcm_field_fb_udf_ethertype_get
  13036  *
  13037  * Purpose:
  13038  *     Set the UDF Ethertype match value.
  13039  *
  13040  * Parameters:
  13041  *     unit      - (IN) BCM device number
  13042  *     index     - (IN) 0->7, Ethertype match index
  13043  *     frametype - (OUT) BCM_FIELD_DATA_FORMAT_L2_XXX
  13044  *     ethertype - (OUT) Ethertype value to match
  13045  *
  13046  * Returns:
  13047  *     BCM_E_XXX
  13048  */
  13049 int
  13050 _bcm_field_fb_udf_ethertype_get(int unit, int index,
  13051                          bcm_port_frametype_t *frametype,
  13052                          bcm_port_ethertype_t *ethertype) 
  13053 {
  13054     uint32  reg_val = 0;
  13055     uint32  enable;
  13056     uint32  frame_type;     
  13057 
  13058     if (0 == SOC_REG_IS_VALID(unit, UDF_ETHERTYPE_MATCHr)) {
  13059         return (BCM_E_UNAVAIL);
  13060     }
  13061 
  13062     /* Range check index. */
  13063     if (index < 0 || (_FP_DATA_ETHERTYPE_MAX  <= index)) {
  13064         return (BCM_E_PARAM);
  13065     }
  13066 
  13067     /* Input parameters check */
  13068     if ((NULL == frametype) || (NULL == ethertype)) {
  13069         return (BCM_E_PARAM);
  13070     }
  13071 
  13072     SOC_IF_ERROR_RETURN(READ_UDF_ETHERTYPE_MATCHr(unit, index, &reg_val));
  13073 
  13074     enable = soc_reg_field_get(unit, UDF_ETHERTYPE_MATCHr, reg_val,
  13075                                ENABLEf);
  13076     if (enable) {
  13077         frame_type = soc_reg_field_get(unit, UDF_ETHERTYPE_MATCHr, reg_val,
  13078                                        L2_PACKET_FORMATf);
  13079 
  13080         switch (frame_type) {
  13081           case 0:
  13082               *frametype = BCM_PORT_FRAMETYPE_ETHER2;
  13083               break;
  13084           case 1:
  13085               *frametype = BCM_PORT_FRAMETYPE_SNAP;
  13086               break;
  13087           case 2:
  13088               *frametype = BCM_PORT_FRAMETYPE_LLC;
  13089               break;
  13090           default:
  13091               return (BCM_E_PARAM);
  13092         }
  13093 
  13094         *ethertype = soc_reg_field_get(unit, UDF_ETHERTYPE_MATCHr, reg_val,
  13095                                        ETHERTYPEf);
  13096     } else {
  13097         *frametype = 0;
  13098         *ethertype = 0;
  13099     }
  13100     return (BCM_E_NONE);
  13101 }
  13102 
  13103 /*
  13104  * Function:
  13105  *      _field_fb_udf_idx_to_l2_format
  13106  * Purpose:
  13107  *      Translate udf offset index l2 portion to packet l2 format.
  13108  * Parameters:
  13109  *      unit     - (IN) Bcm device number.
  13110  *      idx      - (IN) Udf offset table index.
  13111  *      l2       - (OUT)Packet L2 format specification.                 
  13112  * Returns:
  13113  *      BCM_E_XXX
  13114  */
  13115 STATIC int
  13116 _field_fb_udf_idx_to_l2_format(int unit, int idx, uint16 *l2)
  13117 {
  13118     int l2_idx;    /* L2 portion of udf offset table index. */
  13119 
  13120     /* Input parameters check. */
  13121     if (NULL == l2) {
  13122         return (BCM_E_PARAM);
  13123     }
  13124 
  13125     if (SOC_IS_TR_VL(unit)) {
  13126         l2_idx = idx >> 5; 
  13127     } else if  (SOC_IS_SC_CQ(unit)) {
  13128         l2_idx = idx >> 4; 
  13129     } else {
  13130         l2_idx = idx >> 3; 
  13131     }
  13132 
  13133     switch (l2_idx & 0x3) {
  13134       case 0:
  13135           *l2 = BCM_FIELD_DATA_FORMAT_L2_ETH_II;
  13136           break;
  13137       case 1:
  13138           *l2 = BCM_FIELD_DATA_FORMAT_L2_SNAP;
  13139           break;
  13140       case 2:
  13141           *l2 = BCM_FIELD_DATA_FORMAT_L2_LLC;
  13142           break;
  13143       default:
  13144 	  /* for case 3 */
  13145           *l2 = _BCM_FIELD_DATA_FORMAT_ETHERTYPE;
  13146           break;
  13147     }
  13148     return (BCM_E_NONE);
  13149 }
  13150 
  13151 
  13152 /*
  13153  * Function:
  13154  *      _field_fb_udf_idx_to_vlan_format
  13155  * Purpose:
  13156  *      Translate udf offset index vlan portion to packet vlan tag format.
  13157  * Parameters:
  13158  *      unit     - (IN) Bcm device number.
  13159  *      idx      - (IN) Udf offset table index.
  13160  *      vlan     - (OUT)Packet vlan format specification.                 
  13161  * Returns:
  13162  *      BCM_E_XXX
  13163  */
  13164 STATIC int
  13165 _field_fb_udf_idx_to_vlan_format(int unit, int idx, uint16 *vlan)
  13166 {
  13167     int vlan_idx;    /* Vlan portion of udf offset table index. */
  13168 
  13169     /* Input parameters check. */
  13170     if (NULL == vlan) {
  13171         return (BCM_E_PARAM);
  13172     }
  13173 
  13174     if (SOC_IS_TR_VL(unit)) {
  13175         vlan_idx = idx >> 7; 
  13176     } else if  (SOC_IS_SC_CQ(unit)) {
  13177         vlan_idx = idx >> 6; 
  13178     } else {
  13179         vlan_idx = idx >> 5; 
  13180     }
  13181 
  13182     switch (vlan_idx & 0x3) {
  13183       case 0:
  13184           *vlan = BCM_FIELD_DATA_FORMAT_VLAN_NO_TAG;
  13185           break;
  13186       case 1:
  13187           *vlan = BCM_FIELD_DATA_FORMAT_VLAN_SINGLE_TAGGED;
  13188           break;
  13189       case 2:
  13190           *vlan = BCM_FIELD_DATA_FORMAT_VLAN_DOUBLE_TAGGED;
  13191           break;
  13192       default:        
  13193           return (BCM_E_EMPTY);
  13194     }
  13195     return (BCM_E_NONE);
  13196 }
  13197 
  13198 /*
  13199  * Function:
  13200  *      _field_fb_udf_idx_to_ip_format
  13201  * Purpose:
  13202  *      Translate udf offset index ip portion to packet ip format.
  13203  * Parameters:
  13204  *      unit     - (IN) Bcm device number.
  13205  *      idx      - (IN) Udf offset table index.
  13206  *      pkt_fmt  - (OUT)Packet format specification.                 
  13207  * Returns:
  13208  *      BCM_E_XXX
  13209  */
  13210 STATIC int
  13211 _field_fb_udf_idx_to_ip_format(int unit, int idx, 
  13212                             bcm_field_data_packet_format_t *pkt_fmt)
  13213 {
  13214     int ip_idx;    /* Ip portion of udf offset table index. */
  13215 
  13216     /* Input parameters check. */
  13217     if (NULL == pkt_fmt) {
  13218         return (BCM_E_PARAM);
  13219     }
  13220 
  13221     if (SOC_IS_TR_VL(unit)) {
  13222         ip_idx = idx & 0x1f;  
  13223     } else if  (SOC_IS_SC_CQ(unit)) {
  13224         ip_idx = idx & 0xf; 
  13225     } else {
  13226         ip_idx = idx & 0x7; 
  13227     }
  13228 
  13229     /* Init tunnel/ip header version to none. */
  13230     pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_NONE;
  13231     pkt_fmt->outer_ip = BCM_FIELD_DATA_FORMAT_IP_NONE;
  13232     pkt_fmt->inner_ip = BCM_FIELD_DATA_FORMAT_IP_NONE;
  13233 
  13234     switch (ip_idx) {
  13235       case 0:
  13236           pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_NONE;
  13237           pkt_fmt->outer_ip = BCM_FIELD_DATA_FORMAT_IP4;
  13238           pkt_fmt->inner_ip = BCM_FIELD_DATA_FORMAT_IP_NONE;
  13239           break;
  13240       case 1:
  13241           pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_NONE;
  13242           pkt_fmt->outer_ip = BCM_FIELD_DATA_FORMAT_IP6;
  13243           pkt_fmt->inner_ip = BCM_FIELD_DATA_FORMAT_IP_NONE;
  13244           break;
  13245       case 2:
  13246           pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_IP_IN_IP;
  13247           pkt_fmt->outer_ip = BCM_FIELD_DATA_FORMAT_IP4;
  13248           pkt_fmt->inner_ip = BCM_FIELD_DATA_FORMAT_IP4;
  13249           break;
  13250       case 3:
  13251           pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_IP_IN_IP;
  13252           pkt_fmt->outer_ip = BCM_FIELD_DATA_FORMAT_IP4;
  13253           pkt_fmt->inner_ip = BCM_FIELD_DATA_FORMAT_IP6;
  13254           break;
  13255       case 4:
  13256           if (SOC_IS_TRX(unit)) {
  13257               pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_IP_IN_IP;
  13258               pkt_fmt->outer_ip = BCM_FIELD_DATA_FORMAT_IP6;
  13259               pkt_fmt->inner_ip = BCM_FIELD_DATA_FORMAT_IP4;
  13260           }
  13261           break;
  13262       case 5:
  13263           if (SOC_IS_TRX(unit)) {
  13264               pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_IP_IN_IP;
  13265               pkt_fmt->outer_ip = BCM_FIELD_DATA_FORMAT_IP6;
  13266               pkt_fmt->inner_ip = BCM_FIELD_DATA_FORMAT_IP6;
  13267           } else {
  13268               pkt_fmt->outer_ip = _BCM_FIELD_DATA_FORMAT_IP4_PROTOCOL0;
  13269           }
  13270           break;
  13271       case 6:
  13272           if (SOC_IS_TRX(unit)) {
  13273               pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_GRE;
  13274               pkt_fmt->outer_ip = BCM_FIELD_DATA_FORMAT_IP4;
  13275               pkt_fmt->inner_ip = BCM_FIELD_DATA_FORMAT_IP4;
  13276           } else {
  13277               pkt_fmt->outer_ip = _BCM_FIELD_DATA_FORMAT_IP4_PROTOCOL1;
  13278           }
  13279           break;
  13280       case 7:
  13281           if (SOC_IS_TRX(unit)) {
  13282               pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_GRE;
  13283               pkt_fmt->outer_ip = BCM_FIELD_DATA_FORMAT_IP4;
  13284               pkt_fmt->inner_ip = BCM_FIELD_DATA_FORMAT_IP6;
  13285           } else {
  13286               return (BCM_E_EMPTY);
  13287           }
  13288           break;
  13289       case 8:
  13290           if (SOC_IS_TRX(unit)) {
  13291               pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_GRE;
  13292               pkt_fmt->outer_ip = BCM_FIELD_DATA_FORMAT_IP6;
  13293               pkt_fmt->inner_ip = BCM_FIELD_DATA_FORMAT_IP4;
  13294           } else {
  13295               return (BCM_E_EMPTY);
  13296           }
  13297           break;
  13298       case 9:
  13299           if (SOC_IS_TRX(unit)) {
  13300               pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_GRE;
  13301               pkt_fmt->outer_ip = BCM_FIELD_DATA_FORMAT_IP6;
  13302               pkt_fmt->inner_ip = BCM_FIELD_DATA_FORMAT_IP6;
  13303           } else {
  13304               return (BCM_E_EMPTY);
  13305           }
  13306           break;
  13307       case 0xa:
  13308           if (SOC_IS_SC_CQ(unit)) {
  13309                 /* _BCM_FIELD_USER_IP_NOTUSED */
  13310           } else if (SOC_IS_TR_VL(unit)) {
  13311               pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_MPLS;
  13312               pkt_fmt->mpls = BCM_FIELD_DATA_FORMAT_MPLS_ONE_LABEL;
  13313           } else {
  13314               return (BCM_E_EMPTY);
  13315           }
  13316           break;
  13317       case 0xb:
  13318           if (SOC_IS_SC_CQ(unit)) {
  13319               pkt_fmt->outer_ip = _BCM_FIELD_DATA_FORMAT_IP4_PROTOCOL0;
  13320           } else if (SOC_IS_TR_VL(unit)) {
  13321               pkt_fmt->tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_MPLS;
  13322               pkt_fmt->mpls = BCM_FIELD_DATA_FORMAT_MPLS_TWO_LABELS;
  13323           } else {
  13324               return (BCM_E_EMPTY);
  13325           }
  13326           break;
  13327       case 0xc:
  13328           if (SOC_IS_SC_CQ(unit)) {
  13329               pkt_fmt->outer_ip = _BCM_FIELD_DATA_FORMAT_IP4_PROTOCOL1;
  13330           } 
  13331           /* SOC_IS_TR_VL: _BCM_FIELD_USER_IP_NOTUSED */
  13332           break;
  13333       case 0xd:
  13334           if (SOC_IS_SC_CQ(unit)) {
  13335               pkt_fmt->outer_ip = _BCM_FIELD_DATA_FORMAT_IP6_PROTOCOL0;
  13336           } else if (SOC_IS_TR_VL(unit)) {
  13337               pkt_fmt->outer_ip = _BCM_FIELD_DATA_FORMAT_IP4_PROTOCOL0;
  13338           } else {
  13339               return (BCM_E_EMPTY);
  13340           }
  13341           break;
  13342       case 0xe:
  13343           if (SOC_IS_SC_CQ(unit)) {
  13344               pkt_fmt->outer_ip = _BCM_FIELD_DATA_FORMAT_IP6_PROTOCOL1;
  13345           } else if (SOC_IS_TR_VL(unit)) {
  13346               pkt_fmt->outer_ip = _BCM_FIELD_DATA_FORMAT_IP4_PROTOCOL1;
  13347           } else {
  13348               return (BCM_E_EMPTY);
  13349           }
  13350           break;
  13351       case 0xf:
  13352           if (SOC_IS_TR_VL(unit)) {
  13353               pkt_fmt->outer_ip = _BCM_FIELD_DATA_FORMAT_IP6_PROTOCOL0;
  13354           } else {
  13355               return (BCM_E_EMPTY);
  13356           }
  13357           break;
  13358       case 0x10:
  13359           if (SOC_IS_TR_VL(unit)) {
  13360               pkt_fmt->outer_ip = _BCM_FIELD_DATA_FORMAT_IP6_PROTOCOL1;
  13361           } else {
  13362               return (BCM_E_EMPTY);
  13363           }
  13364           break;
  13365       default:
  13366           return (BCM_E_EMPTY);
  13367     }
  13368     return (BCM_E_NONE);
  13369 }
  13370 
  13371 /*
  13372  * Function:
  13373  *      _field_udf_offset_idx_to_packet_format
  13374  * Purpose:
  13375  *      Translate udf offset table index to packet format.
  13376  * Parameters:
  13377  *      unit     - (IN) Bcm device number.
  13378  *      idx      - (IN) Udf offset table index.
  13379  *      pkt_fmt  - (OUT)Packet format specification.                 
  13380  * Returns:
  13381  *      BCM_E_XXX
  13382  */
  13383 STATIC int
  13384 _field_fb_udf_offset_idx_to_packet_format(int unit, int idx,
  13385                                 bcm_field_data_packet_format_t *pkt_fmt)
  13386 {
  13387     int rv;               /* Operation return status. */
  13388 
  13389     /* Input parameters check. */
  13390     if (NULL == pkt_fmt) {
  13391         return (BCM_E_PARAM);
  13392     }
  13393 
  13394     /* parse L2 format */
  13395     rv = _field_fb_udf_idx_to_l2_format(unit, idx, &pkt_fmt->l2);
  13396     BCM_IF_ERROR_RETURN(rv);
  13397 
  13398     /* Ignore ethertype based indexes. */
  13399     if (pkt_fmt->l2 == _BCM_FIELD_DATA_FORMAT_ETHERTYPE) {
  13400         return (BCM_E_EMPTY);
  13401     }
  13402 
  13403     /* parse vlan tag format */
  13404     rv = _field_fb_udf_idx_to_vlan_format(unit, idx, &pkt_fmt->vlan_tag);
  13405     BCM_IF_ERROR_RETURN(rv);
  13406 
  13407     /* parse L3 tunnel type/ Ip headers  format */
  13408     rv = _field_fb_udf_idx_to_ip_format(unit, idx, pkt_fmt);
  13409     BCM_IF_ERROR_RETURN(rv);
  13410 
  13411     /* Ignore ip protcol based indexes. */
  13412     if ((pkt_fmt->outer_ip == _BCM_FIELD_DATA_FORMAT_IP4_PROTOCOL0) ||
  13413         (pkt_fmt->outer_ip == _BCM_FIELD_DATA_FORMAT_IP4_PROTOCOL1) ||
  13414         (pkt_fmt->outer_ip == _BCM_FIELD_DATA_FORMAT_IP6_PROTOCOL0) ||
  13415         (pkt_fmt->outer_ip == _BCM_FIELD_DATA_FORMAT_IP6_PROTOCOL1)) {
  13416         return (BCM_E_EMPTY);
  13417     }
  13418 
  13419     return (BCM_E_NONE);
  13420 }
  13421 
  13422 /*
  13423  * Function:
  13424  *     _field_fb_data_offset_install
  13425  * Purpose:
  13426  *     Write the info in udf_spec to hardware
  13427  * Parameters:
  13428  *     unit     - (IN) BCM device number. 
  13429  *     f_dq     - (IN) Data qualifier structure.
  13430  *     tbl_idx  - (IN) FP_UDF_OFFSETm table index.
  13431  *     offset   - (IN) Word offset value.
  13432  * Returns:
  13433  *     BCM_E_PARAM - UDF number or User number out of range
  13434  *     BCM_E_NONE
  13435  * Notes:
  13436  *     Calling function should have unit's lock.
  13437  */
  13438 STATIC int
  13439 _field_fb_data_offset_install(int unit, _field_data_qualifier_t *f_dq, 
  13440                            int tbl_idx, int offset)
  13441 {
  13442     fp_udf_offset_entry_t  tbl_entry;   /* HW table buffer.               */ 
  13443     uint32                 word_offset; /* Offset iterator.               */      
  13444     int                    idx;         /* Data qualifier words iterator. */
  13445     int                    offset_idx;  /* Swapped udf_offsetX number.    */
  13446     uint32                 value;       /* HW buffer value.               */
  13447 
  13448     static soc_field_t  off_field[] = {UDF1_OFFSET0f, UDF1_OFFSET1f, 
  13449                                        UDF1_OFFSET2f, UDF1_OFFSET3f,
  13450                                        UDF2_OFFSET0f, UDF2_OFFSET1f,
  13451                                        UDF2_OFFSET2f, UDF2_OFFSET3f};
  13452 
  13453     static soc_field_t  option_field[] = {UDF1_ADD_IPV4_OPTIONS0f,
  13454                                           UDF1_ADD_IPV4_OPTIONS1f,
  13455                                           UDF1_ADD_IPV4_OPTIONS2f,
  13456                                           UDF1_ADD_IPV4_OPTIONS3f,
  13457                                           UDF2_ADD_IPV4_OPTIONS0f,
  13458                                           UDF2_ADD_IPV4_OPTIONS1f,
  13459                                           UDF2_ADD_IPV4_OPTIONS2f,
  13460                                           UDF2_ADD_IPV4_OPTIONS3f};
  13461 
  13462     static soc_field_t  gre_option_field[] = {UDF1_ADD_GRE_OPTIONS0f,
  13463                                            UDF1_ADD_GRE_OPTIONS1f,
  13464                                            UDF1_ADD_GRE_OPTIONS2f,
  13465                                            UDF1_ADD_GRE_OPTIONS3f,
  13466                                            UDF2_ADD_GRE_OPTIONS0f,
  13467                                            UDF2_ADD_GRE_OPTIONS1f,
  13468                                            UDF2_ADD_GRE_OPTIONS2f,
  13469                                            UDF2_ADD_GRE_OPTIONS3f};
  13470 
  13471     /* Input parameters check. */
  13472     if (NULL == f_dq) {
  13473         return (BCM_E_PARAM);
  13474     }
  13475 
  13476     /* index sanity check. */
  13477     if ((tbl_idx < soc_mem_index_min(unit, FP_UDF_OFFSETm)) || 
  13478         (tbl_idx > soc_mem_index_max(unit, FP_UDF_OFFSETm))) {
  13479         return (BCM_E_PARAM);
  13480     }
  13481 
  13482     /* Read udf offset table enty.*/
  13483     BCM_IF_ERROR_RETURN
  13484         (READ_FP_UDF_OFFSETm(unit, MEM_BLOCK_ANY, tbl_idx, &tbl_entry));
  13485 
  13486     word_offset = (offset < 0) ? 0 : (uint32)offset;
  13487 
  13488     /* Find a proper word to insert the data. */
  13489     for (idx = 0; idx <= _FP_DATA_DATA1_WORD_MAX; idx++) {
  13490         if (0 == (f_dq->hw_bmap & (1 << idx))) {
  13491             continue;
  13492         }
  13493 
  13494         if (word_offset > 31) {
  13495             return BCM_E_PARAM;
  13496         }
  13497 
  13498         offset_idx = idx;
  13499         soc_FP_UDF_OFFSETm_field32_set(unit, &tbl_entry, off_field[offset_idx], 
  13500                                        word_offset);
  13501 
  13502         /* Set the UDFn_ADD_IPV4_OPTIONSm bit accordingly */ 
  13503         value = (f_dq->flags &
  13504             BCM_FIELD_DATA_QUALIFIER_OFFSET_IP4_OPTIONS_ADJUST) ? TRUE : FALSE;
  13505         soc_FP_UDF_OFFSETm_field32_set(unit, &tbl_entry, 
  13506                                        option_field[offset_idx], value);
  13507 
  13508         /* Set the UDFn_ADD_IPV4_OPTIONSm bit accordingly */ 
  13509         if (SOC_MEM_FIELD_VALID(unit, FP_UDF_OFFSETm, UDF1_ADD_GRE_OPTIONS0f)) {
  13510             value = (f_dq->flags &
  13511                      BCM_FIELD_DATA_QUALIFIER_OFFSET_GRE_OPTIONS_ADJUST) ? TRUE : FALSE;
  13512             soc_FP_UDF_OFFSETm_field32_set(unit, &tbl_entry, 
  13513                                            gre_option_field[offset_idx], value);
  13514         }
  13515 
  13516         if (offset >= 0) {
  13517             /*
  13518              * If word_offset is 31, reset the offset to 0 for 126th and 127th byte
  13519              * of the incoming packet 
  13520              */
  13521             if (word_offset == 31) {
  13522                word_offset = 0;
  13523             } else { 
  13524                word_offset++;
  13525             }
  13526         }
  13527     }
  13528 
  13529     /* Write back udf offset table enty.*/
  13530     BCM_IF_ERROR_RETURN
  13531         (WRITE_FP_UDF_OFFSETm(unit, MEM_BLOCK_ALL, tbl_idx, &tbl_entry));
  13532 
  13533     return BCM_E_NONE;
  13534 }
  13535 
  13536 /*
  13537  * Function:
  13538  *      _field_fb_data_qualifier_ethertype_install
  13539  * Purpose:
  13540  *      Add ethertype based offset to data qualifier object.
  13541  * Parameters:
  13542  *      unit       - (IN) bcm device.
  13543  *      f_dq       - (IN) Data qualifier descriptor.
  13544  *      etype_idx  - (IN) Ethertype index. 
  13545  *      etype      - (IN) Ethertype based offset specification.
  13546  * Returns:
  13547  *      BCM_E_XXX
  13548  */
  13549 STATIC int
  13550 _field_fb_data_qualifier_ethertype_install (int unit,
  13551                                          _field_data_qualifier_t *f_dq,
  13552                                          uint8 idx,
  13553                                          _field_data_ethertype_t *etype)
  13554 {
  13555     bcm_port_frametype_t       frametype; /* HW register encoding.       */ 
  13556     int                        idx_mask;  /* Ethertype id index mask.    */ 
  13557     int                        offset;    /* Adjusted word offset.       */ 
  13558     int                        tbl_idx;   /* Udf offset table iterator.  */
  13559     uint16                     l2;        /* L2 packet format.           */
  13560     uint16                     vlan_tag;  /* Vlan packet format.         */
  13561     
  13562     int                        rv;        /* Operation return status.    */
  13563     uint8                      avail = 0;
  13564 
  13565 
  13566     /* Input parameters check. */
  13567     if ((NULL == f_dq) || (NULL == etype)) {
  13568         return (BCM_E_PARAM);
  13569     }
  13570     /* Verify UDF offset memory is valid. */
  13571     if (0 == SOC_MEM_IS_VALID(unit, FP_UDF_OFFSETm)){
  13572         return (BCM_E_UNAVAIL);
  13573     }
  13574 
  13575     switch (etype->l2) {
  13576       case BCM_FIELD_DATA_FORMAT_L2_ETH_II:
  13577           frametype = BCM_PORT_FRAMETYPE_ETHER2;
  13578           break;
  13579       case BCM_FIELD_DATA_FORMAT_L2_SNAP:
  13580           frametype = BCM_PORT_FRAMETYPE_SNAP;
  13581           break;
  13582       case BCM_FIELD_DATA_FORMAT_L2_LLC:
  13583           frametype = BCM_PORT_FRAMETYPE_LLC;
  13584           break;
  13585       default: 
  13586           frametype = 0;
  13587     } 
  13588 
  13589 
  13590     /* Get ethertype index mask. */
  13591     if (SOC_IS_TR_VL(unit)) {
  13592         idx_mask = 0x1f;  /* Ethertype is 5 lower bits of udf index. */
  13593     } else {
  13594         idx_mask = 0x7;   /* Ethertype is 3 lower bits of udf index. */
  13595     }
  13596 
  13597     /* Calculate offset */
  13598     offset = f_dq->offset + etype->relative_offset;
  13599     if ((offset < 0) || ((offset  + f_dq->length) > _FP_DATA_OFFSET_MAX)) {
  13600         return (BCM_E_PARAM);
  13601     }
  13602     offset = ((offset + 2) % 128) / 4; 
  13603 
  13604     /* Update ethertype match register. */
  13605     rv = _bcm_field_fb_udf_ethertype_set(unit, idx, frametype, etype->ethertype);
  13606     BCM_IF_ERROR_RETURN(rv);
  13607 
  13608     for (tbl_idx = soc_mem_index_min(unit, FP_UDF_OFFSETm); 
  13609          tbl_idx <= soc_mem_index_max(unit, FP_UDF_OFFSETm); tbl_idx++) {
  13610 
  13611         if ((tbl_idx & idx_mask) != idx) {
  13612             continue;
  13613         }
  13614 
  13615         /* parse L2 format */
  13616         rv = _field_fb_udf_idx_to_l2_format(unit, tbl_idx, &l2);
  13617         BCM_IF_ERROR_RETURN(rv);
  13618 
  13619         /* Ignore not ethertype based indexes. */
  13620         if (l2 != _BCM_FIELD_DATA_FORMAT_ETHERTYPE) {
  13621             continue;
  13622         }
  13623 
  13624         /* parse vlan tag format */
  13625         rv = _field_fb_udf_idx_to_vlan_format(unit, tbl_idx, &vlan_tag);
  13626         BCM_IF_ERROR_RETURN(rv);
  13627         /* Compare packet vlan tag format. */
  13628         if ((etype->vlan_tag != BCM_FIELD_DATA_FORMAT_VLAN_TAG_ANY) &&
  13629             (etype->vlan_tag != vlan_tag)) {
  13630             continue;
  13631         }
  13632 
  13633         /* Write offset to udf offset table . */
  13634         rv = _field_fb_data_offset_install(unit, f_dq, tbl_idx, offset);
  13635         BCM_IF_ERROR_RETURN(rv);
  13636         avail = 1;
  13637     }
  13638 
  13639     if (avail) {
  13640         return (BCM_E_NONE);
  13641     } else {
  13642         return (BCM_E_UNAVAIL);
  13643     }
  13644 }
  13645 
  13646 /*
  13647  * Function:
  13648  *      _field_data_qualifier_ip_protocol_install
  13649  * Purpose:
  13650  *      Add ip_protocol based offset to data qualifier object.
  13651  * Parameters:
  13652  *      unit        - (IN) bcm device.
  13653  *      f_dq        - (IN) Data qualifier descriptor.
  13654  *      idx         - (IN) Ip protocol index. 
  13655  *      proto       - (IN) Ip protocol based offset specification.
  13656  * Returns:
  13657  *      BCM_E_XXX
  13658  */
  13659 STATIC int
  13660 _field_fb_data_qualifier_ip_protocol_install(int unit,
  13661                                          _field_data_qualifier_t *f_dq,
  13662                                          uint8 idx,
  13663                                          _field_data_protocol_t *proto)
  13664 {
  13665     bcm_field_data_packet_format_t pkt_fmt;
  13666     int                        offset;    /* Adjusted word offset.       */ 
  13667     int                        tbl_idx;   /* Udf offset table iterator.  */
  13668     uint16                     l2;        /* L2 packet format.           */
  13669     uint16                     vlan_tag;  /* Vlan packet format.         */
  13670     int                        rv;        /* Operation return status.    */
  13671     uint8                      avail = 0;
  13672 
  13673      /* Input parameters check. */
  13674      if ((NULL == f_dq) || (NULL == proto)) {
  13675          return (BCM_E_PARAM);
  13676      }
  13677 
  13678      /* Verify UDF offset memory is valid. */
  13679      if (0 == SOC_MEM_IS_VALID(unit, FP_UDF_OFFSETm)){
  13680          return (BCM_E_UNAVAIL);
  13681      }
  13682 
  13683      /* Calculate offset */
  13684      offset = f_dq->offset + proto->relative_offset;
  13685      if ((offset < 0) || ((offset  + f_dq->length) > _FP_DATA_OFFSET_MAX)) {
  13686          return (BCM_E_PARAM);
  13687      }
  13688      offset = ((offset + 2) % 128) / 4; 
  13689 
  13690      /* Update ip_protocol match register. */
  13691      rv = _bcm_field_fb_udf_ipprotocol_set(unit, idx, proto->flags, proto->ip);
  13692      BCM_IF_ERROR_RETURN(rv);
  13693 
  13694      for (tbl_idx = soc_mem_index_min(unit, FP_UDF_OFFSETm); 
  13695           tbl_idx <= soc_mem_index_max(unit, FP_UDF_OFFSETm); tbl_idx++) {
  13696          /* parse L3 tunnel type/ Ip headers  format */
  13697          rv = _field_fb_udf_idx_to_ip_format(unit, tbl_idx, &pkt_fmt);
  13698          if (rv == BCM_E_EMPTY) {
  13699              continue;
  13700          }
  13701          BCM_IF_ERROR_RETURN(rv);
  13702 
  13703          /* Ignore not ip protcol based indexes. */
  13704          if (idx == 0) {
  13705              if (((pkt_fmt.outer_ip != _BCM_FIELD_DATA_FORMAT_IP4_PROTOCOL0) ||
  13706                   (0 == (proto->flags & BCM_FIELD_DATA_FORMAT_IP4))) &&  
  13707                  (((pkt_fmt.outer_ip != _BCM_FIELD_DATA_FORMAT_IP6_PROTOCOL0) ||
  13708                    (0 == (proto->flags & BCM_FIELD_DATA_FORMAT_IP6))))) {
  13709                  continue;
  13710              }
  13711          } else {
  13712              if (((pkt_fmt.outer_ip != _BCM_FIELD_DATA_FORMAT_IP4_PROTOCOL1) ||
  13713                   (0 == (proto->flags & BCM_FIELD_DATA_FORMAT_IP4))) &&  
  13714                  (((pkt_fmt.outer_ip != _BCM_FIELD_DATA_FORMAT_IP6_PROTOCOL1) ||
  13715                    (0 == (proto->flags & BCM_FIELD_DATA_FORMAT_IP6))))) {
  13716                  continue;
  13717              }
  13718          }
  13719 
  13720         /* parse l2 format */
  13721         rv = _field_fb_udf_idx_to_l2_format(unit, tbl_idx, &l2);
  13722         if (rv == BCM_E_EMPTY) {
  13723             continue;
  13724         }
  13725         BCM_IF_ERROR_RETURN(rv);
  13726         /* Compare packet l2 format. */
  13727         if ((proto->l2  != BCM_FIELD_DATA_FORMAT_L2_ANY) &&
  13728             (proto->l2  != l2)) {
  13729             continue;
  13730         }
  13731 
  13732         /* parse vlan tag format */
  13733         rv = _field_fb_udf_idx_to_vlan_format(unit, tbl_idx, &vlan_tag);
  13734         if (rv == BCM_E_EMPTY) {
  13735             continue;
  13736         }
  13737         BCM_IF_ERROR_RETURN(rv);
  13738         /* Compare packet vlan tag format. */
  13739         if ((proto->vlan_tag != BCM_FIELD_DATA_FORMAT_VLAN_TAG_ANY) &&
  13740             (proto->vlan_tag != vlan_tag)) {
  13741             continue;
  13742         }
  13743 
  13744         /* Write offset to udf offset table . */
  13745         rv = _field_fb_data_offset_install(unit, f_dq, tbl_idx, offset);
  13746         BCM_IF_ERROR_RETURN(rv);
  13747         avail = 1;
  13748     }
  13749 
  13750     if (avail) {
  13751         return (BCM_E_NONE);
  13752     } else {
  13753         return (BCM_E_UNAVAIL);
  13754     }
  13755 }
  13756 
  13757 
  13758 /*
  13759  * Function:
  13760  *      _field_fb_packet_format_is_subset
  13761  * Purpose:
  13762  *      Check if master packet format is superset of 
  13763  *      subset packet format.
  13764  * Parameters:
  13765  *      unit       - (IN) Bcm device number.
  13766  *      master     - (IN) Superset packet format.
  13767  *      subset     - (IN) Subset packet format.
  13768  *      cmp_result - (OUT)Comparison result.
  13769  * Returns:
  13770  *      BCM_E_XXX
  13771  */
  13772 STATIC int
  13773 _field_fb_packet_format_is_subset(int unit, 
  13774                                   bcm_field_data_packet_format_t *master, 
  13775                                   bcm_field_data_packet_format_t *subset, 
  13776                                   uint8 *cmp_result) 
  13777 {
  13778     /* Input parameters check. */
  13779     if ((NULL == master) || (NULL == subset) || (NULL == cmp_result)) {
  13780         return (BCM_E_PARAM);
  13781     }
  13782 
  13783     /* Compare packet l2 format. */
  13784     if ((master->l2 != BCM_FIELD_DATA_FORMAT_L2_ANY) &&
  13785         (master->l2 != subset->l2)) {
  13786         *cmp_result = FALSE;
  13787         return (BCM_E_NONE);
  13788     }
  13789 
  13790     /* Compare packet vlan tag format. */
  13791     if ((master->vlan_tag  != BCM_FIELD_DATA_FORMAT_VLAN_TAG_ANY) &&
  13792         (master->vlan_tag != subset->vlan_tag)) {
  13793         *cmp_result = FALSE;
  13794         return (BCM_E_NONE);
  13795     }
  13796 
  13797     /* Compare packet tunnel type. */
  13798     if ((master->tunnel != BCM_FIELD_DATA_FORMAT_TUNNEL_ANY) &&
  13799         (master->tunnel != subset->tunnel)) {
  13800         *cmp_result = FALSE;
  13801         return (BCM_E_NONE);
  13802     }
  13803 
  13804     /* Compare outer ip header. */
  13805     if ((master->tunnel != BCM_FIELD_DATA_FORMAT_TUNNEL_MPLS) &&  
  13806         (master->outer_ip != BCM_FIELD_DATA_FORMAT_IP_ANY) && 
  13807         (master->outer_ip != subset->outer_ip)) {
  13808         *cmp_result = FALSE;
  13809         return (BCM_E_NONE);
  13810     }
  13811 
  13812     /* Compare inner ip header. */
  13813     if ((master->tunnel != BCM_FIELD_DATA_FORMAT_TUNNEL_NONE) && 
  13814         (master->tunnel != BCM_FIELD_DATA_FORMAT_TUNNEL_MPLS) &&
  13815         (master->inner_ip != BCM_FIELD_DATA_FORMAT_IP_ANY) &&
  13816         (master->inner_ip != subset->inner_ip)) {
  13817         *cmp_result = FALSE;
  13818         return (BCM_E_NONE);
  13819     }
  13820 
  13821     /* Compare number of mpls labels. */
  13822     if ((master->tunnel == BCM_FIELD_DATA_FORMAT_TUNNEL_MPLS) && 
  13823         (master->mpls != BCM_FIELD_DATA_FORMAT_MPLS_ANY) &&
  13824         (master->mpls != subset->mpls)) {
  13825         *cmp_result = FALSE;
  13826         return (BCM_E_NONE);
  13827     }
  13828     *cmp_result = TRUE;
  13829     return (BCM_E_NONE);
  13830 }
  13831 
  13832 /*
  13833  * Function:
  13834  *      _field_fb_packet_format_tunnel_shim_size_get
  13835  * Purpose:
  13836  *      Get  tunnel shim size  based on packet
  13837  *      format descriptor.
  13838  * Parameters:
  13839  *      unit       - (IN) Bcm device number.
  13840  *      pkt_fmt    - (IN) Packet format.
  13841  *      *size      - (OUT)Outer L3 + tunnel shim size.
  13842  * Returns:
  13843  *      BCM_E_XXX
  13844  * NOTE: 
  13845  *      This api calculates basic header size. 
  13846  *      Gre Options... are not handled here.
  13847  *      Please set proper FIELD_DATA_QUALIFIER_XXX options adjust flag.
  13848  */
  13849 STATIC int
  13850 _field_fb_packet_format_tunnel_shim_size_get(int unit, 
  13851                                bcm_field_data_packet_format_t *pkt_fmt, 
  13852                                uint8 *size) 
  13853 {
  13854     /* Input parameters check. */
  13855     if ((NULL == pkt_fmt) || (NULL == size)) {
  13856         return (BCM_E_PARAM);
  13857     }
  13858 
  13859     if (BCM_FIELD_DATA_FORMAT_TUNNEL_GRE == pkt_fmt->tunnel) { 
  13860         *size = 4;  /* Basic (no key/no checksum/no options). */
  13861     } else {
  13862         *size = 0;  /* IPv4 header size. */
  13863     }
  13864     return (BCM_E_NONE);
  13865 }
  13866 
  13867 /*
  13868  * Function:
  13869  *      _field_fb_packet_format_ip_size_get
  13870  * Purpose:
  13871  *      Get outer l3 header + tunnel shim size  based on packet
  13872  *      format descriptor.
  13873  * Parameters:
  13874  *      unit       - (IN) Bcm device number.
  13875  *      ip         - (IN) BCM_FIELD_DATA_FORMAT_IP_XXX.
  13876  *      *size      - (OUT)Outer L3 + tunnel shim size.
  13877  * Returns:
  13878  *      BCM_E_XXX
  13879  * NOTE: 
  13880  *      This api calculates basic header size. 
  13881  *      IP options/Extension headers  ... are not handled here.
  13882  *      Please set proper FIELD_DATA_QUALIFIER_XXX options adjust flag.
  13883  */
  13884 STATIC int
  13885 _field_fb_packet_format_ip_size_get(int unit, uint16 ip, uint8 *size) 
  13886 {
  13887     /* Input parameters check. */
  13888     if (NULL == size) {
  13889         return (BCM_E_PARAM);
  13890     }
  13891 
  13892     if (BCM_FIELD_DATA_FORMAT_IP6 == ip) {
  13893         *size = 40;  /* Ipv6 header size */
  13894     } else if (BCM_FIELD_DATA_FORMAT_IP4 == ip) {
  13895         *size = 20;  /* IPv4 header size. */
  13896     } else if (BCM_FIELD_DATA_FORMAT_IP_NONE == ip) {
  13897         *size = 0;
  13898     } else {
  13899         return (BCM_E_INTERNAL);
  13900     }
  13901     return (BCM_E_NONE);
  13902 }
  13903 
  13904 /*
  13905  * Function:
  13906  *      _field_fb_packet_format_mpls_labels_size_get
  13907  * Purpose:
  13908  *      Get mpls labels size based on packet format descriptor.
  13909  * Parameters:
  13910  *      unit       - (IN) Bcm device number.
  13911  *      pkt_fmt    - (IN) Packet format.
  13912  *      *size      - (OUT)mpls labels size.
  13913  * Returns:
  13914  *      BCM_E_XXX
  13915  */
  13916 STATIC int
  13917 _field_fb_packet_format_mpls_labels_size_get(int unit, 
  13918                                bcm_field_data_packet_format_t *pkt_fmt, 
  13919                                uint8 *size) 
  13920 {
  13921     /* Input parameters check. */
  13922     if ((NULL == pkt_fmt) || (NULL == size)) {
  13923         return (BCM_E_PARAM);
  13924     }
  13925 
  13926     if (BCM_FIELD_DATA_FORMAT_TUNNEL_MPLS != pkt_fmt->tunnel) {
  13927         *size = 0;
  13928     } else if (BCM_FIELD_DATA_FORMAT_MPLS_ONE_LABEL == pkt_fmt->mpls) {
  13929         *size = 4;
  13930     } else if (BCM_FIELD_DATA_FORMAT_MPLS_TWO_LABELS == pkt_fmt->mpls) {
  13931         *size = 8;
  13932     }  else {
  13933         return (BCM_E_INTERNAL);
  13934     }
  13935     return (BCM_E_NONE);
  13936 }
  13937 
  13938 /*
  13939  * Function:
  13940  *      _field_fb_packet_format_l2_header_size_get
  13941  * Purpose:
  13942  *      Get l2 header size based on packet format descriptor.
  13943  * Parameters:
  13944  *      unit       - (IN) Bcm device number.
  13945  *      pkt_fmt    - (IN) Packet format.
  13946  *      *size      - (OUT)L2 header size.
  13947  * Returns:
  13948  *      BCM_E_XXX
  13949  */
  13950 STATIC int
  13951 _field_fb_packet_format_l2_header_size_get(int unit, 
  13952                                bcm_field_data_packet_format_t *pkt_fmt, 
  13953                                uint8 *size) 
  13954 {
  13955     uint8 tmp;
  13956 
  13957     /* Input parameters check. */
  13958     if ((NULL == pkt_fmt) || (NULL == size)) {
  13959         return (BCM_E_PARAM);
  13960     }
  13961 
  13962     switch(pkt_fmt->l2) {
  13963       case BCM_FIELD_DATA_FORMAT_L2_ETH_II:
  13964       case BCM_FIELD_DATA_FORMAT_L2_LLC:
  13965           tmp = 14;
  13966           break;
  13967       case BCM_FIELD_DATA_FORMAT_L2_SNAP:
  13968           tmp = 22;
  13969           break;
  13970       default:
  13971           return (BCM_E_INTERNAL);
  13972     }
  13973 
  13974     switch(pkt_fmt->vlan_tag) {
  13975       case BCM_FIELD_DATA_FORMAT_VLAN_NO_TAG:
  13976           break;
  13977       case BCM_FIELD_DATA_FORMAT_VLAN_SINGLE_TAGGED:
  13978           tmp += 4;  
  13979           break;
  13980       case BCM_FIELD_DATA_FORMAT_VLAN_DOUBLE_TAGGED:
  13981           tmp += 8;
  13982           break;
  13983       default:
  13984           return (BCM_E_INTERNAL);
  13985     }
  13986     *size = tmp;
  13987     return (BCM_E_NONE);
  13988 }
  13989 
  13990 /*
  13991  * Function:
  13992  *      _field_fb_packet_format_offset_adjust
  13993  * Purpose:
  13994  *      Calculate word offset for data qualifier 
  13995  *      based on offset based, relative offset & master offset.
  13996  * Parameters:
  13997  *      unit       - (IN) Bcm device number.
  13998  *      f_dq       - (IN) Data qualifier descriptor.
  13999  *      pkt_fmt    - (IN) Installed packet format.
  14000  *      offset     - (OUT)Final word offset.
  14001  * Returns:
  14002  *      BCM_E_XXX
  14003  */
  14004 STATIC int
  14005 _field_fb_packet_format_offset_adjust(int unit, 
  14006                                _field_data_qualifier_t *f_dq, 
  14007                                bcm_field_data_packet_format_t *pkt_fmt, 
  14008                                int *offset) 
  14009 {
  14010     int tmp_offset;         /* Local calculation variable. */
  14011     uint8 size;             /* Various headers sizes.      */
  14012     int rv;                 /* Operation return status.    */
  14013 
  14014     /* Input parameters check. */
  14015     if ((NULL == f_dq) || (NULL == pkt_fmt) || (NULL == offset)) {
  14016         return (BCM_E_PARAM);
  14017     }
  14018 
  14019     /* Calculate offset */
  14020     tmp_offset = f_dq->offset + pkt_fmt->relative_offset;
  14021 
  14022     if (tmp_offset == _FP_DATA_OFFSET_MAX - 2) {
  14023         if (f_dq->length > 4) {
  14024             return (BCM_E_PARAM);
  14025         }
  14026     } else if ((tmp_offset < 0) || 
  14027                (tmp_offset + f_dq->length) >= _FP_DATA_OFFSET_MAX) {
  14028         return (BCM_E_PARAM);
  14029     }
  14030 
  14031     switch (f_dq->offset_base) {
  14032       case bcmFieldDataOffsetBasePacketStart:
  14033           break;
  14034 
  14035       case bcmFieldDataOffsetBaseOuterL3Header:
  14036           /* a) Add L2 header size. */  
  14037           rv = _field_fb_packet_format_l2_header_size_get(unit, pkt_fmt, &size); 
  14038           BCM_IF_ERROR_RETURN(rv);
  14039           tmp_offset += size;
  14040 
  14041           /* b) Add size of mpls labels. */  
  14042           rv = _field_fb_packet_format_mpls_labels_size_get(unit, pkt_fmt, &size); 
  14043           BCM_IF_ERROR_RETURN(rv);
  14044           tmp_offset += size;
  14045           break;
  14046 
  14047       case bcmFieldDataOffsetBaseInnerL3Header:
  14048           /* a) Add L2 header size. */  
  14049           rv = _field_fb_packet_format_l2_header_size_get(unit, pkt_fmt, &size); 
  14050           BCM_IF_ERROR_RETURN(rv);
  14051           tmp_offset += size;
  14052 
  14053 
  14054           /* b) Add size of outer l3 header . */  
  14055           rv =  _field_fb_packet_format_ip_size_get(unit, pkt_fmt->outer_ip, &size); 
  14056           BCM_IF_ERROR_RETURN(rv);
  14057           tmp_offset += size;
  14058 
  14059           /* c) Add size of GRE shim. */  
  14060           rv =  _field_fb_packet_format_tunnel_shim_size_get(unit, pkt_fmt, &size); 
  14061           BCM_IF_ERROR_RETURN(rv);
  14062           tmp_offset += size;
  14063           break;
  14064 
  14065       case bcmFieldDataOffsetBaseOuterL4Header:
  14066           /* a) Add L2 header size. */  
  14067           rv = _field_fb_packet_format_l2_header_size_get(unit, pkt_fmt, &size); 
  14068           BCM_IF_ERROR_RETURN(rv);
  14069           tmp_offset += size;
  14070 
  14071           /* b) Add size of outer l3 header . */  
  14072           rv =  _field_fb_packet_format_ip_size_get(unit, pkt_fmt->outer_ip, &size); 
  14073           BCM_IF_ERROR_RETURN(rv);
  14074           tmp_offset += size;
  14075           break;
  14076 
  14077       case bcmFieldDataOffsetBaseInnerL4Header:
  14078           /* a) Add L2 header size. */  
  14079           rv = _field_fb_packet_format_l2_header_size_get(unit, pkt_fmt, &size); 
  14080           BCM_IF_ERROR_RETURN(rv);
  14081           tmp_offset += size;
  14082 
  14083 
  14084           /* b) Add size of outer l3 header . */  
  14085           rv =  _field_fb_packet_format_ip_size_get(unit, pkt_fmt->outer_ip, &size); 
  14086           BCM_IF_ERROR_RETURN(rv);
  14087           tmp_offset += size;
  14088 
  14089           /* c) Add size of GRE shim. */  
  14090           rv =  _field_fb_packet_format_tunnel_shim_size_get(unit, pkt_fmt, &size); 
  14091           BCM_IF_ERROR_RETURN(rv);
  14092           tmp_offset += size;
  14093 
  14094           /* d) Add size of inner l3 header . */  
  14095           rv =  _field_fb_packet_format_ip_size_get(unit, pkt_fmt->inner_ip, &size); 
  14096           BCM_IF_ERROR_RETURN(rv);
  14097           tmp_offset += size;
  14098           break;
  14099 
  14100       case bcmFieldDataOffsetBaseHigigHeader:
  14101           if (SOC_IS_FB(unit) ||
  14102               SOC_IS_HB_GW(unit) ||
  14103               SOC_IS_SC_CQ(unit) ||
  14104               SOC_IS_ENDURO(unit) ||
  14105               soc_feature(unit, soc_feature_field_udf_offset_hg_114B)) {
  14106               /* Hardcoded Higig header offset is 114 bytes. */  
  14107               tmp_offset += 0x72;
  14108           } else {
  14109               /* Hardcoded Higig header length is 12 bytes. */  
  14110               tmp_offset += 0xc;
  14111           }
  14112           break;
  14113 
  14114       case bcmFieldDataOffsetBaseHigig2Header:
  14115           if (SOC_IS_FB(unit) ||
  14116               SOC_IS_HB_GW(unit) ||
  14117               SOC_IS_SC_CQ(unit) ||
  14118               SOC_IS_ENDURO(unit) ||
  14119               soc_feature(unit, soc_feature_field_udf_offset_hg2_110B)) {
  14120               /* Hardcoded Higig2 header offset is 110 bytes. */  
  14121               tmp_offset += 0x6e;
  14122           } else {
  14123               /* Hardcoded Higig2 header length is 16 bytes. */  
  14124               tmp_offset += 0x10;
  14125           }  
  14126           break;
  14127 
  14128       default:
  14129           return (BCM_E_PARAM);
  14130     }
  14131 
  14132     *offset = ((tmp_offset + 2) % 128) / 4; 
  14133     return (BCM_E_NONE);
  14134 }
  14135 
  14136 
  14137 /*
  14138  * Function:
  14139  *      _bcm_field_fb_data_qualifier_packet_format_add
  14140  * Purpose:
  14141  *      Add packet format based offset to data qualifier object.
  14142  * Parameters:
  14143  *      unit          - (IN) Bcm device number.
  14144  *      qual_id       - (IN) Data qualifier id.
  14145  *      packet_format - (IN) Packet format specification.                 
  14146  * Returns:
  14147  *      BCM_E_XXX
  14148  */
  14149 int
  14150 _bcm_field_fb_data_qualifier_packet_format_add(int unit,  int qual_id,
  14151                                 bcm_field_data_packet_format_t *packet_format)
  14152 {
  14153     bcm_field_data_packet_format_t pkt_fmt;   /* Packet format iterator.     */
  14154     _field_data_qualifier_t        *f_dq;     /* Data qualifier descriptor.  */
  14155     _field_stage_t                 *stage_fc; /* Stage field control.        */
  14156     uint8                          cmp_result;/* Packet format compare result*/ 
  14157     int                            offset = 0;/* Adjusted word offset.       */ 
  14158     int                            idx;       /* Udf offset table iterator.  */
  14159     int                            rv;        /* Operation return status.    */
  14160     uint8                          avail = 0;
  14161 
  14162     /* Input parameters check. */
  14163     if ((NULL == packet_format)) {
  14164         return (BCM_E_PARAM);
  14165     }
  14166 
  14167     /* Verify UDF offset memory is valid. */
  14168     if (0 == SOC_MEM_IS_VALID(unit, FP_UDF_OFFSETm)){
  14169         return (BCM_E_UNAVAIL);
  14170     }
  14171 
  14172     /* Get stage field control structure. */
  14173     rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc); 
  14174     BCM_IF_ERROR_RETURN(rv);
  14175 
  14176     /* Get data qualifier info. */
  14177     rv = _bcm_field_data_qualifier_get(unit, stage_fc, qual_id, &f_dq);
  14178     BCM_IF_ERROR_RETURN(rv);
  14179 
  14180 
  14181     for (idx = soc_mem_index_min(unit, FP_UDF_OFFSETm); 
  14182          idx <= soc_mem_index_max(unit, FP_UDF_OFFSETm); idx++) {
  14183         sal_memset(&pkt_fmt, 0, sizeof (bcm_field_data_packet_format_t));
  14184 
  14185         /* Get packet format associated with an index. */
  14186         rv = _field_fb_udf_offset_idx_to_packet_format(unit, idx, &pkt_fmt);
  14187         if (BCM_FAILURE(rv)) {
  14188             if (rv == BCM_E_EMPTY) {
  14189                 /* Unused/ethertype/ip protocol  table index. */
  14190                 continue;
  14191             }
  14192             return (rv);
  14193         }
  14194 
  14195         /* Check that idx packet format is subset of installed packet format. */
  14196         rv = _field_fb_packet_format_is_subset(unit, packet_format, 
  14197                                                &pkt_fmt, &cmp_result);
  14198         BCM_IF_ERROR_RETURN(rv);
  14199         if (FALSE == cmp_result) {
  14200             continue;
  14201         }
  14202 
  14203         /* Calculate base offset adjusted offset. */
  14204         rv = _field_fb_packet_format_offset_adjust(unit, f_dq, 
  14205                                                    packet_format, &offset);
  14206         BCM_IF_ERROR_RETURN(rv);
  14207 
  14208 
  14209         /* Write offset to udf offset table . */
  14210         rv = _field_fb_data_offset_install(unit, f_dq, idx, offset);
  14211         BCM_IF_ERROR_RETURN(rv);
  14212         avail = 1;
  14213 
  14214     }
  14215 
  14216     if (avail) {
  14217         return (BCM_E_NONE);
  14218     } else {
  14219         return (BCM_E_UNAVAIL);
  14220     }
  14221 }
  14222 
  14223 /*
  14224  * Function:
  14225  *      _bcm_field_fb_data_qualifier_packet_format_delete
  14226  * Purpose:
  14227  *      Remove packet format based offset to data qualifier object.
  14228  * Parameters:
  14229  *      unit          - (IN) Bcm device number.
  14230  *      qual_id       - (IN) Data qualifier id.
  14231  *      packet_format - (IN) Packet format specification.                 
  14232  * Returns:
  14233  *      BCM_E_XXX
  14234  */
  14235 int
  14236 _bcm_field_fb_data_qualifier_packet_format_delete(int unit,  int qual_id,
  14237                                 bcm_field_data_packet_format_t *packet_format)
  14238 {
  14239     bcm_field_data_packet_format_t pkt_fmt;   /* Packet format iterator.     */
  14240     _field_data_qualifier_t        *f_dq;     /* Data qualifier descriptor.  */
  14241     _field_stage_t                 *stage_fc; /* Stage field control.        */
  14242     uint8                          cmp_result;/* Packet format compare result*/ 
  14243     int                            idx;       /* Udf offset table iterator.  */
  14244     int                            rv;        /* Operation return status.    */
  14245 
  14246     /* Input parameters check. */
  14247     if ((NULL == packet_format)) {
  14248         return (BCM_E_PARAM);
  14249     }
  14250 
  14251     /* Verify UDF offset memory is valid. */
  14252     if (0 == SOC_MEM_IS_VALID(unit, FP_UDF_OFFSETm)){
  14253         return (BCM_E_UNAVAIL);
  14254     }
  14255 
  14256     /* Get stage field control structure. */
  14257     rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc); 
  14258     BCM_IF_ERROR_RETURN(rv);
  14259 
  14260     /* Get data qualifier info. */
  14261     rv = _bcm_field_data_qualifier_get(unit, stage_fc, qual_id, &f_dq);
  14262     BCM_IF_ERROR_RETURN(rv);
  14263 
  14264 
  14265     for (idx = soc_mem_index_min(unit, FP_UDF_OFFSETm); 
  14266          idx <= soc_mem_index_max(unit, FP_UDF_OFFSETm); idx++) {
  14267         sal_memset(&pkt_fmt, 0, sizeof (bcm_field_data_packet_format_t));
  14268 
  14269         /* Get packet format associated with an index. */
  14270         rv = _field_fb_udf_offset_idx_to_packet_format(unit, idx, &pkt_fmt);
  14271         if (BCM_FAILURE(rv)) {
  14272             if (rv == BCM_E_EMPTY) {
  14273                 /* Unused/ethertype/ip protocol  table index. */
  14274                 continue;
  14275             }
  14276             return (rv);
  14277         }
  14278 
  14279         /* Check that idx packet format is subset of installed packet format. */
  14280         rv = _field_fb_packet_format_is_subset(unit, packet_format, &pkt_fmt,
  14281                                             &cmp_result);
  14282         BCM_IF_ERROR_RETURN(rv);
  14283         if (FALSE == cmp_result) {
  14284             continue;
  14285         }
  14286 
  14287         /* Write offset to udf offset table . */
  14288         rv = _field_fb_data_offset_install(unit, f_dq, idx, -1);
  14289         BCM_IF_ERROR_RETURN(rv);
  14290 
  14291     }
  14292     return (BCM_E_NONE);
  14293 }
  14294 
  14295 /*
  14296  * Function:
  14297  *      _field_fb_data_qualifier_ethertype_add
  14298  * Purpose:
  14299  *      Add ethertype based offset to data qualifier object.
  14300  * Parameters:
  14301  *      unit       - (IN) bcm device.
  14302  *      qual_id    - (IN) Data qualifier id.
  14303  *      etype      - (IN) Ethertype based offset specification.
  14304  * Returns:
  14305  *      BCM_E_XXX
  14306  */
  14307 int
  14308 _field_fb_data_qualifier_ethertype_add(int unit,  int qual_id,
  14309                                            bcm_field_data_ethertype_t *etype)
  14310 {
  14311     _field_data_ethertype_t    *etype_ptr;/* Ether type pointer.         */
  14312     _field_stage_t             *stage_fc; /* Stage field control.        */
  14313     _field_data_qualifier_t    *f_dq;     /* Data qualifier descriptor.  */
  14314     int                        idx;       /* Ethertype allocation index. */
  14315     int                        unused_idx;/* Unused ethertype index.     */
  14316     int                        rv;        /* Operation return status.    */
  14317 
  14318     /* Input parameters check. */
  14319     if ((NULL == etype)) {
  14320         return (BCM_E_PARAM);
  14321     }
  14322 
  14323     /* Get stage field control structure. */
  14324     rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc); 
  14325     BCM_IF_ERROR_RETURN(rv);
  14326 
  14327     /* Get data qualifier info. */
  14328     rv = _bcm_field_data_qualifier_get(unit, stage_fc, qual_id,  &f_dq);
  14329     BCM_IF_ERROR_RETURN(rv);
  14330 
  14331     /*
  14332      *  Ethertype based qualifier offset must be 
  14333      *  from the beginning of the packet. 
  14334      */
  14335     if (f_dq->offset_base != bcmFieldDataOffsetBasePacketStart) {
  14336         return (BCM_E_UNAVAIL);
  14337     }
  14338 
  14339     unused_idx = -1;
  14340     for (idx = 0; idx < _FP_DATA_ETHERTYPE_MAX; idx++) {
  14341         etype_ptr = stage_fc->data_ctrl->etype + idx;
  14342         /* Find an entry with identical ethertype/l2format. */
  14343             if ((etype->l2 == etype_ptr->l2) &&
  14344                 (etype->ethertype == etype_ptr->ethertype) &&
  14345                 (etype_ptr->ref_count > 0)) {
  14346                 etype_ptr->ref_count++;
  14347                 rv = BCM_E_NONE;
  14348                 break;
  14349             }
  14350 
  14351         /* Find unused entry. */
  14352         if ((-1 == unused_idx) && (0 == etype_ptr->ref_count)) {
  14353             unused_idx = idx;
  14354         }
  14355     }
  14356 
  14357         if (_FP_DATA_ETHERTYPE_MAX == idx) {
  14358             /* No match found -> check for unused entry. */
  14359             if (-1 == unused_idx) {
  14360                 return (BCM_E_RESOURCE);
  14361             }
  14362             idx = unused_idx;
  14363             etype_ptr = stage_fc->data_ctrl->etype + idx;
  14364             etype_ptr->ref_count = 1;
  14365         }
  14366         etype_ptr->ethertype = etype->ethertype;
  14367         etype_ptr->l2 = etype->l2;
  14368         etype_ptr->vlan_tag  = etype->vlan_tag;
  14369         etype_ptr->relative_offset = etype->relative_offset;
  14370 
  14371         rv = _field_fb_data_qualifier_ethertype_install(unit, f_dq, 
  14372                                                         idx, etype_ptr);
  14373 
  14374     return (rv);
  14375 }
  14376 
  14377 /*
  14378  * Function:
  14379  *      _field_fb_data_qualifier_ethertype_delete
  14380  * Purpose:
  14381  *      Remove ethertype based offset from data qualifier object.
  14382  * Parameters:
  14383  *      unit       - (IN) bcm device.
  14384  *      qual_id    - (IN) Data qualifier id.
  14385  *      etype      - (IN) Ethertype based offset specification. 
  14386  * Returns:
  14387  *      BCM_E_XXX
  14388  */
  14389 int
  14390 _field_fb_data_qualifier_ethertype_delete(int unit,  int qual_id,
  14391                                           bcm_field_data_ethertype_t *etype)
  14392 {
  14393     _field_stage_t             *stage_fc; /* Stage field control.        */
  14394     _field_data_qualifier_t    *f_dq;     /* Data qualifier descriptor.  */
  14395     int                        idx;       /* Ethertype allocation index. */
  14396     int                        offset_idx;/* UDF offset. */
  14397     int                        rv;        /* Operation return status.    */
  14398     _field_data_ethertype_t    *etype_ptr = NULL;/* Ether type pointer.  */
  14399     int                        tbl_idx;   /* Udf offset table iterator.  */
  14400     int                        idx_mask;  /* Ethertype id index mask.    */
  14401     uint16                     l2 = 0;    /* L2 packet format.           */
  14402     uint16                     vlan_tag;  /* Vlan packet format.         */
  14403     fp_udf_offset_entry_t      tbl_entry;   /* HW table buffer.           */
  14404     int                        match_found = 0;
  14405 
  14406     static soc_field_t  off_field[] = {UDF1_OFFSET0f, UDF1_OFFSET1f,
  14407                                        UDF1_OFFSET2f, UDF1_OFFSET3f,
  14408                                        UDF2_OFFSET0f, UDF2_OFFSET1f,
  14409                                        UDF2_OFFSET2f, UDF2_OFFSET3f};
  14410 
  14411     /* Input parameters check. */
  14412     if ((NULL == etype)) {
  14413         return (BCM_E_PARAM);
  14414     }
  14415 
  14416     /* Get ethertype index mask. */
  14417     if (SOC_IS_TR_VL(unit)) {
  14418         idx_mask = 0x1f;  /* Ethertype is 5 lower bits of udf index. */
  14419     } else {
  14420         idx_mask = 0x7;   /* Ethertype is 3 lower bits of udf index. */
  14421     }
  14422 
  14423     /* Get stage field control structure. */
  14424     rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc); 
  14425     BCM_IF_ERROR_RETURN(rv);
  14426 
  14427     /* Get data qualifier info. */
  14428     rv = _bcm_field_data_qualifier_get(unit, stage_fc, qual_id,  &f_dq);
  14429     BCM_IF_ERROR_RETURN(rv);
  14430 
  14431     for (idx = 0; idx < _FP_DATA_ETHERTYPE_MAX; idx++) {
  14432         etype_ptr = stage_fc->data_ctrl->etype + idx;
  14433 
  14434         if (etype_ptr->ref_count <= 0) {
  14435             continue;
  14436         }
  14437 
  14438         /* Find an entry with identical ethertype/l2format. */
  14439             if ((etype->l2 == etype_ptr->l2) &&
  14440                 (etype->ethertype == etype_ptr->ethertype)) {
  14441                 for (tbl_idx = soc_mem_index_min(unit, FP_UDF_OFFSETm); 
  14442                     tbl_idx <= soc_mem_index_max(unit, FP_UDF_OFFSETm); tbl_idx++) {
  14443             
  14444                 if ((tbl_idx & idx_mask) != idx) {
  14445                         continue;
  14446                     }
  14447             
  14448                     /* parse L2 format */
  14449                     rv = _field_fb_udf_idx_to_l2_format(unit, tbl_idx, &l2);
  14450                     BCM_IF_ERROR_RETURN(rv);
  14451             
  14452                     /* Ignore not ethertype based indexes. */
  14453                     if (l2 != _BCM_FIELD_DATA_FORMAT_ETHERTYPE) {
  14454                         continue;
  14455                     }
  14456             
  14457                     /* parse vlan tag format */
  14458                     rv = _field_fb_udf_idx_to_vlan_format(unit, tbl_idx, &vlan_tag);
  14459                     BCM_IF_ERROR_RETURN(rv);
  14460                     /* Compare packet vlan tag format. */
  14461                     if (etype->vlan_tag != vlan_tag) {
  14462                         continue;
  14463                     }
  14464 
  14465                     /* Read udf offset table enty.*/
  14466                     BCM_IF_ERROR_RETURN
  14467                         (READ_FP_UDF_OFFSETm(unit, MEM_BLOCK_ANY, tbl_idx, &tbl_entry));
  14468 
  14469                 /* Check whether the entry has valid data or not.*/
  14470                 for (offset_idx = 0; offset_idx < _FP_DATA_DATA1_WORD_MAX ;
  14471                                                               offset_idx++) {
  14472                     if ((soc_FP_UDF_OFFSETm_field32_get(
  14473                          unit, &tbl_entry, off_field[offset_idx])) != 0) { 
  14474                        match_found = 1;
  14475                        break;
  14476                     }
  14477                 }
  14478 
  14479                 if (!match_found) {
  14480                         continue;
  14481                     }
  14482 
  14483                     etype_ptr->ref_count--;            
  14484                     if (etype_ptr->ref_count >= 0) { 
  14485                         /* Write offset to udf offset table . */
  14486                         rv = _field_fb_data_offset_install(unit, f_dq, tbl_idx, -1);
  14487                         BCM_IF_ERROR_RETURN(rv);
  14488                         if (etype_ptr->ref_count == 0) {
  14489                             /* Update ethertype match register. */
  14490                             rv = _bcm_field_fb_udf_ethertype_set(unit, idx, 0, 0);
  14491                             BCM_IF_ERROR_RETURN(rv);
  14492                         }
  14493                         break;
  14494                     }
  14495                 }
  14496             if (match_found) {
  14497                 break;
  14498             }
  14499         }
  14500     }
  14501 
  14502     if (_FP_DATA_ETHERTYPE_MAX == idx) {
  14503         return (BCM_E_NOT_FOUND);
  14504     }
  14505 
  14506     return (rv);
  14507 }
  14508 
  14509 /*
  14510  * Function:
  14511  *      _bcm_field_fb_data_qualifier_ip_protocol_add
  14512  * Purpose:
  14513  *      Add ip_protocol based offset to data qualifier object.
  14514  * Parameters:
  14515  *      unit       - (IN) Bcm device number. 
  14516  *      qual_id    - (IN) Data qualifier id.
  14517  *      ip_protocol- (IN) Ip protocol based offset specification.
  14518  * Returns:
  14519  *      BCM_E_XXX
  14520  */
  14521 int
  14522 _bcm_field_fb_data_qualifier_ip_protocol_add(int unit,  int qual_id,
  14523                                 bcm_field_data_ip_protocol_t *ip_protocol)
  14524 {
  14525     _field_data_protocol_t     *proto_ptr;/* Ip protocol pointer.        */
  14526     _field_data_qualifier_t    *f_dq;     /* Data qualifier descriptor.  */
  14527     _field_stage_t             *stage_fc; /* Stage field control.        */
  14528     int                        unused_idx;/* Unused ip_protocol index.   */
  14529     int                        idx;       /* Ethertype allocation index. */
  14530     int                        flags;     /* Ip protocol version flags.  */
  14531     int                        rv;        /* Operation return status.    */
  14532 
  14533     /* Input parameters check. */
  14534     if ((NULL == ip_protocol)) {
  14535         return (BCM_E_PARAM);
  14536     }
  14537 
  14538     /* Get stage field control structure. */
  14539     rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc); 
  14540     BCM_IF_ERROR_RETURN(rv);
  14541 
  14542     /* Get data qualifier info. */
  14543     rv = _bcm_field_data_qualifier_get(unit, stage_fc, qual_id, &f_dq);
  14544     BCM_IF_ERROR_RETURN(rv);
  14545 
  14546     unused_idx = -1;
  14547     flags = ip_protocol->flags & 
  14548         (BCM_FIELD_DATA_FORMAT_IP4 | BCM_FIELD_DATA_FORMAT_IP6);
  14549     for (idx = 0; idx < _FP_DATA_IP_PROTOCOL_MAX; idx++) {
  14550         proto_ptr = stage_fc->data_ctrl->ip + idx;
  14551 
  14552         /* Find an entry with identical ip_protocol. */
  14553         if ((ip_protocol->ip == proto_ptr->ip) &&
  14554             ((proto_ptr->ip4_ref_count > 0) || 
  14555              ((proto_ptr->ip6_ref_count > 0)))) {
  14556             break; 
  14557         }
  14558         /* Find unused entry. */
  14559         if ((-1 == unused_idx) && 
  14560             (0 == proto_ptr->ip4_ref_count) && 
  14561             (0 == proto_ptr->ip6_ref_count)) {
  14562             unused_idx = idx;
  14563         }
  14564     }
  14565     if (_FP_DATA_IP_PROTOCOL_MAX == idx) {
  14566         /* No match found -> check for unused entry. */
  14567         if (-1 == unused_idx) {
  14568             return (BCM_E_RESOURCE);
  14569         }
  14570         idx = unused_idx;
  14571     }
  14572 
  14573     proto_ptr = stage_fc->data_ctrl->ip + idx;
  14574     /* Increment reference count. */
  14575     if (flags & BCM_FIELD_DATA_FORMAT_IP4) {
  14576         proto_ptr->ip4_ref_count++;
  14577     } 
  14578     if (flags & BCM_FIELD_DATA_FORMAT_IP6) {
  14579         proto_ptr->ip6_ref_count++;
  14580     } 
  14581 
  14582     /* Check if reinstall is required. */
  14583     proto_ptr->ip = ip_protocol->ip;
  14584     proto_ptr->l2 = ip_protocol->l2;
  14585     proto_ptr->vlan_tag = ip_protocol->vlan_tag;
  14586     proto_ptr->flags = flags;
  14587     proto_ptr->relative_offset = ip_protocol->relative_offset;
  14588 
  14589     rv =  _field_fb_data_qualifier_ip_protocol_install(unit, f_dq,
  14590                                                        idx, proto_ptr);
  14591     return (rv);
  14592 }
  14593 
  14594 /*
  14595  * Function:
  14596  *      _bcm_field_fb_data_qualifier_ip_protocol_delete
  14597  * Purpose:
  14598  *      Remove ip protocol based offset from data qualifier object.
  14599  * Parameters:
  14600  *      unit        - (IN) bcm device.
  14601  *      qual_id     - (IN) Data qualifier id.
  14602  *      ip_protocol - (IN) Ip Protocol based offset specification.
  14603  * Returns:
  14604  *      BCM_E_XXX
  14605  */
  14606 int
  14607 _bcm_field_fb_data_qualifier_ip_protocol_delete(int unit,  int qual_id,
  14608                           bcm_field_data_ip_protocol_t *ip_protocol)
  14609 {
  14610     _field_data_protocol_t     *proto_ptr;/* Ip protocol pointer.        */
  14611     _field_data_qualifier_t    *f_dq;     /* Data qualifier descriptor.  */
  14612     _field_stage_t             *stage_fc; /* Stage field control.        */
  14613     int                        idx;       /* Ethertype allocation index. */
  14614     int                        flags;     /* Ip protocol version flags.  */
  14615     int                        rv;        /* Operation return status.    */
  14616 
  14617     /* Input parameters check. */
  14618     if ((NULL == ip_protocol)) {
  14619         return (BCM_E_PARAM);
  14620     }
  14621 
  14622     /* Get stage field control structure. */
  14623     rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc); 
  14624     BCM_IF_ERROR_RETURN(rv);
  14625 
  14626     /* Get data qualifier info. */
  14627     rv = _bcm_field_data_qualifier_get(unit, stage_fc, qual_id, &f_dq);
  14628     BCM_IF_ERROR_RETURN(rv);
  14629 
  14630     flags = ip_protocol->flags & 
  14631         (BCM_FIELD_DATA_FORMAT_IP4 | BCM_FIELD_DATA_FORMAT_IP6);
  14632     for (idx = 0; idx < _FP_DATA_IP_PROTOCOL_MAX; idx++) {
  14633         proto_ptr = stage_fc->data_ctrl->ip + idx;
  14634 
  14635         /* Find an entry with identical ip_protocol. */
  14636         if ((ip_protocol->ip == proto_ptr->ip) &&
  14637             ((proto_ptr->ip4_ref_count > 0) || 
  14638              ((proto_ptr->ip6_ref_count > 0)))) {
  14639             break; 
  14640         }
  14641     }
  14642     if (_FP_DATA_IP_PROTOCOL_MAX == idx) {
  14643         /* No match found. */
  14644         return (BCM_E_NOT_FOUND);
  14645     }
  14646 
  14647     proto_ptr = stage_fc->data_ctrl->ip + idx;
  14648     /* Increment reference count. */
  14649     if ((flags & BCM_FIELD_DATA_FORMAT_IP4) &&
  14650         (proto_ptr->ip4_ref_count > 0)) {
  14651         proto_ptr->ip4_ref_count--;
  14652         if (0 == proto_ptr->ip4_ref_count) {
  14653             proto_ptr->flags &= ~BCM_FIELD_DATA_FORMAT_IP4;
  14654         } 
  14655     } 
  14656     if ((flags & BCM_FIELD_DATA_FORMAT_IP6) &&
  14657         (proto_ptr->ip6_ref_count > 0)) {
  14658         proto_ptr->ip6_ref_count--;
  14659         if (0 == proto_ptr->ip6_ref_count) {
  14660             proto_ptr->flags &= ~BCM_FIELD_DATA_FORMAT_IP6;
  14661         }
  14662     } 
  14663 
  14664     /* Mark entry as unused. */
  14665     if ((0 == proto_ptr->ip4_ref_count) && (0 == proto_ptr->ip6_ref_count)) {
  14666         proto_ptr->ip = 0;
  14667         proto_ptr->flags = 0;
  14668     } 
  14669 
  14670     /* Install protocol match register. */
  14671     rv = _bcm_field_fb_udf_ipprotocol_set(unit, idx, proto_ptr->flags, 
  14672                                           proto_ptr->ip);
  14673     return (rv);
  14674 }
  14675 
  14676 
  14677 #define _FP_L2_FORMAT_MIN   (0)
  14678 #define _FP_L2_FORMAT_MAX   (2)
  14679 /*
  14680  * Function:
  14681  *      _bcm_field_fb_data_qualifier_ethertype_add
  14682  * Purpose:
  14683  *      Add ethertype based offset to data qualifier object.
  14684  * Parameters:
  14685  *      unit       - (IN) bcm device.
  14686  *      qual_id    - (IN) Data qualifier id.
  14687  *      etype      - (IN) Ethertype based offset specification.
  14688  * Returns:
  14689  *      BCM_E_XXX
  14690  */
  14691 int
  14692 _bcm_field_fb_data_qualifier_ethertype_add(int unit,  int qual_id,
  14693                                  bcm_field_data_ethertype_t *etype)
  14694 {
  14695     int               idx;             /* L2 format iteration index.*/
  14696     uint16            l2;              /* Installed L2 format.      */
  14697     int               rv = BCM_E_NONE; /* Operation return status.  */
  14698 
  14699     /* Input parameters check. */
  14700     if (NULL == etype) {
  14701         return (BCM_E_PARAM);
  14702     }
  14703 
  14704     l2 = etype->l2;
  14705     for (idx = _FP_L2_FORMAT_MIN; idx <= _FP_L2_FORMAT_MAX; idx++) {
  14706         if (0 == (l2 & (1 << idx))) {
  14707             continue;
  14708         }
  14709         etype->l2 = (1 << idx);
  14710         rv = _field_fb_data_qualifier_ethertype_add(unit, qual_id, etype);
  14711         if (BCM_FAILURE(rv)) {
  14712             break;
  14713         }
  14714     }
  14715 
  14716     return (rv);
  14717 }
  14718 
  14719 /*
  14720  * Function:
  14721  *      _bcm_field_fb_data_qualifier_ethertype_delete
  14722  * Purpose:
  14723  *      Remove ethertype based offset from data qualifier object. 
  14724  * Parameters:
  14725  *      unit       - (IN) bcm device.
  14726  *      qual_id    - (IN) Data qualifier id.
  14727  *      etype      - (IN) Ethertype based offset specification.                 
  14728  * Returns:
  14729  *      BCM_E_XXX
  14730  */
  14731 int
  14732 _bcm_field_fb_data_qualifier_ethertype_delete(int unit, int qual_id,
  14733                                  bcm_field_data_ethertype_t *etype)
  14734 {
  14735     int               idx;             /* L2 format iteration index.*/
  14736     uint16            l2;              /* Installed L2 format.      */
  14737     int               rv = BCM_E_NONE; /* Operation return status.  */
  14738 
  14739     /* Input parameters check. */
  14740     if (NULL == etype) {
  14741         return (BCM_E_PARAM);
  14742     }
  14743 
  14744     l2 = etype->l2;
  14745     for (idx = _FP_L2_FORMAT_MIN; idx <= _FP_L2_FORMAT_MAX; idx++) {
  14746         if (0 == (l2 & (1 << idx))) {
  14747             continue;
  14748         }
  14749         etype->l2 = (1 << idx);
  14750         rv = _field_fb_data_qualifier_ethertype_delete(unit, qual_id, etype);
  14751         if (BCM_FAILURE(rv)) {
  14752             break;
  14753         }
  14754     }
  14755     return (rv);
  14756 }
  14757 #undef _FP_L2_FORMAT_MIN
  14758 #undef _FP_L2_FORMAT_MAX
  14759 
  14760 
  14761 /*
  14762  * Function:
  14763  *     _field_fb_functions_init
  14764  *
  14765  * Purpose:
  14766  *     Set up functions pointers 
  14767  *
  14768  * Parameters:
  14769  *     unit     - (IN) BCM device number.
  14770  *     stage_fc - (IN/OUT) pointers to stage control block whe the device 
  14771  *                         and stage specific functions will be registered.
  14772  *
  14773  * Returns:
  14774  *     nothing
  14775  * Notes:
  14776  */
  14777 STATIC void
  14778 _field_fb_functions_init(int unit, _field_funct_t *functions)
  14779 {
  14780     functions->fp_detach               = _field_fb_detach;
  14781     functions->fp_group_install        = _bcm_field_fb_group_install;
  14782     functions->fp_selcodes_install     = _field_selcodes_install;
  14783     functions->fp_slice_clear          = _bcm_field_fb_slice_clear;
  14784     functions->fp_entry_remove         = _bcm_field_fb_entry_remove;
  14785     functions->fp_entry_move           = _bcm_field_fb_entry_move;
  14786     functions->fp_selcode_get          = _bcm_field_fb_selcode_get;
  14787     functions->fp_selcode_to_qset      = _bcm_field_selcode_to_qset;
  14788     functions->fp_qual_list_get        = _bcm_field_qual_lists_get;
  14789     functions->fp_tcam_policy_clear    = _field_fb_tcam_policy_clear;
  14790     functions->fp_tcam_policy_install  = _field_fb_tcam_policy_install;
  14791     functions->fp_tcam_policy_reinstall = _field_fb_tcam_policy_reinstall;
  14792     functions->fp_policer_install      = _bcm_field_fb_policer_install;
  14793     functions->fp_write_slice_map      = _bcm_field_fb_write_slice_map;
  14794     functions->fp_qualify_ip_type      = _field_fb_qualify_ip_type;
  14795     functions->fp_qualify_ip_type_get  = _field_fb_qualify_ip_type_get;
  14796     functions->fp_action_support_check = _field_fb_action_support_check;
  14797     functions->fp_action_conflict_check = _field_fb_action_conflict_check;
  14798     functions->fp_stat_index_get       = _bcm_field_fb_stat_index_get;
  14799     functions->fp_action_params_check  = _field_fb_action_params_check;
  14800     functions->fp_data_qualifier_ethertype_add = 
  14801                        _bcm_field_fb_data_qualifier_ethertype_add;
  14802     functions->fp_data_qualifier_ethertype_delete= 
  14803                        _bcm_field_fb_data_qualifier_ethertype_delete;
  14804     functions->fp_data_qualifier_ip_protocol_add = 
  14805                        _bcm_field_fb_data_qualifier_ip_protocol_add;
  14806     functions->fp_data_qualifier_ip_protocol_delete= 
  14807                        _bcm_field_fb_data_qualifier_ip_protocol_delete;
  14808     functions->fp_data_qualifier_packet_format_add= 
  14809                        _bcm_field_fb_data_qualifier_packet_format_add;
  14810     functions->fp_data_qualifier_packet_format_delete=
  14811                        _bcm_field_fb_data_qualifier_packet_format_delete;
  14812 
  14813 #if defined(BCM_BRADLEY_SUPPORT) 
  14814     if (soc_feature(unit, soc_feature_two_ingress_pipes)) { 
  14815         functions->fp_counter_get    = _field_br_counter_get;
  14816         functions->fp_counter_set    = _field_br_counter_set;
  14817     } else 
  14818 #endif /* BCM_BRADLEY_SUPPORT */
  14819     {
  14820         functions->fp_counter_get    = _bcm_field_fb_counter_get;
  14821         functions->fp_counter_set    = _bcm_field_fb_counter_set;
  14822     }
  14823 
  14824 #if defined(BCM_FIREBOLT2_SUPPORT) 
  14825     functions->fp_egress_key_match_type_set = _field_fb2_key_match_type_set;
  14826 #else  /* BCM_FIREBOLT2_SUPPORT */
  14827     functions->fp_egress_key_match_type_set = NULL;
  14828 #endif  /* BCM_FIREBOLT2_SUPPORT */
  14829     functions->fp_external_entry_install = NULL;
  14830     functions->fp_external_entry_reinstall = NULL;
  14831     functions->fp_external_entry_remove = NULL;
  14832     functions->fp_external_entry_prio_set = NULL;
  14833     functions->fp_stat_value_get = NULL;                          
  14834     functions->fp_stat_value_set = NULL;
  14835     functions->fp_control_set = _bcm_field_control_set;
  14836     functions->fp_control_get = _bcm_field_control_get;
  14837     functions->fp_stat_hw_mode_get = _bcm_field_stat_hw_mode_get;
  14838     functions->fp_stat_hw_alloc = _bcm_field_stat_hw_alloc;
  14839     functions->fp_stat_hw_free = _bcm_field_stat_hw_free;
  14840     functions->fp_group_add = NULL;
  14841     functions->fp_qualify_trunk = _bcm_field_qualify_trunk;
  14842     functions->fp_qualify_trunk_get = _bcm_field_qualify_trunk_get;
  14843     functions->fp_qualify_inports = _bcm_field_qualify_InPorts;
  14844     functions->fp_entry_stat_extended_attach = NULL;
  14845     functions->fp_entry_stat_extended_get = NULL;
  14846     functions->fp_entry_stat_detach = _bcm_field_entry_stat_detach;
  14847     functions->fp_class_size_get = NULL;
  14848     functions->fp_qualify_packet_res = _field_qualify_PacketRes;
  14849     functions->fp_qualify_packet_res_get = _field_qualify_PacketRes_get;
  14850 }
  14851 #else /*BCM_FIREBOLT_SUPPORT && BCM_FIELD_SUPPORT */ 
  14852 int _firebolt_field_not_empty;
  14853 #endif  /* BCM_FIREBOLT_SUPPORT && BCM_FIELD_SUPPORT */