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_common.c (1769010B)


      1 /* 
      2  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      3  * 
      4  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      5  *
      6  * Module: Field Processor APIs
      7  *
      8  * Purpose:
      9  *     API for Field Processor (FP) for XGS3 family and later.
     10  */
     11 /**/
     12 #include <shared/bsl.h>
     13 
     14 #include <soc/drv.h>
     15 #include <soc/scache.h>
     16 #include <soc/cmic.h>
     17 #include <soc/field.h>
     18 #include <shared/pbmp.h>
     19 #include <bcm/field.h>
     20 #include <bcm/error.h>
     21 #include <bcm/mirror.h>
     22 #include <bcm/link.h>
     23 #include <bcm_int/esw/link.h>
     24 #include <bcm/l3.h>
     25 #include <bcm_int/esw/l3.h>
     26 #include <bcm_int/esw/tsn.h>
     27 #ifdef BCM_TRIDENT2_SUPPORT
     28 #include <bcm/nat.h>
     29 #include <bcm_int/esw/nat.h>
     30 #endif
     31 
     32 #if defined(BCM_FIREBOLT_SUPPORT)
     33 #include <bcm_int/esw/firebolt.h>
     34 #endif
     35 
     36 #if defined(BCM_RAPTOR_SUPPORT)
     37 #include <bcm_int/esw/raptor.h>
     38 #endif
     39 
     40 #if defined(BCM_TRX_SUPPORT)
     41 #include <bcm_int/esw/trx.h>
     42 #endif
     43 
     44 #if defined(BCM_TRIUMPH_SUPPORT)
     45 #include <bcm_int/esw/triumph.h>
     46 #endif
     47 
     48 #if defined(BCM_HGPROXY_COE_SUPPORT)
     49 #include <bcm_int/esw/xgs5.h>
     50 #endif /* BCM_HGPROXY_COE_SUPPORT */
     51 
     52 #include <bcm_int/esw/field.h>
     53 #include <bcm_int/esw/range.h>
     54 #include <bcm_int/esw/triumph2.h>
     55 #include <bcm_int/esw/triumph3.h>
     56 #include <bcm_int/esw/trident.h>
     57 #include <bcm_int/esw/katana.h>
     58 #include <bcm_int/esw/trident2.h>
     59 #include <bcm_int/esw/tomahawk.h>
     60 #include <bcm_int/common/multicast.h>
     61 
     62 #if defined(BCM_ENDURO_SUPPORT)
     63 #include <bcm_int/esw/enduro.h>
     64 #endif
     65 
     66 #if defined(BCM_HURRICANE_SUPPORT)
     67 #include <bcm_int/esw/hurricane.h>
     68 #endif
     69 
     70 #if defined(BCM_HURRICANE2_SUPPORT)
     71 #include <bcm_int/esw/hurricane2.h>
     72 #endif
     73 
     74 #if defined(BCM_KATANA2_SUPPORT)
     75 #include <bcm_int/esw/katana2.h>
     76 #endif /* BCM_KATANA2_SUPPORT */
     77 
     78 #if defined(BCM_SABER2_SUPPORT)
     79 #include <bcm_int/esw/saber2.h>
     80 #endif /* BCM_SABER2_SUPPORT */
     81 
     82 #include <bcm_int/esw/scorpion.h>
     83 #include <bcm_int/esw/trunk.h>
     84 #include <bcm_int/esw/mirror.h>
     85 #include <bcm_int/esw/stack.h>
     86 #include <bcm_int/esw/port.h>
     87 #include <bcm_int/control.h>
     88 #include <bcm_int/esw/virtual.h>
     89 #include <bcm_int/esw_dispatch.h>
     90 #include <bcm_int/esw/ecn.h>
     91 #include <bcm_int/esw/keygen_api.h>
     92 
     93 
     94 #if defined(BCM_ESW_SUPPORT)
     95 #include <bcm_int/esw/flex_ctr.h>
     96 #include <bcm_int/esw/xgs4.h>
     97 #endif
     98 
     99 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
    100 #include <bcm_int/esw/policer.h>
    101 #endif
    102 #ifdef BCM_GREYHOUND_SUPPORT
    103 #include <bcm_int/esw/greyhound.h>
    104 #endif /* BCM_GREYHOUND_SUPPORT */
    105 #ifdef BCM_HURRICANE3_SUPPORT
    106 #include <bcm_int/esw/hurricane3.h>
    107 #include <bcm_int/esw/flowcnt.h>
    108 #endif /* BCM_HURRICANE3_SUPPORT */
    109 #ifdef BCM_GREYHOUND2_SUPPORT
    110 #include <bcm_int/esw/greyhound2.h>
    111 #endif /* BCM_GREYHOUND2_SUPPORT */
    112 #if defined(INCLUDE_REGEX)
    113 #include <bcm_int/esw/bregex.h>
    114 #endif
    115 #ifdef BCM_TOMAHAWK3_SUPPORT
    116 #include <bcm_int/esw/tomahawk3.h>
    117 #endif /* BCM_TOMAHAWK3_SUPPORT */
    118 #if defined(BCM_HELIX5_SUPPORT)
    119 #include <bcm_int/esw/helix5.h>
    120 #endif /* BCM_HELIX5_SUPPORT */
    121 
    122 #if defined(BCM_MONTEREY_SUPPORT) && defined(INCLUDE_XFLOW_MACSEC)
    123 #include <bcm_int/common/xflow_macsec_cmn.h>
    124 #endif
    125 
    126 #if defined(BCM_ESW_SUPPORT)
    127 #ifdef BCM_FIELD_SUPPORT
    128 
    129 #define SAL_ALLOC_T(t, n)  ((t *) sal_alloc((n) * sizeof(t), " ")) /* <HP/> */
    130 
    131 #define BCM_POLICER_XGS_NOSUPPORT_FLAGS (BCM_POLICER_DROP_RED | \
    132                                          BCM_POLICER_MACRO    | \
    133                                          BCM_POLICER_EGRESS   | \
    134                                          BCM_POLICER_REPLACE_SHARED)
    135 
    136 #define _FIELD_IS_CLASS_ID_B_SEL(_sec_sel_)    ((_sec_sel_ == _bcmFieldSliceSelEgrClassIdBF1) \
    137                                              || (_sec_sel_ == _bcmFieldSliceSelEgrClassIdBF2) \
    138                                              || (_sec_sel_ == _bcmFieldSliceSelEgrClassIdBF3) \
    139                                              || (_sec_sel_ == _bcmFieldSliceSelEgrClassIdBF4) \
    140                                              || (_sec_sel_ == _bcmFieldSliceSelEgrClassIdBF5) \
    141                                              || (_sec_sel_ == _bcmFieldSliceSelEgrClassIdBF6) \
    142                                              || (_sec_sel_ == _bcmFieldSliceSelEgrClassIdBF7) \
    143                                              || (_sec_sel_ == _bcmFieldSliceSelEgrClassIdBF8))
    144 
    145 #define _FP_ENTRY_MOVE_DOWN 0x01
    146 #define _FP_ENTRY_MOVE_UP 0x02
    147 
    148 int _field_fill_slice_array (int unit, _field_group_t *fg, uint8 *slice_array);
    149 /* Static variables */
    150 int prio_set_with_no_free_entries[BCM_MAX_NUM_UNITS] = {FALSE};
    151 
    152 int
    153 _bcm_field_entry_copy_id(int unit,
    154                             bcm_field_entry_t src_entry,
    155                             bcm_field_entry_t dst_entry,
    156                             uint32 flags);
    157 
    158 int
    159 _field_tcam_policy_install(int unit, bcm_field_entry_t entry);
    160 
    161 int
    162 _field_entry_prio_set(int unit, bcm_field_entry_t entry, int prio);
    163 
    164 int
    165 _field_entry_create_id(int unit, bcm_field_group_t group,
    166                        bcm_field_entry_t entry);
    167 
    168 STATIC int
    169 _field_internal_backup_entry_delete(int unit, bcm_field_entry_t temp_entry);
    170 
    171 #if defined(BCM_TRX_SUPPORT)
    172 STATIC
    173 int _bcm_field_group_entry_port_update(int unit,
    174                                         _field_group_t *fg,
    175                                         bcm_pbmp_t detached_pbmp,
    176                                         bcm_pbmp_t attached_pbmp);
    177 #endif
    178 
    179 #if defined(BCM_TOMAHAWK_SUPPORT)
    180 STATIC
    181 int _bcm_field_group_entry_pipe_port_update(int unit,
    182                                             _field_group_t *fg,
    183                                             bcm_pbmp_t detached_pbmp,
    184                                             bcm_pbmp_t attached_pbmp);
    185 #endif
    186 STATIC
    187 int _bcm_field_slice_idx_allocate(int unit,
    188                                   _field_stage_t *stage_fc,
    189                                   _field_group_t *fg,
    190                                   _field_slice_t *fs,
    191                                   uint32 *slice_idx);
    192 
    193 STATIC
    194 int _field_slice_index_type_get(int unit,
    195                                 _field_group_t *fg,
    196                                 _field_slice_t *fs,
    197                                 int slice_idx,
    198                                 int *slice_idx_type);
    199 STATIC
    200 int _field_slice_next_match_index_get(int unit, _field_group_t *fg,
    201                                       _field_slice_t *fs, int start_idx,
    202                                       int end_idx, int dir, int *next_index);
    203 
    204 STATIC int
    205 _field_entry_shift_params_get(int unit, _field_group_t *fg,
    206                              _field_entry_t *f_ent, int prio,
    207                              _bcm_field_entry_shift_params_t *sp);
    208 
    209 STATIC int
    210 _field_multimode_slice_idx_alloc(int unit,
    211             _field_stage_t *stage_fc, _field_group_t *fg,
    212             _field_slice_t *fs, uint32 *slice_idx);
    213 
    214 STATIC int
    215 _field_multimode_slice_entry_move(int unit, _field_slice_t *fs,
    216             _field_entry_t *f_ent, int amount);
    217 
    218 STATIC int
    219 _field_multimode_slice_entry_shift_down(int unit, _field_group_t *fg,
    220             _field_slice_t *target_fs, uint16 target_idx,
    221             _field_slice_t *next_null_fs, uint16 next_null_idx);
    222 
    223 STATIC int
    224 _field_multimode_slice_entry_shift_up(int unit, _field_group_t *fg,
    225             _field_slice_t *target_fs, uint16 target_idx,
    226             _field_slice_t *prev_null_fs, uint16 prev_null_idx);
    227 
    228 STATIC int
    229 _field_multimode_slice_entry_compress(int unit, _field_slice_t *fs);
    230 
    231 STATIC int
    232 _field_meter_hw_clear(int unit, _field_entry_t *f_ent,
    233                                  int old_hw_index, bcm_policer_mode_t old_mode,
    234                                  int old_pool_index, uint32 old_hw_flags);
    235 
    236 
    237 extern soc_field_t udf_fields_f[][4];
    238 uint8 wb_write_disable = 0;
    239 
    240 #ifdef BCM_WARM_BOOT_SUPPORT
    241 static const uint32 _field_sdk_warmboot_version[][2] = {
    242        {((6 << 16) | (4 << 8) | 7 ), BCM_FIELD_WB_VERSION_1_11},
    243        {((6 << 16) | (4 << 8) | 8 ), BCM_FIELD_WB_VERSION_1_14},
    244        {((6 << 16) | (4 << 8) | 9 ), BCM_FIELD_WB_VERSION_1_15},
    245        {((6 << 16) | (4 << 8) | 10 ), BCM_FIELD_WB_VERSION_1_16},
    246        {((6 << 16) | (4 << 8) | 11 ), BCM_FIELD_WB_VERSION_1_18},
    247        {((6 << 16) | (5 << 8) | 0 ), BCM_FIELD_WB_VERSION_1_11},
    248        {((6 << 16) | (5 << 8) | 1 ), BCM_FIELD_WB_VERSION_1_12},
    249        {((6 << 16) | (5 << 8) | 2 ), BCM_FIELD_WB_VERSION_1_15},
    250        {((6 << 16) | (5 << 8) | 3 ), BCM_FIELD_WB_VERSION_1_18},
    251        {((6 << 16) | (5 << 8) | 4 ), BCM_FIELD_WB_VERSION_1_19},
    252        {((6 << 16) | (5 << 8) | 5 ), BCM_FIELD_WB_VERSION_1_20},
    253        {((6 << 16) | (5 << 8) | 6 ), BCM_FIELD_WB_VERSION_1_21},
    254        {((6 << 16) | (5 << 8) | 7 ), BCM_FIELD_WB_VERSION_1_22},
    255        {((6 << 16) | (5 << 8) | 10 ), BCM_FIELD_WB_VERSION_1_23},
    256        {((6 << 16) | (5 << 8) | 11 ), BCM_FIELD_WB_VERSION_1_24},
    257        {((6 << 16) | (5 << 8) | 12 ), BCM_FIELD_WB_VERSION_1_24},
    258        {((6 << 16) | (5 << 8) | 13 ), BCM_FIELD_WB_VERSION_1_25},
    259        {((6 << 16) | (5 << 8) | 14 ), BCM_FIELD_WB_VERSION_1_27},
    260        {((6 << 16) | (5 << 8) | 15 ), BCM_FIELD_WB_VERSION_1_28},
    261        };
    262 #endif /* WARM_BOOT_SUPPORT*/
    263 
    264 /*
    265  * Macro:
    266  *     FIELD_IS_INIT (internal)
    267  * Purpose:
    268  *     Check that the unit is valid and confirm that the field functions
    269  *     are initialized.
    270  * Parameters:
    271  *     unit - BCM device number
    272  * Notes:
    273  *     Results in return(BCM_E_UNIT), return(BCM_E_UNAVAIL), or
    274  *     return(BCM_E_INIT) if fails.
    275  */
    276 #define FIELD_IS_INIT(unit)                                      \
    277     if (!soc_feature(unit, soc_feature_field)) {                 \
    278         return (BCM_E_UNAVAIL);                                  \
    279     }                                                            \
    280     if (_field_control[unit] == NULL) {                          \
    281         LOG_DEBUG(BSL_LS_BCM_FP, \
    282                   (BSL_META("FP(unit %d) Error: not initialized\n"), \
    283                    unit));   \
    284         return (BCM_E_INIT);                                     \
    285     }
    286 
    287 
    288 /*
    289  * Function:
    290  *      _bcm_field_is_entry_stage_valid(unit, entry, stage) (internal)
    291  * Purpose:
    292  *      Checks whether the entry is in the stage provided
    293  * Parameters:
    294  *      unit        - (IN) BCM device number
    295  *      entry       - (IN) Entry identifier
    296  *      stage       - (IN) Pipeline stage id number
    297  * Return values:
    298  *      Returns BCM_E_XXX
    299  *      BCM_E_NONE - implies for the particular Entry, Stage is Valid
    300  */
    301 int _bcm_field_is_entry_stage_valid(int unit, bcm_field_entry_t entry,
    302         _field_stage_id_t stage)
    303 {
    304     _field_entry_t *f_ent = NULL;
    305 
    306 #if defined(BCM_TOMAHAWK_SUPPORT)
    307     if (soc_feature(unit, soc_feature_field_preselector_support) &&
    308         (_BCM_FIELD_IS_PRESEL_ENTRY(entry) == TRUE)) {
    309        return ((_BCM_FIELD_STAGE_INGRESS == stage) ? BCM_E_NONE : BCM_E_PARAM);
    310     }
    311 #endif /* BCM_TOMAHAWK_SUPPORT */
    312     BCM_IF_ERROR_RETURN(_field_entry_get(unit, entry,
    313                         _FP_ENTRY_PRIMARY, &f_ent));
    314 
    315     /* All qualifiers applicable for ingress are applicable
    316      * for exact match stage also. Hence allow it for exact match
    317      * entries when stage is Ingress. */
    318     if (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) {
    319         stage = (stage == _BCM_FIELD_STAGE_INGRESS) ? \
    320                           _BCM_FIELD_STAGE_EXACTMATCH : stage;
    321     }
    322     if (f_ent->group->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) {
    323         stage = (stage == _BCM_FIELD_STAGE_INGRESS) ? \
    324                           _BCM_FIELD_STAGE_FLOWTRACKER : stage;
    325     }
    326 
    327     return ((f_ent->group->stage_id == stage) ? BCM_E_NONE : BCM_E_CONFIG);
    328 }
    329 
    330 /*
    331  * Local function prototypes
    332  */
    333 char *_field_qual_name(bcm_field_qualify_t qid);
    334 char *_field_group_mode_name(int unit, uint32 group_flags, _field_stage_t *stage_fc);
    335 char* _field_stage_name(_field_stage_t *stage_fc);
    336 
    337 STATIC int _field_entry_move(int unit, _field_entry_t *f_ent, int tcam_idx_new);
    338 
    339 /*
    340  * Field control data, one per device.
    341  */
    342 _field_control_t         *_field_control[BCM_MAX_NUM_UNITS];
    343 
    344 /* Sw WorkAround for EgressPortsAdd Action */
    345 uint8                        _field_egr_ports_recovery_lock[BCM_MAX_NUM_UNITS];
    346 _field_egr_ports_recovery_t  *_field_egr_ports_recovery[BCM_MAX_NUM_UNITS];
    347 
    348 #ifdef BCM_WARM_BOOT_SUPPORT
    349 
    350 /* Warmboot recovery for bcmFieldActionDscpMapNew*/
    351 _field_dscp_map_new_eid_list_t  *dscp_map_new_eid_list[BCM_MAX_NUM_UNITS];
    352 
    353 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
    354 
    355 /* Extract a field from a raw HW entry */
    356 
    357 void
    358 _field_extract(uint32 *buf, int offset, int width, uint32 *value)
    359 {
    360     int idx, wp, bp, len;
    361     wp = offset / 32;
    362     bp = offset & (32 - 1);
    363     idx = 0;
    364 
    365     for (len = width; len > 0; len -= 32) {
    366         if (bp) {
    367             value[idx] = (buf[wp++] >> bp) & ((1 << (32 - bp)) - 1);
    368             value[idx] |= buf[wp] << (32 - bp);
    369         } else {
    370             value[idx] = buf[wp];
    371         }
    372 
    373         if (len < 32) {
    374             value[idx] &= ((1 << len) - 1);
    375         }
    376 
    377         idx++;
    378     }
    379 
    380     return;
    381 }
    382 
    383 #endif
    384 
    385 int
    386 _field_state_cleanup(int unit, _field_control_t *fc)
    387 {
    388     int rv;
    389     _field_group_t *fg;
    390 
    391     /* Destroy all entries in unit. */
    392     rv = bcm_esw_field_entry_destroy_all(unit);
    393     if (BCM_FAILURE(rv)) {
    394         return (rv);
    395     }
    396 
    397     FP_LOCK(unit);
    398 
    399     /* Destroy all statistics entities. */
    400     rv = _field_stat_destroy_all(unit);
    401     if (BCM_FAILURE(rv)) {
    402         FP_UNLOCK(unit);
    403         return (rv);
    404     }
    405     FP_UNLOCK(unit);
    406 
    407     /* Destroy all policers. */
    408     rv = bcm_esw_policer_destroy_all(unit);
    409     if (BCM_FAILURE(rv)) {
    410         return (rv);
    411     }
    412 
    413     /* Destroy all groups in unit. */
    414     fg = fc->groups;
    415     while (fg != NULL) {
    416 
    417         rv = bcm_esw_field_group_destroy(unit, fg->gid);
    418         if (BCM_FAILURE(rv)) {
    419             return (rv);
    420         }
    421         fg = fc->groups;
    422     }
    423     return rv;
    424 }
    425 
    426 void
    427 _bcm_field_last_alloc_eid_incr(int unit)
    428 {
    429     _field_control_t *fc;
    430     int rv = 0;
    431 
    432     /* Get unit FP control structure. */
    433 
    434     FP_LOCK(unit);
    435     rv = (_field_control_get(unit, &fc));
    436     if (BCM_FAILURE(rv)) {
    437         FP_UNLOCK(unit);
    438         return;
    439     }
    440     fc->last_allocated_eid++;
    441     FP_UNLOCK(unit);
    442 
    443 }
    444 int
    445 _bcm_field_last_alloc_eid_get(int unit)
    446 {
    447     _field_control_t *fc;
    448     uint32 last_alloc_eid = -1;
    449     int rv = 0;
    450 
    451     /* Get unit FP control structure. */
    452 
    453     FP_LOCK(unit);
    454     rv = _field_control_get(unit, &fc);
    455     if (BCM_FAILURE(rv)) {
    456         FP_UNLOCK(unit);
    457         return rv;
    458     }
    459     last_alloc_eid = fc->last_allocated_eid;
    460     FP_UNLOCK(unit);
    461 
    462     return last_alloc_eid;
    463 }
    464 
    465 /*
    466  * Function:
    467  *      _field_scache_pointer_init_wb
    468  * Purpose:
    469  *      Initialize field component scache pointers for required partitions
    470  *      during warm boot
    471  * Parameters:
    472  *      unit - (IN) Unit number.
    473  *      fc - (IN) Pointer to field control
    474  * Returns:
    475  *      BCM_E_xxx
    476  * Notes:
    477  */
    478 
    479 int
    480 _field_scache_pointer_init_wb(int unit, _field_control_t  *fc)
    481 {
    482     int               rv;
    483     uint32            alloc_get;
    484     soc_scache_handle_t handle;
    485     int               incr_size = 0;
    486 
    487     SOC_SCACHE_HANDLE_SET(handle, unit, BCM_MODULE_FIELD, 1);
    488     SOC_SCACHE_MODULE_MAX_PARTITIONS_SET(unit, BCM_MODULE_FIELD, 1);
    489 
    490     /* Get the pointer for the Level 2 cache for partition 1*/
    491      rv = soc_scache_ptr_get(unit, handle,
    492                              &(fc->scache_ptr[_FIELD_SCACHE_PART_1]),
    493                                     &alloc_get);
    494      if (SOC_WARM_BOOT(unit) && (SOC_E_NOT_FOUND == rv)) {
    495           SOC_IF_ERROR_RETURN
    496                (soc_scache_alloc(unit, handle,
    497                                  fc->scache_size[_FIELD_SCACHE_PART_1] +
    498                                  SOC_WB_SCACHE_CONTROL_SIZE));
    499           rv = soc_scache_ptr_get(unit, handle,
    500                                   &(fc->scache_ptr[_FIELD_SCACHE_PART_1]),
    501                                   &alloc_get);
    502      }
    503 
    504      if (BCM_FAILURE(rv)) {
    505           return rv;
    506      } else if (alloc_get != fc->scache_size[_FIELD_SCACHE_PART_1] +
    507                 SOC_WB_SCACHE_CONTROL_SIZE) {
    508          /* Expected size doesn't match retrieved size */
    509          return BCM_E_INTERNAL;
    510      } else if (NULL == fc->scache_ptr[_FIELD_SCACHE_PART_1]) {
    511          return BCM_E_MEMORY;
    512      }
    513 
    514      /* scache size - partition 1 is increased for TRX devices only
    515       * from warmboot version 1_6 and devices like Raven
    516       * still follows globalscache allocation method
    517       */
    518      if (SOC_IS_TRX(unit)) {
    519          /* Get the pointer for the Level 2 cache for partition 0 */
    520          SOC_SCACHE_HANDLE_SET(handle, unit, BCM_MODULE_FIELD, 0);
    521 
    522 
    523          if (SOC_WARM_BOOT(unit)) {
    524              if ((fc->wb_recovered_version) < BCM_FIELD_WB_VERSION_1_6) {
    525                  /* Scache size is increased by 16*1024 bytes
    526                   * from version BCM_FIELD_WB_VERSION_1_6 for partition 0.
    527                   */
    528                  incr_size += (16 * 1024);
    529              }
    530 
    531              if ((fc->wb_recovered_version) < BCM_FIELD_WB_VERSION_1_8) {
    532                  /* Scache size is increased by 128*1024 bytes
    533                   * from version BCM_FIELD_WB_VERSION_1_8 for partition 0.
    534                   * with respect to version BCM_FIELD_WB_VERSION_1_6.
    535                   */
    536                  incr_size += (128 * 1024);
    537              }
    538 
    539              if ((fc->wb_recovered_version) < BCM_FIELD_WB_VERSION_1_15) {
    540                  /*
    541                   * Scache size is increased by 135 * 1024 bytes
    542                   * from version BCM_FIELD_WB_VERSION_1_15 for partition 0.
    543                   * with respect to version BCM_FIELD_WB_VERSION_1_8.
    544                   */
    545                  incr_size += (135 * 1024);
    546              }
    547 
    548              if ((fc->wb_recovered_version) < BCM_FIELD_WB_VERSION_1_17) {
    549                  /*
    550                   * Scache size is increased by 144 * 1024 bytes
    551                   * from version BCM_FIELD_WB_VERSION_1_17 for sync and recovery of
    552                   * policer configured rates and bursts
    553                   * with respect to version BCM_FIELD_WB_VERSION_1_15.
    554                   */
    555                  incr_size += (144 * 1024);
    556              }
    557 
    558              if ((fc->wb_recovered_version) < BCM_FIELD_WB_VERSION_1_18) {
    559                  /*
    560                   * Scache size is increased by (18 + 3) * 1024 bytes
    561                   * from version BCM_FIELD_WB_VERSION_1_18 for partition 0.
    562                   * To add sync for SVP DVP type per entry part and
    563                   * ingress, src entity selcode per group part
    564                   * with respect to version BCM_FIELD_WB_VERSION_1_17.
    565                   */
    566                  incr_size += (21 * 1024);
    567              }
    568              if ((fc->wb_recovered_version) < BCM_FIELD_WB_VERSION_1_19) {
    569                  /*
    570                   * Scache size is increased by
    571                   * ((16 + 1 + 1) * 4) + (16) * 12 bytes
    572                   * from version BCM_FIELD_WB_VERSION_1_19 for partition 0.
    573                   * To add sync no parm actions sync enum 4 bytes for each entry
    574                   * And to add PortPrioIntCosQNew Actions(Rp/Yp/Gp) CosQ Gport values
    575                   * 12 bytes for each entry in IFP
    576                   * with respect to version BCM_FIELD_WB_VERSION_1_18.
    577                   */
    578                  incr_size += (264 * 1024);
    579              }
    580 
    581              if ((fc->wb_recovered_version) < BCM_FIELD_WB_VERSION_1_20) {
    582                  /* Allocate additional scache to sync IFP action ingress
    583                   * and egress mirror gport value in no parm actions sync
    584                   * enums per entry. IngressMirror and EgressMirror GPORT
    585                   * can be assigned to single entry. Have to allocate (4+4)
    586                   * bytes per entry.
    587                   * IFP = (8 bytes * 512 entries * 12 slices).
    588                   */
    589                  incr_size += (48 * 1024);
    590                  /*
    591                   * Scache size is increased by (16 * 1024) * 4 bytes
    592                   * (16K entries * 4 bytes) for all devices and
    593                   * (8 * 1024) * 4 * 2 (8K entries * 4 bytes * 2 params
    594                   * for KT2 devices to sync and recover the params of
    595                   * fabricQueue action for all entries of Ingress.
    596                   */
    597                  incr_size += (16 * 1024 * 4);
    598              }
    599 
    600              if ((fc->wb_recovered_version) < BCM_FIELD_WB_VERSION_1_21) {
    601                  /*
    602                   * Group PBMP is synced with max_groups * size of the pbmp array
    603                   * Sync MirrorIngress and MirrorEgress action parameters per entry
    604                   * Worst case 16K * 12 bytes
    605                   */
    606                   incr_size += ((512 * _SHR_PBMP_WORD_MAX * 4) + (16 * 1024 * 12));
    607              }
    608 
    609              if ((fc->wb_recovered_version) < BCM_FIELD_WB_VERSION_1_23) {
    610                  /*
    611                   * Scache size is increased by 128 * 4 bytes
    612                   * to syncloopbacktype selcode per group part.
    613                   * Worst case assuming 128 IFP groups in quad mode
    614                   * (128 * 4) bytes.
    615                   */
    616                   incr_size += (128 * 4);
    617              }
    618 
    619              if ((fc->wb_recovered_version) < BCM_FIELD_WB_VERSION_1_27) {
    620                  /*
    621                   * Scache size is increased by FP_MAX_NUM_PIPES * 1 byte
    622                   * to sync instance for all pipes in EFP/VFP. 
    623                   * _FP_MAX_NUM_PIPES * 1 bytes * 8 groups to sync group
    624                   * instance for all groups in EFP/VFP.
    625                   */
    626                   incr_size += ((_FP_MAX_NUM_PIPES)+ (_FP_MAX_NUM_PIPES * 8));
    627              }
    628 
    629          }
    630 
    631          if (incr_size > 0) {
    632              SOC_IF_ERROR_RETURN
    633                  (soc_scache_realloc(unit, handle,
    634                                      (incr_size)));
    635              rv = soc_scache_ptr_get(unit, handle,
    636                      &(fc->scache_ptr[_FIELD_SCACHE_PART_0]),
    637                      &alloc_get);
    638 
    639              if (BCM_FAILURE(rv)) {
    640                  return rv;
    641              } else if (alloc_get != (fc->scache_size[_FIELD_SCACHE_PART_0] +
    642                          SOC_WB_SCACHE_CONTROL_SIZE)) {
    643                  /* Expected size doesn't match retrieved size */
    644                  return BCM_E_INTERNAL;
    645              } else if (NULL == fc->scache_ptr[_FIELD_SCACHE_PART_0]) {
    646                  return BCM_E_MEMORY;
    647              }
    648          }
    649      }
    650      return BCM_E_NONE;
    651 }
    652 /* Update the scache based on the latest field state */
    653 int
    654 _bcm_esw_field_scache_sync(int unit)
    655 {
    656     int rv = BCM_E_NONE;
    657     _field_control_t *fc;
    658     _field_stage_t *stage_fc;
    659     int (* f)(int, _field_control_t *, _field_stage_t *);
    660     uint16 version;
    661 #if defined(BCM_TOMAHAWK_SUPPORT)
    662     if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
    663         f = _bcm_field_th_scache_sync;
    664     } else
    665 #endif /* BCM_TRIDENT2_SUPPORT */
    666 #ifdef BCM_TRIDENT2_SUPPORT
    667     if (SOC_IS_TD2_TT2(unit)) {
    668         f = _bcm_field_td2_scache_sync;
    669     } else
    670 #endif /* BCM_TRIDENT2_SUPPORT */
    671 #ifdef BCM_TRX_SUPPORT
    672     if (SOC_IS_TRIUMPH(unit)
    673              || SOC_IS_VALKYRIE(unit)
    674              || SOC_IS_TRIUMPH2(unit)
    675              || SOC_IS_APOLLO(unit)
    676              || SOC_IS_VALKYRIE2(unit)
    677              || SOC_IS_SC_CQ(unit)
    678              || SOC_IS_TD_TT(unit)
    679              || SOC_IS_KATANAX(unit)
    680              || SOC_IS_HURRICANE3(unit)
    681              || SOC_IS_GREYHOUND2(unit)
    682              ) {
    683         f = _field_tr2_scache_sync;
    684     } else
    685 #endif /* BCM_TRX_SUPPORT */
    686 #ifdef BCM_TRIUMPH3_SUPPORT
    687     if (SOC_IS_TRIUMPH3(unit)) {
    688         f = _bcm_field_tr3_scache_sync;
    689     } else
    690 #endif
    691     {
    692         f = _field_scache_sync;
    693     }
    694 
    695     if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
    696         return BCM_E_NONE;
    697     }
    698 
    699     /* Get unit FP control structure. */
    700 
    701 
    702     FP_LOCK(unit);
    703     rv = _field_control_get(unit, &fc);
    704     if (BCM_FAILURE(rv)) {
    705         FP_UNLOCK(unit);
    706         return rv;
    707     }
    708 
    709     /* Initialize scache_pos */
    710     fc->scache_pos = 0;
    711     fc->scache_pos1 = 0;
    712 
    713     /* Write the version number */
    714     version = (fc->wb_current_version);
    715     sal_memcpy(fc->scache_ptr[_FIELD_SCACHE_PART_0], &version, sizeof(uint16));
    716     fc->scache_pos += SOC_WB_SCACHE_CONTROL_SIZE;
    717 
    718     /* Write the version number */
    719     if(NULL != fc->scache_ptr[_FIELD_SCACHE_PART_1]) {
    720         version = (fc->wb_current_version);
    721         sal_memcpy(fc->scache_ptr[_FIELD_SCACHE_PART_1], &version, sizeof(uint16));
    722         fc->scache_pos1 += SOC_WB_SCACHE_CONTROL_SIZE;
    723     }
    724 
    725 
    726     if (SOC_IS_FIREBOLT(unit) || SOC_IS_FIREBOLT2(unit) ||
    727         SOC_IS_BRADLEY(unit) || SOC_IS_HUMV(unit) ||
    728         SOC_IS_RAVEN(unit) || SOC_IS_ENDURO(unit) ||
    729         SOC_IS_HAWKEYE(unit) || SOC_IS_APOLLO(unit) ||
    730         SOC_IS_TRIUMPH(unit) || SOC_IS_VALKYRIE(unit) ||
    731         SOC_IS_TRIUMPH2(unit) || SOC_IS_VALKYRIE2(unit) ||
    732         SOC_IS_SC_CQ(unit) || SOC_IS_TD_TT(unit) ||
    733         SOC_IS_KATANAX(unit) || SOC_IS_HURRICANEX(unit) ||
    734         SOC_IS_TRIUMPH3(unit) || SOC_IS_GREYHOUND(unit) ||
    735         SOC_IS_GREYHOUND2(unit)) {
    736 
    737             rv = _field_stage_control_get
    738                 (unit,
    739                  _BCM_FIELD_STAGE_INGRESS,
    740                  &stage_fc
    741                 );
    742 
    743             if (BCM_SUCCESS(rv))
    744             {
    745                 rv = (*f)(unit, fc, stage_fc);
    746             }
    747     }
    748 
    749 #if  defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
    750     if (BCM_SUCCESS(rv) &&
    751         (SOC_IS_FIREBOLT2(unit) || SOC_IS_ENDURO(unit) ||
    752          SOC_IS_APOLLO(unit) ||
    753          SOC_IS_TRIUMPH(unit) || SOC_IS_VALKYRIE(unit) ||
    754          SOC_IS_TRIUMPH2(unit) || SOC_IS_VALKYRIE2(unit) ||
    755          SOC_IS_SC_CQ(unit) || SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit)
    756          || SOC_IS_TRIUMPH3(unit)
    757          || SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit)
    758          || SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) &&
    759          (soc_feature(unit, soc_feature_field_multi_stage))) {
    760         rv = _field_stage_control_get
    761                 (unit,
    762                  _BCM_FIELD_STAGE_EGRESS,
    763                  &stage_fc
    764                 );
    765 
    766         if (BCM_SUCCESS(rv)) {
    767             rv = (*f)(unit, fc, stage_fc);
    768 
    769             if (BCM_SUCCESS(rv)) {
    770                 rv = _field_stage_control_get
    771                         (unit,
    772                          _BCM_FIELD_STAGE_LOOKUP,
    773                          &stage_fc
    774                         );
    775 
    776                 if (BCM_SUCCESS(rv)) {
    777                     rv = (*f)(unit, fc, stage_fc);
    778 
    779                     if (BCM_SUCCESS(rv) &&
    780                         soc_feature(unit, soc_feature_esm_support)) {
    781                         rv = _field_stage_control_get
    782                                 (unit,
    783                                  _BCM_FIELD_STAGE_EXTERNAL,
    784                                  &stage_fc
    785                                 );
    786 
    787                         if (BCM_SUCCESS(rv)) {
    788                             rv = (*f)(unit, fc, stage_fc);
    789                         }
    790                     }
    791                 }
    792             }
    793         }
    794     }
    795 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRIUMPH_SUPPORT */
    796 #if defined(BCM_TOMAHAWK_SUPPORT)
    797     if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
    798         if (soc_feature(unit, soc_feature_field_compression)) {
    799             rv = _field_stage_control_get(unit,
    800                                           _BCM_FIELD_STAGE_CLASS,
    801                                           &stage_fc);
    802             if (BCM_SUCCESS(rv)) {
    803                 rv = (*f)(unit, fc, stage_fc);
    804             }
    805             BCM_IF_ERROR_RETURN(rv);
    806         }
    807 
    808         if (soc_feature(unit, soc_feature_field_exact_match_support)) {
    809 
    810             rv = _field_stage_control_get(unit,
    811                                           _BCM_FIELD_STAGE_EXACTMATCH,
    812                                           &stage_fc);
    813             if (BCM_SUCCESS(rv)) {
    814                 rv = (*f)(unit, fc, stage_fc);
    815             }
    816         }
    817     }
    818 #endif /* BCM_TOMAHAWK_SUPPORT */
    819 
    820 #if defined(BCM_HELIX5_SUPPORT)
    821     if (soc_feature(unit, soc_feature_field_flowtracker_support)) {
    822         rv = _field_stage_control_get(unit,
    823                                       _BCM_FIELD_STAGE_FLOWTRACKER,
    824                                       &stage_fc);
    825         if (BCM_SUCCESS(rv)) {
    826             rv = (*f)(unit, fc, stage_fc);
    827         }
    828         BCM_IF_ERROR_RETURN(rv);
    829     }
    830 #endif
    831 
    832     FP_UNLOCK(unit);
    833     return rv;
    834 }
    835 
    836 STATIC int
    837 _field_group_entry_write(int unit, int slice_idx, _field_slice_t *fs,
    838                          _field_control_t *fc, _field_stage_t *stage_fc)
    839 {
    840     int qset_count, ratio, idx, prev_prio, multigroup, master_slice;
    841     uint8 group_auto_expansion = 0, next_group_valid = 0;
    842     uint8 stat_present, pol_present, prio_ctrl;
    843     uint8 *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0];
    844     uint8 *buf1 = fc->scache_ptr[_FIELD_SCACHE_PART_1];
    845     _field_group_t *fg;
    846     _field_entry_t *f_ent;
    847     bcm_port_t port;
    848     bcm_field_qualify_t q;
    849     bcm_pbmp_t port_cmic_pbmp;
    850     _field_slice_t *temp_fs = fs;
    851     uint8 *count = NULL;
    852     _field_stage_t *ingress_stage_fc = NULL;
    853     uint8 max_udf_count = 0;
    854     uint8 udf_idx;
    855     uint8 color_independent;
    856     uint8 group_flags = 0;
    857     int part_idx;
    858     int parts_cnt;
    859 
    860 
    861     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
    862                 _BCM_FIELD_STAGE_INGRESS, &ingress_stage_fc));
    863 
    864     if (ingress_stage_fc->data_ctrl) {
    865         max_udf_count = ingress_stage_fc->data_ctrl->num_elems * 2;
    866     }
    867 
    868     SOC_PBMP_ASSIGN(port_cmic_pbmp, PBMP_PORT_ALL(unit));
    869     SOC_PBMP_OR(port_cmic_pbmp, PBMP_CMIC(unit));
    870 
    871     /* Check for multiple groups in a slice */
    872     if (SOC_PBMP_EQ(fs->pbmp, port_cmic_pbmp)) {
    873         multigroup = 0;
    874     } else {
    875         LOG_DEBUG(BSL_LS_BCM_FP,
    876                   (BSL_META_U(unit,
    877                               "_field_scache_sync:   Multigroup.\n")));
    878         multigroup = 1;
    879     }
    880     LOG_DEBUG(BSL_LS_BCM_FP,
    881               (BSL_META_U(unit,
    882                           "_field_scache_sync:   Writing slice %d @ byte %d...\n"),
    883                slice_idx, fc->scache_pos));
    884 
    885     buf[fc->scache_pos] = (slice_idx << 1) | multigroup;
    886     fc->scache_pos++;
    887 
    888     /* Get the master slice if expanded */
    889     master_slice = slice_idx;
    890     while (temp_fs->prev != NULL) {
    891         temp_fs = temp_fs->prev;
    892         master_slice = temp_fs->slice_number;
    893     }
    894 
    895     /* Traverse all groups and dump group data for this slice */
    896     fg = fc->groups;
    897     while (fg != NULL) {
    898         if (fg->stage_id != stage_fc->stage_id) {
    899             fg = fg->next;
    900             continue; /* Not in this stage */
    901         }
    902         if (fg->slices[0].slice_number != master_slice) {
    903             LOG_DEBUG(BSL_LS_BCM_FP,
    904                       (BSL_META_U(unit,
    905                                   "_field_scache_sync:   No match on group %d.\n"),
    906                        fg->gid));
    907             fg = fg->next;
    908             continue; /* Not in this slice */
    909         }
    910         LOG_DEBUG(BSL_LS_BCM_FP,
    911                   (BSL_META_U(unit,
    912                               "_field_scache_sync:   Match on group %d...\n"),
    913                    fg->gid));
    914 
    915         LOG_DEBUG(BSL_LS_BCM_FP,
    916                   (BSL_META_U(unit,
    917                               "_field_scache_sync:   Writing group %d @ byte %d...\n"),
    918                    fg->gid, fc->scache_pos));
    919 
    920         SOC_PBMP_ITER(fg->pbmp, port) {
    921             break; /* Pick first port found as representative */
    922         }
    923 
    924 
    925         if (fc->flags & _FP_STABLE_SAVE_LONG_IDS) {
    926             /* Long-id format selected => Save full GID */
    927 
    928             buf[fc->scache_pos] = fg->gid;
    929             fc->scache_pos++;
    930             buf[fc->scache_pos] = fg->gid >> 8;
    931             fc->scache_pos++;
    932             buf[fc->scache_pos] = fg->gid >> 16;
    933             fc->scache_pos++;
    934             buf[fc->scache_pos] = fg->gid >> 24;
    935             fc->scache_pos++;
    936 
    937             buf[fc->scache_pos] = port;
    938             fc->scache_pos++;
    939         } else {
    940             /* Save compact GID */
    941 
    942             buf[fc->scache_pos] = (fg->gid) & 0xFF; /* GID_lo */
    943             fc->scache_pos++;
    944             buf[fc->scache_pos] = ((fg->gid & 0xF00) << 4) | (port & 0xF);
    945             fc->scache_pos++; /* GID_hi | port_lo */
    946             buf[fc->scache_pos] = (port >> 4); /* port_hi */
    947             fc->scache_pos++;
    948         }
    949 
    950         if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_21) {
    951             int i = 0;
    952             for (i = 0; i < _SHR_PBMP_WORD_MAX; i++) {
    953                 buf[fc->scache_pos] = fg->pbmp.pbits[i];
    954                 fc->scache_pos++;
    955                 buf[fc->scache_pos] = fg->pbmp.pbits[i] >> 8;
    956                 fc->scache_pos++;
    957                 buf[fc->scache_pos] = fg->pbmp.pbits[i] >> 16;
    958                 fc->scache_pos++;
    959                 buf[fc->scache_pos] = fg->pbmp.pbits[i] >> 24;
    960                 fc->scache_pos++;
    961             }
    962         }
    963 
    964         buf[fc->scache_pos] = fg->priority;
    965         fc->scache_pos++;
    966         buf[fc->scache_pos] = fg->priority >> 8;
    967         fc->scache_pos++;
    968         buf[fc->scache_pos] = fg->priority >> 16;
    969         fc->scache_pos++;
    970         buf[fc->scache_pos] = fg->priority >> 24;
    971         fc->scache_pos++;
    972 
    973         /* Write group action res id */
    974         buf[fc->scache_pos] = fg->action_res_id;
    975         fc->scache_pos++;
    976         buf[fc->scache_pos] = fg->action_res_id >> 8;
    977         fc->scache_pos++;
    978         buf[fc->scache_pos] = fg->action_res_id >> 16;
    979         fc->scache_pos++;
    980         buf[fc->scache_pos] = fg->action_res_id >> 24;
    981         fc->scache_pos++;
    982 
    983         /* Obtain list of qualifiers in fg->qset */
    984         qset_count = 0;
    985         _FIELD_QSET_ITER(fg->qset, q) {
    986             qset_count++;
    987         }
    988 
    989         LOG_DEBUG(BSL_LS_BCM_FP,
    990                   (BSL_META_U(unit,
    991                               "_field_scache_sync:   Writing qset count (%d) @ byte %d...\n"),
    992                    qset_count, fc->scache_pos));
    993 
    994         buf[fc->scache_pos] = qset_count; /* qset_count */
    995         fc->scache_pos++;
    996         _FIELD_QSET_ITER(fg->qset, q) {
    997             LOG_DEBUG(BSL_LS_BCM_FP,
    998                       (BSL_META_U(unit,
    999                                   "_field_scache_sync:     Writing qid %d @ byte %d...\n"),
   1000                        q, fc->scache_pos));
   1001 
   1002             buf[fc->scache_pos] = q; /* QID */
   1003             fc->scache_pos++;
   1004             if(NULL != buf1) {
   1005                 buf1[fc->scache_pos1] = q >> 8;
   1006                 fc->scache_pos1++;
   1007             }
   1008         }
   1009 
   1010         count = &buf[fc->scache_pos];
   1011         fc->scache_pos++;
   1012         *count = 0;
   1013 
   1014         for (q = bcmFieldQualifyCount; q < ((int)_bcmFieldQualifyCount); q++) {
   1015             if (BCM_FIELD_QSET_TEST(fg->qset, q)) {
   1016                 buf[fc->scache_pos] = q - bcmFieldQualifyCount;
   1017                 fc->scache_pos++;
   1018                 if(NULL != buf1) {
   1019                     buf1[fc->scache_pos1] = (q - bcmFieldQualifyCount) >> 8;
   1020                     fc->scache_pos1++;
   1021                 }
   1022                 *count = *count + 1;
   1023                 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1024                                 "_field_scache_sync:     Writing qid idx %d @ byte %d...\n"),
   1025                             q, fc->scache_pos - 1));
   1026             }
   1027         }
   1028         LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1029                         "_field_scache_sync:   Writing internal qset count (%d) @ byte %d...\n"),
   1030                     *count, fc->scache_pos - 1 - *count));
   1031 
   1032         count = &buf[fc->scache_pos];
   1033         fc->scache_pos++;
   1034         *count = 0;
   1035 
   1036         for (udf_idx = 0; udf_idx < max_udf_count ; udf_idx++) {
   1037             if (SHR_BITGET(fg->qset.udf_map, udf_idx)) {
   1038                 buf[fc->scache_pos] = udf_idx;
   1039                 fc->scache_pos++;
   1040                 *count = *count + 1;
   1041                 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1042                                 "_field_scache_sync:     Writing UDF idx %d @ byte %d...\n"),
   1043                             udf_idx, fc->scache_pos - 1));
   1044             }
   1045         }
   1046         LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
   1047                         "_field_scache_sync:   Writing udf count (%d) @ byte %d...\n"),
   1048                     *count, fc->scache_pos - 1 - *count));
   1049 
   1050 
   1051         if (fg->flags & _FP_GROUP_SELECT_AUTO_EXPANSION) {
   1052             group_auto_expansion = _FIELD_GROUP_AUTO_EXPANSION;
   1053         } else {
   1054             group_auto_expansion = 0;
   1055         }
   1056 
   1057         group_flags = 0;
   1058 
   1059         if (fg->flags & _FP_GROUP_LOOKUP_ENABLED) {
   1060             group_flags |= _FIELD_GROUP_LOOKUP_ENABLED;
   1061         }
   1062 
   1063         if (fg->flags & _FP_GROUP_WLAN) {
   1064             group_flags |= _FIELD_GROUP_WLAN;
   1065         }
   1066 
   1067         /* Next group not valid */
   1068         next_group_valid = 0x0;
   1069         fg = fg->next;
   1070         while (fg != NULL) {
   1071             if (multigroup
   1072                     && (fg->stage_id == stage_fc->stage_id)
   1073                     && (fg->slices[0].slice_number == slice_idx)) {
   1074                 /* Next group valid */
   1075                 next_group_valid = _FIELD_GROUP_NEXT_GROUP_VALID;
   1076                 break;
   1077             }
   1078             fg = fg->next;
   1079         }
   1080 
   1081         /*
   1082          * In this byte, 6 bits are used as below
   1083          * bit 0 --  to indicate wheather next group
   1084          *           in this slice is valid or not
   1085          * bit 1,2 -- contains group's instance.
   1086          * bit 5 --  to indicate group lookup enable status.
   1087          * bit 6 --  to indicate group is WLAN.
   1088          * bit 7 --  to indicate group auto expansion status.
   1089          */
   1090 
   1091         buf[fc->scache_pos] = (group_auto_expansion | next_group_valid | group_flags);
   1092 
   1093         fc->scache_pos++;
   1094     }
   1095         /* Traverse all entries and dump entry data for this slice */
   1096         if (fs->group_flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
   1097             ratio = 2;
   1098         } else {
   1099             ratio = 1;
   1100         }
   1101         prev_prio = -1;
   1102         for (idx = 0; idx < fs->entry_count / ratio; idx++) {
   1103             /* Find EID that matches this HW index */
   1104             f_ent = fs->entries[idx];
   1105             if (f_ent == NULL) {
   1106                 continue;
   1107             }
   1108             if (f_ent->flags & _FP_ENTRY_INSTALLED) {
   1109                 prio_ctrl = (f_ent->prio != prev_prio) ? 1 : 0;
   1110                 stat_present = (f_ent->statistic.flags &
   1111                                 _FP_ENTRY_STAT_INSTALLED) ? 1 : 0;
   1112                 pol_present = (f_ent->policer[0].flags &
   1113                                _FP_POLICER_INSTALLED) ? 1 : 0;
   1114                 if (fc->flags & _FP_STABLE_SAVE_LONG_IDS) {
   1115                     /* Long-id format select => Save complete EID */
   1116 
   1117                     buf[fc->scache_pos] = f_ent->eid;
   1118                     fc->scache_pos++;
   1119                     buf[fc->scache_pos] = f_ent->eid >> 8;
   1120                     fc->scache_pos++;
   1121                     buf[fc->scache_pos] = f_ent->eid >> 16;
   1122                     fc->scache_pos++;
   1123                     buf[fc->scache_pos] = f_ent->eid >> 24;
   1124                     fc->scache_pos++;
   1125 
   1126                     buf[fc->scache_pos] = prio_ctrl
   1127                         | (stat_present << 1)
   1128                         | (pol_present << 2);
   1129                     fc->scache_pos++;
   1130                 } else {
   1131                     /* Save compact EID */
   1132 
   1133                     buf[fc->scache_pos] = f_ent->eid & 0xFF; /* EID_lo */
   1134                     fc->scache_pos++;
   1135                     buf[fc->scache_pos] = ((f_ent->eid >> 8) & 0xF) | (prio_ctrl << 4) |
   1136                         (stat_present << 5) | (pol_present << 6);
   1137                     /* EID_hi + control bits */
   1138                     fc->scache_pos++;
   1139                 }
   1140                 if (multigroup) {
   1141                     /* Multiple groups in slice => Save id of group to which
   1142                        entry belongs
   1143                     */
   1144 
   1145                     if (fc->flags & _FP_STABLE_SAVE_LONG_IDS) {
   1146                         /* Save long GID */
   1147 
   1148                         buf[fc->scache_pos] = f_ent->group->gid;
   1149                         fc->scache_pos++;
   1150                         buf[fc->scache_pos] = f_ent->group->gid >> 8;
   1151                         fc->scache_pos++;
   1152                         buf[fc->scache_pos] = f_ent->group->gid >> 16;
   1153                         fc->scache_pos++;
   1154                         buf[fc->scache_pos] = f_ent->group->gid >> 24;
   1155                         fc->scache_pos++;
   1156                     } else {
   1157                         /* Save compact GID */
   1158 
   1159                         buf[fc->scache_pos] = f_ent->group->gid & 0xFF; /* GID_lo */
   1160                         fc->scache_pos++;
   1161                         buf[fc->scache_pos] = (f_ent->group->gid >> 8) & 0xF;
   1162                         /* GID_hi */
   1163                         fc->scache_pos++;
   1164                     }
   1165                 }
   1166                 if (prio_ctrl) {
   1167                     /* 32-bit priority is written */
   1168                     buf[fc->scache_pos] = f_ent->prio & 0xFF;
   1169                     fc->scache_pos++;
   1170                     buf[fc->scache_pos] = (f_ent->prio >> 8) & 0xFF;
   1171                     fc->scache_pos++;
   1172                     buf[fc->scache_pos] = (f_ent->prio >> 16) & 0xFF;
   1173                     fc->scache_pos++;
   1174                     buf[fc->scache_pos] = (f_ent->prio >> 24) & 0xFF;
   1175                     fc->scache_pos++;
   1176                     prev_prio = f_ent->prio;
   1177                 }
   1178                 /* Write policer and stat object IDs if present */
   1179                 if (fc->flags & _FP_STABLE_SAVE_LONG_IDS) {
   1180                     /* Save long IDs */
   1181 
   1182                     if (pol_present) {
   1183                         buf[fc->scache_pos] = f_ent->policer[0].pid;
   1184                         fc->scache_pos++;
   1185                         buf[fc->scache_pos] = f_ent->policer[0].pid >> 8;
   1186                         fc->scache_pos++;
   1187                         buf[fc->scache_pos] = f_ent->policer[0].pid >> 16;
   1188                         fc->scache_pos++;
   1189                         buf[fc->scache_pos] = f_ent->policer[0].pid >> 24;
   1190                         fc->scache_pos++;
   1191                     }
   1192 
   1193                     if (stat_present) {
   1194                         buf[fc->scache_pos] = f_ent->statistic.sid;
   1195                         fc->scache_pos++;
   1196                         buf[fc->scache_pos] = f_ent->statistic.sid >> 8;
   1197                         fc->scache_pos++;
   1198                         buf[fc->scache_pos] = f_ent->statistic.sid >> 16;
   1199                         fc->scache_pos++;
   1200                         buf[fc->scache_pos] = f_ent->statistic.sid >> 24;
   1201                         fc->scache_pos++;
   1202                     }
   1203                 } else {
   1204                     /* Save compact IDs */
   1205                     if (pol_present) {
   1206                         buf[fc->scache_pos] = (f_ent->policer[0].pid) & 0xFF;
   1207                         fc->scache_pos++;
   1208                     }
   1209                     if (stat_present) {
   1210                         if (pol_present) {
   1211                             buf[fc->scache_pos] =
   1212                                 ((f_ent->policer[0].pid >> 8 & 0xF) << 4) |
   1213                                 (f_ent->statistic.sid & 0xF);
   1214                             fc->scache_pos++;
   1215                         } else {
   1216                             buf[fc->scache_pos] = f_ent->statistic.sid & 0xF;
   1217                             fc->scache_pos++;
   1218                         }
   1219                         buf[fc->scache_pos] = (f_ent->statistic.sid >> 4) & 0xFF;
   1220                         fc->scache_pos++;
   1221                     } else if (pol_present) {
   1222                         buf[fc->scache_pos] =
   1223                             (f_ent->policer[0].pid >> 8 & 0xF) << 4;
   1224                         fc->scache_pos++;
   1225                     }
   1226                 }
   1227 
   1228                 parts_cnt = 0;
   1229                 if ((f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) ||
   1230                         (f_ent->group->stage_id == _BCM_FIELD_STAGE_EGRESS) ||
   1231                         (f_ent->group->stage_id == _BCM_FIELD_STAGE_LOOKUP)) {
   1232                     /* Sync entry part count for SVP & DVP type */
   1233                     BCM_IF_ERROR_RETURN(_bcm_field_entry_tcam_parts_count(unit,
   1234                                 f_ent->group->stage_id, f_ent->group->flags,
   1235                                 &parts_cnt));
   1236 
   1237                     buf[fc->scache_pos] = parts_cnt;
   1238                     fc->scache_pos++;
   1239                 }
   1240 
   1241                 /* Save Dvp Type */
   1242                 buf[fc->scache_pos] = f_ent->dvp_type;
   1243                 fc->scache_pos++;
   1244                 for (part_idx = 1; part_idx < parts_cnt; part_idx++) {
   1245                     buf[fc->scache_pos] = f_ent[part_idx].dvp_type;
   1246                     fc->scache_pos++;
   1247                 }
   1248 
   1249                 /* Save Svp Type */
   1250                 buf[fc->scache_pos] = f_ent->svp_type;
   1251                 fc->scache_pos++;
   1252                 for (part_idx = 1; part_idx < parts_cnt; part_idx++) {
   1253                     buf[fc->scache_pos] = f_ent[part_idx].svp_type;
   1254                     fc->scache_pos++;
   1255                 }
   1256 
   1257                 /* Save Entry Color independent flag */
   1258                 color_independent = (f_ent->flags &
   1259                         _FP_ENTRY_COLOR_INDEPENDENT) ? 1 : 0;
   1260                 buf[fc->scache_pos] = color_independent << 7;
   1261                 fc->scache_pos++;
   1262 
   1263                 BCM_IF_ERROR_RETURN(_field_entry_no_param_actions_scache_sync(
   1264                                     unit, stage_fc, fc, f_ent, buf));
   1265             }
   1266         }
   1267     return BCM_E_NONE;
   1268 }
   1269 
   1270 /*
   1271  * This function manages the Level 2 warm boot cache. The data will be stored
   1272  * in the following format:
   1273  * Start indicator (32 bits): Value = IFP/EFP/VFP
   1274  *
   1275  * Range check IDs (IFP)
   1276  * 8-bit ID count (1 uint8)
   1277  * ID0 (4 x uint8)
   1278  * .
   1279  * IDN (4 x uint8)
   1280  *
   1281  * Data qualifier data, as follows:
   1282  * 8-bit data qualifier count (1 uint 8)
   1283  * 32-bit data qualifier id (1 int)
   1284  * 2-bit "length remainder" | 3-bit flags | 3-bit offset base (1 uint 8)
   1285  * 16-bit data qualifier match-data offset (1 uint 16)
   1286  * 16-bit hw_bmap field of data qualifier
   1287  *   (Note that this field is linked to the hardware; namely, the width of this
   1288  *   bitmap is the number of UDF n-byte chunks supported, i.e. the number of
   1289  *   "columns" in the UDF_OFFSET table.)
   1290  *
   1291  * Group/entry data
   1292  * Slice num (5 bits) | Multigroup slice indicator (1 bit): (1 uint8)
   1293  * GID_lo (8 bits): (1 uint 8)
   1294  * GID_hi (4 bits) | Representative_port_lo (4 bits): (1 uint 8)
   1295  * Representative_port_hi (2 bits) | Reserved (6 bits): (1 uint 8)
   1296  * Group priority (32 bits): (4 uint 8)
   1297  * Qualifier count (8 bits): (1 uint 8)
   1298  * QID 1 (8 bits): (1 uint 8)
   1299  * .
   1300  * QID N (8 bits): (1 uint 8)
   1301  * Next_group_valid (1 bit) | Reserved (7 bits): (1 uint 8)
   1302  *
   1303  * Groups are immediately followed by entries, which can have one of the
   1304  * following two formats depending on the multigroup slice indicator:
   1305  * Long format:
   1306  * 8 bit EID_lo: (1 uint 8)
   1307  * 4 bit EID_hi | priority_ctrl (1 bit) | Policer (1 bit) | Stat (1 bit):
   1308   (1 uint 8)
   1309  * 8 bit GID_lo: (1 uint 8)
   1310  * 4 bit GID_hi | 4 reserved bits: (1 uint 8)
   1311  * priority_0: (1 uint 8)
   1312  * priority_1: (1 uint 8) <---- The 32-bit priority is stored only if it is
   1313  * priority_2: (1 uint 8)       different from the entry before it.
   1314  * priority_3: (1 uint 8)
   1315  * PID_lo (8 bits): (1 uint8)
   1316  * PID_hi (4 bits) | SID_lo (4 bits): (1 uint8)
   1317  * SID_hi (4 bits): (1 uint 8)
   1318  * DVP_Type (4bits): (1 uint4)
   1319  * SVP_Type (4 bits): (1 uint4)
   1320  * Reserved (8 bits): (1 uint8) future purpose
   1321  *
   1322  * Short format:
   1323  * 8 bit EID_lo: (1 uint 8)
   1324  * 4 bit EID_hi | priority_ctrl (1 bit) | Policer (1 bit) | Stat (1 bit):
   1325   (1 uint 8)
   1326  * priority_0: (1 uint 8)
   1327  * priority_1: (1 uint 8) <---- The 32-bit priority is stored only if it is
   1328  * priority_2: (1 uint 8)       different from the entry before it.
   1329  * priority_3: (1 uint 8)
   1330  * PID_lo (8 bits): (1 uint8)
   1331  * PID_hi (4 bits) | SID_lo (4 bits): (1 uint8)
   1332  * SID_hi (8 bits): (1 uint 8)
   1333  * DVP_Type (4bits): (1 uint4)
   1334  * SVP_Type (4 bits): (1 uint4)
   1335  * Reserved (8 bits): (1 uint8) future purpose
   1336  *
   1337  * End indicator (32 bits): Value = IFP/EFP/VFP
   1338  */
   1339 
   1340 void
   1341 _field_scache_stage_hdr_save(_field_control_t *fc,
   1342                              uint32           header
   1343                              )
   1344 {
   1345     uint8  *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0];
   1346     uint8  *buf1 = fc->scache_ptr[_FIELD_SCACHE_PART_1];
   1347 
   1348     /* Mark the beginning of the particular FP section */
   1349     buf[fc->scache_pos] = header;
   1350     fc->scache_pos++;
   1351     buf[fc->scache_pos] = header >> 8;
   1352     fc->scache_pos++;
   1353     buf[fc->scache_pos] = header >> 16;
   1354     fc->scache_pos++;
   1355     buf[fc->scache_pos] = header >> 24;
   1356     fc->scache_pos++;
   1357 
   1358     /* Save long-id setting */
   1359 
   1360     buf[fc->scache_pos] = fc->flags;
   1361     fc->scache_pos++;
   1362 
   1363     if(NULL != buf1) {
   1364         /* Mark the beginning of the particular FP section */
   1365         buf1[fc->scache_pos1] = header;
   1366         fc->scache_pos1++;
   1367         buf1[fc->scache_pos1] = header >> 8;
   1368         fc->scache_pos1++;
   1369         buf1[fc->scache_pos1] = header >> 16;
   1370         fc->scache_pos1++;
   1371         buf1[fc->scache_pos1] = header >> 24;
   1372         fc->scache_pos1++;
   1373     }
   1374 }
   1375 
   1376 int
   1377 _field_scache_stage_hdr_chk(_field_control_t *fc,
   1378                             uint32           header
   1379                             )
   1380 {
   1381     uint8  *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0];
   1382     uint8  *buf1 = fc->scache_ptr[_FIELD_SCACHE_PART_1];
   1383     uint32 temp;
   1384 
   1385     /* Check header */
   1386 
   1387     temp = buf[fc->scache_pos];
   1388     fc->scache_pos++;
   1389     temp |= buf[fc->scache_pos] << 8;
   1390     fc->scache_pos++;
   1391     temp |= buf[fc->scache_pos] << 16;
   1392     fc->scache_pos++;
   1393     temp |= buf[fc->scache_pos] << 24;
   1394     fc->scache_pos++;
   1395     if (temp != header) {
   1396         fc->l2warm = 0;
   1397 
   1398         return (BCM_E_INTERNAL);
   1399     }
   1400 
   1401     if(NULL != buf1) {
   1402         temp = buf1[fc->scache_pos1];
   1403         fc->scache_pos1++;
   1404         temp |= buf1[fc->scache_pos1] << 8;
   1405         fc->scache_pos1++;
   1406         temp |= buf1[fc->scache_pos1] << 16;
   1407         fc->scache_pos1++;
   1408         temp |= buf1[fc->scache_pos1] << 24;
   1409         fc->scache_pos1++;
   1410         if (temp != header) {
   1411             fc->l2warm = 0;
   1412             return (BCM_E_INTERNAL);
   1413         }
   1414     }
   1415 
   1416     if ((fc->wb_recovered_version) == BCM_FIELD_WB_VERSION_1_0) {
   1417         /* Old scache version, always uses compact ids */
   1418 
   1419         fc->flags &= ~_FP_STABLE_SAVE_LONG_IDS;
   1420         fc->flags &= ~_FP_AUTOEXPAND_WITH_POLICER;
   1421     } else {
   1422         /* Retrieve long-id setting */
   1423 
   1424         if (buf[fc->scache_pos] & _FP_STABLE_SAVE_LONG_IDS) {
   1425             fc->flags |= _FP_STABLE_SAVE_LONG_IDS;
   1426         } else {
   1427             fc->flags &= ~_FP_STABLE_SAVE_LONG_IDS;
   1428         }
   1429 
   1430         /* Retrieve Intra-slice device setting */
   1431         if (buf[fc->scache_pos] & _FP_INTRASLICE_ENABLE) {
   1432             fc->flags |= _FP_INTRASLICE_ENABLE;
   1433         } else {
   1434             fc->flags &= ~_FP_INTRASLICE_ENABLE;
   1435         }
   1436 
   1437         /* Retrieve color independent device setting */
   1438         if (buf[fc->scache_pos] & _FP_COLOR_INDEPENDENT) {
   1439             fc->flags |= _FP_COLOR_INDEPENDENT;
   1440         } else {
   1441             fc->flags &= ~_FP_COLOR_INDEPENDENT;
   1442         }
   1443 
   1444         /* Retrieve Stat sync device setting */
   1445         if (buf[fc->scache_pos] & _FP_STAT_SYNC_ENABLE) {
   1446             fc->flags |= _FP_STAT_SYNC_ENABLE;
   1447         } else {
   1448             fc->flags &= ~_FP_STAT_SYNC_ENABLE;
   1449         }
   1450 
   1451         /* Retrieve Group Sharing sync device setting */
   1452         if (buf[fc->scache_pos] & _FP_POLICER_GROUP_SHARE_ENABLE) {
   1453             fc->flags |= _FP_POLICER_GROUP_SHARE_ENABLE;
   1454         } else {
   1455             fc->flags &= ~_FP_POLICER_GROUP_SHARE_ENABLE;
   1456         }
   1457         /* Flag to allow attaching policer to an auto expanded slice */
   1458         if (buf[fc->scache_pos] & _FP_AUTOEXPAND_WITH_POLICER) {
   1459             fc->flags |= _FP_AUTOEXPAND_WITH_POLICER;
   1460         } else {
   1461             fc->flags &= ~_FP_AUTOEXPAND_WITH_POLICER;
   1462         }
   1463 
   1464         fc->scache_pos++;
   1465     }
   1466 
   1467     return (BCM_E_NONE);
   1468 }
   1469 
   1470 void
   1471 _field_scache_sync_data_quals_write(_field_control_t      *fc,
   1472                                     _field_data_control_t *data_ctrl
   1473                                     )
   1474 {
   1475     uint8                   *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0];
   1476     unsigned                cnt;
   1477     _field_data_qualifier_t *f_dq;
   1478 
   1479     LOG_DEBUG(BSL_LS_BCM_FP,
   1480               (BSL_META("FP vverb: _field_scache_sync_data_quals_write...\n")));
   1481     /* Write data qual count */
   1482 
   1483     for (cnt = 0, f_dq = data_ctrl->data_qual; f_dq; f_dq = f_dq->next, ++cnt);
   1484 
   1485     buf[fc->scache_pos] = cnt;
   1486     fc->scache_pos++;
   1487 
   1488     /* For each data qualifier, ... */
   1489     for (f_dq = data_ctrl->data_qual; f_dq; f_dq = f_dq->next) {
   1490         /* Write data qual id */
   1491 
   1492         buf[fc->scache_pos] = f_dq->qid;
   1493         fc->scache_pos++;
   1494         buf[fc->scache_pos] = f_dq->qid >> 8;
   1495         fc->scache_pos++;
   1496         buf[fc->scache_pos] = f_dq->qid >> 16;
   1497         fc->scache_pos++;
   1498         buf[fc->scache_pos] = f_dq->qid >> 24;
   1499         fc->scache_pos++;
   1500 
   1501         /* Write data qual "length remainder", flags and offset base */
   1502         buf[fc->scache_pos] = f_dq->elem_count * data_ctrl->elem_size
   1503                                 - f_dq->length
   1504                                 - f_dq->byte_offset;
   1505         fc->scache_pos++;
   1506         buf[fc->scache_pos] = f_dq->offset_base;
   1507         fc->scache_pos++;
   1508         buf[fc->scache_pos] = f_dq->flags;
   1509         fc->scache_pos++;
   1510         buf[fc->scache_pos] = f_dq->flags >> 8;
   1511         fc->scache_pos++;
   1512         buf[fc->scache_pos] = f_dq->flags >> 16;
   1513         fc->scache_pos++;
   1514         buf[fc->scache_pos] = f_dq->flags >> 24;
   1515         fc->scache_pos++;
   1516 
   1517         /* Write data qual match-data offset */
   1518         buf[fc->scache_pos] = f_dq->offset;
   1519         fc->scache_pos++;
   1520         buf[fc->scache_pos] = f_dq->offset >> 8;
   1521         fc->scache_pos++;
   1522 
   1523         /* Write data qual offset-table occupancy */
   1524         buf[fc->scache_pos] = f_dq->hw_bmap;
   1525         fc->scache_pos++;
   1526         buf[fc->scache_pos] = f_dq->hw_bmap >> 8;
   1527         fc->scache_pos++;
   1528     }
   1529 }
   1530 
   1531 
   1532 int
   1533 _field_scache_sync(int unit, _field_control_t *fc,
   1534                    _field_stage_t *stage_fc)
   1535 {
   1536     int slice_idx, range_count = 0;
   1537     int rv = BCM_E_NONE;
   1538     uint8 *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0];
   1539     uint8 *buf1 = fc->scache_ptr[_FIELD_SCACHE_PART_1];
   1540     _field_slice_t *fs;
   1541     _field_group_t *fg;
   1542     uint32 start_char, end_char;
   1543     int slice_is_primary;
   1544     int slice_mode;
   1545     _field_range_t *fr;
   1546     int ratio = 0;
   1547     int idx;
   1548     _field_entry_t *f_ent;
   1549 
   1550 
   1551     switch (stage_fc->stage_id) {
   1552     case _BCM_FIELD_STAGE_INGRESS:
   1553         start_char = _FIELD_IFP_DATA_START;
   1554         end_char = _FIELD_IFP_DATA_END;
   1555         break;
   1556     case _BCM_FIELD_STAGE_EGRESS:
   1557         start_char = _FIELD_EFP_DATA_START;
   1558         end_char = _FIELD_EFP_DATA_END;
   1559         break;
   1560     case _BCM_FIELD_STAGE_LOOKUP:
   1561         start_char = _FIELD_VFP_DATA_START;
   1562         end_char = _FIELD_VFP_DATA_END;
   1563         break;
   1564     default:
   1565         return BCM_E_PARAM;
   1566         break;
   1567     }
   1568 
   1569     LOG_DEBUG(BSL_LS_BCM_FP,
   1570               (BSL_META_U(unit,
   1571                           "_field_scache_sync: Synching scache for FP stage %d...\n"),
   1572                stage_fc->stage_id));
   1573 
   1574     _field_scache_stage_hdr_save(fc, start_char);
   1575 
   1576     /* Save the range check IDs */
   1577     if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) {
   1578         fr = stage_fc->ranges;
   1579         while (fr) {
   1580             fr = fr->next;
   1581             range_count++;
   1582         }
   1583         buf[fc->scache_pos] = (uint8)range_count;
   1584         fc->scache_pos++;
   1585         if (range_count) {
   1586             fr = stage_fc->ranges;
   1587             while (fr) {
   1588                 buf[fc->scache_pos] = fr->rid & 0xFF;
   1589                 fc->scache_pos++;
   1590                 buf[fc->scache_pos] = (fr->rid >> 8) & 0xFF;
   1591                 fc->scache_pos++;
   1592                 buf[fc->scache_pos] = (fr->rid >> 16) & 0xFF;
   1593                 fc->scache_pos++;
   1594                 buf[fc->scache_pos] = (fr->rid >> 24) & 0xFF;
   1595                 fc->scache_pos++;
   1596                 fr = fr->next;
   1597             }
   1598         }
   1599     }
   1600 
   1601     /* Save data qualifiers */
   1602 
   1603     if (stage_fc->data_ctrl != 0) {
   1604         _field_scache_sync_data_quals_write(fc, stage_fc->data_ctrl);
   1605     }
   1606 
   1607     _field_slice_map_write(unit, fc, stage_fc);
   1608 
   1609     /* First sync the master slices */
   1610     for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) {
   1611         LOG_DEBUG(BSL_LS_BCM_FP,
   1612                   (BSL_META_U(unit,
   1613                               "_field_scache_sync: Checking slice %d...\n"),
   1614                    slice_idx));
   1615 
   1616         /* Skip slices without groups */
   1617         fs = stage_fc->slices[_FP_DEF_INST] + slice_idx;
   1618         fg = fc->groups;
   1619         while (fg != NULL) {
   1620             if (fg->stage_id != stage_fc->stage_id) {
   1621                 fg = fg->next;
   1622                 continue; /* Not in this stage */
   1623             }
   1624             if (fg->slices[0].slice_number == slice_idx) {
   1625                 break;
   1626             }
   1627             fg = fg->next;
   1628         }
   1629         if (fg == NULL) {
   1630             continue; /* No group found */
   1631         }
   1632         /* Also skip expanded slices */
   1633         if (stage_fc->slices[_FP_DEF_INST][slice_idx].prev != NULL) {
   1634             continue;
   1635         }
   1636         /* Ignore secondary slice in paired mode */
   1637 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_ENDURO_SUPPORT) || defined(BCM_KATANA_SUPPORT)
   1638         if (SOC_IS_FIREBOLT2(unit) || SOC_IS_ENDURO(unit) ||
   1639             SOC_IS_KATANAX(unit) || SOC_IS_HURRICANEX(unit) ||
   1640             SOC_IS_GREYHOUND(unit) || SOC_IS_GREYHOUND2(unit)) {
   1641             soc_field_t fld;
   1642             int efp_slice_mode, paired = 0;
   1643             uint32 val;
   1644             fp_port_field_sel_entry_t pfs;
   1645             soc_field_t _fb2_slice_pairing_field[8] = {
   1646                                   SLICE1_0_PAIRINGf,   SLICE3_2_PAIRINGf,
   1647                                   SLICE5_4_PAIRINGf,   SLICE7_6_PAIRINGf,
   1648                                   SLICE9_8_PAIRINGf,   SLICE11_10_PAIRINGf,
   1649                                   SLICE13_12_PAIRINGf, SLICE15_14_PAIRINGf};
   1650             soc_field_t _efp_slice_mode[] = {SLICE_0_MODEf, SLICE_1_MODEf,
   1651                                              SLICE_2_MODEf, SLICE_3_MODEf};
   1652             soc_field_t _vfp_slice_pairing_field[2] = {SLICE1_0_PAIRINGf,
   1653                                                        SLICE3_2_PAIRINGf};
   1654             switch (stage_fc->stage_id) {
   1655             case _BCM_FIELD_STAGE_INGRESS:
   1656                 BCM_IF_ERROR_RETURN(soc_mem_read(unit, FP_PORT_FIELD_SELm,
   1657                                                  MEM_BLOCK_ANY, 0, &pfs));
   1658                 fld = _fb2_slice_pairing_field[slice_idx / 2];
   1659                 paired = soc_FP_PORT_FIELD_SELm_field32_get(unit,
   1660                                                             &pfs, fld);
   1661                 break;
   1662             case _BCM_FIELD_STAGE_EGRESS:
   1663                 BCM_IF_ERROR_RETURN(READ_EFP_SLICE_CONTROLr(unit, &val));
   1664                 efp_slice_mode = soc_reg_field_get(unit, EFP_SLICE_CONTROLr,
   1665                                                 val,_efp_slice_mode[slice_idx]);
   1666                 if ((efp_slice_mode == _BCM_FIELD_EGRESS_SLICE_MODE_DOUBLE)) {
   1667                     paired = 1;
   1668                 }
   1669                 break;
   1670             case _BCM_FIELD_STAGE_LOOKUP:
   1671                 BCM_IF_ERROR_RETURN(READ_VFP_KEY_CONTROLr(unit, &val));
   1672                 fld = _vfp_slice_pairing_field[slice_idx / 2];
   1673                 paired = soc_reg_field_get(unit, VFP_KEY_CONTROLr, val, fld);
   1674                 break;
   1675             default:
   1676                 return BCM_E_PARAM;
   1677                 break;
   1678             }
   1679             if (paired && (slice_idx % 2)) {
   1680                 continue;
   1681             }
   1682         }
   1683 #endif /* BCM_FIREBOLT2_SUPPORT */
   1684 
   1685 #ifdef BCM_FIREBOLT_SUPPORT
   1686         if (SOC_IS_FIREBOLT(unit))
   1687         {
   1688             BCM_IF_ERROR_RETURN(_field_fb_slice_is_primary(unit, slice_idx,
   1689                 &slice_is_primary, &slice_mode));
   1690 
   1691             if (!slice_is_primary)
   1692             {
   1693                 continue;
   1694             }
   1695         }
   1696 #endif /* BCM_FIREBOLT_SUPPORT */
   1697 
   1698 #ifdef BCM_RAVEN_SUPPORT
   1699         if (SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit))
   1700         {
   1701             BCM_IF_ERROR_RETURN(_field_fb_slice_is_primary(unit, slice_idx,
   1702                 &slice_is_primary, &slice_mode));
   1703 
   1704             if (!slice_is_primary)
   1705             {
   1706                 continue;
   1707             }
   1708         }
   1709 #endif /* BCM_RAVEN_SUPPORT */
   1710         BCM_IF_ERROR_RETURN
   1711             (_field_group_entry_write(unit, slice_idx, fs, fc, stage_fc));
   1712     }
   1713 
   1714     /* Now sync the expanded slices */
   1715     for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) {
   1716 
   1717         fs = stage_fc->slices[_FP_DEF_INST] + slice_idx;
   1718         /* Skip empty slices */
   1719         if (fs->entry_count == fs->free_count) {
   1720             LOG_DEBUG(BSL_LS_BCM_FP,
   1721                       (BSL_META_U(unit,
   1722                                   "_field_scache_sync:   Slice is empty.\n")));
   1723             continue;
   1724         }
   1725         /* Skip master slices */
   1726         if (stage_fc->slices[_FP_DEF_INST][slice_idx].prev == NULL) {
   1727             continue;
   1728         }
   1729 
   1730         /* Ignore secondary slice in paired mode */
   1731 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_ENDURO_SUPPORT) || defined(BCM_KATANA_SUPPORT)
   1732         if (SOC_IS_FIREBOLT2(unit) || SOC_IS_ENDURO(unit) ||
   1733             SOC_IS_KATANAX(unit) || SOC_IS_HURRICANEX(unit) ||
   1734             SOC_IS_GREYHOUND(unit) || SOC_IS_GREYHOUND2(unit)) {
   1735             soc_field_t fld;
   1736             int efp_slice_mode, paired = 0;
   1737             uint32 val;
   1738             fp_port_field_sel_entry_t pfs;
   1739             soc_field_t _fb2_slice_pairing_field[8] = {
   1740                                   SLICE1_0_PAIRINGf,   SLICE3_2_PAIRINGf,
   1741                                   SLICE5_4_PAIRINGf,   SLICE7_6_PAIRINGf,
   1742                                   SLICE9_8_PAIRINGf,   SLICE11_10_PAIRINGf,
   1743                                   SLICE13_12_PAIRINGf, SLICE15_14_PAIRINGf};
   1744             soc_field_t _efp_slice_mode[] = {SLICE_0_MODEf, SLICE_1_MODEf,
   1745                                              SLICE_2_MODEf, SLICE_3_MODEf};
   1746             soc_field_t _vfp_slice_pairing_field[2] = {SLICE1_0_PAIRINGf,
   1747                                                        SLICE3_2_PAIRINGf};
   1748             switch (stage_fc->stage_id) {
   1749             case _BCM_FIELD_STAGE_INGRESS:
   1750                 BCM_IF_ERROR_RETURN(soc_mem_read(unit, FP_PORT_FIELD_SELm,
   1751                                                  MEM_BLOCK_ANY, 0, &pfs));
   1752                 fld = _fb2_slice_pairing_field[slice_idx / 2];
   1753                 paired = soc_FP_PORT_FIELD_SELm_field32_get(unit,
   1754                                                             &pfs, fld);
   1755                 break;
   1756             case _BCM_FIELD_STAGE_EGRESS:
   1757                 BCM_IF_ERROR_RETURN(READ_EFP_SLICE_CONTROLr(unit, &val));
   1758                 efp_slice_mode = soc_reg_field_get(unit, EFP_SLICE_CONTROLr,
   1759                                                 val,_efp_slice_mode[slice_idx]);
   1760                 if ((efp_slice_mode == _BCM_FIELD_EGRESS_SLICE_MODE_DOUBLE)) {
   1761                     paired = 1;
   1762                 }
   1763                 break;
   1764             case _BCM_FIELD_STAGE_LOOKUP:
   1765                 BCM_IF_ERROR_RETURN(READ_VFP_KEY_CONTROLr(unit, &val));
   1766                 fld = _vfp_slice_pairing_field[slice_idx / 2];
   1767                 paired = soc_reg_field_get(unit, VFP_KEY_CONTROLr, val, fld);
   1768                 break;
   1769             default:
   1770                 return BCM_E_PARAM;
   1771                 break;
   1772             }
   1773             if (paired && (slice_idx % 2)) {
   1774                 continue;
   1775             }
   1776         }
   1777 #endif /* BCM_FIREBOLT2_SUPPORT */
   1778 
   1779 #ifdef BCM_FIREBOLT_SUPPORT
   1780         if (SOC_IS_FIREBOLT(unit))
   1781         {
   1782             BCM_IF_ERROR_RETURN(_field_fb_slice_is_primary(unit, slice_idx,
   1783                 &slice_is_primary, &slice_mode));
   1784 
   1785             if (!slice_is_primary)
   1786             {
   1787                 continue;
   1788             }
   1789         }
   1790 #endif /* BCM_FIREBOLT_SUPPORT */
   1791 
   1792 #ifdef BCM_RAVEN_SUPPORT
   1793         if (SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit))
   1794         {
   1795             BCM_IF_ERROR_RETURN(_field_fb_slice_is_primary(unit, slice_idx,
   1796                 &slice_is_primary, &slice_mode));
   1797 
   1798             if (!slice_is_primary)
   1799             {
   1800                 continue;
   1801             }
   1802         }
   1803 #endif /* BCM_RAVEN_SUPPORT */
   1804 
   1805         /*
   1806          * Skip expanded slices with no entries installed in Hw
   1807          * to match recovery logic.
   1808          */
   1809         if (fs->group_flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
   1810             ratio = 2;
   1811         } else {
   1812             ratio = 1;
   1813         }
   1814 
   1815         for (idx = 0; idx < fs->entry_count / ratio; idx++) {
   1816             /* Find EID that matches this HW index */
   1817             f_ent = fs->entries[idx];
   1818             if (f_ent == NULL) {
   1819                 continue;
   1820             }
   1821             if (!(f_ent->flags & _FP_ENTRY_INSTALLED)) {
   1822                 continue;
   1823             }
   1824             break;
   1825         }
   1826 
   1827         if (idx == (fs->entry_count / ratio)) {
   1828             continue;
   1829         }
   1830 
   1831         BCM_IF_ERROR_RETURN
   1832             (_field_group_entry_write(unit, slice_idx, fs, fc, stage_fc));
   1833     }
   1834 
   1835     /* Mark end of Slice Info */
   1836     buf[fc->scache_pos] = _FP_WB_END_OF_SLICES;
   1837     fc->scache_pos++;
   1838 
   1839     /* Group Slice Selectors */
   1840     BCM_IF_ERROR_RETURN(_field_group_slice_selectors_sync(unit,
   1841                         &buf[fc->scache_pos], stage_fc->stage_id));
   1842 
   1843     LOG_DEBUG(BSL_LS_BCM_FP,
   1844               (BSL_META_U(unit,
   1845                           "_field_scache_sync: Writing end of section @ byte %d.\n"),
   1846                fc->scache_pos));
   1847 
   1848     /* Mark the end of the IFP section */
   1849     buf[fc->scache_pos] = end_char & 0xFF;
   1850     fc->scache_pos++;
   1851     buf[fc->scache_pos] = (end_char >> 8) & 0xFF;
   1852     fc->scache_pos++;
   1853     buf[fc->scache_pos] = (end_char >> 16) & 0xFF;
   1854     fc->scache_pos++;
   1855     buf[fc->scache_pos] = (end_char >> 24) & 0xFF;
   1856     fc->scache_pos++;
   1857     fc->scache_usage = fc->scache_pos; /* Usage in bytes */
   1858 
   1859 
   1860     if(NULL != buf1) {
   1861         /* Mark the end of the IFP section */
   1862         buf1[fc->scache_pos1] = end_char & 0xFF;
   1863         fc->scache_pos1++;
   1864         buf1[fc->scache_pos1] = (end_char >> 8) & 0xFF;
   1865         fc->scache_pos1++;
   1866         buf1[fc->scache_pos1] = (end_char >> 16) & 0xFF;
   1867         fc->scache_pos1++;
   1868         buf1[fc->scache_pos1] = (end_char >> 24) & 0xFF;
   1869         fc->scache_pos1++;
   1870     }
   1871 
   1872     /* Check for overflow */
   1873     if (fc->scache_pos > fc->scache_size[_FIELD_SCACHE_PART_0]) {
   1874         LOG_DEBUG(BSL_LS_BCM_FP,
   1875                 (BSL_META_U(unit,
   1876                             "FP(unit %d) Error: Current Scache Position[%u] exceeds Scache size[%u]\n"),
   1877                  unit, fc->scache_pos, fc->scache_size[_FIELD_SCACHE_PART_0]));
   1878         return BCM_E_INTERNAL;
   1879     }
   1880 
   1881     if (buf1 != NULL) {
   1882         if (fc->scache_pos1 > fc->scache_size[_FIELD_SCACHE_PART_1]) {
   1883             LOG_DEBUG(BSL_LS_BCM_FP,
   1884                     (BSL_META_U(unit,
   1885                                 "FP(unit %d) Error: Current Scache Position1[%u] exceeds Scache size[%u]\n"),
   1886                      unit, fc->scache_pos1, fc->scache_size[_FIELD_SCACHE_PART_1]));
   1887             return BCM_E_INTERNAL;
   1888         }
   1889     }
   1890 
   1891     return rv;
   1892 }
   1893 
   1894 /* Recover FP data qualifiers */
   1895 
   1896 int
   1897 _field_data_qual_recover(int              unit,
   1898                          _field_control_t *fc,
   1899                          _field_stage_t   *stage_fc
   1900                          )
   1901 {
   1902     _field_data_control_t          *data_ctrl;
   1903     uint8                          *buf;
   1904     unsigned                       dqcnt, n, i, len_rem;
   1905     _field_data_qualifier_t        *f_dq = NULL;
   1906 
   1907     if ((data_ctrl = stage_fc->data_ctrl) == 0) {
   1908         return (BCM_E_NONE);
   1909     }
   1910 
   1911     if (fc->l2warm == 0) {
   1912         /* No data qualifier recovery in Level 1 */
   1913         return BCM_E_NONE;
   1914     }
   1915 
   1916     buf = fc->scache_ptr[_FIELD_SCACHE_PART_0];
   1917 
   1918 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT)
   1919 
   1920     if (soc_mem_is_valid(unit, FP_UDF_TCAMm)) {
   1921         /* Device has UDF TCAM =>
   1922            Recover internal information regarding TCAM entry usage
   1923         */
   1924 
   1925         int                            rv;
   1926         fp_udf_tcam_entry_t            fp_udf_tcam_entry;
   1927         _field_data_tcam_entry_t       *tcam_entryp;
   1928         bcm_field_data_packet_format_t pkt_fmt;
   1929         int8 valid = 0;
   1930         uint32 field = 1;
   1931         uint32 mask = 0;
   1932         uint32 ct;
   1933 
   1934         /* Recover TCAM entry reference counts and priorities */
   1935         for (tcam_entryp = data_ctrl->tcam_entry_arr,
   1936                  i = 0,
   1937                  n = soc_mem_index_count(unit, FP_UDF_TCAMm);
   1938              n;
   1939              --n, ++i, ++tcam_entryp) {
   1940             tcam_entryp->ref_count = buf[fc->scache_pos];
   1941             fc->scache_pos++;
   1942 
   1943             BCM_IF_ERROR_RETURN(soc_mem_read(unit,
   1944                                              FP_UDF_TCAMm,
   1945                                              MEM_BLOCK_ANY,
   1946                                              i,
   1947                                              fp_udf_tcam_entry.entry_data
   1948                                              )
   1949                                 );
   1950 
   1951             if (tcam_entryp->ref_count == 0) {
   1952                 /* TCAM entry is not in use */
   1953 
   1954                 /* Consistency check: the valid bit for the TCAM entry
   1955                    better be cleared!
   1956                 */
   1957                 if (soc_mem_field32_get(unit,
   1958                                         FP_UDF_TCAMm,
   1959                                         fp_udf_tcam_entry.entry_data,
   1960                                         VALIDf
   1961                                         )
   1962                     != 0
   1963                     ) {
   1964                         /* Using new UDF module, value of ref_count always
   1965                            equal zero, but field VALIDf of used UDF entry
   1966                            equals to one. So need to skip this case.
   1967                         */
   1968                         if (soc_feature(unit, soc_feature_udf_support)) {
   1969                             if (UDF_CTRL(unit)->udf_used_by_module
   1970                                 == UDF_USED_BY_FIELD_MODULE) {
   1971                                 return (BCM_E_INTERNAL);
   1972                             }
   1973                         } else {
   1974                             return (BCM_E_INTERNAL);
   1975                         }
   1976                 }
   1977 
   1978                 continue;
   1979             }
   1980 
   1981             /* TCAM entry is in use */
   1982 
   1983             /* Consistency check: the valid bit for the TCAM entry
   1984                better be set!
   1985             */
   1986             if (soc_mem_field32_get(unit,
   1987                                     FP_UDF_TCAMm,
   1988                                     fp_udf_tcam_entry.entry_data,
   1989                                     VALIDf
   1990                                     )
   1991                 == 0
   1992                 ) {
   1993                 return (BCM_E_INTERNAL);
   1994             }
   1995 
   1996             bcm_field_data_packet_format_t_init(&pkt_fmt);
   1997 
   1998             /* Parse l2 format.*/
   1999             rv = _field_trx2_udf_tcam_entry_l2format_parse(
   2000                      unit,
   2001                      fp_udf_tcam_entry.entry_data,
   2002                      &pkt_fmt.l2
   2003                                                            );
   2004             BCM_IF_ERROR_RETURN(rv);
   2005 
   2006             /* Parse vlan_tag format.*/
   2007             rv = _field_trx2_udf_tcam_entry_vlanformat_parse(
   2008                      unit,
   2009                      fp_udf_tcam_entry.entry_data,
   2010                      &pkt_fmt.vlan_tag
   2011                                                              );
   2012             BCM_IF_ERROR_RETURN(rv);
   2013 
   2014             /* Parse l3 fields.*/
   2015             rv = _field_trx2_udf_tcam_entry_l3_parse(
   2016                       unit,
   2017                       fp_udf_tcam_entry.entry_data,
   2018                       &pkt_fmt
   2019                                                      );
   2020             BCM_IF_ERROR_RETURN(rv);
   2021 
   2022             /* Parse Udf flags */
   2023             rv = _field_trx2_udf_tcam_entry_flags_parse(
   2024                     unit,
   2025                     fp_udf_tcam_entry.entry_data,
   2026                     &pkt_fmt.flags);
   2027 
   2028             BCM_IF_ERROR_RETURN(rv);
   2029 
   2030             /* Recover TCAM entry priority */
   2031             tcam_entryp->priority = 0;
   2032             if (pkt_fmt.l2 != BCM_FIELD_DATA_FORMAT_L2_ANY) {
   2033                 /* L2 format was specified */
   2034 
   2035                 tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_L2_FORMAT;
   2036             }
   2037 
   2038             if (pkt_fmt.vlan_tag != BCM_FIELD_DATA_FORMAT_VLAN_TAG_ANY) {
   2039                 /* Vlan tag format was specified */
   2040 
   2041                 tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_VLAN_FORMAT;
   2042             }
   2043 
   2044             if (pkt_fmt.tunnel == BCM_FIELD_DATA_FORMAT_TUNNEL_NONE
   2045                 && pkt_fmt.outer_ip == BCM_FIELD_DATA_FORMAT_IP_ANY
   2046                 && pkt_fmt.inner_ip == BCM_FIELD_DATA_FORMAT_IP_NONE
   2047                 ) {
   2048                 /* Entry corresponds to a call to
   2049                    bcm_field_data_qualifier_ip_protocol_add() or
   2050                    bcm_field_data_qualifier_ethertype_add()
   2051                 */
   2052 
   2053                 if (soc_mem_field32_get(unit,
   2054                                         FP_UDF_TCAMm,
   2055                                         fp_udf_tcam_entry.entry_data,
   2056                                         L3_FIELDS_MASKf)
   2057 
   2058                     ) {
   2059                     if ((soc_mem_field32_get(unit,
   2060                                              FP_UDF_TCAMm,
   2061                                              fp_udf_tcam_entry.entry_data,
   2062                                              L3_FIELDSf)
   2063                                             & 0xff0000) >> 16
   2064 
   2065                         ) {
   2066                         tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_IPPROTO;
   2067                     }
   2068                 }
   2069                 tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_MISC;
   2070             } else {
   2071                 /* Entry corresponds to a call to
   2072                    bcm_field_data_qualifier_packet_format_add()
   2073                  */
   2074                 if ((pkt_fmt.tunnel == BCM_FIELD_DATA_FORMAT_TUNNEL_NONE) ||
   2075                     (pkt_fmt.tunnel == BCM_FIELD_DATA_FORMAT_TUNNEL_IP_IN_IP) ||
   2076                     (pkt_fmt.tunnel == BCM_FIELD_DATA_FORMAT_TUNNEL_GRE)) {
   2077 
   2078                     tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_L3_FORMAT;
   2079 
   2080                 } else  if (pkt_fmt.tunnel == BCM_FIELD_DATA_FORMAT_TUNNEL_FCOE
   2081                         || pkt_fmt.tunnel == BCM_FIELD_DATA_FORMAT_TUNNEL_FCOE_INIT) {
   2082 
   2083                     tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_FCOE_FORMAT;
   2084                     /*
   2085                      * Entry matching on Outer + Inner FCOE extended headers has
   2086                      * higher priority.
   2087                      */
   2088                     if ((BCM_FIELD_DATA_FORMAT_FIBRE_CHAN_ANY
   2089                                 != pkt_fmt.fibre_chan_outer)
   2090                             && (BCM_FIELD_DATA_FORMAT_FIBRE_CHAN_ANY
   2091                                 != pkt_fmt.fibre_chan_inner)) {
   2092                         tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_FCOE_FORMAT;
   2093                     }
   2094                 } else if (pkt_fmt.tunnel == BCM_FIELD_DATA_FORMAT_TUNNEL_MPLS) {
   2095 
   2096                     tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_MPLS_FORMAT;
   2097 
   2098                     switch(pkt_fmt.mpls) {
   2099                         case BCM_FIELD_DATA_FORMAT_MPLS_ONE_LABEL:
   2100                             tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_MPLS_ONE_LABEL;
   2101                             break;
   2102                         case BCM_FIELD_DATA_FORMAT_MPLS_TWO_LABELS:
   2103                             tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_MPLS_TWO_LABEL;
   2104                             break;
   2105                         case BCM_FIELD_DATA_FORMAT_MPLS_THREE_LABELS:
   2106                             tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_MPLS_THREE_LABEL;
   2107                             break;
   2108                         case BCM_FIELD_DATA_FORMAT_MPLS_FOUR_LABELS:
   2109                             tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_MPLS_FOUR_LABEL;
   2110                             break;
   2111                         case BCM_FIELD_DATA_FORMAT_MPLS_FIVE_LABELS:
   2112                             tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_MPLS_FIVE_LABEL;
   2113                             break;
   2114                         case BCM_FIELD_DATA_FORMAT_MPLS_ANY:
   2115                             break;
   2116                         default:
   2117                             return (BCM_E_INTERNAL);
   2118                     }
   2119                 }
   2120 
   2121                 tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_L3_FORMAT;
   2122             }
   2123             /* Update Priority based on UDF Flags */
   2124             for (ct = 0; ; ct++) {
   2125                 if (udf_fields_f[ct][field] == INVALIDf) {
   2126                     break;
   2127                 }
   2128 
   2129                 valid = soc_mem_field_valid(unit, FP_UDF_TCAMm,
   2130                         udf_fields_f[ct][field]);
   2131                 if (valid == TRUE) {
   2132                     if (soc_mem_field32_get(unit, FP_UDF_TCAMm,
   2133                                 fp_udf_tcam_entry.entry_data, udf_fields_f[ct][mask])) {
   2134                         tcam_entryp->priority += _FP_DATA_QUALIFIER_PRIO_FLAGS;
   2135                     }
   2136                 }
   2137             }
   2138         }
   2139     }
   2140 
   2141 #endif /* defined(BCM_TRIDENT_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT) */
   2142 
   2143     for (dqcnt = buf[fc->scache_pos++]; dqcnt; --dqcnt) {
   2144         _bcm_field_data_qualifier_alloc(unit, &f_dq);
   2145 
   2146         /* Read data qual id */
   2147 
   2148         f_dq->qid = buf[fc->scache_pos];
   2149         fc->scache_pos++;
   2150         f_dq->qid |= buf[fc->scache_pos] << 8;
   2151         fc->scache_pos++;
   2152         f_dq->qid |= buf[fc->scache_pos] << 16;
   2153         fc->scache_pos++;
   2154         f_dq->qid |= buf[fc->scache_pos] << 24;
   2155         fc->scache_pos++;
   2156 
   2157         /* Read data qual "length remainder", flags and offset base */
   2158         if ((fc->wb_recovered_version) < BCM_FIELD_WB_VERSION_1_10) {
   2159             len_rem           = buf[fc->scache_pos] >> 6;
   2160             f_dq->flags       = (buf[fc->scache_pos] >> 1)
   2161                 & _BCM_FIELD_DATA_QUALIFIER_FLAGS;
   2162             f_dq->offset_base = buf[fc->scache_pos] & 7;
   2163             fc->scache_pos++;
   2164         } else {
   2165             len_rem           = buf[fc->scache_pos];
   2166             fc->scache_pos++;
   2167 
   2168             f_dq->offset_base = buf[fc->scache_pos];
   2169             fc->scache_pos++;
   2170 
   2171             f_dq->flags = buf[fc->scache_pos];
   2172             fc->scache_pos++;
   2173             f_dq->flags |= buf[fc->scache_pos] << 8;
   2174             fc->scache_pos++;
   2175             f_dq->flags |= buf[fc->scache_pos] << 16;
   2176             fc->scache_pos++;
   2177             f_dq->flags |= buf[fc->scache_pos] << 24;
   2178             fc->scache_pos++;
   2179         }
   2180 
   2181         /* Read data qual match-data offset */
   2182         f_dq->offset = buf[fc->scache_pos];
   2183         fc->scache_pos++;
   2184         f_dq->offset |= buf[fc->scache_pos] << 8;
   2185         fc->scache_pos++;
   2186 
   2187         /* Read data qual hw_bmap */
   2188         f_dq->hw_bmap = buf[fc->scache_pos];
   2189         fc->scache_pos++;
   2190         f_dq->hw_bmap |= buf[fc->scache_pos] << 8;
   2191         fc->scache_pos++;
   2192 
   2193         /* Find number of elements used */
   2194         for (f_dq->elem_count = i = 0, n = (2 * stage_fc->data_ctrl->num_elems);
   2195              n;
   2196              --n, ++i
   2197              ) {
   2198             if (f_dq->hw_bmap & (1U << i)) {
   2199                 ++f_dq->elem_count;
   2200             }
   2201         }
   2202 
   2203         /* Consistency check: hw_bmap should not be 0! */
   2204         if (f_dq->elem_count == 0) {
   2205             _bcm_field_data_qualifier_free(unit, f_dq);
   2206 
   2207             return (BCM_E_INTERNAL);
   2208         }
   2209 
   2210         _field_data_qualifier_init2(unit, stage_fc, f_dq);
   2211 
   2212         f_dq->length = f_dq->elem_count * data_ctrl->elem_size
   2213             - f_dq->byte_offset
   2214             - len_rem;
   2215 
   2216         /* N.B.  fq->flags is not applicable for Triumph2 => Leave as 0 */
   2217 
   2218         /* Merge qualifier's hw_bmap into overall uasge bmap */
   2219         data_ctrl->usage_bmap |= f_dq->hw_bmap;
   2220     }
   2221 
   2222     return (BCM_E_NONE);
   2223 }
   2224 
   2225 
   2226 /* Update a qset's udf_bmap to reflect actual data qualifier usage. */
   2227 
   2228 void
   2229 _field_qset_udf_bmap_reinit(int              unit,
   2230                             _field_stage_t   *stage_fc,
   2231                             bcm_field_qset_t *qset,
   2232                             int              qual_id
   2233                             )
   2234 {
   2235     _field_data_qualifier_t *f_dq;
   2236     unsigned                elem_idx, n;
   2237     int                     rv;
   2238     _field_stage_t          *ingress_stage_fc = NULL;
   2239     _field_control_t        *fc = NULL;
   2240 
   2241     rv = _field_control_get(unit, &fc);
   2242     if (BCM_FAILURE(rv)) {
   2243         return;
   2244     }
   2245     if (fc->l2warm) {
   2246         if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_10) {
   2247             return;
   2248         }
   2249     }
   2250 
   2251 #if defined(BCM_ENDURO_SUPPORT)
   2252     if(SOC_IS_ENDURO(unit) || SOC_IS_HURRICANEX(unit) ||
   2253         SOC_IS_GREYHOUND(unit) || SOC_IS_GREYHOUND2(unit)) {
   2254         if (qual_id < _bcmFieldQualifyData0 || qual_id > _bcmFieldQualifyData3) {
   2255             return;
   2256         }
   2257     } else
   2258 #endif /* BCM_ENDURO_SUPPORT */
   2259 #if defined(BCM_TOMAHAWK_SUPPORT)
   2260     if(soc_feature(unit, soc_feature_field_multi_pipe_support))
   2261     {
   2262         if (qual_id < _bcmFieldQualifyData0 || qual_id > _bcmFieldQualifyData9) {
   2263             return;
   2264         }
   2265     } else
   2266 #endif /*BCM_TOMAHAWK_SUPPORT*/
   2267 #if defined(BCM_TOMAHAWK3_SUPPORT)
   2268     if (soc_feature(unit, soc_feature_udf_selector_support)) {
   2269         if (qual_id < _bcmFieldQualifyData0
   2270             || qual_id > _bcmFieldQualifyData15) {
   2271             return;
   2272         }
   2273     } else
   2274 #endif /*BCM_TOMAHAWK3_SUPPORT*/
   2275 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_KATANA_SUPPORT)
   2276     if ((SOC_IS_TD_TT(unit)
   2277          || SOC_IS_KATANAX(unit)
   2278          || SOC_IS_TRIUMPH3(unit))) {
   2279         if (qual_id < _bcmFieldQualifyData0 || qual_id > _bcmFieldQualifyData3) {
   2280             return;
   2281         }
   2282 
   2283     } else
   2284 #endif /* BCM_TRIDENT_SUPPORT || BCM_KATANA_SUPPORT*/
   2285     {
   2286         if (qual_id < _bcmFieldQualifyData0 || qual_id > _bcmFieldQualifyData1) {
   2287             return;
   2288         }
   2289     }
   2290 
   2291     /* UDF elements are always stored in Ingress stage control
   2292          * irrespective of it being used in any other stage */
   2293     rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &ingress_stage_fc);
   2294     if (BCM_FAILURE(rv)) {
   2295         return;
   2296     }
   2297 
   2298     for (f_dq = ingress_stage_fc->data_ctrl->data_qual ; f_dq; f_dq = f_dq->next) {
   2299         for (elem_idx = 0, n = ingress_stage_fc->data_ctrl->num_elems * 2; n; --n, ++elem_idx) {
   2300             if ((f_dq->hw_bmap & (1U << elem_idx)) == 0) {
   2301                 continue;
   2302             }
   2303 
   2304             SHR_BITSET(qset->udf_map, elem_idx);
   2305         }
   2306     }
   2307 
   2308 #if defined (BCM_TRIUMPH2_SUPPORT)
   2309     if (soc_feature(unit, soc_feature_udf_support)) {
   2310         bcmi_xgs4_udf_offset_info_t *tmp;
   2311         UDF_LOCK(unit);
   2312         for (tmp = UDF_CTRL(unit)->offset_info_head; tmp; tmp = tmp->next) {
   2313             for (elem_idx = 0, n = BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit); n; --n, ++elem_idx) {
   2314                 if ((tmp->hw_bmap & (1U << elem_idx)) == 0) {
   2315                     continue;
   2316                 }
   2317 
   2318                 SHR_BITSET(qset->udf_map, elem_idx);
   2319             }
   2320         }
   2321         UDF_UNLOCK(unit);
   2322     }
   2323 #endif
   2324 
   2325 }
   2326 
   2327 
   2328 /* Recover range checkers */
   2329 int
   2330 _field_range_check_reinit(int unit, _field_stage_t *stage_fc,
   2331                           _field_control_t *fc)
   2332 {
   2333     int idx, index_min, index_max, count, valid_count;
   2334     uint32 enable, type;
   2335     soc_mem_t mem;
   2336     uint32 tbl_entry[SOC_MAX_MEM_FIELD_WORDS];
   2337     _field_range_t *fr, **last_fr;
   2338     uint8 *buf = fc->scache_ptr[_FIELD_SCACHE_PART_0];
   2339 
   2340     count = valid_count = 0;
   2341     if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) {
   2342         mem = FP_RANGE_CHECKm;
   2343     } else {
   2344         mem = ESM_RANGE_CHECKm;
   2345     }
   2346     if (fc->l2warm) {
   2347         count = buf[fc->scache_pos];
   2348         fc->scache_pos++;
   2349     }
   2350 
   2351     last_fr = &stage_fc->ranges;
   2352     index_min = soc_mem_index_min(unit, mem);
   2353     index_max = soc_mem_index_max(unit, mem);
   2354     for (idx = index_min; idx <= index_max; idx ++) {
   2355         sal_memset(tbl_entry, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   2356         BCM_IF_ERROR_RETURN
   2357             (soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx, tbl_entry));
   2358         soc_mem_field_get(unit, mem, tbl_entry, ENABLEf, &enable);
   2359         if (enable == 0) {
   2360             continue;
   2361         }
   2362         valid_count++;
   2363         /* Create a new range entry for the list */
   2364         if ((fr = sal_alloc(sizeof (*fr), "fp_range")) == NULL) {
   2365             return (BCM_E_MEMORY);
   2366         }
   2367         sal_memset(fr, 0, sizeof(_field_range_t));
   2368         /* Populate the structure */
   2369         if (fc->l2warm) {
   2370             /* Get the IDs */
   2371             fr->rid = 0;
   2372             fr->rid |= buf[fc->scache_pos];
   2373             fc->scache_pos++;
   2374             fr->rid |= buf[fc->scache_pos] << 8;
   2375             fc->scache_pos++;
   2376             fr->rid |= buf[fc->scache_pos] << 16;
   2377             fc->scache_pos++;
   2378             fr->rid |= buf[fc->scache_pos] << 24;
   2379             fc->scache_pos++;
   2380         } else {
   2381             fr->rid = idx;
   2382         }
   2383         fr->hw_index = idx;
   2384         fr->style = _FP_RANGE_STYLE_FIREBOLT;
   2385         soc_mem_field_get(unit, mem, tbl_entry, LOWER_BOUNDSf,
   2386                           (uint32 *)&(fr->min));
   2387         soc_mem_field_get(unit, mem, tbl_entry, UPPER_BOUNDSf,
   2388                           (uint32 *)&(fr->max));
   2389         if ((SOC_MEM_FIELD_VALID(unit, mem, FIELD_SELECTf))) {
   2390             soc_mem_field_get(unit, mem, tbl_entry, FIELD_SELECTf, &type);
   2391             switch (type) {
   2392             case 0:
   2393                 fr->flags |= BCM_FIELD_RANGE_SRCPORT;
   2394                 break;
   2395             case 1:
   2396                 fr->flags |= BCM_FIELD_RANGE_DSTPORT;
   2397                 break;
   2398             case 2:
   2399                 fr->flags |= BCM_FIELD_RANGE_OUTER_VLAN;
   2400                 break;
   2401             case 3:
   2402                 fr->flags |= BCM_FIELD_RANGE_PACKET_LENGTH;
   2403                 break;
   2404             default:
   2405                 break; /* Should never happen */
   2406             }
   2407         } else {
   2408             soc_mem_field_get(unit, mem, tbl_entry,
   2409                               SOURCE_DESTINATION_SELECTf, &type);
   2410             if (type == 1) {
   2411                 fr->flags |= BCM_FIELD_RANGE_SRCPORT;
   2412             } else {
   2413                 fr->flags |= BCM_FIELD_RANGE_DSTPORT;
   2414             }
   2415         }
   2416 
   2417         /* Add to list of range checkers. */
   2418 
   2419         *last_fr = fr;
   2420         last_fr = &fr->next;
   2421     }
   2422     if (fc->l2warm && count != valid_count) {
   2423         return BCM_E_INTERNAL;
   2424     }
   2425     return BCM_E_NONE;
   2426 }
   2427 
   2428 STATIC int
   2429 _field_scache_version_size_check(int unit, int former_size,
   2430                                  uint16 former_version,
   2431                                  int current_size,
   2432                                  uint16 current_version)
   2433 {
   2434     int delta_size[10] = {0};
   2435     uint16 fversion, cversion;
   2436     int fsize, csize, cumul_delta_size = 0;
   2437 
   2438     /* Incremental size for BCM_FIELD_WB_VERSION_1_6 */
   2439     delta_size[0] = 16 * 1024;
   2440     /* Incremental size for BCM_FIELD_WB_VERSION_1_8 */
   2441     delta_size[1] = 128 * 1024;
   2442     /* Incremental size for BCM_FIELD_WB_VERSION_1_15 */
   2443     delta_size[2] = 135 * 1024;
   2444     /* Incremental size for BCM_FIELD_WB_VERSION_1_17 */
   2445     delta_size[3] = 144 * 1024;
   2446     /* Incremental size for BCM_FIELD_WB_VERSION_1_18 */
   2447     delta_size[4] = 21 * 1024;
   2448     /* Incremental size for BCM_FIELD_WB_VERSION_1_19 */
   2449     delta_size[5] = 264 * 1024;
   2450     /* Incremental size for BCM_FIELD_WB_VERSION_1_20 */
   2451     delta_size[6] = 48 * 1024;
   2452     /* Incremental size for action bcmFieldActionFabricQueue
   2453      * adding for BCM_FIELD_WB_VERSION_1_20
   2454      */
   2455     delta_size[6] += (16 * 1024 * 4);
   2456     /* Incremental size for BCM_FIELD_WB_VERSION_1_21 */
   2457     delta_size[7] = (512 * _SHR_PBMP_WORD_MAX * 4) + (16 * 1024 * 12);
   2458     /* Incremental size for BCM_FIELD_WB_VERSION_1_23 */
   2459     delta_size[8] = (128 * 4);
   2460     /* Incremental size for BCM_FIELD_WB_VERSION_1_26 */
   2461     delta_size[9] = (_FP_MAX_NUM_PIPES
   2462                      + (_FP_MAX_NUM_PIPES * 8));
   2463 
   2464     fversion = former_version;
   2465     cversion = current_version;
   2466     fsize    = former_size;
   2467     csize    = current_size;
   2468 
   2469     /* This logic only handle upgrade warmboot case, don't consider downgrade case */
   2470         if (fversion < BCM_FIELD_WB_VERSION_1_5) {
   2471             /* skip too old version */
   2472             return TRUE;
   2473         }
   2474 
   2475     if ((fversion < BCM_FIELD_WB_VERSION_1_6)
   2476             && (cversion >= BCM_FIELD_WB_VERSION_1_6)) {
   2477         cumul_delta_size += delta_size[0];
   2478     }
   2479 
   2480     if ((fversion < BCM_FIELD_WB_VERSION_1_8)
   2481             && (cversion >= BCM_FIELD_WB_VERSION_1_8)) {
   2482         cumul_delta_size += delta_size[1];
   2483     }
   2484 
   2485     if ((fversion < BCM_FIELD_WB_VERSION_1_15)
   2486             && (cversion >= BCM_FIELD_WB_VERSION_1_15)) {
   2487         cumul_delta_size += delta_size[2];
   2488     }
   2489 
   2490     if ((fversion < BCM_FIELD_WB_VERSION_1_17)
   2491             && (cversion >= BCM_FIELD_WB_VERSION_1_17)) {
   2492         cumul_delta_size += delta_size[3];
   2493     }
   2494 
   2495     if ((fversion < BCM_FIELD_WB_VERSION_1_18)
   2496             && (cversion >= BCM_FIELD_WB_VERSION_1_18)) {
   2497         cumul_delta_size += delta_size[4];
   2498     }
   2499 
   2500     if ((fversion < BCM_FIELD_WB_VERSION_1_19)
   2501             && (cversion >= BCM_FIELD_WB_VERSION_1_19)) {
   2502         cumul_delta_size += delta_size[5];
   2503     }
   2504 
   2505     if ((fversion < BCM_FIELD_WB_VERSION_1_20)
   2506             && (cversion >= BCM_FIELD_WB_VERSION_1_20)) {
   2507         cumul_delta_size += delta_size[6];
   2508     }
   2509 
   2510     if ((fversion < BCM_FIELD_WB_VERSION_1_21)
   2511             && (cversion >= BCM_FIELD_WB_VERSION_1_21)) {
   2512         cumul_delta_size += delta_size[7];
   2513     }
   2514 
   2515     if ((fversion < BCM_FIELD_WB_VERSION_1_23)
   2516             && (cversion >= BCM_FIELD_WB_VERSION_1_23)) {
   2517         cumul_delta_size += delta_size[8];
   2518     }
   2519 
   2520     if ((fversion < BCM_FIELD_WB_VERSION_1_26)
   2521             && (cversion >= BCM_FIELD_WB_VERSION_1_26)) {
   2522         cumul_delta_size += delta_size[9];
   2523     }
   2524 
   2525     if ((fversion < cversion) &&
   2526             ((csize - fsize) != (cumul_delta_size))) {
   2527                 return FALSE;
   2528             }
   2529 
   2530     return TRUE;
   2531 }
   2532 
   2533 /* Initialize field component scache pointers and scache sizes for
   2534    multiple partitions */
   2535 int
   2536 _field_scache_pointer_init(int unit, _field_control_t  *fc)
   2537 {
   2538     int               stable_size;
   2539     int               rv;
   2540     uint32            alloc_get;
   2541     soc_scache_handle_t handle;
   2542 
   2543     if ((NULL == fc->scache_ptr[_FIELD_SCACHE_PART_0]) ||
   2544         (NULL == fc->scache_ptr[_FIELD_SCACHE_PART_1])) {
   2545 
   2546         SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   2547         SOC_SCACHE_HANDLE_SET(handle, unit, BCM_MODULE_FIELD,
   2548                               _FIELD_SCACHE_PART_0);
   2549         if ((stable_size > 0) && !SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
   2550             if (SOC_IS_TRX(unit)) {
   2551 
   2552                 fc->scache_size[_FIELD_SCACHE_PART_0] = 294 * 1024;
   2553                 /* Taking all average number into account
   2554                  * (Note:S-Slices , P- Ports and Q - Qualifiers)
   2555                  * IFP - 16S * 48P * 25Q
   2556                  * VFP and EFP - 16S * 25Q
   2557                  */
   2558                 fc->scache_size[_FIELD_SCACHE_PART_1] = 20 * 1024;
   2559 
   2560                 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_15) {
   2561                     /*
   2562                      * OAM => 70 * 1024 ((7 bytes * 8K IFP entries) + (7 bytes * 2K EFP entries))
   2563                      * Policer L1 => 20 * 1024 (4 bytes * 20 slices * 256 entries.)
   2564                      * No Param Actions => 40 * 1024 (4 bytes * 20 slices * 512 entries.)
   2565                      * Slice/Secondary Selectors => 5 * 1024 (2 bytes * 128 ports/groups * 20 Slices.)
   2566                      */
   2567                     fc->scache_size[_FIELD_SCACHE_PART_0] += 135 * 1024;
   2568                 }
   2569 
   2570                 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_17) {
   2571 
   2572                     /* For WB sync and recovery of configured policer rates,
   2573                      * syncing only the delta value (diff btw configured and programmed
   2574                      * for ckbits_sec, ckbits_burst, pkbits_sec, pkbits_burst.
   2575                      * Taking 2 bytes for each of the delta,
   2576                      * Required size = Maximum Number of entries * 8 bytes
   2577                      * IFP := 16K * 8  = 128 KB
   2578                      * EFP := 2K  * 8 = 16KB
   2579                      * Total size = 144 KB
   2580                      */
   2581                     fc->scache_size[_FIELD_SCACHE_PART_0] += 144 * 1024;
   2582                 }
   2583 
   2584                 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_18) {
   2585                     /* Sync for SVP DVP type per entry part and
   2586                      * ingress, src entity selcode per group part
   2587                      */
   2588                     fc->scache_size[_FIELD_SCACHE_PART_0] += (21 * 1024);
   2589                 }
   2590 
   2591                 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_19) {
   2592                     /* Sync for Additional 4bytes to sync
   2593                      * no parm actions sync enums per entry
   2594                      * and 12 bytes for PortPrioIntCosQNew
   2595                      * Actions CosQ Gport Values in IFP Stage
   2596                      */
   2597                     fc->scache_size[_FIELD_SCACHE_PART_0] += (264 * 1024);
   2598                 }
   2599 
   2600                 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_20) {
   2601                     /* Allocate additional scache to sync IFP action ingress
   2602                      * and egress mirror gport value in no parm actions sync
   2603                      * enums per entry. IngressMirror and EgressMirror GPORT
   2604                      * can be assigned to single entry. Have to allocate (4+4)
   2605                      * bytes per entry.
   2606                      * IFP = (8 bytes * 512 entries * 12 slices).
   2607                      */
   2608                     fc->scache_size[_FIELD_SCACHE_PART_0] += (48 * 1024);
   2609                     /*
   2610                      * Scache size is increased by (16 * 1024) * 4 bytes
   2611                      * (16K entries * 4 bytes) for all devices and
   2612                      * (8 * 1024) * 4 * 2 (8K entries * 4 bytes * 2 params
   2613                      * for KT2 devices to sync and recover the params of
   2614                      * fabricQueue action for all entries of Ingress.
   2615                      */
   2616                     fc->scache_size[_FIELD_SCACHE_PART_0] += (16 * 4 * 1024);
   2617                 }
   2618 
   2619                 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_21) {
   2620                  /*
   2621                   * Group PBMP is synced with max_groups * size of the pbmp array
   2622                   * Sync MirrorIngress and MirrorEgress action parameters per entry
   2623                   * Worst case 16K * 12 bytes
   2624                   */
   2625                     fc->scache_size[_FIELD_SCACHE_PART_0] += ((512 * _SHR_PBMP_WORD_MAX * 4) + (16 * 1024 * 12));
   2626                 }
   2627 
   2628                 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_23) {
   2629                     /*
   2630                      * Scache size is increased by 128 * 4 bytes
   2631                      * to syncloopbacktype selcode per group part.
   2632                      * Worst case assuming 128 IFP groups in quad mode
   2633                      * (128 * 4) bytes.
   2634                      */
   2635                     fc->scache_size[_FIELD_SCACHE_PART_0] += (128 * 4);
   2636                 }
   2637 
   2638                 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_26) {
   2639                     /*
   2640                      * Scache size is increased by _FP_MAX_NUM_PIPES * 1 bytes
   2641                      * to sync instance for all pipes in EFP/VFP slice map.
   2642                      * _FP_MAX_NUM_PIPES * 1 bytes * 8 groups to sync group
   2643                      * instance for all groups in EFP/VFP
   2644                      */
   2645                     fc->scache_size[_FIELD_SCACHE_PART_0] += ((_FP_MAX_NUM_PIPES)
   2646                                                               + (_FP_MAX_NUM_PIPES * 8));
   2647                 }
   2648 
   2649             } else {
   2650                 /* Allocate a section of the Level 2 Warm Boot
   2651                  * global cache.
   2652                  * Assume 90% of the total stable size - just a heuristic
   2653                  */
   2654                 fc->scache_size[_FIELD_SCACHE_PART_0] = (9 * stable_size) / 10;
   2655                 fc->scache_size[_FIELD_SCACHE_PART_1] = (1 * stable_size) / 100;
   2656             }
   2657 
   2658             /* Get the pointer for the Level 2 cache */
   2659             rv = soc_scache_ptr_get(unit, handle,
   2660                                     &(fc->scache_ptr[_FIELD_SCACHE_PART_0]),
   2661                                     &alloc_get);
   2662             if (!SOC_WARM_BOOT(unit) && (SOC_E_NOT_FOUND == rv)) {
   2663                 /* Not yet allocated in Cold Boot */
   2664                 SOC_IF_ERROR_RETURN
   2665                     (soc_scache_alloc(unit, handle,
   2666                                       fc->scache_size[_FIELD_SCACHE_PART_0] +
   2667                                       SOC_WB_SCACHE_CONTROL_SIZE));
   2668                 rv = soc_scache_ptr_get(unit, handle,
   2669                                         &(fc->scache_ptr[_FIELD_SCACHE_PART_0]),
   2670                                         &alloc_get);
   2671             }
   2672             /* Fetch WB Recovered Version */
   2673             if (SOC_WARM_BOOT(unit)) {
   2674                 sal_memcpy(&(fc->wb_recovered_version),
   2675                            fc->scache_ptr[_FIELD_SCACHE_PART_0],
   2676                            sizeof(fc->wb_recovered_version));
   2677             }
   2678 
   2679 
   2680             if (BCM_FAILURE(rv)) {
   2681                 return rv;
   2682             } else if (alloc_get != fc->scache_size[_FIELD_SCACHE_PART_0] +
   2683                                     SOC_WB_SCACHE_CONTROL_SIZE) {
   2684                    /* Expected size doesn't match retrieved size */
   2685                    /* Scache size is increased by 16*1024 bytes
   2686                     * from version BCM_FIELD_WB_VERSION_1_6.The below check is
   2687                     * for upgrades from lower versions to BCM_FIELD_WB_VERSION_1_6
   2688                     * and above.
   2689                     * Scache size increased by 128 bytes from BCM_FIELD_WB_VERSION_1_8.
   2690                     * with respect to BCM_FIELD_WB_VERSION_1_6
   2691                     */
   2692                     rv = _field_scache_version_size_check(unit, alloc_get,
   2693                                                           (fc->wb_recovered_version),
   2694                                                           fc->scache_size[_FIELD_SCACHE_PART_0] +
   2695                                                           SOC_WB_SCACHE_CONTROL_SIZE,
   2696                                                           (fc->wb_current_version));
   2697                     if (rv != TRUE) {
   2698                         return BCM_E_INTERNAL;
   2699                     }
   2700             } else if (NULL == fc->scache_ptr[_FIELD_SCACHE_PART_0]) {
   2701                 return BCM_E_MEMORY;
   2702             }
   2703 
   2704             if (SOC_WARM_BOOT(unit)) {
   2705                 if ((fc->wb_recovered_version) < BCM_FIELD_WB_VERSION_1_3) {
   2706                     return BCM_E_NONE;
   2707                 }
   2708             }
   2709 
   2710             SOC_SCACHE_HANDLE_SET(handle, unit, BCM_MODULE_FIELD, 1);
   2711             SOC_SCACHE_MODULE_MAX_PARTITIONS_SET(unit, BCM_MODULE_FIELD, 1);
   2712 
   2713             /* Get the pointer for the Level 2 cache */
   2714             rv = soc_scache_ptr_get(unit, handle,
   2715                                     &(fc->scache_ptr[_FIELD_SCACHE_PART_1]),
   2716                                     &alloc_get);
   2717             if (!SOC_WARM_BOOT(unit) && (SOC_E_NOT_FOUND == rv)) {
   2718                 /* Not yet allocated in Cold Boot */
   2719                 SOC_IF_ERROR_RETURN
   2720                     (soc_scache_alloc(unit, handle,
   2721                                       fc->scache_size[_FIELD_SCACHE_PART_1] +
   2722                                       SOC_WB_SCACHE_CONTROL_SIZE));
   2723                 rv = soc_scache_ptr_get(unit, handle,
   2724                                         &(fc->scache_ptr[_FIELD_SCACHE_PART_1]),
   2725                                         &alloc_get);
   2726             }
   2727 
   2728             if (BCM_FAILURE(rv)) {
   2729                 return rv;
   2730             } else if (alloc_get != fc->scache_size[_FIELD_SCACHE_PART_1] +
   2731                                     SOC_WB_SCACHE_CONTROL_SIZE) {
   2732                 /* Expected size doesn't match retrieved size */
   2733                 return BCM_E_INTERNAL;
   2734             } else if (NULL == fc->scache_ptr[_FIELD_SCACHE_PART_1]) {
   2735                 return BCM_E_MEMORY;
   2736             }
   2737 
   2738         }
   2739     }
   2740     return BCM_E_NONE;
   2741 }
   2742 
   2743 /*
   2744  * Function:
   2745  *     _field_slice_map_write
   2746  *
   2747  * Purpose:
   2748  *      Sync's slice status to scache for a stage (Expanded & master slice idx)
   2749  *
   2750  * Parameters:
   2751  *             unit      - (IN) BCM device number
   2752  *               fc      - (IN) FP control info.
   2753  *         stage_fc      - (IN) FP stage control info.
   2754  *
   2755  * Returns:
   2756  *           BCM_E_XXX
   2757  */
   2758 
   2759 int
   2760 _field_slice_map_write(int unit,  _field_control_t *fc,
   2761                            _field_stage_t *stage_fc)
   2762 {
   2763     uint8               slice_id;        /* Slices iterator.              */
   2764     _field_slice_t      *fs;             /* Slice pointer.                 */
   2765     uint8               *buf;            /* Scache pointer.                */
   2766 
   2767     if ((stage_fc == NULL) || (fc == NULL)) {
   2768         return BCM_E_PARAM;
   2769     }
   2770 
   2771     /* No need to sync external stage */
   2772     if (stage_fc->stage_id >= _BCM_FIELD_STAGE_EXTERNAL) {
   2773         return BCM_E_NONE;
   2774     }
   2775 
   2776     buf = fc->scache_ptr[_FIELD_SCACHE_PART_0];
   2777 
   2778     if (((stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) && soc_mem_is_valid(unit, FP_SLICE_MAPm))
   2779         || ((stage_fc->stage_id == _BCM_FIELD_STAGE_EGRESS) && SOC_REG_IS_VALID(unit, EFP_SLICE_MAPr))
   2780         || ((stage_fc->stage_id == _BCM_FIELD_STAGE_LOOKUP) && SOC_REG_IS_VALID(unit, VFP_SLICE_MAPr))) {
   2781 
   2782         for (slice_id = 0; slice_id < stage_fc->tcam_slices; slice_id++) {
   2783             fs = stage_fc->slices[_FP_DEF_INST] + slice_id;
   2784 
   2785             buf[fc->scache_pos] = (fs->prev != NULL) ? 1 : 0;
   2786             /* Go to master slice */
   2787             while (fs->prev != NULL) {
   2788                 fs = fs->prev;
   2789             }
   2790             buf[fc->scache_pos] |= (fs->slice_number << 1);
   2791 
   2792             LOG_DEBUG(BSL_LS_BCM_FP,
   2793                     (BSL_META_U(unit,
   2794                                 "_field_slice_map_write:   Writing slice %d master slice %d expanded %d @ byte %d...\n"),
   2795                      slice_id, (buf[fc->scache_pos] >> 1), (buf[fc->scache_pos] & 0x1), fc->scache_pos));
   2796 
   2797             fc->scache_pos++;
   2798             fs = NULL;
   2799         }
   2800     }
   2801     return BCM_E_NONE;
   2802 }
   2803 
   2804 /*
   2805  * Function:
   2806  *     _field_mark_vmap_valid
   2807  *
   2808  * Purpose:
   2809  *      Marks a virtual map as valid
   2810  *
   2811  * Parameters:
   2812  *             unit      - (IN) BCM device number
   2813  *         stage_fc      - (IN) FP stage control info.
   2814  *               fg      - (IN) Select code information filled into the group.
   2815  *     slice_number      - (IN) Slices iterator.
   2816  *
   2817  * Returns:
   2818  *           BCM_E_XXX
   2819  */
   2820 
   2821 STATIC int
   2822 _field_mark_vmap_valid(int unit, _field_stage_t *stage_fc,
   2823                                   _field_group_t *fg, int s )
   2824 {
   2825     int idx, vmap_size, map_id;
   2826     _field_virtual_map_t *vvmap; /* Currently used virtual map. */
   2827     _field_slice_t         *slices;
   2828 
   2829     BCM_IF_ERROR_RETURN(_bcm_field_virtual_map_size_get(unit,
   2830                                            stage_fc, &vmap_size));
   2831 
   2832     for (map_id = 0; map_id < _FP_VMAP_CNT; map_id++) {
   2833         slices = fg->slices;
   2834         while (slices) {
   2835             for (idx = 0; idx < vmap_size; idx++) {
   2836                 vvmap = stage_fc->vmap[fg->instance][map_id] + idx;
   2837 
   2838                 if (vvmap->vmap_key == slices[s].slice_number) {
   2839                     vvmap->valid = TRUE;
   2840                     vvmap->priority = fg->priority;
   2841                     /* update VMAP flags with group flags */
   2842                     vvmap->flags = fg->flags;
   2843                     if (map_id == 0) {
   2844                         /* Update group VMAP */
   2845                         fg->vmap_group[s] = vvmap->virtual_group;
   2846                     }
   2847                 }
   2848             }
   2849             slices = slices->next;
   2850         }
   2851     }
   2852 
   2853     return BCM_E_NONE;
   2854 }
   2855 
   2856 /*
   2857  * Function:
   2858  *     _field_group_slice_map_recovery
   2859  *
   2860  * Purpose:
   2861  *      Recovers group and stage virtual map
   2862  *
   2863  * Parameters:
   2864  *             unit      - (IN) BCM device number
   2865  *               fc      - (IN) FP control info.
   2866  *         stage_fc      - (IN) FP stage control info.
   2867  *
   2868  * Returns:
   2869  *           BCM_E_XXX
   2870  */
   2871 
   2872 int
   2873 _field_group_slice_vmap_recovery(int unit,  _field_control_t *fc,
   2874                            _field_stage_t *stage_fc)
   2875 {
   2876     _field_group_t      *fg;
   2877     int                 idx;
   2878 
   2879     if ((stage_fc == NULL) || (fc == NULL)) {
   2880         return BCM_E_PARAM;
   2881     }
   2882 
   2883     /* No need to sync external stage */
   2884     if (stage_fc->stage_id >= _BCM_FIELD_STAGE_EXTERNAL) {
   2885         return BCM_E_NONE;
   2886     }
   2887 
   2888     if (((stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) && soc_mem_is_valid(unit, FP_SLICE_MAPm))
   2889         || ((stage_fc->stage_id == _BCM_FIELD_STAGE_EGRESS) && SOC_REG_IS_VALID(unit, EFP_SLICE_MAPr))
   2890         || ((stage_fc->stage_id == _BCM_FIELD_STAGE_LOOKUP) && SOC_REG_IS_VALID(unit, VFP_SLICE_MAPr))) {
   2891 
   2892         for (fg = fc->groups; fg ; fg= fg->next) {
   2893             /* Skip groups not belonging to stage */
   2894             if (fg->stage_id != stage_fc->stage_id) {
   2895                 continue;
   2896             }
   2897 
   2898             _field_mark_vmap_valid( unit, stage_fc, fg, 0 );
   2899 
   2900             if (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) {
   2901                 _field_mark_vmap_valid( unit, stage_fc, fg, 1 );
   2902             }
   2903 
   2904             if (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) {
   2905                 _field_mark_vmap_valid( unit, stage_fc, fg, 1 );
   2906                 _field_mark_vmap_valid( unit, stage_fc, fg, 2 );
   2907             }
   2908 
   2909             if (fg->action_res_id != BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT) {
   2910                 for (idx = 1; idx < _FP_PAIR_MAX; idx++) {
   2911                     fg->vmap_group[idx] = fg->vmap_group[0];
   2912                 }
   2913             } else if (!(fc->l2warm)) {
   2914                 /* For L1 Warmboot
   2915                 *  double wide mode groups check to see if slices have same virtual group
   2916                  * Single wide mode groups action res id will be as -1 */
   2917                 if ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE)
   2918                         || (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE)) {
   2919                     if (fg->vmap_group[0] == fg->vmap_group[1]) {
   2920                         fg->action_res_id = fg->vmap_group[0];
   2921                         for (idx = 2; idx < _FP_PAIR_MAX; idx++) {
   2922                             fg->vmap_group[idx] = fg->vmap_group[0];
   2923                         }
   2924                     }
   2925                 }
   2926             }
   2927         }
   2928     }
   2929     return BCM_E_NONE;
   2930 }
   2931 
   2932 #if defined BCM_KATANA2_SUPPORT || defined BCM_TRIDENT2_SUPPORT
   2933 /*
   2934  * Function:
   2935  *     _bcm_notify_qos_reinit_to_fp
   2936  * Purpose:
   2937  *      Notfiy Field module when qos reinit is successful,
   2938  *      fp uses this notification to update bcmFieldActionDscpMapNew
   2939  *      action in entry
   2940  *
   2941  * Parameters:
   2942  *             unit      - (IN) BCM device number
   2943  *               fc      - (IN) FP control info.
   2944  *         stage_fc      - (IN) FP stage control info.
   2945  *
   2946  * Returns:
   2947  *           BCM_E_XXX
   2948  */
   2949 int _bcm_notify_qos_reinit_to_fp (int unit) {
   2950     _field_dscp_map_new_eid_list_t *dscp_map_new_eid_node = NULL;
   2951     _field_dscp_map_new_eid_list_t *temp = NULL;
   2952     _field_entry_t *f_ent = NULL;
   2953     _field_action_t *fa = NULL;
   2954     uint32 hw_value = 0;
   2955     uint32 param1 = 0;
   2956     int param0 = 0;
   2957 
   2958     dscp_map_new_eid_node = dscp_map_new_eid_list[unit];
   2959 
   2960     /* When DscpMapNew action is configured, after wb recovery,
   2961      * param0 will hold the hw_value. Based on hw value, obtain the
   2962      * mapId and update the entryId with the mapId as param0 */
   2963     while (dscp_map_new_eid_node != NULL) {
   2964         BCM_IF_ERROR_RETURN(bcm_esw_field_action_get(unit,
   2965                     dscp_map_new_eid_node->eid,bcmFieldActionDscpMapNew,
   2966                     &hw_value, &param1));
   2967         BCM_IF_ERROR_RETURN(_bcm_tr2_qos_idx2id(unit, hw_value,
   2968                _BCM_QOS_MAP_TYPE_DSCP_TABLE, &param0));
   2969         BCM_IF_ERROR_RETURN(_field_entry_get(unit,
   2970                     dscp_map_new_eid_node->eid, _FP_ENTRY_PRIMARY, &f_ent));
   2971         for (fa = f_ent->actions; fa != NULL; fa = fa->next) {
   2972             if (fa->action == bcmFieldActionDscpMapNew) {
   2973                 fa->param[0] = param0;
   2974                 break;
   2975             }
   2976         }
   2977         if (fa == NULL) {
   2978             return BCM_E_INTERNAL;
   2979         }
   2980 
   2981         temp = dscp_map_new_eid_node;
   2982         dscp_map_new_eid_node = dscp_map_new_eid_node->next;
   2983         sal_free (temp);
   2984         temp = NULL;
   2985     }
   2986     dscp_map_new_eid_list[unit] = NULL;
   2987 
   2988     return BCM_E_NONE;
   2989 }
   2990 
   2991 #endif /* BCM_KATANA2_SUPPORT, BCM_TRIDENT2_SUPPORT*/
   2992 #endif /*  BCM_WARM_BOOT_SUPPORT */
   2993 
   2994 #ifdef BCM_TRIDENT2_SUPPORT
   2995 /*
   2996  * Function:
   2997  *      bcm_field_efp_update_alternate_key_mask
   2998  * Purpose:
   2999  *      As EFP has 2 types of keys, tcam.key and key_match_tcam.key
   3000  *      using efp_key_match_type, update the alternate key meaning
   3001  *      key which is not the current tcam installed key.
   3002  * Parameters:
   3003  *      unit  - (IN) Unit number.
   3004  *      f_ent - (IN) Pointer to field entry
   3005  *      input_entry_type - (IN) Specifies the key type which is
   3006  *                         currently installed in tcam
   3007  * Returns:
   3008  *      BCM_E_xxx
   3009  * Notes:
   3010  */
   3011 STATIC int
   3012 bcm_field_efp_update_alternate_key_mask(int unit,
   3013                                         _field_entry_t *f_ent_1,
   3014                                         int8 input_entry_type_1)
   3015 {
   3016     int             parts_count = 0;    /* Number of entry parts.          */
   3017     int             part_idx,part_id;   /* Entry parts iteration index.    */
   3018     int             qual_idx;           /* Part qualifiers iteration index.*/
   3019     int             rv;                 /* Operation return stauts.        */
   3020     int             idx;
   3021     int             idx_max;
   3022     int             index;
   3023     uint32          width;
   3024     _field_group_t           *fg;       /* FP group info structure.        */
   3025     _bcm_field_qual_offset_t *q_offset; /* Qualifier offset structure      */
   3026     _bcm_field_group_qual_t  *q_arr;    /* Qualifiers array.               */
   3027     _bcm_field_group_qual_t  *q_arr_1;  /* Qualifiers array.               */
   3028     _bcm_field_qual_offset_t *q_offset_1; /* Qualifier offset structure    */
   3029     _bcm_field_qual_data_t    q_data;
   3030     _bcm_field_qual_data_t    q_mask;
   3031     int8 entry_type;                    /* entry type of alternate key/mask*/
   3032     _field_tcam_t             *tcam;    /* Tcam key/mask structure         */
   3033     int                       dirty;    /* to check if entry is dirty      */
   3034     _field_entry_t            *f_ent;   /* to hold the entry structure     */
   3035     int8                      input_entry_type; /* entry type of entry     */
   3036 
   3037     /* Search the entry by eid. */
   3038     rv = _field_entry_get(unit, f_ent_1->eid, _FP_ENTRY_PRIMARY, &f_ent);
   3039     BCM_IF_ERROR_RETURN(rv);
   3040 
   3041     fg = f_ent->group;
   3042 
   3043     if (NULL == fg) {
   3044         return (BCM_E_INTERNAL);
   3045     }
   3046 
   3047     /* Get number of entry parts we have to read. */
   3048     rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
   3049                                             fg->flags, &parts_count);
   3050     BCM_IF_ERROR_RETURN(rv);
   3051 
   3052     /* clear the data in alternate entry in all the f_ent parts*/
   3053     for (part_idx = 0; part_idx < parts_count; part_idx++) {
   3054         /* when tcam.key is NULL, it might be because */
   3055         /* group is in double mode and we are dealing here with f_ent[1] */
   3056         /* in such cases f_ent[0] vaules can be NULL */
   3057         if((f_ent+part_idx)->tcam.key == NULL) {
   3058            continue;
   3059         }
   3060 	input_entry_type = (f_ent+part_idx)->efp_key_match_type;
   3061         /* clear the data in alternate entry */
   3062         if (input_entry_type == _FP_ENTRY_TYPE_0) {
   3063             tcam = &(f_ent+part_idx)->key_match_tcam;
   3064         } else {
   3065             tcam = &(f_ent+part_idx)->tcam;
   3066         }
   3067         sal_memset(tcam->key, 0, tcam->key_size);
   3068         sal_memset(tcam->mask, 0, tcam->key_size);
   3069     }
   3070     /* Loop for updating the alternate key in f_ent */
   3071     for (part_idx = 0; part_idx < parts_count; part_idx++)
   3072     {
   3073         if((f_ent+part_idx)->tcam.key == NULL) {
   3074            continue;
   3075         }
   3076         /* get the efp_key_match_type for f_ent */
   3077         input_entry_type = (f_ent+part_idx)->efp_key_match_type;
   3078         /* check the entry dirty flag and keep the same value even */
   3079         /* after the alternate entry is updated */
   3080         dirty = 0;
   3081         if ((f_ent+part_idx)->flags & _FP_ENTRY_DIRTY)  {
   3082             dirty = 1;
   3083         }
   3084         q_arr = &(fg->qual_arr[input_entry_type][part_idx]);
   3085         for (qual_idx = 0; qual_idx < q_arr->size; qual_idx++) {
   3086             idx_max = -1;
   3087             q_offset = q_arr->offset_arr + qual_idx;
   3088 
   3089             /* There is no value associated with zero
   3090              * width qualifiers (Stage, Ip4 etc)
   3091              */
   3092              _BCM_FIELD_QUAL_MULTI_OFFSET_WIDTH(q_offset, width);
   3093             if (0 == width) {
   3094                 /* if the qualifier is Ip6 or Ip4
   3095                  * no need to update the key/mask
   3096                  */
   3097                 continue;
   3098             }
   3099 
   3100             _FP_QUAL_DATA_CLEAR(q_data);
   3101             _FP_QUAL_DATA_CLEAR(q_mask);
   3102 
   3103             /* Read qualifier match value and mask. */
   3104             rv = _bcm_field_qual_value_get(unit, q_offset, f_ent+part_idx,
   3105                                                   q_data, q_mask);
   3106             if (BCM_FAILURE(rv)) {
   3107                 return rv;
   3108             }
   3109 
   3110             /* Check if qualifier was installed. */
   3111             for (idx = 7; idx >= 0; idx--) {
   3112                 if (q_mask[idx] != 0)  {
   3113                     idx_max = idx;
   3114                     break;
   3115                 }
   3116             }
   3117 
   3118             if (idx_max >= 0) {
   3119                 if (input_entry_type == 1)  {
   3120                     entry_type = 0;
   3121                 } else {
   3122                     entry_type = 1;
   3123                 }
   3124                 for (part_id = 0; part_id < parts_count; part_id++)
   3125                 {
   3126                     if((f_ent+part_id)->tcam.key == NULL) {
   3127                        continue;
   3128                     }
   3129                     q_arr_1 = &(fg->qual_arr[entry_type][part_id]);
   3130                     for (index = 0; index < q_arr_1->size; index++)
   3131                     {
   3132                         if (q_arr->qid_arr[qual_idx] ==
   3133                             q_arr_1->qid_arr[index])
   3134                         {
   3135                             q_offset_1 = q_arr_1->offset_arr + index;
   3136 
   3137                             rv = _bcm_field_qual_value_set_by_entry_type(unit,
   3138                                                                q_offset_1,
   3139                                                                f_ent+part_id,
   3140                                                                q_data, q_mask, entry_type);
   3141                             BCM_IF_ERROR_RETURN(rv);
   3142 
   3143                             /* When qualifier is found dont go for next qualifier
   3144                              *  in q_arr
   3145                              */
   3146                             break;
   3147                         }
   3148                    }
   3149                }
   3150             }
   3151         }
   3152         /* set the entry dirty flag to the same value */
   3153         /* as before the alternate key update  */
   3154         if (1 == dirty) {
   3155             (f_ent+part_idx)->flags |= _FP_ENTRY_DIRTY;
   3156         } else {
   3157             (f_ent+part_idx)->flags &= ~_FP_ENTRY_DIRTY;
   3158         }
   3159     }
   3160     return (BCM_E_NONE);
   3161 }
   3162 #endif /* BCM_TRIDENT2_SUPPORT*/
   3163 
   3164 /* Given en EID, find the group */
   3165 /* Used in various _qualify APIs */
   3166 int
   3167 _bcm_field_entry_group_find(int unit, bcm_field_entry_t eid,
   3168                             _field_group_t **group_p)
   3169 {
   3170     int                 idx;          /* Entry index */
   3171     _field_control_t    *fc;          /* Unit FP control structure. */
   3172     _field_group_t      *fg;          /* Group information.         */
   3173     _field_entry_t      *f_ent;       /* Field entry info */
   3174 
   3175     if (NULL == group_p) {
   3176         return (BCM_E_PARAM);
   3177     }
   3178 
   3179     /* Get unit FP control structure. */
   3180     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   3181 
   3182     /* Iterate over the groups linked-list */
   3183     fg = fc->groups;
   3184     while (fg != NULL) {
   3185         /* Now iterate over the entries in this group */
   3186         for (idx = 0; idx < fg->group_status.entry_count; idx++) {
   3187            f_ent = fg->entry_arr[idx];
   3188            if (f_ent->eid == eid) {
   3189                *group_p = fg;
   3190                return BCM_E_NONE;
   3191            }
   3192         }
   3193         fg = fg->next;
   3194     }
   3195     /* Group with eid not found. */
   3196     return (BCM_E_NOT_FOUND);
   3197 
   3198 }
   3199 
   3200 
   3201 /*
   3202  * Function:
   3203  *     _bcm_field_action_dest_check
   3204  * Purpose:
   3205  *     Verify destination prameters for fp actions
   3206  * Parameters:
   3207  *     unit    - (IN) BCM device number
   3208  *     fa      - (IN) Field action structure.
   3209  * Returns:
   3210  *     BCM_E_XXX
   3211  */
   3212 int
   3213 _bcm_field_action_dest_check(int unit, _field_action_t *fa)
   3214 {
   3215     int port_out;     /* Calculated port value.    */
   3216     int modid_out;    /* Calculated module id.     */
   3217     int rv;           /* Operation return value.   */
   3218 
   3219     /* Input parameters check. */
   3220     if (NULL == fa) {
   3221         return (BCM_E_PARAM);
   3222     }
   3223 
   3224     /* No checks for Mirror/Mpls/Mim/Wlan gports  */
   3225     if (BCM_GPORT_IS_SET(fa->param[1])) {
   3226         return (BCM_E_NONE);
   3227     }
   3228 
   3229     /* Modport/Trunk were resolved in _field_params_api_to_hw_adapt call.*/
   3230     if (bcmFieldActionRedirectTrunk == fa->action) {
   3231         return  _bcm_trunk_id_validate(unit, fa->param[0]);
   3232     }
   3233 
   3234     /* Check destination module id / port. */
   3235     rv = _bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET,
   3236                                 fa->param[0], fa->param[1],
   3237                                 &modid_out, &port_out);
   3238     BCM_IF_ERROR_RETURN(rv);
   3239 
   3240     if (!SOC_MODID_ADDRESSABLE(unit, modid_out)) {
   3241         return (BCM_E_PARAM);
   3242     }
   3243     if (!SOC_PORT_ADDRESSABLE(unit, port_out)) {
   3244         return (BCM_E_PORT);
   3245     }
   3246     return (BCM_E_NONE);
   3247 }
   3248 
   3249 #ifdef INCLUDE_L3
   3250 /*
   3251  * Function:
   3252  *     _bcm_field_policy_set_l3_nh_resolve
   3253  * Purpose:
   3254  *     Install l3 forwarding policy entry.
   3255  * Parameters:
   3256  *     unit      - (IN) BCM device number
   3257  *     mem       - (IN) Policy table memory.
   3258  *     value     - (IN) Egress object id or combined next hop information.
   3259  * Returns:
   3260  *     BCM_E_XXX
   3261  */
   3262 int
   3263 _bcm_field_policy_set_l3_nh_resolve(int unit,  int value,
   3264                                     uint32 *flags, int *nh_ecmp_id)
   3265 {
   3266     int rv;           /* Operation return value.    */
   3267 
   3268     /* Check if egress forwarding mode is enabled. */
   3269     rv = bcm_xgs3_l3_egress_id_parse(unit, value, flags, nh_ecmp_id);
   3270     if (rv == BCM_E_DISABLED) {
   3271         LOG_DEBUG(BSL_LS_BCM_FP,
   3272                    (BSL_META_U(unit,
   3273                     "Error: L3 Egress Mode must be enabled.\n")));
   3274     }
   3275     return (rv);
   3276 }
   3277 
   3278 /*
   3279  * Function:
   3280  *     _bcm_field_l2_actions_nh_desroy
   3281  *
   3282  * Purpose:
   3283  *     Free l3 next hop and egress interface for
   3284  *     l2 fields update action.
   3285  * Parameters:
   3286  *     unit     - (IN) BCM device number.
   3287  *     nh_index - (IN) Next hop index.
   3288  *     egr_intf_set - (IN) Egress interface allocated.
   3289  * Returns:
   3290  *     BCM_E_XXX
   3291  */
   3292 STATIC int
   3293 _bcm_field_l2_actions_nh_destroy(int unit, int nh_index, int egr_intf_set)
   3294 {
   3295     uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; /* hw entry  buffer.            */
   3296     bcm_l3_egress_t egr;                    /* Egress forwarding object.    */
   3297     uint32 intf;                            /* Egress L3 interface id.      */
   3298 
   3299     /* Initialization. */
   3300     bcm_l3_egress_t_init(&egr);
   3301 
   3302     /* Read next hop. */
   3303     sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   3304     BCM_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm, SOC_BLOCK_ANY,
   3305         nh_index, hw_buf));
   3306 
   3307     /* clear egress interface information + free interface resource */
   3308     if ((1 == egr_intf_set) ||
   3309         (SOC_IS_TRIUMPH2(unit) || SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit) ||
   3310         SOC_IS_APOLLO(unit) || SOC_IS_ENDURO(unit) || SOC_IS_HURRICANEX(unit) ||
   3311         SOC_IS_GREYHOUND(unit) || SOC_IS_TRIUMPH3(unit) ||
   3312         SOC_IS_GREYHOUND2(unit))) {
   3313         /* Get interface id. */
   3314         intf = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm, hw_buf, INTF_NUMf);
   3315         /* Reset interface entry in hw. */
   3316         sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   3317         BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_L3_INTFm, SOC_BLOCK_ALL,
   3318             intf, hw_buf));
   3319         /* Free interface id. */
   3320        BCM_IF_ERROR_RETURN(_bcm_xgs3_egress_l3_intf_id_free(unit, intf));
   3321     }
   3322 
   3323     /* clear egress next hop table information + free next hop index */
   3324     sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   3325     BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_L3_NEXT_HOPm,
   3326         SOC_BLOCK_ALL, nh_index, hw_buf));
   3327 
   3328     BCM_IF_ERROR_RETURN(bcm_xgs3_nh_del(unit, 0, nh_index));
   3329     return (BCM_E_NONE);
   3330 }
   3331 
   3332 /*
   3333  * Function:
   3334  *     _bcm_field_l2_actions_nh_create
   3335  *
   3336  * Purpose:
   3337  *     Free l3 next hop and egress interface for
   3338  *     l2 fields update action.
   3339  * Parameters:
   3340  *     unit    - (IN) BCM device number.
   3341  *     da_fa   - (IN) Update destination mac action.
   3342  *     sa_fa   - (IN) Update source mac action.
   3343  *     vid_fa  - (IN) Update outer vid action.
   3344  *     vn_new_fa  - (IN) Change VN tag action.
   3345  *     vn_del_fa  - (IN) Delete VN tag action.
   3346  *     e_new_fa  - (IN) Change E tag action.
   3347  *     e_del_fa  - (IN) Delete E tag action.
   3348  * Returns:
   3349  *     BCM_E_XXX
   3350  */
   3351 STATIC int
   3352 _bcm_field_l2_actions_nh_create(int unit, _field_action_t *da_fa,
   3353                                 _field_action_t *sa_fa,
   3354                                 _field_action_t *vid_fa,
   3355                                 _field_action_t *vn_new_fa,
   3356                                 _field_action_t *vn_del_fa,
   3357                                 _field_action_t *e_new_fa,
   3358                                 _field_action_t *e_del_fa)
   3359 {
   3360     uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; /* hw entry  buffer.     */
   3361     bcm_l3_egress_t egr;            /* Egress forwarding object.     */
   3362     _bcm_l3_intf_cfg_t  intf;       /* Egress L3 interface id.       */
   3363     int nh_index;                   /* Next hop index.               */
   3364     int nh_flags = 0;               /* Next hop flags.               */
   3365     int rv = BCM_E_NONE;            /* Operation return status.      */
   3366 
   3367     /*validation */
   3368     if (!BCM_XGS3_L3_INITIALIZED(unit)) {
   3369         LOG_ERROR(BSL_LS_BCM_FP,
   3370                   (BSL_META_U(unit,
   3371                    "Error: L3 module is not initialized.\n")));
   3372         return (BCM_E_INIT);
   3373     }
   3374     /* Check l3 switching mode. */
   3375     if (!(BCM_XGS3_L3_EGRESS_MODE_ISSET(unit))) {
   3376         LOG_ERROR(BSL_LS_BCM_FP,
   3377                   (BSL_META_U(unit,
   3378                    "Error: L3 Egress Mode must be enabled.\n")));
   3379         return (BCM_E_DISABLED);
   3380     }
   3381     /* Initialization. */
   3382     bcm_l3_egress_t_init(&egr);
   3383     sal_memset(&intf, 0, sizeof(_bcm_l3_intf_cfg_t));
   3384 
   3385     /* Extract the policy info from the entry structure. */
   3386     if (NULL != da_fa) {
   3387         SAL_MAC_ADDR_FROM_UINT32(egr.mac_addr, da_fa->param);
   3388     }
   3389 
   3390     if (NULL != sa_fa) {
   3391         SAL_MAC_ADDR_FROM_UINT32(intf.l3i_mac_addr, sa_fa->param);
   3392     }
   3393 
   3394     if (NULL != vid_fa) {
   3395         intf.l3i_vid = vid_fa->param[0];
   3396     }
   3397 
   3398     if (SOC_IS_TRIUMPH2(unit)
   3399         || SOC_IS_TD_TT(unit)
   3400         || SOC_IS_KATANAX(unit)
   3401         || SOC_IS_APOLLO(unit)
   3402         || SOC_IS_ENDURO(unit)
   3403         || SOC_IS_HURRICANEX(unit)
   3404         || SOC_IS_TRIUMPH3(unit)
   3405         || SOC_IS_GREYHOUND(unit)
   3406         || SOC_IS_VALKYRIE2(unit)
   3407         || SOC_IS_GREYHOUND2(unit)
   3408         ) {
   3409         /* Create egress l3 interface. */
   3410         BCM_IF_ERROR_RETURN(_bcm_xgs3_egress_l3_intf_id_alloc(unit,
   3411             &intf));
   3412 
   3413         /* Write egress interface to the hw. */
   3414         sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   3415 
   3416         /* Set mac address. */
   3417         soc_mem_mac_addr_set(unit, EGR_L3_INTFm, hw_buf,
   3418             MAC_ADDRESSf, intf.l3i_mac_addr);
   3419 
   3420         /* Set vlan id. */
   3421         soc_mem_field32_set(unit, EGR_L3_INTFm, hw_buf, VIDf, intf.l3i_vid);
   3422 
   3423         /* Write interface configuration to the HW. */
   3424         rv = soc_mem_write(unit, EGR_L3_INTFm, SOC_BLOCK_ALL,
   3425                 intf.l3i_index, hw_buf);
   3426         if (BCM_FAILURE(rv)) {
   3427             (void)_bcm_xgs3_egress_l3_intf_id_free(unit, intf.l3i_index);
   3428             return rv;
   3429         }
   3430 
   3431         /* Allocate next hop entry. */
   3432         nh_flags = _BCM_L3_SHR_MATCH_DISABLE | _BCM_L3_SHR_WRITE_DISABLE;
   3433         rv = bcm_xgs3_nh_add(unit, nh_flags, &egr, &nh_index);
   3434         if (BCM_FAILURE(rv)) {
   3435             sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   3436             (void)soc_mem_write(unit, EGR_L3_INTFm, SOC_BLOCK_ALL,
   3437                         intf.l3i_index, hw_buf);
   3438             (void)_bcm_xgs3_egress_l3_intf_id_free(unit, intf.l3i_index);
   3439             return (rv);
   3440         }
   3441 
   3442         /* Write egress next hop entry. */
   3443         sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   3444 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)
   3445         if (SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit) ||
   3446             SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
   3447             SOC_IS_GREYHOUND2(unit)) {
   3448             /* Set next hop entry type to IFP_ACTIONS. */
   3449             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   3450                 ENTRY_TYPEf, 6);
   3451 
   3452             /* Set next hop mac address. */
   3453             soc_mem_mac_addr_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   3454                 IFP_ACTIONS__MAC_ADDRESSf, egr.mac_addr);
   3455 
   3456             /* Set interface id. */
   3457             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   3458                 IFP_ACTIONS__INTF_NUMf, intf.l3i_index);
   3459 
   3460             /* Set Disable flags. */
   3461             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   3462                 SOC_IS_KATANA2(unit) ? IFP_ACTIONS__L3_TTL_DISABLEf :
   3463                 IFP_ACTIONS__L3_UC_TTL_DISABLEf,
   3464                 0x1);
   3465 
   3466             if (NULL == vid_fa) {
   3467                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   3468                     SOC_IS_KATANA2(unit) ? IFP_ACTIONS__L3_VLAN_DISABLEf :
   3469                     IFP_ACTIONS__L3_UC_VLAN_DISABLEf, 0x1);
   3470             }
   3471 
   3472             if (NULL == sa_fa) {
   3473                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   3474                     SOC_IS_KATANA2(unit) ? IFP_ACTIONS__L3_SA_DISABLEf :
   3475                     IFP_ACTIONS__L3_UC_SA_DISABLEf, 0x1);
   3476             }
   3477 
   3478             if (NULL == da_fa) {
   3479                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   3480                     SOC_IS_KATANA2(unit) ? IFP_ACTIONS__L3_DA_DISABLEf :
   3481                     IFP_ACTIONS__L3_UC_DA_DISABLEf, 0x1);
   3482             }
   3483 
   3484             if (NULL != vn_new_fa) {
   3485                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   3486                     IFP_ACTIONS__VNTAG_ACTIONf, 0x1);
   3487                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   3488                     IFP_ACTIONS__VNTAGf, vn_new_fa->param[0]);
   3489             }
   3490 
   3491             if (NULL != vn_del_fa) {
   3492                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   3493                     IFP_ACTIONS__VNTAG_ACTIONf, 0x3);
   3494             }
   3495 
   3496             if (NULL != e_new_fa) {
   3497                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   3498                     IFP_ACTIONS__VNTAG_ACTIONf, 0x2);
   3499                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   3500                     IFP_ACTIONS__VNTAGf, e_new_fa->param[0]);
   3501             }
   3502 
   3503             if (NULL != e_del_fa) {
   3504                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   3505                     IFP_ACTIONS__VNTAG_ACTIONf, 0x3);
   3506             }
   3507 
   3508         } else
   3509 #endif /* BCM_TRIDENT_SUPPORT||BCM_GREYHOUND_SUPPORT */
   3510         {
   3511             /* Set next hop mac address. */
   3512             soc_mem_mac_addr_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   3513                 MAC_ADDRESSf, egr.mac_addr);
   3514 
   3515             /* Set interface id. */
   3516             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   3517                 INTF_NUMf, intf.l3i_index);
   3518 
   3519             /* Set Disable flags. */
   3520             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   3521                 L3__L3_UC_TTL_DISABLEf, 0x1);
   3522 
   3523             if (NULL == vid_fa) {
   3524                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   3525                     L3__L3_UC_VLAN_DISABLEf, 0x1);
   3526             }
   3527 
   3528             if (NULL == sa_fa) {
   3529                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   3530                     L3__L3_UC_SA_DISABLEf, 0x1);
   3531             }
   3532 
   3533             if (NULL == da_fa) {
   3534                 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   3535                     L3__L3_UC_DA_DISABLEf, 0x1);
   3536             }
   3537 
   3538             if (SOC_IS_TRIUMPH3(unit)) {
   3539                 soc_mem_field32_set(unit,
   3540                                     EGR_L3_NEXT_HOPm,
   3541                                     hw_buf,
   3542                                     ENTRY_TYPEf,
   3543                                     6
   3544                                     );
   3545                 if (NULL != e_new_fa) {
   3546                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   3547                         L2_ACTIONS__VNTAG_ACTIONf, 0x2);
   3548                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   3549                         L2_ACTIONS__VNTAGf, e_new_fa->param[0]);
   3550                 }
   3551 
   3552                 if (NULL != e_del_fa) {
   3553                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   3554                         L2_ACTIONS__VNTAG_ACTIONf, 0x3);
   3555                 }
   3556 
   3557             }
   3558 
   3559         }
   3560         /* Insert next hop information. */
   3561         rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, SOC_BLOCK_ALL,
   3562                 nh_index, hw_buf);
   3563         if (BCM_FAILURE(rv)) {
   3564             sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   3565             (void)soc_mem_write(unit, EGR_L3_INTFm, SOC_BLOCK_ALL,
   3566                                 intf.l3i_index, hw_buf);
   3567             (void)_bcm_xgs3_egress_l3_intf_id_free(unit, intf.l3i_index);
   3568             return (rv);
   3569         }
   3570     } else {
   3571         if (NULL != sa_fa) {
   3572             /* Create egress l3 interface. */
   3573             BCM_IF_ERROR_RETURN(_bcm_xgs3_egress_l3_intf_id_alloc(unit,
   3574                 &intf));
   3575 
   3576             /* Write egress interface to the hw. */
   3577             sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   3578 
   3579             /* Set mac address. */
   3580             soc_mem_mac_addr_set(unit, EGR_L3_INTFm, hw_buf,
   3581                 MAC_ADDRESSf, intf.l3i_mac_addr);
   3582 
   3583             /* Set vlan id. */
   3584             soc_mem_field32_set(unit, EGR_L3_INTFm, hw_buf, VIDf, intf.l3i_vid);
   3585 
   3586             /* Write interface configuration to the HW. */
   3587             rv = soc_mem_write(unit, EGR_L3_INTFm, SOC_BLOCK_ALL,
   3588                     intf.l3i_index, hw_buf);
   3589             if (BCM_FAILURE(rv)) {
   3590                 (void)_bcm_xgs3_egress_l3_intf_id_free(unit, intf.l3i_index);
   3591                 return rv;
   3592             }
   3593         }
   3594 
   3595         /* Allocate next hop entry. */
   3596         nh_flags = _BCM_L3_SHR_MATCH_DISABLE | _BCM_L3_SHR_WRITE_DISABLE;
   3597         rv = bcm_xgs3_nh_add(unit, nh_flags, &egr, &nh_index);
   3598         if (BCM_FAILURE(rv)) {
   3599             if (NULL != sa_fa) {
   3600                 sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   3601                 (void)soc_mem_write(unit, EGR_L3_INTFm, SOC_BLOCK_ALL,
   3602                             intf.l3i_index, hw_buf);
   3603                 (void)_bcm_xgs3_egress_l3_intf_id_free(unit, intf.l3i_index);
   3604             }
   3605             return (rv);
   3606         }
   3607 
   3608         /* Write egress next hop entry. */
   3609         sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   3610 
   3611         /* Set next hop mac address. */
   3612         soc_mem_mac_addr_set(unit, EGR_L3_NEXT_HOPm, hw_buf, MAC_ADDRESSf,
   3613             egr.mac_addr);
   3614 
   3615         /* Set Outer Vlan ID. */
   3616         if (NULL != vid_fa) {
   3617             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   3618                 INTF_NUMf, intf.l3i_vid);
   3619         } else if (NULL != sa_fa) {
   3620             /* Set interface id. */
   3621             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   3622                 INTF_NUMf, intf.l3i_index);
   3623         } else {
   3624             /* Set interface id. */
   3625             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, hw_buf,
   3626                 INTF_NUMf, 0);
   3627         }
   3628 
   3629         /* Insert next hop information. */
   3630         rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, SOC_BLOCK_ALL,
   3631                 nh_index, hw_buf);
   3632         if (BCM_FAILURE(rv)) {
   3633             if (NULL != sa_fa) {
   3634                 sal_memset(hw_buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   3635                 (void)soc_mem_write(unit, EGR_L3_INTFm, SOC_BLOCK_ALL,
   3636                             intf.l3i_index, hw_buf);
   3637                 (void)_bcm_xgs3_egress_l3_intf_id_free(unit, intf.l3i_index);
   3638             }
   3639             return (rv);
   3640         }
   3641     }
   3642 
   3643     /* Preserve next hop index in the action structure. */
   3644     if (NULL != vid_fa) {
   3645         vid_fa->hw_index = nh_index;
   3646     }
   3647 
   3648     if (NULL != sa_fa) {
   3649         sa_fa->hw_index = nh_index;
   3650     }
   3651 
   3652     if (NULL != da_fa) {
   3653         da_fa->hw_index = nh_index;
   3654     }
   3655 
   3656     if (NULL != vn_new_fa) {
   3657         vn_new_fa->hw_index = nh_index;
   3658     }
   3659 
   3660     if (NULL != vn_del_fa) {
   3661         vn_del_fa->hw_index = nh_index;
   3662     }
   3663 
   3664     if (NULL != e_new_fa) {
   3665         e_new_fa->hw_index = nh_index;
   3666     }
   3667 
   3668     if (NULL != e_del_fa) {
   3669         e_del_fa->hw_index = nh_index;
   3670     }
   3671 
   3672     return (BCM_E_NONE);
   3673 }
   3674 
   3675 #if defined (BCM_KATANA_SUPPORT) || defined (BCM_TRIDENT_SUPPORT) \
   3676      || defined (BCM_TRIUMPH3_SUPPORT) || defined (BCM_GREYHOUND_SUPPORT) \
   3677      || defined (BCM_ENDURO_SUPPORT)
   3678 
   3679 /*
   3680  * Function:
   3681  *     _bcm_field_l3_egr_entry_type_set
   3682  *
   3683  * Purpose:
   3684  *     Modify EGR_L3_NEXT_HOP entry type.
   3685  *
   3686  * Parameters:
   3687  *     unit        - (IN) BCM device number.
   3688  *     action      - (IN) FP action.
   3689  *     nh_index    - (IN) L3 Next Hop Index.
   3690  *     entry_type  - (IN) Entry type to be set.
   3691  *     disable_val - (IN) Disable value to be set for L3 fields.
   3692  * Returns:
   3693  *     BCM_E_XXX
   3694  */
   3695 int
   3696 _bcm_field_l3_egr_entry_type_set(int unit, bcm_field_action_t action,
   3697                                      int nh_index, int entry_type,
   3698                                      int disable_val)
   3699 {
   3700     int rv = BCM_E_NONE;                    /* Operation return status.  */
   3701     soc_field_t l3_vlan_disable = INVALIDf; /* L3 VLAN disable field.    */
   3702     soc_field_t l3_ttl_disable  = INVALIDf; /* L3 TTL disable field.     */
   3703     soc_field_t l3_sa_disable   = INVALIDf; /* L3 SrcMac disable field.  */
   3704     soc_field_t l3_da_disable   = INVALIDf; /* L3 DstMac disable field.  */
   3705     egr_l3_next_hop_entry_t  egr_l3_next_hop_entry; /* Egress Next Hop table
   3706                                                      * entry info */
   3707 
   3708     if (SOC_IS_TRIUMPH3(unit)) {
   3709        l3_vlan_disable = L2_ACTIONS__L3_UC_VLAN_DISABLEf ;
   3710        l3_ttl_disable  = L2_ACTIONS__L3_UC_TTL_DISABLEf;
   3711        l3_sa_disable   = L2_ACTIONS__L3_UC_SA_DISABLEf;
   3712        l3_da_disable   = L2_ACTIONS__L3_UC_DA_DISABLEf;
   3713     } else if (SOC_IS_KATANA2(unit)) {
   3714        l3_vlan_disable = IFP_ACTIONS__L3_VLAN_DISABLEf ;
   3715        l3_ttl_disable  = IFP_ACTIONS__L3_TTL_DISABLEf;
   3716        l3_sa_disable   = IFP_ACTIONS__L3_SA_DISABLEf;
   3717        l3_da_disable   = IFP_ACTIONS__L3_DA_DISABLEf;
   3718     } else if (SOC_IS_TD_TT(unit) || SOC_IS_GREYHOUND(unit)
   3719                || SOC_IS_KATANA(unit) || SOC_IS_HURRICANE3(unit)
   3720                || SOC_IS_GREYHOUND2(unit))  {
   3721        l3_vlan_disable = IFP_ACTIONS__L3_UC_VLAN_DISABLEf ;
   3722        l3_ttl_disable  = IFP_ACTIONS__L3_UC_TTL_DISABLEf;
   3723        l3_sa_disable   = IFP_ACTIONS__L3_UC_SA_DISABLEf;
   3724        l3_da_disable   = IFP_ACTIONS__L3_UC_DA_DISABLEf;
   3725     } else {
   3726        return BCM_E_CONFIG;
   3727     }
   3728 
   3729     rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm,
   3730                       MEM_BLOCK_ANY, nh_index,
   3731                       &(egr_l3_next_hop_entry.entry_data));
   3732     if (BCM_FAILURE(rv)) {
   3733        return (rv);
   3734     }
   3735 
   3736     if (SOC_MEM_FIELD_VALID(unit, EGR_L3_NEXT_HOPm,
   3737                             ENTRY_TYPEf)) {
   3738         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   3739                             &(egr_l3_next_hop_entry.entry_data),
   3740                             ENTRY_TYPEf, entry_type);
   3741     } else {
   3742         return BCM_E_CONFIG;
   3743     }
   3744 
   3745     if (action == bcmFieldActionL3ChangeMacDa) {
   3746         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   3747                             &(egr_l3_next_hop_entry.entry_data),
   3748                             l3_vlan_disable, disable_val);
   3749     } else {
   3750         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   3751                             &(egr_l3_next_hop_entry.entry_data),
   3752                             l3_da_disable, disable_val);
   3753     }
   3754 
   3755     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   3756                         &(egr_l3_next_hop_entry.entry_data),
   3757                         l3_sa_disable, disable_val);
   3758 
   3759     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm,
   3760                         &(egr_l3_next_hop_entry.entry_data),
   3761                         l3_ttl_disable, disable_val);
   3762 
   3763     soc_mem_lock(unit, EGR_L3_NEXT_HOPm);
   3764     rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY,
   3765                        nh_index,
   3766                        &(egr_l3_next_hop_entry.entry_data));
   3767     if (BCM_FAILURE(rv)) {
   3768          soc_mem_unlock(unit, EGR_L3_NEXT_HOPm);
   3769          return (rv);
   3770     }
   3771 
   3772     soc_mem_unlock(unit, EGR_L3_NEXT_HOPm);
   3773     return (BCM_E_NONE);
   3774 }
   3775 
   3776 /*
   3777  * Function:
   3778  *     _bcm_field_l3_egress_actions_set
   3779  *
   3780  * Purpose:
   3781  *     Modify EGR_L3_NEXT_HOP entry type to IFP_ACTIONS (6) for FP Actions.
   3782  *
   3783  * Parameters:
   3784  *     unit      - (IN) BCM device number.
   3785  *     f_ent     - (IN) Field entry descriptor.
   3786  * Returns:
   3787  *     BCM_E_XXX
   3788  */
   3789 int
   3790 _bcm_field_l3_egress_actions_set(int unit, _field_entry_t *f_ent)
   3791 {
   3792     _field_action_t *fa;            /* Field action descriptor. */
   3793     int nh_index = 0;               /* Next hop index. */
   3794     uint32 ref_count = 0;           /* L3 Reference count  */
   3795 
   3796     /* Input parameters check. */
   3797     if (NULL == f_ent) {
   3798         return (BCM_E_PARAM);
   3799     }
   3800 
   3801     if (_BCM_FIELD_STAGE_INGRESS != f_ent->group->stage_id) {
   3802         return (BCM_E_NONE);
   3803     }
   3804 
   3805     /* The following chips do not support entry type IFP_ACTIONS (6) */
   3806     if (SOC_IS_ENDURO(unit) || SOC_IS_HURRICANE2(unit)) {
   3807         return (BCM_E_NONE);
   3808     }
   3809 
   3810     /* Extract the policy info from the entry structure. */
   3811     for (fa = f_ent->actions;
   3812          ((fa != NULL) && (_FP_ACTION_VALID & fa->flags));
   3813          fa = fa->next) {
   3814         switch (fa->action) {
   3815           case bcmFieldActionL3ChangeVlan:
   3816                break;
   3817 
   3818           case bcmFieldActionL3ChangeMacDa:
   3819                break;
   3820 
   3821           default:
   3822                continue;
   3823         }
   3824 
   3825         /* Validate the Egress object Id */
   3826         /* Make sure the object is only for Next hop entries
   3827            and not for Multipath and DVP*/
   3828         if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, fa->param[0])) {
   3829             nh_index = fa->param[0] - BCM_XGS3_EGRESS_IDX_MIN(unit);
   3830         } else {
   3831             return BCM_E_PARAM;
   3832         }
   3833 
   3834         ref_count = BCM_XGS3_L3_ENT_REF_CNT(BCM_XGS3_L3_TBL_PTR(unit, next_hop),
   3835                                             nh_index);
   3836 
   3837         /* Check to handle Entry reinstall */
   3838         if ((_FP_INVALID_INDEX == fa->hw_index) ||
   3839                 (nh_index != fa->hw_index)) {
   3840 
   3841         /* Make sure entry is valid and not inuse by other modules */
   3842         if (ref_count < 1) {
   3843             return BCM_E_NOT_FOUND;
   3844         } else if (ref_count > 1) {
   3845             return BCM_E_BUSY;
   3846         }
   3847 
   3848         /* Configure ENTRY_TYPE to 6 (IFP_ACTIONS) */
   3849         BCM_IF_ERROR_RETURN(_bcm_field_l3_egr_entry_type_set(unit, fa->action,
   3850                                                              nh_index, 6, 1));
   3851 
   3852         if (_FP_INVALID_INDEX != fa->hw_index) {
   3853             fa->old_index = fa->hw_index;
   3854         }
   3855         /* Preserve next hop index in the action structure. */
   3856         fa->hw_index = nh_index;
   3857         }
   3858     }
   3859     return (BCM_E_NONE);
   3860 }
   3861 
   3862 /*
   3863  * Function:
   3864  *     _bcm_field_l3_egress_actions_reset
   3865  *
   3866  * Purpose:
   3867  *     Reset EGR_L3_NEXT_HOP entry type to 0 for FP actions
   3868  *
   3869  * Parameters:
   3870  *     unit      - (IN) BCM device number.
   3871  *     f_ent     - (IN) Field entry descriptor.
   3872  *     flags     - (IN) Flags.
   3873  * Returns:
   3874  *     BCM_E_XXX
   3875  */
   3876 int
   3877 _bcm_field_l3_egress_actions_reset(int unit, _field_entry_t *f_ent, int flags)
   3878 {
   3879     _field_action_t *fa;          /* Field action descriptor. */
   3880     int nh_index = 0;             /* Next hop id. */
   3881 
   3882     /* Input parameters check. */
   3883     if (NULL == f_ent) {
   3884         return (BCM_E_PARAM);
   3885     }
   3886 
   3887     if (_BCM_FIELD_STAGE_INGRESS != f_ent->group->stage_id) {
   3888         return (BCM_E_NONE);
   3889     }
   3890 
   3891     /* The following chips do not support entry type IFP_ACTIONS (6) */
   3892     if (SOC_IS_ENDURO(unit) || SOC_IS_HURRICANE2(unit)) {
   3893         return (BCM_E_NONE);
   3894     }
   3895 
   3896     /* Extract the policy info from the entry structure. */
   3897     for (fa = f_ent->actions; fa != NULL; fa = fa->next) {
   3898         switch (fa->action) {
   3899           case bcmFieldActionL3ChangeVlan:
   3900                break;
   3901 
   3902           case bcmFieldActionL3ChangeMacDa:
   3903                break;
   3904 
   3905           default:
   3906                continue;
   3907         }
   3908         if ((flags & _FP_ACTION_RESOURCE_FREE) &&
   3909             (_FP_INVALID_INDEX != fa->hw_index)) {
   3910              nh_index = fa->hw_index;
   3911              fa->hw_index = _FP_INVALID_INDEX;
   3912              BCM_IF_ERROR_RETURN
   3913                    (_bcm_field_l3_egr_entry_type_set(unit, fa->action,
   3914                                                      nh_index, 0, 0));
   3915         }
   3916 
   3917         if ((flags & _FP_ACTION_OLD_RESOURCE_FREE) &&
   3918             (_FP_INVALID_INDEX != fa->old_index)) {
   3919              nh_index = fa->old_index;
   3920              fa->old_index = _FP_INVALID_INDEX;
   3921              BCM_IF_ERROR_RETURN
   3922                    (_bcm_field_l3_egr_entry_type_set(unit, fa->action,
   3923                                                      nh_index, 0, 0));
   3924         }
   3925     }
   3926     return (BCM_E_NONE);
   3927 }
   3928 
   3929 #endif /* (BCM_KATANA_SUPPORT) || (BCM_TRIDENT_SUPPORT) ||
   3930           (BCM_TRIUMPH3_SUPPORT) || (BCM_GREYHOUND_SUPPORT) */
   3931 
   3932 
   3933 /*
   3934  * Function:
   3935  *     _bcm_field_l2_actions_hw_alloc
   3936  *
   3937  * Purpose:
   3938  *     Allocate l3 next hop and egress interface for
   3939  *     l2 fields update action.
   3940  * Parameters:
   3941  *     unit      - (IN) BCM device number.
   3942  *     f_ent     - (IN) Field entry descriptor.
   3943  * Returns:
   3944  *     BCM_E_XXX
   3945  */
   3946 STATIC int
   3947 _bcm_field_l2_actions_hw_alloc(int unit, _field_entry_t *f_ent)
   3948 {
   3949     _field_action_t *vid_fa;        /* Update outer vid action.      */
   3950     _field_action_t *sa_fa;         /* Update source mac action.     */
   3951     _field_action_t *da_fa;         /* Update destination mac action.*/
   3952     _field_action_t *vn_new_fa;     /* Change VN tag.                */
   3953     _field_action_t *vn_del_fa;     /* Delete VN tag action.         */
   3954     _field_action_t *e_new_fa;      /* Change E tag.                */
   3955     _field_action_t *e_del_fa;      /* Delete E tag action.         */
   3956     _field_action_t *fa;            /* Field action descriptor.      */
   3957 
   3958     /*
   3959      * Applicable to stage ingress on devices which support
   3960      * soc_feature_field_action_l2_change feature.
   3961      */
   3962     if ((_BCM_FIELD_STAGE_INGRESS != f_ent->group->stage_id) &&
   3963         (_BCM_FIELD_STAGE_EXACTMATCH != f_ent->group->stage_id)) {
   3964         return (BCM_E_NONE);
   3965     }
   3966 
   3967     /* Initialization. */
   3968     sa_fa = da_fa = vid_fa = vn_new_fa = vn_del_fa = e_new_fa = e_del_fa = NULL;
   3969 
   3970     /* Extract the policy info from the entry structure. */
   3971     for (fa = f_ent->actions; ((fa != NULL) && (_FP_ACTION_VALID & fa->flags)); fa = fa->next) {
   3972         switch (fa->action) {
   3973           case bcmFieldActionSrcMacNew:
   3974               if (_FP_INVALID_INDEX != fa->hw_index) {
   3975                   fa->old_index = fa->hw_index;
   3976               }
   3977               sa_fa = fa;
   3978               break;
   3979           case bcmFieldActionDstMacNew:
   3980               if (_FP_INVALID_INDEX != fa->hw_index) {
   3981                   fa->old_index = fa->hw_index;
   3982               }
   3983               da_fa = fa;
   3984               break;
   3985           case bcmFieldActionOuterVlanNew:
   3986               if (_FP_INVALID_INDEX != fa->hw_index) {
   3987                   fa->old_index = fa->hw_index;
   3988               }
   3989               vid_fa = fa;
   3990               break;
   3991           case bcmFieldActionVnTagNew:
   3992               if (_FP_INVALID_INDEX != fa->hw_index) {
   3993                   fa->old_index = fa->hw_index;
   3994               }
   3995               vn_new_fa = fa;
   3996               break;
   3997           case bcmFieldActionVnTagDelete:
   3998               if (_FP_INVALID_INDEX != fa->hw_index) {
   3999                   fa->old_index = fa->hw_index;
   4000               }
   4001               vn_del_fa = fa;
   4002               break;
   4003           case bcmFieldActionEtagNew:
   4004               if (_FP_INVALID_INDEX != fa->hw_index) {
   4005                   fa->old_index = fa->hw_index;
   4006               }
   4007               e_new_fa = fa;
   4008               break;
   4009           case bcmFieldActionEtagDelete:
   4010               if (_FP_INVALID_INDEX != fa->hw_index) {
   4011                   fa->old_index = fa->hw_index;
   4012               }
   4013               e_del_fa = fa;
   4014               break;
   4015           default:
   4016               continue;
   4017         }
   4018     }
   4019 
   4020     /* Create nh entry. */
   4021     if ((NULL != vid_fa) || (NULL != da_fa) || (NULL != sa_fa) ||
   4022         (NULL != vn_new_fa) || (NULL != vn_del_fa) ||
   4023          (NULL != e_new_fa) || (NULL != e_del_fa)) {
   4024         BCM_IF_ERROR_RETURN(_bcm_field_l2_actions_nh_create(unit, da_fa, sa_fa,
   4025             vid_fa, vn_new_fa, vn_del_fa, e_new_fa, e_del_fa));
   4026     }
   4027     return (BCM_E_NONE);
   4028 }
   4029 
   4030 /*
   4031  * Function:
   4032  *     _bcm_field_l2_actions_hw_free
   4033  *
   4034  * Purpose:
   4035  *     Free l3 next hop and egress interface for
   4036  *     l2 fields update action.
   4037  * Parameters:
   4038  *     unit      - (IN) BCM device number.
   4039  *     f_ent     - (IN) Field entry descriptor.
   4040  *     flags     - (IN) Free flags (old/new/both).
   4041  * Returns:
   4042  *     BCM_E_XXX
   4043  */
   4044 STATIC int
   4045 _bcm_field_l2_actions_hw_free(int unit, _field_entry_t *f_ent,
   4046                                   uint32 flags)
   4047 {
   4048     _field_action_t *fa;            /* Field action descriptor.      */
   4049     int nh_index;                   /* Next hop index.               */
   4050     int old_nh_index;               /* Old next hop index.           */
   4051     int egr_intf_set = 0;            /* Egress interface allocated    */
   4052     int rv = BCM_E_NONE;            /* Operation return status.      */
   4053 
   4054     /* Applicable to stage ingress on TRX and FB family of devices only. */
   4055     if ((0 == SOC_IS_TRX(unit))
   4056         && (0 == SOC_IS_FB(unit))
   4057         && (0 == SOC_IS_BRADLEY(unit))) {
   4058         return (BCM_E_NONE);
   4059     }
   4060 
   4061     if ((_BCM_FIELD_STAGE_INGRESS != f_ent->group->stage_id) &&
   4062         (_BCM_FIELD_STAGE_EXACTMATCH != f_ent->group->stage_id)) {
   4063         return BCM_E_NONE;
   4064     }
   4065 
   4066     /* Initialization. */
   4067     nh_index = old_nh_index = _FP_INVALID_INDEX;
   4068 
   4069     /* Extract the policy info from the entry structure. */
   4070     for (fa = f_ent->actions; fa != NULL; fa = fa->next) {
   4071         switch (fa->action) {
   4072           case bcmFieldActionSrcMacNew:
   4073               egr_intf_set = TRUE;
   4074               /* passthru */
   4075               /* coverity[MISSING_BREAK: FALSE] */
   4076           case bcmFieldActionOuterVlanNew:
   4077           case bcmFieldActionDstMacNew:
   4078           case bcmFieldActionVnTagNew:
   4079           case bcmFieldActionVnTagDelete:
   4080           case bcmFieldActionEtagNew:
   4081           case bcmFieldActionEtagDelete:
   4082               if ((flags & _FP_ACTION_RESOURCE_FREE) &&
   4083                   (_FP_INVALID_INDEX != fa->hw_index)) {
   4084                   nh_index = fa->hw_index;
   4085                   fa->hw_index = _FP_INVALID_INDEX;
   4086               }
   4087               if ((flags & _FP_ACTION_OLD_RESOURCE_FREE) &&
   4088                   (_FP_INVALID_INDEX != fa->old_index)) {
   4089                   old_nh_index = fa->old_index;
   4090                   fa->old_index = _FP_INVALID_INDEX;
   4091               }
   4092               break;
   4093           default:
   4094               break;
   4095         }
   4096     }
   4097 
   4098     /* Destroy old next hop if any. */
   4099     if (_FP_INVALID_INDEX != old_nh_index) {
   4100         rv = _bcm_field_l2_actions_nh_destroy(unit, old_nh_index, egr_intf_set);
   4101         BCM_IF_ERROR_RETURN(rv);
   4102     }
   4103     if (_FP_INVALID_INDEX != nh_index) {
   4104         rv = _bcm_field_l2_actions_nh_destroy(unit, nh_index, egr_intf_set);
   4105         BCM_IF_ERROR_RETURN(rv);
   4106     }
   4107     return (BCM_E_NONE);
   4108 }
   4109 #endif /* INCLUDE_L3 */
   4110 
   4111 /*
   4112  * Function:
   4113  *     _field_dest_type_clear
   4114  * Purpose:
   4115  *     Clear Destination Type value in qualifier data.
   4116  * Parameters:
   4117  *     unit     - (IN) BCM device number.
   4118  *     entry    - (IN) entry identifier.
   4119  *     qual     - (IN) field qualifier.
   4120  *     data     - (IN) qualifier data.
   4121  *     mask     - (IN) qualifier mask.
   4122  * Returns:
   4123  *     BCM_E_XXX
   4124  */
   4125 int
   4126 _field_dest_type_clear(int unit, bcm_field_entry_t entry,
   4127         bcm_field_qualify_t qual, uint32 *data, uint32 *mask)
   4128 {
   4129 #ifdef BCM_TRIUMPH2_SUPPORT
   4130     _field_group_t *fg;         /* Field group structure              */
   4131     int entry_width;            /* Forward Entity Select status       */
   4132     int dst_fwd_entity_status;  /* dst_fwd_entity_sel selector status */
   4133 
   4134     /* Check if this device supports per-slice control fields */
   4135     if (0 == soc_feature(unit, soc_feature_field_slice_dest_entity_select)) {
   4136         return (BCM_E_NONE);
   4137     }
   4138 
   4139     BCM_IF_ERROR_RETURN(_bcm_field_entry_group_find(unit, entry, &fg));
   4140 
   4141 #if defined(BCM_TOMAHAWK_SUPPORT)
   4142     /* Return for multi-pipe supported devices */
   4143     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
   4144         _BCM_FIELD_STAGE_INGRESS == fg->stage_id) {
   4145         return (BCM_E_NONE);
   4146     }
   4147 #endif /* BCM_TOMAHAWK_SUPPORT */
   4148 
   4149     /*
   4150      * Check if dst_fwd_entity_sel secondary selector is used.
   4151      */
   4152     for (entry_width = 0; entry_width < _FP_MAX_ENTRY_WIDTH; entry_width++) {
   4153         switch (fg->sel_codes[entry_width].dst_fwd_entity_sel) {
   4154             case _bcmFieldFwdEntityGlp:
   4155                 if (qual == bcmFieldQualifyDstPort
   4156                     || qual == bcmFieldQualifyDstTrunk) {
   4157                     dst_fwd_entity_status = TRUE;
   4158                 } else {
   4159                     dst_fwd_entity_status = FALSE;
   4160                 }
   4161                 break;
   4162             case _bcmFieldFwdEntityMplsGport:
   4163                 if ((qual == bcmFieldQualifyDstMplsGport) ||
   4164                         (qual == bcmFieldQualifyDstMplsGports)) {
   4165                     dst_fwd_entity_status = TRUE;
   4166                 } else {
   4167                     dst_fwd_entity_status = FALSE;
   4168                 }
   4169                 break;
   4170             case _bcmFieldFwdEntityNivGport:
   4171                 if ((qual == bcmFieldQualifyDstNivGport) ||
   4172                         (qual == bcmFieldQualifyDstNivGports)) {
   4173                     dst_fwd_entity_status = TRUE;
   4174                 } else {
   4175                     dst_fwd_entity_status = FALSE;
   4176                 }
   4177                 break;
   4178             case _bcmFieldFwdEntityMimGport:
   4179                 if ((qual == bcmFieldQualifyDstMimGport) ||
   4180                         (qual == bcmFieldQualifyDstMimGports)) {
   4181                     dst_fwd_entity_status = TRUE;
   4182                 } else {
   4183                     dst_fwd_entity_status = FALSE;
   4184                 }
   4185                 break;
   4186             case _bcmFieldFwdEntityWlanGport:
   4187                 if ((qual == bcmFieldQualifyDstWlanGport) ||
   4188                         (qual == bcmFieldQualifyDstWlanGports)) {
   4189                     dst_fwd_entity_status = TRUE;
   4190                 } else {
   4191                     dst_fwd_entity_status = FALSE;
   4192                 }
   4193                 break;
   4194             case _bcmFieldFwdEntityVxlanGport:
   4195                 if ((qual == bcmFieldQualifyDstVxlanGport) ||
   4196                         (qual == bcmFieldQualifyDstVxlanGports)) {
   4197                     dst_fwd_entity_status = TRUE;
   4198                 } else {
   4199                     dst_fwd_entity_status = FALSE;
   4200                 }
   4201                 break;
   4202             case _bcmFieldFwdEntityVlanGport:
   4203                 if ((qual == bcmFieldQualifyDstVlanGport) ||
   4204                         (qual == bcmFieldQualifyDstVlanGports)) {
   4205                     dst_fwd_entity_status = TRUE;
   4206                 } else {
   4207                     dst_fwd_entity_status = FALSE;
   4208                 }
   4209                 break;
   4210             case _bcmFieldFwdEntityCommonGport:
   4211                 if ((qual == bcmFieldQualifyDstGport) ||
   4212                         (qual == bcmFieldQualifyDstGports)) {
   4213                     dst_fwd_entity_status = TRUE;
   4214                 } else {
   4215                     dst_fwd_entity_status = FALSE;
   4216                 }
   4217                 break;
   4218             case _bcmFieldFwdEntityL3Egress:
   4219                 dst_fwd_entity_status
   4220                     = (qual == bcmFieldQualifyDstL3Egress)
   4221                         ? TRUE : (qual == bcmFieldQualifyDstL3EgressNextHops)
   4222                         ? TRUE : FALSE;
   4223                 break;
   4224             case _bcmFieldFwdEntityMulticastGroup:
   4225                 if ((qual == bcmFieldQualifyDstMulticastGroup) ||
   4226                         (qual == bcmFieldQualifyDstMulticastGroups)) {
   4227                     dst_fwd_entity_status = TRUE;
   4228                 } else {
   4229                     dst_fwd_entity_status = FALSE;
   4230                 }
   4231                 break;
   4232             case _bcmFieldFwdEntityMultipath:
   4233                 dst_fwd_entity_status =
   4234                     (qual == bcmFieldQualifyDstMultipath) ? TRUE: FALSE;
   4235                 break;
   4236             default:
   4237                 dst_fwd_entity_status = FALSE;
   4238         }
   4239         if (TRUE == dst_fwd_entity_status) {
   4240             break;
   4241         }
   4242     }
   4243 
   4244     if (FALSE == dst_fwd_entity_status) {
   4245         return BCM_E_NONE;
   4246     } else {
   4247         _FIELD_D_TYPE_RESET(*data);
   4248         _FIELD_D_TYPE_RESET(*mask);
   4249     }
   4250 #endif /* !BCM_TRIUMPH2_SUPPORT */
   4251     return BCM_E_NONE;
   4252 }
   4253 
   4254 /*
   4255  * Function:
   4256  *     _field_dest_type_qualify
   4257  * Purpose:
   4258  *     Set Destination Type value in qualifier data.
   4259  * Parameters:
   4260  *     unit             - (IN) BCM device number.
   4261  *     entry            - (IN) entry identifier.
   4262  *     qual             - (IN) field qualifier.
   4263  *     data             - (IN) qualifier data.
   4264  *     mask             - (IN) qualifier mask.
   4265  *     flags            - (IN) Flags to set d_type.
   4266  * Returns:
   4267  *     BCM_E_XXX
   4268  */
   4269 int
   4270 _field_dest_type_qualify(int unit, bcm_field_entry_t entry,
   4271         bcm_field_qualify_t qual, uint32 *data, uint32 *mask,
   4272         uint32 flags)
   4273 {
   4274 #ifdef BCM_TRIUMPH2_SUPPORT
   4275     _field_group_t *fg;         /* Field group structure              */
   4276     int entry_width;            /* Forward Entity Select status       */
   4277     int dst_fwd_entity_status;  /* dst_fwd_entity_sel selector status */
   4278 
   4279     /* Check if this device supports per-slice control fields */
   4280     if (0 == soc_feature(unit, soc_feature_field_slice_dest_entity_select)) {
   4281         return (BCM_E_NONE);
   4282     }
   4283 
   4284     BCM_IF_ERROR_RETURN(_bcm_field_entry_group_find(unit, entry, &fg));
   4285 
   4286 #if defined(BCM_TOMAHAWK_SUPPORT)
   4287     /* Return for multi-pipe supported devices */
   4288     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
   4289         _BCM_FIELD_STAGE_INGRESS == fg->stage_id) {
   4290         return (BCM_E_NONE);
   4291     }
   4292 #endif /* BCM_TOMAHAWK_SUPPORT */
   4293 
   4294     /*
   4295      * Check if dst_fwd_entity_sel secondary selector is used.
   4296      */
   4297     for (entry_width = 0; entry_width < _FP_MAX_ENTRY_WIDTH; entry_width++) {
   4298         switch (fg->sel_codes[entry_width].dst_fwd_entity_sel) {
   4299             case _bcmFieldFwdEntityGlp:
   4300                 if (qual == bcmFieldQualifyDstPort
   4301                     || qual == bcmFieldQualifyDstTrunk) {
   4302                     dst_fwd_entity_status = TRUE;
   4303                 } else {
   4304                     dst_fwd_entity_status = FALSE;
   4305                 }
   4306                 break;
   4307             case _bcmFieldFwdEntityMplsGport:
   4308                 if ((qual == bcmFieldQualifyDstMplsGport) ||
   4309                         (qual == bcmFieldQualifyDstMplsGports)) {
   4310                     dst_fwd_entity_status = TRUE;
   4311                 } else {
   4312                     dst_fwd_entity_status = FALSE;
   4313                 }
   4314                 break;
   4315             case _bcmFieldFwdEntityNivGport:
   4316                 if ((qual == bcmFieldQualifyDstNivGport) ||
   4317                         (qual == bcmFieldQualifyDstNivGports)) {
   4318                     dst_fwd_entity_status = TRUE;
   4319                 } else {
   4320                     dst_fwd_entity_status = FALSE;
   4321                 }
   4322                 break;
   4323             case _bcmFieldFwdEntityMimGport:
   4324                 if ((qual == bcmFieldQualifyDstMimGport) ||
   4325                         (qual == bcmFieldQualifyDstMimGports)) {
   4326                     dst_fwd_entity_status = TRUE;
   4327                 } else {
   4328                     dst_fwd_entity_status = FALSE;
   4329                 }
   4330                 break;
   4331             case _bcmFieldFwdEntityWlanGport:
   4332                 if ((qual == bcmFieldQualifyDstWlanGport) ||
   4333                         (qual == bcmFieldQualifyDstWlanGports)) {
   4334                     dst_fwd_entity_status = TRUE;
   4335                 } else {
   4336                     dst_fwd_entity_status = FALSE;
   4337                 }
   4338                 break;
   4339             case _bcmFieldFwdEntityVxlanGport:
   4340                 if ((qual == bcmFieldQualifyDstVxlanGport) ||
   4341                         (qual == bcmFieldQualifyDstVxlanGports)) {
   4342                     dst_fwd_entity_status = TRUE;
   4343                 } else {
   4344                     dst_fwd_entity_status = FALSE;
   4345                 }
   4346                 break;
   4347             case _bcmFieldFwdEntityVlanGport:
   4348                 if ((qual == bcmFieldQualifyDstVlanGport) ||
   4349                         (qual == bcmFieldQualifyDstVlanGports)) {
   4350                     dst_fwd_entity_status = TRUE;
   4351                 } else {
   4352                     dst_fwd_entity_status = FALSE;
   4353                 }
   4354                 break;
   4355             case _bcmFieldFwdEntityCommonGport:
   4356                 if ((qual == bcmFieldQualifyDstGport) ||
   4357                         (qual == bcmFieldQualifyDstGports)) {
   4358                     dst_fwd_entity_status = TRUE;
   4359                 } else {
   4360                     dst_fwd_entity_status = FALSE;
   4361                 }
   4362                 break;
   4363             case _bcmFieldFwdEntityL3Egress:
   4364                 dst_fwd_entity_status
   4365                     = (qual == bcmFieldQualifyDstL3Egress)
   4366                         ? TRUE : (qual == bcmFieldQualifyDstL3EgressNextHops)
   4367                         ? TRUE : FALSE;
   4368                 break;
   4369             case _bcmFieldFwdEntityMulticastGroup:
   4370                 if ((qual == bcmFieldQualifyDstMulticastGroup) ||
   4371                         (qual == bcmFieldQualifyDstMulticastGroups)) {
   4372                     dst_fwd_entity_status = TRUE;
   4373                 } else {
   4374                     dst_fwd_entity_status = FALSE;
   4375                 }
   4376                 break;
   4377             case _bcmFieldFwdEntityMultipath:
   4378                 dst_fwd_entity_status =
   4379                     (qual == bcmFieldQualifyDstMultipath) ? TRUE: FALSE;
   4380                 break;
   4381             default:
   4382                 dst_fwd_entity_status = FALSE;
   4383         }
   4384         if (TRUE == dst_fwd_entity_status) {
   4385             break;
   4386         }
   4387     }
   4388 
   4389     if (FALSE == dst_fwd_entity_status) {
   4390         return BCM_E_NONE;
   4391     } else {
   4392         switch (qual) {
   4393             case bcmFieldQualifyDstMplsGport:
   4394             case bcmFieldQualifyDstNivGport:
   4395             case bcmFieldQualifyDstMimGport:
   4396             case bcmFieldQualifyDstWlanGport:
   4397             case bcmFieldQualifyDstVxlanGport:
   4398             case bcmFieldQualifyDstVlanGport:
   4399             case bcmFieldQualifyDstMplsGports:
   4400             case bcmFieldQualifyDstNivGports:
   4401             case bcmFieldQualifyDstMimGports:
   4402             case bcmFieldQualifyDstWlanGports:
   4403             case bcmFieldQualifyDstVxlanGports:
   4404             case bcmFieldQualifyDstVlanGports:
   4405                 _FIELD_D_TYPE_INSERT(*data, _bcmFieldDestTypeDvp);
   4406                 break;
   4407             case bcmFieldQualifyDstL3Egress:
   4408             case bcmFieldQualifyDstL3EgressNextHops:
   4409                 _FIELD_D_TYPE_INSERT(*data, _bcmFieldDestTypeNhi);
   4410                 break;
   4411             case bcmFieldQualifyDstMultipath:
   4412                 _FIELD_D_TYPE_INSERT(*data, _bcmFieldDestTypeEcmp);
   4413                 break;
   4414             case bcmFieldQualifyDstMulticastGroup:
   4415             case bcmFieldQualifyDstMulticastGroups:
   4416                 if (flags & _bcmFieldDestTypeL3mc) {
   4417                     _FIELD_D_TYPE_INSERT(*data, _bcmFieldDestTypeL3mc);
   4418                 } else if (flags & _bcmFieldDestTypeL2mc) {
   4419                     _FIELD_D_TYPE_INSERT(*data, _bcmFieldDestTypeL2mc);
   4420                 } else {
   4421                     return BCM_E_INTERNAL;
   4422                 }
   4423                 break;
   4424             case bcmFieldQualifyDstGport:
   4425             case bcmFieldQualifyDstGports:
   4426                 if (flags & _bcmFieldDestTypeDglp) {
   4427                     _FIELD_D_TYPE_INSERT(*data, _bcmFieldDestTypeDglp);
   4428                 } else if (flags & _bcmFieldDestTypeDvp) {
   4429                     _FIELD_D_TYPE_INSERT(*data, _bcmFieldDestTypeDvp);
   4430                 } else {
   4431                     return BCM_E_INTERNAL;
   4432                 }
   4433                 break;
   4434             default:
   4435                 _FIELD_D_TYPE_INSERT(*data, _bcmFieldDestTypeDglp);
   4436         }
   4437     }
   4438 
   4439     if ((bcmFieldQualifyDstL3EgressNextHops == qual)
   4440         || (bcmFieldQualifyDstTrunk == qual)
   4441         || (bcmFieldQualifyDstMulticastGroups == qual)
   4442         || (bcmFieldQualifyDstPort == qual)) {
   4443         _FIELD_D_TYPE_MASK_INSERT(*mask);
   4444     } else if ((qual != bcmFieldQualifyDstGports) &&
   4445             (qual != bcmFieldQualifyDstWlanGports) &&
   4446             (qual != bcmFieldQualifyDstVlanGports) &&
   4447             (qual != bcmFieldQualifyDstVxlanGports) &&
   4448             (qual != bcmFieldQualifyDstMimGports) &&
   4449             (qual != bcmFieldQualifyDstNivGports) &&
   4450             (qual != bcmFieldQualifyDstMulticastGroups) &&
   4451             (qual != bcmFieldQualifyDstMplsGports)) {
   4452         *mask = (BCM_FIELD_EXACT_MATCH_MASK);
   4453     }
   4454 #endif /* !BCM_TRIUMPH2_SUPPORT */
   4455     return BCM_E_NONE;
   4456 }
   4457 
   4458 /*
   4459  * Function:
   4460  *     _bcm_field_qual_conf_t_init
   4461  * Purpose:
   4462  *     Initialize qualifier configuration structure.
   4463  * Parameters:
   4464  *     ptr  - (OUT) Pointer to field qualifier configuration strucutre.
   4465  *
   4466  * Returns:
   4467  *     Void.
   4468  */
   4469 void
   4470 _bcm_field_qual_conf_t_init(_bcm_field_qual_conf_t *ptr)
   4471 {
   4472     _bcm_field_selector_t  *selector;
   4473 
   4474     if (NULL == ptr) {
   4475         return;
   4476     }
   4477 
   4478     /* Reset qualifier configuration structure. */
   4479     sal_memset(ptr, 0, sizeof(_bcm_field_qual_conf_t));
   4480 
   4481     /* Set Selectors to Don't care. */
   4482     selector           = &ptr->selector;
   4483     selector->dev_sel  = _bcmFieldDevSelDisable;
   4484     selector->pri_sel  = _bcmFieldSliceSelDisable;
   4485     selector->sec_sel  = _bcmFieldSliceSelDisable;
   4486 
   4487     return;
   4488 }
   4489 
   4490 /*
   4491  * Function:
   4492  *     _bcm_field_qual_info_t_init
   4493  * Purpose:
   4494  *     Initialize qualifier info structure.
   4495  * Parameters:
   4496  *     ptr  - (OUT) Pointer to field qualifier info strucutre.
   4497  *
   4498  * Returns:
   4499  *     Void.
   4500  */
   4501 void
   4502 _bcm_field_qual_info_t_init(_bcm_field_qual_info_t *ptr)
   4503 {
   4504     /* Input parameters check. */
   4505     if (NULL == ptr) {
   4506         return;
   4507     }
   4508 
   4509     /* Reset qualifier configuration structure. */
   4510     sal_memset(ptr, 0, sizeof(_bcm_field_qual_info_t));
   4511 
   4512     return;
   4513 }
   4514 
   4515 /*
   4516  * Function:
   4517  *     _bcm_field_qual_insert
   4518  * Purpose:
   4519  *     Add qualifier to stage qualifers list.
   4520  * Parameters:
   4521  *     unit      - (IN) BCM device number.
   4522  *     stage_fc  - (IN) Stage field control strucutre.
   4523  *     qual_type - (IN) Type of Qualifier.
   4524  *     qual_id   - (IN) Qualifier Id.
   4525  *     ptr       - (IN) Reference to qual configuration structure.
   4526  * Returns:
   4527  *     BCM_E_XXX
   4528  */
   4529 int
   4530 _bcm_field_qual_insert (int unit, _field_stage_t *stage_fc, int qual_type,
   4531                         int qual_id, _bcm_field_qual_conf_t *ptr)
   4532 {
   4533     _bcm_field_qual_info_t *f_qual = NULL;        /* Field qualifier info.    */
   4534     _bcm_field_qual_conf_t *f_qual_conf = NULL;   /* Qualifier configuration. */
   4535     int alloc_size;                               /* Memory allocation size.  */
   4536 
   4537     /* Input parameters check. */
   4538     if ((NULL == ptr) || (NULL == stage_fc) ||
   4539         (qual_id < 0) || (qual_id > _bcmFieldQualifyCount)) {
   4540         return BCM_E_PARAM;
   4541     }
   4542 
   4543     /* Check qualifier support based on flag. */
   4544     if ((_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) &&
   4545            (ptr->offset.flags & _BCM_FIELD_QUAL_OFFSET_NO_IFP_SUPPORT)) {
   4546         return BCM_E_NONE;
   4547     }
   4548     if ((_BCM_FIELD_STAGE_EXACTMATCH == stage_fc->stage_id) &&
   4549             (ptr->offset.flags & _BCM_FIELD_QUAL_OFFSET_NO_EM_SUPPORT)) {
   4550         return BCM_E_NONE;
   4551     }
   4552     if ((_BCM_FIELD_STAGE_FLOWTRACKER == stage_fc->stage_id) &&
   4553             (ptr->offset.flags & _BCM_FIELD_QUAL_OFFSET_NO_FT_SUPPORT)) {
   4554         return BCM_E_NONE;
   4555     }
   4556 
   4557     if (stage_fc->stage_id == _BCM_FIELD_STAGE_LOOKUP) {
   4558         if (soc_feature(unit, soc_feature_vfp_no_inner_ip_fields_support)) {
   4559             switch (qual_id) {
   4560                 case bcmFieldQualifyInnerIpProtocolCommon:
   4561                 case bcmFieldQualifyInnerTtl:
   4562                 case bcmFieldQualifyInnerIpFrag:
   4563                 case bcmFieldQualifyInnerTos:
   4564                 case bcmFieldQualifyInnerL4DstPort:
   4565                 case bcmFieldQualifyInnerL4SrcPort:
   4566                 case bcmFieldQualifyInnerIpProtocol:
   4567                 case bcmFieldQualifyInnerDstIp:
   4568                 case bcmFieldQualifyInnerSrcIp:
   4569                 case bcmFieldQualifyInnerSrcIp6:
   4570                 case bcmFieldQualifyInnerDstIp6:
   4571                 case bcmFieldQualifyInnerSrcIp6High:
   4572                 case bcmFieldQualifyInnerDstIp6High:
   4573                     return BCM_E_NONE;
   4574                 default:
   4575                     break;
   4576             }
   4577         }
   4578         /* ExtensionHeaderSubcode is not supported in TD3 VFP */
   4579         if (soc_feature(unit, soc_feature_td3_style_fp)
   4580             && qual_id == bcmFieldQualifyExtensionHeaderSubCode) {
   4581             return BCM_E_NONE;
   4582         }
   4583     }
   4584 
   4585     /* Assign the stage qual_arr based on the qualifier type */
   4586     if (qual_type == _bcmFieldQualifierTypePresel) {
   4587        if (!soc_feature(unit, soc_feature_field_preselector_support)) {
   4588           return BCM_E_INTERNAL;
   4589        }
   4590        f_qual = stage_fc->f_presel_qual_arr[qual_id];
   4591     } else {
   4592        f_qual = stage_fc->f_qual_arr[qual_id];
   4593     }
   4594 
   4595     /* Allocate qualifier descriptor. */
   4596     if (NULL == f_qual) {
   4597         alloc_size = sizeof(_bcm_field_qual_info_t);
   4598         _FP_XGS3_ALLOC(f_qual, alloc_size, "FP qualifier info");
   4599         if (NULL == f_qual) {
   4600             return (BCM_E_MEMORY);
   4601         }
   4602         _bcm_field_qual_info_t_init(f_qual);
   4603         f_qual->qid = qual_id;
   4604     }
   4605 
   4606     /* Allocate qualifier configurations array. */
   4607     /* Re-alloc configuration array if qualifier has multiple configurations. */
   4608     alloc_size = (f_qual->conf_sz + 1) * sizeof (_bcm_field_qual_conf_t);
   4609 
   4610     /* Allocated qualifier descriptor. */
   4611     _FP_XGS3_ALLOC(f_qual_conf, alloc_size, "FP qualifier config");
   4612     if (NULL == f_qual_conf) {
   4613         if (NULL != f_qual->conf_arr) {
   4614            sal_free(f_qual->conf_arr);
   4615         }
   4616         sal_free(f_qual);
   4617         if (qual_type == _bcmFieldQualifierTypePresel) {
   4618            stage_fc->f_presel_qual_arr[qual_id] = NULL;
   4619         } else {
   4620            stage_fc->f_qual_arr[qual_id] = NULL;
   4621         }
   4622         return (BCM_E_MEMORY);
   4623     }
   4624 
   4625     /* Copy previous configurations if any.  */
   4626     if (NULL != f_qual->conf_arr) {
   4627         alloc_size -= sizeof(_bcm_field_qual_conf_t);
   4628         sal_memcpy (f_qual_conf, f_qual->conf_arr, alloc_size);
   4629         sal_free(f_qual->conf_arr);
   4630     }
   4631 
   4632     /* Set configuration array pointer to a new array. */
   4633     f_qual->conf_arr = f_qual_conf;
   4634 
   4635     /* Copy new configuration to configuration array. */
   4636     f_qual->conf_arr[f_qual->conf_sz] = *ptr;
   4637 
   4638     /* Increment number of active configurations. */
   4639     f_qual->conf_sz++;
   4640 
   4641     /* Install qualifier into stage qualifiers array. */
   4642     if (qual_type == _bcmFieldQualifierTypePresel) {
   4643        stage_fc->f_presel_qual_arr[qual_id] = f_qual;
   4644     } else {
   4645        stage_fc->f_qual_arr[qual_id] = f_qual;
   4646     }
   4647 
   4648     return (BCM_E_NONE);
   4649 }
   4650 
   4651 
   4652 /*
   4653  * Function:
   4654  *      _field_selector_update_cmp
   4655  * Purpose:
   4656  *      Compare number of update required in order to use
   4657  *      a qualifier select code.
   4658  * Parameters:
   4659  *      b - (IN) first compared selector.
   4660  *      a - (IN) second compared selector.
   4661  * Returns:
   4662  *      a<=>b
   4663  */
   4664 static INLINE int
   4665 _field_selector_update_cmp(void *a, void *b)
   4666 {
   4667     _bcm_field_qual_conf_t *first;     /* First compared selector.  */
   4668     _bcm_field_qual_conf_t *second;    /* Second compared selector. */
   4669 
   4670     first = (_bcm_field_qual_conf_t *)a;
   4671     second = (_bcm_field_qual_conf_t *)b;
   4672 
   4673     if (first->selector.update_count <
   4674         second->selector.update_count) {
   4675         return (-1);
   4676     } else if (first->selector.update_count >
   4677                second->selector.update_count) {
   4678         return (1);
   4679     }
   4680     return (0);
   4681 }
   4682 
   4683 /*
   4684  * Function:
   4685  *      _field_qual_info_cmp
   4686  * Purpose:
   4687  *      Compare frequency of two qualifiers appearance.
   4688  * Parameters:
   4689  *      b - (IN) first compared qualifier.
   4690  *      a - (IN) second compared qualifier.
   4691  * Returns:
   4692  *      a<=>b
   4693  */
   4694 static INLINE int
   4695 _field_qual_info_cmp (void *a, void *b)
   4696 {
   4697     _bcm_field_qual_info_t **first;     /* First compared qualifier.  */
   4698     _bcm_field_qual_info_t **second;    /* Second compared qualifier. */
   4699 
   4700     first = (_bcm_field_qual_info_t **)a;
   4701     second = (_bcm_field_qual_info_t **)b;
   4702 
   4703     if ((*first)->conf_sz < (*second)->conf_sz) {
   4704         return (-1);
   4705     } else if ((*first)->conf_sz > (*second)->conf_sz) {
   4706         return (1);
   4707     }
   4708     return (0);
   4709 }
   4710 
   4711 /*
   4712  * Function:
   4713  *     _field_selector_insert
   4714  * Purpose:
   4715  *     Insert selector into a specific tcam part of the entry.
   4716  * Parameters:
   4717  *     sel_arr     - (IN) Current entry select codes.
   4718  *     part_idx    - (IN) Tcam part index.
   4719  *     selector     - (IN) Inserted selector.
   4720  * Returns:
   4721  *     BCM_E_XXX
   4722  */
   4723 STATIC int
   4724 _field_selector_insert (_field_sel_t *sel_arr, int part_idx,
   4725                         _bcm_field_selector_t *selector)
   4726 {
   4727     _field_sel_t *tcam_part;   /* Tcam part selectors. */
   4728 
   4729     /* Input parameters check. */
   4730     if ((NULL == sel_arr) || (NULL == selector)) {
   4731         return (BCM_E_PARAM);
   4732     }
   4733 
   4734     tcam_part = sel_arr + part_idx;
   4735 
   4736     /* Per device selector. */
   4737     switch (selector->dev_sel) {
   4738       case _bcmFieldDevSelDisable:
   4739           break;
   4740       case _bcmFieldDevSelInnerVlanOverlay:
   4741           sel_arr[0].inner_vlan_overlay = selector->dev_sel_val;
   4742           break;
   4743       case _bcmFieldDevSelIntrasliceVfpKey:
   4744           sel_arr[0].intraslice_vfp_sel = selector->dev_sel_val;
   4745           break;
   4746       default:
   4747           return (BCM_E_INTERNAL);
   4748     }
   4749 
   4750     /* Primary slice selector. */
   4751     switch (selector->pri_sel) {
   4752       case _bcmFieldSliceSelDisable:
   4753           break;
   4754       case _bcmFieldSliceSelFpf1:
   4755           tcam_part->fpf1 = selector->pri_sel_val;
   4756           break;
   4757       case _bcmFieldSliceSelFpf2:
   4758           tcam_part->fpf2 = selector->pri_sel_val;
   4759           break;
   4760       case _bcmFieldSliceSelFpf3:
   4761           tcam_part->fpf3 = selector->pri_sel_val;
   4762           break;
   4763       case _bcmFieldSliceSelFpf4:
   4764           tcam_part->fpf4 = selector->pri_sel_val;
   4765           break;
   4766       case _bcmFieldSliceSelExternal:
   4767           tcam_part->extn = selector->pri_sel_val;
   4768           break;
   4769       default:
   4770           return (BCM_E_INTERNAL);
   4771     }
   4772 
   4773     /* Per slice selectors are inserted into primary slice only. */
   4774     if ((selector->intraslice) && (0 != part_idx)) {
   4775         tcam_part = sel_arr + (part_idx - 1);
   4776     }
   4777 
   4778     /* Secondary slice selector. */
   4779     switch (selector->sec_sel) {
   4780     case _bcmFieldSliceSelDisable:
   4781         break;
   4782     case _bcmFieldSliceSrcClassSelect:
   4783         tcam_part->src_class_sel = selector->sec_sel_val;
   4784         break;
   4785     case _bcmFieldSliceDstClassSelect:
   4786         tcam_part->dst_class_sel = selector->sec_sel_val;
   4787         break;
   4788     case _bcmFieldSliceIntfClassSelect:
   4789         tcam_part->intf_class_sel = selector->sec_sel_val;
   4790         break;
   4791     case _bcmFieldSliceLoopbackTypeSelect:
   4792         tcam_part->loopback_type_sel = selector->sec_sel_val;
   4793         break;
   4794     case _bcmFieldSliceIngressEntitySelect:
   4795         tcam_part->ingress_entity_sel = selector->sec_sel_val;
   4796         break;
   4797     case _bcmFieldSliceSrcEntitySelect:
   4798         tcam_part->src_entity_sel = selector->sec_sel_val;
   4799         break;
   4800     case _bcmFieldSliceDstFwdEntitySelect:
   4801         tcam_part->dst_fwd_entity_sel = selector->sec_sel_val;
   4802         break;
   4803     case _bcmFieldSliceFwdFieldSelect:
   4804         tcam_part->fwd_field_sel = selector->sec_sel_val;
   4805         break;
   4806     case _bcmFieldSliceIpHeaderSelect:
   4807         tcam_part->ip_header_sel = selector->sec_sel_val;
   4808         break;
   4809     case _bcmFieldSliceSrcTypeSelect:
   4810         tcam_part->src_type_sel = selector->sec_sel_val;
   4811         break;
   4812     case _bcmFieldSliceIp6AddrSelect:
   4813         tcam_part->ip6_addr_sel = selector->sec_sel_val;
   4814         break;
   4815     case _bcmFieldSliceAuxTag1Select:
   4816         tcam_part->aux_tag_1_sel = selector->sec_sel_val;
   4817         break;
   4818     case _bcmFieldSliceAuxTag2Select:
   4819         tcam_part->aux_tag_2_sel = selector->sec_sel_val;
   4820         break;
   4821     case _bcmFieldSliceOamOverLayEnable:
   4822         tcam_part->oam_overlay_sel = selector->sec_sel_val;
   4823         break;
   4824     case _bcmFieldSliceTtlClassSelect:
   4825         tcam_part->ttl_class_sel = selector->sec_sel_val;
   4826         break;
   4827     case _bcmFieldSliceTcpClassSelect:
   4828         tcam_part->tcp_class_sel = selector->sec_sel_val;
   4829         break;
   4830     case _bcmFieldSliceTosClassSelect:
   4831         tcam_part->tos_class_sel = selector->sec_sel_val;
   4832         break;
   4833     case _bcmFieldSliceSelEgrClassF1:
   4834         tcam_part->egr_class_f1_sel = selector->sec_sel_val;
   4835         break;
   4836     case _bcmFieldSliceSelEgrClassF2:
   4837         tcam_part->egr_class_f2_sel = selector->sec_sel_val;
   4838         break;
   4839     case _bcmFieldSliceSelEgrClassF3:
   4840         tcam_part->egr_class_f3_sel = selector->sec_sel_val;
   4841         break;
   4842     case _bcmFieldSliceSelEgrClassF4:
   4843         tcam_part->egr_class_f4_sel = selector->sec_sel_val;
   4844         break;
   4845     case _bcmFieldSliceSelEgrClassF6:
   4846         tcam_part->egr_class_f6_sel = selector->sec_sel_val;
   4847         break;
   4848     case _bcmFieldSliceSelEgrClassF7:
   4849         tcam_part->egr_class_f7_sel = selector->sec_sel_val;
   4850         break;
   4851     case _bcmFieldSliceSelEgrClassF8:
   4852         tcam_part->egr_class_f8_sel = selector->sec_sel_val;
   4853         break;
   4854     case _bcmFieldSliceSelEgrDvpKey4:
   4855         tcam_part->egr_key4_dvp_sel = selector->sec_sel_val;
   4856         break;
   4857     case _bcmFieldSliceSelEgrDvpKey8:
   4858         tcam_part->egr_key8_dvp_sel = selector->sec_sel_val;
   4859         break;
   4860     case _bcmFieldSliceSelEgrMdlKey4:
   4861         tcam_part->egr_key4_mdl_sel = selector->sec_sel_val;
   4862         break;
   4863     case _bcmFieldSliceSelEgrOamOverlayKey4:
   4864         tcam_part->egr_oam_overlay_sel = selector->sec_sel_val;
   4865         break;
   4866     case _bcmFieldSliceSelEgrDestPortF1:
   4867         tcam_part->egr_dest_port_f1_sel = selector->sec_sel_val;
   4868         break;
   4869     case _bcmFieldSliceSelEgrDestPortF5:
   4870         tcam_part->egr_dest_port_f5_sel = selector->sec_sel_val;
   4871         break;
   4872     case _bcmFieldSliceSelEgrClassIdBF1:
   4873         tcam_part->egr_classId_B_f1_sel = selector->sec_sel_val;
   4874         break;
   4875     case _bcmFieldSliceSelEgrClassIdBF2:
   4876         tcam_part->egr_classId_B_f2_sel = selector->sec_sel_val;
   4877         break;
   4878     case _bcmFieldSliceSelEgrClassIdBF3:
   4879         tcam_part->egr_classId_B_f3_sel = selector->sec_sel_val;
   4880         break;
   4881     case _bcmFieldSliceSelEgrClassIdBF4:
   4882         tcam_part->egr_classId_B_f4_sel = selector->sec_sel_val;
   4883         break;
   4884     case _bcmFieldSliceSelEgrClassIdBF5:
   4885         tcam_part->egr_classId_B_f5_sel = selector->sec_sel_val;
   4886         break;
   4887     case _bcmFieldSliceSelEgrClassIdBF6:
   4888         tcam_part->egr_classId_B_f6_sel = selector->sec_sel_val;
   4889         break;
   4890     case _bcmFieldSliceSelEgrClassIdBF7:
   4891         tcam_part->egr_classId_B_f7_sel = selector->sec_sel_val;
   4892         break;
   4893     case _bcmFieldSliceSelEgrClassIdBF8:
   4894         tcam_part->egr_classId_B_f8_sel = selector->sec_sel_val;
   4895         break;
   4896     case _bcmFieldSliceSelEgrClassKey4:
   4897         tcam_part->egr_key4_l3_classId_sel = selector->sec_sel_val;
   4898         break;
   4899     case _bcmFieldSliceSelEgrClassKey8:
   4900         tcam_part->egr_key8_l3_classId_sel = selector->sec_sel_val;
   4901         break;
   4902     default:
   4903         return (BCM_E_INTERNAL);
   4904     }
   4905 
   4906     /* Tertiary slice selector */
   4907     switch (selector->ter_sel) {
   4908     case _bcmFieldSliceSelDisable:
   4909         break;
   4910     case _bcmFieldSliceFpf1SrcDstClassSelect:
   4911         tcam_part->src_dest_class_f1_sel = selector->ter_sel_val;
   4912         break;
   4913     case _bcmFieldSliceFpf3SrcDstClassSelect:
   4914         tcam_part->src_dest_class_f3_sel = selector->ter_sel_val;
   4915         break;
   4916     case _bcmFieldSliceOamInterfaceClassSelect:
   4917         tcam_part->oam_intf_class_sel = selector->ter_sel_val;
   4918         break;
   4919     case _bcmFieldSliceSelEgrClassF6:
   4920         tcam_part->egr_class_f6_sel = selector->ter_sel_val;
   4921         break;
   4922     default:
   4923         return (BCM_E_INTERNAL);
   4924     }
   4925 
   4926     return (BCM_E_NONE);
   4927 }
   4928 
   4929 /*
   4930  * Function:
   4931  *     _field_selector_diff
   4932  * Purpose:
   4933  *     Compare selector configuration with current selectors
   4934  *     status of field group entry.
   4935  * Parameters:
   4936  *     unit        - (IN) BCM device number.
   4937  *     sel_arr     - (IN) Current entry select codes.
   4938  *     part_idx    - (IN) Tcam part index.
   4939  *     selector    - (IN) Compared selector.
   4940  *     diff_count  - (OUT) Number of different elements.
   4941  * Returns:
   4942  *     BCM_E_XXX
   4943  * NOTE:
   4944  *     Function returns BCM_E_RESOURCE if configurations are conflicting.
   4945  */
   4946 int
   4947 _field_selector_diff(int unit, _field_sel_t *sel_arr, int part_idx,
   4948                      _bcm_field_selector_t *selector,
   4949                      uint8 *diff_count)
   4950 {
   4951     uint8 count;                   /* Required updates count. */
   4952     _field_sel_t *tcam_part;       /* Tcam part selectors.    */
   4953 #if defined(BCM_FIREBOLT_SUPPORT)
   4954     int temp;                      /* Temporary test variable.*/
   4955     int rv;                        /* Operation return status.*/
   4956 #endif /* BCM_FIREBOLT_SUPPORT */
   4957 
   4958     /* Input parameters check. */
   4959     if ((NULL == sel_arr) || (NULL == selector) || (NULL == diff_count)) {
   4960         return (BCM_E_PARAM);
   4961     }
   4962 
   4963     count = 0;
   4964     tcam_part = sel_arr + part_idx;
   4965 
   4966     /* Qualifier is available in the second part of intraslice entry */
   4967     if (selector->intraslice) {
   4968         if (_FP_SELCODE_DONT_USE == tcam_part->intraslice) {
   4969             return (BCM_E_RESOURCE);
   4970         }
   4971     } else {
   4972         if (_FP_SELCODE_DONT_USE != tcam_part->intraslice) {
   4973             return (BCM_E_RESOURCE);
   4974         }
   4975     }
   4976 
   4977     /* Qualifier is available only in the primary part of a paired
   4978        entry */
   4979 
   4980     if (selector->primary) {
   4981         if (part_idx % 2) {
   4982             return (BCM_E_RESOURCE);
   4983         }
   4984     }
   4985 
   4986     /* Qualifier is available only in the secondary part of a paired
   4987        entry */
   4988 
   4989     if (selector->secondary) {
   4990         if (_FP_SELCODE_DONT_USE == tcam_part->secondary) {
   4991             return (BCM_E_RESOURCE);
   4992         }
   4993     }
   4994 
   4995     /* Per device selectors. */
   4996     switch (selector->dev_sel) {
   4997       case _bcmFieldDevSelDisable:
   4998           break;
   4999 #if defined(BCM_FIREBOLT_SUPPORT) || defined(BCM_RAVEN_SUPPORT)
   5000       case _bcmFieldDevSelInnerVlanOverlay:
   5001           rv = _bcm_field_fb_group_inner_vlan_overlay_get(unit, &temp);
   5002           BCM_IF_ERROR_RETURN(rv);
   5003           if (((_FP_SELCODE_DONT_CARE != temp)  &&
   5004                (temp != selector->dev_sel_val)) ||
   5005               ((_FP_SELCODE_DONT_CARE != sel_arr[0].inner_vlan_overlay) &&
   5006                (sel_arr[0].inner_vlan_overlay != selector->dev_sel_val))) {
   5007               return (BCM_E_RESOURCE);
   5008           }
   5009           break;
   5010 #endif /* BCM_FIREBOLT_SUPPORT */
   5011 #if defined(BCM_FIREBOLT2_SUPPORT)
   5012       case _bcmFieldDevSelIntrasliceVfpKey:
   5013           rv = _bcm_field_vfp_doublewide_key_select_get(unit, &temp);
   5014           BCM_IF_ERROR_RETURN(rv);
   5015           if (((_FP_SELCODE_DONT_CARE != temp)  &&
   5016                (temp != selector->dev_sel_val)) ||
   5017               ((_FP_SELCODE_DONT_CARE != sel_arr[0].intraslice_vfp_sel) &&
   5018                (sel_arr[0].intraslice_vfp_sel != selector->dev_sel_val))) {
   5019               return (BCM_E_RESOURCE);
   5020           }
   5021           break;
   5022 #endif /* BCM_FIREBOLT2_SUPPORT */
   5023       default:
   5024           return (BCM_E_INTERNAL);
   5025     }
   5026 
   5027 
   5028     /* Primary slice selector. */
   5029     switch (selector->pri_sel) {
   5030       case _bcmFieldSliceSelDisable:
   5031           break;
   5032       case _bcmFieldSliceSelFpf1:
   5033           if (tcam_part->fpf1 == _FP_SELCODE_DONT_CARE) {
   5034               count++;
   5035           } else if (tcam_part->fpf1 != selector->pri_sel_val) {
   5036               return (BCM_E_RESOURCE);
   5037           }
   5038           break;
   5039       case _bcmFieldSliceSelFpf2:
   5040           if (tcam_part->fpf2 == _FP_SELCODE_DONT_CARE) {
   5041               count++;
   5042           } else if (tcam_part->fpf2 != selector->pri_sel_val) {
   5043               return (BCM_E_RESOURCE);
   5044           }
   5045           break;
   5046       case _bcmFieldSliceSelFpf3:
   5047           if (tcam_part->fpf3 == _FP_SELCODE_DONT_CARE) {
   5048               count++;
   5049           } else if (tcam_part->fpf3 != selector->pri_sel_val) {
   5050               return (BCM_E_RESOURCE);
   5051           }
   5052           break;
   5053       case _bcmFieldSliceSelFpf4:
   5054           if (tcam_part->fpf4 == _FP_SELCODE_DONT_CARE) {
   5055               count++;
   5056           } else if (tcam_part->fpf4 != selector->pri_sel_val) {
   5057               return (BCM_E_RESOURCE);
   5058           }
   5059           break;
   5060       case _bcmFieldSliceSelExternal:
   5061           if (tcam_part->extn == _FP_SELCODE_DONT_CARE) {
   5062               count++;
   5063           } else if (tcam_part->extn != selector->pri_sel_val) {
   5064               return (BCM_E_RESOURCE);
   5065           }
   5066           break;
   5067       default:
   5068           return (BCM_E_INTERNAL);
   5069     }
   5070 
   5071     /* Secondary slice selector. */
   5072     /* Per slice selectors are inserted into primary slice only. */
   5073     if ((selector->intraslice) && (0 != part_idx)) {
   5074         tcam_part = sel_arr + (part_idx - 1);
   5075     }
   5076 
   5077     switch (selector->sec_sel) {
   5078     case _bcmFieldSliceSelDisable:
   5079         break;
   5080     case _bcmFieldSliceSrcClassSelect:
   5081         if (tcam_part->src_class_sel == _FP_SELCODE_DONT_CARE) {
   5082             count++;
   5083         } else if (tcam_part->src_class_sel != selector->sec_sel_val) {
   5084             return (BCM_E_RESOURCE);
   5085         }
   5086         break;
   5087     case _bcmFieldSliceDstClassSelect:
   5088         if (tcam_part->dst_class_sel == _FP_SELCODE_DONT_CARE) {
   5089             count++;
   5090         } else if (tcam_part->dst_class_sel != selector->sec_sel_val) {
   5091             return (BCM_E_RESOURCE);
   5092         }
   5093         break;
   5094     case _bcmFieldSliceIntfClassSelect:
   5095         if (tcam_part->intf_class_sel == _FP_SELCODE_DONT_CARE) {
   5096             count++;
   5097         } else if (tcam_part->intf_class_sel != selector->sec_sel_val) {
   5098             return (BCM_E_RESOURCE);
   5099         }
   5100         break;
   5101     case _bcmFieldSliceLoopbackTypeSelect:
   5102         if (tcam_part->loopback_type_sel == _FP_SELCODE_DONT_CARE) {
   5103             count++;
   5104         } else if (tcam_part->loopback_type_sel != selector->sec_sel_val) {
   5105             return (BCM_E_RESOURCE);
   5106         }
   5107         break;
   5108     case _bcmFieldSliceIngressEntitySelect:
   5109         if (tcam_part->ingress_entity_sel == _FP_SELCODE_DONT_CARE) {
   5110             count++;
   5111         } else if (tcam_part->ingress_entity_sel != selector->sec_sel_val) {
   5112             return (BCM_E_RESOURCE);
   5113         }
   5114         break;
   5115     case _bcmFieldSliceSrcEntitySelect:
   5116         if (tcam_part->src_entity_sel == _FP_SELCODE_DONT_CARE) {
   5117             count++;
   5118         } else if (tcam_part->src_entity_sel != selector->sec_sel_val) {
   5119             return (BCM_E_RESOURCE);
   5120         }
   5121         break;
   5122     case _bcmFieldSliceDstFwdEntitySelect:
   5123         if (tcam_part->dst_fwd_entity_sel == _FP_SELCODE_DONT_CARE) {
   5124             count++;
   5125         } else if (tcam_part->dst_fwd_entity_sel != selector->sec_sel_val) {
   5126             return (BCM_E_RESOURCE);
   5127         }
   5128         break;
   5129     case _bcmFieldSliceFwdFieldSelect:
   5130         if (tcam_part->fwd_field_sel == _FP_SELCODE_DONT_CARE) {
   5131             count++;
   5132         } else if (tcam_part->fwd_field_sel != selector->sec_sel_val) {
   5133             return (BCM_E_RESOURCE);
   5134         }
   5135         break;
   5136     case _bcmFieldSliceIpHeaderSelect:
   5137         if (tcam_part->ip_header_sel== _FP_SELCODE_DONT_CARE) {
   5138             count++;
   5139         } else if (tcam_part->ip_header_sel != selector->sec_sel_val) {
   5140             return (BCM_E_RESOURCE);
   5141         }
   5142         break;
   5143     case _bcmFieldSliceSrcTypeSelect:
   5144         if (tcam_part->src_type_sel== _FP_SELCODE_DONT_CARE) {
   5145             count++;
   5146         } else if (tcam_part->src_type_sel != selector->sec_sel_val) {
   5147             return (BCM_E_RESOURCE);
   5148         }
   5149         break;
   5150     case _bcmFieldSliceIp6AddrSelect:
   5151         if (tcam_part->ip6_addr_sel == _FP_SELCODE_DONT_CARE) {
   5152             count++;
   5153         } else if (tcam_part->ip6_addr_sel != selector->sec_sel_val) {
   5154             return (BCM_E_RESOURCE);
   5155         }
   5156         break;
   5157     case _bcmFieldSliceAuxTag1Select:
   5158         if (tcam_part->aux_tag_1_sel == _FP_SELCODE_DONT_CARE) {
   5159             ++count;
   5160         } else if (tcam_part->aux_tag_1_sel != selector->sec_sel_val) {
   5161             return (BCM_E_RESOURCE);
   5162         }
   5163         break;
   5164     case _bcmFieldSliceAuxTag2Select:
   5165         if (tcam_part->aux_tag_2_sel == _FP_SELCODE_DONT_CARE) {
   5166             ++count;
   5167         } else if (tcam_part->aux_tag_2_sel != selector->sec_sel_val) {
   5168             return (BCM_E_RESOURCE);
   5169         }
   5170         break;
   5171     case _bcmFieldSliceOamOverLayEnable:
   5172         if (tcam_part->oam_overlay_sel == _FP_SELCODE_DONT_CARE) {
   5173             ++count;
   5174         } else if (tcam_part->oam_overlay_sel != selector->sec_sel_val) {
   5175             return (BCM_E_RESOURCE);
   5176         }
   5177         break;
   5178     case _bcmFieldSliceSelEgrClassF1:
   5179         if (tcam_part->egr_class_f1_sel == _FP_SELCODE_DONT_CARE) {
   5180             ++count;
   5181         } else if (tcam_part->egr_class_f1_sel != selector->sec_sel_val) {
   5182             return (BCM_E_RESOURCE);
   5183         }
   5184         break;
   5185     case _bcmFieldSliceSelEgrClassF2:
   5186         if (tcam_part->egr_class_f2_sel == _FP_SELCODE_DONT_CARE) {
   5187             ++count;
   5188         } else if (tcam_part->egr_class_f2_sel != selector->sec_sel_val) {
   5189             return (BCM_E_RESOURCE);
   5190         }
   5191         break;
   5192     case _bcmFieldSliceSelEgrClassF3:
   5193         if (tcam_part->egr_class_f3_sel == _FP_SELCODE_DONT_CARE) {
   5194             ++count;
   5195         } else if (tcam_part->egr_class_f3_sel != selector->sec_sel_val) {
   5196             return (BCM_E_RESOURCE);
   5197         }
   5198         break;
   5199     case _bcmFieldSliceSelEgrClassF4:
   5200         if (tcam_part->egr_class_f4_sel == _FP_SELCODE_DONT_CARE) {
   5201             ++count;
   5202         } else if (tcam_part->egr_class_f4_sel != selector->sec_sel_val) {
   5203             return (BCM_E_RESOURCE);
   5204         }
   5205         break;
   5206     case _bcmFieldSliceSelEgrClassF6:
   5207         if (tcam_part->egr_class_f6_sel == _FP_SELCODE_DONT_CARE) {
   5208             ++count;
   5209         } else if (tcam_part->egr_class_f6_sel != selector->sec_sel_val) {
   5210             return (BCM_E_RESOURCE);
   5211         }
   5212         break;
   5213     case _bcmFieldSliceSelEgrClassF7:
   5214         if (tcam_part->egr_class_f7_sel == _FP_SELCODE_DONT_CARE) {
   5215             ++count;
   5216         } else if (tcam_part->egr_class_f7_sel != selector->sec_sel_val) {
   5217             return (BCM_E_RESOURCE);
   5218         }
   5219         break;
   5220     case _bcmFieldSliceSelEgrClassF8:
   5221         if (tcam_part->egr_class_f8_sel == _FP_SELCODE_DONT_CARE) {
   5222             ++count;
   5223         } else if (tcam_part->egr_class_f8_sel != selector->sec_sel_val) {
   5224             return (BCM_E_RESOURCE);
   5225         }
   5226         break;
   5227     case _bcmFieldSliceSelEgrDvpKey4:
   5228         if (tcam_part->egr_key4_dvp_sel == _FP_SELCODE_DONT_CARE) {
   5229             ++count;
   5230         } else if (tcam_part->egr_key4_dvp_sel != selector->sec_sel_val) {
   5231             return (BCM_E_RESOURCE);
   5232         }
   5233         break;
   5234     case _bcmFieldSliceSelEgrDvpKey8:
   5235         if (tcam_part->egr_key8_dvp_sel == _FP_SELCODE_DONT_CARE) {
   5236             ++count;
   5237         } else if (tcam_part->egr_key8_dvp_sel != selector->sec_sel_val) {
   5238             return (BCM_E_RESOURCE);
   5239         }
   5240         break;
   5241     case _bcmFieldSliceSelEgrMdlKey4:
   5242         if (tcam_part->egr_key4_mdl_sel == _FP_SELCODE_DONT_CARE) {
   5243             ++count;
   5244         } else if (tcam_part->egr_key4_mdl_sel != selector->sec_sel_val) {
   5245             return (BCM_E_RESOURCE);
   5246         }
   5247         break;
   5248     case _bcmFieldSliceSelEgrOamOverlayKey4:
   5249         if (tcam_part->egr_oam_overlay_sel == _FP_SELCODE_DONT_CARE) {
   5250             ++count;
   5251         } else if (tcam_part->egr_oam_overlay_sel != selector->sec_sel_val) {
   5252             return (BCM_E_RESOURCE);
   5253         }
   5254         break;
   5255     case _bcmFieldSliceSelEgrDestPortF1:
   5256         if (tcam_part->egr_dest_port_f1_sel == _FP_SELCODE_DONT_CARE) {
   5257             ++count;
   5258         } else if (tcam_part->egr_dest_port_f1_sel != selector->sec_sel_val) {
   5259             return (BCM_E_RESOURCE);
   5260         }
   5261         break;
   5262     case _bcmFieldSliceSelEgrDestPortF5:
   5263         if (tcam_part->egr_dest_port_f5_sel == _FP_SELCODE_DONT_CARE) {
   5264             ++count;
   5265         } else if (tcam_part->egr_dest_port_f5_sel != selector->sec_sel_val) {
   5266             return (BCM_E_RESOURCE);
   5267         }
   5268         break;
   5269     case _bcmFieldSliceSelEgrClassIdBF1:
   5270         if (tcam_part->egr_classId_B_f1_sel == _FP_SELCODE_DONT_CARE) {
   5271             ++count;
   5272         } else if (tcam_part->egr_classId_B_f1_sel != selector->sec_sel_val) {
   5273             return (BCM_E_RESOURCE);
   5274         }
   5275         break;
   5276     case _bcmFieldSliceSelEgrClassIdBF2:
   5277         if (tcam_part->egr_classId_B_f2_sel == _FP_SELCODE_DONT_CARE) {
   5278             ++count;
   5279         } else if (tcam_part->egr_classId_B_f2_sel != selector->sec_sel_val) {
   5280             return (BCM_E_RESOURCE);
   5281         }
   5282         break;
   5283     case _bcmFieldSliceSelEgrClassIdBF3:
   5284         if (tcam_part->egr_classId_B_f3_sel == _FP_SELCODE_DONT_CARE) {
   5285             ++count;
   5286         } else if (tcam_part->egr_classId_B_f3_sel != selector->sec_sel_val) {
   5287             return (BCM_E_RESOURCE);
   5288         }
   5289         break;
   5290     case _bcmFieldSliceSelEgrClassIdBF4:
   5291         if (tcam_part->egr_classId_B_f4_sel == _FP_SELCODE_DONT_CARE) {
   5292             ++count;
   5293         } else if (tcam_part->egr_classId_B_f4_sel != selector->sec_sel_val) {
   5294             return (BCM_E_RESOURCE);
   5295         }
   5296         break;
   5297     case _bcmFieldSliceSelEgrClassIdBF5:
   5298         if (tcam_part->egr_classId_B_f5_sel == _FP_SELCODE_DONT_CARE) {
   5299             ++count;
   5300         } else if (tcam_part->egr_classId_B_f5_sel != selector->sec_sel_val) {
   5301             return (BCM_E_RESOURCE);
   5302         }
   5303         break;
   5304     case _bcmFieldSliceSelEgrClassIdBF6:
   5305         if (tcam_part->egr_classId_B_f6_sel == _FP_SELCODE_DONT_CARE) {
   5306             ++count;
   5307         } else if (tcam_part->egr_classId_B_f6_sel != selector->sec_sel_val) {
   5308             return (BCM_E_RESOURCE);
   5309         }
   5310         break;
   5311     case _bcmFieldSliceSelEgrClassIdBF7:
   5312         if (tcam_part->egr_classId_B_f7_sel == _FP_SELCODE_DONT_CARE) {
   5313             ++count;
   5314         } else if (tcam_part->egr_classId_B_f7_sel != selector->sec_sel_val) {
   5315             return (BCM_E_RESOURCE);
   5316         }
   5317         break;
   5318     case _bcmFieldSliceSelEgrClassIdBF8:
   5319         if (tcam_part->egr_classId_B_f8_sel == _FP_SELCODE_DONT_CARE) {
   5320             ++count;
   5321         } else if (tcam_part->egr_classId_B_f8_sel != selector->sec_sel_val) {
   5322             return (BCM_E_RESOURCE);
   5323         }
   5324         break;
   5325     case _bcmFieldSliceTtlClassSelect:
   5326         if (tcam_part->ttl_class_sel== _FP_SELCODE_DONT_CARE) {
   5327             ++count;
   5328         } else if (tcam_part->ttl_class_sel != selector->sec_sel_val) {
   5329             return (BCM_E_RESOURCE);
   5330         }
   5331         break;
   5332     case _bcmFieldSliceTcpClassSelect:
   5333         if (tcam_part->tcp_class_sel== _FP_SELCODE_DONT_CARE) {
   5334             ++count;
   5335         } else if (tcam_part->tcp_class_sel != selector->sec_sel_val) {
   5336             return (BCM_E_RESOURCE);
   5337         }
   5338         break;
   5339     case _bcmFieldSliceTosClassSelect:
   5340         if (tcam_part->tos_class_sel== _FP_SELCODE_DONT_CARE) {
   5341             ++count;
   5342         } else if (tcam_part->tos_class_sel != selector->sec_sel_val) {
   5343             return (BCM_E_RESOURCE);
   5344         }
   5345         break;
   5346     case _bcmFieldSliceSelEgrClassKey4:
   5347         if (tcam_part->egr_key4_l3_classId_sel== _FP_SELCODE_DONT_CARE) {
   5348             ++count;
   5349         } else if (tcam_part->egr_key4_l3_classId_sel != selector->sec_sel_val) {
   5350             return (BCM_E_RESOURCE);
   5351         }
   5352         break;
   5353     case _bcmFieldSliceSelEgrClassKey8:
   5354         if (tcam_part->egr_key8_l3_classId_sel== _FP_SELCODE_DONT_CARE) {
   5355             ++count;
   5356         } else if (tcam_part->egr_key8_l3_classId_sel != selector->sec_sel_val) {
   5357             return (BCM_E_RESOURCE);
   5358         }
   5359         break;
   5360     default:
   5361         return (BCM_E_INTERNAL);
   5362     }
   5363 
   5364     /* Tertiary slice selector */
   5365     switch (selector->ter_sel) {
   5366     case _bcmFieldSliceSelDisable:
   5367         break;
   5368     case _bcmFieldSliceFpf1SrcDstClassSelect:
   5369         if (tcam_part->src_dest_class_f1_sel == _FP_SELCODE_DONT_CARE) {
   5370             ++count;
   5371         } else if (tcam_part->src_dest_class_f1_sel != selector->ter_sel_val) {
   5372             return (BCM_E_RESOURCE);
   5373         }
   5374         break;
   5375     case _bcmFieldSliceFpf3SrcDstClassSelect:
   5376         if (tcam_part->src_dest_class_f3_sel == _FP_SELCODE_DONT_CARE) {
   5377             ++count;
   5378         } else if (tcam_part->src_dest_class_f3_sel != selector->ter_sel_val) {
   5379             return (BCM_E_RESOURCE);
   5380         }
   5381         break;
   5382     case _bcmFieldSliceOamInterfaceClassSelect:
   5383         if (tcam_part->oam_intf_class_sel == _FP_SELCODE_DONT_CARE) {
   5384             ++count;
   5385         } else if (tcam_part->oam_intf_class_sel != selector->ter_sel_val) {
   5386             return (BCM_E_RESOURCE);
   5387         }
   5388         break;
   5389     case _bcmFieldSliceSelEgrClassF6:
   5390         if (tcam_part->egr_class_f6_sel == _FP_SELCODE_DONT_CARE) {
   5391             ++count;
   5392         } else if (tcam_part->egr_class_f6_sel != selector->ter_sel_val) {
   5393             return (BCM_E_RESOURCE);
   5394         }
   5395         break;
   5396     default:
   5397         return (BCM_E_INTERNAL);
   5398     }
   5399 
   5400     *diff_count = count;
   5401 
   5402     return (BCM_E_NONE);
   5403 }
   5404 
   5405 
   5406 /*
   5407  * Function:
   5408  *     _field_slice_is_empty
   5409  *
   5410  * Purpose:
   5411  *     Report if a slice has any entries.
   5412  *
   5413  * Parameters:
   5414  *     fc     - (IN) Field control structure.
   5415  *     fs     - (IN) Slice control structure.
   5416  *     empty - (OUT) True - slice is empty/False otherwise.
   5417  *
   5418  * Returns:
   5419  *     BCM_E_XXX
   5420  */
   5421 STATIC int
   5422 _field_slice_is_empty(int unit, _field_slice_t *fs, uint8 *empty)
   5423 {
   5424     int ratio = 1;                  /* Free to Total entry ratio.     */
   5425 
   5426     /* Input parameters check. */
   5427     if (NULL == fs) {
   5428         return (BCM_E_PARAM);
   5429     }
   5430 
   5431     if (fs->group_flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
   5432         ratio = 2;
   5433     }
   5434 
   5435     if (fs->entry_count == ratio * fs->free_count) {
   5436         *empty = TRUE;
   5437     } else {
   5438         *empty = FALSE;
   5439     }
   5440     return (BCM_E_NONE);
   5441 }
   5442 
   5443 /*
   5444  * Function:
   5445  *     _bcm_field_group_status_init
   5446  * Purpose:
   5447  *     Initialize bcm_field_group_status_t structure.
   5448  * Parameters:
   5449  *     unit  -  (IN)BCM unit number.
   5450  *     entry -  (OUT)Initialized field group status structure.
   5451  * Retruns:
   5452  *     BCM_E_XXX
   5453  */
   5454 int
   5455 _bcm_field_group_status_init(int unit, bcm_field_group_status_t *entry)
   5456 {
   5457     /* Input parameters check. */
   5458     if (NULL == entry) {
   5459         return (BCM_E_PARAM);
   5460     }
   5461 
   5462     sal_memset(entry, 0,  sizeof(bcm_field_group_status_t));
   5463 
   5464     entry->prio_min = BCM_FIELD_GROUP_PRIO_ANY;
   5465     entry->prio_max = BCM_FIELD_ENTRY_PRIO_HIGHEST;
   5466     entry->entries_total = -1;
   5467     entry->entries_free = -1;
   5468     entry->counters_total = -1;
   5469     entry->counters_free = -1;
   5470     entry->meters_total = -1;
   5471     entry->meters_free = -1;
   5472     entry->entry_count = 0;
   5473     entry->counter_count = 0;
   5474     entry->meter_count = 0;
   5475 
   5476     return (BCM_E_NONE);
   5477 }
   5478 
   5479 /*
   5480  * Function:
   5481  *     _bcm_field_stage_entries_free
   5482  * Purpose:
   5483  *     Free entries array for all stage slices.
   5484  * Parameters:
   5485  *     unit     -  (IN)BCM unit number.
   5486  *     stage_fc -  (IN)Stage field control
   5487  * Retruns:
   5488  *     BCM_E_XXX
   5489  */
   5490 int
   5491 _bcm_field_stage_entries_free(int unit, _field_stage_t *stage_fc)
   5492 {
   5493     _field_slice_t *fs;   /* Field slice pointer.   */
   5494     int idx;              /* Slice iteration index. */
   5495 
   5496     /* Input parameters check */
   5497     if (NULL == stage_fc) {
   5498         return (BCM_E_PARAM);
   5499     }
   5500     /* Deallocate the entry pointers */
   5501     for (idx = 0; idx < stage_fc->tcam_slices; idx++) {
   5502         fs = stage_fc->slices[_FP_DEF_INST] + idx;
   5503         if (NULL != fs->entries) {
   5504             sal_free(fs->entries);
   5505             fs->entries = NULL;
   5506         }
   5507     }
   5508     return (BCM_E_NONE);
   5509 }
   5510 
   5511 /*
   5512  * Function:
   5513  *     _field_control_get
   5514  * Purpose:
   5515  *     Lookup a FP control config from a bcm device id.
   5516  * Parameters:
   5517  *     unit -  (IN)BCM unit number.
   5518  *     fc   -  (OUT) Field control structure.
   5519  * Retruns:
   5520  *     BCM_E_XXX
   5521  */
   5522 int
   5523 _field_control_get(int unit, _field_control_t **fc)
   5524 {
   5525     /* Input parameters check. */
   5526     if (NULL == fc) {
   5527         return (BCM_E_PARAM);
   5528     }
   5529 
   5530     /* Make sure system was initialized. */
   5531     FIELD_IS_INIT(unit);
   5532 
   5533     /* Fill field control structure. */
   5534     *fc = _field_control[unit];
   5535 
   5536     return (BCM_E_NONE);
   5537 }
   5538 
   5539 /*
   5540  * Function: _field_slice_info_fill
   5541  *
   5542  * Purpose:
   5543  *     fill the slice_info structure with group details
   5544  *
   5545  * Parameters:
   5546  *     unit           - (IN) BCM device number
   5547  *     fs             - (IN) slice pointer
   5548  *     group_id       - (IN) field group ID
   5549  *     slice_no       - (IN) slice no to match
   5550  *     flag_base      - (IN) flag to be set for base slice
   5551  *     flag_expanded  - (IN) flag to be set for expanded slice
   5552  *     slice_info     - (OUT) Slice information
   5553  *
   5554  * Returns:
   5555  *   BCM_E_NONE         - if given slice number is used by the group
   5556  *   BCM_E_NOT_FOUND    - if given slice number is not used by the group
   5557  */
   5558 
   5559 int
   5560 _field_slice_info_fill(int unit,
   5561                       _field_slice_t *fs,
   5562                       int group_id,
   5563                       int slice_no,
   5564                       int flag_base,
   5565                       int flag_expanded,
   5566                       bcm_field_stage_slice_info_t *slice_info) {
   5567     int is_not_first = 0;
   5568     int group_cnt = 0;
   5569     while (fs != NULL) {
   5570         if (is_not_first) {
   5571             if (fs->slice_number == slice_no) {
   5572                 slice_info->flags |= flag_expanded;
   5573                 /* group_cnt points to the next free index
   5574                  * in slice_groupid_list
   5575                  */
   5576                  group_cnt = slice_info->slice_gid_ct;
   5577                  slice_info->slice_gid_list[group_cnt]
   5578                      = group_id;
   5579                  slice_info->slice_gid_ct += 1;
   5580                  return BCM_E_NONE;
   5581             }
   5582         } else {
   5583             if (fs->slice_number == slice_no) {
   5584                 slice_info->flags |= flag_base;
   5585                 /* group_cnt points to the next free index
   5586                  * in slice_groupid_list
   5587                  */
   5588                  group_cnt = slice_info->slice_gid_ct;
   5589                  slice_info->slice_gid_list[group_cnt]
   5590                      = group_id;
   5591                  slice_info->slice_gid_ct += 1;
   5592                  return BCM_E_NONE;
   5593             }
   5594             is_not_first = 1;
   5595         }
   5596         fs = fs->next;
   5597     }
   5598     return (BCM_E_NOT_FOUND);
   5599 }
   5600 
   5601 /*
   5602  * Function: _bcm_field_stage_slice_count_get
   5603  *
   5604  * Purpose:
   5605  *     Return the number of slices in a given stage
   5606  *
   5607  * Parameters:
   5608  *     unit        - (IN)  BCM device number
   5609  *     stage_id    - (IN)  Stage ID
   5610  *     slice_count - (OUT) Number of slices in a given stage
   5611  *
   5612  * Returns:
   5613  *     BCM_E_XXX
   5614  */
   5615 int
   5616 _bcm_field_stage_slice_count_get(
   5617     int unit,
   5618     bcm_field_stage_t stage_id,
   5619     int *slice_count) {
   5620 
   5621     _field_stage_t      *stage_fc;
   5622     _field_control_t    *fc;
   5623     _field_stage_id_t   stage_id_used;
   5624     int  rv = BCM_E_NONE;
   5625 
   5626     if (slice_count == NULL) {
   5627         return BCM_E_PARAM;
   5628     }
   5629 
   5630     if (stage_id == bcmFieldStageIngress) {
   5631         stage_id_used = _BCM_FIELD_STAGE_INGRESS;
   5632     } else if (stage_id == bcmFieldStageEgress) {
   5633         stage_id_used = _BCM_FIELD_STAGE_EGRESS;
   5634     } else if (stage_id == bcmFieldStageLookup) {
   5635         stage_id_used = _BCM_FIELD_STAGE_LOOKUP;
   5636     } else {
   5637         return BCM_E_PARAM;
   5638     }
   5639 
   5640     rv = _field_control_get(unit, &fc);
   5641     BCM_IF_ERROR_RETURN(rv);
   5642 
   5643     rv = _field_stage_control_get (unit, stage_id_used, &stage_fc);
   5644     BCM_IF_ERROR_RETURN(rv);
   5645 
   5646     *slice_count = stage_fc->tcam_slices;
   5647 
   5648     return BCM_E_NONE;
   5649 }
   5650 
   5651 /*
   5652  * Function: _bcm_field_stage_slice_info_get
   5653  *
   5654  * Purpose:
   5655  *     Return the details of the stage and entries
   5656  *     count of the slice for the given portbitmap
   5657  *
   5658  * Parameters:
   5659  *     unit       - (IN) BCM device number
   5660  *     stage_id   - (IN) Stage ID
   5661  *     pbmp       - (IN) port bitmap of the pipe for
   5662  *                       which the details are required
   5663  *     slice_no   - (IN) slice no to retrieve the info
   5664  *     slice_info - (OUT) Slice information
   5665  *
   5666  * Returns:
   5667  *     BCM_E_XXX
   5668  */
   5669 int
   5670 _bcm_field_stage_slice_info_get(
   5671     int unit,
   5672     bcm_field_stage_t stage_id,
   5673     bcm_pbmp_t pbmp,
   5674     int slice_no,
   5675     bcm_field_stage_slice_info_t *slice_info) {
   5676 
   5677     bcm_port_config_t   pc;
   5678     _field_stage_t      *stage_fc;
   5679     _field_group_t      *fg;
   5680     _field_control_t    *fc;
   5681     _field_slice_t      *fs;
   5682     _field_stage_id_t   stage_id_used;
   5683     int indx  = 0;
   5684     int inst  = 0;
   5685     int flags = 0;
   5686     int  rv = BCM_E_NONE;
   5687     int  temp_rv = BCM_E_NONE;
   5688 
   5689     if (slice_info == NULL) {
   5690         return BCM_E_PARAM;
   5691     }
   5692 
   5693     if (stage_id == bcmFieldStageIngress) {
   5694         stage_id_used = _BCM_FIELD_STAGE_INGRESS;
   5695     } else if (stage_id == bcmFieldStageEgress) {
   5696         stage_id_used = _BCM_FIELD_STAGE_EGRESS;
   5697     } else if (stage_id == bcmFieldStageLookup) {
   5698         stage_id_used = _BCM_FIELD_STAGE_LOOKUP;
   5699     } else {
   5700         return BCM_E_PARAM;
   5701     }
   5702 
   5703     rv = _field_control_get(unit, &fc);
   5704     BCM_IF_ERROR_RETURN(rv);
   5705 
   5706     rv = _field_stage_control_get (unit, stage_id_used, &stage_fc);
   5707     BCM_IF_ERROR_RETURN(rv);
   5708 
   5709     if ((slice_no < 0) || (slice_no >= stage_fc->tcam_slices)) {
   5710         return BCM_E_PARAM;
   5711     }
   5712 
   5713     if (stage_fc->oper_mode == bcmFieldGroupOperModePipeLocal) {
   5714         if (BCM_PBMP_IS_NULL(pbmp)) {
   5715             return BCM_E_PARAM;
   5716         }
   5717         bcm_port_config_t_init(&pc);
   5718         rv = bcm_esw_port_config_get(unit, &pc);
   5719         BCM_IF_ERROR_RETURN(rv);
   5720 
   5721         for (indx=0; indx < stage_fc->num_pipes; indx++) {
   5722             if (BCM_PBMP_IS_NULL(PBMP_PIPE(unit, indx))) {
   5723                 continue;
   5724             }
   5725             if (BCM_PBMP_EQ(pbmp, pc.per_pipe[indx])) {
   5726                 inst = indx;
   5727                 break;
   5728             }
   5729         }
   5730         if (indx == stage_fc->num_pipes) {
   5731             return BCM_E_PARAM;
   5732         }
   5733     }
   5734     sal_memset(slice_info, 0x00, sizeof(bcm_field_stage_slice_info_t));
   5735     fs = stage_fc->slices[inst];
   5736     /* fill slice_info with free and entry count */
   5737     slice_info->free_entries =
   5738              fs[slice_no].free_count;
   5739     slice_info->total_entries =
   5740              fs[slice_no].entry_count;
   5741     /* fill slice_info with group details */
   5742     fg = fc->groups;
   5743     for (; fg != NULL; fg = fg->next) {
   5744         if ((fg->stage_id == stage_id_used) &&
   5745             (fg->instance == inst)) {
   5746             flags = BCM_FIELD_SLICE_ALLOCATED;
   5747             if (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) {
   5748                 flags |= BCM_FIELD_SLICE_MODE_TRIPLE;
   5749             } else if (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) {
   5750                 flags |= BCM_FIELD_SLICE_MODE_DOUBLE;
   5751             } else if (fg->flags & _FP_GROUP_SPAN_SINGLE_SLICE) {
   5752                 if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
   5753                     flags |= BCM_FIELD_SLICE_MODE_INTRADOUBLE;
   5754                 } else {
   5755                     flags |= BCM_FIELD_SLICE_MODE_SINGLE;
   5756                 }
   5757             }
   5758             /* fill slice_info  with group primary slices */
   5759             temp_rv = _field_slice_info_fill(unit,
   5760                               &fg->slices[0],
   5761                               fg->gid,
   5762                               slice_no,
   5763                               flags | BCM_FIELD_SLICE_PART_PRIMARY,
   5764                               flags | BCM_FIELD_SLICE_PART_PRIMARY_EXPANDED,
   5765                               slice_info);
   5766 
   5767             /* fill slice_info  with group seconday slices */
   5768             if ((temp_rv == BCM_E_NOT_FOUND) &&
   5769                 ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) ||
   5770                 (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE))) {
   5771                temp_rv =  _field_slice_info_fill(unit,
   5772                               &fg->slices[1],
   5773                               fg->gid,
   5774                               slice_no,
   5775                               flags | BCM_FIELD_SLICE_PART_SECONDARY,
   5776                               flags | BCM_FIELD_SLICE_PART_SECONDARY_EXPANDED,
   5777                               slice_info);
   5778             }
   5779             /* fill slice_info  with group tertiary slices */
   5780             if ((temp_rv == BCM_E_NOT_FOUND) &&
   5781                 (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE)) {
   5782                 _field_slice_info_fill(unit,
   5783                               &fg->slices[2],
   5784                               fg->gid,
   5785                               slice_no,
   5786                               flags | BCM_FIELD_SLICE_PART_TERTIARY,
   5787                               flags | BCM_FIELD_SLICE_PART_TERTIARY_EXPANDED,
   5788                               slice_info);
   5789             }
   5790         }
   5791     }
   5792     return rv;
   5793 }
   5794 
   5795 
   5796 /*
   5797  * Function:
   5798  *     _field_egr_ports_recovery_control_get
   5799  * Purpose:
   5800  *     Lookup a FP EGR_PORTS_RECOVERY config
   5801  *     from a bcm device id.
   5802  * Parameters:
   5803  *     unit           -  (IN) BCM unit number.
   5804  *     f_egr_recovery - (OUT) Field Egr_ports_recovery
   5805  *                            structure.
   5806  * Returns:
   5807  *     BCM_E_XXX
   5808  */
   5809 int
   5810 _field_egr_ports_recovery_control_get(int unit,
   5811          _field_egr_ports_recovery_t **f_egr_recovery)
   5812 {
   5813     /* Input parameters check. */
   5814     if (NULL == f_egr_recovery) {
   5815         return (BCM_E_PARAM);
   5816     }
   5817 
   5818     /* Fill field control structure. */
   5819     *f_egr_recovery = _field_egr_ports_recovery[unit];
   5820 
   5821     return (BCM_E_NONE);
   5822 }
   5823 
   5824 /*
   5825  * Function:
   5826  *     _field_stage_control_get
   5827  * Purpose:
   5828  *     Lookup stage FP control config from bcm device id and
   5829  *     pipeline stage number.
   5830  * Parameters:
   5831  *     unit      -  (IN)BCM unit number.
   5832  *     stage_id  -  (IN)Pipeline stage id number.
   5833  *     stage_fc  -  (OUT) Stage Field control structure.
   5834  * Retruns:
   5835  *     BCM_E_XXX
   5836  */
   5837 int
   5838 _field_stage_control_get(int unit, _field_stage_id_t stage_id,
   5839                           _field_stage_t **stage_fc)
   5840 {
   5841     _field_stage_t *stage_p;  /* Stages iteration pointer. */
   5842 
   5843     FIELD_IS_INIT(unit);                                      \
   5844 
   5845     /* Input parameters check. */
   5846     if (NULL == stage_fc) {
   5847         return (BCM_E_PARAM);
   5848     }
   5849 
   5850     /* Check that module was initialized. */
   5851     if (NULL == (_field_control[unit])->stages) {
   5852         LOG_ERROR(BSL_LS_BCM_FP,
   5853                   (BSL_META_U(unit,
   5854                               "FP(unit %d) Error: Stage (%d) is not initialized.\n"),
   5855                    unit, stage_id));
   5856         return (BCM_E_INIT);
   5857     }
   5858 
   5859     /* Find a stage with stage_id equals to stage. */
   5860     stage_p = (_field_control[unit])->stages;
   5861     while (stage_p) {
   5862         if (stage_p->stage_id == stage_id) {
   5863             break;
   5864         }
   5865         stage_p = stage_p->next;
   5866     }
   5867 
   5868     if (NULL == stage_p) {
   5869         if(((_field_control[unit])->flags & _FP_EXTERNAL_PRESENT) ||
   5870             (_BCM_FIELD_STAGE_EXTERNAL != stage_id))
   5871         {
   5872             LOG_INFO(BSL_LS_BCM_FP,
   5873                     (BSL_META_U(unit,
   5874                                 "FP(unit %d) Verb: Unknown pipeline stage (%d).\n"),
   5875                      unit, stage_id));
   5876         }
   5877         if (_BCM_FIELD_STAGE_EXTERNAL == stage_id) {
   5878             return (BCM_E_UNAVAIL);
   5879         } else if (_BCM_FIELD_STAGE_EXACTMATCH == stage_id) {
   5880             return (BCM_E_UNAVAIL);
   5881         } else if (_BCM_FIELD_STAGE_CLASS == stage_id) {
   5882             return (BCM_E_UNAVAIL);
   5883         } else if (((stage_id == _BCM_FIELD_STAGE_EGRESS) ||
   5884             (stage_id == _BCM_FIELD_STAGE_LOOKUP)) &&
   5885             (!soc_feature(unit, soc_feature_field_multi_stage))) {
   5886             return (BCM_E_UNAVAIL);
   5887         } else {
   5888             return (BCM_E_NOT_FOUND);
   5889         }
   5890     }
   5891 
   5892     /* Fill stage field control structure. */
   5893     *stage_fc = stage_p;
   5894 
   5895     return (BCM_E_NONE);
   5896 }
   5897 
   5898 /*
   5899  * Function:
   5900  *     _field_group_get
   5901  * Purpose:
   5902  *     Lookup a group information on specified bcm device.
   5903  * Parameters:
   5904  *     unit - (IN)BCM device number.
   5905  *     gid  - (IN)Group ID.
   5906  * Returns:
   5907  *     BCM_E_XXX
   5908  */
   5909 int
   5910 _field_group_get(int unit, bcm_field_group_t gid, _field_group_t **group_p)
   5911 {
   5912     _field_control_t    *fc;          /* Unit FP control structure. */
   5913     _field_group_t      *fg;          /* Group information.         */
   5914 
   5915     if (NULL == group_p) {
   5916         return (BCM_E_PARAM);
   5917     }
   5918 
   5919     /* Get unit FP control structure. */
   5920     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   5921 
   5922     /* Iterate over the groups linked-list looking for a matching Group ID */
   5923     fg = fc->groups;
   5924     while (fg != NULL) {
   5925         if (fg->gid == gid) {
   5926             *group_p = fg;
   5927             return (BCM_E_NONE);
   5928         }
   5929         fg = fg->next;
   5930     }
   5931     /* Group with id == gid not found. */
   5932     return (BCM_E_NOT_FOUND);
   5933 }
   5934 
   5935 /*
   5936  * Function:
   5937  *     _bcm_field_group_id_generate
   5938  *
   5939  * Purpose:
   5940  *     Find an unused Group ID.
   5941  *
   5942  * Parameters:
   5943  *     unit  - BCM device number
   5944  *     group - (OUT) new Group ID
   5945  *
   5946  * Returns:
   5947  *     BCM_E_NONE  - Success
   5948  *     BCM_E_PARAM - null pointer to group
   5949  */
   5950 int
   5951 _bcm_field_group_id_generate(int unit, bcm_field_group_t *group)
   5952 {
   5953     _field_group_t *group_p;  /* Group info. */
   5954 
   5955     /* Input parameters check. */
   5956     if (NULL == group) {
   5957         LOG_ERROR(BSL_LS_BCM_FP,
   5958                   (BSL_META_U(unit,
   5959                               "FP(unit %d) Error: group == NULL\n"),
   5960                    unit));
   5961         return (BCM_E_PARAM);
   5962     }
   5963 
   5964     *group = _FP_ID_BASE;
   5965 
   5966     while (!BCM_FAILURE(_field_group_get(unit, *group, &group_p))) {
   5967         (*group)++;
   5968         if ((soc_feature(unit, soc_feature_th3_style_fp)) &&
   5969             (_FP_ID_MAX == (*group))) {
   5970                 (*group) = _FP_ID_BASE;
   5971         }
   5972     }
   5973 
   5974     return (BCM_E_NONE);
   5975 }
   5976 
   5977 /*
   5978  * Function:
   5979  *     _bcm_field_entry_tcam_parts_count
   5980  * Purpose:
   5981  *     Get number of tcam entries needed to accomodate an entry.
   5982  * Parameters:
   5983  *     unit        - (IN)  BCM device number.
   5984  *     group_flags - (IN)  Entry group flags.
   5985  *     count       - (OUT) Entry parts count.
   5986  * Returns:
   5987  *     BCM_E_XXX
   5988  */
   5989 int
   5990 _bcm_field_entry_tcam_parts_count (int unit, _field_stage_id_t stage_id,
   5991                                    uint32 group_flags, int *part_count)
   5992 {
   5993     /* Input parameters check. */
   5994     if (NULL == part_count) {
   5995         return (BCM_E_PARAM);
   5996     }
   5997 
   5998 #if defined(BCM_TOMAHAWK_SUPPORT)
   5999     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
   6000         ((_BCM_FIELD_STAGE_INGRESS == stage_id) ||
   6001          (_BCM_FIELD_STAGE_EXACTMATCH == stage_id))) {
   6002        return _bcm_field_th_entry_tcam_parts_count(unit, group_flags,
   6003                                                    part_count);
   6004     }
   6005 #endif /* BCM_TOMAHAWK_SUPPORT */
   6006 
   6007     if (group_flags & _FP_GROUP_SPAN_SINGLE_SLICE) {
   6008         if ((group_flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) ||
   6009             (group_flags & _FP_GROUP_DW_DEPTH_EXPANDED)) {
   6010             *part_count = 2;
   6011         } else {
   6012             *part_count = 1;
   6013         }
   6014     } else if (group_flags & _FP_GROUP_SPAN_DOUBLE_SLICE) {
   6015         if (group_flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
   6016             *part_count = 4;
   6017         } else {
   6018             *part_count = 2;
   6019         }
   6020     } else if (group_flags & _FP_GROUP_SPAN_TRIPLE_SLICE) {
   6021         *part_count = 3;
   6022     }
   6023 
   6024     return BCM_E_NONE;
   6025 }
   6026 
   6027 /*
   6028  * Function:
   6029  *     _bcm_field_lt_entry_tcam_parts_count
   6030  * Purpose:
   6031  *     Get number of lt tcam entries needed to accomodate an entry.
   6032  * Parameters:
   6033  *     unit        - (IN)  BCM device number.
   6034  *     stage_id    - (IN)  Stage Id
   6035  *     group_flags - (IN)  Entry group flags.
   6036  *     count       - (OUT) Entry parts count.
   6037  * Returns:
   6038  *     BCM_E_XXX
   6039  */
   6040 int
   6041 _bcm_field_lt_entry_tcam_parts_count(int unit, _field_stage_id_t stage_id,
   6042                                      uint32 group_flags, int *part_count)
   6043 {
   6044     /* Input paramaters check */
   6045     if (NULL == part_count) {
   6046         return BCM_E_PARAM;
   6047     }
   6048 
   6049 #if defined(BCM_FLOWTRACKER_SUPPORT)
   6050     if (stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) {
   6051         return _bcm_field_th_lt_entry_tcam_parts_count(unit,
   6052                                 stage_id, group_flags, part_count);
   6053     } else
   6054 #endif
   6055     {
   6056         return _bcm_field_entry_tcam_parts_count(unit,
   6057                                 stage_id, group_flags, part_count);
   6058     }
   6059 }
   6060 
   6061 /*
   6062  * Function:
   6063  *     _field_entry_action_dirty
   6064  * Purpose:
   6065  *     Check if only action was modified for the entry after last installation
   6066  * Parameters:
   6067  *     unit        - (IN)  BCM device number.
   6068  *     f_ent       - (IN)  Primary entry pointer.
   6069  *     dirty       - (OUT) Entry dirty flag.
   6070  * Returns:
   6071  *     BCM_E_XXX
   6072  */
   6073 int
   6074 _field_entry_action_dirty(int unit, _field_entry_t *f_ent, int *dirty)
   6075 {
   6076     int parts_count = 0;               /* Entry tcam parts count.       */
   6077     int idx;                           /* Entry parts iterator.         */
   6078     int rv;                            /* Operation return status.      */
   6079 
   6080     /* Input parameters check. */
   6081     if ((NULL == f_ent) || (NULL == dirty)) {
   6082         return (BCM_E_PARAM);
   6083     }
   6084 
   6085     /* Get number of tcam parts based on group flags. */
   6086     rv = _bcm_field_entry_tcam_parts_count (unit, f_ent->group->stage_id,
   6087                                             f_ent->group->flags, &parts_count);
   6088     BCM_IF_ERROR_RETURN(rv);
   6089 
   6090     /* Check entry dirty and action only dirty for all parts of the entry */
   6091     for (idx = 0; idx < parts_count; idx++) {
   6092         LOG_DEBUG(BSL_LS_BCM_FP,
   6093                   (BSL_META_U(unit,
   6094                               "FP(unit %d) vverb: _field_entry_action_dirty() Part:%x EntryDirty:%x ActionOnlyDirty:%x\n"),
   6095                    unit, idx, (f_ent[idx].flags & (_FP_ENTRY_DIRTY)),
   6096                    (f_ent[idx].flags & (_FP_ENTRY_POLICY_TABLE_ONLY_DIRTY))));
   6097         /*
   6098          * If entry dirty is set and action only dirty is not set,
   6099          * it is likely a qualifier change, return FALSE.
   6100          */
   6101         if ((f_ent[idx].flags & _FP_ENTRY_DIRTY) &&
   6102             (0 == (f_ent[idx].flags & _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY))) {
   6103             *dirty = FALSE;
   6104             return (BCM_E_NONE);
   6105         }
   6106 
   6107         if ((f_ent[idx].flags & _FP_ENTRY_DIRTY) &&
   6108             (f_ent[idx].flags & _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY)) {
   6109             *dirty = TRUE;
   6110         }
   6111     }
   6112 
   6113     return (BCM_E_NONE);
   6114 }
   6115 
   6116 /*
   6117  * Function:
   6118  *     _field_entry_dirty
   6119  * Purpose:
   6120  *     Check if entry was modified after last installation
   6121  * Parameters:
   6122  *     unit        - (IN)  BCM device number.
   6123  *     f_ent       - (IN)  Primary entry pointer.
   6124  *     dirty       - (OUT) Entry dirty flag.
   6125  * Returns:
   6126  *     BCM_E_XXX
   6127  */
   6128 int
   6129 _field_entry_dirty(int unit, _field_entry_t *f_ent, int *dirty)
   6130 {
   6131     _field_entry_policer_t *f_ent_pl;  /* Field entry policer structure.*/
   6132     _field_policer_t *f_pl;            /* Field policer descriptor.     */
   6133     int parts_count = 0;               /* Entry tcam parts count.       */
   6134     int idx;                           /* Entry parts iterator.         */
   6135     int rv;                            /* Operation return status.      */
   6136 
   6137     /* Input parameters check. */
   6138     if ((NULL == f_ent) || (NULL == dirty)) {
   6139         return (BCM_E_PARAM);
   6140     }
   6141 
   6142     /* Get number of tcam parts based on group flags. */
   6143     rv = _bcm_field_entry_tcam_parts_count (unit, f_ent->group->stage_id,
   6144                                             f_ent->group->flags, &parts_count);
   6145     BCM_IF_ERROR_RETURN(rv);
   6146 
   6147     /* If any entry part was changed - reinstall is required. */
   6148     for (idx = 0; idx < parts_count; idx++) {
   6149          if (f_ent[idx].flags & _FP_ENTRY_DIRTY) {
   6150             break;
   6151         }
   6152     }
   6153     *dirty = (idx < parts_count) ? TRUE : FALSE;
   6154 
   6155     if (0 == (*dirty)) {
   6156         /* Policer configuration updates check. */
   6157         for (idx = 0; idx < _FP_POLICER_LEVEL_COUNT; idx++) {
   6158             f_ent_pl = f_ent->policer + idx;
   6159             /* Skip invalid policers. */
   6160             if (0 == (f_ent_pl->flags & _FP_POLICER_VALID)) {
   6161                 continue;
   6162             }
   6163             /* Read policer configuration.*/
   6164             rv = _bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl);
   6165             BCM_IF_ERROR_RETURN(rv);
   6166 
   6167             /* Check if policer was modified. */
   6168             if (f_pl->hw_flags & _FP_POLICER_DIRTY) {
   6169                 *dirty = TRUE;
   6170                 break;
   6171             }
   6172         }
   6173     }
   6174     return (BCM_E_NONE);
   6175 }
   6176 
   6177 /*
   6178  * Function:
   6179  *     _bcm_field_entry_flags_to_tcam_part
   6180  * Purpose:
   6181  *     Each field entry contains up to 4 TCAM
   6182  *     entries. This routine maps sw entry flags
   6183  *     to tcam entry (0-3).
   6184  *     Note this is not a physical address in tcam.
   6185  *     Single: 0
   6186  *     Single & Intraslice Double: 0, 1
   6187  *     Paired: 0, 1
   6188  *     Paired & Intraslice Double: 0, 1, 2, 3
   6189  *     Triple: 0, 1, 2
   6190  * Parameters:
   6191  *     unit        - (IN)  Device number.
   6192  *     entry_flags - (IN)  Entry flags.
   6193  *     fg          - (IN)  Entry group structure.
   6194  *     entry_part  - (OUT) Entry part (0-3)
   6195  * Returns:
   6196  *     BCM_E_NONE  - Success
   6197  *     BCM_E_INTERNAL - Error
   6198  */
   6199 int
   6200 _bcm_field_entry_flags_to_tcam_part (int unit, uint32 entry_flags,
   6201                                      _field_group_t *fg,
   6202                                      uint8 *entry_part)
   6203 {
   6204     /* Input parameters check. */
   6205     if (NULL == entry_part || NULL == fg) {
   6206         return (BCM_E_PARAM);
   6207     }
   6208 #if defined(BCM_TOMAHAWK_SUPPORT)
   6209     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
   6210         (_BCM_FIELD_STAGE_INGRESS == fg->stage_id)) {
   6211        return _bcm_field_th_entry_flags_to_tcam_part(unit, entry_flags,
   6212                                                      fg->flags,
   6213                                                      entry_part);
   6214     }
   6215 #endif /* BCM_TOMAHAWK_SUPPORT */
   6216     if (entry_flags & _FP_ENTRY_PRIMARY) {
   6217         if (entry_flags & _FP_ENTRY_SECOND_HALF) {
   6218             *entry_part = 1;
   6219         } else {
   6220             *entry_part = 0;
   6221         }
   6222     } else if (entry_flags & _FP_ENTRY_SECONDARY) {
   6223         if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
   6224             if (entry_flags & _FP_ENTRY_SECOND_HALF) {
   6225                 *entry_part = 3;
   6226             } else {
   6227                 *entry_part = 2;
   6228             }
   6229         } else {
   6230             *entry_part= 1;
   6231         }
   6232     } else if (entry_flags & _FP_ENTRY_TERTIARY) {
   6233         *entry_part = 2;
   6234     } else {
   6235         return (BCM_E_INTERNAL);
   6236     }
   6237     return BCM_E_NONE;
   6238 }
   6239 
   6240 /*
   6241  * Function:
   6242  *     _bcm_field_tcam_part_to_entry_flags
   6243  * Purpose:
   6244  *     Each field entry contains up to 4 TCAM
   6245  *     entries. This routine maps tcam entry (0-3)
   6246  *     to SW entry flags.
   6247  *     Single: 0
   6248  *     Single & Intraslice Double: 0, 1
   6249  *     Paired: 0, 1
   6250  *     Paired & Intraslice Double: 0, 1, 2, 3
   6251  *     Triple: 0, 1, 2
   6252  *     Retrieve the part of the group entry resides in.
   6253  * Parameters:
   6254  *     unit        - (IN)  Device number.
   6255  *     entry_part  - (IN)  Entry Part number.
   6256  *     fg          - (IN)  Group Structure.
   6257  *     entry_flags - (OUT) Entry Flags.
   6258  * Returns:
   6259  *     BCM_E_NONE  - Success
   6260  *     BCM_E_INTERNAL - Error
   6261  */
   6262 int
   6263 _bcm_field_tcam_part_to_entry_flags(int unit, int entry_part,
   6264                                     _field_group_t *fg,
   6265                                     uint32 *entry_flags)
   6266 {
   6267     /* Input parameters check. */
   6268     if (NULL == entry_flags || NULL == fg) {
   6269         return (BCM_E_PARAM);
   6270     }
   6271 
   6272 #if defined(BCM_TOMAHAWK_SUPPORT)
   6273     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
   6274         ((_BCM_FIELD_STAGE_INGRESS == fg->stage_id) ||
   6275          (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id))) {
   6276        return _bcm_field_th_tcam_part_to_entry_flags(unit, entry_part,
   6277                                                      fg->flags,
   6278                                                      entry_flags);
   6279     }
   6280 #endif /* BCM_TOMAHAWK_SUPPORT */
   6281 
   6282     switch (entry_part) {
   6283       case 0:
   6284           *entry_flags = _FP_ENTRY_PRIMARY |
   6285                          _FP_ENTRY_MODIFY_SLICE_SW_ENTRY_COUNT;
   6286           break;
   6287       case 1:
   6288           if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
   6289               *entry_flags = _FP_ENTRY_PRIMARY |
   6290                               _FP_ENTRY_SECOND_HALF;
   6291           } else if (fg->flags & _FP_GROUP_DW_DEPTH_EXPANDED) {
   6292               *entry_flags = _FP_ENTRY_PRIMARY |
   6293                              _FP_ENTRY_SECOND_HALF |
   6294                              _FP_ENTRY_MODIFY_SLICE_SW_ENTRY_COUNT;
   6295           } else {
   6296               *entry_flags = _FP_ENTRY_SECONDARY;
   6297           }
   6298           break;
   6299       case 2:
   6300           if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
   6301               *entry_flags = _FP_ENTRY_SECONDARY |
   6302                              _FP_ENTRY_MODIFY_SLICE_SW_ENTRY_COUNT;
   6303           } else {
   6304               *entry_flags = _FP_ENTRY_TERTIARY |
   6305                              _FP_ENTRY_MODIFY_SLICE_SW_ENTRY_COUNT;
   6306           }
   6307           break;
   6308       case 3:
   6309           *entry_flags = _FP_ENTRY_SECONDARY | _FP_ENTRY_SECOND_HALF;
   6310           break;
   6311       default:
   6312           return (BCM_E_INTERNAL);
   6313     }
   6314     return (BCM_E_NONE);
   6315 }
   6316 
   6317 
   6318 /*
   6319  * Function:
   6320  *     _bcm_field_tcam_part_to_slice_number
   6321  * Purpose:
   6322  *     Each field entry contains up to 4 TCAM
   6323  *     entries. This routine maps tcam entry (0-3)
   6324  *     to a slice number
   6325  * Parameters:
   6326  *     unit         - (IN)  Unit
   6327  *     entry_part   - (IN)  Entry Part number.
   6328  *     fg           - (IN)  Field Group Structure.
   6329  *     slice_number - (OUT) Slice number (0-2)
   6330  * Returns:
   6331  *     BCM_E_XXX
   6332  */
   6333 int
   6334 _bcm_field_tcam_part_to_slice_number(int unit,
   6335                                      int entry_part,
   6336                                      _field_group_t *fg,
   6337                                      uint8 *slice_number)
   6338 {
   6339     /* Input parameters check. */
   6340     if (NULL == slice_number || NULL == fg) {
   6341         return (BCM_E_PARAM);
   6342     }
   6343 
   6344 #if defined(BCM_TOMAHAWK_SUPPORT)
   6345     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
   6346         (_BCM_FIELD_STAGE_INGRESS == fg->stage_id)) {
   6347        return _bcm_field_th_tcam_part_to_slice_number(entry_part, fg->flags,
   6348                                                       slice_number);
   6349     }
   6350 #endif /* BCM_TOMAHAWK_SUPPORT */
   6351 
   6352     switch (entry_part) {
   6353       case 0:
   6354           *slice_number = 0;
   6355           break;
   6356       case 1:
   6357           if ((fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) ||
   6358               (fg->flags & _FP_GROUP_DW_DEPTH_EXPANDED)) {
   6359               *slice_number = 0;
   6360           } else {
   6361               *slice_number = 1;
   6362           }
   6363           break;
   6364       case 2:
   6365           if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
   6366               *slice_number = 1;
   6367           } else {
   6368               *slice_number = 2;
   6369           }
   6370           break;
   6371       case 3:
   6372           *slice_number = 1;
   6373           break;
   6374       default:
   6375           return (BCM_E_INTERNAL);
   6376     }
   6377     return (BCM_E_NONE);
   6378 }
   6379 
   6380 /*
   6381  * Function:
   6382  *     _field_entry_slice_idx_change
   6383  * Purpose:
   6384  *     Move the software entry to a new slice index.
   6385  * Parmeters:
   6386  *     unit    - (IN) BCM device number.
   6387  *     f_ent   - (IN/OUT) Field entry to be moved.
   6388  *     amount  - (IN) Number of indexes to move + or -.
   6389  * Returns:
   6390  *     BCM_E_XXX
   6391  */
   6392 STATIC int
   6393 _field_entry_slice_idx_change(int unit, _field_entry_t *f_ent,
   6394                               int parts_count, int *tcam_idx_new)
   6395 {
   6396     _field_slice_t *fs;          /* Field slice control structure. */
   6397     _field_stage_t *stage_fc;    /* Stage field control structure. */
   6398     int new_slice_numb = 0;      /* Entry new slice number.        */
   6399     int new_slice_idx = 0;       /* Entry new offset in the slice  */
   6400     int instance;                /* Pipe Instance.                 */
   6401     int idx;                     /* Iteration index.               */
   6402     int rv;                      /* Operation return status.       */
   6403 
   6404     /* Input parameters check. */
   6405     if (NULL == f_ent) {
   6406         return (BCM_E_PARAM);
   6407     }
   6408 
   6409     if ((NULL == f_ent->group) || (NULL == f_ent->fs)) {
   6410         return (BCM_E_PARAM);
   6411     }
   6412 
   6413     /*  Get stage control structure. */
   6414     rv = _field_stage_control_get(unit, f_ent->group->stage_id, &stage_fc);
   6415     BCM_IF_ERROR_RETURN(rv);
   6416 
   6417     /* Retrieve instance */
   6418     instance = f_ent->group->instance;
   6419 
   6420     for (idx = 0; idx < parts_count; idx++) {
   6421         /* Get slice control structure. */
   6422         fs = f_ent[idx].fs;
   6423 
   6424         /* Move the software entry to the new index. */
   6425         if (prio_set_with_no_free_entries[unit] == FALSE) {
   6426             fs->entries[f_ent[idx].slice_idx] = NULL;
   6427         }
   6428 
   6429 #if defined(BCM_TOMAHAWK_SUPPORT)
   6430         if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
   6431                  (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id)) {
   6432             rv = _bcm_field_th_tcam_idx_to_slice_offset(unit, stage_fc,
   6433                                                         f_ent,
   6434                                                         tcam_idx_new[idx],
   6435                                                         &new_slice_numb,
   6436                                                         &new_slice_idx);
   6437         } else
   6438 #endif /* BCM_TOMAHAWK_SUPPORT */
   6439         {
   6440            /* Calculate entry new slice & offset in the slice. */
   6441            rv = _bcm_field_tcam_idx_to_slice_offset (unit, stage_fc,
   6442                                                   instance,
   6443                                                   tcam_idx_new[idx],
   6444                                                   &new_slice_numb,
   6445                                                   &new_slice_idx);
   6446         }
   6447         BCM_IF_ERROR_RETURN(rv);
   6448 
   6449         /* If entry moves across the slices update free/used counters. */
   6450         if ((f_ent[idx].fs->slice_number != new_slice_numb) &&
   6451             (0 == (f_ent[idx].flags & _FP_ENTRY_SECOND_HALF))) {
   6452             fs->free_count++;
   6453             stage_fc->slices[instance][new_slice_numb].free_count--;
   6454         }
   6455 
   6456         /* Update entry structure. */
   6457         stage_fc->slices[instance][new_slice_numb].entries[new_slice_idx]
   6458             = f_ent + idx;
   6459         f_ent[idx].fs = &stage_fc->slices[instance][new_slice_numb];
   6460         f_ent[idx].slice_idx = new_slice_idx;
   6461     }
   6462 
   6463     return (BCM_E_NONE);
   6464 }
   6465 
   6466 /*
   6467  * Function:
   6468  *      _field_entry_t_compare
   6469  * Purpose:
   6470  *      Compare entry id in _field_entry_t structure.
   6471  * Parameters:
   6472  *      b - (IN) first compared qualifier.
   6473  *      a - (IN) second compared qualifier.
   6474  * Returns:
   6475  *      a<=>b
   6476  */
   6477 static INLINE int
   6478 _field_entry_t_compare(void *a, void *b)
   6479 {
   6480     _field_entry_t **first;     /* First compared entry.  */
   6481     _field_entry_t **second;    /* Second compared entry. */
   6482 
   6483     first = (_field_entry_t **)a;
   6484     second = (_field_entry_t **)b;
   6485 
   6486     if ((*first)->eid < (*second)->eid) {
   6487         return (-1);
   6488     } else if ((*first)->eid > (*second)->eid) {
   6489         return (1);
   6490     }
   6491     return (0);
   6492 }
   6493 
   6494 /*
   6495  * Function:
   6496  *     _field_entry_get
   6497  * Purpose:
   6498  *     Lookup a FP rule(entry) from a unit ID and slice & rule id choice.
   6499  * Parmeters:
   6500  *     unit    - (IN)BCM device number.
   6501  *     eid     - (IN)Entry id.
   6502  *     flags   - (IN)Entry flags to match.
   6503  *     entry_p - (OUT) Entry lookup result.
   6504  * Returns:
   6505  *     BCM_E_XXX
   6506  */
   6507 int
   6508 _field_entry_get(int unit, bcm_field_entry_t eid, uint32 flags,
   6509                   _field_entry_t **entry_p)
   6510 {
   6511     _field_entry_t   target;  /* Entry lookup pointer.    */
   6512     _field_entry_t   *f_ent;  /* Entry lookup pointer.    */
   6513     _field_control_t *fc;     /* Field control structure. */
   6514     _field_group_t   *fg;     /* Field group iterator.    */
   6515     uint8  entry_part = 0;    /* Wide entry part number.  */
   6516     int    idx;               /* Entry index.             */
   6517 
   6518     /* Input parameters check. */
   6519     if (NULL == entry_p) {
   6520         return (BCM_E_PARAM);
   6521     }
   6522 
   6523     /* Reset target entry */
   6524     target.eid = eid;
   6525     f_ent = &target;
   6526 
   6527     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   6528 
   6529     fg = fc->groups;
   6530     while (NULL != fg)  {
   6531         /* Skip empty groups. */
   6532         if (NULL == fg->entry_arr) {
   6533             fg = fg->next;
   6534             continue;
   6535         }
   6536         idx = _shr_bsearch(fg->entry_arr, fg->group_status.entry_count,
   6537                            sizeof(_field_entry_t *), (void *)&f_ent,
   6538                            _field_entry_t_compare);
   6539         if (idx >= 0) {
   6540             (void)_bcm_field_entry_flags_to_tcam_part(unit, flags,
   6541                                                       fg,
   6542                                                       &entry_part);
   6543             *entry_p = fg->entry_arr[idx] + entry_part;
   6544             return (BCM_E_NONE);
   6545         }
   6546         fg = fg->next;
   6547     }
   6548     /* Rule with id == eid not found. */
   6549     return (BCM_E_NOT_FOUND);
   6550 }
   6551 
   6552 /*
   6553  * Function:
   6554  *     _field_group_entry_add
   6555  * Purpose:
   6556  *     Insert an entry to field group entry array.
   6557  * Parmeters:
   6558  *     unit    - (IN)BCM device number.
   6559  *     fg      - (IN)Field group structure.
   6560  *     f_ent   - (IN)Inserted entry structure.
   6561  * Returns:
   6562  *     BCM_E_XXX
   6563  */
   6564 int
   6565 _field_group_entry_add (int unit, _field_group_t *fg,
   6566                         _field_entry_t *f_ent)
   6567 {
   6568     _field_entry_t **f_ent_arr;   /* Field group entry array.*/
   6569     int mem_sz;                   /* Memory size.            */
   6570     int idx;                      /* Entry insertion index.  */
   6571     int tmp;                      /* Temporary iterator.     */
   6572 
   6573     /* Input parameters check */
   6574     if ((NULL == fg) || (NULL == f_ent)) {
   6575         return (BCM_E_PARAM);
   6576     }
   6577 
   6578     /* Verify if entry already present in the group . */
   6579     if (NULL != fg->entry_arr) {
   6580         idx = _shr_bsearch(fg->entry_arr, fg->group_status.entry_count,
   6581                            sizeof (_field_entry_t *), &f_ent,
   6582                            _field_entry_t_compare);
   6583         /* Entry already IN. */
   6584         if (idx >= 0) {
   6585             return (BCM_E_NONE);
   6586         }
   6587     } else {
   6588         idx = -1;  /* Insert into 0 location. */
   6589     }
   6590 
   6591     /* Check if group has enough room for new entry */
   6592     if (fg->group_status.entry_count + 1 >
   6593         fg->ent_block_count * _FP_GROUP_ENTRY_ARR_BLOCK) {
   6594 
   6595         mem_sz = _FP_GROUP_ENTRY_ARR_BLOCK * (fg->ent_block_count + 1) *
   6596             sizeof(_field_entry_t *);
   6597 
   6598         f_ent_arr = NULL;
   6599 
   6600         _FP_XGS3_ALLOC(f_ent_arr, mem_sz, "field group entries array");
   6601         if (NULL == f_ent_arr) {
   6602             return (BCM_E_MEMORY);
   6603         }
   6604         /* Copy original array to newly allocated one. */
   6605         if (NULL != fg->entry_arr) {
   6606             mem_sz = _FP_GROUP_ENTRY_ARR_BLOCK * (fg->ent_block_count) *
   6607                 sizeof(_field_entry_t *);
   6608             sal_memcpy(f_ent_arr, fg->entry_arr, mem_sz);
   6609 
   6610             sal_free (fg->entry_arr);
   6611         }
   6612         fg->entry_arr = f_ent_arr;
   6613         fg->ent_block_count++;
   6614     }
   6615     /* Make room for inserted entry */
   6616     idx = (((-1) * idx) - 1);
   6617     tmp = fg->group_status.entry_count - 1;
   6618     while (tmp >= idx) {
   6619     /*    coverity[var_deref_op : FALSE]    */
   6620         fg->entry_arr[tmp + 1] = fg->entry_arr[tmp];
   6621         tmp--;
   6622     }
   6623     fg->entry_arr[idx] = f_ent;
   6624     fg->group_status.entry_count++;
   6625     return (BCM_E_NONE);
   6626 }
   6627 
   6628 
   6629 /*
   6630  * Function:
   6631  *     _field_group_entry_delete
   6632  * Purpose:
   6633  *     Remove an entry from field group entry array.
   6634  * Parmeters:
   6635  *     unit    - (IN)BCM device number.
   6636  *     fg      - (IN)Field group structure.
   6637  *     f_ent   - (IN)Removed entry structure.
   6638  * Returns:
   6639  *     BCM_E_XXX
   6640  */
   6641 int
   6642 _field_group_entry_delete(int unit, _field_group_t *fg,
   6643                         _field_entry_t *f_ent)
   6644 {
   6645     int idx;                      /* Entry insertion index.  */
   6646     int tmp;                      /* Temporary iterator.     */
   6647 
   6648     /* Input parameters check */
   6649     if ((NULL == fg) || (NULL == f_ent)) {
   6650         return (BCM_E_PARAM);
   6651     }
   6652 
   6653     /* Make sure group entry array was not deallocated. */
   6654     if (NULL == fg->entry_arr) {
   6655         return (BCM_E_INTERNAL);
   6656     }
   6657 
   6658     /* Verify if entry already present in the group . */
   6659     idx = _shr_bsearch(fg->entry_arr, fg->group_status.entry_count,
   6660                        sizeof (_field_entry_t *), &f_ent,
   6661                        _field_entry_t_compare);
   6662     if (idx < 0) {
   6663         return (BCM_E_NOT_FOUND);
   6664     }
   6665 
   6666     /* Make room for inserted entry */
   6667     tmp = idx;
   6668     while (tmp < fg->group_status.entry_count - 1) {
   6669         fg->entry_arr[tmp] = fg->entry_arr[tmp + 1];
   6670         tmp++;
   6671     }
   6672     fg->group_status.entry_count--;
   6673     fg->entry_arr[fg->group_status.entry_count] = NULL;
   6674     return (BCM_E_NONE);
   6675 }
   6676 
   6677 /*
   6678  * Function:
   6679  *     _bcm_field_entry_get_by_id
   6680  * Purpose:
   6681  *     Lookup a complete FP rule(entry) from a unit & rule id choice.
   6682  * Parmeters:
   6683  *     unit      - (IN)BCM device number.
   6684  *     eid       - (IN)Entry id.
   6685  *     entry_arr - (OUT) Entry lookup result array. (Array of pointers to
   6686  *                       primary/secondary/teriary ... parts of entry.
   6687  * Returns:
   6688  *     BCM_E_XXX
   6689  */
   6690 int
   6691 _bcm_field_entry_get_by_id(int unit, bcm_field_entry_t eid,
   6692                        _field_entry_t **entry_arr)
   6693 {
   6694     int    rv;     /* Operation return status. */
   6695 
   6696     /* Input parameters check. */
   6697     if (NULL == entry_arr) {
   6698         return (BCM_E_PARAM);
   6699     }
   6700 
   6701     /* Initialize entry array. */
   6702     *entry_arr = NULL;
   6703 
   6704     /* Extract primary entry. */
   6705     rv = _field_entry_get(unit, eid, _FP_ENTRY_PRIMARY, entry_arr);
   6706 
   6707     return (rv);
   6708 }
   6709 
   6710 /*
   6711  * Function:
   6712  *     _bcm_field_entry_qual_get
   6713  *
   6714  * Purpose:
   6715  *     Lookup a _field_entry_t from a unit ID taking into account mode. Since
   6716  *     double and triple-wide modes can have multiple physical entries with the
   6717  *     same Entry ID,
   6718  *
   6719  * Parmeters:
   6720  *     unit    - (IN)BCM device number.
   6721  *     eid     - (IN)Entry id.
   6722  *     qual    - (IN)Qualifier used to select the correct slice
   6723  *     entry_p - (OUT)Lookup result entry.
   6724  *
   6725  * Returns:
   6726  *     BCM_E_XXX
   6727  */
   6728 int
   6729 _bcm_field_entry_qual_get(int unit, bcm_field_entry_t entry,
   6730                           int qual, _field_entry_t **entry_p)
   6731 {
   6732     _bcm_field_group_qual_t *q_arr;  /* Qualifiers array.               */
   6733     int             parts_count = 0; /* Number of entry parts.          */
   6734     uint8                     entry_type;  /* Index to tcam entries of
   6735                                               multiple types            */
   6736     int             part_idx;        /* Entry parts iteration index.    */
   6737     int             qual_idx;        /* Part qualifiers iteration index.*/
   6738     uint8           found;           /* Entry lookup flags.             */
   6739     _field_group_t  *fg;             /* FP group info structure.        */
   6740     int             rv;              /* Operation return status.        */
   6741 
   6742     LOG_DEBUG(BSL_LS_BCM_FP,
   6743               (BSL_META_U(unit,
   6744                           "_bcm_field_entry_qual_get\n")));
   6745 
   6746     /* Input parameters check. */
   6747     if (NULL == entry_p) {
   6748         return (BCM_E_PARAM);
   6749     }
   6750 
   6751     /* Initialization. */
   6752     found = FALSE;
   6753 
   6754     /* Search the entry by eid. */
   6755     rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, entry_p);
   6756     BCM_IF_ERROR_RETURN(rv);
   6757 
   6758     fg = (*entry_p)->group;
   6759     if (NULL == fg) {
   6760         return (BCM_E_INTERNAL);
   6761     }
   6762 
   6763     /* If it's an external slice, then the qualifier has to be in the primary
   6764      * entry, since that's the only entry it has. */
   6765     if (fg->stage_id == _BCM_FIELD_STAGE_EXTERNAL) {
   6766         return (BCM_E_NONE);
   6767     }
   6768 
   6769 #if defined(BCM_TOMAHAWK_SUPPORT)
   6770     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
   6771             (_BCM_FIELD_STAGE_CLASS == fg->stage_id)) {
   6772         return (BCM_E_NONE);
   6773     }
   6774 #endif /* BCM_TOMAHAWK_SUPPORT */
   6775 
   6776     /* Get number of entry parts we have to read. */
   6777     rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
   6778                                             fg->flags, &parts_count);
   6779     BCM_IF_ERROR_RETURN(rv);
   6780 
   6781     entry_type = _FP_ENTRY_TYPE_DEFAULT;
   6782 
   6783     /* Iterate over all entry parts. */
   6784     for (part_idx = 0; part_idx < parts_count; part_idx++) {
   6785         /* Get part qualifiers array. */
   6786         q_arr = &(fg->qual_arr[entry_type][part_idx]);
   6787         /* Search array by qualifier id. */
   6788         for (qual_idx = 0; qual_idx < q_arr->size; qual_idx++) {
   6789             if ((uint16)qual == q_arr->qid_arr[qual_idx]) {
   6790                 found = TRUE;
   6791                 break;
   6792             }
   6793         }
   6794         if (found) {
   6795             break;
   6796         }
   6797     }
   6798 
   6799     /* Check lookup status. */
   6800     if (FALSE == found) {
   6801         return (BCM_E_NOT_FOUND);
   6802     }
   6803 
   6804     *entry_p += part_idx;
   6805     return (BCM_E_NONE);
   6806 }
   6807 
   6808 #if defined(BCM_TRIDENT2_SUPPORT)
   6809 /*
   6810  * Function:
   6811  *     _bcm_field_efp_entry_qual_get
   6812  *
   6813  * Purpose:
   6814  *     Lookup a _field_entry_t from a unit ID taking into account mode. Since
   6815  *     double and triple-wide modes can have multiple physical entries with the
   6816  *     same Entry ID,
   6817  *
   6818  * Parmeters:
   6819  *     unit    - (IN)BCM device number.
   6820  *     eid     - (IN)Entry id.
   6821  *     qual    - (IN)Qualifier used to select the correct slice
   6822  *     entry_p - (OUT)Lookup result entry.
   6823  *
   6824  * Returns:
   6825  *     BCM_E_XXX
   6826  */
   6827 int
   6828 _bcm_field_efp_entry_qual_get(int unit, bcm_field_entry_t entry,
   6829                           int qual, _field_entry_t **entry_p)
   6830 {
   6831     _bcm_field_group_qual_t *q_arr;  /* Qualifiers array.               */
   6832     int             parts_count = 0; /* Number of entry parts.          */
   6833     uint8                     entry_type;  /* Index to tcam entries of
   6834                                               multiple types            */
   6835     int             part_idx;        /* Entry parts iteration index.    */
   6836     int             qual_idx;        /* Part qualifiers iteration index.*/
   6837     uint8           found;           /* Entry lookup flags.             */
   6838     _field_group_t  *fg;             /* FP group info structure.        */
   6839     int             rv;              /* Operation return status.        */
   6840 
   6841     LOG_DEBUG(BSL_LS_BCM_FP,
   6842               (BSL_META_U(unit,
   6843                           "_bcm_field_efp_entry_qual_get\n")));
   6844 
   6845     /* Input parameters check. */
   6846     if (NULL == entry_p) {
   6847         return (BCM_E_PARAM);
   6848     }
   6849 
   6850     /* Initialization. */
   6851     found = FALSE;
   6852 
   6853     /* Search the entry by eid. */
   6854     rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, entry_p);
   6855     BCM_IF_ERROR_RETURN(rv);
   6856 
   6857     fg = (*entry_p)->group;
   6858     if (NULL == fg) {
   6859         return (BCM_E_INTERNAL);
   6860     }
   6861 
   6862     if (!(SOC_IS_TD2_TT2(unit) &&
   6863             (_BCM_FIELD_STAGE_EGRESS == fg->stage_id))) {
   6864         return (BCM_E_INTERNAL);
   6865     }
   6866 
   6867     /* Get number of entry parts we have to read. */
   6868     rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
   6869                                             fg->flags, &parts_count);
   6870     BCM_IF_ERROR_RETURN(rv);
   6871 
   6872     if ((*entry_p)->efp_key_match_type) {
   6873         entry_type = _FP_ENTRY_TYPE_1;
   6874     } else {
   6875         entry_type = _FP_ENTRY_TYPE_0;
   6876     }
   6877 
   6878     /* Iterate over all entry parts. */
   6879     for (part_idx = 0; part_idx < parts_count; part_idx++) {
   6880         /* Get part qualifiers array. */
   6881         q_arr = &(fg->qual_arr[entry_type][part_idx]);
   6882         /* Search array by qualifier id. */
   6883         for (qual_idx = 0; qual_idx < q_arr->size; qual_idx++) {
   6884             if ((uint16)qual == q_arr->qid_arr[qual_idx]) {
   6885                 found = TRUE;
   6886                 break;
   6887             }
   6888         }
   6889         if (found) {
   6890             break;
   6891         }
   6892     }
   6893 
   6894     /* Check lookup status. */
   6895     if (FALSE == found) {
   6896         return (BCM_E_NOT_FOUND);
   6897     }
   6898 
   6899     *entry_p += part_idx;
   6900     return (BCM_E_NONE);
   6901 }
   6902 #endif
   6903 
   6904 /*
   6905  * Function:
   6906  *     _bcm_field_policer_get
   6907  * Purpose:
   6908  *     Lookup a Policer description structure by policer id.
   6909  * Parmeters:
   6910  *     unit      - (IN)BCM device number.
   6911  *     pid       - (IN)Policer id.
   6912  *     policer_p - (OUT) Policer lookup result.
   6913  * Returns:
   6914  *     BCM_E_XXX
   6915  */
   6916 int
   6917 _bcm_field_policer_get(int unit, bcm_policer_t pid,
   6918                        _field_policer_t **policer_p)
   6919 {
   6920     _field_policer_t *f_pl; /* Policer lookup pointer.  */
   6921     _field_control_t *fc;   /* Field control structure. */
   6922     uint32 hash_index;      /* Entry hash.              */
   6923 
   6924     /* Input parameters check. */
   6925     if (NULL == policer_p) {
   6926         return (BCM_E_PARAM);
   6927     }
   6928 
   6929     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   6930 
   6931     hash_index = pid & _FP_HASH_INDEX_MASK(fc);
   6932     f_pl  =  fc->policer_hash[hash_index];
   6933     while (NULL != f_pl) {
   6934         /* Match entry id. */
   6935         if (f_pl->pid == pid) {
   6936             *policer_p = f_pl;
   6937             return (BCM_E_NONE);
   6938         }
   6939         f_pl = f_pl->next;
   6940     }
   6941 
   6942     /* Policer with pid == pid was not found. */
   6943     return (BCM_E_NOT_FOUND);
   6944 }
   6945 
   6946 /*
   6947  * Function:
   6948  *      _field_policer_destroy2
   6949  * Purpose:
   6950  *      Deinitialize a policer entry.
   6951  * Parameters:
   6952  *      unit    - (IN) Unit number.
   6953  *      fc      - (IN) Field control structure.
   6954  *      f_pl    - (IN) Internal policer descriptor.
   6955  * Returns:
   6956  *      BCM_E_XXX
   6957  * Notes:
   6958  */
   6959 int
   6960 _field_policer_destroy2(int unit, _field_control_t *fc,
   6961                         _field_policer_t *f_pl)
   6962 {
   6963     /* Input parameters check. */
   6964     if ((NULL == fc) || (NULL == f_pl)) {
   6965         return (BCM_E_PARAM);
   6966     }
   6967 
   6968     /* Reject destroy if policer is in use. */
   6969     if (f_pl->sw_ref_count > 1) {
   6970         return (BCM_E_BUSY);
   6971     }
   6972 
   6973     /* Remove policer for lookup hash. */
   6974     _FP_HASH_REMOVE(fc->policer_hash, _field_policer_t, f_pl,
   6975                     (f_pl->pid & _FP_HASH_INDEX_MASK(fc)));
   6976 
   6977 
   6978     /* De-allocate policer descriptor. */
   6979     sal_free(f_pl);
   6980 
   6981     /* Decrement number of active policers. */
   6982     if (fc->policer_count > 0) {
   6983         fc->policer_count--;
   6984     }
   6985     return (BCM_E_NONE);
   6986 }
   6987 
   6988 /*
   6989  * Function:
   6990  *      _field_policer_destroy
   6991  * Purpose:
   6992  *      Deinitialize a policer entry.
   6993  * Parameters:
   6994  *      unit    - (IN) Unit number.
   6995  *      pid     - (IN) Policer id.
   6996  * Returns:
   6997  *      BCM_E_XXX
   6998  * Notes:
   6999  */
   7000 int
   7001 _field_policer_destroy(int unit, bcm_policer_t pid)
   7002 {
   7003     _field_control_t    *fc;               /* Field control structure.     */
   7004     _field_policer_t    *f_pl;             /* Internal policer descriptor. */
   7005     int                 rv;                /* Operation return status.     */
   7006 
   7007     /* Get field control structure. */
   7008     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   7009 
   7010     /* Find policer info. */
   7011     rv = _bcm_field_policer_get(unit, pid, &f_pl);
   7012     if (BCM_FAILURE(rv)) {
   7013         return (rv);
   7014     }
   7015 
   7016     return _field_policer_destroy2(unit, fc, f_pl);
   7017 }
   7018 
   7019 /*
   7020  * Function:
   7021  *      _field_policer_hw_flags_set
   7022  * Purpose:
   7023  *      Update policer installation is required flag.
   7024  * Parameters:
   7025  *      unit    - (IN) Unit number.
   7026  *      f_pl    - (IN/OUT) Internal policer descriptor.
   7027  *      flags   - (IN) Internal flags.
   7028  * Returns:
   7029  *      BCM_E_XXX
   7030  * Notes:
   7031  */
   7032 int
   7033 _field_policer_hw_flags_set(int unit, _field_policer_t *f_pl, uint32 flags)
   7034 {
   7035     /* Input parameters check. */
   7036     if (NULL == f_pl) {
   7037         return (BCM_E_PARAM);
   7038     }
   7039 
   7040     f_pl->hw_flags |= flags;
   7041 
   7042     switch (f_pl->cfg.mode) {
   7043         case bcmPolicerModeSrTcm:
   7044         case bcmPolicerModeTrTcm:
   7045         case bcmPolicerModeTrTcmDs:
   7046         case bcmPolicerModeCoupledTrTcmDs:
   7047         case bcmPolicerModeSrTcmModified:
   7048         case bcmPolicerModeSrTcmTsn:
   7049         case bcmPolicerModeCommitted:
   7050             f_pl->hw_flags |= _FP_POLICER_DIRTY;
   7051             break;
   7052         default:
   7053             return (BCM_E_UNAVAIL);
   7054     }
   7055     return (BCM_E_NONE);
   7056 }
   7057 
   7058 /*
   7059  * Function:
   7060  *      _field_policer_id_alloc
   7061  * Purpose:
   7062  *      Allocate a policer id.
   7063  * Parameters:
   7064  *      unit    - (IN) BCM device number.
   7065  *      pid     - (OUT) Policer id.
   7066  * Returns:
   7067  *      BCM_E_XXX
   7068  * Notes:
   7069  */
   7070 int
   7071 _field_policer_id_alloc(int unit, bcm_policer_t *pid)
   7072 {
   7073     int               max_count;           /* Maximum number of pid to try.*/
   7074     _field_policer_t  *f_pl;               /* Field policer descriptor.    */
   7075     int               rv;                  /* Operation return status.     */
   7076     static uint32  last_allocated_pid = 0; /* Policer id alloc tracker.    */
   7077 
   7078     /* Input parameters check. */
   7079     if (NULL == pid) {
   7080         return (BCM_E_PARAM);
   7081     }
   7082 
   7083     max_count = _FP_ID_MAX;
   7084     while (max_count--) {
   7085         last_allocated_pid++;
   7086         if (_FP_ID_MAX == last_allocated_pid) {
   7087             last_allocated_pid = _FP_ID_BASE;
   7088         }
   7089         rv = _bcm_field_policer_get(unit, last_allocated_pid, &f_pl);
   7090         if (BCM_E_NOT_FOUND == rv) {
   7091             *pid = last_allocated_pid;
   7092             return (BCM_E_NONE);
   7093         }
   7094         if (BCM_FAILURE(rv)) {
   7095             return (rv);
   7096         }
   7097     }
   7098     return (BCM_E_RESOURCE);
   7099 }
   7100 
   7101 
   7102 /*
   7103  * Function:
   7104  *      _field_policer_mode_support
   7105  * Purpose:
   7106  *      Validate policer mode support.
   7107  * Parameters:
   7108  *      unit    - (IN) BCM device number.
   7109  *      f_ent   - (IN) Field entry policer attached.
   7110  *      level   - (IN) Level policer attached.
   7111  *      f_pl    - (IN) Policer descriptor.
   7112  * Returns:
   7113  *      BCM_E_XXX
   7114  */
   7115 int
   7116 _bcm_field_policer_mode_support(int unit, _field_entry_t *f_ent,
   7117                                 int level, _field_policer_t *f_pl)
   7118 {
   7119     int rv = BCM_E_UNAVAIL;   /* Operation return status.     */
   7120 
   7121     if ((0 == level) && (bcmPolicerModePeak == f_pl->cfg.mode)) {
   7122         /* bcmPolicerModePeak not supported. */
   7123         return (BCM_E_UNAVAIL);
   7124     }
   7125 
   7126     if (1 == level) {
   7127 #ifdef BCM_TRIDENT_SUPPORT
   7128         if (SOC_IS_TD_TT(unit)) {
   7129             /* Trident device does not support Level1 policers. */
   7130             return (rv);
   7131         }
   7132 #endif
   7133         if ((SOC_IS_TRX(unit)
   7134             && (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id))
   7135             || ((_BCM_FIELD_STAGE_EXTERNAL == f_ent->group->stage_id)
   7136                 && (SOC_IS_TRIUMPH(unit) || SOC_IS_TRIUMPH2(unit)))) {
   7137             /* Level 1 flow mode policer must be bcmPolicerModeCommitted. */
   7138             rv = (_FP_POLICER_IS_FLOW_MODE(f_pl))
   7139                     ? (BCM_E_NONE) : (BCM_E_PARAM);
   7140         }
   7141         return (rv);
   7142     }
   7143 
   7144     switch (f_pl->cfg.mode) {
   7145         case bcmPolicerModeTrTcm:
   7146         case bcmPolicerModeSrTcm:
   7147         case bcmPolicerModeCommitted:
   7148         case bcmPolicerModeGreen:
   7149             rv = BCM_E_NONE;
   7150             break;
   7151         case bcmPolicerModePassThrough:
   7152             if (SOC_IS_TRX(unit)) {
   7153                 rv = BCM_E_NONE;
   7154             } else if ((SOC_IS_FIREBOLT2(unit))
   7155                         && (_BCM_FIELD_STAGE_EGRESS
   7156                             == f_ent->group->stage_id)) {
   7157                 rv = BCM_E_NONE;
   7158             }
   7159             break;
   7160         case bcmPolicerModeTrTcmDs:
   7161             if (SOC_IS_TRX(unit)) {
   7162                 rv = BCM_E_NONE;
   7163             }
   7164             break;
   7165         case bcmPolicerModeSrTcmModified:
   7166             if ((soc_feature(unit, soc_feature_field_virtual_queue))
   7167                 && ((_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id)
   7168                 || ((_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id)
   7169                      && ((SOC_IS_TRIDENT2X(unit)
   7170                             || SOC_IS_TITAN2PLUS(unit)))))) {
   7171                 rv = BCM_E_NONE;
   7172             }
   7173             break;
   7174         case bcmPolicerModeCoupledTrTcmDs:
   7175             if ((soc_feature(unit, soc_feature_field_virtual_queue)) &&
   7176                 (((!SOC_IS_TD_TT(unit)) &&
   7177                   (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id)) ||
   7178                  ((SOC_IS_APACHE(unit) &&
   7179                   (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id))))) {
   7180                 rv = BCM_E_NONE;
   7181             }
   7182             break;
   7183         case bcmPolicerModeSrTcmTsn:
   7184             if (SOC_IS_GREYHOUND2(unit)) {
   7185                 if ((_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id) ||
   7186                     (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id)) {
   7187                     rv = BCM_E_NONE;
   7188                 }
   7189             }
   7190             break;
   7191         default:
   7192             rv = BCM_E_PARAM;
   7193             break;
   7194     }
   7195 
   7196 #if defined(BCM_ENDURO_SUPPORT)
   7197     if (SOC_IS_ENDURO(unit) || SOC_IS_HURRICANE2(unit) ||
   7198         SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
   7199         SOC_IS_GREYHOUND2(unit)) {
   7200         /* Egress stage does not support packet based metering */
   7201         if ((f_pl->cfg.flags & BCM_POLICER_MODE_PACKETS)
   7202             && (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id)) {
   7203             rv = BCM_E_PARAM;
   7204         }
   7205     }
   7206 #endif
   7207     return (rv);
   7208 }
   7209 
   7210 int
   7211 _field_policer_mode_support(int unit, _field_entry_t *f_ent,
   7212                             int level, _field_policer_t *f_pl)
   7213 {
   7214 #ifdef BCM_TRIUMPH3_SUPPORT
   7215     if (SOC_IS_TRIUMPH3(unit)) {
   7216         return (_bcm_field_tr3_policer_mode_support(unit, f_ent, level, f_pl));
   7217     }
   7218 #endif
   7219 
   7220     return (_bcm_field_policer_mode_support(unit, f_ent, level, f_pl));
   7221 }
   7222 
   7223 
   7224 /*
   7225  * Function:
   7226  *      _field_policer_create
   7227  * Purpose:
   7228  *      Initialize a policer entry.
   7229  * Parameters:
   7230  *      unit    - (IN) BCM device number.
   7231  *      pol_cfg - (IN) Policer configuration.
   7232  *      flags   - (IN) HW/API specific flags.
   7233  *      pid     - (OUT) Policer id.
   7234  * Returns:
   7235  *      BCM_E_XXX
   7236  * Notes:
   7237  */
   7238 int
   7239 _field_policer_create(int unit, bcm_policer_config_t *pol_cfg,
   7240                       uint32 flags, bcm_policer_t *pid)
   7241 {
   7242     _field_control_t    *fc;          /* Field control structure.     */
   7243     int                 rv;           /* Operation return status.     */
   7244     _field_policer_t    *f_pl = NULL; /* Internal policer descriptor. */
   7245 
   7246     /* Input parameters check. */
   7247     if (NULL == pol_cfg) {
   7248         return (BCM_E_PARAM);
   7249     }
   7250 
   7251     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   7252 
   7253     /* Generate policer id. */
   7254     if (0 == (pol_cfg->flags & BCM_POLICER_WITH_ID)) {
   7255         BCM_IF_ERROR_RETURN(_field_policer_id_alloc(unit, pid));
   7256     } else {
   7257         /* Check if policer id is already in use. */
   7258         rv = _bcm_field_policer_get(unit, *pid, &f_pl);
   7259         if (BCM_SUCCESS(rv)) {
   7260 
   7261             /* Verify that replace flag is set. */
   7262             if(0 == (pol_cfg->flags & BCM_POLICER_REPLACE)) {
   7263                 return (BCM_E_EXISTS);
   7264             }
   7265 
   7266             /* Make sure police is not attached to any entry. */
   7267             if (1 != f_pl->sw_ref_count) {
   7268                 return (BCM_E_BUSY);
   7269             }
   7270             /* Copy new configuration. */
   7271             sal_memcpy(&f_pl->cfg, pol_cfg, sizeof(bcm_policer_config_t));
   7272 
   7273             /* Set policer "dirty" flag and return. */
   7274             rv = _field_policer_hw_flags_set(unit, f_pl, flags);
   7275             return (rv);
   7276         }
   7277     }
   7278 
   7279     /* Allocate policer descriptor. */
   7280     _FP_XGS3_ALLOC(f_pl, sizeof (_field_policer_t), "Field policer");
   7281     if (NULL == f_pl) {
   7282         return (BCM_E_MEMORY);
   7283     }
   7284 
   7285     /* Copy policer configuration. */
   7286     sal_memcpy(&f_pl->cfg, pol_cfg, sizeof(bcm_policer_config_t));
   7287 
   7288     /* Set policer "dirty" flags. */
   7289     rv = _field_policer_hw_flags_set(unit, f_pl, flags);
   7290     if (BCM_FAILURE(rv)) {
   7291         sal_free(f_pl);
   7292         return (rv);
   7293     }
   7294 
   7295     /* Initialize reference count to 1. */
   7296     f_pl->sw_ref_count = 1;
   7297 
   7298     /* Set hw index to - no hw resources allocated. */
   7299     f_pl->pool_index = _FP_INVALID_INDEX;
   7300 #ifdef BCM_TRIUMPH3_SUPPORT
   7301     f_pl->logical_pool_index = _FP_INVALID_INDEX;
   7302 #endif
   7303     f_pl->hw_index = _FP_INVALID_INDEX;
   7304 
   7305     /* Initialize policer id. */
   7306     f_pl->pid = *pid;
   7307 
   7308     /* Insert policer into policers hash. */
   7309     _FP_HASH_INSERT(fc->policer_hash, f_pl, (*pid & _FP_HASH_INDEX_MASK(fc)));
   7310 
   7311     /* Increment number of active policers. */
   7312     fc->policer_count++;
   7313 
   7314     return (BCM_E_NONE);
   7315 }
   7316 
   7317 /*
   7318  * Function:
   7319  *     _field_meter_mem_get
   7320  * Purpose:
   7321  *     Get meter memory name.
   7322  * Parameters:
   7323  *     unit      - (IN) BCM device number.
   7324  *     stage_fc  - (IN) Stage field control.
   7325  *     mem       - (OUT) Meter memory.
   7326  * Returns:
   7327  *     BCM_E_XXX   -
   7328  */
   7329 STATIC int
   7330 _field_meter_mem_get(int unit, _field_stage_t *stage_fc, soc_mem_t *mem)
   7331 {
   7332     /* Input parameters check. */
   7333     if ((NULL == stage_fc)  || (NULL == mem)) {
   7334         return (BCM_E_PARAM);
   7335     }
   7336 
   7337     switch (stage_fc->stage_id) {
   7338       case _BCM_FIELD_STAGE_INGRESS:
   7339           *mem = FP_METER_TABLEm;
   7340           break;
   7341 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
   7342       case _BCM_FIELD_STAGE_EGRESS:
   7343           *mem = EFP_METER_TABLEm;
   7344           break;
   7345 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
   7346       default:
   7347           return (BCM_E_PARAM);
   7348     }
   7349     return (BCM_E_NONE);
   7350 }
   7351 /*
   7352  * Function: _field_counter_mem_get
   7353  *
   7354  * Description:
   7355  *      Service routine used to extract unit field counters memories
   7356  *
   7357  * Parameters:
   7358  *      unit            - (IN) BCM device number.
   7359  *      fc              - (IN) Field control structure.
   7360  *      stage_fc        - (IN) Stage field control structure.
   7361  *      counter_x_mem   - (OUT)First counters memory.
   7362  *      counter_y_mem   - (OUT)Second counters memory.
   7363  * Returns:
   7364  *      BCM_E_XXX
   7365  */
   7366 int
   7367 _bcm_field_counter_mem_get(int            unit,
   7368                            _field_stage_t *stage_fc,
   7369                            soc_mem_t      *counter_x_mem,
   7370                            soc_mem_t      *counter_y_mem
   7371                            )
   7372 {
   7373     if (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) {
   7374 #ifdef BCM_FIREBOLT_SUPPORT
   7375         if (SOC_IS_FBX(unit)) {
   7376 #ifdef BCM_BRADLEY_SUPPORT
   7377             if (soc_feature(unit, soc_feature_two_ingress_pipes)) {
   7378                 *counter_x_mem = FP_COUNTER_TABLE_Xm;
   7379                 *counter_y_mem = FP_COUNTER_TABLE_Ym;
   7380             } else
   7381 #endif /* BCM_BRADLEY_SUPPORT */
   7382             {
   7383                 *counter_x_mem = FP_COUNTER_TABLEm;
   7384             }
   7385         } else
   7386 #endif /* BCM_FIREBOLT_SUPPORT */
   7387         {
   7388            return (BCM_E_UNAVAIL);
   7389         }
   7390 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
   7391     } else if (_BCM_FIELD_STAGE_LOOKUP== stage_fc->stage_id) {
   7392         return (BCM_E_NONE);
   7393     } else if (_BCM_FIELD_STAGE_EGRESS == stage_fc->stage_id) {
   7394         if (soc_feature(unit, soc_feature_two_ingress_pipes)) {
   7395             *counter_x_mem = EFP_COUNTER_TABLE_Xm;
   7396             *counter_y_mem = EFP_COUNTER_TABLE_Ym;
   7397         } else {
   7398             *counter_x_mem = EFP_COUNTER_TABLEm;
   7399         }
   7400 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
   7401     } else if (_BCM_FIELD_STAGE_EXTERNAL == stage_fc->stage_id) {
   7402         *counter_x_mem = EXT_FP_CNTRm;
   7403     } else {
   7404         return (BCM_E_INTERNAL);
   7405     }
   7406     return (BCM_E_NONE);
   7407 }
   7408 
   7409 
   7410 int
   7411 _field_counter_mem_get(int            unit,
   7412                        _field_stage_t *stage_fc,
   7413                        soc_mem_t      *counter_x_mem,
   7414                        soc_mem_t      *counter_y_mem
   7415                        )
   7416 {
   7417     if (NULL == stage_fc || NULL == counter_x_mem || NULL == counter_y_mem) {
   7418         return (BCM_E_PARAM);
   7419     }
   7420 
   7421     *counter_x_mem = INVALIDm;
   7422     *counter_y_mem = INVALIDm;
   7423 
   7424 #ifdef BCM_TRIUMPH3_SUPPORT
   7425     if (SOC_IS_TRIUMPH3(unit)) {
   7426         return (_bcm_field_tr3_counter_mem_get(unit,
   7427                                                stage_fc,
   7428                                                counter_x_mem,
   7429                                                counter_y_mem
   7430                                                )
   7431                 );
   7432     }
   7433 #endif
   7434 
   7435     return (_bcm_field_counter_mem_get(unit,
   7436                                        stage_fc,
   7437                                        counter_x_mem,
   7438                                        counter_y_mem
   7439                                        )
   7440             );
   7441 }
   7442 
   7443 
   7444 /*
   7445  * Function:
   7446  *     _field_entry_counter_move
   7447  * Purpose:
   7448  *     Move the counter for an entry moving across a slice
   7449  * Parameters:
   7450  *     unit         - (IN) BCM device number.
   7451  *     stage_fc     - (IN) Stage field control.
   7452  *     old_slice    - (IN) Old counter slice number.
   7453  *     old_hw_index - (IN) Old counter hw index.
   7454  *     f_st         - (IN) New statistics entity descriptor.
   7455  * Returns:
   7456  *     BCM_E_XXX
   7457  */
   7458 int
   7459 _bcm_field_entry_counter_move(int unit, _field_stage_t *stage_fc,
   7460                               uint8 old_slice, int old_hw_index,
   7461                               _field_stat_t *f_st_old,
   7462                               _field_stat_t *f_st)
   7463 {
   7464     soc_mem_t counter_x_mem, counter_y_mem; /* Counter memories         */
   7465     _field_control_t *fc;                   /* FP control information   */
   7466     uint32 flags = 0;                       /* Bytes/Packets Stats type */
   7467     uint64 value;                           /* Hardware Stats value     */
   7468     int new_idx1 = _FP_INVALID_INDEX;       /* Primary Hw stats index   */
   7469     int new_idx2 = _FP_INVALID_INDEX;       /* Secondary Hw stats index */
   7470     int new_idx3 = _FP_INVALID_INDEX;       /* Third Hw stats index */
   7471     int nstat;                              /* Number of stats          */
   7472     int rv = BCM_E_INTERNAL;                /* Operation return status  */
   7473 
   7474     /* Get field control structure. */
   7475     rv = _field_control_get(unit, &fc);
   7476     BCM_IF_ERROR_RETURN(rv);
   7477 
   7478     /* Get the counter memories */
   7479     rv = _field_counter_mem_get(unit, stage_fc, &counter_x_mem, &counter_y_mem);
   7480     BCM_IF_ERROR_RETURN(rv);
   7481 
   7482     for (nstat = 0; nstat < f_st_old->nstat; nstat++) {
   7483         /* Get Stat value from old hardware index */
   7484         rv = _field_stat_value_get(unit, 0, f_st_old, f_st_old->stat_arr[nstat],
   7485                 &value);
   7486         BCM_IF_ERROR_RETURN(rv);
   7487 
   7488         if (_BCM_FIELD_STAGE_EXTERNAL != stage_fc->stage_id) {
   7489             /* Get Stat New hardware index values */
   7490             rv = fc->functions.fp_stat_index_get(unit, f_st,
   7491                 f_st->stat_arr[nstat], &new_idx1, &new_idx2, &new_idx3, &flags);
   7492             BCM_IF_ERROR_RETURN(rv);
   7493         } else if (_BCM_FIELD_STAGE_EXTERNAL == stage_fc->stage_id) {
   7494             new_idx1 = f_st->hw_index;
   7495         }
   7496 
   7497         /* Check if new hardware index is valid */
   7498         if (_FP_INVALID_INDEX == new_idx1) {
   7499             return (BCM_E_INTERNAL);
   7500         }
   7501 
   7502         if ((flags & _FP_STAT_BYTES)
   7503             && (stage_fc->flags & _FP_STAGE_SEPARATE_PACKET_BYTE_COUNTERS))  {
   7504             /*
   7505              * For devices that do not support separate packet and byte counters
   7506              * only _field_x32_counters is used.
   7507              */
   7508 
   7509 #if defined(BCM_TRX_SUPPORT)
   7510             /* Zero the accumulated part at new_idx1 */
   7511             COMPILER_64_ZERO(stage_fc->_field_x64_counters[new_idx1].
   7512                 accumulated_counter);
   7513 
   7514             /* Copy the accumulated part value */
   7515             COMPILER_64_OR(stage_fc->_field_x64_counters[new_idx1].
   7516                 accumulated_counter, value);
   7517 
   7518             /* Zero the last_hw_value at new_idx1 */
   7519             COMPILER_64_ZERO(stage_fc->_field_x64_counters[new_idx1].
   7520                 last_hw_value);
   7521 
   7522             /* Zero Y-Pipeline counter values */
   7523             if (INVALIDm != counter_y_mem) {
   7524                 COMPILER_64_ZERO(stage_fc->_field_y64_counters[new_idx1].
   7525                     accumulated_counter);
   7526                 COMPILER_64_ZERO(stage_fc->_field_y64_counters[new_idx1].
   7527                     last_hw_value);
   7528             }
   7529 
   7530             /* Zero counters at secondary index */
   7531             if (_FP_INVALID_INDEX != new_idx2) {
   7532                 COMPILER_64_ZERO(stage_fc->_field_x64_counters[new_idx2].
   7533                     accumulated_counter);
   7534                 COMPILER_64_ZERO(stage_fc->_field_x64_counters[new_idx2].
   7535                     last_hw_value);
   7536 
   7537                 /* Zero Y-Pipeline counter values at secondary index */
   7538                 if (INVALIDm != counter_y_mem) {
   7539                     COMPILER_64_ZERO(stage_fc->_field_y64_counters[new_idx2].
   7540                         accumulated_counter);
   7541                     COMPILER_64_ZERO(stage_fc->_field_y64_counters[new_idx2].
   7542                         last_hw_value);
   7543                 }
   7544             }
   7545 #endif
   7546         } else {
   7547 
   7548             /* Zero the accumulated part at new_idx1 */
   7549             COMPILER_64_ZERO(stage_fc->_field_x32_counters[new_idx1].
   7550                 accumulated_counter);
   7551 
   7552             /* Copy the accumulated part */
   7553             COMPILER_64_OR(stage_fc->_field_x32_counters[new_idx1].
   7554                 accumulated_counter, value);
   7555 
   7556             /* Zero the last_hw_value at new_idx1 */
   7557             stage_fc->_field_x32_counters[new_idx1].last_hw_value = 0;
   7558 
   7559             /* Zero Y-Pipeline packet counter values */
   7560             if (INVALIDm != counter_y_mem) {
   7561 #if defined(BCM_SCORPION_SUPPORT)
   7562                 COMPILER_64_ZERO(stage_fc->_field_y32_counters[new_idx1].
   7563                     accumulated_counter);
   7564 
   7565                 /* Zero the last_hw_value at new_idx1 */
   7566                 stage_fc->_field_y32_counters[new_idx1].last_hw_value = 0;
   7567 #endif
   7568             }
   7569 
   7570             /* Zero counters at secondary index */
   7571             if (_FP_INVALID_INDEX != new_idx2) {
   7572                 /* Zero the accumulated part at new_idx2 */
   7573                 COMPILER_64_ZERO(stage_fc->_field_x32_counters[new_idx2].
   7574                     accumulated_counter);
   7575 
   7576                 /* Zero the last_hw_value at new_idx2 */
   7577                 stage_fc->_field_x32_counters[new_idx2].last_hw_value = 0;
   7578 
   7579                 /* Zero Y-Pipeline packet counter values at secondary index */
   7580                 if (INVALIDm != counter_y_mem) {
   7581 #if defined(BCM_SCORPION_SUPPORT)
   7582                     COMPILER_64_ZERO(stage_fc->_field_y32_counters[new_idx2].
   7583                         accumulated_counter);
   7584 
   7585                     /* Zero the last_hw_value at new_idx2 */
   7586                     stage_fc->_field_y32_counters[new_idx2].last_hw_value = 0;
   7587 #endif
   7588                 }
   7589             }
   7590         }
   7591 
   7592         COMPILER_64_ZERO(value);
   7593         rv = _field_stat_value_set(unit, f_st_old, f_st_old->stat_arr[nstat],
   7594                   value);
   7595         BCM_IF_ERROR_RETURN(rv);
   7596     }
   7597     return rv;
   7598 }
   7599 
   7600 /*
   7601  * Function:
   7602  *     _field_entry_meter_move
   7603  * Purpose:
   7604  *     Move the meters for an entry moving across a slice
   7605  * Parameters:
   7606  *     unit         - (IN) BCM device number.
   7607  *     stage_fc     - (IN) Stage field control.
   7608  *     instance     - (IN) Pipe Instance the entry belongs to.
   7609  *     old_slice    - (IN) Old meter slice number.
   7610  *     old_hw_index - (IN) Old meter hw index.
   7611  *     old_flags    - (IN) Old meter flags.
   7612  *     f_pl         - (IN) New meter descriptor.
   7613  *     f_ent        - (IN) field entry.
   7614  *     old_mode     - (IN) old meter mode.
   7615  * Returns:
   7616  *     BCM_E_XXX
   7617  */
   7618 STATIC int
   7619 _field_entry_meter_move(int unit, _field_stage_t *stage_fc,
   7620                         int instance, uint8 old_slice, int old_hw_index,
   7621                         uint32 old_flags, _field_policer_t *f_pl,
   7622                         _field_entry_t *f_ent, bcm_policer_mode_t old_mode)
   7623 {
   7624     uint32 buf[SOC_MAX_MEM_FIELD_WORDS];  /* Meter memory entry buffer. */
   7625     soc_mem_t mem_x = INVALIDm;           /* Meter memory.              */
   7626     soc_mem_t mem_y = INVALIDm;           /* Meter memory.              */
   7627     int old_index;                        /* Old meter index in memory. */
   7628     int new_index;                        /* New meter index in memory. */
   7629 
   7630 #if defined(BCM_TRX_SUPPORT)
   7631     if (SOC_IS_SC_CQ(unit) || SOC_IS_TD_TT(unit)) {
   7632         BCM_IF_ERROR_RETURN(_field_trx_meter_table_get(unit, stage_fc->stage_id, &mem_x, &mem_y));
   7633     } else
   7634 #endif
   7635     {
   7636         BCM_IF_ERROR_RETURN(_field_meter_mem_get(unit, stage_fc, &mem_x));
   7637     }
   7638 
   7639     old_index =  stage_fc->slices[instance][old_slice].start_tcam_idx
   7640                     + (2 * old_hw_index);
   7641 
   7642     new_index =  stage_fc->slices[instance][f_pl->pool_index].start_tcam_idx
   7643                     + (2 * f_pl->hw_index);
   7644 
   7645     if ((old_index < soc_mem_index_min(unit, mem_x)) ||
   7646         ((old_index + 1) > soc_mem_index_max(unit, mem_x)) ||
   7647         (new_index < soc_mem_index_min(unit, mem_x)) ||
   7648         ((new_index + 1) > soc_mem_index_max(unit, mem_x))) {
   7649         return (BCM_E_PARAM);
   7650     }
   7651 
   7652     /* Clear entry buffer. */
   7653     sal_memset(buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   7654 
   7655     /* Copy meter from old location to a new one. */
   7656     if (!_FP_POLICER_IS_FLOW_MODE(f_pl)) {
   7657         BCM_IF_ERROR_RETURN
   7658             (soc_mem_read(unit, mem_x, MEM_BLOCK_ANY, old_index, buf));
   7659         BCM_IF_ERROR_RETURN
   7660             (soc_mem_write(unit, mem_x, MEM_BLOCK_ALL, new_index, buf));
   7661         sal_memset(buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   7662         if (INVALIDm != mem_y) {
   7663             BCM_IF_ERROR_RETURN
   7664                 (soc_mem_read(unit, mem_y, MEM_BLOCK_ANY, old_index, buf));
   7665             BCM_IF_ERROR_RETURN
   7666                 (soc_mem_write(unit, mem_y, MEM_BLOCK_ALL, new_index, buf));
   7667         }
   7668 
   7669         sal_memset(buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   7670         BCM_IF_ERROR_RETURN
   7671             (soc_mem_read(unit, mem_x, MEM_BLOCK_ANY, old_index + 1, buf));
   7672         BCM_IF_ERROR_RETURN
   7673             (soc_mem_write(unit, mem_x, MEM_BLOCK_ALL, new_index + 1, buf));
   7674         sal_memset(buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   7675         if (INVALIDm != mem_y) {
   7676             BCM_IF_ERROR_RETURN
   7677                 (soc_mem_read(unit, mem_y, MEM_BLOCK_ANY, old_index + 1, buf));
   7678             BCM_IF_ERROR_RETURN
   7679                 (soc_mem_write(unit, mem_y, MEM_BLOCK_ALL, new_index + 1, buf));
   7680         }
   7681     } else {
   7682         /* If its flow mode, consider the old flags to
   7683          * decide on even or odd meter
   7684          */
   7685         if ((bcmPolicerModeCommitted == (f_pl)->cfg.mode) &&
   7686             (old_flags & _FP_POLICER_EXCESS_METER) ) {
   7687             BCM_IF_ERROR_RETURN
   7688                 (soc_mem_read(unit, mem_x, MEM_BLOCK_ANY, old_index, buf));
   7689             if (_FP_POLICER_EXCESS_HW_METER(f_pl)) {
   7690                 BCM_IF_ERROR_RETURN
   7691                     (soc_mem_write(unit, mem_x, MEM_BLOCK_ALL, new_index, buf));
   7692              } else {
   7693                  BCM_IF_ERROR_RETURN
   7694                     (soc_mem_write(unit, mem_x, MEM_BLOCK_ALL, new_index+1, buf));
   7695              }
   7696             sal_memset(buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   7697             if (INVALIDm != mem_y) {
   7698                 BCM_IF_ERROR_RETURN
   7699                     (soc_mem_read(unit, mem_y, MEM_BLOCK_ANY, old_index, buf));
   7700                 if (_FP_POLICER_EXCESS_HW_METER(f_pl)) {
   7701                     BCM_IF_ERROR_RETURN
   7702                         (soc_mem_write(unit, mem_y, MEM_BLOCK_ALL, new_index, buf));
   7703                  } else {
   7704                      BCM_IF_ERROR_RETURN
   7705                         (soc_mem_write(unit, mem_y, MEM_BLOCK_ALL, new_index+1, buf));
   7706                 }
   7707             }
   7708 
   7709             f_pl->hw_flags &= ~_FP_POLICER_PEAK_DIRTY;
   7710         } else if ((bcmPolicerModeCommitted == (f_pl)->cfg.mode) &&
   7711             (!(old_flags & _FP_POLICER_EXCESS_METER)) ) {
   7712             BCM_IF_ERROR_RETURN
   7713                 (soc_mem_read(unit, mem_x, MEM_BLOCK_ANY, old_index + 1, buf));
   7714             if (_FP_POLICER_COMMITTED_HW_METER(f_pl)) {
   7715                 BCM_IF_ERROR_RETURN
   7716                     (soc_mem_write(unit, mem_x, MEM_BLOCK_ALL, new_index+1, buf));
   7717              } else {
   7718                  BCM_IF_ERROR_RETURN
   7719                     (soc_mem_write(unit, mem_x, MEM_BLOCK_ALL, new_index, buf));
   7720              }
   7721             sal_memset(buf, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   7722             if (INVALIDm != mem_y) {
   7723                 BCM_IF_ERROR_RETURN
   7724                     (soc_mem_read(unit, mem_y, MEM_BLOCK_ANY, old_index + 1, buf));
   7725                 if (_FP_POLICER_COMMITTED_HW_METER(f_pl)) {
   7726                     BCM_IF_ERROR_RETURN
   7727                         (soc_mem_write(unit, mem_y, MEM_BLOCK_ALL, new_index + 1, buf));
   7728                  } else {
   7729                      BCM_IF_ERROR_RETURN
   7730                     (soc_mem_write(unit, mem_y, MEM_BLOCK_ALL, new_index, buf));
   7731                  }
   7732             }
   7733 
   7734             /* Clear committed dirty bit. */
   7735             f_pl->hw_flags &= ~_FP_POLICER_COMMITTED_DIRTY;
   7736         }
   7737     }
   7738     /* in case pf td2p where _FP_STAGE_AUTOEXPAND_WITH_POLICER
   7739      * is set, clear the old meter entry(ie meter entry of source entry)
   7740      * from meter table
   7741      */
   7742     _field_meter_hw_clear(unit,f_ent,
   7743                                  old_hw_index, old_mode,
   7744                                  old_slice, old_flags);
   7745     return (BCM_E_NONE);
   7746 }
   7747 
   7748 STATIC int
   7749 _field_meter_pool_apply_pool_id_alloc(int unit, _field_stage_t *stage_fc, int instance,
   7750                         _field_policer_t *f_pl, int half_meters, uint8 *pool_idx)
   7751 {
   7752     _field_meter_pool_t  *f_mp = NULL;                   /* Meter pool descriptor. */
   7753 
   7754     if ((0 > f_pl->cfg.pool_id) ||
   7755             (f_pl->cfg.pool_id > stage_fc->num_meter_pools) ||
   7756             (0 == (f_pl->cfg.flags & BCM_POLICER_APPLY_GLOBAL_POOL_ID))) {
   7757         return BCM_E_PARAM;
   7758     }
   7759 
   7760     /* Check if pool_id passed is a valid pool */
   7761     f_mp = stage_fc->meter_pool[instance][f_pl->cfg.pool_id];
   7762     if ((NULL == f_mp)) {
   7763         return (BCM_E_INTERNAL);
   7764     }
   7765 
   7766     if ((_FP_POLICER_IS_FLOW_MODE(f_pl) && (f_mp->free_meters) > (half_meters-1))
   7767             || (!_FP_POLICER_IS_FLOW_MODE(f_pl) && f_mp->free_meters >= 2)) {
   7768         *pool_idx = f_pl->cfg.pool_id;
   7769     } else {
   7770         return BCM_E_RESOURCE;
   7771     }
   7772 
   7773     return BCM_E_NONE;
   7774 }
   7775 /*
   7776  * Function:
   7777  *     _field_meter_pool_alloc
   7778  *
   7779  * Purpose:
   7780  *     Allocate/Find meter pool with free meters
   7781  *
   7782  * Parameters:
   7783  *     unit     - (IN) BCM device number.
   7784  *     stage_fc - (IN) Stage field control structure.
   7785  *     instance - (IN) Pipe Instance.
   7786  *     f_pl     - (IN) Field policer descriptor
   7787  *     slice_id - (IN) Slice base index.
   7788  *     pool_idx - (OUT) Meter pool index.
   7789  * Returns:
   7790  *     BCM_E_XXX
   7791  */
   7792 STATIC int
   7793 _field_meter_pool_alloc(int unit, _field_stage_t *stage_fc, int instance,
   7794                         _field_policer_t *f_pl, uint8 slice_id, uint8 *pool_idx)
   7795 {
   7796     _field_meter_pool_t  *f_mp;          /* Meter pool descriptor. */
   7797     int                  idx;            /* Pool iteration index.  */
   7798     int                  free_pool;      /* Free meter pool.       */
   7799     /* allocate even meter index for ingress metering for flow mode.
   7800      * If set, the non-flow mode is disabled. Is available only for
   7801      * Trident+ devices as there is an issue with metering on Y-pipe ports
   7802      */
   7803     int              use_even_meter;
   7804     uint16           devid;
   7805     uint8            revid;
   7806     int              half_meters;
   7807 
   7808     /* Input parameters check. */
   7809     if ((NULL == stage_fc) || (NULL == pool_idx)) {
   7810         return (BCM_E_PARAM);
   7811     }
   7812     half_meters = 1;
   7813     if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) {
   7814         use_even_meter = soc_property_get(unit,
   7815                            spn_FP_EVEN_INDEX_FOR_INGRESS_FLOW_METER, 0);
   7816         if (use_even_meter) {
   7817             soc_cm_get_id(unit, &devid, &revid);
   7818             if ((devid == BCM56842_DEVICE_ID)||(devid == BCM56844_DEVICE_ID)||
   7819                 (devid == BCM56846_DEVICE_ID)||(devid == BCM56847_DEVICE_ID)||
   7820                 (devid == BCM56053_DEVICE_ID)||(devid == BCM56549_DEVICE_ID)||
   7821                 (devid == BCM56831_DEVICE_ID)||(devid == BCM56835_DEVICE_ID)||
   7822                 (devid == BCM56838_DEVICE_ID)||(devid == BCM56849_DEVICE_ID)
   7823                 ) {
   7824                 half_meters = 2;
   7825             }
   7826         }
   7827     }
   7828 
   7829     if (f_pl->cfg.flags & BCM_POLICER_APPLY_GLOBAL_POOL_ID) {
   7830         return _field_meter_pool_apply_pool_id_alloc(unit, stage_fc, instance,
   7831                                              f_pl, half_meters, pool_idx);
   7832     }
   7833     free_pool = _FP_INVALID_INDEX;
   7834 
   7835    	/* Create policer in an existing pool */
   7836     if ((f_pl->level == 1) && (f_pl->cfg.pool_id != -1)
   7837         && (f_pl->cfg.flags & BCM_POLICER_WITH_POOL_ID)) {
   7838 
   7839         /* Check if pool_id passed is a valid pool */
   7840         f_mp = stage_fc->meter_pool[instance][f_pl->cfg.pool_id];
   7841         if ((NULL == f_mp) || (f_mp->slice_id == _FP_INVALID_INDEX)
   7842             || (f_mp->level != 1)) {
   7843             return (BCM_E_INTERNAL);
   7844         }
   7845 
   7846         /* If free meters are available then allocate pool */
   7847 		if ((_FP_POLICER_IS_FLOW_MODE(f_pl) &&
   7848               (f_mp->free_meters) > (half_meters-1)) ||
   7849               (!_FP_POLICER_IS_FLOW_MODE(f_pl) && f_mp->free_meters >= 2)) {
   7850             *pool_idx = f_pl->cfg.pool_id;
   7851             return (BCM_E_NONE);
   7852         }
   7853     }
   7854 
   7855     for (idx = 0 ; idx < stage_fc->num_meter_pools; idx++) {
   7856         f_mp = stage_fc->meter_pool[instance][idx];
   7857         if (NULL == f_mp) {
   7858             return (BCM_E_INTERNAL);
   7859         }
   7860 
   7861         /* If we have a matching pool with free entries - just use it. */
   7862         if ((f_mp->slice_id == slice_id)
   7863             && (f_mp->level == f_pl->level)
   7864             && ((_FP_POLICER_IS_FLOW_MODE(f_pl) &&
   7865                 (f_mp->free_meters) > (half_meters-1))
   7866                 || (!_FP_POLICER_IS_FLOW_MODE(f_pl) && f_mp->free_meters >= 2)
   7867                 )) {
   7868 
   7869             *pool_idx = idx;
   7870             f_pl->cfg.pool_id = *pool_idx;
   7871             return (BCM_E_NONE);
   7872         }
   7873 
   7874         /* Preserve first free pool */
   7875         if ((_FP_INVALID_INDEX  == free_pool) &&
   7876             (_FP_INVALID_INDEX  == f_mp->slice_id)) {
   7877             free_pool = idx;
   7878         }
   7879     }
   7880 
   7881 
   7882     /* We have to use free pool at this point. */
   7883     if (_FP_INVALID_INDEX == free_pool) {
   7884         return (BCM_E_RESOURCE);
   7885     }
   7886 
   7887     f_mp = stage_fc->meter_pool[instance][free_pool];
   7888     f_mp->slice_id = slice_id;
   7889     f_mp->level = f_pl->level;
   7890     *pool_idx = free_pool;
   7891     f_pl->cfg.pool_id = *pool_idx;
   7892     return (BCM_E_NONE);
   7893 }
   7894 
   7895 
   7896 /*
   7897  * Function:
   7898  *     _field_meter_pool_free
   7899  *
   7900  * Purpose:
   7901  *     Unreserve a meter pool.
   7902  *
   7903  * Parameters:
   7904  *     unit     - (IN) BCM device number.
   7905  *     stage_fc - (IN) Stage field control structure.
   7906  *     instance - (IN) Pipe Instance.
   7907  *     pool_idx - (IN) Meter pool index.
   7908  * Returns:
   7909  *     BCM_E_XXX
   7910  */
   7911 int
   7912 _field_meter_pool_free(int unit, _field_stage_t *stage_fc,
   7913                        int instance, uint8 pool_idx)
   7914 {
   7915     _field_meter_pool_t *f_mp;          /* Meter pool descriptor. */
   7916 #if defined (BCM_TOMAHAWK_SUPPORT)
   7917     _field_control_t *fc;               /* Field control */
   7918 #endif
   7919 
   7920     /* Input parameters check. */
   7921     if (NULL == stage_fc) {
   7922         return (BCM_E_PARAM);
   7923     }
   7924 
   7925     f_mp = stage_fc->meter_pool[instance][pool_idx];
   7926     if (NULL == f_mp) {
   7927         return (BCM_E_INTERNAL);
   7928     }
   7929 
   7930     /* Make sure pool entries are not in use. */
   7931     if (f_mp->free_meters != f_mp->size) {
   7932         return (BCM_E_BUSY);
   7933     }
   7934 
   7935     f_mp->slice_id = _FP_INVALID_INDEX;
   7936     f_mp->level = -1;
   7937 
   7938 #if defined (BCM_TOMAHAWK_SUPPORT)
   7939     if ((soc_feature(unit, soc_feature_field_multi_pipe_support)) &&
   7940         (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)) {
   7941 
   7942         /* Get field control information. */
   7943         BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   7944         fc->ifp_em_meter_in_use[instance][pool_idx] =
   7945          BCM_FIELD_METER_POOL_USED_BY_NONE;
   7946     }
   7947 #endif
   7948 
   7949     return (BCM_E_NONE);
   7950 }
   7951 
   7952 STATIC int
   7953 _field_meter_pool_entry_free_old(int unit, _field_stage_t *stage_fc,
   7954                              int instance, _field_policer_t *f_pl)
   7955 {
   7956     _field_control_t   *fc;
   7957     _field_meter_pool_t *f_mp;  /* Meter pool descriptor. */
   7958     int idx;                    /* Meter index.           */
   7959     /* allocate even meter index for ingress metering for flow mode.
   7960      * If set, the non-flow mode is disabled. Is available only for
   7961      * Trident+ devices as there is an issue with metering on Y-pipe ports
   7962      */
   7963     int                    use_even_meter;
   7964     int                    is_trident_plus_use_even_meter;
   7965     uint16                 devid;
   7966     uint8                  revid;
   7967 
   7968     /* Input parameters check. */
   7969     if ((NULL == stage_fc) || (NULL == f_pl)) {
   7970         return (BCM_E_PARAM);
   7971     }
   7972 
   7973     /* Meter pool index sanity check. */
   7974     if (stage_fc->num_meter_pools <= f_pl->old_pool_index) {
   7975         return (BCM_E_PARAM);
   7976     }
   7977 
   7978     /* Get field control information. */
   7979     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   7980 
   7981 #ifdef BCM_TRIUMPH3_SUPPORT
   7982     if (SOC_IS_TRIUMPH3(unit)) {
   7983 
   7984         /* When ingress physical policer pools is split into logical pools
   7985          * Allocate pool id and index using the logical meter pool entry
   7986          * allocator
   7987          */
   7988         if (fc->ingress_logical_policer_pools_mode !=
   7989                     bcmFieldIngressLogicalPolicerPools8x1024) {
   7990             LOG_DEBUG(BSL_LS_BCM_FP,
   7991                       (BSL_META_U(unit,
   7992                                   "FP(unit %d) Policer Pools is in non default mode."
   7993                                    " Logical Meter alloc called.\r\n"), unit));
   7994             return _field_tr3_logical_meter_pool_entry_free_old (unit, stage_fc, f_pl);
   7995         }
   7996     }
   7997 #endif
   7998     is_trident_plus_use_even_meter = 0;
   7999     if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) {
   8000         use_even_meter = soc_property_get(unit,
   8001                            spn_FP_EVEN_INDEX_FOR_INGRESS_FLOW_METER, 0);
   8002         if (use_even_meter) {
   8003             soc_cm_get_id(unit, &devid, &revid);
   8004             if ((devid == BCM56842_DEVICE_ID)||(devid == BCM56844_DEVICE_ID)||
   8005                 (devid == BCM56846_DEVICE_ID)||(devid == BCM56847_DEVICE_ID)||
   8006                 (devid == BCM56053_DEVICE_ID)||(devid == BCM56549_DEVICE_ID)||
   8007                 (devid == BCM56831_DEVICE_ID)||(devid == BCM56835_DEVICE_ID)||
   8008                 (devid == BCM56838_DEVICE_ID)||(devid == BCM56849_DEVICE_ID)
   8009                 ) {
   8010                 is_trident_plus_use_even_meter = 1;
   8011             }
   8012         }
   8013     }
   8014 
   8015     f_mp = stage_fc->meter_pool[instance][f_pl->old_pool_index];
   8016 
   8017     /* Mark meter as free in the slice. */
   8018     idx = f_pl->old_hw_index * 2;
   8019 
   8020     /* Meter index in the pool sanity check. */
   8021     if ((f_mp->size <= idx)
   8022         || (f_mp->size <= (idx + 1))) {
   8023         return (BCM_E_PARAM);
   8024     }
   8025     /* if not flow mode */
   8026     if (bcmPolicerModeCommitted != (f_pl)->old_mode) {
   8027         _FP_METER_BMP_REMOVE(f_mp->meter_bmp, idx);
   8028         _FP_METER_BMP_REMOVE(f_mp->meter_bmp, idx + 1);
   8029         f_mp->free_meters += 2;
   8030     } else {
   8031         /* if excess meter */
   8032         if ((bcmPolicerModeCommitted == (f_pl)->old_mode) &&
   8033             ((f_pl)->old_hw_flags & _FP_POLICER_EXCESS_METER)) {
   8034             _FP_METER_BMP_REMOVE(f_mp->meter_bmp, idx);
   8035 
   8036         } else if ((bcmPolicerModeCommitted == (f_pl)->old_mode) &&
   8037             (!((f_pl)->old_hw_flags & _FP_POLICER_EXCESS_METER))) {
   8038             _FP_METER_BMP_REMOVE(f_mp->meter_bmp, idx + 1);
   8039         }
   8040         f_mp->free_meters++;
   8041         if (is_trident_plus_use_even_meter) {
   8042             f_mp->free_meters++;
   8043         }
   8044     }
   8045 
   8046     /* Free empty pool. */
   8047     if (f_mp->free_meters == f_mp->size) {
   8048         BCM_IF_ERROR_RETURN
   8049            (_field_meter_pool_free(unit, stage_fc, instance, f_pl->pool_index));
   8050     }
   8051 
   8052     return (BCM_E_NONE);
   8053 }
   8054 /*
   8055  * Function:
   8056  *     _field_meter_pool_entry_free
   8057  *
   8058  * Purpose:
   8059  *     Free meter pool entry.
   8060  *     if necessary free the pool itself.
   8061  *
   8062  * Parameters:
   8063  *     unit      - (IN) BCM device number.
   8064  *     stage_fc  - (IN) Stage field control structure.
   8065  *     instance  - (IN) Pipe Instance.
   8066  *     f_pl      - (IN) Policer descriptor.
   8067  * Returns:
   8068  *     BCM_E_XXX
   8069  */
   8070 STATIC int
   8071 _field_meter_pool_entry_free(int unit, _field_stage_t *stage_fc,
   8072                              int instance, _field_policer_t *f_pl)
   8073 {
   8074     _field_control_t   *fc;
   8075     _field_meter_pool_t *f_mp;  /* Meter pool descriptor. */
   8076     int idx;                    /* Meter index.           */
   8077     /* allocate even meter index for ingress metering for flow mode.
   8078      * If set, the non-flow mode is disabled. Is available only for
   8079      * Trident+ devices as there is an issue with metering on Y-pipe ports
   8080      */
   8081     int                    use_even_meter;
   8082     int                    is_trident_plus_use_even_meter;
   8083     uint16                 devid;
   8084     uint8                  revid;
   8085 
   8086     /* Input parameters check. */
   8087     if ((NULL == stage_fc) || (NULL == f_pl)) {
   8088         return (BCM_E_PARAM);
   8089     }
   8090 
   8091     /* Meter pool index sanity check. */
   8092     if (stage_fc->num_meter_pools <= f_pl->pool_index) {
   8093         return (BCM_E_PARAM);
   8094     }
   8095 
   8096     /* Get field control information. */
   8097     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   8098 
   8099 #ifdef BCM_TRIUMPH3_SUPPORT
   8100     if (SOC_IS_TRIUMPH3(unit)) {
   8101 
   8102         /* When ingress physical policer pools is split into logical pools
   8103          * Allocate pool id and index using the logical meter pool entry
   8104          * allocator
   8105          */
   8106         if (fc->ingress_logical_policer_pools_mode !=
   8107                     bcmFieldIngressLogicalPolicerPools8x1024) {
   8108             LOG_DEBUG(BSL_LS_BCM_FP,
   8109                       (BSL_META_U(unit,
   8110                                   "FP(unit %d) Policer Pools is in non default mode."
   8111                                    " Logical Meter alloc called.\r\n"), unit));
   8112             return _field_tr3_logical_meter_pool_entry_free (unit, stage_fc, f_pl);
   8113         }
   8114     }
   8115 #endif
   8116     is_trident_plus_use_even_meter = 0;
   8117     if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) {
   8118         use_even_meter = soc_property_get(unit,
   8119                            spn_FP_EVEN_INDEX_FOR_INGRESS_FLOW_METER, 0);
   8120         if (use_even_meter) {
   8121             soc_cm_get_id(unit, &devid, &revid);
   8122             if ((devid == BCM56842_DEVICE_ID)||(devid == BCM56844_DEVICE_ID)||
   8123                 (devid == BCM56846_DEVICE_ID)||(devid == BCM56847_DEVICE_ID)||
   8124                 (devid == BCM56053_DEVICE_ID)||(devid == BCM56549_DEVICE_ID)||
   8125                 (devid == BCM56831_DEVICE_ID)||(devid == BCM56835_DEVICE_ID)||
   8126                 (devid == BCM56838_DEVICE_ID)||(devid == BCM56849_DEVICE_ID)
   8127                 ) {
   8128                 is_trident_plus_use_even_meter = 1;
   8129             }
   8130         }
   8131     }
   8132 
   8133     f_mp = stage_fc->meter_pool[instance][f_pl->pool_index];
   8134 
   8135     /* Mark meter as free in the slice. */
   8136     idx = f_pl->hw_index * 2;
   8137 
   8138     /* Meter index in the pool sanity check. */
   8139     if ((f_mp->size <= idx)
   8140         || (f_mp->size <= (idx + 1))) {
   8141         return (BCM_E_PARAM);
   8142     }
   8143 
   8144     if (!_FP_POLICER_IS_FLOW_MODE(f_pl)) {
   8145         _FP_METER_BMP_REMOVE(f_mp->meter_bmp, idx);
   8146         _FP_METER_BMP_REMOVE(f_mp->meter_bmp, idx + 1);
   8147         f_mp->free_meters += 2;
   8148     } else {
   8149 
   8150         if (_FP_POLICER_EXCESS_HW_METER(f_pl)) {
   8151             _FP_METER_BMP_REMOVE(f_mp->meter_bmp, idx);
   8152 
   8153             /* Clear excess meter flag bit. */
   8154             _FP_POLICER_EXCESS_HW_METER_CLEAR(f_pl);
   8155         } else if (_FP_POLICER_COMMITTED_HW_METER(f_pl)) {
   8156             _FP_METER_BMP_REMOVE(f_mp->meter_bmp, idx + 1);
   8157         }
   8158         f_mp->free_meters++;
   8159         if (is_trident_plus_use_even_meter) {
   8160             f_mp->free_meters++;
   8161         }
   8162     }
   8163 
   8164     /* Free empty pool. */
   8165     if (f_mp->free_meters == f_mp->size) {
   8166         BCM_IF_ERROR_RETURN
   8167            (_field_meter_pool_free(unit, stage_fc, instance, f_pl->pool_index));
   8168     }
   8169 
   8170     /* Reset pool and hw index information in policer structure. */
   8171     f_pl->pool_index = _FP_INVALID_INDEX;
   8172     f_pl->hw_index = _FP_INVALID_INDEX;
   8173 
   8174     return (BCM_E_NONE);
   8175 }
   8176 
   8177 /*
   8178  * Function:
   8179  *     _field_meter_pool_entry_alloc
   8180  *
   8181  * Purpose:
   8182  *     Allocate meter pool entry.
   8183  *
   8184  * Parameters:
   8185  *     unit             - (IN) BCM device number.
   8186  *     stage_fc         - (IN) Stage field control structure.
   8187  *     instance         - (IN) Pipe Instance.
   8188  *     pool_slice_id    - (IN) Meter pool index.
   8189  *     f_pl             - (IN) Field policer descriptor
   8190  * Returns:
   8191  *     BCM_E_XXX
   8192  */
   8193 STATIC int
   8194 _field_meter_pool_entry_alloc(int unit, _field_stage_t *stage_fc, int instance,
   8195                               uint8 pool_slice_id, _field_policer_t *f_pl)
   8196 {
   8197     uint8                   pool_idx;       /* Meter pool index.        */
   8198     int                     idx;            /* Pool iteration index.    */
   8199     _field_meter_pool_t    *f_mp;           /* Meter pool descriptor.   */
   8200     _field_control_t       *fc;             /* Field control structure. */
   8201     /* allocate even meter index for ingress metering for flow mode.
   8202      * If set, the non-flow mode is disabled. Is available only for
   8203      * Trident+ devices as there is an issue with metering on Y-pipe ports
   8204      */
   8205     int                    use_even_meter;
   8206     int                    is_trident_plus_use_even_meter;
   8207     uint16                 devid;
   8208     uint8                  revid;
   8209 
   8210     /* Input parameters check. */
   8211     if ((NULL == stage_fc) || (NULL == f_pl)) {
   8212         return (BCM_E_PARAM);
   8213     }
   8214 
   8215     if (f_pl->level >= _FP_POLICER_LEVEL_COUNT) {
   8216         return (BCM_E_PARAM);
   8217     }
   8218     /* Get field control structure. */
   8219     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   8220 
   8221 #ifdef BCM_TRIUMPH3_SUPPORT
   8222     if (SOC_IS_TRIUMPH3(unit)) {
   8223 
   8224         /* When ingress physical policer pools is split into logical pools
   8225          * Allocate pool id and index using the logical meter pool entry
   8226          * allocator
   8227          */
   8228         if (fc->ingress_logical_policer_pools_mode !=
   8229                     bcmFieldIngressLogicalPolicerPools8x1024) {
   8230             LOG_DEBUG(BSL_LS_BCM_FP,
   8231                       (BSL_META_U(unit,
   8232                                   "FP(unit %d) Policer Pools is in non default mode."
   8233                                    " Logical Meter alloc called.\r\n"), unit));
   8234             return _field_tr3_logical_meter_pool_entry_alloc (unit,
   8235                                                               stage_fc,
   8236                                                               pool_slice_id,
   8237                                                               f_pl);
   8238         }
   8239     }
   8240 #endif
   8241 
   8242     /* Allocate meter pool with free meters. */
   8243     BCM_IF_ERROR_RETURN(_field_meter_pool_alloc(unit, stage_fc, instance, f_pl,
   8244                                                  pool_slice_id, &pool_idx));
   8245     f_mp = stage_fc->meter_pool[instance][pool_idx];
   8246 
   8247     is_trident_plus_use_even_meter = 0;
   8248     if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) {
   8249         use_even_meter = soc_property_get(unit,
   8250                            spn_FP_EVEN_INDEX_FOR_INGRESS_FLOW_METER, 0);
   8251         if (use_even_meter) {
   8252             soc_cm_get_id(unit, &devid, &revid);
   8253             if ((devid == BCM56842_DEVICE_ID)||(devid == BCM56844_DEVICE_ID)||
   8254                 (devid == BCM56846_DEVICE_ID)||(devid == BCM56847_DEVICE_ID)||
   8255                 (devid == BCM56053_DEVICE_ID)||(devid == BCM56549_DEVICE_ID)||
   8256                 (devid == BCM56831_DEVICE_ID)||(devid == BCM56835_DEVICE_ID)||
   8257                 (devid == BCM56838_DEVICE_ID)||(devid == BCM56849_DEVICE_ID)
   8258                 ) {
   8259                 is_trident_plus_use_even_meter = 1;
   8260             }
   8261         }
   8262     }
   8263     /* Reserve unused meter. */
   8264     for (idx = 0; idx < f_mp->size; idx++) {
   8265 
   8266         /* Allocate meter indices for non-flow mode meters. */
   8267         if (!_FP_POLICER_IS_FLOW_MODE(f_pl)) {
   8268             if (is_trident_plus_use_even_meter) {
   8269                 return (BCM_E_PARAM);
   8270             }
   8271             if (0 != (idx % 2)) {
   8272                 /* skip odd meter indices */
   8273                 continue;
   8274             }
   8275 
   8276             if ((0 == _FP_METER_BMP_TEST(f_mp->meter_bmp, idx))
   8277                 && (0 == _FP_METER_BMP_TEST(f_mp->meter_bmp, idx + 1))) {
   8278                 _FP_METER_BMP_ADD(f_mp->meter_bmp, idx);
   8279                 _FP_METER_BMP_ADD(f_mp->meter_bmp, (idx + 1));
   8280                 /* Decrement free meters count in meter pool. */
   8281                 f_mp->free_meters -= 2;
   8282                 f_pl->pool_index = pool_idx ;
   8283                 f_pl->hw_index   = (idx / 2);
   8284                 return (BCM_E_NONE);
   8285             }
   8286         }
   8287 
   8288         /* Allocate hardware resources for flow mode meters. */
   8289         if (_FP_POLICER_IS_FLOW_MODE(f_pl)
   8290             && (0 == _FP_METER_BMP_TEST(f_mp->meter_bmp, idx))) {
   8291             if (is_trident_plus_use_even_meter) {
   8292                 if (0 != (idx % 2)) {
   8293                     /* skip odd meter indices. */
   8294                     continue;
   8295                 }
   8296             }
   8297             if (f_pl->hw_flags & _FP_POLICER_DIRTY) {
   8298                 f_pl->hw_flags &= (idx % 2)
   8299                                     ? ~_FP_POLICER_PEAK_DIRTY
   8300                                     : ~_FP_POLICER_COMMITTED_DIRTY;
   8301             } else {
   8302                 LOG_DEBUG(BSL_LS_BCM_FP,
   8303                           (BSL_META_U(unit,
   8304                                       "FP(unit %d) Error: Meter alloc called with invalid"
   8305                                        " hw_flags=%x\n"), unit, f_pl->hw_flags));
   8306                 return (BCM_E_INTERNAL);
   8307             }
   8308 
   8309             if (f_pl->hw_flags & _FP_POLICER_PEAK_DIRTY) {
   8310                 _FP_POLICER_EXCESS_HW_METER_SET(f_pl);
   8311             } else {
   8312                 _FP_POLICER_EXCESS_HW_METER_CLEAR(f_pl);
   8313             }
   8314 
   8315             _FP_METER_BMP_ADD(f_mp->meter_bmp, idx);
   8316 
   8317             /* Decrement free meter count in meter pool. */
   8318             if (is_trident_plus_use_even_meter) {
   8319                 f_mp->free_meters -= 2;
   8320             } else {
   8321                 f_mp->free_meters--;
   8322             }
   8323 
   8324             f_pl->pool_index =  pool_idx;
   8325             f_pl->hw_index   =  (idx / 2);
   8326             return (BCM_E_NONE);
   8327         }
   8328     }
   8329 
   8330     /* Never reached - pool alloc makes sure at least one meter is available. */
   8331     if (f_mp->free_meters == f_mp->size) {
   8332         BCM_IF_ERROR_RETURN(_field_meter_pool_free(unit, stage_fc, instance, pool_idx));
   8333     }
   8334     return (BCM_E_RESOURCE);
   8335 }
   8336 
   8337 /*
   8338  * Function:
   8339  *     _field_meterpool_hw_entry_alloc
   8340  *
   8341  * Purpose:
   8342  *     Allocate field entry meter from a meter pool.
   8343  *
   8344  * Parameters:
   8345  *     unit  - (IN) BCM device number.
   8346  *     f_ent - (IN) Field entry structure.
   8347  *     f_pl  - (IN) Field policer descriptor.
   8348  * Returns:
   8349  *     BCM_E_XXX
   8350  */
   8351 STATIC int
   8352 _field_meterpool_hw_entry_alloc (int unit, _field_entry_t *f_ent,
   8353                                  _field_policer_t *f_pl)
   8354 {
   8355     _field_stage_id_t      stage_id;  /* Stage id used for metering.          */
   8356     _field_stage_t         *stage_fc; /* Field stage control structure.       */
   8357     _field_group_t         *fg;       /* Field group structure.               */
   8358     uint8                  pool_sid;  /* Key to ensure single update per hit. */
   8359 
   8360     /* Input parameters check. */
   8361     if ((NULL == f_ent) || (NULL == f_pl)) {
   8362         return (BCM_E_PARAM);
   8363     }
   8364 
   8365     fg = f_ent->group;
   8366     stage_id = ((_BCM_FIELD_STAGE_EXTERNAL == fg->stage_id) || \
   8367                 (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id)) ? \
   8368                _BCM_FIELD_STAGE_INGRESS : fg->stage_id;
   8369 
   8370     /* Get meter pool stage control. */
   8371     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, stage_id, &stage_fc));
   8372 
   8373     /* Generate unique pool id.  */
   8374     if ((_BCM_FIELD_STAGE_EXTERNAL == fg->stage_id) ||
   8375         (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id)) {
   8376         pool_sid = stage_fc->tcam_slices;
   8377     } else {
   8378         pool_sid = fg->slices->slice_number;
   8379     }
   8380 
   8381     /* Allocate an entry within the pool. */
   8382     BCM_IF_ERROR_RETURN
   8383         (_field_meter_pool_entry_alloc(unit, stage_fc, 
   8384                                        f_ent->group->instance,
   8385                                        pool_sid, f_pl));
   8386 
   8387     return (BCM_E_NONE);
   8388 }
   8389 
   8390 STATIC int
   8391 _field_slice_meter_free_old(int unit, _field_entry_t *f_ent,
   8392                           _field_policer_t *f_pl)
   8393 {
   8394     _field_stage_t         *stage_fc; /* Field stage control structure. */
   8395     _field_slice_t         *fs;       /* Field slice structure.         */
   8396     int                     idx;
   8397 
   8398     if ((NULL == f_ent) || (NULL == f_pl)) {
   8399         return (BCM_E_PARAM);
   8400     }
   8401 
   8402     /* Get field stage control structure. */
   8403     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, f_ent->group->stage_id,
   8404                                                  &stage_fc));
   8405 
   8406     /* Get slice policer installed in. */
   8407     fs =  stage_fc->slices[f_ent->group->instance] + (f_pl->old_pool_index);
   8408 
   8409     /* Must be a valid meter index. */
   8410     if (f_pl->old_hw_index == _FP_INVALID_INDEX) {
   8411         return (BCM_E_INTERNAL);
   8412     }
   8413 
   8414     /* Determine even meter's index from meter pair index. */
   8415     idx = f_pl->old_hw_index * 2;
   8416 
   8417     /* Validate input hardware index. */
   8418     if ((idx >= fs->meters_count) || ((idx + 1) >= fs->meters_count)) {
   8419         return (BCM_E_INTERNAL);
   8420     }
   8421 
   8422     /* Mark meter as free in the slice. */
   8423     /*if not flow mode */
   8424     if (bcmPolicerModeCommitted != (f_pl)->old_mode) {
   8425         _FP_METER_BMP_REMOVE(fs->meter_bmp, idx);
   8426         _FP_METER_BMP_REMOVE(fs->meter_bmp, idx + 1);
   8427     } else {
   8428         /* if excess meter */
   8429         if ((bcmPolicerModeCommitted == (f_pl)->old_mode) &&
   8430                   ((f_pl)->old_hw_flags & _FP_POLICER_EXCESS_METER)) {
   8431             _FP_METER_BMP_REMOVE(fs->meter_bmp, idx);
   8432 
   8433         } else if ((bcmPolicerModeCommitted == (f_pl)->old_mode) &&
   8434                   (!((f_pl)->old_hw_flags & _FP_POLICER_EXCESS_METER))) {
   8435             _FP_METER_BMP_REMOVE(fs->meter_bmp, idx + 1);
   8436         }
   8437     }
   8438 
   8439     return (BCM_E_NONE);
   8440 }
   8441 /*
   8442  * Function:
   8443  *     _field_slice_meter_free
   8444  *
   8445  * Purpose:
   8446  *     Free slice meter.
   8447  *
   8448  * Parameters:
   8449  *     unit  - (IN) BCM device number.
   8450  *     f_ent - (IN) Field entry structure.
   8451  *     f_pl  - (IN) Field policer descriptor.
   8452  * Returns:
   8453  *     BCM_E_XXX
   8454  */
   8455 STATIC int
   8456 _field_slice_meter_free(int unit, _field_entry_t *f_ent,
   8457                           _field_policer_t *f_pl)
   8458 {
   8459     _field_stage_t         *stage_fc; /* Field stage control structure. */
   8460     _field_slice_t         *fs;       /* Field slice structure.         */
   8461     int                     idx;
   8462 
   8463     if ((NULL == f_ent) || (NULL == f_pl)) {
   8464         return (BCM_E_PARAM);
   8465     }
   8466 
   8467     /* Get field stage control structure. */
   8468     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, f_ent->group->stage_id,
   8469                                                  &stage_fc));
   8470 
   8471     /* Get slice policer installed in. */
   8472     fs =  stage_fc->slices[f_ent->group->instance] + (f_pl->pool_index);
   8473 
   8474     /* Must be a valid meter index. */
   8475     if (f_pl->hw_index == _FP_INVALID_INDEX) {
   8476         return (BCM_E_INTERNAL);
   8477     }
   8478 
   8479     /* Determine even meter's index from meter pair index. */
   8480     idx = f_pl->hw_index * 2;
   8481 
   8482     /* Validate input hardware index. */
   8483     if ((idx >= fs->meters_count) || ((idx + 1) >= fs->meters_count)) {
   8484         return (BCM_E_INTERNAL);
   8485     }
   8486 
   8487     /* Mark meter as free in the slice. */
   8488     if (!_FP_POLICER_IS_FLOW_MODE(f_pl)) {
   8489         _FP_METER_BMP_REMOVE(fs->meter_bmp, idx);
   8490         _FP_METER_BMP_REMOVE(fs->meter_bmp, idx + 1);
   8491     } else {
   8492 
   8493         if (_FP_POLICER_EXCESS_HW_METER(f_pl)) {
   8494             _FP_METER_BMP_REMOVE(fs->meter_bmp, idx);
   8495 
   8496             /* Clear excess meter flag bit. */
   8497             _FP_POLICER_EXCESS_HW_METER_CLEAR(f_pl);
   8498         } else if (_FP_POLICER_COMMITTED_HW_METER(f_pl)) {
   8499             _FP_METER_BMP_REMOVE(fs->meter_bmp, idx + 1);
   8500         }
   8501     }
   8502 
   8503     f_pl->hw_index   = _FP_INVALID_INDEX;
   8504     f_pl->pool_index = _FP_INVALID_INDEX;
   8505     return (BCM_E_NONE);
   8506 }
   8507 
   8508 /*
   8509  * Function:
   8510  *     _field_slice_meter_alloc
   8511  *
   8512  * Purpose:
   8513  *     Allocate a policer for an entry from a slice.
   8514  *
   8515  * Parameters:
   8516  *     unit      - (IN) BCM device number.
   8517  *     fs        - (IN) Slice policer will be installed in.
   8518  *     f_pl      - (IN) Policer descriptor.
   8519  * Returns:
   8520  *     BCM_E_XXX
   8521  */
   8522 STATIC int
   8523 _field_slice_meter_alloc(int unit, _field_slice_t *fs, _field_policer_t *f_pl)
   8524 {
   8525     int              idx;          /* Policer iteration index. */
   8526 
   8527     /* Input parameters check. */
   8528     if ((NULL == f_pl) || (NULL == fs)) {
   8529         return (BCM_E_PARAM);
   8530     }
   8531 
   8532     /* Find unused meter in the slice. */
   8533     for (idx = 0; idx < fs->meters_count; idx++) {
   8534 
   8535         /* Allocate a meter pair for non-flow mode policer. */
   8536         if (!_FP_POLICER_IS_FLOW_MODE(f_pl)) {
   8537 
   8538             if (0 != (idx % 2)) {
   8539                 /* skip odd meter indices. */
   8540                 continue;
   8541             }
   8542 
   8543             if ((0 == _FP_METER_BMP_TEST(fs->meter_bmp, idx))
   8544                 && (0 == _FP_METER_BMP_TEST(fs->meter_bmp, idx + 1))) {
   8545                 _FP_METER_BMP_ADD(fs->meter_bmp, idx);
   8546                 _FP_METER_BMP_ADD(fs->meter_bmp, (idx + 1));
   8547                 f_pl->pool_index =  fs->slice_number;
   8548                 f_pl->cfg.pool_id = f_pl->pool_index;
   8549                 f_pl->hw_index   =  (idx / 2) ;
   8550                 break;
   8551             }
   8552         }
   8553 
   8554         /* Allocate a meter from meter pair for flow mode meters. */
   8555         if (_FP_POLICER_IS_FLOW_MODE(f_pl)
   8556             && (0 == _FP_METER_BMP_TEST(fs->meter_bmp, idx))) {
   8557             if (f_pl->hw_flags & _FP_POLICER_DIRTY) {
   8558                 f_pl->hw_flags &= (idx % 2)
   8559                                     ? ~_FP_POLICER_PEAK_DIRTY
   8560                                     : ~_FP_POLICER_COMMITTED_DIRTY;
   8561             } else {
   8562                 /* Meter move operation, flag is set here. */
   8563                 f_pl->hw_flags |= (idx % 2)
   8564                                     ? _FP_POLICER_COMMITTED_DIRTY
   8565                                     : _FP_POLICER_PEAK_DIRTY;
   8566             }
   8567 
   8568             if (f_pl->hw_flags & _FP_POLICER_PEAK_DIRTY) {
   8569                 _FP_POLICER_EXCESS_HW_METER_SET(f_pl);
   8570             } else {
   8571                 _FP_POLICER_EXCESS_HW_METER_CLEAR(f_pl);
   8572             }
   8573 
   8574             _FP_METER_BMP_ADD(fs->meter_bmp, idx);
   8575             f_pl->pool_index =  fs->slice_number;
   8576             f_pl->cfg.pool_id = f_pl->pool_index;
   8577             f_pl->hw_index   =  (idx / 2);
   8578             break;
   8579         }
   8580     }
   8581 
   8582     if (idx == fs->meters_count) {
   8583         return (BCM_E_RESOURCE);
   8584     }
   8585     return (BCM_E_NONE);
   8586 }
   8587 
   8588 
   8589 STATIC int
   8590 _field_meter_hw_free_old(int unit, _field_entry_t *f_ent)
   8591 {
   8592     _field_stage_t         *stage_fc;    /* Field stage control.            */
   8593     _field_entry_policer_t *f_ent_pl;    /* Field entry policer structure.  */
   8594     _field_policer_t       *f_pl;        /* Policer descriptor.             */
   8595     _field_group_t         *fg;          /* Field group structure.          */
   8596     int                     rv;          /* Operation return status.        */
   8597 
   8598     /* Input parameters check. */
   8599     if (NULL == f_ent) {
   8600         return (BCM_E_PARAM);
   8601     }
   8602 
   8603     f_ent_pl = f_ent->policer;
   8604     fg = f_ent->group;
   8605 
   8606     /* Get stage control structure. */
   8607     rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc);
   8608     BCM_IF_ERROR_RETURN(rv);
   8609 
   8610     /* Read policer configuration.*/
   8611     BCM_IF_ERROR_RETURN(_bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl));
   8612 
   8613     /* Policer slice index sanity check. */
   8614     if ((f_pl->old_pool_index >= stage_fc->tcam_slices)
   8615         || (f_pl->old_pool_index == _FP_INVALID_INDEX)) {
   8616         return (BCM_E_INTERNAL);
   8617     }
   8618 
   8619     /* Free policer id. */
   8620     rv = _field_slice_meter_free_old(unit, f_ent, f_pl);
   8621 
   8622     return (rv);
   8623 }
   8624 /*
   8625  * Function:
   8626  *     _field_meter_hw_free
   8627  *
   8628  * Purpose:
   8629  *     Deallocate a policer from an entry slice.
   8630  *
   8631  * Parameters:
   8632  *     unit      - (IN) BCM device number.
   8633  *     f_ent     - (IN/OUT) Entry policer belongs to.
   8634  * Returns:
   8635  *     BCM_E_XXX
   8636  */
   8637 STATIC int
   8638 _field_meter_hw_free(int unit, _field_entry_t *f_ent)
   8639 {
   8640     _field_stage_t         *stage_fc;    /* Field stage control.            */
   8641     _field_entry_policer_t *f_ent_pl;    /* Field entry policer structure.  */
   8642     uint8                  entry_part;   /* Secondary entry part.           */
   8643     _field_policer_t       *f_pl;        /* Policer descriptor.             */
   8644     _field_group_t         *fg;          /* Field group structure.          */
   8645     int                     rv;          /* Operation return status.        */
   8646 
   8647     /* Input parameters check. */
   8648     if (NULL == f_ent) {
   8649         return (BCM_E_PARAM);
   8650     }
   8651 
   8652     f_ent_pl = f_ent->policer;
   8653     fg = f_ent->group;
   8654 
   8655     /* Get stage control structure. */
   8656     rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc);
   8657     BCM_IF_ERROR_RETURN(rv);
   8658 
   8659     /* Read policer configuration.*/
   8660     BCM_IF_ERROR_RETURN(_bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl));
   8661 
   8662     /* Policer slice index sanity check. */
   8663     if ((f_pl->pool_index >= stage_fc->tcam_slices)
   8664         || (f_pl->pool_index == _FP_INVALID_INDEX)) {
   8665         return (BCM_E_INTERNAL);
   8666     }
   8667 
   8668     /* Free policer id. */
   8669     rv = _field_slice_meter_free(unit, f_ent, f_pl);
   8670 
   8671     /* Reset entry policer related flags. */
   8672     if (f_ent->flags & _FP_ENTRY_POLICER_IN_SECONDARY_SLICE) {
   8673         /* Get primary entry from the second slice. */
   8674         rv = _bcm_field_entry_flags_to_tcam_part(unit, _FP_ENTRY_SECONDARY,
   8675                                                   fg, &entry_part);
   8676         BCM_IF_ERROR_RETURN(rv);
   8677         sal_memset(f_ent[entry_part].policer, 0, sizeof(_field_entry_policer_t));
   8678         f_ent->flags &=  ~_FP_ENTRY_POLICER_IN_SECONDARY_SLICE;
   8679     }
   8680     return (rv);
   8681 }
   8682 
   8683 /*
   8684  * Function:
   8685  *     _field_meter_hw_alloc
   8686  *
   8687  * Purpose:
   8688  *     Allocate a policer/s for an entry from a slice.
   8689  *
   8690  * Parameters:
   8691  *     unit      - (IN) BCM device number.
   8692  *     f_ent     - (IN/OUT) Entry array policer belongs to.
   8693  *     fs        - (IN) Desired slice for the policer.
   8694  * Returns:
   8695  *     BCM_E_XXX
   8696  */
   8697 STATIC int
   8698 _field_meter_hw_alloc(int unit, _field_entry_t *f_ent, _field_slice_t *fs)
   8699 {
   8700     _field_entry_policer_t *f_ent_pl;           /* Field entry policer .     */
   8701     _field_policer_t       *f_pl;               /* Policer descriptor.       */
   8702     _field_group_t         *fg;                 /* Field group structure.    */
   8703     uint8                  entry_part;          /* Field entry tcam part .   */
   8704     int                    rv = BCM_E_RESOURCE; /* Operation return status.  */
   8705 
   8706     /* Input parameters check. */
   8707     if ((NULL == f_ent) || (NULL == fs)) {
   8708         return (BCM_E_PARAM);
   8709     }
   8710 
   8711     f_ent_pl = f_ent->policer;
   8712 
   8713     /* Reject unused policers. */
   8714     if (0 == (f_ent_pl->flags & _FP_POLICER_VALID)) {
   8715         return (BCM_E_PARAM);
   8716     }
   8717 
   8718     /* Read policer configuration. */
   8719     BCM_IF_ERROR_RETURN(_bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl));
   8720 
   8721     /*
   8722      *  Allocate meter from a primary slice unless color dependent counter
   8723      *  is only availabe in secondary slice
   8724      */
   8725     if (0 == (f_ent->flags & _FP_ENTRY_ALLOC_FROM_SECONDARY_SLICE)) {
   8726         rv = _field_slice_meter_alloc(unit, fs, f_pl);
   8727     }
   8728     if (BCM_E_RESOURCE == rv)  {
   8729         fg = f_ent->group;
   8730 
   8731         /* Double/Triple wide groups might allocate from secondary slice. */
   8732         if ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE)
   8733             || (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE)) {
   8734 
   8735             rv = _field_slice_meter_alloc(unit, fs + 1, f_pl);
   8736             if (BCM_SUCCESS(rv)) {
   8737 
   8738                 /* Get primary entry from the second slice. */
   8739                 rv = _bcm_field_entry_flags_to_tcam_part (unit,
   8740                                                          _FP_ENTRY_SECONDARY,
   8741                                                         fg, &entry_part);
   8742                 BCM_IF_ERROR_RETURN(rv);
   8743 
   8744                 f_ent->flags |= _FP_ENTRY_POLICER_IN_SECONDARY_SLICE;
   8745                 sal_memcpy(f_ent[entry_part].policer, f_ent->policer,
   8746                            sizeof(_field_entry_policer_t));
   8747                 f_ent[entry_part].policer->flags |= _FP_POLICER_INSTALLED;
   8748             }
   8749         }
   8750     }
   8751     return (rv);
   8752 }
   8753 /* Clear the hardware entries of the meter table */
   8754 STATIC int
   8755 _field_meter_hw_clear(int unit, _field_entry_t *f_ent,
   8756                                  int old_hw_index, bcm_policer_mode_t old_mode,
   8757                                  int old_pool_index, uint32 old_hw_flags)
   8758 
   8759 {
   8760     _field_stage_t    *stage_fc;        /* Stage field control structure */
   8761     soc_mem_t          meter_table_x;   /* Meter table name              */
   8762     soc_mem_t          meter_table_y;   /* Meter table name              */
   8763     soc_mem_t          meter_table;     /* Meter table name              */
   8764     int                meter_idx;       /* Meter hw index                */
   8765     int                idx;             /* Meter hw index                */
   8766     int                rv = BCM_E_NONE; /* Return value                  */
   8767     int                iter = 0;        /* Iteration count               */
   8768 
   8769 
   8770     meter_table_x = INVALIDm;
   8771     meter_table_y = INVALIDm;
   8772     /* Get field stage control structure. */
   8773     BCM_IF_ERROR_RETURN
   8774         (_field_stage_control_get(unit, f_ent->group->stage_id,
   8775                                   &stage_fc));
   8776 
   8777     if ((f_ent->group->stage_id != _BCM_FIELD_STAGE_EGRESS) ||
   8778         (!(SOC_IS_TRIDENT2PLUS(unit)))) {
   8779         return BCM_E_NONE;
   8780     }
   8781     /* Resolve meter table name. */
   8782 #if defined(BCM_TRX_SUPPORT)
   8783     if (SOC_IS_TRX(unit)) {
   8784         BCM_IF_ERROR_RETURN
   8785             (_field_trx_meter_table_get(unit, f_ent->fs->stage_id,
   8786                                         &meter_table_x, &meter_table_y));
   8787     } else
   8788 #endif
   8789     {
   8790 #if defined(BCM_FIREBOLT_SUPPORT) ||defined(BCM_RAPTOR_SUPPORT)
   8791         BCM_IF_ERROR_RETURN
   8792             (_field_fb_policer_mem_get (unit, f_ent, &meter_table_x));
   8793 #endif
   8794     }
   8795 
   8796 
   8797     /* Must be a valid meter index. */
   8798     if (old_hw_index == _FP_INVALID_INDEX) {
   8799         return (BCM_E_INTERNAL);
   8800     }
   8801 
   8802 
   8803     idx = stage_fc->slices[f_ent->group->instance]
   8804                               [old_pool_index].start_tcam_idx
   8805                               + (2 * old_hw_index);
   8806 
   8807     meter_idx = idx;
   8808     for (iter = 0; iter < 2; iter++) {
   8809         idx = meter_idx;
   8810 
   8811         if (0 == iter) {
   8812             meter_table = meter_table_x;
   8813         } else {
   8814             meter_table = meter_table_y;
   8815         }
   8816 
   8817         if (meter_table == INVALIDm) {
   8818             continue;
   8819         }
   8820 
   8821         if (idx < soc_mem_index_min(unit, meter_table) ||
   8822             idx > soc_mem_index_max(unit, meter_table)) {
   8823             return (BCM_E_INTERNAL);
   8824         }
   8825 
   8826         if (!(bcmPolicerModeCommitted == old_mode)) {
   8827             rv = soc_mem_write(unit, meter_table, MEM_BLOCK_ALL,
   8828                     idx, soc_mem_entry_null(unit,meter_table));
   8829             BCM_IF_ERROR_RETURN(rv);
   8830 
   8831             idx++;
   8832             rv = soc_mem_write(unit, meter_table, MEM_BLOCK_ALL,
   8833                     idx, soc_mem_entry_null(unit,meter_table));
   8834         } else {
   8835             if ((bcmPolicerModeCommitted == old_mode) &&
   8836                 (!(old_hw_flags & _FP_POLICER_EXCESS_METER))) {
   8837                 idx ++;
   8838             }
   8839 
   8840             rv = soc_mem_write(unit, meter_table, MEM_BLOCK_ALL,
   8841                     idx, soc_mem_entry_null(unit,meter_table));
   8842         }
   8843     }
   8844 
   8845     return (BCM_E_NONE);
   8846 }
   8847 
   8848 STATIC int
   8849 _field_policer_meter_hw_free_old(int unit, _field_entry_t *f_ent,
   8850                              _field_entry_policer_t *f_ent_pl)
   8851 {
   8852     _field_stage_t    *stage_fc;        /* Stage field control structure */
   8853     _field_policer_t  *f_pl;            /* Policer descriptor            */
   8854     soc_mem_t          meter_table_x;   /* Meter table name              */
   8855     soc_mem_t          meter_table_y;   /* Meter table name              */
   8856     soc_mem_t          meter_table;     /* Meter table name              */
   8857     int                meter_idx;       /* Meter hw index                */
   8858     int                idx;             /* Meter hw index                */
   8859     int                rv = BCM_E_NONE; /* Return value                  */
   8860     int                iter = 0;        /* Iteration count               */
   8861 
   8862 
   8863     meter_table_x = INVALIDm;
   8864     meter_table_y = INVALIDm;
   8865     /* Get field stage control structure. */
   8866     BCM_IF_ERROR_RETURN
   8867         (_field_stage_control_get(unit, f_ent->group->stage_id,
   8868                                   &stage_fc));
   8869 
   8870 #if defined(BCM_TOMAHAWK_SUPPORT)
   8871     if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
   8872         return _bcm_field_th_policer_meter_hw_free_old(unit, f_ent, f_ent_pl);
   8873     }
   8874 #endif
   8875 
   8876     /* Resolve meter table name. */
   8877 #if defined(BCM_TRX_SUPPORT)
   8878     if (SOC_IS_TRX(unit)) {
   8879         BCM_IF_ERROR_RETURN
   8880             (_field_trx_meter_table_get(unit, f_ent->fs->stage_id,
   8881                                         &meter_table_x, &meter_table_y));
   8882     } else
   8883 #endif
   8884     {
   8885 #if defined(BCM_FIREBOLT_SUPPORT) ||defined(BCM_RAPTOR_SUPPORT)
   8886         BCM_IF_ERROR_RETURN
   8887             (_field_fb_policer_mem_get (unit, f_ent, &meter_table_x));
   8888 #endif
   8889     }
   8890 
   8891     /* Read policer configuration.*/
   8892     BCM_IF_ERROR_RETURN
   8893         (_bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl));
   8894 
   8895     /* Must be a valid meter index. */
   8896     if (f_pl->hw_index == _FP_INVALID_INDEX) {
   8897         return (BCM_E_INTERNAL);
   8898     }
   8899 
   8900     if (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) {
   8901         /* Get slice policer installed in. */
   8902         idx =  (f_pl->old_pool_index *
   8903                 stage_fc->meter_pool[f_ent->group->instance]
   8904                                     [f_pl->old_pool_index]->pool_size)
   8905                 + (2 * f_pl->old_hw_index);
   8906 
   8907     } else {
   8908         idx = stage_fc->slices[f_ent->group->instance]
   8909                               [f_pl->old_pool_index].start_tcam_idx
   8910                               + (2 * f_pl->old_hw_index);
   8911     }
   8912 
   8913     meter_idx = idx;
   8914     for (iter = 0; iter < 2; iter++) {
   8915         idx = meter_idx;
   8916 
   8917         if (0 == iter) {
   8918             meter_table = meter_table_x;
   8919         } else {
   8920             meter_table = meter_table_y;
   8921         }
   8922 
   8923         if (meter_table == INVALIDm) {
   8924             continue;
   8925         }
   8926 
   8927         if (idx < soc_mem_index_min(unit, meter_table) ||
   8928             idx > soc_mem_index_max(unit, meter_table)) {
   8929             return (BCM_E_INTERNAL);
   8930         }
   8931         /* if not flow mode */
   8932         if (bcmPolicerModeCommitted != (f_pl)->old_mode) {
   8933             rv = soc_mem_write(unit, meter_table, MEM_BLOCK_ALL,
   8934                     idx, soc_mem_entry_null(unit,meter_table));
   8935             BCM_IF_ERROR_RETURN(rv);
   8936 
   8937             idx++;
   8938             rv = soc_mem_write(unit, meter_table, MEM_BLOCK_ALL,
   8939                     idx, soc_mem_entry_null(unit,meter_table));
   8940         } else {
   8941             /* if committed meter */
   8942             if ((bcmPolicerModeCommitted == (f_pl)->old_mode) &&
   8943                   (!((f_pl)->old_hw_flags & _FP_POLICER_EXCESS_METER))) {
   8944                 idx ++;
   8945             }
   8946 
   8947             rv = soc_mem_write(unit, meter_table, MEM_BLOCK_ALL,
   8948                     idx, soc_mem_entry_null(unit,meter_table));
   8949         }
   8950     }
   8951 
   8952     return (BCM_E_NONE);
   8953 }
   8954 /*
   8955  * Function:
   8956  *     _field_policer_meter_hw_free
   8957  *
   8958  * Purpose:
   8959  *     Clear the meter entries from the h/w associated with the policer
   8960  *
   8961  * Parameters:
   8962  *     unit      - (IN) BCM device number.
   8963  *     level     - (IN) Policer level.
   8964  *     f_ent     - (IN) Entry policer belongs to.
   8965  * Returns:
   8966  *     BCM_E_XXX
   8967  */
   8968 STATIC int
   8969 _field_policer_meter_hw_free(int unit, _field_entry_t *f_ent,
   8970                              _field_entry_policer_t *f_ent_pl)
   8971 {
   8972     _field_stage_t    *stage_fc;        /* Stage field control structure */
   8973     _field_policer_t  *f_pl;            /* Policer descriptor            */
   8974     soc_mem_t          meter_table_x;   /* Meter table name              */
   8975     soc_mem_t          meter_table_y;   /* Meter table name              */
   8976     soc_mem_t          meter_table;     /* Meter table name              */
   8977     int                meter_idx;       /* Meter hw index                */
   8978     int                idx;             /* Meter hw index                */
   8979     int                rv = BCM_E_NONE; /* Return value                  */
   8980     int                iter = 0;        /* Iteration count               */
   8981 
   8982 
   8983     meter_table_x = INVALIDm;
   8984     meter_table_y = INVALIDm;
   8985     /* Get field stage control structure. */
   8986     BCM_IF_ERROR_RETURN
   8987         (_field_stage_control_get(unit, f_ent->group->stage_id,
   8988                                   &stage_fc));
   8989 
   8990 #if defined(BCM_TOMAHAWK_SUPPORT)
   8991     if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
   8992         return _bcm_field_th_policer_meter_hw_free(unit, f_ent, f_ent_pl);
   8993     }
   8994 #endif
   8995 
   8996     /* Resolve meter table name. */
   8997 #if defined(BCM_TRX_SUPPORT)
   8998     if (SOC_IS_TRX(unit)) {
   8999         BCM_IF_ERROR_RETURN
   9000             (_field_trx_meter_table_get(unit, f_ent->fs->stage_id,
   9001                                         &meter_table_x, &meter_table_y));
   9002     } else
   9003 #endif
   9004     {
   9005 #if defined(BCM_FIREBOLT_SUPPORT) ||defined(BCM_RAPTOR_SUPPORT)
   9006         BCM_IF_ERROR_RETURN
   9007             (_field_fb_policer_mem_get (unit, f_ent, &meter_table_x));
   9008 #endif
   9009     }
   9010 
   9011     /* Read policer configuration.*/
   9012     BCM_IF_ERROR_RETURN
   9013         (_bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl));
   9014 
   9015     /* Must be a valid meter index. */
   9016     if (f_pl->hw_index == _FP_INVALID_INDEX) {
   9017         return (BCM_E_INTERNAL);
   9018     }
   9019 
   9020     if (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) {
   9021         /* Get slice policer installed in. */
   9022         idx =  (f_pl->pool_index *
   9023                 stage_fc->meter_pool[f_ent->group->instance]
   9024                                     [f_pl->pool_index]->pool_size)
   9025                 + (2 * f_pl->hw_index);
   9026 
   9027     } else {
   9028         idx = stage_fc->slices[f_ent->group->instance]
   9029                               [f_pl->pool_index].start_tcam_idx
   9030                               + (2 * f_pl->hw_index);
   9031     }
   9032 
   9033     meter_idx = idx;
   9034     for (iter = 0; iter < 2; iter++) {
   9035         idx = meter_idx;
   9036 
   9037         if (0 == iter) {
   9038             meter_table = meter_table_x;
   9039         } else {
   9040             meter_table = meter_table_y;
   9041         }
   9042 
   9043         if (meter_table == INVALIDm) {
   9044             continue;
   9045         }
   9046 
   9047         if (idx < soc_mem_index_min(unit, meter_table) ||
   9048             idx > soc_mem_index_max(unit, meter_table)) {
   9049             return (BCM_E_INTERNAL);
   9050         }
   9051 
   9052         if (!_FP_POLICER_IS_FLOW_MODE(f_pl)) {
   9053             rv = soc_mem_write(unit, meter_table, MEM_BLOCK_ALL,
   9054                     idx, soc_mem_entry_null(unit,meter_table));
   9055             BCM_IF_ERROR_RETURN(rv);
   9056 
   9057             idx++;
   9058             rv = soc_mem_write(unit, meter_table, MEM_BLOCK_ALL,
   9059                     idx, soc_mem_entry_null(unit,meter_table));
   9060         } else {
   9061             if (_FP_POLICER_COMMITTED_HW_METER(f_pl)) {
   9062                 idx ++;
   9063             }
   9064 
   9065             rv = soc_mem_write(unit, meter_table, MEM_BLOCK_ALL,
   9066                     idx, soc_mem_entry_null(unit,meter_table));
   9067         }
   9068     }
   9069 
   9070     return (BCM_E_NONE);
   9071 }
   9072 
   9073 STATIC int
   9074 _field_policer_hw_free_old(int unit, uint8 level, _field_entry_t *f_ent)
   9075 {
   9076     _field_entry_policer_t *f_ent_pl;  /* Field entry policer structure. */
   9077     _field_stage_t         *stage_fc;  /* Stage field contol.            */
   9078     _field_policer_t       *f_pl;      /* Policer descriptor.            */
   9079     _field_stage_id_t      stage_id;  /* Stage id used for metering.          */
   9080     /* allocate even meter index for ingress metering for flow mode.
   9081      * If set, the non-flow mode is disabled. Is available only for
   9082      * Trident+ devices as there is an issue with metering on Y-pipe ports
   9083      */
   9084     int                    use_even_meter;
   9085     int                    is_trident_plus_use_even_meter;
   9086     uint16                 devid;
   9087     uint8                  revid;
   9088 
   9089     /* Input parameters check. */
   9090     if ((NULL == f_ent) || (level >= _FP_POLICER_LEVEL_COUNT)) {
   9091         return (BCM_E_PARAM);
   9092     }
   9093 
   9094     f_ent_pl = f_ent->policer + level;
   9095 
   9096     if ((f_ent_pl->flags & _FP_POLICER_VALID) == 0 ) {
   9097         return (BCM_E_NONE);
   9098     } else {
   9099         /* Read policer configuration.*/
   9100         BCM_IF_ERROR_RETURN
   9101             (_bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl));
   9102 
   9103         /* Decrement policer reference counter. */
   9104         f_pl->old_sw_ref_count--;
   9105 
   9106     }
   9107 
   9108     /* Read policer configuration.*/
   9109     BCM_IF_ERROR_RETURN(_bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl));
   9110 
   9111     /* Decrement hw reference count. */
   9112     if (f_pl->old_hw_ref_count > 0) {
   9113         f_pl->old_hw_ref_count--;
   9114     }
   9115 
   9116     /* Policer not used by any other entry. */
   9117     if (f_pl->old_hw_ref_count == 0) {
   9118 
   9119         stage_id = (_BCM_FIELD_STAGE_EXACTMATCH == f_ent->group->stage_id) ? \
   9120                    _BCM_FIELD_STAGE_INGRESS : f_ent->group->stage_id;
   9121 
   9122         /* Deinstall policer from hw. */
   9123         BCM_IF_ERROR_RETURN
   9124             (_field_stage_control_get(unit, stage_id, &stage_fc));
   9125 
   9126         _field_policer_meter_hw_free_old(unit, f_ent, f_ent_pl);
   9127         /* Mark hw resource as unused in sw. */
   9128         if (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) {
   9129             BCM_IF_ERROR_RETURN
   9130                 (_field_meter_pool_entry_free_old(unit, stage_fc,
   9131                                               f_ent->group->instance, f_pl));
   9132         } else {
   9133             BCM_IF_ERROR_RETURN(_field_meter_hw_free_old(unit, f_ent));
   9134         }
   9135 
   9136         is_trident_plus_use_even_meter = 0;
   9137         if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) {
   9138             use_even_meter = soc_property_get(unit,
   9139                            spn_FP_EVEN_INDEX_FOR_INGRESS_FLOW_METER, 0);
   9140             if (use_even_meter) {
   9141                 soc_cm_get_id(unit, &devid, &revid);
   9142                 if ((devid == BCM56842_DEVICE_ID)||
   9143                     (devid == BCM56844_DEVICE_ID)||
   9144                     (devid == BCM56846_DEVICE_ID)||
   9145                     (devid == BCM56847_DEVICE_ID)||
   9146                     (devid == BCM56053_DEVICE_ID)||
   9147                     (devid == BCM56549_DEVICE_ID)||
   9148                     (devid == BCM56831_DEVICE_ID)||
   9149                     (devid == BCM56835_DEVICE_ID)||
   9150                     (devid == BCM56838_DEVICE_ID)||
   9151                     (devid == BCM56849_DEVICE_ID)
   9152                     ) {
   9153                     is_trident_plus_use_even_meter = 1;
   9154                 }
   9155             }
   9156         }
   9157         /* decrement group meter count when the hw_ref_count
   9158            becomes 0 */
   9159         f_ent->group->group_status.meter_count--;
   9160         /* for flow mode, 1 meter is associated to group
   9161            and for all other modes, 2 meters are associated */
   9162         if(bcmPolicerModeCommitted != (f_pl)->old_mode) {
   9163             f_ent->group->group_status.meter_count--;
   9164         }
   9165 
   9166         if(bcmPolicerModeCommitted == (f_pl)->old_mode) {
   9167             if (is_trident_plus_use_even_meter) {
   9168                 f_ent->group->group_status.meter_count--;
   9169             }
   9170         }
   9171         /*reset the old ploicer data stored to default */
   9172         sal_memset(&f_pl->old_cfg, 0x00, sizeof(bcm_policer_config_t));
   9173         f_pl->old_hw_flags = 0;
   9174 #ifdef    BCM_TRIUMPH3_SUPPORT
   9175         f_pl->old_logical_pool_index = _FP_INVALID_INDEX;
   9176 #endif
   9177         f_pl->old_mode = 0;
   9178         f_pl->old_pool_index = _FP_INVALID_INDEX;
   9179         f_pl->old_level = 0;
   9180         f_pl->old_hw_index = _FP_INVALID_INDEX;
   9181         f_pl->old_sw_ref_count = 0;
   9182         f_pl->old_hw_ref_count = 0;
   9183     }
   9184 
   9185     /* Decrement policer reference counter. */
   9186     f_pl->old_sw_ref_count--;
   9187 
   9188     return (BCM_E_NONE);
   9189 }
   9190 
   9191 STATIC int
   9192 _field_policer_hw_free(int unit, uint8 level, _field_entry_t *f_ent)
   9193 {
   9194     _field_entry_policer_t *f_ent_pl;  /* Field entry policer structure. */
   9195     _field_stage_t         *stage_fc;  /* Stage field contol.            */
   9196     _field_policer_t       *f_pl;      /* Policer descriptor.            */
   9197     _field_stage_id_t      stage_id;  /* Stage id used for metering.          */
   9198     /* allocate even meter index for ingress metering for flow mode.
   9199      * If set, the non-flow mode is disabled. Is available only for
   9200      * Trident+ devices as there is an issue with metering on Y-pipe ports
   9201      */
   9202     int                    use_even_meter;
   9203     int                    is_trident_plus_use_even_meter;
   9204     uint16                 devid;
   9205     uint8                  revid;
   9206 
   9207     /* Input parameters check. */
   9208     if ((NULL == f_ent) || (level >= _FP_POLICER_LEVEL_COUNT)) {
   9209         return (BCM_E_PARAM);
   9210     }
   9211 
   9212     f_ent_pl = f_ent->policer + level;
   9213 
   9214     if (f_ent_pl->flags & _FP_POLICER_INSTALLED) {
   9215         f_ent_pl->flags = _FP_POLICER_DETACH;
   9216         return (BCM_E_NONE);
   9217     } else {
   9218         if (0 == (f_ent_pl->flags & _FP_POLICER_DETACH)) {
   9219             /* Read policer configuration.*/
   9220             BCM_IF_ERROR_RETURN
   9221                 (_bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl));
   9222 
   9223             /* Decrement policer reference counter. */
   9224             f_pl->sw_ref_count--;
   9225 
   9226             f_ent_pl->pid   = _FP_INVALID_INDEX;
   9227             f_ent_pl->flags = 0;
   9228 
   9229             return (BCM_E_NONE);
   9230         }
   9231     }
   9232 
   9233     /* Read policer configuration.*/
   9234     BCM_IF_ERROR_RETURN(_bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl));
   9235 
   9236     /* Decrement hw reference count. */
   9237     if (f_pl->hw_ref_count > 0) {
   9238         f_pl->hw_ref_count--;
   9239     }
   9240 
   9241     /* Policer not used by any other entry. */
   9242     if (f_pl->hw_ref_count == 0) {
   9243 
   9244         stage_id = (_BCM_FIELD_STAGE_EXACTMATCH == f_ent->group->stage_id) ? \
   9245                    _BCM_FIELD_STAGE_INGRESS : f_ent->group->stage_id;
   9246 
   9247         /* Deinstall policer from hw. */
   9248         BCM_IF_ERROR_RETURN
   9249             (_field_stage_control_get(unit, stage_id, &stage_fc));
   9250 
   9251         _field_policer_meter_hw_free(unit, f_ent, f_ent_pl);
   9252         /* Mark hw resource as unused in sw. */
   9253         if (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) {
   9254             BCM_IF_ERROR_RETURN
   9255                 (_field_meter_pool_entry_free(unit, stage_fc,
   9256                                               f_ent->group->instance, f_pl));
   9257         } else {
   9258             BCM_IF_ERROR_RETURN(_field_meter_hw_free(unit, f_ent));
   9259         }
   9260 
   9261         is_trident_plus_use_even_meter = 0;
   9262         if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) {
   9263             use_even_meter = soc_property_get(unit,
   9264                            spn_FP_EVEN_INDEX_FOR_INGRESS_FLOW_METER, 0);
   9265             if (use_even_meter) {
   9266                 soc_cm_get_id(unit, &devid, &revid);
   9267                 if ((devid == BCM56842_DEVICE_ID)||
   9268                     (devid == BCM56844_DEVICE_ID)||
   9269                     (devid == BCM56846_DEVICE_ID)||
   9270                     (devid == BCM56847_DEVICE_ID)||
   9271                     (devid == BCM56053_DEVICE_ID)||
   9272                     (devid == BCM56549_DEVICE_ID)||
   9273                     (devid == BCM56831_DEVICE_ID)||
   9274                     (devid == BCM56835_DEVICE_ID)||
   9275                     (devid == BCM56838_DEVICE_ID)||
   9276                     (devid == BCM56849_DEVICE_ID)
   9277                     ) {
   9278                     is_trident_plus_use_even_meter = 1;
   9279                 }
   9280             }
   9281         }
   9282         /* decrement group meter count when the hw_ref_count
   9283            becomes 0 */
   9284         f_ent->group->group_status.meter_count--;
   9285         /* for flow mode, 1 meter is associated to group
   9286            and for all other modes, 2 meters are associated */
   9287         if(!_FP_POLICER_IS_FLOW_MODE(f_pl)) {
   9288             f_ent->group->group_status.meter_count--;
   9289         }
   9290 
   9291         if(_FP_POLICER_IS_FLOW_MODE(f_pl)) {
   9292             if (is_trident_plus_use_even_meter) {
   9293                 f_ent->group->group_status.meter_count--;
   9294             }
   9295         }
   9296         /* Mark policer for reinstallation. */
   9297         BCM_IF_ERROR_RETURN (_field_policer_hw_flags_set(unit, f_pl, 0));
   9298     }
   9299 
   9300     /* Decrement policer reference counter. */
   9301     f_pl->sw_ref_count--;
   9302 
   9303     f_ent_pl->pid   = _FP_INVALID_INDEX;
   9304     f_ent_pl->flags = 0;
   9305 
   9306     return (BCM_E_NONE);
   9307 }
   9308 
   9309 /*
   9310  * Function:
   9311  *     _field_policers_hw_alloc
   9312  *
   9313  * Purpose:
   9314  *     Allocate policers required for entry installation.
   9315  *
   9316  * Parameters:
   9317  *     unit      - (IN) BCM device number.
   9318  *     f_ent     - (IN) Field entry array.
   9319  * Returns:
   9320  *     BCM_E_XXX
   9321  * Notes:
   9322  */
   9323 STATIC int
   9324 _field_policers_hw_alloc(int unit, _field_entry_t *f_ent)
   9325 {
   9326     _field_entry_policer_t *f_ent_pl;  /* Field entry policer structure.*/
   9327     _field_stage_t         *stage_fc;  /* Stage field control.          */
   9328     _field_policer_t       *f_pl;      /* Field policer descriptor.     */
   9329     _field_control_t       *fc;        /* Field control structure.      */
   9330     int                    idx;        /* Policer levels iterator.      */
   9331     int                    rv;         /* Operation return status.      */
   9332     _field_meter_pool_t    *f_mp;      /* Meter pool descriptor.        */
   9333     /* allocate even meter index for ingress metering for flow mode.
   9334      * If set, the non-flow mode is disabled. Is available only for
   9335      * Trident+ devices as there is an issue with metering on Y-pipe ports
   9336      */
   9337     int                    use_even_meter;
   9338     int                    is_trident_plus_use_even_meter;
   9339     uint16                 devid;
   9340     uint8                  revid;
   9341     int eid;                     /* Entry ID.                       */
   9342     int tmp = 0;                 /* Temporary iterator.             */
   9343     _field_group_t *fg;          /* Field group info.               */
   9344 #if defined (BCM_TOMAHAWK_SUPPORT)
   9345     _field_stage_t         *stage_em; /* Field stage control structure.       */
   9346     uint8                  pipe = 0;  /* Field Pipe Info */
   9347     int                    meter_pairs_per_pool = 0;
   9348     int                    size = 0;
   9349 #endif
   9350 
   9351     /* Input parameters check. */
   9352     if (NULL == f_ent) {
   9353         return (BCM_E_PARAM);
   9354     }
   9355 
   9356     /* Get field control structure. */
   9357     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   9358 
   9359     /* Get field stage control structure. */
   9360     rv = _field_stage_control_get(unit, f_ent->group->stage_id, &stage_fc);
   9361     BCM_IF_ERROR_RETURN(rv);
   9362 
   9363     is_trident_plus_use_even_meter = 0;
   9364     if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS) {
   9365         use_even_meter = soc_property_get(unit,
   9366                            spn_FP_EVEN_INDEX_FOR_INGRESS_FLOW_METER, 0);
   9367         if (use_even_meter) {
   9368             soc_cm_get_id(unit, &devid, &revid);
   9369             if ((devid == BCM56842_DEVICE_ID)||(devid == BCM56844_DEVICE_ID)||
   9370                 (devid == BCM56846_DEVICE_ID)||(devid == BCM56847_DEVICE_ID)||
   9371                 (devid == BCM56053_DEVICE_ID)||(devid == BCM56549_DEVICE_ID)||
   9372                 (devid == BCM56831_DEVICE_ID)||(devid == BCM56835_DEVICE_ID)||
   9373                 (devid == BCM56838_DEVICE_ID)||(devid == BCM56849_DEVICE_ID)
   9374                 ) {
   9375                 is_trident_plus_use_even_meter = 1;
   9376             }
   9377         }
   9378     }
   9379 
   9380     /* Allocate policers if necessary. */
   9381     for (idx = 0; idx < _FP_POLICER_LEVEL_COUNT; idx++) {
   9382         f_ent_pl = f_ent->policer + idx;
   9383         /* Skip invalid policers. */
   9384         if (0 == (f_ent_pl->flags & _FP_POLICER_VALID)) {
   9385             continue;
   9386         }
   9387 
   9388         /* Read policer configuration.*/
   9389         rv = _bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl);
   9390         BCM_IF_ERROR_RETURN(rv);
   9391 
   9392         /*
   9393          * Check if entry's primary slice_number matches
   9394          * Policer meter pool slice_id for Level0 policer.
   9395          */
   9396         if ((!(_FP_POLICER_GROUP_SHARE_ENABLE & fc->flags)) &&
   9397              (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id)) {
   9398 
   9399             if ((0 == idx) && (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)
   9400                 && (_FP_INVALID_INDEX != f_pl->pool_index)) {
   9401 
   9402 #if defined(BCM_TRIUMPH3_SUPPORT)
   9403                 if (SOC_IS_TRIUMPH3(unit) &&
   9404                     (fc->ingress_logical_policer_pools_mode !=
   9405                                   bcmFieldIngressLogicalPolicerPools8x1024)) {
   9406                     f_mp = stage_fc->logical_meter_pool
   9407                               [f_pl->logical_pool_index];
   9408                 } else
   9409 #endif
   9410                 {
   9411                     f_mp = stage_fc->meter_pool[f_ent->group->instance]
   9412                                                [f_pl->pool_index];
   9413                 }
   9414                 if (f_ent->group->slices->slice_number != f_mp->slice_id) {
   9415                     return (BCM_E_PARAM);
   9416                 }
   9417 
   9418             }
   9419         }
   9420 
   9421         /*
   9422          * Check policer mode support - double check in case
   9423          * attached policer was modified by bcm_policer_set API.
   9424          */
   9425         rv = _field_policer_mode_support(unit, f_ent, idx, f_pl);
   9426         BCM_IF_ERROR_RETURN(rv);
   9427 
   9428         /* Allocate policer hw index. */
   9429         if (_FP_INVALID_INDEX == f_pl->hw_index) {
   9430             if (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) {
   9431                 rv = _field_meterpool_hw_entry_alloc(unit, f_ent, f_pl);
   9432             } else {
   9433                 rv = _field_meter_hw_alloc(unit, f_ent, f_ent->fs);
   9434             }
   9435              /* if there is an error in alocating the meter
   9436              * then reset the policer data of all the entries that are
   9437              * using the policer as that of the current entry to the old
   9438              * data of the policer and reset the flags
   9439              */
   9440             if (BCM_FAILURE(rv)) {
   9441                 if (f_ent->flags & _FP_ENTRY_METER_MODIFIED) {
   9442                     /* reset the entry meter modiied flag so that the meter
   9443                      * entry wont get cleared when meter is not allocated
   9444                      */
   9445                     for (fg = fc->groups; fg != NULL; fg = fg->next) {
   9446                         tmp = 0;
   9447                         /*
   9448                          * Check for all entries where the policer was assigned
   9449                          */
   9450                         while (tmp < fg->group_status.entry_count) {
   9451                             eid = (fg->entry_arr[tmp])->eid;
   9452                             /* Get entry description structure. */
   9453                             BCM_IF_ERROR_RETURN(_field_entry_get(unit, eid,
   9454                                  _FP_ENTRY_PRIMARY, &f_ent));
   9455                             f_ent_pl = f_ent->policer + idx;
   9456                             if (f_ent_pl->pid == f_pl->pid) {
   9457                                 f_ent->flags &=
   9458                                     ~_FP_ENTRY_POLICY_TABLE_ONLY_DIRTY;
   9459                                 f_ent->flags &=  ~_FP_ENTRY_METER_MODIFIED;
   9460                             }
   9461                             tmp++;
   9462                         }
   9463                     }
   9464                 } else if ((idx == 1) &&
   9465                           (f_ent->policer->flags & _FP_POLICER_VALID)) {
   9466                     /* when hw allocation fails for level 1 policer,
   9467                      * check if lvl0 is valid and release lvl0 policer
   9468                      */
   9469                     BCM_IF_ERROR_RETURN(_field_policer_hw_free(unit,0,f_ent));
   9470                 }
   9471                 return rv;
   9472             }
   9473         }
   9474 
   9475         /* Increment hw reference count. */
   9476         if (0 == (f_ent_pl->flags & _FP_POLICER_INSTALLED)) {
   9477             f_ent_pl->flags |=  _FP_POLICER_INSTALLED;
   9478             f_pl->hw_ref_count++;
   9479             /* Increment group meter count when hw_ref_count
   9480                becomes 1 (policer can be shared). */
   9481             f_ent->group->group_status.meter_count++;
   9482             /* for flow mode, 1 meter is associated to group
   9483                and for all other modes, 2 meters are associated */
   9484             if(!_FP_POLICER_IS_FLOW_MODE(f_pl)) {
   9485                 f_ent->group->group_status.meter_count++;
   9486             }
   9487             if(_FP_POLICER_IS_FLOW_MODE(f_pl)) {
   9488                 if (is_trident_plus_use_even_meter) {
   9489                     f_ent->group->group_status.meter_count++;
   9490                 }
   9491             }
   9492         }
   9493 
   9494         if (f_pl->hw_flags & _FP_POLICER_DIRTY) {
   9495             BCM_IF_ERROR_RETURN(fc->functions.fp_policer_install(unit, f_ent, f_pl));
   9496         }
   9497 
   9498 #if defined (BCM_TOMAHAWK_SUPPORT)
   9499         if ((soc_feature(unit, soc_feature_field_multi_pipe_support)) &&
   9500            (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)) {
   9501 
   9502            rv = (_field_stage_control_get(unit,
   9503                    _BCM_FIELD_STAGE_EXACTMATCH , &stage_em));
   9504 
   9505            if (BCM_SUCCESS(rv)) {
   9506   
   9507                if (_BCM_FIELD_STAGE_EXACTMATCH == f_ent->group->stage_id) {
   9508                   fc->ifp_em_meter_in_use[f_ent->group->instance][f_pl->pool_index]
   9509                      = BCM_FIELD_METER_POOL_USED_BY_EM;
   9510                } else 
   9511                if (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id) {
   9512                   fc->ifp_em_meter_in_use[f_ent->group->instance][f_pl->pool_index]
   9513                      = BCM_FIELD_METER_POOL_USED_BY_IFP;
   9514                }
   9515 
   9516                if (soc_feature(unit, soc_feature_td3_style_fp)) {
   9517                    meter_pairs_per_pool = BCM_FIELD_INGRESS_TD3_NUM_METER_PAIRS_PER_POOL;
   9518                } else {
   9519                    meter_pairs_per_pool = BCM_FIELD_INGRESS_TH_NUM_METER_PAIRS_PER_POOL;
   9520                }
   9521 
   9522                pipe = f_ent->group->instance;
   9523 
   9524                /* Initialize number of meter per pool.*/
   9525                size = SHR_BITALLOCSIZE(meter_pairs_per_pool << 1);
   9526                if ((_BCM_FIELD_STAGE_EXACTMATCH == f_ent->group->stage_id) ||
   9527                     (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id)) {
   9528                          sal_memcpy(stage_em->meter_pool[pipe][f_pl->pool_index]->meter_bmp.w,
   9529                                     stage_fc->meter_pool[pipe][f_pl->pool_index]->meter_bmp.w,
   9530                                     size);
   9531                          stage_em->meter_pool[pipe][f_pl->pool_index]->level =
   9532                           stage_fc->meter_pool[pipe][f_pl->pool_index]->level;
   9533                          stage_em->meter_pool[pipe][f_pl->pool_index]->slice_id =
   9534                           stage_fc->meter_pool[pipe][f_pl->pool_index]->slice_id;
   9535                          stage_em->meter_pool[pipe][f_pl->pool_index]->size =
   9536                           stage_fc->meter_pool[pipe][f_pl->pool_index]->size;
   9537                          stage_em->meter_pool[pipe][f_pl->pool_index]->pool_size =
   9538                           stage_fc->meter_pool[pipe][f_pl->pool_index]->pool_size;
   9539                          stage_em->meter_pool[pipe][f_pl->pool_index]->free_meters =
   9540                           stage_fc->meter_pool[pipe][f_pl->pool_index]->free_meters;
   9541                          stage_em->meter_pool[pipe][f_pl->pool_index]->num_meter_pairs =
   9542                           stage_fc->meter_pool[pipe][f_pl->pool_index]->num_meter_pairs;
   9543                 }
   9544             } else {
   9545               if (rv != BCM_E_UNAVAIL) {
   9546                   return rv;
   9547               }
   9548             }
   9549         }
   9550 #endif
   9551     }
   9552     return (BCM_E_NONE);
   9553 }
   9554 
   9555 int
   9556 _field_policers_hw_free_old(int unit, _field_entry_t *f_ent)
   9557 {
   9558     _field_entry_policer_t *f_ent_pl;       /* Field entry policer structure.*/
   9559     int                    idx;             /* Policer levels iterator.      */
   9560 
   9561     /* Input parameters check. */
   9562     if (NULL == f_ent) {
   9563         return (BCM_E_PARAM);
   9564     }
   9565 
   9566     /* meter release will be called only if _FP_ENTRY_METER_MODIFIED
   9567      * is set. once the function is called, the flag is reset
   9568      *  so that it gets called only for the firt time entry install is called.
   9569      */
   9570     if ((f_ent->flags & _FP_ENTRY_METER_MODIFIED) == 0) {
   9571         return BCM_E_NONE;
   9572     }
   9573 
   9574     /* de-allocate policers*/
   9575     for (idx = 0; idx < _FP_POLICER_LEVEL_COUNT; idx++) {
   9576         f_ent_pl = f_ent->policer + idx;
   9577         if (0 == (f_ent_pl->flags & _FP_POLICER_VALID)) {
   9578             continue;
   9579         }
   9580         BCM_IF_ERROR_RETURN(_field_policer_hw_free_old(unit, idx, f_ent));
   9581     }
   9582 
   9583     /*reset the flag */
   9584     f_ent->flags &= ~_FP_ENTRY_METER_MODIFIED;
   9585     return (BCM_E_NONE);
   9586 }
   9587 
   9588 /*
   9589  * Function:
   9590  *     _field_policers_hw_free
   9591  *
   9592  * Purpose:
   9593  *     Free entry policers.
   9594  *
   9595  * Parameters:
   9596  *     unit      - (IN) BCM device number.
   9597  *     f_ent     - (IN) Field entry descriptor.
   9598  *     flags     - (IN) Flags to free old/all resources
   9599  * Returns:
   9600  *     BCM_E_XXX
   9601  * Notes:
   9602  */
   9603 STATIC int
   9604 _field_policers_hw_free(int unit, _field_entry_t *f_ent, uint32 flags)
   9605 {
   9606     _field_entry_policer_t *f_ent_pl;       /* Field entry policer structure.*/
   9607     int                    idx;             /* Policer levels iterator.      */
   9608     bcm_policer_t          policer_id = -1; /* Policer Id.                   */
   9609     uint8                  isPolicerDetach = 0;
   9610 
   9611     /* Input parameters check. */
   9612     if (NULL == f_ent) {
   9613         return (BCM_E_PARAM);
   9614     }
   9615 
   9616     /* Allocate policers if necessary. */
   9617     for (idx = 0; idx < _FP_POLICER_LEVEL_COUNT; idx++) {
   9618         f_ent_pl = f_ent->policer + idx;
   9619         policer_id = f_ent_pl->pid;
   9620         isPolicerDetach = (f_ent_pl->flags & _FP_POLICER_DETACH);
   9621 
   9622         if ((_FP_ACTION_OLD_RESOURCE_FREE & flags) &&
   9623             (0 == (f_ent_pl->flags & _FP_POLICER_DETACH))) {
   9624             /* Old resourse should have the detach flag set */
   9625             continue;
   9626         }
   9627 
   9628         if (0 == (f_ent_pl->flags & _FP_POLICER_DETACH)) {
   9629             /* Skip invalid policers. */
   9630             if (0 == (f_ent_pl->flags & _FP_POLICER_VALID)) {
   9631                 continue;
   9632             }
   9633             /* Skip installed policers. */
   9634             if (0 == (f_ent_pl->flags & _FP_POLICER_INSTALLED)) {
   9635                 continue;
   9636             }
   9637         }
   9638 
   9639         if ((_FP_ACTION_RESOURCE_FREE & flags) &&
   9640             (0 == (f_ent_pl->flags & _FP_POLICER_DETACH))) {
   9641             /* Forced released if h/w resources
   9642              * When this comes to this place, then the policer
   9643              * is not detached but it is valid and installed
   9644              * Mark the policy as detached and release the resource
   9645              */
   9646             f_ent_pl->flags = _FP_POLICER_DETACH;
   9647         }
   9648 
   9649         BCM_IF_ERROR_RETURN(_field_policer_hw_free(unit, idx, f_ent));
   9650 
   9651         if ((flags & _FP_ACTION_POLICER_SW_UPDATE) && (!isPolicerDetach)) {
   9652             BCM_IF_ERROR_RETURN (bcm_esw_field_entry_policer_attach
   9653                                                      (unit,f_ent->eid,
   9654                                                       idx,policer_id));
   9655         }
   9656     }
   9657     return (BCM_E_NONE);
   9658 }
   9659 
   9660 
   9661 /*
   9662  * Function:
   9663  *      _field_entry_policer_detach
   9664  * Purpose:
   9665  *      Detach a policer from a field entry.
   9666  * Parameters:
   9667  *      unit     - (IN) Unit number.
   9668  *      entry_id - (IN) Field entry ID.
   9669  *      level    - (IN) Policer level.
   9670  * Returns:
   9671  *      BCM_E_XXX
   9672  * Notes:
   9673  */
   9674 int
   9675 _field_entry_policer_detach(int unit, _field_entry_t *f_ent, int level)
   9676 {
   9677     _field_entry_policer_t *f_ent_pl;/* Field entry policer structure.*/
   9678 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
   9679     defined(BCM_APACHE_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT)
   9680      int rv=0;
   9681      vfp_policy_table_entry_t vfp_entry;
   9682 #endif /* BCM_KATANA_SUPPORT || BCM_TRIUMPH3_SUPPORT ||
   9683           BCM_APACHE_SUPPORT || BCM_GREYHOUND2_SUPPORT */
   9684     /* Input parameters check. */
   9685     if ((level >= _FP_POLICER_LEVEL_COUNT) || (level < 0)) {
   9686         return (BCM_E_PARAM);
   9687     }
   9688 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
   9689     defined(BCM_APACHE_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT)
   9690     if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_APACHE(unit) ||
   9691         SOC_IS_GREYHOUND2(unit)) {
   9692         if ((_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) ||
   9693             (SOC_IS_TRIUMPH3(unit) &&
   9694             (_BCM_FIELD_STAGE_EXTERNAL == f_ent->group->stage_id))) {
   9695             rv = _bcm_esw_delete_policer_from_table(unit,
   9696                    f_ent->global_meter_policer.pid, VFP_POLICY_TABLEm,0,&vfp_entry);
   9697             if (BCM_FAILURE(rv)) {
   9698                 return (rv);
   9699             }
   9700             f_ent->global_meter_policer.pid = 0;
   9701             f_ent->global_meter_policer.flags = 0;
   9702             /* Entry must be reinstalled for policer to take effect. */
   9703             f_ent->flags  |= _FP_ENTRY_DIRTY;
   9704             return (BCM_E_NONE);
   9705         }
   9706     }
   9707 #endif /* BCM_KATANA_SUPPORT || BCM_TRIUMPH3_SUPPORT ||
   9708           BCM_APACHE_SUPPORT || BCM_GREYHOUND2_SUPPORT */
   9709     /* Make sure policer attached to the entry. */
   9710     f_ent_pl = f_ent->policer + level;
   9711     if (0 == (f_ent_pl->flags & _FP_POLICER_VALID)) {
   9712         return (BCM_E_EMPTY);
   9713     }
   9714 
   9715     /* If entry was installed decrement hw reference counter. */
   9716     BCM_IF_ERROR_RETURN(_field_policer_hw_free (unit, level, f_ent));
   9717 
   9718     /*
   9719      * If qualifiers have not been modified for this entry,
   9720      * set Policy table only dirty flag.
   9721      */
   9722     if (0 == (f_ent->flags & _FP_ENTRY_DIRTY)) {
   9723         f_ent->flags |= _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY;
   9724     }
   9725     /* Mark entry for reinstall. */
   9726     f_ent->flags |= _FP_ENTRY_DIRTY;
   9727 
   9728     return (BCM_E_NONE);
   9729 }
   9730 
   9731 /*
   9732  * Function:
   9733  *     _bcm_field_stat_get
   9734  * Purpose:
   9735  *     Lookup a statistics entity description structure by stat id.
   9736  * Parmeters:
   9737  *     unit      - (IN)  BCM device number.
   9738  *     sid       - (IN)  Statistics entity id.
   9739  *     stat_p    - (OUT) Lookup result.
   9740  * Returns:
   9741  *     BCM_E_XXX
   9742  */
   9743 int
   9744 _bcm_field_stat_get(int unit, int sid, _field_stat_t **stat_p)
   9745 {
   9746     _field_stat_t    *f_st; /* Policer lookup pointer.  */
   9747     _field_control_t *fc;   /* Field control structure. */
   9748     uint32 hash_index;      /* Entry hash.              */
   9749 
   9750     /* Input parameters check. */
   9751     if (NULL == stat_p) {
   9752         return (BCM_E_PARAM);
   9753     }
   9754 
   9755     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
   9756 
   9757     hash_index = sid & _FP_HASH_INDEX_MASK(fc);
   9758     f_st  =  fc->stat_hash[hash_index];
   9759     while (NULL != f_st) {
   9760         /* Match entry id. */
   9761         if (f_st->sid == sid) {
   9762             *stat_p = f_st;
   9763             return (BCM_E_NONE);
   9764         }
   9765         f_st = f_st->next;
   9766     }
   9767 
   9768     /* Statistics entity with sid == sid was not found. */
   9769     return (BCM_E_NOT_FOUND);
   9770 }
   9771 
   9772 /*
   9773  * Function:
   9774  *      _bcm_field_stat_id_alloc
   9775  * Purpose:
   9776  *      Allocate a statistics entity id.
   9777  * Parameters:
   9778  *      unit    - (IN) BCM device number.
   9779  *      sid     - (OUT) Stat id.
   9780  * Returns:
   9781  *      BCM_E_XXX
   9782  * Notes:
   9783  */
   9784 int
   9785 _bcm_field_stat_id_alloc(int unit, int *sid)
   9786 {
   9787     int               max_count;           /* Maximum number of sids to try.*/
   9788     _field_stat_t     *f_st;               /* Field stat descriptor.        */
   9789     int               rv;                  /* Operation return status.      */
   9790     static uint32  last_allocated_sid = 0; /* Policer id alloc tracker.     */
   9791 
   9792     /* Input parameters check. */
   9793     if (NULL == sid) {
   9794         return (BCM_E_PARAM);
   9795     }
   9796 
   9797     max_count = _FP_ID_MAX;
   9798     while (max_count--) {
   9799         last_allocated_sid++;
   9800         if (_FP_ID_MAX == last_allocated_sid) {
   9801             last_allocated_sid = _FP_ID_BASE;
   9802         }
   9803         rv = _bcm_field_stat_get(unit, last_allocated_sid, &f_st);
   9804         if (BCM_E_NOT_FOUND == rv) {
   9805             *sid = last_allocated_sid;
   9806             return (BCM_E_NONE);
   9807         }
   9808         if (BCM_FAILURE(rv)) {
   9809             return (rv);
   9810         }
   9811     }
   9812     return (BCM_E_RESOURCE);
   9813 }
   9814 
   9815 
   9816 /*
   9817  * Function:
   9818  *    _field_stat_array_to_bmap
   9819  *
   9820  * Description:
   9821  *      API caller statistics array bit map
   9822  * Parameters:
   9823  *      unit  - (IN) BCM device number.
   9824  *      f_st  - (IN) Field statistics entity.
   9825  *      bmap  - (OUT) Field group id.
   9826  * Returns:
   9827  *      BCM_E_XXX
   9828  */
   9829 STATIC int
   9830 _field_stat_array_to_bmap(int unit, _field_stat_t *f_st, uint32 *bmap)
   9831 {
   9832     int idx;
   9833 
   9834     /* Input parameters check */
   9835     if ((NULL == f_st) || (NULL == bmap)) {
   9836         return (BCM_E_PARAM);
   9837     }
   9838 
   9839     *bmap = 0;
   9840     for (idx = 0; idx < f_st->nstat; idx++) {
   9841         if (NULL == (f_st->stat_arr + idx)) {
   9842        /*
   9843         * COVERITY
   9844         *
   9845         * This conditin may not hit.
   9846         * It is kept intentionally as a defensive check.
   9847         */
   9848         /* coverity[dead_error_line] */
   9849             return (BCM_E_PARAM);
   9850         }
   9851 
   9852         /* coverity[mixed_enums] */
   9853         if ((int)f_st->stat_arr[idx] >= _bcmFieldStatCount) {
   9854             return (BCM_E_PARAM);
   9855         }
   9856 
   9857         *bmap |= (1 << (int)f_st->stat_arr[idx]);
   9858     }
   9859     return (BCM_E_NONE);
   9860 }
   9861 /*
   9862  * Function:
   9863  *    _bcm_field_stat_array_to_bmap
   9864  *
   9865  * Description:
   9866  *      API caller statistics array bit map
   9867  * Parameters:
   9868  *      unit  - (IN) BCM device number.
   9869  *      f_st  - (IN) Field statistics entity.
   9870  *      bmap  - (OUT) Field group id.
   9871  * Returns:
   9872  *      BCM_E_XXX
   9873  */
   9874 int
   9875 _bcm_field_stat_array_to_bmap(int unit, _field_stat_t *f_st, uint32 *bmap)
   9876 {
   9877     return _field_stat_array_to_bmap(unit, f_st, bmap);
   9878 }
   9879 /*
   9880  * Function:
   9881  *   _field_stat_hw_mode_to_bmap
   9882  *
   9883  * Description:
   9884  *      HW counter mode to statistics bitmap.
   9885  * Parameters:
   9886  *      unit           - (IN) BCM device number.
   9887  *      mode           - (IN) HW counter mode.
   9888  *      stage_id       - (IN) Stage id.
   9889  *      hw_bmap        - (OUT) Statistics bitmap.
   9890  *      hw_entry_count - (OUT) Number of counters required.
   9891  * Returns:
   9892  *      BCM_E_XXX
   9893  */
   9894 STATIC int
   9895 _field_stat_hw_mode_to_bmap(int unit, uint16 mode,
   9896                             _field_stage_id_t stage_id,
   9897                             uint32 *hw_bmap, uint8 *hw_entry_count)
   9898 {
   9899     int rv;
   9900 
   9901     /* Input parameters check. */
   9902     if ((NULL == hw_bmap) || (NULL == hw_entry_count)) {
   9903         return (BCM_E_PARAM);
   9904     }
   9905 
   9906 #ifdef BCM_TRIUMPH3_SUPPORT
   9907     if (SOC_IS_TRIUMPH3(unit)) {
   9908         rv = _bcm_field_tr3_stat_hw_mode_to_bmap(unit,
   9909                                                  mode,
   9910                                                  stage_id,
   9911                                                  hw_bmap,
   9912                                                  hw_entry_count
   9913                                                  );
   9914     } else
   9915 #endif
   9916 #if defined(BCM_TRIDENT_SUPPORT)
   9917     if ((SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit)) &&
   9918         (stage_id == _BCM_FIELD_STAGE_INGRESS)) {
   9919         rv = _bcm_field_trident_stat_hw_mode_to_bmap(unit, mode, stage_id,
   9920                                                  hw_bmap, hw_entry_count);
   9921     } else
   9922 #endif /* BCM_TRIDENT_SUPPORT */
   9923 #if defined(BCM_TRIUMPH2_SUPPORT)
   9924     if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit)
   9925         || SOC_IS_VALKYRIE2(unit)) {
   9926         rv = _bcm_field_tr2_stat_hw_mode_to_bmap(unit, mode, stage_id,
   9927                                                  hw_bmap, hw_entry_count);
   9928     } else
   9929 #endif /* !BCM_TRIUMPH2_SUPPORT */
   9930 #if defined(BCM_TRX_SUPPORT)
   9931     if (SOC_IS_TRX(unit)) {
   9932         rv = _bcm_field_trx_stat_hw_mode_to_bmap(unit, mode, stage_id,
   9933                                                  hw_bmap, hw_entry_count);
   9934     } else
   9935 #endif /* BCM_TRX_SUPPORT */
   9936     {
   9937         rv = _bcm_field_fb_stat_hw_mode_to_bmap(unit, mode, stage_id,
   9938                                                 hw_bmap, hw_entry_count);
   9939     }
   9940     return (rv);
   9941 }
   9942 
   9943 #if defined(BCM_HURRICANE3_SUPPORT)
   9944 /*
   9945  * Function:
   9946  *    _field_flowcnt_mode_get
   9947  * Purpose:
   9948  *    Get flowcnt stat hardware counter mode information
   9949  * Parameters:
   9950  *     unit  - (IN) BCM device number
   9951  *     f_st  - (IN) Pointer to field stat structure
   9952  * Returns:
   9953  *     BCM_E_XXX
   9954  */
   9955 STATIC int
   9956 _field_flowcnt_mode_get(int unit,
   9957                          _field_stat_t *f_st)
   9958 {
   9959     uint32 req_bmap;    /* Requested statistics bitmap.    */
   9960 
   9961     /* Input parameter check. */
   9962     if (NULL == f_st) {
   9963         return (BCM_E_PARAM);
   9964     }
   9965 
   9966     /* Get application requested bitmap. */
   9967     BCM_IF_ERROR_RETURN
   9968         (_field_stat_array_to_bmap(unit, f_st, &req_bmap));
   9969 
   9970     /* If bitmap is zero - no mode selection is required. */
   9971     if (0 == req_bmap) {
   9972         f_st->hw_mode = 0;
   9973         f_st->hw_stat = 0;
   9974         f_st->hw_flags |= _FP_STAT_FLOWCNT_CNTR;
   9975         f_st->flex_mode = 0;
   9976         f_st->hw_entry_count = 0;
   9977         return (BCM_E_NONE);
   9978     }
   9979 
   9980     /* VFP stages support only Pkt or Byte STATs */
   9981     if ((req_bmap != (1 << (int)bcmFieldStatBytes)) &&
   9982         (req_bmap != (1 << (int)bcmFieldStatPackets))) {
   9983         return (BCM_E_UNAVAIL);
   9984     }
   9985 
   9986     /* Initialize stat structure with flowcnt stat parameter info. */
   9987     f_st->hw_mode = (int) bcmStatGroupModeSingle;
   9988     f_st->hw_stat = req_bmap;
   9989     f_st->hw_flags |= _FP_STAT_FLOWCNT_CNTR;
   9990     f_st->flex_mode = 0;
   9991     /* No. of hw entries is known only after Flow Count STAT alloc. */
   9992     /* f_st->hw_entry_count = 1; */
   9993 
   9994     return (BCM_E_NONE);
   9995 }
   9996 #endif
   9997 
   9998 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT)
   9999 /*
  10000  * Function:
  10001  *    _field_flex_mode_get
  10002  * Purpose:
  10003  *    Get flex stat hardware counter mode information
  10004  * Parameters:
  10005  *     unit  - (IN) BCM device number
  10006  *     f_st  - (IN) Pointer to field stat structure
  10007  * Returns:
  10008  *     BCM_E_XXX
  10009  */
  10010 STATIC int
  10011 _field_flex_mode_get(int unit,
  10012                          _field_stat_t *f_st)
  10013 {
  10014     uint32 req_bmap;    /* Requested statistics bitmap.    */
  10015     uint32 valid_bmap;  /* Bitmap of valid flex STAT types. */
  10016 
  10017     /* Input parameter check. */
  10018     if (NULL == f_st) {
  10019         return (BCM_E_PARAM);
  10020     }
  10021 
  10022     /* Get application requested bitmap. */
  10023     BCM_IF_ERROR_RETURN
  10024         (_field_stat_array_to_bmap(unit, f_st, &req_bmap));
  10025 
  10026     /* If bitmap is zero - no mode selection is required. */
  10027     if (0 == req_bmap) {
  10028         f_st->hw_mode = 0;
  10029         f_st->hw_stat = 0;
  10030         f_st->hw_flags |= _FP_STAT_FLEX_CNTR;
  10031         f_st->flex_mode = 0;
  10032         f_st->hw_entry_count = 0;
  10033         return (BCM_E_NONE);
  10034     }
  10035 
  10036     /* VFP stages support only Pkt and Byte STATs */
  10037     valid_bmap = ((1 << (int) bcmFieldStatBytes) |
  10038                     (1 << (int) bcmFieldStatPackets));
  10039 
  10040     /* Validate requested STAT types. */
  10041     if (req_bmap & ~(valid_bmap)) {
  10042         return (BCM_E_UNAVAIL);
  10043     }
  10044 
  10045     /* Initialize stat structure with flex stat parameter info. */
  10046     f_st->hw_mode = (int) bcmStatGroupModeSingle;
  10047     f_st->hw_stat = req_bmap;
  10048     f_st->hw_flags |= _FP_STAT_FLEX_CNTR;
  10049     f_st->flex_mode = 0;
  10050     /* No. of hw entries is known only after Flex Hw STAT alloc. */
  10051     /* f_st->hw_entry_count = 1; */
  10052 
  10053     return (BCM_E_NONE);
  10054 }
  10055 #endif
  10056 
  10057 /*
  10058  * Function:
  10059  *    _bcm_field_stat_hw_mode_get
  10060  *
  10061  * Description:
  10062  *      Get hw counter mode which will satisfy requested statistics set.
  10063  * Parameters:
  10064  *      unit     - (IN) BCM device number.
  10065  *      f_st     - (IN) Field statistics entity.
  10066  *      stage_id - (IN) Field stage id.
  10067  * Returns:
  10068  *      BCM_E_XXX
  10069  */
  10070 int
  10071 _bcm_field_stat_hw_mode_get(int unit, _field_stat_t *f_st,
  10072                             _field_stage_id_t stage_id)
  10073 {
  10074     uint32            req_bmap;       /* Requested statistics bitmap.    */
  10075     uint32            hw_bmap;        /* HW supported statistics bitmap. */
  10076     uint8             hw_entry_count; /* Number of counter table entries.*/
  10077     uint16            idx;            /* HW counter modes iterator.      */
  10078     int               rv;             /* Operation return status.        */
  10079     int               fp_stat_hw_mode_max;
  10080 
  10081     /* Input parameters check. */
  10082     if (NULL == f_st) {
  10083         return (BCM_E_PARAM);
  10084     }
  10085 
  10086 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT)
  10087     /*
  10088      * If device supports advanced flex counters
  10089      * and stage is lookup stage, then get
  10090      * flex stat mode for this Stat.
  10091      */
  10092     if (soc_feature(unit, soc_feature_advanced_flex_counter)
  10093         && ((_BCM_FIELD_STAGE_LOOKUP == stage_id)
  10094         || (_BCM_FIELD_STAGE_EXTERNAL == stage_id))) {
  10095         return (_field_flex_mode_get(unit, f_st));
  10096     }
  10097 #endif
  10098 
  10099 #if defined(BCM_HURRICANE3_SUPPORT)
  10100     /*
  10101      * If device supports vlan flow counters
  10102      * and stage is lookup stage, then get
  10103      * flow count stat mode for this Stat.
  10104      */
  10105     if (soc_feature(unit, soc_feature_flowcnt)
  10106         && (_BCM_FIELD_STAGE_LOOKUP == stage_id)) {
  10107         return (_field_flowcnt_mode_get(unit, f_st));
  10108     }
  10109 #endif
  10110 
  10111 
  10112 #ifdef BCM_TRIUMPH3_SUPPORT
  10113     if (SOC_IS_TRIUMPH3(unit)) {
  10114         BCM_IF_ERROR_RETURN
  10115             (_bcm_field_tr3_stat_hw_mode_max(stage_id,
  10116                                              &fp_stat_hw_mode_max
  10117                                              )
  10118             );
  10119     } else
  10120 #endif
  10121     if ((SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit)) &&
  10122         (stage_id == _BCM_FIELD_STAGE_INGRESS)) {
  10123         fp_stat_hw_mode_max = _FP_TRIDENT_STAT_HW_MODE_MAX;
  10124     } else {
  10125         fp_stat_hw_mode_max = _FP_STAT_HW_MODE_MAX;
  10126     }
  10127 
  10128     /* Get application requested bitmap. */
  10129     rv = _field_stat_array_to_bmap (unit, f_st, &req_bmap);
  10130     BCM_IF_ERROR_RETURN(rv);
  10131 
  10132     /* If bitmap is zero - no mode selection is required. */
  10133     if (0 == req_bmap) {
  10134         f_st->hw_stat = 0;
  10135         f_st->hw_entry_count = 0;
  10136         f_st->hw_mode = 0;
  10137         return (BCM_E_NONE);
  10138     }
  10139 
  10140 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT)
  10141     if ((soc_feature(unit, soc_feature_field_vfp_flex_counter) ||
  10142         soc_feature(unit, soc_feature_flowcnt))
  10143         && (_BCM_FIELD_STAGE_LOOKUP == stage_id)) {
  10144 
  10145         hw_bmap = (1 << (int)bcmFieldStatBytes)
  10146                     | (1 << (int)bcmFieldStatPackets);
  10147 
  10148         if (0 == ((req_bmap | hw_bmap) & ~(hw_bmap))) {
  10149             f_st->hw_mode = 1;
  10150             f_st->hw_stat = hw_bmap;
  10151             f_st->hw_entry_count = 1;
  10152             return (BCM_E_NONE);
  10153         }
  10154 
  10155         return (BCM_E_UNAVAIL);
  10156     }
  10157 #endif /* BCM_TRIUMPH2_SUPPORT */
  10158 
  10159     /* Check if any hw supported mode will produce requested statistics. */
  10160 #ifdef BCM_WARM_BOOT_SUPPORT
  10161     if (SOC_WARM_BOOT(unit)) {
  10162         /* The f_st->hw_mode has already been read from the HW */
  10163         rv = _field_stat_hw_mode_to_bmap (unit, f_st->hw_mode, stage_id,
  10164                                           &hw_bmap, &hw_entry_count);
  10165     } else
  10166 #endif
  10167     {
  10168         for (idx = 1; idx <= fp_stat_hw_mode_max; idx++) {
  10169             rv = _field_stat_hw_mode_to_bmap(unit, idx, stage_id,
  10170                                              &hw_bmap, &hw_entry_count);
  10171             LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
  10172                       "MODE:0x%x (l:%d u:%d) req_bmap:[0x%x] hw_bmap:[0x%x]"
  10173                       " hw_entry_count:%d :: [0x%x]\n\r"), idx, (idx & 0x7),
  10174                       ((idx >> 3) & 0x7), req_bmap, hw_bmap, hw_entry_count,
  10175                       ((req_bmap | hw_bmap) & ~(hw_bmap))));
  10176 
  10177             if (rv == BCM_E_CONFIG) {
  10178                /* Returns BCM_E_CONFIG, if the given mode is not supported */
  10179                continue;
  10180             }
  10181 
  10182             if (0 == ((req_bmap | hw_bmap) & ~(hw_bmap))) {
  10183                 /* <HP>
  10184 
  10185                    For maximizing utilization of hardware counters, this should
  10186                    select the hw_mode both supports the requested stats
  10187                    AND minimizes the number of required hardware counters.
  10188 
  10189                    </HP> */
  10190 
  10191                 break;
  10192             }
  10193         }
  10194         if  (idx > fp_stat_hw_mode_max) {
  10195             return (BCM_E_RESOURCE);
  10196         }
  10197         f_st->hw_mode = idx;
  10198     }
  10199 
  10200     f_st->hw_stat = hw_bmap;
  10201     f_st->hw_entry_count = hw_entry_count;
  10202 
  10203     return (BCM_E_NONE);
  10204 }
  10205 
  10206 
  10207 /*
  10208  * Function:
  10209  *      _field_stat_destroy2
  10210  * Purpose:
  10211  *      Deinitialize a statistics collection entity
  10212  * Parameters:
  10213  *      unit    - (IN) Unit number.
  10214  *      fc      - (IN) Internal stat entity descriptor.
  10215  *      f_st    - (IN) Field stat s
  10216  * Returns:
  10217  *      BCM_E_XXX
  10218  * Notes:
  10219  */
  10220 int
  10221 _field_stat_destroy2(int unit, _field_control_t *fc, _field_stat_t *f_st)
  10222 {
  10223     /* Input parameters check. */
  10224     if ((NULL == fc) || (NULL == f_st)) {
  10225         return (BCM_E_PARAM);
  10226     }
  10227 
  10228     /* Reject destroy if policer is in use. */
  10229     if (f_st->sw_ref_count > 1) {
  10230         return (BCM_E_BUSY);
  10231     }
  10232 
  10233     /* Remove policer for lookup hash. */
  10234     _FP_HASH_REMOVE(fc->stat_hash, _field_stat_t, f_st,
  10235                     (f_st->sid & _FP_HASH_INDEX_MASK(fc)));
  10236 
  10237     /* De-allocate statistics entity descriptor. */
  10238     if (NULL != f_st->stat_arr) {
  10239         sal_free(f_st->stat_arr);
  10240     }
  10241     if (NULL != f_st->stat_values) {
  10242         sal_free(f_st->stat_values);
  10243     }
  10244 
  10245     sal_free(f_st);
  10246 
  10247     /* Decrement number of active policers. */
  10248     if (fc->stat_count > 0) {
  10249         fc->stat_count--;
  10250     }
  10251     return (BCM_E_NONE);
  10252 }
  10253 
  10254 /*
  10255  * Function:
  10256  *      _field_stat_destroy
  10257  * Purpose:
  10258  *      Deinitialize a statistics collection entity
  10259  * Parameters:
  10260  *      unit    - (IN) Unit number.
  10261  *      sid     - (IN) Statistics entity id.
  10262  * Returns:
  10263  *      BCM_E_XXX
  10264  * Notes:
  10265  */
  10266 int
  10267 _field_stat_destroy(int unit, int sid)
  10268 {
  10269     _field_control_t  *fc;         /* Field control structure.     */
  10270     _field_stat_t     *f_st;       /* Internal policer descriptor. */
  10271     int               rv;          /* Operation return status.     */
  10272 
  10273     /* Get field control structure. */
  10274     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  10275 
  10276     /* Find policer info. */
  10277     rv = _bcm_field_stat_get(unit, sid, &f_st);
  10278     BCM_IF_ERROR_RETURN(rv);
  10279 
  10280     return _field_stat_destroy2(unit, fc, f_st);
  10281 }
  10282 /*
  10283  * Function:
  10284  *      _bcm_field_stat_destroy
  10285  * Purpose:
  10286  *      Deinitialize a statistics collection entity
  10287  * Parameters:
  10288  *      unit    - (IN) Unit number.
  10289  *      sid     - (IN) Statistics entity id.
  10290  * Returns:
  10291  *      BCM_E_XXX
  10292  * Notes:
  10293  */
  10294 int
  10295 _bcm_field_stat_destroy(int unit, int sid)
  10296 {
  10297     return _field_stat_destroy(unit, sid);
  10298 }
  10299 /*
  10300  * Function:
  10301  *      _field_stat_destroy_all
  10302  * Purpose:
  10303  *      Destroy all statistics collection entities
  10304  * Parameters:
  10305  *      unit    - (IN) Unit number.
  10306  * Returns:
  10307  *      BCM_E_XXX
  10308  * Notes:
  10309  */
  10310 int
  10311 _field_stat_destroy_all(int unit)
  10312 {
  10313     _field_control_t *fc;   /* Field control structure. */
  10314     int idx;                /* Entry hash iterator.     */
  10315     int idx_max;            /* Index max.               */
  10316     int rv;                 /* Operation return status. */
  10317 
  10318     rv = _field_control_get(unit, &fc);
  10319     BCM_IF_ERROR_RETURN(rv);
  10320 
  10321     idx_max = _FP_HASH_SZ(fc);
  10322     for (idx= 0; idx < idx_max; idx ++) {
  10323         while (NULL != fc->stat_hash[idx]) {
  10324             rv = _field_stat_destroy2(unit, fc, fc->stat_hash[idx]);
  10325             if (BCM_FAILURE(rv)) {
  10326                 break;
  10327             }
  10328         }
  10329     }
  10330     return (rv);
  10331 }
  10332 
  10333 /*
  10334  * Function:
  10335  *      _bcm_field_group_stat_destroy
  10336  * Purpose:
  10337  *      Destroy all statistics collection entities
  10338  *      associated to a field group.
  10339  * Parameters:
  10340  *      unit    - (IN) Unit number.
  10341  *      group   - (IN) field group id.
  10342  * Returns:
  10343  *      BCM_E_XXX
  10344  * Notes:
  10345  */
  10346 int
  10347 _bcm_field_group_stat_destroy(int unit, bcm_field_group_t group)
  10348 {
  10349     _field_control_t *fc;   /* Field control structure. */
  10350     int idx;                /* Entry hash iterator.     */
  10351     int idx_max;            /* Index max.               */
  10352     int rv;                 /* Operation return status. */
  10353     _field_stat_t *f_st;    /* Reference to Field stat structure. */
  10354     _field_stat_t *f_st_free, *f_st_prev;
  10355 
  10356     rv = _field_control_get(unit, &fc);
  10357     BCM_IF_ERROR_RETURN(rv);
  10358 
  10359     idx_max = _FP_HASH_SZ(fc);
  10360     for (idx= 0; idx < idx_max; idx ++) {
  10361         f_st = fc->stat_hash[idx];
  10362         f_st_prev = NULL;
  10363         while (NULL != f_st) {
  10364             if (group == f_st->gid) {
  10365                 if (f_st_prev != NULL) {
  10366                    f_st_prev->next = f_st->next;
  10367                    f_st_free = f_st;
  10368                    f_st = f_st_prev->next;
  10369                 } else {
  10370                    f_st_free = f_st;
  10371                    f_st = f_st->next;
  10372                    rv = _field_stat_destroy2(unit, fc, f_st_free);
  10373                    if (BCM_FAILURE(rv)) {
  10374                       break;
  10375                    }
  10376                    continue;
  10377                 }
  10378 
  10379                 /* De-allocate statistics entity descriptor. */
  10380                 if (NULL != f_st_free->stat_arr) {
  10381                    sal_free(f_st_free->stat_arr);
  10382                 }
  10383                 if (NULL != f_st_free->stat_values) {
  10384                    sal_free(f_st_free->stat_values);
  10385                 }
  10386 
  10387                 sal_free(f_st_free);
  10388                 f_st_free = NULL;
  10389 
  10390                 /* Decrement number of active policers. */
  10391                 if (fc->stat_count > 0) {
  10392                    fc->stat_count--;
  10393                 }
  10394             } else {
  10395                 f_st_prev = f_st;
  10396                 f_st = f_st->next;
  10397             }
  10398         }
  10399     }
  10400     return (rv);
  10401 }
  10402 
  10403 /*
  10404  * Function:
  10405  *    _field_stat_array_init
  10406  *
  10407  * Description:
  10408  *      Preserve API requested statistics array.
  10409  * Parameters:
  10410  *      unit     - (IN) BCM device number.
  10411  *      f_st     - (IN) Field statistics entity.
  10412  *      nstat    - (IN) Number of elements in stat array.
  10413  *      stat_arr - (IN) Collected statistics descriptors array.
  10414  * Returns:
  10415  *      BCM_E_XXX
  10416  */
  10417 int
  10418 _field_stat_array_init(int unit, _field_control_t *fc, _field_stat_t *f_st,
  10419                        int nstat, bcm_field_stat_t *stat_arr)
  10420 {
  10421     int rv;
  10422 
  10423     /* Input parameters check. */
  10424     if ((NULL == f_st) || (0 == nstat) || (NULL == stat_arr) || (NULL == fc)) {
  10425         return (BCM_E_PARAM);
  10426     }
  10427 
  10428     /* Free currently allocated  stat array if any. */
  10429     if (NULL != f_st->stat_arr) {
  10430         sal_free(f_st->stat_arr);
  10431         f_st->stat_arr = NULL;
  10432         f_st->nstat = 0;
  10433     }
  10434 
  10435     /* Free currently allocated  values array if any. */
  10436     if (NULL != f_st->stat_values) {
  10437         sal_free(f_st->stat_values);
  10438         f_st->stat_values = NULL;
  10439     }
  10440 
  10441     _FP_XGS3_ALLOC(f_st->stat_arr, (nstat * sizeof (bcm_field_stat_t)),
  10442                    "Field stat array");
  10443     if (NULL == f_st->stat_arr) {
  10444         return (BCM_E_MEMORY);
  10445     }
  10446 
  10447     _FP_XGS3_ALLOC(f_st->stat_values, (nstat * sizeof (uint64)),
  10448                    "Field stat values array");
  10449     if (NULL == f_st->stat_values) {
  10450         sal_free(f_st->stat_arr);
  10451         f_st->stat_arr = NULL;
  10452         return (BCM_E_MEMORY);
  10453     }
  10454 
  10455     /* Copy stats array. */
  10456     sal_memcpy(f_st->stat_arr, stat_arr, (nstat * sizeof(bcm_field_stat_t)));
  10457     f_st->nstat = nstat;
  10458 
  10459     /* Map stats array to hw mode. */
  10460     rv = fc->functions.fp_stat_hw_mode_get(unit, f_st, f_st->stage_id);
  10461     if (BCM_FAILURE(rv)) {
  10462         if (!(f_st->hw_flags & _FP_STAT_INTERNAL)) {
  10463             sal_free(f_st->stat_arr);
  10464             sal_free(f_st->stat_values);
  10465             f_st->stat_arr = NULL;
  10466             f_st->stat_values = NULL;
  10467         }
  10468         return (rv);
  10469     }
  10470     return (BCM_E_NONE);
  10471 }
  10472 
  10473 /*
  10474  * Function:
  10475  *    _bcm_field_stat_array_init
  10476  *
  10477  * Description:
  10478  *      Preserve API requested statistics array.
  10479  * Parameters:
  10480  *      unit     - (IN) BCM device number.
  10481  *      f_st     - (IN) Field statistics entity.
  10482  *      nstat    - (IN) Number of elements in stat array.
  10483  *      stat_arr - (IN) Collected statistics descriptors array.
  10484  * Returns:
  10485  *      BCM_E_XXX
  10486  */
  10487 int
  10488 _bcm_field_stat_array_init(int unit, _field_control_t *fc,
  10489                            _field_stat_t *f_st, int nstat,
  10490                            bcm_field_stat_t *stat_arr)
  10491 {
  10492     /* Input parameters check. */
  10493     if ((NULL == f_st) || (0 == nstat) || (NULL == stat_arr) || (NULL == fc)) {
  10494         return (BCM_E_PARAM);
  10495     }
  10496 
  10497     return _field_stat_array_init(unit, fc, f_st, nstat, stat_arr);
  10498 }
  10499 /*
  10500  * Function:
  10501  *    _field_stat_create
  10502  *
  10503  * Description:
  10504  *       Create statistics collection entity.
  10505  * Parameters:
  10506  *      unit     - (IN) BCM device number.
  10507  *      group    - (IN) Field group id.
  10508  *      nstat    - (IN) Number of elements in stat array.
  10509  *      stat_arr - (IN) Collected statistics descriptors array.
  10510  *      flags    - (IN) HW/API specific flags.
  10511  *      stat_id  - (OUT) Statistics entity id.
  10512  * Returns:
  10513  *      BCM_E_XXX
  10514  */
  10515 int
  10516 _field_stat_create(int unit, bcm_field_group_t group, int nstat,
  10517                    bcm_field_stat_t *stat_arr, uint32 flags, int *stat_id)
  10518 {
  10519     _field_control_t    *fc;          /* Field control structure.     */
  10520     _field_group_t      *fg;          /* Field group pointer.         */
  10521     int                 rv;           /* Operation return status.     */
  10522     _field_stat_t       *f_st = NULL; /* Internal stat descriptor.    */
  10523     int                 idx;
  10524 
  10525     /* Input parameters check. */
  10526     if ((nstat <= 0) ||
  10527         (NULL == stat_id) ||
  10528         (nstat > (_bcmFieldStatCount + 1))) {
  10529             return (BCM_E_PARAM);
  10530     }
  10531 
  10532     if ((0 != nstat) && (NULL == stat_arr)) {
  10533         return (BCM_E_PARAM);
  10534     }
  10535 
  10536     for (idx = 0; idx < nstat; idx++) {
  10537         if ((stat_arr[idx] < bcmFieldStatBytes) ||
  10538                 (stat_arr[idx] >= bcmFieldStatCount)) {
  10539             return (BCM_E_PARAM);
  10540         }
  10541     }
  10542 
  10543     /* Get field control structure. */
  10544     BCM_IF_ERROR_RETURN (_field_control_get(unit, &fc));
  10545 
  10546     /* Get group descriptor. */
  10547     rv = _field_group_get (unit, group, &fg);
  10548     BCM_IF_ERROR_RETURN(rv);
  10549 
  10550 #if defined(BCM_TOMAHAWK_SUPPORT)
  10551     if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  10552         if(_BCM_FIELD_STAGE_CLASS == fg->stage_id) {
  10553             return (BCM_E_UNAVAIL);
  10554         }
  10555     }
  10556 #endif /* BCM_TOMAHAWK_SUPPORT */
  10557 
  10558 #if defined(BCM_FLOWTRACKER_SUPPORT)
  10559     if (soc_feature(unit, soc_feature_field_flowtracker_support) &&
  10560         (fg->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER)) {
  10561         return (BCM_E_UNAVAIL);
  10562     }
  10563 #endif
  10564 
  10565 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  10566    if (!soc_feature(unit, soc_feature_advanced_flex_counter)) {
  10567        if ((0 == soc_feature(unit, soc_feature_field_vfp_flex_counter)) &&
  10568            (0 == soc_feature(unit, soc_feature_flowcnt))
  10569            && (_BCM_FIELD_STAGE_LOOKUP == fg->stage_id)) {
  10570            return (BCM_E_UNAVAIL);
  10571         }
  10572    }
  10573 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  10574 
  10575     if (flags & _FP_STAT_CREATE_ID) {
  10576         /* Check if statistics entity id already exists. */
  10577         rv = _bcm_field_stat_get(unit, *stat_id, &f_st);
  10578         if (BCM_SUCCESS(rv)) {
  10579             /* Stat ID already exists return */
  10580             return (BCM_E_EXISTS);
  10581         }
  10582         flags = 0;
  10583     } else {
  10584         /* Generate statistics entity id. */
  10585         BCM_IF_ERROR_RETURN (_bcm_field_stat_id_alloc(unit, stat_id));
  10586     }
  10587 
  10588     /* Allocate statistics descriptor. */
  10589     _FP_XGS3_ALLOC(f_st, sizeof (_field_stat_t), "Field stat entity");
  10590     if (NULL == f_st) {
  10591         return (BCM_E_MEMORY);
  10592     }
  10593 
  10594     /* Initialize reference count to 1. */
  10595     f_st->sw_ref_count = 1;
  10596 
  10597     /* Set hw index to - no hw resources allocated. */
  10598     f_st->pool_index = _FP_INVALID_INDEX;
  10599     f_st->hw_index = _FP_INVALID_INDEX;
  10600 
  10601     /* Initialize stat id. */
  10602     f_st->sid = *stat_id;
  10603 
  10604     /* Store caller internal flags. */
  10605     f_st->hw_flags = flags;
  10606     f_st->stage_id = fg->stage_id;
  10607     f_st->gid      = fg->gid;
  10608 
  10609     /* Allocate counters array. */
  10610     if (0 != nstat) {
  10611         rv = _field_stat_array_init(unit, fc, f_st, nstat, stat_arr);
  10612         if (BCM_FAILURE(rv)) {
  10613             sal_free(f_st);
  10614             return (rv);
  10615         }
  10616     }
  10617 
  10618 
  10619     /* Insert policer into statistics hash. */
  10620     _FP_HASH_INSERT(fc->stat_hash, f_st, (*stat_id & _FP_HASH_INDEX_MASK(fc)));
  10621 
  10622     /* Increment number of active policers. */
  10623     fc->stat_count++;
  10624     f_st->flex_mode = 0;
  10625     return (BCM_E_NONE);
  10626 }
  10627 
  10628 /*
  10629  * Function:
  10630  *    _field_entry_stat_attach
  10631  *
  10632  * Description:
  10633  *       Attach statistics entity to Field Processor entry.
  10634  * Parameters:
  10635  *      unit      - (IN) BCM device number.
  10636  *      entry     - (IN) Field entry id.
  10637  *      stat_id   - (IN) Statistics entity id.
  10638  * Returns:
  10639  *      BCM_E_XXX
  10640  */
  10641 int
  10642 _field_entry_stat_attach(int unit, _field_entry_t *f_ent, int stat_id)
  10643 {
  10644     _field_entry_stat_t    *f_ent_st; /* Field entry statistics structure.*/
  10645     _field_stat_t          *f_st;     /* Internal statisics descriptor.   */
  10646     _field_stage_id_t      stage_id;  /* Pipeline stage id.               */
  10647     int                    rv;        /* Operation return status.         */
  10648     _field_stage_t         *stage_fc; /* Field stage control structure.*/
  10649 
  10650     /* Input parameters check. */
  10651     if (NULL == f_ent) {
  10652         return (BCM_E_PARAM);
  10653     }
  10654 
  10655     /* Get entry pipeline stage id. */
  10656     stage_id = f_ent->group->stage_id;
  10657 
  10658 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  10659    if (!soc_feature(unit, soc_feature_advanced_flex_counter)) {
  10660        if (!soc_feature(unit, soc_feature_field_vfp_flex_counter) &&
  10661            !soc_feature(unit, soc_feature_flowcnt)
  10662            && (_BCM_FIELD_STAGE_LOOKUP == stage_id)) {
  10663            return (BCM_E_UNAVAIL);
  10664         }
  10665    }
  10666 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  10667 
  10668 #if defined(BCM_TOMAHAWK_SUPPORT)
  10669    if ((soc_feature(unit, soc_feature_td3_style_fp)
  10670        && _BCM_FIELD_STAGE_INGRESS == stage_id)
  10671        || (_BCM_FIELD_STAGE_EXACTMATCH == stage_id &&
  10672         !(f_ent->flags & _FP_ENTRY_EXACT_MATCH_GROUP_DEFAULT))) {
  10673            if (!(BCM_FIELD_ASET_TEST(f_ent->group->aset,
  10674                                           bcmFieldActionStatGroup))) {
  10675                LOG_ERROR(BSL_LS_BCM_FP,
  10676                   (BSL_META_U(unit,
  10677                    "FP(unit %d) - Group %d created"
  10678                    " without action bcmFieldActionStatGroup.\n"),
  10679                     unit, f_ent->group->gid));
  10680                return (BCM_E_CONFIG);
  10681            }
  10682        }
  10683 #endif /* BCM_TOMAHAWK_SUPPORT */
  10684 
  10685     /* Check if another  statistics entity is already attached. */
  10686     f_ent_st = &f_ent->statistic;
  10687     if (f_ent_st->flags & _FP_ENTRY_STAT_VALID) {
  10688         return (BCM_E_EXISTS);
  10689     }
  10690 
  10691     /* Check if statistics action conflicts with other actions */
  10692     if (f_ent_st->flags & _FP_ENTRY_STAT_NOT_ALLOWED) {
  10693         return (BCM_E_CONFIG);
  10694     }
  10695 
  10696     /* Get statistics entity  description structure. */
  10697     rv = _bcm_field_stat_get(unit, stat_id, &f_st);
  10698     BCM_IF_ERROR_RETURN(rv);
  10699 
  10700     if ((f_st->stage_id != stage_id) ||
  10701         (f_st->gid !=  f_ent->group->gid)) {
  10702         return (BCM_E_PARAM);
  10703     }
  10704 
  10705 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  10706     if (soc_feature(unit, soc_feature_advanced_flex_counter) &&
  10707             !soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  10708         /* Can't attach flex stat to normal field stat */
  10709         if (((f_st->stage_id == _BCM_FIELD_STAGE_INGRESS) ||
  10710                     (f_st->stage_id == _BCM_FIELD_STAGE_EGRESS)) &&
  10711                 (f_st->hw_flags & \
  10712                  (_FP_STAT_FLEX_CNTR | _FP_STAT_INTERNAL_FLEX_COUNTER))) {
  10713             return (BCM_E_CONFIG);
  10714         }
  10715     }
  10716 #endif
  10717 
  10718     /* Get stage control information. */
  10719     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, stage_id, &stage_fc));
  10720 
  10721     /* Validate STAT pool_index */
  10722     if (_BCM_FIELD_STAGE_INGRESS == f_ent->fs->stage_id
  10723         && !(stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS)
  10724         && !(stage_fc->flags & _FP_STAGE_GLOBAL_COUNTERS)
  10725         && (_FP_INVALID_INDEX != f_st->hw_index)) {
  10726         if ((!(f_ent->flags & _FP_ENTRY_STAT_IN_SECONDARY_SLICE)
  10727                 && f_ent->fs->slice_number != f_st->pool_index)
  10728             || ((f_ent->flags & _FP_ENTRY_STAT_IN_SECONDARY_SLICE)
  10729                 && f_ent->fs->slice_number + 1 != f_st->pool_index)) {
  10730             LOG_ERROR(BSL_LS_BCM_FP,
  10731                       (BSL_META_U(unit,
  10732                                   "FP(unit %d) - Counters cannot be shared between slices.\n"),
  10733                        unit));
  10734             LOG_ERROR(BSL_LS_BCM_FP,
  10735                       (BSL_META_U(unit,
  10736                                   "             Create a new stat and attach to EID=%d.\n"),
  10737                        f_ent->eid));
  10738             return (BCM_E_CONFIG);
  10739         }
  10740     }
  10741 
  10742     /* Check if statistics entity can be shared. */
  10743     if (f_st->sw_ref_count > 1) {
  10744         /* Statistics sharing is restricted to a single stage. */
  10745         if (stage_id != f_st->stage_id) {
  10746             return (BCM_E_PARAM);
  10747         }
  10748     }
  10749 
  10750     /* Increment statistics entity reference counter. */
  10751     f_st->sw_ref_count++;
  10752 
  10753     /* Attach statistics entity to an entry. */
  10754     f_ent_st->flags |= _FP_ENTRY_STAT_VALID;
  10755     f_ent_st->flags |= _FP_ENTRY_STAT_DIRTY;
  10756     f_ent_st->sid    = stat_id;
  10757 
  10758     /*
  10759      * If qualifiers have not been modified for this entry,
  10760      * set Policy table only dirty flag.
  10761      */
  10762     if (0 == (f_ent->flags & _FP_ENTRY_DIRTY)) {
  10763         f_ent->flags |= _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY;
  10764     }
  10765 
  10766     /* Entry must be reinstalled for statistics to take effect. */
  10767     f_ent->flags  |= _FP_ENTRY_DIRTY;
  10768 
  10769     return (BCM_E_NONE);
  10770 }
  10771 
  10772 #if defined(BCM_TRIUMPH2_SUPPORT)
  10773 /*
  10774  * Function:
  10775  *     _bcm_esw_fp_flex_stat_index_set
  10776  *
  10777  * Purpose:
  10778  *     Allocation callback from flex stat module used to notify fp module
  10779  *     allocated flex stat index.
  10780  * Parameters:
  10781  *     unit      - (IN) BCM device number.
  10782  *     stage_fc  - (IN) Stage field control structure.
  10783  *     f_ent     - (IN/OUT) Entry array policer belongs to.
  10784  *     fs        - (IN) Desired slice for the counter.
  10785  * Returns:
  10786  *     BCM_E_XXX
  10787  */
  10788 STATIC int
  10789 _bcm_esw_fp_flex_stat_index_set(int unit, _bcm_flex_stat_handle_t handle,
  10790                                 int fs_idx, void *cookie)
  10791 {
  10792     _field_stat_t *f_st = (_field_stat_t *)cookie;
  10793     f_st->hw_index = fs_idx;
  10794     return (BCM_E_NONE);
  10795 }
  10796 #endif /* BCM_TRIUMPH2_SUPPORT */
  10797 
  10798 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT)
  10799 /*
  10800  * Function:
  10801  *     _field_flex_counter_free
  10802  *
  10803  * Purpose:
  10804  *     Free flex counter resources used by field entry/entries.
  10805  * Parameters:
  10806  *     unit     - (IN) BCM device number.
  10807  *     f_ent    - (IN) Entry array policer belongs to.
  10808  *     f_st     - (IN) Statistics entity.
  10809  * Returns:
  10810  *     BCM_E_XXX
  10811  */
  10812 int
  10813 _field_flex_counter_free(int unit, _field_entry_t *f_ent, _field_stat_t *f_st)
  10814 {
  10815     _field_stage_t   *stage_fc;
  10816     int              entry_idx=0;
  10817     int              rv;
  10818     soc_mem_t        tcam_mem;          /* TCAM memory id.         */
  10819     soc_mem_t        policy_mem;        /* Policy table memory id. */
  10820     _field_stage_id_t      stage_id;    /* Pipeline stage id.      */
  10821 
  10822     /* Get pipeline stage information. */
  10823     BCM_IF_ERROR_RETURN
  10824         (_field_stage_control_get(unit,
  10825                                   f_ent->group->stage_id,
  10826                                   &stage_fc
  10827                                   )
  10828         );
  10829 
  10830     stage_id = f_ent->group->stage_id;
  10831 
  10832     /* Detach flex stat only if it has been created. */
  10833     if (f_st->flex_mode != 0) {
  10834         /*
  10835          * Get entry index at which flex STAT information
  10836          * has been programmed in policy table.
  10837          */
  10838         BCM_IF_ERROR_RETURN
  10839             (_bcm_field_slice_offset_to_tcam_idx(unit,
  10840                                                  stage_fc,
  10841                                                  f_ent->group->instance,
  10842                                                  f_ent->fs->slice_number,
  10843                                                  f_ent->slice_idx,
  10844                                                  &entry_idx
  10845                                                  )
  10846             );
  10847 
  10848 #if defined(BCM_TRIDENT3_SUPPORT)
  10849         if (soc_feature(unit, soc_feature_td3_style_fp)){
  10850             rv = _bcm_field_th_tcam_policy_mem_get(unit, f_ent,
  10851                     &tcam_mem, &policy_mem);
  10852         } else
  10853 #endif
  10854         {
  10855         rv = _field_fb_tcam_policy_mem_get(unit, f_ent->group->stage_id,
  10856                 &tcam_mem, &policy_mem);
  10857         }
  10858 
  10859         BCM_IF_ERROR_RETURN(rv);
  10860 
  10861         if (stage_id == _BCM_FIELD_STAGE_EGRESS) {
  10862             rv = _bcm_esw_stat_flex_detach_egress_table_counters
  10863                 (unit, 0,
  10864                  policy_mem,
  10865                  entry_idx
  10866                 );
  10867         } else {
  10868             rv = _bcm_esw_stat_flex_detach_ingress_table_counters
  10869                 (unit,
  10870                  policy_mem,
  10871                  entry_idx
  10872                 );
  10873         }
  10874 
  10875         /*
  10876          * Flex STATs module initialized before field module, ignore
  10877          * error during bcm_field_detach().
  10878          */
  10879         if (BCM_FAILURE(rv) && (TRUE == _field_control[unit]->init)) {
  10880             return (rv);
  10881         }
  10882 
  10883         /*
  10884          * Destroy Flex STAT when created not attached
  10885          * through bcm_field_stat_attach API.
  10886          */
  10887         if (!(f_st->hw_flags & _FP_STAT_CREATED_BY_FLEX_MODULE)) {
  10888             rv = bcm_esw_stat_group_destroy(unit, f_st->flex_mode);
  10889 
  10890             /*
  10891              * Flex STATs module initialized before field module, ignore
  10892              * error during bcm_field_detach().
  10893              * Ignore:BCM_E_INTERNAL (as multiple stat entries use same SingleMode
  10894              */
  10895             if (rv == BCM_E_INTERNAL) { /* Doesn't look appropriate error code but*/
  10896                 rv = BCM_E_NONE;
  10897             }
  10898             if (BCM_FAILURE(rv) && (TRUE == _field_control[unit]->init)) {
  10899                 return (rv);
  10900             }
  10901         }
  10902         /* decrement the group's counter count equal to
  10903            the hw counters used for this stat */
  10904         f_ent->group->group_status.counter_count =
  10905         f_ent->group->group_status.counter_count - f_st->hw_entry_count;
  10906 
  10907         f_st->hw_index   = _FP_INVALID_INDEX;
  10908         f_st->pool_index = _FP_INVALID_INDEX;
  10909         f_st->hw_entry_count = 0;
  10910         f_st->flex_mode = 0;
  10911     }
  10912 
  10913     return (BCM_E_NONE);
  10914 }
  10915 #endif
  10916 
  10917 #if defined(BCM_HURRICANE3_SUPPORT)
  10918 /*
  10919  * Function:
  10920  *     _field_flowcnt_counter_free
  10921  *
  10922  * Purpose:
  10923  *     Free flow count counter resources used by field entry/entries.
  10924  * Parameters:
  10925  *     unit     - (IN) BCM device number.
  10926  *     f_ent    - (IN) Entry array policer belongs to.
  10927  *     f_st     - (IN) Statistics entity.
  10928  * Returns:
  10929  *     BCM_E_XXX
  10930  */
  10931 int
  10932 _field_flowcnt_counter_free(int unit, _field_entry_t *f_ent, _field_stat_t *f_st)
  10933 {
  10934     _field_stage_t   *stage_fc;
  10935     int              entry_idx=0;
  10936     int              rv;
  10937     soc_mem_t        tcam_mem;          /* TCAM memory id.         */
  10938     soc_mem_t        policy_mem;        /* Policy table memory id. */
  10939 
  10940     /* Get pipeline stage information. */
  10941     BCM_IF_ERROR_RETURN
  10942         (_field_stage_control_get(unit,
  10943                                   f_ent->group->stage_id,
  10944                                   &stage_fc
  10945                                   )
  10946         );
  10947 
  10948     /* Detach flex stat only if it has been created. */
  10949     if (f_st->flex_mode != 0) {
  10950         /*
  10951          * Get entry index at which flowcnt STAT information
  10952          * has been programmed in policy table.
  10953          */
  10954         BCM_IF_ERROR_RETURN
  10955             (_bcm_field_slice_offset_to_tcam_idx(unit,
  10956                                                  stage_fc,
  10957                                                  f_ent->group->instance,
  10958                                                  f_ent->fs->slice_number,
  10959                                                  f_ent->slice_idx,
  10960                                                  &entry_idx
  10961                                                  )
  10962             );
  10963 
  10964         rv = _field_fb_tcam_policy_mem_get(unit, f_ent->group->stage_id,
  10965                 &tcam_mem, &policy_mem);
  10966         BCM_IF_ERROR_RETURN(rv);
  10967 
  10968         rv = _bcm_esw_flowcnt_object_table_detach(unit,
  10969                                 policy_mem, entry_idx);
  10970 
  10971         /*
  10972          * Flex STATs module initialized before field module, ignore
  10973          * error during bcm_field_detach().
  10974          */
  10975         if (BCM_FAILURE(rv) && (TRUE == _field_control[unit]->init)) {
  10976             return (rv);
  10977         }
  10978 
  10979         /*
  10980          * Destroy Flow count STAT.
  10981          */
  10982         rv = bcm_esw_stat_group_destroy(unit, f_st->flex_mode);
  10983 
  10984         /*
  10985          *  STATs module initialized before field module, ignore
  10986          * error during bcm_field_detach().
  10987          * Ignore:BCM_E_INTERNAL (as multiple stat entries use same SingleMode
  10988          */
  10989         if (rv == BCM_E_INTERNAL) { /* Doesn't look appropriate error code but*/
  10990             rv = BCM_E_NONE;
  10991         }
  10992         if (BCM_FAILURE(rv) && (TRUE == _field_control[unit]->init)) {
  10993             return (rv);
  10994         }
  10995 
  10996         f_st->hw_index   = _FP_INVALID_INDEX;
  10997         f_st->pool_index = _FP_INVALID_INDEX;
  10998         f_st->hw_entry_count = 0;
  10999         f_st->flex_mode = 0;
  11000     }
  11001 
  11002     return (BCM_E_NONE);
  11003 }
  11004 #endif
  11005 
  11006 
  11007 /*
  11008  * Function:
  11009  *     _field_slice_counter_free
  11010  *
  11011  * Purpose:
  11012  *     Free a counter from a slice.
  11013  *
  11014  * Parameters:
  11015  *     unit  - (IN) Bcm device number.
  11016  *     f_ent - (IN) Field entry.
  11017  *     f_st  - (IN) Statistics entity.
  11018  *
  11019  * Returns:
  11020  *     BCM_E_XXX
  11021  */
  11022 STATIC int
  11023 _field_slice_counter_free(int unit, _field_entry_t *f_ent, _field_stat_t *f_st)
  11024 {
  11025     uint8          entry_part;   /* Secondary slice entry part.    */
  11026     _field_group_t *fg;          /* Field group structure.         */
  11027     _field_slice_t *fs;          /* Field slice structure.         */
  11028     int            idx;          /* SW counter index.              */
  11029     int            rv = BCM_E_NONE; /* Operation return status.    */
  11030 
  11031     if ((NULL == f_ent) || (NULL == f_st)) {
  11032         return (BCM_E_PARAM);
  11033     }
  11034 
  11035     fg = f_ent->group;
  11036     fs = (f_ent->flags & _FP_ENTRY_STAT_IN_SECONDARY_SLICE) ? \
  11037          f_ent->fs + 1: f_ent->fs;
  11038 
  11039 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT)
  11040     if ((soc_feature(unit, soc_feature_advanced_flex_counter)
  11041         && (f_st->hw_flags & _FP_STAT_FLEX_CNTR))) {
  11042         return (_field_flex_counter_free(unit, f_ent, f_st));
  11043     }
  11044 #endif
  11045 
  11046 #if defined(BCM_HURRICANE3_SUPPORT)
  11047     if ((soc_feature(unit, soc_feature_flowcnt)
  11048         && (f_st->hw_flags & _FP_STAT_FLOWCNT_CNTR))) {
  11049         return (_field_flowcnt_counter_free(unit, f_ent, f_st));
  11050     }
  11051 #endif
  11052 
  11053 
  11054 #if defined (BCM_TRIUMPH2_SUPPORT)
  11055     /* Free is  external for vfp counters. */
  11056     if (_BCM_FIELD_STAGE_LOOKUP == fg->stage_id) {
  11057         if (!soc_feature(unit, soc_feature_advanced_flex_counter)) {
  11058             /* During Disable - Pass valid counter index for new STAT API mode
  11059             * or zero as counter index for old STAT API mode
  11060             */
  11061             if (f_st->flex_mode) {
  11062                 _bcm_flex_stat_type_t fs_type;
  11063                 uint32 fs_inx;
  11064 
  11065                 fs_type = _BCM_FLEX_STAT_TYPE(f_st->flex_mode);
  11066                 fs_inx  = _BCM_FLEX_STAT_COUNT_INX(f_st->flex_mode);
  11067                 rv = _bcm_esw_flex_stat_enable_set(unit,
  11068                                                    fs_type,
  11069                                                    _bcm_esw_fp_flex_stat_index_set,
  11070                                                    (void *)f_st,
  11071                                                    f_st->sid,
  11072                                                    FALSE,
  11073                                                    fs_inx);
  11074             } else {
  11075                 rv = _bcm_esw_flex_stat_enable_set(unit,
  11076                                                    _bcmFlexStatTypeFp,
  11077                                                    _bcm_esw_fp_flex_stat_index_set,
  11078                                                    (void *)f_st,
  11079                                                    f_st->sid,
  11080                                                    FALSE,
  11081                                                    0
  11082                                                    );
  11083            }
  11084        }
  11085 
  11086        f_st->hw_index   = _FP_INVALID_INDEX;
  11087        f_st->pool_index = _FP_INVALID_INDEX;
  11088 
  11089        /* During system restart flex stat module
  11090         * might be reinitialized before fp reinit. Hence
  11091         * calls to the flex stat module will result in BCM_E_NOT_FOUND
  11092         * error code.
  11093         */
  11094         if ((_BCM_FIELD_STAGE_LOOKUP == f_st->stage_id) &&
  11095             (BCM_E_NOT_FOUND == rv)) {
  11096             rv = BCM_E_NONE;
  11097         }
  11098         return (rv);
  11099     }
  11100 #endif /* BCM_TRIUMPH2_SUPPORT */
  11101 
  11102 #if defined (BCM_FIREBOLT2_SUPPORT)
  11103     if (SOC_IS_FIREBOLT2(unit) && (_BCM_FIELD_STAGE_EGRESS == f_st->stage_id)) {
  11104         /* FB2 - doesn't have counter pairs in stage egress. */
  11105         idx = f_st->hw_index;
  11106     } else
  11107 #endif /* BCM_FIREBOLT2_SUPPORT */
  11108     {
  11109         idx = 2 * f_st->hw_index;
  11110     }
  11111 
  11112     /* Clear counter is used bit. */
  11113     if (2 == f_st->hw_entry_count) {
  11114         _FP_COUNTER_BMP_REMOVE(fs->counter_bmp, idx);
  11115         _FP_COUNTER_BMP_REMOVE(fs->counter_bmp, idx + 1);
  11116     } else {
  11117         /*
  11118          * hw_mode refers to COUNTER_MODEf in FP_POLICY_TABLEm
  11119          * On TD_TT and KTX, this is a 6-bit field:-
  11120          * 0,1,2 bit positions represent lower or even counters
  11121          * 3,4,5 bit positions represent upper or odd counters
  11122          *
  11123          * On rest of the TRX devices, COUNTER_MODEf in FP_POLICY_TABLEm
  11124          * and EFP_POLICY_TABLEm are 3-bit fields, where
  11125          * value 1 - means lower counter is used
  11126          * value 2 - means upper counter is used.
  11127          * values [3 - 7] - mean both counters are used
  11128          *
  11129          * On older devices, COUNTER_MODEf in FP_POLICY_TABLEM
  11130          * is a 4 bit field with the upper bit indicating
  11131          * byte/packet mode and rest of the 3 bits representing
  11132          * the COUNTER_MODE as above.Egress has only one counter,
  11133          * no mode selection
  11134          */
  11135         if ((SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit)) &&
  11136                 f_st->stage_id == _BCM_FIELD_STAGE_INGRESS) {
  11137             if (f_st->hw_mode > 7)  {
  11138                 idx++;
  11139             }
  11140         } else if (SOC_IS_TRX(unit)) {
  11141             if (f_st->hw_mode > 1) {
  11142                 idx++;
  11143             }
  11144         } else {
  11145             if ((f_st->hw_mode & 0x7) > 1) {
  11146                 idx++;
  11147             }
  11148         }
  11149 
  11150         _FP_COUNTER_BMP_REMOVE(fs->counter_bmp, idx);
  11151     }
  11152 
  11153     /* Reset entry policer related flags. */
  11154     if (f_ent->flags & _FP_ENTRY_STAT_IN_SECONDARY_SLICE) {
  11155         /* Get primary entry from the second slice. */
  11156         rv = _bcm_field_entry_flags_to_tcam_part (unit, _FP_ENTRY_SECONDARY,
  11157                                                   fg, &entry_part);
  11158         BCM_IF_ERROR_RETURN(rv);
  11159         sal_memset(&f_ent[entry_part].statistic, 0, sizeof(_field_entry_stat_t));
  11160         f_ent->flags &=  ~_FP_ENTRY_STAT_IN_SECONDARY_SLICE;
  11161     }
  11162 
  11163     /* decrement the group's counter count equal to
  11164        the hw counters used for this stat */
  11165     f_ent->group->group_status.counter_count =
  11166         f_ent->group->group_status.counter_count - f_st->hw_entry_count;
  11167 
  11168     f_st->hw_index   = _FP_INVALID_INDEX;
  11169     f_st->pool_index = _FP_INVALID_INDEX;
  11170     return BCM_E_NONE;
  11171 }
  11172 /*
  11173  * Function:
  11174  *     _field_counter32_collect_alloc
  11175  * Purpose:
  11176  *     Initialize software field for collection of 32 (or less) bit counters.
  11177  *
  11178  * Parameters:
  11179  *     unit         - (IN) BCM device number.
  11180  *     mem          - (IN) Counter memory.
  11181  *     descr        - (IN) Counter descriptor.
  11182  *     ptr          - (OUT) Allocated pointer.
  11183  * Returns:
  11184  *     BCM_E_XXX
  11185  */
  11186 STATIC int
  11187 _field_counter32_collect_alloc(int unit, soc_mem_t mem, char *descr,
  11188                                _field_counter32_collect_t **ptr)
  11189 {
  11190     int mem_size;
  11191 
  11192     /* Input parameters check. */
  11193     if ((NULL == ptr) || (NULL == descr) || (INVALIDm == mem)) {
  11194         return (BCM_E_PARAM);
  11195     }
  11196 
  11197     /* Allocate a buffer to track counters. */
  11198     mem_size = (soc_mem_index_count(unit, mem) *
  11199                                          sizeof(_field_counter32_collect_t));
  11200     *ptr  = sal_alloc(mem_size, descr);
  11201     if (NULL == *ptr) {
  11202         return (BCM_E_MEMORY);
  11203     }
  11204     sal_memset(*ptr, 0, mem_size);
  11205     return (BCM_E_NONE);
  11206 }
  11207 /*
  11208  * Function:
  11209  *     _bcm_field_counter32_collect_alloc
  11210  * Purpose:
  11211  *     Initialize software field for collection of 32 (or less) bit counters.
  11212  *
  11213  * Parameters:
  11214  *     unit         - (IN) BCM device number.
  11215  *     mem          - (IN) Counter memory.
  11216  *     descr        - (IN) Counter descriptor.
  11217  *     ptr          - (OUT) Allocated pointer.
  11218  * Returns:
  11219  *     BCM_E_XXX
  11220  */
  11221 int
  11222 _bcm_field_counter32_collect_alloc(int unit, soc_mem_t mem, char *descr,
  11223                                    _field_counter32_collect_t **ptr)
  11224 {
  11225     return _field_counter32_collect_alloc(unit, mem, descr, ptr);
  11226 }
  11227 #if defined(BCM_TRX_SUPPORT) || defined(BCM_BRADLEY_SUPPORT)
  11228 /*
  11229  * Function:
  11230  *     _field_counter64_collect_alloc
  11231  * Purpose:
  11232  *     Initialize software field for collection > 32 bit counters.
  11233  *
  11234  * Parameters:
  11235  *     unit         - (IN) BCM device number.
  11236  *     mem          - (IN) Counter memory.
  11237  *     descr        - (IN) Counter descriptor.
  11238  *     ptr          - (OUT) Allocated pointer.
  11239  * Returns:
  11240  *     BCM_E_XXX
  11241  */
  11242 STATIC int
  11243 _field_counter64_collect_alloc(int unit, soc_mem_t mem, char *descr,
  11244                                _field_counter64_collect_t **ptr)
  11245 {
  11246     int mem_size;
  11247 
  11248     /* Input parameters check. */
  11249     if ((NULL == ptr) || (NULL == descr) || (INVALIDm == mem)) {
  11250         return (BCM_E_PARAM);
  11251     }
  11252 
  11253     /* Allocate a buffer to track counters. */
  11254     mem_size = (soc_mem_index_count(unit, mem) *
  11255                                          sizeof(_field_counter64_collect_t));
  11256     *ptr  = sal_alloc(mem_size, descr);
  11257     if (NULL == *ptr) {
  11258         return (BCM_E_MEMORY);
  11259     }
  11260     sal_memset(*ptr, 0, mem_size);
  11261     return (BCM_E_NONE);
  11262 }
  11263 /*
  11264  * Function:
  11265  *     _bcm_field_counter64_collect_alloc
  11266  * Purpose:
  11267  *     Initialize software field for collection > 32 bit counters.
  11268  *
  11269  * Parameters:
  11270  *     unit         - (IN) BCM device number.
  11271  *     mem          - (IN) Counter memory.
  11272  *     descr        - (IN) Counter descriptor.
  11273  *     ptr          - (OUT) Allocated pointer.
  11274  * Returns:
  11275  *     BCM_E_XXX
  11276  */
  11277 int
  11278 _bcm_field_counter64_collect_alloc(int unit, soc_mem_t mem, char *descr,
  11279                                _field_counter64_collect_t **ptr)
  11280 {
  11281     return _field_counter64_collect_alloc(unit, mem, descr, ptr);
  11282 }
  11283 #endif /* BCM_TRX_SUPPORT || BCM_BRADLEY_SUPPORT */
  11284 /*
  11285  * Function:
  11286  *     _field_counter_collect_deinit
  11287  * Purpose:
  11288  *     Denitialize software field counters.
  11289  *
  11290  * Parameters:
  11291  *     unit         - (IN) BCM device number.
  11292  *     stage_fc     - (IN/OUT) Stage field control structure.
  11293  *
  11294  * Returns:
  11295  *     BCM_E_XXX
  11296  * NOTE:
  11297  *    FC must be locked & callback deregistred before calling this
  11298  *    function..
  11299  */
  11300 STATIC int
  11301 _field_counter_collect_deinit(int unit, _field_stage_t *stage_fc)
  11302 {
  11303     _field_control_t *fc;
  11304     int rv = 0;
  11305 #if defined(BCM_TOMAHAWK_SUPPORT)
  11306     int                       pipe;      /* XGS pipeline to operate on. */
  11307     int                       max_pipes; /* Maximum pipeline per stage. */
  11308 #endif
  11309 
  11310     /* Input parameters check. */
  11311     if (NULL == stage_fc) {
  11312         return (BCM_E_PARAM);
  11313     }
  11314 
  11315     /* Field control get. */
  11316 
  11317 
  11318     FP_LOCK(unit);
  11319     rv = _field_control_get(unit, &fc);
  11320     if (BCM_FAILURE(rv)) {
  11321         FP_UNLOCK(unit);
  11322         return rv;
  11323     }
  11324 
  11325 
  11326     if (NULL !=  stage_fc->_field_x32_counters) {
  11327         sal_free(stage_fc->_field_x32_counters);
  11328         stage_fc->_field_x32_counters = NULL;
  11329     }
  11330 
  11331 #if defined(BCM_TRIUMPH_SUPPORT)
  11332     if (NULL !=  stage_fc->_field_ext_counters)  {
  11333         sal_free(stage_fc->_field_ext_counters);
  11334         stage_fc->_field_ext_counters = NULL;
  11335     }
  11336 #endif /* !BCM_TRIUMPH_SUPPORT */
  11337 
  11338 
  11339 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRX_SUPPORT)
  11340     if (NULL !=  stage_fc->_field_x64_counters) {
  11341         sal_free(stage_fc->_field_x64_counters);
  11342         stage_fc->_field_x64_counters = NULL;
  11343     }
  11344 
  11345     if (NULL !=  stage_fc->_field_y64_counters) {
  11346         sal_free(stage_fc->_field_y64_counters);
  11347         stage_fc->_field_y64_counters = NULL;
  11348     }
  11349 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRX_SUPPORT */
  11350 
  11351 #if defined(BCM_SCORPION_SUPPORT)
  11352     if (NULL !=  stage_fc->_field_y32_counters)  {
  11353         sal_free(stage_fc->_field_y32_counters);
  11354         stage_fc->_field_y32_counters = NULL;
  11355     }
  11356 #endif /* BCM_SCORPION_SUPPORT */
  11357 
  11358     if (NULL !=  stage_fc->_field_memacc_counters)  {
  11359         sal_free(stage_fc->_field_memacc_counters);
  11360         stage_fc->_field_memacc_counters = NULL;
  11361     }
  11362 
  11363 #if defined(BCM_TOMAHAWK_SUPPORT)
  11364     max_pipes = stage_fc->num_pipes;
  11365     if (stage_fc->flags & _FP_STAGE_MULTI_PIPE_COUNTERS) {
  11366         for (pipe = 0; pipe < max_pipes; pipe++ ) {
  11367             if (NULL !=  stage_fc->_field_32_counters[pipe]) {
  11368                 sal_free(stage_fc->_field_32_counters[pipe]);
  11369                 stage_fc->_field_32_counters[pipe] = NULL;
  11370             }
  11371         }
  11372 
  11373         for (pipe = 0; pipe < max_pipes; pipe++ ) {
  11374             if (NULL !=  stage_fc->_field_64_counters[pipe]) {
  11375                 sal_free(stage_fc->_field_64_counters[pipe]);
  11376                 stage_fc->_field_32_counters[pipe] = NULL;
  11377             }
  11378         }
  11379     }
  11380 #endif
  11381 
  11382     FP_UNLOCK(unit);
  11383 
  11384     return (BCM_E_NONE);
  11385 }
  11386 /*
  11387  * Function:
  11388  *     _bcm_field_counter_collect_deinit
  11389  * Purpose:
  11390  *     Denitialize software field counters.
  11391  *
  11392  * Parameters:
  11393  *     unit         - (IN) BCM device number.
  11394  *     stage_fc     - (IN/OUT) Stage field control structure.
  11395  *
  11396  * Returns:
  11397  *     BCM_E_XXX
  11398  * NOTE:
  11399  *    FC must be locked & callback deregistred before calling this
  11400  *    function..
  11401  */
  11402 int
  11403 _bcm_field_counter_collect_deinit(int unit, _field_stage_t *stage_fc)
  11404 {
  11405     return _field_counter_collect_deinit(unit, stage_fc);
  11406 }
  11407 
  11408 /*
  11409  * Function:
  11410  *    _field_sw_counter_set
  11411  *
  11412  * Description:
  11413  *   Service routine used to set 64-bit software accumulated counters.
  11414  * Parameters:
  11415  *   unit         - (IN) BCM device number.
  11416  *   stage_fc     - (IN) Stage field control structure.
  11417  *   idx          - (IN) Counter hw index.
  11418  *   packet_count - (OUT) Packet Counter value
  11419  *   byte_count   - (OUT) Byte Counter value
  11420  * Returns:
  11421  *    BCM_E_XXX
  11422  */
  11423 STATIC int
  11424 _field_sw_counter_set(int unit, _field_stage_t *stage_fc,
  11425                       int idx, uint64 *packet_count,
  11426                       uint64 *byte_count)
  11427 {
  11428     _field_control_t          *fc;           /* Field control structure. */
  11429     soc_mem_t                 counter_x_mem; /* Counter table on X pipe  */
  11430     soc_mem_t                 counter_y_mem; /* Counter table on Y pipe  */
  11431     uint32                    *hw_buf_x;     /* X memory HW buffer.      */
  11432     uint32                    *hw_buf_y;     /* Y memory HW buffer.      */
  11433     int                       rv;            /* Operation return status. */
  11434 
  11435     hw_buf_x = hw_buf_y = NULL;
  11436 
  11437     /* Get field control structure. */
  11438     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  11439 
  11440     /* Get counter memory. */
  11441     rv = _field_counter_mem_get(unit, stage_fc, &counter_x_mem, &counter_y_mem);
  11442     BCM_IF_ERROR_RETURN(rv);
  11443 
  11444     /* HW index sanity check. */
  11445     if (idx < soc_mem_index_min(unit, counter_x_mem) ||
  11446         idx > soc_mem_index_max(unit, counter_x_mem)) {
  11447         return (BCM_E_INTERNAL);
  11448     }
  11449 
  11450     /* Allocate buffer for counter values in HW.  */
  11451     _FP_XGS3_ALLOC(hw_buf_x, 2 * WORDS2BYTES(SOC_MAX_MEM_FIELD_WORDS),
  11452                    "Counter buffers");
  11453     if (NULL == hw_buf_x) {
  11454         return (BCM_E_MEMORY);
  11455     }
  11456 
  11457     /* Read X pipeline counter memory. */
  11458     rv = soc_mem_read(unit, counter_x_mem, MEM_BLOCK_ANY, idx, hw_buf_x);
  11459     if (BCM_FAILURE(rv)) {
  11460         sal_free(hw_buf_x);
  11461         return (BCM_E_MEMORY);
  11462     }
  11463 
  11464     /* Read Y pipeline counter memory. */
  11465     if (INVALIDm != counter_y_mem) {
  11466         hw_buf_y = hw_buf_x + SOC_MAX_MEM_FIELD_WORDS;
  11467         rv = soc_mem_read(unit, counter_y_mem, MEM_BLOCK_ANY, idx, hw_buf_y);
  11468         if (BCM_FAILURE(rv)) {
  11469             sal_free(hw_buf_x);
  11470             return (BCM_E_MEMORY);
  11471         }
  11472     }
  11473 
  11474     /* Process accumulated counter value. */
  11475     rv = fc->functions.fp_counter_set(unit, stage_fc, counter_x_mem,
  11476                                       hw_buf_x, counter_y_mem, hw_buf_y,
  11477                                       idx, packet_count, byte_count);
  11478     sal_free(hw_buf_x);
  11479     return (rv);
  11480 }
  11481 
  11482 /*
  11483  * Function:
  11484  *    _field_sw_counter_get
  11485  *
  11486  * Description:
  11487  *       Service routine used to retrieve 64-bit software accumulated counters.
  11488  * Parameters:
  11489  *   unit         - (IN) BCM device number.
  11490  *   stage_fc     - (IN) Stage field control structure.
  11491  *   idx          - (IN) Counter hw index.
  11492  *   packet_count - (OUT) Packet Counter value
  11493  *   byte_count   - (OUT) Byte Counter value
  11494  * Returns:
  11495  *    BCM_E_XXX
  11496  */
  11497 STATIC int
  11498 _field_sw_counter_get(int unit, _field_stage_t *stage_fc,
  11499                       int idx, uint64 *packet_count,
  11500                       uint64 *byte_count)
  11501 {
  11502     _field_control_t          *fc;           /* Field control structure. */
  11503     soc_mem_t                 counter_x_mem; /* Counter table on X pipe  */
  11504     soc_mem_t                 counter_y_mem; /* Counter table on Y pipe  */
  11505     uint32                    *hw_buf_x;     /* X memory HW buffer.      */
  11506     uint32                    *hw_buf_y;     /* Y memory HW buffer.      */
  11507     int                       rv;            /* Operation return status. */
  11508 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRX_SUPPORT)
  11509 #if defined(BCM_SCORPION_SUPPORT)
  11510     _field_counter32_collect_t *cntrs32_buf;  /* Sw packet counter value    */
  11511 #endif
  11512     _field_counter64_collect_t *cntrs64_buf;  /* Sw byte counter value      */
  11513 #endif
  11514 
  11515     COMPILER_64_ZERO(*packet_count);
  11516     COMPILER_64_ZERO(*byte_count);
  11517     hw_buf_x = hw_buf_y = NULL;
  11518 
  11519     /* Get field control structure. */
  11520     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  11521 
  11522     /* Get counter memory. */
  11523     rv = _field_counter_mem_get(unit, stage_fc, &counter_x_mem, &counter_y_mem);
  11524     BCM_IF_ERROR_RETURN(rv);
  11525 
  11526     /* HW index sanity check. */
  11527     if (idx < soc_mem_index_min(unit, counter_x_mem) ||
  11528         idx > soc_mem_index_max(unit, counter_x_mem)) {
  11529         return (BCM_E_INTERNAL);
  11530     }
  11531 
  11532 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRX_SUPPORT)
  11533     if ((0 == (fc->flags & _FP_STAT_SYNC_ENABLE)) &&
  11534         (SOC_IS_TRX(unit) || SOC_IS_BRADLEY(unit))) {
  11535         /* Read X pipeline counter memory. */
  11536         if (INVALIDm != counter_x_mem) {
  11537             cntrs64_buf = &stage_fc->_field_x64_counters[idx];
  11538             COMPILER_64_ADD_64(*byte_count,
  11539                 cntrs64_buf->accumulated_counter);
  11540 #if defined(BCM_SCORPION_SUPPORT)
  11541             cntrs32_buf = &stage_fc->_field_x32_counters[idx];
  11542             COMPILER_64_ADD_64(*packet_count,
  11543                 cntrs32_buf->accumulated_counter);
  11544 #endif
  11545         }
  11546 
  11547         /* Read Y pipeline counter memory. */
  11548         if (INVALIDm != counter_y_mem) {
  11549             cntrs64_buf = &stage_fc->_field_y64_counters[idx];
  11550             COMPILER_64_ADD_64(*byte_count,
  11551                 cntrs64_buf->accumulated_counter);
  11552 
  11553 #if defined(BCM_SCORPION_SUPPORT)
  11554             cntrs32_buf = &stage_fc->_field_y32_counters[idx];
  11555             COMPILER_64_ADD_64(*packet_count,
  11556                 cntrs32_buf->accumulated_counter);
  11557 #endif
  11558         }
  11559     } else
  11560 #endif
  11561     {
  11562         /* Allocate buffer for counter values in HW.  */
  11563         _FP_XGS3_ALLOC(hw_buf_x, 2 * WORDS2BYTES(SOC_MAX_MEM_FIELD_WORDS),
  11564                        "Counter buffers");
  11565         if (NULL == hw_buf_x) {
  11566             return (BCM_E_MEMORY);
  11567         }
  11568 
  11569         /* Read X pipeline counter memory. */
  11570         if (INVALIDm != counter_x_mem) {
  11571             rv = soc_mem_read(unit, counter_x_mem, MEM_BLOCK_ANY, idx, hw_buf_x);
  11572             if (BCM_FAILURE(rv)) {
  11573                 sal_free(hw_buf_x);
  11574                 return (BCM_E_MEMORY);
  11575             }
  11576         }
  11577 
  11578         /* Read Y pipeline counter memory. */
  11579         if (INVALIDm != counter_y_mem) {
  11580             hw_buf_y = hw_buf_x + SOC_MAX_MEM_FIELD_WORDS;
  11581             rv = soc_mem_read(unit, counter_y_mem, MEM_BLOCK_ANY, idx, hw_buf_y);
  11582             if (BCM_FAILURE(rv)) {
  11583                 sal_free(hw_buf_x);
  11584                 return (BCM_E_MEMORY);
  11585             }
  11586         }
  11587 
  11588         /* Process accumulated counter value. */
  11589         rv = fc->functions.fp_counter_get(unit, stage_fc, counter_x_mem,
  11590                                           hw_buf_x, counter_y_mem, hw_buf_y,
  11591                                           idx, packet_count, byte_count);
  11592         sal_free(hw_buf_x);
  11593     }
  11594     return (rv);
  11595 }
  11596 
  11597 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT)
  11598 /*
  11599  * Function:
  11600  *      _field_flex_stat_value_set
  11601  *
  11602  * Description:
  11603  *      Set 64 bit flex counter value for specific statistic type.
  11604  * Parameters:
  11605  *      unit      - (IN) BCM device number.
  11606  *      f_st      - (IN) Statistics entity descriptor.
  11607  *      stat      - (IN) Collected statistics descriptor.
  11608  *      value     - (IN) Collected counters value.
  11609  * Returns:
  11610  *      BCM_E_XXX
  11611  */
  11612 STATIC int
  11613 _field_flex_stat_value_set(int unit,
  11614                            _field_stat_t *f_st,
  11615                            bcm_field_stat_t stat,
  11616                            uint64 value)
  11617 {
  11618     _field_stage_t      *stage_fc;  /* Stage field control.         */
  11619     int                 idx;        /* Stat array index.            */
  11620     bcm_stat_value_t    stat_val = {0};   /* Flex counter statistics.     */
  11621 
  11622     /* Get field control. */
  11623 
  11624 
  11625     /* Stage field control structure. */
  11626     BCM_IF_ERROR_RETURN
  11627         (_field_stage_control_get(unit,
  11628                                   f_st->stage_id,
  11629                                   &stage_fc
  11630                                   )
  11631         );
  11632 
  11633     /* Check that stat was requested during statistics entity creation. */
  11634     for (idx = 0; idx < f_st->nstat; idx++) {
  11635         if (stat == f_st->stat_arr[idx]) {
  11636             break;
  11637         }
  11638     }
  11639 
  11640     if (idx == f_st->nstat) {
  11641         return (BCM_E_PARAM);
  11642     }
  11643 
  11644     if (_FP_INVALID_INDEX != f_st->hw_index) {
  11645 
  11646         if (stat == bcmFieldStatPackets) {
  11647             COMPILER_64_TO_32_LO(stat_val.packets, value);
  11648         } else {
  11649             COMPILER_64_SET(stat_val.bytes,
  11650                             COMPILER_64_HI(value),
  11651                             COMPILER_64_LO(value));
  11652         }
  11653 
  11654 	/* coverity[uninit_use_in_call : FALSE] */
  11655         BCM_IF_ERROR_RETURN
  11656             (_bcm_esw_stat_counter_raw_set(unit,
  11657                                            f_st->flex_mode,
  11658                                            (stat == bcmFieldStatBytes) ? 1 : 0,
  11659                                            (f_st->hw_entry_count - 1),
  11660                                            &stat_val
  11661                                            )
  11662                 );
  11663 
  11664     }
  11665 
  11666     return (BCM_E_NONE);
  11667 }
  11668 #endif
  11669 #if defined(BCM_HURRICANE3_SUPPORT)
  11670 /*
  11671  * Function:
  11672  *      _field_flowcnt_stat_value_set
  11673  *
  11674  * Description:
  11675  *      Set 64 bit flowcnt counter value for specific statistic type.
  11676  * Parameters:
  11677  *      unit      - (IN) BCM device number.
  11678  *      f_st      - (IN) Statistics entity descriptor.
  11679  *      stat      - (IN) Collected statistics descriptor.
  11680  *      value     - (IN) Collected counters value.
  11681  * Returns:
  11682  *      BCM_E_XXX
  11683  */
  11684 STATIC int
  11685 _field_flowcnt_stat_value_set(int unit,
  11686                            _field_stat_t *f_st,
  11687                            bcm_field_stat_t stat,
  11688                            uint64 value)
  11689 {
  11690     int                 idx;        /* Stat array index.            */
  11691     bcm_stat_value_t    stat_val;   /* Flowcnt counter statistics.     */
  11692     uint32              byte_flag;  /* Byte or packet */
  11693 
  11694     /* Check that stat was requested during statistics entity creation. */
  11695     for (idx = 0; idx < f_st->nstat; idx++) {
  11696         if (stat == f_st->stat_arr[idx]) {
  11697             break;
  11698         }
  11699     }
  11700 
  11701     if (idx == f_st->nstat) {
  11702         return (BCM_E_PARAM);
  11703     }
  11704 
  11705     if (_FP_INVALID_INDEX != f_st->hw_index) {
  11706 
  11707         if (stat == bcmFieldStatBytes) {
  11708             byte_flag = 1;
  11709             COMPILER_64_SET(stat_val.bytes,
  11710                             COMPILER_64_HI(value),
  11711                             COMPILER_64_LO(value));
  11712         } else if (stat == bcmFieldStatPackets) {
  11713             byte_flag = 0;
  11714             COMPILER_64_TO_32_LO(stat_val.packets, value);
  11715         } else {
  11716             return BCM_E_CONFIG;
  11717         }
  11718 
  11719         BCM_IF_ERROR_RETURN
  11720             (_bcm_esw_flowcnt_counter_raw_set(unit, f_st->flex_mode,
  11721                                                byte_flag,
  11722                                                0,
  11723                                                &stat_val
  11724                                            )
  11725                 );
  11726 
  11727     }
  11728 
  11729     return (BCM_E_NONE);
  11730 }
  11731 #endif
  11732 
  11733 /*
  11734  * Function:
  11735  *      _field_stat_value_set
  11736  *
  11737  * Description:
  11738  *      Set 64 bit counter value for specific statistic type.
  11739  * Parameters:
  11740  *      unit      - (IN) BCM device number.
  11741  *      f_st      - (IN) Statistics entity descriptor.
  11742  *      stat      - (IN) Collected statistics descriptor.
  11743  *      value     - (IN) Collected counters value.
  11744  * Returns:
  11745  *      BCM_E_XXX
  11746  */
  11747 int
  11748 _field_stat_value_set(int unit, _field_stat_t *f_st, bcm_field_stat_t stat,
  11749                        uint64 value)
  11750 {
  11751     _field_stage_t      *stage_fc;      /* Stage field control.         */
  11752     _field_control_t    *fc;            /* Field control structure.     */
  11753 #if defined (BCM_TRIUMPH2_SUPPORT)
  11754     _bcm_flex_stat_t    flex_stat;      /* Flex stat type.              */
  11755 #endif /* BCM_TRIUMPH2_SUPPORT */
  11756     int                 idx1;           /* First counter index to read. */
  11757     int                 idx2;           /* Second counter index to read.*/
  11758     int                 idx3;           /* Third counter index to read.*/
  11759     uint32              flags;          /* _FP_STAT_XXX.                */
  11760     int                 rv;             /* Operation return status.     */
  11761 
  11762     /* Input parameters check. */
  11763     if (NULL == f_st) {
  11764         return (BCM_E_PARAM);
  11765     }
  11766 
  11767     /* Stage field control structure. */
  11768     rv = _field_stage_control_get(unit, f_st->stage_id, &stage_fc);
  11769     BCM_IF_ERROR_RETURN(rv);
  11770 
  11771     /* Get field control. */
  11772     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  11773 
  11774 #if defined(BCM_TOMAHAWK_SUPPORT)
  11775     if ((stage_fc->flags & _FP_STAGE_MULTI_PIPE_COUNTERS) &&
  11776         !((stage_fc->stage_id == _BCM_FIELD_STAGE_EGRESS) &&
  11777           (f_st->hw_flags & _FP_STAT_FLEX_CNTR))) {
  11778         return (fc->functions.fp_stat_value_set(unit, f_st, stat, value));
  11779     }
  11780 #endif
  11781 
  11782 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT)
  11783     if (soc_feature(unit, soc_feature_advanced_flex_counter)) {
  11784         if (f_st->hw_flags & _FP_STAT_FLEX_CNTR) {
  11785             return (_field_flex_stat_value_set(unit,
  11786                                                f_st,
  11787                                                stat,
  11788                                                value
  11789                                                )
  11790             );
  11791         }
  11792     }
  11793 #endif
  11794 
  11795 #if defined(BCM_HURRICANE3_SUPPORT)
  11796     if ((_BCM_FIELD_STAGE_LOOKUP == f_st->stage_id)
  11797         && soc_feature(unit, soc_feature_flowcnt)) {
  11798 
  11799         if (f_st->hw_flags & _FP_STAT_FLOWCNT_CNTR) {
  11800             return (_field_flowcnt_stat_value_set(unit,
  11801                                                f_st,
  11802                                                stat,
  11803                                                value
  11804                                                )
  11805             );
  11806         }
  11807     }
  11808 #endif
  11809 
  11810 #if defined (BCM_TRIUMPH2_SUPPORT)
  11811     /* Flexible stat counters handling. */
  11812     if (_BCM_FIELD_STAGE_LOOKUP == f_st->stage_id) {
  11813         flex_stat = (stat == bcmFieldStatBytes) ? _bcmFlexStatIngressBytes :
  11814             _bcmFlexStatIngressPackets;
  11815         return _bcm_esw_flex_stat_set(unit, _bcmFlexStatTypeFp,
  11816                                       f_st->sid, flex_stat, value);
  11817     }
  11818 #endif /* BCM_TRIUMPH2_SUPPORT */
  11819 
  11820     /* Check that stat was requested during statistics entity creation. */
  11821     for (idx1 = 0; idx1 < f_st->nstat; idx1++) {
  11822         if (stat == f_st->stat_arr[idx1]) {
  11823             break;
  11824         }
  11825     }
  11826     if (idx1 == f_st->nstat) {
  11827         return (BCM_E_PARAM);
  11828     }
  11829 
  11830     /* Get hw indexes and flags needed to compose requested statistic.*/
  11831     rv = fc->functions.fp_stat_index_get(unit, f_st, stat, &idx1,
  11832                                          &idx2, &idx3, &flags);
  11833     BCM_IF_ERROR_RETURN(rv);
  11834 
  11835     /* Set accumulated counter value at primary index. */
  11836     if (_FP_INVALID_INDEX == idx1) {
  11837         return (BCM_E_INTERNAL);
  11838     }
  11839 
  11840     if (flags & _FP_STAT_BYTES) {
  11841         rv = _field_sw_counter_set(unit, stage_fc, idx1, NULL, &value);
  11842     } else {
  11843         rv = _field_sw_counter_set(unit, stage_fc, idx1, &value, NULL);
  11844     }
  11845     BCM_IF_ERROR_RETURN(rv);
  11846 
  11847     /* Reset accumulated counter value at secondary index. */
  11848     if (_FP_INVALID_INDEX != idx2) {
  11849         /* <HP>
  11850 
  11851            Should this behaviour be looked at?  What this means is that setting
  11852            the value for an "implied" stat (i.e. one not directly represented by
  11853            a hardware counter, but calculated from hardware counters) affects
  11854            values for non-implied stats.
  11855 
  11856            Example:
  11857            stat = { red, yellow, not-green }
  11858 
  11859            which is represented in the hardware by 2 counters, one for r and one
  11860            for y, and not-green is returned as the sum of r and y hardware
  11861            counters.
  11862 
  11863            But, setting the not-green stat to X will set one of the hardware
  11864            counters to X and the other to 0.  Thus, the r and y counts will be
  11865            lost, and one of them will be set to X, and the other to 0 -- rather
  11866            bizarre behaviour from an outside point-of-view.
  11867 
  11868            </HP> */
  11869 
  11870         COMPILER_64_ZERO (value);
  11871         if (flags & _FP_STAT_BYTES) {
  11872             rv = _field_sw_counter_set(unit, stage_fc, idx2, NULL, &value);
  11873         } else {
  11874             rv = _field_sw_counter_set(unit, stage_fc, idx2, &value, NULL);
  11875         }
  11876     }
  11877 
  11878     BCM_IF_ERROR_RETURN(rv);
  11879 
  11880     if (_FP_INVALID_INDEX != idx3) {
  11881         COMPILER_64_ZERO (value);
  11882         if (flags & _FP_STAT_BYTES) {
  11883             rv = _field_sw_counter_set(unit, stage_fc, idx3, NULL, &value);
  11884         } else {
  11885             rv = _field_sw_counter_set(unit, stage_fc, idx3, &value, NULL);
  11886         }
  11887     }
  11888 
  11889     return (rv);
  11890 }
  11891 
  11892 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT)
  11893 /*
  11894  * Function:
  11895  *    _field_flex_stat_get
  11896  * Purpose:
  11897  *    Get flex stat counter value
  11898  * Parameters:
  11899  *    unit  - (IN) BCM device number
  11900  *    f_st  - (IN) Pointer to field stat structure
  11901  *    stat  - (IN) Stat type value to get
  11902  *    value - (OUT) Stat value
  11903  * Returns:
  11904  *    BCM_E_XXX
  11905  */
  11906 STATIC int
  11907 _field_flex_stat_get(int unit,
  11908                      int sync_mode,
  11909                      _field_stat_t *f_st,
  11910                      bcm_field_stat_t stat,
  11911                      uint64 *value)
  11912 {
  11913     int idx;
  11914     bcm_stat_value_t stat_val;
  11915     int rv;
  11916 
  11917     /* Stat Type Check. */
  11918     if ((bcmFieldStatPackets != stat)
  11919         && (bcmFieldStatBytes != stat)) {
  11920         return (BCM_E_PARAM);
  11921     }
  11922 
  11923     /* Check that stat was requested during statistics entity creation. */
  11924     for (idx = 0 ; idx < f_st->nstat; idx++) {
  11925         if (stat == f_st->stat_arr[idx]) {
  11926             break;
  11927         }
  11928     }
  11929 
  11930     /* Invalid Stat. */
  11931     if (idx == f_st->nstat) {
  11932         return (BCM_E_PARAM);
  11933     }
  11934 
  11935     COMPILER_64_ZERO(*value);
  11936 
  11937     if (_FP_INVALID_INDEX != f_st->hw_index) {
  11938         /* Read stat value using flex stat routine.*/
  11939         rv = _bcm_esw_stat_counter_raw_get(unit,
  11940                                            sync_mode,
  11941                                            f_st->flex_mode,
  11942                                            (stat == bcmFieldStatBytes) ? 1 : 0,
  11943                                            (f_st->hw_entry_count - 1),
  11944                                            &stat_val
  11945                                            );
  11946         /*
  11947          * Flex STAT module is initalized before field module during reset.
  11948          * Attempt to read flex stats by field module would result in
  11949          * error. Ignore these errors.
  11950          */
  11951         if (BCM_FAILURE(rv)) {
  11952             if (TRUE == _field_control[unit]->init) {
  11953                 return (rv);
  11954             } else {
  11955                 return (BCM_E_NOT_FOUND);
  11956             }
  11957         } else {
  11958             /* Store retrieved stat value in return variable. */
  11959             if (bcmFieldStatPackets == stat) {
  11960                 COMPILER_64_ADD_32(*value, stat_val.packets);
  11961             } else {
  11962                 COMPILER_64_OR(*value, stat_val.bytes);
  11963             }
  11964         }
  11965     }
  11966 
  11967     return (BCM_E_NONE);
  11968 }
  11969 #endif
  11970 
  11971 #if defined(BCM_HURRICANE3_SUPPORT)
  11972 /*
  11973  * Function:
  11974  *    _field_flowcnt_stat_get
  11975  * Purpose:
  11976  *    Get vlan flow stat counter value
  11977  * Parameters:
  11978  *    unit  - (IN) BCM device number
  11979  *    f_st  - (IN) Pointer to field stat structure
  11980  *    stat  - (IN) Stat type value to get
  11981  *    value - (OUT) Stat value
  11982  * Returns:
  11983  *    BCM_E_XXX
  11984  */
  11985 STATIC int
  11986 _field_flowcnt_stat_get(int unit,
  11987                      int sync_mode,
  11988                      _field_stat_t *f_st,
  11989                      bcm_field_stat_t stat,
  11990                      uint64 *value)
  11991 {
  11992     int idx;
  11993     bcm_stat_value_t stat_val;
  11994     int rv;
  11995 
  11996     /* Stat Type Check. */
  11997     if ((bcmFieldStatPackets != stat)
  11998         && (bcmFieldStatBytes != stat)) {
  11999         return (BCM_E_PARAM);
  12000     }
  12001 
  12002     /* Check that stat was requested during statistics entity creation. */
  12003     for (idx = 0 ; idx < f_st->nstat; idx++) {
  12004         if (stat == f_st->stat_arr[idx]) {
  12005             break;
  12006         }
  12007     }
  12008 
  12009     /* Invalid Stat. */
  12010     if (idx == f_st->nstat) {
  12011         return (BCM_E_PARAM);
  12012     }
  12013 
  12014     COMPILER_64_ZERO(*value);
  12015 
  12016     if (_FP_INVALID_INDEX != f_st->hw_index) {
  12017         /* Read stat value using flowcnt stat routine.*/
  12018         rv = _bcm_esw_flowcnt_counter_raw_get(
  12019                              unit, sync_mode, f_st->flex_mode,
  12020                              (stat == bcmFieldStatBytes) ? 1 : 0,
  12021                              0,
  12022                              &stat_val);
  12023         /*
  12024          * STAT module is initalized before field module during reset.
  12025          * Attempt to read flex stats by field module would result in
  12026          * error. Ignore these errors.
  12027          */
  12028         if (BCM_FAILURE(rv)) {
  12029             if (TRUE == _field_control[unit]->init) {
  12030                 return (rv);
  12031             } else {
  12032                 return (BCM_E_NOT_FOUND);
  12033             }
  12034         } else {
  12035             /* Store retrieved stat value in return variable. */
  12036             if (bcmFieldStatPackets == stat) {
  12037                 COMPILER_64_ADD_32(*value, stat_val.packets);
  12038             } else {
  12039                 COMPILER_64_OR(*value, stat_val.bytes);
  12040             }
  12041         }
  12042     }
  12043 
  12044     return (BCM_E_NONE);
  12045 }
  12046 
  12047 
  12048 #endif /* BCM_HURRICANE3_SUPPORT */
  12049 
  12050 /*
  12051  * Function:
  12052  *      _field_stat_value_get
  12053  *
  12054  * Description:
  12055  *      Get 64 bit counter value for specific statistic type.
  12056  * Parameters:
  12057  *      unit      - (IN) BCM device number.
  12058  *      f_st      - (IN) Statistics entity descriptor.
  12059  *      stat      - (IN) Collected statistics descriptor.
  12060  *      value     - (OUT) Collected counters value.
  12061  * Returns:
  12062  *      BCM_E_XXX
  12063  */
  12064 int
  12065 _field_stat_value_get(int unit, int sync_mode, _field_stat_t *f_st, bcm_field_stat_t stat,
  12066                        uint64 *value)
  12067 {
  12068     uint64              packet_count_1; /* Primary index packet count.  */
  12069     uint64              byte_count_1;   /* Primary index byte count.    */
  12070     uint64              packet_count_2; /* Secondary index packet count.*/
  12071     uint64              byte_count_2;   /* Secondary index byte count.  */
  12072     uint64              packet_count_3; /* Third counter index packet count. */
  12073     uint64              byte_count_3;   /* Third counterindex byte count.    */
  12074     _field_stage_t      *stage_fc;      /* Stage field control.         */
  12075 #if defined (BCM_TRIUMPH2_SUPPORT)
  12076     _bcm_flex_stat_t    flex_stat;      /* Flex stat type.              */
  12077 #endif /* BCM_TRIUMPH2_SUPPORT */
  12078     _field_control_t    *fc;            /* Field control structure.     */
  12079     int                 idx1;           /* First counter index to read. */
  12080     int                 idx2;           /* Second counter index to read.*/
  12081     int                 idx3;           /* Third counter index to read. */
  12082     uint32              flags;          /* _FP_STAT_XXX.                */
  12083     int                 rv;             /* Operation return status.     */
  12084 
  12085     /* Input parameters check. */
  12086     if ((NULL == value) || (NULL == f_st)) {
  12087         return (BCM_E_PARAM);
  12088     }
  12089 
  12090 
  12091     /* Get field control. */
  12092     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  12093 
  12094     /* Stage field control structure. */
  12095     rv = _field_stage_control_get(unit, f_st->stage_id, &stage_fc);
  12096     BCM_IF_ERROR_RETURN(rv);
  12097 
  12098 #if defined(BCM_TOMAHAWK_SUPPORT)
  12099     if ((stage_fc->flags & _FP_STAGE_MULTI_PIPE_COUNTERS) &&
  12100         !((stage_fc->stage_id == _BCM_FIELD_STAGE_EGRESS) &&
  12101           (f_st->hw_flags & _FP_STAT_FLEX_CNTR))) {
  12102         return (fc->functions.fp_stat_value_get(unit, sync_mode,
  12103                                                 f_st, stat, value));
  12104     }
  12105 #endif
  12106 
  12107 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT)
  12108     /* Get flex stat counter value. */
  12109     if (soc_feature(unit, soc_feature_advanced_flex_counter)) {
  12110         if (f_st->hw_flags & _FP_STAT_FLEX_CNTR) {
  12111             return (_field_flex_stat_get(unit, sync_mode, f_st, stat, value));
  12112         }
  12113     }
  12114 #endif
  12115 
  12116 #if defined(BCM_HURRICANE3_SUPPORT)
  12117     if ((_BCM_FIELD_STAGE_LOOKUP == f_st->stage_id)
  12118         && (soc_feature(unit, soc_feature_flowcnt))) {
  12119 
  12120         return (_field_flowcnt_stat_get(unit, sync_mode, f_st, stat, value));
  12121     }
  12122 #endif
  12123 
  12124 
  12125 #if defined (BCM_TRIUMPH2_SUPPORT)
  12126     /* Flexible stat counters handling. */
  12127     if (_BCM_FIELD_STAGE_LOOKUP == f_st->stage_id) {
  12128         flex_stat = (stat == bcmFieldStatBytes) ? _bcmFlexStatIngressBytes :
  12129             _bcmFlexStatIngressPackets;
  12130         return _bcm_esw_flex_stat_get(unit, sync_mode,_bcmFlexStatTypeFp,
  12131                                       f_st->sid, flex_stat, value);
  12132     }
  12133 #endif /* BCM_TRIUMPH2_SUPPORT */
  12134 
  12135     /* Initialization. */
  12136     COMPILER_64_ZERO(packet_count_1);
  12137     COMPILER_64_ZERO(packet_count_2);
  12138     COMPILER_64_ZERO(packet_count_3);
  12139     COMPILER_64_ZERO(byte_count_1);
  12140     COMPILER_64_ZERO(byte_count_2);
  12141     COMPILER_64_ZERO(byte_count_3);
  12142     idx1 = idx2 = idx3 = _FP_INVALID_INDEX;
  12143     flags = 0;
  12144 
  12145 
  12146     /* Check that stat was requested during statistics entity creation. */
  12147     for (idx1 = 0; idx1 < f_st->nstat; idx1++) {
  12148         if (stat == f_st->stat_arr[idx1]) {
  12149             break;
  12150         }
  12151     }
  12152     if (idx1 == f_st->nstat) {
  12153         return (BCM_E_PARAM);
  12154     }
  12155 
  12156     /* Get hw indexes and flags needed to compose requested statistic.*/
  12157     rv = fc->functions.fp_stat_index_get(unit, f_st, stat, &idx1,
  12158                                          &idx2, &idx3, &flags);
  12159     BCM_IF_ERROR_RETURN(rv);
  12160 
  12161     /* Get accumulated counter value at primary index. */
  12162     if (_FP_INVALID_INDEX != idx1) {
  12163         rv = _field_sw_counter_get(unit, stage_fc, idx1, &packet_count_1,
  12164                                    &byte_count_1);
  12165         BCM_IF_ERROR_RETURN(rv);
  12166     }
  12167 
  12168     /* Get accumulated counter value at secondary index. */
  12169     if (_FP_INVALID_INDEX != idx2) {
  12170         rv = _field_sw_counter_get(unit, stage_fc, idx2, &packet_count_2,
  12171                                    &byte_count_2);
  12172         BCM_IF_ERROR_RETURN(rv);
  12173     }
  12174 
  12175     /* Get accumulated counter value at secondary index. */
  12176     if (_FP_INVALID_INDEX != idx3) {
  12177         rv = _field_sw_counter_get(unit, stage_fc, idx3, &packet_count_3,
  12178                                    &byte_count_3);
  12179         BCM_IF_ERROR_RETURN(rv);
  12180     }
  12181 
  12182     /* Get final counter value. */
  12183     COMPILER_64_ZERO(*value);
  12184     if (flags & _FP_STAT_BYTES) {
  12185         if (flags & _FP_STAT_ADD) {
  12186             COMPILER_64_ADD_64(byte_count_1, byte_count_2);
  12187             COMPILER_64_ADD_64(byte_count_1, byte_count_3);
  12188         } else if (flags & _FP_STAT_SUBSTRACT) {
  12189             COMPILER_64_SUB_64(byte_count_1, byte_count_2);
  12190         }
  12191         COMPILER_64_OR(*value, byte_count_1);
  12192     } else {
  12193         if (flags & _FP_STAT_ADD) {
  12194             COMPILER_64_ADD_64(packet_count_1, packet_count_2);
  12195             COMPILER_64_ADD_64(packet_count_1, packet_count_3);
  12196         } else if (flags & _FP_STAT_SUBSTRACT) {
  12197             COMPILER_64_SUB_64(packet_count_1, packet_count_2);
  12198         }
  12199         COMPILER_64_OR(*value, packet_count_1);
  12200     }
  12201     return (BCM_E_NONE);
  12202 }
  12203 
  12204 /*
  12205  * Function:
  12206  *     _field_stat_hw_free
  12207  *
  12208  * Purpose:
  12209  *     Deallocate hw counter from an entry.
  12210  *
  12211  * Parameters:
  12212  *     unit      - (IN) BCM device number.
  12213  *     f_ent     - (IN) Entry statistics belongs to.
  12214  * Returns:
  12215  *     BCM_E_XXX
  12216  */
  12217 int
  12218 _field_stat_hw_free (int unit, _field_entry_t *f_ent)
  12219 {
  12220     _field_entry_stat_t  *f_ent_st;  /* Field entry statistics structure. */
  12221     _field_stat_t        *f_st;      /* Statistics entity descriptor.     */
  12222     uint64               value;      /* 64 bit zero to reset hw value.    */
  12223     int                  idx;        /* Statistics iteration index.       */
  12224     int                  rv;         /* Operation return status.          */
  12225 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
  12226     defined(BCM_HURRICANE3_SUPPORT)
  12227     _field_stage_t       *stage_fc;  /* pipeline stage                    */
  12228     int                  entry_idx = 0; /* Entry index at policy table    */
  12229 #endif
  12230     /* Input parameters check. */
  12231     if (NULL == f_ent) {
  12232         return (BCM_E_PARAM);
  12233     }
  12234     f_ent_st = &f_ent->statistic;
  12235 
  12236     /* Skip uninstalled statistics entity. */
  12237     if (0 == (f_ent_st->flags & _FP_ENTRY_STAT_INSTALLED)) {
  12238         return (BCM_E_NONE);
  12239     }
  12240 
  12241 #if defined(BCM_KATANA2_SUPPORT)
  12242     if (soc_feature(unit, soc_feature_flex_stat_compaction_support) &&
  12243             f_ent->group->stage_id == _BCM_FIELD_STAGE_LOOKUP) {
  12244         BCM_IF_ERROR_RETURN(
  12245                 _bcm_field_kt2_entry_stat_detach(unit, f_ent,
  12246                     f_ent_st->extended_sid));
  12247 
  12248         f_ent_st->flags &=  ~_FP_ENTRY_STAT_INSTALLED;
  12249         return (BCM_E_NONE);
  12250     }
  12251 #endif
  12252     /* No de-allocation is required for external FP. */
  12253     if (_BCM_FIELD_STAGE_EXTERNAL == f_ent->fs->stage_id) {
  12254 #ifdef BCM_TRIUMPH3_SUPPORT
  12255         if (SOC_IS_TRIUMPH3(unit)) {
  12256             /* Update Ingress accounting table's statistics */
  12257             BCM_IF_ERROR_RETURN
  12258                 (_bcm_esw_tr3_ext_stat_flex_detach_ingress_table_counters(
  12259                            unit, f_ent));
  12260         }
  12261 #endif
  12262         f_ent_st->flags &=  ~_FP_ENTRY_STAT_INSTALLED;
  12263         return (BCM_E_NONE);
  12264     }
  12265 
  12266 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
  12267     defined(BCM_HURRICANE3_SUPPORT)
  12268     /* Get pipeline stage information. */
  12269     BCM_IF_ERROR_RETURN
  12270         (_field_stage_control_get(unit,
  12271                                   f_ent->group->stage_id,
  12272                                   &stage_fc
  12273                                   )
  12274         );
  12275 #endif
  12276 
  12277     /* Read stat entity configuration. */
  12278     BCM_IF_ERROR_RETURN(_bcm_field_stat_get(unit, f_ent_st->sid, &f_st));
  12279 
  12280     /* Decrement hw reference count. */
  12281     if (f_st->hw_ref_count > 0) {
  12282         f_st->hw_ref_count--;
  12283 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  12284         if (soc_feature(unit, soc_feature_advanced_flex_counter)) {
  12285             if (f_st->flex_mode != 0 && f_st->hw_ref_count > 0) {
  12286                 /*
  12287                  * Get entry index at which flex STAT information
  12288                  * has been programmed in policy table.
  12289                  */
  12290                 BCM_IF_ERROR_RETURN
  12291                     (_bcm_field_slice_offset_to_tcam_idx(unit,
  12292                                                          stage_fc,
  12293                                                          f_ent->group->instance,
  12294                                                          f_ent->fs->slice_number,
  12295                                                          f_ent->slice_idx,
  12296                                                          &entry_idx
  12297                                                         )
  12298                     );
  12299 
  12300                 rv = _bcm_esw_stat_flex_detach_ingress_table_counters
  12301                     (unit,
  12302                      VFP_POLICY_TABLEm,
  12303                      entry_idx
  12304                     );
  12305                 /*
  12306                  * Flex STAT module detached before field module, ignore
  12307                  * error during bcm_field_detach().
  12308                  */
  12309                 if (BCM_FAILURE(rv) && (TRUE == _field_control[unit]->init)) {
  12310                     return (rv);
  12311                 }
  12312             }
  12313         }
  12314 #endif
  12315 #if defined(BCM_HURRICANE3_SUPPORT)
  12316         if (soc_feature(unit, soc_feature_flowcnt) &&
  12317                 (_BCM_FIELD_STAGE_LOOKUP == f_st->stage_id)) {
  12318             if (f_st->flex_mode != 0 && f_st->hw_ref_count > 0) {
  12319 
  12320                 /*
  12321                  * Get entry index at which STAT information
  12322                  * has been programmed in policy table.
  12323                  */
  12324                 BCM_IF_ERROR_RETURN
  12325                     (_bcm_field_slice_offset_to_tcam_idx(unit,
  12326                                                         stage_fc,
  12327                                                         f_ent->group->instance,
  12328                                                         f_ent->fs->slice_number,
  12329                                                         f_ent->slice_idx,
  12330                                                         &entry_idx
  12331                                                         ));
  12332 
  12333                 rv = _bcm_esw_flowcnt_object_table_detach(unit,
  12334                                 VFP_POLICY_TABLEm, entry_idx);
  12335                 /*
  12336                  * STAT module detached before field module, ignore
  12337                  * error during bcm_field_detach().
  12338                  */
  12339                 if (BCM_FAILURE(rv) && (TRUE == _field_control[unit]->init)) {
  12340                     return (rv);
  12341                 }
  12342             }
  12343         }
  12344 #endif
  12345 
  12346     }
  12347 
  12348     /* Statistics is not used by any other entry. */
  12349     if (f_st->hw_ref_count == 0) {
  12350         COMPILER_64_ZERO(value);
  12351         /* Read & Reset  individual statistics. */
  12352         for (idx = 0; idx < f_st->nstat; idx++) {
  12353             rv = _field_stat_value_get(unit, 0, f_st, f_st->stat_arr[idx],
  12354                                        f_st->stat_values + idx);
  12355             if (BCM_FAILURE(rv)) {
  12356                 /* During system restart flex stat module
  12357                  * might be reinitialized before fp reinit. Hence
  12358                  * calls to the flex stat module will result in
  12359                  * BCM_E_NOT_FOUND * error code.
  12360                  */
  12361                 if (soc_feature(unit, soc_feature_field_multi_pipe_support)
  12362                         && (_BCM_FIELD_STAGE_EGRESS == f_st->stage_id)) {
  12363                     if (TRUE == _field_control[unit]->init) {
  12364                         return rv;
  12365                     }
  12366                 } else if (0 == ((_BCM_FIELD_STAGE_LOOKUP == f_st->stage_id)
  12367                     && (BCM_E_NOT_FOUND == rv))) {
  12368                     return rv;
  12369                 }
  12370             } else {
  12371                 rv = _field_stat_value_set(unit, f_st,
  12372                                            f_st->stat_arr[idx], value);
  12373                 BCM_IF_ERROR_RETURN(rv);
  12374             }
  12375         }
  12376         /* Mark hw resource as unused in sw. */
  12377         BCM_IF_ERROR_RETURN(_field_slice_counter_free(unit, f_ent, f_st));
  12378     }
  12379 
  12380     /*
  12381      * If qualifiers have not been modified for this entry,
  12382      * set Action only dirty flag.
  12383      */
  12384     if (0 == (f_ent->flags & _FP_ENTRY_DIRTY)) {
  12385         f_ent->flags |= _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY;
  12386     }
  12387 
  12388     f_ent_st->flags &= ~_FP_ENTRY_STAT_INSTALLED;
  12389 
  12390     /* Mark entry for reinstall. */
  12391     f_ent->flags |= _FP_ENTRY_DIRTY;
  12392     return (BCM_E_NONE);
  12393 }
  12394 
  12395 /*
  12396  * Function:
  12397  *     _bcm_field_stat_hw_free
  12398  *
  12399  * Purpose:
  12400  *     Free counter resources used by field entry/entries.
  12401  * Parameters:
  12402  *     unit     - (IN) BCM device number.
  12403  *     f_ent    - (IN) Entry array policer belongs to.
  12404  * Returns:
  12405  *     BCM_E_XXX
  12406  */
  12407 int
  12408 _bcm_field_stat_hw_free (int unit, _field_entry_t *f_ent)
  12409 {
  12410 #ifdef BCM_TRIUMPH3_SUPPORT
  12411     if (SOC_IS_TRIUMPH3(unit) &&
  12412        (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id)) {
  12413         return (_bcm_field_tr3_stat_hw_free(unit, f_ent));
  12414     }
  12415 #endif
  12416 
  12417     return (_field_stat_hw_free(unit, f_ent));
  12418 }
  12419 
  12420 
  12421 /*
  12422  * Function:
  12423  *    _field_entry_stat_detach
  12424  *
  12425  * Description:
  12426  *       Detach statistics entity from Field processor entry.
  12427  * Parameters:
  12428  *      unit      - (IN) BCM device number.
  12429  *      f_ent     - (IN) Field entry structure.
  12430  *      stat_id   - (IN) Statistics entity id.
  12431  * Returns:
  12432  *      BCM_E_XXX
  12433  */
  12434 STATIC int
  12435 _field_entry_stat_detach(int unit, _field_entry_t *f_ent, int stat_id)
  12436 {
  12437     _field_stat_t       *f_st;     /* Internal statistics entity.  */
  12438     _field_entry_stat_t *f_ent_st; /* Field entry stat structure.  */
  12439     _field_control_t    *fc;
  12440     int                 rv;        /* Operation return status.     */
  12441 
  12442     /* Input parameters check. */
  12443     if (NULL == f_ent) {
  12444         return (BCM_E_PARAM);
  12445     }
  12446 #if defined(BCM_TRIDENT3_SUPPORT)
  12447     if (soc_feature(unit, soc_feature_td3_style_fp) &&
  12448         f_ent->group->stage_id == _BCM_FIELD_STAGE_EGRESS) {
  12449 	   rv = _bcm_field_td2plus_entry_stat_detach(unit, f_ent, stat_id);
  12450 	   return rv;
  12451     }
  12452 #endif
  12453 #if defined(BCM_KATANA2_SUPPORT)
  12454     if (soc_feature(unit, soc_feature_flex_stat_compaction_support) &&
  12455             f_ent->group->stage_id == _BCM_FIELD_STAGE_LOOKUP) {
  12456         rv = _bcm_field_kt2_entry_stat_detach(unit, f_ent, stat_id);
  12457         return rv;
  12458     }
  12459 #endif
  12460     /* Make sure statistics entity attached to the entry. */
  12461     f_ent_st = &f_ent->statistic;
  12462 
  12463     if (0 == (f_ent_st->flags & _FP_ENTRY_STAT_VALID)) {
  12464         return (BCM_E_EMPTY);
  12465     }
  12466 
  12467     /* Compare statistics entity id with attached entity id. */
  12468     if (stat_id  != f_ent_st->sid) {
  12469         return (BCM_E_PARAM);
  12470     }
  12471 
  12472     /* Get statics entity descriptor structure. */
  12473     rv = _bcm_field_stat_get(unit, f_ent_st->sid, &f_st);
  12474     BCM_IF_ERROR_RETURN(rv);
  12475 
  12476     BCM_IF_ERROR_RETURN (_field_control_get(unit, &fc));
  12477 
  12478     /* If entry was installed decrement hw reference counter. */
  12479     rv = fc->functions.fp_stat_hw_free(unit, f_ent);
  12480     BCM_IF_ERROR_RETURN(rv);
  12481 
  12482     /* Decrement statistics entity reference counter. */
  12483     f_st->sw_ref_count--;
  12484 
  12485     /* If no one else is using the entity and it is internal destroy it. */
  12486     if ((1 == f_st->sw_ref_count) && (f_st->hw_flags & _FP_STAT_INTERNAL)) {
  12487         rv = _field_stat_destroy(unit, f_ent_st->sid);
  12488         BCM_IF_ERROR_RETURN(rv);
  12489     }
  12490 
  12491     /* Detach policer from an entry. */
  12492     f_ent_st->sid   = _FP_INVALID_INDEX;
  12493     f_ent_st->flags = 0;
  12494     f_ent_st->flags = _FP_ENTRY_STAT_DIRTY;
  12495 
  12496     /*
  12497      * If qualifiers have not been modified for this entry,
  12498      * set Policy table only dirty flag.
  12499      */
  12500     if (0 == (f_ent->flags & _FP_ENTRY_DIRTY)) {
  12501         f_ent->flags |= _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY;
  12502     }
  12503     /* Mark entry for reinstall. */
  12504     f_ent->flags |= _FP_ENTRY_DIRTY;
  12505 
  12506     return (BCM_E_NONE);
  12507 }
  12508 /*
  12509  * Function:
  12510  *    _bcm_field_entry_stat_detach
  12511  *
  12512  * Description:
  12513  *       Detach statistics entity from Field processor entry.
  12514  * Parameters:
  12515  *      unit      - (IN) BCM device number.
  12516  *      f_ent     - (IN) Field entry structure.
  12517  *      stat_id   - (IN) Statistics entity id.
  12518  * Returns:
  12519  *      BCM_E_XXX
  12520  */
  12521 int
  12522 _bcm_field_entry_stat_detach(int unit, _field_entry_t *f_ent, int stat_id)
  12523 {
  12524     return _field_entry_stat_detach(unit, f_ent, stat_id);
  12525 }
  12526 /*
  12527  * Function:
  12528  *     _field_stat_color_dependent
  12529  *
  12530  * Purpose:
  12531  *    Check if statistics entity is color dependent.
  12532  *
  12533  * Parameters:
  12534  *     unit            - (IN) BCM device number.
  12535  *     f_st            - (IN) Field statistics entity..
  12536  *     color_dependent - (IN) Field statistics entity..
  12537  * Returns:
  12538  *     BCM_E_XXX
  12539  */
  12540 STATIC int
  12541 _field_stat_color_dependent(int unit, _field_stat_t *f_st,
  12542                             uint8 *color_dependent)
  12543 {
  12544    /* Input parameters check. */
  12545     if ((NULL == f_st) || (NULL == color_dependent)) {
  12546         return (BCM_E_PARAM);
  12547     }
  12548 #if defined(BCM_TRIDENT_SUPPORT)
  12549     if ((SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit)) &&
  12550         (f_st->stage_id == _BCM_FIELD_STAGE_INGRESS)) {
  12551         switch (f_st->hw_mode & 0x7) {
  12552             case (0x0):
  12553             /* Fall thru */
  12554             case (0x7):
  12555                 *color_dependent = FALSE;
  12556                 break;
  12557             default:
  12558                 *color_dependent = TRUE;
  12559                 break;
  12560         }
  12561         switch ((f_st->hw_mode >> 3) & 0x7) {
  12562             case (0x0):
  12563             /* Fall thru */
  12564             case (0x7):
  12565                 break;
  12566             default:
  12567                 *color_dependent = TRUE;
  12568                 break;
  12569         }
  12570     } else
  12571 #endif /* BCM_TRIDENT_SUPPORT */
  12572     {
  12573         switch (f_st->hw_mode) {
  12574           case (0x0):
  12575           case (0x1):
  12576           case (0x2):
  12577           case (0x9):
  12578           case (0xa):
  12579               *color_dependent = FALSE;
  12580               break;
  12581           default:
  12582               *color_dependent = TRUE;
  12583               break;
  12584         }
  12585     }
  12586     return (BCM_E_NONE);
  12587 }
  12588 
  12589 /*
  12590  * Function:
  12591  *     _field_stat_hw_mode_adjust
  12592  *
  12593  * Purpose:
  12594  *     Ajust statistics entity mode based on
  12595  *     allocated counter index.
  12596  *
  12597  * Parameters:
  12598  *     unit  - (IN)     Bcm device number.
  12599  *     f_st  - (IN/OUT) Statistics entity.
  12600  *     idx   - (IN)     Allocated hw index.
  12601  *
  12602  * Returns:
  12603  *     BCM_E_XXX
  12604  */
  12605 STATIC int
  12606 _field_stat_hw_mode_adjust(int unit, _field_stat_t *f_st, int idx)
  12607 {
  12608     /* Input parameters check. */
  12609     if (NULL == f_st) {
  12610         return (BCM_E_PARAM);
  12611     }
  12612 
  12613 #if defined(BCM_TRIDENT_SUPPORT)
  12614     if ((SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit)) &&
  12615         (f_st->stage_id == _BCM_FIELD_STAGE_INGRESS)) {
  12616         /* Adjust statistics hw mode  */
  12617         if (0x1 == (idx & 0x1)) {
  12618             if (f_st->hw_mode & 0x7) {
  12619                 f_st->hw_mode <<= 3;
  12620             }
  12621         } else {
  12622             if (((f_st->hw_mode >> 3) & 0x7)) {
  12623                 f_st->hw_mode >>= 3;
  12624             }
  12625         }
  12626     } else
  12627 #endif /* BCM_TRIDENT_SUPPORT */
  12628     {
  12629         /* Adjust statistics hw mode  */
  12630         if (0 == (idx & 0x1)) {
  12631             if ((0xa == f_st->hw_mode) || (0x2 == f_st->hw_mode)) {
  12632                 f_st->hw_mode--;
  12633             }
  12634         } else {
  12635             if ((0x9 == f_st->hw_mode) || (0x1 == f_st->hw_mode)) {
  12636                 f_st->hw_mode++;
  12637             }
  12638         }
  12639     }
  12640     return (BCM_E_NONE);
  12641 }
  12642 
  12643 /*
  12644  * Function:
  12645  *     _field_slice_counter_alloc
  12646  *
  12647  * Purpose:
  12648  *     Allocate a counter from a slice.
  12649  *
  12650  * Parameters:
  12651  *     unit  - (IN)     Bcm device number.
  12652  *     fs    - (IN)     Slice where counter resides.
  12653  *     f_st  - (IN/OUT) Statistics entity.
  12654  *
  12655  * Returns:
  12656  *     BCM_E_XXX
  12657  */
  12658 STATIC int
  12659 _field_slice_counter_alloc(int unit, _field_slice_t *fs, _field_stat_t *f_st)
  12660 {
  12661     int  idx;        /* Bitmap iteration index.     */
  12662     int  idx_max;    /* Total number of counters.   */
  12663 
  12664     if ((NULL == fs) || (NULL == f_st)) {
  12665         return (BCM_E_PARAM);
  12666     }
  12667 
  12668     idx_max = fs->counters_count;
  12669 
  12670     /* If counter is disabled  skip allocation. */
  12671     if (0 == f_st->hw_mode) {
  12672         return (BCM_E_NONE);
  12673     }
  12674 
  12675     for (idx = 0; idx < idx_max; idx++) {
  12676         /* Double entry counters. (e.g Red + Green) */
  12677         if (0x2 == f_st->hw_entry_count) {
  12678             if (0 != (idx % 2)) {
  12679                 /* Skip odd indexes. */
  12680                 continue;
  12681             }
  12682             if ((0 == _FP_COUNTER_BMP_TEST(fs->counter_bmp, idx)) &&
  12683                 (0 == _FP_COUNTER_BMP_TEST(fs->counter_bmp, (idx + 1)))) {
  12684                 /* Mark counter as used. */
  12685                 _FP_COUNTER_BMP_ADD(fs->counter_bmp, idx);
  12686                 _FP_COUNTER_BMP_ADD(fs->counter_bmp, idx + 1);
  12687                 /* Save counter information in statistics entity structure. */
  12688                 f_st->pool_index = fs->slice_number;
  12689                 f_st->hw_index = idx/2;
  12690                 /* Set counter dirty flag. */
  12691                 break;
  12692             } else {
  12693                 continue;
  12694             }
  12695         }
  12696 
  12697         /* Single entry counters. (e.g Bytes) */
  12698         if ((0x1 == f_st->hw_entry_count)
  12699             && (0 == _FP_COUNTER_BMP_TEST(fs->counter_bmp, idx))) {
  12700             /* Mark counter as used. */
  12701             _FP_COUNTER_BMP_ADD(fs->counter_bmp, idx);
  12702             /* Save counter information in statistics entity structure. */
  12703             f_st->pool_index = fs->slice_number;
  12704 #if defined (BCM_FIREBOLT2_SUPPORT)
  12705             if (SOC_IS_FIREBOLT2(unit) && (_BCM_FIELD_STAGE_EGRESS == f_st->stage_id)) {
  12706                 /* FB2 - doesn't have counter pairs in stage egress. */
  12707                 f_st->hw_index = idx;
  12708             } else
  12709 #endif /* BCM_FIREBOLT2_SUPPORT */
  12710             {
  12711                 f_st->hw_index = (idx/2);
  12712                 /* Adjust statistics hw mode */
  12713                 BCM_IF_ERROR_RETURN(_field_stat_hw_mode_adjust(unit, f_st, idx));
  12714             }
  12715             break;
  12716         }
  12717     }
  12718     if (idx == idx_max) {
  12719         return (BCM_E_RESOURCE);
  12720     }
  12721     return (BCM_E_NONE);
  12722 }
  12723 
  12724 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT)
  12725 /*
  12726  * Function:
  12727  *     _field_flex_counter_hw_alloc
  12728  *
  12729  * Purpose:
  12730  *     Allocate flex stat hardware resource
  12731  *
  12732  * Parameters:
  12733  *     unit      - (IN) BCM device number.
  12734  *     f_ent     - (IN) Entry array policer belongs to.
  12735  * Returns:
  12736  *     BCM_E_XXX
  12737  */
  12738 STATIC int
  12739 _field_flex_counter_hw_alloc(int unit,
  12740                              _field_entry_t *f_ent)
  12741 {
  12742     bcm_stat_flex_mode_t    offset_mode;  /* Counter mode.                  */
  12743     bcm_stat_group_mode_t   stat_mode;    /* Stat type bcmStatGroupModeXXX. */
  12744     bcm_stat_object_t       stat_obj;     /* Stat object type.              */
  12745     _field_entry_stat_t     *f_ent_st;    /* Field entry stat collector.    */
  12746     _field_stat_t           *f_st;        /* Field statistics descriptor.   */
  12747     uint32                  flex_sid;     /* Flex Stat ID.                  */
  12748     uint32                  num_hw_cntrs; /* Number of counters allocated.  */
  12749     uint32                  pool_num;     /* Flex Stat Hw Pool No.          */
  12750     uint32                  base_index;   /* Flex Stat counter base index.  */
  12751 
  12752     /* Input parameters check. */
  12753     if (NULL == f_ent) {
  12754         return (BCM_E_PARAM);
  12755     }
  12756 
  12757     /* Get field entry STAT structure. */
  12758     f_ent_st = &f_ent->statistic;
  12759 
  12760     /* Read STAT configuration. */
  12761     BCM_IF_ERROR_RETURN(_bcm_field_stat_get(unit, f_ent_st->sid, &f_st));
  12762 
  12763     /* If counter is disabled skip allocation. */
  12764     if (0 == f_st->hw_stat) {
  12765         return (BCM_E_NONE);
  12766     }
  12767 
  12768     if (_FP_INVALID_INDEX == f_st->hw_index) {
  12769         switch (f_st->stage_id) {
  12770             case _BCM_FIELD_STAGE_LOOKUP:
  12771                 stat_obj = bcmStatObjectIngPolicy;
  12772                 break;
  12773             case _BCM_FIELD_STAGE_EXTERNAL:
  12774                 stat_obj = bcmStatObjectIngEXTPolicy;
  12775                 break;
  12776             default:
  12777                 /* IFP and EFP stages does not use Flex STAT. */
  12778                 return (BCM_E_INTERNAL);
  12779         }
  12780 
  12781         /* Create a flex stat group. */
  12782         BCM_IF_ERROR_RETURN
  12783             (bcm_esw_stat_group_create(unit,
  12784                                        stat_obj,
  12785                                        (bcm_stat_group_mode_t) f_st->hw_mode,
  12786                                        &flex_sid,
  12787                                        &num_hw_cntrs
  12788                                        )
  12789             );
  12790 
  12791         /* Get flex counter hardware details stored in flex stat ID.*/
  12792         _bcm_esw_stat_get_counter_id_info(unit, flex_sid,
  12793                                           &stat_mode,
  12794                                           &stat_obj,
  12795                                           &offset_mode,
  12796                                           &pool_num,
  12797                                           &base_index
  12798                                           );
  12799         /* Store flex stat hardware details in stat data structure. */
  12800         f_st->flex_mode = flex_sid;
  12801         f_st->pool_index = pool_num;
  12802         f_st->hw_index = base_index;
  12803         f_st->hw_mode = offset_mode;
  12804         f_st->hw_entry_count = num_hw_cntrs;
  12805         /* increment the group's counter count equal to
  12806            the hw counters used for this stat
  12807         */
  12808         f_ent->group->group_status.counter_count =
  12809           f_ent->group->group_status.counter_count + f_st->hw_entry_count;
  12810     }
  12811 
  12812     /* For VFP, this flag is set in _field_trx_flex_stat_action_set */
  12813     if (_BCM_FIELD_STAGE_EXTERNAL == f_ent->fs->stage_id) {
  12814        f_ent->statistic.flags |= _FP_ENTRY_STAT_INSTALLED;
  12815     }
  12816     return (BCM_E_NONE);
  12817 }
  12818 #endif
  12819 
  12820 #if defined(BCM_HURRICANE3_SUPPORT)
  12821 /*
  12822  * Function:
  12823  *     _field_flowcnt_counter_hw_alloc
  12824  *
  12825  * Purpose:
  12826  *     Allocate flow count stat hardware resource
  12827  *
  12828  * Parameters:
  12829  *     unit      - (IN) BCM device number.
  12830  *     f_ent     - (IN) Entry array policer belongs to.
  12831  * Returns:
  12832  *     BCM_E_XXX
  12833  */
  12834 STATIC int
  12835 _field_flowcnt_counter_hw_alloc(int unit,
  12836                              _field_entry_t *f_ent)
  12837 {
  12838     bcm_stat_object_t       stat_obj;     /* Stat object type.              */
  12839     _field_entry_stat_t     *f_ent_st;    /* Field entry stat collector.    */
  12840     _field_stat_t           *f_st;        /* Field statistics descriptor.   */
  12841     bcm_stat_group_mode_t   group;
  12842     uint32                  profile_group, pool_idx, base_idx;
  12843     uint32                  flowcnt_sid; /* Flowcnt Stat ID.                  */
  12844     uint32                  num_hw_cntrs; /* Number of counters allocated.  */
  12845 
  12846     /* Input parameters check. */
  12847     if (NULL == f_ent) {
  12848         return (BCM_E_PARAM);
  12849     }
  12850 
  12851     /* Get field entry STAT structure. */
  12852     f_ent_st = &f_ent->statistic;
  12853 
  12854     /* Read STAT configuration. */
  12855     BCM_IF_ERROR_RETURN(_bcm_field_stat_get(unit, f_ent_st->sid, &f_st));
  12856 
  12857     /* If counter is disabled skip allocation. */
  12858     if (0 == f_st->hw_stat) {
  12859         return (BCM_E_NONE);
  12860     }
  12861 
  12862     if (_FP_INVALID_INDEX == f_st->hw_index) {
  12863         switch (f_st->stage_id) {
  12864             case _BCM_FIELD_STAGE_LOOKUP:
  12865                 stat_obj = bcmStatObjectIngFieldStageLookup;
  12866                 break;
  12867             default:
  12868                 /* IFP and EFP stages does not use flow count STAT. */
  12869                 return (BCM_E_INTERNAL);
  12870         }
  12871 
  12872         /* Create a flowcnt stat group. */
  12873         BCM_IF_ERROR_RETURN
  12874             (bcm_esw_stat_group_create(unit,
  12875                                        stat_obj,
  12876                                        (bcm_stat_group_mode_t) f_st->hw_mode,
  12877                                        &flowcnt_sid,
  12878                                        &num_hw_cntrs
  12879                                        )
  12880             );
  12881 
  12882         /* Get flowcnt counter hardware details stored in flowcnt stat ID.*/
  12883         _bcm_esw_flowcnt_counter_id_get(flowcnt_sid,
  12884                 &group, &stat_obj, &profile_group, &pool_idx, &base_idx);
  12885 
  12886         /* Store flex stat hardware details in stat data structure. */
  12887         f_st->flex_mode = flowcnt_sid;
  12888         f_st->pool_index = pool_idx;
  12889         f_st->hw_index = base_idx;
  12890         f_st->hw_entry_count = num_hw_cntrs;
  12891     }
  12892 
  12893     return (BCM_E_NONE);
  12894 }
  12895 #endif /* BCM_HURRICANE3_SUPPORT */
  12896 
  12897 
  12898 /*
  12899  * Function:
  12900  *     _bcm_field_counter_hw_alloc
  12901  *
  12902  * Purpose:
  12903  *     Allocate a counter/s for an entry from a slice.
  12904  *
  12905  * Parameters:
  12906  *     unit      - (IN) BCM device number.
  12907  *     stage_fc  - (IN) Stage field control structure.
  12908  *     f_ent     - (IN/OUT) Entry array policer belongs to.
  12909  *     fs        - (IN) Desired slice for the counter.
  12910  * Returns:
  12911  *     BCM_E_XXX
  12912  */
  12913 int
  12914 _bcm_field_counter_hw_alloc(int unit, _field_entry_t *f_ent, _field_slice_t *fs)
  12915 {
  12916     uint8                  color_dependent;/* Statistics is color based.*/
  12917     uint8                  entry_part; /* Field entry tcam part.        */
  12918     _field_entry_stat_t    *f_ent_st;  /* Field entry stat structure.   */
  12919     _field_entry_policer_t *f_ent_pl;  /* Field entry policer structure.*/
  12920     _field_stage_t         *stage_fc;  /* Stage field control.          */
  12921     _field_group_t         *fg;        /* Field group structure.        */
  12922     _field_stat_t          *f_st;      /* Field statistics descriptor.  */
  12923     int                    rv;         /* Operation return status.      */
  12924 
  12925     /* Input parameters check. */
  12926     if ((NULL == f_ent) || (NULL == fs)) {
  12927         return (BCM_E_PARAM);
  12928     }
  12929 
  12930     fg       = f_ent->group;
  12931     f_ent_pl = f_ent->policer;
  12932     f_ent_st = &f_ent->statistic;
  12933 
  12934     /* Reject unused counters. */
  12935     if (0 == (f_ent_st->flags & _FP_ENTRY_STAT_VALID)) {
  12936         return (BCM_E_PARAM);
  12937     }
  12938 
  12939     /* Read STAT configuration. */
  12940     BCM_IF_ERROR_RETURN(_bcm_field_stat_get(unit, f_ent_st->sid, &f_st));
  12941 
  12942 #if defined(BCM_TRIUMPH2_SUPPORT)
  12943     /* Allocation is external for vfp counters. */
  12944     if (_BCM_FIELD_STAGE_LOOKUP == fg->stage_id
  12945         && !soc_feature(unit, soc_feature_advanced_flex_counter)
  12946         && !soc_feature(unit, soc_feature_flowcnt)) {
  12947        if ((f_st->hw_flags & _FP_STAT_INTERNAL) && 0 == f_st->hw_mode) {
  12948         /*
  12949          * Invalid counter mode used for bcmFieldActionUpdateCounter action.
  12950          * BCM_FIELD_COUNTER_MODE_DEFAULT or BCM_FIELD_COUNTER_MODE_NO_YES
  12951          * are the valid counter modes for lookup stage.
  12952          */
  12953             return (BCM_E_CONFIG);
  12954         }
  12955         /* During Enable - Pass valid counter index for new STAT API mode
  12956          * or zero as counter index for old STAT API mode
  12957          */
  12958         if (f_st->flex_mode) {
  12959             _bcm_flex_stat_type_t fs_type;
  12960             uint32 fs_inx;
  12961 
  12962             fs_type = _BCM_FLEX_STAT_TYPE(f_st->flex_mode);
  12963             fs_inx  = _BCM_FLEX_STAT_COUNT_INX(f_st->flex_mode);
  12964             rv = _bcm_esw_flex_stat_enable_set(unit, fs_type,
  12965                                                 _bcm_esw_fp_flex_stat_index_set,
  12966                                                 (void *)f_st, f_st->sid,
  12967                                                 TRUE,fs_inx);
  12968         } else {
  12969             rv = _bcm_esw_flex_stat_enable_set(unit, _bcmFlexStatTypeFp,
  12970                                                 _bcm_esw_fp_flex_stat_index_set,
  12971                                                 (void *)f_st, f_st->sid,
  12972                                                 TRUE,0);
  12973         }
  12974         if (BCM_SUCCESS(rv)) {
  12975            /* Increment the group counters count equal to
  12976            the hw entries count .*/
  12977            f_ent->group->group_status.counter_count =
  12978                  f_ent->group->group_status.counter_count + f_st->hw_entry_count;
  12979         }
  12980         return rv;
  12981     }
  12982 #endif /* BCM_TRIUMPH2_SUPPORT */
  12983 
  12984     /* Get entry stage control structure. */
  12985     rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc);
  12986     BCM_IF_ERROR_RETURN (rv);
  12987 
  12988 
  12989     /* Verify if statistics entity is color dependent. */
  12990     rv = _field_stat_color_dependent(unit, f_st, &color_dependent);
  12991     BCM_IF_ERROR_RETURN (rv);
  12992 
  12993     if ((0 == (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)) &&
  12994         (f_ent_pl->flags & _FP_POLICER_INSTALLED) &&
  12995         (color_dependent)) {
  12996         /* If meter is present, counter must reside in the same slice. */
  12997         if (f_ent->flags & _FP_ENTRY_POLICER_IN_SECONDARY_SLICE) {
  12998             rv = _field_slice_counter_alloc(unit, fs + 1, f_st);
  12999             if (BCM_SUCCESS(rv)) {
  13000                 /* Get primary entry from the second slice. */
  13001                 rv = _bcm_field_entry_flags_to_tcam_part (unit,
  13002                                                       _FP_ENTRY_SECONDARY,
  13003                                                       fg, &entry_part);
  13004                 BCM_IF_ERROR_RETURN(rv);
  13005                 f_ent->flags |= _FP_ENTRY_STAT_IN_SECONDARY_SLICE;
  13006                 sal_memcpy(&f_ent[entry_part].statistic, &f_ent->statistic,
  13007                            sizeof(_field_entry_stat_t));
  13008                 f_ent[entry_part].statistic.flags |= _FP_ENTRY_STAT_INSTALLED;
  13009             }
  13010         } else {
  13011             rv = _field_slice_counter_alloc(unit, fs, f_st);
  13012         }
  13013     } else {
  13014         rv = _field_slice_counter_alloc(unit, fs, f_st);
  13015         if((BCM_FAILURE(rv)) &&
  13016            ((f_ent->group->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) ||
  13017             (f_ent->group->flags & _FP_GROUP_SPAN_TRIPLE_SLICE))) {
  13018             rv = _field_slice_counter_alloc(unit, fs + 1, f_st);
  13019             if (BCM_SUCCESS(rv)) {
  13020                 rv = _bcm_field_entry_flags_to_tcam_part (unit,
  13021                                                     _FP_ENTRY_SECONDARY,
  13022                                                     fg, &entry_part);
  13023                 BCM_IF_ERROR_RETURN(rv);
  13024                 f_ent->flags |= _FP_ENTRY_STAT_IN_SECONDARY_SLICE;
  13025                 sal_memcpy(&f_ent[entry_part].statistic, &f_ent->statistic,
  13026                            sizeof(_field_entry_stat_t));
  13027                 f_ent[entry_part].statistic.flags |=  _FP_ENTRY_STAT_INSTALLED;
  13028             }
  13029         }
  13030     }
  13031     /* Increment the group counters count equal to
  13032            the hw entries count .*/
  13033     f_ent->group->group_status.counter_count =
  13034           f_ent->group->group_status.counter_count + f_st->hw_entry_count;
  13035     return (rv);
  13036 }
  13037 
  13038 
  13039 STATIC int
  13040 _field_counter_hw_alloc(int unit, _field_entry_t *f_ent, _field_slice_t *fs)
  13041 {
  13042 #ifdef BCM_TRIUMPH3_SUPPORT
  13043     if (SOC_IS_TRIUMPH3(unit)) {
  13044         return (_bcm_field_tr3_counter_hw_alloc(unit, f_ent));
  13045     }
  13046 #endif
  13047 
  13048     return (_bcm_field_counter_hw_alloc(unit, f_ent, fs));
  13049 }
  13050 
  13051 
  13052 /*
  13053  * Function:
  13054  *     _field_stat_hw_alloc
  13055  *
  13056  * Purpose:
  13057  *     Allocate counters required for entry installation.
  13058  *
  13059  * Parameters:
  13060  *     unit      - (IN) BCM device number.
  13061  *     f_ent     - (IN) Field entry array.
  13062  *     fs        - (IN) Slice to allocate a counter.
  13063  * Returns:
  13064  *     BCM_E_XXX
  13065  * Notes:
  13066  */
  13067 STATIC int
  13068 _field_stat_hw_alloc(int unit, _field_entry_t *f_ent)
  13069 {
  13070     _field_entry_stat_t    *f_ent_st;  /* Field entry stat structure.   */
  13071     _field_stat_t          *f_st;      /* Field statistics descriptor.  */
  13072     int                    rv;         /* Operation return status.      */
  13073     _field_stage_t         *stage_fc; /* Field stage control structure.*/
  13074 
  13075     /* Input parameters check. */
  13076     if (NULL == f_ent) {
  13077         return (BCM_E_PARAM);
  13078     }
  13079 
  13080     f_ent_st = &f_ent->statistic;
  13081 
  13082     /* Skip entries without countres attached. */
  13083     if ((0 == (f_ent_st->flags & _FP_ENTRY_STAT_VALID)) ||
  13084         (f_ent_st->flags & _FP_ENTRY_STAT_EMPTY)) {
  13085         return (BCM_E_NONE);
  13086     }
  13087 
  13088     /* No allocation is required for external FP, because:
  13089        - for TR/TR2, each entry has it's own dedicated counter, and
  13090        - for TR3, EXTFP supports only flex counters (as does VFP)
  13091      */
  13092     if ((_BCM_FIELD_STAGE_EXTERNAL == f_ent->fs->stage_id) &&
  13093         !soc_feature(unit, soc_feature_advanced_flex_counter)) {
  13094         f_ent_st->flags |=  _FP_ENTRY_STAT_INSTALLED;
  13095         return (BCM_E_NONE);
  13096     }
  13097 
  13098     /* Read statistics entity configuration. */
  13099     rv = _bcm_field_stat_get(unit, f_ent_st->sid, &f_st);
  13100     BCM_IF_ERROR_RETURN (rv);
  13101 
  13102 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA_SUPPORT)
  13103     if (soc_feature(unit, soc_feature_advanced_flex_counter)) {
  13104         /* Allocate flex STAT entity hw index. */
  13105         if (f_st->hw_flags & _FP_STAT_FLEX_CNTR) {
  13106             return (_field_flex_counter_hw_alloc(unit, f_ent));
  13107         }
  13108     }
  13109 #endif
  13110 
  13111 #if defined(BCM_HURRICANE3_SUPPORT)
  13112         if (soc_feature(unit, soc_feature_flowcnt)) {
  13113             /* Allocate flowcnt STAT entity hw index. */
  13114             if (f_st->hw_flags & _FP_STAT_FLOWCNT_CNTR) {
  13115                 return (_field_flowcnt_counter_hw_alloc(unit, f_ent));
  13116             }
  13117         }
  13118 #endif
  13119 
  13120     /* Allocate statistics entity hw index. */
  13121     if (_FP_INVALID_INDEX == f_st->hw_index) {
  13122         rv = _field_counter_hw_alloc(unit, f_ent, f_ent->fs);
  13123         BCM_IF_ERROR_RETURN(rv);
  13124     }
  13125 
  13126     /* Get stage control information. */
  13127     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
  13128                                                  f_ent->fs->stage_id,
  13129                                                  &stage_fc
  13130                                                  )
  13131                         );
  13132 
  13133     /* Validate STAT pool_index */
  13134     if (_BCM_FIELD_STAGE_INGRESS == f_ent->fs->stage_id
  13135         && !(stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS)
  13136         && !(stage_fc->flags & _FP_STAGE_GLOBAL_COUNTERS)
  13137         && (_FP_INVALID_INDEX != f_st->hw_index)) {
  13138         if ((!(f_ent->flags & _FP_ENTRY_STAT_IN_SECONDARY_SLICE)
  13139                 && f_ent->fs->slice_number != f_st->pool_index)
  13140             || ((f_ent->flags & _FP_ENTRY_STAT_IN_SECONDARY_SLICE)
  13141                 && f_ent->fs->slice_number + 1 != f_st->pool_index)) {
  13142             LOG_ERROR(BSL_LS_BCM_FP,
  13143                       (BSL_META_U(unit,
  13144                                   "FP(unit %d) - Counters cannot be shared between slices.\n"),
  13145                        unit));
  13146             LOG_ERROR(BSL_LS_BCM_FP,
  13147                       (BSL_META_U(unit,
  13148                                   "             Create a new stat and attach to EID=%d.\n"),
  13149                        f_ent->eid));
  13150             BCM_IF_ERROR_RETURN(_field_slice_counter_free(unit, f_ent, f_st));
  13151             return (BCM_E_CONFIG);
  13152         }
  13153     }
  13154 
  13155     /* Increment statistics hw reference count. */
  13156     if (0 == (f_ent_st->flags & _FP_ENTRY_STAT_INSTALLED)) {
  13157         f_ent_st->flags |=  _FP_ENTRY_STAT_INSTALLED;
  13158         f_st->hw_ref_count++;
  13159         if (1 == f_st->hw_ref_count) {
  13160             int idx;
  13161 
  13162             /* Write individual statistics privious value. */
  13163             for (idx = 0; idx < f_st->nstat; idx++) {
  13164                 rv = _field_stat_value_set(unit, f_st, f_st->stat_arr[idx],
  13165                                            f_st->stat_values[idx]);
  13166                 BCM_IF_ERROR_RETURN(rv);
  13167             }
  13168         }
  13169     }
  13170     return (BCM_E_NONE);
  13171 }
  13172 
  13173 /*
  13174  * Function:
  13175  *     _bcm_field_stat_hw_alloc
  13176  *
  13177  * Purpose:
  13178  *     Allocate counters required for entry installation.
  13179  *
  13180  * Parameters:
  13181  *     unit      - (IN) BCM device number.
  13182  *     f_ent     - (IN) Field entry array.
  13183  *     fs        - (IN) Slice to allocate a counter.
  13184  * Returns:
  13185  *     BCM_E_XXX
  13186  * Notes:
  13187  */
  13188 int
  13189 _bcm_field_stat_hw_alloc(int unit, _field_entry_t *f_ent)
  13190 {
  13191     /* Input parameters check. */
  13192     if (NULL == f_ent) {
  13193         return (BCM_E_PARAM);
  13194     }
  13195 
  13196     return _field_stat_hw_alloc(unit, f_ent);
  13197 }
  13198 /*
  13199  * Function:
  13200  *     _field_mirror_dest_delete
  13201  * Purpose:
  13202  *     Unset mirroring destination & disable mirroring for rule matching
  13203  *     packets.
  13204  * Parameters:
  13205  *     unit     - (IN) BCM device number
  13206  *     fa       - (IN) Field action descriptor.
  13207  * Returns:
  13208  *     BCM_E_XXX
  13209  */
  13210 STATIC int
  13211 _field_mirror_dest_delete(int unit, _field_entry_t  *f_ent, _field_action_t *fa, uint32 flags)
  13212 {
  13213     uint32 mirror_flags;      /* Mirror module flags.     */
  13214     int rv;
  13215     uint32 mirror_slot_flags;
  13216 
  13217     /* Input parameters check */
  13218     if ((NULL == fa) || (NULL == f_ent)) {
  13219         return (BCM_E_PARAM);
  13220     }
  13221 
  13222     /* Set mirror flags. */
  13223     if (bcmFieldActionMirrorIngress == fa->action) {
  13224         mirror_flags = BCM_MIRROR_PORT_INGRESS;
  13225     }  else if (bcmFieldActionMirrorEgress == fa->action) {
  13226         if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) {
  13227             mirror_flags = BCM_MIRROR_PORT_EGRESS_TRUE;
  13228         } else {
  13229             /* Stage Ingress */
  13230             mirror_flags = BCM_MIRROR_PORT_EGRESS;
  13231         }
  13232     } else {
  13233         return (BCM_E_PARAM);
  13234     }
  13235 
  13236     if ((flags & _FP_ACTION_RESOURCE_FREE) &&
  13237         (_FP_INVALID_INDEX != fa->hw_index)) {
  13238            rv = _bcm_esw_mirror_fp_dest_delete(unit, fa->hw_index, mirror_flags);
  13239            BCM_IF_ERROR_RETURN(rv);
  13240            fa->hw_index = _FP_INVALID_INDEX;
  13241 
  13242            /* Delete Ref to any mirror slot container if any */
  13243            if (mirror_flags & BCM_MIRROR_PORT_INGRESS) {
  13244                 mirror_slot_flags =
  13245                             _BCM_MIRROR_SLOT_INGRESS | _BCM_MIRROR_SLOT_FP;
  13246                 BCM_IF_ERROR_RETURN
  13247                  (_bcm_esw_mirror_fp_slot_del_ref(unit,
  13248                                                   mirror_slot_flags,
  13249                                                   f_ent->ing_mtp_slot_map));
  13250                 f_ent->ing_mtp_slot_map = 0;
  13251             }
  13252             if (mirror_flags & BCM_MIRROR_PORT_EGRESS) {
  13253                 mirror_slot_flags =
  13254                             _BCM_MIRROR_SLOT_EGRESS | _BCM_MIRROR_SLOT_FP;
  13255                 BCM_IF_ERROR_RETURN
  13256                  (_bcm_esw_mirror_fp_slot_del_ref(unit,
  13257                                                   mirror_slot_flags,
  13258                                                   f_ent->egr_mtp_slot_map));
  13259                 f_ent->egr_mtp_slot_map = 0;
  13260             }
  13261     }
  13262 
  13263     if ((flags & _FP_ACTION_OLD_RESOURCE_FREE) &&
  13264         (_FP_INVALID_INDEX != fa->old_index)) {
  13265           rv = _bcm_esw_mirror_fp_dest_delete(unit, fa->old_index, mirror_flags);
  13266           BCM_IF_ERROR_RETURN(rv);
  13267           fa->old_index = _FP_INVALID_INDEX;
  13268 
  13269           /* Delete Referece to Mirror Slot Container if any */
  13270           if (mirror_flags & BCM_MIRROR_PORT_INGRESS) {
  13271               mirror_slot_flags =
  13272                             _BCM_MIRROR_SLOT_INGRESS | _BCM_MIRROR_SLOT_FP;
  13273               BCM_IF_ERROR_RETURN
  13274                  (_bcm_esw_mirror_fp_slot_del_ref(unit,
  13275                                                   mirror_slot_flags,
  13276                                                   f_ent->ing_mtp_slot_map));
  13277               f_ent->ing_mtp_slot_map = 0;
  13278           }
  13279           if (mirror_flags & BCM_MIRROR_PORT_EGRESS) {
  13280               mirror_slot_flags =
  13281                             _BCM_MIRROR_SLOT_EGRESS | _BCM_MIRROR_SLOT_FP;
  13282               BCM_IF_ERROR_RETURN
  13283                  (_bcm_esw_mirror_fp_slot_del_ref(unit,
  13284                                                   mirror_slot_flags,
  13285                                                   f_ent->egr_mtp_slot_map));
  13286               f_ent->egr_mtp_slot_map = 0;
  13287           }
  13288     }
  13289     return (BCM_E_NONE);
  13290 }
  13291 
  13292 /*
  13293  * Function:
  13294  *     _field_mirror_dest_add
  13295  * Purpose:
  13296  *     Set mirroring destination & enable mirroring for rule matching
  13297  *     packets.
  13298  * Parameters:
  13299  *     unit     - (IN) BCM device number
  13300  *     fa       - (IN) field action
  13301  * Returns:
  13302  *     BCM_E_XXX
  13303  */
  13304 STATIC int
  13305 _field_mirror_dest_add (int unit, _field_entry_t *f_ent, _field_action_t *fa)
  13306 {
  13307     uint32 mirror_flags;      /* Mirror module flags.     */
  13308 
  13309     /* Input parameters check. */
  13310     if ((NULL == fa) || (NULL == f_ent)) {
  13311         return (BCM_E_PARAM);
  13312     }
  13313 
  13314     /* Set mirror flags. */
  13315     if (bcmFieldActionMirrorIngress == fa->action) {
  13316         mirror_flags = BCM_MIRROR_PORT_INGRESS;
  13317     }  else if (bcmFieldActionMirrorEgress == fa->action) {
  13318         if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) {
  13319             mirror_flags = BCM_MIRROR_PORT_EGRESS_TRUE;
  13320         } else {
  13321             /* Stage Ingress */
  13322             mirror_flags = BCM_MIRROR_PORT_EGRESS;
  13323         }
  13324     } else {
  13325         return (BCM_E_PARAM);
  13326     }
  13327 
  13328     return _bcm_esw_mirror_fp_dest_add(unit,  fa->param[0], fa->param[1],
  13329                                        mirror_flags, &fa->hw_index);
  13330 }
  13331 
  13332 
  13333 /*
  13334  * Function:
  13335  *      _field_slice_counter_available
  13336  * Purpose:
  13337  *      Checks if counter might be installed in a slice.
  13338  * Parameters:
  13339  *   unit       - (IN) BCM device number.
  13340  *   f_st       - (IN) Field statistics entity.
  13341  *   fs         - (IN) Destination slice.
  13342  * Returs:
  13343  *   BCM_E_XXX
  13344  */
  13345 int
  13346 _field_slice_counter_available(int unit, _field_stat_t *f_st, _field_slice_t *fs)
  13347 {
  13348     int  idx;            /* Counters iteration index.        */
  13349 
  13350     /* Input parameters check. */
  13351     if ((NULL == f_st) || (NULL == fs)) {
  13352         return (BCM_E_PARAM);
  13353     }
  13354 
  13355     /* Check if target slice has a free counters */
  13356     for (idx = 0; idx < fs->counters_count; idx++) {
  13357         if (0x2 == f_st->hw_entry_count) {
  13358             if (0 != (idx % 2)) {
  13359                 /* Skip odd indexes. */
  13360                 continue;
  13361             }
  13362             if ((0 == _FP_COUNTER_BMP_TEST(fs->counter_bmp, idx)) &&
  13363                 (0 == _FP_COUNTER_BMP_TEST(fs->counter_bmp, (idx+ 1)))) {
  13364                     break;
  13365             }
  13366         } else if (0 == _FP_COUNTER_BMP_TEST(fs->counter_bmp, idx)) {
  13367             break;
  13368         }
  13369     }
  13370 
  13371     if (idx == fs->counters_count) {
  13372         return (BCM_E_RESOURCE);
  13373     }
  13374     return (BCM_E_NONE);
  13375 }
  13376 
  13377 
  13378 /*
  13379  * Function:
  13380  *     _field_slice_meter_available
  13381  * Purpose:
  13382  *      Checks if policer might be installed in a slice.
  13383  * Parameters:
  13384  *   unit       - (IN) BCM device number.
  13385  *   f_pl       - (IN) Policer descriptor.
  13386  *   fs         - (IN) Destination slice.
  13387  * Returs:
  13388  *   BCM_E_XXX
  13389  */
  13390 STATIC int
  13391 _field_slice_meter_available(int unit, _field_policer_t *f_pl, _field_slice_t *fs)
  13392 {
  13393     int   idx;            /* Meters iteration index.       */
  13394 
  13395     /* Input parameters check. */
  13396     if ((NULL == f_pl) || (NULL == fs)) {
  13397         return (BCM_E_PARAM);
  13398     }
  13399 
  13400     /* Check if target slice has a free meter */
  13401     for (idx = 0; idx < fs->meters_count; idx++) {
  13402         if (!_FP_POLICER_IS_FLOW_MODE(f_pl)) {
  13403             if (0 != (idx % 2)) {
  13404                 /* skip odd */
  13405                 continue;
  13406             }
  13407 
  13408             if ((0 == _FP_METER_BMP_TEST(fs->meter_bmp, idx))
  13409                 && (0 == _FP_METER_BMP_TEST(fs->meter_bmp, idx + 1))) {
  13410                 break;
  13411             }
  13412         }
  13413 
  13414         if (_FP_POLICER_IS_FLOW_MODE(f_pl)
  13415             && 0 == _FP_METER_BMP_TEST(fs->meter_bmp, idx)) {
  13416             break;
  13417         }
  13418     }
  13419 
  13420     if (idx == fs->meters_count) {
  13421         return (BCM_E_RESOURCE);
  13422     }
  13423     return (BCM_E_NONE);
  13424 }
  13425 
  13426 
  13427 /*
  13428  * Function: _field_entry_install_slice_fit
  13429  *
  13430  * Purpose: Checks if slice has HW resource required for entry installation.
  13431  * Parameters:
  13432  *   unit        - (IN) BCM device number.
  13433  *   stage_fc    - (IN) Stage field control.
  13434  *   f_ent       - (IN) Entry to be inserted.
  13435  *   fs          - (IN) Destination slice.
  13436  * Returs:
  13437  *   BCM_E_NONE - Entry fits the slice.
  13438  *   BCM_E_XXX  - Otherwise.
  13439  */
  13440 STATIC int
  13441 _field_entry_install_slice_fit(int unit, _field_stage_t *stage_fc,
  13442                        _field_entry_t *f_ent, _field_slice_t *fs)
  13443 {
  13444     _field_entry_policer_t *f_ent_pl;      /* Field entry policers.    */
  13445     _field_entry_stat_t    *f_ent_st;      /* Field entry statistics.  */
  13446     _field_stat_t          *f_st;          /* Field statistics entity. */
  13447     _field_policer_t       *f_pl;          /* Field policer.           */
  13448     _field_group_t         *fg;            /* Field group structure.   */
  13449     uint8                  color_dependent;/* Stat is color dependend. */
  13450     int                    rv;             /* Operation return status. */
  13451 
  13452     /* Input parameters check. */
  13453     if ((NULL == stage_fc) || (NULL == f_ent) || (NULL == fs)) {
  13454         return (BCM_E_PARAM);
  13455     }
  13456     fg = f_ent->group;
  13457 
  13458     /* Reset allocation flags. */
  13459     f_ent->flags &= ~_FP_ENTRY_ALLOC_FROM_SECONDARY_SLICE;
  13460 
  13461     /* If device supports global meter pools or no meter installed -> no issue. */
  13462     f_ent_pl = f_ent->policer;
  13463     if ((stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) ||
  13464         (0 == (f_ent_pl->flags & _FP_POLICER_VALID))) {
  13465         f_pl = NULL;
  13466     }  else {
  13467         rv = _bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl);
  13468         BCM_IF_ERROR_RETURN(rv);
  13469         if (_FP_INVALID_INDEX != f_pl->hw_index) {
  13470             f_pl = NULL; /* NO allocation required. */
  13471         }
  13472     }
  13473 
  13474     /* If device supports global counters or no counter installed -> no issue. */
  13475     f_ent_st = &f_ent->statistic;
  13476     if (_BCM_FIELD_STAGE_EXTERNAL == stage_fc->stage_id) {
  13477         /* Nothing to do for external FP, because:
  13478            - for TR/TR2, each entry has it's own dedicated counter, and
  13479            - for TR3, EXTFP supports only flex counters (as does VFP)
  13480         */
  13481         f_st = NULL;
  13482     } else if ((stage_fc->flags & _FP_STAGE_GLOBAL_COUNTERS) ||
  13483                (stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS) ||
  13484         (0 == (f_ent_st->flags & _FP_ENTRY_STAT_VALID))) {
  13485         f_st = NULL;
  13486     }  else {
  13487         rv = _bcm_field_stat_get(unit, f_ent_st->sid, &f_st);
  13488         BCM_IF_ERROR_RETURN(rv);
  13489 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  13490         if (soc_feature(unit, soc_feature_advanced_flex_counter)) {
  13491             if (f_st->flex_mode != 0) {
  13492                 return BCM_E_NONE; /* NO allocation required. */
  13493             }
  13494             if (stage_fc->stage_id == _BCM_FIELD_STAGE_LOOKUP) {
  13495                 return BCM_E_NONE;
  13496             }
  13497         }
  13498 #endif
  13499         if (_FP_INVALID_INDEX != f_st->hw_index) {
  13500             f_st = NULL; /* NO allocation required. */
  13501         }
  13502     }
  13503 
  13504     /* Check if counter & meter are available in primary slice. */
  13505     rv = BCM_E_NONE;
  13506     /*    coverity[new_values : FALSE]    */
  13507     if (f_pl != NULL) {
  13508         rv =  _field_slice_meter_available(unit, f_pl, fs);
  13509     }
  13510     if ((f_st != NULL) && (BCM_SUCCESS (rv))) {
  13511         rv = _field_slice_counter_available(unit, f_st, fs);
  13512     }
  13513     if (BCM_SUCCESS (rv)) {
  13514         return (BCM_E_NONE);
  13515     }
  13516 
  13517     if ((fg->flags  & _FP_GROUP_SPAN_DOUBLE_SLICE) ||
  13518         (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE)) {
  13519         /* No counters -> policer can be allocated from any slice. */
  13520         /* No policers -> counter can be allocated from any slice. */
  13521         if ((f_st == NULL) || (f_pl == NULL)) {
  13522             return (BCM_E_NONE);
  13523         }
  13524 
  13525         /*
  13526          * Only if counter is color blind it might be allocated
  13527          * in a slice a different s policer.
  13528          */
  13529 
  13530         /* Check if statistics entity is color dependent. */
  13531         rv = _field_stat_color_dependent(unit, f_st, &color_dependent);
  13532         BCM_IF_ERROR_RETURN(rv);
  13533         if (FALSE == color_dependent) {
  13534             return (BCM_E_NONE);
  13535         }
  13536 
  13537         /* Check if counter & meter are available in secondary slice. */
  13538         rv =  _field_slice_meter_available(unit, f_pl, fs + 1);
  13539         if (BCM_SUCCESS (rv)) {
  13540             rv =  _field_slice_counter_available(unit, f_st, fs + 1);
  13541         }
  13542 
  13543         /* Policer must be allocated from secondary slice */
  13544         if (BCM_SUCCESS (rv)) {
  13545             f_ent->flags |= _FP_ENTRY_ALLOC_FROM_SECONDARY_SLICE;
  13546             return (BCM_E_NONE);
  13547         }
  13548     }
  13549     return (BCM_E_RESOURCE);
  13550 }
  13551 
  13552 /*
  13553  * Function: _field_entry_move_slice_fit
  13554  *
  13555  * Purpose: Checks if slice has HW resource required for entry movement.
  13556  * Parameters:
  13557  *   unit        - (IN) BCM device number.
  13558  *   stage_fc    - (IN) Stage field control.
  13559  *   f_ent       - (IN) Entry to be inserted.
  13560  *   fs          - (IN) Destination slice.
  13561  *   freed_counters - (INOUT) Number of counters to be freed by a planned move
  13562  * Returs:
  13563  *   BCM_E_NONE - Entry fits the slice.
  13564  *   BCM_E_XXX  - Otherwise.
  13565  */
  13566 STATIC int
  13567 _field_entry_move_slice_fit(int unit, _field_stage_t *stage_fc,
  13568     _field_entry_t *f_ent, _field_slice_t *fs, int *freed_meters,
  13569     int *freed_counters)
  13570 {
  13571     _field_entry_policer_t *f_ent_pl;      /* Field entry policers.    */
  13572     _field_entry_stat_t    *f_ent_st;      /* Field entry statistics.  */
  13573     _field_stat_t          *f_st;          /* Field statistics entity. */
  13574     _field_policer_t       *f_pl;          /* Field policer.           */
  13575     _field_group_t         *fg;            /* Field group structure.   */
  13576     uint8                  color_dependent;/* Stat is color dependend. */
  13577     int                    rv = BCM_E_NONE;/* Operation return status. */
  13578 
  13579     /* Input parameters check. */
  13580     if ((NULL == stage_fc) || (NULL == f_ent) || (NULL == fs)) {
  13581         return (BCM_E_PARAM);
  13582     }
  13583 
  13584     fg = f_ent->group;
  13585 
  13586     /* Reset allocation flags. */
  13587     f_ent->flags &= ~_FP_ENTRY_ALLOC_FROM_SECONDARY_SLICE;
  13588 
  13589     /* If device supports global meter pools or no meter installed -> no issue. */
  13590     f_ent_pl = f_ent->policer;
  13591     if ((stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) ||
  13592         (0 == (f_ent_pl->flags & _FP_POLICER_VALID))) {
  13593         f_pl = NULL;
  13594     }  else {
  13595         rv = _bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl);
  13596         BCM_IF_ERROR_RETURN(rv);
  13597 
  13598         /* Reject policers shared by multiple entries. */
  13599         if (2 != f_pl->sw_ref_count) {
  13600             return (BCM_E_RESOURCE);
  13601         }
  13602     }
  13603 
  13604     /* If device supports global counters or no counter installed -> no issue. */
  13605     f_ent_st = &f_ent->statistic;
  13606     if ((stage_fc->flags & _FP_STAGE_GLOBAL_COUNTERS) ||
  13607         (stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS) ||
  13608         (0 == (f_ent_st->flags & _FP_ENTRY_STAT_VALID))) {
  13609         f_st = NULL;
  13610     }  else {
  13611         rv = _bcm_field_stat_get(unit, f_ent_st->sid, &f_st);
  13612         BCM_IF_ERROR_RETURN(rv);
  13613 
  13614         /* Reject counters shared by multiple entries. */
  13615         if (2 != f_st->sw_ref_count) {
  13616             return (BCM_E_RESOURCE);
  13617         }
  13618     }
  13619 
  13620     /* Check if counter & meter are available in primary slice. */
  13621 
  13622     rv = BCM_E_NONE;
  13623 
  13624     /* coverity[new_values : FALSE]    */
  13625     if (f_pl != NULL && *freed_meters == 0)
  13626     {
  13627         rv =  _field_slice_meter_available(unit, f_pl, fs);
  13628     }
  13629 
  13630     if ((f_st != NULL) && (BCM_SUCCESS (rv)))
  13631     {
  13632         if (f_st->hw_entry_count > *freed_counters)
  13633         {
  13634             f_st->hw_entry_count -= *freed_counters;
  13635             rv = _field_slice_counter_available(unit, f_st, fs);
  13636             f_st->hw_entry_count += *freed_counters;
  13637         }
  13638     }
  13639 
  13640     if (BCM_SUCCESS (rv))
  13641     {
  13642         *freed_meters = (f_pl != NULL) ? 1 : 0;
  13643         *freed_counters = (f_st != NULL) ? f_st->hw_entry_count : 0;
  13644 
  13645         return (BCM_E_NONE);
  13646     }
  13647 
  13648     if ((fg->flags  & _FP_GROUP_SPAN_DOUBLE_SLICE) ||
  13649         (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE)) {
  13650         /* No counters -> policer can be allocated from any slice. */
  13651         /* No policers -> counter can be allocated from any slice. */
  13652         if ((NULL == f_st) || (NULL == f_pl)) {
  13653             return (BCM_E_NONE);
  13654         }
  13655 
  13656         /*
  13657          * Only if counter is color blind it might be allocated
  13658          * in a slice a different s policer.
  13659          */
  13660 
  13661         /* Check if statistics entity is color dependent. */
  13662         rv = _field_stat_color_dependent(unit, f_st, &color_dependent);
  13663         BCM_IF_ERROR_RETURN(rv);
  13664         if (FALSE == color_dependent) {
  13665             return (BCM_E_NONE);
  13666         }
  13667 
  13668         /* Check if counter & meter are available in secondary slice. */
  13669         rv =  _field_slice_meter_available(unit, f_pl, fs + 1);
  13670         if (BCM_SUCCESS (rv)) {
  13671             rv =  _field_slice_counter_available(unit, f_st, fs + 1);
  13672         }
  13673 
  13674         /* Policer must be allocated from secondary slice */
  13675         if (BCM_SUCCESS (rv)) {
  13676             f_ent->flags |= _FP_ENTRY_ALLOC_FROM_SECONDARY_SLICE;
  13677             return (BCM_E_NONE);
  13678         }
  13679     }
  13680     return (BCM_E_RESOURCE);
  13681 }
  13682 
  13683 /*
  13684  * Function:
  13685  *      _field_action_hw_resources_free
  13686  * Purpose:
  13687  *      Free hw resources allocated for field action installation.
  13688  * Parameters:
  13689  *      unit     - (IN) BCM device number
  13690  *      f_ent    - (IN) Field entry structure.
  13691  *      fa       - (IN) Field action structure.
  13692  * Returns:
  13693  *      BCM_E_XXX
  13694  * Notes:
  13695  */
  13696 int
  13697 _field_action_hw_resources_free(int unit, _field_entry_t  *f_ent,
  13698                                 _field_action_t *fa,uint32 flags)
  13699 {
  13700     int rv; /* Operational Status */
  13701 #if defined(BCM_TOMAHAWK_SUPPORT)
  13702     _field_control_t *fc; /* Field Control Structure */
  13703 #endif
  13704 #if defined(INCLUDE_L3)
  13705 #if defined (BCM_KATANA_SUPPORT) || defined (BCM_TRIDENT_SUPPORT) \
  13706          || defined (BCM_TRIUMPH3_SUPPORT) || defined (BCM_GREYHOUND_SUPPORT) \
  13707          || defined (BCM_ENDURO_SUPPORT)
  13708     uint32 flags_action;         /* L3 forwarding flags.    */
  13709     int nh_ecmp_id;              /* Next hop/Ecmp group id. */
  13710 #endif
  13711 #endif /* INCLUDE_L3 */
  13712 
  13713 #if defined(BCM_TRIDENT2_SUPPORT)
  13714     soc_mem_t mem;
  13715 #endif
  13716 
  13717 #if defined(INCLUDE_L3)
  13718 #if defined (BCM_KATANA_SUPPORT) || defined (BCM_TRIDENT_SUPPORT) \
  13719          || defined (BCM_TRIUMPH3_SUPPORT) || defined (BCM_GREYHOUND_SUPPORT)
  13720     flags_action = 0;
  13721     nh_ecmp_id = 0;
  13722 #endif
  13723 #endif
  13724     /* Input parameters check. */
  13725     if ((NULL == f_ent) || (NULL == fa)) {
  13726         return (BCM_E_PARAM);
  13727     }
  13728 
  13729 
  13730     switch (fa->action) {
  13731       case bcmFieldActionMirrorIngress:
  13732       case bcmFieldActionMirrorEgress:
  13733           return _field_mirror_dest_delete(unit, f_ent, fa,flags);
  13734           break;
  13735       case bcmFieldActionRedirectMcast:
  13736 #if defined(INCLUDE_L3)
  13737       case bcmFieldActionRedirectIpmc:
  13738 #endif /* INCLUDE_L3 */
  13739           if (soc_feature(unit, soc_feature_field_action_redirect_ipmc)){
  13740               break;
  13741           }
  13742       case bcmFieldActionRedirectPbmp:
  13743       case bcmFieldActionEgressMask:
  13744       case bcmFieldActionEgressPortsAdd:
  13745           /* Applicable to stage ingress on TRX devices only. */
  13746           if ((0 == SOC_IS_TRX(unit)) ||
  13747               ((_BCM_FIELD_STAGE_INGRESS != f_ent->group->stage_id) &&
  13748                (_BCM_FIELD_STAGE_EXACTMATCH !=  f_ent->group->stage_id))) {
  13749               break;
  13750           }
  13751 #if defined (BCM_TOMAHAWK3_SUPPORT)
  13752           if ((fa->action == bcmFieldActionEgressMask) &&
  13753               (soc_feature(unit, soc_feature_th3_style_fp))) {
  13754               BCM_IF_ERROR_RETURN
  13755                   (_bcm_field_th3_redirect_profile_delete(unit, fa->hw_index));
  13756           } else
  13757 #endif
  13758 #if defined(BCM_TRX_SUPPORT)
  13759           {
  13760               BCM_IF_ERROR_RETURN
  13761                   (_bcm_field_trx_redirect_profile_delete(unit, fa->hw_index));
  13762           }
  13763 #endif /* BCM_TRX_SUPPORT */
  13764           break;
  13765 #if defined(INCLUDE_L3)
  13766 #if defined(BCM_FIREBOLT_SUPPORT) || defined(BCM_TRX_SUPPORT)
  13767       case bcmFieldActionSrcMacNew:
  13768       case bcmFieldActionDstMacNew:
  13769       case bcmFieldActionOuterVlanNew:
  13770           if (soc_feature(unit, soc_feature_field_action_l2_change)) {
  13771               BCM_IF_ERROR_RETURN(_bcm_field_l2_actions_hw_free(unit, f_ent,
  13772                         _FP_ACTION_HW_FREE));
  13773 
  13774           }
  13775           break;
  13776 #endif /* BCM_TRX_SUPPORT || BCM_FIREBOLT2_SUPPORT */
  13777 
  13778 #if defined (BCM_KATANA_SUPPORT) || defined (BCM_TRIDENT_SUPPORT) \
  13779          || defined (BCM_TRIUMPH3_SUPPORT) || defined (BCM_GREYHOUND_SUPPORT) \
  13780          || defined (BCM_ENDURO_SUPPORT)
  13781       case bcmFieldActionL3ChangeMacDa:
  13782       case bcmFieldActionL3ChangeVlan:
  13783           if (SOC_IS_KATANAX(unit) || SOC_IS_TD_TT(unit)
  13784               || SOC_IS_TRIUMPH3(unit) || SOC_IS_GREYHOUND(unit) ||
  13785               SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) {
  13786               BCM_IF_ERROR_RETURN(_bcm_field_l3_egress_actions_reset(unit,
  13787                                                   f_ent, _FP_ACTION_HW_FREE));
  13788           }
  13789           break;
  13790       case bcmFieldActionL3Switch:
  13791       case bcmFieldActionRedirectEgrNextHop:
  13792           if (SOC_IS_KATANAX(unit) || SOC_IS_TD_TT(unit)
  13793                   || SOC_IS_TRIUMPH3(unit) || SOC_IS_GREYHOUND(unit)
  13794                   || SOC_IS_HURRICANEX(unit) || SOC_IS_ENDURO(unit)
  13795                   || SOC_IS_GREYHOUND2(unit)) {
  13796               BCM_IF_ERROR_RETURN(_bcm_field_policy_set_l3_nh_resolve (unit,
  13797                           fa->param[0], &flags_action, &nh_ecmp_id));
  13798 
  13799               BCM_IF_ERROR_RETURN(bcmi_esw_l3_egress_ref_count_update (unit,
  13800                           fa->param[0], flags_action, nh_ecmp_id,0));
  13801               fa->hw_index = _FP_INVALID_INDEX;
  13802           }
  13803           break;
  13804 #endif /* BCM_KATANA_SUPPORT || BCM_TRIDENT_SUPPORT || BCM_TRIUMPH3_SUPPORT \
  13805           || BCM_GREYHOUND_SUPPORT || BCM_ENDURO_SUPPORT */
  13806 
  13807 #if defined(BCM_TRIDENT2_SUPPORT) /* BCM_TRIDENT2_SUPPORT */
  13808       case bcmFieldActionNatEgressOverride:
  13809           BCM_IF_ERROR_RETURN(_bcm_esw_nat_egress_ref_count_update
  13810                   (unit, fa->param[0], 0));
  13811           fa->hw_index = _FP_INVALID_INDEX;
  13812           break;
  13813 #endif /* BCM_TRIDENT2_SUPPORT */
  13814 
  13815 #endif /* INCLUDE_L3 */
  13816 
  13817 #if defined(BCM_TRIDENT2_SUPPORT)
  13818       case bcmFieldActionHashSelect0:
  13819       case bcmFieldActionHashSelect1:
  13820           /* Applicable to stage lookup on TRIDENT2 device only. */
  13821           if ((0 == (SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit)
  13822                       || soc_feature(unit, soc_feature_field_multi_pipe_support)))
  13823                       || (_BCM_FIELD_STAGE_LOOKUP != f_ent->group->stage_id)) {
  13824               break;
  13825           }
  13826           mem = ((fa->action == bcmFieldActionHashSelect0)?
  13827                   VFP_HASH_FIELD_BMAP_TABLE_Am:
  13828                   VFP_HASH_FIELD_BMAP_TABLE_Bm);
  13829          BCM_IF_ERROR_RETURN(_bcm_field_td2_hash_select_profile_delete(unit,
  13830                                                          mem,
  13831                                                          fa->hw_index));
  13832           break;
  13833 #endif /* BCM_TRIDENT2_SUPPORT */
  13834 #if defined(BCM_TOMAHAWK_SUPPORT)
  13835       case bcmFieldActionFabricEHAddOrUpdate:
  13836 
  13837           BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  13838           if(NULL != fc->functions.fp_eh_mask_profile_hw_free) {
  13839               rv = fc->functions.fp_eh_mask_profile_hw_free(unit, f_ent, flags);
  13840               BCM_IF_ERROR_RETURN(rv);
  13841           }
  13842           break;
  13843 #endif
  13844 #if defined(BCM_TRIDENT3_SUPPORT)
  13845       case bcmFieldActionVlanActions:
  13846           BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  13847           if (NULL != fc->functions.fp_vlan_actions_profile_hw_free) {
  13848              rv = fc->functions.fp_vlan_actions_profile_hw_free(unit, f_ent, flags);
  13849              BCM_IF_ERROR_RETURN(rv);
  13850           }
  13851           break;
  13852 #endif /* BCM_TRIDENT3_SUPPORT */
  13853 #if defined(BCM_FLOWTRACKER_SUPPORT)
  13854       case bcmFieldActionFlowtrackerGroupId:
  13855           rv = _bcm_field_hx5_ft_group_hw_free(unit, f_ent, flags);
  13856           BCM_IF_ERROR_RETURN(rv);
  13857           break;
  13858 #endif
  13859       case bcmFieldActionMatchPbmpRedirect:
  13860       case bcmFieldActionMatchPbmpDrop:
  13861           if (soc_feature(unit, soc_feature_th3_style_fp)) {
  13862               rv = _field_delayed_profile_hw_free(unit, f_ent, flags);
  13863               BCM_IF_ERROR_RETURN(rv);
  13864           }
  13865           break;
  13866       default:
  13867           break;
  13868     }
  13869     fa->hw_index = _FP_INVALID_INDEX;
  13870     return (BCM_E_NONE);
  13871 }
  13872 
  13873 /*
  13874  * Function:
  13875  *     _field_mtp_hw_free
  13876  *
  13877  * Purpose:
  13878  *     Free mtp indexes used in field entry
  13879  *
  13880  * Parameters:
  13881  *     unit      - (IN) BCM device number.
  13882  *     f_ent     - (IN) Field entry descriptor.
  13883  * Returns:
  13884  *     BCM_E_XXX
  13885  * Notes:
  13886  */
  13887 STATIC int
  13888 _field_mtp_hw_free (int unit, _field_entry_t *f_ent, uint32 flags)
  13889 {
  13890     _field_action_t *fa;        /* Field action descriptor. */
  13891     int rv;                     /* Operation return status. */
  13892 
  13893     /* Extract action info from the entry structure. */
  13894     for (fa = f_ent->actions; fa != NULL; fa = fa->next) {
  13895         /* Allocate mtp destination only for mirroring actions */
  13896         if ((bcmFieldActionMirrorIngress != fa->action) &&
  13897             (bcmFieldActionMirrorEgress != fa->action)) {
  13898             continue;
  13899         }
  13900 
  13901         if ((_FP_INVALID_INDEX == fa->hw_index) && (_FP_INVALID_INDEX == fa->old_index) ) {
  13902             continue;
  13903         }
  13904 
  13905         rv = _field_action_hw_resources_free(unit, f_ent, fa,flags);
  13906         BCM_IF_ERROR_RETURN(rv);
  13907     }
  13908 
  13909     return (BCM_E_NONE);
  13910 }
  13911 
  13912 
  13913 /*
  13914  * Function:
  13915  *      _field_invalid_actions_remove
  13916  * Purpose:
  13917  *      Remove deleted actions from entry actions
  13918  *      linked list.
  13919  * Parameters:
  13920  *      unit  - (IN) BCM device number
  13921  *      f_ent - (IN) Field entry structure.
  13922  * Returns:
  13923  *      BCM_E_XXX
  13924  * Notes:
  13925  */
  13926 int
  13927 _field_invalid_actions_remove(int unit, _field_entry_t  *f_ent)
  13928 {
  13929     _field_action_t     *fa;
  13930     _field_action_t     *fa_prev = NULL;
  13931     _field_action_t     *fa_next = NULL;
  13932     _field_action_t     *fa_iter;        /* Field entry actions iterator.*/
  13933     int                 rv;
  13934 #if defined(BCM_TRIDENT_SUPPORT)
  13935     uint8               idx;             /* Entry array action dest index. */
  13936     uint32              entry_flags;     /* Entry flags                    */
  13937 #endif
  13938 #ifdef BCM_KATANA_SUPPORT
  13939     uint32 param0 = 0, param1 = 0, in_flags = 0;
  13940     int queue_id = 0;
  13941     ing_queue_map_entry_t ing_queue_entry;
  13942     int referenceCount = 0;
  13943 #endif
  13944 
  13945     /* Input parameters check. */
  13946     if (NULL == f_ent) {
  13947         return (BCM_E_PARAM);
  13948     }
  13949 
  13950     /* Find the action in the entry */
  13951     fa = f_ent->actions; /* start at head */
  13952     while (fa != NULL) {
  13953         fa_next = fa->next;
  13954         if (fa->flags & _FP_ACTION_VALID) {
  13955             fa_prev = fa;
  13956             fa      = fa_next;
  13957             continue;
  13958         }
  13959 #if defined (BCM_TRIUMPH3_SUPPORT)
  13960         if ( SOC_IS_TRIUMPH3(unit) && (_FP_INVALID_INDEX != fa->hw_index) &&
  13961              ((fa->action == bcmFieldActionReplaceSrcMac) ||
  13962               (fa->action == bcmFieldActionReplaceDstMac) ||
  13963               (fa->action == bcmFieldActionReplaceInnerVlan) ||
  13964               (fa->action == bcmFieldActionReplaceOuterVlan) ||
  13965               (fa->action == bcmFieldActionReplaceInnerVlanPriority)  ||
  13966               (fa->action == bcmFieldActionReplaceOuterVlanPriority) )) {
  13967             rv = _bcm__field_tr3_action_replaceL2Fields_remove_HWEntries(unit, f_ent, fa);
  13968             BCM_IF_ERROR_RETURN(rv);
  13969         }
  13970 #endif
  13971 
  13972         if (_FP_INVALID_INDEX != fa->hw_index) {
  13973             /*
  13974              * Check if a valid instance of this action exists in
  13975              * the entry actions linked list.
  13976              * If TRUE, hardware index must be freed only
  13977              * after updating policy table with new information.
  13978              */
  13979             if ((bcmFieldActionEgressMask == fa->action)
  13980                 || (bcmFieldActionRedirectBcastPbmp == fa->action)
  13981                 || (bcmFieldActionRedirectPbmp == fa->action)
  13982                 || (bcmFieldActionEgressPortsAdd == fa->action)
  13983                 || (bcmFieldActionRedirectMcast == fa->action)
  13984                 || (bcmFieldActionRedirectIpmc == fa->action)
  13985                 || (bcmFieldActionMirrorIngress == fa->action)
  13986                 || (bcmFieldActionMirrorEgress == fa->action)
  13987                 || (bcmFieldActionHashSelect0 == fa->action)
  13988                 || (bcmFieldActionHashSelect1 == fa->action)
  13989                 || (bcmFieldActionFabricEHAddOrUpdate == fa->action)) {
  13990 
  13991                if(_FP_ACTION_MODIFY & fa->flags) {
  13992 
  13993 
  13994                 fa->flags &= ~_FP_ACTION_MODIFY;
  13995 
  13996                 fa_iter = f_ent->actions;
  13997 
  13998                 while (fa_iter != NULL) {
  13999                     if ((1 == (fa_iter->flags & _FP_ACTION_VALID))
  14000                         && (fa_iter->action == fa->action)
  14001                         && (_FP_INVALID_INDEX == fa_iter->hw_index)) {
  14002                             /* Do not free here. Release the hardware
  14003                              * index after policy install operation.
  14004                              */
  14005                             fa_iter->hw_index = fa->hw_index;
  14006                             fa_iter->flags |= _FP_ACTION_MODIFY;
  14007                             fa->hw_index = _FP_INVALID_INDEX;
  14008                             break;
  14009                     }
  14010                     fa_iter = fa_iter->next;
  14011                 }
  14012 
  14013                 /* Here _FP_ACTION_MODIFY flag cleared means , no duplicate
  14014                    actions are found i.e an action is removed from the entry.
  14015                    Those invalid but not modified entries will be removed in
  14016                    the second pass to this function,so just return BCM_E_NONE
  14017                    on first pass */
  14018                 if(!(_FP_ACTION_MODIFY & fa->flags)) {
  14019                    fa_prev = fa;
  14020                    fa      = fa_next;
  14021                    continue;
  14022                 }
  14023               }
  14024             }
  14025 
  14026 
  14027             /*
  14028              * Action not set for this entry, free the hardware index.
  14029              */
  14030             if (_FP_INVALID_INDEX != fa->hw_index) {
  14031                 rv = _field_action_hw_resources_free(unit, f_ent, fa,
  14032                                                      _FP_ACTION_RESOURCE_FREE);
  14033                 BCM_IF_ERROR_RETURN(rv);
  14034             }
  14035         }
  14036 
  14037         if (fa_prev != NULL) {
  14038             fa_prev->next = fa->next;
  14039         } else { /* matched head of list */
  14040             f_ent->actions = fa_next;
  14041         }
  14042 #if defined(BCM_KATANA_SUPPORT)
  14043     if (SOC_IS_KATANAX(unit)) {
  14044         if (fa != NULL) {
  14045             if ((fa->action == bcmFieldActionFabricQueue) &&
  14046                 (f_ent->fs->stage_id == _BCM_FIELD_STAGE_INGRESS)) {
  14047                 sal_memset(&ing_queue_entry, 0, sizeof(ing_queue_map_entry_t));
  14048                 param0 = fa->param[0];
  14049                 param1 = fa->param[1];
  14050                 /* For Katana if param1 BCM_FABRIC_QUEUE_xxx
  14051                  * flags are set then param0 is
  14052                  * ucast/ucast_subscriber group cosq gport */
  14053                 if ((param1 & BCM_FABRIC_QUEUE_DEST_OFFSET) ||
  14054                     (param1 & BCM_FABRIC_QUEUE_CUSTOMER)) {
  14055                    if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(param0) ||
  14056                         BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(param0) ||
  14057                         BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(param0)) {
  14058 #if defined(BCM_KATANA2_SUPPORT)
  14059                         if (SOC_IS_KATANA2(unit)) {
  14060                             queue_id = -1;
  14061                             rv = _bcm_kt2_cosq_index_resolve(
  14062                                   unit, param0, 0,
  14063                                  _BCM_KT_COSQ_INDEX_STYLE_BUCKET,
  14064                                   NULL, &queue_id, NULL);
  14065                             if (BCM_FAILURE(rv) &&
  14066                                  (rv != BCM_E_NOT_FOUND)) {
  14067                                  return rv;
  14068                              }
  14069                         } else
  14070 #endif
  14071                         {
  14072                             if (SOC_IS_KATANA(unit)) {
  14073                                 BCM_IF_ERROR_RETURN(_bcm_kt_cosq_index_resolve(
  14074                                     unit, param0, 0,
  14075                                     _BCM_KT_COSQ_INDEX_STYLE_BUCKET,
  14076                                     NULL, &queue_id, NULL));
  14077                             }
  14078                         }
  14079                     } else {
  14080                         queue_id = param0 & 0xffff;
  14081                     }
  14082                     in_flags = param1;
  14083                 } else {
  14084                     queue_id = param0 & 0xffff;
  14085                     in_flags = param0;
  14086                 }
  14087 
  14088                 if (in_flags & BCM_FABRIC_QUEUE_DEST_OFFSET) {
  14089                    if (queue_id != -1) {
  14090                        BCM_IF_ERROR_RETURN(
  14091                           _bcm_field_fabricQueue_action_node_delete (unit,
  14092                               queue_id, param1, &referenceCount));
  14093                        if(referenceCount == 0) {
  14094                            BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_WRITE(unit,
  14095                                         ING_QUEUE_MAPm,
  14096                                         queue_id, &ing_queue_entry));
  14097                        }
  14098                     }
  14099                }
  14100             }
  14101         }
  14102     }
  14103 #endif
  14104         /* okay to free action */
  14105         if (NULL != (fa->egress_pbmp)) {
  14106             sal_free(fa->egress_pbmp);
  14107         }
  14108         sal_free(fa);
  14109         fa = fa_next;
  14110     }
  14111 
  14112 #if defined(BCM_TRIDENT_SUPPORT)
  14113     if (SOC_IS_TD_TT (unit) &&
  14114         !(soc_feature(unit, soc_feature_field_multi_pipe_support))) {
  14115         if ((f_ent->group->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) ||
  14116             (f_ent->group->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) ||
  14117             (f_ent->group->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) {
  14118 
  14119             if (f_ent->group->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
  14120                 entry_flags = (_FP_ENTRY_PRIMARY | _FP_ENTRY_SECOND_HALF);
  14121             } else {
  14122                 entry_flags = _FP_ENTRY_SECONDARY;
  14123             }
  14124 
  14125             rv = _bcm_field_entry_flags_to_tcam_part(unit, entry_flags,
  14126                                                      f_ent->group,
  14127                                                      &idx);
  14128 
  14129             BCM_IF_ERROR_RETURN(rv);
  14130             /* Find the action in the entry */
  14131             fa = f_ent[idx].actions; /* start at head */
  14132             fa_prev = NULL;
  14133             fa_next = NULL;
  14134             while (fa != NULL) {
  14135                 fa_next = fa->next;
  14136                 if (fa->flags & _FP_ACTION_VALID) {
  14137                     fa_prev = fa;
  14138                     fa = fa_next;
  14139                     continue;
  14140                 }
  14141                 if (fa_prev != NULL) {
  14142                     fa_prev->next = fa->next;
  14143                 } else { /* matched head of list */
  14144                     f_ent[idx].actions = fa_next;
  14145                 }
  14146 
  14147                 /* okay to free action */
  14148                 if (NULL != (fa->egress_pbmp)) {
  14149                     sal_free(fa->egress_pbmp);
  14150                 }
  14151                 sal_free(fa);
  14152                 fa = fa_next;
  14153             }
  14154         }
  14155     }
  14156 #endif
  14157 
  14158     /* Remove Invalid Oam Actions */
  14159 #if defined BCM_TRIDENT2PLUS_SUPPORT
  14160     if (soc_feature(unit, soc_feature_fp_based_oam)) {
  14161         rv = _bcm_field_oam_stat_invalid_actions_remove (unit, f_ent);
  14162         BCM_IF_ERROR_RETURN(rv);
  14163     }
  14164 #endif
  14165 
  14166     return (BCM_E_NONE);
  14167 }
  14168 
  14169 /*
  14170  * Function:
  14171  *     _field_mtp_hw_alloc
  14172  *
  14173  * Purpose:
  14174  *     Allocate mtp indexes required for entry installation.
  14175  *
  14176  * Parameters:
  14177  *     unit      - (IN) BCM device number.
  14178  *     f_ent     - (IN) Field entry descriptor.
  14179  * Returns:
  14180  *     BCM_E_XXX
  14181  * Notes:
  14182  */
  14183 STATIC int
  14184 _field_mtp_hw_alloc (int unit, _field_entry_t *f_ent)
  14185 {
  14186     _field_action_t *fa;  /* Field action descriptor. */
  14187     int rv;               /* Operation return status. */
  14188     int mirror_flags = 0;
  14189 
  14190     /* Extract action info from the entry structure. */
  14191     for (fa = f_ent->actions; ((fa != NULL) && (_FP_ACTION_VALID & fa->flags)); fa = fa->next) {
  14192         /* Allocate mtp destination only for mirroring actions */
  14193         if ((bcmFieldActionMirrorIngress != fa->action) &&
  14194             (bcmFieldActionMirrorEgress != fa->action)) {
  14195             continue;
  14196         }
  14197         if(_FP_ACTION_MODIFY & fa->flags) {
  14198             fa->old_index = fa->hw_index;
  14199             fa->hw_index = _FP_INVALID_INDEX;
  14200         }
  14201         if (_FP_INVALID_INDEX == fa->hw_index) {
  14202         /* Allocate mirror destination. */
  14203           if(BCM_E_RESOURCE == (rv = _field_mirror_dest_add(unit, f_ent, fa))) {
  14204             if(_FP_ACTION_MODIFY & fa->flags) {
  14205                 fa->hw_index = fa->old_index;
  14206                 fa->old_index = _FP_INVALID_INDEX;
  14207             }
  14208             for (fa = f_ent->actions;
  14209                  ((fa != NULL) &&
  14210                  (_FP_ACTION_VALID & fa->flags)); fa = fa->next) {
  14211                 if ((bcmFieldActionMirrorIngress != fa->action)
  14212                      && (bcmFieldActionMirrorEgress != fa->action)) {
  14213                     continue;
  14214                 }
  14215                 if (fa->flags & _FP_ACTION_DIRTY) {
  14216                     /* Free the alloted resources */
  14217                     _field_mirror_dest_delete(unit, f_ent, fa,
  14218                                               _FP_ACTION_RESOURCE_FREE);
  14219                 }
  14220             }
  14221           }
  14222           BCM_IF_ERROR_RETURN(rv);
  14223         } else {
  14224             if (bcmFieldActionMirrorIngress == fa->action) {
  14225                 mirror_flags =
  14226                     _BCM_MIRROR_SLOT_INGRESS | _BCM_MIRROR_SLOT_FP;
  14227                 BCM_IF_ERROR_RETURN
  14228                     (_bcm_esw_mirror_fp_slot_del_ref(unit,
  14229                                                      mirror_flags,
  14230                                                      f_ent->ing_mtp_slot_map));
  14231                 f_ent->ing_mtp_slot_map = 0;
  14232             }
  14233             if (bcmFieldActionMirrorEgress == fa->action) {
  14234                 if (_BCM_FIELD_STAGE_EGRESS != f_ent->group->stage_id) {
  14235                     mirror_flags =
  14236                         _BCM_MIRROR_SLOT_EGRESS | _BCM_MIRROR_SLOT_FP;
  14237                     BCM_IF_ERROR_RETURN
  14238                         (_bcm_esw_mirror_fp_slot_del_ref(unit,
  14239                                                          mirror_flags,
  14240                                                          f_ent->egr_mtp_slot_map));
  14241                     f_ent->egr_mtp_slot_map = 0;
  14242                 }
  14243             }
  14244         }
  14245     }
  14246     return (BCM_E_NONE);
  14247 }
  14248 
  14249 /*
  14250  * Function:
  14251  *     _field_redirect_profile_hw_free
  14252  *
  14253  * Purpose:
  14254  *     Free redirect profile indexes required for entry installation.
  14255  *
  14256  * Parameters:
  14257  *     unit      - (IN) BCM device number.
  14258  *     f_ent     - (IN) Field entry descriptor.
  14259  *     flags     - (IN) Free flags (old/new/both).
  14260  * Returns:
  14261  *     BCM_E_XXX
  14262  * Notes:
  14263  */
  14264 STATIC int
  14265 _field_redirect_profile_hw_free(int unit, _field_entry_t *f_ent, uint32 flags)
  14266 {
  14267     _field_action_t *fa;  /* Field action descriptor. */
  14268     int rv = BCM_E_NONE;  /* Operation return status. */
  14269 
  14270     /* Applicable to stage ingress on TRX devices only. */
  14271     if ((0 == SOC_IS_TRX(unit)) ||
  14272         ((_BCM_FIELD_STAGE_INGRESS != f_ent->group->stage_id) &&
  14273          (_BCM_FIELD_STAGE_EXTERNAL != f_ent->group->stage_id) &&
  14274          (_BCM_FIELD_STAGE_EXACTMATCH != f_ent->group->stage_id))) {
  14275         if (!SOC_IS_GREYHOUND2(unit)) {
  14276             return (BCM_E_NONE);
  14277         }
  14278     }
  14279 
  14280     /* Extract the policy info from the entry structure. */
  14281     for (fa = f_ent->actions; fa != NULL; fa = fa->next) {
  14282         switch (fa->action) {
  14283           case bcmFieldActionRedirectMcast:
  14284 #if defined(INCLUDE_L3)
  14285           case bcmFieldActionRedirectIpmc:
  14286 #endif /* INCLUDE_L3 */
  14287               if (soc_feature(unit, soc_feature_field_action_redirect_ipmc)){
  14288                   break;
  14289               }
  14290           case bcmFieldActionRedirectPbmp:
  14291           case bcmFieldActionRedirectBcastPbmp:
  14292           case bcmFieldActionEgressMask:
  14293           case bcmFieldActionEgressPortsAdd:
  14294 #if defined (BCM_TOMAHAWK3_SUPPORT)
  14295               if ((fa->action == bcmFieldActionEgressMask) &&
  14296                   (soc_feature(unit, soc_feature_th3_style_fp))) {
  14297                   if ((flags & _FP_ACTION_RESOURCE_FREE) &&
  14298                       (_FP_INVALID_INDEX != fa->hw_index)) {
  14299                       rv = _bcm_field_th3_redirect_profile_delete(unit,
  14300                                                                   fa->hw_index);
  14301                       BCM_IF_ERROR_RETURN(rv);
  14302                       fa->hw_index = _FP_INVALID_INDEX;
  14303                   }
  14304 
  14305                   if ((flags & _FP_ACTION_OLD_RESOURCE_FREE) &&
  14306                       (_FP_INVALID_INDEX != fa->old_index)) {
  14307                       rv = _bcm_field_th3_redirect_profile_delete(unit,
  14308                                                                   fa->old_index);
  14309                       BCM_IF_ERROR_RETURN(rv);
  14310                       fa->old_index = _FP_INVALID_INDEX;
  14311                   }
  14312               } else
  14313 #endif
  14314 #if defined(BCM_TRX_SUPPORT)
  14315               {
  14316                   if ((flags & _FP_ACTION_RESOURCE_FREE) &&
  14317                       (_FP_INVALID_INDEX != fa->hw_index)) {
  14318                       rv = _bcm_field_trx_redirect_profile_delete(unit,
  14319                                                                   fa->hw_index);
  14320                       BCM_IF_ERROR_RETURN(rv);
  14321                       fa->hw_index = _FP_INVALID_INDEX;
  14322                   }
  14323 
  14324                   if ((flags & _FP_ACTION_OLD_RESOURCE_FREE) &&
  14325                       (_FP_INVALID_INDEX != fa->old_index)) {
  14326                       rv = _bcm_field_trx_redirect_profile_delete(unit,
  14327                                                                   fa->old_index);
  14328                       BCM_IF_ERROR_RETURN(rv);
  14329                       fa->old_index = _FP_INVALID_INDEX;
  14330                   }
  14331               }
  14332               break;
  14333 #endif /* BCM_TRX_SUPPORT */
  14334 #if defined(BCM_TSN_SUPPORT)
  14335           case bcmFieldActionMtuProfileIdNew:
  14336               if (soc_feature(unit, soc_feature_tsn_mtu_stu) &&
  14337                    (flags & (_FP_ACTION_RESOURCE_FREE | _FP_ACTION_OLD_RESOURCE_FREE))) {
  14338                   (void)bcmi_esw_tsn_mtu_profile_ref_dec(unit, fa->param[0]);
  14339               }
  14340               break;
  14341           case bcmFieldActionStuProfileIdNew:
  14342               if (soc_feature(unit, soc_feature_tsn_mtu_stu) &&
  14343                    (flags & (_FP_ACTION_RESOURCE_FREE | _FP_ACTION_OLD_RESOURCE_FREE))) {
  14344                   (void)bcmi_esw_tsn_stu_profile_ref_dec(unit, fa->param[0]);
  14345               }
  14346               break;
  14347 #endif /*BCM_TSN_SUPPORT*/
  14348           default:
  14349               break;
  14350         }
  14351     }
  14352     return (rv);
  14353 }
  14354 
  14355 
  14356 /*
  14357  * Function:
  14358  *     _field_redirect_profile_hw_alloc
  14359  *
  14360  * Purpose:
  14361  *     Allocate redirect profile index required for entry installation.
  14362  *
  14363  * Parameters:
  14364  *     unit      - (IN) BCM device number.
  14365  *     f_ent     - (IN) Field entry descriptor.
  14366  * Returns:
  14367  *     BCM_E_XXX
  14368  * Notes:
  14369  */
  14370 STATIC int
  14371 _field_redirect_profile_hw_alloc (int unit, _field_entry_t *f_ent)
  14372 {
  14373     int rv = BCM_E_NONE;  /* Operation return status.     */
  14374 #if defined (BCM_TRX_SUPPORT)
  14375     _field_action_t *fa;  /* Field action descriptor.     */
  14376 
  14377     int ref_count;        /* Profile use reference count. */
  14378 
  14379     /* Applicable to stage ingress on TRX devices only. */
  14380     if ((0 == SOC_IS_TRX(unit)) ||
  14381         ((_BCM_FIELD_STAGE_INGRESS != f_ent->group->stage_id) &&
  14382          (_BCM_FIELD_STAGE_EXTERNAL != f_ent->group->stage_id) &&
  14383          (_BCM_FIELD_STAGE_EXACTMATCH != f_ent->group->stage_id))) {
  14384         if (!SOC_IS_GREYHOUND2(unit)) {
  14385             return (BCM_E_NONE);
  14386         }
  14387     }
  14388 
  14389     /* Extract the policy info from the entry structure. */
  14390     for (fa = f_ent->actions; ((fa != NULL) && (_FP_ACTION_VALID & fa->flags)); fa = fa->next) {
  14391         switch (fa->action) {
  14392           case bcmFieldActionRedirectMcast:
  14393 #if defined(INCLUDE_L3)
  14394           case bcmFieldActionRedirectIpmc:
  14395 #endif /* INCLUDE_L3 */
  14396               if (soc_feature(unit, soc_feature_field_action_redirect_ipmc)){
  14397                   break;
  14398               }
  14399           case bcmFieldActionRedirectPbmp:
  14400           case bcmFieldActionRedirectBcastPbmp:
  14401           case bcmFieldActionEgressMask:
  14402           case bcmFieldActionEgressPortsAdd:
  14403               /*
  14404                * Store previous hardware index value in old_index.
  14405                */
  14406               fa->old_index = fa->hw_index;
  14407 
  14408 #if defined (BCM_TOMAHAWK3_SUPPORT)
  14409               if ((fa->action == bcmFieldActionEgressMask) &&
  14410                   (soc_feature(unit, soc_feature_th3_style_fp))) {
  14411                   rv = _bcm_field_trx_redirect_profile_alloc(unit, f_ent, fa);
  14412                   if ((BCM_E_RESOURCE == rv) &&
  14413                       (_FP_INVALID_INDEX != fa->old_index)) {
  14414                       /* Destroy old profile ONLY
  14415                        * if it is not used by other entries.
  14416                        */
  14417                       rv = _bcm_field_th3_redirect_profile_ref_count_get(unit,
  14418                                                                          fa->old_index,
  14419                                                                          &ref_count);
  14420                       BCM_IF_ERROR_RETURN(rv);
  14421                       if (ref_count > 1) {
  14422                           return (BCM_E_RESOURCE);
  14423                       }
  14424                       rv = _bcm_field_th3_redirect_profile_delete(unit, fa->old_index);
  14425                       BCM_IF_ERROR_RETURN(rv);
  14426 
  14427                       /* Destroy old profile is no longer required. */
  14428                       fa->old_index = _FP_INVALID_INDEX;
  14429 
  14430                       /* Reallocate profile for new action. */
  14431                       rv = _bcm_field_trx_redirect_profile_alloc(unit, f_ent, fa);
  14432                   }
  14433 
  14434               } else
  14435 #endif
  14436               {
  14437                   rv = _bcm_field_trx_redirect_profile_alloc(unit, f_ent, fa);
  14438                   if ((BCM_E_RESOURCE == rv) &&
  14439                       (_FP_INVALID_INDEX != fa->old_index)) {
  14440                       /* Destroy old profile ONLY
  14441                        * if it is not used by other entries.
  14442                        */
  14443                       rv = _bcm_field_trx_redirect_profile_ref_count_get(unit,
  14444                                                                          fa->old_index,
  14445                                                                          &ref_count);
  14446                       BCM_IF_ERROR_RETURN(rv);
  14447                       if (ref_count > 1) {
  14448                           return (BCM_E_RESOURCE);
  14449                       }
  14450                       rv = _bcm_field_trx_redirect_profile_delete(unit, fa->old_index);
  14451                       BCM_IF_ERROR_RETURN(rv);
  14452 
  14453                       /* Destroy old profile is no longer required. */
  14454                       fa->old_index = _FP_INVALID_INDEX;
  14455 
  14456                       /* Reallocate profile for new action. */
  14457                       rv = _bcm_field_trx_redirect_profile_alloc(unit, f_ent, fa);
  14458                   }
  14459               }
  14460               break;
  14461 #if defined(BCM_TSN_SUPPORT)
  14462           case bcmFieldActionMtuProfileIdNew:
  14463               if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  14464                   /* To prevent ref cnt inc from field entry re-install*/
  14465                   if (fa->hw_index == _FP_INVALID_INDEX) {
  14466                       (void)bcmi_esw_tsn_mtu_profile_ref_inc(unit,
  14467                                                              fa->param[0]);
  14468                       fa->hw_index = 0;
  14469                   }
  14470               } else {
  14471                   return BCM_E_UNAVAIL;
  14472               }
  14473               break;
  14474           case bcmFieldActionStuProfileIdNew:
  14475               if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  14476                   /* To prevent ref cnt inc from field entry re-install*/
  14477                   if (fa->hw_index == _FP_INVALID_INDEX) {
  14478                       (void)bcmi_esw_tsn_stu_profile_ref_inc(unit,
  14479                                                              fa->param[0]);
  14480                       fa->hw_index = 0;
  14481                   }
  14482               } else {
  14483                   return BCM_E_UNAVAIL;
  14484               }
  14485               break;
  14486 #endif/* BCM_TSN_SUPPORT */
  14487           default:
  14488               break;
  14489         }
  14490         if (BCM_FAILURE(rv)) {
  14491             _field_redirect_profile_hw_free(unit, f_ent, _FP_ACTION_HW_FREE);
  14492             break;
  14493         }
  14494     }
  14495 #endif /* BCM_TRX_SUPPORT */
  14496     return (rv);
  14497 }
  14498 
  14499 /*
  14500  * Function:
  14501  *     _field_port_filter_enable_set
  14502  *
  14503  * Purpose:
  14504  *     Set the filter enable state in the Port Tables.
  14505  *
  14506  * Parameters:
  14507  *     unit   - (IN)BCM device number.
  14508  *     fc     - (IN)Field control structure.
  14509  *     state  - (IN) TRUE = to enable
  14510  *                   FALSE = disable filtering.
  14511  *
  14512  * Returns:
  14513  *     BCM_E_NONE  - Success
  14514  *     BCM_E_XXX   - From table read/write
  14515  */
  14516 int
  14517 _field_port_filter_enable_set(int unit, _field_control_t *fc, uint32 state)
  14518 {
  14519     int port;                      /* Port iterator.               */
  14520     int ret_val = BCM_E_NONE;      /* Operation return value.      */
  14521     bcm_port_config_t  port_config;/* Device port config structure.*/
  14522     bcm_pbmp_t port_pbmp, all_pbmp;
  14523 
  14524     /* Input parameters check. */
  14525     if (NULL == fc || ((state != TRUE) && (state != FALSE))) {
  14526         return (BCM_E_PARAM);
  14527     }
  14528 
  14529     state = (state) ? 1 : 0;
  14530 
  14531     /* Read device port configuration. */
  14532     BCM_IF_ERROR_RETURN(bcm_esw_port_config_get(unit, &port_config));
  14533     BCM_PBMP_CLEAR(port_pbmp);
  14534     BCM_PBMP_CLEAR(all_pbmp);
  14535     BCM_PBMP_ASSIGN(port_pbmp, port_config.port);
  14536     BCM_PBMP_ASSIGN(all_pbmp, port_config.all);
  14537 #ifdef BCM_KATANA2_SUPPORT
  14538     if (SOC_IS_KATANA2(unit) && soc_feature(unit, soc_feature_flex_port)) {
  14539         BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, &port_pbmp));
  14540         BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, &all_pbmp));
  14541     }
  14542     if (soc_feature(unit, soc_feature_linkphy_coe) ||
  14543         soc_feature(unit, soc_feature_subtag_coe)) {
  14544         _bcm_kt2_subport_pbmp_update(unit, &port_pbmp);
  14545         _bcm_kt2_subport_pbmp_update(unit, &all_pbmp);
  14546     }
  14547 #endif
  14548 
  14549 #if defined(BCM_SABER2_SUPPORT)
  14550     if(SOC_IS_SABER2(unit)){
  14551         int oamp_enable;
  14552         (void)bcm_sb2_sat_oamp_enable_get(unit, &oamp_enable);
  14553         /* Skip OAMP port for saber2 device */
  14554         if(oamp_enable) {
  14555             SOC_PBMP_PORT_REMOVE(port_pbmp,
  14556                     _BCM_SB2_SAT_OAMP_PHY_PORT_NUMBER);
  14557             SOC_PBMP_PORT_REMOVE(all_pbmp,
  14558                     _BCM_SB2_SAT_OAMP_PHY_PORT_NUMBER);
  14559         }
  14560     }
  14561 #endif
  14562 
  14563     FP_LOCK(unit);
  14564 
  14565     /* Iterate over all the ports but CPU set Lookup filtering. */
  14566     BCM_PBMP_ITER(port_pbmp, port) {
  14567         /* Set field  enable to the hw. */
  14568         ret_val =  bcm_esw_port_control_set(unit, port,
  14569                                             bcmPortControlFilterLookup, state);
  14570 
  14571         if (BCM_E_UNAVAIL == ret_val) {
  14572             /* Device doesn't support lookup filtering. */
  14573             break;
  14574         }
  14575 
  14576         if (BCM_FAILURE(ret_val)) {
  14577             FP_UNLOCK(unit);
  14578             return (ret_val);
  14579         }
  14580     }
  14581 
  14582     /* Iterate over all the ports but CPU set ingress filtering. */
  14583     BCM_PBMP_ITER(port_pbmp, port) {
  14584         /* Set field  enable to the hw. */
  14585         ret_val =  bcm_esw_port_control_set(unit, port,
  14586                                             bcmPortControlFilterIngress, state);
  14587         if (BCM_FAILURE(ret_val)) {
  14588             FP_UNLOCK(unit);
  14589             return (ret_val);
  14590         }
  14591     }
  14592 
  14593     /* Iterate over all the ports set egress filtering. */
  14594     BCM_PBMP_ITER(all_pbmp, port) {
  14595         /* Set field  enable to the hw. */
  14596         ret_val =  bcm_esw_port_control_set(unit, port,
  14597                                             bcmPortControlFilterEgress, state);
  14598 
  14599         if (BCM_E_UNAVAIL == ret_val) {
  14600             /* Device doesn't support egress filtering. */
  14601             break;
  14602         }
  14603 
  14604         if (BCM_FAILURE(ret_val)) {
  14605             FP_UNLOCK(unit);
  14606             return (ret_val);
  14607         }
  14608     }
  14609     FP_UNLOCK(unit);
  14610     return (BCM_E_NONE);
  14611 }
  14612 
  14613 /*
  14614  * Function: _field_qualifier_gport_resolve
  14615  *
  14616  * Purpose:
  14617  *     Resolves gport as parameter of qualifier.
  14618  *
  14619  * Parameters:
  14620  *     unit     - (IN) BCM device number
  14621  *     gport    - (IN) GPORT to resolve
  14622  *     mask     - (IN) qualifier mask, in case of gport must be -1
  14623  *     out_p    - (OUT) port encoded into gport.
  14624  *     out_m    - (OUT) module encoded into gport.
  14625  *     out_t    - (OUT) trunk encoded into gport.
  14626  *
  14627  * Returns:
  14628  *     BCM_E_NONE      - No errors.
  14629  *     BCM_E_XXX       - Otherwise.
  14630  */
  14631 
  14632 int
  14633 _field_qualifier_gport_resolve(int unit, bcm_gport_t gport, int mask,
  14634                                int *out_p, int *out_m, int *out_t)
  14635 {
  14636     bcm_port_t      port;
  14637     bcm_module_t    modid;
  14638     bcm_trunk_t     tgid = BCM_TRUNK_INVALID;
  14639     int             id;
  14640 
  14641     /* In case of gport mask must be exact match */
  14642     if (BCM_FIELD_EXACT_MATCH_MASK != mask) {
  14643         return BCM_E_PARAM;
  14644     }
  14645 
  14646     BCM_IF_ERROR_RETURN(
  14647         _bcm_esw_gport_resolve(unit, gport, &modid, &port, &tgid, &id));
  14648 
  14649 #if defined(BCM_HGPROXY_COE_SUPPORT)
  14650     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
  14651         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) {
  14652         /* For this case gport_resolve returns non-negative id */
  14653     } else
  14654 #endif
  14655 #if defined(BCM_KATANA2_SUPPORT)
  14656     if (BCM_GPORT_IS_SET(gport) &&
  14657         _BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit, gport)) {
  14658         /* For this case gport_resolve returns non-negative id */
  14659     } else
  14660 #endif
  14661     {
  14662         if (-1 != id) {
  14663             return BCM_E_PORT;
  14664         }
  14665     }
  14666 
  14667     if (BCM_TRUNK_INVALID != tgid && NULL == out_t) {
  14668         return BCM_E_PORT;
  14669     }
  14670     if (NULL != out_t) {
  14671         *out_t = tgid;
  14672     }
  14673     if (NULL != out_m) {
  14674         *out_m = modid;
  14675     }
  14676     if (NULL != out_p) {
  14677         *out_p = port;
  14678     }
  14679 
  14680     return (BCM_E_NONE);
  14681 }
  14682 
  14683 /*
  14684  * Function: _field_params_hw_to_api_adapt
  14685  *
  14686  * Purpose:
  14687  *     Adapts action parameters from HW to API space.
  14688  *
  14689  * Parameters:
  14690  *     unit   - (IN) BCM device number
  14691  *     action - (IN)Action to adapt parameters for (bcmFieldActionXXX)
  14692  *     param0 - (IN/OUT)Action parameter
  14693  *     param1 - (IN/OUT)Action parameter
  14694  *
  14695  * Returns:
  14696  *     BCM_E_NONE      - No errors.
  14697  *     BCM_E_XXX       - Otherwise.
  14698  */
  14699 
  14700 int
  14701 _field_params_hw_to_api_adapt(int unit, bcm_field_action_t action,
  14702                               uint32 *param0, uint32 *param1)
  14703 {
  14704     int                 isGport;
  14705     _bcm_gport_dest_t   dest;
  14706 
  14707     _bcm_gport_dest_t_init(&dest);
  14708     BCM_IF_ERROR_RETURN(
  14709         bcm_esw_switch_control_get(unit, bcmSwitchUseGport, &isGport));
  14710 
  14711     switch (action) {
  14712         case bcmFieldActionRedirect:
  14713             if (isGport) {
  14714                 dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
  14715                 dest.modid = *param0;
  14716                 dest.port = *param1;
  14717                 BCM_IF_ERROR_RETURN(
  14718                    _bcm_esw_gport_construct(unit, &dest, (bcm_gport_t*)param1));
  14719                *param0 = -1;   /* If gport requested param0 should be ignored */
  14720             }
  14721             break;
  14722         case bcmFieldActionRedirectTrunk:
  14723             if (isGport) {
  14724                 dest.gport_type = _SHR_GPORT_TYPE_TRUNK;
  14725                 dest.tgid = *param0;
  14726                 BCM_IF_ERROR_RETURN(
  14727                     _bcm_esw_gport_construct(unit, &dest, (bcm_gport_t*)param0));
  14728                 *param1 = -1;   /* If gport requested param1 should be ignored */
  14729             }
  14730             break;
  14731         default:
  14732             break;
  14733     }
  14734     return (BCM_E_NONE);
  14735 }
  14736 
  14737 /*
  14738  * Function: _field_params_api_to_hw_adapt
  14739  *
  14740  * Purpose:
  14741  *     Adapts action parameters from API to HW space.
  14742  *
  14743  * Parameters:
  14744  *     unit   - (IN) BCM device number
  14745  *     action - (IN)Action to adapt parameters for (bcmFieldActionXXX)
  14746  *     param0 - (IN/OUT)Action parameter
  14747  *     param1 - (IN/OUT)Action parameter
  14748  *
  14749  * Returns:
  14750  *     BCM_E_NONE      - No errors.
  14751  *     BCM_E_XXX       - Otherwise.
  14752  */
  14753 
  14754 int
  14755 _field_params_api_to_hw_adapt(int unit, bcm_field_action_t action,
  14756                               uint32 *param0, uint32 *param1)
  14757 {
  14758     bcm_module_t        l_modid;
  14759     bcm_trunk_t         l_tgid;
  14760     bcm_port_t          l_port;
  14761     int                 id;
  14762 
  14763 
  14764     switch (action) {
  14765         case bcmFieldActionRedirect:
  14766             if (BCM_GPORT_IS_SET(*param1)) {
  14767                 BCM_IF_ERROR_RETURN(
  14768                     _bcm_esw_gport_resolve(unit, *param1, &l_modid, &l_port, &l_tgid, &id));
  14769 
  14770 #if defined(BCM_HGPROXY_COE_SUPPORT)
  14771                 /* modify param0 and param1 for
  14772                  * SubportPktTag subport gport.
  14773                  * For this case gport_resolve function returns
  14774                  * non-negative id */
  14775             if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
  14776                 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, *param1)) {
  14777                     if (BCM_TRUNK_INVALID != l_tgid) {
  14778                         return BCM_E_PARAM;
  14779                     }
  14780                     *param1 = l_port;
  14781                     *param0 = l_modid;
  14782             } else
  14783 #endif
  14784 
  14785 #if defined(BCM_KATANA2_SUPPORT)
  14786                 /* modify param0 and param1 for
  14787                  * LinkPHy/SubportPktTag subport gport.
  14788                  * For this case gport_resolve function returns
  14789                  * non-negative id */
  14790                 if (_BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit,
  14791                     *param1)) {
  14792                     if (BCM_TRUNK_INVALID != l_tgid) {
  14793                         return BCM_E_PARAM;
  14794                     }
  14795                     *param1 = l_port;
  14796                     *param0 = l_modid;
  14797                 } else
  14798 #endif
  14799                 {
  14800                     /* Do not modify param0 and param1 if id != -1 */
  14801                     if (-1 == id) {
  14802                         if (BCM_TRUNK_INVALID != l_tgid) {
  14803                             return BCM_E_PARAM;
  14804                         }
  14805                         *param1 = l_port;
  14806                         *param0 = l_modid;
  14807                     }
  14808                 }
  14809             }
  14810             break;
  14811         case bcmFieldActionRedirectTrunk:
  14812             if (BCM_GPORT_IS_SET(*param0)) {
  14813                 BCM_IF_ERROR_RETURN(
  14814                     _bcm_esw_gport_resolve(unit, *param0, &l_modid, &l_port, &l_tgid, &id));
  14815 
  14816 #if defined(BCM_HGPROXY_COE_SUPPORT)
  14817             if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
  14818                 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, *param0)) {
  14819                     /* For this case gport_resolve function returns
  14820                      * non-negative id */
  14821                     if ((BCM_TRUNK_INVALID == l_tgid) ){
  14822                         return BCM_E_PARAM;
  14823                     }
  14824                     *param0 = l_tgid;
  14825                     *param1 = -1;   /* if param0 is trunk, param1 ignored */
  14826                 } else
  14827 #endif
  14828 #if defined(BCM_KATANA2_SUPPORT)
  14829                 if (_BCM_KT2_GPORT_IS_LINKPHY_OR_SUBTAG_SUBPORT_GPORT(unit,
  14830                     *param0)) {
  14831                     /* For this case gport_resolve function returns
  14832                      * non-negative id */
  14833                     if ((BCM_TRUNK_INVALID == l_tgid) ){
  14834                         return BCM_E_PARAM;
  14835                     }
  14836                     *param0 = l_tgid;
  14837                     *param1 = -1;   /* if param0 is trunk, param1 ignored */
  14838                 } else
  14839 #endif
  14840                 {
  14841                     if ((-1 != id) || (BCM_TRUNK_INVALID == l_tgid) ){
  14842                         return BCM_E_PARAM;
  14843                     }
  14844                     *param0 = l_tgid;
  14845                     *param1 = -1;   /* if param0 is trunk, param1 ignored */
  14846                 }
  14847             }
  14848             break;
  14849         default:
  14850             break;
  14851     }
  14852 
  14853     return (BCM_E_NONE);
  14854 }
  14855 
  14856 /*
  14857  * Function: _field_meter_refresh_enable_set
  14858  *
  14859  * Purpose:
  14860  *     Enable meters refresh cycle.
  14861  *
  14862  * Parameters:
  14863  *     unit   - (IN) BCM device number
  14864  *     fc     - (IN) Field control structure.
  14865  *     state  - (IN) On/Off boolean.
  14866  *
  14867  * Returns:
  14868  *     BCM_E_NONE      - No errors.
  14869  *     BCM_E_XXX       - Otherwise.
  14870  */
  14871 int
  14872 _field_meter_refresh_enable_set(int unit, _field_control_t *fc, uint32 state)
  14873 {
  14874 
  14875     int rv = BCM_E_NONE;    /* Operation return status. */
  14876 #ifdef BCM_TRIUMPH_SUPPORT
  14877     soc_reg_t  reg;
  14878 #endif /* BCM_TRIUMPH_SUPPORT */
  14879 
  14880     /* Input parameters check. */
  14881     if (NULL == fc || ((state != TRUE) && (state != FALSE))) {
  14882         return (BCM_E_PARAM);
  14883     }
  14884 
  14885     state = (state) ? 1 : 0;
  14886 
  14887 #ifdef BCM_TRIUMPH_SUPPORT
  14888     if (SOC_IS_TR_VL(unit)) {
  14889         reg = (SOC_IS_ENDURO(unit) || SOC_IS_HURRICANEX(unit) ||
  14890             SOC_IS_GREYHOUND(unit)|| SOC_IS_GREYHOUND2(unit)) ?
  14891             IESMIF_CONTROLr : IESMIF_CONTROL2r;
  14892         if (SOC_REG_IS_VALID (unit, reg)) {
  14893             if (SOC_REG_FIELD_VALID(unit, reg, FP_REFRESH_ENABLEf)) {
  14894                 rv = soc_reg_field32_modify(unit, reg, REG_PORT_ANY,
  14895                                         FP_REFRESH_ENABLEf, state);
  14896                 BCM_IF_ERROR_RETURN(rv);
  14897             }
  14898         }
  14899         if(!SOC_IS_HURRICANE(unit)) {
  14900             if (SOC_REG_IS_VALID (unit, EFP_METER_CONTROLr)) {
  14901                 if (SOC_REG_FIELD_VALID(unit,  EFP_METER_CONTROLr, EFP_REFRESH_ENABLEf)) {
  14902                     rv = soc_reg_field32_modify(unit, EFP_METER_CONTROLr, REG_PORT_ANY,
  14903                                     EFP_REFRESH_ENABLEf, state);
  14904                 }
  14905             }
  14906             BCM_IF_ERROR_RETURN(rv);
  14907         }
  14908 #if defined(BCM_TOMAHAWK_SUPPORT)
  14909         if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  14910             rv = soc_reg_field32_modify(unit, AUX_ARB_CONTROLr,
  14911                                         REG_PORT_ANY,
  14912                                         FP_REFRESH_ENABLEf, state);
  14913             BCM_IF_ERROR_RETURN(rv);
  14914 
  14915         } else
  14916 #endif
  14917 #if defined(BCM_APACHE_SUPPORT)
  14918         if (SOC_IS_APACHE(unit)) {
  14919             rv = soc_reg_field32_modify(unit, AUX_ARB_CONTROL_2_64r,
  14920                                         REG_PORT_ANY,
  14921                                         FP_REFRESH_ENABLEf, state);
  14922             BCM_IF_ERROR_RETURN(rv);
  14923 
  14924         } else
  14925 #endif
  14926         if (SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit) ||
  14927             SOC_IS_TRIUMPH3(unit) || SOC_IS_HURRICANE2(unit) ||
  14928             SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
  14929             SOC_IS_GREYHOUND2(unit)) {
  14930             rv = soc_reg_field32_modify(unit, AUX_ARB_CONTROL_2r,
  14931                                         REG_PORT_ANY,
  14932                                         FP_REFRESH_ENABLEf, state);
  14933             BCM_IF_ERROR_RETURN(rv);
  14934         }
  14935         return rv;
  14936     }
  14937 #endif /* BCM_TRIUMPH_SUPPORT */
  14938 
  14939 #ifdef BCM_SCORPION_SUPPORT
  14940     if (SOC_IS_SC_CQ(unit)) {
  14941 
  14942         rv = soc_reg_field32_modify(unit, AUX_ARB_CONTROL_2r, REG_PORT_ANY,
  14943                                     FP_REFRESH_ENABLEf, state);
  14944         BCM_IF_ERROR_RETURN(rv);
  14945         if (SOC_SWITCH_BYPASS_MODE_L3_ONLY != SOC_SWITCH_BYPASS_MODE(unit)) {
  14946             rv = soc_reg_field32_modify(unit, EFP_METER_CONTROLr,
  14947                                         REG_PORT_ANY,
  14948                                         EFP_REFRESH_ENABLEf, state);
  14949             BCM_IF_ERROR_RETURN(rv);
  14950         }
  14951         return BCM_E_NONE;
  14952     }
  14953 #endif /* BCM_SCORPION_SUPPORT */
  14954 
  14955 #ifdef BCM_BRADLEY_SUPPORT
  14956     if (SOC_IS_HBX(unit)) {
  14957         uint32 sbs_ctrl;
  14958         uint32 pipe_sel;
  14959         BCM_IF_ERROR_RETURN(READ_SBS_CONTROLr(unit, &sbs_ctrl));
  14960         pipe_sel = soc_reg_field_get(unit, SBS_CONTROLr, sbs_ctrl,
  14961                                      PIPE_SELECTf);
  14962 
  14963         rv =soc_reg_field32_modify(unit, AUX_ARB_CONTROL_2r, REG_PORT_ANY,
  14964                                    FP_REFRESH_ENABLEf, state);
  14965         BCM_IF_ERROR_RETURN(rv);
  14966 
  14967         /* Flip between X and Y pipe */
  14968         pipe_sel = (pipe_sel == 0) ? 1 : 0;
  14969         soc_reg_field_set(unit, SBS_CONTROLr, &sbs_ctrl, PIPE_SELECTf,
  14970                           pipe_sel);
  14971         BCM_IF_ERROR_RETURN(WRITE_SBS_CONTROLr(unit, sbs_ctrl));
  14972 
  14973         rv = soc_reg_field32_modify(unit, AUX_ARB_CONTROL_2r, REG_PORT_ANY,
  14974                                     FP_REFRESH_ENABLEf, state);
  14975         BCM_IF_ERROR_RETURN(rv);
  14976         /* Restore original pipeline selection */
  14977         pipe_sel = (pipe_sel == 0) ? 1 : 0;
  14978         soc_reg_field_set(unit, SBS_CONTROLr, &sbs_ctrl, PIPE_SELECTf,
  14979                           pipe_sel);
  14980         return WRITE_SBS_CONTROLr(unit, sbs_ctrl);
  14981     }
  14982 #endif /* BCM_BRADLEY_SUPPORT */
  14983 
  14984 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT)
  14985     if (soc_feature(unit, soc_feature_field_multi_stage)) {
  14986         rv = soc_reg_field32_modify(unit, EFP_METER_CONTROLr, REG_PORT_ANY,
  14987                                     EFP_REFRESH_ENABLEf, state);
  14988         BCM_IF_ERROR_RETURN(rv);
  14989     }
  14990 #endif /* BCM_FIREBOLT2_SUPPORT */
  14991 
  14992     rv = soc_reg_field32_modify(unit, AUX_ARB_CONTROLr, REG_PORT_ANY,
  14993                                 FP_REFRESH_ENABLEf, state);
  14994 
  14995     return (rv);
  14996 }
  14997 
  14998 
  14999 /*
  15000  * Function:
  15001  *     _bcm_field_stage_qualifiers_free
  15002  * Purpose:
  15003  *     De-initialize stage qaualifiers descriptors.
  15004  * Parameters:
  15005  *     unit       - (IN) BCM device number.
  15006  *     stage_fc   - (IN) Field Processor stage control structure.
  15007  *
  15008  * Returns:
  15009  *     BCM_E_NONE
  15010  */
  15011 int
  15012 _bcm_field_stage_qualifiers_free(int unit, _field_stage_t *stage_fc)
  15013 {
  15014     _bcm_field_qual_info_t  *f_qual; /* Qualifier descriptor.       */
  15015     int idx;                         /* Qualifiers iteration index. */
  15016 
  15017     /* Input parameters check. */
  15018     if (NULL == stage_fc) {
  15019         return (BCM_E_PARAM);
  15020     }
  15021 
  15022     if (NULL == stage_fc->f_qual_arr) {
  15023         return (BCM_E_NONE);
  15024     }
  15025 
  15026     for (idx = 0; idx < _bcmFieldQualifyCount; idx++) {
  15027         f_qual = stage_fc->f_qual_arr[idx];
  15028 
  15029         /* Skip unused qualifiers. */
  15030         if (NULL == f_qual) {
  15031             continue;
  15032         }
  15033         /* Free qualifier configurations array. */
  15034         if (NULL != f_qual->conf_arr) sal_free(f_qual->conf_arr);
  15035 
  15036         /* Free qualifier descriptor structure. */
  15037         sal_free(f_qual);
  15038 
  15039         /* Mark qualifier as unused. */
  15040         stage_fc->f_qual_arr[idx] = NULL;
  15041     }
  15042 
  15043     /* Free qualifiers array. */
  15044     sal_free(stage_fc->f_qual_arr);
  15045     stage_fc->f_qual_arr = NULL;
  15046 
  15047     return (BCM_E_NONE);
  15048 }
  15049 
  15050 /*
  15051  * Function:
  15052  *     _field_qual_add
  15053  * Purpose:
  15054  *     Install field selector to selectors table.
  15055  *
  15056  * Parameters:
  15057  *   fpf_info - (IN) FPF memory, field, qual table and selector table info.
  15058  *   qid      - (IN) Qualifier id.
  15059  *   offset   - (IN) Qualifier offset.
  15060  *   width    - (IN) Qualifier width.
  15061  *   code     - (IN) FPF table index.
  15062  * Returns:
  15063  *     BCM_E_XXX
  15064  */
  15065 int
  15066 _field_qual_add (_field_fpf_info_t *fpf_info, int qid,
  15067                  int offset, int width, int code)
  15068 {
  15069     _qual_info_t     *fq_p;
  15070 
  15071     /* Input parameters check. */
  15072     if ((code >= FPF_SZ_MAX) || (NULL == fpf_info)) {
  15073          return (BCM_E_PARAM);
  15074     }
  15075 
  15076     /* Allocate qualifier info. */
  15077     fq_p = sal_alloc(sizeof(_qual_info_t), "Qualifier Info");
  15078     if (NULL == fq_p) {
  15079         return (BCM_E_MEMORY);
  15080     }
  15081 
  15082     /* Set qualifier data. */
  15083     _FP_QUAL_INFO_SET(qid, fpf_info->field, offset, width, fq_p);
  15084 
  15085     /* Insert qual_table */
  15086     fq_p->next = fpf_info->qual_table[code];
  15087     fpf_info->qual_table[code] = fq_p;
  15088 
  15089     /* Insert qual_table */
  15090     BCM_FIELD_QSET_ADD_INTERNAL(fpf_info->sel_table[code], qid);
  15091 
  15092     return (BCM_E_NONE);
  15093 }
  15094 
  15095 /*
  15096  * Function:
  15097  *     _bcm_field_group_slice_count_get
  15098  * Purpose:
  15099  *     Retrieve number of slices group occupies
  15100  * Parameters:
  15101  *     flags -(IN) Group flags.
  15102  *     count -(OUT)Slice count (1-3).
  15103  * Returns:
  15104  *    BCM_E_XXX
  15105  */
  15106 int
  15107 _bcm_field_group_slice_count_get(uint32 flags, int *count)
  15108 {
  15109 
  15110     if (NULL == count) {
  15111         return (BCM_E_PARAM);
  15112     }
  15113 
  15114     if (flags & _FP_GROUP_SPAN_TRIPLE_SLICE) {
  15115         *count = 3;
  15116     } else if (flags & _FP_GROUP_SPAN_DOUBLE_SLICE) {
  15117         *count = 2;
  15118     } else {
  15119         *count = 1;
  15120     }
  15121     return (BCM_E_NONE);
  15122 }
  15123 
  15124 /*
  15125  * Function:
  15126  *     _field_qual_offset_get
  15127  * Purpose:
  15128  *     Retrieve qualifier offsets
  15129  * Parameters:
  15130  *     unit     - (IN) BCM device number.
  15131  *     f_ent    - (IN) Field entry structure.
  15132  *     qid      - (IN) Qualifier id.
  15133  *     offset   - (OUT) Qualifier offset and width.
  15134  * Returns:
  15135  *     BCM_E_XXX
  15136  */
  15137 int
  15138 _field_qual_offset_get(int unit, _field_entry_t *f_ent, int qid,
  15139                        _bcm_field_qual_offset_t **offset)
  15140 {
  15141     _bcm_field_group_qual_t *q_arr;    /* Qualifiers array.          */
  15142     _field_group_t          *fg;       /* Field group structure.     */
  15143     uint8                   entry_part;/* Wide entry part number.    */
  15144     uint8                   entry_type;  /* Index to tcam entries
  15145                                               of multiple types      */
  15146     int                     rv;        /* Operation return status.   */
  15147     int                     idx;       /* Entry qualifiers iterator. */
  15148 
  15149     LOG_DEBUG(BSL_LS_BCM_FP,
  15150               (BSL_META_U(unit,
  15151                           "_field_qual_offset_get\n")));
  15152 
  15153     /* Input parameters check. */
  15154     if ((NULL == offset) || (NULL == f_ent)) {
  15155         return (BCM_E_PARAM);
  15156     }
  15157 
  15158     /* Get entry group. */
  15159     fg = f_ent->group;
  15160 
  15161 #if defined(BCM_TOMAHAWK_SUPPORT)
  15162     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  15163                         (_BCM_FIELD_STAGE_CLASS == fg->stage_id)) {
  15164         return (BCM_E_NONE);
  15165     }
  15166 #endif /* BCM_TOMAHAWK_SUPPORT */
  15167 
  15168     if (0 == BCM_FIELD_QSET_TEST(fg->qset, qid)) {
  15169         /* Only qualifiers that were explicitly requested may be used */
  15170 #ifdef BROADCOM_DEBUG
  15171         LOG_ERROR(BSL_LS_BCM_FP,
  15172                   (BSL_META_U(unit,
  15173                               "FP(unit %d) Error: qual=%s not in group=%d Qset\n"),
  15174                    unit,
  15175                    _field_qual_name(qid), f_ent->group->gid));
  15176 #endif
  15177         return (BCM_E_PARAM);
  15178     }
  15179 
  15180     /* Get field entry part where qualifier resides. */
  15181     rv = _bcm_field_entry_flags_to_tcam_part (unit, f_ent->flags, fg,
  15182                                               &entry_part);
  15183     BCM_IF_ERROR_RETURN(rv);
  15184 
  15185     entry_type = _FP_ENTRY_TYPE_DEFAULT;
  15186 
  15187     /* Get qualifier information. */
  15188     q_arr = &(fg->qual_arr[entry_type][entry_part]);
  15189     for (idx = 0; idx < q_arr->size; idx++) {
  15190         if (qid == q_arr->qid_arr[idx]) {
  15191             *offset = q_arr->offset_arr + idx;
  15192             break;
  15193         }
  15194     }
  15195 
  15196     if (idx == q_arr->size) {
  15197         *offset = NULL;
  15198         return (BCM_E_NOT_FOUND);
  15199     }
  15200     return (BCM_E_NONE);
  15201 }
  15202 #if defined(BCM_TRIDENT2_SUPPORT)
  15203 /*
  15204  * Function:
  15205  *     _field_qual_offset_get_by_entry_type
  15206  * Purpose:
  15207  *     Retrieve qualifier offsets
  15208  * Parameters:
  15209  *     unit          - (IN) BCM device number.
  15210  *     f_ent         - (IN) Field entry structure.
  15211  *     qid           - (IN) Qualifier id.
  15212  *     entry_type    - (IN) Index to groups qual_arr
  15213  *     offset        - (OUT) Qualifier offset and width.
  15214  * Returns:
  15215  *     BCM_E_XXX
  15216  */
  15217 int
  15218 _field_qual_offset_get_by_entry_type(int unit, _field_entry_t *f_ent, int qid,
  15219                                      uint8 entry_type,
  15220                                      _bcm_field_qual_offset_t **offset)
  15221 {
  15222     _bcm_field_group_qual_t *q_arr;    /* Qualifiers array.          */
  15223     _field_group_t          *fg;       /* Field group structure.     */
  15224     uint8                   entry_part;/* Wide entry part number.    */
  15225     int                     rv;        /* Operation return status.   */
  15226     int                     idx;       /* Entry qualifiers iterator. */
  15227 
  15228     LOG_DEBUG(BSL_LS_BCM_FP,
  15229               (BSL_META_U(unit,
  15230                           "_field_qual_offset_get_by_entry_type\n")));
  15231 
  15232     /* Input parameters check. */
  15233     if ((NULL == offset) || (NULL == f_ent)) {
  15234         return (BCM_E_PARAM);
  15235     }
  15236 
  15237     /* Get entry group. */
  15238     fg = f_ent->group;
  15239 
  15240     if (0 == BCM_FIELD_QSET_TEST(fg->qset, qid)) {
  15241         /* Only qualifiers that were explicitly requested may be used */
  15242 #ifdef BROADCOM_DEBUG
  15243         LOG_ERROR(BSL_LS_BCM_FP,
  15244                   (BSL_META_U(unit,
  15245                               "FP(unit %d) Error: qual=%s not in group=%d Qset\n"),
  15246                    unit,
  15247                    _field_qual_name(qid), f_ent->group->gid));
  15248 #endif
  15249         return (BCM_E_PARAM);
  15250     }
  15251 
  15252     /* Get field entry part where qualifier resides. */
  15253     rv = _bcm_field_entry_flags_to_tcam_part (unit, f_ent->flags, fg,
  15254                                               &entry_part);
  15255     BCM_IF_ERROR_RETURN(rv);
  15256 
  15257     /* Get qualifier information. */
  15258     q_arr = &(fg->qual_arr[entry_type][entry_part]);
  15259     for (idx = 0; idx < q_arr->size; idx++) {
  15260         if (qid == q_arr->qid_arr[idx]) {
  15261             *offset = q_arr->offset_arr + idx;
  15262             break;
  15263         }
  15264     }
  15265 
  15266     if (idx == q_arr->size) {
  15267         *offset = NULL;
  15268         return (BCM_E_NOT_FOUND);
  15269     }
  15270     return (BCM_E_NONE);
  15271 }
  15272 #endif
  15273 
  15274 /*
  15275  * Function:
  15276  *     _field_group_qualifiers_free
  15277  * Purpose:
  15278  *     Free group qualifiers array.
  15279  * Parameters:
  15280  *     fg   - (IN) Field group structure.
  15281  *     idx  - (IN) Entry part.
  15282  * Returns:
  15283  *     void
  15284  * Note:
  15285  */
  15286 int
  15287 _bcm_field_group_qualifiers_free(_field_group_t *fg, int idx)
  15288 {
  15289     _bcm_field_group_qual_t *q_arr;       /* Qualifiers array.        */
  15290     int entry_type;    /* holds type(L3/FcoE/L2) of an entry in a group. */
  15291 
  15292     /* Input parameters check. */
  15293     if ((NULL == fg) || (idx < 0) || (idx >= _FP_MAX_ENTRY_WIDTH)) {
  15294         return BCM_E_PARAM;
  15295     }
  15296 
  15297     for (entry_type = 0; entry_type < _FP_MAX_ENTRY_TYPES; entry_type++) {
  15298         q_arr = &(fg->qual_arr[entry_type][idx]);
  15299 
  15300         /* Free qualifiers arrays. */
  15301         if (NULL != q_arr->qid_arr) {
  15302             sal_free(q_arr->qid_arr);
  15303             q_arr->qid_arr = NULL;
  15304         }
  15305         if (NULL != q_arr->offset_arr) {
  15306             sal_free(q_arr->offset_arr);
  15307             q_arr->offset_arr = NULL;
  15308         }
  15309         /* Reset arrays size. */
  15310         q_arr->size = 0;
  15311     }
  15312 
  15313     return (BCM_E_NONE);
  15314 }
  15315 
  15316 /*
  15317  * Function:
  15318  *  _bcm_field_group_default_entry_set
  15319  * Purpose:
  15320  *  Set or Clear default entry status of a entry.
  15321  * Parameters:
  15322  *  unit    - (IN) BCM Device Number.
  15323  *  group   - (IN) Field Group ID.
  15324  *  entry   - (IN) Field Entry ID.
  15325  *  enable  - (IN) Enable Flag.
  15326  * Returns:
  15327  *  BCM_E_XXX
  15328  * Note:
  15329  *  Currently it is applicable only for exact
  15330  *  match stage.
  15331  */
  15332 int
  15333 _bcm_field_group_default_entry_set(int unit, bcm_field_group_t group,
  15334                                    bcm_field_entry_t entry, int enable)
  15335 {
  15336     int rv = BCM_E_NONE;         /* Operation return status.         */
  15337     int idx = 0;                 /* Entry index                      */
  15338     _field_group_t *fg = NULL;   /* Field group structure.           */
  15339     _field_entry_t *f_ent = NULL;/* Field entry pointer.             */
  15340     _field_entry_t *f_ent_tmp = NULL;
  15341                                  /* Field entry temp pointer.        */
  15342     _field_entry_stat_t *f_ent_st = NULL;
  15343                                  /* Field entry statistics structure.*/
  15344     _field_entry_policer_t *f_ent_pl = NULL;
  15345                                  /* Field entry policer structure.   */
  15346     _field_action_t *fa = NULL;  /* Field action descriptor.         */
  15347     int level = 0;               /* Field policer Level.             */
  15348     int parts_cnt = 0;           /* Field Entry parts count.         */
  15349 
  15350     /* First validate if provided group and entry id exist. */
  15351     BCM_IF_ERROR_RETURN(_field_group_get(unit, group, &fg));
  15352     BCM_IF_ERROR_RETURN(_field_entry_get(unit, entry,
  15353                                          _FP_ENTRY_PRIMARY, &f_ent));
  15354 
  15355     /* Check enable flag value. */
  15356     if ((enable < 0) && (enable > 1)) {
  15357         LOG_ERROR(BSL_LS_BCM_FP,
  15358            (BSL_META_U(unit,
  15359             "FP(unit %d) Error: enable flag value %d not valid.\n"),
  15360             unit, enable));
  15361         return (BCM_E_PARAM);
  15362     }
  15363 
  15364     /* Check if entry belongs to same group provided. */
  15365     if (f_ent->group->gid != group) {
  15366         LOG_ERROR(BSL_LS_BCM_FP,
  15367            (BSL_META_U(unit,
  15368             "FP(unit %d) Error: entry=(%d) does not belong to group %d.\n"),
  15369             unit, entry, group));
  15370         return (BCM_E_CONFIG);
  15371     }
  15372 
  15373     /* Check if Group belongs to exact match stage. */
  15374     if (fg->stage_id != _BCM_FIELD_STAGE_EXACTMATCH) {
  15375         LOG_ERROR(BSL_LS_BCM_FP,
  15376            (BSL_META_U(unit,
  15377             "FP(unit %d) Error: group=(%d) stage is not exact match.\n"),
  15378             unit, group));
  15379         return (BCM_E_CONFIG);
  15380     }
  15381 
  15382     /* Get Field Entry Parts. */
  15383     BCM_IF_ERROR_RETURN(_bcm_field_entry_tcam_parts_count(unit,
  15384                                                           fg->stage_id,
  15385                                                           fg->flags,
  15386                                                           &parts_cnt));
  15387 
  15388     /* Check existing set or clear status for entry default status flag. */
  15389     if (enable) {
  15390         if (f_ent->flags & _FP_ENTRY_EXACT_MATCH_GROUP_DEFAULT) {
  15391             return (BCM_E_NONE);
  15392         }
  15393     } else {
  15394         if (!(f_ent->flags & _FP_ENTRY_EXACT_MATCH_GROUP_DEFAULT)) {
  15395             return (BCM_E_NONE);
  15396         }
  15397     }
  15398 
  15399     /* Check group default entry status for set and clear. */
  15400     if (enable) {
  15401         for (idx = 0; idx < fg->group_status.entry_count; idx++) {
  15402             f_ent_tmp = fg->entry_arr[idx];
  15403             if (f_ent_tmp->flags & _FP_ENTRY_EXACT_MATCH_GROUP_DEFAULT) {
  15404                 LOG_ERROR(BSL_LS_BCM_FP,
  15405                    (BSL_META_U(unit,
  15406                     "FP(unit %d) Error: group=(%d) already have existing"
  15407                     "default entry %d.\n"),
  15408                     unit, group, f_ent_tmp->eid));
  15409                 return (BCM_E_CONFIG);
  15410             }
  15411         }
  15412     }
  15413 
  15414     /* Check if entry is installed. */
  15415     if (f_ent->flags & _FP_ENTRY_INSTALLED) {
  15416         LOG_ERROR(BSL_LS_BCM_FP,
  15417            (BSL_META_U(unit,
  15418             "FP(unit %d) Error: entry=(%d) is installed, "
  15419             "cannot change default status.\n"),
  15420              unit, entry));
  15421         return (BCM_E_CONFIG);
  15422     }
  15423 
  15424     /* Check if group have qualifier associated to it. */
  15425     for(idx = 0; idx < parts_cnt; idx++) {
  15426         f_ent_tmp = f_ent + idx;
  15427 
  15428         /* Check if any action is attached to entry. */
  15429         fa = f_ent_tmp->actions;
  15430         if (fa != NULL) {
  15431             LOG_ERROR(BSL_LS_BCM_FP,
  15432                (BSL_META_U(unit,
  15433                 "FP(unit %d) Error: entry=(%d) have action associated, "
  15434                 "cannot change default status.\n"),
  15435                  unit, entry));
  15436             return (BCM_E_CONFIG);
  15437         }
  15438 
  15439         /* Check if valid stat is attached. */
  15440         f_ent_st = &f_ent_tmp->statistic;
  15441         if (f_ent_st->flags & _FP_ENTRY_STAT_VALID) {
  15442             LOG_ERROR(BSL_LS_BCM_FP,
  15443                (BSL_META_U(unit,
  15444                 "FP(unit %d) Error: entry=(%d) have stats attached to it, "
  15445                 "cannot change default status.\n"),
  15446                 unit, entry));
  15447             return (BCM_E_CONFIG);
  15448         }
  15449 
  15450         /* Check if valid policer is attached. */
  15451         for (level = 0; level < _FP_POLICER_LEVEL_COUNT; level++) {
  15452             f_ent_pl = f_ent_tmp->policer + level;
  15453             if (f_ent_pl->flags & _FP_POLICER_VALID) {
  15454                 LOG_ERROR(BSL_LS_BCM_FP,
  15455                    (BSL_META_U(unit,
  15456                     "FP(unit %d) Error: entry=(%d) have policer attached to "
  15457                     "it, cannot change default status.\n"),
  15458                      unit, entry));
  15459                 return (BCM_E_CONFIG);
  15460             }
  15461         }
  15462     }
  15463 
  15464     /* Configure entry as default. */
  15465     if (enable) {
  15466         /* Clear qualifier if any. */
  15467         BCM_IF_ERROR_RETURN(bcm_esw_field_qualify_clear(unit, entry));
  15468         f_ent->flags |= _FP_ENTRY_EXACT_MATCH_GROUP_DEFAULT;
  15469     } else {
  15470         f_ent->flags &= ~_FP_ENTRY_EXACT_MATCH_GROUP_DEFAULT;
  15471     }
  15472 
  15473     return (rv);
  15474 }
  15475 
  15476 /*
  15477  * Function:
  15478  *  _bcm_field_group_default_entry_get
  15479  * Purpose:
  15480  *  Get Default Field entry ID associated to group.
  15481  * Parameters:
  15482  *  unit    - (IN) BCM Device Number.
  15483  *  group   - (IN) Field Group ID.
  15484  *  entry   - (OUT) Field Entry ID.
  15485  * Returns:
  15486  *  BCM_E_XXX
  15487  * Note:
  15488  */
  15489 int
  15490 _bcm_field_group_default_entry_get(int unit, bcm_field_group_t group,
  15491                                             bcm_field_entry_t *entry)
  15492 {
  15493     int rv = BCM_E_NONE;           /* Operation return status.    */
  15494     _field_group_t *fg = NULL;     /* Field group structure.      */
  15495     _field_entry_t *f_ent = NULL;  /* Field entry pointer.        */
  15496     int found = 0;                 /* Entry Found Variable.       */
  15497     int idx = 0;                   /* Entry index                 */
  15498 
  15499     /* Input Parameter Check. */
  15500     if (entry == NULL) {
  15501         return (BCM_E_PARAM);
  15502     }
  15503 
  15504     /* First validate if provided group and entry id exist. */
  15505     BCM_IF_ERROR_RETURN(_field_group_get(unit, group, &fg));
  15506 
  15507     /* Check if Group belongs to exact match stage. */
  15508     if (fg->stage_id != _BCM_FIELD_STAGE_EXACTMATCH) {
  15509         LOG_ERROR(BSL_LS_BCM_FP,
  15510            (BSL_META_U(unit,
  15511             "FP(unit %d) Error: group=(%d) stage is not exact match.\n"),
  15512              unit, group));
  15513         return (BCM_E_PARAM);
  15514     }
  15515 
  15516     /* Search for all entries in group. */
  15517     for (idx = 0; idx < fg->group_status.entry_count; idx++) {
  15518         f_ent = fg->entry_arr[idx];
  15519         if (f_ent->flags & _FP_ENTRY_EXACT_MATCH_GROUP_DEFAULT) {
  15520             found = 1;
  15521             break;
  15522         }
  15523     }
  15524 
  15525     /* Return entry id if found. */
  15526     if (found) {
  15527         *entry = f_ent->eid;
  15528     } else {
  15529         rv = BCM_E_NOT_FOUND;
  15530     }
  15531 
  15532     return (rv);
  15533 }
  15534 
  15535 /*
  15536  * Function:
  15537  *     _bcm_field_qual_list_append
  15538  * Purpose:
  15539  *     Append a copy of a qualify info linked list.
  15540  * Parameters:
  15541  *     fg         - (IN) Field group structure.
  15542  *     entry_part - (IN) Field entry part.
  15543  *     fq_src     - (IN) Copy source list.
  15544  *     offset     - (IN) Offset within FPFx field.
  15545  * Returns:
  15546  *     BCM_E_NONE
  15547  * Note:
  15548  */
  15549 int
  15550 _bcm_field_qual_list_append(_field_group_t *fg, uint8 entry_part,
  15551                             _qual_info_t *fq_src, int offset)
  15552 {
  15553     _bcm_field_qual_offset_t *q_offset_arr;  /* Qualifier offsets array. */
  15554     _bcm_field_group_qual_t  *q_arr;         /* Qualifiers array.        */
  15555     _qual_info_t *fq_src_iter;               /* Qualifier list iterator. */
  15556     uint16 *qid_arr;                         /* Qualifier id array.      */
  15557     int    size;                             /* Qualifiers array size.   */
  15558 
  15559     /* Input parameters check. */
  15560     if ((NULL == fg) || (NULL == fq_src) ||
  15561         (entry_part >= _FP_MAX_ENTRY_WIDTH)) {
  15562         return (BCM_E_PARAM);
  15563     }
  15564 
  15565     /* Initialization. */
  15566     qid_arr = NULL;
  15567     q_offset_arr = NULL;
  15568     q_arr = &(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][entry_part]);
  15569 
  15570     /* Count number of group qualifiers. */
  15571     fq_src_iter = fq_src;
  15572     size = 0;
  15573 
  15574     while (NULL != fq_src_iter) {
  15575         if (0 == BCM_FIELD_QSET_TEST(fg->qset, fq_src_iter->qid)) {
  15576             fq_src_iter = fq_src_iter->next;
  15577             continue;
  15578         }
  15579         size++;
  15580         fq_src_iter = fq_src_iter->next;
  15581     }
  15582 
  15583     if (0 == size) {
  15584         return (BCM_E_NONE);
  15585     }
  15586 
  15587     size += q_arr->size;
  15588 
  15589     /* Allocate qualifiers id and offsets array. */
  15590     _FP_XGS3_ALLOC(qid_arr, size * sizeof (uint16), "Group qual id");
  15591     if (NULL == qid_arr) {
  15592         return (BCM_E_MEMORY);
  15593     }
  15594 
  15595     _FP_XGS3_ALLOC(q_offset_arr, size * sizeof (_bcm_field_qual_offset_t),
  15596                    "Group qual offset");
  15597     if (NULL == q_offset_arr) {
  15598         sal_free (qid_arr);
  15599         return (BCM_E_MEMORY);
  15600     }
  15601 
  15602     /* Copy original qualifiers array if any. */
  15603     if (q_arr->size) {
  15604         sal_memcpy(qid_arr, q_arr->qid_arr, q_arr->size * sizeof (uint16));
  15605         sal_memcpy(q_offset_arr, q_arr->offset_arr, q_arr->size * sizeof (_bcm_field_qual_offset_t));
  15606         sal_free (q_arr->qid_arr);
  15607         sal_free (q_arr->offset_arr);
  15608     }
  15609 
  15610     /* Copy qualifiers id and offsets. */
  15611     q_arr->qid_arr = qid_arr;
  15612     q_arr->offset_arr = q_offset_arr;
  15613     fq_src_iter = fq_src;
  15614     while (NULL != fq_src_iter) {
  15615         if (0 == BCM_FIELD_QSET_TEST(fg->qset, fq_src_iter->qid)) {
  15616             fq_src_iter = fq_src_iter->next;
  15617             continue;
  15618         }
  15619         q_arr->qid_arr[q_arr->size] = fq_src_iter->qid;
  15620         q_arr->offset_arr[q_arr->size].offset[0] = fq_src_iter->offset + offset;
  15621         q_arr->offset_arr[q_arr->size].width[0] = fq_src_iter->width;
  15622         q_arr->offset_arr[q_arr->size].field = fq_src_iter->fpf;
  15623         q_arr->size++;
  15624         fq_src_iter = fq_src_iter->next;
  15625     }
  15626     return (BCM_E_NONE);
  15627 }
  15628 
  15629 /*
  15630  * Function:
  15631  *     _field_entry_tcam_memory_info_get
  15632  * Purpose:
  15633  *     Get TCAM memory and field names for specific entry.
  15634  * Parameters:
  15635  *     unit  - (IN)  BCM device number.
  15636  *     f_ent - (IN)  Field entry.
  15637  *     tcam  - (OUT) TCAM memory info.
  15638  * Returns:
  15639  *     BCM_E_XXX
  15640  */
  15641 STATIC int
  15642 _field_entry_tcam_memory_info_get(int unit, _field_entry_t *f_ent,
  15643     _field_tcam_mem_info_t *tcam, int ipbm_overlay)
  15644 {
  15645 
  15646     /* Input parameters check. */
  15647     if ((NULL == f_ent)  || (NULL == tcam)) {
  15648         return (BCM_E_PARAM);
  15649     }
  15650 
  15651 #if defined(BCM_FIREBOLT_SUPPORT)
  15652 
  15653 #if defined(BCM_HURRICANE_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT)
  15654         if (SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) ||
  15655             SOC_IS_GREYHOUND2(unit)) {
  15656            if (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id) {
  15657                 tcam->key_field = (SOC_IS_HURRICANE2(unit) ||
  15658                     SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) ||
  15659                     SOC_IS_GREYHOUND2(unit)) ?
  15660                     DATA_KEYf : DATAf;
  15661                 tcam->mask_field = DATA_MASKf;
  15662                 tcam->memory = FP_TCAMm;
  15663            } else if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) {
  15664                 tcam->memory = EFP_TCAMm;
  15665                 tcam->key_field = KEYf;
  15666                 tcam->mask_field = KEY_MASKf;
  15667             } else if (_BCM_FIELD_STAGE_LOOKUP== f_ent->group->stage_id) {
  15668                 tcam->memory = VFP_TCAMm;
  15669                 tcam->key_field = KEYf;
  15670                 tcam->mask_field = MASKf;
  15671             }
  15672 
  15673         } else
  15674 #endif /* BCM_HURRICANE_SUPPORT || BCM_GREYHOUND_SUPPORT */
  15675 
  15676     if (SOC_IS_FBX(unit)) {
  15677         if ((_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id)) {
  15678             tcam->memory = FP_TCAMm;
  15679 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  15680             if (SOC_IS_TD_TT(unit))
  15681             {
  15682                 tcam->key_field = KEYf;
  15683                 tcam->mask_field = MASKf;
  15684 
  15685                 if (ipbm_overlay)
  15686                 {
  15687                     tcam->memory = FP_GM_FIELDSm;
  15688                 }
  15689             } else if ((SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || SOC_IS_KATANAX(unit))
  15690                     && ipbm_overlay) {
  15691                 tcam->key_field = IPBMf;
  15692                 tcam->mask_field = IPBM_MASKf;
  15693                 tcam->memory = FP_GLOBAL_MASK_TCAMm;
  15694             } else if ((SOC_IS_TRX(unit)) ||
  15695                     (f_ent->flags & _FP_ENTRY_SECOND_HALF)) {
  15696                 tcam->key_field = DATAf;
  15697                 tcam->mask_field = DATA_MASKf;
  15698             } else
  15699 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  15700             {
  15701                 tcam->key_field = KEYf;
  15702                 tcam->mask_field = MASKf;
  15703             }
  15704         }
  15705 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  15706         if (soc_feature(unit, soc_feature_field_multi_stage)) {
  15707             if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) {
  15708                 tcam->memory = EFP_TCAMm;
  15709                 tcam->key_field = KEYf;
  15710                 tcam->mask_field = KEY_MASKf;
  15711             } else if (_BCM_FIELD_STAGE_LOOKUP== f_ent->group->stage_id) {
  15712                 tcam->memory = VFP_TCAMm;
  15713                 tcam->key_field = KEYf;
  15714                 tcam->mask_field = MASKf;
  15715             }
  15716         }
  15717 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  15718     }
  15719 #endif /* BCM_FIREBOLT_SUPPORT */
  15720     return (BCM_E_NONE);
  15721 }
  15722 
  15723 /*
  15724  * Function:
  15725  *     _bcm_field_qual_tcam_key_mask_free
  15726  * Purpose:
  15727  *     Free tcam key/mask buffers.
  15728  * Parameters:
  15729  *     unit  - (IN)     BCM device number.
  15730  *     f_ent - (IN/OUT) Field entry.
  15731  * Returns:
  15732  *     BCM_E_XXX
  15733  */
  15734 int
  15735 _bcm_field_qual_tcam_key_mask_free(int unit, _field_entry_t *f_ent)
  15736 {
  15737     /* Input parameters check. */
  15738     if (NULL == f_ent) {
  15739         return (BCM_E_PARAM);
  15740     }
  15741 
  15742     if (NULL != f_ent->tcam.key) {
  15743         sal_free(f_ent->tcam.key);
  15744         f_ent->tcam.key = NULL;
  15745     }
  15746     if (NULL != f_ent->tcam.mask) {
  15747         sal_free(f_ent->tcam.mask);
  15748         f_ent->tcam.mask = NULL;
  15749     }
  15750     if (NULL != f_ent->tcam.key_hw) {
  15751         sal_free(f_ent->tcam.key_hw);
  15752         f_ent->tcam.key_hw = NULL;
  15753     }
  15754     if (NULL != f_ent->tcam.mask_hw) {
  15755         sal_free(f_ent->tcam.mask_hw);
  15756         f_ent->tcam.mask_hw = NULL;
  15757     }
  15758     if (NULL != f_ent->key_match_tcam.key) {
  15759         sal_free(f_ent->key_match_tcam.key);
  15760         f_ent->key_match_tcam.key = NULL;
  15761     }
  15762     if (NULL != f_ent->key_match_tcam.mask) {
  15763         sal_free(f_ent->key_match_tcam.mask);
  15764         f_ent->key_match_tcam.mask = NULL;
  15765     }
  15766     if (NULL != f_ent->key_match_tcam.key_hw) {
  15767         sal_free(f_ent->key_match_tcam.key_hw);
  15768         f_ent->key_match_tcam.key_hw = NULL;
  15769     }
  15770     if (NULL != f_ent->key_match_tcam.mask_hw) {
  15771         sal_free(f_ent->key_match_tcam.mask_hw);
  15772         f_ent->key_match_tcam.mask_hw = NULL;
  15773     }
  15774     if (NULL != f_ent->extra_tcam.key) {
  15775         sal_free(f_ent->extra_tcam.key);
  15776         f_ent->extra_tcam.key = NULL;
  15777     }
  15778     if (NULL != f_ent->extra_tcam.mask) {
  15779         sal_free(f_ent->extra_tcam.mask);
  15780         f_ent->extra_tcam.mask = NULL;
  15781     }
  15782     if (NULL != f_ent->extra_tcam.key_hw) {
  15783         sal_free(f_ent->extra_tcam.key_hw);
  15784         f_ent->extra_tcam.key_hw = NULL;
  15785     }
  15786     if (NULL != f_ent->extra_tcam.mask_hw) {
  15787         sal_free(f_ent->extra_tcam.mask_hw);
  15788         f_ent->extra_tcam.mask_hw = NULL;
  15789     }
  15790     return (BCM_E_NONE);
  15791 }
  15792 
  15793 int _field_qual_tcam_key_mask_get(int unit, _field_entry_t *f_ent,
  15794     _field_tcam_t *tcam, int ipbm_overlay)
  15795 {
  15796     uint32 tcam_entry[SOC_MAX_MEM_FIELD_WORDS];
  15797     _field_tcam_mem_info_t tcam_info = { 0 };
  15798     int tcam_idx;
  15799     int rv;
  15800     int key_size;
  15801 
  15802     /* Get TCAM memory and Fields information. */
  15803 
  15804     BCM_IF_ERROR_RETURN(_field_entry_tcam_memory_info_get(unit, f_ent,
  15805         &tcam_info, ipbm_overlay));
  15806 
  15807     if (!SOC_MEM_FIELD_VALID(unit, tcam_info.memory, tcam_info.key_field)) {
  15808         return (BCM_E_INTERNAL);
  15809     }
  15810     /* Key size in bits. */
  15811     key_size = soc_mem_field_length(unit, tcam_info.memory,
  15812         tcam_info.key_field);
  15813     /* Convert to bytes - full number of words alligned. */
  15814     key_size = (((key_size >> 5) + 1) << 2);
  15815 
  15816 
  15817     /* Allocate and zero memory for tcam image.*/
  15818     tcam->key  = sal_alloc(key_size, "field_entry_tcam_key");
  15819     tcam->mask = sal_alloc(key_size, "field_entry_tcam_mask");
  15820     if ((NULL == tcam->key) || (NULL == tcam->mask)) {
  15821         LOG_ERROR(BSL_LS_BCM_FP,
  15822                 (BSL_META_U(unit,
  15823                 "FP(unit %d) Error: allocation failure for field_entry tcam\n"),
  15824                  unit));
  15825         if (tcam->key) sal_free(tcam->key);
  15826         if (tcam->mask) sal_free(tcam->mask);
  15827         return (BCM_E_MEMORY);
  15828     }
  15829     sal_memset(tcam->key, 0, key_size);
  15830     sal_memset(tcam->mask, 0, key_size);
  15831     tcam->key_size = key_size;
  15832 
  15833     /* Read entry from HW if it was installed previously. */
  15834     if(f_ent->flags & _FP_ENTRY_INSTALLED) {
  15835         rv = _bcm_field_entry_tcam_idx_get(unit, f_ent, &tcam_idx);
  15836         if (BCM_FAILURE(rv)) {
  15837             if (tcam->key) sal_free(tcam->key);
  15838             if (tcam->mask) sal_free(tcam->mask);
  15839             tcam->mask = tcam->key = NULL;
  15840             return (rv);
  15841         }
  15842         rv = soc_mem_read(unit, tcam_info.memory, MEM_BLOCK_ANY,
  15843                           tcam_idx, tcam_entry);
  15844         if (BCM_FAILURE(rv)) {
  15845             if (tcam->key) sal_free(tcam->key);
  15846             if (tcam->mask) sal_free(tcam->mask);
  15847             tcam->mask = tcam->key = NULL;
  15848             return (rv);
  15849         }
  15850         soc_mem_field_get(unit, tcam_info.memory, tcam_entry,
  15851                           tcam_info.key_field, tcam->key);
  15852         soc_mem_field_get(unit, tcam_info.memory, tcam_entry,
  15853                           tcam_info.mask_field, tcam->mask);
  15854         if (SOC_MEM_FIELD_VALID(unit, tcam_info.memory, F4f)) {
  15855             soc_mem_field_get(unit, tcam_info.memory, tcam_entry,
  15856                               F4f, &tcam->f4);
  15857             soc_mem_field_get(unit, tcam_info.memory, tcam_entry,
  15858                               F4_MASKf, &tcam->f4_mask);
  15859         }
  15860     }
  15861 
  15862     return BCM_E_NONE;
  15863 }
  15864 
  15865 /*
  15866  * Function:
  15867  *     _bcm_field_qual_tcam_key_mask_get
  15868  * Purpose:
  15869  *     Allocate & read from hw tcam key/mask image.
  15870  * Parameters:
  15871  *     unit  - (IN)     BCM device number.
  15872  *     f_ent - (IN/OUT) Field entry.
  15873  * Returns:
  15874  *     BCM_E_XXX
  15875  */
  15876 int
  15877 _bcm_field_qual_tcam_key_mask_get(int unit, _field_entry_t *f_ent)
  15878 {
  15879     /* Input parameters check. */
  15880     if (NULL == f_ent) {
  15881         return (BCM_E_PARAM);
  15882     }
  15883 
  15884     if (f_ent->flags & _FP_ENTRY_USES_IPBM_OVERLAY) {
  15885         if (NULL == f_ent->extra_tcam.key) {
  15886             BCM_IF_ERROR_RETURN(_field_qual_tcam_key_mask_get(unit, f_ent,
  15887                 &f_ent->extra_tcam, 1));
  15888         }
  15889     }
  15890 
  15891     /* Check if tcam info already present. */
  15892     if (NULL != f_ent->tcam.key) {
  15893         return (BCM_E_NONE);
  15894     }
  15895 
  15896     if (_BCM_FIELD_STAGE_EXTERNAL == f_ent->fs->stage_id) {
  15897 #if defined(BCM_TRIUMPH_SUPPORT)
  15898         if (SOC_IS_TRIUMPH(unit) || SOC_IS_TRIUMPH2(unit)) {
  15899             return _bcm_field_tr_external_tcam_key_mask_get(unit, f_ent);
  15900         }
  15901 #endif /* BCM_TRIUMPH_SUPPORT */
  15902     }
  15903 
  15904 #ifdef BCM_TRIDENT2_SUPPORT
  15905     if (SOC_IS_TD2_TT2(unit)) {
  15906 #if defined(BCM_TOMAHAWK_SUPPORT)
  15907        if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  15908            ((_BCM_FIELD_STAGE_INGRESS == f_ent->fs->stage_id) ||
  15909             (_BCM_FIELD_STAGE_LOOKUP == f_ent->fs->stage_id) ||
  15910             (_BCM_FIELD_STAGE_EGRESS == f_ent->fs->stage_id) ||
  15911             (_BCM_FIELD_STAGE_EXACTMATCH == f_ent->fs->stage_id) ||
  15912             (_BCM_FIELD_STAGE_FLOWTRACKER == f_ent->fs->stage_id))) {
  15913           BCM_IF_ERROR_RETURN
  15914             (_bcm_field_th_qual_tcam_key_mask_get(unit, f_ent, &f_ent->tcam));
  15915           /* EFP has 2 types of keys for each entry. 1. tcam will have
  15916            * all the qualifiers i.e., default qset. 2. key_match_tcam is
  15917            * a subset of default qset having only Not L3 and Not FCoE quals */
  15918           if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) {
  15919              if (NULL != f_ent->key_match_tcam.key) {
  15920                 return (BCM_E_NONE);
  15921              }
  15922              /* if key_match_tcam is Null, Allocate memory for it */
  15923              BCM_IF_ERROR_RETURN
  15924                 (_bcm_field_th_qual_tcam_key_mask_get(unit, f_ent,
  15925                                           &f_ent->key_match_tcam));
  15926 
  15927              /* At the time of entry install, both tcam and key_match_tcam
  15928               * are freed. if entry is already installed, one key will be
  15929               * updated from the h/w tcam, and the other key will be updated
  15930               * in the below function depending on efp_key_match_type value*/
  15931              if (f_ent->flags & _FP_ENTRY_INSTALLED) {
  15932                   if(!(f_ent->group->flags & _FP_GROUP_SPAN_DOUBLE_SLICE
  15933                        && f_ent->flags & _FP_ENTRY_PRIMARY)) {
  15934                       return (bcm_field_efp_update_alternate_key_mask(unit, f_ent,
  15935                                                 f_ent->efp_key_match_type));
  15936                   }
  15937              }
  15938              return (BCM_E_NONE);
  15939           }
  15940 
  15941        } else
  15942 #endif /* BCM_TOMAHAWK_SUPPORT */
  15943        {
  15944           BCM_IF_ERROR_RETURN
  15945               (_bcm_field_td2_qual_tcam_key_mask_get(unit, f_ent,
  15946                                                      &f_ent->tcam));
  15947        }
  15948 
  15949        if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) {
  15950           if (NULL != f_ent->key_match_tcam.key) {
  15951               return (BCM_E_NONE);
  15952           }
  15953           BCM_IF_ERROR_RETURN
  15954            (_bcm_field_td2_qual_tcam_key_mask_get(unit, f_ent, &f_ent->key_match_tcam));
  15955 
  15956           if (f_ent->flags & _FP_ENTRY_INSTALLED) {
  15957               if(!(f_ent->group->flags & _FP_GROUP_SPAN_DOUBLE_SLICE
  15958                    && f_ent->flags & _FP_ENTRY_PRIMARY)) {
  15959                   return (bcm_field_efp_update_alternate_key_mask(unit, f_ent,
  15960                                             f_ent->efp_key_match_type));
  15961               }
  15962           }
  15963           return (BCM_E_NONE);
  15964        } else {
  15965           return (BCM_E_NONE);
  15966        }
  15967     } else
  15968 #endif
  15969 
  15970 #ifdef BCM_TRIUMPH3_SUPPORT
  15971     if (SOC_IS_TRIUMPH3(unit)) {
  15972         return (_bcm_field_tr3_qual_tcam_key_mask_get(unit, f_ent, &f_ent->tcam));
  15973     }
  15974 #endif
  15975 
  15976 #ifdef BCM_KATANA2_SUPPORT
  15977     if (SOC_IS_KATANA2(unit)) {
  15978         return (_bcm_field_kt2_qual_tcam_key_mask_get(unit, f_ent, &f_ent->tcam));
  15979     }
  15980 #endif
  15981 
  15982 
  15983     BCM_IF_ERROR_RETURN(_field_qual_tcam_key_mask_get(unit, f_ent,
  15984                         &f_ent->tcam, 0));
  15985 
  15986     return (BCM_E_NONE);
  15987 }
  15988 
  15989 
  15990 /*
  15991  * Function:
  15992  *     _field_qual_value_set
  15993  *
  15994  * Purpose:
  15995  *     Set a qualifier field from the designated data and mask arrays.
  15996  *
  15997  * Parameters:
  15998  *     unit    - (IN) BCM devices number
  15999  *     qi      - (IN) Qualifier offset inside tcam.
  16000  *     f_ent   - (IN) Field entry descriptor.
  16001  *     p_data  - (IN) Inserted data.
  16002  *     p_mask  - (IN) Data mask.
  16003  *     ipbm_overlay - (IN) Flag to indicate extra_tcam has to be used or not
  16004  *     key_match_tcam - (IN) Flag to indicate which tcam to use
  16005  * Returns:
  16006  *     BCM_E_XXX
  16007  */
  16008 STATIC int
  16009 _field_qual_value_set(int unit, _qual_info_t *qi,
  16010                       _field_entry_t *f_ent,
  16011                       uint32 *p_data, uint32 *p_mask,
  16012                       int ipbm_overlay, uint8 key_match_tcam)
  16013 {
  16014     uint32              u32_mask, *p_fn_data, *p_fn_mask;
  16015     int                 idx, wp, bp, len;
  16016 
  16017 #define DATA_TOO_BIG_FOR_FIELD ((p_data[idx] & ~u32_mask) != 0)
  16018     wp = qi->offset / 32;
  16019     bp = qi->offset & (32 - 1);
  16020     idx = 0;
  16021     p_fn_data = p_fn_mask = NULL;
  16022 
  16023     LOG_DEBUG(BSL_LS_BCM_FP,
  16024               (BSL_META_U(unit,
  16025               "FP(unit %d) vverb: qi={offset=%d, width=%d}, ipbm_overlay=%d, data=0x%08x, mask=0x%08x\n"),
  16026                unit, qi->offset, qi->width, ipbm_overlay, *p_data, *p_mask));
  16027 
  16028     BCM_IF_ERROR_RETURN(_bcm_field_qual_tcam_key_mask_get(unit, f_ent));
  16029 
  16030     switch (qi->fpf) {
  16031 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  16032       case DATAf:
  16033       case DATA_KEYf:
  16034 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  16035       case KEYf:
  16036 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT)
  16037           if (ipbm_overlay) {
  16038               p_fn_data = f_ent->extra_tcam.key;
  16039               p_fn_mask = f_ent->extra_tcam.mask;
  16040           } else
  16041 #endif /* BCM_TRIDENT_SUPPORT */
  16042           if (key_match_tcam) {
  16043               p_fn_data = f_ent->key_match_tcam.key;
  16044               p_fn_mask = f_ent->key_match_tcam.mask;
  16045           } else {
  16046               p_fn_data = f_ent->tcam.key;
  16047               p_fn_mask = f_ent->tcam.mask;
  16048           }
  16049 
  16050           break;
  16051 #ifdef BCM_FIREBOLT_SUPPORT
  16052       case F4f:
  16053           p_fn_data = &f_ent->tcam.f4;
  16054           /* coverity[ptr_arith : FALSE] */
  16055           p_fn_mask = &f_ent->tcam.f4_mask;
  16056           break;
  16057 #endif /* BCM_FIREBOLT_SUPPORT */
  16058       default:
  16059           LOG_ERROR(BSL_LS_BCM_FP,
  16060                     (BSL_META_U(unit,
  16061                                 "FP(unit %d) Error: Bad TCAM field=%#05x\n"),
  16062                      unit, qi->fpf));
  16063           return (BCM_E_INTERNAL);
  16064     };
  16065 
  16066     for (len = qi->width; len > 0; len -= 32) {
  16067         if (bp) {
  16068             if (len < 32) {
  16069                 u32_mask = (1 << len) - 1;
  16070                 /* Chop mask to fit mask field. */
  16071                 p_mask[idx] &= u32_mask;
  16072                 if (DATA_TOO_BIG_FOR_FIELD) {
  16073                     LOG_ERROR(BSL_LS_BCM_FP,
  16074                               (BSL_META_U(unit,
  16075                                           "FP(unit %d) Error: data=%#x "),
  16076                                unit, *p_data));
  16077                     LOG_ERROR(BSL_LS_BCM_FP,
  16078                               (BSL_META_U(unit,
  16079                                           "or mask=%#x too big for field\n"),
  16080                                *p_mask));
  16081                     return (BCM_E_PARAM);
  16082                 }
  16083             } else {
  16084                 u32_mask = 0xffffffff;
  16085             }
  16086 
  16087             p_fn_data[wp] &= ~(u32_mask << bp);
  16088             p_fn_data[wp] |= p_data[idx] << bp;
  16089             /*
  16090     * COVERITY
  16091     *
  16092     *This flow takes care of the  Out-of-bounds access issue
  16093     * for data and mask.
  16094     */
  16095     /* coverity[ptr_arith : FALSE] */
  16096 
  16097             p_fn_mask[wp] &= ~(u32_mask << bp);
  16098             p_fn_mask[wp] |= p_mask[idx] << bp;
  16099 
  16100             if (len > (32-bp)) {
  16101                 wp++;
  16102                 p_fn_data[wp] &= ~(u32_mask >> (32 - bp));
  16103                 p_fn_data[wp] |= p_data[idx] >> (32 - bp) & ((1 << bp) - 1);
  16104 
  16105                 p_fn_mask[wp] &= ~(u32_mask >> (32 - bp));
  16106                 p_fn_mask[wp] |= p_mask[idx] >> (32 - bp) & ((1 << bp) - 1);
  16107             }
  16108         } else {
  16109             if (len < 32) {
  16110                 u32_mask = (1 << len) - 1;
  16111                 /* Chop mask to fit mask field. */
  16112                 p_mask[idx] &= u32_mask;
  16113                 if (DATA_TOO_BIG_FOR_FIELD) {
  16114                     LOG_ERROR(BSL_LS_BCM_FP,
  16115                               (BSL_META_U(unit,
  16116                                           "FP(unit %d) Error: data=%#x or mask=%#x "
  16117                                            "too big for field\n"),
  16118                                unit, *p_data, *p_mask));
  16119                     return (BCM_E_PARAM);
  16120                 }
  16121                 p_fn_data[wp] &= ~u32_mask;
  16122                 p_fn_data[wp] |= p_data[idx];
  16123                 /* coverity[ptr_arith : FALSE] */
  16124                 p_fn_mask[wp] &= ~u32_mask;
  16125                 p_fn_mask[wp++] |= p_mask[idx];
  16126 
  16127             } else {
  16128                 p_fn_data[wp] = p_data[idx];
  16129                 /* coverity[ptr_arith : FALSE] */
  16130                 p_fn_mask[wp++] = p_mask[idx];
  16131             }
  16132         }
  16133 
  16134         idx++;
  16135     }
  16136 
  16137     f_ent->flags |= _FP_ENTRY_DIRTY;
  16138     f_ent->flags &= ~(_FP_ENTRY_POLICY_TABLE_ONLY_DIRTY);
  16139 
  16140     return (BCM_E_NONE);
  16141 }
  16142 #undef DATA_TOO_BIG_FOR_FIELD
  16143 
  16144 /*
  16145  * Function:
  16146  *     _field_qual_value_get
  16147  *
  16148  * Purpose:
  16149  *     Retrieve a qualifier value from the designated data/mask
  16150  *     field pair, returning them to *p_data and *p_mask.
  16151  *
  16152  * Returns:
  16153  *     BCM_E_NONE - Success
  16154  */
  16155 STATIC int
  16156 _field_qual_value_get(int unit, _qual_info_t *qi, _field_entry_t *f_ent,
  16157                       uint32 *p_data, uint32 *p_mask, int ipbm_overlay)
  16158 {
  16159     uint32              *p_fn_data, *p_fn_mask;
  16160     int                 idx, wp, bp, len;
  16161 
  16162     /* Input parameters check. */
  16163     if ((NULL == f_ent) || (NULL == p_data) ||
  16164         (NULL == qi) || (NULL == p_mask)) {
  16165         return (BCM_E_PARAM);
  16166     }
  16167 
  16168     wp = qi->offset / 32;
  16169     bp = qi->offset & (32 - 1);
  16170     idx = 0;
  16171     p_fn_data = p_fn_mask = NULL;
  16172 
  16173     BCM_IF_ERROR_RETURN(_bcm_field_qual_tcam_key_mask_get(unit, f_ent));
  16174 
  16175     switch (qi->fpf) {
  16176 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  16177         case DATAf:
  16178         case DATA_KEYf:
  16179 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  16180         case KEYf:
  16181 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT)
  16182             if (ipbm_overlay) {
  16183                 p_fn_data = f_ent->extra_tcam.key;
  16184                 p_fn_mask = f_ent->extra_tcam.mask;
  16185             } else
  16186 #endif /* BCM_TRIDENT_SUPPORT */
  16187 #if defined(BCM_TRIDENT2_SUPPORT)
  16188             if (SOC_IS_TD2_TT2(unit) &&
  16189                 ((_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id)) &&
  16190                 (f_ent->efp_key_match_type)) {
  16191                 p_fn_data = f_ent->key_match_tcam.key;
  16192                 p_fn_mask = f_ent->key_match_tcam.mask;
  16193             } else
  16194 #endif
  16195             {
  16196                 p_fn_data = f_ent->tcam.key;
  16197                 p_fn_mask = f_ent->tcam.mask;
  16198             }
  16199             break;
  16200 #ifdef BCM_FIREBOLT_SUPPORT
  16201         case F4f:
  16202             p_fn_data = &f_ent->tcam.f4;
  16203             p_fn_mask = &f_ent->tcam.f4_mask;
  16204             break;
  16205 #endif /* BCM_FIREBOLT_SUPPORT */
  16206         default:
  16207             LOG_ERROR(BSL_LS_BCM_FP,
  16208                       (BSL_META_U(unit,
  16209                                   "FP(unit %d) Error: Bad TCAM field=%#05x\n"),
  16210                        unit, qi->fpf));
  16211             return (BCM_E_INTERNAL);
  16212     };
  16213 
  16214     for (len = qi->width; len > 0; len -= 32) {
  16215         if ((NULL == p_fn_data) || (NULL == p_fn_mask)) {
  16216             /*
  16217              * IPBM Overlay qualifier set in the group but
  16218              * not qualified for this entry.
  16219              */
  16220             p_data[idx] = 0x0;
  16221             p_mask[idx] = 0x0;
  16222         } else {
  16223             if (bp) {
  16224                 p_data[idx] = (p_fn_data[wp] >> bp) & ((1 << (32 - bp)) - 1);
  16225                 /* coverity[ptr_arith : FALSE] */
  16226                 p_mask[idx] = (p_fn_mask[wp] >> bp) & ((1 << (32 - bp)) - 1);
  16227                 if (len > (32-bp)) {
  16228                     wp++;
  16229                 p_data[idx] |= p_fn_data[wp] << (32 - bp);
  16230                 p_mask[idx] |= p_fn_mask[wp] << (32 - bp);
  16231                 }
  16232             } else {
  16233                 p_data[idx] = p_fn_data[wp];
  16234                 /* coverity[ptr_arith : FALSE] */
  16235                 p_mask[idx] = p_fn_mask[wp++];
  16236             }
  16237         }
  16238 
  16239         if (len < 32) {
  16240             p_data[idx] &= ((1 << len) - 1);
  16241             p_mask[idx] &= ((1 << len) - 1);
  16242         }
  16243 
  16244         idx++;
  16245     }
  16246 
  16247     return (BCM_E_NONE);
  16248 }
  16249 
  16250 
  16251 /*
  16252  * Function:
  16253  *     _bcm_field_qual_partial_data_get
  16254  * Purpose:
  16255  *     Get a portion of a uint32 array
  16256  * Parameters:
  16257  *     in_data   - uint32 array
  16258  *     start_pos - starting bit postion in above array requested (base-0)
  16259  *     len       - length of data requested (in bits)
  16260  *     out_data  - uint32 array of in_data from start_pos to start_pos + len
  16261  * Returns:
  16262  *     BCM_E_XXX
  16263  * Notes:
  16264  *     - Calculate the word in in_data where start_pos occurs
  16265  *     - Calculate the bit position in above word where start_pos occurs
  16266  *     - Iterate:
  16267  *         - Get upper half of word (from bit position to end of word)
  16268  *         - Get remainder portion from next word
  16269  *             - If required: bit postion not 0 (start_pos not a multiple of 32)
  16270  *             - If present
  16271  *         - These two together form one word of out_data
  16272  *         - Go to next word.
  16273  *     - Mask the higher (extra) bits in last word of out_data
  16274  *
  16275  *     - max_size is set to 16 (128 bits) as this is used for Ip6 and DstMac
  16276  *     - max_size is increased to 144 bits as this is used for bcmFieldQualifyL2PayLoad
  16277  */
  16278 int
  16279 _bcm_field_qual_partial_data_get(uint32 *in_data, uint8 start_pos,
  16280                                       uint16 len, uint32 *out_data)
  16281 {
  16282     int current_word, bit_pos, result_word;
  16283     int i;
  16284     int max_size = 16;
  16285 
  16286     /* Input parameters check. */
  16287     if ((NULL == in_data) || (NULL == out_data) ||
  16288         ((start_pos + len) > 256)) {
  16289         return (BCM_E_UNAVAIL);
  16290     }
  16291 
  16292     current_word = start_pos / 32;
  16293     bit_pos = start_pos - current_word * 32;
  16294 
  16295     sal_memset(out_data, 0, max_size);
  16296 
  16297     for (i = 0, result_word = 0; i < len;
  16298          i += 32, current_word++, result_word++) {
  16299 
  16300         out_data[result_word] = in_data[current_word] >> bit_pos;
  16301 
  16302         if ((bit_pos != 0) && ((bit_pos + (len - i)) > 32)) {
  16303             out_data[result_word] |= (in_data[current_word + 1] << (32 - bit_pos));
  16304         }
  16305     }
  16306     /* This check may be redundant as -1 = 0xffffffff */
  16307     if (i != len) {
  16308         i -= 32;
  16309         out_data[result_word - 1] &= ((1 << (len - i)) - 1);
  16310     }
  16311     return (BCM_E_NONE);
  16312 }
  16313 
  16314 /*
  16315  * Function:
  16316  *     _bcm_field_qual_partial_data_set
  16317  * Purpose:
  16318  *     Set a portion of a uint32 array
  16319  * Parameters:
  16320  *     in_data   - uint32 array
  16321  *     start_pos - starting bit postion in above array requested (base-0)
  16322  *     len       - length of data requested (in bits)
  16323  *     out_data  - uint32 array of in_data from start_pos to start_pos + len
  16324  * Returns:
  16325  *     none
  16326  * Notes:
  16327  *     - Calculate the word in out_data where start_pos occurs
  16328  *     - Calculate the bit position in above word where start_pos occurs
  16329  *     - Iterate:
  16330  *         - Or upper half of word (from bit position to end of word)
  16331  *         - Set remainder portion to the next word
  16332  *             - If required: bit postion not 0 (start_pos not a multiple of 32)
  16333  *             - If present
  16334  *         - These two together form one word of out_data
  16335  *         - Go to next word.
  16336  *     - Mask the higher (extra) bits in last word of out_data
  16337  *
  16338  *     - max_size is set to 16 (128 bits) as this is used for Ip6 and DstMac
  16339  *     - max_size is increased to 144 bits as this is used for bcmFieldQualifyL2PayLoad
  16340  *
  16341  * NOTES
  16342  * 1. Assumes that there are no extra bits in in_data, i.e. all of in_data is
  16343  *    copied.
  16344  * 2. Assumes that out_data has been zeroed-out.
  16345  */
  16346 int
  16347 _bcm_field_qual_partial_data_set(uint32 *in_data, uint8 start_pos,
  16348                                  uint16 len, uint32 *out_data)
  16349 {
  16350     int current_word, bit_pos, result_word;
  16351     int i;
  16352 
  16353     /* Input parameters check. */
  16354     if ((NULL == in_data) || (NULL == out_data) ||
  16355         ((start_pos + len) > 256)) {
  16356         return (BCM_E_UNAVAIL);
  16357     }
  16358 
  16359     result_word = start_pos / 32;
  16360     bit_pos = start_pos - result_word * 32;
  16361 
  16362     for (i = 0, current_word= 0; i < len;
  16363          i += 32, current_word++, result_word++) {
  16364 
  16365         out_data[result_word] |= (in_data[current_word] <<  bit_pos);
  16366 
  16367         if ((bit_pos != 0) && ((bit_pos + (len - i)) > 32)) {
  16368             out_data[result_word + 1] |= (in_data[current_word] >> (32 - bit_pos));
  16369         }
  16370     }
  16371 
  16372     return (BCM_E_NONE);
  16373 }
  16374 
  16375 /*
  16376  * Function:
  16377  *     _field_qual_part_value_get
  16378  *
  16379  * Purpose:
  16380  *     Get a qualifier field from the designated data and mask arrays.
  16381  *
  16382  * Parameters:
  16383  *     unit       - (IN) BCM devices number
  16384  *     q_offset   - (IN) Qualifier offset inside tcam.
  16385  *     f_ent      - (IN) Field entry descriptor.
  16386  *     p_data     - (IN) Inserted data.
  16387  *     p_mask     - (IN) Data mask.
  16388  *
  16389  * Returns:
  16390  *     BCM_E_XXX
  16391  */
  16392 STATIC int
  16393 _field_qual_part_value_get(int unit,
  16394                            _bcm_field_qual_offset_t *q_offset,
  16395                            uint8 qual_part,
  16396                            _field_entry_t *f_ent,
  16397                            _bcm_field_qual_data_t p_data,
  16398                            _bcm_field_qual_data_t p_mask)
  16399 {
  16400     _qual_info_t qi;
  16401     int rv;
  16402     _bcm_field_qual_data_t data;
  16403     _bcm_field_qual_data_t mask;
  16404     int offset = 0, idx = 0;
  16405     int ipbm_overlay = 0;
  16406 
  16407     /* Input parameters check. */
  16408     if ((NULL == q_offset) || (NULL == f_ent) ||
  16409         (NULL == p_data) || (NULL == p_mask)) {
  16410         return (BCM_E_PARAM);
  16411     }
  16412 
  16413     /* Primary offset handling. */
  16414     sal_memset(&qi, 0, sizeof(_qual_info_t));
  16415 
  16416     _FP_QUAL_DATA_CLEAR(data);
  16417     _FP_QUAL_DATA_CLEAR(mask);
  16418     qi.fpf = q_offset->field;
  16419     qi.offset = q_offset->offset[qual_part];
  16420     qi.width = q_offset->width[qual_part];
  16421     /* calculate offset */
  16422     for (idx = 0; idx < qual_part; idx++) {
  16423         offset += q_offset->width[idx];
  16424     }
  16425 
  16426 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT)
  16427     /*
  16428      * 1. Check if the part goes into the IPBM TCAM.
  16429      * 2. In slice Pairing mode, TCP control flag bits[5:0] are split between
  16430      *    IFP_PAIRING_IPBM_F0:TCP_FN_5_1[5:1] and IFP_PAIRING_F1:TCP_FN_0[0]
  16431      *    This special overlay case is handled here (1 == qual_part)...
  16432      */
  16433     if ((((!SOC_IS_TRIDENT2X(unit) && !SOC_IS_TITAN2PLUS(unit)))
  16434             && SOC_IS_TD_TT(unit) && q_offset->secondary &&
  16435         ((qual_part == 0 && 1 != q_offset->width[0] && 5 != q_offset->width[1]) ||
  16436         (1 == qual_part && 1 == q_offset->width[0] && 5 == q_offset->width[1])))
  16437         || ((SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || SOC_IS_KATANAX(unit))
  16438              && q_offset->secondary)) {
  16439         ipbm_overlay = 1;
  16440     }
  16441 #endif
  16442 
  16443     /* Read qualifier information from tcam.. */
  16444     rv = _field_qual_value_get(unit, &qi, f_ent, data, mask, ipbm_overlay);
  16445     BCM_IF_ERROR_RETURN(rv);
  16446 
  16447     /* Split primary portion of the qualifier. */
  16448     rv = _bcm_field_qual_partial_data_set(data, offset,
  16449                                           qi.width, p_data);
  16450     BCM_IF_ERROR_RETURN(rv);
  16451     rv = _bcm_field_qual_partial_data_set(mask, offset,
  16452                                           qi.width, p_mask);
  16453     BCM_IF_ERROR_RETURN(rv);
  16454 
  16455     return (BCM_E_NONE);
  16456 }
  16457 
  16458 
  16459 /*
  16460  * Function:
  16461  *     _bcm_field_qual_value_get
  16462  *
  16463  * Purpose:
  16464  *     Get a qualifier field from the designated data and mask arrays.
  16465  *
  16466  * Parameters:
  16467  *     unit     - (IN) BCM devices number
  16468  *     q_offset - (IN) Qualifier offset inside tcam.
  16469  *     f_ent    - (IN) Field entry descriptor.
  16470  *     p_data   - (IN) Inserted data.
  16471  *     p_mask   - (IN) Data mask.
  16472  *
  16473  * Returns:
  16474  *     BCM_E_XXX
  16475  */
  16476 int
  16477 _bcm_field_qual_value_get(int unit, _bcm_field_qual_offset_t *q_offset,
  16478                           _field_entry_t *f_ent, _bcm_field_qual_data_t p_data,
  16479                           _bcm_field_qual_data_t p_mask)
  16480 {
  16481     int rv, qual_part;
  16482 
  16483     /* Input parameters check. */
  16484     if ((NULL == q_offset) || (NULL == f_ent) ||
  16485         (NULL == p_data) || (NULL == p_mask)) {
  16486         return (BCM_E_PARAM);
  16487     }
  16488 
  16489     _FP_QUAL_DATA_CLEAR(p_data);
  16490     _FP_QUAL_DATA_CLEAR(p_mask);
  16491 
  16492     /* offset handling */
  16493     for (qual_part = 0; qual_part < q_offset->num_offsets; qual_part++) {
  16494         if (q_offset->width[qual_part] > 0)
  16495         {
  16496            rv = _field_qual_part_value_get(unit, q_offset, qual_part,
  16497                                            f_ent, p_data, p_mask);
  16498            BCM_IF_ERROR_RETURN(rv);
  16499         }
  16500     }
  16501 
  16502     return (BCM_E_NONE);
  16503 }
  16504 
  16505 /*
  16506  * Function:
  16507  *     _field_qual_part_value_set
  16508  *
  16509  * Purpose:
  16510  *     Set a qualifier field from the designated data and mask arrays.
  16511  *
  16512  * Parameters:
  16513  *     unit      - (IN) BCM devices number
  16514  *     q_offset  - (IN) Qualifier offset inside tcam.
  16515  *     qual_part - (IN) Split qualifier part.
  16516  *     f_ent     - (IN) Field entry descriptor.
  16517  *     p_data    - (IN) Inserted data.
  16518  *     p_mask    - (IN) Data mask.
  16519  *     key_match_tcam - (IN) Flag to indicate which tcam to use
  16520  * Returns:
  16521  *     BCM_E_XXX
  16522  */
  16523 int
  16524 _field_qual_part_value_set(int unit, _bcm_field_qual_offset_t *q_offset,
  16525                                uint8 qual_part, _field_entry_t *f_ent,
  16526                            uint32 *p_data, uint32 *p_mask,
  16527                            uint8 key_match_tcam)
  16528 {
  16529     uint32 data[_FP_QUAL_DATA_WORDS];
  16530     uint32 mask[_FP_QUAL_DATA_WORDS];
  16531     _qual_info_t qi;
  16532     int offset = 0;
  16533     int ipbm_overlay = 0;
  16534     int rv, idx;
  16535 
  16536     LOG_DEBUG(BSL_LS_BCM_FP,
  16537               (BSL_META_U(unit,
  16538                           "_field_qual_part_value_set\n")));
  16539     LOG_DEBUG(BSL_LS_BCM_FP,
  16540               (BSL_META_U(unit,
  16541                           "_field_qual_part_value_set:data:%x mask:%x\n"),
  16542                *p_data, *p_mask));
  16543 
  16544     /* Input parameters check. */
  16545     if ((NULL == q_offset) || (NULL == f_ent) ||
  16546         (NULL == p_data) || (NULL == p_mask)) {
  16547         return (BCM_E_PARAM);
  16548     }
  16549 
  16550     /* Primary offset handling. */
  16551     sal_memset(&qi, 0, sizeof(_qual_info_t));
  16552     qi.fpf = q_offset->field;
  16553     qi.offset = q_offset->offset[qual_part];
  16554     qi.width = q_offset->width[qual_part];
  16555     /* calculate offset */
  16556     for (idx = 0; idx < qual_part; idx++) {
  16557         offset += q_offset->width[idx];
  16558     }
  16559 
  16560     /* Split primary portion of the qualifier. */
  16561     rv = _bcm_field_qual_partial_data_get (p_data, offset,
  16562                                            qi.width, data);
  16563     BCM_IF_ERROR_RETURN(rv);
  16564     rv = _bcm_field_qual_partial_data_get(p_mask, offset,
  16565                                           qi.width, mask);
  16566     BCM_IF_ERROR_RETURN(rv);
  16567 
  16568 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT)
  16569     /*
  16570      * 1. Check if the part goes into the IPBM TCAM.
  16571      * 2. In slice Pairing mode, TCP control flag bits[5:0] are split between
  16572      *    IFP_PAIRING_IPBM_F0:TCP_FN_5_1[5:1] and IFP_PAIRING_F1:TCP_FN_0[0]
  16573      *    This special overlay case is handled here (1 == qual_part)...
  16574      */
  16575     if ((((!SOC_IS_TRIDENT2X(unit) && !SOC_IS_TITAN2PLUS(unit)))
  16576             && SOC_IS_TD_TT(unit) && q_offset->secondary &&
  16577         ((qual_part == 0 && 1 != q_offset->width[0] && 5 != q_offset->width[1]) ||
  16578         (1 == qual_part && 1 == q_offset->width[0] && 5 == q_offset->width[1])))
  16579         || ((SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || SOC_IS_KATANAX(unit))
  16580              && q_offset->secondary)) {
  16581         ipbm_overlay = 1;
  16582     }
  16583 #endif
  16584 
  16585     /* Program qualifier into tcam.. */
  16586     rv = _field_qual_value_set(unit, &qi, f_ent, data, mask,
  16587                                ipbm_overlay, key_match_tcam);
  16588     return (rv);
  16589 }
  16590 
  16591 /*
  16592  * Function:
  16593  *     _field_entry_qualifier_key_get
  16594  *
  16595  * Purpose:
  16596  *     Get qualifier match value and mask.
  16597  *
  16598  * Parameters:
  16599  *     unit      - BCM device number
  16600  *     entry     - Entry id.
  16601  *     qual_id   - qualifier id.
  16602  *     q_data    - Qualifier data array.
  16603  *     q_mask    - Qualifier mask array.
  16604  * Returns:
  16605  *     Nothing.
  16606  */
  16607 int
  16608 _field_entry_qualifier_key_get(int unit,
  16609                                bcm_field_entry_t entry,
  16610                                int qual_id,
  16611                                _bcm_field_qual_data_t q_data,
  16612                                _bcm_field_qual_data_t q_mask)
  16613 {
  16614     uint8                     entry_part;  /* Tcam part number.             */
  16615     uint8                     entry_type;  /* Index to tcam entries of
  16616                                               multiple types                */
  16617     _bcm_field_qual_offset_t  *q_offset;   /* Qualifier offset in the tcam. */
  16618     int                       qual_idx;    /* Tcam part qualifiers iterator.*/
  16619     _field_entry_t            *f_ent;      /* Field entry structure.        */
  16620     _bcm_field_group_qual_t   *q_arr;      /* Tcam part Qualifiers array.   */
  16621     _field_group_t            *fg;         /* Field group structure.        */
  16622     int                       rv;          /* Operation return status.      */
  16623     int                       free_tcam;   /* Free tcam key flag.           */
  16624     uint32                    width;       /* Offset width                  */
  16625 
  16626     _FP_QUAL_DATA_CLEAR(q_data);
  16627     _FP_QUAL_DATA_CLEAR(q_mask);
  16628 
  16629     q_offset = NULL;
  16630     free_tcam = FALSE;
  16631 
  16632 #if defined(BCM_TOMAHAWK_SUPPORT)
  16633     if (soc_feature(unit, soc_feature_field_preselector_support) &&
  16634         (_BCM_FIELD_IS_PRESEL_ENTRY(entry) == TRUE)) {
  16635        return _bcm_field_presel_qualifier_get(unit, entry, qual_id,
  16636                                               q_data, q_mask);
  16637     }
  16638 #endif /* BCM_TOMAHAWK_SUPPORT */
  16639 
  16640 
  16641     /* Get entry part that contains requested qualifier. */
  16642 #if defined(BCM_TRIDENT2_SUPPORT)
  16643     /* Search the entry by eid. */
  16644     rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent);
  16645     BCM_IF_ERROR_RETURN(rv);
  16646     if (SOC_IS_TD2_TT2(unit) &&
  16647         (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id)) {
  16648         f_ent = NULL;
  16649         rv = _bcm_field_efp_entry_qual_get(unit, entry, qual_id, &f_ent);
  16650     } else
  16651 #endif
  16652     {
  16653         f_ent = NULL;
  16654         rv = _bcm_field_entry_qual_get(unit, entry, qual_id, &f_ent);
  16655     }
  16656     BCM_IF_ERROR_RETURN(rv);
  16657 
  16658     fg = f_ent->group;
  16659 
  16660 #if defined(BCM_TOMAHAWK_SUPPORT)
  16661     if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  16662        if ((fg->stage_id == _BCM_FIELD_STAGE_INGRESS) ||
  16663            (fg->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) ||
  16664            (fg->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER)) {
  16665           return _bcm_field_th_entry_qualifier_key_get(unit, entry, qual_id,
  16666                                                        q_data, q_mask);
  16667        }
  16668        if (fg->stage_id == _BCM_FIELD_STAGE_CLASS) {
  16669           return _bcm_field_th_class_entry_qualifier_key_get(unit, entry,
  16670                                                              qual_id,
  16671                                                              q_data, q_mask);
  16672        }
  16673     }
  16674 #endif /* BCM_TOMAHAWK_SUPPORT */
  16675 
  16676     /* Get entry tcam part number. */
  16677     rv = _bcm_field_entry_flags_to_tcam_part (unit, f_ent->flags,
  16678                                               fg, &entry_part);
  16679     BCM_IF_ERROR_RETURN(rv);
  16680 
  16681     /*  Check if tcam data has to be freed at the end. */
  16682     if (NULL == f_ent->tcam.key) {
  16683         free_tcam = TRUE;
  16684     }
  16685 
  16686     entry_type = _FP_ENTRY_TYPE_DEFAULT;
  16687 
  16688 #if defined(BCM_TRIDENT2_SUPPORT)
  16689     if (SOC_IS_TD2_TT2(unit) &&
  16690         (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id)) {
  16691 
  16692         if (f_ent->efp_key_match_type) {
  16693             entry_type = _FP_ENTRY_TYPE_1;
  16694         } else {
  16695             entry_type = _FP_ENTRY_TYPE_0;
  16696         }
  16697     }
  16698 #endif
  16699     /* Get entry part qualifiers array. */
  16700     q_arr = &(fg->qual_arr[entry_type][entry_part]);
  16701 
  16702     /* Search array by qualifier id to extract qualifier offsets in the tcam. */
  16703     for (qual_idx = 0; qual_idx < q_arr->size; qual_idx++) {
  16704         if ((uint16)qual_id == q_arr->qid_arr[qual_idx]) {
  16705             q_offset = q_arr->offset_arr + qual_idx;
  16706             break;
  16707         }
  16708     }
  16709     if (NULL == q_offset) {
  16710         return (BCM_E_INTERNAL);
  16711     }
  16712 
  16713     /* Read tcam data/mask. */
  16714     rv = _bcm_field_qual_tcam_key_mask_get(unit, f_ent);
  16715     BCM_IF_ERROR_RETURN(rv);
  16716 
  16717     /* There is no value associated with zero width qualifiers (Stage, Ip4 etc)
  16718      */
  16719 /* MERGE-CHANGE */
  16720     _BCM_FIELD_QUAL_MULTI_OFFSET_WIDTH(q_offset, width);
  16721     if (width > 0) {
  16722         /* Read qualifier match value and mask. */
  16723         rv = _bcm_field_qual_value_get(unit, q_offset, f_ent, q_data, q_mask);
  16724     }
  16725 
  16726     if (free_tcam) {
  16727         if (NULL != f_ent->tcam.key) {
  16728             sal_free(f_ent->tcam.key);
  16729             sal_free(f_ent->tcam.mask);
  16730         }
  16731         if (f_ent->flags & _FP_ENTRY_USES_IPBM_OVERLAY) {
  16732             if (NULL != f_ent->extra_tcam.key) {
  16733                 sal_free(f_ent->extra_tcam.key);
  16734                 sal_free(f_ent->extra_tcam.mask);
  16735             }
  16736         }
  16737         f_ent->tcam.key = f_ent->tcam.mask =
  16738             f_ent->extra_tcam.key = f_ent->extra_tcam.mask = NULL;
  16739 
  16740 #if defined(BCM_TRIDENT2_SUPPORT)
  16741         if (SOC_IS_TD2_TT2(unit) &&
  16742             (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id)) {
  16743 
  16744             if (NULL != f_ent->key_match_tcam.key) {
  16745                 sal_free(f_ent->key_match_tcam.key);
  16746                 sal_free(f_ent->key_match_tcam.mask);
  16747             }
  16748             f_ent->key_match_tcam.key = f_ent->key_match_tcam.mask = NULL;
  16749         }
  16750 #endif
  16751         free_tcam = FALSE;
  16752     }
  16753     return (rv);
  16754 }
  16755 /*
  16756  * Function:
  16757  *     _bcm_field_entry_qualifier_uint8_get
  16758  *
  16759  * Purpose:
  16760  *     Get qualifier match value and mask.
  16761  *
  16762  * Parameters:
  16763  *     unit      - BCM device number
  16764  *     entry     - Entry id.
  16765  *     qual_id   - qualifier id.
  16766  *     data      - Qualifier data.
  16767  *     mask      - Qualifier mask.
  16768  * Returns:
  16769  *     Nothing.
  16770  */
  16771 int
  16772 _bcm_field_entry_qualifier_uint8_get(int unit, bcm_field_entry_t entry,
  16773                                  int qual_id, uint8 *data,
  16774                                  uint8 *mask)
  16775 {
  16776     _bcm_field_qual_data_t     q_data;/* Qualifier match data.     */
  16777     _bcm_field_qual_data_t     q_mask;/* Qualifier match mask.     */
  16778     int                        rv;    /* Operation return status.  */
  16779 #if defined(BCM_TRIUMPH3_SUPPORT)
  16780     esm_l3_protocol_fn_entry_t  l3_proto_fn_entry;
  16781     uint32                      ip_proto, index;
  16782     int                         idx_end;
  16783     _bcm_field_qual_offset_t    *q_offset;
  16784     _field_entry_t              *f_ent;
  16785 #endif
  16786    /* Input parameters check. */
  16787     if ((NULL == data) || (NULL == mask)) {
  16788         return (BCM_E_PARAM);
  16789     }
  16790 
  16791 
  16792     FP_LOCK(unit);
  16793 
  16794     rv = _field_entry_qualifier_key_get(unit, entry, qual_id, q_data, q_mask);
  16795 
  16796 #if defined(BCM_TRIUMPH3_SUPPORT)
  16797     if (SOC_IS_TRIUMPH3(unit) &&
  16798             (qual_id == bcmFieldQualifyIpProtocol) &&
  16799             BCM_SUCCESS(rv)) {
  16800 
  16801         rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent);
  16802 
  16803         if (BCM_FAILURE(rv)) {
  16804             FP_UNLOCK(unit);
  16805             return rv;
  16806         }
  16807 
  16808         if (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXTERNAL) {
  16809 
  16810             rv = _bcm_field_entry_qual_get(unit, entry, qual_id, &f_ent);
  16811             if (BCM_FAILURE(rv)) {
  16812                 FP_UNLOCK(unit);
  16813                 return rv;
  16814             }
  16815 
  16816             rv = _field_qual_offset_get(unit, f_ent, qual_id, &q_offset);
  16817             if (BCM_FAILURE(rv)) {
  16818                 FP_UNLOCK(unit);
  16819                 return rv;
  16820             }
  16821 
  16822             if (((q_offset->offset[0] == 132) || (q_offset->offset[0] == 4)) &&
  16823                     (q_offset->width[0] == 4)) {
  16824                 /* For EXT_IP4 EXT_L2IP4 and EXT_IP6S ACL, L3_PROTOCOL_FN value from
  16825                    ESM_L3_PROTOCOL_FN table is treated as data to send it to
  16826                    external TCAM as key
  16827                  */
  16828                 idx_end = soc_mem_index_max(unit, ESM_L3_PROTOCOL_FNm);
  16829                 for (index = 0; index < idx_end + 1; index++) {
  16830                     rv = soc_mem_read(unit, ESM_L3_PROTOCOL_FNm,
  16831                             MEM_BLOCK_ANY, index, &l3_proto_fn_entry);
  16832                     if (BCM_FAILURE(rv)) {
  16833                         FP_UNLOCK(unit);
  16834                         return rv;
  16835                     }
  16836 
  16837                     ip_proto = soc_mem_field32_get(unit, ESM_L3_PROTOCOL_FNm, &l3_proto_fn_entry,
  16838                             L3_PROTOCOL_FNf);
  16839                     if (ip_proto == (q_data[0] & 0xf)) {
  16840                         q_data[0] = index;
  16841                         q_mask[0] = 0xff;
  16842                         break;
  16843                     }
  16844                 }
  16845             }
  16846         }
  16847     }
  16848 #endif
  16849 
  16850     FP_UNLOCK(unit);
  16851 
  16852     if (BCM_SUCCESS(rv)) {
  16853         *data = (uint8)(q_data[0] & 0xff);
  16854         *mask = (uint8)(q_mask[0] & 0xff);
  16855     }
  16856     return (rv);
  16857 }
  16858 
  16859 /*
  16860  * Function:
  16861  *     _bcm_field_entry_qualifier_uint16_get
  16862  *
  16863  * Purpose:
  16864  *     Get qualifier match value and mask.
  16865  *
  16866  * Parameters:
  16867  *     unit      - BCM device number
  16868  *     entry     - Entry id.
  16869  *     qual_id   - qualifier id.
  16870  *     data      - Qualifier data.
  16871  *     mask      - Qualifier mask.
  16872  * Returns:
  16873  *     Nothing.
  16874  */
  16875 int
  16876 _bcm_field_entry_qualifier_uint16_get(int unit, bcm_field_entry_t entry,
  16877                                   int qual_id, uint16 *data,
  16878                                   uint16 *mask)
  16879 {
  16880     _bcm_field_qual_data_t     q_data;/* Qualifier match data.     */
  16881     _bcm_field_qual_data_t     q_mask;/* Qualifier match mask.     */
  16882     int                        rv;    /* Operation return status.  */
  16883    /* Input parameters check. */
  16884     if ((NULL == data) || (NULL == mask)) {
  16885         return (BCM_E_PARAM);
  16886     }
  16887 
  16888 
  16889     FP_LOCK(unit);
  16890 
  16891     rv = _field_entry_qualifier_key_get(unit, entry, qual_id, q_data, q_mask);
  16892 
  16893     FP_UNLOCK(unit);
  16894 
  16895     if (BCM_SUCCESS(rv)) {
  16896         *data = (uint16)(q_data[0] & 0xffff);
  16897         *mask = (uint16)(q_mask[0] & 0xffff);
  16898     }
  16899     return (rv);
  16900 }
  16901 
  16902 /*
  16903  * Function:
  16904  *     _bcm_field_entry_qualifier_uint32_get
  16905  *
  16906  * Purpose:
  16907  *     Get qualifier match value and mask.
  16908  *
  16909  * Parameters:
  16910  *     unit      - BCM device number
  16911  *     entry     - Entry id.
  16912  *     qual_id   - qualifier id.
  16913  *     data      - Qualifier data.
  16914  *     mask      - Qualifier mask.
  16915  * Returns:
  16916  *     Nothing.
  16917  */
  16918 int
  16919 _bcm_field_entry_qualifier_uint32_get(int unit, bcm_field_entry_t entry,
  16920                                   int qual_id, uint32 *data,
  16921                                   uint32 *mask)
  16922 {
  16923     _bcm_field_qual_data_t     q_data;/* Qualifier match data.     */
  16924     _bcm_field_qual_data_t     q_mask;/* Qualifier match mask.     */
  16925     int                        rv;    /* Operation return status.  */
  16926 
  16927    /* Input parameters check. */
  16928     if ((NULL == data) || (NULL == mask)) {
  16929         return (BCM_E_PARAM);
  16930     }
  16931 
  16932 
  16933     FP_LOCK(unit);
  16934 
  16935     rv = _field_entry_qualifier_key_get(unit, entry, qual_id, q_data, q_mask);
  16936 
  16937     FP_UNLOCK(unit);
  16938 
  16939     if (BCM_SUCCESS(rv)) {
  16940         *data = q_data[0];
  16941         *mask = q_mask[0];
  16942     }
  16943     return (rv);
  16944 }
  16945 
  16946 /*
  16947  * Function:
  16948  *     _bcm_field_entry_qualifier_uint64_get
  16949  *
  16950  * Purpose:
  16951  *     Get qualifier match value and mask.
  16952  *
  16953  * Parameters:
  16954  *     unit      - BCM device number
  16955  *     entry     - Entry id.
  16956  *     qual_id   - qualifier id.
  16957  *     data      - Qualifier data.
  16958  *     mask      - Qualifier mask.
  16959  * Returns:
  16960  *     BCM_E_XXX.
  16961  */
  16962 int
  16963 _bcm_field_entry_qualifier_uint64_get(int unit, bcm_field_entry_t entry,
  16964                                       int qual_id, uint64 *data,
  16965                                       uint64 *mask)
  16966 {
  16967     _bcm_field_qual_data_t     q_data;/* Qualifier match data.     */
  16968     _bcm_field_qual_data_t     q_mask;/* Qualifier match mask.     */
  16969     int                        rv;    /* Operation return status.  */
  16970 
  16971     /* Input parameters check. */
  16972     if ((NULL == data) || (NULL == mask)) {
  16973         return (BCM_E_PARAM);
  16974     }
  16975 
  16976 
  16977     FP_LOCK(unit);
  16978 
  16979     rv = _field_entry_qualifier_key_get(unit, entry, qual_id, q_data, q_mask);
  16980 
  16981     FP_UNLOCK(unit);
  16982 
  16983     if (BCM_SUCCESS(rv)) {
  16984         COMPILER_64_SET(*data, q_data[1], q_data[0]);
  16985         COMPILER_64_SET(*mask, q_mask[1], q_mask[0]);
  16986     }
  16987     return (rv);
  16988 }
  16989 
  16990 
  16991 /*
  16992  * Function:
  16993  *     _bcm_field_qual_value_set
  16994  *
  16995  * Purpose:
  16996  *     Set a qualifier field from the designated data and mask arrays.
  16997  *
  16998  * Parameters:
  16999  *     unit     - (IN) BCM devices number
  17000  *     q_offset - (IN) Qualifier offset inside tcam.
  17001  *     f_ent    - (IN) Field entry descriptor.
  17002  *     p_data   - (IN) Inserted data.
  17003  *     p_mask   - (IN) Data mask.
  17004  *
  17005  * Returns:
  17006  *     BCM_E_XXX
  17007  */
  17008 int
  17009 _bcm_field_qual_value_set(int unit, _bcm_field_qual_offset_t *q_offset,
  17010                           _field_entry_t *f_ent,
  17011                           uint32 *p_data, uint32 *p_mask)
  17012 {
  17013     int    rv;
  17014     uint8  qual_part;
  17015 
  17016     LOG_DEBUG(BSL_LS_BCM_FP,
  17017               (BSL_META_U(unit,
  17018                           "_bcm_field_qual_value_set\n")));
  17019 
  17020     /* Input parameters check. */
  17021     if ((NULL == q_offset) || (NULL == f_ent) ||
  17022         (NULL == p_data) || (NULL == p_mask)) {
  17023         return (BCM_E_PARAM);
  17024     }
  17025 
  17026     /* Primary offset handling. */
  17027     for (qual_part = 0; qual_part < q_offset->num_offsets; qual_part++) {
  17028         if (q_offset->width[qual_part] > 0)
  17029         {
  17030            rv = _field_qual_part_value_set(unit, q_offset, qual_part, f_ent,
  17031                                               p_data, p_mask, 0);
  17032            BCM_IF_ERROR_RETURN(rv);
  17033         }
  17034     }
  17035 
  17036     return (BCM_E_NONE);
  17037 }
  17038 
  17039 /*
  17040  * Function:
  17041  *     _bcm_field_qual_value_set_by_entry_type
  17042  *
  17043  * Purpose:
  17044  *     Set a qualifier field from the designated data and mask arrays in the
  17045  *     tcam of the given index.
  17046  *
  17047  * Parameters:
  17048  *     unit       - (IN) BCM devices number
  17049  *     q_offset   - (IN) Qualifier offset inside tcam.
  17050  *     f_ent      - (IN) Field entry descriptor.
  17051  *     p_data     - (IN) Inserted data.
  17052  *     p_mask     - (IN) Data mask.
  17053  *     entry_type - (IN) Index of the tcam entry
  17054  *
  17055  * Returns:
  17056  *     BCM_E_XXX
  17057  */
  17058 
  17059 int
  17060 _bcm_field_qual_value_set_by_entry_type(int unit,
  17061                                         _bcm_field_qual_offset_t *q_offset,
  17062                                         _field_entry_t *f_ent,
  17063                                         uint32 *p_data,
  17064                                         uint32 *p_mask,
  17065                                         uint8 entry_type)
  17066 {
  17067     uint8 qual_part;
  17068 
  17069     LOG_DEBUG(BSL_LS_BCM_FP,
  17070               (BSL_META_U(unit,
  17071                           "_bcm_field_qual_value_set_by_index\n")));
  17072 
  17073     /* Input parameters check. */
  17074     if ((NULL == q_offset) || (NULL == f_ent) ||
  17075         (NULL == p_data) || (NULL == p_mask)) {
  17076         return (BCM_E_PARAM);
  17077     }
  17078 
  17079     /* Primary offset handling. */
  17080     for (qual_part = 0; qual_part < q_offset->num_offsets; qual_part++) {
  17081         if (q_offset->width[qual_part] > 0)
  17082         {
  17083            BCM_IF_ERROR_RETURN
  17084                 (_field_qual_part_value_set(unit, q_offset, qual_part, f_ent,
  17085                                             p_data, p_mask, entry_type));
  17086         }
  17087     }
  17088 
  17089     return (BCM_E_NONE);
  17090 }
  17091 
  17092 /*
  17093  * Function:
  17094  *     _bcm_field_group_stage_get
  17095  *
  17096  * Purpose:
  17097  *     Extract group pipeline stage from qualifiers set.
  17098  *
  17099  * Parameters:
  17100  *     unit    - (IN)BCM device number.
  17101  *     qset_p  - (IN)Group qualifiers set.
  17102  *     stage   - (OUT)Pipeline stage id.
  17103  *
  17104  * Returns:
  17105  *     BCM_E_XXX
  17106  */
  17107 int
  17108 _bcm_field_group_stage_get(int unit, bcm_field_qset_t *qset_p,
  17109                        _field_stage_id_t *stage)
  17110 {
  17111     int stage_count = 0;   /* Check that only 1 stage specified in qset */
  17112 
  17113     /* Input parameters check. */
  17114     if ((NULL == qset_p) || (NULL == stage)) {
  17115         return (BCM_E_PARAM);
  17116     }
  17117 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  17118     /* Set stage based on qualifiers set. */
  17119     if (soc_feature(unit, soc_feature_field_multi_stage)) {
  17120         if(BCM_FIELD_QSET_TEST(*qset_p, bcmFieldQualifyStageIngress)) {
  17121             *stage  = _BCM_FIELD_STAGE_INGRESS;
  17122             stage_count++;
  17123         }
  17124         if(BCM_FIELD_QSET_TEST(*qset_p, bcmFieldQualifyStageEgress)) {
  17125             *stage  = _BCM_FIELD_STAGE_EGRESS;
  17126             stage_count++;
  17127         }
  17128 
  17129         if(BCM_FIELD_QSET_TEST(*qset_p, bcmFieldQualifyStageLookup)) {
  17130             *stage  = _BCM_FIELD_STAGE_LOOKUP;
  17131             stage_count++;
  17132         }
  17133     }
  17134 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  17135 
  17136     if (BCM_FIELD_QSET_TEST(*qset_p, bcmFieldQualifyStageExternal)) {
  17137         *stage  = _BCM_FIELD_STAGE_EXTERNAL;
  17138         stage_count++;
  17139     }
  17140 
  17141 #if defined(BCM_TOMAHAWK_SUPPORT)
  17142     if (BCM_FIELD_QSET_TEST(*qset_p, bcmFieldQualifyStageClass)) {
  17143         *stage  = _BCM_FIELD_STAGE_CLASS;
  17144         stage_count++;
  17145     }
  17146     if (BCM_FIELD_QSET_TEST(*qset_p, bcmFieldQualifyStageClassExactMatch)) {
  17147         *stage  = _BCM_FIELD_STAGE_CLASS;
  17148         stage_count++;
  17149     }
  17150     if (BCM_FIELD_QSET_TEST(*qset_p, bcmFieldQualifyStageIngressExactMatch)) {
  17151         *stage  = _BCM_FIELD_STAGE_EXACTMATCH;
  17152         stage_count++;
  17153     }
  17154 #endif /* BCM_TOMAHAWK_SUPPORT */
  17155 
  17156 #if defined(BCM_FLOWTRACKER_SUPPORT)
  17157     if (BCM_FIELD_QSET_TEST(*qset_p, bcmFieldQualifyStageIngressFlowtracker)) {
  17158         *stage  = _BCM_FIELD_STAGE_FLOWTRACKER;
  17159         stage_count++;
  17160     }
  17161 #endif
  17162 
  17163     if (stage_count == 0) {
  17164         /* Default to ingress. */
  17165         *stage = _BCM_FIELD_STAGE_INGRESS;
  17166         stage_count++;
  17167     }
  17168 
  17169     if (stage_count > 1) {
  17170         LOG_ERROR(BSL_LS_BCM_FP,
  17171                   (BSL_META_U(unit,
  17172                               "FP(unit %d) Error: More than one pipeline stage was specified.\n"),
  17173                    unit));
  17174         return (BCM_E_PARAM);
  17175     }
  17176 
  17177     return (BCM_E_NONE);
  17178 }
  17179 
  17180 /*
  17181  * Function:
  17182  *     _bcm_field_group_stage_validate
  17183  *
  17184  * Purpose:
  17185  *     Validate group pipeline stage.
  17186  *
  17187  * Parameters:
  17188  *     unit    - (IN)BCM device number.
  17189  *     stage   - (IN)Pipeline stage id.
  17190  *
  17191  * Returns:
  17192  *     BCM_E_XXX
  17193  */
  17194 int
  17195 _bcm_field_group_stage_validate(int unit, _field_stage_id_t stage)
  17196 {
  17197    int rv = BCM_E_NONE;
  17198     if (soc_feature(unit, soc_feature_no_ifp) &&
  17199         _BCM_FIELD_STAGE_INGRESS == stage) {
  17200         rv = BCM_E_UNAVAIL;
  17201     }
  17202     if (soc_feature(unit, soc_feature_no_ifp) &&
  17203         _BCM_FIELD_STAGE_CLASS == stage) {
  17204         rv = BCM_E_UNAVAIL;
  17205     }
  17206     if (soc_feature(unit, soc_feature_no_vfp) &&
  17207         _BCM_FIELD_STAGE_LOOKUP == stage) {
  17208         rv = BCM_E_UNAVAIL;
  17209     }
  17210     if (soc_feature(unit, soc_feature_no_efp) &&
  17211         _BCM_FIELD_STAGE_EGRESS == stage) {
  17212         rv = BCM_E_UNAVAIL;
  17213     }
  17214     if (BCM_FAILURE(rv)) {
  17215         LOG_DEBUG(BSL_LS_BCM_FP,
  17216                   (BSL_META_U(unit,
  17217                               "FP(unit %d) Verb: stage %d is not supported.\n"),
  17218                    unit, stage));
  17219     }
  17220     return rv;
  17221 }
  17222 
  17223 /*
  17224  * Function:
  17225  *     _bcm_field_data_qualifier_free
  17226  *
  17227  * Purpose:
  17228  *     Free data qualifier descriptor structure.
  17229  *
  17230  * Parameters:
  17231  *     unit       - (IN) BCM device number.
  17232  *     qual       - (OUT)Qualifier strusture.
  17233  *
  17234  * Returns:
  17235  *     BCM_E_XXX
  17236  */
  17237 int
  17238 _bcm_field_data_qualifier_free(int unit, _field_data_qualifier_t *qual)
  17239 {
  17240     /* Input parameters check. */
  17241     if (NULL == qual) {
  17242         return (BCM_E_PARAM);
  17243     }
  17244 
  17245     /* Free data offset structure. */
  17246     if (NULL != qual->spec) {
  17247         sal_free(qual->spec);
  17248     }
  17249 
  17250     /* Free data qualifier structure. */
  17251     sal_free(qual);
  17252 
  17253     return (BCM_E_NONE);
  17254 }
  17255 
  17256 
  17257 /*
  17258  * Function:
  17259  *     _field_data_qualifier_bmap_alloc
  17260  *
  17261  * Purpose:
  17262  *     Allocate hw resources for data qualifier installation
  17263  * Parameters:
  17264  * Parameters:
  17265  *     unit       - (IN) BCM device number.
  17266  *     stage_fc   - (IN) Stage field control.
  17267  *     f_dq       - (IN) Field data qualifier descriptor.
  17268  *     idx_low    - (IN) Lower boundary.
  17269  *     idx_hi     - (IN) Upper boundary.
  17270  *
  17271  * Returns:
  17272  *     BCM_E_XXX
  17273  */
  17274 
  17275 STATIC int
  17276 _field_data_qualifier_bmap_alloc(int unit,
  17277                                _field_stage_t *stage_fc,
  17278                                _field_data_qualifier_t *f_dq,
  17279                                uint8 idx_low, uint8 idx_hi)
  17280 {
  17281     int idx;                 /* Data qualifier word iterator. */
  17282     int elem_count;          /* Number of elements allocated.    */
  17283     int temp_elem_count = 0; /* Number of elements allocated.    */
  17284     uint32   *usage_bmap;    /* Offset usage bitmap.          */
  17285 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_KATANA_SUPPORT) || defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT)
  17286                             /* Valid HW offsets for FPF1.9 and FPF3.9 */
  17287     SHR_BITDCL udf1_hw_offsets;
  17288 #endif /* !BCM_TRIDENT_SUPPORT or BCM_KATANA_SUPPORT or BCM_ENDURO_SUPPORT */
  17289 
  17290     /* Input parameters check. */
  17291     if ((NULL == f_dq) || (NULL == stage_fc) ||
  17292         (idx_low > 31) || (idx_hi > 31)) {
  17293         return (BCM_E_PARAM);
  17294     }
  17295 
  17296 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_KATANA_SUPPORT) || defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT)
  17297     memset(&udf1_hw_offsets, 0x0, sizeof(udf1_hw_offsets));
  17298     if (SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit)) {
  17299          /* set UDF1.1 for FPF3.9 - {0 0 1 1 0 0 0 0} */
  17300          SHR_BITSET(&udf1_hw_offsets, 0x2);
  17301          SHR_BITSET(&udf1_hw_offsets, 0x3);
  17302          /* set UDF1.3 for FPF1.9 - {0 0 0 0 0 0 1 1} */
  17303          SHR_BITSET(&udf1_hw_offsets, 0x6);
  17304          SHR_BITSET(&udf1_hw_offsets, 0x7);
  17305     } else if (SOC_IS_ENDURO(unit) || SOC_IS_HURRICANEX(unit) ||
  17306          SOC_IS_GREYHOUND(unit) || SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit)
  17307          || SOC_IS_VALKYRIE2(unit) || SOC_IS_GREYHOUND2(unit)) {
  17308          /* set UDF1.1 for FPF3.9  - {0 1 0 0} 1st bit Position */
  17309          SHR_BITSET(&udf1_hw_offsets, 0x1);
  17310          /* set UDF1.3 for FPF1.9  - {0 0 0 1} 3rd bit Position */
  17311          SHR_BITSET(&udf1_hw_offsets, 0x3);
  17312     }
  17313 #endif /* !BCM_TRIDENT_SUPPORT or BCM_KATANA_SUPPORT or BCM_ENDURO_SUPPORT */
  17314 
  17315     elem_count = 0;
  17316     usage_bmap = &stage_fc->data_ctrl->usage_bmap;
  17317     for (idx = idx_low; idx <= idx_hi; idx++) {
  17318         if (0 == ((*usage_bmap) & (1 << idx))) {
  17319             elem_count++;
  17320         }
  17321     }
  17322 
  17323     if (elem_count >= f_dq->elem_count) {
  17324 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_KATANA_SUPPORT) || defined(BCM_ENDURO_SUPPORT)  || defined(BCM_TRIUMPH2_SUPPORT)
  17325         if ((SOC_IS_TD_TT(unit)
  17326              || SOC_IS_KATANAX(unit)
  17327              || SOC_IS_TRIUMPH3(unit)
  17328              || SOC_IS_ENDURO(unit)
  17329              || SOC_IS_HURRICANEX(unit)
  17330              || SOC_IS_GREYHOUND(unit)
  17331              || SOC_IS_TRIUMPH2(unit)
  17332              || SOC_IS_APOLLO(unit)
  17333              || SOC_IS_VALKYRIE2(unit)
  17334              || SOC_IS_GREYHOUND2(unit))
  17335              && !(f_dq->flags & BCM_FIELD_DATA_QUALIFIER_STAGE_LOOKUP)) {
  17336             /* Check if index is in UDF1 range (0 - 7) */
  17337             if (((idx_low == 0)
  17338                 && (idx_hi <= (stage_fc->data_ctrl->num_elems - 1)))
  17339                 && (f_dq->elem_count > 0 && f_dq->elem_count <= 4)) {
  17340 
  17341                 /* Get number of requested elements. */
  17342                 elem_count = f_dq->elem_count;
  17343 
  17344                 /* Check if requested count of elements are available */
  17345                 for (idx = idx_low; ((idx <= idx_hi) && elem_count); idx++) {
  17346                     /* We check the upper limit of idx_hi and idx_low
  17347                        in the beginning of the function */
  17348                     /* coverity[ptr_arith] */
  17349                     if (SHR_BITGET(&udf1_hw_offsets, idx) == 0) {
  17350                         continue;
  17351                     }
  17352 
  17353                     if (0 == ((*usage_bmap) & (1 << idx))) {
  17354                         elem_count--;
  17355                     }
  17356                 }
  17357 
  17358                 /*
  17359                  * If elem_count is zero, required no. of elements are
  17360                  * available.
  17361                  */
  17362                 if (0 == elem_count) {
  17363                     elem_count = f_dq->elem_count;
  17364                     /* Reserve the indices */
  17365                     for (idx = idx_hi; ((idx >= idx_low) && elem_count); idx--) {
  17366                         /* We check the upper limit of idx_hi and idx_low
  17367                            in the beginning of the function */
  17368                         /* coverity[ptr_arith] */
  17369                         if (SHR_BITGET(&udf1_hw_offsets, idx) == 0) {
  17370                             continue;
  17371                         }
  17372 
  17373                         if (0 == ((*usage_bmap) & (1 << idx))) {
  17374                             f_dq->hw_bmap |= (1 << idx);
  17375                             (*usage_bmap) |= (1 << idx);
  17376                             elem_count--;
  17377                         }
  17378                     }
  17379                     return (BCM_E_NONE);
  17380                 }
  17381             } else if((idx_low == 0)
  17382                     && (idx_hi == ((stage_fc->data_ctrl->num_elems * 2) - 1))) {
  17383                 /* When both UDF1 & UDF 2 are required
  17384                  * Try to fill from UDF2 followed by
  17385                  * UDF1 specical chunks(0,1,4,5) for more flexibilty and
  17386                  * then from the remaining UDF1 chunks(2,3,6,7) */
  17387                 temp_elem_count = f_dq->elem_count;
  17388                 for (idx = stage_fc->data_ctrl->num_elems;
  17389                         ((idx <= idx_hi) && temp_elem_count); idx++) {
  17390                     if (0 == ((*usage_bmap) & (1 << idx))) {
  17391                         f_dq->hw_bmap |= (1 << idx);
  17392                         (*usage_bmap) |= (1 << idx);
  17393                         temp_elem_count--;
  17394                     }
  17395                 }
  17396                 for (idx = stage_fc->data_ctrl->num_elems - 1 ;
  17397                         ((idx >= idx_low) && temp_elem_count); idx--) {
  17398                     /* We check the upper limit of idx_hi and idx_low
  17399                        in the beginning of the function */
  17400                     /* coverity[ptr_arith] */
  17401                     if (SHR_BITGET(&udf1_hw_offsets, idx) == 0) {
  17402                         continue;
  17403                     }
  17404 
  17405                     if (0 == ((*usage_bmap) & (1 << idx))) {
  17406                         f_dq->hw_bmap |= (1 << idx);
  17407                         (*usage_bmap) |= (1 << idx);
  17408                         temp_elem_count--;
  17409                     }
  17410                 }
  17411                 temp_elem_count = f_dq->elem_count - temp_elem_count;
  17412             }
  17413         }
  17414 #endif /* !BCM_TRIDENT_SUPPORT or BCM_KATANA_SUPPORT or BCM_ENDURO_SUPPORT */
  17415 
  17416         elem_count = f_dq->elem_count - temp_elem_count;
  17417         for (idx = idx_low; ((idx <= idx_hi) && elem_count); idx++) {
  17418             if (0 == ((*usage_bmap) & (1 << idx))) {
  17419                 f_dq->hw_bmap |= (1 << idx);
  17420                 (*usage_bmap) |= (1 << idx);
  17421                 elem_count--;
  17422             }
  17423         }
  17424         return (BCM_E_NONE);
  17425     }
  17426     return (BCM_E_RESOURCE);
  17427 }
  17428 
  17429 /*
  17430  * Function:
  17431  *     _field_data_qualifier_hw_alloc
  17432  *
  17433  * Purpose:
  17434  *     Allocate hw resources for data qualifier installation
  17435  *
  17436  * Parameters:
  17437  *     unit       - (IN) BCM device number.
  17438  *     stage_fc   - (IN) Stage field control.
  17439  *     f_dq       - (IN) Field data qualifier descriptor.
  17440  * Returns:
  17441  *     BCM_E_XXX
  17442  */
  17443 
  17444 STATIC int
  17445 _field_data_qualifier_hw_alloc(int unit,
  17446                                _field_stage_t *stage_fc,
  17447                                _field_data_qualifier_t *f_dq)
  17448 {
  17449     int rv;               /* Operation return status.        */
  17450 
  17451     /* Input parameters check. */
  17452     if ((NULL == f_dq) || (NULL == stage_fc)) {
  17453         return (BCM_E_PARAM);
  17454     }
  17455 
  17456 #if defined(BCM_TOMAHAWK_SUPPORT)
  17457     if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  17458         return _bcm_field_th_data_qualifier_hw_alloc(unit, stage_fc, f_dq);
  17459     }
  17460 #endif
  17461 #if defined(BCM_TRIDENT2_SUPPORT)
  17462     if (SOC_IS_TD2_TT2(unit) &&
  17463         f_dq->flags & BCM_FIELD_DATA_QUALIFIER_OFFSET_FLEX_HASH) {
  17464         /* flex hash uses UDF2_OFFSET4 to UDF2_OFFSET7 */
  17465         rv = _field_data_qualifier_bmap_alloc
  17466             (unit, stage_fc, f_dq, 12, ((2 * stage_fc->data_ctrl->num_elems) - 1));
  17467         if (BCM_FAILURE(rv)) {
  17468             return (BCM_E_FAIL);
  17469         }
  17470         return BCM_E_NONE;
  17471     }
  17472 #endif
  17473 
  17474     /* First try to allocate with single udf */
  17475 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_KATANA_SUPPORT) || defined(BCM_ENDURO_SUPPORT)
  17476     if ((SOC_IS_TD_TT(unit)
  17477          || SOC_IS_KATANAX(unit)
  17478          || SOC_IS_TRIUMPH3(unit)
  17479          || SOC_IS_ENDURO(unit)
  17480          || SOC_IS_HURRICANEX(unit)
  17481          || SOC_IS_GREYHOUND2(unit))
  17482          && !(f_dq->flags & BCM_FIELD_DATA_QUALIFIER_STAGE_LOOKUP)
  17483          && (f_dq->elem_count > 4)) {
  17484         /* Try UDF 2  followed by UDF 1*/
  17485         rv = _field_data_qualifier_bmap_alloc
  17486             (unit, stage_fc, f_dq, stage_fc->data_ctrl->num_elems,
  17487              stage_fc->data_ctrl->num_elems * 2 - 1);
  17488 
  17489         if (BCM_SUCCESS(rv)) {
  17490             return (BCM_E_NONE);
  17491         }
  17492         rv = _field_data_qualifier_bmap_alloc
  17493             (unit, stage_fc, f_dq, 0, stage_fc->data_ctrl->num_elems - 1);
  17494 
  17495         if (BCM_SUCCESS(rv)) {
  17496             return (BCM_E_NONE);
  17497         }
  17498     } else
  17499 #endif
  17500     {
  17501         rv = _field_data_qualifier_bmap_alloc
  17502             (unit, stage_fc, f_dq, 0, stage_fc->data_ctrl->num_elems - 1);
  17503 
  17504         if (BCM_SUCCESS(rv)) {
  17505             return (BCM_E_NONE);
  17506         }
  17507         rv = _field_data_qualifier_bmap_alloc
  17508             (unit, stage_fc, f_dq, stage_fc->data_ctrl->num_elems,
  17509              stage_fc->data_ctrl->num_elems * 2 - 1);
  17510 
  17511         if (BCM_SUCCESS(rv)) {
  17512             return (BCM_E_NONE);
  17513         }
  17514     }
  17515 
  17516     /* Need 2 udfs to insert the qualifier. */
  17517     rv  = _field_data_qualifier_bmap_alloc
  17518         (unit, stage_fc, f_dq, 0, stage_fc->data_ctrl->num_elems * 2 - 1);
  17519 
  17520     return (rv);
  17521 }
  17522 
  17523 /*
  17524  * Function:
  17525  *     _bcm_field_data_qualifier_alloc
  17526  *
  17527  * Purpose:
  17528  *     Allocate data qualifier descriptor structure.
  17529  *
  17530  * Parameters:
  17531  *     unit       - (IN) BCM device number.
  17532  *     qual       - (OUT)Qualifier strusture.
  17533  *
  17534  * Returns:
  17535  *     BCM_E_XXX
  17536  */
  17537 
  17538 int
  17539 _bcm_field_data_qualifier_alloc(int unit, _field_data_qualifier_t **qual)
  17540 {
  17541     int mem_sz;                  /* Allocated memory size.  */
  17542     _field_data_qualifier_p f_dq;/* Data qualifier pointer. */
  17543 
  17544     /* Input parameters check. */
  17545     if (NULL == qual) {
  17546         return (BCM_E_PARAM);
  17547     }
  17548 
  17549     /* Allocate field data qualifier structure. */
  17550     mem_sz = sizeof(_field_data_qualifier_t);
  17551     f_dq = sal_alloc(mem_sz, "Data qualifier");
  17552     if (NULL == f_dq) {
  17553         return (BCM_E_MEMORY);
  17554     }
  17555     sal_memset(f_dq, 0, mem_sz);
  17556 
  17557     /* Allocate offsets spec required for qualifier. */
  17558     mem_sz = sizeof(bcm_field_udf_spec_t);
  17559     f_dq->spec = sal_alloc(mem_sz, "Data spec");
  17560     if (NULL == f_dq->spec) {
  17561         sal_free(f_dq);
  17562         return (BCM_E_MEMORY);
  17563     }
  17564     sal_memset(f_dq->spec->offset, 0xff, sizeof(f_dq->spec->offset));
  17565     *qual = f_dq;
  17566 
  17567     return (BCM_E_NONE);
  17568 }
  17569 
  17570 
  17571 /*
  17572  * Function:
  17573  *     _field_stage_data_ctrl_init
  17574  *
  17575  * Purpose:
  17576  *     Allocate and initialize data qualifiers control structure.
  17577  *
  17578  * Parameters:
  17579  *     unit     - (IN)     BCM unit
  17580  *     stage_fc - (IN/OUT) Stage to be initialize.
  17581  * Returns:
  17582  *     BCM_E_XXX
  17583  */
  17584 STATIC int
  17585 _field_stage_data_ctrl_init(int unit, _field_stage_t *stage_fc)
  17586 {
  17587     int mem_sz;
  17588     _field_data_control_t *data_ctrl = NULL;
  17589 
  17590     /* Input parameters check. */
  17591     if (NULL == stage_fc) {
  17592         return (BCM_E_PARAM);
  17593     }
  17594 
  17595     /* Allocate data control structure. */
  17596     mem_sz = sizeof(_field_data_control_t);
  17597     _FP_XGS3_ALLOC(data_ctrl, mem_sz,
  17598                    "Data qualification control");
  17599     if (NULL == data_ctrl) {
  17600         return (BCM_E_MEMORY);
  17601     }
  17602 
  17603 #if defined(BCM_TRIUMPH2_SUPPORT)
  17604     if (SOC_MEM_IS_VALID(unit, FP_UDF_TCAMm)) {
  17605         mem_sz = sizeof (_field_data_tcam_entry_t) *
  17606             soc_mem_index_count(unit, FP_UDF_TCAMm);
  17607         _FP_XGS3_ALLOC(data_ctrl->tcam_entry_arr, mem_sz,
  17608                        "Udf tcam entry array.");
  17609         if (NULL == data_ctrl->tcam_entry_arr) {
  17610             sal_free (data_ctrl);
  17611             return (BCM_E_MEMORY);
  17612         }
  17613     }
  17614 #endif /* BCM_TRIUMPH2_SUPPORT */
  17615 
  17616     if (SOC_MEM_FIELD_VALID(unit, FP_UDF_OFFSETm, UDF1_OFFSET4f)) {
  17617         data_ctrl->elem_size = 2;
  17618         data_ctrl->num_elems = 8;
  17619     } else {
  17620         data_ctrl->elem_size = 4;
  17621         data_ctrl->num_elems = 4;
  17622     }
  17623 
  17624     stage_fc->data_ctrl = data_ctrl;
  17625     return (BCM_E_NONE);
  17626 }
  17627 
  17628 /*
  17629  * Function:
  17630  *     _field_stage_external_data_ctrl_init
  17631  *
  17632  * Purpose:
  17633  *     Allocate and initialize external data qualifiers control structure.
  17634  *
  17635  * Parameters:
  17636  *     unit     - (IN)     BCM unit
  17637  *     stage_fc - (IN/OUT) Stage to be initialize.
  17638  * Returns:
  17639  *     BCM_E_XXX
  17640  */
  17641 STATIC int
  17642 _field_stage_external_data_ctrl_init(int unit, _field_control_t *fc)
  17643 {
  17644     _field_stage_t *stage_ingress, *stage_external, *stage_p;
  17645 
  17646     stage_external = stage_ingress = NULL;
  17647     stage_p = fc->stages;
  17648 
  17649     while (stage_p) {
  17650         if (stage_p->stage_id == _BCM_FIELD_STAGE_INGRESS) {
  17651             stage_ingress = stage_p;
  17652         } else if (stage_p->stage_id == _BCM_FIELD_STAGE_EXTERNAL) {
  17653             stage_external = stage_p;
  17654         }
  17655         stage_p = stage_p->next;
  17656     }
  17657 
  17658     if ((stage_ingress == NULL) || (stage_external == NULL)) {
  17659         return (BCM_E_INTERNAL);
  17660     }
  17661 
  17662     stage_external->data_ctrl = stage_ingress->data_ctrl;
  17663     return (BCM_E_NONE);
  17664 }
  17665 
  17666 /*
  17667  * Function:
  17668  *      _field_data_qualifier_destroy
  17669  * Purpose:
  17670  *      Destroy a data/offset based qualifier.
  17671  * Parameters:
  17672  *      unit  - (IN) Bcm device number.
  17673  *      qid   - (IN) Data qualifier id.
  17674  *
  17675  * Returns:
  17676  *      BCM_E_XXX
  17677  */
  17678 int
  17679 _bcm_field_data_qualifier_destroy(int unit, int qid)
  17680 {
  17681     _field_data_qualifier_t *f_dq;/* Internal data qualifier descriptor. */
  17682     _field_data_qualifier_t *f_dq_prev;/* Prev data qualifier descriptor.*/
  17683     _field_stage_t  *stage_fc;    /* Stage field control.                */
  17684     int rv;
  17685 
  17686 #if defined (BCM_TRIUMPH2_SUPPORT)
  17687     if (soc_feature(unit, soc_feature_udf_support) && UDF_CTRL(unit)) {
  17688         if (UDF_CTRL(unit)->udf_used_by_module == UDF_USED_BY_UDF_MODULE) {
  17689             LOG_CLI((BSL_META("Udf resource is used by UDF module. \n")));
  17690             return (BCM_E_RESOURCE);
  17691         }
  17692     }
  17693 #endif
  17694 
  17695     /* Get stage field control structure. */
  17696     rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc);
  17697     BCM_IF_ERROR_RETURN(rv);
  17698 
  17699     f_dq_prev = f_dq = stage_fc->data_ctrl->data_qual;
  17700     while (NULL != f_dq) {
  17701         if (f_dq->qid == qid) {
  17702             /* Free used offset words bitmap. */
  17703             stage_fc->data_ctrl->usage_bmap &= ~f_dq->hw_bmap;
  17704 
  17705             /* Remove qualifier from qualifiers linked list. */
  17706             if (f_dq == f_dq_prev) {
  17707                 stage_fc->data_ctrl->data_qual = f_dq->next;
  17708             } else {
  17709                 f_dq_prev->next = f_dq->next;
  17710             }
  17711             /* Free qualifieer allocated memory. */
  17712             BCM_IF_ERROR_RETURN(_bcm_field_data_qualifier_free(unit, f_dq));
  17713 
  17714 #if defined (BCM_TRIUMPH2_SUPPORT)
  17715             if (soc_feature(unit, soc_feature_udf_support) && UDF_CTRL(unit)) {
  17716                 UDF_LOCK(unit);
  17717                 if (NULL == stage_fc->data_ctrl->data_qual) {
  17718                     UDF_CTRL(unit)->udf_used_by_module = UDF_USED_BY_NONE;
  17719                 }
  17720                 UDF_UNLOCK(unit);
  17721             }
  17722 #endif
  17723             return (BCM_E_NONE);
  17724         }
  17725         f_dq_prev = f_dq;
  17726         f_dq = f_dq->next;
  17727     }
  17728     return (BCM_E_NOT_FOUND);
  17729 }
  17730 
  17731 /*
  17732  * Function:
  17733  *      _field_data_qualifier_destroy_all
  17734  * Purpose:
  17735  *      Destroy all data/offset  based qualifiers.
  17736  * Parameters:
  17737  *      unit           - (IN) bcm device.
  17738  * Returns:
  17739  *      BCM_E_XXX
  17740  */
  17741 int
  17742 _field_data_qualifier_destroy_all(int unit)
  17743 {
  17744     _field_data_qualifier_t *f_dq;/* Internal data qualifier descriptor. */
  17745     _field_stage_t  *stage_fc;    /* Stage field control.                */
  17746     int rv;                       /* Operation return status.            */
  17747 
  17748     /* Get stage field control structure. */
  17749     rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc);
  17750     BCM_IF_ERROR_RETURN(rv);
  17751 
  17752     while (NULL != stage_fc->data_ctrl->data_qual) {
  17753         f_dq = stage_fc->data_ctrl->data_qual;
  17754         BCM_IF_ERROR_RETURN (_bcm_field_data_qualifier_destroy(unit, f_dq->qid));
  17755     }
  17756     return (BCM_E_NONE);
  17757 }
  17758 
  17759 /*
  17760  * Function:
  17761  *     _field_stage_data_ctrl_deinit
  17762  *
  17763  * Purpose:
  17764  *     De-allocate data qualifiers control structure.
  17765  *
  17766  * Parameters:
  17767  *     unit     - (IN)     BCM unit
  17768  *     stage_fc - (IN/OUT) Stage to be initialize.
  17769  * Returns:
  17770  *     BCM_E_XXX
  17771  */
  17772 STATIC int
  17773 _field_stage_data_ctrl_deinit(int unit, _field_stage_t *stage_fc)
  17774 {
  17775     _field_data_control_t *data_ctrl;
  17776 
  17777     /* Input parameters check. */
  17778     if (NULL == stage_fc) {
  17779         return (BCM_E_PARAM);
  17780     }
  17781 
  17782     if (stage_fc->stage_id != _BCM_FIELD_STAGE_INGRESS) {
  17783         return (BCM_E_NONE);
  17784     }
  17785 
  17786     data_ctrl = stage_fc->data_ctrl;
  17787     if (NULL == data_ctrl) {
  17788         return (BCM_E_NONE);
  17789     }
  17790 
  17791     /* Delete all data qualifiers. */
  17792     _field_data_qualifier_destroy_all(unit) ;
  17793 
  17794     /* Free control structures. */
  17795     if (NULL != data_ctrl->tcam_entry_arr) {
  17796         sal_free(data_ctrl->tcam_entry_arr);
  17797     }
  17798 
  17799     if (NULL != data_ctrl) {
  17800         sal_free(data_ctrl);
  17801     }
  17802 
  17803     stage_fc->data_ctrl  = NULL;
  17804     return (BCM_E_NONE);
  17805 }
  17806 
  17807 /*
  17808  * Function:
  17809  *      _bcm_field_data_qualifier_get
  17810  * Purpose:
  17811  *      Get data qualifier by id.
  17812  * Parameters:
  17813  *      unit           - (IN) bcm device.
  17814  *      stage_fc       - (IN) Stage field control.
  17815  *      qid            - (IN) Qualifier id.
  17816  *      data_qual      - (OUT) Internal data qualifier descriptor:
  17817  *
  17818  * Returns:
  17819  *      BCM_E_XXX
  17820  */
  17821 int
  17822 _bcm_field_data_qualifier_get(int unit, _field_stage_t *stage_fc,
  17823                               int qid, _field_data_qualifier_t **data_qual)
  17824 {
  17825     _field_data_qualifier_p f_dq;  /* Field data qualifier iterator. */
  17826 
  17827     /* Input parameters check. */
  17828     if((NULL == data_qual) ||  (NULL == stage_fc)){
  17829         return (BCM_E_PARAM);
  17830     }
  17831 
  17832     f_dq = stage_fc->data_ctrl->data_qual;
  17833     while (NULL != f_dq) {
  17834         if (f_dq->qid == qid) {
  17835             *data_qual = f_dq;
  17836             return (BCM_E_NONE);
  17837         }
  17838         f_dq = f_dq->next;
  17839     }
  17840     return (BCM_E_NOT_FOUND);
  17841 }
  17842 
  17843 
  17844 /*
  17845  * Function:
  17846  *      _field_data_qualifier_get
  17847  *
  17848  * Purpose:
  17849  *      Get data qualifier by qualifier id.
  17850  *
  17851  * Parameters:
  17852  *      unit       - (IN)  bcm device.
  17853  *      qual_id    - (IN)  Id of data qualifier.
  17854  *      data_qual  - (OUT) Internal data qualifier descriptor:
  17855  *
  17856  * Returns:
  17857  *      BCM_E_XXX
  17858  */
  17859 int
  17860 _field_data_qualifier_get(int unit, int qual_id,
  17861                            _field_data_qualifier_t *data_qual)
  17862 {
  17863     int                     rv;
  17864     _field_control_t        *fc;
  17865     _field_stage_t          *stage_fc;
  17866     _field_data_qualifier_t *f_dq;
  17867 
  17868     /* Parameter checking */
  17869     if (data_qual == NULL) {
  17870         LOG_ERROR(BSL_LS_BCM_FP,
  17871                   (BSL_META_U(unit,
  17872                               "FP(unit %d) Error: data_qual == NULL.\n"),
  17873                    unit));
  17874         return (BCM_E_PARAM);
  17875     }
  17876 
  17877     /* Point to needed things */
  17878     FP_LOCK(unit);
  17879     rv = _field_control_get(unit, &fc);
  17880     if (BCM_FAILURE(rv)) {
  17881         FP_UNLOCK(unit);
  17882         return rv;
  17883     }
  17884     rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc);
  17885     if (BCM_FAILURE(rv)) {
  17886         FP_UNLOCK(unit);
  17887         return rv;
  17888     }
  17889 
  17890     if ((rv = _bcm_field_data_qualifier_get(unit,
  17891                 stage_fc, qual_id, &f_dq)) == BCM_E_NONE) {
  17892         sal_memcpy(data_qual, f_dq, sizeof(_field_data_qualifier_t));
  17893     }
  17894 
  17895     FP_UNLOCK(unit);
  17896 
  17897     return (rv);
  17898 }
  17899 
  17900 
  17901 /*
  17902  * Function:
  17903  *      _field_data_qualifier_id_alloc
  17904  * Purpose:
  17905  *      Allocate unused date qualifier id.
  17906  * Parameters:
  17907  *      unit           - (IN) bcm device.
  17908  *      stage_fc       - (IN) Stage field control.
  17909  *      data_qualifier - (IN) API level qualifier descriptor:
  17910  *
  17911  * Returns:
  17912  *      BCM_E_XXX
  17913  */
  17914 int
  17915 _field_data_qualifier_id_alloc(int unit, _field_stage_t *stage_fc,
  17916                              bcm_field_data_qualifier_t *data_qualifier)
  17917 {
  17918     _field_data_qualifier_t *f_dq;    /* Data qualifier descriptor.    */
  17919     static int last_allocated_qid = 0;/* last allocated qid. */
  17920     int max_try;                      /* Maximum number of allocation. */
  17921     int qid;                          /* Qualifier id.                 */
  17922     int rv;                           /* Operation return status.      */
  17923 
  17924 
  17925     /* Input parameters check. */
  17926     if ((NULL == data_qualifier) || (NULL == stage_fc)) {
  17927         return (BCM_E_PARAM);
  17928     }
  17929 
  17930     /* If qualifier id was passed by the caller,
  17931        verify the range and make sure id is not used. */
  17932     if (data_qualifier->flags & BCM_FIELD_DATA_QUALIFIER_WITH_ID) {
  17933         qid = data_qualifier->qual_id;
  17934         rv = _bcm_field_data_qualifier_get(unit, stage_fc, qid, &f_dq);
  17935         if (BCM_SUCCESS(rv)) {
  17936             /*  Data qual with requested id already exists */
  17937 
  17938             if (!(data_qualifier->flags & BCM_FIELD_DATA_QUALIFIER_REPLACE)) {
  17939                 /* "Replace" flag was not specified => Return error */
  17940 
  17941                 return (BCM_E_EXISTS);
  17942             }
  17943 
  17944             /* Destroy existing one */
  17945 
  17946             _bcm_field_data_qualifier_destroy(unit, qid);
  17947         }
  17948         return (BCM_E_NONE);
  17949     }
  17950     max_try = _FP_ID_MAX;
  17951     qid = last_allocated_qid;
  17952     while (max_try--) {
  17953         qid++;
  17954         if ((qid < _FP_ID_BASE) || (qid >= _FP_ID_MAX)) {
  17955             qid = _FP_ID_BASE;
  17956         }
  17957         rv = _bcm_field_data_qualifier_get(unit, stage_fc, qid, &f_dq);
  17958         if (BCM_E_NOT_FOUND == rv) {
  17959             last_allocated_qid =  qid;
  17960             data_qualifier->qual_id = qid;
  17961             return (BCM_E_NONE);
  17962         }
  17963         if (BCM_FAILURE(rv)) {
  17964             return (rv);
  17965         }
  17966     }
  17967     return (BCM_E_RESOURCE);
  17968 }
  17969 
  17970 
  17971 int
  17972 _field_data_qualifier_init2(int                        unit,
  17973                             _field_stage_t             *stage_fc,
  17974                             _field_data_qualifier_t    *f_dq
  17975                             )
  17976 {
  17977     int add_offset;               /* Additional offset due to l2         */
  17978                                   /* header size is not multiples of 4.  */
  17979 
  17980     /* Add to stage's data qual list */
  17981     f_dq->next        = stage_fc->data_ctrl->data_qual;
  17982     stage_fc->data_ctrl->data_qual = f_dq;
  17983 
  17984     /* Verify data qualifier offset base value. */
  17985     switch (f_dq->offset_base) {
  17986       /* The following data qualifier offsets are not supported by XGS */
  17987       case bcmFieldDataOffsetBaseTrillPayload:
  17988       case bcmFieldDataOffsetBaseTrillHeader:
  17989 #ifdef BCM_TRIUMPH2_SUPPORT
  17990           /* The following chips support the above mentioned offset base */
  17991           if ((SOC_IS_TD2_TT2(unit)) || (SOC_IS_KATANAX(unit)) ||
  17992               (SOC_IS_TRIUMPH3(unit)) || (SOC_IS_TRIDENT(unit))) {
  17993               break;
  17994           }
  17995 #endif
  17996       case bcmFieldDataOffsetBaseL2Header:
  17997       case bcmFieldDataOffsetBaseFirstHeader:
  17998       case bcmFieldDataOffsetBaseSecondHeader:
  17999       case bcmFieldDataOffsetBaseThirdHeader:
  18000       case bcmFieldDataOffsetBaseMplsLabel1Header:
  18001       case bcmFieldDataOffsetBaseMplsLabel2Header:
  18002       case bcmFieldDataOffsetBaseMplsLabel3Header:
  18003       case bcmFieldDataOffsetBaseInnerL2Header:
  18004       case bcmFieldDataOffsetBaseFourthHeader:
  18005       case bcmFieldDataOffsetBaseForwardingHeader:
  18006       case bcmFieldDataOffsetBaseNextForwardingHeader:
  18007            {
  18008              return (BCM_E_PARAM);
  18009            }
  18010            break;
  18011       default:
  18012            break;
  18013     }
  18014 
  18015 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT)
  18016     if (SOC_MEM_IS_VALID(unit, FP_UDF_TCAMm)) {
  18017         if (stage_fc->data_ctrl->elem_size <= 2) { /* no wrap around needed */
  18018             f_dq->byte_offset = f_dq->offset %
  18019                 stage_fc->data_ctrl->elem_size;
  18020         } else {
  18021             if (bcmFieldDataOffsetBasePacketStart ==
  18022                 f_dq->offset_base) {
  18023                 f_dq->byte_offset = (f_dq->offset + 2) % 4;
  18024             } else {
  18025                 f_dq->byte_offset = f_dq->offset % 4;
  18026             }
  18027         }
  18028     } else
  18029 #endif /* BCM_TRIUMPH2_SUPPORT */
  18030     {
  18031         switch (f_dq->offset_base) {
  18032           case bcmFieldDataOffsetBaseOuterL3Header:
  18033           case bcmFieldDataOffsetBaseInnerL3Header:
  18034           case bcmFieldDataOffsetBaseOuterL4Header:
  18035           case bcmFieldDataOffsetBaseInnerL4Header:
  18036               /* Older devices supports Start of Packet offset only. */
  18037               return (BCM_E_PARAM);
  18038           case bcmFieldDataOffsetBasePacketStart:
  18039               add_offset = 0;
  18040               break;
  18041           case bcmFieldDataOffsetBaseHigigHeader:
  18042               if (SOC_IS_FB(unit) ||
  18043                   SOC_IS_HB_GW(unit) ||
  18044                   SOC_IS_SC_CQ(unit) ||
  18045                   SOC_IS_ENDURO(unit) ||
  18046                   soc_feature(unit, soc_feature_field_udf_offset_hg_114B)) {
  18047                   add_offset = 2;
  18048               } else {
  18049                   add_offset = 0;
  18050               }
  18051               break;
  18052           case bcmFieldDataOffsetBaseHigig2Header:
  18053               if (SOC_IS_FB(unit) ||
  18054                   SOC_IS_HB_GW(unit) ||
  18055                   SOC_IS_SC_CQ(unit) ||
  18056                   SOC_IS_ENDURO(unit) ||
  18057                   soc_feature(unit, soc_feature_field_udf_offset_hg2_110B)) {
  18058                   add_offset = 2;
  18059               } else {
  18060                   add_offset = 0;
  18061               }
  18062               break;
  18063           default:
  18064               return (BCM_E_PARAM);
  18065         }
  18066 
  18067         f_dq->byte_offset = (f_dq->offset + add_offset + 2) % 4;
  18068     }
  18069 
  18070     return (BCM_E_NONE);
  18071 }
  18072 
  18073 
  18074 int
  18075 _field_data_qualifier_init(int                        unit,
  18076                            _field_stage_t             *stage_fc,
  18077                            _field_data_qualifier_t    *f_dq,
  18078                            bcm_field_data_qualifier_t *data_qualifier
  18079                            )
  18080 {
  18081     f_dq->qid         = data_qualifier->qual_id;
  18082     f_dq->offset_base = data_qualifier->offset_base;
  18083     f_dq->offset      = data_qualifier->offset;
  18084     f_dq->length      = data_qualifier->length;
  18085     f_dq->flags       = data_qualifier->flags & _BCM_FIELD_DATA_QUALIFIER_FLAGS;
  18086 
  18087     BCM_IF_ERROR_RETURN(_field_data_qualifier_init2(unit, stage_fc, f_dq));
  18088 
  18089     f_dq->elem_count = (f_dq->length + f_dq->byte_offset +
  18090                         stage_fc->data_ctrl->elem_size - 1
  18091                         )
  18092         / stage_fc->data_ctrl->elem_size;
  18093 
  18094     return (BCM_E_NONE);
  18095 }
  18096 
  18097 void
  18098 _field_data_qualifier_debug(int unit,
  18099                             _field_stage_t *stage_fc,
  18100                             _field_data_qualifier_t *f_dq)
  18101 {
  18102     int  idx, first=1;
  18103     int  num_elems;
  18104 
  18105     if (stage_fc == NULL || f_dq == NULL) {
  18106        return;
  18107     }
  18108 
  18109     num_elems = stage_fc->data_ctrl->num_elems;
  18110     LOG_VERBOSE(BSL_LS_BCM_FP,
  18111                 (BSL_META_U(unit,
  18112                             "Chunks allocated for Data Qualifier ID - %d:\n\r"),
  18113                  f_dq->qid));
  18114     LOG_VERBOSE(BSL_LS_BCM_FP,
  18115                 (BSL_META_U(unit,
  18116                             "UDF1{")));
  18117     for (idx = 0; idx < num_elems; idx++) {
  18118        if (f_dq->hw_bmap & (1 << idx)) {
  18119           if (first == 0) {
  18120              LOG_VERBOSE(BSL_LS_BCM_FP,
  18121                          (BSL_META_U(unit,
  18122                                      "), ")));
  18123           }
  18124           first = 0;
  18125           LOG_VERBOSE(BSL_LS_BCM_FP,
  18126                       (BSL_META_U(unit,
  18127                                   "%d"),
  18128                        idx));
  18129        }
  18130     }
  18131     LOG_VERBOSE(BSL_LS_BCM_FP,
  18132                 (BSL_META_U(unit,
  18133                             "%s}\n\r"),
  18134                  (first == 1)?"None":""));
  18135     first = 1;
  18136     LOG_VERBOSE(BSL_LS_BCM_FP,
  18137                 (BSL_META_U(unit,
  18138                             "UDF2{")));
  18139     for (idx = num_elems; idx < num_elems * 2; idx++) {
  18140        if (f_dq->hw_bmap & (1 << idx)) {
  18141           if (first == 0) {
  18142              LOG_VERBOSE(BSL_LS_BCM_FP,
  18143                          (BSL_META_U(unit,
  18144                                      "), ")));
  18145           }
  18146           first = 0;
  18147           LOG_VERBOSE(BSL_LS_BCM_FP,
  18148                       (BSL_META_U(unit,
  18149                                   "%d"),
  18150                        idx));
  18151        }
  18152     }
  18153     LOG_VERBOSE(BSL_LS_BCM_FP,
  18154                 (BSL_META_U(unit,
  18155                             "%s}\n\r"),
  18156                  (first == 1)?"None":""));
  18157 }
  18158 
  18159 int
  18160 _field_data_qualifier_create(int unit,
  18161                              bcm_field_data_qualifier_t *data_qualifier)
  18162 {
  18163     _field_data_qualifier_t *f_dq;/* Internal data qualifier descriptor. */
  18164     _field_stage_t  *stage_fc;    /* Stage field control.                */
  18165     int rv;                       /* Operation return status.            */
  18166 
  18167     /* Input parameters check. */
  18168     if (NULL == data_qualifier) {
  18169         return (BCM_E_PARAM);
  18170     }
  18171 
  18172 #if defined (BCM_TRIUMPH2_SUPPORT)
  18173     if (soc_feature(unit, soc_feature_udf_support)) {
  18174         if (UDF_CTRL(unit) == NULL) {
  18175             LOG_CLI((BSL_META("UDF module is not initialized. \n")));
  18176             return (BCM_E_RESOURCE);
  18177         }
  18178         if (UDF_CTRL(unit)->udf_used_by_module == UDF_USED_BY_UDF_MODULE) {
  18179             LOG_CLI((BSL_META("Udf resource is used by UDF module. \n")));
  18180             return (BCM_E_RESOURCE);
  18181         }
  18182     }
  18183 #endif
  18184 
  18185     /* Get stage field control structure. */
  18186     rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc);
  18187     BCM_IF_ERROR_RETURN(rv);
  18188 
  18189     /* Allocate data qualifier id. */
  18190     rv = _field_data_qualifier_id_alloc(unit, stage_fc, data_qualifier);
  18191     BCM_IF_ERROR_RETURN(rv);
  18192 
  18193     /* Allocated internal data qualifier descriptor. */
  18194     rv = _bcm_field_data_qualifier_alloc(unit, &f_dq);
  18195     BCM_IF_ERROR_RETURN(rv);
  18196 
  18197     /* Initialize internal data qualifier record from given one */
  18198     rv = _field_data_qualifier_init(unit, stage_fc, f_dq, data_qualifier);
  18199     if (BCM_FAILURE(rv)) {
  18200         goto error_cleanup;
  18201     }
  18202 
  18203     /* Allocate words in hw to accommodate data qualifier. */
  18204     rv = _field_data_qualifier_hw_alloc(unit, stage_fc, f_dq);
  18205     if (BCM_FAILURE(rv)) {
  18206         goto error_cleanup;
  18207     }
  18208 
  18209     if (FP_VERB_CHECK()) {
  18210       (void)_field_data_qualifier_debug(unit, stage_fc, f_dq);
  18211     }
  18212 
  18213 #if defined (BCM_TRIUMPH2_SUPPORT)
  18214     if (soc_feature(unit, soc_feature_udf_support)) {
  18215         UDF_LOCK(unit);
  18216         UDF_CTRL(unit)->udf_used_by_module = UDF_USED_BY_FIELD_MODULE;
  18217         UDF_UNLOCK(unit);
  18218     }
  18219 #endif
  18220 
  18221     return (BCM_E_NONE);
  18222 
  18223  error_cleanup:
  18224     _bcm_field_data_qualifier_destroy(unit, f_dq->qid);
  18225 
  18226     return (rv);
  18227 }
  18228 
  18229 /*
  18230  * Function: _field_qualify_data_elem
  18231  *
  18232  * Purpose:
  18233  *
  18234  * Parameters:
  18235  *     unit          - (IN) BCM device number.
  18236  *     eid           - (IN) Entry ID.
  18237  *     f_dq          - (IN) Data qualifier descriptor.
  18238  *     qual_elem_idx - (IN) Data qualifier element index.
  18239  *     data          - (IN) Data bytes for the indicated data qualifier.
  18240  *                Network byte ordered.
  18241  *     mask     - Mask bytes for the indicated data qualifier.
  18242  *                Network byte ordered.
  18243  * Returns:
  18244  *     BCM_E_XXX
  18245  */
  18246 int
  18247 _field_qualify_data_elem(int unit, bcm_field_entry_t eid,
  18248                          _field_data_qualifier_t *f_dq,
  18249                          uint8 qual_elem_idx,
  18250                          uint32 data, uint32 mask)
  18251 {
  18252     _field_stage_t           *stage_fc;
  18253     _bcm_field_qual_offset_t *q_offset;
  18254     _bcm_field_qual_offset_t q_offset_temp;
  18255     _field_entry_t           *f_ent = NULL;
  18256     int                      idx;
  18257     int                      rv;
  18258     int                      elem_idx = 0;
  18259     int                      qid = 0;
  18260 
  18261     /* Input parameters check. */
  18262     if (NULL == f_dq) {
  18263         return (BCM_E_PARAM);
  18264     }
  18265 
  18266     BCM_IF_ERROR_RETURN
  18267         (_field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc));
  18268 
  18269     /* Find a proper element to insert the data. */
  18270     for (idx = 0; idx < stage_fc->data_ctrl->num_elems * 2; idx++) {
  18271         if (f_dq->hw_bmap & (1 << idx)) {
  18272             if (elem_idx == qual_elem_idx) {
  18273                 break;
  18274             } else {
  18275                 elem_idx++;
  18276             }
  18277         }
  18278     }
  18279 
  18280     /* Get entry info. */
  18281     BCM_IF_ERROR_RETURN
  18282         (_field_entry_get(unit, eid, _FP_ENTRY_PRIMARY, &f_ent));
  18283 
  18284     /* Get data qualifier id. */
  18285     if (idx >= 0 && idx < stage_fc->data_ctrl->num_elems) {
  18286 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT)
  18287         if (SOC_IS_ENDURO(unit)
  18288             || SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit)
  18289             || SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit)
  18290             || SOC_IS_VALKYRIE2(unit) || SOC_IS_GREYHOUND2(unit)) {
  18291             /* Check in group Qset if Data0 is set. */
  18292             if (!BCM_FIELD_QSET_TEST_INTERNAL
  18293                     (f_ent->group->qset, _bcmFieldQualifyData0)) {
  18294                 if ((1 == idx)
  18295                     && !(f_dq->hw_bmap & (1 << 0x0))
  18296                     && !(f_dq->hw_bmap & (1 << 0x2))) {
  18297                     /* qid = UDF1_31_0 */
  18298                     qid = _bcmFieldQualifyData3;
  18299                 } else if ((3 == idx)
  18300                     && !(f_dq->hw_bmap & (1 << 0x0))
  18301                     && !(f_dq->hw_bmap & (1 << 0x2))) {
  18302                     /* qid = UDF1_95_64 */
  18303                     qid = _bcmFieldQualifyData2;
  18304                 } else {
  18305                     return (BCM_E_INTERNAL);
  18306                 }
  18307             } else {
  18308                 /* qid = UDF1_127_0 */
  18309                 qid = _bcmFieldQualifyData0;
  18310             }
  18311         } else
  18312 #endif /* BCM_ENDURO_SUPPORT */
  18313 
  18314 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_KATANA_SUPPORT)
  18315         if (SOC_IS_TD_TT(unit)
  18316             || SOC_IS_KATANAX(unit)
  18317             || SOC_IS_TRIUMPH3(unit)) {
  18318             /* Check in group Qset if Data0 is set. */
  18319             if (!BCM_FIELD_QSET_TEST_INTERNAL
  18320                     (f_ent->group->qset, _bcmFieldQualifyData0)) {
  18321                 if ((2 == idx || 3 == idx)
  18322                     && !(f_dq->hw_bmap & 0x33)) {
  18323                     /* UDF1_95_64 */
  18324                     qid = _bcmFieldQualifyData3;
  18325                 } else if ((6 == idx || 7 == idx)
  18326                            && !(f_dq->hw_bmap & 0x33)) {
  18327                     /* UDF1_31_0 */
  18328                     qid = _bcmFieldQualifyData2;
  18329                 } else {
  18330                     /*
  18331                      * udf_offset0_1 and udf_offset4_5 must be in
  18332                      * _bcmFieldQualifyData0
  18333                      */
  18334                     return (BCM_E_INTERNAL);
  18335                 }
  18336             } else {
  18337                 /* UDF1_127_0 */
  18338                 qid = _bcmFieldQualifyData0;
  18339             }
  18340         } else
  18341 #endif /* !BCM_TRIDENT_SUPPORT or BCM_KATANA_SUPPORT*/
  18342         {
  18343             qid =  _bcmFieldQualifyData0;
  18344         }
  18345     } else if (idx >= stage_fc->data_ctrl->num_elems &&
  18346                idx < stage_fc->data_ctrl->num_elems * 2) {
  18347         qid =  _bcmFieldQualifyData1;
  18348         idx -= stage_fc->data_ctrl->num_elems;
  18349     } else {
  18350         return (BCM_E_INTERNAL);
  18351     }
  18352 #if defined(BCM_TOMAHAWK_SUPPORT)
  18353     /* If device supports per-pipe FP configuration, */
  18354     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  18355         ((f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) ||
  18356          (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH))) {
  18357         /* coverity[address_of : FALSE] */
  18358         /* coverity[callee_ptr_arith : FALSE] */
  18359         return (_bcm_field_th_qualify_set(unit, eid, qid,
  18360                                           &data, &mask,
  18361                                           _FP_QUALIFIER_ADD));
  18362     }
  18363     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  18364             (f_ent->group->stage_id == _BCM_FIELD_STAGE_CLASS)) {
  18365         return (_bcm_field_th_class_qualify_set(unit, eid, qid,
  18366                                                 &data, &mask));
  18367     }
  18368 #endif /* BCM_TOMAHAWK_SUPPORT */
  18369 
  18370     /* Get entry qualifier should be installed in. */
  18371     f_ent = NULL;
  18372     rv = _bcm_field_entry_qual_get(unit, eid, qid, &f_ent);
  18373     BCM_IF_ERROR_RETURN(rv);
  18374 
  18375     /* Get entry qualifier offset in tcam. */
  18376     rv = _field_qual_offset_get(unit, f_ent, qid, &q_offset);
  18377     BCM_IF_ERROR_RETURN(rv);
  18378 
  18379 #if defined(BCM_ENDURO_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT)
  18380     if (SOC_IS_ENDURO(unit)
  18381         || SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit)
  18382         || SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit)
  18383         || SOC_IS_VALKYRIE2(unit) || SOC_IS_GREYHOUND2(unit)) {
  18384         if ((qid == _bcmFieldQualifyData2)
  18385             || (qid == _bcmFieldQualifyData3)) {
  18386             /* Don't have to swap if only one chunk used in UDF1 */
  18387             idx = 0;
  18388         } else {
  18389             idx = (stage_fc->data_ctrl->num_elems - 1) - idx;
  18390         }
  18391     } else
  18392 #endif /* !BCM_ENDURO_SUPPORT */
  18393 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_KATANA_SUPPORT)
  18394     if (SOC_IS_TD_TT(unit)
  18395         || SOC_IS_KATANAX(unit)
  18396         || SOC_IS_TRIUMPH3(unit)) {
  18397         if (qid == _bcmFieldQualifyData3) {
  18398             if (2 == idx) {
  18399                 /* Shift of 2 bytes (16 bits). */
  18400                 idx = 1;
  18401             } else {
  18402                 idx = 0;
  18403             }
  18404         } else {
  18405             idx = (stage_fc->data_ctrl->num_elems - 1) - idx;
  18406         }
  18407     } else
  18408 #endif
  18409     {
  18410         idx = (stage_fc->data_ctrl->num_elems - 1) - idx;
  18411     }
  18412 
  18413     sal_memcpy(&q_offset_temp, q_offset,
  18414                sizeof(_bcm_field_qual_offset_t));
  18415 
  18416     q_offset_temp.offset[0] += idx * stage_fc->data_ctrl->elem_size * 8;
  18417     q_offset_temp.width[0] = stage_fc->data_ctrl->elem_size * 8;
  18418    /*
  18419     * COVERITY
  18420     *
  18421     *This flow takes care of the  Out-of-bounds access issue
  18422     * for data and mask.
  18423     */
  18424     /* coverity[callee_ptr_arith : FALSE] */
  18425     rv = _bcm_field_qual_value_set(unit, &q_offset_temp, f_ent, &data, &mask);
  18426     BCM_IF_ERROR_RETURN(rv);
  18427 
  18428     f_ent->flags |= _FP_ENTRY_DIRTY;
  18429     return (BCM_E_NONE);
  18430 }
  18431 
  18432 /*
  18433  * Function: _field_external_qualify_data_elem
  18434  *
  18435  * Purpose:
  18436  *
  18437  * Parameters:
  18438  *     unit          - (IN) BCM device number.
  18439  *     eid           - (IN) Entry ID.
  18440  *     f_dq          - (IN) Data qualifier descriptor.
  18441  *     qual_elem_idx - (IN) Data qualifier element index.
  18442  *     data          - (IN) Data bytes for the indicated data qualifier.
  18443  *                Network byte ordered.
  18444  *     mask     - Mask bytes for the indicated data qualifier.
  18445  *                Network byte ordered.
  18446  * Returns:
  18447  *     BCM_E_XXX
  18448  */
  18449 int
  18450 _field_external_qualify_data_elem(int unit, bcm_field_entry_t eid,
  18451                          _field_data_qualifier_t *f_dq,
  18452                          uint8 qual_elem_idx,
  18453                          uint32 data, uint32 mask)
  18454 {
  18455     _field_stage_t           *stage_fc;
  18456     _bcm_field_qual_offset_t *q_offset;
  18457     _field_entry_t           *f_ent = NULL;
  18458     int                      idx;
  18459     int                      rv;
  18460     int                      elem_idx = 0;
  18461     int                      qid = 0;
  18462 
  18463     /* Input parameters check. */
  18464     if (NULL == f_dq) {
  18465         return (BCM_E_PARAM);
  18466     }
  18467 
  18468     LOG_DEBUG(BSL_LS_BCM_FP,
  18469               (BSL_META_U(unit,
  18470                           "FP(unit %d) vverb: eid (%d): qual_elem_idx (%d)"
  18471                            "data (%x) mask (%x)\n"), unit, eid, qual_elem_idx, data, mask));
  18472 
  18473     BCM_IF_ERROR_RETURN
  18474         (_field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc));
  18475 
  18476     /* Find a proper element to insert the data. */
  18477     for (idx = 0; idx < (stage_fc->data_ctrl->num_elems - 2); idx++) {
  18478         if (f_dq->hw_bmap & (1 << idx)) {
  18479             if (elem_idx == qual_elem_idx) {
  18480                 break;
  18481             } else {
  18482                 elem_idx++;
  18483             }
  18484         }
  18485     }
  18486 
  18487     /* Get data qualifier id. */
  18488     if ((f_dq->hw_bmap & 0x1) && (idx >= 0 && idx < 2)) {
  18489         qid =  _bcmFieldQualifyData0;
  18490     } else if ((f_dq->hw_bmap & 0x2) && (idx == 1)) {
  18491         qid =  _bcmFieldQualifyData2;
  18492     } else {
  18493         return (BCM_E_INTERNAL);
  18494     }
  18495 
  18496     /* Get entry qualifier should be installed in. */
  18497     rv = _bcm_field_entry_qual_get(unit, eid, qid, &f_ent);
  18498     BCM_IF_ERROR_RETURN(rv);
  18499 
  18500     /* Get entry qualifier offset in tcam. */
  18501     rv = _field_qual_offset_get(unit, f_ent, qid, &q_offset);
  18502     BCM_IF_ERROR_RETURN(rv);
  18503    /*
  18504     * COVERITY
  18505     *
  18506     *This flow takes care of the  Out-of-bounds access issue
  18507     * for data and mask.
  18508     */
  18509     /* coverity[callee_ptr_arith : FALSE] */
  18510     rv = _bcm_field_qual_value_set(unit, q_offset, f_ent, &data, &mask);
  18511     BCM_IF_ERROR_RETURN(rv);
  18512 
  18513     f_ent->flags |= _FP_ENTRY_DIRTY;
  18514     return (BCM_E_NONE);
  18515 }
  18516 
  18517 
  18518 /*
  18519  * Function: _field_qualify_data
  18520  *
  18521  * Purpose:
  18522  *
  18523  * Parameters:
  18524  *     unit     - (IN) BCM device number.
  18525  *     eid      - (IN) Entry ID.
  18526  *     qual_id  - (IN) Data qualifier id.
  18527  *     data     - (IN) Data bytes for the indicated data qualifier.
  18528  *                     Network byte ordered.
  18529  *     mask     - (IN) Mask bytes for the indicated data qualifier.
  18530  *                     Network byte ordered.
  18531  *     length   - (IN) data/mask length.
  18532  * Returns:
  18533  *     BCM_E_XXX
  18534  */
  18535 int
  18536 _field_qualify_data (int unit, bcm_field_entry_t eid, int qual_id,
  18537                      uint8 *data, uint8 *mask, uint16 length)
  18538 {
  18539     _field_stage_t          *stage_fc;  /* Stage field control.       */
  18540     _field_data_qualifier_t *f_dq;      /* Data qualifier descriptor. */
  18541     int                     idx;        /* HW bitmap iteration index. */
  18542     int                     byte_offset;/* Byte offset in the word.   */
  18543     int                     qual_elem_idx; /* Qualifier element index.*/
  18544     uint32                  data_elem;  /* Hw info data word.         */
  18545     uint32                  mask_elem;  /* Hw info data mask.         */
  18546     uint8                   data_qual_done = 0;
  18547     int                     rv;         /* Operation return status.   */
  18548 #ifdef BCM_TRIUMPH_SUPPORT
  18549     _field_entry_t          *entry_p = NULL; /* Field entry pointer */
  18550 #endif
  18551 
  18552     /* Input parameters check. */
  18553     if ((NULL == data) || (NULL == mask)) {
  18554             return (BCM_E_PARAM);
  18555     }
  18556 
  18557 
  18558 
  18559     /* Get stage field control structure. */
  18560     rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc);
  18561     BCM_IF_ERROR_RETURN(rv);
  18562 
  18563     /* Get data qualifier info. */
  18564     rv = _bcm_field_data_qualifier_get(unit, stage_fc, qual_id,  &f_dq);
  18565     BCM_IF_ERROR_RETURN(rv);
  18566 
  18567 #ifdef BCM_TRIUMPH_SUPPORT
  18568     rv = _field_entry_get(unit, eid, _FP_ENTRY_PRIMARY, &entry_p);
  18569     BCM_IF_ERROR_RETURN(rv);
  18570 #endif
  18571 
  18572     /*
  18573      * If provided entry data length is greater than data length used
  18574      * to create qualifier then return error
  18575      */
  18576 
  18577     if (length > f_dq->length) {
  18578         return (BCM_E_PARAM);
  18579     }
  18580 
  18581 #ifdef BCM_TOMAHAWK_SUPPORT
  18582    if (_BCM_FIELD_STAGE_EXACTMATCH == entry_p->group->stage_id) {
  18583        if (length != f_dq->length) {
  18584            return BCM_E_PARAM;
  18585        }
  18586    }
  18587 #endif
  18588 
  18589 #ifdef BCM_TRIUMPH_SUPPORT
  18590     if (SOC_IS_TRIUMPH(unit) || SOC_IS_TRIUMPH2(unit)) {
  18591         /* Get entry qualifier should be installed in. */
  18592         if (entry_p->group->stage_id == _BCM_FIELD_STAGE_EXTERNAL) {
  18593             if (length > 4) {
  18594                 return (BCM_E_PARAM);
  18595             }
  18596         }
  18597     }
  18598 #endif
  18599 
  18600     data_elem = 0;
  18601     mask_elem = 0;
  18602     qual_elem_idx = 0;
  18603     byte_offset = f_dq->byte_offset;
  18604     for (idx = 0; idx < length; idx++) {
  18605 
  18606 #ifdef BCM_TOMAHAWK_SUPPORT
  18607         if (_BCM_FIELD_STAGE_EXACTMATCH == entry_p->group->stage_id) {
  18608             if (0xFF != mask[idx]) {
  18609                 return BCM_E_PARAM;
  18610             }
  18611         }
  18612 #endif
  18613 
  18614         data_elem |= (data[idx] << (8 * (stage_fc->data_ctrl->elem_size - 1 -
  18615                                          byte_offset)));
  18616         mask_elem |= (mask[idx] << (8 * (stage_fc->data_ctrl->elem_size - 1 -
  18617                                          byte_offset)));
  18618         byte_offset++;
  18619         data_qual_done = 0;
  18620 
  18621         if (byte_offset == stage_fc->data_ctrl->elem_size) {
  18622             /* Install the element data & mask. */
  18623 #ifdef BCM_TRIUMPH_SUPPORT
  18624             if ((SOC_IS_TRIUMPH(unit) || SOC_IS_TRIUMPH2(unit)) &&
  18625                 (entry_p->group->stage_id == _BCM_FIELD_STAGE_EXTERNAL)) {
  18626                 rv = _field_external_qualify_data_elem(unit, eid,
  18627                                                        f_dq, qual_elem_idx,
  18628                                                        data_elem, mask_elem);
  18629             } else
  18630 #endif
  18631 #ifdef BCM_TOMAHAWK_SUPPORT
  18632             if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  18633                 rv = _bcm_field_th_field_qualify_data_elem(unit, eid, f_dq, qual_elem_idx,
  18634                         data_elem, mask_elem);
  18635             } else
  18636 #endif
  18637             {
  18638                 rv = _field_qualify_data_elem(unit, eid, f_dq, qual_elem_idx,
  18639                                               data_elem, mask_elem);
  18640             }
  18641             BCM_IF_ERROR_RETURN(rv);
  18642             qual_elem_idx++;
  18643             byte_offset = 0;
  18644             data_elem = 0;
  18645             mask_elem = 0;
  18646             data_qual_done = 1;
  18647         }
  18648     }
  18649 
  18650     /* Install last element data & mask, if data/mask still exists to be qualified.
  18651      * (data_qual_done == 0)
  18652      */
  18653 
  18654     if (data_qual_done != 1) {
  18655 #ifdef BCM_TRIUMPH_SUPPORT
  18656         if ((SOC_IS_TRIUMPH(unit) || SOC_IS_TRIUMPH2(unit)) &&
  18657             (entry_p->group->stage_id == _BCM_FIELD_STAGE_EXTERNAL)) {
  18658             rv = _field_external_qualify_data_elem(unit, eid, f_dq,
  18659                                                    qual_elem_idx, data_elem,
  18660                                                    mask_elem);
  18661         } else
  18662 #endif
  18663 #ifdef BCM_TOMAHAWK_SUPPORT
  18664         if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  18665             rv = _bcm_field_th_field_qualify_data_elem(unit, eid, f_dq, qual_elem_idx,
  18666                     data_elem, mask_elem);
  18667         } else
  18668 #endif
  18669         {
  18670             rv = _field_qualify_data_elem(unit, eid, f_dq, qual_elem_idx,
  18671                                           data_elem, mask_elem);
  18672         }
  18673     }
  18674     return (rv);
  18675 }
  18676 
  18677 /*
  18678  * Function:
  18679  *     _field_selcode_assign
  18680  *
  18681  * Purpose:
  18682  *     Calculate the FPFx select codes from a qualifier set and group mode.
  18683  *
  18684  * Parameters:
  18685  *     unit           - (IN) BCM device number.
  18686  *     qset           - (IN) Client qualifier set.
  18687  *     selcode_clear  - (IN) Clear the selcodes
  18688  *     fg             - (IN/OUT) Group info structure.
  18689  *
  18690  * Returns:
  18691  *     BCM_E_PARAM    - mode unknown
  18692  *     BCM_E_RESOURCE - No select code will satisfy qualifier set
  18693  *     BCM_E_NONE     - Success
  18694  *
  18695  * Notes:
  18696  *     Calling function is responsible for ensuring appropriate slices
  18697  *     are available.
  18698  *     selcode_clear will be 0 (don't clear) when this function is called
  18699  *         from bcm_field_group_set
  18700  */
  18701 int
  18702 _field_selcode_assign(int unit, bcm_field_qset_t qset, int selcode_clear,
  18703                       _field_group_t *fg)
  18704 {
  18705     _field_stage_t      *stage_fc;  /* Stage field control structure. */
  18706     _field_control_t    *fc;        /* Field control structure.       */
  18707     int                 idx;        /* Generic iteration index.       */
  18708 
  18709     /* Input parameters check. */
  18710     if (NULL == fg) {
  18711         return (BCM_E_PARAM);
  18712     }
  18713 
  18714     /* Get field control structure for this device. */
  18715     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  18716 
  18717     /* Get stage FP control info. */
  18718     BCM_IF_ERROR_RETURN
  18719         (_field_stage_control_get(unit, fg->stage_id, &stage_fc));
  18720 
  18721     /*
  18722      * Clear the group's slice Qsets.
  18723      *   Selcodes need not be cleared if this function is called from group_set
  18724      */
  18725     for (idx = 0; idx < _FP_MAX_ENTRY_WIDTH; idx++) {
  18726         if (selcode_clear) {
  18727             _FIELD_SELCODE_CLEAR(fg->sel_codes[idx]);
  18728             BCM_IF_ERROR_RETURN(_bcm_field_group_qualifiers_free(fg, idx));
  18729         }
  18730     }
  18731 
  18732     /* Get select codes based on group flags. */
  18733     BCM_IF_ERROR_RETURN (fc->functions.fp_selcode_get(unit, stage_fc,
  18734                                                       &qset, fg));
  18735     return (BCM_E_NONE);
  18736 }
  18737 
  18738 
  18739 /*
  18740  * Function:
  18741  *     _field_meters_deinit
  18742  * Purpose:
  18743  *     Deinitialize field slice meters usage bitmap.
  18744  *
  18745  * Parameters:
  18746  *     unit         - (IN) BCM device number.
  18747  *     stage_fc     - (IN/OUT) Stage field control structure.
  18748  *
  18749  * Returns:
  18750  *     BCM_E_XXX
  18751  *
  18752  * Notes:
  18753  *     The External stage of Triumph shares the meter pool with Ingress.
  18754  *         free only when it is called for Ingress.
  18755  */
  18756 STATIC int
  18757 _field_meters_deinit (int unit, _field_stage_t *stage_fc)
  18758 {
  18759     _field_slice_t   *slice;      /* Slice config structure. */
  18760     int              slice_idx;   /* Slices iterator.        */
  18761 
  18762     /* Input parameters check. */
  18763     if (NULL == stage_fc) {
  18764         return (BCM_E_NONE);
  18765     }
  18766 
  18767     /* Make sure slices array is initialized. */
  18768     if (NULL == stage_fc->slices[_FP_DEF_INST]) {
  18769         return (BCM_E_NONE);
  18770     }
  18771 
  18772     if (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) {
  18773         int i;
  18774         if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXTERNAL) {
  18775             return (BCM_E_NONE);
  18776         }
  18777         for (i = 0; i < stage_fc->num_meter_pools; i++) {
  18778             if (stage_fc->meter_pool[_FP_DEF_INST][i] != NULL) {
  18779                 if (stage_fc->meter_pool[_FP_DEF_INST][i]->meter_bmp.w
  18780                     != NULL) {
  18781                     sal_free(
  18782                         stage_fc->meter_pool[_FP_DEF_INST][i]->meter_bmp.w);
  18783                 }
  18784                 sal_free(stage_fc->meter_pool[_FP_DEF_INST][i]);
  18785                 stage_fc->meter_pool[_FP_DEF_INST][i] = NULL;
  18786             }
  18787         }
  18788 
  18789 #ifdef BCM_TRIUMPH3_SUPPORT
  18790         if (SOC_IS_TRIUMPH3(unit)) {
  18791             for (i = 0; i < stage_fc->num_logical_meter_pools; i++) {
  18792                 if (stage_fc->logical_meter_pool[i] != NULL) {
  18793                     if (stage_fc->logical_meter_pool[i]->meter_bmp.w != NULL) {
  18794                         sal_free(stage_fc->logical_meter_pool[i]->meter_bmp.w);
  18795                     }
  18796                     sal_free(stage_fc->logical_meter_pool[i]);
  18797                     stage_fc->logical_meter_pool[i] = NULL;
  18798                 }
  18799             }
  18800         }
  18801 #endif
  18802 
  18803         return BCM_E_NONE;
  18804     }
  18805 
  18806     for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) {
  18807         slice = stage_fc->slices[_FP_DEF_INST] + slice_idx;
  18808         if (NULL != slice->meter_bmp.w) {
  18809             sal_free(slice->meter_bmp.w);
  18810         }
  18811         slice->meter_bmp.w = NULL;
  18812     }
  18813     return (BCM_E_NONE);
  18814 }
  18815 
  18816 /*
  18817  * Function:
  18818  *     _field_counters_deinit
  18819  * Purpose:
  18820  *     Deinitialize field slice counters bitmap.
  18821  *
  18822  * Parameters:
  18823  *     unit         - (IN) BCM device number.
  18824  *     stage_fc     - (IN/OUT) Stage field control structure.
  18825  *
  18826  * Returns:
  18827  *     BCM_E_XXX
  18828  */
  18829 
  18830 STATIC void
  18831 _field_cntr_pools_deinit(int unit, _field_stage_t *stage_fc)
  18832 {
  18833     _field_cntr_pool_t **pp, *p;
  18834     unsigned           n;
  18835 
  18836     for (pp = stage_fc->cntr_pool, n = COUNTOF(stage_fc->cntr_pool); n; --n, ++pp) {
  18837         if ((p = *pp) == 0) {
  18838             continue;
  18839         }
  18840 
  18841         sal_free(p->cntr_bmp.w);
  18842         sal_free(p);
  18843 
  18844         *pp = 0;
  18845     }
  18846 }
  18847 
  18848 
  18849 STATIC int
  18850 _field_counters_deinit(int unit, _field_stage_t *stage_fc)
  18851 {
  18852     _field_slice_t   *slice;      /* Slice config structure.   */
  18853     int              slice_idx;   /* Slices iterator.        */
  18854 
  18855     /* Input parameters check. */
  18856     if (NULL == stage_fc) {
  18857         return (BCM_E_NONE);
  18858     }
  18859 
  18860     /* Make sure slices array is initialized. */
  18861     if (NULL == stage_fc->slices[_FP_DEF_INST]) {
  18862         return (BCM_E_NONE);
  18863     }
  18864 
  18865     /* Destroy 64 bit counters. */
  18866     _field_counter_collect_deinit(unit, stage_fc);
  18867 
  18868     /*
  18869      * There is an 1-1 mapping between rules and counters
  18870      * for external FP, so no bitmap was allocated.
  18871      *     (Triumph)
  18872      */
  18873     if (_BCM_FIELD_STAGE_EXTERNAL == stage_fc->stage_id) {
  18874         return (BCM_E_NONE);
  18875     }
  18876 
  18877     /* Denitialize stage slices info. */
  18878 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  18879     if (_BCM_FIELD_STAGE_EGRESS == stage_fc->stage_id) {
  18880         if (NULL != stage_fc->slices[_FP_DEF_INST][0].counter_bmp.w) {
  18881             sal_free (stage_fc->slices[_FP_DEF_INST][0].counter_bmp.w);
  18882         }
  18883         for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) {
  18884             stage_fc->slices[_FP_DEF_INST][slice_idx].counter_bmp.w = NULL;
  18885         }
  18886     } else if (_BCM_FIELD_STAGE_LOOKUP == stage_fc->stage_id) {
  18887 #if defined(BCM_TRIUMPH2_SUPPORT)
  18888         /* Deallocate flexible stat counters. */
  18889         if (soc_feature(unit, soc_feature_field_vfp_flex_counter)) {
  18890             _bcm_esw_flex_stat_release_handles(unit, _bcmFlexStatTypeFp);
  18891         }
  18892 #endif /* BCM_TRIUMPH2_SUPPORT */
  18893     } else
  18894 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  18895     {
  18896         for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) {
  18897             slice = stage_fc->slices[_FP_DEF_INST] + slice_idx;
  18898             if (NULL != slice->counter_bmp.w) {
  18899                 sal_free (slice->counter_bmp.w);
  18900             }
  18901             slice->counter_bmp.w = NULL;
  18902         }
  18903     }
  18904 
  18905     _field_cntr_pools_deinit(unit, stage_fc);
  18906 
  18907     return (BCM_E_NONE);
  18908 }
  18909 
  18910 /*
  18911  * Function:
  18912  *     _field_stage_delete
  18913  *
  18914  * Purpose:
  18915  *     Deinitialize field stage.
  18916  *
  18917  * Parameters:
  18918  *     unit      - (IN) BCM device number.
  18919  *     fc        - (IN/OUT)Field control info for device.
  18920  *     stage_fc  - (IN) Stage control structure.
  18921  *
  18922  * Returns:
  18923  *     BCM_E_XXX
  18924  */
  18925 int
  18926 _field_stage_delete(int unit, _field_control_t *fc, _field_stage_t *stage_fc)
  18927 {
  18928     _field_stage_t        *stage_iter;    /* Device stages iterator. */
  18929 
  18930     /* Input parameters check. */
  18931     if (NULL == fc) {
  18932         return (BCM_E_PARAM);
  18933     }
  18934 
  18935     if (NULL == stage_fc) {
  18936         return (BCM_E_NONE);
  18937     }
  18938 
  18939     /* Destroy data qualifiers control structure */
  18940     _field_stage_data_ctrl_deinit(unit, stage_fc);
  18941 
  18942     /* Deallocate stage qualifiers */
  18943     _bcm_field_stage_qualifiers_free(unit, stage_fc);
  18944 
  18945     /* Free stage slices info. */
  18946     if (NULL != stage_fc->slices[_FP_DEF_INST]) {
  18947 
  18948         /* Deallocate counters usage bitmap. */
  18949         _field_counters_deinit(unit, stage_fc);
  18950 
  18951         /* Deallocate meters usage bitmap. */
  18952         _field_meters_deinit(unit, stage_fc);
  18953 
  18954         /* Deallocate the entry pointers */
  18955         _bcm_field_stage_entries_free(unit, stage_fc);
  18956 
  18957         /* Deallocate the priority management structures */
  18958         _bcm_field_prio_mgmt_deinit(unit, stage_fc);
  18959 
  18960         sal_free(stage_fc->slices[_FP_DEF_INST]);
  18961         stage_fc->slices[_FP_DEF_INST] = NULL;
  18962     }
  18963 
  18964     /* destroy all ranges */
  18965     while (stage_fc->ranges != NULL) {
  18966         bcm_esw_field_range_destroy(unit, stage_fc->ranges->rid);
  18967     }
  18968 
  18969     /* Destroy action profile */
  18970     soc_profile_mem_destroy(unit, &stage_fc->ext_act_profile);
  18971 #ifdef  BCM_TRIDENT2_SUPPORT
  18972     if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit))) {
  18973         soc_profile_mem_destroy(unit, &stage_fc->hash_select[0]);
  18974 
  18975         soc_profile_mem_destroy(unit, &stage_fc->hash_select[1]);
  18976     }
  18977 #endif
  18978     /* Remove stage from stages linked list. */
  18979     stage_iter = fc->stages;
  18980     while (NULL != stage_iter) {
  18981         if (stage_iter == stage_fc) {
  18982             fc->stages = stage_fc->next;
  18983             break;
  18984         } else if (stage_iter->next == stage_fc) {
  18985             stage_iter->next = stage_fc->next;
  18986             break;
  18987         }
  18988         stage_iter = stage_iter->next;
  18989     }
  18990 
  18991     /* Free stage info. */
  18992     sal_free(stage_fc);
  18993     stage_fc = NULL;
  18994 
  18995     return (BCM_E_NONE);
  18996 }
  18997 
  18998 /*
  18999  * Function:
  19000  *     _field_stages_destroy
  19001  *
  19002  * Purpose:
  19003  *     Deinitialize field stages within the field control struct.
  19004  *
  19005  * Parameters:
  19006  *     unit - (IN) BCM device number.
  19007  *     fc -   (IN/OUT)Field control info for device.
  19008  *
  19009  * Returns:
  19010  *     BCM_E_XXX
  19011  */
  19012 int
  19013 _field_stages_destroy(int unit, _field_control_t *fc)
  19014 {
  19015     _field_stage_t *stage_fc; /* Stage field control structure. */
  19016 
  19017     /* Input parameters check. */
  19018     if (fc == NULL) {
  19019         return (BCM_E_PARAM);
  19020     }
  19021 
  19022     FP_LOCK(unit);
  19023 
  19024     /* Free stages & slices structures. */
  19025     while (NULL != fc->stages) {
  19026         stage_fc = fc->stages;
  19027 
  19028         /* Free stage resources & stage itself. */
  19029         _field_stage_delete(unit, fc, stage_fc);
  19030     }
  19031 
  19032     FP_UNLOCK(unit);
  19033     return (BCM_E_NONE);
  19034 }
  19035 
  19036 /*
  19037  * Function:
  19038  *     _field_qset_union
  19039  *
  19040  * Purpose:
  19041  *     make a union of two qsets
  19042  *
  19043  * Parameters:
  19044  *     qset1      - source 1
  19045  *     qset2      - source 2
  19046  *     qset_union - (OUT) result of union operation
  19047  *
  19048  * Returns:
  19049  *     BCM_E_NONE - Success
  19050  */
  19051 int
  19052 _field_qset_union(const bcm_field_qset_t *qset1,
  19053                   const bcm_field_qset_t *qset2,
  19054                   bcm_field_qset_t *qset_union)
  19055 {
  19056     int                    idx;
  19057 
  19058     if (NULL == qset_union) {
  19059         return (BCM_E_PARAM);
  19060     }
  19061 
  19062 
  19063     /* Perform the union of the qualifier bitmap. */
  19064     for (idx = 0; idx < _SHR_BITDCLSIZE(BCM_FIELD_QUALIFY_MAX); idx++) {
  19065         qset_union->w[idx] = qset1->w[idx] | qset2->w[idx];
  19066     }
  19067 
  19068     /* Perform the union of the qualifier udfs. */
  19069     for (idx = 0; idx < _SHR_BITDCLSIZE(BCM_FIELD_USER_NUM_UDFS); idx++) {
  19070         qset_union->udf_map[idx] = qset1->udf_map[idx] | qset2->udf_map[idx];
  19071     }
  19072 
  19073     return (BCM_E_NONE);
  19074 }
  19075 
  19076 /*
  19077  * Function:
  19078  *     _field_qset_is_subset
  19079  * Purpose:
  19080  *     Determine if qset one is a subset of qset two.
  19081  * Parameters:
  19082  *     qset_1
  19083  *     qset_2
  19084  * Returns:
  19085  *     TRUE - if 'qset_1' is a subset of 'qset_2'
  19086  *     FALSE - if 'qset_1' is NOT a subset of 'qset_2'
  19087  */
  19088 int
  19089 _field_qset_is_subset(const bcm_field_qset_t *qset_1,
  19090                       const bcm_field_qset_t *qset_2)
  19091 {
  19092     int                 idx;
  19093 
  19094     for (idx = 0; idx < _SHR_BITDCLSIZE(BCM_FIELD_QUALIFY_MAX); idx++) {
  19095         if ((qset_1->w[idx] | qset_2->w[idx]) & ~qset_2->w[idx]) {
  19096             return (FALSE);
  19097         }
  19098     }
  19099     return (TRUE);
  19100 }
  19101 
  19102 /*
  19103  * Function:
  19104  *     _field_qset_diff
  19105  * Purpose:
  19106  *     Calculate the result of subtracting qset_2 from qset_1
  19107  * Parameters:
  19108  *     qset_1 - First parameter
  19109  *     qset_2 - Second parameter
  19110  * Returns:
  19111  *     (qset_1 - qset_2)
  19112  */
  19113 bcm_field_qset_t
  19114 _field_qset_diff(const bcm_field_qset_t qset_1,
  19115                  const bcm_field_qset_t qset_2)
  19116 {
  19117     int                 idx;
  19118     bcm_field_qset_t    qset_result;
  19119 
  19120     BCM_FIELD_QSET_INIT(qset_result);
  19121     for (idx = 0; idx < _SHR_BITDCLSIZE(BCM_FIELD_QUALIFY_MAX); idx++) {
  19122         qset_result.w[idx] = qset_1.w[idx] & ~qset_2.w[idx];
  19123     }
  19124     return qset_result;
  19125 }
  19126 
  19127 /*
  19128  * Function:
  19129  *     _field_qset_is_empty
  19130  * Purpose:
  19131  *     Detect empty Qsets
  19132  * Parameters:
  19133  *     qset - Qset to be tested
  19134  * Returns:
  19135  *     1 if qset has no qualifiers
  19136  *     0 if qset has at least one qualifier
  19137  */
  19138 int
  19139 _field_qset_is_empty(const bcm_field_qset_t qset)
  19140 {
  19141     int                 idx;
  19142 
  19143     for (idx = 0; idx < _SHR_BITDCLSIZE(BCM_FIELD_QUALIFY_MAX); idx++) {
  19144         if (qset.w[idx] != 0) {
  19145             return 0;
  19146         }
  19147     }
  19148     return 1;
  19149 }
  19150 
  19151 /*
  19152  * Function:
  19153  *     _bcm_field_qset_test
  19154  * Purpose:
  19155  *     Identify if qualifier is part of the qset.
  19156  * Parameters:
  19157  *     qid    - Qualifier id.
  19158  *     qset   - Qset to be tested
  19159  *     result - Result
  19160  * Returns:
  19161  *     BCM_E_XXX
  19162  */
  19163 int
  19164 _bcm_field_qset_test(bcm_field_qualify_t qid, bcm_field_qset_t *qset,
  19165                              uint8 *result)
  19166 {
  19167     bcm_field_qset_t  test_qset;
  19168 
  19169     /* Input parameters check. */
  19170     if ((NULL == qset) || (NULL == result)) {
  19171         return (BCM_E_PARAM);
  19172     }
  19173 
  19174     BCM_FIELD_QSET_INIT(test_qset);
  19175     BCM_FIELD_QSET_ADD(test_qset, qid);
  19176 
  19177     *result = (_field_qset_is_subset(&test_qset, qset)) ? TRUE : FALSE;
  19178     return (BCM_E_NONE);
  19179 }
  19180 
  19181 /*
  19182  * Function: _bcm_esw_field_group_mode_get
  19183  *
  19184  * Purpose:
  19185  *     Return the mode of a Group ID. This is its single, double or triple-wide
  19186  *     state. Mode specified the number of slices allocated to the group.
  19187  *
  19188  * Parameters:
  19189  *     flags - (IN) Field group flags.
  19190  *     mode  - (OUT) single, double, triple or auto mode.
  19191  *
  19192  * Returns:
  19193  *     BCM_E_XXX
  19194  */
  19195 int
  19196 _bcm_esw_field_group_mode_get(uint32 flags, bcm_field_group_mode_t *mode)
  19197 {
  19198     /* Input parameters check. */
  19199     if (mode == NULL) {
  19200         return (BCM_E_PARAM);
  19201     }
  19202 
  19203     if (flags & _FP_GROUP_SPAN_TRIPLE_SLICE) {
  19204         *mode = bcmFieldGroupModeTriple;
  19205     } else if (flags & _FP_GROUP_SPAN_DOUBLE_SLICE) {
  19206         if (flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
  19207             *mode = bcmFieldGroupModeQuad;
  19208         } else {
  19209             *mode = bcmFieldGroupModeDouble;
  19210         }
  19211     } else if (flags & _FP_GROUP_SPAN_SINGLE_SLICE) {
  19212         if (flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
  19213             *mode = bcmFieldGroupModeIntraSliceDouble;
  19214         } else if (flags & _FP_GROUP_DW_DEPTH_EXPANDED) {
  19215             *mode = bcmFieldGroupModeDouble;
  19216         } else {
  19217             *mode = bcmFieldGroupModeSingle;
  19218         }
  19219     }
  19220     return (BCM_E_NONE);
  19221 }
  19222 
  19223 /*
  19224  * Function:
  19225  *     _field_qual_name
  19226  * Purpose:
  19227  *     Translate a Qualifier enum value to a text string.
  19228  * Parameters:
  19229  *     Enum value from bcm_field_qualify_e. (ex.bcmFieldQualifyInPorts)
  19230  * Returns:
  19231  *     Text name of indicated qualifier enum value.
  19232  */
  19233 char *
  19234 _field_qual_name(bcm_field_qualify_t qid)
  19235 {
  19236     /* Text names of the enumerated qualifier IDs. */
  19237     static char *qual_text[bcmFieldQualifyCount] = BCM_FIELD_QUALIFY_STRINGS;
  19238     static char *_qual_text[_bcmFieldQualifyCount - bcmFieldQualifyCount] =
  19239                                                   _BCM_FIELD_QUALIFY_STRINGS;
  19240 
  19241     if (qid < bcmFieldQualifyCount) {
  19242         return qual_text[qid];
  19243     } else if ((int)qid < _bcmFieldQualifyCount) {
  19244         return _qual_text[qid - bcmFieldQualifyCount];
  19245     }
  19246     return "UnknownQualifier";
  19247 }
  19248 
  19249 /*
  19250  * Function:
  19251  *     _field_stage_name
  19252  * Purpose:
  19253  *     Translate group pipeline  stage to a text string.
  19254  * Parameters:
  19255  *     stage_fc stage field control structure.
  19256  * Returns:
  19257  *     Text name of indicated stage qualifier enum value.
  19258  */
  19259 char *
  19260 _field_stage_name(_field_stage_t *stage_fc)
  19261 {
  19262     static char *stage_text[] = _BCM_FIELD_STAGE_STRINGS;
  19263 
  19264     if (stage_fc->stage_id >= COUNTOF(stage_text)) {
  19265         return "??";
  19266     }
  19267     return stage_text[stage_fc->stage_id];
  19268 }
  19269 
  19270 /*
  19271  * Function:
  19272  *     _field_action_name
  19273  * Purpose:
  19274  *     Return text name of indicated action enum value.
  19275  */
  19276 char *
  19277 _field_action_name(bcm_field_action_t action)
  19278 {
  19279     /* Text names of Actions. These are used for debugging output and CLIs.
  19280      * Note that the order needs to match the bcm_field_action_t enum order.
  19281      */
  19282     static char *action_text[] = BCM_FIELD_ACTION_STRINGS;
  19283     assert(COUNTOF(action_text)     == bcmFieldActionCount);
  19284 
  19285     return (action >= bcmFieldActionCount ? "??" : action_text[action]);
  19286 }
  19287 
  19288 
  19289 /*
  19290  * Function:
  19291  *     _field_group_mode_name
  19292  * Purpose:
  19293  *     Return text name of indicated group mode enum value.
  19294  */
  19295 char *
  19296 _field_group_mode_name(int unit, uint32 group_flags,
  19297                        _field_stage_t *stage_fc)
  19298 {
  19299     bcm_field_group_mode_t mode = 0;
  19300     static char *mode_text[bcmFieldGroupModeCount] =
  19301                  BCM_FIELD_GROUP_MODE_STRINGS;
  19302 
  19303     _bcm_esw_field_group_mode_get(group_flags, &mode);
  19304 #if defined (BCM_TOMAHAWK3_SUPPORT) || defined (BCM_HELIX5_SUPPORT)
  19305     if ((soc_feature(unit, soc_feature_ifp_no_narrow_mode_support) ||
  19306          soc_feature(unit, soc_feature_hx5_style_ifp_no_narrow_mode_support)) &&
  19307          (mode == bcmFieldGroupModeIntraSliceDouble) &&
  19308          (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id)) {
  19309           mode = bcmFieldGroupModeSingle;
  19310     }
  19311 #endif
  19312 
  19313     return (mode >= bcmFieldGroupModeCount ? "??" : mode_text[mode]);
  19314 }
  19315 
  19316 /* Section: Field Initialization */
  19317 
  19318 /*
  19319  * Function: _field_control_free
  19320  *
  19321  * Purpose:
  19322  *    Free field_control structure.
  19323  *
  19324  * Parameters:
  19325  *     unit - (IN) BCM device number
  19326  *     fc   - (IN) Field control structure.
  19327  *
  19328  * Returns:
  19329  *     BCM_E_XXX
  19330  */
  19331 int
  19332 _field_control_free(int unit, _field_control_t *fc)
  19333 {
  19334  #ifdef BCM_TOMAHAWK_SUPPORT
  19335     int inst;       /* Instance Iterator.   */
  19336     int lt_idx;     /* Logical Table Index. */
  19337  #endif
  19338 
  19339     if (NULL == fc) {
  19340         return (BCM_E_NONE);
  19341     }
  19342 
  19343     /* Free policers lookup hash. */
  19344     if (NULL != fc->policer_hash) {
  19345         sal_free(fc->policer_hash);
  19346         fc->policer_hash = NULL;
  19347     }
  19348 
  19349     /* Free counters lookup hash. */
  19350     if (NULL != fc->stat_hash) {
  19351         sal_free(fc->stat_hash);
  19352         fc->stat_hash = NULL;
  19353     }
  19354 
  19355     /* Free udf configuration. */
  19356     if (NULL != fc->udf) {
  19357         sal_free(fc->udf);
  19358         fc->udf = NULL;
  19359     }
  19360 
  19361     /* Free Hints lookup hash. */
  19362     if (NULL != fc->hints_hash) {
  19363         sal_free(fc->hints_hash);
  19364         fc->hints_hash = NULL;
  19365     }
  19366 
  19367     /* Free Hints bitmap. */
  19368     if (NULL != fc->hintid_bmp.w) {
  19369         sal_free(fc->hintid_bmp.w);
  19370         fc->hintid_bmp.w = NULL;
  19371     }
  19372 
  19373 #ifdef BCM_TOMAHAWK_SUPPORT
  19374     /* Free presel lookup database. */
  19375     if (NULL != fc->presel_db) {
  19376         sal_free(fc->presel_db);
  19377         fc->presel_db = NULL;
  19378     }
  19379 
  19380     /* Free presel information. */
  19381     if (NULL != fc->presel_info) {
  19382         sal_free(fc->presel_info);
  19383         fc->presel_info = NULL;
  19384     }
  19385 
  19386     /* Free logical table information. */
  19387     for (inst = 0; inst < NUM_PIPE(unit); inst++) {
  19388         for (lt_idx = 0; lt_idx < _FP_MAX_NUM_LT; lt_idx++) {
  19389             if (NULL != fc->lt_info[inst][lt_idx]) {
  19390                 sal_free(fc->lt_info[inst][lt_idx]->lt_part_pri);
  19391                 sal_free(fc->lt_info[inst][lt_idx]);
  19392                 fc->lt_info[inst][lt_idx] = NULL;
  19393             }
  19394         }
  19395     }
  19396 #endif
  19397 
  19398 #if defined (BCM_TRIUMPH3_SUPPORT)
  19399     /* Free L2changeFields bitmap. */
  19400     if( (SOC_IS_TRIUMPH3(unit)) &&
  19401         (NULL != fc->field_action_l2mod_index_bmp.w) ) {
  19402         sal_free (fc->field_action_l2mod_index_bmp.w);
  19403         fc->field_action_l2mod_index_bmp.w = NULL;
  19404     }
  19405 #endif
  19406 
  19407     /*
  19408      * Retaining "fc" during bcm_field_init for retaining Sticky ExactMatch stage.
  19409      */
  19410     if (0 == (fc->flags & _FP_EXACTMATCH_STAGE_SKIP_DETACH)) {
  19411     /* Free module control structure. */
  19412     sal_free(fc);
  19413         _field_control[unit] = NULL;
  19414     }
  19415 
  19416     return (BCM_E_NONE);
  19417 }
  19418 
  19419 /*
  19420  * Function:
  19421  *     _field_egr_ports_recovery_control_free
  19422  * Purpose:
  19423  *         Free f_egr_recovery structure
  19424  * Parameters:
  19425  *     unit           -  (IN) BCM unit number.
  19426  *     f_egr_recovery - (OUT) Field Egr_ports_recovery
  19427  *                            structure.
  19428  * Returns:
  19429  *     BCM_E_XXX
  19430  */
  19431 
  19432 int
  19433 _field_egr_ports_recovery_control_free (int unit,
  19434                         _field_egr_ports_recovery_t *f_egr_recovery
  19435                                        )
  19436 {
  19437     _field_egr_ports_recovery[unit] = NULL;
  19438 
  19439     if (NULL == f_egr_recovery) {
  19440         return (BCM_E_PARAM);
  19441     }
  19442 
  19443     if (f_egr_recovery->entry_recover_egr_ports != NULL) {
  19444         sal_free (f_egr_recovery->entry_recover_egr_ports);
  19445         f_egr_recovery->entry_recover_egr_ports = NULL;
  19446     }
  19447 
  19448     sal_free (f_egr_recovery);
  19449     f_egr_recovery = NULL;
  19450 
  19451     return BCM_E_NONE;
  19452 }
  19453 
  19454 
  19455 /*
  19456  * Function:
  19457  *     _bcm_field_stages_supported_qset_init
  19458  *
  19459  * Purpose:
  19460  *     Initialize field stages supported qset for each stage
  19461  *
  19462  * Parameters:
  19463  *     unit - (IN) BCM device number.
  19464  *
  19465  * Returns:
  19466  *     BCM_E_NONE   - Success
  19467  *     BCM_E_MEMORY - Allocation failure
  19468  */
  19469 int
  19470 _bcm_field_stages_supported_qset_init(int unit, _field_control_t *fc)
  19471 {
  19472     _field_stage_t   *stage_fc; /* Stage field control structure. */
  19473     bcm_field_qset_t *qset;     /* Operation result.              */
  19474     int idx;                    /* Iteration index.               */
  19475 #if defined(BCM_TOMAHAWK_SUPPORT)
  19476     bcmi_keygen_qual_cfg_info_t **qual_cfg_info = NULL;
  19477     bcmi_keygen_qual_flags_bmp_t qual_flags;
  19478 #endif
  19479 
  19480     /* Fill supported qset for each  pipeline stage. */
  19481     stage_fc = fc->stages;
  19482     while (NULL != stage_fc) {
  19483         qset = &stage_fc->_field_supported_qset;
  19484 
  19485 #if defined (BCM_TOMAHAWK_SUPPORT)
  19486         if ((soc_feature(unit, soc_feature_ifp_no_narrow_mode_support)) &&
  19487             ((_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) ||
  19488             (_BCM_FIELD_STAGE_EXACTMATCH == stage_fc->stage_id))) {
  19489             if (stage_fc->qual_cfg_info_db != NULL ) {
  19490                 qual_cfg_info = stage_fc->qual_cfg_info_db->qual_cfg_info;
  19491                 for (idx = 0; idx < _bcmFieldQualifyCount; idx++) {
  19492                     if (NULL != qual_cfg_info[idx]) {
  19493                         if (_BCM_FIELD_STAGE_EXACTMATCH == stage_fc->stage_id) {
  19494                             qual_flags = qual_cfg_info[idx]->qual_cfg_arr->qual_flags;
  19495                             if (SHR_BITGET(qual_flags.w, BCMI_KEYGEN_QUAL_FLAGS_NOT_IN_EM)) {
  19496                                 continue;
  19497                             }
  19498                         }
  19499                         BCM_FIELD_QSET_ADD(*qset,
  19500                             (stage_fc->qual_cfg_info_db->qual_cfg_info[idx])->qual);
  19501                     }
  19502                 }
  19503             }
  19504         } else
  19505 #endif
  19506         {
  19507             if (stage_fc->f_qual_arr != NULL ) {
  19508                 for (idx = 0; idx < _bcmFieldQualifyCount; idx++) {
  19509                     if (NULL != stage_fc->f_qual_arr[idx]) {
  19510                         BCM_FIELD_QSET_ADD(*qset, (stage_fc->f_qual_arr[idx])->qid);
  19511                     }
  19512                 }
  19513 #if defined(BCM_TOMAHAWK_SUPPORT)
  19514             } else if (stage_fc->qual_cfg_info_db != NULL) {
  19515                 qual_cfg_info = stage_fc->qual_cfg_info_db->qual_cfg_info;
  19516                 for (idx = 0; idx < BCM_FIELD_QUALIFY_MAX; idx++) {
  19517                     if (NULL != qual_cfg_info[idx]) {
  19518                         BCM_FIELD_QSET_ADD(*qset, (qual_cfg_info[idx])->qual);
  19519                     }
  19520                 }
  19521 #endif
  19522             }
  19523         }
  19524 
  19525         stage_fc = stage_fc->next;
  19526     }
  19527     return (BCM_E_NONE);
  19528 }
  19529 
  19530 /*
  19531  * Function:
  19532  *     _field_tcam_info_init
  19533  * Purpose:
  19534  *     Initialize TCAM related information in Field Control
  19535  *
  19536  * Parameters:
  19537  *     unit     - (IN) BCM device number.
  19538  *     stage_fc - (IN) Stage field control structure pointer.
  19539  *     fc       - (IN/OUT) Field control infoformation for device.
  19540  *
  19541  * Returns:
  19542  *    BCM_E_XXX
  19543  */
  19544 STATIC int
  19545 _field_tcam_info_init(int unit, _field_stage_t *stage_fc,  _field_control_t *fc)
  19546 {
  19547     soc_mem_t mem = INVALIDm;            /* FP tcam memory id for stage/device. */
  19548 
  19549     /* Input parameters check. */
  19550     if ((NULL == fc) || (NULL == stage_fc)) {
  19551         return (BCM_E_PARAM);
  19552     }
  19553 
  19554     if (_BCM_FIELD_STAGE_EXTERNAL == stage_fc->stage_id) {
  19555 #ifdef BCM_TRIUMPH_SUPPORT
  19556         if (SOC_IS_TRIUMPH(unit) || SOC_IS_TRIUMPH2(unit)) {
  19557             stage_fc->tcam_slices = 9;
  19558     }
  19559 #endif /* BCM_TRIUMPH_SUPPORT */
  19560         return BCM_E_NONE;
  19561     }
  19562 
  19563     if (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) {
  19564 #ifdef BCM_FIREBOLT_SUPPORT
  19565           if (SOC_IS_FBX(unit)) {
  19566               mem = FP_TCAMm;
  19567           }
  19568 #endif /* BCM_FIREBOLT_SUPPORT */
  19569 
  19570 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  19571     } else if (soc_feature(unit, soc_feature_field_multi_stage)) {
  19572 
  19573         if (_BCM_FIELD_STAGE_LOOKUP  == stage_fc->stage_id) {
  19574             mem = VFP_TCAMm;
  19575         } else if (_BCM_FIELD_STAGE_EGRESS  == stage_fc->stage_id) {
  19576             mem = EFP_TCAMm;
  19577         }
  19578 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT*/
  19579     } else {
  19580         return (BCM_E_UNAVAIL);
  19581     }
  19582 
  19583     if (INVALIDm == mem) {
  19584         return (BCM_E_UNAVAIL);
  19585     }
  19586 
  19587     /* Get tcam size. */
  19588     stage_fc->tcam_sz = soc_mem_index_count(unit, mem);
  19589 
  19590     /* Note fc->tcam_slices only counts internal slices. */
  19591     if (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) {
  19592         if (soc_feature(unit, soc_feature_field_slices2)) {
  19593             stage_fc->tcam_slices   = 2;
  19594         } else if (soc_feature(unit, soc_feature_field_slices4)) {
  19595             stage_fc->tcam_slices  = 4;
  19596         } else if (soc_feature(unit, soc_feature_field_slices8))  {
  19597             stage_fc->tcam_slices  = 8;
  19598         } else if (soc_feature(unit, soc_feature_field_slices12)) {
  19599             stage_fc->tcam_slices  = 12;
  19600         } else if (soc_feature(unit, soc_feature_field_slices10)) {
  19601             stage_fc->tcam_slices  = 10;
  19602         } else {
  19603             stage_fc->tcam_slices  = 16;
  19604         }
  19605 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  19606     } else if (soc_feature(unit, soc_feature_field_multi_stage)) {
  19607         if (_BCM_FIELD_STAGE_LOOKUP == stage_fc->stage_id) {
  19608             stage_fc->tcam_slices = 4;
  19609         } else if (_BCM_FIELD_STAGE_EGRESS == stage_fc->stage_id) {
  19610             stage_fc->tcam_slices = 4;
  19611         } else {
  19612             return (BCM_E_PARAM);
  19613         }
  19614 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  19615     } else {
  19616         return (BCM_E_PARAM);
  19617     }
  19618 
  19619 
  19620     /*  Check external tcam presence for ingress (default stage) */
  19621     /* Only for EasyRider; Triumph taken care of elsewhere */
  19622     fc->tcam_ext_numb = FP_EXT_TCAM_NONE;
  19623 
  19624     return (BCM_E_NONE);
  19625 }
  19626 
  19627 
  19628 /*
  19629  * Function:
  19630  *     _field_meter_pools_init
  19631  * Purpose:
  19632  *     Initialize field meter pools usage bitmap.
  19633  * Parameters:
  19634  *     unit         - (IN) BCM device number.
  19635  *     stage_fc     - (IN/OUT) Stage field control structure.
  19636  * Returns:
  19637  *     BCM_E_XXX
  19638  */
  19639 STATIC int
  19640 _field_meter_pools_init(int unit, _field_stage_t *stage_fc)
  19641 {
  19642     int              meter_pair_num;   /* Number of meter pairs.           */
  19643     int              pool_idx;         /* Meter pools iterator.            */
  19644     int              size;             /* Allocation size.                 */
  19645     uint16           pool_size;        /* Total number of meters in pool.  */
  19646 #ifdef BCM_TRIUMPH3_SUPPORT
  19647     int              rv;               /* Operation return status.         */
  19648 #endif
  19649 
  19650 
  19651     /* Input parameters check. */
  19652     if (NULL == stage_fc) {
  19653         return (BCM_E_PARAM);
  19654     }
  19655 
  19656     if (0 == (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)) {
  19657         return (BCM_E_PARAM);
  19658     }
  19659 
  19660     /* Make sure slices array is initialized. */
  19661     if (NULL == stage_fc->slices[_FP_DEF_INST]) {
  19662         return (BCM_E_INTERNAL);
  19663     }
  19664 
  19665     /* Set number of meters. */
  19666 #if defined(BCM_SCORPION_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
  19667     if (soc_feature(unit, soc_feature_field_meter_pools4)) {
  19668         meter_pair_num = _BCM_FIELD_SC_INGRESS_DOUBLE_WIDE_SLICE_SZ;
  19669     } else
  19670 #endif /* BCM_SCORPION_SUPPORT || BCM_TRIDENT_SUPPORT */
  19671 #if defined(BCM_TRIUMPH_SUPPORT)
  19672     if ((stage_fc->flags & _FP_STAGE_HALF_SLICE) &&  \
  19673         (!soc_feature(unit,soc_feature_field_slice_size128))) {
  19674         meter_pair_num = _BCM_FIELD_SLICE_SIZE(stage_fc, _FP_DEF_INST, 0);
  19675     } else
  19676 #endif /* BCM_TRIUMPH_SUPPORT */
  19677     {
  19678         meter_pair_num = _BCM_FIELD_SLICE_SIZE(stage_fc, _FP_DEF_INST, 0) >> 1;
  19679 #if defined(BCM_HURRICANE1_SUPPORT)
  19680         if (SOC_IS_HURRICANE(unit)) {
  19681             /* hurricane has 64 meter pairs/pool */
  19682             meter_pair_num = meter_pair_num / 2;
  19683         }
  19684 #endif /* BCM_HURRICANE1_SUPPORT */
  19685     }
  19686 
  19687     pool_size = (meter_pair_num * 2);
  19688 
  19689     /* Get number of meter pools for the device. */
  19690     if (soc_feature(unit, soc_feature_field_meter_pools4)) {
  19691         stage_fc->num_meter_pools = 4;
  19692     } else if (soc_feature(unit, soc_feature_field_meter_pools8)) {
  19693         stage_fc->num_meter_pools = 8;
  19694     } else if (soc_feature(unit, soc_feature_field_meter_pools12)) {
  19695         stage_fc->num_meter_pools = 12;
  19696     } else {
  19697         stage_fc->num_meter_pools = 16;
  19698     }
  19699 
  19700 #ifdef BCM_TRIUMPH3_SUPPORT
  19701     if (SOC_IS_TRIUMPH3(unit)) {
  19702         BCM_IF_ERROR_RETURN(_bcm_field_tr3_meter_pool_info(unit,
  19703                                                     stage_fc,
  19704                                                     &stage_fc->num_meter_pools,
  19705                                                     &meter_pair_num, &pool_size)
  19706                             );
  19707     }
  19708 #endif
  19709 
  19710     /* Total meters per pool = 2 * (No. of meter pairs) */
  19711     size = SHR_BITALLOCSIZE(meter_pair_num << 1);
  19712 
  19713     for (pool_idx = 0; pool_idx < stage_fc->num_meter_pools; pool_idx++) {
  19714         /* Allocate pool usage bitmap. */
  19715         stage_fc->meter_pool[_FP_DEF_INST][pool_idx] =
  19716             sal_alloc(sizeof(_field_meter_pool_t), "fp_meter_pool");
  19717         if (stage_fc->meter_pool[_FP_DEF_INST][pool_idx] == NULL) {
  19718             _field_meters_deinit (unit, stage_fc);
  19719             return (BCM_E_MEMORY);
  19720         }
  19721 
  19722         /* Initalize stage meter pool info. */
  19723         /* Pool is not in use. */
  19724         stage_fc->meter_pool[_FP_DEF_INST][pool_idx]->slice_id = -1;
  19725         /* Level not yet set */
  19726         stage_fc->meter_pool[_FP_DEF_INST][pool_idx]->level = -1;
  19727         /* Total number of meters in pool. */
  19728         stage_fc->meter_pool[_FP_DEF_INST][pool_idx]->pool_size = pool_size;
  19729         /* Number of valid meters in pool.*/
  19730         stage_fc->meter_pool[_FP_DEF_INST][pool_idx]->size = (meter_pair_num
  19731                                                                 * 2);
  19732         stage_fc->meter_pool[_FP_DEF_INST][pool_idx]->free_meters =
  19733             (meter_pair_num * 2);
  19734         stage_fc->meter_pool[_FP_DEF_INST][pool_idx]->num_meter_pairs =
  19735             meter_pair_num;
  19736         stage_fc->meter_pool[_FP_DEF_INST][pool_idx]->meter_bmp.w =
  19737             sal_alloc(size, "fp_meters_map");
  19738         if (stage_fc->meter_pool[_FP_DEF_INST][pool_idx]->meter_bmp.w == NULL) {
  19739             _field_meters_deinit(unit, stage_fc);
  19740             return (BCM_E_MEMORY);
  19741         }
  19742 
  19743         /* Reset pool usage bitmap. */
  19744         sal_memset(stage_fc->meter_pool[_FP_DEF_INST][pool_idx]->meter_bmp.w,
  19745             0, size);
  19746     }
  19747 
  19748 #ifdef BCM_TRIUMPH3_SUPPORT
  19749         /* Logical Pools supported in Triumph3.Init corresponding
  19750          * data structures.
  19751          */
  19752         if (SOC_IS_TRIUMPH3(unit)) {
  19753             rv =  _field_tr3_logical_meter_pools_init (unit, stage_fc);
  19754             if (rv == BCM_E_MEMORY) {
  19755                 _field_meters_deinit(unit, stage_fc);
  19756             }
  19757             return (rv);
  19758         }
  19759 #endif
  19760     return BCM_E_NONE;
  19761 }
  19762 
  19763 
  19764 STATIC int
  19765 _field_cntr_pool_info(int            unit,
  19766                       _field_stage_t *stage_fc,
  19767                       unsigned       *cntrs_per_pool
  19768                       )
  19769 {
  19770     stage_fc->num_cntr_pools = 0;
  19771 
  19772 #ifdef BCM_TRIUMPH3_SUPPORT
  19773     if (SOC_IS_TRIUMPH3(unit)) {
  19774         BCM_IF_ERROR_RETURN(_bcm_field_tr3_cntr_pool_info(unit,
  19775                                                           stage_fc,
  19776                                                           &stage_fc->num_cntr_pools,
  19777                                                           cntrs_per_pool
  19778                                                           )
  19779                             );
  19780     }
  19781 #endif
  19782 
  19783     return (BCM_E_NONE);
  19784 }
  19785 
  19786 
  19787 STATIC int
  19788 _field_cntr_pools_init(int unit, _field_stage_t *stage_fc)
  19789 {
  19790     int                errcode = BCM_E_NONE;
  19791     unsigned           cntrs_per_pool, bmap_size_bytes, n;
  19792     _field_cntr_pool_t **pp, *p;
  19793 
  19794     /* Input parameters check. */
  19795     if (NULL == stage_fc) {
  19796         return (BCM_E_PARAM);
  19797     }
  19798 
  19799     /* Make sure slices array is initialized. */
  19800     if (NULL == stage_fc->slices[_FP_DEF_INST]) {
  19801         return (BCM_E_INTERNAL);
  19802     }
  19803 
  19804     BCM_IF_ERROR_RETURN(_field_cntr_pool_info(unit,
  19805                                               stage_fc,
  19806                                               &cntrs_per_pool
  19807                                               )
  19808                         );
  19809 
  19810     bmap_size_bytes = SHR_BITALLOCSIZE(cntrs_per_pool);
  19811 
  19812     for (pp = stage_fc->cntr_pool, n = stage_fc->num_cntr_pools; n; --n, ++pp) {
  19813         if ((p = SAL_ALLOC_T(_field_cntr_pool_t, 1)) == 0) {
  19814             errcode = BCM_E_MEMORY;
  19815             break;
  19816         }
  19817 
  19818         p->slice_id = -1;
  19819         p->size = p->free_cntrs = cntrs_per_pool;
  19820         if ((p->cntr_bmp.w = (SHR_BITDCL *) sal_alloc(bmap_size_bytes, " ")) == 0) {
  19821             sal_free(p);
  19822             errcode = BCM_E_MEMORY;
  19823             break;
  19824         }
  19825         sal_memset(p->cntr_bmp.w, 0, bmap_size_bytes);
  19826 
  19827         *pp = p;
  19828     }
  19829 
  19830     if (errcode != BCM_E_NONE) {
  19831         _field_counters_deinit(unit, stage_fc);
  19832     }
  19833 
  19834     return (errcode);
  19835 }
  19836 
  19837 
  19838 /*
  19839  * Function:
  19840  *     _field_meters_init
  19841  * Purpose:
  19842  *     Initialize field slice meters usage bitmap.
  19843  *
  19844  * Parameters:
  19845  *     unit         - (IN) BCM device number.
  19846  *     fc           - (IN) Field control structure.
  19847  *     stage_fc     - (IN/OUT) Stage field control structure.
  19848  *
  19849  * Returns:
  19850  *     BCM_E_XXX
  19851  * Notes:
  19852  *     Triumph External stage uses the same meter pool as Ingress
  19853  *     It is inited in _field_external_meters_init
  19854  */
  19855 STATIC int
  19856 _field_meters_init(int unit, _field_stage_t *stage_fc)
  19857 {
  19858     int              slice_idx;        /* Slices iterator.          */
  19859     int              size;             /* Allocation size.          */
  19860     _field_slice_t   *fs;              /* Slice config structure.   */
  19861 
  19862     /* Input parameters check. */
  19863     if (NULL == stage_fc) {
  19864         return (BCM_E_PARAM);
  19865     }
  19866 
  19867 
  19868     /* External config was not processed yet - don't initialize meters.
  19869      * Lookup stage has no meter support.
  19870      */
  19871     if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXTERNAL
  19872         || stage_fc->stage_id == _BCM_FIELD_STAGE_LOOKUP) {
  19873         return (BCM_E_NONE);
  19874     }
  19875 
  19876     /* Make sure slices array is initialized. */
  19877     if (NULL == stage_fc->slices[_FP_DEF_INST]) {
  19878         return (BCM_E_INTERNAL);
  19879     }
  19880 
  19881     /*
  19882      * For devices with global meter pools
  19883      * Initialize meter pools, skip slice bounded meters .
  19884      */
  19885     if (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) {
  19886         return _field_meter_pools_init(unit, stage_fc);
  19887     }
  19888 
  19889     size = SHR_BITALLOCSIZE(_BCM_FIELD_SLICE_SIZE(stage_fc, _FP_DEF_INST, 0));
  19890 
  19891     /* Iterate over slices & initialize meter infor. */
  19892     for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) {
  19893         fs = stage_fc->slices[_FP_DEF_INST] + slice_idx;
  19894 
  19895         /* Allocate meter usage bitmap. */
  19896         fs->meter_bmp.w = sal_alloc(size, "fp_meters_map");
  19897         if (NULL == fs->meter_bmp.w) {
  19898             _field_meters_deinit(unit, stage_fc);
  19899             return (BCM_E_MEMORY);
  19900         }
  19901 
  19902         /* Set slice meter count & reset usage bitmap. */
  19903         fs->meters_count = _BCM_FIELD_SLICE_SIZE(stage_fc, _FP_DEF_INST, 0);
  19904         sal_memset(fs->meter_bmp.w, 0, size);
  19905     }
  19906     return (BCM_E_NONE);
  19907 }
  19908 
  19909 /*
  19910  * Function:
  19911  *     _field_external_meters_init
  19912  * Purpose:
  19913  *     Initialize field meters for external FP
  19914  * Parameters:
  19915  *     unit         - (IN) BCM device number.
  19916  *     fc           - (IN) Field control structure
  19917  * Returns:
  19918  *     BCM_E_XXX
  19919  */
  19920 STATIC int
  19921 _field_external_meters_init(int unit, _field_control_t *fc)
  19922 {
  19923     int i;
  19924     _field_stage_t *stage_ingress, *stage_external, *stage_p;
  19925 
  19926     stage_external = stage_ingress = NULL;
  19927     stage_p = fc->stages;
  19928 
  19929     while (stage_p) {
  19930         if (stage_p->stage_id == _BCM_FIELD_STAGE_INGRESS) {
  19931             stage_ingress = stage_p;
  19932         } else if (stage_p->stage_id == _BCM_FIELD_STAGE_EXTERNAL) {
  19933             stage_external = stage_p;
  19934         }
  19935         stage_p = stage_p->next;
  19936     }
  19937     if ((stage_ingress == NULL) || (stage_external == NULL)) {
  19938         return (BCM_E_INTERNAL);
  19939     }
  19940 
  19941     stage_external->flags |=  _FP_STAGE_GLOBAL_METER_POOLS;
  19942     stage_external->num_meter_pools = stage_ingress->num_meter_pools;
  19943     for (i = 0; i < stage_external->num_meter_pools; i++) {
  19944         if (stage_ingress->meter_pool[_FP_DEF_INST][i] == NULL) {
  19945             return (BCM_E_INTERNAL);
  19946         }
  19947         stage_external->meter_pool[_FP_DEF_INST][i]
  19948             = stage_ingress->meter_pool[_FP_DEF_INST][i];
  19949     }
  19950     return (BCM_E_NONE);
  19951 }
  19952 
  19953 /*
  19954  * Function:
  19955  *     _field_slice_counters_alloc
  19956  * Purpose:
  19957  *     Allocate counters usage bitmap for a slice.
  19958  *
  19959  * Parameters:
  19960  *     unit        - (IN) BCM device number.
  19961  *     fs          - (IN/OUT) Slice control structure.
  19962  *
  19963  * Returns:
  19964  *     BCM_E_XXX
  19965  */
  19966 STATIC int
  19967 _field_slice_counters_alloc(int unit, _field_slice_t *fs)
  19968 {
  19969     int size;            /* Allocation size. */
  19970     /* Input parameters check. */
  19971     if (NULL == fs) {
  19972         return (BCM_E_PARAM);
  19973     }
  19974 
  19975     size = SHR_BITALLOCSIZE(fs->counters_count);
  19976     fs->counter_bmp.w = sal_alloc(size, "fp_counter_map");
  19977     if (NULL == fs->counter_bmp.w) {
  19978         return (BCM_E_MEMORY);
  19979     }
  19980     sal_memset(fs->counter_bmp.w, 0, size);
  19981     return (BCM_E_NONE);
  19982 }
  19983 
  19984 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  19985 /*
  19986  * Function:
  19987  *     _field_slice_counters_share
  19988  * Purpose:
  19989  *     Share counters usage bitmap between slices.
  19990  *
  19991  * Parameters:
  19992  *     unit        - (IN) BCM device number.
  19993  *     stage_fc    - (IN/OUT) Stage field control structure.
  19994  *     slice_src   - (IN) Slice sharing counters.
  19995  *     slice_dst   - (IN) Slice receivingshared counters.
  19996  *
  19997  * Returns:
  19998  *     BCM_E_XXX
  19999  */
  20000 STATIC int
  20001 _field_slice_counters_share(int unit, _field_stage_t *stage_fc,
  20002                             int slice_src, int slice_dst)
  20003 {
  20004 
  20005     /* Input parameters check. */
  20006     if (NULL == stage_fc) {
  20007         return (BCM_E_PARAM);
  20008     }
  20009 
  20010     if (((slice_src < 0) || (slice_src >= stage_fc->tcam_slices)) ||
  20011         ((slice_dst < 0) || (slice_dst >= stage_fc->tcam_slices))) {
  20012         return (BCM_E_PARAM);
  20013     }
  20014 
  20015     stage_fc->slices[_FP_DEF_INST][slice_dst].counter_bmp.w =
  20016         stage_fc->slices[_FP_DEF_INST][slice_src].counter_bmp.w;
  20017 
  20018     return (BCM_E_NONE);
  20019 }
  20020 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  20021 
  20022 
  20023 /*
  20024  * Function:
  20025  *     _field_counter_memacc_alloc
  20026  * Purpose:
  20027  *     Initialize software cached memory access info for field counters
  20028  *
  20029  * Parameters:
  20030  *     unit         - (IN) BCM device number.
  20031  *     mem          - (IN) Counter memory.
  20032  *     descr        - (IN) Counter descriptor.
  20033  *     ptr          - (OUT) Allocated pointer.
  20034  * Returns:
  20035  *     BCM_E_XXX
  20036  */
  20037 STATIC int
  20038 _field_counter_memacc_alloc(int unit, soc_memacc_t **memacc_ptr)
  20039 {
  20040     int mem_size;
  20041 
  20042     /* Input parameters check. */
  20043     if (NULL == memacc_ptr) {
  20044         return (BCM_E_PARAM);
  20045     }
  20046 
  20047     mem_size = _FIELD_COUNTER_MEMACC_NUM * sizeof(soc_memacc_t);
  20048     *memacc_ptr = sal_alloc(mem_size, "FP counter memory access cache");
  20049     if (NULL == *memacc_ptr) {
  20050         return (BCM_E_MEMORY);
  20051     }
  20052     sal_memset(*memacc_ptr, 0, mem_size);
  20053     return (BCM_E_NONE);
  20054 }
  20055 /*
  20056  * Function:
  20057  *     _field_counter_collect_init
  20058  * Purpose:
  20059  *     Initialize software field 64bit counters.
  20060  *
  20061  * Parameters:
  20062  *     unit         - (IN) BCM device number.
  20063  *     fc           - (IN) Field control structure.
  20064  *     stage_fc     - (IN/OUT) Stage field control structure.
  20065  *
  20066  * Returns:
  20067  *     BCM_E_XXX
  20068  */
  20069 STATIC int
  20070 _field_counter_collect_init(int unit, _field_control_t *fc,
  20071                             _field_stage_t *stage_fc)
  20072 {
  20073     soc_mem_t counter_x_mem;        /* Pipeline 1 counters memory. */
  20074     soc_mem_t counter_y_mem;        /* Pipeline 2 counters memory. */
  20075     soc_memacc_t *memacc_list;      /* Memory access cache list.   */
  20076     int retval = BCM_E_NONE;        /* Operation return status.    */
  20077 
  20078     /* Input parameters check. */
  20079     if (NULL == stage_fc) {
  20080         return (BCM_E_PARAM);
  20081     }
  20082 
  20083 #if defined(BCM_TOMAHAWK_SUPPORT)
  20084     if (stage_fc->flags & _FP_STAGE_MULTI_PIPE_COUNTERS) {
  20085         if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  20086             return BCM_E_NONE;
  20087         }
  20088     }
  20089 #endif
  20090 
  20091     /*
  20092      * For counter collection in chunks
  20093      *     Relevant for External Counter Table of Triumph
  20094      */
  20095     stage_fc->counter_collect_table = 0;
  20096     stage_fc->counter_collect_index = 0;
  20097 
  20098     BCM_IF_ERROR_RETURN(_field_counter_mem_get(unit, stage_fc,
  20099                                                &counter_x_mem, &counter_y_mem));
  20100 
  20101     /* Check if stage has counters. */
  20102     if (INVALIDm == counter_x_mem) {
  20103         return (BCM_E_NONE);
  20104     }
  20105 
  20106     /* Allocate space for cached counter memory access info */
  20107     retval = _field_counter_memacc_alloc(unit,
  20108                                    &(stage_fc->_field_memacc_counters));
  20109     if (BCM_FAILURE(retval)) {
  20110         return (retval);
  20111     }
  20112     memacc_list = stage_fc->_field_memacc_counters;
  20113 
  20114 #if defined(BCM_TRX_SUPPORT)
  20115     if (stage_fc->flags & _FP_STAGE_SEPARATE_PACKET_BYTE_COUNTERS) {
  20116         retval = _field_counter32_collect_alloc(unit, counter_x_mem,
  20117                                                 "FP pipeline X counters",
  20118                                                 &stage_fc->_field_x32_counters);
  20119         if (BCM_FAILURE(retval)) {
  20120             _field_counter_collect_deinit(unit, stage_fc);
  20121             return (retval);
  20122         }
  20123 
  20124         retval = _field_counter64_collect_alloc(unit, counter_x_mem,
  20125                                                 "FP pipeline X byte counters",
  20126                                                 &stage_fc->_field_x64_counters);
  20127         if(BCM_FAILURE(retval)) {
  20128             _field_counter_collect_deinit(unit, stage_fc);
  20129             return (retval);
  20130         }
  20131 
  20132         retval = soc_memacc_init(unit, counter_x_mem, BYTE_COUNTERf,
  20133                                  &(memacc_list[_FIELD_COUNTER_MEMACC_BYTE]));
  20134         if(BCM_FAILURE(retval)) {
  20135             _field_counter_collect_deinit(unit, stage_fc);
  20136             return (retval);
  20137         }
  20138 
  20139         retval = soc_memacc_init(unit, counter_x_mem, PACKET_COUNTERf,
  20140                             &(memacc_list[_FIELD_COUNTER_MEMACC_PACKET]));
  20141         if(BCM_FAILURE(retval)) {
  20142             _field_counter_collect_deinit(unit, stage_fc);
  20143             return (retval);
  20144         }
  20145 
  20146 #if defined (BCM_SCORPION_SUPPORT)
  20147         if (soc_feature(unit, soc_feature_two_ingress_pipes)) {
  20148             retval = _field_counter32_collect_alloc(unit, counter_y_mem,
  20149                                                     "FP pipeline Y counters",
  20150                                                     &stage_fc->_field_y32_counters);
  20151             if(BCM_FAILURE(retval)) {
  20152                 _field_counter_collect_deinit(unit, stage_fc);
  20153                 return (retval);
  20154             }
  20155 
  20156             retval = _field_counter64_collect_alloc(unit, counter_y_mem,
  20157                                                     "FP pipeline Y byte counters",
  20158                                                     &stage_fc->_field_y64_counters);
  20159             if(BCM_FAILURE(retval)) {
  20160                 _field_counter_collect_deinit(unit, stage_fc);
  20161                 return (retval);
  20162             }
  20163 
  20164             retval = soc_memacc_init(unit, counter_y_mem, BYTE_COUNTERf,
  20165                          &(memacc_list[_FIELD_COUNTER_MEMACC_BYTE_Y]));
  20166             if(BCM_FAILURE(retval)) {
  20167                 _field_counter_collect_deinit(unit, stage_fc);
  20168                 return (retval);
  20169             }
  20170 
  20171             retval = soc_memacc_init(unit, counter_y_mem, PACKET_COUNTERf,
  20172                          &(memacc_list[_FIELD_COUNTER_MEMACC_PACKET_Y]));
  20173             if(BCM_FAILURE(retval)) {
  20174                 _field_counter_collect_deinit(unit, stage_fc);
  20175                 return (retval);
  20176             }
  20177 
  20178         }
  20179 #endif /* BCM_SCORPION_SUPPORT */
  20180     } else
  20181 #endif /* BCM_TRX_SUPPORT */
  20182 
  20183 #if defined(BCM_BRADLEY_SUPPORT)
  20184     if (soc_feature(unit, soc_feature_two_ingress_pipes)) {
  20185         retval = _field_counter64_collect_alloc(unit, counter_x_mem,
  20186                                                 "FP pipeline X byte cntrs",
  20187                                                 &stage_fc->_field_x64_counters);
  20188         if(BCM_FAILURE(retval)) {
  20189             _field_counter_collect_deinit(unit, stage_fc);
  20190             return (retval);
  20191         }
  20192 
  20193         retval = soc_memacc_init(unit, counter_x_mem, COUNTERf,
  20194                      &(memacc_list[_FIELD_COUNTER_MEMACC_COUNTER]));
  20195         if(BCM_FAILURE(retval)) {
  20196             _field_counter_collect_deinit(unit, stage_fc);
  20197             return (retval);
  20198         }
  20199 
  20200         retval = _field_counter64_collect_alloc(unit, counter_y_mem,
  20201                                                 "FP pipeline Y byte cntrs",
  20202                                                 &stage_fc->_field_y64_counters);
  20203         if(BCM_FAILURE(retval)) {
  20204             _field_counter_collect_deinit(unit, stage_fc);
  20205             return (retval);
  20206         }
  20207 
  20208         retval = soc_memacc_init(unit, counter_y_mem, COUNTERf,
  20209                      &(memacc_list[_FIELD_COUNTER_MEMACC_COUNTER_Y]));
  20210         if(BCM_FAILURE(retval)) {
  20211             _field_counter_collect_deinit(unit, stage_fc);
  20212             return (retval);
  20213         }
  20214     } else
  20215 #endif /* BCM_BRADLEY_SUPPORT */
  20216     {
  20217         retval = _field_counter32_collect_alloc(unit, counter_x_mem,
  20218                                                 "FP pipeline X counters",
  20219                                                 &stage_fc->_field_x32_counters);
  20220         if(BCM_FAILURE(retval)) {
  20221             _field_counter_collect_deinit(unit, stage_fc);
  20222             return (retval);
  20223         }
  20224 
  20225         retval = soc_memacc_init(unit, counter_x_mem, COUNTERf,
  20226                      &(memacc_list[_FIELD_COUNTER_MEMACC_COUNTER]));
  20227         if(BCM_FAILURE(retval)) {
  20228             _field_counter_collect_deinit(unit, stage_fc);
  20229             return (retval);
  20230         }
  20231     }
  20232 
  20233     return (retval);
  20234 }
  20235 
  20236 /*
  20237  * Function:
  20238  *     _field_counters_init
  20239  * Purpose:
  20240  *     Initialize field slice counters bitmap.
  20241  *
  20242  * Parameters:
  20243  *     unit         - (IN) BCM device number.
  20244  *     fc           - (IN) Field control structure.
  20245  *     stage_fc     - (IN/OUT) Stage field control structure.
  20246  *
  20247  * Returns:
  20248  *     BCM_E_XXX
  20249  */
  20250 
  20251 STATIC int
  20252 _field_counters_init(int unit, _field_control_t *fc,
  20253                          _field_stage_t *stage_fc)
  20254 {
  20255     _field_slice_t   *fs;                 /* Slice config structure.    */
  20256     int              slice_idx;           /* Slices iterator.           */
  20257     int              retval;              /* Operation return value.    */
  20258     int              cntr_share = FALSE;  /* Share counter with slice 0 */
  20259 
  20260     /* Input parameters check. */
  20261     if (NULL == stage_fc) {
  20262         return (BCM_E_PARAM);
  20263     }
  20264 
  20265     /* Make sure slices array is initialized. */
  20266     if (NULL == stage_fc->slices[_FP_DEF_INST]) {
  20267         return (BCM_E_INTERNAL);
  20268     }
  20269 
  20270     /* Allocate software 64 bit counters image. */
  20271     BCM_IF_ERROR_RETURN(_field_counter_collect_init(unit, fc, stage_fc));
  20272 
  20273 #if defined(BCM_TRIUMPH_SUPPORT)     \
  20274     || defined(BCM_TRIUMPH2_SUPPORT) \
  20275     || defined(BCM_TRIUMPH3_SUPPORT)
  20276     /*
  20277      * There is an 1-1 mapping between rules and counters
  20278      * for external FP, so no bitmap needs to be allocated (Triumph and
  20279      * Triumph2); Triumph3 EXTFP can access only flex counters.
  20280      */
  20281     if (_BCM_FIELD_STAGE_EXTERNAL == stage_fc->stage_id) {
  20282         return (BCM_E_NONE);
  20283     }
  20284 #endif /* BCM_TRIUMPH_SUPPORT || BCM_TRIUMPH2_SUPPORT || BCM_TRIUMPH3_SUPPORT */
  20285 
  20286     if (stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS) {
  20287         return (_field_cntr_pools_init(unit, stage_fc));
  20288     }
  20289 
  20290     /* Allocate counters for each of the tcam slices. */
  20291     for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) {
  20292         fs = stage_fc->slices[_FP_DEF_INST] + slice_idx;
  20293 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  20294         if (_BCM_FIELD_STAGE_LOOKUP == stage_fc->stage_id) {
  20295             fs->counters_count = 0;
  20296             continue;
  20297         } else if (_BCM_FIELD_STAGE_EGRESS == stage_fc->stage_id) {
  20298             fs->counters_count = soc_mem_index_count(unit, EFP_COUNTER_TABLEm);
  20299 
  20300             if(stage_fc->flags & _FP_STAGE_HALF_SLICE) {
  20301                 fs->counters_count = fs->counters_count / 2;
  20302             }
  20303             if (slice_idx) {
  20304                 cntr_share = TRUE;
  20305             }
  20306         } else
  20307 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  20308         {
  20309            if (soc_feature(unit,soc_feature_field_slice_size128)) {
  20310               fs->counters_count = fs->entry_count * 2;     /*Counters are double the number of TCAM entries*/
  20311            } else {
  20312               fs->counters_count = fs->entry_count;
  20313            }
  20314         }
  20315 
  20316         if (cntr_share) {
  20317 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  20318             /* Share counters with slice zero(Global counter pool). */
  20319             retval = _field_slice_counters_share(unit, stage_fc,
  20320                                                  0, slice_idx);
  20321             if (BCM_FAILURE(retval)) {
  20322                 _field_counters_deinit(unit, stage_fc);
  20323                 return (retval);
  20324             }
  20325 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  20326         } else {
  20327             /* Allocate new set of counters for the slice. */
  20328             retval = _field_slice_counters_alloc(unit, fs);
  20329             if (BCM_FAILURE(retval)) {
  20330                 _field_counters_deinit(unit, stage_fc);
  20331                 return (retval);
  20332             }
  20333         }
  20334     }
  20335     return (BCM_E_NONE);
  20336 }
  20337 
  20338 /*
  20339  * Function:
  20340  *     _field_entries_init
  20341  * Purpose:
  20342  *     Allocate the memory for entries in all the slices of the stage.
  20343  *     External TCAM (for Triumph) is taken care of in _bcm_tr_field_init.
  20344  *     Entries  will be de-allocated in bcm_esw_field_detach
  20345  *
  20346  * Parameters:
  20347  *     unit         - (IN) BCM device number.
  20348  *     stage_fc     - (IN/OUT) Stage field control structure.
  20349  *
  20350  * Returns:
  20351  *     BCM_E_XXX
  20352  */
  20353 STATIC int
  20354 _field_entries_init(int unit, _field_stage_t *stage_fc)
  20355 {
  20356     int              slice_idx;    /* Slices iterator.                      */
  20357     int              tcam_idx;     /* Slice first entry tcam index tracker. */
  20358     int              mem_size;     /* Allocation size.                      */
  20359     int              entry_ratio;  /* Invalid entries ratio.                */
  20360     int              entry_ratio_per_slice; /* Invalid entries ratio for each
  20361                                                slice. */
  20362     _field_slice_t   *fs;          /* Slice config structure.               */
  20363 
  20364     /* Input parameters check. */
  20365     if (NULL == stage_fc)  {
  20366         return (BCM_E_PARAM);
  20367     }
  20368 
  20369     /* Triumph external slice handled in _bcm_tr_field_init. */
  20370     if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXTERNAL) {
  20371         return (BCM_E_NONE);
  20372     }
  20373 
  20374     /* Make sure slices array is initialized. */
  20375     if (NULL == stage_fc->slices[_FP_DEF_INST]) {
  20376         return (BCM_E_INTERNAL);
  20377     }
  20378 
  20379     entry_ratio = (stage_fc->flags & _FP_STAGE_QUARTER_SLICE) ? 4:
  20380                       ((stage_fc->flags & _FP_STAGE_HALF_SLICE) ? 2 : 1);
  20381 
  20382     /* Iterate over all stage slices and allocated entries for each slice. */
  20383     for (slice_idx = 0, tcam_idx = 0;
  20384          slice_idx < stage_fc->tcam_slices; slice_idx++) {
  20385 
  20386         /* Default entry ratio per each slice equals to global entry ratio */
  20387         entry_ratio_per_slice = entry_ratio;
  20388 
  20389         /* Get slice control structure pointer. */
  20390         fs = stage_fc->slices[_FP_DEF_INST] + slice_idx;
  20391 
  20392         /* Get number of entries in the slice. */
  20393 #if defined(BCM_SCORPION_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT)
  20394         if ((soc_feature(unit, soc_feature_field_ingress_two_slice_types)) &&
  20395             (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id)) {
  20396             if (SOC_IS_TD2_TT2(unit)){
  20397                 if (slice_idx < _BCM_FIELD_TD2_INGRESS_DOUBLE_WIDE_SLICE0) {
  20398                     fs->entry_count =
  20399                         _BCM_FIELD_TD2_INGRESS_LARGE_SLICE_SZ;
  20400                     if (soc_feature(unit,
  20401                         soc_feature_field_stage_ingress_512_half_slice)) {
  20402                         entry_ratio_per_slice = 2;
  20403                         fs->entry_count /= entry_ratio_per_slice;
  20404                     }
  20405                 } else {
  20406                     fs->entry_count =
  20407                         _BCM_FIELD_TD2_INGRESS_SMALL_SLICE_SZ;
  20408                 }
  20409 
  20410 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
  20411                 /* In Trident2 Plus number of entries in each slice is 4
  20412                  * times entries in Trident2. For OTP variants of Td2Plus
  20413                  * entry ratio will be used to reduce the entry count
  20414                  */
  20415                 if (SOC_IS_TD2P_TT2P(unit)) {
  20416                     fs->entry_count = ((fs->entry_count * 4) / entry_ratio);
  20417                 }
  20418 #endif
  20419 #if defined(BCM_APACHE_SUPPORT)
  20420                 /* In Apache number of entries in each slice is 2
  20421                  * times entries in Trident2.
  20422                  */
  20423                 if(SOC_IS_APACHE(unit)) {
  20424                     fs->entry_count = (fs->entry_count * 2) / entry_ratio;
  20425                 }
  20426 #endif
  20427             } else if (SOC_IS_TD_TT(unit)){
  20428                 if (slice_idx < _BCM_FIELD_TD_INGRESS_DOUBLE_WIDE_SLICE0) {
  20429                     fs->entry_count =
  20430                         _BCM_FIELD_TD_INGRESS_SINGLE_WIDE_SLICE_SZ;
  20431                 } else {
  20432                     fs->entry_count =
  20433                         _BCM_FIELD_TD_INGRESS_DOUBLE_WIDE_SLICE_SZ;
  20434                 }
  20435             } else {
  20436                 if (slice_idx < _BCM_FIELD_SC_INGRESS_DOUBLE_WIDE_SLICE0) {
  20437                     fs->entry_count =
  20438                         _BCM_FIELD_SC_INGRESS_SINGLE_WIDE_SLICE_SZ;
  20439                 } else {
  20440                     fs->entry_count =
  20441                         _BCM_FIELD_SC_INGRESS_DOUBLE_WIDE_SLICE_SZ;
  20442                 }
  20443             }
  20444         } else
  20445 #endif /* BCM_SCORPION_SUPPORT || BCM_TRIDENT_SUPPORT */
  20446         {
  20447             fs->entry_count = stage_fc->tcam_sz /  \
  20448                             (entry_ratio_per_slice * stage_fc->tcam_slices);
  20449         }
  20450 
  20451         /* Allocate slice entries pointers array. */
  20452         mem_size = fs->entry_count * sizeof (void *);
  20453         _FP_XGS3_ALLOC(fs->entries, mem_size, "array of entry pointers");
  20454         if (fs->entries == NULL) {
  20455             /* Allocation failed free all previously allocated entries. */
  20456             _bcm_field_stage_entries_free(unit, stage_fc);
  20457             return (BCM_E_MEMORY);
  20458         }
  20459         fs->start_tcam_idx = tcam_idx;
  20460         tcam_idx += fs->entry_count * entry_ratio_per_slice;
  20461         fs->free_count = fs->entry_count;
  20462     }
  20463     return (BCM_E_NONE);
  20464 }
  20465 
  20466 /*
  20467  * Function:
  20468  *     _field_slices_init
  20469  * Purpose:
  20470  *     Allocate the memory for slices.
  20471  *     Initialize slice specific flags, parameters.
  20472  *
  20473  * Parameters:
  20474  *     unit         - (IN) BCM device number.
  20475  *     stage_fc     - (IN/OUT) Stage field control structure.
  20476  *     fc           - (IN/OUT) Field control structure.
  20477  *
  20478  * Returns:
  20479  *     BCM_E_XXX
  20480  */
  20481 STATIC int
  20482 _field_slices_init(int unit, _field_stage_t *stage_fc, _field_control_t *fc)
  20483 {
  20484     struct _field_slice_s *fs; /* Slice info.                    */
  20485     int             slice_idx; /* Slice iteration index.         */
  20486     int              mem_size; /* Memory allocation buffer size. */
  20487 
  20488     /* Input parameters check. */
  20489     if (NULL == stage_fc) {
  20490         return (BCM_E_PARAM);
  20491     }
  20492 
  20493     /* Allocate slices info. */
  20494     mem_size = stage_fc->tcam_slices * sizeof(struct _field_slice_s);
  20495     fs = sal_alloc(mem_size, "stage slices info");
  20496     if (NULL == fs) {
  20497         return (BCM_E_MEMORY);
  20498     }
  20499 
  20500     sal_memset(fs, 0, mem_size);
  20501     stage_fc->slices[_FP_DEF_INST] = fs;
  20502 
  20503     /* Initialize stage slices info. */
  20504     for (slice_idx = 0; slice_idx < stage_fc->tcam_slices; slice_idx++) {
  20505         fs[slice_idx].slice_number = slice_idx;
  20506         fs[slice_idx].stage_id = stage_fc->stage_id;
  20507         fs[slice_idx].next = NULL;
  20508         fs[slice_idx].prev = NULL;
  20509         fs[slice_idx].doublewide_key_select = _FP_SELCODE_DONT_CARE;
  20510         fs[slice_idx].src_class_sel = _FP_SELCODE_DONT_CARE;
  20511         fs[slice_idx].dst_class_sel = _FP_SELCODE_DONT_CARE;
  20512         fs[slice_idx].intf_class_sel = _FP_SELCODE_DONT_CARE;
  20513         fs[slice_idx].loopback_type_sel = _FP_SELCODE_DONT_CARE;
  20514         fs[slice_idx].ingress_entity_sel = _FP_SELCODE_DONT_CARE;
  20515         fs[slice_idx].src_entity_sel = _FP_SELCODE_DONT_CARE;
  20516         fs[slice_idx].dst_fwd_entity_sel = _FP_SELCODE_DONT_CARE;
  20517         fs[slice_idx].fwd_field_sel = _FP_SELCODE_DONT_CARE;
  20518         fs[slice_idx].ttl_class_sel = _FP_SELCODE_DONT_CARE;
  20519         fs[slice_idx].tcp_class_sel = _FP_SELCODE_DONT_CARE;
  20520         fs[slice_idx].tos_class_sel = _FP_SELCODE_DONT_CARE;
  20521 
  20522         /* Set intraslice  capable flag if appropriate. */
  20523 #if defined(BCM_HURRICANE_SUPPORT)
  20524         if (SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) ||
  20525             SOC_IS_GREYHOUND2(unit)) {
  20526             fs[slice_idx].slice_flags |= _BCM_FIELD_SLICE_INTRASLICE_CAPABLE;
  20527         }
  20528 #endif
  20529 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  20530         if (soc_feature(unit, soc_feature_field_multi_stage)) {
  20531             if ((_BCM_FIELD_STAGE_INGRESS != stage_fc->stage_id) &&
  20532                 (_BCM_FIELD_STAGE_LOOKUP  != stage_fc->stage_id)) {
  20533                 continue;
  20534             }
  20535 
  20536 #if defined(BCM_SCORPION_SUPPORT) || defined (BCM_TRIDENT_SUPPORT)
  20537             /* Skip single wide slices on 5682x devices. */
  20538             if ((soc_feature(unit, soc_feature_field_ingress_two_slice_types)) &&
  20539                 (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id)) {
  20540                 if (SOC_IS_TD2_TT2(unit)) {
  20541                     if (_BCM_FIELD_TD2_INGRESS_DOUBLE_WIDE_SLICE0 <= slice_idx) {
  20542                         fs[slice_idx].slice_flags |= _BCM_FIELD_SLICE_SIZE_SMALL;
  20543                         continue;
  20544                     }
  20545                 } else if (SOC_IS_TD_TT(unit)) {
  20546                     if (_BCM_FIELD_TD_INGRESS_DOUBLE_WIDE_SLICE0 > slice_idx) {
  20547                         fs[slice_idx].slice_flags |= _BCM_FIELD_SLICE_SIZE_SMALL;
  20548                         continue;
  20549                     }
  20550                 } else {
  20551                     if (_BCM_FIELD_SC_INGRESS_DOUBLE_WIDE_SLICE0 > slice_idx) {
  20552                         fs[slice_idx].slice_flags |= _BCM_FIELD_SLICE_SIZE_SMALL;
  20553                         continue;
  20554                     }
  20555                 }
  20556                 fs[slice_idx].slice_flags |= _BCM_FIELD_SLICE_SIZE_LARGE;
  20557 
  20558                 /* TD2: Intra Slice mode not available from IFP stage */
  20559                 if (SOC_IS_TD_TT(unit)) {
  20560                     continue;
  20561                 }
  20562             }
  20563 #ifdef BCM_MONTEREY_SUPPORT
  20564             /* Monterey: Intra Slice mode not available from IFP stage */
  20565             if (SOC_IS_MONTEREY(unit) &&
  20566                     (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id)) {
  20567                 continue;
  20568             }
  20569 #endif
  20570 #endif /* BCM_SCORPION_SUPPORT || BCM_TRIDENT_SUPPORT */
  20571             fs[slice_idx].slice_flags |= _BCM_FIELD_SLICE_INTRASLICE_CAPABLE;
  20572         }
  20573 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  20574     }
  20575 
  20576     return (BCM_E_NONE);
  20577 }
  20578 
  20579 /*
  20580  * Function:
  20581  *     _field_stage_add
  20582  *
  20583  * Purpose:
  20584  *     Add stage to field processor pipeline.
  20585  *
  20586  * Parameters:
  20587  *     unit - (IN) BCM device number.
  20588  *     fc -   (IN/OUT)Field control info for device.
  20589  *
  20590  * Returns:
  20591  *     BCM_E_NONE   - Success
  20592  *     BCM_E_MEMORY - Allocation failure
  20593  */
  20594 STATIC int
  20595 _field_stage_add(int unit, _field_control_t *fc, _field_stage_id_t stage_id)
  20596 {
  20597     _field_stage_t *stage_fc; /* Stage info.                 */
  20598     int    ret_val;           /* Operation return value.     */
  20599     int    idx;
  20600     int    map_id;
  20601 #if defined(BCM_TRIDENT2_SUPPORT)
  20602     soc_mem_t mem;
  20603     int entry_words;
  20604 #endif /* BCM_TRX_SUPPORT */
  20605 #if defined(BCM_TRIUMPH_SUPPORT)
  20606     uint16              dev_id;
  20607     uint8               rev_id;
  20608 #endif /* BCM_TRIUMPH_SUPPORT */
  20609     int                 inst;  /* Pipe Instance. */
  20610 
  20611     /* Input parameters check. */
  20612     if (NULL == fc) {
  20613         return (BCM_E_PARAM);
  20614     }
  20615 
  20616     /* Allocate stage structure. */
  20617     stage_fc = sal_alloc(sizeof(_field_stage_t), "FP stage info");
  20618     if (NULL == stage_fc) {
  20619         LOG_ERROR(BSL_LS_BCM_FP,
  20620                   (BSL_META_U(unit,
  20621                               "FP(unit %d) Error: Allocation failure for stage info\n"),
  20622                    unit));
  20623         return (BCM_E_MEMORY);
  20624     }
  20625     /* Reset allocated buffer. */
  20626     sal_memset(stage_fc, 0, sizeof(_field_stage_t));
  20627 
  20628 
  20629     /* Set stage id. */
  20630     stage_fc->stage_id = stage_id;
  20631     /* Set default num instances to 1 */
  20632     stage_fc->num_instances = 1;
  20633 
  20634 #ifdef BCM_TRIDENT2_SUPPORT
  20635     if (SOC_IS_TD2_TT2(unit)) {
  20636         ret_val = _bcm_field_td2_stage_init(unit, stage_fc);
  20637         if (BCM_FAILURE(ret_val)) {
  20638             sal_free(stage_fc);
  20639             return (ret_val);
  20640         }
  20641     } else
  20642 #endif
  20643 #ifdef BCM_HELIX4_SUPPORT
  20644     if (SOC_IS_HELIX4(unit)) {
  20645         ret_val = _bcm_field_helix4_stage_init(unit, stage_fc);
  20646         if (BCM_FAILURE(ret_val)) {
  20647             sal_free(stage_fc);
  20648             return (ret_val);
  20649         }
  20650     } else
  20651 #endif
  20652 #ifdef BCM_TRIUMPH3_SUPPORT
  20653 if (SOC_IS_TRIUMPH3(unit)) {
  20654         ret_val = _bcm_field_tr3_stage_init(unit, stage_fc);
  20655         if (BCM_FAILURE(ret_val)) {
  20656             sal_free(stage_fc);
  20657             return (ret_val);
  20658         }
  20659     } else
  20660 #endif
  20661     {
  20662         /* Set the stage features */
  20663         if ((soc_feature(unit, soc_feature_field_ingress_global_meter_pools)) &&
  20664             (stage_id == _BCM_FIELD_STAGE_INGRESS)) {
  20665             stage_fc->flags |= _FP_STAGE_GLOBAL_METER_POOLS;
  20666         }
  20667 
  20668 #if defined(BCM_TRIUMPH_SUPPORT)
  20669         if (SOC_IS_VALKYRIE(unit) || SOC_IS_VALKYRIE2(unit)) {
  20670            stage_fc->flags |= _FP_STAGE_HALF_SLICE;
  20671         } else if (SOC_IS_APOLLO(unit)
  20672             && (_BCM_FIELD_STAGE_LOOKUP != stage_id)) {
  20673             stage_fc->flags |= _FP_STAGE_HALF_SLICE;
  20674         }
  20675 
  20676         /* 56620/56630 devices have full slices on all stages. */
  20677         /* 56538/56534 devices have half slices on ingress and egress */
  20678         soc_cm_get_id(unit, &dev_id, &rev_id);
  20679         if (((BCM56538_DEVICE_ID == dev_id) || (BCM56534_DEVICE_ID == dev_id))
  20680             && (_BCM_FIELD_STAGE_LOOKUP != stage_id)) {
  20681             stage_fc->flags |= _FP_STAGE_HALF_SLICE;
  20682         }
  20683 
  20684         if ((BCM56630_DEVICE_ID == dev_id) || (BCM56620_DEVICE_ID == dev_id)) {
  20685             stage_fc->flags &= ~_FP_STAGE_HALF_SLICE;
  20686         }
  20687 
  20688 #ifdef BCM_HURRICANE2_SUPPORT
  20689         if (soc_feature(unit, soc_feature_field_slice_size128)) {
  20690             stage_fc->flags |= _FP_STAGE_HALF_SLICE;
  20691         }
  20692 #endif
  20693 #endif /* BCM_TRIUMPH_SUPPORT */
  20694 
  20695 #if defined(BCM_TRX_SUPPORT)
  20696         if ((soc_feature(unit,
  20697             soc_feature_field_ing_egr_separate_packet_byte_counters))
  20698             && ((stage_id == _BCM_FIELD_STAGE_INGRESS)
  20699                 || (stage_id == _BCM_FIELD_STAGE_EXTERNAL)
  20700                 || (stage_id == _BCM_FIELD_STAGE_EGRESS))) {
  20701             stage_fc->flags |= _FP_STAGE_SEPARATE_PACKET_BYTE_COUNTERS;
  20702         }
  20703 #endif /* BCM_TRX_SUPPORT  */
  20704 
  20705 
  20706 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  20707         if ((soc_feature(unit, soc_feature_field_egress_global_counters))
  20708             && (stage_id == _BCM_FIELD_STAGE_EGRESS)) {
  20709             stage_fc->flags |= _FP_STAGE_GLOBAL_COUNTERS;
  20710         }
  20711 
  20712         if ((soc_feature(unit, soc_feature_field_vfp_flex_counter))
  20713             && (stage_id == _BCM_FIELD_STAGE_LOOKUP)) {
  20714             stage_fc->flags |= _FP_STAGE_GLOBAL_COUNTERS;
  20715         }
  20716 
  20717         if (SOC_IS_KATANAX(unit)) {
  20718             if ((soc_feature(unit, soc_feature_advanced_flex_counter))
  20719                 && (stage_id == _BCM_FIELD_STAGE_LOOKUP)) {
  20720                 stage_fc->flags |= _FP_STAGE_GLOBAL_COUNTERS;
  20721             }
  20722         }
  20723         if ((soc_feature(unit, soc_feature_flowcnt))
  20724                 && (stage_id == _BCM_FIELD_STAGE_LOOKUP)) {
  20725             stage_fc->flags |= _FP_STAGE_GLOBAL_COUNTERS;
  20726         }
  20727 #endif /* BCM_FIREBOLT2_SUPPORT  || BCM_TRX_SUPPORT */
  20728 
  20729 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) || \
  20730     defined(BCM_RAPTOR_SUPPORT)
  20731         if ((soc_feature(unit, soc_feature_field_virtual_slice_group)
  20732             && (_BCM_FIELD_STAGE_INGRESS == stage_id))
  20733             || (SOC_IS_TRX(unit)
  20734                 && (_BCM_FIELD_STAGE_EXTERNAL != stage_id)
  20735                 && soc_feature(unit, soc_feature_field_virtual_slice_group))) {
  20736             stage_fc->flags |= _FP_STAGE_AUTO_EXPANSION;
  20737         }
  20738 #endif /* BCM_FIREBOLT2_SUPPORT  || BCM_TRX_SUPPORT || BCM_RAPTOR_SUPPORT */
  20739 
  20740         if ((soc_feature(unit, soc_feature_field_slice_enable))
  20741             && (_BCM_FIELD_STAGE_EXTERNAL != stage_id)) {
  20742             stage_fc->flags |= _FP_STAGE_SLICE_ENABLE;
  20743         }
  20744 
  20745 
  20746         /* Init tcam info for stage. */
  20747         ret_val = _field_tcam_info_init(unit, stage_fc, fc);
  20748         if (BCM_FAILURE(ret_val)) {
  20749             _field_stage_delete(unit, fc, stage_fc);
  20750             return (ret_val);
  20751         }
  20752     }
  20753 
  20754     /* Initialize slices information. */
  20755     ret_val = _field_slices_init (unit, stage_fc, fc);
  20756     if (BCM_FAILURE(ret_val)) {
  20757         _field_stage_delete(unit, fc, stage_fc);
  20758         return (ret_val);
  20759     }
  20760 
  20761     /*
  20762      * Allocate the memory for entries in all the slices
  20763      *     external TCAM (for Triumph) is taken care of in _bcm_tr_field_init.
  20764      * This will be de-allocated in bcm_esw_field_detach
  20765      */
  20766     if (stage_fc->stage_id != _BCM_FIELD_STAGE_EXTERNAL) {
  20767         /* Initialize stage slices . */
  20768         ret_val = _field_entries_init (unit, stage_fc);
  20769         if (BCM_FAILURE(ret_val)) {
  20770             _field_stage_delete(unit, fc, stage_fc);
  20771             return (ret_val);
  20772         }
  20773     }
  20774 
  20775     /* Initialize meters usage bitmap. */
  20776     ret_val = _field_meters_init (unit, stage_fc);
  20777     if (BCM_FAILURE(ret_val)) {
  20778         _field_stage_delete(unit, fc, stage_fc);
  20779         return (ret_val);
  20780     }
  20781 
  20782     /* Initialize counters usage bitmap. */
  20783     ret_val = _field_counters_init(unit, fc, stage_fc);
  20784     if (BCM_FAILURE(ret_val)) {
  20785         _field_stage_delete(unit, fc, stage_fc);
  20786         return (ret_val);
  20787     }
  20788 
  20789     /* Action profile; will be setup in chip-specific init */
  20790     soc_profile_mem_t_init(&stage_fc->ext_act_profile);
  20791 
  20792 #if defined(BCM_TRIDENT2_SUPPORT)
  20793     if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit))) {
  20794         /* hash select 0 action memory profile initialization. */
  20795         soc_profile_mem_t_init(&stage_fc->hash_select[0]);
  20796 
  20797         /* hash select 1 action memory profile initialization. */
  20798         soc_profile_mem_t_init(&stage_fc->hash_select[1]);
  20799     }
  20800 #endif /* BCM_TRIDENT2_SUPPORT */
  20801 
  20802     /* Ingress specific initialization. */
  20803     if (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) {
  20804 
  20805         stage_fc->range_id = 1;
  20806 
  20807         /* Initialize stage select codes table. */
  20808         ret_val = _field_stage_data_ctrl_init(unit, stage_fc);
  20809         if (BCM_FAILURE(ret_val)) {
  20810             _field_stage_delete(unit, fc, stage_fc);
  20811             return (ret_val);
  20812         }
  20813     }
  20814 
  20815 #if defined(BCM_TRIDENT2_SUPPORT)
  20816     /* Lookup stage specific initialization. */
  20817     if (((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit))) &&
  20818         (_BCM_FIELD_STAGE_LOOKUP == stage_fc->stage_id)) {
  20819         /* hash select action memory profile initialization. */
  20820         soc_profile_mem_t_init(&stage_fc->hash_select[0]);
  20821         soc_profile_mem_t_init(&stage_fc->hash_select[1]);
  20822 
  20823         /* Hash select 0 action profile table initialization. */
  20824         if (SOC_MEM_IS_VALID(unit, VFP_HASH_FIELD_BMAP_TABLE_Am)) {
  20825             mem = VFP_HASH_FIELD_BMAP_TABLE_Am;
  20826             entry_words = sizeof(vfp_hash_field_bmap_table_a_entry_t) /
  20827                                  sizeof(uint32);
  20828             ret_val = soc_profile_mem_create(unit, &mem, &entry_words, 1,
  20829                                              &stage_fc->hash_select[0]);
  20830 
  20831             if (BCM_FAILURE(ret_val)) {
  20832                 _field_stage_delete(unit, fc, stage_fc);
  20833                 return (ret_val);
  20834             }
  20835         }
  20836         /* Hash select 1 action profile table initialization. */
  20837         if (SOC_MEM_IS_VALID(unit, VFP_HASH_FIELD_BMAP_TABLE_Bm)) {
  20838             mem = VFP_HASH_FIELD_BMAP_TABLE_Bm;
  20839             entry_words = sizeof(vfp_hash_field_bmap_table_a_entry_t) /
  20840                                  sizeof(uint32);
  20841             ret_val = soc_profile_mem_create(unit, &mem, &entry_words, 1,
  20842                                              &stage_fc->hash_select[1]);
  20843 
  20844             if (BCM_FAILURE(ret_val)) {
  20845                 _field_stage_delete(unit, fc, stage_fc);
  20846                 return (ret_val);
  20847             }
  20848         }
  20849         /*
  20850          * Index 0 of vfp_hash_field_bmap_table_a/b is invalid as the
  20851          * hardware will consider hash bitmap selection from VFP only
  20852          * if HASH_FIELD_BITMAP_PTR_A and HASH_FIELD_BITMAP_PTR_B are non-zero.
  20853          * Making the entry to NULL.
  20854          */
  20855         ret_val = _bcm_field_td2_hash_select_profile_alloc_reserve_entry(unit,
  20856                                                                     stage_fc);
  20857         if (BCM_FAILURE(ret_val)) {
  20858             _field_stage_delete(unit, fc, stage_fc);
  20859             return (ret_val);
  20860         }
  20861     }
  20862 #endif /* BCM_TRIDENT2_SUPPORT */
  20863     /* Initializing supported Qset*/
  20864     sal_memset(&stage_fc->_field_supported_qset, 0, sizeof(bcm_field_qset_t));
  20865 
  20866     /*
  20867      * Initialize the FP_SLICE_MAP
  20868      *     physical_slice and virtual_group are H/W initial values
  20869      * Although initialized for all stages, valid only on Raptor (1 stage)
  20870      *     , FB-2 Ingress stage, Triumph
  20871      */
  20872     for (inst = 0; inst < stage_fc->num_instances; inst++) {
  20873         if (!(fc->pipe_map & (1 << inst))) {
  20874               continue;
  20875         }
  20876         for (map_id = 0; map_id < _FP_VMAP_CNT; map_id++) {
  20877             for (idx = 0; idx < _FP_VMAP_SIZE; idx++) {
  20878                 stage_fc->vmap[inst][map_id][idx].valid = FALSE;
  20879                 stage_fc->vmap[inst][map_id][idx].vmap_key = idx;
  20880                 stage_fc->vmap[inst][map_id][idx].virtual_group = idx;
  20881                 stage_fc->vmap[inst][map_id][idx].flags = 0;
  20882             }
  20883         }
  20884     }
  20885 
  20886     FP_LOCK(unit);
  20887     /* Add stage to field control structure. */
  20888     stage_fc->next = fc->stages;
  20889     fc->stages = stage_fc;
  20890     FP_UNLOCK(unit);
  20891 
  20892     return (BCM_E_NONE);
  20893 }
  20894 
  20895 /*
  20896  * Function:
  20897  *     _field_stages_init
  20898  *
  20899  * Purpose:
  20900  *     Initialize field stages array within the field control struct.
  20901  *
  20902  * Parameters:
  20903  *     unit - (IN) BCM device number.
  20904  *     fc -   (IN/OUT)Field control info for device.
  20905  *
  20906  * Returns:
  20907  *     BCM_E_NONE   - Success
  20908  *     BCM_E_MEMORY - Allocation failure
  20909  *
  20910  * Notes:
  20911  *     It is important that _BCM_FIELD_STAGE_INGRESS be inited before
  20912  *         _BCM_FIELD_STAGE_EXTERNAL
  20913  */
  20914 int
  20915 _field_stages_init(int unit, _field_control_t *fc)
  20916 {
  20917     int            ret_val;    /* Operation return value.     */
  20918 
  20919 
  20920     /* Input parameters check. */
  20921     if (fc == NULL) {
  20922         return (BCM_E_PARAM);
  20923     }
  20924 
  20925 #if defined(BCM_TOMAHAWK_SUPPORT) /* BCM_TOMAHAWK_SUPPORT */
  20926     if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  20927         /* Initialize stage add and delete functions for tomahawk device. */
  20928         fc->stage_func.fp_stages_add = _bcm_field_th_stages_add;
  20929         fc->stage_func.fp_stages_delete = _bcm_field_th_stages_delete;
  20930 
  20931         /* Invoke stage add function. */
  20932         return (fc->stage_func.fp_stages_add(unit, fc));
  20933     }
  20934 #endif /* !BCM_TOMAHAWK_SUPPORT*/
  20935 
  20936     /* Based on unit type add pipeline stages to field control. */
  20937 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  20938     if ((soc_feature(unit, soc_feature_field_multi_stage)) &&
  20939         (SOC_SWITCH_BYPASS_MODE_L3_ONLY != SOC_SWITCH_BYPASS_MODE(unit))) {
  20940 
  20941         ret_val = _field_stage_add(unit, fc, _BCM_FIELD_STAGE_LOOKUP);
  20942         if (BCM_FAILURE(ret_val)) {
  20943             _field_stages_destroy(unit, fc);
  20944             return (ret_val);
  20945         }
  20946 
  20947         ret_val = _field_stage_add(unit, fc, _BCM_FIELD_STAGE_EGRESS);
  20948         if (BCM_FAILURE(ret_val)) {
  20949             _field_stages_destroy(unit, fc);
  20950             return (ret_val);
  20951         }
  20952     }
  20953 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  20954 
  20955     ret_val = _field_stage_add(unit, fc, _BCM_FIELD_STAGE_INGRESS);
  20956     if (BCM_FAILURE(ret_val)) {
  20957         _field_stages_destroy(unit, fc);
  20958         return (ret_val);
  20959     }
  20960 
  20961     /* Add the External TCAM (stage) */
  20962     if ((soc_feature(unit, soc_feature_esm_support)) &&
  20963         (fc->flags & _FP_EXTERNAL_PRESENT)) {
  20964         ret_val = _field_stage_add(unit, fc, _BCM_FIELD_STAGE_EXTERNAL);
  20965         if (BCM_FAILURE(ret_val)) {
  20966             _field_stages_destroy(unit, fc);
  20967             return (ret_val);
  20968         }
  20969 
  20970         ret_val = _field_external_meters_init(unit, fc);
  20971         if (BCM_FAILURE(ret_val)) {
  20972             _field_stages_destroy(unit, fc);
  20973             return (ret_val);
  20974         }
  20975 
  20976         ret_val = _field_stage_external_data_ctrl_init(unit, fc);
  20977         if (BCM_FAILURE(ret_val)) {
  20978             _field_stages_destroy(unit, fc);
  20979             return (ret_val);
  20980         }
  20981     }
  20982     return (ret_val);
  20983 
  20984 }
  20985 /*
  20986  * Function: _field_min_virtual_priorty_group_get
  20987  *
  20988  * Purpose:
  20989  *     Service routine used to update virtual priority map.
  20990  *     Function returns a minimum priority group, which
  20991  *     might be assigned a virtual priority passed to the function.
  20992  * Parameters:
  20993  *     unit           - (IN) BCM device number.
  20994  *     vmap           - (IN) Virutal map array.
  20995  *     vmap_size      - (IN) Map size.
  20996  *     unused_groups  - (OUT) Unused virtual groups.
  20997  *     unused_slices  - (OUT) Unused physical slices.
  20998  * Returns:
  20999  *     BCM_E_XXX
  21000  */
  21001 STATIC int
  21002 _field_min_virtual_priorty_group_get(int unit, _field_virtual_map_t *vmap,
  21003                                      int vmap_size, int *virtual_priority,
  21004                                      int *candidate)
  21005 {
  21006     int idx;                     /* Virtual map iteration index.  */
  21007     int prio_max;                /* Max limit on group priority.  */
  21008     int min_group;               /* Minimum priority group index. */
  21009     int even_boundary_constraint;/*  even boundary constraint     */
  21010     int incr_priority = FALSE;   /* Increment priority to meet    */
  21011 
  21012     /* Input parameters check. */
  21013     if ((NULL == vmap) || (NULL ==  candidate) || (NULL == virtual_priority)) {
  21014         return (BCM_E_PARAM);
  21015     }
  21016 
  21017     /* Initialize max limit for group priority to ANY (unlimited). */
  21018     prio_max  = 0x7fffffff; /* Unlimited priority.*/
  21019     min_group = -1;         /* No candidates.    */
  21020 
  21021     /* FB2 double wide group must reside in even virtual priority. */
  21022     even_boundary_constraint = (SOC_IS_FIREBOLT2(unit)) ? TRUE : FALSE;
  21023 
  21024     /* Fill new virtual map. */
  21025     for (idx = 0; idx <  vmap_size; idx++) {
  21026 
  21027         /* Skip unused virtual priorities. */
  21028         if (vmap[idx].valid == FALSE) {
  21029             continue;
  21030         }
  21031 
  21032         /* Skip groups not meeting even_boundary_constraint */
  21033         if ((even_boundary_constraint) &&
  21034             (vmap[idx].flags & _FP_GROUP_SPAN_DOUBLE_SLICE)  &&
  21035             (0 != ((*virtual_priority) % 2))) {
  21036             if (prio_max > vmap[idx].priority) {
  21037                 prio_max = vmap[idx].priority;
  21038             }
  21039             if (-1 == min_group)  {
  21040                 min_group = idx;
  21041                 /* Priority increment is required.*/
  21042                 incr_priority = TRUE;
  21043             }
  21044             /* Double wide group -> no point to check next map. */
  21045             idx ++;
  21046             continue;
  21047         }
  21048 
  21049         /*
  21050          *  Make sure double wide group with
  21051          *  lower priority was not skipped because of even_boundary_constraint.
  21052          */
  21053         if (prio_max >= vmap[idx].priority) {
  21054             min_group = idx;
  21055             incr_priority = FALSE;
  21056         }
  21057         break;
  21058     }
  21059 
  21060     if (incr_priority) {
  21061         /*
  21062          *  Originally, a candidate was skipped because of
  21063          *  even boundary constraint violation (virtual_priority is odd).
  21064          *  lets use next priority.
  21065          */
  21066         (*virtual_priority)++;
  21067     }
  21068 
  21069     *candidate = min_group;
  21070 
  21071     return (BCM_E_NONE);
  21072 }
  21073 
  21074 /*
  21075  * Function:
  21076  *     _field_slice_clear
  21077  *
  21078  * Purpose:
  21079  *     Reset the fields in a slice. Note that the entries list must be
  21080  *     empty before calling this. Also, this does NOT deallocate the memory for
  21081  *     the slice itself. Normally, this is used when a group no longer needs
  21082  *     ownership of a slice so the slice gets returned to the pool of available
  21083  *     slices.
  21084  *
  21085  * Paramters:
  21086  *     unit  - BCM device number
  21087  *     fg    - Field group structure.
  21088  *     fs    - Link to physical slice structure to be cleared
  21089  *     pbmp  - Port bitmap to remove from slice
  21090  *
  21091  * Returns:
  21092  *     BCM_E_NONE      - Success
  21093  *     BCM_E_BUSY      - Entries still in slice, can't clear slice
  21094  */
  21095 STATIC int
  21096 _field_slice_clear(int unit, _field_group_t *fg,
  21097                    _field_slice_t *fs, bcm_pbmp_t pbmp)
  21098 {
  21099     _field_stage_t      *stage_fc;      /* Stage field control structure. */
  21100     _field_control_t    *fc;            /* Field control structure.       */
  21101     uint32              entry_idx;      /* Slice entries iterator.        */
  21102 
  21103     /* Input parameters check. */
  21104     if ((NULL == fs) || (NULL == fg)){
  21105        return (BCM_E_PARAM);
  21106     }
  21107     /* Get field control structure. */
  21108     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  21109 
  21110     /* Get stage field control structure. */
  21111     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, fs->stage_id, &stage_fc));
  21112 
  21113 
  21114     for (entry_idx = 0; entry_idx < fs->entry_count; entry_idx++) {
  21115         if (fs->entries[entry_idx] != NULL &&
  21116             fs->entries[entry_idx]->group->gid == fg->gid) {
  21117             LOG_ERROR(BSL_LS_BCM_FP,
  21118                       (BSL_META_U(unit,
  21119                                   "FP(unit %d) Error: Entries still in slice=%d.\n"),
  21120                        unit, fs->slice_number));
  21121             return (BCM_E_BUSY);
  21122         }
  21123     }
  21124 
  21125     if (fg->stage_id != _BCM_FIELD_STAGE_INGRESS) {
  21126         BCM_PBMP_CLEAR(fs->pbmp);
  21127     } else {
  21128         /* Remove ports from slice's port bit map. */
  21129         BCM_PBMP_REMOVE(fs->pbmp, pbmp);
  21130     }
  21131 
  21132     /* Clean up group configuration if last group was removed from the slice. */
  21133     if(BCM_PBMP_IS_NULL(fs->pbmp)) {
  21134         /* Clear slice configuration in hw. */
  21135         if (NULL != fc->functions.fp_slice_clear) {
  21136             BCM_IF_ERROR_RETURN(fc->functions.fp_slice_clear(unit, fg, fs));
  21137         }
  21138 
  21139         fs->group_flags = 0;
  21140         fs->doublewide_key_select = _FP_SELCODE_DONT_CARE;
  21141         fs->src_class_sel = _FP_SELCODE_DONT_CARE;
  21142         fs->dst_class_sel = _FP_SELCODE_DONT_CARE;
  21143         fs->intf_class_sel = _FP_SELCODE_DONT_CARE;
  21144         fs->loopback_type_sel = _FP_SELCODE_DONT_CARE;
  21145         fs->ingress_entity_sel = _FP_SELCODE_DONT_CARE;
  21146         fs->src_entity_sel = _FP_SELCODE_DONT_CARE;
  21147         fs->dst_fwd_entity_sel = _FP_SELCODE_DONT_CARE;
  21148         fs->fwd_field_sel = _FP_SELCODE_DONT_CARE;
  21149         fs->ttl_class_sel
  21150             = fs->tcp_class_sel
  21151             = fs->tos_class_sel
  21152             =_FP_SELCODE_DONT_CARE;
  21153         fs->aux_tag_1_sel
  21154             = fs->aux_tag_2_sel
  21155             = fs->oam_overlay_sel
  21156             = fs->egr_class_f1_sel
  21157             = fs->egr_class_f2_sel
  21158             = fs->egr_class_f3_sel
  21159             = fs->egr_class_f4_sel
  21160             = fs->src_dest_class_f1_sel
  21161             = fs->src_dest_class_f3_sel
  21162             = fs->egr_key4_dvp_sel
  21163             = fs->egr_key4_mdl_sel
  21164             = fs->egr_oam_overlay_sel
  21165             = fs->oam_intf_class_sel
  21166             = fs->egr_dest_port_f1_sel
  21167             = fs->egr_dest_port_f5_sel
  21168             = _FP_SELCODE_DONT_CARE;
  21169     }
  21170 
  21171     return (BCM_E_NONE);
  21172 }
  21173 
  21174 /*
  21175  * Function: _field_vmap_unused_resources_get
  21176  *
  21177  * Purpose:
  21178  *     Service routine used to retrieve unused virtual groups
  21179  *     and physical slices
  21180  * Parameter
  21181  *     unit           - (IN) BCM device number.
  21182  *     vmap           - (IN) Virutal map array.
  21183  *     vmap_size      - (IN) Virtual map size.
  21184  *     unused_groups  - (OUT) Unused virtual groups.
  21185  *     unused_slices  - (OUT) Unused physical slices.
  21186  * Returns:
  21187  *     BCM_E_XXX
  21188  */
  21189 STATIC int
  21190 _field_vmap_unused_resources_get(int unit, _field_virtual_map_t *vmap,
  21191                                  int vmap_size, uint32 *unused_groups,
  21192                                  uint32 *unused_slices)
  21193 {
  21194     int idx;                   /* Virtual map iteration index. */
  21195     uint32 used_groups = 0;    /* Used virtual groups.         */
  21196     uint32 used_slices = 0;    /* Used physical slices.        */
  21197 
  21198     /* Input parameters check. */
  21199     if ((NULL == vmap) || (NULL == unused_groups) || (NULL == unused_slices)) {
  21200         return (BCM_E_PARAM);
  21201     }
  21202 
  21203 
  21204     /* Iterate over all currently used groups & update bitmap. */
  21205     for (idx = 0; idx < vmap_size; idx++) {
  21206         /* Skip unused virtual priorities. */
  21207         if (vmap[idx].valid == FALSE) {
  21208             continue;
  21209         }
  21210 
  21211         used_groups |= (1 << vmap[idx].virtual_group);
  21212         used_slices |= (1 << vmap[idx].vmap_key);
  21213     }
  21214 
  21215     /* Update caller information. */
  21216     *unused_groups = ~used_groups;
  21217     *unused_slices = ~used_slices;
  21218 
  21219     return (BCM_E_NONE);
  21220 }
  21221 
  21222 /*
  21223  * Function: _field_vmap_resource_alloc
  21224  *
  21225  * Purpose:
  21226  *     Service routine used to allocate virutal group/physical
  21227  *     slice from unused resources map.
  21228  * Parameter
  21229  *     unit           - (IN) BCM device number.
  21230  *     vmap           - (IN) Virutal map array.
  21231  *     vmap_size      - (IN) Virtual map size.
  21232  *     resource       - (IN) Available resources bitmap.
  21233  *     allocated_idx  - (OUT) Allocated index.
  21234  * Returns:
  21235  *     BCM_E_XXX
  21236  */
  21237 STATIC int
  21238 _field_vmap_resource_alloc(int unit, _field_virtual_map_t *vmap,
  21239                            int vmap_size, uint32 *resource,
  21240                            int *allocated_idx)
  21241 {
  21242     int idx;                      /* Tcam slices iteration index. */
  21243 
  21244     /* Input parameters check. */
  21245     if ((NULL == vmap) || (NULL == resource) || (NULL == allocated_idx)) {
  21246         return (BCM_E_PARAM);
  21247     }
  21248 
  21249     /* Iterate over all currently used groups & update bitmap. */
  21250     for (idx = 0; idx < vmap_size; idx++) {
  21251         if ((*resource) & (1 << idx)) {
  21252             break;
  21253         }
  21254     }
  21255 
  21256     /* Check if any resources are available. */
  21257     if (idx == vmap_size) {
  21258         return (BCM_E_RESOURCE);
  21259     }
  21260 
  21261     *resource &= ~(1 << idx);
  21262     *allocated_idx = idx;
  21263     return (BCM_E_NONE);
  21264 }
  21265 
  21266 /*
  21267  * Function: _bcm_field_group_virtual_map_update
  21268  *
  21269  * Purpose:
  21270  *     Find the map between virtual group and vmap group id
  21271  * Parameters:
  21272  *     unit         - (IN) BCM device number.
  21273  *     fg           - (INOUT) Field Group Structure.
  21274  * Returns:
  21275  *     BCM_E_XXX
  21276  */
  21277  int
  21278  _bcm_field_group_virtual_map_update(int unit, _field_group_t *fg)
  21279 {
  21280     _field_control_t *fc;             /* Field control structure. */
  21281     _field_group_t *temp_fg = NULL;
  21282     int idx = 0;
  21283 
  21284     /* Input parameters check. */
  21285     if (NULL == fg) {
  21286         return (BCM_E_PARAM);
  21287     }
  21288 
  21289     for (idx = 0; idx < _FP_PAIR_MAX; idx++) {
  21290         fg->vmap_group[idx] = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT;
  21291     }
  21292     /* Find and validate field control. */
  21293     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  21294 
  21295     for (temp_fg = fc->groups; temp_fg != NULL ; temp_fg = temp_fg->next) {
  21296         /* Skip other stages. */
  21297         if (temp_fg->stage_id != fg->stage_id) {
  21298             continue;
  21299         }
  21300 
  21301         if (temp_fg->action_res_id == BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT) {
  21302             continue;
  21303         }
  21304 
  21305         if(temp_fg->action_res_id == fg->action_res_id) {
  21306             /* ALL VALID action Resoultion Id will have same virtual group */
  21307             for (idx = 0; idx < _FP_PAIR_MAX; idx++) {
  21308                 fg->vmap_group[idx] = temp_fg->vmap_group[0];
  21309             }
  21310             break;
  21311         }
  21312     }
  21313 
  21314     return (BCM_E_NONE);
  21315 }
  21316 
  21317 /*
  21318  * Function: _field_group_slice_sharing_virtual_map_group
  21319  *
  21320  * Purpose:
  21321  *     Find the map between physical slice and vmap group id
  21322  *     for slice sharing case
  21323  * Parameters:
  21324  *     unit         - (IN) BCM device number.
  21325  *     stage_fc     - (IN) Stage field control structure.
  21326  *     fg           - (INOUT) Field Group Structure.
  21327  * Returns:
  21328  *     BCM_E_XXX
  21329  */
  21330  int
  21331 _field_group_slice_sharing_virtual_map_group(int unit, _field_stage_t *stage_fc, _field_group_t *fg)
  21332 {
  21333     _field_virtual_map_t *vmap = NULL;
  21334     int                  idx;
  21335     int                  idx1;
  21336     int                  vmap_key;
  21337     int                  vmap_size;
  21338     uint8                map_id = _FP_VMAP_DEFAULT;
  21339     int                  rv;
  21340     int                  slice_count = 0;
  21341 
  21342     /* Input parameters check. */
  21343     if ((stage_fc == NULL) || (NULL == fg)) {
  21344         return (BCM_E_PARAM);
  21345     }
  21346 
  21347     vmap_key = (_BCM_FIELD_STAGE_EXTERNAL == fg->stage_id) ? \
  21348                (_FP_VMAP_SIZE - 1) : fg->slices->slice_number;
  21349 
  21350 
  21351     if (_BCM_FIELD_STAGE_EXTERNAL == fg->stage_id) {
  21352         /* Slice sharing is not supported by EXTERNAL stage
  21353          * This check should be never hit
  21354          * External slices controlled by stage ingress map. */
  21355         rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS,
  21356                 &stage_fc);
  21357         BCM_IF_ERROR_RETURN(rv);
  21358         if((fg->slices)->pkt_type[_FP_EXT_L2]) {
  21359             map_id = _FP_EXT_L2;
  21360         } else if ((fg->slices)->pkt_type[_FP_EXT_IP4]) {
  21361             map_id = _FP_EXT_IP4;
  21362         } else if ((fg->slices)->pkt_type[_FP_EXT_IP6]) {
  21363             map_id = _FP_EXT_IP6;
  21364         } else {
  21365             return (BCM_E_INTERNAL);
  21366         }
  21367         return (BCM_E_UNAVAIL);
  21368     }
  21369 
  21370     /* Calculate virtual map size. */
  21371     rv = _bcm_field_virtual_map_size_get(unit, stage_fc, &vmap_size);
  21372     BCM_IF_ERROR_RETURN(rv);
  21373 
  21374     rv = _bcm_field_group_slice_count_get(fg->flags, &slice_count);
  21375     BCM_IF_ERROR_RETURN(rv);
  21376 
  21377     /* check only in default map */
  21378     for (idx = 0; idx < vmap_size; idx++) {
  21379         vmap = (stage_fc->vmap[fg->instance][map_id]) + idx;
  21380         if (TRUE != vmap->valid) {
  21381             continue;
  21382         }
  21383         /* Slice sharing is possible only for groups of same mode */
  21384         if ((vmap->vmap_key == vmap_key)
  21385                 && ((idx + slice_count -1)  < vmap_size)){
  21386             for (idx1 = 0; idx1 < slice_count; idx1++) {
  21387                 fg->vmap_group[idx1] = (vmap + idx1)->virtual_group;
  21388             }
  21389             if (fg->action_res_id != BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT)
  21390             {
  21391                 for (idx1 = slice_count; idx1 < _FP_PAIR_MAX; idx1++) {
  21392                     fg->vmap_group[idx1] = fg->vmap_group[0];
  21393                 }
  21394             }
  21395             break;
  21396         }
  21397     }
  21398 
  21399     if(idx == vmap_size)
  21400     {
  21401         return (BCM_E_CONFIG);
  21402     }
  21403 
  21404     return (BCM_E_NONE);
  21405 }
  21406 
  21407 /*
  21408  * Function: _bcm_field_virtual_map_size_get
  21409  *
  21410  * Purpose:
  21411  *     Calculate virtual map size.
  21412  * Parameters:
  21413  *     unit         - (IN) BCM device number.
  21414  *     stage_fc     - (IN) Stage field control structure.
  21415  *     vmap_size    - (OUT) Virtual map size.
  21416  * Returns:
  21417  *     BCM_E_XXX
  21418  */
  21419  int
  21420  _bcm_field_virtual_map_size_get(int unit, _field_stage_t *stage_fc, int *vmap_size)
  21421 {
  21422     _field_control_t *fc;             /* Field control structure. */
  21423     uint16              dev_id;
  21424     uint8               rev_id;
  21425     soc_cm_get_id(unit, &dev_id, &rev_id);
  21426 
  21427     /* Input parameters check. */
  21428     if ((NULL == stage_fc) || (NULL == vmap_size)) {
  21429         return (BCM_E_PARAM);
  21430     }
  21431 
  21432     /* Find and validate field control. */
  21433     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  21434 
  21435 
  21436     /* Virtual map on stage ingress contains includes priority
  21437        for external slice.
  21438      */
  21439     if ((_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) &&  \
  21440         (fc->flags & _FP_EXTERNAL_PRESENT)) {
  21441         *vmap_size = stage_fc->tcam_slices + 1;
  21442     } else {
  21443         *vmap_size = stage_fc->tcam_slices;
  21444         if ((_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) &&
  21445            ((dev_id == BCM55441_DEVICE_ID) ||
  21446             (dev_id == BCM56240_DEVICE_ID) ||
  21447             (dev_id == BCM56241_DEVICE_ID) ||
  21448             (dev_id == BCM56242_DEVICE_ID) ||
  21449             (dev_id == BCM56243_DEVICE_ID) ||
  21450             (dev_id == BCM56245_DEVICE_ID) ||
  21451             (dev_id == BCM56246_DEVICE_ID))) {
  21452             *vmap_size = 12;
  21453         }
  21454     }
  21455     return (BCM_E_NONE);
  21456 }
  21457 
  21458 /*
  21459  * Function: _field_virtual_map_insert2
  21460  *
  21461  * Purpose:
  21462  *     For chips which support the virtual slice/group feature,
  21463  *     1) Sort groups by priority.
  21464  *     2) Aggregate expanded slices into virtual group priority.
  21465  * Parameters:
  21466  *     unit           - (IN) BCM device number.
  21467  *     stage_fc       - (IN) Stage field control structure.
  21468  *     fg             - (IN) Field group structure.
  21469  *     map_id         - (IN) Virtual map id.
  21470  *     vmap_key       - (IN) Virtual map key.
  21471  *     virtual_group  - (IN/OUT) Array of up to _FP_PAIR_MAX virtual group ids
  21472  *                               or -1 if Virtual group id needs to be assigned.
  21473  *     install        - (IN) Perform installation in HW flag.
  21474  * Returns:
  21475  *     BCM_E_XXX
  21476  */
  21477 STATIC int
  21478 _field_virtual_map_insert2(int unit, _field_stage_t *stage_fc,
  21479                           _field_group_t *fg, uint8 map_id,
  21480                           int vmap_key, int *virtual_group,
  21481                           int install)
  21482 {
  21483     int idx;                      /* Virtual map iteration index.        */
  21484     int idx_tmp;                  /* Temp iteration index.               */
  21485     int sizeof_vmap;              /* Virtual map byte size.              */
  21486     int candidate;                /* Virtual priority candidate group.   */
  21487     int slice_count;              /* Number of slices for each map entry.*/
  21488     int group_installed;          /* Group installation is complete.     */
  21489     _field_control_t *fc;         /* Field control structure.            */
  21490     uint32 unused_groups;         /* Unused virtual groups bitmap.       */
  21491     uint32 unused_slices;         /* Unused physical slices bitmap       */
  21492                                   /* Updated virtual map.                */
  21493     _field_virtual_map_t vmap_new[_FP_VMAP_SIZE];
  21494                                   /* Original virtual map.               */
  21495     _field_virtual_map_t vmap_orig[_FP_VMAP_SIZE];
  21496     _field_virtual_map_t *vmap;   /* Currently used virtual map.         */
  21497     int even_boundary_constraint = FALSE; /* Flag for double wide slices.*/
  21498     int vmap_size;                /* Virtual map index count.            */
  21499     int rv;                       /* Operation return status.            */
  21500     int idx_pair;                 /* Virtual map iteration index.        */
  21501     int inst;                     /* Pipe Instance.                      */
  21502 
  21503     /* Input parameters check */
  21504     if ((NULL == fg) || (NULL == stage_fc) || (NULL == virtual_group)) {
  21505         return (BCM_E_PARAM);
  21506     }
  21507 
  21508     /* Find and validate field control. */
  21509     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  21510 
  21511     inst = fg->instance;
  21512 
  21513 #if defined(BCM_FIREBOLT2_SUPPORT)
  21514     if (SOC_IS_FIREBOLT2(unit)) {
  21515         /* FB2 supports virtual priority in stage ingress only. */
  21516         if (stage_fc->stage_id != _BCM_FIELD_STAGE_INGRESS) {
  21517             return (BCM_E_NONE);
  21518         }
  21519         /* FB2 double wide group must reside in even virtual priority. */
  21520         even_boundary_constraint = TRUE;
  21521     }
  21522 #endif /* BCM_FIREBOLT2_SUPPORT */
  21523 
  21524     /* Reset new virtual map. */
  21525     sizeof_vmap = _FP_VMAP_SIZE * sizeof(_field_virtual_map_t);
  21526     sal_memset(vmap_new, 0, sizeof_vmap);
  21527 
  21528     /* Calculate virtual map size. */
  21529     rv = _bcm_field_virtual_map_size_get(unit, stage_fc, &vmap_size);
  21530     BCM_IF_ERROR_RETURN(rv);
  21531 
  21532     /* Get unused virtual groups & physical slices */
  21533     sal_memcpy(vmap_orig, stage_fc->vmap[inst][map_id], sizeof_vmap);
  21534     vmap = vmap_orig;
  21535     rv = _field_vmap_unused_resources_get(unit, vmap, vmap_size,
  21536                                           &unused_groups, &unused_slices);
  21537     BCM_IF_ERROR_RETURN(rv);
  21538 
  21539     group_installed = FALSE;
  21540     /* Fill new virtual map. */
  21541     for (idx = 0; idx < vmap_size;) {
  21542         idx_tmp = idx;
  21543         vmap = vmap_orig;
  21544         rv = _field_min_virtual_priorty_group_get(unit, vmap, vmap_size,
  21545                                                   &idx_tmp, &candidate);
  21546         BCM_IF_ERROR_RETURN(rv);
  21547 
  21548         if (_FP_INVALID_INDEX != candidate) {
  21549             vmap = vmap_orig + candidate;
  21550             if ((group_installed) || (vmap->priority <= fg->priority)) {
  21551                 idx = idx_tmp;
  21552                 /* Get number of slices required for this map. */
  21553                 rv = _bcm_field_group_slice_count_get(vmap->flags, &slice_count);
  21554                 BCM_IF_ERROR_RETURN(rv);
  21555                 /* Copy map info for each of the slices. */
  21556                 for (idx_tmp = 0; idx_tmp < slice_count; idx_tmp++, idx++) {
  21557                     vmap_new[idx] = vmap[idx_tmp];
  21558                     vmap[idx_tmp].valid = FALSE;
  21559                 }
  21560                 continue;
  21561             }
  21562         }
  21563 
  21564         if (FALSE == group_installed) {
  21565             /* New group insertion portion. */
  21566             /*
  21567              * Increment virtual priority index to meet even boundary
  21568              * constraints.
  21569              */
  21570             if ((even_boundary_constraint) &&
  21571                 (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE)  &&
  21572                 (0 != (idx % 2))) {
  21573                 idx++;
  21574             }
  21575 
  21576             /* Get number of slices required for this map. */
  21577             rv = _bcm_field_group_slice_count_get(fg->flags, &slice_count);
  21578             BCM_IF_ERROR_RETURN(rv);
  21579 
  21580             /* Set virtual map info. */
  21581             for (idx_tmp = 0; idx_tmp < slice_count; idx_tmp++, idx++) {
  21582                 /* Allocate virtual group id. */
  21583                 if (BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT == virtual_group[idx_tmp]) {
  21584                     vmap = vmap_orig;
  21585                     rv = _field_vmap_resource_alloc(unit, vmap, vmap_size,
  21586                                                     &unused_groups,
  21587                                                     &virtual_group[idx_tmp]);
  21588                     BCM_IF_ERROR_RETURN(rv);
  21589                     /* Valid action res id will have all slices mapped to same virtual group */
  21590                     if (BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT != fg->action_res_id) {
  21591                         for (idx_pair = 1; idx_pair < _FP_PAIR_MAX; idx_pair++) {
  21592                             virtual_group[idx_pair] = virtual_group[idx_tmp];
  21593                         }
  21594                     }
  21595                 }
  21596                 vmap_new[idx].valid = TRUE;
  21597                 vmap_new[idx].vmap_key = vmap_key + idx_tmp;
  21598                 vmap_new[idx].virtual_group = virtual_group[idx_tmp];
  21599                 vmap_new[idx].priority = fg->priority;
  21600                 vmap_new[idx].flags = fg->flags;
  21601 
  21602                 unused_slices &= ~(1 << (vmap_key + idx_tmp));
  21603             }
  21604             group_installed = TRUE;
  21605         }
  21606         if (-1 == candidate) {
  21607             /* No more groups to install. */
  21608             break;
  21609         }
  21610     }
  21611 
  21612     if (group_installed == FALSE) {
  21613         return BCM_E_RESOURCE;
  21614     }
  21615 
  21616     /* Assign distinct virtual group numbers to unused virtual slices */
  21617     vmap = vmap_orig;
  21618     for (idx = 0; idx < vmap_size; idx++) {
  21619         if (vmap_new[idx].valid == TRUE) {
  21620             continue;
  21621         }
  21622         /* Allocated unused virtual group id. */
  21623         rv = _field_vmap_resource_alloc(unit, vmap, vmap_size,
  21624                                         &unused_groups, &idx_tmp);
  21625         BCM_IF_ERROR_RETURN(rv);
  21626         vmap_new[idx].virtual_group = idx_tmp;
  21627 
  21628         /* Allocated unused physical slice. */
  21629         rv = _field_vmap_resource_alloc(unit, vmap, vmap_size,
  21630                                         &unused_slices, &idx_tmp);
  21631         BCM_IF_ERROR_RETURN(rv);
  21632         vmap_new[idx].vmap_key = idx_tmp;
  21633     }
  21634 
  21635     /* Write new map to the slice virtual map. */
  21636     sal_memcpy(stage_fc->vmap[inst][map_id], vmap_new, sizeof_vmap);
  21637 
  21638     /*
  21639      * Write the new_fp_virtual_map to H/W, and
  21640      *     copy to stage's fp_virtual_map
  21641      */
  21642     if (install) {
  21643         rv = fc->functions.fp_write_slice_map(unit, stage_fc, fg);
  21644         BCM_IF_ERROR_RETURN(rv);
  21645     }
  21646 #if defined(BROADCOM_DEBUG)
  21647     for (idx = 0; idx < vmap_size; idx++) {
  21648         vmap = stage_fc->vmap[inst][map_id] + idx;
  21649         if (0 == vmap->valid)  {
  21650             continue;
  21651         }
  21652         LOG_DEBUG(BSL_LS_BCM_FP,
  21653                   (BSL_META_U(unit,
  21654                            "FP(unit %d) vverb: vmap_id (%d): virutal group (%d)"
  21655                            "physical slice (%d) flags (%d)\n"),
  21656                    unit, idx, vmap->virtual_group,
  21657                    vmap->vmap_key,
  21658                    vmap->flags));
  21659     }
  21660 #endif /* BROADCOM_DEBUG */
  21661     return BCM_E_NONE;
  21662 }
  21663 
  21664 /*
  21665  * Function: _field_virtual_map_insert
  21666  *
  21667  * Purpose:
  21668  *     Insert fp group slices
  21669  * Parameters:
  21670  *     unit           - (IN) BCM device number.
  21671  *     stage_fc       - (IN) Stage field control structure.
  21672  *     fg             - (IN) Field group structure.
  21673  *     map_id         - (IN) Virtual map id.
  21674  *     install        - (IN) Install the map in hw flag.
  21675  * Returns:
  21676  *     BCM_E_XXX
  21677  */
  21678 STATIC int
  21679 _field_virtual_map_insert(int unit, _field_stage_t *stage_fc,
  21680                           _field_group_t *fg, uint8 map_id,
  21681                           uint8 install)
  21682 {
  21683     int  v_group[_FP_PAIR_MAX];  /* Virtual group id.        */
  21684     _field_slice_t *fs;          /* Field slice pointer.     */
  21685     int vmap_key;                /* Virtual map key.         */
  21686     int tmp_install;             /* Install map in hw.       */
  21687     int idx;                     /* group iteration index.   */
  21688     int rv;                      /* Operation return status. */
  21689 
  21690     /* Input parameters check. */
  21691     if ((NULL == stage_fc) || (NULL == fg)) {
  21692         return (BCM_E_PARAM);
  21693     }
  21694 
  21695     /* Initialize virtual group ids. */
  21696     for (idx = 0; idx < _FP_PAIR_MAX; idx++) {
  21697         v_group[idx] = fg->vmap_group[idx];
  21698     }
  21699 
  21700     /* Get to the last slice. */
  21701     fs = fg->slices;
  21702     while (fs->next != NULL) {
  21703         fs = fs->next;
  21704     }
  21705 
  21706     while (fs != NULL) {
  21707         tmp_install = ((fs == fg->slices) && (install)) ? TRUE : FALSE;
  21708         vmap_key = (_BCM_FIELD_STAGE_EXTERNAL == fg->stage_id) ? \
  21709                    (_FP_VMAP_SIZE - 1) : fs->slice_number;
  21710         rv = _field_virtual_map_insert2(unit, stage_fc, fg, map_id,
  21711                                         vmap_key, v_group, tmp_install);
  21712         BCM_IF_ERROR_RETURN(rv);
  21713         fs = fs->prev;
  21714     }
  21715 
  21716     /* Update virtual group index */
  21717     if (fg->vmap_group[0] == BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT) {
  21718         for (idx = 0; idx < _FP_PAIR_MAX; idx++) {
  21719             fg->vmap_group[idx] = v_group[idx];
  21720         }
  21721     }
  21722     return (BCM_E_NONE);
  21723 }
  21724 
  21725 /*
  21726  * Function: _field_virtual_map_remove
  21727  *
  21728  * Purpose:
  21729  *     For chips which support the virtual slice/group feature,
  21730  *     Wipe out groups physical slices from virtual map.
  21731  * Parameters:
  21732  *     unit           - (IN) BCM device number.
  21733  *     stage_fc       - (IN) Stage field control structure.
  21734  *     fg             - (IN) Field Group Structure.
  21735  *     map_id         - (IN) Virtual map id.
  21736  *     vmap_key       - (IN) Virtual map key.
  21737  *     install        - (IN) Perform installation in HW flag.
  21738  * Returns:
  21739  *     BCM_E_XXX
  21740  */
  21741 STATIC int
  21742 _field_virtual_map_remove(int unit, _field_stage_t *stage_fc, _field_group_t *fg,
  21743                           uint8 map_id, int vmap_key, int install)
  21744 {
  21745     int idx;                           /* Virtual map iteration index.   */
  21746     int idx_tmp=0;                     /* Temp iteration index.          */
  21747     int slice_count;                   /* Number of slices used by group.*/
  21748     _field_control_t *fc;              /* Field control structure.       */
  21749     uint32 unused_groups;              /* Unused virtual groups bitmap.  */
  21750     uint32 unused_slices;              /* Unused physical slices bitmap  */
  21751     int rv = BCM_E_NONE;               /* Operation return status.       */
  21752     int v_group[_FP_PAIR_MAX];         /* Virtual group id.              */
  21753     _field_virtual_map_t *vmap = NULL; /* Currently used virtual map.    */
  21754     int vmap_size;                     /* Virtual map size.              */
  21755     int inst;                          /* Pipe Instance.                 */
  21756 
  21757     /* Input parameters check. */
  21758     if ((NULL == stage_fc) || (NULL == fg)) {
  21759         return (BCM_E_PARAM);
  21760     }
  21761 
  21762     /* Find and validate field control. */
  21763     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  21764 
  21765     inst = fg->instance;
  21766 #if defined(BCM_FIREBOLT2_SUPPORT)
  21767     if (SOC_IS_FIREBOLT2(unit)) {
  21768         /* FB2 supports virtual priority in stage ingress only. */
  21769         if (stage_fc->stage_id != _BCM_FIELD_STAGE_INGRESS) {
  21770             return (BCM_E_NONE);
  21771         }
  21772     }
  21773 #endif /* BCM_FIREBOLT2_SUPPORT */
  21774 
  21775     /* Calculate virtual map size. */
  21776     rv = _bcm_field_virtual_map_size_get(unit, stage_fc, &vmap_size);
  21777     BCM_IF_ERROR_RETURN(rv);
  21778 
  21779 
  21780     /* Get virtual group id. */
  21781     for (idx = 0; idx <  _FP_PAIR_MAX; idx++) {
  21782         v_group[idx] = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT;
  21783     }
  21784 
  21785     for (idx = 0; idx < vmap_size; idx++) {
  21786         vmap = (stage_fc->vmap[inst][map_id]) + idx;
  21787         if (TRUE != vmap->valid) {
  21788             continue;
  21789         }
  21790         if (vmap->vmap_key == vmap_key) {
  21791             break;
  21792         }
  21793     }
  21794 
  21795     /* Make sure virtual group was found. */
  21796     if (idx == vmap_size) {
  21797         /* No such virtual group. */
  21798         return (rv);
  21799     }
  21800 
  21801     /* Get group width. */
  21802     rv = _bcm_field_group_slice_count_get(vmap->flags, &slice_count);
  21803     BCM_IF_ERROR_RETURN(rv);
  21804 
  21805     /* Get virtual group ids. */
  21806     for (idx = 0; idx < slice_count; idx++) {
  21807         v_group[idx] = (vmap + idx)->virtual_group;
  21808     }
  21809 
  21810     /* Mark group maps as invalid. */
  21811     for (idx = 0; idx <  vmap_size; idx++) {
  21812         vmap = stage_fc->vmap[inst][map_id] + idx;
  21813         if (TRUE != vmap->valid) {
  21814             continue;
  21815         }
  21816         /* Check if slice and virtual group matches to mark it invalid*/
  21817         for (idx_tmp = 0; idx_tmp < slice_count; idx_tmp++) {
  21818             if ((vmap->virtual_group == v_group[idx_tmp]) &&
  21819                 (vmap->vmap_key == (vmap_key + idx_tmp))){
  21820                 vmap->valid = FALSE;
  21821             }
  21822         }
  21823     }
  21824 
  21825     /* Get unused virtual groups & physical slices */
  21826     vmap = stage_fc->vmap[inst][map_id];
  21827     rv = _field_vmap_unused_resources_get(unit, vmap, vmap_size,
  21828                                           &unused_groups, &unused_slices);
  21829     BCM_IF_ERROR_RETURN(rv);
  21830 
  21831 
  21832     /* Assign distinct virtual group numbers to unused virtual slices */
  21833     for (idx = 0; idx < vmap_size; idx++) {
  21834         vmap = (stage_fc->vmap[inst][map_id]) + idx;
  21835         if (vmap->valid == TRUE) {
  21836             continue;
  21837         }
  21838         /* Allocated unused virtual group id. */
  21839         rv = _field_vmap_resource_alloc(unit, vmap, vmap_size,
  21840                                         &unused_groups, &idx_tmp);
  21841         vmap->virtual_group = idx_tmp;
  21842 
  21843         /* Allocated unused physical slice. */
  21844         rv = _field_vmap_resource_alloc(unit, vmap, vmap_size,
  21845                                         &unused_slices, &idx_tmp);
  21846         vmap->vmap_key = idx_tmp;
  21847     }
  21848 
  21849 
  21850     /*
  21851      * Write the new_fp_virtual_map to H/W, and copy to stage's fp_virtual_map
  21852      */
  21853     if (install) {
  21854         rv = fc->functions.fp_write_slice_map(unit, stage_fc, fg);
  21855     }
  21856 #if defined(BROADCOM_DEBUG)
  21857     for (idx = 0; idx < vmap_size; idx++) {
  21858         vmap = stage_fc->vmap[inst][map_id] + idx;
  21859         if (0 == vmap->valid)  {
  21860             continue;
  21861         }
  21862         LOG_DEBUG(BSL_LS_BCM_FP,
  21863                   (BSL_META_U(unit,
  21864                               "FP(unit %d) vverb: vmap_id (%d): virutal group (%d)"
  21865                                "physical slice (%d) flags (%d)\n"),
  21866                    unit, idx, vmap->virtual_group,
  21867                    vmap->vmap_key,
  21868                    vmap->flags));
  21869     }
  21870 #endif /* BROADCOM_DEBUG */
  21871 
  21872     return rv;
  21873 }
  21874 
  21875 
  21876 /*
  21877  * Function: _field_group_vmap_delete
  21878  *
  21879  * Purpose:
  21880  *     For chips which support the virtual slice/group feature,
  21881  *     Wipe out groups physical slices from virtual map.
  21882  * Parameters:
  21883  *     unit           - (IN) BCM device number.
  21884  *     stage_fc       - (IN) Stage field control structure.
  21885  *     fg             - (IN) Field group structure.
  21886  *     install        - (IN) Perform installation in HW flag.
  21887  * Returns:
  21888  *     BCM_E_XXX
  21889  */
  21890 int
  21891 _field_group_vmap_delete(int unit, _field_stage_t *stage_fc,
  21892                       _field_group_t *fg, int install)
  21893 {
  21894     _field_slice_t   *fs;                    /* Field slice structure.  */
  21895     int              idx;                    /* Temp iteration index.   */
  21896     int              rv;                     /* Operation return status.*/
  21897 
  21898     fs = fg->slices;
  21899 
  21900     /* Find and validate field control. */
  21901 
  21902 
  21903     /* Loop for deleting all the AUTO expanded slices in group */
  21904     while(fs != NULL) {
  21905 
  21906         switch (stage_fc->stage_id) {
  21907             case _BCM_FIELD_STAGE_LOOKUP:
  21908             case _BCM_FIELD_STAGE_EGRESS:
  21909                 rv = _field_virtual_map_remove(unit, stage_fc, fg,
  21910                         _FP_VMAP_DEFAULT, fs->slice_number, install);
  21911                 BCM_IF_ERROR_RETURN(rv);
  21912                 break;
  21913             case _BCM_FIELD_STAGE_EXTERNAL:
  21914                 idx = (_FP_VMAP_SIZE) - 1;
  21915                 /* External slices controlled by stage ingress map. */
  21916                 rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS,
  21917                         &stage_fc);
  21918                 BCM_IF_ERROR_RETURN(rv);
  21919 
  21920 #if defined(BCM_TRIUMPH3_SUPPORT)
  21921                 if (SOC_IS_TRIUMPH3(unit)) {
  21922                 rv = _field_virtual_map_remove(unit, stage_fc, fg,
  21923                         _FP_VMAP_DEFAULT, idx, FALSE);
  21924                 BCM_IF_ERROR_RETURN(rv);
  21925 
  21926                 rv = _field_virtual_map_remove(unit, stage_fc, fg,
  21927                         _FP_EXT_IP4, idx, FALSE);
  21928                 BCM_IF_ERROR_RETURN(rv);
  21929 
  21930                 rv = _field_virtual_map_remove(unit, stage_fc, fg,
  21931                         _FP_EXT_IP6, idx, install);
  21932                 } else
  21933 #endif
  21934                 {
  21935                 if ((fg->slices)->pkt_type[_FP_EXT_L2]) {
  21936                     rv = _field_virtual_map_remove(unit, stage_fc, fg,
  21937                             _FP_EXT_L2, idx, install);
  21938                 } else if ((fg->slices)->pkt_type[_FP_EXT_IP4]) {
  21939                     rv = _field_virtual_map_remove(unit, stage_fc, fg,
  21940                             _FP_EXT_IP4, idx, install);
  21941                 } else if ((fg->slices)->pkt_type[_FP_EXT_IP6]) {
  21942                     rv = _field_virtual_map_remove(unit, stage_fc, fg,
  21943                             _FP_EXT_IP6, idx, install);
  21944                 } else {
  21945                     rv = BCM_E_INTERNAL;
  21946                 }
  21947                 }
  21948                 BCM_IF_ERROR_RETURN(rv);
  21949                 break;
  21950             case _BCM_FIELD_STAGE_INGRESS:
  21951                 rv = _field_virtual_map_remove(unit, stage_fc, fg,
  21952                         _FP_VMAP_DEFAULT, fs->slice_number, FALSE);
  21953                 BCM_IF_ERROR_RETURN(rv);
  21954 
  21955                 rv = _field_virtual_map_remove(unit, stage_fc, fg,
  21956                         _FP_EXT_IP4, fs->slice_number, FALSE);
  21957                 BCM_IF_ERROR_RETURN(rv);
  21958 
  21959                 rv = _field_virtual_map_remove(unit, stage_fc, fg,
  21960                         _FP_EXT_IP6, fs->slice_number, install);
  21961                 BCM_IF_ERROR_RETURN(rv);
  21962                 break;
  21963             default:
  21964                 return BCM_E_INTERNAL;
  21965         }
  21966         fs = fs->next;
  21967     }
  21968 
  21969     return (BCM_E_NONE);
  21970 }
  21971 
  21972 
  21973 /*
  21974  * Function: _field_group_vmap_add
  21975  *
  21976  * Purpose:
  21977  *     For chips which support the virtual slice/group feature,
  21978  *     Add group physical slices to virtual map.
  21979  * Parameters:
  21980  *     unit           - (IN) BCM device number.
  21981  *     stage_fc       - (IN) Stage field control structure.
  21982  *     fg             - (IN) Field group structure.
  21983  * Returns:
  21984  *     BCM_E_XXX
  21985  */
  21986 int
  21987 _field_group_vmap_add(int unit, _field_stage_t *stage_fc,
  21988                       _field_group_t *fg)
  21989 {
  21990     int              rv;              /* Operation return status.*/
  21991 
  21992     switch (stage_fc->stage_id) {
  21993       case _BCM_FIELD_STAGE_LOOKUP:
  21994       case _BCM_FIELD_STAGE_EGRESS:
  21995           rv = _field_virtual_map_insert(unit, stage_fc, fg,
  21996                                          _FP_VMAP_DEFAULT, TRUE);
  21997           BCM_IF_ERROR_RETURN(rv);
  21998           break;
  21999       case _BCM_FIELD_STAGE_EXTERNAL:
  22000           /* External slices controlled by stage ingress map. */
  22001           rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS,
  22002                                         &stage_fc);
  22003           BCM_IF_ERROR_RETURN(rv);
  22004 
  22005 #if defined(BCM_TRIUMPH3_SUPPORT)
  22006           if (SOC_IS_TRIUMPH3(unit)) {
  22007           rv = _field_virtual_map_insert(unit, stage_fc, fg,
  22008                                          _FP_VMAP_DEFAULT, FALSE);
  22009           BCM_IF_ERROR_RETURN(rv);
  22010 
  22011           rv = _field_virtual_map_insert(unit, stage_fc, fg,
  22012                                          _FP_EXT_IP4, FALSE);
  22013           BCM_IF_ERROR_RETURN(rv);
  22014 
  22015           rv = _field_virtual_map_insert(unit, stage_fc, fg,
  22016                                          _FP_EXT_IP6, TRUE);
  22017           } else
  22018 #endif
  22019           {
  22020           if ((fg->slices)->pkt_type[_FP_EXT_L2]) {
  22021               rv = _field_virtual_map_insert(unit, stage_fc, fg,
  22022                                              _FP_EXT_L2, TRUE);
  22023           } else if ((fg->slices)->pkt_type[_FP_EXT_IP4]) {
  22024               rv = _field_virtual_map_insert(unit, stage_fc, fg,
  22025                                              _FP_EXT_IP4, TRUE);
  22026           } else if ((fg->slices)->pkt_type[_FP_EXT_IP6]) {
  22027               rv = _field_virtual_map_insert(unit, stage_fc, fg,
  22028                                              _FP_EXT_IP6, TRUE);
  22029           } else {
  22030               rv = BCM_E_INTERNAL;
  22031           }
  22032           }
  22033           BCM_IF_ERROR_RETURN(rv);
  22034           break;
  22035       case _BCM_FIELD_STAGE_INGRESS:
  22036           rv = _field_virtual_map_insert(unit, stage_fc, fg,
  22037                                          _FP_VMAP_DEFAULT, FALSE);
  22038           BCM_IF_ERROR_RETURN(rv);
  22039 
  22040           rv = _field_virtual_map_insert(unit, stage_fc, fg,
  22041                                          _FP_EXT_IP4, FALSE);
  22042           BCM_IF_ERROR_RETURN(rv);
  22043 
  22044           rv = _field_virtual_map_insert(unit, stage_fc, fg,
  22045                                          _FP_EXT_IP6, TRUE);
  22046           BCM_IF_ERROR_RETURN(rv);
  22047           break;
  22048       default:
  22049           return BCM_E_INTERNAL;
  22050     }
  22051 
  22052     return (BCM_E_NONE);
  22053 }
  22054 
  22055 /*
  22056  * Function: _field_group_free_unused_slices
  22057  *
  22058  * Purpose:
  22059  *     Unallocate group unused slices.
  22060  * Parameters:
  22061  *     unit           - (IN) BCM device number.
  22062  *     stage_fc       - (IN) Stage field control structure.
  22063  *     fg             - (IN) Field group structure.
  22064  * Returns:
  22065  *     BCM_E_XXX
  22066  */
  22067 int
  22068 _field_group_free_unused_slices(int unit, _field_stage_t *stage_fc,
  22069                                 _field_group_t *fg)
  22070 {
  22071     _field_slice_t *fs;       /* Field slice structure.        */
  22072     _field_slice_t *fs_next;  /* Field slice structure.        */
  22073     _field_slice_t *fs_ptr;   /* Field slice structure.        */
  22074     uint8          empty;     /* Slice is empty flag.          */
  22075     int            idx;       /* Group slices iteration index. */
  22076     int            remap;     /* Reinstall virtual slice map.  */
  22077     int            count;     /* Group slices iteration index. */
  22078     int            rv;        /* Operation return status.      */
  22079     _field_group_t *curr_group;
  22080     _field_control_t  *fc;
  22081     bcm_field_group_mode_t mode1 = 0;
  22082     bcm_field_group_mode_t mode2 = 0;
  22083 
  22084     int            temp_rv = 0;        /* Operation return status.      */
  22085     int            err_occured = 0;
  22086     int            virtual_priority = FALSE;/* Virtual priority support flag.*/
  22087 
  22088     /* We never free first group slice. */
  22089     fs = fg->slices->next;
  22090     remap = FALSE;
  22091 
  22092     _field_virtual_priority_support(unit, stage_fc, &virtual_priority);
  22093 
  22094     while (fs != NULL) {
  22095         fs_next = fs->next;
  22096         rv = _field_slice_is_empty(unit, fs, &empty);
  22097         BCM_IF_ERROR_RETURN(rv);
  22098         if (empty) {
  22099             BCM_IF_ERROR_RETURN
  22100                 (_bcm_field_group_slice_count_get(fs->group_flags, &count));
  22101 
  22102             if ((remap == FALSE)
  22103                     && (virtual_priority)) {
  22104                 BCM_IF_ERROR_RETURN(_field_group_vmap_delete(unit, stage_fc, fg, FALSE));
  22105             }
  22106 
  22107             remap = TRUE;
  22108             /* Preserve next slice to continue the loop over group slices. */
  22109 
  22110             for (idx = 0; idx < count; idx++) {
  22111                 /* Remove slice from group slices linked list. */
  22112                 fs_ptr = fs + idx;
  22113                 if (fs_ptr->prev != NULL) {
  22114                     fs_ptr->prev->next = fs_ptr->next;
  22115                 }
  22116 
  22117                 if (fs_ptr->next != NULL) {
  22118                     fs_ptr->next->prev = fs_ptr->prev;
  22119                 }
  22120 
  22121                 /* Clear used entries pbmp. */
  22122                 /* for a per-port group, the slice should be cleared
  22123                  * if the entries of all the groups sharing the slice
  22124                  * are removed.
  22125                  */
  22126                 if ((fg->flags & _FP_GROUP_PER_PORT_OR_PBMP) &&
  22127                     (fg->priority != BCM_FIELD_GROUP_PRIO_ANY)) {
  22128                      /* Get device Field control structure. */
  22129                      BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  22130                      curr_group = fc->groups;
  22131 
  22132                       if (curr_group == NULL) {
  22133                           return BCM_E_NONE;
  22134                       }
  22135                       temp_rv = 0;
  22136                       err_occured = 0;
  22137                       while (curr_group != NULL) {
  22138                           if ((curr_group->stage_id == fg->stage_id) &&
  22139                               (curr_group->flags &
  22140                               _FP_GROUP_PER_PORT_OR_PBMP) &&
  22141                               (curr_group->priority == fg->priority)) {
  22142                               _bcm_esw_field_group_mode_get(curr_group->flags,
  22143                                                             &mode1);
  22144                               _bcm_esw_field_group_mode_get(fg->flags,
  22145                                                             &mode2);
  22146                                if( (mode1 == mode2) ){
  22147                                    /* uninstall selcodes of this group in the
  22148                                     * slice. selcodes are uninstalled only
  22149                                     * when the slice is not having any entry
  22150                                     * of the groups it shares with.
  22151                                     */
  22152                                    temp_rv = _field_slice_clear(unit,
  22153                                                   curr_group,
  22154                                                   fs_ptr,
  22155                                                   curr_group->pbmp);
  22156                                    if (BCM_FAILURE(temp_rv)) {
  22157                                        err_occured = temp_rv;
  22158                                    }
  22159                                }
  22160                            }
  22161                            curr_group = curr_group->next;
  22162                        }
  22163                        if (err_occured) {
  22164                            return err_occured;
  22165                        } else {
  22166                            fs_ptr->next = fs_ptr->prev = NULL;
  22167                        }
  22168                    } else {
  22169                        rv = _field_slice_clear(unit, fg, fs_ptr, fg->pbmp);
  22170                        BCM_IF_ERROR_RETURN(rv);
  22171                        fs_ptr->next = fs_ptr->prev = NULL;
  22172                    }
  22173             }
  22174         }
  22175         fs = fs_next;
  22176      }
  22177 
  22178     if ((remap)
  22179             && (virtual_priority)){
  22180         /* Remove the group from virtual map . */
  22181         BCM_IF_ERROR_RETURN(_field_group_vmap_add(unit, stage_fc, fg));
  22182     }
  22183 
  22184     return (BCM_E_NONE);
  22185 }
  22186 
  22187 /*
  22188  * Function: _field_group_uninstall
  22189  *
  22190  * Purpose:
  22191  *     Uninstall group from all slices.
  22192  *
  22193  * Parameters:
  22194  *     unit - (IN)BCM device number.
  22195  *     fg   - (IN)Field group.
  22196  *
  22197  * Returns:
  22198  *     BCM_E_XXX
  22199  */
  22200 int
  22201 _field_group_uninstall(int unit, _field_group_t *fg)
  22202 {
  22203     _field_slice_t      *fs;         /* Field slice structure.   */
  22204     _field_slice_t      *temp_fs;    /* Expanded slices iterator.*/
  22205     int                 parts_count = 0; /* Number of entry parts.   */
  22206     uint32              entry_flags; /* Entry part flags.        */
  22207     uint8               slice_number;/* Slices iterator.         */
  22208     int                 rv;          /* Operation return status. */
  22209     int                 idx;         /* Slices iterator.         */
  22210 
  22211 
  22212     /* Find and validate field control. */
  22213 
  22214 
  22215     /* Get number of entry parts . */
  22216     rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
  22217                                             fg->flags, &parts_count);
  22218     BCM_IF_ERROR_RETURN(rv);
  22219 
  22220 
  22221     for (idx = parts_count - 1; idx >= 0; idx--) {
  22222         /* Get entry flags. */
  22223         rv = _bcm_field_tcam_part_to_entry_flags(unit, idx, fg,
  22224                                                  &entry_flags);
  22225         BCM_IF_ERROR_RETURN(rv);
  22226 
  22227         if (entry_flags & _FP_ENTRY_SECOND_HALF) {
  22228             continue;
  22229         }
  22230 
  22231         /* Get slice id for entry part */
  22232         rv = _bcm_field_tcam_part_to_slice_number(unit, idx, fg,
  22233                                                   &slice_number);
  22234         BCM_IF_ERROR_RETURN(rv);
  22235 
  22236         fs = fg->slices + slice_number;
  22237         while (fs != NULL) {
  22238             /* Clear tertiary slice, if in-use. */
  22239             BCM_IF_ERROR_RETURN(_field_slice_clear(unit, fg, fs, fg->pbmp));
  22240             temp_fs = fs->next;
  22241             if (fs->prev != NULL) {
  22242                 fs->prev->next = NULL;
  22243                 fs->prev = NULL;
  22244             }
  22245             fs = temp_fs;
  22246         }
  22247     }
  22248     return (BCM_E_NONE);
  22249 }
  22250 
  22251 /*
  22252  * Function:
  22253  *     _bcm_field_group_linked_list_remove
  22254  * Purpose:
  22255  *     Remove field group from unit's groups list
  22256  * Parameters:
  22257  *     unit     - (IN) BCM device number.
  22258  *     fg       - (IN) State machine tracking structure.
  22259  * Returns:
  22260  *     BCM_E_XXX
  22261  */
  22262 int
  22263 _bcm_field_group_linked_list_remove(int unit, _field_group_t *fg)
  22264 {
  22265     _field_control_t *fc;      /* Field control structure.    */
  22266     _field_group_t   *fg_prev; /* Fied group iterator.        */
  22267 
  22268     if (NULL == fg) {
  22269         return (BCM_E_PARAM);
  22270     }
  22271 
  22272     /* Find and validate field control. */
  22273     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  22274 
  22275     /* Remove this group from device's linked-list of groups. */
  22276     if (fc->groups == fg) {
  22277         fc->groups = fg->next;
  22278     }
  22279     else {
  22280         fg_prev = fc->groups;
  22281         while (NULL != fg_prev) {
  22282             if (fg_prev->next ==  fg) {
  22283                 fg_prev->next = fg->next;
  22284                 break;
  22285             }
  22286             fg_prev = fg_prev->next;
  22287         }
  22288     }
  22289     return (BCM_E_NONE);
  22290 }
  22291 
  22292 /*
  22293  * Function:
  22294  *     _field_group_linked_list_insert
  22295  * Purpose:
  22296  *     Insert new field group into unit's groups list sorted
  22297  *     by priority & group width.
  22298  * Parameters:
  22299  *     unit     - (IN) BCM device number.
  22300  *     fsm_ptr  - (IN) State machine tracking structure.
  22301  * Returns:
  22302  *     BCM_E_XXX
  22303  */
  22304 int
  22305 _bcm_field_group_linked_list_insert(int unit, _field_group_add_fsm_t *fsm_ptr)
  22306 {
  22307     _field_group_t      *fg;           /* Field group pointer.     */
  22308     _field_group_t      *fg_iter;      /* Field group iterator.    */
  22309     _field_group_t      *fg_iter_prev; /* Field group iterator.    */
  22310 
  22311 
  22312     /* Input parameters check. */
  22313     if (NULL == fsm_ptr) {
  22314         return (BCM_E_PARAM);
  22315     }
  22316 
  22317     fg = fsm_ptr->fg;
  22318     if (NULL == fg) {
  22319          return (BCM_E_PARAM);
  22320     }
  22321 
  22322     /* Linked list insertion must be done after group mode was
  22323        decided(after select codes selection stage). On 5682x devices
  22324        we might need to reselect select codes based on slice availability,
  22325        to avoid double insertion remove any installed group first.
  22326      */
  22327     BCM_IF_ERROR_RETURN(_bcm_field_group_linked_list_remove(unit, fg));
  22328 
  22329     /* Insert new field group into unit's groups list sorted by priority. */
  22330     fg_iter_prev = fg_iter = fsm_ptr->fc->groups;
  22331     while (fg_iter != NULL)  {
  22332         /* Priority comparison: low to high insertion. */
  22333         if (fg_iter->priority > fg->priority) {
  22334             break;
  22335         }
  22336 
  22337         /* Group width comparison: wide group first. */
  22338         if (fg_iter->priority ==  fg->priority) {
  22339             if (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) {
  22340                 break;
  22341             }
  22342 
  22343             if ((0 == (fg_iter->flags & _FP_GROUP_SPAN_TRIPLE_SLICE)) &&
  22344                 (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE)) {
  22345                 break;
  22346             }
  22347         }
  22348 
  22349         fg_iter_prev = fg_iter;
  22350         fg_iter = fg_iter->next;
  22351     }
  22352 
  22353     /* Head of the list insertion. */
  22354     if (fg_iter == fg_iter_prev) {
  22355         fg->next = fg_iter;
  22356         fsm_ptr->fc->groups = fg;
  22357     } else {
  22358         fg_iter_prev->next = fg;
  22359         fg->next = fg_iter;
  22360     }
  22361     return (BCM_E_NONE);
  22362 }
  22363 
  22364 /*
  22365  * Function: _field_group_deinit
  22366  * Purpose:
  22367  *    Destroy field group structure.
  22368  * Parameters:
  22369  *     unit   - (IN) BCM device number.
  22370  *     fg     - (IN) Allocated group structure.
  22371  *
  22372  * Returns:
  22373  *     BCM_E_NONE      - Success
  22374  */
  22375 int
  22376 _field_group_deinit(int unit, _field_group_t *fg)
  22377 {
  22378     _field_control_t *fc;          /* Field control structure.    */
  22379     int idx;                       /* Qualifiers iteration index. */
  22380     int rv = BCM_E_NONE;           /* OPerational Status. */
  22381 
  22382     if (NULL == fg) {
  22383         return (BCM_E_NONE);
  22384     }
  22385 
  22386     /* Find and validate field control. */
  22387     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  22388 
  22389     /* Uninstall group from every slice. */
  22390     if (NULL != fg->slices) {
  22391         _field_group_uninstall(unit, fg);
  22392     }
  22393 
  22394     /* Deallocate group qualifiers list. */
  22395     for (idx = 0; idx < _FP_MAX_ENTRY_WIDTH; idx++) {
  22396         /* If qualifier set was updated free original qualifiers array. */
  22397         BCM_IF_ERROR_RETURN(_bcm_field_group_qualifiers_free(fg, idx));
  22398     }
  22399 
  22400     /* Decrement the use counts for any UDFs used by the group */
  22401     for (idx = 0; idx < BCM_FIELD_USER_NUM_UDFS; idx++) {
  22402         /* coverity[ptr_arith] */
  22403         if (SHR_BITGET(fg->qset.udf_map, idx))  {
  22404             if (fc->udf[idx].use_count > 0) {
  22405                 fc->udf[idx].use_count--;
  22406             }
  22407         }
  22408     }
  22409 
  22410     /* Deallocate group entry array if any. */
  22411     if (NULL != fg->entry_arr) {
  22412         sal_free(fg->entry_arr);
  22413     }
  22414 
  22415     rv = _bcm_field_group_stat_destroy(unit, fg->gid);
  22416     BCM_IF_ERROR_RETURN(rv);
  22417 
  22418     /* Remove group from units group list. */
  22419     BCM_IF_ERROR_RETURN(_bcm_field_group_linked_list_remove(unit, fg));
  22420 
  22421     if ( soc_feature(unit, soc_feature_field_multi_pipe_support) ||
  22422          soc_feature(unit, soc_feature_field_ingress_two_slice_types)) {
  22423         /* Group has been destroyed, Decrement group ref count in
  22424          * corresponding hintid in hints hash lookup table */
  22425         BCM_IF_ERROR_RETURN(
  22426                 _bcm_field_hints_group_count_update (unit, fg->hintid, 0));
  22427     }
  22428 
  22429     sal_free(fg);
  22430     return (BCM_E_NONE);
  22431 }
  22432 
  22433 #ifdef BCM_FIREBOLT_SUPPORT
  22434 /*
  22435  * Function:
  22436  *     _field_fb_slice_to_field
  22437  *
  22438  * Purpose:
  22439  *     Determines which FP_SLICE_ENABLEr field corresponds to given slice.
  22440  *
  22441  * Parameters:
  22442  *     slice - slice number
  22443  *     field - (OUT) FP_SLICE_ENABLE register field
  22444  *
  22445  * Returns:
  22446  *     BCM_E_NONE      - Success
  22447  *     BCM_E_PARAM     - slice number out of range
  22448  */
  22449 STATIC int
  22450 _field_fb_slice_to_field(_field_group_t *fg,
  22451                          int slice, soc_field_t *field)
  22452 {
  22453     static soc_field_t _ifp_slice_enable_field[16] = {
  22454                                                FP_LOOKUP_ENABLE_SLICE_0f,
  22455                                                FP_LOOKUP_ENABLE_SLICE_1f,
  22456                                                FP_LOOKUP_ENABLE_SLICE_2f,
  22457                                                FP_LOOKUP_ENABLE_SLICE_3f,
  22458                                                FP_LOOKUP_ENABLE_SLICE_4f,
  22459                                                FP_LOOKUP_ENABLE_SLICE_5f,
  22460                                                FP_LOOKUP_ENABLE_SLICE_6f,
  22461                                                FP_LOOKUP_ENABLE_SLICE_7f,
  22462                                                FP_LOOKUP_ENABLE_SLICE_8f,
  22463                                                FP_LOOKUP_ENABLE_SLICE_9f,
  22464                                                FP_LOOKUP_ENABLE_SLICE_10f,
  22465                                                FP_LOOKUP_ENABLE_SLICE_11f,
  22466                                                FP_LOOKUP_ENABLE_SLICE_12f,
  22467                                                FP_LOOKUP_ENABLE_SLICE_13f,
  22468                                                FP_LOOKUP_ENABLE_SLICE_14f,
  22469                                                FP_LOOKUP_ENABLE_SLICE_15f};
  22470 
  22471 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  22472     static soc_field_t _vfp_slice_enable_field[4] = {LOOKUP_ENABLE_SLICE_0f,
  22473                                                      LOOKUP_ENABLE_SLICE_1f,
  22474                                                      LOOKUP_ENABLE_SLICE_2f,
  22475                                                      LOOKUP_ENABLE_SLICE_3f};
  22476 
  22477     static soc_field_t _efp_slice_enable_field[4] = {LOOKUP_ENABLE_SLICE_0f,
  22478                                                      LOOKUP_ENABLE_SLICE_1f,
  22479                                                      LOOKUP_ENABLE_SLICE_2f,
  22480                                                      LOOKUP_ENABLE_SLICE_3f};
  22481 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  22482 
  22483     assert(fg != NULL && field != NULL);
  22484     if (_BCM_FIELD_STAGE_INGRESS == fg->stage_id) {
  22485          if (slice < 0 || slice >= COUNTOF(_ifp_slice_enable_field)) {
  22486              return (BCM_E_PARAM);
  22487          }
  22488          *field = _ifp_slice_enable_field[slice];
  22489 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  22490     } else if (_BCM_FIELD_STAGE_LOOKUP == fg->stage_id) {
  22491          if (slice < 0 || slice >= COUNTOF(_vfp_slice_enable_field)) {
  22492              return (BCM_E_PARAM);
  22493          }
  22494          *field = _vfp_slice_enable_field[slice];
  22495 
  22496     } else if (_BCM_FIELD_STAGE_EGRESS == fg->stage_id) {
  22497          if (slice < 0 || slice >= COUNTOF(_efp_slice_enable_field)) {
  22498              return (BCM_E_PARAM);
  22499          }
  22500          *field = _efp_slice_enable_field[slice];
  22501 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  22502     } else {
  22503          return (BCM_E_INTERNAL);
  22504     }
  22505     return (BCM_E_NONE);
  22506 }
  22507 
  22508 /*
  22509  * Function:
  22510  *     _field_fb_slice_enable_set
  22511  *
  22512  * Purpose:
  22513  *     Enables or disables packet lookup on a hardware slice.
  22514  *
  22515  * Parameters:
  22516  *     unit   - BCM device number
  22517  *     slice  - Slice number to enable
  22518  *     enable - enable/disable state of slice
  22519  *
  22520  * Returns:
  22521  *     BCM_E_NONE      - Success
  22522  *     BCM_E_INTERNAL  - SOC read/write error
  22523  *
  22524  * Note:
  22525  *     Calling function is responsible for checking feature availability.
  22526  */
  22527 int
  22528 _bcm_field_fb_slice_enable_set(int unit, _field_group_t *fg,
  22529                            uint8 slice, int enable)
  22530 {
  22531     uint32              reg_val_old, reg_val_new;
  22532     soc_field_t         field;
  22533 
  22534     LOG_VERBOSE(BSL_LS_BCM_FP,
  22535                 (BSL_META_U(unit,
  22536                        "FP: _field_fb_slice_enable_set(slice=%d, enable=%d)\n"),
  22537                  slice, enable));
  22538 
  22539     if (NULL == fg) {
  22540         return (BCM_E_PARAM);
  22541     }
  22542 
  22543     BCM_IF_ERROR_RETURN(_field_fb_slice_to_field(fg, slice, &field));
  22544     enable = (enable ? 1 : 0);
  22545     if (_BCM_FIELD_STAGE_INGRESS == fg->stage_id) {
  22546         SOC_IF_ERROR_RETURN(READ_FP_SLICE_ENABLEr(unit, &reg_val_old));
  22547         reg_val_new = reg_val_old;
  22548         soc_reg_field_set(unit, FP_SLICE_ENABLEr, &reg_val_new, field, enable);
  22549         if (reg_val_new != reg_val_old) {
  22550             BCM_IF_ERROR_RETURN(WRITE_FP_SLICE_ENABLEr(unit, reg_val_new));
  22551         }
  22552 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  22553     } else if (_BCM_FIELD_STAGE_LOOKUP == fg->stage_id) {
  22554         SOC_IF_ERROR_RETURN(READ_VFP_SLICE_CONTROLr(unit, &reg_val_old));
  22555         reg_val_new = reg_val_old;
  22556         soc_reg_field_set(unit, VFP_SLICE_CONTROLr, &reg_val_new,
  22557                           field, enable);
  22558         if (reg_val_new != reg_val_old) {
  22559             SOC_IF_ERROR_RETURN(WRITE_VFP_SLICE_CONTROLr(unit, reg_val_new));
  22560         }
  22561     } else if (_BCM_FIELD_STAGE_EGRESS == fg->stage_id) {
  22562         SOC_IF_ERROR_RETURN(READ_EFP_SLICE_CONTROLr(unit, &reg_val_old));
  22563         reg_val_new = reg_val_old;
  22564         soc_reg_field_set(unit, EFP_SLICE_CONTROLr, &reg_val_new,
  22565                           field, enable);
  22566         if (reg_val_new != reg_val_old) {
  22567             BCM_IF_ERROR_RETURN(WRITE_EFP_SLICE_CONTROLr(unit, reg_val_new));
  22568         }
  22569 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT  */
  22570     } else {
  22571          return (BCM_E_INTERNAL);
  22572     }
  22573 
  22574 
  22575     return (BCM_E_NONE);
  22576 }
  22577 #endif /* BCM_FIREBOLT_SUPPORT */
  22578 
  22579 
  22580 STATIC int
  22581 _field_slice_enable_set(int            unit,
  22582                         _field_stage_t *stage_fc,
  22583                         _field_group_t *fg,
  22584                         _field_slice_t *fs,
  22585                         unsigned       enable
  22586                         )
  22587 {
  22588     if (stage_fc->flags & _FP_STAGE_SLICE_ENABLE) {
  22589 #if defined (BCM_TOMAHAWK_SUPPORT)
  22590         if ((soc_feature(unit, soc_feature_field_multi_pipe_support)) &&
  22591             ((fg->stage_id == _BCM_FIELD_STAGE_LOOKUP) ||
  22592              (fg->stage_id == _BCM_FIELD_STAGE_EGRESS))) {
  22593             return (_bcm_field_th_slice_enable_set(unit,
  22594                                                    fg, fs, 1));
  22595         }
  22596 #endif
  22597 #ifdef BCM_TRIUMPH3_SUPPORT
  22598         if (SOC_IS_TRIUMPH3(unit)) {
  22599             return (_bcm_field_tr3_slice_enable_set(unit, stage_fc, fg, fs, 1));
  22600         }
  22601 #endif
  22602 #ifdef BCM_FIREBOLT_SUPPORT
  22603         return (_bcm_field_fb_slice_enable_set(unit, fg, fs->slice_number, 1));
  22604 #endif /* BCM_FIREBOLT_SUPPORT */
  22605     }
  22606 
  22607     return (BCM_E_NONE);
  22608 }
  22609 
  22610 
  22611 unsigned
  22612 _field_stage_action_support_check(int              unit,
  22613                                   _field_group_t   *fg,
  22614                                   unsigned         action
  22615                                   )
  22616 {
  22617     _field_control_t *fc;
  22618     _field_entry_t   f_ent[1];  /* Dummy entry */
  22619     int              suppf = 0;
  22620 
  22621     if (BCM_FAILURE(_field_control_get(unit, &fc))) {
  22622         return (FALSE);
  22623     }
  22624 
  22625     /* Set group in dummy entry, since old code takes entry as parameter
  22626        (nothing else in entry matters).
  22627      */
  22628 
  22629     f_ent->group = fg;
  22630 
  22631     return (BCM_SUCCESS(fc->functions.fp_action_support_check(unit,
  22632                                                               f_ent,
  22633                                                               action,
  22634                                                               &suppf
  22635                                                               )
  22636                         )
  22637             && suppf
  22638             );
  22639 }
  22640 
  22641 
  22642 int
  22643 _bcm_field_group_default_aset_set(int unit, _field_group_t *fg)
  22644 {
  22645     /* Set group's aset to all actions supported by stage */
  22646 
  22647     unsigned action;
  22648 
  22649     for (action = 0; action < bcmFieldActionCount; ++action) {
  22650         if (_field_stage_action_support_check(unit, fg, action)) {
  22651             SHR_BITSET(fg->aset.w, action);
  22652         }
  22653     }
  22654 
  22655     return (BCM_E_NONE);
  22656 }
  22657 
  22658 
  22659 int
  22660 _field_group_default_aset_set(int unit, _field_group_t *fg)
  22661 {
  22662     sal_memset(fg->aset.w, 0, sizeof(fg->aset.w));
  22663 
  22664 #ifdef BCM_TRIUMPH3_SUPPORT
  22665     if (SOC_IS_TRIUMPH3(unit)) {
  22666         return (_bcm_field_tr3_group_default_aset_set(unit, fg));
  22667     }
  22668 #endif
  22669 
  22670     /* Default aset is set of all supported actions */
  22671     return (_bcm_field_group_default_aset_set(unit, fg));
  22672 }
  22673 
  22674 /*
  22675  * Function:
  22676  *     _field_group_add_selcodes_install
  22677  * Purpose:
  22678  *     Update allocated slice sw controls &
  22679  *     install slice select codes into hw.
  22680  * Parameters:
  22681 
  22682  *     unit     - (IN)     BCM device number.
  22683  *     fsm_ptr  - (IN/OUT) State machine tracking structure.
  22684  * Returns:
  22685  *     BCM_E_XXX
  22686  */
  22687 STATIC int
  22688 _field_group_add_selcodes_install(int unit, _field_group_add_fsm_t *fsm_ptr)
  22689 {
  22690     _field_slice_t *fs;                /* Slice pointer.          */
  22691     _field_group_t *fg;                /* Field group pointer.    */
  22692     uint32         entry_flags;        /* Entry lookup flags.     */
  22693     uint8          slice_number;       /* Slices iterator.        */
  22694     int            idx;                /* Slice iteration index.  */
  22695     int            parts_count = 0;    /* Number of entry parts.  */
  22696     int            slice_init;         /* Slice sw init needed.   */
  22697     int            rv;                 /* Operation return status.*/
  22698 
  22699     /* Input parameters check. */
  22700     if (NULL == fsm_ptr) {
  22701         return (BCM_E_PARAM);
  22702     }
  22703 
  22704     fg = fsm_ptr->fg;
  22705 
  22706     /* Check if this is the first group installed in slice. */
  22707     slice_init = BCM_PBMP_IS_NULL(fg->slices[0].pbmp) ? TRUE : FALSE;
  22708 
  22709     /* Install slice/s select codes. */
  22710     BCM_PBMP_OR(fg->slices[0].pbmp, fg->pbmp);
  22711 
  22712     /* Write group parameters to hardware. */
  22713     BCM_IF_ERROR_RETURN(fsm_ptr->fc->functions.fp_group_install(unit, fg));
  22714 
  22715     /* Get number of entry parts. */
  22716     rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
  22717                                             fg->flags, &parts_count);
  22718     BCM_IF_ERROR_RETURN(rv);
  22719 
  22720     for (idx = parts_count - 1; idx >= 0; idx--) {
  22721         /* Get entry flags. */
  22722         rv = _bcm_field_tcam_part_to_entry_flags(unit, idx, fg,
  22723                                                  &entry_flags);
  22724         BCM_IF_ERROR_RETURN(rv);
  22725 
  22726         /* Get slice id for entry part */
  22727         rv = _bcm_field_tcam_part_to_slice_number(unit, idx, fg,
  22728                                                   &slice_number);
  22729         BCM_IF_ERROR_RETURN(rv);
  22730 
  22731         /* Get slice pointer. */
  22732         fs = fg->slices + slice_number;
  22733 
  22734         /* Enable slice. */
  22735         if (0 == (entry_flags & _FP_ENTRY_SECOND_HALF)) {
  22736 
  22737             /* Set per slice configuration &  number of free entries in the slice.*/
  22738             if (slice_init)  {
  22739                 fs->free_count = fs->entry_count;
  22740                 if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
  22741                     fs->free_count >>= 1;
  22742                 }
  22743                 /* Set group flags in in slice.*/
  22744                 fs->group_flags = fg->flags & _FP_GROUP_STATUS_MASK;
  22745             }
  22746 
  22747             /* Set slice usage by device ports. */
  22748             BCM_PBMP_OR(fs->pbmp, fg->pbmp);
  22749         }
  22750         /* Set source class selection. */
  22751         if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].src_class_sel) {
  22752             fs->src_class_sel = fg->sel_codes[idx].src_class_sel;
  22753         }
  22754         /* Set destination class selection. */
  22755         if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].dst_class_sel) {
  22756             fs->dst_class_sel = fg->sel_codes[idx].dst_class_sel;
  22757         }
  22758         /* Set interface class selection. */
  22759         if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].intf_class_sel) {
  22760             fs->intf_class_sel = fg->sel_codes[idx].intf_class_sel;
  22761         }
  22762         /* Set loopback type/tunnel type selection. */
  22763         if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].loopback_type_sel) {
  22764             fs->loopback_type_sel = fg->sel_codes[idx].loopback_type_sel;
  22765         }
  22766         /* Set ingress entity selection. */
  22767         if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].ingress_entity_sel) {
  22768             fs->ingress_entity_sel = fg->sel_codes[idx].ingress_entity_sel;
  22769         }
  22770         /* Set src entity selection. */
  22771         if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].src_entity_sel) {
  22772             fs->src_entity_sel = fg->sel_codes[idx].src_entity_sel;
  22773         }
  22774         /* Set destination forwarding entity selection. */
  22775         if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].dst_fwd_entity_sel) {
  22776             fs->dst_fwd_entity_sel = fg->sel_codes[idx].dst_fwd_entity_sel;
  22777         }
  22778 
  22779         /* Set destination forwarding field selection. */
  22780         if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].fwd_field_sel) {
  22781             fs->fwd_field_sel = fg->sel_codes[idx].fwd_field_sel;
  22782         }
  22783 
  22784         if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].ttl_class_sel) {
  22785             fs->ttl_class_sel = fg->sel_codes[idx].ttl_class_sel;
  22786         }
  22787 
  22788         if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].tcp_class_sel) {
  22789             fs->tcp_class_sel = fg->sel_codes[idx].tcp_class_sel;
  22790         }
  22791 
  22792         if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].tos_class_sel) {
  22793             fs->tos_class_sel = fg->sel_codes[idx].tos_class_sel;
  22794         }
  22795 
  22796         if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].aux_tag_1_sel) {
  22797             fs->aux_tag_1_sel = fg->sel_codes[idx].aux_tag_1_sel;
  22798         }
  22799 
  22800         if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].aux_tag_2_sel) {
  22801             fs->aux_tag_2_sel = fg->sel_codes[idx].aux_tag_2_sel;
  22802         }
  22803 
  22804         if (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].oam_overlay_sel) {
  22805             fs->oam_overlay_sel = fg->sel_codes[idx].oam_overlay_sel;
  22806         }
  22807 
  22808         if (fg->sel_codes[idx].egr_class_f1_sel != _FP_SELCODE_DONT_CARE) {
  22809             fs->egr_class_f1_sel = fg->sel_codes[idx].egr_class_f1_sel;
  22810         }
  22811 
  22812         if (fg->sel_codes[idx].egr_class_f2_sel != _FP_SELCODE_DONT_CARE) {
  22813             fs->egr_class_f2_sel = fg->sel_codes[idx].egr_class_f2_sel;
  22814         }
  22815 
  22816         if (fg->sel_codes[idx].egr_class_f3_sel != _FP_SELCODE_DONT_CARE) {
  22817             fs->egr_class_f3_sel = fg->sel_codes[idx].egr_class_f3_sel;
  22818         }
  22819 
  22820         if (fg->sel_codes[idx].egr_class_f4_sel != _FP_SELCODE_DONT_CARE) {
  22821             fs->egr_class_f4_sel = fg->sel_codes[idx].egr_class_f4_sel;
  22822         }
  22823 
  22824         if (fg->sel_codes[idx].src_dest_class_f1_sel != _FP_SELCODE_DONT_CARE) {
  22825             fs->src_dest_class_f1_sel = fg->sel_codes[idx].src_dest_class_f1_sel;
  22826         }
  22827 
  22828         if (fg->sel_codes[idx].src_dest_class_f3_sel != _FP_SELCODE_DONT_CARE) {
  22829             fs->src_dest_class_f3_sel = fg->sel_codes[idx].src_dest_class_f3_sel;
  22830         }
  22831 
  22832         if (fg->sel_codes[idx].egr_key4_dvp_sel != _FP_SELCODE_DONT_CARE) {
  22833             fs->egr_key4_dvp_sel = fg->sel_codes[idx].egr_key4_dvp_sel;
  22834         }
  22835 
  22836         if (fg->sel_codes[idx].egr_key4_mdl_sel != _FP_SELCODE_DONT_CARE) {
  22837             fs->egr_key4_mdl_sel = fg->sel_codes[idx].egr_key4_mdl_sel;
  22838         }
  22839 
  22840         if (fg->sel_codes[idx].egr_oam_overlay_sel != _FP_SELCODE_DONT_CARE) {
  22841             fs->egr_oam_overlay_sel = fg->sel_codes[idx].egr_oam_overlay_sel;
  22842         }
  22843 
  22844         if (fg->sel_codes[idx].oam_intf_class_sel != _FP_SELCODE_DONT_CARE) {
  22845             fs->oam_intf_class_sel = fg->sel_codes[idx].oam_intf_class_sel;
  22846         }
  22847 
  22848         if (fg->sel_codes[idx].egr_dest_port_f1_sel != _FP_SELCODE_DONT_CARE) {
  22849             fs->egr_dest_port_f1_sel = fg->sel_codes[idx].egr_dest_port_f1_sel;
  22850         }
  22851 
  22852         if (fg->sel_codes[idx].egr_dest_port_f5_sel != _FP_SELCODE_DONT_CARE) {
  22853             fs->egr_dest_port_f5_sel = fg->sel_codes[idx].egr_dest_port_f5_sel;
  22854         }
  22855 
  22856         /* Set intraslice double wide key selection. */
  22857         if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
  22858             if ((_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].fpf2) &&
  22859                 ((idx == _FP_INTRA_SLICE_PART_1) ||
  22860                  (idx == _FP_INTRA_SLICE_PART_3))) {
  22861                 fs->doublewide_key_select = fg->sel_codes[idx].fpf2;
  22862             }
  22863         }
  22864     }
  22865     return (BCM_E_NONE);
  22866 }
  22867 
  22868 /*
  22869  * Function:
  22870  *     _field_group_add_adjust_virtual_map
  22871  * Purpose:
  22872  *     Update slices virtual priorities map.
  22873  * Parameters:
  22874  *     unit     - (IN)     BCM device number.
  22875  *     fsm_ptr  - (IN/OUT) State machine tracking structure.
  22876  * Returns:
  22877  *     BCM_E_XXX
  22878  */
  22879 STATIC int
  22880 _field_group_add_adjust_virtual_map(int unit, _field_group_add_fsm_t *fsm_ptr)
  22881 {
  22882     _field_group_t   *fg;         /* Field group control structure.  */
  22883     int              virtual_priority = FALSE;/* Virtual priority support flag.*/
  22884 
  22885     /* Input parameters check. */
  22886     if (NULL == fsm_ptr) {
  22887         return (BCM_E_PARAM);
  22888     }
  22889 
  22890     _field_virtual_priority_support(unit, fsm_ptr->stage_fc, &virtual_priority);
  22891 
  22892     /* Initialize group pointer. */
  22893     fg = fsm_ptr->fg;
  22894 
  22895     /* Set current state to be previous state. */
  22896     fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state;
  22897 
  22898     /*  Update slices virtual priorities map.  */
  22899     if (virtual_priority) {
  22900         if (BCM_PBMP_EQ(fg->slices->pbmp, fg->pbmp)) {
  22901             /*
  22902              * If this is a first group in a slice
  22903              * a) allocate virtual group.
  22904              * b) Update slice virtual priority.
  22905              */
  22906             fsm_ptr->rv = _field_group_vmap_add(unit, fsm_ptr->stage_fc, fg);
  22907         } else {
  22908             /* Slice sharing find the slice in VMAP
  22909              * and update the corresponding VMAP group */
  22910             fsm_ptr->rv = _field_group_slice_sharing_virtual_map_group(unit, fsm_ptr->stage_fc, fg);
  22911         }
  22912     }
  22913 
  22914     if (BCM_SUCCESS(fsm_ptr->rv)) {
  22915         fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_UDF_UPDATE;
  22916     } else {
  22917         fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END;
  22918     }
  22919     return _bcm_field_group_add(unit, fsm_ptr);
  22920 }
  22921 
  22922 /*
  22923  * Function:
  22924  *     _field_group_add_hw_qual_list_get
  22925  * Purpose:
  22926  *     Get qualifiers offset in hw.
  22927  * Parameters:
  22928  *     unit     - (IN)     BCM device number.
  22929  *     fsm_ptr  - (IN/OUT) State machine tracking structure.
  22930  * Returns:
  22931  *     BCM_E_XXX
  22932  */
  22933 STATIC int
  22934 _field_group_add_hw_qual_list_get(int unit, _field_group_add_fsm_t *fsm_ptr)
  22935 {
  22936     /* Input parameters check. */
  22937     if (NULL == fsm_ptr) {
  22938         return (BCM_E_PARAM);
  22939     }
  22940 
  22941     /* Set current state to be previous state. */
  22942     fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state;
  22943 
  22944    /*
  22945     * Set the FPFx metadata (bit offset, width) for this HW
  22946     * this fills the group's qualifier lists.
  22947     */
  22948     fsm_ptr->rv = fsm_ptr->fc->functions.fp_qual_list_get(unit,
  22949                                                           fsm_ptr->stage_fc,
  22950                                                           fsm_ptr->fg);
  22951     if (BCM_FAILURE(fsm_ptr->rv)) {
  22952         fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END;
  22953     } else {
  22954         fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_ADJUST_VIRTUAL_MAP;
  22955     }
  22956     return _bcm_field_group_add(unit, fsm_ptr);
  22957 }
  22958 
  22959 /*
  22960  * Function:
  22961  *     _field_udf_usecount_increment
  22962  *
  22963  * Purpose:
  22964  *     Increment the use counts for any UDFs used
  22965  *
  22966  * Parameters:
  22967  *     fc - unit's field control struct
  22968  *     fg - group's metadata struct
  22969  *
  22970  * Returns:
  22971  *     BCM_E_RESOURCE - Invalid UDF
  22972  *     BCM_E_NONE     - Success
  22973  */
  22974 STATIC int
  22975 _field_udf_usecount_increment(_field_control_t *fc, _field_group_t *fg)
  22976 {
  22977     int                 idx;
  22978 
  22979     for (idx = 0; idx < BCM_FIELD_USER_NUM_UDFS; idx++) {
  22980         /* coverity[ptr_arith] */
  22981         if (SHR_BITGET(fg->qset.udf_map, idx)) {
  22982             fc->udf[idx].use_count++;
  22983         }
  22984     }
  22985     return (BCM_E_NONE);
  22986 }
  22987 
  22988 /*
  22989  * Function:
  22990  *     _field_group_add_udf_update
  22991  * Purpose:
  22992  *     Update udf usage count.
  22993  * Parameters:
  22994  *     unit     - (IN)     BCM device number.
  22995  *     fsm_ptr  - (IN/OUT) State machine tracking structure.
  22996  * Returns:
  22997  *     BCM_E_XXX
  22998  */
  22999 STATIC int
  23000 _field_group_add_udf_update(int unit, _field_group_add_fsm_t *fsm_ptr)
  23001 {
  23002     /* Input parameters check. */
  23003     if (NULL == fsm_ptr) {
  23004         return (BCM_E_PARAM);
  23005     }
  23006 
  23007     /* Set current state to be previous state. */
  23008     fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state;
  23009 
  23010     /* Increment the use counts for any UDFs used */
  23011     fsm_ptr->rv = _field_udf_usecount_increment(fsm_ptr->fc, fsm_ptr->fg);
  23012     fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END;
  23013 
  23014     return _bcm_field_group_add(unit, fsm_ptr);
  23015 }
  23016 
  23017 /*
  23018  * Function: _field_group_virtual_group_validate
  23019  *
  23020  * Purpose:
  23021  *  Verify that there is no virtual group conflict between
  23022  *  group & other groups in the slice.
  23023  *
  23024  * Parameters:
  23025  *     unit          - (IN)BCM device number.
  23026  *     stage_fc      - (IN)FP stage control info.
  23027  *     fg            - (IN)FP group
  23028  *     slice_numb    - (IN)Slice number where mode is to be programmed.
  23029  *
  23030  * Returns:
  23031  *     BCM_E_NONE      - Success
  23032  *     BCM_E_CONFIG    - Slice is already programmed with conflicting priority.
  23033  *     BCM_E_XXX       - Any other error.
  23034  */
  23035 STATIC int
  23036 _field_group_virtual_group_validate(int unit, _field_stage_t *stage_fc,
  23037                                        _field_group_t *fg, int slice_numb)
  23038 {
  23039     _field_slice_t       *fs;    /* First group slice.          */
  23040     _field_control_t     *fc;
  23041     _field_group_t       *fg_temp = NULL;
  23042 
  23043     /* Input parameters check. */
  23044     if ((NULL == stage_fc) || (NULL == fg)) {
  23045         return (BCM_E_PARAM);
  23046     }
  23047 
  23048     if (slice_numb > stage_fc->tcam_slices) {
  23049         return (BCM_E_PARAM);
  23050     }
  23051 
  23052     LOG_DEBUG(BSL_LS_BCM_FP,
  23053               (BSL_META_U(unit,
  23054                      "FP(unit %d) vverb: _field_group_virtual_group_validate"
  23055                      "(slice_numb=%d, Virtual group=%d)\n"), unit, slice_numb,
  23056                fg->action_res_id));
  23057 
  23058     /*
  23059      *  Since we already checked ports & mode it is enough to check
  23060      *  virtual priority for first slice only.
  23061      */
  23062     fs = stage_fc->slices[fg->instance] + slice_numb;
  23063     if (BCM_PBMP_IS_NULL(fs->pbmp)) {
  23064         /* Slice is not used -> no conflicts. */
  23065         return (BCM_E_NONE);
  23066     }
  23067 
  23068 
  23069     /*
  23070      * If two groups sharing a slice they should have the same action resolution id.
  23071      */
  23072 
  23073     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  23074 
  23075     for (fg_temp =  fc->groups; fg_temp != NULL; fg_temp = fg_temp->next) {
  23076         if (fg_temp->stage_id != stage_fc->stage_id) {
  23077             continue;
  23078         }
  23079 
  23080         if (fg_temp == fg) {
  23081             continue;
  23082         }
  23083 
  23084         /* If slice doesn't belong to group continue */
  23085         if (fg_temp->slices[0].slice_number != fs->slice_number) {
  23086             continue;
  23087         }
  23088 
  23089         if (fg->action_res_id == fg_temp->action_res_id){
  23090             return (BCM_E_NONE);
  23091         }
  23092     }
  23093 
  23094     return (BCM_E_CONFIG);
  23095 }
  23096 
  23097 /*
  23098  * Function: _field_group_virtual_priority_validate
  23099  *
  23100  * Purpose:
  23101  *  Verify that ther is no virtual priority conflict between
  23102  *  group & other groups in the slice.
  23103  *
  23104  * Parameters:
  23105  *     unit          - (IN)BCM device number.
  23106  *     stage_fc      - (IN)FP stage control info.
  23107  *     fg            - (IN)FP group
  23108  *     slice_numb    - (IN)Slice number where mode is to be programmed.
  23109  *
  23110  * Returns:
  23111  *     BCM_E_NONE      - Success
  23112  *     BCM_E_CONFIG    - Slice is already programmed with conflicting priority.
  23113  *     BCM_E_XXX       - Any other error.
  23114  */
  23115 STATIC int
  23116 _field_group_virtual_priority_validate(int unit, _field_stage_t *stage_fc,
  23117                                        _field_group_t *fg, int slice_numb)
  23118 {
  23119     _field_slice_t       *fs;    /* First group slice.          */
  23120     int                  idx;    /* Virtual map iteration index.*/
  23121     _field_virtual_map_t *vmap;  /* Virtual map for stage.      */
  23122 
  23123     /* Input parameters check. */
  23124     if ((NULL == stage_fc) || (NULL == fg)) {
  23125         return (BCM_E_PARAM);
  23126     }
  23127 
  23128     if (slice_numb > stage_fc->tcam_slices) {
  23129         return (BCM_E_PARAM);
  23130     }
  23131 
  23132     LOG_DEBUG(BSL_LS_BCM_FP,
  23133               (BSL_META_U(unit,
  23134                      "FP(unit %d) vverb: _field_group_virtual_priority_validate"
  23135                      "(slice_numb=%d, priority=%d)\n"), unit, slice_numb,
  23136                fg->priority));
  23137 
  23138     /* If group doesn't care about priority - done. */
  23139     if (BCM_FIELD_GROUP_PRIO_ANY == fg->priority) {
  23140         return (BCM_E_NONE);
  23141     }
  23142 
  23143     /*
  23144      *  Since we already checked ports & mode it is enough to check
  23145      *  virtual priority for first slice only.
  23146      */
  23147     fs = stage_fc->slices[fg->instance] + slice_numb;
  23148     if (BCM_PBMP_IS_NULL(fs->pbmp)) {
  23149         /* Slice is not used -> no conflicts. */
  23150         return (BCM_E_NONE);
  23151     }
  23152 
  23153     /*
  23154      * If two groups sharing a slice they should have the same priority.
  23155      */
  23156     vmap = stage_fc->vmap[fg->instance][_FP_VMAP_DEFAULT];
  23157     for (idx = 0; idx < stage_fc->tcam_slices; idx++) {
  23158         if (vmap[idx].valid == FALSE) {
  23159             continue;
  23160         } else {
  23161             if (fs->slice_number != vmap[idx].vmap_key) {
  23162                 continue;
  23163             }
  23164             if (fg->priority != vmap[idx].priority) {
  23165                 return (BCM_E_CONFIG);
  23166             }
  23167         }
  23168     }
  23169     return (BCM_E_NONE);
  23170 }
  23171 
  23172 /*
  23173  * Function: _field_group_ports_validate
  23174  *
  23175  * Purpose:
  23176  *     Test requested group ports against available ports in the slice or
  23177  *     slices needed by the group.
  23178  *
  23179  *     Test to see if mode is appropriate for device. Basically this means
  23180  *     checking for double and triple wide requests on devices that do not
  23181  *     support it. There are additional range checks, but those should almost
  23182  *     never fail.
  23183  *
  23184  * Parameters:
  23185  *     unit          - (IN)BCM device number
  23186  *     stage_fc      - (IN)Stage FP control info.
  23187  *     instance      - (IN)Pipe Instance the group belongs to.
  23188  *     slice_base    - (IN)Primary slice number.
  23189  *     flags         - (IN)Flags with group mode (single, double, triple or Auto-wide).
  23190  *     pbmp          - (IN)Bit map of ports that group is requesting.
  23191  *
  23192  * Returns:
  23193  *     BCM_E_CONFIG    - Requested at least one port unavailable on one or more
  23194  *                       slices.
  23195  *     BCM_E_NONE      - Success
  23196  */
  23197 STATIC int
  23198 _field_group_ports_validate(int unit, const _field_stage_t *stage_fc,
  23199                             int instance, const int slice_base,
  23200                             const uint8 flags, const bcm_pbmp_t pbmp)
  23201 {
  23202     _field_slice_t     *fs;          /* Field slice structure. */
  23203     bcm_pbmp_t          pbmp_temp;
  23204     bcm_pbmp_t          group_pbmp;
  23205 
  23206     LOG_DEBUG(BSL_LS_BCM_FP,
  23207               (BSL_META_U(unit,
  23208                "FP(unit %d) vverb: _field_group_ports_validate(slice_base=%d,"
  23209                " flags=%d)\n"), unit, slice_base, flags));
  23210 
  23211     if (NULL == stage_fc) {
  23212         return (BCM_E_PARAM);
  23213     }
  23214 
  23215     BCM_PBMP_ASSIGN(group_pbmp, pbmp);
  23216 #if defined(BCM_TOMAHAWK_SUPPORT)
  23217     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  23218         ((_BCM_FIELD_STAGE_LOOKUP == stage_fc->stage_id) ||
  23219          (_BCM_FIELD_STAGE_EGRESS == stage_fc->stage_id))) {
  23220 
  23221         /* Read device port configuration. */
  23222         BCM_PBMP_CLEAR(group_pbmp);
  23223         BCM_IF_ERROR_RETURN(_bcm_field_valid_pbmp_get(unit, &group_pbmp));
  23224     }
  23225 #endif /* BCM_TOMAHAWK_SUPPORT */
  23226 
  23227     if (flags & _FP_GROUP_SPAN_TRIPLE_SLICE) {
  23228         if (slice_base % 4 != 0) {
  23229             LOG_DEBUG(BSL_LS_BCM_FP,
  23230                       (BSL_META_U(unit,
  23231                        "FP(unit %d) Error: bad slice=%d for triple-mode.\n"),
  23232                        unit,
  23233                        slice_base));
  23234             return (BCM_E_PARAM);
  23235         }
  23236         if ((slice_base + 2) > stage_fc->tcam_slices) {
  23237             return (BCM_E_CONFIG);
  23238         }
  23239         fs = stage_fc->slices[instance] + slice_base + 2;
  23240         BCM_PBMP_ASSIGN(pbmp_temp, fs->pbmp);
  23241         BCM_PBMP_AND(pbmp_temp, group_pbmp);
  23242         if (BCM_PBMP_NOT_NULL(pbmp_temp)) {
  23243             LOG_DEBUG(BSL_LS_BCM_FP,
  23244                       (BSL_META_U(unit,
  23245                                   "FP(unit %d) vverb: slice=%d in-use.\n"),
  23246                        unit, slice_base));
  23247             return (BCM_E_CONFIG);
  23248         }
  23249     }
  23250 
  23251     if ((flags & _FP_GROUP_SPAN_DOUBLE_SLICE) ||
  23252         (flags & _FP_GROUP_SPAN_TRIPLE_SLICE)) {
  23253 
  23254         if (slice_base % 2 != 0) {
  23255             LOG_DEBUG(BSL_LS_BCM_FP,
  23256                       (BSL_META_U(unit,
  23257                        "FP(unit %d) Error: bad slice=%d for double-mode.\n"),
  23258                        unit,
  23259                        slice_base));
  23260             return (BCM_E_PARAM);
  23261         }
  23262 
  23263         if ((slice_base + 1) > stage_fc->tcam_slices) {
  23264             return (BCM_E_CONFIG);
  23265         }
  23266         fs = stage_fc->slices[instance] + slice_base + 1;
  23267         /* If group is intraslice verify that slice is intraslice capable. */
  23268         if (flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)  {
  23269              if (0 == (fs->slice_flags & _BCM_FIELD_SLICE_INTRASLICE_CAPABLE)) {
  23270                  return (BCM_E_CONFIG);
  23271              }
  23272         }
  23273 
  23274         BCM_PBMP_ASSIGN(pbmp_temp, fs->pbmp);
  23275         BCM_PBMP_AND(pbmp_temp, group_pbmp);
  23276         if (BCM_PBMP_NOT_NULL(pbmp_temp)) {
  23277             LOG_DEBUG(BSL_LS_BCM_FP,
  23278                       (BSL_META_U(unit,
  23279                                   "FP(unit %d) vverb: slice=%d in-use.\n"),
  23280                        unit, slice_base));
  23281             return (BCM_E_CONFIG);
  23282         }
  23283     }
  23284 
  23285     fs = stage_fc->slices[instance] + slice_base;
  23286     /* If group is intraslice verify that slice is intraslice capable. */
  23287     if (flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)  {
  23288         if (0 == (fs->slice_flags & _BCM_FIELD_SLICE_INTRASLICE_CAPABLE)) {
  23289             return (BCM_E_CONFIG);
  23290         }
  23291     }
  23292 
  23293     BCM_PBMP_ASSIGN(pbmp_temp, fs->pbmp);
  23294     BCM_PBMP_AND(pbmp_temp, group_pbmp);
  23295     if (BCM_PBMP_NOT_NULL(pbmp_temp)) {
  23296         LOG_DEBUG(BSL_LS_BCM_FP,
  23297                   (BSL_META_U(unit,
  23298                               "FP(unit %d) vverb: slice=%d in-use.\n"),
  23299                    unit, slice_base));
  23300         return (BCM_E_CONFIG);
  23301     }
  23302 
  23303     return (BCM_E_NONE);
  23304 }
  23305 
  23306 /*
  23307  * Function: _field_group_slice_mode_validate
  23308  *
  23309  * Purpose:
  23310  *     Check if group can use the slice e.g.
  23311  *     per slice configuration for other installed groups
  23312  *     doesn't create a conflict.
  23313  * Parameters:
  23314  *     unit      - (IN)BCM device number.
  23315  *     slice_num - (IN)Group slice number.
  23316  *     fs        - (IN)Slice control structure.
  23317  *     fg        - (IN)Field group structure.
  23318  *
  23319  * Returns:
  23320  *     BCM_E_NONE      - No conflicts
  23321  *     BCM_E_CONFIG    - Slice is already programmed with conflicting mode.
  23322  *     BCM_E_XXX - other errors.
  23323  */
  23324 STATIC int
  23325 _field_group_slice_mode_validate(int unit, int slice_num,
  23326                                  _field_slice_t *fs, _field_group_t *fg)
  23327 {
  23328     uint8          slice_number;       /* Slices iterator.        */
  23329     int            idx;                /* Slice iteration index.  */
  23330     int            parts_count = 0;    /* Number of entry parts.  */
  23331     int            rv;                 /* Operation return status.*/
  23332 
  23333     /* Input parameters check. */
  23334     if ((NULL == fs) || (NULL == fg)) {
  23335         return (BCM_E_PARAM);
  23336     }
  23337 
  23338     if (BCM_PBMP_IS_NULL(fs->pbmp)) {
  23339         /* Slice is not used -> no conflicts. */
  23340         return (BCM_E_NONE);
  23341     }
  23342 
  23343     /* Check for single/double/triple wide mode match. */
  23344     if ((fg->flags & _FP_GROUP_STATUS_MASK) !=
  23345         (fs->group_flags & _FP_GROUP_STATUS_MASK)) {
  23346         return (BCM_E_CONFIG);
  23347     }
  23348 
  23349     /* Get number of entry parts. */
  23350     rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
  23351                                             fg->flags, &parts_count);
  23352     BCM_IF_ERROR_RETURN(rv);
  23353 
  23354     for (idx = 0; idx < parts_count; idx++) {
  23355         /* Get slice id for entry part */
  23356         rv = _bcm_field_tcam_part_to_slice_number(unit, idx, fg,
  23357                                                   &slice_number);
  23358         BCM_IF_ERROR_RETURN(rv);
  23359 
  23360         /* Get slice pointer. */
  23361         fs += slice_number;
  23362 
  23363         /* Source class selection comparison. */
  23364         if ((_FP_SELCODE_DONT_CARE != fs->src_class_sel) &&
  23365             (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].src_class_sel) &&
  23366             (fs->src_class_sel != fg->sel_codes[idx].src_class_sel)) {
  23367             return (BCM_E_CONFIG);
  23368         }
  23369 
  23370         /* Destination class selection comparison. */
  23371         if ((_FP_SELCODE_DONT_CARE != fs->dst_class_sel) &&
  23372             (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].dst_class_sel) &&
  23373             (fs->dst_class_sel != fg->sel_codes[idx].dst_class_sel)) {
  23374             return (BCM_E_CONFIG);
  23375         }
  23376         /* Interface class selection comparison. */
  23377         if ((_FP_SELCODE_DONT_CARE != fs->intf_class_sel) &&
  23378             (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].intf_class_sel) &&
  23379             (fs->intf_class_sel != fg->sel_codes[idx].intf_class_sel)) {
  23380             return (BCM_E_CONFIG);
  23381         }
  23382         /* Loopback type/Tunnel type selection comparison. */
  23383         if ((_FP_SELCODE_DONT_CARE != fs->loopback_type_sel) &&
  23384             (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].loopback_type_sel) &&
  23385             (fs->loopback_type_sel != fg->sel_codes[idx].loopback_type_sel)) {
  23386             return (BCM_E_CONFIG);
  23387         }
  23388         /* Ingress entity selection comparison. */
  23389         if ((_FP_SELCODE_DONT_CARE != fs->ingress_entity_sel) &&
  23390             (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].ingress_entity_sel) &&
  23391             (fs->ingress_entity_sel != fg->sel_codes[idx].ingress_entity_sel)) {
  23392             return (BCM_E_CONFIG);
  23393         }
  23394         /* Src entity selection comparison. */
  23395         if ((_FP_SELCODE_DONT_CARE != fs->src_entity_sel) &&
  23396             (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].src_entity_sel) &&
  23397             (fs->src_entity_sel != fg->sel_codes[idx].src_entity_sel)) {
  23398             return (BCM_E_CONFIG);
  23399         }
  23400         /* Dstination forwarding entity selection comparison. */
  23401         if ((_FP_SELCODE_DONT_CARE != fs->dst_fwd_entity_sel) &&
  23402             (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].dst_fwd_entity_sel) &&
  23403             (fs->dst_fwd_entity_sel != fg->sel_codes[idx].dst_fwd_entity_sel)) {
  23404             return (BCM_E_CONFIG);
  23405         }
  23406 
  23407         /* Dstination forwarding entity selection comparison. */
  23408         if ((_FP_SELCODE_DONT_CARE != fs->fwd_field_sel) &&
  23409             (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].fwd_field_sel) &&
  23410             (fs->fwd_field_sel != fg->sel_codes[idx].fwd_field_sel)) {
  23411             return (BCM_E_CONFIG);
  23412         }
  23413 
  23414         if ((_FP_SELCODE_DONT_CARE != fs->ttl_class_sel) &&
  23415             (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].ttl_class_sel) &&
  23416             (fs->ttl_class_sel != fg->sel_codes[idx].ttl_class_sel)) {
  23417             return (BCM_E_CONFIG);
  23418         }
  23419 
  23420         if ((_FP_SELCODE_DONT_CARE != fs->tos_class_sel) &&
  23421             (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].tos_class_sel) &&
  23422             (fs->tos_class_sel != fg->sel_codes[idx].tos_class_sel)) {
  23423             return (BCM_E_CONFIG);
  23424         }
  23425 
  23426         if ((_FP_SELCODE_DONT_CARE != fs->tcp_class_sel) &&
  23427             (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].tcp_class_sel) &&
  23428             (fs->tcp_class_sel != fg->sel_codes[idx].tcp_class_sel)) {
  23429             return (BCM_E_CONFIG);
  23430         }
  23431 
  23432         if ((_FP_SELCODE_DONT_CARE != fs->aux_tag_1_sel) &&
  23433             (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].aux_tag_1_sel) &&
  23434             (fs->aux_tag_1_sel != fg->sel_codes[idx].aux_tag_1_sel)) {
  23435             return (BCM_E_CONFIG);
  23436         }
  23437 
  23438         if ((_FP_SELCODE_DONT_CARE != fs->aux_tag_2_sel) &&
  23439             (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].aux_tag_2_sel) &&
  23440             (fs->aux_tag_2_sel != fg->sel_codes[idx].aux_tag_2_sel)) {
  23441             return (BCM_E_CONFIG);
  23442         }
  23443 
  23444         if ((_FP_SELCODE_DONT_CARE != fs->oam_overlay_sel) &&
  23445             (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].oam_overlay_sel) &&
  23446             (fs->oam_overlay_sel != fg->sel_codes[idx].oam_overlay_sel)) {
  23447             return (BCM_E_CONFIG);
  23448         }
  23449         if (fs->egr_class_f1_sel != _FP_SELCODE_DONT_CARE
  23450             && fg->sel_codes[idx].egr_class_f1_sel != _FP_SELCODE_DONT_CARE
  23451             && fs->egr_class_f1_sel != fg->sel_codes[idx].egr_class_f1_sel
  23452             ) {
  23453             return (BCM_E_CONFIG);
  23454         }
  23455 
  23456         if (fs->egr_class_f2_sel != _FP_SELCODE_DONT_CARE
  23457             && fg->sel_codes[idx].egr_class_f2_sel != _FP_SELCODE_DONT_CARE
  23458             && fs->egr_class_f2_sel != fg->sel_codes[idx].egr_class_f2_sel
  23459             ) {
  23460             return (BCM_E_CONFIG);
  23461         }
  23462 
  23463         if (fs->egr_class_f3_sel != _FP_SELCODE_DONT_CARE
  23464             && fg->sel_codes[idx].egr_class_f3_sel != _FP_SELCODE_DONT_CARE
  23465             && fs->egr_class_f3_sel != fg->sel_codes[idx].egr_class_f3_sel
  23466             ) {
  23467             return (BCM_E_CONFIG);
  23468         }
  23469 
  23470         if (fs->egr_class_f4_sel != _FP_SELCODE_DONT_CARE
  23471             && fg->sel_codes[idx].egr_class_f4_sel != _FP_SELCODE_DONT_CARE
  23472             && fs->egr_class_f4_sel != fg->sel_codes[idx].egr_class_f4_sel
  23473             ) {
  23474             return (BCM_E_CONFIG);
  23475         }
  23476 
  23477         if (fs->src_dest_class_f1_sel != _FP_SELCODE_DONT_CARE
  23478             && fg->sel_codes[idx].src_dest_class_f1_sel != _FP_SELCODE_DONT_CARE
  23479             && fs->src_dest_class_f1_sel != fg->sel_codes[idx].src_dest_class_f1_sel
  23480             ) {
  23481             return (BCM_E_CONFIG);
  23482         }
  23483 
  23484         if (fs->src_dest_class_f3_sel != _FP_SELCODE_DONT_CARE
  23485             && fg->sel_codes[idx].src_dest_class_f3_sel != _FP_SELCODE_DONT_CARE
  23486             && fs->src_dest_class_f3_sel != fg->sel_codes[idx].src_dest_class_f3_sel
  23487             ) {
  23488             return (BCM_E_CONFIG);
  23489         }
  23490 
  23491         if (fs->egr_key4_dvp_sel != _FP_SELCODE_DONT_CARE
  23492             && fg->sel_codes[idx].egr_key4_dvp_sel != _FP_SELCODE_DONT_CARE
  23493             && fs->egr_key4_dvp_sel != fg->sel_codes[idx].egr_key4_dvp_sel
  23494             ) {
  23495             return (BCM_E_CONFIG);
  23496         }
  23497 
  23498         if (fs->egr_key4_mdl_sel != _FP_SELCODE_DONT_CARE
  23499             && fg->sel_codes[idx].egr_key4_mdl_sel != _FP_SELCODE_DONT_CARE
  23500             && fs->egr_key4_mdl_sel != fg->sel_codes[idx].egr_key4_mdl_sel
  23501             ) {
  23502             return (BCM_E_CONFIG);
  23503         }
  23504 
  23505         if (fs->egr_oam_overlay_sel != _FP_SELCODE_DONT_CARE
  23506             && fg->sel_codes[idx].egr_oam_overlay_sel != _FP_SELCODE_DONT_CARE
  23507             && fs->egr_oam_overlay_sel != fg->sel_codes[idx].egr_oam_overlay_sel
  23508             ) {
  23509             return (BCM_E_CONFIG);
  23510         }
  23511 
  23512         if (fs->oam_intf_class_sel != _FP_SELCODE_DONT_CARE
  23513                 && fg->sel_codes[idx].oam_intf_class_sel != _FP_SELCODE_DONT_CARE
  23514                 && fs->oam_intf_class_sel != fg->sel_codes[idx].oam_intf_class_sel
  23515            ) {
  23516             return (BCM_E_CONFIG);
  23517         }
  23518 
  23519         if (fs->egr_dest_port_f1_sel != _FP_SELCODE_DONT_CARE
  23520             && fg->sel_codes[idx].egr_dest_port_f1_sel != _FP_SELCODE_DONT_CARE
  23521             && fs->egr_dest_port_f1_sel != fg->sel_codes[idx].egr_dest_port_f1_sel
  23522             ) {
  23523             return (BCM_E_CONFIG);
  23524         }
  23525 
  23526         if (fs->egr_dest_port_f5_sel != _FP_SELCODE_DONT_CARE
  23527             && fg->sel_codes[idx].egr_dest_port_f5_sel != _FP_SELCODE_DONT_CARE
  23528             && fs->egr_dest_port_f5_sel != fg->sel_codes[idx].egr_dest_port_f5_sel
  23529             ) {
  23530             return (BCM_E_CONFIG);
  23531         }
  23532 
  23533         /* Set intraslice double wide key selection. */
  23534         if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
  23535             if (((idx == _FP_INTRA_SLICE_PART_1) ||
  23536                  (idx == _FP_INTRA_SLICE_PART_3)) &&
  23537                 ((_FP_SELCODE_DONT_CARE != fs->doublewide_key_select) &&
  23538                  (_FP_SELCODE_DONT_CARE != fg->sel_codes[idx].fpf2) &&
  23539                  (fs->doublewide_key_select != fg->sel_codes[idx].fpf2))) {
  23540                 return (BCM_E_CONFIG);
  23541             }
  23542         }
  23543     }
  23544     return (BCM_E_NONE);
  23545 }
  23546 
  23547 /*
  23548  * Function: _field_group_mode_validate
  23549  *
  23550  * Purpose:
  23551  *      Check if set of slices are usable for a new group.
  23552  *
  23553  * Parameters:
  23554  *     unit          - (IN)BCM device number.
  23555  *     stage_fc      - (IN)FP stage control info.
  23556  *     fg            - (IN)FP group
  23557  *     slice_numb    - (IN)Slice number where mode is to be programmed.
  23558  *
  23559  * Returns:
  23560  *     BCM_E_NONE      - Success
  23561  *     BCM_E_CONFIG    - Slice is already programmed with conflicting mode.
  23562  *     BCM_E_XXX       - Any other error.
  23563  */
  23564 STATIC int
  23565 _field_group_mode_validate(int unit, _field_stage_t *stage_fc,
  23566                            _field_group_t *fg, int slice_numb)
  23567 {
  23568     _field_slice_t *fs;
  23569 
  23570     /* Input parameters check. */
  23571     if ((NULL == stage_fc) || (NULL == fg)) {
  23572        return (BCM_E_PARAM);
  23573     }
  23574 
  23575     if (slice_numb > stage_fc->tcam_slices) {
  23576        return (BCM_E_PARAM);
  23577     }
  23578 
  23579     LOG_DEBUG(BSL_LS_BCM_FP,
  23580               (BSL_META_U(unit,
  23581               "FP(unit %d) vverb: _field_group_mode_validate(slice_numb=%d, "
  23582               "flags=%d)\n"), unit, slice_numb, fg->flags));
  23583 
  23584     /* Confirm that mode will work on specific slice(s). If another group is
  23585      * already defined on slice(s), then the requested mode has to match
  23586      * the hardware mode. */
  23587     fs = stage_fc->slices[fg->instance] + slice_numb;
  23588 
  23589     return
  23590       _field_group_slice_mode_validate(unit, _FP_INTER_SLICE_PART_2, fs, fg);
  23591 }
  23592 
  23593 /*
  23594  * Function:
  23595  *     _field_group_add_slice_validate
  23596  * Purpose:
  23597  *     Validate a candidate slice if it fits for a group.
  23598  * Parameters:
  23599  *     unit     - (IN  BCM device number.
  23600  *     stage_fc - (IN) State machine tracking structure.
  23601  *     fg       - (IN) Field group structure.
  23602  *     slice_id - (IN) Candidate slice id.
  23603  * Returns:
  23604  *     BCM_E_XXX
  23605  */
  23606 STATIC int
  23607 _field_group_add_slice_validate(int unit, _field_stage_t *stage_fc,
  23608                                 _field_group_t *fg, int slice_id)
  23609 {
  23610     int rv;                       /* Operation return status. */
  23611     int virtual_priority = FALSE;/* Virtual priority support flag.*/
  23612 
  23613     /* Input parameters check. */
  23614     if ((NULL == stage_fc) || (NULL == fg)) {
  23615         return (BCM_E_PARAM);
  23616     }
  23617 
  23618     _field_virtual_priority_support(unit, stage_fc, &virtual_priority);
  23619 
  23620     /*
  23621      * If this slice belongs to an auto-expanded group, AND
  23622      *     is not the first one of that group,
  23623      *         cannot use it
  23624      */
  23625     if (stage_fc->slices[fg->instance][slice_id].prev != NULL) {
  23626         return (BCM_E_CONFIG);
  23627     }
  23628 
  23629     /*
  23630      *  Skip the slice if group is intraslice and
  23631      *  slice is not intraslice capable.
  23632      */
  23633     if ((fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) &&
  23634         (0 == (stage_fc->slices[fg->instance][slice_id].slice_flags &
  23635                _BCM_FIELD_SLICE_INTRASLICE_CAPABLE))) {
  23636         return (BCM_E_CONFIG);
  23637     }
  23638 
  23639     /*
  23640      *  Skip the slice if group slice size is small  and
  23641      *  slice is not of smaller size.
  23642      */
  23643     if ((fg->flags & _FP_GROUP_SELECT_SMALL_SLICE) &&
  23644         (0 == (stage_fc->slices[fg->instance][slice_id].slice_flags &
  23645                _BCM_FIELD_SLICE_SIZE_SMALL))) {
  23646         return (BCM_E_CONFIG);
  23647     }
  23648 
  23649     /*
  23650      *  Skip the slice if group slice size is large  and
  23651      *  slice is not of large size.
  23652      */
  23653     if ((fg->flags & _FP_GROUP_SELECT_LARGE_SLICE) &&
  23654         (0 == (stage_fc->slices[fg->instance][slice_id].slice_flags &
  23655                _BCM_FIELD_SLICE_SIZE_LARGE))) {
  23656         return (BCM_E_CONFIG);
  23657     }
  23658 
  23659     /*
  23660      *  Make sure there is no conflict between groups ports
  23661      *  and other groups in the slice.
  23662      */
  23663     rv = _field_group_ports_validate(unit, stage_fc, fg->instance, slice_id,
  23664                                      fg->flags, fg->pbmp);
  23665     BCM_IF_ERROR_RETURN(rv);
  23666 
  23667     /*
  23668      *  Make sure there is no conflict between
  23669      *  group & other groups mode. (single/double/triple)
  23670      *  do not coexist.
  23671      */
  23672     rv = _field_group_mode_validate(unit, stage_fc, fg, slice_id);
  23673     BCM_IF_ERROR_RETURN(rv);
  23674 
  23675     /*
  23676      *  Make sure there is no virtual priority conflict between
  23677      *  group & other groups in the slice.
  23678      */
  23679     if (virtual_priority) {
  23680         if (stage_fc->flags & _FP_STAGE_AUTO_EXPANSION) {
  23681             fg->flags |= _FP_GROUP_SELECT_AUTO_EXPANSION;
  23682         }
  23683         rv = _field_group_virtual_priority_validate(unit, stage_fc,
  23684                                                     fg, slice_id);
  23685         BCM_IF_ERROR_RETURN(rv);
  23686         rv = _field_group_virtual_group_validate(unit, stage_fc,
  23687                                                     fg, slice_id);
  23688         BCM_IF_ERROR_RETURN(rv);
  23689     }
  23690 
  23691     return (BCM_E_NONE);
  23692 }
  23693 
  23694 /*
  23695  * Function:
  23696  *     _field_virtual_priority_support
  23697  * Purpose:
  23698  *     Check if device supports virtual priority.
  23699  * Parameters:
  23700  *     unit     - (IN) BCM device number.
  23701  *     stage_fc - (IN) Field stage control.
  23702  *     support  - (OUT) TRUE supports virtual priority.
  23703  *                      FALSE otherwise.
  23704  * Returns:
  23705  *     BCM_E_XXX
  23706  */
  23707 int
  23708 _field_virtual_priority_support(int unit, _field_stage_t *stage_fc, int *support)
  23709 {
  23710 
  23711     /* Input parameters check. */
  23712     if ((NULL == stage_fc) ||  (NULL == support)){
  23713         return (BCM_E_PARAM);
  23714     }
  23715 
  23716     if (0 == soc_feature(unit, soc_feature_field_virtual_slice_group)) {
  23717         *support = FALSE;
  23718     } else if (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) {
  23719         *support = TRUE;
  23720     } else if (SOC_IS_FIREBOLT2(unit)) {
  23721         *support = FALSE;
  23722     } else {
  23723         *support = TRUE;
  23724     }
  23725     return (BCM_E_NONE);
  23726 }
  23727 
  23728 /*
  23729  * Function:
  23730  *     _field_group_add_slice_allocate
  23731  * Purpose:
  23732  *     Allocate slice for a new group.
  23733  * Parameters:
  23734  *     unit     - (IN)     BCM device number.
  23735  *     fsm_ptr  - (IN/OUT) State machine tracking structure.
  23736  * Returns:
  23737  *     BCM_E_XXX
  23738  */
  23739 STATIC int
  23740 _field_group_add_slice_allocate(int unit, _field_group_add_fsm_t *fsm_ptr)
  23741 {
  23742     _field_group_t      *fg;             /* Field group pointer.          */
  23743     _field_stage_t      *stage_fc;       /* Stage field control.          */
  23744     int                 slice_id;        /* Slices iterator.              */
  23745     int                 virtual_priority = FALSE;/* Virtual priority support flag.*/
  23746 
  23747     /* Input parameters check. */
  23748     if (NULL == fsm_ptr) {
  23749         return (BCM_E_PARAM);
  23750     }
  23751 
  23752     /* Group pointer initialization. */
  23753     fg = fsm_ptr->fg;
  23754     stage_fc = fsm_ptr->stage_fc;
  23755     slice_id = -1;
  23756 
  23757     _field_virtual_priority_support(unit, stage_fc, &virtual_priority);
  23758 
  23759     if ((_BCM_FIELD_STAGE_EXTERNAL == fg->stage_id)) {
  23760         /* External slices mapped 1-1 to selected keys.*/
  23761         fg->slices = stage_fc->slices[_FP_DEF_INST] + fg->sel_codes[0].extn;
  23762         slice_id = fg->sel_codes[0].extn;
  23763     } else if ((BCM_FIELD_GROUP_PRIO_ANY == fsm_ptr->priority) || (virtual_priority)) {
  23764         /* If not specified, generate a priority. */
  23765         for (slice_id = 0; slice_id < stage_fc->tcam_slices; slice_id++) {
  23766             fsm_ptr->rv = _field_group_add_slice_validate(unit, stage_fc,
  23767                                                           fg, slice_id);
  23768             if(BCM_SUCCESS(fsm_ptr->rv)) {
  23769                 break;
  23770             }
  23771         }
  23772         /* Check if allocation was successful. */
  23773         if (slice_id == stage_fc->tcam_slices) {
  23774             fsm_ptr->rv = (BCM_E_RESOURCE);
  23775         }
  23776     } else {
  23777         if ((fsm_ptr->priority < 0) ||
  23778             (fsm_ptr->stage_fc->tcam_slices <= fsm_ptr->priority)) {
  23779             LOG_ERROR(BSL_LS_BCM_FP,
  23780                       (BSL_META_U(unit,
  23781                                   "FP(unit %d) Error: pri=%d out-of-range.\n"),
  23782                        unit, fsm_ptr->priority));
  23783             fsm_ptr->rv = BCM_E_PARAM;
  23784         } else {
  23785             slice_id = fsm_ptr->priority;
  23786             fsm_ptr->rv = _field_group_add_slice_validate(unit, stage_fc,
  23787                                                           fg, slice_id);
  23788         }
  23789     }
  23790 
  23791     if (BCM_FAILURE(fsm_ptr->rv)) {
  23792         /* Different select codes might help for 5682x devices. */
  23793         if ((soc_feature(unit, soc_feature_two_ingress_pipes)) &&
  23794             (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) &&
  23795             ((0 == (fsm_ptr->priority % 2)) ||
  23796              (BCM_FIELD_GROUP_PRIO_ANY == fsm_ptr->priority))) {
  23797             fsm_ptr->rv = (BCM_E_NONE);
  23798             fsm_ptr->flags &= ~_BCM_FP_GROUP_ADD_INTRA_SLICE;
  23799             fg->flags &= ~_FP_GROUP_INTRASLICE_DOUBLEWIDE;
  23800             fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET;
  23801         } else if (fsm_ptr->fsm_state_prev ==
  23802                   _BCM_FP_GROUP_ADD_STATE_SLICE_ALIGN) {
  23803             fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END;
  23804         } else if ((fsm_ptr->fsm_state_prev !=
  23805                     _BCM_FP_GROUP_ADD_STATE_CAM_COMPRESS) && virtual_priority) {
  23806             fsm_ptr->rv = (BCM_E_NONE);
  23807             fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_CAM_COMPRESS;
  23808         } else {
  23809             if ((fsm_ptr->fsm_state_prev ==
  23810                   _BCM_FP_GROUP_ADD_STATE_CAM_COMPRESS) && virtual_priority &&
  23811                   (fsm_ptr->rv == BCM_E_RESOURCE) &&
  23812                   (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) &&
  23813                   (fg->stage_id == _BCM_FIELD_STAGE_INGRESS) &&
  23814                   (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)
  23815                 ) {
  23816                 /* If there are atleast two free slices to create a
  23817                  * double wide group. But, if the slices are not in
  23818                  * consecutive locations, then state slice align is
  23819                  * set to align the slices
  23820                  */
  23821                 fsm_ptr->rv = (BCM_E_NONE);
  23822                 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SLICE_ALIGN;
  23823             } else if ((fsm_ptr->fsm_state_prev ==
  23824                   _BCM_FP_GROUP_ADD_STATE_CAM_COMPRESS) &&
  23825                   (fsm_ptr->rv == BCM_E_RESOURCE) &&
  23826                   (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) &&
  23827                   (fg->stage_id == _BCM_FIELD_STAGE_LOOKUP)) {
  23828                 /* For VFP stage, If there are atleast two free slices to
  23829                  *  create a double wide group. But, if the slices are not in
  23830                  * consecutive locations, then state slice align is
  23831                  * set to align the slices
  23832                  */
  23833                 fsm_ptr->rv = (BCM_E_NONE);
  23834                 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SLICE_ALIGN;
  23835             } else {
  23836                 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END;
  23837             }
  23838         }
  23839     } else {
  23840         fg->slices = stage_fc->slices[fg->instance] + slice_id;
  23841         fsm_ptr->rv = _field_group_add_selcodes_install(unit, fsm_ptr);
  23842         if (BCM_SUCCESS(fsm_ptr->rv)) {
  23843             fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_HW_QUAL_LIST_GET;
  23844         } else {
  23845             fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END;
  23846         }
  23847     }
  23848     /* Set current state to be previous state. */
  23849     fsm_ptr->fsm_state_prev = _BCM_FP_GROUP_ADD_STATE_SLICE_ALLOCATE;
  23850     return _bcm_field_group_add(unit, fsm_ptr);
  23851 }
  23852 
  23853 /*
  23854  * Function: _field_group_compress
  23855  *
  23856  * Purpose:
  23857  *     Compress filed group entries,
  23858  *     in order to free slices used by the group.
  23859  * Paramters:
  23860  *     unit     - (IN) BCM device number
  23861  *     fg       - (IN) Field group structure
  23862  *     stage_fc - (IN) Stage field control structure.
  23863  * Returns:
  23864  *     BCM_E_XXX
  23865  */
  23866 
  23867 int
  23868 _field_group_compress(int unit, _field_group_t *fg,
  23869                       _field_stage_t *stage_fc)
  23870 {
  23871     _field_slice_t       *fs; /* Field slice structure.         */
  23872     _field_slice_t      *efs; /* Slice that contains free slots.*/
  23873     int                 eidx; /* Empty slot index.              */
  23874     int                  idx; /* Slice iteration index.         */
  23875     int             tmp_idx1; /* Slice entry index 1.           */
  23876     int             tmp_idx2; /* Slice entry index 2.           */
  23877     int             slice_sz; /* Number of entries in a slice.  */
  23878     int                   rv; /* Operation return status.       */
  23879 
  23880     /* Input parameters check. */
  23881     if (NULL == fg) {
  23882         return (BCM_E_PARAM);
  23883     }
  23884 
  23885     /* Stage External doesn't require compression. */
  23886     if (_BCM_FIELD_STAGE_EXTERNAL == fg->stage_id) {
  23887         return (BCM_E_NONE);
  23888     }
  23889 
  23890     /* Get group slice pointer. */
  23891     fs = fg->slices;
  23892 
  23893     efs = NULL;
  23894     eidx = -1;
  23895     while (NULL != fs) {
  23896         _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs, slice_sz);
  23897         for (idx = 0; idx < slice_sz; idx ++)  {
  23898             /* Find an empty slot. */
  23899             if (NULL == fs->entries[idx]) {
  23900                 if (NULL == efs) {
  23901                     efs = fs;
  23902                     eidx = idx;
  23903                 }
  23904                 continue;
  23905             }
  23906 
  23907             if (NULL != efs) {
  23908                 rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc,
  23909                                                          fg->instance,
  23910                                                          efs->slice_number,
  23911                                                          eidx, &tmp_idx1);
  23912                 BCM_IF_ERROR_RETURN(rv);
  23913 
  23914                 rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc,
  23915                                                          fg->instance,
  23916                                                          fs->slice_number,
  23917                                                          idx, &tmp_idx2);
  23918                 BCM_IF_ERROR_RETURN(rv);
  23919 
  23920                 rv = _field_entry_move(unit, fs->entries[idx],
  23921                                        (tmp_idx1 - tmp_idx2));
  23922                 BCM_IF_ERROR_RETURN(rv);
  23923                 fs = efs;
  23924                 idx = eidx;
  23925                 efs = NULL;
  23926                 eidx = -1;
  23927                 _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs, slice_sz);
  23928             }
  23929         }
  23930         fs = fs->next;
  23931     }
  23932     rv = _field_group_free_unused_slices(unit, stage_fc, fg);
  23933     return (rv);
  23934 }
  23935 
  23936 /*
  23937  * Function:
  23938  *     _field_stage_groups_compress
  23939  * Purpose:
  23940  *     Compress stage groups to free room for inserted group.
  23941  * Parameters:
  23942  *     unit      - (IN) BCM device number.
  23943  *     fc        - (IN) Field control structure.
  23944  *     stage_fc  - (IN) Stage field control.
  23945  * Returns:
  23946  *     BCM_E_XXX
  23947  */
  23948 STATIC int
  23949 _field_stage_groups_compress(int unit, _field_control_t *fc,
  23950                              _field_stage_t *stage_fc)
  23951 {
  23952     _field_group_t *fg;              /* Field group structure. */
  23953     int             rv = BCM_E_NONE; /* Operation return Status */
  23954 
  23955     /* Input parameters check. */
  23956     if ((NULL == fc) || (NULL == stage_fc)) {
  23957         return (BCM_E_PARAM);
  23958     }
  23959 
  23960     /* Compress expanded groups. */
  23961     for (fg = fc->groups; fg != NULL; fg = fg->next) {
  23962         /* Skip other stages. */
  23963         if (fg->stage_id != stage_fc->stage_id) {
  23964             continue;
  23965         }
  23966 
  23967         /* Skip new group. */
  23968         if (NULL == fg->slices) {
  23969             continue;
  23970         }
  23971 
  23972         /* Ignore not expanded groups. */
  23973         if (NULL == fg->slices->next)  {
  23974             continue;
  23975         }
  23976 
  23977         /* Best effort to compress expanded virtual groups. */
  23978         rv = _field_group_compress(unit, fg, stage_fc);
  23979     }
  23980     return (rv);
  23981 }
  23982 
  23983 /*
  23984  * Function:
  23985  *     _field_group_add_cam_compress
  23986  * Purpose:
  23987  *     Compress other groups to free room for inserted group.
  23988  * Parameters:
  23989  *     unit     - (IN)     BCM device number.
  23990  *     fsm_ptr  - (IN/OUT) State machine tracking structure.
  23991  * Returns:
  23992  *     BCM_E_XXX
  23993  */
  23994 STATIC int
  23995 _field_group_add_cam_compress(int unit, _field_group_add_fsm_t *fsm_ptr)
  23996 {
  23997     /* Set current state to be previous state. */
  23998     fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state;
  23999 
  24000     /* Compress expanded groups. */
  24001     fsm_ptr->rv =
  24002         (_field_stage_groups_compress(unit, fsm_ptr->fc, fsm_ptr->stage_fc));
  24003 
  24004     if (BCM_SUCCESS(fsm_ptr->rv)) {
  24005        /* Retry allocating slice/s for the new field group. */
  24006        fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SLICE_ALLOCATE;
  24007     } else {
  24008        fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END;
  24009     }
  24010 
  24011 
  24012     return _bcm_field_group_add(unit, fsm_ptr);
  24013 }
  24014 
  24015 /*
  24016  * Function:
  24017  *     _bcm_field_group_selcode_initialize
  24018  * Purpose:
  24019  *     Initialize selcodes of a group in a slice.
  24020  * Parameters:
  24021  *     unit      - (IN) BCM device number.
  24022  *     fg        - (IN) Group in the slice.
  24023  *     fs        - (IN) Field slice.
  24024  *     part_index- (IN) part index of group belonging to slice
  24025  * Returns:
  24026  *     BCM_E_XXX
  24027  */
  24028 int _bcm_field_group_selcode_initialize(int unit,
  24029                               _field_group_t *fg, _field_slice_t *fs,
  24030                               int part_index) {
  24031     if (fg == NULL || fs == NULL) {
  24032         return BCM_E_PARAM;
  24033     }
  24034     /* Set source class selection. */
  24035     if (_FP_SELCODE_DONT_CARE != fg->sel_codes[part_index].src_class_sel) {
  24036         fs->src_class_sel = fg->sel_codes[part_index].src_class_sel;
  24037     }
  24038     /* Set destination class selection. */
  24039     if (_FP_SELCODE_DONT_CARE != fg->sel_codes[part_index].dst_class_sel) {
  24040         fs->dst_class_sel = fg->sel_codes[part_index].dst_class_sel;
  24041     }
  24042     /* Set interface class selection. */
  24043     if (_FP_SELCODE_DONT_CARE != fg->sel_codes[part_index].intf_class_sel) {
  24044         fs->intf_class_sel = fg->sel_codes[part_index].intf_class_sel;
  24045     }
  24046     /* Set loopback type/tunnel type selection. */
  24047     if (_FP_SELCODE_DONT_CARE != fg->sel_codes[part_index].loopback_type_sel) {
  24048         fs->loopback_type_sel = fg->sel_codes[part_index].loopback_type_sel;
  24049     }
  24050     /* Set ingress entity type selection. */
  24051     if (_FP_SELCODE_DONT_CARE != fg->sel_codes[part_index].ingress_entity_sel) {
  24052         fs->ingress_entity_sel = fg->sel_codes[part_index].ingress_entity_sel;
  24053     }
  24054     /* Set src entity type selection. */
  24055     if (_FP_SELCODE_DONT_CARE != fg->sel_codes[part_index].src_entity_sel) {
  24056         fs->src_entity_sel = fg->sel_codes[part_index].src_entity_sel;
  24057     }
  24058     /* Set destination forwarding entity type selection. */
  24059     if (_FP_SELCODE_DONT_CARE != fg->sel_codes[part_index].dst_fwd_entity_sel) {
  24060         fs->dst_fwd_entity_sel = fg->sel_codes[part_index].dst_fwd_entity_sel;
  24061     }
  24062 
  24063     /* Set destination forwarding field selection. */
  24064     if (_FP_SELCODE_DONT_CARE != fg->sel_codes[part_index].fwd_field_sel) {
  24065         fs->fwd_field_sel = fg->sel_codes[part_index].fwd_field_sel;
  24066     }
  24067 
  24068     if (_FP_SELCODE_DONT_CARE != fg->sel_codes[part_index].ttl_class_sel) {
  24069         fs->ttl_class_sel = fg->sel_codes[part_index].ttl_class_sel;
  24070     }
  24071 
  24072     if (_FP_SELCODE_DONT_CARE != fg->sel_codes[part_index].tos_class_sel) {
  24073         fs->tos_class_sel = fg->sel_codes[part_index].tos_class_sel;
  24074     }
  24075 
  24076     if (_FP_SELCODE_DONT_CARE != fg->sel_codes[part_index].tcp_class_sel) {
  24077         fs->tcp_class_sel = fg->sel_codes[part_index].tcp_class_sel;
  24078     }
  24079 
  24080     /* Set intraslice double wide key selection. */
  24081     if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
  24082         if ((_FP_SELCODE_DONT_CARE != fg->sel_codes[part_index].fpf2) &&
  24083             ((part_index == _FP_INTRA_SLICE_PART_1) ||
  24084              (part_index == _FP_INTRA_SLICE_PART_3))) {
  24085             fs->doublewide_key_select = fg->sel_codes[part_index].fpf2;
  24086         }
  24087     }
  24088     return BCM_E_NONE;
  24089 }
  24090 
  24091 /*
  24092  * Function:
  24093  *     _bcm_field_slice_group_get_next
  24094  * Purpose:
  24095  *     Retrieve the next valid group pointer associated with the given slice.
  24096  * Parameters:
  24097  *     unit       - (IN   BCM device number.
  24098  *     instance   - (IN)  Pipe to which group belongs to.
  24099  *     stage_id   - (IN)  Stage (IFP/VFP/EFP) to which group belongs to.
  24100  *     slice_id   - (IN)  Field slice id.
  24101  *     curr_group - (IN)  Reference to current group index associated to slice.
  24102  *     next_group - (OUT) Reference to next available group index associated to
  24103  *                        the given slice.
  24104  * Returns:
  24105  *     BCM_E_XXX
  24106  * Note:
  24107  *     "*curr_group == NULL" to retrieve the first group associated with the
  24108  *      given slice.
  24109  */
  24110 int
  24111 _bcm_field_slice_group_get_next(int unit,
  24112                                    int instance,
  24113                                    _field_stage_id_t stage_id,
  24114                                    int slice_id,
  24115                                    _field_group_t **curr_group,
  24116                                    _field_group_t **next_group)
  24117 {
  24118     _field_group_t    *fg = NULL;
  24119     _field_slice_t    *fs = NULL;
  24120 
  24121     if (curr_group == NULL || next_group == NULL) {
  24122        return BCM_E_PARAM;
  24123     }
  24124 
  24125     if (*curr_group == NULL) {
  24126        _field_control_t  *fc;     /* Field Control Structure */
  24127 
  24128        /* Get device Field control structure. */
  24129        BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  24130        fg = fc->groups;
  24131     } else {
  24132        fg = (*curr_group)->next;
  24133     }
  24134 
  24135     *next_group = NULL;
  24136     for (; fg != NULL; fg = fg->next) {
  24137         if ((instance != fg->instance) || (stage_id != fg->stage_id)) {
  24138             continue;
  24139         }
  24140 
  24141         for (fs = fg->slices; fs != NULL; fs = fs->next) {
  24142             if (fs->slice_number == slice_id) {
  24143                *next_group = fg;
  24144                return BCM_E_NONE;
  24145             }
  24146         }
  24147     }
  24148     return BCM_E_NOT_FOUND;
  24149 }
  24150 
  24151 /* update the primary slice pointer of all the groups using the
  24152  * given slice
  24153  */
  24154 int
  24155 _bcm_field_group_primary_slice_update(int unit,
  24156                                    int instance,
  24157                                    _field_stage_id_t stage_id,
  24158                                    int slice_id,
  24159                                    _field_slice_t *fs_primary
  24160                                    )
  24161 {
  24162     _field_group_t    *fg = NULL;
  24163     _field_control_t  *fc;     /* Field Control Structure */
  24164 
  24165     if (fs_primary == NULL) {
  24166        return BCM_E_PARAM;
  24167     }
  24168 
  24169      /* Get device Field control structure. */
  24170     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  24171     fg = fc->groups;
  24172 
  24173     for (; fg != NULL; fg = fg->next) {
  24174         if ((instance != fg->instance) || (stage_id != fg->stage_id)) {
  24175             continue;
  24176         }
  24177         if (fg->slices != NULL) {
  24178             if (fg->slices[0].slice_number == slice_id) {
  24179                 fg->slices = fs_primary;
  24180             }
  24181         }
  24182     }
  24183     return BCM_E_NONE;
  24184 }
  24185 
  24186 /*
  24187  * Function:
  24188  *     _field_group_slice_align
  24189  * Purpose:
  24190  *     Move source slice to des slice so that two consecutive slices are
  24191  *     free to create a double wide group.
  24192  *     The destination slice is added before source slice. the selcodes are
  24193  *     readd from source slice and installed in destination slice.
  24194  *     If the source slice was the primary slice of a group in that slice, then
  24195  *      the group slice pointer(fg->slices) of all the groups in the slice will
  24196  *     be set to the point to destination slice. The entries are moved from
  24197  *     source to destination slice and the source slice is removed and vmap of
  24198  *     is reset accordingly.
  24199  * Parameters:
  24200  *     unit       - (IN) BCM device number.
  24201  *     fg         - (IN) group of the slice to move.
  24202  *     stage_fc   - (IN) stage pointer
  24203  *     src_slice  - (IN  source slice no
  24204  *     dst_sicice - (IN) desination slice no
  24205  * Returns:
  24206  *     BCM_E_XXX
  24207  */
  24208 STATIC int
  24209 _field_group_slice_align(
  24210                    int unit, _field_group_t *fg,
  24211                    _field_stage_t *stage_fc,
  24212                    uint8 src_slice, uint8 dst_slice) {
  24213     int  virtual_priority = FALSE;
  24214     _field_slice_t   *fs;
  24215 
  24216     _field_slice_t   *src_fs;
  24217     _field_slice_t   *dst_fs;
  24218     _field_slice_t   *base_ptr;
  24219     _field_slice_t   *old_fs;
  24220     _field_control_t *fc;
  24221 
  24222     int    idx; /* Slice iteration index.   */
  24223     int    tmp_idx1; /* Slice entry index 1.  */
  24224     int    tmp_idx2; /* Slice entry index 2.  */
  24225     int    slice_sz; /* Number of entries in a slice.  */
  24226 
  24227     int    rv;
  24228     uint8  is_root_slice = 0;
  24229     uint8  is_cell_codes_init = 0;
  24230     _field_group_t *src_fg;
  24231 
  24232     rv = _field_control_get(unit, &fc);
  24233     BCM_IF_ERROR_RETURN(rv);
  24234     _field_virtual_priority_support(unit, stage_fc, &virtual_priority);
  24235 
  24236     /* Remove original group from the map. */
  24237     if (virtual_priority) {
  24238         rv = _field_group_vmap_delete(unit, stage_fc, fg, FALSE);
  24239         BCM_IF_ERROR_RETURN(rv);
  24240     }
  24241 
  24242     /* Set up the new physical slice parameters in Software */
  24243     /* Get slice pointer for the destination slice. */
  24244     fs = stage_fc->slices[fg->instance] + dst_slice;
  24245 
  24246     /* Enable the destination slice and initialize. */
  24247     BCM_IF_ERROR_RETURN
  24248         (_field_slice_enable_set(unit, stage_fc, fg, fs, 1));
  24249 
  24250     /* Set per slice configuration & number of free entries in the slice.*/
  24251     fs->free_count = fs->entry_count;
  24252     if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
  24253         fs->free_count >>= 1;
  24254     }
  24255     /* Set group flags in in slice.*/
  24256     fs->group_flags = fg->flags & _FP_GROUP_STATUS_MASK;
  24257 
  24258     old_fs = &stage_fc->slices[fg->instance][src_slice];
  24259     /* insert destination slice before source slice */
  24260     if (old_fs->prev == NULL) {
  24261         old_fs->prev = fs;
  24262         fs->next = old_fs;
  24263         fs->prev = NULL;
  24264         fg->slices = fs;
  24265         is_root_slice = 1;
  24266     } else {
  24267         fs->prev = old_fs->prev;
  24268         old_fs->prev->next = fs;
  24269         old_fs->prev = fs;
  24270         fs->next = old_fs;
  24271     }
  24272 
  24273     BCM_PBMP_OR(fs->pbmp, fg->pbmp);
  24274 
  24275     dst_fs = stage_fc->slices[fg->instance] + dst_slice;
  24276     src_fs = stage_fc->slices[fg->instance] + src_slice;
  24277     /* loop through all the groups of source slice and
  24278      * install the sel codes for dest slice if there are entries
  24279      * installed for that group. If the dest slice is primary slice,
  24280      * then install sel codes for all groups.
  24281      */
  24282     src_fg=NULL;
  24283     do {
  24284         (void)_bcm_field_slice_group_get_next(unit,
  24285                                       fg->instance, fg->stage_id,
  24286                                       src_fs->slice_number,
  24287                                       &src_fg, &src_fg);
  24288         if (src_fg != NULL) {
  24289             BCM_PBMP_OR(dst_fs->pbmp, src_fg->pbmp);
  24290 
  24291             if (is_root_slice) {
  24292                 rv = fc->functions.fp_selcodes_install(unit, src_fg,
  24293                                       dst_slice,
  24294                                       dst_fs->pbmp, 0);
  24295                 BCM_IF_ERROR_RETURN(rv);
  24296                 if (is_cell_codes_init == 0) {
  24297                     is_cell_codes_init = 1;
  24298                 }
  24299             } else {
  24300                 /* check if the grp has entries in src slice*/
  24301                 for (idx = 0; idx < src_fs->entry_count; idx++) {
  24302                     if ((NULL != src_fs->entries[idx]) &&
  24303                        (NULL != src_fs->entries[idx]->group) &&
  24304                        (src_fs->entries[idx]->group->gid == src_fg->gid)) {
  24305                         break;
  24306                     }
  24307                 }
  24308 
  24309                 if (idx != src_fs->entry_count) {
  24310                     /*
  24311                      * This means that there is an entry in the slice
  24312                      *  belonging to same group. So,install the selcodes.
  24313                      */
  24314                     rv = fc->functions.fp_selcodes_install(unit, src_fg,
  24315                                   dst_slice,
  24316                                   dst_fs->pbmp, 0);
  24317                     BCM_IF_ERROR_RETURN(rv);
  24318                     if (is_cell_codes_init == 0) {
  24319                         is_cell_codes_init = 1;
  24320                     }
  24321                 }
  24322             }
  24323             if (is_cell_codes_init == 1) {
  24324                 is_cell_codes_init = 2;
  24325                 rv = _bcm_field_group_selcode_initialize(unit,
  24326                               src_fg, dst_fs, 0);
  24327                 BCM_IF_ERROR_RETURN(rv);
  24328             }
  24329         } /* if (src_fg != NULL)*/
  24330     } while (src_fg != NULL);
  24331 
  24332     /* Reinstall group virtual map . */
  24333     if (virtual_priority) {
  24334         BCM_IF_ERROR_RETURN (_field_group_vmap_add(unit, stage_fc, fg));
  24335     }
  24336     /* Move the entries from source to destination slice */
  24337     _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, src_fs, slice_sz);
  24338     for (idx = 0; idx < slice_sz; idx ++)  {
  24339         /* Find an empty slot. */
  24340         if (src_fs->entries[idx]) {
  24341             rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc,
  24342                                                      fg->instance,
  24343                                                      src_fs->slice_number,
  24344                                                      idx, &tmp_idx1);
  24345             BCM_IF_ERROR_RETURN(rv);
  24346 
  24347             rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc,
  24348                                                      fg->instance,
  24349                                                      dst_fs->slice_number,
  24350                                                      idx, &tmp_idx2);
  24351             BCM_IF_ERROR_RETURN(rv);
  24352             /* move the entry from source slice to destination slice */
  24353             rv = _field_entry_move(unit, src_fs->entries[idx],
  24354                                   (tmp_idx2 - tmp_idx1));
  24355             BCM_IF_ERROR_RETURN(rv);
  24356         }
  24357     }
  24358     if (virtual_priority) {
  24359         BCM_IF_ERROR_RETURN(_field_group_vmap_delete(
  24360                               unit, stage_fc, fg, FALSE));
  24361     }
  24362 
  24363     /*remove the source slice slice*/
  24364     if (is_root_slice) {
  24365         /*remove the head*/
  24366         base_ptr = src_fs->prev;
  24367         /* since head is changed, set the head for each group whose
  24368          * primary slice number is the source slice
  24369          */
  24370         (void) _bcm_field_group_primary_slice_update(unit,
  24371                              fg->instance, fg->stage_id,
  24372                              src_slice, base_ptr);
  24373     }
  24374     src_fs->prev->next = src_fs->next;
  24375     if (src_fs->next) {
  24376         src_fs->next->prev = src_fs->prev;
  24377     }
  24378 
  24379     src_fg=NULL;
  24380     do {
  24381         (void)_bcm_field_slice_group_get_next(unit,
  24382                                           fg->instance, fg->stage_id,
  24383                                           dst_fs->slice_number,
  24384                                           &src_fg, &src_fg);
  24385         if (src_fg != NULL) {
  24386             rv = _field_slice_clear(unit, src_fg, src_fs, src_fg->pbmp);
  24387             BCM_IF_ERROR_RETURN(rv);
  24388         }
  24389     } while(src_fg != NULL);
  24390     /* Clear used entries pbmp. */
  24391     src_fs->next = src_fs->prev = NULL;
  24392 
  24393     if (virtual_priority) {
  24394         /* Add the virtual map . */
  24395         BCM_IF_ERROR_RETURN(_field_group_vmap_add(unit, stage_fc, fg));
  24396     }
  24397 
  24398     return BCM_E_NONE;
  24399 }
  24400 
  24401 /*
  24402  * Function:
  24403  *     _field_group_add_slice_align
  24404  * Purpose:
  24405  *     move slices so that two consecutive slices are
  24406  *     free to create a double wide group.
  24407  * Parameters:
  24408  *     unit     - (IN)     BCM device number.
  24409  *     fsm_ptr  - (IN/OUT) State machine tracking structure.
  24410  * Returns:
  24411  *     BCM_E_XXX
  24412  */
  24413 STATIC int
  24414 _field_group_add_slice_align(int unit, _field_group_add_fsm_t *fsm_ptr) {
  24415     int  *free_slice_array = NULL;    /* Array containing slice ids */
  24416     uint8  *slice_array_fill = NULL;    /* Array containing slice ids */
  24417     int slice_index;               /* Slice Index */
  24418     int free_slice_count = 0;
  24419     int rv = 0;    /* Operation return status. */
  24420 
  24421     _field_slice_t *src_fs;
  24422     _field_slice_t *dst_fs;
  24423     uint8 indx = 0;
  24424     uint8 src_slice = 0;
  24425     uint8 src_slice_free = 0;
  24426     _field_group_t *src_fg = NULL;
  24427     /* Set current state to be previous state. */
  24428     fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state;
  24429     fsm_ptr->rv = BCM_E_NONE;
  24430 
  24431     /* check if atleast two slices are free */
  24432     _FP_XGS3_ALLOC(free_slice_array, sizeof(int) * fsm_ptr->stage_fc->tcam_slices,
  24433                       "Free Slice Array");
  24434     if (NULL == free_slice_array) {
  24435         fsm_ptr->rv = BCM_E_MEMORY;
  24436         goto cleanup;
  24437     }
  24438 
  24439     for (slice_index = 0;
  24440           slice_index < fsm_ptr->stage_fc->tcam_slices; slice_index++) {
  24441         if (!(fsm_ptr->stage_fc->slices[0][slice_index].group_flags)) {
  24442             free_slice_array[free_slice_count] = slice_index;
  24443             free_slice_count++;
  24444         }
  24445     }
  24446 
  24447     /* double wide group requires atleast 2 slices to be free */
  24448     if (free_slice_count < 2) {
  24449         fsm_ptr->rv = BCM_E_RESOURCE;
  24450         goto cleanup;
  24451     }
  24452 
  24453     _FP_XGS3_ALLOC(slice_array_fill, sizeof(uint8) *fsm_ptr->stage_fc->tcam_slices,
  24454                       "Slice Array Fill");
  24455     if (NULL == slice_array_fill) {
  24456         fsm_ptr->rv = BCM_E_MEMORY;
  24457         goto cleanup;
  24458     }
  24459 
  24460     /* For each free slice found, find a slice that its partner slice
  24461      * can autoexpand. For each free slice found, see if the double byte
  24462      * group requested can be created.
  24463      * if a slice for auto expansion is found and a double wide group
  24464      * can be created, go ahead and move the slice
  24465      */
  24466     /* loop for each free slice found*/
  24467 
  24468     for ( indx = 0; indx < free_slice_count; indx++) {
  24469         src_slice_free =  free_slice_array[indx];
  24470         src_slice =  free_slice_array[indx];
  24471         if ( (free_slice_array[indx] ==0) ||
  24472              (free_slice_array[indx] % 2 == 0) ) {
  24473             src_slice++;
  24474         } else {
  24475             src_slice--;
  24476         }
  24477         /* find the first group associated with the slice */
  24478         src_fg = NULL;
  24479         (void)_bcm_field_slice_group_get_next(unit,
  24480                                       fsm_ptr->fg->instance,
  24481                                       fsm_ptr->stage_fc->stage_id,
  24482                                       src_slice,
  24483                                       &src_fg, &src_fg);
  24484         if ( src_fg == NULL) {
  24485             fsm_ptr->rv = BCM_E_INTERNAL;
  24486             goto cleanup;
  24487         }
  24488 
  24489         for (slice_index = 0; slice_index < fsm_ptr->stage_fc->tcam_slices; slice_index++) {
  24490             slice_array_fill[slice_index] = slice_index;
  24491         }
  24492 
  24493         rv = _field_fill_slice_array (unit, src_fg, slice_array_fill);
  24494         if (rv != BCM_E_NONE) {
  24495             fsm_ptr->rv = BCM_E_INTERNAL;
  24496             goto cleanup;
  24497         }
  24498 
  24499         /* find an empty slice for the slice move */
  24500         for (slice_index = 0;
  24501              slice_index < fsm_ptr->stage_fc->tcam_slices; slice_index++) {
  24502             if (slice_array_fill[slice_index] == src_slice_free) {
  24503                continue;
  24504             }
  24505             if (fsm_ptr->stage_fc->slices[0][slice_index].group_flags) {
  24506                 continue;
  24507             }
  24508 
  24509             /* Slice move is valid Check if
  24510              * the requested group can be created after this move
  24511              */
  24512             src_fs = fsm_ptr->stage_fc->slices[src_fg->instance] + src_slice;
  24513             dst_fs = fsm_ptr->stage_fc->slices[src_fg->instance] +
  24514                             slice_array_fill[slice_index];
  24515             if (dst_fs->free_count <
  24516                  (src_fs->entry_count - src_fs->free_count)) {
  24517                 continue;
  24518             }
  24519 
  24520             /* move the slice and return */
  24521             rv = _field_group_slice_align(
  24522                     unit, src_fg, fsm_ptr->stage_fc,
  24523                     src_slice, slice_array_fill[slice_index]);
  24524             if (BCM_FAILURE(rv)) {
  24525                 fsm_ptr->rv = BCM_E_INTERNAL;
  24526                 goto cleanup;
  24527             } else {
  24528                 fsm_ptr->rv = BCM_E_NONE;
  24529                 goto cleanup;
  24530             }
  24531         }
  24532     }
  24533 
  24534     goto cleanup;
  24535 
  24536 cleanup:
  24537     if (free_slice_array) {
  24538          sal_free (free_slice_array);
  24539         free_slice_array = NULL;
  24540     }
  24541     if (slice_array_fill) {
  24542          sal_free (slice_array_fill);
  24543         slice_array_fill = NULL;
  24544     }
  24545     if (BCM_SUCCESS(fsm_ptr->rv)) {
  24546        /* Retry allocating slice/s for the new field group. */
  24547        fsm_ptr->fsm_state_prev =
  24548                   _BCM_FP_GROUP_ADD_STATE_SLICE_ALIGN;
  24549        fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SLICE_ALLOCATE;
  24550     } else {
  24551        fsm_ptr->fsm_state_prev =
  24552                   _BCM_FP_GROUP_ADD_STATE_SLICE_ALIGN;
  24553        fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END;
  24554     }
  24555 
  24556     return _bcm_field_group_add(unit, fsm_ptr);
  24557 }
  24558 
  24559 /*
  24560  * Function:
  24561  *     _field_group_add_initialize
  24562  * Purpose:
  24563  *     Perform fsm initialization & execute basic checks
  24564  *     required before field group creation.
  24565  * Parameters:
  24566  *     unit     - (IN)     BCM device number.
  24567  *     fsm_ptr  - (IN/OUT) State machine tracking structure.
  24568  * Returns:
  24569  *     BCM_E_XXX.
  24570  */
  24571 STATIC int
  24572 _field_group_add_initialize(int unit, _field_group_add_fsm_t *fsm_ptr)
  24573 {
  24574 
  24575     _field_stage_id_t stage = _BCM_FIELD_STAGE_INGRESS; /* Group pipeline stage id.*/
  24576     _field_group_t      *fg_temp; /* Existing field group pointer. */
  24577 
  24578     /* Input parameters check. */
  24579     if (NULL == fsm_ptr) {
  24580         return (BCM_E_PARAM);
  24581     }
  24582 
  24583     /* Set current state to be previous state. */
  24584     fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state;
  24585 
  24586     /* Group IDs must be unique within a unit. */
  24587     if(BCM_SUCCESS(_field_group_get(unit, fsm_ptr->group_id, &fg_temp))) {
  24588         LOG_ERROR(BSL_LS_BCM_FP,
  24589                   (BSL_META_U(unit,
  24590                               "FP(unit %d) Error: group=%d already exists.\n"),
  24591                    unit, fsm_ptr->group_id));
  24592         fsm_ptr->rv = (BCM_E_EXISTS);
  24593     }
  24594 
  24595     /* Get field stage control pointer. */
  24596     if (BCM_SUCCESS(fsm_ptr->rv)) {
  24597         fsm_ptr->rv = _field_control_get(unit, &fsm_ptr->fc);
  24598     }
  24599 
  24600     /* Get pipeline stage from qualifiers set. */
  24601     if (BCM_SUCCESS(fsm_ptr->rv)) {
  24602         fsm_ptr->rv = _bcm_field_group_stage_get(unit, &fsm_ptr->qset, &stage);
  24603     }
  24604 
  24605 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  24606     /* Allow intraslice select codes if they are supported by the stage. */
  24607     if (BCM_SUCCESS(fsm_ptr->rv)  &&
  24608         soc_feature(unit, soc_feature_field_intraslice_double_wide) &&
  24609         (fsm_ptr->fc->flags & _FP_INTRASLICE_ENABLE) &&
  24610         (_BCM_FIELD_STAGE_EGRESS != stage) &&
  24611         (_BCM_FIELD_STAGE_EXTERNAL != stage)) {
  24612             /* We might try intraslice group. */
  24613         if (((!SOC_IS_TD_TT(unit)) &&
  24614              (!((SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) ||
  24615                  SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit) ||
  24616                  (SOC_IS_TRIUMPH3(unit) &&
  24617                   soc_feature(unit, soc_feature_field_stage_quarter_slice)))
  24618              && (_BCM_FIELD_STAGE_LOOKUP == stage))))
  24619             || (SOC_IS_TD_TT(unit) && (_BCM_FIELD_STAGE_LOOKUP == stage))) {
  24620             /* Hurricane2/GH does not support intraslice double wide mode in VFP */
  24621             /* In Ranger+ one TCAM in each slice is fused out in VFP stage.
  24622              * Hence it can not support intraslice double wide mode in VFP */
  24623             /* For TD and TT Intra-slice mode supported only for VFP */
  24624             fsm_ptr->flags |= _BCM_FP_GROUP_ADD_INTRA_SLICE;
  24625         }
  24626     }
  24627 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  24628 
  24629     /* Get field stage control pointer. */
  24630     if (BCM_SUCCESS(fsm_ptr->rv)) {
  24631         fsm_ptr->rv  = _field_stage_control_get(unit, stage, &fsm_ptr->stage_fc);
  24632     }
  24633 
  24634 #ifdef BCM_TRIUMPH_SUPPORT
  24635     /* _bcmFieldQualifyData2 is valid only for external stage on Triumph */
  24636     if (SOC_IS_TRIUMPH(unit)) {
  24637         if ((BCM_FIELD_QSET_TEST(fsm_ptr->qset,
  24638                 bcmFieldQualifyStageExternal) == 0) &&
  24639             (BCM_FIELD_QSET_TEST(fsm_ptr->qset,
  24640                 _bcmFieldQualifyData2))) {
  24641             BCM_FIELD_QSET_REMOVE_INTERNAL(fsm_ptr->qset,
  24642                 _bcmFieldQualifyData2);
  24643         }
  24644     }
  24645 #endif /* !BCM_TRIUMPH_SUPPORT || BCM_TRIUMPH2_SUPPORT */
  24646 
  24647     /* Verify that requested qualifiers set is supported by stage. */
  24648     if (BCM_SUCCESS(fsm_ptr->rv)) {
  24649         if (FALSE == _field_qset_is_subset(&fsm_ptr->qset,
  24650                                            &fsm_ptr->stage_fc->_field_supported_qset)) {
  24651             LOG_VERBOSE(BSL_LS_BCM_FP,
  24652                       (BSL_META_U(unit,
  24653                                   "FP(unit %d) Error: Qualifier set is not supported by the device.\n"),
  24654                        unit));
  24655             fsm_ptr->rv = BCM_E_UNAVAIL;
  24656         }
  24657     }
  24658 
  24659     if (BCM_FAILURE(fsm_ptr->rv)) {
  24660         /* Error occured -> clean up.. */
  24661         fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END;
  24662     } else {
  24663         /* Proceed to group allocation stage. */
  24664         fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_ALLOC;
  24665     }
  24666     return _bcm_field_group_add(unit, fsm_ptr);
  24667 }
  24668 
  24669 /*
  24670  * Function:
  24671  *     _field_group_add_alloc
  24672  * Purpose:
  24673  *     Allocate & initialize field group structure.
  24674  * Parameters:
  24675  *     unit     - (IN) BCM device number.
  24676  *     fsm_ptr  - (IN/OUT) State machine tracking structure.
  24677  * Returns:
  24678  *     BCM_E_XXX.
  24679  */
  24680 STATIC int
  24681 _field_group_add_alloc(int unit, _field_group_add_fsm_t *fsm_ptr)
  24682 {
  24683     int                 idx;         /* Misc iterator.           */
  24684     int                 mem_sz;      /* Allocated memory size.   */
  24685     _field_group_t      *fg = NULL;  /* New group info.          */
  24686     int                 virtual_priority = FALSE;/* Virtual priority support flag.*/
  24687 
  24688 
  24689     /* Input parameters check. */
  24690     if (NULL == fsm_ptr) {
  24691         return (BCM_E_PARAM);
  24692     }
  24693 
  24694     /* Set current state to be previous state. */
  24695     fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state;
  24696 
  24697     /* Allocate & initialize memory for field group. */
  24698     mem_sz = sizeof(_field_group_t);
  24699     _FP_XGS3_ALLOC(fg, mem_sz, "field group");
  24700     if (NULL == fg) {
  24701         LOG_ERROR(BSL_LS_BCM_FP,
  24702                   (BSL_META_U(unit,
  24703                               "FP(unit %d) Error:Allocation failure for _field_group_t\n"),
  24704                    unit));
  24705         fsm_ptr->rv = BCM_E_MEMORY;
  24706         fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END;
  24707         return _bcm_field_group_add(unit, fsm_ptr);
  24708     }
  24709 
  24710 
  24711     /* Initialize group structure. */
  24712     fg->gid            = fsm_ptr->group_id;
  24713     fg->stage_id       = fsm_ptr->stage_fc->stage_id;
  24714     fg->qset           = fsm_ptr->qset;
  24715     fg->pbmp           = fsm_ptr->pbmp;
  24716     fg->priority       = fsm_ptr->priority;
  24717 
  24718     if ( soc_feature(unit, soc_feature_field_multi_pipe_support) ||
  24719          soc_feature(unit, soc_feature_field_ingress_two_slice_types)) {
  24720         fg->hintid         = fsm_ptr->hintid;
  24721          /* Group has been created, Increment group ref count in
  24722          * corresponding hintid in hints hash lookup table */
  24723         fsm_ptr->rv = _bcm_field_hints_group_count_update (unit, fg->hintid, 1);
  24724         if (BCM_FAILURE(fsm_ptr->rv)) {
  24725             sal_free (fg);
  24726             fg = NULL;
  24727             fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END;
  24728             /* coverity[leaked_storage: FALSE] */
  24729             return _bcm_field_group_add(unit, fsm_ptr);
  24730         }
  24731     }
  24732 
  24733     /* Initialize group status. */
  24734     fsm_ptr->rv = _bcm_field_group_status_init(unit, &fg->group_status);
  24735     if (BCM_FAILURE(fsm_ptr->rv)) {
  24736         sal_free (fg);
  24737         fg = NULL;
  24738         fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END;
  24739         /* coverity[leaked_storage: FALSE] */
  24740         return _bcm_field_group_add(unit, fsm_ptr);
  24741     }
  24742 
  24743     if ( soc_feature(unit, soc_feature_field_multi_pipe_support) ||
  24744          soc_feature(unit, soc_feature_field_ingress_two_slice_types) ) {
  24745         /* Update group datastructure from hintid */
  24746         fsm_ptr->rv = _bcm_field_hints_group_info_update (unit, fg);
  24747         if (BCM_FAILURE(fsm_ptr->rv)) {
  24748             sal_free (fg);
  24749             fg = NULL;
  24750             fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END;
  24751             /* coverity[leaked_storage: FALSE] */
  24752             return _bcm_field_group_add(unit, fsm_ptr);
  24753         }
  24754     }
  24755 
  24756 
  24757     /* Clear the group's select codes and its slice Qsets. */
  24758     for (idx = 0; idx < _FP_MAX_ENTRY_WIDTH; idx++) {
  24759         _FIELD_SELCODE_CLEAR(fg->sel_codes[idx]);
  24760     }
  24761 
  24762     /* By default mark group as active. */
  24763     fg->flags |= _FP_GROUP_LOOKUP_ENABLED;
  24764 
  24765     /* Set special group flags. */
  24766     if (fsm_ptr->flags & _BCM_FP_GROUP_ADD_WLAN) {
  24767         fg->flags |= _FP_GROUP_WLAN;
  24768     }
  24769 
  24770     /* Set slice size selection group flags. */
  24771     if (fsm_ptr->flags & _BCM_FP_GROUP_ADD_SMALL_SLICE) {
  24772         fg->flags |= _FP_GROUP_SELECT_SMALL_SLICE;
  24773     } else if (fsm_ptr->flags & _BCM_FP_GROUP_ADD_LARGE_SLICE) {
  24774         fg->flags |= _FP_GROUP_SELECT_LARGE_SLICE;
  24775     }
  24776 
  24777     /* Set action res id and vmap group to default */
  24778     fg->action_res_id = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT;
  24779     for (idx = 0; idx < _FP_PAIR_MAX; idx++) {
  24780         fg->vmap_group[idx] = BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT;
  24781     }
  24782 
  24783     _field_virtual_priority_support(unit, fsm_ptr->stage_fc, &virtual_priority);
  24784 
  24785     /* Update virtual group related parameters */
  24786     if ((virtual_priority == TRUE)
  24787             && (fsm_ptr->stage_fc->stage_id != _BCM_FIELD_STAGE_EXTERNAL)) {
  24788         fg->action_res_id = fsm_ptr->action_res_id;
  24789         /* If virtual group is valid check if any existing internal vmap group exists */
  24790         if(fg->action_res_id != BCM_FIELD_GROUP_ACTION_RES_ID_DEFAULT)
  24791         {
  24792             fsm_ptr->rv = _bcm_field_group_virtual_map_update(unit, fg);
  24793             if (BCM_FAILURE(fsm_ptr->rv)) {
  24794                 sal_free (fg);
  24795                 fg = NULL;
  24796                 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END;
  24797                 return _bcm_field_group_add(unit, fsm_ptr);
  24798             }
  24799         }
  24800     }
  24801 #if defined(BCM_TOMAHAWK_SUPPORT)
  24802     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  24803         ((_BCM_FIELD_STAGE_LOOKUP == fg->stage_id) ||
  24804          (_BCM_FIELD_STAGE_EGRESS == fg->stage_id))) {
  24805 
  24806        /* Set the Field Group's instance information. */
  24807        fsm_ptr->rv = _bcm_field_th_group_instance_set(unit, fg);
  24808        if (BCM_FAILURE(fsm_ptr->rv)) {
  24809            sal_free (fg);
  24810            fg = NULL;
  24811            fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END;
  24812            return _bcm_field_group_add(unit, fsm_ptr);
  24813        }
  24814     }
  24815 #endif /* BCM_TOMAHAWK_SUPPORT */
  24816 
  24817     /* Set allocated pointer to FSM structure. */
  24818     fsm_ptr->fg = fg;
  24819     /* Update group qset with internal qualifiers. */
  24820     fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_QSET_UPDATE;
  24821 
  24822     return _bcm_field_group_add(unit, fsm_ptr);
  24823 }
  24824 
  24825 /*
  24826  * Function:
  24827  *     _field_group_add_qualify_in_ports
  24828  * Purpose:
  24829  *     Update group application requested qset
  24830  *     if group is restricted to subset of device ports.
  24831  * Parameters:
  24832  *     unit     - (IN)     BCM device number.
  24833  *     fg       - (IN/OUT) Field Group pointer.
  24834  * Returns:
  24835  *     BCM_E_XXX
  24836  */
  24837 STATIC int
  24838 _field_group_add_qualify_in_ports(int unit, _field_group_t *fg)
  24839 {
  24840     bcm_pbmp_t  pbmp_temp;       /* Port bitmap buffer.      */
  24841     int         count;           /* Number of ports in PBMP. */
  24842     int         qual_in_ports;   /* Qualify InPorts flag.    */
  24843 
  24844 
  24845     /* Input parameters check. */
  24846     if (NULL == fg) {
  24847         return (BCM_E_PARAM);
  24848     }
  24849 
  24850 #if defined(BCM_TOMAHAWK_SUPPORT)
  24851     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  24852         ((_BCM_FIELD_STAGE_LOOKUP == fg->stage_id) ||
  24853          (_BCM_FIELD_STAGE_EGRESS == fg->stage_id))) {
  24854         /* Do nothing */
  24855         return BCM_E_NONE;
  24856     }
  24857 #endif /* BCM_TOMAHAWK_SUPPORT */
  24858 
  24859     /* Read device port configuration. */
  24860     BCM_IF_ERROR_RETURN(_bcm_field_valid_pbmp_get(unit, &pbmp_temp));
  24861 
  24862     /*
  24863      *  If group active on on all ports no InPort/InPorts
  24864      *  qualification  is required.
  24865      */
  24866     if (BCM_PBMP_EQ(fg->pbmp, pbmp_temp)) {
  24867         /* Update the instance to default. */
  24868         fg->instance = _FP_DEF_INST;
  24869         return (BCM_E_NONE);
  24870     }
  24871 
  24872     if (_BCM_FIELD_STAGE_INGRESS != fg->stage_id) {
  24873         return (BCM_E_RESOURCE);
  24874     }
  24875 
  24876     qual_in_ports = TRUE;
  24877     /*
  24878      * If there's only 1 port and device capable efficiently
  24879      * qualify on source port use InPort qualifier in stead of InPorts
  24880      */
  24881     BCM_PBMP_COUNT(fg->pbmp, count);
  24882     if ((count == 1) && (!soc_feature(unit, soc_feature_table_hi))) {
  24883         if (soc_feature(unit, soc_feature_field_multi_stage)) {
  24884             BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyInPort);
  24885             qual_in_ports = FALSE;
  24886         } else if (SOC_MEM_FIELD_VALID(unit, FP_TCAMm, SOURCE_PORT_NUMBER_MASKf)) {
  24887             /*
  24888              *  In Order to qualify on a single Higig port -
  24889              *  Higig quailifier must be  present in each rule.
  24890              */
  24891             BCM_PBMP_ASSIGN(pbmp_temp, fg->pbmp);
  24892             BCM_PBMP_AND(pbmp_temp, PBMP_HG_ALL(unit));
  24893             if (BCM_PBMP_IS_NULL(pbmp_temp)) {
  24894                 BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyInPort);
  24895                 qual_in_ports = FALSE;
  24896             }
  24897         }
  24898     }
  24899     if (qual_in_ports) {
  24900         if (soc_feature(unit, soc_feature_ifp_no_inports_support)) {
  24901             return (BCM_E_UNAVAIL);
  24902         } else {
  24903         BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyInPorts);
  24904     }
  24905     }
  24906     return (BCM_E_NONE);
  24907 }
  24908 
  24909 #if defined(BCM_TRX_SUPPORT)
  24910 /*
  24911  * Function:
  24912  *     _field_group_qset_rangecheck_update
  24913  * Purpose:
  24914  *     Update application requested qset with internal qualifiers.
  24915  * Parameters:
  24916  *     unit  - (IN)     BCM device number.
  24917  *     fg    - (IN/OUT) Field group structure.
  24918  * Returns:
  24919  *     BCM_E_XXX
  24920  */
  24921 STATIC int
  24922 _field_group_qset_rangecheck_update(int unit, _field_group_t *fg)
  24923 {
  24924     _field_stage_t   *stage_fc; /* Stage field control structure. */
  24925     /* Input parameters check. */
  24926     if (NULL == fg) {
  24927         return (BCM_E_PARAM);
  24928     }
  24929 
  24930 
  24931     if (_BCM_FIELD_STAGE_INGRESS != fg->stage_id) {
  24932         return (BCM_E_NONE);
  24933     }
  24934 
  24935     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
  24936                 _BCM_FIELD_STAGE_INGRESS, &stage_fc));
  24937 
  24938     /* Check if interface Class id qualifiers are not present */
  24939     if (!(BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInterfaceClassPort) ||
  24940             BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInterfaceClassL3) ||
  24941             BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInterfaceClassVPort) ||
  24942             BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInterfaceClassL2))) {
  24943         /* Check if stage supports the new internal qualifier */
  24944         if (BCM_FIELD_QSET_TEST(stage_fc->_field_supported_qset,
  24945                     _bcmFieldQualifyRangeCheckBits24_31)) {
  24946             BCM_FIELD_QSET_ADD(fg->qset, _bcmFieldQualifyRangeCheckBits24_31);
  24947         }
  24948     }
  24949     return (BCM_E_NONE);
  24950 }
  24951 #endif
  24952 
  24953  /*
  24954  * Function:
  24955  *     _field_group_qset_update
  24956  * Purpose:
  24957  *     Update application requested qset with internal qualifiers.
  24958  * Parameters:
  24959  *     unit  - (IN)     BCM device number.
  24960  *     fg    - (IN/OUT) Field group structure.
  24961  * Returns:
  24962  *     BCM_E_XXX
  24963  */
  24964 int
  24965 _field_group_qset_update(int unit, _field_group_t *fg)
  24966 {
  24967     /* Input parameters check. */
  24968     if (NULL == fg) {
  24969         return (BCM_E_PARAM);
  24970     }
  24971 
  24972     /* All ingress devices implicitly have bcmFieldQualifyStage in Qsets.*/
  24973     if (_BCM_FIELD_STAGE_INGRESS == fg->stage_id) {
  24974         BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyStage);
  24975     }
  24976     /*
  24977      * Vlan qualifiers ared extended to Id/Cfi/Pri
  24978      */
  24979     if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyOuterVlan)) {
  24980         BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyOuterVlanId);
  24981         BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyOuterVlanPri);
  24982         BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyOuterVlanCfi);
  24983     }
  24984     if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInnerVlan)) {
  24985         BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyInnerVlanId);
  24986         BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyInnerVlanPri);
  24987         BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyInnerVlanCfi);
  24988     }
  24989 #ifdef BCM_HURRICANE3_SUPPORT
  24990     if (soc_feature(unit, soc_feature_miml)) {
  24991         if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyMimlVlan)) {
  24992             BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyMimlVlanId);
  24993             BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyMimlVlanPri);
  24994             BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyMimlVlanCfi);
  24995         }
  24996     }
  24997     if (soc_feature(unit, soc_feature_ing_capwap_parser)) {
  24998         if (BCM_FIELD_QSET_TEST(fg->qset,
  24999                             bcmFieldQualifyCapwapPayloadOuterVlan)) {
  25000             BCM_FIELD_QSET_ADD(fg->qset,
  25001                             bcmFieldQualifyCapwapPayloadOuterVlanId);
  25002             BCM_FIELD_QSET_ADD(fg->qset,
  25003                             bcmFieldQualifyCapwapPayloadOuterVlanPri);
  25004             BCM_FIELD_QSET_ADD(fg->qset,
  25005                             bcmFieldQualifyCapwapPayloadOuterVlanCfi);
  25006         }
  25007         if (BCM_FIELD_QSET_TEST(fg->qset,
  25008                             bcmFieldQualifyCapwapPayloadInnerVlan)) {
  25009             BCM_FIELD_QSET_ADD(fg->qset,
  25010                             bcmFieldQualifyCapwapPayloadInnerVlanId);
  25011             BCM_FIELD_QSET_ADD(fg->qset,
  25012                             bcmFieldQualifyCapwapPayloadInnerVlanPri);
  25013             BCM_FIELD_QSET_ADD(fg->qset,
  25014                             bcmFieldQualifyCapwapPayloadInnerVlanCfi);
  25015         }
  25016     }
  25017 #endif /* BCM_HURRICANE3_SUPPORT */
  25018 
  25019     /*
  25020      * Automatically include IpType
  25021      * if the qset contains PacketFormat/Ip4/Ip6.
  25022      * FB2 stage egress and stage external are an exception.
  25023      */
  25024     if (_BCM_FIELD_STAGE_EXTERNAL != fg->stage_id) {
  25025         if (
  25026 #if defined (BCM_FIREBOLT2_SUPPORT)
  25027                 ((0 == SOC_IS_FIREBOLT2(unit)) ||
  25028                  (_BCM_FIELD_STAGE_EGRESS != fg->stage_id)) &&
  25029 #endif /* BCM_FIREBOLT2_SUPPORT */
  25030                 ((BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyIp4)) ||
  25031                  (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyIp6)))) {
  25032             BCM_FIELD_QSET_ADD(fg->qset, bcmFieldQualifyIpType);
  25033         }
  25034     }
  25035 
  25036 #if defined(BCM_FIREBOLT2_SUPPORT)
  25037     if (SOC_IS_FIREBOLT2(unit)) {
  25038         /* Device doesn't support qualification on IP without version. */
  25039         if  ((BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyIp4)) &&
  25040              (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyIp6))) {
  25041             return  (BCM_E_RESOURCE);
  25042         }
  25043     }
  25044 #endif /* BCM_FIREBOLT2_SUPPORT */
  25045 
  25046     /*
  25047      * Add qualification on InPorts/InPort in case group applicable only
  25048      * to part of the ports.
  25049      */
  25050     BCM_IF_ERROR_RETURN(_field_group_add_qualify_in_ports(unit, fg));
  25051 
  25052 #ifdef BCM_TRIUMPH3_SUPPORT
  25053     if ((SOC_IS_TRIUMPH3(unit))
  25054         || ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit)))
  25055         || (SOC_IS_KATANA2(unit))) {
  25056         BCM_IF_ERROR_RETURN(_bcm_field_tr3_group_qset_update(unit, fg));
  25057     }
  25058 #endif
  25059 
  25060 #if defined(BCM_TRX_SUPPORT)
  25061     if (SOC_IS_TRX(unit) &&
  25062           !(soc_feature(unit, soc_feature_field_multi_pipe_support)) &&
  25063             BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyRangeCheck)) {
  25064         BCM_IF_ERROR_RETURN(_field_group_qset_rangecheck_update(unit, fg));
  25065     }
  25066 #endif
  25067 
  25068     return (BCM_E_NONE);
  25069 }
  25070 
  25071 /*
  25072  * Function:
  25073  *     _field_group_add_qset_update
  25074  * Purpose:
  25075  *     Update application requested qset with internal qualifiers.
  25076  * Parameters:
  25077  *     unit     - (IN)     BCM device number.
  25078  *     fsm_ptr  - (IN/OUT) State machine tracking structure.
  25079  * Returns:
  25080  *     BCM_E_XXX
  25081  */
  25082 STATIC int
  25083 _field_group_add_qset_update(int unit, _field_group_add_fsm_t *fsm_ptr)
  25084 {
  25085     /* Input parameters check. */
  25086     if (NULL == fsm_ptr) {
  25087         return (BCM_E_PARAM);
  25088     }
  25089 
  25090     if (NULL == fsm_ptr->fg) {
  25091         fsm_ptr->rv = (BCM_E_PARAM);
  25092         fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END;
  25093         return _bcm_field_group_add(unit, fsm_ptr);
  25094     }
  25095 
  25096     /* Set current state to be previous state. */
  25097     fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state;
  25098 
  25099     /* Update group qset with internal qualifiers. */
  25100     fsm_ptr->rv = _field_group_qset_update(unit, fsm_ptr->fg);
  25101 
  25102     if (BCM_FAILURE(fsm_ptr->rv)) {
  25103         /* Qset verification/modification failed - clean up. */
  25104         fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END;
  25105     } else {
  25106         /* Proceed to select codes selection. */
  25107         fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET;
  25108     }
  25109     return _bcm_field_group_add(unit, fsm_ptr);
  25110 }
  25111 
  25112 
  25113 /*
  25114  * Function:
  25115  *     _field_selcode_assign_udf_alternative
  25116  * Purpose:
  25117  *     Calculate the FPFx select codes from a qualifier set and group mode.
  25118  * Parameters:
  25119  *     unit     - (IN)     BCM device number.
  25120  *     fsm_ptr  - (IN/OUT) State machine tracking structure.
  25121  * Returns:
  25122  *     BCM_E_XXX
  25123  */
  25124 STATIC int
  25125 _field_selcode_assign_udf_alternative(int unit, _field_group_add_fsm_t *fsm_ptr)
  25126 {
  25127     _field_group_t      *fg;                 /* Field group pointer.     */
  25128     bcm_field_qset_t   temp_qset;
  25129 
  25130     /* Input parameters check. */
  25131     if (NULL == fsm_ptr) {
  25132         return (BCM_E_PARAM);
  25133     }
  25134 
  25135     if (NULL == fsm_ptr->fg) {
  25136         return (BCM_E_PARAM);
  25137     }
  25138 
  25139     /* Group pointer initialization. */
  25140     fg = fsm_ptr->fg;
  25141 
  25142     if (!(soc_feature(unit, soc_feature_field_multi_pipe_support)) &&
  25143             (BCM_FIELD_QSET_TEST(fg->qset, _bcmFieldQualifyData2) ||
  25144              BCM_FIELD_QSET_TEST(fg->qset, _bcmFieldQualifyData3))) {
  25145         /* Try with Data0 instead of optimized Data2/Data3 qualifiers */
  25146         temp_qset = fg->qset;
  25147         BCM_FIELD_QSET_REMOVE_INTERNAL(fg->qset, _bcmFieldQualifyData2);
  25148         BCM_FIELD_QSET_REMOVE_INTERNAL(fg->qset, _bcmFieldQualifyData3);
  25149         BCM_FIELD_QSET_ADD_INTERNAL(fg->qset, _bcmFieldQualifyData0);
  25150 
  25151         LOG_DEBUG(BSL_LS_BCM_FP,
  25152                 (BSL_META_U(unit,
  25153                             "Trying with alternative udf...\n")));
  25154         fsm_ptr->rv = _field_selcode_assign(unit, fg->qset, 1, fg);
  25155         /* Restore back the old qset in case of failure */
  25156         if (BCM_FAILURE(fsm_ptr->rv)) {
  25157             fg->qset = temp_qset;
  25158         }
  25159     }
  25160 
  25161     return (BCM_E_NONE);
  25162 }
  25163 
  25164 /*
  25165  * Function:
  25166  *     _field_group_add_sel_codes_get
  25167  * Purpose:
  25168  *     Calculate the FPFx select codes from a qualifier set and group mode.
  25169  * Parameters:
  25170  *     unit     - (IN)     BCM device number.
  25171  *     fsm_ptr  - (IN/OUT) State machine tracking structure.
  25172  * Returns:
  25173  *     BCM_E_XXX
  25174  */
  25175 STATIC int
  25176 _field_group_add_sel_codes_get(int unit, _field_group_add_fsm_t *fsm_ptr)
  25177 {
  25178     _field_group_t      *fg;                 /* Field group pointer.     */
  25179     int                orig_group_flags;     /* Original group flags.    */
  25180 
  25181 
  25182     /* Input parameters check. */
  25183     if (NULL == fsm_ptr) {
  25184         return (BCM_E_PARAM);
  25185     }
  25186 
  25187     if (NULL == fsm_ptr->fg) {
  25188         fsm_ptr->rv = (BCM_E_PARAM);
  25189     }
  25190 
  25191     /* Check if requested mode is supported by device. */
  25192     switch (fsm_ptr->mode) {
  25193       case bcmFieldGroupModeQuad:
  25194           if (0 == soc_feature(unit, soc_feature_field_intraslice_double_wide)) {
  25195               fsm_ptr->rv = (BCM_E_RESOURCE);
  25196           }
  25197           break;
  25198       case bcmFieldGroupModeTriple:
  25199           if (soc_feature(unit, soc_feature_field_intraslice_double_wide)) {
  25200               fsm_ptr->rv = (BCM_E_RESOURCE);
  25201           }
  25202 #ifdef BCM_TRIDENT_SUPPORT
  25203           if (SOC_IS_TD_TT(unit))
  25204           {
  25205               fsm_ptr->rv = (BCM_E_UNAVAIL);
  25206           }
  25207 #endif
  25208           /* Fall through. */
  25209       case bcmFieldGroupModeDouble:
  25210           if (0 == soc_feature(unit, soc_feature_field_wide)) {
  25211               fsm_ptr->rv = (BCM_E_RESOURCE);
  25212           }
  25213           break;
  25214       case bcmFieldGroupModeIntraSliceDouble:
  25215           if (0 == soc_feature(unit, soc_feature_field_intraslice_double_wide)) {
  25216               fsm_ptr->rv = (BCM_E_RESOURCE);
  25217           }
  25218           break;
  25219       default:
  25220           break;
  25221     }
  25222     if (BCM_FAILURE(fsm_ptr->rv)) {
  25223         fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state;
  25224         fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END;
  25225         return _bcm_field_group_add(unit, fsm_ptr);
  25226     }
  25227 
  25228     /* Group pointer initialization. */
  25229     fg = fsm_ptr->fg;
  25230 
  25231     fsm_ptr->rv = BCM_E_RESOURCE;
  25232     orig_group_flags = fg->flags;
  25233 
  25234     /* Allocate & initialize memory for field group. */
  25235     if (fsm_ptr->mode == bcmFieldGroupModeAuto)
  25236     {
  25237         LOG_DEBUG(BSL_LS_BCM_FP,
  25238                   (BSL_META_U(unit,
  25239                               "Group mode auto.\n")));
  25240 
  25241         /* For Auto mode, try Single, Double, then Triple. */
  25242         /* Single wide non intra slice selection. */
  25243         if (0 == (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY)) {
  25244             LOG_DEBUG(BSL_LS_BCM_FP,
  25245                       (BSL_META_U(unit,
  25246                                   "Trying single...\n")));
  25247             fg->flags = (orig_group_flags | _FP_GROUP_SPAN_SINGLE_SLICE);
  25248             fsm_ptr->rv = _field_selcode_assign(unit, fg->qset, 1, fg);
  25249             if (BCM_FAILURE(fsm_ptr->rv)) {
  25250                 BCM_IF_ERROR_RETURN(_field_selcode_assign_udf_alternative(unit, fsm_ptr));
  25251             }
  25252         }
  25253 
  25254         /* Double wide intra slice selection. */
  25255         if ((BCM_FAILURE(fsm_ptr->rv) &&
  25256              (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE))) {
  25257             if (soc_feature(unit, soc_feature_field_intraslice_double_wide)) {
  25258                 LOG_DEBUG(BSL_LS_BCM_FP,
  25259                           (BSL_META_U(unit,
  25260                                       "Trying intra...\n")));
  25261                 fg->flags = (orig_group_flags |
  25262                              _FP_GROUP_SPAN_SINGLE_SLICE |
  25263                              _FP_GROUP_INTRASLICE_DOUBLEWIDE);
  25264                 fsm_ptr->rv = _field_selcode_assign(unit, fg->qset, 1, fg);
  25265                 if (BCM_FAILURE(fsm_ptr->rv)) {
  25266                     BCM_IF_ERROR_RETURN(_field_selcode_assign_udf_alternative(unit, fsm_ptr));
  25267                 }
  25268             }
  25269         }
  25270 
  25271         /* Double wide inter slice selection. */
  25272         if (0 == (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY)) {
  25273             if (BCM_FAILURE(fsm_ptr->rv)) {
  25274                 LOG_DEBUG(BSL_LS_BCM_FP,
  25275                           (BSL_META_U(unit,
  25276                                       "Trying double...\n")));
  25277                 fg->flags = (orig_group_flags | _FP_GROUP_SPAN_DOUBLE_SLICE);
  25278                 fsm_ptr->rv = _field_selcode_assign(unit, fg->qset, 1, fg);
  25279                 if (BCM_FAILURE(fsm_ptr->rv)) {
  25280                     BCM_IF_ERROR_RETURN(_field_selcode_assign_udf_alternative(unit, fsm_ptr));
  25281                 }
  25282             }
  25283         }
  25284 
  25285         /* Quad wide inter & intra slice selection. */
  25286         if ((BCM_FAILURE(fsm_ptr->rv) &&
  25287              (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE))) {
  25288             if (soc_feature(unit, soc_feature_field_intraslice_double_wide)) {
  25289                 LOG_DEBUG(BSL_LS_BCM_FP,
  25290                           (BSL_META_U(unit,
  25291                                       "Trying quad...\n")));
  25292                 fg->flags = (orig_group_flags |
  25293                              _FP_GROUP_SPAN_DOUBLE_SLICE |
  25294                              _FP_GROUP_INTRASLICE_DOUBLEWIDE);
  25295                 fsm_ptr->rv = _field_selcode_assign(unit, fg->qset, 1, fg);
  25296                 if (BCM_FAILURE(fsm_ptr->rv)) {
  25297                     BCM_IF_ERROR_RETURN(_field_selcode_assign_udf_alternative(unit, fsm_ptr));
  25298                 }
  25299             }
  25300         }
  25301 
  25302         /* Triple wide inter slice selection. */
  25303         if ((0 == soc_feature(unit, soc_feature_field_intraslice_double_wide)) &&
  25304             (0 == (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY)) &&
  25305             (!SOC_IS_TD_TT(unit))) {
  25306             if (BCM_FAILURE(fsm_ptr->rv)) {
  25307                 LOG_DEBUG(BSL_LS_BCM_FP,
  25308                           (BSL_META_U(unit,
  25309                                       "Trying triple...\n")));
  25310                 fg->flags = (orig_group_flags | _FP_GROUP_SPAN_TRIPLE_SLICE);
  25311                 fsm_ptr->rv = _field_selcode_assign(unit, fg->qset, 1, fg);
  25312                 if (BCM_FAILURE(fsm_ptr->rv)) {
  25313                     BCM_IF_ERROR_RETURN(_field_selcode_assign_udf_alternative(unit, fsm_ptr));
  25314                 }
  25315             }
  25316         }
  25317     } else {
  25318         switch (fsm_ptr->mode) {
  25319           case bcmFieldGroupModeSingle:
  25320               /* Single wide non intra slice selection. */
  25321               if (0 == (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY)) {
  25322                   fg->flags = (orig_group_flags | _FP_GROUP_SPAN_SINGLE_SLICE);
  25323                   fsm_ptr->rv = _field_selcode_assign(unit, fg->qset, 1, fg);
  25324                   if (BCM_FAILURE(fsm_ptr->rv)) {
  25325                       BCM_IF_ERROR_RETURN(_field_selcode_assign_udf_alternative(unit, fsm_ptr));
  25326                   }
  25327               }
  25328               break;
  25329           case bcmFieldGroupModeIntraSliceDouble:
  25330               /* Double wide intra slice selection. */
  25331               if ((soc_feature(unit, soc_feature_field_intraslice_double_wide)) &&
  25332                    (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE)) {
  25333                   fg->flags = (orig_group_flags |
  25334                                _FP_GROUP_SPAN_SINGLE_SLICE |
  25335                                _FP_GROUP_INTRASLICE_DOUBLEWIDE);
  25336                   fsm_ptr->rv = _field_selcode_assign(unit, fg->qset, 1, fg);
  25337                   if (BCM_FAILURE(fsm_ptr->rv)) {
  25338                       BCM_IF_ERROR_RETURN(_field_selcode_assign_udf_alternative(unit, fsm_ptr));
  25339                   }
  25340               }
  25341               break;
  25342           case bcmFieldGroupModeDouble:
  25343               /* Double wide intra slice selection. */
  25344               if ((soc_feature(unit, soc_feature_field_intraslice_double_wide) &&
  25345                    (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE))) {
  25346                   fg->flags = (orig_group_flags |
  25347                                _FP_GROUP_SPAN_SINGLE_SLICE |
  25348                                _FP_GROUP_INTRASLICE_DOUBLEWIDE);
  25349                   fsm_ptr->rv = _field_selcode_assign(unit, fg->qset, 1, fg);
  25350                   if (BCM_FAILURE(fsm_ptr->rv)) {
  25351                       BCM_IF_ERROR_RETURN(_field_selcode_assign_udf_alternative(unit, fsm_ptr));
  25352                   }
  25353               }
  25354               /* Double wide inter slice selection. */
  25355               if ((BCM_FAILURE(fsm_ptr->rv)) &&
  25356                   (0 == (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY))) {
  25357                   fg->flags = (orig_group_flags | _FP_GROUP_SPAN_DOUBLE_SLICE);
  25358                   fsm_ptr->rv = _field_selcode_assign(unit, fg->qset, 1, fg);
  25359                   if (BCM_FAILURE(fsm_ptr->rv)) {
  25360                       BCM_IF_ERROR_RETURN(_field_selcode_assign_udf_alternative(unit, fsm_ptr));
  25361                   }
  25362               }
  25363               break;
  25364           case bcmFieldGroupModeTriple:
  25365               /* Triple wide inter slice selection. */
  25366               if (0 == (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY)) {
  25367                   fg->flags = (orig_group_flags | _FP_GROUP_SPAN_TRIPLE_SLICE);
  25368                   fsm_ptr->rv = _field_selcode_assign(unit, fg->qset, 1, fg);
  25369                   if (BCM_FAILURE(fsm_ptr->rv)) {
  25370                       BCM_IF_ERROR_RETURN(_field_selcode_assign_udf_alternative(unit, fsm_ptr));
  25371                   }
  25372               }
  25373               break;
  25374           case bcmFieldGroupModeQuad:
  25375               if ((soc_feature(unit, soc_feature_field_intraslice_double_wide) &&
  25376                    (fsm_ptr->flags & _BCM_FP_GROUP_ADD_INTRA_SLICE))) {
  25377                   fg->flags = (orig_group_flags | _FP_GROUP_SPAN_DOUBLE_SLICE |
  25378                                _FP_GROUP_INTRASLICE_DOUBLEWIDE);
  25379                   fsm_ptr->rv = _field_selcode_assign(unit, fg->qset, 1, fg);
  25380                   if (BCM_FAILURE(fsm_ptr->rv)) {
  25381                       BCM_IF_ERROR_RETURN(_field_selcode_assign_udf_alternative(unit, fsm_ptr));
  25382                   }
  25383               }
  25384               break;
  25385           default:
  25386               fsm_ptr->rv = (BCM_E_PARAM);
  25387         }
  25388     }
  25389 
  25390     if (BCM_FAILURE(fsm_ptr->rv)) {
  25391         LOG_DEBUG(BSL_LS_BCM_FP,
  25392                   (BSL_META_U(unit,
  25393                               "No success so far.\n")));
  25394         /* No luck so far - try different alternative qset if possible. */
  25395         if ((BCM_E_RESOURCE == fsm_ptr->rv) &&
  25396             (_BCM_FP_GROUP_ADD_STATE_QSET_UPDATE == fsm_ptr->fsm_state_prev)) {
  25397             fsm_ptr->rv = (BCM_E_NONE);
  25398             fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_QSET_ALTERNATE;
  25399         }
  25400     } else {
  25401 #ifdef BCM_TRIUMPH2_SUPPORT /* BCM_TRIUMPH2_SUPPORT */
  25402         int i, ingress_entity = 0;
  25403 #endif /* !BCM_TRIUMPH2_SUPPORT */
  25404 
  25405         LOG_DEBUG(BSL_LS_BCM_FP,
  25406                   (BSL_META_U(unit,
  25407                               "Configuration found...\n")));
  25408         /* Check if unit supports wide rules. */
  25409         if ((!soc_feature(unit, soc_feature_field_wide)) &&
  25410             (!(fg->flags & _FP_GROUP_SPAN_SINGLE_SLICE)))
  25411         {
  25412             LOG_DEBUG(BSL_LS_BCM_FP,
  25413                       (BSL_META_U(unit,
  25414                                   "Double not supported.\n")));
  25415             fsm_ptr->rv = (BCM_E_UNAVAIL);
  25416         }
  25417 
  25418 #ifdef BCM_TRIUMPH2_SUPPORT /* BCM_TRIUMPH2_SUPPORT */
  25419         /*
  25420          * Check which configuration of SrcMplsGport/SrcMimGport/
  25421          * SrcNivGport is in use.
  25422          */
  25423         for (i = 0; i < _FP_MAX_ENTRY_WIDTH; i++) {
  25424             if ((fg->sel_codes[i].ingress_entity_sel ==
  25425                     _bcmFieldFwdEntityMimGport) ||
  25426                 (fg->sel_codes[i].ingress_entity_sel ==
  25427                     _bcmFieldFwdEntityMplsGport) ||
  25428                 (fg->sel_codes[i].ingress_entity_sel ==
  25429                     _bcmFieldFwdEntityNivGport) ||
  25430                 (fg->sel_codes[i].ingress_entity_sel ==
  25431                     _bcmFieldFwdEntityWlanGport) ||
  25432                 (fg->sel_codes[i].ingress_entity_sel ==
  25433                     _bcmFieldFwdEntityVxlanGport) ||
  25434                 (fg->sel_codes[i].ingress_entity_sel ==
  25435                     _bcmFieldFwdEntityVlanGport) ||
  25436                 (fg->sel_codes[i].ingress_entity_sel ==
  25437                     _bcmFieldFwdEntityCommonGport)) {
  25438                 ingress_entity = 1;
  25439                 break;
  25440             }
  25441         }
  25442 
  25443         /* Adjust for SvpValid where applicable */
  25444         if (soc_feature(unit, soc_feature_mim) &&
  25445               (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcMimGport) ||
  25446               (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcMimGports)) ||
  25447                BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcGports) ||
  25448                BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcGport)) &&
  25449                !BCM_FIELD_QSET_TEST(fg->qset, _bcmFieldQualifySvpValid) &&
  25450                (1 == ingress_entity)) {
  25451 
  25452             /* SrcMimGport */
  25453             BCM_FIELD_QSET_ADD(fg->qset, _bcmFieldQualifySvpValid);
  25454             fsm_ptr->rv = (BCM_E_NONE);
  25455             fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_QSET_ALTERNATE;
  25456 
  25457         } else if ((_BCM_FIELD_STAGE_INGRESS == fg->stage_id) &&
  25458                 (1 == ingress_entity) &&
  25459                 !BCM_FIELD_QSET_TEST(fg->qset, _bcmFieldQualifySvpValid) &&
  25460                 (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcMplsGport) ||
  25461                  BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcMplsGports) ||
  25462                  BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcGports) ||
  25463                  BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcGport)  ||
  25464                  BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcNivGport) ||
  25465                  BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcNivGports) ||
  25466                  BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcVxlanGport) ||
  25467                  BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcVxlanGports) ||
  25468                  BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcVlanGport) ||
  25469                  BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcVlanGports))) {
  25470             /* SrcMplsGport or SrcNivGport or SrcVxlanGport or SrcVlanGport */
  25471             BCM_FIELD_QSET_ADD(fg->qset, _bcmFieldQualifySvpValid);
  25472             fsm_ptr->rv = (BCM_E_NONE);
  25473             fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_QSET_ALTERNATE;
  25474         } else
  25475 #endif /* !BCM_TRIUMPH2_SUPPORT */
  25476         {
  25477             /* Insert group into units group list. */
  25478             if (BCM_SUCCESS(fsm_ptr->rv)) {
  25479                 fsm_ptr->rv = _bcm_field_group_linked_list_insert(unit, fsm_ptr);
  25480             }
  25481 
  25482             /* Success proceed to slice allocation. */
  25483             if (BCM_SUCCESS(fsm_ptr->rv)) {
  25484                 if ((fsm_ptr->flags & _FP_GROUP_CONFIG_VALIDATE)) {
  25485                     fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END;
  25486                 } else {
  25487                     fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SLICE_ALLOCATE;
  25488                 }
  25489             } else {
  25490                 fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END;
  25491             }
  25492         }
  25493     }
  25494 
  25495     /* Set current state to be previous state. */
  25496     fsm_ptr->fsm_state_prev = _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET;
  25497 
  25498     return _bcm_field_group_add(unit, fsm_ptr);
  25499 }
  25500 
  25501 
  25502 /*
  25503  * Function:
  25504  *     _field_group_add_qset_alternate
  25505  * Purpose:
  25506  *     Update application requested qset with equivalent one
  25507  *     which might allow to select F1, F2 Fn  select codes.
  25508  * Parameters:
  25509  *     unit     - (IN)     BCM device number.
  25510  *     fsm_ptr  - (IN/OUT) State machine tracking structure.
  25511  * Returns:
  25512  *     BCM_E_XXX
  25513  */
  25514 STATIC int
  25515 _field_group_add_qset_alternate(int unit, _field_group_add_fsm_t *fsm_ptr)
  25516 {
  25517     /* Input parameters check. */
  25518     if (NULL == fsm_ptr) {
  25519         return (BCM_E_PARAM);
  25520     }
  25521 
  25522     /* Set current state to be previous state. */
  25523     fsm_ptr->fsm_state_prev = fsm_ptr->fsm_state;
  25524 
  25525 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAPTOR_SUPPORT)
  25526     if ((SOC_IS_FIREBOLT2(unit) || SOC_IS_HAWKEYE(unit))
  25527         && (BCM_FIELD_QSET_TEST(fsm_ptr->fg->qset, bcmFieldQualifyTtl))) {
  25528 
  25529         BCM_FIELD_QSET_REMOVE(fsm_ptr->fg->qset, bcmFieldQualifyTtl);
  25530         if (SOC_IS_FIREBOLT2(unit)) {
  25531             fsm_ptr->flags |= _BCM_FP_GROUP_ADD_INTRA_SLICE_ONLY;
  25532         }
  25533 
  25534         /* Proceed to a second attempt of select codes selection. */
  25535         fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET;
  25536     } else
  25537 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAPTOR_SUPPORT */
  25538 #ifdef BCM_TRIUMPH2_SUPPORT
  25539     if (soc_feature(unit, soc_feature_mim)) {
  25540         /* Proceed to a second attempt of select codes selection. */
  25541         fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET;
  25542     } else if (BCM_FIELD_QSET_TEST(fsm_ptr->fg->qset, bcmFieldQualifySrcMplsGport)) {
  25543         /* Proceed to a second attempt of select codes selection. */
  25544         fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET;
  25545     } else if (BCM_FIELD_QSET_TEST(fsm_ptr->fg->qset, bcmFieldQualifySrcNivGport)) {
  25546         /* Proceed to a second attempt of select codes selection. */
  25547         fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET;
  25548     } else if (BCM_FIELD_QSET_TEST(fsm_ptr->fg->qset, bcmFieldQualifySrcVxlanGport)) {
  25549         /* Proceed to a second attempt of select codes selection. */
  25550         fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET;
  25551     } else if (BCM_FIELD_QSET_TEST(fsm_ptr->fg->qset, bcmFieldQualifySrcVlanGport)) {
  25552         /* Proceed to a second attempt of select codes selection. */
  25553         fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET;
  25554     } else if (BCM_FIELD_QSET_TEST(fsm_ptr->fg->qset, bcmFieldQualifySrcGport)) {
  25555         /* Proceed to a second attempt of select codes selection. */
  25556         fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET;
  25557     } else if (BCM_FIELD_QSET_TEST(fsm_ptr->fg->qset, bcmFieldQualifySrcGports)) {
  25558         /* Proceed to a second attempt of select codes selection. */
  25559         fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET;
  25560     } else
  25561 #endif
  25562     {
  25563         fsm_ptr->rv = (BCM_E_RESOURCE);
  25564         fsm_ptr->fsm_state = _BCM_FP_GROUP_ADD_STATE_END;
  25565     }
  25566     return _bcm_field_group_add(unit, fsm_ptr);
  25567 }
  25568 
  25569 /*
  25570  * Function:
  25571  *     _field_group_add_end
  25572  * Purpose:
  25573  *     Group add state machine last /clean up state.
  25574  * Parameters:
  25575  *     unit     - (IN)     BCM device number.
  25576  *     fsm_ptr  - (IN/OUT) State machine tracking structure.
  25577  * Returns:
  25578  *     BCM_E_XXX
  25579  */
  25580 STATIC int
  25581 _field_group_add_end(int unit, _field_group_add_fsm_t *fsm_ptr)
  25582 {
  25583     /* Input parameters check. */
  25584     if (NULL == fsm_ptr) {
  25585         return (BCM_E_PARAM);
  25586     }
  25587 
  25588     if (BCM_FAILURE(fsm_ptr->rv)
  25589         || BCM_FAILURE(fsm_ptr->rv = _field_group_default_aset_set(unit, fsm_ptr->fg))
  25590         ) {
  25591         _field_group_deinit(unit, fsm_ptr->fg);
  25592     }
  25593 
  25594     return (fsm_ptr->rv);
  25595 }
  25596 
  25597 /*
  25598  * Function: _bcm_field_group_add
  25599  *
  25600  * Purpose:
  25601  *     Create a field processor group
  25602  * Parameters:
  25603  *     unit     - (IN)     BCM device number.
  25604  *     fsm_ptr  - (IN/OUT) State machine tracking structure.
  25605  * Returns:
  25606  *     BCM_E_XXX.
  25607  */
  25608 int
  25609 _bcm_field_group_add(int unit, _field_group_add_fsm_t *fsm_ptr)
  25610 {
  25611     int rv;             /* Operation return status.   */
  25612                         /* Group add fsm state names. */
  25613 #if defined(BROADCOM_DEBUG)
  25614     static char *_bcm_fp_group_add_state[bcmFieldQualifyCount] = \
  25615         _BCM_FP_GROUP_ADD_STATE_STRINGS;
  25616 #endif /* BROADCOM_DEBUG */
  25617 
  25618     /* Input parameters check. */
  25619     if (NULL == fsm_ptr) {
  25620         return (BCM_E_PARAM);
  25621     }
  25622 
  25623     rv = (BCM_E_NONE);
  25624 
  25625 #if defined(BROADCOM_DEBUG)
  25626     LOG_DEBUG(BSL_LS_BCM_FP,
  25627               (BSL_META_U(unit,
  25628                           "FP(unit %d) vverb: group add: state (%s) state_prev (%s)  status (%d).\n"),
  25629                unit,
  25630                _bcm_fp_group_add_state[fsm_ptr->fsm_state],
  25631                _bcm_fp_group_add_state[fsm_ptr->fsm_state_prev],
  25632                fsm_ptr->rv));
  25633 #endif /* BROADCOM_DEBUG */
  25634 
  25635     /* Run through group creation states. */
  25636     switch (fsm_ptr->fsm_state) {
  25637       case _BCM_FP_GROUP_ADD_STATE_START:
  25638           rv = _field_group_add_initialize(unit, fsm_ptr);
  25639           break;
  25640 
  25641       case _BCM_FP_GROUP_ADD_STATE_ALLOC:
  25642           rv = _field_group_add_alloc(unit, fsm_ptr);
  25643           break;
  25644 
  25645       case _BCM_FP_GROUP_ADD_STATE_QSET_UPDATE:
  25646           rv = _field_group_add_qset_update(unit, fsm_ptr);
  25647           break;
  25648 
  25649       case _BCM_FP_GROUP_ADD_STATE_SEL_CODES_GET:
  25650           rv = _field_group_add_sel_codes_get(unit, fsm_ptr);
  25651           break;
  25652 
  25653       case _BCM_FP_GROUP_ADD_STATE_QSET_ALTERNATE:
  25654           rv = _field_group_add_qset_alternate(unit, fsm_ptr);
  25655           break;
  25656 
  25657       case _BCM_FP_GROUP_ADD_STATE_SLICE_ALLOCATE:
  25658           rv = _field_group_add_slice_allocate(unit, fsm_ptr);
  25659           break;
  25660 
  25661       case _BCM_FP_GROUP_ADD_STATE_CAM_COMPRESS:
  25662           rv = _field_group_add_cam_compress(unit, fsm_ptr);
  25663           break;
  25664       case _BCM_FP_GROUP_ADD_STATE_SLICE_ALIGN:
  25665           rv = _field_group_add_slice_align(unit, fsm_ptr);
  25666           break;
  25667       case _BCM_FP_GROUP_ADD_STATE_HW_QUAL_LIST_GET:
  25668           rv = _field_group_add_hw_qual_list_get(unit, fsm_ptr);
  25669           break;
  25670 
  25671       case _BCM_FP_GROUP_ADD_STATE_UDF_UPDATE:
  25672           rv = _field_group_add_udf_update(unit, fsm_ptr);
  25673           break;
  25674 
  25675       case _BCM_FP_GROUP_ADD_STATE_ADJUST_VIRTUAL_MAP:
  25676           rv = _field_group_add_adjust_virtual_map(unit, fsm_ptr);
  25677           break;
  25678 
  25679       case _BCM_FP_GROUP_ADD_STATE_END:
  25680           rv = _field_group_add_end(unit, fsm_ptr);
  25681           break;
  25682 
  25683     }
  25684     return (rv);
  25685 }
  25686 
  25687 /*
  25688  * Function:
  25689  *     _bcm_field_entries_free_get
  25690  *
  25691  * Purpose:
  25692  *     Return the number of free entries in a slice.
  25693  *
  25694  * Parameters:
  25695  *     unit        - (IN) BCM device number.
  25696  *     fs          - (IN) Slice to count free entries in.
  25697  *     fg          - (IN) Group (for checking the INTRASLICE-DW flag)
  25698  *     free_cnt  - (OUT)Count of unused entries.
  25699  *
  25700  * Returns:
  25701  *     BCM_E_XXX
  25702  *
  25703  * Notes:
  25704  *     Assumes all groups in a slice have the same mode (regular/INTRASLICE-DW)
  25705  */
  25706 int
  25707 _bcm_field_entries_free_get(int unit, _field_slice_t *fs,
  25708                             _field_group_t *fg, int *free_cnt)
  25709 {
  25710     /* Input parameters check. */
  25711     if ((NULL == fs) || (NULL == free_cnt)) {
  25712         return (BCM_E_PARAM);
  25713     }
  25714 
  25715     /* Initialization check. */
  25716     FIELD_IS_INIT(unit);
  25717 
  25718 #if defined(BCM_FLOWTRACKER_SUPPORT)
  25719     if (fg->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) {
  25720         return _field_hx5_ft_entries_free_get(unit, fs, fg, free_cnt);
  25721     }
  25722 #endif
  25723 
  25724     *free_cnt = fs->free_count;
  25725     return (BCM_E_NONE);
  25726 }
  25727 
  25728 /*
  25729  * Function:
  25730  *     _bcm_field_counters_total_get
  25731  *
  25732  * Purpose:
  25733  *     Report total number of counters available.
  25734  *
  25735  * Parameters:
  25736  *     stage_fc     - (IN) Stage field control structure.
  25737  *     fs           - (IN) Slice to count the total counters.
  25738  *
  25739  * Returns:
  25740  *     Number of unused counters in slice.
  25741  */
  25742 int
  25743 _bcm_field_counters_total_get(const _field_stage_t *stage_fc,
  25744                               const _field_slice_t *fs)
  25745 {
  25746     int total_count = 0;
  25747     /* Input parameters check. */
  25748     if ((NULL == fs) || (NULL == stage_fc)) {
  25749         return (BCM_E_PARAM);
  25750     }
  25751 
  25752     if (fs->stage_id == _BCM_FIELD_STAGE_EXTERNAL) {
  25753         /*
  25754          * There is an 1-1 mapping between rules and counters
  25755          * for external FP. So, total number of counters is equal
  25756          * to number of entries on that slice.
  25757          */
  25758         return fs->entry_count;
  25759     } else {
  25760            if (stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS) {
  25761                int i;
  25762                for (i = 0; i < stage_fc->num_cntr_pools; i++) {
  25763                total_count += stage_fc->cntr_pool[i]->size;
  25764                }
  25765                return total_count;
  25766            }
  25767            return fs->counters_count;
  25768       }
  25769 }
  25770 
  25771 /*
  25772  * Function:
  25773  *     _bcm_field_counter_free_get
  25774  *
  25775  * Purpose:
  25776  *     Report the number of unused counter pairs in a slice.
  25777  *
  25778  * Parameters:
  25779  *     stage_fc     - (IN) Stage field control structure.
  25780  *     fs           - (IN) Slice to count free counters in.
  25781  *
  25782  * Returns:
  25783  *     Number of unused counters in slice.
  25784  */
  25785 int
  25786 _bcm_field_counter_free_get(const _field_stage_t *stage_fc,
  25787                             const _field_slice_t *fs)
  25788 {
  25789     int                 counter;
  25790     int                 free_count = 0;
  25791 
  25792     /* Input parameters check. */
  25793     if ((NULL == fs) || (NULL == stage_fc)) {
  25794         return (BCM_E_PARAM);
  25795     }
  25796 
  25797     if (fs->stage_id == _BCM_FIELD_STAGE_EXTERNAL) {
  25798         return fs->free_count;
  25799     }
  25800     if (stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS) {
  25801         int i;
  25802         for (i = 0; i < stage_fc->num_cntr_pools; i++) {
  25803             free_count += stage_fc->cntr_pool[i]->free_cntrs;
  25804         }
  25805         return free_count;
  25806     }
  25807 
  25808     /* Count unused counters. */
  25809     for (counter = 0; counter < fs->counters_count; counter++) {
  25810         if (0 == _FP_COUNTER_BMP_TEST(fs->counter_bmp, counter)) {
  25811             free_count++;
  25812         }
  25813     }
  25814     return free_count;
  25815 }
  25816 
  25817 /*
  25818  * Function:
  25819  *     _bcm_field_meters_total_get
  25820  *
  25821  * Purpose:
  25822  *     Return total number of meters/meter pairs on device.
  25823  *
  25824  * Parameters:
  25825  *     stage_fc    - (IN) Stage field control structure.
  25826  *     instance    - (IN) Pipe Instance.
  25827  *     fs          - (IN) Slice to count number of meters.
  25828  *
  25829  * Returns:
  25830  *     Total number of meters/meter pairs on device.
  25831  */
  25832 int
  25833 _bcm_field_meters_total_get(const _field_stage_t *stage_fc, int instance,
  25834                             const _field_slice_t *fs)
  25835 {
  25836     int                 numb_meters = 0;
  25837 
  25838     /* Input parameters check. */
  25839     if ((NULL == fs) || (NULL == stage_fc)) {
  25840         return (BCM_E_PARAM);
  25841     }
  25842 
  25843     if (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) {
  25844         int i;
  25845         for (i = 0; i < stage_fc->num_meter_pools; i++) {
  25846             numb_meters += stage_fc->meter_pool[instance][i]->size;
  25847         }
  25848         return numb_meters;
  25849     } else {
  25850         return  fs->meters_count;
  25851     }
  25852 }
  25853 
  25854 /*
  25855  * Function:
  25856  *     _bcm_field_meter_free_get
  25857  *
  25858  * Purpose:
  25859  *     Fill in the values of a group status struct.
  25860  *
  25861  * Parameters:
  25862  *     stage_fc    - (IN) Stage field control structure.
  25863  *     fg          - (IN) field group structure.
  25864  *     fs          - (IN) Slice to count free counters in.
  25865  *
  25866  * Returns:
  25867  *     Number of unused meters in slice.
  25868  */
  25869 int
  25870 _bcm_field_meter_free_get(const _field_stage_t *stage_fc, const
  25871                           _field_group_t *fg, const _field_slice_t *fs)
  25872 {
  25873     int                 meter;
  25874     int                 numb_meters = 0;
  25875     int                 slice_id;
  25876 
  25877     /* Input parameters check. */
  25878     if ((NULL == fs) || (NULL == stage_fc)) {
  25879         return (BCM_E_PARAM);
  25880     }
  25881 
  25882     /* For stages ExactMatch and External meter pool slice id is
  25883        equal to tcam slices */
  25884     if ((_BCM_FIELD_STAGE_EXTERNAL == fg->stage_id) ||
  25885         (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id)) {
  25886         slice_id = stage_fc->tcam_slices;
  25887     } else {
  25888         slice_id = fs->slice_number;
  25889     }
  25890 
  25891     if (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) {
  25892         int i;
  25893         for (i = 0; i < stage_fc->num_meter_pools; i++) {
  25894             _field_meter_pool_t *mp = stage_fc->meter_pool[fg->instance][i];
  25895 
  25896             if (mp->slice_id == slice_id /* Pool belongs to slice */
  25897                 || mp->slice_id == _FP_INVALID_INDEX /* Pool is unallocated */
  25898                 ) {
  25899                 numb_meters += mp->free_meters;
  25900             }
  25901         }
  25902         return numb_meters;
  25903     }
  25904 
  25905     for (meter = 0; meter < fs->meters_count; meter++) {
  25906         if (_FP_METER_BMP_TEST(fs->meter_bmp, meter)) {
  25907             numb_meters++;
  25908         }
  25909     }
  25910     return  fs->meters_count - numb_meters;
  25911 }
  25912 
  25913 
  25914 /*
  25915  * Function:
  25916  *     _field_udf_usecount_update
  25917  *
  25918  * Purpose:
  25919  *     Increment the use-counts of any new UDFs.
  25920  *
  25921  * Parameters:
  25922  *     udf      - Unit's control array of UDFs
  25923  *     qset_old - Previous Qset
  25924  *     qset_new - New Qset
  25925  *
  25926  * Returns:
  25927  *     nothing
  25928  */
  25929 void
  25930 _field_udf_usecount_update(_field_udf_t *udf,
  25931                            bcm_field_qset_t *qset_old,
  25932                            bcm_field_qset_t *qset_new)
  25933 {
  25934     int                  idx_new;
  25935 
  25936     /* For all UDFs in new Qset. */
  25937     for (idx_new = 0; idx_new < BCM_FIELD_USER_NUM_UDFS; idx_new++) {
  25938         if (!SHR_BITGET(qset_new->udf_map, idx_new)) {
  25939             continue;
  25940         }
  25941 
  25942         /* If UDF is in new Qset but not in old Qset, increment use-count. */
  25943         if (!SHR_BITGET(qset_old->udf_map, idx_new)) {
  25944             udf[idx_new].use_count++;
  25945         }
  25946     }
  25947 }
  25948 
  25949 /*
  25950  * Function: _field_fb_entries_enable_set
  25951  *
  25952  * Purpose:
  25953  *     Enable/disable the lookup of entries of a group
  25954  *
  25955  * Parameters:
  25956  *     unit   - BCM device number
  25957  *     fg     - Group the entry belongs to
  25958  *     fs     - Slice the entry is present in
  25959  *     enable - lookup enable!=0/disable==0 state of group
  25960  *
  25961  * Returns:
  25962  *     BCM_E_NONE      - Success
  25963  *     BCM_E_XXX       - BCM error codes
  25964  *
  25965  * Note:
  25966  *     For Intraslice-dw (FB2), we run over entries in both half's.
  25967  *
  25968  *     A group may be spanning multiple slices
  25969  *         (due to group autoexpansion)
  25970  */
  25971 int
  25972 _field_fb_entries_enable_set(int unit, _field_group_t *fg,
  25973                               _field_slice_t *fs, int enable)
  25974 {
  25975     _field_stage_t *stage_fc;
  25976     soc_mem_t mem = INVALIDm;
  25977     uint32  e[SOC_MAX_MEM_FIELD_WORDS];
  25978     int index, i;
  25979 
  25980     /* External stage entries are always enabled */
  25981     if (_BCM_FIELD_STAGE_EXTERNAL == fg->stage_id) {
  25982         return (BCM_E_NONE);
  25983     }
  25984 
  25985     BCM_IF_ERROR_RETURN
  25986         (_field_stage_control_get(unit, fg->stage_id, &stage_fc));
  25987 
  25988     if (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) {
  25989         mem = FP_TCAMm;
  25990 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  25991     } else if (soc_feature(unit, soc_feature_field_multi_stage)) {
  25992         if (_BCM_FIELD_STAGE_LOOKUP  == stage_fc->stage_id) {
  25993             mem = VFP_TCAMm;
  25994         } else if (_BCM_FIELD_STAGE_EGRESS  == stage_fc->stage_id) {
  25995             mem = EFP_TCAMm;
  25996         } else {
  25997             return (BCM_E_INTERNAL);
  25998         }
  25999 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  26000     } else {
  26001         return BCM_E_INTERNAL;
  26002     }
  26003 
  26004     while (fs->next != NULL) {
  26005         fs = fs->next;
  26006     }
  26007 
  26008     while (fs != NULL) {
  26009         for (i = fs->entry_count - 1; i >= 0; i--) {
  26010             if (fs->entries[i] != NULL) {
  26011                 if (fs->entries[i]->group->gid == fg->gid) {
  26012                     BCM_IF_ERROR_RETURN(
  26013                        _bcm_field_entry_tcam_idx_get(unit, fs->entries[i], &index));
  26014                     /* Read tcam entry from index. */
  26015                     SOC_IF_ERROR_RETURN
  26016                         (soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, e));
  26017 
  26018                     /* Set the VALIDf bits appropriately, VALIDf in VFP_TCAM on TH2 only has one bit*/
  26019 #if defined(BCM_TOMAHAWK2_SUPPORT)
  26020                     if (soc_feature(unit, soc_feature_field_multi_pipe_enhanced) &&
  26021                         _BCM_FIELD_STAGE_LOOKUP  == stage_fc->stage_id) {
  26022                         soc_mem_field32_set(unit, mem, e, VALIDf, enable? 1 : 0);
  26023                     } else
  26024 #endif /* BCM_TOMAHAWK2_SUPPORT */
  26025                     {
  26026                         if (enable) {
  26027                             if (fs->entries[i]->flags & _FP_ENTRY_INSTALLED) {
  26028 #if defined(BCM_TOMAHAWK3_SUPPORT)
  26029                                 if (SOC_IS_TOMAHAWK3(unit) &&
  26030                                     ((stage_fc->stage_id == _BCM_FIELD_STAGE_EGRESS) ||
  26031                                      (stage_fc->stage_id == _BCM_FIELD_STAGE_LOOKUP))) {
  26032                                      soc_mem_field32_set(unit, mem, e, VALIDf, 1);
  26033                                 } else
  26034 #endif /* BCM_TOMAHAWK3_SUPPORT */
  26035                                 {
  26036                                     soc_mem_field32_set(unit, mem, e, VALIDf, 3);
  26037                                 }
  26038 
  26039                             } else {
  26040                                 soc_mem_field32_set(unit, mem, e, VALIDf, 0);
  26041                             }
  26042                         } else {
  26043 #if defined(BCM_TOMAHAWK3_SUPPORT)
  26044                             if (SOC_IS_TOMAHAWK3(unit) &&
  26045                                 ((stage_fc->stage_id == _BCM_FIELD_STAGE_EGRESS) ||
  26046                                  (stage_fc->stage_id == _BCM_FIELD_STAGE_LOOKUP))) {
  26047 
  26048                                  soc_mem_field32_set(unit, mem, e, VALIDf, 0);
  26049                             } else
  26050 #endif /* BCM_TOMAHAWK3_SUPPORT */
  26051                             {
  26052                                 soc_mem_field32_set(unit, mem, e, VALIDf, 2);
  26053                             }
  26054                         }
  26055                     }
  26056 
  26057                     /* Write back the TCAM entry */
  26058                     SOC_IF_ERROR_RETURN
  26059                         (soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, e));
  26060                 }
  26061             }
  26062         }
  26063         fs = fs->prev;
  26064     }
  26065 
  26066     if (enable) {
  26067         fg->flags |= _FP_GROUP_LOOKUP_ENABLED;
  26068     } else {
  26069         fg->flags &= ~_FP_GROUP_LOOKUP_ENABLED;
  26070     }
  26071 
  26072     return BCM_E_NONE;
  26073 }
  26074 
  26075 /*
  26076  * Function: _field_range_flags_check
  26077  *
  26078  * Purpose:
  26079  *     Sanity check on range flags.
  26080  *
  26081  * Parameters:
  26082  *     unit   - (IN) BCM device number.
  26083  *     flags  - (IN) One or more of BCM_FIELD_RANGE_* flags.
  26084  *
  26085  * Returns:
  26086  *     BCM_E_XXX  - Flags are valid & supported.
  26087  */
  26088 int
  26089 _field_range_flags_check(int unit, uint32 flags)
  26090 {
  26091     int   cntr;                 /* Range types counter.  */
  26092 
  26093     /* ESW family of devices do not support range check in lookup stage */
  26094     if (flags & BCM_FIELD_RANGE_LOOKUP) {
  26095         return (BCM_E_UNAVAIL);
  26096     }
  26097 
  26098     /* Make sure only one range was selected. */
  26099     cntr = 0;
  26100     if (flags & BCM_FIELD_RANGE_SRCPORT) {
  26101         cntr++;
  26102     }
  26103     if (flags & BCM_FIELD_RANGE_DSTPORT) {
  26104         cntr++;
  26105     }
  26106     if (flags & BCM_FIELD_RANGE_OUTER_VLAN) {
  26107         cntr++;
  26108     }
  26109     if (flags & BCM_FIELD_RANGE_PACKET_LENGTH) {
  26110         cntr++;
  26111     }
  26112     if (cntr > 1) {
  26113         return (BCM_E_PARAM);
  26114     }
  26115 
  26116     /* Outer vlan & packet length ranges supported by trx devices only.*/
  26117     if ((flags & BCM_FIELD_RANGE_OUTER_VLAN)  ||
  26118         (flags & BCM_FIELD_RANGE_PACKET_LENGTH)) {
  26119         if (0 == SOC_IS_TRX(unit)) {
  26120             return (BCM_E_UNAVAIL);
  26121         }
  26122     }
  26123 
  26124     /* Range TCP/UDP/Invert supported on 5660x devices only. */
  26125     if (flags & (BCM_FIELD_RANGE_TCP |
  26126                  BCM_FIELD_RANGE_UDP |
  26127                  BCM_FIELD_RANGE_INVERT)) {
  26128         return (BCM_E_UNAVAIL);
  26129     }
  26130     return (BCM_E_NONE);
  26131 }
  26132 
  26133 
  26134 /*
  26135  * Function: _field_range_create
  26136  *
  26137  * Purpose:
  26138  *     Create field range object.
  26139  *
  26140  * Parameters:
  26141  *     unit   - (IN) BCM device number.
  26142  *
  26143  * Returns:
  26144  *     BCM_E_XXX
  26145  */
  26146 int
  26147 _field_range_create(int unit, bcm_field_range_t *range,
  26148                     uint32 flags, bcm_l4_port_t min,
  26149                     bcm_l4_port_t max, bcm_if_group_t group)
  26150 {
  26151     _field_stage_t      *stage_fc;
  26152     int                 rv;
  26153 
  26154     if (flags & BCM_FIELD_RANGE_EXTERNAL) {
  26155         BCM_IF_ERROR_RETURN
  26156             (_field_stage_control_get(unit, _BCM_FIELD_STAGE_EXTERNAL,
  26157                                       &stage_fc));
  26158     } else {
  26159         BCM_IF_ERROR_RETURN
  26160             (_field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS,
  26161                                       &stage_fc));
  26162     }
  26163 
  26164     for (;;) {
  26165         if (group == -1) {
  26166             rv = bcm_esw_field_range_create_id(unit, stage_fc->range_id,
  26167                                                flags, min, max);
  26168         } else {
  26169             rv = bcm_esw_field_range_group_create_id(unit, stage_fc->range_id,
  26170                                                      flags, min, max, group);
  26171         }
  26172 
  26173         if (rv != BCM_E_EXISTS) {
  26174             break;
  26175         }
  26176 
  26177         if (++stage_fc->range_id == 0) {
  26178             stage_fc->range_id = 1;
  26179         }
  26180     }
  26181 
  26182     if (BCM_SUCCESS(rv)) {
  26183         *range = stage_fc->range_id;
  26184 
  26185         if (++stage_fc->range_id == 0) {
  26186             stage_fc->range_id = 1;
  26187         }
  26188     }
  26189     return rv;
  26190 }
  26191 
  26192 /*
  26193  * Function:
  26194  *     _field_fb_er_range_check_set
  26195  * Purpose:
  26196  *     Write the group's range checking parameters into the FP_RANGE_CHECK
  26197  *     memory.
  26198  * Parameters:
  26199  *     unit   - BCM unit
  26200  *     range  - Range HW index
  26201  *     flags  - One of more of the BCM_FIELD_RANGE_* flags
  26202  *     enable - TRUE or FALSE
  26203  *     min    - Lower bounds of port range to be checked
  26204  *     max    - Upper bounds of port range to be checked
  26205  * Returns:
  26206  *     BCM_E_NONE
  26207  *     BCM_E_PARAM - Unrecognized flag.
  26208  * Notes:
  26209  *    Calling function should have unit's lock.
  26210  */
  26211 int
  26212 _field_fb_er_range_check_set(int unit, int range, uint32 flags, int enable,
  26213                              bcm_l4_port_t min, bcm_l4_port_t max)
  26214 {
  26215     fp_range_check_entry_t  tbl_entry;
  26216     uint32                  src_chk = 0;
  26217 
  26218     assert(soc_mem_index_valid(unit, FP_RANGE_CHECKm, range));
  26219 
  26220     if (enable) {
  26221         switch (flags & (BCM_FIELD_RANGE_SRCPORT | BCM_FIELD_RANGE_DSTPORT)) {
  26222         case BCM_FIELD_RANGE_SRCPORT:
  26223             src_chk = 1;
  26224             break;
  26225         case BCM_FIELD_RANGE_DSTPORT:
  26226             break;
  26227         default:
  26228             LOG_ERROR(BSL_LS_BCM_FP,
  26229                       (BSL_META_U(unit,
  26230                                   "FP(unit %d) Error: unsupported flags %#x\n"),
  26231                        unit, flags));
  26232             return (BCM_E_PARAM);
  26233         }
  26234     }
  26235 
  26236     /* read/modify/write range check memory */
  26237     SOC_IF_ERROR_RETURN(READ_FP_RANGE_CHECKm(unit, MEM_BLOCK_ANY,
  26238                                              range, &tbl_entry));
  26239 
  26240     soc_FP_RANGE_CHECKm_field32_set(unit, &tbl_entry,
  26241                                     SOURCE_DESTINATION_SELECTf, src_chk);
  26242     soc_FP_RANGE_CHECKm_field32_set(unit, &tbl_entry, ENABLEf, enable);
  26243     soc_FP_RANGE_CHECKm_field32_set(unit, &tbl_entry, LOWER_BOUNDSf, min);
  26244     soc_FP_RANGE_CHECKm_field32_set(unit, &tbl_entry, UPPER_BOUNDSf, max);
  26245 
  26246     SOC_IF_ERROR_RETURN(WRITE_FP_RANGE_CHECKm(unit, MEM_BLOCK_ALL,
  26247                                               range, &tbl_entry));
  26248 
  26249     return (BCM_E_NONE);
  26250 }
  26251 
  26252 /*
  26253  * Function:
  26254  *  _bcm_field_modify_range_checker
  26255  * Purpose:
  26256  *  Modify the configurations of an existing range checker.
  26257  * Parameters:
  26258  *  unit        - (IN) BCM device number.
  26259  *  stage_id    - (IN) Pipeline stage id.
  26260  *  range_id    - (IN) Range check ID to use.
  26261  *  flags       - (IN) Range checker type to be set.
  26262  *  min         - (IN) Lower bounds of range to be checked, inclusive.
  26263  *  max         - (IN) Upper bounds of range to be checked, inclusive.
  26264  * Returns:
  26265  *  BCM_E_NOT_FOUND - Range Check id to be modified does not exist.
  26266  *  BCM_E_NONE      - Success.
  26267  * Notes:
  26268  *    Calling function should have unit's lock.
  26269  */
  26270 
  26271 int _bcm_field_modify_range_checker(int unit, _field_stage_id_t stage_id,
  26272         int range_id, uint32 flags,
  26273         bcm_l4_port_t min, bcm_l4_port_t max)
  26274 {
  26275     _field_stage_t      *stage_fc;      /* Stage field control info.*/
  26276     _field_range_t      *fr;            /* Field range info.        */
  26277     int                 rv;             /* Operation return value.  */
  26278 
  26279     rv = _field_stage_control_get(unit, stage_id, &stage_fc);
  26280     if (BCM_FAILURE(rv)) {
  26281         return rv;
  26282     }
  26283 
  26284     for (fr = stage_fc->ranges; fr != NULL; fr = fr->next) {
  26285         if (fr->rid == range_id) {
  26286             /* Try to program hardware */
  26287 #if defined(BCM_TRX_SUPPORT)
  26288             if (SOC_IS_TRX(unit)) {
  26289                 rv = _bcm_field_trx_range_check_set(unit, fr->hw_index,
  26290                         flags, 1, min, max);
  26291             } else
  26292 #endif /* BCM_TRX_SUPPORT */
  26293             {
  26294                 rv = _field_fb_er_range_check_set(unit, fr->hw_index,
  26295                         flags, 1, min, max);
  26296             }
  26297             return rv;
  26298         }
  26299     }
  26300 
  26301     return BCM_E_NOT_FOUND;
  26302 }
  26303 
  26304 /*
  26305  * Function: _field_fill_slice_array
  26306  *
  26307  * Purpose:
  26308  *      Based on GroupAutoExpansion Flags and MaxGroupSize
  26309  *      Fill the slice_array with slice ids.
  26310  *
  26311  * Parameters:
  26312  *     unit        - (IN) BCM device number
  26313  *     fg          - (IN) field group
  26314  *     slice_array - (INOUT) Array where the slice ids will be filled.
  26315  *
  26316  * Returns:
  26317  *     BCM_E_xxx
  26318  */
  26319 int _field_fill_slice_array (int unit, _field_group_t *fg, uint8 *slice_array)
  26320 {
  26321     _field_control_t *fc;             /* Field control structure. */
  26322     _field_stage_t   *stage_fc;       /* Field stage control.     */
  26323     int rv = 0;                       /* Operation return status. */
  26324     int slice_index = 0;              /* Slice Index */
  26325     uint8 idx = 0;                    /* Slice Index */
  26326     int8 autoexpand_hints_set = -1;   /* Check AutoExpansion Flag is set*/
  26327     uint16 small_slice_size = 0;      /* Small Slice Size */
  26328     uint8 prioritize_large_slice = 0; /* Prioritize large entries */
  26329     int remaining_entries = 0;        /* Remaining allowed entries in a group */
  26330 
  26331     if (NULL == slice_array) {
  26332         return BCM_E_PARAM;
  26333     }
  26334 
  26335     /* Get field control structure. */
  26336     rv = _field_control_get(unit, &fc);
  26337     BCM_IF_ERROR_RETURN(rv);
  26338 
  26339     /* Get stage field control structure. */
  26340     rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc);
  26341     BCM_IF_ERROR_RETURN(rv);
  26342 
  26343     /* AutoExpansion Hints Flags supported only for Ingress Stage */
  26344     if ((stage_fc->stage_id == _BCM_FIELD_STAGE_EGRESS)
  26345             || (stage_fc->stage_id == _BCM_FIELD_STAGE_LOOKUP)) {
  26346         return BCM_E_NONE;
  26347     }
  26348 
  26349     /* AutoExpansion Hints Flags supported only for Ingress Stage which
  26350      * has two slice types */
  26351     if (soc_feature(unit, soc_feature_field_ingress_two_slice_types) == 0) {
  26352         return BCM_E_NONE;
  26353     }
  26354 
  26355     /* If both autoexpansion hint flags specified or both not specified
  26356      * it means autoexpansion is not set */
  26357     if ((fg->flags & _FP_GROUP_AUTO_EXPAND_SMALL_SLICE)
  26358             && (fg->flags & _FP_GROUP_AUTO_EXPAND_LARGE_SLICE)) {
  26359         autoexpand_hints_set = 0;
  26360     }
  26361 
  26362     if (((fg->flags & _FP_GROUP_AUTO_EXPAND_SMALL_SLICE) == 0)
  26363             && ((fg->flags & _FP_GROUP_AUTO_EXPAND_LARGE_SLICE) == 0)) {
  26364         autoexpand_hints_set = 0;
  26365     }
  26366 
  26367     /* If AutoExpansion hints not set and maxGroupSize not specified
  26368      * Slice allocation will follow default pattern */
  26369     if ((autoexpand_hints_set == 0) && (fg->max_group_size == 0)) {
  26370         return BCM_E_NONE;
  26371     }
  26372 
  26373     for (slice_index = 0;
  26374             slice_index < stage_fc->tcam_slices; slice_index++) {
  26375         if (stage_fc->slices[fg->instance][slice_index].slice_flags &
  26376                 _BCM_FIELD_SLICE_SIZE_SMALL) {
  26377             small_slice_size  =
  26378                   stage_fc->slices[fg->instance][slice_index].entry_count;
  26379             break;
  26380         }
  26381     }
  26382 
  26383     if (autoexpand_hints_set == 0) {
  26384         remaining_entries = fg->max_group_size - (fg->group_status.entry_count);
  26385         if (remaining_entries <= 0) {
  26386             /* Falling back to default slice allocation pattern */
  26387             return BCM_E_NONE;
  26388         } else {
  26389             if (remaining_entries <= small_slice_size) {
  26390                 prioritize_large_slice = 0;
  26391             } else {
  26392                 prioritize_large_slice = 1;
  26393             }
  26394         }
  26395     } else if (fg->flags & _FP_GROUP_AUTO_EXPAND_SMALL_SLICE) {
  26396         prioritize_large_slice = 0;
  26397     }else if (fg->flags & _FP_GROUP_AUTO_EXPAND_LARGE_SLICE) {
  26398         prioritize_large_slice = 1;
  26399     }
  26400 
  26401     if (prioritize_large_slice) {
  26402         while (idx < stage_fc->tcam_slices) {
  26403             for (slice_index = 0;
  26404                     slice_index < stage_fc->tcam_slices; slice_index++) {
  26405                 if (stage_fc->slices[fg->instance][slice_index].slice_flags &
  26406                         _BCM_FIELD_SLICE_SIZE_LARGE) {
  26407                     slice_array[idx] = slice_index;
  26408                     idx++;
  26409                 }
  26410             }
  26411             for (slice_index = 0;
  26412                     slice_index < stage_fc->tcam_slices; slice_index++) {
  26413                 if (stage_fc->slices[fg->instance][slice_index].slice_flags &
  26414                         _BCM_FIELD_SLICE_SIZE_SMALL) {
  26415                     slice_array[idx] = slice_index;
  26416                     idx++;
  26417                 }
  26418             }
  26419         }
  26420     } else {
  26421         while (idx < stage_fc->tcam_slices) {
  26422             for (slice_index = 0;
  26423                     slice_index < stage_fc->tcam_slices; slice_index++) {
  26424                 if (stage_fc->slices[fg->instance][slice_index].slice_flags &
  26425                         _BCM_FIELD_SLICE_SIZE_SMALL) {
  26426                     slice_array[idx] = slice_index;
  26427                     idx++;
  26428                 }
  26429             }
  26430             for (slice_index = 0;
  26431                     slice_index < stage_fc->tcam_slices; slice_index++) {
  26432                 if (stage_fc->slices[fg->instance][slice_index].slice_flags &
  26433                         _BCM_FIELD_SLICE_SIZE_LARGE) {
  26434                     slice_array[idx] = slice_index;
  26435                     idx++;
  26436                 }
  26437             }
  26438         }
  26439     }
  26440 
  26441     return BCM_E_NONE;
  26442 }
  26443 
  26444 /*
  26445  * Function: _field_find_empty_slice
  26446  *
  26447  * Purpose:
  26448  *     Get a new slice for an existing group if available.
  26449  *     Used for auto-expansion of groups
  26450  *     Currently: supported in Raptor, Firebolt2.
  26451  *
  26452  * Parameters:
  26453  *     unit  - BCM device number
  26454  *     fg - field group
  26455  *     fs_ptr - _field_slice_t for the PRIMARY if there is one available.
  26456  *
  26457  * Returns:
  26458  *     BCM_E_xxx
  26459  *
  26460  * Notes:
  26461  *     Need to change the array size (16) for devices which support
  26462  *     more slices, and correspondingly change the map arrays in
  26463  *     bcm_int/esw/field.h
  26464  */
  26465 STATIC int
  26466 _field_find_empty_slice(int unit, _field_group_t *fg, _field_slice_t **fs_ptr)
  26467 {
  26468     _field_control_t *fc;          /* Field control structure. */
  26469     _field_stage_t   *stage_fc;    /* Field stage control.     */
  26470     _field_slice_t   *fs;          /* Field slice pointer.     */
  26471     uint8 slice_number;            /* Slice iterator.          */
  26472     int parts_count = 0;           /* Number of entry parts.   */
  26473     uint32 entry_flags;            /* Field entry part flags.  */
  26474     int rv;                        /* Operation return status. */
  26475     int part_index;                /* Tcam Part Index */
  26476     int slice_index;               /* Slice Index */
  26477     uint8 old_physical_slice;      /* Last slice in group.     */
  26478     uint8 new_physical_slice;      /* Allocated slice.         */
  26479     bcm_pbmp_t all_pbmp;           /* Port bitmap */
  26480     uint8  *slice_array = NULL;    /* Array containing slice ids */
  26481     int  virtual_priority = FALSE;/* Virtual priority support flag.*/
  26482 
  26483     /* Get field control structure. */
  26484     rv = _field_control_get(unit, &fc);
  26485     BCM_IF_ERROR_RETURN(rv);
  26486 
  26487     BCM_PBMP_CLEAR(all_pbmp);
  26488     BCM_IF_ERROR_RETURN(_bcm_field_valid_pbmp_get(unit, &all_pbmp));
  26489 
  26490     /* Get stage field control structure. */
  26491     rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc);
  26492     BCM_IF_ERROR_RETURN(rv);
  26493 
  26494     if (0 == (stage_fc->flags & _FP_STAGE_AUTO_EXPANSION)) {
  26495         return (BCM_E_RESOURCE);
  26496     }
  26497 
  26498     fs = &fg->slices[0];
  26499     while (fs->next != NULL) {
  26500         fs = fs->next;
  26501     }
  26502     old_physical_slice = fs->slice_number;
  26503 
  26504     _FP_XGS3_ALLOC(slice_array, sizeof(uint8) * stage_fc->tcam_slices,
  26505                       "Slice Array");
  26506     if (NULL == slice_array) {
  26507         return BCM_E_MEMORY;
  26508     }
  26509 
  26510     for (slice_index = 0; slice_index < stage_fc->tcam_slices; slice_index++) {
  26511         slice_array[slice_index] = slice_index;
  26512     }
  26513 
  26514     rv = _field_fill_slice_array (unit, fg, slice_array);
  26515     if (rv != BCM_E_NONE) {
  26516         sal_free (slice_array);
  26517         slice_array = NULL;
  26518         return rv;
  26519     }
  26520 
  26521     /*
  26522      * Find an empty slice
  26523      * Validate the ports and mode
  26524      */
  26525     for (slice_index = 0; slice_index < stage_fc->tcam_slices; slice_index++) {
  26526         if (slice_index == old_physical_slice) {
  26527            continue;
  26528         }
  26529         rv = _field_group_ports_validate(unit, stage_fc, fg->instance,
  26530                                          slice_array[slice_index],
  26531                                          fg->flags, all_pbmp);
  26532         if (BCM_SUCCESS(rv)) {
  26533             break;
  26534         }
  26535     }
  26536 
  26537     if (slice_index == stage_fc->tcam_slices) {
  26538         /* No free slice; attempt to compress existing auto expanded  groups. */
  26539         rv = _field_stage_groups_compress(unit, fc, stage_fc);
  26540         if (rv != BCM_E_NONE) {
  26541             sal_free (slice_array);
  26542             slice_array = NULL;
  26543             return rv;
  26544         }
  26545 
  26546         /* Retry slice allocation. */
  26547         for (slice_index = 0; slice_index < stage_fc->tcam_slices;
  26548              slice_index++) {
  26549             rv = _field_group_ports_validate(unit, stage_fc, fg->instance,
  26550                                              slice_array[slice_index], fg->flags,
  26551                                              all_pbmp);
  26552             if (BCM_SUCCESS(rv)) {
  26553                 break;
  26554             }
  26555         }
  26556     }
  26557 
  26558     if (slice_index == stage_fc->tcam_slices)
  26559     {
  26560         /* No free slice */
  26561         sal_free (slice_array);
  26562         slice_array = NULL;
  26563         return (BCM_E_RESOURCE);
  26564     }
  26565 
  26566     new_physical_slice = slice_array[slice_index];
  26567     sal_free (slice_array);
  26568     slice_array = NULL;
  26569 
  26570     _field_virtual_priority_support(unit, stage_fc, &virtual_priority);
  26571 
  26572     /* Remove original group from the map. */
  26573     if (virtual_priority) {
  26574         rv = _field_group_vmap_delete(unit, stage_fc, fg, FALSE);
  26575         BCM_IF_ERROR_RETURN(rv);
  26576     }
  26577 
  26578     /* Get number of entry parts for the group. */
  26579     rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id, fg->flags, &parts_count);
  26580     BCM_IF_ERROR_RETURN(rv);
  26581 
  26582 
  26583     /* Set up the new physical slice parameters in Software */
  26584     for(part_index = parts_count - 1; part_index >= 0; part_index--) {
  26585         /* Get entry flags. */
  26586         rv = _bcm_field_tcam_part_to_entry_flags(unit, part_index, fg,
  26587                                                  &entry_flags);
  26588         BCM_IF_ERROR_RETURN(rv);
  26589 
  26590         /* Get slice id for entry part */
  26591         rv = _bcm_field_tcam_part_to_slice_number(unit, part_index, fg,
  26592                                                   &slice_number);
  26593         BCM_IF_ERROR_RETURN(rv);
  26594 
  26595         /* Get slice pointer. */
  26596         fs = stage_fc->slices[fg->instance] + new_physical_slice
  26597                 + slice_number;
  26598 
  26599         /* Enable slice. */
  26600         if (0 == (entry_flags & _FP_ENTRY_SECOND_HALF)) {
  26601             BCM_IF_ERROR_RETURN
  26602                 (_field_slice_enable_set(unit, stage_fc, fg, fs, 1));
  26603 
  26604             /* Set per slice configuration & number of free entries in the slice.*/
  26605             fs->free_count = fs->entry_count;
  26606             if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
  26607                 fs->free_count >>= 1;
  26608             }
  26609             /* Set group flags in in slice.*/
  26610             fs->group_flags = fg->flags & _FP_GROUP_STATUS_MASK;
  26611 
  26612             /* Add slice to slices linked list . */
  26613             stage_fc->slices[fg->instance][old_physical_slice + slice_number].
  26614                 next = fs;
  26615             fs->prev =
  26616              &stage_fc->slices[fg->instance][old_physical_slice + slice_number];
  26617             BCM_PBMP_OR(fs->pbmp, fg->pbmp);
  26618         }
  26619 
  26620         rv = fc->functions.fp_selcodes_install(unit, fg,
  26621                                               new_physical_slice + slice_number,
  26622                                               fs->pbmp, part_index);
  26623         BCM_IF_ERROR_RETURN(rv);
  26624 
  26625         rv = _bcm_field_group_selcode_initialize(unit,
  26626                               fg, fs, part_index);
  26627         BCM_IF_ERROR_RETURN(rv);
  26628     }
  26629 
  26630     /* Reinstall group virtual map . */
  26631     if (virtual_priority) {
  26632         BCM_IF_ERROR_RETURN (_field_group_vmap_add(unit, stage_fc, fg));
  26633     }
  26634 
  26635     *fs_ptr = stage_fc->slices[fg->instance] + new_physical_slice;
  26636     return (BCM_E_NONE);
  26637 }
  26638 
  26639 /*
  26640  * Function: _field_per_port_group_install_selcodes
  26641  *
  26642  * Purpose:
  26643  *      This is called to install the selcodes for a per port
  26644  *      group. This should be called only for the autoexpanded slice during
  26645  *      autoexpansion.
  26646  * Parameters:
  26647  *     unit  - (IN) BCM device number.
  26648  *     fg    - (IN) Field group.
  26649  *     fs    - (IN) Slice pointer.
  26650  * Returns:
  26651  *     BCM_E_XXX
  26652  */
  26653 STATIC int
  26654 _field_per_port_group_install_selcodes(int unit, _field_group_t *fg,
  26655                                         _field_slice_t *fs)
  26656 {
  26657     _field_control_t   *fc;             /* Field control structure.           */
  26658     _field_stage_t     *stage_fc;       /* Field stage control.               */
  26659     uint32              entry_flags;    /* Field entry part flags.            */
  26660     uint8               new_physical_slice;
  26661                                         /* Allocated slice.                   */
  26662     uint8               slice_number = 0;
  26663                                         /* Slice index based on the TCAM parts*/
  26664     int                 part_index = 0; /* TCAM parts index                   */
  26665     int                 rv = 0;         /* Operation return status            */
  26666     int                 parts_count = 0;
  26667                                         /* Number of entry parts.             */
  26668 
  26669     /* Get field control structure. */
  26670     rv = _field_control_get(unit, &fc);
  26671     BCM_IF_ERROR_RETURN(rv);
  26672 
  26673 
  26674     /* Get stage field control structure. */
  26675     rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc);
  26676     BCM_IF_ERROR_RETURN(rv);
  26677 
  26678     new_physical_slice = fs->slice_number;
  26679 
  26680     /*
  26681      * Add the selcodes. This case occurs when the slice contains some entries
  26682      * from another group and a new entry is to be added in this slice for this
  26683      * group. This scenario is for the group with port modes and so, no need
  26684      * to update the virtual slice priority.
  26685      *
  26686      * Get number of entry parts for the group.
  26687      */
  26688     rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
  26689                                             fg->flags, &parts_count);
  26690     BCM_IF_ERROR_RETURN(rv);
  26691 
  26692     /* Set up the new physical slice parameters in Software */
  26693     for(part_index = parts_count - 1; part_index >= 0; part_index--) {
  26694         /* Get entry flags. */
  26695         rv = _bcm_field_tcam_part_to_entry_flags(unit, part_index, fg,
  26696                                                  &entry_flags);
  26697         BCM_IF_ERROR_RETURN(rv);
  26698 
  26699         /* Get slice id for entry part */
  26700         rv = _bcm_field_tcam_part_to_slice_number(unit, part_index, fg,
  26701                                                   &slice_number);
  26702         BCM_IF_ERROR_RETURN(rv);
  26703 
  26704         fs = stage_fc->slices[fg->instance] + new_physical_slice
  26705                 + slice_number;
  26706 
  26707         /* Enable slice. */
  26708         if (0 == (entry_flags & _FP_ENTRY_SECOND_HALF)) {
  26709             /* Set group flags in in slice.*/
  26710             fs->group_flags |= fg->flags & _FP_GROUP_STATUS_MASK;
  26711 
  26712             BCM_PBMP_OR(fs->pbmp, fg->pbmp);
  26713         }
  26714 
  26715         rv = fc->functions.fp_selcodes_install(unit, fg,
  26716                                                new_physical_slice +
  26717                                                slice_number,
  26718                                                fg->pbmp, part_index);
  26719         BCM_IF_ERROR_RETURN(rv);
  26720     }
  26721 
  26722     return (BCM_E_NONE);
  26723 }
  26724 
  26725 /*
  26726  * Function: _field_group_check_and_install_selcodes
  26727  *
  26728  * Purpose:
  26729  *      Check if this is the first entry for the group
  26730  *      in the given slice. If this is the first entry
  26731  *      install the selcodes for the group in this slice
  26732  *      This function is called when the slice is not empty
  26733  * Parameters:
  26734  *     unit  - (IN) BCM device number.
  26735  *     fg    - (IN) Field group.
  26736  *     fs    - (IN) Slice pointer.
  26737  * Returns:
  26738  *     BCM_E_XXX
  26739  */
  26740 STATIC int
  26741 _field_group_check_and_install_selcodes(int unit, _field_group_t *fg,
  26742                                         _field_slice_t *fs)
  26743 {
  26744     _field_control_t   *fc;             /* Field control structure.           */
  26745     _field_stage_t     *stage_fc;       /* Field stage control.               */
  26746     uint32              entry_flags;    /* Field entry part flags.            */
  26747     uint8               new_physical_slice;
  26748                                         /* Allocated slice.                   */
  26749     uint8               slice_number = 0;
  26750                                         /* Slice index based on the TCAM parts*/
  26751     int                 idx = 0;        /* Index to iter the entries in slice */
  26752     int                 part_index = 0; /* TCAM parts index                   */
  26753     int                 rv = 0;         /* Operation return status            */
  26754     int                 parts_count = 0;
  26755                                         /* Number of entry parts.             */
  26756 
  26757     /* Input parameters check. */
  26758     if ((NULL == fg) || (NULL == fs)) {
  26759         return (BCM_E_PARAM);
  26760     }
  26761 
  26762     /* Get field control structure. */
  26763     rv = _field_control_get(unit, &fc);
  26764     BCM_IF_ERROR_RETURN(rv);
  26765 
  26766     /* If the slice is empty, then return BCM_E_NONE */
  26767     if (fs->free_count == fs->entry_count) {
  26768         return (BCM_E_NONE);
  26769     }
  26770 
  26771     /*
  26772      * Scan through all the entries in the slice and check if any
  26773      * entry belongs to the given group. If any entry belongs to
  26774      * this group, then return. Else, install the selcodes for the
  26775      * group
  26776      */
  26777     for (idx = 0; idx < fs->entry_count; idx++) {
  26778         if ((NULL != fs->entries[idx]) &&
  26779             (NULL != fs->entries[idx]->group) &&
  26780             (fs->entries[idx]->group->gid == fg->gid)) {
  26781             break;
  26782         }
  26783     }
  26784 
  26785     if (idx != fs->entry_count) {
  26786         /*
  26787          * This means that there is an entry in the slice belonging
  26788          * to the same group. So, no need to install the selcodes
  26789          */
  26790         return (BCM_E_NONE);
  26791     }
  26792 
  26793     /* Get stage field control structure. */
  26794     rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc);
  26795     BCM_IF_ERROR_RETURN(rv);
  26796 
  26797     new_physical_slice = fs->slice_number;
  26798 
  26799     /*
  26800      * Add the selcodes. This case occurs when the slice contains some entries
  26801      * from another group and a new entry is to be added in this slice for this
  26802      * group. This scenario is for the group with port modes and so, no need
  26803      * to update the virtual slice priority.
  26804      *
  26805      * Get number of entry parts for the group.
  26806      */
  26807     rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
  26808                                             fg->flags, &parts_count);
  26809     BCM_IF_ERROR_RETURN(rv);
  26810 
  26811     /* Set up the new physical slice parameters in Software */
  26812     for(part_index = parts_count - 1; part_index >= 0; part_index--) {
  26813         /* Get entry flags. */
  26814         rv = _bcm_field_tcam_part_to_entry_flags(unit, part_index, fg,
  26815                                                  &entry_flags);
  26816         BCM_IF_ERROR_RETURN(rv);
  26817 
  26818         /* Get slice id for entry part */
  26819         rv = _bcm_field_tcam_part_to_slice_number(unit, part_index, fg,
  26820                                                   &slice_number);
  26821         BCM_IF_ERROR_RETURN(rv);
  26822 
  26823         fs = stage_fc->slices[fg->instance] + new_physical_slice
  26824                 + slice_number;
  26825 
  26826         /* Enable slice. */
  26827         if (0 == (entry_flags & _FP_ENTRY_SECOND_HALF)) {
  26828             /* Set group flags in in slice.*/
  26829             fs->group_flags |= fg->flags & _FP_GROUP_STATUS_MASK;
  26830 
  26831             BCM_PBMP_OR(fs->pbmp, fg->pbmp);
  26832         }
  26833 
  26834         rv = fc->functions.fp_selcodes_install(unit, fg,
  26835                                                new_physical_slice +
  26836                                                slice_number,
  26837                                                fg->pbmp, part_index);
  26838         BCM_IF_ERROR_RETURN(rv);
  26839     }
  26840 
  26841     return (BCM_E_NONE);
  26842 }
  26843 
  26844 STATIC int _field_group_is_policer_attached(int unit,
  26845                                  _field_group_t *fg,
  26846                                  int *is_pol_attached) {
  26847     int idx, pidx;
  26848     _field_entry_t  *f_ent; /* Field entry info */
  26849     bcm_policer_t   policer_id;  /* Policer id. */
  26850     int rv;
  26851     *is_pol_attached = 0;
  26852 
  26853     if (NULL == fg) {
  26854         return (BCM_E_PARAM);
  26855     }
  26856     /*loop throught he entries of the group */
  26857     for (idx = 0; idx < fg->group_status.entry_count; idx++) {
  26858         f_ent = fg->entry_arr[idx];
  26859         /* check if entry has a policer attached */
  26860         if(f_ent != NULL) {
  26861             for (pidx = 0; pidx < _FP_POLICER_LEVEL_COUNT; pidx++) {
  26862                /* Read policer id from entry. */
  26863                 rv = bcm_esw_field_entry_policer_get(unit, f_ent->eid,
  26864                                              pidx, &policer_id);
  26865                 if (BCM_E_NOT_FOUND == rv) {
  26866                     continue;
  26867                 }
  26868                 if (!BCM_FAILURE(rv)) {
  26869                     *is_pol_attached = 1;
  26870                     return BCM_E_NONE;
  26871                 } else {
  26872                     return rv;
  26873                 }
  26874             }
  26875         }
  26876     }
  26877     return BCM_E_NONE;
  26878 }
  26879 
  26880 /*
  26881  * Function: _field_group_slice_entry_reserve
  26882  *
  26883  * Purpose:
  26884  *      Find a slice attached to a group which has a room
  26885  *      to insert a new entry.
  26886  * Parameters:
  26887  *     unit  - (IN) BCM device number.
  26888  *     fg    - (IN/OUT) Field group.
  26889  *     fs    - (OUT) Slice pointer or NULL.
  26890  * Returns:
  26891  *     BCM_E_XXX
  26892  */
  26893 STATIC int
  26894 _field_group_slice_entry_reserve(int unit, _field_group_t *fg,
  26895                                  _field_slice_t **fs)
  26896 {
  26897     _field_slice_t  *slice;        /* Slice iteration count.           */
  26898     int             free_entry_cnt;/* Free entries in slice count.     */
  26899     _field_stage_t  *stage_fc;     /* Stage field control info.        */
  26900     int is_pol_attached;
  26901     int rv;
  26902     _field_group_t *curr_group;
  26903     _field_control_t  *fc;
  26904     bcm_field_group_mode_t mode1 = 0;
  26905     bcm_field_group_mode_t mode2 = 0;
  26906     uint32 state = 0;
  26907 
  26908 
  26909     /* Input parameters check. */
  26910     if ((NULL == fg) || (NULL == fs)) {
  26911         return (BCM_E_PARAM);
  26912     }
  26913 
  26914     /* Find an empty spot in one of the groups slices.  */
  26915     slice = &fg->slices[0];
  26916     while (slice->next != NULL) {
  26917         slice = slice->next; /* Start from the last slice */
  26918     }
  26919 
  26920     while (slice != NULL) {
  26921 #if defined(BCM_TOMAHAWK_SUPPORT)
  26922         if (fg->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) {
  26923             BCM_IF_ERROR_RETURN
  26924                 (_field_th_em_entries_free_get(unit, fg,
  26925                                                &free_entry_cnt));
  26926         } else
  26927 #endif /* BCM_TOMAHAWK_SUPPORT */
  26928         {
  26929             BCM_IF_ERROR_RETURN
  26930                 (_bcm_field_entries_free_get(unit, slice, fg,
  26931                                              &free_entry_cnt));
  26932         }
  26933         if (free_entry_cnt) {
  26934             break;
  26935         }
  26936         slice = slice->prev;
  26937     }
  26938 
  26939     /*
  26940      * If there is no room in existing group slices try to allocate a new one.
  26941      * Find a feasible empty slice for auto-expand
  26942      * Set these slices in the same virtual group
  26943      */
  26944     if (slice == NULL) {
  26945         /* Need to check if you need to allocate a new slice */
  26946         if (!(fg->flags & _FP_GROUP_SELECT_AUTO_EXPANSION)) {
  26947             return (BCM_E_RESOURCE);
  26948         }
  26949 
  26950         /*
  26951          * Auto expansion is not allowed if a policer a policer is attached
  26952          * to an entry in the group which doesnot support global pools
  26953          */
  26954         rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc);
  26955         if (BCM_FAILURE(rv)) {
  26956             LOG_ERROR(BSL_LS_BCM_FP,
  26957                  (BSL_META_U(unit,
  26958                   "FP(unit %d) Error: Stage (%d) control get failure.\n"),
  26959                   unit, fg->stage_id));
  26960             return (rv);
  26961         }
  26962         if (!(stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS))  {
  26963             is_pol_attached = 0;
  26964             BCM_IF_ERROR_RETURN(_field_group_is_policer_attached(
  26965                                   unit, fg, &is_pol_attached));
  26966            if(is_pol_attached) {
  26967                if ((fg->stage_id == _BCM_FIELD_STAGE_EGRESS) &&
  26968                    (SOC_IS_TRIDENT2PLUS(unit))) {
  26969                    BCM_IF_ERROR_RETURN(bcm_esw_field_control_get(
  26970                        unit, bcmFieldControlEgressAutoExpandWithPolicer,
  26971                        &state));
  26972                    if (state == 0) {
  26973                        return BCM_E_RESOURCE;
  26974                    }
  26975                } else {
  26976                    return BCM_E_RESOURCE;
  26977                }
  26978            }
  26979         }
  26980 
  26981 #if defined(BCM_TOMAHAWK_SUPPORT)
  26982         if (soc_feature(unit, soc_feature_field_multi_pipe_support)
  26983              && (fg->stage_id == _BCM_FIELD_STAGE_INGRESS)) {
  26984            BCM_IF_ERROR_RETURN
  26985                 (_bcm_field_th_find_empty_slice(unit, fg, &slice));
  26986         } else
  26987 #endif /* BCM_TOMAHAWK_SUPPORT */
  26988         {
  26989            BCM_IF_ERROR_RETURN(_field_find_empty_slice(unit, fg, &slice));
  26990         }
  26991 
  26992         BCM_IF_ERROR_RETURN
  26993             (_bcm_field_entries_free_get(unit, slice, fg, &free_entry_cnt));
  26994 
  26995         if (0 == free_entry_cnt) {
  26996             LOG_ERROR(BSL_LS_BCM_FP,
  26997                       (BSL_META_U(unit,
  26998                        "FP(unit %d) Error: No entries free in slice.\n"),
  26999                        unit));
  27000             return (BCM_E_RESOURCE);
  27001         }
  27002         /* for perport groups, the selcodes should be
  27003          * installed for all the groups with same prioirty and mode*/
  27004 
  27005         if ((fg->flags & _FP_GROUP_PER_PORT_OR_PBMP) &&
  27006             (fg->priority != BCM_FIELD_GROUP_PRIO_ANY)) {
  27007             /* Get device Field control structure. */
  27008             BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  27009             curr_group = fc->groups;
  27010 
  27011             if (curr_group == NULL) {
  27012                 return BCM_E_NONE;
  27013             }
  27014             while (curr_group != NULL) {
  27015                 if ((curr_group->stage_id == fg->stage_id) &&
  27016                     (curr_group->gid != fg->gid) &&
  27017                     (curr_group->flags & _FP_GROUP_PER_PORT_OR_PBMP) &&
  27018                     (curr_group->priority == fg->priority)) {
  27019                     _bcm_esw_field_group_mode_get(curr_group->flags, &mode1);
  27020                     _bcm_esw_field_group_mode_get(fg->flags, &mode2);
  27021                     if( (mode1 == mode2) ){
  27022                         /* install selcodes of this gorup in the slice */
  27023                        BCM_IF_ERROR_RETURN(
  27024                            _field_per_port_group_install_selcodes(unit,
  27025                                                                   curr_group,
  27026                                                                   slice));
  27027                     }
  27028                 }
  27029                 curr_group = curr_group->next;
  27030             }
  27031         }
  27032 
  27033     } else {
  27034         BCM_IF_ERROR_RETURN
  27035             (_field_group_check_and_install_selcodes(unit, fg, slice));
  27036     }
  27037     *fs = slice;
  27038     return (BCM_E_NONE);
  27039 }
  27040 
  27041 /*
  27042  * Function:
  27043  *     _field_entry_actions_free
  27044  * Purpose:
  27045  *     Free and deinitialize field entry actions linked list
  27046  * Parameters:
  27047  *     f_ent       - (IN/OUT) Field entry with actions.
  27048  *     color_only  - (IN) Color based actions only.
  27049  *
  27050  * Returns:
  27051  *     BCM_E_MEMORY - allocation failure
  27052  *     BCM_E_NONE   - Success
  27053  */
  27054 STATIC int
  27055 _field_entry_actions_free (int unit, _field_entry_t *f_ent, int color_only)
  27056 {
  27057     _field_action_t *fa;        /* Action structure pointer. */
  27058     _field_action_t *fa_prev;   /* Action structure pointer. */
  27059 
  27060     /* Input parameters check.*/
  27061     if (NULL == f_ent) {
  27062         return (BCM_E_PARAM);
  27063     }
  27064 
  27065     fa_prev = fa = f_ent->actions;
  27066 
  27067     /* Free actions from the entry. */
  27068     while (fa != NULL) {
  27069         if (color_only && (!_FP_ACTION_IS_COLOR_BASED(fa->action))) {
  27070             fa_prev = fa;
  27071             fa = fa->next;
  27072             continue;
  27073         }
  27074 
  27075         /* Head entry deletion. */
  27076         if (fa == f_ent->actions) {
  27077             f_ent->actions = fa->next;
  27078 #if defined(BCM_TRIDENT3_SUPPORT)
  27079             if (fa->action == bcmFieldActionVlanActions) {
  27080                 if (f_ent->vlan_action_set) {
  27081                     sal_free(f_ent->vlan_action_set);
  27082                    f_ent->vlan_action_set = NULL;
  27083                 }
  27084             }
  27085 #endif
  27086             if (NULL != (fa->egress_pbmp)) {
  27087                 sal_free(fa->egress_pbmp);
  27088             }
  27089             sal_free(fa);
  27090             fa_prev = fa = f_ent->actions;
  27091         } else {
  27092             /* Middle/Tail entry deletion. */
  27093             fa_prev->next = fa->next;
  27094 #if defined(BCM_TRIDENT3_SUPPORT)
  27095             if (fa->action == bcmFieldActionVlanActions) {
  27096                 if (f_ent->vlan_action_set) {
  27097                     sal_free(f_ent->vlan_action_set);
  27098                    f_ent->vlan_action_set = NULL;
  27099                 }
  27100             }
  27101 #endif
  27102             if (NULL != (fa->egress_pbmp)) {
  27103                 sal_free(fa->egress_pbmp);
  27104             }
  27105             sal_free(fa);
  27106             fa = fa_prev->next;
  27107         }
  27108     }
  27109 
  27110     /* Destroy Oam related actions */
  27111 #if defined BCM_TRIDENT2PLUS_SUPPORT
  27112     if (soc_feature(unit, soc_feature_fp_based_oam)){
  27113         BCM_IF_ERROR_RETURN(_bcm_field_oam_stat_actions_destroy (unit,f_ent));
  27114     }
  27115 #endif
  27116 
  27117     return (BCM_E_NONE);
  27118 }
  27119 
  27120 /*
  27121  * Function:
  27122  *     _field_entry_phys_destroy
  27123  *
  27124  * Purpose:
  27125  *     Destroy a physical entry from a slice. Note that this does not remove
  27126  *     the entry from the hardware.
  27127  *
  27128  * Parameters:
  27129  *     unit      - BCM device number
  27130  *     fs        - slice that entry resides in
  27131  *     entry     - Entry ID to remove
  27132  *
  27133  * Returns:
  27134  *     BCM_E_NONE - Success
  27135  */
  27136 int
  27137 _field_entry_phys_destroy (int unit, _field_entry_t *f_ent)
  27138 {
  27139     _field_stage_t   *stage_fc;   /* Stage field control.            */
  27140     _field_group_t   *fg;         /* Field group structure.          */
  27141     _field_slice_t   *fs;         /* Field slice structure.          */
  27142     int              parts_count = 0; /* Entry parts count.              */
  27143     uint8            slice_number;/* Field entry part slice number.  */
  27144     int              idx;         /* Entry parts iterator.           */
  27145     int              rv;          /* Operation return status.        */
  27146 
  27147     if (NULL == f_ent) {
  27148         return (BCM_E_PARAM);
  27149     }
  27150 
  27151     fs = f_ent->fs;
  27152     fg = f_ent->group;
  27153 
  27154     /* Get field control structure. */
  27155 
  27156 
  27157     /* Get stage field control structure. */
  27158     rv = _field_stage_control_get(unit, fs->stage_id, &stage_fc);
  27159     BCM_IF_ERROR_RETURN(rv);
  27160 
  27161     /* Get number of entry parts we have to read. */
  27162     rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
  27163                                             fg->flags, &parts_count);
  27164     BCM_IF_ERROR_RETURN(rv);
  27165 
  27166     for (idx = 0; idx < parts_count; idx++) {
  27167         /* Destroy all actions from entry. */
  27168         rv = _field_entry_actions_free (unit, f_ent + idx, FALSE);
  27169         BCM_IF_ERROR_RETURN(rv);
  27170 
  27171         /* Free tcam image. */
  27172         if(NULL != f_ent[idx].tcam.key) {
  27173             sal_free(f_ent[idx].tcam.key);
  27174         }
  27175         if(NULL != f_ent[idx].tcam.mask) {
  27176             sal_free(f_ent[idx].tcam.mask);
  27177         }
  27178         if(NULL != f_ent[idx].tcam.key_hw) {
  27179             sal_free(f_ent[idx].tcam.key_hw);
  27180         }
  27181         if(NULL != f_ent[idx].tcam.mask_hw) {
  27182             sal_free(f_ent[idx].tcam.mask_hw);
  27183         }
  27184         if(NULL != f_ent[idx].extra_tcam.key) {
  27185             sal_free(f_ent[idx].extra_tcam.key);
  27186         }
  27187         if(NULL != f_ent[idx].extra_tcam.mask) {
  27188             sal_free(f_ent[idx].extra_tcam.mask);
  27189         }
  27190         if(NULL != f_ent[idx].extra_tcam.key_hw) {
  27191             sal_free(f_ent[idx].extra_tcam.key_hw);
  27192         }
  27193         if(NULL != f_ent[idx].extra_tcam.mask_hw) {
  27194             sal_free(f_ent[idx].extra_tcam.mask_hw);
  27195         }
  27196         if(NULL != f_ent[idx].key_match_tcam.key) {
  27197             sal_free(f_ent[idx].key_match_tcam.key);
  27198         }
  27199         if(NULL != f_ent[idx].key_match_tcam.mask) {
  27200             sal_free(f_ent[idx].key_match_tcam.mask);
  27201         }
  27202         if(NULL != f_ent[idx].key_match_tcam.key_hw) {
  27203             sal_free(f_ent[idx].key_match_tcam.key_hw);
  27204         }
  27205         if(NULL != f_ent[idx].key_match_tcam.mask_hw) {
  27206             sal_free(f_ent[idx].key_match_tcam.mask_hw);
  27207         }
  27208 
  27209         /* Get slice id for entry part */
  27210         rv = _bcm_field_tcam_part_to_slice_number(unit, idx, fg,
  27211                                                   &slice_number);
  27212         BCM_IF_ERROR_RETURN(rv);
  27213 
  27214         /* Remove entry pointer from the slice. */
  27215         if ((stage_fc->stage_id != _BCM_FIELD_STAGE_EXTERNAL) &&
  27216             (stage_fc->stage_id != _BCM_FIELD_STAGE_EXACTMATCH)) {
  27217             fs[slice_number].entries[f_ent[idx].slice_idx] = NULL;
  27218         }
  27219 
  27220         /* Increment slice unused entry count. */
  27221         if ((0 == (f_ent[idx].flags & _FP_ENTRY_SECOND_HALF)) ||
  27222             (f_ent[idx].flags & _FP_ENTRY_MODIFY_SLICE_SW_ENTRY_COUNT)) {
  27223             fs[slice_number].free_count++;
  27224         }
  27225     }
  27226 
  27227     /* Remove the entry from group entry array. */
  27228     rv = _field_group_entry_delete(unit, fg,  f_ent);
  27229     if (BCM_FAILURE(rv)) {
  27230         sal_free(f_ent);
  27231         return (rv);
  27232     }
  27233 
  27234     /* Free the entry */
  27235     sal_free(f_ent);
  27236 
  27237     return (BCM_E_NONE);
  27238 }
  27239 
  27240 /*
  27241  * Function:
  27242  *     _bcm_field_entry_part_tcam_idx_get
  27243  *
  27244  * Purpose:
  27245  *     Given primary entry slice/idx calculate
  27246  *     secondary/tertiary/second half slice/index.
  27247  *
  27248  * Parameters:
  27249  *     unit    - (IN) BCM device number.
  27250  *     f_ent   - (IN) Field entry pointer.
  27251  *     idx_pri - (IN) Primary entry tcam index.
  27252  *     ent_part    - (IN) Entry part id.
  27253  *     idx_out - (OUT) Entry part tcam index.
  27254  * Returns
  27255  *     BCM_E_XXX
  27256  */
  27257 int
  27258 _bcm_field_entry_part_tcam_idx_get(int unit, _field_entry_t *f_ent,
  27259                                    uint32 idx_pri, uint8 ent_part,
  27260                                    int *idx_out)
  27261 {
  27262     uint8            slice_number = 0;/* Primary entry slice number.    */
  27263     int              pri_slice = 0;   /* Primary entry slice number.    */
  27264     int              pri_index = 0;   /* Primary entry in slice index.  */
  27265     int              part_index;      /* Entry part slice index.        */
  27266     _field_stage_t   *stage_fc;       /* Stage field control.           */
  27267     _field_slice_t   *fs;             /* Field slice structure.         */
  27268     _field_group_t   *fg;             /* Field group structure.         */
  27269     int              rv;              /* Operation return status.       */
  27270 
  27271     /* Input parameters ceck. */
  27272     if ((NULL == f_ent) || (NULL == idx_out)) {
  27273         return (BCM_E_PARAM);
  27274     }
  27275 
  27276 #if defined(BCM_TOMAHAWK_SUPPORT)
  27277     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  27278         (f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS)) {
  27279        return _bcm_field_th_entry_part_tcam_idx_get(unit, f_ent, idx_pri,
  27280                                                     ent_part, idx_out);
  27281     }
  27282 #endif /* BCM_TOMAHAWK_SUPPORT */
  27283 
  27284     /* Primary entry index. */
  27285     if (0 == ent_part) {
  27286         *idx_out = idx_pri;
  27287         return (BCM_E_NONE);
  27288     }
  27289 
  27290     fg = f_ent->group;
  27291 
  27292     /* External tcam doesn't support wide entries. */
  27293     if (_BCM_FIELD_STAGE_EXTERNAL == fg->stage_id) {
  27294         return (BCM_E_INTERNAL);
  27295     }
  27296 
  27297     /* TCAM Entries are consecutive in DW_DEPTH_EXPANDED. */
  27298     if (fg->flags & _FP_GROUP_DW_DEPTH_EXPANDED) {
  27299         *idx_out = idx_pri + ent_part;
  27300         return (BCM_E_NONE);
  27301     }
  27302 
  27303     /* Get stage field control structure. */
  27304     rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc);
  27305     BCM_IF_ERROR_RETURN(rv);
  27306 
  27307     /* Get primary part entry index & slice. */
  27308     rv = _bcm_field_tcam_idx_to_slice_offset (unit, stage_fc, fg->instance,
  27309                                               idx_pri, &pri_slice,
  27310                                               &pri_index);
  27311     BCM_IF_ERROR_RETURN(rv);
  27312 
  27313     /* Get entry part slice number 0,1,2 */
  27314     rv = _bcm_field_tcam_part_to_slice_number(unit, ent_part, fg,
  27315                                               &slice_number);
  27316     BCM_IF_ERROR_RETURN(rv);
  27317 
  27318     /* Get slice description structure. */
  27319     fs = stage_fc->slices[fg->instance] + (pri_slice + slice_number);
  27320 
  27321     if (f_ent[ent_part].flags &  _FP_ENTRY_SECOND_HALF) {
  27322         part_index = pri_index + (fs->entry_count >> 1);
  27323     } else {
  27324         part_index = pri_index;
  27325     }
  27326 
  27327     rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc, fg->instance,
  27328                                              fs->slice_number, part_index,
  27329                                              idx_out);
  27330     return (rv);
  27331 }
  27332 
  27333 /*
  27334  * Function:
  27335  *     _field_entry_phys_create
  27336  *
  27337  * Purpose:
  27338  *     Initialize a physical entry structure.
  27339  *
  27340  * Parameters:
  27341  *     unit           - (IN) BCM device number.
  27342  *     stage_fc       - (IN) Stage field control structure.
  27343  *     entry          - (IN) Entry ID.
  27344  *     prio           - (IN) Priority relative to other entries in group.
  27345  *     fs             - (IN) Slice where entry resides.
  27346  *     fg             - (IN) Entry's group.
  27347  *     entry_p        - (OUT)Allocated & initialized entry.
  27348  *
  27349  * Returns
  27350  *     BCM_E_XXX
  27351  *
  27352  * Notes:
  27353  *     Assumes that for wide-mode, the same index within the slice
  27354  *     is assigned for the 2(3) slices.
  27355  */
  27356 STATIC int
  27357 _field_entry_phys_create(int unit, _field_stage_t *stage_fc,
  27358                          bcm_field_entry_t entry, int prio,
  27359                          _field_slice_t *fs, _field_group_t *fg,
  27360                          _field_entry_t **entry_p)
  27361 {
  27362     _field_control_t    *fc;          /* Field control structure.         */
  27363     int                 idx;          /* Slice entries iteration index.   */
  27364     int                 parts_count = 0;/* Number of entry parts.           */
  27365     int                 part_index;   /* Entry parts iterator.            */
  27366     int                 rv;           /* Operation return status.         */
  27367     int                 mem_sz;       /* Memory allocation size.          */
  27368     int                 slice_number = 0;/* Field entry part slice number.*/
  27369     _field_entry_t      *f_ent = NULL;/* Field entry structure.           */
  27370     int                 pri_tcam_idx = -1; /* Primary entry tcam index.   */
  27371 #if defined(BCM_TOMAHAWK_SUPPORT)
  27372     int                 free_count = 0;    /* Free entry count.           */
  27373 #endif /* BCM_TOMAHAWK_SUPPORT */
  27374 
  27375     LOG_DEBUG(BSL_LS_BCM_FP,
  27376               (BSL_META_U(unit,
  27377                "FP(unit %d): BEGIN "
  27378                "_field_entry_phys_create(entry=%d, prio=%d, gid=%d)\n"),
  27379                unit, entry, prio, fg->gid));
  27380 
  27381     if ((NULL == fs) || (NULL == fg) || (NULL == entry_p)) {
  27382         return (BCM_E_PARAM);
  27383     }
  27384 
  27385 #if defined(BCM_TOMAHAWK_SUPPORT)
  27386     if (fg->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) {
  27387         BCM_IF_ERROR_RETURN(_field_th_em_entries_free_get(unit, fg,
  27388                                                           &free_count));
  27389         /* Check if free entries are available in the UFT. */
  27390         if (0 == free_count) {
  27391             return (BCM_E_RESOURCE);
  27392         }
  27393     } else
  27394 #endif
  27395     {
  27396         /* Check if free entries are available in the slice. */
  27397         if (0 == fs->free_count) {
  27398             return (BCM_E_RESOURCE);
  27399         }
  27400     }
  27401 
  27402     /* Get field control structure. */
  27403     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  27404 
  27405     /* Get number of parts in field entry based on group flags. */
  27406     rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
  27407                                             fg->flags, &parts_count);
  27408     BCM_IF_ERROR_RETURN(rv);
  27409 
  27410     /* Allocate and zero memory for field entry. */
  27411     mem_sz = parts_count * sizeof (_field_entry_t);
  27412 
  27413     _FP_XGS3_ALLOC(f_ent, mem_sz, "field entry");
  27414     if (f_ent == NULL) {
  27415         LOG_ERROR(BSL_LS_BCM_FP,
  27416                   (BSL_META_U(unit,
  27417                     "FP(unit %d) Error: allocation failure for field_entry\n"),
  27418                     unit));
  27419         return (BCM_E_MEMORY);
  27420     }
  27421 
  27422     /* Initalize policer id as invalid for all policer levels. */
  27423     for (idx = 0; idx < _FP_POLICER_LEVEL_COUNT; idx++) {
  27424         f_ent->policer[idx].pid = _FP_INVALID_INDEX;
  27425     }
  27426 
  27427     rv = _bcm_field_slice_idx_allocate(unit, stage_fc,
  27428                 fg, fs, &(f_ent->slice_idx));
  27429     if (BCM_FAILURE(rv)) {
  27430         sal_free(f_ent);
  27431     }
  27432     if (f_ent->slice_idx != _FP_INVALID_INDEX) {
  27433         rv = _bcm_field_slice_offset_to_tcam_idx (unit, stage_fc,
  27434                 fg->instance,
  27435                 fs->slice_number,
  27436                 f_ent->slice_idx,
  27437                 &pri_tcam_idx);
  27438     }
  27439     if (BCM_FAILURE(rv)) {
  27440         sal_free(f_ent);
  27441     }
  27442 
  27443     for (idx = 0; idx < parts_count; idx++) {
  27444         /* Fill in entry primitives. */
  27445         f_ent[idx].eid          = entry;
  27446         f_ent[idx].prio         = prio;
  27447         f_ent[idx].group        = fg;
  27448         f_ent[idx].ent_copy     = NULL;
  27449         f_ent[idx].efp_key_match_type = _FP_ENTRY_TYPE_1;
  27450 
  27451         /* Get entry part flags. */
  27452         rv = _bcm_field_tcam_part_to_entry_flags(unit, idx, fg,
  27453                                                  &f_ent[idx].flags);
  27454         if (BCM_FAILURE(rv)) {
  27455             sal_free(f_ent);
  27456             return (rv);
  27457         }
  27458 
  27459         /* Enable color independent actions based on field control. */
  27460         if (fc->flags & _FP_COLOR_INDEPENDENT) {
  27461             f_ent[idx].flags |= _FP_ENTRY_COLOR_INDEPENDENT;
  27462         }
  27463 
  27464         /* Given primary entry tcam index calculate entry part tcam index. */
  27465         if (idx && ((_BCM_FIELD_STAGE_EXTERNAL != fg->stage_id) &&
  27466                     (_BCM_FIELD_STAGE_EXACTMATCH != fg->stage_id))) {
  27467             rv = _bcm_field_entry_part_tcam_idx_get(unit, f_ent, pri_tcam_idx,
  27468                                                     idx, &part_index);
  27469             if (BCM_FAILURE(rv)) {
  27470                 sal_free(f_ent);
  27471                 return (rv);
  27472             }
  27473 
  27474 #if defined(BCM_TOMAHAWK_SUPPORT)
  27475             if (soc_feature(unit, soc_feature_field_multi_pipe_support)
  27476                  && (fg->stage_id == _BCM_FIELD_STAGE_INGRESS)) {
  27477                 rv = _bcm_field_th_tcam_idx_to_slice_offset(unit, stage_fc,
  27478                                                   f_ent, part_index,
  27479                                                   &slice_number,
  27480                                                   (int *)&f_ent[idx].slice_idx);
  27481             } else
  27482 #endif /* BCM_TOMAHAWK_SUPPORT */
  27483             {
  27484                 rv = _bcm_field_tcam_idx_to_slice_offset (unit, stage_fc,
  27485                                                   fg->instance, part_index,
  27486                                                   &slice_number,
  27487                                                   (int *)&f_ent[idx].slice_idx);
  27488             }
  27489             if (BCM_FAILURE(rv)) {
  27490                 sal_free(f_ent);
  27491                 return (rv);
  27492             }
  27493             f_ent[idx].fs = stage_fc->slices[fg->instance] + slice_number;
  27494         } else {
  27495             /* Set entry slice. */
  27496             f_ent[idx].fs = fs;
  27497         }
  27498 
  27499         /* Mark entry dirty. */
  27500         f_ent[idx].flags |=  _FP_ENTRY_DIRTY;
  27501         f_ent[idx].flags |= _FP_ENTRY_CREATED_WITHOUT_PRIO;
  27502     }
  27503 
  27504     /* Insert the entry into group entry array. */
  27505     rv = _field_group_entry_add(unit, fg,  f_ent);
  27506     if (BCM_FAILURE(rv)) {
  27507         sal_free(f_ent);
  27508         return (rv);
  27509     }
  27510 
  27511     /* Update slice related parameters after succesful update */
  27512     for (idx = 0; idx < parts_count; idx++) {
  27513         /* Decrement slice free entry count. */
  27514         if ((0 == (f_ent[idx].flags & _FP_ENTRY_SECOND_HALF)) ||
  27515             (f_ent[idx].flags & _FP_ENTRY_MODIFY_SLICE_SW_ENTRY_COUNT)) {
  27516             f_ent[idx].fs->free_count--;
  27517         }
  27518 
  27519         /* Assign entry to a slice */
  27520         if ((fg->stage_id != _BCM_FIELD_STAGE_EXTERNAL) &&
  27521             (fg->stage_id != _BCM_FIELD_STAGE_EXACTMATCH)) {
  27522             f_ent[idx].fs->entries[f_ent[idx].slice_idx] = f_ent + idx;
  27523         }
  27524     }
  27525 
  27526     /* Return allocated/filled entry structure to the caller. */
  27527     *entry_p = f_ent;
  27528     return (BCM_E_NONE);
  27529 }
  27530 
  27531 /*
  27532  * Function:
  27533  *     _field_tcam_policy_external_reinstall
  27534  *
  27535  * Purpose:
  27536  *     Re-Install POLICY_TABLE entry. This writes the
  27537  *     actions to the hardware.
  27538  *
  27539  * Parameters:
  27540  *     unit      - (IN) BCM device number.
  27541  *     f_ent     - (IN) Entry to be installed.
  27542  *
  27543  * Returns:
  27544  *     BCM_E_INTERNAL  - Memory Read failure
  27545  *     BCM_E_UNAVAIL   - Device not supported
  27546  *     BCM_E_NONE      - Success
  27547  *
  27548  * Notes:
  27549  */
  27550 STATIC int
  27551 _field_tcam_policy_external_reinstall(int unit, _field_entry_t *f_ent)
  27552 {
  27553     _field_control_t    *fc;         /* Field control structure.  */
  27554     int                 rv;          /* Operation return status.  */
  27555 
  27556     /* Input parameters check. */
  27557     if (NULL == f_ent) {
  27558         return (BCM_E_PARAM);
  27559     }
  27560 
  27561     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  27562 
  27563     /* If not installed, and no qualifiers yet
  27564      *     i.e. installing empty entry for first time
  27565      */
  27566     if (0 == (f_ent->flags & _FP_ENTRY_INSTALLED)) {
  27567         BCM_IF_ERROR_RETURN (_bcm_field_qual_tcam_key_mask_get(unit, f_ent));
  27568     }
  27569 
  27570     /* Next copy S/W copy to H/W copy if required */
  27571     if(NULL != f_ent->tcam.key) {
  27572         sal_memcpy(f_ent->tcam.key_hw, f_ent->tcam.key,
  27573                    f_ent->tcam.key_size);
  27574         sal_free(f_ent->tcam.key);
  27575         f_ent->tcam.key = NULL;
  27576     }
  27577     if(NULL != f_ent->tcam.mask) {
  27578         sal_memcpy(f_ent->tcam.mask_hw, f_ent->tcam.mask,
  27579                    f_ent->tcam.key_size);
  27580         sal_free(f_ent->tcam.mask);
  27581         f_ent->tcam.mask = NULL;
  27582     }
  27583 
  27584     /* Then install the H/W copy into H/W */
  27585     rv = fc->functions.fp_external_entry_reinstall(unit, f_ent);
  27586 
  27587     if (rv == BCM_E_NONE) {
  27588         f_ent->flags &= ~_FP_ENTRY_DIRTY;
  27589         f_ent->flags &= ~(_FP_ENTRY_POLICY_TABLE_ONLY_DIRTY);
  27590     }
  27591     return (rv);
  27592 }
  27593 
  27594 /*
  27595  * Function:
  27596  *     _field_tcam_policy_external_install
  27597  *
  27598  * Purpose:
  27599  *     Install a combined TCAM and POLICY_TABLE entry. This writes the
  27600  *     qualifiers and actions to the hardware.
  27601  *
  27602  * Parameters:
  27603  *     unit      - (IN) BCM device number.
  27604  *     f_ent     - (IN) Entry to be installed.
  27605  *
  27606  * Returns:
  27607  *     BCM_E_INTERNAL  - Memory Read failure
  27608  *     BCM_E_UNAVAIL   - Device not supported
  27609  *     BCM_E_NONE      - Success
  27610  *
  27611  * Notes:
  27612  */
  27613 STATIC int
  27614 _field_tcam_policy_external_install(int unit, _field_entry_t *f_ent)
  27615 {
  27616     _field_control_t    *fc;         /* Field control structure.  */
  27617     int                 rv;          /* Operation return status.  */
  27618 
  27619 
  27620     /* Input parameters check. */
  27621     if (NULL == f_ent) {
  27622         return (BCM_E_PARAM);
  27623     }
  27624 
  27625     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  27626 
  27627     /* If not installed, and no qualifiers yet
  27628      *     i.e. installing empty entry for first time
  27629      */
  27630     if (0 == (f_ent->flags & _FP_ENTRY_INSTALLED)) {
  27631         BCM_IF_ERROR_RETURN (_bcm_field_qual_tcam_key_mask_get(unit, f_ent));
  27632     }
  27633 
  27634     /* Next copy S/W copy to H/W copy if required */
  27635     if(NULL != f_ent->tcam.key) {
  27636         sal_memcpy(f_ent->tcam.key_hw, f_ent->tcam.key,
  27637                    f_ent->tcam.key_size);
  27638         sal_free(f_ent->tcam.key);
  27639         f_ent->tcam.key = NULL;
  27640     }
  27641     if(NULL != f_ent->tcam.mask) {
  27642         sal_memcpy(f_ent->tcam.mask_hw, f_ent->tcam.mask,
  27643                    f_ent->tcam.key_size);
  27644         sal_free(f_ent->tcam.mask);
  27645         f_ent->tcam.mask = NULL;
  27646     }
  27647 
  27648     /* Then install the H/W copy into H/W */
  27649     rv = fc->functions.fp_external_entry_install(unit, f_ent);
  27650 
  27651     if (rv == BCM_E_NONE) {
  27652         f_ent->flags &= ~_FP_ENTRY_DIRTY;
  27653         f_ent->flags |= _FP_ENTRY_INSTALLED;
  27654         f_ent->flags |= _FP_ENTRY_ENABLED;
  27655     }
  27656     return (rv);
  27657 }
  27658 
  27659 #ifdef INCLUDE_L3
  27660 #if defined (BCM_TRIDENT2_SUPPORT) /* BCM_TRIDENT2_SUPPORT */
  27661 /*
  27662  * Function: _bcm_field_nat_actions_update
  27663  *
  27664  * Purpose: Update Egress Nat Reference Count for
  27665  * NatEgressOverride action.
  27666  *
  27667  * Parameters:
  27668  * unit      - (IN) Device number.
  27669  * f_ent     - (IN) Field entry.
  27670  * set       - (IN) Set or reset the Reference count
  27671  *                  based on action add/delete.
  27672  * Returns:
  27673  *      BCM_E_XXX
  27674  */
  27675 STATIC int
  27676 _bcm_field_nat_actions_update(int unit, _field_entry_t *f_ent,
  27677         int set)
  27678 {
  27679     _field_action_t *fa;            /* Field action descriptor. */
  27680 
  27681     /* Input parameters check. */
  27682     if (NULL == f_ent) {
  27683         return (BCM_E_PARAM);
  27684     }
  27685 
  27686     if ((_BCM_FIELD_STAGE_INGRESS != f_ent->group->stage_id) &&
  27687             (_BCM_FIELD_STAGE_EXACTMATCH != f_ent->group->stage_id)){
  27688         return (BCM_E_NONE);
  27689     }
  27690 
  27691     /* Extract the policy info from the entry structure. */
  27692     for (fa = f_ent->actions;
  27693          ((fa != NULL) && (_FP_ACTION_VALID & fa->flags));
  27694          fa = fa->next) {
  27695         if (fa->action != bcmFieldActionNatEgressOverride) {
  27696             continue;
  27697         }
  27698 
  27699         if (set) {
  27700             /* Action is added, increment reference count if not already done.*/
  27701             if ((_FP_ACTION_DIRTY & fa->flags) || SOC_WARM_BOOT(unit)) {
  27702                 BCM_IF_ERROR_RETURN(_bcm_esw_nat_egress_ref_count_update(unit, fa->param[0], 1));
  27703                 /* Setting hw_index to non-zero in order to handle fp action remove, fp action add
  27704                  * config sequence */
  27705                 fa->hw_index = 1;
  27706             }
  27707         }
  27708         else {
  27709             /* Action is deleted, decrement reference count if not already done.*/
  27710             if ((fa->flags & _FP_ACTION_DIRTY)) {
  27711                 continue;
  27712             }
  27713 
  27714             BCM_IF_ERROR_RETURN(_bcm_esw_nat_egress_ref_count_update(unit, fa->param[0], 0));
  27715             fa->hw_index = _FP_INVALID_INDEX;
  27716             fa->flags |= _FP_ACTION_DIRTY;
  27717         }
  27718     }
  27719     return BCM_E_NONE;
  27720 }
  27721 #endif /* BCM_TRIDENT2_SUPPORT */
  27722 
  27723 #if defined (BCM_KATANA_SUPPORT) || defined (BCM_TRIDENT_SUPPORT) \
  27724         || defined (BCM_TRIUMPH3_SUPPORT) || defined (BCM_GREYHOUND_SUPPORT) \
  27725         || defined (BCM_ENDURO_SUPPORT) \
  27726 
  27727 
  27728 /*
  27729  * Function:
  27730  *    _field_nh_ref_count_incr
  27731  *
  27732  * Purpose:
  27733  *     Increment next hop refCount for RedirectEgrNextHop and
  27734  *     L3Switch action.
  27735  *
  27736  * Parameters:
  27737  *     unit      - (IN) BCM device number.
  27738  *     f_ent     - (IN) Entry array
  27739  * Returns:
  27740  *     BCM_E_XXX
  27741  * Notes:
  27742  */
  27743 int
  27744 _field_nh_ref_count_incr (int unit, _field_entry_t *f_ent)
  27745 {
  27746     _field_action_t *fa = NULL;  /* Field action descriptor. */
  27747     uint32 flags;                /* L3 forwarding flags.    */
  27748     int nh_ecmp_id;              /* Next hop/Ecmp group id. */
  27749 
  27750     /* Extract action info from the entry structure. */
  27751     for (fa = f_ent->actions; ((fa != NULL) && (_FP_ACTION_VALID & fa->flags)
  27752                 && ((_FP_ACTION_DIRTY & fa->flags) || SOC_WARM_BOOT(unit)));
  27753             fa = fa->next) {
  27754         if ((fa->action != bcmFieldActionRedirectEgrNextHop)
  27755                 && (fa->action != bcmFieldActionL3Switch)) {
  27756             continue;
  27757         }
  27758 
  27759         BCM_IF_ERROR_RETURN(_bcm_field_policy_set_l3_nh_resolve (unit,
  27760                     fa->param[0], &flags, &nh_ecmp_id));
  27761 
  27762         BCM_IF_ERROR_RETURN(bcmi_esw_l3_egress_ref_count_update (unit,
  27763                     fa->param[0], flags, nh_ecmp_id,1));
  27764 
  27765         /* Setting hw_index to non-zero in order to handle fp action remove, fp action add
  27766          * config sequence */
  27767         fa->hw_index = 1;
  27768     }
  27769 
  27770     return BCM_E_NONE;
  27771 }
  27772 
  27773 /*
  27774  * Function:
  27775  *    _field_nh_ref_count_decr
  27776  *
  27777  * Purpose:
  27778  *     Decrement next hop refCount for RedirectEgrNextHop and
  27779  *     L3Switch action.
  27780  *
  27781  * Parameters:
  27782  *     unit      - (IN) BCM device number.
  27783  *     f_ent     - (IN) Entry array
  27784  * Returns:
  27785  *     BCM_E_XXX
  27786  * Notes:
  27787  */
  27788 STATIC int
  27789 _field_nh_ref_count_decr (int unit, _field_entry_t *f_ent)
  27790 {
  27791     _field_action_t *fa = NULL;  /* Field action descriptor. */
  27792     uint32 flags;                /* L3 forwarding flags.    */
  27793     int nh_ecmp_id;              /* Next hop/Ecmp group id. */
  27794 
  27795     /* Extract action info from the entry structure. */
  27796     for (fa = f_ent->actions; fa != NULL; fa = fa->next) {
  27797         if ((fa->action != bcmFieldActionRedirectEgrNextHop)
  27798                 && (fa->action != bcmFieldActionL3Switch)) {
  27799             continue;
  27800         }
  27801 
  27802         /* If action is not valid and dirty, do not decrement
  27803          * the ref Count. For modified action, the ref count
  27804          * decrement will happen in invalid_actions_free */
  27805         if ((fa->flags & _FP_ACTION_VALID) == 0) {
  27806             continue;
  27807         }
  27808 
  27809         if ((fa->flags & _FP_ACTION_DIRTY)) {
  27810             continue;
  27811         }
  27812 
  27813         BCM_IF_ERROR_RETURN(_bcm_field_policy_set_l3_nh_resolve (unit,
  27814                     fa->param[0], &flags, &nh_ecmp_id));
  27815 
  27816         BCM_IF_ERROR_RETURN(bcmi_esw_l3_egress_ref_count_update (unit,
  27817                     fa->param[0], flags, nh_ecmp_id,0));
  27818         fa->hw_index = _FP_INVALID_INDEX;
  27819         fa->flags |= _FP_ACTION_DIRTY;
  27820     }
  27821 
  27822     return BCM_E_NONE;
  27823 }
  27824 
  27825 
  27826 
  27827 /*
  27828  * Function:
  27829  *   bcmi_xgs3_fp_l3_egress_ref_count_update
  27830  *
  27831  * Purpose:
  27832  *     Increment next hop refCount for RedirectEgrNextHop and
  27833  *     L3Switch action after warmboot.
  27834  *
  27835  * Parameters:
  27836  *     unit      - (IN) BCM device number.
  27837  * Returns:
  27838  *     BCM_E_XXX
  27839  * Notes:
  27840  */
  27841 int
  27842 bcmi_xgs3_fp_l3_egress_ref_count_update (int unit)
  27843 {
  27844     _field_group_t      *fg;      /* Group information. */
  27845     _field_control_t    *fc;      /* Field Control Structure. */
  27846     _field_entry_t      *f_ent;   /* Field Entry. */
  27847     int                  idx = 0; /* Iteration index. */
  27848     int                   rv = 0; /* Return Value. */
  27849 
  27850     /* Get unit FP control structure. */
  27851     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  27852 
  27853     /* Iterate over the groups linked-list */
  27854     fg = fc->groups;
  27855     while (fg != NULL) {
  27856         if (fg->stage_id == _BCM_FIELD_STAGE_INGRESS ||
  27857             fg->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) {
  27858             /* Now iterate over the entries in this group */
  27859             for (idx = 0; idx < fg->group_status.entry_count; idx++) {
  27860                 f_ent = fg->entry_arr[idx];
  27861                 rv = _field_nh_ref_count_incr (unit, f_ent);
  27862                 BCM_IF_ERROR_RETURN(rv);
  27863 #if defined (BCM_TRIDENT2_SUPPORT) /* BCM_TRIDENT2_SUPPORT */
  27864                 rv = _bcm_field_nat_actions_update(unit, f_ent, 1);
  27865                 BCM_IF_ERROR_RETURN(rv);
  27866 #endif /* BCM_TRIDENT2_SUPPORT */
  27867             }
  27868         }
  27869         fg = fg->next;
  27870     }
  27871 
  27872     return rv;
  27873 }
  27874 
  27875 
  27876 #endif /* BCM_KATANA_SUPPORT || BCM_TRIDENT_SUPPORT || BCM_TRIUMPH3_SUPPORT \
  27877           || BCM_GREYHOUND_SUPPORT */
  27878 
  27879 #endif /* INCLUDE_L3 */
  27880 
  27881 /*
  27882  * Function:
  27883  *     _field_resources_free
  27884  *
  27885  * Purpose:
  27886  *     Free hw resources used in FP entry.
  27887  *
  27888  * Parameters:
  27889  *     unit      - (IN) BCM device number.
  27890  *     f_ent     - (IN) Field entry structure.
  27891  *     flags     - (IN) Old/installed resource to free.
  27892  * Returns:
  27893  *     BCM_E_XXX
  27894  * Notes:
  27895  */
  27896 STATIC int
  27897 _field_resources_free(int unit, _field_entry_t *f_ent, uint32 flags)
  27898 {
  27899     int rv;   /* Operation return status. */
  27900     _field_control_t *fc; /* Field Control Structure. */
  27901 
  27902     /* Input parameters check. */
  27903     if (NULL == f_ent) {
  27904         return (BCM_E_PARAM);
  27905     }
  27906 
  27907     BCM_IF_ERROR_RETURN (_field_control_get(unit, &fc));
  27908 
  27909     /* Free redirection profiles. */
  27910     rv = _field_redirect_profile_hw_free(unit, f_ent, flags);
  27911     BCM_IF_ERROR_RETURN(rv);
  27912 
  27913     /* Free mirror destination indexes. */
  27914     rv = _field_mtp_hw_free(unit, f_ent, flags);
  27915     BCM_IF_ERROR_RETURN(rv);
  27916 
  27917 #if defined(BCM_TRIDENT2_SUPPORT)
  27918     if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit) ||
  27919            soc_feature(unit, soc_feature_field_multi_pipe_support))) {
  27920         rv = _bcm_field_td2_hash_select_profile_hw_free(unit, f_ent, flags);
  27921         BCM_IF_ERROR_RETURN(rv);
  27922     }
  27923 #endif
  27924 
  27925     /* Free counters. */
  27926     if (flags & _FP_ACTION_RESOURCE_FREE) {
  27927         rv = fc->functions.fp_stat_hw_free(unit, f_ent);
  27928         BCM_IF_ERROR_RETURN(rv);
  27929     }
  27930 
  27931 
  27932 #if defined(INCLUDE_L3)
  27933 #if defined(BCM_FIREBOLT_SUPPORT) || defined(BCM_TRX_SUPPORT)
  27934     if (soc_feature(unit, soc_feature_field_action_l2_change)) {
  27935         rv = _bcm_field_l2_actions_hw_free(unit, f_ent, flags);
  27936         BCM_IF_ERROR_RETURN(rv);
  27937     }
  27938 #endif /* BCM_TRIUMPH2_SUPPORT || BCM_TRIDENT_SUPPORT */
  27939 
  27940 #if defined (BCM_KATANA_SUPPORT) || defined (BCM_TRIDENT_SUPPORT) \
  27941          || defined (BCM_TRIUMPH3_SUPPORT) || defined (BCM_GREYHOUND_SUPPORT) \
  27942          || defined (BCM_ENDURO_SUPPORT)
  27943     if (SOC_IS_KATANAX(unit) || SOC_IS_TD_TT(unit) || SOC_IS_TRIUMPH3(unit)
  27944         || SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANEX(unit)
  27945         || SOC_IS_ENDURO(unit) || SOC_IS_GREYHOUND2(unit)) {
  27946         BCM_IF_ERROR_RETURN(_bcm_field_l3_egress_actions_reset(unit, f_ent,
  27947                                                                flags));
  27948 
  27949         /* Decrement next hop ref Count. */
  27950         if (flags & _FP_ACTION_RESOURCE_FREE) {
  27951             rv = _field_nh_ref_count_decr (unit, f_ent);
  27952             BCM_IF_ERROR_RETURN(rv);
  27953         }
  27954     }
  27955 
  27956 #endif /* BCM_KATANA_SUPPORT || BCM_TRIDENT_SUPPORT || BCM_TRIUMPH3_SUPPORT \
  27957           || BCM_GREYHOUND_SUPPORT || BCM_ENDURO_SUPPORT */
  27958 
  27959 #if defined (BCM_TRIDENT2_SUPPORT) /* BCM_TRIDENT2_SUPPORT */
  27960     if (flags & _FP_ACTION_RESOURCE_FREE) {
  27961         BCM_IF_ERROR_RETURN(_bcm_field_nat_actions_update(unit, f_ent, 0));
  27962     }
  27963 #endif /* BCM_TRIDENT2_SUPPORT */
  27964 
  27965 #endif /* INCLUDE_L3 */
  27966 
  27967 #if defined(BCM_TOMAHAWK_SUPPORT)
  27968      if(NULL != fc->functions.fp_eh_mask_profile_hw_free) {
  27969          fc->functions.fp_eh_mask_profile_hw_free(unit, f_ent, flags);
  27970          BCM_IF_ERROR_RETURN(rv);
  27971      }
  27972 #endif
  27973 
  27974 #if defined(BCM_TRIDENT3_SUPPORT)
  27975     if (NULL != fc->functions.fp_vlan_actions_profile_hw_free) {
  27976        rv = fc->functions.fp_vlan_actions_profile_hw_free(unit, f_ent, flags);
  27977        BCM_IF_ERROR_RETURN(rv);
  27978     }
  27979 #endif /* BCM_TRIDENT3_SUPPORT */
  27980 
  27981 #if defined(BCM_FLOWTRACKER_SUPPORT)
  27982     BCM_IF_ERROR_RETURN(_bcm_field_hx5_ft_group_hw_free(unit, f_ent,
  27983                                 flags));
  27984 #endif
  27985 
  27986     if (soc_feature(unit, soc_feature_th3_style_fp)) {
  27987         rv = _field_delayed_profile_hw_free(unit, f_ent, flags);
  27988         BCM_IF_ERROR_RETURN(rv);
  27989     }
  27990     return (BCM_E_NONE);
  27991 }
  27992 
  27993 /*
  27994  * Function:
  27995  *     _field_hw_resources_free
  27996  *
  27997  * Purpose:
  27998  *     Free hw resources used in FP entry.
  27999  *
  28000  * Parameters:
  28001  *     unit      - (IN) BCM device number.
  28002  *     f_ent     - (IN) Field entry structure.
  28003  *     flags     - (IN) Old/installed resource to free.
  28004  * Returns:
  28005  *     BCM_E_XXX
  28006  * Notes:
  28007  */
  28008 STATIC int
  28009 _field_hw_resources_free(int unit, _field_entry_t *f_ent, uint32 flags)
  28010 {
  28011     int rv;	/* Operation return status. */
  28012 
  28013     rv = _field_resources_free(unit, f_ent, flags);
  28014     BCM_IF_ERROR_RETURN(rv);
  28015 
  28016     /* Free policers. */
  28017     if (flags & _FP_ACTION_RESOURCE_FREE) {
  28018         if (flags & _FP_ACTION_POLICER_SW_UPDATE) {
  28019             rv = _field_policers_hw_free(unit, f_ent,
  28020                     _FP_ACTION_RESOURCE_FREE|_FP_ACTION_POLICER_SW_UPDATE);
  28021         } else {
  28022             rv = _field_policers_hw_free(unit, f_ent, _FP_ACTION_RESOURCE_FREE);
  28023         }
  28024         BCM_IF_ERROR_RETURN(rv);
  28025     }
  28026 
  28027     if (flags & _FP_ACTION_OLD_RESOURCE_FREE) {
  28028         if (flags & _FP_ACTION_POLICER_SW_UPDATE) {
  28029             rv = _field_policers_hw_free(unit, f_ent,
  28030                     _FP_ACTION_OLD_RESOURCE_FREE|_FP_ACTION_POLICER_SW_UPDATE);
  28031         } else {
  28032             rv = _field_policers_hw_free(unit, f_ent, _FP_ACTION_OLD_RESOURCE_FREE);
  28033         }
  28034         BCM_IF_ERROR_RETURN(rv);
  28035     }
  28036 
  28037     return (BCM_E_NONE);
  28038 }
  28039 
  28040 /*
  28041  * Function:
  28042  *     _field_hw_resources_alloc
  28043  *
  28044  * Purpose:
  28045  *     Allocate hw resources required for entry installation.
  28046  *
  28047  * Parameters:
  28048  *     unit      - (IN) BCM device number.
  28049  *     f_ent     - (IN) Entry array
  28050  * Returns:
  28051  *     BCM_E_XXX
  28052  * Notes:
  28053  */
  28054 STATIC int
  28055 _field_hw_resources_alloc(int unit, _field_entry_t *f_ent)
  28056 {
  28057     _field_control_t *fc;
  28058     _field_stage_t   *stage_fc;    /* Stage field control.     */
  28059     int rv = BCM_E_NONE;           /* Operation return status. */
  28060 
  28061     /* Input parameters check. */
  28062     if (NULL == f_ent) {
  28063         return (BCM_E_PARAM);
  28064     }
  28065 
  28066     BCM_IF_ERROR_RETURN (_field_control_get(unit, &fc));
  28067 
  28068     /* Get Stage Control structure. */
  28069     rv = _field_stage_control_get(unit, f_ent->group->stage_id, &stage_fc);
  28070     BCM_IF_ERROR_RETURN(rv);
  28071 
  28072     /* Select slice for hw resources allocation. */
  28073     rv = _field_entry_install_slice_fit(unit, stage_fc, f_ent, f_ent->fs);
  28074     BCM_IF_ERROR_RETURN(rv);
  28075 
  28076     /* Allocate policers. */
  28077     BCM_IF_ERROR_RETURN(_field_policers_hw_alloc(unit, f_ent));
  28078 
  28079     /* Allocate statistics. */
  28080     if ((f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) &&
  28081         (soc_feature(unit, soc_feature_field_multi_pipe_support))) {
  28082         if (f_ent->statistic.flags & _FP_ENTRY_STAT_DIRTY) {
  28083            /* Allocate statistics. */
  28084     rv = fc->functions.fp_stat_hw_alloc(unit, f_ent);
  28085     if (BCM_FAILURE(rv)) {
  28086         _field_policers_hw_free(unit, f_ent, _FP_ACTION_RESOURCE_FREE);
  28087         return (rv);
  28088     }
  28089         }
  28090     } else {
  28091        /* Allocate statistics. */
  28092        rv = fc->functions.fp_stat_hw_alloc(unit, f_ent);
  28093        if (BCM_FAILURE(rv)) {
  28094           _field_policers_hw_free(unit, f_ent, _FP_ACTION_RESOURCE_FREE);
  28095           return (rv);
  28096        }
  28097     }
  28098 
  28099     /* Allocate mirror destination indexes. */
  28100     rv = _field_mtp_hw_alloc(unit, f_ent);
  28101     if (BCM_FAILURE(rv)) {
  28102         fc->functions.fp_stat_hw_free(unit, f_ent);
  28103         _field_policers_hw_free(unit, f_ent, _FP_ACTION_RESOURCE_FREE);
  28104         return (rv);
  28105     }
  28106 
  28107     /* Allocate redirection profiles. */
  28108     rv = _field_redirect_profile_hw_alloc(unit, f_ent);
  28109     if (BCM_FAILURE(rv)) {
  28110         _field_mtp_hw_free(unit, f_ent, _FP_ACTION_HW_FREE);
  28111         fc->functions.fp_stat_hw_free(unit, f_ent);
  28112         _field_policers_hw_free(unit, f_ent, _FP_ACTION_RESOURCE_FREE);
  28113         return (rv);
  28114     }
  28115 
  28116 #if defined(BCM_TOMAHAWK_SUPPORT)
  28117     /* Allocate redirection profiles. */
  28118     if (NULL != fc->functions.fp_eh_mask_profile_hw_alloc) {
  28119         rv = fc->functions.fp_eh_mask_profile_hw_alloc(unit, f_ent);
  28120         if (BCM_FAILURE(rv)) {
  28121             _field_mtp_hw_free(unit, f_ent, _FP_ACTION_HW_FREE);
  28122             fc->functions.fp_stat_hw_free(unit, f_ent);
  28123             _field_policers_hw_free(unit, f_ent, _FP_ACTION_RESOURCE_FREE);
  28124             _field_redirect_profile_hw_free(unit, f_ent, _FP_ACTION_HW_FREE);
  28125             return (rv);
  28126         }
  28127     }
  28128 #endif
  28129 
  28130 #if defined(BCM_TRIDENT2_SUPPORT)
  28131     /* Allocate hash select profiles. */
  28132     if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit) ||
  28133          soc_feature(unit, soc_feature_field_multi_pipe_support))) {
  28134         rv = _bcm_field_td2_hash_select_profile_hw_alloc(unit, f_ent);
  28135         if (BCM_FAILURE(rv)) {
  28136             _field_mtp_hw_free(unit, f_ent, _FP_ACTION_HW_FREE);
  28137             fc->functions.fp_stat_hw_free(unit, f_ent);
  28138             _field_policers_hw_free(unit, f_ent, _FP_ACTION_RESOURCE_FREE);
  28139             _field_redirect_profile_hw_free(unit, f_ent, _FP_ACTION_HW_FREE);
  28140 #if defined(BCM_TOMAHAWK_SUPPORT)
  28141             if (NULL != fc->functions.fp_eh_mask_profile_hw_free) {
  28142                fc->functions.fp_eh_mask_profile_hw_free(unit, f_ent,
  28143                                                      _FP_ACTION_HW_FREE);
  28144             }
  28145 #endif
  28146             return (rv);
  28147         }
  28148     }
  28149 #endif /* BCM_TRIDENT2_SUPPORT */
  28150 
  28151 #if defined (INCLUDE_L3)
  28152 #if defined(BCM_FIREBOLT_SUPPORT) || defined(BCM_TRX_SUPPORT)
  28153     if (soc_feature(unit, soc_feature_field_action_l2_change)) {
  28154         rv =  _bcm_field_l2_actions_hw_alloc(unit, f_ent);
  28155         if (BCM_FAILURE(rv)) {
  28156             _field_mtp_hw_free(unit, f_ent, _FP_ACTION_HW_FREE);
  28157             fc->functions.fp_stat_hw_free(unit, f_ent);
  28158             _field_policers_hw_free(unit, f_ent, _FP_ACTION_RESOURCE_FREE);
  28159             _field_redirect_profile_hw_free(unit, f_ent, _FP_ACTION_HW_FREE);
  28160 #if defined(BCM_TRIDENT2_SUPPORT)
  28161             if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit) ||
  28162                  soc_feature(unit, soc_feature_field_multi_pipe_support))) {
  28163                 _bcm_field_td2_hash_select_profile_hw_free(unit,
  28164                                                            f_ent,
  28165                                                            _FP_ACTION_HW_FREE);
  28166             }
  28167 #endif
  28168 #if defined(BCM_TOMAHAWK_SUPPORT)
  28169             if (NULL != fc->functions.fp_eh_mask_profile_hw_free) {
  28170                fc->functions.fp_eh_mask_profile_hw_free(unit, f_ent,
  28171                                                      _FP_ACTION_HW_FREE);
  28172             }
  28173 #endif
  28174             return (rv);
  28175         }
  28176     }
  28177 #endif /* BCM_TRIUMPH2_SUPPORT || defined (BCM_TRIDENT_SUPPORT) */
  28178 #if defined (BCM_KATANA_SUPPORT) || defined (BCM_TRIDENT_SUPPORT) \
  28179          || defined (BCM_TRIUMPH3_SUPPORT) || defined (BCM_GREYHOUND_SUPPORT) \
  28180          || defined (BCM_ENDURO_SUPPORT)
  28181     if (SOC_IS_KATANAX(unit) || SOC_IS_TD_TT(unit) || SOC_IS_TRIUMPH3(unit)
  28182         || SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANEX(unit)
  28183         || SOC_IS_ENDURO(unit) || SOC_IS_GREYHOUND2(unit)) {
  28184         rv = _bcm_field_l3_egress_actions_set(unit, f_ent);
  28185         if (BCM_SUCCESS(rv)) {
  28186             rv = _field_nh_ref_count_incr(unit, f_ent);
  28187             if (BCM_FAILURE(rv)) {
  28188                 _bcm_field_l3_egress_actions_reset(unit,
  28189                                                    f_ent, _FP_ACTION_HW_FREE);
  28190             }
  28191         }
  28192 
  28193         if (BCM_FAILURE(rv)) {
  28194             if (soc_feature(unit, soc_feature_field_action_l2_change)) {
  28195                 _bcm_field_l2_actions_hw_free(unit, f_ent,
  28196                                             _FP_ACTION_RESOURCE_FREE);
  28197             }
  28198             _field_mtp_hw_free(unit, f_ent, _FP_ACTION_HW_FREE);
  28199             fc->functions.fp_stat_hw_free(unit, f_ent);
  28200             _field_policers_hw_free(unit, f_ent, _FP_ACTION_RESOURCE_FREE);
  28201             _field_redirect_profile_hw_free(unit, f_ent, _FP_ACTION_HW_FREE);
  28202 #if defined(BCM_TOMAHAWK_SUPPORT)
  28203             if (NULL != fc->functions.fp_eh_mask_profile_hw_free) {
  28204                fc->functions.fp_eh_mask_profile_hw_free(unit, f_ent,
  28205                                                      _FP_ACTION_HW_FREE);
  28206             }
  28207 #endif
  28208             return (rv);
  28209         }
  28210     }
  28211 #endif /* BCM_KATANA_SUPPORT || BCM_TRIDENT_SUPPORT || BCM_TRIUMPH3_SUPPORT \
  28212           || BCM_GREYHOUND_SUPPORT || BCM_ENDURO_SUPPORT */
  28213 
  28214 #if defined (BCM_TRIDENT2_SUPPORT)
  28215     rv = _bcm_field_nat_actions_update(unit, f_ent, 1);
  28216     if (BCM_FAILURE(rv)) {
  28217         if (SOC_IS_KATANAX(unit) || SOC_IS_TD_TT(unit) || SOC_IS_TRIUMPH3(unit)
  28218                 || SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANEX(unit)
  28219                 || SOC_IS_ENDURO(unit)) {
  28220             _field_nh_ref_count_decr (unit, f_ent);
  28221             _bcm_field_l3_egress_actions_reset(unit,
  28222                     f_ent, _FP_ACTION_HW_FREE);
  28223         }
  28224         if (soc_feature(unit, soc_feature_field_action_l2_change)) {
  28225             _bcm_field_l2_actions_hw_free(unit, f_ent,
  28226                     _FP_ACTION_RESOURCE_FREE);
  28227         }
  28228 #if defined(BCM_TRIDENT2_SUPPORT)
  28229         if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit) ||
  28230              soc_feature(unit, soc_feature_field_multi_pipe_support))) {
  28231             _bcm_field_td2_hash_select_profile_hw_free(unit,
  28232                     f_ent,
  28233                     _FP_ACTION_HW_FREE);
  28234         }
  28235 #endif
  28236 #if defined(BCM_TOMAHAWK_SUPPORT)
  28237         if (NULL != fc->functions.fp_eh_mask_profile_hw_free) {
  28238             fc->functions.fp_eh_mask_profile_hw_free(unit, f_ent,
  28239                     _FP_ACTION_HW_FREE);
  28240         }
  28241 #endif
  28242         _field_redirect_profile_hw_free(unit, f_ent, _FP_ACTION_HW_FREE);
  28243         _field_mtp_hw_free(unit, f_ent, _FP_ACTION_HW_FREE);
  28244         fc->functions.fp_stat_hw_free(unit, f_ent);
  28245         _field_policers_hw_free(unit, f_ent, _FP_ACTION_RESOURCE_FREE);
  28246     }
  28247 #endif
  28248 
  28249 
  28250 /* Delayed Action profile alloc */
  28251     if (soc_feature(unit, soc_feature_th3_style_fp)) {
  28252         rv = _field_delayed_profile_hw_alloc(unit, f_ent);
  28253         if (BCM_FAILURE(rv)) {
  28254 #if defined (BCM_TRIDENT2_SUPPORT)
  28255             if (SOC_IS_KATANAX(unit) || SOC_IS_TD_TT(unit) || SOC_IS_TRIUMPH3(unit)
  28256                     || SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANEX(unit)
  28257                     || SOC_IS_ENDURO(unit)) {
  28258                 _field_nh_ref_count_decr (unit, f_ent);
  28259                 _bcm_field_l3_egress_actions_reset(unit,
  28260                         f_ent, _FP_ACTION_HW_FREE);
  28261             }
  28262             if (soc_feature(unit, soc_feature_field_action_l2_change)) {
  28263                 _bcm_field_l2_actions_hw_free(unit, f_ent,
  28264                         _FP_ACTION_RESOURCE_FREE);
  28265             }
  28266 #if defined(BCM_TRIDENT2_SUPPORT)
  28267             if ((SOC_IS_TRIDENT2X(unit) || SOC_IS_TITAN2PLUS(unit) ||
  28268                   SOC_IS_TOMAHAWKX(unit))) {
  28269                 _bcm_field_td2_hash_select_profile_hw_free(unit,
  28270                         f_ent,
  28271                         _FP_ACTION_HW_FREE);
  28272             }
  28273 #endif
  28274 #if defined(BCM_TOMAHAWK_SUPPORT)
  28275             if (NULL != fc->functions.fp_eh_mask_profile_hw_free) {
  28276                 fc->functions.fp_eh_mask_profile_hw_free(unit, f_ent,
  28277                         _FP_ACTION_HW_FREE);
  28278             }
  28279 #endif
  28280             _field_redirect_profile_hw_free(unit, f_ent, _FP_ACTION_HW_FREE);
  28281             _field_mtp_hw_free(unit, f_ent, _FP_ACTION_HW_FREE);
  28282             fc->functions.fp_stat_hw_free(unit, f_ent);
  28283             _field_policers_hw_free(unit, f_ent, _FP_ACTION_RESOURCE_FREE);
  28284 #endif
  28285         }
  28286     }
  28287 
  28288 #endif /* INCLUDE_L3 */
  28289 
  28290 #if defined(BCM_TRIDENT3_SUPPORT)
  28291     if ((f_ent->vlan_action_set != NULL) &&
  28292         (fc->functions.fp_vlan_actions_profile_hw_alloc != NULL)) {
  28293        fc->functions.fp_vlan_actions_profile_hw_alloc(unit, f_ent);
  28294     }
  28295 #endif /* BCM_TRIDENT3_SUPPORT */
  28296 
  28297 #if defined(BCM_FLOWTRACKER_SUPPORT)
  28298     if (soc_feature(unit, soc_feature_field_flowtracker_support) &&
  28299         (f_ent->group->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER)) {
  28300         rv = _bcm_field_hx5_ft_group_hw_alloc(unit, f_ent);
  28301     }
  28302 #endif /* BCM_FLOWTRACKER_SUPPORT */
  28303 
  28304     return rv;
  28305 }
  28306 
  28307 /*
  28308  * Function:
  28309  *     _field_entry_policer_stat_slice_move
  28310  * Purpose:
  28311  *     Move policer to slice in which counter resides
  28312  * Parameters:
  28313  *     unit          - (IN) BCM device number.
  28314  *     f_ent         - (IN) Entry to be installed.
  28315  *     to_secondary  - (IN) Movement direction.
  28316  * Returns:
  28317  *     BCM_E_XXX
  28318  */
  28319 STATIC int
  28320 _field_entry_policer_stat_slice_move(int unit,
  28321                                      _field_entry_t *f_ent,
  28322                                      int to_secondary)
  28323 {
  28324     _field_entry_policer_t *f_ent_pl_src; /* Src entry policer descriptor  */
  28325     _field_entry_policer_t *f_ent_pl_dst; /* Dest entry policer descriptor */
  28326     _field_stage_t *stage_fc;             /* Stage field control.          */
  28327     uint8 src_idx;                        /* Source entry hardware index.  */
  28328     uint8 dst_idx;                        /* Dest entry hardware index.    */
  28329     uint8 level;                          /* Policer level.                */
  28330     _field_action_t  *fa;                 /* Entry actions iterator.       */
  28331     _field_action_t  *fa_next;            /* Entry actions iterator.       */
  28332 
  28333     /* Input parameters check */
  28334     if  (NULL == f_ent) {
  28335         return (BCM_E_PARAM);
  28336     }
  28337 
  28338     /* Get stage control structure. */
  28339     BCM_IF_ERROR_RETURN
  28340         (_field_stage_control_get(unit,
  28341                                   f_ent->group->stage_id,
  28342                                   &stage_fc
  28343                                   )
  28344         );
  28345 
  28346     if ((stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)
  28347         && !(stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS)
  28348         && (f_ent->flags & _FP_ENTRY_STAT_IN_SECONDARY_SLICE)) {
  28349         /* Get entry secondary part hardware index. */
  28350         BCM_IF_ERROR_RETURN
  28351             (_bcm_field_entry_flags_to_tcam_part(unit, _FP_ENTRY_SECONDARY,
  28352                                                  f_ent->group,
  28353                                                  &dst_idx
  28354                                                  )
  28355             );
  28356 
  28357         /* Determine source and destination slice indices. */
  28358         if (to_secondary) {
  28359             src_idx = 0;
  28360         } else {
  28361             src_idx = dst_idx;
  28362             dst_idx = 0;
  28363         }
  28364 
  28365         fa = f_ent[src_idx].actions;
  28366         /* Copy all actions from source index to destination index. */
  28367         while (NULL != fa)  {
  28368             fa_next = fa->next;
  28369             /* Insert action to the destination slice actions list. */
  28370             fa->next = f_ent[dst_idx].actions;
  28371             f_ent[dst_idx].actions = fa;
  28372             /* Remove action from the primary slice actions list. */
  28373             f_ent[src_idx].actions = fa_next;
  28374             fa = fa_next;
  28375         }
  28376 
  28377         for (level = 0; level < _FP_POLICER_LEVEL_COUNT; level++) {
  28378             f_ent_pl_src = f_ent[src_idx].policer + level;
  28379 
  28380             if (f_ent_pl_src->flags & _FP_POLICER_INSTALLED) {
  28381                 f_ent_pl_dst = (f_ent[dst_idx].policer + level);
  28382                 f_ent_pl_dst->pid = f_ent_pl_src->pid;
  28383                 f_ent_pl_dst->flags |= _FP_POLICER_INSTALLED;
  28384 
  28385                 f_ent_pl_src->flags &= ~_FP_POLICER_INSTALLED;
  28386                 f_ent_pl_src->pid = _FP_INVALID_INDEX;
  28387             }
  28388         }
  28389     }
  28390     return (BCM_E_NONE);
  28391 }
  28392 
  28393 /*
  28394  * Function:
  28395  *     _field_entry_actions_meter_slice_move
  28396  * Purpose:
  28397  *    Move actions to a slice where meter resides.
  28398  * Parameters:
  28399  *     unit  - (IN) BCM device number.
  28400  *     f_ent - (IN) Entry to be installed.
  28401  *     to_secondary  - (IN) Movement direction.
  28402  * Returns:
  28403  *     BCM_E_XXX
  28404  */
  28405 STATIC int
  28406 _field_entry_actions_meter_slice_move(int unit, _field_entry_t *f_ent,
  28407                                       int to_secondary)
  28408 {
  28409     _field_stage_t   *stage_fc;   /* Stage field control.              */
  28410     _field_action_t  *fa;         /* Entry actions iterator.           */
  28411     _field_action_t  *fa_prev;    /* Entry actions iterator.           */
  28412     _field_action_t  *fa_next;    /* Entry actions iterator.           */
  28413     uint8            src_idx;     /* Entry array action source index.  */
  28414     uint8            dst_idx;     /* Entry array action dest index.    */
  28415     int              rv;          /* Operation return status.          */
  28416 
  28417 
  28418     /* Input parameters check */
  28419     if  (NULL == f_ent) {
  28420         return (BCM_E_PARAM);
  28421     }
  28422 
  28423     /* Get stage control structure. */
  28424     rv = _field_stage_control_get(unit, f_ent->group->stage_id, &stage_fc);
  28425     BCM_IF_ERROR_RETURN(rv);
  28426 
  28427     if ((0 == (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)) &&
  28428         (f_ent->flags & _FP_ENTRY_POLICER_IN_SECONDARY_SLICE)) {
  28429           rv =
  28430             _bcm_field_entry_flags_to_tcam_part(unit, _FP_ENTRY_SECONDARY,
  28431                                                 f_ent->group, &dst_idx);
  28432           BCM_IF_ERROR_RETURN(rv);
  28433 
  28434           if (to_secondary) {
  28435               src_idx = 0;
  28436           } else {
  28437               src_idx = dst_idx;
  28438               dst_idx = 0;
  28439           }
  28440 
  28441           /* Copy all but counter action. */
  28442           fa = f_ent[src_idx].actions;
  28443           fa_prev = NULL;
  28444           while (NULL != fa)  {
  28445               fa_next = fa->next;
  28446               /* coverity[always_true_or : FALSE]*/
  28447               if ((fa->action != bcmFieldActionUpdateCounter) ||
  28448                   (fa->action != bcmFieldActionCosQCpuNew)||
  28449                   (fa->action != bcmFieldActionServicePoolIdNew)||
  28450                   (fa->action != bcmFieldActionServicePoolIdPrecedenceNew)) {
  28451 
  28452                   /* Insert action to the destination slice actions list. */
  28453                   fa->next = f_ent[dst_idx].actions;
  28454                   f_ent[dst_idx].actions = fa;
  28455                   /* Remove action from the primary slice actions list. */
  28456                   if (NULL == fa_prev)  {
  28457                       f_ent[src_idx].actions = fa_next;
  28458                   } else {
  28459                       fa_prev->next = fa_next;
  28460                   }
  28461               } else {
  28462                   fa_prev = fa;
  28463               }
  28464               fa = fa_next;
  28465           }
  28466     }
  28467     return (BCM_E_NONE);
  28468 }
  28469 
  28470 /*
  28471  * Function: _field_entry_tcam_remove
  28472  *
  28473  * Purpose:
  28474  *     Remove an entry from the FP tcam.
  28475  *
  28476  * Parameters:
  28477  *     unit     - (IN) BCM device number
  28478  *     fc       - (IN) Field control structure.
  28479  *     f_ent    - (IN) Primary entry pointer.
  28480  *     tcam_idx - (IN) Entry tcam index.
  28481  *
  28482  * Returns:
  28483  *     BCM_E_XXX
  28484  */
  28485 int
  28486 _field_entry_tcam_remove(int unit, _field_control_t *fc,
  28487                          _field_entry_t *f_ent, int tcam_idx)
  28488 {
  28489     int rv;           /* Operation return status. */
  28490 
  28491     /* Input parameter check. */
  28492     if ((NULL == fc) || (NULL == f_ent)) {
  28493         return (BCM_E_PARAM);
  28494     }
  28495     /* Remove entry in slice. */
  28496     if (f_ent->fs->stage_id == _BCM_FIELD_STAGE_EXTERNAL) {
  28497         rv = fc->functions.fp_external_entry_remove(unit, f_ent);
  28498         BCM_IF_ERROR_RETURN(rv);
  28499     } else {
  28500         rv = fc->functions.fp_entry_remove(unit, f_ent, tcam_idx);
  28501         BCM_IF_ERROR_RETURN(rv);
  28502     }
  28503     return (rv);
  28504 }
  28505 
  28506 /*
  28507  * Function:
  28508  *     _field_tcam_policy_reinstall
  28509  *
  28510  * Purpose:
  28511  *     Re-Install a POLICY_TABLE entry. This re-writes the
  28512  *     modified actions to the hardware.
  28513  *
  28514  * Parameters:
  28515  *     unit  - (IN) BCM device number.
  28516  *     entry - (IN) Entry to be installed.
  28517  * Returns:
  28518  *     BCM_E_XXX
  28519  */
  28520 int
  28521 _field_tcam_policy_reinstall(int unit, bcm_field_entry_t entry)
  28522 {
  28523     int                 tcam_idx[_FP_MAX_ENTRY_WIDTH]; /* Entry tcam index. */
  28524     int                 parts_count = 0;       /* Field entry parts count.  */
  28525     _field_entry_t      *f_ent;                /* Field entry pointer.      */
  28526     _field_control_t    *fc;                   /* Field control structure.  */
  28527     int                 idx;                   /* Iteration index.          */
  28528     int                 rv;                    /* Operation return status.  */
  28529 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
  28530     defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT)
  28531     _field_entry_stat_t  *f_ent_st = NULL;     /* Field entry statistics
  28532                                                   structure.                */
  28533     _field_stat_t        *f_st = NULL;         /* Statistics entity
  28534                                                   descriptor.               */
  28535 #endif
  28536 
  28537     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  28538     LOG_DEBUG(BSL_LS_BCM_FP,
  28539               (BSL_META_U(unit,
  28540                "FP(unit %d) vverb: _field_tcam_policy_reinstall (%d)\n"),
  28541                unit, entry));
  28542 
  28543 
  28544     /* Installing the entry. */
  28545     rv = _bcm_field_entry_get_by_id(unit, entry, &f_ent);
  28546     BCM_IF_ERROR_RETURN(rv);
  28547 
  28548     /* Get number of parts. */
  28549     rv = _bcm_field_entry_tcam_parts_count (unit, f_ent->group->stage_id,
  28550                                             f_ent->group->flags, &parts_count);
  28551     BCM_IF_ERROR_RETURN(rv);
  28552 
  28553     /* Initialize tcam_idx array. */
  28554     sal_memset(tcam_idx, 0, sizeof(tcam_idx));
  28555 
  28556     /* Get tcam indexes for installed entry. */
  28557     if (f_ent->group->stage_id != _BCM_FIELD_STAGE_EXTERNAL) {
  28558         for (idx = parts_count - 1; idx >=0; idx--) {
  28559             rv = _bcm_field_entry_tcam_idx_get(unit, f_ent + idx,
  28560                                                tcam_idx + idx);
  28561             BCM_IF_ERROR_RETURN(rv);
  28562         }
  28563     }
  28564 
  28565 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  28566     /* Advanced flex STAT counters reference count handled here. */
  28567     if ((f_ent->flags & _FP_ENTRY_INSTALLED) &&
  28568         (soc_feature(unit, soc_feature_advanced_flex_counter)) &&
  28569          !(soc_feature(unit, soc_feature_field_multi_pipe_support))) {
  28570 
  28571         for (idx = 0; idx < parts_count; idx++) {
  28572             /* Read existing entry qualifiers from the HW. */
  28573             BCM_IF_ERROR_RETURN
  28574                 (_bcm_field_qual_tcam_key_mask_get(unit,
  28575                                                    f_ent + idx));
  28576 
  28577             if (_BCM_FIELD_STAGE_LOOKUP == f_ent->fs->stage_id) {
  28578                 f_ent_st = &((f_ent + idx)->statistic);
  28579                 if (f_ent_st->flags & _FP_ENTRY_STAT_INSTALLED) {
  28580                     /* Read stat entity configuration. */
  28581                     if ((f_ent_st->flags & _FP_ENTRY_EXTENDED_STAT_VALID) &&
  28582                             soc_feature(unit, soc_feature_flex_stat_compaction_support)) {
  28583                         /* Read stat entity configuration. */
  28584                         BCM_IF_ERROR_RETURN
  28585                             (_bcm_field_stat_get(unit, f_ent_st->extended_sid, &f_st));
  28586                     } else {
  28587                         BCM_IF_ERROR_RETURN
  28588                             (_bcm_field_stat_get(unit, f_ent_st->sid, &f_st));
  28589                     }
  28590                     if (f_st->hw_ref_count > 0) {
  28591                         /*
  28592                          * If this is the only entry using this stat, store the stat
  28593                          * values to retain on next attach.
  28594                          */
  28595                         if (1 == f_st->hw_ref_count) {
  28596                             int  i;
  28597                             for (i= 0; i < f_st->nstat; i++) {
  28598                                 rv = _field_stat_value_get(unit, 0, f_st,
  28599                                         f_st->stat_arr[i],
  28600                                         f_st->stat_values + i);
  28601                                 BCM_IF_ERROR_RETURN(rv);
  28602                             }
  28603                         }
  28604                         BCM_IF_ERROR_RETURN
  28605                             (_bcm_esw_stat_flex_detach_ingress_table_counters
  28606                              (unit, VFP_POLICY_TABLEm, tcam_idx[idx]));
  28607                         if (soc_feature(unit, soc_feature_flex_stat_compaction_support)) {
  28608                             f_ent_st->flags &= ~_FP_ENTRY_EXTENDED_STAT_INSTALLED;
  28609                             f_ent_st->flags &= ~_FP_ENTRY_EXTENDED_STAT_RESERVED;
  28610                             f_ent_st->flags &= ~_FP_ENTRY_STAT_INSTALLED;
  28611                         } else {
  28612                             f_ent_st->flags &= ~_FP_ENTRY_STAT_INSTALLED;
  28613                         }
  28614                         f_st->hw_ref_count--;
  28615                     }
  28616                 }
  28617             }
  28618 
  28619             if (_BCM_FIELD_STAGE_INGRESS == f_ent->fs->stage_id) {
  28620                 f_ent_st = &((f_ent + idx)->statistic);
  28621                 if (f_ent_st->flags & _FP_ENTRY_EXTENDED_STAT_INSTALLED) {
  28622                     /* Read stat entity configuration. */
  28623                     BCM_IF_ERROR_RETURN
  28624                         (_bcm_field_stat_get(unit, f_ent_st->extended_sid, &f_st));
  28625                     if (f_st->hw_ref_count > 0) {
  28626                         /*
  28627                          * If this is the only entry using this stat, store the stat
  28628                          * values to retain on next attach.
  28629                          */
  28630                         if (1 == f_st->hw_ref_count) {
  28631                             int  i;
  28632                             for (i= 0; i < f_st->nstat; i++) {
  28633                                 rv = _field_stat_value_get(unit, 0, f_st,
  28634                                         f_st->stat_arr[i],
  28635                                         f_st->stat_values + i);
  28636                                 BCM_IF_ERROR_RETURN(rv);
  28637                             }
  28638                         }
  28639 
  28640                         rv = _bcm_esw_stat_flex_detach_ingress_table_counters
  28641                             (unit, FP_POLICY_TABLEm, tcam_idx[idx]);
  28642                         BCM_IF_ERROR_RETURN(rv);
  28643                         f_ent_st->flags &= ~_FP_ENTRY_EXTENDED_STAT_INSTALLED;
  28644                         f_ent_st->flags &= ~_FP_ENTRY_EXTENDED_STAT_RESERVED;
  28645                         f_st->hw_ref_count--;
  28646                     }
  28647                 }
  28648             }
  28649 
  28650             if (_BCM_FIELD_STAGE_EGRESS == f_ent->fs->stage_id) {
  28651                 f_ent_st = &((f_ent + idx)->statistic);
  28652                 if (f_ent_st->flags & _FP_ENTRY_EXTENDED_STAT_INSTALLED) {
  28653                     /* Read stat entity configuration. */
  28654                     BCM_IF_ERROR_RETURN
  28655                         (_bcm_field_stat_get(unit, f_ent_st->extended_sid, &f_st));
  28656                     if (f_st->hw_ref_count > 0) {
  28657                         /*
  28658                          * If this is the only entry using this stat, store the stat
  28659                          * values to retain on next attach.
  28660                          */
  28661                         if (1 == f_st->hw_ref_count) {
  28662                             int  i;
  28663                             for (i= 0; i < f_st->nstat; i++) {
  28664                                 rv = _field_stat_value_get(unit, 0, f_st,
  28665                                         f_st->stat_arr[i],
  28666                                         f_st->stat_values + i);
  28667                                 BCM_IF_ERROR_RETURN(rv);
  28668                             }
  28669                         }
  28670 
  28671                         rv = _bcm_esw_stat_flex_detach_egress_table_counters
  28672                             (unit, 0, EFP_POLICY_TABLEm, tcam_idx[idx]);
  28673                         BCM_IF_ERROR_RETURN(rv);
  28674                         f_ent_st->flags &= ~_FP_ENTRY_EXTENDED_STAT_INSTALLED;
  28675                         f_ent_st->flags &= ~_FP_ENTRY_EXTENDED_STAT_RESERVED;
  28676                         f_st->hw_ref_count--;
  28677                     }
  28678                 }
  28679             }
  28680         }
  28681     }
  28682 #endif
  28683 
  28684 #if defined(BCM_HURRICANE3_SUPPORT)
  28685     /* Advanced flowcnt STAT counters reference count handled here. */
  28686     if ((f_ent->flags & _FP_ENTRY_INSTALLED) &&
  28687         (_BCM_FIELD_STAGE_LOOKUP == f_ent->fs->stage_id) &&
  28688         (soc_feature(unit, soc_feature_flowcnt))) {
  28689 
  28690         for (idx = 0; idx < parts_count; idx++) {
  28691             /* Read existing entry qualifiers from the HW. */
  28692             BCM_IF_ERROR_RETURN
  28693                 (_bcm_field_qual_tcam_key_mask_get(unit,
  28694                                                    f_ent + idx));
  28695 
  28696             f_ent_st = &((f_ent + idx)->statistic);
  28697             if (f_ent_st->flags & _FP_ENTRY_STAT_INSTALLED) {
  28698                 /* Read stat entity configuration. */
  28699                 BCM_IF_ERROR_RETURN
  28700                    (_bcm_field_stat_get(unit, f_ent_st->sid, &f_st));
  28701                 if (f_st->hw_ref_count > 0) {
  28702 
  28703                     /*
  28704                      * If this is the only entry using this stat, store the stat
  28705                      * values to retain on next attach.
  28706                      */
  28707                     if (1 == f_st->hw_ref_count) {
  28708                         int  i;
  28709                         for (i= 0; i < f_st->nstat; i++) {
  28710                             rv = _field_stat_value_get(unit, 0, f_st,
  28711                                     f_st->stat_arr[i],
  28712                                     f_st->stat_values + i);
  28713                             BCM_IF_ERROR_RETURN(rv);
  28714                         }
  28715                     }
  28716 
  28717                     BCM_IF_ERROR_RETURN(
  28718                                 _bcm_esw_flowcnt_object_table_detach(unit,
  28719                                 VFP_POLICY_TABLEm, tcam_idx[idx]));
  28720                     f_ent_st->flags &= ~_FP_ENTRY_STAT_INSTALLED;
  28721                     f_st->hw_ref_count--;
  28722                 }
  28723             }
  28724 
  28725         }
  28726     }
  28727 #endif
  28728 
  28729 
  28730 #if defined(BCM_TOMAHAWK_SUPPORT)
  28731     if ((f_ent->flags & _FP_ENTRY_INSTALLED) &&
  28732          ((_BCM_FIELD_STAGE_INGRESS == f_ent->fs->stage_id) ||
  28733           (_BCM_FIELD_STAGE_LOOKUP == f_ent->fs->stage_id))&&
  28734          (soc_feature(unit, soc_feature_advanced_flex_counter)) &&
  28735          (soc_feature(unit, soc_feature_field_multi_pipe_support))) {
  28736 
  28737         int update_stats = 1;
  28738 
  28739         if (f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) {
  28740            if (!(f_ent->statistic.flags & _FP_ENTRY_STAT_DIRTY)) {
  28741                update_stats = 0;
  28742            }
  28743         }
  28744 
  28745         if (update_stats) {
  28746         f_ent_st = &(f_ent->statistic);
  28747         if (f_ent_st->flags & _FP_ENTRY_STAT_INSTALLED) {
  28748 
  28749             soc_mem_t tcam_mem = INVALIDm;
  28750             soc_mem_t policy_mem = INVALIDm;
  28751 
  28752             /* Read stat entity configuration. */
  28753             rv = _bcm_field_stat_get(unit, f_ent_st->sid, &f_st);
  28754             BCM_IF_ERROR_RETURN(rv);
  28755 
  28756             if (f_st->hw_ref_count > 0) {
  28757 
  28758                 int policy_idx;
  28759 
  28760                /* If this is the only entry using this stat, store the stat
  28761                 * values to retain on next attach.
  28762                 */
  28763 
  28764                 if (0 == (f_st->hw_ref_count - 1)) {
  28765                     for (idx= 0; idx < f_st->nstat; idx++) {
  28766                         rv = _field_stat_value_get(unit, 0, f_st,
  28767                                                    f_st->stat_arr[idx],
  28768                                                    f_st->stat_values + idx);
  28769                         BCM_IF_ERROR_RETURN(rv);
  28770                     }
  28771                 }
  28772 
  28773                 /* (Intra Slice) Double Wide/ Triple wide modes, IFP_TCAM_WIDE
  28774                  * have 256 entries but IFP_POLICY_TABLE will have 512 entries.
  28775                  */
  28776                 if ((SOC_IS_TOMAHAWKX(unit)) &&
  28777                     (f_ent->fs->stage_id == _BCM_FIELD_STAGE_INGRESS) &&
  28778                     (!(f_ent->group->flags & _FP_GROUP_SPAN_SINGLE_SLICE) ||
  28779                         (f_ent->group->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)
  28780                        )) {
  28781                      policy_idx = tcam_idx[0] + (f_ent->fs->slice_number * 256);
  28782                 } else {
  28783                      policy_idx = tcam_idx[0];
  28784                 }
  28785 
  28786                 rv = _bcm_field_th_tcam_policy_mem_get(unit, f_ent,
  28787                                                        &tcam_mem, &policy_mem);
  28788                 BCM_IF_ERROR_RETURN(rv);
  28789 
  28790 
  28791                 /* Stats are attached to only first part of multiwide group.
  28792                  * So in calling stat detach for tcam_idx[0] is enough.
  28793                  */
  28794                 if ((soc_feature(unit, soc_feature_td3_style_fp)
  28795                     && (_BCM_FIELD_STAGE_INGRESS == f_ent->fs->stage_id))) {
  28796                         rv =
  28797                          _bcm_esw_stat_flex_detach_ingress_table_counters_sw(
  28798                                                     unit,
  28799                                                     policy_mem, 0,
  28800                                                     f_st->hw_mode,
  28801                                                     f_st->hw_index,
  28802                                                     f_st->pool_index);
  28803                 } else {
  28804                         rv = _bcm_esw_stat_flex_detach_ingress_table_counters(
  28805                                                                      unit,
  28806                                                                     policy_mem,
  28807                                                                     policy_idx);
  28808                 }
  28809                 BCM_IF_ERROR_RETURN(rv);
  28810                 f_ent_st->flags &= ~_FP_ENTRY_STAT_INSTALLED;
  28811                 f_st->hw_ref_count--;
  28812             }
  28813         }
  28814     }
  28815     }
  28816 #endif
  28817 
  28818     /* Remove deleted actions. */
  28819     rv = _field_invalid_actions_remove(unit, f_ent);
  28820     BCM_IF_ERROR_RETURN(rv);
  28821 
  28822     /* Allocate hw resources required for entry installation. */
  28823     rv = _field_hw_resources_alloc(unit, f_ent);
  28824     BCM_IF_ERROR_RETURN(rv);
  28825 
  28826     /* Move  all actions to the slice where meter resides. */
  28827     rv = _field_entry_actions_meter_slice_move(unit, f_ent, TRUE);
  28828     if (BCM_FAILURE(rv)) {
  28829         BCM_IF_ERROR_RETURN
  28830            (_field_hw_resources_free(unit, f_ent, _FP_ACTION_HW_FREE));
  28831         return (rv);
  28832     }
  28833 
  28834     /*
  28835      * For stages that support global meter pools, meters must be in
  28836      * same slice as counters. Move policer to counter slice if
  28837      * counters are in secondary slice.
  28838      */
  28839     rv = _field_entry_policer_stat_slice_move(unit, f_ent, TRUE);
  28840     if (BCM_FAILURE(rv)) {
  28841         BCM_IF_ERROR_RETURN
  28842             (_field_hw_resources_free(unit, f_ent, _FP_ACTION_HW_FREE));
  28843         return (rv);
  28844     }
  28845 
  28846     if (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXTERNAL) {
  28847         rv = _field_tcam_policy_external_reinstall(unit, f_ent);
  28848     }  else {
  28849         for (idx = parts_count - 1; idx >=0; idx--) {
  28850 
  28851             LOG_DEBUG(BSL_LS_BCM_FP,
  28852                       (BSL_META_U(unit,
  28853                        "FP(unit %d) vverb: Part:%x EntryDirty:%x"
  28854                        " ActionOnlyDirty:%x\n"), unit, idx,
  28855                        (f_ent[idx].flags & _FP_ENTRY_DIRTY),
  28856                        (f_ent[idx].flags & _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY)));
  28857 
  28858             /*
  28859              * For Trident FP_GM_FIELDS.VALID = 1 when used in paired mode
  28860              */
  28861             if (((!SOC_IS_TRIDENT2X(unit) && !SOC_IS_TITAN2PLUS(unit)))
  28862                 && (!soc_feature(unit, soc_feature_field_multi_pipe_support)) &&
  28863                 SOC_IS_TD_TT(unit) && (idx == 1) &&
  28864                 (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id)) {
  28865                 f_ent[idx].flags |= _FP_ENTRY_USES_IPBM_OVERLAY;
  28866             }
  28867 
  28868             /* Get entry tcam key/mask. */
  28869             rv = _bcm_field_qual_tcam_key_mask_get(unit, f_ent + idx);
  28870             if (BCM_FAILURE(rv)) {
  28871                 break;
  28872             }
  28873 
  28874             if (f_ent->statistic.flags & _FP_ENTRY_STAT_DIRTY) {
  28875                f_ent[idx].statistic.flags |= _FP_ENTRY_STAT_DIRTY;
  28876             }
  28877 
  28878             /* Install physical entry into primary slice */
  28879             rv = fc->functions.fp_tcam_policy_reinstall(unit, f_ent + idx,
  28880                                                       tcam_idx[idx]);
  28881             if (BCM_FAILURE(rv)) {
  28882                 break;
  28883             }
  28884 
  28885             f_ent[idx].flags &= ~_FP_ENTRY_DIRTY;
  28886             f_ent[idx].flags &= ~(_FP_ENTRY_POLICY_TABLE_ONLY_DIRTY);
  28887             f_ent[idx].statistic.flags &= ~_FP_ENTRY_STAT_DIRTY;
  28888 
  28889             if(NULL != f_ent[idx].tcam.key) {
  28890                 sal_free(f_ent[idx].tcam.key);
  28891             }
  28892 
  28893             if(NULL != f_ent[idx].tcam.mask) {
  28894                 sal_free(f_ent[idx].tcam.mask);
  28895             }
  28896 
  28897             f_ent[idx].tcam.key = f_ent[idx].tcam.mask = NULL;
  28898         }
  28899     }
  28900 
  28901     if (BCM_FAILURE(rv)) {
  28902         (void)_field_entry_actions_meter_slice_move(unit, f_ent, FALSE);
  28903         (void)_field_entry_policer_stat_slice_move(unit, f_ent, FALSE);
  28904         (void)_field_hw_resources_free(unit, f_ent, _FP_ACTION_HW_FREE);
  28905         return (rv);
  28906     }
  28907 
  28908     /* Move  all actions back to the primary slice . */
  28909     rv = _field_entry_actions_meter_slice_move(unit, f_ent, FALSE);
  28910     if (BCM_FAILURE(rv)) {
  28911         BCM_IF_ERROR_RETURN
  28912             (_field_hw_resources_free(unit, f_ent, _FP_ACTION_HW_FREE));
  28913         return (rv);
  28914     }
  28915 
  28916     /* Move policers to primary slice. */
  28917     rv = _field_entry_policer_stat_slice_move(unit, f_ent, FALSE);
  28918     if (BCM_FAILURE(rv)) {
  28919         BCM_IF_ERROR_RETURN
  28920             (_field_hw_resources_free(unit, f_ent, _FP_ACTION_HW_FREE));
  28921         return (rv);
  28922     }
  28923 
  28924 
  28925     /* Remove stale deleted actions. */
  28926     rv = _field_invalid_actions_remove(unit, f_ent);
  28927     BCM_IF_ERROR_RETURN(rv);
  28928 
  28929     /* In case of entry reinstall free previous installation hw resources. */
  28930     rv = _field_hw_resources_free(unit, f_ent, _FP_ACTION_OLD_RESOURCE_FREE);
  28931     if (BCM_FAILURE(rv)) {
  28932         BCM_IF_ERROR_RETURN
  28933             (_field_hw_resources_free(unit, f_ent, _FP_ACTION_HW_FREE));
  28934         return (rv);
  28935     }
  28936     return (BCM_E_NONE);
  28937 }
  28938 
  28939 /*
  28940  * Function:
  28941  *     bcm_field_find_free_index_in_slice
  28942  *
  28943  * Purpose:
  28944  *     Find free index near by current entry
  28945  *
  28946  * Parameters:
  28947  *     unit           - (IN) BCM device number.
  28948  *     f_ent_orig     - (IN) Current Entry
  28949  *     direction      - (OUT) Direction in which free index found
  28950  *     free_idx       - (OUT) Found free index
  28951  *
  28952  * Returns:
  28953  *     BCM_E_INTERNAL -> If free count in slice is zero
  28954  *     BCM_E_XXX
  28955  */
  28956 
  28957 STATIC int
  28958 _bcm_field_find_free_index_in_slice(int unit, _field_entry_t *f_ent_orig,
  28959         int *direction, uint32 *free_idx)
  28960 {
  28961     int iter = 0;
  28962     int idx = 0;
  28963 
  28964     idx =  f_ent_orig->slice_idx;
  28965 
  28966     if (0 == f_ent_orig->fs->free_count) {
  28967         return BCM_E_INTERNAL;
  28968     }
  28969 
  28970     for (iter = 0; iter < f_ent_orig->fs->entry_count; iter++) {
  28971         if (((idx + iter) <  f_ent_orig->fs->entry_count) &&
  28972                 (NULL == f_ent_orig->fs->entries[idx + iter])) {
  28973             *direction = _FP_ENTRY_MOVE_DOWN; /* Found Down side */
  28974             *free_idx = idx + iter;
  28975             break;
  28976         }
  28977         if (((idx - iter) >=  0) &&
  28978                 (NULL == f_ent_orig->fs->entries[idx - iter])) {
  28979             *direction = _FP_ENTRY_MOVE_UP; /* Found Up side */
  28980             *free_idx = idx - iter;
  28981             break;
  28982         }
  28983         if (((idx + iter) >=  f_ent_orig->fs->entry_count) && ((idx - iter) <=  0)) {
  28984             break;
  28985         }
  28986     }
  28987     return BCM_E_NONE;
  28988 }
  28989 
  28990 /*
  28991  * Function:
  28992  *    _bcm_field_slice_entry_compress
  28993  *
  28994  * Purpose:
  28995  *    Compress slice between Start and End TCAM indices
  28996  *
  28997  * Parameters:
  28998  *     unit           - (IN) BCM device number.
  28999  *     stage_fc       - (IN) Field Stage control structure
  29000  *     fg             - (IN) Field Group structure
  29001  *     start_tcam_idx - (IN) Index with hole towards which
  29002  *                           compress will be done
  29003  *     end_tcam_idx   - (IN) End Index for slice compress
  29004  *     direction      - (IN) direction(UP/DOWN) towards
  29005  *                           which compression will be done
  29006  *     first_free_idx - (OUT) Writes the first found free index
  29007  *                            after compression
  29008  *                            if first_free_idx is not NULL.
  29009  *
  29010  * Returns:
  29011  *     BCM_E_INTERNAL -> If start index is not NULL or end index is NULL
  29012  *     BCM_E_XXX
  29013  */
  29014 STATIC int
  29015 _bcm_field_slice_entry_compress(int unit, _field_stage_t *stage_fc, _field_group_t *fg,
  29016         int start_tcam_idx, int end_tcam_idx, int direction,
  29017         int *first_free_idx)
  29018 {
  29019     int               from_idx = 0;
  29020     int               to_idx = 0;
  29021     int               rv = BCM_E_NONE;
  29022     int               start_idx = 0;
  29023     int               end_idx = 0;
  29024     int               start_slice_numb = 0;
  29025     int               end_slice_numb = 0;
  29026     int               slice_numb = 0;
  29027     int               slice_idx = 0;
  29028     _field_slice_t    *fs = NULL;
  29029     _field_slice_t    *start_fs =  NULL;
  29030     _field_slice_t    *end_fs = NULL;
  29031 
  29032     if ((NULL == stage_fc) || (NULL == fg)) {
  29033         return BCM_E_PARAM;
  29034     }
  29035 
  29036     /* Getting starting slice number and starting slice offset */
  29037     rv = _bcm_field_tcam_idx_to_slice_offset (unit, stage_fc, fg->instance,
  29038             start_tcam_idx, &start_slice_numb,
  29039             &start_idx);
  29040     BCM_IF_ERROR_RETURN(rv);
  29041     /* Getting end slice number and ending slice offset */
  29042     rv = _bcm_field_tcam_idx_to_slice_offset (unit, stage_fc, fg->instance,
  29043             end_tcam_idx, &end_slice_numb,
  29044             &end_idx);
  29045     BCM_IF_ERROR_RETURN(rv);
  29046 
  29047     start_fs = stage_fc->slices[fg->instance] + start_slice_numb;
  29048     end_fs = stage_fc->slices[fg->instance] + end_slice_numb;
  29049 
  29050     fs = start_fs;
  29051 
  29052     /*
  29053      * Entry present in Start index is expected to be NULL as compression
  29054      * may overwrite the existing entry.
  29055      * Entry present in End index is expected to be not NULL as compression
  29056      * ends with end index compressing NULL entry can't be done.
  29057      */
  29058     if ((start_fs->entries[start_idx] != NULL) || (end_fs->entries[end_idx] == NULL)) {
  29059         LOG_DEBUG(BSL_LS_BCM_FP,
  29060                 (BSL_META_U(unit,
  29061                             "FP(unit %d) Wrong index provided to compress \n"),
  29062                  unit));
  29063         return BCM_E_INTERNAL;
  29064     }
  29065 
  29066     /*************************************************************************************************
  29067       Compression logic explained
  29068       ---------------------------
  29069 Direction         :  _FP_ENTRY_MOVE_DOWN
  29070 Start TCAm index  :  7
  29071 End TCAM idx      :  2
  29072 
  29073 1.
  29074 ______
  29075 |______|1
  29076 |______|2 ==> End TCAM index
  29077 |______|3
  29078 |______|4
  29079 |______|5
  29080 |______|6
  29081 |_NULL_|7 ==> Start TCAM index
  29082 |______|8
  29083 
  29084 Entry@6 will be copied to 7.
  29085 then entry@5 will be copied to 6.......
  29086 and ends with entry@2 copy to 3.
  29087 ______                ______
  29088 |______|1             |______|1
  29089 |______|2             |_NULL_|2 ==> first found free index
  29090 |______|3             |______|3
  29091 |______|4     ....>   |______|4
  29092 |______|5     ....>   |______|5
  29093 |_NULL_|6             |______|6
  29094 |______|7 <--         |______|7
  29095 |______|8             |______|8
  29096 
  29097 and first free index will be assigned to 2
  29098 if first_free_idx is not NULL ptr.
  29099 
  29100 2.
  29101 ______
  29102 |______|1
  29103 |______|2 ==> End TCAM index
  29104 |______|3
  29105 |_NULL_|4
  29106 |_NULL_|5
  29107 |______|6
  29108 |_NULL_|7 ==> Start TCAM index
  29109 |______|8
  29110 
  29111 
  29112 Entry@6 will be copied to 7.
  29113 Entry@5 is NULL and entry@4 is also NULL
  29114 so entry@3 will be copied to 6
  29115 and then entry@2 is copied to 5.
  29116 
  29117 ______                ______
  29118 |______|1             |______|1
  29119 |______|2             |_NULL_|2
  29120 |______|3             |_NULL_|3
  29121 |_NULL_|4     ....>   |_NULL_|4 ==> first found free index
  29122 |_NULL_|5     ....>   |______|5
  29123 |_NULL_|6             |______|6
  29124 |______|7 <--         |______|7
  29125 |______|8             |______|8
  29126 
  29127 and first free index will be assigned to 4
  29128 if first_free_idx is not NULL ptr.
  29129 
  29130      */
  29131     if (direction == _FP_ENTRY_MOVE_DOWN) {
  29132         /* free index found in down direction slice has to be compressed towards down */
  29133         for (slice_idx = start_idx - 1, to_idx = start_tcam_idx, from_idx = start_tcam_idx - 1;
  29134                 from_idx >= end_tcam_idx; from_idx--, slice_idx-- ) {
  29135             if (-1 == slice_idx) {
  29136                 rv = _bcm_field_tcam_idx_to_slice_offset (unit, stage_fc, fg->instance,
  29137                         from_idx, &slice_numb,
  29138                         &slice_idx);
  29139                 BCM_IF_ERROR_RETURN(rv);
  29140                 if (slice_numb != fs->slice_number) {
  29141                     /* if compression is across slices end TCAM index will be in previous slice */
  29142                     fs = fs->prev;
  29143                 }
  29144             }
  29145             if (NULL == fs->entries[slice_idx]) {
  29146                 /* Ignore holes*/
  29147                 continue;
  29148             }
  29149             rv = _field_entry_move(unit, fs->entries[slice_idx], (to_idx - from_idx));
  29150             BCM_IF_ERROR_RETURN(rv);
  29151             to_idx--;
  29152         }   /*End of For*/
  29153         if (NULL != first_free_idx) {
  29154             *first_free_idx= to_idx;
  29155         }
  29156     }    else if (direction & _FP_ENTRY_MOVE_UP) {
  29157         /* free index found in up direction slice has to be compressed towards up */
  29158         for (slice_idx = start_idx + 1, to_idx = start_tcam_idx, from_idx = start_tcam_idx + 1;
  29159                 from_idx <= end_tcam_idx; from_idx++, slice_idx++ ) {
  29160             if (fs->entry_count == slice_idx) {
  29161                 rv = _bcm_field_tcam_idx_to_slice_offset (unit, stage_fc, fg->instance,
  29162                         from_idx, &slice_numb,
  29163                         &slice_idx);
  29164                 BCM_IF_ERROR_RETURN(rv);
  29165                 if (slice_numb != fs->slice_number) {
  29166                     /* if compression is across slices end TCAM index will be in next slice */
  29167                     fs = fs->next;
  29168                 }
  29169             }
  29170             if (NULL == fs->entries[slice_idx]) {
  29171                 /* Ignore holes*/
  29172                 continue;
  29173             }
  29174             rv = _field_entry_move(unit, fs->entries[slice_idx], (to_idx - from_idx));
  29175             BCM_IF_ERROR_RETURN(rv);
  29176             to_idx++;
  29177         }/*End of For*/
  29178         if (NULL != first_free_idx) {
  29179             *first_free_idx= to_idx;
  29180         }
  29181     } else {
  29182         return BCM_E_INTERNAL;
  29183     }
  29184     return BCM_E_NONE;
  29185 }
  29186 /*
  29187  * Function:
  29188  *     _field_internal_backup_entry_create
  29189  *
  29190  * Purpose:
  29191  *     To achieve hitless update by
  29192  *     creating a temporary entry during
  29193  *     current entry modification.
  29194  *     TCAM and FP_POLICY_TABLEs will be
  29195  *     copied from orginal entry to the
  29196  *     temperary entry and
  29197  *     New Hardware won't be allocated for
  29198  *     Temperary entry.
  29199  *
  29200  * Parameters:
  29201  *     unit  - (IN) BCM device number.
  29202  *     entry - (IN) Current Entry
  29203  *     temp_entry - (OUT) Entry to be installed.
  29204  *
  29205  * Returns:
  29206  *     BCM_E_XXX
  29207  */
  29208 STATIC int
  29209 _field_internal_backup_entry_create(int unit, bcm_field_entry_t entry,
  29210                                     bcm_field_entry_t *temp_entry)
  29211 {
  29212     int                 rv = BCM_E_NONE;            /* Return Variable */
  29213     int  tcam_idx_orig[_FP_MAX_ENTRY_WIDTH] = {0};  /* Original entry tcam index. */
  29214     int  tcam_idx_temp[_FP_MAX_ENTRY_WIDTH] = {0};  /* temp tcam index for the entry.*/
  29215     int                 idx;
  29216     int                 parts_count = 0;            /* Field entry parts count.  */
  29217     int                 direction = 0;
  29218     int                 free_idx_after_compress = 0;
  29219     int                 start_tcam_idx = 0;
  29220     int                 end_tcam_idx = 0;
  29221     uint32              free_idx = 0;
  29222     uint32              start_idx = 0;
  29223     uint32              end_idx = 0;
  29224     _field_stage_t      *stage_fc = NULL;        /* Stage field control structure */
  29225     _field_control_t    *fc = NULL;              /* Field control structure.      */
  29226     _field_entry_t      *f_ent_temp = NULL;
  29227     _field_entry_t      *f_ent_copy_temp = NULL;
  29228     _field_entry_t      *f_ent_orig = NULL;
  29229 
  29230     LOG_DEBUG(BSL_LS_BCM_FP,
  29231             (BSL_META_U(unit,
  29232                         "FP(unit %d) vverb: _field_internal_backup_entry_create (%d)\n"),
  29233              unit, entry));
  29234     /* Check whether entry with INTERNAL_RESERVED_ID is  already present */
  29235     if (BCM_SUCCESS(_field_entry_get(unit, (_FP_INTERNAL_RESERVED_ID),
  29236                     _FP_ENTRY_PRIMARY,
  29237                     &f_ent_temp))) {
  29238         LOG_DEBUG(BSL_LS_BCM_FP,
  29239                 (BSL_META_U(unit,
  29240                             "FP(unit %d) Error: "
  29241                             "Entry _FP_INTERNAL_RESERVED_ID already present"
  29242                             "Unable to create backup entry for entry (%d)\n"),
  29243                  unit, entry));
  29244         return BCM_E_EXISTS;
  29245     }
  29246 
  29247     /* Get the original entry */
  29248     BCM_IF_ERROR_RETURN(_field_entry_get(unit, entry,
  29249                 _FP_ENTRY_PRIMARY,
  29250                 &f_ent_orig));
  29251 
  29252     /* Get field and stage control structures. */
  29253     BCM_IF_ERROR_RETURN (_field_control_get(unit, &fc));
  29254     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, f_ent_orig->group->stage_id, &stage_fc));
  29255 
  29256     *temp_entry = (_FP_INTERNAL_RESERVED_ID);
  29257     /* Create backup entry sharing
  29258        the same group with original entry */
  29259     rv = _field_entry_create_id (unit,
  29260             f_ent_orig->group->gid,
  29261             *temp_entry);
  29262     /* Fall back to old method if new entry has no space */
  29263     if (BCM_FAILURE(rv)) {
  29264         if ((rv == BCM_E_RESOURCE) && ((soc_property_get(unit,
  29265                             spn_FIELD_ATOMIC_UPDATE, FALSE) == TRUE))) {
  29266             return rv;
  29267         }
  29268         goto fallback;
  29269     }
  29270 
  29271     if (!(f_ent_orig->flags & _FP_ENTRY_CREATED_WITHOUT_PRIO)) {
  29272         rv = _field_entry_prio_set(unit, *temp_entry, f_ent_orig->prio);
  29273         if (BCM_FAILURE(rv)) {
  29274             LOG_DEBUG(BSL_LS_BCM_FP,
  29275                     (BSL_META_U(unit,
  29276                                 "FP(unit %d) Error: "
  29277                                 "Unable to create backup entry for entry (%d)"
  29278                                 "Entry prio set failed with error %d \n"),
  29279                      unit, entry, rv));
  29280             goto fallback;
  29281         }
  29282     }
  29283     /* Get created backup entry*/
  29284     rv =  _field_entry_get(unit, *temp_entry,
  29285             _FP_ENTRY_PRIMARY,
  29286             &f_ent_temp);
  29287     if (BCM_FAILURE(rv)) {
  29288         LOG_DEBUG(BSL_LS_BCM_FP,
  29289                 (BSL_META_U(unit,
  29290                             "FP(unit %d) Error: "
  29291                             "Unable to create backup entry for entry (%d)"
  29292                             "backup entry get failed with error %d \n"),
  29293                  unit, entry, rv));
  29294         rv = BCM_E_INTERNAL;
  29295         goto fallback;
  29296     }
  29297     /* Get number of parts. */
  29298     rv = _bcm_field_entry_tcam_parts_count (unit, f_ent_orig->group->stage_id,
  29299             f_ent_orig->group->flags, &parts_count);
  29300     if (BCM_FAILURE(rv)) {
  29301         LOG_DEBUG(BSL_LS_BCM_FP,
  29302                 (BSL_META_U(unit,
  29303                             "FP(unit %d) Error: "
  29304                             "Unable to create backup entry for entry (%d)"
  29305                             "Getting Parts count for original entry failed with error : %d"),
  29306                  unit, entry, rv));
  29307         rv = BCM_E_INTERNAL;
  29308         goto fallback;
  29309     }
  29310     /* backup entry and original entry entry are not in same slice*/
  29311     if (f_ent_orig->fs->slice_number != f_ent_temp->fs->slice_number) {
  29312         /* Check for the global Policers and Statistics associated with the entry. */
  29313         /* Global policer and Installed ||  Global Stats and installed */
  29314         if(((0 == (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)) &&
  29315                     ((f_ent_orig->policer[0].flags & _FP_POLICER_INSTALLED) ||
  29316                      (f_ent_orig->policer[1].flags & _FP_POLICER_INSTALLED))) ||
  29317                 ((0 == ((stage_fc->flags & _FP_STAGE_GLOBAL_COUNTERS) ||
  29318                         (stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS))) &&
  29319                  (f_ent_orig->statistic.flags & _FP_ENTRY_STAT_INSTALLED))) {
  29320             if (0 == f_ent_orig->fs->free_count) {
  29321                 LOG_DEBUG(BSL_LS_BCM_FP,
  29322                         (BSL_META_U(unit,
  29323                                     "FP(unit %d) Error: "
  29324                                     "Unable to create backup entry for entry (%d)"
  29325                                     "No free space in original entry slice\n"),
  29326                          unit, entry));
  29327                 rv = BCM_E_CONFIG;
  29328                 goto fallback;
  29329             }
  29330 
  29331             /* Find the nearest free index to the original entry and direction */
  29332             rv = _bcm_field_find_free_index_in_slice (unit, f_ent_orig, &direction, &free_idx);
  29333             if (BCM_FAILURE(rv)) {
  29334                 LOG_DEBUG(BSL_LS_BCM_FP,
  29335                         (BSL_META_U(unit,
  29336                                     "FP(unit %d) Error: "
  29337                                     "Unable to create backup entry for entry (%d)"
  29338                                     "Finding free idx failed with error : %d\n"),
  29339                          unit, entry, rv));
  29340                 rv = BCM_E_INTERNAL;
  29341                 goto fallback;
  29342             }
  29343 
  29344             start_idx = free_idx;
  29345             /*
  29346              * keep the orginal entry stable and move in between entries
  29347              * from free index and original entry index
  29348              */
  29349             end_idx = (_FP_ENTRY_MOVE_UP == direction) ?
  29350                           (f_ent_orig->slice_idx - 1) :
  29351                           (f_ent_orig->slice_idx + 1);
  29352             if (start_idx != end_idx) {
  29353                 /* Get Start TCAM index based on start slice offset */
  29354                 rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc,
  29355                         f_ent_orig->group->instance,
  29356                         f_ent_orig->fs->slice_number,
  29357                         start_idx, &start_tcam_idx);
  29358                 if (BCM_FAILURE(rv)) {
  29359                     LOG_DEBUG(BSL_LS_BCM_FP,
  29360                         (BSL_META_U(unit,
  29361                                 "FP(unit %d) Error: "
  29362                                 "Unable to create backup entry for entry (%d)"
  29363                                 "slice compress failed with error %d \n"),
  29364                          unit, entry, rv));
  29365                     rv = BCM_E_INTERNAL;
  29366                     goto fallback;
  29367                 }
  29368                 /* Get end TCAM index based on end slice offset */
  29369                 rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc,
  29370                          f_ent_orig->group->instance,
  29371                          f_ent_orig->fs->slice_number,
  29372                          end_idx, &end_tcam_idx);
  29373                 if (BCM_FAILURE(rv)) {
  29374                     LOG_DEBUG(BSL_LS_BCM_FP,
  29375                         (BSL_META_U(unit,
  29376                                 "FP(unit %d) Error: "
  29377                                 "Unable to create backup entry for entry (%d)"
  29378                                 "slice compress failed with error %d \n"),
  29379                          unit, entry, rv));
  29380                     rv = BCM_E_INTERNAL;
  29381                     goto fallback;
  29382                 }
  29383                 /* Compress slice towards the free index and
  29384                  * make hole near by original entry
  29385                  */
  29386                 rv = _bcm_field_slice_entry_compress (unit,
  29387                          stage_fc, f_ent_orig->group,
  29388                          start_tcam_idx, end_tcam_idx, direction,
  29389                          &free_idx_after_compress);
  29390                 if (BCM_FAILURE(rv)) {
  29391                     LOG_DEBUG(BSL_LS_BCM_FP,
  29392                         (BSL_META_U(unit,
  29393                                 "FP(unit %d) Error: "
  29394                                 "Unable to create backup entry for entry (%d)"
  29395                                 "slice compress failed with error %d \n"),
  29396                          unit, entry, rv));
  29397                     rv = BCM_E_INTERNAL;
  29398                     goto fallback;
  29399                 }
  29400             } else {
  29401                 rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc,
  29402                         f_ent_orig->group->instance,
  29403                         f_ent_orig->fs->slice_number,
  29404                         start_idx, &start_tcam_idx);
  29405                 if (BCM_FAILURE(rv)) {
  29406                     LOG_DEBUG(BSL_LS_BCM_FP,
  29407                         (BSL_META_U(unit,
  29408                                 "FP(unit %d) Error: "
  29409                                 "Unable to create backup entry for entry (%d)"
  29410                                 "slice compress failed with error %d \n"),
  29411                          unit, entry, rv));
  29412                     rv = BCM_E_INTERNAL;
  29413                     goto fallback;
  29414                 }
  29415                 free_idx_after_compress = start_tcam_idx;
  29416             }
  29417 
  29418 
  29419             /* Get the tcam_idx for all parts of backup entry using
  29420              * free_idx_after_compress
  29421              */
  29422             for (idx = 0; idx < parts_count; idx++) {
  29423                 rv = _bcm_field_entry_part_tcam_idx_get(unit, f_ent_temp,
  29424                                                 free_idx_after_compress,
  29425                                                 idx, &tcam_idx_temp[idx]);
  29426                 if (BCM_FAILURE(rv)) {
  29427                     LOG_DEBUG(BSL_LS_BCM_FP,
  29428                         (BSL_META_U(unit,
  29429                             "FP(unit %d) Error: "
  29430                             "Unable to create backup entry for entry (%d)"
  29431                             "tcam idx get failed for part %d "
  29432                             "with rv %d \n"),
  29433                          unit, entry, idx, rv));
  29434                     rv = BCM_E_INTERNAL;
  29435                     goto fallback;
  29436                 }
  29437             }
  29438             /* change slice index of backup entry to the
  29439              * tcam_idx_temp after compres
  29440              */
  29441             rv = _field_entry_slice_idx_change (unit,
  29442                      f_ent_temp, parts_count,tcam_idx_temp);
  29443             if (BCM_FAILURE(rv)) {
  29444                 LOG_DEBUG(BSL_LS_BCM_FP,
  29445                    (BSL_META_U(unit,
  29446                             "FP(unit %d) Error: "
  29447                             "Unable to create backup entry for entry (%d)"
  29448                             "backup entry slice idx change to the found "
  29449                             "free idx failed with error %d \n"),
  29450                     unit, entry, rv));
  29451                 rv = BCM_E_INTERNAL;
  29452                 goto fallback;
  29453             }
  29454         }
  29455     }
  29456     /* Calculate the new and old TCAM indexes. */
  29457     for (idx = 0; idx < parts_count; idx++) {
  29458         /* Calculate the new and old TCAM indexes. */
  29459         rv = _bcm_field_entry_tcam_idx_get(unit, f_ent_orig + idx,
  29460                  &tcam_idx_orig[idx]);
  29461         if (BCM_FAILURE(rv)) {
  29462             LOG_DEBUG(BSL_LS_BCM_FP,
  29463                     (BSL_META_U(unit,
  29464                         "FP(unit %d) Error: "
  29465                         "Unable to create backup entry for entry (%d)"
  29466                         "TCAM index get for orig entry failed "
  29467                         "with error %d \n"),
  29468                          unit, entry, rv));
  29469             rv = BCM_E_INTERNAL;
  29470             goto fallback;
  29471         }
  29472         rv = _bcm_field_entry_tcam_idx_get(unit, f_ent_temp + idx,
  29473                  &tcam_idx_temp[idx]);
  29474         if (BCM_FAILURE(rv)) {
  29475             LOG_DEBUG(BSL_LS_BCM_FP,
  29476                     (BSL_META_U(unit,
  29477                         "FP(unit %d) Error: "
  29478                         "Unable to create backup entry for entry (%d)"
  29479                         "TCAM index get for backup entry failed "
  29480                         "with error %d \n"),
  29481                         unit, entry, rv));
  29482             rv = BCM_E_INTERNAL;
  29483             goto fallback;
  29484         }
  29485     }
  29486     /* store orginal entry's ent_copy*/
  29487     f_ent_copy_temp = f_ent_orig->ent_copy;
  29488     /*
  29489      * Assign backup entry to the ent_copy as fp_entry_move
  29490      * should not clear FP_TCAM and FP_POLICY_TABLE of original entry
  29491      */
  29492     f_ent_orig->ent_copy = f_ent_temp;
  29493 
  29494     rv = fc->functions.fp_entry_move(unit, f_ent_orig, parts_count,
  29495             tcam_idx_orig, tcam_idx_temp);
  29496     if (BCM_FAILURE(rv)) {
  29497         LOG_DEBUG(BSL_LS_BCM_FP,
  29498                 (BSL_META_U(unit,
  29499                             "FP(unit %d) Error: "
  29500                             "Unable to create backup entry for entry (%d)"
  29501                             "hw entry move failed with error %d \n"),
  29502                  unit, entry, rv));
  29503         rv = BCM_E_INTERNAL;
  29504     }
  29505 
  29506     f_ent_temp->flags |= _FP_ENTRY_INSTALLED;
  29507     f_ent_temp->flags |= _FP_ENTRY_ENABLED;
  29508     f_ent_orig->ent_copy = f_ent_copy_temp;
  29509 
  29510 fallback:
  29511     /*Common cleanup for the method */
  29512     if (BCM_FAILURE(rv)) {
  29513         /* Remove the created backup entry upon failure */
  29514         BCM_IF_ERROR_RETURN(_field_internal_backup_entry_delete(unit, *temp_entry));
  29515 
  29516         if (BCM_E_INTERNAL == rv) {
  29517             return rv;
  29518         }
  29519 
  29520         /* Fall back to old method */
  29521         if (soc_property_get(unit,
  29522                     spn_FIELD_ATOMIC_UPDATE, FALSE) == FALSE) {
  29523             LOG_DEBUG(BSL_LS_BCM_FP,
  29524                     (BSL_META_U(unit,
  29525                                 "FP(unit %d) Error: "
  29526                                 "Unable to create backup entry for entry (%d)"
  29527                                 "Falling back to old method \n"),
  29528                      unit, entry));
  29529             rv = BCM_E_NONE;
  29530             *temp_entry = _FP_INVALID_INDEX;
  29531         }
  29532         return rv;
  29533     }
  29534     return BCM_E_NONE;
  29535 }
  29536 
  29537 /*
  29538  * Function:
  29539  *     _field_internal_backup_entry_delete
  29540  *
  29541  * Purpose:
  29542  *     Delete temporary entry created during
  29543  *     current entry modification
  29544  *     to achieve hitless update.
  29545  *
  29546  * Parameters:
  29547  *     unit  - (IN) BCM device number.
  29548  *     temp_entry - (IN) Entry to be installed.
  29549  *
  29550  * Returns:
  29551  *     BCM_E_XXX
  29552  */
  29553 STATIC int
  29554 _field_internal_backup_entry_delete(int unit, bcm_field_entry_t temp_entry)
  29555 {
  29556     int                 rv = BCM_E_NONE;        /* Return Variable */
  29557     _field_entry_t      *f_ent_check = NULL ;   /* Field entry pointer */
  29558 
  29559     if (BCM_SUCCESS(_field_entry_get(unit, temp_entry, _FP_ENTRY_PRIMARY,
  29560                     &f_ent_check))) {
  29561         rv = bcm_esw_field_entry_destroy(unit, temp_entry);
  29562     }
  29563     return (rv);
  29564 }
  29565 
  29566 /*
  29567  * Function:
  29568  *  _bcm_field_meter_rate_burst_calculate
  29569  *
  29570  * Purpose:
  29571  *  Calculate rate and burst of the meter based on
  29572  *  granularity, refresh_rate and bucket size.
  29573  *
  29574  * Parameters:
  29575  *  unit  - (IN) BCM device number.
  29576  *  meter_mem - (IN) Meter table to read
  29577  *  meter_hw_idx - (IN) Index in the meter table
  29578  *  flags - (IN) Policer flags.
  29579  *  prate - (OUT) Policer rate calculated
  29580  *  pburst - (OUT) Policer burst calculated
  29581  *
  29582  * Returns:
  29583  * BCM_E_XXX
  29584  */
  29585 STATIC int
  29586 _bcm_field_meter_rate_burst_calculate (uint32 unit,
  29587         soc_mem_t meter_mem,
  29588         uint32 meter_hw_idx,
  29589         uint32 *prate,
  29590         uint32 *pburst,
  29591         uint32 flags
  29592         )
  29593 {
  29594     uint32 ent[SOC_MAX_MEM_FIELD_WORDS];    /* HW entry buffer.         */
  29595     uint32 refresh_rate = 0;                /* Policer refresh rate.    */
  29596     uint32 granularity = 0;                 /* Policer granularity.     */
  29597     uint32 bucket_max = 0;                  /* Bucket size.             */
  29598 
  29599     BCM_IF_ERROR_RETURN(soc_mem_read(unit, meter_mem, MEM_BLOCK_ANY,
  29600                 meter_hw_idx, ent));
  29601 
  29602     refresh_rate = soc_mem_field32_get(unit, meter_mem, ent, REFRESHCOUNTf);
  29603     granularity = soc_mem_field32_get(unit, meter_mem, ent, METER_GRANf);
  29604     bucket_max = soc_mem_field32_get(unit, meter_mem, ent, BUCKETSIZEf);
  29605 
  29606     BCM_IF_ERROR_RETURN(_bcm_xgs_bucket_encoding_to_kbits
  29607             (refresh_rate, bucket_max, granularity, flags,
  29608              prate, pburst));
  29609 
  29610     return BCM_E_NONE;
  29611 }
  29612 
  29613 /*
  29614  * Function:
  29615  *     _field_entry_policer_update_actual_hw_rates
  29616  *
  29617  * Purpose:
  29618  *     Update actual hardware rates for committed packet rate
  29619  *     and burst size and peak packet rate and burst size in
  29620  *     the internal policer structure.
  29621  *
  29622  * Parameters:
  29623  *     unit  - (IN) BCM device number.
  29624  *     policer_mem - (IN) Meter table name.
  29625  *     instance - (IN) FP instance
  29626  *     f_ent   - (IN) Entry policer belongs to.
  29627  *     f_pl - (IN) Field policer descriptor.
  29628  *
  29629  * Returns:
  29630  *     BCM_E_XXX
  29631  */
  29632 int
  29633 _field_entry_policer_update_actual_hw_rates(int unit, soc_mem_t policer_mem,
  29634         int instance, _field_entry_t *f_ent, _field_policer_t *f_pl)
  29635 {
  29636     uint32  flags;                          /* Policer flags.           */
  29637     _field_stage_t *stage_fc;               /* Field stage information. */
  29638     int meter_hw_idx;                       /* Meter table index.       */
  29639     int rv = BCM_E_NONE;                    /* Operation return status. */
  29640     soc_mem_t   meter_mem = policer_mem;    /* Meter table name.        */
  29641     int meter_offset = 0;                   /* Odd or even meter.       */
  29642     _field_stage_id_t      stage_id;        /* StageId used for metering*/
  29643 
  29644     if ((f_pl == NULL) || (f_ent == NULL)) {
  29645         return BCM_E_PARAM;
  29646     }
  29647 
  29648     if (meter_mem == INVALIDm) {
  29649         return BCM_E_PARAM;
  29650     }
  29651 
  29652     stage_id = ((_BCM_FIELD_STAGE_EXACTMATCH == f_ent->group->stage_id) ||
  29653                 (_BCM_FIELD_STAGE_EXTERNAL == f_ent->group->stage_id)) ? \
  29654                _BCM_FIELD_STAGE_INGRESS : f_ent->group->stage_id;
  29655 
  29656     /* Get stage control */
  29657     rv = _field_stage_control_get(unit, stage_id, &stage_fc);
  29658     BCM_IF_ERROR_RETURN(rv);
  29659 
  29660     if (f_pl->cfg.mode == bcmPolicerModeCommitted) {
  29661         if (_FP_POLICER_EXCESS_HW_METER(f_pl)) {
  29662             meter_offset = 0;
  29663         }
  29664         else {
  29665             meter_offset = 1;
  29666         }
  29667     }
  29668 
  29669     /* Calculate hardware meter index. */
  29670     if (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) {
  29671         /*
  29672          * Hw index is:
  29673          * ((Pool number * pool_size) + (2 * pair number)
  29674          */
  29675         meter_hw_idx = (f_pl->pool_index *
  29676                 stage_fc->meter_pool[instance][f_pl->pool_index]->size)
  29677             + (2 * f_pl->hw_index) + meter_offset;
  29678     } else {
  29679         /*
  29680          * Hw index is:
  29681          * (slice index) + (2 * pair number)
  29682          */
  29683         meter_hw_idx =
  29684             stage_fc->slices[instance][f_pl->pool_index].start_tcam_idx
  29685             + (2 * f_pl->hw_index) + meter_offset;
  29686     }
  29687 
  29688     /* lookup bucket size from tables */
  29689     flags = _BCM_XGS_METER_FLAG_GRANULARITY | _BCM_XGS_METER_FLAG_FP_POLICER;
  29690 
  29691     /* TD2 has change in granularity calculation */
  29692     if ((SOC_IS_TD2_TT2(unit)) &&
  29693         (f_pl->cfg.flags & BCM_POLICER_MODE_PACKETS)) {
  29694         flags = flags | _BCM_XGS_METER_FLAG_FP_TD2_POLICER;
  29695     }
  29696 
  29697     /* Set packet mode flags setting */
  29698     if (f_pl->cfg.flags & BCM_POLICER_MODE_PACKETS) {
  29699         flags |= _BCM_XGS_METER_FLAG_PACKET_MODE;
  29700     } else {
  29701         flags &= ~_BCM_XGS_METER_FLAG_PACKET_MODE;
  29702     }
  29703 
  29704     f_pl->cfg.actual_ckbits_sec = 0;
  29705     f_pl->cfg.actual_ckbits_burst = 0;
  29706     f_pl->cfg.actual_pkbits_sec = 0;
  29707     f_pl->cfg.actual_pkbits_burst = 0;
  29708 
  29709     if ((f_pl->cfg.mode == bcmPolicerModeTrTcmDs) ||
  29710             (f_pl->cfg.mode == bcmPolicerModeTrTcm)||
  29711             (f_pl->cfg.mode == bcmPolicerModeSrTcm) ||
  29712         (f_pl->cfg.mode == bcmPolicerModeSrTcmTsn) ||
  29713             (f_pl->cfg.mode == bcmPolicerModeSrTcmModified) ||
  29714             (f_pl->cfg.mode == bcmPolicerModeCoupledTrTcmDs)){
  29715         _bcm_field_meter_rate_burst_calculate(unit, meter_mem,
  29716                 meter_hw_idx, &f_pl->cfg.actual_pkbits_sec,
  29717                 &f_pl->cfg.actual_pkbits_burst, flags);
  29718         _bcm_field_meter_rate_burst_calculate(unit, meter_mem,
  29719                 meter_hw_idx + 1, &f_pl->cfg.actual_ckbits_sec,
  29720                 &f_pl->cfg.actual_ckbits_burst, flags);
  29721     }
  29722     else {
  29723         _bcm_field_meter_rate_burst_calculate(unit, meter_mem,
  29724                 meter_hw_idx, &f_pl->cfg.actual_ckbits_sec,
  29725                 &f_pl->cfg.actual_ckbits_burst, flags);
  29726     }
  29727 
  29728     /* In Tomahawk EFP metering, Refresh tick duration has changed from
  29729      * 7.8125us to 15.625us ,but the RTL does not double the REFRESHCOUNT
  29730      * while putting the tokens into the bucket which is causing 50% lesser
  29731      * traffic rate than expected. So the work around is the value programmed
  29732      * from software in EFP meters needs to be doubled.
  29733      */
  29734     if (soc_feature(unit, soc_feature_field_multi_pipe_support)
  29735         && (_BCM_FIELD_STAGE_EGRESS == stage_fc->stage_id)) {
  29736         f_pl->cfg.actual_ckbits_sec = (f_pl->cfg.actual_ckbits_sec / 2) ;
  29737         f_pl->cfg.actual_pkbits_sec = (f_pl->cfg.actual_pkbits_sec / 2) ;
  29738     }
  29739 
  29740     return BCM_E_NONE;
  29741 }
  29742 
  29743 /*
  29744  * Function:
  29745  *     _field_tcam_policy_install
  29746  *
  29747  * Purpose:
  29748  *     Install a combined TCAM and POLICY_TABLE entry. This writes the
  29749  *     qualifiers and actions to the hardware.
  29750  *
  29751  * Parameters:
  29752  *     unit  - (IN) BCM device number.
  29753  *     entry - (IN) Entry to be installed.
  29754  * Returns:
  29755  *     BCM_E_XXX
  29756  */
  29757 int
  29758 _field_tcam_policy_install(int unit, bcm_field_entry_t entry)
  29759 {
  29760     int                 tcam_idx[_FP_MAX_ENTRY_WIDTH]; /* Entry tcam index. */
  29761     int                 parts_count = 0;       /* Field entry parts count.  */
  29762     _field_entry_t      *f_ent;                /* Field entry pointer.      */
  29763     _field_control_t    *fc;                   /* Field control structure.  */
  29764     int                 idx;                   /* Iteration index.          */
  29765     int                 rv;                    /* Operation return status.  */
  29766 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
  29767     defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT)
  29768     _field_entry_stat_t  *f_ent_st=NULL; /* Field entry statistics structure. */
  29769     _field_stat_t        *f_st=NULL;     /* Statistics entity descriptor.     */
  29770 #endif
  29771     bcm_field_entry_t    temp_entry = _FP_INVALID_INDEX;
  29772                                          /* Entry id for internal backup entry*/
  29773     int slice_count = 0;                 /* count of slices attached to group */
  29774     int slice_count_updated = 0;         /* count of slices attached to group
  29775                                             after internal backup entry */
  29776     _field_slice_t *fs = NULL;           /* Field Slice Structure */
  29777 
  29778     LOG_DEBUG(BSL_LS_BCM_FP,
  29779             (BSL_META_U(unit,
  29780                         "FP(unit %d) vverb: bcm_field_policy_install (%d)\n"),
  29781              unit, entry));
  29782 
  29783     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  29784 
  29785     /* Installing the entry. */
  29786     rv = _bcm_field_entry_get_by_id(unit, entry, &f_ent);
  29787     BCM_IF_ERROR_RETURN(rv);
  29788 
  29789 #if defined(BCM_TRX_SUPPORT)
  29790     if (BCM_FIELD_QSET_TEST(f_ent->group->qset, bcmFieldQualifyInPorts) &&
  29791             (!soc_feature(unit, soc_feature_field_multi_pipe_support)) &&
  29792             (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id)) {
  29793 
  29794         /*
  29795          * Re-Check whether InPorts has ports other than fg->pbmp
  29796          * To confirm existing ports from fg->pbmp were not removed
  29797          * using bcm_field_group_ports_remove.
  29798          */
  29799         bcm_pbmp_t temp_pbm;
  29800 
  29801         BCM_PBMP_ASSIGN(temp_pbm, f_ent->pbmp.data);
  29802         BCM_PBMP_OR(temp_pbm, f_ent->group->pbmp);
  29803         if (BCM_PBMP_NEQ(temp_pbm, f_ent->group->pbmp)) {
  29804         LOG_ERROR(BSL_LS_BCM_FP,
  29805                   (BSL_META_U(unit,
  29806                               "FP(unit %d) Error: Field qualifier InPorts "
  29807                               "in an entry with eid :%d "
  29808                               "has been qualified with the ports which are not"
  29809                               " part of its group pbmp with gid : %d \n"),
  29810                                unit, f_ent->eid, f_ent->group->gid));
  29811             return BCM_E_CONFIG;
  29812         }
  29813     }
  29814 #endif
  29815 
  29816     /* Get number of parts. */
  29817     rv = _bcm_field_entry_tcam_parts_count (unit, f_ent->group->stage_id,
  29818             f_ent->group->flags, &parts_count);
  29819     BCM_IF_ERROR_RETURN(rv);
  29820 
  29821     /* Initialize tcam_idx array. */
  29822     sal_memset(tcam_idx, 0, sizeof(tcam_idx));
  29823 
  29824     /* Get tcam indexes for installed entry. */
  29825     if ((f_ent->group->stage_id != _BCM_FIELD_STAGE_EXTERNAL) &&
  29826             (f_ent->group->stage_id != _BCM_FIELD_STAGE_EXACTMATCH)) {
  29827         for (idx = parts_count - 1; idx >=0; idx--) {
  29828             rv = _bcm_field_entry_tcam_idx_get(unit, f_ent + idx,
  29829                     tcam_idx + idx);
  29830             BCM_IF_ERROR_RETURN(rv);
  29831         }
  29832     }
  29833 
  29834     /* If entry was previously installed, we better disable it temporarily,
  29835      * to avoid intermittent actions.
  29836      */
  29837 #if defined(BCM_TOMAHAWK_SUPPORT)
  29838     if ((f_ent->flags & _FP_ENTRY_INSTALLED) &&
  29839         ((_BCM_FIELD_STAGE_INGRESS == f_ent->fs->stage_id) ||
  29840         (_BCM_FIELD_STAGE_LOOKUP == f_ent->fs->stage_id) ||
  29841         (_BCM_FIELD_STAGE_EXACTMATCH == f_ent->fs->stage_id)) &&
  29842         (soc_feature(unit, soc_feature_advanced_flex_counter)) &&
  29843         (soc_feature(unit, soc_feature_field_multi_pipe_support))) {
  29844         int update_stats = 1;
  29845 
  29846         if (f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) {
  29847            if(!(f_ent->statistic.flags & _FP_ENTRY_STAT_DIRTY)) {
  29848                update_stats = 0;
  29849            }
  29850         }
  29851 
  29852         if (update_stats) {
  29853 
  29854         f_ent_st = &(f_ent->statistic);
  29855         if (f_ent_st->flags & _FP_ENTRY_STAT_INSTALLED) {
  29856             soc_mem_t tcam_mem = INVALIDm;
  29857             soc_mem_t policy_mem = INVALIDm;
  29858 
  29859             /* Read stat entity configuration. */
  29860             rv = _bcm_field_stat_get(unit, f_ent_st->sid, &f_st);
  29861             BCM_IF_ERROR_RETURN(rv);
  29862 
  29863             if (f_st->hw_ref_count > 0) {
  29864 
  29865                 int policy_idx;
  29866 
  29867                     /* If this is the only entry using this stat, store the
  29868                      * stat values to retain on next attach.
  29869                  */
  29870 
  29871                 if (0 == (f_st->hw_ref_count - 1)) {
  29872                     for (idx= 0; idx < f_st->nstat; idx++) {
  29873                         rv = _field_stat_value_get(unit, 0, f_st,
  29874                                 f_st->stat_arr[idx],
  29875                                 f_st->stat_values + idx);
  29876                         BCM_IF_ERROR_RETURN(rv);
  29877                     }
  29878                 }
  29879 
  29880                 /* (Intra Slice) Double Wide/ Triple wide modes,
  29881                  * IFP_TCAM_WIDE have 256 entries but IFP_POLICY_TABLE
  29882                  * will have 512 entries.
  29883                  */
  29884 
  29885                 if (!soc_feature(unit, soc_feature_td3_style_fp) &&
  29886                         (f_ent->fs->stage_id == _BCM_FIELD_STAGE_INGRESS) &&
  29887                         (!(f_ent->group->flags & _FP_GROUP_SPAN_SINGLE_SLICE) ||
  29888                         (f_ent->group->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE))
  29889                         ) {
  29890                         policy_idx = tcam_idx[0] +
  29891                                       (f_ent->fs->slice_number * 256);
  29892                 } else {
  29893                     policy_idx = tcam_idx[0];
  29894                 }
  29895 
  29896                 rv = _bcm_field_th_tcam_policy_mem_get(unit, f_ent,
  29897                         &tcam_mem, &policy_mem);
  29898                 BCM_IF_ERROR_RETURN(rv);
  29899                     /* Stats are attached to only first part of multiwide group
  29900                  * So in calling stat detach for tcam_idx[0] is enough.
  29901                  */
  29902                 if (_BCM_FIELD_STAGE_EXACTMATCH == f_ent->fs->stage_id
  29903                     || (soc_feature(unit, soc_feature_td3_style_fp)
  29904                     && (_BCM_FIELD_STAGE_INGRESS == f_ent->fs->stage_id))) {
  29905                         rv =
  29906                           _bcm_esw_stat_flex_detach_ingress_table_counters_sw(
  29907                             unit,
  29908                             policy_mem, 0,
  29909                             f_st->hw_mode,
  29910                             f_st->hw_index,
  29911                             f_st->pool_index);
  29912                 } else {
  29913                         rv = _bcm_esw_stat_flex_detach_ingress_table_counters(
  29914                                 unit,
  29915                             policy_mem,
  29916                             policy_idx);
  29917                 }
  29918                 BCM_IF_ERROR_RETURN(rv);
  29919                 f_ent_st->flags &= ~_FP_ENTRY_STAT_INSTALLED;
  29920                 f_st->hw_ref_count--;
  29921             }
  29922         }
  29923     }
  29924     }
  29925 #endif
  29926 
  29927     /* If entry was previously installed, we better disable it temporarily,
  29928      * to avoid intermittent actions.
  29929      */
  29930     if (f_ent->flags & _FP_ENTRY_INSTALLED) {
  29931         int temp_entry_set = 0;
  29932         for (idx = 0; idx < parts_count; idx++) {
  29933             /* Read existing entry qualifiers from the HW. */
  29934             rv = _bcm_field_qual_tcam_key_mask_get(unit, f_ent + idx);
  29935             if (BCM_FAILURE(rv)) {
  29936                 goto backup_clean;
  29937             }
  29938             /* internal backup entry installed temporarily */
  29939             if ((soc_feature(unit,
  29940                             soc_feature_field_tcam_hitless_update_on_modify)) &&
  29941                     (f_ent->fs->stage_id != _BCM_FIELD_STAGE_EXTERNAL) &&
  29942                     (f_ent->fs->stage_id != _BCM_FIELD_STAGE_EXACTMATCH) &&
  29943                     (f_ent->fs->stage_id != _BCM_FIELD_STAGE_FLOWTRACKER)) {
  29944 
  29945                 fs = f_ent->group->slices;
  29946                 while(fs->next != NULL) {
  29947                     slice_count++;
  29948                     fs = fs->next;
  29949                 }
  29950 
  29951                 if (idx == 0) {
  29952                     rv = _field_internal_backup_entry_create(unit,f_ent->eid,
  29953                             &temp_entry);
  29954                     BCM_IF_ERROR_RETURN(rv);
  29955                     temp_entry_set = 1;
  29956                 }
  29957                 /* Prio set may change the TCAM idx of f_ent
  29958                    Getting new TCAM idx after bacup entry create*/
  29959                 if (temp_entry_set == 1) {
  29960                     rv = _bcm_field_entry_tcam_idx_get(unit, f_ent + idx,
  29961                             tcam_idx + idx);
  29962                     if (BCM_FAILURE(rv)) {
  29963                         goto backup_clean;
  29964                     }
  29965                 }
  29966 
  29967                 fs = f_ent->group->slices;
  29968                 while(fs->next != NULL) {
  29969                     slice_count_updated++;
  29970                     fs = fs->next;
  29971                 }
  29972             }
  29973 #if ((defined(BCM_KATANA_SUPPORT)) || (defined(BCM_TRIUMPH3_SUPPORT)))
  29974             if (soc_feature(unit, soc_feature_advanced_flex_counter)) {
  29975                 int sid = -1;
  29976 
  29977                 f_ent_st = &((f_ent + idx)->statistic);
  29978                 if (f_ent_st->flags & _FP_ENTRY_STAT_INSTALLED) {
  29979                     if (f_ent->fs->stage_id == _BCM_FIELD_STAGE_LOOKUP) {
  29980                         if(soc_feature(unit, soc_feature_flex_stat_compaction_support)) {
  29981                             sid = f_ent_st->extended_sid;
  29982                         } else {
  29983                             sid = f_ent_st->sid;
  29984                         }
  29985                     }
  29986                 } else if(f_ent_st->flags & _FP_ENTRY_EXTENDED_STAT_INSTALLED) {
  29987                     sid = f_ent_st->extended_sid;
  29988                 }
  29989 
  29990                 if (sid != -1) {
  29991                     /* Read stat entity configuration. */
  29992                     rv = _bcm_field_stat_get(unit, sid, &f_st);
  29993                     if (BCM_FAILURE(rv)) {
  29994                         goto backup_clean;
  29995                     }
  29996                     if (f_st->hw_ref_count > 0) {
  29997                         soc_mem_t policy_mem = INVALIDm;
  29998                         /*
  29999                          * If this is the only entry using this stat, store the stat
  30000                          * values to retain on next attach.
  30001                          */
  30002                         if (1 == f_st->hw_ref_count) {
  30003                             int  i;
  30004                             for (i= 0; i < f_st->nstat; i++) {
  30005                                 rv = _field_stat_value_get(unit, 0, f_st,
  30006                                         f_st->stat_arr[i],
  30007                                         f_st->stat_values + i);
  30008                                 if (BCM_FAILURE(rv)) {
  30009                                     goto backup_clean;
  30010                                 }
  30011                             }
  30012                         }
  30013                         switch (f_ent->fs->stage_id) {
  30014                             case _BCM_FIELD_STAGE_LOOKUP:
  30015                             case _BCM_FIELD_STAGE_INGRESS:
  30016                                 policy_mem =
  30017                                     (f_ent->fs->stage_id == _BCM_FIELD_STAGE_LOOKUP)
  30018                                     ? VFP_POLICY_TABLEm : FP_POLICY_TABLEm;
  30019                                 rv = _bcm_esw_stat_flex_detach_ingress_table_counters
  30020                                     (unit, policy_mem, tcam_idx[idx]);
  30021                                 if (BCM_FAILURE(rv)) {
  30022                                     goto backup_clean;
  30023                                 }
  30024                                 break;
  30025                             case _BCM_FIELD_STAGE_EGRESS:
  30026                                 policy_mem = EFP_POLICY_TABLEm;
  30027                                 rv = _bcm_esw_stat_flex_detach_egress_table_counters
  30028                                     (unit, 0, policy_mem, tcam_idx[idx]);
  30029                                 if (BCM_FAILURE(rv)) {
  30030                                     goto backup_clean;
  30031                                 }
  30032                                 break;
  30033                             default:
  30034                                 rv = BCM_E_INTERNAL;
  30035                                 goto backup_clean;
  30036                                 break;
  30037                         }
  30038 
  30039                         if (f_ent_st->flags & _FP_ENTRY_STAT_INSTALLED) {
  30040                             f_ent_st->flags &= ~_FP_ENTRY_STAT_INSTALLED;
  30041                             if(soc_feature(unit,
  30042                                         soc_feature_flex_stat_compaction_support) &&
  30043                                     (f_ent->fs->stage_id == _BCM_FIELD_STAGE_LOOKUP)) {
  30044                                 f_ent_st->flags &= ~_FP_ENTRY_EXTENDED_STAT_INSTALLED;
  30045                                 f_ent_st->flags &= ~_FP_ENTRY_EXTENDED_STAT_RESERVED;
  30046                             }
  30047                         } else {
  30048                             f_ent_st->flags &= ~_FP_ENTRY_EXTENDED_STAT_INSTALLED;
  30049                             f_ent_st->flags &= ~_FP_ENTRY_EXTENDED_STAT_RESERVED;
  30050                         }
  30051                         f_st->hw_ref_count--;
  30052                     }
  30053                 }
  30054             }
  30055 #endif
  30056 
  30057 
  30058 #if defined(BCM_HURRICANE3_SUPPORT)
  30059             if (soc_feature(unit, soc_feature_flowcnt)) {
  30060                 if (_BCM_FIELD_STAGE_LOOKUP == f_ent->fs->stage_id) {
  30061                     f_ent_st = &((f_ent + idx)->statistic);
  30062                     if (f_ent_st->flags & _FP_ENTRY_STAT_INSTALLED) {
  30063                         /* Read stat entity configuration. */
  30064                         rv = _bcm_field_stat_get(unit, f_ent_st->sid, &f_st);
  30065                         if (BCM_FAILURE(rv)) {
  30066                             goto backup_clean;
  30067                         }
  30068                         if (f_st->hw_ref_count > 0) {
  30069                             /* Disable VLAN Flow counter */
  30070                             rv = _bcm_esw_flowcnt_object_table_detach(unit,
  30071                                     VFP_POLICY_TABLEm, tcam_idx[idx]);
  30072                             if (BCM_FAILURE(rv)) {
  30073                                 goto backup_clean;
  30074                             }
  30075                             f_ent_st->flags &= ~_FP_ENTRY_STAT_INSTALLED;
  30076                             f_st->hw_ref_count--;
  30077                         }
  30078                     }
  30079                 }
  30080             }
  30081 #endif /* BCM_HURRICANE3_SUPPORT */
  30082             /* Disable installed entry. */
  30083             if ( !((f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) &&
  30084                    (soc_feature(unit, soc_feature_field_multi_pipe_support)))) {
  30085                 rv = _field_entry_tcam_remove(unit, fc, f_ent + idx,
  30086                                    tcam_idx[idx]);
  30087                 if (BCM_FAILURE(rv)) {
  30088                     goto backup_clean;
  30089                 }
  30090                 if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  30091                     /*
  30092                      * For not missing each Slice hw_ent_count update for VFP/EFP groups
  30093                      * Entry install flag should be reset and it will be set once the installation is succesful.
  30094                      */
  30095                     (f_ent + idx)->flags &= ~_FP_ENTRY_INSTALLED;
  30096                 }
  30097         }
  30098     }
  30099     }
  30100 
  30101     /* Remove deleted actions. */
  30102     rv = _field_invalid_actions_remove(unit, f_ent);
  30103     if (BCM_FAILURE(rv)) {
  30104         goto backup_clean;
  30105     }
  30106 
  30107     /* Allocate hw resources required for entry installation. */
  30108     rv = _field_hw_resources_alloc(unit, f_ent);
  30109     if (BCM_FAILURE(rv)) {
  30110         goto backup_clean;
  30111     }
  30112 
  30113     /* Move  all actions to the slice where meter resides. */
  30114     rv = _field_entry_actions_meter_slice_move(unit, f_ent, TRUE);
  30115     if (BCM_FAILURE(rv)) {
  30116         (void) _field_hw_resources_free(unit, f_ent, _FP_ACTION_HW_FREE);
  30117         goto backup_clean;
  30118     }
  30119 
  30120     /*
  30121      * For stages that support global meter pools, meters must be in
  30122      * same slice as counters. Move policer to counter slice if
  30123      * counters are in secondary slice.
  30124      */
  30125     rv = _field_entry_policer_stat_slice_move(unit, f_ent, TRUE);
  30126     if (BCM_FAILURE(rv)) {
  30127         (void) _field_hw_resources_free(unit, f_ent, _FP_ACTION_HW_FREE);
  30128         goto backup_clean;
  30129     }
  30130 
  30131     if (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXTERNAL) {
  30132         rv = _field_tcam_policy_external_install(unit, f_ent);
  30133     } else if (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) {
  30134 #if defined (BCM_TOMAHAWK_SUPPORT)
  30135         rv = _field_th_em_entry_install(unit, f_ent);
  30136 #endif
  30137     } else {
  30138         for (idx = parts_count - 1; idx >=0; idx--) {
  30139             /*
  30140              * For Trident FP_GM_FIELDS.VALID = 1 when used in paired mode
  30141              */
  30142             if (((!SOC_IS_TRIDENT2X(unit) && !SOC_IS_TITAN2PLUS(unit)))
  30143                     && (!soc_feature(unit, soc_feature_field_multi_pipe_support)) &&
  30144                     SOC_IS_TD_TT(unit) && (idx == 1) &&
  30145                     (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id)) {
  30146                 f_ent[idx].flags |= _FP_ENTRY_USES_IPBM_OVERLAY;
  30147             }
  30148 
  30149             /* Get entry tcam key/mask. */
  30150             rv = _bcm_field_qual_tcam_key_mask_get(unit, f_ent + idx);
  30151             if (BCM_FAILURE(rv)) {
  30152                 break;
  30153             }
  30154 
  30155 #if defined(BCM_TRIDENT2_SUPPORT)
  30156             if (SOC_IS_TD2_TT2(unit) &&
  30157                     (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id)) {
  30158                 rv = fc->functions.fp_egress_key_match_type_set(unit,
  30159                         f_ent + idx);
  30160                 if (BCM_FAILURE(rv)) {
  30161                     break;
  30162                 }
  30163             }
  30164 #endif
  30165 
  30166             if (f_ent->statistic.flags & _FP_ENTRY_STAT_DIRTY) {
  30167               f_ent[idx].statistic.flags |= _FP_ENTRY_STAT_DIRTY;
  30168             }
  30169             /* Install physical entry into primary slice */
  30170             rv = fc->functions.fp_tcam_policy_install(unit, f_ent + idx,
  30171                     tcam_idx[idx]);
  30172             if (BCM_FAILURE(rv)) {
  30173                 break;
  30174             }
  30175             f_ent[idx].flags &= ~_FP_ENTRY_DIRTY;
  30176             f_ent[idx].flags |= _FP_ENTRY_INSTALLED;
  30177             f_ent[idx].flags |= _FP_ENTRY_ENABLED;
  30178             f_ent[idx].statistic.flags &= ~_FP_ENTRY_STAT_DIRTY;
  30179 #if defined(BCM_TRIDENT2_SUPPORT)
  30180             if (SOC_IS_TD2_TT2(unit) &&
  30181                     (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id)){
  30182                 if (NULL != f_ent[idx].key_match_tcam.key) {
  30183                     sal_free(f_ent[idx].key_match_tcam.key);
  30184                 }
  30185                 if (NULL != f_ent[idx].key_match_tcam.mask) {
  30186                     sal_free(f_ent[idx].key_match_tcam.mask);
  30187                 }
  30188                 f_ent[idx].key_match_tcam.key = f_ent[idx].key_match_tcam.mask = NULL;
  30189             }
  30190 #endif
  30191             {
  30192                 if(NULL != f_ent[idx].tcam.key) sal_free(f_ent[idx].tcam.key);
  30193                 if(NULL != f_ent[idx].tcam.mask) sal_free(f_ent[idx].tcam.mask);
  30194                 f_ent[idx].tcam.key = f_ent[idx].tcam.mask = NULL;
  30195             }
  30196         }
  30197         /*
  30198          * TD3 qualifies on Inports for all other pipes in Global Mode
  30199          * inturn set _FP_ENTRY_DIRTY for all other parts of entry
  30200          */
  30201         if (soc_feature(unit, soc_feature_td3_style_fp) &&
  30202             BCM_FIELD_QSET_TEST(f_ent->group->qset, bcmFieldQualifyInPorts)) {
  30203             for (idx = parts_count - 1; idx >=0; idx--) {
  30204                 f_ent[idx].flags &= ~_FP_ENTRY_DIRTY;
  30205             }
  30206         }
  30207     }
  30208 
  30209     if (BCM_FAILURE(rv)) {
  30210         (void)_field_entry_actions_meter_slice_move(unit, f_ent, FALSE);
  30211         (void)_field_entry_policer_stat_slice_move(unit, f_ent, FALSE);
  30212         (void)_field_hw_resources_free(unit, f_ent, _FP_ACTION_HW_FREE);
  30213         /*  internal backup entry removed */
  30214         goto backup_clean;
  30215     }
  30216 
  30217     /*  internal backup entry removed */
  30218     if ((soc_feature(unit, soc_feature_field_tcam_hitless_update_on_modify)) &&
  30219             (f_ent->fs->stage_id != _BCM_FIELD_STAGE_EXTERNAL) &&
  30220             (f_ent->fs->stage_id != _BCM_FIELD_STAGE_EXACTMATCH)) {
  30221         rv = _field_internal_backup_entry_delete(unit, temp_entry);
  30222         BCM_IF_ERROR_RETURN(rv);
  30223     }
  30224 
  30225     /* Move  all actions back to the primary slice . */
  30226     rv = _field_entry_actions_meter_slice_move(unit, f_ent, FALSE);
  30227     if (BCM_FAILURE(rv)) {
  30228         (void) _field_hw_resources_free(unit, f_ent, _FP_ACTION_HW_FREE);
  30229         goto backup_clean;
  30230     }
  30231 
  30232     /* Move policers to primary slice. */
  30233     rv = _field_entry_policer_stat_slice_move(unit, f_ent, FALSE);
  30234     if (BCM_FAILURE(rv)) {
  30235         (void) _field_hw_resources_free(unit, f_ent, _FP_ACTION_HW_FREE);
  30236         goto backup_clean;
  30237     }
  30238 
  30239 
  30240     /* Remove stale deleted actions. */
  30241     rv = _field_invalid_actions_remove(unit, f_ent);
  30242     if (BCM_FAILURE(rv)) {
  30243         goto backup_clean;
  30244     }
  30245     BCM_IF_ERROR_RETURN(rv);
  30246 
  30247     /* In case of entry reinstall free previous installation hw resources. */
  30248     rv = _field_hw_resources_free(unit, f_ent, _FP_ACTION_OLD_RESOURCE_FREE);
  30249     if (BCM_FAILURE(rv)) {
  30250         (void) _field_hw_resources_free(unit, f_ent, _FP_ACTION_HW_FREE);
  30251         goto backup_clean;
  30252     }
  30253 
  30254 backup_clean:
  30255     if (BCM_FAILURE(rv)) {
  30256         if ((soc_feature(unit, soc_feature_field_tcam_hitless_update_on_modify)) &&
  30257                 (f_ent->fs->stage_id != _BCM_FIELD_STAGE_EXTERNAL) &&
  30258                 (f_ent->fs->stage_id != _BCM_FIELD_STAGE_EXACTMATCH)) {
  30259             BCM_IF_ERROR_RETURN(_field_internal_backup_entry_delete(unit, temp_entry));
  30260         }
  30261         /* Returning failure error */
  30262         return (rv);
  30263     }
  30264     return (BCM_E_NONE);
  30265 }
  30266 
  30267 
  30268 
  30269 
  30270 /*
  30271  * Function: _field_entry_remove
  30272  *
  30273  * Purpose:
  30274  *     Remove an entry from the hardware tables.
  30275  *
  30276  * Parameters:
  30277  *     unit  - (IN) BCM device number
  30278  *     fc    - (IN) Field control structure.
  30279  *     entry - (IN) Entry to remove.
  30280  *
  30281  * Returns:
  30282  *     BCM_E_XXX
  30283  */
  30284     int
  30285 _field_entry_remove(int unit, _field_control_t *fc, bcm_field_entry_t entry)
  30286 {
  30287     _field_entry_t      *f_ent;      /* Field entry pointer.     */
  30288     int                 tcam_idx;    /* Entry tcam index.        */
  30289     int                 parts_count = 0; /* Entry parts count.       */
  30290     int                 idx;         /* Iteration index.         */
  30291     int                 rv;          /* Operation return status. */
  30292     _field_action_t     *fa;
  30293 
  30294     rv = _bcm_field_entry_get_by_id(unit, entry, &f_ent);
  30295     if (BCM_FAILURE(rv)) {
  30296         return (rv);
  30297     }
  30298 
  30299 #if defined(BCM_TOMAHAWK_SUPPORT)
  30300     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  30301                 (_BCM_FIELD_STAGE_CLASS == f_ent->group->stage_id)) {
  30302         rv = _bcm_field_th_class_entry_remove(unit, entry);
  30303         return (rv);
  30304     }
  30305 #endif /* BCM_TOMAHAWK_SUPPORT */
  30306 
  30307     if (!(f_ent->flags & _FP_ENTRY_INSTALLED)) {
  30308         /* Entry not installed in hardware to perform remove operation. */
  30309         return (BCM_E_NONE);
  30310     }
  30311 
  30312     if ((_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id) ||
  30313         (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) ||
  30314         (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) ||
  30315         (_BCM_FIELD_STAGE_FLOWTRACKER == f_ent->group->stage_id)) {
  30316         /* Disable the Entry. */
  30317         BCM_IF_ERROR_RETURN(bcm_esw_field_entry_enable_set(unit, entry, 0));
  30318     }
  30319 
  30320     /* Free hw resources allocated during entry installation. */
  30321     rv = _field_resources_free(unit, f_ent,
  30322             _FP_ACTION_RESOURCE_FREE | _FP_ACTION_POLICER_SW_UPDATE);
  30323     BCM_IF_ERROR_RETURN(rv);
  30324 
  30325     /* Get number of parts. */
  30326     rv = _bcm_field_entry_tcam_parts_count (unit, f_ent->group->stage_id,
  30327                                             f_ent->group->flags, &parts_count);
  30328 
  30329     for (idx = 0; idx < parts_count; idx++) {
  30330         /* Store entry in S/W before removing from H/W */
  30331         rv = _bcm_field_qual_tcam_key_mask_get(unit, f_ent + idx);
  30332         BCM_IF_ERROR_RETURN(rv);
  30333 
  30334         /* Get entry tcam index. */
  30335         rv = _bcm_field_entry_tcam_idx_get(unit, f_ent + idx, &tcam_idx);
  30336         BCM_IF_ERROR_RETURN(rv);
  30337 
  30338         /* Remove entry in slice. */
  30339 
  30340         rv = _field_entry_tcam_remove(unit, fc, f_ent + idx, tcam_idx);
  30341         BCM_IF_ERROR_RETURN(rv);
  30342 
  30343         f_ent[idx].flags |= _FP_ENTRY_DIRTY;
  30344         f_ent[idx].flags &= ~_FP_ENTRY_POLICY_TABLE_ONLY_DIRTY;
  30345         f_ent[idx].flags &= ~_FP_ENTRY_INSTALLED;
  30346         f_ent[idx].flags &= ~_FP_ENTRY_ENABLED;
  30347     }
  30348 
  30349     if (f_ent->statistic.flags & _FP_ENTRY_STAT_VALID) {
  30350         f_ent->statistic.flags |= _FP_ENTRY_STAT_DIRTY;
  30351     }
  30352 
  30353     /* Free policers. */
  30354     rv = _field_policers_hw_free(unit, f_ent,
  30355 			_FP_ACTION_RESOURCE_FREE|_FP_ACTION_POLICER_SW_UPDATE);
  30356     BCM_IF_ERROR_RETURN(rv);
  30357 
  30358     /* Remove deleted actions. */
  30359     rv = _field_invalid_actions_remove(unit, f_ent);
  30360     BCM_IF_ERROR_RETURN(rv);
  30361     for (fa = f_ent->actions; (NULL != fa) && (fa->flags & _FP_ACTION_VALID); fa = fa->next) {
  30362         fa->flags |= _FP_ACTION_DIRTY;
  30363     }
  30364     return (BCM_E_NONE);
  30365 }
  30366 
  30367 
  30368 /* Function: _field_reqd_prio_set_move
  30369  *
  30370  * Purpose: Checks if the entry needs to be moved due to prio set
  30371  *
  30372  * Parameters:
  30373  *   unit -
  30374  *   f_ent - Entry whose priority is being set
  30375  *   prio - The new priority for f_ent
  30376  *
  30377  * Returns:
  30378  *   TRUE/FALSE
  30379  */
  30380 int
  30381 _field_reqd_prio_set_move(int unit, _field_entry_t *f_ent, int prio)
  30382 {
  30383     _field_group_t *fg;
  30384     _field_slice_t *fs;
  30385     _field_stage_t *stage_fc;
  30386     int slice_sz;
  30387     int idx_type;
  30388 
  30389     int i, flag; /* flag denotes is we are before OR after f_ent */
  30390 
  30391     fg = f_ent->group;
  30392 
  30393     /* Get stage control structure. */
  30394     BCM_IF_ERROR_RETURN
  30395         (_field_stage_control_get(unit, fg->stage_id, &stage_fc));
  30396 
  30397     fs = &fg->slices[0];
  30398     flag = -1; /* We are before f_ent */
  30399     while (fs != NULL) {
  30400         _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs, slice_sz);
  30401         for (i = 0; i < slice_sz; i++) {
  30402             if (fs->entries[i] == f_ent) {
  30403                 flag = 1; /* Now, we are after f_ent */
  30404                 continue;
  30405             }
  30406             _field_slice_index_type_get(unit, fg, fs, i, &idx_type);
  30407             if ((idx_type == _BCM_FIELD_SLICE_IDX_TYPE_FREE) ||
  30408                 (idx_type == _BCM_FIELD_SLICE_IDX_TYPE_DIFF)) {
  30409                 continue;
  30410             }
  30411             if (flag == -1) {
  30412                 if (_field_entry_prio_cmp(fs->entries[i]->prio, prio) < 0) {
  30413                     /*
  30414                      * An entry before f_ent has lower priority than prio
  30415                      *     Movement is required
  30416                      */
  30417                     return TRUE;
  30418                 }
  30419             } else {
  30420                 if (_field_entry_prio_cmp(fs->entries[i]->prio, prio) > 0) {
  30421                     /*
  30422                      * An entry after f_ent has higher priority than prio
  30423                      *     Movement is required
  30424                      */
  30425                     return TRUE;
  30426                 }
  30427             }
  30428         }
  30429         fs = fs->next;
  30430     }
  30431     return FALSE; /* f_ent with new prio is in proper location */
  30432 }
  30433 
  30434 /*
  30435  * Function: _field_entry_multiple_slice_move_check
  30436  *
  30437  * Purpose: Checks if a series of entries can be shifted to the
  30438  *          nearest hole and returns how many entries would end up
  30439  *          being shifted.
  30440  *
  30441  *          This function is called recursively for each slice in
  30442  *          which entries need to be shifted.
  30443  *
  30444  * Parameters:
  30445  *   unit - unit
  30446  *   fg - The group to which the slices belong
  30447  *   entry - Pointer to the entry which is being moved
  30448  *   null_index - Index of the next empty slot within its slice, in the
  30449  *                specified direction
  30450  *   null_fs - Pointer to the next slice with an empty slot, in the
  30451  *             specified direction
  30452  *   target_index - Index of the slot in which we want to insert the entry
  30453  *   target_fs - Pointer to the slice in which we want to insert the entry
  30454  *   direction - The direction in which we're checking entry shifting
  30455  *               feasibility; -1 for up or 1 for down
  30456  *   shifted_entry_count (IN/OUT) - The number of entries that would be shifted
  30457  *                               to make the move possible
  30458  *   freed_counter_count (IN/OUT) - The number of counters that would be freed
  30459  *                               by the shift
  30460  *
  30461  * Returs:
  30462  *   BCM_E_NONE if the move can be done
  30463  */
  30464 
  30465 STATIC int _field_entry_multiple_slice_move_check(int unit,
  30466     _field_group_t *fg, _field_entry_t *entry, int null_index,
  30467     _field_slice_t *null_fs, int target_index, _field_slice_t *target_fs,
  30468     int direction, int *shifted_entry_count, int *freed_meter_count,
  30469     int *freed_counter_count)
  30470 {
  30471     int rv = BCM_E_NONE;
  30472     _field_stage_t *stage_fc;
  30473     _field_slice_t *adjacent_fs;
  30474     int adjacent_index;
  30475     int slice_entry_count;
  30476     int adjacent_slice_entry_count;
  30477     _field_entry_t *entry_to_move;
  30478 
  30479     BCM_IF_ERROR_RETURN
  30480         (_field_stage_control_get(unit, target_fs->stage_id, &stage_fc));
  30481 
  30482     _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, target_fs, slice_entry_count);
  30483 
  30484     if (target_fs != null_fs)
  30485     {
  30486         if (direction < 0)
  30487         {
  30488             /* Shift up */
  30489 
  30490             adjacent_fs = target_fs->prev;
  30491 
  30492             _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, adjacent_fs,
  30493                 adjacent_slice_entry_count);
  30494 
  30495             adjacent_index = adjacent_slice_entry_count - 1;
  30496             entry_to_move = target_fs->entries[0];
  30497             *shifted_entry_count += target_index;
  30498         }
  30499         else
  30500         {
  30501             /* Shift down */
  30502 
  30503             adjacent_fs = target_fs->next;
  30504             adjacent_index = 0;
  30505             entry_to_move = target_fs->entries[slice_entry_count - 1];
  30506             *shifted_entry_count += slice_entry_count - target_index;
  30507         }
  30508 
  30509         rv = _field_entry_multiple_slice_move_check(unit, fg,
  30510             entry_to_move, null_index, null_fs, adjacent_index,
  30511             adjacent_fs, direction, shifted_entry_count, freed_meter_count,
  30512             freed_counter_count);
  30513 
  30514         BCM_IF_ERROR_RETURN(rv);
  30515     }
  30516     else
  30517     {
  30518         *shifted_entry_count += direction * (null_index - target_index);
  30519     }
  30520 
  30521     if (entry->fs != target_fs)
  30522     {
  30523         rv = _field_entry_move_slice_fit(unit, stage_fc, entry, target_fs,
  30524             freed_meter_count, freed_counter_count);
  30525     }
  30526 
  30527     return rv;
  30528 }
  30529 
  30530 /*
  30531  * Function: _field_validate_prio_set
  30532  *
  30533  * Purpose: Checks if the prio_set can be successful.
  30534  *     Meaningful only when entries need to be moved across slices
  30535  *     1. Check that entries moving across slices don't have shared
  30536  *        meters/counters
  30537  *     2. For entries moving across slices, and having meters/counters,
  30538  *        check if there are resources in the new slice
  30539  *
  30540  * Parameters:
  30541  *   unit - unit
  30542  *   fg - group the entry whose prio is being set belongs to
  30543  *   f_ent_pri - primary entry whose priorty is to be changed
  30544  *   prev_null_index - index with no entry just before target_index
  30545  *   prev_null_fs - corresponding slice
  30546  *   target_index - the target index where f_ent is supposed to go
  30547  *   target_fs - the slice where index resides
  30548  *   next_null_index - index with no entry just after target_index
  30549  *   next_null_fs - corresponding slice
  30550  *   dir (OUT) - shift up (-1) or down (+1)
  30551  *
  30552  * Returs:
  30553  *   TRUE/FALSE
  30554  *
  30555  * Notes:
  30556  *     Check both up and down movement. If both feasible, take the one
  30557  *     which leads to lesser moves.
  30558  *     Note the slice_sz for intraslice-double wide (FB2). Also shift_up_amount
  30559  *     and shift_down_amount are not absolute amounts, but # entries which
  30560  *     need to be shifted (each entry moves by 1 unit UP/DOWN).
  30561  */
  30562 STATIC int
  30563 _field_validate_prio_set(int unit,
  30564                          _field_group_t *fg, _field_entry_t *f_ent_pri,
  30565                          int prev_null_index, _field_slice_t *prev_null_fs,
  30566                          int target_index, _field_slice_t *target_fs,
  30567                          int next_null_index, _field_slice_t *next_null_fs,
  30568                          int *dir)
  30569 {
  30570     _field_stage_t *stage_fc;
  30571     int rv;
  30572     int shift_up = FALSE, shift_down = FALSE;
  30573     int shift_up_amount = 0, shift_down_amount = 0;
  30574     int up_meters_freed = 0, down_meters_freed = 0;
  30575     int up_counters_freed = 0, down_counters_freed = 0;
  30576 
  30577     /* Input parameter check. */
  30578     if ((NULL == f_ent_pri) || (NULL == target_fs)) {
  30579         return (BCM_E_PARAM);
  30580     }
  30581 
  30582     BCM_IF_ERROR_RETURN
  30583         (_field_stage_control_get(unit, target_fs->stage_id, &stage_fc));
  30584 
  30585     /*
  30586      * STEP-1
  30587      * Check the shift operation for UP movement
  30588      * Entries from target_index up till entry after prev_null_index
  30589      * need to move one entry up
  30590      */
  30591 
  30592     if (prev_null_fs != NULL)
  30593     {
  30594         rv = _field_entry_multiple_slice_move_check(unit, fg, f_ent_pri,
  30595             prev_null_index, prev_null_fs, target_index, target_fs, -1,
  30596             &shift_up_amount, &up_meters_freed, &up_counters_freed);
  30597 
  30598         shift_up = BCM_SUCCESS(rv);
  30599     }
  30600     else
  30601     {
  30602         shift_up = FALSE;
  30603     }
  30604 
  30605     /*
  30606      * Step-2
  30607      * Check the shift operation for DOWN movement
  30608      * Entries from target_index till entry before next_null_index
  30609      * need to move one entry down
  30610      */
  30611 
  30612     if (next_null_fs != NULL)
  30613     {
  30614         rv = _field_entry_multiple_slice_move_check(unit, fg, f_ent_pri,
  30615             next_null_index, next_null_fs, target_index, target_fs, 1,
  30616             &shift_down_amount, &down_meters_freed, &down_counters_freed);
  30617 
  30618         shift_down = BCM_SUCCESS(rv);
  30619     }
  30620     else
  30621     {
  30622         shift_down = FALSE;
  30623     }
  30624 
  30625     if (shift_up == TRUE)
  30626     {
  30627         if (shift_down == TRUE)
  30628         {
  30629             if (shift_up_amount < shift_down_amount)
  30630             {
  30631                 *dir = -1;
  30632             }
  30633             else
  30634             {
  30635                 *dir = 1;
  30636             }
  30637         }
  30638         else
  30639         {
  30640             *dir = -1;
  30641         }
  30642     }
  30643     else
  30644     {
  30645         if (shift_down == TRUE)
  30646         {
  30647             *dir = 1;
  30648         }
  30649         else
  30650         {
  30651             return FALSE;
  30652         }
  30653     }
  30654 
  30655     return TRUE;
  30656 }
  30657 
  30658 /*
  30659  * Function: _field_no_free_entries
  30660  *
  30661  * Purpose:
  30662  *     To see if the any of the slices allocated to this
  30663  *     group has any free entries
  30664  *
  30665  * Parameters:
  30666  *     unit - BCM device number
  30667  *     fg - group
  30668  *
  30669  * Returns:
  30670  *     FALSE: Atleast 1 free entry
  30671  *     TRUE: No free entries
  30672  *
  30673  * Notes:
  30674  */
  30675 int
  30676 _field_no_free_entries(int unit, _field_group_t *fg)
  30677 {
  30678     _field_slice_t *fs;
  30679     int free_entry_cnt;
  30680 
  30681     fs = &fg->slices[0];
  30682 
  30683     while (fs != NULL) {
  30684         _bcm_field_entries_free_get(unit, fs, fg, &free_entry_cnt);
  30685         if (free_entry_cnt) {
  30686             return FALSE;
  30687         }
  30688         fs = fs->next;
  30689     }
  30690 
  30691     return TRUE;
  30692 }
  30693 
  30694 /*
  30695  * Function:
  30696  *     _field_entry_prio_cmp
  30697  * Purpose:
  30698  *     Compare two entry priorities
  30699  * Parameters:
  30700  * Returns:
  30701  *     -1 if prio_first <  prio_second
  30702  *      0 if prio_first == prio_second
  30703  *      1 if prio_first >  prio_second
  30704  */
  30705 int
  30706 _field_entry_prio_cmp(int prio_first, int prio_second)
  30707 {
  30708     int retval;
  30709 
  30710     if (prio_first == prio_second) {
  30711         retval = 0;
  30712     } else if (prio_first < prio_second) {
  30713         retval = -1;
  30714     } else {
  30715         retval = 1;
  30716     }
  30717     return retval;
  30718 }
  30719 
  30720 
  30721 /*
  30722  * Function:
  30723  *     _field_entry_move
  30724  * Purpose:
  30725  *     Move an entry within a slice by "amount" indexes
  30726  *
  30727  * Parameters:
  30728  *     unit     - BCM device number
  30729  *     f_ent    - entry to be moved
  30730  *     amount   - number of indexes to move + or -
  30731  * Returns:
  30732  *     BCM_E_NONE   - Success
  30733  */
  30734 STATIC int
  30735 _field_entry_move(int unit, _field_entry_t *f_ent, int amount)
  30736 {
  30737     int  tcam_idx_old[_FP_MAX_ENTRY_WIDTH];/* Original entry tcam index.    */
  30738     int  tcam_idx_new[_FP_MAX_ENTRY_WIDTH];/* Next tcam index for the entry.*/
  30739     _field_entry_policer_t *f_ent_pl;   /* Field entry policer structure.*/
  30740     _field_entry_stat_t    *f_ent_st;   /* Field entry stat structure.   */
  30741     _field_control_t       *fc;         /* Field control structure.      */
  30742     _field_stage_t         *stage_fc;   /* Stage field control.          */
  30743     _field_group_t         *fg;         /* Field entry group.            */
  30744     _field_slice_t         *fs;         /* Field slice control.          */
  30745     _field_policer_t       *f_pl = NULL;/* Field policer info.           */
  30746     _field_stat_t          *f_st = NULL;/* Field statatistics entity.    */
  30747     int                    parts_count = 0; /* Field entry parts count.      */
  30748     int                     idx;
  30749     int                    rv;          /* Operation return status.      */
  30750     int counter_movement = 0;           /* Boolean which tells if entry moved
  30751                                            across slice, and if so, did it
  30752                                            have a counter */
  30753     uint8 entry_part;                    /* Field entry parts iterator.  */
  30754     int meter_movement   = 0;            /* For meter                      */
  30755     int meter_index      = 0;            /* Meter hardware index.          */
  30756     int meter_pool_index = 0;            /* Meter pool value.              */
  30757     int stat_index       = 0;            /* STAT hardware index.           */
  30758     int stat_slice       = 0;            /* STAT slice value.              */
  30759     int new_offset;                      /* Entry offset in slice.         */
  30760     int new_slice_numb   = 0;            /* New slice number.              */
  30761     _field_stat_t        f_st_old;       /* Old Field statatistics entity. */
  30762     uint64               value;          /* STAT value.                    */
  30763     int                  nstat;          /* STAT array index.              */
  30764     int                  instance;       /* Pipe Instance.                 */
  30765     bcm_policer_mode_t old_mode;
  30766     uint32 pl_flags = 0;
  30767     old_mode = bcmPolicerModeCount;
  30768     LOG_DEBUG(BSL_LS_BCM_FP,
  30769               (BSL_META_U(unit,
  30770                "FP(unit %d) vverb: BEGIN _field_entry_move(entry=%d,"
  30771                " amount=%d)\n"), unit, f_ent->eid, amount));
  30772 
  30773     if (NULL == f_ent) {
  30774         return (BCM_E_PARAM);
  30775     }
  30776 
  30777     if ((NULL == f_ent->fs) || (NULL == f_ent->group)) {
  30778         return (BCM_E_PARAM);
  30779     }
  30780 
  30781 #if defined(BCM_FLOWTRACKER_SUPPORT)
  30782     if (f_ent->fs->slice_flags & _BCM_FIELD_SLICE_MULTIMODE_ENTRIES) {
  30783         return _field_multimode_slice_entry_move(unit,
  30784                             f_ent->fs, f_ent, amount);
  30785     }
  30786 #endif
  30787 
  30788     /* Initialization. */
  30789     sal_memset(tcam_idx_old, 0,  (_FP_MAX_ENTRY_WIDTH * sizeof(int)));
  30790     sal_memset(tcam_idx_new, 0, (_FP_MAX_ENTRY_WIDTH * sizeof(int)));
  30791     fg = f_ent->group;
  30792 
  30793     if (amount == 0) {
  30794         LOG_WARN(BSL_LS_BCM_FP,
  30795                  (BSL_META_U(unit,
  30796                   "Warning: moving entry=%d, same slice_idx=%d(%#x)\n"),
  30797                   f_ent->eid, f_ent->slice_idx, f_ent->slice_idx));
  30798         return (BCM_E_NONE);
  30799     }
  30800 
  30801     /* Get field control structure. */
  30802     BCM_IF_ERROR_RETURN (_field_control_get(unit, &fc));
  30803 
  30804     /* Get stage field control structure. */
  30805     rv =  _field_stage_control_get(unit, fg->stage_id, &stage_fc);
  30806     BCM_IF_ERROR_RETURN(rv);
  30807 
  30808     /* Get number of parts. */
  30809     rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
  30810                                             fg->flags, &parts_count);
  30811     BCM_IF_ERROR_RETURN(rv);
  30812 
  30813     /* Retrieve the pipe instance */
  30814     instance = fg->instance;
  30815 
  30816     /* Calculate the new and old TCAM indexes. */
  30817     for (idx = 0; idx < parts_count; idx++) {
  30818         /* Calculate the new and old TCAM indexes. */
  30819         rv = _bcm_field_entry_tcam_idx_get(unit, f_ent + idx,
  30820                                            &tcam_idx_old[idx]);
  30821         BCM_IF_ERROR_RETURN(rv);
  30822 
  30823         /* Calculate entry part tcam offset. */
  30824         rv = _bcm_field_entry_part_tcam_idx_get(unit, f_ent,
  30825                                                 tcam_idx_old[0] + amount,
  30826                                                 idx, &tcam_idx_new[idx]);
  30827         BCM_IF_ERROR_RETURN(rv);
  30828     }
  30829 
  30830     /* Get secondary slice entry pointer. */
  30831     if ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) ||
  30832         (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE)) {
  30833         rv = _bcm_field_entry_flags_to_tcam_part (unit, _FP_ENTRY_SECONDARY,
  30834                                                   fg, &entry_part);
  30835         BCM_IF_ERROR_RETURN(rv);
  30836     }
  30837 
  30838     /* Calculate entry new slice number. */
  30839 #if defined(BCM_TOMAHAWK_SUPPORT)
  30840     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  30841         (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id)) {
  30842         rv = _bcm_field_th_tcam_idx_to_slice_offset(unit, stage_fc, f_ent,
  30843                                               tcam_idx_new[0], &new_slice_numb,
  30844                                               &new_offset);
  30845     } else
  30846 #endif /* BCM_TOMAHAWK_SUPPORT */
  30847     {
  30848         rv = _bcm_field_tcam_idx_to_slice_offset (unit, stage_fc, instance,
  30849                                               tcam_idx_new[0], &new_slice_numb,
  30850                                               &new_offset);
  30851     }
  30852     BCM_IF_ERROR_RETURN(rv);
  30853 
  30854     if ((f_ent->fs->slice_number != new_slice_numb) &&
  30855         (f_ent->flags  & _FP_ENTRY_INSTALLED)) {
  30856 
  30857         fs = stage_fc->slices[instance] + new_slice_numb;
  30858 
  30859         /*
  30860          * If global meter pools are not present, AND
  30861          *     current entry has a meter, allocate one in new slice
  30862          */
  30863         f_ent_pl = f_ent->policer;
  30864         if ((0 == (stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)) &&
  30865             (f_ent_pl->flags & _FP_POLICER_INSTALLED))  {
  30866             meter_movement = 1;
  30867 
  30868             /* Read policer configuration.*/
  30869             rv = _bcm_field_policer_get(unit, f_ent_pl->pid, &f_pl);
  30870             BCM_IF_ERROR_RETURN(rv);
  30871 
  30872             /* Preserve original policer hw index,
  30873              * flag and mode.
  30874              */
  30875             meter_pool_index = f_pl->pool_index;
  30876             meter_index = f_pl->hw_index;
  30877             pl_flags = f_pl->hw_flags;
  30878             old_mode = (f_pl)->cfg.mode;
  30879            /* _field_policer_meter_hw_free(unit, f_ent, f_ent_pl); */
  30880             /* Deallocate policer from original entry slice. */
  30881             BCM_IF_ERROR_RETURN(_field_meter_hw_free(unit, f_ent));
  30882 
  30883             /* Allocate policer in a new slice. */
  30884             rv = _field_meter_hw_alloc(unit, f_ent, fs);
  30885             if (BCM_FAILURE(rv)) {
  30886                 if (rv == BCM_E_RESOURCE) {
  30887                     /*
  30888                      * Re-allocate policer resource in original slice
  30889                      * and re-install the entry in hardware.
  30890                      */
  30891                     BCM_IF_ERROR_RETURN(_field_meter_hw_alloc(unit, f_ent,
  30892                                                               f_ent->fs));
  30893                     f_ent->flags |= _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY;
  30894                     f_ent->flags  |= _FP_ENTRY_DIRTY;
  30895                     BCM_IF_ERROR_RETURN
  30896                         (bcm_esw_field_entry_reinstall(unit, f_ent->eid));
  30897                 }
  30898                return rv;
  30899             }
  30900         }
  30901 
  30902         /*
  30903          * If global counters are not present, AND
  30904          *     current entry has a counter, allocate one in new slice
  30905          *  NOTE: Must be after policer allocation in order to
  30906          *  determine counter slice.
  30907          */
  30908         f_ent_st = &f_ent->statistic;
  30909         if ((0 == (stage_fc->flags & _FP_STAGE_GLOBAL_COUNTERS)) &&
  30910             (0 == (stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS)) &&
  30911             (f_ent_st->flags & _FP_ENTRY_STAT_INSTALLED))  {
  30912             counter_movement = 1;
  30913 
  30914             /* Read statistics entity configuration.*/
  30915             BCM_IF_ERROR_RETURN(_bcm_field_stat_get(unit, f_ent_st->sid, &f_st));
  30916             f_st_old = *f_st;
  30917 
  30918             /* Preserve original policer hw index. */
  30919             stat_slice = f_st->pool_index;
  30920             stat_index = f_st->hw_index;
  30921 
  30922             /* Deallocate statistics entity from original entry slice. */
  30923             BCM_IF_ERROR_RETURN(_field_slice_counter_free(unit, f_ent, f_st));
  30924 
  30925             /* Allocate statistics entity in a new slice. */
  30926             BCM_IF_ERROR_RETURN(_field_counter_hw_alloc(unit, f_ent, fs));
  30927 
  30928             /* Clear allocated new hardware counters */
  30929             for (nstat = 0; nstat < f_st->nstat; nstat++) {
  30930                 COMPILER_64_ZERO(value);
  30931                 rv = _field_stat_value_set(unit,
  30932                                            f_st,
  30933                                            f_st->stat_arr[nstat],
  30934                                            value);
  30935                 BCM_IF_ERROR_RETURN(rv);
  30936             }
  30937         }
  30938     }
  30939 
  30940     /* Move the hardware entry.*/
  30941     if (f_ent->flags  & _FP_ENTRY_INSTALLED) {
  30942         rv = fc->functions.fp_entry_move(unit, f_ent, parts_count,
  30943                                          tcam_idx_old, tcam_idx_new);
  30944         BCM_IF_ERROR_RETURN(rv);
  30945     }
  30946 
  30947     /* Move the software entry.*/
  30948     rv = _field_entry_slice_idx_change(unit, f_ent, parts_count, tcam_idx_new);
  30949     BCM_IF_ERROR_RETURN(rv);
  30950 
  30951     if (meter_movement) {
  30952         f_ent_pl = f_ent->policer;
  30953         /* Read policer configuration. */
  30954         rv = _bcm_field_policer_get (unit, f_ent_pl->pid, &f_pl);
  30955         BCM_IF_ERROR_RETURN(rv);
  30956 
  30957         rv = _field_entry_meter_move(unit, stage_fc, instance,
  30958                                      meter_pool_index,
  30959                                      meter_index, pl_flags, f_pl,
  30960                                      f_ent, old_mode);
  30961         BCM_IF_ERROR_RETURN(rv);
  30962     }
  30963 
  30964     if (counter_movement) {
  30965         f_ent_st = &f_ent->statistic;
  30966         BCM_IF_ERROR_RETURN (_bcm_field_stat_get (unit, f_ent_st->sid, &f_st));
  30967         rv = _bcm_field_entry_counter_move(unit, stage_fc, stat_slice,
  30968                                            stat_index, &f_st_old, f_st);
  30969         BCM_IF_ERROR_RETURN(rv);
  30970     }
  30971 
  30972     return (BCM_E_NONE);
  30973 }
  30974 /*
  30975  * Function:
  30976  *      _field_efp_entry_qual_value_qualify
  30977  *
  30978  * Purpose:
  30979  *      Utility routine check encoding of a qualifier and decide that qualifier
  30980  *      can be part of key_match_tcam of an entry.
  30981  *
  30982  * Parameters:
  30983  *      unit  - (IN) BCM device number
  30984  *      entry - (IN) Entry ID
  30985  *      qual_id - (IN) Qualifier Id
  30986  *      can_qualify - (IN/OUT) Status of the qualifier
  30987  *      data - (IN) Data to qualify with.
  30988  *      mask - (IN) Mask to qualify with.
  30989  *
  30990  * Returns:
  30991  *     BCM_E_XXX     - BCM device number
  30992  */
  30993 int
  30994 _field_efp_entry_qual_value_qualify(int unit,
  30995                             bcm_field_entry_t entry,
  30996                             uint32  qual_id,
  30997                             uint32 *data, uint32 *mask,
  30998                             uint8   *can_qualify)
  30999 {
  31000     int    rv;                 /* Operation return stauts.        */
  31001     uint8  slice_mode;         /* Slice Mode of the group         */
  31002     bcm_field_IpType_t ipType; /* Ip type encoding                */
  31003     _field_group_t *fg;        /* FP group info structure.        */
  31004     _field_entry_t *f_ent;     /* Pointer to field entry          */
  31005 
  31006     /* Input parameters checks. */
  31007     if ((NULL == data) || (NULL == mask) || (NULL == can_qualify)) {
  31008         return (BCM_E_PARAM);
  31009     }
  31010 
  31011     /* Search the entry by eid. */
  31012     rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent);
  31013     BCM_IF_ERROR_RETURN(rv);
  31014 
  31015     fg = f_ent->group;
  31016     if (NULL == fg) {
  31017         return (BCM_E_INTERNAL);
  31018     }
  31019 
  31020     *can_qualify = 1;
  31021     slice_mode = 0;
  31022 
  31023 #if defined(BCM_TRX_SUPPORT)
  31024 #if defined(BCM_TOMAHAWK_SUPPORT)
  31025     if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  31026        rv = _bcm_field_th_egress_mode_get(unit, fg, &slice_mode);
  31027     } else
  31028 #endif
  31029     {
  31030        rv = _bcm_field_trx_egress_mode_get(unit, fg, &slice_mode);
  31031     }
  31032     BCM_IF_ERROR_RETURN(rv);
  31033 #endif
  31034 
  31035     switch (qual_id){
  31036         case bcmFieldQualifyIpType:
  31037 #if defined(BCM_TOMAHAWK3_SUPPORT)
  31038             if (SOC_IS_TOMAHAWK3(unit)) {
  31039 
  31040                 rv = _bcm_field_th3_qualify_ip_type_encode_get(unit, *data,
  31041                                                                *mask, &ipType);
  31042             } else
  31043 #endif /* BCM_TOMAHAWK3_SUPPORT */
  31044 #if defined(BCM_TRIDENT2_SUPPORT)
  31045             if (SOC_IS_TD2_TT2(unit)) {
  31046                 rv = _bcm_field_td2_qualify_ip_type_encode_get(unit, *data,
  31047                                                                *mask, &ipType);
  31048             } else
  31049 #endif /* BCM_TRIDENT2_SUPPORT */
  31050 #if defined(BCM_TRX_SUPPORT)
  31051             if (SOC_IS_TRX(unit)) {
  31052                 rv = _bcm_field_trx_qualify_ip_type_encode_get(unit, *data,
  31053                                                                *mask, &ipType);
  31054             } else
  31055 #endif /* BCM_TRX_SUPPORT */
  31056 #if defined(BCM_FIREBOLT_SUPPORT)
  31057             if (SOC_IS_FIREBOLT(unit)) {
  31058                 rv = _bcm_field_fb_qualify_ip_type_encode_get(unit, fg,
  31059                                                               *data, *mask,
  31060                                                               &ipType);
  31061             } else
  31062 #endif /* BCM_FIREBOLT_SUPPORT */
  31063 #if defined(BCM_RAPTOR1_SUPPORT)
  31064             if (SOC_IS_RAPTOR(unit)) {
  31065                 rv = _bcm_field_raptor_qualify_ip_type_get(unit, entry,
  31066                                                            &ipType, qual_id);
  31067             } else
  31068 #endif /* BCM_RAPTOR1_SUPPORT */
  31069             {
  31070                 rv = BCM_E_INTERNAL;
  31071             }
  31072 
  31073             BCM_IF_ERROR_RETURN(rv);
  31074 
  31075 
  31076             switch(slice_mode) {
  31077                 case 1:
  31078                 case 3:
  31079                     switch(ipType) {
  31080                         case bcmFieldIpTypeIp:
  31081                         case bcmFieldIpTypeIpv4NoOpts:
  31082                         case bcmFieldIpTypeIpv4Any:
  31083                         case bcmFieldIpTypeIpv6NoExtHdr:
  31084                         case bcmFieldIpTypeIpv6OneExtHdr:
  31085                         case bcmFieldIpTypeIpv6TwoExtHdr:
  31086                         case bcmFieldIpTypeIpv6:
  31087                             *can_qualify = 0;
  31088                             break;
  31089                         default :
  31090                             break;
  31091                     }
  31092                     break;
  31093                 case 2:
  31094                 case 5:
  31095                     switch(ipType) {
  31096                         case bcmFieldIpTypeIpv6NoExtHdr:
  31097                         case bcmFieldIpTypeIpv6OneExtHdr:
  31098                         case bcmFieldIpTypeIpv6TwoExtHdr:
  31099                         case bcmFieldIpTypeIpv6:
  31100                             *can_qualify = 0;
  31101                             break;
  31102 #if defined(BCM_TOMAHAWK_SUPPORT)
  31103                         case bcmFieldIpTypeIp:
  31104                         case bcmFieldIpTypeIpv4NoOpts:
  31105                         case bcmFieldIpTypeIpv4Any:
  31106                             if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  31107                                 *can_qualify = 0;
  31108                             }
  31109                             break;
  31110 #endif
  31111                         default :
  31112                             break;
  31113                     }
  31114                     break;
  31115                 default:
  31116                     break;
  31117             }
  31118             break;
  31119         default:
  31120             break;
  31121     }
  31122     return BCM_E_NONE;
  31123 }
  31124 /*
  31125  * Function:
  31126  *      _field_efp_key_match_type_set_on_qual_delete
  31127  *
  31128  * Purpose:
  31129  *      Utility routine for setting efp key match type of an entry
  31130  *      when qualifier is deleted from the entry.
  31131  *
  31132  * Parameters:
  31133  *      unit  - (IN) BCM device number
  31134  *      entry - (IN) Entry ID
  31135  * Returns:
  31136  *     BCM_E_XXX     - BCM device number
  31137  */
  31138 int
  31139 _field_efp_key_match_type_set_on_qual_delete(int unit, bcm_field_entry_t entry)
  31140 {
  31141     int             parts_count = 0;    /* Number of entry parts.          */
  31142     int             part_idx;           /* Entry parts iteration index.    */
  31143     int             qual_idx;           /* Part qualifiers iteration index.*/
  31144     int             rv;                 /* Operation return stauts.        */
  31145     int             idx;
  31146     int             found;
  31147     int             idx_max;
  31148     int             index;
  31149     uint32          width;
  31150     uint8           can_qualify = 1;
  31151     _field_group_t           *fg;       /* FP group info structure.        */
  31152     _field_entry_t           *f_ent;    /* Pointer to field entry          */
  31153     _bcm_field_qual_offset_t *q_offset; /* Qualifier offset structure      */
  31154     _bcm_field_group_qual_t  *q_arr;    /* Qualifiers array.               */
  31155     _bcm_field_group_qual_t  *q_arr_1;  /* Qualifiers array.               */
  31156     _bcm_field_qual_data_t    q_data;
  31157     _bcm_field_qual_data_t    q_mask;
  31158     /* Search the entry by eid. */
  31159     BCM_IF_ERROR_RETURN(_field_entry_get(unit, entry, _FP_ENTRY_PRIMARY,
  31160                                          &f_ent));
  31161 
  31162     fg = f_ent->group;
  31163     if (NULL == fg) {
  31164         return (BCM_E_INTERNAL);
  31165     }
  31166 
  31167     /* Get number of entry parts we have to read. */
  31168     rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
  31169                                             fg->flags, &parts_count);
  31170     BCM_IF_ERROR_RETURN(rv);
  31171 
  31172     for (part_idx = 0; part_idx < parts_count; part_idx++) {
  31173         q_arr = &(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part_idx]);
  31174         for (qual_idx = 0; qual_idx < q_arr->size; qual_idx++) {
  31175             idx_max = -1;
  31176             q_offset = q_arr->offset_arr + qual_idx;
  31177 
  31178             /* There is no value associated with zero
  31179              * width qualifiers (Stage, Ip4 etc)
  31180              */
  31181              _BCM_FIELD_QUAL_MULTI_OFFSET_WIDTH(q_offset, width);
  31182             if (0 == width) {
  31183                 continue;
  31184             }
  31185 
  31186             _FP_QUAL_DATA_CLEAR(q_data);
  31187             _FP_QUAL_DATA_CLEAR(q_mask);
  31188 
  31189 
  31190             /* Read qualifier match value and mask. */
  31191             rv = _bcm_field_qual_value_get(unit, q_offset,
  31192                                            f_ent + part_idx,
  31193                                            q_data, q_mask);
  31194             if (BCM_FAILURE(rv)) {
  31195                 return rv;
  31196             }
  31197 
  31198             /* Check if qualifier was installed. */
  31199             for (idx = 3; idx >= 0; idx--) {
  31200                 if (q_mask[idx] != 0)  {
  31201                     idx_max = idx;
  31202                     break;
  31203                 }
  31204             }
  31205 
  31206             if (idx_max >= 0) {
  31207                 found = FALSE;
  31208                 for (idx = 0; idx < parts_count; idx++) {
  31209                     q_arr_1 = &(fg->qual_arr[_FP_ENTRY_TYPE_1][idx]);
  31210                     for (index = 0; index < q_arr_1->size; index++) {
  31211                         if (q_arr->qid_arr[qual_idx] ==
  31212                             q_arr_1->qid_arr[index]) {
  31213                             found = TRUE;
  31214                             break;
  31215                         }
  31216                     }
  31217                     if (TRUE == found) {
  31218                         rv = _field_efp_entry_qual_value_qualify(unit, entry,
  31219                                                      q_arr->qid_arr[qual_idx],
  31220                                                      q_data, q_mask,
  31221                                                      &can_qualify);
  31222                         BCM_IF_ERROR_RETURN(rv);
  31223                         if (!can_qualify) {
  31224                             found = FALSE;
  31225                         } else {
  31226                            break;
  31227                         }
  31228                     }
  31229                 }
  31230                 if (FALSE == found) {
  31231                     f_ent->efp_key_match_type = _FP_ENTRY_TYPE_0;
  31232                     if (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) {
  31233                         (f_ent + 1)->efp_key_match_type = _FP_ENTRY_TYPE_0;
  31234                     }
  31235                     return BCM_E_NONE;
  31236                 }
  31237             }
  31238         }
  31239     }
  31240 
  31241     f_ent->efp_key_match_type = _FP_ENTRY_TYPE_1;
  31242     if (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) {
  31243         (f_ent + 1)->efp_key_match_type = _FP_ENTRY_TYPE_1;
  31244     }
  31245     return BCM_E_NONE;
  31246 }
  31247 /*
  31248  * Function:
  31249  *      _field_efp_key_match_type_set
  31250  *
  31251  * Purpose:
  31252  *      Utility routine for setting efp key match type of an entry
  31253  *
  31254  * Parameters:
  31255  *      unit     - (IN) BCM device number
  31256  *      qual_add - (IN) Flag to indicate qualifier is added/deleted
  31257  *      entry    - (IN) Entry ID
  31258  *      per_ent_key_type - (IN) Flag to indicate entry can fit in default key
  31259  *      grp_def_key_type - (IN) Flag to indicate entry can fit in original key
  31260  * Returns:
  31261  *     BCM_E_XXX     - BCM device number
  31262  */
  31263 int
  31264 _field_efp_key_match_type_set(int unit,
  31265                               uint8 qual_add,
  31266                               bcm_field_entry_t entry,
  31267                               uint8 per_ent_key_type,
  31268                               uint8 grp_def_key_type)
  31269 {
  31270     _field_group_t  *fg;  /* FP group info structure. */
  31271     _field_entry_t  *f_ent; /* Field entry info structure */
  31272     int8            use_per_ent_key_type;
  31273     int             rv;                 /* Operation return stauts.        */
  31274 
  31275     /* Search the entry by eid. */
  31276     BCM_IF_ERROR_RETURN(_field_entry_get(unit, entry, _FP_ENTRY_PRIMARY,
  31277                                          &f_ent));
  31278 
  31279     fg = f_ent->group;
  31280     if (NULL == fg) {
  31281         return (BCM_E_INTERNAL);
  31282     }
  31283 
  31284     use_per_ent_key_type = 0;
  31285     if (qual_add) {
  31286         /* When qualifier is added to the field entry */
  31287         if (grp_def_key_type) {
  31288             if (per_ent_key_type && f_ent->efp_key_match_type) {
  31289                 use_per_ent_key_type = 1;
  31290             }
  31291         } else {
  31292             return BCM_E_INTERNAL;
  31293         }
  31294 
  31295         f_ent->efp_key_match_type = use_per_ent_key_type;
  31296 
  31297         if (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) {
  31298             (f_ent + 1)->efp_key_match_type = use_per_ent_key_type;
  31299         }
  31300     } else {
  31301         /* When qualifier is deleted from the field entry */
  31302         if (_FP_ENTRY_TYPE_0 == f_ent->efp_key_match_type) {
  31303             rv = _field_efp_key_match_type_set_on_qual_delete(unit, entry);
  31304             if (BCM_FAILURE(rv)) {
  31305                 return rv;
  31306             }
  31307         }
  31308     }
  31309     return BCM_E_NONE;
  31310 }
  31311 /*
  31312  * Function:
  31313  *      _field_efp_qualify32
  31314  *
  31315  * Purpose:
  31316  *      Utility routine for qualify APIs taking 32 bits or less.
  31317  *      This routine applies to only EGRESS stage.
  31318  *
  31319  * Parameters:
  31320  *      unit  - (IN)BCM device number
  31321  *      entry - (IN)Entry ID
  31322  *      qual  - (IN) Qualifier field
  31323  *      data  - (IN)Matching data
  31324  *      mask  - (IN)Bit mask for data
  31325  *
  31326  * Returns:
  31327  *     BCM_E_NONE     - BCM device number
  31328  *     BCM_E_PARAM    - Qualifier not in group's Qset
  31329  *     BCM_E_INTERNAL - Entry doesnot belong to any group
  31330  */
  31331 int
  31332 _field_efp_qualify32(int unit, bcm_field_entry_t entry,
  31333                  int qual, uint32 *data, uint32 *mask)
  31334 {
  31335     _bcm_field_qual_offset_t *q_offset; /* Qualifier offset structure      */
  31336     _field_entry_t           *f_ent;    /* Field entry structure           */
  31337     _bcm_field_group_qual_t  *q_arr;    /* Qualifiers array.               */
  31338     int             parts_count = 0;    /* Number of entry parts.          */
  31339     int             part_idx;           /* Entry parts iteration index.    */
  31340     int             qual_idx;           /* Part qualifiers iteration index.*/
  31341     uint8           per_ent_key_type;   /* Entry lookup flags.             */
  31342     uint8           grp_def_key_type;   /* Entry lookup flags.             */
  31343     _field_group_t  *fg;                /* FP group info structure.        */
  31344     int             rv;                 /* Operation return stauts.        */
  31345     int             entry_type;         /* Type of an entry                */
  31346     uint8           can_qualify = 1;
  31347     uint32          multi_width;
  31348 #if defined(BCM_TRIDENT3_SUPPORT)
  31349     uint32          old_data = 0;
  31350 #endif /* BCM_TRIDENT3_SUPPORT */
  31351 
  31352     /* Search the entry by eid. */
  31353     rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent);
  31354     BCM_IF_ERROR_RETURN(rv);
  31355 
  31356     fg = f_ent->group;
  31357     if (NULL == fg) {
  31358         return (BCM_E_INTERNAL);
  31359     }
  31360     /* Get number of entry parts we have to read. */
  31361     rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
  31362                                             fg->flags, &parts_count);
  31363     BCM_IF_ERROR_RETURN(rv);
  31364 
  31365     /* update the EFP tcam.key and key_match_tcam.key */
  31366     if (f_ent->flags & _FP_ENTRY_INSTALLED &&
  31367         f_ent->flags != _FP_ENTRY_DIRTY) {
  31368         for (part_idx = 0; part_idx < parts_count; part_idx++) {
  31369             rv = _bcm_field_qual_tcam_key_mask_get(unit, f_ent+part_idx);
  31370             BCM_IF_ERROR_RETURN(rv);
  31371         }
  31372     }
  31373 
  31374     /* Get field entry part that contains the qualifier. */
  31375     rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent);
  31376     BCM_IF_ERROR_RETURN(rv);
  31377 
  31378     /* Get qualifier offsets in the tcam. */
  31379     rv = _field_qual_offset_get(unit, f_ent, qual, &q_offset);
  31380     BCM_IF_ERROR_RETURN(rv);
  31381 
  31382 
  31383     /* Exact match requested, make maximum mask value */
  31384     _BCM_FIELD_QUAL_MULTI_OFFSET_WIDTH(q_offset, multi_width);
  31385     if ((32 >= multi_width) &&
  31386         (*mask == (uint32)BCM_FIELD_EXACT_MATCH_MASK)) {
  31387 
  31388         *mask = ((32 == q_offset->width[0]) || (32 == multi_width))
  31389                   ? ~0 : ((1 << multi_width) - 1);
  31390 
  31391     }
  31392 
  31393     if (bcmFieldQualifyIpType == qual) {
  31394         rv = bcm_esw_field_qualifier_delete(unit, entry, qual);
  31395         BCM_IF_ERROR_RETURN(rv);
  31396     }
  31397 
  31398     grp_def_key_type = FALSE;
  31399     per_ent_key_type  = FALSE;
  31400 #if defined(BCM_TRIDENT3_SUPPORT)
  31401     /* to reset the data back to original data after being
  31402      * updated for bcmFieldQualifyDstVxlanGport
  31403      */
  31404     old_data = *data;
  31405 #endif /* BCM_TRIDENT3_SUPPORT */
  31406     for (entry_type = 0; entry_type < _FP_MAX_ENTRY_TYPES; entry_type++) {
  31407 
  31408         /* Search the entry by eid. */
  31409         rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent);
  31410         BCM_IF_ERROR_RETURN(rv);
  31411 
  31412         fg = f_ent->group;
  31413         if (NULL == fg) {
  31414             return (BCM_E_INTERNAL);
  31415         }
  31416 
  31417 
  31418         /* Iterate over all entry parts. */
  31419         for (part_idx = 0; part_idx < parts_count; part_idx++) {
  31420             /* Get part qualifiers array. */
  31421             q_arr = &(fg->qual_arr[entry_type][part_idx]);
  31422             /* Search array by qualifier id. */
  31423             for (qual_idx = 0; qual_idx < q_arr->size; qual_idx++) {
  31424                 if ((uint16)qual == q_arr->qid_arr[qual_idx]) {
  31425                     q_offset = q_arr->offset_arr + qual_idx;
  31426 #if defined(BCM_TRIDENT3_SUPPORT)
  31427                     /* for Trident3 devices, DstVxlanGPort qualifier is
  31428                      * supporting using dvp selector along with class b
  31429                      * selectors. If DVP selector is used, the dvp_valid
  31430                      * field should be enabled. Below code checks and
  31431                      * sets the DVP_valid bit in the tcam key where its
  31432                      * required based on the offset
  31433                      */
  31434                     if (soc_feature(unit, soc_feature_td3_style_fp)) {
  31435                         if (qual == bcmFieldQualifyDstVxlanGport) {
  31436                             if (entry_type == 1) {
  31437                                 *data = old_data;
  31438                             }
  31439                             if ((q_offset->offset[0] == 0) ||
  31440                                 (q_offset->offset[0] == 1) ) {
  31441                                 *data <<= 1;
  31442                                 /* Set DVP Valid bit. */
  31443                                 *data |= 1;
  31444                             }
  31445                         }
  31446                     }
  31447 #endif /* BCM_TRIDENT3_SUPPORT */
  31448                     if (_FP_ENTRY_TYPE_1 == entry_type) {
  31449                         per_ent_key_type = TRUE;
  31450                         /* Program data/mask pair to tcam buffer. */
  31451 
  31452                         /*
  31453                          * COVERITY
  31454                          *
  31455                          * This flow takes care of the  Out-of-bounds access
  31456                          * issue for data and mask.
  31457                          */
  31458 
  31459                         /* coverity[callee_ptr_arith : FALSE] */
  31460                         rv = _bcm_field_qual_value_set_by_entry_type(unit,
  31461                                                                q_offset,
  31462                                                                f_ent + part_idx,
  31463                                                                data, mask, 1);
  31464                         BCM_IF_ERROR_RETURN(rv);
  31465 
  31466                         /* When qualifier is found dont go for next qualifier
  31467                          *  in q_arr
  31468                          */
  31469                         break;
  31470 
  31471                     } else if (_FP_ENTRY_TYPE_0 == entry_type) {
  31472                         grp_def_key_type = TRUE;
  31473                         /* Program data/mask pair to tcam buffer. */
  31474 
  31475                         /*
  31476                          * COVERITY
  31477                          *
  31478                          * This flow takes care of the  Out-of-bounds access
  31479                          * issue for data and mask.
  31480                          */
  31481 
  31482                         /* coverity[callee_ptr_arith : FALSE] */
  31483 
  31484                         rv = _bcm_field_qual_value_set_by_entry_type(unit,
  31485                                                               q_offset,
  31486                                                               f_ent + part_idx,
  31487                                                               data, mask, 0);
  31488                         BCM_IF_ERROR_RETURN(rv);
  31489 
  31490                         /* When qualifier is found dont go for next qualifier
  31491                          *  in q_arr
  31492                          */
  31493                         break;
  31494                     }
  31495                 }
  31496             }
  31497 
  31498             /* When qualifier is found dont go for next partition */
  31499             if (((_FP_ENTRY_TYPE_0 == entry_type) && grp_def_key_type) ||
  31500                 ((_FP_ENTRY_TYPE_1 == entry_type) && per_ent_key_type)) {
  31501                 break;
  31502             }
  31503         }
  31504 
  31505         /* Qualifier must found in select code types populated
  31506          * by group create logic
  31507          */
  31508         if (FALSE == grp_def_key_type && (_FP_ENTRY_TYPE_0 == entry_type)) {
  31509             return (BCM_E_NOT_FOUND);
  31510         }
  31511 
  31512     }
  31513 
  31514     if (per_ent_key_type) {
  31515         rv = _field_efp_entry_qual_value_qualify(unit, entry, qual,
  31516                                              data, mask, &can_qualify);
  31517         BCM_IF_ERROR_RETURN(rv);
  31518         if (!can_qualify) {
  31519             per_ent_key_type = FALSE;
  31520         }
  31521     }
  31522 
  31523     rv = _field_efp_key_match_type_set(unit, TRUE, entry,
  31524                                        per_ent_key_type,
  31525                                        grp_def_key_type);
  31526     BCM_IF_ERROR_RETURN(rv);
  31527 
  31528     f_ent->flags |= _FP_ENTRY_DIRTY;
  31529 
  31530     return (BCM_E_NONE);
  31531 }
  31532 /*
  31533  * Function:
  31534  *     _field_qualify_macaddr_get
  31535  * Purpose:
  31536  *     Get qualifier Source or Destination mac address.
  31537  *
  31538  * Parameters:
  31539  *     unit     - (IN) BCM device number
  31540  *     entry    - (IN) Field entry to qualify on
  31541  *     qual     - (IN) Field qualifier id.
  31542  *     data     - (OUT)Data to qualify with (type varies)
  31543  *     mask     - (OUT)Mask to qualify with (type is same as for data)
  31544  *
  31545  * Returns:
  31546  *     BCM_E_INIT      - BCM Unit not initialized.
  31547  *     BCM_E_XXX       - Other errors
  31548  */
  31549 int
  31550 _field_qualify_macaddr_get(int unit, bcm_field_entry_t entry,
  31551                            bcm_field_qualify_t qual,
  31552                            bcm_mac_t *data, bcm_mac_t *mask)
  31553 {
  31554     _bcm_field_qual_offset_t *q_offset;
  31555     _field_entry_t           *f_ent;
  31556     uint32                   ref_data[_FP_QUAL_DATA_WORDS];
  31557     uint32                   ref_mask[_FP_QUAL_DATA_WORDS];
  31558     int                      rv;
  31559 
  31560     /* Input parameters check. */
  31561     if ((NULL == data) || (NULL == mask)) {
  31562         return (BCM_E_PARAM);
  31563     }
  31564 
  31565     /* Get field entry part that contains the qualifier. */
  31566     rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent);
  31567     BCM_IF_ERROR_RETURN(rv);
  31568 
  31569 #if defined(BCM_TOMAHAWK_SUPPORT)
  31570     if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  31571        /* Read qualifier match value and mask. */
  31572        rv = _field_entry_qualifier_key_get(unit, entry, qual,
  31573                                            ref_data, ref_mask);
  31574     } else
  31575 #endif /* BCM_TOMAHAWK_SUPPORT */
  31576     {
  31577        /* Get qualifier offsets in the tcam. */
  31578        rv = _field_qual_offset_get(unit, f_ent, qual, &q_offset);
  31579        BCM_IF_ERROR_RETURN(rv);
  31580 
  31581        /* Read qualifier match value and mask. */
  31582        rv = _bcm_field_qual_value_get(unit, q_offset, f_ent,
  31583                                       ref_data, ref_mask);
  31584     }
  31585     BCM_IF_ERROR_RETURN(rv);
  31586 
  31587     SAL_MAC_ADDR_FROM_UINT32((*data), ref_data);
  31588     SAL_MAC_ADDR_FROM_UINT32((*mask), ref_mask);
  31589 
  31590     return (BCM_E_NONE);
  31591 }
  31592 
  31593 /*
  31594  * Function:
  31595  *     _field_qualify_macaddr
  31596  * Purpose:
  31597  *     Qualify on a Source or Destination mac address.
  31598  *
  31599  * Parameters:
  31600  *     unit     - (IN) BCM device number
  31601  *     entry    - (IN) Field entry to qualify on
  31602  *     qual     - (IN) Field qualifier id.
  31603  *     data     - (IN) Data to qualify with (type varies)
  31604  *     mask     - (IN) Mask to qualify with (type is same as for data)
  31605  *
  31606  * Returns:
  31607  *     BCM_E_INIT      - BCM Unit not initialized.
  31608  *     BCM_E_XXX       - Other errors
  31609  */
  31610 int
  31611 _field_qualify_macaddr(int unit, bcm_field_entry_t entry,
  31612                     bcm_field_qualify_t qual,
  31613                     bcm_mac_t data, bcm_mac_t mask)
  31614 {
  31615     _bcm_field_qual_offset_t *q_offset;
  31616     _field_entry_t           *f_ent;
  31617     uint32                   ref_data[_FP_QUAL_DATA_WORDS];
  31618     uint32                   ref_mask[_FP_QUAL_DATA_WORDS];
  31619     int                      rv;
  31620 
  31621     SAL_MAC_ADDR_TO_UINT32(data, ref_data);
  31622     SAL_MAC_ADDR_TO_UINT32(mask, ref_mask);
  31623 
  31624     /* Get field entry part that contains the qualifier. */
  31625     rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent);
  31626     BCM_IF_ERROR_RETURN(rv);
  31627 
  31628 #if defined(BCM_TOMAHAWK_SUPPORT)
  31629     /* If device supports per-pipe FP configuration, */
  31630     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  31631         ((f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) ||
  31632         (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) ||
  31633         (f_ent->group->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER))) {
  31634         /* coverity[callee_ptr_arith : FALSE] */
  31635         return (_bcm_field_th_qualify_set(unit, entry, qual,
  31636                                           ref_data, ref_mask,
  31637                                           _FP_QUALIFIER_ADD));
  31638     }
  31639     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  31640         (f_ent->group->stage_id == _BCM_FIELD_STAGE_CLASS)) {
  31641         return (_bcm_field_th_class_qualify_set(unit, entry, qual,
  31642                                                 ref_data, ref_mask));
  31643     }
  31644 #endif /* BCM_TOMAHAWK_SUPPORT */
  31645 #if defined(BCM_TRIDENT2_SUPPORT)
  31646     if (SOC_IS_TD2_TT2(unit)) {
  31647         /* Redirect to _field_efp_qualify32 for egress stage */
  31648         if (f_ent->group->stage_id == _BCM_FIELD_STAGE_EGRESS) {
  31649             return _field_efp_qualify32(unit, entry, qual, ref_data, ref_mask);
  31650         }
  31651     }
  31652 #endif /* BCM_TRIDENT2_SUPPORT */
  31653 
  31654     /* Get qualifier offsets in the tcam. */
  31655     rv = _field_qual_offset_get(unit, f_ent, qual, &q_offset);
  31656     BCM_IF_ERROR_RETURN(rv);
  31657 
  31658     /* Program data/mask pair to tcam buffer. */
  31659    /*
  31660     * COVERITY
  31661     *
  31662     *This flow takes care of the  Out-of-bounds access issue
  31663     * for ref_data and ref_mask.
  31664     */
  31665     /* coverity[callee_ptr_arith : FALSE] */
  31666     rv = _bcm_field_qual_value_set(unit, q_offset, f_ent, ref_data, ref_mask);
  31667     return (rv);
  31668 }
  31669 
  31670 /*
  31671  * Function:
  31672  *     _field_qualify_Port
  31673  * Purpose:
  31674  *     Qualify on a Source or Destination Port.
  31675  *
  31676  * Parameters:
  31677  *     unit       - BCM device number
  31678  *     entry      - Field entry to qualify on
  31679  *     data_modid - Data to qualify with (type varies)
  31680  *     mask_modid - Mask to qualify with (type is same as for data)
  31681  *     data_port  - Data to qualify with (type varies)
  31682  *     mask_port  - Mask to qualify with (type is same as for data)
  31683  *
  31684  * Returns:
  31685  *     BCM_E_INIT      - BCM Unit not initialized.
  31686  *     BCM_E_INTERNAL  - qual neither SrcPort or DstPort
  31687  *     BCM_E_NOT_FOUND - Entry ID not found in unit.
  31688  *     BCM_E_PARAM     - port data out of range
  31689  *     BCM_E_XXX       - Other errors
  31690  */
  31691 int
  31692 _field_qualify_Port(int unit, bcm_field_entry_t entry,
  31693                     bcm_module_t data_modid, bcm_module_t mask_modid,
  31694                     bcm_port_t   data_port,  bcm_port_t   mask_port,
  31695                     bcm_field_qualify_t qual)
  31696 {
  31697     uint32 mod_port_data = 0;   /* concatenated modid and port */
  31698     uint32 mod_port_mask = 0;   /* concatenated modid and port */
  31699 
  31700     if (qual != bcmFieldQualifySrcPort
  31701         && qual != bcmFieldQualifyDstPort
  31702         && qual != bcmFieldQualifySrcGport
  31703         && qual != bcmFieldQualifyDstGport) {
  31704         LOG_ERROR(BSL_LS_BCM_FP,
  31705                   (BSL_META_U(unit,
  31706                               "FP(unit %d) Error: _field_qualify_Port() only works with"
  31707                                "SrcPort or DstPort \n"), unit));
  31708         return (BCM_E_INTERNAL);
  31709     }
  31710 
  31711     /* Range check data port */
  31712     if (!SOC_PORT_ADDRESSABLE(unit, data_port)) {
  31713         LOG_ERROR(BSL_LS_BCM_FP,
  31714                   (BSL_META_U(unit,
  31715                               "FP(unit %d) Error: data_port=%#x too large\n"),
  31716                    unit, data_port));
  31717         return (BCM_E_PARAM);
  31718     }
  31719 
  31720     /* Set masks to all ones if exact match is specified. */
  31721     if (mask_modid == BCM_FIELD_EXACT_MATCH_MASK) {
  31722         mask_modid = SOC_MODID_MAX(unit);
  31723     }
  31724     if (soc_feature(unit, soc_feature_trunk_group_overlay)) {
  31725         /* Trunk Bit (Tf) is not with Trunk/Port ID */
  31726         int num_bits_for_port;
  31727         if (mask_port == BCM_FIELD_EXACT_MATCH_MASK) {
  31728             mask_port = SOC_PORT_ADDR_MAX(unit);
  31729         }
  31730         num_bits_for_port = _shr_popcount((unsigned int)SOC_PORT_ADDR_MAX(unit));
  31731         /* SrcPort and DstPort are programmed as 0 - 7 bits are used to store port and 7 - 14 are for Module ID
  31732            num_bits_for_port is increased by 2 as SOC_PORT_ADDR_MAX returns 5 for Metrolite.
  31733         */
  31734 #if defined(BCM_METROLITE_SUPPORT)
  31735         if (SOC_IS_METROLITE(unit)) {
  31736             num_bits_for_port += 2;
  31737         }
  31738 #endif
  31739 
  31740         mod_port_data = (data_modid << num_bits_for_port) | data_port;
  31741         mod_port_mask = (mask_modid << num_bits_for_port) | mask_port;
  31742            /* Clear the trunk ID bit. */
  31743            mod_port_data &= ~(1 << SOC_TRUNK_BIT_POS(unit));
  31744            /* Must match on the T bit (which should be 0) */
  31745            mod_port_mask |= (1 << SOC_TRUNK_BIT_POS(unit));
  31746 
  31747         if (bcmFieldQualifyDstPort == qual || bcmFieldQualifyDstGport == qual) {
  31748             BCM_IF_ERROR_RETURN(_field_dest_type_qualify(unit,
  31749                                 entry, qual, &mod_port_data, &mod_port_mask,
  31750                                 _bcmFieldDestTypeDglp));
  31751         }
  31752 
  31753         return _field_qualify32(unit, entry, qual, mod_port_data, mod_port_mask);
  31754     }
  31755 
  31756     /* Note: Trunk bit is the MSB in PORT_TGID */
  31757     if (mask_port == BCM_FIELD_EXACT_MATCH_MASK) {
  31758         mask_port = (1 << (SOC_TRUNK_BIT_POS(unit) + 1)) - 1;
  31759     }
  31760 
  31761     /* Combine module IDs and ports */
  31762     mod_port_data = (data_modid << (SOC_TRUNK_BIT_POS(unit) + 1)) | data_port;
  31763     mod_port_mask = (mask_modid << (SOC_TRUNK_BIT_POS(unit) + 1)) | mask_port;
  31764 
  31765     /* Clear the trunk ID bit. */
  31766     mod_port_data &= ~(1 << SOC_TRUNK_BIT_POS(unit));
  31767     /* Must match on the T bit (which should be 0) */
  31768     mod_port_mask |= (1 << SOC_TRUNK_BIT_POS(unit));
  31769 
  31770     if (bcmFieldQualifyDstPort == qual || bcmFieldQualifyDstGport == qual) {
  31771         BCM_IF_ERROR_RETURN(_field_dest_type_qualify(unit,
  31772                             entry, qual, &mod_port_data, &mod_port_mask,
  31773                             _bcmFieldDestTypeDglp));
  31774     }
  31775 
  31776     return _field_qualify32(unit, entry, qual, mod_port_data, mod_port_mask);
  31777 }
  31778 
  31779 
  31780 /*
  31781  * Function:
  31782  *     _field_qualify_Port_get
  31783  * Purpose:
  31784  *     Qualify on a Source or Destination Port.
  31785  *
  31786  * Parameters:
  31787  *     unit       - BCM device number
  31788  *     entry      - Field entry to qualify on
  31789  *     data_modid - Data to qualify with (type varies)
  31790  *     mask_modid - Mask to qualify with (type is same as for data)
  31791  *     data_port  - Data to qualify with (type varies)
  31792  *     mask_port  - Mask to qualify with (type is same as for data)
  31793  *
  31794  * Returns:
  31795  *     BCM_E_INIT      - BCM Unit not initialized.
  31796  *     BCM_E_INTERNAL  - qual neither SrcPort or DstPort
  31797  *     BCM_E_NOT_FOUND - Entry ID not found in unit.
  31798  *     BCM_E_PARAM     - port data out of range
  31799  *     BCM_E_XXX       - Other errors
  31800  */
  31801 int
  31802 _field_qualify_Port_get(int unit, bcm_field_entry_t entry,
  31803                         bcm_module_t *data_modid,
  31804                         bcm_module_t *mask_modid,
  31805                         bcm_port_t   *data_port,
  31806                         bcm_port_t   *mask_port,
  31807                         bcm_field_qualify_t qual)
  31808 {
  31809     uint32    mod_port_data = 0; /* Concatenated modid and port */
  31810     uint32    mod_port_mask = 0; /* Concatenated modid and port */
  31811     int       rv;                /* Operation return stauts.    */
  31812     int       num_bits_for_port; /* Port field size.            */
  31813     int       trunk_bit_pos = 0;
  31814 
  31815     /* Input parameter check. */
  31816     if ((NULL == data_modid) || (NULL == mask_modid) ||
  31817         (NULL == data_port) || (NULL == mask_port)) {
  31818         return (BCM_E_PARAM);
  31819     }
  31820     /* Internal sanity check. */
  31821     if (qual != bcmFieldQualifySrcPort
  31822         && qual != bcmFieldQualifyDstPort
  31823         && qual != bcmFieldQualifySrcGport) {
  31824         return (BCM_E_INTERNAL);
  31825     }
  31826 
  31827     /* Read qualifier match value and mask. */
  31828     rv = _bcm_field_entry_qualifier_uint32_get(unit, entry, qual,
  31829                                            (uint32 *)&mod_port_data,
  31830                                            (uint32 *)&mod_port_mask);
  31831     BCM_IF_ERROR_RETURN(rv);
  31832 
  31833     if (qual == bcmFieldQualifyDstPort) {
  31834         BCM_IF_ERROR_RETURN(_field_dest_type_clear(unit,
  31835             entry, qual, (uint32 *) &mod_port_data, (uint32 *) &mod_port_mask));
  31836     }
  31837 
  31838     num_bits_for_port = _shr_popcount((unsigned int)SOC_PORT_ADDR_MAX(unit));
  31839     /* SrcPort and DstPort are programmed as 0 - 7 bits are used to store port and 7 - 14 are for Module ID
  31840        num_bits_for_port is increased by 2 as SOC_PORT_ADDR_MAX returns 5 for Metrolite.
  31841     */
  31842 
  31843 #if defined(BCM_METROLITE_SUPPORT)
  31844     if (SOC_IS_METROLITE(unit)) {
  31845         num_bits_for_port += 2;
  31846     }
  31847 #endif
  31848     /* Get the trunk bit position */
  31849     trunk_bit_pos = SOC_TRUNK_BIT_POS(unit);
  31850 
  31851     /* Clear the overlaid trunk bit from the modid mask. */
  31852     if (soc_feature(unit, soc_feature_trunk_group_overlay)) {
  31853     /* Get the trunk bit position */
  31854         mod_port_mask = mod_port_mask & ~(1 << trunk_bit_pos);
  31855        *data_modid =  mod_port_data >> num_bits_for_port;
  31856        *mask_modid =  mod_port_mask >> num_bits_for_port;
  31857 
  31858        *data_port = mod_port_data & ((1 << num_bits_for_port) - 1);
  31859        *mask_port = mod_port_mask & ((1 << num_bits_for_port) - 1);
  31860        return (rv);
  31861     }
  31862 
  31863     /* Get Modid Info */
  31864     *data_modid =  mod_port_data >> (trunk_bit_pos + 1);
  31865     *mask_modid =  mod_port_mask >> (trunk_bit_pos + 1);
  31866 
  31867     /* Get Port Info */
  31868     *data_port = mod_port_data & ((1 << trunk_bit_pos) - 1);
  31869     *mask_port = mod_port_mask & ((1 << trunk_bit_pos) - 1);
  31870     return (rv);
  31871 }
  31872 
  31873 #define _FIELD_TRUNK_BIT_INSERT(_u_, _t_)                       \
  31874     ((((_t_) & BCM_TGID_PORT_TRUNK_MASK_HI(_u_)) << 1) |        \
  31875      BCM_TGID_TRUNK_INDICATOR(_u_) | ((_t_) & BCM_TGID_PORT_TRUNK_MASK(_u_)))
  31876 
  31877 #define _FIELD_TRUNK_BIT_RESET(_u_, _t_)                        \
  31878     ((((_t_) - ((_t_) & BCM_TGID_PORT_TRUNK_MASK(_u_))) >> 1) | \
  31879      ((_t_) & BCM_TGID_PORT_TRUNK_MASK(_u_)))
  31880 
  31881 
  31882 /*
  31883  * Function:
  31884  *     _bcm_field_qualify_trunk
  31885  * Purpose:
  31886  *     Qualify on a Source or Destination Trunk ID.
  31887  *
  31888  * Parameters:
  31889  *     unit       - BCM device number
  31890  *     entry      - Field entry to qualify on
  31891  *     qual       - Field qualifier of type bcmFieldQualifyXXX.
  31892  *     data       - Trunk ID to qualify
  31893  *     mask       - Trunk mask to qualify
  31894  *
  31895  * Returns:
  31896  *     BCM_E_INIT      - BCM Unit not initialized.
  31897  *     BCM_E_INTERNAL  - qual neither SrcPort or DstPort
  31898  *     BCM_E_NOT_FOUND - Entry ID not found in unit.
  31899  *     BCM_E_PARAM     - Trunk ID or mask out of range
  31900  *     BCM_E_XXX       - Other errors
  31901  */
  31902 int
  31903 _bcm_field_qualify_trunk(int unit,
  31904                          bcm_field_entry_t entry,
  31905                          bcm_field_qualify_t qual,
  31906                          bcm_trunk_t data,
  31907                          bcm_trunk_t mask)
  31908 {
  31909     bcm_trunk_t               q_mask;
  31910     _field_entry_t            *f_ent;
  31911     _bcm_field_qual_offset_t  *q_offset;
  31912     uint32                    q_width;
  31913     int                       rv;
  31914     uint32 trunk_bit_pos = SOC_TRUNK_BIT_POS(unit);
  31915 
  31916     if (qual != bcmFieldQualifySrcTrunk && qual != bcmFieldQualifyDstTrunk
  31917        && qual != bcmFieldQualifySrcGport && qual != bcmFieldQualifyDstGport) {
  31918         LOG_ERROR(BSL_LS_BCM_FP,
  31919                   (BSL_META_U(unit,
  31920                               "FP(unit %d) Error: _bcm_field_qualify_trunk() only works with"
  31921                                "SrcTrunk or DstTrunk or SrcGport\n"), unit));
  31922         return (BCM_E_INTERNAL);
  31923     }
  31924 
  31925     /*
  31926      * Validate Trunk ID value. spn_TRUNK_EXTEND is TRUE when device
  31927      * supports more than 32 FP trunk groups.
  31928      */
  31929     if (soc_property_get(unit, spn_TRUNK_EXTEND, 1)
  31930         || soc_feature(unit, soc_feature_trunk_extended_only)) {
  31931         TRUNK_CHK_TGID_EXTENDED(unit, data);
  31932     } else {
  31933         TRUNK_CHK_TGID32(unit, data);
  31934     }
  31935 
  31936     /* Get field entry part that contains the qualifier. */
  31937     rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent);
  31938     BCM_IF_ERROR_RETURN(rv);
  31939 
  31940     if (soc_feature(unit, soc_feature_trunk_group_overlay)) {
  31941         /* Trunk Bit (Tf) is not with Trunk/Port ID */
  31942            data = data | (1 << trunk_bit_pos);
  31943            mask = mask | (1 << trunk_bit_pos);
  31944     } else {
  31945         data = _FIELD_TRUNK_BIT_INSERT(unit, data);
  31946         mask = _FIELD_TRUNK_BIT_INSERT(unit, mask);
  31947     }
  31948 
  31949     if (bcmFieldQualifyDstTrunk == qual || bcmFieldQualifyDstGport == qual) {
  31950         BCM_IF_ERROR_RETURN(_field_dest_type_qualify(unit,
  31951                             entry, qual, (uint32 *)&data, (uint32 *)&mask,
  31952                             _bcmFieldDestTypeDglp));
  31953     }
  31954 
  31955     /* Get qualifier offsets in the tcam. */
  31956     rv = _field_qual_offset_get(unit, f_ent, qual, &q_offset);
  31957     BCM_IF_ERROR_RETURN(rv);
  31958 
  31959     /*
  31960      * srcTrunk Qualifier contains TrunkBit + Module ID + Port ID
  31961      * MSB bit of Module ID indicates Remote trunk identifier
  31962      * Ignoring the remote trunk identifier bit.
  31963      * MSB bit position for MOD ID is TrunkBit position - 1
  31964      */
  31965     q_mask = ~(1 << (trunk_bit_pos-1));
  31966 
  31967     if (mask == (uint32)BCM_FIELD_EXACT_MATCH_MASK) {
  31968         /* Exact match requested, make maximum mask value */
  31969         _BCM_FIELD_QUAL_MULTI_OFFSET_WIDTH(q_offset, q_width);
  31970         mask =  (1 << q_width) - 1;
  31971     }
  31972     mask &= q_mask;
  31973 
  31974     return _field_qualify32(unit, entry, qual, data, mask);
  31975 }
  31976 
  31977 /*
  31978  * Function:
  31979  *     _bcm_field_qualify_trunk_get
  31980  * Purpose:
  31981  *     Get qualifiers  Trunk ID and mask.
  31982  *
  31983  * Parameters:
  31984  *     unit       - (IN)  BCM device number
  31985  *     entry      - (IN)  Field entry to qualify on
  31986  *     qual       - (IN)  Field Qualifier of type bcmFieldQualifyXXX.
  31987  *     data       - (OUT) Trunk ID to qualify
  31988  *     mask       - (OUT) Trunk mask to qualify
  31989  *
  31990  * Returns:
  31991  *     BCM_E_XXX
  31992  */
  31993 int
  31994 _bcm_field_qualify_trunk_get(int unit,
  31995                              bcm_field_entry_t entry,
  31996                              bcm_field_qualify_t qual,
  31997                              bcm_trunk_t *data,
  31998                              bcm_trunk_t *mask)
  31999 {
  32000     uint32    hw_data = 0;       /* HW buffer data.             */
  32001     uint32    hw_mask = 0;       /* HW buffer mask.             */
  32002     int       rv;                /* Operation return stauts.    */
  32003 
  32004     /* Input parameters check. */
  32005     if ((NULL == data) || (NULL == mask))  {
  32006         return (BCM_E_PARAM);
  32007     }
  32008 
  32009     if ((qual != bcmFieldQualifySrcTrunk) && (qual != bcmFieldQualifyDstTrunk)) {
  32010         return (BCM_E_INTERNAL);
  32011     }
  32012 
  32013     /* Read qualifier match value and mask. */
  32014     rv = _bcm_field_entry_qualifier_uint32_get(unit, entry, qual,
  32015                                            &hw_data, &hw_mask);
  32016     BCM_IF_ERROR_RETURN(rv);
  32017 
  32018     if (qual == bcmFieldQualifyDstTrunk) {
  32019         BCM_IF_ERROR_RETURN(_field_dest_type_clear(unit,
  32020             entry, qual, &hw_data, &hw_mask));
  32021     }
  32022 
  32023     if (soc_feature(unit, soc_feature_trunk_group_overlay)) {
  32024         /* Trunk Bit (Tf) is not with Trunk/Port ID */
  32025            *data = hw_data & ~(1 << SOC_TRUNK_BIT_POS(unit));
  32026            *mask = hw_mask & ~(1 << SOC_TRUNK_BIT_POS(unit));
  32027     } else {
  32028         *data = _FIELD_TRUNK_BIT_RESET(unit, hw_data);
  32029         *mask = _FIELD_TRUNK_BIT_RESET(unit, hw_mask);
  32030     }
  32031     return (BCM_E_NONE);
  32032 }
  32033 #undef _FIELD_TRUNK_BIT_INSERT
  32034 #undef _FIELD_TRUNK_BIT_RESET
  32035 
  32036 /*
  32037  * Function:
  32038  *      _field_qualify_source_virtual_port
  32039  *
  32040  * Purpose:
  32041  *      Utility routine to qualify MPLS/MIM Source Virtual Port.
  32042  * Parameters:
  32043  *      unit            - BCM device number
  32044  *      entry           - Entry ID
  32045  *      qual            - Qualifier field
  32046  *      data            - Matching data
  32047  *      mask            - Bit mask for data
  32048  *      ingress_entity  - Ingress entity type selector status
  32049  *
  32050  * Returns:
  32051  *     BCM_E_NONE     - BCM device number
  32052  *     BCM_E_PARAM    - Qualifier not in group's Qset
  32053  */
  32054 
  32055 int
  32056 _field_qualify_source_virtual_port(int unit, bcm_field_entry_t entry,
  32057                  int qual, uint32 data, uint32 mask, int ingress_entity)
  32058 {
  32059     _bcm_field_qual_offset_t *q_offset;
  32060     _field_entry_t *f_ent;
  32061     int rv;
  32062 
  32063     /* Get field entry part that contains the qualifier. */
  32064     rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent);
  32065     BCM_IF_ERROR_RETURN(rv);
  32066 
  32067     /* Get qualifier offsets in the tcam. */
  32068     rv = _field_qual_offset_get(unit, f_ent, qual, &q_offset);
  32069     BCM_IF_ERROR_RETURN(rv);
  32070 
  32071     if (((!SOC_IS_TRIDENT2X(unit) && !SOC_IS_TITAN2PLUS(unit)))
  32072         && (q_offset->secondary)) {
  32073         f_ent->flags |= _FP_ENTRY_USES_IPBM_OVERLAY;
  32074     }
  32075 
  32076     if (mask == (uint32)BCM_FIELD_EXACT_MATCH_MASK) {
  32077         /* Exact match requested, make maximum mask value */
  32078         mask = ((1 << q_offset->width[0]) - 1);
  32079         if ((_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) &&
  32080                 (SOC_IS_KATANAX(unit))) {
  32081             /*
  32082              * Setting Mask for SVP_VALID.
  32083              * In KT2, SB2 and ML SVP_VALID and S_FIELD are not sequent.
  32084              * Hence program mask with two different widths
  32085              */
  32086             mask |= (((1 << q_offset->width[1]) - 1) << q_offset->width[0]);
  32087         }
  32088     }
  32089 
  32090     if ((_BCM_FIELD_STAGE_EXTERNAL != f_ent->group->stage_id)
  32091         && (0 == ingress_entity)) {
  32092         /* Set SVP valid bit to TRUE */
  32093         data |= ((_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) &&
  32094                 (SOC_IS_KATANAX(unit))) ? (1 << (q_offset->width[0])) :
  32095                 (1 << (q_offset->width[0] - 1));
  32096     }
  32097 
  32098     /* Program data/mask pair to tcam buffer. */
  32099    /*
  32100     * COVERITY
  32101     *
  32102     *This flow takes care of the  Out-of-bounds access issue
  32103     * for data and mask.
  32104     */
  32105     /* coverity[callee_ptr_arith : FALSE] */
  32106     rv = _bcm_field_qual_value_set(unit, q_offset, f_ent, &data, &mask);
  32107     BCM_IF_ERROR_RETURN(rv);
  32108 
  32109     f_ent->flags |= _FP_ENTRY_DIRTY;
  32110     return (BCM_E_NONE);
  32111 }
  32112 
  32113 /*
  32114  * Function:
  32115  *      _field_qualifier32_input_range_check
  32116  *
  32117  * Purpose:
  32118  *      Utility routine for qualfiers input param check for
  32119  *      qualifiers whose h/w width is less than the bcm api data
  32120  *      width
  32121  * Parameters:
  32122  *     unit    - BCM device number
  32123  *     entry   - Entry Id
  32124  *     qual_id - Qualifier field
  32125  *     data    - Matching data
  32126  *     size    - size of data
  32127  * Return
  32128  *      BCM_E_NONE
  32129  *      BCM_E_PARAM
  32130  */
  32131 int _field_qualifier32_input_range_check (int unit, int qual, bcm_field_entry_t entry,
  32132                                      uint8 *data, int size)
  32133 {
  32134     int width = 0;
  32135     int rv = 0;
  32136     uint32 max_allowed_data = 0;
  32137     _field_entry_t *f_ent = NULL;
  32138     _bcm_field_qual_offset_t *q_offset;
  32139     int bitpos = 0;
  32140 
  32141     if ((data == NULL) || (size == 0)) {
  32142         return BCM_E_PARAM;
  32143     }
  32144 
  32145     /* Get field entry part that contains the qualifier. */
  32146     rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent);
  32147     BCM_IF_ERROR_RETURN(rv);
  32148 
  32149     rv = _field_qual_offset_get(unit, f_ent, qual, &q_offset);
  32150     BCM_IF_ERROR_RETURN(rv);
  32151 
  32152     _BCM_FIELD_QUAL_MULTI_OFFSET_WIDTH(q_offset, width);
  32153 
  32154     for (bitpos = 0; bitpos < width; bitpos++) {
  32155         max_allowed_data |= (1 << bitpos);
  32156     }
  32157 
  32158     switch (size) {
  32159         case 1:
  32160             if (max_allowed_data < (*data)) {
  32161                 return BCM_E_PARAM;
  32162             }
  32163             break;
  32164         case 2:
  32165             if (max_allowed_data < *((uint16 *)data)) {
  32166                 return BCM_E_PARAM;
  32167             }
  32168             break;
  32169         case 4:
  32170             if (max_allowed_data < *((uint32 *)data)) {
  32171                 return BCM_E_PARAM;
  32172             }
  32173             break;
  32174         default :
  32175             return BCM_E_PARAM;
  32176             break;
  32177     }
  32178 
  32179     return BCM_E_NONE;
  32180 }
  32181 
  32182 /*
  32183  * Function:
  32184  *      _field_qualify32
  32185  *
  32186  * Purpose:
  32187  *      Utility routine for qualify APIs taking 32 bits or less
  32188  *
  32189  * Parameters:
  32190  *      unit - BCM device number
  32191  *      entry - Entry ID
  32192  *      qual  - Qualifier field
  32193  *      data  - Matching data
  32194  *      mask  - Bit mask for data
  32195  *
  32196  * Returns:
  32197  *     BCM_E_NONE     - BCM device number
  32198  *     BCM_E_PARAM    - Qualifier not in group's Qset
  32199  */
  32200 
  32201 int
  32202 _field_qualify32(int unit, bcm_field_entry_t entry,
  32203                  int qual, uint32 data, uint32 mask)
  32204 {
  32205     _bcm_field_qual_offset_t *q_offset;
  32206     _field_entry_t           *f_ent;
  32207     int                      rv;
  32208 #if defined(BCM_TRIUMPH3_SUPPORT)
  32209     esm_l3_protocol_fn_entry_t  l3_proto_fn_entry;
  32210     uint32                      ip_proto, index = data;
  32211 #endif
  32212 
  32213 #if defined(BCM_TOMAHAWK_SUPPORT)
  32214     if (soc_feature(unit, soc_feature_field_preselector_support) &&
  32215         (_BCM_FIELD_IS_PRESEL_ENTRY(entry) == TRUE)) {
  32216         /* coverity[address_of : FALSE] */
  32217         /* coverity[callee_ptr_arith : FALSE] */
  32218         return _bcm_field_presel_qualify_set(unit, entry, qual, &data, &mask);
  32219     }
  32220 #endif /* BCM_TOMAHAWK_SUPPORT */
  32221 
  32222     /* Search the entry by eid. */
  32223     rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent);
  32224     BCM_IF_ERROR_RETURN(rv);
  32225 
  32226     if (NULL == f_ent->group) {
  32227         return (BCM_E_INTERNAL);
  32228     }
  32229 #if defined(BCM_TRIDENT2_SUPPORT)
  32230     if (SOC_IS_TD2_TT2(unit)) {
  32231         /* Redirect to _field_efp_qualify32 for egress stage */
  32232         if (f_ent->group->stage_id == _BCM_FIELD_STAGE_EGRESS) {
  32233            /*
  32234             * COVERITY
  32235             *
  32236             * This flow takes care of the Out-of-bounds access
  32237             * issue for data and mask.
  32238             */
  32239 
  32240             /* coverity[callee_ptr_arith : FALSE] */
  32241             return _field_efp_qualify32(unit, entry, qual, &data, &mask);
  32242         }
  32243     }
  32244 #endif
  32245 
  32246 #if defined(BCM_TOMAHAWK_SUPPORT)
  32247     /* If device supports per-pipe FP configuration, */
  32248     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  32249         ((f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) ||
  32250          (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) ||
  32251          (f_ent->group->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER))) {
  32252         /* coverity[address_of : FALSE] */
  32253         /* coverity[callee_ptr_arith : FALSE] */
  32254         return (_bcm_field_th_qualify_set(unit, entry, qual,
  32255                                           &data, &mask,
  32256                                           _FP_QUALIFIER_ADD));
  32257     }
  32258     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  32259             (f_ent->group->stage_id == _BCM_FIELD_STAGE_CLASS)) {
  32260         return (_bcm_field_th_class_qualify_set(unit, entry, qual,
  32261                                                 &data, &mask));
  32262     }
  32263 #endif /* BCM_TOMAHAWK_SUPPORT */
  32264 
  32265     /* Get field entry part that contains the qualifier. */
  32266     rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent);
  32267     BCM_IF_ERROR_RETURN(rv);
  32268 
  32269     /* Get qualifier offsets in the tcam. */
  32270     rv = _field_qual_offset_get(unit, f_ent, qual, &q_offset);
  32271     BCM_IF_ERROR_RETURN(rv);
  32272 
  32273     if (((!SOC_IS_TRIDENT2X(unit) && !SOC_IS_TITAN2PLUS(unit)))
  32274         && (q_offset->secondary))
  32275     {
  32276         f_ent->flags |= _FP_ENTRY_USES_IPBM_OVERLAY;
  32277     }
  32278 
  32279     if (mask == (uint32)BCM_FIELD_EXACT_MATCH_MASK) {
  32280         int multi_width;
  32281 
  32282         /* Exact match requested, make maximum mask value */
  32283         _BCM_FIELD_QUAL_MULTI_OFFSET_WIDTH(q_offset, multi_width);
  32284         mask = (32 == q_offset->width[0]) ? ~0 : ((1 << multi_width) - 1);
  32285     }
  32286 
  32287 #if defined(BCM_TRIUMPH3_SUPPORT)
  32288     if (SOC_IS_TRIUMPH3(unit)) {
  32289         if ((f_ent->group->stage_id == _BCM_FIELD_STAGE_EXTERNAL) &&
  32290                 (qual == bcmFieldQualifyIpProtocol) &&
  32291                 ((q_offset->offset[0] == 132) || (q_offset->offset[0] == 4)) &&
  32292                 (q_offset->width[0] == 4)) {
  32293             /* For EXT_IP4 EXT_L2IP4 and EXT_IP6S ACL, L3_PROTOCOL_FN value from
  32294                ESM_L3_PROTOCOL_FN table is treated as data to send it to
  32295                external TCAM as key */
  32296             BCM_IF_ERROR_RETURN(soc_mem_read(unit, ESM_L3_PROTOCOL_FNm,
  32297                                     MEM_BLOCK_ANY, index, &l3_proto_fn_entry));
  32298             soc_mem_field_get(unit, ESM_L3_PROTOCOL_FNm,
  32299                                     l3_proto_fn_entry.entry_data,
  32300                                     L3_PROTOCOL_FNf, &ip_proto);
  32301             data = ip_proto;
  32302             mask = 0xf;
  32303         }
  32304     }
  32305 #endif
  32306 
  32307     /* Program data/mask pair to tcam buffer. */
  32308    /*
  32309     * COVERITY
  32310     *
  32311     *This flow takes care of the  Out-of-bounds access issue
  32312     * for data and mask.
  32313     */
  32314     /* coverity[callee_ptr_arith : FALSE] */
  32315     rv = _bcm_field_qual_value_set(unit, q_offset, f_ent, &data, &mask);
  32316     BCM_IF_ERROR_RETURN(rv);
  32317 
  32318     f_ent->flags |= _FP_ENTRY_DIRTY;
  32319     return (BCM_E_NONE);
  32320 }
  32321 
  32322 /*
  32323  * Function:
  32324  *      _field_qualify_cpu_queue
  32325  *
  32326  * Purpose:
  32327  *      Utility routine to qualify cos queue.
  32328  * Parameters:
  32329  *      unit            - BCM device number
  32330  *      entry           - Entry ID
  32331  *      qual            - Qualifier field
  32332  *      data            - Matching data
  32333  *      mask            - Bit mask for data
  32334  *
  32335  * Returns:
  32336  *     BCM_E_NONE     - BCM device number
  32337  *     BCM_E_PARAM    - Qualifier not in group's Qset
  32338  */
  32339 int
  32340 _field_qualify_cpu_queue(int unit, bcm_field_entry_t entry,
  32341                          int qual, uint32 data, uint32 mask)
  32342 {
  32343     int rv = BCM_E_NONE;         /* return value of this function */
  32344     uint32 cos_queue_data = 0;   /* concatenated modified cpu queue and MSB 2
  32345                                     bits with 0 */
  32346     uint32 cos_queue_mask = 0;   /* concatenated modified cpu queue mask and
  32347                                     MSB 2 bits of original cpu queue mask */
  32348 #if defined(BCM_TRIDENT2_SUPPORT)
  32349     char nm = 0x0, nv = 0x0;     /* New mask and New value*/
  32350     char om = 0x0, ov = 0x0;     /* Original mask and original value */
  32351 #endif
  32352 
  32353     _field_entry_t *f_ent;
  32354     /* Get field entry part that contains the qualifier. */
  32355     rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent);
  32356     BCM_IF_ERROR_RETURN(rv);
  32357 
  32358     cos_queue_data = data;
  32359     cos_queue_mask = mask;
  32360 
  32361 #if defined(BCM_TRIDENT2_SUPPORT)
  32362     if (SOC_IS_TRIDENT2(unit) || SOC_IS_TITAN2(unit)) {
  32363         if (f_ent->group->stage_id == _BCM_FIELD_STAGE_EGRESS) {
  32364 
  32365             /* On Trident2 the CPU cos which ranges from 0~47, is shown as
  32366              * value=16~63 in EFP logic, basically the H/W adds 16 to the cos
  32367              * value in the key.So in S/W, 16 has to be added to actual data
  32368              * value and adjust the mask accordingly passed by application code.
  32369              * Since all the manipulation required to bit 5 and 6 of 6 bit wide
  32370              * CpuCosQNew, we will generate new mask and new data as in table
  32371              * below.We also save the MSB two bits of the mask into SPARE_DVP
  32372              * field in the EFP entry.
  32373              * So the cpuCosQNew is an 8 bit qualifier now.
  32374              *  --------------------------------------------------------------
  32375              * |Application calls API with  |   SDK writes S-CHAN with        |
  32376              * |----------------------------|---------------------------------|
  32377              * |             |              |   CPUCOS[5:4] | SPARE_DVP[1:0]  |
  32378              * |             |              |---------------|-----------------|
  32379              * |   MASK[5:4] |   DATA[5:4]  |   MASK | KEY  |   MASK | KEY    |
  32380              * |-------------|--------------|--------|------|--------|--------|
  32381              * |   00        |   xx         |    00  | 00   |   00   | 00     |
  32382              * |-------------|--------------|--------|------|--------|--------|
  32383              * |   01        |   x0         |    01  | 01   |   01   | 00     |
  32384              * |-------------|--------------|--------|------|--------|--------|
  32385              * |   01        |   x1         |    11  | 10   |   01   | 00     |
  32386              * |-------------|--------------|--------|------|--------|--------|
  32387              * |   10        |   0x         |    11  | 01   |   10   | 00     |
  32388              * |             |              |    ----|------|--------|--------|
  32389              * |             |              |    11  | 10   |   10   | 00     |
  32390              * |-------------|--------------|--------|------|--------|--------|
  32391              * |   10        |   10         |    11  | 10   |   10   | 00     |
  32392              * |-------------|--------------|--------|------|--------|--------|
  32393              * |   11        |   00         |    11  | 01   |   11   | 00     |
  32394              * |-------------|--------------|--------|------|--------|--------|
  32395              * |   11        |   01         |    11  | 10   |   11   | 00     |
  32396              * |-------------|--------------|--------|------|--------|--------|
  32397              * |   11        |   10         |    11  | 11   |   11   | 00     |
  32398              * |-------------|--------------|---------------------------------|
  32399              * |   11(or xx) |   11         |    Wrong Value from API,        |
  32400              * |             |              |    cpu only has 48 queues       |
  32401              *  --------------------------------------------------------------
  32402              */
  32403             cos_queue_data = 0;
  32404             cos_queue_mask = 0;
  32405             ov = (data >> 4) & 0x3;
  32406             om = (mask >> 4) & 0x3;
  32407             switch(om) {
  32408                 case 0x0:
  32409                 case 0x3:
  32410                     nm = om;
  32411                     nv = ov + 1;
  32412                     break;
  32413                 case 0x1:
  32414                     switch(ov) {
  32415                         case 0x0:
  32416                         case 0x2:
  32417                             nm = 0x1;
  32418                             nv = 0x1;
  32419                             break;
  32420                         case 0x1:
  32421                             nm = 0x3;
  32422                             nv = 0x2;
  32423                             break;
  32424                     }
  32425                     break;
  32426                 case 0x2:
  32427                     switch (ov) {
  32428                         case 0x0:
  32429                         case 0x1:
  32430                             /* Invalid DATA & MASK */
  32431                             rv = BCM_E_PARAM;
  32432                             break;
  32433                         case 0x2:
  32434                             nm = 0x3;
  32435                             nv = 0x2;
  32436                             break;
  32437                         case 0x3:
  32438                             /* Invalid DATA & MASK */
  32439                             rv = BCM_E_PARAM;
  32440                             break;
  32441                     }
  32442                     break;
  32443                     /* coverity[dead_error_begin] */
  32444                 default:
  32445                     /* Invalid DATA & MASK */
  32446                     rv = BCM_E_PARAM;
  32447             }
  32448 
  32449             if (BCM_E_NONE == rv) {
  32450 
  32451                 /* Building new mask and new data */
  32452 
  32453                 cos_queue_data = (data & ~(0x3 << 4)) | (nv << 0x4);
  32454                 cos_queue_mask = (mask & ~(0x3 << 4)) | (nm << 0x4);
  32455 
  32456                 /* copying upper most two bits[5:4] of riginal mask and 00 into
  32457                    MSB two bits[7:6] of new mask and new data respectively */
  32458 
  32459                 cos_queue_data = (cos_queue_data & ~(0x3 << 6));
  32460                 cos_queue_mask  = (cos_queue_mask & ~(0x3 << 6)) | (om << 0x6);
  32461             } else {
  32462                return rv;
  32463             }
  32464         }
  32465     }
  32466 #endif
  32467 
  32468     rv = _field_qualify32(unit, entry, qual, cos_queue_data, cos_queue_mask);
  32469     BCM_IF_ERROR_RETURN(rv);
  32470 
  32471     f_ent->flags |= _FP_ENTRY_DIRTY;
  32472     return (BCM_E_NONE);
  32473 }
  32474 /*
  32475  * Function:
  32476  *      _field_qualify_cpu_queue_get
  32477  *
  32478  * Purpose:
  32479  *      Utility routine to extract qualifier cos queue data and mask.
  32480  * Parameters:
  32481  *      unit            - (IN) BCM device number
  32482  *      entry           - (IN) Entry ID
  32483  *      qual            - (IN) Qualifier field
  32484  *      data            - (OUT) Qualifier data
  32485  *      mask            - (OUT) Qualifier mask
  32486  *
  32487  * Returns:
  32488  *     BCM_E_NONE     - BCM device number
  32489  *     BCM_E_PARAM    - Qualifier not in group's Qset
  32490  */
  32491 int
  32492 _field_qualify_cpu_queue_get(int unit, bcm_field_entry_t entry,
  32493                          int qual, uint8 *data, uint8 *mask)
  32494 {
  32495     int rv = BCM_E_NONE;
  32496 
  32497 #if defined(BCM_TRIDENT2_SUPPORT)
  32498     _field_entry_t *f_ent;
  32499     /* Get field entry part that contains the qualifier. */
  32500     rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent);
  32501     BCM_IF_ERROR_RETURN(rv);
  32502 #endif
  32503 
  32504     if (NULL == data || NULL == mask) {
  32505         return BCM_E_PARAM;
  32506     }
  32507 
  32508     /* Read qualifier match value and mask. */
  32509     rv =  _bcm_field_entry_qualifier_uint8_get(unit, entry,
  32510                        bcmFieldQualifyCpuQueue, data, mask);
  32511     BCM_IF_ERROR_RETURN(rv);
  32512 
  32513 #if defined(BCM_TRIDENT2_SUPPORT)
  32514     if (SOC_IS_TRIDENT2(unit) || SOC_IS_TITAN2(unit)) {
  32515         if (f_ent->group->stage_id == _BCM_FIELD_STAGE_EGRESS) {
  32516 
  32517             *mask = ((*mask & 0xf) | ((*mask & 0xc0) >> 0x2));
  32518             if (*mask & 0x10) {
  32519                 *data = *data - 0x10;
  32520             } else {
  32521                 *data = *data & *mask;
  32522             }
  32523         }
  32524     }
  32525 #endif
  32526 
  32527     return rv;
  32528 }
  32529 /*
  32530  * Function:
  32531  *      _field_qualify_ip6_get
  32532  *
  32533  * Purpose:
  32534  *      Utility routine to extract qualifier IPv6 data and mask.
  32535  *
  32536  * Parameters:
  32537  *     unit   - (IN) BCM device number
  32538  *     entry  - (IN) BCM field entry id.
  32539  *     qual   - (IN) Qualifier id.
  32540  *     flags  - (IN) Part of IPv6 address specification.
  32541  *     data   - (OUT) Qualifier data.
  32542  *     mask   - (OUT) Qualifier mask.
  32543  * Returns:
  32544  *     BCM_E_XXX
  32545  */
  32546 
  32547 int
  32548 _field_qualify_ip6_get(int unit, bcm_field_entry_t entry,
  32549                    bcm_field_qualify_t qual,
  32550                    bcm_ip6_t *data, bcm_ip6_t *mask)
  32551 {
  32552     _bcm_field_qual_offset_t *q_offset;
  32553     _field_entry_t           *f_ent;
  32554     uint32                   ref_data[_FP_QUAL_DATA_WORDS];
  32555     uint32                   ref_mask[_FP_QUAL_DATA_WORDS];
  32556     uint8                    ref_offset;
  32557     int                      rv;
  32558     int                      i;
  32559 
  32560     /* Input parameters check. */
  32561     if ((NULL == data) || (NULL == mask)) {
  32562         return (BCM_E_PARAM);
  32563     }
  32564 
  32565     /* Initialization. */
  32566     sal_memset(ref_data, 0, 4 * sizeof(uint32));
  32567     sal_memset(ref_mask, 0, 4 * sizeof(uint32));
  32568     switch(qual) {
  32569       case bcmFieldQualifySrcIp6High:
  32570       case bcmFieldQualifyDstIp6High:
  32571       case bcmFieldQualifyInnerSrcIp6High:
  32572       case bcmFieldQualifyInnerDstIp6High:
  32573           ref_offset = 2;
  32574           break;
  32575       default:
  32576           ref_offset = 0;
  32577     }
  32578 
  32579     /* Get field entry part that contains qualifier. */
  32580     rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent);
  32581     BCM_IF_ERROR_RETURN(rv);
  32582 
  32583 #if defined(BCM_TOMAHAWK_SUPPORT)
  32584     /* If device supports per-pipe FP configuration, */
  32585     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  32586         ((f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) ||
  32587          (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) ||
  32588          (f_ent->group->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER))) {
  32589        /* Read qualifier match value and mask. */
  32590        rv = _bcm_field_th_entry_qualifier_key_get(unit, entry, qual,
  32591                                                   ref_data, ref_mask);
  32592        BCM_IF_ERROR_RETURN(rv);
  32593     } else if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  32594                     (f_ent->group->stage_id == _BCM_FIELD_STAGE_CLASS)) {
  32595 
  32596         /* Read qualifier match value and mask. */
  32597         rv = _bcm_field_th_class_entry_qualifier_key_get(unit, entry, qual,
  32598                                                          ref_data, ref_mask);
  32599         BCM_IF_ERROR_RETURN(rv);
  32600     } else
  32601 #endif /* BCM_TOMAHAWK_SUPPORT */
  32602     {
  32603        /* Get qualifier offsets in the tcam. */
  32604        rv = _field_qual_offset_get(unit, f_ent, qual, &q_offset);
  32605        BCM_IF_ERROR_RETURN(rv);
  32606 
  32607        /* Read qualifier match value and mask. */
  32608        rv = _bcm_field_qual_value_get(unit, q_offset, f_ent,
  32609                                       ref_data, ref_mask);
  32610        BCM_IF_ERROR_RETURN(rv);
  32611     }
  32612 
  32613     /* Rearrange data and mask according to reference offset */
  32614     for (i = (_FP_QUAL_DATA_WORDS - 1); i >= ref_offset ; i--) {
  32615          ref_data[i] = ref_data[i - ref_offset];
  32616          ref_mask[i] = ref_mask[i - ref_offset];
  32617     }
  32618     for (i = 0; i < ref_offset; i++) {
  32619          ref_data[i] = 0x0;
  32620          ref_mask[i] = 0x0;
  32621     }
  32622 
  32623     SAL_IP6_ADDR_FROM_UINT32((*data), ref_data);
  32624     SAL_IP6_ADDR_FROM_UINT32((*mask), ref_mask);
  32625 
  32626     return (BCM_E_NONE);
  32627 }
  32628 
  32629 /*
  32630  * Function:
  32631  *      _field_qualify_ip6
  32632  *
  32633  * Purpose:
  32634  *      Utility routine for qualify APIs taking IPv6 data and mask.
  32635  *
  32636  * Parameters:
  32637  *     unit   - (IN) BCM device number
  32638  *     entry  - (IN) BCM field entry id.
  32639  *     qual   - (IN) Qualifier id.
  32640  *     data   - (IN) Qualifier data.
  32641  *     mask   - (IN) Qualifier mask.
  32642  * Returns:
  32643  *     BCM_E_XXX
  32644  */
  32645 
  32646 int
  32647 _field_qualify_ip6(int unit, bcm_field_entry_t entry,
  32648                    bcm_field_qualify_t qual,
  32649                    bcm_ip6_t data, bcm_ip6_t mask)
  32650 {
  32651     _bcm_field_qual_offset_t *q_offset;
  32652     _field_entry_t           *f_ent;
  32653     uint32                   ref_data[_FP_QUAL_DATA_WORDS];
  32654     uint32                   ref_mask[_FP_QUAL_DATA_WORDS];
  32655     uint8                    ref_offset;
  32656     int                      rv;
  32657 
  32658     LOG_DEBUG(BSL_LS_BCM_FP,
  32659               (BSL_META_U(unit,
  32660                           "_field_qualify_ip6\n")));
  32661 
  32662     /* Initialization. */
  32663     switch(qual) {
  32664       case bcmFieldQualifySrcIp6High:
  32665       case bcmFieldQualifyDstIp6High:
  32666       case bcmFieldQualifyInnerSrcIp6High:
  32667       case bcmFieldQualifyInnerDstIp6High:
  32668           ref_offset = 2;
  32669           break;
  32670       default:
  32671           ref_offset = 0;
  32672     }
  32673 
  32674     /* Get field entry part that contains qualifier. */
  32675     rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent);
  32676     BCM_IF_ERROR_RETURN(rv);
  32677 
  32678     /* Get qualifier offsets in the tcam. */
  32679     rv = _field_qual_offset_get(unit, f_ent, qual, &q_offset);
  32680     BCM_IF_ERROR_RETURN(rv);
  32681 
  32682     SAL_IP6_ADDR_TO_UINT32(data, ref_data);
  32683     SAL_IP6_ADDR_TO_UINT32(mask, ref_mask);
  32684 
  32685 #if defined(BCM_TOMAHAWK_SUPPORT)
  32686     /* If device supports per-pipe FP configuration, */
  32687     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  32688         ((f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) ||
  32689          (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) ||
  32690          (f_ent->group->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER))) {
  32691         /* coverity[callee_ptr_arith : FALSE] */
  32692         return (_bcm_field_th_qualify_set(unit, entry, qual,
  32693                                           ref_data + ref_offset,
  32694                                           ref_mask + ref_offset,
  32695                                           _FP_QUALIFIER_ADD));
  32696     }
  32697     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  32698             (f_ent->group->stage_id == _BCM_FIELD_STAGE_CLASS)) {
  32699         return (_bcm_field_th_class_qualify_set(unit, entry, qual,
  32700                                                 ref_data + ref_offset,
  32701                                                 ref_mask + ref_offset));
  32702     }
  32703 #endif /* BCM_TOMAHAWK_SUPPORT */
  32704 
  32705 #if defined(BCM_TRIDENT2_SUPPORT)
  32706     if (SOC_IS_TD2_TT2(unit)) {
  32707         /* Redirect to _field_efp_qualify32 for egress stage */
  32708         if (f_ent->group->stage_id == _BCM_FIELD_STAGE_EGRESS) {
  32709             return _field_efp_qualify32(unit, entry, qual,
  32710                                         ref_data + ref_offset,
  32711                                         ref_mask + ref_offset);
  32712         }
  32713     }
  32714 #endif
  32715 
  32716     /* Program data/mask pair to tcam buffer. */
  32717    /*
  32718     * COVERITY
  32719     *
  32720     *This flow takes care of the  Out-of-bounds access issue
  32721     * for ref_data and ref_mask.
  32722     */
  32723     /* coverity[callee_ptr_arith : FALSE] */
  32724     rv = _bcm_field_qual_value_set(unit, q_offset, f_ent,
  32725                                    ref_data + ref_offset,
  32726                                    ref_mask + ref_offset);
  32727     BCM_IF_ERROR_RETURN(rv);
  32728 
  32729     f_ent->flags |= _FP_ENTRY_DIRTY;
  32730     return (BCM_E_NONE);
  32731 }
  32732 
  32733 /*
  32734  * Function:
  32735  *      _field_qualify_L2PayloadFirstEightBytes_get
  32736  *
  32737  * Purpose:
  32738  *      Utility routine to extract qualifier L2PayloadFirstEightBytes
  32739  *      data and mask.
  32740  *
  32741  * Parameters:
  32742  *     unit   - (IN) BCM device number
  32743  *     entry  - (IN) BCM field entry id.
  32744  *     qual   - (IN) Qualifier id.
  32745  *     data1   - (OUT) Qualifier first four bytes of match data.
  32746  *     data2   - (OUT) Qualifier last four bytes of match data.
  32747  *     mask1   - (OUT) Qualifier first four bytes of match mask.
  32748  *     mask2   - (OUT) Qualifier last four bytes of match mask.
  32749  * Returns:
  32750  *     BCM_E_XXX
  32751  */
  32752 
  32753 int
  32754 _field_qualify_L2PayloadFirstEightBytes_get(int unit,
  32755                                             bcm_field_entry_t entry,
  32756                                             bcm_field_qualify_t qual,
  32757                                             uint32 *data1, uint32 *data2,
  32758                                             uint32 *mask1, uint32 *mask2)
  32759 {
  32760     _bcm_field_qual_offset_t *q_offset;
  32761     _field_entry_t           *f_ent;
  32762     uint32                   ref_data[_FP_QUAL_DATA_WORDS];
  32763     uint32                   ref_mask[_FP_QUAL_DATA_WORDS];
  32764     int                      rv;
  32765 
  32766     /* Input parameters check. */
  32767     if ((NULL == data1) || (NULL == data2) ||
  32768         (NULL == mask1) || (NULL == mask2)) {
  32769         return (BCM_E_PARAM);
  32770     }
  32771 
  32772     /* Get field entry part that contains qualifier. */
  32773     rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent);
  32774     BCM_IF_ERROR_RETURN(rv);
  32775 
  32776     sal_memset(&ref_data, 0, sizeof(ref_data));
  32777     sal_memset(&ref_mask, 0, sizeof(ref_mask));
  32778 
  32779 #if defined(BCM_TOMAHAWK_SUPPORT)
  32780     /* If device supports per-pipe FP configuration, */
  32781     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  32782         ((f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) ||
  32783         (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH))) {
  32784        /* Read qualifier match value and mask. */
  32785        rv = _bcm_field_th_entry_qualifier_key_get(unit, entry, qual,
  32786                                                   ref_data, ref_mask);
  32787        BCM_IF_ERROR_RETURN(rv);
  32788     } else if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  32789             (f_ent->group->stage_id == _BCM_FIELD_STAGE_CLASS)) {
  32790 
  32791         /* Read qualifier match value and mask. */
  32792         rv = _bcm_field_th_class_entry_qualifier_key_get(unit, entry, qual,
  32793                                                          ref_data, ref_mask);
  32794         BCM_IF_ERROR_RETURN(rv);
  32795     } else
  32796 #endif /* BCM_TOMAHAWK_SUPPORT */
  32797     {
  32798        /* Get qualifier offsets in the tcam. */
  32799        rv = _field_qual_offset_get(unit, f_ent, qual, &q_offset);
  32800        BCM_IF_ERROR_RETURN(rv);
  32801 
  32802        /* Read qualifier match value and mask. */
  32803        rv = _bcm_field_qual_value_get(unit, q_offset, f_ent, ref_data,
  32804                                       ref_mask);
  32805        BCM_IF_ERROR_RETURN(rv);
  32806     }
  32807 
  32808     _FP_UNPACK_L2_EIGHT_BYTES_PAYLOAD(ref_data, data1, data2);
  32809     _FP_UNPACK_L2_EIGHT_BYTES_PAYLOAD(ref_mask, mask1, mask2);
  32810 
  32811     return (BCM_E_NONE);
  32812 }
  32813 
  32814 /*
  32815  * Function:
  32816  *      _field_qualify_L2PayloadFirstEightBytes
  32817  *
  32818  * Purpose:
  32819  *      Utility routine for qualify L2PayloadFirstEightBytes
  32820  *      data and mask.
  32821  *
  32822  * Parameters:
  32823  *     unit   - (IN) BCM device number
  32824  *     entry  - (IN) BCM field entry id.
  32825  *     qual   - (IN) Qualifier id.
  32826  *     data1  - (IN) Qualifier first four bytes of match data.
  32827  *     data2  - (IN) Qualifier last four bytes of match data.
  32828  *     mask1  - (IN) Qualifier first four bytes of match mask.
  32829  *     mask2  - (IN) Qualifier last four bytes of match mask.
  32830  *
  32831  * Returns:
  32832  *     BCM_E_XXX
  32833  */
  32834 
  32835 int
  32836 _field_qualify_L2PayloadFirstEightBytes(int unit,
  32837                                         bcm_field_entry_t entry,
  32838                                         bcm_field_qualify_t qual,
  32839                                         uint32 data1, uint32 data2,
  32840                                         uint32 mask1, uint32 mask2)
  32841 {
  32842     _bcm_field_qual_offset_t *q_offset;
  32843     _field_entry_t           *f_ent;
  32844     uint32                   ref_data[_FP_QUAL_DATA_WORDS];
  32845     uint32                   ref_mask[_FP_QUAL_DATA_WORDS];
  32846     int                      rv;
  32847 
  32848     LOG_DEBUG(BSL_LS_BCM_FP,
  32849               (BSL_META_U(unit,
  32850                           "_field_qualify_L2PayloadFirstEightBytes\n")));
  32851 
  32852     sal_memset(&ref_data, 0, sizeof(ref_data));
  32853     sal_memset(&ref_mask, 0, sizeof(ref_mask));
  32854 
  32855     _FP_PACK_L2_EIGHT_BYTES_PAYLOAD(data1, data2, ref_data);
  32856     _FP_PACK_L2_EIGHT_BYTES_PAYLOAD(mask1, mask2, ref_mask);
  32857 
  32858     /* Get field entry part that contains qualifier. */
  32859     rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent);
  32860     BCM_IF_ERROR_RETURN(rv);
  32861 
  32862 #if defined(BCM_TOMAHAWK_SUPPORT)
  32863     /* If device supports per-pipe FP configuration, */
  32864     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  32865         ((f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) ||
  32866          (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH))) {
  32867         /* coverity[callee_ptr_arith : FALSE] */
  32868         return (_bcm_field_th_qualify_set(unit, entry, qual,
  32869                                           ref_data, ref_mask,
  32870                                           _FP_QUALIFIER_ADD));
  32871     }
  32872     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  32873         (f_ent->group->stage_id == _BCM_FIELD_STAGE_CLASS)) {
  32874         return (_bcm_field_th_class_qualify_set(unit, entry, qual,
  32875                                                 ref_data, ref_mask));
  32876     }
  32877 #endif /* BCM_TOMAHAWK_SUPPORT */
  32878 
  32879     /* Get qualifier offsets in the tcam. */
  32880     rv = _field_qual_offset_get(unit, f_ent, qual, &q_offset);
  32881     BCM_IF_ERROR_RETURN(rv);
  32882 
  32883     /* Program data/mask pair to tcam buffer. */
  32884    /*
  32885     * COVERITY
  32886     *
  32887     *This flow takes care of the  Out-of-bounds access issue
  32888     * for ref_data and ref_mask.
  32889     */
  32890     /* coverity[callee_ptr_arith : FALSE] */
  32891     rv = _bcm_field_qual_value_set(unit, q_offset, f_ent, ref_data,
  32892                                    ref_mask);
  32893     BCM_IF_ERROR_RETURN(rv);
  32894 
  32895     f_ent->flags |= _FP_ENTRY_DIRTY;
  32896     return (BCM_E_NONE);
  32897 }
  32898 
  32899 /*
  32900  * Function:
  32901  *     _field_entry_shift_down
  32902  * Purpose:
  32903  *
  32904  * Parameters:
  32905  *     unit     - BCM device number
  32906  *     target_fs - slice where the entry in prio_set should go
  32907  *     target_index - corresponding index
  32908  *     next_null_fs - slice which contains a NULL entry after target_index
  32909  *     next_null_index - corresponding index
  32910  * Returns:
  32911  *     BCM_E_NONE   - Success
  32912  */
  32913 STATIC int
  32914 _field_entry_shift_down(int unit, _field_group_t *fg,
  32915                         _field_slice_t *target_fs, uint16 target_index,
  32916                         _field_slice_t *next_null_fs, uint16 next_null_index)
  32917 {
  32918     uint16              slice_idx_empty;
  32919     _field_stage_t      *stage_fc;
  32920     int                 slice_sz;
  32921     int                 tmp_idx1;
  32922     int                 tmp_idx2;
  32923     _field_slice_t      *fs;
  32924     int                 rv;
  32925 
  32926     /* Input parameter check. */
  32927     if ((NULL == target_fs) || (NULL == fg) || (NULL == next_null_fs))  {
  32928         return (BCM_E_PARAM);
  32929     }
  32930 
  32931     if (target_fs->slice_flags & _BCM_FIELD_SLICE_MULTIMODE_ENTRIES) {
  32932         return _field_multimode_slice_entry_shift_down(unit, fg,
  32933                                 target_fs, target_index,
  32934                                 next_null_fs, next_null_index);
  32935     }
  32936 
  32937     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, target_fs->stage_id,
  32938                                                  &stage_fc));
  32939 
  32940     slice_idx_empty = next_null_index;
  32941     fs = next_null_fs;
  32942 
  32943     /*
  32944      * Move entries one step down
  32945      *     starting from the last entry
  32946      * IDEA:
  32947      *     when in different slices, target_fs != fs
  32948      *     when in same slice, move till slice_idx_empty > target_index
  32949      */
  32950     while ((slice_idx_empty > target_index) || (target_fs != fs)) {
  32951         /* Move the entry at the previous index to the empty index. */
  32952         if (slice_idx_empty == 0) {
  32953             /* Get number of entries in slice. */
  32954             _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs->prev, slice_sz);
  32955 
  32956             /* Get higher slice first entry tcam index. */
  32957             rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc,
  32958                                                      fg->instance,
  32959                                                      fs->slice_number,
  32960                                                      slice_idx_empty,
  32961                                                      &tmp_idx1);
  32962             BCM_IF_ERROR_RETURN(rv);
  32963 
  32964             /* Get lower slice last entry tcam index. */
  32965             rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc,
  32966                                                      fg->instance,
  32967                                                      fs->prev->slice_number,
  32968                                                      slice_sz - 1, &tmp_idx2);
  32969             BCM_IF_ERROR_RETURN(rv);
  32970 
  32971             /* Perform entry move. */
  32972             rv = _field_entry_move(unit, fs->prev->entries[slice_sz-1],
  32973                                    (tmp_idx1 - tmp_idx2));
  32974             BCM_IF_ERROR_RETURN(rv);
  32975 
  32976             slice_idx_empty = slice_sz - 1;
  32977             fs = fs->prev;
  32978         } else {
  32979             /* Get higher entry tcam index. */
  32980             rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc,
  32981                                                      fg->instance,
  32982                                                      fs->slice_number,
  32983                                                      slice_idx_empty,
  32984                                                      &tmp_idx1);
  32985             BCM_IF_ERROR_RETURN(rv);
  32986 
  32987             /* Get lower entry tcam index. */
  32988             rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc,
  32989                                                      fg->instance,
  32990                                                      fs->slice_number,
  32991                                                      slice_idx_empty - 1,
  32992                                                      &tmp_idx2);
  32993             BCM_IF_ERROR_RETURN(rv);
  32994 
  32995             /* Perform entry move. */
  32996             rv = _field_entry_move(unit, fs->entries[slice_idx_empty - 1],
  32997                                    (tmp_idx1 - tmp_idx2));
  32998             BCM_IF_ERROR_RETURN(rv);
  32999 
  33000             slice_idx_empty--;
  33001         }
  33002     }
  33003 
  33004     return (BCM_E_NONE);
  33005 }
  33006 
  33007 /*
  33008  * Function:
  33009  *     _field_entry_shift_up
  33010  * Purpose:
  33011  *
  33012  * Parameters:
  33013  *     unit     - BCM device number
  33014  *     target_fs - slice where the entry in prio_set should go
  33015  *     target_index - corresponding index
  33016  *     prev_null_fs - slice which contains a NULL entry before target_index
  33017  *     prev_null_index - corresponding index
  33018  * Returns:
  33019  *     BCM_E_NONE   - Success
  33020  */
  33021 STATIC int
  33022 _field_entry_shift_up(int unit, _field_group_t *fg,
  33023                       _field_slice_t *target_fs, uint16 target_index,
  33024                       _field_slice_t *prev_null_fs, uint16 prev_null_index)
  33025 {
  33026     uint16              slice_idx_empty;
  33027     _field_stage_t      *stage_fc;
  33028     int                 slice_sz;
  33029     int                 tmp_idx1;
  33030     int                 tmp_idx2;
  33031     _field_slice_t      *fs;
  33032     int                 rv;
  33033 
  33034     /* Input parameter check. */
  33035     if ((NULL == target_fs) || (NULL == fg) || (NULL == prev_null_fs))  {
  33036         return (BCM_E_PARAM);
  33037     }
  33038 
  33039     if (target_fs->slice_flags & _BCM_FIELD_SLICE_MULTIMODE_ENTRIES) {
  33040         return _field_multimode_slice_entry_shift_up(unit, fg,
  33041                                 target_fs, target_index,
  33042                                 prev_null_fs, prev_null_index);
  33043     }
  33044 
  33045     BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, target_fs->stage_id,
  33046                                                  &stage_fc));
  33047 
  33048     slice_idx_empty = prev_null_index;
  33049     fs = prev_null_fs;
  33050 
  33051     while ((slice_idx_empty < target_index) || (fs != target_fs)) {
  33052         /* Move the entry at the next index to the prev. empty index. */
  33053         _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs, slice_sz);
  33054         if (slice_idx_empty == (slice_sz - 1)) {
  33055             /* Get lower slice last entry tcam index. */
  33056             rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc,
  33057                                                      fg->instance,
  33058                                                      fs->slice_number,
  33059                                                      slice_sz - 1, &tmp_idx1);
  33060             BCM_IF_ERROR_RETURN(rv);
  33061 
  33062             /* Get upper slice first entry tcam index. */
  33063             rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc,
  33064                                                      fg->instance,
  33065                                                      fs->next->slice_number,
  33066                                                      0, &tmp_idx2);
  33067             BCM_IF_ERROR_RETURN(rv);
  33068 
  33069             /* Perform entry move. */
  33070             rv = _field_entry_move(unit, fs->next->entries[0],
  33071                                    (tmp_idx1 - tmp_idx2));
  33072             BCM_IF_ERROR_RETURN(rv);
  33073 
  33074             fs = fs->next;
  33075             slice_idx_empty = 0;
  33076         } else {
  33077             /* Get lower entry tcam index. */
  33078             rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc,
  33079                                                      fg->instance,
  33080                                                      fs->slice_number,
  33081                                                      slice_idx_empty,
  33082                                                      &tmp_idx1);
  33083             BCM_IF_ERROR_RETURN(rv);
  33084 
  33085             /* Get higher entry tcam index. */
  33086             rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc,
  33087                                                      fg->instance,
  33088                                                      fs->slice_number,
  33089                                                      slice_idx_empty + 1,
  33090                                                      &tmp_idx2);
  33091             BCM_IF_ERROR_RETURN(rv);
  33092 
  33093             /* Perform entry move. */
  33094             rv = _field_entry_move(unit, fs->entries[slice_idx_empty + 1],
  33095                                    (tmp_idx1 - tmp_idx2));
  33096             BCM_IF_ERROR_RETURN(rv);
  33097 
  33098             slice_idx_empty++;
  33099         }
  33100     }
  33101 
  33102     return (BCM_E_NONE);
  33103 }
  33104 
  33105 /*
  33106  * Function:
  33107  *     _field_slice_index_type_get
  33108  * Purpose:
  33109  *     Get Index type at given index in the slice.
  33110  * Parameters:
  33111  *     unit     - (IN) BCM device number
  33112  *     fg       - (IN) Field group control
  33113  *     fs       - (IN) Field slice control.
  33114  *     slice_idx- (IN) Index to verify
  33115  *     slice_idx_type - (OUT) Index type (_BCM_FIELD_SLICE_IDX_TYPE_XXX)
  33116  * Returns:
  33117  *     BCM_E_NONE   - Success
  33118  * Notes:
  33119  *     If slice supports multiple group modes, it is required to verify
  33120  *     if the given index in the slice can be used for comparison or the
  33121  *     movement of entry in given group. This function returns the following
  33122  *     type of index in the given slice:
  33123  *     _BCM_FIELD_SLICE_IDX_TYPE_FREE - Index is free to be used.
  33124  *     _BCM_FIELD_SLICE_IDX_TYPE_DIFF - Entry at given index has different group
  33125  *     flags and should be used.
  33126  *     _BCM_FIELD_SLICE_IDX_TYPE_SAME - Entry at index has same group flags and
  33127  *     can be used for priority comparison.
  33128  */
  33129 STATIC int
  33130 _field_slice_index_type_get(int unit, _field_group_t *fg, _field_slice_t *fs,
  33131                             int slice_idx, int *slice_idx_type)
  33132 {
  33133     int  part = 0;
  33134     int rv = BCM_E_NONE;
  33135     int parts_count = 0;
  33136     uint32 grp_mode_bmp1 = 0;
  33137     uint32 grp_mode_bmp2 = 0;
  33138 
  33139     grp_mode_bmp1 = fg->flags & _FP_GROUP_MODE_MASK;
  33140 
  33141     if (fs->slice_flags & _BCM_FIELD_SLICE_MULTIMODE_ENTRIES) {
  33142         rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
  33143                                             fg->flags, &parts_count);
  33144         BCM_IF_ERROR_RETURN(rv);
  33145 
  33146         /*
  33147          * Parts count is always non-zero, however adding this check
  33148          * to avoid coverity DIVIDE_BY_ZERO error.
  33149          */
  33150         if (parts_count == 0) {
  33151            return BCM_E_INTERNAL;
  33152         }
  33153 
  33154         if ((slice_idx % parts_count) != 0) {
  33155             *slice_idx_type = _BCM_FIELD_SLICE_IDX_TYPE_DIFF;
  33156             return rv;
  33157         }
  33158 
  33159         *slice_idx_type = _BCM_FIELD_SLICE_IDX_TYPE_FREE;
  33160         for (part = 0; part < parts_count; part++) {
  33161             if (fs->entries[slice_idx + part] != NULL) {
  33162                 grp_mode_bmp2 =
  33163                     fs->entries[slice_idx + part]->group->flags &
  33164                     _FP_GROUP_MODE_MASK;
  33165                 if (grp_mode_bmp1 == grp_mode_bmp2) {
  33166                     *slice_idx_type = _BCM_FIELD_SLICE_IDX_TYPE_SAME;
  33167                 } else {
  33168                     *slice_idx_type = _BCM_FIELD_SLICE_IDX_TYPE_DIFF;
  33169                     break;
  33170                 }
  33171             }
  33172         }
  33173     } else if (fs->entries[slice_idx] == NULL) {
  33174         *slice_idx_type = _BCM_FIELD_SLICE_IDX_TYPE_FREE;
  33175     } else {
  33176         *slice_idx_type = _BCM_FIELD_SLICE_IDX_TYPE_SAME;
  33177     }
  33178 
  33179     return rv;
  33180 }
  33181 /*
  33182  * Function:
  33183  *     _field_slice_next_match_index_get
  33184  * Purpose:
  33185  *     Get next valid index for given group flags in slice from given index
  33186  *     in given direction.
  33187  * Parameters:
  33188  *     unit     - (IN) BCM device number
  33189  *     fg       - (IN) Field group control
  33190  *     fs       - (IN) Field slice control.
  33191  *     start_idx- (IN) Start index from where search to start.
  33192  *     end_idx  - (IN) End Index for search.
  33193  *     dir      - (IN) Direction of search (-1 for UP and +1 for Down)
  33194  *     next_idx - (OUT) First compatible index in given direction.
  33195  * Returns:
  33196  *     BCM_E_NONE   - Success
  33197  * Notes:
  33198  *     If slice supports multiple group modes, it is essential to use only
  33199  *     those indices in the slice which has same index type. This function
  33200  *     searches in the given direction for entry which has same index type
  33201  *     as input group in the given slice. In case, no compatible entry is
  33202  *     found in given direction, -1 is returned.
  33203  */
  33204 STATIC int
  33205 _field_slice_next_match_index_get(int unit, _field_group_t *fg,
  33206                                   _field_slice_t *fs, int start_idx,
  33207                                   int end_idx, int dir, int *next_index)
  33208 {
  33209     int rv = BCM_E_NONE;
  33210     int parts_count = 1;
  33211     int index = 0;
  33212     int idx_type;
  33213     int slice_sz = 0;
  33214 
  33215     if ((fg == NULL) || (fs == NULL) || (next_index == NULL)) {
  33216         return BCM_E_PARAM;
  33217     }
  33218 
  33219     _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs, slice_sz);
  33220     if (end_idx == -1) {
  33221         end_idx = (dir == 1) ? (slice_sz - 1) : 0;
  33222     }
  33223 
  33224     if (fs->slice_flags & _BCM_FIELD_SLICE_MULTIMODE_ENTRIES) {
  33225         rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
  33226                                             fg->flags, &parts_count);
  33227         BCM_IF_ERROR_RETURN(rv);
  33228 
  33229         if (dir == -1) { /* Search in UP direction. */
  33230             index = start_idx - parts_count;
  33231             while(index >= end_idx) {
  33232                 _field_slice_index_type_get(unit, fg, fs, index, &idx_type);
  33233                 if (idx_type != _BCM_FIELD_SLICE_IDX_TYPE_DIFF) {
  33234                     break;
  33235                 }
  33236                 index -= parts_count;
  33237             }
  33238         } else { /* Search in DOWN direction. */
  33239             index = start_idx + parts_count;
  33240             while(index <= end_idx) {
  33241                 _field_slice_index_type_get(unit, fg, fs, index, &idx_type);
  33242                 if (idx_type != _BCM_FIELD_SLICE_IDX_TYPE_DIFF) {
  33243                     break;
  33244                 }
  33245                 index += parts_count;
  33246             }
  33247         }
  33248     } else {
  33249         index = start_idx + dir;
  33250     }
  33251 
  33252     if ((index < 0) || (index >= slice_sz)) {
  33253         *next_index = -1;
  33254         return BCM_E_INTERNAL;
  33255     }
  33256 
  33257     *next_index = index;
  33258 
  33259     return BCM_E_NONE;
  33260 }
  33261 
  33262 /*
  33263  * Function:
  33264  *     _field_entry_shift_params_get
  33265  * Purpose:
  33266  *     Calculate paramaters required for shifting entry due to priority change.
  33267  * Parameters:
  33268  *     unit     - (IN) BCM device number
  33269  *     fg       - (IN) Field group control
  33270  *     f_ent    - (IN) Field entry whose priority is changed.
  33271  *     prio     - (IN) New Priority.
  33272  *     shift_params - (OUT) shifting related parameters.
  33273  * Returns:
  33274  *     BCM_E_NONE   - Success
  33275  * Notes:
  33276  *     If slice supports multiple group modes, it is required to find
  33277  *     target/next/prev slice/index which has compatible index type to
  33278  *     be used for comparison or movement of entry. This function performs
  33279  *     first part of entry movement i.e. finding out target/next/prev field
  33280  *     slice for given field group and corresponding indices.
  33281  */
  33282 STATIC int
  33283 _field_entry_shift_params_get(int unit, _field_group_t *fg,
  33284                              _field_entry_t *f_ent, int prio,
  33285                              _bcm_field_entry_shift_params_t *shift_params)
  33286 {
  33287     int rv = BCM_E_NONE;
  33288     _field_slice_t *fs = NULL;
  33289     int slice_sz = 0;
  33290     int slice_idx_target = 0;
  33291     int temp = 0;
  33292     int idx_type;
  33293     _field_slice_t *first_null_fs = NULL;
  33294     _field_slice_t *target_fs = NULL;
  33295     int first_null_index = 0;
  33296     int first_null_flag = 0;
  33297     _field_slice_t *next_null_fs = NULL;
  33298     int next_null_index = 0;
  33299     _field_slice_t *prev_null_fs = NULL;
  33300     int prev_null_index = 0;
  33301     int decr_on_shift_up = TRUE;
  33302     int flag_no_free_entries = 0;
  33303     int only_move = FALSE;
  33304     int last_valid_index = 0;
  33305 
  33306     if ((fg == NULL) || (f_ent == NULL) || (shift_params == NULL)) {
  33307         return BCM_E_INTERNAL;
  33308     }
  33309 
  33310     BCM_IF_ERROR_RETURN(rv);
  33311 
  33312     if (_field_no_free_entries(unit, fg) == TRUE) {
  33313         if (!(f_ent->flags & _FP_ENTRY_INSTALLED)) {
  33314             /*
  33315              * As there are no free entries in any of the slices belonging to
  33316              * this group, and this entry is NOT installed,
  33317              * fake that it does not exist.
  33318              */
  33319             if ((f_ent->fs->slice_flags & _BCM_FIELD_SLICE_MULTIMODE_ENTRIES) &&
  33320                 (fg->flags & _FP_GROUP_DW_DEPTH_EXPANDED)) {
  33321                 f_ent->fs->entries[f_ent->slice_idx] = NULL;
  33322                 f_ent->fs->entries[f_ent->slice_idx + 1] = NULL;
  33323             } else {
  33324                 f_ent->fs->entries[f_ent->slice_idx] = NULL;
  33325             }
  33326             flag_no_free_entries = TRUE;
  33327         } else {
  33328             return BCM_E_CONFIG;
  33329         }
  33330     }
  33331 
  33332     /* Find the target slice index. That is the one with the highest index
  33333      * for this priority class. */
  33334     fs = &fg->slices[0];
  33335     while (fs != NULL) {
  33336         _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs, slice_sz);
  33337         for (slice_idx_target = 0;
  33338              slice_idx_target < slice_sz;
  33339              slice_idx_target++) {
  33340 
  33341             /* Skip the f_ent itself */
  33342             if (f_ent == fs->entries[slice_idx_target]) {
  33343                 continue;
  33344             }
  33345             /* Check if this Index can be used. */
  33346             _field_slice_index_type_get(unit, fg, fs, slice_idx_target, &idx_type);
  33347             if (idx_type == _BCM_FIELD_SLICE_IDX_TYPE_FREE) {
  33348                 prev_null_fs = fs;
  33349                 prev_null_index = slice_idx_target;
  33350                 if (first_null_flag == 0) {
  33351                    first_null_fs = fs;
  33352                    first_null_index = slice_idx_target;
  33353                    first_null_flag = 1;
  33354                 }
  33355                 continue;
  33356             } else if (idx_type == _BCM_FIELD_SLICE_IDX_TYPE_DIFF) {
  33357                 continue;
  33358             } else { /* idx_type == _BCM_FIELD_SLICE_IDX_SAME_TYPE */
  33359                 if (fs->entries[slice_idx_target]->flags &
  33360                     _FP_ENTRY_CREATED_WITHOUT_PRIO) {
  33361                     continue;
  33362                 }
  33363                 first_null_flag = 0;
  33364             }
  33365 
  33366             if (_field_entry_prio_cmp(prio, fs->entries[slice_idx_target]->prio)
  33367                 > 0) {
  33368                 LOG_DEBUG(BSL_LS_BCM_FP,
  33369                           (BSL_META_U(unit,
  33370                                       "FP(unit %d) vverb: Found target slice_idx=%d\n"),
  33371                            unit, slice_idx_target));
  33372                 target_fs = fs;
  33373                 break;
  33374             }
  33375         }
  33376         if (slice_idx_target < slice_sz) {
  33377             break;
  33378         }
  33379         fs = fs->next;
  33380     }
  33381     temp = slice_idx_target;
  33382     while (fs != NULL) {
  33383         _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs, slice_sz);
  33384         for (; temp < slice_sz; temp++) {
  33385             _field_slice_index_type_get(unit, fg, fs, temp, &idx_type);
  33386             if (idx_type == _BCM_FIELD_SLICE_IDX_TYPE_FREE) {
  33387                 next_null_fs = fs;
  33388                 next_null_index = temp;
  33389                 break;
  33390             }
  33391         }
  33392         if (next_null_fs != NULL) {
  33393             break;
  33394         }
  33395         fs = fs->next;
  33396         temp = 0;
  33397     }
  33398 
  33399     /*
  33400      * Put the entry back,
  33401      *     in case there is a context switch, AND
  33402      *     another thread calls entry_create
  33403      */
  33404     if (flag_no_free_entries == TRUE) {
  33405         if ((f_ent->fs->slice_flags & _BCM_FIELD_SLICE_MULTIMODE_ENTRIES) &&
  33406                 (fg->flags & _FP_GROUP_DW_DEPTH_EXPANDED)) {
  33407             f_ent->fs->entries[f_ent->slice_idx] = f_ent;
  33408             f_ent->fs->entries[f_ent->slice_idx + 1] = f_ent + 1;
  33409         } else {
  33410             f_ent->fs->entries[f_ent->slice_idx] = f_ent;
  33411         }
  33412     }
  33413 
  33414     if ((prev_null_fs == NULL) && (next_null_fs == NULL)) {
  33415         return BCM_E_CONFIG; /* No free entries to move */
  33416     }
  33417 
  33418     if (target_fs == NULL) {
  33419         /*
  33420          * target_fs will be NULL when the target location is after
  33421          * the last entry in slice.
  33422          * Now,
  33423          *   1. There may be NULL entries after last entry
  33424          *       Insert entry there
  33425          *   2. The last entry is at last location in (last) slice
  33426          *       Need to do a shift_up to free-up the last location.
  33427          */
  33428 /*
  33429  *  Case 1:
  33430  *  |-------------|
  33431  *  |       6     |
  33432  *  |-------------|
  33433  *  |       5     |
  33434  *  |-------------|
  33435  *  |       4     |<--- change priority to 1
  33436  *  |-------------|
  33437  *  |       3     |
  33438  *  |-------------|
  33439  *  |       2     |
  33440  *  |-------------|
  33441  *  |     .       |
  33442  *  |NULL .entries|
  33443  *  |     .       |
  33444  *  |-------------|
  33445  *
  33446  *  becomes                  |-------------|
  33447  *                           |       6     |
  33448  *                           |-------------|
  33449  *                           |       5     |
  33450  *                           |-------------|
  33451  *                           |    NULL     |
  33452  *                           |-------------|
  33453  *                           |       3     |
  33454  *                           |-------------|
  33455  *                           |       2     |
  33456  *                           |-------------|
  33457  *                           |     .       |
  33458  *                           |NULL .entries|
  33459  *                           |     1       |<--- comes to the end.
  33460  *                           |-------------|
  33461  *
  33462  *  Case 2:
  33463  *  |-------------|
  33464  *  |     .       |
  33465  *  |NULL .entries|
  33466  *  |     .       |
  33467  *  |-------------|
  33468  *  |       6     |
  33469  *  |-------------|
  33470  *  |       5     |
  33471  *  |-------------|
  33472  *  |       4     |<--- change priority to 1
  33473  *  |-------------|
  33474  *  |       3     |
  33475  *  |-------------|
  33476  *  |       2     |
  33477  *  |-------------|
  33478  *
  33479  *  becomes                  |-------------|
  33480  *                           |     .       |
  33481  *                           |NULL .entries|
  33482  *                           |       6     |
  33483  *                           |-------------|
  33484  *                           |       5     |
  33485  *                           |-------------|
  33486  *                           |     NULL    |
  33487  *                           |-------------|
  33488  *                           |       3     |
  33489  *                           |-------------|
  33490  *                           |       2     |
  33491  *                           |-------------|
  33492  *                           |       1     |<--- comes to the end,
  33493  *                           |-------------|           others shift UP
  33494  */
  33495         fs = &fg->slices[0];
  33496         while (fs->next != NULL) {
  33497             fs = fs->next;
  33498         }
  33499         /* Get first Index from bottom dir Up which has same type */
  33500         _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs, slice_sz);
  33501         _field_slice_next_match_index_get(unit, fg,
  33502                                 fs, slice_sz, -1, -1, &last_valid_index);
  33503         if ((fs == prev_null_fs) &&
  33504             (prev_null_index == last_valid_index) &&
  33505             (first_null_flag == 1)) {
  33506             target_fs = first_null_fs;
  33507             slice_idx_target = first_null_index;
  33508             only_move = TRUE;
  33509         } else {
  33510             target_fs = fs;
  33511             slice_idx_target = last_valid_index;
  33512             decr_on_shift_up = FALSE;
  33513         }
  33514     }
  33515 
  33516     shift_params->target_fs = target_fs;
  33517     shift_params->slice_idx_target = slice_idx_target;
  33518     shift_params->next_null_fs = next_null_fs;
  33519     shift_params->next_null_index = next_null_index;
  33520     shift_params->prev_null_fs = prev_null_fs;
  33521     shift_params->prev_null_index = prev_null_index;
  33522     shift_params->decr_on_shift_up = decr_on_shift_up;
  33523     shift_params->flag_no_free_entries = flag_no_free_entries;
  33524     shift_params->only_move = only_move;
  33525 
  33526     shift_params->first_null_fs = first_null_fs;
  33527     shift_params->first_null_index = first_null_index;
  33528     shift_params->first_null_flag = first_null_flag;
  33529 
  33530     return rv;
  33531 }
  33532 
  33533 /*
  33534  * Function: _field_entry_prio_set
  33535  *
  33536  * Purpose:
  33537  *
  33538  * Parameters:
  33539  *     unit - BCM device number
  33540  *     entry - Field entry to operate on
  33541  *
  33542  * Returns:
  33543  *     BCM_E_NONE       Success
  33544  *
  33545  * Notes:
  33546  *     The earlier checks guarantee that there is a free slot somewhere
  33547  *     i.e. in one of the alloted slices for the group.
  33548  */
  33549 int
  33550 _field_entry_prio_set(int unit, bcm_field_entry_t entry, int prio)
  33551 {
  33552     int                 slice_idx_target = 0;
  33553     int                 temp;
  33554     int                 temp1;
  33555     int                 slice_idx_old;
  33556     int                 idx;
  33557     _field_control_t    *fc;
  33558     _field_group_t      *fg;
  33559     _field_slice_t      *fs;
  33560     _field_stage_t      *stage_fc;
  33561     _field_entry_t      *f_ent;
  33562     int parts_count = 0;
  33563     int rv;
  33564     int slice_sz;
  33565     _field_slice_t  *prev_null_fs = NULL;
  33566                         /* The last NULL entry b4 target loc */
  33567     _field_slice_t  *target_fs = NULL;
  33568                         /* The target slice */
  33569     _field_slice_t  *next_null_fs = NULL;
  33570     int prev_null_index = -1;
  33571     int next_null_index = -1;
  33572     int dir = -1; /* Direction of shift: -1 = UP, 1 = DOWN */
  33573     int decr_on_shift_up = TRUE;
  33574     int flag_no_free_entries = FALSE;
  33575     _bcm_field_entry_shift_params_t shift_params;
  33576 
  33577     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  33578 
  33579     rv = _bcm_field_entry_get_by_id(unit, entry, &f_ent);
  33580     if (BCM_FAILURE(rv)) {
  33581         return (rv);
  33582     }
  33583 
  33584     fg = f_ent->group;
  33585     fs = f_ent->fs;
  33586 
  33587     if (fg->stage_id == _BCM_FIELD_STAGE_EXTERNAL) {
  33588         rv = fc->functions.fp_external_entry_prio_set(unit, f_ent, prio);
  33589         return (rv);
  33590     }
  33591 
  33592 #if defined(BCM_TOMAHAWK_SUPPORT)
  33593     /* Priority cannot be set for exact match entries. */
  33594     if (fg->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) {
  33595         rv = BCM_E_UNAVAIL;
  33596         return (rv);
  33597     }
  33598     /* Priority set for class entries. */
  33599     if (fg->stage_id == _BCM_FIELD_STAGE_CLASS) {
  33600         rv = _bcm_field_th_class_entry_prio_set(unit, f_ent, prio);
  33601         return (rv);
  33602     }
  33603 #endif /* BCM_TOMAHAWK_SUPPORT */
  33604 
  33605     prio_set_with_no_free_entries[unit] = FALSE; /* Global variable */
  33606 
  33607     /* Get stage control structure. */
  33608     rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc);
  33609     if (BCM_FAILURE(rv)) {
  33610         return (rv);
  33611     }
  33612 
  33613     /* Get number of entry parts we have to read. */
  33614     rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
  33615                                             fg->flags, &parts_count);
  33616     BCM_IF_ERROR_RETURN(rv);
  33617 
  33618     /*
  33619      * If priority is changing, but still in proper place,
  33620      * just goto end (change the f_ent->prio to prio)
  33621      */
  33622     if (_field_reqd_prio_set_move(unit, f_ent, prio) == FALSE) {
  33623         goto end;
  33624     }
  33625 
  33626     _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs, slice_sz);
  33627 
  33628     slice_idx_old = f_ent->slice_idx;
  33629     if (slice_idx_old >= slice_sz) {
  33630         return (BCM_E_INTERNAL);
  33631     }
  33632 
  33633     sal_memset(&shift_params, 0, sizeof(shift_params));
  33634     rv = _field_entry_shift_params_get(unit, fg, f_ent, prio, &shift_params);
  33635     if (BCM_FAILURE(rv) &&
  33636         (fg->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) &&
  33637          (fs->slice_flags & _BCM_FIELD_SLICE_MULTIMODE_ENTRIES)) {
  33638         rv = _field_multimode_slice_entry_compress(unit, fs);
  33639         BCM_IF_ERROR_RETURN(rv);
  33640 
  33641         rv = _field_entry_shift_params_get(unit, fg, f_ent, prio, &shift_params);
  33642     }
  33643     BCM_IF_ERROR_RETURN(rv);
  33644 
  33645     target_fs       = shift_params.target_fs;
  33646     slice_idx_target= shift_params.slice_idx_target;
  33647     next_null_fs    = shift_params.next_null_fs;
  33648     next_null_index = shift_params.next_null_index;
  33649     prev_null_fs    = shift_params.prev_null_fs;
  33650     prev_null_index = shift_params.prev_null_index;
  33651     flag_no_free_entries = shift_params.flag_no_free_entries;
  33652     decr_on_shift_up = shift_params.decr_on_shift_up;
  33653 
  33654     if (shift_params.only_move == TRUE) {
  33655         goto only_move;
  33656     }
  33657 
  33658     /*
  33659      * Check if the movement is feasible
  33660      * If group spans across slices, need to verify that
  33661      * entries moving across slices do not have shared meters, counters
  33662      * AND that new slice has meter, counter available, if required
  33663      */
  33664     if (_field_validate_prio_set(unit, fg, f_ent,
  33665                                  prev_null_index, prev_null_fs,
  33666                                  slice_idx_target, target_fs,
  33667                                  next_null_index, next_null_fs,
  33668                                  &dir) == FALSE) {
  33669         return (BCM_E_PARAM);
  33670     }
  33671 
  33672     if (dir == 1) {
  33673         /*
  33674          * Move the entry at the target index to target_index+1. This may
  33675          * mean shifting more entries down to make room. In other words,
  33676          * shift the target index and any that follow it down 1 as far as the
  33677          * next empty index.
  33678          */
  33679         if (target_fs->entries[slice_idx_target] != NULL) {
  33680             rv = _field_entry_shift_down(unit, fg,
  33681                                          target_fs, slice_idx_target,
  33682                                          next_null_fs, next_null_index);
  33683             BCM_IF_ERROR_RETURN(rv);
  33684         }
  33685     } else {
  33686         /*
  33687          * Similar thing for Shifting UP
  33688          *     Depends on if this falls into Case-2 in the fig. above.
  33689          */
  33690         if (decr_on_shift_up == TRUE) {
  33691             _field_slice_next_match_index_get(unit, fg,
  33692                     target_fs, slice_idx_target, -1, -1, &slice_idx_target);
  33693             if (slice_idx_target == -1) {
  33694                 target_fs = target_fs->prev;
  33695                 /*
  33696                  * Certain devices have physical slices of different sizes.
  33697                  * So, determine the target index based on the new target slice.
  33698                  */
  33699                 _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, target_fs, slice_sz);
  33700                 slice_idx_target = slice_sz - 1;
  33701             }
  33702         }
  33703         if (target_fs->entries[slice_idx_target] != NULL) {
  33704             rv = _field_entry_shift_up(unit, fg,
  33705                                        target_fs, slice_idx_target,
  33706                                        prev_null_fs, prev_null_index);
  33707             BCM_IF_ERROR_RETURN(rv);
  33708         }
  33709     }
  33710 
  33711     /* Move the entry from its old slice index to the target slice index. */
  33712 only_move:
  33713     rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc,
  33714                                              fg->instance,
  33715                                              target_fs->slice_number,
  33716                                              slice_idx_target, &temp);
  33717     BCM_IF_ERROR_RETURN(rv);
  33718 
  33719     rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc,
  33720                                              fg->instance,
  33721                                              f_ent->fs->slice_number,
  33722                                              f_ent->slice_idx, &temp1);
  33723     BCM_IF_ERROR_RETURN(rv);
  33724 
  33725     if ((temp - temp1) != 0) {
  33726         if (flag_no_free_entries) {
  33727             prio_set_with_no_free_entries[unit] = TRUE;
  33728         }
  33729 
  33730         rv = _field_entry_move(unit, f_ent, (temp - temp1));
  33731         if (BCM_FAILURE(rv)) {
  33732             prio_set_with_no_free_entries[unit] = FALSE;
  33733             return rv;
  33734         }
  33735 
  33736         /* in case _field_entry_move is called from some other function */
  33737         prio_set_with_no_free_entries[unit] = FALSE;
  33738     }
  33739 
  33740 end:
  33741     /* Assign the requested priority to the entry. */
  33742     for (idx = 0; idx < parts_count; idx++) {
  33743         f_ent[idx].prio = prio;
  33744         f_ent[idx].flags &= ~_FP_ENTRY_CREATED_WITHOUT_PRIO;
  33745     }
  33746 
  33747     if (fg->group_status.prio_max < prio) {
  33748         fg->group_status.prio_max = prio;
  33749     }
  33750     if (0 <= prio &&
  33751         (prio < fg->group_status.prio_min || fg->group_status.prio_min < 0)) {
  33752         fg->group_status.prio_min = prio;
  33753     }
  33754 
  33755     return (BCM_E_NONE);
  33756 }
  33757 
  33758 #ifdef BCM_WARM_BOOT_SUPPORT
  33759 int _field_table_read(int unit, soc_mem_t mem, char **buffer_p,
  33760     const char *buffer_name_p)
  33761 {
  33762     int index_min;
  33763     int index_max;
  33764     int rv;
  33765 
  33766     *buffer_p = soc_cm_salloc(unit, SOC_MEM_TABLE_BYTES(unit, mem),
  33767         buffer_name_p);
  33768 
  33769     if (*buffer_p == NULL)
  33770     {
  33771         return BCM_E_MEMORY;
  33772     }
  33773 
  33774     index_min = soc_mem_index_min(unit, mem);
  33775     index_max = soc_mem_index_max(unit, mem);
  33776 
  33777     rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, index_min, index_max,
  33778         *buffer_p);
  33779 
  33780     return rv;
  33781 }
  33782 #endif /* BCM_WARM_BOOT_SUPPORT */
  33783 
  33784 /*
  33785  * Function: _bcm_field_valid_pbmp_get
  33786  *
  33787  * Purpose:
  33788  *     Returns valid PBMP
  33789  *
  33790  * Parameters:
  33791  *     unit - (IN) BCM device number.
  33792  *     pbm  - (OUT) Pbmp structure.
  33793  * Returns:
  33794  *     BCM_E_XXX
  33795  */
  33796 int
  33797 _bcm_field_valid_pbmp_get(int unit, bcm_pbmp_t *pbm)
  33798 {
  33799     bcm_pbmp_t         valid_pbm;    /* Holds valid pbm supported */
  33800 
  33801     /* Retrieve valid ports */
  33802     BCM_PBMP_CLEAR(valid_pbm);
  33803     BCM_PBMP_ASSIGN(valid_pbm, PBMP_ALL(unit));
  33804     BCM_PBMP_REMOVE(valid_pbm, PBMP_LB(unit));
  33805     BCM_PBMP_REMOVE(valid_pbm, PBMP_RDB_ALL(unit));
  33806     BCM_PBMP_REMOVE(valid_pbm, PBMP_MACSEC_ALL(unit));
  33807     BCM_PBMP_REMOVE(valid_pbm, PBMP_FAE_ALL(unit));
  33808 
  33809 #ifdef BCM_KATANA2_SUPPORT
  33810     if (soc_feature(unit, soc_feature_linkphy_coe) ||
  33811         soc_feature(unit, soc_feature_subtag_coe)) {
  33812         _bcm_kt2_subport_pbmp_update(unit, &valid_pbm);
  33813     }
  33814     if (SOC_IS_KATANA2(unit) && soc_feature(unit, soc_feature_flex_port)) {
  33815         BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, &valid_pbm));
  33816     }
  33817 #endif /* BCM_KATANA2_SUPPORT */
  33818 
  33819     BCM_PBMP_ASSIGN(*pbm, valid_pbm);
  33820 
  33821     return BCM_E_NONE;
  33822 }
  33823 
  33824 /*
  33825  * Function: _bcm_field_qualify_InPorts
  33826  *
  33827  * Purpose:
  33828  *     Initialize entry qualifiers for all ports
  33829  *
  33830  * Parameters:
  33831  *     unit -  (IN) BCM device number.
  33832  *     entry - (IN) Field entry structure.
  33833  *     data - (IN) Field pbmp structure.
  33834  *     mask - (IN) Field pbmp structure.
  33835  * Returns:
  33836  *     BCM_E_XXX
  33837  */
  33838 int
  33839 _bcm_field_qualify_InPorts(int unit,
  33840                            bcm_field_entry_t entry,
  33841                            bcm_field_qualify_t qual,
  33842                            bcm_pbmp_t data,
  33843                            bcm_pbmp_t mask)
  33844 {
  33845     int                rv;
  33846     bcm_pbmp_t         temp_pbm;     /* Holds temp pbmp */
  33847     bcm_pbmp_t         valid_pbm;    /* Holds valid pbm supported */
  33848     _field_group_t     *fg;
  33849     _field_entry_t     *f_ent;
  33850 
  33851     rv = _bcm_field_entry_qual_get(unit, entry,
  33852                                    bcmFieldQualifyInPorts, &f_ent);
  33853     BCM_IF_ERROR_RETURN(rv);
  33854 
  33855     /* Confirm that InPorts is in group's Qset. */
  33856     fg = f_ent->group;
  33857     if (!BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInPorts)) {
  33858         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
  33859                   "Error: InPorts part of entry group's[%d] QSET.\n\r"),
  33860                   fg->gid));
  33861         return (BCM_E_PARAM);
  33862     }
  33863 
  33864     /*
  33865      * Validate InPorts data PBMP with group's PBMP.
  33866      * Ports in InPorts pbmp should be part of group's PBMP.
  33867      */
  33868     BCM_PBMP_ASSIGN(temp_pbm, data);
  33869     BCM_PBMP_OR(temp_pbm, fg->pbmp);
  33870     if (BCM_PBMP_NEQ(temp_pbm, fg->pbmp)) {
  33871         return BCM_E_PARAM;
  33872     }
  33873 
  33874     rv = _bcm_field_valid_pbmp_get(unit, &valid_pbm);
  33875     if (BCM_FAILURE(rv)) {
  33876         return (rv);
  33877     }
  33878     /* Check and clear invalid ports in the mask. */
  33879    BCM_PBMP_AND(mask, valid_pbm);
  33880 
  33881 #if defined(BCM_RAPTOR_SUPPORT) || defined (BCM_TRX_SUPPORT)
  33882     if (soc_feature(unit, soc_feature_field_ingress_ipbm)) {
  33883         bcm_pbmp_t          lb_pbm;
  33884 
  33885         /* Add data & mask to entry. */
  33886         BCM_PBMP_ASSIGN(f_ent->pbmp.data, data);
  33887         BCM_PBMP_ASSIGN(f_ent->pbmp.mask, mask);
  33888 
  33889         /* Add loopback port to ipbm mask to avoid false ingress port match */
  33890         BCM_PBMP_ASSIGN(lb_pbm, PBMP_LB(unit));
  33891         if (BCM_PBMP_NOT_NULL(lb_pbm)) {
  33892             BCM_PBMP_OR(f_ent->pbmp.mask, PBMP_LB(unit));
  33893         }
  33894 #if defined(BCM_MONTEREY_SUPPORT) && defined(INCLUDE_XFLOW_MACSEC)
  33895         /* Add MACSEC Port to IPBM mask to avoid match on MACSEC port */
  33896         if (soc_feature(unit, soc_feature_xflow_macsec)) {
  33897             bcm_pbmp_t       macsec_pbm;
  33898             BCM_PBMP_CLEAR(macsec_pbm);
  33899             BCM_PBMP_OR(macsec_pbm, PBMP_MACSEC_ALL(unit));
  33900             if (BCM_PBMP_NOT_NULL(macsec_pbm)) {
  33901                 BCM_PBMP_OR(f_ent->pbmp.mask, PBMP_MACSEC_ALL(unit));
  33902             }
  33903         }
  33904 #endif
  33905         f_ent->flags |= _FP_ENTRY_DIRTY;
  33906         f_ent->flags &= ~(_FP_ENTRY_POLICY_TABLE_ONLY_DIRTY);
  33907 
  33908         return (BCM_E_NONE);
  33909     }
  33910 #endif /* BCM_RAPTOR_SUPPORT || BCM_TRX_SUPPORT */
  33911 
  33912     rv = _field_qualify32(unit, entry, bcmFieldQualifyInPorts,
  33913                           SOC_PBMP_WORD_GET(data, 0),
  33914                           SOC_PBMP_WORD_GET(mask, 0));
  33915     return (rv);
  33916 }
  33917 
  33918 /*
  33919  * Function: _field_entry_qualifiers_init
  33920  *
  33921  * Purpose:
  33922  *     Initialize entry qualifiers based on a group qset.
  33923  *
  33924  * Parameters:
  33925  *     unit -  (IN) BCM device number.
  33926  *     f_ent - (IN/OUT) Field entry structure.
  33927  * Returns:
  33928  *     BCM_E_XXX
  33929  */
  33930 int
  33931 _field_entry_qualifiers_init(int unit, _field_entry_t *f_ent)
  33932 {
  33933     int                 count;        /* Number of ports.             */
  33934     bcm_port_t          port;         /* Port iterator.               */
  33935     _field_group_t      *fg;          /* Field group info.            */
  33936     int                 rv;           /* Operation return status.     */
  33937     _field_control_t    *fc;          /* Field control structure.     */
  33938     _field_stage_t      *stage_fc;    /* Stage field control info.    */
  33939 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  33940     int                 parts_count = 0;  /* Field entry parts count.     */
  33941     int                 idx;          /* Parts iteration index.       */
  33942 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  33943     bcm_pbmp_t all_pbmp;
  33944     bcm_pbmp_t data_pbmp;
  33945     bcm_pbmp_t valid_mask;
  33946 
  33947     fg = f_ent->group;
  33948 
  33949     /* Read device port configuration. */
  33950     BCM_PBMP_CLEAR(all_pbmp);
  33951     rv = _bcm_field_valid_pbmp_get(unit, &all_pbmp);
  33952     BCM_IF_ERROR_RETURN(rv);
  33953 
  33954     /* Get field control structure. */
  33955     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  33956 
  33957     rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc);
  33958     BCM_IF_ERROR_RETURN(rv);
  33959 
  33960     /*
  33961      * If the group has bcmFieldQualifyInPorts in its Qset, qualify the entry
  33962      * on the group's port bitmap.
  33963      */
  33964     if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInPorts)) {
  33965         if (fg->flags & _FP_GROUP_PER_PORT_OR_PBMP) {
  33966             BCM_PBMP_ASSIGN(data_pbmp, fg->pbmp);
  33967             BCM_PBMP_ASSIGN(valid_mask, all_pbmp);
  33968             BCM_PBMP_OR(valid_mask, PBMP_LB(unit));
  33969 
  33970             rv = fc->functions.fp_qualify_inports(unit,
  33971                      f_ent->eid,
  33972                      bcmFieldQualifyInPorts,
  33973                      data_pbmp,
  33974                      valid_mask);
  33975             BCM_IF_ERROR_RETURN(rv);
  33976         }
  33977     }
  33978     /*
  33979      * If the group has bcmFieldQualifyOutPorts in its Qset, qualify the entry
  33980      * on the group's port bitmap.
  33981      */
  33982     if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyOutPorts)) {
  33983         rv = bcm_esw_field_qualify_OutPorts(unit, f_ent->eid, fg->pbmp,
  33984                                             all_pbmp);
  33985         BCM_IF_ERROR_RETURN(rv);
  33986     }
  33987     /*
  33988      * If the group has bcmFieldQualifyInPort in its Qset, and there is only
  33989      * one port in the group's pbmp, then qualify on that port.
  33990      */
  33991     if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInPort)) {
  33992         BCM_PBMP_COUNT(fg->pbmp, count);
  33993         if (count == 1) {
  33994             BCM_PBMP_ITER(fg->pbmp, port) {
  33995                 rv = bcm_esw_field_qualify_InPort(unit, f_ent->eid, port,
  33996                                                   BCM_FIELD_EXACT_MATCH_MASK);
  33997                 BCM_IF_ERROR_RETURN(rv);
  33998             }
  33999         }
  34000     }
  34001 
  34002     /*
  34003      *  If the group has bcmFieldQualifyIp4/6 in Qset add IpType
  34004      * default value to the entry.
  34005      */
  34006     if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyIp4) &&
  34007         (fg->stage_id != _BCM_FIELD_STAGE_EXTERNAL)) {
  34008         rv = bcm_esw_field_qualify_IpType(unit, f_ent->eid, bcmFieldIpTypeIpv4Any);
  34009         BCM_IF_ERROR_RETURN(rv);
  34010     }
  34011 
  34012     if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyIp6) &&
  34013         (fg->stage_id != _BCM_FIELD_STAGE_EXTERNAL)) {
  34014         rv = bcm_esw_field_qualify_IpType(unit, f_ent->eid, bcmFieldIpTypeIpv6);
  34015         BCM_IF_ERROR_RETURN(rv);
  34016     }
  34017 
  34018 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3)
  34019     if (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyDstGport) ||
  34020         BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifySrcGport)) {
  34021         f_ent->dvp_type = f_ent->svp_type = _bcmVpTypeAny;
  34022     }
  34023 #endif
  34024 
  34025     /*
  34026      *  Set key match type for egress FP.
  34027      */
  34028 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  34029     if (_BCM_FIELD_STAGE_EGRESS == fg->stage_id) {
  34030 
  34031         /* Get number of parts in field entry based on group flags. */
  34032         rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
  34033                                                 fg->flags, &parts_count);
  34034         BCM_IF_ERROR_RETURN(rv);
  34035 
  34036         for (idx = 0; idx < parts_count; idx++) {
  34037             rv = fc->functions.fp_egress_key_match_type_set(unit, f_ent + idx);
  34038             BCM_IF_ERROR_RETURN(rv);
  34039         }
  34040     }
  34041 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT  */
  34042 
  34043 #if defined(BCM_FLOWTRACKER_SUPPORT)
  34044     if (fg->stage_id == _BCM_FIELD_STAGE_FLOWTRACKER) {
  34045         /* Get number of parts in field entry based on group flags. */
  34046         rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
  34047                                                 fg->flags, &parts_count);
  34048         BCM_IF_ERROR_RETURN(rv);
  34049 
  34050         for (idx = 0; idx < parts_count; idx++) {
  34051             rv = _bcm_field_hx5_ft_entry_keytype_set(unit, f_ent + idx);
  34052             BCM_IF_ERROR_RETURN(rv);
  34053         }
  34054     }
  34055 #endif
  34056 
  34057     /*
  34058      * If the group supports Preselector, qualify the entry on the
  34059      * Preselector logical table Id.
  34060      */
  34061 #if defined(BCM_TOMAHAWK_SUPPORT)
  34062     if ((fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT) &&
  34063         (fg->stage_id != _BCM_FIELD_STAGE_FLOWTRACKER)) {
  34064        if (BCM_FIELD_QSET_TEST(fg->qset, _bcmFieldQualifyPreLogicalTableId) &&
  34065            (fg->lt_id != -1)) {
  34066            uint32   data, mask;
  34067 
  34068            data = fg->lt_id;
  34069            mask = BCM_FIELD_EXACT_MATCH_MASK;
  34070            /* coverity[address_of : FALSE] */
  34071            /* coverity[callee_ptr_arith : FALSE] */
  34072            rv = _bcm_field_th_qualify_set(unit, f_ent->eid,
  34073                                           _bcmFieldQualifyPreLogicalTableId,
  34074                                           &data, &mask, _FP_QUALIFIER_ADD);
  34075            BCM_IF_ERROR_RETURN(rv);
  34076 
  34077            if (soc_feature(unit, soc_feature_fp_ltid_match_all_parts)) {
  34078               if (BCM_FIELD_QSET_TEST(fg->qset, _bcmFieldQualifyPreLogicalTableId1)) {
  34079                  /* coverity[address_of : FALSE] */
  34080                  /* coverity[callee_ptr_arith : FALSE] */
  34081                  rv = _bcm_field_th_qualify_set(unit, f_ent->eid,
  34082                                              _bcmFieldQualifyPreLogicalTableId1,
  34083                                              &data, &mask, _FP_QUALIFIER_ADD);
  34084                  BCM_IF_ERROR_RETURN(rv);
  34085               }
  34086  
  34087               if (BCM_FIELD_QSET_TEST(fg->qset, _bcmFieldQualifyPreLogicalTableId2)) {
  34088                  /* coverity[address_of : FALSE] */
  34089                  /* coverity[callee_ptr_arith : FALSE] */
  34090                  rv = _bcm_field_th_qualify_set(unit, f_ent->eid,
  34091                                              _bcmFieldQualifyPreLogicalTableId2,
  34092                                              &data, &mask, _FP_QUALIFIER_ADD);
  34093                  BCM_IF_ERROR_RETURN(rv);
  34094               }
  34095            }
  34096        } else {
  34097            return BCM_E_INTERNAL;
  34098        }
  34099     }
  34100 #endif /* BCM_TOMAHAWK_SUPPORT */
  34101 #if defined(BCM_APACHE_SUPPORT)
  34102     f_ent->eth_oam_ctrl_mep_type = 0;
  34103     f_ent->eth_oam_data_mep_type = 0;
  34104     f_ent->mpls_oam_ctrl_mep_type = 0;
  34105     f_ent->mpls_oam_data_mep_type = 0;
  34106 #endif
  34107     return (BCM_E_NONE);
  34108 }
  34109 
  34110 /*
  34111  * Function: _field_entry_create_id
  34112  *
  34113  * Purpose:
  34114  *     Create a blank entry group based on a group;
  34115  *     allows selection of a specific slot in a slice
  34116  *
  34117  * Parameters:
  34118  *     unit -  (IN) BCM device number.
  34119  *     group - (IN) Field group ID.
  34120  *     entry - (IN) Requested entry ID; must be in the range prio_min through
  34121  *             prio_max as returned by bcm_field_group_status_get().
  34122  * Returns:
  34123  *     BCM_E_INIT      - unit not initialized
  34124  *     BCM_E_EXISTS    - Entry ID already in use
  34125  *     BCM_E_NOT_FOUND - Group ID not found in unit
  34126  *     BCM_E_MEMORY    - allocation failure
  34127  *     BCM_E_NONE      - Success
  34128  */
  34129 int
  34130 _field_entry_create_id(int unit, bcm_field_group_t group,
  34131                        bcm_field_entry_t entry)
  34132 {
  34133     _field_stage_t      *stage_fc;    /* Stage field control info.    */
  34134     _field_group_t      *fg;          /* Field group info.            */
  34135     _field_slice_t      *fs_pri = NULL; /* Primary slice pointer.       */
  34136     _field_entry_t      *f_ent;       /* Allocated entry buffer.      */
  34137     int                 rv;           /* Operation return status.     */
  34138 
  34139     LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
  34140               "FP(unit %d) vverb: bcm_esw_field_entry_create_id(group=%d,"
  34141               " entry=%d)\n"), unit, group, entry));
  34142 
  34143     /* Confirm that 'entry' is not already used on unit */
  34144     if (BCM_SUCCESS(_field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent))) {
  34145         LOG_DEBUG(BSL_LS_BCM_FP,
  34146                   (BSL_META_U(unit,
  34147                    "FP(unit %d) Error: entry=(%d) already exists.\n"),
  34148                    unit, entry));
  34149         return (BCM_E_EXISTS);
  34150     }
  34151 
  34152     /* Get group control structure. */
  34153     rv = _field_group_get(unit, group, &fg);
  34154     if (BCM_FAILURE(rv)) {
  34155         LOG_DEBUG(BSL_LS_BCM_FP,
  34156                   (BSL_META_U(unit,
  34157                    "FP(unit %d) Error: group=(%d) group get failure.\n"),
  34158                    unit, group));
  34159         return (rv);
  34160     }
  34161 
  34162 #if defined(BCM_TOMAHAWK_SUPPORT)
  34163     if((soc_property_get(unit, spn_FLOWTRACKER_ENABLE, 0) == 1) &&
  34164             (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id)) {
  34165         LOG_DEBUG(BSL_LS_BCM_FP,
  34166                   (BSL_META_U(unit,
  34167                    "Error: ExactMatch group:%d is dedicated to Flowtracker app"
  34168                    " Field entries can't be created in flow tracker groups\n"),
  34169                    group));
  34170         return BCM_E_UNAVAIL;
  34171     }
  34172 #endif /* BCM_TOMAHAWK_SUPPORT */
  34173 
  34174     /* Get group stage control structure. */
  34175     rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc);
  34176     if (BCM_FAILURE(rv)) {
  34177         LOG_DEBUG(BSL_LS_BCM_FP,
  34178                   (BSL_META_U(unit,
  34179                    "FP(unit %d) Error: Stage (%d) control get failure.\n"),
  34180                    unit, fg->stage_id));
  34181         return (rv);
  34182     }
  34183 
  34184     /* Reserve a slice with room for new entry. */
  34185     rv = _field_group_slice_entry_reserve(unit, fg, &fs_pri);
  34186     if (BCM_FAILURE(rv)) {
  34187         if(entry != _FP_INTERNAL_RESERVED_ID) {
  34188            LOG_DEBUG(BSL_LS_BCM_FP,
  34189                      (BSL_META_U(unit,
  34190                                  "FP(unit %d) Error: Group (%d) no room.\n"),
  34191                       unit, group));
  34192         } else {
  34193            LOG_DEBUG(BSL_LS_BCM_FP,
  34194                      (BSL_META_U(unit,
  34195                                  "FP(unit %d) Warning: Group (%d) no room."
  34196                                  " Hitless update cannot be done due to "
  34197                                  "resource constraints\n"),
  34198                       unit, group));
  34199         }
  34200         return (rv);
  34201     }
  34202 
  34203     /* Create entry in primary slice. */
  34204     rv = _field_entry_phys_create(unit, stage_fc, entry,
  34205                                   BCM_FIELD_ENTRY_PRIO_LOWEST,
  34206                                   fs_pri, fg, &f_ent);
  34207     if (BCM_FAILURE(rv)) {
  34208         return (rv);
  34209     }
  34210 
  34211     /* Initialize entry qualifiers based on group qset. */
  34212     rv = _field_entry_qualifiers_init(unit, f_ent);
  34213     if (BCM_FAILURE(rv)) {
  34214         _field_entry_phys_destroy(unit, f_ent);
  34215         return (rv);
  34216     }
  34217     return (BCM_E_NONE);
  34218 }
  34219 
  34220 /* Function    : _field_tpid_hw_decode
  34221  * Description : Encode tpid value to hw specific value.
  34222  * Parameters  : (IN) unit   BCM driver unit
  34223  *               (IN) hw_code HW code.
  34224  *               (OUT) tpid  decoded TPID
  34225  * Returns     : BCM_E_XXX
  34226  */
  34227 int
  34228 _field_tpid_hw_decode(int unit, uint32 hw_code, uint16 *tpid)
  34229 {
  34230     switch (hw_code) {
  34231       case 0x0:
  34232           *tpid = 0x8100;
  34233           break;
  34234       case 0x1:
  34235           *tpid = 0x9100;
  34236           break;
  34237       case 0x2:
  34238           *tpid = 0x88a8;
  34239           break;
  34240       default:
  34241           return (BCM_E_UNAVAIL);
  34242     }
  34243     return (BCM_E_NONE);
  34244 }
  34245 
  34246 /* Function    : _bcm_field_tpid_hw_encode
  34247  * Description : Encode tpid value to hw specific value.
  34248  * Parameters  : (IN) unit   BCM driver unit
  34249  *               (IN) tpid   TPID to encode
  34250  *               (OUT) hw_code HW code.
  34251  * Returns     : BCM_E_XXX
  34252  */
  34253 int
  34254 _bcm_field_tpid_hw_encode(int unit, uint16 tpid, uint32 *hw_code)
  34255 {
  34256     switch (tpid) {
  34257       case 0x8100:
  34258           *hw_code = 0x00;
  34259           break;
  34260       case 0x9100:
  34261           *hw_code = 0x01;
  34262           break;
  34263       case 0x88a8:
  34264           *hw_code = 0x02;
  34265           break;
  34266       default:
  34267           *hw_code = 0x03;
  34268     }
  34269     return (BCM_E_NONE);
  34270 }
  34271 
  34272 /*
  34273  * Function:
  34274  *     _field_action_alloc
  34275  * Purpose:
  34276  *     Allocate and initialize an action structure.
  34277  * Parameters:
  34278  *     unit     - BCM device number.
  34279  *     action   - Action to perform (bcmFieldActionXXX)
  34280  *     param0   - Action parameter (use 0 if not required)
  34281  *     param1   - Action parameter (use 0 if not required)
  34282  *     param2   - Action parameter (use 0 if not required)
  34283  *     param3   - Action parameter (use 0 if not required)
  34284  *     param4   - Action parameter (use 0 if not required)
  34285  *     param5   - Action parameter (use 0 if not required)
  34286  *     fa (OUT) - pointer to field action structure
  34287  * Returns:
  34288  *     BCM_E_MEMORY - allocation failure
  34289  *     BCM_E_NONE   - Success
  34290  */
  34291 int
  34292 _field_action_alloc(int unit, bcm_field_action_t action,
  34293                     uint32 param0, uint32 param1,
  34294                     uint32 param2, uint32 param3,
  34295                     uint32 param4, uint32 param5,
  34296                     _field_action_t **fa)
  34297 {
  34298     *fa = sal_alloc(sizeof (_field_action_t), "field_action");
  34299     if (*fa == NULL) {
  34300         LOG_ERROR(BSL_LS_BCM_FP,
  34301                   (BSL_META_U(unit,
  34302                               "FP(unit %d) Error: allocation failure for field_action\n"),
  34303                    unit));
  34304         return (BCM_E_MEMORY);
  34305     }
  34306     sal_memset(*fa, 0, sizeof (_field_action_t));
  34307 
  34308     (*fa)->action = action;
  34309     (*fa)->param[0] = param0;
  34310     (*fa)->param[1] = param1;
  34311     (*fa)->param[2] = param2;
  34312     (*fa)->param[3] = param3;
  34313     (*fa)->param[4] = param4;
  34314     (*fa)->param[5] = param5;
  34315     (*fa)->hw_index = _FP_INVALID_INDEX;
  34316     (*fa)->old_index = _FP_INVALID_INDEX;
  34317     /* mark new action as not yet installed */
  34318     (*fa)->flags |= (_FP_ACTION_VALID | _FP_ACTION_DIRTY);
  34319     (*fa)->egress_pbmp = NULL;
  34320     (*fa)->elephant_pkts_only = 0;
  34321 
  34322     return (BCM_E_NONE);
  34323 }
  34324 
  34325 /*
  34326  * Function: _field_action_add
  34327  *
  34328  * Purpose:
  34329  *     Add action performed when entry rule is matched for a packet
  34330  *
  34331  * Parameters:
  34332  *     unit  - (IN) BCM device number.
  34333  *     fc    - (IN) Field control structure.
  34334  *     f_ent - (IN) Field entry id.
  34335  *     fa    - (IN) Field action structure.
  34336  * Returns:
  34337  *     BCM_E_XXX
  34338  */
  34339 int
  34340 _field_action_add(int unit, _field_control_t *fc,
  34341                   bcm_field_entry_t entry, _field_action_t *fa)
  34342 {
  34343     _field_entry_t   *f_ent;            /* Field entry structure.       */
  34344     _field_action_t  *fa_iter;          /* Field entry actions iterator.*/
  34345     int               rv;               /* Operation return status.     */
  34346 #if defined(BCM_TRIDENT_SUPPORT)
  34347     uint8                  idx;             /* entry pard Id  */
  34348     bcm_field_action_t     action, action1;          /* Action type    */
  34349     uint32                 entry_flags = 0; /* Entry flags    */
  34350 #endif
  34351 #if defined (BCM_TRIUMPH3_SUPPORT)
  34352     uint32 bitIndex;
  34353 #endif
  34354 
  34355 #if defined(BCM_TOMAHAWK_SUPPORT)
  34356     int supported = 0;                  /* Action Supported flag.     */
  34357     int action_size = 0;                /* Action Size.               */
  34358 #endif /* BCM_TOMAHAWK_SUPPORT */
  34359 
  34360 #if defined(BCM_TOMAHAWK_SUPPORT)
  34361     if (soc_feature(unit, soc_feature_field_preselector_support) &&
  34362         (_BCM_FIELD_IS_PRESEL_ENTRY(entry) == TRUE)) {
  34363         return _bcm_field_presel_action_add(unit, fc, entry, fa);
  34364     }
  34365 #endif /* BCM_TOMAHAWK_SUPPORT */
  34366 
  34367     /* Get field entry structure pointer. */
  34368     rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent);
  34369     BCM_IF_ERROR_RETURN(rv);
  34370 
  34371 #if defined(BCM_TOMAHAWK_SUPPORT)
  34372     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  34373         (f_ent->group->stage_id == _BCM_FIELD_STAGE_CLASS)) {
  34374         return (BCM_E_UNAVAIL);
  34375     }
  34376 #endif /* BCM_TOMAHAWK_SUPPORT */
  34377 
  34378     /* Confirm that action is in aset. */
  34379     /* coverity[ptr_arith] */
  34380     if (SHR_BITGET(f_ent->group->aset.w, fa->action) == 0) {
  34381         if(f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) {
  34382             if (f_ent->flags & _FP_ENTRY_EXACT_MATCH_GROUP_DEFAULT) {
  34383 #if defined(BCM_TOMAHAWK_SUPPORT)
  34384                 BCM_IF_ERROR_RETURN(
  34385                         _bcm_field_th_action_support_check(unit, f_ent,
  34386                                                 fa->action, &supported));
  34387                 if (!supported) {
  34388 #ifdef BROADCOM_DEBUG
  34389                     LOG_ERROR(BSL_LS_BCM_FP,
  34390                        (BSL_META_U(unit,
  34391                         "FP(unit %d) Error: action=%s not supported\n"),
  34392                          unit,_field_action_name(fa->action)));
  34393 #endif
  34394                     return (BCM_E_UNAVAIL);
  34395                 }
  34396 #endif /* BCM_TOMAHAWK_SUPPORT */
  34397             } else {
  34398 #ifdef BROADCOM_DEBUG
  34399                 LOG_ERROR(BSL_LS_BCM_FP,
  34400                          (BSL_META_U(unit,
  34401                          "FP(unit %d) Error: action=%s not supported\n"),
  34402                          unit,_field_action_name(fa->action)));
  34403 #endif
  34404                     return (BCM_E_UNAVAIL);
  34405             }
  34406         } else {
  34407 #ifdef BROADCOM_DEBUG
  34408             LOG_ERROR(BSL_LS_BCM_FP,
  34409                     (BSL_META_U(unit,
  34410                      "FP(unit %d) Error: action=%s not supported\n"),
  34411                      unit,_field_action_name(fa->action)));
  34412 #endif
  34413             return (BCM_E_UNAVAIL);
  34414         }
  34415     }
  34416 
  34417 #if defined BCM_TRIDENT2_SUPPORT || defined BCM_TOMAHAWK_SUPPORT
  34418     /* Check if actions conflict with Statistics action */
  34419     BCM_IF_ERROR_RETURN (_bcm_field_action_stat_conflict_check(unit, f_ent, fa));
  34420 #endif
  34421 
  34422     /* Oam Actions conflict with Nat actions */
  34423     if (soc_feature(unit, soc_feature_fp_based_oam)) {
  34424         if ((fa->action == bcmFieldActionNatEgressOverride)
  34425                 || (fa->action == bcmFieldActionNat)
  34426                 || (fa->action == bcmFieldActionNatCancel)) {
  34427             if (f_ent->flags & _FP_ENTRY_OAM_STAT_VALID) {
  34428 #ifdef BROADCOM_DEBUG
  34429                 LOG_ERROR(BSL_LS_BCM_FP,
  34430                         (BSL_META_U(unit,
  34431                                     "FP(unit %d) Error: action=%s conflicts with"
  34432                                     " oam stat action in entry=%d\n"), unit,
  34433                          _field_action_name(fa->action), entry ));
  34434 #endif
  34435                 return BCM_E_CONFIG;
  34436             }
  34437         }
  34438     }
  34439 
  34440     /* Check for existing actions that conflict with the new action. */
  34441     fa_iter = f_ent->actions;
  34442     while (fa_iter != NULL) {
  34443         if (0 == (fa_iter->flags & _FP_ACTION_VALID)) {
  34444             fa_iter = fa_iter->next;
  34445             continue;
  34446         }
  34447         rv = fc->functions.fp_action_conflict_check(unit,
  34448                                                     f_ent,
  34449                                                     fa_iter->action,
  34450                                                     fa->action);
  34451         if (BCM_FAILURE(rv)) {
  34452 #ifdef BROADCOM_DEBUG
  34453             LOG_ERROR(BSL_LS_BCM_FP,
  34454                       (BSL_META_U(unit,
  34455                                   "FP(unit %d) Error: action=%s conflicts with  "
  34456                                   "existing action in entry=%d\n"), unit,
  34457                        _field_action_name(fa->action), entry ));
  34458 #endif
  34459             return (rv);
  34460         }
  34461         fa_iter = fa_iter->next;
  34462     }
  34463 #if defined (BCM_TRIUMPH3_SUPPORT)
  34464     if(SOC_IS_TRIUMPH3(unit)) {
  34465         if(fa->action ==  bcmFieldActionReplaceSrcMac ||
  34466            fa->action == bcmFieldActionReplaceDstMac ||
  34467            fa->action == bcmFieldActionReplaceInnerVlan ||
  34468            fa->action == bcmFieldActionReplaceOuterVlan ||
  34469            fa->action == bcmFieldActionReplaceInnerVlanPriority  ||
  34470            fa->action == bcmFieldActionReplaceOuterVlanPriority)  {
  34471             fa_iter = f_ent->actions;
  34472             fa->hw_index = -1;
  34473             while (fa_iter != NULL) {
  34474                 if(fa_iter->action ==  bcmFieldActionReplaceSrcMac ||
  34475                         fa_iter->action == bcmFieldActionReplaceDstMac ||
  34476                         fa_iter->action == bcmFieldActionReplaceInnerVlan ||
  34477                         fa_iter->action == bcmFieldActionReplaceOuterVlan ||
  34478                         fa_iter->action == bcmFieldActionReplaceInnerVlanPriority  ||
  34479                         fa_iter->action == bcmFieldActionReplaceOuterVlanPriority) {
  34480                     fa->hw_index = fa_iter->hw_index;
  34481                     break;
  34482                 }
  34483                 fa_iter = fa_iter->next;
  34484             }
  34485 
  34486             if(fa->hw_index < 0) {
  34487                 bitIndex = 0;
  34488                 for (bitIndex=0; bitIndex < fc->_fp_egr_ifp_mod_fields_size;bitIndex++) {
  34489                     if(SHR_BITGET(fc->field_action_l2mod_index_bmp.w,bitIndex) == 0) {
  34490                         break;
  34491                     }
  34492                 }
  34493                 SHR_BITSET(fc->field_action_l2mod_index_bmp.w,bitIndex);
  34494                 fa->hw_index = bitIndex;
  34495             }
  34496         }
  34497     }
  34498 #endif
  34499 
  34500 #if defined(BCM_TRIDENT_SUPPORT)
  34501     if (SOC_IS_TD_TT(unit) &&
  34502         !soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  34503         if ((f_ent->group->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) ||
  34504             (f_ent->group->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) ||
  34505             (f_ent->group->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) {
  34506             if (f_ent->group->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
  34507                 entry_flags = (_FP_ENTRY_PRIMARY | _FP_ENTRY_SECOND_HALF);
  34508             } else {
  34509                 entry_flags = _FP_ENTRY_SECONDARY;
  34510             }
  34511             rv = _bcm_field_entry_flags_to_tcam_part(unit, entry_flags,
  34512                                                      f_ent->group,
  34513                                                      &idx);
  34514             BCM_IF_ERROR_RETURN(rv);
  34515             fa_iter = f_ent[idx].actions;
  34516             while (fa_iter != NULL) {
  34517                 if (0 == (fa_iter->flags & _FP_ACTION_VALID)) {
  34518                     fa_iter = fa_iter->next;
  34519                     continue;
  34520                 }
  34521                 rv = fc->functions.fp_action_conflict_check(unit,
  34522                                                             f_ent,
  34523                                                             fa_iter->action,
  34524                                                             fa->action);
  34525                 if (BCM_FAILURE(rv)) {
  34526 #ifdef BROADCOM_DEBUG
  34527                     LOG_ERROR(BSL_LS_BCM_FP,
  34528                               (BSL_META_U(unit,
  34529                                           "FP(unit %d) Error: action=%s conflicts with  "
  34530                                           "existing action in entry=%d\n"), unit,
  34531                                _field_action_name(fa->action), entry ));
  34532 #endif
  34533                     return (rv);
  34534                 }
  34535                 fa_iter = fa_iter->next;
  34536             }
  34537         }
  34538     }
  34539 #endif
  34540     /* Check action parameters. */
  34541     rv = fc->functions.fp_action_params_check(unit, f_ent, fa);
  34542     if (BCM_FAILURE(rv)) {
  34543 #ifdef BROADCOM_DEBUG
  34544         LOG_ERROR(BSL_LS_BCM_FP,
  34545                   (BSL_META_U(unit,
  34546                               "FP(unit %d) Error: action=%s parameters check failed (%d)\n"),
  34547                    unit, _field_action_name(fa->action), rv));
  34548 #endif
  34549         return (rv);
  34550     }
  34551 
  34552     /* Check dependency(s) of action */
  34553     if (fc->functions.fp_action_depends_check) {
  34554         rv = (*fc->functions.fp_action_depends_check)(unit, f_ent, fa);
  34555         if (BCM_FAILURE(rv)) {
  34556 #ifdef BROADCOM_DEBUG
  34557             LOG_ERROR(BSL_LS_BCM_FP,
  34558                       (BSL_META_U(unit,
  34559                                   "FP(unit %d) Error: action=%s dependency check failed (%d)\n"),
  34560                        unit, _field_action_name(fa->action), rv));
  34561 #endif
  34562             return (rv);
  34563         }
  34564     }
  34565 
  34566 
  34567 #if defined(BCM_TOMAHAWK_SUPPORT)
  34568     if (f_ent->flags & _FP_ENTRY_EXACT_MATCH_GROUP_DEFAULT) {
  34569         rv = _field_th_em_entry_action_size_get(unit, f_ent,
  34570                                                 &action_size, NULL);
  34571         if (BCM_FAILURE(rv)) {
  34572             return (rv);
  34573         }
  34574 
  34575         if (action_size > EM_DEFAULT_POLICY_ACTION_DATA_SIZE) {
  34576             return (BCM_E_RESOURCE);
  34577         }
  34578     }
  34579 #endif /* BCM_TOMAHAWK_SUPPORT */
  34580 
  34581     if (fa->action == bcmFieldActionColorIndependent) {
  34582         if (fa->param[0])  {
  34583             f_ent->flags |= _FP_ENTRY_COLOR_INDEPENDENT;
  34584         } else {
  34585             f_ent->flags &= ~_FP_ENTRY_COLOR_INDEPENDENT;
  34586         }
  34587         if (0 == (f_ent->flags & _FP_ENTRY_DIRTY)) {
  34588             f_ent->flags |= _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY;
  34589         }
  34590         f_ent->flags  |= _FP_ENTRY_DIRTY;
  34591 
  34592         if (NULL != (fa->egress_pbmp)) {
  34593             sal_free(fa->egress_pbmp);
  34594         }
  34595         sal_free(fa);
  34596         return (BCM_E_NONE);
  34597     }
  34598 
  34599 #if defined(BCM_TRIDENT_SUPPORT)
  34600     if (SOC_IS_TD_TT(unit) &&
  34601 	!soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  34602         if ((f_ent->group->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) ||
  34603             (f_ent->group->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) ||
  34604             (f_ent->group->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) {
  34605             switch(fa->action) {
  34606                 case bcmFieldActionCosQCpuNew:
  34607                     action = bcmFieldActionServicePoolIdNew;
  34608                     action1 = bcmFieldActionServicePoolIdPrecedenceNew;
  34609                     break;
  34610                 case bcmFieldActionServicePoolIdNew:
  34611                 case bcmFieldActionServicePoolIdPrecedenceNew:
  34612                     action = bcmFieldActionCosQCpuNew;
  34613                     action1 = -1;
  34614                     break;
  34615                 default:
  34616                     action = bcmFieldActionCount;
  34617                     break;
  34618             }
  34619             if (action != bcmFieldActionCount) {
  34620                 for (fa_iter = f_ent->actions;
  34621                      fa_iter != NULL;
  34622                      fa_iter = fa_iter->next) {
  34623                     if (((fa_iter->action == action) ||
  34624                          (fa_iter->action == action1)) &&
  34625                         (fa_iter->flags & _FP_ACTION_VALID)) {
  34626                         rv = _bcm_field_entry_flags_to_tcam_part(
  34627                                                             unit,
  34628                                                             entry_flags,
  34629                                                             f_ent->group,
  34630                                                             &idx);
  34631                         BCM_IF_ERROR_RETURN(rv);
  34632                         fa->next = f_ent[idx].actions;
  34633                         f_ent[idx].actions  = fa;
  34634                         if (0 == (f_ent[idx].flags & _FP_ENTRY_DIRTY)) {
  34635                             f_ent[idx].flags |= _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY;
  34636                         }
  34637                         f_ent[idx].flags    |= _FP_ENTRY_DIRTY;
  34638                         return (BCM_E_NONE);
  34639                     }
  34640                 }
  34641             }
  34642         }
  34643     }
  34644 #endif
  34645 
  34646 #if defined BCM_TRIDENT2_SUPPORT
  34647     BCM_IF_ERROR_RETURN(_bcm_field_action_stat_flag_update(unit, f_ent, fa, TRUE));
  34648 #endif
  34649 
  34650     /* Oam Actions conflict with Nat actions */
  34651     if (soc_feature(unit, soc_feature_fp_based_oam)) {
  34652         if ((fa->action == bcmFieldActionNatEgressOverride)
  34653                 || (fa->action == bcmFieldActionNat)
  34654                 || (fa->action == bcmFieldActionNatCancel)) {
  34655             f_ent->flags |= _FP_ENTRY_OAM_STAT_NOT_ALLOWED;
  34656         }
  34657     }
  34658 
  34659     /* Add action to front of entry's linked-list. */
  34660     fa->next = f_ent->actions;
  34661     f_ent->actions  = fa;
  34662     /*
  34663      * Do not set action only dirty flag if qualifier parameter has
  34664      * been modified for this entry.
  34665      */
  34666     if (0 == (f_ent->flags & _FP_ENTRY_DIRTY)) {
  34667         f_ent->flags |= _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY;
  34668     }
  34669     f_ent->flags    |= _FP_ENTRY_DIRTY;
  34670 
  34671     return (BCM_E_NONE);
  34672 }
  34673 
  34674 /*
  34675  * Function: _bcm_field_action_ports_add
  34676  *
  34677  * Purpose:
  34678  *     Add action performed when entry rule is matched for a packet
  34679  *
  34680  * Parameters:
  34681  *     unit - BCM device number
  34682  *     entry - entry ID
  34683  *     action - Action to perform (bcmFieldActionXXX)
  34684  *     param0 - Action parameter (use 0 if not required)
  34685  *     param1 - Action parameter (use 0 if not required)
  34686  *     param2 - Action parameter (use 0 if not required)
  34687  *     param3 - Action parameter (use 0 if not required)
  34688  *     param4   - Action parameter (use 0 if not required)
  34689  *     param5   - Action parameter (use 0 if not required)
  34690  *
  34691  * Returns:
  34692  *     BCM_E_XXX
  34693  */
  34694 int
  34695 _bcm_field_action_ports_add(int unit,
  34696                          bcm_field_entry_t entry,
  34697                          bcm_field_action_t action,
  34698                          uint32 param0, uint32 param1,
  34699                          uint32 param2, uint32 param3,
  34700                          uint32 param4, uint32 param5)
  34701 {
  34702     _field_control_t    *fc;           /* Field control structure. */
  34703     _field_action_t     *fa = NULL;    /* Field action descriptor. */
  34704     int                 rv;            /* Operation return status. */
  34705 
  34706 #ifdef BROADCOM_DEBUG
  34707     LOG_DEBUG(BSL_LS_BCM_FP,
  34708               (BSL_META_U(unit,
  34709                           "FP(unit %d) vverb: bcm_field_action_add(entry=%d, action=%s, "
  34710                           "p0=%d, p1=%d, p2=%d, p3=%d, p4=%d, p5=%d)\n"), unit, entry,
  34711                _field_action_name(action),
  34712                param0, param1, param2, param3, param4, param5));
  34713 #endif
  34714 
  34715 
  34716     FP_LOCK(unit);
  34717     rv = _field_control_get(unit, &fc);
  34718     if (BCM_FAILURE(rv)) {
  34719         FP_UNLOCK(unit);
  34720         return rv;
  34721     }
  34722 
  34723     /*
  34724      * Allocate the action  descriptor.
  34725      */
  34726     rv = _field_action_alloc(unit, action,
  34727              param0, param1, param2, param3, param4, param5, &fa);
  34728     if (BCM_FAILURE(rv)) {
  34729         LOG_ERROR(BSL_LS_BCM_FP,
  34730                   (BSL_META_U(unit,
  34731                               "FP(unit %d) Error: failure in _field_action_alloc()\n"),
  34732                    unit));
  34733         FP_UNLOCK(unit);
  34734         return rv;
  34735     }
  34736 
  34737     /*
  34738      * Add action to entry actions list.
  34739      */
  34740     rv = _field_action_add(unit, fc, entry, fa);
  34741     FP_UNLOCK(unit);
  34742     if (BCM_FAILURE(rv)) {
  34743         sal_free(fa);
  34744         return rv;
  34745     }
  34746     return (BCM_E_NONE);
  34747 }
  34748 
  34749 /*
  34750  * Function: _bcm_field_action_ports_get
  34751  *
  34752  * Purpose:
  34753  *     Get parameters associated with an entry action
  34754  *
  34755  * Parameters:
  34756  *     unit - BCM device number
  34757  *     entry - Entry ID
  34758  *     action - Action to perform (bcmFieldActionXXX)
  34759  *     param0 - (OUT) Action parameter
  34760  *     param1 - (OUT) Action parameter
  34761  *     param2 - (OUT) Action parameter
  34762  *     param3 - (OUT) Action parameter
  34763  *     param4 - (OUT) Action parameter
  34764  *     param5 - (OUT) Action parameter
  34765  **
  34766  * Returns:
  34767  *     BCM_E_INIT      - BCM Unit not initialized
  34768  *     BCM_E_NOT_FOUND - Entry ID not found
  34769  *     BCM_E_NOT_FOUND - No matching Action for entry
  34770  *     BCM_E_PARAM     - paramX is NULL
  34771  *     BCM_E_NONE      - Success
  34772  */
  34773 
  34774 int
  34775 _bcm_field_action_ports_get(int unit,
  34776                          bcm_field_entry_t entry,
  34777                          bcm_field_action_t action,
  34778                          uint32 *param0, uint32 *param1,
  34779                          uint32 *param2, uint32 *param3,
  34780                          uint32 *param4, uint32 *param5)
  34781 {
  34782     _field_entry_t      *f_ent;
  34783     _field_action_t     *fa;
  34784     int                 rv;
  34785 
  34786     /* Input parameters check. */
  34787     if ((NULL == param0) || (NULL == param1) ||
  34788         (NULL == param2) || (NULL == param3) ||
  34789         (NULL == param4) || (NULL == param5)) {
  34790             return (BCM_E_PARAM);
  34791     }
  34792 
  34793     /* Lock the module. */
  34794 
  34795     FP_LOCK(unit);
  34796 
  34797     rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent);
  34798     if (BCM_FAILURE(rv)) {
  34799         FP_UNLOCK(unit);
  34800         return (rv);
  34801     }
  34802 
  34803     /* Find matching action in the entry */
  34804     for (fa = f_ent->actions; fa != NULL; fa = fa->next) {
  34805         if (fa->action == action) {
  34806             break;
  34807         }
  34808     }
  34809 
  34810     if (fa == NULL) {
  34811         FP_UNLOCK(unit);
  34812         LOG_VERBOSE(BSL_LS_BCM_FP,
  34813                     (BSL_META_U(unit,
  34814                                 "FP(unit %d) Error: action not in entry=%d\n"),
  34815                      unit, entry));
  34816         return (BCM_E_NOT_FOUND);
  34817     }
  34818 
  34819     *param0 = fa->param[0];
  34820     *param1 = fa->param[1];
  34821     *param2 = fa->param[2];
  34822     *param3 = fa->param[3];
  34823     *param4 = fa->param[4];
  34824     *param5 = fa->param[5];
  34825 
  34826     /* Unlock the module. */
  34827     FP_UNLOCK(unit);
  34828 
  34829     return (rv);
  34830 }
  34831 
  34832 /*
  34833  * Function:
  34834  *     _bcm_field_slice_offset_to_tcam_idx
  34835  *
  34836  * Purpose:
  34837  *     Given stage and tcam_index,
  34838  *     calculate slice and entry offset in the
  34839  *
  34840  * Parameters:
  34841  *     unit      - (IN) BCM device number.
  34842  *     stage_fc  - (IN) Pointer to field entry structure.
  34843  *     instance  - (IN) Instance of the pipe, the slice belongs to.
  34844  *     slice     - (IN) Entry slice number.
  34845  *     slice_idx - (IN) Entry offset in the slice.
  34846  *     tcam_idx  - (OUT) Entry tcam index.
  34847  * Returns:
  34848  *     BCM_E_XXX
  34849  */
  34850 int
  34851 _bcm_field_slice_offset_to_tcam_idx(int unit, _field_stage_t *stage_fc,
  34852                                     int instance, int slice, int slice_idx,
  34853                                     int *tcam_idx)
  34854 {
  34855     _field_slice_t  *fs;          /* Field slice number. */
  34856 
  34857     /* Input parameters check. */
  34858     if ((NULL == stage_fc) || (NULL == tcam_idx))  {
  34859         return (BCM_E_PARAM);
  34860     }
  34861 
  34862 #if defined(BCM_TOMAHAWK_SUPPORT)
  34863     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  34864         ((_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) ||
  34865         (_BCM_FIELD_STAGE_FLOWTRACKER == stage_fc->stage_id))) {
  34866        return _bcm_field_th_slice_offset_to_tcam_idx(unit, stage_fc, instance,
  34867                                                   slice, slice_idx, tcam_idx);
  34868     }
  34869 #endif /* BCM_TOMAHAWK_SUPPORT */
  34870 
  34871     /* Given stage flags slice number and slice index, calculate tcam index. */
  34872     fs = stage_fc->slices[instance] + slice;
  34873 
  34874     if ((stage_fc->flags & _FP_STAGE_HALF_SLICE) &&
  34875         (slice_idx >= (fs->entry_count >> 1)) &&
  34876         ((_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) ||
  34877          (_BCM_FIELD_STAGE_LOOKUP == stage_fc->stage_id))) {
  34878         if ((soc_feature(unit,
  34879                         soc_feature_field_half_slice_single_tcam))
  34880                && (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id)) {
  34881             /* Currently Half Slice with Single Tcam in a
  34882              * Slice is supported only in IFP Stage in Ranger2Plus .*/
  34883             *tcam_idx = fs->start_tcam_idx + slice_idx;
  34884         } else {
  34885         /*
  34886          * Entry in the second quater of the sw slice
  34887          * maps to the hw entry in the first quater
  34888          * of the secondary tcam.
  34889          */
  34890         *tcam_idx = fs->start_tcam_idx + slice_idx + (fs->entry_count >> 1);
  34891         }
  34892     }  else if ((stage_fc->flags & _FP_STAGE_QUARTER_SLICE) &&
  34893                 (slice_idx >= (fs->entry_count >> 1)) &&
  34894                 ((_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) ||
  34895                 (_BCM_FIELD_STAGE_LOOKUP == stage_fc->stage_id))) {
  34896         if ((soc_feature(unit,
  34897                         soc_feature_field_quarter_slice_single_tcam))
  34898                && (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id)) {
  34899             /* Currently Quarter Slice with Single Tcam in a
  34900              * Slice is supported only in IFP Stage in Td2Plus.*/
  34901             *tcam_idx = fs->start_tcam_idx + slice_idx;
  34902         } else {
  34903         /*
  34904          * Entry in the second quater of the sw slice
  34905          * maps to the hw entry in the first quater
  34906          * of the secondary tcam.
  34907          */
  34908 
  34909         *tcam_idx = fs->start_tcam_idx + slice_idx +
  34910                     ((fs->entry_count >> 1 )* 3);
  34911         }
  34912     } else {
  34913         *tcam_idx = fs->start_tcam_idx + slice_idx;
  34914     }
  34915     return (BCM_E_NONE);
  34916 }
  34917 
  34918 /*
  34919  * Function:
  34920  *     _bcm_field_tcam_idx_to_slice_offset
  34921  *
  34922  * Purpose:
  34923  *     Given stage and tcam_index,
  34924  *     calculate slice and entry offset in the
  34925  *
  34926  * Parameters:
  34927  *     unit      - (IN) BCM device number.
  34928  *     stage_fc  - (IN) Pointer to field entry structure.
  34929  *     instance  - (IN) Instance of the pipe, the slice belongs to.
  34930  *     tcam_idx  - (IN) Entry tcam index.
  34931  *     slice     - (OUT) Entry slice number.
  34932  *     slice_idx - (OUT) Entry offset in the slice.
  34933  * Returns:
  34934  *     BCM_E_XXX
  34935  */
  34936 int
  34937 _bcm_field_tcam_idx_to_slice_offset(int unit, _field_stage_t *stage_fc,
  34938                                     int instance, int tcam_idx,
  34939                                     int *slice, int *slice_idx)
  34940 {
  34941     _field_slice_t  *fs;          /* Field slice number.         */
  34942     int idx;                      /* Slices iteration index.     */
  34943 
  34944     /* Input parameters check. */
  34945     if ((NULL == stage_fc) || (NULL == slice) ||
  34946         (NULL == slice_idx) || (tcam_idx < 0))  {
  34947         return (BCM_E_PARAM);
  34948     }
  34949 
  34950 
  34951     for (idx = 0; idx < stage_fc->tcam_slices; idx++) {
  34952         fs = stage_fc->slices[instance] + idx;
  34953         if (tcam_idx < (fs->start_tcam_idx + fs->entry_count)) {
  34954             *slice = idx;
  34955             *slice_idx = tcam_idx - fs->start_tcam_idx;
  34956             break;
  34957         }
  34958 
  34959         if (stage_fc->flags & _FP_STAGE_HALF_SLICE) {
  34960             if (tcam_idx < (fs->start_tcam_idx + (fs->entry_count << 1))) {
  34961                 *slice = idx;
  34962                 *slice_idx = tcam_idx - fs->start_tcam_idx -  \
  34963                           (fs->entry_count >> 1);
  34964                 break;
  34965             }
  34966         }
  34967 
  34968        if (stage_fc->flags & _FP_STAGE_QUARTER_SLICE) {
  34969            if (tcam_idx < (fs->start_tcam_idx + (fs->entry_count << 2))) {
  34970                *slice = idx;
  34971                *slice_idx = tcam_idx - fs->start_tcam_idx -  \
  34972                             ((fs->entry_count >> 1) * 3);
  34973                break;
  34974            }
  34975        }
  34976     }
  34977 
  34978     /* Tcam idx sanity check. */
  34979     if (idx == stage_fc->tcam_slices) {
  34980         return (BCM_E_PARAM);
  34981     }
  34982     return (BCM_E_NONE);
  34983 }
  34984 
  34985 /*
  34986  * Function:
  34987  *     _bcm_field_entry_tcam_idx_get
  34988  *
  34989  * Purpose:
  34990  *     Get the TCAM index of an entry ID.
  34991  *
  34992  * Parameters:
  34993  *     unit     - (IN) BCM device number.
  34994  *     f_ent    - (IN) Pointer to field entry structure.
  34995  *     tcam_idx - (OUT) Entry tcam index.
  34996  *
  34997  * Returns:
  34998  *     BCM_E_XXX
  34999  */
  35000 int
  35001 _bcm_field_entry_tcam_idx_get(int unit,_field_entry_t *f_ent, int *tcam_idx)
  35002 {
  35003     _field_stage_t  *stage_fc;    /* Stage field control structure. */
  35004     _field_slice_t  *fs;          /* Field slice number.            */
  35005     int             rv;           /* Operation return status.       */
  35006 
  35007     /* Input parameters check. */
  35008     if ((NULL == f_ent) || (NULL == tcam_idx))  {
  35009         return (BCM_E_PARAM);
  35010     }
  35011 
  35012     /* Requested entry structure sanity check. */
  35013     if ((NULL == f_ent->group) || (NULL == f_ent->fs)) {
  35014         return (BCM_E_PARAM);
  35015     }
  35016 
  35017     /* Get stage control structure. */
  35018     rv = _field_stage_control_get(unit, f_ent->group->stage_id, &stage_fc);
  35019     BCM_IF_ERROR_RETURN(rv);
  35020 
  35021     /* Given entry and stage flags calculate tcam index. */
  35022     fs = f_ent->fs;
  35023     if ((stage_fc->flags & _FP_STAGE_HALF_SLICE) &&
  35024         ((f_ent->flags & _FP_ENTRY_SECOND_HALF) ||
  35025          (f_ent->slice_idx >= (fs->entry_count >> 1))) &&
  35026         ((_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) ||
  35027          (_BCM_FIELD_STAGE_LOOKUP == stage_fc->stage_id))) {
  35028         if ((soc_feature(unit,
  35029                         soc_feature_field_half_slice_single_tcam))
  35030                && (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id)) {
  35031             /* Currently half Slice with Single Tcam in a
  35032              * Slice is supported only in IFP Stage in Ranger2Plus.*/
  35033             *tcam_idx = fs->start_tcam_idx + f_ent->slice_idx;
  35034         } else {
  35035         /*
  35036          * Entry in the second quater of the sw slice
  35037          * maps to the hw entry in the first quater
  35038          * of the secondary tcam.
  35039          */
  35040         *tcam_idx = fs->start_tcam_idx + f_ent->slice_idx +
  35041             (fs->entry_count >> 1);
  35042         }
  35043     } else if ((stage_fc->flags & _FP_STAGE_QUARTER_SLICE) &&
  35044             (f_ent->slice_idx >= (fs->entry_count >> 1))) {
  35045         if ((soc_feature(unit,
  35046                         soc_feature_field_quarter_slice_single_tcam))
  35047                && (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id)) {
  35048             /* Currently Quarter Slice with Single Tcam in a
  35049              * Slice is supported only in IFP Stage in Td2Plus.*/
  35050             *tcam_idx = fs->start_tcam_idx + f_ent->slice_idx;
  35051         } else {
  35052             *tcam_idx = fs->start_tcam_idx + f_ent->slice_idx +
  35053                 ((fs->entry_count >> 1) * 3);
  35054         }
  35055     } else {
  35056         *tcam_idx = fs->start_tcam_idx + f_ent->slice_idx;
  35057     }
  35058     return (BCM_E_NONE);
  35059 }
  35060 
  35061 
  35062 /*
  35063  * Function:
  35064  *      _field_action_delete
  35065  * Purpose:
  35066  *      Delete field action from a field entry.
  35067  * Parameters:
  35068  *      unit   - (IN) BCM device number
  35069  *      entry  - (IN) Entry ID
  35070  *      action - (IN) Action to remove (bcmFieldActionXXX)
  35071  *      param0 - (IN) Action parameter (use 0 if not required)
  35072  *      param1 - (IN) Action parameter (use 0 if not required)
  35073  * Returns:
  35074  *      BCM_E_XXX
  35075  * Notes:
  35076  */
  35077 int
  35078 _field_action_delete(int unit, bcm_field_entry_t entry,
  35079                         bcm_field_action_t action,
  35080                         uint32 param0, uint32 param1)
  35081 {
  35082     _field_control_t       *fc;            /* Field control structure.     */
  35083     _field_entry_t      *f_ent;
  35084     _field_action_t     *fa;
  35085     _field_action_t     *fa_prev = NULL;
  35086     int                 rv;                /* Operation return status. */
  35087 #if defined(BCM_TRIDENT_SUPPORT)
  35088     uint8               idx;               /* Entry array action index.    */
  35089     uint32              entry_flags;       /* Entry flags                  */
  35090 #endif
  35091     _field_action_t     *fa_cnt = NULL;
  35092     int8 nat_action_count = 0;
  35093 
  35094 #if defined(BCM_TOMAHAWK_SUPPORT)
  35095     if (soc_feature(unit, soc_feature_field_preselector_support) &&
  35096         (_BCM_FIELD_IS_PRESEL_ENTRY(entry) == TRUE)) {
  35097        return _bcm_field_presel_action_delete
  35098                     (unit, entry, action, param0, param1);
  35099     }
  35100 #endif /* BCM_TOMAHAWK_SUPPORT */
  35101 
  35102     /* Get field entry descriptor. */
  35103     rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent);
  35104     if (BCM_FAILURE(rv)) {
  35105         return (rv);
  35106     }
  35107 
  35108 #if defined(BCM_TOMAHAWK_SUPPORT)
  35109     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  35110         (f_ent->group->stage_id == _BCM_FIELD_STAGE_CLASS)) {
  35111         rv = _bcm_field_th_class_action_delete(unit, entry, action);
  35112         return (rv);
  35113     }
  35114 #endif /* BCM_TOMAHAWK_SUPPORT */
  35115 
  35116     /* Special treatment for pre-historic actions. */
  35117     switch (action) {
  35118       case  bcmFieldActionColorIndependent:
  35119 
  35120           BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  35121 
  35122           if(fc->flags & _FP_COLOR_INDEPENDENT) {
  35123               f_ent->flags |= _FP_ENTRY_COLOR_INDEPENDENT;
  35124           } else {
  35125               f_ent->flags &= ~_FP_ENTRY_COLOR_INDEPENDENT;
  35126           }
  35127           if (0 == (f_ent->flags & _FP_ENTRY_DIRTY)) {
  35128               f_ent->flags |= _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY;
  35129           }
  35130           f_ent->flags |= _FP_ENTRY_DIRTY;
  35131           return (BCM_E_NONE);
  35132       default:
  35133           break;
  35134     }
  35135 
  35136 
  35137     /* Find the action in the entry */
  35138     fa = f_ent->actions; /* start at head */
  35139 
  35140     while (fa != NULL) {
  35141         if (fa->action != action) {
  35142             fa_prev = fa;
  35143             fa      = fa->next;
  35144             continue;
  35145         }
  35146 
  35147         /* Some actions might be applied multiple times.*/
  35148         if (((action == bcmFieldActionMirrorIngress) ||
  35149              (action == bcmFieldActionMirrorEgress)) &&
  35150             (((uint32)_FP_INVALID_INDEX != param0) &&
  35151              ((uint32)_FP_INVALID_INDEX != param1)))  {
  35152             if ((fa->param[0] != param0)  || (fa->param[1] != param1)) {
  35153                 fa_prev = fa;
  35154                 fa      = fa->next;
  35155                 continue;
  35156             }
  35157         }
  35158 #if defined(BCM_TRIDENT3_SUPPORT)
  35159         if (action == bcmFieldActionVlanActions) {
  35160            if (f_ent->vlan_action_set) {
  35161               sal_free(f_ent->vlan_action_set);
  35162               f_ent->vlan_action_set = NULL;
  35163            }
  35164         }
  35165 #endif /* BCM_TRIDENT3_SUPPORT */
  35166         break;
  35167     }
  35168 
  35169 #if defined(BCM_TRIDENT_SUPPORT)
  35170     if (SOC_IS_TD_TT(unit)) {
  35171         if ((f_ent->group->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) ||
  35172             (f_ent->group->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) ||
  35173             (f_ent->group->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE)) {
  35174             if (NULL == fa) {
  35175                 if (f_ent->group->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
  35176                     entry_flags = (_FP_ENTRY_PRIMARY | _FP_ENTRY_SECOND_HALF);
  35177                 } else {
  35178                     entry_flags = _FP_ENTRY_SECONDARY;
  35179                 }
  35180 
  35181                 rv = _bcm_field_entry_flags_to_tcam_part(unit, entry_flags,
  35182                                                      f_ent->group,
  35183                                                      &idx);
  35184 
  35185                 BCM_IF_ERROR_RETURN(rv);
  35186                 /* Find the action in the entry */
  35187                 fa = f_ent[idx].actions; /* start at head */
  35188                 fa_prev = NULL;
  35189                 while (fa != NULL) {
  35190                     if (fa->action != action) {
  35191                         fa_prev = fa;
  35192                         fa      = fa->next;
  35193                         continue;
  35194                     }
  35195                     f_ent = &f_ent[idx];
  35196                     break;
  35197                 }
  35198             }
  35199         }
  35200     }
  35201 #endif
  35202 
  35203     if (NULL == fa) {
  35204         return (BCM_E_NOT_FOUND);
  35205     }
  35206 
  35207 #if defined(BCM_TRIDENT2_SUPPORT)
  35208     BCM_IF_ERROR_RETURN(_bcm_field_action_stat_flag_update
  35209                              (unit, f_ent, fa, FALSE));
  35210 #endif
  35211      /* Nat Actions Conflict with Oam Actions */
  35212     if (soc_feature(unit, soc_feature_fp_based_oam)) {
  35213         if ((fa->action == bcmFieldActionNatCancel)
  35214                 || (fa->action == bcmFieldActionNatEgressOverride)
  35215                 || (fa->action == bcmFieldActionNat)) {
  35216             fa_cnt = f_ent->actions; /* start at head */
  35217             while (fa_cnt != NULL) {
  35218                 if ((fa_cnt->action == bcmFieldActionNatCancel)
  35219                         || (fa_cnt->action == bcmFieldActionNatEgressOverride)
  35220                         || (fa_cnt->action == bcmFieldActionNat)) {
  35221                     if (fa_cnt->flags & _FP_ACTION_VALID) {
  35222                         nat_action_count++;
  35223                     }
  35224                 }
  35225                 fa_cnt = fa_cnt->next;
  35226             }
  35227             if (nat_action_count == 1) {
  35228                 f_ent->flags &= ~_FP_ENTRY_OAM_STAT_NOT_ALLOWED;
  35229             }
  35230         }
  35231     }
  35232 
  35233     /* If entry is installed mark action as invalid.
  35234      * Invalid actions will be removed during entry remove/reinstall.
  35235      */
  35236     if (f_ent->flags & _FP_ENTRY_INSTALLED) {
  35237         fa->flags  &= ~_FP_ACTION_VALID;
  35238         fa->flags |= _FP_ACTION_MODIFY;
  35239         /*
  35240          * Do not set action only dirty flag if qualifier parameter has
  35241          * been modified for this entry.
  35242          */
  35243         if (0 == (f_ent->flags & _FP_ENTRY_DIRTY)) {
  35244             f_ent->flags |= _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY;
  35245         }
  35246         f_ent->flags |= _FP_ENTRY_DIRTY;
  35247         return (BCM_E_NONE);
  35248     }
  35249 
  35250     if (fa_prev != NULL) {
  35251         fa_prev->next = fa->next;
  35252     } else { /* matched head of list */
  35253         f_ent->actions = fa->next;
  35254     }
  35255 
  35256     /* okay to free action */
  35257     if (NULL != (fa->egress_pbmp)) {
  35258         sal_free(fa->egress_pbmp);
  35259     }
  35260     sal_free(fa);
  35261     fa = NULL;
  35262 
  35263    /*
  35264     * Do not set action only dirty flag if qualifier parameter has
  35265     * been modified for this entry.
  35266     */
  35267     if (0 == (f_ent->flags & _FP_ENTRY_DIRTY)) {
  35268         f_ent->flags |= _FP_ENTRY_POLICY_TABLE_ONLY_DIRTY;
  35269     }
  35270     f_ent->flags |= _FP_ENTRY_DIRTY;
  35271     return (BCM_E_NONE);
  35272 }
  35273 #if defined(BCM_TOMAHAWK_SUPPORT)
  35274 /*
  35275  * Function:
  35276  *     _bcm_field_34bit_counter_update
  35277  * Description:
  35278  *     Service routine used to update 64-bit software accumulated 34 bit counters.
  35279  * Parameters:
  35280  *     unit     - (IN) BCM device number.
  35281  *     new_val  - (IN) New hw counter value from.
  35282  *     result   - (IN/OUT) Operation result.
  35283  * Returns:
  35284  *     BCM_E_XXX
  35285  * Notes:
  35286  *     This is for Tomahawk Devices
  35287  */
  35288 int
  35289 _bcm_field_34bit_counter_update(int unit, uint32 *new_val,
  35290                         _field_counter64_collect_t *result)
  35291 {
  35292     uint64 hw_val;
  35293     uint64 diff64;
  35294 
  35295     /* Input parameters check. */
  35296     if ((NULL == new_val) || (NULL == result)) {
  35297         return (BCM_E_PARAM);
  35298     }
  35299 
  35300     /* Compose H/W counter value. */
  35301     COMPILER_64_SET(hw_val, new_val[1], new_val[0]);
  35302 
  35303     if (COMPILER_64_LE(result->last_hw_value, hw_val)) {
  35304         /* diff = hw_val - result->last_hw_value */
  35305         COMPILER_64_ZERO(diff64);
  35306         COMPILER_64_OR(diff64, hw_val);
  35307         COMPILER_64_SUB_64(diff64, result->last_hw_value);
  35308     } else {
  35309         /*
  35310          * diff = 0x3ffffffff - (result->last_hw_value - hw_val) + 1
  35311          *      = 0x400000000 - result->last_hw_value + hw_val
  35312          */
  35313         COMPILER_64_SET(diff64, 0x4, 0);
  35314         COMPILER_64_SUB_64(diff64, result->last_hw_value);
  35315         COMPILER_64_ADD_64(diff64, hw_val);
  35316     }
  35317 
  35318     COMPILER_64_ADD_64(result->accumulated_counter, diff64);
  35319 
  35320     COMPILER_64_ZERO(result->last_hw_value);
  35321     COMPILER_64_OR(result->last_hw_value, hw_val);
  35322 
  35323     return (BCM_E_NONE);
  35324 }
  35325 
  35326 /*
  35327  * Function:
  35328  *  _bcm_field_26bit_counter_update
  35329  * Description:
  35330  *  Service routine used to update 64-bit software accumulated 26 bit counter.
  35331  * Parameters:
  35332  *   unit     - (IN) BCM device number.
  35333  *   new_val  - (IN) New hw counter value from.
  35334  *   result   - (IN/OUT) Operation result.
  35335  * Returns:
  35336  *   BCM_E_XXX
  35337  */
  35338 int
  35339 _bcm_field_26bit_counter_update(int unit, uint32 *new_val,
  35340                         _field_counter32_collect_t *result)
  35341 {
  35342     uint32 diff;
  35343     uint64 diff64;
  35344 
  35345     /* Input parameters check. */
  35346     if ((NULL == new_val) || (NULL == result)) {
  35347         return (BCM_E_PARAM);
  35348     }
  35349 
  35350     if (result->last_hw_value <= new_val[0]) {
  35351         diff = new_val[0] - result->last_hw_value;
  35352     } else {
  35353         diff = ((1 << 26) - 1) - (result->last_hw_value - new_val[0]) + 1;
  35354     }
  35355 
  35356     COMPILER_64_SET(diff64, 0, diff);
  35357     COMPILER_64_ADD_64(result->accumulated_counter, diff64);
  35358 
  35359     result->last_hw_value = new_val[0];
  35360 
  35361     return (BCM_E_NONE);
  35362 }
  35363 #endif /* BCM_TOMAHAWK_SUPPORT */
  35364 
  35365 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  35366 
  35367 /*
  35368  * Function:
  35369  *     _bcm_field_36bit_counter_update
  35370  * Description:
  35371  *     Service routine used to update 64-bit software accumulated 36 bit counters.
  35372  * Parameters:
  35373  *     unit     - (IN) BCM device number.
  35374  *     new_val  - (IN) New hw counter value from.
  35375  *     result   - (IN/OUT) Operation result.
  35376  * Returns:
  35377  *     BCM_E_XXX
  35378  * Notes:
  35379  *     This is for Bradley
  35380  */
  35381 int
  35382 _bcm_field_36bit_counter_update(int unit, uint32 *new_val,
  35383                         _field_counter64_collect_t *result)
  35384 {
  35385     uint64 hw_val;
  35386     uint64 diff64;
  35387 
  35388     /* Input parameters check. */
  35389     if ((NULL == new_val) || (NULL == result)) {
  35390         return (BCM_E_PARAM);
  35391     }
  35392 
  35393     /* Compose H/W counter value. */
  35394     COMPILER_64_SET(hw_val, new_val[1], new_val[0]);
  35395 
  35396     if (COMPILER_64_LE(result->last_hw_value, hw_val)) {
  35397         /* diff = hw_val - result->last_hw_value */
  35398         COMPILER_64_ZERO(diff64);
  35399         COMPILER_64_OR(diff64, hw_val);
  35400         COMPILER_64_SUB_64(diff64, result->last_hw_value);
  35401     } else {
  35402         /*
  35403          * diff = 0xfffffffff - (result->last_hw_value - hw_val) + 1
  35404          *      = 0x1000000000 - result->last_hw_value + hw_val
  35405          */
  35406         COMPILER_64_SET(diff64, 0x10, 0);
  35407         COMPILER_64_SUB_64(diff64, result->last_hw_value);
  35408         COMPILER_64_ADD_64(diff64, hw_val);
  35409     }
  35410 
  35411     COMPILER_64_ADD_64(result->accumulated_counter, diff64);
  35412 
  35413     COMPILER_64_ZERO(result->last_hw_value);
  35414     COMPILER_64_OR(result->last_hw_value, hw_val);
  35415 
  35416     return (BCM_E_NONE);
  35417 }
  35418 #endif /* BCM_BRADLEY_SUPPORT  || BCM_TRIUMPH3_SUPPORT */
  35419 /*
  35420  * Function:
  35421  *  _bcm_field_32bit_counter_update
  35422  * Description:
  35423  *  Service routine used to update 64-bit software accumulated 32 bit counter.
  35424  * Parameters:
  35425  *   unit     - (IN) BCM device number.
  35426  *   new_val  - (IN) New hw counter value from.
  35427  *   result   - (IN/OUT) Operation result.
  35428  * Returns:
  35429  *   BCM_E_XXX
  35430  */
  35431 int
  35432 _bcm_field_32bit_counter_update(int unit, uint32 *new_val,
  35433                         _field_counter32_collect_t *result)
  35434 {
  35435     uint32 diff;
  35436     uint64 diff64;
  35437 
  35438     /* Input parameters check. */
  35439     if ((NULL == new_val) || (NULL == result)) {
  35440         return (BCM_E_PARAM);
  35441     }
  35442 
  35443     if (result->last_hw_value <= new_val[0]) {
  35444         diff = new_val[0] - result->last_hw_value;
  35445     } else {
  35446         diff = ((0xFFFFFFFFL) - result->last_hw_value) + new_val[0] + 1;
  35447     }
  35448 
  35449     COMPILER_64_SET(diff64, 0, diff);
  35450     COMPILER_64_ADD_64(result->accumulated_counter, diff64);
  35451 
  35452     result->last_hw_value = new_val[0];
  35453 
  35454     return (BCM_E_NONE);
  35455 }
  35456 
  35457 /*
  35458  * Function:
  35459  *  _bcm_field_29bit_counter_update
  35460  * Description:
  35461  *  Service routine used to update 64-bit software accumulated 29 bit counter.
  35462  * Parameters:
  35463  *   unit     - (IN) BCM device number.
  35464  *   new_val  - (IN) New hw counter value from.
  35465  *   result   - (IN/OUT) Operation result.
  35466  * Returns:
  35467  *   BCM_E_XXX
  35468  */
  35469 int
  35470 _bcm_field_29bit_counter_update(int unit, uint32 *new_val,
  35471                         _field_counter32_collect_t *result)
  35472 {
  35473     uint32 diff;
  35474     uint64 diff64;
  35475 
  35476     /* Input parameters check. */
  35477     if ((NULL == new_val) || (NULL == result)) {
  35478         return (BCM_E_PARAM);
  35479     }
  35480 
  35481     if (result->last_hw_value <= new_val[0]) {
  35482         diff = new_val[0] - result->last_hw_value;
  35483     } else {
  35484         diff = ((1 << 29) - 1) - (result->last_hw_value - new_val[0]) + 1;
  35485     }
  35486 
  35487     COMPILER_64_SET(diff64, 0, diff);
  35488     COMPILER_64_ADD_64(result->accumulated_counter, diff64);
  35489 
  35490     result->last_hw_value = new_val[0];
  35491 
  35492     return (BCM_E_NONE);
  35493 }
  35494 #if defined(BCM_TRX_SUPPORT)
  35495 /*
  35496  * Function:
  35497  *     _bcm_field_35bit_counter_update
  35498  * Description:
  35499  *     Service routine used to update 64-bit software accumulated 35 bit counters.
  35500  * Parameters:
  35501  *     unit     - (IN) BCM device number.
  35502  *     new_val  - (IN) New hw counter value from.
  35503  *     result   - (IN/OUT) Operation result.
  35504  * Returns:
  35505  *     BCM_E_XXX
  35506  * Notes:
  35507  *     This is for BYTE_COUNTER field
  35508  */
  35509 int
  35510 _bcm_field_35bit_counter_update(int unit, uint32 *new_val,
  35511                         _field_counter64_collect_t *result)
  35512 {
  35513     uint64 hw_val;
  35514     uint64 diff64;
  35515 
  35516     /* Input parameters check. */
  35517     if ((NULL == new_val) || (NULL == result)) {
  35518         return (BCM_E_PARAM);
  35519     }
  35520 
  35521     /* Compose H/W counter value. */
  35522     COMPILER_64_SET(hw_val, new_val[1], new_val[0]);
  35523 
  35524     if (COMPILER_64_LE(result->last_hw_value, hw_val)) {
  35525         /* diff = hw_val - result->last_hw_value */
  35526         COMPILER_64_ZERO(diff64);
  35527         COMPILER_64_OR(diff64, hw_val);
  35528         COMPILER_64_SUB_64(diff64, result->last_hw_value);
  35529     } else {
  35530         /*
  35531          * diff = 0x7ffffffff - (result->last_hw_value - hw_val) + 1
  35532          *      = 0x800000000 - result->last_hw_value + hw_val
  35533          */
  35534         COMPILER_64_SET(diff64, 0x8, 0);
  35535         COMPILER_64_SUB_64(diff64, result->last_hw_value);
  35536         COMPILER_64_ADD_64(diff64, hw_val);
  35537     }
  35538 
  35539     COMPILER_64_ADD_64(result->accumulated_counter, diff64);
  35540 
  35541     COMPILER_64_ZERO(result->last_hw_value);
  35542     COMPILER_64_OR(result->last_hw_value, hw_val);
  35543 
  35544     return (BCM_E_NONE);
  35545 }
  35546 #endif /* BCM_TRX_SUPPORT */
  35547 
  35548 #ifdef BCM_TRIDENT_SUPPORT
  35549 /*
  35550  * Function:
  35551  *     _bcm_field_37bit_counter_update
  35552  * Description:
  35553  *     Service routine used to update 64-bit software accumulated 37 bit counters.
  35554  * Parameters:
  35555  *     unit     - (IN) BCM device number.
  35556  *     new_val  - (IN) New hw counter value from.
  35557  *     result   - (IN/OUT) Operation result.
  35558  * Returns:
  35559  *     BCM_E_XXX
  35560  * Notes:
  35561  *     This is for Trident2
  35562  */
  35563 int
  35564 _bcm_field_37bit_counter_update(int unit, uint32 *new_val,
  35565                         _field_counter64_collect_t *result)
  35566 {
  35567     uint64 hw_val;
  35568     uint64 diff64;
  35569 
  35570     /* Input parameters check. */
  35571     if ((NULL == new_val) || (NULL == result)) {
  35572         return (BCM_E_PARAM);
  35573     }
  35574 
  35575     /* Compose H/W counter value. */
  35576     COMPILER_64_SET(hw_val, new_val[1], new_val[0]);
  35577 
  35578     if (COMPILER_64_LE(result->last_hw_value, hw_val)) {
  35579         /* diff = hw_val - result->last_hw_value */
  35580         COMPILER_64_ZERO(diff64);
  35581         COMPILER_64_OR(diff64, hw_val);
  35582         COMPILER_64_SUB_64(diff64, result->last_hw_value);
  35583     } else {
  35584         /*
  35585          * diff = 0x1FFFFFFFFF - (result->last_hw_value - hw_val) + 1
  35586          *      = 0x2000000000 - result->last_hw_value + hw_val
  35587          */
  35588         COMPILER_64_SET(diff64, 0x20, 0);
  35589         COMPILER_64_SUB_64(diff64, result->last_hw_value);
  35590         COMPILER_64_ADD_64(diff64, hw_val);
  35591     }
  35592 
  35593     COMPILER_64_ADD_64(result->accumulated_counter, diff64);
  35594 
  35595     COMPILER_64_ZERO(result->last_hw_value);
  35596     COMPILER_64_OR(result->last_hw_value, hw_val);
  35597 
  35598     return (BCM_E_NONE);
  35599 }
  35600 #endif /* BCM_TRIDENT_SUPPORT */
  35601 
  35602 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  35603 /*
  35604  * Function:
  35605  *  _bcm_field_30bit_counter_update
  35606  * Description:
  35607  *  Service routine used to update 64-bit software accumulated 30 bit counter.
  35608  * Parameters:
  35609  *   unit     - (IN) BCM device number.
  35610  *   new_val  - (IN) New hw counter value from.
  35611  *   result   - (IN/OUT) Operation result.
  35612  * Returns:
  35613  *   BCM_E_XXX
  35614  */
  35615 int
  35616 _bcm_field_30bit_counter_update(int unit, uint32 *new_val,
  35617                         _field_counter32_collect_t *result)
  35618 {
  35619     uint32 diff;
  35620     uint64 diff64;
  35621 
  35622     /* Input parameters check. */
  35623     if ((NULL == new_val) || (NULL == result)) {
  35624         return (BCM_E_PARAM);
  35625     }
  35626 
  35627     if (result->last_hw_value <= new_val[0]) {
  35628         diff = new_val[0] - result->last_hw_value;
  35629     } else {
  35630         diff = ((1 << 30) - 1) - (result->last_hw_value - new_val[0]) + 1;
  35631     }
  35632 
  35633     COMPILER_64_SET(diff64, 0, diff);
  35634     COMPILER_64_ADD_64(result->accumulated_counter, diff64);
  35635 
  35636     result->last_hw_value = new_val[0];
  35637 
  35638     return (BCM_E_NONE);
  35639 }
  35640 #endif /* (BCM_TRIDENT_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) */
  35641 
  35642 /*
  35643  * Function:
  35644  *  _bcm_field_sw_counter_update
  35645  * Description:
  35646  *  Service routine used to update 64-bit software accumulated counters.
  35647  *  based on hw memory block.
  35648  * Parameters:
  35649  *   unit     - (IN) BCM device number.
  35650  *   stage_fc - (IN/OUT) Stage field control structure.
  35651  *   mem      - (IN) Counters memory.
  35652  *   idx_min  - (IN) First counter index in the buffer.
  35653  *   idx_max  - (IN) Last counter index in the buffer.
  35654  *   buf      - (IN) Counters buffer.
  35655  *   flags    - (IN) Device counters flags.
  35656  * Returns:
  35657  *  BCM_E_XXX
  35658  */
  35659 int
  35660 _bcm_field_sw_counter_update(int unit, _field_stage_t *stage_fc, soc_mem_t mem,
  35661                          int idx_min, int idx_max, char *buf, int flags)
  35662 {
  35663     _field_control_t       *fc;        /* Field control structure.         */
  35664     uint32                 *entry_p;   /* HW entry pointer.                */
  35665     int                    buf_offset; /* Offset into counters buffer.     */
  35666     int                    idx;        /* Iteration index.                 */
  35667     int                    rv;         /* Operartion return status.        */
  35668 
  35669 
  35670     /* Get field control structure. */
  35671     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  35672 
  35673     for (idx = idx_min, buf_offset = 0; idx <= idx_max; idx++, buf_offset++) {
  35674         /* Read counter value from the first memory. */
  35675         entry_p = soc_mem_table_idx_to_pointer(unit, mem, uint32 *,
  35676                                                buf, buf_offset);
  35677 
  35678         /* Process accumulated counter value. */
  35679         if (flags & _FIELD_FIRST_MEMORY_COUNTERS) {
  35680             rv = fc->functions.fp_counter_get(unit, stage_fc, mem,
  35681                                               entry_p, INVALIDm,
  35682                                               NULL, idx, NULL, NULL);
  35683         } else {
  35684             rv = fc->functions.fp_counter_get(unit, stage_fc, INVALIDm,
  35685                                               NULL, mem, entry_p, idx,
  35686                                               NULL, NULL);
  35687         }
  35688         if (BCM_FAILURE(rv)) {
  35689             break;
  35690         }
  35691     }
  35692     return (BCM_E_NONE);
  35693 }
  35694 
  35695 /*
  35696  * Function:
  35697  *    _field_mem_counters_read
  35698  * Description:
  35699  *    Service routine used to coolect 64-bit software accumulated counters.
  35700  *    for a specific stage.
  35701  * Parameters:
  35702  *    unit     - (IN) BCM device number.
  35703  *    stage_fc - (IN/OUT) Stage field control structure.
  35704  *    mem      - (IN) Counters memory.
  35705  * Returns:
  35706  *  BCM_E_XXX
  35707  */
  35708 
  35709 STATIC int
  35710 _field_mem_counters_read(int unit, _field_stage_t *stage_fc,
  35711                               soc_mem_t mem, int flags)
  35712 {
  35713     int       buf_end_idx;           /* Buffer end index.         */
  35714     int       alloc_size;            /* DMA buffer size.          */
  35715     int       max_idx;               /* Counter memory index max. */
  35716     int       min_idx;               /* Counter memory index min. */
  35717     char      *buf;                  /* Buffer to read the table. */
  35718     int       idx = 0;               /* Table iteration index.    */
  35719     int       rv = BCM_E_NONE;       /* Operation return value.   */
  35720     int       slice_index = 0;       /* Slice index               */
  35721     int       slice_size = 0;        /* Size of each slice        */
  35722     int       entry_ratio = 0;       /* entries per slice         */
  35723 
  35724     /* Input parameters check. */
  35725     if (NULL == stage_fc) {
  35726         return (BCM_E_PARAM);
  35727     }
  35728 
  35729     /* Make sure memory is valid */
  35730     if (INVALIDm == mem) {
  35731         return (BCM_E_NONE);
  35732     }
  35733 
  35734     /* Get table boundaries. */
  35735     min_idx = soc_mem_index_min(unit, mem);
  35736     max_idx = soc_mem_index_max(unit, mem);
  35737 
  35738     /* Dma part of the table & update software counters. */
  35739     if ((soc_feature(unit,
  35740                     soc_feature_field_quarter_slice_single_tcam) ||
  35741           soc_feature(unit,
  35742                     soc_feature_field_half_slice_single_tcam))
  35743             && (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id)) {
  35744         entry_ratio = (stage_fc->flags & _FP_STAGE_QUARTER_SLICE) ? 4:
  35745                             ((stage_fc->flags & _FP_STAGE_HALF_SLICE) ? 2 : 1);
  35746         idx = min_idx;
  35747         for (slice_index = 0;
  35748                 slice_index < stage_fc->tcam_slices; slice_index++) {
  35749             slice_size = stage_fc->slices[_FP_DEF_INST][slice_index].entry_count;
  35750 
  35751             /* Allocate memory buffer. */
  35752             alloc_size = ((slice_size) * sizeof(fp_counter_table_entry_t));
  35753             buf = soc_cm_salloc(unit, alloc_size, "fp_64_bit_counter");
  35754             if (buf == NULL) {
  35755                 return (BCM_E_MEMORY);
  35756             }
  35757             buf_end_idx = idx + (slice_size - 1);
  35758 
  35759             /* Dma range of entries in counter table. */
  35760             rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, idx,
  35761                     buf_end_idx, buf);
  35762             if (BCM_FAILURE(rv)) {
  35763                 break;
  35764             }
  35765 
  35766             rv = _bcm_field_sw_counter_update(unit, stage_fc, mem, idx,
  35767                     buf_end_idx, buf, flags);
  35768             if (BCM_FAILURE(rv)) {
  35769                 break;
  35770             }
  35771 
  35772             idx += stage_fc->slices[_FP_DEF_INST][slice_index].entry_count * entry_ratio;
  35773             soc_cm_sfree(unit, buf);
  35774             buf = NULL;
  35775         }
  35776     } else {
  35777         /* Allocate memory buffer. */
  35778         alloc_size = (_FP_64_COUNTER_BUCKET * sizeof(fp_counter_table_entry_t));
  35779         buf = soc_cm_salloc(unit, alloc_size, "fp_64_bit_counter");
  35780         if (buf == NULL) {
  35781             return (BCM_E_MEMORY);
  35782         }
  35783         for (idx = min_idx; idx <= max_idx; idx += _FP_64_COUNTER_BUCKET) {
  35784             buf_end_idx = MIN(max_idx, (idx + _FP_64_COUNTER_BUCKET - 1));
  35785             if (soc_feature(unit, soc_feature_field_stage_quarter_slice) &&
  35786                     (SOC_IS_TRIUMPH3(unit))) {
  35787                 /* Do not access h/w for tcam index mapping to the holes */
  35788                 if (stage_fc->stage_id == _BCM_FIELD_STAGE_INGRESS)  {
  35789                     buf_end_idx = MIN(max_idx, (idx + 128 - 1));
  35790                 }
  35791             }
  35792 
  35793             /* Dma range of entries in counter table. */
  35794             rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, idx,
  35795                     buf_end_idx, buf);
  35796             if (BCM_FAILURE(rv)) {
  35797                 break;
  35798             }
  35799 
  35800             rv = _bcm_field_sw_counter_update(unit, stage_fc, mem, idx,
  35801                     buf_end_idx, buf, flags);
  35802             if (BCM_FAILURE(rv)) {
  35803                 break;
  35804             }
  35805         }
  35806         soc_cm_sfree(unit, buf);
  35807     }
  35808     return (rv);
  35809 }
  35810 
  35811 
  35812 /*
  35813  * Function:
  35814  *     _field_stage_external_counters_collect
  35815  * Description:
  35816  *     Service routine used to coolect  64-bit software accumulated counters.
  35817  *          For the External-FP (Triumph).
  35818  * Parameters:
  35819  *     unit     - (IN) BCM device number.
  35820  *     fc       - (IN) Field control structure.
  35821  *     stage_fc - (IN/OUT) Stage field control structure.
  35822  * Returns:
  35823  *     BCM_E_XXX
  35824  */
  35825 
  35826 STATIC int
  35827 _field_stage_external_counters_collect (int unit, _field_control_t *fc,
  35828                                         _field_stage_t *stage_fc)
  35829 {
  35830     if ((stage_fc->_field_x32_counters == NULL)
  35831 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRX_SUPPORT)
  35832         && (stage_fc->_field_x64_counters == NULL)
  35833 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRX_SUPPORT */
  35834         )
  35835     {
  35836         return (BCM_E_UNAVAIL);
  35837     }
  35838 
  35839 #ifdef BCM_TRIUMPH_SUPPORT
  35840     BCM_IF_ERROR_RETURN
  35841         (_bcm_field_tr_external_counters_collect(unit, stage_fc));
  35842 #endif /* BCM_TRIUMPH_SUPPORT */
  35843 
  35844     return (BCM_E_NONE);
  35845 }
  35846 /*
  35847  * Function:
  35848  *  _field_stage_counters_collect
  35849  * Description:
  35850  *  Service routine used to coolect  64-bit software accumulated counters.
  35851  *  for a specific stage.
  35852  * Parameters:
  35853  *   unit     - (IN) BCM device number.
  35854  *   fc       - (IN) Field control structure.
  35855  *   stage_fc - (IN/OUT) Stage field control structure.
  35856  * Returns:
  35857  *  BCM_E_XXX
  35858  * Notes:
  35859  *  None.
  35860  */
  35861 
  35862 STATIC int
  35863 _field_stage_counters_collect (int unit, _field_control_t *fc,
  35864                                _field_stage_t *stage_fc)
  35865 {
  35866     soc_mem_t  counter_x_mem;        /* First counters memory.    */
  35867     soc_mem_t  counter_y_mem;        /* Second counters memory    */
  35868                                      /* for dual pipeline devices.*/
  35869 
  35870     /* Input parameters check. */
  35871     if (NULL == stage_fc) {
  35872         return (BCM_E_PARAM);
  35873     }
  35874 
  35875 #if defined(BCM_TOMAHAWK_SUPPORT)
  35876     if (stage_fc->flags & _FP_STAGE_MULTI_PIPE_COUNTERS) {
  35877         return BCM_E_NONE;
  35878     }
  35879 #endif
  35880 
  35881     /*  Check if counters are available at this stage. */
  35882     if ((stage_fc->_field_x32_counters == NULL)
  35883 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRX_SUPPORT)
  35884         && (stage_fc->_field_x64_counters == NULL)
  35885 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRX_SUPPORT */
  35886         )
  35887     {
  35888         return (BCM_E_UNAVAIL);
  35889     }
  35890 
  35891     /* Get counters memory for the stage. */
  35892     BCM_IF_ERROR_RETURN(_field_counter_mem_get(unit, stage_fc,
  35893                                                &counter_x_mem, &counter_y_mem));
  35894 
  35895     /* If stage doesn't have counters - we are done. */
  35896     if ((INVALIDm == counter_x_mem) && (INVALIDm == counter_y_mem)) {
  35897         return (BCM_E_NONE);
  35898     }
  35899 
  35900     if (INVALIDm != counter_x_mem) {
  35901         BCM_IF_ERROR_RETURN
  35902             (_field_mem_counters_read(unit, stage_fc, counter_x_mem,
  35903                                       _FIELD_FIRST_MEMORY_COUNTERS));
  35904     }
  35905 
  35906 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_SCORPION_SUPPORT)
  35907     if (INVALIDm != counter_y_mem) {
  35908         BCM_IF_ERROR_RETURN
  35909             (_field_mem_counters_read(unit, stage_fc, counter_y_mem,
  35910                                       _FIELD_SECOND_MEMORY_COUNTERS));
  35911     }
  35912 #endif /* BCM_BRADLEY_SUPPORT || BCM_SCORPION_SUPPORT */
  35913     return (BCM_E_NONE);
  35914 }
  35915 
  35916 
  35917 /*
  35918  * Function:
  35919  *  _bcm_esw_fp_counters_collect
  35920  * Description:
  35921  *  Callback routine executed each counter cycle to add up the
  35922  *  64-bit software accumulated counter values.
  35923  * Parameters:
  35924  *  unit -  (IN) BCM device number.
  35925  * Returns:
  35926  *  BCM_E_XXX
  35927  * Notes:
  35928  *  None.
  35929  */
  35930 
  35931 void
  35932 _bcm_esw_fp_counters_collect(int unit)
  35933 {
  35934    _field_control_t  *fc = NULL;           /* Field control structure.      */
  35935    _field_stage_t    *stage_fc;     /* Stage field control iterator. */
  35936 
  35937 
  35938    FP_LOCK(unit);
  35939    if (BCM_FAILURE(_field_control_get(unit, &fc))) {
  35940        FP_UNLOCK(unit);
  35941        return;
  35942    }
  35943 
  35944    /* Collect  counters from each fp pipeline stage. */
  35945    stage_fc = fc->stages;
  35946    while (NULL != stage_fc) {
  35947         if (stage_fc->stage_id == _BCM_FIELD_STAGE_EXTERNAL) {
  35948            _field_stage_external_counters_collect(unit, fc, stage_fc);
  35949         } else {
  35950            _field_stage_counters_collect(unit, fc, stage_fc);
  35951         }
  35952        stage_fc = stage_fc->next;
  35953    }
  35954 
  35955    FP_UNLOCK(unit);
  35956    return;
  35957 }
  35958 
  35959 /* Function    :
  35960  *           _field_qualify_IpProtocolCommon_get
  35961  * Description :
  35962  *           Get qualifier common L3 protocol ID
  35963  * Parameters  :
  35964  *   unit     (IN) BCM device number
  35965  *   entry    (IN) Field entry to qualify
  35966  *   qual_id  (IN) Field qualifier id.
  35967  *   protocol (OUT) Protocol name to qualify
  35968  * Returns:
  35969  *   BCM_E_XXX
  35970  */
  35971 int
  35972 _field_qualify_IpProtocolCommon_get(int unit,
  35973                                     bcm_field_entry_t entry,
  35974                                     bcm_field_qualify_t qual_id,
  35975                                     bcm_field_IpProtocolCommon_t *protocol)
  35976 {
  35977     uint8  data;              /* HW encoded data.         */
  35978     uint8  mask;              /* HW encoded mask.         */
  35979     int    rv;                /* Operation return status. */
  35980 
  35981     if (NULL == protocol) {
  35982         return (BCM_E_PARAM);
  35983     }
  35984 
  35985     /* Read qualifier match value and mask. */
  35986     rv = _bcm_field_entry_qualifier_uint8_get(unit, entry,
  35987                                        qual_id, &data, &mask);
  35988     BCM_IF_ERROR_RETURN(rv);
  35989 
  35990     if ((0 == data)  && (0x7 == mask)) {
  35991        *protocol = bcmFieldIpProtocolCommonTcp;
  35992     } else  if ((1 == data)  && (0x7 == mask)) {
  35993        *protocol = bcmFieldIpProtocolCommonUdp;
  35994     } else  if ((2 == data)  && (0x7 == mask)) {
  35995        *protocol = bcmFieldIpProtocolCommonIgmp;
  35996     } else  if ((3 == data)  && (0x7 == mask)) {
  35997        *protocol = bcmFieldIpProtocolCommonIcmp;
  35998     } else  if ((4 == data)  && (0x7 == mask)) {
  35999        *protocol = bcmFieldIpProtocolCommonIp6Icmp;
  36000     } else  if ((5 == data)  && (0x7 == mask)) {
  36001        *protocol = bcmFieldIpProtocolCommonIp6HopByHop;
  36002     } else  if ((6 == data)  && (0x7 == mask)) {
  36003        *protocol = bcmFieldIpProtocolCommonIpInIp;
  36004     } else  if ((0 == data)  && (0x6 == mask)) {
  36005        *protocol = bcmFieldIpProtocolCommonTcpUdp;
  36006     } else {
  36007         return (BCM_E_INTERNAL);
  36008     }
  36009     return (BCM_E_NONE);
  36010 }
  36011 
  36012 /* Function    :
  36013  *           _field_qualify_IpProtocolCommon
  36014  * Description :
  36015  *           Qualify common L3 protocol ID
  36016  * Parameters  :
  36017  *   unit     (IN) BCM device number
  36018  *   entry    (IN) Field entry to qualify
  36019  *   qual_id  (IN) Field qualifier id.
  36020  *   protocol (IN) Protocol name to qualify
  36021  * Returns:
  36022  *   BCM_E_XXX
  36023  */
  36024 int
  36025 _field_qualify_IpProtocolCommon(int unit, bcm_field_entry_t entry,
  36026                                 bcm_field_qualify_t qual_id,
  36027                                 bcm_field_IpProtocolCommon_t protocol)
  36028 {
  36029     uint32   data;
  36030     uint32   mask;
  36031 
  36032     if (protocol >= bcmFieldIpProtocolCommonCount) {
  36033         return (BCM_E_PARAM);
  36034     }
  36035 
  36036     switch (protocol) {
  36037       case bcmFieldIpProtocolCommonTcp:
  36038           data = 0x00;
  36039           mask = 0x07;
  36040           break;
  36041       case bcmFieldIpProtocolCommonUdp:
  36042           data = 0x01;
  36043           mask = 0x07;
  36044           break;
  36045       case bcmFieldIpProtocolCommonIgmp:
  36046           data = 0x02;
  36047           mask = 0x07;
  36048           break;
  36049       case bcmFieldIpProtocolCommonIcmp:
  36050           data = 0x03;
  36051           mask = 0x07;
  36052           break;
  36053       case bcmFieldIpProtocolCommonIp6Icmp:
  36054           data = 0x04;
  36055           mask = 0x07;
  36056           break;
  36057       case bcmFieldIpProtocolCommonIp6HopByHop:
  36058           /* TRX  devices do not use extension headers
  36059            * for packet ip protocol is determination.
  36060            * Please use  bcm_esw_field_qualify_ExtensionHeaderType */
  36061           if (SOC_IS_TRX(unit)) {
  36062               return (BCM_E_UNAVAIL);
  36063           }
  36064           data = 0x05;
  36065           mask = 0x07;
  36066           break;
  36067       case bcmFieldIpProtocolCommonIpInIp:
  36068           data = 0x06;
  36069           mask = 0x07;
  36070           break;
  36071       case bcmFieldIpProtocolCommonTcpUdp:
  36072           data = 0x00;
  36073           mask = 0x06;
  36074           break;
  36075       default:
  36076           return (BCM_E_UNAVAIL);
  36077     }
  36078     return  _field_qualify32(unit, entry, qual_id, data, mask);
  36079 }
  36080 
  36081 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) \
  36082     || defined(BCM_RAPTOR_SUPPORT)
  36083 
  36084 /* Function    : _field_qualify_IpFrag
  36085  * Description : qualify on Ip Frag Info.
  36086  * Parameters  : (IN) unit       BCM device number
  36087  *               (IN) entry      Field entry to qualify
  36088  *               (IN) qual_id    Field qualifier id.
  36089  *               (IN) frag_info  bcm_field_IpFrag_t to qualify
  36090  * Returns     : BCM_E_XXX
  36091  */
  36092 int
  36093 _field_qualify_IpFrag(int unit, bcm_field_entry_t entry,
  36094                       bcm_field_qualify_t qual_id,
  36095                       bcm_field_IpFrag_t frag_info)
  36096 {
  36097     int             rv;
  36098     _field_entry_t *f_ent = NULL;
  36099     uint32          data;
  36100     uint32          mask;
  36101     _field_stage_id_t stage_id;
  36102 
  36103     if (frag_info >= bcmFieldIpFragCount) {
  36104         return (BCM_E_PARAM);
  36105     }
  36106 
  36107 #if defined (BCM_TOMAHAWK_SUPPORT)
  36108     if (soc_feature(unit, soc_feature_field_preselector_support) &&
  36109         (_BCM_FIELD_IS_PRESEL_ENTRY(entry) == TRUE)) {
  36110 #if defined (BCM_FLOWTRACKER_SUPPORT)
  36111         if (soc_feature(unit, soc_feature_field_flowtracker_support)) {
  36112             stage_id =_BCM_FIELD_STAGE_FLOWTRACKER;
  36113         } else
  36114 #endif /* BCM_FLOWTRACKER_SUPPORT */
  36115         {
  36116             return BCM_E_UNAVAIL;
  36117         }
  36118     } else
  36119 #endif /* BCM_TOMAHAWK_SUPPORT */
  36120     {
  36121         rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent);
  36122         BCM_IF_ERROR_RETURN(rv);
  36123         stage_id = f_ent->group->stage_id;
  36124     }
  36125 
  36126 #if defined (BCM_TOMAHAWK3_SUPPORT)
  36127     if (((_BCM_FIELD_STAGE_INGRESS == stage_id) ||
  36128         (_BCM_FIELD_STAGE_EXACTMATCH == stage_id)) &&
  36129         (soc_feature(unit, soc_feature_th3_style_fp)))
  36130     {
  36131         return _field_th3_qualify_IpFrag(unit, entry,
  36132                                          qual_id,
  36133                                          frag_info);
  36134 
  36135     }
  36136 #endif
  36137 
  36138     if ((_BCM_FIELD_STAGE_INGRESS == stage_id) ||
  36139         (_BCM_FIELD_STAGE_EXACTMATCH == stage_id) ||
  36140         (_BCM_FIELD_STAGE_FLOWTRACKER == stage_id) ||
  36141 #if defined (BCM_TRX_SUPPORT)
  36142         (SOC_IS_TRX(unit) &&
  36143          (_BCM_FIELD_STAGE_LOOKUP == stage_id)) ||
  36144 #endif /* BCM_TRX_SUPPORT */
  36145         (_BCM_FIELD_STAGE_EXTERNAL == stage_id)) {
  36146         /*
  36147          * IP_FRAG_INFO[1] = (IP_OFFSET == 0) & !MoreFragmentlifyIpFragNonOrFirstbcmFieldQualifyIpFragNonOrFirst
  36148          * IP_FRAG_INFO[0] = (IP_OFFSET == 0)
  36149          */
  36150         switch(frag_info) {
  36151           case bcmFieldIpFragAny:
  36152               /* Any fragment of fragmented packet */
  36153               data = 0x00;
  36154               mask = 0x02;
  36155               break;
  36156           case bcmFieldIpFragNon:
  36157               /* Non-fragmented packet */
  36158               data = 0x02;
  36159               mask = 0x02;
  36160               break;
  36161           case bcmFieldIpFragFirst:
  36162               /* First fragment of fragmented packet*/
  36163               data = 0x01;
  36164               mask = 0x03;
  36165               break;
  36166           case bcmFieldIpFragNonOrFirst:
  36167               /* Non-fragmented or first fragment */
  36168               data = 0x01;
  36169               mask = 0x01;
  36170               break;
  36171           case bcmFieldIpFragNotFirst:
  36172               /* Not the first fragment */
  36173               data = 0x00;
  36174               mask = 0x03;
  36175               break;
  36176           default:
  36177               return (BCM_E_PARAM);
  36178         }
  36179     }
  36180 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  36181     else if((_BCM_FIELD_STAGE_EGRESS == stage_id) ||
  36182             (_BCM_FIELD_STAGE_LOOKUP == stage_id)) {
  36183         /*
  36184          * 00 : Not a fragment
  36185          * 10 : First fragment
  36186          * 11 : Non-first fragment
  36187          * 01 : Reserved
  36188          */
  36189         switch(frag_info) {
  36190           case bcmFieldIpFragAny:
  36191               /* Any fragment of fragmented packet */
  36192               data = 0x02;
  36193               mask = 0x02;
  36194               break;
  36195           case bcmFieldIpFragNon:
  36196               /* Non-fragmented packet */
  36197               data = 0x00;
  36198               mask = 0x03;
  36199               break;
  36200           case bcmFieldIpFragFirst:
  36201               /* First fragment of fragmented packet*/
  36202               data = 0x02;
  36203               mask = 0x03;
  36204               break;
  36205           case bcmFieldIpFragNonOrFirst:
  36206               /* Non-fragmented or first fragment */
  36207               data = 0x00;
  36208               mask = 0x01;
  36209               break;
  36210           case bcmFieldIpFragNotFirst:
  36211               /* Not the first fragment */
  36212               data = 0x03;
  36213               mask = 0x03;
  36214               break;
  36215           default:
  36216               return (BCM_E_PARAM);
  36217         }
  36218     }
  36219 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  36220     else {
  36221         return (BCM_E_INTERNAL);
  36222     }
  36223     rv = _field_qualify32(unit, entry, qual_id, data, mask);
  36224     return (rv);
  36225 }
  36226 
  36227 
  36228 /* Function    : _field_qualify_IpFrag_get
  36229  * Description : qualify on Ip Frag Info.
  36230  * Parameters  : (IN) unit       BCM device number
  36231  *               (IN) entry      Field entry to qualify
  36232  *               (IN) qual_id    Field qualifier id.
  36233  *               (OUT) frag_info  bcm_field_IpFrag_t to qualify
  36234  * Returns     : BCM_E_XXX
  36235  */
  36236 int
  36237 _field_qualify_IpFrag_get(int unit, bcm_field_entry_t entry,
  36238                           bcm_field_qualify_t qual_id,
  36239                           bcm_field_IpFrag_t *frag_info)
  36240 {
  36241     _field_entry_t *f_ent;       /* Field entry structure.      */
  36242     uint32    hw_data = 0;       /* HW buffer data.             */
  36243     uint32    hw_mask = 0;       /* HW buffer mask.             */
  36244     int       rv;                /* Operation return status.    */
  36245     _field_stage_id_t stage_id;  /* Field entry stage.          */
  36246 
  36247     /* Input parameters check. */
  36248     if (NULL == frag_info) {
  36249         return (BCM_E_PARAM);
  36250     }
  36251 
  36252 #if defined (BCM_TOMAHAWK_SUPPORT)
  36253     if (soc_feature(unit, soc_feature_field_preselector_support) &&
  36254         (_BCM_FIELD_IS_PRESEL_ENTRY(entry) == TRUE)) {
  36255 #if defined (BCM_FLOWTRACKER_SUPPORT)
  36256         if (soc_feature(unit, soc_feature_field_flowtracker_support)) {
  36257             stage_id =_BCM_FIELD_STAGE_FLOWTRACKER;
  36258         } else
  36259 #endif /* BCM_FLOWTRACKER_SUPPORT */
  36260         {
  36261             return BCM_E_UNAVAIL;
  36262         }
  36263     } else
  36264 #endif /* BCM_TOMAHAWK_SUPPORT */
  36265     {
  36266         rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent);
  36267         BCM_IF_ERROR_RETURN(rv);
  36268         stage_id = f_ent->group->stage_id;
  36269     }
  36270 
  36271 #if defined (BCM_TOMAHAWK3_SUPPORT)
  36272     if (((_BCM_FIELD_STAGE_INGRESS == stage_id) ||
  36273         (_BCM_FIELD_STAGE_EXACTMATCH == stage_id)) &&
  36274         (soc_feature(unit, soc_feature_th3_style_fp)))
  36275     {
  36276         return _field_th3_qualify_IpFrag_get(unit, entry,
  36277                                          qual_id,
  36278                                          frag_info);
  36279 
  36280     }
  36281 #endif
  36282 
  36283     /* Read qualifier match value and mask. */
  36284     rv = _bcm_field_entry_qualifier_uint32_get(unit, entry,
  36285                                                qual_id,
  36286                                                &hw_data, &hw_mask);
  36287     BCM_IF_ERROR_RETURN(rv);
  36288 
  36289     if ((_BCM_FIELD_STAGE_INGRESS == stage_id) ||
  36290         (_BCM_FIELD_STAGE_EXACTMATCH == stage_id) ||
  36291         (_BCM_FIELD_STAGE_FLOWTRACKER == stage_id) ||
  36292 #if defined (BCM_TRX_SUPPORT)
  36293         (SOC_IS_TRX(unit) &&
  36294          (_BCM_FIELD_STAGE_LOOKUP == stage_id)) ||
  36295 #endif /* BCM_TRX_SUPPORT */
  36296         (_BCM_FIELD_STAGE_EXTERNAL == stage_id)) {
  36297         /*
  36298          * IP_FRAG_INFO[1] = (IP_OFFSET == 0) & !MoreFragment
  36299          * IP_FRAG_INFO[0] = (IP_OFFSET == 0)
  36300          */
  36301 
  36302         if ((hw_data == 0x2) && (hw_mask == 0x2)) {
  36303             *frag_info = bcmFieldIpFragNon;
  36304         } else  if ((hw_data == 0x1) && (hw_mask == 0x3)) {
  36305             *frag_info = bcmFieldIpFragFirst;
  36306         } else  if ((hw_data == 0x1) && (hw_mask == 0x1)) {
  36307             *frag_info = bcmFieldIpFragNonOrFirst;
  36308         } else  if ((hw_data == 0x0) && (hw_mask == 0x3)) {
  36309             *frag_info = bcmFieldIpFragNotFirst;
  36310         } else  if ((hw_data == 0x0) && (hw_mask == 0x2)) {
  36311             *frag_info = bcmFieldIpFragAny;
  36312         } else {
  36313             return (BCM_E_INTERNAL);
  36314         }
  36315     }
  36316 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  36317     else if((_BCM_FIELD_STAGE_EGRESS == stage_id) ||
  36318             (_BCM_FIELD_STAGE_LOOKUP == stage_id)) {
  36319         /*
  36320          * 00 : Not a fragment
  36321          * 10 : First fragment
  36322          * 11 : Non-first fragment
  36323          * 01 : Reserved
  36324          */
  36325         if ((hw_data == 0x0) && (hw_mask == 0x3)) {
  36326             *frag_info = bcmFieldIpFragNon;
  36327         } else  if ((hw_data == 0x2) && (hw_mask == 0x3)) {
  36328             *frag_info = bcmFieldIpFragFirst;
  36329         } else  if ((hw_data == 0x0) && (hw_mask == 0x1)) {
  36330             *frag_info = bcmFieldIpFragNonOrFirst;
  36331         } else  if ((hw_data == 0x3) && (hw_mask == 0x3)) {
  36332             *frag_info = bcmFieldIpFragNotFirst;
  36333         } else  if ((hw_data == 0x2) && (hw_mask == 0x2)) {
  36334             *frag_info = bcmFieldIpFragAny;
  36335         } else {
  36336             return (BCM_E_INTERNAL);
  36337         }
  36338     }
  36339 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  36340     else {
  36341         return (BCM_E_INTERNAL);
  36342     }
  36343     return (BCM_E_NONE);
  36344 }
  36345 
  36346 
  36347 #endif /* BCM_FIREBOLT_SUPPORT || BCM_TRX_SUPPORT || BCM_RAPTOR_SUPPORT */
  36348 
  36349 /*
  36350  * Function:
  36351  *     _field_qual_selectors_insert
  36352  * Purpose:
  36353  *     Initialize field group select codes.
  36354  * Parameters:
  36355  *     unit        - (IN) BCM device number.
  36356  *     candidate   - (IN) Inserted selector set.
  36357  *     parts_count - (IN) Number of tcam parts.
  36358  *     selector    - (IN/OUT) Result selector set.
  36359  *
  36360  * Returns:
  36361  *     BCM_E_XXX
  36362  */
  36363 STATIC int
  36364 _field_qual_selectors_insert (int unit, _field_sel_t *candidate,
  36365                               uint8 parts_count,
  36366                               _bcm_field_selector_t *selector)
  36367 {
  36368     int8 idx;                       /* Tcam parts iterator.            */
  36369     uint8 selected_part;            /* Tcam part selected for
  36370                                        qualifier installation.         */
  36371     uint8 update_count_min;         /* Minimum selectors update count. */
  36372     uint8 update_count;             /* Number of updates required
  36373                                        to accommodate qualifier.       */
  36374     int rv;                         /* Operation return status.        */
  36375 
  36376     /* Input parameters check. */
  36377     if ((NULL == candidate) || (NULL == selector)) {
  36378         return (BCM_E_PARAM);
  36379     }
  36380 
  36381     update_count_min = _FP_INVALID_INDEX;
  36382     selected_part = _FP_INVALID_INDEX;
  36383 
  36384     if (soc_feature(unit, soc_feature_td2p_fp_sw_war)) {
  36385         for (idx = (parts_count -1); idx >= 0; idx--) {
  36386             update_count = 0;
  36387 
  36388             /* Test if selector can be inserted in a specific tcam part. */
  36389             rv = _field_selector_diff(unit, candidate, idx, selector, &update_count);
  36390             if (BCM_FAILURE(rv)) {
  36391                 continue;
  36392             }
  36393 
  36394             if (update_count < update_count_min) {
  36395                 update_count_min = update_count;
  36396                 selected_part = idx;
  36397             }
  36398         }
  36399     } else {
  36400         for (idx = 0; idx < parts_count; idx++) {
  36401             update_count = 0;
  36402 
  36403             /* Test if selector can be inserted in a specific tcam part. */
  36404             rv = _field_selector_diff(unit, candidate, idx, selector, &update_count);
  36405             if (BCM_FAILURE(rv)) {
  36406                 continue;
  36407             }
  36408 
  36409             if (update_count < update_count_min) {
  36410                 update_count_min = update_count;
  36411                 selected_part = idx;
  36412             }
  36413         }
  36414     }
  36415 
  36416     /* Check if any tcam part can accommodate all the required selectors. */
  36417     if ((uint8)_FP_INVALID_INDEX == selected_part) {
  36418         return (BCM_E_RESOURCE);
  36419     }
  36420 
  36421     /* Insert selector configuration. */
  36422     rv = _field_selector_insert(candidate, selected_part, selector);
  36423     return (rv);
  36424 }
  36425 
  36426 /*
  36427  * Function:
  36428  *     _field_qual_selectors_sort
  36429  * Purpose:
  36430  *     Sorf field qualifiers select codes.
  36431  * Parameters:
  36432  *     unit        - (IN) BCM device number.
  36433  *     candidate   - (IN) Inserted selector set.
  36434  *     parts_count - (IN) Number of tcam parts.
  36435  *     f_qual_arr  - (IN/OUT) Result selector set.
  36436  *
  36437  * Returns:
  36438  *     BCM_E_XXX
  36439  */
  36440 STATIC int
  36441 _field_qual_selectors_sort (int unit,
  36442                             _field_sel_t *candidate,
  36443                             uint8 parts_count,
  36444                             _bcm_field_qual_info_t *f_qual)
  36445 {
  36446     uint8 idx;                      /* Tcam parts iterator.               */
  36447     uint8 conf_idx;                 /* Configurations iterator.           */
  36448     uint8 update_count_min;         /* Minimum selectors update count.    */
  36449     uint8 update_count;             /* Number of updates required
  36450                                        to accommodate qualifier.          */
  36451     int rv;                         /* Operation return status.           */
  36452     _bcm_field_selector_t *selector;/* Qualifier select codes config.     */
  36453 
  36454     /* Input parameters check. */
  36455     if ((NULL == candidate) || (NULL == f_qual)) {
  36456         return (BCM_E_PARAM);
  36457     }
  36458 
  36459     /* Don't sort if only one configuration is available. */
  36460     if (f_qual->conf_sz <= 1) {
  36461         return (BCM_E_NONE);
  36462     }
  36463 
  36464     /* Get number of updates required for each qualifier configuration. */
  36465     for (conf_idx = 0; conf_idx < f_qual->conf_sz; conf_idx++) {
  36466         update_count_min = _FP_INVALID_INDEX;
  36467         selector = &((f_qual->conf_arr[conf_idx]).selector);
  36468 
  36469         for (idx = 0; idx < parts_count; idx++) {
  36470             update_count = 0;
  36471 
  36472             /* Test if selector can be inserted in a specific tcam part. */
  36473             rv = _field_selector_diff(unit, candidate, idx,
  36474                                       selector, &update_count);
  36475             if (BCM_FAILURE(rv)) {
  36476                 continue;
  36477             }
  36478 
  36479             if (update_count < update_count_min) {
  36480                 update_count_min = update_count;
  36481             }
  36482         }
  36483         /* Keep minimum number of required updates. */
  36484         selector->update_count  =  update_count_min;
  36485     }
  36486 
  36487     /* Qualifier configurations sort based on number of updates required.  */
  36488     _shr_sort(f_qual->conf_arr, f_qual->conf_sz,
  36489                sizeof(_bcm_field_qual_conf_t), _field_selector_update_cmp);
  36490     return (BCM_E_NONE);
  36491 }
  36492 
  36493 /*
  36494  * Function:
  36495  *     _field_group_selectors_init
  36496  * Purpose:
  36497  *     Initialize field group select codes.
  36498  * Parameters:
  36499  *     unit   - (IN) BCM device number.
  36500  *     fg     - (IN/OUT) Field group structure.
  36501  *
  36502  * Returns:
  36503  *     BCM_E_XXX
  36504  */
  36505 STATIC int
  36506 _field_group_selectors_init(int unit, _field_group_t *fg)
  36507 {
  36508     /* Input parameters check. */
  36509     if (NULL == fg) {
  36510         return (BCM_E_PARAM);
  36511     }
  36512 
  36513     fg->sel_codes[0].intraslice = _FP_SELCODE_DONT_USE;
  36514     if (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) {
  36515         if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
  36516             fg->sel_codes[2].intraslice = _FP_SELCODE_DONT_USE;
  36517         } else {
  36518             fg->sel_codes[1].intraslice = _FP_SELCODE_DONT_USE;
  36519         }
  36520     } else if (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) {
  36521         fg->sel_codes[1].intraslice = _FP_SELCODE_DONT_USE;
  36522         fg->sel_codes[2].intraslice = _FP_SELCODE_DONT_USE;
  36523     }
  36524 
  36525     fg->sel_codes[0].secondary = _FP_SELCODE_DONT_USE;
  36526     if (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) {
  36527         if (fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
  36528             fg->sel_codes[1].secondary = _FP_SELCODE_DONT_USE;
  36529             fg->sel_codes[2].secondary = _FP_SELCODE_DONT_USE;
  36530         }
  36531     } else if (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) {
  36532         fg->sel_codes[1].secondary = _FP_SELCODE_DONT_USE;
  36533         fg->sel_codes[2].secondary = _FP_SELCODE_DONT_USE;
  36534     }
  36535 
  36536     return BCM_E_NONE;
  36537 }
  36538 
  36539 /*
  36540  * Function:
  36541  *     _bcm_field_selcode_qual_arr_free
  36542  * Purpose:
  36543  *     Free memory allocated for the temporary qual array used during group creation.
  36544  * Parameters:
  36545  *     unit          - (IN) BCM device number.
  36546  *     f_qual_arr    - (INOUT)Qualifiers information array.
  36547  *     qual_count    - (IN)Qualifiers information array size.
  36548  */
  36549 void _bcm_field_selcode_qual_arr_free(int unit,
  36550         _bcm_field_qual_info_t ***f_qual_arr, uint16 qual_count)
  36551 {
  36552     int   qual_idx = 0;
  36553 
  36554     if (NULL == f_qual_arr) {
  36555         return;
  36556     }
  36557 
  36558     if (*f_qual_arr) {
  36559         for (qual_idx = 0; qual_idx < qual_count ; qual_idx++) {
  36560             if ((*f_qual_arr)[qual_idx]) {
  36561                 if ((*f_qual_arr)[qual_idx]->conf_arr) {
  36562                     sal_free((*f_qual_arr)[qual_idx]->conf_arr);
  36563                     (*f_qual_arr)[qual_idx]->conf_arr = NULL;
  36564                 }
  36565                 sal_free((*f_qual_arr)[qual_idx]);
  36566                 (*f_qual_arr)[qual_idx] = NULL;
  36567             }
  36568         }
  36569         sal_free(*f_qual_arr);
  36570         *f_qual_arr = NULL;
  36571     }
  36572 }
  36573 
  36574 /*
  36575  * Function:
  36576  *     _bcm_field_qualifiers_info_get
  36577  * Purpose:
  36578  *     Copy qualifiers configuration for a given qualifiers set.
  36579  * Parameters:
  36580  *     unit          - (IN) BCM device number.
  36581  *     stage_fc      - (IN) Stage Field control structure.
  36582  *     qset_req      - (IN) Client qualifier set.
  36583  *     f_qual_arr    - (OUT)Qualifiers information array.
  36584  *     qual_arr_size - (OUT)Qualifiers information array size.
  36585  *
  36586  * Returns:
  36587  *     BCM_E_XXX
  36588  */
  36589 int
  36590 _bcm_field_qualifiers_info_get(int unit, _field_stage_t *stage_fc,
  36591                                bcm_field_qset_t *qset_req,
  36592                                _bcm_field_qual_info_t ***f_qual_arr,
  36593                                uint16 *qual_arr_size)
  36594 {
  36595     uint16 idx;              /* Qualifier set iterator.   */
  36596     uint16 arr_idx;          /* Qualifiers array index.   */
  36597 
  36598     /* Input parameters check. */
  36599     if ((NULL == f_qual_arr) || (NULL == qset_req) ||
  36600         (NULL == qual_arr_size) || (NULL == stage_fc)) {
  36601         return (BCM_E_PARAM);
  36602     }
  36603 
  36604     /* Get number of qualifiers in requested qualifier set. */
  36605     *qual_arr_size = 0;
  36606     for(idx = 0; idx < _SHR_BITDCLSIZE(BCM_FIELD_QUALIFY_MAX); idx++) {
  36607         *qual_arr_size += _shr_popcount(qset_req->w[idx]);
  36608     }
  36609 
  36610 
  36611     /* Allocate & initialize group select codes array. */
  36612     _FP_XGS3_ALLOC((*f_qual_arr),
  36613                    (*qual_arr_size * sizeof(_bcm_field_qual_info_t *)),
  36614                    "Field qualifiers");
  36615     if (NULL == (*f_qual_arr)) {
  36616         return (BCM_E_MEMORY);
  36617     }
  36618 
  36619     /* Copy individual qualifiers information from the requested qset */
  36620     arr_idx = 0;
  36621     for (idx = 0; idx < _bcmFieldQualifyCount; idx++) {
  36622         /* Skip unused qualifiers. */
  36623         if (0 == BCM_FIELD_QSET_TEST((*qset_req), idx)) {
  36624             continue;
  36625         }
  36626 
  36627         /* Qualifiers support check. */
  36628         if (NULL == stage_fc->f_qual_arr[idx]) {
  36629             sal_free (*f_qual_arr);
  36630             return (BCM_E_RESOURCE);
  36631         }
  36632 
  36633         /* Make a copy of the qualifier combination for sorting
  36634          * instead of using pointer to the data in stage_fc
  36635          * this will avoid sorting of qualifiers in stage_fc
  36636          * and make group create independent of previously
  36637          * created groups.
  36638          */
  36639         _FP_XGS3_ALLOC(((*f_qual_arr)[arr_idx]),
  36640                       (sizeof(_bcm_field_qual_info_t)),
  36641                       "Field qualifiers");
  36642         if (NULL == (*f_qual_arr)[arr_idx]) {
  36643             _bcm_field_selcode_qual_arr_free(unit, f_qual_arr, arr_idx);
  36644             return (BCM_E_MEMORY);
  36645         }
  36646 
  36647         (*f_qual_arr)[arr_idx]->qid = stage_fc->f_qual_arr[idx]->qid;
  36648         (*f_qual_arr)[arr_idx]->conf_sz = stage_fc->f_qual_arr[idx]->conf_sz;
  36649 
  36650         /* Allocate memory for qualifer config array */
  36651         _FP_XGS3_ALLOC(((*f_qual_arr)[arr_idx]->conf_arr),
  36652                       (stage_fc->f_qual_arr[idx]->conf_sz * sizeof(_bcm_field_qual_conf_t)),
  36653                       "Field qualifiers");
  36654         if (NULL == (*f_qual_arr)[arr_idx]->conf_arr) {
  36655             sal_free((*f_qual_arr)[arr_idx]);
  36656             (*f_qual_arr)[arr_idx] = NULL;
  36657             _bcm_field_selcode_qual_arr_free(unit, f_qual_arr, arr_idx);
  36658             return (BCM_E_MEMORY);
  36659         }
  36660 
  36661         /* Copy qual info from stage fc to new memory allocated */
  36662         memcpy((*f_qual_arr)[arr_idx]->conf_arr, stage_fc->f_qual_arr[idx]->conf_arr,
  36663                 (stage_fc->f_qual_arr[idx]->conf_sz * sizeof(_bcm_field_qual_conf_t)));
  36664 
  36665         arr_idx++;
  36666         if (arr_idx == (*qual_arr_size)) {
  36667             break;
  36668         }
  36669     }
  36670 
  36671     /* Qualifier array elements are sorted so less frequently present
  36672        qualifiers appear first. */
  36673     _shr_sort((*f_qual_arr), *qual_arr_size, sizeof(_bcm_field_qual_info_t *),
  36674               _field_qual_info_cmp);
  36675 
  36676     return (BCM_E_NONE);
  36677 }
  36678 /*
  36679  * Function:
  36680  *     _field_qual_offsets_copy
  36681  * Purpose:
  36682  *     Copy group qualifiers offsets.
  36683  * Parameters:
  36684  *     unit       - (IN) BCM unit number.
  36685  *     fg         - (IN) Field group.
  36686  *     qual_count - (IN) Number of qualifiers on group qset.
  36687  *     f_qual_arr - (IN) Qualifier descriptors array.
  36688  *     fg        - (IN/OUT)Select code information filled into the group.
  36689  *
  36690  * Returns:
  36691  *     BCM_E_XXX
  36692  */
  36693 STATIC int
  36694 _field_qual_offsets_copy(int unit, _field_group_t *fg, uint16 qual_count,
  36695                          _bcm_field_qual_info_t **f_qual_arr,
  36696                          uint8 *qual_conf_idx)
  36697 {
  36698     _bcm_field_qual_conf_t *qual_config; /* Qualifier configuration.       */
  36699     _bcm_field_group_qual_t *q_arr;      /* Qualifiers array.              */
  36700     bcm_field_qset_t qset_assigned;      /* Assigned to a specific         */
  36701                                          /* entry part qualifiers.         */
  36702     int    qual_idx;                     /* Qualifiers iteration index.    */
  36703     int    part_idx;                     /* Tcam parts iteration index.    */
  36704     int    parts_count = 0;              /* Number of entry parts.         */
  36705     uint8  conf_idx;                     /* Qualifiers configuration index.*/
  36706     uint8  diff;                         /* Selector diff .                */
  36707     uint16 *qid_arr;                     /* New qualifiers array.          */
  36708     _bcm_field_qual_offset_t *offset_arr;/* New qualifier offsets array.   */
  36709     uint16 size = 0;                     /* Qualifiers array size.         */
  36710     int   rv;                            /* Operation return status.       */
  36711 
  36712     /* Input parameters check. */
  36713     if ((NULL == fg) || (NULL == f_qual_arr) || (NULL == qual_conf_idx)) {
  36714         return (BCM_E_PARAM);
  36715     }
  36716 
  36717     BCM_FIELD_QSET_INIT(qset_assigned);
  36718     /* Get number of entry parts we have to read. */
  36719     rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
  36720                                             fg->flags, &parts_count);
  36721     BCM_IF_ERROR_RETURN(rv);
  36722 
  36723     /* Get currently assigned qualifiers. */
  36724     for (part_idx = 0; part_idx < parts_count; part_idx++) {
  36725         q_arr = &(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part_idx]);
  36726         for (qual_idx = 0; qual_idx < q_arr->size; qual_idx++) {
  36727             BCM_FIELD_QSET_ADD (qset_assigned, q_arr->qid_arr[qual_idx]);
  36728         }
  36729     }
  36730 
  36731     for (part_idx = 0; part_idx < parts_count; part_idx++) {
  36732         /* Initialization. */
  36733         offset_arr = NULL;
  36734         qid_arr = NULL;
  36735 
  36736         /* Get qualifiers array pointer. */
  36737         q_arr = &(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part_idx]);
  36738         size = q_arr->size;
  36739 
  36740         for (qual_idx = 0; qual_idx < qual_count; qual_idx++) {
  36741             /* Check if qualifier was already assigned. */
  36742             if (BCM_FIELD_QSET_TEST (qset_assigned, f_qual_arr[qual_idx]->qid)) {
  36743                 continue;
  36744             }
  36745 
  36746             /* Get qualifier configuration index. */
  36747             conf_idx = qual_conf_idx[qual_idx];
  36748             /* Get qualifier configuration for the index. */
  36749             qual_config = f_qual_arr[qual_idx]->conf_arr + conf_idx;
  36750             /* Test if selector was inserted in a specific tcam part. */
  36751             rv = _field_selector_diff(unit, fg->sel_codes, part_idx,
  36752                                       &qual_config->selector,
  36753                                       &diff);
  36754             if (BCM_FAILURE(rv) || diff) {
  36755                 continue;
  36756             }
  36757             size++;
  36758         }
  36759 
  36760         /* Allocate qualifiers id and offsets array. */
  36761         _FP_XGS3_ALLOC(qid_arr, (size * sizeof (uint16)), "Group qual id");
  36762         if (NULL == qid_arr) {
  36763             return (BCM_E_MEMORY);
  36764         }
  36765         _FP_XGS3_ALLOC(offset_arr, (size *
  36766                        sizeof (_bcm_field_qual_offset_t)), "Group qual offset");
  36767         if (NULL == offset_arr) {
  36768             sal_free (qid_arr);
  36769             return (BCM_E_MEMORY);
  36770         }
  36771 
  36772         /* Copy whatever qualifiers the group already have into the new array */
  36773         if (q_arr->size) {
  36774             sal_memcpy(qid_arr, q_arr->qid_arr,
  36775                        q_arr->size * sizeof (uint16));
  36776             sal_memcpy(offset_arr, q_arr->offset_arr,
  36777                        q_arr->size * sizeof(_bcm_field_qual_offset_t));
  36778         }
  36779         size = q_arr->size;
  36780 
  36781         /* Free old group qualifiers. */
  36782         rv = _bcm_field_group_qualifiers_free(fg, part_idx);
  36783         if (BCM_FAILURE(rv)) {
  36784             sal_free(qid_arr);
  36785             sal_free(offset_arr);
  36786             return (rv);
  36787         }
  36788 
  36789         /* Now let the group point to the new and bigger array */
  36790         q_arr->qid_arr = qid_arr;
  36791         q_arr->offset_arr = offset_arr;
  36792         q_arr->size = size;
  36793 
  36794         for (qual_idx = 0; qual_idx < qual_count; qual_idx++) {
  36795             /* Check if qualifier was already assigned. */
  36796             if (BCM_FIELD_QSET_TEST (qset_assigned, f_qual_arr[qual_idx]->qid)) {
  36797                 continue;
  36798             }
  36799 
  36800             /* Get qualifier configuration index. */
  36801             conf_idx = qual_conf_idx[qual_idx];
  36802             /* Get qualifier configuration for the index. */
  36803             qual_config = f_qual_arr[qual_idx]->conf_arr + conf_idx;
  36804             /* Test if selector was inserted in a specific tcam part. */
  36805             rv = _field_selector_diff(unit, fg->sel_codes, part_idx,
  36806                                       &qual_config->selector,
  36807                                       &diff);
  36808             if (BCM_FAILURE(rv) || diff) {
  36809                 continue;
  36810             }
  36811             q_arr->qid_arr[q_arr->size] = f_qual_arr[qual_idx]->qid;
  36812             q_arr->offset_arr[q_arr->size] = qual_config->offset;
  36813             q_arr->size++;
  36814             BCM_FIELD_QSET_ADD (qset_assigned, f_qual_arr[qual_idx]->qid);
  36815         }
  36816     }
  36817     return (BCM_E_NONE);
  36818 }
  36819 
  36820 /*
  36821  * Function:
  36822  *     _bcm_field_qual_lists_get
  36823  * Purpose:
  36824  *     Build a group's qual_info_t linked list by assembling
  36825  *     linked-lists from each select code.
  36826  * Parameters:
  36827  *     unit      - (IN) BCM device number.
  36828  *     stage_fc  - (IN) Stage field control structure.
  36829  *     fg        - (IN) Group control structure.
  36830  * Returns:
  36831  *     BCM_E_XXX
  36832  */
  36833 int
  36834 _bcm_field_qual_lists_get(int unit, _field_stage_t *stage_fc,
  36835                              _field_group_t *fg)
  36836 {
  36837     return (BCM_E_NONE);
  36838 }
  36839 
  36840 /*
  36841  * Function:
  36842  *     _bcm_field_selcode_to_qset
  36843  * Purpose:
  36844  *     Find the qset that corresponds to all the possible qualifiers
  36845  *     supported by the field selection codes (FPF1, FPF2, FPF3).
  36846  * Parameters:
  36847  *     unit      - (IN)  unit
  36848  *     stage_fc  - (IN)  Stage Field control structure.
  36849  *     fg        - (IN)  Field group control structure.
  36850  *     code_id   - (IN)  Entry part.
  36851  *     qset      - (OUT) Client qualifier set.
  36852  * Returns:
  36853  *     BCM_E_XXX
  36854  */
  36855 int
  36856 _bcm_field_selcode_to_qset(int unit, _field_stage_t *stage_fc,
  36857                               _field_group_t *fg, int code_id,
  36858                               bcm_field_qset_t *qset)
  36859 {
  36860                                 /* selectors value.              */
  36861     int idx;                    /* Qualifiers array iterator.    */
  36862 
  36863     /* Input parameters check. */
  36864     if ((NULL == qset) || (NULL == stage_fc) ||
  36865         (NULL == fg)   || (code_id < 0) || (code_id >= _FP_MAX_ENTRY_WIDTH)) {
  36866         return (BCM_E_PARAM);
  36867     }
  36868 
  36869     BCM_FIELD_QSET_INIT(*qset);
  36870 
  36871     for(idx = 0; idx < fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][code_id].size; idx++) {
  36872         BCM_FIELD_QSET_ADD(*qset, fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][code_id].qid_arr[idx]);
  36873     }
  36874     return (BCM_E_NONE);
  36875 }
  36876 
  36877 /*
  36878  * Function:
  36879  *     _bcm_field_selcode_get
  36880  * Purpose:
  36881  *     Finds a 4-tuple of select encodings that will satisfy the
  36882  *     requested qualifier set (Qset).
  36883  * Parameters:
  36884  *     unit      - (IN) BCM unit number.
  36885  *     stage_fc  - (IN) Stage Field control structure.
  36886  *     qset_req  - (IN) Client qualifier set.
  36887  *     fg        - (IN/OUT)Select code information filled into the group.
  36888  *
  36889  * Returns:
  36890  *     BCM_E_XXX
  36891  */
  36892 int
  36893 _bcm_field_selcode_get(int unit, _field_stage_t *stage_fc,
  36894                            bcm_field_qset_t *qset_req,
  36895                            _field_group_t *fg)
  36896 {
  36897 #ifdef BCM_WARM_BOOT_SUPPORT
  36898     _field_control_t     *fc;            /* Pointer to field control  */
  36899 #endif
  36900     _bcm_field_qual_info_t **f_qual_arr; /* Qualifiers information.         */
  36901     _bcm_field_qual_conf_t *qual_config; /* Qualifier configuration.        */
  36902     uint8 *qual_conf_idx;                /* Array of iterators over each    */
  36903                                          /* individual qual configurations. */
  36904     _field_sel_t *sel_arr;               /* Selectors status before each    */
  36905                                          /* individual qualifier            */
  36906                                          /* configuration was added.        */
  36907     _field_sel_t *candidate;             /* Candidate select codes set.     */
  36908     uint8  conf_idx = 0;                 /* Qualifiers configuration index. */
  36909     uint16 qual_count = 0;               /* Number of qualifiers in         */
  36910                                          /* the requested qset.             */
  36911     int   parts_count = 0;               /* Number of tcam parts.           */
  36912     int   qual_idx = 0;                  /* Qualifiers iteration index.     */
  36913     int   sel_entry_sz = 0;              /* Byte size of sel_arr entity.    */
  36914     int   rv = BCM_E_NONE;               /* Operation return status.        */
  36915 
  36916     /* Input parameters check. */
  36917     if ((NULL == fg) || (NULL == qset_req) || (NULL == stage_fc)) {
  36918         return (BCM_E_PARAM);
  36919     }
  36920 
  36921     /* Initialization. */
  36922     f_qual_arr = NULL;
  36923     qual_config = NULL;
  36924     qual_conf_idx = NULL;
  36925     sel_arr = NULL;
  36926     candidate = NULL;
  36927 
  36928 #ifdef BCM_WARM_BOOT_SUPPORT
  36929     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  36930 #endif
  36931     /* Update group selectors based on group flags. */
  36932     rv = _field_group_selectors_init(unit, fg);
  36933     BCM_IF_ERROR_RETURN(rv);
  36934 
  36935     /* Get qualifiers configuration.          */
  36936     /* NOTE: Must free f_qual_arr at the end. */
  36937     rv = _bcm_field_qualifiers_info_get (unit, stage_fc, qset_req,
  36938                                          &f_qual_arr, &qual_count);
  36939     BCM_IF_ERROR_RETURN(rv);
  36940 
  36941     /* Allocate and initialize qualifier configurations iterators. */
  36942     _FP_XGS3_ALLOC(qual_conf_idx, (qual_count * sizeof(uint8)),
  36943                    "Field qualifier configuration");
  36944     if (NULL == qual_conf_idx) {
  36945         _bcm_field_selcode_qual_arr_free(unit, &f_qual_arr, qual_count);
  36946         return (BCM_E_MEMORY);
  36947     }
  36948 
  36949     /* Get number of entry parts. */
  36950     rv  = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
  36951                                              fg->flags, &parts_count);
  36952     if (BCM_FAILURE(rv)) {
  36953         sal_free(qual_conf_idx);
  36954         qual_conf_idx = NULL;
  36955         _bcm_field_selcode_qual_arr_free(unit, &f_qual_arr, qual_count);
  36956         return (rv);
  36957     }
  36958 
  36959     /* Allocate and initialize select codes status before           */
  36960     /* individual qualifier configuration was applied.              */
  36961     /* Candidate select codes are in the last element of the array. */
  36962     sel_entry_sz = parts_count * sizeof(_field_sel_t);
  36963     _FP_XGS3_ALLOC(sel_arr, ((1 + qual_count) * sel_entry_sz), \
  36964                    "Field group select codes");
  36965     if (NULL == sel_arr) {
  36966         sal_free(qual_conf_idx);
  36967         _bcm_field_selcode_qual_arr_free(unit, &f_qual_arr, qual_count);
  36968         return (BCM_E_MEMORY);
  36969     }
  36970 
  36971     /* Initialize first qualifier select codes to group select codes. */
  36972     candidate = sel_arr + (qual_count * parts_count);
  36973     sal_memcpy(candidate, fg->sel_codes, sel_entry_sz);
  36974 
  36975     /* Initialize first qualifier select codes to a group defaults */
  36976     sal_memcpy(sel_arr, candidate, sel_entry_sz);
  36977 
  36978     /* Main select codes selection loop over caller requested qualifier set. */
  36979     for (qual_idx = 0; qual_idx < qual_count;) {
  36980 
  36981         /* Get qualifier selcodes configuration index. */
  36982         conf_idx = qual_conf_idx[qual_idx];
  36983 
  36984         /*
  36985          * Sort qualifier configurations so minimum
  36986          * change configuration attempted first.
  36987          */
  36988         if (0 == conf_idx) {
  36989             rv = _field_qual_selectors_sort(unit, candidate,
  36990                     parts_count, f_qual_arr[qual_idx]);
  36991             if (BCM_FAILURE(rv)) {
  36992                 sal_free(sel_arr);
  36993                 sal_free(qual_conf_idx);
  36994                 _bcm_field_selcode_qual_arr_free(unit, &f_qual_arr, qual_count);
  36995                 return (rv);
  36996             }
  36997         }
  36998 
  36999         /*
  37000          * Set default return value, in case all configuration
  37001          * options were exhausted.
  37002          */
  37003         rv = BCM_E_RESOURCE;
  37004 
  37005         /* Loop over possible qualifier configurations. */
  37006         for (;conf_idx < f_qual_arr[qual_idx]->conf_sz; conf_idx++)  {
  37007 
  37008             /* Get qualifier configuration for the index. */
  37009             qual_config = f_qual_arr[qual_idx]->conf_arr + conf_idx;
  37010 #ifdef BCM_WARM_BOOT_SUPPORT
  37011          if (SOC_WARM_BOOT(unit) && (_BCM_FIELD_STAGE_EGRESS == stage_fc->stage_id)) {
  37012              if(soc_feature(unit, soc_feature_td3_style_fp)
  37013                 && (BCM_FIELD_WB_VERSION_1_25 == fc->wb_recovered_version)
  37014                 && (_FIELD_IS_CLASS_ID_B_SEL(qual_config->selector.sec_sel)
  37015                     && (9 != qual_config->selector.sec_sel_val)
  37016                     && (4 != qual_config->selector.sec_sel_val)
  37017                     && (2 != qual_config->selector.sec_sel_val))) {
  37018                 continue;
  37019             }
  37020             if (soc_feature(unit, soc_feature_td3_style_fp)
  37021                 && (BCM_FIELD_WB_VERSION_1_25 >= fc->wb_recovered_version)
  37022                 && (_bcmFieldSliceSelEgrClassIdBF5 == qual_config->selector.sec_sel)) {
  37023                 continue;
  37024             }
  37025          }
  37026 #endif
  37027             /* Skip conflicting configurations. */
  37028             if ((uint8) _FP_INVALID_INDEX ==
  37029                 qual_config->selector.update_count) {
  37030                continue;
  37031             }
  37032 
  37033             /*
  37034              *  Attempt to accommodate specific qualifier
  37035              *  configuration into candidate select codes.
  37036              */
  37037             rv = _field_qual_selectors_insert(unit, candidate,
  37038                                               parts_count,
  37039                                               &qual_config->selector);
  37040 
  37041             if (BCM_SUCCESS(rv) || (BCM_E_RESOURCE != rv)) {
  37042                 break;
  37043             }
  37044         }
  37045 
  37046         /*
  37047          * If code failed to insert qualifier configuration
  37048          * attempt a previous qualifier in the list using alternative
  37049          * configuration.
  37050          */
  37051         if (BCM_FAILURE(rv)) {
  37052             if ((qual_idx == 0) || (BCM_E_RESOURCE != rv)) {
  37053                 break;
  37054             }
  37055             /* Previous qualifier has to use next available configuration. */
  37056             while (qual_idx > 0) {
  37057                 /* This qualifier configuration will be re-selected. */
  37058                 qual_conf_idx[qual_idx] = 0;
  37059                 /* Back to the previous qualifier. */
  37060                 qual_idx--;
  37061                 /* Check select codes were modified by qualifier. */
  37062                 qual_config = f_qual_arr[qual_idx]->conf_arr +
  37063                               qual_conf_idx[qual_idx];
  37064                 /* If modified -> reverse changes and proceed to next config.*/
  37065                 if ((0 == qual_idx) ||
  37066                     (0 != qual_config->selector.update_count)) {
  37067                     /* Go to the next configuration */
  37068                     qual_conf_idx[qual_idx]++;
  37069                     /* Restore original select codes state. */
  37070                     sal_memcpy(candidate,
  37071                         sel_arr + (qual_idx * parts_count),
  37072                         sel_entry_sz);
  37073                     break;
  37074                 }
  37075             }
  37076         } else {
  37077             /* Preserve current qualifier configuration index. */
  37078             qual_conf_idx[qual_idx] = conf_idx;
  37079             /* Proceed to the next qualifier. */
  37080             qual_idx++;
  37081             /* Set selection base line for the next qualifier */
  37082             if (qual_idx < qual_count) {
  37083                 sal_memcpy(sel_arr + (qual_idx * parts_count),
  37084                            candidate, sel_entry_sz);
  37085             }
  37086         }
  37087     }
  37088     if (BCM_SUCCESS(rv)) {
  37089         /* Copy selected codes to the group configuration. */
  37090         sal_memcpy(fg->sel_codes, candidate, sel_entry_sz);
  37091         /* Copy qualifiers offset to group tcam parts. */
  37092         rv = _field_qual_offsets_copy(unit, fg, qual_count,
  37093                                       f_qual_arr, qual_conf_idx);
  37094     }
  37095     sal_free(sel_arr);
  37096     sal_free(qual_conf_idx);
  37097     _bcm_field_selcode_qual_arr_free(unit, &f_qual_arr, qual_count);
  37098     return (rv);
  37099 }
  37100 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  37101 /*
  37102  * Function:
  37103  *     _field_egress_key_attempt
  37104  * Purpose:
  37105  *     Verify if specific key can satisfy user requested qset.
  37106  *
  37107  * Parameters:
  37108  *     unit      - (IN) BCM unit number.
  37109  *     stage_fc  - (IN) Stage Field control structure.
  37110  *     qset_req  - (IN) Client qualifier set.
  37111  *     key_pri   - (IN) Primary key id.
  37112  *     key_sec   - (IN) Secondary key id.
  37113  *     fg        - (IN/OUT)Select code information filled into the group.
  37114  *
  37115  * Returns:
  37116  *     BCM_E_XXX
  37117  */
  37118 int
  37119 _bcm_field_egress_key_attempt(int unit, _field_stage_t *stage_fc,
  37120                               bcm_field_qset_t *qset_req,
  37121                               uint8 key_pri, uint8 key_sec,
  37122                               _field_group_t *fg)
  37123 {
  37124     /* Input parameters check. */
  37125     if ((NULL == fg) || (NULL == qset_req) || (NULL == stage_fc)) {
  37126         return (BCM_E_PARAM);
  37127     }
  37128     fg->sel_codes[0].fpf3= key_pri;
  37129     if (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) {
  37130         fg->sel_codes[1].fpf3= key_sec;
  37131     }
  37132     /* Verify that each requested qualifier present in the key. */
  37133     return _bcm_field_selcode_get(unit, stage_fc, qset_req, fg);
  37134 }
  37135 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  37136 
  37137 /*
  37138  * Function: _field_qualify_VlanFormat
  37139  *
  37140  * Purpose:
  37141  *     Add qualification data to an entry for Vlan Tag Format.
  37142  *
  37143  * Parameters:
  37144  *     unit     - (IN) BCM unit number.
  37145  *     entry    - (IN) Entry ID.
  37146  *     qual_id  - (IN) Qualifier id.
  37147  *     data     - (IN) Outer & Inner tag presence info.
  37148  *     mask     - (IN) Data mask.
  37149  * Returns:
  37150  *     BCM_E_XXX
  37151  */
  37152 int
  37153 _field_qualify_VlanFormat(int unit, bcm_field_entry_t entry,
  37154                           bcm_field_qualify_t qual_id,
  37155                           uint8 data, uint8 mask)
  37156 {
  37157     _field_entry_t      *f_ent;  /* Field entry structure.   */
  37158     int                 rv;      /* Operation return status. */
  37159     uint8 hw_data = data;
  37160     uint8 hw_mask = mask;
  37161 
  37162 #if defined(BCM_TOMAHAWK_SUPPORT)
  37163     if (soc_feature(unit, soc_feature_field_preselector_support) &&
  37164         (_BCM_FIELD_IS_PRESEL_ENTRY(entry) == TRUE)) {
  37165 #if defined(BCM_TRIDENT3_SUPPORT)
  37166         if(soc_feature(unit, soc_feature_td3_style_fp)) {
  37167            rv = _bcm_field_td3_qualify_VlanFormat(unit, qual_id,
  37168                                                   data, mask,
  37169                                                   &hw_data, &hw_mask);
  37170            BCM_IF_ERROR_RETURN(rv);
  37171         } else
  37172 #endif /* BCM_TRIDENT3_SUPPORT */
  37173         {
  37174            return BCM_E_UNAVAIL;
  37175         }
  37176     } else
  37177 #endif /* BCM_TOMAHAWK_SUPPORT */
  37178     {
  37179         rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent);
  37180         if (BCM_FAILURE(rv)) {
  37181            return (rv);
  37182         }
  37183 
  37184 #if defined (BCM_TOMAHAWK3_SUPPORT)
  37185         if (soc_feature(unit, soc_feature_th3_style_fp)) {
  37186             if (_BCM_FIELD_STAGE_INGRESS != f_ent->group->stage_id) {
  37187                 hw_data = (((data & 0x2) >> 1) | ((data & 0x1) << 1));
  37188                 hw_mask = (((mask & 0x2) >> 1) | ((mask & 0x1) << 1));
  37189             }
  37190         } else 
  37191 #endif
  37192         {
  37193 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  37194             if (soc_feature(unit, soc_feature_field_qual_vlanformat_reverse) ||
  37195                 soc_feature(unit, soc_feature_field_multi_stage)) {
  37196                 if ((_BCM_FIELD_STAGE_INGRESS != f_ent->group->stage_id) ||
  37197                     (SOC_IS_TRX(unit))) {
  37198                    hw_data = (((data & 0x2) >> 1) | ((data & 0x1) << 1));
  37199                    hw_mask = (((mask & 0x2) >> 1) | ((mask & 0x1) << 1));
  37200                 }
  37201             }
  37202 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  37203         }
  37204     }
  37205 
  37206     rv = _field_qualify32(unit, entry, qual_id, hw_data, hw_mask);
  37207     return (rv);
  37208 }
  37209 
  37210 /*
  37211  * Function: _field_qualify_VlanFormat_get
  37212  *
  37213  * Purpose:
  37214  *     Get qualification match criteria from an entry for Vlan Tag Format.
  37215  *
  37216  * Parameters:
  37217  *     unit     - (IN) BCM unit number.
  37218  *     entry    - (IN) Entry ID.
  37219  *     qual_id  - (IN) Qualifier id.
  37220  *     data     - (OUT) Outer & Inner tag presence info.
  37221  *     mask     - (OUT) Data mask.
  37222  * Returns:
  37223  *     BCM_E_XXX
  37224  */
  37225 int
  37226 _field_qualify_VlanFormat_get(int unit, bcm_field_entry_t entry,
  37227                           bcm_field_qualify_t qual_id,
  37228                           uint8 *data, uint8 *mask)
  37229 {
  37230     uint8            hw_data;   /* HW encoded data.         */
  37231     uint8            hw_mask;   /* HW encoded mask.         */
  37232     int              rv;        /* Operation return status. */
  37233 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  37234     _field_entry_t   *f_ent;    /* Field entry structure.   */
  37235 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  37236 
  37237     /* Read qualifier match value and mask. */
  37238     rv = _bcm_field_entry_qualifier_uint8_get(unit, entry, qual_id,
  37239                                           &hw_data, &hw_mask);
  37240     BCM_IF_ERROR_RETURN(rv);
  37241 
  37242 
  37243 #if defined(BCM_TOMAHAWK_SUPPORT)
  37244     if (soc_feature(unit, soc_feature_field_preselector_support) &&
  37245         (_BCM_FIELD_IS_PRESEL_ENTRY(entry) == TRUE)) {
  37246 #if defined(BCM_TRIDENT3_SUPPORT)
  37247         if(soc_feature(unit, soc_feature_td3_style_fp)) {
  37248            rv = _bcm_field_td3_qualify_VlanFormat_get(unit, qual_id,
  37249                                                       hw_data, hw_mask,
  37250                                                       data, mask);
  37251            BCM_IF_ERROR_RETURN(rv);
  37252         } else
  37253 #endif /* BCM_TRIDENT3_SUPPORT */
  37254         {
  37255            return BCM_E_UNAVAIL;
  37256         }
  37257     } else
  37258 #endif /* BCM_TOMAHAWK_SUPPORT */
  37259     {
  37260 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  37261         rv = _field_entry_get(unit, entry, _FP_ENTRY_PRIMARY, &f_ent);
  37262         BCM_IF_ERROR_RETURN(rv);
  37263 
  37264 #if defined (BCM_TOMAHAWK3_SUPPORT)
  37265         if (soc_feature(unit, soc_feature_th3_style_fp)) {
  37266            if (_BCM_FIELD_STAGE_INGRESS != f_ent->group->stage_id) {
  37267                 *data = (((hw_data & 0x2) >> 1) | ((hw_data & 0x1) << 1));
  37268                 *mask = (((hw_mask & 0x2) >> 1) | ((hw_mask & 0x1) << 1));
  37269            } else {
  37270                *data = hw_data;
  37271                *mask = hw_mask;
  37272            }
  37273         } else 
  37274 #endif
  37275         {
  37276             if (((soc_feature(unit, soc_feature_field_qual_vlanformat_reverse)) ||
  37277                 (soc_feature(unit, soc_feature_field_multi_stage))) &&
  37278                  ((_BCM_FIELD_STAGE_INGRESS != f_ent->group->stage_id) ||
  37279                  (SOC_IS_TRX(unit)))) {
  37280                     *data = (((hw_data & 0x2) >> 1) | ((hw_data & 0x1) << 1));
  37281                     *mask = (((hw_mask & 0x2) >> 1) | ((hw_mask & 0x1) << 1));
  37282             } else
  37283 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  37284             {
  37285                *data = hw_data;
  37286                *mask = hw_mask;
  37287             }
  37288 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  37289         }
  37290 #endif
  37291 
  37292     }
  37293 
  37294     return (rv);
  37295 }
  37296 
  37297 /*
  37298  * Function:
  37299  *     _field_range_dump
  37300  *
  37301  * Purpose:
  37302  *     Show contents of a range checker
  37303  *
  37304  * Parameters:
  37305  *     fr - range checker structure pointer
  37306  *
  37307  * Returns:
  37308  *     Nothing.
  37309  */
  37310 void
  37311 _field_range_dump(const char *pfx, _field_range_t *fr)
  37312 {
  37313     LOG_CLI((BSL_META("%s: Range ID=%d, flag=%#x, min=%d, max=%d, hw_index=%d(%#x), "),
  37314              pfx, fr->rid, fr->flags, fr->min, fr->max, fr->hw_index,
  37315              fr->hw_index));
  37316     LOG_CLI((BSL_META("style=BCM56504\n")));
  37317 }
  37318 
  37319 /*
  37320  * Function:
  37321  *     _field_entry_phys_dump
  37322  *
  37323  * Purpose:
  37324  *     Show contents of a physical entry structure
  37325  *
  37326  * Parameters:
  37327  *     unit       - BCM device number
  37328  *     f_ent      - Physical entry to dump
  37329  *     entry_part - Field entry part.
  37330  * Returns:
  37331  *     Nothing.
  37332  */
  37333 void
  37334 _field_entry_phys_dump(int unit, _field_entry_t *f_ent, uint8 entry_part)
  37335 {
  37336     _bcm_field_group_qual_t   *q_arr;  /* Qualifiers array.    */
  37337     int                       idx;
  37338     int                       idx_max;
  37339     int                       qual_idx;
  37340     int                       free_tcam = FALSE;
  37341     uint32                    width;
  37342     _field_group_t            *fg;
  37343     _bcm_field_qual_data_t    q_data;
  37344     _bcm_field_qual_data_t    q_mask;
  37345     _bcm_field_qual_offset_t  *q_offset;
  37346     char                      *ip_type_str[] = BCM_FIELD_IPTYPE_STRINGS;
  37347     int                       rv;
  37348 #if defined(BCM_TRX_SUPPORT)
  37349     int                       range_check_valid = 0;
  37350 #endif /* !BCM_TRX_SUPPORT */
  37351 
  37352     LOG_CLI((BSL_META_U(unit,
  37353                         "         slice=%d, slice_idx=%#x, part =%d prio=%#x, flags=%#x, "),
  37354              f_ent->fs->slice_number, f_ent->slice_idx, entry_part,
  37355              f_ent->prio, f_ent->flags));
  37356     if (!(f_ent->flags & _FP_ENTRY_INSTALLED)) {
  37357         LOG_CLI((BSL_META_U(unit,
  37358                             "Not installed\n")));
  37359     } else {
  37360         LOG_CLI((BSL_META_U(unit,
  37361                             "Installed, ")));
  37362 
  37363         if (!(f_ent->flags & _FP_ENTRY_ENABLED)) {
  37364             LOG_CLI((BSL_META_U(unit,
  37365                                 "Disabled")));
  37366         }
  37367         else {
  37368             LOG_CLI((BSL_META_U(unit,
  37369                                 "Enabled")));
  37370         }
  37371         if (f_ent->flags & _FP_ENTRY_DIRTY) {
  37372             LOG_CLI((BSL_META_U(unit,
  37373                                 ", Dirty")));
  37374         }
  37375         if (f_ent->flags & _FP_ENTRY_OAM_STAT_VALID) {
  37376             LOG_CLI((BSL_META_U(unit,
  37377                                 ", OamStatValid")));
  37378         }
  37379         else {
  37380              LOG_CLI((BSL_META_U(unit,
  37381                                  "\n")));
  37382         }
  37383     }
  37384 
  37385     if ((NULL == f_ent->tcam.key)) {
  37386         free_tcam = TRUE;
  37387     }
  37388 
  37389     rv = _bcm_field_qual_tcam_key_mask_get(unit, f_ent);
  37390     if (BCM_FAILURE(rv)) {
  37391         LOG_CLI((BSL_META_U(unit,
  37392                             "\nUnit (%d) Entry (%d) tcam key read failure.\n"),
  37393                  unit, f_ent->eid));
  37394         return;
  37395     }
  37396 
  37397     LOG_CLI((BSL_META_U(unit,
  37398                         "              tcam: color_indep=%d, "),
  37399              ((f_ent->flags & _FP_ENTRY_COLOR_INDEPENDENT) ? 1 : 0)));
  37400 
  37401 
  37402 
  37403     fg = f_ent->group;
  37404     idx = _FP_ENTRY_TYPE_DEFAULT;
  37405 
  37406 #if defined(BCM_TRIDENT2_SUPPORT)
  37407     if (SOC_IS_TD2_TT2(unit) ||
  37408         soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  37409         if (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) {
  37410             if (f_ent->efp_key_match_type) {
  37411                 idx = _FP_ENTRY_TYPE_1;
  37412             } else {
  37413                 idx = _FP_ENTRY_TYPE_0;
  37414             }
  37415         }
  37416     }
  37417 #endif
  37418 
  37419     q_arr = &(fg->qual_arr[idx][entry_part]);
  37420     for (qual_idx = 0; qual_idx < q_arr->size; qual_idx++) {
  37421         idx_max = -1;
  37422         q_offset = q_arr->offset_arr + qual_idx;
  37423 
  37424         /*
  37425          * There is no value associated with zero width qualifiers
  37426          * (Stage, Ip4 etc) just print the name.
  37427          */
  37428         _BCM_FIELD_QUAL_MULTI_OFFSET_WIDTH(q_offset, width);
  37429         if (0 == width) {
  37430             switch (q_arr->qid_arr[qual_idx]) {
  37431                 case bcmFieldQualifyInPorts:
  37432                 case bcmFieldQualifyInPort:
  37433 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_TRX_SUPPORT)
  37434                     if (BCM_PBMP_NOT_NULL(f_ent->pbmp.mask)) {
  37435                         char pfmt[SOC_PBMP_FMT_LEN];
  37436                         bcm_pbmp_t lb_pbm;
  37437                         bcm_pbmp_t mask_pbm;
  37438                         /* Remove loopback port from ipbm mask */
  37439                         BCM_PBMP_CLEAR(lb_pbm);
  37440                         BCM_PBMP_ASSIGN(mask_pbm, f_ent->pbmp.mask);
  37441                         BCM_PBMP_OR(lb_pbm, PBMP_LB(unit));
  37442                         if (BCM_PBMP_NOT_NULL(lb_pbm)) {
  37443                             BCM_PBMP_REMOVE(mask_pbm, PBMP_LB(unit));
  37444                         }
  37445 #if defined(BCM_MONTEREY_SUPPORT) && defined(INCLUDE_XFLOW_MACSEC)
  37446                         /* Remove MACSEC Port from IPBM mask */
  37447                         if (soc_feature(unit, soc_feature_xflow_macsec)) {
  37448                             bcm_pbmp_t       macsec_pbm;
  37449                             BCM_PBMP_CLEAR(macsec_pbm);
  37450                             BCM_PBMP_OR(macsec_pbm, PBMP_MACSEC_ALL(unit));
  37451                             if (BCM_PBMP_NOT_NULL(macsec_pbm)) {
  37452                                 BCM_PBMP_REMOVE(mask_pbm, PBMP_MACSEC_ALL(unit));
  37453                             }
  37454                         }
  37455 #endif
  37456 
  37457                         LOG_CLI((BSL_META_U(unit,
  37458                                             "\n %s "),
  37459                                  _field_qual_name(q_arr->qid_arr[qual_idx])));
  37460                         LOG_CLI((BSL_META_U(unit,
  37461                                             "\n    DATA=")));
  37462                         LOG_CLI((BSL_META_U(unit,
  37463                                             "%s"),
  37464                                  SOC_PBMP_FMT(f_ent->pbmp.data, pfmt)));
  37465                         LOG_CLI((BSL_META_U(unit,
  37466                                             "\n    MASK=")));
  37467                         LOG_CLI((BSL_META_U(unit,
  37468                                             "%s"),
  37469                                  SOC_PBMP_FMT(mask_pbm, pfmt)));
  37470                     }
  37471 #endif
  37472                     break;
  37473                 case bcmFieldQualifyHiGig:
  37474                     if (f_ent->tcam.higig_mask) {
  37475                         LOG_CLI((BSL_META_U(unit,
  37476                                             "\n %s "),
  37477                                  _field_qual_name(q_arr->qid_arr[qual_idx])));
  37478                         LOG_CLI((BSL_META_U(unit,
  37479                                             "\n    DATA= %d"),
  37480                                  f_ent->tcam.higig));
  37481                         LOG_CLI((BSL_META_U(unit,
  37482                                             "\n    MASK= %d"),
  37483                                  f_ent->tcam.higig_mask));
  37484                     }
  37485                     break;
  37486                 case bcmFieldQualifyIpType:
  37487                     if ((bcmFieldIpTypeAny != f_ent->tcam.ip_type) &&
  37488                             (bcmFieldIpTypeCount > f_ent->tcam.ip_type)) {
  37489                         LOG_CLI((BSL_META_U(unit,
  37490                                             "\n %s "),
  37491                                  _field_qual_name(q_arr->qid_arr[qual_idx])));
  37492                         LOG_CLI((BSL_META_U(unit,
  37493                                             "\n    DATA= %s"),
  37494                                  ip_type_str[f_ent->tcam.ip_type]));
  37495                     }
  37496                     break;
  37497                 default:
  37498                     LOG_CLI((BSL_META_U(unit,
  37499                                         "\n %s "),
  37500                              _field_qual_name(q_arr->qid_arr[qual_idx])));
  37501             }
  37502             continue;
  37503         } else {
  37504 #if defined(BCM_FIREBOLT2_SUPPORT)
  37505             /*
  37506              * Although FB2 has drop qualifier -
  37507              * Drop bit is always present in the tcam
  37508              * ancestor of the fixed key.
  37509              */
  37510             if ((bcmFieldQualifyDrop == q_arr->qid_arr[qual_idx]) &&
  37511                 (SOC_IS_FIREBOLT2(unit))) {
  37512                 if (f_ent->tcam.drop_mask) {
  37513                     LOG_CLI((BSL_META_U(unit,
  37514                                         "\n %s "),
  37515                              _field_qual_name(q_arr->qid_arr[qual_idx])));
  37516                     LOG_CLI((BSL_META_U(unit,
  37517                                         "\n    DATA= %d"),
  37518                              f_ent->tcam.drop));
  37519                     LOG_CLI((BSL_META_U(unit,
  37520                                         "\n    MASK= %d"),
  37521                              f_ent->tcam.drop_mask));
  37522                 }
  37523                 continue;
  37524             }
  37525 #endif /* BCM_FIREBOLT2_SUPPORT */
  37526         }
  37527 
  37528         _FP_QUAL_DATA_CLEAR(q_data);
  37529         _FP_QUAL_DATA_CLEAR(q_mask);
  37530         /* Read qualifier match value and mask. */
  37531         rv = _bcm_field_qual_value_get(unit, q_offset, f_ent, q_data, q_mask);
  37532         if (BCM_FAILURE(rv)) {
  37533             return;
  37534         }
  37535 
  37536         /* Check if qualifier was installed. */
  37537         for (idx = 7; idx >= 0; idx--) {
  37538             if (q_mask[idx] != 0)  {
  37539                 idx_max = idx;
  37540                 break;
  37541             }
  37542         }
  37543 
  37544 #if defined(BCM_TRX_SUPPORT)
  37545         if ((bcmFieldQualifyRangeCheck == q_arr->qid_arr[qual_idx]) &&
  37546             (BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInterfaceClassPort) ||
  37547              BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInterfaceClassL3) ||
  37548              BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInterfaceClassVPort) ||
  37549              BCM_FIELD_QSET_TEST(fg->qset, bcmFieldQualifyInterfaceClassL2))) {
  37550             for (idx = idx_max; idx >= 0; idx--) {
  37551                 if (0 != (q_mask[idx] & 0xffffff)) {
  37552                     range_check_valid = 1;
  37553                 }
  37554             }
  37555             if (0 == range_check_valid) {
  37556                 continue;
  37557             }
  37558         }
  37559 #endif /* !BCM_TRX_SUPPORT */
  37560 
  37561         if (idx_max >= 0) {
  37562             int i;
  37563             LOG_CLI((BSL_META_U(unit,
  37564                                 "\n %s "),
  37565                      _field_qual_name(q_arr->qid_arr[qual_idx])));
  37566             for (i = 0; i < q_offset->num_offsets; i++) {
  37567                if (0 != q_offset->width[i]) {
  37568                   LOG_CLI((BSL_META_U(unit,
  37569                                 "\n    Offset%d: %d Width%d: %d "),
  37570                                 i, q_offset->offset[i], i, q_offset->width[i]));
  37571                }
  37572             }
  37573 
  37574             LOG_CLI((BSL_META_U(unit,
  37575                                 "\n    DATA=0x")));
  37576             if (SOC_IS_TRX(unit)
  37577                 && (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id)
  37578                 && (bcmFieldQualifyInnerVlan == q_arr->qid_arr[qual_idx])) {
  37579                 /* EFP InnerVlan hardware format is different from IFP.
  37580                  */
  37581                 int32 data = 0;
  37582                 for (idx = 0; idx <= idx_max; idx++) {
  37583                     data = ((q_data[idx] & 0xfff0) >> 4) |
  37584                             ((q_data[idx] & 0xf) << 12);
  37585                     LOG_CLI((BSL_META_U(unit,
  37586                                         "%08x "), data));
  37587                 }
  37588             } else {
  37589                 uint32 data = 0;
  37590                 uint32 mask = 0;
  37591                 for (idx = idx_max; idx >= 0; idx--) {
  37592                     data = q_data[idx];
  37593                     mask = q_mask[idx];
  37594 
  37595                     if (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id) {
  37596                         /* Check if HW packet_res must be remmaped for API use */
  37597                         if (bcmFieldQualifyPacketRes == q_arr->qid_arr[qual_idx]) {
  37598                             int (*func)(int, bcm_field_entry_t, uint32 *, uint32 *)
  37599                                = _field_qualify_PacketRes_get;
  37600 
  37601 #if defined(BCM_TRIDENT2_SUPPORT)
  37602                             if (SOC_IS_TD2_TT2(unit)) {
  37603                                 func = _bcm_field_td2_qualify_PacketRes_get;
  37604                             } else
  37605 #endif /* BCM_TRIDENT2_SUPPORT */
  37606 #if defined(BCM_TRIUMPH3_SUPPORT)
  37607                             if (SOC_IS_TRIUMPH3(unit)) {
  37608                                 func = _bcm_field_tr3_qualify_PacketRes_get;
  37609                             } else
  37610 #endif /* BCM_TRIUMPH3_SUPPORT */
  37611 #if defined(BCM_KATANA_SUPPORT)
  37612                             if (SOC_IS_KATANA(unit)) {
  37613                                 func = _bcm_field_kt_qualify_PacketRes_get;
  37614                             } else
  37615 #endif /* BCM_KATANA_SUPPORT */
  37616                             {
  37617 #if defined (BCM_KATANA2_SUPPORT)
  37618                                 if (SOC_IS_KATANA2(unit)) {
  37619                                    func = _bcm_field_kt2_qualify_PacketRes_get;
  37620                                 }
  37621 #endif /* BCM_KATANA2_SUPPORT */
  37622                             }
  37623 
  37624                             (*func)(unit, f_ent->eid, &data, &mask);
  37625                             q_mask[idx] = mask;
  37626                         }
  37627                     }
  37628                     LOG_CLI((BSL_META_U(unit,
  37629                                         "%08x "), data));
  37630                 }
  37631             }
  37632 
  37633             LOG_CLI((BSL_META_U(unit,
  37634                                 "\n    MASK=0x")));
  37635             if (SOC_IS_TRX(unit)
  37636                 && (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id)
  37637                 && (bcmFieldQualifyInnerVlan == q_arr->qid_arr[qual_idx])) {
  37638                 /* EFP InnerVlan hardware format is different from IFP.
  37639                  */
  37640                 int32 mask = 0;
  37641                 for (idx = 0; idx <= idx_max; idx++) {
  37642                     mask = ((q_mask[idx] & 0xfff0) >> 4) |
  37643                             ((q_mask[idx] & 0xf) << 12);
  37644                     LOG_CLI((BSL_META_U(unit,
  37645                                         "%08x "), mask));
  37646                 }
  37647             } else {
  37648                 for (idx = idx_max; idx >= 0; idx--) {
  37649                     LOG_CLI((BSL_META_U(unit,
  37650                                         "%08x "), q_mask[idx]));
  37651                 }
  37652             }
  37653         }
  37654     }
  37655 
  37656     if (free_tcam) {
  37657         if (NULL != f_ent->tcam.key) {
  37658             sal_free(f_ent->tcam.key);
  37659             sal_free(f_ent->tcam.mask);
  37660         }
  37661         if (f_ent->flags & _FP_ENTRY_USES_IPBM_OVERLAY) {
  37662             if (NULL != f_ent->extra_tcam.key) {
  37663                 sal_free(f_ent->extra_tcam.key);
  37664                 sal_free(f_ent->extra_tcam.mask);
  37665             }
  37666         }
  37667         f_ent->tcam.key = f_ent->tcam.mask =
  37668             f_ent->extra_tcam.key = f_ent->extra_tcam.mask = NULL;
  37669 #if defined(BCM_TRIDENT2_SUPPORT)
  37670         if (SOC_IS_TD2_TT2(unit) &&
  37671             (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id)) {
  37672 
  37673             if (NULL != f_ent->key_match_tcam.key) {
  37674                 sal_free(f_ent->key_match_tcam.key);
  37675                 sal_free(f_ent->key_match_tcam.mask);
  37676             }
  37677             f_ent->key_match_tcam.key = f_ent->key_match_tcam.mask = NULL;
  37678         }
  37679 #endif
  37680         free_tcam = FALSE;
  37681     }
  37682 
  37683     LOG_CLI((BSL_META_U(unit,
  37684                         "\n")));
  37685 }
  37686 
  37687 
  37688 /*
  37689  * Function:
  37690  *     _field_selcode_dump
  37691  * Purpose:
  37692  *     Output a set of field selects code.
  37693  */
  37694 void
  37695 _field_selcode_dump(int unit, char *prefix, _field_sel_t *sel_codes,
  37696                     char *suffix, _field_stage_id_t stage_id)
  37697 {
  37698 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  37699     char                      *efp_key_type_str[] = _BCM_EFP_FIELD_KEY_STRINGS;
  37700 #endif
  37701     if (NULL == sel_codes) {
  37702         return;
  37703     }
  37704 
  37705     LOG_CLI((BSL_META_U(unit,
  37706                         "%s{"), (prefix == NULL) ? "" : prefix));
  37707     if (_FP_SELCODE_DONT_CARE != sel_codes->fpf1) {
  37708         LOG_CLI((BSL_META_U(unit,
  37709                             "\n         FPF1=%d"), sel_codes->fpf1));
  37710     }
  37711     if (_FP_SELCODE_DONT_CARE != sel_codes->fpf2) {
  37712         LOG_CLI((BSL_META_U(unit,
  37713                             "\n         FPF2=%d"), sel_codes->fpf2));
  37714     }
  37715     if (_FP_SELCODE_DONT_CARE != sel_codes->fpf3) {
  37716 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  37717         if (_BCM_FIELD_STAGE_EGRESS == stage_id) {
  37718             LOG_CLI((BSL_META_U(unit,
  37719                             "\n         FPF3=%s"), efp_key_type_str[sel_codes->fpf3]));
  37720         } else
  37721 #endif
  37722         {
  37723             LOG_CLI((BSL_META_U(unit,
  37724                             "\n         FPF3=%d"), sel_codes->fpf3));
  37725         }
  37726     }
  37727     if (_FP_SELCODE_DONT_CARE != sel_codes->fpf4) {
  37728         LOG_CLI((BSL_META_U(unit,
  37729                             "\n         FPF4=%d"), sel_codes->fpf4));
  37730     }
  37731     if (_FP_SELCODE_DONT_CARE != sel_codes->src_class_sel) {
  37732         LOG_CLI((BSL_META_U(unit,
  37733                             "\n         SourceClassSelect=%d"),
  37734                  sel_codes->src_class_sel));
  37735     }
  37736     if (_FP_SELCODE_DONT_CARE != sel_codes->dst_class_sel) {
  37737         LOG_CLI((BSL_META_U(unit,
  37738                             "\n         DestinationClassSelect=%d"),
  37739                  sel_codes->dst_class_sel));
  37740     }
  37741     if (_FP_SELCODE_DONT_CARE != sel_codes->intf_class_sel) {
  37742         LOG_CLI((BSL_META_U(unit,
  37743                             "\n         InterfaceClassSelect=%d"),
  37744                  sel_codes->intf_class_sel));
  37745     }
  37746     if (_FP_SELCODE_DONT_CARE != sel_codes->loopback_type_sel) {
  37747         LOG_CLI((BSL_META_U(unit,
  37748                             "\n         LoopbackTypeSelect=%d"),
  37749                  sel_codes->loopback_type_sel));
  37750     }
  37751     if (_FP_SELCODE_DONT_CARE != sel_codes->egr_dest_port_f1_sel) {
  37752         LOG_CLI((BSL_META_U(unit,
  37753                             "\n         EgrDstPortF1Select=%d"),
  37754                  sel_codes->egr_dest_port_f1_sel));
  37755     }
  37756     if (_FP_SELCODE_DONT_CARE != sel_codes->egr_dest_port_f5_sel) {
  37757         LOG_CLI((BSL_META_U(unit,
  37758                             "\n         EgrDstPortF5Select=%d"),
  37759                  sel_codes->egr_dest_port_f5_sel));
  37760     }
  37761     if (_FP_SELCODE_DONT_CARE != sel_codes->ingress_entity_sel) {
  37762         LOG_CLI((BSL_META_U(unit,
  37763                             "\n         IngressEntitySelect=%d"),
  37764                  sel_codes->ingress_entity_sel));
  37765     }
  37766     if (_FP_SELCODE_DONT_CARE != sel_codes->src_entity_sel) {
  37767         LOG_CLI((BSL_META_U(unit,
  37768                             "\n         SrcEntitySelect=%d"),
  37769                  sel_codes->src_entity_sel));    }
  37770 
  37771     if (_FP_SELCODE_DONT_CARE != sel_codes->dst_fwd_entity_sel) {
  37772         LOG_CLI((BSL_META_U(unit,
  37773                             "\n         DestinationEntitySelect=%d"),
  37774                  sel_codes->dst_fwd_entity_sel));
  37775     }
  37776     if (_FP_SELCODE_DONT_CARE != sel_codes->fwd_field_sel) {
  37777         LOG_CLI((BSL_META_U(unit,
  37778                             "\n         ForwardingFieldSelect=%d"),
  37779                  sel_codes->fwd_field_sel));
  37780     }
  37781     if (_FP_SELCODE_DONT_CARE != sel_codes->ttl_class_sel) {
  37782         LOG_CLI((BSL_META_U(unit,
  37783                             "\n         TtlClassSelect=%d"),
  37784                  sel_codes->ttl_class_sel));
  37785     }
  37786     if (_FP_SELCODE_DONT_CARE != sel_codes->tos_class_sel) {
  37787         LOG_CLI((BSL_META_U(unit,
  37788                             "\n         TosClassSelect=%d"),
  37789                  sel_codes->tos_class_sel));
  37790     }
  37791     if (_FP_SELCODE_DONT_CARE != sel_codes->tcp_class_sel) {
  37792         LOG_CLI((BSL_META_U(unit,
  37793                             "\n         TcpClassSelect=%d"),
  37794                  sel_codes->tcp_class_sel));
  37795     }
  37796     if (_FP_SELCODE_DONT_CARE != sel_codes->ip_header_sel) {
  37797         LOG_CLI((BSL_META_U(unit,
  37798                             "\n         IpHeaderSelect=%s"),
  37799                  (sel_codes->ip_header_sel) ? "Inner" : "Outer"));
  37800     }
  37801     if (_FP_SELCODE_DONT_CARE != sel_codes->inner_vlan_overlay) {
  37802         LOG_CLI((BSL_META_U(unit,
  37803                             "\n         InnerVlanOverlaySelect=%d"),
  37804                  sel_codes->inner_vlan_overlay));
  37805     }
  37806     if (_FP_SELCODE_DONT_CARE != sel_codes->aux_tag_1_sel) {
  37807         LOG_CLI((BSL_META_U(unit,
  37808                             "\n         AuxTag1Select=%d"),
  37809                  sel_codes->aux_tag_1_sel));
  37810     }
  37811     if (_FP_SELCODE_DONT_CARE != sel_codes->aux_tag_2_sel) {
  37812         LOG_CLI((BSL_META_U(unit,
  37813                             "\n         AuxTag2Select=%d"),
  37814                  sel_codes->aux_tag_2_sel));
  37815     }
  37816     if (_FP_SELCODE_DONT_CARE != sel_codes->oam_overlay_sel) {
  37817         LOG_CLI((BSL_META_U(unit,
  37818 		                     "\n         OamOverlaySelect=%d"),
  37819                    sel_codes->oam_overlay_sel));
  37820     }
  37821     if (_FP_SELCODE_DONT_CARE != sel_codes->intraslice) {
  37822         if (_FP_SELCODE_DONT_USE == sel_codes->intraslice) {
  37823             LOG_CLI((BSL_META_U(unit,
  37824                                 "\n         Intraslice=%s\n"),
  37825                      "Primary slice."));
  37826         } else {
  37827             LOG_CLI((BSL_META_U(unit,
  37828                                 "\n         Intraslice=%d\n"),
  37829                      sel_codes->intraslice));
  37830         }
  37831     }
  37832     return;
  37833 }
  37834 
  37835 
  37836 /*
  37837  * Function:
  37838  *     _field_slice_dump
  37839  * Purpose:
  37840  *     Output a slice worth of data, including any entries in the slice.
  37841  */
  37842 void
  37843 _field_slice_dump(int unit, char *prefix, _field_group_t *fg,
  37844                   _field_slice_t *fs, char *suffix)
  37845 {
  37846 #if defined(BCM_TOMAHAWK_SUPPORT)
  37847     if (soc_feature(unit, soc_feature_field_multi_pipe_support)
  37848         && (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id)) {
  37849         _field_stage_t *stage_fc;     /* Stage field control structure.*/
  37850         int slice = 0;                /* Slice Count Iterator. */
  37851         _field_slice_t *fslice;       /*slice structure */
  37852         int free_entries_count = 0;   /*free entry count */
  37853         int total_entries_count = 0;  /* total entry count */
  37854         int rv;
  37855          /* Get field group stage control structure. */
  37856         rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc);
  37857         if (BCM_FAILURE(rv)) {
  37858             return;
  37859         }
  37860          /* Retreive Slice Instance. */
  37861         fslice = stage_fc->slices[fg->instance];
  37862         /* Calculate free entry count. */
  37863         for (slice = 0; slice < stage_fc->tcam_slices; slice++) {
  37864             free_entries_count += fslice[slice].free_count;
  37865             total_entries_count += fslice[slice].entry_count;
  37866         }
  37867 
  37868         LOG_CLI((BSL_META_U(unit,
  37869                         "%s{"), (prefix == NULL) ? "" : prefix));
  37870         LOG_CLI((BSL_META_U(unit,
  37871                         "slice_number=%d, "), fs->slice_number));
  37872         LOG_CLI((BSL_META_U(unit,
  37873                         "Entry count=%d(%#x), "),
  37874                     total_entries_count, total_entries_count));
  37875         LOG_CLI((BSL_META_U(unit,
  37876                         "Entry free=%d(%#x)"),
  37877                     free_entries_count, free_entries_count));
  37878         LOG_CLI((BSL_META_U(unit,
  37879                         "},%s"), (suffix == NULL) ? "" : suffix));
  37880     } else
  37881 #endif
  37882 {
  37883     while (fs != NULL) {
  37884         LOG_CLI((BSL_META_U(unit,
  37885                         "%s{"), (prefix == NULL) ? "" : prefix));
  37886         LOG_CLI((BSL_META_U(unit,
  37887                         "slice_number=%d, "), fs->slice_number));
  37888         LOG_CLI((BSL_META_U(unit,
  37889                         "Entry count=%d(%#x), "),
  37890                     fs->entry_count, fs->entry_count));
  37891         LOG_CLI((BSL_META_U(unit,
  37892                         "Entry free=%d(%#x)"),
  37893                     fs->free_count, fs->free_count));
  37894         LOG_CLI((BSL_META_U(unit,
  37895                         "},%s"), (suffix == NULL) ? "" : suffix));
  37896         fs = fs->next;
  37897     }
  37898 }
  37899 }
  37900 
  37901 /*
  37902  * Function:
  37903  *     _field_qual_list_dump
  37904  * Purpose:
  37905  *     Output qualiers set in 'qset'.
  37906  */
  37907 void
  37908 _field_qual_list_dump(char *prefix, _field_group_t *fg, uint8 entry_part, char *suffix)
  37909 {
  37910 
  37911     _bcm_field_group_qual_t *q_arr;   /* Qualifiers array.        */
  37912     int first_print = 1;
  37913     int idx;
  37914 
  37915     LOG_CLI((BSL_META("%s{"), (prefix == NULL) ? "" : prefix));
  37916     q_arr = &(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][entry_part]);
  37917     /* Output the qualifier info list*/
  37918     for (idx = 0; idx < q_arr->size; idx++) {
  37919         LOG_CLI((BSL_META("%s%s"),
  37920 (first_print ? "" : "->"),
  37921                  _field_qual_name(q_arr->qid_arr[idx])));
  37922         first_print = 0;
  37923     }
  37924     LOG_CLI((BSL_META("}%s"), (suffix == NULL) ? "" : suffix));
  37925 }
  37926 
  37927 /*
  37928  * Function:
  37929  *     _field_qset_dump
  37930  * Purpose:
  37931  *     Output qualiers set in 'qset'.
  37932  */
  37933 void
  37934 _field_qset_dump(char *prefix, bcm_field_qset_t qset, char *suffix)
  37935 {
  37936     int                 qual;
  37937     int                 idx;
  37938     int first_qual = 1, first_udf_id = 1;
  37939 
  37940     if (prefix == NULL) {
  37941         prefix = "";
  37942     }
  37943     if (suffix == NULL) {
  37944         suffix = "";
  37945     }
  37946 
  37947     LOG_CLI((BSL_META("%s{"), prefix));
  37948     for (qual = 0; qual < _bcmFieldQualifyCount; qual++) {
  37949         if (BCM_FIELD_QSET_TEST(qset, qual)) {
  37950             LOG_CLI((BSL_META("%s%s"),
  37951 (first_qual ? "" : ", "), _field_qual_name(qual)));
  37952             first_qual = 0;
  37953         }
  37954     }
  37955 
  37956     for (idx = 0; idx < BCM_FIELD_USER_NUM_UDFS; idx++) {
  37957         if (!SHR_BITGET(qset.udf_map, idx)) {
  37958             continue;
  37959         }
  37960         LOG_CLI((BSL_META("%s%d"),
  37961 (first_udf_id ? " : udf_id={" : ", "), idx));
  37962         first_udf_id = 0;
  37963     }
  37964     if (first_udf_id == 0) {
  37965         LOG_CLI((BSL_META("}")));
  37966     }
  37967 
  37968     LOG_CLI((BSL_META("}%s"), suffix));
  37969 }
  37970 
  37971 /*
  37972  * Function:
  37973  *     _field_qset_debug
  37974  * Purpose:
  37975  *     Output qualier set in 'qset' for debug mode only.
  37976  */
  37977 void
  37978 _field_qset_debug(bcm_field_qset_t qset)
  37979 {
  37980     int qual;
  37981     int first_qual = 1;
  37982 
  37983     LOG_VERBOSE(BSL_LS_BCM_FP,
  37984                 (BSL_META("{")));
  37985     for (qual = 0; qual < _bcmFieldQualifyCount; qual++) {
  37986         if (BCM_FIELD_QSET_TEST(qset, qual)) {
  37987             LOG_VERBOSE(BSL_LS_BCM_FP,
  37988                         (BSL_META("%s%s"),
  37989                          (first_qual ? "" : "), "),
  37990                          _field_qual_name(qual)));
  37991             first_qual = 0;
  37992         }
  37993     }
  37994     LOG_VERBOSE(BSL_LS_BCM_FP,
  37995                 (BSL_META("}")));
  37996 }
  37997 
  37998 /*
  37999  * Function:
  38000  *     _field_aset_dump
  38001  * Purpose:
  38002  *     Output qualiers set in 'aset'.
  38003  */
  38004 #if defined(BCM_TOMAHAWK_SUPPORT)
  38005 void
  38006 _field_aset_dump(char *prefix, _bcm_field_aset_t aset, char *suffix)
  38007 #else
  38008 void
  38009 _field_aset_dump(char *prefix, bcm_field_aset_t aset, char *suffix)
  38010 #endif
  38011 {
  38012     int action;
  38013     int first_action = 1;
  38014 
  38015     if (prefix == NULL) {
  38016         prefix = "";
  38017     }
  38018     if (suffix == NULL) {
  38019         suffix = "";
  38020     }
  38021 
  38022     LOG_CLI((BSL_META("%s{"), prefix));
  38023     for (action = 0; action < bcmFieldActionCount; action++) {
  38024         if (BCM_FIELD_ASET_TEST(aset, action)) {
  38025             LOG_CLI((BSL_META("%s%s"),
  38026 (first_action ? "" : ", "), _field_action_name(action)));
  38027             first_action = 0;
  38028         }
  38029     }
  38030 
  38031     LOG_CLI((BSL_META("}%s"), suffix));
  38032 }
  38033 
  38034 
  38035 /*
  38036  * Function:
  38037  *     _field_counter_dump
  38038  * Purpose:
  38039  *     Output fields in a _field_counter_s struct.
  38040  */
  38041 int
  38042 _field_stat_dump(int unit, const _field_entry_t *f_ent)
  38043 {
  38044     _field_stat_t        *f_st;
  38045     int                  idx;
  38046     int                  rv = BCM_E_NONE;
  38047     char                 *sname[] = BCM_FIELD_STAT;
  38048 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT)
  38049     char                 *aname[] = BCM_FIELD_STAT_ACTION;
  38050 #endif
  38051 
  38052     /* Input parameters check. */
  38053     if (f_ent == NULL) {
  38054         return (BCM_E_PARAM);
  38055     }
  38056 
  38057     if (f_ent->statistic.flags  & _FP_ENTRY_STAT_VALID) {
  38058         rv = _bcm_field_stat_get (unit, f_ent->statistic.sid, &f_st);
  38059         if (BCM_FAILURE(rv)) {
  38060             return (rv);
  38061         }
  38062 
  38063 
  38064         LOG_CLI((BSL_META_U(unit,
  38065                             "{stat id %d  slice = %d idx=%d entries=%d}"),
  38066                  f_st->sid, f_st->pool_index, f_st->hw_index,
  38067                                            f_st->hw_entry_count));
  38068         for (idx = 0; idx < f_st->nstat; idx++) {
  38069             /* coverity[mixed_enums] */
  38070             if (f_st->stat_arr[idx] < (bcm_field_stat_t)_bcmFieldStatCount) {
  38071                 LOG_CLI((BSL_META_U(unit,
  38072                                     "{%s}"), sname[f_st->stat_arr[idx]]));
  38073             }
  38074         }
  38075     } else {
  38076         LOG_CLI((BSL_META_U(unit,
  38077                             "NULL")));
  38078     }
  38079 
  38080 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIDENT2PLUS_SUPPORT)
  38081     if (SOC_IS_TRIDENT3X(unit) || SOC_IS_TD2P_TT2P(unit) || SOC_IS_APACHE(unit) ||
  38082             soc_feature(unit, soc_feature_flex_stat_compaction_support)) {
  38083         LOG_CLI((BSL_META_U(unit, "\r\n")));
  38084         LOG_CLI((BSL_META_U(unit,
  38085                         "         Extended statistics=")));
  38086         if (f_ent->statistic.flags  & _FP_ENTRY_EXTENDED_STAT_VALID) {
  38087             rv = _bcm_field_stat_get (unit,
  38088                           f_ent->statistic.extended_sid, &f_st);
  38089             if (BCM_FAILURE(rv)) {
  38090                 return (rv);
  38091             }
  38092 
  38093             LOG_CLI((BSL_META_U(unit,
  38094                             "\r\n                    {stat id %d action = %s"
  38095                             " slice = %d idx=%d entries=%d}"),
  38096                         f_st->sid, aname[f_ent->statistic.stat_action],
  38097                         f_st->pool_index, f_st->hw_index,
  38098                         f_st->hw_entry_count));
  38099             for (idx = 0; idx < f_st->nstat; idx++) {
  38100                 /* coverity[mixed_enums] */
  38101                 if (f_st->stat_arr[idx] < (bcm_field_stat_t)_bcmFieldStatCount){
  38102                     LOG_CLI((BSL_META_U(unit,
  38103                                     "{%s}"), sname[f_st->stat_arr[idx]]));
  38104                 }
  38105             }
  38106         } else {
  38107             LOG_CLI((BSL_META_U(unit,
  38108                             "NULL")));
  38109         }
  38110     }
  38111 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
  38112     return (rv);
  38113 }
  38114 
  38115 /*
  38116  * Function:
  38117  *     _field_policers_dump
  38118  * Purpose:
  38119 
  38120  *     Output meter data for given entry.
  38121  */
  38122 void
  38123 _field_policers_dump(int unit, _field_entry_t *f_ent)
  38124 {
  38125     bcm_policer_t     policer_id;     /* Policer id.                  */
  38126     _field_policer_t  *f_pl;          /* Internal policer descriptor. */
  38127     int               idx;            /* Policers levels iterator.    */
  38128     int               rv;             /* Operation return status.     */
  38129     uint8             isPolicerDirty; /* Verify if policer Dirty      */
  38130 
  38131     for (idx = 0; idx < _FP_POLICER_LEVEL_COUNT; idx++) {
  38132         /* Read policer id from entry. */
  38133         rv = bcm_esw_field_entry_policer_get(unit, f_ent->eid,
  38134                                              idx, &policer_id);
  38135         if (BCM_E_NOT_FOUND == rv) {
  38136             continue;
  38137         }
  38138         if (BCM_FAILURE(rv)) {
  38139             return;
  38140         }
  38141 
  38142         /* Get policer reference count. */
  38143         rv = _bcm_field_policer_get(unit, policer_id, &f_pl);
  38144         if (BCM_FAILURE(rv)) {
  38145             return;
  38146         }
  38147 
  38148         if ((f_pl->hw_flags & _FP_POLICER_DIRTY)
  38149                     || (f_ent->flags & _FP_ENTRY_DIRTY)) {
  38150             isPolicerDirty = TRUE;
  38151         } else {
  38152             isPolicerDirty = FALSE;
  38153         }
  38154 
  38155         LOG_CLI((BSL_META_U(unit,
  38156                             "{pid=%#x, level=%#x, "), f_pl->pid, f_pl->level));
  38157 
  38158         if (!_FP_POLICER_IS_FLOW_MODE(f_pl)) {
  38159             LOG_CLI((BSL_META_U(unit,
  38160                                 "peak_kbits_sec=%#x, peak_kbits_burst=%#x,"),
  38161                      f_pl->cfg.pkbits_sec, f_pl->cfg.pkbits_burst));
  38162         }
  38163 
  38164         if ((bcmPolicerModePeak != f_pl->cfg.mode)) {
  38165             LOG_CLI((BSL_META_U(unit,
  38166                                 " commit_kbits_sec=%#x, commit_kbits_burst=%#x, "),
  38167                      f_pl->cfg.ckbits_sec, f_pl->cfg.ckbits_burst));
  38168         }
  38169 
  38170         LOG_CLI((BSL_META_U(unit,
  38171                             "PacketBased=%#x,"),
  38172                  (f_pl->cfg.flags & BCM_POLICER_MODE_PACKETS) ? 1 : 0));
  38173 
  38174         LOG_CLI((BSL_META_U(unit,
  38175                             " mode=%#x, entries=%d, %s}"),
  38176                  f_pl->cfg.mode, f_pl->sw_ref_count,
  38177                  (isPolicerDirty) ? "Dirty" : "Clean"));
  38178     }
  38179 }
  38180 
  38181 /*
  38182  * Function:
  38183  *     _field_action_dump
  38184  * Purpose:
  38185  *     Output fields in a _field_action_s struct.
  38186  */
  38187 void
  38188 _field_action_dump(const _field_action_t *fa)
  38189 {
  38190     if (fa == NULL) {
  38191         LOG_CLI((BSL_META("NULL")));
  38192     } else {
  38193 #if defined(BCM_TOMAHAWK_SUPPORT)
  38194        /*
  38195         * Manuplate EgressMirror to CopyToCpu Action for CTC WAR.
  38196         */
  38197         if ((fa->action == bcmFieldActionMirrorEgress) &&
  38198             (fa->flags & _BCM_FIELD_ACTION_CTC_MANIPULATE_FLAG)) {
  38199             LOG_CLI((BSL_META("{act=%s, param0=%d(%#x), param1=%d(%#x),"
  38200                  " param2=%d(%#x), param3=%d(%#x)}"),
  38201                  _field_action_name(bcmFieldActionCopyToCpu), fa->param[2],
  38202                  fa->param[2], fa->param[3], fa->param[3], 0, 0, 0, 0));
  38203             return;
  38204         }
  38205 #endif
  38206         LOG_CLI((BSL_META("{act=%s, param0=%d(%#x), param1=%d(%#x), param2=%d(%#x), param3=%d(%#x)%s"),
  38207                  _field_action_name(fa->action), fa->param[0], fa->param[0],
  38208                  fa->param[1], fa->param[1], fa->param[2], fa->param[2],
  38209                  fa->param[3], fa->param[3], (fa->flags & _FP_ACTION_VALID) ? "" : ", Dirty"));
  38210 #if defined(BCM_TOMAHAWK_SUPPORT)
  38211         if (bcmFieldActionFabricEHAddOrUpdate == fa->action) {
  38212             LOG_CLI((BSL_META("Extended_Header_Mask_Profile=%d,"), fa->hw_index));
  38213         }
  38214 #endif
  38215         LOG_CLI((BSL_META("}")));
  38216 
  38217         }
  38218 }
  38219 
  38220 /*
  38221  * Function:
  38222  *     _field_group_status_dump
  38223  * Purpose:
  38224  *     Output the fields in a bcm_field_group_status_s struct.
  38225  */
  38226 void
  38227 _field_group_status_dump(const bcm_field_group_status_t *gstat)
  38228 {
  38229     LOG_CLI((BSL_META("{prio_min=%d,"),       gstat->prio_min));
  38230     LOG_CLI((BSL_META(" prio_max=%d,"),       gstat->prio_max));
  38231     LOG_CLI((BSL_META(" entries_total=%d,"),  gstat->entries_total));
  38232     LOG_CLI((BSL_META(" entries_free=%d,"),   gstat->entries_free));
  38233     LOG_CLI((BSL_META("\n                      ")));
  38234     LOG_CLI((BSL_META(" counters_total=%d,"), gstat->counters_total));
  38235     LOG_CLI((BSL_META(" counters_free=%d,"),  gstat->counters_free));
  38236     LOG_CLI((BSL_META(" meters_total=%d,"),   gstat->meters_total));
  38237     LOG_CLI((BSL_META(" meters_free=%d}"),    gstat->meters_free));
  38238 }
  38239 
  38240 
  38241 
  38242 
  38243 int
  38244 _field_is_inited(int unit)
  38245 {
  38246     /* Make sure system was initialized. */
  38247     FIELD_IS_INIT(unit);
  38248     return BCM_E_NONE;
  38249 }
  38250 
  38251 /*
  38252  * Function: _bcm_field_linkscan_update
  38253  *
  38254  * Purpose:
  38255  *    Register with link scan thread to get port updates.
  38256  *
  38257  * Parameters:
  38258  *     unit     - (IN) BCM device numberi
  38259  *     port     - (OUT) Port
  38260  *    *portInfo - (OUT) Port Info Data Structure
  38261  *
  38262  * Returns:
  38263  *     BCM_E_NONE    - Success
  38264  */
  38265 void _bcm_field_linkscan_update(int unit,
  38266                                   bcm_port_t port,
  38267                                   bcm_port_info_t *portInfo)
  38268 {
  38269     int                               rc = 0;
  38270     int                               isEntryDirty = 0;
  38271     bcm_pbmp_t                        egrPortPbmp;
  38272     _field_entry_t                   *f_ent;
  38273     _field_control_t                 *fc;
  38274     _field_entry_recover_egr_ports_t *egrPortDbEntry = NULL;
  38275     _field_entry_recover_egr_ports_t *head;
  38276     _field_egr_ports_recovery_t *f_egr_recovery = NULL;
  38277 
  38278     rc = _field_egr_ports_recovery_control_get (unit, &f_egr_recovery);
  38279 
  38280     if (rc != BCM_E_NONE) {
  38281         LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
  38282                         "FP (%d) RECOVERY_DB() not initialized\r\n"),unit));
  38283         return;
  38284     }
  38285 
  38286     if (f_egr_recovery == NULL) {
  38287         LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
  38288                         "FP (%d) RECOVERY_DB() Internal Error\r\n"),unit));
  38289         return;
  38290     }
  38291 
  38292     head = f_egr_recovery->entry_recover_egr_ports[port];
  38293 
  38294         LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
  38295                "FP (%d) Received update on port = %d en = %d linstat = %d\r\n"),
  38296                     unit, (int)port,portInfo->enable,portInfo->linkstatus));
  38297 
  38298      BCM_PBMP_CLEAR(egrPortPbmp);
  38299 
  38300     /* Using the port (which the linkscan notified) as index, loop
  38301      * through all the entries in the redirect_pbm_recovery database,
  38302      * retrieve the egrPortPbmp configured in that entry and update the
  38303      * pbmp based on the port's link status and then reinstall the
  38304      * FP entry.
  38305      */
  38306     FP_LOCK(unit);
  38307     if (NULL != head) {
  38308         rc = _field_control_get(unit, &fc);
  38309         if (BCM_FAILURE(rc)) {
  38310             FP_UNLOCK(unit);
  38311             return;
  38312         }
  38313 
  38314 
  38315         egrPortDbEntry = head;
  38316         while (egrPortDbEntry != NULL) {
  38317             /* Set Global variable to inform that FP action is updated due
  38318                to Link Scan Update and hence redirect_pbm_recovery database
  38319                should not be modified */
  38320             _field_egr_ports_recovery_lock[unit] = 1;
  38321             rc = bcm_esw_field_action_ports_get (unit, egrPortDbEntry->eid,
  38322                     bcmFieldActionEgressPortsAdd, &egrPortPbmp);
  38323             if (rc != BCM_E_NONE) {
  38324                 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
  38325                 "FP (%d) RECOVERY_DB() bcm_field_action_ports_get failed \r\n"),unit));
  38326                 _field_egr_ports_recovery_lock[unit] = 0;
  38327                 FP_UNLOCK(unit);
  38328                 return;
  38329             }
  38330 
  38331             if (portInfo->linkstatus == BCM_PORT_LINK_STATUS_UP) {
  38332                 BCM_PBMP_PORT_ADD (egrPortPbmp, port);
  38333             } else {
  38334                 BCM_PBMP_PORT_REMOVE (egrPortPbmp, port);
  38335             }
  38336 
  38337             /* Get field control structure. Check if entry already installed
  38338              * If so, reinstall the entry, else just update the fp entry action
  38339              */
  38340             rc = _field_entry_get(unit, egrPortDbEntry->eid,
  38341                     _FP_ENTRY_PRIMARY, &f_ent);
  38342             if (BCM_FAILURE(rc)) {
  38343                 _field_egr_ports_recovery_lock[unit] = 0;
  38344                 FP_UNLOCK(unit);
  38345                 return;
  38346             }
  38347 
  38348             isEntryDirty = (f_ent->flags & _FP_ENTRY_DIRTY);
  38349 
  38350             rc = bcm_esw_field_action_remove (unit, egrPortDbEntry->eid,
  38351                                     bcmFieldActionEgressPortsAdd);
  38352             if (BCM_FAILURE(rc)) {
  38353                 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
  38354                    "FP (%d) RECOVERY_DB() bcm_field_action_remove failed"),
  38355                                                                         unit));
  38356                 _field_egr_ports_recovery_lock[unit] = 0;
  38357                 FP_UNLOCK(unit);
  38358                 return;
  38359             }
  38360             rc = bcm_esw_field_action_ports_add (unit, egrPortDbEntry->eid,
  38361                                     bcmFieldActionEgressPortsAdd, egrPortPbmp);
  38362             if (BCM_FAILURE(rc)) {
  38363                 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
  38364                 "FP (%d) RECOVERY_DB() bcm_field_action_ports_add failed"),
  38365                                                                       unit));
  38366                 _field_egr_ports_recovery_lock[unit] = 0;
  38367                 FP_UNLOCK(unit);
  38368                 return;
  38369             }
  38370 
  38371             /* Re-install Entry only when Entry is not Dirty*/
  38372             if (!isEntryDirty) {
  38373                 rc = bcm_esw_field_entry_reinstall (unit, egrPortDbEntry->eid);
  38374                 if (BCM_FAILURE(rc)) {
  38375                     LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
  38376                      "FP (%d) RECOVERY_DB() bcm_field_entry_reinstall failed"),
  38377                                                                          unit));
  38378                     _field_egr_ports_recovery_lock[unit] = 0;
  38379                     FP_UNLOCK(unit);
  38380                     return;
  38381                 }
  38382             }
  38383              egrPortDbEntry = egrPortDbEntry->next;
  38384         }
  38385         _field_egr_ports_recovery_lock[unit] = 0;
  38386 
  38387     }
  38388     FP_UNLOCK(unit);
  38389     return;
  38390 }
  38391 
  38392 
  38393 /*
  38394  * Function: _bcm_field_control_EgressAutoExpanWithPolicer_set
  38395  *
  38396  * Purpose:
  38397  *     Set control status.
  38398  *
  38399  * Parameters:
  38400  *     unit     - (IN) BCM device number.
  38401  *     fc       - (IN/OUT) Field Control Structure.
  38402  *     state    - (IN) State (0/1).
  38403  *
  38404  * Returns:
  38405  *     BCM_E_NONE    - Success
  38406  *     BCM_E_INIT    - BCM unit not initialized
  38407  *     BCM_E_PARAM   - Flag state not valid on device
  38408  */
  38409 int
  38410 _bcm_field_control_EgressAutoExpanWithPolicer_set(int unit,
  38411          _field_control_t *fc, uint32 state)
  38412 {
  38413     _field_stage_t     *stage_fc = NULL; /* fc stage structure*/
  38414     _field_group_t     *fg;   /* Field group structure */
  38415     int  slice_sz; /* Number of entries in a slice.*/
  38416     _field_slice_t       *fs; /* Field slice structure.  */
  38417     _field_entry_policer_t *f_ent_pl; /* Field entry policer structure.*/
  38418     int      idx; /* Slice iteration index. */
  38419 
  38420     slice_sz = 0;
  38421     /*currently supported only for TD2Plus */
  38422     if (!(SOC_IS_TRIDENT2PLUS(unit))) {
  38423         return BCM_E_UNAVAIL;
  38424     }
  38425 
  38426     if (NULL == fc) {
  38427         return (BCM_E_PARAM);
  38428     }
  38429 
  38430     if ((state != 0) && (state != 1)) {
  38431         return BCM_E_PARAM;
  38432     }
  38433     BCM_IF_ERROR_RETURN
  38434          (_field_stage_control_get(unit, _BCM_FIELD_STAGE_EGRESS, &stage_fc));
  38435 
  38436     if ((stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS) ||
  38437         (fc->flags &_FP_POLICER_GROUP_SHARE_ENABLE) ) {
  38438         return BCM_E_UNAVAIL;
  38439     }
  38440 
  38441     if( ((state == 0) &&
  38442          (!(fc->flags & _FP_AUTOEXPAND_WITH_POLICER))) ||
  38443          ((state == 1) &&
  38444          ((fc->flags & _FP_AUTOEXPAND_WITH_POLICER))) ) {
  38445             /* do nothing and return */
  38446             return BCM_E_NONE;
  38447     }
  38448     fg = fc->groups;
  38449     while (NULL != fg) {
  38450         if (fg->stage_id == _BCM_FIELD_STAGE_EGRESS) {
  38451             /* Egress group found. Check if the group
  38452              * is autoexpanded or has policers attached
  38453              */
  38454             fs = fg->slices;
  38455             while (NULL != fs) {
  38456                 _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs, slice_sz);
  38457                 for (idx = 0; idx < slice_sz; idx ++)  {
  38458                    /* Find  non-empty slot. */
  38459                    if (NULL != fs->entries[idx]) {
  38460                         /* check if policer is attached to entry.
  38461                          * if attached, then we cannot enable the feature
  38462                          */
  38463                         f_ent_pl = fs->entries[idx]->policer;
  38464                         if ((f_ent_pl) &&
  38465                             (f_ent_pl->pid != _FP_INVALID_INDEX) ) {
  38466                             return BCM_E_UNAVAIL;
  38467                         }
  38468                     }
  38469                 }
  38470                 fs = fs->next;
  38471             }
  38472         }
  38473         fg = fg->next;
  38474     }
  38475     if (state == 0) {
  38476         fc->flags &= ~_FP_AUTOEXPAND_WITH_POLICER;
  38477     } else {
  38478         fc->flags |= _FP_AUTOEXPAND_WITH_POLICER;
  38479     }
  38480     return BCM_E_NONE;
  38481 }
  38482 /*
  38483  * Function: _bcm_field_control_get
  38484  *
  38485  * Purpose:
  38486  *     Get control status info.
  38487  *
  38488  * Parameters:
  38489  *     unit     - (IN)  BCM device number.
  38490  *     fc       - (IN)  Field Control Structure.
  38491  *     control  - (IN)  Control element to get.
  38492  *     status   - (OUT) Status of field element.
  38493  *
  38494  * Returns:
  38495  *     BCM_E_INIT    - BCM unit not initialized
  38496  *     BCM_E_PARAM   - *state pointing to NULL
  38497  *     BCM_E_NONE    - Success
  38498  */
  38499 int
  38500 _bcm_field_control_get(int unit, _field_control_t *fc,
  38501                        bcm_field_control_t control, uint32 *state)
  38502 {
  38503     int                 rv = BCM_E_NONE; /* Operation return status.      */
  38504     uint32              val1;
  38505     uint32              val2;
  38506     uint32              reg_val;         /* Register value buffer.        */
  38507 #if defined (BCM_TRX_SUPPORT)
  38508     uint64              val64;           /* Register 64bitvalue buffer.   */
  38509 #endif /* BCM_TRX_SUPPORT */
  38510 
  38511     if (NULL == fc || NULL == state) {
  38512         return BCM_E_PARAM;
  38513     }
  38514 
  38515     switch (control) {
  38516       case bcmFieldControlIntraDoubleEnable:
  38517           *state = (fc->flags & _FP_INTRASLICE_ENABLE) ? TRUE : FALSE;
  38518           break;
  38519       case bcmFieldControlColorIndependent:
  38520           *state = (fc->flags & _FP_COLOR_INDEPENDENT) ? TRUE : FALSE;
  38521           break;
  38522       case bcmFieldControlStage:
  38523           rv = (BCM_E_UNAVAIL);
  38524           break;
  38525 
  38526 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT)
  38527       case bcmFieldControlExternalUdfEnable:
  38528           if (SOC_REG_IS_VALID(unit, ESM_KEYGEN_CTLr)) {
  38529               rv = READ_ESM_KEYGEN_CTLr(unit, &reg_val);
  38530               if (BCM_SUCCESS(rv)) {
  38531                   *state = soc_reg_field_get(unit, ESM_KEYGEN_CTLr, reg_val,
  38532                                              L2_ACL_PAYLOAD_MODEf);
  38533               }
  38534           } else {
  38535               rv = (BCM_E_UNAVAIL);
  38536           }
  38537           break;
  38538 #endif /* !(BCM_TRIUMPH2_SUPPORT || BCM_TRIUMPH_SUPPORT) */
  38539 
  38540       case bcmFieldControlSharedVlanFieldSet:
  38541           if (SOC_IS_TRX(unit)) {
  38542               rv = (BCM_E_UNAVAIL);
  38543               break;
  38544           }
  38545           if (SOC_REG_FIELD_VALID(unit, ING_CONFIGr, MAP_FID_ID_TO_INNER_TAGf)) {
  38546               rv = READ_ING_CONFIGr(unit, &reg_val);
  38547               val1 = soc_reg_field_get(unit, ING_CONFIGr, reg_val, MAP_FID_ID_TO_INNER_TAGf);
  38548               val2 = soc_reg_field_get(unit, ING_CONFIGr, reg_val, MAP_FID_ID_TO_OUTER_TAGf);
  38549               if ((0 == val1) && (0 == val2)) {
  38550                   *state = BCM_FIELD_SHARED_VLAN_NONE;
  38551               }
  38552               if ((0 == val1) && (1 == val2)) {
  38553                   *state = BCM_FIELD_SHARED_VLAN_OUTER;
  38554               }
  38555               if ((1 == val1) && (0 == val2)) {
  38556                   *state = BCM_FIELD_SHARED_VLAN_INNER;
  38557               }
  38558           } else {
  38559               rv = (BCM_E_UNAVAIL);
  38560           }
  38561           break;
  38562 #if defined(BCM_TRX_SUPPORT)
  38563       case bcmFieldControlArpAsIp:
  38564           if (SOC_REG_FIELD_VALID(unit, ING_CONFIG_64r, ARP_RARP_TO_FPf)) {
  38565               rv = READ_ING_CONFIG_64r(unit, &val64);
  38566               if (BCM_SUCCESS(rv)) {
  38567                   reg_val = soc_reg64_field32_get(unit, ING_CONFIG_64r,
  38568                                                   val64, ARP_RARP_TO_FPf);
  38569                   *state = (0x1 & reg_val) ? TRUE : FALSE;
  38570               }
  38571           } else {
  38572               rv = (BCM_E_UNAVAIL);
  38573           }
  38574           break;
  38575       case bcmFieldControlRarpAsIp:
  38576           if (SOC_REG_FIELD_VALID(unit, ING_CONFIG_64r, ARP_RARP_TO_FPf)) {
  38577               rv = READ_ING_CONFIG_64r(unit, &val64);
  38578               if (BCM_SUCCESS(rv)) {
  38579                   reg_val = soc_reg64_field32_get(unit, ING_CONFIG_64r,
  38580                                                   val64, ARP_RARP_TO_FPf);
  38581                   *state = (0x2 & reg_val) ? TRUE : FALSE;
  38582               }
  38583           } else {
  38584               rv = (BCM_E_UNAVAIL);
  38585           }
  38586           break;
  38587       case bcmFieldControlRedirectIngressVlanCheck:
  38588           if (SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) {
  38589               rv = READ_SW2_FP_DST_ACTION_CONTROLr(unit, &reg_val);
  38590               if (BCM_SUCCESS(rv)) {
  38591                   *state = soc_reg_field_get(unit, SW2_FP_DST_ACTION_CONTROLr,
  38592                                              reg_val, VLAN_CHECK_ENf);
  38593               }
  38594           } else {
  38595               rv = (BCM_E_UNAVAIL);
  38596           }
  38597           break;
  38598       case bcmFieldControlRedirectNonUcastTrunkResolve:
  38599           if (SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) {
  38600               rv = READ_SW2_FP_DST_ACTION_CONTROLr(unit, &reg_val);
  38601               if (BCM_SUCCESS(rv)) {
  38602                   *state = soc_reg_field_get(unit, SW2_FP_DST_ACTION_CONTROLr,
  38603                                              reg_val, LAG_RES_ENf);
  38604               }
  38605           } else {
  38606               rv = (BCM_E_UNAVAIL);
  38607           }
  38608           break;
  38609       case bcmFieldControlRedirectNonUcastEtherTrunkResolve:
  38610           if (SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) {
  38611               rv = READ_SW2_FP_DST_ACTION_CONTROLr(unit, &reg_val);
  38612               if (BCM_SUCCESS(rv)) {
  38613                   *state = soc_reg_field_get(unit, SW2_FP_DST_ACTION_CONTROLr,
  38614                                              reg_val, LAG_RES_ENf);
  38615               }
  38616           } else {
  38617               rv = (BCM_E_UNAVAIL);
  38618           }
  38619           break;
  38620       case bcmFieldControlRedirectNonUcastFabricTrunkResolve:
  38621           if (SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) {
  38622               rv = READ_SW2_FP_DST_ACTION_CONTROLr(unit, &reg_val);
  38623               if (BCM_SUCCESS(rv)) {
  38624                   *state = soc_reg_field_get(unit, SW2_FP_DST_ACTION_CONTROLr,
  38625                                              reg_val, HGTRUNK_RES_ENf);
  38626               }
  38627           } else {
  38628               rv = (BCM_E_UNAVAIL);
  38629           }
  38630           break;
  38631       case bcmFieldControlRedirectExcludeSrcPort:
  38632           if (SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) {
  38633               rv = READ_SW2_FP_DST_ACTION_CONTROLr(unit, &reg_val);
  38634               if (BCM_SUCCESS(rv)) {
  38635                   *state = soc_reg_field_get(unit, SW2_FP_DST_ACTION_CONTROLr,
  38636                                              reg_val, SRC_REMOVAL_ENf);
  38637               }
  38638           } else {
  38639               rv = (BCM_E_UNAVAIL);
  38640           }
  38641           break;
  38642       case bcmFieldControlRedirectPortFloodBlock:
  38643           if (SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) {
  38644               rv = READ_SW2_FP_DST_ACTION_CONTROLr(unit, &reg_val);
  38645               if (BCM_SUCCESS(rv)) {
  38646                   *state = soc_reg_field_get(unit, SW2_FP_DST_ACTION_CONTROLr,
  38647                                              reg_val, PORT_BLOCK_ENf);
  38648               }
  38649           } else {
  38650               rv = (BCM_E_UNAVAIL);
  38651           }
  38652           break;
  38653       case  bcmFieldControlRedirectVlanFloodBlock:
  38654           if (SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) {
  38655               rv = READ_SW2_FP_DST_ACTION_CONTROLr(unit, &reg_val);
  38656               if (BCM_SUCCESS(rv)) {
  38657                   *state = soc_reg_field_get(unit, SW2_FP_DST_ACTION_CONTROLr,
  38658                                              reg_val, VLAN_BLOCK_ENf);
  38659               }
  38660           } else {
  38661               rv = (BCM_E_UNAVAIL);
  38662           }
  38663           break;
  38664       case bcmFieldControlRedirectExcludeEtherSrcPort:
  38665           if (SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) {
  38666               rv = READ_SW2_FP_DST_ACTION_CONTROLr(unit, &reg_val);
  38667               if (BCM_SUCCESS(rv)) {
  38668                   *state = soc_reg_field_get(unit, SW2_FP_DST_ACTION_CONTROLr,
  38669                           reg_val, SRC_REMOVAL_ENf);
  38670               }
  38671           } else {
  38672               rv = (BCM_E_UNAVAIL);
  38673           }
  38674           break;
  38675       case bcmFieldControlRedirectExcludeHiGigSrcPort:
  38676           if (SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) {
  38677               rv = READ_SW2_FP_DST_ACTION_CONTROLr(unit, &reg_val);
  38678               if (BCM_SUCCESS(rv)) {
  38679                   *state = soc_reg_field_get(unit, SW2_FP_DST_ACTION_CONTROLr,
  38680                                              reg_val, HG_SRC_REMOVAL_ENf);
  38681               }
  38682           } else {
  38683               rv = (BCM_E_UNAVAIL);
  38684           }
  38685           break;
  38686 #endif /* BCM_TRX_SUPPORT */
  38687       case bcmFieldControlStatSyncEnable:
  38688 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRX_SUPPORT)
  38689           if (SOC_IS_TRX(unit) || SOC_IS_BRADLEY(unit)) {
  38690               *state = (fc->flags & _FP_STAT_SYNC_ENABLE) ? TRUE : FALSE;
  38691           } else
  38692 #endif
  38693           {
  38694               rv = (BCM_E_UNAVAIL);
  38695           }
  38696           break;
  38697       case bcmFieldControlPolicerGroupSharingEnable:
  38698           *state = (fc->flags & _FP_POLICER_GROUP_SHARE_ENABLE) ? TRUE : FALSE;
  38699           break;
  38700       case  bcmFieldControlRedirectNextHopExcludeSrcPort:
  38701           if (0 == soc_reg_field_valid(unit,SW2_FP_DST_ACTION_CONTROLr,
  38702               SRC_REMOVAL_EN_FOR_REDIRECT_TO_NHIf)) {
  38703               rv = (BCM_E_UNAVAIL);
  38704           } else {
  38705               rv = READ_SW2_FP_DST_ACTION_CONTROLr(unit, &reg_val);
  38706               if (BCM_SUCCESS(rv)) {
  38707                   *state = soc_reg_field_get(unit, SW2_FP_DST_ACTION_CONTROLr,
  38708                                            reg_val,
  38709                                            SRC_REMOVAL_EN_FOR_REDIRECT_TO_NHIf);
  38710               }
  38711 
  38712           }
  38713           break;
  38714 #ifdef BCM_TRIUMPH3_SUPPORT
  38715       case bcmFieldControlIngressLogicalPolicerPoolsMode:
  38716           if (SOC_IS_TRIUMPH3(unit)) {
  38717               *state = fc->ingress_logical_policer_pools_mode;
  38718           }else {
  38719               *state = -1;
  38720               rv = BCM_E_UNAVAIL;
  38721           }
  38722           break;
  38723 #endif
  38724 
  38725 #if defined(BCM_METROLITE_SUPPORT)
  38726       case bcmFieldControlReplacementTtl:
  38727           if (SOC_REG_IS_VALID(unit, EGR_REPLACEMENT_TTLr)) {
  38728               rv = READ_EGR_REPLACEMENT_TTLr(unit, &reg_val);
  38729             if (BCM_SUCCESS(rv)) {
  38730                 *state = soc_reg_field_get(unit, EGR_REPLACEMENT_TTLr,
  38731                     reg_val, REPLACEMENT_TTLf);
  38732             } else {
  38733                 rv = (BCM_E_UNAVAIL);
  38734             }
  38735           } else {
  38736               rv = (BCM_E_UNAVAIL);
  38737           }
  38738           break;
  38739 #endif
  38740 
  38741       case bcmFieldControlOverrideStageLookupPhb:
  38742 #if defined (BCM_TRX_SUPPORT)
  38743           if ((SOC_REG_IS_VALID(unit, ING_CONFIG_64r)) &&
  38744               (SOC_REG_FIELD_VALID(unit, ING_CONFIG_64r,
  38745                                     VFP_PRI_ACTION_FB2_MODEf))) {
  38746               rv = READ_ING_CONFIG_64r(unit, &val64);
  38747               if (BCM_SUCCESS(rv)) {
  38748                   *state = soc_reg64_field32_get(unit, ING_CONFIG_64r,
  38749                                           val64, VFP_PRI_ACTION_FB2_MODEf);
  38750               }
  38751           } else {
  38752                rv = BCM_E_UNAVAIL;
  38753           }
  38754 #endif
  38755           break;
  38756       case bcmFieldControlEgressAutoExpandWithPolicer:
  38757           *state = (fc->flags & _FP_AUTOEXPAND_WITH_POLICER) ?
  38758                           TRUE : FALSE;
  38759           break;
  38760       default:
  38761           rv = (BCM_E_UNAVAIL);
  38762     }
  38763 
  38764     return rv;
  38765 }
  38766 
  38767 /*
  38768  * Function: _bcm_field_control_set
  38769  *
  38770  * Purpose:
  38771  *     Set control status.
  38772  *
  38773  * Parameters:
  38774  *     unit     - (IN) BCM device number.
  38775  *     fc       - (IN/OUT) Field Control Structure.
  38776  *     control  - (IN) Control element to set.
  38777  *     state    - (IN) State (0/1).
  38778  *
  38779  * Returns:
  38780  *     BCM_E_NONE    - Success
  38781  *     BCM_E_INIT    - BCM unit not initialized
  38782  *     BCM_E_PARAM   - Flag state not valid on device
  38783  */
  38784 int
  38785 _bcm_field_control_set(int unit,  _field_control_t *fc,
  38786                        bcm_field_control_t control, uint32 state)
  38787 {
  38788     int                 rv = BCM_E_NONE;  /* Operation return status.   */
  38789     uint32              reg_values[2];    /* Register value buffer.     */
  38790     soc_field_t         reg_fields[2];    /* Register fields to modify. */
  38791     int                 field_count = 2;  /* Number of updated fields.  */
  38792     reg_values[0] = reg_values[1] = (state == TRUE) ? 1: 0;
  38793 
  38794     if (NULL == fc) {
  38795         return BCM_E_PARAM;
  38796     }
  38797 
  38798     switch (control) {
  38799       case bcmFieldControlIntraDoubleEnable:
  38800           if (soc_feature(unit, soc_feature_field_intraslice_double_wide)) {
  38801               if (state == 0) {
  38802                   fc->flags &= ~_FP_INTRASLICE_ENABLE;
  38803               } else {
  38804                   fc->flags |= _FP_INTRASLICE_ENABLE;
  38805               }
  38806           } else if (state == 0) {
  38807               fc->flags &= ~_FP_INTRASLICE_ENABLE;
  38808           } else {
  38809               LOG_ERROR(BSL_LS_BCM_FP,
  38810                         (BSL_META_U(unit,
  38811                                     "FP(unit %d) Error: Device doesn't support intraslice\n"),
  38812                          unit));
  38813               rv = (BCM_E_UNAVAIL);
  38814           }
  38815           break;
  38816       case bcmFieldControlColorIndependent:
  38817           if (soc_feature(unit, soc_feature_field_color_indep)) {
  38818               if (state == 0) {
  38819                   fc->flags &= ~_FP_COLOR_INDEPENDENT;
  38820               } else {
  38821                   fc->flags |= _FP_COLOR_INDEPENDENT;
  38822               }
  38823           } else if (state == 0) {
  38824               fc->flags &= ~_FP_COLOR_INDEPENDENT;
  38825           } else {
  38826               LOG_ERROR(BSL_LS_BCM_FP,
  38827                         (BSL_META_U(unit,
  38828                                     "FP(unit %d) Error: Color Independence unsupported on this unit\n"),
  38829                          unit));
  38830               rv = BCM_E_UNAVAIL;
  38831           }
  38832           break;
  38833       case bcmFieldControlStage:
  38834           rv = (BCM_E_UNAVAIL);
  38835           break;
  38836       case bcmFieldControlSharedVlanFieldSet:
  38837           if (SOC_IS_TRX(unit)) {
  38838               rv = (BCM_E_UNAVAIL);
  38839               break;
  38840           }
  38841           if (SOC_REG_FIELD_VALID(unit, ING_CONFIGr, MAP_FID_ID_TO_INNER_TAGf)) {
  38842               reg_fields[0] = MAP_FID_ID_TO_INNER_TAGf;
  38843               reg_fields[1] = MAP_FID_ID_TO_OUTER_TAGf;
  38844               if (BCM_FIELD_SHARED_VLAN_NONE == state) {
  38845                   reg_values[0] = 0;
  38846                   reg_values[1] = 0;
  38847               } else if (BCM_FIELD_SHARED_VLAN_INNER == state) {
  38848                   reg_values[0] = 1;
  38849                   reg_values[1] = 0;
  38850               } else if (BCM_FIELD_SHARED_VLAN_OUTER == state) {
  38851                   reg_values[0] = 0;
  38852                   reg_values[1] = 1;
  38853               } else {
  38854                   rv = (BCM_E_PARAM);
  38855                   break;
  38856               }
  38857               rv =  soc_reg_fields32_modify(unit, ING_CONFIGr, REG_PORT_ANY,
  38858                                             field_count, reg_fields, reg_values);
  38859           } else {
  38860               rv = (BCM_E_UNAVAIL);
  38861           }
  38862           break;
  38863 #if defined(BCM_TRX_SUPPORT)
  38864       case bcmFieldControlArpAsIp:
  38865       case bcmFieldControlRarpAsIp:
  38866           if (SOC_REG_FIELD_VALID(unit, ING_CONFIG_64r, ARP_RARP_TO_FPf)) {
  38867               rv = _bcm_field_trx_control_arp_set(unit, control, state);
  38868           } else {
  38869               rv = (BCM_E_UNAVAIL);
  38870           }
  38871           break;
  38872       case bcmFieldControlRedirectIngressVlanCheck:
  38873           if (!SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) {
  38874               rv = (BCM_E_UNAVAIL);
  38875           } else {
  38876               reg_fields[0] = VLAN_CHECK_ENf;
  38877               field_count = 1;
  38878               rv = soc_reg_fields32_modify(unit, SW2_FP_DST_ACTION_CONTROLr,
  38879                                           REG_PORT_ANY, field_count,
  38880                                           reg_fields, reg_values);
  38881           }
  38882           break;
  38883       case bcmFieldControlRedirectNonUcastTrunkResolve:
  38884           if (!SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) {
  38885               rv = (BCM_E_UNAVAIL);
  38886           } else {
  38887               reg_fields[0] = LAG_RES_ENf;
  38888               reg_fields[1] = HGTRUNK_RES_ENf;
  38889               field_count = 2;
  38890               rv = soc_reg_fields32_modify(unit, SW2_FP_DST_ACTION_CONTROLr,
  38891                                            REG_PORT_ANY, field_count,
  38892                                            reg_fields, reg_values);
  38893           }
  38894           break;
  38895       case bcmFieldControlRedirectNonUcastEtherTrunkResolve:
  38896           if (!SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) {
  38897               rv = (BCM_E_UNAVAIL);
  38898           } else {
  38899               reg_fields[0] = LAG_RES_ENf;
  38900               field_count = 1;
  38901               rv = soc_reg_fields32_modify(unit, SW2_FP_DST_ACTION_CONTROLr,
  38902                                            REG_PORT_ANY, field_count,
  38903                                            reg_fields, reg_values);
  38904           }
  38905           break;
  38906       case bcmFieldControlRedirectNonUcastFabricTrunkResolve:
  38907           if (!SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) {
  38908               rv = (BCM_E_UNAVAIL);
  38909           } else {
  38910               reg_fields[0] = HGTRUNK_RES_ENf;
  38911               field_count = 1;
  38912               rv = soc_reg_fields32_modify(unit, SW2_FP_DST_ACTION_CONTROLr,
  38913                                            REG_PORT_ANY, field_count,
  38914                                            reg_fields, reg_values);
  38915           }
  38916           break;
  38917       case bcmFieldControlRedirectExcludeSrcPort:
  38918           if (!SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) {
  38919               rv = (BCM_E_UNAVAIL);
  38920           } else {
  38921               reg_fields[0] = HG_SRC_REMOVAL_ENf;
  38922               reg_fields[1] = SRC_REMOVAL_ENf;
  38923               field_count = 2;
  38924               rv = soc_reg_fields32_modify(unit, SW2_FP_DST_ACTION_CONTROLr,
  38925                                            REG_PORT_ANY, field_count,
  38926                                            reg_fields, reg_values);
  38927           }
  38928           break;
  38929       case bcmFieldControlRedirectExcludeEtherSrcPort:
  38930           if (!SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) {
  38931               rv = (BCM_E_UNAVAIL);
  38932           } else {
  38933               reg_fields[0] = SRC_REMOVAL_ENf;
  38934               field_count = 1;
  38935               rv = soc_reg_fields32_modify(unit, SW2_FP_DST_ACTION_CONTROLr,
  38936                                            REG_PORT_ANY, field_count,
  38937                                            reg_fields, reg_values);
  38938           }
  38939           break;
  38940       case bcmFieldControlRedirectExcludeHiGigSrcPort:
  38941           if (!SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) {
  38942               rv = (BCM_E_UNAVAIL);
  38943           } else {
  38944               reg_fields[0] = HG_SRC_REMOVAL_ENf;
  38945               field_count = 1;
  38946               rv = soc_reg_fields32_modify(unit, SW2_FP_DST_ACTION_CONTROLr,
  38947                                            REG_PORT_ANY, field_count,
  38948                                            reg_fields, reg_values);
  38949           }
  38950           break;
  38951       case bcmFieldControlRedirectPortFloodBlock:
  38952           if (!SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) {
  38953               rv = (BCM_E_UNAVAIL);
  38954           } else {
  38955               reg_fields[0] = PORT_BLOCK_ENf;
  38956               field_count = 1;
  38957               rv = soc_reg_fields32_modify(unit, SW2_FP_DST_ACTION_CONTROLr,
  38958                                            REG_PORT_ANY, field_count,
  38959                                            reg_fields, reg_values);
  38960           }
  38961           break;
  38962       case  bcmFieldControlRedirectVlanFloodBlock:
  38963           if (!SOC_REG_IS_VALID(unit, SW2_FP_DST_ACTION_CONTROLr)) {
  38964               rv = (BCM_E_UNAVAIL);
  38965           } else {
  38966               reg_fields[0] = VLAN_BLOCK_ENf;
  38967               field_count = 1;
  38968               rv = soc_reg_fields32_modify(unit, SW2_FP_DST_ACTION_CONTROLr,
  38969                                            REG_PORT_ANY, field_count,
  38970                                            reg_fields, reg_values);
  38971           }
  38972           break;
  38973 #endif /* BCM_TRX_SUPPORT */
  38974 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT)
  38975       case bcmFieldControlExternalUdfEnable:
  38976           if (SOC_REG_IS_VALID(unit, ESM_KEYGEN_CTLr)) {
  38977               rv = soc_reg_field32_modify(unit, ESM_KEYGEN_CTLr, REG_PORT_ANY,
  38978                                           L2_ACL_PAYLOAD_MODEf, state);
  38979           } else {
  38980               rv = (BCM_E_UNAVAIL);
  38981           }
  38982           break;
  38983 #endif /* !(BCM_TRIUMPH2_SUPPORT || BCM_TRIUMPH_SUPPORT) */
  38984       case bcmFieldControlStatSyncEnable:
  38985 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRX_SUPPORT)
  38986           if (SOC_IS_TRX(unit) || SOC_IS_BRADLEY(unit)) {
  38987               if (state == 0) {
  38988                   fc->flags &= ~_FP_STAT_SYNC_ENABLE;
  38989               } else {
  38990                   fc->flags |= _FP_STAT_SYNC_ENABLE;
  38991               }
  38992           } else
  38993 #endif
  38994           {
  38995               rv = (BCM_E_UNAVAIL);
  38996           }
  38997           break;
  38998       case bcmFieldControlPolicerGroupSharingEnable:
  38999           if (fc->groups) {
  39000               rv = BCM_E_CONFIG;
  39001           } else if (state == 0) {
  39002               fc->flags &= ~_FP_POLICER_GROUP_SHARE_ENABLE;
  39003           } else {
  39004               fc->flags |= _FP_POLICER_GROUP_SHARE_ENABLE;
  39005           }
  39006           break;
  39007       case  bcmFieldControlRedirectNextHopExcludeSrcPort:
  39008           if (0 == soc_reg_field_valid(unit,SW2_FP_DST_ACTION_CONTROLr,
  39009               SRC_REMOVAL_EN_FOR_REDIRECT_TO_NHIf)) {
  39010               rv = (BCM_E_UNAVAIL);
  39011           } else {
  39012               reg_fields[0] = SRC_REMOVAL_EN_FOR_REDIRECT_TO_NHIf;
  39013               field_count = 1;
  39014               rv = soc_reg_fields32_modify(unit, SW2_FP_DST_ACTION_CONTROLr,
  39015                                            REG_PORT_ANY, field_count,
  39016                                            reg_fields, reg_values);
  39017           }
  39018           break;
  39019 #ifdef BCM_TRIUMPH3_SUPPORT
  39020       case bcmFieldControlIngressLogicalPolicerPoolsMode:
  39021           if (SOC_IS_TRIUMPH3(unit)) {
  39022               if (state == fc->ingress_logical_policer_pools_mode) {
  39023                   return BCM_E_NONE;
  39024               } else {
  39025                   /* Cannot set the field control
  39026                    * if policers are already created.
  39027                    */
  39028                   if (fc->policer_count > 0) {
  39029                       return BCM_E_CONFIG;
  39030                   }
  39031               }
  39032               switch (state) {
  39033                   case bcmFieldIngressLogicalPolicerPools16x512Split:
  39034                       fc->ingress_logical_policer_pools_mode =
  39035                                  bcmFieldIngressLogicalPolicerPools16x512Split;
  39036                       break;
  39037                   case bcmFieldIngressLogicalPolicerPools16x512Contiguous:
  39038                       fc->ingress_logical_policer_pools_mode =
  39039                             bcmFieldIngressLogicalPolicerPools16x512Contiguous;
  39040                       break;
  39041                   case bcmFieldIngressLogicalPolicerPools8x1024:
  39042                       fc->ingress_logical_policer_pools_mode =
  39043                                       bcmFieldIngressLogicalPolicerPools8x1024;
  39044                       break;
  39045                   default:
  39046                       fc->ingress_logical_policer_pools_mode =
  39047                                       bcmFieldIngressLogicalPolicerPools8x1024;
  39048                       rv = BCM_E_CONFIG;
  39049               }
  39050           }else {
  39051               fc->ingress_logical_policer_pools_mode = -1;
  39052               rv = BCM_E_UNAVAIL;
  39053           }
  39054           break;
  39055 #endif
  39056 
  39057 #if defined(BCM_METROLITE_SUPPORT)
  39058       case bcmFieldControlReplacementTtl:
  39059           if (SOC_REG_IS_VALID(unit, EGR_REPLACEMENT_TTLr)) {
  39060               if (255 >= state ) {
  39061                   rv = soc_reg_field32_modify(unit, EGR_REPLACEMENT_TTLr,
  39062                                                     REG_PORT_ANY,
  39063                                                     REPLACEMENT_TTLf, state);
  39064             } else {
  39065                 rv = (BCM_E_PARAM);
  39066             }
  39067           } else {
  39068               rv = (BCM_E_UNAVAIL);
  39069           }
  39070           break;
  39071 #endif /* (BCM_METROLITE_SUPPORT) */
  39072 
  39073       case bcmFieldControlOverrideStageLookupPhb:
  39074           if ((SOC_REG_IS_VALID(unit, ING_CONFIG_64r)) &&
  39075               (SOC_REG_FIELD_VALID(unit, ING_CONFIG_64r,
  39076                                     VFP_PRI_ACTION_FB2_MODEf))) {
  39077               if (state) {
  39078                  rv = soc_reg_field32_modify(unit, ING_CONFIG_64r,
  39079                          REG_PORT_ANY, VFP_PRI_ACTION_FB2_MODEf, 1);
  39080               } else {
  39081                   rv = soc_reg_field32_modify(unit, ING_CONFIG_64r,
  39082                           REG_PORT_ANY, VFP_PRI_ACTION_FB2_MODEf, 0);
  39083               }
  39084           } else {
  39085               rv = BCM_E_UNAVAIL;
  39086           }
  39087           break;
  39088       case bcmFieldControlEgressAutoExpandWithPolicer:
  39089           rv = _bcm_field_control_EgressAutoExpanWithPolicer_set(
  39090                               unit, fc, state);
  39091           break;
  39092       default:
  39093           rv = (BCM_E_UNAVAIL);
  39094     }
  39095 
  39096     return rv;
  39097 }
  39098 
  39099 
  39100 /* Function: _field_hints_control_get
  39101  *
  39102  * Purpose:
  39103  *        Get Field Hints Control
  39104  * Parameters:
  39105  *     unit      - (IN) BCM device number.
  39106  *     hint_id   - (IN) Hint Id.
  39107  *        f_ht   - (OUT) hints_control_structure
  39108  * Returns:
  39109  *      BCM_E_XXXX.
  39110  */
  39111 int _field_hints_control_get(int unit,
  39112                              bcm_field_hintid_t hint_id,
  39113                              _field_hints_t **f_ht)
  39114 {
  39115     uint32             hash_index = 0; /* Hash index */
  39116     _field_hints_t    *f_ht_tmp;       /* field hints */
  39117     _field_control_t  *fc;             /* Field control structure. */
  39118 
  39119     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  39120 
  39121     hash_index = hint_id & _FP_HASH_INDEX_MASK(fc);
  39122     f_ht_tmp = fc->hints_hash[hash_index];
  39123 
  39124     while (NULL != f_ht_tmp) {
  39125         /* Match Hint id. */
  39126         if (f_ht_tmp->hintid == hint_id) {
  39127             *f_ht = f_ht_tmp;
  39128             break;
  39129         }
  39130         f_ht_tmp = f_ht_tmp->next;
  39131     }
  39132 
  39133     return BCM_E_NONE;
  39134 
  39135 }
  39136 
  39137 #ifdef BCM_WARM_BOOT_SUPPORT
  39138 /* Function: _bcm_field_hints_scache_sync
  39139  *
  39140  * Purpose:
  39141  *        Sync hints Hash table information into scache
  39142  * Parameters:
  39143  *         unit      - (IN)    BCM device number.
  39144  *           fc      - (IN)    Field Control.
  39145  *     stage_fc      - (IN)    Stage Control.
  39146  *     scache_ptr    - (INOUT) Scache Pointer.
  39147  * Returns:
  39148  *      BCM_E_XXXX.
  39149  */
  39150 int _bcm_field_hints_scache_sync (int unit,
  39151                                   _field_control_t *fc,
  39152                                   _field_stage_t   *stage_fc,
  39153                                   uint8 *scache_ptr)
  39154 {
  39155     bcm_field_hintid_t     hint_id = 0;       /* Hint Id */
  39156     _field_hints_t        *f_ht = NULL;       /* Field hints Structure */
  39157     _field_hint_t         *hints_dump = NULL; /* Field hints Structure */
  39158     bcm_field_hint_t      *hint_entry;        /* Hint Entry */
  39159     uint32                 hint_count = 0;    /* Hint count */
  39160     uint8 *curr_scache_ptr = scache_ptr;      /* Scache Pointer */
  39161 
  39162     if ((fc == NULL) || (stage_fc == NULL) || (scache_ptr == NULL)) {
  39163         return BCM_E_PARAM;
  39164     }
  39165 
  39166     if (stage_fc->stage_id != _BCM_FIELD_STAGE_INGRESS) {
  39167         return BCM_E_NONE;
  39168     }
  39169 
  39170     /* Sync hintid bitmap into scache */
  39171     sal_memcpy (curr_scache_ptr, ((fc->hintid_bmp).w),
  39172             SHR_BITALLOCSIZE(_FP_HINT_ID_MAX));
  39173     fc->scache_pos += SHR_BITALLOCSIZE(_FP_HINT_ID_MAX);
  39174     curr_scache_ptr += SHR_BITALLOCSIZE(_FP_HINT_ID_MAX);
  39175 
  39176     for (hint_id = _FP_HINT_ID_BASE; hint_id < _FP_HINT_ID_MAX; hint_id++) {
  39177         if (_FP_HINTID_BMP_TEST(fc->hintid_bmp, hint_id)) {
  39178             hint_count = 0;
  39179 
  39180             BCM_IF_ERROR_RETURN(_field_hints_control_get(unit, hint_id, &f_ht));
  39181             if (f_ht == NULL) {
  39182                 LOG_DEBUG(BSL_LS_BCM_FP,
  39183                         (BSL_META_U(unit,"FP (unit %d) HintId %d not present"
  39184                                    " in Hint Hash table\r\n"), unit, hint_id));
  39185                 continue;
  39186             }
  39187 
  39188             /* Sync Hint Id */
  39189             LOG_DEBUG(BSL_LS_BCM_FP,
  39190                     (BSL_META_U(unit,"@Pos(%d) Syncing hints information"
  39191                            " for Hint ID (%d)\r\n"), fc->scache_pos, hint_id));
  39192             sal_memcpy (curr_scache_ptr, &(f_ht->hintid),
  39193                                         sizeof(bcm_field_hintid_t));
  39194             fc->scache_pos += sizeof (bcm_field_hintid_t);
  39195             curr_scache_ptr += sizeof (bcm_field_hintid_t);
  39196 
  39197             /* Sync Hints Count */
  39198             LOG_DEBUG(BSL_LS_BCM_FP,
  39199                     (BSL_META_U(unit,"@Pos(%d) Syncing number of Hints"
  39200                                 "present = %d\r\n"),
  39201                                  fc->scache_pos, f_ht->hint_count));
  39202             sal_memcpy (curr_scache_ptr, &(f_ht->hint_count), sizeof(uint16));
  39203             fc->scache_pos += sizeof (uint16);
  39204             curr_scache_ptr += sizeof (uint16);
  39205 
  39206             /* Group ref Count will be updated when group is recovered.
  39207              * Hence no need to sync group refCount */
  39208 
  39209             hints_dump = f_ht->hints;
  39210 
  39211             while (hints_dump != NULL) {
  39212                 hint_entry = hints_dump->hint;
  39213                 if (hint_entry != NULL) {
  39214                     LOG_DEBUG(BSL_LS_BCM_FP,
  39215                             (BSL_META_U(unit,"@Pos(%d) HintId(%d) Syncing"
  39216                                       "HintType = %d\r\n"), fc->scache_pos,
  39217                                             hint_id, hint_entry->hint_type));
  39218                     sal_memcpy (curr_scache_ptr, &(hint_entry->hint_type),
  39219                                               sizeof(bcm_field_hint_type_t));
  39220                     fc->scache_pos += sizeof (bcm_field_hint_type_t);
  39221                     curr_scache_ptr += sizeof (bcm_field_hint_type_t);
  39222 
  39223                     LOG_DEBUG(BSL_LS_BCM_FP,
  39224                             (BSL_META_U(unit,"@Pos(%d) HintId(%d) Syncing"
  39225                                         " Flags = %d\r\n"), fc->scache_pos,
  39226                                                 hint_id, hint_entry->flags));
  39227                     sal_memcpy (curr_scache_ptr, &(hint_entry->flags),
  39228                                               sizeof(uint32));
  39229                     fc->scache_pos += sizeof (uint32);
  39230                     curr_scache_ptr += sizeof (uint32);
  39231 
  39232                     LOG_DEBUG(BSL_LS_BCM_FP,
  39233                             (BSL_META_U(unit,"@Pos(%d) HintId(%d) Sync Max"
  39234                                         " Group Size = %d\r\n"), fc->scache_pos,
  39235                              hint_id, hint_entry->max_group_size));
  39236                     sal_memcpy (curr_scache_ptr, &(hint_entry->max_group_size),
  39237                                               sizeof(uint32));
  39238                     fc->scache_pos += sizeof (uint32);
  39239                     curr_scache_ptr += sizeof (uint32);
  39240                 }
  39241                 hint_count++;
  39242                 hints_dump = hints_dump->next;
  39243             }
  39244             LOG_DEBUG(BSL_LS_BCM_FP,
  39245                     (BSL_META_U(unit, "HintId(%d) Number of hints synced (%d)"
  39246                                 " and Number of hints present (%d)\r\n"),
  39247                                        hint_id, hint_count,f_ht->hint_count));
  39248         }
  39249     }
  39250     return BCM_E_NONE;
  39251 }
  39252 
  39253 /* Function: _bcm_field_hints_scache_recover
  39254  *
  39255  * Purpose:
  39256  *        Recover hints Hash table information from scache
  39257  * Parameters:
  39258  *         unit      - (IN)    BCM device number.
  39259  *           fc      - (IN)    Field Control.
  39260  *     stage_fc      - (IN)    Stage Control.
  39261  *     scache_ptr    - (INOUT) Scache Pointer.
  39262  * Returns:
  39263  *      BCM_E_XXXX.
  39264  */
  39265 int _bcm_field_hints_scache_recover (int unit,
  39266                                      _field_control_t *fc,
  39267                                      _field_stage_t   *stage_fc,
  39268                                      uint8 *scache_ptr)
  39269 {
  39270     bcm_field_hintid_t     hint_id = 0;    /* Hint Id */
  39271     bcm_field_hint_t       hint_entry;     /* Hint Entry */
  39272     uint16                 hint_count = 0; /* Hint Count */
  39273     int                    count = 0;      /* Counter */
  39274     uint8 *curr_scache_ptr = scache_ptr;
  39275 
  39276     if ((fc == NULL) || (stage_fc == NULL) || (scache_ptr == NULL)) {
  39277         return BCM_E_PARAM;
  39278     }
  39279 
  39280     /* Sync hintid bitmap into scache */
  39281     sal_memcpy (fc->hintid_bmp.w, curr_scache_ptr,
  39282                     SHR_BITALLOCSIZE(_FP_HINT_ID_MAX));
  39283     fc->scache_pos += SHR_BITALLOCSIZE(_FP_HINT_ID_MAX);
  39284     curr_scache_ptr += SHR_BITALLOCSIZE(_FP_HINT_ID_MAX);
  39285 
  39286     for (hint_id = _FP_HINT_ID_BASE; hint_id < _FP_HINT_ID_MAX; hint_id++) {
  39287         if (_FP_HINTID_BMP_TEST(fc->hintid_bmp, hint_id)) {
  39288             /* Recover Hint Id */
  39289             sal_memcpy (&hint_id, curr_scache_ptr,
  39290                                      sizeof(bcm_field_hintid_t));
  39291             LOG_DEBUG(BSL_LS_BCM_FP,
  39292                     (BSL_META_U(unit,"@Pos(%d) Recovered hints information"
  39293                                 " for Hint ID (%d)\r\n"),
  39294                                       fc->scache_pos, hint_id));
  39295             fc->scache_pos += sizeof (bcm_field_hintid_t);
  39296             curr_scache_ptr += sizeof (bcm_field_hintid_t);
  39297 
  39298             /* Recover Hints Count */
  39299             sal_memcpy (&hint_count, curr_scache_ptr, sizeof(uint16));
  39300             LOG_DEBUG(BSL_LS_BCM_FP,
  39301                     (BSL_META_U(unit,"@Pos(%d) Recovered number of Hints"
  39302                            " present = %d\r\n"), fc->scache_pos, hint_count));
  39303             fc->scache_pos += sizeof (uint16);
  39304             curr_scache_ptr += sizeof (uint16);
  39305 
  39306             for (count = 0; count < hint_count; count++) {
  39307                 sal_memset (&hint_entry, 0, sizeof (bcm_field_hint_t));
  39308                 sal_memcpy (&(hint_entry.hint_type), curr_scache_ptr,
  39309                         sizeof(bcm_field_hint_type_t));
  39310                 LOG_DEBUG(BSL_LS_BCM_FP,
  39311                         (BSL_META_U(unit,"@Pos(%d) HintId(%d) Recovered"
  39312                                     " HintType = %d\r\n"), fc->scache_pos,
  39313                                              hint_id, hint_entry.hint_type));
  39314                 fc->scache_pos += sizeof (bcm_field_hint_type_t);
  39315                 curr_scache_ptr += sizeof (bcm_field_hint_type_t);
  39316 
  39317                 sal_memcpy (&(hint_entry.flags), curr_scache_ptr,
  39318                         sizeof(uint32));
  39319                 LOG_DEBUG(BSL_LS_BCM_FP,
  39320                         (BSL_META_U(unit,"@Pos(%d) HintId(%d) Recovered"
  39321                                     " Flags = %d\r\n"), fc->scache_pos,
  39322                                               hint_id, hint_entry.flags));
  39323                 fc->scache_pos += sizeof (uint32);
  39324                 curr_scache_ptr += sizeof (uint32);
  39325 
  39326                 sal_memcpy (&(hint_entry.max_group_size), curr_scache_ptr,
  39327                         sizeof(uint32));
  39328                 LOG_DEBUG(BSL_LS_BCM_FP,
  39329                         (BSL_META_U(unit,"@Pos(%d) HintId(%d) Recovered"
  39330                                    " Max Group Size = %d\r\n"), fc->scache_pos,
  39331                                     hint_id, hint_entry.max_group_size));
  39332                 fc->scache_pos += sizeof (uint32);
  39333                 curr_scache_ptr += sizeof (uint32);
  39334 
  39335                 BCM_IF_ERROR_RETURN (bcm_esw_field_hints_add (unit, hint_id,
  39336                             &hint_entry));
  39337             }
  39338         }
  39339     }
  39340     return BCM_E_NONE;
  39341 }
  39342 
  39343 /* Function: _bcm_hints_scache_hintid_sync
  39344  *
  39345  * Purpose:
  39346  *        Sync the hint id associated with the group.
  39347  * Parameters:
  39348  *     unit      - (IN) BCM device number.
  39349  *     uint8     - (IN) Scache_ptr
  39350  * Returns:
  39351  *      BCM_E_XXXX.
  39352  */
  39353 int _bcm_hints_scache_hintid_sync (int unit, _field_stage_t *stage_fc,
  39354                                       uint8 *scache_ptr)
  39355 {
  39356     _field_control_t    *fc;             /* Field control structure. */
  39357     _field_group_t      *fg;             /* Field group info.        */
  39358     uint8 *curr_scache_ptr = scache_ptr; /* Scache Pointer */
  39359 
  39360     if (scache_ptr == NULL) {
  39361         return BCM_E_PARAM;
  39362     }
  39363 
  39364     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  39365 
  39366     fg = fc->groups;
  39367     if (NULL == fg) {
  39368         return (BCM_E_NONE);
  39369     }
  39370 
  39371     for (; fg != NULL; fg = fg->next) {
  39372         if (fg->stage_id == _BCM_FIELD_STAGE_INGRESS ||
  39373               fg->stage_id == _BCM_FIELD_STAGE_EGRESS ||
  39374               fg->stage_id == _BCM_FIELD_STAGE_LOOKUP) {
  39375 
  39376             if(stage_fc->stage_id == fg->stage_id) {
  39377                 sal_memcpy (curr_scache_ptr, &(fg->gid),
  39378                         sizeof(bcm_field_group_t));
  39379                 fc->scache_pos += sizeof (bcm_field_group_t);
  39380                 curr_scache_ptr += sizeof (bcm_field_group_t);
  39381 
  39382                 sal_memcpy (curr_scache_ptr, &(fg->hintid),
  39383                         sizeof(bcm_field_hintid_t));
  39384                 fc->scache_pos += sizeof (bcm_field_hintid_t);
  39385                 curr_scache_ptr += sizeof (bcm_field_hintid_t);
  39386             }
  39387         }
  39388     }
  39389 
  39390     return BCM_E_NONE;
  39391 }
  39392 
  39393 /* Function: _bcm_hints_scache_hintid_recover
  39394  *
  39395  * Purpose:
  39396  *        Recover the hint id associated with the group.
  39397  * Parameters:
  39398  *         unit - (IN) BCM device number.
  39399  *           fc - (IN) Field Control.
  39400  *   scache_ptr - (IN) Scache Pointer.
  39401  * Returns:
  39402  *      BCM_E_XXXX.
  39403  */
  39404 int _bcm_hints_scache_hintid_recover (int unit,
  39405                                       _field_stage_t *stage_fc,
  39406                                       _field_control_t *fc,
  39407                                       uint8 *scache_ptr)
  39408 {
  39409     uint8 *curr_scache_ptr = scache_ptr; /* Scache Pointer */
  39410     _field_group_t *fg_entry = NULL;     /* Field Group Entry */
  39411     _field_group_t *fg = NULL;           /* Field Group Entry */
  39412     bcm_field_group_t gid = 0;           /* Group Id */
  39413 
  39414     if ((scache_ptr == NULL) || (fc == NULL)) {
  39415         return BCM_E_PARAM;
  39416     }
  39417 
  39418     fg = fc->groups;
  39419 
  39420     while (fg != NULL) {
  39421         if (fg->stage_id == _BCM_FIELD_STAGE_INGRESS ||
  39422                fg->stage_id == _BCM_FIELD_STAGE_EGRESS ||
  39423                fg->stage_id == _BCM_FIELD_STAGE_LOOKUP) {
  39424             if(stage_fc->stage_id == fg->stage_id) {
  39425 
  39426                  sal_memcpy (&gid, curr_scache_ptr,
  39427                         sizeof (bcm_field_group_t));
  39428                 fc->scache_pos += sizeof (bcm_field_group_t);
  39429                 curr_scache_ptr += sizeof (bcm_field_group_t);
  39430 
  39431                 BCM_IF_ERROR_RETURN(_field_group_get(unit, gid, &fg_entry));
  39432                 if (!(fg_entry->stage_id == _BCM_FIELD_STAGE_INGRESS ||
  39433                         fg_entry->stage_id == _BCM_FIELD_STAGE_EGRESS ||
  39434                         fg_entry->stage_id == _BCM_FIELD_STAGE_LOOKUP)) {
  39435                     return BCM_E_INTERNAL;
  39436                 }
  39437 
  39438                 sal_memcpy ( &(fg_entry->hintid),curr_scache_ptr,
  39439                         sizeof(bcm_field_hintid_t));
  39440                 fc->scache_pos += sizeof (bcm_field_hintid_t);
  39441                 curr_scache_ptr += sizeof (bcm_field_hintid_t);
  39442 
  39443                 /* Group has been created, Increment group ref count in
  39444                  * corresponding hintid in hints hash lookup table */
  39445                 BCM_IF_ERROR_RETURN(_bcm_field_hints_group_count_update
  39446                         (unit, fg_entry->hintid, 1));
  39447                 BCM_IF_ERROR_RETURN(_bcm_field_hints_group_info_update(
  39448                                          unit, fg_entry));
  39449             }
  39450 
  39451         }
  39452         fg = fg->next;
  39453     }
  39454 
  39455     return BCM_E_NONE;
  39456 }
  39457 
  39458 #endif /* BCM_WARM_BOOT_SUPPORT */
  39459 /* Function: _bcm_field_hints_group_info_update
  39460  *
  39461  * Purpose:
  39462  *       During Group creation, update group structure with the
  39463  *       data from the hintid
  39464  * Parameters:
  39465  *     unit      - (IN) BCM device number.
  39466  *       fg      - (INOUT) Field Group Structure.
  39467  * Returns:
  39468  *      BCM_E_XXXX.
  39469  */
  39470 int _bcm_field_hints_group_info_update (int unit,
  39471                                         _field_group_t *fg)
  39472 {
  39473     _field_hints_t     *f_ht = NULL;      /* Field hints Structure. */
  39474     bcm_field_hint_t   *hint_entry;       /* Hint Entry. */
  39475     _field_hint_t      *hint_list = NULL; /* Field Hints Structure. */
  39476 
  39477     if (NULL == fg) {
  39478         return BCM_E_PARAM;
  39479     }
  39480 
  39481     if (fg->hintid == 0) {
  39482         LOG_DEBUG(BSL_LS_BCM_FP,
  39483                 (BSL_META_U(unit,"Hints not configured. Hence no need"
  39484                             " to update\r\n")));
  39485         return BCM_E_NONE;
  39486     }
  39487 
  39488 
  39489 
  39490     BCM_IF_ERROR_RETURN(_field_hints_control_get (unit, fg->hintid, &f_ht));
  39491     if (f_ht == NULL) {
  39492         return (BCM_E_NOT_FOUND);
  39493     }
  39494 
  39495     hint_list = f_ht->hints;
  39496 
  39497     while (hint_list != NULL) {
  39498         hint_entry = hint_list->hint;
  39499         if (hint_entry != NULL) {
  39500             /* Hint Found */
  39501             LOG_DEBUG(BSL_LS_BCM_FP,
  39502                     (BSL_META_U(unit, "Updating Group"
  39503                        " Structure from hints in hintid %d\r\n"), fg->hintid));
  39504             switch (hint_entry->hint_type) {
  39505                 case bcmFieldHintTypeCompression:
  39506                     /* Fill Flags, max_values, start_bit, end_bit */
  39507                     break;
  39508                 case bcmFieldHintTypeExtraction:
  39509                     /* Fill Flags, max_values, start_bit, end_bit */
  39510                     break;
  39511                 case bcmFieldHintTypeGroupAutoExpansion:
  39512                     /* Fill Flags, max_group_size */
  39513                     if ((hint_entry->flags & BCM_FIELD_GROUP_AUTO_EXPANSION_SMALL)
  39514                         && (hint_entry->flags & BCM_FIELD_GROUP_AUTO_EXPANSION_LARGE)) {
  39515                         LOG_ERROR(BSL_LS_BCM_FP,
  39516                                 (BSL_META_U(unit,
  39517                                       "Group(%d) hint flags have"
  39518                                         "both SMALL and LARGE\r\n"),fg->gid));
  39519                         return BCM_E_PARAM;
  39520                     }
  39521                     if (hint_entry->flags &
  39522                             BCM_FIELD_GROUP_AUTO_EXPANSION_SMALL) {
  39523                         fg->flags |= _FP_GROUP_AUTO_EXPAND_SMALL_SLICE;
  39524                         LOG_DEBUG(BSL_LS_BCM_FP,
  39525                                 (BSL_META_U(unit,
  39526                                       "Updating Group(%d) Structure flag with "
  39527                                         "AutoExpandSmall \r\n"),fg->gid));
  39528                     }
  39529                     if (hint_entry->flags &
  39530                             BCM_FIELD_GROUP_AUTO_EXPANSION_LARGE) {
  39531                         fg->flags |= _FP_GROUP_AUTO_EXPAND_LARGE_SLICE;
  39532                         LOG_DEBUG(BSL_LS_BCM_FP,
  39533                                 (BSL_META_U(unit,"Updating"
  39534                                         " Group(%d) Structure flag with "
  39535                                             "AutoExpandLarge\r\n"), fg->gid));
  39536                     }
  39537                     if (hint_entry->flags &
  39538                             BCM_FIELD_GROUP_MAX_SIZE_HARD_LIMIT) {
  39539                         fg->flags |= _FP_GROUP_MAX_SIZE_HARD_LIMIT;
  39540                         LOG_DEBUG(BSL_LS_BCM_FP,
  39541                                 (BSL_META_U(unit, "Updating Group(%d) "
  39542                                             " Structure flag with MaxGroupSize"
  39543                                             " hardLimit \r\n"),fg->gid));
  39544                     }
  39545                     fg->max_group_size = hint_entry->max_group_size;
  39546 
  39547                     LOG_DEBUG(BSL_LS_BCM_FP,
  39548                             (BSL_META_U(unit,"Updating Group(%d) Structure"
  39549                                         " flag with MaxGroupSize %u \r\n"),
  39550                              fg->gid, fg->max_group_size));
  39551                     break;
  39552                 case bcmFieldHintTypeExactMatch:
  39553 #ifdef BCM_TOMAHAWK_SUPPORT
  39554                     if (hint_entry->flags &
  39555                         BCM_FIELD_HINT_EXACT_MATCH_GROUP_PRIORITY) {
  39556                         if (soc_feature(unit,
  39557                                 soc_feature_field_exact_match_support)) {
  39558                             _field_th_em_group_priority_hintbased_qset_update(
  39559                                                          unit, fg, hint_entry);
  39560                         }
  39561                     }
  39562 #endif
  39563                     break;
  39564                 default:
  39565                     LOG_DEBUG(BSL_LS_BCM_FP,
  39566                             (BSL_META_U(unit,"Unknown Hint Type\r\n")));
  39567                     return BCM_E_PARAM;
  39568                     break;
  39569             }
  39570         }
  39571         hint_list = hint_list->next;
  39572     }
  39573 
  39574     return BCM_E_NONE;
  39575 }
  39576 
  39577 /* Function: _bcm_field_hints_group_count_update
  39578  *
  39579  * Purpose:
  39580  *          When a group is created associating with a hint_id,
  39581  *          increment the refCount in the hint_id for the group.
  39582  *          Similary decrement the refCount when a group is destroyed.
  39583  * Parameters:
  39584  *     unit      - (IN) BCM device number.
  39585  *     hint_id    - (IN) Hint Id.
  39586  *     action    - (IN) Increment/Decrement.
  39587  * Returns:
  39588  *      BCM_E_XXXX.
  39589  */
  39590 int _bcm_field_hints_group_count_update (int unit,
  39591                                      bcm_field_hintid_t hint_id,
  39592                                      uint8 action)
  39593 {
  39594     _field_hints_t  *f_ht = NULL; /* Field hints Structure. */
  39595 
  39596     if (hint_id == 0) {
  39597         LOG_DEBUG(BSL_LS_BCM_FP,
  39598                 (BSL_META_U(unit,"Hints not configured. Hence no need"
  39599                             " to update\r\n")));
  39600         return BCM_E_NONE;
  39601     }
  39602 
  39603 
  39604 
  39605     BCM_IF_ERROR_RETURN(_field_hints_control_get (unit, hint_id, &f_ht));
  39606     if (f_ht == NULL) {
  39607         return (BCM_E_NOT_FOUND);
  39608     }
  39609 
  39610     if (action) {
  39611         f_ht->grp_ref_count++;
  39612         LOG_DEBUG(BSL_LS_BCM_FP,
  39613                 (BSL_META_U(unit,"New Group Attached to hintid %d,"
  39614                            " Group cnt %d\r\n"), hint_id,f_ht->grp_ref_count));
  39615     } else {
  39616         if (f_ht->grp_ref_count > 0) {
  39617             f_ht->grp_ref_count--;
  39618             LOG_DEBUG(BSL_LS_BCM_FP,
  39619                     (BSL_META_U(unit, "Group detached from hintid %d,"
  39620                            " Group cnt %d\r\n"), hint_id,f_ht->grp_ref_count));
  39621         }
  39622     }
  39623 
  39624     return BCM_E_NONE;
  39625 }
  39626 
  39627 /*
  39628  * Function:
  39629  *     _field_hints_id_alloc
  39630  * Purpose:
  39631  *      Allocate a hint id.
  39632  * Parameters:
  39633  *      unit    - (IN) BCM device number.
  39634  *      hint_id - (OUT) Hint id.
  39635  * Returns:
  39636  *      BCM_E_XXX
  39637  * Notes:
  39638  */
  39639 int _field_hints_id_alloc (int unit, bcm_field_hintid_t *hint_id)
  39640 {
  39641     _field_control_t *fc;   /* Field control structure.*/
  39642     uint32  hint_iter = 0;  /* Hint Id */
  39643 
  39644     /* Input parameters check. */
  39645     if (NULL == hint_id) {
  39646         return (BCM_E_PARAM);
  39647     }
  39648 
  39649     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  39650 
  39651     for (hint_iter = _FP_HINT_ID_BASE;
  39652             hint_iter < _FP_HINT_ID_MAX; hint_iter++) {
  39653         if (_FP_HINTID_BMP_TEST((fc->hintid_bmp), hint_iter) == 0) {
  39654             *hint_id = hint_iter;
  39655             return (BCM_E_NONE);
  39656         }
  39657     }
  39658     return (BCM_E_RESOURCE);
  39659 }
  39660 
  39661 
  39662 /* Function: _bcm_field_hints_add
  39663  *
  39664  * Purpose:
  39665  *     Associate hint to hint id.
  39666  * Parameters:
  39667  *     unit    - (IN) BCM device number.
  39668  *     hint_id - (IN) Hint id to which the hint should be associated
  39669  *     hint    - (IN) bcm_field_hint_t structure
  39670  * Returns:
  39671  *     BCM_E_XXXX.
  39672  */
  39673  int _bcm_field_hints_add (int unit,
  39674                         bcm_field_hintid_t hint_id,
  39675                         bcm_field_hint_t *hint)
  39676 {
  39677     _field_hints_t    *f_ht = NULL;        /* Field hints Structure. */
  39678     _field_hints_t    *f_ht_new = NULL;    /* Field hints Structure. */
  39679     _field_hint_t     *hint_entry = NULL;  /* Field hints Structure. */
  39680     _field_hint_t     *hint_node = NULL;   /* Field hints Structure. */
  39681     bcm_field_hint_t  tmp_hint;            /* Hint Node */
  39682     _field_control_t  *fc;                 /* Field control structure. */
  39683     int                rv = BCM_E_NONE;    /* Return Value */
  39684 
  39685     /* Input parameters check. */
  39686     if (hint == NULL) {
  39687         return BCM_E_PARAM;
  39688     }
  39689 
  39690     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  39691 
  39692     /* Check if the hint_id is already present in the hash table,
  39693      * if so, see if a group is attached to the hintid or the hint
  39694      * is already present in the hintid. */
  39695     BCM_IF_ERROR_RETURN(_field_hints_control_get (unit, hint_id, &f_ht));
  39696 
  39697     /* Hint id already present in Hints hash table */
  39698     if (f_ht != NULL) {
  39699         LOG_DEBUG(BSL_LS_BCM_FP,
  39700                 (BSL_META_U(unit,"FP(unit %d) hint id %d already present in"
  39701                             " hash table\r\n"), unit, hint_id));
  39702         /* Check if hint_id is already associated with a group */
  39703         if (f_ht->grp_ref_count != 0) {
  39704             LOG_DEBUG(BSL_LS_BCM_FP,
  39705                     (BSL_META_U(unit,"FP(unit %d) hint id %d already"
  39706                              " associated with a group \r\n"), unit, hint_id));
  39707             return BCM_E_BUSY;
  39708         }
  39709 
  39710         /* Check if max hint count per hintid reached */
  39711         if (f_ht->hint_count >= _FP_MAX_HINTS_PER_HINTID) {
  39712             LOG_DEBUG(BSL_LS_BCM_FP,
  39713                     (BSL_META_U(unit, "FP(unit %d) Maximum hints limit reached"
  39714                                 " for hintid %d\r\n"), unit, hint_id));
  39715             return BCM_E_FULL;
  39716         }
  39717 
  39718         /* Check if duplicate hint exists */
  39719         sal_memcpy (&tmp_hint, hint, sizeof (bcm_field_hint_t));
  39720         rv = _bcm_field_hints_node_get (unit, f_ht->hints,
  39721                                             &tmp_hint, &hint_node);
  39722 
  39723         if ((rv == BCM_E_NONE) && (hint_node != NULL)) {
  39724             if (bcmFieldHintTypeExtraction != hint_node->hint->hint_type) {
  39725                 LOG_DEBUG(BSL_LS_BCM_FP,
  39726                     (BSL_META_U(unit, "FP(unit %d) Duplicate hint addition to "
  39727                                 "hint id %d\r\n"), unit, hint_id));
  39728                 return BCM_E_EXISTS;
  39729             }
  39730         }
  39731     } else {
  39732         _FP_XGS3_ALLOC (f_ht_new, sizeof (_field_hints_t), "Field Hints");
  39733         if (NULL == f_ht_new) {
  39734             return BCM_E_MEMORY;
  39735         }
  39736         f_ht_new->hintid = hint_id;
  39737         f_ht_new->grp_ref_count = 0;
  39738         f_ht_new->next = NULL;
  39739     }
  39740 
  39741     /* Allocate a Hint Entry and add the hint into hint_entry */
  39742     _FP_XGS3_ALLOC (hint_entry, sizeof (_field_hint_t),
  39743             "Field Hint Entry Structure");
  39744     if (NULL == hint_entry) {
  39745         sal_free (f_ht_new);
  39746         return BCM_E_MEMORY;
  39747     }
  39748 
  39749     /* Allocate a Hint Entry and add the hint into hint_entry */
  39750     _FP_XGS3_ALLOC (hint_entry->hint, sizeof (bcm_field_hint_t),
  39751             "Field Hint Entry");
  39752     if (NULL == hint_entry->hint) {
  39753         sal_free (hint_entry);
  39754         sal_free (f_ht_new);
  39755         return BCM_E_MEMORY;
  39756     }
  39757 
  39758     sal_memcpy (hint_entry->hint, hint, sizeof (bcm_field_hint_t));
  39759     hint_entry->next = NULL;
  39760 
  39761     /* If entry is newly allocated add it to hash database */
  39762     if (f_ht_new != NULL) {
  39763         /* Insert hint_id into Hash table. */
  39764         _FP_HASH_INSERT(fc->hints_hash, f_ht_new,
  39765                 (hint_id & _FP_HASH_INDEX_MASK(fc)));
  39766 
  39767         LOG_DEBUG(BSL_LS_BCM_FP,
  39768                 (BSL_META_U(unit,"FP(unit %d) HintId added to hash"
  39769                             " table %d\r\n"), unit, hint_id));
  39770         f_ht = f_ht_new;
  39771     }
  39772 
  39773     _FP_HINTS_LINKLIST_INSERT(&(f_ht->hints),hint_entry);
  39774     LOG_DEBUG(BSL_LS_BCM_FP,
  39775                                 (BSL_META_U(unit, "FP(unit %d) Hint added to"
  39776                                             " hint id %d\r\n"), unit, hint_id));
  39777     f_ht->hint_count++;
  39778 
  39779     return BCM_E_NONE;
  39780 }
  39781 
  39782 
  39783 /* Function: _bcm_field_hints_node_get
  39784  *
  39785  * Purpose:
  39786  *    Return complete hint structure after passing partial structure
  39787  *    and return the hint_node present in the hint list.
  39788  * Parameters:
  39789  *     unit      - (IN) BCM device number.
  39790  *     hint_list - (IN) Linked List of hints attached to a hint id.
  39791  *     hint      - (INOUT) bcm_field_hint_t structure
  39792  *     hint_node - (OUT) Node that matches the hint structure.
  39793  * Returns:
  39794  *      BCM_E_XXXX.
  39795  */
  39796 int _bcm_field_hints_node_get (int unit,
  39797                             _field_hint_t *hint_list,
  39798                             bcm_field_hint_t *hint,
  39799                             _field_hint_t **hint_node)
  39800 {
  39801     bcm_field_hint_t       *hint_entry; /* Hint Entry */
  39802 
  39803     /* Input Parameter Check */
  39804     if ((hint_list == NULL) || (hint == NULL)) {
  39805         return BCM_E_PARAM;
  39806     }
  39807 
  39808     /* Loop through the hints and search for a match,
  39809      * if found, fill the entire hint and also return the hint_node
  39810      * that matched */
  39811     while (hint_list != NULL) {
  39812         hint_entry = hint_list->hint;
  39813         if (hint_entry != NULL) {
  39814             if (hint_entry->hint_type == hint->hint_type) {
  39815                 /* Hint Found */
  39816                 switch (hint_entry->hint_type) {
  39817                     case bcmFieldHintTypeCompression:
  39818                         if (hint_entry->qual == hint->qual) {
  39819                             LOG_DEBUG(BSL_LS_BCM_FP,
  39820                                     (BSL_META_U(unit, "FP(unit %d) Hint with"
  39821                                                 " type = Compression and "
  39822                                                 " qual_id %d found\r\n"),
  39823                                      unit, hint->qual));
  39824                             *hint_node = hint_list;
  39825                             /* Fill Flags, max_values, start_bit, end_bit */
  39826                             hint->flags = hint_entry->flags;
  39827                             hint->max_values = hint_entry->max_values;
  39828                             hint->start_bit = hint_entry->start_bit;
  39829                             hint->end_bit = hint_entry->end_bit;
  39830                             return BCM_E_NONE;
  39831                         }
  39832                         break;
  39833                     case bcmFieldHintTypeExtraction:
  39834                         if (hint_entry->qual == hint->qual) {
  39835                             LOG_DEBUG(BSL_LS_BCM_FP,
  39836                                     (BSL_META_U(unit, "FP(unit %d) Hint with"
  39837                                                 " type = Extraction and "
  39838                                                 " qual_id %d found\r\n"),
  39839                                      unit, hint->qual));
  39840                             *hint_node = hint_list;
  39841                             /* Fill Flags, max_values, start_bit, end_bit */
  39842                             hint->flags = hint_entry->flags;
  39843                             hint->max_values = hint_entry->max_values;
  39844                             hint->start_bit = hint_entry->start_bit;
  39845                             hint->end_bit = hint_entry->end_bit;
  39846                             return BCM_E_NONE;
  39847                         }
  39848                         break;
  39849                     case bcmFieldHintTypeGroupAutoExpansion:
  39850                         {
  39851                             LOG_DEBUG(BSL_LS_BCM_FP,
  39852                                     (BSL_META_U(unit, "FP(unit %d) Hint with"
  39853                                                 " type = GroupAutoExpansion "
  39854                                                 " found\r\n"), unit));
  39855                             *hint_node = hint_list;
  39856                             /* Fill Flags, max_group_size */
  39857                             hint->flags = hint_entry->flags;
  39858                             hint->max_group_size = hint_entry->max_group_size;
  39859                             return BCM_E_NONE;
  39860                         }
  39861                         break;
  39862                     case bcmFieldHintTypeExactMatch:
  39863                         if (hint_entry->qual == hint->qual) {
  39864                             LOG_DEBUG(BSL_LS_BCM_FP,
  39865                                     (BSL_META_U(unit, "FP(unit %d) Hint with"
  39866                                                 " type = Exact Match and "
  39867                                                 " found\r\n"), unit));
  39868                             *hint_node = hint_list;
  39869                             /* Fill Flags, Priority and Qualifier details. */
  39870                             hint->flags = hint_entry->flags;
  39871                             hint->priority = hint_entry->priority;
  39872                             return BCM_E_NONE;
  39873                         }
  39874                         break;
  39875                     default:
  39876                         {
  39877                             LOG_DEBUG(BSL_LS_BCM_FP,
  39878                                     (BSL_META_U(unit, "Unknown Hint Type\r\n")));
  39879                             return BCM_E_PARAM;
  39880                         }
  39881                         break;
  39882                 }
  39883             }
  39884         }
  39885         hint_list = hint_list->next;
  39886     }
  39887     return BCM_E_NOT_FOUND;
  39888 }
  39889 
  39890 /* Function: _bcm_field_hints_get
  39891  *
  39892  * Purpose:
  39893  *    Return complete hint structure after passing partial structure
  39894  * Parameters:
  39895  *     unit    - (IN) BCM device number.
  39896  *     hint_id - (IN) Hint id to which the hint should be associated
  39897  *     hint    - (INOUT) bcm_field_hint_t structure
  39898  * Returns:
  39899  *      BCM_E_XXXX.
  39900  */
  39901 int _bcm_field_hints_get(int unit,
  39902                          bcm_field_hintid_t hint_id,
  39903                          bcm_field_hint_t *hint)
  39904 {
  39905     _field_hints_t        *f_ht = NULL;      /* Field hints Structure. */
  39906     _field_hint_t         *hint_node = NULL; /* Field hints Structure. */
  39907 
  39908 
  39909     /* Input parameters check. */
  39910     if (hint == NULL) {
  39911         return BCM_E_PARAM;
  39912     }
  39913 
  39914 
  39915 
  39916     BCM_IF_ERROR_RETURN(_field_hints_control_get (unit, hint_id, &f_ht));
  39917     if (f_ht == NULL) {
  39918         LOG_DEBUG(BSL_LS_BCM_FP,
  39919                 (BSL_META_U(unit,"FP(unit %d) Hint id %d not present "
  39920                             "in Hints Hash table.\r\n"), unit, hint_id));
  39921         return (BCM_E_NOT_FOUND);
  39922     }
  39923 
  39924     /* Hints corresponding to hint_id not found */
  39925     if (f_ht->hints == NULL) {
  39926         LOG_DEBUG(BSL_LS_BCM_FP,
  39927                 (BSL_META_U(unit, "FP(unit %d) No Hints are associated with "
  39928                             "hint id %d\r\n"), unit, hint_id));
  39929         return (BCM_E_NOT_FOUND);
  39930     }
  39931 
  39932     return _bcm_field_hints_node_get (unit, f_ht->hints, hint, &hint_node);
  39933 }
  39934 
  39935 
  39936 /* Function: _bcm_field_hints_delete
  39937  *
  39938  * Purpose:
  39939  *     Delete bcm_field_hint_t structure from a hint_id
  39940  * Parameters:
  39941  *     unit      - (IN) BCM device number.
  39942  *     hint_id   - (IN) Hint Id.
  39943  *     hint      - (IN) Hint to delete.
  39944  * Returns:
  39945  *      BCM_E_XXXX.
  39946  */
  39947 
  39948 int _bcm_field_hints_delete (int unit,
  39949                              bcm_field_hintid_t hint_id,
  39950                              bcm_field_hint_t *hint)
  39951 {
  39952     _field_hints_t        *f_ht = NULL;      /* Field hints Structure. */
  39953     _field_hint_t         *hint_node = NULL; /* Field hints Structure. */
  39954     _field_control_t      *fc;               /* Field control structure. */
  39955 
  39956     /* Input parameters check. */
  39957     if (hint == NULL) {
  39958         return BCM_E_PARAM;
  39959     }
  39960 
  39961     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  39962 
  39963     BCM_IF_ERROR_RETURN(_field_hints_control_get (unit, hint_id, &f_ht));
  39964     if (f_ht == NULL) {
  39965         LOG_DEBUG(BSL_LS_BCM_FP,
  39966                 (BSL_META_U(unit, "FP (unit %d) HintId %d not present in"
  39967                             " hints hash table\r\n"), unit, hint_id));
  39968         return (BCM_E_NOT_FOUND);
  39969     }
  39970 
  39971     /* HintId is attached to a group. Hence deletion not allowed */
  39972     if (f_ht->grp_ref_count != 0) {
  39973         LOG_DEBUG(BSL_LS_BCM_FP,
  39974                 (BSL_META_U(unit, "FP (unit %d) Group is associated "
  39975                             " with HintId %d\r\n"), unit, hint_id));
  39976         return BCM_E_BUSY;
  39977     }
  39978 
  39979     /* Hints corresponding to hint_id not found */
  39980     if (f_ht->hints == NULL) {
  39981         LOG_DEBUG(BSL_LS_BCM_FP,
  39982                 (BSL_META_U(unit, "FP (unit %d) No hints are present in"
  39983                             " HintId %d\r\n"), unit, hint_id));
  39984         return (BCM_E_NOT_FOUND);
  39985     }
  39986 
  39987     BCM_IF_ERROR_RETURN(_bcm_field_hints_node_get (unit, f_ht->hints,
  39988                        hint, &hint_node));
  39989 
  39990     _FP_HINTS_LINKLIST_DELETE (&(f_ht->hints), _field_hint_t, hint_node);
  39991 
  39992     if (f_ht->hint_count > 0) {
  39993         f_ht->hint_count--;
  39994     }
  39995 
  39996     if (f_ht->hint_count == 0) {
  39997         /* Remove hints for lookup hash. */
  39998         _FP_HASH_REMOVE(fc->hints_hash, _field_hints_t, f_ht,
  39999                 (hint_id & _FP_HASH_INDEX_MASK(fc)));
  40000         sal_free (f_ht);
  40001         f_ht = NULL;
  40002         LOG_DEBUG(BSL_LS_BCM_FP,
  40003                 (BSL_META_U(unit, "FP (unit %d) HintId %d destroyed from Hint "
  40004                             "hash table\r\n"), unit, hint_id));
  40005     }
  40006 
  40007     return BCM_E_NONE;
  40008 }
  40009 
  40010 
  40011 /* Function: _bcm_field_hints_delete_all
  40012  *
  40013  * Purpose:
  40014  *     Delete all hints from a hint_id
  40015  * Parameters:
  40016  *     unit    - (IN) BCM device number.
  40017  *     hint_id - (IN) Hint id to which the hint should be associated
  40018  * Returns:
  40019  *     BCM_E_XXXX.
  40020  */
  40021 int _bcm_field_hints_delete_all (int unit,
  40022                              bcm_field_hintid_t hint_id)
  40023 {
  40024     _field_hints_t        *f_ht = NULL; /* Field hints Structure.   */
  40025     _field_control_t      *fc;          /* Field control structure. */
  40026 
  40027     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  40028 
  40029     BCM_IF_ERROR_RETURN(_field_hints_control_get (unit, hint_id, &f_ht));
  40030     if (f_ht == NULL) {
  40031         LOG_DEBUG(BSL_LS_BCM_FP,
  40032                 (BSL_META_U(unit, "FP (unit %d) HintId %d not present in "
  40033                             "Hint Hash table\r\n"), unit, hint_id));
  40034         return (BCM_E_NOT_FOUND);
  40035     }
  40036 
  40037     /* HintId is attached to a group. Hence deletion not allowed */
  40038     if (f_ht->grp_ref_count != 0) {
  40039         LOG_DEBUG(BSL_LS_BCM_FP,
  40040                 (BSL_META_U(unit, "FP (unit %d) Group is associated with "
  40041                             " HintId %d\r\n"), unit, hint_id));
  40042         return BCM_E_BUSY;
  40043     }
  40044 
  40045     /* Hints corresponding to hint_id not found.
  40046      * delete_all should return BCM_E_NONE
  40047  */
  40048     if (f_ht->hints == NULL) {
  40049         LOG_DEBUG(BSL_LS_BCM_FP,
  40050                 (BSL_META_U(unit, "FP (unit %d) No Hints present "
  40051                             " in a hintid %d\r\n"), unit, hint_id));
  40052         return (BCM_E_NONE);
  40053     }
  40054 
  40055     _FP_HINTS_LINKLIST_DELETE_ALL (&(f_ht->hints), _field_hint_t);
  40056 
  40057     f_ht->hint_count = 0;
  40058 
  40059     /* Remove hints for lookup hash. */
  40060     _FP_HASH_REMOVE(fc->hints_hash, _field_hints_t, f_ht,
  40061             (hint_id & _FP_HASH_INDEX_MASK(fc)));
  40062     sal_free (f_ht);
  40063     f_ht = NULL;
  40064     LOG_DEBUG(BSL_LS_BCM_FP,
  40065             (BSL_META_U(unit, "FP (unit %d) HintId %d destroyed from Hint "
  40066                         " hash table\r\n"), unit, hint_id));
  40067 
  40068     return BCM_E_NONE;
  40069 }
  40070 
  40071 /* Function: _bcm_field_hints_dump
  40072  *
  40073  * Purpose:
  40074  *    Dump the hints database.
  40075  * Parameters:
  40076  *     unit - (IN) BCM device number.
  40077  * Returns:
  40078  *     BCM_E_XXXX.
  40079  */
  40080 int _bcm_field_hints_dump (int unit)
  40081 {
  40082     bcm_field_hintid_t id = 0; /* Hint Id */
  40083     _field_control_t    *fc;   /* Field control structure.*/
  40084 
  40085     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  40086 
  40087     for (id = _FP_HINT_ID_BASE; id < _FP_HINT_ID_MAX; id++) {
  40088         if (_FP_HINTID_BMP_TEST(fc->hintid_bmp, id)) {
  40089             LOG_DEBUG(BSL_LS_BCM_FP,
  40090                     (BSL_META_U(unit, "HINTID %d \r\n"), id));
  40091             LOG_DEBUG(BSL_LS_BCM_FP,
  40092                     (BSL_META_U(unit,"=========\r\n")));
  40093             _bcm_field_hints_display (unit, id);
  40094         }
  40095     }
  40096 
  40097     return BCM_E_NONE;
  40098 }
  40099 
  40100 /* Function: _bcm_field_hints_display
  40101  *
  40102  * Purpose:
  40103  *    Dump the hints database.
  40104  * Parameters:
  40105  *     unit -    (IN) BCM device number.
  40106  *     hint_id - (IN) Hint id to which the hint should be associated.
  40107  * Returns:
  40108  *     BCM_E_XXXX.
  40109  */
  40110 int _bcm_field_hints_display (int unit, bcm_field_hintid_t hint_id)
  40111 {
  40112     _field_hints_t        *f_ht = NULL;       /* Field hints Structure. */
  40113     _field_hint_t         *hints_dump = NULL; /* Field hints Structure. */
  40114     bcm_field_hint_t      *hint_entry;        /* Hint Entry */
  40115     uint32                 hint_count = 1;    /* Hint Count */
  40116 
  40117 
  40118 
  40119     BCM_IF_ERROR_RETURN(_field_hints_control_get (unit, hint_id, &f_ht));
  40120     if (f_ht == NULL) {
  40121         LOG_DEBUG(BSL_LS_BCM_FP,
  40122                 (BSL_META_U(unit,"FP (unit %d) HintId %d not present in "
  40123                             "Hint Hash table\r\n"), unit, hint_id));
  40124         return (BCM_E_NOT_FOUND);
  40125     }
  40126 
  40127     hints_dump = f_ht->hints;
  40128 
  40129     LOG_DEBUG(BSL_LS_BCM_FP,
  40130           (BSL_META_U(unit,"Hints information for Hint ID (%d)\r\n"),hint_id));
  40131     LOG_DEBUG(BSL_LS_BCM_FP,
  40132             (BSL_META_U(unit,"==================================\r\n")));
  40133     LOG_DEBUG(BSL_LS_BCM_FP,
  40134             (BSL_META_U(unit,"Number of Groups Attached  = %d\r\n"),
  40135                                                      f_ht->grp_ref_count));
  40136     LOG_DEBUG(BSL_LS_BCM_FP,
  40137             (BSL_META_U(unit, "Number of Hints present    = %d\r\n"),
  40138                                                      f_ht->hint_count));
  40139 
  40140     while (hints_dump != NULL) {
  40141         hint_entry = hints_dump->hint;
  40142         if (hint_entry != NULL) {
  40143             LOG_DEBUG(BSL_LS_BCM_FP,
  40144                     (BSL_META_U(unit, "Hint %d\r\n"), hint_count));
  40145             LOG_DEBUG(BSL_LS_BCM_FP,
  40146                     (BSL_META_U(unit, "=======\r\n")));
  40147             if (hint_entry->hint_type == bcmFieldHintTypeGroupAutoExpansion) {
  40148                 LOG_DEBUG(BSL_LS_BCM_FP,
  40149                     (BSL_META_U(unit, "Hint Type      = AutoExpansion\r\n")));
  40150             } else if (hint_entry->hint_type == bcmFieldHintTypeCompression) {
  40151                 LOG_DEBUG(BSL_LS_BCM_FP,
  40152                     (BSL_META_U(unit, "HintType       = Compression\r\n")));
  40153             } else if (hint_entry->hint_type == bcmFieldHintTypeExtraction) {
  40154                 LOG_DEBUG(BSL_LS_BCM_FP,
  40155                     (BSL_META_U(unit, "HintType       = Extraction\r\n")));
  40156             } else if (hint_entry->hint_type == bcmFieldHintTypeExactMatch) {
  40157                 LOG_DEBUG(BSL_LS_BCM_FP,
  40158                     (BSL_META_U(unit, "HintType       = Exact Match\r\n")));
  40159             } else {
  40160                 LOG_DEBUG(BSL_LS_BCM_FP,
  40161                     (BSL_META_U(unit, "HintType       = Unknown\r\n")));
  40162             }
  40163             LOG_DEBUG(BSL_LS_BCM_FP,
  40164                     (BSL_META_U(unit, "Qual           = %u\r\n"),
  40165                                                   hint_entry->qual));
  40166             LOG_DEBUG(BSL_LS_BCM_FP,
  40167                     (BSL_META_U(unit, "Max Values     = %u\r\n"),
  40168                                                   hint_entry->max_values));
  40169             LOG_DEBUG(BSL_LS_BCM_FP,
  40170                     (BSL_META_U(unit, "Start Bit      = %u\r\n"),
  40171                                                   hint_entry->start_bit));
  40172             LOG_DEBUG(BSL_LS_BCM_FP,
  40173                     (BSL_META_U(unit, "End Bit        = %u\r\n"),
  40174                                                   hint_entry->end_bit));
  40175             LOG_DEBUG(BSL_LS_BCM_FP,
  40176                     (BSL_META_U(unit, "Flags          = %u\r\n"),
  40177                                                   hint_entry->flags));
  40178             LOG_DEBUG(BSL_LS_BCM_FP,
  40179                     (BSL_META_U(unit, "Max Group Size = %u\r\n"),
  40180                                                   hint_entry->max_group_size));
  40181             LOG_DEBUG(BSL_LS_BCM_FP,
  40182                     (BSL_META_U(unit, "Exact Match Group Priority = %u\r\n"),
  40183                                                   hint_entry->priority));
  40184         }
  40185         hint_count++;
  40186         hints_dump = hints_dump->next;
  40187     }
  40188 
  40189     return BCM_E_NONE;
  40190 }
  40191 
  40192 int
  40193 _field_aset_install(int unit, _field_group_t *fg)
  40194 {
  40195 #ifdef BCM_TRIUMPH3_SUPPORT
  40196     if (SOC_IS_TRIUMPH3(unit)) {
  40197         return (_bcm_field_tr3_aset_install(unit, fg));
  40198     }
  40199 #endif
  40200 
  40201     return (BCM_E_NONE);
  40202 }
  40203 
  40204 /*
  40205  * Function:
  40206  *     _field_group_status_calc
  40207  * Purpose:
  40208  *     Fill in the values of a group status struct.
  40209  * Parameters:
  40210  *     unit     - (IN) BCM device number.
  40211  *     fg       - (OUT)Group with up-to-date status structure
  40212  * Returns:
  40213  *     BCM_E_XXX
  40214  */
  40215 int
  40216 _bcm_field_group_status_calc(int unit, _field_group_t *fg)
  40217 {
  40218     bcm_field_group_status_t    *status;
  40219     _field_stage_t              *stage_fc; /* Stage field control structure. */
  40220     _field_slice_t              *fs;       /* Field slice control structure. */
  40221     int                         count=0;   /* Generic purposes counter.      */
  40222     int                         rv;        /* Operation return status. */
  40223     int slice_index;
  40224     bcm_pbmp_t all_pbmp;
  40225     int ratio = 0;
  40226 
  40227     /* Input parameters check. */
  40228     if (NULL == fg) {
  40229         return (BCM_E_PARAM);
  40230     }
  40231 
  40232     BCM_IF_ERROR_RETURN
  40233         (_field_stage_control_get(unit, fg->stage_id, &stage_fc));
  40234 
  40235     status = &fg->group_status;
  40236 
  40237     /* Calculate total number of entries slices in group slices. */
  40238 
  40239     status->entries_total = 0;
  40240     fs = &fg->slices[0];
  40241 
  40242     if (fs->group_flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) {
  40243         ratio = 2;
  40244     } else {
  40245         ratio = 1;
  40246     }
  40247 
  40248     while (fs != NULL)
  40249     {
  40250         status->entries_total += fs->entry_count/ratio;
  40251         fs = fs->next;
  40252     }
  40253 
  40254     status->entries_free = 0;
  40255     fs = &fg->slices[0];
  40256 
  40257     while (fs != NULL)
  40258     {
  40259         _bcm_field_entries_free_get(unit, fs, fg, &count);
  40260         status->entries_free += count;
  40261         fs = fs->next;
  40262     }
  40263 
  40264     fs = fg->slices;
  40265 
  40266 #if defined(BCM_TOMAHAWK_SUPPORT)
  40267     if (soc_feature(unit, soc_feature_field_multi_pipe_support)
  40268         && (_BCM_FIELD_STAGE_LOOKUP == fg->stage_id)) {
  40269         rv = _bcm_field_th_flex_counter_status_get(unit, fg,
  40270                                                    &(status->counters_total),
  40271                                                    &(status->counters_free));
  40272         BCM_IF_ERROR_RETURN(rv);
  40273 
  40274     } else
  40275 #endif
  40276     {
  40277 
  40278         status->counters_total = _bcm_field_counters_total_get(stage_fc, fs);
  40279         status->counters_free  = _bcm_field_counter_free_get(stage_fc, fs);
  40280     }
  40281 
  40282     status->meters_total  = _bcm_field_meters_total_get(stage_fc, fg->instance, fs);
  40283     status->meters_free   = _bcm_field_meter_free_get(stage_fc, fg, fs);
  40284 
  40285     if (!(fg->flags & _FP_GROUP_SPAN_SINGLE_SLICE))
  40286     {
  40287         fs += 1;
  40288 
  40289         /* If device supports Per Slice Counters, need to account the counters
  40290          * associated to the secondary slice.
  40291          */
  40292         if (!(stage_fc->flags & _FP_STAGE_GLOBAL_COUNTERS) &&
  40293             !(stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS)) {
  40294             status->counters_total += fs->counters_count;
  40295             status->counters_free  += _bcm_field_counter_free_get(stage_fc, fs);
  40296         }
  40297 
  40298         /*
  40299          * If device stage supports global meter pools, then
  40300          * meter information is already updated.
  40301          */
  40302         if (!(stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)) {
  40303             status->meters_total  += fs->meters_count;
  40304             status->meters_free   += _bcm_field_meter_free_get(stage_fc,
  40305                                                      fg, fs);
  40306         }
  40307     }
  40308 
  40309     if (stage_fc->flags & _FP_STAGE_AUTO_EXPANSION)
  40310     {
  40311         /* For expandable groups, find free slices and add the info */
  40312         BCM_PBMP_CLEAR(all_pbmp);
  40313         BCM_IF_ERROR_RETURN(_bcm_field_valid_pbmp_get(unit, &all_pbmp));
  40314 
  40315         for (slice_index = 0; slice_index < stage_fc->tcam_slices;
  40316             ++slice_index)
  40317         {
  40318             /* Ignore the secondary and tertiary slices */
  40319             if ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) ||
  40320                     (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE)) {
  40321                 if (fg->slices[1].slice_number == slice_index) {
  40322                     continue;
  40323                 }
  40324             }
  40325             if (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) {
  40326                 if (fg->slices[2].slice_number == slice_index) {
  40327                     continue;
  40328                 }
  40329             }
  40330 #if defined(BCM_TOMAHAWK_SUPPORT)
  40331             if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  40332                 _BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id) {
  40333 
  40334                rv = _bcm_field_th_group_add_slice_validate(unit, stage_fc, fg,
  40335                                                            slice_index);
  40336             } else
  40337 #endif /* BCM_TOMAHAWK_SUPPORT */
  40338             {
  40339                rv = _field_group_ports_validate(unit, stage_fc, fg->instance,
  40340                                               slice_index, fg->flags, all_pbmp);
  40341             }
  40342 
  40343             if (BCM_SUCCESS(rv)) {
  40344                 fs = stage_fc->slices[fg->instance] + slice_index;
  40345 
  40346                 status->entries_total += fs->entry_count/ratio;
  40347                 status->entries_free += fs->entry_count/ratio;
  40348 
  40349                 /* If device supports Per Slice Counters, need to account the counters
  40350                  * associated to the secondary slice.
  40351                  */
  40352                 if (!(stage_fc->flags & _FP_STAGE_GLOBAL_COUNTERS) &&
  40353                     !(stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS)) {
  40354                     status->counters_total += fs->counters_count;
  40355                     status->counters_free += fs->counters_count;
  40356                 }
  40357 
  40358                 /*
  40359                  * If device stage supports global meter pools, then
  40360                  * meter information is already updated.
  40361                  */
  40362                 if (!(stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)) {
  40363                     status->meters_total += fs->meters_count;
  40364                     status->meters_free += fs->meters_count;
  40365                 }
  40366             }
  40367         }
  40368 
  40369         /* Go through used slice list except first slice for expandable groups */
  40370         fs = &fg->slices[0];
  40371         while (fs != NULL) {
  40372             fs = fs->next;
  40373             if (fs != NULL) {
  40374                 if (!(stage_fc->flags & _FP_STAGE_GLOBAL_COUNTERS) &&
  40375                     !(stage_fc->flags & _FP_STAGE_GLOBAL_CNTR_POOLS)) {
  40376                     status->counters_total += fs->counters_count;
  40377                     status->counters_free  += _bcm_field_counter_free_get(stage_fc, fs);
  40378                 }
  40379 
  40380                 if (!(stage_fc->flags & _FP_STAGE_GLOBAL_METER_POOLS)) {
  40381                     status->meters_total  += fs->meters_count;
  40382                     status->meters_free   += _bcm_field_meter_free_get(stage_fc,
  40383                                                              fg, fs);
  40384                 }
  40385             }
  40386         }
  40387     }
  40388 
  40389     return (BCM_E_NONE);
  40390 }
  40391 
  40392 /*
  40393  * Function :
  40394  *          _bcm_field_is_stage_range_check_exist(unit, stage) (internal)
  40395  * Purpose  :
  40396  *          Checks whether the field stage has existing range checkers
  40397  * Parameters :
  40398  *          unit        - (IN) BCM device number
  40399  *          stage       - (IN) Pipeline stage id number
  40400  * Return Values:
  40401  *          BCM_E_EXISTS - There are existing range checkers.
  40402  *          BCM_E_NONE  - No Existing range checkers.
  40403  */
  40404 int _bcm_field_is_stage_range_check_exist (int unit,
  40405         _field_stage_id_t stage)
  40406 {
  40407     _field_stage_t      *stage_fc;      /* Stage field control info.*/
  40408     _field_control_t    *fc;            /* Field control structure. */
  40409     int                 rv;             /* Operation return status. */
  40410 
  40411     rv = _field_control_get(unit, &fc);
  40412     BCM_IF_ERROR_RETURN(rv);
  40413 
  40414     rv = _field_stage_control_get(unit, stage, &stage_fc);
  40415     BCM_IF_ERROR_RETURN(rv);
  40416 
  40417     if (stage_fc->ranges != NULL) {
  40418         return BCM_E_EXISTS;
  40419     }
  40420     return BCM_E_NONE;
  40421 }
  40422 
  40423 
  40424 /*
  40425  * Function: _bcm_field_entry_create_id
  40426  *
  40427  * Purpose:
  40428  *     Create a blank entry group based on a group;
  40429  *     allows selection of a specific slot in a slice
  40430  *
  40431  * Parameters:
  40432  *     unit -  (IN) BCM device number.
  40433  *     group - (IN) Field group ID.
  40434  *     entry - (IN) Requested entry ID; must be in the range prio_min through
  40435  *             prio_max as returned by bcm_field_group_status_get().
  40436  * Returns:
  40437  *     BCM_E_INIT      - unit not initialized
  40438  *     BCM_E_EXISTS    - Entry ID already in use
  40439  *     BCM_E_NOT_FOUND - Group ID not found in unit
  40440  *     BCM_E_MEMORY    - allocation failure
  40441  *     BCM_E_NONE      - Success
  40442  */
  40443 int
  40444 _bcm_field_entry_create_id(int unit,
  40445                               bcm_field_group_t group,
  40446                               bcm_field_entry_t entry)
  40447 {
  40448     _field_group_t      *fg;           /* Field group structure.      */
  40449     int                 rv;
  40450 
  40451     FP_LOCK(unit);
  40452 
  40453     rv = _field_group_get(unit, group, &fg);
  40454     if (BCM_FAILURE(rv)) {
  40455         FP_UNLOCK(unit);
  40456         return (rv);
  40457     }
  40458 
  40459     /* When MaxGroupSizeHardLimit is set and limit is reached
  40460      * return BCM_E_FULL */
  40461     if (fg->flags & _FP_GROUP_MAX_SIZE_HARD_LIMIT) {
  40462         if (fg->max_group_size -
  40463                 (fg->group_status.entry_count) <= 0) {
  40464             FP_UNLOCK(unit);
  40465             return BCM_E_FULL;
  40466         }
  40467     }
  40468 
  40469 #if defined(BCM_TOMAHAWK_SUPPORT)
  40470     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  40471         (fg->stage_id == _BCM_FIELD_STAGE_CLASS)) {
  40472         rv = _bcm_field_th_class_entry_create(unit, group, entry);
  40473         FP_UNLOCK(unit);
  40474         return (rv);
  40475     }
  40476 #endif /* BCM_TOMAHAWK_SUPPORT */
  40477 
  40478     rv = _field_entry_create_id(unit, group, entry);
  40479 
  40480     FP_UNLOCK(unit);
  40481     return (rv);
  40482 }
  40483 
  40484 
  40485 /*
  40486  * Function: _bcm_field_entry_copy_id
  40487  *
  40488  * Purpose:
  40489  *     Create a copy of an existing entry with a requested ID
  40490  *
  40491  * Parameters:
  40492  *     unit      - BCM device number
  40493  *     src_entry - Source entry to copy
  40494  *     dst_entry - Destination entry for copy
  40495  *     flags     - flags to control entry copy
  40496  *                 0 : stats(if attached)will be copied
  40497  *                 BCM_FIELD_ENTRY_COPY_WITHOUT_STATS : Stats are not copied
  40498  *
  40499  * Returns:
  40500  *     BCM_E_INIT      - BCM Unit not initialized
  40501  *     BCM_E_NOT_FOUND - Source Entry ID not found
  40502  *     BCM_E_XXX       - Error code from bcm_field_entry_create_id()
  40503  *     BCM_E_NONE      - Success
  40504  */
  40505 
  40506 int
  40507 _bcm_field_entry_copy_id(int unit,
  40508                             bcm_field_entry_t src_entry,
  40509                             bcm_field_entry_t dst_entry,
  40510                             uint32 flags)
  40511 {
  40512     _field_entry_t      *f_ent_src, *f_ent_dst;
  40513     int                 parts_count = 0;
  40514     _field_action_t     *fa_src;
  40515     int                 free_tcam = FALSE;
  40516     int                 rv;
  40517     int                 i;
  40518     bcm_pbmp_t          pbmp;
  40519     _field_stage_t      *stage_fc;
  40520 
  40521 
  40522     FP_LOCK(unit);
  40523 
  40524     rv = _bcm_field_entry_get_by_id(unit, src_entry, &f_ent_src);
  40525     if (BCM_FAILURE(rv)) {
  40526         FP_UNLOCK(unit);
  40527         return (rv);
  40528     }
  40529 
  40530     rv = _field_stage_control_get(unit, f_ent_src->group->stage_id, &stage_fc);
  40531     if (BCM_FAILURE(rv)) {
  40532         FP_UNLOCK(unit);
  40533         return (rv);
  40534     }
  40535 
  40536     /* Get number of entry parts . */
  40537     rv = _bcm_field_entry_tcam_parts_count (unit, f_ent_src->group->stage_id,
  40538                                             f_ent_src->group->flags, &parts_count);
  40539     if (BCM_FAILURE(rv)) {
  40540         FP_UNLOCK(unit);
  40541     	return (rv);
  40542     }
  40543 
  40544 
  40545     /* Creating a new destination entry sets the unit, eid, gid, slice_idx,
  40546      * ext, dirty, fs and next fields. Also, it correctly creates multiple
  40547      * physical entry structures for wide-mode groups.
  40548      */
  40549 
  40550     rv = _bcm_field_entry_create_id(unit, f_ent_src->group->gid,
  40551                                        dst_entry);
  40552     if (BCM_FAILURE(rv)) {
  40553         FP_UNLOCK(unit);
  40554         return (rv);
  40555     }
  40556 
  40557     rv = _bcm_field_entry_get_by_id(unit, dst_entry, &f_ent_dst);
  40558     if (BCM_FAILURE(rv)) {
  40559         FP_UNLOCK(unit);
  40560         BCM_IF_ERROR_RETURN(bcm_esw_field_entry_destroy(unit, dst_entry));
  40561         return (rv);
  40562     }
  40563 
  40564     for (i = 0; i < parts_count; i++) {
  40565         if (NULL == f_ent_src[i].tcam.key) {
  40566             free_tcam = TRUE;
  40567         }
  40568 
  40569 #if defined(BCM_TRIDENT2_SUPPORT)
  40570     if (SOC_IS_TD2_TT2(unit) &&
  40571         (f_ent_dst[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) {
  40572         (f_ent_dst+i)->efp_key_match_type = (f_ent_src+i)->efp_key_match_type;
  40573     }
  40574 #endif
  40575 
  40576         rv = _bcm_field_qual_tcam_key_mask_get(unit, f_ent_src + i);
  40577         if (BCM_FAILURE(rv)) {
  40578             FP_UNLOCK(unit);
  40579             BCM_IF_ERROR_RETURN(bcm_esw_field_entry_destroy(unit, dst_entry));
  40580             return (rv);
  40581         }
  40582 
  40583         /* Entry create id might allocated tcam already. */
  40584         rv = _bcm_field_qual_tcam_key_mask_free(unit, f_ent_dst + i);
  40585         if (BCM_FAILURE(rv)) {
  40586             FP_UNLOCK(unit);
  40587             BCM_IF_ERROR_RETURN(bcm_esw_field_entry_destroy(unit, dst_entry));
  40588             return (rv);
  40589         }
  40590 
  40591         /* Copy qualification data. */
  40592         sal_memcpy(&f_ent_dst[i].tcam, &f_ent_src[i].tcam,
  40593                    sizeof(_field_tcam_t));
  40594         sal_memcpy(&f_ent_dst[i].extra_tcam, &f_ent_src[i].extra_tcam,
  40595                    sizeof(_field_tcam_t));
  40596 
  40597 #if defined(BCM_TRIDENT2_SUPPORT)
  40598         if (SOC_IS_TD2_TT2(unit) &&
  40599             (f_ent_dst[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) {
  40600             sal_memcpy(&f_ent_dst[i].key_match_tcam,
  40601                        &f_ent_src[i].key_match_tcam,
  40602                        sizeof(_field_tcam_t));
  40603         }
  40604 #endif
  40605         f_ent_dst[i].tcam.key  = NULL;/* Do not copy allocated part.*/
  40606         f_ent_dst[i].tcam.mask = NULL;/* Do not copy allocated part.*/
  40607         f_ent_dst[i].extra_tcam.key  = NULL;/* Do not copy allocated part.*/
  40608         f_ent_dst[i].extra_tcam.mask = NULL;/* Do not copy allocated part.*/
  40609         if (f_ent_dst[i].fs->stage_id == _BCM_FIELD_STAGE_EXTERNAL) {
  40610             f_ent_dst[i].tcam.key_hw = NULL;
  40611             f_ent_dst[i].tcam.mask_hw = NULL;
  40612         }
  40613 
  40614 #if defined(BCM_TRIDENT2_SUPPORT)
  40615         if (SOC_IS_TD2_TT2(unit) &&
  40616             (f_ent_dst[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) {
  40617             f_ent_dst[i].key_match_tcam.key  = NULL;/* Do not copy
  40618                                                        allocated part.*/
  40619             f_ent_dst[i].key_match_tcam.mask = NULL;/* Do not copy
  40620                                                        allocated part.*/
  40621         }
  40622 #endif
  40623 
  40624         if (f_ent_src[i].flags & _FP_ENTRY_USES_IPBM_OVERLAY) {
  40625             f_ent_dst[i].flags |= _FP_ENTRY_USES_IPBM_OVERLAY;
  40626         }
  40627 
  40628         /* Allocate tcam key and mask for destination entry. */
  40629         rv = _bcm_field_qual_tcam_key_mask_get(unit,  f_ent_dst + i);
  40630         if (BCM_FAILURE(rv)) {
  40631             FP_UNLOCK(unit);
  40632             BCM_IF_ERROR_RETURN(bcm_esw_field_entry_destroy(unit, dst_entry));
  40633             return (rv);
  40634         }
  40635 
  40636         /* Copy key and mask information. */
  40637         sal_memcpy(f_ent_dst[i].tcam.key, f_ent_src[i].tcam.key,
  40638                    f_ent_src[i].tcam.key_size);
  40639         sal_memcpy(f_ent_dst[i].tcam.mask, f_ent_src[i].tcam.mask,
  40640                    f_ent_src[i].tcam.key_size);
  40641 
  40642         if (f_ent_src[i].flags & _FP_ENTRY_USES_IPBM_OVERLAY) {
  40643             sal_memcpy(f_ent_dst[i].extra_tcam.key,
  40644                 f_ent_src[i].extra_tcam.key,
  40645                 f_ent_src[i].extra_tcam.key_size);
  40646 
  40647             sal_memcpy(f_ent_dst[i].extra_tcam.mask,
  40648                 f_ent_src[i].extra_tcam.mask,
  40649                 f_ent_src[i].extra_tcam.key_size);
  40650         }
  40651 #if defined(BCM_TRIDENT2_SUPPORT)
  40652         if (SOC_IS_TD2_TT2(unit) &&
  40653             (f_ent_dst[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) {
  40654             /* Copy key and mask information. */
  40655             sal_memcpy(f_ent_dst[i].key_match_tcam.key,
  40656                        f_ent_src[i].key_match_tcam.key,
  40657                        f_ent_dst[i].key_match_tcam.key_size);
  40658             sal_memcpy(f_ent_dst[i].key_match_tcam.mask,
  40659                        f_ent_src[i].key_match_tcam.mask,
  40660                        f_ent_dst[i].key_match_tcam.key_size);
  40661 
  40662         }
  40663 #endif
  40664         if (f_ent_dst[i].fs->stage_id == _BCM_FIELD_STAGE_EXTERNAL) {
  40665             sal_memcpy(f_ent_dst[i].tcam.key_hw,
  40666                        f_ent_src[i].tcam.key_hw,
  40667                        f_ent_src[i].tcam.key_size);
  40668             sal_memcpy(f_ent_dst[i].tcam.mask_hw,
  40669                        f_ent_src[i].tcam.mask_hw,
  40670                        f_ent_src[i].tcam.key_size);
  40671         }
  40672 
  40673         if (free_tcam) {
  40674             if (NULL != f_ent_src[i].tcam.key) {
  40675                 sal_free(f_ent_src[i].tcam.key);
  40676                 sal_free(f_ent_src[i].tcam.mask);
  40677             }
  40678             if (f_ent_src[i].flags & _FP_ENTRY_USES_IPBM_OVERLAY) {
  40679                 if (NULL != f_ent_src[i].extra_tcam.key) {
  40680                     sal_free(f_ent_src[i].extra_tcam.key);
  40681                     sal_free(f_ent_src[i].extra_tcam.mask);
  40682                 }
  40683             }
  40684             f_ent_src[i].tcam.key = f_ent_src[i].tcam.mask =
  40685                 f_ent_src[i].extra_tcam.key = f_ent_src[i].extra_tcam.mask =
  40686                     NULL;
  40687 #if defined(BCM_TRIDENT2_SUPPORT)
  40688         if (SOC_IS_TD2_TT2(unit) &&
  40689             (f_ent_src[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) {
  40690             if (NULL != f_ent_src[i].key_match_tcam.key) {
  40691                 sal_free(f_ent_src[i].key_match_tcam.key);
  40692                 sal_free(f_ent_src[i].key_match_tcam.mask);
  40693             }
  40694             f_ent_src[i].key_match_tcam.key = NULL;
  40695             f_ent_src[i].key_match_tcam.mask = NULL;
  40696         }
  40697 #endif
  40698             free_tcam = FALSE;
  40699         }
  40700     }
  40701 
  40702 #if defined(BCM_RAPTOR_SUPPORT) || defined (BCM_TRX_SUPPORT)
  40703     if ((soc_feature(unit, soc_feature_field_ingress_ipbm))
  40704               || (soc_feature(unit, soc_feature_field_multi_pipe_support))) {
  40705         BCM_PBMP_ASSIGN(f_ent_dst->pbmp.data, f_ent_src->pbmp.data);
  40706         BCM_PBMP_ASSIGN(f_ent_dst->pbmp.mask, f_ent_src->pbmp.mask);
  40707     }
  40708 #endif /* BCM_RAPTOR_SUPPORT || BCM_TRX_SUPPORT */
  40709 
  40710     /* Copy counter, if it exists. */
  40711     /* In case of internal backup entry, copy only for
  40712      * devices that have global/flex counter pools
  40713      */
  40714     if (!(flags & BCM_FIELD_ENTRY_COPY_WITHOUT_STATS)) {
  40715         if (f_ent_src->statistic.flags & _FP_ENTRY_STAT_VALID) {
  40716             rv = bcm_esw_field_entry_stat_attach(unit, dst_entry,
  40717                     f_ent_src->statistic.sid);
  40718             if (BCM_FAILURE(rv)) {
  40719                 FP_UNLOCK(unit);
  40720                 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_destroy
  40721                         (unit, dst_entry));
  40722                 return (rv);
  40723             }
  40724             /* Preseve original entry flags. */
  40725             f_ent_dst->statistic.flags = (f_ent_src->statistic.flags &  \
  40726                     (_FP_ENTRY_STAT_VALID | _FP_ENTRY_STAT_EMPTY |
  40727                      _FP_ENTRY_STAT_USE_EVEN | _FP_ENTRY_STAT_USE_ODD));
  40728             f_ent_dst->statistic.flags |=  _FP_ENTRY_STAT_DIRTY;
  40729         }
  40730     }
  40731 
  40732     /*  Copy meter, if it exists. */
  40733     for (i = 0; i < _FP_POLICER_LEVEL_COUNT; i++)  {
  40734         if (f_ent_src->policer[i].flags & _FP_POLICER_VALID) {
  40735             rv = bcm_esw_field_entry_policer_attach(unit, dst_entry, i,
  40736                                                     f_ent_src->policer[i].pid);
  40737             if (BCM_FAILURE(rv)) {
  40738                 FP_UNLOCK(unit);
  40739                 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_destroy
  40740                         (unit, dst_entry));
  40741                 return (rv);
  40742             }
  40743         }
  40744     }
  40745 
  40746     /* Copy source entry's action linked list.  */
  40747     /* This also copies the counter specific actions */
  40748     for (i = 0; i < parts_count; i++) {
  40749         for (fa_src = f_ent_src[i].actions;
  40750              fa_src != NULL;
  40751              fa_src = fa_src->next) {
  40752 
  40753             int idx = 0;
  40754             if ((bcmFieldActionRedirectPbmp == fa_src->action)
  40755                 || (bcmFieldActionEgressMask == fa_src->action)
  40756                 || (bcmFieldActionEgressPortsAdd == fa_src->action)
  40757                 || (bcmFieldActionRedirectBcastPbmp == fa_src->action)) {
  40758 
  40759                 SOC_PBMP_CLEAR(pbmp);
  40760 
  40761                 for (idx = 0; (idx < _FP_ACTION_PARAM_SZ) &&
  40762                      (idx < SOC_PBMP_WORD_MAX); idx++) {
  40763 
  40764                      SOC_PBMP_WORD_SET(pbmp, idx, fa_src->param[idx]);
  40765                 }
  40766 
  40767                 rv = bcm_esw_field_action_ports_add(unit,
  40768                                                     dst_entry,
  40769                                                     fa_src->action,
  40770                                                     pbmp);
  40771             } else {
  40772                 rv = bcm_esw_field_action_add(unit,
  40773                                               dst_entry,
  40774                                               fa_src->action,
  40775                                               fa_src->param[0],
  40776                                               fa_src->param[1]);
  40777             }
  40778             if (BCM_FAILURE(rv)) {
  40779                 FP_UNLOCK(unit);
  40780                 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_destroy
  40781                         (unit, dst_entry));
  40782                 return (rv);
  40783             }
  40784         }
  40785     }
  40786     f_ent_dst->flags     |= _FP_ENTRY_DIRTY;
  40787 
  40788     if (!(f_ent_src->flags & _FP_ENTRY_CREATED_WITHOUT_PRIO)) {
  40789         /* Set the destination entry's priority to the same as the source's. */
  40790         rv = _field_entry_prio_set(unit, dst_entry, f_ent_src->prio);
  40791 
  40792         if (BCM_FAILURE(rv)) {
  40793             FP_UNLOCK(unit);
  40794             BCM_IF_ERROR_RETURN(bcm_esw_field_entry_destroy(unit, dst_entry));
  40795             return (rv);
  40796         }
  40797     }
  40798     FP_UNLOCK(unit);
  40799     return (rv);
  40800 }
  40801 
  40802 
  40803 
  40804 /*
  40805  * Function:
  40806  *      _field_qualify_VlanTranslationHit
  40807  * Purpose:
  40808  *      Set match criteria for bcmFieildQualifyVlanTranslationHit
  40809  *                     qualifier from the field entry.
  40810  * Parameters:
  40811  *      unit - (IN) Unit number.
  40812  *      entry - (IN) BCM field entry id.
  40813  *      data - (OUT) Qualifier match data.
  40814  *      mask - (OUT) Qualifier match mask.
  40815  * Returns:
  40816  *      BCM_E_XXX
  40817  * Notes:
  40818  */
  40819 
  40820 int
  40821 _field_qualify_VlanTranslationHit(int               unit,
  40822                                   bcm_field_entry_t entry,
  40823                                   uint8             *data,
  40824                                   uint8             *mask
  40825                                  )
  40826 {
  40827 
  40828     /* Check for valid data mask combinations */
  40829     switch (*data) {
  40830     case BCM_FIELD_VXLT_LOOKUP_STATUS_NO_HIT:
  40831         *data = 0x0;
  40832         *mask = 0x1;
  40833         break;
  40834     case BCM_FIELD_VXLT_LOOKUP_STATUS_HIT:
  40835         *data = 0x1;
  40836 	*mask = 0x1;
  40837 	break;
  40838     default:
  40839         LOG_ERROR(BSL_LS_BCM_FP,
  40840                   (BSL_META_U(unit,
  40841                               "FP(unit %d) Error: PacketRes *data=%#x undefined\n"),
  40842                    unit,
  40843                    *data));
  40844         return (BCM_E_PARAM);
  40845     }
  40846 
  40847     return (BCM_E_NONE);
  40848 }
  40849 
  40850 /*
  40851  * Function:
  40852  *      _field_qualify_VlanTranslationHit_get
  40853  * Purpose:
  40854  *      Get match criteria for bcmFieildQualifyVlanTranslationHit
  40855  *                     qualifier from the field entry.
  40856  * Parameters:
  40857  *      unit - (IN) Unit number.
  40858  *      entry - (IN) BCM field entry id.
  40859  *      data - (OUT) Qualifier match data.
  40860  *      mask - (OUT) Qualifier match mask.
  40861  * Returns:
  40862  *      BCM_E_XXX
  40863  * Notes:
  40864  */
  40865 int
  40866 _field_qualify_VlanTranslationHit_get(int               unit,
  40867                                       bcm_field_entry_t entry,
  40868                                       uint8             *data,
  40869                                       uint8             *mask
  40870                                      )
  40871 {
  40872     /* Translate data #defines to hardware encodings */
  40873     switch (*data) {
  40874     case 0x0:
  40875         *data = BCM_FIELD_VXLT_LOOKUP_STATUS_NO_HIT;
  40876         break;
  40877     case 0x1:
  40878         *data = BCM_FIELD_VXLT_LOOKUP_STATUS_HIT;
  40879         break;
  40880     default:
  40881         return (BCM_E_INTERNAL);
  40882     }
  40883 
  40884     /*
  40885      * In bcm_field_qualify_VlanTranslationHit, mask passed by application code
  40886      * will be ignored, and SDK will internally set the right mask in h/w.
  40887      * In this get routine, giving h/w encoded mask confuses end user.
  40888      * So mask is setting to EXACT_MASK(1bit is allocated in h/w to qualify
  40889      * Vlan Translation Hit Status).
  40890      */
  40891 
  40892    *mask = 0x1;
  40893 
  40894     return (BCM_E_NONE);
  40895 }
  40896 
  40897 
  40898 int
  40899 _field_qualify_PacketRes(int               unit,
  40900                          bcm_field_entry_t entry,
  40901                          uint32            *data,
  40902                          uint32            *mask
  40903                          )
  40904 {
  40905     switch (*data) {
  40906     case BCM_FIELD_PKT_RES_UNKNOWN:
  40907         *data = 0x0;
  40908         break;
  40909     case BCM_FIELD_PKT_RES_CONTROL:
  40910         *data = 0x1;
  40911         break;
  40912     case BCM_FIELD_PKT_RES_BPDU:
  40913         *data = 0x2;
  40914         break;
  40915     case BCM_FIELD_PKT_RES_L2BC:
  40916         *data = 0x3;
  40917         break;
  40918     case BCM_FIELD_PKT_RES_L2UC:
  40919         *data = 0x4;
  40920         break;
  40921     case BCM_FIELD_PKT_RES_L2UNKNOWN:
  40922         *data = 0x5;
  40923         break;
  40924     case BCM_FIELD_PKT_RES_L3MCUNKNOWN:
  40925 #ifdef BCM_RAPTOR1_SUPPORT
  40926         if (SOC_IS_RAPTOR(unit)) {
  40927             return BCM_E_UNAVAIL;
  40928         }
  40929 #endif /* BCM_RAPTOR1_SUPPORT */
  40930         *data = 0x6;
  40931         break;
  40932     case BCM_FIELD_PKT_RES_L3MCKNOWN:
  40933 #ifdef BCM_RAPTOR1_SUPPORT
  40934         if (SOC_IS_RAPTOR(unit)) {
  40935             return BCM_E_UNAVAIL;
  40936         }
  40937 #endif /* BCM_RAPTOR1_SUPPORT */
  40938         *data = 0x7;
  40939         break;
  40940     case BCM_FIELD_PKT_RES_L2MCKNOWN:
  40941         *data = 0x8;
  40942         break;
  40943     case BCM_FIELD_PKT_RES_L2MCUNKNOWN:
  40944         *data = 0x9;
  40945         break;
  40946     case BCM_FIELD_PKT_RES_L3UCKNOWN:
  40947 #ifdef BCM_RAPTOR1_SUPPORT
  40948         if (SOC_IS_RAPTOR(unit)) {
  40949             return BCM_E_UNAVAIL;
  40950         }
  40951 #endif /* BCM_RAPTOR1_SUPPORT */
  40952         *data = 0xA;
  40953         break;
  40954     case BCM_FIELD_PKT_RES_L3UCUNKNOWN:
  40955 #ifdef BCM_RAPTOR1_SUPPORT
  40956         if (SOC_IS_RAPTOR(unit)) {
  40957             return BCM_E_UNAVAIL;
  40958         }
  40959 #endif /* BCM_RAPTOR1_SUPPORT */
  40960         *data = 0xB;
  40961         break;
  40962     case BCM_FIELD_PKT_RES_MPLSKNOWN:
  40963         if (SOC_IS_TR_VL(unit)) {
  40964             *data = 0xC;
  40965             break;
  40966         }
  40967         return (BCM_E_UNAVAIL);
  40968     case BCM_FIELD_PKT_RES_MPLSL3KNOWN:
  40969         if (SOC_IS_TR_VL(unit)) {
  40970             *data = 0xD;
  40971             break;
  40972         }
  40973         return (BCM_E_UNAVAIL);
  40974     case BCM_FIELD_PKT_RES_MPLSL2KNOWN:
  40975         if (SOC_IS_TR_VL(unit)) {
  40976             *data = 0xE;
  40977             break;
  40978         }
  40979         return (BCM_E_UNAVAIL);
  40980     case BCM_FIELD_PKT_RES_MPLSUNKNOWN:
  40981         if (SOC_IS_TR_VL(unit)) {
  40982             *data = 0xF;
  40983             break;
  40984         }
  40985         return (BCM_E_UNAVAIL);
  40986     case BCM_FIELD_PKT_RES_MIMKNOWN:
  40987         if (SOC_IS_TR_VL(unit)) {
  40988             *data = 0x10;
  40989             break;
  40990         }
  40991         return (BCM_E_UNAVAIL);
  40992     case BCM_FIELD_PKT_RES_MIMUNKNOWN:
  40993         if (SOC_IS_TR_VL(unit)) {
  40994             *data = 0x11;
  40995             break;
  40996         }
  40997         return (BCM_E_UNAVAIL);
  40998     default:
  40999         LOG_ERROR(BSL_LS_BCM_FP,
  41000                   (BSL_META_U(unit,
  41001                           "FP(unit %d) Error: PacketRes *data=%#x undefined\n"),
  41002                    unit, *data));
  41003         return (BCM_E_PARAM);
  41004     }
  41005     if ( *mask != *data ) {
  41006         *mask = 0x1F;
  41007     }
  41008 
  41009     return (BCM_E_NONE);
  41010 }
  41011 
  41012 
  41013 int
  41014 _bcm_esw_field_qualify_aux_tag(int                 unit,
  41015                                bcm_field_entry_t   entry,
  41016                                bcm_field_qualify_t qual,
  41017                                uint32              data,
  41018                                uint32              mask
  41019                                )
  41020 {
  41021     _field_entry_t           *f_ent;
  41022     _field_group_t           *fg;
  41023     _bcm_field_qual_offset_t *q_offset;
  41024     uint32                   ref_data[_FP_QUAL_DATA_WORDS];
  41025     uint32                   ref_mask[_FP_QUAL_DATA_WORDS];
  41026     int                      rv;
  41027 
  41028 
  41029     FP_LOCK(unit);
  41030 
  41031     /* Get field entry part that contains the qualifier. */
  41032     rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent);
  41033     if (BCM_FAILURE(rv)) {
  41034         FP_UNLOCK(unit);
  41035         return (rv);
  41036     }
  41037 
  41038     
  41039     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  41040          ((_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id) ||
  41041           (_BCM_FIELD_STAGE_EXACTMATCH == f_ent->group->stage_id) ||
  41042           (_BCM_FIELD_STAGE_EGRESS == f_ent->group->stage_id) ||
  41043           (_BCM_FIELD_STAGE_FLOWTRACKER ==f_ent->group->stage_id))) {
  41044        rv = _field_qualify32(unit, entry, qual, data, mask);
  41045        FP_UNLOCK(unit);
  41046        return rv;
  41047     }
  41048 
  41049     /* Get qualifier offsets in the tcam. */
  41050     rv = _field_qual_offset_get(unit, f_ent, qual, &q_offset);
  41051     if (BCM_FAILURE(rv)) {
  41052         FP_UNLOCK(unit);
  41053         return (rv);
  41054     }
  41055 
  41056     /* Take the given 32-bit data and mask value, and prefix them with
  41057        a 1 bit, which in the hardware is the "tag valid" bit.
  41058     */
  41059 
  41060     /* The LLTAG overlaid the VNTAG lower 16bits, and the LLTAG VALID bit  will
  41061     disambiguate the field. So the VNTAG_VALID field should be set to 0 and
  41062     LLTAG_VALID field should be set to 1.
  41063     */
  41064     fg = f_ent->group;
  41065     if ((_BCM_FIELD_STAGE_LOOKUP == fg->stage_id)
  41066            && (qual == bcmFieldQualifySubportPktTag)) {
  41067                 ref_data[1] = 2;
  41068         ref_mask[1] = 2;
  41069         ref_data[0] = (data & 0xffff);
  41070         ref_mask[0] = (mask & 0xffff);
  41071     } else if ((_BCM_FIELD_STAGE_INGRESS == fg->stage_id)
  41072            && (qual == bcmFieldQualifySubportPktTag)) {
  41073         ref_data[1] = 1;
  41074         ref_mask[1] = 1;
  41075         ref_data[0] = (data & 0xffff);
  41076         ref_mask[0] = (mask & 0xffff);
  41077     } else {
  41078         ref_data[1] = 1;
  41079         ref_mask[1] = 1;
  41080         ref_data[0] = data;
  41081         ref_mask[0] = mask;
  41082     }
  41083 
  41084     /* Program data/mask pair to tcam buffer. */
  41085     /* coverity[callee_ptr_arith : FALSE] */
  41086     rv = _bcm_field_qual_value_set(unit, q_offset, f_ent,
  41087                                    ref_data, ref_mask);
  41088     FP_UNLOCK(unit);
  41089     return (rv);
  41090 }
  41091 
  41092 /*
  41093  * Function:
  41094  *      bcm_esw_field_stat_counter_get
  41095  * Description:
  41096  *      Get counter statistic values for a field entity
  41097  *
  41098  * Parameters:
  41099  *      unit             - (IN) unit number
  41100  *      Stat_id          - (IN) Statistics entity ID.
  41101  *      stat             - (IN) Type of the counter to retrieve
  41102  *                              I.e. ingress/egress byte/packet)
  41103  *      num_entries      - (IN) Number of counter Entries
  41104  *      counter_indexes  - (IN) Pointer to Counter indexes entries
  41105  *      counter_values   - (OUT) Pointer to counter values
  41106  *
  41107  * Return Value:
  41108  *      BCM_E_XXX
  41109  * Notes:
  41110  */
  41111 
  41112 int
  41113 _bcm_esw_field_stat_counter_get(int unit, int sync_mode, uint32 stat_id,
  41114                                bcm_field_stat_t stat, uint32 num_entries,
  41115                                uint32 *counter_indexes,
  41116                                bcm_stat_value_t *counter_values)
  41117 {
  41118 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
  41119     defined(BCM_HURRICANE3_SUPPORT)
  41120     _field_stat_t                   *f_st=NULL; /* Field statistics entity.  */
  41121     uint32                          index_count=0;
  41122     uint32                          byte_flag=0;
  41123 
  41124     if (!soc_feature(unit, soc_feature_advanced_flex_counter) &&
  41125         !soc_feature(unit, soc_feature_flowcnt)) {
  41126          return BCM_E_UNAVAIL;
  41127     }
  41128 
  41129     if (stat == bcmFieldStatPackets ||
  41130         stat == bcmFieldStatGreenPackets ||
  41131         stat == bcmFieldStatYellowPackets ||
  41132         stat == bcmFieldStatRedPackets ||
  41133         stat == bcmFieldStatNotGreenPackets ||
  41134         stat == bcmFieldStatNotYellowPackets ||
  41135         stat == bcmFieldStatNotRedPackets) {
  41136         byte_flag=0;
  41137     } else {
  41138         byte_flag=1;
  41139     }
  41140 
  41141 
  41142     BCM_IF_ERROR_RETURN(_bcm_field_stat_get(unit, stat_id, &f_st));
  41143     if (f_st->flex_mode == 0) {
  41144         LOG_VERBOSE(BSL_LS_BCM_FP,
  41145                     (BSL_META_U(unit,
  41146                                 "Entry not attached \n")));
  41147         return BCM_E_PARAM;
  41148     }
  41149     for (index_count=0; index_count < num_entries ; index_count++) {
  41150 #if defined(BCM_HURRICANE3_SUPPORT)
  41151         if (soc_feature(unit, soc_feature_flowcnt)) {
  41152             BCM_IF_ERROR_RETURN(_bcm_esw_flowcnt_counter_raw_get(
  41153                              unit, sync_mode, f_st->flex_mode, byte_flag,
  41154                              counter_indexes[index_count],
  41155                              &counter_values[index_count]));
  41156         }
  41157 #endif /* BCM_HURRICANE3_SUPPORT */
  41158 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  41159         if (soc_feature(unit, soc_feature_advanced_flex_counter)) {
  41160             BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_raw_get(
  41161                              unit, sync_mode, f_st->flex_mode, byte_flag,
  41162                              counter_indexes[index_count],
  41163                              &counter_values[index_count]));
  41164         }
  41165 #endif /* BCM_KATANA_SUPPORT ||  BCM_TRIUMPH3_SUPPORT */
  41166     }
  41167     return BCM_E_NONE;
  41168 #else
  41169     return BCM_E_UNAVAIL;
  41170 #endif
  41171 }
  41172 /*
  41173  * Function:
  41174  *      _bcm_esw_field_stat_get
  41175  *
  41176  * Description:
  41177  *      Get 64 bit counter value for specific statistic type.
  41178  *      if sync_mode is set, sync the sw accumulated count
  41179  *      with hw count value first, else return sw count.
  41180  * Parameters:
  41181  *      unit      - (IN) BCM device number.
  41182  *      sync_mode - (IN) hwcount is to be synced to sw count
  41183  *      stat_id   - (IN) Statistics entity id.
  41184  *      stat      - (IN) Collected statistics descriptor.
  41185  *      value     - (OUT) Collected counters value.
  41186  * Returns:
  41187  *      BCM_E_XXX
  41188  */
  41189 int
  41190 _bcm_esw_field_stat_get(int unit, int sync_mode, int stat_id,
  41191                        bcm_field_stat_t stat, uint64 *value)
  41192 {
  41193     _field_stat_t       *f_st;     /* Field statistics entity.   */
  41194     int                 rv;        /* Operation return status.   */
  41195 
  41196     /* Input parameters check. */
  41197     if (NULL == value) {
  41198         return (BCM_E_PARAM);
  41199     }
  41200 
  41201     COMPILER_64_ZERO(*value);
  41202 
  41203     /* Get field control structure. */
  41204 
  41205     FP_LOCK(unit);
  41206 
  41207     /* Get statistics entity descriptor. */
  41208     rv = _bcm_field_stat_get(unit, stat_id, &f_st);
  41209     if (BCM_FAILURE(rv)) {
  41210         FP_UNLOCK(unit);
  41211         return (rv);
  41212     }
  41213 
  41214     if (_FP_INVALID_INDEX != f_st->hw_index) {
  41215         rv = _field_stat_value_get(unit, sync_mode, f_st, stat, value);
  41216     }
  41217 
  41218     FP_UNLOCK(unit);
  41219     return (rv);
  41220 }
  41221 
  41222 /*
  41223  * Function:
  41224  *      _bcm_esw_field_stat_get32
  41225  *
  41226  * Description:
  41227  *      Get lower 32 bit counter value for specific statistic type.
  41228  *      if sync_mode is set, sync the sw accumulated count
  41229  *      with hw count value first, else return sw count.
  41230  * Parameters:
  41231  *      unit      - (IN) BCM device number.
  41232  *      sync_mode - (IN) hwcount is to be synced to sw count
  41233  *      stat_id   - (IN) Statistics entity id.
  41234  *      stat      - (IN) Collected statistics descriptor.
  41235  *      value     - (OUT) Collected counters value.
  41236  * Returns:
  41237  *      BCM_E_XXX
  41238  */
  41239 int
  41240 _bcm_esw_field_stat_get32(int unit, int sync_mode, int stat_id,
  41241                          bcm_field_stat_t stat, uint32 *value)
  41242 {
  41243     uint64 val64;            /* 64 bit counter value.    */
  41244     int rv;                  /* Operation return status. */
  41245 
  41246     /* Input parameters check. */
  41247     if (NULL == value) {
  41248         return (BCM_E_PARAM);
  41249     }
  41250 
  41251     /* Read 64 bit counter value. */
  41252     rv = _bcm_esw_field_stat_get (unit, sync_mode, stat_id, stat, &val64);
  41253     if (BCM_SUCCESS(rv)) {
  41254         *value = COMPILER_64_LO(val64);
  41255     }
  41256     return rv;
  41257 }
  41258 
  41259 
  41260 /*
  41261  * Function:
  41262  *      _bcm_field_meter_pair_mode_get
  41263  * Purpose:
  41264  *      Set the config settings for a policer entry.
  41265  * Parameters:
  41266  *      unit  - (IN) Unit number.
  41267  *      f_pl  - (IN) Policer config.
  41268  *      mode  - (OUT) Meter pair mode.
  41269  * Returns:
  41270  *      BCM_E_XXX
  41271  * Notes:
  41272  */
  41273 int
  41274 _bcm_field_meter_pair_mode_get(int unit, _field_policer_t *f_pl,
  41275                                uint32 *mode)
  41276 {
  41277     /* Input parameters check. */
  41278     if ((NULL == f_pl) || (NULL == mode)) {
  41279         return (BCM_E_PARAM);
  41280     }
  41281 
  41282     switch (f_pl->cfg.mode) {
  41283       case bcmPolicerModeSrTcmTsn:
  41284           if (f_pl->cfg.flags & BCM_POLICER_COLOR_BLIND) {
  41285               *mode = BCM_FIELD_METER_MODE_srTCM_COLOR_BLIND;
  41286           } else {
  41287               *mode = BCM_FIELD_METER_MODE_srTCM_COLOR_AWARE;
  41288           }
  41289           break;
  41290       case bcmPolicerModeSrTcmModified:
  41291       case bcmPolicerModeSrTcm:
  41292           if (f_pl->cfg.flags & BCM_POLICER_COLOR_BLIND) {
  41293               *mode = BCM_FIELD_METER_MODE_srTCM_COLOR_BLIND;
  41294           } else {
  41295               *mode = BCM_FIELD_METER_MODE_srTCM_COLOR_AWARE;
  41296           }
  41297           break;
  41298       case bcmPolicerModeCommitted:
  41299           *mode = BCM_FIELD_METER_MODE_FLOW;
  41300           break;
  41301       case bcmPolicerModeTrTcm:
  41302           if (f_pl->cfg.flags & BCM_POLICER_COLOR_BLIND) {
  41303               *mode = BCM_FIELD_METER_MODE_trTCM_COLOR_BLIND;
  41304           } else {
  41305               *mode = BCM_FIELD_METER_MODE_trTCM_COLOR_AWARE;
  41306           }
  41307           break;
  41308       case bcmPolicerModeTrTcmDs:
  41309       case bcmPolicerModeCoupledTrTcmDs:
  41310           if (f_pl->cfg.flags & BCM_POLICER_COLOR_BLIND) {
  41311               *mode = 4;
  41312           } else {
  41313               *mode = 5;
  41314           }
  41315           break;
  41316       case bcmPolicerModePassThrough:
  41317           if (SOC_IS_FIREBOLT2(unit)) {
  41318               *mode = 4;
  41319           } else {
  41320               *mode = BCM_FIELD_METER_MODE_DEFAULT;
  41321           }
  41322           break;
  41323       case bcmPolicerModeGreen:
  41324           *mode = BCM_FIELD_METER_MODE_DEFAULT;
  41325           break;
  41326       default:
  41327           return (BCM_E_INTERNAL);
  41328     }
  41329     return (BCM_E_NONE);
  41330 }
  41331 
  41332 /*
  41333  * Function:
  41334  *      _bcm_field_qualify_InPorts_get
  41335  * Purpose:
  41336  *      Get match criteria for bcmFieildQualifyInPorts
  41337  *                     qualifier from the field entry.
  41338  * Parameters:
  41339  *      unit  - (IN) Unit number.
  41340  *      entry - (IN) BCM field entry id.
  41341  *      qual  - (IN) BCM field qualifier.
  41342  *      data  - (OUT) Qualifier match data.
  41343  *      mask  - (OUT) Qualifier match mask.
  41344  * Returns:
  41345  *      BCM_E_XXX
  41346  * Notes:
  41347  */
  41348 int
  41349 _bcm_field_qualify_InPorts_get(int unit,  bcm_field_entry_t entry,
  41350                                bcm_field_qualify_t qual,
  41351                                bcm_pbmp_t *data,
  41352                                bcm_pbmp_t *mask)
  41353 {
  41354     _field_entry_t *f_ent;   /* Field entry pointer.        */
  41355     uint32 hw_data;          /* HW encoded qualifier data.  */
  41356     uint32 hw_mask;          /* HW encoding qualifier mask. */
  41357     int rv;                  /* Operation return status.    */
  41358 #if defined(BCM_TOMAHAWK_SUPPORT)
  41359     _field_stage_t *stage_fc; /* Stage operational Structure.  */
  41360     bcm_port_t  port;         /* Holds physical port number.   */
  41361     uint8        instance;    /* Field group pipe information. */
  41362     bcm_pbmp_t   valid_pbm;   /* Holds valid pbm supported     */
  41363 #endif
  41364     /* Input parameters check. */
  41365     if ((NULL == data) || (NULL == mask)) {
  41366         return (BCM_E_PARAM);
  41367     }
  41368 
  41369     rv = _bcm_field_entry_qual_get(unit, entry, qual, &f_ent);
  41370     if (BCM_FAILURE(rv)) {
  41371         return (rv);
  41372     }
  41373 
  41374 #if defined(BCM_RAPTOR_SUPPORT) || defined (BCM_TRX_SUPPORT)
  41375     if (soc_feature(unit, soc_feature_field_ingress_ipbm) ||
  41376         _BCM_FIELD_IS_SLICE_MODE_PBMP_SUPPORTED(f_ent->group->flags)) {
  41377 
  41378 #if defined(BCM_TOMAHAWK_SUPPORT)
  41379         /* For TH devices, reset the perpipe ports to the pbmp */
  41380         if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  41381             (qual == bcmFieldQualifyInPorts)) {
  41382 
  41383             /* Get the stage control structure. */
  41384             rv = _field_stage_control_get(unit, f_ent->group->stage_id,
  41385                                             &stage_fc);
  41386             BCM_IF_ERROR_RETURN(rv);
  41387 
  41388             if (bcmFieldGroupOperModePipeLocal == stage_fc->oper_mode) {
  41389                 instance = f_ent->group->instance;
  41390                 BCM_PBMP_ASSIGN(valid_pbm, PBMP_PIPE(unit,
  41391                                   f_ent->group->instance));
  41392             } else {
  41393                 instance = _BCM_FIELD_GLOBAL_GROUP;
  41394                 BCM_IF_ERROR_RETURN(_bcm_field_valid_pbmp_get(unit, &valid_pbm));
  41395             }
  41396             BCM_PBMP_CLEAR(*data);
  41397             BCM_PBMP_CLEAR(*mask);
  41398             switch (instance) {
  41399                 case _BCM_FIELD_PIPE0_GROUP:
  41400                 case _BCM_FIELD_PIPE1_GROUP:
  41401                 case _BCM_FIELD_PIPE2_GROUP:
  41402                 case _BCM_FIELD_PIPE3_GROUP:
  41403                 case _BCM_FIELD_PIPE4_GROUP:
  41404                 case _BCM_FIELD_PIPE5_GROUP:
  41405                 case _BCM_FIELD_PIPE6_GROUP:
  41406                 case _BCM_FIELD_PIPE7_GROUP:
  41407                     if (soc_feature(unit, soc_feature_td3_style_fp)) {
  41408                         BCM_PBMP_ASSIGN(*data, f_ent->pbmp.data);
  41409                         BCM_PBMP_ASSIGN(*mask, f_ent->pbmp.mask);
  41410                     } else {
  41411                         BCM_PBMP_ITER(f_ent->pbmp.data, port)  {
  41412                             BCM_PBMP_PORT_ADD(*data, port +
  41413                                     (_FP_TCAM_IPBMP_SIZE(unit) * f_ent->group->instance));
  41414                         }
  41415                         BCM_PBMP_ITER(f_ent->pbmp.mask, port)  {
  41416                             BCM_PBMP_PORT_ADD(*mask, port +
  41417                                     (_FP_TCAM_IPBMP_SIZE(unit) * f_ent->group->instance));
  41418                         }
  41419                     }
  41420                     break;
  41421                 case _BCM_FIELD_GLOBAL_GROUP:
  41422                     BCM_PBMP_ASSIGN(*data, f_ent->pbmp.data);
  41423                     BCM_PBMP_ASSIGN(*mask, f_ent->pbmp.mask);
  41424                     break;
  41425                 default:
  41426                     return BCM_E_INTERNAL;
  41427             }
  41428             BCM_PBMP_AND(*data, valid_pbm);
  41429             BCM_PBMP_AND(*mask, valid_pbm);
  41430         } else {
  41431             /* Add data & mask to entry. */
  41432             BCM_PBMP_ASSIGN(*data, f_ent->pbmp.data);
  41433             BCM_PBMP_ASSIGN(*mask, f_ent->pbmp.mask);
  41434         }
  41435 #else
  41436         /* Add data & mask to entry. */
  41437         BCM_PBMP_ASSIGN(*data, f_ent->pbmp.data);
  41438         BCM_PBMP_ASSIGN(*mask, f_ent->pbmp.mask);
  41439 #endif
  41440 
  41441         if (qual == bcmFieldQualifyInPorts) {
  41442            bcm_pbmp_t lb_pbm;       /* Loopback port bitmap. */
  41443 
  41444            /* Remove loopback port from ipbm data and mask */
  41445            BCM_PBMP_CLEAR(lb_pbm);
  41446            BCM_PBMP_OR(lb_pbm, PBMP_LB(unit));
  41447            if (BCM_PBMP_NOT_NULL(lb_pbm)) {
  41448               BCM_PBMP_REMOVE(*data, PBMP_LB(unit));
  41449               BCM_PBMP_REMOVE(*mask, PBMP_LB(unit));
  41450            }
  41451 #if defined(BCM_MONTEREY_SUPPORT) && defined(INCLUDE_XFLOW_MACSEC)
  41452            /* Remove MACSEC Port from IPBM mask */
  41453            if (soc_feature(unit, soc_feature_xflow_macsec)) {
  41454                bcm_pbmp_t       macsec_pbm;
  41455                BCM_PBMP_CLEAR(macsec_pbm);
  41456                BCM_PBMP_OR(macsec_pbm, PBMP_MACSEC_ALL(unit));
  41457                if (BCM_PBMP_NOT_NULL(macsec_pbm)) {
  41458                    BCM_PBMP_REMOVE(*mask, PBMP_MACSEC_ALL(unit));
  41459                }
  41460            }
  41461 #endif
  41462         }
  41463 
  41464         return (BCM_E_NONE);
  41465     }
  41466 #endif /* BCM_RAPTOR_SUPPORT || BCM_TRX_SUPPORT */
  41467 
  41468     /* Read qualifier match value and mask. */
  41469     rv = _bcm_field_entry_qualifier_uint32_get(unit, entry, qual,
  41470                                               (uint32 *)&hw_data,
  41471                                               (uint32 *)&hw_mask);
  41472     BCM_IF_ERROR_RETURN(rv);
  41473 
  41474     SOC_PBMP_WORD_SET(*data, 0, hw_data);
  41475     SOC_PBMP_WORD_SET(*mask, 0, hw_mask);
  41476     return (rv);
  41477 }
  41478 
  41479 /*
  41480  * Function:
  41481  *      bcm_esw_field_qualify_PacketRes_get
  41482  * Purpose:
  41483  *      Get match criteria for bcmFieildQualifyPacketRes
  41484  *                     qualifier from the field entry.
  41485  * Parameters:
  41486  *      unit - (IN) Unit number.
  41487  *      entry - (IN) BCM field entry id.
  41488  *      data - (OUT) Qualifier match data.
  41489  *      mask - (OUT) Qualifier match mask.
  41490  * Returns:
  41491  *      BCM_E_XXX
  41492  * Notes:
  41493  */
  41494 int
  41495 _field_qualify_PacketRes_get(int               unit,
  41496                              bcm_field_entry_t entry,
  41497                              uint32            *data,
  41498                              uint32            *mask
  41499                              )
  41500 {
  41501     /* Translate data #defines to hardware encodings */
  41502     switch (*data) {
  41503     case 0x0:
  41504         *data = BCM_FIELD_PKT_RES_UNKNOWN;
  41505         break;
  41506     case 0x1:
  41507         *data = BCM_FIELD_PKT_RES_CONTROL;
  41508         break;
  41509     case 0x2:
  41510         *data = BCM_FIELD_PKT_RES_BPDU;
  41511         break;
  41512     case 0x3:
  41513         *data = BCM_FIELD_PKT_RES_L2BC;
  41514         break;
  41515     case 0x4:
  41516         *data = BCM_FIELD_PKT_RES_L2UC;
  41517         break;
  41518     case 0x5:
  41519         *data = BCM_FIELD_PKT_RES_L2UNKNOWN;
  41520         break;
  41521     case 0x6:
  41522         *data = BCM_FIELD_PKT_RES_L3MCUNKNOWN;
  41523         break;
  41524     case 0x7:
  41525         *data = BCM_FIELD_PKT_RES_L3MCKNOWN;
  41526         break;
  41527     case 0x8:
  41528         *data = BCM_FIELD_PKT_RES_L2MCKNOWN;
  41529         break;
  41530     case 0x9:
  41531         *data = BCM_FIELD_PKT_RES_L2MCUNKNOWN;
  41532         break;
  41533     case 0xa:
  41534         *data = BCM_FIELD_PKT_RES_L3UCKNOWN;
  41535         break;
  41536     case 0xb:
  41537         *data = BCM_FIELD_PKT_RES_L3UCUNKNOWN;
  41538         break;
  41539     case 0xc:
  41540         *data = BCM_FIELD_PKT_RES_MPLSKNOWN;
  41541         break;
  41542     case 0xd:
  41543         *data = BCM_FIELD_PKT_RES_MPLSL3KNOWN;
  41544         break;
  41545     case 0xe:
  41546         *data = BCM_FIELD_PKT_RES_MPLSL2KNOWN;
  41547         break;
  41548     case 0xf:
  41549         *data = BCM_FIELD_PKT_RES_MPLSUNKNOWN;
  41550         break;
  41551     case 0x10:
  41552         *data = BCM_FIELD_PKT_RES_MIMKNOWN;
  41553         break;
  41554     case 0x11:
  41555         *data = BCM_FIELD_PKT_RES_MIMUNKNOWN;
  41556         break;
  41557 
  41558     default:
  41559         return (BCM_E_INTERNAL);
  41560     }
  41561     *mask = BCM_FIELD_EXACT_MATCH_MASK;
  41562 
  41563     return (BCM_E_NONE);
  41564 }
  41565 
  41566 
  41567 /*
  41568  * Function:
  41569  *     _bcm_field_entry_backup
  41570  * Purpose:
  41571  *     Backup a field entry configuration.
  41572  * Parameters:
  41573  *     unit       - (IN) BCM device number
  41574  *     entry_id   - (IN) Entry identifier
  41575  * Returns:
  41576  *      BCM_E_XXX
  41577  */
  41578 int
  41579 _bcm_field_entry_backup(int unit, bcm_field_entry_t entry_id)
  41580 {
  41581     _field_entry_t      *f_ent_orig;        /* Field entry to be backed up.   */
  41582     _field_entry_t      *f_ent_copy = NULL; /* Backup copy of field entry.    */
  41583     _field_action_t     *fa_orig;           /* Pointer to entry action list.  */
  41584     _field_action_t     *fa = NULL;         /* Field action descriptor.       */
  41585     _field_action_t     *fa_free = NULL;    /* Field action descriptor.       */
  41586     _field_stat_t       *f_st;              /* Internal Statisics descriptor. */
  41587     _field_policer_t    *f_pl;              /* Internal policer descriptor.   */
  41588     int                 free_tcam = FALSE;  /* KEY/MASK memory alloc status.  */
  41589     int                 parts_count = 0;    /* Entry parts count.             */
  41590     int                 i;                  /* Iterator variable.             */
  41591     int                 rv;                 /* Operation return status.       */
  41592     uint32              mem_sz;             /* Field entry alloc size.        */
  41593 
  41594 
  41595     FP_LOCK(unit);
  41596 
  41597     rv = _bcm_field_entry_get_by_id(unit,
  41598                                     entry_id,
  41599                                     &f_ent_orig);
  41600     if (BCM_FAILURE(rv)) {
  41601         FP_UNLOCK(unit);
  41602         return (rv);
  41603     }
  41604 
  41605     if (NULL != f_ent_orig->ent_copy) {
  41606         rv = _bcm_field_entry_cleanup(unit, entry_id);
  41607         if (BCM_FAILURE(rv)) {
  41608             FP_UNLOCK(unit);
  41609             return (rv);
  41610         }
  41611     }
  41612 
  41613     /* Get number of entry parts . */
  41614     rv = _bcm_field_entry_tcam_parts_count(unit,
  41615                                            f_ent_orig->group->stage_id,
  41616                                            f_ent_orig->group->flags,
  41617                                            &parts_count);
  41618     if (BCM_FAILURE(rv)) {
  41619         FP_UNLOCK(unit);
  41620         return (rv);
  41621     }
  41622 
  41623     mem_sz = parts_count * sizeof(_field_entry_t);
  41624 
  41625     _FP_XGS3_ALLOC(f_ent_copy, mem_sz, "field entry copy");
  41626     if (f_ent_copy == NULL) {
  41627         LOG_ERROR(BSL_LS_BCM_FP,
  41628                   (BSL_META_U(unit,
  41629                               "FP(unit %d) Error: allocation failure for field_entry\n"),
  41630                    unit));
  41631         FP_UNLOCK(unit);
  41632         return (BCM_E_MEMORY);
  41633     }
  41634 
  41635 
  41636     for (i = 0; i < parts_count; i++) {
  41637 
  41638         f_ent_copy[i].eid = f_ent_orig[i].eid;
  41639         f_ent_copy[i].prio = f_ent_orig[i].prio;
  41640         f_ent_copy[i].slice_idx = f_ent_orig[i].slice_idx;
  41641         f_ent_copy[i].fs = f_ent_orig[i].fs;
  41642         f_ent_copy[i].group = f_ent_orig[i].group;
  41643         f_ent_copy[i].flags = f_ent_orig[i].flags;
  41644 
  41645 #if defined(BCM_TRIDENT2_SUPPORT)
  41646     if (SOC_IS_TD2_TT2(unit) &&
  41647         (f_ent_copy[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) {
  41648         f_ent_copy->efp_key_match_type = f_ent_orig->efp_key_match_type;
  41649     }
  41650 #endif
  41651 
  41652         if (NULL == f_ent_orig[i].tcam.key) {
  41653             free_tcam = TRUE;
  41654         }
  41655 
  41656         rv = _bcm_field_qual_tcam_key_mask_get(unit, f_ent_orig + i);
  41657         if (BCM_FAILURE(rv)) {
  41658             goto cleanup;
  41659         }
  41660 
  41661         /*
  41662          * Calling backup routine for the second time, means
  41663          * TCAM buffer already allocated needs to be freed.
  41664          */
  41665         rv = _bcm_field_qual_tcam_key_mask_free(unit, f_ent_copy + i);
  41666         if (BCM_FAILURE(rv)) {
  41667             goto cleanup;
  41668         }
  41669 
  41670         /* Copy qualification data. */
  41671         sal_memcpy(&f_ent_copy[i].tcam, &f_ent_orig[i].tcam,
  41672                    sizeof(_field_tcam_t));
  41673         sal_memcpy(&f_ent_copy[i].extra_tcam, &f_ent_orig[i].extra_tcam,
  41674                    sizeof(_field_tcam_t));
  41675 #if defined(BCM_TRIDENT2_SUPPORT)
  41676         if (SOC_IS_TD2_TT2(unit) &&
  41677             (f_ent_copy[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) {
  41678             sal_memcpy(&f_ent_copy[i].key_match_tcam,
  41679                        &f_ent_orig[i].key_match_tcam,
  41680                        sizeof(_field_tcam_t));
  41681         }
  41682 #endif
  41683 
  41684         f_ent_copy[i].tcam.key  = NULL;/* Do not copy allocated part.*/
  41685         f_ent_copy[i].tcam.mask = NULL;/* Do not copy allocated part.*/
  41686         f_ent_copy[i].extra_tcam.key  = NULL;/* Do not copy allocated part.*/
  41687         f_ent_copy[i].extra_tcam.mask = NULL;/* Do not copy allocated part.*/
  41688         if (f_ent_copy[i].fs->stage_id == _BCM_FIELD_STAGE_EXTERNAL) {
  41689             f_ent_copy[i].tcam.key_hw = NULL;
  41690             f_ent_copy[i].tcam.mask_hw = NULL;
  41691         }
  41692 #if defined(BCM_TRIDENT2_SUPPORT)
  41693         if (SOC_IS_TD2_TT2(unit) &&
  41694             (f_ent_copy[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) {
  41695             f_ent_copy[i].key_match_tcam.key  = NULL; /* Do not copy
  41696                                                          allocated part.*/
  41697             f_ent_copy[i].key_match_tcam.mask = NULL; /* Do not copy
  41698                                                          allocated part.*/
  41699         }
  41700 #endif
  41701 
  41702         /* Allocate tcam key and mask for destination entry. */
  41703         rv = _bcm_field_qual_tcam_key_mask_get(unit,  f_ent_copy + i);
  41704         if (BCM_FAILURE(rv)) {
  41705             goto cleanup;
  41706         }
  41707 
  41708         /* Copy key and mask information. */
  41709         sal_memcpy(f_ent_copy[i].tcam.key, f_ent_orig[i].tcam.key,
  41710                    f_ent_copy[i].tcam.key_size);
  41711         sal_memcpy(f_ent_copy[i].tcam.mask, f_ent_orig[i].tcam.mask,
  41712                    f_ent_copy[i].tcam.key_size);
  41713 
  41714         if (f_ent_orig[i].flags & _FP_ENTRY_USES_IPBM_OVERLAY) {
  41715             sal_memcpy(f_ent_copy[i].extra_tcam.key,
  41716                 f_ent_orig[i].extra_tcam.key,
  41717                 f_ent_orig[i].extra_tcam.key_size);
  41718 
  41719             sal_memcpy(f_ent_copy[i].extra_tcam.mask,
  41720                 f_ent_orig[i].extra_tcam.mask,
  41721                 f_ent_orig[i].extra_tcam.key_size);
  41722         }
  41723 
  41724         if (f_ent_orig[i].fs->stage_id == _BCM_FIELD_STAGE_EXTERNAL) {
  41725             sal_memcpy(f_ent_copy[i].tcam.key_hw,
  41726                        f_ent_orig[i].tcam.key_hw,
  41727                        f_ent_orig[i].tcam.key_size);
  41728             sal_memcpy(f_ent_copy[i].tcam.mask_hw,
  41729                        f_ent_orig[i].tcam.mask_hw,
  41730                        f_ent_orig[i].tcam.key_size);
  41731         }
  41732 #if defined(BCM_TRIDENT2_SUPPORT)
  41733         if (SOC_IS_TD2_TT2(unit) &&
  41734             (f_ent_copy[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) {
  41735             /* Copy key and mask information. */
  41736             sal_memcpy(f_ent_copy[i].key_match_tcam.key,
  41737                        f_ent_orig[i].key_match_tcam.key,
  41738                        f_ent_copy[i].key_match_tcam.key_size);
  41739             sal_memcpy(f_ent_copy[i].key_match_tcam.mask,
  41740                        f_ent_orig[i].key_match_tcam.mask,
  41741                        f_ent_copy[i].key_match_tcam.key_size);
  41742 
  41743         }
  41744 #endif
  41745         if (free_tcam) {
  41746 
  41747             if (NULL != f_ent_orig[i].tcam.key) {
  41748                 sal_free(f_ent_orig[i].tcam.key);
  41749                 sal_free(f_ent_orig[i].tcam.mask);
  41750             }
  41751 
  41752             if (f_ent_orig[i].flags & _FP_ENTRY_USES_IPBM_OVERLAY) {
  41753                 if (NULL != f_ent_orig[i].extra_tcam.key) {
  41754                     sal_free(f_ent_orig[i].extra_tcam.key);
  41755                     sal_free(f_ent_orig[i].extra_tcam.mask);
  41756                 }
  41757             }
  41758 
  41759             f_ent_orig[i].tcam.key = f_ent_orig[i].tcam.mask =
  41760                 f_ent_orig[i].extra_tcam.key = f_ent_orig[i].extra_tcam.mask =
  41761                     NULL;
  41762 #if defined(BCM_TRIDENT2_SUPPORT)
  41763         if (SOC_IS_TD2_TT2(unit) &&
  41764             (f_ent_copy[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) {
  41765             if (NULL != f_ent_orig[i].key_match_tcam.key) {
  41766                 sal_free(f_ent_orig[i].key_match_tcam.key);
  41767                 sal_free(f_ent_orig[i].key_match_tcam.mask);
  41768             }
  41769             f_ent_orig[i].key_match_tcam.key = NULL;
  41770             f_ent_orig[i].key_match_tcam.mask = NULL;
  41771         }
  41772 #endif
  41773             free_tcam = FALSE;
  41774         }
  41775     }
  41776 
  41777 #if defined(BCM_RAPTOR_SUPPORT) || defined (BCM_TRX_SUPPORT)
  41778     if (soc_feature(unit, soc_feature_field_ingress_ipbm) ||
  41779         _BCM_FIELD_IS_SLICE_MODE_PBMP_SUPPORTED(f_ent_orig->group->flags)) {
  41780         BCM_PBMP_ASSIGN(f_ent_copy->pbmp.data, f_ent_orig->pbmp.data);
  41781         BCM_PBMP_ASSIGN(f_ent_copy->pbmp.mask, f_ent_orig->pbmp.mask);
  41782     }
  41783 #endif /* BCM_RAPTOR_SUPPORT || BCM_TRX_SUPPORT */
  41784 
  41785     if (f_ent_orig->statistic.flags & _FP_ENTRY_STAT_VALID) {
  41786 
  41787         /* Get statistics entity  description structure. */
  41788         rv = _bcm_field_stat_get(unit, f_ent_orig->statistic.sid, &f_st);
  41789         if (BCM_FAILURE(rv)) {
  41790             goto cleanup;
  41791         }
  41792 
  41793         f_ent_copy->statistic.sid = f_ent_orig->statistic.sid;
  41794 
  41795         /* Increment statistics entity reference counter. */
  41796         f_st->sw_ref_count++;
  41797 
  41798         f_ent_copy->statistic.flags = f_ent_orig->statistic.flags;
  41799 
  41800     }
  41801 
  41802     /*  Copy meter, if it exists. */
  41803     for (i = 0; i < _FP_POLICER_LEVEL_COUNT; i++)  {
  41804 
  41805         if (f_ent_orig->policer[i].flags & _FP_POLICER_VALID) {
  41806 
  41807             /* Get policer description structure. */
  41808             rv = _bcm_field_policer_get(unit,
  41809                                         f_ent_orig->policer[i].pid,
  41810                                         &f_pl);
  41811             if (BCM_FAILURE(rv)) {
  41812                 goto cleanup;
  41813             }
  41814 
  41815             f_ent_copy->policer[i].pid = f_ent_orig->policer[i].pid;
  41816 
  41817             /* Increment policer reference counter. */
  41818             f_pl->sw_ref_count++;
  41819 
  41820             f_ent_copy->policer[i].flags = f_ent_orig->policer[i].flags;
  41821         }
  41822     }
  41823 
  41824     for (fa_orig = f_ent_orig->actions;
  41825         fa_orig != NULL;
  41826         fa_orig = fa_orig->next) {
  41827         rv = _field_action_alloc(unit,
  41828                                 fa_orig->action,
  41829                                 fa_orig->param[0],
  41830                                 fa_orig->param[1],
  41831                                 fa_orig->param[2],
  41832                                 fa_orig->param[3],
  41833                                 fa_orig->param[4],
  41834                                 fa_orig->param[5],
  41835                                 &fa);
  41836         if (BCM_FAILURE(rv)) {
  41837             LOG_ERROR(BSL_LS_BCM_FP,
  41838                       (BSL_META_U(unit,
  41839                                   "FP(unit %d) Error: failure in _field_action_alloc()\n"),
  41840                        unit));
  41841             goto cleanup;
  41842         }
  41843 
  41844         fa->next = f_ent_copy->actions;
  41845         fa->flags |= fa_orig->flags;
  41846         fa->hw_index = fa_orig->hw_index;
  41847         fa->old_index = fa_orig->old_index;
  41848         f_ent_copy->actions = fa;
  41849     }
  41850 
  41851     /*Remove the Installed and Enabled flags in the backup copy
  41852     so that restore and install updates tcam*/
  41853     f_ent_copy->flags |= _FP_ENTRY_DIRTY;
  41854     f_ent_copy->flags &= ~_FP_ENTRY_INSTALLED;
  41855     f_ent_copy->flags &= ~_FP_ENTRY_ENABLED;
  41856 
  41857     f_ent_orig->ent_copy = f_ent_copy;
  41858 
  41859     FP_UNLOCK(unit);
  41860     return (BCM_E_NONE);
  41861 
  41862 cleanup:
  41863 
  41864     fa = f_ent_copy->actions;
  41865     while (fa != NULL) {
  41866         fa_free = fa;
  41867         fa = fa->next;
  41868         sal_free(fa_free);
  41869     }
  41870 
  41871     for (i = 0; i < parts_count; i++) {
  41872         _bcm_field_qual_tcam_key_mask_free(unit, f_ent_copy + i);
  41873     }
  41874 
  41875     if (NULL != f_ent_copy) {
  41876         sal_free(f_ent_copy);
  41877     }
  41878 
  41879     FP_UNLOCK(unit);
  41880     return (rv);
  41881 }
  41882 
  41883 /*
  41884  * Function:
  41885  *     _bcm_field_entry_restore
  41886  * Purpose:
  41887  *     Restore the configuration of a field entry from backup. Resources
  41888  *     allocated for the backup entry are released by calling the API
  41889  *     with BCM_FIELD_ENTRY_OPER_CLEANUP flag bit set.
  41890  * Parameters:
  41891  *     unit         - (IN) BCM device number
  41892  *     entry_id   - (IN) Entry identifier
  41893  * Returns:
  41894  *      BCM_E_XXX
  41895  */
  41896 int
  41897 _bcm_field_entry_restore(int unit, bcm_field_entry_t entry_id)
  41898 {
  41899     _field_entry_t      *f_ent_orig;
  41900     _field_entry_t      *f_ent_copy;
  41901     _field_action_t     *fa_copy;
  41902     _field_action_t     *fa = NULL;         /* Field action descriptor.       */
  41903     _field_action_t     *fa_iter = NULL;    /* Field action descriptor.       */
  41904     _field_stat_t       *f_st;          /* Internal statisics descriptor. */
  41905     _field_policer_t    *f_pl;          /* Internal policer descriptor.   */
  41906     int                 parts_count = 0;
  41907     int                 i;
  41908     int                 rv;
  41909 
  41910 
  41911 
  41912     FP_LOCK(unit);
  41913 
  41914     rv = _bcm_field_entry_get_by_id(unit,
  41915                                     entry_id,
  41916                                     &f_ent_orig);
  41917     if (BCM_FAILURE(rv)) {
  41918         FP_UNLOCK(unit);
  41919         LOG_ERROR(BSL_LS_BCM_FP,
  41920                   (BSL_META_U(unit,
  41921                               "FP(unit %d) Error: failure in "
  41922                                "bcm_esw_field_entry_policer_detach() - rv:%s\n"),
  41923                    unit, bcm_errmsg(rv)));
  41924         return (rv);
  41925     }
  41926 
  41927     if (NULL == f_ent_orig->ent_copy) {
  41928         FP_UNLOCK(unit);
  41929         return (BCM_E_NOT_FOUND);
  41930     }
  41931 
  41932     /* Detach any attached policers. */
  41933     for (i = 0; i < _FP_POLICER_LEVEL_COUNT; i++)  {
  41934         if (f_ent_orig->policer[i].flags & _FP_POLICER_VALID) {
  41935             rv = bcm_esw_field_entry_policer_detach(unit,
  41936                                                     f_ent_orig->eid,
  41937                                                     i);
  41938             if (BCM_FAILURE(rv)) {
  41939                 FP_UNLOCK(unit);
  41940                 LOG_ERROR(BSL_LS_BCM_FP,
  41941                           (BSL_META_U(unit,
  41942                                       "FP(unit %d) Error: failure in "
  41943                                        "bcm_esw_field_entry_policer_detach() - rv:%s\n"),
  41944                            unit, bcm_errmsg(rv)));
  41945                 return (rv);
  41946             }
  41947         }
  41948     }
  41949 
  41950     /* Detach attached STATs. */
  41951     if (f_ent_orig->statistic.flags & _FP_ENTRY_STAT_VALID) {
  41952         rv = bcm_esw_field_entry_stat_detach(unit,
  41953                                              f_ent_orig->eid,
  41954                                              f_ent_orig->statistic.sid);
  41955         if (BCM_FAILURE(rv)) {
  41956             FP_UNLOCK(unit);
  41957             LOG_ERROR(BSL_LS_BCM_FP,
  41958                       (BSL_META_U(unit,
  41959                                   "FP(unit %d) Error: failure in "
  41960                                    "bcm_esw_field_stat_detach() - rv:%s\n"),
  41961                        unit, bcm_errmsg(rv)));
  41962             return (rv);
  41963         }
  41964     }
  41965 
  41966     /* Remove all actions set for this entry. */
  41967     rv = bcm_esw_field_action_remove_all(unit, f_ent_orig->eid);
  41968     if (BCM_FAILURE(rv)) {
  41969         FP_UNLOCK(unit);
  41970         LOG_ERROR(BSL_LS_BCM_FP,
  41971                   (BSL_META_U(unit,
  41972                               "FP(unit %d) Error: failure in "
  41973                                "bcm_esw_field_action_remove_all() - rv:%s\n"),
  41974                    unit, bcm_errmsg(rv)));
  41975         return (rv);
  41976     }
  41977 
  41978     /* Clear qualifiers set for this entry. */
  41979     rv = bcm_esw_field_qualify_clear(unit, f_ent_orig->eid);
  41980     if (BCM_FAILURE(rv)) {
  41981         FP_UNLOCK(unit);
  41982         LOG_ERROR(BSL_LS_BCM_FP,
  41983                   (BSL_META_U(unit,
  41984                               "FP(unit %d) Error: failure in "
  41985                                "bcm_esw_field_qualify_clear() - rv:%s\n"),
  41986                    unit, bcm_errmsg(rv)));
  41987         return (rv);
  41988     }
  41989 
  41990     /* Get the backup entry pointer. */
  41991     f_ent_copy = f_ent_orig->ent_copy;
  41992 
  41993     /* Get number of entry parts . */
  41994     rv = _bcm_field_entry_tcam_parts_count(unit,
  41995                                            f_ent_orig->group->stage_id,
  41996                                            f_ent_orig->group->flags,
  41997                                            &parts_count);
  41998     if (BCM_FAILURE(rv)) {
  41999         FP_UNLOCK(unit);
  42000         return (rv);
  42001     }
  42002 
  42003     for (i = 0; i < parts_count; i++) {
  42004         f_ent_orig[i].eid = f_ent_copy[i].eid;
  42005         f_ent_orig[i].group = f_ent_copy[i].group;
  42006         f_ent_orig[i].flags = f_ent_copy[i].flags;
  42007 
  42008 #if defined(BCM_TRIDENT2_SUPPORT)
  42009     if (SOC_IS_TD2_TT2(unit) &&
  42010         (f_ent_orig[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) {
  42011         f_ent_orig->efp_key_match_type = f_ent_copy->efp_key_match_type;
  42012     }
  42013 #endif
  42014 
  42015         /* Free allocated portion of sw tcam image. */
  42016         _bcm_field_qual_tcam_key_mask_free(unit, &f_ent_orig[i]);
  42017         if (BCM_FAILURE(rv)) {
  42018            FP_UNLOCK(unit);
  42019            return (rv);
  42020         }
  42021 
  42022         /* Copy qualification data. */
  42023         sal_memcpy(&f_ent_orig[i].tcam, &f_ent_copy[i].tcam,
  42024                     sizeof(_field_tcam_t));
  42025         sal_memcpy(&f_ent_orig[i].extra_tcam, &f_ent_copy[i].extra_tcam,
  42026                     sizeof(_field_tcam_t));
  42027 
  42028 #if defined(BCM_TRIDENT2_SUPPORT)
  42029         if (SOC_IS_TD2_TT2(unit) &&
  42030             (f_ent_orig[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) {
  42031             sal_memcpy(&f_ent_orig[i].key_match_tcam,
  42032                        &f_ent_copy[i].key_match_tcam,
  42033                        sizeof(_field_tcam_t));
  42034         }
  42035 #endif
  42036         f_ent_orig[i].tcam.key  = NULL; /* Do not copy allocated part.*/
  42037         f_ent_orig[i].tcam.mask = NULL; /* Do not copy allocated part.*/
  42038         f_ent_orig[i].extra_tcam.key  = NULL; /* Do not copy allocated part.*/
  42039         f_ent_orig[i].extra_tcam.mask = NULL; /* Do not copy allocated part.*/
  42040 
  42041         if (f_ent_orig[i].fs->stage_id == _BCM_FIELD_STAGE_EXTERNAL) {
  42042             f_ent_orig[i].tcam.key_hw = NULL;
  42043             f_ent_orig[i].tcam.mask_hw = NULL;
  42044         }
  42045 #if defined(BCM_TRIDENT2_SUPPORT)
  42046         if (SOC_IS_TD2_TT2(unit) &&
  42047             (f_ent_orig[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) {
  42048             f_ent_orig[i].key_match_tcam.key  = NULL; /* Do not copy
  42049                                                          allocated part.*/
  42050             f_ent_orig[i].key_match_tcam.mask = NULL; /* Do not copy
  42051                                                          allocated part.*/
  42052         }
  42053 #endif
  42054         if (f_ent_copy[i].flags & _FP_ENTRY_DIRTY) {
  42055 
  42056             /* Allocate tcam key and mask for entry. */
  42057             rv = _bcm_field_qual_tcam_key_mask_get(unit,  f_ent_orig + i);
  42058             if (BCM_FAILURE(rv)) {
  42059                 FP_UNLOCK(unit);
  42060                 return (rv);
  42061             }
  42062 
  42063             /* Copy key and mask information. */
  42064             sal_memcpy(f_ent_orig[i].tcam.key, f_ent_copy[i].tcam.key,
  42065                 f_ent_copy[i].tcam.key_size);
  42066             sal_memcpy(f_ent_orig[i].tcam.mask, f_ent_copy[i].tcam.mask,
  42067                 f_ent_copy[i].tcam.key_size);
  42068             if (f_ent_orig[i].flags & _FP_ENTRY_USES_IPBM_OVERLAY) {
  42069                 sal_memcpy(f_ent_orig[i].extra_tcam.key,
  42070                     f_ent_copy[i].extra_tcam.key,
  42071                     f_ent_copy[i].extra_tcam.key_size);
  42072                 sal_memcpy(f_ent_orig[i].extra_tcam.mask,
  42073                     f_ent_copy[i].extra_tcam.mask,
  42074                     f_ent_copy[i].extra_tcam.key_size);
  42075             }
  42076 
  42077             if (f_ent_orig[i].fs->stage_id == _BCM_FIELD_STAGE_EXTERNAL) {
  42078                 sal_memcpy(f_ent_orig[i].tcam.key_hw,
  42079                     f_ent_copy[i].tcam.key_hw,
  42080                     f_ent_copy[i].tcam.key_size);
  42081                 sal_memcpy(f_ent_orig[i].tcam.mask_hw,
  42082                     f_ent_copy[i].tcam.mask_hw,
  42083                     f_ent_copy[i].tcam.key_size);
  42084             }
  42085 
  42086 #if defined(BCM_TRIDENT2_SUPPORT)
  42087         if (SOC_IS_TD2_TT2(unit) &&
  42088             (f_ent_orig[i].fs->stage_id == _BCM_FIELD_STAGE_EGRESS)) {
  42089             /* Copy key and mask information. */
  42090             sal_memcpy(f_ent_orig[i].key_match_tcam.key,
  42091                        f_ent_copy[i].key_match_tcam.key,
  42092                        f_ent_orig[i].key_match_tcam.key_size);
  42093             sal_memcpy(f_ent_orig[i].key_match_tcam.mask,
  42094                        f_ent_copy[i].key_match_tcam.mask,
  42095                        f_ent_orig[i].key_match_tcam.key_size);
  42096 
  42097         }
  42098 #endif
  42099         }
  42100     }
  42101 
  42102 #if defined(BCM_RAPTOR_SUPPORT) || defined (BCM_TRX_SUPPORT)
  42103     if (soc_feature(unit, soc_feature_field_ingress_ipbm) ||
  42104         _BCM_FIELD_IS_SLICE_MODE_PBMP_SUPPORTED(f_ent_copy->group->flags)) {
  42105         BCM_PBMP_ASSIGN(f_ent_orig->pbmp.data, f_ent_copy->pbmp.data);
  42106         BCM_PBMP_ASSIGN(f_ent_orig->pbmp.mask, f_ent_copy->pbmp.mask);
  42107     }
  42108 #endif /* BCM_RAPTOR_SUPPORT || BCM_TRX_SUPPORT */
  42109 
  42110     if (f_ent_copy->statistic.flags & _FP_ENTRY_STAT_VALID) {
  42111 
  42112         /* Get statistics entity  description structure. */
  42113         rv = _bcm_field_stat_get(unit, f_ent_copy->statistic.sid, &f_st);
  42114         if (BCM_FAILURE(rv)) {
  42115             FP_UNLOCK(unit);
  42116             return (rv);
  42117         }
  42118 
  42119         /* Decrement statistics entity reference counter. */
  42120         f_st->sw_ref_count--;
  42121 
  42122         rv = bcm_esw_field_entry_stat_attach(unit, f_ent_orig->eid,
  42123                                              f_ent_copy->statistic.sid);
  42124         if (BCM_FAILURE(rv)) {
  42125             FP_UNLOCK(unit);
  42126             return (rv);
  42127         }
  42128 
  42129         f_ent_copy->statistic.flags
  42130             = (f_ent_orig->statistic.flags
  42131                 & (_FP_ENTRY_STAT_VALID | _FP_ENTRY_STAT_EMPTY
  42132                     | _FP_ENTRY_STAT_USE_EVEN | _FP_ENTRY_STAT_USE_ODD));
  42133 
  42134     }
  42135 
  42136     /*  Copy meter, if it exists. */
  42137     for (i = 0; i < _FP_POLICER_LEVEL_COUNT; i++)  {
  42138 
  42139         if (f_ent_copy->policer[i].flags & _FP_POLICER_VALID) {
  42140 
  42141             /* Get policer description structure. */
  42142             rv = _bcm_field_policer_get(unit,
  42143                                         f_ent_copy->policer[i].pid,
  42144                                         &f_pl);
  42145             if (BCM_FAILURE(rv)) {
  42146                 FP_UNLOCK(unit);
  42147                 return (rv);
  42148             }
  42149 
  42150             /* Decrement policer entity reference counter. */
  42151             f_pl->sw_ref_count--;
  42152 
  42153             rv = bcm_esw_field_entry_policer_attach(unit,
  42154                                                     f_ent_orig->eid,
  42155                                                     i,
  42156                                                     f_ent_copy->policer[i].pid);
  42157             if (BCM_FAILURE(rv)) {
  42158                 FP_UNLOCK(unit);
  42159                 return (rv);
  42160             }
  42161         }
  42162     }
  42163 
  42164     for (fa_copy = f_ent_copy->actions;
  42165         fa_copy != NULL;
  42166         fa_copy = fa_copy->next) {
  42167         rv = _field_action_alloc(unit,
  42168                                 fa_copy->action,
  42169                                 fa_copy->param[0],
  42170                                 fa_copy->param[1],
  42171                                 fa_copy->param[2],
  42172                                 fa_copy->param[3],
  42173                                 fa_copy->param[4],
  42174                                 fa_copy->param[5],
  42175                                 &fa);
  42176         if (BCM_FAILURE(rv)) {
  42177             LOG_ERROR(BSL_LS_BCM_FP,
  42178                       (BSL_META_U(unit,
  42179                                   "FP(unit %d) Error: failure in _field_action_alloc()\n"),
  42180                        unit));
  42181             FP_UNLOCK(unit);
  42182             return (rv);
  42183         }
  42184 
  42185         fa->next = f_ent_orig->actions;
  42186         fa->flags |= fa_copy->flags;
  42187         f_ent_orig->actions = fa;
  42188     }
  42189 
  42190     /* Free resources allocated for entry dirty actions. */
  42191     rv = _field_invalid_actions_remove(unit, f_ent_orig);
  42192     if (BCM_FAILURE(rv)) {
  42193         FP_UNLOCK(unit);
  42194         LOG_ERROR(BSL_LS_BCM_FP,
  42195                   (BSL_META_U(unit,
  42196                               "FP(unit %d) Error: failure in "
  42197                                "_field_invalid_actions_remove() - rv:%s\n"),
  42198                    unit, bcm_errmsg(rv)));
  42199         return (rv);
  42200     }
  42201 
  42202     /* Update hardware index for profiled actions. */
  42203     for (fa = f_ent_copy->actions;
  42204         fa != NULL;
  42205         fa = fa->next) {
  42206 
  42207         if (_FP_INVALID_INDEX != fa->hw_index) {
  42208             fa_iter = f_ent_orig->actions;
  42209             while (fa_iter != NULL) {
  42210                 if ((1 == (fa_iter->flags & _FP_ACTION_VALID))
  42211                         && (fa_iter->action == fa->action)
  42212                         && (_FP_INVALID_INDEX == fa_iter->hw_index)) {
  42213                     fa_iter->hw_index = fa->hw_index;
  42214                     fa_iter->old_index = fa->old_index;
  42215                     break;
  42216                 }
  42217                 fa_iter = fa_iter->next;
  42218             }
  42219         }
  42220     }
  42221 
  42222     /* Restore the entry priority. */
  42223     if (!(f_ent_copy->flags & _FP_ENTRY_CREATED_WITHOUT_PRIO)) {
  42224         rv = _field_entry_prio_set(unit, entry_id, f_ent_copy[0].prio);
  42225     }
  42226 
  42227     FP_UNLOCK(unit);
  42228     return (rv);
  42229 
  42230 }
  42231 
  42232 /*
  42233  * Function:
  42234  *     _bcm_field_entry_cleanup
  42235  * Purpose:
  42236  *     Release the resources allocated for the back entry.
  42237  * Parameters:
  42238  *     unit         - (IN) BCM device number
  42239  *     entry_id   - (IN) Entry identifier
  42240  * Returns:
  42241  *      BCM_E_XXX
  42242  */
  42243 int
  42244 _bcm_field_entry_cleanup(int unit, bcm_field_entry_t entry_id)
  42245 {
  42246     _field_entry_t      *f_ent_orig;
  42247     _field_entry_t      *f_ent_copy;
  42248     _field_action_t     *fa = NULL;         /* Field action descriptor.       */
  42249     _field_action_t     *fa_free = NULL;    /* Field action descriptor.       */
  42250     _field_stat_t       *f_st;              /* Internal Statisics descriptor. */
  42251     _field_policer_t    *f_pl;              /* Internal policer descriptor.   */
  42252     int                 rv;
  42253     int                 parts_count = 0;
  42254     int                 i;
  42255 
  42256 
  42257     FP_LOCK(unit);
  42258 
  42259     rv = _bcm_field_entry_get_by_id(unit,
  42260                                     entry_id,
  42261                                     &f_ent_orig);
  42262     if (BCM_FAILURE(rv)) {
  42263         FP_UNLOCK(unit);
  42264         return (rv);
  42265     }
  42266 
  42267     if (NULL == f_ent_orig->ent_copy) {
  42268         FP_UNLOCK(unit);
  42269         /* No resources to free. */
  42270         return (BCM_E_NONE);
  42271     }
  42272 
  42273     /* Get number of entry parts . */
  42274     rv = _bcm_field_entry_tcam_parts_count(unit,
  42275                                            f_ent_orig->group->stage_id,
  42276                                            f_ent_orig->group->flags,
  42277                                            &parts_count);
  42278     if (BCM_FAILURE(rv)) {
  42279         FP_UNLOCK(unit);
  42280         return (rv);
  42281     }
  42282 
  42283     f_ent_copy = f_ent_orig->ent_copy;
  42284 
  42285     for (i = 0; i < parts_count; i++) {
  42286         _bcm_field_qual_tcam_key_mask_free(unit, f_ent_copy + i);
  42287     }
  42288 
  42289     if (f_ent_copy->statistic.flags & _FP_ENTRY_STAT_VALID) {
  42290 
  42291         /* Get statistics entity  description structure. */
  42292         rv = _bcm_field_stat_get(unit, f_ent_copy->statistic.sid, &f_st);
  42293         if (BCM_FAILURE(rv)) {
  42294             goto cleanup;
  42295         }
  42296         /* Decrement statistics entity reference counter. */
  42297         f_st->sw_ref_count--;
  42298     }
  42299 
  42300     for (i = 0; i < _FP_POLICER_LEVEL_COUNT; i++)  {
  42301         if (f_ent_copy->policer[i].flags & _FP_POLICER_VALID) {
  42302 
  42303             /* Get policer description structure. */
  42304             rv = _bcm_field_policer_get(unit,
  42305                                         f_ent_copy->policer[i].pid,
  42306                                         &f_pl);
  42307             if (BCM_FAILURE(rv)) {
  42308                 goto cleanup;
  42309             }
  42310             /* Decrement policer reference counter. */
  42311             f_pl->sw_ref_count--;
  42312         }
  42313     }
  42314 
  42315 cleanup:
  42316     fa = f_ent_copy->actions;
  42317     while (fa != NULL) {
  42318         fa_free = fa;
  42319         fa = fa->next;
  42320         sal_free(fa_free);
  42321     }
  42322 
  42323     if (NULL != f_ent_copy) {
  42324         sal_free(f_ent_orig->ent_copy);
  42325         f_ent_orig->ent_copy = NULL;
  42326     }
  42327 
  42328     FP_UNLOCK(unit);
  42329     return (BCM_E_NONE);
  42330 }
  42331 
  42332 #if defined (BCM_TRIUMPH2_SUPPORT)
  42333 /*
  42334  * Function:
  42335  *      _bcm_esw_field_udf_chunks_to_int_qset
  42336  * Purpose:
  42337  *      Sets internal data qualifiers corrspeonding to the
  42338  *      offset chunks used by the UDF.
  42339  * Parameters:
  42340  *      unit                - (IN)  Unit number.
  42341  *      udf_chunks_bmap     - (IN)  UDF offsets chunks map
  42342  *      qset                - (OUT) Qualifier set
  42343  * Returns:
  42344  *      BCM_E_NONE
  42345  * Notes:
  42346  */
  42347 int
  42348 _bcm_esw_field_udf_chunks_to_int_qset(int unit, uint32 udf_chunks_bmap,
  42349                                       bcm_field_qset_t *qset)
  42350 {
  42351     int gran = 0, max_chunks = 0;
  42352     int idx;             /* HW bitmap iteration index. */
  42353     int offset0_1 = 0;   /* HW offset 0 and 1 usage status. */
  42354     int offset2_3 = 0;   /* HW offset 2 and 3 usage status. */
  42355     int offset4_5 = 0;   /* HW offset 4 and 5 usage status. */
  42356     int offset6_7 = 0;   /* HW offset 6 and 7 usage status. */
  42357 
  42358     /* Retreive granularity and max chunks in unit */
  42359     gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit);
  42360     max_chunks = BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit);
  42361 
  42362 
  42363 #if defined(BCM_TOMAHAWK_SUPPORT)
  42364     if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  42365 
  42366 #if defined(BCM_TOMAHAWK3_SUPPORT)
  42367         if (soc_feature(unit, soc_feature_udf_selector_support)) {
  42368             return (
  42369                     _bcm_field_th3_udf_chunks_to_int_qset(
  42370                         unit, udf_chunks_bmap, qset));
  42371         } else
  42372 #endif
  42373         {
  42374             return (
  42375                     _bcm_field_th_udf_chunks_to_int_qset(
  42376                                 unit, udf_chunks_bmap, qset));
  42377         }
  42378     }
  42379 #endif /* BCM_TOMAHAWK_SUPPORT */
  42380 
  42381     /* First Check Data0 and Data1 Qualify */
  42382     for (idx = 0; idx <= max_chunks; idx++) {
  42383         if(udf_chunks_bmap & (1 << idx)) {
  42384             if (idx >= 0 && idx < (max_chunks/2)) {
  42385                 BCM_FIELD_QSET_ADD_INTERNAL(*qset, _bcmFieldQualifyData0);
  42386             } else if (idx >= (max_chunks/2) && idx < max_chunks) {
  42387                 BCM_FIELD_QSET_ADD_INTERNAL(*qset, _bcmFieldQualifyData1);
  42388             }
  42389         }
  42390     }
  42391 
  42392     /* Based on Granularity set Data2 and Data3 Qualify */
  42393     if(gran == UDF_OFFSET_GRAN2) {
  42394 
  42395         if (BCM_FIELD_QSET_TEST_INTERNAL(*qset, _bcmFieldQualifyData0)) {
  42396 
  42397             /* See if not having to use all UDF1 */
  42398             BCM_FIELD_QSET_REMOVE_INTERNAL(*qset, _bcmFieldQualifyData0);
  42399             BCM_FIELD_QSET_REMOVE_INTERNAL(*qset, _bcmFieldQualifyData2);
  42400             BCM_FIELD_QSET_REMOVE_INTERNAL(*qset, _bcmFieldQualifyData3);
  42401 
  42402             /* Get HW offsets usage status. */
  42403             /* coverity[callee_ptr_arith : FALSE] */
  42404             SHR_BITTEST_RANGE(&udf_chunks_bmap, 0, 2, offset0_1);
  42405             /* coverity[callee_ptr_arith : FALSE] */
  42406             SHR_BITTEST_RANGE(&udf_chunks_bmap, 2, 2, offset2_3);
  42407             /* coverity[callee_ptr_arith : FALSE] */
  42408             SHR_BITTEST_RANGE(&udf_chunks_bmap, 4, 2, offset4_5);
  42409             /* coverity[callee_ptr_arith : FALSE] */
  42410             SHR_BITTEST_RANGE(&udf_chunks_bmap, 6, 2, offset6_7);
  42411 
  42412 
  42413             /* Add new internal qualifiers based on HW offsets usage status. */
  42414             if ((!offset0_1 && !offset4_5) && (offset2_3 || offset6_7)) {
  42415                 if (offset2_3 && offset6_7) {
  42416                     /* Add both UDF1_31_0 and UDF1_95_64 */
  42417                     BCM_FIELD_QSET_ADD_INTERNAL(*qset, _bcmFieldQualifyData2);
  42418                     BCM_FIELD_QSET_ADD_INTERNAL(*qset, _bcmFieldQualifyData3);
  42419                 } else if (offset6_7 && !offset2_3) {
  42420                     /* Add UDF1_31_0 */
  42421                     BCM_FIELD_QSET_ADD_INTERNAL(*qset, _bcmFieldQualifyData2);
  42422                 } else {
  42423                     /* Add UDF1_95_64 */
  42424                     BCM_FIELD_QSET_ADD_INTERNAL(*qset, _bcmFieldQualifyData3);
  42425                 }
  42426             } else {
  42427                 /* Add UDF1_127_0 */
  42428                 BCM_FIELD_QSET_ADD_INTERNAL(*qset, _bcmFieldQualifyData0);
  42429             }
  42430         }
  42431 
  42432     }
  42433 
  42434     return BCM_E_NONE;
  42435 }
  42436 
  42437 
  42438 
  42439 /*
  42440  * Function:
  42441  *      bcmi_xgs4_field_qset_udf_id_multi_set
  42442  * Purpose:
  42443  *      Sets the list of udf id objects in the qset
  42444  * Parameters:
  42445  *      unit                - (IN)  Unit number.
  42446  *      num_objects         - (IN)  Number of objects.
  42447  *      object_list         - (IN)  List of objects (Ex; UDF ids).
  42448  *      qset                - (OUT) Qualifier set.
  42449  * Returns:
  42450  *      BCM_E_XXX
  42451  * Notes:
  42452  */
  42453 int
  42454 bcmi_xgs4_field_qset_udf_id_multi_set(
  42455     int unit,
  42456     int num_objects,
  42457     int objects_list[],
  42458     bcm_field_qset_t *qset
  42459     )
  42460 {
  42461 
  42462     int i;
  42463     int rv;
  42464     uint32 udf_chunks = 0;
  42465     bcmi_xgs4_udf_offset_info_t *offset_info = NULL;
  42466 #ifdef BCM_TOMAHAWK_SUPPORT
  42467     int j;
  42468 #endif
  42469 
  42470     UDF_LOCK(unit);
  42471 
  42472     for (i = 0; i < num_objects;  i++) {
  42473         /* Fetch udf info for hw_bmap */
  42474         rv = bcmi_xgs4_udf_offset_node_get(unit, objects_list[i], &offset_info);
  42475         if (BCM_FAILURE(rv)) {
  42476             UDF_UNLOCK(unit);
  42477             return rv;
  42478         }
  42479 
  42480         udf_chunks |= offset_info->hw_bmap;
  42481     }
  42482 
  42483     /* Update udf_chuks bmap with qset */
  42484     for (i = 0; i < BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit); i++) {
  42485         /* coverity[ptr_arith] */
  42486         if (SHR_BITGET(qset->udf_map, i)) {
  42487             SHR_BITSET(&udf_chunks, i);
  42488         }
  42489     }
  42490     /* Update qset with internal data qualifiers based on udf_chunks */
  42491     rv = _bcm_esw_field_udf_chunks_to_int_qset(unit, udf_chunks, qset);
  42492     if (BCM_FAILURE(rv)) {
  42493         UDF_UNLOCK(unit);
  42494         return rv;
  42495     }
  42496 
  42497     /* setting udf_map helps in gets/deletes */
  42498     for (i = 0; i < BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit); i++) {
  42499         /* coverity[ptr_arith] */
  42500         if (SHR_BITGET(&udf_chunks, i)) {
  42501             SHR_BITSET(qset->udf_map, i);
  42502         }
  42503     }
  42504 
  42505 #ifdef BCM_TOMAHAWK_SUPPORT
  42506     /* SDK builds key gen mask for exact match group during group create.
  42507      * group control structure has information only about data qualifiers
  42508      * (_bcmFieldQualifyData0 - _bcmFieldQualifyData9) and chunks allocated
  42509      * in groups qset.But no information is available about which bytes of
  42510      * the chunk is actually allocated.
  42511      * But we need which bytes of chunk is allocated for the data qualifier to
  42512      * properly build the EM key gen mask, in case of partially allocated chunks.
  42513      * So updating the unused bits of udf_map in bcm_field_qset_t to hold the
  42514      * bytes allocated in chunks allocated for the data qualifier.*/
  42515     for (j = 0; j < num_objects;  j++) {
  42516         rv = bcmi_xgs4_udf_offset_node_get(unit, objects_list[j], &offset_info);
  42517         if (BCM_FAILURE(rv)) {
  42518             UDF_UNLOCK(unit);
  42519             return rv;
  42520         }
  42521         if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  42522             for (i = 0; i < (BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit) * 2); i++) {
  42523                 if (SHR_BITGET(&(offset_info->byte_bmap), i)) {
  42524                     SHR_BITSET(qset->udf_map,
  42525                               (BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit) + i));
  42526                 }
  42527             }
  42528         }
  42529     }
  42530 #endif
  42531 
  42532     UDF_UNLOCK(unit);
  42533 
  42534     return rv;
  42535 }
  42536 
  42537 /*
  42538  * Function:
  42539  *      bcmi_xgs4_field_qset_udf_id_multi_delete
  42540  * Purpose:
  42541  *      Deletes list of udf id objects from the qset
  42542  * Parameters:
  42543  *      unit                - (IN)  Unit number.
  42544  *      num_objects         - (IN)  Number of objects.
  42545  *      object_list         - (IN)  List of objects (Ex; UDF ids).
  42546  *      qset                - (OUT) Qualifier set.
  42547  * Returns:
  42548  *      BCM_E_XXX
  42549  * Notes:
  42550  */
  42551 int
  42552 bcmi_xgs4_field_qset_udf_id_multi_delete(
  42553     int unit,
  42554     int num_objects,
  42555     int objects_list[],
  42556     bcm_field_qset_t *qset
  42557     )
  42558 {
  42559 
  42560     int i;
  42561     int rv;
  42562     uint32 udf_chunks = 0; /* Offset chunks bitmap */
  42563     bcmi_xgs4_udf_offset_info_t *offset_info = NULL; /* UDF offset info */
  42564 
  42565 
  42566     UDF_LOCK(unit);
  42567 
  42568     for (i = 0; i < num_objects;  i++) {
  42569         /* Fetch udf info for hw_bmap */
  42570         rv = bcmi_xgs4_udf_offset_node_get(unit, objects_list[i], &offset_info);
  42571         if (BCM_FAILURE(rv)) {
  42572             UDF_UNLOCK(unit);
  42573             return rv;
  42574         }
  42575 
  42576         udf_chunks |= offset_info->hw_bmap;
  42577     }
  42578 
  42579     /* Update qset with internal data qualifiers based on udf_chunks */
  42580     rv = _bcm_esw_field_udf_chunks_to_int_qset(unit, udf_chunks, qset);
  42581     if (BCM_FAILURE(rv)) {
  42582         UDF_UNLOCK(unit);
  42583         return rv;
  42584     }
  42585 
  42586     /* setting udf_map helps in gets/deletes */
  42587     for (i = 0; i < BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit); i++) {
  42588         /* coverity[ptr_arith] */
  42589         if (SHR_BITGET(&udf_chunks, i)) {
  42590             SHR_BITCLR(qset->udf_map, i);
  42591         }
  42592     }
  42593 
  42594     UDF_UNLOCK(unit);
  42595 
  42596     return rv;
  42597 }
  42598 
  42599 
  42600 /*
  42601  * Function:
  42602  *      bcmi_xgs4_field_qset_udf_id_multi_get
  42603  * Purpose:
  42604  *      Gets list of udf id objects in a qset
  42605  * Parameters:
  42606  *      unit                - (IN)  Unit number.
  42607  *      qset                - (IN)  Qualifier set.
  42608  *      max                 - (IN)  Max number of objects.
  42609  *      object_list         - (OUT) List of objects (Ex; UDF ids).
  42610  *      actual              - (OUT) Number of objects.
  42611  * Returns:
  42612  *      BCM_E_XXX
  42613  * Notes:
  42614  */
  42615 int
  42616 bcmi_xgs4_field_qset_udf_id_multi_get(
  42617     int unit,
  42618     bcm_field_qset_t qset,
  42619     int max,
  42620     int objects_list[],
  42621     int *actual
  42622     )
  42623 {
  42624     int i;
  42625     uint32 hw_bmap = 0;
  42626     int max_chunks = 0;
  42627     bcmi_xgs4_udf_offset_info_t *tmp;
  42628 
  42629     UDF_LOCK(unit);
  42630 
  42631     max_chunks = BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit);
  42632 
  42633     /* Input parameters check. */
  42634     if (actual == NULL) {
  42635 	UDF_UNLOCK(unit);
  42636         return BCM_E_PARAM;
  42637     }
  42638 
  42639     for (i = 0; i < max_chunks; i++) {
  42640         /* coverity[ptr_arith] */
  42641         if (SHR_BITGET(qset.udf_map, i)) {
  42642             SHR_BITSET(&hw_bmap, i);
  42643         }
  42644     }
  42645 
  42646     i = 0;
  42647     tmp = UDF_CTRL(unit)->offset_info_head;
  42648 
  42649     while (tmp != NULL) {
  42650        if ( hw_bmap & (tmp->hw_bmap)) {
  42651            if (i >= max) {
  42652                break;
  42653            }
  42654            objects_list[i++] = tmp->udf_id;
  42655        }
  42656        tmp = tmp->next;
  42657     }
  42658 
  42659 
  42660     *actual = i;
  42661 
  42662     UDF_UNLOCK(unit);
  42663 
  42664     return BCM_E_NONE;
  42665 }
  42666 
  42667 
  42668 /*
  42669  * Function:
  42670  *      _bcm_esw_field_qual_udf_offsets_get
  42671  * Purpose:
  42672  *      Gets list of udf id objects in a qset
  42673  * Parameters:
  42674  *      unit          - (IN)  Unit number.
  42675  *      qid           - (IN)  Internal Data qualifier.
  42676  *      chunk_order   - (IN)  Offset chunks in the order of availability.
  42677  *      num_chunks    - (OUT) Number of chunks.
  42678  * Returns:
  42679  *      BCM_E_NONE
  42680  * Notes:
  42681  */
  42682 int
  42683 _bcm_esw_field_qual_udf_offsets_get(int unit, int qid,  _field_group_t *fg,
  42684                                     int chunk_order[], int *num_chunks,
  42685                                     int pipe_num)
  42686 {
  42687     int idx;
  42688     int alloc_count = 0;
  42689     uint32 hw_bmap;
  42690     int max_chunks = BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit);
  42691     int gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit);
  42692 
  42693 #if defined (BCM_TOMAHAWK_SUPPORT)
  42694     bcm_udf_oper_mode_t udf_oper_mode = bcmUdfOperModeGlobal;
  42695     bcmi_xgs4_udf_oper_mode_get(unit, &udf_oper_mode);
  42696 
  42697     if ((soc_feature(unit, soc_feature_udf_multi_pipe_support)) &&
  42698         (udf_oper_mode == bcmUdfOperModePipeLocal)) {
  42699             hw_bmap = (UDF_CTRL(unit)->hw_bmap_per_pipe[pipe_num]);
  42700     } else
  42701 #endif
  42702     {
  42703         hw_bmap = (UDF_CTRL(unit)->hw_bmap);
  42704     }
  42705 
  42706 #if defined(BCM_TOMAHAWK_SUPPORT)
  42707     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  42708         ((_BCM_FIELD_STAGE_INGRESS == fg->stage_id) || (_BCM_FIELD_STAGE_LOOKUP == fg->stage_id))) {
  42709         return (
  42710             _bcm_field_th_qual_udf_offsets_get(
  42711                        unit, qid, chunk_order, num_chunks, hw_bmap));
  42712     }
  42713 #endif
  42714 
  42715     for (idx = 0; idx < max_chunks; idx++) {
  42716         /* coverity[ptr_arith] */
  42717         if (SHR_BITGET(&hw_bmap, idx)) {
  42718             continue;
  42719         }
  42720 
  42721         /* Allocate as per granularity */
  42722         if (gran == UDF_OFFSET_GRAN2) {
  42723             if (((qid == _bcmFieldQualifyData2) && ((idx == 6) || (idx == 7)))  ||
  42724                     ((qid == _bcmFieldQualifyData3) && ((idx == 2) || (idx == 3)))  ||
  42725                     ((qid == _bcmFieldQualifyData1) && ((idx >= 8)))                ||
  42726                     ((qid == _bcmFieldQualifyData0) && ((idx <= 7))))               {
  42727 
  42728                 chunk_order[alloc_count] = idx;
  42729                 alloc_count++;
  42730 
  42731                 if ((*num_chunks + alloc_count) >= max_chunks) {
  42732                     break;
  42733                 }
  42734             }
  42735         } else {
  42736             if (((qid == _bcmFieldQualifyData2) && (idx == 3))       ||
  42737                     ((qid == _bcmFieldQualifyData3) && (idx == 1))   ||
  42738                     ((qid == _bcmFieldQualifyData1) && ((idx >= 4))) ||
  42739                     ((qid == _bcmFieldQualifyData0) && ((idx <= 3))))               {
  42740 
  42741                 chunk_order[alloc_count] = idx;
  42742                 alloc_count++;
  42743 
  42744                 if ((*num_chunks + alloc_count) >= max_chunks) {
  42745                     break;
  42746                 }
  42747             }
  42748         }
  42749     }
  42750 
  42751     *num_chunks += alloc_count;
  42752 
  42753     return BCM_E_NONE;
  42754 }
  42755 
  42756 
  42757 /*
  42758  * Function:
  42759  *      _bcm_esw_field_qset_udf_offsets_alloc
  42760  * Purpose:
  42761  *      Allocates offset chunks based on the INPUT qset.
  42762  * Parameters:
  42763  *      unit          - (IN)  Unit number.
  42764  *      stage         - (IN)  Field Group Stage.
  42765  *      qset          - (IN)  Qualifier set.
  42766  *      req_offsets   - (IN)  Number of chunks to be allocated.
  42767  *      offset_array  - (OUT) Offset chunks in the order of availability.
  42768  * Returns:
  42769  *      BCM_E_XXX
  42770  * Notes:
  42771  */
  42772 int
  42773 _bcm_esw_field_qset_udf_offsets_alloc(int unit, _field_stage_id_t stage,
  42774     bcm_field_qset_t qset, int req_offsets, int offset_array[], int *max_chunks,
  42775     int pipe_num)
  42776 {
  42777     int group_flags[5] =  {
  42778             /* SINGLE */
  42779             (_FP_GROUP_SPAN_SINGLE_SLICE),
  42780             /* DOUBLE_INTRA */
  42781             (_FP_GROUP_SPAN_SINGLE_SLICE | _FP_GROUP_INTRASLICE_DOUBLEWIDE),
  42782             /* DOUBLE */
  42783             (_FP_GROUP_SPAN_DOUBLE_SLICE),
  42784             /* QUAD_INTRA */
  42785             (_FP_GROUP_SPAN_DOUBLE_SLICE | _FP_GROUP_INTRASLICE_DOUBLEWIDE),
  42786             /* TRIPLE */
  42787             (_FP_GROUP_SPAN_TRIPLE_SLICE)
  42788         };
  42789 
  42790     int qset_comb[9][4] =  {
  42791             /* Internal qualifier Data2 (UDF1_6,UDF1_7) for Gran2
  42792              *                          (UDF1_3) for Gran4
  42793              */
  42794             {1, _bcmFieldQualifyData2, -1, -1},
  42795             /* Internal qualifier Data3 (UDF1_2,UDF1_3) for Gran2
  42796              *                          (UDF1_1) for Gran 4
  42797              */
  42798             {1, _bcmFieldQualifyData3, -1, -1},
  42799             /* Internal qualifier Data2 & Data3 (UDF1_6,UDF1_7,UDF1_2,UDF1_3)
  42800              *                     for Gran2 and (UDF1_3,UDF1_1) for Gran4
  42801              */
  42802             {2, _bcmFieldQualifyData2,
  42803                 _bcmFieldQualifyData3,
  42804                 -1},
  42805             /* Internal qualifier Data1 (UDF2) */
  42806             {1, _bcmFieldQualifyData1, -1, -1},
  42807             /* Internal qualifier Data0 (UDF1) */
  42808             {1, _bcmFieldQualifyData0, -1, -1},
  42809             /* Internal qualifier Data1 & Data2 (UDF1_6, UDF1_7 & UDF2) for Gran2
  42810              *                                  (UDF1_3 & UDF2) for Gran4
  42811              */
  42812             {2, _bcmFieldQualifyData1,
  42813                 _bcmFieldQualifyData2,
  42814                 -1},
  42815             /* Internal qualifier Data1 & Data3 (UDF1_2, UDF1_3 & UDF2) for Gran 2
  42816              *                                  (UDF1_1 & UDF2) for Gran4
  42817              */
  42818             {2, _bcmFieldQualifyData1,
  42819                 _bcmFieldQualifyData3,
  42820                 -1},
  42821             /* Internal qualifier Data1, Data2 & Data3 (UDF1_6, UDF1_7, UDF1_2, UDF1_3 & UDF2)
  42822              *                for Gran2 and (UDF1_3, UDF1_1, & UDF2) for Gran4
  42823              */
  42824             {3, _bcmFieldQualifyData1,
  42825                 _bcmFieldQualifyData2,
  42826                 _bcmFieldQualifyData3},
  42827             /* Internal qualifier Data0 & Data1 (UDF1 & UDF2) */
  42828             {2, _bcmFieldQualifyData0,
  42829                 _bcmFieldQualifyData1,
  42830                 -1}
  42831         };
  42832 
  42833     int i, j;
  42834     int qid;
  42835     int qual_count;
  42836     int rv = BCM_E_NONE;
  42837     int num_chunks = 0;
  42838     _field_group_t fg;
  42839     bcm_field_qset_t qset_test;
  42840     int idx;
  42841 
  42842 #if defined (BCM_TOMAHAWK_SUPPORT)
  42843     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  42844         ((_BCM_FIELD_STAGE_INGRESS == stage) || (_BCM_FIELD_STAGE_LOOKUP == stage))) {
  42845         return (_bcm_field_th_qset_udf_offsets_alloc(
  42846                     unit, stage, qset, req_offsets,
  42847                     offset_array, max_chunks, pipe_num));
  42848 
  42849     }
  42850 #endif
  42851 
  42852     /* Initialize group creation tracking structure. */
  42853     sal_memset(&fg, 0, sizeof(fg));
  42854 
  42855     fg.stage_id = stage;
  42856     for (i = 0; i < COUNTOF(group_flags); i++) {
  42857 
  42858         /* TD_TT family  support intra_double mode group only in VFP */
  42859         if (soc_feature(unit, soc_feature_field_intraslice_double_wide)) {
  42860             if (((i == 1) || (i == 4)) && (stage != _BCM_FIELD_STAGE_LOOKUP)) {
  42861                 continue;
  42862             }
  42863         }
  42864 
  42865         fg.flags = group_flags[i];
  42866 
  42867         for (j = 0; j < COUNTOF(qset_comb); j++) {
  42868 
  42869             num_chunks = 0;
  42870             qual_count = qset_comb[j][0];
  42871 
  42872             sal_memcpy(&qset_test, &qset, sizeof(bcm_field_qset_t));
  42873 
  42874             for (qid = 0; qid < qual_count; qid++) {
  42875                 BCM_FIELD_QSET_ADD_INTERNAL(qset_test, qset_comb[j][1 + qid]);
  42876             }
  42877 
  42878             FP_LOCK(unit);
  42879             rv = _field_selcode_assign(unit, qset_test, 1, &fg);
  42880             FP_UNLOCK(unit);
  42881 
  42882             if (BCM_SUCCESS(rv)) {
  42883 
  42884                 for (qid = 0; qid < qual_count; qid++) {
  42885                     rv = _bcm_esw_field_qual_udf_offsets_get(unit,
  42886                                      qset_comb[j][1 + qid], &fg,
  42887                                      offset_array+num_chunks, &num_chunks,
  42888                                      pipe_num);
  42889                     if (BCM_FAILURE(rv)) {
  42890                         for (idx = 0; idx < _FP_MAX_ENTRY_WIDTH; idx++) {
  42891                             BCM_IF_ERROR_RETURN(_bcm_field_group_qualifiers_free(&fg, idx));
  42892                         }
  42893                         return rv;
  42894                     }
  42895                 }
  42896 
  42897                 if (num_chunks >= req_offsets) {
  42898                     break;
  42899                 }
  42900             }
  42901         }
  42902 
  42903         if (num_chunks >= req_offsets) {
  42904             break;
  42905         }
  42906     }
  42907 
  42908     for (idx = 0; idx < _FP_MAX_ENTRY_WIDTH; idx++) {
  42909         BCM_IF_ERROR_RETURN(_bcm_field_group_qualifiers_free(&fg, idx));
  42910     }
  42911 
  42912     /* The UDF offset allocation to suit in an fp group
  42913      * that consists of the user specified qset is not possible */
  42914     if (num_chunks < req_offsets) {
  42915         return BCM_E_RESOURCE;
  42916     }
  42917 
  42918     *max_chunks = num_chunks;
  42919 
  42920     return BCM_E_NONE;
  42921 }
  42922 
  42923 
  42924 /*
  42925  * Function:
  42926  *      _bcm_xgs4_field_qualify_udf_data_elem
  42927  * Purpose:
  42928  *      Qualify the field entry with data/mask corresponding to an offset chunk.
  42929  * Parameters:
  42930  *      unit            - (IN)  Unit number.
  42931  *      eid             - (IN)  Field Entry.
  42932  *      offset_info     - (IN)  UDF offset info.
  42933  *      data_idx        - (IN)  The offset chunk index.
  42934  *      data            - (IN)  Input data to qualify the entry.
  42935  *      mask            - (IN)  Input mask to qualify the entry.
  42936  * Returns:
  42937  *      BCM_E_XXX
  42938  * Notes:
  42939  */
  42940 int
  42941 _bcm_xgs4_field_qualify_udf_data_elem(int unit, bcm_field_entry_t eid,
  42942                          bcmi_xgs4_udf_offset_info_t *offset_info,
  42943                          int data_idx, uint32 data, uint32 mask)
  42944 {
  42945     int rv;
  42946     int idx;
  42947     int elem_idx = 0;
  42948     int qid = 0;
  42949     int gran, max_chunks;
  42950     _field_entry_t *f_ent = NULL;
  42951     _bcm_field_qual_offset_t *q_offset;
  42952     _bcm_field_qual_offset_t q_offset_temp;
  42953 #if defined (BCM_TOMAHAWK_SUPPORT)
  42954     uint32                   q_data = 0;        /* Qualifier data             */
  42955     uint32                   q_mask = 0;        /* Qualifier mask             */
  42956     int                      bit32_chunk = 0;   /* Chunk is 32bit or 16bit    */
  42957     uint8                    hints_present = 0;
  42958 #endif
  42959 
  42960     max_chunks = BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit);
  42961     gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit);
  42962 
  42963     /* Get the appropriate element index to insert the data */
  42964     for (idx = max_chunks - 1; idx >= 0; idx--) {
  42965         /* coverity[ptr_arith] */
  42966         if (SHR_BITGET(&(offset_info->hw_bmap), idx)) {
  42967             if (elem_idx == data_idx) {
  42968                 break;
  42969             } else {
  42970                 elem_idx++;
  42971             }
  42972         }
  42973     }
  42974 
  42975     /* Get entry info. */
  42976     BCM_IF_ERROR_RETURN
  42977         (_field_entry_get(unit, eid, _FP_ENTRY_PRIMARY, &f_ent));
  42978 
  42979 #if defined (BCM_TOMAHAWK_SUPPORT)
  42980     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  42981         ((_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id) ||
  42982         (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) ||
  42983          (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH))) {
  42984         BCM_IF_ERROR_RETURN(
  42985                     _bcm_field_th_qualify_udf_data_elem_get
  42986                                  (unit, idx, max_chunks, &qid));
  42987     } else
  42988 #endif
  42989     {
  42990         /* idx - chunk id; data_idx - ? */
  42991         if ((idx >= 0) && (idx < max_chunks/2)) {
  42992 
  42993             /*
  42994              * If _bcmFieldQualifyData0 is not set in the qset,
  42995              * either _bcmFieldQualifyData2 or _bcmFieldQualifyData3
  42996              * will be set in the qset.
  42997              */
  42998             if (gran == UDF_OFFSET_GRAN2) {
  42999                 if (!BCM_FIELD_QSET_TEST_INTERNAL
  43000                         (f_ent->group->qset, _bcmFieldQualifyData0)) {
  43001                     if ((2 == idx || 3 == idx)
  43002                             && !(offset_info->hw_bmap & 0x33)) {
  43003                         /* UDF1_95_64 */
  43004                         qid = _bcmFieldQualifyData3;
  43005                     } else if ((6 == idx || 7 == idx)
  43006                             && !(offset_info->hw_bmap & 0x33)) {
  43007                         /* UDF1_31_0 */
  43008                         qid = _bcmFieldQualifyData2;
  43009                     } else {
  43010                         /*
  43011                          * udf_offset0_1 and udf_offset4_5 must be in
  43012                          * _bcmFieldQualifyData0
  43013                          */
  43014                         return (BCM_E_INTERNAL);
  43015                     }
  43016                 } else {
  43017                     /* UDF1_127_0 */
  43018                     qid = _bcmFieldQualifyData0;
  43019                 }
  43020             } else {
  43021                 /* GRAN 4 */
  43022                 qid = _bcmFieldQualifyData0;
  43023             }
  43024         } else if ((idx >= max_chunks/2) &&
  43025                    idx < max_chunks) {
  43026             qid =  _bcmFieldQualifyData1;
  43027             idx -= (max_chunks / 2);
  43028         } else {
  43029             return (BCM_E_INTERNAL);
  43030         }
  43031 
  43032         /* Get entry qualifier offset in tcam */
  43033         if(gran == UDF_OFFSET_GRAN2) {
  43034             if (qid == _bcmFieldQualifyData3) {
  43035                 if (idx == 2) {
  43036                     idx = 1;
  43037                 } else {
  43038                     idx = 0;
  43039                 }
  43040             } else {
  43041                 idx = (((max_chunks/2) - 1) - idx);
  43042             }
  43043         } else {
  43044             /* GRAN4 Case */
  43045             idx = (((max_chunks/2) - 1) - idx);
  43046         }
  43047     }
  43048 #if defined(BCM_TOMAHAWK_SUPPORT)
  43049     /* If device supports per-pipe FP configuration, */
  43050     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  43051         ((f_ent->group->stage_id == _BCM_FIELD_STAGE_INGRESS) ||
  43052         (f_ent->group->stage_id == _BCM_FIELD_STAGE_LOOKUP) ||
  43053         (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH))) {
  43054 
  43055         if (idx != 0x0 && idx != 0x1 && idx != 0x8 && idx != 0x9)
  43056         {
  43057            if (!(soc_feature(unit, soc_feature_udf_selector_support))) {
  43058                 bit32_chunk = 1;
  43059            }
  43060         }
  43061         if(bit32_chunk) {
  43062             /*Since a 32 bit chunk can be allocated even partially,
  43063               do not overwrite existing data in 32bit chunk.*/
  43064             rv = _bcm_field_entry_qualifier_uint32_get(unit, f_ent->eid, qid,
  43065                                                            &q_data, &q_mask);
  43066 
  43067             if ((rv != BCM_E_NOT_FOUND) && (BCM_FAILURE(rv))) {
  43068                 return rv;
  43069             }
  43070 
  43071             if (rv == BCM_E_NONE) {
  43072                 if((idx % 2) == 0) {
  43073                     /* Idx is even => Upper 16 bits need to be written.Hence,mask the lower
  43074                      *16 bits of the q_data fetched from tcam and add the data*/
  43075                     q_data &= ((1 << 16) - 1);
  43076                     q_mask &= ((1 << 16) - 1);
  43077 
  43078                     data = data << 16 | q_data;
  43079                     mask = mask << 16 | q_mask;
  43080                 } else {
  43081                     /* Idx is odd => Lower 16 bits need to be written.Hence,mask the upper
  43082                      *16 bits of the q_data fetched from tcam and add the data*/
  43083                     q_data &= ~((1 << 16) - 1);
  43084                     q_mask &= ~((1 << 16) - 1);
  43085 
  43086                     data |= q_data;
  43087                     mask |= q_mask;
  43088                 }
  43089             }
  43090         }
  43091 
  43092         /* For exact Match, though 32bit/16bit chunk is  partially allocated,
  43093          * _bcm_field_th_entry_check_full_mask will expect full mask to during
  43094          * validation.
  43095          */
  43096         if (f_ent->group->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) {
  43097 
  43098             if (bit32_chunk) {
  43099                 if ((idx % 2) == 0) {
  43100                     mask |= 0xffff;
  43101                 } else {
  43102                     mask |= 0xffff0000;
  43103                 }
  43104             }
  43105 
  43106             if (!(offset_info->byte_bmap & (1 << (idx * 2)))) {
  43107                 mask |= 0xff;
  43108             }
  43109 
  43110             if (!(offset_info->byte_bmap & (1 << ((idx * 2) + 1)))) {
  43111                     mask |= 0xff00;
  43112             }
  43113         }
  43114 
  43115         if (f_ent->group->stage_id == _BCM_FIELD_STAGE_LOOKUP) {
  43116             f_ent = NULL;
  43117             rv = _bcm_field_entry_qual_get(unit, eid, qid, &f_ent);
  43118             BCM_IF_ERROR_RETURN(rv);
  43119 
  43120             /* Get entry qualifier offset in tcam. */
  43121             rv = _field_qual_offset_get(unit, f_ent, qid, &q_offset);
  43122             BCM_IF_ERROR_RETURN(rv);
  43123             /* COVERITY
  43124              *
  43125              * This flow takes care of the  Out-of-bounds access issue
  43126              * for data and mask.
  43127              */
  43128 
  43129             /* coverity[callee_ptr_arith : FALSE] */
  43130             rv = _bcm_field_qual_value_set(unit, q_offset, f_ent, &data, &mask);
  43131             BCM_IF_ERROR_RETURN(rv);
  43132 
  43133             f_ent->flags |= _FP_ENTRY_DIRTY;
  43134 
  43135             return (BCM_E_NONE);
  43136         }
  43137         /* coverity[address_of : FALSE] */
  43138         /* coverity[callee_ptr_arith : FALSE] */
  43139         rv = (_bcm_field_th_qualify_set(unit, eid, qid,
  43140                                           &data, &mask,
  43141                                           _FP_QUALIFIER_ADD));
  43142         if (BCM_E_PARAM == rv) {
  43143             rv = _field_udf_hints_present_get(unit, eid, offset_info->udf_id, &hints_present);
  43144             if (BCM_FAILURE(rv)) {
  43145                 return BCM_E_INTERNAL;
  43146             }
  43147             if (hints_present && !BCM_FIELD_QSET_TEST_INTERNAL(f_ent->group->qset, qid)) {
  43148                 rv = BCM_E_NONE;
  43149             }
  43150         }
  43151 
  43152         return (rv);
  43153     }
  43154     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  43155         (f_ent->group->stage_id == _BCM_FIELD_STAGE_CLASS)) {
  43156         return (_bcm_field_th_class_qualify_set(unit, eid, qid,
  43157                                                 &data, &mask));
  43158     }
  43159 #endif /* BCM_TOMAHAWK_SUPPORT */
  43160     /* Get entry qualifier should be installed in. */
  43161     f_ent = NULL;
  43162     rv = _bcm_field_entry_qual_get(unit, eid, qid, &f_ent);
  43163     BCM_IF_ERROR_RETURN(rv);
  43164 
  43165     /* Get entry qualifier offset in tcam. */
  43166     rv = _field_qual_offset_get(unit, f_ent, qid, &q_offset);
  43167     BCM_IF_ERROR_RETURN(rv);
  43168 
  43169     sal_memcpy(&q_offset_temp, q_offset,
  43170                sizeof(_bcm_field_qual_offset_t));
  43171 
  43172 #ifdef BCM_MONTEREY_SUPPORT
  43173     if (soc_feature(unit, soc_feature_monterey_b0_fp_sw_war) &&
  43174         (q_offset_temp.width[0] == 1)) {
  43175         if (idx > 0) {
  43176             q_offset_temp.offset[0] = q_offset_temp.offset[1] + (idx * gran * 8) - 1;
  43177             q_offset_temp.width[0] = gran * 8;
  43178             q_offset_temp.width[1] = 0;
  43179         } else {
  43180             q_offset_temp.width[1] = (gran * 8) - 1;
  43181         }
  43182     } else
  43183 #endif
  43184     {
  43185         q_offset_temp.offset[0] += idx * gran * 8;
  43186         q_offset_temp.width[0] = gran * 8;
  43187     }
  43188 
  43189    /*
  43190     * COVERITY
  43191     *
  43192     * This flow takes care of the  Out-of-bounds access issue
  43193     * for data and mask.
  43194     */
  43195 
  43196     /* coverity[callee_ptr_arith : FALSE] */
  43197     rv = _bcm_field_qual_value_set(unit, &q_offset_temp, f_ent, &data, &mask);
  43198     BCM_IF_ERROR_RETURN(rv);
  43199 
  43200     f_ent->flags |= _FP_ENTRY_DIRTY;
  43201 
  43202     return (BCM_E_NONE);
  43203 }
  43204 
  43205 int
  43206 _field_udf_hints_present_get(int unit, bcm_field_entry_t eid,
  43207                              bcm_udf_id_t udf_id,
  43208                              uint8 *hints_present)
  43209 {
  43210     int                   rv = BCM_E_INTERNAL;
  43211     bcm_field_hintid_t    hintid = 0;
  43212     _field_hints_t        *f_ht = NULL;      /* Field hints Structure. */
  43213     _field_hint_t         *hint_node = NULL; /* Field hint Structure. */
  43214     _field_entry_t        *f_ent = NULL;
  43215 
  43216     /* Parameters Check */
  43217     if (NULL == hints_present) {
  43218         return BCM_E_PARAM;
  43219     }
  43220 
  43221     *hints_present = 0;
  43222     rv = _field_entry_get(unit, eid, _FP_ENTRY_PRIMARY, &f_ent);
  43223     BCM_IF_ERROR_RETURN(rv);
  43224 
  43225     hintid = f_ent->group->hintid;
  43226     BCM_IF_ERROR_RETURN(_field_hints_control_get(unit, hintid, &f_ht));
  43227 
  43228     /* Not a valid hint Id. */
  43229     if (NULL == f_ht) {
  43230         return BCM_E_NONE;
  43231     }
  43232 
  43233     /* No hinta are attached to the hintid. */
  43234     if (NULL == f_ht->hints) {
  43235         return BCM_E_NONE;
  43236     }
  43237 
  43238     /* Go through all the hints in the hintid. */
  43239     hint_node = f_ht->hints;
  43240     while (NULL != hint_node) {
  43241         if ((bcmFieldHintTypeExtraction == hint_node->hint->hint_type) &&
  43242                 (bcmFieldQualifyUdf == hint_node->hint->qual)) {
  43243             if (udf_id == hint_node->hint->udf_id) {
  43244                 *hints_present = 1;
  43245                 break;
  43246             }
  43247         }
  43248         hint_node = hint_node->next;
  43249     }
  43250 
  43251     return rv;
  43252 }
  43253 
  43254 /*
  43255  * Function:
  43256  *      bcmi_xgs4_field_qualify_udf_data
  43257  * Purpose:
  43258  *      Add UDF data that the packet must match to trigger qualifier.
  43259  * Parameters:
  43260  *      unit            - (IN)  Unit number.
  43261  *      eid             - (IN)  Field Entry.
  43262  *      udf_id          - (IN)  UDF ID.
  43263  *      length          - (IN)  Number of bytes to match in field entry.
  43264  *      data            - (IN)  Input data to qualify the entry.
  43265  *      mask            - (IN)  Input mask to qualify the entry.
  43266  * Returns:
  43267  *      BCM_E_xxx
  43268  * Notes:
  43269  */
  43270 int
  43271 bcmi_xgs4_field_qualify_udf_data (int unit, bcm_field_entry_t eid,
  43272     bcm_udf_id_t udf_id, int length, uint8 *data, uint8 *mask)
  43273 {
  43274     int      idx = 0;            /* HW bitmap iteration index. */
  43275     int      data_idx = 0;       /* Qualifier element index.   */
  43276     int      rv = BCM_E_NONE;    /* Operation return status.   */
  43277     int      byte_offset;        /* Byte offset in the word.   */
  43278     int      gran = 0;           /* Granularity of the chunk.  */
  43279     uint32   data_elem = 0;      /* Hw info data word.         */
  43280     uint32   mask_elem = 0;      /* Hw info data mask.         */
  43281     uint8    data_qual_done = 0;
  43282     int      size = 0;
  43283     uint8    hints_present;
  43284     uint8    pdata[32];
  43285     uint8    pmask[32];
  43286     bcmi_xgs4_udf_offset_info_t *offset_info = NULL;   /* UDF offset info */
  43287 
  43288     UDF_LOCK(unit);
  43289 
  43290     /* Get UDF info. */
  43291     rv = bcmi_xgs4_udf_offset_node_get(unit, udf_id,  &offset_info);
  43292     if (BCM_FAILURE(rv)) {
  43293         UDF_UNLOCK(unit);
  43294         return rv;
  43295     }
  43296 
  43297     /* If provided entry data length is greater than UDF width */
  43298     if ((length > offset_info->width) || (length <= 0)) {
  43299         UDF_UNLOCK(unit);
  43300         return (BCM_E_PARAM);
  43301     }
  43302 
  43303     sal_memset(pdata, 0, 32 * sizeof(uint8));
  43304     sal_memset(pmask, 0, 32 * sizeof(uint8));
  43305     sal_memcpy(pdata, data, length);
  43306     sal_memcpy(pmask, mask, length);
  43307 
  43308     /* Max chunks */
  43309     gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit);
  43310 
  43311     /* data_idx - chunk iterator */
  43312     data_elem = 0;
  43313     mask_elem = 0;
  43314     data_idx = 0;
  43315     byte_offset = gran - 1;
  43316 
  43317     rv = _field_udf_hints_present_get(unit, eid, udf_id, &hints_present);
  43318     if (BCM_FAILURE(rv)) {
  43319         UDF_UNLOCK(unit);
  43320         return rv;
  43321     }
  43322 
  43323     size = hints_present ? length : offset_info->width;
  43324     /*
  43325      * If the size is odd number,
  43326      * make it even by adding 1 to it as the pdata and pmask are already filled
  43327      * with 0s at that size + 1 position.
  43328      */
  43329     size = (size == 1) ? (size + 1) : size;
  43330     /* idx - input data bytes iterator */
  43331     for (idx = size - 1; idx >= 0; idx--) {
  43332         data_elem |= (pdata[idx] << (8 * (gran - 1 - byte_offset)));
  43333         mask_elem |= (pmask[idx] << (8 * (gran - 1 - byte_offset)));
  43334 
  43335         data_qual_done = 0;
  43336 
  43337         if ((byte_offset == 0)) {
  43338             /* Install the element data & mask of "gran" bytes (even if zeros) */
  43339             rv = _bcm_xgs4_field_qualify_udf_data_elem(unit, eid, offset_info,
  43340                                                data_idx, data_elem, mask_elem);
  43341             if (BCM_FAILURE(rv)) {
  43342                 UDF_UNLOCK(unit);
  43343                 return rv;
  43344             }
  43345 
  43346             data_idx += 1;
  43347             byte_offset = 0;
  43348             data_elem = 0;
  43349             mask_elem = 0;
  43350             data_qual_done = 1;
  43351         }
  43352 
  43353         byte_offset -= 1;
  43354         if ((byte_offset == -1)) {
  43355             byte_offset = gran - 1;
  43356         }
  43357     }
  43358 
  43359     /* Install last element data & mask, if data/mask still exists to be qualified */
  43360     if (data_qual_done != 1) {
  43361         rv = _bcm_xgs4_field_qualify_udf_data_elem(unit, eid, offset_info,
  43362                 data_idx, data_elem, mask_elem);
  43363     }
  43364 
  43365     UDF_UNLOCK(unit);
  43366 
  43367     return (rv);
  43368 }
  43369 
  43370 
  43371 /*
  43372  * Function:
  43373  *      bcmi_xgs4_field_qualify_udf_get
  43374  * Purpose:
  43375  *      Qualify the field entry with data/mask corresponding to an offset chunk.
  43376  * Parameters:
  43377  *      unit            - (IN)  Unit number.
  43378  *      eid             - (IN)  Field Entry.
  43379  *      udf_id          - (IN)  UDF ID.
  43380  *      max_length      - (IN)  Length of bytes of data/mask to fetch.
  43381  *      data            - (OUT) Data to qualify the entry.
  43382  *      mask            - (OUT  Mask to qualify the entry.
  43383  *      actual_length   - (OUT) Length of bytes of data/mask fetched.
  43384  * Returns:
  43385  *      BCM_E_XXX
  43386  * Notes:
  43387  */
  43388 int
  43389 bcmi_xgs4_field_qualify_udf_get(int unit, bcm_field_entry_t eid,
  43390                               bcm_udf_id_t udf_id, int max_length,
  43391                               uint8 *data, uint8 *mask, int *actual_length)
  43392 {
  43393     _field_stage_t          *stage_fc;          /* Stage field control.       */
  43394     _field_entry_t          *f_ent = NULL;
  43395     _field_group_t          *fg;
  43396     bcm_field_qset_t        *qset;
  43397     bcmi_xgs4_udf_offset_info_t *offset_info = NULL;   /* UDF offset info.   */
  43398     int  num_elems = 0;
  43399     int  qid = 0;
  43400     int idx;        /* HW bitmap iteration index. */
  43401     int rv;         /* Operation return status.   */
  43402     int copy_len;
  43403     int len = 0;
  43404     int off = 0;
  43405     int max_elems = 0;
  43406     int min_elems = 0;
  43407     int udf1_elems = 0; /* elements in UDF1 */
  43408     int udf2_elems = 0; /* elements in UDF2 */
  43409     _bcm_field_udf_data_t udf_data; /* UDF full data */
  43410     _bcm_field_udf_data_t udf_mask; /* UDF mask for full data */
  43411     _bcm_field_qual_data_t udf_data1; /* UDF full data */
  43412     _bcm_field_qual_data_t udf_mask1; /* UDF mask for full data */
  43413     int gran = 0;
  43414 #if defined(BCM_TOMAHAWK_SUPPORT)
  43415     uint8 hints_present = 0;
  43416 #endif
  43417 
  43418 #ifdef LE_HOST
  43419     _bcm_field_udf_data_t udf_data_swap; /* UDF full data */
  43420     _bcm_field_udf_data_t udf_mask_swap; /* UDF mask for full data */
  43421     int part = 0;
  43422 #endif /* LE_HOST */
  43423 
  43424 
  43425     /* Input parameters check. */
  43426     if ((NULL == data) || (NULL == mask) ||
  43427             (NULL == actual_length) || (max_length == 0)) {
  43428         return (BCM_E_PARAM);
  43429     }
  43430 
  43431    UDF_LOCK(unit);
  43432 
  43433     /* Get Granularity */
  43434     gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit);
  43435 
  43436     /* Get UDF info. */
  43437     rv = bcmi_xgs4_udf_offset_node_get(unit, udf_id,  &offset_info);
  43438     if (BCM_FAILURE(rv)) {
  43439         UDF_UNLOCK(unit);
  43440         return (rv);
  43441     }
  43442 
  43443     /*
  43444      * If provided entry data length is less than data length used
  43445      * to create qualifier then return error
  43446      */
  43447 
  43448     if (max_length < offset_info->width) {
  43449         UDF_UNLOCK(unit);
  43450         return (BCM_E_PARAM);
  43451     }
  43452 
  43453     FP_LOCK(unit);
  43454 
  43455     /* Get stage field control structure. */
  43456     rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_INGRESS, &stage_fc);
  43457     if (BCM_FAILURE(rv)) {
  43458         FP_UNLOCK(unit);
  43459         UDF_UNLOCK(unit);
  43460         return (rv);
  43461     }
  43462 
  43463     rv = _bcm_field_entry_get_by_id(unit, eid, &f_ent);
  43464     if (BCM_FAILURE(rv)) {
  43465         FP_UNLOCK(unit);
  43466         UDF_UNLOCK(unit);
  43467         return (rv);
  43468     }
  43469 
  43470     /* Get field group */
  43471     fg = f_ent->group;
  43472 
  43473 #if defined(BCM_TOMAHAWK_SUPPORT)
  43474     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  43475         _BCM_FIELD_STAGE_INGRESS == fg->stage_id) {
  43476         FP_UNLOCK(unit);
  43477         UDF_UNLOCK(unit);
  43478         rv = (bcmi_field_th_qualify_udf_get(
  43479                     unit, eid, udf_id, max_length,
  43480                     data, mask, actual_length));
  43481         if (BCM_E_NOT_FOUND == rv) {
  43482             rv = _field_udf_hints_present_get(unit, eid, udf_id, &hints_present);
  43483             if (BCM_FAILURE(rv)) {
  43484                 return BCM_E_INTERNAL;
  43485             }
  43486             if (hints_present) {
  43487                 rv = BCM_E_NONE;
  43488             }
  43489         }
  43490 
  43491         return rv;
  43492     }
  43493 #endif
  43494 
  43495 
  43496     /* get qset */
  43497     qset = &(fg->qset);
  43498 
  43499     /* Get number of elems per UDF and elem size */
  43500     num_elems = BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit);
  43501 
  43502     for (idx = 0; idx < num_elems/2; idx++) {
  43503         if (!(offset_info->hw_bmap & (1 << idx))) {
  43504             continue;
  43505         }
  43506         udf1_elems++;
  43507     }
  43508 
  43509     for (idx = num_elems/2; idx < num_elems; idx++) {
  43510         if (!(offset_info->hw_bmap & (1 << idx))) {
  43511             continue;
  43512         }
  43513         udf2_elems++;
  43514     }
  43515 
  43516     if (udf1_elems != 0) {
  43517         qid = _bcmFieldQualifyData0;
  43518         max_elems = num_elems/2;
  43519         min_elems = 0;
  43520     } else if (udf2_elems != 0) {
  43521         qid = _bcmFieldQualifyData1;
  43522         max_elems = num_elems;
  43523         min_elems = num_elems/2;
  43524     }
  43525 
  43526     do {
  43527         /* Qset has Data2 Data3 instead of Data0 qualifier */
  43528         if ((qid == _bcmFieldQualifyData0) &&
  43529                 (!BCM_FIELD_QSET_TEST_INTERNAL(*qset, _bcmFieldQualifyData0))) {
  43530             sal_memset(udf_data, 0, sizeof(_bcm_field_qual_data_t));
  43531             sal_memset(udf_mask, 0, sizeof(_bcm_field_qual_data_t));
  43532             if (BCM_FIELD_QSET_TEST_INTERNAL(*qset, _bcmFieldQualifyData2)) {
  43533                 rv = _field_entry_qualifier_key_get(unit, eid, _bcmFieldQualifyData2,
  43534                         udf_data1, udf_mask1);
  43535                 if (BCM_FAILURE(rv)) {
  43536                     FP_UNLOCK(unit);
  43537                     UDF_UNLOCK(unit);
  43538                     return (rv);
  43539                 }
  43540                 udf_data[0] = udf_data1[0];
  43541                 udf_mask[0] = udf_mask1[0];
  43542             }
  43543             if (BCM_FIELD_QSET_TEST_INTERNAL(*qset, _bcmFieldQualifyData3)) {
  43544                 rv = _field_entry_qualifier_key_get(unit, eid, _bcmFieldQualifyData3,
  43545                         udf_data1, udf_mask1);
  43546                 if (BCM_FAILURE(rv)) {
  43547                     FP_UNLOCK(unit);
  43548                     UDF_UNLOCK(unit);
  43549                     return (rv);
  43550                 }
  43551                 udf_data[2] = udf_data1[0];
  43552                 udf_mask[2] = udf_mask1[0];
  43553             }
  43554         } else {
  43555             rv = _field_entry_qualifier_key_get(unit, eid, qid,
  43556                     udf_data, udf_mask);
  43557             if (BCM_FAILURE(rv)) {
  43558                 FP_UNLOCK(unit);
  43559                 UDF_UNLOCK(unit);
  43560                 return (rv);
  43561             }
  43562         }
  43563 #ifdef LE_HOST
  43564         for (part = 0; part < _FP_UDF_DATA_WORDS; part++) {
  43565             udf_data_swap[part]= _shr_swap32(udf_data[part]);
  43566             udf_data[part]= udf_data_swap[part];
  43567             udf_mask_swap[part]= _shr_swap32(udf_mask[part]);
  43568             udf_mask[part]= udf_mask_swap[part];
  43569         }
  43570 #endif /* LE_HOST */
  43571 
  43572         for (idx = min_elems; idx < max_elems; idx++) {
  43573             if (!(offset_info->hw_bmap & (1 << idx))) {
  43574                 continue;
  43575             }
  43576 
  43577             if ((offset_info->width - len) <= 0) {
  43578                 break;
  43579             }
  43580 
  43581             if (gran == UDF_OFFSET_GRAN2) {
  43582                 /*
  43583                  * Retreive the relevant data and mask from 4 words
  43584                  * (4 * 4 = 16 bytes) of data and mask.
  43585                  * For each index set  a chunk(2 bytes) are read. The way
  43586                  * information is organized is for different index values
  43587                  * data resides in following location.
  43588                  * index = 0 data in 12,13 - W = 3 offset = 0
  43589                  * index = 1 data in 14,15 - W = 3 offset = 2
  43590                  * index = 2 data in 8,9   - W = 2 offset = 0
  43591                  * index = 3 data in 10,11 - W = 2 offset = 2
  43592                  * index = 4 data in 4,5   - W = 1 offset = 0
  43593                  * index = 5 data in 6,7   - W = 1 offset = 2
  43594                  * index = 6 data is 0,1   - W = 0 offset = 0
  43595                  * index = 7 data is 2,3   - W = 0 offset = 2
  43596                  */
  43597                 off = idx % 2 * 2;
  43598                 copy_len = ((offset_info->width - len) == 1)? 1 : 2;
  43599                 if (len == 0) {
  43600                     off += offset_info->byte_offset;
  43601                     copy_len = 2 - offset_info->byte_offset;
  43602                     if (copy_len > offset_info->width) {
  43603                         copy_len = offset_info->width;
  43604                     }
  43605                 }
  43606                 sal_memcpy(data+len,
  43607                         (uint8 *)&udf_data[((max_elems - 1)
  43608                             - idx)/2]+off, copy_len);
  43609                 sal_memcpy(mask+len,
  43610                         (uint8 *)&udf_mask[((max_elems - 1)
  43611                             - idx)/2]+off, copy_len);
  43612                 len += copy_len;
  43613             } else {
  43614                 /* Retreive the relevant data and mask from 4 words
  43615                  * (4 * 4 = 16 bytes) of data and mask.
  43616                  * For each index set  a chunk(4 bytes) are read. The way
  43617                  * information is organized is for different index values
  43618                  * data resides in following location.
  43619                  * index = 0 data in 12,13,14,15 - W = 3 offset = 0
  43620                  * index = 1 data in 8,9,10,11   - W = 2 offset = 0
  43621                  * index = 2 data in 4,5,6,7     - W = 1 offset = 0
  43622                  * index = 3 data is 0,1,2,3     - W = 0 offset = 0
  43623                  */
  43624                 off = offset_info->byte_offset;
  43625                 if (len == 0) {
  43626                     /* first word */
  43627                     copy_len = 4 - off;
  43628                     /* Only one word */
  43629                     if (copy_len > offset_info->width) {
  43630                         copy_len = offset_info->width;
  43631                     }
  43632                     sal_memcpy(data+len,
  43633                             (uint8 *)&udf_data[(max_elems - 1) - idx] + off,
  43634                             copy_len);
  43635                     sal_memcpy(mask+len,
  43636                             (uint8 *)&udf_mask[(max_elems - 1) - idx] + off,
  43637                             copy_len);
  43638                     len += copy_len;
  43639                 } else if ((len + 4) > offset_info->width) {
  43640                     /* last word */
  43641                     sal_memcpy(data+len,
  43642                             (uint8 *)&udf_data[(max_elems - 1) - idx],
  43643                             (offset_info->width - len));
  43644                     sal_memcpy(mask+len,
  43645                             (uint8 *)&udf_mask[(max_elems - 1) - idx],
  43646                             (offset_info->width - len));
  43647                     len += (offset_info->width - len);
  43648                 } else {
  43649                     /* others */
  43650                     sal_memcpy(data+len,
  43651                             (uint8 *)&udf_data[(max_elems - 1) - idx], 4);
  43652                     sal_memcpy(mask+len,
  43653                             (uint8 *)&udf_mask[(max_elems - 1) - idx], 4);
  43654                     len += 4;
  43655                 }
  43656             }
  43657         }
  43658 
  43659         if ((qid == _bcmFieldQualifyData0) && (udf2_elems != 0)) {
  43660             qid = _bcmFieldQualifyData1;
  43661             max_elems = num_elems;
  43662             min_elems = num_elems/2;
  43663             continue;
  43664         }
  43665 
  43666         *actual_length = offset_info->width;
  43667         break;
  43668 
  43669     } while (1);
  43670 
  43671     FP_UNLOCK(unit);
  43672     UDF_UNLOCK(unit);
  43673 
  43674     return rv;
  43675 }
  43676 
  43677 #endif /* (BCM_TRIUMPH2_SUPPORT) */
  43678 
  43679 #if defined(INCLUDE_L3)
  43680 /*
  43681  * Function: _bcm_field_l3_egr_object_ifp_type_get
  43682  *
  43683  * Purpose:
  43684  *     Retrieve the IFP type and resolved next hop index with flags for the
  43685  *     given egress object index.
  43686  *
  43687  * Parameters:
  43688  *      unit       - (IN) Unit number.
  43689  *      nh_index   - (IN) Egress object index.
  43690  *      ifp_type   - (OUT) TRUE or FALSE
  43691  *      nh_flags   - (OUT) Next Hop Flags
  43692  *      nh_ecmp_id - (OUT) Resolved Next Hop Index.
  43693  *
  43694  * Returns:
  43695  *      BCM_E_XXX
  43696  * Notes:
  43697  */
  43698 int _bcm_field_l3_egr_object_ifp_type_index_get(int unit, bcm_if_t nh_index,
  43699                                                 int *ifp_type, uint32 *nh_flags,
  43700                                                 int *nh_ecmp_id)
  43701 {
  43702     int rv, ct;
  43703     int intf_ct = 0;
  43704     int intf_size = 0;
  43705     bcm_l3_egress_t l3_egr;
  43706     bcm_if_t *intf_arr = NULL;
  43707     int l3_object_ct = 0;
  43708     int ifp_object_ct = 0;
  43709 #ifdef BCM_TOMAHAWK_SUPPORT
  43710     int i = 0;
  43711     int total_intf_ct = 0, tmp_intf_ct = 0;
  43712     bcm_if_t *total_intf_arr = NULL;
  43713     int offset = 0;
  43714     int *intf_arr_cnt = NULL;
  43715 #endif
  43716 
  43717     if ((ifp_type == NULL) || (nh_flags == NULL) || (nh_ecmp_id == NULL)) {
  43718        return BCM_E_PARAM;
  43719     }
  43720 
  43721     /* Get next hop info from Egress Object ID param */
  43722     BCM_IF_ERROR_RETURN(_bcm_field_policy_set_l3_nh_resolve(unit,
  43723                                       nh_index, nh_flags, nh_ecmp_id));
  43724 
  43725     if (*nh_flags & BCM_L3_MULTIPATH) {
  43726 
  43727         if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, nh_index)) {
  43728             nh_index += BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit);
  43729         }
  43730 
  43731         rv = bcm_xgs3_l3_egress_multipath_get(unit, nh_index,
  43732                                               0, NULL, &intf_ct);
  43733         BCM_IF_ERROR_RETURN(rv);
  43734 
  43735         _FP_XGS3_ALLOC(intf_arr, (sizeof(bcm_if_t) * intf_ct),
  43736                        "FP: Temp Intf Array");
  43737         if (intf_arr == NULL) {
  43738            return (BCM_E_MEMORY);
  43739         }
  43740 
  43741         intf_size = intf_ct;
  43742         intf_ct = 0;
  43743         rv = bcm_esw_l3_egress_multipath_get(unit, nh_index,
  43744                                              intf_size,
  43745                                              intf_arr, &intf_ct);
  43746         if (BCM_FAILURE(rv)) {
  43747             sal_free(intf_arr);
  43748             return BCM_E_PARAM;
  43749         }
  43750 #ifdef BCM_TOMAHAWK_SUPPORT
  43751         /* In case of Hierarchical ECMP, Overlay groups may contain ECMP
  43752            interfaces as members. In such cases, these ecmp interfaces have to
  43753            be further resolved to get l3 interfaces */
  43754         if ((soc_feature(unit, soc_feature_hierarchical_ecmp) ||
  43755             (SOC_IS_TRIDENT3X(unit) && (soc_property_get(unit, spn_L3_ECMP_LEVELS, 1) == 2))) &&
  43756             BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, nh_index)) {
  43757 
  43758             /* coverity[overrun-local] */
  43759             if ((BCM_XGS3_L3_ECMP_GROUP_FLAGS_ISSET(unit,
  43760                  nh_index - BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit), BCM_L3_ECMP_OVERLAY))) {
  43761                  _FP_XGS3_ALLOC(intf_arr_cnt, sizeof(bcm_if_t) * intf_ct,
  43762                                              "FP:temp intf arr");
  43763                  /* First get the count of total ECMP interfaces.
  43764                     Go through all interfaces and get the next level interfaces
  43765                     if it is an ECMP interface. If not, add that to array of
  43766                     interfaces Count of ECMP interfaces needs to be maintained
  43767                     as bcm_xgs3_l3_egress_multipath_get returns interfaces only
  43768                     when correct count is passed. */
  43769                  for (i=0; i < intf_ct; i++) {
  43770                     if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, intf_arr[i])){
  43771                         total_intf_ct += 1;
  43772                         continue;
  43773                     }
  43774                     if ((BCM_XGS3_L3_ECMP_GROUP_FLAGS_ISSET(unit,
  43775                         intf_arr[i]-BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit),
  43776                         BCM_L3_ECMP_UNDERLAY))) {
  43777                         tmp_intf_ct = 0;
  43778                         nh_index = intf_arr[i];
  43779                         rv = bcm_xgs3_l3_egress_multipath_get(unit, nh_index, 0,
  43780                                                             NULL, &tmp_intf_ct);
  43781                         if (BCM_FAILURE(rv)) {
  43782                             sal_free(intf_arr_cnt);
  43783                             sal_free(intf_arr);
  43784                             return BCM_E_PARAM;
  43785                         }
  43786                         intf_arr_cnt[i] = tmp_intf_ct;
  43787                         total_intf_ct += tmp_intf_ct;
  43788                     } else {
  43789                             sal_free(intf_arr_cnt);
  43790                             sal_free(intf_arr);
  43791                             return BCM_E_PARAM;
  43792                     }
  43793                 }
  43794                 _FP_XGS3_ALLOC(total_intf_arr, sizeof(bcm_if_t) * total_intf_ct,
  43795                                                         "FP:temp intf arr");
  43796                 offset = 0;
  43797                 for (i=0; i < intf_ct; i++) {
  43798                     tmp_intf_ct = 0;
  43799                     if (!BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, intf_arr[i])){
  43800                         sal_memcpy(&total_intf_arr[offset], &intf_arr[i],
  43801                                    sizeof(bcm_if_t));
  43802                         offset += 1;
  43803                         continue;
  43804                     }
  43805 
  43806                     if ((BCM_XGS3_L3_ECMP_GROUP_FLAGS_ISSET(unit,
  43807                         intf_arr[i]-BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit), BCM_L3_ECMP_UNDERLAY))) {
  43808                         nh_index = intf_arr[i];
  43809                         rv = bcm_esw_l3_egress_multipath_get(unit, nh_index,
  43810                                 intf_arr_cnt[i], &total_intf_arr[offset], &tmp_intf_ct);
  43811                         if (BCM_FAILURE(rv)) {
  43812                             sal_free(intf_arr);
  43813                             sal_free(total_intf_arr);
  43814                             sal_free(intf_arr_cnt);
  43815                             return BCM_E_PARAM;
  43816                         }
  43817                         offset += tmp_intf_ct;
  43818                     }
  43819                 }
  43820                 sal_free(intf_arr);
  43821                 sal_free(intf_arr_cnt);
  43822                 intf_arr = total_intf_arr;
  43823                 intf_ct = total_intf_ct;
  43824 
  43825             }
  43826         }
  43827 #endif
  43828 
  43829     } else {
  43830         if (!BCM_XGS3_L3_EGRESS_IDX_VALID(unit, nh_index) &&
  43831                 !(soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  43832                     BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, nh_index))) {
  43833             nh_index += BCM_XGS3_EGRESS_IDX_MIN(unit);
  43834         }
  43835 
  43836         intf_ct = 1;
  43837         _FP_XGS3_ALLOC(intf_arr, (sizeof(bcm_if_t) * intf_ct),
  43838                        "FP: Temp Intf Array");
  43839         if (intf_arr == NULL) {
  43840            return (BCM_E_MEMORY);
  43841         }
  43842         intf_arr[0] = nh_index;
  43843     }
  43844 
  43845     for (ct = 0; ct < intf_ct; ct++) {
  43846         rv = bcm_esw_l3_egress_get(unit, intf_arr[ct], &l3_egr);
  43847         if (BCM_FAILURE(rv)) {
  43848            sal_free(intf_arr);
  43849            return BCM_E_PARAM;
  43850         }
  43851 
  43852         if (l3_egr.flags2 & BCM_L3_FLAGS2_FIELD_ONLY) {
  43853            ifp_object_ct++;
  43854         } else {
  43855            l3_object_ct++;
  43856         }
  43857     }
  43858 
  43859     if (ifp_object_ct && l3_object_ct) {
  43860        sal_free(intf_arr);
  43861        return BCM_E_PARAM;
  43862     }
  43863 
  43864     if (ifp_object_ct) {
  43865        *ifp_type = TRUE;
  43866     } else {
  43867        *ifp_type = FALSE;
  43868     }
  43869 
  43870     sal_free(intf_arr);
  43871     return BCM_E_NONE;
  43872 }
  43873 
  43874 #endif /* INCLUDE_L3 */
  43875 
  43876 /*
  43877  * Function:
  43878  *     _bcm_field_initialized_status_get
  43879  * Purpose:
  43880  *     Check whether the field module is initialized
  43881  * Parameters:
  43882  *     unit   - BCM device number
  43883  *     status - Reference to the init status.
  43884  *              returns TRUE if initialized
  43885  *                      FALSE if not initialized.
  43886  */
  43887 int
  43888 _bcm_field_initialized_status_get(int unit, uint8 *status)
  43889 {
  43890     if (status == NULL) {
  43891         return BCM_E_PARAM;
  43892     }
  43893 
  43894     if (!soc_feature(unit, soc_feature_field)) {
  43895         return (BCM_E_UNAVAIL);
  43896     }
  43897 
  43898     *status = FALSE;
  43899     if (_field_control[unit] != NULL) {
  43900        *status = (TRUE == _field_control[unit]->init) ? TRUE:FALSE;
  43901     }
  43902 
  43903     return BCM_E_NONE;
  43904 }
  43905 
  43906 
  43907 #ifdef BCM_WARM_BOOT_SUPPORT
  43908 int
  43909 _field_table_pointers_init(int unit, _field_table_pointers_t *field_tables)
  43910 {
  43911     if (NULL == field_tables) {
  43912         return BCM_E_INTERNAL;
  43913     }
  43914 
  43915     field_tables->fp_global_mask_tcam_buf = NULL;
  43916     field_tables->fp_gm_tcam_x_buf        = NULL;
  43917     field_tables->fp_gm_tcam_y_buf        = NULL;
  43918     field_tables->fp_tcam_buf             = NULL;
  43919     field_tables->fp_tcam_x_buf           = NULL;
  43920     field_tables->fp_tcam_y_buf           = NULL;
  43921 
  43922     return BCM_E_NONE;
  43923 }
  43924 
  43925 /*
  43926  * Function: _field_entry_no_param_actions_scache_sync
  43927  *
  43928  * Purpose:
  43929  *        Sync entry field actions with no params into scache
  43930  * Parameters:
  43931  *     unit       - (IN) BCM device number.
  43932  *     stage_fc   - (IN) Stage Control.
  43933  *     fc         - (IN) Field Control.
  43934  *     f_ent      - (IN) Entry structure.
  43935  *     scache_buf - (OUT) Update Scache buffer.
  43936  * Returns:
  43937  *      BCM_E_XXXX.
  43938  */
  43939 int _field_entry_no_param_actions_scache_sync(int unit,
  43940                                      _field_stage_t   *stage_fc,
  43941                                      _field_control_t *fc,
  43942                                      _field_entry_t   *f_ent,
  43943                                      uint8 *scache_buf)
  43944 {
  43945     _field_action_t  *fa;
  43946     _field_action_bmp_t action_bk_bitmap; /* bit map of actions used for entry */
  43947     int errcode = BCM_E_NONE;
  43948     int _action = -1;
  43949     int size;
  43950     int copyToCpuZeroParam1 = 0;
  43951     int gport_type = 0;
  43952 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) || \
  43953                 defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  43954     uint32 PortPrioIntGportVal = 0;
  43955     uint32 YpPortPrioIntGportVal = 0;
  43956     uint32 RpPortPrioIntGportVal = 0;
  43957 #endif
  43958 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3)
  43959     int ingressGportAction = -1;
  43960     int ingressGportVal = 0;
  43961 #endif
  43962     bcm_gport_t ingress_mirror_gport[4] = {0};
  43963     _bcmFieldActionNoParam_t ingress_mirror_actions[] = {
  43964                                     _bcmFieldActionNoParamMirrorIngress,
  43965                                     _bcmFieldActionNoParamMirrorIngress1,
  43966                                     _bcmFieldActionNoParamMirrorIngress2,
  43967                                     _bcmFieldActionNoParamMirrorIngress3};
  43968     bcm_gport_t egress_mirror_gport[4] = {0};
  43969     _bcmFieldActionNoParam_t egress_mirror_actions[] = {
  43970                                     _bcmFieldActionNoParamMirrorEgress,
  43971                                     _bcmFieldActionNoParamMirrorEgress1,
  43972                                     _bcmFieldActionNoParamMirrorEgress2,
  43973                                     _bcmFieldActionNoParamMirrorEgress3};
  43974     uint32 param0 = 0;
  43975     uint8  index = 0;
  43976 #if defined(BCM_KATANA_SUPPORT)
  43977     uint32 param1 = 0;
  43978 #endif /* BCM_KATANA_SUPPORT */
  43979 
  43980     if (stage_fc == NULL || fc == NULL || f_ent == NULL || scache_buf == NULL) {
  43981        return BCM_E_PARAM;
  43982     }
  43983 
  43984     if ((stage_fc->stage_id != _BCM_FIELD_STAGE_INGRESS) &&
  43985         (stage_fc->stage_id != _BCM_FIELD_STAGE_EGRESS) &&
  43986         (stage_fc->stage_id != _BCM_FIELD_STAGE_LOOKUP)) {
  43987         return BCM_E_NONE;
  43988     }
  43989 
  43990     action_bk_bitmap.w = NULL;
  43991     _FP_XGS3_ALLOC(action_bk_bitmap.w, SHR_BITALLOCSIZE(_bcmFieldActionNoParamCount),
  43992                     "Action No Param Bitmap");
  43993 
  43994     if (action_bk_bitmap.w == NULL) {
  43995        return BCM_E_MEMORY;
  43996     }
  43997 
  43998     fa = f_ent->actions;
  43999     for (fa = f_ent->actions; fa != NULL; fa = fa->next) {
  44000         switch(fa->action) {
  44001         case bcmFieldActionPrioPktAndIntCopy:
  44002         case bcmFieldActionPrioPktAndIntNew:
  44003         case bcmFieldActionPrioPktNew:
  44004         case bcmFieldActionPrioPktAndIntTos:
  44005         case bcmFieldActionPrioPktAndIntCancel:
  44006         case bcmFieldActionPrioPktCopy:
  44007         case bcmFieldActionPrioPktTos:
  44008         case bcmFieldActionPrioPktCancel:
  44009             _action = _bcmFieldActionNoParamPrioPktNoColor;
  44010             break;
  44011         case bcmFieldActionPrioIntCopy:
  44012         case bcmFieldActionPrioIntNew:
  44013         case bcmFieldActionPrioIntTos:
  44014         case bcmFieldActionPrioIntCancel:
  44015             _action = _bcmFieldActionNoParamPrioIntNoColor;
  44016             break;
  44017         case bcmFieldActionCopyToCpu:
  44018         case bcmFieldActionTimeStampToCpu:
  44019             _action = _bcmFieldActionNoParamCopyToCpuNoColor;
  44020             if ((fa->param[0] != 0) && (fa->param[1] == 0)) {
  44021                 copyToCpuZeroParam1 = 1;
  44022             }
  44023             break;
  44024         case bcmFieldActionCopyToCpuCancel:
  44025         case bcmFieldActionSwitchToCpuCancel:
  44026         case bcmFieldActionSwitchToCpuReinstate:
  44027         case bcmFieldActionTimeStampToCpuCancel:
  44028             _action = _bcmFieldActionNoParamCopyToCpuNoColor;
  44029             break;
  44030         case bcmFieldActionRpCopyToCpu:
  44031         case bcmFieldActionRpTimeStampToCpu:
  44032             if ((fa->param[0] != 0) && (fa->param[1] == 0)) {
  44033                 _action = _bcmFieldActionNoParamRpCopyToCpuZeroParam1;
  44034             }
  44035             break;
  44036         case bcmFieldActionYpCopyToCpu:
  44037         case bcmFieldActionYpTimeStampToCpu:
  44038             if ((fa->param[0] != 0) && (fa->param[1] == 0)) {
  44039                 _action = _bcmFieldActionNoParamYpCopyToCpuZeroParam1;
  44040             }
  44041             break;
  44042         case bcmFieldActionGpCopyToCpu:
  44043         case bcmFieldActionGpTimeStampToCpu:
  44044             if ((fa->param[0] != 0) && (fa->param[1] == 0)) {
  44045                 _action = _bcmFieldActionNoParamCopyToCpuZeroParam1;
  44046             }
  44047             break;
  44048         case bcmFieldActionDrop:
  44049         case bcmFieldActionDropCancel:
  44050             _action = _bcmFieldActionNoParamDropNoColor;
  44051             break;
  44052         case bcmFieldActionOamUpMep:
  44053             if (fa->param[0] != 0) {
  44054                 continue;
  44055             }
  44056             _action = _bcmFieldActionNoParamOamUpMep;
  44057             break;
  44058         case bcmFieldActionOamTx:
  44059             if (fa->param[0] != 0) {
  44060                 continue;
  44061             }
  44062             _action = _bcmFieldActionNoParamOamTx;
  44063             break;
  44064         case bcmFieldActionOamLmepEnable:
  44065             if (fa->param[0] != 0) {
  44066                 continue;
  44067             }
  44068             _action = _bcmFieldActionNoParamOamLmepEnable;
  44069             break;
  44070         case bcmFieldActionOamLmEnable:
  44071             if (fa->param[0] != 0) {
  44072                 continue;
  44073             }
  44074             _action = _bcmFieldActionNoParamOamLmEnable;
  44075             break;
  44076         case bcmFieldActionOamDmEnable:
  44077             if (fa->param[0] != 0) {
  44078                 continue;
  44079             }
  44080             _action = _bcmFieldActionNoParamOamDmEnable;
  44081             break;
  44082         case bcmFieldActionOamLmepMdl:
  44083             if (fa->param[0] != 0) {
  44084                 continue;
  44085             }
  44086             _action = _bcmFieldActionNoParamOamLmepMdl;
  44087             break;
  44088         case bcmFieldActionOamLmBasePtr:
  44089             if (fa->param[0] != 0) {
  44090                 continue;
  44091             }
  44092             _action = _bcmFieldActionNoParamOamLmBasePtr;
  44093             break;
  44094         case bcmFieldActionOamServicePriMappingPtr:
  44095             if (fa->param[0] != 0) {
  44096                 continue;
  44097             }
  44098             _action = _bcmFieldActionNoParamOamServicePriMappingPtr;
  44099             break;
  44100         case bcmFieldActionOamPbbteLookupEnable:
  44101             if (fa->param[0] != 0) {
  44102                 continue;
  44103             }
  44104             _action = _bcmFieldActionNoParamOamPbbteLookupEnable;
  44105             break;
  44106         case bcmFieldActionOamLmDmSampleEnable:
  44107             if (fa->param[0] != 0) {
  44108                 continue;
  44109             }
  44110             _action = _bcmFieldActionNoParamOamLmDmSampleEnable;
  44111             break;
  44112         case bcmFieldActionNewClassId:
  44113             if (fa->param[0] != 0) {
  44114                 continue;
  44115             }
  44116             _action = _bcmFieldActionNoParamNewClassId;
  44117             break;
  44118         case bcmFieldActionOamLmCounterPoolId:
  44119             _action = _bcmFieldActionNoParamOamLmCounterPoolId;
  44120             break;
  44121         case bcmFieldActionDscpNew:
  44122         case bcmFieldActionDscpCancel:
  44123             _action = _bcmFieldActionNoParamDscpNoColor;
  44124             break;
  44125         case bcmFieldActionInnerVlanPrioNew:
  44126             _action = _bcmFieldActionNoParamInnerVlanPriNewNoColor;
  44127             break;
  44128         case bcmFieldActionOuterVlanPrioNew:
  44129             _action = _bcmFieldActionNoParamOuterVlanPriNewNoColor;
  44130             break;
  44131         case bcmFieldActionInnerVlanCfiNew:
  44132             _action = _bcmFieldActionNoParamInnerVlanCfiNewNoColor;
  44133             break;
  44134         case bcmFieldActionOuterVlanCfiNew:
  44135             _action = _bcmFieldActionNoParamOuterVlanCfiNewNoColor;
  44136             break;
  44137         case bcmFieldActionEcnNew:
  44138             _action = _bcmFieldActionNoParamEcnNewNoColor;
  44139             break;
  44140         case bcmFieldActionRpDropPrecedence:
  44141             if (fa->param[0] != 0) {
  44142                 continue;
  44143             }
  44144             _action = _bcmFieldActionNoParamRpDropPrecedence;
  44145             break;
  44146         case bcmFieldActionYpDropPrecedence:
  44147             if (fa->param[0] != 0) {
  44148                 continue;
  44149             }
  44150             _action = _bcmFieldActionNoParamYpDropPrecedence;
  44151             break;
  44152         case bcmFieldActionGpDropPrecedence:
  44153             if (fa->param[0] != 0) {
  44154                 continue;
  44155             }
  44156             _action = _bcmFieldActionNoParamGpDropPrecedence;
  44157             break;
  44158         case bcmFieldActionDropPrecedence:
  44159             _action = _bcmFieldActionNoParamDropPrecedenceNoColor;
  44160             break;
  44161 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3)
  44162         case bcmFieldActionIngressGportSet:
  44163             _action = _bcmFieldActionNoParamIngressGportSet;
  44164             ingressGportAction = 1;
  44165             ingressGportVal = fa->param[0];
  44166             break;
  44167 #endif /* INCLUDE_L3 */
  44168         case bcmFieldActionRedirectIpmc:
  44169             if (_BCM_MULTICAST_IS_WLAN(fa->param[0])) {
  44170                 _action = _bcmFieldActionNoParamRedirectIpmcWlan;
  44171             } else if (_BCM_MULTICAST_IS_VPLS(fa->param[0])) {
  44172                 _action = _bcmFieldActionNoParamRedirectIpmcVpls;
  44173             } else if (_BCM_MULTICAST_IS_L3(fa->param[0])) {
  44174                 _action = _bcmFieldActionNoParamRedirectIpmcL3;
  44175             } else if (_BCM_MULTICAST_IS_VLAN(fa->param[0])) {
  44176                 _action = _bcmFieldActionNoParamRedirectIpmcVlan;
  44177             }
  44178             break;
  44179 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3)
  44180         case bcmFieldActionIncomingMplsPortSet:
  44181             _action = _bcmFieldActionNoParamIncomingMplsPortSet;
  44182             ingressGportAction = 1;
  44183             ingressGportVal = fa->param[0];
  44184             break;
  44185 #endif /* INCLUDE_L3 */
  44186 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) || \
  44187             defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  44188         case bcmFieldActionPortPrioIntCosQNew:
  44189             _action = _bcmFieldActionNoParamPortPrioIntCosQNew;
  44190             PortPrioIntGportVal = fa->param[1];
  44191             break;
  44192         case bcmFieldActionGpPortPrioIntCosQNew:
  44193             _action = _bcmFieldActionNoParamGpPortPrioIntCosQNew;
  44194             PortPrioIntGportVal = fa->param[1];
  44195             break;
  44196         case bcmFieldActionYpPortPrioIntCosQNew:
  44197             _action = _bcmFieldActionNoParamYpPortPrioIntCosQNew;
  44198             YpPortPrioIntGportVal = fa->param[1];
  44199             break;
  44200         case bcmFieldActionRpPortPrioIntCosQNew:
  44201             _action = _bcmFieldActionNoParamRpPortPrioIntCosQNew;
  44202             RpPortPrioIntGportVal = fa->param[1];
  44203             break;
  44204 #endif
  44205         case bcmFieldActionMirrorIngress:
  44206             if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_20) {
  44207                 if (!BCM_GPORT_IS_MIRROR(fa->param[1])) {
  44208                     continue;
  44209                 }
  44210 
  44211 #ifdef BCM_TRIUMPH2_SUPPORT
  44212                 if (((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_21) &&
  44213                     soc_feature(unit, soc_feature_mirror_flexible) &&
  44214                     (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id)) {
  44215                     int mtp_type_index;
  44216                     int flexibleMirror;
  44217                     int directedMirror;
  44218                     int rv;
  44219 
  44220                     rv = bcm_esw_switch_control_get(unit,bcmSwitchFlexibleMirrorDestinations,
  44221                                                     &flexibleMirror);
  44222                     if (BCM_FAILURE(rv)) {
  44223                         errcode = rv;
  44224                         goto cleanup;
  44225                     }
  44226 
  44227                     rv = bcm_esw_switch_control_get(unit,bcmSwitchDirectedMirroring,
  44228                                                     &directedMirror);
  44229                     if (BCM_FAILURE(rv)) {
  44230                         errcode = rv;
  44231                         goto cleanup;
  44232                     }
  44233 
  44234                     if (flexibleMirror && directedMirror) {
  44235                         mtp_type_index = ((fa->hw_index >> BCM_MIRROR_MTP_FLEX_SLOT_SHIFT)
  44236                                           & BCM_MIRROR_MTP_FLEX_SLOT_MASK);
  44237                     } else {
  44238                         mtp_type_index = fa->hw_index;
  44239                     }
  44240                     if ((mtp_type_index >= 4) || (mtp_type_index < 0)) {
  44241                         errcode = BCM_E_INTERNAL;
  44242                         goto cleanup;
  44243                     }
  44244                     _action = ingress_mirror_actions[mtp_type_index];
  44245                     ingress_mirror_gport[mtp_type_index] = fa->param[1];
  44246                 } else
  44247 #endif
  44248                 {
  44249                     _action = _bcmFieldActionNoParamMirrorIngress;
  44250                     ingress_mirror_gport[0] = fa->param[1];
  44251                 }
  44252             }
  44253             break;
  44254         case bcmFieldActionMirrorEgress:
  44255             if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_20) {
  44256                 if (!BCM_GPORT_IS_MIRROR(fa->param[1])) {
  44257                     continue;
  44258                 }
  44259 #ifdef BCM_TRIUMPH2_SUPPORT
  44260                 if (((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_21) &&
  44261                     soc_feature(unit, soc_feature_mirror_flexible) &&
  44262                     (_BCM_FIELD_STAGE_INGRESS == f_ent->group->stage_id)) {
  44263                     int mtp_type_index;
  44264                     int flexibleMirror;
  44265                     int directedMirror;
  44266                     int rv;
  44267 
  44268                     rv = bcm_esw_switch_control_get(unit,bcmSwitchFlexibleMirrorDestinations,
  44269                                                     &flexibleMirror);
  44270                     if (BCM_FAILURE(rv)) {
  44271                         errcode = rv;
  44272                         goto cleanup;
  44273                     }
  44274 
  44275                     rv = bcm_esw_switch_control_get(unit,bcmSwitchDirectedMirroring,
  44276                                                     &directedMirror);
  44277                     if (BCM_FAILURE(rv)) {
  44278                         errcode = rv;
  44279                         goto cleanup;
  44280                     }
  44281 
  44282                     if (flexibleMirror && directedMirror) {
  44283                         mtp_type_index = ((fa->hw_index >> BCM_MIRROR_MTP_FLEX_SLOT_SHIFT)
  44284                                           & BCM_MIRROR_MTP_FLEX_SLOT_MASK);
  44285                     } else {
  44286                         mtp_type_index = fa->hw_index;
  44287                     }
  44288                     if ((mtp_type_index >= 4) || (mtp_type_index < 0)) {
  44289                         errcode = BCM_E_INTERNAL;
  44290                         goto cleanup;
  44291                     }
  44292                     _action = egress_mirror_actions[mtp_type_index];
  44293                     egress_mirror_gport[mtp_type_index] = fa->param[1];
  44294                 } else
  44295 #endif
  44296                 {
  44297                     _action = _bcmFieldActionNoParamMirrorEgress;
  44298                     egress_mirror_gport[0] = fa->param[1];
  44299                 }
  44300             }
  44301             break;
  44302         case bcmFieldActionRedirDropPrecedence:
  44303             _action = _bcmFieldActionNoParamRedirDropPrecedenceNoColor;
  44304             break;
  44305         case bcmFieldActionFabricQueue:
  44306             _action = _bcmFieldActionNoParamFabricQueue;
  44307             param0 = fa->param[0];
  44308 #if defined(BCM_KATANA_SUPPORT)
  44309             if (SOC_IS_KATANAX(unit)) {
  44310                 param1 = fa->param[1];
  44311             }
  44312 #endif
  44313             break;
  44314         case bcmFieldActionEnableVlanCheck:
  44315             _action = _bcmFieldActionNoParamEnableVlanCheck;
  44316             break;
  44317         case bcmFieldActionHiGigIntPriNew:
  44318             _action = _bcmFieldActionNoParamHiGigIntPriNew;
  44319             break;
  44320         case bcmFieldActionHiGigDropPrecedenceNew:
  44321             _action = _bcmFieldActionNoParamHiGigDropPrecedenceNew;
  44322             break;
  44323         case bcmFieldActionRedirect:
  44324 #ifdef BCM_TRIUMPH3_SUPPORT
  44325             if (SOC_IS_TRIUMPH3(unit) || SOC_IS_TD2_TT2(unit)) {
  44326                 if (BCM_GPORT_IS_MPLS_PORT(fa->param[1])) {
  44327                     _action = _bcmFieldActionNoParamRedirectMpls;
  44328                 } else if (BCM_GPORT_IS_MIM_PORT(fa->param[1])) {
  44329                     _action = _bcmFieldActionNoParamRedirectMim;
  44330                 } else if (BCM_GPORT_IS_NIV_PORT(fa->param[1])) {
  44331                     _action = _bcmFieldActionNoParamRedirectNiv;
  44332                 } else if (BCM_GPORT_IS_TRILL_PORT(fa->param[1])) {
  44333                     _action = _bcmFieldActionNoParamRedirectTrill;
  44334                 } else if (BCM_GPORT_IS_L2GRE_PORT(fa->param[1])) {
  44335                     _action = _bcmFieldActionNoParamRedirectL2Gre;
  44336                 } else if (BCM_GPORT_IS_VXLAN_PORT(fa->param[1])) {
  44337                     _action = _bcmFieldActionNoParamRedirectVxLan;
  44338                 }
  44339             }
  44340 #endif
  44341             break;
  44342         case bcmFieldActionRedirectTrunk:
  44343 #if defined(BCM_TRIDENT2_SUPPORT)
  44344             if ((soc_feature(unit, soc_feature_vp_lag)) &&
  44345                 ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_24)) {
  44346                 _action = _bcmFieldActionNoParamRedirectTrunk;
  44347             }
  44348 #endif
  44349             break;
  44350 #if defined(BCM_MONTEREY_SUPPORT) && defined(INCLUDE_XFLOW_MACSEC)
  44351         case bcmFieldActionMacSecSubPortNumAdd:
  44352             if (SOC_IS_MONTEREY(unit)) {
  44353                 if (BCM_XFLOW_MACSEC_SUBPORT_ID_DIR_TYPE_GET(fa->param[0]) \
  44354                     == BCM_XFLOW_MACSEC_ENCRYPT) {
  44355                     _action = _bcmFieldActionNoParamMacSecSubPortEncrypt;
  44356                 } else {
  44357                     _action = _bcmFieldActionNoParamMacSecSubPortDecrypt;
  44358                 }
  44359             }
  44360             break;
  44361 #endif
  44362 #if defined(BCM_GREYHOUND2_SUPPORT)
  44363        case bcmFieldActionSRNetIdSource:
  44364             _action = _bcmFieldActionNoParamSRNetIdSource;
  44365             break;
  44366 #endif /* BCM_GREYHOUND2_SUPPORT */
  44367         default:
  44368             continue;
  44369         }
  44370         if (_action != -1) {
  44371             _FP_ACTION_BMP_ADD(action_bk_bitmap, _action);
  44372             _action = -1;
  44373         }
  44374     }
  44375 
  44376     if (copyToCpuZeroParam1 == 1) {
  44377         _FP_ACTION_BMP_ADD(action_bk_bitmap,
  44378                            _bcmFieldActionNoParamCopyToCpuZeroParam1);
  44379     }
  44380 
  44381     size = SHR_BITALLOCSIZE(_bcmFieldActionNoParamCount);
  44382     LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
  44383             "%s(): Writing actions backup bitmap[0x%x] for entry:%d size:%d"
  44384             " @ byte %d.\n\r"), __func__,
  44385             action_bk_bitmap.w[0], f_ent->eid, size, fc->scache_pos));
  44386 
  44387     /* To avoid endiness issues always sync in mutlple of 4 bytes */
  44388     scache_buf[fc->scache_pos] = action_bk_bitmap.w[0];
  44389     fc->scache_pos++;
  44390     scache_buf[fc->scache_pos] = action_bk_bitmap.w[0] >> 8;
  44391     fc->scache_pos++;
  44392     scache_buf[fc->scache_pos] = action_bk_bitmap.w[0] >> 16;
  44393     fc->scache_pos++;
  44394     scache_buf[fc->scache_pos] = action_bk_bitmap.w[0] >> 24;
  44395     fc->scache_pos++;
  44396     if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_19) {
  44397         scache_buf[fc->scache_pos] = action_bk_bitmap.w[1];
  44398         fc->scache_pos++;
  44399         scache_buf[fc->scache_pos] = action_bk_bitmap.w[1] >> 8;
  44400         fc->scache_pos++;
  44401         scache_buf[fc->scache_pos] = action_bk_bitmap.w[1] >> 16;
  44402         fc->scache_pos++;
  44403         scache_buf[fc->scache_pos] = action_bk_bitmap.w[1] >> 24;
  44404         fc->scache_pos++;
  44405 #if defined(BCM_KATANA2_SUPPORT) || defined(BCM_TRIDENT2_SUPPORT) || \
  44406         defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  44407         /* Sync data only if actions are present */
  44408         if ((SHR_BITGET(action_bk_bitmap.w, _bcmFieldActionNoParamPortPrioIntCosQNew)) ||
  44409             (SHR_BITGET(action_bk_bitmap.w, _bcmFieldActionNoParamGpPortPrioIntCosQNew))) {
  44410             scache_buf[fc->scache_pos] = PortPrioIntGportVal;
  44411             fc->scache_pos++;
  44412             scache_buf[fc->scache_pos] = PortPrioIntGportVal >> 8;
  44413             fc->scache_pos++;
  44414             scache_buf[fc->scache_pos] = PortPrioIntGportVal >> 16;
  44415             fc->scache_pos++;
  44416             scache_buf[fc->scache_pos] = PortPrioIntGportVal >> 24;
  44417             fc->scache_pos++;
  44418         }
  44419         if (SHR_BITGET(action_bk_bitmap.w, _bcmFieldActionNoParamYpPortPrioIntCosQNew)) {
  44420             scache_buf[fc->scache_pos] = YpPortPrioIntGportVal;
  44421             fc->scache_pos++;
  44422             scache_buf[fc->scache_pos] = YpPortPrioIntGportVal >> 8;
  44423             fc->scache_pos++;
  44424             scache_buf[fc->scache_pos] = YpPortPrioIntGportVal >> 16;
  44425             fc->scache_pos++;
  44426             scache_buf[fc->scache_pos] = YpPortPrioIntGportVal >> 24;
  44427             fc->scache_pos++;
  44428         }
  44429         if (SHR_BITGET(action_bk_bitmap.w, _bcmFieldActionNoParamRpPortPrioIntCosQNew)) {
  44430             scache_buf[fc->scache_pos] = RpPortPrioIntGportVal;
  44431             fc->scache_pos++;
  44432             scache_buf[fc->scache_pos] = RpPortPrioIntGportVal >> 8;
  44433             fc->scache_pos++;
  44434             scache_buf[fc->scache_pos] = RpPortPrioIntGportVal >> 16;
  44435             fc->scache_pos++;
  44436             scache_buf[fc->scache_pos] = RpPortPrioIntGportVal >> 24;
  44437             fc->scache_pos++;
  44438         }
  44439 #endif
  44440     }
  44441 
  44442 #if defined(BCM_TRX_SUPPORT) && defined(INCLUDE_L3)
  44443     if (ingressGportAction == 1) {
  44444         /* Get the source virtual port value */
  44445         if (BCM_GPORT_IS_MPLS_PORT(ingressGportVal)) {
  44446             gport_type = _bcmVpTypeMpls;
  44447         } else if (BCM_GPORT_IS_MIM_PORT(ingressGportVal)) {
  44448             gport_type = _bcmVpTypeMim;
  44449         } else if (BCM_GPORT_IS_WLAN_PORT(ingressGportVal)) {
  44450             gport_type = _bcmVpTypeWlan;
  44451         } else if (BCM_GPORT_IS_TRILL_PORT(ingressGportVal)) {
  44452             gport_type = _bcmVpTypeTrill;
  44453         } else if (BCM_GPORT_IS_NIV_PORT(ingressGportVal)) {
  44454             gport_type = _bcmVpTypeNiv;
  44455         } else if (BCM_GPORT_IS_VXLAN_PORT(ingressGportVal)) {
  44456             gport_type = _bcmVpTypeVxlan;
  44457         } else if (BCM_GPORT_IS_FLOW_PORT(ingressGportVal)) {
  44458             gport_type = _bcmVpTypeFlow;
  44459         } else if (BCM_GPORT_IS_VLAN_PORT(ingressGportVal)) {
  44460             gport_type = _bcmVpTypeVlan;
  44461         } else {
  44462             errcode = BCM_E_PARAM;
  44463             goto cleanup;
  44464         }
  44465     }
  44466 #endif /* INCLUDE_L3 */
  44467     /* Reserve 1-byte to write IngressGportAction Gport Type. */
  44468     if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_16) {
  44469         scache_buf[fc->scache_pos] = gport_type;
  44470         fc->scache_pos++;
  44471     }
  44472 
  44473     /* Reserve 4-bytes each for Ingress and Egress Mirror Gports. */
  44474     if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_20) {
  44475         for (index = 0 ; index < 4; index++) {
  44476             if (SHR_BITGET(action_bk_bitmap.w, ingress_mirror_actions[index])) {
  44477                 scache_buf[fc->scache_pos] = ingress_mirror_gport[index];
  44478                 fc->scache_pos++;
  44479                 scache_buf[fc->scache_pos] = ingress_mirror_gport[index] >> 8;
  44480                 fc->scache_pos++;
  44481                 scache_buf[fc->scache_pos] = ingress_mirror_gport[index] >> 16;
  44482                 fc->scache_pos++;
  44483                 scache_buf[fc->scache_pos] = ingress_mirror_gport[index] >> 24;
  44484                 fc->scache_pos++;
  44485             }
  44486         }
  44487         for (index = 0 ; index < 4; index++) {
  44488             if (SHR_BITGET(action_bk_bitmap.w, egress_mirror_actions[index])) {
  44489                 scache_buf[fc->scache_pos] = egress_mirror_gport[index];
  44490                 fc->scache_pos++;
  44491                 scache_buf[fc->scache_pos] = egress_mirror_gport[index] >> 8;
  44492                 fc->scache_pos++;
  44493                 scache_buf[fc->scache_pos] = egress_mirror_gport[index] >> 16;
  44494                 fc->scache_pos++;
  44495                 scache_buf[fc->scache_pos] = egress_mirror_gport[index] >> 24;
  44496                 fc->scache_pos++;
  44497             }
  44498         }
  44499         if ( SHR_BITGET(action_bk_bitmap.w,
  44500                         _bcmFieldActionNoParamFabricQueue)) {
  44501             scache_buf[fc->scache_pos] = param0;
  44502             fc->scache_pos++;
  44503             scache_buf[fc->scache_pos] = param0 >> 8;
  44504             fc->scache_pos++;
  44505             scache_buf[fc->scache_pos] = param0 >> 16;
  44506             fc->scache_pos++;
  44507             scache_buf[fc->scache_pos] = param0 >> 24;
  44508             fc->scache_pos++;
  44509 #if defined(BCM_KATANA_SUPPORT)
  44510             if (SOC_IS_KATANAX(unit)) {
  44511                 scache_buf[fc->scache_pos] = param1;
  44512                 fc->scache_pos++;
  44513                 scache_buf[fc->scache_pos] = param1 >> 8;
  44514                 fc->scache_pos++;
  44515                 scache_buf[fc->scache_pos] = param1 >> 16;
  44516                 fc->scache_pos++;
  44517                 scache_buf[fc->scache_pos] = param1 >> 24;
  44518                 fc->scache_pos++;
  44519             }
  44520 #endif /* BCM_KATANA_SUPPORT*/
  44521         }
  44522     }
  44523     goto cleanup;
  44524 cleanup:
  44525     if (action_bk_bitmap.w != NULL) {
  44526         _FP_ACTION_BMP_FREE(action_bk_bitmap);
  44527         action_bk_bitmap.w = NULL;
  44528     }
  44529     return (errcode);
  44530 }
  44531 
  44532 int _field_group_slice_sel_get(int unit,
  44533                                _field_group_t *fg,
  44534                                _field_slice_sel_info_t *slice_sels)
  44535 {
  44536     int i = 0;
  44537     int parts_count = 0;
  44538 
  44539     /* Retrieve the parts count for the given group */
  44540     BCM_IF_ERROR_RETURN(_bcm_field_entry_tcam_parts_count(unit, fg->stage_id,
  44541                                            fg->flags, &parts_count));
  44542 
  44543     for (i = 0; i < parts_count; i++) {
  44544         if (fg->sel_codes[i].src_class_sel != _FP_INVALID_INDEX) {
  44545            _FP_SEL_BMP_ADD(slice_sels->slice_sel[i],
  44546                            _bcmFieldGroupSliceSrcClassSel);
  44547          }
  44548          if (fg->sel_codes[i].dst_class_sel != _FP_INVALID_INDEX) {
  44549            _FP_SEL_BMP_ADD(slice_sels->slice_sel[i],
  44550                            _bcmFieldGroupSliceDstClassSel);
  44551          }
  44552          if (fg->sel_codes[i].intf_class_sel != _FP_INVALID_INDEX) {
  44553            _FP_SEL_BMP_ADD(slice_sels->slice_sel[i],
  44554                            _bcmFieldGroupSliceIntfClassSel);
  44555          }
  44556          if (fg->sel_codes[i].intf_class_sel != _FP_INVALID_INDEX) {
  44557            _FP_SEL_BMP_ADD(slice_sels->slice_sel[i],
  44558                            _bcmFieldGroupSliceIntfClassSel);
  44559          }
  44560          if (fg->sel_codes[i].ingress_entity_sel != _FP_INVALID_INDEX) {
  44561            _FP_SEL_BMP_ADD(slice_sels->slice_sel[i],
  44562                            _bcmFieldGroupSliceIngressEntitySel);
  44563          }
  44564          if (fg->sel_codes[i].src_entity_sel != _FP_INVALID_INDEX) {
  44565            _FP_SEL_BMP_ADD(slice_sels->slice_sel[i],
  44566                            _bcmFieldGroupSliceSrcEntitySel);
  44567          }
  44568          if (fg->sel_codes[i].dst_fwd_entity_sel != _FP_INVALID_INDEX) {
  44569            _FP_SEL_BMP_ADD(slice_sels->slice_sel[i],
  44570                            _bcmFieldGroupSliceDstFwdEntitySel);
  44571          }
  44572          if (fg->sel_codes[i].fwd_field_sel != _FP_INVALID_INDEX) {
  44573            _FP_SEL_BMP_ADD(slice_sels->slice_sel[i],
  44574                            _bcmFieldGroupSliceFwdFieldSel);
  44575          }
  44576          if (fg->sel_codes[i].ttl_class_sel != _FP_INVALID_INDEX) {
  44577            _FP_SEL_BMP_ADD(slice_sels->slice_sel[i],
  44578                            _bcmFieldGroupSliceTtlClassSelect);
  44579          }
  44580          if (fg->sel_codes[i].tos_class_sel != _FP_INVALID_INDEX) {
  44581            _FP_SEL_BMP_ADD(slice_sels->slice_sel[i],
  44582                            _bcmFieldGroupSliceTosClassSelect);
  44583          }
  44584          if (fg->sel_codes[i].tcp_class_sel != _FP_INVALID_INDEX) {
  44585            _FP_SEL_BMP_ADD(slice_sels->slice_sel[i],
  44586                            _bcmFieldGroupSliceTcpClassSelect);
  44587          }
  44588          if (fg->sel_codes[i].loopback_type_sel != _FP_INVALID_INDEX) {
  44589            _FP_SEL_BMP_ADD(slice_sels->slice_sel[i],
  44590                            _bcmFieldGroupSliceLoopbackTypeSel);
  44591          }
  44592          if (fg->sel_codes[i].ip_header_sel != _FP_INVALID_INDEX) {
  44593            _FP_SEL_BMP_ADD(slice_sels->slice_sel[i],
  44594                            _bcmFieldGroupSliceIpHeaderSel);
  44595          }
  44596          if (fg->sel_codes[i].ip6_addr_sel != _FP_INVALID_INDEX) {
  44597            _FP_SEL_BMP_ADD(slice_sels->slice_sel[i],
  44598                            _bcmFieldGroupSliceIp6AddrSel);
  44599          }
  44600          if (fg->sel_codes[i].aux_tag_1_sel != _FP_INVALID_INDEX) {
  44601            _FP_SEL_BMP_ADD(slice_sels->slice_sel[i],
  44602                            _bcmFieldGroupSliceAuxTag1Sel);
  44603          }
  44604          if (fg->sel_codes[i].aux_tag_2_sel != _FP_INVALID_INDEX) {
  44605            _FP_SEL_BMP_ADD(slice_sels->slice_sel[i],
  44606                            _bcmFieldGroupSliceAuxTag2Sel);
  44607          }
  44608          if (fg->sel_codes[i].normalize_ip_sel != _FP_INVALID_INDEX) {
  44609            _FP_SEL_BMP_ADD(slice_sels->slice_sel[i],
  44610                            _bcmFieldGroupSliceNormalizeIpSel);
  44611          }
  44612          if (fg->sel_codes[i].normalize_mac_sel != _FP_INVALID_INDEX) {
  44613            _FP_SEL_BMP_ADD(slice_sels->slice_sel[i],
  44614                            _bcmFieldGroupSliceNormalizeMacSel);
  44615          }
  44616     }
  44617 
  44618     return BCM_E_NONE;
  44619 
  44620 }
  44621 
  44622 int _field_group_slice_sel_set(int unit, _field_group_t *fg,
  44623                                _field_slice_sel_info_t *slice_sels)
  44624 {
  44625     int i = 0;
  44626     int parts_count = 0;
  44627 
  44628     /* Retrieve the parts count for the given group */
  44629     BCM_IF_ERROR_RETURN(_bcm_field_entry_tcam_parts_count(unit, fg->stage_id,
  44630                                            fg->flags, &parts_count));
  44631 
  44632     for (i = 0; i < parts_count; i++) {
  44633 
  44634         if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i],
  44635                           _bcmFieldGroupSliceSrcClassSel) == 0)
  44636         && (_bcmFieldGroupSliceSrcClassSel < slice_sels->slice_sel_count)) {
  44637             fg->sel_codes[i].src_class_sel = _FP_INVALID_INDEX;
  44638         }
  44639         if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i],
  44640                           _bcmFieldGroupSliceDstClassSel) == 0)
  44641         && (_bcmFieldGroupSliceDstClassSel < slice_sels->slice_sel_count)) {
  44642             fg->sel_codes[i].dst_class_sel = _FP_INVALID_INDEX;
  44643         }
  44644         if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i],
  44645                           _bcmFieldGroupSliceIntfClassSel) == 0)
  44646         && (_bcmFieldGroupSliceIntfClassSel < slice_sels->slice_sel_count)) {
  44647             fg->sel_codes[i].intf_class_sel = _FP_INVALID_INDEX;
  44648         }
  44649         if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i],
  44650                           _bcmFieldGroupSliceIngressEntitySel) == 0)
  44651         && (_bcmFieldGroupSliceIngressEntitySel < slice_sels->slice_sel_count)) {
  44652             fg->sel_codes[i].ingress_entity_sel = _FP_INVALID_INDEX;
  44653         }
  44654         if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i],
  44655                           _bcmFieldGroupSliceSrcEntitySel) == 0)
  44656         && (_bcmFieldGroupSliceSrcEntitySel < slice_sels->slice_sel_count)) {
  44657             fg->sel_codes[i].src_entity_sel = _FP_INVALID_INDEX;
  44658         }
  44659         if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i],
  44660                           _bcmFieldGroupSliceDstFwdEntitySel) == 0)
  44661         && (_bcmFieldGroupSliceDstFwdEntitySel < slice_sels->slice_sel_count)) {
  44662             fg->sel_codes[i].dst_fwd_entity_sel = _FP_INVALID_INDEX;
  44663         }
  44664         if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i],
  44665                           _bcmFieldGroupSliceFwdFieldSel) == 0)
  44666         && (_bcmFieldGroupSliceFwdFieldSel < slice_sels->slice_sel_count)) {
  44667             fg->sel_codes[i].fwd_field_sel = _FP_INVALID_INDEX;
  44668         }
  44669         if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i],
  44670                           _bcmFieldGroupSliceTtlClassSelect) == 0)
  44671         && (_bcmFieldGroupSliceTtlClassSelect < slice_sels->slice_sel_count)) {
  44672             fg->sel_codes[i].ttl_class_sel = _FP_INVALID_INDEX;
  44673         }
  44674         if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i],
  44675                           _bcmFieldGroupSliceTosClassSelect) == 0)
  44676         && (_bcmFieldGroupSliceTosClassSelect < slice_sels->slice_sel_count)) {
  44677             fg->sel_codes[i].tos_class_sel = _FP_INVALID_INDEX;
  44678         }
  44679         if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i],
  44680                           _bcmFieldGroupSliceTcpClassSelect) == 0)
  44681         && (_bcmFieldGroupSliceTcpClassSelect < slice_sels->slice_sel_count)) {
  44682             fg->sel_codes[i].tcp_class_sel = _FP_INVALID_INDEX;
  44683         }
  44684         if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i],
  44685                           _bcmFieldGroupSliceLoopbackTypeSel) == 0)
  44686         && (_bcmFieldGroupSliceLoopbackTypeSel < slice_sels->slice_sel_count)) {
  44687             fg->sel_codes[i].loopback_type_sel = _FP_INVALID_INDEX;
  44688         }
  44689         if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i],
  44690                           _bcmFieldGroupSliceIpHeaderSel) == 0)
  44691         && (_bcmFieldGroupSliceIpHeaderSel < slice_sels->slice_sel_count)) {
  44692             fg->sel_codes[i].ip_header_sel = _FP_INVALID_INDEX;
  44693         }
  44694         if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i],
  44695                           _bcmFieldGroupSliceIp6AddrSel) == 0)
  44696         && (_bcmFieldGroupSliceIp6AddrSel < slice_sels->slice_sel_count)) {
  44697             fg->sel_codes[i].ip6_addr_sel = _FP_INVALID_INDEX;
  44698         }
  44699         if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i],
  44700                           _bcmFieldGroupSliceAuxTag1Sel) == 0)
  44701         && (_bcmFieldGroupSliceAuxTag1Sel < slice_sels->slice_sel_count)) {
  44702             fg->sel_codes[i].aux_tag_1_sel = _FP_INVALID_INDEX;
  44703         }
  44704         if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i],
  44705                           _bcmFieldGroupSliceAuxTag2Sel) == 0)
  44706         && (_bcmFieldGroupSliceAuxTag2Sel < slice_sels->slice_sel_count)) {
  44707             fg->sel_codes[i].aux_tag_2_sel = _FP_INVALID_INDEX;
  44708         }
  44709         if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i],
  44710                           _bcmFieldGroupSliceNormalizeIpSel) == 0)
  44711         && (_bcmFieldGroupSliceNormalizeIpSel < slice_sels->slice_sel_count)) {
  44712             fg->sel_codes[i].normalize_ip_sel = _FP_INVALID_INDEX;
  44713         }
  44714         if((_FP_SEL_BMP_TEST(slice_sels->slice_sel[i],
  44715                           _bcmFieldGroupSliceNormalizeMacSel) == 0)
  44716         && (_bcmFieldGroupSliceNormalizeMacSel < slice_sels->slice_sel_count)) {
  44717             fg->sel_codes[i].normalize_mac_sel = _FP_INVALID_INDEX;
  44718         }
  44719     }
  44720 
  44721     return BCM_E_NONE;
  44722 
  44723 }
  44724 
  44725 
  44726 /* Function: _field_group_slice_selectors_sync
  44727  *
  44728  * Purpose:
  44729  *        Sync the hint id associated with the group.
  44730  * Parameters:
  44731  *     unit      - (IN) BCM device number.
  44732  *     uint8     - (IN) Scache_ptr
  44733  * Returns:
  44734  *      BCM_E_XXXX.
  44735  */
  44736 int _field_group_slice_selectors_sync (int unit, uint8 *scache_ptr,
  44737                                        _field_stage_id_t stage_id)
  44738 {
  44739     _field_control_t    *fc;             /* Field control structure. */
  44740     _field_group_t      *fg;             /* Field group info.        */
  44741     _field_slice_sel_info_t slice_sels;  /* Field Group Slice selectors */
  44742     int idx = 0;
  44743     int parts_count = 0;
  44744 
  44745     if (scache_ptr == NULL) {
  44746         return BCM_E_PARAM;
  44747     }
  44748 
  44749     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  44750 
  44751     fg = fc->groups;
  44752     if (NULL == fg) {
  44753         return (BCM_E_NONE);
  44754     }
  44755 
  44756     for (; fg != NULL; fg = fg->next) {
  44757         if (stage_id == fg->stage_id) {
  44758             /* Retrieve the parts count for the given group */
  44759             BCM_IF_ERROR_RETURN(_bcm_field_entry_tcam_parts_count(unit,
  44760                                            fg->stage_id,
  44761                                            fg->flags, &parts_count));
  44762 
  44763             for (idx = 0; idx < parts_count; idx++) {
  44764                 slice_sels.slice_sel[idx].w = NULL;
  44765                 _FP_XGS3_ALLOC(slice_sels.slice_sel[idx].w,
  44766                                SHR_BITALLOCSIZE(_bcmFieldGroupSliceCount),
  44767                                "Group Slice Selectors Bitmap");
  44768                 if (slice_sels.slice_sel[idx].w == NULL) {
  44769                    int index;
  44770                    for (index = 0; index < idx; index++) {
  44771                       _FP_SEL_BMP_FREE(slice_sels.slice_sel[index]);
  44772                    }
  44773                    return BCM_E_MEMORY;
  44774                 }
  44775             }
  44776             _field_group_slice_sel_get(unit, fg,
  44777                                        &slice_sels);
  44778             slice_sels.gid = fg->gid;
  44779             slice_sels.slice_sel_count = _bcmFieldGroupSliceCount;
  44780 
  44781             LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
  44782             "%s(): Writing gid[%d] @ byte %d.\n\r"), __func__,
  44783             slice_sels.gid, fc->scache_pos));
  44784             sal_memcpy (scache_ptr, &(slice_sels.gid),
  44785                     sizeof(bcm_field_group_t));
  44786             fc->scache_pos += sizeof (bcm_field_group_t);
  44787             scache_ptr += sizeof (bcm_field_group_t);
  44788 
  44789             LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
  44790             "%s(): Writing slice_sel_count[%d] @ byte %d.\n\r"), __func__,
  44791             slice_sels.slice_sel_count, fc->scache_pos));
  44792             sal_memcpy (scache_ptr, &(slice_sels.slice_sel_count),
  44793                     sizeof(slice_sels.slice_sel_count));
  44794             fc->scache_pos += sizeof (slice_sels.slice_sel_count);
  44795             scache_ptr += sizeof (slice_sels.slice_sel_count);
  44796 
  44797 
  44798             for (idx = 0; idx < parts_count; idx++) {
  44799                 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
  44800                   "%s(): Writing selector bitmap[0x%x] group:%d part:%d"
  44801                   " @ byte %d.\n\r"), __func__,
  44802                  slice_sels.slice_sel[idx].w[0], fg->gid, idx, fc->scache_pos));
  44803 
  44804                 sal_memcpy (scache_ptr, slice_sels.slice_sel[idx].w,
  44805                         sizeof(_field_selector_bmp_t));
  44806                 fc->scache_pos += sizeof (_field_selector_bmp_t);
  44807                 scache_ptr += sizeof (_field_selector_bmp_t);
  44808 
  44809                 _FP_SEL_BMP_FREE(slice_sels.slice_sel[idx]);
  44810             }
  44811         }
  44812     }
  44813 
  44814     return BCM_E_NONE;
  44815 }
  44816 
  44817 /* Function: _field_group_slice_selectors_recover
  44818  *
  44819  * Purpose:
  44820  *        Sync the hint id associated with the group.
  44821  * Parameters:
  44822  *     unit      - (IN) BCM device number.
  44823  *     uint8     - (IN) Scache_ptr
  44824  * Returns:
  44825  *      BCM_E_XXXX.
  44826  */
  44827 int _field_group_slice_selectors_recover (int unit, uint8 *scache_ptr,
  44828                                           _field_stage_id_t stage_id)
  44829 {
  44830     _field_control_t    *fc;             /* Field control structure. */
  44831     _field_group_t      *fg;             /* Field group info.        */
  44832     _field_slice_sel_info_t slice_sels;  /* Field Group Slice selectors */
  44833     int idx = 0, grp_idx = 0;
  44834     int group_count = 0;
  44835     int rv = 0;
  44836     int parts_count = 0;
  44837 
  44838     if (scache_ptr == NULL) {
  44839         return BCM_E_PARAM;
  44840     }
  44841 
  44842     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  44843 
  44844     fg = fc->groups;
  44845     if (NULL == fg) {
  44846         return (BCM_E_NONE);
  44847     }
  44848 
  44849     for (; fg != NULL; fg = fg->next) {
  44850         if (stage_id == fg->stage_id) {
  44851             group_count++;
  44852         }
  44853     }
  44854 
  44855     if (group_count == 0) {
  44856         return (BCM_E_NONE);
  44857     }
  44858 
  44859     fg = NULL;
  44860     for (grp_idx = 0; grp_idx < group_count; grp_idx++) {
  44861         sal_memcpy (&(slice_sels.gid), scache_ptr,
  44862                     sizeof (bcm_field_group_t));
  44863         fc->scache_pos += sizeof (bcm_field_group_t);
  44864         scache_ptr += sizeof (bcm_field_group_t);
  44865 
  44866         LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
  44867             "%s(): Recovering gid[%d] @ byte %d.\n\r"), __func__,
  44868             slice_sels.gid, (fc->scache_pos - 4)));
  44869 
  44870         sal_memcpy (&(slice_sels.slice_sel_count), scache_ptr,
  44871                     sizeof (slice_sels.slice_sel_count));
  44872         fc->scache_pos += sizeof (slice_sels.slice_sel_count);
  44873         scache_ptr += sizeof (slice_sels.slice_sel_count);
  44874 
  44875         LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
  44876             "%s(): Recovering slice_sel_count[%d] @ byte %d.\n\r"), __func__,
  44877             slice_sels.slice_sel_count, (fc->scache_pos - 1)));
  44878 
  44879         rv = _field_group_get(unit, slice_sels.gid, &fg);
  44880         if (BCM_FAILURE(rv)) {
  44881             return rv;
  44882         }
  44883 
  44884         /* Retrieve the parts count for the given group */
  44885         rv = _bcm_field_entry_tcam_parts_count(unit,
  44886                                            fg->stage_id,
  44887                                            fg->flags, &parts_count);
  44888         if (BCM_FAILURE(rv)) {
  44889             return rv;
  44890         }
  44891 
  44892         sal_memset(slice_sels.slice_sel, 0x0,
  44893                    sizeof(_field_selector_bmp_t) * _FP_MAX_ENTRY_WIDTH);
  44894 
  44895         for (idx = 0; idx < parts_count; idx++) {
  44896             slice_sels.slice_sel[idx].w = NULL;
  44897             _FP_XGS3_ALLOC(slice_sels.slice_sel[idx].w,
  44898                            SHR_BITALLOCSIZE(slice_sels.slice_sel_count),
  44899                            "Group Slice Selectors Bitmap");
  44900             if (slice_sels.slice_sel[idx].w == NULL) {
  44901                rv = BCM_E_MEMORY;
  44902                goto cleanup;
  44903             }
  44904 
  44905             sal_memcpy (slice_sels.slice_sel[idx].w, scache_ptr,
  44906                     sizeof(_field_selector_bmp_t));
  44907             fc->scache_pos += sizeof (_field_selector_bmp_t);
  44908             scache_ptr += sizeof (_field_selector_bmp_t);
  44909 
  44910             LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
  44911             "%s(): Recovering selectors bitmap[0x%x] for group:%d part:%d"
  44912             " @ byte %d.\n\r"), __func__,
  44913             slice_sels.slice_sel[idx].w[0], fg->gid, idx,
  44914             (fc->scache_pos - 4)));
  44915         }
  44916 
  44917         _field_group_slice_sel_set(unit, fg,
  44918                                    &slice_sels);
  44919         for (idx = 0; idx < parts_count; idx++) {
  44920             if (slice_sels.slice_sel[idx].w != NULL) {
  44921                 _FP_SEL_BMP_FREE(slice_sels.slice_sel[idx]);
  44922                 slice_sels.slice_sel[idx].w = NULL;
  44923             }
  44924         }
  44925     }
  44926 
  44927 cleanup:
  44928     for (idx = 0; idx < _FP_MAX_ENTRY_WIDTH; idx++) {
  44929          if (slice_sels.slice_sel[idx].w != NULL) {
  44930              _FP_SEL_BMP_FREE(slice_sels.slice_sel[idx]);
  44931          }
  44932     }
  44933     return rv;
  44934 }
  44935 
  44936 
  44937 #endif
  44938 
  44939 
  44940 
  44941 /*
  44942  * Function: _field_dump_brief
  44943  *
  44944  * Purpose:
  44945  *     Show current S/W state if compiled in debug mode without entries.
  44946  *
  44947  * Parameters:
  44948  *     unit - BCM device number
  44949  *     pfx - Character string to prefix output lines
  44950  *
  44951  * Returns:
  44952  *     BCM_E_XXX.
  44953  */
  44954 
  44955 int
  44956 _field_dump_brief(int unit, const char *pfx)
  44957 {
  44958     int                 idx;
  44959     _field_group_t      *fg;
  44960     _field_range_t      *fr;
  44961     _field_stage_t      *stage_fc;
  44962     _field_control_t    *fc;
  44963     int                  rv = 0;
  44964     int                  entry_ratio;  /* Invalid entries ratio. */
  44965 
  44966 
  44967     FP_LOCK(unit);
  44968     rv = _field_control_get(unit, &fc);
  44969     if (BCM_FAILURE(rv)) {
  44970         FP_UNLOCK(unit);
  44971         return rv;
  44972     }
  44973 
  44974     stage_fc = fc->stages;
  44975 
  44976 
  44977     LOG_CLI((BSL_META_U(unit,
  44978                         "%s:\tunit %d:\n"), pfx, unit));
  44979 
  44980     while(stage_fc) {
  44981 
  44982         entry_ratio = (stage_fc->flags & _FP_STAGE_QUARTER_SLICE) ? 4:
  44983             ((stage_fc->flags & _FP_STAGE_HALF_SLICE) ? 2 : 1);
  44984 
  44985         switch (stage_fc->stage_id) {
  44986             case _BCM_FIELD_STAGE_INGRESS:
  44987               LOG_CLI((BSL_META_U(unit,
  44988                                   "PIPELINE STAGE INGRESS\n")));
  44989               LOG_CLI((BSL_META_U(unit,
  44990                               "%s:\t      :tcam_sz=%d(%#x),"),
  44991                           pfx, stage_fc->tcam_sz/entry_ratio,
  44992                           stage_fc->tcam_sz/entry_ratio));
  44993               break;
  44994 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  44995           case _BCM_FIELD_STAGE_LOOKUP:
  44996               LOG_CLI((BSL_META_U(unit,
  44997                                   "PIPELINE STAGE LOOKUP\n")));
  44998               LOG_CLI((BSL_META_U(unit,
  44999                               "%s:\t      :tcam_sz=%d(%#x),"),
  45000                           pfx, stage_fc->tcam_sz/entry_ratio,
  45001                           stage_fc->tcam_sz/entry_ratio));
  45002               break;
  45003           case _BCM_FIELD_STAGE_EGRESS:
  45004               LOG_CLI((BSL_META_U(unit,
  45005                                   "PIPELINE STAGE EGRESS\n")));
  45006               LOG_CLI((BSL_META_U(unit,
  45007                               "%s:\t      :tcam_sz=%d(%#x),"),
  45008                           pfx, stage_fc->tcam_sz/entry_ratio,
  45009                           stage_fc->tcam_sz/entry_ratio));
  45010               break;
  45011 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  45012           case _BCM_FIELD_STAGE_EXTERNAL:
  45013               LOG_CLI((BSL_META_U(unit,
  45014                                   "PIPELINE STAGE EXTERNAL\n")));
  45015               LOG_CLI((BSL_META_U(unit,
  45016                               "%s:\t      :tcam_sz=%d(%#x),"),
  45017                           pfx, stage_fc->tcam_sz, stage_fc->tcam_sz));
  45018               break;
  45019           default:
  45020               break;
  45021         }
  45022 
  45023         LOG_CLI((BSL_META_U(unit,
  45024                             " tcam_slices=%d,"), stage_fc->tcam_slices));
  45025         LOG_CLI((BSL_META_U(unit,
  45026                             " tcam_ext_numb=%d,"), fc->tcam_ext_numb));
  45027         LOG_CLI((BSL_META_U(unit,
  45028                             "\n")));
  45029 
  45030         /* Display any range checkers defined. */
  45031         if ((_BCM_FIELD_STAGE_INGRESS  == stage_fc->stage_id) ||
  45032             (_BCM_FIELD_STAGE_EXTERNAL == stage_fc->stage_id)) {
  45033             for (fr = stage_fc->ranges; fr != NULL; fr = fr->next) {
  45034                 _field_range_dump(pfx, fr);
  45035             }
  45036         }
  45037         stage_fc = stage_fc->next;
  45038     }
  45039     /* Print the any defined UDFs. */
  45040     for (idx = 0; idx < BCM_FIELD_USER_NUM_UDFS; idx++) {
  45041         if (fc->udf[idx].valid) {
  45042         LOG_CLI((BSL_META_U(unit,
  45043                             "%s:\tudf %d: use_count=%d, udf_num=%s, user_num=%d\n"),
  45044                  pfx, idx, fc->udf[idx].use_count,
  45045                  _field_qual_name(fc->udf[idx].udf_num + _bcmFieldQualifyData0),
  45046                  fc->udf[idx].user_num));
  45047         }
  45048     }
  45049 
  45050     /* Print the groups, along with their entries. */
  45051     for (fg = fc->groups; fg != NULL ; fg = fg->next) {
  45052 #if defined(BCM_TOMAHAWK_SUPPORT)
  45053         if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  45054             (_BCM_FIELD_STAGE_CLASS == fg->stage_id)) {
  45055             /* Don't dump Class Group in 'fp show brief' command */
  45056             continue;
  45057         }
  45058 #endif /* BCM_TOMAHAWK_SUPPORT */
  45059         _field_group_dump_brief(unit, fg->gid);
  45060     }
  45061 
  45062     if (soc_feature(unit, soc_feature_epc_linkflap_recover)) {
  45063 #if defined(BCM_TRX_SUPPORT)
  45064         if (SOC_IS_TRX(unit)) {
  45065             _bcm_trx_field_egr_ports_recovery_print (unit);
  45066         }
  45067 #endif
  45068     }
  45069 
  45070     FP_UNLOCK(unit);
  45071     return (BCM_E_NONE);
  45072 }
  45073 
  45074 /*
  45075  * Function: _field_dump_class
  45076  * Purpose:
  45077  *  Show current S/W state for class.
  45078  * Parameters:
  45079  *  unit - BCM device number
  45080  *  pfx - Character string to prefix output lines.
  45081  *  flag - Flag to control class display.
  45082  * Returns:
  45083  *  BCM_E_XXX.
  45084  * Notes:
  45085  *  If flag is -1 it dumps class group and entries as well.
  45086  *  Otherwise it dumps brief class table summary.
  45087  */
  45088 int
  45089 _field_dump_class(int unit, const char *pfx, int flag)
  45090 {
  45091      int rv = BCM_E_NONE;
  45092 #if defined(BCM_TOMAHAWK_SUPPORT)
  45093     _field_group_t      *fg = NULL;
  45094     _field_stage_t      *stage_fc = NULL;
  45095     _field_control_t    *fc = NULL;
  45096 
  45097     /* Retreive Field Control. */
  45098 
  45099     FP_LOCK(unit);
  45100     rv = _field_control_get(unit, &fc);
  45101     if (BCM_FAILURE(rv)) {
  45102         FP_UNLOCK(unit);
  45103         return rv;
  45104     }
  45105 
  45106     stage_fc = fc->stages;
  45107 
  45108     LOG_CLI((BSL_META_U(unit,
  45109              "%s:\tunit %d:"), pfx, unit));
  45110 
  45111     /* Retreive Field Stage Class Control */
  45112     rv = _field_stage_control_get(unit, _BCM_FIELD_STAGE_CLASS, &stage_fc);
  45113     if (BCM_FAILURE(rv)) {
  45114         FP_UNLOCK(unit);
  45115         return (rv);
  45116     }
  45117 
  45118     LOG_CLI((BSL_META_U(unit,
  45119                     "PIPELINE STAGE CLASS\n")));
  45120     _bcm_field_th_class_stage_dump(unit,stage_fc);
  45121 
  45122     /* Dump groups and entries if flag is -1. */
  45123     if (flag == -1) {
  45124         /* Print the groups, along with their entries. */
  45125         for (fg = fc->groups; fg != NULL ; fg = fg->next) {
  45126             if (fg->stage_id == _BCM_FIELD_STAGE_CLASS) {
  45127                 /* Dump Group only if it is stage class */
  45128                 _bcm_esw_field_group_dump(unit, fg->gid, -1);
  45129             }
  45130         }
  45131     }
  45132 
  45133     FP_UNLOCK(unit);
  45134 #endif /* BCM_TOMAHAWK_SUPPORT */
  45135     return (rv);
  45136 }
  45137 
  45138 
  45139 /*
  45140  * Function: _field_group_dump_brief
  45141  *
  45142  * Purpose:
  45143  *     Show contents of a field group without the entries.
  45144  *
  45145  * Parameters:
  45146  *     unit  - BCM device number
  45147  *     group - Field group to dump
  45148  *
  45149  * Returns:
  45150  *     Nothing.
  45151  */
  45152 int
  45153 _field_group_dump_brief(int unit, bcm_field_group_t group)
  45154 {
  45155     _field_stage_t      *stage_fc;
  45156     _field_group_t      *fg;
  45157     int                 enable = 0;
  45158     int                 parts_count = 0;
  45159     int                 idx;
  45160     /* buffer big enough to write out pbmp
  45161      * as characters + 0x + terminating NULL */
  45162     char                buf[BCM_PBMP_PORT_MAX + 3];
  45163     int                 rv;
  45164 
  45165 
  45166     FP_LOCK(unit);
  45167 
  45168     rv = _field_group_get(unit, group, &fg);
  45169     if (BCM_FAILURE(rv)) {
  45170         FP_UNLOCK(unit);
  45171         return (rv);
  45172     }
  45173 
  45174 #if defined(BCM_TOMAHAWK_SUPPORT)
  45175     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  45176         (_BCM_FIELD_STAGE_CLASS == fg->stage_id)) {
  45177         rv = _bcm_field_th_class_group_brief_dump(unit,fg);
  45178         FP_UNLOCK(unit);
  45179         return (rv);
  45180     }
  45181 #endif /* BCM_TOMAHAWK_SUPPORT */
  45182 
  45183     rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc);
  45184     if (BCM_FAILURE(rv)) {
  45185         FP_UNLOCK(unit);
  45186         return (rv);
  45187     }
  45188 
  45189     rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
  45190                                             fg->flags, &parts_count);
  45191     if (BCM_FAILURE(rv)) {
  45192         FP_UNLOCK(unit);
  45193         return (rv);
  45194     }
  45195 
  45196     if ((fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) &&
  45197         (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE)) {
  45198         LOG_CLI((BSL_META_U(unit,
  45199                             "Quad wide intra-slice group, ")));
  45200     } else if ((fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) &&
  45201                (fg->flags & _FP_GROUP_SPAN_SINGLE_SLICE)) {
  45202         if (!((soc_feature(unit, soc_feature_ifp_no_narrow_mode_support) ||
  45203                soc_feature(unit, soc_feature_hx5_style_ifp_no_narrow_mode_support)) &&
  45204                (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id))) {
  45205               LOG_CLI((BSL_META_U(unit,
  45206                             "Intra-slice double wide group, ")));
  45207         }
  45208     }
  45209     LOG_CLI((BSL_META_U(unit,
  45210                         "GID %10d: gid=0x%x, mode=%s, stage=%s "), group,
  45211              fg->gid, _field_group_mode_name(unit, fg->flags, stage_fc),
  45212              _field_stage_name(stage_fc)));
  45213     bcm_esw_field_group_enable_get(unit, group, &enable);
  45214     if (enable) {
  45215         LOG_CLI((BSL_META_U(unit,
  45216                             "lookup=Enabled, ")));
  45217     } else {
  45218         LOG_CLI((BSL_META_U(unit,
  45219                             "lookup=Disabled, ")));
  45220     }
  45221 
  45222     LOG_CLI((BSL_META_U(unit,
  45223                         "ActionResId={%d}, "), fg->action_res_id));
  45224     LOG_VERBOSE(BSL_LS_BCM_FP,
  45225                 (BSL_META_U(unit,
  45226                         "VMAP={%d %d %d}, "),
  45227                  fg->vmap_group[0], fg->vmap_group[1], fg->vmap_group[2]));
  45228 
  45229     LOG_CLI((BSL_META_U(unit,
  45230                         "pbmp={%s}\n"), SOC_PBMP_FMT(fg->pbmp, buf)));
  45231 
  45232     _field_qset_dump("         qset=", fg->qset, ",\n");
  45233 
  45234 #if defined(BCM_TOMAHAWK_SUPPORT)
  45235     if (soc_feature(unit, soc_feature_field_preselector_support) &&
  45236         (fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT)) {
  45237        uint8              not_first = 0;
  45238 
  45239        LOG_CLI((BSL_META_U(unit,
  45240                     "         preselectors={")));
  45241        for (idx = 0; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) {
  45242            if (fg->presel_ent_arr[idx] != NULL) {
  45243               if (not_first) {
  45244                  LOG_CLI((BSL_META_U(unit, ", ")));
  45245               }
  45246               LOG_CLI((BSL_META_U(unit, "%d"), fg->presel_ent_arr[idx]->presel_id));
  45247               not_first = 1;
  45248            }
  45249        }
  45250        LOG_CLI((BSL_META_U(unit, "}\n\r")));
  45251     }
  45252 #endif /* BCM_TOMAHAWK_SUPPORT */
  45253 
  45254     if (fg->hintid != 0) {
  45255         LOG_CLI((BSL_META_U(unit,
  45256                         "         HintId=%d\n"), fg->hintid));
  45257     }
  45258 
  45259     for (idx = 0; idx < parts_count; idx++) {
  45260         sal_sprintf(buf, "         selcodes[%d]=\n", idx);
  45261         _field_selcode_dump(unit, buf, fg->sel_codes + idx,  ", ", fg->stage_id);
  45262         _field_qual_list_dump(" ",fg, idx,",\n");
  45263 
  45264     }
  45265 
  45266     LOG_CLI((BSL_META_U(unit,
  45267                         "\n")));
  45268 
  45269     /* Print the primary slice data. */
  45270     LOG_CLI((BSL_META_U(unit,
  45271                         "         slice_pri= %d "), fg->priority));
  45272     _field_slice_dump(unit, "   ", fg, &fg->slices[0], "\n");
  45273 
  45274     /* Print the secondary slice data. */
  45275     if ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) ||
  45276         (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE)) {
  45277         LOG_CLI((BSL_META_U(unit,"         slice_sec = {slice_number=%d}\n"),
  45278                             fg->slices[1].slice_number));
  45279     }
  45280 
  45281     /* Print the tertiary slice data. */
  45282     if (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) {
  45283         LOG_CLI((BSL_META_U(unit,"         slice_ter = {slice_number=%d}\n"),
  45284                             fg->slices[2].slice_number));
  45285     }
  45286 
  45287 #if defined(BCM_TOMAHAWK_SUPPORT) /* BCM_TOMAHAWK_SUPPORT */
  45288     if (soc_feature(unit, soc_feature_field_multi_pipe_support)
  45289         && ((_BCM_FIELD_STAGE_INGRESS == fg->stage_id) ||
  45290             (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id) ||
  45291             (_BCM_FIELD_STAGE_FLOWTRACKER == fg->stage_id))) {
  45292         /* Get TH IFP group's status. */
  45293         rv = _bcm_field_th_group_status_calc(unit, fg);
  45294     } else
  45295 #endif /* !BCM_TOMAHAWK_SUPPORT */
  45296     {
  45297         /* Update the numbers of free entries, meters and counters. */
  45298         rv = _bcm_field_group_status_calc(unit, fg);
  45299     }
  45300 
  45301     /* Print group used resources status */
  45302     if (BCM_SUCCESS(rv)) {
  45303         LOG_CLI((BSL_META_U(unit,
  45304                             "         group_status=")));
  45305         _field_group_status_dump(&fg->group_status);
  45306         LOG_CLI((BSL_META_U(unit,
  45307                             "\n")));
  45308     }
  45309 
  45310     FP_UNLOCK(unit);
  45311     return (BCM_E_NONE);
  45312 }
  45313 
  45314 /*
  45315  * Function: _bcm_field_presel_dump
  45316  *
  45317  * Purpose:
  45318  *     Show current S/W state for Preselectors
  45319  *
  45320  * Parameters:
  45321  *     unit - BCM device number
  45322  *     pfx - Character string to prefix output lines
  45323  *
  45324  * Returns:
  45325  *     BCM_E_XXX.
  45326  */
  45327 
  45328 int
  45329 _bcm_field_presel_dump(int unit, bcm_field_presel_t presel_id, int stage)
  45330 {
  45331      int rv = BCM_E_UNAVAIL;
  45332 #if defined(BCM_TOMAHAWK_SUPPORT)
  45333     _field_action_t           *fa;
  45334     _field_presel_entry_t     *f_presel;
  45335     bcm_field_presel_t        presel;
  45336     _field_control_t          *fc;
  45337 
  45338     /* Preselector feature check */
  45339     if (!soc_feature(unit, soc_feature_field_preselector_support)) {
  45340        return BCM_E_UNAVAIL;
  45341     }
  45342 
  45343     FP_LOCK(unit);
  45344     rv = _field_control_get(unit, &fc);
  45345     if (BCM_FAILURE(rv)) {
  45346         FP_UNLOCK(unit);
  45347         return rv;
  45348     }
  45349 
  45350     for (presel = 0; presel < BCM_FIELD_PRESEL_SEL_MAX; presel++) {
  45351 
  45352        if ((presel_id != -1) && (presel != presel_id)) {
  45353           continue;
  45354        }
  45355 
  45356 #if defined (BCM_TOMAHAWK3_SUPPORT)
  45357        if ((soc_feature(unit, soc_feature_sw_mmu_flush_rqe_operation)) &&
  45358             (presel == _FP_PRESEL_INTERNAL_RESERVED_ID)) {
  45359              continue;
  45360        }
  45361 #endif
  45362 
  45363         /* Check if presel ID present in presel_set */
  45364        if (!BCM_FIELD_PRESEL_TEST(fc->presel_info->presel_set, presel)) {
  45365           continue;
  45366        }
  45367 
  45368        /* Retrieve the Presel Entry */
  45369        rv = _bcm_field_presel_entry_get(unit, presel, &f_presel);
  45370        if (BCM_FAILURE(rv)) {
  45371            LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
  45372               "ERROR: Couldn't retrieve the Preselector Entry for the given"
  45373               " Presel ID[%d].\n\r"), presel));
  45374            FP_UNLOCK(unit);
  45375            return rv;
  45376        }
  45377 
  45378 
  45379        if (BCM_FIELD_QSET_TEST(f_presel->p_qset, bcmFieldQualifyStage)) {
  45380            if (BCM_FIELD_QSET_TEST(f_presel->p_qset, bcmFieldQualifyStageIngress)) {
  45381                if ((-1 != stage) &&
  45382                    (_BCM_FIELD_STAGE_INGRESS != stage)) {
  45383                    continue;
  45384                }
  45385                LOG_CLI((BSL_META_U(unit,
  45386                                "PRESEL ID:  %d, eid=0x%x, priority=%d, hw_index=%d\n\r"), presel,
  45387                            (presel | BCM_FIELD_QUALIFY_PRESEL), f_presel->priority,
  45388                            f_presel->hw_index));
  45389                LOG_CLI((BSL_META_U(unit, "\tStage:%s"), "Ingress, "));
  45390            } else if(BCM_FIELD_QSET_TEST(f_presel->p_qset, bcmFieldQualifyStageIngressExactMatch)) {
  45391                if ((-1 != stage) &&
  45392                        (_BCM_FIELD_STAGE_EXACTMATCH != stage)) {
  45393                    continue;
  45394                }
  45395                LOG_CLI((BSL_META_U(unit,
  45396                                "PRESEL ID:  %d, eid=0x%x, priority=%d, hw_index=%d\n\r"), presel,
  45397                            (presel | BCM_FIELD_QUALIFY_PRESEL), f_presel->priority,
  45398                            f_presel->hw_index));
  45399                LOG_CLI((BSL_META_U(unit, "\tStage:%s"), "IngressExactMatch, "));
  45400            } else { /* Stage Flowtracker */
  45401                if ((-1 != stage) &&
  45402                        (_BCM_FIELD_STAGE_FLOWTRACKER != stage)) {
  45403                     continue;
  45404                }
  45405                LOG_CLI((BSL_META_U(unit,
  45406                                "PRESEL ID:  %d, eid=0x%x, priority=%d, hw_index=%d\n\r"), presel,
  45407                            (presel | BCM_FIELD_QUALIFY_PRESEL), f_presel->priority,
  45408                            f_presel->hw_index));
  45409                LOG_CLI((BSL_META_U(unit, "\tStage:%s"), "Flowtracker, "));
  45410            }
  45411 
  45412            LOG_CLI((BSL_META_U(unit, " Status:")));
  45413            if (!(f_presel->flags & _FP_ENTRY_INSTALLED)) {
  45414               LOG_CLI((BSL_META_U(unit,
  45415                               "Not installed")));
  45416            } else {
  45417               LOG_CLI((BSL_META_U(unit,
  45418                               "Installed")));
  45419 
  45420               if (!(f_presel->flags & _FP_ENTRY_ENABLED)) {
  45421                  LOG_CLI((BSL_META_U(unit,
  45422                                   ", Disabled")));
  45423               } else {
  45424                  LOG_CLI((BSL_META_U(unit,
  45425                                 ", Enabled")));
  45426               }
  45427 
  45428               if (f_presel->flags & _FP_ENTRY_DIRTY) {
  45429                   LOG_CLI((BSL_META_U(unit,
  45430                                  ", Dirty")));
  45431               }
  45432            }
  45433            LOG_CLI((BSL_META_U(unit, "\n\r")));
  45434        } else {
  45435            LOG_CLI((BSL_META_U(unit,
  45436                               "\tNot Configured\n\r")));
  45437            LOG_CLI((BSL_META_U(unit, "\n\r")));
  45438            continue;
  45439        }
  45440 
  45441        _field_qset_dump("\tQualifiers=", f_presel->p_qset, ",\n\r");
  45442 
  45443        _bcm_field_presel_qualifiers_dump(unit, presel);
  45444 
  45445        LOG_CLI((BSL_META_U(unit, "\n\r")));
  45446        fa = f_presel->actions;
  45447        while (fa != NULL) {
  45448             LOG_CLI((BSL_META_U(unit,
  45449                                 "\taction=")));
  45450             _field_action_dump (fa);
  45451             LOG_CLI((BSL_META_U(unit,
  45452                                 "\n\r")));
  45453             fa = fa->next;
  45454        }
  45455 
  45456        if (presel_id != -1) {
  45457           break;
  45458        }
  45459        LOG_CLI((BSL_META_U(unit, "\n\r")));
  45460     }
  45461 
  45462     FP_UNLOCK(unit);
  45463     rv = BCM_E_NONE;
  45464 #endif /* BCM_TOMAHAWK_SUPPORT */
  45465     return (rv);
  45466 }
  45467 
  45468 /*
  45469  * Function: _field_calc_cache_size
  45470  *
  45471  * Purpose:
  45472  *     Show Scache size for FP for current configuration
  45473  *
  45474  * Parameters:
  45475  *     unit - BCM device number
  45476  *
  45477  * Returns:
  45478  *     BCM_E_XXX.
  45479  */
  45480 
  45481 int
  45482 _field_calc_cache_size(int unit)
  45483 {
  45484 
  45485 #ifdef BCM_WARM_BOOT_SUPPORT
  45486 #ifdef BCM_TOMAHAWK_SUPPORT
  45487 
  45488    _field_control_t *fc = NULL;       /* Field control Structure */
  45489    _field_stage_t *stage_fc = NULL;   /* Field Stage Structure */
  45490    uint32 final_pos = 0;              /* Final Scache size */
  45491 
  45492    BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  45493 
  45494    fc->scache_pos = 0;
  45495    wb_write_disable = 1;
  45496 
  45497    BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
  45498                                                 _BCM_FIELD_STAGE_INGRESS,
  45499                                                 &stage_fc));
  45500 
  45501    BCM_IF_ERROR_RETURN(_bcm_field_th_stage_ingress_sync(unit,
  45502                                                         stage_fc));
  45503    /* End Header */
  45504    fc->scache_pos = fc->scache_pos + 4;
  45505 
  45506    BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
  45507                                                 _BCM_FIELD_STAGE_CLASS,
  45508                                                 &stage_fc));
  45509    /* Start Header */
  45510    fc->scache_pos = fc->scache_pos + 5;
  45511 
  45512    BCM_IF_ERROR_RETURN(_bcm_field_th_stage_class_sync(unit, fc, stage_fc));
  45513 
  45514    /* End Header */
  45515    fc->scache_pos = fc->scache_pos + 5;
  45516 
  45517    BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
  45518                                                 _BCM_FIELD_STAGE_EXACTMATCH,
  45519                                                 &stage_fc));
  45520 
  45521    BCM_IF_ERROR_RETURN(_bcm_field_th_stage_em_sync(unit, fc, stage_fc));
  45522 
  45523    /* End Header */
  45524    fc->scache_pos = fc->scache_pos + 5;
  45525 
  45526 #if defined(BCM_HELIX5_SUPPORT)
  45527    BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
  45528                                                 _BCM_FIELD_STAGE_FLOWTRACKER,
  45529                                                 &stage_fc));
  45530 
  45531    BCM_IF_ERROR_RETURN(_bcm_field_stage_ft_sync(unit, fc, stage_fc));
  45532 
  45533    fc->scache_pos = fc->scache_pos + 5;
  45534 #endif
  45535 
  45536                                /* size for IFP */
  45537    final_pos = (((fc->scache_pos + 1023) / 1024) * 1024)
  45538                + (294 * 1024)  /* Size for EFP,VFP partition 0 */
  45539                + (20 *1024);   /* Size for EFP,VFP partition 1 */
  45540    /*
  45541     * Scache size is increased to sync the bitmap of slice
  45542     * indexes that is used to store the slice indexes of the
  45543     * disabled entries.
  45544     * This is added from WB version BCM_FIELD_WB_VERSION_1_27
  45545     * The size is to accomodate both efp and vfp assuming each
  45546     * stage have 1024 slice indexes at max.
  45547     * so size is bitmap will be
  45548     * ((1024/32)bits * 4)bytes*2(efp and vfp)*_FP_MAX_NUM_PIPES
  45549     * (((1024/32)*4*2 * _FP_MAX_NUM_PIPES))
  45550     */
  45551    final_pos += ((1024/32)*4 *2*_FP_MAX_NUM_PIPES);
  45552    LOG_CLI((BSL_META("Scache size for Field Module : %d \n"), final_pos));
  45553    wb_write_disable = 0;
  45554    fc->scache_pos = 0;
  45555 
  45556 #endif /* BCM_WARM_BOOT_SUPPORT */
  45557 #endif /* BCM_TOMAHAWK_SUPPORT */
  45558 
  45559    return BCM_E_NONE;
  45560 }
  45561 
  45562 #ifdef BCM_WARM_BOOT_SUPPORT
  45563 
  45564 /*
  45565  * Function: _field_scache_pointer_realloc
  45566  *
  45567  * Purpose:
  45568  *     Initialize field component scache pointers and scache sizes for
  45569  *     multiple partitions.
  45570  * Parameters:
  45571  *     unit - BCM device number
  45572  *     fc   - Field Control Structure
  45573  *
  45574  * Returns:
  45575  *     BCM_E_XXX.
  45576  */
  45577 
  45578 
  45579 static int
  45580 _field_scache_pointer_realloc(int unit, _field_control_t  *fc)
  45581 {
  45582     int               stable_size;
  45583     int               rv = BCM_E_NONE;
  45584     uint32            alloc_get;
  45585     soc_scache_handle_t handle;
  45586 
  45587     if ((NULL != fc->scache_ptr[_FIELD_SCACHE_PART_0]) ||
  45588         (NULL != fc->scache_ptr[_FIELD_SCACHE_PART_1])) {
  45589 
  45590         SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
  45591         SOC_SCACHE_HANDLE_SET(handle, unit, BCM_MODULE_FIELD,
  45592                               _FIELD_SCACHE_PART_0);
  45593         if ((stable_size > 0) && !SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) {
  45594             if (SOC_IS_TRX(unit)) {
  45595 
  45596                 fc->scache_size[_FIELD_SCACHE_PART_0] = 294 * 1024;
  45597                 /* Taking all average number into account
  45598                  * (Note:S-Slices , P- Ports and Q - Qualifiers)
  45599                  * IFP - 16S * 48P * 25Q
  45600                  * VFP and EFP - 16S * 25Q
  45601                  */
  45602                 fc->scache_size[_FIELD_SCACHE_PART_1] = 20 * 1024;
  45603 
  45604                 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_15) {
  45605                     /*
  45606                      * OAM => 70 * 1024 ((7 bytes * 8K IFP entries) + (7 bytes * 2K EFP entries))
  45607                      * Policer L1 => 20 * 1024 (4 bytes * 20 slices * 256 entries.)
  45608                      * No Param Actions => 40 * 1024 (4 bytes * 20 slices * 512 entries.)
  45609                      * Slice/Secondary Selectors => 5 * 1024 (2 bytes * 128 ports/groups * 20 Slices.)
  45610                      */
  45611                     fc->scache_size[_FIELD_SCACHE_PART_0] += 135 * 1024;
  45612                 }
  45613 
  45614                 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_17) {
  45615 
  45616                     /* For WB sync and recovery of configured policer rates,
  45617                      * syncing only the delta value (diff btw configured and programmed
  45618                      * for ckbits_sec, ckbits_burst, pkbits_sec, pkbits_burst.
  45619                      * Taking 2 bytes for each of the delta,
  45620                      * Required size = Maximum Number of entries * 8 bytes
  45621                      * IFP := 16K * 8  = 128 KB
  45622                      * EFP := 2K  * 8 = 16KB
  45623                      * Total size = 144 KB
  45624                      */
  45625                     fc->scache_size[_FIELD_SCACHE_PART_0] += 144 * 1024;
  45626                 }
  45627 
  45628                 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_18) {
  45629                     /* Sync for SVP DVP type per entry part and
  45630                      * ingress, src entity selcode per group part
  45631                      */
  45632                     fc->scache_size[_FIELD_SCACHE_PART_0] += (21 * 1024);
  45633                 }
  45634 
  45635                 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_19) {
  45636                     /* Sync No Param Actions enum and PortPrioIntCosQNew Actions Gport Values
  45637                      * ((4) Bytes * (16 + 1 + 1)  + ((12) bytes * 16) K entries
  45638                      * in IFP Stage
  45639                      */
  45640                     fc->scache_size[_FIELD_SCACHE_PART_0] += (264 * 1024);
  45641                 }
  45642 
  45643                 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_20) {
  45644                     /* Allocate additional scache to sync IFP action ingress
  45645                      * and egress mirror gport value in no parm actions sync
  45646                      * enums per entry. IngressMirror and EgressMirror GPORT
  45647                      * can be assigned to single entry. Have to allocate (4+4)
  45648                      * bytes per entry.
  45649                      * IFP = (8 bytes * 512 entries * 12 slices).
  45650                      */
  45651                     fc->scache_size[_FIELD_SCACHE_PART_0] += (48 * 1024);
  45652                     /*
  45653                      * Scache size is increased by (16 * 4) * 1024 bytes for
  45654                      * all devices and (8 * 4) *1024 * 2 for KT2 devices
  45655                      * to sync and recover the params of fabricQueue action
  45656                      * for all entries of Ingress.
  45657                      */
  45658                     fc->scache_size[_FIELD_SCACHE_PART_0] += (16 * 4 * 1024);
  45659                 }
  45660 
  45661                 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_21) {
  45662                     /*
  45663                      * Group PBMP is synced with max_groups * size of the pbmp array
  45664                      */
  45665                     fc->scache_size[_FIELD_SCACHE_PART_0] += ((512 * _SHR_PBMP_WORD_MAX * 4) + (16 * 1024 * 12));
  45666                 }
  45667 
  45668                 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_23) {
  45669                     /*
  45670                      * Scache size is increased by 128 * 4 bytes
  45671                      * to syncloopbacktype selcode per group part.
  45672                      * Worst case assuming 128 IFP groups in quad mode
  45673                      * (128 * 4) bytes.
  45674                      */
  45675                     fc->scache_size[_FIELD_SCACHE_PART_0] += (128 * 4);
  45676                 }
  45677 
  45678                 if ((fc->wb_current_version) >= BCM_FIELD_WB_VERSION_1_26) {
  45679                     /*
  45680                      * Scache size is increased by _FP_MAX_NUM_PIPES * 1 bytes
  45681                      * to sync instance for all pipes in EFP/VFP slice map.
  45682                      * _FP_MAX_NUM_PIPES * 1 bytes * 8 groups to sync group
  45683                      * instance for all groups in EFP/VFP
  45684                      */
  45685                     fc->scache_size[_FIELD_SCACHE_PART_0] += ((_FP_MAX_NUM_PIPES)
  45686                                                               + (_FP_MAX_NUM_PIPES * 8));
  45687                 }
  45688 
  45689             } else {
  45690                 /* Allocate a section of the Level 2 Warm Boot
  45691                  * global cache.
  45692                  * Assume 90% of the total stable size - just a heuristic
  45693                  */
  45694                 fc->scache_size[_FIELD_SCACHE_PART_0] = (9 * stable_size) / 10;
  45695                 fc->scache_size[_FIELD_SCACHE_PART_1] = (1 * stable_size) / 100;
  45696             }
  45697 
  45698             /* Get the pointer for the Level 2 cache */
  45699             SOC_IF_ERROR_RETURN(soc_scache_ptr_get(unit, handle,
  45700                                     &(fc->scache_ptr[_FIELD_SCACHE_PART_0]),
  45701                                     &alloc_get));
  45702             if (!SOC_WARM_BOOT(unit)) {
  45703                 /* Not yet allocated in Cold Boot */
  45704                 SOC_IF_ERROR_RETURN
  45705                     (soc_scache_realloc(unit, handle,
  45706                                   (fc->scache_size[_FIELD_SCACHE_PART_0]
  45707                                   - (alloc_get - SOC_WB_SCACHE_CONTROL_SIZE))));
  45708                 rv = soc_scache_ptr_get(unit, handle,
  45709                                         &(fc->scache_ptr[_FIELD_SCACHE_PART_0]),
  45710                                         &alloc_get);
  45711             }
  45712 
  45713             if (BCM_FAILURE(rv)) {
  45714                 return rv;
  45715             } else if (alloc_get != fc->scache_size[_FIELD_SCACHE_PART_0] +
  45716                                     SOC_WB_SCACHE_CONTROL_SIZE) {
  45717                    /* Expected size doesn't match retrieved size */
  45718                    /* Scache size is increased by 16*1024 bytes
  45719                     * from version BCM_FIELD_WB_VERSION_1_6.The below check is
  45720                     * for upgrades from lower versions to BCM_FIELD_WB_VERSION_1_6
  45721                     * and above.
  45722                     * Scache size increased by 128 bytes from BCM_FIELD_WB_VERSION_1_8.
  45723                     * with respect to BCM_FIELD_WB_VERSION_1_6
  45724                     */
  45725                     rv = _field_scache_version_size_check(unit, alloc_get,
  45726                                                           (fc->wb_recovered_version),
  45727                                                           fc->scache_size[_FIELD_SCACHE_PART_0] +
  45728                                                           SOC_WB_SCACHE_CONTROL_SIZE,
  45729                                                           (fc->wb_current_version));
  45730                     if (rv != TRUE) {
  45731                         return BCM_E_INTERNAL;
  45732                     }
  45733             } else if (NULL == fc->scache_ptr[_FIELD_SCACHE_PART_0]) {
  45734                 return BCM_E_MEMORY;
  45735             }
  45736 
  45737             SOC_SCACHE_HANDLE_SET(handle, unit, BCM_MODULE_FIELD, 1);
  45738             SOC_SCACHE_MODULE_MAX_PARTITIONS_SET(unit, BCM_MODULE_FIELD, 1);
  45739 
  45740             /* Get the pointer for the Level 2 cache */
  45741             SOC_IF_ERROR_RETURN(soc_scache_ptr_get(unit, handle,
  45742                                     &(fc->scache_ptr[_FIELD_SCACHE_PART_1]),
  45743                                     &alloc_get));
  45744             if (!SOC_WARM_BOOT(unit)) {
  45745                 /*Allocated in Cold Boot */
  45746                 SOC_IF_ERROR_RETURN
  45747                     (soc_scache_realloc(unit, handle,
  45748                              (fc->scache_size[_FIELD_SCACHE_PART_1]
  45749                              - (alloc_get - SOC_WB_SCACHE_CONTROL_SIZE))));
  45750                 rv = (soc_scache_ptr_get(unit, handle,
  45751                                         &(fc->scache_ptr[_FIELD_SCACHE_PART_1]),
  45752                                         &alloc_get));
  45753             }
  45754 
  45755             if (BCM_FAILURE(rv)) {
  45756                 return rv;
  45757             } else if (alloc_get != fc->scache_size[_FIELD_SCACHE_PART_1] +
  45758                                     SOC_WB_SCACHE_CONTROL_SIZE) {
  45759                 /* Expected size doesn't match retrieved size */
  45760                 return BCM_E_INTERNAL;
  45761             } else if (NULL == fc->scache_ptr[_FIELD_SCACHE_PART_1]) {
  45762                 return BCM_E_MEMORY;
  45763             }
  45764 
  45765         }
  45766     }
  45767     return rv;
  45768 }
  45769 
  45770 
  45771 /*
  45772  * Function: _bcm_field_wb_downgrade_config_set
  45773  *
  45774  * Purpose:
  45775  *     Field Downgrade Configuration Set
  45776  *
  45777  * Parameters:
  45778  *     unit - BCM device number
  45779  *     warmboot_ver - WarmBoot Version for SDK
  45780  *
  45781  * Returns:
  45782  *     BCM_E_XXX.
  45783  */
  45784 
  45785 int
  45786 _bcm_field_wb_downgrade_config_set(int unit, uint32 warmboot_ver) {
  45787 
  45788     int pos = 0;
  45789     _field_control_t *fc;
  45790     int rv = BCM_E_NONE;
  45791     uint32 prev_version;
  45792 
  45793 
  45794     FP_LOCK(unit);
  45795 
  45796     rv = _field_control_get(unit, &fc);
  45797 
  45798     if (BCM_FAILURE(rv)) {
  45799         FP_UNLOCK(unit);
  45800         return rv;
  45801     }
  45802 
  45803     prev_version = fc->wb_current_version;
  45804 
  45805     for (pos = 0; pos < COUNTOF(_field_sdk_warmboot_version); pos++) {
  45806         if (_field_sdk_warmboot_version[pos][0] == warmboot_ver) {
  45807             if (fc->wb_current_version != _field_sdk_warmboot_version[pos][1]) {
  45808                 fc->wb_current_version = _field_sdk_warmboot_version[pos][1];
  45809                 break;
  45810             } else {
  45811                 FP_UNLOCK(unit);
  45812                 return BCM_E_NONE;
  45813             }
  45814         } else if ((pos > 0) &&
  45815                 (_field_sdk_warmboot_version[pos][0] > warmboot_ver) &&
  45816                 (_field_sdk_warmboot_version[pos - 1][0] < warmboot_ver)) {
  45817             /* As _field_sdk_warmboot_version database will be updated only when a
  45818              * WB change in present in a version. So this database structure will not have
  45819              * all the version number. When a requested version number is in between 2
  45820              * valid versions, use the previous version number. */
  45821             pos--;
  45822             if (fc->wb_current_version != _field_sdk_warmboot_version[pos][1]) {
  45823                 fc->wb_current_version = _field_sdk_warmboot_version[pos][1];
  45824                 break;
  45825             } else {
  45826                 FP_UNLOCK(unit);
  45827                 return BCM_E_NONE;
  45828             }
  45829         }
  45830     }
  45831 
  45832     if (pos == COUNTOF(_field_sdk_warmboot_version)) {
  45833         if (_field_sdk_warmboot_version[pos - 1][0] < warmboot_ver) {
  45834             /* Upgrade case or like to like case */
  45835             if (fc->wb_current_version != _field_sdk_warmboot_version[pos -1][1]) {
  45836                 fc->wb_current_version = _field_sdk_warmboot_version[pos - 1][1];
  45837             } else {
  45838                 FP_UNLOCK(unit);
  45839                 return BCM_E_NONE;
  45840             }
  45841         } else {
  45842             LOG_DEBUG(BSL_LS_BCM_FP,
  45843                     (BSL_META_U(unit,
  45844                                 "Version invalid for Warmboot Downgrade\n")));
  45845             FP_UNLOCK(unit);
  45846             return BCM_E_PARAM;
  45847         }
  45848     }
  45849 
  45850     LOG_DEBUG(BSL_LS_BCM_FP,
  45851             (BSL_META_U(unit, "FP(unit %d) Current WB version [0x%x]\n"),
  45852              unit, fc->wb_current_version));
  45853 
  45854 #ifdef BCM_TOMAHAWK_SUPPORT
  45855      if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  45856          rv = (_bcm_field_scache_th_pointer_realloc(unit, fc));
  45857      } else
  45858 #endif
  45859      {
  45860          rv = (_field_scache_pointer_realloc(unit, fc));
  45861      }
  45862 
  45863     if (BCM_FAILURE(rv)) {
  45864         /* In case of failure, reallocate based on
  45865          * previous version number */
  45866         fc->wb_current_version = prev_version;
  45867 #ifdef BCM_TOMAHAWK_SUPPORT
  45868         if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  45869             _bcm_field_scache_th_pointer_realloc(unit, fc);
  45870         } else
  45871 #endif
  45872         {
  45873             _field_scache_pointer_realloc(unit, fc);
  45874         }
  45875     }
  45876 
  45877     FP_UNLOCK(unit);
  45878     return rv;
  45879 }
  45880 
  45881 #endif /* BCM_WARM_BOOT_SUPPORT */
  45882 
  45883 
  45884 /*
  45885  * Function: _bcm_esw_field_init
  45886  *
  45887  * Purpose:
  45888  *    Initialize field module.
  45889  *
  45890  * Parameters:
  45891  *     unit - (IN) BCM device number
  45892  *
  45893  * Returns:
  45894  *     BCM_E_UNIT    - Invalid BCM unit number.
  45895  *     BCM_E_UNAVAIL - Field Processor not on device.
  45896  *     BCM_E_MEMORY  - Allocation failure
  45897  *     BCM_E_XXX     - Error code from bcm_XX_field_init()
  45898  *     BCM_E_NONE    - Success
  45899  */
  45900 int
  45901 _bcm_esw_field_init(int unit)
  45902 {
  45903     int                udf_idx;    /* Iteration index.         */
  45904     int                rv;         /* Operation return value.  */
  45905     int                size;       /* Allocation size.         */
  45906     _field_control_t   *fc = NULL; /* Field control structure. */
  45907 #ifdef BCM_WARM_BOOT_SUPPORT
  45908     _field_stage_id_t  stage_id;
  45909     _field_stage_t     *stage_fc = NULL;
  45910 #endif /* BCM_WARM_BOOT_SUPPORT */
  45911 #if defined(BCM_TOMAHAWK_SUPPORT)
  45912     int pool = -1;
  45913 #endif
  45914     _field_egr_ports_recovery_t *f_egr_recovery = NULL;
  45915     int pipe = -1;
  45916 #if defined(BCM_TRX_SUPPORT)
  45917     int entry_words; /* Redirection profile entry size. */
  45918     soc_mem_t mem; /* SOC Memory name variable. */
  45919 #endif
  45920 
  45921     /* Make sure the Unit can support this module. */
  45922     if (SOC_IS_SHADOW(unit) || !soc_feature(unit, soc_feature_field)) {
  45923         LOG_ERROR(BSL_LS_BCM_FP,
  45924                   (BSL_META_U(unit,
  45925                               "FP(unit %d) Error: No Field Processor available \n"),
  45926                    unit));
  45927         return (BCM_E_UNAVAIL);
  45928     }
  45929 
  45930     /* Detatch first if it's been previously initialized. */
  45931     if (_field_control[unit] != NULL) {
  45932         if (SOC_WARM_BOOT(unit)) {
  45933             /* Clear Sticky ExactMatch stage flag */
  45934             _field_control[unit]->flags &= ~_FP_EXACTMATCH_STAGE_SKIP_DETACH;
  45935         }
  45936         _field_control[unit]->init = FALSE;
  45937         rv = bcm_esw_field_detach(unit);
  45938         if (BCM_FAILURE(rv)) {
  45939             LOG_ERROR(BSL_LS_BCM_FP,
  45940                       (BSL_META_U(unit,
  45941                                   "FP(unit %d) Error: Module deinit failed.\n"),
  45942                        unit));
  45943             return (rv);
  45944         }
  45945     }
  45946 
  45947     fc = _field_control[unit];
  45948     /* Allocate a bcm_field_control */
  45949     if (NULL == fc) {
  45950     _FP_XGS3_ALLOC(fc, sizeof (_field_control_t), "field_control");
  45951     }
  45952     if (NULL == fc) {
  45953         return (BCM_E_MEMORY);
  45954     }
  45955 
  45956     if (soc_feature(unit, soc_feature_epc_linkflap_recover)) {
  45957         /* Allocate a _field_egr_ports_recovery_t */
  45958         _FP_XGS3_ALLOC(f_egr_recovery,
  45959                 sizeof (_field_egr_ports_recovery_t),
  45960                 "field_egr_ports_recovery");
  45961         if (NULL == f_egr_recovery) {
  45962             _field_control_free(unit, fc);
  45963             return (BCM_E_MEMORY);
  45964         }
  45965 
  45966         /* Allocate a _field_entry_egr_ports_recovery_t */
  45967         _FP_XGS3_ALLOC(f_egr_recovery->entry_recover_egr_ports,
  45968               (sizeof (_field_entry_recover_egr_ports_t *) * SOC_MAX_NUM_PORTS),
  45969                 "field_entry_egr_ports_recovery");
  45970 
  45971         if (NULL == f_egr_recovery->entry_recover_egr_ports) {
  45972             _field_egr_ports_recovery_control_free (unit, f_egr_recovery);
  45973             _field_control_free(unit, fc);
  45974             return (BCM_E_MEMORY);
  45975         }
  45976 
  45977         _field_egr_ports_recovery[unit] = f_egr_recovery;
  45978 
  45979         /* Initialize _field_egr_ports_recovery*/
  45980         sal_memset (_field_egr_ports_recovery_lock, 0,
  45981                 sizeof (_field_egr_ports_recovery_lock));
  45982     }
  45983 
  45984 #if defined (BCM_TRIUMPH3_SUPPORT)
  45985     if(SOC_IS_TRIUMPH3(unit)) {
  45986         fc->_fp_egr_ifp_mod_fields_size = soc_mem_index_count(unit,EGR_IFP_MOD_FIELDSm);
  45987         size = SHR_BITALLOCSIZE(fc->_fp_egr_ifp_mod_fields_size);
  45988         fc->field_action_l2mod_index_bmp.w = NULL;
  45989         _FP_XGS3_ALLOC(fc->field_action_l2mod_index_bmp.w,
  45990                         size, "L2ModIndexSize Bitmap");
  45991         if (NULL == fc->field_action_l2mod_index_bmp.w) {
  45992             _field_control_free(unit, fc);
  45993             return (BCM_E_MEMORY);
  45994         }
  45995     }
  45996 #endif
  45997 
  45998     /* First check if external FP is present. */
  45999 
  46000 #if defined(BCM_TRIUMPH_SUPPORT)
  46001     if (soc_feature(unit, soc_feature_esm_support)) {
  46002         if (SOC_IS_TRIUMPH(unit) || SOC_IS_TRIUMPH2(unit)) {
  46003             if ((SOC_MEM_IS_VALID(unit, EXT_FP_CNTRm)) &&
  46004                 (soc_mem_index_count(unit, EXT_FP_CNTRm))
  46005                 ) {
  46006                 fc->flags |= _FP_EXTERNAL_PRESENT;
  46007             }
  46008         }
  46009     }
  46010 #endif /* BCM_TRIUMPH_SUPPORT */
  46011 
  46012 #ifdef BCM_TRIUMPH3_SUPPORT
  46013     if (SOC_IS_TRIUMPH3(unit) && _bcm_field_tr3_external_present(unit)) {
  46014         fc->flags |= _FP_EXTERNAL_PRESENT;
  46015     }
  46016 #endif
  46017 
  46018 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRX_SUPPORT)
  46019     if (SOC_IS_TRX(unit) || SOC_IS_BRADLEY(unit)) {
  46020         /*
  46021          * Note:
  46022          * Enable field stat sync with hardware
  46023          * for bcm_field_stat_get()/_getxx() apis.
  46024          */
  46025         fc->flags |= _FP_STAT_SYNC_ENABLE;
  46026     }
  46027 #endif
  46028 
  46029     /*Set field control- Color Independent to TRUE which implies -
  46030      *Packet Redirect and L3SW_CHANGE_L2 field actions are applicable
  46031      *to all packets(Green/Yellow/Red)*/
  46032     fc->flags |= _FP_COLOR_INDEPENDENT;
  46033 
  46034     /* Allocate Hints lookup hash. */
  46035     _FP_XGS3_ALLOC(fc->hints_hash, _FP_HASH_SZ(fc) * \
  46036                    sizeof(_field_hints_t *), "Hints hash");
  46037     if (NULL == fc->hints_hash) {
  46038         _field_control_free(unit, fc);
  46039         return (BCM_E_MEMORY);
  46040     }
  46041     size = SHR_BITALLOCSIZE(_FP_HINT_ID_MAX);
  46042 
  46043     _FP_XGS3_ALLOC(fc->hintid_bmp.w, size, "HintIds Bitmap");
  46044     if (NULL == fc->hintid_bmp.w) {
  46045         _field_control_free(unit, fc);
  46046         return (BCM_E_MEMORY);
  46047     }
  46048 
  46049     /* Allocate policer lookup hash. */
  46050     _FP_XGS3_ALLOC(fc->policer_hash, _FP_HASH_SZ(fc) * \
  46051                    sizeof(_field_policer_t *), "Policer hash");
  46052     if (NULL == fc->policer_hash) {
  46053         _field_control_free(unit, fc);
  46054         return (BCM_E_MEMORY);
  46055     }
  46056 
  46057     /* Allocate statistics collection lookup hash. */
  46058     _FP_XGS3_ALLOC(fc->stat_hash, _FP_HASH_SZ(fc) * \
  46059                    sizeof(_field_stat_t *), "Stat hash");
  46060     if (NULL == fc->stat_hash) {
  46061         _field_control_free(unit, fc);
  46062         return (BCM_E_MEMORY);
  46063     }
  46064 
  46065     /* Initialize Pipe map or valid pipes on a device */
  46066     fc->pipe_map = 0;
  46067 #ifdef BCM_TOMAHAWK3_SUPPORT
  46068     if (soc_feature(unit, soc_feature_th3_style_fp)) {
  46069         /* fetch active pipes */
  46070         soc_tomahawk3_pipe_map_get(unit, &(fc->pipe_map));
  46071     } else
  46072 #endif
  46073     {
  46074         for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) {
  46075              fc->pipe_map |= (1 << pipe);
  46076         }
  46077     }
  46078 
  46079 #ifdef BCM_TOMAHAWK_SUPPORT
  46080     if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  46081         for (pipe = 0; pipe < _FP_MAX_NUM_PIPES; pipe++) {
  46082             for (pool = 0; pool < _FIELD_MAX_METER_POOLS; pool++) {
  46083                  fc->ifp_em_meter_in_use[pipe][pool]
  46084                   = BCM_FIELD_METER_POOL_USED_BY_NONE;
  46085             }
  46086         }
  46087     }
  46088 #endif
  46089 
  46090 #ifdef BCM_TOMAHAWK_SUPPORT
  46091     if (soc_feature(unit, soc_feature_field_preselector_support)) {
  46092         /* Allocate memory for preselector lookup database. */
  46093         _FP_XGS3_ALLOC(fc->presel_db, BCM_FIELD_PRESEL_SEL_MAX * \
  46094                 sizeof(_field_presel_entry_t *), "Presel db");
  46095         if (NULL == fc->presel_db) {
  46096             _field_control_free(unit, fc);
  46097             return (BCM_E_MEMORY);
  46098         }
  46099 
  46100         /* Allocate preselector information structure. */
  46101         _FP_XGS3_ALLOC(fc->presel_info, sizeof(_field_presel_info_t),
  46102                 "Field Control Presel Info Alloc.");
  46103         if (NULL == fc->presel_info) {
  46104             _field_control_free(unit, fc);
  46105             return (BCM_E_MEMORY);
  46106         }
  46107 
  46108         /* Update the Preselector Max Limit */
  46109         fc->presel_info->presel_limit = _BCM_FIELD_PRESEL_ID_MAX;
  46110     }
  46111 
  46112     /* Initialize field control lt table structures. */
  46113     rv =  _field_th_lt_config_init(unit, fc);
  46114     if (BCM_FAILURE(rv)) {
  46115         _field_control_free(unit, fc);
  46116         return rv;
  46117     }
  46118 #endif
  46119 
  46120     /* Allocate user defined qualifiers. */
  46121     _FP_XGS3_ALLOC(fc->udf, BCM_FIELD_USER_NUM_UDFS * \
  46122                    sizeof(_field_udf_t), "Udf table");
  46123     if (NULL == fc->udf) {
  46124         _field_control_free(unit, fc);
  46125         return (BCM_E_MEMORY);
  46126     }
  46127 
  46128     /* Initialize pipeline stages field control structures. */
  46129     rv = _field_stages_init(unit, fc);
  46130     if (BCM_FAILURE(rv)) {
  46131         _field_control_free(unit, fc);
  46132         return rv;
  46133     }
  46134 
  46135     /* Initialize fp status structure. */
  46136     fc->stage       = bcmFieldStageDefault;
  46137 
  46138 #ifdef BCM_WARM_BOOT_SUPPORT
  46139     /* Inititalize WB default/Recovered Version */
  46140     fc->wb_current_version = BCM_FIELD_WB_DEFAULT_VERSION;
  46141     fc->wb_recovered_version = 0;
  46142 #endif
  46143 
  46144     if (soc_feature(unit, soc_feature_field_intraslice_double_wide)) {
  46145         fc->flags |= _FP_INTRASLICE_ENABLE;
  46146     }
  46147 
  46148     /* Assign the virtual UDFs to the underlying H/W */
  46149     for (udf_idx = 0; udf_idx < BCM_FIELD_USER_NUM_UDFS; udf_idx++) {
  46150         fc->udf[udf_idx].udf_num = udf_idx >> 2;
  46151         fc->udf[udf_idx].user_num = udf_idx & 0x03;
  46152     }
  46153 
  46154 #if defined (BCM_TRX_SUPPORT)
  46155     /* Initialize global Redirect action memory profile. */
  46156     soc_profile_mem_t_init(&fc->redirect_profile);
  46157 
  46158 #if defined (BCM_TOMAHAWK3_SUPPORT)
  46159     /* Initialize global Redirect action memory profile. */
  46160     soc_profile_mem_t_init(&fc->redirect_profile1);
  46161     /* Initialize Delayed drop action memory profile. */
  46162     soc_profile_mem_t_init(&fc->ddrop_profile);
  46163     /* Initialize Delayed Redirect action memory profile. */
  46164     soc_profile_mem_t_init(&fc->dredirect_profile);
  46165 #endif
  46166 
  46167 #if defined (BCM_TOMAHAWK_SUPPORT)
  46168     /* Redirect HiGiG2 extended header mask profile initialization. */
  46169     if (soc_feature(unit, soc_feature_higig_lookup) && SOC_IS_TOMAHAWKX(unit))
  46170     {
  46171        soc_profile_mem_t_init(&fc->eh_mask_profile);
  46172     }
  46173 #endif
  46174 
  46175     /* Assign redirection profile memory name "mem" variable. */
  46176     if (soc_feature(unit, soc_feature_th3_style_fp)) {
  46177         mem = IFP_OR_REDIRECTION_PROFILEm;
  46178     } else {
  46179         mem = IFP_REDIRECTION_PROFILEm;
  46180     }
  46181 
  46182     /* Determine redirection profile entry size in number of words. */
  46183     entry_words = sizeof(ifp_redirection_profile_entry_t) / sizeof(uint32);
  46184 
  46185     if (SOC_MEM_IS_VALID(unit, mem)) {
  46186         /* Create the redirection profile table. */
  46187         rv = soc_profile_mem_create(unit, &mem, &entry_words, 1,
  46188                 &fc->redirect_profile);
  46189         if (BCM_FAILURE(rv)) {
  46190             LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
  46191                 "FP(unit %d) Error: Redirection profile creation failed.=%d\n"),
  46192                  unit, rv));
  46193             return (rv);
  46194         }
  46195     }
  46196 
  46197 #if defined (BCM_TOMAHAWK3_SUPPORT)
  46198     if (soc_feature(unit, soc_feature_th3_style_fp)) {
  46199         mem = IFP_AND_REDIRECTION_PROFILEm;
  46200         /* Determine redirection profile entry size in number of words. */
  46201         entry_words = sizeof(ifp_redirection_profile_entry_t) / sizeof(uint32);
  46202 
  46203         /* Create the redirection profile table. */
  46204         rv = soc_profile_mem_create(unit, &mem, &entry_words, 1,
  46205                 &fc->redirect_profile1);
  46206         if (BCM_FAILURE(rv)) {
  46207             LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
  46208                 "FP(unit %d) Error: Redirection profile creation failed.=%d\n"),
  46209                  unit, rv));
  46210             return (rv);
  46211         }
  46212 
  46213         mem = IFP_EGRESS_PORT_CHECK_FOR_DROPm;
  46214         /* Determine redirection profile entry size in number of words. */
  46215         entry_words = sizeof(ifp_egress_port_check_for_drop_entry_t) / sizeof(uint32);
  46216 
  46217         /* Create the redirection profile table. */
  46218         rv = soc_profile_mem_create(unit, &mem, &entry_words, 1,
  46219                     &fc->ddrop_profile);
  46220             if (BCM_FAILURE(rv)) {
  46221                 LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
  46222                     "FP(unit %d) Error: Action Drop profile creation failed.=%d\n"),
  46223                      unit, rv));
  46224                 return (rv);
  46225             }
  46226 
  46227         mem = IFP_EGRESS_PORT_CHECK_FOR_REDIRECTm;
  46228         /* Determine redirection profile entry size in number of words. */
  46229         entry_words = sizeof(ifp_egress_port_check_for_redirect_entry_t) / sizeof(uint32);
  46230 
  46231         /* Create the redirection profile table. */
  46232         rv = soc_profile_mem_create(unit, &mem, &entry_words, 1,
  46233                 &fc->dredirect_profile);
  46234         if (BCM_FAILURE(rv)) {
  46235             LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
  46236                 "FP(unit %d) Error: Action Redirect profile creation failed.=%d\n"),
  46237                  unit, rv));
  46238             return (rv);
  46239         }
  46240 
  46241     }
  46242 #endif
  46243 #if defined (BCM_TOMAHAWK_SUPPORT)
  46244     if (soc_feature(unit, soc_feature_higig_lookup) && SOC_IS_TOMAHAWKX(unit)) {
  46245         /* Assign HiGiG2 extended header mask memory name "mem" variable. */
  46246         mem = EH_MASK_PROFILEm;
  46247 
  46248         /* Determine HiGiG2 extended header mask profile entry size
  46249          * in number of words. */
  46250         entry_words = sizeof(eh_mask_profile_entry_t) / sizeof(uint32);
  46251 
  46252         /* Create the HiGiG2 extended header mask profile table. */
  46253         rv = soc_profile_mem_create(unit, &mem, &entry_words, 1,
  46254                 &fc->eh_mask_profile);
  46255         if (BCM_FAILURE(rv)) {
  46256             LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
  46257             "FP(unit %d) Error: HiGiG2 EH mask profile creation failed.=%d\n"),
  46258                  unit, rv));
  46259             return (rv);
  46260         }
  46261     }
  46262 #endif
  46263 #endif
  46264 
  46265 #if defined(BCM_RAPTOR_SUPPORT)
  46266     if (SOC_IS_RAPTOR(unit) || SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit)) {
  46267         rv = _bcm_field_raptor_init(unit, fc);
  46268     } else
  46269 #endif /* BCM_RAPTOR_SUPPORT */
  46270 
  46271 #if defined(BCM_TRIUMPH_SUPPORT)
  46272     if (SOC_IS_TR_VL(unit)) {
  46273 #if defined(BCM_TOMAHAWK_SUPPORT)
  46274         if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  46275             rv = _bcm_field_th_init(unit, fc);
  46276         } else
  46277 #endif /*BCM_TOMAHAWK_SUPPORT */
  46278 #if defined(BCM_TRIDENT2_SUPPORT)
  46279         if (SOC_IS_TD2_TT2(unit)) {
  46280             rv = _bcm_field_td2_init(unit, fc);
  46281         } else
  46282 #endif /*BCM_TRIDENT2_SUPPORT */
  46283 #if defined(BCM_TRIUMPH3_SUPPORT)
  46284         if (SOC_IS_TRIUMPH3(unit)) {
  46285             rv = _bcm_field_tr3_init(unit, fc);
  46286         } else
  46287 #endif /* BCM_TRIUMPH3_SUPPORT */
  46288 #if defined(BCM_TRIDENT_SUPPORT)
  46289         if (SOC_IS_TD_TT(unit)) {
  46290             rv = _bcm_field_trident_init(unit, fc);
  46291         } else
  46292 #endif /* BCM_TRIDENT_SUPPORT */
  46293 #if defined(BCM_TRIUMPH2_SUPPORT)
  46294         if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) ||
  46295             SOC_IS_VALKYRIE2(unit)) {
  46296             rv = _bcm_field_tr2_init(unit, fc);
  46297         } else
  46298 #endif /* BCM_TRIUMPH2_SUPPORT */
  46299 #if defined(BCM_ENDURO_SUPPORT)
  46300         if (SOC_IS_ENDURO(unit)) {
  46301             rv = _bcm_field_en_init(unit, fc);
  46302         } else
  46303 #endif /* BCM_ENDURO_SUPPORT */
  46304 #if defined(BCM_HURRICANE1_SUPPORT)
  46305         if (SOC_IS_HURRICANE(unit)) {
  46306             rv = _bcm_field_hu_init(unit, fc);
  46307         } else
  46308 #endif /* BCM_HURRICANE1_SUPPORT */
  46309 #if defined(BCM_HURRICANE2_SUPPORT)
  46310         if (SOC_IS_HURRICANE2(unit)) {
  46311             rv = _bcm_field_hu2_init(unit,fc);
  46312         } else
  46313 #endif /* BCM_HURRICANE_SUPPORT */
  46314 #if defined(BCM_KATANA_SUPPORT)
  46315         if (SOC_IS_KATANA(unit)) {
  46316             rv = _bcm_field_katana_init(unit, fc);
  46317         } else
  46318 #endif /* BCM_KATANA_SUPPORT */
  46319 #if defined(BCM_KATANA2_SUPPORT)
  46320         if (SOC_IS_KATANA2(unit)) {
  46321             rv = _bcm_field_kt2_init(unit, fc);
  46322         } else
  46323 #endif /* BCM_KATANA_SUPPORT */
  46324 #if defined(BCM_GREYHOUND_SUPPORT)
  46325         if (SOC_IS_GREYHOUND(unit)) {
  46326             rv = _bcm_field_gh_init(unit,fc);
  46327         } else
  46328 #endif /* BCM_GREYHOUND_SUPPORT */
  46329 #if defined(BCM_HURRICANE3_SUPPORT)
  46330         if (SOC_IS_HURRICANE3(unit)) {
  46331             rv = _bcm_field_hr3_init(unit,fc);
  46332         } else
  46333 #endif /* BCM_HURRICANE3_SUPPORT */
  46334 #if defined(BCM_GREYHOUND2_SUPPORT)
  46335         if (SOC_IS_GREYHOUND2(unit)) {
  46336             rv = _bcm_field_gh2_init(unit,fc);
  46337         } else
  46338 #endif /* BCM_GREYHOUND2_SUPPORT */
  46339 
  46340         {
  46341             rv = _bcm_field_tr_init(unit, fc);
  46342         }
  46343     } else
  46344 #endif /* BCM_TRIUMPH_SUPPORT */
  46345 
  46346 #if defined(BCM_SCORPION_SUPPORT)
  46347     if (SOC_IS_SC_CQ(unit)) {
  46348         rv = _bcm_field_sc_init(unit, fc);
  46349     } else
  46350 #endif /* BCM_TRIUMPH_SUPPORT */
  46351 
  46352 #ifdef BCM_FIREBOLT_SUPPORT
  46353     if (SOC_IS_FBX(unit)) {
  46354         rv = _bcm_field_fb_init(unit, fc);
  46355     }
  46356 #endif /* BCM_FIREBOLT_SUPPORT */
  46357 
  46358 
  46359     /* cleanup on device specific init failure.  */
  46360     if (BCM_FAILURE(rv)) {
  46361         if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  46362             /* Destroy all CAP stages and its FP instances. */
  46363             fc->stage_func.fp_stages_delete(unit, fc);
  46364         } else {
  46365             _field_stages_destroy(unit, fc);
  46366         }
  46367         _field_control_free(unit, fc);
  46368         return rv;
  46369     }
  46370 
  46371     /* Initialize supported qset for each stage. */
  46372     _bcm_field_stages_supported_qset_init(unit, fc);
  46373 
  46374     fc->last_allocated_eid = 0;
  46375     _field_control[unit] = fc;
  46376 
  46377     /* Register counter collection callback. */
  46378     BCM_IF_ERROR_RETURN(soc_counter_extra_register(unit,
  46379                          _bcm_esw_fp_counters_collect));
  46380 
  46381 #ifdef BCM_WARM_BOOT_SUPPORT
  46382 #ifdef BCM_TOMAHAWK_SUPPORT
  46383      if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  46384          BCM_IF_ERROR_RETURN(_bcm_field_scache_th_pointer_init(unit, fc));
  46385      } else
  46386 #endif
  46387      {
  46388          BCM_IF_ERROR_RETURN(_field_scache_pointer_init(unit, fc));
  46389      }
  46390     /* Construct the _field_stage_t structure based on HW programming
  46391      * in Warm Boot mode */
  46392     if (SOC_WARM_BOOT(unit)) {
  46393         fc->l2warm = (fc->scache_size[_FIELD_SCACHE_PART_0] &&
  46394                       !SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit)) ? 1 : 0;
  46395 
  46396         if (SOC_IS_FIREBOLT(unit) || SOC_IS_HB_GW(unit)) {
  46397             stage_id = _BCM_FIELD_STAGE_INGRESS;
  46398 
  46399             BCM_IF_ERROR_RETURN(_field_stage_control_get(unit, stage_id,
  46400                 &stage_fc));
  46401 
  46402             rv = _field_fb_stage_reinit(unit, fc, stage_fc);
  46403             if ((rv == BCM_E_INTERNAL) &&
  46404                 (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) &&
  46405                 (fc->l2warm == 0)) {
  46406                 /* Stale scache */
  46407                 SOC_IF_ERROR_RETURN
  46408                     (soc_event_generate(unit, SOC_SWITCH_EVENT_STABLE_ERROR,
  46409                                         SOC_STABLE_STALE, SOC_STABLE_FIELD, 0));
  46410                 /* Clean up generated state and restart as Level 1 */
  46411                 BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc));
  46412                 rv = _field_fb_stage_reinit(unit, fc, stage_fc);
  46413             }
  46414         } else if (SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit)) {
  46415 #ifdef BCM_RAVEN_SUPPORT
  46416             stage_id = _BCM_FIELD_STAGE_INGRESS;
  46417             BCM_IF_ERROR_RETURN
  46418                 (_field_stage_control_get(unit, stage_id, &stage_fc));
  46419             rv = _field_raven_stage_reinit(unit, fc, stage_fc);
  46420             if ((rv == BCM_E_INTERNAL) &&
  46421                 (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) &&
  46422                 (fc->l2warm == 0)) {
  46423                 /* Stale scache */
  46424                 SOC_IF_ERROR_RETURN
  46425                     (soc_event_generate(unit, SOC_SWITCH_EVENT_STABLE_ERROR,
  46426                                         SOC_STABLE_STALE, SOC_STABLE_FIELD, 0));
  46427                 /* Clean up generated state and restart as Level 1 */
  46428                 BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc));
  46429                 rv = _field_raven_stage_reinit(unit, fc, stage_fc);
  46430             }
  46431 #endif
  46432         } else if (SOC_IS_FIREBOLT2(unit)) {
  46433 #ifdef BCM_FIREBOLT2_SUPPORT
  46434             uint8 oldl2warm = 0;
  46435             stage_id = _BCM_FIELD_STAGE_INGRESS;
  46436             BCM_IF_ERROR_RETURN
  46437                 (_field_stage_control_get(unit, stage_id, &stage_fc));
  46438             rv = _field_fb2_stage_ingress_reinit(unit, fc, stage_fc);
  46439             if ((rv == BCM_E_INTERNAL) &&
  46440                 (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) &&
  46441                 (fc->l2warm == 0)) {
  46442                 /* Stale scache in ingress section */
  46443                 SOC_IF_ERROR_RETURN
  46444                     (soc_event_generate(unit, SOC_SWITCH_EVENT_STABLE_ERROR,
  46445                                         SOC_STABLE_STALE, SOC_STABLE_FIELD, 0));
  46446                 /* Clean up generated state and restart as Level 1 */
  46447                 BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc));
  46448                 rv = _field_fb2_stage_ingress_reinit(unit, fc, stage_fc);
  46449             }
  46450             if (BCM_SUCCESS(rv)) {
  46451                 stage_id = _BCM_FIELD_STAGE_EGRESS;
  46452                 BCM_IF_ERROR_RETURN
  46453                     (_field_stage_control_get(unit, stage_id, &stage_fc));
  46454                 oldl2warm = fc->l2warm;
  46455                 rv = _field_fb2_stage_egress_reinit(unit, fc, stage_fc);
  46456                 if ((rv == BCM_E_INTERNAL) &&
  46457                     (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) &&
  46458                     (fc->l2warm == 0) && (oldl2warm != 0)) {
  46459                     /* Stale scache in egress section */
  46460                     SOC_IF_ERROR_RETURN
  46461                         (soc_event_generate(unit, SOC_SWITCH_EVENT_STABLE_ERROR,
  46462                                             SOC_STABLE_STALE,
  46463                                             SOC_STABLE_FIELD, 0));
  46464                     /* Clean up generated state and restart as Level 1 */
  46465                     BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc));
  46466                     stage_id = _BCM_FIELD_STAGE_INGRESS;
  46467                     BCM_IF_ERROR_RETURN
  46468                         (_field_stage_control_get(unit, stage_id, &stage_fc));
  46469                     rv = _field_fb2_stage_ingress_reinit(unit, fc, stage_fc);
  46470                     if (BCM_SUCCESS(rv)) {
  46471                         stage_id = _BCM_FIELD_STAGE_EGRESS;
  46472                         BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
  46473                                             stage_id, &stage_fc));
  46474                         rv = _field_fb2_stage_egress_reinit(unit, fc, stage_fc);
  46475                     }
  46476                 }
  46477             }
  46478             if (BCM_SUCCESS(rv)) {
  46479                 stage_id = _BCM_FIELD_STAGE_LOOKUP;
  46480                 BCM_IF_ERROR_RETURN
  46481                     (_field_stage_control_get(unit, stage_id, &stage_fc));
  46482                 oldl2warm = fc->l2warm;
  46483                 rv = _field_fb2_stage_lookup_reinit(unit, fc, stage_fc);
  46484                 if ((rv == BCM_E_INTERNAL) &&
  46485                     (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) &&
  46486                     (fc->l2warm == 0) && (oldl2warm != 0)) {
  46487                     /* Stale scache in lookup section */
  46488                     SOC_IF_ERROR_RETURN
  46489                         (soc_event_generate(unit, SOC_SWITCH_EVENT_STABLE_ERROR,
  46490                                             SOC_STABLE_STALE,
  46491                                             SOC_STABLE_FIELD, 0));
  46492                     /* Clean up generated state and restart as Level 1 */
  46493                     BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc));
  46494                     stage_id = _BCM_FIELD_STAGE_INGRESS;
  46495                     BCM_IF_ERROR_RETURN
  46496                         (_field_stage_control_get(unit, stage_id, &stage_fc));
  46497                     rv = _field_fb2_stage_ingress_reinit(unit, fc, stage_fc);
  46498                     if (BCM_SUCCESS(rv)) {
  46499                         stage_id = _BCM_FIELD_STAGE_EGRESS;
  46500                         BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
  46501                                             stage_id, &stage_fc));
  46502                         rv = _field_fb2_stage_egress_reinit(unit, fc, stage_fc);
  46503                     }
  46504                     if (BCM_SUCCESS(rv)) {
  46505                         stage_id = _BCM_FIELD_STAGE_LOOKUP;
  46506                         BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
  46507                                             stage_id, &stage_fc));
  46508                         rv = _field_fb2_stage_lookup_reinit(unit, fc, stage_fc);
  46509                     }
  46510                 }
  46511             }
  46512 #endif
  46513         } else if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  46514 
  46515 #if defined(BCM_TOMAHAWK_SUPPORT)
  46516 
  46517             uint8 oldl2warm = 0;
  46518             rv = BCM_E_NONE;
  46519 
  46520             /* Tomahawk supports only level-2 for Warmboot */
  46521             if (fc->l2warm) {
  46522             do {
  46523                stage_id = _BCM_FIELD_STAGE_INGRESS;
  46524                BCM_IF_ERROR_RETURN
  46525                    (_field_stage_control_get(unit, stage_id, &stage_fc));
  46526 
  46527                if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_9) {
  46528                   rv = _bcm_field_th_stage_ingress_reinit(unit, fc, stage_fc);
  46529                } else {
  46530                   /* To account for start marker */
  46531                   fc->scache_pos += SOC_WB_SCACHE_CONTROL_SIZE;
  46532                   /* To account for end marker */
  46533                   fc->scache_pos += SOC_WB_SCACHE_CONTROL_SIZE;
  46534                }
  46535             } while (0);
  46536             do {
  46537                if (BCM_SUCCESS(rv) &&
  46538                    soc_feature(unit, soc_feature_field_multi_stage)) {
  46539                    stage_id = _BCM_FIELD_STAGE_EGRESS;
  46540 
  46541                    rv = _field_stage_control_get(unit, stage_id, &stage_fc);
  46542                    if (BCM_FAILURE(rv)) {
  46543                        _bcm_field_th_tlv_recovery_map_free(unit);
  46544                        return rv;
  46545                    }
  46546 
  46547                    oldl2warm = fc->l2warm;
  46548                    rv = _bcm_field_th_stage_egress_reinit(unit, fc, stage_fc);
  46549                    if ((rv == BCM_E_INTERNAL) &&
  46550                        (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) &&
  46551                        (fc->l2warm == 0) && (oldl2warm != 0)) {
  46552 
  46553                        _bcm_field_th_tlv_recovery_map_free(unit);
  46554 
  46555                        /* Stale scache in egress section */
  46556                        SOC_IF_ERROR_RETURN
  46557                            (soc_event_generate(unit,
  46558                                                SOC_SWITCH_EVENT_STABLE_ERROR,
  46559                                                SOC_STABLE_STALE,
  46560                                                SOC_STABLE_FIELD, 0));
  46561                        /* Clean up generated state and restart as Level 1 */
  46562                        BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc));
  46563                    }
  46564                 }
  46565 
  46566             } while (0);
  46567 
  46568             do {
  46569                if (BCM_SUCCESS(rv) &&
  46570                    soc_feature(unit, soc_feature_field_multi_stage)) {
  46571 
  46572                    stage_id = _BCM_FIELD_STAGE_LOOKUP;
  46573 
  46574                    rv = _field_stage_control_get(unit, stage_id, &stage_fc);
  46575                    if (BCM_FAILURE(rv)) {
  46576                        _bcm_field_th_tlv_recovery_map_free(unit);
  46577                        return rv;
  46578                    }
  46579 
  46580                    oldl2warm = fc->l2warm;
  46581 
  46582                    rv = _bcm_field_th_stage_lookup_reinit(unit, fc, stage_fc);
  46583 
  46584                    if ((rv == BCM_E_INTERNAL) &&
  46585                        (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) &&
  46586                        (fc->l2warm == 0) && (oldl2warm != 0)) {
  46587 
  46588                        _bcm_field_th_tlv_recovery_map_free(unit);
  46589 
  46590                        /* Stale scache in lookup section */
  46591                        SOC_IF_ERROR_RETURN
  46592                            (soc_event_generate(unit,
  46593                                                SOC_SWITCH_EVENT_STABLE_ERROR,
  46594                                                SOC_STABLE_STALE,
  46595                                                SOC_STABLE_FIELD, 0));
  46596 
  46597                        /* Clean up generated state and restart as Level 1 */
  46598                        BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc));
  46599                    }
  46600                 }
  46601             } while(0);
  46602 
  46603             do {
  46604                 if (BCM_SUCCESS(rv) &&
  46605                     soc_feature(unit, soc_feature_field_compression)) {
  46606                     stage_id = _BCM_FIELD_STAGE_CLASS;
  46607                     rv = _field_stage_control_get(unit, stage_id, &stage_fc);
  46608                    if (BCM_FAILURE(rv)) {
  46609                        _bcm_field_th_tlv_recovery_map_free(unit);
  46610                        return rv;
  46611                    }
  46612                     if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_10) {
  46613                          rv = _bcm_field_th_stage_class_reinit(unit,
  46614                                                                fc, stage_fc);
  46615                      }
  46616                 }
  46617             } while(0);
  46618 
  46619             do {
  46620                 if (BCM_SUCCESS(rv) &&
  46621                     soc_feature(unit, soc_feature_field_exact_match_support)) {
  46622                     stage_id = _BCM_FIELD_STAGE_EXACTMATCH;
  46623                     rv = _field_stage_control_get(unit, stage_id, &stage_fc);
  46624                     if (BCM_FAILURE(rv)) {
  46625                         _bcm_field_th_tlv_recovery_map_free(unit);
  46626                         return rv;
  46627                     }
  46628                     if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_10) {
  46629                         rv = _bcm_field_th_stage_em_reinit(unit,
  46630                                                           fc, stage_fc);
  46631                     }
  46632                 }
  46633             } while(0);
  46634 
  46635 #if defined(BCM_HELIX5_SUPPORT)
  46636             do {
  46637                 if (BCM_SUCCESS(rv) &&
  46638                     soc_feature(unit, soc_feature_field_flowtracker_support)) {
  46639                     stage_id = _BCM_FIELD_STAGE_FLOWTRACKER;
  46640                     rv = _field_stage_control_get(unit, stage_id, &stage_fc);
  46641                     if (BCM_FAILURE(rv)) {
  46642                         _bcm_field_th_tlv_recovery_map_free(unit);
  46643                         return rv;
  46644                     }
  46645                     if ((fc->wb_recovered_version) >= BCM_FIELD_WB_VERSION_1_26) {
  46646                         rv = _bcm_field_stage_ft_reinit(unit, fc, stage_fc);
  46647                     }
  46648                 }
  46649             } while(0);
  46650 #endif
  46651 
  46652             _bcm_field_th_tlv_recovery_map_free(unit);
  46653 
  46654             } else {
  46655                 LOG_WARN(BSL_LS_BCM_FP,
  46656                  (BSL_META_U(unit,
  46657                   "Warning: Level-1 not supported for FP Warmboot\n")));
  46658             }
  46659 #endif
  46660         } else if (SOC_IS_TRIUMPH(unit)
  46661                    || SOC_IS_VALKYRIE(unit)
  46662                    || SOC_IS_ENDURO(unit)
  46663                    || SOC_IS_TRIUMPH2(unit)
  46664                    || SOC_IS_APOLLO(unit)
  46665                    || SOC_IS_VALKYRIE2(unit)
  46666                    || SOC_IS_SC_CQ(unit) || SOC_IS_HURRICANEX(unit)
  46667                    || SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit)
  46668                    || SOC_IS_GREYHOUND(unit)
  46669                    || SOC_IS_GREYHOUND2(unit)
  46670                    ) {
  46671 #if defined(BCM_TRX_SUPPORT)
  46672             uint8 oldl2warm = 0;
  46673             stage_id = _BCM_FIELD_STAGE_INGRESS;
  46674             BCM_IF_ERROR_RETURN
  46675                 (_field_stage_control_get(unit, stage_id, &stage_fc));
  46676             rv = _field_tr2_stage_ingress_reinit(unit, fc, stage_fc);
  46677             if ((rv == BCM_E_INTERNAL) &&
  46678                 (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) &&
  46679                 (fc->l2warm == 0)) {
  46680                 /* Stale scache in ingress section */
  46681                 SOC_IF_ERROR_RETURN
  46682                     (soc_event_generate(unit, SOC_SWITCH_EVENT_STABLE_ERROR,
  46683                                         SOC_STABLE_STALE, SOC_STABLE_FIELD, 0));
  46684                 /* Clean up generated state and restart as Level 1 */
  46685                 BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc));
  46686                 rv = _field_tr2_stage_ingress_reinit(unit, fc, stage_fc);
  46687             }
  46688             do {
  46689                if (BCM_SUCCESS(rv)) {
  46690                    stage_id = _BCM_FIELD_STAGE_EGRESS;
  46691 
  46692 #if defined(BCM_HURRICANE1_SUPPORT)
  46693                    /* Egress Stage might not be available for some devices
  46694                       (hurricane) */
  46695                    if (SOC_IS_HURRICANE(unit) ||
  46696                         (!soc_feature(unit, soc_feature_field_multi_stage))) {
  46697                        LOG_VERBOSE(BSL_LS_BCM_FP,
  46698                                    (BSL_META_U(unit,
  46699                                   "\t#Skipping Egress Stage(NotAvailable)\n")));
  46700                        rv = BCM_E_NONE;
  46701                        break;
  46702                    }
  46703 #endif /* BCM_HURRICANE1_SUPPORT */
  46704                    rv = _field_stage_control_get(unit, stage_id, &stage_fc);
  46705                    if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_UNAVAIL)) {
  46706                         /* Cannot return as LOOKUP+External Stages need to be
  46707                            checked yet */
  46708                         rv = BCM_E_NONE;
  46709                         break;
  46710                    }
  46711                    BCM_IF_ERROR_RETURN(rv);
  46712                    oldl2warm = fc->l2warm;
  46713                    rv = _field_tr2_stage_egress_reinit(unit, fc, stage_fc);
  46714                    if ((rv == BCM_E_INTERNAL) &&
  46715                        (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) &&
  46716                        (fc->l2warm == 0) && (oldl2warm != 0)) {
  46717                        /* Stale scache in egress section */
  46718                        SOC_IF_ERROR_RETURN
  46719                            (soc_event_generate(unit,
  46720                                                SOC_SWITCH_EVENT_STABLE_ERROR,
  46721                                                SOC_STABLE_STALE,
  46722                                                SOC_STABLE_FIELD, 0));
  46723                        /* Clean up generated state and restart as Level 1 */
  46724                        BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc));
  46725                        stage_id = _BCM_FIELD_STAGE_INGRESS;
  46726                        BCM_IF_ERROR_RETURN
  46727                          (_field_stage_control_get(unit, stage_id, &stage_fc));
  46728                        rv = _field_tr2_stage_ingress_reinit(unit, fc,
  46729                                                             stage_fc);
  46730                        if (BCM_SUCCESS(rv)) {
  46731                            stage_id = _BCM_FIELD_STAGE_EGRESS;
  46732                            BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
  46733                                                stage_id, &stage_fc));
  46734                            rv = _field_tr2_stage_egress_reinit(unit, fc,
  46735                                                                stage_fc);
  46736                        }
  46737                    }
  46738                }
  46739             } while (0);
  46740             do {
  46741                if (BCM_SUCCESS(rv)) {
  46742                    stage_id = _BCM_FIELD_STAGE_LOOKUP;
  46743 #if defined(BCM_HURRICANE1_SUPPORT)
  46744                    if (SOC_IS_HURRICANE(unit) ||
  46745                         (!soc_feature(unit, soc_feature_field_multi_stage))) {
  46746                        LOG_VERBOSE(BSL_LS_BCM_FP,
  46747                                    (BSL_META_U(unit,
  46748                                                "\t#Skipping Lookup Stage(NotAvailable)\n")));
  46749                        rv = BCM_E_NONE;
  46750                        break;
  46751                    }
  46752 #endif /* BCM_HURRICANE1_SUPPORT */
  46753                    rv = _field_stage_control_get(unit, stage_id, &stage_fc);
  46754                    if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_UNAVAIL)) {
  46755                         /* Cannot return as External Stages need to be checked*/
  46756                         rv = BCM_E_NONE;
  46757                         break;
  46758                    }
  46759                    BCM_IF_ERROR_RETURN(rv);
  46760                    oldl2warm = fc->l2warm;
  46761 
  46762 #if defined(BCM_TRIDENT2_SUPPORT)
  46763                    if (SOC_IS_TD2_TT2(unit)) {
  46764                        rv = _bcm_field_td2_stage_lookup_reinit(unit, fc, stage_fc);
  46765                    } else
  46766 #endif
  46767 #if defined(BCM_KATANA2_SUPPORT)
  46768                    if (SOC_IS_KATANA2(unit)) {
  46769                        rv = _field_kt2_stage_lookup_reinit(unit, fc, stage_fc);
  46770                    } else
  46771 #endif
  46772                    {
  46773                        rv = _field_tr2_stage_lookup_reinit(unit, fc, stage_fc);
  46774                    }
  46775 
  46776                    if ((rv == BCM_E_INTERNAL) &&
  46777                        (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) &&
  46778                        (fc->l2warm == 0) && (oldl2warm != 0)) {
  46779                        /* Stale scache in lookup section */
  46780                        SOC_IF_ERROR_RETURN
  46781                            (soc_event_generate(unit,
  46782                                                SOC_SWITCH_EVENT_STABLE_ERROR,
  46783                                                SOC_STABLE_STALE,
  46784                                                SOC_STABLE_FIELD, 0));
  46785                        /* Clean up generated state and restart as Level 1 */
  46786                        BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc));
  46787                        stage_id = _BCM_FIELD_STAGE_INGRESS;
  46788                        BCM_IF_ERROR_RETURN
  46789                           (_field_stage_control_get(unit, stage_id, &stage_fc));
  46790                        rv = _field_tr2_stage_ingress_reinit(unit, fc, stage_fc);
  46791                        if (BCM_SUCCESS(rv)) {
  46792                            stage_id = _BCM_FIELD_STAGE_EGRESS;
  46793                            BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
  46794                                                stage_id, &stage_fc));
  46795                            rv = _field_tr2_stage_egress_reinit(unit, fc,
  46796                                                                stage_fc);
  46797                        }
  46798                        if (BCM_SUCCESS(rv)) {
  46799                            stage_id = _BCM_FIELD_STAGE_LOOKUP;
  46800                            BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
  46801                                                stage_id, &stage_fc));
  46802 #if defined(BCM_TRIDENT2_SUPPORT)
  46803                            if (SOC_IS_TD2_TT2(unit)) {
  46804                                rv = _bcm_field_td2_stage_lookup_reinit(unit, fc, stage_fc);
  46805                            } else
  46806 #endif
  46807                            {
  46808                                rv = _field_tr2_stage_lookup_reinit(unit, fc, stage_fc);
  46809                            }
  46810                        }
  46811                    }
  46812                }
  46813             } while(0);
  46814             do {
  46815             if (BCM_SUCCESS(rv) && soc_feature(unit, soc_feature_esm_support)) {
  46816                 stage_id = _BCM_FIELD_STAGE_EXTERNAL;
  46817                 rv = _field_stage_control_get(unit, stage_id, &stage_fc);
  46818                 if (rv == BCM_E_UNAVAIL) {
  46819                     /* External stage supported but not configured => Skip it */
  46820 
  46821                     rv = BCM_E_NONE;
  46822                     break;
  46823                 }
  46824                 BCM_IF_ERROR_RETURN(rv);
  46825 
  46826                 oldl2warm = fc->l2warm;
  46827                 rv = _field_tr2_stage_external_reinit(unit, fc, stage_fc);
  46828                 if ((rv == BCM_E_INTERNAL) &&
  46829                     (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) &&
  46830                     (fc->l2warm == 0) && (oldl2warm != 0)) {
  46831                     /* Stale scache in lookup section */
  46832                     SOC_IF_ERROR_RETURN
  46833                         (soc_event_generate(unit, SOC_SWITCH_EVENT_STABLE_ERROR,
  46834                                             SOC_STABLE_STALE,
  46835                                             SOC_STABLE_FIELD, 0));
  46836                     /* Clean up generated state and restart as Level 1 */
  46837                     BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc));
  46838                     stage_id = _BCM_FIELD_STAGE_INGRESS;
  46839                     BCM_IF_ERROR_RETURN
  46840                         (_field_stage_control_get(unit, stage_id, &stage_fc));
  46841                     rv = _field_tr2_stage_ingress_reinit(unit, fc, stage_fc);
  46842                     if (BCM_SUCCESS(rv)) {
  46843                         stage_id = _BCM_FIELD_STAGE_EGRESS;
  46844                         BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
  46845                                             stage_id, &stage_fc));
  46846                         rv = _field_tr2_stage_egress_reinit(unit, fc, stage_fc);
  46847                     }
  46848                     if (BCM_SUCCESS(rv)) {
  46849                         stage_id = _BCM_FIELD_STAGE_LOOKUP;
  46850                         BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
  46851                                             stage_id, &stage_fc));
  46852 #if defined(BCM_TRIDENT2_SUPPORT)
  46853                         if (SOC_IS_TD2_TT2(unit)) {
  46854                             rv = _bcm_field_td2_stage_lookup_reinit(unit, fc, stage_fc);
  46855                         } else
  46856 #endif
  46857                         {
  46858                             rv = _field_tr2_stage_lookup_reinit(unit, fc, stage_fc);
  46859                         }
  46860                     }
  46861                     if (BCM_SUCCESS(rv)) {
  46862                         stage_id = _BCM_FIELD_STAGE_EXTERNAL;
  46863                         BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
  46864                                             stage_id, &stage_fc));
  46865                         rv = _field_tr2_stage_external_reinit(unit, fc, stage_fc);
  46866                     }
  46867                 }
  46868             }
  46869             }while(0);
  46870 #endif /* BCM_TRX_SUPPORT */
  46871         } else if (SOC_IS_TRIUMPH3(unit)) {
  46872 #if defined(BCM_TRIUMPH3_SUPPORT)
  46873             uint8 oldl2warm = 0;
  46874             stage_id = _BCM_FIELD_STAGE_INGRESS;
  46875             BCM_IF_ERROR_RETURN
  46876                 (_field_stage_control_get(unit, stage_id, &stage_fc));
  46877             rv = _bcm_field_tr3_stage_ingress_reinit(unit, fc, stage_fc);
  46878             if ((rv == BCM_E_INTERNAL) &&
  46879                 (fc->scache_size[_FIELD_SCACHE_PART_0] > 0)
  46880                 && (fc->l2warm == 0)) {
  46881                 /* Stale scache in ingress section */
  46882                 SOC_IF_ERROR_RETURN
  46883                     (soc_event_generate(unit,
  46884                                         SOC_SWITCH_EVENT_STABLE_ERROR,
  46885                                         SOC_STABLE_STALE,
  46886                                         SOC_STABLE_FIELD,
  46887                                         0
  46888                                         )
  46889                     );
  46890                 /* Clean up generated state and restart as Level 1 */
  46891                 BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc));
  46892                 rv = _bcm_field_tr3_stage_ingress_reinit(unit, fc, stage_fc);
  46893             }
  46894             do {
  46895                 if (BCM_SUCCESS(rv)) {
  46896                     stage_id = _BCM_FIELD_STAGE_EGRESS;
  46897                     rv = _field_stage_control_get(unit, stage_id, &stage_fc);
  46898                     if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_UNAVAIL)) {
  46899                         /* Cannot return as LOOKUP+External Stages need to be
  46900                          * checked yet.
  46901                          */
  46902                         rv = BCM_E_NONE;
  46903                         break;
  46904                     }
  46905                     BCM_IF_ERROR_RETURN(rv);
  46906                     oldl2warm = fc->l2warm;
  46907                     rv = _field_tr2_stage_egress_reinit(unit, fc, stage_fc);
  46908                     if ((rv == BCM_E_INTERNAL) &&
  46909                         (fc->scache_size[_FIELD_SCACHE_PART_0] > 0)
  46910                         && (fc->l2warm == 0) && (oldl2warm != 0)) {
  46911                         /* Stale scache in egress section */
  46912                         SOC_IF_ERROR_RETURN
  46913                             (soc_event_generate(unit,
  46914                                                 SOC_SWITCH_EVENT_STABLE_ERROR,
  46915                                                 SOC_STABLE_STALE,
  46916                                                 SOC_STABLE_FIELD,
  46917                                                 0
  46918                                                 )
  46919                             );
  46920                         /* Clean up generated state and restart as Level 1 */
  46921                         BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc));
  46922                         stage_id = _BCM_FIELD_STAGE_INGRESS;
  46923                         BCM_IF_ERROR_RETURN
  46924                             (_field_stage_control_get(unit,
  46925                                                       stage_id,
  46926                                                       &stage_fc)
  46927                             );
  46928                         rv = _field_tr2_stage_ingress_reinit
  46929                                 (unit,
  46930                                  fc,
  46931                                  stage_fc
  46932                                  );
  46933                         if (BCM_SUCCESS(rv)) {
  46934                             stage_id = _BCM_FIELD_STAGE_EGRESS;
  46935                             BCM_IF_ERROR_RETURN
  46936                                 (_field_stage_control_get(unit,
  46937                                                           stage_id,
  46938                                                           &stage_fc
  46939                                                           )
  46940                                 );
  46941                             rv = _field_tr2_stage_egress_reinit(unit,
  46942                                                                 fc,
  46943                                                                 stage_fc);
  46944                         }
  46945                     }
  46946                 }
  46947             } while (0);
  46948             do {
  46949                 if (BCM_SUCCESS(rv)) {
  46950                     stage_id = _BCM_FIELD_STAGE_LOOKUP;
  46951                     rv = _field_stage_control_get(unit, stage_id, &stage_fc);
  46952                     if ((rv == BCM_E_NOT_FOUND) || (rv == BCM_E_UNAVAIL)) {
  46953                         /* Cannot return as External Stages need to be checked*/
  46954                         rv = BCM_E_NONE;
  46955                         break;
  46956                     }
  46957                     BCM_IF_ERROR_RETURN(rv);
  46958                     oldl2warm = fc->l2warm;
  46959                     rv = _bcm_field_tr3_stage_lookup_reinit(unit, fc, stage_fc);
  46960                     if ((rv == BCM_E_INTERNAL) &&
  46961                         (fc->scache_size[_FIELD_SCACHE_PART_0] > 0)
  46962                         && (fc->l2warm == 0) && (oldl2warm != 0)) {
  46963                         /* Stale scache in lookup section */
  46964                         SOC_IF_ERROR_RETURN
  46965                             (soc_event_generate(unit,
  46966                                                 SOC_SWITCH_EVENT_STABLE_ERROR,
  46967                                                 SOC_STABLE_STALE,
  46968                                                 SOC_STABLE_FIELD, 0
  46969                                                 )
  46970                             );
  46971                         /* Clean up generated state and restart as Level 1 */
  46972                         BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc));
  46973                         stage_id = _BCM_FIELD_STAGE_INGRESS;
  46974                         BCM_IF_ERROR_RETURN
  46975                             (_field_stage_control_get(unit,
  46976                                                       stage_id,
  46977                                                       &stage_fc
  46978                                                       )
  46979                             );
  46980                         rv = _bcm_field_tr3_stage_ingress_reinit(unit, fc, stage_fc);
  46981                         if (BCM_SUCCESS(rv)) {
  46982                             stage_id = _BCM_FIELD_STAGE_EGRESS;
  46983                             BCM_IF_ERROR_RETURN
  46984                                 (_field_stage_control_get(unit,
  46985                                                           stage_id,
  46986                                                           &stage_fc
  46987                                                           )
  46988                                 );
  46989                             rv = _field_tr2_stage_egress_reinit(unit,
  46990                                                                 fc,
  46991                                                                 stage_fc
  46992                                                                 );
  46993                         }
  46994                         if (BCM_SUCCESS(rv)) {
  46995                             stage_id = _BCM_FIELD_STAGE_LOOKUP;
  46996                             BCM_IF_ERROR_RETURN
  46997                                 (_field_stage_control_get(unit,
  46998                                                           stage_id,
  46999                                                           &stage_fc
  47000                                                           )
  47001                                 );
  47002                             rv = _bcm_field_tr3_stage_lookup_reinit(unit,
  47003                                                                 fc,
  47004                                                                 stage_fc
  47005                                                                 );
  47006                         }
  47007                     }
  47008                 }
  47009             } while(0);
  47010             /* Warm boot level 1 and level 2 recovery for TR3 FP ESM */
  47011             do {
  47012             if (BCM_SUCCESS(rv) && soc_feature(unit, soc_feature_esm_support)) {
  47013                 stage_id = _BCM_FIELD_STAGE_EXTERNAL;
  47014                 rv = _field_stage_control_get(unit, stage_id, &stage_fc);
  47015                 if (rv == BCM_E_UNAVAIL) {
  47016                     /* External stage supported but not configured => Skip it */
  47017                     rv = BCM_E_NONE;
  47018                     break;
  47019                 }
  47020                 BCM_IF_ERROR_RETURN(rv);
  47021 
  47022                 oldl2warm = fc->l2warm;
  47023                 rv = _bcm_field_tr3_stage_external_reinit(unit, fc, stage_fc);
  47024                 if ((rv == BCM_E_INTERNAL) &&
  47025                     (fc->scache_size[_FIELD_SCACHE_PART_0] > 0) &&
  47026                     (fc->l2warm == 0) && (oldl2warm != 0)) {
  47027                     /* Stale scache in lookup section */
  47028                     SOC_IF_ERROR_RETURN
  47029                         (soc_event_generate(unit, SOC_SWITCH_EVENT_STABLE_ERROR,
  47030                                             SOC_STABLE_STALE,
  47031                                             SOC_STABLE_FIELD, 0));
  47032                     /* Clean up generated state and restart as Level 1 */
  47033                     BCM_IF_ERROR_RETURN(_field_state_cleanup(unit, fc));
  47034                     stage_id = _BCM_FIELD_STAGE_INGRESS;
  47035                     BCM_IF_ERROR_RETURN
  47036                         (_field_stage_control_get(unit, stage_id, &stage_fc));
  47037                     rv = _bcm_field_tr3_stage_ingress_reinit(unit, fc, stage_fc);
  47038                     if (BCM_SUCCESS(rv)) {
  47039                         stage_id = _BCM_FIELD_STAGE_EGRESS;
  47040                         BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
  47041                                             stage_id, &stage_fc));
  47042                         rv = _bcm_field_tr3_stage_egress_reinit(unit, fc, stage_fc);
  47043                     }
  47044                     if (BCM_SUCCESS(rv)) {
  47045                         stage_id = _BCM_FIELD_STAGE_LOOKUP;
  47046                         BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
  47047                                             stage_id, &stage_fc));
  47048                         rv = _bcm_field_tr3_stage_lookup_reinit(unit, fc, stage_fc);
  47049                     }
  47050                     if (BCM_SUCCESS(rv)) {
  47051                         stage_id = _BCM_FIELD_STAGE_EXTERNAL;
  47052                         BCM_IF_ERROR_RETURN(_field_stage_control_get(unit,
  47053                                             stage_id, &stage_fc));
  47054                         rv = _bcm_field_tr3_stage_external_reinit(unit, fc, stage_fc);
  47055                     }
  47056                 }
  47057             }
  47058             } while(0);
  47059 #endif
  47060         }
  47061 
  47062         if (BCM_FAILURE(rv)) {
  47063             _field_stage_delete(unit, fc, stage_fc);
  47064             return (rv);
  47065         }
  47066 
  47067         /* During Warm Boot upgrade partitions not existed in previous code
  47068            version but need to be existed , must be created now */
  47069 
  47070         if (fc->l2warm) {
  47071 #ifdef BCM_TOMAHAWK_SUPPORT
  47072             if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  47073                 BCM_IF_ERROR_RETURN(_bcm_field_scache_th_pointer_realloc(unit,
  47074                                                                          fc));
  47075             } else
  47076 #endif
  47077             {
  47078                 BCM_IF_ERROR_RETURN(_field_scache_pointer_init_wb(unit, fc));
  47079             }
  47080 
  47081         }
  47082     }
  47083 #endif
  47084     if (soc_feature(unit, soc_feature_epc_linkflap_recover)) {
  47085         bcm_esw_linkscan_register(unit, _bcm_field_linkscan_update);
  47086     }
  47087 
  47088     _field_control[unit]->init = TRUE;
  47089 
  47090 /* EM COS SW WAR for TH3 */
  47091 #if defined(BCM_TOMAHAWK3_SUPPORT)
  47092     if((soc_feature(unit, soc_feature_sw_mmu_flush_rqe_operation)) &&
  47093        (soc_feature(unit, soc_feature_field_exact_match_support)) &&
  47094        (!(SOC_WARM_BOOT(unit)))) {
  47095         rv = _bcm_field_th3_internal_em_group_create(unit,
  47096                                              fc);
  47097         if (BCM_FAILURE(rv)) {
  47098             LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
  47099                             "FP(unit %d) Error:_field_internal_em_group_create =%d"
  47100                             "\n"), unit, rv));
  47101             return (rv);
  47102         }
  47103 
  47104     }
  47105 #endif
  47106     return (BCM_E_NONE);
  47107 }
  47108 
  47109 /*
  47110  * Function: _bcm_esw_field_detach
  47111  *
  47112  * Purpose:
  47113  *     Free resources associated with field module
  47114  *
  47115  * Parameters:
  47116  *     unit - BCM device number
  47117  *
  47118  * Returns:
  47119  *     BCM_E_INIT - BCM Unit not initialized.
  47120  *     BCM_E_XXX  - Error code from bcm_field_group_destroy() or
  47121  *                  bcm_field_entry_destroy_all().
  47122  *     BCM_E_NONE - Success
  47123  */
  47124 
  47125 int
  47126 _bcm_esw_field_detach(int unit)
  47127 {
  47128     _field_control_t    *fc;
  47129     _field_group_t      *fg;
  47130     int                  rv = BCM_E_NONE;
  47131     int                  id = 0;
  47132     _field_egr_ports_recovery_t *f_egr_recovery = NULL;
  47133 
  47134     LOG_DEBUG(BSL_LS_BCM_FP,
  47135               (BSL_META_U(unit,
  47136                           "FP(unit %d) vverb: bcm_field_detach()\n"),
  47137                unit));
  47138 
  47139     FP_LOCK(unit);
  47140     fc = _field_control[unit];
  47141     if (NULL == fc) {
  47142         FP_UNLOCK(unit);
  47143         return (BCM_E_NONE);
  47144     }
  47145 
  47146     /*
  47147      * De-initialize the field module as all
  47148      * the componenets are getting detached
  47149      */
  47150     _field_control[unit]->init = FALSE;
  47151 
  47152     soc_counter_extra_unregister(unit, _bcm_esw_fp_counters_collect);
  47153     /* Unregister counter collection callback. */
  47154 
  47155 
  47156     /* Unregister link scan updates */
  47157     if (soc_feature(unit, soc_feature_epc_linkflap_recover)) {
  47158         rv = bcm_esw_linkscan_unregister(unit, _bcm_field_linkscan_update);
  47159         if (rv != BCM_E_NONE) {
  47160             LOG_VERBOSE(BSL_LS_BCM_FP,
  47161               (BSL_META_U(unit,
  47162                           "FP(unit %d) vverb:Field Module not registered to LinkScan\n"),
  47163                unit));
  47164         }
  47165     }
  47166 
  47167     /* Destroy all entries in unit. */
  47168     rv = bcm_esw_field_entry_destroy_all(unit);
  47169     if (BCM_FAILURE(rv)) {
  47170         FP_UNLOCK(unit);
  47171         return (rv);
  47172     }
  47173 
  47174     /* EM COS SW WAR for TH3 */
  47175 #if defined(BCM_TOMAHAWK3_SUPPORT)
  47176     if (soc_feature(unit, soc_feature_sw_mmu_flush_rqe_operation)) {
  47177         rv = _field_group_get(unit, _FP_INTERNAL_RESERVED_EM_ID, &fg);
  47178         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
  47179             FP_UNLOCK(unit);
  47180             LOG_ERROR(BSL_LS_BCM_FP,
  47181                  (BSL_META_U(unit,
  47182                  "FP(unit %d) Error: Failed to get Group=%d\n"),
  47183                  unit, _FP_INTERNAL_RESERVED_EM_ID));
  47184             return (rv);
  47185         }
  47186         rv =  bcm_esw_field_entry_destroy(unit, _FP_INTERNAL_RESERVED_EM_ID);
  47187         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND) ) {
  47188             LOG_ERROR(BSL_LS_BCM_FP,
  47189                  (BSL_META_U(unit,
  47190                  "FP(unit %d) Error: Failed to destroy entry=%d\n"),
  47191                  unit, _FP_INTERNAL_RESERVED_EM_ID));
  47192             FP_UNLOCK(unit);
  47193             return (rv);
  47194         }
  47195     }
  47196 #endif
  47197 
  47198     /* Destroy all statistics entities. */
  47199     rv = _field_stat_destroy_all(unit);
  47200     if (BCM_FAILURE(rv)) {
  47201         FP_UNLOCK(unit);
  47202         return (rv);
  47203     }
  47204 
  47205     /* Destroy all policers. */
  47206     rv = bcm_esw_policer_destroy_all(unit);
  47207     if (BCM_FAILURE(rv)) {
  47208         FP_UNLOCK(unit);
  47209         return (rv);
  47210     }
  47211 
  47212     /* Destroy all groups in unit. */
  47213     fg = fc->groups;
  47214 
  47215     while (fg != NULL) {
  47216         _field_group_t *fg_next = NULL;
  47217 
  47218         fg_next = fg->next;
  47219         /*
  47220          * Retaining ExactMatch groups during bcm_field_init for retaining Sticky ExactMatch stage.
  47221          */
  47222         if ((fc->flags & _FP_EXACTMATCH_STAGE_SKIP_DETACH) &&
  47223             (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id)) {
  47224             fg = fg_next;
  47225             continue;
  47226         }
  47227 
  47228         rv = bcm_esw_field_group_destroy(unit, fg->gid);
  47229         if (BCM_FAILURE(rv)) {
  47230             FP_UNLOCK(unit);
  47231             return (rv);
  47232         }
  47233         fg = fg_next;
  47234     }
  47235 
  47236     /* Destroy all hints */
  47237     for (id = _FP_HINT_ID_BASE; id < _FP_HINT_ID_MAX; id++) {
  47238         if (_FP_HINTID_BMP_TEST(fc->hintid_bmp, id)) {
  47239             rv = bcm_esw_field_hints_destroy (unit, id);
  47240             if (BCM_FAILURE(rv)) {
  47241                 FP_UNLOCK(unit);
  47242                 return (rv);
  47243             }
  47244         }
  47245     }
  47246 
  47247     /* Device specific detach */
  47248     if (NULL != fc->functions.fp_detach) {
  47249         rv = fc->functions.fp_detach(unit, fc);
  47250         if (BCM_FAILURE(rv)) {
  47251             FP_UNLOCK(unit);
  47252             return (rv);
  47253         }
  47254     }
  47255 
  47256     if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  47257         /* Invoke tomahawk stage delete routine.*/
  47258         rv = fc->stage_func.fp_stages_delete(unit, fc);
  47259     } else {
  47260         /* Destroy a Unit's stages*/
  47261         rv = _field_stages_destroy(unit, fc);
  47262     }
  47263     if (BCM_FAILURE(rv)) {
  47264         FP_UNLOCK(unit);
  47265         return (rv);
  47266     }
  47267 #if defined (BCM_APACHE_SUPPORT)
  47268     if (soc_feature(unit, soc_feature_fp_based_sat)) {
  47269         rv = bcm_esw_field_sat_macsa_delete_all(unit);
  47270         if (BCM_FAILURE(rv)) {
  47271             FP_UNLOCK(unit);
  47272             return (rv);
  47273         }
  47274     }
  47275 #endif
  47276 
  47277     if (soc_feature(unit, soc_feature_epc_linkflap_recover)) {
  47278         _field_egr_ports_recovery_control_get (unit, &f_egr_recovery);
  47279         _field_egr_ports_recovery_control_free (unit, f_egr_recovery);
  47280     }
  47281 
  47282 #if defined(BCM_TRX_SUPPORT)
  47283    /* Destroy global redirection action profile. */
  47284     soc_profile_mem_destroy(unit, &fc->redirect_profile);
  47285 
  47286 #if defined(BCM_TOMAHAWK3_SUPPORT)
  47287     /* Destroy global redirection action profile. */
  47288     soc_profile_mem_destroy(unit, &fc->redirect_profile1);
  47289     /* Destroy delayed drop action profile. */
  47290     soc_profile_mem_destroy(unit, &fc->ddrop_profile);
  47291     /* Destroy delayed redirection action profile. */
  47292     soc_profile_mem_destroy(unit, &fc->dredirect_profile);
  47293 #endif
  47294 #endif
  47295 
  47296 #if defined (BCM_TOMAHAWK_SUPPORT)
  47297     /* Destroy HiGiG2 extended header mask profile. */
  47298     if (soc_feature(unit, soc_feature_higig_lookup) && SOC_IS_TOMAHAWKX(unit))
  47299     {
  47300        soc_profile_mem_destroy(unit, &fc->eh_mask_profile);
  47301     }
  47302 #endif
  47303 
  47304     _field_control_free(unit, fc);
  47305     FP_UNLOCK(unit);
  47306 
  47307     return (BCM_E_NONE);
  47308 }
  47309 
  47310 #if defined(BCM_TRX_SUPPORT)
  47311 
  47312 /*
  47313  * Function: _bcm_field_flex_port_detach
  47314  *
  47315  * Purpose:
  47316  *    Detached Flexed ports from Field Group.
  47317  *
  47318  * Parameters:
  47319  *     unit  - BCM device number
  47320  *     port  - Port to be cleared
  47321  *
  47322  * Returns:
  47323  *     BCM_E_XXX  - Error code from _bcm_field_pfs_entry_clear() or
  47324  *                  _field_control_get().
  47325  */
  47326 
  47327 int
  47328 _bcm_field_flex_port_detach(int unit, bcm_port_t port)
  47329 {
  47330     _field_control_t        *fc = NULL;
  47331     _field_group_t          *fg = NULL;
  47332     int                     rv = BCM_E_NONE;
  47333     _field_slice_t          *fs = NULL;
  47334 
  47335     FP_LOCK(unit);
  47336     rv = _field_control_get(unit, &fc);
  47337     if (BCM_FAILURE(rv)) {
  47338         goto cleanup;
  47339     }
  47340 
  47341     for (fg = fc->groups; fg != NULL; fg = fg->next) {
  47342         if ((fg->flags & _FP_GROUP_PER_PORT_OR_PBMP)) {
  47343            if (BCM_PBMP_MEMBER(fg->pbmp,port)) {
  47344                 rv = _bcm_field_pfs_entry_clear(unit,
  47345                                                 fg, port);
  47346                 if (BCM_FAILURE(rv)) {
  47347                     goto cleanup;
  47348                 }
  47349            }
  47350         } else {
  47351             if(BCM_PBMP_MEMBER(fg->pbmp, port)) {
  47352                 BCM_PBMP_PORT_REMOVE(fg->pbmp, port);
  47353                 if (fg->slices != NULL) {
  47354                    for (fs = fg->slices; fs != NULL; fs = fs->next) {
  47355                        BCM_PBMP_PORT_REMOVE(fs->pbmp, port);
  47356                    }
  47357                 }
  47358             }
  47359 
  47360         }
  47361     }
  47362 
  47363 cleanup:
  47364     FP_UNLOCK(unit);
  47365     return (rv);
  47366 }
  47367 
  47368 /*
  47369  * Function: _bcm_field_flex_port_attach
  47370  *
  47371  * Purpose:
  47372  *    Detached Flexed ports from Field Group.
  47373  *
  47374  * Parameters:
  47375  *     unit  - BCM device number
  47376  *     port  - Port to be cleared
  47377  *
  47378  * Returns:
  47379  *     BCM_E_NONE - Success
  47380  */
  47381 
  47382 int
  47383 _bcm_field_flex_port_attach(int unit, bcm_port_t port)
  47384 {
  47385     _field_control_t *fc = NULL;
  47386     _field_group_t   *fg = NULL;
  47387     bcm_error_t       rv = BCM_E_NONE;
  47388     _field_slice_t *fs;
  47389 
  47390 #if defined(BCM_TOMAHAWK_SUPPORT)
  47391     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  47392         (!soc_feature(unit, soc_feature_field_multi_pipe_enhanced)) &&
  47393         (!soc_feature(unit, soc_feature_th3_style_fp)) &&
  47394         (!soc_feature(unit, soc_feature_td3_style_fp))) {
  47395         return BCM_E_NONE;
  47396     }
  47397 #endif
  47398 
  47399     FP_LOCK(unit);
  47400     rv = _field_control_get(unit, &fc);
  47401     if (BCM_FAILURE(rv)) {
  47402         goto cleanup;
  47403     }
  47404 
  47405     for (fg = fc->groups; fg != NULL; fg = fg->next) {
  47406         if (fg->flags & _FP_GROUP_PER_PORT_OR_PBMP) {
  47407             /* Ignore per port based groups*/
  47408             continue;
  47409         }
  47410         /* Ignore PBMP update for the stages other than Ingress */
  47411         if (fg->stage_id != _BCM_FIELD_STAGE_INGRESS) {
  47412             continue;
  47413         }
  47414         BCM_PBMP_PORT_ADD(fg->pbmp, port);
  47415         if (fg->slices != NULL) {
  47416             for (fs = fg->slices; fs != NULL; fs = fs->next) {
  47417                BCM_PBMP_PORT_ADD(fs->pbmp, port);
  47418             }
  47419         }
  47420     }
  47421 
  47422 cleanup:
  47423     FP_UNLOCK(unit);
  47424     return (rv);
  47425 }
  47426 
  47427 /*
  47428  * Function: _bcm_field_flex_port_update
  47429  *
  47430  * Purpose:
  47431  *    Routine is invoked after performing flex operation to
  47432  *    update the field module resources.
  47433  *
  47434  * Parameters:
  47435  *     unit  - BCM device number
  47436  *     detached_pbmp  - Ports detached after flex operation.
  47437  *     attached_pbmp  - Ports attached after flex operation.
  47438  *
  47439  * Returns:
  47440  *     BCM_E_xxx
  47441  */
  47442 
  47443 int
  47444 _bcm_field_flex_port_update(int unit,
  47445                             bcm_pbmp_t detached_pbmp,
  47446                             bcm_pbmp_t attached_pbmp)
  47447 {
  47448     _field_control_t *fc = NULL;
  47449     _field_group_t   *fg = NULL;
  47450     bcm_error_t       rv = BCM_E_NONE;
  47451 
  47452     if (!(SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_APACHE(unit) ||
  47453           SOC_IS_TOMAHAWK2(unit) || SOC_IS_TOMAHAWK3(unit) ||
  47454           soc_feature(unit, soc_feature_td3_style_fp))) {
  47455        return BCM_E_NONE;
  47456     }
  47457 
  47458     if (SOC_REG_IS_VALID(unit, IFP_GM_LOGICAL_TO_PHYSICAL_MAPPINGr)) {
  47459         /* considering only attached ports. */
  47460         if (BCM_PBMP_IS_NULL(attached_pbmp)) {
  47461             return BCM_E_NONE;
  47462         }
  47463     } else {
  47464         if (BCM_PBMP_IS_NULL(attached_pbmp) && BCM_PBMP_IS_NULL(detached_pbmp)) {
  47465             return BCM_E_NONE;
  47466         }
  47467     }
  47468 
  47469     FP_LOCK(unit);
  47470     rv = _field_control_get(unit, &fc);
  47471     if (BCM_FAILURE(rv)) {
  47472         goto cleanup;
  47473     }
  47474 
  47475     for (fg = fc->groups; fg != NULL; fg = fg->next) {
  47476         if (fg->flags & _FP_GROUP_PER_PORT_OR_PBMP) {
  47477             /* Ignore per port based groups*/
  47478             continue;
  47479         }
  47480 
  47481         /* Ignore PBMP update for the stages other than Ingress */
  47482         if (fg->stage_id != _BCM_FIELD_STAGE_INGRESS) {
  47483             continue;
  47484         }
  47485 
  47486         if ((SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_APACHE(unit)) &&
  47487             (BCM_FIELD_QSET_TEST(fg->qset,
  47488                                  bcmFieldQualifyInPorts) ||
  47489              BCM_FIELD_QSET_TEST(fg->qset,
  47490                                  bcmFieldQualifyInPort))) {
  47491            (void)_bcm_field_group_entry_port_update(unit, fg,
  47492                                                     detached_pbmp,
  47493                                                     attached_pbmp);
  47494         }
  47495 #if defined(BCM_TOMAHAWK_SUPPORT)
  47496         else if ((SOC_IS_TOMAHAWK2(unit) || SOC_IS_TOMAHAWK3(unit) ||
  47497                   soc_feature(unit, soc_feature_td3_style_fp)) &&
  47498                    BCM_FIELD_QSET_TEST(fg->qset,
  47499                                        bcmFieldQualifyInPorts)) {
  47500            (void)_bcm_field_group_entry_pipe_port_update(unit, fg,
  47501                                                          detached_pbmp,
  47502                                                          attached_pbmp);
  47503         }
  47504 #endif
  47505     }
  47506 
  47507 cleanup:
  47508     FP_UNLOCK(unit);
  47509     return (rv);
  47510 
  47511 }
  47512 
  47513 /*
  47514  * Function: _bcm_esw_field_group_ports_add
  47515  *
  47516  * Purpose:
  47517  *    Add ports to the specified group.
  47518  *
  47519  * Parameters:
  47520  *     unit  - BCM device number
  47521  *     group - Field group
  47522  *     pbmp  - Set of Ports
  47523  *
  47524  * Returns:
  47525  *     BCM_E_XXX  - Error code from _bcm_field_fb_group_install() or
  47526  *                  _field_group_get().
  47527  *     BCM_E_NONE - If ports are already part of the group.
  47528  */
  47529 
  47530 int
  47531 _bcm_esw_field_group_ports_add(
  47532     int unit,
  47533     bcm_field_group_t group,
  47534     bcm_pbmp_t pbmp)
  47535 {
  47536     _field_group_t          *fg = NULL;
  47537     bcm_port_t              port;
  47538     int                     rv = BCM_E_NONE;
  47539     bcm_pbmp_t              group_pbmp;
  47540     bcm_pbmp_t              add_pbmp;
  47541     bcm_pbmp_t              valid_pbmp;
  47542     bcm_pbmp_t              temp_pbmp;
  47543 
  47544     BCM_PBMP_CLEAR(valid_pbmp);
  47545 
  47546     /* check if the ports are valid */
  47547     rv = _bcm_field_valid_pbmp_get(unit, &valid_pbmp);
  47548     if (BCM_FAILURE(rv)) {
  47549         return rv;
  47550     }
  47551 
  47552     BCM_PBMP_ASSIGN(temp_pbmp, valid_pbmp);
  47553     BCM_PBMP_OR(temp_pbmp, pbmp);
  47554     if (BCM_PBMP_NEQ(valid_pbmp, temp_pbmp)) {
  47555          return BCM_E_PARAM;
  47556     }
  47557 
  47558     rv = _field_group_get(unit, group, &fg);
  47559     if (BCM_FAILURE(rv)){
  47560         return rv;
  47561     }
  47562 
  47563     if ((fg->flags & _FP_GROUP_PER_PORT_OR_PBMP)) {
  47564 
  47565         BCM_PBMP_CLEAR(add_pbmp);
  47566 
  47567     BCM_PBMP_ASSIGN(group_pbmp, fg->pbmp);
  47568     BCM_PBMP_OR(group_pbmp, pbmp);
  47569 
  47570         if (BCM_PBMP_EQ(group_pbmp, fg->pbmp)) {
  47571             /* Ports are already part of this group */
  47572             return BCM_E_NONE;
  47573         }
  47574         BCM_PBMP_ITER(pbmp, port) {
  47575             if((BCM_PBMP_MEMBER(fg->slices[0].pbmp, port))) {
  47576                 if(BCM_PBMP_MEMBER(fg->pbmp,port)) {
  47577                     continue;
  47578                 }
  47579               /* Port is part of another group in same slice */
  47580               LOG_DEBUG(BSL_LS_BCM_FP,
  47581                         (BSL_META_U(unit,
  47582                          "Port is present in another group in same slice \n")));
  47583               return BCM_E_PARAM;
  47584             }
  47585             BCM_PBMP_PORT_ADD(add_pbmp, port);
  47586         }
  47587         BCM_PBMP_OR(fg->pbmp, add_pbmp);
  47588         BCM_PBMP_OR(fg->slices[0].pbmp, add_pbmp);
  47589         rv = _bcm_field_fb_group_install(unit,fg);
  47590         if (BCM_FAILURE(rv)){
  47591             BCM_PBMP_REMOVE(fg->pbmp, add_pbmp);
  47592             BCM_PBMP_REMOVE(fg->slices[0].pbmp, add_pbmp);
  47593         }
  47594     } else {
  47595         rv = BCM_E_PARAM;
  47596         LOG_DEBUG(BSL_LS_BCM_FP,
  47597                   (BSL_META_U(unit,
  47598                               "Per port or Pbmp base Group is expected \n")));
  47599     }
  47600     return (rv);
  47601 
  47602 }
  47603 /*
  47604  * Function: _field_entry_update_ipbm
  47605  *
  47606  * Purpose:
  47607  *    Remove given pbmp from the entry IPBM
  47608  *
  47609  * Parameters:
  47610  *     unit  - BCM device number
  47611  *     f_ent - Field entry structure
  47612  *     pbmp  - Set of Ports
  47613  *
  47614  * Returns:
  47615  *     BCM_E_XXX  - Error code from internal functions
  47616  */
  47617 STATIC int
  47618 _field_entry_update_ipbm(
  47619       int unit,
  47620       _field_entry_t *f_ent,
  47621       bcm_pbmp_t pbmp)
  47622 {
  47623     int                           tcam_idx;
  47624     bcm_error_t                   rv = BCM_E_NONE;
  47625     bcm_error_t                   rv_internal = BCM_E_NONE;
  47626     bcm_pbmp_t                    ipbm;
  47627     bcm_pbmp_t                    ipbm_copy;
  47628     bcm_field_entry_t             backup_entry;
  47629     fp_global_mask_tcam_entry_t   ipbm_entry;
  47630 
  47631     if (!soc_mem_is_valid(unit, FP_GLOBAL_MASK_TCAMm)) {
  47632            return BCM_E_NONE;
  47633     }
  47634 
  47635     rv = _bcm_field_entry_tcam_idx_get(unit, f_ent, &tcam_idx);
  47636     BCM_IF_ERROR_RETURN(rv);
  47637 
  47638     BCM_PBMP_CLEAR(ipbm);
  47639     sal_memset(&ipbm_entry, 0, sizeof(fp_global_mask_tcam_entry_t));
  47640 
  47641     rv = READ_FP_GLOBAL_MASK_TCAMm(unit, MEM_BLOCK_ANY, tcam_idx,
  47642                                     &ipbm_entry);
  47643     BCM_IF_ERROR_RETURN(rv);
  47644 
  47645     soc_mem_pbmp_field_get(unit, FP_GLOBAL_MASK_TCAMm, &ipbm_entry, IPBMf,
  47646                            &ipbm);
  47647 
  47648     BCM_PBMP_ASSIGN(ipbm_copy, ipbm);
  47649     /* Removing pbmp from ipbm. ipbm &= ~pbmp */
  47650     BCM_PBMP_NEGATE(pbmp, pbmp);
  47651     BCM_PBMP_AND(ipbm, pbmp);
  47652 
  47653     if (BCM_PBMP_EQ(ipbm, ipbm_copy)) {
  47654         /* pbmp is not part of f_ent IPBM. Nothing to be done */
  47655         return BCM_E_NONE;
  47656     }
  47657 
  47658     rv = _field_internal_backup_entry_create(unit, f_ent->eid,
  47659                                              &backup_entry);
  47660     BCM_IF_ERROR_RETURN(rv);
  47661 
  47662     soc_mem_pbmp_field_set(unit, FP_GLOBAL_MASK_TCAMm, &ipbm_entry, IPBMf,
  47663                            &ipbm);
  47664     soc_mem_pbmp_field_set(unit, FP_GLOBAL_MASK_TCAMm, &ipbm_entry,
  47665                            IPBM_MASKf, &f_ent->pbmp.mask);
  47666     rv = WRITE_FP_GLOBAL_MASK_TCAMm(unit, MEM_BLOCK_ALL,
  47667                                     tcam_idx, &ipbm_entry);
  47668 
  47669     rv_internal = _field_internal_backup_entry_delete(unit, backup_entry);
  47670     if (BCM_FAILURE(rv_internal)) {
  47671         LOG_DEBUG(BSL_LS_BCM_FP,
  47672                   (BSL_META_U(unit,
  47673                               "Internal backup entry delete failed \n")));
  47674         if (BCM_SUCCESS(rv)) {
  47675             return rv_internal;
  47676         }
  47677     }
  47678     return rv;
  47679 }
  47680 
  47681 /*
  47682  * Routine to add newly attached port to the InPorts qualifier of all the
  47683  * group entries in order to avoid the false match.
  47684  * Note: The change affects only if mask parameter of InPorts qualifier
  47685  * configured for all valid ports before flex operation.
  47686  */
  47687 STATIC
  47688 int _bcm_field_group_entry_port_update(int unit,
  47689                                         _field_group_t *fg,
  47690                                         bcm_pbmp_t detached_pbmp,
  47691                                         bcm_pbmp_t attached_pbmp)
  47692 {
  47693     int                           idx;
  47694     _field_entry_t                *f_ent;
  47695     int                           tcam_idx;
  47696     bcm_error_t                   rv = BCM_E_NONE;
  47697     bcm_error_t                   rv_internal = BCM_E_NONE;
  47698     bcm_field_entry_t             backup_entry;
  47699     bcm_pbmp_t                    valid_full_mask;
  47700     bcm_pbmp_t                    temp_mask;
  47701     fp_global_mask_tcam_entry_t   ipbm_entry;
  47702 
  47703     /* Retrieve valid pbmp of the device */
  47704     rv = _bcm_field_valid_pbmp_get(unit, &valid_full_mask);
  47705     if (BCM_FAILURE(rv)) {
  47706         return (rv);
  47707     }
  47708     BCM_PBMP_OR(valid_full_mask, PBMP_LB(unit));
  47709     BCM_PBMP_REMOVE(valid_full_mask, attached_pbmp);
  47710 
  47711     for (idx = 0; idx < fg->group_status.entry_count; idx++) {
  47712         f_ent = fg->entry_arr[idx];
  47713         if ((f_ent == NULL) ||
  47714              BCM_PBMP_IS_NULL(f_ent->pbmp.mask)) {
  47715            continue;
  47716         }
  47717 
  47718         /* Check if entry is already part of attached_pbmp */
  47719         BCM_PBMP_ASSIGN(temp_mask, f_ent->pbmp.mask);
  47720         BCM_PBMP_XOR(temp_mask, detached_pbmp);
  47721         BCM_PBMP_OR(temp_mask, attached_pbmp);
  47722         if (BCM_PBMP_EQ(temp_mask, f_ent->pbmp.mask)) {
  47723            continue;
  47724         }
  47725 
  47726         /* Check if entry pbmp contains all valid ports */
  47727         BCM_PBMP_ASSIGN(temp_mask, f_ent->pbmp.mask);
  47728         BCM_PBMP_AND(temp_mask, valid_full_mask);
  47729         if (BCM_PBMP_EQ(valid_full_mask, temp_mask)) {
  47730            /* Remove detached ports from the entry mask */
  47731            BCM_PBMP_XOR(f_ent->pbmp.mask, detached_pbmp);
  47732            /* Add newly attached ports to the entry mask */
  47733            BCM_PBMP_OR(f_ent->pbmp.mask, attached_pbmp);
  47734 
  47735            rv = _field_internal_backup_entry_create(unit, f_ent->eid,
  47736                                              &backup_entry);
  47737            BCM_IF_ERROR_RETURN(rv);
  47738 
  47739            rv = _bcm_field_entry_tcam_idx_get(unit, f_ent, &tcam_idx);
  47740            BCM_IF_ERROR_RETURN(rv);
  47741 
  47742            sal_memset(&ipbm_entry, 0, sizeof(fp_global_mask_tcam_entry_t));
  47743            rv = READ_FP_GLOBAL_MASK_TCAMm(unit, MEM_BLOCK_ANY, tcam_idx,
  47744                                           &ipbm_entry);
  47745            BCM_IF_ERROR_RETURN(rv);
  47746            soc_mem_pbmp_field_set(unit, FP_GLOBAL_MASK_TCAMm, &ipbm_entry, IPBMf,
  47747                                   &f_ent->pbmp.data);
  47748            soc_mem_pbmp_field_set(unit, FP_GLOBAL_MASK_TCAMm, &ipbm_entry,
  47749                                   IPBM_MASKf, &f_ent->pbmp.mask);
  47750            rv = WRITE_FP_GLOBAL_MASK_TCAMm(unit, MEM_BLOCK_ALL,
  47751                                   tcam_idx, &ipbm_entry);
  47752 
  47753            rv_internal = _field_internal_backup_entry_delete(unit, backup_entry);
  47754            if (BCM_FAILURE(rv_internal)) {
  47755                LOG_DEBUG(BSL_LS_BCM_FP,
  47756                   (BSL_META_U(unit,
  47757                               "Internal backup entry delete failed \n")));
  47758                if (BCM_SUCCESS(rv)) {
  47759                   return rv_internal;
  47760                }
  47761            }
  47762         }
  47763     }
  47764 
  47765     return BCM_E_NONE;
  47766 }
  47767 
  47768 #if defined(BCM_TOMAHAWK_SUPPORT)
  47769 /*
  47770  * Routine to add newly attached port to the InPorts qualifier of all the
  47771  * group entries in order to avoid the false match.
  47772  * Note: The change affects only if mask parameter of InPorts qualifier
  47773  * configured for all global / pipe local valid ports before flex operation.
  47774  */
  47775 STATIC
  47776 int _bcm_field_group_entry_pipe_port_update(int unit,
  47777                                             _field_group_t *fg,
  47778                                             bcm_pbmp_t detached_pbmp,
  47779                                             bcm_pbmp_t attached_pbmp)
  47780 {
  47781     int                           idx;
  47782     _field_entry_t                *f_ent = NULL;
  47783     _field_stage_t                *stage_fc = NULL;
  47784     bcm_error_t                   rv = BCM_E_NONE;
  47785     bcm_pbmp_t                    valid_full_mask;
  47786     bcm_pbmp_t                    old_valid_full_mask;
  47787     bcm_pbmp_t                    temp_mask;
  47788     bcm_pbmp_t                    entry_mask;
  47789     bcm_pbmp_t                    entry_data;
  47790 
  47791     rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc);
  47792     BCM_IF_ERROR_RETURN(rv);
  47793     if (bcmFieldGroupOperModePipeLocal == stage_fc->oper_mode) {
  47794         BCM_PBMP_ASSIGN(valid_full_mask, PBMP_PIPE(unit, fg->instance));
  47795         BCM_PBMP_REMOVE(valid_full_mask, PBMP_LB(unit));
  47796     } else {
  47797         /* Retrieve valid pbmp of the device */
  47798         rv = _bcm_field_valid_pbmp_get(unit, &valid_full_mask);
  47799         if (BCM_FAILURE(rv)) {
  47800             return (rv);
  47801         }
  47802     }
  47803     BCM_PBMP_ASSIGN(old_valid_full_mask, valid_full_mask);
  47804     BCM_PBMP_REMOVE(old_valid_full_mask, attached_pbmp);
  47805 
  47806     for (idx = 0; idx < fg->group_status.entry_count; idx++) {
  47807         f_ent = fg->entry_arr[idx];
  47808         if ((f_ent == NULL) ||
  47809              BCM_PBMP_IS_NULL(f_ent->pbmp.mask)) {
  47810            continue;
  47811         }
  47812 
  47813         /* Get entry data/mask */
  47814         rv = _bcm_field_qualify_InPorts_get(unit, f_ent->eid, bcmFieldQualifyInPorts,
  47815                                             &entry_data, &entry_mask);
  47816         BCM_IF_ERROR_RETURN(rv);
  47817 
  47818         /* Check if entry pbmp contains all valid ports */
  47819         BCM_PBMP_ASSIGN(temp_mask, entry_mask);
  47820         BCM_PBMP_AND(temp_mask, old_valid_full_mask);
  47821         if (BCM_PBMP_EQ(old_valid_full_mask, temp_mask)) {
  47822             /* Remove detached ports from the entry mask */
  47823             BCM_PBMP_REMOVE(entry_mask, detached_pbmp);
  47824             /* Add newly attached ports to the entry mask */
  47825             BCM_PBMP_OR(entry_mask, attached_pbmp);
  47826             BCM_PBMP_AND(entry_mask, valid_full_mask);
  47827 
  47828             rv = _bcm_field_th_qualify_InPorts(unit, f_ent->eid, bcmFieldQualifyInPorts,
  47829                                                entry_data, entry_mask);
  47830 
  47831             rv = bcm_esw_field_entry_reinstall(unit, f_ent->eid);
  47832             BCM_IF_ERROR_RETURN(rv);
  47833         }
  47834     }
  47835 
  47836     return BCM_E_NONE;
  47837 }
  47838 #endif
  47839 
  47840 /*
  47841  * Function: _bcm_esw_field_group_ports_remove
  47842  *
  47843  * Purpose:
  47844  *    Remove ports from the specified group.
  47845  *
  47846  * Parameters:
  47847  *     unit  - BCM device number
  47848  *     group - Field group
  47849  *     pbmp  - Set of Ports
  47850  *
  47851  * Returns:
  47852  *     BCM_E_XXX  - Error code from _bcm_field_pfs_entry_clear() or
  47853  *                  _field_control_get().
  47854  */
  47855 
  47856 int
  47857 _bcm_esw_field_group_ports_remove(
  47858     int unit,
  47859     bcm_field_group_t group,
  47860     bcm_pbmp_t pbmp)
  47861 {
  47862     _field_group_t          *fg = NULL;
  47863     _field_entry_t          **entries = NULL;
  47864     bcm_port_t              port;
  47865     int                     rv = BCM_E_NONE;
  47866     int                     idx;
  47867 
  47868     rv = _field_group_get(unit, group, &fg);
  47869     BCM_IF_ERROR_RETURN(rv);
  47870 
  47871     if ((fg->flags & _FP_GROUP_PER_PORT_OR_PBMP)) {
  47872         BCM_PBMP_ITER(pbmp, port) {
  47873             if (BCM_PBMP_MEMBER(fg->pbmp, port)) {
  47874                 rv = _bcm_field_pfs_entry_clear(unit,
  47875                                                 fg, port);
  47876                 BCM_IF_ERROR_RETURN(rv);
  47877 
  47878              }
  47879         }
  47880         entries = fg->entry_arr;
  47881         for (idx = 0; idx < fg->group_status.entry_count; idx++) {
  47882             rv = _field_entry_update_ipbm(unit, (entries[idx]), pbmp);
  47883             BCM_IF_ERROR_RETURN(rv);
  47884         }
  47885     } else {
  47886         rv = BCM_E_PARAM;
  47887         LOG_DEBUG(BSL_LS_BCM_FP,
  47888                   (BSL_META_U(unit,
  47889                               "Per port or Pbmp base Group is expected \n")));
  47890     }
  47891 
  47892     return (rv);
  47893 }
  47894 
  47895 int
  47896 _bcm_esw_field_class_map_get(
  47897                        int unit,
  47898                        bcm_field_qualify_t qual,
  47899                        uint32 num_entries,
  47900                        uint32 *orig_values_array,
  47901                        uint32 *map_values_array)
  47902 {
  47903     bcm_error_t rv = BCM_E_NONE;
  47904     uint32 i = 0;
  47905     ttl_fn_entry_t map_buf;
  47906 
  47907     soc_mem_t mem = INVALIDm;
  47908     soc_field_t fld = INVALIDf;
  47909 
  47910     if ((NULL == orig_values_array) ||
  47911         (NULL == map_values_array)) {
  47912         return BCM_E_PARAM;
  47913     }
  47914 
  47915     switch(qual) {
  47916         case bcmFieldQualifyTtlClassZero :
  47917         case bcmFieldQualifyTtl          :
  47918             mem = TTL_FNm;
  47919             fld = FN0f;
  47920             break;
  47921         case bcmFieldQualifyTtlClassOne  :
  47922             mem = TTL_FNm;
  47923             fld = FN1f;
  47924             break;
  47925         case bcmFieldQualifyTosClassZero  :
  47926         case bcmFieldQualifyTos :
  47927             mem = TOS_FNm;
  47928             fld = FN0f;
  47929             break;
  47930         case bcmFieldQualifyTosClassOne  :
  47931             mem = TOS_FNm;
  47932             fld = FN1f;
  47933             break;
  47934         case bcmFieldQualifyTcpClassZero :
  47935         case bcmFieldQualifyTcpControl :
  47936             mem = TCP_FNm;
  47937             fld = FN0f;
  47938             break;
  47939         case bcmFieldQualifyTcpClassOne  :
  47940             mem = TCP_FNm;
  47941             fld = FN1f;
  47942             break;
  47943         default :
  47944             LOG_ERROR(BSL_LS_BCM_FP,
  47945                     (BSL_META_U(unit,
  47946                                 "FP(unit %d) Error: Field class mapping is "
  47947                                 "not applicable for qual %s\n"),
  47948                      unit, _field_qual_name(qual)));
  47949             return BCM_E_UNAVAIL;
  47950     }
  47951 
  47952     sal_memset(&map_buf, 0, sizeof(ttl_fn_entry_t));
  47953     for (i = 0; i < (num_entries); i++) {
  47954         if ((orig_values_array[i] > soc_mem_index_max(unit, mem)) ||
  47955                 (orig_values_array[i] < soc_mem_index_min(unit, mem))) {
  47956             LOG_ERROR(BSL_LS_BCM_FP,
  47957                     (BSL_META_U(unit,
  47958                                 "FP(unit %d) Error: Original value %d "
  47959                                 "is out of range for qual %s \n"),
  47960                      unit,orig_values_array[i], _field_qual_name(qual)));
  47961             return BCM_E_PARAM;
  47962         }
  47963         SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY,
  47964                                          orig_values_array[i], &map_values_array[i]));
  47965         map_values_array[i] = soc_mem_field32_get(unit, mem, &map_values_array[i], fld);
  47966     }
  47967 
  47968     return rv;
  47969 }
  47970 
  47971 int
  47972 _bcm_esw_field_class_map_set(
  47973                        int unit,
  47974                        bcm_field_qualify_t qual,
  47975                        uint32 num_entries,
  47976                        uint32 *orig_values_array,
  47977                        uint32 *map_values_array)
  47978 {
  47979     int    rv            = BCM_E_NONE;
  47980     uint32 i             = 0;
  47981     uint32 hw_retain_val = 0;
  47982     uint32 *hw_val_array = NULL;
  47983 
  47984     soc_mem_t mem = INVALIDm;
  47985     soc_field_t mod_fld = INVALIDf;
  47986     soc_field_t retain_fld = INVALIDf;
  47987 
  47988     if ((NULL == orig_values_array) ||
  47989         (NULL == map_values_array)) {
  47990         return BCM_E_PARAM;
  47991     }
  47992 
  47993     switch(qual) {
  47994         case bcmFieldQualifyTtlClassZero :
  47995         case bcmFieldQualifyTtl          :
  47996             mem = TTL_FNm;
  47997             mod_fld = FN0f;
  47998             retain_fld = FN1f;
  47999             break;
  48000         case bcmFieldQualifyTtlClassOne  :
  48001             mem = TTL_FNm;
  48002             mod_fld = FN1f;
  48003             retain_fld = FN0f;
  48004             break;
  48005         case bcmFieldQualifyTosClassZero :
  48006         case bcmFieldQualifyTos          :
  48007             mem = TOS_FNm;
  48008             mod_fld = FN0f;
  48009             retain_fld = FN1f;
  48010             break;
  48011         case bcmFieldQualifyTosClassOne  :
  48012             mem = TOS_FNm;
  48013             mod_fld = FN1f;
  48014             retain_fld = FN0f;
  48015             break;
  48016         case bcmFieldQualifyTcpClassZero :
  48017         case bcmFieldQualifyTcpControl   :
  48018             mem = TCP_FNm;
  48019             mod_fld = FN0f;
  48020             retain_fld = FN1f;
  48021             break;
  48022         case bcmFieldQualifyTcpClassOne  :
  48023             mem = TCP_FNm;
  48024             mod_fld = FN1f;
  48025             retain_fld = FN0f;
  48026             break;
  48027         default :
  48028             LOG_ERROR(BSL_LS_BCM_FP,
  48029                     (BSL_META_U(unit,
  48030                                 "FP(unit %d) Error: Field class mapping is "
  48031                                 "not applicable for qual %s\n"),
  48032                      unit, _field_qual_name(qual)));
  48033             return BCM_E_UNAVAIL;
  48034     }
  48035 
  48036     _FP_XGS3_ALLOC(hw_val_array, num_entries * sizeof(uint32), "Field class Mapping array");
  48037     if (NULL == hw_val_array) {
  48038         return BCM_E_MEMORY;
  48039     }
  48040 
  48041     for (i = 0; i < (num_entries); i++) {
  48042 
  48043         if ((orig_values_array[i] > soc_mem_index_max(unit, mem)) ||
  48044                 (orig_values_array[i] < soc_mem_index_min(unit, mem))) {
  48045 
  48046             LOG_ERROR(BSL_LS_BCM_FP,
  48047                     (BSL_META_U(unit,
  48048                                 "FP(unit %d) Error: Original value %d "
  48049                                 "is out of range for qual %s \n"),
  48050                      unit,orig_values_array[i], _field_qual_name(qual)));
  48051             rv = BCM_E_PARAM;
  48052             goto cleanup;
  48053         }
  48054 
  48055         /*
  48056          * Soc mem write over writes all fields in the memory
  48057          * So retaining the other field (FN0f or FN1f).
  48058          */
  48059         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY,
  48060                           orig_values_array[i], &hw_retain_val);
  48061         if (BCM_FAILURE(rv)) {
  48062             goto cleanup;
  48063         }
  48064         hw_retain_val = soc_mem_field32_get(unit, mem, &hw_retain_val, retain_fld);
  48065         soc_mem_field32_set(unit, mem, &hw_val_array[i], mod_fld, map_values_array[i]);
  48066         soc_mem_field32_set(unit, mem, &hw_val_array[i], retain_fld, hw_retain_val);
  48067     }
  48068 
  48069     /* Write to Hardware only after SW operations and error/range checks */
  48070     for (i = 0; i < (num_entries); i++) {
  48071         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, orig_values_array[i], &hw_val_array[i]);
  48072         if (BCM_FAILURE(rv)) {
  48073             goto cleanup;
  48074         }
  48075     }
  48076 
  48077 cleanup:
  48078     sal_free(hw_val_array);
  48079     return rv;
  48080 }
  48081 
  48082 /*
  48083  * Function: _bcm_field_pfs_entry_clear
  48084  *
  48085  * Purpose:
  48086  *    Remove ports from the specified group's PFS entry
  48087  *
  48088  * Parameters:
  48089  *     unit  - BCM device number
  48090  *     group - Field group
  48091  *     port  - Port for PFS clear
  48092  *
  48093  * Returns:
  48094  *     BCM_E_XXX  - Error code from _bcm_field_entry_tcam_parts_count() or
  48095  *                  READ_FP_PORT_FIELD_SELm() or
  48096  *                  _bcm_field_tcam_part_to_slice_number() or
  48097  *                  WRITE_FP_PORT_FIELD_SELm().
  48098  */
  48099 
  48100 int _bcm_field_pfs_entry_clear(int unit,
  48101                                _field_group_t *fg,
  48102                                bcm_port_t port) {
  48103 
  48104     fp_port_field_sel_entry_t   pfs_entry;
  48105     int                         index;
  48106     int                         rv = 0;
  48107     uint8                       slice_numb = -1;
  48108     int                         parts_count = -1;
  48109     int                         idx = -1;
  48110 
  48111     index = (int)port;
  48112 
  48113     /* Get number of entry parts for the group. */
  48114     rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
  48115                                                 fg->flags, &parts_count);
  48116 
  48117     BCM_IF_ERROR_RETURN(rv);
  48118 
  48119     /* Read Port's current entry in FP_PORT_FIELD_SEL table */
  48120     rv = READ_FP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL,
  48121                                  index, &pfs_entry);
  48122     BCM_IF_ERROR_RETURN(rv);
  48123 
  48124     for (idx = 0; idx < parts_count;  idx++) {
  48125 
  48126         /* Get slice id for entry part */
  48127         rv = _bcm_field_tcam_part_to_slice_number(unit, idx, fg,
  48128                                                   &slice_numb);
  48129         BCM_IF_ERROR_RETURN(rv);
  48130 
  48131         soc_FP_PORT_FIELD_SELm_field32_set
  48132             (unit,
  48133              &pfs_entry,
  48134              _bcm_field_trx_field_sel[slice_numb][0],
  48135              0
  48136              );
  48137         soc_FP_PORT_FIELD_SELm_field32_set
  48138             (unit,
  48139              &pfs_entry,
  48140              _bcm_field_trx_field_sel[slice_numb][1],
  48141              0
  48142              );
  48143         soc_FP_PORT_FIELD_SELm_field32_set
  48144             (unit,
  48145              &pfs_entry,
  48146              _bcm_field_trx_field_sel[slice_numb][2],
  48147              0
  48148              );
  48149 
  48150 #if defined(BCM_TRIDENT2_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT)
  48151         if (SOC_MEM_FIELD_VALID(unit, FP_PORT_FIELD_SELm,
  48152                     _bcm_ifp_normalize_fldtbl[slice_numb][0])) {
  48153             soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry,
  48154                     _bcm_ifp_normalize_fldtbl[slice_numb][0], 0);
  48155         }
  48156         if (SOC_MEM_FIELD_VALID(unit, FP_PORT_FIELD_SELm,
  48157                     _bcm_ifp_normalize_fldtbl[slice_numb][1])) {
  48158             soc_FP_PORT_FIELD_SELm_field32_set(unit, &pfs_entry,
  48159                     _bcm_ifp_normalize_fldtbl[slice_numb][1], 0);
  48160         }
  48161 #endif
  48162         if (SOC_MEM_FIELD_VALID(unit,
  48163                  FP_PORT_FIELD_SELm,
  48164                  _bcm_field_trx_d_type_sel[slice_numb])) {
  48165              soc_FP_PORT_FIELD_SELm_field32_set(unit,
  48166                  &pfs_entry,
  48167                  _bcm_field_trx_d_type_sel[slice_numb], 0);
  48168         }
  48169         if (SOC_MEM_FIELD_VALID(unit,
  48170                  FP_PORT_FIELD_SELm,
  48171                  _bcm_field_trx_s_type_sel[slice_numb])) {
  48172              soc_FP_PORT_FIELD_SELm_field32_set(unit,
  48173                  &pfs_entry,
  48174                  _bcm_field_trx_s_type_sel[slice_numb], 0);
  48175         }
  48176 
  48177      }
  48178 
  48179     rv = WRITE_FP_PORT_FIELD_SELm(unit, MEM_BLOCK_ALL, index, &pfs_entry);
  48180     BCM_IF_ERROR_RETURN(rv);
  48181 
  48182     BCM_PBMP_PORT_REMOVE(fg->pbmp,port);
  48183     BCM_PBMP_PORT_REMOVE(fg->slices[0].pbmp, port);
  48184 
  48185     return rv;
  48186 
  48187 }
  48188 #endif  /* BCM_TRX_SUPPORT */
  48189 
  48190 /* Function: _bcm_esw_field_group_config_create
  48191  *
  48192  * Purpose:
  48193  *     Create a group with a mode (single, double, etc.), a port bitmap,
  48194  *     group size and a Group ID.
  48195  * Parameters:
  48196  *     unit - BCM device number.
  48197  *     group_config - Group create attributes namely:
  48198  *          flags       - (IN) Bits indicate which parameters have been
  48199  *                             passed to API and should be used during group
  48200  *                             creation.
  48201  *          qset        - (IN) Field qualifier set
  48202  *          priority    - (IN) Priority within allowable range,
  48203  *                             or BCM_FIELD_GROUP_PRIO_ANY to automatically
  48204  *                             assign a priority; each priority value may be
  48205  *                             used only once
  48206  *          mode        - (IN) Group mode (single, double, triple or Auto-wide)
  48207  *          ports       - (IN) Ports where group is defined
  48208  *          group       - (IN/OUT) Requested Group ID. If Group ID is not set,
  48209  *                              then API allocates and returns the created
  48210  *                              Group ID.
  48211  *    flags - internal Group Config flags.
  48212  *
  48213  * Returns:
  48214  *     BCM_E_INIT      - BCM unit not initialized
  48215  *     BCM_E_RESOURCE  - no select codes will satisfy qualifier set
  48216  *     BCM_E_NONE      - Success
  48217  */
  48218 int
  48219 _bcm_esw_field_group_config_create(int unit,
  48220                                   bcm_field_group_config_t *group_config,
  48221                                   uint32 flags)
  48222 {
  48223     _field_group_add_fsm_t *fsm;     /* Group creation state machine. */
  48224     _field_control_t       *fc;     /* Field control structure.      */
  48225     int                    rv;      /* Operation return status.      */
  48226     bcm_pbmp_t             all_pbmp;
  48227     _field_hints_t         *f_ht = NULL;
  48228                                      /* Field hints Structure. */
  48229     _field_hint_t          *hint_list = NULL;
  48230                                      /* Field Hints Structure. */
  48231     bcm_field_hint_t       *hint_entry;
  48232                                      /* Hint Entry.            */
  48233 
  48234 
  48235     if (NULL == group_config) {
  48236         return (BCM_E_PARAM);
  48237     }
  48238 
  48239     fsm = NULL;
  48240 
  48241 #if defined(BCM_TOMAHAWK3_SUPPORT) 
  48242     if ((group_config->flags & BCM_FIELD_GROUP_CREATE_WITH_ID)
  48243         && (soc_feature(unit, soc_feature_th3_style_fp)) &&
  48244            ((group_config->group >= (_FP_INTERNAL_RESERVED_ID_MIN))
  48245            /* coverity[result_independent_of_operands : FALSE] */
  48246            && (group_config->group <= _FP_INTERNAL_RESERVED_ID_MAX))) {
  48247            LOG_ERROR(BSL_LS_BCM_FP,
  48248                       (BSL_META_U(unit,
  48249                       "FP(unit %d) Error: This Group ID is reserved"
  48250                       " for internal use\n"),
  48251                       unit));
  48252             return (BCM_E_PARAM);
  48253     }
  48254 #endif
  48255 
  48256     /* Both SMALL and LARGE slice combination is not encouraged */
  48257     if (soc_feature(unit, soc_feature_field_ingress_two_slice_types)
  48258         && ((group_config->flags & BCM_FIELD_GROUP_CREATE_SMALL)
  48259             && (group_config->flags & BCM_FIELD_GROUP_CREATE_LARGE))) {
  48260         LOG_ERROR(BSL_LS_BCM_FP,
  48261                 (BSL_META_U(unit,
  48262                             "Group hint flags have"
  48263                             "both SMALL and LARGE\r\n")));
  48264         return (BCM_E_PARAM);
  48265     }
  48266 
  48267 #if defined(BCM_TOMAHAWK_SUPPORT)
  48268     /* If device supports per-pipe FP configuration, */
  48269     if (soc_feature(unit, soc_feature_field_multi_pipe_support)) {
  48270         rv = _field_control_get(unit, &fc);
  48271         if (BCM_FAILURE(rv)) {
  48272             return rv;
  48273         }
  48274         /* Call Flexible Key Extraction programming function for TH IFP. */
  48275         rv = fc->functions.fp_group_add(unit, flags, group_config);
  48276         return rv;
  48277     }
  48278 #endif /* BCM_TOMAHAWK_SUPPORT */
  48279 
  48280     /* Check if passed group configuration is valid for this device */
  48281     if ((0 == soc_feature(unit, soc_feature_field_ingress_two_slice_types))
  48282         && ((group_config->flags & BCM_FIELD_GROUP_CREATE_SMALL)
  48283             || (group_config->flags & BCM_FIELD_GROUP_CREATE_LARGE)
  48284             || group_config->hintid != 0)) {
  48285         return (BCM_E_UNAVAIL);
  48286     }
  48287 
  48288     /* Read device port configuration. */
  48289     BCM_PBMP_CLEAR(all_pbmp);
  48290     rv = _bcm_field_valid_pbmp_get(unit, &all_pbmp);
  48291     if (BCM_FAILURE(rv)) {
  48292         return (rv);
  48293     }
  48294 
  48295     rv = _field_control_get(unit, &fc);
  48296     if (BCM_FAILURE(rv)) {
  48297         goto bcm_error;
  48298     }
  48299 
  48300     if (!(group_config->flags & BCM_FIELD_GROUP_CREATE_WITH_ID)) {
  48301         /* qset and pri are validated in bcm_field_group_create_mode_id(). */
  48302         rv = _bcm_field_group_id_generate(unit, &group_config->group);
  48303         if (BCM_FAILURE(rv)) {
  48304            goto bcm_error;
  48305         }
  48306     }
  48307 
  48308     /* Initialize group creation tracking structure. */
  48309     _FP_XGS3_ALLOC(fsm, sizeof(_field_group_add_fsm_t),
  48310                    "Group fsm info ");
  48311     if (fsm == NULL) {
  48312         rv = BCM_E_MEMORY;
  48313         goto  bcm_error;
  48314     }
  48315 
  48316     fsm->fsm_state = _BCM_FP_GROUP_ADD_STATE_START;
  48317     fsm->priority  = group_config->priority;
  48318     fsm->group_id  = group_config->group;
  48319     fsm->qset = group_config->qset;
  48320     fsm->hintid = group_config->hintid;
  48321     fsm->action_res_id     = group_config->action_res_id;
  48322 
  48323     if (fsm->hintid != 0) {
  48324         if (fsm->hintid >= _FP_HINT_ID_MAX) {
  48325             LOG_DEBUG(BSL_LS_BCM_FP,
  48326                     (BSL_META_U(unit, "HintId is out of allowed range\r\n")));
  48327             rv = BCM_E_PARAM;
  48328             goto bcm_error;
  48329         }
  48330 
  48331         if (_FP_HINTID_BMP_TEST(fc->hintid_bmp, fsm->hintid) == 0) {
  48332             LOG_DEBUG(BSL_LS_BCM_FP,
  48333                     (BSL_META_U(unit, "Trying to attach hintid which is"
  48334                                 " not created\r\n")));
  48335             rv = BCM_E_NOT_FOUND;
  48336             goto bcm_error;
  48337         }
  48338 
  48339         rv= _field_hints_control_get (unit, group_config->hintid, &f_ht);
  48340         if ( (BCM_FAILURE(rv)) || (f_ht == NULL) ){
  48341             LOG_DEBUG(BSL_LS_BCM_FP,
  48342                     (BSL_META_U(unit,"Hints are not attached to hintid(%d)."
  48343                                 "\r\n"),
  48344                                 group_config->hintid));
  48345             rv = BCM_E_NOT_FOUND;
  48346             goto bcm_error;
  48347         }
  48348 
  48349         if (BCM_FIELD_QSET_TEST(fsm->qset,
  48350                                  bcmFieldQualifyStageExternal)) {
  48351             LOG_DEBUG(BSL_LS_BCM_FP,
  48352             (BSL_META_U(unit,"Unsupported hint type attached"
  48353                                   "to hintid(%d).\r\n"),
  48354                                    group_config->hintid));
  48355             rv = BCM_E_PARAM;
  48356             goto bcm_error;
  48357         }
  48358 
  48359         hint_list = f_ht->hints;
  48360         while (hint_list != NULL) {
  48361             hint_entry = hint_list->hint;
  48362             if (hint_entry != NULL) {
  48363                 if ((BCM_FIELD_QSET_TEST(fsm->qset,
  48364                                 bcmFieldQualifyStageEgress)) ||
  48365                     (BCM_FIELD_QSET_TEST(fsm->qset,
  48366                                 bcmFieldQualifyStageLookup))) {
  48367 
  48368                     if(!((hint_entry->hint_type ==
  48369                             bcmFieldHintTypeGroupAutoExpansion) &&
  48370                          (hint_entry->flags ==
  48371                             BCM_FIELD_GROUP_MAX_SIZE_HARD_LIMIT) ) ) {
  48372                         LOG_DEBUG(BSL_LS_BCM_FP,
  48373                         (BSL_META_U(unit,"Unsupported hint type attached"
  48374                                          "to hintid(%d).\r\n"),
  48375                                           group_config->hintid));
  48376                         rv = BCM_E_PARAM;
  48377                         goto bcm_error; /*error*/
  48378                     }
  48379                 }
  48380             }
  48381             hint_list = hint_list->next;
  48382         } /* while (hint_list != NULL) */
  48383     }
  48384 
  48385     /* Apply group member port configuration */
  48386     if (group_config->flags & BCM_FIELD_GROUP_CREATE_WITH_PORT) {
  48387         BCM_PBMP_ASSIGN(fsm->pbmp, group_config->ports);
  48388     } else {
  48389         BCM_PBMP_ASSIGN(fsm->pbmp, all_pbmp);
  48390     }
  48391 
  48392     /* Apply group mode configuration */
  48393     if (group_config->flags & BCM_FIELD_GROUP_CREATE_WITH_MODE) {
  48394         fsm->mode = group_config->mode;
  48395     } else {
  48396         fsm->mode = bcmFieldGroupModeDefault;
  48397     }
  48398 
  48399     /* Apply slice selection configuration */
  48400     if (group_config->flags & BCM_FIELD_GROUP_CREATE_SMALL) {
  48401         fsm->flags |= _BCM_FP_GROUP_ADD_SMALL_SLICE;
  48402     } else if (group_config->flags & BCM_FIELD_GROUP_CREATE_LARGE) {
  48403         fsm->flags |= _BCM_FP_GROUP_ADD_LARGE_SLICE;
  48404     }
  48405 
  48406     if (flags & _FP_GROUP_CONFIG_VALIDATE) {
  48407         fsm->flags |= _FP_GROUP_CONFIG_VALIDATE;
  48408     }
  48409 
  48410     /*  Add FP group. */
  48411     rv = _bcm_field_group_add(unit, fsm);
  48412 
  48413 #ifdef BCM_WARM_BOOT_SUPPORT
  48414     SOC_CONTROL_LOCK(unit);
  48415     SOC_CONTROL(unit)->scache_dirty = 1;
  48416     SOC_CONTROL_UNLOCK(unit);
  48417 #endif
  48418 
  48419 bcm_error:
  48420     if (fsm != NULL) {
  48421         sal_free(fsm);
  48422     }
  48423     return (rv);
  48424 }
  48425 
  48426 int
  48427 _bcm_esw_field_group_config_destroy(int unit,
  48428                                   bcm_field_group_t group,
  48429                                   uint32 flags)
  48430 {
  48431     int                      rv = BCM_E_NONE;
  48432     _field_control_t         *fc = NULL;
  48433     _field_group_t           *fg = NULL;
  48434     _field_stage_id_t        stage = -1;
  48435 
  48436     FP_LOCK(unit);
  48437 
  48438     rv = _field_control_get(unit, &fc);
  48439     if (BCM_FAILURE(rv)) {
  48440         goto error;
  48441     }
  48442 
  48443     rv = _field_group_get(unit, group, &fg);
  48444     if (BCM_FAILURE(rv)) {
  48445         goto error;
  48446     }
  48447 
  48448     stage = fg->stage_id;
  48449 
  48450     if ((flags & _FP_GROUP_CONFIG_FLOWTRACKER_SPECIFIC) &&
  48451             (_BCM_FIELD_STAGE_EXACTMATCH != stage)){
  48452         /* FLOWTRACKER SPECIFIC flag should be used for EXACTMATCH Stage only */
  48453         rv = BCM_E_PARAM;
  48454         goto error;
  48455     }
  48456 
  48457     if (soc_property_get(unit, spn_FLOWTRACKER_ENABLE, 0)) {
  48458         if (_BCM_FIELD_STAGE_EXACTMATCH == stage) {
  48459             /* Validation for internal flag for FLOWTRACKER module */
  48460             if (0 == (flags & _FP_GROUP_CONFIG_FLOWTRACKER_SPECIFIC)) {
  48461                 rv = BCM_E_CONFIG;
  48462                 goto error;
  48463             }
  48464 
  48465             /* Check to Restrict EM for internal use */
  48466             if (_FP_FLOWTRACKER_RESERVED_EM_GID_AFTER_SHIFT !=
  48467                     ((uint32)group >> (_FP_FLOWTRACKER_RESERVED_EM_GID_SHIFT_VAL))) {
  48468                 rv = BCM_E_CONFIG;
  48469                 goto error;
  48470             }
  48471 
  48472             if (0 == (fc->flags & _FP_EXACTMATCH_STAGE_SKIP_DETACH)) {
  48473                 rv = BCM_E_INTERNAL;
  48474                 goto error;
  48475             }
  48476         }
  48477     } else {
  48478         if (flags & _FP_GROUP_CONFIG_FLOWTRACKER_SPECIFIC) {
  48479             /* FLOWTRACKER SPECIFIC flag should be used only if soc property FLOWTRACKER_ENABLE is enabled */
  48480             rv = BCM_E_PARAM;
  48481             goto error;
  48482         }
  48483     }
  48484 
  48485     rv = bcm_esw_field_group_destroy(unit, group);
  48486     if (BCM_FAILURE(rv)) {
  48487         goto error;
  48488     }
  48489 
  48490     if ((_BCM_FIELD_STAGE_EXACTMATCH == stage) &&
  48491         (flags & _FP_GROUP_CONFIG_FLOWTRACKER_SPECIFIC)) {
  48492         /* Check whether any group is present under EM stage */
  48493         for (fg = fc->groups;
  48494             (NULL != fg) && (_BCM_FIELD_STAGE_EXACTMATCH != fg->stage_id);
  48495             fg = fg->next);
  48496 
  48497         if (NULL == fg) {
  48498             /* NO EM group is present. EM flag can be cleared */
  48499             fc->flags &= ~_FP_EXACTMATCH_STAGE_SKIP_DETACH;
  48500         }
  48501     }
  48502 
  48503 error:
  48504     FP_UNLOCK(unit);
  48505     return rv;
  48506 }
  48507 
  48508 /*
  48509  * Function: _bcm_esw_field_group_config_validate
  48510  *
  48511  * Purpose:
  48512  *     To verify whether a group can be created with a given qset and mode.
  48513  *
  48514  * Parameters:
  48515  *     unit  - BCM device number
  48516  *     gc    - Field group config.
  48517  *     group_mode - Field Group Mode.
  48518  *
  48519  * Returns:
  48520  *     BCM_E_XXX - from _bcm_esw_field_group_config_validate()
  48521  */
  48522 
  48523 int _bcm_esw_field_group_config_validate(
  48524                           int unit,
  48525                           bcm_field_group_config_t *group_config,
  48526                           bcm_field_group_mode_t *group_mode) {
  48527 
  48528     int rv = BCM_E_NONE;
  48529     _field_group_t *fg = NULL;
  48530     uint32 flags = 0;
  48531     _field_stage_t *stage_fc; /* Stage field control structure. */
  48532 
  48533     flags |= _FP_GROUP_CONFIG_VALIDATE;
  48534     rv = _bcm_esw_field_group_config_create(unit,group_config, flags);
  48535     if (BCM_SUCCESS(rv)) {
  48536 
  48537         /* Search the field control for the Group ID. */
  48538         rv = _field_group_get(unit, group_config->group, &fg);
  48539         if (BCM_FAILURE(rv)) {
  48540             goto cleanup;
  48541         }
  48542         /* Get the mode from group */
  48543         rv = _bcm_esw_field_group_mode_get(fg->flags, group_mode);
  48544         if (BCM_FAILURE(rv)) {
  48545             goto cleanup;
  48546         }
  48547 
  48548         /* Retreive Stage Control. */
  48549         rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc);
  48550         if (BCM_FAILURE(rv)) {
  48551             goto cleanup;
  48552         }
  48553 
  48554 #if defined (BCM_TOMAHAWK3_SUPPORT)
  48555         if ((soc_feature(unit, soc_feature_ifp_no_narrow_mode_support)) &&
  48556              (*group_mode == bcmFieldGroupModeIntraSliceDouble) &&
  48557              (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id)) {
  48558              *group_mode = bcmFieldGroupModeSingle;
  48559         }
  48560 #endif
  48561 
  48562         fg->flags |= _FP_GROUP_CONFIG_VALIDATE;
  48563         /* Destroy the group */
  48564         rv = bcm_esw_field_group_destroy(unit, group_config->group);
  48565     }
  48566 cleanup:
  48567     return rv;
  48568 }
  48569 
  48570 #if defined(BCM_TRIDENT3_SUPPORT)
  48571 int
  48572 _bcm_field_action_vlan_actions_add(int unit,
  48573                                    bcm_field_entry_t entry,
  48574                                    bcm_field_action_t action,
  48575                                    bcm_vlan_action_set_t *vlan_set)
  48576 {
  48577     _field_entry_t     *f_ent = NULL;
  48578     _field_action_t    *fa = NULL;    /* Field action descriptor. */
  48579     _field_control_t   *fc;           /* Field control structure. */
  48580     int                rv;            /* Operation return status. */
  48581     bcm_vlan_action_set_t *new_action_set = NULL;
  48582 
  48583     if ((vlan_set == NULL) || (action != bcmFieldActionVlanActions)) {
  48584        return BCM_E_PARAM;
  48585     }
  48586 
  48587     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  48588 
  48589     BCM_IF_ERROR_RETURN(_field_entry_get(unit, entry,
  48590                         _FP_ENTRY_PRIMARY, &f_ent));
  48591 
  48592     if (f_ent->group->stage_id != _BCM_FIELD_STAGE_LOOKUP) {
  48593         return BCM_E_UNAVAIL;
  48594     }
  48595 
  48596     if (f_ent->vlan_action_set == NULL) {
  48597        _FP_XGS3_ALLOC(new_action_set, sizeof(bcm_vlan_action_set_t),
  48598                       "FP Entry VLAN Action set");
  48599        if (new_action_set == NULL) {
  48600           return BCM_E_MEMORY;
  48601        }
  48602        sal_memcpy(new_action_set, vlan_set, sizeof(bcm_vlan_action_set_t));
  48603        f_ent->vlan_action_set = new_action_set;
  48604     } else {
  48605        bcm_vlan_action_set_t *old_vlan_set;
  48606 
  48607        old_vlan_set = f_ent->vlan_action_set;
  48608        if (!sal_memcmp(old_vlan_set, vlan_set, sizeof(bcm_vlan_action_set_t))) {
  48609           return BCM_E_NONE;
  48610        }
  48611     }
  48612 
  48613     /*
  48614      * Allocate the action descriptor, params are not valid here.
  48615      */
  48616     rv = _field_action_alloc(unit, action, 0, 0, 0, 0, 0, 0, &fa);
  48617     if (BCM_FAILURE(rv)) {
  48618         LOG_ERROR(BSL_LS_BCM_FP, (BSL_META_U(unit,
  48619                   "Error: Action alloc failure.\n\r")));
  48620         goto cleanup;
  48621     }
  48622 
  48623     /*
  48624      * Add action to entry actions list.
  48625      */
  48626     rv = _field_action_add(unit, fc, entry, fa);
  48627     if (BCM_FAILURE(rv)) {
  48628         goto cleanup;
  48629     }
  48630 
  48631 cleanup:
  48632     if (BCM_FAILURE(rv)) {
  48633        if (new_action_set != NULL) {
  48634           sal_free(new_action_set);
  48635           f_ent->vlan_action_set = NULL;
  48636        }
  48637 
  48638        if (fa != NULL) {
  48639           sal_free(fa);
  48640        }
  48641     }
  48642 
  48643     return rv;
  48644 }
  48645 
  48646 int
  48647 _bcm_field_action_vlan_actions_get(int unit,
  48648                                    bcm_field_entry_t entry,
  48649                                    bcm_field_action_t action,
  48650                                    bcm_vlan_action_set_t *vlan_action_set)
  48651 {
  48652     _field_entry_t     *f_ent = NULL;
  48653 
  48654     if ((vlan_action_set == NULL) || (action != bcmFieldActionVlanActions)) {
  48655        return BCM_E_PARAM;
  48656     }
  48657 
  48658     BCM_IF_ERROR_RETURN(_field_entry_get(unit, entry,
  48659                         _FP_ENTRY_PRIMARY, &f_ent));
  48660 
  48661     if (f_ent->group->stage_id != _BCM_FIELD_STAGE_LOOKUP) {
  48662         return BCM_E_UNAVAIL;
  48663     }
  48664 
  48665     if (f_ent->vlan_action_set != NULL) {
  48666        sal_memcpy(vlan_action_set, f_ent->vlan_action_set,
  48667                   sizeof(bcm_vlan_action_set_t));
  48668     } else {
  48669        return BCM_E_NOT_FOUND;
  48670     }
  48671 
  48672     return BCM_E_NONE;
  48673 }
  48674 
  48675 STATIC int
  48676 _field_td3_em_entry_profile_dump (int unit, _field_stage_t *stage_fc, _field_group_t *fg, _field_entry_t *f_ent)
  48677 {
  48678     exact_match_2_entry_t ebuf_nar;  /* Narrow Entry Buffer.        */
  48679     exact_match_4_entry_t ebuf_wide; /* Wide Entry Buffer.          */
  48680     _field_entry_t *f_ent_part = NULL;  /* Field Entry Part.         */
  48681     uint32 tbuf[SOC_MAX_MEM_FIELD_WORDS] = {0};
  48682                                         /* Temp Buffer One.          */
  48683     uint32 tbuf_temp[SOC_MAX_MEM_FIELD_WORDS] = {0};
  48684                                         /* Temp Buffer Two.          */
  48685     soc_mem_t mem = INVALIDm;
  48686     int eindex = 0;                  /* Entry Index inn UFT memory. */
  48687     static soc_mem_t em_entry_nar_mem[_FP_MAX_NUM_PIPES] = {
  48688         EXACT_MATCH_2_PIPE0m,
  48689         EXACT_MATCH_2_PIPE1m
  48690     };
  48691     static soc_mem_t em_entry_wide_mem[_FP_MAX_NUM_PIPES] = {
  48692         EXACT_MATCH_4_PIPE0m,
  48693         EXACT_MATCH_4_PIPE1m
  48694     };
  48695     uint32 *bufp = NULL;                /* Hardware Buffer Ptr.      */
  48696     uint32 qp_idx = -1;                  /* Qos Actions Profile Index.*/
  48697     uint32 ap_idx = -1;                  /* Actions Profile Index.    */
  48698 
  48699     if ((NULL == stage_fc) || (NULL == fg) || (NULL == f_ent)) {
  48700         return BCM_E_PARAM;
  48701     }
  48702 
  48703     /* Get Hardware Buffer Pointer and memory identifier. */
  48704     if ((fg->em_mode == _FieldExactMatchMode128) ||
  48705             (fg->em_mode == _FieldExactMatchMode160)) {
  48706         bufp = (uint32 *)&ebuf_nar;
  48707         if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) {
  48708             mem = EXACT_MATCH_2m;
  48709         } else {
  48710             mem = em_entry_nar_mem[fg->instance];
  48711         }
  48712     } else {
  48713         bufp = (uint32 *)&ebuf_wide;
  48714         if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) {
  48715             mem = EXACT_MATCH_4m;
  48716         } else {
  48717             mem = em_entry_wide_mem[fg->instance];
  48718         }
  48719     }
  48720 
  48721     /* Initialize exact match entries. */
  48722     sal_memcpy(bufp, soc_mem_entry_null(unit, mem),
  48723             soc_mem_entry_words(unit, mem) * sizeof(uint32));
  48724 
  48725     /* Initialize exact match entries. */
  48726     soc_mem_field32_set(unit, mem, bufp, KEY_TYPEf, fg->em_mode);
  48727     /* Set Exact Match Entry */
  48728     if (fg->em_mode == _FieldExactMatchMode128) {
  48729 
  48730         _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 0,
  48731                                    TD3_EM_MODE128_KEY_PART0_SIZE);
  48732         soc_mem_field_set(unit, mem, bufp, MODE128__KEY_0_ONLYf, tbuf);
  48733         _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf,
  48734                                    TD3_EM_MODE128_KEY_PART0_SIZE,
  48735                                    TD3_EM_MODE128_KEY_PART1_SIZE);
  48736         soc_mem_field_set(unit, mem, bufp, MODE128__KEY_1_ONLYf, tbuf);
  48737 
  48738     } else if (fg->em_mode == _FieldExactMatchMode160) {
  48739 
  48740         _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 0,
  48741                                    TD3_EM_MODE160_KEY_PART0_SIZE);
  48742         soc_mem_field_set(unit, mem, bufp, MODE160__KEY_0_ONLYf, tbuf);
  48743         _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf,
  48744                                    TD3_EM_MODE160_KEY_PART0_SIZE,
  48745                                    TD3_EM_MODE160_KEY_PART1_SIZE);
  48746         soc_mem_field_set(unit, mem, bufp, MODE160__KEY_1_ONLYf, tbuf);
  48747 
  48748     } else if (fg->em_mode == _FieldExactMatchMode320) {
  48749 
  48750         _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 0,
  48751                                    TD3_EM_MODE320_KEY_PART0_SIZE);
  48752         soc_mem_field_set(unit, mem, bufp, MODE320__KEY_0_ONLYf, tbuf);
  48753         _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf,
  48754                                    TD3_EM_MODE320_KEY_PART0_SIZE,
  48755                                    (EM_ENTRY_PART0_KEYSIZE -
  48756                                     TD3_EM_MODE320_KEY_PART0_SIZE));
  48757 
  48758         /* Key From Second Entry Part. */
  48759         f_ent_part = f_ent + 1;
  48760 
  48761         _bcm_field_th_val_get(f_ent_part->tcam.key_hw, tbuf_temp, 0,
  48762                                    (TD3_EM_MODE320_KEY_PART1_SIZE -
  48763                                    (EM_ENTRY_PART0_KEYSIZE -
  48764                                     TD3_EM_MODE320_KEY_PART0_SIZE)));
  48765         BCM_IF_ERROR_RETURN(_bcm_field_th_val_set(tbuf, tbuf_temp,
  48766                                    (EM_ENTRY_PART0_KEYSIZE -
  48767                                     TD3_EM_MODE320_KEY_PART0_SIZE),
  48768                                    (TD3_EM_MODE320_KEY_PART1_SIZE -
  48769                                    (EM_ENTRY_PART0_KEYSIZE -
  48770                                     TD3_EM_MODE320_KEY_PART0_SIZE))));
  48771         soc_mem_field_set(unit, mem, bufp, MODE320__KEY_1_ONLYf, tbuf);
  48772         _bcm_field_th_val_get(f_ent_part->tcam.key_hw, tbuf,
  48773                                    (TD3_EM_MODE320_KEY_PART1_SIZE -
  48774                                    (EM_ENTRY_PART0_KEYSIZE -
  48775                                     TD3_EM_MODE320_KEY_PART0_SIZE)),
  48776                                     TD3_EM_MODE320_KEY_PART2_SIZE);
  48777         soc_mem_field_set(unit, mem, bufp, MODE320__KEY_2_ONLYf, tbuf);
  48778         _bcm_field_th_val_get(f_ent_part->tcam.key_hw, tbuf,
  48779                                    ((TD3_EM_MODE320_KEY_PART1_SIZE -
  48780                                     (EM_ENTRY_PART0_KEYSIZE -
  48781                                      TD3_EM_MODE320_KEY_PART0_SIZE)) +
  48782                                      TD3_EM_MODE320_KEY_PART2_SIZE),
  48783                                      TD3_EM_MODE320_KEY_PART3_SIZE);
  48784         soc_mem_field_set(unit, mem, bufp, MODE320__KEY_3_ONLYf, tbuf);
  48785 
  48786     }
  48787 
  48788     BCM_IF_ERROR_RETURN(soc_mem_search(unit, mem, MEM_BLOCK_ANY, &eindex, bufp, bufp, 0));
  48789 
  48790     /* Get Qos and Action Profile Index Allocated From Entry. */
  48791     if (fg->em_mode == _FieldExactMatchMode128) {
  48792         qp_idx = soc_mem_field32_get(unit, mem,
  48793                 bufp, MODE128__QOS_PROFILE_IDf);
  48794         ap_idx = soc_mem_field32_get(unit, mem,
  48795                 bufp, MODE128__DATA_TYPEf);
  48796     } else if (fg->em_mode == _FieldExactMatchMode160) {
  48797         qp_idx = soc_mem_field32_get(unit, mem,
  48798                 bufp, MODE160__QOS_PROFILE_IDf);
  48799         ap_idx = soc_mem_field32_get(unit, mem,
  48800                 bufp, MODE160__DATA_TYPEf);
  48801     } else if (fg->em_mode == _FieldExactMatchMode320) {
  48802         qp_idx = soc_mem_field32_get(unit, mem,
  48803                 bufp, MODE320__QOS_PROFILE_IDf);
  48804         ap_idx = soc_mem_field32_get(unit, mem,
  48805                 bufp, MODE320__DATA_TYPEf);
  48806     }
  48807 
  48808     LOG_CLI((BSL_META_U(unit,
  48809                     "         {Action_profile_idx=%d"), ap_idx));
  48810     LOG_CLI((BSL_META_U(unit,
  48811                     " Qos_action_profile_idx=%d }\n"), qp_idx));
  48812 
  48813     return BCM_E_NONE;
  48814 }
  48815 #endif /* BCM_TRIDENT3_SUPPORT */
  48816 
  48817 #if defined(BCM_TOMAHAWK3_SUPPORT)
  48818     STATIC int
  48819 _field_th3_em_entry_profile_dump (int unit, _field_stage_t *stage_fc, _field_group_t *fg, _field_entry_t *f_ent)
  48820 {
  48821     exact_match_2_entry_t ebuf_nar;  /* Narrow Entry Buffer.        */
  48822     exact_match_4_entry_t ebuf_wide; /* Wide Entry Buffer.          */
  48823     _field_entry_t *f_ent_part = NULL;  /* Field Entry Part.         */
  48824     uint32 tbuf[SOC_MAX_MEM_FIELD_WORDS] = {0};
  48825                                         /* Temp Buffer One.          */
  48826     uint32 tbuf_temp[SOC_MAX_MEM_FIELD_WORDS] = {0};
  48827                                         /* Temp Buffer Two.          */
  48828     soc_mem_t mem = INVALIDm;
  48829     int eindex = 0;                  /* Entry Index inn UFT memory. */
  48830     static soc_mem_t em_entry_nar_mem[_FP_MAX_NUM_PIPES] = {
  48831         EXACT_MATCH_2_PIPE0m,
  48832         EXACT_MATCH_2_PIPE1m
  48833     };
  48834     static soc_mem_t em_entry_wide_mem[_FP_MAX_NUM_PIPES] = {
  48835         EXACT_MATCH_4_PIPE0m,
  48836         EXACT_MATCH_4_PIPE1m
  48837     };
  48838     uint32 *bufp = NULL;                /* Hardware Buffer Ptr.      */
  48839     uint32 qp_idx = -1;                  /* Qos Actions Profile Index.*/
  48840     uint32 ap_idx = -1;                  /* Actions Profile Index.    */
  48841 
  48842     if ((NULL == stage_fc) || (NULL == fg) || (NULL == f_ent)) {
  48843         return BCM_E_PARAM;
  48844     }
  48845 
  48846     /* Get Hardware Buffer Pointer and memory identifier. */
  48847     if ((fg->em_mode == _FieldExactMatchMode128) ||
  48848             (fg->em_mode == _FieldExactMatchMode160)) {
  48849         bufp = (uint32 *)&ebuf_nar;
  48850         if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) {
  48851             mem = EXACT_MATCH_2m;
  48852         } else {
  48853             mem = em_entry_nar_mem[fg->instance];
  48854         }
  48855     } else {
  48856         bufp = (uint32 *)&ebuf_wide;
  48857         if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) {
  48858             mem = EXACT_MATCH_4m;
  48859         } else {
  48860             mem = em_entry_wide_mem[fg->instance];
  48861         }
  48862     }
  48863 
  48864     /* Initialize exact match entries. */
  48865     sal_memcpy(bufp, soc_mem_entry_null(unit, mem),
  48866             soc_mem_entry_words(unit, mem) * sizeof(uint32));
  48867 
  48868     /* Initialize exact match entries. */
  48869     soc_mem_field32_set(unit, mem, bufp, KEY_TYPEf, fg->em_mode);
  48870     /* Set Exact Match Entry */
  48871     if (fg->em_mode == _FieldExactMatchMode128) {
  48872         _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 0,
  48873                               TH3_EM_MODE128_KEY_PART0_SIZE);
  48874         soc_mem_field_set(unit, mem, bufp, MODE128__KEY_0_ONLYf, tbuf);
  48875         _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf,
  48876                               TH3_EM_MODE128_KEY_PART0_SIZE,
  48877                               TH3_EM_MODE128_KEY_PART1_SIZE);
  48878         soc_mem_field_set(unit, mem, bufp, MODE128__KEY_1_ONLYf, tbuf);
  48879     } else if (fg->em_mode == _FieldExactMatchMode160) {
  48880         _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 0,
  48881                               TH3_EM_MODE160_KEY_PART0_SIZE);
  48882         soc_mem_field_set(unit, mem, bufp, MODE160__KEY_0_ONLYf, tbuf);
  48883         _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf,
  48884                               TH3_EM_MODE160_KEY_PART0_SIZE,
  48885                               TH3_EM_MODE160_KEY_PART1_SIZE);
  48886         soc_mem_field_set(unit, mem, bufp, MODE160__KEY_1_ONLYf, tbuf);
  48887     } else if (fg->em_mode == _FieldExactMatchMode320) {
  48888         _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 0,
  48889                               TH3_EM_MODE320_KEY_PART0_SIZE);
  48890         soc_mem_field_set(unit, mem, bufp, MODE320__KEY_0_ONLYf, tbuf);
  48891         _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf,
  48892                               TH3_EM_MODE320_KEY_PART0_SIZE,
  48893                              (EM_ENTRY_PART0_KEYSIZE -
  48894                               TH3_EM_MODE320_KEY_PART0_SIZE));
  48895 
  48896         /* Key From Second Entry Part. */
  48897         f_ent_part = f_ent + 1;
  48898 
  48899         _bcm_field_th_val_get(f_ent_part->tcam.key_hw, tbuf_temp, 0,
  48900                              (TH3_EM_MODE320_KEY_PART1_SIZE -
  48901                              (EM_ENTRY_PART0_KEYSIZE -
  48902                               TH3_EM_MODE320_KEY_PART0_SIZE)));
  48903         BCM_IF_ERROR_RETURN(_bcm_field_th_val_set(tbuf, tbuf_temp,
  48904                              (EM_ENTRY_PART0_KEYSIZE -
  48905                               TH3_EM_MODE320_KEY_PART0_SIZE),
  48906                              (TH3_EM_MODE320_KEY_PART1_SIZE -
  48907                              (EM_ENTRY_PART0_KEYSIZE -
  48908                               TH3_EM_MODE320_KEY_PART0_SIZE))));
  48909         soc_mem_field_set(unit, mem, bufp, MODE320__KEY_1_ONLYf, tbuf);
  48910         _bcm_field_th_val_get(f_ent_part->tcam.key_hw, tbuf,
  48911                              (TH3_EM_MODE320_KEY_PART1_SIZE -
  48912                              (EM_ENTRY_PART0_KEYSIZE -
  48913                               TH3_EM_MODE320_KEY_PART0_SIZE)),
  48914                               TH3_EM_MODE320_KEY_PART2_SIZE);
  48915         soc_mem_field_set(unit, mem, bufp, MODE320__KEY_2_ONLYf, tbuf);
  48916     }
  48917 
  48918     BCM_IF_ERROR_RETURN(soc_mem_search(unit, mem, MEM_BLOCK_ANY, &eindex, bufp, bufp, 0));
  48919 
  48920     /* Get Qos and Action Profile Index Allocated From Entry. */
  48921     if (fg->em_mode == _FieldExactMatchMode128) {
  48922         qp_idx = soc_mem_field32_get(unit, mem,
  48923                                      bufp, MODE128__QOS_PROFILE_IDf);
  48924         ap_idx = soc_mem_field32_get(unit, mem,
  48925                                      bufp, MODE128__DATA_TYPEf);
  48926     } else if (fg->em_mode == _FieldExactMatchMode160) {
  48927         qp_idx = soc_mem_field32_get(unit, mem,
  48928                                      bufp, MODE160__QOS_PROFILE_IDf);
  48929         ap_idx = soc_mem_field32_get(unit, mem,
  48930                                      bufp, MODE160__DATA_TYPEf);
  48931     } else if (fg->em_mode == _FieldExactMatchMode320) {
  48932         qp_idx = soc_mem_field32_get(unit, mem,
  48933                                      bufp, MODE320__QOS_PROFILE_IDf);
  48934         ap_idx = soc_mem_field32_get(unit, mem,
  48935                                      bufp, MODE320__DATA_TYPEf);
  48936     }
  48937 
  48938     LOG_CLI((BSL_META_U(unit,
  48939                     "         {Action_profile_idx=%d"), ap_idx));
  48940     LOG_CLI((BSL_META_U(unit,
  48941                     " Qos_action_profile_idx=%d }\n"), qp_idx));
  48942 
  48943     return BCM_E_NONE;
  48944 }
  48945 #endif /* BCM_TOMAHAWK3_SUPPORT */
  48946 
  48947 #if defined(BCM_TOMAHAWK_SUPPORT)
  48948 STATIC int
  48949 _field_th_em_entry_profile_dump (int unit, _field_stage_t *stage_fc, _field_group_t *fg, _field_entry_t *f_ent)
  48950 {
  48951     exact_match_2_entry_t ebuf_nar;  /* Narrow Entry Buffer.        */
  48952     exact_match_4_entry_t ebuf_wide; /* Wide Entry Buffer.          */
  48953     uint32 tbuf[SOC_MAX_MEM_FIELD_WORDS] = {0};
  48954                                      /* Temp Buffer One.            */
  48955     uint32 tbuf_temp[SOC_MAX_MEM_FIELD_WORDS] = {0};
  48956                                      /* Temp Buffer Two.            */
  48957     soc_mem_t mem = INVALIDm;
  48958     int eindex = 0;                  /* Entry Index inn UFT memory. */
  48959     _field_entry_t *f_ent_part = NULL;
  48960     static soc_mem_t em_entry_nar_mem[_FP_MAX_NUM_PIPES] = {
  48961         EXACT_MATCH_2_PIPE0m,
  48962         EXACT_MATCH_2_PIPE1m,
  48963         EXACT_MATCH_2_PIPE2m,
  48964         EXACT_MATCH_2_PIPE3m,
  48965     };
  48966     static soc_mem_t em_entry_wide_mem[_FP_MAX_NUM_PIPES] = {
  48967         EXACT_MATCH_4_PIPE0m,
  48968         EXACT_MATCH_4_PIPE1m,
  48969         EXACT_MATCH_4_PIPE2m,
  48970         EXACT_MATCH_4_PIPE3m,
  48971     };
  48972     uint32 *bufp = NULL;                /* Hardware Buffer Ptr.      */
  48973     uint32 qp_idx = -1;                  /* Qos Actions Profile Index.*/
  48974     uint32 ap_idx = -1;                  /* Actions Profile Index.    */
  48975 
  48976     if ((NULL == stage_fc) || (NULL == fg) || (NULL == f_ent)) {
  48977         return BCM_E_PARAM;
  48978     }
  48979 
  48980            /* Get Hardware Buffer Pointer and memory identifier. */
  48981            if ((fg->em_mode == _FieldExactMatchMode128) ||
  48982                    (fg->em_mode == _FieldExactMatchMode160)) {
  48983                bufp = (uint32 *)&ebuf_nar;
  48984                if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) {
  48985                    mem = EXACT_MATCH_2m;
  48986                } else {
  48987                    mem = em_entry_nar_mem[fg->instance];
  48988                }
  48989            } else {
  48990                bufp = (uint32 *)&ebuf_wide;
  48991                if (stage_fc->oper_mode == bcmFieldGroupOperModeGlobal) {
  48992                    mem = EXACT_MATCH_4m;
  48993                } else {
  48994                    mem = em_entry_wide_mem[fg->instance];
  48995                }
  48996            }
  48997 
  48998            /* Initialize exact match entries. */
  48999            sal_memcpy(bufp, soc_mem_entry_null(unit, mem),
  49000                    soc_mem_entry_words(unit, mem) * sizeof(uint32));
  49001 
  49002            /* Set Exact Match Entry Search Key. */
  49003            if (fg->em_mode == _FieldExactMatchMode128) {
  49004 
  49005                soc_mem_field32_set(unit, mem, bufp, KEY_TYPE_0f, fg->em_mode);
  49006                soc_mem_field32_set(unit, mem, bufp, KEY_TYPE_1f, fg->em_mode);
  49007                soc_mem_field32_set(unit, mem, bufp, VALID_0f, 1);
  49008                soc_mem_field32_set(unit, mem, bufp, VALID_1f, 1);
  49009                _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 0,
  49010                        EM_MODE128_KEY_PART0_SIZE);
  49011                soc_mem_field_set(unit, mem, bufp, MODE128__KEY_0_ONLYf, tbuf);
  49012                _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf,
  49013                        EM_MODE128_KEY_PART0_SIZE,
  49014                        EM_MODE128_KEY_PART1_SIZE);
  49015                soc_mem_field_set(unit, mem, bufp, MODE128__KEY_1_ONLYf, tbuf);
  49016 
  49017            } else if (fg->em_mode == _FieldExactMatchMode160) {
  49018 
  49019                soc_mem_field32_set(unit, mem, bufp, KEY_TYPE_0f, fg->em_mode);
  49020                soc_mem_field32_set(unit, mem, bufp, KEY_TYPE_1f, fg->em_mode);
  49021                soc_mem_field32_set(unit, mem, bufp, VALID_0f, 1);
  49022                soc_mem_field32_set(unit, mem, bufp, VALID_1f, 1);
  49023                _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 0,
  49024                        EM_MODE160_KEY_PART0_SIZE);
  49025                soc_mem_field_set(unit, mem, bufp, MODE160__KEY_0_ONLYf, tbuf);
  49026                _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf,
  49027                        EM_MODE160_KEY_PART0_SIZE,
  49028                        EM_MODE160_KEY_PART1_SIZE);
  49029                soc_mem_field_set(unit, mem, bufp, MODE160__KEY_1_ONLYf, tbuf);
  49030 
  49031            } else if (fg->em_mode == _FieldExactMatchMode320) {
  49032 
  49033                soc_mem_field32_set(unit, mem, bufp, KEY_TYPE_0f, fg->em_mode);
  49034                soc_mem_field32_set(unit, mem, bufp, KEY_TYPE_1f, fg->em_mode);
  49035                soc_mem_field32_set(unit, mem, bufp, KEY_TYPE_2f, fg->em_mode);
  49036                soc_mem_field32_set(unit, mem, bufp, KEY_TYPE_3f, fg->em_mode);
  49037                soc_mem_field32_set(unit, mem, bufp, VALID_0f, 1);
  49038                soc_mem_field32_set(unit, mem, bufp, VALID_1f, 1);
  49039                soc_mem_field32_set(unit, mem, bufp, VALID_2f, 1);
  49040                soc_mem_field32_set(unit, mem, bufp, VALID_3f, 1);
  49041                _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf, 0,
  49042                        EM_MODE320_KEY_PART0_SIZE);
  49043                soc_mem_field_set(unit, mem, bufp, MODE320__KEY_0_ONLYf, tbuf);
  49044                _bcm_field_th_val_get(f_ent->tcam.key_hw, tbuf,
  49045                        EM_MODE320_KEY_PART0_SIZE, 59);
  49046 
  49047                /* Key From Second Entry Part. */
  49048                f_ent_part = f_ent + 1;
  49049                _bcm_field_th_val_get(f_ent_part->tcam.key_hw, tbuf_temp, 0, 42);
  49050                BCM_IF_ERROR_RETURN(_bcm_field_th_val_set(tbuf, tbuf_temp, 59, 42));
  49051                soc_mem_field_set(unit, mem, bufp, MODE320__KEY_1_ONLYf, tbuf);;
  49052                _bcm_field_th_val_get(f_ent_part->tcam.key_hw, tbuf, 42,
  49053                        EM_MODE320_KEY_PART2_SIZE);
  49054                soc_mem_field_set(unit, mem, bufp, MODE320__KEY_2_ONLYf, tbuf);
  49055                _bcm_field_th_val_get(f_ent_part->tcam.key_hw, tbuf, 143, 17);
  49056                soc_mem_field_set(unit, mem, bufp, MODE320__KEY_3_ONLYf, tbuf);
  49057 
  49058            }
  49059 
  49060     BCM_IF_ERROR_RETURN(soc_mem_search(unit, mem, MEM_BLOCK_ANY, &eindex, bufp, bufp, 0));
  49061 
  49062            /* Get Qos and Action Profile Index Allocated From Entry. */
  49063            if (fg->em_mode == _FieldExactMatchMode128) {
  49064                qp_idx = soc_mem_field32_get(unit, mem,
  49065                        bufp, MODE128__QOS_PROFILE_IDf);
  49066                ap_idx = soc_mem_field32_get(unit, mem,
  49067                        bufp, MODE128__ACTION_PROFILE_IDf);
  49068            } else if (fg->em_mode == _FieldExactMatchMode160) {
  49069                qp_idx = soc_mem_field32_get(unit, mem,
  49070                        bufp, MODE160__QOS_PROFILE_IDf);
  49071                ap_idx = soc_mem_field32_get(unit, mem,
  49072                        bufp, MODE160__ACTION_PROFILE_IDf);
  49073            } else if (fg->em_mode == _FieldExactMatchMode320) {
  49074                qp_idx = soc_mem_field32_get(unit, mem,
  49075                        bufp, MODE320__QOS_PROFILE_IDf);
  49076                ap_idx = soc_mem_field32_get(unit, mem,
  49077                        bufp, MODE320__ACTION_PROFILE_IDf);
  49078            }
  49079 
  49080            LOG_CLI((BSL_META_U(unit,
  49081                            "         {Action_profile_idx=%d"), ap_idx));
  49082            LOG_CLI((BSL_META_U(unit,
  49083                            " Qos_action_profile_idx=%d }\n"), qp_idx));
  49084 
  49085     return BCM_E_NONE;
  49086 }
  49087 
  49088 #endif
  49089 /*
  49090  * Function: _bcm_field_entry_dump
  49091  *
  49092  * Purpose:
  49093  *     Show contents of a field entry.
  49094  *
  49095  * Parameters:
  49096  *     unit  - BCM device number
  49097  *     entry - Field entry to dump
  49098  *
  49099  * Returns:
  49100  *     Nothing.
  49101  */
  49102 int
  49103 _bcm_esw_field_entry_dump(int unit, bcm_field_entry_t entry, int stage)
  49104 {
  49105     int                 parts_count = 0;
  49106     _field_stage_t *stage_fc = NULL;    /* Field Stage Control.      */
  49107     _field_group_t      *fg;
  49108     _field_action_t     *fa;
  49109     _field_entry_t      *f_ent;
  49110     bcm_pbmp_t          pbmp;
  49111     uint8               idx;
  49112     int                 rv;
  49113     char                buf_pbmp[SOC_PBMP_FMT_LEN];
  49114 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
  49115     defined(BCM_APACHE_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT)
  49116     bcm_policer_t    policer_id = 0;
  49117 #endif /* BCM_KATANA_SUPPORT || BCM_TRIUMPH3_SUPPORT ||
  49118           BCM_APACHE_SUPPORT || BCM_GREYHOUND2_SUPPORT */
  49119 
  49120     FP_LOCK(unit);
  49121 
  49122     rv = _bcm_field_entry_get_by_id(unit, entry, &f_ent);
  49123     if (BCM_FAILURE(rv)) {
  49124         FP_UNLOCK(unit);
  49125         return (rv);
  49126     }
  49127 
  49128 #if defined(BCM_TOMAHAWK_SUPPORT)
  49129     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  49130         (_BCM_FIELD_STAGE_CLASS == f_ent->group->stage_id)) {
  49131         rv = _bcm_field_th_class_entry_dump(unit,f_ent);
  49132         FP_UNLOCK(unit);
  49133         return (rv);
  49134     }
  49135 #endif /* BCM_TOMAHAWK_SUPPORT */
  49136 
  49137     fg = f_ent->group;
  49138     LOG_CLI((BSL_META_U(unit,
  49139                     "EID 0x%08x: gid=0x%x,\n"), f_ent->eid, fg->gid));
  49140 
  49141     /* Retreive Stage Control. */
  49142     rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc);
  49143     if (BCM_FAILURE(rv)) {
  49144         FP_UNLOCK(unit);
  49145         return (rv);
  49146     }
  49147 
  49148     /* Get number of entry parts. */
  49149     rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
  49150                                             fg->flags, &parts_count);
  49151     if (BCM_FAILURE(rv)) {
  49152         FP_UNLOCK(unit);
  49153         return (rv);
  49154     }
  49155 
  49156 #if defined(BCM_TOMAHAWK_SUPPORT)
  49157     /* Display Entry info for multi-pipe supported devices */
  49158     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  49159         ((_BCM_FIELD_STAGE_INGRESS == fg->stage_id) ||
  49160          (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id) ||
  49161          (_BCM_FIELD_STAGE_FLOWTRACKER == fg->stage_id))) {
  49162         rv =  _bcm_field_th_entry_phys_dump(unit, f_ent);
  49163         if (BCM_FAILURE(rv)) {
  49164             FP_UNLOCK(unit);
  49165             return (rv);
  49166         }
  49167 
  49168         if  ((-1 != stage) && (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id)) {
  49169 #if defined(BCM_TOMAHAWK3_SUPPORT)
  49170             if(soc_feature(unit, soc_feature_th3_style_fp)) {
  49171                 rv = _field_th3_em_entry_profile_dump(unit, stage_fc, fg, f_ent);
  49172                 if (BCM_FAILURE(rv)) {
  49173                     FP_UNLOCK(unit);
  49174                     return (rv);
  49175                 }
  49176             } else
  49177 #endif
  49178 #if defined(BCM_TRIDENT3_SUPPORT)
  49179                 if (soc_feature(unit, soc_feature_td3_style_fp)) {
  49180                     rv = _field_td3_em_entry_profile_dump(unit, stage_fc, fg, f_ent);
  49181                     if (BCM_FAILURE(rv)) {
  49182                         FP_UNLOCK(unit);
  49183                         return (rv);
  49184                     }
  49185                 } else
  49186 #endif
  49187                 {
  49188                     rv = _field_th_em_entry_profile_dump(unit, stage_fc, fg, f_ent);
  49189                     if (BCM_FAILURE(rv)) {
  49190                         FP_UNLOCK(unit);
  49191                         return (rv);
  49192                     }
  49193                 }
  49194         }
  49195     } else
  49196 #endif /* BCM_TOMAHAWK_SUPPORT */
  49197     {
  49198        /* Dump the primary entry. */
  49199        for(idx = 0; idx < parts_count; idx++) {
  49200            _field_entry_phys_dump(unit, f_ent + idx, idx);
  49201        }
  49202     }
  49203     /* Display action data */
  49204     for(idx = 0; idx < parts_count; idx++) {
  49205         fa = f_ent[idx].actions;
  49206         while (fa != NULL) {
  49207             LOG_CLI((BSL_META_U(unit,
  49208                                 "         action=")));
  49209             if ((fa->action == bcmFieldActionEgressMask) ||
  49210                (fa->action == bcmFieldActionEgressPortsAdd) ||
  49211                (fa->action == bcmFieldActionRedirectPbmp) ||
  49212                (fa->action == bcmFieldActionRedirectBcastPbmp)) {
  49213                 rv = bcm_esw_field_action_ports_get (unit, f_ent->eid, fa->action, &pbmp);
  49214                 if (BCM_FAILURE(rv)) {
  49215                     FP_UNLOCK(unit);
  49216                     return (rv);
  49217                 }
  49218                 LOG_CLI((BSL_META("{act=%s, pbmp=%s  %s"),
  49219                             _field_action_name(fa->action),SOC_PBMP_FMT(pbmp, buf_pbmp),
  49220                             (fa->flags & _FP_ACTION_DIRTY) ? ", Dirty" : ""));
  49221                 if (stage != -1) {
  49222                     LOG_CLI((BSL_META(", ActionFlags=%08x "),
  49223                                 fa->flags));
  49224                     if (!(fa->flags & _FP_ACTION_DIRTY)) {
  49225                         LOG_CLI((BSL_META(", Redirection_Profile=%d "),
  49226                                     fa->hw_index));
  49227                     }
  49228                 }
  49229                 LOG_CLI((BSL_META_U(unit,
  49230                                 "}")));
  49231 
  49232             } else {
  49233                 _field_action_dump (fa);
  49234             }
  49235             LOG_CLI((BSL_META_U(unit,
  49236                                 "\n")));
  49237             fa = fa->next;
  49238         }
  49239     }
  49240 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) || \
  49241     defined(BCM_APACHE_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT)
  49242     if (SOC_IS_KATANAX(unit) || SOC_IS_TRIUMPH3(unit) || SOC_IS_APACHE(unit) ||
  49243         SOC_IS_GREYHOUND2(unit)) {
  49244         if (_BCM_FIELD_STAGE_LOOKUP == f_ent->group->stage_id) {
  49245             if (f_ent->global_meter_policer.pid) {
  49246                 policer_id = f_ent->global_meter_policer.pid;
  49247             }
  49248             LOG_CLI((BSL_META_U(unit,
  49249                                 " Global Meter policer=0x%x"), policer_id));
  49250         }
  49251     }
  49252 #endif /* BCM_KATANA_SUPPORT || BCM_TRIUMPH3_SUPPORT ||
  49253           BCM_APACHE_SUPPORT || BCM_GREYHOUND2_SUPPORT */
  49254 #if defined(BCM_TRIUMPH3_SUPPORT)
  49255     if (SOC_IS_TRIUMPH3(unit)) {
  49256         if (_BCM_FIELD_STAGE_EXTERNAL == f_ent->group->stage_id) {
  49257             if (f_ent->global_meter_policer.pid) {
  49258                 policer_id = f_ent->global_meter_policer.pid;
  49259             }
  49260             LOG_CLI((BSL_META_U(unit,
  49261                                 " Global Meter policer=%x"), policer_id));
  49262         }
  49263     }
  49264 #endif
  49265 
  49266     /* Display entry's meter. */
  49267     LOG_CLI((BSL_META_U(unit,
  49268                         "         policer=")));
  49269     _field_policers_dump(unit, f_ent);
  49270     LOG_CLI((BSL_META_U(unit,
  49271                         "\n")));
  49272 
  49273 #if defined (BCM_TRIDENT2PLUS_SUPPORT)
  49274     /* Display Oam Stat Actions */
  49275     if (soc_feature(unit, soc_feature_fp_based_oam)) {
  49276         rv = _field_oam_stat_action_dump (unit, f_ent);
  49277         if (BCM_FAILURE(rv)) {
  49278             FP_UNLOCK(unit);
  49279             return (rv);
  49280         }
  49281     }
  49282 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
  49283 
  49284     /* Display entry's counter. */
  49285     LOG_CLI((BSL_META_U(unit,
  49286                         "         statistics=")));
  49287     rv = _field_stat_dump(unit, f_ent);
  49288     if (BCM_FAILURE(rv)) {
  49289         FP_UNLOCK(unit);
  49290     	return (rv);
  49291     }
  49292     LOG_CLI((BSL_META_U(unit,
  49293                         "\n")));
  49294 
  49295     FP_UNLOCK(unit);
  49296     return (BCM_E_NONE);
  49297 }
  49298 /*
  49299  * Function: _bcm_field_group_dump
  49300  *
  49301  * Purpose:
  49302  *     Show contents of a field group.
  49303  *
  49304  * Parameters:
  49305  *     unit  - BCM device number
  49306  *     group - Field group to dump
  49307  *     stage - -1 for print all groups otherwise stage id
  49308  *
  49309  * Returns:
  49310  *     Nothing.
  49311  */
  49312 int
  49313 _bcm_esw_field_group_dump(int unit, bcm_field_group_t group, int stage)
  49314 {
  49315     _field_stage_t      *stage_fc;
  49316     _field_group_t      *fg;
  49317     int                 enable = 0;
  49318     int                 parts_count = 0;
  49319     int                 idx;
  49320     char                buf[SOC_PBMP_FMT_LEN];
  49321     int                 rv;
  49322     int entry_count;
  49323     int entry_index;
  49324     bcm_field_entry_t *entry_ids;
  49325 
  49326     FP_LOCK(unit);
  49327 
  49328 #if defined(BCM_TOMAHAWK3_SUPPORT)
  49329     if ((soc_feature(unit, soc_feature_sw_mmu_flush_rqe_operation)) &&
  49330         (group == _FP_INTERNAL_RESERVED_EM_ID)) {
  49331          FP_UNLOCK(unit);
  49332          return BCM_E_NONE;
  49333     }
  49334 #endif
  49335 
  49336 
  49337     rv = _field_group_get(unit, group, &fg);
  49338     if (BCM_FAILURE(rv)) {
  49339         FP_UNLOCK(unit);
  49340         return (rv);
  49341     }
  49342 
  49343 #if defined(BCM_TOMAHAWK_SUPPORT)
  49344     if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  49345         (_BCM_FIELD_STAGE_CLASS == fg->stage_id)) {
  49346         rv = _bcm_field_th_class_group_dump(unit,fg);
  49347         FP_UNLOCK(unit);
  49348         return (rv);
  49349     }
  49350 #endif /* BCM_TOMAHAWK_SUPPORT */
  49351 
  49352     rv = _field_stage_control_get(unit, fg->stage_id, &stage_fc);
  49353     if (BCM_FAILURE(rv)) {
  49354         FP_UNLOCK(unit);
  49355         return (rv);
  49356     }
  49357 
  49358     rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
  49359                                             fg->flags, &parts_count);
  49360     if (BCM_FAILURE(rv)) {
  49361         FP_UNLOCK(unit);
  49362         return (rv);
  49363     }
  49364 
  49365     if ((fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) &&
  49366         (fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE)) {
  49367         LOG_CLI((BSL_META_U(unit,
  49368                             "Quad wide intra-slice group, ")));
  49369     } else if ((fg->flags & _FP_GROUP_INTRASLICE_DOUBLEWIDE) &&
  49370                (fg->flags & _FP_GROUP_SPAN_SINGLE_SLICE)) {
  49371         if (!((soc_feature(unit, soc_feature_ifp_no_narrow_mode_support) ||
  49372                (soc_feature(unit, soc_feature_hx5_style_ifp_no_narrow_mode_support))) &&
  49373                (_BCM_FIELD_STAGE_INGRESS == stage_fc->stage_id))) {
  49374               LOG_CLI((BSL_META_U(unit,
  49375                             "Intra-slice double wide group, ")));
  49376         }
  49377     }
  49378     LOG_CLI((BSL_META_U(unit,
  49379              "GID %10d: gid=0x%x, instance=%d mode=%s, stage=%s "), group,
  49380              fg->gid, fg->instance,
  49381              _field_group_mode_name(unit, fg->flags, stage_fc),
  49382              _field_stage_name(stage_fc)));
  49383     bcm_esw_field_group_enable_get(unit, group, &enable);
  49384     if (enable) {
  49385         LOG_CLI((BSL_META_U(unit,"lookup=Enabled, ")));
  49386     } else {
  49387         LOG_CLI((BSL_META_U(unit,"lookup=Disabled, ")));
  49388     }
  49389 
  49390     LOG_CLI((BSL_META_U(unit,
  49391                         "ActionResId={%d}, "), fg->action_res_id));
  49392     LOG_VERBOSE(BSL_LS_BCM_FP,
  49393                 (BSL_META_U(unit,
  49394                       "VMAP={%d %d %d}, "),
  49395                       fg->vmap_group[0], fg->vmap_group[1], fg->vmap_group[2]));
  49396 
  49397     LOG_CLI((BSL_META_U(unit,
  49398                     "pbmp={%s}\n"), SOC_PBMP_FMT(fg->pbmp, buf)));
  49399 
  49400     _field_qset_dump("         qset=", fg->qset, ",\n");
  49401 
  49402 #if defined(BCM_TOMAHAWK_SUPPORT)
  49403     if ((soc_feature(unit, soc_feature_td3_style_fp) &&
  49404         (_BCM_FIELD_STAGE_INGRESS == fg->stage_id)) ||
  49405         (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id) ||
  49406         (_BCM_FIELD_STAGE_FLOWTRACKER) == fg->stage_id) {
  49407         _field_aset_dump("         aset=", fg->aset, ",\n");
  49408     }
  49409 
  49410     if (soc_feature(unit, soc_feature_field_preselector_support) &&
  49411         (fg->flags & _FP_GROUP_PRESELECTOR_SUPPORT)) {
  49412        uint8              not_first = 0;
  49413 
  49414        LOG_CLI((BSL_META_U(unit,
  49415                     "         preselectors={")));
  49416        for (idx = 0; idx < _FP_PRESEL_ENTRIES_MAX_PER_GROUP; idx++) {
  49417            if (fg->presel_ent_arr[idx] != NULL) {
  49418               if (not_first) {
  49419                  LOG_CLI((BSL_META_U(unit, ", ")));
  49420               }
  49421               LOG_CLI((BSL_META_U(unit, "%d"), fg->presel_ent_arr[idx]->presel_id));
  49422               not_first = 1;
  49423            }
  49424        }
  49425        LOG_CLI((BSL_META_U(unit, "}\n\r")));
  49426     }
  49427 #endif /* BCM_TOMAHAWK_SUPPORT */
  49428 
  49429     if (fg->hintid != 0) {
  49430         LOG_CLI((BSL_META_U(unit,"         HintId=%d\n"),fg->hintid));
  49431     }
  49432 
  49433 #if defined(BCM_TOMAHAWK_SUPPORT)
  49434     if (soc_feature(unit, soc_feature_field_preselector_support) &&
  49435         ((_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id) ||
  49436          (_BCM_FIELD_STAGE_INGRESS == fg->stage_id) ||
  49437          (_BCM_FIELD_STAGE_FLOWTRACKER == fg->stage_id))) {
  49438         /* Lot of values to print. So we will revisit if there are
  49439          * any debugging requirements. */
  49440         for (idx = 0; ((idx < parts_count) && (1 != parts_count)); idx++) {
  49441             LOG_CLI((BSL_META_U(unit,
  49442                                "         Qualifiers in Part-%d:"), idx));
  49443             _field_qual_list_dump(" ", fg, idx,",\n");
  49444         }
  49445     } else
  49446 #endif
  49447     if ((_BCM_FIELD_STAGE_LOOKUP == fg->stage_id) ||
  49448                (_BCM_FIELD_STAGE_EGRESS == fg->stage_id) ||
  49449                (_BCM_FIELD_STAGE_INGRESS == fg->stage_id)) {
  49450         for (idx = 0; idx < parts_count; idx++) {
  49451             sal_sprintf(buf, "         selcodes[%d]=\n", idx);
  49452             _field_selcode_dump(unit, buf, fg->sel_codes + idx,  ", ",
  49453                                                          fg->stage_id);
  49454             _field_qual_list_dump(" ",fg, idx,",\n");
  49455 
  49456         }
  49457     }
  49458 
  49459     LOG_CLI((BSL_META_U(unit,"\n")));
  49460 
  49461     /* Print the primary slice data. */
  49462     LOG_CLI((BSL_META_U(unit,"         group_priority= %d\n"), fg->priority));
  49463 
  49464     LOG_CLI((BSL_META_U(unit,"         slice_primary =")));
  49465 
  49466     _field_slice_dump(unit, "  ", fg, &fg->slices[0], "\n");
  49467 
  49468     /* Print the secondary slice data. */
  49469     if ((fg->flags & _FP_GROUP_SPAN_DOUBLE_SLICE) ||
  49470         (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE)) {
  49471         LOG_CLI((BSL_META_U(unit,"         slice_secondary = {slice_number=%d}\n"),
  49472                             fg->slices[1].slice_number));
  49473     }
  49474 
  49475     /* Print the tertiary slice data. */
  49476     if (fg->flags & _FP_GROUP_SPAN_TRIPLE_SLICE) {
  49477         LOG_CLI((BSL_META_U(unit,"         slice_ternary = {slice_number=%d}\n"),
  49478                             fg->slices[2].slice_number));
  49479 
  49480     }
  49481 #if defined(BCM_TOMAHAWK_SUPPORT) /* BCM_TOMAHAWK_SUPPORT */
  49482     if (soc_feature(unit, soc_feature_field_multi_pipe_support)
  49483         && ((_BCM_FIELD_STAGE_INGRESS == fg->stage_id) ||
  49484             (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id) ||
  49485             (_BCM_FIELD_STAGE_FLOWTRACKER == fg->stage_id))) {
  49486         /* Get TH IFP group's status. */
  49487         rv = _bcm_field_th_group_status_calc(unit, fg);
  49488     } else
  49489 #endif /* !BCM_TOMAHAWK_SUPPORT */
  49490     {
  49491         /* Update the numbers of free entries, meters and counters. */
  49492         rv = _bcm_field_group_status_calc(unit, fg);
  49493     }
  49494 
  49495     /* Print group used resources status */
  49496     if (BCM_SUCCESS(rv)) {
  49497         LOG_CLI((BSL_META_U(unit,"         group_status=")));
  49498         _field_group_status_dump(&fg->group_status);
  49499         LOG_CLI((BSL_META_U(unit,"\n")));
  49500     }
  49501 
  49502 #if defined(BCM_TOMAHAWK_SUPPORT) /* BCM_TOMAHAWK_SUPPORT */
  49503     if ((soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  49504         (-1 != stage)) &&
  49505         ((_BCM_FIELD_STAGE_INGRESS == fg->stage_id) ||
  49506         (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id))) {
  49507         for (idx = 0; idx < parts_count; idx++) {
  49508             LOG_CLI((BSL_META_U(unit,
  49509                             "Keygen_profile%d=%u\n"), fg->instance,
  49510                         fg->ext_codes[idx].keygen_index));
  49511         }
  49512     }
  49513 #endif /* !BCM_TOMAHAWK_SUPPORT */
  49514 
  49515     /* Print group's entries */
  49516     rv = bcm_esw_field_entry_multi_get(unit, group, 0, NULL, &entry_count);
  49517 
  49518     if (BCM_SUCCESS(rv))
  49519     {
  49520         entry_ids = sal_alloc(entry_count * sizeof (bcm_field_entry_t),
  49521             "Entry ID array");
  49522 
  49523         if (entry_ids == NULL)
  49524         {
  49525             rv = BCM_E_MEMORY;
  49526         }
  49527         else
  49528         {
  49529             rv = bcm_esw_field_entry_multi_get(unit, group, entry_count,
  49530                 entry_ids, &entry_count);
  49531 
  49532             if (BCM_SUCCESS(rv))
  49533             {
  49534                 for (entry_index = 0; entry_index < entry_count;
  49535                     ++entry_index)
  49536                 {
  49537                     _bcm_esw_field_entry_dump(unit, entry_ids[entry_index], stage);
  49538                 }
  49539             }
  49540 
  49541             sal_free(entry_ids);
  49542         }
  49543     }
  49544 
  49545     FP_UNLOCK(unit);
  49546     return (BCM_E_NONE);
  49547 }
  49548 
  49549 /*
  49550  * Function: bcm_field_show
  49551  *
  49552  * Purpose:
  49553  *     Show current S/W state if compiled in debug mode.
  49554  *
  49555  * Parameters:
  49556  *     unit - BCM device number
  49557  *     pfx - Character string to prefix output lines
  49558  *
  49559  * Returns:
  49560  *     Nothing.
  49561  */
  49562 int
  49563 _bcm_esw_field_show(int unit, const char *pfx, int stage)
  49564 {
  49565     _field_group_t      *fg;
  49566     _field_stage_t      *stage_fc;
  49567     _field_control_t    *fc;
  49568     int                  entry_ratio;  /* Invalid entries ratio. */
  49569     int                  rv = 0;
  49570 
  49571     FP_LOCK(unit);
  49572     rv = _field_control_get(unit, &fc);
  49573     if (BCM_FAILURE(rv)) {
  49574         FP_UNLOCK(unit);
  49575         return rv;
  49576     }
  49577 
  49578     stage_fc = fc->stages;
  49579 
  49580     LOG_CLI((BSL_META_U(unit,
  49581                         "%s:\tunit %d:\n"), pfx, unit));
  49582 
  49583     while(stage_fc) {
  49584 
  49585         if ((stage != -1) &&
  49586                 (stage != stage_fc->stage_id)) {
  49587             stage_fc = stage_fc->next;
  49588             continue;
  49589         }
  49590         rv = _bcm_field_group_stage_validate(unit, stage_fc->stage_id);
  49591         if (BCM_FAILURE(rv)) {
  49592             stage_fc = stage_fc->next;
  49593             continue;
  49594         }
  49595 
  49596         entry_ratio = (stage_fc->flags & _FP_STAGE_QUARTER_SLICE) ? 4:
  49597             ((stage_fc->flags & _FP_STAGE_HALF_SLICE) ? 2 : 1);
  49598 
  49599         switch (stage_fc->stage_id) {
  49600           case _BCM_FIELD_STAGE_INGRESS:
  49601               LOG_CLI((BSL_META_U(unit,
  49602                                   "PIPELINE STAGE INGRESS\n")));
  49603               /*
  49604                * 80 bit mode is not supported in HX5 in IFP.
  49605                * But IFP_TCAM is still available 80 bit view.
  49606                * stage_fc->tcam_sz will be initialized as depth of IFP_TCAM.
  49607                * As 160 bit mode is called as Single wide mode, depth has to
  49608                * be halved.
  49609                */
  49610                {
  49611                    int tcam_sz;
  49612                    tcam_sz = soc_feature(unit, soc_feature_hx5_style_ifp_no_narrow_mode_support) ?
  49613                               (stage_fc->tcam_sz/2) : (stage_fc->tcam_sz);
  49614                    LOG_CLI((BSL_META_U(unit,
  49615                                    "%s:\t      :tcam_sz=%d(%#x),"),
  49616                                pfx, tcam_sz/entry_ratio,
  49617                                tcam_sz/entry_ratio));
  49618                }
  49619               break;
  49620 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT)
  49621           case _BCM_FIELD_STAGE_LOOKUP:
  49622               LOG_CLI((BSL_META_U(unit,
  49623                                   "PIPELINE STAGE LOOKUP\n")));
  49624               LOG_CLI((BSL_META_U(unit,
  49625                               "%s:\t      :tcam_sz=%d(%#x),"),
  49626                  pfx, stage_fc->tcam_sz/entry_ratio,
  49627                       stage_fc->tcam_sz/entry_ratio));
  49628               break;
  49629           case _BCM_FIELD_STAGE_EGRESS:
  49630               LOG_CLI((BSL_META_U(unit,
  49631                                   "PIPELINE STAGE EGRESS\n")));
  49632               LOG_CLI((BSL_META_U(unit,
  49633                               "%s:\t      :tcam_sz=%d(%#x),"),
  49634                  pfx, stage_fc->tcam_sz/entry_ratio,
  49635                       stage_fc->tcam_sz/entry_ratio));
  49636               break;
  49637 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */
  49638           case _BCM_FIELD_STAGE_EXTERNAL:
  49639               LOG_CLI((BSL_META_U(unit,
  49640                                   "PIPELINE STAGE EXTERNAL\n")));
  49641               LOG_CLI((BSL_META_U(unit,
  49642                               "%s:\t      :tcam_sz=%d(%#x),"),
  49643                  pfx, stage_fc->tcam_sz, stage_fc->tcam_sz));
  49644               break;
  49645 #ifdef BCM_TOMAHAWK_SUPPORT
  49646           case _BCM_FIELD_STAGE_EXACTMATCH:
  49647               if (soc_feature(unit, soc_feature_field_exact_match_support)) {
  49648                   LOG_CLI((BSL_META_U(unit,
  49649                                   "PIPELINE STAGE EXACTMATCH\n")));
  49650                   LOG_CLI((BSL_META_U(unit,
  49651                                   "%s:\t      :tcam_sz=%d(%#x),"),
  49652                               pfx, stage_fc->tcam_sz, stage_fc->tcam_sz));
  49653               }
  49654               break;
  49655 #endif
  49656 #if defined(BCM_FLOWTRACKER_SUPPORT)
  49657           case _BCM_FIELD_STAGE_FLOWTRACKER:
  49658               if (soc_feature(unit, soc_feature_field_flowtracker_support)) {
  49659                   LOG_CLI((BSL_META_U(unit,
  49660                               "PIPELINE STAGE FLOWTRACKER\n")));
  49661                   LOG_CLI((BSL_META_U(unit,
  49662                               "%s:\t      :tcam_sz=%d(%#x),"),
  49663                           pfx, stage_fc->tcam_sz, stage_fc->tcam_sz));
  49664               }
  49665               break;
  49666 #endif
  49667 
  49668           default:
  49669               break;
  49670         }
  49671 
  49672         /* Skip for Stage Class alone. */
  49673         if (stage_fc->stage_id != _BCM_FIELD_STAGE_CLASS) {
  49674             LOG_CLI((BSL_META_U(unit,
  49675                         " tcam_slices=%d,"), stage_fc->tcam_slices));
  49676             LOG_CLI((BSL_META_U(unit,
  49677                         " tcam_ext_numb=%d,"), fc->tcam_ext_numb));
  49678             LOG_CLI((BSL_META_U(unit,
  49679                         "\n")));
  49680         }
  49681 
  49682 #ifdef BCM_TOMAHAWK_SUPPORT
  49683         if (soc_feature(unit, soc_feature_field_preselector_support) &&
  49684            (stage_fc->stage_id == stage)) {
  49685             _bcm_field_presel_dump(unit, -1, stage);
  49686         }
  49687         if ((-1 != stage) && (stage_fc->stage_id == _BCM_FIELD_STAGE_CLASS)) {
  49688             _field_dump_class(unit, pfx, -1);
  49689         }
  49690 #endif
  49691         stage_fc = stage_fc->next;
  49692 
  49693     }
  49694 
  49695     /* Print the groups, along with their entries. */
  49696     for (fg = fc->groups; fg != NULL ; fg = fg->next) {
  49697         if ((stage != -1) &&
  49698                 (stage != fg->stage_id)) {
  49699             continue;
  49700         }
  49701 #if defined(BCM_TOMAHAWK_SUPPORT)
  49702         if (soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  49703             (_BCM_FIELD_STAGE_CLASS == fg->stage_id)) {
  49704             /* Don't dump Class Group in 'fp show' command */
  49705             continue;
  49706         }
  49707         /*
  49708          * Don't dump ExactMatch based field configuration related to
  49709          * Flowtracker module if soc property FLOWTRACKER_ENABLE is enabled.
  49710          */
  49711         if ((soc_property_get(unit, spn_FLOWTRACKER_ENABLE, 0) == 1) &&
  49712                 soc_feature(unit, soc_feature_field_multi_pipe_support) &&
  49713                 (_BCM_FIELD_STAGE_EXACTMATCH == fg->stage_id)) {
  49714             continue;
  49715         }
  49716 #endif /* BCM_TOMAHAWK_SUPPORT */
  49717         _bcm_esw_field_group_dump(unit, fg->gid, stage);
  49718     }
  49719 
  49720     FP_UNLOCK(unit);
  49721     return (BCM_E_NONE);
  49722 }
  49723 /*
  49724  * Function: _bcm_esw_field_range_show
  49725  *
  49726  * Purpose:
  49727  *     Show current S/W state of field range if compiled in debug mode.
  49728  *
  49729  * Parameters:
  49730  *     unit - BCM device number
  49731  *     pfx - Character string to prefix output lines
  49732  *
  49733  * Returns:
  49734  *     Nothing.
  49735  */
  49736 int
  49737 _bcm_esw_field_range_show(int unit, const char *pfx, int stage)
  49738 {
  49739     int                 rv = BCM_E_NONE;
  49740     _field_range_t      *fr;
  49741     _field_stage_t      *stage_fc;
  49742     _field_control_t    *fc;
  49743 
  49744     FP_LOCK(unit);
  49745     rv = _field_control_get(unit, &fc);
  49746     if (BCM_FAILURE(rv)) {
  49747         FP_UNLOCK(unit);
  49748         return rv;
  49749     }
  49750 
  49751     stage_fc = fc->stages;
  49752 
  49753     while(stage_fc) {
  49754         rv = _bcm_field_group_stage_validate(unit, stage_fc->stage_id);
  49755         if (BCM_FAILURE(rv)) {
  49756             stage_fc = stage_fc->next;
  49757             continue;
  49758         }
  49759         /* Display any range checkers defined. */
  49760         if ((_BCM_FIELD_STAGE_INGRESS  == stage_fc->stage_id) ||
  49761            ((_BCM_FIELD_STAGE_EXTERNAL == stage_fc->stage_id) && (stage == -1))){
  49762             for (fr = stage_fc->ranges; fr != NULL; fr = fr->next) {
  49763                 _field_range_dump(pfx, fr);
  49764             }
  49765         }
  49766         stage_fc = stage_fc->next;
  49767     }
  49768 
  49769     FP_UNLOCK(unit);
  49770     return (BCM_E_NONE);
  49771 }
  49772 /*
  49773  * Function: _bcm_esw_field_udf_show
  49774  *
  49775  * Purpose:
  49776  *     Show current S/W state of field range if compiled in debug mode.
  49777  *
  49778  * Parameters:
  49779  *     unit - BCM device number
  49780  *     pfx - Character string to prefix output lines
  49781  *
  49782  * Returns:
  49783  *     Nothing.
  49784  */
  49785 int
  49786 _bcm_esw_field_udf_show(int unit, const char *pfx)
  49787 {
  49788     _field_control_t    *fc;
  49789     int                 idx = 0;
  49790     int                 rv = BCM_E_NONE;
  49791 
  49792     FP_LOCK(unit);
  49793     rv = _field_control_get(unit, &fc);
  49794     if (BCM_FAILURE(rv)) {
  49795         FP_UNLOCK(unit);
  49796         return rv;
  49797     }
  49798     /* Print the any defined UDFs. */
  49799     for (idx = 0; idx < BCM_FIELD_USER_NUM_UDFS; idx++) {
  49800         if (fc->udf[idx].valid) {
  49801         LOG_CLI((BSL_META_U(unit,
  49802                             "%s:\tudf %d: use_count=%d, udf_num=%s, user_num=%d\n"),
  49803                  pfx, idx, fc->udf[idx].use_count,
  49804                  _field_qual_name(fc->udf[idx].udf_num + _bcmFieldQualifyData0),
  49805                  fc->udf[idx].user_num));
  49806         }
  49807     }
  49808     FP_UNLOCK(unit);
  49809     return (BCM_E_NONE);
  49810 }
  49811 
  49812 /*
  49813  * Function:
  49814  *     _bcm_esw_field_group_info_key_get
  49815  *
  49816  * Purpose:
  49817  *     To retrieve qualifier key info for the given group
  49818  *
  49819  * Parmeters:
  49820  *     unit               - (IN)BCM device number.
  49821  *     group              - (IN)Field group id
  49822  *     max_parts_count    - (IN)Maximum TCAM parts
  49823  *     qual_offset        - (OUT)Qualifier used to select the correct slice
  49824  *     num_parts_count    - (OUT)Number of TCAM parts present for group
  49825  *
  49826  * Returns:
  49827  *     BCM_E_XXX
  49828  */
  49829 int
  49830 _bcm_esw_field_group_info_key_get(int unit,
  49831                                   bcm_field_group_t group,
  49832                                   int max_parts_count,
  49833                                   _bcm_field_group_qual_t **qual_arr,
  49834                                   int *num_parts_count)
  49835 {
  49836     int                       rv = BCM_E_NONE;
  49837     int                       part_idx = 0;
  49838     _field_group_t            *fg = NULL;
  49839 
  49840     if ((NULL == qual_arr) || (NULL == num_parts_count)){
  49841         return BCM_E_PARAM;
  49842     }
  49843 
  49844     FP_LOCK(unit);
  49845 
  49846     rv = _field_group_get(unit, group, &fg);
  49847     if (BCM_FAILURE(rv)) {
  49848         FP_UNLOCK(unit);
  49849         return (rv);
  49850     }
  49851 
  49852     /* Get number of tcam parts to be read. */
  49853     rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
  49854                                             fg->flags, num_parts_count);
  49855     if (BCM_FAILURE(rv)) {
  49856         FP_UNLOCK(unit);
  49857         return (rv);
  49858     }
  49859 
  49860     if (*num_parts_count > max_parts_count) {
  49861         FP_UNLOCK(unit);
  49862         return BCM_E_PARAM;
  49863     }
  49864 
  49865     /* Iterate over all entry parts. */
  49866     for (part_idx = 0; part_idx < *num_parts_count; part_idx++) {
  49867         sal_memcpy(&qual_arr[_FP_ENTRY_TYPE_DEFAULT][part_idx],
  49868                    &(fg->qual_arr[_FP_ENTRY_TYPE_DEFAULT][part_idx]),
  49869                    sizeof(_bcm_field_group_qual_t));
  49870     }
  49871 
  49872     FP_UNLOCK(unit);
  49873     return (rv);
  49874 }
  49875 
  49876 /*
  49877  * Function:
  49878  *     _bcm_field_slice_idx_allocate
  49879  *
  49880  * Purpose:
  49881  *     Allocate free index in slice
  49882  *
  49883  * Parmeters:
  49884  *     unit               - (IN) BCM device number.
  49885  *     stage_fc           - (IN) Stage field control structure.
  49886  *     fg                 - (IN) Field group structure
  49887  *     fs                 - (IN) Field slice structure.
  49888  *     slice_idx          - (OUT) slice index allocated.
  49889  *
  49890  * Returns:
  49891  *     BCM_E_XXX
  49892  */
  49893 STATIC
  49894 int _bcm_field_slice_idx_allocate(int unit,
  49895                                   _field_stage_t *stage_fc,
  49896                                   _field_group_t *fg,
  49897                                   _field_slice_t *fs,
  49898                                   uint32 *slice_idx)
  49899 {
  49900     int rv = BCM_E_NONE;
  49901     uint32 idx = 0;
  49902 
  49903     /*
  49904      * In External TCAM, each slice has different number of entries
  49905      *     Also, allocation happens only at Install time
  49906      */
  49907     if (fg->stage_id == _BCM_FIELD_STAGE_EXTERNAL) {
  49908         idx = _FP_INVALID_INDEX;
  49909     } else if (fg->stage_id == _BCM_FIELD_STAGE_EXACTMATCH) {
  49910         idx = _FP_INVALID_INDEX;
  49911     } else if (fs->slice_flags & _BCM_FIELD_SLICE_MULTIMODE_ENTRIES) {
  49912         rv = _field_multimode_slice_idx_alloc(unit,
  49913                                 stage_fc, fg, fs, &idx);
  49914         if (rv == BCM_E_RESOURCE) {
  49915             rv = _field_multimode_slice_entry_compress(unit, fs);
  49916 
  49917             if (BCM_FAILURE(rv)) {
  49918                 return rv;
  49919             }
  49920             rv = _field_multimode_slice_idx_alloc(unit,
  49921                                     stage_fc, fg, fs, &idx);
  49922         }
  49923         BCM_IF_ERROR_RETURN(rv);
  49924     } else {
  49925         /* Get index for primary entry. */
  49926         for (idx = 0; idx < fs->entry_count; idx++) {
  49927             if (NULL == fs->entries[idx]) {
  49928                 break;
  49929             }
  49930         }
  49931     }
  49932 
  49933     *slice_idx = idx;
  49934     return rv;
  49935 }
  49936 
  49937 /*
  49938  * Function:
  49939  *    _field_multimode_slice_idx_alloc
  49940  *
  49941  * Purpose:
  49942  *    Allocate a free index for entry creation in mixed entry capable slice.
  49943  *
  49944  * Parameters:
  49945  *    unit       - (IN) BCM device number.
  49946  *    stage_fc   - (IN) Stage field control structure.
  49947  *    fg         - (IN) Field group structure.
  49948  *    fs         - (IN) Field slice structure.
  49949  *    slice_idx  - (OUT) slice index to be allocate
  49950  *
  49951  * Returns:
  49952  *    BCM_E_PARAM       - Input params are wrong.
  49953  *    BCM_E_RESOURCE    - Failed to allocate index in given slice.
  49954  *    BCM_E_NONE        - Success.
  49955  */
  49956 STATIC int
  49957 _field_multimode_slice_idx_alloc(int unit,
  49958                                  _field_stage_t *stage_fc,
  49959                                  _field_group_t *fg,
  49960                                  _field_slice_t *fs,
  49961                                  uint32 *slice_idx)
  49962 {
  49963     int rv = BCM_E_NONE;
  49964     int index = 0;
  49965     int slice_sz = 0;
  49966     int idx_type;
  49967 
  49968     if ((stage_fc == NULL) || (fg == NULL) ||
  49969         (fs == NULL) || (slice_idx == NULL)) {
  49970         return (BCM_E_PARAM);
  49971     }
  49972 
  49973     *slice_idx = _FP_INVALID_INDEX;
  49974     _BCM_FIELD_ENTRIES_IN_SLICE(unit, fg, fs, slice_sz);
  49975     for (index = 0; index < slice_sz; index++) {
  49976         _field_slice_index_type_get(unit, fg, fs, index, &idx_type);
  49977         if (idx_type == _BCM_FIELD_SLICE_IDX_TYPE_FREE) {
  49978             *slice_idx = index;
  49979             break;
  49980         }
  49981     }
  49982 
  49983     if (index == slice_sz) {
  49984         rv = BCM_E_RESOURCE;
  49985     }
  49986     return rv;
  49987 }
  49988 
  49989 /*
  49990  * Function:
  49991  *    _field_multimode_slice_entry_move
  49992  *
  49993  * Purpose:
  49994  *    Move field entry in the slice by given amount.
  49995  *
  49996  * Parameters:
  49997  *    unit       - (IN) BCM device number.
  49998  *    f_ent      - (IN) field entry structure.
  49999  *    amount     - (IN) amount of movement.
  50000  *
  50001  * Returns:
  50002  *    BCM_E_PARAM       - Null field stage control structure.
  50003  *    BCM_E_XXX         - For other errors.
  50004  *    BCM_E_NONE        - Success.
  50005  * Note:
  50006  *    Currently, entry movement in same slice is supported.
  50007  */
  50008 STATIC int
  50009 _field_multimode_slice_entry_move(int unit,
  50010                                  _field_slice_t *fs,
  50011                                  _field_entry_t *f_ent,
  50012                                  int amount)
  50013 {
  50014     int rv = BCM_E_NONE;                    /* Operation return status.      */
  50015     _field_control_t *fc = NULL;            /* Field control structure.      */
  50016     _field_stage_t *stage_fc = NULL;        /* Stage field control.          */
  50017     _field_group_t *fg = NULL;              /* Field group control.          */
  50018     int parts_count = 0;                    /* Field entry parts count.      */
  50019     int part;                               /* Part iterator.                */
  50020     int new_slice_idx    = 0;               /* New Slice index for entry.    */
  50021     int new_pri_tcam_idx = 0;               /* New Primary tcam index.       */
  50022     int  tcam_idx_old[_FP_MAX_ENTRY_WIDTH]; /* Original entry tcam index.    */
  50023     int  tcam_idx_new[_FP_MAX_ENTRY_WIDTH]; /* Next tcam index for the entry.*/
  50024 
  50025     /* validate input params */
  50026     if ((NULL == fs) || (NULL == f_ent)) {
  50027         return (BCM_E_PARAM);
  50028     }
  50029 
  50030     LOG_DEBUG(BSL_LS_BCM_FP,
  50031               (BSL_META_U(unit,
  50032                "FP(unit %d) vverb: BEGIN _field_multimode_slice_entry_move(entry=%d,"
  50033                " amount=%d)\n"), unit, f_ent->eid, amount));
  50034 
  50035     /* Initialization. */
  50036     sal_memset(tcam_idx_old, 0,  (_FP_MAX_ENTRY_WIDTH * sizeof(int)));
  50037     sal_memset(tcam_idx_new, 0, (_FP_MAX_ENTRY_WIDTH * sizeof(int)));
  50038     fg = f_ent->group;
  50039 
  50040     new_slice_idx = f_ent->slice_idx + amount;
  50041 
  50042     if (amount == 0) {
  50043         LOG_WARN(BSL_LS_BCM_FP,
  50044                  (BSL_META_U(unit,
  50045                   "Warning: moving entry=%d, same slice_idx=%d(%#x)\n"),
  50046                   f_ent->eid, f_ent->slice_idx, f_ent->slice_idx));
  50047         return (BCM_E_NONE);
  50048     }
  50049 
  50050     /* Get field control structure. */
  50051     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  50052 
  50053     /* Get stage field control structure. */
  50054     rv =  _field_stage_control_get(unit, fg->stage_id, &stage_fc);
  50055     BCM_IF_ERROR_RETURN(rv);
  50056 
  50057     /* Get number of parts. */
  50058     rv = _bcm_field_entry_tcam_parts_count (unit, fg->stage_id,
  50059                                             fg->flags, &parts_count);
  50060     BCM_IF_ERROR_RETURN(rv);
  50061 
  50062     /* Get new primary tcam index for entry. */
  50063     rv = _bcm_field_slice_offset_to_tcam_idx(unit, stage_fc,
  50064                                             fg->instance, fs->slice_number,
  50065                                             new_slice_idx, &new_pri_tcam_idx);
  50066     BCM_IF_ERROR_RETURN(rv);
  50067 
  50068     /* Calculate the new and old TCAM indexes. */
  50069     for (part = 0; part < parts_count; part++) {
  50070         rv = _bcm_field_entry_tcam_idx_get(unit, f_ent + part,
  50071                                             &tcam_idx_old[part]);
  50072         BCM_IF_ERROR_RETURN(rv);
  50073 
  50074         /* Calculate entry part tcam offset. */
  50075         rv = _bcm_field_entry_part_tcam_idx_get(unit, f_ent,
  50076                                 new_pri_tcam_idx, part, &tcam_idx_new[part]);
  50077         BCM_IF_ERROR_RETURN(rv);
  50078     }
  50079 
  50080     /* Call Entry move if installed */
  50081     if (f_ent->flags  & _FP_ENTRY_INSTALLED) {
  50082         rv = fc->functions.fp_entry_move(unit, f_ent, parts_count,
  50083                                             tcam_idx_old, tcam_idx_new);
  50084         BCM_IF_ERROR_RETURN(rv);
  50085     }
  50086 
  50087     rv = _field_entry_slice_idx_change(unit, f_ent, parts_count, tcam_idx_new);
  50088 
  50089     return rv;
  50090 }
  50091 
  50092 /*
  50093  * Function:
  50094  *    _field_multimode_slice_entry_compress
  50095  *
  50096  * Purpose:
  50097  *    Compress hw entries in mixed entry capable slice
  50098  *
  50099  * Parameters:
  50100  *    unit       - (IN) BCM device number.
  50101  *    fs         - (IN) Field slice control structure.
  50102  *
  50103  * Returns:
  50104  *    BCM_E_PARAM       - Null field stage control structure.
  50105  *    BCM_E_XXX         - Other errors.
  50106  *    BCM_E_NONE        - Success.
  50107  * Note:
  50108  *    Currently, entry movement in same slice is supported.
  50109  */
  50110 STATIC int
  50111 _field_multimode_slice_entry_compress(int unit, _field_slice_t *fs)
  50112 {
  50113     int rv = BCM_E_NONE;
  50114     int to_idx = 0, from_idx = 0;
  50115     int start_idx = 0, end_idx = 0;
  50116 
  50117     if (fs == NULL) {
  50118         return (BCM_E_PARAM);
  50119     }
  50120 
  50121     if (fs->stage_id != _BCM_FIELD_STAGE_FLOWTRACKER) {
  50122         return (BCM_E_INTERNAL);
  50123     }
  50124 
  50125     start_idx = fs->start_tcam_idx;
  50126     end_idx = start_idx + fs->entry_count - 1;
  50127 
  50128     /* Find First hole */
  50129     while ((fs->entries[start_idx] != NULL) &&
  50130             (start_idx != end_idx)) {
  50131         start_idx++;
  50132     }
  50133 
  50134     if (start_idx == end_idx) {
  50135         return BCM_E_RESOURCE;
  50136     }
  50137 
  50138     for (to_idx = start_idx, from_idx = start_idx + 1;
  50139          from_idx <= end_idx; from_idx++) {
  50140         /* If it is single wide entry, move to hole */
  50141         if (fs->entries[from_idx] == NULL) {
  50142             continue;
  50143         }
  50144 
  50145         if (fs->entries[from_idx]->group->flags &
  50146                    _FP_GROUP_DW_DEPTH_EXPANDED) {
  50147             continue;
  50148         }
  50149         rv = _field_multimode_slice_entry_move(unit, fs,
  50150                         fs->entries[from_idx], to_idx - from_idx);
  50151         BCM_IF_ERROR_RETURN(rv);
  50152 
  50153         /* get next free index */
  50154         to_idx++;
  50155         while ((fs->entries[to_idx] != NULL) &&
  50156                 (start_idx != end_idx)) {
  50157             to_idx++;
  50158         }
  50159     }
  50160     return rv;
  50161 }
  50162 
  50163 /*
  50164  * Function:
  50165  *    _field_multimode_slice_entry_shift_down
  50166  *
  50167  * Purpose:
  50168  *    Shift entry down in the mixed-entry capable slice.
  50169  *
  50170  * Parameters:
  50171  *    unit       - (IN) BCM device number.
  50172  *    fg         - (IN) Field group control structure.
  50173  *    target_fs  - (IN) Target flice slice where entry to be shifted.
  50174  *    target_idx - (IN) Corresponding index in target_fs
  50175  *    next_null_fs-(IN) Next slice which has freee entry.
  50176  *    next_null_idx-(IN) Corresponding index in next_null_fs
  50177  *
  50178  * Returns:
  50179  *    BCM_E_PARAM       - Null field stage control structure.
  50180  *    BCM_E_XXX         - For other errors.
  50181  *    BCM_E_NONE        - Success.
  50182  * Note:
  50183  *    Currently, entry movement in same slice is supported.
  50184  */
  50185 STATIC int
  50186 _field_multimode_slice_entry_shift_down(int unit,
  50187                                    _field_group_t *fg,
  50188                                    _field_slice_t *target_fs,
  50189                                    uint16 target_idx,
  50190                                    _field_slice_t *next_null_fs,
  50191                                    uint16 next_null_idx)
  50192 {
  50193     int rv = BCM_E_NONE;
  50194     _field_slice_t *fs = NULL;
  50195     int slice_idx_empty = 0;
  50196     int new_shift_idx = 0;
  50197 
  50198     /* Input parameter check. */
  50199     if ((NULL == target_fs) || (NULL == fg) || (NULL == next_null_fs))  {
  50200         return (BCM_E_PARAM);
  50201     }
  50202     if (target_fs != next_null_fs) {
  50203         return (BCM_E_INTERNAL);
  50204     }
  50205 
  50206     slice_idx_empty = next_null_idx;
  50207     fs = next_null_fs;
  50208 
  50209     /*
  50210      * Idea is Move entries down in the same group based on number of parts.
  50211      */
  50212     while (slice_idx_empty > target_idx) {
  50213         rv = _field_slice_next_match_index_get(unit, fg, fs,
  50214                                             slice_idx_empty, target_idx,
  50215                                             -1, &new_shift_idx);
  50216         BCM_IF_ERROR_RETURN(rv);
  50217 
  50218         /* Perform entry move. */
  50219         rv = _field_multimode_slice_entry_move(unit, fs,
  50220                     fs->entries[new_shift_idx],
  50221                     slice_idx_empty - new_shift_idx);
  50222         BCM_IF_ERROR_RETURN(rv);
  50223 
  50224         slice_idx_empty = new_shift_idx;
  50225     }
  50226 
  50227     return rv;
  50228 }
  50229 
  50230 /*
  50231  * Function:
  50232  *    _field_multimode_slice_entry_shift_up
  50233  *
  50234  * Purpose:
  50235  *    Shift entries up in the mixed-entry capable slice.
  50236  *
  50237  * Parameters:
  50238  *    unit       - (IN) BCM device number.
  50239  *    fg         - (IN) Field group control structure.
  50240  *    target_fs  - (IN) Target flice slice where entry to be shifted.
  50241  *    target_idx - (IN) Corresponding index in target_fs
  50242  *    prev_null_fs-(IN) Previous slice which has freee entry.
  50243  *    prev_null_idx-(IN) Corresponding index in prev_null_fs
  50244  *
  50245  * Returns:
  50246  *    BCM_E_PARAM       - Null field stage control structure.
  50247  *    BCM_E_XXX         - Other errors.
  50248  *    BCM_E_NONE        - Success.
  50249  * Note:
  50250  *    Currently, entry movement in same slice is supported.
  50251  */
  50252 STATIC int
  50253 _field_multimode_slice_entry_shift_up(int unit,
  50254                                       _field_group_t *fg,
  50255                                       _field_slice_t *target_fs,
  50256                                       uint16 target_idx,
  50257                                       _field_slice_t *prev_null_fs,
  50258                                       uint16 prev_null_idx)
  50259 {
  50260     int rv = BCM_E_NONE;
  50261     _field_slice_t *fs = NULL;
  50262     int slice_idx_empty = 0;
  50263     int new_shift_idx = 0;
  50264 
  50265     /* input parameter check. */
  50266     if ((NULL == target_fs) || (NULL == fg) || (NULL == prev_null_fs))  {
  50267         return (BCM_E_PARAM);
  50268     }
  50269     if (target_fs != prev_null_fs) {
  50270         return (BCM_E_INTERNAL);
  50271     }
  50272 
  50273     slice_idx_empty = prev_null_idx;
  50274     fs = prev_null_fs;
  50275 
  50276     /*
  50277      * Idea is move entries up in the same group mode based on number of parts.
  50278      */
  50279     while (slice_idx_empty < target_idx) {
  50280         rv = _field_slice_next_match_index_get(unit, fg, fs,
  50281                                             slice_idx_empty, target_idx,
  50282                                             1, &new_shift_idx);
  50283         BCM_IF_ERROR_RETURN(rv);
  50284 
  50285         /* perform entry move. */
  50286         rv = _field_multimode_slice_entry_move(unit, fs,
  50287                             fs->entries[new_shift_idx],
  50288                             slice_idx_empty - new_shift_idx);
  50289         BCM_IF_ERROR_RETURN(rv);
  50290 
  50291         slice_idx_empty = new_shift_idx;
  50292     }
  50293 
  50294     return rv;
  50295 }
  50296 
  50297 
  50298 int _field_action_match_config_alloc (int unit,
  50299                               bcm_field_action_match_config_t *match_config,
  50300                               _field_action_t *fa)
  50301 {
  50302     uint32 port = 0;
  50303 
  50304     /* Do not allow LB ports */
  50305     if (BCM_PBMP_NOT_NULL(match_config->egr_pbmp)) {
  50306         BCM_PBMP_ITER(match_config->egr_pbmp, port) {
  50307             if (BCM_PBMP_MEMBER(PBMP_LB(unit), port)) {
  50308                 return BCM_E_PARAM;
  50309                 LOG_DEBUG(BSL_LS_BCM_FP, (BSL_META_U(unit,
  50310                         "Field Action Egress Pbmp has Loopback ports\r\n")));
  50311             }
  50312         }
  50313     }
  50314 
  50315     if (BCM_PBMP_NOT_NULL(match_config->egr_pbmp)) {
  50316         _FP_XGS3_ALLOC(fa->egress_pbmp, sizeof(bcm_pbmp_t),
  50317                        "Field Action Pbmp Allocation ");
  50318         if (NULL == fa->egress_pbmp) {
  50319             return (BCM_E_MEMORY);
  50320         }
  50321         BCM_PBMP_ASSIGN(*(fa->egress_pbmp), match_config->egr_pbmp);
  50322     }
  50323 
  50324     (fa->elephant_pkts_only) = (match_config->elephant_pkt_only);
  50325     return BCM_E_NONE;
  50326 }
  50327 
  50328 
  50329 /*
  50330  * Function:
  50331  *     _field_ddrop_profile_get
  50332  * Purpose:
  50333  *     Get the redirect profile for the unit
  50334  * Parameters:
  50335  *     unit             - BCM device number
  50336  *     ddrop_profile - (OUT) redirect profile
  50337  * Returns:
  50338  *     BCM_E_XXX
  50339  * Notes:
  50340  *     For triumph, External TCAM and IFP refer to same IFP_EGRESS_PORT_CHECK_FOR_DROPm
  50341  */
  50342 int
  50343 _bcm_field_ddrop_profile_get(int unit,
  50344                                 soc_profile_mem_t **ddrop_profile)
  50345 {
  50346     _field_control_t *fc = NULL;
  50347 
  50348     /* Get field control structure. */
  50349     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  50350 
  50351     *ddrop_profile = &fc->ddrop_profile;
  50352 
  50353     return (BCM_E_NONE);
  50354 }
  50355 
  50356 /*
  50357  * Function:
  50358  *     _bcm_field_ddrop_profile_ref_count_get
  50359  * Purpose:
  50360  *     Get redirect profile entry use count.
  50361  * Parameters:
  50362  *     unit      - (IN) BCM device number.
  50363  *     index     - (IN) Profile entry index.
  50364  *     ref_count - (OUT) redirect profile use count.
  50365  * Returns:
  50366  *     BCM_E_XXX
  50367  */
  50368 int
  50369 _bcm_field_ddrop_profile_ref_count_get(int unit,
  50370                                               int index,
  50371                                               int *ref_count)
  50372 {
  50373     soc_profile_mem_t *ddrop_profile;
  50374 
  50375     if (NULL == ref_count) {
  50376         return (BCM_E_PARAM);
  50377     }
  50378 
  50379     /* Get the redirect profile */
  50380     BCM_IF_ERROR_RETURN
  50381         (_bcm_field_ddrop_profile_get(unit, &ddrop_profile));
  50382 
  50383     return (soc_profile_mem_ref_count_get(unit, ddrop_profile,
  50384                                           index, ref_count));
  50385 }
  50386 
  50387 /*
  50388  * Function:
  50389  *     _bcm_field_ddrop_profile_delete
  50390  * Purpose:
  50391  *     Delete redirect profile entry.
  50392  * Parameters:
  50393  *     unit      - (IN) BCM device number.
  50394  *     index     - (IN) Profile entry index.
  50395  * Returns:
  50396  *     BCM_E_XXX
  50397  */
  50398 int
  50399 _bcm_field_ddrop_profile_delete(int unit, int index)
  50400 {
  50401     soc_profile_mem_t *ddrop_profile;
  50402 
  50403     /* Get the redirect profile */
  50404     BCM_IF_ERROR_RETURN
  50405         (_bcm_field_ddrop_profile_get(unit, &ddrop_profile));
  50406 
  50407     return (soc_profile_mem_delete(unit, ddrop_profile, index));
  50408 }
  50409 
  50410 /*
  50411  * Function:
  50412  *     _field_dredirect_profile_get
  50413  * Purpose:
  50414  *     Get the redirect profile for the unit
  50415  * Parameters:
  50416  *     unit             - BCM device number
  50417  *     dredirect_profile - (OUT) redirect profile
  50418  * Returns:
  50419  *     BCM_E_XXX
  50420  * Notes:
  50421  *     For triumph, External TCAM and IFP refer to same IFP_EGRESS_PORT_CHECK_FOR_REDIRECTm
  50422  */
  50423 int
  50424 _bcm_field_dredirect_profile_get(int unit,
  50425                                 soc_profile_mem_t **dredirect_profile)
  50426 {
  50427     _field_control_t *fc = NULL;
  50428 
  50429     /* Get field control structure. */
  50430     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  50431 
  50432     *dredirect_profile = &fc->dredirect_profile;
  50433 
  50434     return (BCM_E_NONE);
  50435 }
  50436 
  50437 /*
  50438  * Function:
  50439  *     _bcm_field_dredirect_profile_ref_count_get
  50440  * Purpose:
  50441  *     Get redirect profile entry use count.
  50442  * Parameters:
  50443  *     unit      - (IN) BCM device number.
  50444  *     index     - (IN) Profile entry index.
  50445  *     ref_count - (OUT) redirect profile use count.
  50446  * Returns:
  50447  *     BCM_E_XXX
  50448  */
  50449 int
  50450 _bcm_field_dredirect_profile_ref_count_get(int unit,
  50451                                               int index,
  50452                                               int *ref_count)
  50453 {
  50454     soc_profile_mem_t *dredirect_profile;
  50455 
  50456     if (NULL == ref_count) {
  50457         return (BCM_E_PARAM);
  50458     }
  50459 
  50460     /* Get the redirect profile */
  50461     BCM_IF_ERROR_RETURN
  50462         (_bcm_field_dredirect_profile_get(unit, &dredirect_profile));
  50463 
  50464     return (soc_profile_mem_ref_count_get(unit, dredirect_profile,
  50465                                           index, ref_count));
  50466 }
  50467 
  50468 /*
  50469  * Function:
  50470  *     _bcm_field_dredirect_profile_delete
  50471  * Purpose:
  50472  *     Delete redirect profile entry.
  50473  * Parameters:
  50474  *     unit      - (IN) BCM device number.
  50475  *     index     - (IN) Profile entry index.
  50476  * Returns:
  50477  *     BCM_E_XXX
  50478  */
  50479 int
  50480 _bcm_field_dredirect_profile_delete(int unit, int index)
  50481 {
  50482     soc_profile_mem_t *dredirect_profile;
  50483 
  50484     /* Get the redirect profile */
  50485     BCM_IF_ERROR_RETURN
  50486         (_bcm_field_dredirect_profile_get(unit, &dredirect_profile));
  50487 
  50488     return (soc_profile_mem_delete(unit, dredirect_profile, index));
  50489 }
  50490 
  50491 int
  50492 _field_delayed_profile_hw_alloc(int unit, _field_entry_t *f_ent)
  50493 {
  50494     int rv = BCM_E_NONE;  /* Operation return status.     */
  50495     _field_action_t *fa;  /* Field action descriptor.     */
  50496 
  50497     int ref_count;        /* Profile use reference count. */
  50498     _field_control_t *fc = NULL;
  50499 
  50500     BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  50501 
  50502     for (fa = f_ent->actions; ((fa != NULL) && (_FP_ACTION_VALID & fa->flags)); fa = fa->next) {
  50503         switch (fa->action) {
  50504             case bcmFieldActionMatchPbmpRedirect:
  50505                 /*
  50506                  * Store previous hardware index value in old_index.
  50507                  */
  50508                 fa->old_index = fa->hw_index;
  50509 
  50510                 if (NULL == fc->functions.fp_dredirect_action_alloc) {
  50511                      return BCM_E_CONFIG;
  50512                  }
  50513 
  50514                 rv = fc->functions.fp_dredirect_action_alloc(unit, f_ent, fa);
  50515 
  50516                 if ((BCM_E_RESOURCE == rv) &&
  50517                     (_FP_INVALID_INDEX != fa->old_index)) {
  50518 
  50519                     /* Destroy old profile ONLY
  50520                      * if it is not used by other entries.
  50521                      */
  50522                     rv = _bcm_field_dredirect_profile_ref_count_get(unit,
  50523                                                                        fa->old_index,
  50524                                                                        &ref_count);
  50525                     BCM_IF_ERROR_RETURN(rv);
  50526                     if (ref_count > 1) {
  50527                         return (BCM_E_RESOURCE);
  50528                     }
  50529                     rv = _bcm_field_dredirect_profile_delete(unit, fa->old_index);
  50530                     BCM_IF_ERROR_RETURN(rv);
  50531 
  50532                     /* Destroy old profile is no longer required. */
  50533                     fa->old_index = _FP_INVALID_INDEX;
  50534 
  50535                     /* Reallocate profile for new action. */
  50536                     rv = fc->functions.fp_dredirect_action_alloc(unit, f_ent, fa);
  50537                 }
  50538                 break;
  50539 
  50540             case bcmFieldActionMatchPbmpDrop:
  50541                 /*
  50542                  * Store previous hardware index value in old_index.
  50543                  */
  50544                 fa->old_index = fa->hw_index;
  50545 
  50546                 if (NULL == fc->functions.fp_ddrop_action_alloc) {
  50547                      return BCM_E_CONFIG;
  50548                  }
  50549 
  50550                 rv = fc->functions.fp_ddrop_action_alloc(unit, f_ent, fa);
  50551 
  50552                 if ((BCM_E_RESOURCE == rv) &&
  50553                     (_FP_INVALID_INDEX != fa->old_index)) {
  50554 
  50555                     /* Destroy old profile ONLY
  50556                      * if it is not used by other entries.
  50557                      */
  50558                     rv = _bcm_field_ddrop_profile_ref_count_get(unit,
  50559                                                                 fa->old_index,
  50560                                                                 &ref_count);
  50561                     BCM_IF_ERROR_RETURN(rv);
  50562                     if (ref_count > 1) {
  50563                         return (BCM_E_RESOURCE);
  50564                     }
  50565                     rv = _bcm_field_ddrop_profile_delete(unit, fa->old_index);
  50566                     BCM_IF_ERROR_RETURN(rv);
  50567 
  50568                     /* Destroy old profile is no longer required. */
  50569                     fa->old_index = _FP_INVALID_INDEX;
  50570 
  50571                     /* Reallocate profile for new action. */
  50572                     rv = fc->functions.fp_ddrop_action_alloc(unit, f_ent, fa);
  50573                 }
  50574                 break;
  50575             default:
  50576                 break;
  50577         }
  50578         if (BCM_FAILURE(rv)) {
  50579             _field_delayed_profile_hw_free(unit, f_ent, _FP_ACTION_HW_FREE);
  50580             break;
  50581         }
  50582     }
  50583     return rv;
  50584 }
  50585 
  50586 /*
  50587  * Function:
  50588  *    _field_delayed_profile_hw_free
  50589  *
  50590  * Purpose:
  50591  *     Free redirect profile indexes required for entry installation.
  50592  *
  50593  * Parameters:
  50594  *     unit      - (IN) BCM device number.
  50595  *     f_ent     - (IN) Field entry descriptor.
  50596  *     flags     - (IN) Free flags (old/new/both).
  50597  * Returns:
  50598  *     BCM_E_XXX
  50599  * Notes:
  50600  */
  50601 
  50602 int
  50603 _field_delayed_profile_hw_free(int unit, _field_entry_t *f_ent, uint32 flags)
  50604 {
  50605     _field_action_t *fa;  /* Field action descriptor. */
  50606     int rv = BCM_E_NONE;  /* Operation return status. */
  50607 
  50608     /* Extract the policy info from the entry structure. */
  50609     for (fa = f_ent->actions; fa != NULL; fa = fa->next) {
  50610         switch (fa->action) {
  50611             case bcmFieldActionMatchPbmpRedirect:
  50612                   if ((flags & _FP_ACTION_RESOURCE_FREE) &&
  50613                       (_FP_INVALID_INDEX != fa->hw_index)) {
  50614                       rv = _bcm_field_dredirect_profile_delete(unit,
  50615                                                                   fa->hw_index);
  50616                       BCM_IF_ERROR_RETURN(rv);
  50617                       fa->hw_index = _FP_INVALID_INDEX;
  50618                   }
  50619 
  50620                   if ((flags & _FP_ACTION_OLD_RESOURCE_FREE) &&
  50621                       (_FP_INVALID_INDEX != fa->old_index)) {
  50622                       rv = _bcm_field_dredirect_profile_delete(unit,
  50623                                                                   fa->old_index);
  50624                       BCM_IF_ERROR_RETURN(rv);
  50625                       fa->old_index = _FP_INVALID_INDEX;
  50626                   }
  50627                break;
  50628             case bcmFieldActionMatchPbmpDrop:
  50629                   if ((flags & _FP_ACTION_RESOURCE_FREE) &&
  50630                       (_FP_INVALID_INDEX != fa->hw_index)) {
  50631                       rv = _bcm_field_ddrop_profile_delete(unit,
  50632                                                                fa->hw_index);
  50633                       BCM_IF_ERROR_RETURN(rv);
  50634                       fa->hw_index = _FP_INVALID_INDEX;
  50635                   }
  50636 
  50637                   if ((flags & _FP_ACTION_OLD_RESOURCE_FREE) &&
  50638                       (_FP_INVALID_INDEX != fa->old_index)) {
  50639                       rv = _bcm_field_ddrop_profile_delete(unit,
  50640                                                                fa->old_index);
  50641                       BCM_IF_ERROR_RETURN(rv);
  50642                       fa->old_index = _FP_INVALID_INDEX;
  50643                   }
  50644                break;
  50645            default:
  50646                break;
  50647         }
  50648     }
  50649     return (rv);
  50650 }
  50651 
  50652 /*
  50653  * Function:
  50654  *  _bcm_field_priority_group_get_next
  50655  * Purpose:
  50656  *  Retrieve the next valid group pointer associated with the given priority.
  50657  * Parameters:
  50658  *  unit       - (IN   BCM device number.
  50659  *  instance   - (IN)  Pipe to which group belongs to.
  50660  *  stage_id   - (IN)  Stage (IFP/VFP/EFP) to which group belongs to.
  50661  *  priority   - (IN)  Field Group Priority.
  50662  *  curr_group - (IN)  Reference to current group index associated to group
  50663  *                     priority.
  50664  *  next_group - (OUT) Reference to next available group index associated to
  50665  *                     the given priority.
  50666  * Returns:
  50667  *  BCM_E_XXX
  50668  * Note:
  50669  *  "*curr_group == NULL" to retrieve the first group associated with the
  50670  *   given slice.
  50671  */
  50672 int
  50673 _bcm_field_priority_group_get_next(int unit,
  50674                                    int instance,
  50675                                    _field_stage_id_t stage_id,
  50676                                    int priority,
  50677                                    uint32 group_mode,
  50678                                    _field_group_t **curr_group,
  50679                                    _field_group_t **next_group)
  50680 {
  50681     _field_group_t *fg = NULL;
  50682 
  50683     if (curr_group == NULL || next_group == NULL) {
  50684         return BCM_E_PARAM;
  50685     }
  50686 
  50687     if (*curr_group == NULL) {
  50688         _field_control_t  *fc;     /* Field Control Structure */
  50689 
  50690         /* Get device Field control structure. */
  50691         BCM_IF_ERROR_RETURN(_field_control_get(unit, &fc));
  50692         fg = fc->groups;
  50693     } else {
  50694         fg = (*curr_group)->next;
  50695     }
  50696         
  50697     *next_group = NULL;
  50698     for (; fg != NULL; fg = fg->next) {
  50699         if ((instance != fg->instance) ||
  50700             (stage_id != fg->stage_id) ||
  50701             (priority != fg->priority)) {
  50702             continue;
  50703         }
  50704 
  50705         if ((group_mode == _FP_GROUP_SPAN_MASK) ||
  50706             ((fg->flags & _FP_GROUP_SPAN_MASK) == group_mode)) {
  50707             *next_group = fg;
  50708             return BCM_E_NONE;
  50709         }
  50710     }
  50711 
  50712     return BCM_E_NOT_FOUND;
  50713 }
  50714 
  50715 
  50716 /*
  50717  * Retrieve number of groups available for a given priority.
  50718  */
  50719 int
  50720 _bcm_field_group_count_get(int unit,
  50721                            int instance,
  50722                            _field_stage_t *stage_fc,
  50723                            int group_priority,
  50724                            uint32 group_mode,
  50725                            uint16 *group_count)
  50726 {
  50727     int rv;
  50728     _field_group_t *fg_next = NULL;
  50729 
  50730     *group_count = 0;
  50731     do {
  50732        rv = _bcm_field_priority_group_get_next(unit,
  50733                                            instance,
  50734                                  stage_fc->stage_id,
  50735                                      group_priority,
  50736                                          group_mode,
  50737                                  &fg_next, &fg_next);
  50738        if (BCM_FAILURE(rv)) {
  50739            break;
  50740        }
  50741 
  50742        *group_count += 1;
  50743     } while (fg_next != NULL);
  50744    
  50745     return BCM_E_NONE;
  50746 }
  50747 
  50748 #endif  /* BCM_FIELD_SUPPORT */
  50749 #endif  /* BCM_ESW_SUPPORT */
  50750