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_presel.c (235814B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        field_presel.c
      8  * Purpose:     Field Processor routines Specific to Preselector Module.
      9  */
     10 
     11 #include <soc/defs.h>
     12 
     13 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(BCM_FIELD_SUPPORT)
     14 
     15 #include <bcm/error.h>
     16 #include <bcm/field.h>
     17 #include <shared/bsl.h>
     18 
     19 #include <bcm_int/esw/field.h>
     20 #include <bcm_int/esw/tomahawk.h>
     21 #include <bcm_int/esw/tomahawk3.h>
     22 #if defined(BCM_HELIX5_SUPPORT)
     23 #include <bcm_int/esw/helix5.h>
     24 #endif /* BCM_HELIX5_SUPPORT */
     25 
     26 /* Function Declarations */
     27 STATIC int
     28 _bcm_field_presel_action_remove_all(int unit, bcm_field_entry_t entry);
     29 
     30 #define _BCM_FIELD_PRESEL_IS_STAGE_SUPPORTED(_stage_)   \
     31        ((_stage_ == bcmFieldStageIngress) ||            \
     32         (_stage_ == bcmFieldStageIngressExactMatch) ||  \
     33         (_stage_ == bcmFieldStageIngressFlowtracker))
     34 /*
     35  * Function:
     36  *    _field_th_presel_qualifiers_init
     37  *
     38  * Purpose:
     39  *    Initialize Field Ingress Stage Preselector Qualifiers.
     40  *
     41  * Parameters:
     42  *    unit       - (IN) BCM device number.
     43  *    stage_fc   - (IN/OUT) Field Processor stage control structure.
     44  *
     45  * Returns:
     46  *    BCM_E_PARAM       - Null field stage control structure.
     47  *    BCM_E_MEMORY      - Allocation failure.
     48  *    BCM_E_INTERNAL    - Invalid CAP Stage ID.
     49  *    BCM_E_NONE        - Success.
     50  */
     51 STATIC int
     52 _field_th_presel_qualifiers_init(int unit, _field_stage_t *stage_fc)
     53 {
     54     /*
     55      * All the qualifiers offset mentioned are the actual individual HW field
     56      * offset in IFP_LOGICAL_TABLE_SELECT Memory which are starting from bit
     57      * position 2. "KEY" overlap field in the memory is used during write,
     58      * hence to accomidate in the field, the offsets of the qualifiers has to
     59      * be substracted by 2.
     60      */
     61     static int8 key_base_off;
     62     soc_mem_t mem = INVALIDm;
     63     soc_field_info_t *field_info = NULL;
     64     _FP_QUAL_DECL;
     65 
     66 
     67     /* Allocated stage qualifiers configuration array. */
     68     _FP_XGS3_ALLOC(stage_fc->f_presel_qual_arr,
     69         (_bcmFieldQualifyCount * sizeof(_bcm_field_qual_info_t *)),
     70         "IFP Preselector qualifiers");
     71 
     72     if (stage_fc->f_presel_qual_arr == 0) {
     73         return (BCM_E_MEMORY);
     74     }
     75 
     76     if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) {
     77        mem = EXACT_MATCH_LOGICAL_TABLE_SELECT_TCAM_ONLYm;
     78     } else {
     79        mem = IFP_LOGICAL_TABLE_SELECT_TCAM_ONLYm;
     80     }
     81 
     82     field_info = soc_mem_fieldinfo_get(unit, mem, KEYf);
     83     if (field_info == NULL) {
     84        return BCM_E_PARAM;
     85     }
     86     key_base_off = field_info->bp;
     87 
     88     /* Preselector qualifiers. */
     89     /* SOURCE_CLASS - 32 */
     90     field_info = soc_mem_fieldinfo_get(unit, mem, SOURCE_CLASSf);
     91     if (field_info != NULL) {
     92         _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMixedSrcClassId,
     93             0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
     94             field_info->bp - key_base_off, 32);
     95     }
     96 
     97     /* EXACT_MATCH_LOGICAL_TABLE_ID_0 - 5 */
     98     field_info = soc_mem_fieldinfo_get(unit, mem,
     99                                        EXACT_MATCH_LOGICAL_TABLE_ID_0f);
    100     if (field_info != NULL) {
    101         _FP_PRESEL_QUAL_ADD(unit, stage_fc,
    102             _bcmFieldQualifyExactMatchGroupClassIdLookup0,
    103             _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT,
    104             _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    105             field_info->bp - key_base_off, 5);
    106     } else {
    107         /* EXACT_MATCH_LOGICAL_TABLE_ID - 5 */
    108         field_info = soc_mem_fieldinfo_get(unit, mem,
    109                                    EXACT_MATCH_LOGICAL_TABLE_IDf);
    110         if (field_info != NULL) {
    111             _FP_PRESEL_QUAL_ADD(unit, stage_fc,
    112                 _bcmFieldQualifyExactMatchGroupClassIdLookup0,
    113                 _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT,
    114                 _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    115                 field_info->bp - key_base_off, 5);
    116         }
    117     }
    118 
    119     /* EXACT_MATCH_LOGICAL_TABLE_ID_1 - 5 */
    120     field_info = soc_mem_fieldinfo_get(unit, mem,                                                                      EXACT_MATCH_LOGICAL_TABLE_ID_1f);
    121     if (field_info != NULL) {
    122         _FP_PRESEL_QUAL_ADD(unit, stage_fc,
    123             _bcmFieldQualifyExactMatchGroupClassIdLookup1,
    124             _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT
    125             , _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    126             field_info->bp - key_base_off, 5);
    127     }
    128 
    129     /* RESERVED_0 - 1 */
    130 
    131     /* HG_LOOKUP - 1 */
    132     field_info = soc_mem_fieldinfo_get(unit, mem, HG_LOOKUPf);
    133     if (field_info != NULL) {
    134         _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyHiGigProxy,
    135             0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    136             field_info->bp - key_base_off , 1);
    137     }
    138 
    139     /* CPU_PKT_PROFILE_KEY_CONTROL - 1 */
    140 #if 0
    141     _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualify,
    142         0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    143         45 - key_base_off , 1);
    144 #endif
    145 
    146     /* MIRROR - 1 */
    147     field_info = soc_mem_fieldinfo_get(unit, mem, MIRRORf);
    148     if (field_info != NULL) {
    149         _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMirrorCopy,
    150             0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    151             field_info->bp - key_base_off , 1);
    152     }
    153 
    154     /* HG - 1 */
    155     field_info = soc_mem_fieldinfo_get(unit, mem, HGf);
    156     if (field_info != NULL) {
    157         _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyHiGig,
    158             0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    159             field_info->bp - key_base_off , 1);
    160     }
    161 
    162     /* DROP - 1 */
    163     field_info = soc_mem_fieldinfo_get(unit, mem, DROPf);
    164     if (field_info != NULL) {
    165         _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDrop,
    166             0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    167             field_info->bp - key_base_off , 1);
    168     }
    169 
    170     /* PKT_RESOLUTION - 6 */
    171     field_info = soc_mem_fieldinfo_get(unit, mem, PKT_RESOLUTIONf);
    172     if (field_info != NULL) {
    173         _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyPacketRes,
    174             _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT,
    175             _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    176             field_info->bp - key_base_off , 6);
    177     }
    178 
    179     /* FORWARDING_TYPE - 4 */
    180     field_info = soc_mem_fieldinfo_get(unit, mem, FORWARDING_TYPEf);
    181     if (field_info != NULL) {
    182         _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyForwardingType,
    183             0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    184             field_info->bp - key_base_off , 4);
    185     }
    186 
    187     /* LOOKUP_STATUS_VECTOR - 19 */
    188     field_info = soc_mem_fieldinfo_get(unit, mem, LOOKUP_STATUS_VECTORf);
    189     if (field_info != NULL) {
    190         if (SOC_IS_TOMAHAWK3(unit)) {
    191             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIngressStpState,
    192                 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    193                 field_info->bp+0 - key_base_off , 2);
    194             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyStpState,
    195                 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    196                 field_info->bp+0 - key_base_off , 2);
    197             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDosAttack,
    198                 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    199                 field_info->bp+2 - key_base_off , 1);
    200             _FP_PRESEL_QUAL_ADD(unit, stage_fc,
    201                 bcmFieldQualifyForwardingVlanValid,
    202                 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    203                 field_info->bp+3 - key_base_off , 1);
    204             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMplsLabel1Hit,
    205                 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    206                 field_info->bp+4 - key_base_off , 1);
    207             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMplsLabel2Hit,
    208                 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    209                 field_info->bp+5 - key_base_off , 1);
    210             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMplsTerminated,
    211                 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    212                 field_info->bp+6 - key_base_off , 1);
    213             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpTunnelHit,
    214                 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    215                 field_info->bp+7 - key_base_off , 1);
    216         } else {
    217             _FP_PRESEL_QUAL_ADD(unit, stage_fc,
    218                 bcmFieldQualifyVlanTranslationHit,
    219                 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    220                 field_info->bp+0 - key_base_off , 3);
    221             _FP_PRESEL_QUAL_ADD(unit, stage_fc,
    222                 bcmFieldQualifyForwardingVlanValid,
    223                 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    224                 field_info->bp+3 - key_base_off , 1);
    225             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIngressStpState,
    226                 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    227                 field_info->bp+4 - key_base_off , 2);
    228             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyStpState,
    229                 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    230                 field_info->bp+4 - key_base_off , 2);
    231             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2SrcHit,
    232                 _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT,
    233                 _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    234                 field_info->bp+6 - key_base_off , 1);
    235             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2SrcStatic,
    236                 _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT,
    237                 _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    238                 field_info->bp+7 - key_base_off , 1);
    239             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2DestHit,
    240                 _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT,
    241                 _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    242                 field_info->bp+8 - key_base_off , 1);
    243             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2CacheHit,
    244                 _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT,
    245                 _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    246                 field_info->bp+9 - key_base_off , 1);
    247             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3SrcHostHit,
    248                 _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT,
    249                  _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    250                 field_info->bp+10 - key_base_off , 1);
    251             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpmcStarGroupHit,
    252                 _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT,
    253                 _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    254                 field_info->bp+10 - key_base_off , 1);
    255             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3DestHostHit,
    256                 _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT,
    257                 _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    258                 field_info->bp+11 - key_base_off , 1);
    259             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL3DestRouteHit,
    260                 _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT,
    261                 _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    262                 field_info->bp+12 - key_base_off , 1);
    263             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2StationMove,
    264                 _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT,
    265                 _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    266                 field_info->bp+13 - key_base_off , 1);
    267             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyDosAttack,
    268                 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    269                 field_info->bp+14 - key_base_off , 1);
    270             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpTunnelHit,
    271                 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    272                 field_info->bp+15 - key_base_off , 1);
    273             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMplsLabel1Hit,
    274                 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    275                 field_info->bp+16 - key_base_off , 1);
    276             _FP_PRESEL_QUAL_ADD(unit, stage_fc,
    277                 bcmFieldQualifyTrillEgressRbridgeHit,
    278                 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    279                 field_info->bp+16 - key_base_off , 1);
    280             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2GreSrcIpHit,
    281                 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    282                 field_info->bp+16 - key_base_off , 1);
    283             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMimSrcGportHit,
    284                 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    285                 field_info->bp+16 - key_base_off , 1);
    286             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMplsLabel2Hit,
    287                 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    288                 field_info->bp+17 - key_base_off , 1);
    289             _FP_PRESEL_QUAL_ADD(unit, stage_fc,
    290                 bcmFieldQualifyTrillIngressRbridgeHit,
    291                 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    292                 field_info->bp+17 - key_base_off , 1);
    293             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL2GreVfiHit,
    294                 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    295                 field_info->bp+17 - key_base_off , 1);
    296             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMimVfiHit,
    297                 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    298                 field_info->bp+17 - key_base_off , 1);
    299             _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMplsTerminated,
    300                 0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    301                 field_info->bp+18 - key_base_off , 1);
    302         }
    303     }
    304 
    305     /* SVP_VALID - 1 */
    306     field_info = soc_mem_fieldinfo_get(unit, mem, SVP_VALIDf);
    307     if (field_info != NULL) {
    308         _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifySrcVirtualPortValid,
    309             0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    310             field_info->bp - key_base_off , 1);
    311     }
    312 
    313     /* TUNNEL_TERMINATED - 1 */
    314     field_info = soc_mem_fieldinfo_get(unit, mem, TUNNEL_TERMINATEDf);
    315     if (field_info != NULL) {
    316         _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTunnelTerminated,
    317             0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    318             field_info->bp - key_base_off , 1);
    319     }
    320 
    321     /* MY_STATION_HIT - 1 */
    322     field_info = soc_mem_fieldinfo_get(unit, mem, MY_STATION_HITf);
    323     if (field_info != NULL) {
    324         _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyMyStationHit,
    325             0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    326             field_info->bp - key_base_off , 1);
    327     }
    328 
    329     /* TUNNEL_TYPE_LOOPBACK_TYPE - 5 */
    330     field_info = soc_mem_fieldinfo_get(unit, mem, TUNNEL_TYPE_LOOPBACK_TYPEf);
    331     if (field_info != NULL) {
    332         _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyLoopbackType,
    333             0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    334             field_info->bp - key_base_off , 5);
    335         _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyTunnelType,
    336             0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    337             field_info->bp - key_base_off , 5);
    338         _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyLoopback,
    339             0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    340             field_info->bp + 4 - key_base_off , 1);
    341     }
    342 
    343     /* L4_VALID - 1 */
    344     field_info = soc_mem_fieldinfo_get(unit, mem, L4_VALIDf);
    345     if (field_info != NULL) {
    346         _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyL4Ports,
    347             0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    348             field_info->bp - key_base_off , 1);
    349     }
    350 
    351     /* L3_TYPE - 5 */
    352     field_info = soc_mem_fieldinfo_get(unit, mem, L3_TYPEf);
    353     if (field_info != NULL) {
    354         _FP_PRESEL_QUAL_ADD(unit, stage_fc, bcmFieldQualifyIpType,
    355             0, _bcmFieldSliceSelDisable, 0, _bcmFieldQualifierTypePresel,
    356             field_info->bp - key_base_off , 5);
    357     }
    358 
    359     return (BCM_E_NONE);
    360 }
    361 
    362 /*
    363  * Function:
    364  *     _field_th_lt_config_init
    365  * Purpose:
    366  *     Initialize a Logical Table configuration in field control.
    367  * Parameters:
    368  *     unit     - (IN) BCM device number.
    369  *     fc       - (IN) field control structure pointer.
    370  * Returns:
    371  *     BCM_E_PARAM - Device field control information is NULL
    372  *     BCM_E_NONE  - Success
    373  */
    374 int
    375 _field_th_lt_config_init(int unit, _field_control_t *fc)
    376 {
    377     int lt_idx;                 /* Logical Table iterator.         */
    378     int inst;                   /* Instance iterator.              */
    379     _field_lt_config_t *lt_p = NULL;
    380                                /* Field LT configuration pointer. */
    381 
    382     int max_lt_parts = _FP_MAX_LT_PARTS(unit);
    383     /* Input parameters check. */
    384     if (NULL == fc) {
    385         return (BCM_E_PARAM);
    386     }
    387 
    388     /* Initialize for all pipes and all logical tables. */
    389     for (inst = 0; inst < NUM_PIPE(unit); inst++) {
    390         for (lt_idx = 0; lt_idx < _FP_MAX_NUM_LT; lt_idx++) {
    391 
    392             /* Allocate memory to store LT information. */
    393             _FP_XGS3_ALLOC(lt_p, sizeof(_field_lt_config_t),
    394                              "logical table config");
    395 
    396             if (NULL == lt_p) {
    397                 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
    398                    "FP(unit %d) Error: LT(Inst=%d) allocation=%d\n"),
    399                     unit, inst, (BCM_E_MEMORY)));
    400                 return (BCM_E_MEMORY);
    401             }
    402 
    403             lt_p->lt_part_pri = NULL;
    404 
    405             /* Allocate memory for Lt part pri */
    406             _FP_XGS3_ALLOC(lt_p->lt_part_pri, (sizeof(int) * max_lt_parts),
    407                            "Part Pri for logical table ");
    408 
    409             if (NULL == lt_p->lt_part_pri) {
    410                 sal_free(lt_p);
    411                 lt_p = NULL;
    412                 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
    413                    "FP(unit %d) Error: LT Part Pri(Inst=%d) allocation=%d\n"),
    414                     unit, inst, (BCM_E_MEMORY)));
    415                 return (BCM_E_MEMORY);
    416             }
    417 
    418             /* Initialize Logical Table ID. */
    419             lt_p->lt_id = lt_idx;
    420 
    421             /* Initialize stage LT pointer for given instance. */
    422             fc->lt_info[inst][lt_idx] = lt_p;
    423             lt_p = NULL;
    424         }
    425     }
    426     return (BCM_E_NONE);
    427 }
    428 
    429 /*
    430  * Function:
    431  *     _field_th_instance_lt_slices_init
    432  * Purpose:
    433  *     Initialize a Logical Table instance slices for Ingress stage.
    434  * Parameters:
    435  *     unit     - (IN) BCM device number
    436  *     stage_fc - (IN) stage control structure.
    437  *     inst     - (IN) Field Pipe Instance for which Logical tables must be
    438  *                     deinitialized.
    439  * Returns:
    440  *     BCM_E_PARAM - Device stage field control information is NULL
    441  *                   or Invalid instance specified.
    442  *     BCM_E_NONE  - Success
    443  */
    444 STATIC int
    445 _field_th_instance_lt_slices_init(int unit,
    446                                   _field_stage_t *stage_fc,
    447                                   int inst)
    448 {
    449     _field_lt_slice_t *lt_fs;   /* Logical table slice info.      */
    450     int slice;                  /* Slice iterator.                */
    451     int mem_sz;                 /* Memory allocation buffer size. */
    452     uint32 flags;               /* Stage slice related flags */
    453 
    454     /* Input parameters check. */
    455     if (NULL == stage_fc) {
    456         return (BCM_E_PARAM);
    457     }
    458 
    459     /* Validate instance value. */
    460     if (inst < 0 || inst >= stage_fc->num_instances) {
    461         return (BCM_E_PARAM);
    462     }
    463 
    464     if (stage_fc->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) {
    465         flags = _BCM_FIELD_SLICE_HW_ATOMICITY_SUPPORT;
    466     } else {
    467         flags = _BCM_FIELD_SLICE_SW_ATOMICITY_SUPPORT;
    468     }
    469     /* Allocate memory to store logical table slices information. */
    470     mem_sz = stage_fc->tcam_slices * sizeof(_field_lt_slice_t);
    471     lt_fs = sal_alloc(mem_sz, "stage LT slices info");
    472     if (NULL == lt_fs) {
    473         return (BCM_E_MEMORY);
    474     }
    475 
    476     /* Initialize memory allocated for logical tables. */
    477     sal_memset(lt_fs, 0, mem_sz);
    478 
    479     /* Update stage's logical table slices pointer for the instance. */
    480     stage_fc->lt_slices[inst] = lt_fs;
    481 
    482     /* Initialize LT slice structure fields. */
    483     for (slice = 0; slice < stage_fc->tcam_slices; slice++) {
    484         lt_fs[slice].slice_number = slice;
    485         lt_fs[slice].stage_id = stage_fc->stage_id;
    486         lt_fs[slice].next = NULL;
    487         lt_fs[slice].prev = NULL;
    488         lt_fs[slice].slice_flags = flags;
    489     }
    490 
    491     return (BCM_E_NONE);
    492 }
    493 
    494 /*
    495  * Function:
    496  *     _field_th_stage_lt_entries_free
    497  * Purpose:
    498  *     Deallocate Logical Table entries for all instance in StageIngress.
    499  * Parameters:
    500  *     unit     - (IN) BCM device number.
    501  *     stage_fc - (IN) stage control structure pointer.
    502  * Returns:
    503  *     BCM_E_PARAM - Device stage field control information is NULL.
    504  *     BCM_E_NONE  - Success
    505  */
    506 STATIC int
    507 _field_th_stage_lt_entries_free(int unit, _field_stage_t *stage_fc)
    508 {
    509     _field_lt_slice_t *lt_fs; /* Field logical table slice pointer. */
    510     int slice;                /* Slice iterator.                    */
    511     int inst;                 /* Instance iterator.                 */
    512     _field_control_t *fc;     /* Field Control Info                 */
    513 
    514     /* Input prameters check. */
    515     if (NULL == stage_fc) {
    516         return (BCM_E_PARAM);
    517     }
    518 
    519     /* Get field control structure. */
    520     BCM_IF_ERROR_RETURN (_field_control_get(unit, &fc));
    521 
    522     /* Deallocate instance entry pointers. */
    523     for (inst = 0; inst < stage_fc->num_instances; inst++) {
    524         if (!(fc->pipe_map & (1 << inst))) {
    525              continue;
    526         }
    527        /* Ensure stage's logical table slices instance is valid. */
    528        if (NULL != stage_fc->lt_slices[inst]) {
    529           for (slice = 0; slice < stage_fc->tcam_slices; slice++) {
    530               lt_fs = stage_fc->lt_slices[inst] + slice;
    531               if (NULL != lt_fs->entries) {
    532                   sal_free(lt_fs->entries);
    533                   lt_fs->entries = NULL;
    534               }
    535 
    536               if (NULL != lt_fs->p_entries) {
    537                   sal_free(lt_fs->p_entries);
    538                   lt_fs->p_entries = NULL;
    539               }
    540           }
    541        }
    542     }
    543 
    544     return (BCM_E_NONE);
    545 }
    546 
    547 /*
    548  * Function:
    549  *     _field_th_instance_lt_entries_init
    550  * Purpose:
    551  *     Initialize Logical Table slices for a StageIngress instance.
    552  * Parameters:
    553  *     unit     - (IN) BCM device number.
    554  *     stage_fc - (IN) stage control structure pointer.
    555  *     inst     - (IN) Field Pipe Instance for which Logical tables must be
    556  *                     deinitialized.
    557  * Returns:
    558  *     BCM_E_PARAM - Device stage field control information is NULL
    559  *                   or Invalid instance specified.
    560  *     BCM_E_NONE  - Success
    561  */
    562 STATIC int
    563 _field_th_instance_lt_entries_init(int unit, _field_stage_t *stage_fc, int inst)
    564 {
    565     _field_lt_slice_t *lt_fs;   /* Field logical table slice pointer.    */
    566     int slice;                  /* Slice index iterator.                 */
    567     int tcam_idx;               /* Slice first entry tcam index tracker. */
    568     int mem_sz;                 /* Size of memory to be allocated.       */
    569 
    570     /* Input parameters check. */
    571     if (NULL == stage_fc) {
    572         return (BCM_E_PARAM);
    573     }
    574 
    575     /* Check if instance is in valid range. */
    576     if (inst < 0 || inst >= stage_fc->num_instances) {
    577         return (BCM_E_PARAM);
    578     }
    579 
    580     /* Make sure slices array is initialized. */
    581     if (NULL == stage_fc->lt_slices[inst]) {
    582         return (BCM_E_INTERNAL);
    583     }
    584 
    585     /* Iterate over all stage's slices and allocate entries for each slice. */
    586     for (slice = 0, tcam_idx = 0; slice < stage_fc->tcam_slices; slice++) {
    587         /* Get Pipe slice control structure pointer. */
    588         lt_fs = stage_fc->lt_slices[inst] + slice;
    589 
    590         /*  Initialize entries per-slice count. */
    591         lt_fs->entry_count = stage_fc->lt_tcam_sz / stage_fc->tcam_slices;
    592 
    593         /* Calculate size for total entry pointers. */
    594         mem_sz = lt_fs->entry_count * sizeof(void *);
    595 
    596         /* Allocate slice entries pointers array. */
    597         _FP_XGS3_ALLOC(lt_fs->entries, mem_sz, "LT array of entry pointers.");
    598 
    599         /* Allocate slice presel entries pointers array. */
    600         _FP_XGS3_ALLOC(lt_fs->p_entries, mem_sz,
    601                       "Presel LT array of entry pointers.");
    602         if ((NULL == lt_fs->p_entries) || (NULL == lt_fs->entries)) {
    603             /* Allocation failed free all previously allocated entries. */
    604             _field_th_stage_lt_entries_free(unit, stage_fc);
    605             return (BCM_E_MEMORY);
    606         }
    607 
    608         lt_fs->start_tcam_idx = tcam_idx;
    609         tcam_idx += lt_fs->entry_count;
    610         lt_fs->free_count = lt_fs->entry_count;
    611     }
    612     return (BCM_E_NONE);
    613 }
    614 
    615 /*
    616  * Function:
    617  *     _field_th_presel_qual_init
    618  * Purpose:
    619  *     Initialize Field control Preselector qualifiers.
    620  * Parameters:
    621  *     unit     - (IN) BCM device number.
    622  *     fc       - (IN) Reference to Field Control structure.
    623  *     stage_fc - (IN/OUT) Stage field control structure.
    624  * Returns:
    625  *     BCM_E_PARAM  - Device field control information is NULL.
    626  *     BCM_E_MEMORY - In-case of Allocation fails.
    627  *     BCM_E_NONE   - Success.
    628  */
    629 
    630 STATIC int
    631 _field_th_presel_qual_init(int unit,
    632                            _field_control_t *fc,
    633                            _field_stage_t *stage_fc)
    634 {
    635     int                   rv;                   /* Operation return status.  */
    636     int                   qual_idx;             /* Qualifier index. */
    637 
    638     /* Input parameters check. */
    639     if (NULL == fc || NULL == stage_fc) {
    640         return (BCM_E_PARAM);
    641     }
    642 
    643     /* Initialize qualifiers info. */
    644 #if defined(BCM_TRIDENT3_SUPPORT)
    645     if (soc_feature(unit, soc_feature_td3_style_fp)) {
    646         rv = (_field_td3_presel_qualifiers_init(unit, stage_fc));
    647     } else
    648 #endif
    649 #if defined(BCM_TOMAHAWK3_SUPPORT)
    650     if (soc_feature(unit, soc_feature_th3_style_fp)) {
    651 	    rv = (_field_th3_presel_qualifiers_init(unit, stage_fc));
    652     } else
    653 #endif
    654     {
    655         rv = (_field_th_presel_qualifiers_init(unit, stage_fc));
    656     }
    657 
    658     if (BCM_FAILURE(rv)) {
    659         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
    660            "Error: Preselector Qualifiers init failed[%d].\n"),
    661             rv));
    662         return rv;
    663     }
    664 
    665     /* Update the Valid Preselector QSET */
    666     for (qual_idx = 0; qual_idx < _bcmFieldQualifyCount; qual_idx++) {
    667        if ((NULL != stage_fc->f_presel_qual_arr[qual_idx]) &&
    668            (NULL != stage_fc->f_presel_qual_arr[qual_idx]->conf_arr)) {
    669           BCM_FIELD_QSET_ADD(stage_fc->presel_qset, qual_idx);
    670        }
    671     }
    672 
    673     return (BCM_E_NONE);
    674 }
    675 
    676 /*
    677  * Function:
    678  *    _field_th_stage_preselector_init
    679  * Purpose:
    680  *    Initialize Preselector resources for given stage and field control.
    681  *    - Logical Table configuration initialization for each instance.
    682  *    - Logical Table Slice initialization for each instance.
    683  *    - Logical Table Entries initialization for each instance.
    684  *    - Preselection Qualifier Database initialization.
    685  *
    686  * Parameters:
    687  *    unit      - (IN) BCM device number.
    688  *    fc        - (IN) Field control structure.
    689  *    stage_fc  - (IN/OUT) Stage field control structure.
    690  *
    691  * Returns:
    692  *    BCM_E_PARAM   - NULL stage control or field control pointer.
    693  *    BCM_E_MEMORY  - Allocation failure.
    694  *    BCM_E_NONE    - Success.
    695  */
    696 int
    697 _bcm_field_th_stage_preselector_init(int unit,
    698                                      _field_control_t *fc,
    699                                      _field_stage_t *stage_fc)
    700 {
    701     int inst;   /* Field processor pipe instance.   */
    702     int rv;     /* Operation return status.         */
    703 
    704     /* Input parameters check. */
    705     if (NULL == fc || NULL == stage_fc) {
    706         return (BCM_E_PARAM);
    707     }
    708 
    709     /* Do nothing for Non-PresePreseltages. */
    710     if ((_BCM_FIELD_STAGE_INGRESS != stage_fc->stage_id) &&
    711         (_BCM_FIELD_STAGE_EXACTMATCH != stage_fc->stage_id) &&
    712         (_BCM_FIELD_STAGE_FLOWTRACKER != stage_fc->stage_id)) {
    713         return (BCM_E_NONE);
    714     }
    715 
    716     /* Initialize Preselection qualifiers */
    717     rv = _field_th_presel_qual_init(unit, fc, stage_fc);
    718     if (BCM_FAILURE(rv)) {
    719             LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
    720                "FP(unit %d) Error: Presel Info init failed(%d)\n"),
    721                 unit, rv));
    722             return (rv);
    723     }
    724 
    725     for (inst = 0; inst < stage_fc->num_instances; inst++) {
    726         if (!(fc->pipe_map & (1 << inst))) {
    727              continue;
    728         }
    729         /* Initialize logical table slices for IFP and EM stage. */
    730         rv = _field_th_instance_lt_slices_init(unit, stage_fc, inst);
    731         if (BCM_FAILURE(rv)) {
    732             LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
    733                "FP(unit %d) Error: LT(Inst=%d) Slices Init=%d\n"),
    734                 unit, inst, rv));
    735             return (rv);
    736         }
    737 
    738         /* Initialize logical table slice entries for IFP and EM stage. */
    739         rv = _field_th_instance_lt_entries_init(unit, stage_fc, inst);
    740         if (BCM_FAILURE(rv)) {
    741             LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
    742                "FP(unit %d) Error: LT(Inst=%d) Entries Init=%d\n"),
    743                 unit, inst, rv));
    744             return (rv);
    745         }
    746     }
    747 
    748     return (BCM_E_NONE);
    749 }
    750 
    751 /*
    752  * Function:
    753  *     _field_th_presel_qual_free
    754  * Purpose:
    755  *     De-Initialize Preselector Qualifier Database.
    756  * Parameters:
    757  *     unit     - (IN) BCM device number.
    758  *     stage_fc - (IN) Stage field control structure.
    759  * Returns:
    760  *     BCM_E_PARAM  - Device field control information is NULL.
    761  *     BCM_E_MEMORY - In-case of Allocation fails.
    762  *     BCM_E_NONE   - Success.
    763  */
    764 
    765 STATIC int
    766 _field_th_presel_qual_free(int unit,
    767                            _field_stage_t *stage_fc)
    768 {
    769     _bcm_field_qual_info_t  *f_qual; /* Qualifier descriptor.       */
    770     int idx;                         /* Qualifiers iteration index. */
    771 
    772     /* Input parameters check. */
    773     if (NULL == stage_fc) {
    774         return (BCM_E_PARAM);
    775     }
    776 
    777     if (NULL == stage_fc->f_presel_qual_arr) {
    778         return (BCM_E_NONE);
    779     }
    780 
    781     for (idx = 0; idx < _bcmFieldQualifyCount; idx++) {
    782         f_qual = stage_fc->f_presel_qual_arr[idx];
    783 
    784         /* Skip unused qualifiers. */
    785         if (NULL == f_qual) {
    786             continue;
    787         }
    788         /* Free qualifier configurations array. */
    789         if (NULL != f_qual->conf_arr) sal_free(f_qual->conf_arr);
    790 
    791         /* Free qualifier descriptor structure. */
    792         sal_free(f_qual);
    793 
    794         /* Mark qualifier as unused. */
    795         stage_fc->f_presel_qual_arr[idx] = NULL;
    796     }
    797 
    798     /* Free qualifiers array. */
    799     sal_free(stage_fc->f_presel_qual_arr);
    800     stage_fc->f_presel_qual_arr = NULL;
    801 
    802     return (BCM_E_NONE);
    803 }
    804 
    805 /*
    806  * Function:
    807  *     _bcm_field_th_preselector_deinit
    808  * Purpose:
    809  *     Deinitialize a Preselector resources in Ingress stage.
    810  *     - Deallocate Logical table slice entries and slices for each instance.
    811  *     - Deallocate Logical table configuration structures for each instance.
    812  *     - Deallocate Preselector Qualifiers Information.
    813  * Parameters:
    814  *     unit     - (IN) BCM device number
    815  *     fc       - (IN) Field control structure.
    816  *     stage_fc - (IN) Stage field control structure.
    817  * Returns:
    818  *     BCM_E_PARAM - Device field control or stage field control information
    819  *                   is NULL.
    820  *     BCM_E_NONE  - Success
    821  */
    822 int
    823 _bcm_field_th_preselector_deinit(int unit,
    824                                  _field_control_t *fc,
    825                                  _field_stage_t *stage_fc)
    826 {
    827     int slice;                  /* Slice iterator.                  */
    828     int inst;                   /* Pipe instance.                   */
    829     _field_lt_slice_t *lt_fs;   /* Logical Table slice information. */
    830 
    831     /* Input parameters check. */
    832     if (NULL == fc || NULL == stage_fc) {
    833         return (BCM_E_PARAM);
    834     }
    835 
    836     /* Do nothing for Non-Presel stages. */
    837     if ((_BCM_FIELD_STAGE_INGRESS != stage_fc->stage_id) &&
    838         (_BCM_FIELD_STAGE_EXACTMATCH != stage_fc->stage_id) &&
    839         (_BCM_FIELD_STAGE_FLOWTRACKER != stage_fc->stage_id)) {
    840         return (BCM_E_NONE);
    841     }
    842 
    843     /* Free the resources for each instance. */
    844     for (inst = 0; inst < stage_fc->num_instances; inst++) {
    845         if (!(fc->pipe_map & (1 << inst))) {
    846              continue;
    847         }
    848        /* Ensure stage's logical table slices instance is valid. */
    849        if (NULL != stage_fc->lt_slices[inst]) {
    850            /* Deallocate logical table entry pointers for the given instance. */
    851            for (slice = 0; slice < stage_fc->tcam_slices; slice++) {
    852               lt_fs = stage_fc->lt_slices[inst] + slice;
    853               if (NULL != lt_fs->entries) {
    854                  sal_free(lt_fs->entries);
    855                  lt_fs->entries = NULL;
    856               }
    857               if (NULL != lt_fs->p_entries) {
    858                  sal_free(lt_fs->p_entries);
    859                  lt_fs->p_entries = NULL;
    860               }
    861            }
    862 
    863            /* Free logical table slices memory for active instances. */
    864            sal_free(stage_fc->lt_slices[inst]);
    865            stage_fc->lt_slices[inst] = NULL;
    866        }
    867     }
    868 
    869     /* Deallocate Field Control Preselector information */
    870     _field_th_presel_qual_free(unit, stage_fc);
    871 
    872     return (BCM_E_NONE);
    873 }
    874 
    875 /*
    876  * Function: bcmi_field_th_presel_alloc
    877  *
    878  * Purpose: Allocate a preselector
    879  *
    880  * Parameters:
    881  *     unit      - (IN)  BCM device number.
    882  *     presel_id - (OUT) Reference to a new preselector ID to be created
    883  *
    884  * Returns:
    885  *     BCM_E_NONE   - Success
    886  *     BCM_E_XXX    - BCM_E_xx appropriately otherwise
    887  */
    888 int
    889 _bcm_field_th_presel_create(int unit,
    890                             _bcm_field_presel_flags_t flags,
    891                             bcm_field_presel_t *presel)
    892 {
    893     bcm_field_presel_t        id = -1;          /* Presel id */
    894     _field_presel_entry_t     *f_presel = NULL; /* Internal Presel descriptor */
    895     _field_presel_info_t      *presel_info;     /* Presel information structure */
    896     _field_control_t          *fc;              /* Field control structure. */
    897 
    898     /* Validate input arguments NULL reference */
    899     if (presel == NULL) {
    900        return BCM_E_PARAM;
    901     }
    902 
    903     /* Get field control structure. */
    904     BCM_IF_ERROR_RETURN (_field_control_get(unit, &fc));
    905 
    906     /* Get the preselector information */
    907     presel_info = fc->presel_info;
    908     if (presel_info == NULL) {
    909        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
    910              "ERROR: Field control for Presel Information returns NULL.\n\r")));
    911        return BCM_E_INTERNAL;
    912     }
    913 
    914     /* Presel create with ID */
    915     if (flags & _bcmFieldPreselCreateWithId) {
    916        id = *presel;
    917        if ((id < 0) || (id >= presel_info->presel_limit)) {
    918           LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
    919                     "ERROR: Invalid Preselector ID %d.\n\r"), id));
    920           return BCM_E_PARAM;
    921        }
    922 
    923        /* TH3 COS SW WAR */
    924        if ((soc_feature(unit, soc_feature_sw_mmu_flush_rqe_operation)) &&
    925           (id == _FP_PRESEL_INTERNAL_RESERVED_ID)) {
    926           LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
    927                     "ERROR: Invalid Preselector ID %d.\n\r"), id));
    928           return BCM_E_PARAM;
    929        }
    930 
    931        /* Check if presel ID is already created */
    932        if (BCM_FIELD_PRESEL_TEST(presel_info->presel_set, id)) {
    933           LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
    934                  "ERROR: Preselector ID[%d] is already created.\n\r"), id));
    935           return BCM_E_EXISTS;
    936        }
    937     } else {
    938        uint32  max_count;  /* Maximum number of ids supported */
    939 
    940        max_count = presel_info->presel_limit;
    941 
    942        if (soc_feature(unit, soc_feature_sw_mmu_flush_rqe_operation)) {
    943           max_count = (presel_info->presel_limit - 1);
    944        }
    945 
    946        while (max_count) {
    947           id = presel_info->last_allocated_id++;
    948 
    949           if (soc_feature(unit, soc_feature_sw_mmu_flush_rqe_operation)) {
    950               if (id == (presel_info->presel_limit - 2)) {
    951                  presel_info->last_allocated_id = 0;
    952               }
    953           } else {
    954               if (id == (presel_info->presel_limit - 1)) {
    955                  presel_info->last_allocated_id = 0;
    956               }
    957           }
    958 
    959           if (!BCM_FIELD_PRESEL_TEST(presel_info->presel_set, id)) {
    960              *presel = id;
    961              break;
    962           }
    963           max_count--;
    964        }
    965 
    966        if (max_count == 0) {
    967           LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
    968                     "ERROR: Can't create the ID, max limit reached[0x%x].\n\r"),
    969                     (soc_feature(unit, soc_feature_sw_mmu_flush_rqe_operation))
    970                      ?(presel_info->presel_limit -1):(presel_info->presel_limit)));
    971           return BCM_E_RESOURCE;
    972        }
    973     }
    974 
    975     /* Allocate presel descriptor. */
    976     _FP_XGS3_ALLOC(f_presel, sizeof (_field_presel_entry_t), "Field Presel entity");
    977     if (NULL == f_presel) {
    978        return BCM_E_MEMORY;
    979     }
    980 
    981     /* Initialize the newly created presel id */
    982     f_presel->presel_id   = id;
    983     /* Initialize the hw index to No HW resources allocated */
    984     f_presel->hw_index    = _FP_INVALID_INDEX;
    985     /* Initialize internal flags and stage information */
    986     f_presel->flags       = flags;
    987 
    988     /* Insert Presel into Preselector database */
    989     if (fc->presel_db == NULL) {
    990         sal_free(f_presel);
    991         return BCM_E_INTERNAL;
    992     }
    993 
    994     fc->presel_db[id] = f_presel;
    995 
    996     /* Update preselector global information */
    997     /* coverity[negative_shift : FALSE] */
    998     BCM_FIELD_PRESEL_ADD(presel_info->presel_set, id);
    999 
   1000     return BCM_E_NONE;
   1001 }
   1002 
   1003 
   1004 /*
   1005  * Function: bcmi_field_th_presel_destroy
   1006  *
   1007  * Purpose: Destroy a preselector entry
   1008  *
   1009  * Parameters:
   1010  *     unit      - (IN) BCM device number.
   1011  *     presel_id - (IN) A preselector ID to be deleted
   1012  *
   1013  * Returns:
   1014  *     BCM_E_NONE   - Success
   1015  *     BCM_E_BUSY   - If the presel is already in use by a group.
   1016  *     BCM_E_XXX    - BCM_E_xx appropriately otherwise
   1017  */
   1018 
   1019 int
   1020 _bcm_field_th_presel_destroy(int unit,
   1021                              bcm_field_presel_t presel_id)
   1022 {
   1023     int                       rv;           /* Operation return status. */
   1024     _field_control_t          *fc;          /* Field control structure        */
   1025     _field_presel_entry_t     *f_presel;    /* Internal preselector descriptor*/
   1026 
   1027     /* Validate the Preselector ID */
   1028     if (_BCM_FIELD_IS_PRESEL_VALID(presel_id) == FALSE) {
   1029        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1030            "ERROR: Invalid Presel ID[%d].\n\r"), presel_id));
   1031        return BCM_E_PARAM;
   1032     }
   1033 
   1034     /* Get field control structure. */
   1035     BCM_IF_ERROR_RETURN (_field_control_get(unit, &fc));
   1036 
   1037     /* Check if presel ID present in presel_set */
   1038     if (!BCM_FIELD_PRESEL_TEST(fc->presel_info->presel_set, presel_id)) {
   1039        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1040                  "ERROR: Preselector ID[%d] is not found.\n\r"), presel_id));
   1041        return BCM_E_NOT_FOUND;
   1042     }
   1043 
   1044     /* Check if presel ID is operational */
   1045     if (BCM_FIELD_PRESEL_TEST(fc->presel_info->operational_set, presel_id)) {
   1046        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1047                  "ERROR: Preselector ID[%d] is in USE.\n\r"), presel_id));
   1048        return BCM_E_BUSY;
   1049     }
   1050 
   1051     /* Find preselector descriptor */
   1052     BCM_IF_ERROR_RETURN
   1053       (_bcm_field_presel_entry_get(unit, presel_id, &f_presel));
   1054 
   1055     /* Remove the actions associated with the preselector entry */
   1056     rv = _bcm_field_presel_action_remove_all(unit,
   1057                    (presel_id | BCM_FIELD_QUALIFY_PRESEL));
   1058     if (BCM_FAILURE(rv)) {
   1059         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1060              "ERROR: Unable to remove the actions associated with the"
   1061              "Preselector Id[%d].\n\r"), presel_id));
   1062         return BCM_E_INTERNAL;
   1063     }
   1064 
   1065     /* Remove preselector for lookup database. */
   1066     fc->presel_db[presel_id] = NULL;
   1067 
   1068     /* Deallocate the memories */
   1069     if (f_presel->lt_tcam.key != NULL) sal_free(f_presel->lt_tcam.key);
   1070     if (f_presel->lt_tcam.mask != NULL) sal_free(f_presel->lt_tcam.mask);
   1071     if (f_presel->lt_data.data != NULL) sal_free(f_presel->lt_data.data);
   1072     sal_free (f_presel);
   1073 
   1074     /* Get the preselector information */
   1075     BCM_FIELD_PRESEL_REMOVE(fc->presel_info->presel_set, presel_id);
   1076 
   1077     return BCM_E_NONE;
   1078 }
   1079 
   1080 /*
   1081  * Function: _bcm_field_presel_entry_get
   1082  *
   1083  * Purpose: Get the preselector description structure for the given presel id
   1084  *
   1085  * Parameters:
   1086  *     unit      - (IN)  BCM device number.
   1087  *     presel_id - (IN)  Preselector ID
   1088  *     presel    - (OUT) Reference to the preselector description structure
   1089  *
   1090  *   Returns:
   1091  *     BCM_E_NONE      - Success
   1092  *     BCM_E_NOT_FOUND - If the ID is not found.
   1093  *     BCM_E_XXX       - BCM_E_xx appropriately otherwise
   1094  */
   1095 int
   1096 _bcm_field_presel_entry_get(int unit,
   1097                             bcm_field_presel_t presel_id,
   1098                             _field_presel_entry_t **presel)
   1099 {
   1100    _field_control_t      *fc;        /* Field control structure */
   1101    _field_presel_entry_t *f_presel;  /* Preselector lookup pointer */
   1102 
   1103    /* Input parameters check */
   1104    if (NULL == presel) {
   1105       return BCM_E_PARAM;
   1106    }
   1107 
   1108    /* Get field control structure. */
   1109    BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   1110 
   1111    /* Check if presel ID present in presel_set */
   1112    if (!BCM_FIELD_PRESEL_TEST(fc->presel_info->presel_set, presel_id)) {
   1113       LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1114                 "ERROR: Preselector ID[%d] is not found.\n\r"), presel_id));
   1115       return BCM_E_NOT_FOUND;
   1116    }
   1117 
   1118    f_presel = fc->presel_db[presel_id];
   1119    if (f_presel != NULL) {
   1120       /* Match entry id */
   1121       *presel = f_presel;
   1122       return BCM_E_NONE;
   1123    }
   1124 
   1125    return BCM_E_INTERNAL;
   1126 }
   1127 
   1128 /*
   1129  * Function: _bcm_field_entry_presel_resolve
   1130  *
   1131  * Purpose:
   1132  *     Resolve the presel info from the given entry id.
   1133  *
   1134  * Parameters:
   1135  *     unit      - (IN)  BCM device number.
   1136  *     entry     - (IN)  An entry id to be validated for presel.
   1137  *     presel    - (OUT) Reference to the resolved presel id.
   1138  *     presel    - (OUT) Reference to the preselector description structure
   1139  *
   1140  * Returns:
   1141  *     BCM_E_PARAM     - presel contained in entry id is not valid
   1142  *                       or presel == NULL.
   1143  *     BCM_E_UNAVAIL   - entry id doesn't contain a presel id.
   1144  *     BCM_E_NOT_FOUND - presel id is not found.
   1145  *     BCM_E_NONE      - returns valid presel id.
   1146  */
   1147 STATIC int
   1148 _bcm_field_entry_presel_resolve(int unit,
   1149                                 bcm_field_entry_t entry,
   1150                                 bcm_field_presel_t *presel,
   1151                                 _field_presel_entry_t **f_presel)
   1152 {
   1153     int                     rv;         /* Operation return status.   */
   1154 
   1155     if (presel == NULL) {
   1156        return BCM_E_PARAM;
   1157     }
   1158 
   1159     if (_BCM_FIELD_IS_PRESEL_ENTRY(entry) == TRUE) {
   1160        _field_control_t        *fc;  /* Field control structure */
   1161        bcm_field_presel_t       id;  /* Preselector Id */
   1162 
   1163 
   1164        id = _BCM_FIELD_PRESEL_FROM_ENTRY(entry);
   1165        if (_BCM_FIELD_IS_PRESEL_VALID(id) == FALSE) {
   1166           LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1167               "ERROR: Invalid Presel ID[%d] retrieved from Entry ID[%d].\n\r"),
   1168                id, entry));
   1169           return BCM_E_PARAM;
   1170        }
   1171 
   1172        BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   1173        /* Check if presel ID present in presel_set */
   1174        if (!BCM_FIELD_PRESEL_TEST(fc->presel_info->presel_set, id)) {
   1175           LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1176                "ERROR: Preselector ID[%d] is not found.\n\r"), id));
   1177           return BCM_E_NOT_FOUND;
   1178        }
   1179 
   1180        *presel = id;
   1181 
   1182        /* Retrieve the Presel Entry */
   1183        rv = _bcm_field_presel_entry_get(unit, id, f_presel);
   1184        if (BCM_FAILURE(rv)) {
   1185           LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1186               "ERROR: Couldn't retrieve the Preselector Entry for the given"
   1187               " Presel ID[%d].\n\r"), *presel));
   1188           return rv;
   1189        }
   1190     } else {
   1191        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1192               "ERROR: Entry ID[%d] is not of Preselector Type.\n\r"), entry));
   1193        return BCM_E_UNAVAIL;
   1194     }
   1195 
   1196     return BCM_E_NONE;
   1197 }
   1198 
   1199 /*
   1200  * Function:
   1201  *     _field_presel_qual_offset_get
   1202  * Purpose:
   1203  *     Retrieve qualifier offsets for the given preselector qual.
   1204  * Parameters:
   1205  *     unit     - (IN) BCM device number.
   1206  *     stage_fc - (IN) Stage field control structure.
   1207  *     f_presel - (IN) Reference to Field preselector entry descriptor.
   1208  *     qid      - (IN) Qualifier id.
   1209  *     q_offset - (OUT) Qualifier offset and width.
   1210  * Returns:
   1211  *     BCM_E_XXX
   1212  */
   1213 STATIC int
   1214 _field_presel_qual_offset_get(int unit, _field_stage_t *stage_fc,
   1215                               _field_presel_entry_t *f_presel,
   1216                               int qid, _bcm_field_qual_offset_t *q_offset)
   1217 {
   1218     int                     ct;
   1219     _field_control_t        *fc;        /* Field control structure. */
   1220     _bcm_field_qual_info_t  *f_qual = NULL;
   1221     _bcm_field_qual_conf_t  *conf_arr = NULL;
   1222 
   1223     /* Input parameters check. */
   1224     if ((NULL == stage_fc) || (NULL == f_presel) || (NULL == q_offset)) {
   1225         return (BCM_E_PARAM);
   1226     }
   1227 
   1228     /* Retrieve the control structure */
   1229     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   1230 
   1231     /* Validate the Qualifier */
   1232     if (0 == BCM_FIELD_QSET_TEST(stage_fc->presel_qset, qid)) {
   1233         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1234              "ERROR: Preselector Stage doesn't support the qualifier[%s].\n\r"),
   1235              _field_qual_name(qid)));
   1236         return (BCM_E_PARAM);
   1237     }
   1238 
   1239     f_qual = stage_fc->f_presel_qual_arr[qid];
   1240     if (f_qual == NULL) {
   1241        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1242              "ERROR: Unable to retrieve Preselector Qualifier[%s] offset.\n\r"),
   1243              _field_qual_name(qid)));
   1244        return BCM_E_INTERNAL;
   1245     }
   1246 
   1247     for (ct = 0; ct < f_qual->conf_sz; ct++) {
   1248         conf_arr = &f_qual->conf_arr[ct];
   1249         if ((conf_arr->offset.flags & _BCM_FIELD_QUAL_OFFSET_FLOW_TYPE_TUNNEL_NONE) ||
   1250             (conf_arr->offset.flags & _BCM_FIELD_QUAL_OFFSET_FLOW_TYPE_TUNNEL_L3) ||
   1251             (conf_arr->offset.flags & _BCM_FIELD_QUAL_OFFSET_FLOW_TYPE_TUNNEL_L2)) {
   1252             if (BCM_FIELD_QSET_TEST(f_presel->p_qset,
   1253                                            bcmFieldQualifyPktFlowType)) {
   1254                 if (BCM_FIELD_QSET_TEST(f_presel->p_qset,
   1255                                         _bcmFieldQualifyPktFlowTypeTunnelNone) &&
   1256                         !(conf_arr->offset.flags & _BCM_FIELD_QUAL_OFFSET_FLOW_TYPE_TUNNEL_NONE)) {
   1257                     continue;
   1258                 } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset,
   1259                                                _bcmFieldQualifyPktFlowTypeTunnelL3) &&
   1260                         !(conf_arr->offset.flags & _BCM_FIELD_QUAL_OFFSET_FLOW_TYPE_TUNNEL_L3)) {
   1261                     continue;
   1262                 } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset,
   1263                                                _bcmFieldQualifyPktFlowTypeTunnelL2) &&
   1264                         !(conf_arr->offset.flags & _BCM_FIELD_QUAL_OFFSET_FLOW_TYPE_TUNNEL_L2)) {
   1265                     continue;
   1266                 }
   1267             }
   1268         }
   1269 
   1270         /* Get qualifier information. */
   1271         sal_memcpy(q_offset,
   1272                    &conf_arr->offset,
   1273                    sizeof(_bcm_field_qual_offset_t));
   1274         return (BCM_E_NONE);
   1275     }
   1276 
   1277     return (BCM_E_NOT_FOUND);
   1278 }
   1279 
   1280 /*
   1281  * Function:
   1282  *     _bcm_field_presel_entry_tcam_idx_get
   1283  * Purpose:
   1284  *     Get the TCAM index of an entry ID.
   1285  * Parameters:
   1286  *     unit         - (IN) BCM device number.
   1287  *     f_presel     - (IN) Pointer to field logical table entry structure.
   1288  *     lt_fs        - (IN) Pointer to field logical table slice structure.
   1289  *     tcam_idx     - (OUT) Entry tcam index.
   1290  *
   1291  * Returns:
   1292  *     BCM_E_XXX
   1293  */
   1294 int
   1295 _bcm_field_presel_entry_tcam_idx_get(int unit, _field_presel_entry_t *f_presel,
   1296                                      _field_lt_slice_t *lt_fs, int *tcam_idx)
   1297 {
   1298     /* Input parameters check. */
   1299     if ((NULL == f_presel) || (NULL == lt_fs) || (NULL == tcam_idx)) {
   1300         return (BCM_E_PARAM);
   1301     }
   1302 
   1303     /* Requested entry structure sanity check. */
   1304     if ((NULL == f_presel->group) || (NULL == f_presel->lt_fs)) {
   1305         return (BCM_E_PARAM);
   1306     }
   1307 
   1308     /* Calculate the TCAM index. */
   1309     *tcam_idx = lt_fs->start_tcam_idx + f_presel->hw_index;
   1310 
   1311     return (BCM_E_NONE);
   1312 }
   1313 
   1314 
   1315 /*
   1316  * Function:
   1317  *     _bcm_field_th_presel_tcam_key_mask_get
   1318  * Purpose:
   1319  *     Allocate & read from hw preselector tcam key/mask image.
   1320  * Parameters:
   1321  *     unit     - (IN)     BCM device number.
   1322  *     stage_fc - (IN)     Reference to Field Stage control structure.
   1323  *     inst     - (IN)     Pipe Instance.
   1324  *     f_presel - (IN/OUT) Field Presel Entry.
   1325  *     tcam     - (IN)     Reference to Presel Entry TCAM structure.
   1326  * Returns:
   1327  *     BCM_E_XXX
   1328  */
   1329 int
   1330 _bcm_field_th_presel_tcam_key_mask_get(int unit,
   1331                                    _field_stage_t *stage_fc,
   1332                                    int inst,
   1333                                    _field_presel_entry_t *f_presel,
   1334                                    _field_presel_tcam_t  *tcam)
   1335 {
   1336     uint32          tcam_key_words;      /* tcam key length */
   1337     soc_mem_t       tcam_mem;            /* TCAM Memory name */
   1338 
   1339 
   1340     /* Validate input parameters */
   1341     if (NULL == f_presel || NULL == tcam) {
   1342        return BCM_E_PARAM;
   1343     }
   1344 
   1345     /* Check if tcam info already present. */
   1346     if (NULL != f_presel->lt_tcam.key) {
   1347         return (BCM_E_NONE);
   1348     }
   1349 
   1350     if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) {
   1351         BCM_IF_ERROR_RETURN
   1352             (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, inst,
   1353                                                   _BCM_FIELD_MEM_TYPE_IFP_LT,
   1354                                                   _BCM_FIELD_MEM_VIEW_TYPE_TCAM,
   1355                                                   &tcam_mem, NULL));
   1356     } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) {
   1357         BCM_IF_ERROR_RETURN
   1358             (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, inst,
   1359                                                   _BCM_FIELD_MEM_TYPE_EM_LT,
   1360                                                   _BCM_FIELD_MEM_VIEW_TYPE_TCAM,
   1361                                                   &tcam_mem, NULL));
   1362 #if defined(BCM_FLOWTRACKER_SUPPORT)
   1363     } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) {
   1364         BCM_IF_ERROR_RETURN
   1365             (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, inst,
   1366                                                   _BCM_FIELD_MEM_TYPE_FT_LT,
   1367                                                   _BCM_FIELD_MEM_VIEW_TYPE_TCAM,
   1368                                                   &tcam_mem, NULL));
   1369 #endif
   1370     } else {
   1371         return BCM_E_PARAM;
   1372     }
   1373 
   1374     tcam_key_words = BITS2WORDS(soc_mem_field_length(unit,
   1375                                                      tcam_mem,
   1376                                                      KEYf));
   1377     /* Retrieve the key size */
   1378     tcam->key_size = WORDS2BYTES(tcam_key_words);
   1379 
   1380     /* Allocate Memory for TCAM Key and Mask */
   1381     _FP_XGS3_ALLOC(tcam->key, tcam->key_size,
   1382                     "IFP_LOGICAL_TABLE_SELECT_TCAM_ONLY Key Alloc.");
   1383     if (tcam->key == NULL) {
   1384        return BCM_E_MEMORY;
   1385     }
   1386     _FP_XGS3_ALLOC(tcam->mask, tcam->key_size,
   1387                     "IFP_LOGICAL_TABLE_SELECT_TCAM_ONLY Mask Alloc.");
   1388     if (tcam->mask == NULL) {
   1389        sal_free(tcam->key);
   1390        tcam->key = NULL;
   1391        return BCM_E_MEMORY;
   1392     }
   1393 
   1394     return (BCM_E_NONE);
   1395 }
   1396 
   1397 /*
   1398  * Function:
   1399  *     _bcm_field_th_presel_mem_data_get
   1400  * Purpose:
   1401  *     Allocate & read from hw preselector data image.
   1402  * Parameters:
   1403  *     unit     - (IN)     BCM device number.
   1404  *     stage_fc - (IN)     Reference to Field Stage control structure.
   1405  *     inst     - (IN)     Pipe Instance.
   1406  *     f_presel - (IN/OUT) Field Presel Entry.
   1407  *     p_data   - (OUT)    Reference to Presel Entry Data structure.
   1408  * Returns:
   1409  *     BCM_E_XXX
   1410  */
   1411 int
   1412 _bcm_field_th_presel_mem_data_get(int unit,
   1413                                   _field_stage_t *stage_fc,
   1414                                   int inst,
   1415                                   _field_presel_entry_t *f_presel,
   1416                                   _field_presel_data_t *p_data)
   1417 {
   1418     int             rv;                           /* Operation return status. */
   1419     int             data_idx;                           /* Data Mem index.    */
   1420     soc_mem_t       lt_mem;                             /* LT TCAM-DATA mem.  */
   1421     uint32          mem_entry[SOC_MAX_MEM_FIELD_WORDS]; /* Entry buffer.      */
   1422 
   1423     /* Validate input parameters */
   1424     if (NULL == f_presel || NULL == p_data ||
   1425         NULL == stage_fc) {
   1426        return BCM_E_PARAM;
   1427     }
   1428 
   1429     /* Check if tcam info already present. */
   1430     if (NULL != f_presel->lt_data.data) {
   1431         return (BCM_E_NONE);
   1432     }
   1433 
   1434     if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) {
   1435         BCM_IF_ERROR_RETURN
   1436             (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, inst,
   1437                                                   _BCM_FIELD_MEM_TYPE_IFP_LT,
   1438                                                   _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB,
   1439                                                   &lt_mem, NULL));
   1440     } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) {
   1441         BCM_IF_ERROR_RETURN
   1442             (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, inst,
   1443                                                   _BCM_FIELD_MEM_TYPE_EM_LT,
   1444                                                   _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB,
   1445                                                   &lt_mem, NULL));
   1446 #if defined(BCM_FLOWTRACKER_SUPPORT)
   1447     } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) {
   1448         /* Getting mem for Data table as combo is not supported */
   1449         BCM_IF_ERROR_RETURN
   1450             (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, inst,
   1451                                                   _BCM_FIELD_MEM_TYPE_FT_LT,
   1452                                                   _BCM_FIELD_MEM_VIEW_TYPE_DATA,
   1453                                                   NULL, &lt_mem));
   1454 #endif
   1455     } else {
   1456         return BCM_E_PARAM;
   1457     }
   1458 
   1459     /* Get data field size in logical table entry. */
   1460     if (!SOC_IS_TOMAHAWK3(unit)) {
   1461     p_data->data_size = WORDS2BYTES(soc_mem_field_length(unit,
   1462                                     lt_mem, DATAf));
   1463     } else {
   1464        p_data->data_size = 57;
   1465     }
   1466 
   1467     /* Allocate Memory for SRAM Data */
   1468     _FP_XGS3_ALLOC(p_data->data, p_data->data_size,
   1469                    "IFP_LOGICAL_TABLE_SELECT Data Alloc.");
   1470     if (p_data->data == NULL) {
   1471        return BCM_E_MEMORY;
   1472     }
   1473 
   1474     if (!(f_presel->flags & _FP_ENTRY_DIRTY)) {
   1475        /* Get entry Data Entry index. */
   1476        rv = _bcm_field_presel_entry_tcam_idx_get(unit, f_presel,
   1477                                                  f_presel->lt_fs, &data_idx);
   1478        if (BCM_FAILURE(rv)) {
   1479           goto bcm_error;
   1480        }
   1481 
   1482        /* Read entry part from hardware. */
   1483        rv = soc_mem_read(unit, lt_mem, MEM_BLOCK_ANY, data_idx,
   1484                          mem_entry);
   1485        if (BCM_FAILURE(rv)) {
   1486           goto bcm_error;
   1487        }
   1488 
   1489     if (!SOC_IS_TOMAHAWK3(unit)) {
   1490        /* Get entry Data value. */
   1491        soc_mem_field_get(unit, lt_mem, mem_entry, DATAf,
   1492                          p_data->data);
   1493     }
   1494     }
   1495 
   1496     return (BCM_E_NONE);
   1497 
   1498 bcm_error:
   1499     sal_free(p_data->data);
   1500     p_data->data = NULL;
   1501     return rv;
   1502 }
   1503 
   1504 
   1505 /*
   1506  * Function:
   1507  *     _field_presel_qual_value_set
   1508  *
   1509  * Purpose:
   1510  *     Set a qualifier field from the designated data and mask arrays.
   1511  *
   1512  * Parameters:
   1513  *     unit     - (IN) BCM devices number
   1514  *     stage_fc - (IN) Stage field control structure.
   1515  *     inst     - (IN) Pipe Instance.
   1516  *     qi       - (IN) Qualifier offset inside tcam.
   1517  *     f_presel - (IN) Field Presel entry descriptor.
   1518  *     p_data   - (IN) Inserted data.
   1519  *     p_mask   - (IN) Data mask.
   1520  * Returns:
   1521  *     BCM_E_XXX
   1522  */
   1523 STATIC int
   1524 _field_presel_qual_value_set(int unit, _field_stage_t *stage_fc,
   1525                              int inst, _qual_info_t *qi,
   1526                              _field_presel_entry_t *f_presel,
   1527                              uint32 *p_data, uint32 *p_mask)
   1528 {
   1529     int                 rv;         /* Operation return status. */
   1530     uint32              u32_mask,
   1531                         *p_fn_data, *p_fn_mask;
   1532     int                 idx, wp, bp, len;
   1533 
   1534 #undef DATA_TOO_BIG_FOR_FIELD
   1535 #define DATA_TOO_BIG_FOR_FIELD ((p_data[idx] & ~u32_mask) != 0)
   1536 
   1537     wp = qi->offset / 32;
   1538     bp = qi->offset & (32 - 1);
   1539     idx = 0;
   1540     p_fn_data = p_fn_mask = NULL;
   1541 
   1542     LOG_DEBUG(BSL_LS_BCM_FP,
   1543               (BSL_META_U(unit,
   1544               "vverb: qi={offset=%d, width=%d}, data=0x%08x, mask=0x%08x\n"),
   1545                qi->offset, qi->width, *p_data, *p_mask));
   1546 
   1547     /* Allocate memory for TCAM Key and Mask. */
   1548     rv = _bcm_field_th_presel_tcam_key_mask_get(unit, stage_fc, inst,
   1549                                             f_presel, &f_presel->lt_tcam);
   1550     if (BCM_FAILURE(rv)) {
   1551        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1552          "Error: Unable to allocate the Presel Entry TCAM Key and Mask.\n\r")));
   1553        return rv;
   1554     }
   1555 
   1556     switch (qi->fpf) {
   1557       case KEYf:
   1558            p_fn_data = f_presel->lt_tcam.key;
   1559            p_fn_mask = f_presel->lt_tcam.mask;
   1560            break;
   1561 
   1562       default:
   1563           LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1564                    "Error: Bad TCAM field=%#05x\n"), qi->fpf));
   1565           return (BCM_E_INTERNAL);
   1566     };
   1567 
   1568     for (len = qi->width; len > 0; len -= 32) {
   1569         if (bp) {
   1570             if (len < 32) {
   1571                 u32_mask = (1 << len) - 1;
   1572                 /* Chop mask to fit mask field. */
   1573                 p_mask[idx] &= u32_mask;
   1574                 if (DATA_TOO_BIG_FOR_FIELD) {
   1575                     LOG_ERROR(BSL_LS_BCM_FP,
   1576                               (BSL_META_U(unit,
   1577                                           "FP(unit %d) Error: data=%#x "),
   1578                                unit, *p_data));
   1579                     LOG_ERROR(BSL_LS_BCM_FP,
   1580                               (BSL_META_U(unit,
   1581                                           "or mask=%#x too big for field\n"),
   1582                                *p_mask));
   1583                     return (BCM_E_PARAM);
   1584                 }
   1585             } else {
   1586                 u32_mask = 0xffffffff;
   1587             }
   1588 
   1589             p_fn_data[wp] &= ~(u32_mask << bp);
   1590             p_fn_data[wp] |= p_data[idx] << bp;
   1591 
   1592             /* coverity[ptr_arith : FALSE] */
   1593             p_fn_mask[wp] &= ~(u32_mask << bp);
   1594             p_fn_mask[wp++] |= p_mask[idx] << bp;
   1595 
   1596             p_fn_data[wp] &= ~(u32_mask >> (32 - bp));
   1597             p_fn_data[wp] |= p_data[idx] >> (32 - bp) & ((1 << bp) - 1);
   1598 
   1599             p_fn_mask[wp] &= ~(u32_mask >> (32 - bp));
   1600             p_fn_mask[wp] |= p_mask[idx] >> (32 - bp) & ((1 << bp) - 1);
   1601         } else {
   1602             if (len < 32) {
   1603                 u32_mask = (1 << len) - 1;
   1604                 /* Chop mask to fit mask field. */
   1605                 p_mask[idx] &= u32_mask;
   1606                 if (DATA_TOO_BIG_FOR_FIELD) {
   1607                     LOG_ERROR(BSL_LS_BCM_FP,
   1608                               (BSL_META_U(unit,
   1609                                "Error: data=%#x or mask=%#x "
   1610                                "too big for field\n\r"),
   1611                                *p_data, *p_mask));
   1612                     return (BCM_E_PARAM);
   1613                 }
   1614                 p_fn_data[wp] &= ~u32_mask;
   1615                 p_fn_data[wp] |= p_data[idx];
   1616                 /* coverity[ptr_arith : FALSE] */
   1617                 p_fn_mask[wp] &= ~u32_mask;
   1618                 p_fn_mask[wp++] |= p_mask[idx];
   1619             } else {
   1620                 p_fn_data[wp] = p_data[idx];
   1621                 /* coverity[ptr_arith : FALSE] */
   1622                 p_fn_mask[wp++] = p_mask[idx];
   1623             }
   1624         }
   1625 
   1626         idx++;
   1627     }
   1628 
   1629     f_presel->flags |= _FP_ENTRY_DIRTY;
   1630     f_presel->flags &= ~(_FP_ENTRY_POLICY_TABLE_ONLY_DIRTY);
   1631     return (BCM_E_NONE);
   1632 }
   1633 #undef DATA_TOO_BIG_FOR_FIELD
   1634 
   1635 
   1636 /*
   1637  * Function:
   1638  *     _field_presel_qual_part_value_set
   1639  *
   1640  * Purpose:
   1641  *     Set a preselector qualifier field from the designated
   1642  *     data and mask arrays.
   1643  *
   1644  * Parameters:
   1645  *     unit      - (IN) BCM devices number
   1646  *     stage_fc  - (IN) Stage field control structure.
   1647  *     inst      - (IN) Pipe Instance.
   1648  *     q_offset  - (IN) Qualifier offset inside tcam.
   1649  *     qual_part - (IN) Split qualifier part.
   1650  *     f_presel  - (IN) Field entry descriptor.
   1651  *     p_data    - (IN) Inserted data.
   1652  *     p_mask    - (IN) Data mask.
   1653  * Returns:
   1654  *     BCM_E_XXX
   1655  */
   1656 STATIC int
   1657 _field_presel_qual_part_value_set(int unit, _field_stage_t *stage_fc, int inst,
   1658                                   _bcm_field_qual_offset_t *q_offset,
   1659                                   uint8 qual_part,
   1660                                   _field_presel_entry_t *f_presel,
   1661                                   uint32 *p_data, uint32 *p_mask)
   1662 {
   1663     int                       rv;         /* Operation return status. */
   1664     int                       idx = 0,
   1665                               offset = 0;
   1666     _qual_info_t              qi;
   1667     _bcm_field_qual_data_t    data;
   1668     _bcm_field_qual_data_t    mask;
   1669 
   1670     /* Input parameters check. */
   1671     if ((NULL == q_offset) || (NULL == f_presel) ||
   1672         (NULL == p_data) || (NULL == p_mask)) {
   1673         return (BCM_E_PARAM);
   1674     }
   1675 
   1676     /* Primary offset handling. */
   1677     sal_memset(&qi, 0, sizeof(_qual_info_t));
   1678     qi.fpf = q_offset->field;
   1679     qi.offset = q_offset->offset[qual_part];
   1680     qi.width = q_offset->width[qual_part];
   1681     /* calculate offset */
   1682     for (idx = 0; idx < qual_part; idx++) {
   1683         offset += q_offset->width[idx];
   1684     }
   1685 
   1686     /* Split primary portion of the qualifier. */
   1687     rv = _bcm_field_qual_partial_data_get (p_data, offset,
   1688                                            qi.width, data);
   1689     BCM_IF_ERROR_RETURN(rv);
   1690     rv = _bcm_field_qual_partial_data_get(p_mask, offset,
   1691                                           qi.width, mask);
   1692     BCM_IF_ERROR_RETURN(rv);
   1693 
   1694     /* Program qualifier into tcam */
   1695     rv = _field_presel_qual_value_set(unit, stage_fc, inst, &qi,
   1696                                       f_presel, data, mask);
   1697     return (rv);
   1698 }
   1699 
   1700 
   1701 /*
   1702  * Function:
   1703  *     _bcm_field_presel_qual_value_set
   1704  *
   1705  * Purpose:
   1706  *     Set a preselector qual field from the designated data and mask arrays.
   1707  *
   1708  * Parameters:
   1709  *     unit     - (IN) BCM devices number
   1710  *     stage_fc - (IN) Stage field control structure.
   1711  *     inst     - (IN) Pipe Instance.
   1712  *     q_offset - (IN) Qualifier offset inside tcam.
   1713  *     f_presel - (IN) Field Preselector entry descriptor.
   1714  *     p_data   - (IN) Inserted data.
   1715  *     p_mask   - (IN) Data mask.
   1716  *
   1717  * Returns:
   1718  *     BCM_E_XXX
   1719  */
   1720 
   1721 STATIC int
   1722 _bcm_field_presel_qual_value_set(int unit, _field_stage_t *stage_fc, int inst,
   1723                                  _bcm_field_qual_offset_t *q_offset,
   1724                                  _field_presel_entry_t *f_presel,
   1725                                  uint32 *p_data, uint32 *p_mask)
   1726 {
   1727     int    rv;
   1728     uint8  qual_part;
   1729 
   1730     LOG_DEBUG(BSL_LS_BCM_FP,
   1731               (BSL_META_U(unit,
   1732                           "_bcm_field_qual_value_set\n")));
   1733 
   1734     /* Input parameters check. */
   1735     if ((NULL == stage_fc) || (NULL == q_offset) || (NULL == f_presel) ||
   1736         (NULL == p_data) || (NULL == p_mask)) {
   1737         return (BCM_E_PARAM);
   1738     }
   1739 
   1740     /* Iterate for the number of offsets handling. */
   1741     for (qual_part = 0; qual_part < q_offset->num_offsets; qual_part++) {
   1742         if (q_offset->width[qual_part] > 0)
   1743         {
   1744            rv = _field_presel_qual_part_value_set(unit, stage_fc, inst,
   1745                                                   q_offset, qual_part, f_presel,
   1746                                                   p_data, p_mask);
   1747            BCM_IF_ERROR_RETURN(rv);
   1748         }
   1749     }
   1750 
   1751     return (BCM_E_NONE);
   1752 }
   1753 
   1754 
   1755 /*
   1756  * Function: _bcm_field_presel_qualify_set
   1757  *
   1758  * Purpose:
   1759  *     Qualify the presel for the given qualifier
   1760  *
   1761  * Parameters:
   1762  *     unit      - (IN) BCM device number.
   1763  *     entry     - (IN) Entry ID contains preselector Id.
   1764  *     qual      - (IN) Qualifier Id.
   1765  *     data      - (IN) Data
   1766  *     mask      - (IN) Mask
   1767  *
   1768  * Returns:
   1769  *     BCM_E_PARAM     - presel contained in entry id is not valid
   1770  *                       or presel == NULL.
   1771  *     BCM_E_NOT_FOUND - presel id is not found.
   1772  *     BCM_E_NONE      - returns on Success
   1773  */
   1774 
   1775 int
   1776 _bcm_field_presel_qualify_set(int unit,
   1777                               bcm_field_entry_t entry,
   1778                               bcm_field_qualify_t qual,
   1779                               uint32 *data,
   1780                               uint32 *mask)
   1781 {
   1782     int                       rv;               /* Operation return status. */
   1783     int                       inst;             /* Pipe Instance. */
   1784     int                       width;            /* Qualifier Width. */
   1785     bcm_field_presel_t        presel;           /* Presel id. */
   1786     _field_presel_entry_t     *f_presel = NULL; /* Presel Entry descriptor. */
   1787     _field_control_t          *fc;              /* Field control structure. */
   1788     _field_stage_t            *stage_fc;        /* Field Stage structure. */
   1789     _bcm_field_qual_offset_t  q_offset;         /* Qualifier offset instance. */
   1790     _field_stage_id_t         stage_id;         /* Stage id. */
   1791 
   1792     /* Preselector feature check */
   1793     if (!soc_feature(unit, soc_feature_field_preselector_support)) {
   1794        return BCM_E_UNAVAIL;
   1795     }
   1796 
   1797     /* Retrieve the control structure */
   1798     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   1799 
   1800     /* Resolve the Preselector ID from the given Entry ID */
   1801     rv = _bcm_field_entry_presel_resolve(unit, entry, &presel, &f_presel);
   1802     if (BCM_FAILURE(rv)) {
   1803        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1804                "ERROR: Unable to resolve the Presel Entry ID %d.\n\r"), entry));
   1805        return rv;
   1806     }
   1807 
   1808 
   1809     /* Verify and update the mandate qualifier. */
   1810     if (qual == bcmFieldQualifyStage) {
   1811        bcm_field_stage_t stage;
   1812 
   1813        stage = *data;
   1814        if (_BCM_FIELD_PRESEL_IS_STAGE_SUPPORTED(stage) == FALSE) {
   1815           LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1816               "ERROR: Preselector doesn't support the given stage:[%d].\n\r"),
   1817               stage));
   1818           return BCM_E_PARAM;
   1819        }
   1820 
   1821        if ((stage == bcmFieldStageIngressFlowtracker) &&
   1822            ((!soc_feature(unit, soc_feature_field_flowtracker_support)) ||
   1823             (soc_property_get(unit, spn_FLOWTRACKER_ENABLE, 1) != 1))) {
   1824            LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1825                 "ERROR: Stage is not available.")));
   1826            return BCM_E_UNAVAIL;
   1827        }
   1828 
   1829        if (BCM_FIELD_QSET_TEST(f_presel->p_qset, qual)) {
   1830           if (((stage == bcmFieldStageIngress) &&
   1831                (BCM_FIELD_QSET_TEST(f_presel->p_qset,
   1832                                     bcmFieldQualifyStageIngress))) ||
   1833               ((stage == bcmFieldStageIngressExactMatch) &&
   1834                (BCM_FIELD_QSET_TEST(f_presel->p_qset,
   1835                           bcmFieldQualifyStageIngressExactMatch))) ||
   1836               ((stage == bcmFieldStageIngressFlowtracker) &&
   1837                (BCM_FIELD_QSET_TEST(f_presel->p_qset,
   1838                           bcmFieldQualifyStageIngressFlowtracker)))) {
   1839               return BCM_E_NONE;
   1840           }
   1841 
   1842          /*
   1843           * If the entry's lt_tcam->key is not NULL, indicates some other
   1844           * non-stage qualifier is associated to the presel entry.
   1845           */
   1846           if (f_presel->lt_tcam.key != NULL) {
   1847              LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1848                 "ERROR: Stage is already associated with the given Presel"
   1849                 " Entry[%d] and the entry is in use.\n\r"), presel));
   1850              return BCM_E_BUSY;
   1851           }
   1852        }
   1853 
   1854        BCM_FIELD_QSET_INIT(f_presel->p_qset);
   1855        BCM_FIELD_QSET_ADD(f_presel->p_qset, bcmFieldQualifyStage);
   1856        if (stage == bcmFieldStageIngress) {
   1857             BCM_FIELD_QSET_ADD(f_presel->p_qset, bcmFieldQualifyStageIngress);
   1858        } else if (stage == bcmFieldStageIngressExactMatch) {
   1859             BCM_FIELD_QSET_ADD(f_presel->p_qset,
   1860                                        bcmFieldQualifyStageIngressExactMatch);
   1861        } else  { /* stage == bcmFieldStageIngressFlowtracker */
   1862             BCM_FIELD_QSET_ADD(f_presel->p_qset,
   1863                                        bcmFieldQualifyStageIngressFlowtracker);
   1864        }
   1865 
   1866        return BCM_E_NONE;
   1867     } else {
   1868         /* Verify if the Presel Entry is already associated with the stage. */
   1869         if (BCM_FIELD_QSET_TEST(f_presel->p_qset, bcmFieldQualifyStage)
   1870                                                                      == FALSE) {
   1871             LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1872                "ERROR: Preselector Entry[%d] doesn't associated with any stage."
   1873                "\n\rIt is mandate to qualify the Stage first.\n\r"), presel));
   1874             return BCM_E_PARAM;
   1875         }
   1876     }
   1877 
   1878     /* Retrieve the stage id. */
   1879     if (BCM_FIELD_QSET_TEST(f_presel->p_qset, bcmFieldQualifyStageIngress)) {
   1880         stage_id = _BCM_FIELD_STAGE_INGRESS;
   1881     } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset,
   1882                                     bcmFieldQualifyStageIngressExactMatch)) {
   1883         stage_id = _BCM_FIELD_STAGE_EXACTMATCH;
   1884 #if defined(BCM_FLOWTRACKER_SUPPORT)
   1885     } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset,
   1886                                     bcmFieldQualifyStageIngressFlowtracker)) {
   1887         stage_id = _BCM_FIELD_STAGE_FLOWTRACKER;
   1888 #endif
   1889     } else {
   1890         return BCM_E_INTERNAL;
   1891     }
   1892 
   1893     /* Get stage field control structure. */
   1894     BCM_IF_ERROR_RETURN
   1895         (_field_stage_control_get(unit, stage_id, &stage_fc));
   1896 
   1897     /* Pkt flow mandate qualifier */
   1898     if (qual == bcmFieldQualifyPktFlowType) {
   1899         _bcm_field_internal_qualify_t _qual;
   1900 
   1901         if (BCM_FIELD_QSET_TEST(f_presel->p_qset, qual)) {
   1902            return BCM_E_EXISTS;
   1903         }
   1904 
   1905         switch (*data) {
   1906            case bcmFieldPktFlowTypeTunnelNone:
   1907                _qual = _bcmFieldQualifyPktFlowTypeTunnelNone;
   1908                break;
   1909            case bcmFieldPktFlowTypeTunnelL2:
   1910                _qual = _bcmFieldQualifyPktFlowTypeTunnelL2;
   1911                break;
   1912            case bcmFieldPktFlowTypeTunnelL3:
   1913                _qual = _bcmFieldQualifyPktFlowTypeTunnelL3;
   1914                break;
   1915            default:
   1916                return BCM_E_PARAM;
   1917         }
   1918         BCM_FIELD_QSET_ADD(f_presel->p_qset, qual);
   1919         BCM_FIELD_QSET_ADD(f_presel->p_qset, _qual);
   1920         return BCM_E_NONE;
   1921     }
   1922 
   1923     /* Verify if the given Qualifier belongs to Preselector QSET */
   1924     if (BCM_FIELD_QSET_TEST(stage_fc->presel_qset, qual) == FALSE) {
   1925        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1926              "ERROR: Preselector Stage doesn't support the qualifier[%s].\n\r"),
   1927              _field_qual_name(qual)));
   1928        return BCM_E_PARAM;
   1929     }
   1930 
   1931 
   1932     /* Retrieve the qualifier offset */
   1933     rv = _field_presel_qual_offset_get(unit, stage_fc, f_presel,
   1934                                        qual, &q_offset);
   1935     if (BCM_FAILURE(rv)) {
   1936        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1937            "ERROR: Unable to retrieve the qualifier's offset[%d].\n\r"), qual));
   1938        return rv;
   1939     }
   1940 
   1941     /* Check if the qualifier is associated to PktFlowType. */
   1942     if ((q_offset.flags & _BCM_FIELD_QUAL_OFFSET_FLOW_TYPE_TUNNEL_L2) ||
   1943         (q_offset.flags & _BCM_FIELD_QUAL_OFFSET_FLOW_TYPE_TUNNEL_L3) ||
   1944         (q_offset.flags & _BCM_FIELD_QUAL_OFFSET_FLOW_TYPE_TUNNEL_NONE)) {
   1945        if (!BCM_FIELD_QSET_TEST(f_presel->p_qset, bcmFieldQualifyPktFlowType)) {
   1946           LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1947                "ERROR: Preselector Entry[%d] doesn't associated with any packet flow."
   1948                "\n\rIt is mandate to associate the packet flow 'bcmFieldQualifyPktFlowType'"
   1949                " prior to '%s' configuration.\n\r"),
   1950                presel, _field_qual_name(qual)));
   1951           return BCM_E_PARAM;
   1952        }
   1953     }
   1954 
   1955     /* Combined width of a qualifier for a given part */
   1956     _BCM_FIELD_QUAL_MULTI_OFFSET_WIDTH(&q_offset, width);
   1957 
   1958     /* Validate the Qualifier Data with the offset's width. */
   1959     if (width < 32) {
   1960        if (data[0] & ~((1 << width) - 1)) {
   1961           return BCM_E_PARAM;
   1962        }
   1963     }
   1964 
   1965     /*
   1966      * Assuming Instance as 0, Pipe instance is unknown at this point and
   1967      * and also it doesn't make any difference as key and mask fields for
   1968      * a TCAM is same for all the instances.
   1969      */
   1970     inst = 0;
   1971 
   1972     /* Program data/mask pair to tcam buffer. */
   1973     /* coverity[callee_ptr_arith : FALSE] */
   1974     rv = _bcm_field_presel_qual_value_set(unit, stage_fc, inst, &q_offset,
   1975                                           f_presel, data, mask);
   1976     BCM_IF_ERROR_RETURN(rv);
   1977 
   1978     BCM_FIELD_QSET_ADD(f_presel->p_qset, qual);
   1979     f_presel->flags |= _FP_ENTRY_DIRTY;
   1980     return BCM_E_NONE;
   1981 }
   1982 
   1983 /*
   1984  * Function:
   1985  *     _field_presel_qual_value_get
   1986  *
   1987  * Purpose:
   1988  *     Retrieve a qualifier value from the designated data/mask
   1989  *     field pair, returning them to *p_data and *p_mask.
   1990  *
   1991  * Returns:
   1992  *     BCM_E_NONE - Success
   1993  */
   1994 STATIC int
   1995 _field_presel_qual_value_get(int unit, _field_stage_t *stage_fc, int inst,
   1996                              _qual_info_t *qi, _field_presel_entry_t *f_presel,
   1997                              uint32 *p_data, uint32 *p_mask)
   1998 {
   1999     int                 rv;               /* Operation return status. */
   2000     uint32              *p_fn_data, *p_fn_mask;
   2001     int                 idx, wp, bp, len;
   2002 
   2003     /* Input parameters check. */
   2004     if ((NULL == f_presel) || (NULL == p_data) ||
   2005         (NULL == qi) || (NULL == p_mask)) {
   2006         return (BCM_E_PARAM);
   2007     }
   2008 
   2009     wp = qi->offset / 32;
   2010     bp = qi->offset & (32 - 1);
   2011     idx = 0;
   2012     p_fn_data = p_fn_mask = NULL;
   2013 
   2014     /* Allocate memory for TCAM Key and Mask. */
   2015     rv = _bcm_field_th_presel_tcam_key_mask_get(unit, stage_fc, inst,
   2016                                             f_presel, &f_presel->lt_tcam);
   2017     if (BCM_FAILURE(rv)) {
   2018        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2019          "Error: Unable to allocate the Presel Entry TCAM Key and Mask.\n\r")));
   2020        return rv;
   2021     }
   2022 
   2023     switch (qi->fpf) {
   2024         case KEYf:
   2025             p_fn_data = f_presel->lt_tcam.key;
   2026             p_fn_mask = f_presel->lt_tcam.mask;
   2027             break;
   2028         default:
   2029           LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2030                    "Error: Bad TCAM field=%#05x\n"), qi->fpf));
   2031           return (BCM_E_INTERNAL);
   2032     };
   2033 
   2034     for (len = qi->width; len > 0; len -= 32) {
   2035         if ((NULL == p_fn_data) || (NULL == p_fn_mask)) {
   2036             /*
   2037              * IPBM Overlay qualifier set in the group but
   2038              * not qualified for this entry.
   2039              */
   2040             p_data[idx] = 0x0;
   2041             p_mask[idx] = 0x0;
   2042         } else {
   2043             if (bp) {
   2044                 p_data[idx] = (p_fn_data[wp] >> bp) & ((1 << (32 - bp)) - 1);
   2045                 /* coverity[ptr_arith : FALSE] */
   2046                 p_mask[idx] = (p_fn_mask[wp++] >> bp) & ((1 << (32 - bp)) - 1);
   2047                 p_data[idx] |= p_fn_data[wp] << (32 - bp);
   2048                 p_mask[idx] |= p_fn_mask[wp] << (32 - bp);
   2049             } else {
   2050                 p_data[idx] = p_fn_data[wp];
   2051                 /* coverity[ptr_arith : FALSE] */
   2052                 p_mask[idx] = p_fn_mask[wp++];
   2053             }
   2054         }
   2055 
   2056         if (len < 32) {
   2057             p_data[idx] &= ((1 << len) - 1);
   2058             p_mask[idx] &= ((1 << len) - 1);
   2059         }
   2060 
   2061         idx++;
   2062     }
   2063 
   2064     return (BCM_E_NONE);
   2065 }
   2066 
   2067 
   2068 
   2069 /*
   2070  * Function:
   2071  *     _field_presel_qual_part_value_get
   2072  *
   2073  * Purpose:
   2074  *     Get a qualifier field from the designated data and mask arrays.
   2075  *
   2076  * Parameters:
   2077  *     unit       - (IN) BCM devices number
   2078  *     stage_fc   - (IN) Stage field control structure.
   2079  *     inst       - (IN) Pipe Instance.
   2080  *     q_offset   - (IN) Qualifier offset inside tcam.
   2081  *     f_presel   - (IN) Field Presel entry descriptor.
   2082  *     p_data     - (IN) Inserted data.
   2083  *     p_mask     - (IN) Data mask.
   2084  *
   2085  * Returns:
   2086  *     BCM_E_XXX
   2087  */
   2088 STATIC int
   2089 _field_presel_qual_part_value_get(int unit, _field_stage_t *stage_fc, int inst,
   2090                                   _bcm_field_qual_offset_t *q_offset,
   2091                                   uint8 qual_part,
   2092                                   _field_presel_entry_t *f_presel,
   2093                                   _bcm_field_qual_data_t p_data,
   2094                                   _bcm_field_qual_data_t p_mask)
   2095 {
   2096     _qual_info_t qi;
   2097     int rv;
   2098     _bcm_field_qual_data_t data;
   2099     _bcm_field_qual_data_t mask;
   2100     int offset = 0, idx = 0;
   2101 
   2102     /* Input parameters check. */
   2103     if ((NULL == stage_fc) || (NULL == q_offset) || (NULL == f_presel) ||
   2104         (NULL == p_data) || (NULL == p_mask)) {
   2105         return (BCM_E_PARAM);
   2106     }
   2107 
   2108     /* Primary offset handling. */
   2109     sal_memset(&qi, 0, sizeof(_qual_info_t));
   2110 
   2111     _FP_QUAL_DATA_CLEAR(data);
   2112     _FP_QUAL_DATA_CLEAR(mask);
   2113     qi.fpf = q_offset->field;
   2114     qi.offset = q_offset->offset[qual_part];
   2115     qi.width = q_offset->width[qual_part];
   2116     /* calculate offset */
   2117     for (idx = 0; idx < qual_part; idx++) {
   2118         offset += q_offset->width[idx];
   2119     }
   2120 
   2121     /* Read qualifier information from tcam.. */
   2122     rv = _field_presel_qual_value_get(unit, stage_fc, inst, &qi,
   2123                                       f_presel, data, mask);
   2124     BCM_IF_ERROR_RETURN(rv);
   2125 
   2126     /* Split primary portion of the qualifier. */
   2127     rv = _bcm_field_qual_partial_data_set(data, offset,
   2128                                           qi.width, p_data);
   2129     BCM_IF_ERROR_RETURN(rv);
   2130     rv = _bcm_field_qual_partial_data_set(mask, offset,
   2131                                           qi.width, p_mask);
   2132     BCM_IF_ERROR_RETURN(rv);
   2133 
   2134     return (BCM_E_NONE);
   2135 }
   2136 
   2137 
   2138 /*
   2139  * Function:
   2140  *     _bcm_field_presel_value_get
   2141  *
   2142  * Purpose:
   2143  *     Get a qualifier field from the designated data and mask arrays.
   2144  *
   2145  * Parameters:
   2146  *     unit     - (IN) BCM devices number
   2147  *     stage_fc - (IN) Stage field control structure.
   2148  *     inst     - (IN) Pipe Instance.
   2149  *     q_offset - (IN) Qualifier offset inside tcam.
   2150  *     f_presel - (IN) Field presel entry descriptor.
   2151  *     p_data   - (IN) Inserted data.
   2152  *     p_mask   - (IN) Data mask.
   2153  *
   2154  * Returns:
   2155  *     BCM_E_XXX
   2156  */
   2157 STATIC int
   2158 _bcm_field_presel_qual_value_get(int unit, _field_stage_t *stage_fc, int inst,
   2159                                  _bcm_field_qual_offset_t *q_offset,
   2160                                  _field_presel_entry_t *f_presel,
   2161                                  _bcm_field_qual_data_t p_data,
   2162                                  _bcm_field_qual_data_t p_mask)
   2163 {
   2164     int rv, qual_part;
   2165 
   2166     /* Input parameters check. */
   2167     if ((NULL == stage_fc) || (NULL == q_offset) || (NULL == f_presel) ||
   2168         (NULL == p_data) || (NULL == p_mask)) {
   2169         return (BCM_E_PARAM);
   2170     }
   2171 
   2172     _FP_QUAL_DATA_CLEAR(p_data);
   2173     _FP_QUAL_DATA_CLEAR(p_mask);
   2174 
   2175     /* offset handling */
   2176     for (qual_part = 0; qual_part < q_offset->num_offsets; qual_part++) {
   2177         if (q_offset->width[qual_part] > 0)
   2178         {
   2179            rv = _field_presel_qual_part_value_get(unit, stage_fc, inst,
   2180                                                   q_offset, qual_part,
   2181                                                   f_presel, p_data, p_mask);
   2182            BCM_IF_ERROR_RETURN(rv);
   2183         }
   2184     }
   2185 
   2186     return (BCM_E_NONE);
   2187 }
   2188 
   2189 
   2190 /*
   2191  * Function:
   2192  *     _bcm_field_presel_qualifier_get
   2193  *
   2194  * Purpose:
   2195  *     Get qualifier match value and mask.
   2196  *
   2197  * Parameters:
   2198  *     unit      - BCM device number
   2199  *     entry     - Entry id.
   2200  *     qual_id   - qualifier id.
   2201  *     q_data    - Qualifier data array.
   2202  *     q_mask    - Qualifier mask array.
   2203  * Returns:
   2204  *     Nothing.
   2205  */
   2206 int
   2207 _bcm_field_presel_qualifier_get(int unit,
   2208                                 bcm_field_entry_t entry,
   2209                                 int qual_id,
   2210                                 _bcm_field_qual_data_t q_data,
   2211                                 _bcm_field_qual_data_t q_mask)
   2212 {
   2213     _bcm_field_qual_offset_t  q_offset;    /* Qualifier offset in the tcam. */
   2214     _field_presel_entry_t     *f_presel;   /* Field entry structure.        */
   2215     bcm_field_presel_t        presel;      /* Field Preselector ID.         */
   2216     int                       rv;          /* Operation return status.      */
   2217     int                       inst;        /* Pipe Instance.                */
   2218     _field_stage_t           *stage_fc;
   2219     _field_control_t         *fc;
   2220     _field_stage_id_t         stage_id;    /* Stage id. */
   2221 
   2222     /* Preselector feature check */
   2223     if (!soc_feature(unit, soc_feature_field_preselector_support)) {
   2224        return BCM_E_UNAVAIL;
   2225     }
   2226 
   2227     /* Retrieve the control structure */
   2228     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   2229 
   2230     /* Resolve the Preselector ID from the given Entry ID */
   2231     rv = _bcm_field_entry_presel_resolve(unit, entry, &presel, &f_presel);
   2232     if (BCM_FAILURE(rv)) {
   2233        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2234                "ERROR: Unable to resolve the Presel Entry ID %d.\n\r"), entry));
   2235        return rv;
   2236     }
   2237 
   2238     /* Verify and update the mandate qualifier. */
   2239     if (qual_id == bcmFieldQualifyStage) {
   2240        if (BCM_FIELD_QSET_TEST(f_presel->p_qset, bcmFieldQualifyStageIngress)) {
   2241            q_data[0] = q_mask[0] = bcmFieldStageIngress;
   2242        } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset,
   2243                                        bcmFieldQualifyStageIngressExactMatch)) {
   2244            q_data[0] = q_mask[0] = bcmFieldStageIngressExactMatch;
   2245 #if defined(BCM_FLOWTRACKER_SUPPORT)
   2246        } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset,
   2247                                        bcmFieldQualifyStageIngressFlowtracker)) {
   2248            q_data[0] = q_mask[0] = bcmFieldStageIngressFlowtracker;
   2249 #endif
   2250        }
   2251        return BCM_E_NONE;
   2252     }
   2253 
   2254     if (qual_id == bcmFieldQualifyPktFlowType) {
   2255        if (BCM_FIELD_QSET_TEST(f_presel->p_qset, _bcmFieldQualifyPktFlowTypeTunnelNone)) {
   2256            q_data[0] = q_mask[0] = bcmFieldPktFlowTypeTunnelNone;
   2257        } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset, _bcmFieldQualifyPktFlowTypeTunnelL3)) {
   2258            q_data[0] = q_mask[0] = bcmFieldPktFlowTypeTunnelL3;
   2259        } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset, _bcmFieldQualifyPktFlowTypeTunnelL2)) {
   2260            q_data[0] = q_mask[0] = bcmFieldPktFlowTypeTunnelL2;
   2261        } else {
   2262            return BCM_E_NOT_FOUND;
   2263        }
   2264        return BCM_E_NONE;
   2265     }
   2266 
   2267     /* Retrieve the stage id. */
   2268     if (BCM_FIELD_QSET_TEST(f_presel->p_qset, bcmFieldQualifyStageIngress)) {
   2269         stage_id = _BCM_FIELD_STAGE_INGRESS;
   2270     } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset,
   2271                                     bcmFieldQualifyStageIngressExactMatch)) {
   2272         stage_id = _BCM_FIELD_STAGE_EXACTMATCH;
   2273 #if defined(BCM_FLOWTRACKER_SUPPORT)
   2274     } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset,
   2275                                     bcmFieldQualifyStageIngressFlowtracker)) {
   2276         stage_id = _BCM_FIELD_STAGE_FLOWTRACKER;
   2277 #endif
   2278     } else {
   2279         return BCM_E_INTERNAL;
   2280     }
   2281 
   2282     /* Get stage field control structure. */
   2283     BCM_IF_ERROR_RETURN
   2284         (_field_stage_control_get(unit, stage_id, &stage_fc));
   2285 
   2286 
   2287     /* Verify if the given Qualifier belongs to Preselector QSET */
   2288     if (BCM_FIELD_QSET_TEST(stage_fc->presel_qset, qual_id) == FALSE) {
   2289        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2290              "ERROR: Preselector Stage doesn't support the qualifier[%s].\n\r"),
   2291              _field_qual_name(qual_id)));
   2292        return BCM_E_PARAM;
   2293     }
   2294 
   2295     /* Initialize q_offset to NULL */
   2296     sal_memset(&q_offset, 0x0, sizeof(q_offset));
   2297 
   2298     /* Retrieve the Qualifier offsets */
   2299     rv = _field_presel_qual_offset_get(unit, stage_fc, f_presel,
   2300                                        qual_id, &q_offset);
   2301     if (BCM_FAILURE(rv)) {
   2302        return rv;
   2303     }
   2304 
   2305     /* Instance setting to 0 */
   2306     inst = 0;
   2307 
   2308     /* Read qualifier match value and mask. */
   2309     rv = _bcm_field_presel_qual_value_get(unit, stage_fc, inst, &q_offset,
   2310                                           f_presel, q_data, q_mask);
   2311     return (BCM_E_NONE);
   2312 }
   2313 
   2314 #if defined(BCM_TOMAHAWK_SUPPORT)
   2315 /*
   2316  * Dump Preselector Qualifiers.
   2317  */
   2318 int
   2319 _bcm_field_presel_qualifiers_dump(int unit, bcm_field_presel_t presel_id)
   2320 {
   2321     _bcm_field_qual_offset_t  q_offset;    /* Qualifier offset in the tcam. */
   2322     _field_presel_entry_t     *f_presel;   /* Field entry structure.        */
   2323     bcm_field_entry_t         entry;       /* Field entry structure.        */
   2324     int                       rv;          /* Operation return status.      */
   2325     int                       inst = 0;    /* Pipe Instance.                */
   2326     int                       idx = 0;
   2327     int                       num_qual = 0;
   2328     _field_stage_t           *stage_fc;
   2329     _field_control_t         *fc;
   2330     _bcm_field_qual_data_t   q_data;
   2331     _bcm_field_qual_data_t   q_mask;
   2332     int                      qual_id;
   2333     _field_stage_id_t        stage_id;         /* Stage id. */
   2334     bcm_field_src_class_t    data;        /* MixedSrcClassId data */
   2335     bcm_field_src_class_t    mask;        /* MixedSrcClassId mask */
   2336 
   2337     /* Preselector feature check */
   2338     if (!soc_feature(unit, soc_feature_field_preselector_support)) {
   2339        return BCM_E_UNAVAIL;
   2340     }
   2341 
   2342     /* Retrieve the control structure */
   2343     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   2344 
   2345     /* Check if presel ID present in presel_set */
   2346     if (!BCM_FIELD_PRESEL_TEST(fc->presel_info->presel_set, presel_id)) {
   2347        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2348                  "ERROR: Preselector ID[%d] not found.\n\r"), presel_id));
   2349        return BCM_E_NOT_FOUND;
   2350     }
   2351 
   2352     /* Retrieve the Presel Entry */
   2353     rv = _bcm_field_presel_entry_get(unit, presel_id, &f_presel);
   2354     if (BCM_FAILURE(rv)) {
   2355         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2356               "ERROR: Couldn't retrieve the Preselector Entry for the given"
   2357               " Presel ID[%d].\n\r"), presel_id));
   2358         return rv;
   2359     }
   2360 
   2361     /* Retrieve the stage id. */
   2362     if (BCM_FIELD_QSET_TEST(f_presel->p_qset, bcmFieldQualifyStageIngress)) {
   2363         stage_id = _BCM_FIELD_STAGE_INGRESS;
   2364     } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset,
   2365                                     bcmFieldQualifyStageIngressExactMatch)) {
   2366         stage_id = _BCM_FIELD_STAGE_EXACTMATCH;
   2367 #if defined(BCM_FLOWTRACKER_SUPPORT)
   2368     } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset,
   2369                                     bcmFieldQualifyStageIngressFlowtracker)) {
   2370         stage_id = _BCM_FIELD_STAGE_FLOWTRACKER;
   2371 #endif
   2372     } else {
   2373         return BCM_E_INTERNAL;
   2374     }
   2375 
   2376     /* Get stage field control structure. */
   2377     BCM_IF_ERROR_RETURN
   2378         (_field_stage_control_get(unit, stage_id, &stage_fc));
   2379 
   2380     /* Get the entry ID from presel ID */
   2381     BCM_FIELD_PRESEL_ENTRY_SET(entry, presel_id);
   2382 
   2383     for (qual_id = 0; qual_id < _bcmFieldQualifyCount; qual_id++) {
   2384         /* Verify if the given Qualifier belongs to Preselector QSET */
   2385         if (BCM_FIELD_QSET_TEST(f_presel->p_qset, qual_id) == FALSE) {
   2386            continue;
   2387         }
   2388 
   2389         if ((qual_id == bcmFieldQualifyStage) ||
   2390             (qual_id == bcmFieldQualifyStageIngress) ||
   2391             (qual_id == bcmFieldQualifyStageIngressExactMatch) ||
   2392             (qual_id == bcmFieldQualifyStageIngressFlowtracker) ||
   2393             (qual_id == _bcmFieldQualifyPktFlowTypeTunnelNone) ||
   2394             (qual_id == _bcmFieldQualifyPktFlowTypeTunnelL2) ||
   2395             (qual_id == _bcmFieldQualifyPktFlowTypeTunnelL3) ||
   2396             (qual_id == bcmFieldQualifyPktFlowType)) {
   2397             continue;
   2398         }
   2399 
   2400         LOG_CLI((BSL_META_U(unit, "  %-10s\n\r"), _field_qual_name(qual_id)));
   2401         /* Initialize q_offset to NULL */
   2402         sal_memset(&q_offset, 0x0, sizeof(q_offset));
   2403 
   2404         /* Retrieve the Qualifier offsets */
   2405         rv = _field_presel_qual_offset_get(unit, stage_fc, f_presel,
   2406                                            qual_id, &q_offset);
   2407         if (BCM_FAILURE(rv)) {
   2408            return rv;
   2409         }
   2410 
   2411         /* Instance setting to 0 */
   2412         inst = 0;
   2413 
   2414         _FP_QUAL_DATA_CLEAR(q_data);
   2415         _FP_QUAL_DATA_CLEAR(q_mask);
   2416 
   2417         /* Read qualifier match value and mask. */
   2418         BCM_IF_ERROR_RETURN (_bcm_field_presel_qual_value_get(unit, stage_fc,
   2419                                  inst, &q_offset, f_presel, q_data, q_mask));
   2420         for (idx = 0; idx <q_offset.num_offsets; idx++) {
   2421             LOG_CLI((BSL_META_U(unit, "\tOffset: %-2d Width: %-2d\n\r"),
   2422                                 q_offset.offset[idx], q_offset.width[idx]));
   2423         }
   2424 
   2425         LOG_CLI((BSL_META_U(unit, "\tData: 0x%x\n\r"), q_data[0]));
   2426         LOG_CLI((BSL_META_U(unit, "\tMask: 0x%x\n\r"), q_mask[0]));
   2427 
   2428         /* if qualifier is MixedSrcClassId */
   2429         /* print the detailed data and mask */
   2430         if ((qual_id == bcmFieldQualifyMixedSrcClassId)) {
   2431             BCM_IF_ERROR_RETURN(
   2432                _bcm_field_th_qualify_MixedSrcClassId_get(unit,
   2433                         entry, f_presel->mixed_src_class_pbmp,
   2434                            q_data[0], q_mask[0], &data, &mask));
   2435             if (mask.src_class_field != 0) {
   2436                 LOG_CLI((BSL_META_U(unit, "\tSrc Class Data: 0x%x\n\r"), data.src_class_field));
   2437                 LOG_CLI((BSL_META_U(unit, "\tSrc Class Mask: 0x%x\n\r"), mask.src_class_field));
   2438             }
   2439             if (mask.dst_class_field != 0) {
   2440                 LOG_CLI((BSL_META_U(unit, "\tDst Class Data: 0x%x\n\r"), data.dst_class_field));
   2441                 LOG_CLI((BSL_META_U(unit, "\tDst Class Mask: 0x%x\n\r"), mask.dst_class_field));
   2442             }
   2443             if (mask.udf_class != 0) {
   2444                 LOG_CLI((BSL_META_U(unit, "\tUdf Class Data: 0x%x\n\r"), data.udf_class));
   2445                 LOG_CLI((BSL_META_U(unit, "\tUdf Class Mask: 0x%x\n\r"), mask.udf_class));
   2446             }
   2447             if (mask.intf_class_port != 0) {
   2448                 LOG_CLI((BSL_META_U(unit, "\tIntf Class Port Data: 0x%x\n\r"), data.intf_class_port));
   2449                 LOG_CLI((BSL_META_U(unit, "\tIntf Class Port Mask: 0x%x\n\r"), mask.intf_class_port));
   2450             }
   2451             if (mask.intf_class_l2 != 0) {
   2452                 LOG_CLI((BSL_META_U(unit, "\tIntf Class L2 Data: 0x%x\n\r"), data.intf_class_l2));
   2453                 LOG_CLI((BSL_META_U(unit, "\tIntf Class L2 Mask: 0x%x\n\r"), mask.intf_class_l2));
   2454             }
   2455         }
   2456         /* Reference count */
   2457         num_qual = 1;
   2458     }
   2459 
   2460     if (num_qual == 0) {
   2461        LOG_CLI((BSL_META_U(unit, "No Qualifiers Associated.\n\r")));
   2462     }
   2463     return BCM_E_NONE;
   2464 }
   2465 
   2466 #endif /* BCM_TOMAHAWK_SUPPORT */
   2467 
   2468 /*
   2469  * Function:
   2470  *     _bcm_field_presel_action_params_check
   2471  * Purpose:
   2472  *     Check field action parameters.
   2473  * Parameters:
   2474  *     unit     - (IN) BCM device number
   2475  *     stage_fc - (IN) Stage field control structure.
   2476  *     inst     - (IN) Pipe Instance.
   2477  *     f_presel - (IN) Field Preselector entry structure.
   2478  *     fa       - (IN) Field action structure.
   2479  *     action   - (IN) Field Action of type bcmFieldActionXXX.
   2480  * Returns:
   2481  *     BCM_E_XXX
   2482  */
   2483 STATIC int
   2484 _bcm_field_presel_action_params_check(int unit,
   2485                                       _field_stage_t *stage_fc,
   2486                                       int inst,
   2487                                       _field_presel_entry_t *f_presel,
   2488                                       _field_action_t *fa)
   2489 {
   2490     _field_action_params_t      params; /* Field Params Structutre. */
   2491     bcm_field_action_t          action;  /* Field Action of Type bcmFieldActionXXX. */
   2492     soc_mem_t                   data_mem;
   2493 
   2494     /* Validate input parameters */
   2495     if (NULL == stage_fc || NULL == f_presel || NULL == fa) {
   2496         LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META("Invalid Parameters\n")));
   2497         return BCM_E_PARAM;
   2498     }
   2499 
   2500     sal_memset(&params , 0, sizeof(params));
   2501 
   2502     if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) {
   2503         BCM_IF_ERROR_RETURN
   2504             (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, inst,
   2505                                                   _BCM_FIELD_MEM_TYPE_IFP_LT,
   2506                                                   _BCM_FIELD_MEM_VIEW_TYPE_DATA,
   2507                                                   NULL, &data_mem));
   2508     } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) {
   2509         BCM_IF_ERROR_RETURN
   2510             (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, inst,
   2511                                                   _BCM_FIELD_MEM_TYPE_EM_LT,
   2512                                                   _BCM_FIELD_MEM_VIEW_TYPE_DATA,
   2513                                                   NULL, &data_mem));
   2514     } else {
   2515         return BCM_E_PARAM;
   2516     }
   2517 
   2518     action = fa->action;
   2519     switch (action) {
   2520        case bcmFieldActionGroupClassSet:
   2521             PolicyCheck(unit, data_mem, LOGICAL_TABLE_CLASS_IDf, fa->param[0]);
   2522             break;
   2523        case bcmFieldActionGroupLookupDisable:
   2524             break;
   2525        default:
   2526             return BCM_E_PARAM;
   2527             break;
   2528     }
   2529 
   2530     return BCM_E_NONE;
   2531 }
   2532 
   2533 /*
   2534  * Function:
   2535  *     _field_presel_entry_action_set
   2536  * Purpose:
   2537  *     Set the action to the given Preselector Entry Data buffer
   2538  * Parameters:
   2539  *     unit     - (IN) BCM device number
   2540  *     data_mem - (IN) LT Data Memory
   2541  *     f_presel - (IN) Reference to Preselector Entry structure.
   2542  *     fa       - (IN) field action
   2543  *     buf      - (OUT) Entry data buffer.
   2544  * Returns:
   2545  *     BCM_E_XXX
   2546  */
   2547 STATIC int
   2548 _field_presel_entry_action_set(int unit, soc_mem_t data_mem,
   2549                                _field_presel_entry_t *f_presel,
   2550                                _field_action_t *fa, uint32 *buf)
   2551 {
   2552     /* Input parameters check. */
   2553     if ((NULL == f_presel) || (NULL == fa) || (NULL == buf)) {
   2554         return (BCM_E_PARAM);
   2555     }
   2556 
   2557     switch (fa->action) {
   2558        case bcmFieldActionGroupClassSet:
   2559             soc_mem_field32_set(unit, data_mem, buf, LOGICAL_TABLE_CLASS_IDf,
   2560                                 fa->param[0]);
   2561             break;
   2562        case bcmFieldActionGroupLookupDisable:
   2563             soc_mem_field32_set(unit, data_mem, buf, ENABLEf, 0);
   2564             break;
   2565        default:
   2566             return BCM_E_INTERNAL;
   2567             break;
   2568     }
   2569 
   2570     return BCM_E_NONE;
   2571 }
   2572 
   2573 /*
   2574  * Function:
   2575  *     _bcm_field_presel_entry_actions_set
   2576  * Purpose:
   2577  *     Set the actions to the given Preselector Entry Data buffer
   2578  * Parameters:
   2579  *     unit     - (IN) BCM device number
   2580  *     data_mem - (IN) LT Data Memory
   2581  *     f_presel - (IN) Reference to Preselector Entry structure.
   2582  *     fa       - (IN) field action
   2583  *     buf      - (OUT) Entry data buffer.
   2584  * Returns:
   2585  *     BCM_E_NONE
   2586  *     BCM_E_PARAM - Action parameter out-of-range or unrecognized action.
   2587  */
   2588 int
   2589 _bcm_field_presel_entry_actions_set(int unit, soc_mem_t data_mem,
   2590                                     _field_presel_entry_t *f_presel,
   2591                                     uint32 *buf)
   2592 {
   2593     _field_action_t         *fa_iter;          /* Presel actions iterator. */
   2594 
   2595     /* Input parameters check. */
   2596     if ((NULL == f_presel) || (NULL == buf)) {
   2597         return (BCM_E_PARAM);
   2598     }
   2599 
   2600     /* Assign Action to the Preselector entry */
   2601     for (fa_iter = f_presel->actions; fa_iter != NULL; fa_iter = fa_iter->next)
   2602     {
   2603        BCM_IF_ERROR_RETURN
   2604            (_field_presel_entry_action_set(unit, data_mem, f_presel,
   2605                                            fa_iter, buf));
   2606     }
   2607 
   2608     return BCM_E_NONE;
   2609 }
   2610 
   2611 
   2612 /*
   2613  * Function: _bcm_field_presel_action_add
   2614  *
   2615  * Purpose:
   2616  *     Associate the action descriptor to the preselector entry.
   2617  *
   2618  * Parameters:
   2619  *     unit  - (IN) BCM device number.
   2620  *     fc    - (IN) Field control structure.
   2621  *     entry - (IN) Field Preselector Entry id.
   2622  *     fa    - (IN) Field action structure.
   2623  * Returns:
   2624  *     BCM_E_XXX
   2625  */
   2626 int
   2627 _bcm_field_presel_action_add(int unit, _field_control_t *fc,
   2628                              bcm_field_entry_t entry, _field_action_t *fa)
   2629 {
   2630     int                      rv;               /* Operation return status. */
   2631     _field_presel_entry_t   *f_presel;         /* Presel entry structure.  */
   2632     _field_action_t         *fa_iter;          /* Presel actions iterator. */
   2633     _field_action_t         *fa_prev_ptr=NULL; /* Action previous pointer. */
   2634     _field_stage_t          *stage_fc;         /* Reference to stage control. */
   2635     _field_stage_id_t        stage_id;         /* Stage id. */
   2636     bcm_field_presel_t       presel;           /* Field Preselector ID.    */
   2637 
   2638     /* Input parameters check. */
   2639     if ((NULL == fc) || (NULL == fa)) {
   2640         return (BCM_E_PARAM);
   2641     }
   2642 
   2643     /* Preselector feature check */
   2644     if (!soc_feature(unit, soc_feature_field_preselector_support)) {
   2645        return BCM_E_UNAVAIL;
   2646     }
   2647 
   2648     /* Resolve the Preselector ID from the given Entry ID */
   2649     rv = _bcm_field_entry_presel_resolve(unit, entry, &presel, &f_presel);
   2650     if (BCM_FAILURE(rv)) {
   2651        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2652                "ERROR: Unable to resolve the Presel Entry ID %d.\n\r"), entry));
   2653        return rv;
   2654     }
   2655 
   2656     /* Verify if the Presel ID is already in USE */
   2657     if (BCM_FIELD_PRESEL_TEST(fc->presel_info->operational_set, presel) &&
   2658         !(f_presel->flags & _FP_ENTRY_DIRTY)) {
   2659        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2660                  "ERROR: Preselector ID[%d] is in USE.\n\r"), presel));
   2661        return BCM_E_BUSY;
   2662     }
   2663 
   2664     /* Retrieve the stage id. */
   2665     if (BCM_FIELD_QSET_TEST(f_presel->p_qset, bcmFieldQualifyStageIngress)) {
   2666         stage_id = _BCM_FIELD_STAGE_INGRESS;
   2667     } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset,
   2668                                     bcmFieldQualifyStageIngressExactMatch)) {
   2669         stage_id = _BCM_FIELD_STAGE_EXACTMATCH;
   2670 #if defined(BCM_FLOWTRACKER_SUPPORT)
   2671     } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset,
   2672                                     bcmFieldQualifyStageIngressFlowtracker)) {
   2673         stage_id = _BCM_FIELD_STAGE_FLOWTRACKER;
   2674 #endif
   2675     } else {
   2676         return BCM_E_INTERNAL;
   2677     }
   2678 
   2679 #if defined(BCM_FLOWTRACKER_SUPPORT)
   2680     if (_BCM_FIELD_STAGE_FLOWTRACKER == stage_id) {
   2681         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2682                  "ERROR: Presel Action is not supported in this stage\n\r")));
   2683         return BCM_E_UNAVAIL;
   2684     }
   2685 #endif
   2686 
   2687     /* Get stage field control structure. */
   2688     BCM_IF_ERROR_RETURN
   2689         (_field_stage_control_get(unit, stage_id, &stage_fc));
   2690 
   2691     /* Verify the Params */
   2692     rv = _bcm_field_presel_action_params_check(unit, stage_fc, 0, f_presel, fa);
   2693     if (BCM_FAILURE(rv)) {
   2694        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2695                "ERROR: Invalid Preselector Action Parameters.\n\r")));
   2696        return rv;
   2697     }
   2698 
   2699     /* Assign Action to the Preselector entry */
   2700     for (fa_iter = f_presel->actions;
   2701          fa_iter != NULL;
   2702          fa_iter = fa_iter->next) {
   2703          if (fa_iter->action == fa->action) {
   2704             fa->next = fa_iter->next;
   2705             if (fa_prev_ptr == NULL) {
   2706                f_presel->actions = fa;
   2707             } else {
   2708                fa_prev_ptr->next = fa;
   2709             }
   2710             sal_free (fa_iter);
   2711             return BCM_E_NONE;
   2712          }
   2713          fa_prev_ptr = fa_iter;
   2714     }
   2715 
   2716     /* Add action to the front of presel entry's linked-list */
   2717     fa->next = f_presel->actions;
   2718     f_presel->actions = fa;
   2719 
   2720     return BCM_E_NONE;
   2721 }
   2722 
   2723 /*
   2724  * Function:
   2725  *      _bcm_field_presel_action_delete
   2726  * Purpose:
   2727  *      Delete field action from a field preselector entry.
   2728  * Parameters:
   2729  *      unit   - (IN) BCM device number
   2730  *      entry  - (IN) Entry ID
   2731  *      action - (IN) Action to remove (bcmFieldActionXXX)
   2732  *      param0 - (IN) Action parameter (use 0 if not required)
   2733  *      param1 - (IN) Action parameter (use 0 if not required)
   2734  * Returns:
   2735  *      BCM_E_XXX
   2736  * Notes:
   2737  */
   2738 int
   2739 _bcm_field_presel_action_delete(int unit, bcm_field_entry_t entry,
   2740                                 bcm_field_action_t action,
   2741                                 uint32 param0, uint32 param1)
   2742 {
   2743     int                     rv;                /* Operation return status. */
   2744     _field_presel_entry_t   *f_presel;         /* Presel entry structure.  */
   2745     _field_action_t         *fa_iter;          /* Presel actions iterator. */
   2746     _field_action_t         *fa_prev_ptr=NULL; /* Action previous pointer. */
   2747     _field_control_t        *fc;               /* Field control structure. */
   2748     bcm_field_presel_t      presel;            /* Field Preselector ID.    */
   2749 
   2750     /* Preselector feature check */
   2751     if (!soc_feature(unit, soc_feature_field_preselector_support)) {
   2752        return BCM_E_UNAVAIL;
   2753     }
   2754 
   2755     /* Resolve the Preselector ID from the given Entry ID */
   2756     rv = _bcm_field_entry_presel_resolve(unit, entry, &presel, &f_presel);
   2757     if (BCM_FAILURE(rv)) {
   2758        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2759                "ERROR: Unable to resolve the Presel Entry ID %d.\n\r"), entry));
   2760        return rv;
   2761     }
   2762 
   2763     /* Retrieve the control structure */
   2764     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   2765 
   2766     /* Verify if the Presel ID is already in USE */
   2767     if (BCM_FIELD_PRESEL_TEST(fc->presel_info->operational_set, presel) &&
   2768         !(f_presel->flags & _FP_ENTRY_DIRTY)) {
   2769        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2770                  "ERROR: Preselector ID[%d] is in USE.\n\r"), presel));
   2771        return BCM_E_BUSY;
   2772     }
   2773 
   2774     /* Search and Delete the Action from the Preselector entry */
   2775     for (fa_iter = f_presel->actions;
   2776          fa_iter != NULL;
   2777          fa_iter = fa_iter->next) {
   2778          if (fa_iter->action == action) {
   2779             if (fa_prev_ptr == NULL) {
   2780                f_presel->actions = fa_iter->next;
   2781             } else {
   2782                fa_prev_ptr->next = fa_iter->next;
   2783             }
   2784             sal_free (fa_iter);
   2785             return BCM_E_NONE;
   2786          }
   2787          fa_prev_ptr = fa_iter;
   2788     }
   2789 
   2790     return BCM_E_NONE;
   2791 }
   2792 
   2793 /*
   2794  * Function: _bcm_field_presel_action_get
   2795  *
   2796  * Purpose:
   2797  *     Get parameters associated with the preselection entry action
   2798  *
   2799  * Parameters:
   2800  *     unit   - (IN) BCM device number
   2801  *     entry  - (IN) Preselector Entry ID
   2802  *     action - (IN) Action to perform (bcmFieldActionXXX)
   2803  *     param0 - (OUT) Action parameter
   2804  *     param1 - (OUT) Action parameter
   2805  *
   2806  * Returns:
   2807  *     BCM_E_INIT      - BCM Unit not initialized
   2808  *     BCM_E_NOT_FOUND - Entry ID not found
   2809  *     BCM_E_NOT_FOUND - No matching Action for entry
   2810  *     BCM_E_PARAM     - paramX is NULL
   2811  *     BCM_E_NONE      - Success
   2812  */
   2813 
   2814 int
   2815 _bcm_field_presel_action_get(int unit,
   2816                              bcm_field_entry_t entry,
   2817                              bcm_field_action_t action,
   2818                              uint32 *param0,
   2819                              uint32 *param1)
   2820 {
   2821     int                     rv;                /* Operation return status. */
   2822     _field_presel_entry_t   *f_presel;         /* Presel entry structure.  */
   2823     _field_action_t         *fa;               /* Presel actions iterator. */
   2824     _field_control_t        *fc;               /* Field control structure. */
   2825     bcm_field_presel_t      presel;            /* Field Preselector ID.    */
   2826 
   2827     /* Input parameters check. */
   2828     if ((NULL == param0) || (NULL == param1)) {
   2829         return (BCM_E_PARAM);
   2830     }
   2831 
   2832     /* Resolve the Preselector ID from the given Entry ID */
   2833     rv = _bcm_field_entry_presel_resolve(unit, entry, &presel, &f_presel);
   2834     if (BCM_FAILURE(rv)) {
   2835        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2836                "ERROR: Unable to resolve the Presel Entry ID %d.\n\r"), entry));
   2837        return rv;
   2838     }
   2839 
   2840     /* Retrieve the control structure */
   2841     FP_LOCK(unit);
   2842     rv = _field_control_get(unit, &fc);
   2843     if (BCM_FAILURE(rv)) {
   2844         FP_UNLOCK(unit);
   2845         return rv;
   2846     }
   2847 
   2848     /* Find matching action in the entry */
   2849     for (fa = f_presel->actions; fa != NULL; fa = fa->next) {
   2850         if (fa->action == action) {
   2851             break;
   2852         }
   2853     }
   2854 
   2855     if (fa == NULL) {
   2856         FP_UNLOCK(unit);
   2857         LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2858               "Error: Action[%d] not found in the preselector entry[0x%x]\n\r"),
   2859                action, entry));
   2860         return (BCM_E_NOT_FOUND);
   2861     }
   2862 
   2863     *param0 = fa->param[0];
   2864     *param1 = fa->param[1];
   2865 
   2866     /* Unlock the module. */
   2867     FP_UNLOCK(unit);
   2868     return (rv);
   2869 }
   2870 
   2871 /*
   2872  * Function: _bcm_field_presel_action_remove_all
   2873  *
   2874  * Purpose:
   2875  *     Remove all actions from a preselector entry rule.
   2876  *
   2877  * Parameters:
   2878  *     unit  - (IN) BCM device number
   2879  *     entry - (IN) Preselector Entry ID
   2880  *
   2881  * Returns:
   2882  *     BCM_E_INIT      - BCM Unit not initialized
   2883  *     BCM_E_NOT_FOUND - Entry ID not found
   2884  *     BCM_E_NONE      - Success
   2885  */
   2886 
   2887 STATIC int
   2888 _bcm_field_presel_action_remove_all(int unit,
   2889                                     bcm_field_entry_t entry)
   2890 {
   2891     int                     rv;                /* Operation return status. */
   2892     _field_presel_entry_t   *f_presel;         /* Presel entry structure.  */
   2893     _field_action_t         *fa;               /* Presel actions iterator. */
   2894     _field_action_t         *fa_ptr=NULL;      /* Action previous pointer. */
   2895     _field_control_t        *fc;               /* Field control structure. */
   2896     bcm_field_presel_t      presel;            /* Field Preselector ID.    */
   2897 
   2898 
   2899     /* Get field control structure. */
   2900     FP_LOCK(unit);
   2901     rv = _field_control_get(unit, &fc);
   2902     if (BCM_FAILURE(rv)) {
   2903         FP_UNLOCK(unit);
   2904         return rv;
   2905     }
   2906 
   2907    /* Resolve the Preselector ID from the given Entry ID */
   2908     rv = _bcm_field_entry_presel_resolve(unit, entry, &presel, &f_presel);
   2909     if (BCM_FAILURE(rv)) {
   2910        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2911                "ERROR: Unable to resolve the Presel Entry ID %d.\n\r"), entry));
   2912        FP_UNLOCK(unit);
   2913        return rv;
   2914     }
   2915 
   2916     /* Verify if the Presel ID is already in USE */
   2917     if (BCM_FIELD_PRESEL_TEST(fc->presel_info->operational_set, presel) &&
   2918         !(f_presel->flags & _FP_ENTRY_DIRTY)) {
   2919        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2920                  "ERROR: Preselector ID[%d] is in USE.\n\r"), presel));
   2921        return BCM_E_BUSY;
   2922     }
   2923 
   2924     /* start at the head of the actions list and burn them up */
   2925     fa = f_presel->actions;
   2926 
   2927     /* Search and Delete the Action from the Preselector entry */
   2928     while (fa != NULL) {
   2929        fa_ptr = fa;
   2930        f_presel->actions = fa = fa->next;
   2931        sal_free (fa_ptr);
   2932     }
   2933 
   2934     FP_UNLOCK(unit);
   2935     return (BCM_E_NONE);
   2936 }
   2937 
   2938 int
   2939 _bcm_field_presel_group_prio_sort(int unit, _field_group_t *fg)
   2940 {
   2941    _field_presel_entry_t  *f_presel[_FP_PRESEL_ENTRIES_MAX_PER_GROUP];
   2942    _field_presel_entry_t  *f_presel_tmp;
   2943    int i,j;
   2944 
   2945     /* Input parameters check. */
   2946     if (NULL == fg) {
   2947        return (BCM_E_PARAM);
   2948     }
   2949 
   2950     sal_memcpy(f_presel, fg->presel_ent_arr,
   2951             sizeof(_field_presel_entry_t *) * _FP_PRESEL_ENTRIES_MAX_PER_GROUP);
   2952 
   2953     for (i = 0; i < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; i++) {
   2954         for (j = i; j < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; j++) {
   2955             if (f_presel[i] && f_presel[j]) {
   2956                if (f_presel[i]->priority < f_presel[j]->priority) {
   2957                    f_presel_tmp = f_presel[i];
   2958                    f_presel[i] = f_presel[j];
   2959                    f_presel[j] = f_presel_tmp;
   2960                }
   2961             }
   2962         }
   2963     }
   2964 
   2965     return BCM_E_NONE;
   2966 }
   2967 
   2968 /*
   2969  * Function: _bcm_field_presel_group_add
   2970  *
   2971  * Purpose:
   2972  *     Add preselector Id to a field group structure
   2973  *
   2974  * Parameters:
   2975  *     unit   - (IN) BCM device number
   2976  *     fg     - (IN) Reference to Field Group structure
   2977  *     presel - (IN) Preselector Id.
   2978  *
   2979  * Returns:
   2980  *     BCM_E_XXX
   2981  */
   2982 int
   2983 _bcm_field_presel_group_add(int unit, _field_group_t *fg,
   2984                             bcm_field_presel_t presel)
   2985 {
   2986     _field_presel_entry_t   *f_presel;         /* Presel entry structure.  */
   2987     _field_control_t        *fc;               /* Field control structure. */
   2988     _field_stage_id_t        stage_id;         /* Stage id. */
   2989     uint8                   id, idx;
   2990 
   2991     /* Input parameters check. */
   2992     if (NULL == fg) {
   2993        return (BCM_E_PARAM);
   2994     }
   2995 
   2996     /* Validate the Preselector ID */
   2997     if (_BCM_FIELD_IS_PRESEL_VALID(presel) == FALSE) {
   2998        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2999            "ERROR: Invalid Presel ID[%d].\n\r"), presel));
   3000        return BCM_E_PARAM;
   3001     }
   3002 
   3003     /* Get field control structure. */
   3004     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   3005 
   3006     /* Check if presel ID is already created */
   3007     if (!BCM_FIELD_PRESEL_TEST(fc->presel_info->presel_set, presel)) {
   3008        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3009        "ERROR: Preselector ID[%d] is not created.\n\r"), presel));
   3010        return BCM_E_NOT_FOUND;
   3011     }
   3012 
   3013     /* Verify if the Presel ID is already in USE */
   3014     if (BCM_FIELD_PRESEL_TEST(fc->presel_info->operational_set, presel)) {
   3015        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3016        "ERROR: Preselector ID[%d] is already in USE"
   3017        " by some other group.\n\r"), presel));
   3018        return BCM_E_BUSY;
   3019     }
   3020 
   3021     /* Find preselector descriptor */
   3022     BCM_IF_ERROR_RETURN
   3023       (_bcm_field_presel_entry_get(unit, presel, &f_presel));
   3024 
   3025     /* Retrieve the stage id. */
   3026     if (BCM_FIELD_QSET_TEST(f_presel->p_qset, bcmFieldQualifyStageIngress)) {
   3027         stage_id = _BCM_FIELD_STAGE_INGRESS;
   3028     } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset,
   3029                                     bcmFieldQualifyStageIngressExactMatch)) {
   3030         stage_id = _BCM_FIELD_STAGE_EXACTMATCH;
   3031 #if defined(BCM_FLOWTRACKER_SUPPORT)
   3032     } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset,
   3033                                     bcmFieldQualifyStageIngressFlowtracker)) {
   3034         stage_id = _BCM_FIELD_STAGE_FLOWTRACKER;
   3035 #endif
   3036     } else {
   3037         return BCM_E_INTERNAL;
   3038     }
   3039 
   3040     /* Validate the Group's stage_id with Presel Entry stage_id */
   3041     if (stage_id != fg->stage_id) {
   3042        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3043          "ERROR: Presel Entry[%d] doesn't belongs to Field Group's stage.\n\r"),
   3044           presel));
   3045        return BCM_E_PARAM;
   3046     }
   3047 
   3048     /* Verify the last entry in the array to check the free slot */
   3049     if (fg->presel_ent_arr[_FP_PRESEL_ENTRIES_MAX_PER_GROUP-1] != NULL) {
   3050        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit, "ERROR: Exceeded Max "
   3051        "Preselector IDs[%d] for the group[%d].\n\r"),
   3052         _FP_PRESEL_ENTRIES_MAX_PER_GROUP, fg->gid));
   3053        return BCM_E_FULL;
   3054     }
   3055 
   3056     /* Adjust the presel entry as per the priority. */
   3057     for (id = 0; id < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; id++) {
   3058        if (fg->presel_ent_arr[id] == NULL) {
   3059           fg->presel_ent_arr[id] = f_presel;
   3060           break;
   3061        } else {
   3062           if (fg->presel_ent_arr[id]->priority < f_presel->priority) {
   3063              /* Move down all the entries */
   3064              for (idx = _FP_PRESEL_ENTRIES_MAX_PER_GROUP-1; idx > id; idx--) {
   3065                 fg->presel_ent_arr[idx] = fg->presel_ent_arr[idx - 1];
   3066              }
   3067              fg->presel_ent_arr[id] = f_presel;
   3068              break;
   3069           }
   3070        }
   3071     }
   3072 
   3073     /* Debug prints to be removed */
   3074     for (id = 0; id < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; id++) {
   3075        if (fg->presel_ent_arr[id]) {
   3076           LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3077                     "arr[%d]:priority[%d]\n\r"),
   3078                     id, fg->presel_ent_arr[id]->priority));
   3079        }
   3080     }
   3081 
   3082     return BCM_E_NONE;
   3083 }
   3084 
   3085 STATIC int
   3086 _field_presel_entry_part_update(int unit, _field_stage_t *stage_fc,
   3087                                 _field_presel_entry_t *f_presel)
   3088 {
   3089     int                     rv;                /* Operation return status. */
   3090     _field_group_t          *fg;
   3091     _field_lt_slice_t       *lt_fs;
   3092     _field_presel_entry_t   *f_presel_p;
   3093     int                      part, parts_count;
   3094     int                      slice_num, pri_tcam_idx,
   3095                              part_index;
   3096 
   3097     /* Input parameters check. */
   3098     if (NULL == stage_fc || NULL == f_presel) {
   3099        return (BCM_E_PARAM);
   3100     }
   3101 
   3102     fg = f_presel->group;
   3103     lt_fs = f_presel->lt_fs;
   3104     if (NULL == fg || NULL == lt_fs) {
   3105        return BCM_E_INTERNAL;
   3106     }
   3107 
   3108     /* Get entry TCAM index given slice number and entry offset in slice. */
   3109     rv = _bcm_field_th_lt_slice_offset_to_tcam_index(unit, stage_fc,
   3110                                              fg->instance, lt_fs->slice_number,
   3111                                              f_presel->hw_index, &pri_tcam_idx);
   3112     BCM_IF_ERROR_RETURN(rv);
   3113 
   3114     /* Get number of entry parts based on group flags. */
   3115     BCM_IF_ERROR_RETURN(_bcm_field_th_lt_entry_tcam_parts_count(unit,
   3116                                             fg->stage_id, fg->flags,
   3117                                             &parts_count));
   3118 
   3119     f_presel_p = f_presel;
   3120     for (part = 0; (part < parts_count && f_presel_p != NULL); part++) {
   3121        /* Given primary entry TCAM index calculate entry part tcam index. */
   3122        if (0 != part) {
   3123            rv = _bcm_field_th_lt_entry_part_tcam_idx_get(unit, fg,
   3124                                                          pri_tcam_idx,
   3125                                                          part, &part_index);
   3126            if (BCM_FAILURE(rv)) {
   3127               return BCM_E_INTERNAL;
   3128            }
   3129 
   3130           /*
   3131            * Given entry part TCAM index, determine the slice number and slice
   3132            * offset index.
   3133            */
   3134           rv = _bcm_field_th_lt_tcam_idx_to_slice_offset(unit, stage_fc,
   3135                                    fg->instance, part_index, &slice_num,
   3136                                    (int *)&f_presel_p->hw_index);
   3137           if (BCM_FAILURE(rv)) {
   3138              return BCM_E_INTERNAL;
   3139           }
   3140        }
   3141        /* Assign entry to a slice. */
   3142        f_presel_p->lt_fs->p_entries[f_presel_p->hw_index] = f_presel_p;
   3143        f_presel_p = f_presel_p->next;
   3144     }
   3145 
   3146     return BCM_E_NONE;
   3147 }
   3148 
   3149 /*
   3150  * Function: _field_presel_entry_prio_set
   3151  *
   3152  * Purpose:
   3153  *
   3154  * Parameters:
   3155  *     unit     - (IN) BCM device number
   3156  *     f_presel - (IN) Reference to Field preselector entry structure.
   3157  *     prio  - (IN) Presel Entry Priority value.
   3158  *
   3159  * Returns:
   3160  *     BCM_E_XX
   3161  *
   3162  * Notes:
   3163  *     The earlier checks guarantee that there is a free slot somewhere
   3164  *     i.e. in one of the alloted slices for the group.
   3165  */
   3166 STATIC int
   3167 _field_presel_entry_prio_set(int unit,
   3168                              _field_presel_entry_t *f_presel,
   3169                              int prio)
   3170 {
   3171     int                     rv;                /* Operation return status. */
   3172     _field_group_t          *fg;               /* Field Group structure. */
   3173     _field_control_t        *fc;               /* Field control structure. */
   3174     _field_stage_t          *stage_fc;
   3175     _field_presel_entry_t   *f_presel_tmp;
   3176     _field_lt_slice_t       *lt_fs;
   3177     uint8                   move_down = 0;
   3178     uint8                   move_required = 0;
   3179     uint8                   skip = 0;
   3180     int                     idx, curr_idx, dest_idx = -1, move_idx, pre_idx;
   3181     int                     next_hw_index, dest_hw_index = -1;
   3182     int                     target_hw_index = -1;
   3183     int                     valid_entries = 0;
   3184     int                     no_move_down_match = 0;
   3185     _field_presel_entry_t   *presel_entries[_FP_PRESEL_ENTRIES_MAX_PER_GROUP+1];
   3186 
   3187     /* Input parameters check. */
   3188     if (NULL == f_presel) {
   3189        return (BCM_E_PARAM);
   3190     }
   3191 
   3192     /* If the priority is same, return */
   3193     if (f_presel->priority == prio) {
   3194        return BCM_E_NONE;
   3195     }
   3196 
   3197     /* Get field control structure. */
   3198     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   3199 
   3200     if (NULL == f_presel->group) {
   3201        return BCM_E_INTERNAL;
   3202     }
   3203 
   3204     fg = f_presel->group;
   3205     if (NULL ==  fg->presel_ent_arr[0]) {
   3206        return BCM_E_INTERNAL;
   3207     }
   3208 
   3209     /* Retrieve the slice the entry belongs to. */
   3210     lt_fs = f_presel->lt_fs;
   3211     if (lt_fs == NULL) {
   3212        return BCM_E_INTERNAL;
   3213     }
   3214 
   3215     if(fg->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) {
   3216         /* Currently, not supporting priority movement in this stage */
   3217         return BCM_E_NONE;
   3218     }
   3219 
   3220     /* Check if the slice supports SW Atomicity */
   3221     if ((lt_fs->slice_flags & _BCM_FIELD_SLICE_SW_ATOMICITY_SUPPORT) == 0) {
   3222        return BCM_E_CONFIG;
   3223     }
   3224 
   3225     /* Update LT Slice's last free entry index. */
   3226     target_hw_index = lt_fs->entry_count - 1;
   3227     /* Verify if the last entry in the slice is free */
   3228     if (lt_fs->p_entries[target_hw_index] != NULL) {
   3229        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3230                "ERROR: No free entries left to swap.\n\r")));
   3231        return BCM_E_INTERNAL;
   3232     }
   3233 
   3234     /* Get stage field control structure. */
   3235     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fg->stage_id,
   3236                                                  &stage_fc));
   3237 
   3238     /* Count Valid entries in the group preselector array. */
   3239     LOG_VERBOSE(BSL_LS_BCM_FP,
   3240               (BSL_META_U(unit, "Before Prio Set ..\n\r")));
   3241     valid_entries = 0;
   3242     for (idx = 0; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) {
   3243        if (fg->presel_ent_arr[idx]) {
   3244           LOG_VERBOSE(BSL_LS_BCM_FP,
   3245                     (BSL_META_U(unit, "arr[%d]:presel_id[%d]:"
   3246                      "hw_index[%d]:priority[%d]"),
   3247                     idx, fg->presel_ent_arr[idx]->presel_id,
   3248                     fg->presel_ent_arr[idx]->hw_index,
   3249                     fg->presel_ent_arr[idx]->priority));
   3250           if (f_presel == fg->presel_ent_arr[idx]) {
   3251              LOG_VERBOSE(BSL_LS_BCM_FP,
   3252                    (BSL_META_U(unit, ":next_priority:[%d]\n\r"), prio));
   3253           } else {
   3254              LOG_VERBOSE(BSL_LS_BCM_FP,(BSL_META_U(unit, "\n\r")));
   3255           }
   3256           valid_entries++;
   3257        }
   3258     }
   3259 
   3260     /* Validate if the given priority entry has to be move up or down. */
   3261     if (prio > f_presel->priority) {
   3262        /* the entry should move upward */
   3263        move_down = 0;
   3264        curr_idx = -1;
   3265     } else {
   3266        /* the entry should move downward */
   3267        move_down = 1;
   3268        curr_idx = valid_entries;
   3269     }
   3270 
   3271 
   3272     no_move_down_match = 0;
   3273     /* Get the Destination hw index */
   3274     for (idx = 0; idx < valid_entries; idx++) {
   3275        f_presel_tmp = fg->presel_ent_arr[idx];
   3276        if (f_presel_tmp != NULL) {
   3277           if ((move_down == 1) && (prio < f_presel_tmp->priority)) {
   3278              no_move_down_match++;
   3279           }
   3280           if (f_presel_tmp == f_presel) {
   3281              curr_idx = idx;
   3282              continue;
   3283           }
   3284 
   3285           if (((move_down == 1) && (curr_idx < idx) &&
   3286                (prio >= f_presel_tmp->priority)) ||
   3287               ((move_down == 0) && (curr_idx == -1) &&
   3288                (prio > f_presel_tmp->priority) &&
   3289                (f_presel->priority <= f_presel_tmp->priority))) {
   3290 
   3291              if ((move_down == 1) && (curr_idx + 1) == idx) {
   3292                 /* Down move is not required as the immediate next entry
   3293                  * priority is still less than or equal to the new priority. */
   3294                 break;
   3295              }
   3296 
   3297              /* movement required. */
   3298              move_required = 1;
   3299              dest_hw_index = f_presel_tmp->hw_index;
   3300              dest_idx = idx;
   3301              break;
   3302           }
   3303        }
   3304     }
   3305 
   3306     /*
   3307      * This case occurs when the priority of the entry to be set
   3308      * is the least priority among all the existing entries.
   3309      */
   3310     if (no_move_down_match == valid_entries) {
   3311        move_required = 1;
   3312        dest_idx = valid_entries;
   3313     }
   3314 
   3315     if (move_required == 0) {
   3316        LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3317                "== Move Not Required ==\n\r")));
   3318        return BCM_E_NONE;
   3319     }
   3320 
   3321     /* initialize the local preselector array */
   3322     sal_memset(&presel_entries[0], 0x0,
   3323         sizeof(_field_presel_entry_t *) * (_FP_PRESEL_ENTRIES_MAX_PER_GROUP+1));
   3324 
   3325     /*
   3326      * Iteration Move down the low priority entries and adjust the
   3327      * given presel entry as per its new priority.
   3328      */
   3329     for (idx = valid_entries-1; idx >= 0; idx--) {
   3330        f_presel_tmp = fg->presel_ent_arr[idx];
   3331        move_idx = 0;
   3332        if (f_presel_tmp != NULL) {
   3333           if (((move_down == 1) && ((prio >= f_presel_tmp->priority) ||
   3334                 (f_presel_tmp == f_presel))) ||
   3335               ((move_down == 0) && ((prio > f_presel_tmp->priority) &&
   3336                 (f_presel_tmp->hw_index >= dest_hw_index)))) {
   3337 
   3338              next_hw_index = f_presel_tmp->hw_index;
   3339              f_presel_tmp->hw_index = target_hw_index;
   3340 
   3341              rv = _field_presel_entry_part_update(unit, stage_fc, f_presel_tmp);
   3342              if (BCM_FAILURE(rv)) {
   3343                 return BCM_E_INTERNAL;
   3344              }
   3345 
   3346              rv = _bcm_field_th_lt_entry_parts_install(unit, f_presel_tmp);
   3347              if (BCM_FAILURE(rv)) {
   3348                 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3349                      "ERROR: Unable to install Presel Entry hw_index:%d\n\r"),
   3350                      f_presel_tmp->hw_index));
   3351                 return BCM_E_INTERNAL;
   3352              }
   3353 
   3354              target_hw_index = next_hw_index;
   3355              move_idx = 1;
   3356           }
   3357           if (f_presel_tmp == f_presel) {
   3358              curr_idx = idx + move_idx;
   3359              if (move_down == 1) {
   3360                 presel_entries[dest_idx] = f_presel_tmp;
   3361                 continue;
   3362              }
   3363           }
   3364           presel_entries[idx + move_idx] = f_presel_tmp;
   3365        }
   3366     }
   3367 
   3368     if (target_hw_index == -1) {
   3369        return BCM_E_INTERNAL;
   3370     }
   3371 
   3372     pre_idx = 0;
   3373     skip = 1;
   3374     /*
   3375      * Iteration to bring up the entries to the destination indices.
   3376      */
   3377     for (idx = 0; idx <= valid_entries; idx++) {
   3378           f_presel_tmp = presel_entries[idx];
   3379 
   3380           if (move_down == 0) {
   3381              /* Look for a free entry in the presel_entries */
   3382              if (f_presel_tmp == NULL) {
   3383                 if (dest_idx != idx) {
   3384                    continue;
   3385                 }
   3386                 if (curr_idx < 0) {
   3387                    return BCM_E_INTERNAL;
   3388                 }
   3389                 f_presel_tmp = presel_entries[curr_idx];
   3390              } else if (idx < curr_idx) {
   3391                 fg->presel_ent_arr[idx] = f_presel_tmp;
   3392                 continue;
   3393              } else if (idx == curr_idx) {
   3394                 continue;
   3395              }
   3396           } else {
   3397              if (f_presel_tmp == NULL) {
   3398                 pre_idx = 1;
   3399                 skip = 0;
   3400                 continue;
   3401              } else if (skip == 1) { /* Skip till free entry */
   3402                 continue;
   3403              }
   3404           }
   3405 
   3406           next_hw_index = f_presel_tmp->hw_index;
   3407           f_presel_tmp->hw_index = target_hw_index;
   3408           rv = _field_presel_entry_part_update(unit, stage_fc, f_presel_tmp);
   3409           if (BCM_FAILURE(rv)) {
   3410              return BCM_E_INTERNAL;
   3411           }
   3412 
   3413           rv = _bcm_field_th_lt_entry_parts_install(unit, f_presel_tmp);
   3414           if (BCM_FAILURE(rv)) {
   3415              LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3416                   "ERROR: Unable to install Presel Entry hw_index:%d\n\r"),
   3417                   f_presel_tmp->hw_index));
   3418              return BCM_E_INTERNAL;
   3419           }
   3420 
   3421           target_hw_index = next_hw_index;
   3422           fg->presel_ent_arr[idx - pre_idx] = f_presel_tmp;
   3423     }
   3424 
   3425     /* Delete Slice's last entry. */
   3426     f_presel_tmp = presel_entries[valid_entries];
   3427     if (f_presel_tmp != NULL) {
   3428           int                      parts_count, part, tcam_idx;
   3429           int                      last_hw_index;
   3430           soc_mem_t                lt_tcam_mem;
   3431           _field_presel_entry_t   *f_presel_p;
   3432           uint32                   entry[SOC_MAX_MEM_FIELD_WORDS] = {0};
   3433                                                       /* Entry buffer.   */
   3434 
   3435           last_hw_index = lt_fs->entry_count - 1;
   3436 
   3437           /* Get number of entry parts. */
   3438           BCM_IF_ERROR_RETURN(_bcm_field_th_entry_tcam_parts_count(unit,
   3439                                                 fg->flags, &parts_count));
   3440 
   3441           /* Get TCAM view to be used for programming the hardware. */
   3442           if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) {
   3443               rv = (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc,
   3444                                               f_presel->group->instance,
   3445                                              _BCM_FIELD_MEM_TYPE_IFP_LT,
   3446                                 _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB,
   3447                                                    &lt_tcam_mem, NULL));
   3448           } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) {
   3449               rv = (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc,
   3450                                               f_presel->group->instance,
   3451                                               _BCM_FIELD_MEM_TYPE_EM_LT,
   3452                                 _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB,
   3453                                                    &lt_tcam_mem, NULL));
   3454           } else {
   3455               return BCM_E_INTERNAL;
   3456           }
   3457           BCM_IF_ERROR_RETURN(rv);
   3458 
   3459           f_presel_p = f_presel_tmp;
   3460           for (part = parts_count -1; part >= 0; part--) {
   3461              if (f_presel_p == NULL) {
   3462                 break;
   3463              }
   3464              /* Calculate the TCAM index. */
   3465              tcam_idx = f_presel_p->lt_fs->start_tcam_idx + last_hw_index;
   3466 
   3467              /* Clear the entry in hardware. */
   3468              BCM_IF_ERROR_RETURN(soc_mem_write(unit, lt_tcam_mem, MEM_BLOCK_ALL,
   3469                                                tcam_idx, entry));
   3470 
   3471              /* Update the entry to a slice. */
   3472              f_presel_p->lt_fs->p_entries[last_hw_index] = NULL;
   3473              f_presel_p = f_presel_p->next;
   3474           }
   3475     }
   3476 
   3477     f_presel->priority = prio;
   3478     
   3479     LOG_VERBOSE(BSL_LS_BCM_FP,(BSL_META_U(unit, "After Prio Set...\n\r")));
   3480     for (idx = 0; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) {
   3481        if (fg->presel_ent_arr[idx]) {
   3482           LOG_VERBOSE(BSL_LS_BCM_FP,
   3483                     (BSL_META_U(unit, "arr[%d]:presel_id[%d]:"
   3484                     "hw_index[%d]:priority[%d]\n\r"),
   3485                     idx, fg->presel_ent_arr[idx]->presel_id,
   3486                     fg->presel_ent_arr[idx]->hw_index,
   3487                     fg->presel_ent_arr[idx]->priority));
   3488        }
   3489     }
   3490     return BCM_E_NONE;
   3491 }
   3492 
   3493 /*
   3494  * Function:_field_presel_delete_last_entry_hw
   3495  * Purpose:To delete the last presel entry in the slice
   3496  *
   3497  * Parameters:
   3498  *     unit     - (IN) BCM device number
   3499  *     f_presel - (IN) Reference to Field preselector entry structure.
   3500  *
   3501  * Returns:
   3502  *     BCM_E_XX
   3503  */
   3504     STATIC int
   3505 _field_presel_delete_last_entry_hw(int unit,
   3506     _field_presel_entry_t *f_presel)
   3507 {
   3508 
   3509     int                     rv;                /* Operation return status. */
   3510     _field_group_t          *fg;               /* Field Group structure. */
   3511     _field_stage_t          *stage_fc;
   3512     _field_presel_entry_t   *f_presel_tmp = NULL;
   3513     _field_lt_slice_t       *lt_fs;
   3514     int                     idx;
   3515     int                     last_hw_index;
   3516     /* Input parameters check. */
   3517     if (NULL == f_presel) {
   3518         return (BCM_E_PARAM);
   3519     }
   3520 
   3521     if (NULL == f_presel->group) {
   3522         return BCM_E_INTERNAL;
   3523     }
   3524 
   3525     fg = f_presel->group;
   3526     if (NULL ==  fg->presel_ent_arr[0]) {
   3527         return BCM_E_INTERNAL;
   3528     }
   3529 
   3530     /* Get stage field control structure. */
   3531     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fg->stage_id,
   3532                 &stage_fc));
   3533    /*Find the last entry */
   3534     for (idx = _FP_PRESEL_ENTRIES_MAX_PER_GROUP - 1; idx >=0; idx--) {
   3535         if (fg->presel_ent_arr[idx]) {
   3536             f_presel_tmp = fg->presel_ent_arr[idx];
   3537             break;
   3538         }
   3539     }
   3540     lt_fs = f_presel->lt_fs;
   3541     if (lt_fs == NULL) {
   3542         return BCM_E_INTERNAL;
   3543     }
   3544 
   3545 
   3546 
   3547     if (f_presel_tmp != NULL) {
   3548         int                      parts_count, part, tcam_idx;
   3549         soc_mem_t                lt_tcam_mem;
   3550         uint32                   entry[SOC_MAX_MEM_FIELD_WORDS] = {0};
   3551         /* Entry buffer.   */
   3552 
   3553         last_hw_index = lt_fs->entry_count - 1;
   3554 
   3555         /* Get number of entry parts. */
   3556         BCM_IF_ERROR_RETURN(_bcm_field_th_lt_entry_tcam_parts_count(unit,
   3557                     fg->stage_id, fg->flags, &parts_count));
   3558 
   3559         /* Get TCAM view to be used for programming the hardware. */
   3560         if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) {
   3561             rv = (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc,
   3562                         f_presel->group->instance,
   3563                         _BCM_FIELD_MEM_TYPE_IFP_LT,
   3564                         _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB,
   3565                         &lt_tcam_mem, NULL));
   3566         } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) {
   3567             rv = (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc,
   3568                         f_presel->group->instance,
   3569                         _BCM_FIELD_MEM_TYPE_EM_LT,
   3570                         _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB,
   3571                         &lt_tcam_mem, NULL));
   3572 #if defined(BCM_FLOWTRACKER_SUPPORT)
   3573         } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) {
   3574             /* Combo view is not available */
   3575             return _field_hx5_ft_presel_delete_last_entry_hw(unit,
   3576                         f_presel_tmp, last_hw_index);
   3577 #endif
   3578         } else {
   3579             return BCM_E_INTERNAL;
   3580         }
   3581         BCM_IF_ERROR_RETURN(rv);
   3582 
   3583         for (part = parts_count -1; part >= 0; part--) {
   3584             if (f_presel_tmp == NULL) {
   3585                 break;
   3586             }
   3587             /* Calculate the TCAM index. */
   3588             tcam_idx = f_presel_tmp->lt_fs->start_tcam_idx + last_hw_index;
   3589             /* Clear the entry in hardware. */
   3590             BCM_IF_ERROR_RETURN(soc_mem_write(unit, lt_tcam_mem, MEM_BLOCK_ALL,
   3591                         tcam_idx, entry));
   3592             /* Update the entry to a slice. */
   3593             f_presel_tmp->lt_fs->p_entries[last_hw_index] = NULL;
   3594             f_presel_tmp= f_presel_tmp->next;
   3595         }
   3596     }
   3597     return BCM_E_NONE;
   3598 }
   3599 
   3600 
   3601 /*
   3602  * Function: _field_presel_entries_move_down_hw
   3603  * Purpose:To move the entries down in the hardware
   3604  *
   3605  * Parameters:
   3606  *     unit     - (IN) BCM device number
   3607  *     f_presel - (IN) Reference to Field preselector entry structure.
   3608  *
   3609  * Returns:
   3610  *     BCM_E_XX
   3611  */
   3612     STATIC int
   3613 _field_presel_entries_move_down_hw (int unit,
   3614         _field_presel_entry_t *f_presel)
   3615 {
   3616     int target_hw_index = -1, next_hw_index =-1;
   3617     int                     rv;                /* Operation return status. */
   3618     int idx;
   3619     _field_stage_t          *stage_fc;
   3620     _field_group_t          *fg;               /* Field Group structure. */
   3621     _field_lt_slice_t       *lt_fs;
   3622     _field_presel_entry_t *f_presel_tmp;
   3623     lt_fs = f_presel->lt_fs;
   3624     target_hw_index = lt_fs->entry_count - 1; /*Index of the free slice entry*/
   3625     if (NULL == f_presel->group) {
   3626         return BCM_E_INTERNAL;
   3627     }
   3628     fg = f_presel->group;
   3629 
   3630     /* Get stage field control structure. */
   3631     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fg->stage_id,
   3632                 &stage_fc));
   3633     /*
   3634      * Iteration to move down the low priority entries and  the entry being updated.
   3635      */
   3636     for (idx = _FP_PRESEL_ENTRIES_MAX_PER_GROUP - 1; idx >= 0; idx--) {
   3637         f_presel_tmp = fg->presel_ent_arr[idx];
   3638         if (f_presel_tmp != NULL) {
   3639             next_hw_index = f_presel_tmp->hw_index;
   3640             f_presel_tmp->hw_index = target_hw_index;
   3641 
   3642             rv = _field_presel_entry_part_update(unit, stage_fc, f_presel_tmp);
   3643             if (BCM_FAILURE(rv)) {
   3644                 return BCM_E_INTERNAL;
   3645             }
   3646 
   3647             rv = _bcm_field_th_lt_entry_parts_install(unit, f_presel_tmp);
   3648             if (BCM_FAILURE(rv)) {
   3649                 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3650                                 "ERROR: Unable to install Presel Entry hw_index:%d\n\r"),
   3651                             f_presel_tmp->hw_index));
   3652                 return BCM_E_INTERNAL;
   3653             }
   3654             if(f_presel_tmp == f_presel) {
   3655                 break;
   3656             }
   3657             target_hw_index = next_hw_index;
   3658         }
   3659     }
   3660 
   3661     return BCM_E_NONE;
   3662 }
   3663 /*
   3664  * Function: _field_presel_entries_move_up_hw
   3665  * Purpose:To move the entries up in the hardware
   3666  *
   3667  * Parameters:
   3668  *     unit     - (IN) BCM device number
   3669  *     entry_index - (IN) presel_ent_arr index, entries after this will
   3670  *     updated with next below entry HW index
   3671  *     start_entry_hw_index - (IN) HW index to be updated for the first entry
   3672  *     below the intry with index entry_index
   3673  *     f_presel - (IN) Reference to Field preselector entry structure.
   3674  *
   3675  * Returns:
   3676  *     BCM_E_XX
   3677  */
   3678 
   3679     STATIC int
   3680 _field_presel_entries_move_up_hw (int unit,
   3681         int entry_index,
   3682         int start_entry_hw_index,
   3683         _field_presel_entry_t *f_presel)
   3684 {
   3685     int                     rv;                /* Operation return status. */
   3686     _field_group_t          *fg;               /* Field Group structure. */
   3687     _field_presel_entry_t *f_presel_tmp = NULL;
   3688     int target_hw_index = -1, next_hw_index=-1;
   3689     _field_stage_t          *stage_fc;
   3690     int                     idx;
   3691     if (NULL == f_presel->group) {
   3692         return BCM_E_INTERNAL;
   3693     }
   3694 
   3695     fg = f_presel->group;
   3696     if (NULL ==  fg->presel_ent_arr[0]) {
   3697         return BCM_E_INTERNAL;
   3698     }
   3699     /* Get stage field control structure. */
   3700     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fg->stage_id,
   3701                 &stage_fc));
   3702 
   3703     target_hw_index = start_entry_hw_index;
   3704 
   3705     /*The operation starts from the entry below the entry to be updated*/
   3706     for (idx = entry_index + 1; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) {
   3707       if ((fg->presel_ent_arr[idx] != NULL)) {
   3708         f_presel_tmp = fg->presel_ent_arr[idx];
   3709         next_hw_index = f_presel_tmp->hw_index;
   3710         f_presel_tmp->hw_index = target_hw_index;
   3711 
   3712       } else {
   3713         if (f_presel_tmp != NULL) {
   3714             LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3715                  "No more entry to move up as this is last valid entry:%d\n\r"),
   3716                  f_presel_tmp->hw_index));
   3717         } else {
   3718             LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3719                  "No entries available to move up \n\r")));
   3720         }
   3721         return BCM_E_NONE;
   3722       }
   3723       target_hw_index = next_hw_index;
   3724 
   3725       rv = _field_presel_entry_part_update(unit, stage_fc, f_presel_tmp);
   3726       if (BCM_FAILURE(rv)) {
   3727         return BCM_E_INTERNAL;
   3728       }
   3729 
   3730       rv = _bcm_field_th_lt_entry_parts_install(unit, f_presel_tmp);
   3731       if (BCM_FAILURE(rv)) {
   3732         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3733                 "ERROR: Unable to install Presel Entry hw_index:%d\n\r"),
   3734               f_presel_tmp->hw_index));
   3735         return BCM_E_INTERNAL;
   3736       }
   3737 
   3738     }
   3739     return BCM_E_NONE;
   3740 }
   3741 
   3742 /*
   3743  * Function: _field_presel_entry_update_hw_index
   3744  * Purpose:To re-install the Presel entry with given HW index in the hardware
   3745  *
   3746  * Parameters:
   3747  *     unit     - (IN) BCM device number
   3748  *     entry_hw_index - (IN) Hardware index of the entry to be updated.
   3749  *     f_presel - (IN) Reference to Field preselector entry structure.
   3750  *
   3751  * Returns:
   3752  *     BCM_E_XX
   3753  */
   3754     STATIC int
   3755 _field_presel_entry_update_hw_index(int unit,
   3756         int entry_hw_index,
   3757         _field_presel_entry_t *f_presel)
   3758 {
   3759     int                     rv;                /* Operation return status. */
   3760     _field_group_t          *fg;               /* Field Group structure. */
   3761     _field_stage_t          *stage_fc;
   3762 
   3763     if (NULL == f_presel->group) {
   3764         return BCM_E_INTERNAL;
   3765     }
   3766 
   3767     fg = f_presel->group;
   3768     /* Get stage field controBCM_E_NONE l structure. */
   3769     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fg->stage_id,
   3770                 &stage_fc));
   3771     /*Update the Presel with new qualifier value in the H/W */
   3772     f_presel->hw_index = entry_hw_index;
   3773     rv = _field_presel_entry_part_update(unit, stage_fc, f_presel);
   3774     if (BCM_FAILURE(rv)) {
   3775         return BCM_E_INTERNAL;
   3776     }
   3777 
   3778     rv = _bcm_field_th_lt_entry_parts_install(unit, f_presel);
   3779     if (BCM_FAILURE(rv)) {
   3780         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3781                         "ERROR: Unable to install Presel Entry hw_index:%d\n\r"),
   3782                     f_presel->hw_index));
   3783         return BCM_E_INTERNAL;
   3784     }
   3785 
   3786     return BCM_E_NONE;
   3787 }
   3788 
   3789 /*
   3790  * Function: _field_presel_entry_update
   3791  * Purpose:To update the Presel entry into hardware when the group is operational.
   3792  *
   3793  * Parameters:
   3794  *     unit     - (IN) BCM device number
   3795  *     f_presel - (IN) Reference to Field preselector entry structure.
   3796  *
   3797  * Returns:
   3798  *     BCM_E_XX
   3799  *
   3800  * Notes:
   3801  *     The earlier checks guarantee that there is a free slot somewhere
   3802  *     i.e. in one of the alloted slices for the group.
   3803  */
   3804 STATIC int
   3805 _field_presel_entry_update(int unit,
   3806                      _field_presel_entry_t *f_presel)
   3807 {
   3808     int                     rv;                /* Operation return status. */
   3809     _field_group_t          *fg;               /* Field Group structure. */
   3810     _field_control_t        *fc;               /* Field control structure. */
   3811     _field_stage_t          *stage_fc;
   3812     _field_lt_slice_t       *lt_fs;
   3813     int                     entry_hw_index, copy_entry_hw_index;
   3814     int                     free_hw_index = -1;
   3815     int                     idx, entry_idx = -1;
   3816 
   3817     /* Input parameters check. */
   3818     if (NULL == f_presel) {
   3819         return (BCM_E_PARAM);
   3820     }
   3821 
   3822     /* Get field control structure. */
   3823     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   3824 
   3825     if (NULL == f_presel->group) {
   3826         return BCM_E_INTERNAL;
   3827     }
   3828 
   3829     fg = f_presel->group;
   3830     if (NULL ==  fg->presel_ent_arr[0]) {
   3831         return BCM_E_INTERNAL;
   3832     }
   3833 
   3834     /* Retrieve the slice the entry belongs to. */
   3835     lt_fs = f_presel->lt_fs;
   3836     if (lt_fs == NULL) {
   3837         return BCM_E_INTERNAL;
   3838     }
   3839 
   3840     if (lt_fs->slice_flags & _BCM_FIELD_SLICE_HW_ATOMICITY_SUPPORT) {
   3841         entry_hw_index = f_presel->hw_index;
   3842         rv = _field_presel_entry_update_hw_index(unit, entry_hw_index, f_presel);
   3843         if (BCM_FAILURE(rv)) {
   3844             LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3845                             "ERROR: updating the entry with index:%d\n\r"),
   3846                         entry_hw_index));
   3847             return BCM_E_INTERNAL;
   3848         }
   3849         return rv;
   3850     }
   3851 
   3852     /* Check if the slice supports SW Atomicity */
   3853     if ((lt_fs->slice_flags & _BCM_FIELD_SLICE_SW_ATOMICITY_SUPPORT) == 0) {
   3854         return BCM_E_CONFIG;
   3855     }
   3856     /*Hardware index of the entry to be updated*/
   3857     entry_hw_index = f_presel->hw_index;
   3858 
   3859     /* Update LT Slice's last free entry index. */
   3860     free_hw_index = lt_fs->entry_count - 1;
   3861     /* Verify if the last entry in the slice is free */
   3862     if (lt_fs->p_entries[free_hw_index] != NULL) {
   3863         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3864                         "ERROR: No free entries left to swap.\n\r")));
   3865         return BCM_E_INTERNAL;
   3866     }
   3867 
   3868     /* Get stage field control structure. */
   3869     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fg->stage_id,
   3870                 &stage_fc));
   3871 
   3872     /*Find the index of the entry being updated */
   3873     for (idx = 0; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) {
   3874         if (fg->presel_ent_arr[idx]) {
   3875             LOG_VERBOSE(BSL_LS_BCM_FP,
   3876                     (BSL_META_U(unit, "arr[%d]:presel_id[%d]:"
   3877                                 "hw_index[%d]:priority[%d]"),
   3878                      idx, fg->presel_ent_arr[idx]->presel_id,
   3879                      fg->presel_ent_arr[idx]->hw_index,
   3880                      fg->presel_ent_arr[idx]->priority));
   3881             if (fg->presel_ent_arr[idx]->hw_index == f_presel->hw_index) {
   3882                 entry_idx = idx;
   3883                 break;
   3884             }
   3885         }
   3886     }
   3887 
   3888     /* Move down the low priority entries and along with the entry being changed.
   3889     */
   3890     rv =_field_presel_entries_move_down_hw(unit, f_presel);
   3891     if (BCM_FAILURE(rv)) {
   3892         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3893                         "ERROR: shifting the entries down starting from index:%d\n\r"),
   3894                     entry_hw_index));
   3895         return BCM_E_INTERNAL;
   3896     }
   3897 
   3898     copy_entry_hw_index = f_presel->hw_index;
   3899 
   3900     /*Update the Presel with new qualifier value in the H/W */
   3901     rv = _field_presel_entry_update_hw_index(unit, entry_hw_index, f_presel);
   3902     if (BCM_FAILURE(rv)) {
   3903         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3904                         "ERROR: updating the entry with index:%d\n\r"),
   3905                     entry_hw_index));
   3906         return BCM_E_INTERNAL;
   3907     }
   3908 
   3909     /* Move up the low priority entries.
   3910     */
   3911     rv =_field_presel_entries_move_up_hw(unit, entry_idx, copy_entry_hw_index, f_presel);
   3912     if (BCM_FAILURE(rv)) {
   3913         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3914                         "ERROR: shifting the entries up below index:%d\n\r"),
   3915                     entry_hw_index));
   3916         return BCM_E_INTERNAL;
   3917     }
   3918    /*Delete the last entry to keep a free entry*/
   3919     rv =_field_presel_delete_last_entry_hw(unit, f_presel);
   3920     if (BCM_FAILURE(rv)) {
   3921         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3922                         "ERROR: Deleting the last entry with index:%d\n\r"),
   3923                     free_hw_index));
   3924         return BCM_E_INTERNAL;
   3925     }
   3926 
   3927     return BCM_E_NONE;
   3928 }
   3929 
   3930 /*
   3931  * Function: _bcm_field_presel_entry_prio_set
   3932  *
   3933  * Purpose:
   3934  *
   3935  * Parameters:
   3936  *     unit  - (IN) BCM device number
   3937  *     entry - (IN) Field presel entry to operate on.
   3938  *     prio  - (IN) Presel Entry Priority value.
   3939  *
   3940  * Returns:
   3941  *     BCM_E_XX
   3942  *
   3943  * Notes:
   3944  *     The earlier checks guarantee that there is a free slot somewhere
   3945  *     i.e. in one of the alloted slices for the group.
   3946  */
   3947 int
   3948 _bcm_field_presel_entry_prio_set(int unit, bcm_field_entry_t entry, int prio)
   3949 {
   3950     int                     rv;                /* Operation return status. */
   3951     _field_control_t        *fc;               /* Field control structure. */
   3952     _field_presel_entry_t   *f_presel;         /* Presel entry structure.  */
   3953     bcm_field_presel_t      presel;            /* Field Preselector ID.    */
   3954 
   3955     /* Preselector feature check */
   3956     if (!soc_feature(unit, soc_feature_field_preselector_support)) {
   3957        return BCM_E_UNAVAIL;
   3958     }
   3959 
   3960     /* Resolve the Preselector ID from the given Entry ID */
   3961     rv = _bcm_field_entry_presel_resolve(unit, entry, &presel, &f_presel);
   3962     if (BCM_FAILURE(rv)) {
   3963        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   3964                "ERROR: Unable to resolve the Presel Entry ID %d.\n\r"), entry));
   3965        return rv;
   3966     }
   3967 
   3968     /* Get field control structure. */
   3969     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   3970 
   3971     /* Verify if the Presel ID is already in USE */
   3972     if (BCM_FIELD_PRESEL_TEST(fc->presel_info->operational_set, presel) &&
   3973         !(f_presel->flags & _FP_ENTRY_DIRTY)) {
   3974        BCM_IF_ERROR_RETURN (_field_presel_entry_prio_set(unit, f_presel, prio));
   3975     }
   3976 
   3977     /* Assign the priority */
   3978     f_presel->priority = prio;
   3979 
   3980     return BCM_E_NONE;
   3981 }
   3982 
   3983 /*
   3984  * Function: _bcm_field_presel_entry_prio_get
   3985  *
   3986  * Purpose: Retreive the preselector entry priority value.
   3987  *
   3988  * Parameters:
   3989  *     unit  - (IN)  BCM device number
   3990  *     entry - (IN)  Field presel entry to operate on.
   3991  *     prio  - (OUT) Presel Entry Priority value.
   3992  *
   3993  * Returns:
   3994  *     BCM_E_XX
   3995  */
   3996 int
   3997 _bcm_field_presel_entry_prio_get(int unit, bcm_field_entry_t entry, int *prio)
   3998 {
   3999     int                     rv;                /* Operation return status. */
   4000     _field_presel_entry_t   *f_presel;         /* Presel entry structure.  */
   4001     bcm_field_presel_t      presel;            /* Field Preselector ID.    */
   4002 
   4003     /* Validate input parameters. */
   4004     if (prio == NULL) {
   4005        return BCM_E_PARAM;
   4006     }
   4007 
   4008     /* Preselector feature check */
   4009     if (!soc_feature(unit, soc_feature_field_preselector_support)) {
   4010        return BCM_E_UNAVAIL;
   4011     }
   4012 
   4013     /* Resolve the Preselector ID from the given Entry ID */
   4014     rv = _bcm_field_entry_presel_resolve(unit, entry, &presel, &f_presel);
   4015     if (BCM_FAILURE(rv)) {
   4016        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   4017                "ERROR: Unable to resolve the Presel Entry ID %d.\n\r"), entry));
   4018        return rv;
   4019     }
   4020 
   4021     *prio = f_presel->priority;
   4022     return BCM_E_NONE;
   4023 }
   4024 
   4025 
   4026 /*
   4027  * Function:
   4028  *    _field_th_lt_entry_data_config_set
   4029  * Purpose:
   4030  *    Configure LT Entry data parameters generated by group (keygen profile ..)
   4031  *    and actions configured by the presel.
   4032  * Parameters:
   4033  *     unit     - (IN)      BCM device number.
   4034  *     stage_fc - (IN)      Stage field control structure.
   4035  *     f_presel - (IN/OUT)  Preselector Entry structure.
   4036  * Returns:
   4037  *     BCM_E_XXX
   4038  */
   4039 int
   4040 _field_th_lt_entry_data_config_set(int unit, _field_stage_t *stage_fc,
   4041                                    _field_presel_entry_t *f_presel)
   4042 {
   4043     int                   idx;      /* Entry parts iterator.        */
   4044     int                   parts;    /* Number of field entry parts. */
   4045     _field_group_t        *fg;      /* Field group structure.       */
   4046     soc_mem_t             lt_data_mem;
   4047     _field_presel_entry_t *f_presel_part;
   4048 
   4049     /* Input parameters check. */
   4050     if ((NULL == stage_fc) || (NULL == f_presel)) {
   4051         return (BCM_E_PARAM);
   4052     }
   4053 
   4054     /* Get entry's group structure. */
   4055     fg = f_presel->group;
   4056 
   4057     /* Get number of lt entry parts. */
   4058     BCM_IF_ERROR_RETURN(_bcm_field_th_lt_entry_tcam_parts_count(unit,
   4059                                     stage_fc->stage_id, fg->flags, &parts));
   4060 
   4061     if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) {
   4062         BCM_IF_ERROR_RETURN (_bcm_field_th_lt_tcam_policy_mem_get(
   4063                                         unit, stage_fc, fg->instance,
   4064                                           _BCM_FIELD_MEM_TYPE_IFP_LT,
   4065                                        _BCM_FIELD_MEM_VIEW_TYPE_DATA,
   4066                                                 NULL, &lt_data_mem));
   4067     } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) {
   4068         BCM_IF_ERROR_RETURN (_bcm_field_th_lt_tcam_policy_mem_get(
   4069                                         unit, stage_fc, fg->instance,
   4070                                            _BCM_FIELD_MEM_TYPE_EM_LT,
   4071                                        _BCM_FIELD_MEM_VIEW_TYPE_DATA,
   4072                                                 NULL, &lt_data_mem));
   4073 #if defined(BCM_FLOWTRACKER_SUPPORT)
   4074     } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) {
   4075         BCM_IF_ERROR_RETURN (_bcm_field_th_lt_tcam_policy_mem_get(
   4076                                         unit, stage_fc, fg->instance,
   4077                                            _BCM_FIELD_MEM_TYPE_FT_LT,
   4078                                        _BCM_FIELD_MEM_VIEW_TYPE_DATA,
   4079                                                 NULL, &lt_data_mem));
   4080 #endif
   4081     } else {
   4082         return (BCM_E_PARAM);
   4083     }
   4084 
   4085     f_presel_part = f_presel;
   4086     /* Install entry parts in hardware. */
   4087     for (idx = 0; (idx < parts && f_presel_part != NULL); idx++) {
   4088         /* Install keygen program profile table entries for the group in HW */
   4089         BCM_IF_ERROR_RETURN (_bcm_field_th_group_keygen_profiles_index_alloc(
   4090                                                               unit, stage_fc,
   4091                                                               fg, idx));
   4092 
   4093         /* Allocate the Preselector Data Memory. */
   4094         BCM_IF_ERROR_RETURN (_bcm_field_th_presel_mem_data_get(
   4095                                                unit, stage_fc, fg->instance,
   4096                                                f_presel_part,
   4097                                                &f_presel_part->lt_data));
   4098 
   4099         /* Build LT selection Data entry. */
   4100         BCM_IF_ERROR_RETURN (_bcm_field_th_lt_entry_data_value_set(
   4101                                                unit, stage_fc, fg, idx,
   4102                                                lt_data_mem,
   4103                                                f_presel_part->lt_data.data));
   4104 
   4105         /* Assign the Preselector Entry Actions to the LT Data entry. */
   4106         BCM_IF_ERROR_RETURN (_bcm_field_presel_entry_actions_set(
   4107                                                 unit, lt_data_mem,
   4108                                                 f_presel_part,
   4109                                                 f_presel_part->lt_data.data));
   4110 
   4111         f_presel_part = f_presel_part->next;
   4112     }
   4113 
   4114     return (BCM_E_NONE);
   4115 }
   4116 
   4117 
   4118 /*
   4119  * Function:
   4120  *    _field_th_lt_entry_phys_create
   4121  * Purpose:
   4122  *    Create a physical entry in a logical table slice.
   4123  * Parameters:
   4124  *    unit      - (IN) BCM device number.
   4125  *    stage_fc  - (IN) Stage field control structure.
   4126  *    lt_ent    - (IN) Logical table entry identifier.
   4127  *    prio      - (IN) Logical table entry priority.
   4128  *    lt_fs     - (IN) Logical table slice structure.
   4129  *    fg        - (IN) Field group structure.
   4130  *    f_presel  - (OUT) Allocated & initialized entry.
   4131  * Returns:
   4132  *    BCM_E_XXX
   4133  */
   4134 STATIC int
   4135 _field_th_lt_entry_phys_create(int unit, _field_stage_t *stage_fc,
   4136                                bcm_field_presel_t lt_ent, int prio,
   4137                                _field_lt_slice_t *lt_fs, _field_group_t *fg,
   4138                                _field_presel_entry_t *f_presel)
   4139 {
   4140     _field_control_t *fc;   /* Field control structure.              */
   4141     int idx;                /* Slice entries iteration index.        */
   4142     int parts_count = -1;   /* Number of entry parts.                */
   4143     int part_index;         /* Entry parts iterator.                 */
   4144     int rv;                 /* Operation return status.              */
   4145     int pri_tcam_idx = -1;  /* Primary entry TCAM index.             */
   4146     int slice_num = -1;     /* Slice number.                         */
   4147     _field_presel_entry_t *f_presel_p = NULL; /* LT field entry structure. */
   4148 
   4149     /* Input parameters check. */
   4150     if ((NULL == stage_fc) || (NULL == lt_fs) ||
   4151         (NULL == fg) || (NULL == f_presel)) {
   4152         return (BCM_E_PARAM);
   4153     }
   4154 
   4155     /* Check if free entries are available in the slice. */
   4156     if (0 == lt_fs->free_count) {
   4157         return (BCM_E_RESOURCE);
   4158     }
   4159 
   4160     /* Get device field control structure. */
   4161     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   4162 
   4163     /* Get number of entry partss. */
   4164     BCM_IF_ERROR_RETURN(_bcm_field_th_lt_entry_tcam_parts_count(unit,
   4165                                 stage_fc->stage_id, fg->flags, &parts_count));
   4166 
   4167     /* Get index for primary entry. */
   4168     for (idx = 0; idx < lt_fs->entry_count; idx++) {
   4169         if (NULL == lt_fs->p_entries[idx]) {
   4170             f_presel->hw_index = idx;
   4171             break;
   4172         }
   4173     }
   4174 
   4175     if (idx == lt_fs->entry_count) {
   4176        /* If this condition occurs, that means, free_count is not decremented
   4177         * properly, it would have caught above for (0 == lt_fs->free_count) */
   4178        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   4179            "Error: Allocation failure for presel[%d], Entries reached max"
   4180            "entries in the slice, free_count is not decremented properly.\n\r"),
   4181            f_presel->presel_id));
   4182        return BCM_E_INTERNAL;
   4183     }
   4184 
   4185     /* Get entry TCAM index given slice number and entry offset in slice. */
   4186     rv = _bcm_field_th_lt_slice_offset_to_tcam_index(unit, stage_fc,
   4187                                   fg->instance, lt_fs->slice_number,
   4188                                   f_presel->hw_index, &pri_tcam_idx);
   4189     if (BCM_FAILURE(rv)) {
   4190        return rv;
   4191     }
   4192 
   4193     if (parts_count > 1) {
   4194        _field_presel_entry_t *p_ent_alloc;
   4195 
   4196        f_presel_p = f_presel;
   4197        /* Allocate memory for presel entries for double/triple wide modes. */
   4198        for (idx = 1; idx < parts_count; idx++) {
   4199           p_ent_alloc = NULL;
   4200           _FP_XGS3_ALLOC(p_ent_alloc, sizeof(_field_presel_entry_t),
   4201                       "Presel Entry Alloc.");
   4202           if (NULL == p_ent_alloc) {
   4203               LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   4204                 "Error: allocation failure for Presel[%d] Parts entry[%d]\n"),
   4205                  f_presel->presel_id, idx));
   4206               return (BCM_E_MEMORY);
   4207           }
   4208           /* Copy the base presel entry contents to its allocated part entry */
   4209           sal_memcpy(p_ent_alloc, f_presel_p, sizeof(_field_presel_entry_t));
   4210           f_presel_p->next = p_ent_alloc;
   4211           f_presel_p = p_ent_alloc;
   4212        }
   4213     }
   4214 
   4215     f_presel_p = f_presel;
   4216     /* Fill entry primitives. */
   4217     for (idx = 0; (idx < parts_count && f_presel_p != NULL); idx++) {
   4218         /* Get entry part flags. */
   4219         rv = _bcm_field_th_tcam_part_to_entry_flags(unit, idx, fg->flags,
   4220                                                     &(f_presel_p->flags));
   4221         if (BCM_FAILURE(rv)) {
   4222             goto bcm_error;
   4223         }
   4224 
   4225         /* Given primary entry TCAM index calculate entry part tcam index. */
   4226         if (0 != idx) {
   4227             rv = _bcm_field_th_lt_entry_part_tcam_idx_get(unit, fg,
   4228                                                           pri_tcam_idx,
   4229                                                           idx, &part_index);
   4230             if (BCM_FAILURE(rv)) {
   4231                 goto bcm_error;
   4232             }
   4233 
   4234             /*
   4235              * Given entry part TCAM index, determine the slice number and slice
   4236              * offset index.
   4237              */
   4238             rv = _bcm_field_th_lt_tcam_idx_to_slice_offset(unit, stage_fc,
   4239                     fg->instance, part_index, &slice_num,
   4240                     (int *)&f_presel_p->hw_index);
   4241             if (BCM_FAILURE(rv)) {
   4242                 goto bcm_error;
   4243             }
   4244             f_presel_p->lt_fs = stage_fc->lt_slices[fg->instance] + slice_num;
   4245         } else {
   4246             /* Set entry slice. */
   4247             f_presel_p->lt_fs = lt_fs;
   4248         }
   4249 
   4250         /* Assign the group it belongs to. */
   4251         f_presel_p->group = fg;
   4252 
   4253         /* Decrement slice free entry count for primary entries. */
   4254         f_presel_p->lt_fs->free_count--;
   4255 
   4256         /* Assign entry to a slice. */
   4257         f_presel_p->lt_fs->p_entries[f_presel_p->hw_index] = f_presel_p;
   4258 
   4259         /* Mark entry dirty. */
   4260         f_presel_p->flags |= _FP_ENTRY_DIRTY;
   4261 
   4262         /* Next Entry Part */
   4263         f_presel_p = f_presel_p->next;
   4264     }
   4265 
   4266     /* Add the Preselector from field control operational status. */
   4267     BCM_FIELD_PRESEL_ADD(fc->presel_info->operational_set, f_presel->presel_id);
   4268 
   4269     return (rv);
   4270 
   4271 bcm_error:
   4272     if (BCM_FAILURE(rv)) {
   4273        _field_presel_entry_t *p_ent_free = NULL;
   4274 
   4275        f_presel_p = f_presel;
   4276        /* Allocate memory for presel entries for double/triple wide modes. */
   4277        for (idx = 1; idx < parts_count; idx++) {
   4278           if (f_presel_p != NULL) {
   4279              p_ent_free = f_presel_p;
   4280              f_presel_p = f_presel_p->next;
   4281              sal_free(p_ent_free);
   4282           }
   4283        }
   4284     }
   4285 
   4286     return rv;
   4287 }
   4288 
   4289 /*
   4290  * Function:
   4291  *    _bcm_field_th_lt_entry_phys_destroy
   4292  * Purpose:
   4293  *    Destroy a physical entry from a logical table slice.
   4294  * Parameters:
   4295  *    unit     - (IN) BCM device number.
   4296  *    f_presel - (IN) Preselector Logical table entry structure.
   4297  * Returns:
   4298  *    BCM_E_XXX
   4299  */
   4300 int
   4301 _bcm_field_th_lt_entry_phys_destroy(int unit, _field_presel_entry_t *f_presel)
   4302 {
   4303     int                    idx;      /* Entry iterator index.           */
   4304     int                    parts;    /* Entry parts count.              */
   4305     uint8                  slice_number; /* Slice number.               */
   4306     _field_control_t       *fc;      /* Device field control structure. */
   4307     _field_group_t         *fg;      /* Field group structure.          */
   4308     _field_presel_entry_t  *f_presel_p;    /* Presel Part Entry.        */
   4309     _field_presel_entry_t  *f_presel_free; /* Presel entry to be freed. */
   4310 
   4311     /* Input parameters check. */
   4312     if ((NULL == f_presel) || (NULL == f_presel->lt_fs)) {
   4313         return (BCM_E_PARAM);
   4314     }
   4315 
   4316     /* Get field control structure. */
   4317     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   4318 
   4319     /* Get the group to which the entry belongs. */
   4320     fg = f_presel->group;
   4321 
   4322     /* Get entry parts count. */
   4323     BCM_IF_ERROR_RETURN(_bcm_field_th_lt_entry_tcam_parts_count(unit,
   4324                                 fg->stage_id, fg->flags, &parts));
   4325 
   4326     f_presel_p = f_presel;
   4327     for (idx = 0; (idx < parts && f_presel_p != NULL); idx++) {
   4328         /* Free entry Data mask buffer if valid. */
   4329         if (NULL != f_presel_p->lt_data.data) {
   4330             sal_free(f_presel_p->lt_data.data);
   4331             f_presel_p->lt_data.data = NULL;
   4332         }
   4333 
   4334         /* Get entry part slice number. */
   4335         BCM_IF_ERROR_RETURN(_bcm_field_th_tcam_part_to_slice_number(idx,
   4336             fg->flags, &slice_number));
   4337 
   4338         /* Remove entry pointer from the slice. */
   4339         f_presel_p->lt_fs->p_entries[f_presel_p->hw_index] = NULL;
   4340 
   4341         /* Increment slice unused entry count. */
   4342         f_presel_p->lt_fs->free_count++;
   4343 
   4344         f_presel_free = f_presel_p;
   4345         f_presel_p = f_presel_p->next;
   4346 
   4347         /* De-allocate the part entries except Primary entry */
   4348         if (f_presel_free != f_presel) {
   4349            sal_free(f_presel_free);
   4350            f_presel_free = NULL;
   4351         }
   4352     }
   4353     f_presel->next = NULL;
   4354 
   4355     /* Remove the Preselector from field control operational status. */
   4356     BCM_FIELD_PRESEL_REMOVE(fc->presel_info->operational_set,
   4357                             f_presel->presel_id);
   4358 
   4359     return (BCM_E_NONE);
   4360 }
   4361 
   4362 /*
   4363  * Function:
   4364  *    _bcm_field_th_lt_entry_config_set
   4365  * Purpose:
   4366  *    Associate presel entry to the slice/s reserved in logical table selection
   4367  *    TCAM for the field group.
   4368  * Parameters:
   4369  *     unit         - (IN)  BCM device number.
   4370  *     stage_fc     - (IN)  Stage field control structure.
   4371  *     fg           - (IN)  Field group structure.
   4372  *     lt_fs        - (IN)  Field logical table slice structure.
   4373  *     f_presel     - (IN)  Reference to Field Preselector Entry strcture.
   4374  * Returns:
   4375  *     BCM_E_XXX
   4376  */
   4377 int
   4378 _bcm_field_th_lt_entry_config_set(int unit,
   4379                                   _field_stage_t *stage_fc,
   4380                                   _field_group_t *fg,
   4381                                   _field_lt_slice_t *lt_fs,
   4382                                   _field_presel_entry_t *f_presel)
   4383 {
   4384     _field_control_t      *fc;       /* Field control structure.    */
   4385     int                   rv;        /* Operation return status.    */
   4386 
   4387     /* Input parameter check. */
   4388     if ((NULL == stage_fc) || (NULL == fg) ||
   4389         (NULL == lt_fs) || (NULL == f_presel)) {
   4390        return (BCM_E_PARAM);
   4391     }
   4392 
   4393     /* Check if Presel Flags are appropriate */
   4394     if (!(fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT)) {
   4395        return (BCM_E_INTERNAL);
   4396     }
   4397 
   4398     /* Get device field control handle. */
   4399     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   4400 
   4401     /*
   4402      * Create Presel Entries in the LT slice associated with the group
   4403      */
   4404     rv = _field_th_lt_entry_phys_create
   4405                   (unit, stage_fc, f_presel->presel_id,
   4406                    BCM_FIELD_ENTRY_PRIO_LOWEST, lt_fs, fg, f_presel);
   4407     if (BCM_FAILURE(rv)) {
   4408        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   4409          "Error: Presel Slice Entry Creation failed for Id[%d]\n\r"),
   4410                  f_presel->presel_id));
   4411        return (rv);
   4412     }
   4413 
   4414     /* Set up LT selection rule based on group's keygen codes. */
   4415     rv = _field_th_lt_entry_data_config_set(unit, stage_fc, f_presel);
   4416     if (BCM_FAILURE(rv)) {
   4417        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   4418          "Error: Presel Entry Rule Configuration failed for Id[%d]\n\r"),
   4419                  f_presel->presel_id));
   4420        /* Destroy resources allocated for the entry. */
   4421        _bcm_field_th_lt_entry_phys_destroy(unit, f_presel);
   4422        return (rv);
   4423     }
   4424     return (rv);
   4425 }
   4426 
   4427 /*
   4428  * Function:
   4429  *     _bcm_field_th_lt_entry_hw_install
   4430  * Purpose:
   4431  *     Install an LT TCAM entry part in hardware at the supplied entry index.
   4432  * Parameters:
   4433  *     unit        - (IN) BCM device number.
   4434  *     lt_tcam_mem - (IN) LT TCAM Memory.
   4435  *     tcam_idx    - (IN) TCAM index at which entry must be written in HW.
   4436  *     key         - (IN) TCAM Entry Key to be written.
   4437  *     mask        - (IN) TCAM Entry Mask to be written.
   4438  *     data        - (IN) TCAM Entry Data to be written.
   4439  *     valid       - (IN) Entry Valid (TRUE) / Invalid (FALSE)
   4440  * Returns:
   4441  *     BCM_E_XXX
   4442  *
   4443  * Note: To only enable/disable the entry, invoke this function with NULL key, mask and data.
   4444  */
   4445 int
   4446 _bcm_field_th_lt_entry_hw_install(int unit, soc_mem_t lt_tcam_mem, int tcam_idx,
   4447                                   uint32 *key, uint32 *mask, uint32 *data,
   4448                                   uint8 valid)
   4449 {
   4450     uint32         entry[SOC_MAX_MEM_FIELD_WORDS] = {0}; /* Entry buffer.   */
   4451 
   4452     /* Input parameters check. */
   4453     if ((NULL == key) || (NULL == mask) || (NULL == data)) {
   4454         /* Read entry into SW buffer. */
   4455         BCM_IF_ERROR_RETURN(soc_mem_read(unit, lt_tcam_mem, MEM_BLOCK_ANY,
   4456                                          tcam_idx, entry));
   4457     } else {
   4458         /* Clear the entry in hardware. */
   4459         BCM_IF_ERROR_RETURN(soc_mem_write(unit, lt_tcam_mem, MEM_BLOCK_ALL,
   4460                                       tcam_idx, entry));
   4461         /* Read entry into SW buffer. */
   4462         BCM_IF_ERROR_RETURN(soc_mem_read(unit, lt_tcam_mem, MEM_BLOCK_ANY, tcam_idx,
   4463                                      entry));
   4464         /* Set entry Key, Mask and Data value. */
   4465         soc_mem_field_set(unit, lt_tcam_mem, entry, KEYf,  key);
   4466         soc_mem_field_set(unit, lt_tcam_mem, entry, MASKf, mask);
   4467         soc_mem_field_set(unit, lt_tcam_mem, entry, DATAf, data);
   4468     }
   4469 
   4470     /* Set entry valid bit status. */
   4471     soc_mem_field32_set(unit, lt_tcam_mem, entry, VALIDf, valid);
   4472 
   4473     /* Install entry in hardware. */
   4474     BCM_IF_ERROR_RETURN(soc_mem_write(unit, lt_tcam_mem, MEM_BLOCK_ALL,
   4475                                       tcam_idx, entry));
   4476     return (BCM_E_NONE);
   4477 }
   4478 
   4479 /*
   4480  * Function:
   4481  *     _bcm_field_th_lt_entry_install
   4482  * Purpose:
   4483  *     Install a logical table entry in hardware.
   4484  * Parameters:
   4485  *     unit     - (IN) BCM device number.
   4486  *     f_presel - (IN) Reference to Field Preselector Entry structure.
   4487  *     lt_fs    - (IN) Reference to the Logical table slice structure.
   4488  * Returns:
   4489  *     BCM_E_XXX
   4490  */
   4491 int
   4492 _bcm_field_th_lt_entry_install(int unit, _field_presel_entry_t *f_presel,
   4493                                _field_lt_slice_t *lt_fs)
   4494 {
   4495     _field_stage_t   *stage_fc;        /* Stage Field Control structure.  */
   4496     int              tcam_idx;         /* Entry TCAM index.               */
   4497     _field_control_t *fc;              /* Field control pointer.          */
   4498     int              rv = BCM_E_NONE;  /* Operation return status.        */
   4499     soc_mem_t        lt_tcam_mem;      /* TCAM memory ID.                 */
   4500     uint8            valid;            /* Entry Valid bit.                */
   4501 
   4502     /* Input parameters check. */
   4503     if (NULL == f_presel || NULL == lt_fs) {
   4504         return (BCM_E_PARAM);
   4505     }
   4506 
   4507     /* Get device field control structure. */
   4508     BCM_IF_ERROR_RETURN(_field_control_get(unit , &fc));
   4509 
   4510     /* Get device stage control structure. */
   4511     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
   4512                             f_presel->group->stage_id, &stage_fc));
   4513 
   4514     /*
   4515      * Get TCAM view to be used for programming the hardware based on the group
   4516      * operational mode.
   4517      */
   4518     if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) {
   4519         rv = (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc,
   4520                                         f_presel->group->instance,
   4521                                        _BCM_FIELD_MEM_TYPE_IFP_LT,
   4522                           _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB,
   4523                                              &lt_tcam_mem, NULL));
   4524     } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) {
   4525         rv = (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc,
   4526                                         f_presel->group->instance,
   4527                                         _BCM_FIELD_MEM_TYPE_EM_LT,
   4528                           _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB,
   4529                                              &lt_tcam_mem, NULL));
   4530 #if defined(BCM_FLOWTRACKER_SUPPORT)
   4531     } else if ((soc_feature(unit, soc_feature_field_flowtracker_support)) &&
   4532         (stage_fc->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER)) {
   4533         return _bcm_field_hx5_ft_lt_entry_install(unit, f_presel, lt_fs);
   4534 #endif
   4535     } else {
   4536         return (BCM_E_PARAM);
   4537     }
   4538     BCM_IF_ERROR_RETURN(rv);
   4539 
   4540 #if defined(BCM_TOMAHAWK2_SUPPORT)
   4541     if (soc_feature(unit, soc_feature_field_multi_pipe_enhanced) &&
   4542         _BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) {
   4543         valid = (f_presel->group->flags & _FP_GROUP_LOOKUP_ENABLED) ? 3 : 0;
   4544     } else
   4545 #endif /* BCM_TOMAHAWK2_SUPPORT */
   4546     {
   4547         valid = (f_presel->group->flags & _FP_GROUP_LOOKUP_ENABLED) ?
   4548                 (soc_feature(unit, soc_feature_td3_style_fp) ? 3 : 1) : 0;
   4549     }
   4550     rv = _bcm_field_presel_entry_tcam_idx_get(unit, f_presel, lt_fs,
   4551                                               &tcam_idx);
   4552     BCM_IF_ERROR_RETURN(rv);
   4553 
   4554     /* Install all parts of the entry in hardware. */
   4555     rv = _bcm_field_th_lt_entry_hw_install(unit, lt_tcam_mem, tcam_idx,
   4556                                                f_presel->lt_tcam.key,
   4557                                                f_presel->lt_tcam.mask,
   4558                                                f_presel->lt_data.data,
   4559                                                valid);
   4560     if (BCM_FAILURE(rv)) {
   4561         return (rv);
   4562     }
   4563 
   4564     f_presel->flags &= ~_FP_ENTRY_DIRTY;
   4565     f_presel->flags |= _FP_ENTRY_INSTALLED;
   4566     f_presel->flags |= _FP_ENTRY_ENABLED;
   4567 
   4568     return (rv);
   4569 }
   4570 
   4571 /*
   4572  * Function:
   4573  *     _bcm_field_th_lt_entry_parts_install
   4574  * Purpose:
   4575  *     Install a logical table entry and its parts in hardware.
   4576  * Parameters:
   4577  *     unit     - (IN) BCM device number.
   4578  *     f_presel - (IN)  Reference to Field Preselector Entry strcture.
   4579  * Returns:
   4580  *     BCM_E_XXX
   4581  */
   4582 int
   4583 _bcm_field_th_lt_entry_parts_install(int unit, _field_presel_entry_t *f_presel)
   4584 {
   4585     int part, parts_count = -1;
   4586     _field_lt_slice_t      *lt_fs;
   4587     _field_presel_entry_t  *f_presel_p;
   4588 
   4589     /* Input parameters check. */
   4590     if (NULL == f_presel) {
   4591         return (BCM_E_PARAM);
   4592     }
   4593 
   4594     /* Get number of entry parts. */
   4595     BCM_IF_ERROR_RETURN(_bcm_field_th_lt_entry_tcam_parts_count(unit,
   4596                                 f_presel->group->stage_id,
   4597                                 f_presel->group->flags, &parts_count));
   4598 
   4599     f_presel_p = f_presel;
   4600     for (part = parts_count -1; part >= 0; part--) {
   4601         if (f_presel_p == NULL) {
   4602            return BCM_E_INTERNAL;
   4603         }
   4604 
   4605         lt_fs = f_presel_p->lt_fs;
   4606         BCM_IF_ERROR_RETURN(_bcm_field_th_lt_entry_install
   4607                                       (unit, f_presel_p, lt_fs));
   4608         f_presel_p = f_presel_p->next;
   4609     }
   4610 
   4611     return BCM_E_NONE;
   4612 }
   4613 
   4614 /*
   4615  * Function: _bcm_field_th_group_presel_get
   4616  *
   4617  * Purpose:
   4618  *     Retrieve the set of preselectors associated with the given group.
   4619  *
   4620  * Parameters:
   4621  *     unit      - (IN)  BCM device number.
   4622  *     group     - (IN)  Group Id.
   4623  *     presel    - (OUT) Reference to the set of preselectors.
   4624  *
   4625  * Returns:
   4626  *     BCM_E_PARAM    - if presel_id == NULL or given group Id is not valid.
   4627  *     BCM_E_UNAVAIL  - not supported
   4628  *     BCM_E_NONE     - Success
   4629  */
   4630 
   4631 int
   4632 _bcm_field_th_group_presel_get(
   4633     int unit,
   4634     bcm_field_group_t group,
   4635     bcm_field_presel_set_t *presel)
   4636 {
   4637     int                   idx;
   4638     _field_group_t        *fg;                 /* Field group pointer.      */
   4639     _field_control_t      *fc;                 /* Field control structure.  */
   4640 
   4641     /* Input parameters check. */
   4642     if (NULL == presel) {
   4643         return (BCM_E_PARAM);
   4644     }
   4645 
   4646     /* Get field control structure. */
   4647     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   4648 
   4649     BCM_IF_ERROR_RETURN(_field_group_get(unit, group, &fg));
   4650 
   4651     sal_memset(presel, 0x0, sizeof(bcm_field_presel_set_t));
   4652     /* count the number of preselector entries associated to the group */
   4653     for (idx = 0; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) {
   4654        if (fg->presel_ent_arr[idx] != NULL) {
   4655           BCM_FIELD_PRESEL_ADD(*presel, fg->presel_ent_arr[idx]->presel_id);
   4656        }
   4657     }
   4658 
   4659     return BCM_E_NONE;
   4660 }
   4661 
   4662 /*
   4663  * Function: _bcm_field_th_field_presel_set
   4664  *
   4665  * Purpose:
   4666  *     Set the preselectors to the given group.
   4667  *
   4668  * Parameters:
   4669  *     unit      - (IN) BCM device number.
   4670  *     group     - (IN) Group Id.
   4671  *     presel    - (IN) Reference to the set of preselectors.
   4672  *
   4673  * Returns:
   4674  *     BCM_E_PARAM     - if presel_id == NULL
   4675  *     BCM_E_UNAVAIL   - not supported
   4676  *     BCM_E_NOT_FOUND - if the presel Ids are not created.
   4677  *     BCM_E_INTERAL   - in-case of internal functionality issues.
   4678  *     BCM_E_NONE      - Success
   4679  */
   4680 
   4681 int
   4682 _bcm_field_th_group_presel_set(
   4683     int unit,
   4684     bcm_field_group_t group,
   4685     bcm_field_presel_set_t *presel)
   4686 {
   4687     int                    rv = BCM_E_UNAVAIL; /* Operation return status.  */
   4688     _field_group_t         *fg;                /* Field group pointer.      */
   4689     _field_control_t       *fc;                /* Field control structure.  */
   4690     _field_stage_t         *stage_fc;          /* Stage field structure.    */
   4691     int                    idx, ent_ct;
   4692     int                    presel_ent_ct = 0, presel_id_ct = 0;
   4693     int                    prio[_FP_PRESEL_ENTRIES_MAX_PER_GROUP];
   4694     _field_presel_entry_t  *f_presel;
   4695     _field_presel_entry_t  *f_presel_arr[_FP_PRESEL_ENTRIES_MAX_PER_GROUP];
   4696     _field_lt_slice_t      *lt_fs;
   4697 
   4698     /* Get field control structure. */
   4699     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   4700 
   4701     BCM_IF_ERROR_RETURN(_field_group_get(unit, group, &fg));
   4702 
   4703     /* Get device stage control structure. */
   4704     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
   4705                             fg->stage_id, &stage_fc));
   4706 
   4707     /* Group should support the preselector feature. */
   4708     if (!(fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT)) {
   4709        return BCM_E_UNAVAIL;
   4710     }
   4711 
   4712 
   4713     /* Validate all the preselector entries in the set */
   4714     for (idx = 0; idx < BCM_FIELD_PRESEL_SEL_MAX; idx++) {
   4715        if (BCM_FIELD_PRESEL_TEST(*presel, idx)) {
   4716           /* Check if presel ID is already created */
   4717           if (!BCM_FIELD_PRESEL_TEST(fc->presel_info->presel_set, idx)) {
   4718              LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   4719              "ERROR: Preselector ID[%d] is not created.\n\r"), idx));
   4720              return BCM_E_NOT_FOUND;
   4721           }
   4722           if (BCM_FIELD_PRESEL_TEST(fc->presel_info->operational_set, idx)) {
   4723              LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
   4724              "Preselector ID[%d] is already in USE"
   4725              "Updating the hardware.\n\r"), idx));
   4726              BCM_IF_ERROR_RETURN(_bcm_field_presel_entry_get(unit, idx,
   4727                          &f_presel));
   4728              rv = _field_presel_entry_update(unit, f_presel);
   4729           }
   4730           presel_id_ct++;
   4731        }
   4732     }
   4733     if(BCM_E_UNAVAIL != rv) {
   4734         return rv;
   4735     }
   4736     /* count the number of preselector entries associated to the group */
   4737     for (idx = 0; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) {
   4738        if (fg->presel_ent_arr[idx] != NULL) {
   4739           presel_ent_ct++;
   4740        }
   4741     }
   4742 
   4743     /* Check if group supports the presel entries. */
   4744     if ((presel_ent_ct + presel_id_ct) > _FP_PRESEL_ENTRIES_MAX_PER_GROUP) {
   4745        return BCM_E_RESOURCE;
   4746     }
   4747 
   4748     /* Check if the Slice has free entries */
   4749     lt_fs = fg->presel_ent_arr[0]->lt_fs;
   4750     if (lt_fs->free_count < presel_id_ct) {
   4751        return BCM_E_RESOURCE;
   4752     }
   4753 
   4754     ent_ct = 0;
   4755     /* Add the preselector entries to the group */
   4756     for (idx = 0; idx < BCM_FIELD_PRESEL_SEL_MAX; idx++) {
   4757        if (BCM_FIELD_PRESEL_TEST(*presel, idx)) {
   4758           BCM_IF_ERROR_RETURN(_bcm_field_presel_entry_get(unit, idx,
   4759                                                           &f_presel));
   4760           f_presel_arr[ent_ct] = f_presel;
   4761           prio[ent_ct] = f_presel->priority;
   4762           f_presel->priority = 0;
   4763           ent_ct++;
   4764        }
   4765     }
   4766 
   4767     /*
   4768      * Create Presel Entries in the LT slice associated with the group
   4769      */
   4770     for (idx = 0; idx < ent_ct; idx++) {
   4771        f_presel = f_presel_arr[idx];
   4772        /* Assign the preselectors to the group presel array. */
   4773        rv = _bcm_field_presel_group_add(unit, fg, f_presel->presel_id);
   4774        if (BCM_FAILURE(rv)) {
   4775           return rv;
   4776        }
   4777 
   4778        /* Allocate the presel entries in the LT slice for this group. */
   4779        BCM_IF_ERROR_RETURN
   4780            (_bcm_field_th_lt_entry_config_set(unit, stage_fc, fg,
   4781                                               lt_fs, f_presel));
   4782 
   4783        /* Install the LT Entry in HW. */
   4784        rv = _bcm_field_th_lt_entry_parts_install(unit, f_presel);
   4785        BCM_IF_ERROR_RETURN(rv);
   4786 
   4787        rv = _field_presel_entry_prio_set(unit, f_presel, prio[idx]);
   4788        if (BCM_FAILURE(rv)) {
   4789           LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   4790           "ERROR: Unable to set the priority[%d] for Preselector ID[%d].\n\r"),
   4791           prio[idx], idx));
   4792           return BCM_E_INTERNAL;
   4793        }
   4794     }
   4795 
   4796     return rv;
   4797 }
   4798 
   4799 /*
   4800  * Function:
   4801  *     _bcm_field_th_ingress_lt_action_prio_install
   4802  * Purpose:
   4803  *     Write logical table action priortiy information to hardware.
   4804  * Parameters:
   4805  *     unit     - (IN) BCM device number.
   4806  *     stage_fc - (IN) Field stage control structure.
   4807  *     fg       - (IN) Field group Structure.
   4808  * Returns:
   4809  *     BCM_E_XXX
   4810  */
   4811 int
   4812 _bcm_field_th_ingress_lt_action_prio_install(int unit,
   4813                                              _field_stage_t *stage_fc,
   4814                                              _field_group_t *fg)
   4815 {
   4816     soc_field_t         field;              /* HW entry field.       */
   4817     uint32              value;              /* Entry field value.    */
   4818     int                 lt_idx;             /* LT iterator.          */
   4819     _field_lt_config_t *lt_info;            /* Logical table info.   */
   4820     _field_control_t    *fc;        /* Field control structure.     */
   4821     uint32              entry[SOC_MAX_MEM_FIELD_WORDS];
   4822                                             /* Entry buffer.         */
   4823     static const soc_field_t lt_action_pri[] = {     /* LT action priority
   4824                                                         fields list.    */
   4825         LOGICAL_TABLE_0_ACTION_PRIORITYf,
   4826         LOGICAL_TABLE_1_ACTION_PRIORITYf,
   4827         LOGICAL_TABLE_2_ACTION_PRIORITYf,
   4828         LOGICAL_TABLE_3_ACTION_PRIORITYf,
   4829         LOGICAL_TABLE_4_ACTION_PRIORITYf,
   4830         LOGICAL_TABLE_5_ACTION_PRIORITYf,
   4831         LOGICAL_TABLE_6_ACTION_PRIORITYf,
   4832         LOGICAL_TABLE_7_ACTION_PRIORITYf,
   4833         LOGICAL_TABLE_8_ACTION_PRIORITYf,
   4834         LOGICAL_TABLE_9_ACTION_PRIORITYf,
   4835         LOGICAL_TABLE_10_ACTION_PRIORITYf,
   4836         LOGICAL_TABLE_11_ACTION_PRIORITYf,
   4837         LOGICAL_TABLE_12_ACTION_PRIORITYf,
   4838         LOGICAL_TABLE_13_ACTION_PRIORITYf,
   4839         LOGICAL_TABLE_14_ACTION_PRIORITYf,
   4840         LOGICAL_TABLE_15_ACTION_PRIORITYf,
   4841         LOGICAL_TABLE_16_ACTION_PRIORITYf,
   4842         LOGICAL_TABLE_17_ACTION_PRIORITYf,
   4843         LOGICAL_TABLE_18_ACTION_PRIORITYf,
   4844         LOGICAL_TABLE_19_ACTION_PRIORITYf,
   4845         LOGICAL_TABLE_20_ACTION_PRIORITYf,
   4846         LOGICAL_TABLE_21_ACTION_PRIORITYf,
   4847         LOGICAL_TABLE_22_ACTION_PRIORITYf,
   4848         LOGICAL_TABLE_23_ACTION_PRIORITYf,
   4849         LOGICAL_TABLE_24_ACTION_PRIORITYf,
   4850         LOGICAL_TABLE_25_ACTION_PRIORITYf,
   4851         LOGICAL_TABLE_26_ACTION_PRIORITYf,
   4852         LOGICAL_TABLE_27_ACTION_PRIORITYf,
   4853         LOGICAL_TABLE_28_ACTION_PRIORITYf,
   4854         LOGICAL_TABLE_29_ACTION_PRIORITYf,
   4855         LOGICAL_TABLE_30_ACTION_PRIORITYf,
   4856         LOGICAL_TABLE_31_ACTION_PRIORITYf
   4857     };
   4858 
   4859     static soc_mem_t lt_action_mem;
   4860 
   4861     /* Input parameters check. */
   4862     if (NULL == fg || NULL == stage_fc) {
   4863         return (BCM_E_PARAM);
   4864     }
   4865 
   4866     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   4867 
   4868     if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) {
   4869             BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit,
   4870                                              IFP_LOGICAL_TABLE_ACTION_PRIORITYm,
   4871                                              _FP_GLOBAL_INST, &lt_action_mem));
   4872     } else {
   4873         BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit,
   4874                                          IFP_LOGICAL_TABLE_ACTION_PRIORITYm,
   4875                                          fg->instance, &lt_action_mem));
   4876     }
   4877     /* Read logical table action priority entry from hardware. */
   4878     BCM_IF_ERROR_RETURN(soc_mem_read(unit, lt_action_mem,
   4879                 MEM_BLOCK_ANY, 0, &entry));
   4880 
   4881     /* Program Logical Tables configuration in hardware. */
   4882     for (lt_idx = 0; lt_idx < stage_fc->num_logical_tables; lt_idx++) {
   4883         /* Get logical table info for the default FP instance. */
   4884         lt_info = fc->lt_info[fg->instance][lt_idx];
   4885 
   4886         /* Get LT action priority value. */
   4887         value = lt_info->lt_action_pri;
   4888         field = lt_action_pri[lt_idx];
   4889 
   4890         /* Set the value in entry buffer that's to be programmed in HW. */
   4891         soc_mem_field32_set(unit, lt_action_mem, &entry,
   4892                 field, value);
   4893     }
   4894 
   4895     /* Write LT action priority entry in hardware. */
   4896     BCM_IF_ERROR_RETURN(soc_mem_write(unit, lt_action_mem,
   4897                 MEM_BLOCK_ANY, 0, &entry));
   4898 
   4899     return BCM_E_NONE;
   4900 }
   4901 
   4902 #if defined (BCM_HELIX5_SUPPORT)
   4903 /*
   4904  * Function:
   4905  *     _field_hx5_ingress_lt_partition_prio_write
   4906  * Purpose:
   4907  *     Write LT Partition priortiy for the given LT ID and Slice to HW.
   4908  * Parameters:
   4909  *     unit     - (IN) BCM device number.
   4910  *     stage_fc - (IN) Field stage control structure.
   4911  *     fg       - (IN) Field group Structure.
   4912  * Returns:
   4913  *     BCM_E_XXX
   4914  * Note: slice == -1 implies configure partition priority for all slices
   4915  *       for the given lt_id.
   4916  */
   4917 
   4918 int
   4919 _bcm_field_hx5_ingress_lt_partition_prio_write(int unit,
   4920                                               _field_stage_t *stage_fc,
   4921                                               _field_group_t *fg, int lt_id,
   4922                                               int slice)
   4923 {
   4924     int rv;                         /* Operation return status.         */
   4925     int slice_num;                  /* Slice number.                    */
   4926     int value;                      /* Partition Prio value.            */
   4927     uint32 lt_config_entry[SOC_MAX_MEM_FIELD_WORDS] = {0};
   4928                                     /* HW entry buffer.                 */
   4929     _field_lt_config_t *lt_info;    /* Logical table info.              */
   4930     soc_field_t field;              /* HW entry field.                  */
   4931     _field_control_t    *fc;        /* Field control structure.     */
   4932 
   4933     static const soc_field_t lt_part_pri[] = {
   4934         LOGICAL_PARTITION_PRIORITY_0f,
   4935         LOGICAL_PARTITION_PRIORITY_1f,
   4936         LOGICAL_PARTITION_PRIORITY_2f,
   4937         LOGICAL_PARTITION_PRIORITY_3f,
   4938         LOGICAL_PARTITION_PRIORITY_4f,
   4939         LOGICAL_PARTITION_PRIORITY_5f,
   4940         LOGICAL_PARTITION_PRIORITY_6f,
   4941         LOGICAL_PARTITION_PRIORITY_7f,
   4942         LOGICAL_PARTITION_PRIORITY_8f,
   4943         LOGICAL_PARTITION_PRIORITY_9f,
   4944         LOGICAL_PARTITION_PRIORITY_10f,
   4945         LOGICAL_PARTITION_PRIORITY_11f,
   4946         LOGICAL_PARTITION_PRIORITY_12f,
   4947         LOGICAL_PARTITION_PRIORITY_13f,
   4948         LOGICAL_PARTITION_PRIORITY_14f,
   4949         LOGICAL_PARTITION_PRIORITY_15f,
   4950         LOGICAL_PARTITION_PRIORITY_16f,
   4951         LOGICAL_PARTITION_PRIORITY_17f
   4952 
   4953     };
   4954 
   4955     static soc_mem_t lt_config_mem = IFP_LOGICAL_TABLE_CONFIGm;
   4956 
   4957     /* Input parameters check. */
   4958     if (NULL == fg || NULL == stage_fc) {
   4959         return (BCM_E_PARAM);
   4960     }
   4961 
   4962     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   4963 
   4964     rv = soc_mem_read(unit, lt_config_mem, MEM_BLOCK_ANY,
   4965             lt_id, &lt_config_entry);
   4966     BCM_IF_ERROR_RETURN(rv);
   4967 
   4968     /* Get logical table info for the default FP instance. */
   4969     lt_info = fc->lt_info[fg->instance][lt_id];
   4970     for (slice_num = 0; slice_num < stage_fc->tcam_slices; slice_num++) {
   4971         if ((slice != -1) && (slice_num != slice)) {
   4972             continue;
   4973         }
   4974         field = lt_part_pri[slice_num];
   4975         value = lt_info->lt_part_pri[slice_num];
   4976         soc_mem_field32_set(unit, lt_config_mem,
   4977                 &lt_config_entry, field, value);
   4978     }
   4979     soc_mem_field32_set(unit, lt_config_mem, &lt_config_entry,
   4980             LOGICAL_PARTITION_MAPf, lt_info->lt_part_map);
   4981 
   4982     /* Write new LT configuration in hardware. */
   4983     BCM_IF_ERROR_RETURN(soc_mem_write(unit, lt_config_mem,
   4984                 MEM_BLOCK_ANY, lt_id, &lt_config_entry));
   4985     return BCM_E_NONE;
   4986 }
   4987 
   4988 /*
   4989  * Function:
   4990  *     _field_hx5_ingress_lt_partition_prio_install
   4991  * Purpose:
   4992  *     Write logical table Partition priortiy information to hardware.
   4993  * Parameters:
   4994  *     unit     - (IN) BCM device number.
   4995  *     stage_fc - (IN) Field stage control structure.
   4996  *     fg       - (IN) Field group Structure.
   4997  * Returns:
   4998  *     BCM_E_XXX
   4999  */
   5000 STATIC int
   5001 _field_hx5_ingress_lt_partition_prio_install(int unit, _field_stage_t *stage_fc,
   5002                                             _field_group_t *fg)
   5003 {
   5004     soc_field_t field;              /* HW entry field.                  */
   5005     uint32 value;                   /* Entry field value.               */
   5006     int lt_idx;                     /* LT iterator.                     */
   5007     int slice;                      /* Slice iterator.                  */
   5008     uint32 lt_config_entry[SOC_MAX_MEM_FIELD_WORDS] = {0};
   5009                                     /* HW entry buffer.                 */
   5010     _field_lt_config_t *lt_info;    /* Logical table info.              */
   5011     int rv;                         /* Operation return status.         */
   5012     _field_control_t    *fc;        /* Field control structure.     */
   5013 
   5014     static const soc_field_t lt_part_pri[] = {
   5015         LOGICAL_PARTITION_PRIORITY_0f,
   5016         LOGICAL_PARTITION_PRIORITY_1f,
   5017         LOGICAL_PARTITION_PRIORITY_2f,
   5018         LOGICAL_PARTITION_PRIORITY_3f,
   5019         LOGICAL_PARTITION_PRIORITY_4f,
   5020         LOGICAL_PARTITION_PRIORITY_5f,
   5021         LOGICAL_PARTITION_PRIORITY_6f,
   5022         LOGICAL_PARTITION_PRIORITY_7f,
   5023         LOGICAL_PARTITION_PRIORITY_8f,
   5024         LOGICAL_PARTITION_PRIORITY_9f,
   5025         LOGICAL_PARTITION_PRIORITY_10f,
   5026         LOGICAL_PARTITION_PRIORITY_11f,
   5027         LOGICAL_PARTITION_PRIORITY_12f,
   5028         LOGICAL_PARTITION_PRIORITY_13f,
   5029         LOGICAL_PARTITION_PRIORITY_14f,
   5030         LOGICAL_PARTITION_PRIORITY_15f,
   5031         LOGICAL_PARTITION_PRIORITY_16f,
   5032         LOGICAL_PARTITION_PRIORITY_17f
   5033 
   5034     };
   5035 
   5036     static soc_mem_t lt_config_mem = IFP_LOGICAL_TABLE_CONFIGm;
   5037 
   5038     /* Input parameters check. */
   5039     if (NULL == fg || NULL == stage_fc) {
   5040         return (BCM_E_PARAM);
   5041     }
   5042 
   5043     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   5044 
   5045     /* Program Logical Tables configuration in hardware. */
   5046     for (lt_idx = 0; lt_idx < stage_fc->num_logical_tables; lt_idx++) {
   5047 
   5048         /* Get logical table info for the default FP instance. */
   5049         lt_info = fc->lt_info[fg->instance][lt_idx];
   5050 
   5051         rv = soc_mem_read(unit, lt_config_mem, MEM_BLOCK_ANY,
   5052                           lt_idx, &lt_config_entry);
   5053         BCM_IF_ERROR_RETURN(rv);
   5054 
   5055         /*
   5056          * Construct the LT Partition Map and Partition
   5057          * Priority entry for the LT.
   5058          */
   5059         for (slice = 0; slice < stage_fc->tcam_slices; slice++) {
   5060             field = lt_part_pri[slice];
   5061             value = lt_info->lt_part_pri[slice];
   5062             soc_mem_field32_set(unit, lt_config_mem,
   5063                     &lt_config_entry, field, value);
   5064         }
   5065 
   5066         soc_mem_field32_set(unit, lt_config_mem, &lt_config_entry,
   5067                 LOGICAL_PARTITION_MAPf, lt_info->lt_part_map);
   5068 
   5069         /* Write new LT configuration in hardware. */
   5070         BCM_IF_ERROR_RETURN(soc_mem_write(unit, lt_config_mem,
   5071                     MEM_BLOCK_ANY, lt_idx, &lt_config_entry));
   5072     }
   5073     return BCM_E_NONE;
   5074 }
   5075 #endif
   5076 
   5077 /*
   5078  * Function:
   5079  *     _field_th_ingress_lt_partition_prio_write
   5080  * Purpose:
   5081  *     Write LT Partition priortiy for the given LT ID and Slice to HW.
   5082  * Parameters:
   5083  *     unit     - (IN) BCM device number.
   5084  *     stage_fc - (IN) Field stage control structure.
   5085  *     fg       - (IN) Field group Structure.
   5086  * Returns:
   5087  *     BCM_E_XXX
   5088  * Note: slice == -1 implies configure partition priority for all slices
   5089  *       for the given lt_id.
   5090  */
   5091 
   5092 int
   5093 _bcm_field_th_ingress_lt_partition_prio_write(int unit,
   5094                                               _field_stage_t *stage_fc,
   5095                                               _field_group_t *fg, int lt_id,
   5096                                               int slice)
   5097 {
   5098     int rv;                         /* Operation return status.         */
   5099     int slice_num;                  /* Slice number.                    */
   5100     int value;                      /* Partition Prio value.            */
   5101     uint64 lt_config_entry;         /* HW entry buffer.                 */
   5102     _field_lt_config_t *lt_info;    /* Logical table info.              */
   5103     soc_field_t field;              /* HW entry field.                  */
   5104     _field_control_t    *fc;        /* Field control structure.     */
   5105 
   5106     static const soc_field_t lt_part_pri[] = {
   5107         LOGICAL_PARTITION_PRIORITY_0f,
   5108         LOGICAL_PARTITION_PRIORITY_1f,
   5109         LOGICAL_PARTITION_PRIORITY_2f,
   5110         LOGICAL_PARTITION_PRIORITY_3f,
   5111         LOGICAL_PARTITION_PRIORITY_4f,
   5112         LOGICAL_PARTITION_PRIORITY_5f,
   5113         LOGICAL_PARTITION_PRIORITY_6f,
   5114         LOGICAL_PARTITION_PRIORITY_7f,
   5115         LOGICAL_PARTITION_PRIORITY_8f,
   5116         LOGICAL_PARTITION_PRIORITY_9f,
   5117         LOGICAL_PARTITION_PRIORITY_10f,
   5118         LOGICAL_PARTITION_PRIORITY_11f
   5119     };
   5120 
   5121     static soc_reg_t lt_config_reg;
   5122 
   5123     /* Input parameters check. */
   5124     if (NULL == fg || NULL == stage_fc) {
   5125         return (BCM_E_PARAM);
   5126     }
   5127 
   5128     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   5129 
   5130     /* Retrieve the Pipe instance. */
   5131     if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) {
   5132 
   5133         BCM_IF_ERROR_RETURN(_bcm_field_reg_instance_get(unit,
   5134                                       IFP_LOGICAL_TABLE_CONFIGr,
   5135                                       _FP_GLOBAL_INST,
   5136                                       &lt_config_reg));
   5137     } else {
   5138         BCM_IF_ERROR_RETURN(_bcm_field_reg_instance_get(unit,
   5139                                       IFP_LOGICAL_TABLE_CONFIGr,
   5140                                       fg->instance,
   5141                                       &lt_config_reg));
   5142     }
   5143 
   5144     rv = soc_reg_get(unit, lt_config_reg, REG_PORT_ANY,
   5145             lt_id, &lt_config_entry);
   5146     BCM_IF_ERROR_RETURN(rv);
   5147 
   5148     /* Get logical table info for the default FP instance. */
   5149     lt_info = fc->lt_info[fg->instance][lt_id];
   5150     for (slice_num = 0; slice_num < stage_fc->tcam_slices; slice_num++) {
   5151         if ((slice != -1) && (slice_num != slice)) {
   5152             continue;
   5153         }
   5154         field = lt_part_pri[slice_num];
   5155         value = lt_info->lt_part_pri[slice_num];
   5156         soc_reg64_field32_set(unit, lt_config_reg,
   5157                 &lt_config_entry, field, value);
   5158     }
   5159     soc_reg64_field32_set(unit, lt_config_reg, &lt_config_entry,
   5160             LOGICAL_PARTITION_MAPf, lt_info->lt_part_map);
   5161 
   5162     /* Write new LT configuration in hardware. */
   5163     BCM_IF_ERROR_RETURN(soc_reg_set(unit, lt_config_reg,
   5164                 REG_PORT_ANY, lt_id, lt_config_entry));
   5165     return BCM_E_NONE;
   5166 }
   5167 
   5168 /*
   5169  * Function:
   5170  *     _field_th_ingress_lt_partition_prio_install
   5171  * Purpose:
   5172  *     Write logical table Partition priortiy information to hardware.
   5173  * Parameters:
   5174  *     unit     - (IN) BCM device number.
   5175  *     stage_fc - (IN) Field stage control structure.
   5176  *     fg       - (IN) Field group Structure.
   5177  * Returns:
   5178  *     BCM_E_XXX
   5179  */
   5180 STATIC int
   5181 _field_th_ingress_lt_partition_prio_install(int unit, _field_stage_t *stage_fc,
   5182                                             _field_group_t *fg)
   5183 {
   5184     soc_field_t field;              /* HW entry field.                  */
   5185     uint32 value;                   /* Entry field value.               */
   5186     int lt_idx;                     /* LT iterator.                     */
   5187     int slice;                      /* Slice iterator.                  */
   5188     uint64 lt_config_entry;         /* HW entry buffer.                 */
   5189     _field_lt_config_t *lt_info;    /* Logical table info.              */
   5190     int rv;                         /* Operation return status.         */
   5191     _field_control_t    *fc;        /* Field control structure.     */
   5192 
   5193     static const soc_field_t lt_part_pri[] = {
   5194         LOGICAL_PARTITION_PRIORITY_0f,
   5195         LOGICAL_PARTITION_PRIORITY_1f,
   5196         LOGICAL_PARTITION_PRIORITY_2f,
   5197         LOGICAL_PARTITION_PRIORITY_3f,
   5198         LOGICAL_PARTITION_PRIORITY_4f,
   5199         LOGICAL_PARTITION_PRIORITY_5f,
   5200         LOGICAL_PARTITION_PRIORITY_6f,
   5201         LOGICAL_PARTITION_PRIORITY_7f,
   5202         LOGICAL_PARTITION_PRIORITY_8f,
   5203         LOGICAL_PARTITION_PRIORITY_9f,
   5204         LOGICAL_PARTITION_PRIORITY_10f,
   5205         LOGICAL_PARTITION_PRIORITY_11f
   5206     };
   5207 
   5208     static soc_reg_t lt_config_reg;
   5209 
   5210     /* Input parameters check. */
   5211     if (NULL == fg || NULL == stage_fc) {
   5212         return (BCM_E_PARAM);
   5213     }
   5214 
   5215     /* Skip for Flowtracker */
   5216 #if defined(BCM_FLOWTRACKER_SUPPORT)
   5217     if (fg->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) {
   5218         return BCM_E_NONE;
   5219     }
   5220 #endif
   5221 
   5222     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   5223 
   5224     /* Retrieve the Pipe instance. */
   5225     if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) {
   5226         BCM_IF_ERROR_RETURN(_bcm_field_reg_instance_get(unit,
   5227                                       IFP_LOGICAL_TABLE_CONFIGr,
   5228                                       _FP_GLOBAL_INST,
   5229                                       &lt_config_reg));
   5230     } else {
   5231 
   5232         BCM_IF_ERROR_RETURN(_bcm_field_reg_instance_get(unit,
   5233                                       IFP_LOGICAL_TABLE_CONFIGr,
   5234                                       fg->instance,
   5235                                       &lt_config_reg));
   5236     }
   5237     /* Program Logical Tables configuration in hardware. */
   5238     for (lt_idx = 0; lt_idx < stage_fc->num_logical_tables; lt_idx++) {
   5239 
   5240         /* Get logical table info for the default FP instance. */
   5241         lt_info = fc->lt_info[fg->instance][lt_idx];
   5242 
   5243         rv = soc_reg_get(unit, lt_config_reg, REG_PORT_ANY,
   5244                 lt_idx, &lt_config_entry);
   5245         BCM_IF_ERROR_RETURN(rv);
   5246 
   5247         /*
   5248          * Construct the LT Partition Map and Partition
   5249          * Priority entry for the LT.
   5250          */
   5251         for (slice = 0; slice < stage_fc->tcam_slices; slice++) {
   5252             field = lt_part_pri[slice];
   5253             value = lt_info->lt_part_pri[slice];
   5254             soc_reg64_field32_set(unit, lt_config_reg,
   5255                     &lt_config_entry, field, value);
   5256         }
   5257         soc_reg64_field32_set(unit, lt_config_reg, &lt_config_entry,
   5258                 LOGICAL_PARTITION_MAPf, lt_info->lt_part_map);
   5259 
   5260         /* Write new LT configuration in hardware. */
   5261         BCM_IF_ERROR_RETURN(soc_reg_set(unit, lt_config_reg,
   5262                    REG_PORT_ANY, lt_idx, lt_config_entry));
   5263     }
   5264     return BCM_E_NONE;
   5265 }
   5266 
   5267 /*
   5268  * Function:
   5269  *     _bcm_field_th_ingress_logical_table_map_write
   5270  * Purpose:
   5271  *     Write logical table partition map information to hardware.
   5272  * Parameters:
   5273  *     unit     - (IN) BCM device number.
   5274  *     stage_fc - (IN) Field stage control structure.
   5275  *     fg       - (IN) Field group Structure.
   5276  * Returns:
   5277  *     BCM_E_XXX
   5278  */
   5279 int
   5280 _bcm_field_th_ingress_logical_table_map_write(int unit,
   5281                                               _field_stage_t *stage_fc,
   5282                                               _field_group_t *fg)
   5283 {
   5284     int rv;                         /* Operation return status.         */
   5285 
   5286     /* Input parameters check. */
   5287     if (NULL == fg || NULL == stage_fc) {
   5288         return (BCM_E_PARAM);
   5289     }
   5290 
   5291     if (fg->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) {
   5292         return BCM_E_NONE;
   5293     }
   5294 
   5295     /* Install LT Action Priority. */
   5296     rv = _bcm_field_th_ingress_lt_action_prio_install(unit, stage_fc, fg);
   5297     if (BCM_FAILURE(rv)) {
   5298        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   5299                 "Error: LT Action Priority Install failed for group:%d\n\r"),
   5300                  fg->gid));
   5301        return rv;
   5302     }
   5303 
   5304     /* Install LT Partition Priority. */
   5305 #if defined (BCM_HELIX5_SUPPORT)
   5306     if (SOC_IS_HELIX5(unit)) {
   5307         rv = _field_hx5_ingress_lt_partition_prio_install(unit, stage_fc, fg);
   5308  
   5309     } else
   5310 #endif
   5311     {
   5312         rv = _field_th_ingress_lt_partition_prio_install(unit, stage_fc, fg);
   5313     }
   5314 
   5315     if (BCM_FAILURE(rv)) {
   5316        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   5317                 "Error: LT Partition Priority Install failed for group:%d\n\r"),
   5318                  fg->gid));
   5319        return rv;
   5320     }
   5321 
   5322     return BCM_E_NONE;
   5323 }
   5324 
   5325 /*
   5326  * Function:
   5327  *     _bcm_field_th_lt_part_prio_reset
   5328  * Purpose:
   5329  *     Reset the LT Partition Priority and also clear the
   5330  *     lt_map for the given slice.
   5331  * Parameters:
   5332  *     unit     - (IN) BCM device number.
   5333  *     stage_fc - (IN) Field stage control structure.
   5334  *     fg       - (IN) Field group Structure.
   5335  *     fs       - (IN) Field slice Structure.
   5336  * Returns:
   5337  *     BCM_E_XXX
   5338  */
   5339 int _bcm_field_th_lt_part_prio_reset(int unit, _field_stage_t *stage_fc,
   5340                                      _field_group_t *fg,
   5341                                      _field_slice_t *fs)
   5342 {
   5343     int              rv;
   5344     int              found = 0;
   5345     _field_slice_t   *fs_ptr;
   5346     _field_control_t *fc;           /* Field control structure. */
   5347 
   5348     /* Input parameters check. */
   5349     if (NULL == stage_fc || NULL == fg || NULL == fs) {
   5350         return (BCM_E_PARAM);
   5351     }
   5352 
   5353     if (NULL == fg->slices) {
   5354        return BCM_E_INTERNAL;
   5355     }
   5356 
   5357     /* Get field control structure. */
   5358     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   5359 
   5360     /* Clear Group's LT_ID bit in slice LT map. */
   5361     fs->lt_map &= ~(1 << fg->lt_id);
   5362 
   5363     /* Reset the LT Partition Priority. */
   5364     fc->lt_info[fg->instance][fg->lt_id]->lt_part_map &= ~(1 << fs->slice_number);
   5365     fc->lt_info[fg->instance][fg->lt_id]->lt_part_pri[fs->slice_number] = 0;
   5366 
   5367     /*
   5368      *  Parse the existing auto-expanded slices for the group
   5369      *  And updae the partition priority.
   5370     */
   5371     for (fs_ptr = fg->slices; fs_ptr != NULL; fs_ptr = fs_ptr->next) {
   5372         if (fs_ptr == fs) {
   5373            found = 1;
   5374            continue;
   5375         }
   5376 
   5377         if (found == 1) {
   5378             fc->lt_info[fg->instance][fg->lt_id]->lt_part_pri[fs_ptr->slice_number] += 1;
   5379         }
   5380     }
   5381 
   5382     /* Set the partition Priority. */
   5383 #if defined (BCM_HELIX5_SUPPORT)
   5384     if (SOC_IS_HELIX5(unit)) {
   5385         rv = _bcm_field_hx5_ingress_lt_partition_prio_write(unit, stage_fc, fg,
   5386                                                            fg->lt_id, -1);
   5387  
   5388     } else
   5389 #endif
   5390     {
   5391         rv = _bcm_field_th_ingress_lt_partition_prio_write(unit, stage_fc, fg,
   5392                                                            fg->lt_id, -1);
   5393     }
   5394 
   5395     if (BCM_FAILURE(rv)) {
   5396         LOG_ERROR(BSL_LS_BCM_FP,
   5397             (BSL_META_U(unit, "Error: LT Partition Reset failed for"
   5398              " group:%d lt_id:%d slice:%d\n\r"),
   5399              fg->gid, fg->lt_id, fs->slice_number));
   5400     }
   5401 
   5402     return rv;
   5403 }
   5404 
   5405 
   5406 /*
   5407  * Function:
   5408  *     _bcm_field_th_lt_part_prio_value_get
   5409  * Purpose:
   5410  *     Configure and return a LT Partition Priority for the given LT ID from a group.
   5411  * Parameters:
   5412  *     unit         - (IN)  BCM device number.
   5413  *     fg           - (IN)  Field group Structure.
   5414  *     lt_part_prio - (OUT) LT Partition priority value.
   5415  * Returns:
   5416  *     BCM_E_XXX
   5417  */
   5418 int _bcm_field_th_lt_part_prio_value_get(int unit, _field_group_t *fg,
   5419                                          int *lt_part_prio)
   5420 {
   5421     int            part_prio = 0;
   5422     _field_slice_t *group_fs;
   5423     _field_control_t  *fc;           /* Field control structure. */
   5424     _field_stage_t      *stage_fc;      /* Stage field control.         */
   5425 
   5426     /* Input parameters check. */
   5427     if (NULL == fg || NULL == lt_part_prio) {
   5428         return (BCM_E_PARAM);
   5429     }
   5430 
   5431     /* Get field control structure. */
   5432     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   5433 
   5434     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fg->stage_id,
   5435                 &stage_fc));
   5436 
   5437     /* Parse the existing auto-expanded slices for the group */
   5438     for (group_fs = fg->slices; group_fs != NULL; group_fs = group_fs->next) {
   5439         part_prio = fc->lt_info[fg->instance][fg->lt_id]->lt_part_pri[group_fs->slice_number];
   5440     }
   5441 
   5442     /* Assign the least priority to the latest slice. */
   5443     *lt_part_prio = part_prio - 1;
   5444     if (*lt_part_prio <= 0) {
   5445        return BCM_E_INTERNAL;
   5446     }
   5447 
   5448     return BCM_E_NONE;
   5449 }
   5450 
   5451 /*
   5452  * Function:
   5453  *     _bcm_field_th_presel_entry_hw_remove
   5454  * Purpose:
   5455  *     Remove Preselector Entries from hardware.
   5456  * Parameters:
   5457  *     unit     - (IN) BCM device number.
   5458  *     f_presel - (IN) Field Preselector Entries.
   5459  * Returns:
   5460  *     BCM_E_XXX
   5461  */
   5462 int
   5463 _bcm_field_th_presel_entry_hw_remove(int unit, _field_presel_entry_t *f_presel)
   5464 {
   5465     int                    parts_count = -1; /* Entry parts count.          */
   5466     int                    part;             /* Entry part.                 */
   5467     int                    tcam_idx;         /* LT TCAM entry index.        */
   5468     soc_mem_t              lt_tcam_mem;      /* LT TCAM Memory.             */
   5469     _field_stage_t        *stage_fc;         /* Field Stage Pointer.        */
   5470     _field_presel_entry_t *f_presel_p;       /* Presel Part entry.          */
   5471 
   5472    /* Input parameters check. */
   5473     if (NULL == f_presel) {
   5474         return (BCM_E_PARAM);
   5475     }
   5476 
   5477     if ((f_presel->flags & _FP_ENTRY_INSTALLED) == 0) {
   5478         /* Entry not installed in hardware. */
   5479         return (BCM_E_NONE);
   5480     }
   5481 
   5482     /* Get device stage control structure. */
   5483     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
   5484                             f_presel->group->stage_id, &stage_fc));
   5485 
   5486     /* Get number of entry parts using group flags. . */
   5487     BCM_IF_ERROR_RETURN(_bcm_field_th_entry_tcam_parts_count(unit,
   5488         f_presel->group->flags, &parts_count));
   5489 
   5490     /* Get TCAM view to be used for programming the hardware. */
   5491     if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) {
   5492         BCM_IF_ERROR_RETURN(_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc,
   5493                                                       f_presel->group->instance,
   5494                                                      _BCM_FIELD_MEM_TYPE_IFP_LT,
   5495                                         _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB,
   5496                                                            &lt_tcam_mem, NULL));
   5497     } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) {
   5498         BCM_IF_ERROR_RETURN(_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc,
   5499                                                       f_presel->group->instance,
   5500                                                       _BCM_FIELD_MEM_TYPE_EM_LT,
   5501                                         _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB,
   5502                                                            &lt_tcam_mem, NULL));
   5503 #if defined(BCM_FLOWTRACKER_SUPPORT)
   5504     } else if ((soc_feature(unit, soc_feature_field_flowtracker_support)) &&
   5505         (stage_fc->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER)) {
   5506         return _bcm_field_hx5_ft_lt_entry_hw_remove(unit, f_presel);
   5507 #endif
   5508     } else {
   5509         return (BCM_E_PARAM);
   5510     }
   5511 
   5512     /* Iterate over entry parts and remove the entry from HW. */
   5513     f_presel_p = f_presel;
   5514     for (part = 0; part < parts_count; part++) {
   5515         if (f_presel_p == NULL) {
   5516            break;
   5517         }
   5518 
   5519         /* Given entry part number, get the entry TCAM index. */
   5520         BCM_IF_ERROR_RETURN(_bcm_field_presel_entry_tcam_idx_get(unit,
   5521                             f_presel_p, f_presel_p->lt_fs, &tcam_idx));
   5522 
   5523         /* Clear TCAM entry in hardware at the supplied TCAM index. */
   5524         SOC_IF_ERROR_RETURN(soc_mem_write(unit, lt_tcam_mem, MEM_BLOCK_ALL,
   5525                          tcam_idx, soc_mem_entry_null(unit, lt_tcam_mem)));
   5526 
   5527         f_presel_p->flags |= _FP_ENTRY_DIRTY;
   5528         f_presel_p->flags &= ~(_FP_ENTRY_INSTALLED);
   5529         f_presel_p->flags &= ~(_FP_ENTRY_ENABLED);
   5530 
   5531         f_presel_p = f_presel_p->next;
   5532     }
   5533 
   5534     return (BCM_E_NONE);
   5535 }
   5536 
   5537 /* Function to disable the presel entries for a given group */
   5538 int
   5539 _bcm_field_th_group_presel_enable_set(int unit,
   5540                                       _field_stage_t *stage_fc,
   5541                                       _field_group_t *fg,
   5542                                       uint32 valid)
   5543 {
   5544     int rv, idx;
   5545     int                    tcam_idx;
   5546     soc_mem_t              lt_tcam_mem;
   5547     _field_lt_slice_t     *lt_part_fs;
   5548     _field_presel_entry_t *f_presel_p;
   5549     _field_presel_entry_t *f_presel;
   5550 
   5551     /* Input parameters check. */
   5552     if ((NULL == fg) || (NULL == stage_fc)) {
   5553         return (BCM_E_PARAM);
   5554     }
   5555 
   5556     /*
   5557      * Get TCAM view to be used for programming the hardware based on the group
   5558      * operational mode.
   5559      */
   5560     if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) {
   5561         rv = (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc,
   5562                                                      fg->instance,
   5563                                        _BCM_FIELD_MEM_TYPE_IFP_LT,
   5564                           _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB,
   5565                                              &lt_tcam_mem, NULL));
   5566         /*
   5567          * For TH2 and TD3, the IFP valid field is of 2 bits,
   5568          * hence the value 3 has to be set in case of enable
   5569          */
   5570         valid = (valid) ?
   5571                 ((soc_feature(unit, soc_feature_field_multi_pipe_enhanced) ||
   5572                   soc_feature(unit, soc_feature_td3_style_fp)) ? 3 : 1) : 0;
   5573     } else if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) {
   5574         rv = (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc,
   5575                                                      fg->instance,
   5576                                         _BCM_FIELD_MEM_TYPE_EM_LT,
   5577                           _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB,
   5578                                              &lt_tcam_mem, NULL));
   5579         /* TD3 EM valid field is of 2 bits */ 
   5580         valid = (valid) ?
   5581                 (soc_feature(unit, soc_feature_td3_style_fp) ? 3 : 1) : 0;
   5582     } else {
   5583         return (BCM_E_PARAM);
   5584     }
   5585     BCM_IF_ERROR_RETURN(rv);
   5586 
   5587     f_presel = fg->presel_ent_arr[0];
   5588     if (f_presel == NULL) {
   5589        return BCM_E_INTERNAL;
   5590     }
   5591 
   5592     /* Update Presel LT Slices. */
   5593     for (idx = 0; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) {
   5594         if (fg->presel_ent_arr[idx] != NULL) {
   5595            f_presel = fg->presel_ent_arr[idx];
   5596         } else {
   5597            continue;
   5598         }
   5599 
   5600         f_presel_p = f_presel;
   5601         for (; f_presel_p != NULL; f_presel_p = f_presel_p->next) {
   5602             lt_part_fs = f_presel_p->lt_fs;
   5603             for (; lt_part_fs != NULL; lt_part_fs = lt_part_fs->next) {
   5604                  rv = _bcm_field_presel_entry_tcam_idx_get(unit, f_presel_p,
   5605                                                            lt_part_fs,
   5606                                                            &tcam_idx);
   5607                  BCM_IF_ERROR_RETURN(rv);
   5608                  /* Install the LT Entry in HW. */
   5609                  rv = _bcm_field_th_lt_entry_hw_install(unit, lt_tcam_mem,
   5610                                                    tcam_idx,
   5611                                                    NULL, NULL, NULL,
   5612                                                    valid);
   5613                  BCM_IF_ERROR_RETURN(rv);
   5614             }
   5615         }
   5616     }
   5617 
   5618     /* Enable/Disable group flags. */
   5619     if (valid) {
   5620         fg->flags |= _FP_GROUP_LOOKUP_ENABLED;
   5621     } else {
   5622         fg->flags &= ~_FP_GROUP_LOOKUP_ENABLED;
   5623     }
   5624 
   5625     return BCM_E_NONE;
   5626 }
   5627 
   5628 
   5629 
   5630 /*
   5631  * Function:
   5632  *      _bcm_field_th_source_class_mode_set
   5633  * Purpose:
   5634  *      Retrieve Field Processor Source Class operational mode
   5635  *      per-CAP stage.
   5636  * Parameters:
   5637  *      unit    - (IN)  BCM Device number.
   5638  *      stage   - (IN)  Field Stage enum value.
   5639  *      pbmp    - (IN)  Device Port Bitmap value
   5640  *      mode    - (IN)  Reference to Field Source Class Operational
   5641  *                      Mode enum value.
   5642  * Returns:
   5643  *      BCM_E_XXX
   5644  * Notes:
   5645  *      Valid "stage" input parameter values supported by
   5646  *      this API are:
   5647  * 	            "bcmFieldStageIngress"
   5648  *              "bcmFieldStageIngressExactMatch"
   5649  */
   5650     int
   5651 _bcm_field_th_source_class_mode_set(int unit,
   5652                                     bcm_field_stage_t stage,
   5653                                     bcm_pbmp_t pbmp,
   5654                                     bcm_field_src_class_mode_t mode)
   5655 {
   5656     _field_stage_t                *stage_fc; /* Stage field control structure. */
   5657     _field_stage_id_t             stage_id;  /* Pipeline stage id */
   5658     _field_control_t              *fc;
   5659     _field_presel_entry_t         *f_presel = NULL; /* Internal Presel descriptor */
   5660     _field_presel_info_t          *presel_info;     /* Presel information structure */
   5661     bcm_field_presel_t            presel_idx = 0;
   5662     bcm_field_qualify_t           stage_qual;
   5663     bcm_field_group_oper_mode_t   group_mode;
   5664     uint8                         pipe_idx = 0;
   5665     bcm_pbmp_t                    pbmp_temp;
   5666     soc_reg_t                     lt_select_cfg_reg = INVALIDr;
   5667     bcm_pbmp_t                    all_pbmp;   /* Group port bitmap.           */
   5668 
   5669     if (mode >= bcmFieldSrcClassModeCount) {
   5670         return (BCM_E_PARAM);
   5671     }
   5672 
   5673     switch (stage) {
   5674         case bcmFieldStageIngress:
   5675              lt_select_cfg_reg = IFP_LOGICAL_TABLE_SELECT_CONFIGr;
   5676              stage_id = _BCM_FIELD_STAGE_INGRESS;
   5677              stage_qual = bcmFieldQualifyStageIngress;
   5678              break;
   5679         case bcmFieldStageIngressExactMatch:
   5680              stage_id = _BCM_FIELD_STAGE_EXACTMATCH;
   5681              stage_qual = bcmFieldQualifyStageIngressExactMatch;
   5682              lt_select_cfg_reg = EXACT_MATCH_LOGICAL_TABLE_SELECT_CONFIGr;
   5683              break;
   5684 #if defined (BCM_FLOWTRACKER_SUPPORT)
   5685         case bcmFieldStageIngressFlowtracker:
   5686              stage_id = _BCM_FIELD_STAGE_FLOWTRACKER;
   5687              stage_qual = bcmFieldQualifyStageIngressFlowtracker;
   5688              lt_select_cfg_reg = BROADSCAN_LOGICAL_TABLE_SELECT_CONFIGr;
   5689              break;
   5690 #endif
   5691         default:
   5692             return BCM_E_PARAM;
   5693     }
   5694 
   5695 
   5696 
   5697     /* Verifiy PBMP based on group mode and port config */
   5698     /* Get group mode */
   5699     if (soc_feature(unit, soc_feature_field_single_pipe_support)) {
   5700         group_mode = bcmFieldGroupOperModeGlobal;
   5701     } else {
   5702         BCM_IF_ERROR_RETURN(bcm_esw_field_group_oper_mode_get(unit,
   5703                     stage_qual, &group_mode));
   5704     }
   5705 
   5706     /* Read device port configuration. */ 
   5707     BCM_PBMP_CLEAR(all_pbmp);
   5708     BCM_IF_ERROR_RETURN(_bcm_field_valid_pbmp_get(unit, &all_pbmp));
   5709 
   5710     if (group_mode == bcmFieldGroupOperModeGlobal) {
   5711         /* Pbmp should match all the valid ports */
   5712         if (!BCM_PBMP_EQ(all_pbmp, pbmp)) {
   5713             return BCM_E_PARAM;
   5714         }
   5715     } else if (group_mode == bcmFieldGroupOperModePipeLocal) {
   5716         /* Pbmp provided should be belong to only one pipe */
   5717         for (pipe_idx = 0; pipe_idx < BCM_PIPES_MAX ; pipe_idx++) {
   5718             BCM_PBMP_CLEAR(pbmp_temp);
   5719             BCM_PBMP_ASSIGN(pbmp_temp, PBMP_PIPE(unit, pipe_idx));
   5720             SOC_PBMP_REMOVE(pbmp_temp, PBMP_LB(unit));
   5721             SOC_PBMP_REMOVE(pbmp_temp, PBMP_RDB_ALL(unit));
   5722             SOC_PBMP_REMOVE(pbmp_temp, PBMP_FAE_ALL(unit));
   5723             if (BCM_PBMP_EQ(pbmp_temp, pbmp)) {
   5724                 break;
   5725             }
   5726         }
   5727 
   5728         /* Pbmp doesn't match any of the pipes */
   5729         if (pipe_idx == BCM_PIPES_MAX) {
   5730             return BCM_E_PARAM;
   5731         }
   5732 
   5733         BCM_IF_ERROR_RETURN(_bcm_field_reg_instance_get(unit,
   5734                                             lt_select_cfg_reg,
   5735                                             pipe_idx,
   5736                                             &lt_select_cfg_reg));
   5737     } else {
   5738         return BCM_E_INTERNAL;
   5739     }
   5740 
   5741     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, stage_id, &stage_fc));
   5742 
   5743     /* Mode can't be changed unless no entry is configured for that stage */
   5744     if(mode != stage_fc->field_src_class_mode[pipe_idx]) {
   5745 
   5746         BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   5747 
   5748         /* Get the preselector information */
   5749         presel_info = fc->presel_info;
   5750         if (presel_info == NULL) {
   5751             LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   5752                             "ERROR: Field control for Presel Information returns NULL.\n\r")));
   5753             return BCM_E_INTERNAL;
   5754         }
   5755 
   5756         /* Loop through all the presel id to check if Mixed src class was configured
   5757          * for any entry belonging to this stage */
   5758         for (presel_idx = 0 ; presel_idx < presel_info->presel_limit; presel_idx++) {
   5759             if (BCM_FIELD_PRESEL_TEST(presel_info->presel_set, presel_idx)) {
   5760                 /* Find preselector descriptor */
   5761                 BCM_IF_ERROR_RETURN
   5762                     (_bcm_field_presel_entry_get(unit, presel_idx, &f_presel));
   5763 
   5764                 /* Preselecor attached to ingress or extact match stage
   5765                  * if MIXED SRC FLAG is set return error */
   5766                 if (BCM_FIELD_QSET_TEST(f_presel->p_qset, stage_qual) &&
   5767                         BCM_PBMP_EQ(f_presel->mixed_src_class_pbmp, pbmp) &&
   5768                         (f_presel->flags & _FP_ENTRY_MIXED_SRC_CLASS_QUALIFIED)) {
   5769                     return BCM_E_PARAM;
   5770                 }
   5771             }
   5772         }
   5773 
   5774         stage_fc->field_src_class_mode[pipe_idx] = mode;
   5775         /* Write to HW */
   5776         if ((lt_select_cfg_reg != INVALIDr) &&
   5777              SOC_REG_FIELD_VALID(unit, lt_select_cfg_reg, SOURCE_CLASS_MODEf)) {
   5778             BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit, lt_select_cfg_reg,
   5779                         REG_PORT_ANY,
   5780                         SOURCE_CLASS_MODEf,
   5781                         mode));
   5782         } else {
   5783             return BCM_E_INTERNAL;
   5784         }
   5785     }
   5786 
   5787     return BCM_E_NONE;
   5788 }
   5789 
   5790 /*
   5791  * Function:
   5792  *      _bcm_field_th_source_class_mode_get
   5793  * Purpose:
   5794  *      Retrieve Field Processor Source Class operational mode
   5795  *      per-CAP stage.
   5796  * Parameters:
   5797  *      unit    - (IN)  BCM Device number.
   5798  *      stage   - (IN)  Field Stage enum value.
   5799  *      pbmp    - (IN)  Device Port Bitmap value
   5800  *      mode    - (OUT) Reference to Field Source Class Operational
   5801  *                      Mode enum value.
   5802  * Returns:
   5803  *      BCM_E_XXX
   5804  * Notes:
   5805  *      Valid "stage" input parameter values supported by
   5806  *      this API are:
   5807  * 	            "bcmFieldStageIngress"
   5808  *              "bcmFieldStageIngressExactMatch"
   5809  *              "bcmFieldStageIngressFlowtracker"
   5810  */
   5811     int
   5812 _bcm_field_th_source_class_mode_get(int unit,
   5813                                     bcm_field_stage_t stage,
   5814                                     bcm_pbmp_t pbmp,
   5815                                     bcm_field_src_class_mode_t *mode)
   5816 {
   5817     _field_stage_t     *stage_fc; /* Stage field control structure. */
   5818     _field_stage_id_t  stage_id;  /* Pipeline stage id */
   5819     bcm_field_qualify_t           stage_qual;
   5820     bcm_field_group_oper_mode_t   group_mode;
   5821     uint8                         pipe_idx = 0;
   5822     bcm_pbmp_t                    pbmp_temp;
   5823     bcm_pbmp_t                    all_pbmp;   /* Group port bitmap.           */
   5824 
   5825     /* Applicable for Ingress and ExtactMatch only */
   5826     if ((stage != bcmFieldStageIngress) &&
   5827             (stage != bcmFieldStageIngressExactMatch) &&
   5828             (stage != bcmFieldStageIngressFlowtracker)) {
   5829         return (BCM_E_PARAM);
   5830     }
   5831 
   5832     if (stage == bcmFieldStageIngress) {
   5833         stage_id = _BCM_FIELD_STAGE_INGRESS;
   5834         stage_qual = bcmFieldQualifyStageIngress;
   5835     } else if (stage == bcmFieldStageIngressExactMatch) {
   5836         stage_id = _BCM_FIELD_STAGE_EXACTMATCH;
   5837         stage_qual = bcmFieldQualifyStageIngressExactMatch;
   5838     } else { /* bcmFieldStageIngressFlowtracker */
   5839         stage_id = _BCM_FIELD_STAGE_FLOWTRACKER;
   5840         stage_qual = bcmFieldQualifyStageIngressFlowtracker;
   5841     }
   5842 
   5843     /* Verifiy PBMP based on group mode and port config */
   5844     /* Get group mode */
   5845     if (soc_feature(unit, soc_feature_field_single_pipe_support)) {
   5846         group_mode = bcmFieldGroupOperModeGlobal;
   5847     } else {
   5848         BCM_IF_ERROR_RETURN(bcm_esw_field_group_oper_mode_get(unit,
   5849                     stage_qual, &group_mode));
   5850     }
   5851 
   5852     /* Read device port configuration. */ 
   5853     BCM_PBMP_CLEAR(all_pbmp);
   5854     BCM_IF_ERROR_RETURN(_bcm_field_valid_pbmp_get(unit, &all_pbmp));
   5855 
   5856     if (group_mode == bcmFieldGroupOperModeGlobal) {
   5857         /* Pbmp should match all the valid ports */
   5858         if (!BCM_PBMP_EQ(all_pbmp, pbmp)) {
   5859             return BCM_E_PARAM;
   5860         }
   5861     } else if (group_mode == bcmFieldGroupOperModePipeLocal) {
   5862         /* Pbmp provided should be belong to only one pipe */
   5863         for (pipe_idx = 0; pipe_idx < BCM_PIPES_MAX ; pipe_idx++) {
   5864             BCM_PBMP_CLEAR(pbmp_temp);
   5865             BCM_PBMP_ASSIGN(pbmp_temp, PBMP_PIPE(unit, pipe_idx));
   5866             SOC_PBMP_REMOVE(pbmp_temp, PBMP_LB(unit));
   5867             SOC_PBMP_REMOVE(pbmp_temp, PBMP_RDB_ALL(unit));
   5868             SOC_PBMP_REMOVE(pbmp_temp, PBMP_FAE_ALL(unit));
   5869             if (BCM_PBMP_EQ(pbmp_temp, pbmp)) {
   5870                 break;
   5871             }
   5872         }
   5873 
   5874         /* Pbmp doesn't match any of the pipes */
   5875         if (pipe_idx == BCM_PIPES_MAX) {
   5876             return BCM_E_PARAM;
   5877         }
   5878     } else {
   5879         return BCM_E_INTERNAL;
   5880     }
   5881 
   5882     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, stage_id, &stage_fc));
   5883 
   5884     *mode = stage_fc->field_src_class_mode[pipe_idx];
   5885 
   5886     return BCM_E_NONE;
   5887 }
   5888 
   5889 /*
   5890  * Function:
   5891  *      _bcm_field_th_qualify_MixedSrcClassId
   5892  * Purpose:
   5893  *     Add a Mixed Source Class Id field qualification to a field entry.
   5894  * Parameters:
   5895  *      unit  - (IN) Unit number.
   5896  *      entry - (IN) Field Entry id.
   5897  *      pbmp  - (IN) Device Port Bitmap value
   5898  *      data  - (IN) Mixed Source Class Id.
   5899  *      mask  - (IN) Mixed Source Class Id mask.
   5900  * Returns:
   5901  *      BCM_E_XXX
   5902  * Notes:
   5903  */
   5904     int
   5905 _bcm_field_th_qualify_MixedSrcClassId(int unit,
   5906                                       bcm_field_entry_t entry,
   5907                                       bcm_pbmp_t pbmp,
   5908                                       bcm_field_src_class_t data,
   5909                                       bcm_field_src_class_t mask)
   5910 {
   5911     bcm_field_presel_t            presel;             /* Presel id. */
   5912     _field_presel_entry_t         *f_presel = NULL;   /* Presel Entry descriptor. */
   5913     _field_stage_id_t             stage_id;
   5914     _field_stage_t                *stage_fc;
   5915     uint32                        hw_data;            /* HW data match criteria.  */
   5916     uint32                        hw_mask;            /* HW data mask.            */
   5917     int                           rv = BCM_E_UNAVAIL; /* Operation return status. */
   5918     bcm_field_qualify_t           stage_qual;
   5919     bcm_field_group_oper_mode_t   group_mode;
   5920     uint8                         pipe_idx = 0;
   5921     bcm_pbmp_t                    pbmp_temp;
   5922     bcm_pbmp_t                    all_pbmp;   /* Group port bitmap.           */
   5923 
   5924     if (!(soc_feature(unit, soc_feature_field_preselector_support) &&
   5925                 (_BCM_FIELD_IS_PRESEL_ENTRY(entry) == TRUE))) {
   5926         return (BCM_E_PARAM);
   5927     }
   5928 
   5929     BCM_IF_ERROR_RETURN(_bcm_field_entry_presel_resolve(unit,
   5930                 entry, &presel, &f_presel));
   5931 
   5932     /* Mixed source class is applicable only
   5933      * for Ingress, extact match and flowtracker stages */
   5934     if (BCM_FIELD_QSET_TEST(f_presel->p_qset,
   5935                 bcmFieldQualifyStageIngress)) {
   5936         stage_id = _BCM_FIELD_STAGE_INGRESS;
   5937         stage_qual = bcmFieldQualifyStageIngress;
   5938     } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset,
   5939                 bcmFieldQualifyStageIngressExactMatch)) {
   5940         stage_id = _BCM_FIELD_STAGE_EXACTMATCH;
   5941         stage_qual = bcmFieldQualifyStageIngressExactMatch;
   5942 #if defined(BCM_FLOWTRACKER_SUPPORT)
   5943     } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset,
   5944                 bcmFieldQualifyStageIngressFlowtracker)) {
   5945         stage_id = _BCM_FIELD_STAGE_FLOWTRACKER;
   5946         stage_qual = bcmFieldQualifyStageIngressFlowtracker;
   5947 #endif
   5948     } else {
   5949         return (BCM_E_PARAM);
   5950     }
   5951 
   5952     /* Verifiy PBMP based on group mode and port config */
   5953     /* Get group mode */
   5954     if (soc_feature(unit, soc_feature_field_single_pipe_support)) {
   5955         group_mode = bcmFieldGroupOperModeGlobal;
   5956     } else {
   5957         BCM_IF_ERROR_RETURN(bcm_esw_field_group_oper_mode_get(unit,
   5958                     stage_qual, &group_mode));
   5959     }
   5960 
   5961     /* Read device port configuration. */ 
   5962     BCM_PBMP_CLEAR(all_pbmp);
   5963     BCM_IF_ERROR_RETURN(_bcm_field_valid_pbmp_get(unit, &all_pbmp));
   5964 
   5965     if (group_mode == bcmFieldGroupOperModeGlobal) {
   5966         /* Pbmp should match all the valid ports */
   5967         if (!BCM_PBMP_EQ(all_pbmp, pbmp)) {
   5968             return BCM_E_PARAM;
   5969         }
   5970     } else if (group_mode == bcmFieldGroupOperModePipeLocal) {
   5971         /* Pbmp provided should be belong to only one pipe */
   5972         for (pipe_idx = 0; pipe_idx < BCM_PIPES_MAX ; pipe_idx++) {
   5973             BCM_PBMP_CLEAR(pbmp_temp);
   5974             BCM_PBMP_ASSIGN(pbmp_temp, PBMP_PIPE(unit, pipe_idx));
   5975 
   5976             SOC_PBMP_REMOVE(pbmp_temp, PBMP_LB(unit));
   5977             SOC_PBMP_REMOVE(pbmp_temp, PBMP_RDB_ALL(unit));
   5978             SOC_PBMP_REMOVE(pbmp_temp, PBMP_FAE_ALL(unit));
   5979             if (BCM_PBMP_EQ(pbmp_temp, pbmp)) {
   5980                 break;
   5981             }
   5982         }
   5983 
   5984         /* Pbmp doesn't match any of the pipes */
   5985         if (pipe_idx == BCM_PIPES_MAX) {
   5986             return BCM_E_PARAM;
   5987         }
   5988     } else {
   5989         return BCM_E_INTERNAL;
   5990     }
   5991 
   5992     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, stage_id, &stage_fc));
   5993     switch (stage_fc->field_src_class_mode[pipe_idx]) {
   5994         case bcmFieldSrcClassModeDefault:
   5995             if (soc_feature(unit, soc_feature_th3_style_fp)) {
   5996                 hw_data = (uint32)((uint32)((data.intf_class_l2 & 0xF) << 28))
   5997                     | ((data.src_class_field & 0x3) << 26)
   5998                     | ((data.dst_class_field & 0x3FF) << 16)
   5999                     | ((data.udf_class & 0xFF) << 8)
   6000                     | (data.intf_class_port & 0xFF);
   6001 
   6002                 hw_mask = (uint32)((uint32)((mask.intf_class_l2 & 0xF) << 28))
   6003                     | ((mask.src_class_field & 0x3) << 26)
   6004                     | ((mask.dst_class_field & 0x3FF) << 16)
   6005                     | ((mask.udf_class & 0xFF) << 8)
   6006                     | (mask.intf_class_port & 0xFF);
   6007             } else {
   6008                 hw_data = (uint32)((uint32)(
   6009                     (data.src_class_field & 0x3) << 30))
   6010                     | ((data.dst_class_field & 0x3FF) << 20)
   6011                     | ((data.udf_class & 0xFF) << 12)
   6012                     | ((data.intf_class_port & 0xFF) << 4)
   6013                     | (data.intf_class_l2 & 0xF);
   6014 
   6015                 hw_mask = (uint32)((uint32)(
   6016                     (mask.src_class_field & 0x3) << 30 ))
   6017                     | ((mask.dst_class_field & 0x3FF) << 20)
   6018                     | ((mask.udf_class & 0xFF) << 12)
   6019                     | ((mask.intf_class_port & 0xFF) << 4)
   6020                     | (mask.intf_class_l2 & 0xF);
   6021             }
   6022             break;
   6023         case bcmFieldSrcClassModeSDN:
   6024             if (soc_feature(unit, soc_feature_th3_style_fp)) {
   6025                 hw_data = (uint32)((uint32)((data.intf_class_l2 & 0xF) << 28))
   6026                     | ((data.src_class_field & 0x3) << 26)
   6027                     | ((data.dst_class_field & 0x3FF) << 16)
   6028                     | ((data.udf_class & 0xF) << 12)
   6029                     | ((data.intf_class_port & 0xF) << 4)
   6030                     | (data.intf_class_l3 & 0xF);
   6031 
   6032                 hw_mask = (uint32)((uint32)((mask.intf_class_l2 & 0xF) << 28))
   6033                     | ((mask.src_class_field & 0x3) << 26)
   6034                     | ((mask.dst_class_field & 0x3FF) << 16)
   6035                     | ((mask.udf_class & 0xF) << 12)
   6036                     | ((mask.intf_class_port & 0xF) << 4)
   6037                     | (mask.intf_class_l3 & 0xF);
   6038             } else {
   6039                 hw_data = (uint32)((uint32)(
   6040                     (data.src_class_field & 0x3) << 30))
   6041                     | ((data.dst_class_field & 0x3FF) << 20)
   6042                     | ((data.udf_class & 0xF) << 16)
   6043                     | ((data.intf_class_port & 0xF) << 12)
   6044                     | ((data.intf_class_l2 & 0xF) << 8)
   6045                     | ((data.intf_class_vport & 0xF) << 4)
   6046                     | (data.intf_class_l3 & 0xF);
   6047 
   6048                 hw_mask = (uint32)((uint32)(
   6049                     (mask.src_class_field & 0x3) << 30))
   6050                     | ((mask.dst_class_field & 0x3FF) << 20)
   6051                     | ((mask.udf_class & 0xF) << 16)
   6052                     | ((mask.intf_class_port & 0xF) << 12)
   6053                     | ((mask.intf_class_l2 & 0xF) << 8)
   6054                     | ((mask.intf_class_vport & 0xF) << 4)
   6055                     | (mask.intf_class_l3 & 0xF);
   6056             }
   6057             break;
   6058         case bcmFieldSrcClassModeBalanced:
   6059             if (soc_feature(unit, soc_feature_th3_style_fp)) {
   6060                 hw_data = (uint32)((uint32)((data.intf_class_l2 & 0xF) << 28))
   6061                     | ((data.dst_class_field & 0xFF) << 20)
   6062                     | ((data.udf_class & 0xF) << 16)
   6063                     | ((data.intf_class_port & 0xFF) << 4)
   6064                     | (data.intf_class_l3 & 0xF);
   6065                 hw_mask = (uint32)((uint32)((mask.intf_class_l2 & 0xF) << 28))
   6066                     | ((mask.dst_class_field & 0xFF) << 20)
   6067                     | ((mask.udf_class & 0xF) << 16)
   6068                     | ((mask.intf_class_port & 0xFF) << 4)
   6069                     | (mask.intf_class_l3 & 0xF);
   6070             } else {
   6071                 hw_data = (uint32)((uint32)(
   6072                     (data.dst_class_field & 0xFF) << 24))
   6073                     | ((data.udf_class & 0xF) << 20)
   6074                     | ((data.intf_class_port & 0xFF) << 12)
   6075                     | ((data.intf_class_l2 & 0xF) << 8)
   6076                     | ((data.intf_class_vport & 0xF) << 4)
   6077                     | (data.intf_class_l3 & 0xF);
   6078 
   6079                 hw_mask = (uint32)((uint32)(
   6080                     (mask.dst_class_field & 0xFF) << 24))
   6081                     | ((mask.udf_class & 0xF) << 20)
   6082                     | ((mask.intf_class_port & 0xFF) << 12)
   6083                     | ((mask.intf_class_l2 & 0xF) << 8)
   6084                     | ((mask.intf_class_vport & 0xF) << 4)
   6085                     | (mask.intf_class_l3 & 0xF);
   6086             }
   6087             break;
   6088         case bcmFieldSrcClassModeOverlayNetworks:
   6089             if (soc_feature(unit, soc_feature_th3_style_fp)) {
   6090                 hw_data = (uint32)((uint32)((data.intf_class_l2 & 0xFF) << 24))
   6091                     | ((data.dst_class_field & 0xF) << 20)
   6092                     | ((data.intf_class_port & 0xF) << 8)
   6093                     | (data.intf_class_l3 & 0xFF);
   6094 
   6095                 hw_mask = (uint32)((uint32)((mask.intf_class_l2 & 0xFF) << 24))
   6096                     | ((mask.dst_class_field & 0xF) << 20)
   6097                     | ((mask.intf_class_port & 0xF) << 8)
   6098                     | (mask.intf_class_l3 & 0xFF);
   6099             } else {
   6100                 hw_data = (uint32)((uint32)(
   6101                     (data.dst_class_field & 0xF) << 28))
   6102                     | ((data.intf_class_port & 0xF) << 24)
   6103                     | ((data.intf_class_l2 & 0xFF) << 16)
   6104                     | ((data.intf_class_vport & 0xFF) << 8)
   6105                     | (data.intf_class_l3 & 0xFF);
   6106 
   6107                 hw_mask = (uint32)((uint32)(
   6108                     (mask.dst_class_field & 0xF) << 28))
   6109                     | ((mask.intf_class_port & 0xF) << 24)
   6110                     | ((mask.intf_class_l2 & 0xFF) << 16)
   6111                     | ((mask.intf_class_vport & 0xFF) << 8)
   6112                     | (mask.intf_class_l3 & 0xFF);
   6113             }
   6114             break;
   6115         default:
   6116             return (BCM_E_PARAM);
   6117             break;
   6118     }
   6119     rv = _field_qualify32(unit, entry, bcmFieldQualifyMixedSrcClassId,
   6120             hw_data, hw_mask);
   6121     if (BCM_SUCCESS(rv)) {
   6122         f_presel->flags |= _FP_ENTRY_MIXED_SRC_CLASS_QUALIFIED;
   6123         BCM_PBMP_ASSIGN(f_presel->mixed_src_class_pbmp, pbmp);
   6124     }
   6125 
   6126     return (rv);
   6127 }
   6128 
   6129 /*
   6130  * Function:
   6131  *      _bcm_field_th_qualify_MixedSrcClassId_get
   6132  * Purpose:
   6133  *      Get match criteria for bcmFieildQualifyMixedSrcClassId
   6134  *                     qualifier from the field entry.
   6135  * Parameters:
   6136  *      unit  - (IN) Unit number.
   6137  *      entry - (IN) Field Entry id.
   6138  *      pbmp  - (IN) Device Port Bitmap value
   6139  *      data  - (OUT) Mixed Source Class Id.
   6140  *      mask  - (OUT) Mixed Source Class Id mask.
   6141  * Returns:
   6142  *      BCM_E_XXX
   6143  * Notes:
   6144  */
   6145     int
   6146 _bcm_field_th_qualify_MixedSrcClassId_get(int unit,
   6147                                           bcm_field_entry_t entry,
   6148                                           bcm_pbmp_t pbmp,
   6149                                           uint32 hw_data,
   6150                                           uint32 hw_mask,
   6151                                           bcm_field_src_class_t *data,
   6152                                           bcm_field_src_class_t *mask)
   6153 {
   6154     bcm_field_presel_t            presel;             /* Presel id. */
   6155     _field_presel_entry_t         *f_presel = NULL;   /* Presel Entry descriptor. */
   6156     _field_stage_id_t             stage_id;
   6157     _field_stage_t                *stage_fc;
   6158     bcm_field_qualify_t           stage_qual;
   6159     bcm_field_group_oper_mode_t   group_mode;
   6160     uint8                         pipe_idx = 0;
   6161     bcm_pbmp_t                    pbmp_temp;
   6162     bcm_pbmp_t                    all_pbmp;   /* Group port bitmap.           */
   6163 
   6164     if ((data == NULL) || (mask == NULL)) {
   6165         return BCM_E_PARAM;
   6166     }
   6167 
   6168     if (!(soc_feature(unit, soc_feature_field_preselector_support) &&
   6169                 (_BCM_FIELD_IS_PRESEL_ENTRY(entry) == TRUE))) {
   6170         return (BCM_E_PARAM);
   6171     }
   6172 
   6173     BCM_IF_ERROR_RETURN(_bcm_field_entry_presel_resolve(unit,
   6174                 entry, &presel, &f_presel));
   6175 
   6176     /* Mixed source class is applicable only
   6177      * for Ingress, extact match and flowtracker stages */
   6178     if (BCM_FIELD_QSET_TEST(f_presel->p_qset,
   6179                 bcmFieldQualifyStageIngress)) {
   6180         stage_id = _BCM_FIELD_STAGE_INGRESS;
   6181         stage_qual = bcmFieldQualifyStageIngress;
   6182     } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset,
   6183                 bcmFieldQualifyStageIngressExactMatch)) {
   6184         stage_id = _BCM_FIELD_STAGE_EXACTMATCH;
   6185         stage_qual = bcmFieldQualifyStageIngressExactMatch;
   6186 #if defined(BCM_FLOWTRACKER_SUPPORT)
   6187     } else if (BCM_FIELD_QSET_TEST(f_presel->p_qset,
   6188                 bcmFieldQualifyStageIngressFlowtracker)) {
   6189         stage_id = _BCM_FIELD_STAGE_FLOWTRACKER;
   6190         stage_qual = bcmFieldQualifyStageIngressFlowtracker;
   6191 #endif
   6192     } else {
   6193         return (BCM_E_PARAM);
   6194     }
   6195 
   6196     /* Verifiy PBMP based on group mode and port config */
   6197     /* Get group mode */
   6198     if (soc_feature(unit, soc_feature_field_single_pipe_support)) {
   6199         group_mode = bcmFieldGroupOperModeGlobal;
   6200     } else {
   6201         BCM_IF_ERROR_RETURN(bcm_esw_field_group_oper_mode_get(unit,
   6202                     stage_qual, &group_mode));
   6203     }
   6204 
   6205     /* Read device port configuration. */ 
   6206     BCM_PBMP_CLEAR(all_pbmp);
   6207     BCM_IF_ERROR_RETURN(_bcm_field_valid_pbmp_get(unit, &all_pbmp));
   6208 
   6209     if (group_mode == bcmFieldGroupOperModeGlobal) {
   6210         /* Pbmp should match all the valid ports */
   6211         if (!BCM_PBMP_EQ(all_pbmp, pbmp)) {
   6212             return BCM_E_PARAM;
   6213         }
   6214     } else if (group_mode == bcmFieldGroupOperModePipeLocal) {
   6215         /* Pbmp provided should be belong to only one pipe */
   6216         for (pipe_idx = 0; pipe_idx < BCM_PIPES_MAX ; pipe_idx++) {
   6217             BCM_PBMP_CLEAR(pbmp_temp);
   6218             BCM_PBMP_ASSIGN(pbmp_temp, PBMP_PIPE(unit, pipe_idx));
   6219             SOC_PBMP_REMOVE(pbmp_temp, PBMP_LB(unit));
   6220             SOC_PBMP_REMOVE(pbmp_temp, PBMP_RDB_ALL(unit));
   6221             SOC_PBMP_REMOVE(pbmp_temp, PBMP_FAE_ALL(unit));
   6222             if (BCM_PBMP_EQ(pbmp_temp, pbmp)) {
   6223                 break;
   6224             }
   6225         }
   6226 
   6227         /* Pbmp doesn't match any of the pipes */
   6228         if (pipe_idx == BCM_PIPES_MAX) {
   6229             return BCM_E_PARAM;
   6230         }
   6231     } else {
   6232         return BCM_E_INTERNAL;
   6233     }
   6234 
   6235     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, stage_id, &stage_fc));
   6236 
   6237     sal_memset(data, 0, sizeof(bcm_field_src_class_t));
   6238     sal_memset(mask, 0, sizeof(bcm_field_src_class_t));
   6239 
   6240     switch (stage_fc->field_src_class_mode[pipe_idx]) {
   6241         case bcmFieldSrcClassModeDefault:
   6242             if (soc_feature(unit, soc_feature_th3_style_fp)) {
   6243                 data->intf_class_l2     = (hw_data >> 28) & 0xF;
   6244                 data->src_class_field   = (hw_data >> 26) & 0x3;
   6245                 data->dst_class_field   = (hw_data >> 16) & 0x3FF;
   6246                 data->udf_class         = (hw_data >> 8) & 0xFF;
   6247                 data->intf_class_port   = hw_data & 0xFF;
   6248 
   6249                 mask->intf_class_l2     = (hw_mask >> 28) & 0xF;
   6250                 mask->src_class_field   = (hw_mask >> 26) & 0x3;
   6251                 mask->dst_class_field   = (hw_mask >> 16) & 0x3FF;
   6252                 mask->udf_class         = (hw_mask >> 8) & 0xFF;
   6253                 mask->intf_class_port   = hw_mask & 0xFF;
   6254             } else {
   6255                 data->src_class_field   = (hw_data >> 30) & 0x3;
   6256                 data->dst_class_field   = (hw_data >> 20) & 0x3FF;
   6257                 data->udf_class         = (hw_data >> 12) & 0xFF;
   6258                 data->intf_class_port   = (hw_data >> 4) & 0xFF;
   6259                 data->intf_class_l2     = hw_data & 0xF;
   6260 
   6261                 mask->src_class_field   = (hw_mask >> 30) & 0x3;
   6262                 mask->dst_class_field   = (hw_mask >> 20) & 0x3FF;
   6263                 mask->udf_class         = (hw_mask >> 12) & 0xFF;
   6264                 mask->intf_class_port   = (hw_mask >> 4) & 0xFF;
   6265                 mask->intf_class_l2     = hw_mask & 0xF;
   6266             }
   6267             break;
   6268         case bcmFieldSrcClassModeSDN:
   6269             if (soc_feature(unit, soc_feature_th3_style_fp)) {
   6270                 data->intf_class_l2     = (hw_data >> 28) & 0xF;
   6271                 data->src_class_field   = (hw_data >> 26) & 0x3;
   6272                 data->dst_class_field   = (hw_data >> 16) & 0x3FF;
   6273                 data->udf_class         = (hw_data >> 12) & 0xF;
   6274                 data->intf_class_port   = (hw_data >> 4) & 0xF;
   6275                 data->intf_class_l3     = hw_data & 0xF;
   6276 
   6277                 mask->intf_class_l2     = (hw_mask >> 28) & 0xF;
   6278                 mask->src_class_field   = (hw_mask >> 26) & 0x3;
   6279                 mask->dst_class_field   = (hw_mask >> 16) & 0x3FF;
   6280                 mask->udf_class         = (hw_mask >> 12) & 0xF;
   6281                 mask->intf_class_port   = (hw_mask >> 4) & 0xF;
   6282                 mask->intf_class_l3     = hw_mask & 0xF;
   6283             } else {
   6284                 data->src_class_field   = (hw_data >> 30) & 0x3;
   6285                 data->dst_class_field   = (hw_data >> 20) & 0x3FF;
   6286                 data->udf_class         = (hw_data >> 16) & 0xF;
   6287                 data->intf_class_port   = (hw_data >> 12) & 0xF;
   6288                 data->intf_class_l2     = (hw_data >> 8) & 0xF;
   6289                 data->intf_class_vport  = (hw_data >> 4) & 0xF;
   6290                 data->intf_class_l3     = hw_data & 0xF;
   6291 
   6292                 mask->src_class_field   = (hw_mask >> 30) & 0x3;
   6293                 mask->dst_class_field   = (hw_mask >> 20) & 0x3FF;
   6294                 mask->udf_class         = (hw_mask >> 16) & 0xF;
   6295                 mask->intf_class_port   = (hw_mask >> 12) & 0xF;
   6296                 mask->intf_class_l2     = (hw_mask >> 8) & 0xF;
   6297                 mask->intf_class_vport  = (hw_mask >> 4) & 0xF;
   6298                 mask->intf_class_l3     = hw_mask & 0xF;
   6299             }
   6300             break;
   6301         case bcmFieldSrcClassModeBalanced:
   6302             if (soc_feature(unit, soc_feature_th3_style_fp)) {
   6303                 data->intf_class_l2     = (hw_data >> 28) & 0xF;
   6304                 data->dst_class_field   = (hw_data >> 20) & 0xFF;
   6305                 data->udf_class         = (hw_data >> 16) & 0xF;
   6306                 data->intf_class_port   = (hw_data >> 4) & 0xFF;
   6307                 data->intf_class_l3     = hw_data & 0xF;
   6308 
   6309                 mask->intf_class_l2     = (hw_mask >> 28) & 0xF;
   6310                 mask->dst_class_field   = (hw_mask >> 20) & 0xFF;
   6311                 mask->udf_class         = (hw_mask >> 16) & 0xF;
   6312                 mask->intf_class_port   = (hw_mask >> 4) & 0xFF;
   6313                 mask->intf_class_l3     = hw_mask & 0xF;
   6314             } else {
   6315                 data->dst_class_field   = (hw_data >> 24) & 0xFF;
   6316                 data->udf_class         = (hw_data >> 20) & 0xF;
   6317                 data->intf_class_port   = (hw_data >> 12) & 0xFF;
   6318                 data->intf_class_l2     = (hw_data >> 8) & 0xF;
   6319                 data->intf_class_vport  = (hw_data >> 4) & 0xF;
   6320                 data->intf_class_l3     = hw_data & 0xF;
   6321 
   6322                 mask->dst_class_field   = (hw_mask >> 24) & 0xFF;
   6323                 mask->udf_class         = (hw_mask >> 20) & 0xF;
   6324                 mask->intf_class_port   = (hw_mask >> 12) & 0xFF;
   6325                 mask->intf_class_l2     = (hw_mask >> 8) & 0xF;
   6326                 mask->intf_class_vport  = (hw_mask >> 4) & 0xF;
   6327                 mask->intf_class_l3     = hw_mask & 0xF;
   6328             }
   6329             break;
   6330         case bcmFieldSrcClassModeOverlayNetworks:
   6331             if (soc_feature(unit, soc_feature_th3_style_fp)) {
   6332                 data->intf_class_l2     = (hw_data >> 24) & 0xFF;
   6333                 data->dst_class_field   = (hw_data >> 20) & 0xF;
   6334                 data->intf_class_port   = (hw_data >> 8) & 0xF;
   6335                 data->intf_class_l3     = hw_data & 0xFF;
   6336 
   6337                 mask->intf_class_l2     = (hw_mask >> 24) & 0xFF;
   6338                 mask->dst_class_field   = (hw_mask >> 20) & 0xF;
   6339                 mask->intf_class_port   = (hw_mask >> 8) & 0xF;
   6340                 mask->intf_class_l3     = hw_mask & 0xFF;
   6341             } else {
   6342                 data->dst_class_field   = (hw_data >> 28) & 0xF;
   6343                 data->intf_class_port   = (hw_data >> 24) & 0xF;
   6344                 data->intf_class_l2     = (hw_data >> 16) & 0xFF;
   6345                 data->intf_class_vport  = (hw_data >> 8) & 0xFF;
   6346                 data->intf_class_l3     = hw_data & 0xFF;
   6347 
   6348                 mask->dst_class_field   = (hw_mask >> 28) & 0xF;
   6349                 mask->intf_class_port   = (hw_mask >> 24) & 0xF;
   6350                 mask->intf_class_l2     = (hw_mask >> 16) & 0xFF;
   6351                 mask->intf_class_vport  = (hw_mask >> 8) & 0xFF;
   6352                 mask->intf_class_l3     = hw_mask & 0xFF;
   6353             }
   6354             break;
   6355         default:
   6356             return (BCM_E_PARAM);
   6357     }
   6358     return (BCM_E_NONE);
   6359 }
   6360 
   6361 /*
   6362  * Function: _bcm_field_th_qualifier_MixedSrcClassId_delete
   6363  *
   6364  * Purpose: Resets data related to MixedSrxClassId
   6365  *
   6366  * Parameters:
   6367  *     unit  - (IN)  BCM device number
   6368  *     entry - (IN)  Field presel entry to operate on.
   6369  *
   6370  * Returns:
   6371  *     BCM_E_XX
   6372  */
   6373 int
   6374 _bcm_field_th_qualifier_MixedSrcClassId_delete(int unit, bcm_field_entry_t entry)
   6375 {
   6376     int                     rv;                /* Operation return status. */
   6377     _field_presel_entry_t   *f_presel;         /* Presel entry structure.  */
   6378     bcm_field_presel_t      presel;            /* Field Preselector ID.    */
   6379 
   6380     /* Preselector feature check */
   6381     if (!soc_feature(unit, soc_feature_field_preselector_support)) {
   6382        return BCM_E_UNAVAIL;
   6383     }
   6384 
   6385     /* Resolve the Preselector ID from the given Entry ID */
   6386     rv = _bcm_field_entry_presel_resolve(unit, entry, &presel, &f_presel);
   6387     if (BCM_FAILURE(rv)) {
   6388        LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   6389                "ERROR: Unable to resolve the Presel Entry ID %d.\n\r"), entry));
   6390        return rv;
   6391     }
   6392 
   6393     f_presel->flags &= ~(_FP_ENTRY_MIXED_SRC_CLASS_QUALIFIED);
   6394     BCM_PBMP_CLEAR(f_presel->mixed_src_class_pbmp);
   6395 
   6396     return BCM_E_NONE;
   6397 }
   6398 
   6399 int
   6400 _bcm_field_max_lt_part_prio_get(int unit)
   6401 {
   6402      if (SOC_IS_HELIX5(unit)) {
   6403          return 18;
   6404      } else {
   6405          return 15;
   6406      }
   6407 }
   6408 
   6409 int
   6410 _bcm_field_th_max_lt_parts_get(int unit)
   6411 {
   6412 #ifdef BCM_TOMAHAWK3_SUPPORT
   6413     if (SOC_IS_TOMAHAWK3(unit)) {
   6414         return 9;
   6415     } else
   6416 #endif
   6417     {
   6418         if (soc_feature(unit, soc_feature_field_slices18)) {
   6419             return 18;
   6420         } else {
   6421             return 12;
   6422         }
   6423     }
   6424 }
   6425 
   6426 #endif /* (BCM_TOMAHAWK_SUPPORT) && (BCM_FIELD_SUPPORT) */