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_em.c (141295B)


      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  * All Rights Reserved.$
      7  *
      8  * File:       field_em.c
      9  * Purpose:    BCM56960 Field Processor Exact Match functions.
     10  */
     11 
     12 #include <soc/defs.h>
     13 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(BCM_FIELD_SUPPORT)
     14 #include <shared/bsl.h>
     15 #include <soc/mem.h>
     16 #include <soc/drv.h>
     17 #include <bcm_int/esw/tomahawk.h>
     18 #if defined(BCM_TOMAHAWK3_SUPPORT)
     19 #include <soc/tomahawk3.h>
     20 #include <bcm_int/esw/tomahawk3.h>
     21 #endif
     22 #include <bcm/field.h>
     23 #include <bcm_int/esw/field.h>
     24 
     25 /* Local functions prototypes. */
     26 STATIC
     27 int _field_th_action_profiles_init(int unit, _field_stage_t *stage_fc,
     28                                    _field_control_t *fc);
     29 
     30 STATIC
     31 int _field_th_qos_action_profiles_init(int unit, _field_stage_t *stage_fc,
     32                                        _field_control_t *fc);
     33 
     34 int
     35 _field_th_em_entry_set(int unit,
     36                             _field_entry_t *f_ent,
     37                             soc_mem_t mem,
     38                             uint32 *bufp, int search_entry);
     39 int
     40 _field_td3_em_entry_set(int unit,
     41                             _field_entry_t *f_ent,
     42                             soc_mem_t mem,
     43                             uint32 *bufp, int search_entry);
     44 
     45 /*Action sets array as per bit positions in Action profile */
     46 uint8 em_action_profile_bitmap[17] = {
     47     _FieldActionMeterSet,
     48     _FieldActionGreenToPidSet,
     49     _FieldActionMirrorOverrideSet,
     50     _FieldActionNatOverrideSet,
     51     _FieldActionSflowSet,
     52     _FieldActionCutThrOverrideSet,
     53     _FieldActionUrpfOverrideSet,
     54     _FieldActionTtlOverrideSet,
     55     _FieldActionLbControlSet,
     56     _FieldActionDropSet,
     57     _FieldActionChangeCpuCosSet,
     58     _FieldActionMirrorSet,
     59     _FieldActionNatSet,
     60     _FieldActionCopyToCpuSet,
     61     _FieldActionL3SwChangeL2Set,
     62     _FieldActionRedirectSet,
     63     _FieldActionCounterSet
     64 };
     65 uint8 ifp_td3_action_profile_bitmap[44] = {
     66     _FieldActionProtectionSwitchingDropOverrideSet,
     67     _FieldActionIfpDlbAlternatePathControlSet,
     68     _FieldActionEcmpDlbActionSet,
     69     _FieldActionHgtLagDlbActionSet,
     70     _FieldActionEcmp2RhActionSet,
     71     _FieldActionEcmp1RhActionSet,
     72     _FieldActionLagRhActionSet,
     73     _FieldActionHgtRhActionSet,
     74     _FieldActionLoopbackProfileActionSet,
     75     _FieldActionExtractionCtrlIdActionSet,
     76     _FieldActionOpaque4ActionSet,
     77     _FieldActionOpaque3ActionSet,
     78     _FieldActionOpaque2ActionSet,
     79     _FieldActionOpaque1ActionSet,
     80     _FieldActionTxTimestampInsertionSet,
     81     _FieldActionRxTimestampInsertionSet,
     82     _FieldActionIgnoreFcoEZoneCheckSet,
     83     _FieldActionGreenToPidSet,
     84     _FieldActionMirrorOverrideSet,
     85     _FieldActionNatOverrideSet,
     86     _FieldActionSflowSet,
     87     _FieldActionCutThrOverrideSet,
     88     _FieldActionUrpfOverrideSet,
     89     _FieldActionTtlOverrideSet,
     90     _FieldActionLbControlSet,
     91     _FieldActionDropSet,
     92     _FieldActionChangeCpuCosSet,
     93     _FieldActionMirrorSet,
     94     _FieldActionNatSet,
     95     _FieldActionCopyToCpuSet,
     96     _FieldActionL3SwChangeL2Set,
     97     _FieldActionRedirectSet,
     98     _FieldActionCounterSet,
     99     _FieldActionChangeEcnSet,
    100     _FieldActionChangePktPriSet,
    101     _FieldActionChangeDscpTosSet,
    102     _FieldActionChangeDropPrecendenceSet,
    103     _FieldActionChangeCosOrIntPriSet,
    104     _FieldActionChangeIntCNSet,
    105     _FieldActionChangeInputPrioritySet,
    106     _FieldActionInstrumentationSet,
    107     _FieldActionEditCtrlIdSet,
    108     _FieldActionFcoEVsanSet,
    109     _FieldActionMeterSet
    110 };
    111 uint8 em_td3_action_profile_bitmap[37] = {
    112     _FieldActionProtectionSwitchingDropOverrideSet,
    113     _FieldActionIfpDlbAlternatePathControlSet,
    114     _FieldActionEcmpDlbActionSet,
    115     _FieldActionHgtLagDlbActionSet,
    116     _FieldActionEcmp2RhActionSet,
    117     _FieldActionEcmp1RhActionSet,
    118     _FieldActionLagRhActionSet,
    119     _FieldActionHgtRhActionSet,
    120     _FieldActionLoopbackProfileActionSet,
    121     _FieldActionExtractionCtrlIdActionSet,
    122     _FieldActionOpaque4ActionSet,
    123     _FieldActionOpaque3ActionSet,
    124     _FieldActionOpaque2ActionSet,
    125     _FieldActionOpaque1ActionSet,
    126     _FieldActionTxTimestampInsertionSet,
    127     _FieldActionRxTimestampInsertionSet,
    128     _FieldActionIgnoreFcoEZoneCheckSet,
    129     _FieldActionGreenToPidSet,
    130     _FieldActionMirrorOverrideSet,
    131     _FieldActionNatOverrideSet,
    132     _FieldActionSflowSet,
    133     _FieldActionCutThrOverrideSet,
    134     _FieldActionUrpfOverrideSet,
    135     _FieldActionTtlOverrideSet,
    136     _FieldActionLbControlSet,
    137     _FieldActionDropSet,
    138     _FieldActionChangeCpuCosSet,
    139     _FieldActionMirrorSet,
    140     _FieldActionNatSet,
    141     _FieldActionCopyToCpuSet,
    142     _FieldActionL3SwChangeL2Set,
    143     _FieldActionRedirectSet,
    144     _FieldActionCounterSet,
    145     _FieldActionInstrumentationSet,
    146     _FieldActionEditCtrlIdSet,
    147     _FieldActionFcoEVsanSet,
    148     _FieldActionMeterSet
    149 };
    150 uint8 em_th2_action_profile_bitmap[23] = {
    151     _FieldActionMeterSet,
    152     _FieldActionGreenToPidSet,
    153     _FieldActionMirrorOverrideSet,
    154     _FieldActionNatOverrideSet,
    155     _FieldActionSflowSet,
    156     _FieldActionCutThrOverrideSet,
    157     _FieldActionUrpfOverrideSet,
    158     _FieldActionTtlOverrideSet,
    159     _FieldActionLbControlSet,
    160     _FieldActionDropSet,
    161     _FieldActionChangeCpuCosSet,
    162     _FieldActionMirrorSet,
    163     _FieldActionNatSet,
    164     _FieldActionCopyToCpuSet,
    165     _FieldActionL3SwChangeL2Set,
    166     _FieldActionRedirectSet,
    167     _FieldActionCounterSet,
    168     _FieldActionIfpDlbAlternatePathControlSet,
    169     _FieldActionEcmpDlbActionSet,
    170     _FieldActionHgtLagDlbActionSet,
    171     _FieldActionTimestampInsertionSet,
    172     _FieldActionInstrumentationSet,
    173     _FieldActionProtectionSwitchingDropOverrideSet,
    174 };
    175 
    176 uint8 em_th3_action_profile_bitmap[24] = {
    177     _FieldActionMeterSet,
    178     _FieldActionChangeCpuCosSet,
    179     _FieldActionCopyToCpuSet,
    180     _FieldActionCounterSet,
    181     _FieldActionCutThrOverrideSet,
    182     _FieldActionDelayedDropSet,
    183     _FieldActionDelayedRedirectSet,
    184     _FieldActionIfpDlbAlternatePathControlSet,
    185     _FieldActionEcmpDlbMonitorSet,
    186     _FieldActionEcmpDlbActionSet,
    187     _FieldActionDropSet,
    188     _FieldActionElephantTrapSet,
    189     _FieldActionRedirectSet,
    190     _FieldActionGreenToPidSet,
    191     _FieldActionInbandTelemetrySet,
    192     _FieldActionInstrumentationSet,
    193     _FieldActionL3SwChangeL2Set,
    194     _FieldActionLbControlSet,
    195     _FieldActionMirrorOverrideSet,
    196     _FieldActionMirrorSet,
    197     _FieldActionProtectionSwitchingDropOverrideSet,
    198     _FieldActionSflowSet,
    199     _FieldActionTimestampInsertionSet,
    200     _FieldActionTtlOverrideSet,
    201 };
    202 
    203 /*
    204  * Function:
    205  *  _field_th_emstage_init
    206  * Purpose:
    207  *  Initialize Exact Match Stage.
    208  * Parameters:
    209  *  unit     - (IN) BCM device number.
    210  *  fc       - (IN) Field control structure.
    211  *  stage_fc - (IN) Stage field control structure.
    212  * Returns:
    213  *  BCM_E_XXX
    214  * Notes:
    215  *  Exact Match Stage in Tomahawk is almost same as IFP stage. Hence there
    216  *  is no need to make separate database for extractor and ibus. Instead IFP
    217  *  database is created first and then exact match stage pointers just use
    218  *  same database instead of creating it's own database.
    219  */
    220 int
    221 _field_th_emstage_init(int unit, _field_control_t *fc,
    222                                  _field_stage_t *stage_fc)
    223 {
    224     int rv = BCM_E_NONE;         /* Operation Return Status */
    225     _field_stage_t *stage_ing;   /* Ingress Stage Control Struct */
    226 
    227     /* Input parameter Check */
    228     if ((fc == NULL) || (stage_fc == NULL)) {
    229         return (BCM_E_PARAM);
    230     }
    231 
    232     /* Applicable only for exact match stage */
    233     if (stage_fc->stage_id != _BCM_FIELD_STAGE_EXACTMATCH) {
    234         return (BCM_E_NONE);
    235     }
    236 
    237     /* Get Ingress Stage Control Structure */
    238     stage_ing = fc->stages;
    239     while (stage_ing) {
    240         if (stage_ing->stage_id == _BCM_FIELD_STAGE_INGRESS) {
    241             break;
    242         }
    243         stage_ing = stage_ing->next;
    244     }
    245 
    246     /* Ingress stage check */
    247     if (NULL == stage_ing) {
    248         return (BCM_E_PARAM);
    249     }
    250     stage_fc->qual_cfg_info_db = stage_ing->qual_cfg_info_db;
    251     stage_fc->ext_cfg_db_arr = stage_ing->ext_cfg_db_arr;
    252 
    253     /* Initialise Keygen Profile */
    254     rv = _field_th_keygen_profiles_init(unit, stage_fc, fc);
    255     if (BCM_FAILURE(rv)) {
    256         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
    257                   "FP(unit %d) Error: _field_th_keygen_profiles_init=%d\n"),
    258                   unit, rv));
    259         return (rv);
    260     }
    261 
    262     /* Initialise Action Profile */
    263     rv = _field_th_action_profiles_init(unit, stage_fc, fc);
    264     if (BCM_FAILURE(rv)) {
    265         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
    266                   "FP(unit %d) Error: _field_th_action_profiles_init=%d\n"),
    267                   unit, rv));
    268         return (rv);
    269     }
    270 
    271     /* Initialise Qos Action Profile */
    272     rv = _field_th_qos_action_profiles_init(unit, stage_fc, fc);
    273     if (BCM_FAILURE(rv)) {
    274         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
    275                 "FP(unit %d) Error: _field_th_qos_action_profiles_init=%d\n"),
    276                  unit, rv));
    277         return (rv);
    278     }
    279     /* Initializing supported Qset*/
    280     sal_memset(&stage_fc->_field_supported_qset, 0, sizeof(bcm_field_qset_t));
    281 
    282     /* Initialize stage Preselector information. */
    283     rv = _bcm_field_th_stage_preselector_init(unit, fc, stage_fc);
    284     if (BCM_FAILURE(rv)) {
    285         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
    286            "FP(unit %d) Error: _bcm_field_th_stage_preselector_init=%d"
    287            "\n"), unit, rv));
    288         return (rv);
    289     }
    290 #if defined(BCM_TRIDENT3_SUPPORT)
    291     if(soc_feature(unit, soc_feature_td3_style_fp)) {
    292         rv = _bcm_field_td3_em_key_attributes_init(unit, stage_fc);
    293         if (BCM_FAILURE(rv)) {
    294             LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
    295                 "FP(unit %d) Error:_bcm_field_td3_em_key_attributes_init =%d"
    296                        "\n"), unit, rv));
    297             return (rv);
    298         }
    299     }
    300 #endif
    301 #if defined(BCM_TOMAHAWK3_SUPPORT)
    302     if(soc_feature(unit, soc_feature_th3_style_fp)) {
    303         rv = _bcm_field_th3_em_key_attributes_init(unit, stage_fc, fc);
    304         if (BCM_FAILURE(rv)) {
    305             LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
    306                             "FP(unit %d) Error:_bcm_field_th3_em_key_attributes_init =%d"
    307                             "\n"), unit, rv));
    308             return (rv);
    309         }
    310     }
    311 #endif
    312 
    313     return (rv);
    314 }
    315 
    316 /*
    317  * Function:
    318  *  _field_th_emstage_update
    319  * Purpose:
    320  *  Update Exact Match Stage.
    321  * Parameters:
    322  *  unit     - (IN) BCM device number.
    323  *  stage_fc - (IN) Stage field control structure.
    324  * Returns:
    325  *  BCM_E_XXX
    326  * Notes:
    327  *  This call is required as exact match uses ext and input
    328  *  data bus same as ingress stage. During oper mode set
    329  *  ingress stage delete and add back database leading
    330  *  to exact match pointing to freed information.
    331  *  Hence whenever ingress oper mode is changed, these
    332  *  database pointers should be updated in exact match stage.
    333  */
    334 int
    335 _field_th_emstage_update(int unit, _field_stage_t *stage_fc)
    336 {
    337     int rv = BCM_E_NONE;         /* Operation Return Status */
    338     _field_stage_t *stage_em;   /* Ingress Stage Control Struct */
    339 
    340     /* Input parameter Check */
    341     if (stage_fc == NULL) {
    342         return (BCM_E_PARAM);
    343     }
    344 
    345     /* Applicable only for ingress stage */
    346     if (stage_fc->stage_id != _BCM_FIELD_STAGE_INGRESS) {
    347         return (BCM_E_NONE);
    348     }
    349 
    350     /* Get Exact match stage structure. */
    351     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
    352                 _BCM_FIELD_STAGE_EXACTMATCH, &stage_em));
    353     stage_em->qual_cfg_info_db = stage_fc->qual_cfg_info_db;
    354     stage_em->ext_cfg_db_arr = stage_fc->ext_cfg_db_arr;
    355 
    356     return (rv);
    357 }
    358 /*
    359  * Function:
    360  *    _field_th_action_profiles_init
    361  * Purpose:
    362  *   Initialize keygen program profiles based on group operational mode.
    363  * Parameters:
    364  *     unit - (IN) BCM device number.
    365  *     stage_fc - (IN/OUT) Stage field control structure.
    366  *
    367  * Returns:
    368  *    BCM_E_PARAM - Null field control structure or stage control parameter.
    369  *    BCM_E_INTERNAL - Null stage slice control structure.
    370  *    BCM_E_MEMORY - Allocation failure.
    371  *    BCM_E_NONE - Success.
    372  */
    373 STATIC int
    374 _field_th_action_profiles_init(int unit, _field_stage_t *stage_fc,
    375                                _field_control_t *fc)
    376 {
    377     soc_mem_t mem;               /* SOC memory names.         */
    378     int entry_words;             /* Entry size in words.      */
    379     int inst;                    /* Instance iterator.        */
    380     int rv;                      /* Operation return status.  */
    381 
    382     /* Input parameter check. */
    383     if (NULL == stage_fc) {
    384         return (BCM_E_PARAM);
    385     }
    386 
    387     /* Applicable only for Exact Match Stage */
    388     if (stage_fc->stage_id != _BCM_FIELD_STAGE_EXACTMATCH) {
    389         return (BCM_E_NONE);
    390     }
    391 
    392     switch (stage_fc->oper_mode) {
    393 
    394         /* Field Groups operational in Global mode. */
    395         case bcmFieldGroupOperModeGlobal:
    396 
    397             /* Initialize action profile memory name. */
    398             mem = EXACT_MATCH_ACTION_PROFILEm;
    399 
    400             /* Determine action profile entry size in number of words. */
    401             entry_words = soc_mem_entry_words(unit, mem);
    402 
    403             /* Create action program profile table. */
    404             rv = soc_profile_mem_create(unit, &mem, &entry_words, 1,
    405                     &stage_fc->action_profile[_FP_DEF_INST]);
    406 
    407             if (BCM_FAILURE(rv)) {
    408                 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
    409                    "FP(unit %d) Error: action profile creation failed."
    410                    "=%d\n"), unit, rv));
    411                 return (rv);
    412             }
    413             break;
    414 
    415         /* Field Groups operational in Per-Pipe mode. */
    416         case bcmFieldGroupOperModePipeLocal:
    417 
    418             /* Determine action profiles entry size in number of words. */
    419             entry_words = soc_mem_entry_words(unit,
    420                                  EXACT_MATCH_ACTION_PROFILE_PIPE0m);
    421 
    422             for (inst = 0; inst < stage_fc->num_instances; inst++) {
    423                 if (!(fc->pipe_map & (1 << inst))) {
    424                      continue;
    425                 }
    426                 /* Initialize action program profile memory name. */
    427                 BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit,
    428                                           EXACT_MATCH_ACTION_PROFILEm,
    429                                           inst, &mem));
    430 
    431                 /* Create action program profile table. */
    432                 rv = soc_profile_mem_create(unit, &mem, &entry_words, 1,
    433                         &stage_fc->action_profile[inst]);
    434 
    435                 if (BCM_FAILURE(rv)) {
    436                     LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
    437                        "FP(unit %d) Error: action profile creation failed."
    438                        "=%d\n"), unit, rv));
    439                     return (rv);
    440                 }
    441             }
    442             break;
    443 
    444         default:
    445             /*
    446              * Invalid Group Operational mode, should never hit this condition.
    447              */
    448             return (BCM_E_INTERNAL);
    449     }
    450 
    451     return (BCM_E_NONE);
    452 }
    453 
    454 /*
    455  * Function:
    456  *    _field_th_qos_action_profiles_init
    457  * Purpose:
    458  *   Initialize qos action profiles based on group operational mode.
    459  * Parameters:
    460  *     unit - (IN) BCM device number.
    461  *     stage_fc - (IN/OUT) Stage field control structure.
    462  *
    463  * Returns:
    464  *    BCM_E_PARAM - Null field control structure or stage control parameter.
    465  *    BCM_E_INTERNAL - Null stage slice control structure.
    466  *    BCM_E_MEMORY - Allocation failure.
    467  *    BCM_E_NONE - Success.
    468  */
    469 STATIC int
    470 _field_th_qos_action_profiles_init(int unit, _field_stage_t *stage_fc,
    471                                    _field_control_t *fc)
    472 {
    473     int entry_words;             /* Entry size in words.               */
    474     int inst;                    /* Instance iterator.                 */
    475     int rv;                      /* Operation return status.           */
    476     soc_mem_t mem;               /* SOC memory names.                  */
    477 
    478     /* Input parameter check. */
    479     if (NULL == stage_fc) {
    480         return (BCM_E_PARAM);
    481     }
    482 
    483     /* Applicable only for Exact Match Stage */
    484     if (stage_fc->stage_id != _BCM_FIELD_STAGE_EXACTMATCH) {
    485         return (BCM_E_NONE);
    486     }
    487 
    488     switch (stage_fc->oper_mode) {
    489 
    490         /* Field Groups operational in Global mode. */
    491         case bcmFieldGroupOperModeGlobal:
    492 
    493             /* Initialize profile1 memory name. */
    494             mem = EXACT_MATCH_QOS_ACTIONS_PROFILEm;
    495 
    496             /* Determine qos action profile entry size in number of words. */
    497             entry_words = soc_mem_entry_words(unit, mem);
    498 
    499             /* Create qos action program profile table. */
    500             rv = soc_profile_mem_create(unit, &mem, &entry_words, 1,
    501                     &stage_fc->qos_action_profile[_FP_DEF_INST]);
    502 
    503             if (BCM_FAILURE(rv)) {
    504                 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
    505                    "FP(unit %d) Error: qos action "
    506                    "profile creation failed."
    507                    "=%d\n"), unit, rv));
    508                 return (rv);
    509             }
    510             break;
    511 
    512          /* Field Groups operational in Per-Pipe mode. */
    513         case bcmFieldGroupOperModePipeLocal:
    514 
    515             /* Determine qos action profiles entry size in number of words. */
    516             entry_words = soc_mem_entry_words(unit,
    517                     EXACT_MATCH_QOS_ACTIONS_PROFILE_PIPE0m);
    518 
    519             for (inst = 0; inst < stage_fc->num_instances; inst++) {
    520                 if (!(fc->pipe_map & (1 << inst))) {
    521                      continue;
    522                 }
    523                 /* Initialize qos action program profile memory name. */
    524                 BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit,
    525                                           EXACT_MATCH_QOS_ACTIONS_PROFILEm,
    526                                           inst, &mem));
    527 
    528                 /* Create qos action program profile table. */
    529                 rv = soc_profile_mem_create(unit, &mem, &entry_words, 1,
    530                                          &stage_fc->qos_action_profile[inst]);
    531                 if (BCM_FAILURE(rv)) {
    532                     LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
    533                        "FP(unit %d) Error: qos action "
    534                        "profile creation failed."
    535                        "=%d\n"), unit, rv));
    536                     return (rv);
    537                 }
    538             }
    539             break;
    540 
    541         default:
    542             /*
    543              * Invalid Group Operational mode, should never hit this condition.
    544              */
    545             return (BCM_E_INTERNAL);
    546     }
    547 
    548     return (BCM_E_NONE);
    549 }
    550 
    551 /*
    552  * Function:
    553  *  _field_th_emstage_deinit
    554  * Purpose:
    555  *   De-Initialize Exact Match Stage.
    556  * Parameters:
    557  *   unit     - (IN) BCM device number.
    558  *   stage_fc - (IN) Stage field control structure.
    559  * Returns:
    560  *   BCM_E_XXX
    561  * Notes:
    562  */
    563 int
    564 _field_th_emstage_deinit(int unit, _field_stage_t *stage_fc)
    565 {
    566     int rv = BCM_E_NONE;    /* Operation Return Status */
    567 
    568     /* Input Parameter Check. */
    569     if (stage_fc == NULL) {
    570         return (BCM_E_PARAM);
    571     }
    572 
    573     /* Do nothing for non EM stage. */
    574     if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) {
    575         return (BCM_E_NONE);
    576     }
    577 
    578     /* Since Exact Match Stage uses same extractor and input
    579      * bus database as ingress stage. hence deinit will happen
    580      * during ingress stage delete. Set to NULL here as we
    581      * are simply using ingress stage database previously.
    582      */
    583 
    584     return (rv);
    585 }
    586 
    587 /*
    588  * Function:
    589  *  _field_th_em_entries_free_get
    590  * Purpose:
    591  *  Retreive Free Entries available in UFT table.
    592  * Parameters:
    593  *  unit       - (IN)  BCM device number.
    594  *  fg         - (IN)  Field group structure.
    595  *  free_count - (OUT) Free Entries Count.
    596  * Returns:
    597  *  BCM_E_XXX
    598  * Notes:
    599  */
    600 int
    601 _field_th_em_entries_free_get(int unit, _field_group_t *fg,
    602                                            int *free_count)
    603 {
    604     _field_stage_t *stage_fc = NULL;    /* Field Stage Control.      */
    605     _field_slice_t *fs = NULL;          /* Slice info.               */
    606     int slice = 0;                      /* Slice Count Iterator.     */
    607 
    608     /* Input Paramter Check. */
    609     if ((fg == NULL) ||
    610         (free_count == NULL)) {
    611         return (BCM_E_PARAM);
    612     }
    613 
    614     /* Initialize free entry count. */
    615     *free_count = 0;
    616 
    617     /* Not applicable for non exact match stages. */
    618     if (fg->stage_id != _BCM_FIELD_STAGE_EXACTMATCH) {
    619         return (BCM_E_INTERNAL);
    620     }
    621 
    622     /* Retreive Stage Control. */
    623     BCM_IF_ERROR_RETURN(
    624             _field_stage_control_get(unit, fg->stage_id, &stage_fc));
    625 
    626     /* Retreive Slice Instance. */
    627     fs = stage_fc->slices[fg->instance];
    628 
    629     /* Calculate free entry count. */
    630     for (slice = 0; slice < stage_fc->tcam_slices; slice++) {
    631         *free_count += fs[slice].free_count;
    632     }
    633 
    634     return (BCM_E_NONE);
    635 }
    636 
    637 /*
    638  * Function:
    639  *  _field_th_em_qualifier_set
    640  * Purpose:
    641  *  Set Exact Match Qualifier Value.
    642  * Parameters:
    643  *  unit     - (IN) BCM device number.
    644  *  entry    - (IN) Entry ID.
    645  *  qual     - (IN) Qualifier Field.
    646  *  data     - (IN) Matching Data.
    647  *  mask     - (IN) Bit Mask For Data.
    648  * Returns:
    649  *  BCM_E_XXX
    650  * Notes:
    651  */
    652 int
    653 _field_th_em_qualifier_set(int unit, bcm_field_entry_t entry,
    654                            int qual, uint32 *data, uint32 *mask)
    655 {
    656     int rv = BCM_E_NONE;          /* Operational Status.    */
    657     _field_entry_t *f_ent;        /* Field Entry Control.   */
    658     _field_group_t *fg;           /* Field Group Struc.     */
    659     bcm_field_qualify_t qual_id;  /* Qualfier ID.           */
    660     int flag = 0;                 /* Flag.                  */
    661 
    662     if (NULL == data || NULL == mask) {
    663         return BCM_E_PARAM;
    664     }
    665 
    666     /* Retrieve the field entry. */
    667     rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent);
    668     BCM_IF_ERROR_RETURN(rv);
    669 
    670     /* Retreive Field Group. */
    671     fg = f_ent->group;
    672 
    673     if (qual == bcmFieldQualifyExactMatchHitStatus) {
    674         if (BCM_FIELD_QSET_TEST(fg->qset,
    675                      _bcmFieldQualifyExactMatchHitStatusLookup0)) {
    676             qual_id = _bcmFieldQualifyExactMatchHitStatusLookup0;
    677             rv = _bcm_field_th_qualify_set(unit, entry, qual_id,
    678                                                       data, mask,
    679                                                       _FP_QUALIFIER_DEL);
    680             BCM_IF_ERROR_RETURN(rv);
    681             flag = 1;
    682         }
    683         if (BCM_FIELD_QSET_TEST(fg->qset,
    684                      _bcmFieldQualifyExactMatchHitStatusLookup1)) {
    685             qual_id = _bcmFieldQualifyExactMatchHitStatusLookup1;
    686             rv = _bcm_field_th_qualify_set(unit, entry, qual_id,
    687                                                      data, mask,
    688                                                      _FP_QUALIFIER_DEL);
    689             BCM_IF_ERROR_RETURN(rv);
    690             flag = 1;
    691         }
    692     } else if (qual == bcmFieldQualifyExactMatchActionClassId) {
    693         if (BCM_FIELD_QSET_TEST(fg->qset,
    694                      _bcmFieldQualifyExactMatchActionClassIdLookup0)) {
    695             qual_id = _bcmFieldQualifyExactMatchActionClassIdLookup0;
    696             rv = _bcm_field_th_qualify_set(unit, entry, qual_id,
    697                                                      data, mask,
    698                                                      _FP_QUALIFIER_DEL);
    699             BCM_IF_ERROR_RETURN(rv);
    700             flag = 1;
    701         }
    702         if (BCM_FIELD_QSET_TEST(fg->qset,
    703                      _bcmFieldQualifyExactMatchActionClassIdLookup1)) {
    704             qual_id = _bcmFieldQualifyExactMatchActionClassIdLookup1;
    705             rv = _bcm_field_th_qualify_set(unit, entry, qual_id,
    706                                                      data, mask,
    707                                                      _FP_QUALIFIER_DEL);
    708             BCM_IF_ERROR_RETURN(rv);
    709             flag = 1;
    710         }
    711     } else if (qual == bcmFieldQualifyExactMatchGroupClassId) {
    712         if (BCM_FIELD_QSET_TEST(fg->qset,
    713                      _bcmFieldQualifyExactMatchGroupClassIdLookup0)) {
    714             qual_id = _bcmFieldQualifyExactMatchGroupClassIdLookup0;
    715             rv = _bcm_field_th_qualify_set(unit, entry, qual_id,
    716                                                      data, mask,
    717                                                      _FP_QUALIFIER_DEL);
    718             BCM_IF_ERROR_RETURN(rv);
    719             flag = 1;
    720         }
    721         if (BCM_FIELD_QSET_TEST(fg->qset,
    722                      _bcmFieldQualifyExactMatchGroupClassIdLookup1)) {
    723             qual_id = _bcmFieldQualifyExactMatchGroupClassIdLookup1;
    724             rv = _bcm_field_th_qualify_set(unit, entry, qual_id,
    725                                                      data, mask,
    726                                                      _FP_QUALIFIER_DEL);
    727             BCM_IF_ERROR_RETURN(rv);
    728             flag = 1;
    729         }
    730     } else {
    731         rv = BCM_E_PARAM;
    732     }
    733 
    734     /* Check if qual was present. */
    735     if (flag == 0) {
    736         LOG_ERROR(BSL_LS_BCM_FP,
    737                 (BSL_META_U(unit,
    738                  "FP(unit %d) Error: qual=%s not in group=%d Qset\n"),
    739                  unit, _field_qual_name(qual), fg->gid));
    740         rv = BCM_E_PARAM;
    741     }
    742 
    743     return (rv);
    744 }
    745 
    746 /*
    747  * Function:
    748  *  _field_th_em_group_lookup_get
    749  * Purpose:
    750  *  Get Lookup information for exact match group
    751  *  with given priority.
    752  * Parameters:
    753  *  unit     - (IN) BCM device number.
    754  *  priority - (IN) Exact Match Group Priority.
    755  *  lookup   - (OUT) Exact Match Lookup Information.
    756  * Returns:
    757  *  BCM_E_XXX
    758  * Notes:
    759  *  This function is applicable only for exact match
    760  *  group.
    761  */
    762 int
    763 _field_th_em_group_lookup_get(int unit,
    764                               int priority,
    765                               uint8 *lookup)
    766 {
    767     int rv = BCM_E_NONE;        /* Operational Status.        */
    768     _field_control_t *fc;       /* Unit FP control structure. */
    769     _field_group_t *fg = NULL;  /* Group information.         */
    770 
    771     /* Input Parameter Check. */
    772     if (lookup == NULL) {
    773         return (BCM_E_PARAM);
    774     }
    775 
    776     /* Get unit FP control structure. */
    777     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
    778 
    779     /* Iterate over the groups linked-list looking for a matching
    780      * group Id. */
    781     fg = fc->groups;
    782     while (fg != NULL) {
    783         if ((fg->priority == priority) &&
    784             (fg->stage_id == _BCM_FIELD_STAGE_EXACTMATCH)) {
    785             break;
    786         }
    787         fg = fg->next;
    788     }
    789 
    790     /* Exact Match Group Check. */
    791     if (fg == NULL) {
    792         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
    793             "FP(unit %d) Error: Exact Match Group with priority %d "
    794             "does not exist.\n"),
    795             unit,priority));
    796         return (BCM_E_NOT_FOUND);
    797     }
    798 
    799     /* Slice Check. */
    800     if (fg->slices == NULL) {
    801         return (BCM_E_INTERNAL);
    802     }
    803 
    804     /* Return Lookup Information. */
    805     if (fg->slices->slice_number == 0) {
    806         *lookup = BCM_FIELD_EXACT_MATCH_LOOKUP_0;
    807     } else if (fg->slices->slice_number == 1) {
    808         *lookup = BCM_FIELD_EXACT_MATCH_LOOKUP_1;
    809     } else {
    810         rv = BCM_E_INTERNAL;
    811     }
    812 
    813     return (rv);
    814 }
    815 
    816 /*
    817  * Function:
    818  *  _field_th_em_ltid_based_groupid_get
    819  * Purpose:
    820  *  Get group id information for exact match group
    821  *  with given logical table id.
    822  * Parameters:
    823  *  unit     - (IN) BCM device number.
    824  *  ltid     - (IN) Exact Match Logical Table Id.
    825  *  group    - (OUT) Exact Match Group Id.
    826  * Returns:
    827  *  BCM_E_XXX
    828  * Notes:
    829  *  This function is only applicable for exact match
    830  *  group.
    831  */
    832 int
    833 _field_th_em_ltid_based_groupid_get(int unit, int ltid,
    834                                               bcm_field_group_t *group)
    835 {
    836     int rv = BCM_E_NONE;         /* Operational Status.        */
    837     _field_control_t *fc;        /* Unit FP control structure. */
    838     _field_group_t *fg = NULL;   /* Group information.         */
    839 
    840     /* Input Parameter Check */
    841     if (group == NULL) {
    842         return (BCM_E_PARAM);
    843     }
    844 
    845     /* Get unit FP control structure. */
    846     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
    847 
    848     /* Iterate over the groups linked-list looking for a matching Group ID */
    849     fg = fc->groups;
    850     while (fg != NULL) {
    851         if ((fg->lt_id == ltid) &&
    852             (fg->stage_id == _BCM_FIELD_STAGE_EXACTMATCH)) {
    853             break;
    854         }
    855         fg = fg->next;
    856     }
    857 
    858     /* Exact Match Group Check. */
    859     if (fg == NULL) {
    860         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
    861             "FP(unit %d) Error: Exact Match Group with ltid %d "
    862             "does not exist.\n"),
    863              unit,ltid));
    864         return (BCM_E_NOT_FOUND);
    865     }
    866 
    867     /* Return Group Information. */
    868     *group = fg->gid;
    869 
    870     return (rv);
    871 }
    872 
    873 /*
    874  * Function:
    875  *  _field_th_em_group_priority_hintbased_qset_update
    876  * Purpose:
    877  *  Update Field Group Qset based on Group Priority.
    878  * Parameters:
    879  *  unit       - (IN) BCM device number.
    880  *  hint_entry - (IN) - Field Hint Structure.
    881  *  fg         - (OUT) field group structure.
    882  * Returns:
    883  *  BCM_E_XXX
    884  * Notes:
    885  */
    886 int
    887 _field_th_em_group_priority_hintbased_qset_update(int unit,
    888                                                   _field_group_t *fg,
    889                                                   bcm_field_hint_t *hint_entry)
    890 {
    891     int rv = BCM_E_NONE;        /* Operational Status. */
    892     uint8 lkup = 0;             /* Exact Match Lookup. */
    893 
    894     /* Input Parameter Check. */
    895     if ((fg == NULL) || (hint_entry == NULL)) {
    896         return (BCM_E_PARAM);
    897     }
    898 
    899     /* Get Exact Match with provided priority. */
    900     rv = _field_th_em_group_lookup_get(unit, hint_entry->priority, &lkup);
    901     if (BCM_FAILURE(rv)) {
    902         return (rv);
    903     }
    904 
    905     /* Set Exact Match Hit Status. */
    906     if (hint_entry->qual == bcmFieldQualifyExactMatchHitStatus) {
    907         if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyExactMatchHitStatus)) {
    908             if (lkup == BCM_FIELD_EXACT_MATCH_LOOKUP_0) {
    909                 BCM_FIELD_QSET_ADD(fg->qset,
    910                         _bcmFieldQualifyExactMatchHitStatusLookup0);
    911             } else if (lkup == BCM_FIELD_EXACT_MATCH_LOOKUP_1) {
    912                 BCM_FIELD_QSET_ADD(fg->qset,
    913                         _bcmFieldQualifyExactMatchHitStatusLookup1);
    914             } else {
    915                 rv = BCM_E_INTERNAL;
    916             }
    917         }
    918     } else if (hint_entry->qual == bcmFieldQualifyExactMatchGroupClassId) {
    919         /* Set Exact Match Group Class Id. */
    920         if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyExactMatchGroupClassId)) {
    921             if (lkup == BCM_FIELD_EXACT_MATCH_LOOKUP_0) {
    922                 BCM_FIELD_QSET_ADD(fg->qset,
    923                         _bcmFieldQualifyExactMatchGroupClassIdLookup0);
    924             } else if (lkup == BCM_FIELD_EXACT_MATCH_LOOKUP_1) {
    925                 BCM_FIELD_QSET_ADD(fg->qset,
    926                         _bcmFieldQualifyExactMatchGroupClassIdLookup1);
    927             } else {
    928                 rv = BCM_E_INTERNAL;
    929             }
    930         }
    931     } else if (hint_entry->qual == bcmFieldQualifyExactMatchActionClassId) {
    932         /* Set Exact Match Action Class Id. */
    933         if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyExactMatchActionClassId)) {
    934             if (lkup == BCM_FIELD_EXACT_MATCH_LOOKUP_0) {
    935                 BCM_FIELD_QSET_ADD(fg->qset,
    936                         _bcmFieldQualifyExactMatchActionClassIdLookup0);
    937             } else if (lkup == BCM_FIELD_EXACT_MATCH_LOOKUP_1) {
    938                 BCM_FIELD_QSET_ADD(fg->qset,
    939                         _bcmFieldQualifyExactMatchActionClassIdLookup1);
    940             } else {
    941                 rv = BCM_E_INTERNAL;
    942             }
    943         }
    944     } else {
    945         rv = BCM_E_PARAM;
    946     }
    947 
    948     return (rv);
    949 }
    950 
    951 /*
    952  * Function:
    953  *  _field_th_exactmatch_slice_validate
    954  * Purpose:
    955  *   Validate Exact Match Slice Allocation.
    956  * Parameters:
    957  *   unit     - (IN) BCM device number.
    958  *   stage_fc - (IN) Stage Control structure.
    959  *   fg       - (IN) field group structure.
    960  *   slice_id - (IN) Slice Identifier.
    961  * Returns:
    962  *   BCM_E_XXX
    963  * Notes:
    964  */
    965 int
    966 _field_th_exactmatch_slice_validate(int unit,
    967                                     _field_stage_t *stage_fc,
    968                                     _field_group_t *fg, int slice_id)
    969 {
    970     int rv = BCM_E_NONE;                   /* Operational Status   */
    971     _field_group_t *fg_ptr = NULL;         /* Field Group Pointer. */
    972     _field_lt_slice_t *lt_slice = NULL;    /* Lt Slice Pointer.    */
    973     _field_slice_t *fs_part = NULL;        /* Field slice Pointer. */
    974 
    975     /* Input parameters check. */
    976     if (NULL == stage_fc || NULL == fg) {
    977         return (BCM_E_PARAM);
    978     }
    979 
    980     /* Lookup One is not present in TH3 EM */
    981 #if defined(BCM_TOMAHAWK3_SUPPORT)
    982     if (soc_feature(unit, soc_feature_th3_style_fp)) {
    983         if (1 == (slice_id % 3)) {
    984             LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit,
    985                        "FP(unit %d) Verb: Lookup One"
    986                        " not supported.\n"), unit));
    987             return (BCM_E_CONFIG);
    988         }
    989     }
    990 #endif
    991     /* In Exact Match Single and Double Wide
    992      * Groups can share slices.
    993      */
    994     if ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) && (1 == (slice_id % 3))) {
    995         LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit,
    996                     "FP(unit %d) Verb: slices not available for DoubleWide"
    997                     " exact match group.\n"), unit));
    998         return (BCM_E_CONFIG);
    999     }
   1000 
   1001     if ((fg->flags & _FP_GROUP_SPAN_SINGLE_SLICE) && (1 == (slice_id % 3))) {
   1002         fs_part = stage_fc->slices[fg->instance] + (slice_id - 1);
   1003         if (fs_part->group_flags & _FP_GROUP_SPAN_DOUBLE_SLICE) {
   1004             LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1005                             "FP(unit %d) Verb: slice=%d is secondary "
   1006                             "slice of DoubleWide"
   1007                             " group.\n"), unit, slice_id));
   1008             return (BCM_E_CONFIG);
   1009         }
   1010     }
   1011 
   1012     if ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE)) {
   1013         fs_part = stage_fc->slices[fg->instance] + (slice_id + 1);
   1014         if (fs_part->group_flags & _FP_GROUP_SPAN_SINGLE_SLICE) {
   1015             LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1016                             "FP(unit %d) Verb: slice=%d is already occupied "
   1017                             "by SingleWide"
   1018                             " group.\n"), unit, (slice_id + 1)));
   1019             return (BCM_E_CONFIG);
   1020         }
   1021     }
   1022 
   1023     /* Retrieve the existing groups associated with the Slice */
   1024     rv = _bcm_field_slice_group_get_next(unit, fg->instance,
   1025                                             fg->stage_id, slice_id,
   1026                                             &fg_ptr, &fg_ptr);
   1027     if (BCM_SUCCESS(rv)) {
   1028 
   1029         /* TH3 needs to fetch group other than internal group if any */
   1030         if ((soc_feature(unit, soc_feature_sw_mmu_flush_rqe_operation)) &&
   1031             (fg_ptr->gid == _FP_INTERNAL_RESERVED_EM_ID)) {
   1032 
   1033             lt_slice = fg_ptr->lt_slices;
   1034 
   1035             /* Retrieve the existing groups associated with the Slice */
   1036             rv = _bcm_field_slice_group_get_next(unit, fg->instance,
   1037                                                     fg->stage_id, slice_id,
   1038                                                     &fg_ptr, &fg_ptr);
   1039 
   1040            if (rv == BCM_E_NOT_FOUND) {
   1041                /* Nothing to do. */
   1042                rv = BCM_E_NONE;
   1043                goto next;
   1044            } else if (BCM_FAILURE(rv)) {
   1045                return rv;
   1046            }
   1047 
   1048         }
   1049 
   1050         /* Group with priority ANY, can't share
   1051          * slice with any other group's. */
   1052         if (BCM_FIELD_GROUP_PRIO_ANY == fg->priority) {
   1053             LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1054                         "Group with prio ANY"
   1055                         "can't share slice with any other groups.\n\r")));
   1056             return BCM_E_CONFIG;
   1057         }
   1058 
   1059         /* Compare the group priority with
   1060            the existing group in the slice. */
   1061         if (fg->priority != fg_ptr->priority) {
   1062             LOG_VERBOSE(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1063                 "Slice[%d] contains other"
   1064                 " groups with different priority.\n\r"),
   1065                  slice_id));
   1066             return (BCM_E_CONFIG);
   1067         }
   1068 
   1069         if ((fg_ptr->flags & _FP_GROUP_PRESELECTOR_SUPPORT) == 0) {
   1070             LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1071                      "Group creation failed, Already default group exists"
   1072                      " with the same priority[%d].\n\r"),
   1073                      fg_ptr->priority));
   1074             return (BCM_E_PARAM);
   1075         }
   1076 
   1077         if ((fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT) == 0) {
   1078             LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1079                     "Group creation failed, can't create a group with the"
   1080                     " priority"
   1081                     " same as existing preselector group priority[%d]\n\r"),
   1082                      fg_ptr->priority));
   1083             return (BCM_E_PARAM);
   1084         }
   1085 
   1086         lt_slice = fg_ptr->lt_slices;
   1087 
   1088     } else if (rv == BCM_E_NOT_FOUND) {
   1089         /* Nothing to do. */
   1090         rv = BCM_E_NONE;
   1091     } else {
   1092         return rv;
   1093     }
   1094 
   1095 next:
   1096 
   1097     BCM_IF_ERROR_RETURN(_field_th_group_lt_slice_validate(unit, stage_fc, fg,
   1098                                                           slice_id, lt_slice));
   1099 
   1100     return (rv);
   1101 }
   1102 
   1103 /*
   1104  * Function:
   1105  *  _field_th_keygen_em_profile_entry_pack
   1106  * Purpose:
   1107  *  Build a LT keygen exact match program profile
   1108  *  table entry.
   1109  * Parameters:
   1110  *  unit         - (IN)     BCM device number.
   1111  *  stage_fc     - (IN)     Stage field control structure.
   1112  *  fg           - (IN)     Field group structure.
   1113  *  part         - (IN)     Entry part number.
   1114  *  mem          - (IN)     Memory name identifier.
   1115  *  prof_entry  - (IN/OUT) Entry buffer pointer.
   1116  * Returns:
   1117  *  BCM_E_XXX
   1118  */
   1119 int
   1120 _field_th_keygen_em_profile_entry_pack(int unit, _field_stage_t *stage_fc,
   1121                                    _field_group_t *fg, int part, soc_mem_t mem,
   1122                         exact_match_key_gen_program_profile_entry_t *prof_entry)
   1123 {
   1124     int idx; /* Iterator index. */
   1125     static const soc_field_t l1_32_sel[] = /* 32 bit extractors. */
   1126     {
   1127         L1_E32_SEL_0f,
   1128         L1_E32_SEL_1f,
   1129         L1_E32_SEL_2f,
   1130         L1_E32_SEL_3f
   1131     };
   1132     static const soc_field_t l1_16_sel[] = /* 16 bit extractors. */
   1133     {
   1134         L1_E16_SEL_0f,
   1135         L1_E16_SEL_1f,
   1136         L1_E16_SEL_2f,
   1137         L1_E16_SEL_3f,
   1138         L1_E16_SEL_4f,
   1139         L1_E16_SEL_5f,
   1140         L1_E16_SEL_6f
   1141     };
   1142     static const soc_field_t l1_8_sel[] = /* 8 bit extractors. */
   1143     {
   1144         L1_E8_SEL_0f,
   1145         L1_E8_SEL_1f,
   1146         L1_E8_SEL_2f,
   1147         L1_E8_SEL_3f,
   1148         L1_E8_SEL_4f,
   1149         L1_E8_SEL_5f,
   1150         L1_E8_SEL_6f
   1151     };
   1152     static const soc_field_t l1_4_sel[] = /* 4 bit extractors. */
   1153     {
   1154         L1_E4_SEL_0f,
   1155         L1_E4_SEL_1f,
   1156         L1_E4_SEL_2f,
   1157         L1_E4_SEL_3f,
   1158         L1_E4_SEL_4f,
   1159         L1_E4_SEL_5f,
   1160         L1_E4_SEL_6f,
   1161         L1_E4_SEL_7f
   1162     };
   1163     static const soc_field_t l1_2_sel[] = /* 2 bit extractors. */
   1164     {
   1165         L1_E2_SEL_0f,
   1166         L1_E2_SEL_1f,
   1167         L1_E2_SEL_2f,
   1168         L1_E2_SEL_3f,
   1169         L1_E2_SEL_4f,
   1170         L1_E2_SEL_5f,
   1171         L1_E2_SEL_6f,
   1172         L1_E2_SEL_7f
   1173     };
   1174     static const soc_field_t l2_16_sel[] = /* 16 bit extractors. */
   1175     {
   1176         L2_E16_SEL_0f,
   1177         L2_E16_SEL_1f,
   1178         L2_E16_SEL_2f,
   1179         L2_E16_SEL_3f,
   1180         L2_E16_SEL_4f,
   1181         L2_E16_SEL_5f,
   1182         L2_E16_SEL_6f,
   1183         L2_E16_SEL_7f,
   1184         L2_E16_SEL_8f,
   1185         L2_E16_SEL_9f
   1186     };
   1187     static const soc_field_t l3_4_sel[] = /* 4 bit extractors. */
   1188     {
   1189         L3_E4_SEL_0f,
   1190         L3_E4_SEL_1f,
   1191         L3_E4_SEL_2f,
   1192         L3_E4_SEL_3f,
   1193         L3_E4_SEL_4f,
   1194         L3_E4_SEL_5f,
   1195         L3_E4_SEL_6f,
   1196         L3_E4_SEL_7f,
   1197         L3_E4_SEL_8f,
   1198         L3_E4_SEL_9f,
   1199         L3_E4_SEL_10f,
   1200         L3_E4_SEL_11f,
   1201         L3_E4_SEL_12f,
   1202         L3_E4_SEL_13f,
   1203         L3_E4_SEL_14f,
   1204         L3_E4_SEL_15f,
   1205         L3_E4_SEL_16f,
   1206         L3_E4_SEL_17f,
   1207         L3_E4_SEL_18f,
   1208         L3_E4_SEL_19f,
   1209         L3_E4_SEL_20f
   1210     };
   1211     static const soc_field_t l3_2_sel[] = /* 2 bit extractors. */
   1212     {
   1213         L3_E2_SEL_0f,
   1214         L3_E2_SEL_1f,
   1215         L3_E2_SEL_2f,
   1216         L3_E2_SEL_3f,
   1217         L3_E2_SEL_4f
   1218     };
   1219     static const soc_field_t l3_1_sel[] = /* 1 bit extractors. */
   1220     {
   1221         L3_E1_SEL_0f,
   1222         L3_E1_SEL_1f
   1223     };
   1224 
   1225     /* Input parameters check. */
   1226     if ((NULL == stage_fc) || (NULL == fg) || (NULL == prof_entry)) {
   1227         return (BCM_E_PARAM);
   1228     }
   1229 
   1230     /* Set 32bit extractor selcode values. */
   1231     for (idx = 0; idx < 4; idx++) {
   1232         if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[part].l1_e32_sel[idx]) {
   1233             soc_mem_field32_set(unit, mem, prof_entry, l1_32_sel[idx],
   1234                     fg->ext_codes[part].l1_e32_sel[idx]);
   1235         }
   1236     }
   1237 
   1238     /* Set 16bit extractor selcode values. */
   1239     for (idx = 0; idx < 7; idx++) {
   1240         if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[part].l1_e16_sel[idx]) {
   1241             soc_mem_field32_set(unit, mem, prof_entry, l1_16_sel[idx],
   1242                     fg->ext_codes[part].l1_e16_sel[idx]);
   1243         }
   1244     }
   1245 
   1246     /* Set 8bit extractor selcode values. */
   1247     for (idx = 0; idx < 7; idx++) {
   1248         if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[part].l1_e8_sel[idx]) {
   1249             soc_mem_field32_set(unit, mem, prof_entry, l1_8_sel[idx],
   1250                     fg->ext_codes[part].l1_e8_sel[idx]);
   1251         }
   1252     }
   1253 
   1254     /* Set 4bit extractor selcode values. */
   1255     for (idx = 0; idx < 8; idx++) {
   1256         if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[part].l1_e4_sel[idx]) {
   1257             soc_mem_field32_set(unit, mem, prof_entry, l1_4_sel[idx],
   1258                     fg->ext_codes[part].l1_e4_sel[idx]);
   1259         }
   1260     }
   1261 
   1262     /* Set 2bit extractor selcode values. */
   1263     for (idx = 0; idx < 8; idx++) {
   1264         if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[part].l1_e2_sel[idx]) {
   1265             soc_mem_field32_set(unit, mem, prof_entry, l1_2_sel[idx],
   1266                     fg->ext_codes[part].l1_e2_sel[idx]);
   1267         }
   1268     }
   1269 
   1270     /* Set 16bit extractor selcode values. */
   1271     for (idx = 0; idx < 10; idx++) {
   1272         if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[part].l2_e16_sel[idx]) {
   1273             soc_mem_field32_set(unit, mem, prof_entry, l2_16_sel[idx],
   1274                     fg->ext_codes[part].l2_e16_sel[idx]);
   1275         }
   1276     }
   1277 
   1278     /* Set 4bit extractor selcode values. */
   1279     for (idx = 0; idx < 21; idx++) {
   1280         if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[part].l3_e4_sel[idx]) {
   1281             soc_mem_field32_set(unit, mem, prof_entry, l3_4_sel[idx],
   1282                     fg->ext_codes[part].l3_e4_sel[idx]);
   1283         }
   1284     }
   1285 
   1286     /* Set 2bit extractor selcode values. */
   1287     for (idx = 0; idx < 5; idx++) {
   1288         if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[part].l3_e2_sel[idx]) {
   1289             soc_mem_field32_set(unit, mem, prof_entry, l3_2_sel[idx],
   1290                     fg->ext_codes[part].l3_e2_sel[idx]);
   1291         }
   1292     }
   1293 
   1294     /* Set 1bit extractor selcode values. */
   1295     for (idx = 0; idx < 2; idx++) {
   1296         if (_FP_EXT_SELCODE_DONT_CARE != fg->ext_codes[part].l3_e1_sel[idx]) {
   1297             soc_mem_field32_set(unit, mem, prof_entry, l3_1_sel[idx],
   1298                     fg->ext_codes[part].l3_e1_sel[idx]);
   1299         }
   1300     }
   1301 
   1302     return (BCM_E_NONE);
   1303 }
   1304 /*
   1305  * Function:
   1306  *     _bcm_field_th_em_udf_keygen_mask_get
   1307  * Purpose:
   1308  *  Get the mask to be applied for data qualifiers.
   1309  * Parameters:
   1310  *  unit         - (IN)     BCM device number.
   1311  *  fg           - (IN)     Field group structure.
   1312  *  qid          - (IN)     Qualifier number.
   1313  *  mask         - (OUT)    Mask to be applied.
   1314  * Returns:
   1315  *  BCM_E_XXX
   1316  */
   1317 int _bcm_field_th_em_udf_keygen_mask_get(int unit,
   1318                                          _field_group_t *fg,
   1319                                          uint16 qid, uint32 *mask)
   1320 {
   1321     _field_hints_t        *f_ht = NULL;      /* Field hints Structure. */
   1322     _field_hint_t         *hint_node = NULL; /* Field hint Structure. */
   1323     int rv = BCM_E_NONE; /* Operational status. */
   1324     uint32 mask_temp = 0;
   1325     uint8 idx = 0;       /* Index Variable. */
   1326     uint8 num_bytes = 0; /* number of bytes used in each UDF chunk. */
   1327     _field_stage_t *stage_fc = NULL; /* Stage operational Structure. */
   1328 
   1329     /* Parameters Check. */
   1330     if (NULL == fg) {
   1331         return BCM_E_PARAM;
   1332     }
   1333 
   1334     /* Exact Match and IFP shares UDF's */
   1335     rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc);
   1336     BCM_IF_ERROR_RETURN(rv);
   1337 
   1338     if (stage_fc->data_ctrl == NULL) {
   1339        return BCM_E_INTERNAL;
   1340     }
   1341 
   1342     /* Derive the offset of byte bit map in QSET's udf_map
   1343      * for a data qualifier. */
   1344     *mask = 0;
   1345     switch (qid) {
   1346          case _bcmFieldQualifyData0:
   1347               num_bytes = 2;
   1348               idx = stage_fc->data_ctrl->num_elems * 2;
   1349               break;
   1350          case _bcmFieldQualifyData1:
   1351               num_bytes = 2;
   1352               idx = (stage_fc->data_ctrl->num_elems * 2) + 2;
   1353               break;
   1354          case _bcmFieldQualifyData2:
   1355               num_bytes = 4;
   1356               idx = (stage_fc->data_ctrl->num_elems * 2) + 4;
   1357               break;
   1358          case _bcmFieldQualifyData3:
   1359               num_bytes = 4;
   1360               idx = (stage_fc->data_ctrl->num_elems * 2) + 8;
   1361               break;
   1362          case _bcmFieldQualifyData4:
   1363               num_bytes = 4;
   1364               idx = (stage_fc->data_ctrl->num_elems * 2) + 12;
   1365               break;
   1366          case _bcmFieldQualifyData5:
   1367               num_bytes = 2;
   1368               idx = (stage_fc->data_ctrl->num_elems * 2) + 16;
   1369               break;
   1370          case _bcmFieldQualifyData6:
   1371               num_bytes = 2;
   1372               idx = (stage_fc->data_ctrl->num_elems * 2) + 18;
   1373               break;
   1374          case _bcmFieldQualifyData7:
   1375               num_bytes = 4;
   1376               idx = (stage_fc->data_ctrl->num_elems * 2) + 20;
   1377               break;
   1378          case _bcmFieldQualifyData8:
   1379               num_bytes = 4;
   1380               idx = (stage_fc->data_ctrl->num_elems * 2) + 24;
   1381               break;
   1382          case _bcmFieldQualifyData9:
   1383               num_bytes = 4;
   1384               idx = (stage_fc->data_ctrl->num_elems * 2) + 28;
   1385               break;
   1386          default:
   1387               *mask = 0xFFFFFFFF;
   1388               break;
   1389     }
   1390 
   1391     if (idx) {
   1392         if (SHR_BITGET(fg->qset.udf_map, idx)) {
   1393             *mask |= 0xFF;
   1394         }
   1395 
   1396         if (SHR_BITGET(fg->qset.udf_map, idx + 1)) {
   1397             *mask |= 0xFF00;
   1398         }
   1399 
   1400         if (4 == num_bytes) {
   1401             if (SHR_BITGET(fg->qset.udf_map, idx + 2)) {
   1402                 *mask |= 0xFF0000;
   1403             }
   1404 
   1405             if (SHR_BITGET(fg->qset.udf_map, idx + 3)) {
   1406                 *mask |= 0xFF000000;
   1407             }
   1408         }
   1409     }
   1410 
   1411     if (fg->hintid) {
   1412         if (0 == *mask) {
   1413             return BCM_E_NONE;
   1414         }
   1415         mask_temp = *mask;
   1416         *mask = 0;
   1417         BCM_IF_ERROR_RETURN(_field_hints_control_get (unit, fg->hintid, &f_ht));
   1418         /* Not a valid hint Id. */
   1419         if (NULL == f_ht) {
   1420             return BCM_E_NONE;
   1421         }
   1422         /* No hints are attached to the hintid. */
   1423         if (NULL == f_ht->hints) {
   1424             return BCM_E_NONE;
   1425         }
   1426         /* Go through all the hints in the hintid. */
   1427         hint_node = f_ht->hints;
   1428         while (NULL != hint_node) {
   1429             if (bcmFieldHintTypeExtraction == hint_node->hint->hint_type) {
   1430                 BCM_IF_ERROR_RETURN(_bcm_th_qual_hint_bmp_get(unit, qid, 1, hint_node, mask,
   1431                                                                    0, NULL, NULL));
   1432             }
   1433             hint_node = hint_node->next;
   1434         }
   1435         if (0 == *mask) {
   1436             *mask = mask_temp;
   1437         }
   1438     }
   1439 
   1440     return BCM_E_NONE;
   1441 }
   1442 
   1443 
   1444 /*
   1445  * Function:
   1446  *  _field_th_keygen_em_profile_mask_entry_pack
   1447  * Purpose:
   1448  *  Build a LT keygen exact match program profile
   1449  *  mask table entry.
   1450  * Parameters:
   1451  *  unit         - (IN)     BCM device number.
   1452  *  stage_fc     - (IN)     Stage field control structure.
   1453  *  fg           - (IN)     Field group structure.
   1454  *  part         - (IN)     Entry part number.
   1455  *  mem          - (IN)     Memory name identifier.
   1456  *  prof_entry  - (IN/OUT) Entry buffer pointer.
   1457  * Returns:
   1458  *  BCM_E_XXX
   1459  */
   1460 int
   1461 _field_th_keygen_em_profile_mask_entry_pack(int unit,
   1462                                 _field_stage_t *stage_fc,
   1463                                 _field_group_t *fg,
   1464                                 int part, soc_mem_t mem,
   1465                                 exact_match_key_gen_mask_entry_t *prof_entry)
   1466 {
   1467     _bcm_field_group_qual_t *q_arr = NULL;    /* Group Qualifier Array.    */
   1468     _bcm_field_qual_offset_t *offset = NULL;  /* Qualifier Offset Pointer. */
   1469     uint32 *fn_data = NULL;                   /* Data Buffer Pointer.      */
   1470     uint32 value = 0;                         /* Value.                    */
   1471     uint32 mask = 0;                          /* Mask.                     */
   1472     int i = 0, j = 0;                         /* Iterators.                */
   1473     int rv = BCM_E_NONE;                      /* Operational Status        */
   1474 
   1475     /* Input Parameter Check. */
   1476     if ((NULL == stage_fc) ||
   1477         (NULL == fg) ||
   1478         (NULL == prof_entry)) {
   1479         return (BCM_E_PARAM);
   1480     }
   1481 
   1482     /* Retreive Buffer data pointer and qualifier array. */
   1483     fn_data = (uint32 *)prof_entry;
   1484     q_arr = &(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part]);
   1485 
   1486     /* Set Mask entry. */
   1487     if (q_arr != NULL) {
   1488         if (q_arr->size > 0) {
   1489             for(i=0; i < q_arr->size; i++) {
   1490 
   1491                 offset = q_arr->offset_arr + i;
   1492 
   1493                 if ((_bcmFieldQualifyData0 == q_arr->qid_arr[i]) ||
   1494                     (_bcmFieldQualifyData1 == q_arr->qid_arr[i]) ||
   1495                     (_bcmFieldQualifyData2 == q_arr->qid_arr[i]) ||
   1496                     (_bcmFieldQualifyData3 == q_arr->qid_arr[i]) ||
   1497                     (_bcmFieldQualifyData4 == q_arr->qid_arr[i]) ||
   1498                     (_bcmFieldQualifyData5 == q_arr->qid_arr[i]) ||
   1499                     (_bcmFieldQualifyData6 == q_arr->qid_arr[i]) ||
   1500                     (_bcmFieldQualifyData7 == q_arr->qid_arr[i]) ||
   1501                     (_bcmFieldQualifyData8 == q_arr->qid_arr[i]) ||
   1502                     (_bcmFieldQualifyData9 == q_arr->qid_arr[i]) ||
   1503                     (_bcmFieldQualifyData10 == q_arr->qid_arr[i]) ||
   1504                     (_bcmFieldQualifyData11 == q_arr->qid_arr[i]) ||
   1505                     (_bcmFieldQualifyData12 == q_arr->qid_arr[i]) ||
   1506                     (_bcmFieldQualifyData13 == q_arr->qid_arr[i]) ||
   1507                     (_bcmFieldQualifyData14 == q_arr->qid_arr[i]) ||
   1508                     (_bcmFieldQualifyData15 == q_arr->qid_arr[i])) {
   1509 
   1510                     if (soc_feature(unit, soc_feature_udf_support)) {
   1511 #if defined (BCM_TOMAHAWK3_SUPPORT)
   1512                         if (soc_feature(unit, soc_feature_th3_style_fp)) {
   1513                             rv = _bcm_field_th3_em_udf_keygen_mask_get(unit, fg,
   1514                                                                  q_arr->qid_arr[i],
   1515                                                                  &mask);
   1516                         } else
   1517 #endif
   1518                         {
   1519                             rv = _bcm_field_th_em_udf_keygen_mask_get(unit, fg,
   1520                                                                  q_arr->qid_arr[i],
   1521                                                                  &mask);
   1522                         }
   1523                     }
   1524 #if defined (BCM_TRIDENT3_SUPPORT)
   1525                     else if (soc_feature(unit, soc_feature_udf_td3x_support)) {
   1526                         rv = _bcm_field_td3_em_udf_keygen_mask_get(unit, fg,
   1527                                                                    q_arr->qid_arr[i],
   1528                                                                    &mask);
   1529                     }
   1530 #endif
   1531                     BCM_IF_ERROR_RETURN(rv);
   1532 
   1533                     for (j=0; j < offset->num_offsets; j++) {
   1534                         if (offset->width[j] > 0) {
   1535                             value = (1 << offset->width[j]) - 1;
   1536                             value = value & mask;
   1537                             mask = (mask >> offset->width[j]);
   1538                             if (!value) {
   1539                                 continue;
   1540                             }
   1541                             rv = _bcm_field_th_val_set(fn_data, &value,
   1542                                                        offset->offset[j],
   1543                                                        offset->width[j]);
   1544                             BCM_IF_ERROR_RETURN(rv);
   1545                         }
   1546                     }
   1547                 } else {
   1548                     for (j=0; j < offset->num_offsets; j++) {
   1549                         if (offset->width[j] > 0) {
   1550                             value = (1 << offset->width[j]) - 1;
   1551                             rv = _bcm_field_th_val_set(fn_data, &value,
   1552                                                        offset->offset[j],
   1553                                                        offset->width[j]);
   1554                             BCM_IF_ERROR_RETURN(rv);
   1555 
   1556                         }
   1557                     }
   1558                 }
   1559             }
   1560         }
   1561     }
   1562 
   1563     return (BCM_E_NONE);
   1564 }
   1565 
   1566 /*
   1567  * Function:
   1568  *  _field_th_em_flex_stat_action_set
   1569  * Purpose:
   1570  *  Attach Flex Stat Action data for Exact Match Entry.
   1571  * Parameters:
   1572  *  unit     - (IN) BCM device number.
   1573  *  f_ent    - (IN) Field Entry.
   1574  *  buf      - (OUT) Exact Match Action Stat Data Buffer.
   1575  * Returns:
   1576  *  BCM_E_XXX
   1577  * Notes:
   1578  */
   1579 STATIC int
   1580 _field_th_em_flex_stat_action_set(int unit, _field_entry_t *f_ent,
   1581                                              soc_mem_t policy_mem,
   1582                                                       uint32 *buf)
   1583 {
   1584     int rv = BCM_E_NONE;             /* BCM Operational Status.      */
   1585     _field_stage_t *stage_fc = NULL; /* Field Stage Control.         */
   1586     _field_group_t *fg = NULL;       /* Field Group Control.         */
   1587     _field_stat_t  *f_st = NULL;     /* Field statistics descriptor. */
   1588     int idx = 0;                     /* Stat array index.            */
   1589     uint32 g_off = 0, y_off = 0, r_off = 0;
   1590                                      /* Color Offsets.               */
   1591     uint32 hw_real_mode = 0;         /* Real Hw Mode.                */
   1592     uint32 hw_pool_num = 0;          /* Stat pool Number.            */
   1593     uint32 hw_ctr_base_idx = 0;      /* Stat Ctr base index.         */
   1594     soc_mem_t mem;                   /* Memory Identifier.           */
   1595 
   1596     /* Input Parameters Check. */
   1597     if ((NULL == f_ent) ||
   1598         (NULL == f_ent->group) ||
   1599         (NULL == f_ent->fs) ||
   1600         (NULL == buf)) {
   1601         return (BCM_E_PARAM);
   1602     }
   1603 
   1604     /* Retreive Field Group */
   1605     fg = f_ent->group;
   1606 
   1607     /* Retreive Stage Control. */
   1608     BCM_IF_ERROR_RETURN(
   1609             _field_stage_control_get(unit, fg->stage_id, &stage_fc));
   1610 
   1611     if (fg->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) {
   1612         /* Get Hardware Buffer Pointer and memory identifier. */
   1613         if ((fg->em_mode == _FieldExactMatchMode128) ||
   1614             (fg->em_mode == _FieldExactMatchMode160)) {
   1615             if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) {
   1616                 mem = EXACT_MATCH_2m;
   1617             } else {
   1618                 BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit,
   1619                                                EXACT_MATCH_2m,
   1620                                                fg->instance, &mem));
   1621             }
   1622         } else {
   1623             if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) {
   1624                 mem = EXACT_MATCH_4m;
   1625             } else {
   1626                 BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit,
   1627                                                EXACT_MATCH_4m,
   1628                                                fg->instance, &mem));
   1629             }
   1630         }
   1631     } else {
   1632         mem = policy_mem;
   1633     }
   1634 
   1635     /* Increment statistics hw reference count. */
   1636     if (f_ent->statistic.flags & _FP_ENTRY_STAT_VALID) {
   1637 
   1638         /* Get statistics entity description structure. */
   1639         BCM_IF_ERROR_RETURN
   1640             (_bcm_field_stat_get(unit, f_ent->statistic.sid, &f_st));
   1641         if (_FP_INVALID_INDEX != f_st->hw_index) {
   1642             /*
   1643              * Not detaching the stats if there is no change in it during entry modification (re-install).
   1644              * Currently, it is applicable to only IFP stage.
   1645              */
   1646             if ((_BCM_FIELD_STAGE_INGRESS != stage_fc->stage_id) ||
   1647                 ((f_ent->statistic.flags & _FP_ENTRY_STAT_DIRTY) &&
   1648                  !(f_ent->statistic.flags & _FP_ENTRY_STAT_INSTALLED))) {
   1649                 /*
   1650                  * For STATs that are shared by entries, hardware counters
   1651                  * are not allocated again. But reference count is incremented
   1652                  * for these counters.
   1653                  */
   1654                 f_st->hw_ref_count++;
   1655 
   1656                 BCM_IF_ERROR_RETURN
   1657                     (_bcm_esw_stat_flex_attach_ingress_table_counters1
   1658                                      (unit, mem, 0, f_st->hw_mode, f_st->hw_index,
   1659                                       f_st->pool_index, buf));
   1660 
   1661                 /* Mark entry as installed. */
   1662                 f_ent->statistic.flags |=  _FP_ENTRY_STAT_INSTALLED;
   1663             }
   1664 
   1665             /* Set Stat Action Buffer. */
   1666 #if defined(BCM_TOMAHAWK3_SUPPORT)
   1667             if(soc_feature(unit, soc_feature_th3_style_fp)) {
   1668 
   1669                 rv = _bcm_field_th_em_color_offset_get(unit, f_st,
   1670                         &g_off, &y_off, &r_off);
   1671                 BCM_IF_ERROR_RETURN(rv);
   1672 
   1673                 rv = _bcm_field_th_val_set(buf, &y_off, 23, 2);
   1674                 BCM_IF_ERROR_RETURN(rv);
   1675 
   1676                 rv = _bcm_field_th_val_set(buf, &r_off, 21, 2);
   1677                 BCM_IF_ERROR_RETURN(rv);
   1678 
   1679                 rv = _bcm_field_th_val_set(buf, &g_off, 19, 2);
   1680                 BCM_IF_ERROR_RETURN(rv);
   1681 
   1682                 hw_pool_num = f_st->pool_index;
   1683                 rv = _bcm_field_th_val_set(buf, &hw_pool_num, 14, 5);
   1684                 BCM_IF_ERROR_RETURN(rv);
   1685 
   1686                 rv = _bcm_esw_stat_flex_get_hw_mode(unit,
   1687                         f_st->hw_mode, &hw_real_mode);
   1688                 BCM_IF_ERROR_RETURN(rv);
   1689 
   1690                 rv = _bcm_field_th_val_set(buf, &hw_real_mode, 12, 2);
   1691                 BCM_IF_ERROR_RETURN(rv);
   1692 
   1693                 hw_ctr_base_idx = f_st->hw_index;
   1694                 rv = _bcm_field_th_val_set(buf, &hw_ctr_base_idx, 0, 12);
   1695 
   1696                 BCM_IF_ERROR_RETURN(rv);
   1697             } else
   1698 #endif
   1699             {
   1700                 rv = _bcm_field_th_em_color_offset_get(unit, f_st,
   1701                         &g_off, &y_off, &r_off);
   1702                 BCM_IF_ERROR_RETURN(rv);
   1703 
   1704                 rv = _bcm_field_th_val_set(buf, &g_off, 0, 2);
   1705                 BCM_IF_ERROR_RETURN(rv);
   1706 
   1707                 rv = _bcm_field_th_val_set(buf, &y_off, 2, 2);
   1708                 BCM_IF_ERROR_RETURN(rv);
   1709 
   1710                 rv = _bcm_field_th_val_set(buf, &r_off, 4, 2);
   1711                 BCM_IF_ERROR_RETURN(rv);
   1712 
   1713                 hw_pool_num = f_st->pool_index;
   1714                 rv = _bcm_field_th_val_set(buf, &hw_pool_num, 6, 5);
   1715                 BCM_IF_ERROR_RETURN(rv);
   1716 
   1717                 rv = _bcm_esw_stat_flex_get_hw_mode(unit,
   1718                         f_st->hw_mode, &hw_real_mode);
   1719                 BCM_IF_ERROR_RETURN(rv);
   1720 
   1721                 rv = _bcm_field_th_val_set(buf, &hw_real_mode, 11, 2);
   1722                 BCM_IF_ERROR_RETURN(rv);
   1723 
   1724                 hw_ctr_base_idx = f_st->hw_index;
   1725                 rv = _bcm_field_th_val_set(buf, &hw_ctr_base_idx, 13,
   1726                         (soc_feature(unit, soc_feature_td3_style_fp) ? 13 : 12));
   1727                 BCM_IF_ERROR_RETURN(rv);
   1728             }
   1729             /*
   1730              * Not detaching the stats if there is no change in it during entry modification (re-install).
   1731              * So do not copy the previous stat value as the copy should be done only for the first time.
   1732              * Currently, it is applicable to only IFP stage.
   1733              */
   1734             if (((_BCM_FIELD_STAGE_INGRESS != stage_fc->stage_id) ||
   1735                  (f_ent->statistic.flags & _FP_ENTRY_STAT_DIRTY)) &&
   1736                   (1 == f_st->hw_ref_count)) {
   1737                 /*
   1738                  * Write individual statistics previous value, first time
   1739                  * entry is installed in hardware.
   1740                  */
   1741                 for (idx = 0; idx < f_st->nstat; idx++) {
   1742                     BCM_IF_ERROR_RETURN
   1743                         (_field_stat_value_set(unit, f_st, f_st->stat_arr[idx],
   1744                                                f_st->stat_values[idx]));
   1745                 }
   1746             }
   1747         }
   1748     }
   1749 
   1750     return (rv);
   1751 }
   1752 
   1753 /*
   1754  * Function:
   1755  *  _field_th_em_qos_profile_actions_alloc
   1756  * Purpose:
   1757  *  Allocate Qos Actions Profile for Exact Match Entry.
   1758  * Parameters:
   1759  *  unit     - (IN) BCM device number.
   1760  *  f_ent    - (IN) Field Entry.
   1761  *  qp_idx   - (OUT) Qos Actions Profile Index.
   1762  * Returns:
   1763  *  BCM_E_XXX
   1764  * Notes:
   1765  *  This api will allocate actions in exact match
   1766  *  qos profile table. Also will return qos profile
   1767  *  index allocated.
   1768  */
   1769 STATIC int
   1770 _field_th_em_qos_profile_actions_alloc(int unit,
   1771                                        _field_entry_t *f_ent,
   1772                                        uint32 *qp_idx)
   1773 {
   1774     int rv = BCM_E_NONE;                /* Operational Status.               */
   1775     _field_group_t *fg = NULL;          /* Field Group Control.              */
   1776     _field_action_t *fa = NULL;         /* Field Action Structure.           */
   1777     _field_stage_t *stage_fc = NULL;    /* Field Stage Control.              */
   1778     exact_match_qos_actions_profile_entry_t qos_prof_entry;
   1779                                         /* Qos Actions Profile Entry Buffer. */
   1780     void *entries[1];                   /* Profile Entry.                    */
   1781     uint32 *bufp = NULL;                /* Hardware Buffer Ptr.              */
   1782     soc_mem_t mem;                      /* Memory Identifier.                */
   1783 
   1784     /* Input Parameter Check */
   1785     if ((NULL == f_ent) ||
   1786         (NULL == f_ent->group) ||
   1787         (NULL == qp_idx)) {
   1788         return (BCM_E_PARAM);
   1789     }
   1790 
   1791     /* Retreive Field Entry Group */
   1792     fg = f_ent->group;
   1793 
   1794     /* Retreive Stage Control */
   1795     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
   1796                                                  fg->stage_id,
   1797                                                  &stage_fc));
   1798 
   1799     /* Assign Qos Actions Profile Memory */
   1800     mem = EXACT_MATCH_QOS_ACTIONS_PROFILEm;
   1801 
   1802     /* Initialize Qos Profile Actions Entry */
   1803     bufp = (uint32 *)&qos_prof_entry;
   1804     sal_memcpy(bufp, soc_mem_entry_null(unit, mem),
   1805             soc_mem_entry_words(unit, mem) * sizeof(uint32));
   1806 
   1807     /* Set QoS Profile Action Buffer. */
   1808     for (fa = f_ent->actions; fa != NULL; fa = fa->next) {
   1809         if (_FP_ACTION_VALID & fa->flags) {
   1810             switch (fa->action) {
   1811                 case bcmFieldActionCosQNew:
   1812                 case bcmFieldActionGpCosQNew:
   1813                 case bcmFieldActionYpCosQNew:
   1814                 case bcmFieldActionRpCosQNew:
   1815                 case bcmFieldActionCosMapNew:
   1816                 case bcmFieldActionGpCosMapNew:
   1817                 case bcmFieldActionYpCosMapNew:
   1818                 case bcmFieldActionRpCosMapNew:
   1819                 case bcmFieldActionUcastCosQNew:
   1820                 case bcmFieldActionGpUcastCosQNew:
   1821                 case bcmFieldActionYpUcastCosQNew:
   1822                 case bcmFieldActionRpUcastCosQNew:
   1823                 case bcmFieldActionMcastCosQNew:
   1824                 case bcmFieldActionGpMcastCosQNew:
   1825                 case bcmFieldActionYpMcastCosQNew:
   1826                 case bcmFieldActionRpMcastCosQNew:
   1827                 case bcmFieldActionPrioIntNew:
   1828                 case bcmFieldActionGpPrioIntNew:
   1829                 case bcmFieldActionYpPrioIntNew:
   1830                 case bcmFieldActionRpPrioIntNew:
   1831                 case bcmFieldActionDropPrecedence:
   1832                 case bcmFieldActionGpDropPrecedence:
   1833                 case bcmFieldActionYpDropPrecedence:
   1834                 case bcmFieldActionRpDropPrecedence:
   1835                 case bcmFieldActionPrioIntCopy:
   1836                 case bcmFieldActionPrioIntTos:
   1837                 case bcmFieldActionPrioIntCancel:
   1838                 case bcmFieldActionGpPrioIntCopy:
   1839                 case bcmFieldActionGpPrioIntTos:
   1840                 case bcmFieldActionGpPrioIntCancel:
   1841                 case bcmFieldActionYpPrioIntCopy:
   1842                 case bcmFieldActionYpPrioIntTos:
   1843                 case bcmFieldActionYpPrioIntCancel:
   1844                 case bcmFieldActionRpPrioIntCopy:
   1845                 case bcmFieldActionRpPrioIntTos:
   1846                 case bcmFieldActionRpPrioIntCancel:
   1847                 case bcmFieldActionGpIntCongestionNotificationNew:
   1848                 case bcmFieldActionYpIntCongestionNotificationNew:
   1849                 case bcmFieldActionRpIntCongestionNotificationNew:
   1850                 case bcmFieldActionPfcClassNew:
   1851                 case bcmFieldActionUntaggedPacketPriorityNew:
   1852                     rv = _bcm_field_th_profile1_action_set(unit,
   1853                                                            f_ent, fa,
   1854                                                            bufp);
   1855                     BCM_IF_ERROR_RETURN(rv);
   1856                     fa->flags &= ~_FP_ACTION_DIRTY;
   1857                     break;
   1858                 case bcmFieldActionEcnNew:
   1859                 case bcmFieldActionGpEcnNew:
   1860                 case bcmFieldActionYpEcnNew:
   1861                 case bcmFieldActionRpEcnNew:
   1862                 case bcmFieldActionPrioPktNew:
   1863                 case bcmFieldActionGpPrioPktNew:
   1864                 case bcmFieldActionYpPrioPktNew:
   1865                 case bcmFieldActionRpPrioPktNew:
   1866                 case bcmFieldActionGpTosPrecedenceNew:
   1867                 case bcmFieldActionDscpNew:
   1868                 case bcmFieldActionGpDscpNew:
   1869                 case bcmFieldActionYpDscpNew:
   1870                 case bcmFieldActionRpDscpNew:
   1871                 case bcmFieldActionPrioPktCopy:
   1872                 case bcmFieldActionGpPrioPktCopy:
   1873                 case bcmFieldActionYpPrioPktCopy:
   1874                 case bcmFieldActionRpPrioPktCopy:
   1875                 case bcmFieldActionPrioPktTos:
   1876                 case bcmFieldActionGpPrioPktTos:
   1877                 case bcmFieldActionYpPrioPktTos:
   1878                 case bcmFieldActionRpPrioPktTos:
   1879                 case bcmFieldActionPrioPktCancel:
   1880                 case bcmFieldActionGpPrioPktCancel:
   1881                 case bcmFieldActionYpPrioPktCancel:
   1882                 case bcmFieldActionRpPrioPktCancel:
   1883                 case bcmFieldActionDot1pPreserve:
   1884                 case bcmFieldActionGpDot1pPreserve:
   1885                 case bcmFieldActionYpDot1pPreserve:
   1886                 case bcmFieldActionRpDot1pPreserve:
   1887                 case bcmFieldActionDscpCancel:
   1888                 case bcmFieldActionGpDscpCancel:
   1889                 case bcmFieldActionYpDscpCancel:
   1890                 case bcmFieldActionRpDscpCancel:
   1891                 case bcmFieldActionGpTosPrecedenceCopy:
   1892                 case bcmFieldActionDscpPreserve:
   1893                 case bcmFieldActionGpDscpPreserve:
   1894                 case bcmFieldActionYpDscpPreserve:
   1895                 case bcmFieldActionRpDscpPreserve:
   1896                     rv = _bcm_field_th_profile2_action_set(unit,
   1897                                                            f_ent, fa,
   1898                                                            bufp);
   1899                     BCM_IF_ERROR_RETURN(rv);
   1900                     fa->flags &= ~_FP_ACTION_DIRTY;
   1901                     break;
   1902                 default :
   1903                     /* Do nothing */
   1904                     break;
   1905             }
   1906         }
   1907     }
   1908 
   1909     /* Set Profile Entry. */
   1910     entries[0] = bufp;
   1911 
   1912     /* Add entry to Qos Actions Profile Tables In Hardware */
   1913     rv = soc_profile_mem_add(unit,
   1914                              &stage_fc->qos_action_profile[fg->instance],
   1915                              entries, 1, qp_idx);
   1916     return rv;
   1917 }
   1918 
   1919 
   1920 
   1921 /*
   1922  * Function:
   1923  *  _field_th_entry_action_profile_data_set
   1924  * Purpose:
   1925  *  generate the action profiel data buffer from
   1926  *  Actions Profile index
   1927  *    1) for Exact Match Entry of TH and TD3.
   1928  *    2) for Ingress Entry of TD3.
   1929  * Parameters:
   1930  *  unit     - (IN) BCM device number.
   1931  *  f_ent    - (IN) Field Entry.
   1932  *  abuf     - (OUT) Action Data Buffer.
   1933  *  ap_idx   - (IN) Actions Profile Index.
   1934  * Returns:
   1935  *  BCM_E_XXX
   1936  * Notes:
   1937  *  This api will return the filled action data
   1938  *  buffer using action profile entry index
   1939  */
   1940 int
   1941 _field_th_entry_action_profile_data_set(int unit,
   1942                                    _field_entry_t *f_ent,
   1943                                    uint32 *ap_idx,
   1944 				   soc_mem_t policy_mem,
   1945                                    uint32 *abuf)
   1946 {
   1947     int rv = BCM_E_NONE;              /* Operational Status.          */
   1948     _field_stage_t *stage_fc = NULL;  /* Field Stage Control.         */
   1949     _field_group_t *fg = NULL;        /* Field Group Control.         */
   1950     _field_action_t *fa = NULL;       /* Field Action Structure.      */
   1951     exact_match_action_profile_entry_t em_act_prof_entry;
   1952                                       /* Action Profile Table Buffer. */
   1953     ifp_policy_action_profile_entry_t  ifp_act_prof_entry;
   1954                                       /* Action Profile Table Buffer. */
   1955     void *act_prof_entry;               /* Profile table buffer pointer */
   1956     _field_em_action_set_t acts_buf[_FieldActionSetCount];
   1957                                       /* Action Set Buuffer.          */
   1958     _field_em_action_set_t *acts = NULL;
   1959                                       /* Action Set Data.             */
   1960     int idx;                          /* Exact Match Action Set
   1961                                          Iterator.                    */
   1962     uint32 act_offset = 0;            /* Exact Match Action Set
   1963                                         Offset.                      */
   1964     uint32 meterbuf[SOC_MAX_MEM_FIELD_WORDS] = {0};
   1965                                       /* Action Meter Data Buffer.    */
   1966     uint8 field_action_set;           /* to hold Action set value     */
   1967     _bcm_field_action_conf_t *action_conf_ptr;
   1968                                       /* Action configuration pointer */
   1969     int counter_present = 0;          /* Counter Present flag.        */
   1970     soc_mem_t mem;                    /* Memory Identifier.           */
   1971     uint32 *action_set_bitmap;       /* Action bitmap as per hardware*/
   1972     uint32 act_valid =0;               /* Action valid flag */
   1973     _bcm_field_action_set_t            *action_set_ptr;
   1974                                         /* action set pointer */
   1975     uint8 *hw_bitmap;                    /* hw bitmap */
   1976     uint8 hw_bitmap_entries = 0;
   1977     soc_field_info_t * f_info;  /* field info structure. */
   1978     int meter_base = 0; /* meter field base offset */
   1979 
   1980     /* Input Parameter Check */
   1981     if ((NULL == f_ent) ||
   1982         (NULL == f_ent->group) ||
   1983         (NULL == abuf) ||
   1984         (NULL == ap_idx)) {
   1985         return (BCM_E_PARAM);
   1986     }
   1987 
   1988     LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1989              "\n\n_field_th_entry_action_profile_data_set: ap_idx %d\n\r"),*ap_idx));
   1990 
   1991     /* Retreive Field Group */
   1992     fg = f_ent->group;
   1993 
   1994     /* Retreive Stage Control */
   1995     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
   1996                                                  fg->stage_id,
   1997                                                  &stage_fc));
   1998 
   1999     /* Check whether it is a valid stage */
   2000     if (!(((SOC_IS_TOMAHAWKX(unit))
   2001         && (fg->stage_id == _BCM_FIELD_STAGE_EXACTMATCH))
   2002         || soc_feature(unit, soc_feature_ifp_action_profiling)))
   2003     {
   2004         return BCM_E_INTERNAL;
   2005     }
   2006     action_set_ptr = stage_fc->action_set_ptr;
   2007     /* Assign correct Action Profile Memory
   2008      * and Action set's depending on stage */
   2009     if (fg->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) {
   2010         /* Assign Exact Match Action Profile Memory */
   2011         mem = EXACT_MATCH_ACTION_PROFILEm;
   2012         act_prof_entry = &em_act_prof_entry;
   2013         if (SOC_IS_TOMAHAWK(unit)) {
   2014             hw_bitmap = em_action_profile_bitmap;
   2015             hw_bitmap_entries =
   2016                 sizeof(em_action_profile_bitmap)/sizeof(uint8);
   2017         } else if (SOC_IS_TOMAHAWK2(unit)){
   2018             hw_bitmap = em_th2_action_profile_bitmap;
   2019             hw_bitmap_entries =
   2020                 sizeof(em_th2_action_profile_bitmap)/sizeof(uint8);
   2021         } else if (SOC_IS_TOMAHAWK3(unit)){
   2022             hw_bitmap = em_th3_action_profile_bitmap;
   2023             hw_bitmap_entries =
   2024                 sizeof(em_th3_action_profile_bitmap)/sizeof(uint8);
   2025         } else {
   2026             hw_bitmap = em_td3_action_profile_bitmap;
   2027             hw_bitmap_entries =
   2028                 sizeof(em_td3_action_profile_bitmap)/sizeof(uint8);
   2029         }
   2030     } else {
   2031         /* Assign ifp Action Profile Memory */
   2032         mem = IFP_POLICY_ACTION_PROFILEm;
   2033         act_prof_entry = &ifp_act_prof_entry;
   2034         hw_bitmap = ifp_td3_action_profile_bitmap;
   2035         hw_bitmap_entries =
   2036                sizeof(ifp_td3_action_profile_bitmap)/sizeof(uint8);
   2037     }
   2038 
   2039     /* Initialise variables */
   2040     sal_memset(acts_buf, 0, sizeof(acts_buf));
   2041     sal_memcpy(act_prof_entry, soc_mem_entry_null(unit, mem),
   2042                soc_mem_entry_words(unit, mem) * sizeof(uint32));
   2043 
   2044     /* Set Action Set Buffer. */
   2045     for (fa = f_ent->actions; fa != NULL; fa = fa->next) {
   2046         if (_FP_ACTION_VALID & fa->flags) {
   2047             /* get the action conf ptr from stage structure */
   2048             LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2049                "field action %s is valid\n"),_field_action_name(fa->action)));
   2050             action_conf_ptr = stage_fc->f_action_arr[fa->action];
   2051             /* Test whether the current action is
   2052              * supported in this stage */
   2053             if (NULL != action_conf_ptr) {
   2054                 /* get the aset enum from action_conf_pointer */
   2055                 field_action_set = action_conf_ptr->offset->aset;
   2056             } else if (fa->action == bcmFieldActionPolicerGroup ||
   2057                        fa->action == bcmFieldActionStatGroup) {
   2058                 /* Policer and Stat are dealt later */
   2059                 continue;
   2060             } else {
   2061 
   2062                 /* action is not supported in this stage */
   2063                 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2064                   "FP(unit %d) Error: Action is not supported \n"),
   2065                   unit ));
   2066                 return (BCM_E_UNAVAIL);
   2067             }
   2068 
   2069             /* if the aset for current action is 0, or
   2070              * action_set size is 0 for this stage/chip
   2071              * skip updating the action set data */
   2072             if ((0 == field_action_set) ||
   2073                 (0 == action_set_ptr[field_action_set].size)) {
   2074 #if defined(BCM_TRIDENT3_SUPPORT)
   2075                 if(soc_feature(unit, soc_feature_ifp_action_profiling)) {
   2076                    rv = _bcm_field_td3_internal_action_profile_data_set(unit, f_ent, fa, acts_buf);
   2077                    BCM_IF_ERROR_RETURN(rv);
   2078                 }
   2079 #endif /* BCM_TRIDENT3_SUPPORT */
   2080                 continue;
   2081             } else {
   2082                 /* Set Action Set Buffer. */
   2083                 acts = &acts_buf[field_action_set];
   2084                 rv = _bcm_field_th_action_set(unit, 0, f_ent,
   2085                                           0, fa,  acts->data);
   2086                 if (BCM_FAILURE(rv)) {
   2087                     LOG_ERROR(BSL_LS_BCM_FP, (BSL_META("TH Action set failed.\n")));
   2088                     return rv;
   2089                 }
   2090                 acts->valid = 1;
   2091             }
   2092         }
   2093     }
   2094 
   2095     /* Set Counter Action Data if present.
   2096      * Stat can be attached to entry only if it is
   2097      * present in entry group qset.*/
   2098     if (f_ent->statistic.flags & _FP_ENTRY_STAT_VALID) {
   2099         counter_present = 1;
   2100     }
   2101 
   2102     if (counter_present) {
   2103         acts = &acts_buf[_FieldActionCounterSet];
   2104         rv = _field_th_em_flex_stat_action_set(unit, f_ent, policy_mem,
   2105                                                acts->data);
   2106         BCM_IF_ERROR_RETURN(rv);
   2107         acts->valid = 1;
   2108     }
   2109 
   2110     /* Set Meter related information */
   2111     acts = &acts_buf[_FieldActionMeterSet];
   2112     rv = _field_th_ingress_policer_action_set(unit, f_ent, meterbuf);
   2113     BCM_IF_ERROR_RETURN(rv);
   2114     if(soc_feature(unit, soc_feature_ifp_action_profiling)) {
   2115         meter_base = 0;
   2116     } else {
   2117         f_info = soc_mem_fieldinfo_get(unit, IFP_POLICY_TABLEm, METER_SETf);
   2118         meter_base = f_info->bp;
   2119     }
   2120 
   2121     rv = _bcm_field_th_val_get(meterbuf,
   2122                       acts->data, meter_base,
   2123                       action_set_ptr[_FieldActionMeterSet].size);
   2124     BCM_IF_ERROR_RETURN(rv);
   2125     acts->valid = 1;
   2126 
   2127     /* Handle Green to Pid Action. */
   2128     if ((acts_buf[_FieldActionL3SwChangeL2Set].valid) ||
   2129         (acts_buf[_FieldActionRedirectSet].valid)) {
   2130         acts = &acts_buf[_FieldActionGreenToPidSet];
   2131         acts->valid = 1;
   2132         if (f_ent->flags & _FP_ENTRY_COLOR_INDEPENDENT) {
   2133             acts->data[0] = 1;
   2134         } else {
   2135             acts->data[0] = 0;
   2136         }
   2137     }
   2138 
   2139     /* Now Populate Action Data Buffer.
   2140      * Sequence here for action set is hardware dependant
   2141      */
   2142     /* get the action profile pointer from fg structure */
   2143     BCM_IF_ERROR_RETURN(soc_profile_mem_get(unit,
   2144                              &stage_fc->action_profile[fg->instance],
   2145                              *ap_idx, 1, &act_prof_entry));
   2146     LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2147               "All action data is set, read action profile entry and set data one by one\n")));
   2148     /* For TH and TH2 EM, policy_data needs to be filled from LSB to MSB */
   2149      act_offset = 0;
   2150     /* For TD3, policy data is filled from MSB to LSB */
   2151 #if defined(BCM_TRIDENT3_SUPPORT)
   2152     if(soc_feature(unit, soc_feature_td3_style_fp)) {
   2153         if (policy_mem == IFP_POLICY_TABLEm
   2154             || policy_mem == IFP_POLICY_TABLE_PIPE0m
   2155             || policy_mem == IFP_POLICY_TABLE_PIPE1m) {
   2156             act_offset = _FP_ASET_DATA_SIZE_FOR_POLICY_NARROW;
   2157         } else if (policy_mem == IFP_POLICY_TABLE_WIDEm
   2158                     || policy_mem == IFP_POLICY_TABLE_WIDE_PIPE0m
   2159                     || policy_mem == IFP_POLICY_TABLE_WIDE_PIPE1m) {
   2160             act_offset = _FP_ASET_DATA_SIZE_FOR_POLICY_WIDE;
   2161         } else if ((EXACT_MATCH_DEFAULT_POLICYm == policy_mem) ||
   2162                 (EXACT_MATCH_DEFAULT_POLICY_PIPE0m == policy_mem) ||
   2163                 (EXACT_MATCH_DEFAULT_POLICY_PIPE1m == policy_mem)) {
   2164             act_offset = EM_DEFAULT_POLICY_ACTION_DATA_SIZE;
   2165         } else if (fg->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) {
   2166             if(fg->em_mode == _FieldExactMatchMode128) {
   2167                 act_offset = EM_MODE128_ACTION_DATA_SIZE;
   2168             } else if (fg->em_mode == _FieldExactMatchMode160){
   2169                 act_offset = EM_MODE160_ACTION_DATA_SIZE;
   2170             } else {
   2171                 act_offset = EM_MODE320_ACTION_DATA_SIZE;
   2172             }
   2173         }
   2174     }
   2175 #endif
   2176 
   2177     action_set_bitmap = act_prof_entry;
   2178 
   2179     /* Iterate through all the valid actions
   2180      * for the group and update action data buffer */
   2181     if(soc_feature(unit, soc_feature_td3_style_fp)) {
   2182         for (idx = hw_bitmap_entries-1; idx >= 0; idx--)
   2183         {
   2184             rv = _bcm_field_th_val_get(action_set_bitmap, &act_valid, idx, 1);
   2185             BCM_IF_ERROR_RETURN(rv);
   2186             if (act_valid == 1) {
   2187                 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2188                    "hw action profile set at loc %d is valid\n"),idx));
   2189                 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2190                    "action buffer has %s data\n"),
   2191                    ((acts_buf[hw_bitmap[idx]].valid != 0) ? "VALID":"INVALID")));
   2192                 /*idx Bit is set in the action profile */
   2193                 if (acts_buf[hw_bitmap[idx]].valid)
   2194                 {
   2195                      rv = _bcm_field_th_val_set(abuf,
   2196                             &acts_buf[hw_bitmap[idx]].data[0],
   2197                             act_offset - action_set_ptr[hw_bitmap[idx]].size,
   2198                             action_set_ptr[hw_bitmap[idx]].size);
   2199                      BCM_IF_ERROR_RETURN(rv);
   2200                 }
   2201                 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2202                    "action_set data at offset %d\n"),act_offset - action_set_ptr[hw_bitmap[idx]].size));
   2203                 act_offset -=  action_set_ptr[hw_bitmap[idx]].size;
   2204                 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2205                    "data[0] = 0x%08x, size of action set %d\n"),
   2206                    acts_buf[hw_bitmap[idx]].data[0],action_set_ptr[hw_bitmap[idx]].size));
   2207             }
   2208         }
   2209     } else {
   2210         for (idx = 0; idx < hw_bitmap_entries; idx++)
   2211         {
   2212             rv = _bcm_field_th_val_get(action_set_bitmap, &act_valid, idx, 1);
   2213             BCM_IF_ERROR_RETURN(rv);
   2214             if (act_valid == 1) {
   2215                 /*idx Bit is set in the action profile */
   2216                 if (acts_buf[hw_bitmap[idx]].valid)
   2217                 {
   2218                      rv = _bcm_field_th_val_set(abuf,
   2219                             &acts_buf[hw_bitmap[idx]].data[0],
   2220                             act_offset,
   2221                             action_set_ptr[hw_bitmap[idx]].size);
   2222                      BCM_IF_ERROR_RETURN(rv);
   2223                 }
   2224                 act_offset +=  action_set_ptr[hw_bitmap[idx]].size;
   2225             }
   2226         }
   2227     }
   2228 
   2229     return (rv);
   2230 }
   2231 
   2232 /*
   2233  * Function:
   2234  *  _field_th_em_entry_data_set
   2235  * Purpose:
   2236  *   Set Exact Match Policy Data.
   2237  * Parameters:
   2238  *   unit     - (IN) BCM device number.
   2239  *   f_ent    - (IN) Field Entry.
   2240  *   entbuf   - (OUT) Entry Policy Data Buffer.
   2241  *   qp_idx   - (OUT) Qos Actions Profile Index.
   2242  *   ap_idx   - (OUT) Action Profile Index.
   2243  * Returns:
   2244  *   BCM_E_XXX
   2245  * Notes:
   2246  */
   2247 STATIC int
   2248 _field_th_em_entry_data_set(int unit,
   2249                             _field_entry_t *f_ent,
   2250                             uint32 *entbuf,
   2251                             uint32 *qp_idx,
   2252                             uint32 *ap_idx)
   2253 {
   2254     int rv = BCM_E_NONE;              /* Operation Return Status.    */
   2255     _field_stage_t *stage_fc = NULL;  /* Field Stage Control.        */
   2256     _field_group_t *fg = NULL;        /* Field Group Control.        */
   2257     _field_action_t *fa = NULL;       /* Field action descriptor.    */
   2258     uint32 abuf[SOC_MAX_MEM_FIELD_WORDS] = {0};
   2259                                       /* Action Profile Data Buffer. */
   2260     uint32 class_id = 0;              /* Action Param 0.             */
   2261     soc_mem_t mem, mem_wide;
   2262     soc_field_t policy_data_128, policy_data_160, policy_data_320;
   2263     soc_field_t act_prof_id_128, act_prof_id_160, act_prof_id_320;
   2264 
   2265     /* Input Parameters Check. */
   2266     if ((NULL == f_ent) ||
   2267         (NULL == f_ent->group) ||
   2268         (NULL == entbuf) ||
   2269         (NULL == qp_idx) ||
   2270         (NULL == ap_idx)) {
   2271         return (BCM_E_PARAM);
   2272     }
   2273 
   2274     /* Retreive Field Group. */
   2275     fg = f_ent->group;
   2276 
   2277     /* Return for non EM Stage. */
   2278     if (fg->stage_id != _BCM_FIELD_STAGE_EXACTMATCH) {
   2279         return (BCM_E_INTERNAL);
   2280     }
   2281 
   2282     /* Retreive Stage Control. */
   2283     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
   2284                                                  fg->stage_id, &stage_fc));
   2285 
   2286     /* Get Action Exact Match class id. */
   2287     for (fa = f_ent->actions; fa != NULL; fa = fa->next) {
   2288         if (_FP_ACTION_VALID & fa->flags) {
   2289             if (fa->action == bcmFieldActionExactMatchClassId) {
   2290                 break;
   2291             }
   2292         }
   2293     }
   2294 
   2295     /* If found set class id. */
   2296     if (fa != NULL) {
   2297         class_id = fa->param[0];
   2298         fa->flags &= ~_FP_ACTION_DIRTY;
   2299     }
   2300 
   2301     /* Set Qos Profile Index. */
   2302     rv = _field_th_em_qos_profile_actions_alloc(unit,
   2303                                                 f_ent,
   2304                                                 qp_idx);
   2305     BCM_IF_ERROR_RETURN(rv);
   2306     /* Set Action Profile data. */
   2307     rv = _field_th_entry_action_profile_data_set(unit,
   2308                                             f_ent,
   2309                                             ap_idx,
   2310                                             0, abuf);
   2311     if (BCM_FAILURE(rv)) {
   2312         BCM_IF_ERROR_RETURN(soc_profile_mem_delete(unit,
   2313                                &stage_fc->qos_action_profile[fg->instance],
   2314                                *qp_idx));
   2315         return (rv);
   2316     }
   2317 
   2318     mem = EXACT_MATCH_2m;
   2319     mem_wide = EXACT_MATCH_4m;
   2320 #if defined(BCM_TRIDENT3_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT)
   2321     if(soc_feature(unit, soc_feature_td3_style_fp) ||
   2322        soc_feature(unit, soc_feature_th3_style_fp)) {
   2323         policy_data_128 = MODE128__POLICY_DATAf;
   2324         policy_data_160 = MODE160__POLICY_DATAf;
   2325         policy_data_320 = MODE320__POLICY_DATAf;
   2326         act_prof_id_128 = MODE128__DATA_TYPEf;
   2327         act_prof_id_160 = MODE160__DATA_TYPEf;
   2328         act_prof_id_320 = MODE320__DATA_TYPEf;
   2329     } else
   2330 #endif
   2331     {
   2332         policy_data_128 = MODE128__ACTION_DATAf;
   2333         policy_data_160 = MODE160__ACTION_DATAf;
   2334         policy_data_320 = MODE320__ACTION_DATAf;
   2335         act_prof_id_128 = MODE128__ACTION_PROFILE_IDf;
   2336         act_prof_id_160 = MODE160__ACTION_PROFILE_IDf;
   2337         act_prof_id_320 = MODE320__ACTION_PROFILE_IDf;
   2338     }
   2339 
   2340     /* Set Action Data in entry Buffer. */
   2341     if (fg->em_mode == _FieldExactMatchMode128) {
   2342         soc_mem_field32_set(unit, mem,
   2343                              entbuf,
   2344                              MODE128__QOS_PROFILE_IDf, *qp_idx);
   2345         soc_mem_field32_set(unit, mem,
   2346                              entbuf,
   2347                             act_prof_id_128, *ap_idx);
   2348         soc_mem_field_set(unit, mem,
   2349                              entbuf,
   2350                             policy_data_128, abuf);
   2351         soc_mem_field32_set(unit, mem,
   2352                              entbuf,
   2353                              MODE128__EXACT_MATCH_CLASS_IDf,
   2354                              class_id);
   2355      } else if (fg->em_mode == _FieldExactMatchMode160) {
   2356         soc_mem_field32_set(unit, mem,
   2357                              entbuf,
   2358                              MODE160__QOS_PROFILE_IDf, *qp_idx);
   2359         soc_mem_field32_set(unit, mem,
   2360                              entbuf,
   2361                             act_prof_id_160, *ap_idx);
   2362         soc_mem_field_set(unit, mem,
   2363                              entbuf,
   2364                             policy_data_160, abuf);
   2365         soc_mem_field32_set(unit, mem,
   2366                              entbuf,
   2367                              MODE160__EXACT_MATCH_CLASS_IDf,
   2368                              class_id);
   2369      } else if (fg->em_mode == _FieldExactMatchMode320) {
   2370         soc_mem_field32_set(unit, mem_wide,
   2371                              entbuf,
   2372                              MODE320__QOS_PROFILE_IDf, *qp_idx);
   2373         soc_mem_field32_set(unit, mem_wide,
   2374                              entbuf,
   2375                             act_prof_id_320, *ap_idx);
   2376         soc_mem_field_set(unit, mem_wide,
   2377                              entbuf,
   2378                             policy_data_320, abuf);
   2379         soc_mem_field32_set(unit, mem_wide,
   2380                              entbuf,
   2381                              MODE320__EXACT_MATCH_CLASS_IDf, class_id);
   2382      } else {
   2383         /* Invalid Exact Match Mode. */
   2384         return (BCM_E_PARAM);
   2385     }
   2386 
   2387     return rv;
   2388 }
   2389 
   2390 /*
   2391  * Function:
   2392  *  _field_th_em_entry_action_size_get
   2393  * Purpose:
   2394  *   Get exact match entry action size.
   2395  *   required to add an action
   2396  * Parameters:
   2397  *   unit          - (IN) BCM device number.
   2398  *   f_ent         - (IN) Field Entry.
   2399  *   action_size   - (OUT) Qos Actions Profile Index.
   2400  * Returns:
   2401  *   BCM_E_XXX
   2402  * Notes:
   2403  *  This api returns size of action data based on
   2404  *  actions added to entry, stat and policer
   2405  *  attached to it.
   2406  */
   2407  int
   2408 _field_th_em_entry_action_size_get(int unit, _field_entry_t *f_ent,
   2409                                    int *action_size, uint32 *action_prof_idx)
   2410 {
   2411     _field_stage_t *stage_fc = NULL;    /* Field Stage Control.         */
   2412     _field_group_t *fg;                 /* Field Group structure pointer. */
   2413     _field_action_t *fa = NULL;         /* Field action descriptor.  */
   2414     _field_entry_stat_t    *f_ent_st; /* Field entry statistics structure.*/
   2415     _field_entry_policer_t *f_ent_pl;           /* Field entry policer .     */
   2416     uint16 aset_key_size = 0;           /* Action Set Size.      */
   2417     uint8 aset_cnt[_FieldActionSetCount] = {0};
   2418                                         /* Action Per Set Count. */
   2419     _bcm_field_action_conf_t           *action_conf_ptr;
   2420                                         /* action configuration pointer */
   2421     uint8 field_action_set;             /* to hold Aset enum */
   2422     exact_match_action_profile_entry_t em_act_prof_entry;
   2423                                         /* Action Profile Table Buffer. */
   2424     void *entries[1];                   /* Profile Entry.               */
   2425     void *act_prof_entry;               /* Profile table buffer pointer */
   2426     soc_mem_t mem;                      /* Memory Identifier.           */
   2427     _bcm_field_action_set_t            *action_set_ptr;
   2428                                         /* action set pointer */
   2429     uint32 action_profile_idx;          /* Action profile index         */
   2430 
   2431     /* Input Parameter Check. */
   2432     if ((f_ent == NULL) ||
   2433         (f_ent->group == NULL) ||
   2434         (action_size == NULL)) {
   2435         return (BCM_E_PARAM);
   2436     }
   2437     fg = f_ent->group;
   2438     /* Allowed only for exact match stage currently. */
   2439     if (f_ent->group->stage_id != _BCM_FIELD_STAGE_EXACTMATCH) {
   2440         return (BCM_E_PARAM);
   2441     }
   2442     /* Retreive Stage Control. */
   2443     BCM_IF_ERROR_RETURN(
   2444             _field_stage_control_get(unit, f_ent->group->stage_id, &stage_fc));
   2445 
   2446     mem = EXACT_MATCH_ACTION_PROFILEm;
   2447     act_prof_entry = &em_act_prof_entry;
   2448     action_set_ptr = stage_fc->action_set_ptr;
   2449 
   2450     /* Initialise variables */
   2451     sal_memcpy(act_prof_entry, soc_mem_entry_null(unit, mem),
   2452                 soc_mem_entry_words(unit, mem) * sizeof(uint32));
   2453 
   2454     f_ent_st = &f_ent->statistic;
   2455     if (f_ent_st->flags & _FP_ENTRY_STAT_VALID) {
   2456         if (aset_cnt[_FieldActionCounterSet] == 0) {
   2457             aset_key_size +=
   2458                       action_set_ptr[_FieldActionCounterSet].size;
   2459             aset_cnt[_FieldActionCounterSet]++;
   2460             if (NULL != action_prof_idx) {
   2461                 soc_mem_field32_set(unit, mem, act_prof_entry,
   2462                     action_set_ptr[_FieldActionCounterSet].hw_field, 1);
   2463             }
   2464         }
   2465     }
   2466 
   2467     f_ent_pl = f_ent->policer;
   2468     if (f_ent_pl->flags & _FP_POLICER_VALID) {
   2469         if (aset_cnt[_FieldActionMeterSet] == 0) {
   2470             aset_key_size +=
   2471                       action_set_ptr[_FieldActionMeterSet].size;
   2472             aset_cnt[_FieldActionMeterSet]++;
   2473             if (NULL != action_prof_idx) {
   2474                 soc_mem_field32_set(unit, mem, act_prof_entry,
   2475                     action_set_ptr[_FieldActionMeterSet].hw_field, 1);
   2476             }
   2477         }
   2478     }
   2479 
   2480     for (fa = f_ent->actions; fa != NULL; fa = fa->next) {
   2481         if (_FP_ACTION_VALID & fa->flags) {
   2482             /* get the action conf ptr from stage structure */
   2483             action_conf_ptr = stage_fc->f_action_arr[fa->action];
   2484             /* Test whether the current action is
   2485              * supported in this stage */
   2486             if (NULL != action_conf_ptr) {
   2487                 /* get the aset enum from action_conf_pointer */
   2488                 field_action_set = action_conf_ptr->offset->aset;
   2489             } else if (fa->action == bcmFieldActionPolicerGroup) {
   2490                 /* Flag in ASETs to indicate group
   2491                  * policer usage with the group */
   2492                 field_action_set = _FieldActionMeterSet;
   2493             } else if (fa->action == bcmFieldActionStatGroup) {
   2494                 /* Flag in ASETs to indicate stat group
   2495                  * usage with the group */
   2496                  field_action_set = _FieldActionCounterSet;
   2497             } else {
   2498                  /* action is not supported in this stage */
   2499                  /* add log_error with stage, action, chip*/
   2500                  LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
   2501                   "FP(unit %d) Error: Action is not supported \n"),
   2502                   unit ));
   2503                  return BCM_E_INTERNAL;
   2504             }
   2505             /* if the aset for current action is 0, or
   2506                action_set size is 0 for this stage/chip
   2507                skip the hw field updation step */
   2508             if ((0 == field_action_set) ||
   2509                 (0 == action_set_ptr[field_action_set].size)) {
   2510                 continue;
   2511             } else {
   2512                if (aset_cnt[field_action_set] ==0) {
   2513                    aset_key_size +=
   2514                               action_set_ptr[field_action_set].size;
   2515                    aset_cnt[field_action_set]++;
   2516                    if (NULL != action_prof_idx) {
   2517                        soc_mem_field32_set(unit, mem, act_prof_entry,
   2518                           action_set_ptr[field_action_set].hw_field, 1);
   2519                    }
   2520                }
   2521             }
   2522         }
   2523     }
   2524     /* Check if L3SW/Redirect action is set.
   2525      * If yes then reserve 1 bit for Green To Pid. */
   2526     if (aset_cnt[_FieldActionL3SwChangeL2Set] ||
   2527         aset_cnt[_FieldActionRedirectSet]) {
   2528         aset_key_size +=
   2529                    action_set_ptr[_FieldActionGreenToPidSet].size;
   2530         if (NULL != action_prof_idx) {
   2531             soc_mem_field32_set(unit, mem, act_prof_entry,
   2532                    action_set_ptr[_FieldActionGreenToPidSet].hw_field , 1);
   2533         }
   2534     }
   2535 
   2536     *action_size = aset_key_size;
   2537     LOG_VERBOSE(BSL_LS_BCM_FP,(BSL_META_U(unit,
   2538             "VERB: Default entry EM  aset size %d \n\r"),
   2539              aset_key_size));
   2540 
   2541     if (NULL != action_prof_idx) {
   2542         entries[0] = act_prof_entry;
   2543         /* Add Entries To Action Profile Table In Hardware. */
   2544         BCM_IF_ERROR_RETURN(soc_profile_mem_add(unit,
   2545                              &stage_fc->action_profile[fg->instance],
   2546                              entries, 1, &action_profile_idx));
   2547         *action_prof_idx = action_profile_idx;
   2548     }
   2549     return (BCM_E_NONE);
   2550 }
   2551 
   2552 /*
   2553  * Function:
   2554  *  _field_th_em_default_entry_install
   2555  * Purpose:
   2556  *  Install Default Exact Match Entry.
   2557  * Parameters:
   2558  *  unit     - (IN) BCM device number.
   2559  *  f_ent    - (IN) Field Entry.
   2560  * Returns:
   2561  *  BCM_E_XXX
   2562  * Notes:
   2563  */
   2564 STATIC int
   2565 
   2566 _field_th_em_default_entry_install(int unit, _field_entry_t *f_ent)
   2567 {
   2568     int rv = BCM_E_NONE;                /* Operational Status.       */
   2569     _field_group_t *fg = NULL;          /* Field Group Control.      */
   2570     _field_stage_t *stage_fc = NULL;    /* Field Stage Control.      */
   2571     exact_match_default_policy_entry_t ebuf;
   2572                                         /* Default Entry Buffer.     */
   2573     uint32 *bufp = NULL;                /* Hardware Buffer Ptr.      */
   2574     uint32 abuf[SOC_MAX_MEM_FIELD_WORDS] = {0};
   2575                                         /* Action Data Buffer.       */
   2576     uint32 lt_entry[SOC_MAX_MEM_FIELD_WORDS] = {0};
   2577                                         /* LT Entry buffer.          */
   2578     _field_presel_entry_t *f_presel = NULL;
   2579                                         /* Presel entry structure.   */
   2580     _field_lt_entry_t *f_lt_ent = NULL;
   2581                                         /* Logical entry strucutre.  */
   2582     _field_entry_t *f_ent_part = NULL;  /* Field Entry Part.         */
   2583     _field_action_t *fa = NULL;         /* Field action descriptor.  */
   2584     int part_idx = 0;                   /* Entry Part Index.         */
   2585     int parts_count = 0;                /* Field Entry Parts Count.  */
   2586     uint32 qp_idx = 0;                  /* Qos Actions Profile Index.*/
   2587     uint32 ap_idx = 0;                  /* Actions Profile Index.    */
   2588     uint32 class_id = 0;                /* Exact Match Classs Id.    */
   2589     int aset_size = 0;                  /* Action Data Size.         */
   2590     int idx = 0, tcam_idx = 0;          /* Iter variables.           */
   2591     soc_mem_t mem;                      /* Memory Identifier.        */
   2592     soc_mem_t lt_tcam_mem;              /* LT memory identifier.     */
   2593 
   2594     /* Input Parameter Check. */
   2595     if ((NULL == f_ent) ||
   2596         (NULL == f_ent->group) ||
   2597         (NULL == f_ent->fs)) {
   2598         return (BCM_E_PARAM);
   2599     }
   2600 
   2601     /* Retreive Field Group */
   2602     fg = f_ent->group;
   2603 
   2604     /* Group must have a valid KeyGen index, else return error. */
   2605     if (_FP_EXT_SELCODE_DONT_CARE == fg->ext_codes[0].keygen_index) {
   2606         return (BCM_E_INTERNAL);
   2607     }
   2608 
   2609     /* Should be default entry. */
   2610     if (!(f_ent->flags & _FP_ENTRY_EXACT_MATCH_GROUP_DEFAULT)) {
   2611         return (BCM_E_CONFIG);
   2612     }
   2613 
   2614     /* Do nothing for non EM Stage. */
   2615     if (fg->stage_id != _BCM_FIELD_STAGE_EXACTMATCH) {
   2616         return (BCM_E_INTERNAL);
   2617     }
   2618 
   2619     /* Retreive Stage Control. */
   2620     BCM_IF_ERROR_RETURN(
   2621             _field_stage_control_get(unit, fg->stage_id, &stage_fc));
   2622 
   2623     /* Get Hardware Buffer Pointer and memory identifier. */
   2624     if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) {
   2625         mem = EXACT_MATCH_DEFAULT_POLICYm;
   2626     } else {
   2627         BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit,
   2628                                           EXACT_MATCH_DEFAULT_POLICYm,
   2629                                           fg->instance, &mem));
   2630     }
   2631 
   2632     /* Initialize exact match default policy entry buffer. */
   2633     bufp = (uint32 *)&ebuf;
   2634     sal_memcpy(bufp, soc_mem_entry_null(unit, mem),
   2635             soc_mem_entry_words(unit, mem) * sizeof(uint32));
   2636 
   2637     /* Get number of entry parts. */
   2638     rv = _bcm_field_entry_tcam_parts_count(unit, fg->stage_id,
   2639                                       fg->flags, &parts_count);
   2640     BCM_IF_ERROR_RETURN(rv);
   2641 
   2642     /* Get Size of action attached to entry. */
   2643     rv = _field_th_em_entry_action_size_get(unit, f_ent, &aset_size, &ap_idx);
   2644     BCM_IF_ERROR_RETURN(rv);
   2645 
   2646     /* Validate action Data Size. */
   2647     if (aset_size > EM_DEFAULT_POLICY_ACTION_DATA_SIZE) {
   2648         /* Delete Action Profile. */
   2649         BCM_IF_ERROR_RETURN(soc_profile_mem_delete(unit,
   2650             &stage_fc->action_profile[fg->instance],
   2651             ap_idx));
   2652         return (BCM_E_RESOURCE);
   2653     }
   2654 
   2655     /* Get Action Exact Match class id. */
   2656     for (fa = f_ent->actions; fa != NULL; fa = fa->next) {
   2657         if (_FP_ACTION_VALID & fa->flags) {
   2658             if (fa->action == bcmFieldActionExactMatchClassId) {
   2659                 break;
   2660             }
   2661         }
   2662     }
   2663 
   2664     /* If found set class id. */
   2665     if (fa != NULL) {
   2666         class_id = fa->param[0];
   2667         fa->flags &= ~_FP_ACTION_DIRTY;
   2668     }
   2669 
   2670     /* Set Qos Profile Index. */
   2671     rv = _field_th_em_qos_profile_actions_alloc(unit,
   2672                                                 f_ent,
   2673                                                 &qp_idx);
   2674     BCM_IF_ERROR_RETURN(rv);
   2675     /* Set Action Profile data. */
   2676     rv = _field_th_entry_action_profile_data_set(unit,
   2677                                             f_ent,
   2678                                             &ap_idx,
   2679                                             mem, abuf);
   2680     if (BCM_FAILURE(rv)) {
   2681         BCM_IF_ERROR_RETURN(soc_profile_mem_delete(unit,
   2682                                &stage_fc->qos_action_profile[fg->instance],
   2683                                qp_idx));
   2684         /* Delete Action Profile. */
   2685         BCM_IF_ERROR_RETURN(soc_profile_mem_delete(unit,
   2686             &stage_fc->action_profile[fg->instance],
   2687             ap_idx));
   2688     }
   2689 
   2690     /* Set Default Policy Data Buffer. */
   2691     soc_mem_field32_set(unit, mem,
   2692                         bufp,
   2693                         QOS_PROFILE_IDf, qp_idx);
   2694     soc_mem_field32_set(unit, mem,
   2695                         bufp,
   2696                         soc_feature(unit, soc_feature_td3_style_fp) ? DATA_TYPEf : ACTION_PROFILE_IDf,
   2697                         ap_idx);
   2698     soc_mem_field_set(unit, mem,
   2699                       bufp,
   2700                       soc_feature(unit, soc_feature_td3_style_fp) ? POLICY_DATAf : ACTION_DATAf,
   2701                       abuf);
   2702     soc_mem_field32_set(unit, mem, bufp,
   2703                         EXACT_MATCH_CLASS_IDf, class_id);
   2704 
   2705     /* Install entry in hardware. */
   2706     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL,
   2707                        fg->ext_codes[0].keygen_index, bufp);
   2708     if (BCM_FAILURE(rv)) {
   2709         goto bcm_error;
   2710     }
   2711 
   2712     /* Enable Default Policy in Logical table entries. */
   2713     if (fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT) {
   2714         for (idx = 0; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) {
   2715             if (fg->presel_ent_arr[idx] != NULL) {
   2716                 f_presel = fg->presel_ent_arr[idx];
   2717 
   2718                 tcam_idx = f_presel->hw_index + f_presel->lt_fs->start_tcam_idx;
   2719 
   2720                 rv = _bcm_field_th_lt_tcam_policy_mem_get(unit,
   2721                                         stage_fc, fg->instance,
   2722                                         _BCM_FIELD_MEM_TYPE_EM_LT,
   2723                                         _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB,
   2724                                         &lt_tcam_mem, NULL);
   2725                 if (BCM_FAILURE(rv)) {
   2726                     goto bcm_error;
   2727                 }
   2728 
   2729                 /* Read entry into SW buffer. */
   2730                 rv = soc_mem_read(unit, lt_tcam_mem, MEM_BLOCK_ANY, tcam_idx,
   2731                                                                     lt_entry);
   2732                 if (BCM_FAILURE(rv)) {
   2733                     goto bcm_error;
   2734                 }
   2735 
   2736                 /* Set entry valid bit status. */
   2737                 soc_mem_field32_set(unit, lt_tcam_mem, lt_entry,
   2738                                     DEFAULT_POLICY_ENABLEf, 1);
   2739 
   2740                 /* Install entry in hardware. */
   2741                 rv = soc_mem_write(unit, lt_tcam_mem, MEM_BLOCK_ALL,
   2742                                                  tcam_idx, lt_entry);
   2743                 if (BCM_FAILURE(rv)) {
   2744                     goto bcm_error;
   2745                 }
   2746             }
   2747         }
   2748     } else {
   2749         for (idx = 0; idx < (fg->lt_grp_status.entry_count); idx++) {
   2750             if (fg->lt_entry_arr[idx] == NULL) {
   2751                 continue;
   2752             }
   2753             f_lt_ent = fg->lt_entry_arr[idx];
   2754 
   2755             tcam_idx = f_lt_ent->index + f_lt_ent->lt_fs->start_tcam_idx;
   2756             rv = _bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, fg->instance,
   2757                                                       _BCM_FIELD_MEM_TYPE_EM_LT,
   2758                                                       _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB,
   2759                                                       &lt_tcam_mem, NULL);
   2760             if (BCM_FAILURE(rv)) {
   2761                 goto bcm_error;
   2762             }
   2763 
   2764             /* Read entry into SW buffer. */
   2765             rv = soc_mem_read(unit, lt_tcam_mem, MEM_BLOCK_ANY, tcam_idx,
   2766                                                                 lt_entry);
   2767             if (BCM_FAILURE(rv)) {
   2768                 goto bcm_error;
   2769             }
   2770 
   2771             /* Set entry valid bit status. */
   2772             soc_mem_field32_set(unit, lt_tcam_mem, lt_entry, DEFAULT_POLICY_ENABLEf, 1);
   2773 
   2774             /* Install entry in hardware. */
   2775             rv = soc_mem_write(unit, lt_tcam_mem, MEM_BLOCK_ALL,
   2776                                                tcam_idx, lt_entry);
   2777             if (BCM_FAILURE(rv)) {
   2778                 goto bcm_error;
   2779             }
   2780         }
   2781     }
   2782 
   2783     /* Set Flags. */
   2784     for (part_idx = 0; part_idx < parts_count; part_idx++) {
   2785         f_ent_part = f_ent + part_idx;
   2786 
   2787         /* Set Entry Flags. */
   2788         f_ent_part->flags &= ~_FP_ENTRY_DIRTY;
   2789         f_ent_part->flags |= _FP_ENTRY_INSTALLED;
   2790         f_ent_part->flags |= _FP_ENTRY_ENABLED;
   2791     }
   2792 
   2793     return (rv);
   2794 
   2795 bcm_error:
   2796     /* Delete QoS Action Profile. */
   2797     BCM_IF_ERROR_RETURN(soc_profile_mem_delete(unit,
   2798             &stage_fc->qos_action_profile[fg->instance],
   2799             qp_idx));
   2800     return (rv);
   2801 }
   2802 
   2803 /*
   2804  * Function:
   2805  *  _field_th_em_default_entry_remove
   2806  * Purpose:
   2807  *  Remove Default Exact Match Entry.
   2808  * Parameters:
   2809  *  unit     - (IN) BCM device number.
   2810  *  f_ent    - (IN) Field Entry.
   2811  * Returns:
   2812  *  BCM_E_XXX
   2813  * Notes:
   2814  */
   2815 STATIC int
   2816 _field_th_em_default_entry_remove(int unit, _field_entry_t *f_ent)
   2817 {
   2818     int rv = BCM_E_NONE;                /* Operational Status.       */
   2819     _field_control_t *fc;               /* Field control structure.  */
   2820     _field_group_t *fg = NULL;          /* Field Group Control.      */
   2821     _field_stage_t *stage_fc = NULL;    /* Field Stage Control.      */
   2822     exact_match_default_policy_entry_t ebuf;
   2823                                         /* Default Entry Buffer.     */
   2824     uint32 *bufp = NULL;                /* Hardware Buffer Ptr.      */
   2825     uint32 lt_entry[SOC_MAX_MEM_FIELD_WORDS] = {0};
   2826                                         /* LT Entry buffer.          */
   2827     _field_presel_entry_t *f_presel = NULL;
   2828                                         /* Presel entry structure.   */
   2829     _field_lt_entry_t *f_lt_ent = NULL;
   2830                                         /* Logical entry strucutre.  */
   2831     _field_entry_t *f_ent_part = NULL;  /* Field Entry Part.         */
   2832     int part_idx = 0;                   /* Entry Part Index.         */
   2833     int parts_count = 0;                /* Field Entry Parts Count.  */
   2834     uint32 qp_idx = 0;                  /* Qos Actions Profile Index.*/
   2835     uint32 ap_idx = 0;                  /* Actions Profile Index.    */
   2836     int idx = 0, tcam_idx = 0;          /* Iter variables.           */
   2837     soc_mem_t mem;                      /* Memory Identifier.        */
   2838     soc_mem_t lt_tcam_mem;              /* LT memory identifier.     */
   2839 
   2840     /* Input Parameter Check. */
   2841     if ((NULL == f_ent) ||
   2842         (NULL == f_ent->group) ||
   2843         (NULL == f_ent->fs)) {
   2844         return (BCM_E_PARAM);
   2845     }
   2846 
   2847     /* Retreive Field Group */
   2848     fg = f_ent->group;
   2849 
   2850     /* Group must have a valid KeyGen index, else return error. */
   2851     if (_FP_EXT_SELCODE_DONT_CARE == fg->ext_codes[0].keygen_index) {
   2852         return (BCM_E_INTERNAL);
   2853     }
   2854 
   2855     /* Should be default entry. */
   2856     if (!(f_ent->flags & _FP_ENTRY_EXACT_MATCH_GROUP_DEFAULT)) {
   2857         return (BCM_E_CONFIG);
   2858     }
   2859 
   2860     /* Do nothing for non EM Stage. */
   2861     if (fg->stage_id != _BCM_FIELD_STAGE_EXACTMATCH) {
   2862         return (BCM_E_INTERNAL);
   2863     }
   2864 
   2865     /* Get Field Control structure. */
   2866     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   2867 
   2868     /* Retreive Stage Control. */
   2869     BCM_IF_ERROR_RETURN(
   2870             _field_stage_control_get(unit, fg->stage_id, &stage_fc));
   2871 
   2872     /* Get Hardware Buffer Pointer and memory identifier. */
   2873     if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) {
   2874         mem = EXACT_MATCH_DEFAULT_POLICYm;
   2875     } else {
   2876         BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit,
   2877                                           EXACT_MATCH_DEFAULT_POLICYm,
   2878                                           fg->instance, &mem));
   2879     }
   2880 
   2881     /* Initialize exact match entries. */
   2882     bufp = (uint32 *)&ebuf;
   2883     sal_memcpy(bufp, soc_mem_entry_null(unit, mem),
   2884             soc_mem_entry_words(unit, mem) * sizeof(uint32));
   2885 
   2886     /* Get number of entry parts. */
   2887     rv = _bcm_field_entry_tcam_parts_count(unit, fg->stage_id,
   2888                                            fg->flags, &parts_count);
   2889     BCM_IF_ERROR_RETURN(rv);
   2890 
   2891     /* Read Exact Match Default Policy Entry. */
   2892     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY,
   2893                       fg->ext_codes[0].keygen_index, bufp);
   2894     BCM_IF_ERROR_RETURN(rv);
   2895 
   2896     /* Retreive Qos profile index from entry. */
   2897     qp_idx = soc_mem_field32_get(unit, mem,
   2898                                  bufp, QOS_PROFILE_IDf);
   2899 
   2900     /* Delete Entry QoS Profile Memories for actions. */
   2901     BCM_IF_ERROR_RETURN(soc_profile_mem_delete(unit,
   2902                            &stage_fc->qos_action_profile[fg->instance],
   2903                            qp_idx));
   2904     /*
   2905      * For regular EM entries, action profile is group property
   2906      * So _bcm_field_th_group_deinit will clear EM action profile
   2907      * whereas for EM default entry, Action profile is specifically used by EM default entry alone
   2908      * So need to remove Action profile for EM default entry.
   2909      */
   2910     /*
   2911      * For regular EM entries, action profile will be cleared in _bcm_field_th_group_deinit.
   2912      * So in case of bcm_field_init, method _bcm_field_th_group_deinit will clear
   2913      * all EM action profiles for regular EM entries and default entry.
   2914      * Skip to clear the action profile for now.
   2915      */
   2916     if (fc->init) {
   2917         /* Retreive Action profile index from entry. */
   2918         ap_idx = soc_mem_field32_get(unit, mem,
   2919                                      bufp,
   2920                                      soc_feature(unit, soc_feature_td3_style_fp) ? DATA_TYPEf :
   2921                                      ACTION_PROFILE_IDf);
   2922         /* Delete Entry Action Profile Memories for actions. */
   2923         BCM_IF_ERROR_RETURN(soc_profile_mem_delete(unit,
   2924                                &stage_fc->action_profile[fg->instance],
   2925                                ap_idx));
   2926     }
   2927 
   2928     /* Clear entry buffer. */
   2929     sal_memcpy(bufp, soc_mem_entry_null(unit, mem),
   2930                 soc_mem_entry_words(unit, mem) * sizeof(uint32));
   2931 
   2932     /* Install clear entry in hardware. */
   2933     BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL,
   2934                 fg->ext_codes[0].keygen_index, bufp));
   2935 
   2936     /* Enable Default Policy in Logical table entries. */
   2937     if (fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT) {
   2938         for (idx = 0; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) {
   2939             if (fg->presel_ent_arr[idx] != NULL) {
   2940                 f_presel = fg->presel_ent_arr[idx];
   2941 
   2942                 tcam_idx = f_presel->hw_index + f_presel->lt_fs->start_tcam_idx;
   2943 
   2944                 BCM_IF_ERROR_RETURN
   2945                     (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, fg->instance,
   2946                                                           _BCM_FIELD_MEM_TYPE_EM_LT,
   2947                                                           _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB,
   2948                                                           &lt_tcam_mem, NULL));
   2949                 /* Read entry into SW buffer. */
   2950                 BCM_IF_ERROR_RETURN(soc_mem_read(unit,
   2951                                                  lt_tcam_mem, MEM_BLOCK_ANY,
   2952                                                  tcam_idx, lt_entry));
   2953 
   2954                 /* Set entry valid bit status. */
   2955                 soc_mem_field32_set(unit, lt_tcam_mem,
   2956                                     lt_entry, DEFAULT_POLICY_ENABLEf, 0);
   2957 
   2958                 /* Install entry in hardware. */
   2959                 BCM_IF_ERROR_RETURN(soc_mem_write(unit, lt_tcam_mem, MEM_BLOCK_ALL,
   2960                                                               tcam_idx, lt_entry));
   2961             }
   2962         }
   2963     } else {
   2964         for (idx = 0; idx < (fg->lt_grp_status.entry_count); idx++) {
   2965             if (fg->lt_entry_arr[idx] == NULL) {
   2966                 continue;
   2967             }
   2968             f_lt_ent = fg->lt_entry_arr[idx];
   2969 
   2970             tcam_idx = f_lt_ent->index + f_lt_ent->lt_fs->start_tcam_idx;
   2971 
   2972             BCM_IF_ERROR_RETURN
   2973                 (_bcm_field_th_lt_tcam_policy_mem_get(unit, stage_fc, fg->instance,
   2974                                                       _BCM_FIELD_MEM_TYPE_EM_LT,
   2975                                                       _BCM_FIELD_MEM_VIEW_TYPE_TCAM_DATA_COMB,
   2976                                                       &lt_tcam_mem, NULL));
   2977 
   2978             /* Read entry into SW buffer. */
   2979             BCM_IF_ERROR_RETURN(soc_mem_read(unit,
   2980                                              lt_tcam_mem, MEM_BLOCK_ANY,
   2981                                              tcam_idx, lt_entry));
   2982 
   2983             /* Set entry valid bit status. */
   2984             soc_mem_field32_set(unit, lt_tcam_mem,
   2985                                 lt_entry, DEFAULT_POLICY_ENABLEf, 0);
   2986 
   2987             /* Install entry in hardware. */
   2988             BCM_IF_ERROR_RETURN(soc_mem_write(unit, lt_tcam_mem, MEM_BLOCK_ALL,
   2989                                                            tcam_idx, lt_entry));
   2990         }
   2991     }
   2992 
   2993     /* Clear Flags. */
   2994     for (part_idx = 0; part_idx < parts_count; part_idx++) {
   2995         f_ent_part = f_ent + part_idx;
   2996         /* CLear  Entry Flags. */
   2997         f_ent_part->flags |= _FP_ENTRY_DIRTY;
   2998         f_ent_part->flags &= ~_FP_ENTRY_INSTALLED;
   2999         f_ent_part->flags &= ~_FP_ENTRY_ENABLED;
   3000     }
   3001 
   3002     return (rv);
   3003 }
   3004 
   3005 /*
   3006  * Function:
   3007  *  _field_th_em_entry_install
   3008  * Purpose:
   3009  *  Install Exact Match Entry in Hardware.
   3010  * Parameters:
   3011  *  unit     - (IN) BCM device number.
   3012  *  f_ent    - (IN) Field Entry Pointer.
   3013  * Returns:
   3014  *  BCM_E_XXX
   3015  * Notes:
   3016  *  f_ent is primary entry part.
   3017  */
   3018 int
   3019 _field_th_em_entry_install(int unit, _field_entry_t *f_ent)
   3020 {
   3021     int rv = BCM_E_NONE;                /* Operational Status.       */
   3022     _field_stage_t *stage_fc = NULL;    /* Field Stage Control.      */
   3023     _field_group_t *fg = NULL;          /* Field Group Control.      */
   3024     _field_entry_t *f_ent_part = NULL;  /* Field Entry Part.         */
   3025     uint32 qp_idx = 0;                  /* Qos Actions Profile Index.*/
   3026     uint32 ap_idx = 0;                  /* Actions Profile Index.    */
   3027     int part_idx = 0;                   /* Entry Part Index.         */
   3028     int parts_count = 0;                /* Field Entry Parts Count.  */
   3029     soc_mem_t mem;                      /* Memory Identifier.        */
   3030     uint32 bufp[SOC_MAX_MEM_FIELD_WORDS] = {0}; /* Hardware Buffer*/
   3031 
   3032     /* Input Parameters Check. */
   3033     if ((NULL == f_ent) ||
   3034         (NULL == f_ent->group) ||
   3035         (NULL == f_ent->fs)) {
   3036         return (BCM_E_PARAM);
   3037     }
   3038 
   3039     /* Retreive Field Group */
   3040     fg = f_ent->group;
   3041 
   3042     /* Retreive Stage Control. */
   3043     BCM_IF_ERROR_RETURN(
   3044             _field_stage_control_get(unit, fg->stage_id, &stage_fc));
   3045 
   3046     /* Not applicable for non EM Stage. */
   3047     if (fg->stage_id != _BCM_FIELD_STAGE_EXACTMATCH) {
   3048         return (BCM_E_INTERNAL);
   3049     }
   3050     /* set Action profile index */
   3051     ap_idx = fg->action_profile_idx[0];
   3052     /* Default Entry Install. */
   3053     if (f_ent->flags & _FP_ENTRY_EXACT_MATCH_GROUP_DEFAULT) {
   3054         return _field_th_em_default_entry_install(unit, f_ent);
   3055     }
   3056     rv = _bcm_field_th_tcam_policy_mem_get(unit, f_ent,
   3057                                        &mem, &mem);
   3058     BCM_IF_ERROR_RETURN(rv);
   3059     /* Get number of entry parts. */
   3060     rv = _bcm_field_entry_tcam_parts_count(unit, fg->stage_id,
   3061                                            fg->flags, &parts_count);
   3062     BCM_IF_ERROR_RETURN(rv);
   3063 
   3064     /* Get Key If Not Installed, for all entry parts. */
   3065     if (!(f_ent->flags & _FP_ENTRY_INSTALLED)) {
   3066         for (part_idx = 0; part_idx < parts_count; part_idx++) {
   3067             f_ent_part = f_ent + part_idx;
   3068             BCM_IF_ERROR_RETURN(
   3069                     _bcm_field_qual_tcam_key_mask_get(unit, f_ent_part));
   3070         }
   3071     }
   3072 
   3073     /* Initialize exact match entries. */
   3074     sal_memcpy(bufp, soc_mem_entry_null(unit, mem),
   3075                 soc_mem_entry_words(unit, mem) * sizeof(uint32));
   3076 
   3077     /* Validate Parts and EM View. */
   3078     if ((((fg->em_mode == _FieldExactMatchMode128) ||
   3079           (fg->em_mode == _FieldExactMatchMode160)) &&
   3080           (parts_count != 1)) ||
   3081          ((fg->em_mode == _FieldExactMatchMode320) &&
   3082           (parts_count != 2))) {
   3083         return (BCM_E_INTERNAL);
   3084     }
   3085 
   3086     /* Set Action Buffer. */
   3087     rv = _field_th_em_entry_data_set(unit, f_ent, bufp, &qp_idx, &ap_idx);
   3088     BCM_IF_ERROR_RETURN(rv);
   3089 
   3090     if (soc_feature(unit, soc_feature_th3_style_fp)) {
   3091         rv = _field_th3_em_entry_set(unit, f_ent, mem, bufp, 0);
   3092     } else if (soc_feature(unit, soc_feature_td3_style_fp)) {
   3093         rv = _field_td3_em_entry_set(unit, f_ent, mem, bufp, 0);
   3094     } else {
   3095         rv = _field_th_em_entry_set(unit, f_ent, mem, bufp, 0);
   3096     }
   3097     BCM_IF_ERROR_RETURN(rv);
   3098     /* Write Entry In Hardware. */
   3099     rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, bufp);
   3100 
   3101     if (BCM_FAILURE(rv)) {
   3102         goto bcm_error;
   3103     }
   3104 
   3105     /* Copy into Hw Key. */
   3106     for (part_idx = 0; part_idx < parts_count; part_idx++) {
   3107         f_ent_part = f_ent + part_idx;
   3108         if(f_ent_part->tcam.key_hw == NULL) {
   3109             _FP_XGS3_ALLOC(f_ent_part->tcam.key_hw,
   3110                 f_ent_part->tcam.key_size, "EM_TCAM Key Alloc.");
   3111         }
   3112 
   3113         sal_memcpy(f_ent_part->tcam.key_hw,
   3114                 f_ent_part->tcam.key, f_ent_part->tcam.key_size);
   3115 
   3116         /* Set Entry Flags. */
   3117         f_ent_part->flags &= ~_FP_ENTRY_DIRTY;
   3118         f_ent_part->flags |= _FP_ENTRY_INSTALLED;
   3119         f_ent_part->flags |= _FP_ENTRY_ENABLED;
   3120     }
   3121 
   3122     /* Increment Hardware Count to count of entry parts. */
   3123     for (part_idx = 0; part_idx < parts_count; part_idx++) {
   3124         f_ent->fs->hw_ent_count++;
   3125     }
   3126 
   3127     return rv;
   3128 
   3129 bcm_error:
   3130     /* Delete QoS Action Profile. */
   3131     BCM_IF_ERROR_RETURN(soc_profile_mem_delete(unit,
   3132             &stage_fc->qos_action_profile[fg->instance],
   3133             qp_idx));
   3134     return (rv);
   3135 }
   3136 
   3137 /*
   3138  * Function:
   3139  *  _field_th_em_entry_remove
   3140  * Purpose:
   3141  *  Remove Exact Match Entry from hardware.
   3142  * Parameters:
   3143  *  unit     - (IN) BCM device number.
   3144  *  f_ent    - (IN) Field Entry.
   3145  * Returns:
   3146  *   BCM_E_XXX
   3147  * Notes:
   3148  *   Install and Enabled Flags will
   3149  *   be cleared by calling function.
   3150  */
   3151 int
   3152 _field_th_em_entry_remove(int unit, _field_entry_t *f_ent)
   3153 {
   3154     int rv = BCM_E_NONE;             /* Operational Status.         */
   3155     _field_control_t *fc = NULL;     /* Field Control Structure.    */
   3156     _field_stage_t *stage_fc = NULL; /* Field Stage Control.        */
   3157     _field_group_t *fg = NULL;       /* Field Group Control.        */
   3158     _field_entry_t *f_ent_part = NULL;
   3159                                      /* Field Entry Part.           */
   3160     int eindex = 0;                  /* Entry Index inn UFT memory. */
   3161     uint32 qp_idx = 0;               /* Qos Actions Profile Index.  */
   3162     int parts_count = 0;             /* Field entry parts count.    */
   3163     int part_idx = 0;                /* Entry Part Iterator.        */
   3164     soc_mem_t mem;                   /* Memory Identifier.          */
   3165     uint32 bufp[SOC_MAX_MEM_FIELD_WORDS] = {0}; /* Hardware Buffer  */
   3166 
   3167     /* Input Parameters Check. */
   3168     if ((NULL == f_ent) ||
   3169         (NULL == f_ent->group) ||
   3170         (NULL == f_ent->fs)) {
   3171         return (BCM_E_PARAM);
   3172     }
   3173 
   3174     /* If secondary part return none as uninstall
   3175      * has happened in primary part already.
   3176      */
   3177     if (f_ent->flags & _FP_ENTRY_SECONDARY) {
   3178         return (BCM_E_NONE);
   3179     }
   3180 
   3181     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   3182 
   3183     /* Retreive Field Group. */
   3184     fg = f_ent->group;
   3185 
   3186     /* Retreive Stage Control. */
   3187     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
   3188                                                  fg->stage_id, &stage_fc));
   3189 
   3190     /* Do nothing for non EM Stage. */
   3191     if (fg->stage_id != _BCM_FIELD_STAGE_EXACTMATCH) {
   3192         return (BCM_E_INTERNAL);
   3193     }
   3194 
   3195     /* Default Entry Remove. */
   3196     if (f_ent->flags & _FP_ENTRY_EXACT_MATCH_GROUP_DEFAULT) {
   3197         return _field_th_em_default_entry_remove(unit, f_ent);
   3198     }
   3199 
   3200     /* Check if HW key is present to remove entry. */
   3201     if (NULL == f_ent->tcam.key_hw) {
   3202         return (BCM_E_PARAM);
   3203     }
   3204     rv = _bcm_field_th_tcam_policy_mem_get(unit, f_ent,
   3205                                        &mem, &mem);
   3206     BCM_IF_ERROR_RETURN(rv);
   3207     /* Initialize exact match entries. */
   3208     sal_memcpy(bufp, soc_mem_entry_null(unit, mem),
   3209             soc_mem_entry_words(unit, mem) * sizeof(uint32));
   3210 
   3211     /* Get number of entry parts. */
   3212     rv = _bcm_field_entry_tcam_parts_count(unit, fg->stage_id,
   3213                                            fg->flags, &parts_count);
   3214     BCM_IF_ERROR_RETURN(rv);
   3215 
   3216     /* Validate Parts and EM View. */
   3217     if ((((fg->em_mode == _FieldExactMatchMode128) ||
   3218           (fg->em_mode == _FieldExactMatchMode160)) &&
   3219           (parts_count != 1)) ||
   3220          ((fg->em_mode == _FieldExactMatchMode320) &&
   3221           (parts_count != 2))) {
   3222         return (BCM_E_INTERNAL);
   3223     }
   3224     if (soc_feature(unit, soc_feature_th3_style_fp)) {
   3225         rv = _field_th3_em_entry_set(unit, f_ent, mem, bufp, 1);
   3226     } else if (soc_feature(unit, soc_feature_td3_style_fp)) {
   3227         rv = _field_td3_em_entry_set(unit, f_ent, mem, bufp, 1);
   3228     } else {
   3229         rv = _field_th_em_entry_set(unit, f_ent, mem, bufp, 1);
   3230     }
   3231     BCM_IF_ERROR_RETURN(rv);
   3232     /* Search Entry First Before Delete. */
   3233     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &eindex, bufp, bufp, 0);
   3234     if (BCM_FAILURE(rv)) {
   3235         if (fc->init == TRUE) {
   3236             return (rv);
   3237         } else {
   3238             /* If init is false it means field detach is happening.
   3239              * which might be due to rc or fp init.
   3240              * since soc init will clear all memories hence
   3241              * exact match memory will be cleared and search will
   3242              * not be a success. Since memory is cleared before itself
   3243              * so delete call should return success in such case.
   3244              */
   3245             rv = BCM_E_NONE;
   3246             return rv;
   3247         }
   3248     }
   3249 
   3250     /* Get Qos and Action Profile Index Allocated From Entry. */
   3251     if (fg->em_mode == _FieldExactMatchMode128) {
   3252         qp_idx = soc_mem_field32_get(unit, mem,
   3253                                      bufp, MODE128__QOS_PROFILE_IDf);
   3254     } else if (fg->em_mode == _FieldExactMatchMode160) {
   3255         qp_idx = soc_mem_field32_get(unit, mem,
   3256                                      bufp, MODE160__QOS_PROFILE_IDf);
   3257     } else if (fg->em_mode == _FieldExactMatchMode320) {
   3258         qp_idx = soc_mem_field32_get(unit, mem,
   3259                                      bufp, MODE320__QOS_PROFILE_IDf);
   3260     } else {
   3261         /* Invalid Exact Mode Mode. */
   3262         return (BCM_E_PARAM);
   3263     }
   3264 
   3265     /* Delete Entry From HW if found. */
   3266     BCM_IF_ERROR_RETURN(
   3267             soc_mem_delete(unit, mem, MEM_BLOCK_ALL, bufp));
   3268 
   3269     /* Delete Entry Profile Memories for actions. */
   3270     BCM_IF_ERROR_RETURN(soc_profile_mem_delete(unit,
   3271                            &stage_fc->qos_action_profile[fg->instance],
   3272                            qp_idx));
   3273 
   3274     /* Free Hw Entry Copy. */
   3275     for (part_idx = 0; part_idx < parts_count; part_idx++) {
   3276         f_ent_part = f_ent + part_idx;
   3277         sal_free(f_ent_part->tcam.key_hw);
   3278         f_ent_part->tcam.key_hw = NULL;
   3279 
   3280         /* Set Entry Flags. */
   3281         f_ent_part->flags |= _FP_ENTRY_DIRTY;
   3282         f_ent_part->flags &= ~_FP_ENTRY_INSTALLED;
   3283         f_ent_part->flags &= ~_FP_ENTRY_ENABLED;
   3284     }
   3285 
   3286     /* Decrement Hw Slice Entry Count to count of entry parts. */
   3287     for (part_idx = 0; part_idx < parts_count; part_idx++) {
   3288         f_ent->fs->hw_ent_count--;
   3289     }
   3290 
   3291     return rv;
   3292 }
   3293 
   3294 int
   3295 _bcm_field_th_em_entry_tcam_idx_get(int unit, _field_entry_t *f_ent, int *hw_index)
   3296 {
   3297     bcm_error_t rv = BCM_E_NONE;
   3298     _field_stage_t *stage_fc = NULL;
   3299     _field_group_t *fg = NULL;
   3300     exact_match_2_entry_t ebuf_nar;         /* Narrow Entry Buffer.      */
   3301     exact_match_4_entry_t ebuf_wide;        /* Wide Entry Buffer.        */
   3302     soc_mem_t mem = INVALIDm;               /* Memory Identifier.        */
   3303     uint32 tbuf[SOC_MAX_MEM_FIELD_WORDS] = {0};
   3304     /* Temp Buffer One.          */
   3305     uint32 *bufp = NULL;                    /* Hardware Buffer Ptr.      */
   3306 
   3307 
   3308     fg = f_ent->group;
   3309     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
   3310                      _BCM_FIELD_STAGE_EXACTMATCH, &stage_fc));
   3311     if ((fg->em_mode == _FieldExactMatchMode128) ||
   3312             (fg->em_mode == _FieldExactMatchMode160)) {
   3313         bufp = (uint32 *)&ebuf_nar;
   3314         sal_memset(bufp, 0, sizeof(exact_match_2_entry_t));
   3315         if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) {
   3316             mem = EXACT_MATCH_2m;
   3317         } else {
   3318             BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit,
   3319                         EXACT_MATCH_2m,
   3320                         fg->instance, &mem));
   3321         }
   3322     } else {
   3323         bufp = (uint32 *)&ebuf_wide;
   3324         sal_memset(bufp, 0, sizeof(exact_match_4_entry_t));
   3325         if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) {
   3326             mem = EXACT_MATCH_4m;
   3327         } else {
   3328             BCM_IF_ERROR_RETURN(_bcm_field_mem_instance_get(unit,
   3329                         EXACT_MATCH_4m,
   3330                         fg->instance, &mem));
   3331         }
   3332     }
   3333 
   3334     sal_memset(&ebuf_nar, 0x0, sizeof(exact_match_2_entry_t));
   3335     sal_memset(&ebuf_wide, 0x0, sizeof(exact_match_4_entry_t));
   3336 
   3337     if (soc_feature(unit, soc_feature_th3_style_fp)) {
   3338         rv = _field_th3_em_entry_set(unit, f_ent, mem, bufp, 0);
   3339     } else if (soc_feature(unit, soc_feature_td3_style_fp)) {
   3340         rv = _field_td3_em_entry_set(unit, f_ent, mem, bufp, 0);
   3341     } else {
   3342         rv = _field_th_em_entry_set(unit, f_ent, mem, bufp, 0);
   3343     }
   3344     BCM_IF_ERROR_RETURN(rv);
   3345     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, hw_index,
   3346                                 bufp, tbuf, 0 );
   3347     BCM_IF_ERROR_RETURN(rv);
   3348 
   3349     return rv;
   3350 }
   3351 
   3352 /*
   3353  * Function:
   3354  *  _field_th_em_entry_set
   3355  * Purpose:
   3356  *   Set Exact Match Policy Data.
   3357  * Parameters:
   3358  *   unit     - (IN) BCM device number.
   3359  *   f_ent    - (IN) Field Entry.
   3360  *   entbuf   - (OUT) Entry Policy Data Buffer.
   3361  *   qp_idx   - (OUT) Qos Actions Profile Index.
   3362  *   ap_idx   - (OUT) Action Profile Index.
   3363  * Returns:
   3364  *   BCM_E_XXX
   3365  * Notes:
   3366  */
   3367 int
   3368 _field_th_em_entry_set(int unit,
   3369                             _field_entry_t *f_ent,
   3370                             soc_mem_t mem,
   3371                             uint32 *bufp, int search_entry)
   3372 {
   3373     int rv = BCM_E_NONE;                /* Operational Status.       */
   3374     _field_group_t *fg = NULL;          /* Field Group Control.      */
   3375     _field_entry_t *f_ent_part = NULL;  /* Field Entry Part.         */
   3376     uint32 tbuf[SOC_MAX_MEM_FIELD_WORDS] = {0};
   3377                                         /* Temp Buffer One.          */
   3378     uint32 tbuf_temp[SOC_MAX_MEM_FIELD_WORDS] = {0};
   3379                                         /* Temp Buffer Two.          */
   3380     uint32                 *key;
   3381 
   3382     /* Input Parameters Check. */
   3383     if ((NULL == f_ent) ||
   3384         (NULL == f_ent->group) ||
   3385         (NULL == f_ent->fs)) {
   3386         return (BCM_E_PARAM);
   3387     }
   3388 
   3389     /* Retreive Field Group */
   3390     fg = f_ent->group;
   3391 
   3392     /* Assign the correct key */
   3393     if (1 == search_entry) {
   3394         key = f_ent->tcam.key_hw;
   3395     } else {
   3396         key = f_ent->tcam.key;
   3397     }
   3398 
   3399     /* Set Exact Match Entry */
   3400     if (fg->em_mode == _FieldExactMatchMode128) {
   3401 
   3402         soc_mem_field32_set(unit, mem, bufp, KEY_TYPE_0f, fg->em_mode);
   3403         soc_mem_field32_set(unit, mem, bufp, KEY_TYPE_1f, fg->em_mode);
   3404         soc_mem_field32_set(unit, mem, bufp, VALID_0f, 1);
   3405         soc_mem_field32_set(unit, mem, bufp, VALID_1f, 1);
   3406         rv = _bcm_field_th_val_get(key, tbuf, 0,
   3407                                    EM_MODE128_KEY_PART0_SIZE);
   3408         BCM_IF_ERROR_RETURN(rv);
   3409         soc_mem_field_set(unit, mem, bufp, MODE128__KEY_0_ONLYf, tbuf);
   3410         rv = _bcm_field_th_val_get(key, tbuf,
   3411                                    EM_MODE128_KEY_PART0_SIZE,
   3412                                    EM_MODE128_KEY_PART1_SIZE);
   3413         BCM_IF_ERROR_RETURN(rv);
   3414         soc_mem_field_set(unit, mem, bufp, MODE128__KEY_1_ONLYf, tbuf);
   3415 
   3416     } else if (fg->em_mode == _FieldExactMatchMode160) {
   3417 
   3418         soc_mem_field32_set(unit, mem, bufp, KEY_TYPE_0f, fg->em_mode);
   3419         soc_mem_field32_set(unit, mem, bufp, KEY_TYPE_1f, fg->em_mode);
   3420         soc_mem_field32_set(unit, mem, bufp, VALID_0f, 1);
   3421         soc_mem_field32_set(unit, mem, bufp, VALID_1f, 1);
   3422         rv = _bcm_field_th_val_get(key, tbuf, 0,
   3423                                    EM_MODE160_KEY_PART0_SIZE);
   3424         BCM_IF_ERROR_RETURN(rv);
   3425         soc_mem_field_set(unit, mem, bufp, MODE160__KEY_0_ONLYf, tbuf);
   3426         rv = _bcm_field_th_val_get(key, tbuf,
   3427                                    EM_MODE160_KEY_PART0_SIZE,
   3428                                    EM_MODE160_KEY_PART1_SIZE);
   3429         BCM_IF_ERROR_RETURN(rv);
   3430         soc_mem_field_set(unit, mem, bufp, MODE160__KEY_1_ONLYf, tbuf);
   3431 
   3432     } else if (fg->em_mode == _FieldExactMatchMode320) {
   3433 
   3434         soc_mem_field32_set(unit, mem, bufp, KEY_TYPE_0f, fg->em_mode);
   3435         soc_mem_field32_set(unit, mem, bufp, KEY_TYPE_1f, fg->em_mode);
   3436         soc_mem_field32_set(unit, mem, bufp, KEY_TYPE_2f, fg->em_mode);
   3437         soc_mem_field32_set(unit, mem, bufp, KEY_TYPE_3f, fg->em_mode);
   3438         soc_mem_field32_set(unit, mem, bufp, VALID_0f, 1);
   3439         soc_mem_field32_set(unit, mem, bufp, VALID_1f, 1);
   3440         soc_mem_field32_set(unit, mem, bufp, VALID_2f, 1);
   3441         soc_mem_field32_set(unit, mem, bufp, VALID_3f, 1);
   3442         rv = _bcm_field_th_val_get(key, tbuf, 0,
   3443                                    EM_MODE320_KEY_PART0_SIZE);
   3444         BCM_IF_ERROR_RETURN(rv);
   3445         soc_mem_field_set(unit, mem, bufp, MODE320__KEY_0_ONLYf, tbuf);
   3446         rv = _bcm_field_th_val_get(key, tbuf,
   3447                                    EM_MODE320_KEY_PART0_SIZE,
   3448                                    (EM_ENTRY_PART0_KEYSIZE -
   3449                                     EM_MODE320_KEY_PART0_SIZE));
   3450         BCM_IF_ERROR_RETURN(rv);
   3451 
   3452         /* Key From Second Entry Part. */
   3453         f_ent_part = f_ent + 1;
   3454 
   3455         /* Assign the correct key */
   3456         if (1 == search_entry) {
   3457             key = f_ent_part->tcam.key_hw;
   3458         } else {
   3459             key = f_ent_part->tcam.key;
   3460         }
   3461         if (key == NULL) {
   3462             return BCM_E_PARAM;
   3463         }
   3464         rv = _bcm_field_th_val_get(key, tbuf_temp, 0,
   3465                                    (EM_MODE320_KEY_PART1_SIZE -
   3466                                    (EM_ENTRY_PART0_KEYSIZE -
   3467                                     EM_MODE320_KEY_PART0_SIZE)));
   3468         BCM_IF_ERROR_RETURN(rv);
   3469         rv = _bcm_field_th_val_set(tbuf, tbuf_temp,
   3470                                    (EM_ENTRY_PART0_KEYSIZE -
   3471                                     EM_MODE320_KEY_PART0_SIZE),
   3472                                    (EM_MODE320_KEY_PART1_SIZE -
   3473                                    (EM_ENTRY_PART0_KEYSIZE -
   3474                                     EM_MODE320_KEY_PART0_SIZE)));
   3475         BCM_IF_ERROR_RETURN(rv);
   3476         soc_mem_field_set(unit, mem, bufp, MODE320__KEY_1_ONLYf, tbuf);
   3477         rv = _bcm_field_th_val_get(key, tbuf,
   3478                                    (EM_MODE320_KEY_PART1_SIZE -
   3479                                    (EM_ENTRY_PART0_KEYSIZE -
   3480                                     EM_MODE320_KEY_PART0_SIZE)),
   3481                                     EM_MODE320_KEY_PART2_SIZE);
   3482         BCM_IF_ERROR_RETURN(rv);
   3483         soc_mem_field_set(unit, mem, bufp, MODE320__KEY_2_ONLYf, tbuf);
   3484         rv = _bcm_field_th_val_get(key, tbuf,
   3485                                    ((EM_MODE320_KEY_PART1_SIZE -
   3486                                     (EM_ENTRY_PART0_KEYSIZE -
   3487                                      EM_MODE320_KEY_PART0_SIZE)) +
   3488                                      EM_MODE320_KEY_PART2_SIZE),
   3489                                      EM_MODE320_KEY_PART3_SIZE);
   3490         BCM_IF_ERROR_RETURN(rv);
   3491         soc_mem_field_set(unit, mem, bufp, MODE320__KEY_3_ONLYf, tbuf);
   3492 
   3493     } else {
   3494         /* Invalid Exact Match Mode. */
   3495         return BCM_E_PARAM;
   3496     }
   3497     return rv;
   3498 }
   3499 /*
   3500  * Function:
   3501  *  _field_td3_em_entry_set
   3502  * Purpose:
   3503  *   Set Exact Match Policy Data.
   3504  * Parameters:
   3505  *   unit     - (IN) BCM device number.
   3506  *   f_ent    - (IN) Field Entry.
   3507  *   entbuf   - (OUT) Entry Policy Data Buffer.
   3508  *   qp_idx   - (OUT) Qos Actions Profile Index.
   3509  *   ap_idx   - (OUT) Action Profile Index.
   3510  * Returns:
   3511  *   BCM_E_XXX
   3512  * Notes:
   3513  */
   3514 int
   3515 _field_td3_em_entry_set(int unit,
   3516                             _field_entry_t *f_ent,
   3517                             soc_mem_t mem,
   3518                             uint32 *bufp, int search_entry)
   3519 {
   3520     int rv = BCM_E_NONE;                /* Operational Status.       */
   3521     _field_group_t *fg = NULL;          /* Field Group Control.      */
   3522     _field_entry_t *f_ent_part = NULL;  /* Field Entry Part.         */
   3523     uint32 tbuf[SOC_MAX_MEM_FIELD_WORDS] = {0};
   3524                                         /* Temp Buffer One.          */
   3525     uint32 tbuf_temp[SOC_MAX_MEM_FIELD_WORDS] = {0};
   3526                                         /* Temp Buffer Two.          */
   3527     uint32                 *key;
   3528 
   3529     /* Input Parameters Check. */
   3530     if ((NULL == f_ent) ||
   3531         (NULL == f_ent->group) ||
   3532         (NULL == f_ent->fs)) {
   3533         return (BCM_E_PARAM);
   3534     }
   3535 
   3536     /* Retreive Field Group */
   3537     fg = f_ent->group;
   3538 
   3539     /* Assign the correct key */
   3540     if (1 == search_entry) {
   3541         key = f_ent->tcam.key_hw;
   3542     } else {
   3543         key = f_ent->tcam.key;
   3544     }
   3545 
   3546     soc_mem_field32_set(unit, mem, bufp, KEY_TYPEf, fg->em_mode);
   3547     /* Set Exact Match Entry */
   3548     if (fg->em_mode == _FieldExactMatchMode128) {
   3549 
   3550         if (0 == search_entry) {
   3551             soc_mem_field32_set(unit, mem, bufp, BASE_VALID_0f, 3);
   3552             soc_mem_field32_set(unit, mem, bufp, BASE_VALID_1f, 4);
   3553         }
   3554         rv = _bcm_field_th_val_get(key, tbuf, 0,
   3555                                    TD3_EM_MODE128_KEY_PART0_SIZE);
   3556         BCM_IF_ERROR_RETURN(rv);
   3557         soc_mem_field_set(unit, mem, bufp, MODE128__KEY_0_ONLYf, tbuf);
   3558         rv = _bcm_field_th_val_get(key, tbuf,
   3559                                    TD3_EM_MODE128_KEY_PART0_SIZE,
   3560                                    TD3_EM_MODE128_KEY_PART1_SIZE);
   3561         BCM_IF_ERROR_RETURN(rv);
   3562         soc_mem_field_set(unit, mem, bufp, MODE128__KEY_1_ONLYf, tbuf);
   3563 
   3564     } else if (fg->em_mode == _FieldExactMatchMode160) {
   3565 
   3566         if (0 == search_entry) {
   3567             soc_mem_field32_set(unit, mem, bufp, BASE_VALID_0f, 3);
   3568             soc_mem_field32_set(unit, mem, bufp, BASE_VALID_1f, 4);
   3569         }
   3570         rv = _bcm_field_th_val_get(key, tbuf, 0,
   3571                                    TD3_EM_MODE160_KEY_PART0_SIZE);
   3572         BCM_IF_ERROR_RETURN(rv);
   3573         soc_mem_field_set(unit, mem, bufp, MODE160__KEY_0_ONLYf, tbuf);
   3574         rv = _bcm_field_th_val_get(key, tbuf,
   3575                                    TD3_EM_MODE160_KEY_PART0_SIZE,
   3576                                    TD3_EM_MODE160_KEY_PART1_SIZE);
   3577         BCM_IF_ERROR_RETURN(rv);
   3578         soc_mem_field_set(unit, mem, bufp, MODE160__KEY_1_ONLYf, tbuf);
   3579 
   3580     } else if (fg->em_mode == _FieldExactMatchMode320) {
   3581 
   3582         if (0 == search_entry) {
   3583             soc_mem_field32_set(unit, mem, bufp, BASE_VALID_0f, 5);
   3584             soc_mem_field32_set(unit, mem, bufp, BASE_VALID_1f, 6);
   3585             soc_mem_field32_set(unit, mem, bufp, BASE_VALID_2f, 6);
   3586             soc_mem_field32_set(unit, mem, bufp, BASE_VALID_3f, 6);
   3587         }
   3588         rv = _bcm_field_th_val_get(key, tbuf, 0,
   3589                                    TD3_EM_MODE320_KEY_PART0_SIZE);
   3590         BCM_IF_ERROR_RETURN(rv);
   3591         soc_mem_field_set(unit, mem, bufp, MODE320__KEY_0_ONLYf, tbuf);
   3592         rv = _bcm_field_th_val_get(key, tbuf,
   3593                                    TD3_EM_MODE320_KEY_PART0_SIZE,
   3594                                    (EM_ENTRY_PART0_KEYSIZE -
   3595                                     TD3_EM_MODE320_KEY_PART0_SIZE));
   3596         BCM_IF_ERROR_RETURN(rv);
   3597 
   3598         /* Key From Second Entry Part. */
   3599         f_ent_part = f_ent + 1;
   3600 
   3601         /* Assign the correct key */
   3602         if (1 == search_entry) {
   3603             key = f_ent_part->tcam.key_hw;
   3604         } else {
   3605             key = f_ent_part->tcam.key;
   3606         }
   3607 
   3608         if (NULL == key) {
   3609             return BCM_E_PARAM;
   3610         }
   3611 
   3612         rv = _bcm_field_th_val_get(key, tbuf_temp, 0,
   3613                                    (TD3_EM_MODE320_KEY_PART1_SIZE -
   3614                                    (EM_ENTRY_PART0_KEYSIZE -
   3615                                     TD3_EM_MODE320_KEY_PART0_SIZE)));
   3616         BCM_IF_ERROR_RETURN(rv);
   3617         rv = _bcm_field_th_val_set(tbuf, tbuf_temp,
   3618                                    (EM_ENTRY_PART0_KEYSIZE -
   3619                                     TD3_EM_MODE320_KEY_PART0_SIZE),
   3620                                    (TD3_EM_MODE320_KEY_PART1_SIZE -
   3621                                    (EM_ENTRY_PART0_KEYSIZE -
   3622                                     TD3_EM_MODE320_KEY_PART0_SIZE)));
   3623         BCM_IF_ERROR_RETURN(rv);
   3624         soc_mem_field_set(unit, mem, bufp, MODE320__KEY_1_ONLYf, tbuf);
   3625         rv = _bcm_field_th_val_get(key, tbuf,
   3626                                    (TD3_EM_MODE320_KEY_PART1_SIZE -
   3627                                    (EM_ENTRY_PART0_KEYSIZE -
   3628                                     TD3_EM_MODE320_KEY_PART0_SIZE)),
   3629                                     TD3_EM_MODE320_KEY_PART2_SIZE);
   3630         BCM_IF_ERROR_RETURN(rv);
   3631         soc_mem_field_set(unit, mem, bufp, MODE320__KEY_2_ONLYf, tbuf);
   3632         rv = _bcm_field_th_val_get(key, tbuf,
   3633                                    ((TD3_EM_MODE320_KEY_PART1_SIZE -
   3634                                     (EM_ENTRY_PART0_KEYSIZE -
   3635                                      TD3_EM_MODE320_KEY_PART0_SIZE)) +
   3636                                      TD3_EM_MODE320_KEY_PART2_SIZE),
   3637                                      TD3_EM_MODE320_KEY_PART3_SIZE);
   3638         BCM_IF_ERROR_RETURN(rv);
   3639         soc_mem_field_set(unit, mem, bufp, MODE320__KEY_3_ONLYf, tbuf);
   3640 
   3641     } else {
   3642         /* Invalid Exact Match Mode. */
   3643         rv = BCM_E_PARAM;
   3644     }
   3645     return rv;
   3646 }
   3647 
   3648 /*
   3649  * Function:
   3650  *  _field_th3_em_entry_set
   3651  * Purpose:
   3652  *  Set Exact Match Policy Data.
   3653  * Parameters:
   3654  *  unit     - (IN) BCM device number.
   3655  *  f_ent    - (IN) Field Entry.
   3656  *  entbuf   - (OUT) Entry Policy Data Buffer.
   3657  *  qp_idx   - (OUT) Qos Actions Profile Index.
   3658  *  ap_idx   - (OUT) Action Profile Index.
   3659  * Returns:
   3660  *  BCM_E_XXX
   3661  * Notes:
   3662  */
   3663 int
   3664 _field_th3_em_entry_set(int unit,
   3665                         _field_entry_t *f_ent,
   3666                         soc_mem_t mem,
   3667                         uint32 *bufp, int search_entry)
   3668 {
   3669     int rv = BCM_E_NONE;                /* Operational Status.       */
   3670     _field_group_t *fg = NULL;          /* Field Group Control.      */
   3671     _field_entry_t *f_ent_part = NULL;  /* Field Entry Part.         */
   3672     uint32 tbuf[SOC_MAX_MEM_FIELD_WORDS] = {0};
   3673                                         /* Temp Buffer One.          */
   3674     uint32 tbuf_temp[SOC_MAX_MEM_FIELD_WORDS] = {0};
   3675                                         /* Temp Buffer Two.          */
   3676     uint32                 *key;
   3677 
   3678     /* Input Parameters Check. */
   3679     if ((NULL == f_ent) ||
   3680         (NULL == f_ent->group) ||
   3681         (NULL == f_ent->fs)) {
   3682         return (BCM_E_PARAM);
   3683     }
   3684 
   3685     /* Retreive Field Group */
   3686     fg = f_ent->group;
   3687 
   3688     /* Assign the correct key */
   3689     if (1 == search_entry) {
   3690         key = f_ent->tcam.key_hw;
   3691     } else {
   3692         key = f_ent->tcam.key;
   3693     }
   3694 
   3695     soc_mem_field32_set(unit, mem, bufp, KEY_TYPEf, fg->em_mode);
   3696     /* Set Exact Match Entry */
   3697     if (fg->em_mode == _FieldExactMatchMode128) {
   3698         if (0 == search_entry) {
   3699             soc_mem_field32_set(unit, mem, bufp, BASE_VALID_0f, 1);
   3700             soc_mem_field32_set(unit, mem, bufp, BASE_VALID_1f, 2);
   3701         }
   3702         rv = _bcm_field_th_val_get(key, tbuf, 0,
   3703                                    TH3_EM_MODE128_KEY_PART0_SIZE);
   3704         soc_mem_field_set(unit, mem, bufp, MODE128__KEY_0_ONLYf, tbuf);
   3705         rv = _bcm_field_th_val_get(key, tbuf,
   3706                                    TH3_EM_MODE128_KEY_PART0_SIZE,
   3707                                    TH3_EM_MODE128_KEY_PART1_SIZE);
   3708         soc_mem_field_set(unit, mem, bufp, MODE128__KEY_1_ONLYf, tbuf);
   3709     } else if (fg->em_mode == _FieldExactMatchMode160) {
   3710         if (0 == search_entry) {
   3711             soc_mem_field32_set(unit, mem, bufp, BASE_VALID_0f, 1);
   3712             soc_mem_field32_set(unit, mem, bufp, BASE_VALID_1f, 2);
   3713         }
   3714         rv = _bcm_field_th_val_get(key, tbuf, 0,
   3715                                    TH3_EM_MODE160_KEY_PART0_SIZE);
   3716         soc_mem_field_set(unit, mem, bufp, MODE160__KEY_0_ONLYf, tbuf);
   3717         rv = _bcm_field_th_val_get(key, tbuf,
   3718                                    TH3_EM_MODE160_KEY_PART0_SIZE,
   3719                                    TH3_EM_MODE160_KEY_PART1_SIZE);
   3720         soc_mem_field_set(unit, mem, bufp, MODE160__KEY_1_ONLYf, tbuf);
   3721     } else if (fg->em_mode == _FieldExactMatchMode320) {
   3722         if (0 == search_entry) {
   3723             soc_mem_field32_set(unit, mem, bufp, BASE_VALID_0f, 1);
   3724             soc_mem_field32_set(unit, mem, bufp, BASE_VALID_1f, 2);
   3725             soc_mem_field32_set(unit, mem, bufp, BASE_VALID_2f, 2);
   3726             soc_mem_field32_set(unit, mem, bufp, BASE_VALID_3f, 7);
   3727         }
   3728         rv = _bcm_field_th_val_get(key, tbuf, 0,
   3729                                    TH3_EM_MODE320_KEY_PART0_SIZE);
   3730         soc_mem_field_set(unit, mem, bufp, MODE320__KEY_0_ONLYf, tbuf);
   3731         rv = _bcm_field_th_val_get(key, tbuf,
   3732                                    TH3_EM_MODE320_KEY_PART0_SIZE,
   3733                                   (EM_ENTRY_PART0_KEYSIZE -
   3734                                    TH3_EM_MODE320_KEY_PART0_SIZE));
   3735 
   3736         /* Key From Second Entry Part. */
   3737         f_ent_part = f_ent + 1;
   3738 
   3739         /* Assign the correct key */
   3740         if (1 == search_entry) {
   3741             key = f_ent_part->tcam.key_hw;
   3742         } else {
   3743             key = f_ent_part->tcam.key;
   3744         }
   3745 
   3746         rv = _bcm_field_th_val_get(key, tbuf_temp, 0,
   3747                                   (TH3_EM_MODE320_KEY_PART1_SIZE -
   3748                                   (EM_ENTRY_PART0_KEYSIZE -
   3749                                    TH3_EM_MODE320_KEY_PART0_SIZE)));
   3750         rv = _bcm_field_th_val_set(tbuf, tbuf_temp,
   3751                                   (EM_ENTRY_PART0_KEYSIZE -
   3752                                    TH3_EM_MODE320_KEY_PART0_SIZE),
   3753                                   (TH3_EM_MODE320_KEY_PART1_SIZE -
   3754                                   (EM_ENTRY_PART0_KEYSIZE -
   3755                                    TH3_EM_MODE320_KEY_PART0_SIZE)));
   3756         soc_mem_field_set(unit, mem, bufp, MODE320__KEY_1_ONLYf, tbuf);
   3757         rv = _bcm_field_th_val_get(key, tbuf,
   3758                                   (TH3_EM_MODE320_KEY_PART1_SIZE -
   3759                                   (EM_ENTRY_PART0_KEYSIZE -
   3760                                    TH3_EM_MODE320_KEY_PART0_SIZE)),
   3761                                    TH3_EM_MODE320_KEY_PART2_SIZE);
   3762         soc_mem_field_set(unit, mem, bufp, MODE320__KEY_2_ONLYf, tbuf);
   3763     } else {
   3764         /* Invalid Exact Match Mode. */
   3765         rv = BCM_E_PARAM;
   3766     }
   3767     return rv;
   3768 }
   3769 
   3770 #else /* BCM_TOMAHAWK_SUPPORT && BCM_FIELD_SUPPORT */
   3771 int _th_field_not_empty;
   3772 #endif /* !BCM_TOMAHAWK_SUPPORT && !BCM_FIELD_SUPPORT */