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

udf.c (228033B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:    udf.c
      8  * Purpose: Manages XGS4 UDF_TCAM and UDF_OFFSET tables
      9  */
     10 
     11 
     12 #include <shared/bsl.h>
     13 
     14 #include <soc/field.h>
     15 
     16 #include <soc/drv.h>
     17 #include <soc/scache.h>
     18 #include <soc/error.h>
     19 
     20 #include <shared/bitop.h>
     21 
     22 #include <bcm/udf.h>
     23 #include <bcm/field.h>
     24 #include <bcm/error.h>
     25 #include <bcm/module.h>
     26 
     27 #include <bcm_int/esw/xgs4.h>
     28 #include <bcm_int/esw/switch.h>
     29 #include <bcm_int/esw/field.h>
     30 
     31 #define OUTER_IP4_TYPE_VAL(x) (SOC_IS_TD_TT(x) || SOC_IS_TRIUMPH3(x)) ? 1 : 2
     32 #define OUTER_IP6_TYPE_VAL(x) (SOC_IS_TD_TT(x) || SOC_IS_TRIUMPH3(x)) ? 5 : 4
     33 
     34 /* WarmBoot Sensitive Macro : Need to bump up scache version if changes */
     35 #define TD2_UDF_MAX_OBJECTS 0xff
     36 
     37 #define UDF_MALLOC(_p_, _t_, _sz_, _desc_)                  \
     38     do {                                                    \
     39         if (!_p_) {                                         \
     40             (_p_) = (_t_ *) sal_alloc((_sz_), (_desc_));    \
     41         }                                                   \
     42         if (_p_) {                                          \
     43             sal_memset((_p_), 0, (_sz_));                   \
     44         }                                                   \
     45     } while(0)
     46 
     47 #define UDF_UNLINK_OFFSET_NODE(_t_) \
     48     do {                                                    \
     49         if ((_t_)->prev) {                                   \
     50             (_t_)->prev->next = (_t_)->next;                 \
     51         } else {                                            \
     52             UDF_CTRL(unit)->offset_info_head = (_t_)->next; \
     53         }                                                   \
     54         if ((_t_)->next) {                                  \
     55             ((_t_)->next)->prev = (_t_)->prev;              \
     56         }                                                   \
     57     } while(0)
     58 
     59 #define UDF_UNLINK_TCAM_NODE(_t_) \
     60     do {                                                    \
     61         if ((_t_)->prev) {                                   \
     62             (_t_)->prev->next = (_t_)->next;                 \
     63         } else {                                            \
     64             UDF_CTRL(unit)->tcam_info_head = (_t_)->next;   \
     65         }                                                   \
     66         if ((_t_)->next) {                                  \
     67             ((_t_)->next)->prev = (_t_)->prev;              \
     68         }                                                   \
     69     } while(0)
     70 
     71 #define BCM_IF_NULL_RETURN_PARAM(_p_) \
     72     do {                                                    \
     73         if ((_p_) == NULL) {                                \
     74             return BCM_E_PARAM;                             \
     75         }                                                   \
     76     } while(0)
     77 
     78 
     79 #define UDF_IF_ERROR_CLEANUP(_rv_) \
     80     do {                                                    \
     81         if (BCM_FAILURE(rv)) {                              \
     82             goto cleanup;                                   \
     83         }                                                   \
     84     } while (0)
     85 
     86 #define UDF_ID_VALIDATE(_id_) \
     87     do {                                                    \
     88         if (((_id_) < BCMI_XGS4_UDF_ID_MIN) ||              \
     89             ((_id_) > BCMI_XGS4_UDF_ID_MAX)) {              \
     90             return BCM_E_PARAM;                             \
     91         }                                                   \
     92     } while(0)
     93 #define UDF_ID_VALIDATE_UNLOCK(unit, _id_)                  \
     94     do {                                                    \
     95         if (((_id_) < BCMI_XGS4_UDF_ID_MIN) ||              \
     96             ((_id_) > BCMI_XGS4_UDF_ID_MAX)) {              \
     97             UDF_UNLOCK(unit);                               \
     98             return BCM_E_PARAM;                             \
     99         }                                                   \
    100     } while(0)
    101 
    102 #define UDF_PKT_FORMAT_ID_VALIDATE(_id_) \
    103     do {                                                    \
    104         if (((_id_) < BCMI_XGS4_UDF_PKT_FORMAT_ID_MIN) ||   \
    105             ((_id_) > BCMI_XGS4_UDF_PKT_FORMAT_ID_MAX)) {   \
    106             return BCM_E_PARAM;                             \
    107         }                                                   \
    108     } while(0)
    109 
    110 #define UDF_PKT_FORMAT_ID_VALIDATE_UNLOCK(unit, _id_)       \
    111     do {                                                    \
    112         if (((_id_) < BCMI_XGS4_UDF_PKT_FORMAT_ID_MIN) ||   \
    113             ((_id_) > BCMI_XGS4_UDF_PKT_FORMAT_ID_MAX)) {   \
    114             UDF_UNLOCK(unit);                               \
    115             return BCM_E_PARAM;                             \
    116         }                                                   \
    117     } while(0)
    118 
    119 
    120 /* Global UDF control structure pointers */
    121 bcmi_xgs4_udf_ctrl_t *udf_control[BCM_MAX_NUM_UNITS];
    122 
    123 typedef enum {
    124     bcmiUdfObjectUdf = 1,
    125     bcmiUdfObjectPktFormat = 2
    126 } bcmiUdfObjectType;
    127 
    128 typedef enum bcmi_xgs4_udf_pkt_format_misc_e {
    129     bcmiUdfPktFormatHigig = 0,
    130     bcmiUdfPktFormatCntag = 1,
    131     bcmiUdfPktFormatIcnm = 2,
    132     bcmiUdfPktFormatVntag = 3,
    133     bcmiUdfPktFormatEtag = 4,
    134     bcmiUdfPktFormatSubportTag = 5,
    135     bcmiUdfPktFormatIntPkt = 6,
    136     bcmiUdfPktFormatNone
    137 } bcmi_xgs4_udf_pkt_format_misc_t;
    138 
    139 
    140 
    141 /* STATIC function declarations */
    142 STATIC int bcmi_xgs4_udf_ctrl_init(int unit);
    143 
    144 STATIC int bcmi_xgs4_udf_hw_init(int unit);
    145 
    146 STATIC int bcmi_xgs4_udf_offset_reserve(int unit, int max, int offset[],
    147                                         int pipe_num);
    148 
    149 STATIC int bcmi_xgs4_udf_offset_unreserve(int unit, int max, int offset[],
    150                                           int pipe_num);
    151 
    152 STATIC int bcmi_xgs4_udf_offset_hw_alloc(int unit,
    153     bcm_udf_alloc_hints_t *hints,
    154     bcmi_xgs4_udf_offset_info_t *offset_info);
    155 
    156 STATIC int bcmi_xgs4_udf_layer_to_offset_base(int unit,
    157     bcmi_xgs4_udf_offset_info_t *offset_info,
    158     bcmi_xgs4_udf_tcam_info_t *tcam_info,
    159     int *base, int *baseoffset);
    160 
    161 STATIC int bcmi_xgs4_udf_offset_info_alloc(int unit,
    162     bcmi_xgs4_udf_offset_info_t **offset_info);
    163 
    164 STATIC int bcmi_xgs4_udf_offset_info_add(int unit,
    165     bcm_udf_t *udf_info, bcmi_xgs4_udf_offset_info_t **offset_info);
    166 
    167 STATIC int bcmi_xgs4_udf_offset_node_add(
    168     int unit, bcmi_xgs4_udf_offset_info_t *new);
    169 
    170 STATIC int bcmi_xgs4_udf_offset_node_delete(int unit,
    171     bcm_udf_id_t udf_id, bcmi_xgs4_udf_offset_info_t **del);
    172 
    173 STATIC int bcmi_xgs4_udf_tcam_info_alloc(int unit,
    174     bcmi_xgs4_udf_tcam_info_t **tcam_info);
    175 
    176 STATIC int bcmi_xgs4_udf_tcam_info_add(int unit,
    177     bcm_udf_pkt_format_info_t *pkt_format,
    178     bcmi_xgs4_udf_tcam_info_t **tcam_info);
    179 
    180 STATIC int bcmi_xgs4_udf_tcam_node_add(
    181     int unit, bcmi_xgs4_udf_tcam_info_t *new);
    182 
    183 STATIC int bcmi_xgs4_udf_tcam_node_delete(int unit,
    184     bcm_udf_pkt_format_id_t pkt_format_id, bcmi_xgs4_udf_tcam_info_t **del);
    185 
    186 STATIC int bcmi_xgs4_udf_id_running_id_alloc(int unit,
    187     bcmiUdfObjectType type, int *id);
    188 
    189 STATIC int bcmi_xgs4_udf_offset_to_hw_field(int unit, int udf_num, int user_num,
    190     soc_field_t *base_hw_f, soc_field_t *offset_hw_f);
    191 
    192 STATIC int bcmi_xgs4_udf_offset_install(int unit,
    193     int e, uint32 hw_bmap, int base, int offset, int pipe_num, int class_id, uint8 flags);
    194 
    195 #if defined (BCM_TOMAHAWK_SUPPORT)
    196 int bcmi_xgs4_udf_ser_init(int unit,
    197                          bcm_udf_oper_mode_t mode);
    198 #endif
    199 /* tcam help apis */
    200 STATIC int bcmi_xgs4_udf_tcam_entry_move(int unit,
    201     bcmi_xgs4_udf_tcam_entry_t *tcam_entry_arr, int src, int dst, int pipe_num);
    202 
    203 STATIC int bcmi_xgs4_udf_tcam_move_up(int unit,
    204     bcmi_xgs4_udf_tcam_entry_t *tcam_entry_arr, int dest, int free_slot, int pipe_num);
    205 
    206 STATIC int bcmi_xgs4_udf_tcam_move_down(int unit,
    207     bcmi_xgs4_udf_tcam_entry_t *tcam_entry_arr, int dest, int free_slot, int pipe_num);
    208 
    209 STATIC int bcmi_xgs4_udf_tcam_entry_match(int unit,
    210     bcmi_xgs4_udf_tcam_info_t *new,  bcmi_xgs4_udf_tcam_info_t **match);
    211 
    212 STATIC int bcmi_xgs4_udf_tcam_entry_insert(int unit,
    213     bcmi_xgs4_udf_tcam_info_t *tcam_new);
    214 
    215 STATIC int bcmi_xgs4_udf_tcam_entry_vlanformat_parse(int unit,
    216     uint32 *hw_buf, bcm_udf_pkt_format_info_t *pkt_fmt);
    217 
    218 STATIC int bcmi_xgs4_udf_tcam_entry_l2format_parse(int unit,
    219     uint32 *hw_buf, bcm_udf_pkt_format_info_t *pkt_fmt);
    220 
    221 STATIC int bcmi_xgs4_udf_tcam_entry_l3_parse(int unit,
    222     uint32 *hw_buf, bcm_udf_pkt_format_info_t *pkt_fmt);
    223 
    224 STATIC int bcmi_xgs4_udf_tcam_entry_misc_parse(int unit,
    225     int type, uint32 *hw_buf, uint16 *flags);
    226 
    227 STATIC int bcmi_xgs4_udf_tcam_entry_vlanformat_init(int unit,
    228     bcm_udf_pkt_format_info_t *pkt_fmt, uint32 *hw_buf);
    229 
    230 STATIC int bcmi_xgs4_udf_tcam_entry_l2format_init(int unit,
    231     bcm_udf_pkt_format_info_t *pkt_fmt, uint32 *hw_buf);
    232 
    233 STATIC int bcmi_xgs4_udf_tcam_entry_l3_init(int unit,
    234     bcm_udf_pkt_format_info_t *pkt_fmt, uint32 *hw_buf);
    235 
    236 STATIC int bcmi_xgs4_udf_tcam_entry_misc_init(int unit,
    237     int type, uint16 flags, uint32 *hw_buf);
    238 
    239 STATIC int bcmi_xgs4_udf_tcam_entry_parse(int unit,
    240     uint32 *hw_buf, bcm_udf_pkt_format_info_t *pkt_fmt);
    241 
    242 STATIC int bcmi_xgs4_udf_pkt_format_tcam_key_init(int unit,
    243     bcm_udf_pkt_format_info_t *pkt_format, uint32 *hw_buf);
    244 
    245 STATIC int bcmi_xgs4_udf_tcam_misc_format_to_hw_fields(int unit, int type,
    246     soc_field_t *data_f, soc_field_t *mask_f,
    247     int *present, int *none, int *any, int *support);
    248 
    249 STATIC int bcmi_xgs4_udf_hash_config_set(int unit,
    250     bcm_udf_hash_config_t *config, bcmi_xgs4_udf_offset_info_t *offset_info);
    251 
    252 /* static global variable */
    253 #if defined (BCM_TOMAHAWK_SUPPORT)
    254 STATIC bcm_udf_oper_mode_t bcmi_xgs4_udf_oper_mode[BCM_MAX_NUM_UNITS] = {bcmUdfOperModeGlobal};
    255 #endif
    256 
    257 /*
    258  * Function:
    259  *      bcmi_xgs4_udf_ctrl_free
    260  * Purpose:
    261  *      Frees udf control structure and its members.
    262  * Parameters:
    263  *      unit            - (IN)  Unit number.
    264  *      udfc            - (IN)  UDF Control structure to free.
    265  * Returns:
    266  *      BCM_E_XXX
    267  * Notes:
    268  */
    269 STATIC int
    270 bcmi_xgs4_udf_ctrl_free(int unit, bcmi_xgs4_udf_ctrl_t *udfc)
    271 {
    272     bcmi_xgs4_udf_tcam_info_t *prv_t, *cur_t;
    273     bcmi_xgs4_udf_offset_info_t *prv_o, *cur_o;
    274     int pipe_id = 0;
    275 
    276 #if defined (BCM_TOMAHAWK_SUPPORT)
    277     int pipe;
    278 #endif
    279 
    280     if (NULL == udfc) {
    281         /* Already freed */
    282         return BCM_E_NONE;
    283     }
    284 
    285     /* Free mutex */
    286     if (NULL != udfc->udf_mutex) {
    287         sal_mutex_destroy(udfc->udf_mutex);
    288         udfc->udf_mutex = NULL;
    289     }
    290 
    291 #if defined (BCM_TOMAHAWK_SUPPORT)
    292     if (soc_feature(unit, soc_feature_udf_multi_pipe_support)) {
    293         for (pipe = 0; pipe < SOC_MAX_NUM_PIPES; pipe++) {
    294             if (NULL != udfc->tcam_entry_array_per_pipe[pipe]) {
    295                 sal_free(udfc->tcam_entry_array_per_pipe[pipe]);
    296                 udfc->tcam_entry_array_per_pipe[pipe] = NULL;
    297             }
    298             if (NULL != udfc->offset_entry_array_per_pipe[pipe]) {
    299                 sal_free(udfc->offset_entry_array_per_pipe[pipe]);
    300                 udfc->offset_entry_array_per_pipe[pipe] = NULL;
    301             }
    302         }
    303     }
    304 #endif
    305     /* Free tcam entry array */
    306     if (NULL != udfc->tcam_entry_array) {
    307         sal_free(udfc->tcam_entry_array);
    308         udfc->tcam_entry_array = NULL;
    309     }
    310 
    311     /* Free offset entry array */
    312     if (NULL != udfc->offset_entry_array) {
    313         sal_free(udfc->offset_entry_array);
    314         udfc->offset_entry_array = NULL;
    315     }
    316 
    317     /* Free list of pkt format objects */
    318     cur_o = udfc->offset_info_head;
    319 
    320     while (NULL != cur_o) {
    321         prv_o = cur_o;
    322         cur_o = cur_o->next;
    323 
    324         sal_free(prv_o);
    325     }
    326     udfc->offset_info_head = NULL;
    327 
    328     /* Free list of offset objects */
    329     cur_t = udfc->tcam_info_head;
    330 
    331     while (NULL != cur_t) {
    332         prv_t = cur_t;
    333         cur_t = cur_t->next;
    334 
    335         sal_free(prv_t);
    336     }
    337     udfc->tcam_info_head = NULL;
    338 
    339     /* Clean up udf field module resources */
    340     if (soc_feature(unit, soc_feature_udf_selector_support)) {
    341         for (pipe_id = 0; pipe_id < SOC_MAX_NUM_PIPES; pipe_id++) {
    342             if (NULL != udfc->udf_field_bmp[pipe_id].w) {
    343                 _BCMI_UDF_BMP_FREE(udfc->udf_field_bmp[pipe_id]);
    344             }
    345             udfc->max_chunks = 0;
    346         }
    347     }
    348     /* Free the udf control structure */
    349     sal_free(udfc);
    350 
    351     udf_control[unit] = NULL;
    352 
    353     return BCM_E_NONE;
    354 }
    355 
    356 /*
    357  * Function:
    358  *      bcmi_xgs4_udf_ctrl_init
    359  * Purpose:
    360  *      Initialize UDF control and internal data structures.
    361  * Parameters:
    362  *      unit           - (IN) bcm device.
    363  *
    364  * Returns:
    365  *      BCM_E_XXX
    366  */
    367 STATIC int
    368 bcmi_xgs4_udf_ctrl_init(int unit)
    369 {
    370     int alloc_sz;
    371     soc_mem_t tcam_mem, offset_mem;
    372     int nentries, noffsets;
    373     bcmi_xgs4_udf_ctrl_t *udf_ctrl = NULL;
    374     int pipe_id = 0;
    375 #if defined (BCM_TOMAHAWK_SUPPORT)
    376     int pipe;
    377 #endif
    378     tcam_mem = FP_UDF_TCAMm;
    379     offset_mem = FP_UDF_OFFSETm;
    380 
    381     /* Detach module if already installed */
    382     if (udf_control[unit] != NULL) {
    383         bcmi_xgs4_udf_detach(unit);
    384     }
    385 
    386     nentries = soc_mem_index_count(unit, tcam_mem);
    387 
    388     /* No. of maximum offset chunks supported */
    389     if (SOC_MEM_FIELD_VALID(unit, offset_mem, UDF1_OFFSET4f)) {
    390         noffsets = UDF_OFFSET_CHUNKS16;
    391     } else {
    392         noffsets = UDF_OFFSET_CHUNKS8;
    393     }
    394 
    395     if (udf_control[unit] != NULL) {
    396         (void)bcmi_xgs4_udf_ctrl_free(unit, udf_control[unit]);
    397     }
    398 
    399    /* Allocating memory of UDF control structure */
    400     alloc_sz = sizeof(bcmi_xgs4_udf_ctrl_t);
    401     UDF_MALLOC(udf_ctrl, bcmi_xgs4_udf_ctrl_t, alloc_sz, "udf control");
    402     if (udf_ctrl == NULL) {
    403         return BCM_E_MEMORY;
    404     }
    405 
    406     udf_control[unit] = udf_ctrl;
    407 
    408     /* Allocate memory for tcam_entry_array structure */
    409 #if defined (BCM_TOMAHAWK_SUPPORT)
    410     if (soc_feature(unit, soc_feature_udf_multi_pipe_support) &&
    411        (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) {
    412         sal_memset(udf_ctrl->hw_bmap_per_pipe,   0, sizeof(udf_ctrl->hw_bmap_per_pipe));
    413         sal_memset(udf_ctrl->byte_bmap_per_pipe, 0, sizeof(udf_ctrl->byte_bmap_per_pipe));
    414 
    415         /* Allocate memory for tcam_entry_array structure */
    416         alloc_sz = sizeof(bcmi_xgs4_udf_tcam_entry_t) * nentries;
    417         for (pipe = 0; pipe < SOC_MAX_NUM_PIPES; pipe++) {
    418             UDF_MALLOC(udf_ctrl->tcam_entry_array_per_pipe[pipe], bcmi_xgs4_udf_tcam_entry_t,
    419                    alloc_sz, "udf tcam entry array per pipe");
    420             if (udf_ctrl->tcam_entry_array_per_pipe[pipe] == NULL) {
    421                 /* Free udf control struct */
    422                 (void)bcmi_xgs4_udf_ctrl_free(unit, udf_ctrl);
    423                 return BCM_E_MEMORY;
    424             }
    425         }
    426 
    427         /* Allocate memory for offset_entry_array structure */
    428         alloc_sz = sizeof(bcmi_xgs4_udf_offset_entry_t) * noffsets;
    429         for (pipe = 0; pipe < SOC_MAX_NUM_PIPES; pipe++) {
    430             UDF_MALLOC(udf_ctrl->offset_entry_array_per_pipe[pipe], bcmi_xgs4_udf_offset_entry_t,
    431                    alloc_sz, "udf offset entry array per pipe");
    432 
    433             if (udf_ctrl->offset_entry_array_per_pipe[pipe] == NULL) {
    434                 /* Free udf control struct */
    435                 (void)bcmi_xgs4_udf_ctrl_free(unit, udf_ctrl);
    436                 return BCM_E_MEMORY;
    437             }
    438         }
    439     } else
    440 #endif
    441     {
    442         /* Allocate memory for tcam_entry_array structure */
    443         alloc_sz = sizeof(bcmi_xgs4_udf_tcam_entry_t) * nentries;
    444         UDF_MALLOC(udf_ctrl->tcam_entry_array, bcmi_xgs4_udf_tcam_entry_t,
    445                alloc_sz, "udf tcam entry array");
    446         if (udf_ctrl->tcam_entry_array == NULL) {
    447             /* Free udf control struct */
    448             (void)bcmi_xgs4_udf_ctrl_free(unit, udf_ctrl);
    449             return BCM_E_MEMORY;
    450         }
    451 
    452         /* Allocate memory for offset_entry_array structure */
    453         alloc_sz = sizeof(bcmi_xgs4_udf_offset_entry_t) * noffsets;
    454         UDF_MALLOC(udf_ctrl->offset_entry_array, bcmi_xgs4_udf_offset_entry_t,
    455                    alloc_sz, "udf offset entry array");
    456         if (udf_ctrl->offset_entry_array == NULL) {
    457             /* Free udf control struct */
    458             (void)bcmi_xgs4_udf_ctrl_free(unit, udf_ctrl);
    459             return BCM_E_MEMORY;
    460         }
    461     }
    462 
    463     /* Create UDF lock */
    464     if (udf_ctrl->udf_mutex == NULL) {
    465         udf_ctrl->udf_mutex = sal_mutex_create("udf_mutex");
    466         if (udf_ctrl->udf_mutex == NULL) {
    467             /* Free udf control struct */
    468             (void)bcmi_xgs4_udf_ctrl_free(unit, udf_ctrl);
    469             return BCM_E_MEMORY;
    470         }
    471     }
    472 
    473 
    474     udf_ctrl->tcam_mem = tcam_mem;
    475     udf_ctrl->offset_mem = offset_mem;
    476 
    477     /* Check if GRE options adjust for UDF selection is supported */
    478     if (SOC_MEM_FIELD_VALID(unit, offset_mem, UDF1_ADD_GRE_OPTIONS0f)) {
    479         udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_OFFSET_ADJUST_GRE;
    480     }
    481 
    482     /* Check if IPV4 options adjust for UDF selection is supported */
    483     if (SOC_MEM_FIELD_VALID(unit, offset_mem, UDF1_ADD_IPV4_OPTIONS0f)) {
    484         udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_OFFSET_ADJUST_IP4;
    485     }
    486     if (SOC_MEM_FIELD_VALID(unit, offset_mem, UDF_CLASS_IDf)) {
    487         udf_ctrl->flags |= BCMI_XGS4_UDF_PKT_FORMAT_CLASS_ID;
    488     }
    489 
    490     if (SOC_MEM_FIELD_VALID(unit, tcam_mem, HIGIGf)) {
    491         udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_TCAM_HIGIG;
    492     }
    493     if (SOC_MEM_FIELD_VALID(unit, tcam_mem, VNTAG_PRESENTf)) {
    494         udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_TCAM_VNTAG;
    495     }
    496     if (SOC_MEM_FIELD_VALID(unit, tcam_mem, ETAG_PACKETf)) {
    497         udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_TCAM_ETAG;
    498     }
    499     if (SOC_MEM_FIELD_VALID(unit, tcam_mem, CNTAG_PRESENTf)) {
    500         udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_TCAM_CNTAG;
    501     }
    502     if (SOC_MEM_FIELD_VALID(unit, tcam_mem, ICNM_PACKETf)) {
    503         udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_TCAM_ICNM;
    504     }
    505     if (SOC_MEM_FIELD_VALID(unit, tcam_mem, SUBPORT_TAG_PRESENTf)) {
    506         udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_TCAM_SUBPORT_TAG;
    507     }
    508 #if defined(BCM_TOMAHAWK_SUPPORT)
    509     if (SOC_MEM_FIELD_VALID(unit, offset_mem,
    510                             ENABLE_UDF_CONDITIONAL_CHECKf)) {
    511         udf_ctrl->flags |= BCMI_XGS4_UDF_CONDITIONAL_CHECK;
    512     }
    513 #endif
    514 
    515 #if defined(BCM_TRIDENT2_SUPPORT)
    516     /* Check if flex hash is supported */
    517     if soc_feature(unit, soc_feature_flex_hashing) {
    518         udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_FLEXHASH;
    519     }
    520     /* Check if udf hash is supported */
    521     if soc_feature(unit, soc_feature_udf_hashing) {
    522         udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_UDFHASH;
    523     }
    524 #endif
    525 
    526 #if defined(BCM_TOMAHAWK_SUPPORT)
    527     if (SOC_IS_TOMAHAWKX(unit)) {
    528         /* UDF Range Checker is supported only in Tomahawk. */
    529         udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_RANGE_CHECK;
    530     }
    531 #endif
    532     if soc_feature(unit, soc_feature_advanced_flex_counter) {
    533         udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_FLEX_COUNTER;
    534     }
    535 
    536     if (SOC_MEM_FIELD_VALID(unit, tcam_mem, L4_DST_PORTf)) {
    537         udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_L4_DST_PORT;
    538     }
    539     if (SOC_MEM_FIELD_VALID(unit, tcam_mem, OPAQUE_TAG_TYPEf)) {
    540         udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_OPAQUE_TAG_TYPE;
    541     }
    542     if (SOC_MEM_FIELD_VALID(unit, tcam_mem, INT_PKTf)) {
    543         udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_INT_PKT;
    544     }
    545     if (SOC_MEM_FIELD_VALID(unit, tcam_mem, SOURCE_PORT_NUMBERf)) {
    546         udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_SRC_PORT;
    547     }
    548     if (SOC_MEM_FIELD_VALID(unit, tcam_mem, LOOPBACK_PKT_TYPEf)) {
    549         udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_LB_PKT_TYPE;
    550     }
    551 
    552     udf_ctrl->nentries = nentries;
    553     udf_ctrl->noffsets = noffsets;
    554 
    555     /* restriction merely for warmboot purposes */
    556     udf_ctrl->max_udfs = TD2_UDF_MAX_OBJECTS;
    557 
    558     /* restriction merely for byte selection */
    559     udf_ctrl->max_parse_bytes = BCMI_XGS4_UDF_MAX_BYTE_SELECTION;
    560 
    561     /* offset chunk granularity */
    562     if (SOC_MEM_FIELD_VALID(unit, offset_mem, UDF1_OFFSET4f)) {
    563         udf_ctrl->gran = UDF_OFFSET_GRAN2;
    564     } else {
    565         udf_ctrl->gran = UDF_OFFSET_GRAN4;
    566     }
    567 
    568     /* Check if policer group is supported */
    569     if (soc_feature(unit, soc_feature_global_meter)) {
    570         udf_ctrl->flags |= BCMI_XGS4_UDF_CTRL_POLICER_GROUP;
    571     }
    572 
    573     /* udf hash chunks */
    574 #if defined(BCM_TRIDENT2_SUPPORT)
    575     if soc_feature(unit, soc_feature_udf_hashing) {
    576         udf_ctrl->udf_hash_1 = 6;
    577         udf_ctrl->udf_hash_2 = 7;
    578     }
    579 #endif
    580 
    581     if (soc_feature(unit, soc_feature_udf_selector_support)) {
    582         /* Allocate udf field module related resources */
    583         for (pipe_id = 0; pipe_id < SOC_MAX_NUM_PIPES; pipe_id++) {
    584              udf_ctrl->max_chunks = 16;
    585              udf_ctrl->udf_field_bmp[pipe_id].w = NULL;
    586              _FP_XGS3_ALLOC(udf_ctrl->udf_field_bmp[pipe_id].w,
    587                             SHR_BITALLOCSIZE(udf_ctrl->max_chunks),
    588                             "UDF BMP");
    589              if (udf_ctrl->udf_field_bmp[pipe_id].w == NULL) {
    590                  return BCM_E_MEMORY;
    591              }
    592         }
    593     }
    594 
    595     udf_ctrl->udf_used_by_module = UDF_USED_BY_NONE;
    596 
    597     return BCM_E_NONE;
    598 }
    599 
    600 /*
    601  * Function:
    602  *      bcmi_xgs4_udf_hw_init
    603  * Purpose:
    604  *      Clears the hardware tables related to UDF.
    605  * Parameters:
    606  *      unit            - (IN)  Unit number.
    607  * Returns:
    608  *      BCM_E_XXX
    609  * Notes:
    610  */
    611 STATIC int
    612 bcmi_xgs4_udf_hw_init(int unit)
    613 {
    614     int rv;
    615 
    616     /* Clear UDF_TCAM table */
    617     rv = soc_mem_clear(unit, UDF_CTRL(unit)->tcam_mem, MEM_BLOCK_ALL, TRUE);
    618     SOC_IF_ERROR_RETURN(rv);
    619 
    620     /* Clear UDF_OFFSET table */
    621     rv = soc_mem_clear(unit, UDF_CTRL(unit)->offset_mem, MEM_BLOCK_ALL, TRUE);
    622     SOC_IF_ERROR_RETURN(rv);
    623 
    624     return BCM_E_NONE;
    625 }
    626 
    627 
    628 #if defined (BCM_WARM_BOOT_SUPPORT)
    629 #define BCM_WB_VERSION_1_3     SOC_SCACHE_VERSION(1, 3)
    630 #define BCM_WB_VERSION_1_2     SOC_SCACHE_VERSION(1, 2)
    631 #define BCM_WB_VERSION_1_1     SOC_SCACHE_VERSION(1, 1)
    632 #define BCM_WB_VERSION_1_0     SOC_SCACHE_VERSION(1, 0)
    633 #define BCM_WB_VERSION_1_4     SOC_SCACHE_VERSION(1, 4)
    634 #define BCM_WB_VERSION_1_5     SOC_SCACHE_VERSION(1, 5)
    635 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_5
    636 
    637 /* Data structure for UDF Offset entry */
    638 struct bcmi_xgs4_wb_offset_entry_1_0 {
    639     uint8 flags;
    640     uint8 grp_id;
    641     uint8 num_pkt_formats;
    642 };
    643 
    644 /* Data structure for UDF offset info */
    645 struct bcmi_xgs4_wb_offset_info_1_0 {
    646 
    647     uint8 layer;
    648     uint8 start;
    649     uint8 width;
    650     uint8 flags;
    651 
    652     uint16 num_pkt_formats;
    653 
    654     uint16 id;
    655     uint32 byte_bmap;
    656 #if defined (BCM_TOMAHAWK_SUPPORT)
    657     bcm_pbmp_t associated_ports;
    658     uint32 associated_pipe;
    659 #endif
    660 };
    661 
    662 /* Data structure for UDF tcam info */
    663 struct bcmi_xgs4_wb_tcam_info_1_0 {
    664     uint16 hw_id;
    665     uint16 num_udfs;
    666 
    667     uint16 id;
    668     uint16 priority;
    669 
    670     uint16 udf_id_list[MAX_UDF_OFFSET_CHUNKS];
    671 #if defined (BCM_TOMAHAWK_SUPPORT)
    672     uint32 associated_pipe;
    673 #endif
    674 };
    675 
    676 #if defined (BCM_TOMAHAWK_SUPPORT)
    677 struct bcmi_xgs4_wb_tcam_info_1_3 {
    678     uint16 hw_idx;
    679     uint32 class_id;
    680     uint32 associated_pipe;
    681 };
    682 
    683 struct bcmi_xgs4_wb_tcam_info_1_4 {
    684     uint16 hw_idx[SOC_MAX_NUM_PIPES];
    685     uint16 num_udfs[SOC_MAX_NUM_PIPES];
    686     uint32 offset_bmap[SOC_MAX_NUM_PIPES];
    687     uint32 associated_pipes[SOC_MAX_NUM_PIPES];
    688     uint16 udf_id_list[MAX_UDF_ID_LIST];
    689 };
    690 #endif
    691 
    692 struct bcmi_xgs4_wb_tcam_info_1_5 {
    693     uint32 udf_field_bmp[SOC_MAX_NUM_PIPES];
    694     int max_chunks;
    695 };
    696 
    697 /* Returns required scache size in bytes for version = 1_0 */
    698 STATIC int
    699 bcmi_xgs4_udf_wb_scache_size_get_1_0(int unit, int *req_scache_size)
    700 {
    701     int alloc_size = 0;
    702     bcmi_xgs4_udf_ctrl_t *udf_ctrl;
    703 
    704     udf_ctrl = UDF_CTRL(unit);
    705 
    706     /* Number of UDFs */
    707     alloc_size += sizeof(udf_ctrl->num_udfs);
    708 
    709     /* Number of Packet formats */
    710     alloc_size += sizeof(udf_ctrl->num_pkt_formats);
    711 
    712 #if defined (BCM_TOMAHAWK_SUPPORT)
    713     if (SOC_IS_TOMAHAWKX(unit)) {
    714         /* operation mode */
    715         alloc_size += sizeof(bcmi_xgs4_udf_oper_mode[unit]);
    716     }
    717     if ((SOC_IS_TOMAHAWKX(unit)) &&
    718         (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) {
    719 
    720         alloc_size += (udf_ctrl->noffsets * SOC_MAX_NUM_PIPES *
    721                         sizeof (struct bcmi_xgs4_wb_offset_entry_1_0));
    722         /* offset nodes */
    723         alloc_size += (udf_ctrl->max_udfs * SOC_MAX_NUM_PIPES *
    724                         sizeof(struct bcmi_xgs4_wb_offset_info_1_0));
    725 
    726         /* tcam nodes */
    727         alloc_size += (udf_ctrl->nentries * SOC_MAX_NUM_PIPES *
    728                         sizeof(struct bcmi_xgs4_wb_tcam_info_1_0));
    729 
    730     } else
    731 #endif
    732     {
    733         /* offset entries */
    734         alloc_size += (udf_ctrl->noffsets *
    735                        sizeof (struct bcmi_xgs4_wb_offset_entry_1_0));
    736 
    737         /* offset nodes */
    738         alloc_size += (udf_ctrl->max_udfs *
    739                         sizeof(struct bcmi_xgs4_wb_offset_info_1_0));
    740 
    741         /* tcam nodes */
    742         alloc_size += (udf_ctrl->nentries *
    743                         sizeof(struct bcmi_xgs4_wb_tcam_info_1_0));
    744     }
    745 
    746     *req_scache_size = alloc_size;
    747 
    748     return BCM_E_NONE;
    749 }
    750 
    751 /* Returns required scache size in bytes for version = 1_1 */
    752 STATIC int
    753 bcmi_xgs4_udf_wb_scache_size_get_1_1(int unit, int *req_scache_size)
    754 {
    755     int alloc_size = 0;
    756 
    757     /* udf used by module */
    758     alloc_size += sizeof(UDF_CTRL(unit)->udf_used_by_module);
    759 
    760     *req_scache_size += alloc_size;
    761 
    762     return BCM_E_NONE;
    763 }
    764 
    765 #if defined (BCM_TOMAHAWK_SUPPORT)
    766 /* Returns required scache size in bytes for version = 1_3 */
    767 STATIC int
    768 bcmi_xgs4_udf_wb_scache_size_get_1_3(int unit, int *req_scache_size)
    769 {
    770     int alloc_size = 0;
    771 
    772     alloc_size += (UDF_CTRL(unit)->nentries * SOC_MAX_NUM_PIPES *
    773                         sizeof(struct bcmi_xgs4_wb_tcam_info_1_3));
    774 
    775     *req_scache_size += alloc_size;
    776 
    777     return BCM_E_NONE;
    778 }
    779 
    780 STATIC int
    781 bcmi_xgs4_udf_wb_scache_size_get_1_4(int unit, int *req_scache_size)
    782 {
    783     int alloc_size = 0;
    784 
    785     alloc_size = (UDF_CTRL(unit)->nentries *
    786                         sizeof(struct bcmi_xgs4_wb_tcam_info_1_4));
    787 
    788     *req_scache_size += alloc_size;
    789 
    790     return BCM_E_NONE;
    791 }
    792 #endif
    793 
    794 
    795 STATIC int
    796 bcmi_xgs4_udf_wb_scache_size_get_1_5(int unit, int *req_scache_size)
    797 {
    798 
    799     *req_scache_size += sizeof(struct bcmi_xgs4_wb_tcam_info_1_5);
    800 
    801     return BCM_E_NONE;
    802 }
    803 
    804 
    805 /* get warmboot recover version */
    806 STATIC int
    807 bcmi_xgs4_udf_recovered_version_get(
    808     int unit,
    809     uint16 *recovered_ver)
    810 {
    811     int     rv = BCM_E_INTERNAL;
    812     uint8   *scache_ptr;
    813     soc_scache_handle_t scache_handle;
    814 
    815     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_UDF, 0);
    816     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
    817                                  0, &scache_ptr,
    818                                  BCM_WB_DEFAULT_VERSION, recovered_ver);
    819 
    820     if (rv == BCM_E_NOT_FOUND) {
    821         *recovered_ver = BCM_WB_DEFAULT_VERSION;
    822         return BCM_E_NONE;
    823     }
    824 
    825     BCM_IF_ERROR_RETURN(rv);
    826 
    827     return BCM_E_NONE;
    828 }
    829 
    830 /* Recovers offsets info nodes from scache for version = 1_0 */
    831 STATIC int
    832 bcmi_xgs4_udf_wb_offset_info_reinit_1_0(int unit, int num_offset_nodes,
    833                                         uint8 **scache_ptr)
    834 {
    835     int rv;
    836     int i;
    837     int val = 0;
    838     uint32 offset_reserve[MAX_UDF_OFFSET_CHUNKS] = {0};
    839     int gran, max_chunks;
    840     bcm_udf_t udf_info;
    841     bcmi_xgs4_udf_offset_info_t *offset_info = NULL;
    842     bcmi_xgs4_udf_offset_entry_t *offset_entry_array; /* offset entries array.  */
    843     struct bcmi_xgs4_wb_offset_info_1_0 *scache_offset_p;
    844     uint8  byte_offset = 0;
    845     uint16 recovered_ver = BCM_WB_DEFAULT_VERSION;
    846 #if defined (BCM_TOMAHAWK_SUPPORT)
    847     int offset_num, port;
    848     soc_info_t  *si;
    849     si = &SOC_INFO(unit);
    850 #endif
    851 
    852     BCM_IF_ERROR_RETURN(
    853         bcmi_xgs4_udf_recovered_version_get(
    854                                         unit,
    855                                         &recovered_ver));
    856 
    857     gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit);
    858     max_chunks = BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit);
    859 
    860     scache_offset_p = (struct bcmi_xgs4_wb_offset_info_1_0 *)(*scache_ptr);
    861 
    862     /* Recover offset nodes from scache */
    863     while (num_offset_nodes > 0) {
    864 
    865         offset_info = NULL;
    866         sal_memset(offset_reserve, 0, sizeof(offset_reserve));
    867 
    868         udf_info.start = BYTES2BITS(scache_offset_p->start);
    869         udf_info.width = BYTES2BITS(scache_offset_p->width);
    870         udf_info.layer = scache_offset_p->layer;
    871 #if defined (BCM_TOMAHAWK_SUPPORT)
    872         if ((soc_feature(unit, soc_feature_udf_multi_pipe_support)) &&
    873            (recovered_ver >= BCM_WB_VERSION_1_2)) {
    874             SOC_PBMP_ASSIGN(udf_info.ports, scache_offset_p->associated_ports);
    875         }
    876 #endif
    877 
    878         rv = bcmi_xgs4_udf_offset_info_add(unit, &udf_info, &offset_info);
    879         BCM_IF_ERROR_RETURN(rv);
    880 
    881         offset_info->udf_id = scache_offset_p->id;
    882         offset_info->flags = scache_offset_p->flags;
    883         offset_info->num_pkt_formats = scache_offset_p->num_pkt_formats;
    884         offset_info->byte_bmap = scache_offset_p->byte_bmap;
    885 
    886 #if defined (BCM_TOMAHAWK_SUPPORT) 
    887         if ((soc_feature(unit, soc_feature_udf_multi_pipe_support)) && 
    888            (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) {
    889             SOC_PBMP_ITER(udf_info.ports, port) {
    890                 offset_info->associated_pipe = si->port_pipe[port];
    891                 break;
    892             }
    893             offset_entry_array =
    894                     UDF_CTRL(unit)->offset_entry_array_per_pipe[offset_info->associated_pipe];
    895         } else
    896 #endif
    897         {
    898             offset_entry_array = UDF_CTRL(unit)->offset_entry_array;
    899         }
    900         /* Compute byte offset again and store */
    901         if (gran == UDF_OFFSET_GRAN2) {
    902             byte_offset = offset_info->start % gran;
    903         } else {
    904             if (offset_info->layer == bcmUdfLayerL2Header) {
    905                 byte_offset = (offset_info->start + 2) % gran;
    906             } else {
    907                 byte_offset = offset_info->start % gran;
    908             }
    909         }
    910         offset_info->byte_offset = byte_offset;
    911 
    912         if (offset_info->udf_id > UDF_CTRL(unit)->udf_id_running) {
    913             UDF_CTRL(unit)->udf_id_running = offset_info->udf_id;
    914         }
    915 
    916         for (i = 0; i < max_chunks; i++) {
    917             SHR_BITTEST_RANGE(&(scache_offset_p->byte_bmap),
    918                                (i * gran), gran, val);
    919             if (val) {
    920                 SHR_BITCOPY_RANGE(&offset_reserve[i], 0, &(scache_offset_p->byte_bmap), i*gran, gran);
    921                 SHR_BITSET(&(offset_info->hw_bmap), i);
    922                 offset_info->grp_id = offset_entry_array[i].grp_id;
    923             }
    924         }
    925 
    926         /* Mark the global bitmap as used */
    927         (void) bcmi_xgs4_udf_offset_reserve(unit, max_chunks, (int *)offset_reserve,
    928                                             offset_info->associated_pipe);
    929 
    930         scache_offset_p++;
    931         num_offset_nodes--;
    932     }
    933 
    934     *scache_ptr = (uint8 *)scache_offset_p;
    935 
    936 /* clear invalid udf_offset cache recovery */
    937 #if defined (BCM_TOMAHAWK_SUPPORT)
    938    if (soc_feature(unit, soc_feature_udf_multi_pipe_support)) {
    939        offset_num = soc_mem_index_count(unit, FP_UDF_OFFSETm);
    940        for(i=0;i<offset_num;i++){
    941            if (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal) {
    942                soc_mem_cache_invalidate(unit, FP_UDF_OFFSETm, MEM_BLOCK_ALL, i);
    943            }
    944            else{
    945                soc_mem_cache_invalidate(unit, FP_UDF_OFFSET_PIPE0m, MEM_BLOCK_ALL, i);
    946                soc_mem_cache_invalidate(unit, FP_UDF_OFFSET_PIPE1m, MEM_BLOCK_ALL, i);
    947                soc_mem_cache_invalidate(unit, FP_UDF_OFFSET_PIPE2m, MEM_BLOCK_ALL, i);
    948                soc_mem_cache_invalidate(unit, FP_UDF_OFFSET_PIPE3m, MEM_BLOCK_ALL, i);
    949            }
    950        }
    951 }
    952 #endif
    953     return BCM_E_NONE;
    954 }
    955 
    956 /* Recovers tcam info nodes from scache for version = 1_0 */
    957 
    958 STATIC int
    959 bcmi_xgs4_udf_wb_tcam_info_reinit_1_0(int unit, int num_tcam_nodes,
    960                                       uint8 **scache_ptr)
    961 {
    962     uint32 *buffer;      /* Hw buffer to dma udf tcam. */
    963     uint32 *entry_ptr = 0;   /* Tcam entry pointer.    */
    964     int alloc_size;      /* Memory allocation size.    */
    965     int entry_size;      /* Single tcam entry size.    */
    966     soc_mem_t tcam_mem;  /* UDF_TCAM memory            */
    967     bcmi_xgs4_udf_tcam_entry_t *tcam_entry_arr; /* Tcam entries array.  */
    968     int idx;             /* Tcam entries iterator.     */
    969     int rv;              /* Operation return status.   */
    970     int udf_id;
    971     bcmi_xgs4_udf_offset_info_t *offset_info;
    972     bcmi_xgs4_udf_tcam_info_t *tcam_info = NULL;
    973     fp_udf_tcam_entry_t *tcam_buf;
    974     struct bcmi_xgs4_wb_tcam_info_1_0 *scache_tcam_p;
    975     uint16 recovered_ver = BCM_WB_DEFAULT_VERSION;
    976 
    977     BCM_IF_ERROR_RETURN(
    978         bcmi_xgs4_udf_recovered_version_get(
    979                                         unit,
    980                                         &recovered_ver));
    981 
    982     tcam_mem = UDF_CTRL(unit)->tcam_mem;
    983     tcam_entry_arr = UDF_CTRL(unit)->tcam_entry_array;
    984 
    985     entry_size = sizeof(fp_udf_tcam_entry_t);
    986     alloc_size = SOC_MEM_TABLE_BYTES(unit, tcam_mem);
    987 
    988     /* Allocate memory buffer. */
    989     buffer = soc_cm_salloc(unit, alloc_size, "Udf tcam");
    990     if (buffer == NULL) {
    991         return (BCM_E_MEMORY);
    992     }
    993 
    994     sal_memset(buffer, 0, alloc_size);
    995 
    996     /* Read table to the buffer. */
    997     rv = soc_mem_read_range(unit, tcam_mem, MEM_BLOCK_ANY,
    998                             soc_mem_index_min(unit, tcam_mem),
    999                             soc_mem_index_max(unit, tcam_mem), buffer);
   1000     if (BCM_FAILURE(rv)) {
   1001         soc_cm_sfree(unit, buffer);
   1002         return (BCM_E_INTERNAL);
   1003     }
   1004 
   1005 
   1006 
   1007     scache_tcam_p = (struct bcmi_xgs4_wb_tcam_info_1_0 *)(*scache_ptr);
   1008 
   1009     /* Recover tcam info from scache */
   1010     while (num_tcam_nodes > 0) {
   1011 
   1012         tcam_info = sal_alloc(sizeof(bcmi_xgs4_udf_tcam_info_t), "tcam info");
   1013         sal_memset(tcam_info, 0, sizeof(bcmi_xgs4_udf_tcam_info_t));
   1014 
   1015         idx = scache_tcam_p->hw_id;
   1016         tcam_info->hw_idx = idx;
   1017         tcam_info->pkt_format_id = scache_tcam_p->id;
   1018         tcam_info->priority = scache_tcam_p->priority;
   1019         tcam_info->num_udfs = scache_tcam_p->num_udfs;
   1020 #if defined (BCM_TOMAHAWK_SUPPORT)
   1021         if ((soc_feature(unit, soc_feature_udf_multi_pipe_support)) &&
   1022            (recovered_ver >= BCM_WB_VERSION_1_2) &&
   1023            (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) {
   1024             tcam_info->associated_pipe = scache_tcam_p->associated_pipe;
   1025             if (tcam_info->associated_pipe == BCMI_XGS4_UDF_INVALID_PIPE_NUM) {
   1026                 return BCM_E_PARAM;
   1027             }
   1028             tcam_entry_arr = UDF_CTRL(unit)->tcam_entry_array_per_pipe[tcam_info->associated_pipe];
   1029             tcam_mem = SOC_MEM_UNIQUE_ACC(unit, UDF_CTRL(unit)->tcam_mem)[tcam_info->associated_pipe];
   1030         }
   1031 #endif
   1032         entry_ptr = soc_mem_table_idx_to_pointer(unit, tcam_mem, uint32 *,
   1033                                                  buffer, idx);
   1034 
   1035         tcam_buf = (fp_udf_tcam_entry_t *)&(tcam_info->hw_buf);
   1036         sal_memcpy(tcam_buf, entry_ptr, entry_size);
   1037 
   1038         if (soc_mem_field32_get(unit, tcam_mem, entry_ptr, VALIDf)) {
   1039             tcam_entry_arr[idx].valid = 1;
   1040             tcam_entry_arr[idx].tcam_info = tcam_info;
   1041         }
   1042 
   1043         /* Not installed entries will have 512 as hw_idx */
   1044         if (idx < MAX_UDF_TCAM_ENTRIES) {
   1045 
   1046             for (idx = 0; idx < MAX_UDF_OFFSET_CHUNKS; idx++) {
   1047 
   1048                 udf_id = scache_tcam_p->udf_id_list[idx];
   1049 
   1050                 if (udf_id != 0) {
   1051                     rv = bcmi_xgs4_udf_offset_node_get(unit, udf_id,
   1052                                                        &offset_info);
   1053                     /* Continue recovering other udfs added to the tcam entry */
   1054                     if (BCM_SUCCESS(rv)) {
   1055                         tcam_info->offset_info_list[offset_info->grp_id] =
   1056                                                             offset_info;
   1057                         tcam_info->offset_bmap |= offset_info->hw_bmap;
   1058                         tcam_info->udf_id_list[idx] = offset_info->udf_id;
   1059                     }
   1060                 }
   1061             }
   1062             if (tcam_info->pkt_format_id >
   1063                 UDF_CTRL(unit)->udf_pkt_format_id_running) {
   1064 
   1065                 UDF_CTRL(unit)->udf_pkt_format_id_running =
   1066                     tcam_info->pkt_format_id;
   1067             }
   1068 
   1069         }
   1070 
   1071         /* Continue recovering other packet format entries even on failure */
   1072         (void) bcmi_xgs4_udf_tcam_node_add(unit, tcam_info);
   1073 
   1074         scache_tcam_p++;
   1075         num_tcam_nodes--;
   1076     }
   1077 
   1078     *scache_ptr = (uint8 *)scache_tcam_p;
   1079 
   1080     soc_cm_sfree(unit, buffer);
   1081 
   1082     return BCM_E_NONE;
   1083 }
   1084 
   1085 
   1086 /* Syncs offset nodes info into scache for version = 1_0 */
   1087 STATIC int
   1088 bcmi_xgs4_udf_wb_offset_info_sync_1_0(int unit, int num_offset_nodes,
   1089                                       uint8 **scache_ptr)
   1090 {
   1091     bcmi_xgs4_udf_offset_info_t *offset_info;
   1092     struct bcmi_xgs4_wb_offset_info_1_0 *scache_offset_p;
   1093 
   1094     scache_offset_p = (struct bcmi_xgs4_wb_offset_info_1_0 *)(*scache_ptr);
   1095 
   1096     offset_info = UDF_CTRL(unit)->offset_info_head;
   1097 
   1098     /* Recover offset nodes from scache */
   1099     while (num_offset_nodes > 0) {
   1100 
   1101         scache_offset_p->layer = offset_info->layer;
   1102         scache_offset_p->start = offset_info->start;
   1103         scache_offset_p->width = offset_info->width;
   1104         scache_offset_p->flags = offset_info->flags;
   1105 
   1106         scache_offset_p->num_pkt_formats = offset_info->num_pkt_formats;
   1107 
   1108         scache_offset_p->id = offset_info->udf_id;
   1109         scache_offset_p->byte_bmap = offset_info->byte_bmap;
   1110 #if defined (BCM_TOMAHAWK_SUPPORT)
   1111         if (soc_feature(unit, soc_feature_udf_multi_pipe_support)) {
   1112             scache_offset_p->associated_pipe = offset_info->associated_pipe;
   1113             SOC_PBMP_ASSIGN(scache_offset_p->associated_ports, offset_info->associated_ports);
   1114         }
   1115 #endif
   1116         num_offset_nodes--;
   1117         scache_offset_p++;
   1118         offset_info = offset_info->next;
   1119     }
   1120 
   1121     *scache_ptr = (uint8 *)scache_offset_p;
   1122 
   1123     return BCM_E_NONE;
   1124 }
   1125 
   1126 /* Syncs tcam nodes info into scache for version = 1_0 */
   1127 STATIC int
   1128 bcmi_xgs4_udf_wb_tcam_info_sync_1_0(int unit, int num_tcam_nodes,
   1129                                     uint8 **scache_ptr)
   1130 {
   1131     int idx;
   1132     bcmi_xgs4_udf_tcam_info_t *tcam_info;
   1133     struct bcmi_xgs4_wb_tcam_info_1_0 *scache_tcam_p;
   1134 
   1135 
   1136     tcam_info = UDF_CTRL(unit)->tcam_info_head;
   1137     scache_tcam_p = (struct bcmi_xgs4_wb_tcam_info_1_0 *)(*scache_ptr);
   1138 
   1139     /* Sync data to scache */
   1140     while (num_tcam_nodes > 0) {
   1141 
   1142         idx = scache_tcam_p->hw_id;
   1143         scache_tcam_p->hw_id = tcam_info->hw_idx;
   1144         scache_tcam_p->id = tcam_info->pkt_format_id;
   1145         scache_tcam_p->priority = tcam_info->priority;
   1146         scache_tcam_p->num_udfs = tcam_info->num_udfs;
   1147 #if defined (BCM_TOMAHAWK_SUPPORT)
   1148         if (soc_feature(unit, soc_feature_udf_multi_pipe_support)) {
   1149             scache_tcam_p->associated_pipe = tcam_info->associated_pipe;
   1150         }
   1151 #endif
   1152 
   1153         for (idx = 0; idx < MAX_UDF_OFFSET_CHUNKS; idx++) {
   1154             if (tcam_info->offset_info_list[idx] != NULL) {
   1155                 scache_tcam_p->udf_id_list[idx] =
   1156                     (tcam_info->offset_info_list[idx])->udf_id;
   1157             } else {
   1158                 scache_tcam_p->udf_id_list[idx] = 0;
   1159             }
   1160         }
   1161 
   1162         scache_tcam_p++;
   1163         num_tcam_nodes--;
   1164         tcam_info = tcam_info->next;
   1165     }
   1166 
   1167     *scache_ptr = (uint8 *)scache_tcam_p;
   1168 
   1169     return BCM_E_NONE;
   1170 }
   1171 
   1172 #if defined (BCM_TOMAHAWK_SUPPORT) && defined (BCM_WB_VERSION_1_3)
   1173 STATIC int
   1174 bcmi_xgs4_udf_wb_offset_info_reinit_1_2_to_1_3
   1175                             (int unit, int num_offset_nodes,
   1176                              uint8 **scache_ptr,
   1177                              struct bcmi_xgs4_wb_offset_entry_1_0 *offset_entry_scache_p)
   1178 {
   1179 
   1180     int rv;
   1181     int i;
   1182     int val = 0;
   1183     uint32 offset_reserve[MAX_UDF_OFFSET_CHUNKS] = {0};
   1184     int gran;
   1185     bcm_udf_t udf_info;
   1186     bcmi_xgs4_udf_offset_info_t   *offset_info = NULL;
   1187     bcmi_xgs4_udf_offset_entry_t  *offset_entry_array; /* offset entries array.  */
   1188     struct bcmi_xgs4_wb_offset_entry_1_0 *offset_entry_recover_p;
   1189     struct bcmi_xgs4_wb_offset_info_1_0 *scache_offset_p;
   1190     uint8  byte_offset = 0;
   1191     int offset_num;
   1192     int port = 0, max_chunks = 0;
   1193     soc_info_t  *si;
   1194     si = &SOC_INFO(unit);
   1195 
   1196     gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit);
   1197     max_chunks = BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit);
   1198 
   1199     offset_entry_recover_p = offset_entry_scache_p;
   1200     for (i = 0; i < max_chunks; i++) {
   1201         /* skip offset entry reinit */
   1202         offset_entry_scache_p++;
   1203     }
   1204     scache_offset_p = (struct bcmi_xgs4_wb_offset_info_1_0 *)offset_entry_scache_p;
   1205 
   1206     /* Recover offset nodes from scache */
   1207     while (num_offset_nodes > 0) {
   1208 
   1209         offset_info = NULL;
   1210         sal_memset(offset_reserve, 0, sizeof(offset_reserve));
   1211 
   1212         udf_info.start = BYTES2BITS(scache_offset_p->start);
   1213         udf_info.width = BYTES2BITS(scache_offset_p->width);
   1214         udf_info.layer = scache_offset_p->layer;
   1215 
   1216         SOC_PBMP_ASSIGN(udf_info.ports, scache_offset_p->associated_ports);
   1217 
   1218         rv = bcmi_xgs4_udf_offset_info_add(unit, &udf_info, &offset_info);
   1219         BCM_IF_ERROR_RETURN(rv);
   1220 
   1221         offset_info->udf_id = scache_offset_p->id;
   1222         offset_info->flags = scache_offset_p->flags;
   1223         offset_info->num_pkt_formats = scache_offset_p->num_pkt_formats;
   1224         offset_info->byte_bmap = scache_offset_p->byte_bmap;
   1225 
   1226         SOC_PBMP_ITER(udf_info.ports, port) {
   1227             offset_info->associated_pipe = si->port_pipe[port];
   1228             break;
   1229          }
   1230 
   1231          offset_entry_array =
   1232                     UDF_CTRL(unit)->offset_entry_array_per_pipe[offset_info->associated_pipe];
   1233 
   1234        /* Compute byte offset again and store */
   1235         if (gran == UDF_OFFSET_GRAN2) {
   1236             byte_offset = offset_info->start % gran;
   1237         } else {
   1238             if (offset_info->layer == bcmUdfLayerL2Header) {
   1239                 byte_offset = (offset_info->start + 2) % gran;
   1240             } else {
   1241                 byte_offset = offset_info->start % gran;
   1242             }
   1243         }
   1244         offset_info->byte_offset = byte_offset;
   1245 
   1246         if (offset_info->udf_id > UDF_CTRL(unit)->udf_id_running) {
   1247             UDF_CTRL(unit)->udf_id_running = offset_info->udf_id;
   1248         }
   1249 
   1250         for (i = 0; i < max_chunks; i++) {
   1251             SHR_BITTEST_RANGE(&(scache_offset_p->byte_bmap),
   1252                                (i * gran), gran, val);
   1253             offset_entry_scache_p = offset_entry_recover_p;
   1254             if (val) {
   1255                 SHR_BITCOPY_RANGE(&offset_reserve[i], 0, &(scache_offset_p->byte_bmap), i*gran, gran);
   1256                 SHR_BITSET(&(offset_info->hw_bmap), i);
   1257 
   1258                 offset_entry_scache_p += i;
   1259                 offset_entry_array[i].flags =  offset_entry_scache_p->flags;
   1260                 offset_entry_array[i].grp_id = offset_entry_scache_p->grp_id;
   1261                 offset_entry_array[i].num_pkt_formats = offset_entry_scache_p->num_pkt_formats;
   1262 
   1263                 offset_info->grp_id = offset_entry_scache_p->grp_id;
   1264 
   1265             }
   1266         }
   1267 
   1268         /* Mark the global bitmap as used */
   1269         (void) bcmi_xgs4_udf_offset_reserve(unit, max_chunks, (int *)offset_reserve,
   1270                                             offset_info->associated_pipe);
   1271 
   1272         scache_offset_p++;
   1273         num_offset_nodes--;
   1274     }
   1275 
   1276     *scache_ptr = (uint8 *)scache_offset_p;
   1277 
   1278 /* clear invalid udf_offset cache recovery */
   1279    offset_num = soc_mem_index_count(unit, FP_UDF_OFFSETm);
   1280    for(i=0;i<offset_num;i++){
   1281        if (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal) {
   1282            soc_mem_cache_invalidate(unit, FP_UDF_OFFSETm, MEM_BLOCK_ALL, i);
   1283        }
   1284        else{
   1285            soc_mem_cache_invalidate(unit, FP_UDF_OFFSET_PIPE0m, MEM_BLOCK_ALL, i);
   1286            soc_mem_cache_invalidate(unit, FP_UDF_OFFSET_PIPE1m, MEM_BLOCK_ALL, i);
   1287            soc_mem_cache_invalidate(unit, FP_UDF_OFFSET_PIPE2m, MEM_BLOCK_ALL, i);
   1288            soc_mem_cache_invalidate(unit, FP_UDF_OFFSET_PIPE3m, MEM_BLOCK_ALL, i);
   1289        }
   1290     }
   1291 
   1292     rv = bcmi_xgs4_udf_wb_tcam_info_reinit_1_0(unit,
   1293                 UDF_CTRL(unit)->num_pkt_formats, scache_ptr);
   1294     BCM_IF_ERROR_RETURN(rv);
   1295 
   1296     return BCM_E_NONE;
   1297 }
   1298 
   1299 /* Recovers UDF control state for offset multipipe support */
   1300 STATIC int
   1301 bcmi_xgs4_udf_wb_reinit_multipipe
   1302                             (int unit,
   1303                              uint8 **scache_ptr,
   1304                              struct bcmi_xgs4_wb_offset_entry_1_0* offset_entry_scache_p,
   1305                              uint16 recovered_ver, int max_chunks
   1306                             )
   1307 {
   1308     int pipe, i, rv;
   1309     bcmi_xgs4_udf_offset_entry_t *offset_entry;
   1310 
   1311     if (recovered_ver >= BCM_WB_VERSION_1_3) {
   1312         for (pipe = 0; pipe < SOC_MAX_NUM_PIPES; pipe++) {
   1313             for (i = 0; i < max_chunks; i++) {
   1314                 offset_entry = &(UDF_CTRL(unit)->offset_entry_array_per_pipe[pipe][i]);
   1315                 offset_entry->flags = offset_entry_scache_p->flags;
   1316                 offset_entry->grp_id = offset_entry_scache_p->grp_id;
   1317                 offset_entry->num_pkt_formats = offset_entry_scache_p->num_pkt_formats;
   1318                 offset_entry_scache_p++;
   1319             }
   1320         }
   1321     } else {
   1322         rv = bcmi_xgs4_udf_wb_offset_info_reinit_1_2_to_1_3(unit,
   1323                                           UDF_CTRL(unit)->num_udfs,
   1324                                           scache_ptr, offset_entry_scache_p);
   1325         return rv;
   1326     }
   1327     *scache_ptr = (uint8 *)offset_entry_scache_p;
   1328 
   1329     rv = bcmi_xgs4_udf_wb_offset_info_reinit_1_0(unit,
   1330                  UDF_CTRL(unit)->num_udfs, scache_ptr);
   1331     BCM_IF_ERROR_RETURN(rv);
   1332 
   1333     rv = bcmi_xgs4_udf_wb_tcam_info_reinit_1_0(unit,
   1334                 UDF_CTRL(unit)->num_pkt_formats, scache_ptr);
   1335     BCM_IF_ERROR_RETURN(rv);
   1336 
   1337     return BCM_E_NONE;
   1338 
   1339 }
   1340 #endif /* (BCM_TOMAHAWK_SUPPORT) && (BCM_WB_VERSION_1_3) */
   1341 
   1342 /* Recovers UDF control state from scache for version = 1_0 */
   1343 STATIC int
   1344 bcmi_xgs4_udf_wb_reinit_1_0(int unit, uint8 **scache_ptr)
   1345 {
   1346     int rv;
   1347     int i;
   1348     int max_chunks;
   1349     bcmi_xgs4_udf_offset_entry_t *offset_entry;
   1350     struct bcmi_xgs4_wb_offset_entry_1_0 *offset_entry_scache_p;
   1351     uint32 *u32_scache_p;
   1352     uint16 recovered_ver = BCM_WB_DEFAULT_VERSION;
   1353 
   1354     BCM_IF_ERROR_RETURN(
   1355         bcmi_xgs4_udf_recovered_version_get(
   1356                                         unit,
   1357                                         &recovered_ver));
   1358 
   1359     max_chunks = UDF_CTRL(unit)->noffsets;
   1360 
   1361     u32_scache_p = (uint32 *)(*scache_ptr);
   1362 
   1363 #if defined (BCM_TOMAHAWK_SUPPORT)
   1364     if ((SOC_IS_TOMAHAWKX(unit)) &&
   1365         (recovered_ver >= BCM_WB_VERSION_1_2)) {
   1366         /* Operation Mode Retrieval */
   1367         bcmi_xgs4_udf_oper_mode_set(unit,u32_scache_p[2]);
   1368     }
   1369 #endif
   1370 
   1371     /* Number of UDFs created */
   1372     UDF_CTRL(unit)->num_udfs = *u32_scache_p;
   1373     u32_scache_p++;
   1374 
   1375     /* Number of Packet formats created */
   1376     UDF_CTRL(unit)->num_pkt_formats = *u32_scache_p;
   1377     u32_scache_p++;
   1378 
   1379 #if defined (BCM_TOMAHAWK_SUPPORT)
   1380     if ((SOC_IS_TOMAHAWKX(unit)) &&
   1381         (recovered_ver >= BCM_WB_VERSION_1_2)) {
   1382         /* Pass Operation Mode */
   1383         u32_scache_p++;
   1384     }
   1385 #endif
   1386     offset_entry_scache_p =
   1387         (struct bcmi_xgs4_wb_offset_entry_1_0 *)u32_scache_p;
   1388 
   1389 
   1390 #if defined (BCM_TOMAHAWK_SUPPORT) && defined (BCM_WB_VERSION_1_3)
   1391     if ((SOC_IS_TOMAHAWKX(unit)) &&
   1392         (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) {
   1393         rv = bcmi_xgs4_udf_wb_reinit_multipipe(unit, scache_ptr, 
   1394                                                offset_entry_scache_p, 
   1395                                                recovered_ver, max_chunks);
   1396         return rv;
   1397     }
   1398 #endif
   1399     for (i = 0; i < max_chunks; i++) {
   1400         offset_entry = &(UDF_CTRL(unit)->offset_entry_array[i]);
   1401 
   1402         offset_entry->flags = offset_entry_scache_p->flags;
   1403         offset_entry->grp_id = offset_entry_scache_p->grp_id;
   1404         offset_entry->num_pkt_formats = offset_entry_scache_p->num_pkt_formats;
   1405 
   1406         offset_entry_scache_p++;
   1407     }
   1408     *scache_ptr = (uint8 *)offset_entry_scache_p;
   1409 
   1410     rv = bcmi_xgs4_udf_wb_offset_info_reinit_1_0(unit,
   1411                  UDF_CTRL(unit)->num_udfs, scache_ptr);
   1412     BCM_IF_ERROR_RETURN(rv);
   1413 
   1414     rv = bcmi_xgs4_udf_wb_tcam_info_reinit_1_0(unit,
   1415                 UDF_CTRL(unit)->num_pkt_formats, scache_ptr);
   1416     BCM_IF_ERROR_RETURN(rv);
   1417 
   1418     return BCM_E_NONE;
   1419 }
   1420 
   1421 /* Recovers UDF control state from scache for version = 1_1 */
   1422 STATIC int
   1423 bcmi_xgs4_udf_wb_reinit_1_1(int unit, uint8 **scache_ptr)
   1424 {
   1425     uint32 *u32_scache_p;
   1426 
   1427     u32_scache_p = (uint32 *)(*scache_ptr);
   1428 
   1429     /* Udf resource of used module */
   1430     UDF_CTRL(unit)->udf_used_by_module = *u32_scache_p;
   1431     u32_scache_p++;
   1432 
   1433     *scache_ptr = (uint8 *)u32_scache_p;
   1434 
   1435     return BCM_E_NONE;
   1436 }
   1437 
   1438 #if defined (BCM_TOMAHAWK_SUPPORT)
   1439 /* Recovers UDF control state from scache for version = 1_3 */
   1440 STATIC int
   1441 bcmi_xgs4_udf_wb_reinit_1_3(int unit, uint8 **scache_ptr)
   1442 {
   1443     bcmi_xgs4_udf_tcam_entry_t *tcam_entry_arr; /* Tcam entries array.  */
   1444     int num_tcam_nodes;
   1445     struct bcmi_xgs4_wb_tcam_info_1_3 *scache_tcam_p;
   1446 
   1447     scache_tcam_p = (struct bcmi_xgs4_wb_tcam_info_1_3 *)(*scache_ptr);
   1448     num_tcam_nodes = UDF_CTRL(unit)->num_pkt_formats;
   1449 
   1450     while (num_tcam_nodes > 0) {
   1451         if (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal) {
   1452             tcam_entry_arr = 
   1453             UDF_CTRL(unit)->tcam_entry_array_per_pipe[scache_tcam_p->associated_pipe];
   1454         } else {
   1455             tcam_entry_arr = UDF_CTRL(unit)->tcam_entry_array;
   1456         }
   1457         if (tcam_entry_arr[scache_tcam_p->hw_idx].tcam_info != NULL) {
   1458             tcam_entry_arr[scache_tcam_p->hw_idx].tcam_info->class_id = scache_tcam_p->class_id;
   1459         }
   1460         scache_tcam_p++;
   1461         num_tcam_nodes--;
   1462     }
   1463 
   1464     *scache_ptr = (uint8 *)scache_tcam_p;
   1465 
   1466     return BCM_E_NONE;
   1467 }
   1468 
   1469 STATIC int
   1470 bcmi_xgs4_udf_wb_tcam_info_reinit_1_2_to_1_4(int unit)
   1471 {
   1472     int idx;
   1473     int pipe;
   1474     bcmi_xgs4_udf_tcam_info_t *tcam_info;
   1475 
   1476     if (soc_feature(unit, soc_feature_udf_multi_pipe_support) &&
   1477         bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal) {
   1478         tcam_info = UDF_CTRL(unit)->tcam_info_head;
   1479 
   1480         while (tcam_info) {
   1481             for (idx = 0; idx < SOC_MAX_NUM_PIPES; idx++) {
   1482                 tcam_info->hw_idx_per_pipe[idx] = MAX_UDF_TCAM_ENTRIES;
   1483                 tcam_info->associated_pipes[idx] = BCMI_XGS4_UDF_INVALID_PIPE_NUM;
   1484             }
   1485 
   1486             pipe = tcam_info->associated_pipe;
   1487             tcam_info->hw_idx_per_pipe[pipe] = tcam_info->hw_idx;
   1488             tcam_info->num_udfs_per_pipe[pipe] = tcam_info->num_udfs;
   1489             tcam_info->offset_bmap_per_pipe[pipe] = tcam_info->offset_bmap;
   1490             tcam_info->associated_pipes[pipe] = pipe;
   1491             tcam_info = tcam_info->next;
   1492         }
   1493     }
   1494 
   1495     return BCM_E_NONE;
   1496 }
   1497 
   1498 STATIC int
   1499 bcmi_xgs4_udf_wb_reinit_1_4(int unit, uint8 **scache_ptr)
   1500 {
   1501     int idx;
   1502     int pipe;
   1503     int hw_idx;
   1504     soc_mem_t tcam_mem;
   1505     bcmi_xgs4_udf_tcam_info_t *tcam_info;
   1506     bcmi_xgs4_udf_tcam_entry_t *tcam_entry_arr;
   1507     struct bcmi_xgs4_wb_tcam_info_1_4 *scache_tcam_p;
   1508 
   1509     if (soc_feature(unit, soc_feature_udf_multi_pipe_support) &&
   1510         bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal) {
   1511         tcam_info = UDF_CTRL(unit)->tcam_info_head;
   1512         scache_tcam_p = (struct bcmi_xgs4_wb_tcam_info_1_4*)(*scache_ptr);
   1513 
   1514         while (tcam_info) {
   1515             for (idx = 0; idx < SOC_MAX_NUM_PIPES; idx++) {
   1516                 tcam_info->hw_idx_per_pipe[idx] = scache_tcam_p->hw_idx[idx];
   1517                 tcam_info->num_udfs_per_pipe[idx] = scache_tcam_p->num_udfs[idx];
   1518                 tcam_info->offset_bmap_per_pipe[idx] = scache_tcam_p->offset_bmap[idx];
   1519                 tcam_info->associated_pipes[idx] = scache_tcam_p->associated_pipes[idx];
   1520 
   1521                 pipe = tcam_info->associated_pipes[idx];
   1522                 hw_idx = tcam_info->hw_idx_per_pipe[idx];
   1523                 if (hw_idx == MAX_UDF_TCAM_ENTRIES ||
   1524                     pipe == BCMI_XGS4_UDF_INVALID_PIPE_NUM) {
   1525                     continue;
   1526                 }
   1527 
   1528                 tcam_entry_arr = UDF_CTRL(unit)->tcam_entry_array_per_pipe[pipe];
   1529                 tcam_mem = SOC_MEM_UNIQUE_ACC(unit, UDF_CTRL(unit)->tcam_mem)[pipe];
   1530 
   1531                 BCM_IF_ERROR_RETURN(
   1532                     soc_mem_read(unit, tcam_mem, MEM_BLOCK_ALL, hw_idx, &tcam_info->hw_buf));
   1533 
   1534                 if (soc_mem_field32_get(unit, tcam_mem, &tcam_info->hw_buf, VALIDf)) {
   1535                     tcam_entry_arr[hw_idx].valid = 1;
   1536                     tcam_entry_arr[hw_idx].tcam_info = tcam_info;
   1537                 }
   1538             }
   1539 
   1540             for (idx = 0; idx < MAX_UDF_ID_LIST; idx++) {
   1541                 tcam_info->udf_id_list[idx] = scache_tcam_p->udf_id_list[idx];
   1542             }
   1543 
   1544             scache_tcam_p++;
   1545             tcam_info = tcam_info->next;
   1546         }
   1547 
   1548         *scache_ptr = (uint8 *)scache_tcam_p;
   1549     }
   1550 
   1551     return BCM_E_NONE;
   1552 }
   1553 #endif
   1554 
   1555 STATIC int
   1556 bcmi_xgs4_udf_wb_reinit_1_5(int unit, uint8 **scache_ptr)
   1557 {
   1558     int idx;
   1559     struct bcmi_xgs4_wb_tcam_info_1_5 *scache_tcam_p;
   1560 
   1561     scache_tcam_p = (struct bcmi_xgs4_wb_tcam_info_1_5*)(*scache_ptr);
   1562 
   1563     for (idx = 0; idx < SOC_MAX_NUM_PIPES; idx++) {
   1564         sal_memcpy(UDF_CTRL(unit)->udf_field_bmp[idx].w,
   1565                    &(scache_tcam_p->udf_field_bmp[idx]),
   1566                    sizeof(uint32));
   1567     }
   1568     UDF_CTRL(unit)->max_chunks = scache_tcam_p->max_chunks;
   1569 
   1570     scache_tcam_p++;
   1571     *scache_ptr = (uint8 *)scache_tcam_p;
   1572 
   1573 
   1574     return BCM_E_NONE;
   1575 }
   1576 
   1577 /* Syncs UDF control state into scache for version = 1_0 */
   1578 STATIC int
   1579 bcmi_xgs4_udf_wb_sync_1_0(int unit, uint8 **scache_ptr)
   1580 {
   1581     int rv;
   1582     int i;
   1583     int max_chunks;
   1584     struct bcmi_xgs4_wb_offset_entry_1_0 *offset_entry_scache_p;
   1585     uint32 *u32_scache_p;
   1586 
   1587 #if defined (BCM_TOMAHAWK_SUPPORT)
   1588     int pipe = 0;
   1589 #endif
   1590     max_chunks = UDF_CTRL(unit)->noffsets;
   1591 
   1592     u32_scache_p = (uint32 *)(*scache_ptr);
   1593 
   1594     /* Number of UDFs created */
   1595     *u32_scache_p = UDF_CTRL(unit)->num_udfs;
   1596     u32_scache_p++;
   1597 
   1598     /* Number of Packet formats created */
   1599     *u32_scache_p = UDF_CTRL(unit)->num_pkt_formats;
   1600     u32_scache_p++;
   1601 
   1602 #if defined (BCM_TOMAHAWK_SUPPORT)
   1603     if (SOC_IS_TOMAHAWKX(unit)) {
   1604         /* saving operation mode */
   1605         *u32_scache_p = bcmi_xgs4_udf_oper_mode[unit] ;
   1606         u32_scache_p++;
   1607     }
   1608 #endif
   1609 
   1610     offset_entry_scache_p =
   1611         (struct bcmi_xgs4_wb_offset_entry_1_0 *)u32_scache_p;
   1612 
   1613 #if defined (BCM_TOMAHAWK_SUPPORT)
   1614     if ((soc_feature(unit, soc_feature_udf_multi_pipe_support)) &&
   1615         (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) {
   1616 
   1617         for (pipe = 0; pipe < SOC_MAX_NUM_PIPES; pipe++) {
   1618             for (i = 0; i < max_chunks; i++) {
   1619                 offset_entry_scache_p->flags =
   1620                     (UDF_CTRL(unit)->offset_entry_array_per_pipe[pipe][i]).flags;
   1621                 offset_entry_scache_p->grp_id =
   1622                     (UDF_CTRL(unit)->offset_entry_array_per_pipe[pipe][i]).grp_id;
   1623                 offset_entry_scache_p->num_pkt_formats =
   1624                     (UDF_CTRL(unit)->offset_entry_array_per_pipe[pipe][i]).num_pkt_formats;
   1625                 offset_entry_scache_p++;
   1626             }
   1627         }
   1628     } else
   1629 #endif
   1630     {
   1631         for (i = 0; i < max_chunks; i++) {
   1632             offset_entry_scache_p->flags =
   1633                     (UDF_CTRL(unit)->offset_entry_array[i]).flags;
   1634             offset_entry_scache_p->grp_id =
   1635                     (UDF_CTRL(unit)->offset_entry_array[i]).grp_id;
   1636             offset_entry_scache_p->num_pkt_formats =
   1637                     (UDF_CTRL(unit)->offset_entry_array[i]).num_pkt_formats;
   1638 
   1639             offset_entry_scache_p++;
   1640         }
   1641     }
   1642 
   1643     *scache_ptr = (uint8 *)offset_entry_scache_p;
   1644 
   1645     rv = bcmi_xgs4_udf_wb_offset_info_sync_1_0(unit,
   1646                 UDF_CTRL(unit)->num_udfs, scache_ptr);
   1647     BCM_IF_ERROR_RETURN(rv);
   1648 
   1649     rv = bcmi_xgs4_udf_wb_tcam_info_sync_1_0(unit,
   1650                 UDF_CTRL(unit)->num_pkt_formats, scache_ptr);
   1651     BCM_IF_ERROR_RETURN(rv);
   1652 
   1653     return BCM_E_NONE;
   1654 }
   1655 
   1656 /* Syncs UDF control state into scache for version = 1_1 */
   1657 STATIC int
   1658 bcmi_xgs4_udf_wb_sync_1_1(int unit, uint8 **scache_ptr)
   1659 {
   1660     uint32 *u32_scache_p;
   1661 
   1662     u32_scache_p = (uint32 *)(*scache_ptr);
   1663 
   1664     /* Udf resource of used module */
   1665     *u32_scache_p = UDF_CTRL(unit)->udf_used_by_module;
   1666     u32_scache_p++;
   1667 
   1668     *scache_ptr = (uint8 *)u32_scache_p;
   1669 
   1670     return BCM_E_NONE;
   1671 }
   1672 
   1673 #if defined (BCM_TOMAHAWK_SUPPORT)
   1674 /* Syncs UDF control state into scache for version = 1_3 */
   1675 STATIC int
   1676 bcmi_xgs4_udf_wb_sync_1_3(int unit, uint8 **scache_ptr)
   1677 {
   1678     int num_tcam_nodes;
   1679     bcmi_xgs4_udf_tcam_info_t *tcam_info;
   1680     struct bcmi_xgs4_wb_tcam_info_1_3 *scache_tcam_p;
   1681 
   1682     tcam_info = UDF_CTRL(unit)->tcam_info_head;
   1683     scache_tcam_p = (struct bcmi_xgs4_wb_tcam_info_1_3 *)(*scache_ptr);
   1684     num_tcam_nodes = UDF_CTRL(unit)->num_pkt_formats;
   1685 
   1686     /* Sync data to scache */
   1687     while (num_tcam_nodes > 0) {
   1688         scache_tcam_p->hw_idx = tcam_info->hw_idx;
   1689         scache_tcam_p->class_id = tcam_info->class_id;
   1690         /* in global mode, this should be always 0 */
   1691         scache_tcam_p->associated_pipe=tcam_info->associated_pipe;
   1692         scache_tcam_p++;
   1693         num_tcam_nodes--;
   1694         tcam_info = tcam_info->next;
   1695     }
   1696 
   1697     *scache_ptr = (uint8 *)scache_tcam_p;
   1698 
   1699     return BCM_E_NONE;
   1700 }
   1701 
   1702 STATIC int
   1703 bcmi_xgs4_udf_wb_sync_1_4(int unit, uint8 **scache_ptr)
   1704 {
   1705     int idx;
   1706     bcmi_xgs4_udf_tcam_info_t *tcam_info;
   1707     struct bcmi_xgs4_wb_tcam_info_1_4 *scache_tcam_p;
   1708 
   1709     if ((soc_feature(unit, soc_feature_udf_multi_pipe_support)) &&
   1710         (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) {
   1711         tcam_info = UDF_CTRL(unit)->tcam_info_head;
   1712         scache_tcam_p = (struct bcmi_xgs4_wb_tcam_info_1_4*)(*scache_ptr);
   1713 
   1714         while (tcam_info) {
   1715             for (idx = 0; idx < SOC_MAX_NUM_PIPES; idx++) {
   1716                 scache_tcam_p->hw_idx[idx] = tcam_info->hw_idx_per_pipe[idx];
   1717                 scache_tcam_p->num_udfs[idx] = tcam_info->num_udfs_per_pipe[idx];
   1718                 scache_tcam_p->offset_bmap[idx] = tcam_info->offset_bmap_per_pipe[idx];
   1719                 scache_tcam_p->associated_pipes[idx] = tcam_info->associated_pipes[idx];
   1720             }
   1721 
   1722             for (idx = 0; idx < MAX_UDF_ID_LIST; idx++) {
   1723                 scache_tcam_p->udf_id_list[idx] = tcam_info->udf_id_list[idx];
   1724             }
   1725 
   1726             scache_tcam_p++;
   1727             tcam_info = tcam_info->next;
   1728         }
   1729 
   1730         *scache_ptr = (uint8*)scache_tcam_p;
   1731     }
   1732 
   1733     return BCM_E_NONE;
   1734 }
   1735 #endif
   1736 
   1737 STATIC int
   1738 bcmi_xgs4_udf_wb_sync_1_5(int unit, uint8 **scache_ptr)
   1739 {
   1740     int idx;
   1741     struct bcmi_xgs4_wb_tcam_info_1_5 *scache_tcam_p;
   1742 
   1743     scache_tcam_p = (struct bcmi_xgs4_wb_tcam_info_1_5*)(*scache_ptr);
   1744 
   1745     for (idx = 0; idx < SOC_MAX_NUM_PIPES; idx++) {
   1746         sal_memcpy(&(scache_tcam_p->udf_field_bmp[idx]),
   1747                    UDF_CTRL(unit)->udf_field_bmp[idx].w,
   1748                    sizeof(uint32));
   1749     }
   1750     scache_tcam_p->max_chunks = UDF_CTRL(unit)->max_chunks;
   1751     scache_tcam_p++;
   1752     *scache_ptr = (uint8*)scache_tcam_p;
   1753 
   1754     return BCM_E_NONE;
   1755 }
   1756 
   1757 
   1758 /* Returns required scache size for UDF module */
   1759 STATIC int
   1760 bcmi_xgs4_udf_wb_scache_size_get(int unit, int *req_scache_size)
   1761 {
   1762     BCM_IF_ERROR_RETURN(
   1763         bcmi_xgs4_udf_wb_scache_size_get_1_0(unit, req_scache_size));
   1764 
   1765     BCM_IF_ERROR_RETURN(
   1766         bcmi_xgs4_udf_wb_scache_size_get_1_1(unit, req_scache_size));
   1767 
   1768 #if defined (BCM_TOMAHAWK_SUPPORT)
   1769     BCM_IF_ERROR_RETURN(
   1770         bcmi_xgs4_udf_wb_scache_size_get_1_3(unit, req_scache_size));
   1771 
   1772     BCM_IF_ERROR_RETURN(
   1773         bcmi_xgs4_udf_wb_scache_size_get_1_4(unit, req_scache_size));
   1774 #endif
   1775 
   1776     if (soc_feature(unit, soc_feature_udf_selector_support)) {
   1777         BCM_IF_ERROR_RETURN(
   1778             bcmi_xgs4_udf_wb_scache_size_get_1_5(unit, req_scache_size));
   1779     }
   1780 
   1781     return BCM_E_NONE;
   1782 }
   1783 
   1784 /* Allocates required scache size for the UDF module recovery */
   1785 STATIC int
   1786 bcmi_xgs4_udf_wb_alloc(int unit)
   1787 {
   1788     int     rv;
   1789     int     req_scache_size;
   1790     uint8   *scache_ptr;
   1791     soc_scache_handle_t scache_handle;
   1792 
   1793     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_UDF, 0);
   1794 
   1795     rv = bcmi_xgs4_udf_wb_scache_size_get(unit, &req_scache_size);
   1796     BCM_IF_ERROR_RETURN(rv);
   1797 
   1798    rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE,
   1799             req_scache_size, &scache_ptr, BCM_WB_DEFAULT_VERSION, NULL);
   1800 
   1801     if (BCM_E_NOT_FOUND == rv) {
   1802         /* Proceed with Level 1 Warm Boot */
   1803         rv = BCM_E_NONE;
   1804     }
   1805 
   1806     BCM_IF_ERROR_RETURN(rv);
   1807 
   1808     return BCM_E_NONE;
   1809 }
   1810 
   1811 /*
   1812  * Function:
   1813  *      bcmi_xgs4_udf_wb_sync
   1814  * Purpose:
   1815  *      Syncs UDF warmboot state to scache
   1816  * Parameters:
   1817  *      unit            - (IN)  Unit number.
   1818  * Returns:
   1819  *      BCM_E_XXX
   1820  * Notes:
   1821  */
   1822 int
   1823 bcmi_xgs4_udf_wb_sync(int unit)
   1824 {
   1825     uint8   *scache_ptr;
   1826     soc_scache_handle_t scache_handle;
   1827 
   1828     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_UDF, 0);
   1829 
   1830     BCM_IF_ERROR_RETURN
   1831         (_bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
   1832                                  0, &scache_ptr,
   1833                                  BCM_WB_DEFAULT_VERSION, NULL));
   1834     if (UDF_CTRL(unit) != NULL) {
   1835         BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_wb_sync_1_0(unit, &scache_ptr));
   1836         BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_wb_sync_1_1(unit, &scache_ptr));
   1837 #if defined (BCM_TOMAHAWK_SUPPORT)
   1838         BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_wb_sync_1_3(unit, &scache_ptr));
   1839         BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_wb_sync_1_4(unit, &scache_ptr));
   1840 #endif
   1841     }
   1842     if (soc_feature(unit, soc_feature_udf_selector_support)) {
   1843         BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_wb_sync_1_5(unit, &scache_ptr));
   1844     }
   1845     return BCM_E_NONE;
   1846 }
   1847 
   1848 
   1849 
   1850 /*
   1851  * Function:
   1852  *      bcmi_xgs4_udf_reinit
   1853  * Purpose:
   1854  *      Recovers UDF warmboot state from scache
   1855  * Parameters:
   1856  *      unit            - (IN)  Unit number.
   1857  * Returns:
   1858  *      BCM_E_XXX
   1859  * Notes:
   1860  */
   1861 STATIC int
   1862 bcmi_xgs4_udf_reinit(int unit)
   1863 {
   1864     int     rv = BCM_E_INTERNAL;
   1865     uint8   *scache_ptr;
   1866     uint16  recovered_ver = 0;
   1867     soc_scache_handle_t scache_handle;
   1868 
   1869     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_UDF, 0);
   1870 
   1871     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
   1872                                  0, &scache_ptr,
   1873                                  BCM_WB_DEFAULT_VERSION, &recovered_ver);
   1874 
   1875     if (BCM_E_NOT_FOUND == rv) {
   1876         /* Proceed with Level 1 Warm Boot */
   1877         rv = BCM_E_NONE;
   1878     }
   1879 
   1880     BCM_IF_ERROR_RETURN(rv);
   1881 
   1882     if (recovered_ver >= BCM_WB_VERSION_1_0) {
   1883         BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_wb_reinit_1_0(unit, &scache_ptr));
   1884     }
   1885 
   1886     if (recovered_ver >= BCM_WB_VERSION_1_1) {
   1887         BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_wb_reinit_1_1(unit, &scache_ptr));
   1888     }
   1889 
   1890 #if defined (BCM_TOMAHAWK_SUPPORT)
   1891     if (recovered_ver >= BCM_WB_VERSION_1_2) {
   1892         BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_wb_tcam_info_reinit_1_2_to_1_4(unit));
   1893     }
   1894 
   1895     if (recovered_ver >= BCM_WB_VERSION_1_3) {
   1896         BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_wb_reinit_1_3(unit, &scache_ptr));
   1897     }
   1898 
   1899     if (recovered_ver >= BCM_WB_VERSION_1_4) {
   1900         BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_wb_reinit_1_4(unit, &scache_ptr));
   1901     }
   1902 #endif
   1903 
   1904     if (soc_feature(unit, soc_feature_udf_selector_support)) {
   1905         if (recovered_ver >= BCM_WB_VERSION_1_5) {
   1906             BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_wb_reinit_1_5(unit, &scache_ptr));
   1907         }
   1908     }
   1909 
   1910     if (BCM_SUCCESS(rv) &&
   1911             (recovered_ver < BCM_WB_DEFAULT_VERSION)) {
   1912         /* This will handle the below cases
   1913           1. When warboot from release which didn't had UDF module in SCACHE or
   1914           2. The current release SCACHE size required is more than preivous version  or
   1915           3. Level 1 warmboot in this case memory will not be allocated. */
   1916         BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_wb_alloc(unit));
   1917     }
   1918 
   1919     return rv;
   1920 }
   1921 
   1922 #endif /* BCM_WARM_BOOT_SUPPORT */
   1923 
   1924 /*
   1925  * Function:
   1926  *      bcmi_xgs4_udf_offset_reserve
   1927  * Purpose:
   1928  *      Reserves requested offset chunks.
   1929  * Parameters:
   1930  *      unit            - (IN)  Unit number.
   1931  *      max_offsets     - (IN)  Number of offsets to reserve.
   1932  *      offset[]        - (IN)  Array of offset chunks requested.
   1933  *      pipe_num        - (IN)  Pipe Num where offset is reserved
   1934  * Returns:
   1935  *      BCM_E_XXX
   1936  * Notes:
   1937  *  offset[i]: 0x1 means only first half of the chunk is used.
   1938  *  offset[i]: 0x2 means only second half of the chunk is used.
   1939  *  offset[i]: 0x3 means both the chunks are used.
   1940  */
   1941 STATIC int
   1942 bcmi_xgs4_udf_offset_reserve(int unit, int max_offsets, int offset[], int pipe_num)
   1943 {
   1944     int j;
   1945     int first = 1;
   1946     int grp_id = 0;
   1947     int gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit);
   1948     bcmi_xgs4_udf_offset_entry_t *offset_entry;
   1949     bcmi_xgs4_udf_offset_entry_t *offset_entry_array;
   1950     SHR_BITDCL *chunk_bmap;
   1951     SHR_BITDCL *byte_bmap;
   1952 
   1953 #if defined (BCM_TOMAHAWK_SUPPORT)
   1954     if (soc_feature(unit, soc_feature_udf_multi_pipe_support) &&
   1955        (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) {
   1956 
   1957         offset_entry_array = UDF_CTRL(unit)->offset_entry_array_per_pipe[pipe_num];
   1958         chunk_bmap = &(UDF_CTRL(unit)->hw_bmap_per_pipe[pipe_num]);
   1959         byte_bmap = &(UDF_CTRL(unit)->byte_bmap_per_pipe[pipe_num]);
   1960     } else
   1961 #endif
   1962     {
   1963         offset_entry_array = UDF_CTRL(unit)->offset_entry_array;
   1964         chunk_bmap = &(UDF_CTRL(unit)->hw_bmap);
   1965         byte_bmap = &(UDF_CTRL(unit)->byte_bmap);
   1966     }
   1967 
   1968 
   1969     for (j = 0; j < max_offsets; j++) {
   1970         if (offset[j] == 0) {
   1971             continue;
   1972         }
   1973 
   1974         /* Return BCM_E_RESOURCE if the offset chunk is already in use */
   1975         if (SHR_BITGET(chunk_bmap, j)) {
   1976             return BCM_E_RESOURCE;
   1977         }
   1978 
   1979         offset_entry = &(offset_entry_array[j]);
   1980 
   1981 #if defined (BCM_TOMAHAWK_SUPPORT)
   1982         if (soc_feature(unit, soc_feature_udf_multi_pipe_support) &&
   1983             (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) {
   1984             offset_entry->associated_pipe = pipe_num;
   1985         }
   1986 #endif
   1987         offset_entry->num_udfs += 1;
   1988 
   1989         if (offset_entry_array[j].num_udfs == 1) {
   1990             /* Mark the entries as used */
   1991             SHR_BITSET(chunk_bmap, j);
   1992             *byte_bmap |= offset[j] << (j * gran);
   1993         }
   1994 
   1995         if (gran == UDF_OFFSET_GRAN2) {
   1996             /* Offset flag updated when gran is 2.
   1997              * offset[i] can be 1,2,3 only in case of gran2
   1998              */
   1999             if ((offset[j] == 0x1) || (offset[j] == 0x2)) {
   2000                 offset_entry_array[j].flags |=
   2001                     BCMI_XGS4_UDF_OFFSET_ENTRY_HALF;
   2002             }
   2003         }
   2004 
   2005         if (first == 1) {
   2006             offset_entry_array[j].flags |=
   2007                 BCMI_XGS4_UDF_OFFSET_ENTRY_GROUP;
   2008 
   2009             offset_entry_array[j].grp_id = j;
   2010 
   2011             first = 0;
   2012             grp_id = j;
   2013         } else {
   2014             offset_entry_array[j].flags |=
   2015                 BCMI_XGS4_UDF_OFFSET_ENTRY_MEMBER;
   2016             offset_entry_array[j].grp_id = grp_id;
   2017         }
   2018     }
   2019 
   2020     return BCM_E_NONE;
   2021 }
   2022 
   2023 /*
   2024  * Function:
   2025  *      _bcmi_xgs4_th3_qset_udf_offsets_alloc
   2026  * Purpose:
   2027  *      Allocates offset chunks based on the INPUT qset.
   2028  * Parameters:
   2029  *      unit          - (IN)  Unit number.
   2030  *      req_offsets   - (IN)  Number of chunks to be allocated.
   2031  *      offset_array  - (OUT) Offset chunks in the order of availability.
   2032  *      max_chunks    - (OUT) Number of chunks allocated
   2033  *      pipe_num      - (IN)  Pipe Number
   2034  *
   2035  * Returns:
   2036  *      BCM_E_XXX
   2037  * Notes:
   2038  */
   2039 int
   2040  _bcmi_xgs4_th3_qset_udf_offsets_alloc(int unit, int req_offsets,
   2041                                        int offset_array[], int *max_chunks,
   2042                                        int pipe_num)
   2043 {
   2044     int chunk = 0;
   2045     uint32 hw_bmap[1];
   2046     int num_chunks = 0;
   2047     uint8 use_udf1 = 0, use_udf2 = 0, use_udf12 = 0;
   2048     int pipe = 0;
   2049     int udf1_used_chunks = 0, udf2_used_chunks = 0;
   2050 
   2051 #if defined (BCM_TOMAHAWK_SUPPORT)
   2052     if (soc_feature(unit, soc_feature_udf_multi_pipe_support) &&
   2053        (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) {
   2054         hw_bmap[0] = UDF_CTRL(unit)->hw_bmap_per_pipe[pipe_num];
   2055         pipe = pipe_num;
   2056     } else
   2057 #endif
   2058     {
   2059         hw_bmap[0] = UDF_CTRL(unit)->hw_bmap;
   2060         pipe = 0;
   2061     }
   2062 
   2063     /* Count the number of used chunks in UDF 1 and 2 */
   2064     for (chunk = 0; chunk < (UDF_CTRL(unit)->max_chunks);
   2065          chunk++) {
   2066          if (SHR_BITGET(&(hw_bmap[0]), chunk)) {
   2067              if (chunk < (UDF_CTRL(unit)->max_chunks / 2)) {
   2068                  udf1_used_chunks++;
   2069              } else {
   2070                  udf2_used_chunks++;
   2071              }
   2072          }
   2073     }
   2074 
   2075     /* verify if resources are available in order of udf1 alone,
   2076        udf2 alone, followed by udf1 + udf2 together */
   2077 
   2078     if (((UDF_CTRL(unit)->max_chunks / 2 )
   2079          - udf1_used_chunks) >= req_offsets ) {
   2080         use_udf1 = 1;
   2081     } else if (((UDF_CTRL(unit)->max_chunks / 2 )
   2082         - udf2_used_chunks) >= req_offsets ) {
   2083         use_udf2 = 1;
   2084     } else if ((UDF_CTRL(unit)->max_chunks
   2085         - (udf1_used_chunks
   2086         + udf2_used_chunks)) >= req_offsets) {
   2087         use_udf12 = 1;
   2088     } else {
   2089         /* No resources available in all cases */
   2090         return (BCM_E_RESOURCE);
   2091     }
   2092 
   2093 
   2094     if (use_udf1) {     /* Use UDF1 */
   2095         chunk = 0;
   2096         while ((chunk < (UDF_CTRL(unit)->max_chunks / 2)) && (num_chunks < req_offsets)) {
   2097              if (((_BCMI_UDF_BMP_TEST(UDF_CTRL(unit)->udf_field_bmp[pipe], chunk)) == 0)
   2098                   && (SHR_BITGET(&(hw_bmap[0]), chunk) == 0)) {
   2099                   offset_array[num_chunks] = chunk;
   2100                   udf1_used_chunks++;
   2101                   num_chunks++;
   2102                   _BCMI_UDF_BMP_ADD(UDF_CTRL(unit)->udf_field_bmp[pipe], chunk);
   2103              }
   2104              chunk++;
   2105         }
   2106     } else if (use_udf2) {    /* Use UDF2 */
   2107         chunk = (UDF_CTRL(unit)->max_chunks / 2);
   2108 
   2109         while ((chunk < UDF_CTRL(unit)->max_chunks) && (num_chunks < req_offsets)) {
   2110              if (((_BCMI_UDF_BMP_TEST(UDF_CTRL(unit)->udf_field_bmp[pipe], chunk)) == 0)
   2111                   && (SHR_BITGET(&(hw_bmap[0]), chunk) == 0)) {
   2112                   offset_array[num_chunks] = chunk;
   2113                   udf2_used_chunks++;
   2114                   num_chunks++;
   2115                   _BCMI_UDF_BMP_ADD(UDF_CTRL(unit)->udf_field_bmp[pipe], chunk);
   2116              }
   2117              chunk++;
   2118         }
   2119     } else if (use_udf12) {    /* Use UDF1 and  UDF2 */
   2120         chunk = 0;
   2121         while ((chunk < UDF_CTRL(unit)->max_chunks) && (num_chunks < req_offsets)) {
   2122              if (((_BCMI_UDF_BMP_TEST(UDF_CTRL(unit)->udf_field_bmp[pipe], chunk)) == 0)
   2123                   && (SHR_BITGET(&(hw_bmap[0]), chunk) == 0)) {
   2124                   offset_array[num_chunks] = chunk;
   2125                   num_chunks++;
   2126                   if (chunk < (UDF_CTRL(unit)->max_chunks / 2)) {
   2127                       udf1_used_chunks++;
   2128                   } else {
   2129                       udf2_used_chunks++;
   2130                   }
   2131                   _BCMI_UDF_BMP_ADD(UDF_CTRL(unit)->udf_field_bmp[pipe], chunk);
   2132              }
   2133              chunk++;
   2134         }
   2135     }
   2136 
   2137     if (num_chunks < req_offsets) {
   2138         /* Mismatch in internal calculations */
   2139         return (BCM_E_INTERNAL);
   2140     }
   2141 
   2142 
   2143     *max_chunks = num_chunks;
   2144 
   2145     return BCM_E_NONE;
   2146 }
   2147 
   2148 int
   2149 _bcmi_xgs4_th3_qset_udf_offsets_free(int unit, int chunk, int pipe) {
   2150 
   2151     _BCMI_UDF_BMP_REMOVE(UDF_CTRL(unit)->udf_field_bmp[pipe], chunk);
   2152     return BCM_E_NONE;
   2153 
   2154 }
   2155 
   2156 
   2157 /*
   2158  * Function:
   2159  *      bcmi_xgs4_udf_offset_unreserve
   2160  * Purpose:
   2161  *      UnReserves offset chunks.
   2162  * Parameters:
   2163  *      unit            - (IN)  Unit number.
   2164  *      max_offsets     - (IN)  Number of offsets to unreserve.
   2165  *      offset[]        - (IN)  Array of offset chunks to be unreserved.
   2166  *      pipe_num        - (IN)  Pipe Num where offset is unreserved
   2167  * Returns:
   2168  *      BCM_E_XXX
   2169  * Notes:
   2170  */
   2171 STATIC int
   2172 bcmi_xgs4_udf_offset_unreserve(int unit, int max_offsets, int offset[], int pipe_num)
   2173 {
   2174     int j;
   2175     int gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit);
   2176     bcmi_xgs4_udf_offset_entry_t *offset_entry;
   2177     bcmi_xgs4_udf_offset_entry_t *offset_entry_array;
   2178     SHR_BITDCL *chunk_bmap;
   2179     SHR_BITDCL *byte_bmap;
   2180 
   2181 #if defined (BCM_TOMAHAWK_SUPPORT)
   2182     if (soc_feature(unit, soc_feature_udf_multi_pipe_support) &&
   2183        (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) {
   2184 
   2185         offset_entry_array = UDF_CTRL(unit)->offset_entry_array_per_pipe[pipe_num];
   2186         chunk_bmap = &(UDF_CTRL(unit)->hw_bmap_per_pipe[pipe_num]);
   2187         byte_bmap = &(UDF_CTRL(unit)->byte_bmap_per_pipe[pipe_num]);
   2188     } else
   2189 #endif
   2190     {
   2191         offset_entry_array = UDF_CTRL(unit)->offset_entry_array;
   2192         chunk_bmap = &(UDF_CTRL(unit)->hw_bmap);
   2193         byte_bmap = &(UDF_CTRL(unit)->byte_bmap);
   2194     }
   2195 
   2196     for (j = 0; j < max_offsets; j++) {
   2197         if (offset[j] == 0) {
   2198             continue;
   2199         }
   2200 
   2201         offset_entry = &(offset_entry_array[j]);
   2202 
   2203         /* Decr ref_cnt on the offset entry */
   2204         offset_entry->num_udfs -= 1;
   2205 
   2206         if (offset_entry->num_udfs == 0) {
   2207             /* Defensive Check: num_pkt_formats must be 0 */
   2208             if (offset_entry->num_pkt_formats != 0) {
   2209                 return BCM_E_INTERNAL;
   2210             }
   2211 
   2212             /* Mark the entries as free */
   2213             SHR_BITCLR(chunk_bmap, j);
   2214             *byte_bmap &= ~(offset[j] << (j * gran));
   2215 
   2216             if (soc_feature(unit, soc_feature_udf_selector_support)) {
   2217                 /* Free the chunk in field module */
   2218                 BCM_IF_ERROR_RETURN(_bcmi_xgs4_th3_qset_udf_offsets_free(unit, j, pipe_num));
   2219             }
   2220 
   2221             /* Clear the UDF Offset entry */
   2222             offset_entry->flags = 0x0;
   2223             offset_entry->grp_id = 0x0;
   2224         }
   2225     }
   2226 
   2227     return BCM_E_NONE;
   2228 }
   2229 
   2230 /*
   2231  * Function:
   2232  *      bcmi_xgs4_udf_offset_hw_alloc
   2233  * Purpose:
   2234  *      Allocates offsets for the UDF
   2235  * Parameters:
   2236  *      unit            - (IN)      Unit number.
   2237  *      hints           - (IN)      Hints for allocation of offset chunks.
   2238  *      offset_info     - (INOUT)   UDF Offset info struct
   2239  * Returns:
   2240  *      BCM_E_XXX
   2241  * Notes:
   2242  */
   2243 STATIC int
   2244 bcmi_xgs4_udf_offset_hw_alloc(int unit, bcm_udf_alloc_hints_t *hints,
   2245                               bcmi_xgs4_udf_offset_info_t *offset_info)
   2246 {
   2247     int rv;
   2248     int i, j;
   2249     int gran;
   2250     int grp_id = -1;
   2251     int max_chunks;
   2252     uint32 hw_bmap[1];
   2253     uint32 alloc_bmap = 0;
   2254     uint32 byte_bmap  = 0;
   2255     int *offset_order;
   2256     int offset_array[MAX_UDF_OFFSET_CHUNKS] = {0};
   2257     int offset_order_d[MAX_UDF_OFFSET_CHUNKS] = {0};
   2258     int alloc_cnt = 0, max_offsets = 0, req_offsets = 0;
   2259     uint8 byte_offset = 0;
   2260     int widthcovergbl = 0, widthcoverint = 0;
   2261 
   2262     /* offset allocation order */
   2263     int bcmi_xgs4_udf_offsets_gran2_default[]  = {2, 3, 6, 7, 0, 1, 4, 5,
   2264                                                   8, 9, 10, 11, 12, 13, 14, 15};
   2265     int bcmi_xgs4_udf_offsets_gran4_default[]  = {1, 3, 0, 2, 4, 5, 6, 7};
   2266     int bcmi_xgs4_udf_offsets_flexhash[] = {12, 13, 14, 15};
   2267     int bcmi_xgs4_udf_offsets_udfhash[]  = {6, 7};
   2268     int bcmi_xgs4_udf_offsets_policer[]  = {0, 1};
   2269     int bcmi_xgs4_udf_offsets_range_checker[] = {5};    /*UDF1 chunk 2: bits (47 - 32 of UDF1)*/
   2270     int bcmi_xgs4_udf_offsets_flex_counter[]  = {0, 1};
   2271 
   2272     gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit);
   2273     max_chunks = BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit);
   2274 
   2275     /*
   2276      * The 'start' and 'width' need not always align to the offset granularity.
   2277      * Every offset can extract 2 bytes or 4 bytes.
   2278      * Also on devices with gran 4 if layer is L2 Header then offset
   2279      * need to be adjusted with negative offset of 2.
   2280      * This negative offset of 2 for L2 Header start is done because first
   2281      * chunk will pick up B0,B1,B126,B127 bytes of frame.
   2282      * If the user request a UDF that starts/ends on an odd-byte boundary,
   2283      * SDK should allocate extra chunk(s) to facilitate for the requested
   2284      * byte extraction and account for this extra byte in the field APIs
   2285      * (by masking "don'tcare" for those extra bytes.
   2286      */
   2287     if (gran == UDF_OFFSET_GRAN2) {
   2288         byte_offset = offset_info->start % gran;
   2289     } else {
   2290         if (offset_info->layer == bcmUdfLayerL2Header) {
   2291             byte_offset = (offset_info->start + 2) % gran;
   2292         } else {
   2293             byte_offset = offset_info->start % gran;
   2294         }
   2295     }
   2296 
   2297     offset_info->byte_offset = byte_offset;
   2298     req_offsets = (offset_info->width + byte_offset + gran -1) / gran;
   2299 
   2300     /*
   2301      * FLEXHASH and IFP/VFP flags can be set at the same time
   2302      * Since FLEXHASH has limited chunks, it is preferred during allocation
   2303      */
   2304 
   2305     if ((hints != NULL) && (hints->flags & BCM_UDF_CREATE_O_FLEXHASH)) {
   2306         max_offsets = COUNTOF(bcmi_xgs4_udf_offsets_flexhash);
   2307         offset_order = &bcmi_xgs4_udf_offsets_flexhash[0];
   2308 
   2309     } else if ((hints != NULL) && (hints->flags & BCM_UDF_CREATE_O_UDFHASH)) {
   2310         max_offsets = COUNTOF(bcmi_xgs4_udf_offsets_udfhash);
   2311         offset_order = &bcmi_xgs4_udf_offsets_udfhash[0];
   2312 
   2313     } else if ((hints != NULL) &&
   2314             (hints->flags & BCM_UDF_CREATE_O_RANGE_CHECK)) {
   2315         max_offsets = COUNTOF(bcmi_xgs4_udf_offsets_range_checker);
   2316         offset_order = &bcmi_xgs4_udf_offsets_range_checker[0];
   2317 
   2318     } else if ((hints != NULL) &&
   2319                ((hints->flags & BCM_UDF_CREATE_O_FIELD_INGRESS) ||
   2320                 (hints->flags & BCM_UDF_CREATE_O_FIELD_LOOKUP))) {
   2321 
   2322         _field_stage_id_t stage;
   2323 
   2324         if (hints->flags & BCM_UDF_CREATE_O_FIELD_INGRESS) {
   2325             stage  = _BCM_FIELD_STAGE_INGRESS;
   2326         } else {
   2327             stage  = _BCM_FIELD_STAGE_LOOKUP;
   2328         }
   2329 
   2330         /* allocate based on qset */
   2331         if (soc_feature(unit, soc_feature_udf_selector_support)) {
   2332             rv = _bcmi_xgs4_th3_qset_udf_offsets_alloc(unit,
   2333                          req_offsets, &offset_order_d[0], &max_offsets,
   2334                          offset_info->associated_pipe);
   2335             BCM_IF_ERROR_RETURN(rv);
   2336         } else {
   2337             rv = _bcm_esw_field_qset_udf_offsets_alloc(unit, stage, hints->qset,
   2338                          req_offsets, &offset_order_d[0], &max_offsets,
   2339                          offset_info->associated_pipe);
   2340             BCM_IF_ERROR_RETURN(rv);
   2341         }
   2342 
   2343 
   2344         offset_order = &offset_order_d[0];
   2345     } else if ((hints != NULL) &&
   2346                 (hints->flags & BCM_UDF_CREATE_O_POLICER_GROUP)) {
   2347         max_offsets = COUNTOF(bcmi_xgs4_udf_offsets_policer);
   2348         offset_order = &bcmi_xgs4_udf_offsets_policer[0];
   2349 
   2350     } else if ((hints != NULL) &&
   2351                (hints->flags & BCM_UDF_CREATE_O_FLEX_COUNTER)) {
   2352         max_offsets = COUNTOF(bcmi_xgs4_udf_offsets_flex_counter);
   2353         offset_order = &bcmi_xgs4_udf_offsets_flex_counter[0];
   2354 
   2355     }  else {
   2356         if (gran == UDF_OFFSET_GRAN2) {
   2357             max_offsets = COUNTOF(bcmi_xgs4_udf_offsets_gran2_default);
   2358             offset_order = &bcmi_xgs4_udf_offsets_gran2_default[0];
   2359         } else {
   2360             max_offsets = COUNTOF(bcmi_xgs4_udf_offsets_gran4_default);
   2361             offset_order = &bcmi_xgs4_udf_offsets_gran4_default[0];
   2362         }
   2363     }
   2364 
   2365     /* max_chunks cannot be greater than 8 for chipsets with gran 4
   2366      * and greater than 16 for chipsets with gran 2
   2367      */
   2368 #if defined (BCM_TOMAHAWK_SUPPORT)
   2369     if (soc_feature(unit, soc_feature_udf_multi_pipe_support) &&
   2370        (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) {
   2371         hw_bmap[0] = UDF_CTRL(unit)->hw_bmap_per_pipe[offset_info->associated_pipe];
   2372     } else
   2373 #endif
   2374     {
   2375         hw_bmap[0] = UDF_CTRL(unit)->hw_bmap;
   2376     }
   2377 
   2378     /* All chunks are reserved */
   2379     if ((hw_bmap[0] & 0xffff) == 0xffff) {
   2380         return BCM_E_RESOURCE;
   2381     }
   2382 
   2383     for (j = 0; j < max_offsets; j++) {
   2384         if ((SHR_BITGET(&(hw_bmap[0]), offset_order[j]))) {
   2385             offset_array[offset_order[j]] = 0;
   2386             continue;
   2387         }
   2388 
   2389         /* Mark the first offset entry as the grp_id */
   2390         if (grp_id == -1) {
   2391             grp_id = offset_order[j];
   2392         } else if (grp_id > offset_order[j]) {
   2393             grp_id = offset_order[j];
   2394         }
   2395 
   2396         /* offset_order will have order of chunks to be allocated.
   2397          * offset_array should be filled with 0x1, 0x2 or 0x3 if
   2398          * first half, or second half or full chunk is alloc'ed respy.
   2399          */
   2400         alloc_bmap |= (1 << offset_order[j]);
   2401         if (alloc_cnt == 0) {
   2402             /* First Chunk to be allocated */
   2403             for(i = 0;i< (gran - byte_offset); i++) {
   2404                 if (widthcovergbl < offset_info->width) {
   2405                     byte_bmap |= (0x1 << (((offset_order[j]+1) * gran) - byte_offset -i -1));
   2406                     offset_array[offset_order[j]] |= (0x1 << (gran - byte_offset -i -1));
   2407                     widthcovergbl++;
   2408                 }
   2409             }
   2410         } else {
   2411             /* Rest all chunk to be allocated */
   2412             widthcoverint = 0;
   2413             for(i = 0;(i <(offset_info->width - widthcovergbl) && (i < gran)); i++){
   2414                 byte_bmap |= (0x1 << (((offset_order[j]+1) * gran) -i -1));
   2415                 offset_array[offset_order[j]] |= (0x1 << (gran -i -1));
   2416                 widthcoverint++;
   2417             }
   2418             widthcovergbl += widthcoverint;
   2419         }
   2420 
   2421         if (++alloc_cnt == req_offsets) {
   2422             break;
   2423         }
   2424     }
   2425 
   2426     if (alloc_cnt < req_offsets) {
   2427         return BCM_E_RESOURCE;
   2428     }
   2429 
   2430     rv = bcmi_xgs4_udf_offset_reserve(unit, max_chunks, offset_array,
   2431                                       offset_info->associated_pipe);
   2432     BCM_IF_ERROR_RETURN(rv);
   2433 
   2434     /* grp_id is the first chunk number */
   2435     offset_info->grp_id = grp_id;
   2436 
   2437     offset_info->hw_bmap |= alloc_bmap;
   2438     offset_info->byte_bmap |= byte_bmap;
   2439 
   2440     return BCM_E_NONE;
   2441 }
   2442 
   2443 
   2444 /*
   2445  * Function:
   2446  *      bcmi_xgs4_udf_layer_to_offset_base
   2447  * Purpose:
   2448  *      Fetches base and offsets values to configure in UDF_OFFSET table.
   2449  * Parameters:
   2450  *      unit            - (IN)      Unit number.
   2451  *      offset_info     - (IN)      UDF Offset info struct
   2452  *      tcam_info       - (IN)      UDF tcam info struct
   2453  *      base            - (OUT)     base_offset to be configured in BASE_OFFSETx
   2454  *      baseoffset      - (OUT)     base offset to be configured in OFFSETx field
   2455  * Returns:
   2456  *      BCM_E_XXX
   2457  * Notes:
   2458  *  Users can implement bcmUdfLayerUserPayload according to the requirement.
   2459  */
   2460 STATIC int
   2461 bcmi_xgs4_udf_layer_to_offset_base(int unit,
   2462                                    bcmi_xgs4_udf_offset_info_t *offset_info,
   2463                                    bcmi_xgs4_udf_tcam_info_t *tcam_info,
   2464                                    int *base, int *baseoffset)
   2465 {
   2466     int gran;
   2467 
   2468     /* get udf gran from udf control */
   2469     gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit);
   2470 
   2471     /* base offset */
   2472     switch (offset_info->layer) {
   2473         case bcmUdfLayerL2Header:
   2474             *base = BCMI_XGS4_UDF_OFFSET_BASE_START_OF_L2;
   2475             break;
   2476         case bcmUdfLayerL3OuterHeader:
   2477         case bcmUdfLayerTunnelHeader:
   2478             *base = BCMI_XGS4_UDF_OFFSET_BASE_START_OF_OUTER_L3;
   2479             break;
   2480         case bcmUdfLayerL3InnerHeader:
   2481         case bcmUdfLayerL4OuterHeader:
   2482             *base = BCMI_XGS4_UDF_OFFSET_BASE_START_OF_INNER_L3;
   2483             break;
   2484         case bcmUdfLayerL4InnerHeader:
   2485         case bcmUdfLayerTunnelPayload:
   2486             *base = BCMI_XGS4_UDF_OFFSET_BASE_START_OF_L4;
   2487             break;
   2488         case bcmUdfLayerHigigHeader:
   2489         case bcmUdfLayerHigig2Header:
   2490             *base = BCMI_XGS4_UDF_OFFSET_BASE_START_OF_MH;
   2491             break;
   2492         default:
   2493             /* Unknown layer type: Return Error */
   2494             return BCM_E_PARAM;
   2495     }
   2496 
   2497     /* Base offset value */
   2498     if (gran == UDF_OFFSET_GRAN2) {
   2499         *baseoffset = ((offset_info->start % UDF_PACKET_PARSE_LENGTH)
   2500                         / gran);
   2501     } else {
   2502         if ((offset_info->layer == bcmUdfLayerL2Header) ||
   2503                 (offset_info->layer == bcmUdfLayerHigigHeader) ||
   2504                 (offset_info->layer == bcmUdfLayerHigig2Header)) {
   2505             *baseoffset = (((offset_info->start + 2) % UDF_PACKET_PARSE_LENGTH)
   2506                             / gran);
   2507         } else {
   2508             *baseoffset = ((offset_info->start % UDF_PACKET_PARSE_LENGTH)
   2509                             / gran);
   2510         }
   2511     }
   2512 
   2513     return BCM_E_NONE;
   2514 }
   2515 
   2516 /*
   2517  * Function:
   2518  *      bcmi_xgs4_udf_get
   2519  * Purpose:
   2520  *      To fetch the udf info given the UDF ID.
   2521  * Parameters:
   2522  *      unit            - (IN)      Unit number.
   2523  *      udf_id          - (IN)      UDF Id.
   2524  *      udf_info        - (OUT)     UDF info struct
   2525  * Returns:
   2526  *      BCM_E_XXX
   2527  * Notes:
   2528  */
   2529 int
   2530 bcmi_xgs4_udf_get(int unit, bcm_udf_id_t udf_id, bcm_udf_t *udf_info)
   2531 {
   2532     int rv;
   2533     bcmi_xgs4_udf_offset_info_t *offset_info = NULL;
   2534 
   2535     /* UDF Module Init check */
   2536     UDF_INIT_CHECK(unit);
   2537 
   2538     BCM_IF_NULL_RETURN_PARAM(udf_info);
   2539 
   2540     /* UDF Module Lock */
   2541     UDF_LOCK(unit);
   2542 
   2543     rv = bcmi_xgs4_udf_offset_node_get(unit, udf_id, &offset_info);
   2544     if (BCM_FAILURE(rv)) {
   2545         UDF_UNLOCK(unit);
   2546         return rv;
   2547     }
   2548 
   2549     /* Copy tmp to offset_info */
   2550     udf_info->start = BYTES2BITS(offset_info->start);
   2551     udf_info->width = BYTES2BITS(offset_info->width);
   2552     udf_info->layer = offset_info->layer;
   2553 #if defined (BCM_TOMAHAWK_SUPPORT)
   2554     if (soc_feature(unit, soc_feature_udf_multi_pipe_support)) {
   2555         SOC_PBMP_ASSIGN(udf_info->ports, offset_info->associated_ports);
   2556     }
   2557 #endif
   2558     /* Not used for XGS4 */
   2559     udf_info->flags = 0;
   2560 
   2561     /* Release UDF mutex */
   2562     UDF_UNLOCK(unit);
   2563 
   2564     return BCM_E_NONE;
   2565 }
   2566 
   2567 
   2568 /*
   2569  * Function:
   2570  *      bcmi_xgs4_udf_get_all
   2571  * Purpose:
   2572  *      To fetch all the udfs in the system.
   2573  * Parameters:
   2574  *      unit            - (IN)      Unit number.
   2575  *      max             - (IN)      Number of udf ids to fetch.
   2576  *      udf_id_list     - (OUT)     List of UDF Ids fetched.
   2577  *      actual          - (OUT)     Actual udfs fetched.
   2578  * Returns:
   2579  *      BCM_E_XXX
   2580  * Notes:
   2581  */
   2582 int
   2583 bcmi_xgs4_udf_get_all(int unit, int max, bcm_udf_id_t *udf_list, int *actual)
   2584 {
   2585     bcmi_xgs4_udf_offset_info_t *tmp;
   2586 
   2587     /* UDF Module Init check */
   2588     UDF_INIT_CHECK(unit);
   2589 
   2590     BCM_IF_NULL_RETURN_PARAM(actual);
   2591 
   2592     /* UDF Module Lock */
   2593     UDF_LOCK(unit);
   2594 
   2595     *actual = 0;
   2596     tmp = UDF_CTRL(unit)->offset_info_head;
   2597 
   2598     while (tmp != NULL) {
   2599         if ((udf_list != NULL) && (*actual < max)) {
   2600             udf_list[(*actual)] = tmp->udf_id;
   2601         }
   2602 
   2603         (*actual) += 1;
   2604         tmp = tmp->next;
   2605     }
   2606 
   2607     /* Release UDF mutex */
   2608     UDF_UNLOCK(unit);
   2609 
   2610     return BCM_E_NONE;
   2611 }
   2612 
   2613 /*
   2614  * Function:
   2615  *      bcmi_xgs4_udf_get_all
   2616  * Purpose:
   2617  *      To destroy udf object.
   2618  * Parameters:
   2619  *      unit            - (IN)      Unit number.
   2620  *      udf_id          - (IN)      UDF ID to be destroyed.
   2621  * Returns:
   2622  *      BCM_E_XXX
   2623  * Notes:
   2624  */
   2625 int
   2626 bcmi_xgs4_udf_destroy(int unit, bcm_udf_id_t udf_id)
   2627 {
   2628     int rv;
   2629     int i;
   2630     int max, gran;
   2631     uint32 offset[MAX_UDF_OFFSET_CHUNKS] = {0};
   2632     bcmi_xgs4_udf_offset_info_t *cur = NULL;
   2633 
   2634     /* UDF Module Init check */
   2635     UDF_INIT_CHECK(unit);
   2636 
   2637     /* UDF Module Lock */
   2638     UDF_LOCK(unit);
   2639 
   2640     if (UDF_CTRL(unit)->udf_used_by_module == UDF_USED_BY_FIELD_MODULE) {
   2641         LOG_CLI((BSL_META("Udf resource is used by FIELD module. \n")));
   2642         UDF_UNLOCK(unit);
   2643         return BCM_E_RESOURCE;
   2644     }
   2645 
   2646     gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit);
   2647     max = BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit);;
   2648 
   2649     rv = bcmi_xgs4_udf_offset_node_get(unit, udf_id, &cur);
   2650     if (BCM_FAILURE(rv)) {
   2651         UDF_UNLOCK(unit);
   2652         return rv;
   2653     }
   2654 
   2655     /* Matching node not found */
   2656     if (cur == NULL) {
   2657         UDF_UNLOCK(unit);
   2658         return BCM_E_NOT_FOUND;
   2659     }
   2660 
   2661     if (cur->num_pkt_formats >= 1) {
   2662         UDF_UNLOCK(unit);
   2663         return BCM_E_BUSY;
   2664     }
   2665 
   2666     for (i = 0; i < max; i++) {
   2667         SHR_BITCOPY_RANGE(&offset[i], 0, &(cur->byte_bmap), i*gran, gran);
   2668     }
   2669 
   2670     /* unreserve the offset chunks */
   2671     rv = bcmi_xgs4_udf_offset_unreserve(unit, max, (int *)offset,
   2672                                         cur->associated_pipe);
   2673     if (BCM_FAILURE(rv)) {
   2674         UDF_UNLOCK(unit);
   2675         return rv;
   2676     }
   2677 
   2678     /* Free the cur node */
   2679     UDF_UNLINK_OFFSET_NODE(cur);
   2680     sal_free(cur);
   2681 
   2682     UDF_CTRL(unit)->num_udfs -= 1;
   2683 
   2684     if (NULL == UDF_CTRL(unit)->offset_info_head) {
   2685         UDF_CTRL(unit)->udf_used_by_module = UDF_USED_BY_NONE;
   2686     }
   2687 
   2688     /* Release UDF mutex */
   2689     UDF_UNLOCK(unit);
   2690 
   2691     return BCM_E_NONE;
   2692 }
   2693 
   2694 
   2695 /*
   2696  * Function:
   2697  *      bcmi_xgs4_udf_offset_info_alloc
   2698  * Purpose:
   2699  *      To allocate memory for UDF offset info struct
   2700  * Parameters:
   2701  *      unit            - (IN)      Unit number.
   2702  *      offset_info     - (OUT)     Pointer to hold the allocated memory.
   2703  * Returns:
   2704  *      BCM_E_XXX
   2705  * Notes:
   2706  */
   2707 STATIC int
   2708 bcmi_xgs4_udf_offset_info_alloc(int unit,
   2709                                 bcmi_xgs4_udf_offset_info_t **offset_info)
   2710 {
   2711     int mem_sz;
   2712 
   2713     mem_sz = sizeof(bcmi_xgs4_udf_offset_info_t);
   2714 
   2715     /* Allocate memory for bcmi_xgs4_udf_offset_info_t structure. */
   2716     UDF_MALLOC((*offset_info), bcmi_xgs4_udf_offset_info_t,
   2717                 mem_sz, "udf offset info");
   2718 
   2719     if (NULL == *offset_info) {
   2720         return (BCM_E_MEMORY);
   2721     }
   2722 
   2723 
   2724     return BCM_E_NONE;
   2725 }
   2726 
   2727 
   2728 /*
   2729  * Function:
   2730  *      bcmi_xgs4_udf_offset_info_add
   2731  * Purpose:
   2732  *      To convert the UDF info to offset info and add to the linked list.
   2733  * Parameters:
   2734  *      unit            - (IN)      Unit number.
   2735  *      udf_info        - (IN)      UDF info to be added to linked list.
   2736  *      offset_info     - (INOUT)   Pointer to hold the allocated memory.
   2737  * Returns:
   2738  *      BCM_E_XXX
   2739  * Notes:
   2740  */
   2741 STATIC int
   2742 bcmi_xgs4_udf_offset_info_add(int unit, bcm_udf_t *udf_info,
   2743                               bcmi_xgs4_udf_offset_info_t **offset_info)
   2744 {
   2745     int rv;
   2746 #if defined (BCM_TOMAHAWK_SUPPORT)
   2747     int port;
   2748     soc_info_t  *si;
   2749     si = &SOC_INFO(unit);
   2750 #endif
   2751 
   2752     /* Allocate memory for bcmi_xgs4_udf_offset_info_t structure. */
   2753     rv = bcmi_xgs4_udf_offset_info_alloc(unit, offset_info);
   2754     BCM_IF_ERROR_RETURN(rv);
   2755 
   2756     /* Save user inputs into the offset_info struct */
   2757     (*offset_info)->layer = udf_info->layer;
   2758     (*offset_info)->start = BITS2BYTES(udf_info->start);
   2759     (*offset_info)->width = BITS2BYTES(udf_info->width);
   2760 
   2761 #if defined (BCM_TOMAHAWK_SUPPORT)
   2762     if (soc_feature(unit, soc_feature_udf_multi_pipe_support) &&
   2763        (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) {
   2764 
   2765         /* save pbmp ports in order to return in get function */
   2766         SOC_PBMP_ASSIGN((*offset_info)->associated_ports, udf_info->ports);
   2767 
   2768         /* get the pipe where the entry will be configured */
   2769         SOC_PBMP_ITER(udf_info->ports, port) {
   2770             (*offset_info)->associated_pipe = si->port_pipe[port];
   2771             break;
   2772         }
   2773     }
   2774 #endif
   2775 
   2776     /* Add offset_info item to the linked list */
   2777     rv = bcmi_xgs4_udf_offset_node_add(unit, *offset_info);
   2778     if (BCM_FAILURE(rv)) {
   2779         sal_free(*offset_info);
   2780         *offset_info = NULL;
   2781     }
   2782 
   2783     return rv;
   2784 }
   2785 
   2786 /* Linked list node add: for offset nodes */
   2787 STATIC int
   2788 bcmi_xgs4_udf_offset_node_add(int unit, bcmi_xgs4_udf_offset_info_t *new)
   2789 {
   2790     bcmi_xgs4_udf_offset_info_t *tmp;
   2791 
   2792     if (new == NULL) {
   2793         return BCM_E_INTERNAL;
   2794     }
   2795 
   2796     tmp = (UDF_CTRL(unit)->offset_info_head);
   2797 
   2798     if (NULL == tmp) {
   2799         /* Adding first node */
   2800         (UDF_CTRL(unit)->offset_info_head) = new;
   2801         new->prev = NULL;
   2802 
   2803     } else {
   2804 
   2805         /* traverse to the end of the list */
   2806         while (tmp->next != NULL) {
   2807             tmp = tmp->next;
   2808         }
   2809 
   2810         /* insert new node to the end of the list */
   2811         new->prev = tmp;
   2812         tmp->next = new;
   2813 
   2814     }
   2815 
   2816     new->next = NULL;
   2817 
   2818     return  BCM_E_NONE;
   2819 }
   2820 
   2821 /* Linked list node delete: for offset nodes */
   2822 STATIC int
   2823 bcmi_xgs4_udf_offset_node_delete(int unit, bcm_udf_id_t udf_id,
   2824                                  bcmi_xgs4_udf_offset_info_t **del)
   2825 {
   2826     int rv;
   2827     bcmi_xgs4_udf_offset_info_t *cur = NULL;
   2828 
   2829     rv = bcmi_xgs4_udf_offset_node_get(unit, udf_id, &cur);
   2830     BCM_IF_ERROR_RETURN(rv);
   2831 
   2832     /* Matching node not found */
   2833     if (cur == NULL) {
   2834         return BCM_E_NOT_FOUND;
   2835     }
   2836 
   2837     /* unlink cur from the list */
   2838     if (cur->prev) {
   2839         (cur->prev)->next = cur->next;
   2840     } else {
   2841         /* cur node is the head */
   2842         UDF_CTRL(unit)->offset_info_head = cur->next;
   2843     }
   2844 
   2845     if (cur->next) {
   2846         (cur->next)->prev = cur->prev;
   2847     }
   2848 
   2849     /* Callee function to free the node */
   2850     *del = cur;
   2851 
   2852     return BCM_E_NONE;
   2853 }
   2854 
   2855 /*
   2856  * Function:
   2857  *      bcmi_xgs4_udf_tcam_info_alloc
   2858  * Purpose:
   2859  *      To allocate memory for UDF tcam info struct
   2860  * Parameters:
   2861  *      unit            - (IN)      Unit number.
   2862  *      tcam_info       - (OUT)     Pointer to hold the allocated memory.
   2863  * Returns:
   2864  *      BCM_E_XXX
   2865  * Notes:
   2866  */
   2867 STATIC int
   2868 bcmi_xgs4_udf_tcam_info_alloc(int unit, bcmi_xgs4_udf_tcam_info_t **tcam_info)
   2869 {
   2870     int mem_sz;
   2871 
   2872     mem_sz = sizeof(bcmi_xgs4_udf_tcam_info_t);
   2873 
   2874     /* Allocate memory for bcmi_xgs4_udf_offset_info_t structure. */
   2875     UDF_MALLOC((*tcam_info), bcmi_xgs4_udf_tcam_info_t,
   2876                 mem_sz, "udf tcam info");
   2877 
   2878     if (NULL == *tcam_info) {
   2879         return (BCM_E_MEMORY);
   2880     }
   2881 
   2882     /* Mark entry invalid */
   2883     (*tcam_info)->hw_idx = MAX_UDF_TCAM_ENTRIES;
   2884 
   2885 #if defined (BCM_TOMAHAWK_SUPPORT)
   2886     if (soc_feature(unit, soc_feature_udf_multi_pipe_support)) {
   2887         int i;
   2888         /* Mark pipe num invalid */
   2889         (*tcam_info)->associated_pipe = BCMI_XGS4_UDF_INVALID_PIPE_NUM;
   2890 
   2891         for (i = 0; i < SOC_MAX_NUM_PIPES; i++) {
   2892             (*tcam_info)->hw_idx_per_pipe[i] = MAX_UDF_TCAM_ENTRIES;
   2893             (*tcam_info)->associated_pipes[i] = BCMI_XGS4_UDF_INVALID_PIPE_NUM;
   2894         }
   2895     }
   2896 #endif
   2897     return BCM_E_NONE;
   2898 }
   2899 
   2900 
   2901 /*
   2902  * Function:
   2903  *      bcmi_xgs4_udf_tcam_info_add
   2904  * Purpose:
   2905  *      To convert the packet format info to tcam info and add to the list.
   2906  * Parameters:
   2907  *      unit            - (IN)      Unit number.
   2908  *      pkt_format      - (IN)      UDF Packet format to be added to list.
   2909  *      tcam_info       - (INOUT)   Pointer to hold the allocated memory.
   2910  * Returns:
   2911  *      BCM_E_XXX
   2912  * Notes:
   2913  */
   2914 STATIC int
   2915 bcmi_xgs4_udf_tcam_info_add(int unit,
   2916                             bcm_udf_pkt_format_info_t *pkt_format,
   2917                             bcmi_xgs4_udf_tcam_info_t **tcam_info)
   2918 {
   2919     int rv;
   2920     fp_udf_tcam_entry_t *tcam_buf;
   2921 
   2922     /* Allocate memory for bcmi_xgs4_udf_tcam_info_t structure. */
   2923     rv = bcmi_xgs4_udf_tcam_info_alloc(unit, tcam_info);
   2924     BCM_IF_ERROR_RETURN(rv);
   2925 
   2926     tcam_buf = (fp_udf_tcam_entry_t *)&((*tcam_info)->hw_buf);
   2927     sal_memset(tcam_buf, 0, sizeof(fp_udf_tcam_entry_t));
   2928 
   2929     /* Initialize packet format entry */
   2930     rv = bcmi_xgs4_udf_pkt_format_tcam_key_init(unit, pkt_format,
   2931                                            (uint32 *)tcam_buf);
   2932     if (BCM_FAILURE(rv)) {
   2933         sal_free(*tcam_info);
   2934         (*tcam_info) = NULL;
   2935         return rv;
   2936     }
   2937 
   2938     (*tcam_info)->priority = pkt_format->prio;
   2939 #if defined (BCM_TOMAHAWK_SUPPORT)
   2940     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_PKT_FORMAT_CLASS_ID) {
   2941         (*tcam_info)->class_id = pkt_format->class_id;
   2942     }
   2943 #endif
   2944     /* Add offset_info item to the linked list */
   2945     rv = bcmi_xgs4_udf_tcam_node_add(unit, *tcam_info);
   2946     if (BCM_FAILURE(rv)) {
   2947         sal_free(*tcam_info);
   2948         (*tcam_info) = NULL;
   2949     }
   2950 
   2951     return rv;
   2952 }
   2953 
   2954 /* Linked list node add: for tcam nodes */
   2955 STATIC int
   2956 bcmi_xgs4_udf_tcam_node_add(int unit, bcmi_xgs4_udf_tcam_info_t *new)
   2957 {
   2958     bcmi_xgs4_udf_tcam_info_t *tmp;
   2959 
   2960     if (new == NULL) {
   2961         return BCM_E_INTERNAL;
   2962     }
   2963 
   2964     tmp = (UDF_CTRL(unit)->tcam_info_head);
   2965 
   2966     if (NULL == tmp) {
   2967         /* Adding first node */
   2968         (UDF_CTRL(unit)->tcam_info_head) = new;
   2969         new->prev = NULL;
   2970 
   2971     } else {
   2972 
   2973         /* traverse to the end of the list */
   2974         while (tmp->next != NULL) {
   2975             tmp = tmp->next;
   2976         }
   2977 
   2978         /* insert new node to the end of the list */
   2979         new->prev = tmp;
   2980         tmp->next = new;
   2981 
   2982     }
   2983     new->next = NULL;
   2984 
   2985     return  BCM_E_NONE;
   2986 }
   2987 
   2988 /* Linked list node delete: for tcam nodes */
   2989 STATIC int
   2990 bcmi_xgs4_udf_tcam_node_delete(int unit, bcm_udf_pkt_format_id_t pkt_format_id,
   2991                                bcmi_xgs4_udf_tcam_info_t **del)
   2992 {
   2993     int rv;
   2994     bcmi_xgs4_udf_tcam_info_t *cur = NULL;
   2995 
   2996     rv = bcmi_xgs4_udf_tcam_node_get(unit, pkt_format_id, &cur);
   2997     BCM_IF_ERROR_RETURN(rv);
   2998 
   2999     *del = NULL;
   3000 
   3001     /* Matching node not found */
   3002     if (cur == NULL) {
   3003         return BCM_E_NOT_FOUND;
   3004     }
   3005 
   3006     /* unlink cur from the list */
   3007     if (cur->prev) {
   3008         (cur->prev)->next = cur->next;
   3009     } else {
   3010         /* cur node is the head node */
   3011         UDF_CTRL(unit)->tcam_info_head = cur->next;
   3012     }
   3013     if (cur->next) {
   3014         (cur->next)->prev = cur->prev;
   3015     }
   3016 
   3017     /* Callee function to free the node */
   3018     *del = cur;
   3019 
   3020     return BCM_E_NONE;
   3021 }
   3022 
   3023 
   3024 /* To allocate running id for UDF and Packet format IDs. */
   3025 STATIC int
   3026 bcmi_xgs4_udf_id_running_id_alloc(int unit, bcmiUdfObjectType type, int *id)
   3027 {
   3028     int rv;
   3029     int ix;
   3030     int min_ix, max_ix;
   3031     bcmi_xgs4_udf_offset_info_t *offset_info = NULL;
   3032     bcmi_xgs4_udf_tcam_info_t *tcam_info = NULL;
   3033 
   3034     if (type == bcmiUdfObjectUdf) {
   3035         min_ix = BCMI_XGS4_UDF_ID_MIN;
   3036         max_ix = BCMI_XGS4_UDF_ID_MAX;
   3037 
   3038         ix = BCMI_XGS4_UDF_ID_RUNNING(unit);
   3039     } else {
   3040         min_ix = BCMI_XGS4_UDF_PKT_FORMAT_ID_MIN;
   3041         max_ix = BCMI_XGS4_UDF_PKT_FORMAT_ID_MAX;
   3042 
   3043         ix = BCMI_XGS4_UDF_PKT_FORMAT_ID_RUNNING(unit);
   3044     }
   3045 
   3046     if (max_ix < ix) {
   3047         for (ix = min_ix; ix <= max_ix; ix++) {
   3048             if (type == bcmiUdfObjectUdf) {
   3049                 rv = bcmi_xgs4_udf_offset_node_get(unit, ix, &offset_info);
   3050                 if (BCM_E_NOT_FOUND == rv) {
   3051                     break;
   3052                 }
   3053             } else {
   3054                 rv = bcmi_xgs4_udf_tcam_node_get(unit, ix, &tcam_info);
   3055                 if (BCM_E_NOT_FOUND == rv) {
   3056                     break;
   3057                 }
   3058             }
   3059             if (BCM_FAILURE(rv)) {
   3060                 break;
   3061             }
   3062         }
   3063 
   3064         /* All 64k udf ids are used up */
   3065         if (max_ix < ix) {
   3066             return BCM_E_FULL;
   3067         }
   3068     }
   3069 
   3070     *id = ix;
   3071 
   3072     return BCM_E_NONE;
   3073 }
   3074 
   3075 /* Conveerts chunk ID to OFFSET_xf and BASE_OFFSET_xf fields */
   3076 STATIC int
   3077 bcmi_xgs4_udf_offset_to_hw_field(int unit, int udf_num, int user_num,
   3078             soc_field_t *base_hw_f, soc_field_t *offset_hw_f)
   3079 {
   3080     soc_field_t offset_f[2][8] = {
   3081         {
   3082             UDF1_OFFSET0f,            UDF1_OFFSET1f,
   3083             UDF1_OFFSET2f,            UDF1_OFFSET3f,
   3084             UDF1_OFFSET4f,            UDF1_OFFSET5f,
   3085             UDF1_OFFSET6f,            UDF1_OFFSET7f
   3086         },
   3087         {
   3088             UDF2_OFFSET0f,            UDF2_OFFSET1f,
   3089             UDF2_OFFSET2f,            UDF2_OFFSET3f,
   3090             UDF2_OFFSET4f,            UDF2_OFFSET5f,
   3091             UDF2_OFFSET6f,            UDF2_OFFSET7f
   3092         }
   3093     };
   3094 
   3095     soc_field_t base_offset_f[2][8] = {
   3096         {
   3097             UDF1_BASE_OFFSET_0f,      UDF1_BASE_OFFSET_1f,
   3098             UDF1_BASE_OFFSET_2f,      UDF1_BASE_OFFSET_3f,
   3099             UDF1_BASE_OFFSET_4f,      UDF1_BASE_OFFSET_5f,
   3100             UDF1_BASE_OFFSET_6f,      UDF1_BASE_OFFSET_7f
   3101         },
   3102         {
   3103             UDF2_BASE_OFFSET_0f,      UDF2_BASE_OFFSET_1f,
   3104             UDF2_BASE_OFFSET_2f,      UDF2_BASE_OFFSET_3f,
   3105             UDF2_BASE_OFFSET_4f,      UDF2_BASE_OFFSET_5f,
   3106             UDF2_BASE_OFFSET_6f,      UDF2_BASE_OFFSET_7f
   3107         }
   3108     };
   3109 
   3110     *base_hw_f = base_offset_f[udf_num][user_num];
   3111     *offset_hw_f = offset_f[udf_num][user_num];
   3112 
   3113     return BCM_E_NONE;
   3114 }
   3115 
   3116 /*
   3117  * Function:
   3118  *      bcmi_xgs4_udf_offset_uninstall
   3119  * Purpose:
   3120  *      To uninstall the UDF offsets in the hardware
   3121  * Parameters:
   3122  *      unit            - (IN)      Unit number.
   3123  *      e               - (IN)      Entry in the UDF_OFFSET table.
   3124  *      hw_bmap         - (IN)      Offsets to uninstall.
   3125  *      pipe_num        - (IN)      pipe_num (used only in pipeLocal mode)
   3126  * Returns:
   3127  *      BCM_E_XXX
   3128  * Notes:
   3129  */
   3130 STATIC int
   3131 bcmi_xgs4_udf_offset_uninstall(int unit, int e, uint32 hw_bmap, int pipe_num)
   3132 {
   3133     int udf_idx, user_idx;
   3134     int rv;
   3135     int base = 0x0;
   3136     int offset = 0x0;
   3137     soc_mem_t mem;
   3138     soc_field_t base_f, offset_f;
   3139     fp_udf_offset_entry_t offset_buf;
   3140 
   3141     if ((e < 0) && (e > BCMI_XGS4_UDF_CTRL_MAX_UDF_ENTRIES(unit))) {
   3142         return BCM_E_PARAM;
   3143     }
   3144 
   3145 #if defined (BCM_TOMAHAWK_SUPPORT)
   3146     if (soc_feature(unit, soc_feature_udf_multi_pipe_support) &&
   3147        (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) {
   3148          mem = SOC_MEM_UNIQUE_ACC(unit, UDF_CTRL(unit)->offset_mem)[pipe_num];
   3149     } else
   3150 #endif
   3151     {
   3152         mem = UDF_CTRL(unit)->offset_mem;
   3153     }
   3154 
   3155     rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, e, &offset_buf);
   3156     BCM_IF_ERROR_RETURN(rv);
   3157 
   3158     for (udf_idx = 0; udf_idx < 2; udf_idx++) {
   3159         for (user_idx = 0; user_idx < (BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit)/2); user_idx++) {
   3160             if (!(hw_bmap & (1 << (udf_idx *
   3161                                 (BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit)/2) + user_idx)))) {
   3162                 continue;
   3163             }
   3164 
   3165 
   3166             rv = bcmi_xgs4_udf_offset_to_hw_field(unit, udf_idx, user_idx, &base_f, &offset_f);
   3167             BCM_IF_ERROR_RETURN(rv);
   3168 
   3169             soc_mem_field32_set(unit, mem, &offset_buf, base_f, base);
   3170             soc_mem_field32_set(unit, mem, &offset_buf, offset_f, offset);
   3171         }
   3172     }
   3173 #if defined (BCM_TOMAHAWK_SUPPORT)
   3174     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_PKT_FORMAT_CLASS_ID) {
   3175         soc_mem_field32_set(unit, mem, &offset_buf, UDF_CLASS_IDf, 0);
   3176     }
   3177 #endif
   3178 
   3179     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, e, &offset_buf);
   3180     BCM_IF_ERROR_RETURN(rv);
   3181 
   3182     return BCM_E_NONE;
   3183 }
   3184 
   3185 /*
   3186  * Function:
   3187  *      bcmi_xgs4_udf_offset_install
   3188  * Purpose:
   3189  *      To install the UDF offsets in the hardware
   3190  * Parameters:
   3191  *      unit            - (IN)      Unit number.
   3192  *      e               - (IN)      Entry in the UDF_OFFSET table.
   3193  *      hw_bmap         - (IN)      Offsets to uninstall.
   3194  *      base            - (IN)      value to write in BASE_OFFSETx.
   3195  *      offset          - (IN)      Value to write in the OFFSETx.
   3196  *      pipe_num        - (IN)      Pipe number (used only in pipeLocal)
   3197  *      udf_class_id    - (IN)      Class ID used by the IFP Key Selection Mechanism
   3198  *      flags           - (IN)      Flags for offset entry
   3199  * Returns:
   3200  *      BCM_E_XXX
   3201  * Notes:
   3202  */
   3203 STATIC int
   3204 bcmi_xgs4_udf_offset_install(int unit, int e, uint32 hw_bmap,
   3205                              int base, int offset, int pipe_num,
   3206                              int class_id, uint8 flags)
   3207 {
   3208     int udf_idx, user_idx;
   3209     int rv, max_offset;
   3210     soc_mem_t mem;
   3211     soc_field_t base_f, offset_f;
   3212     fp_udf_offset_entry_t offset_buf;
   3213 
   3214     if ((e < 0) && (e > BCMI_XGS4_UDF_CTRL_MAX_UDF_ENTRIES(unit))) {
   3215         return BCM_E_PARAM;
   3216     }
   3217     if (!BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit)) {
   3218         return BCM_E_PARAM;
   3219     }
   3220     max_offset = UDF_PACKET_PARSE_LENGTH/BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit);
   3221 
   3222 #if defined (BCM_TOMAHAWK_SUPPORT)
   3223     if (soc_feature(unit, soc_feature_udf_multi_pipe_support) &&
   3224        (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) {
   3225         mem = SOC_MEM_UNIQUE_ACC(unit, UDF_CTRL(unit)->offset_mem)[pipe_num];
   3226     } else
   3227 #endif
   3228     {
   3229         mem = UDF_CTRL(unit)->offset_mem;
   3230     }
   3231     offset = (offset < 0) ? 0 : (uint32)offset;
   3232 
   3233     rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, e, &offset_buf);
   3234     BCM_IF_ERROR_RETURN(rv);
   3235 
   3236     for (udf_idx = 0; udf_idx < 2; udf_idx++) {
   3237         for (user_idx = 0; user_idx < (BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit)/2); user_idx++) {
   3238             if (!(hw_bmap & (1 << (udf_idx *
   3239                     (BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit)/2) + user_idx)))) {
   3240                 continue;
   3241             }
   3242 
   3243             rv = bcmi_xgs4_udf_offset_to_hw_field(unit, udf_idx, user_idx, &base_f, &offset_f);
   3244             BCM_IF_ERROR_RETURN(rv);
   3245 
   3246             /*handling wrap around*/
   3247             if((offset >= max_offset) || (offset < 0)){
   3248                 offset = 0;
   3249             }
   3250 
   3251             soc_mem_field32_set(unit, mem, &offset_buf, base_f, base);
   3252             soc_mem_field32_set(unit, mem, &offset_buf, offset_f, offset);
   3253 
   3254             /* Every other offset chunk should have offset incr by 1 */
   3255             offset += 1;
   3256         }
   3257     }
   3258 
   3259 #if defined (BCM_TOMAHAWK_SUPPORT)
   3260     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_PKT_FORMAT_CLASS_ID) {
   3261         soc_mem_field32_set(unit, mem, &offset_buf, UDF_CLASS_IDf, class_id);
   3262     }
   3263     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CONDITIONAL_CHECK) {
   3264         if (flags & BCMI_XGS4_UDF_OFFSET_FLEXHASH) {
   3265             soc_mem_field32_set(unit, mem, &offset_buf,
   3266                                 ENABLE_UDF_CONDITIONAL_CHECKf, 1);
   3267         }
   3268     }
   3269 #endif
   3270 
   3271     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, e, &offset_buf);
   3272     BCM_IF_ERROR_RETURN(rv);
   3273 
   3274 
   3275     return BCM_E_NONE;
   3276 }
   3277 
   3278 /*
   3279  * Function:
   3280  *     bcmi_xgs4_udf_tcam_entry_move
   3281  * Purpose:
   3282  *     Move a single entry in  udf tcam and offset tables.
   3283  * Parameters:
   3284  *     unit      - (IN) BCM device number.
   3285  *     tcam_entry_arr - (IN) Data control structure.
   3286  *     src       - (IN) Move from index.
   3287  *     dst       - (IN) Move to index.
   3288  *     pipe      - (IN) Pipe num
   3289  * Returns:
   3290  *     BCM_E_XXX
   3291  */
   3292 STATIC int
   3293 bcmi_xgs4_udf_tcam_entry_move(int unit,
   3294                          bcmi_xgs4_udf_tcam_entry_t *tcam_entry_arr,
   3295                          int src, int dst, int pipe_num)
   3296 {
   3297     int rv;                                 /* Operation return status.   */
   3298     soc_mem_t offset_mem, tcam_mem;         /* Memory Ids                 */
   3299     uint32 hw_buf[SOC_MAX_MEM_FIELD_WORDS]; /* Buffer to read hw entry.   */
   3300 
   3301     /* Input parameters check. */
   3302     BCM_IF_NULL_RETURN_PARAM(tcam_entry_arr);
   3303 
   3304 #if defined (BCM_TOMAHAWK_SUPPORT)
   3305     if (soc_feature(unit, soc_feature_udf_multi_pipe_support) &&
   3306        (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) {
   3307         if (pipe_num == BCMI_XGS4_UDF_INVALID_PIPE_NUM) {
   3308             return BCM_E_PARAM;
   3309         }
   3310         tcam_mem = SOC_MEM_UNIQUE_ACC(unit, UDF_CTRL(unit)->tcam_mem)[pipe_num];
   3311         offset_mem = SOC_MEM_UNIQUE_ACC(unit, UDF_CTRL(unit)->offset_mem)[pipe_num];
   3312     } else
   3313 #endif
   3314     {
   3315         tcam_mem = UDF_CTRL(unit)->tcam_mem;
   3316         offset_mem = UDF_CTRL(unit)->offset_mem;
   3317     }
   3318     if (tcam_mem == INVALIDm || offset_mem == INVALIDm) {
   3319         return BCM_E_INTERNAL;
   3320     }
   3321 
   3322     rv = soc_mem_read(unit, offset_mem, MEM_BLOCK_ANY, src, hw_buf);
   3323     BCM_IF_ERROR_RETURN(rv);
   3324     rv = soc_mem_write(unit, offset_mem, MEM_BLOCK_ALL, dst, hw_buf);
   3325     BCM_IF_ERROR_RETURN(rv);
   3326 
   3327     rv = soc_mem_read(unit, tcam_mem, MEM_BLOCK_ANY, src, hw_buf);
   3328     BCM_IF_ERROR_RETURN(rv);
   3329     rv = soc_mem_write(unit, tcam_mem, MEM_BLOCK_ALL, dst, hw_buf);
   3330     BCM_IF_ERROR_RETURN(rv);
   3331 
   3332     /* Clear entries at old index. */
   3333     rv = soc_mem_write(unit, offset_mem, MEM_BLOCK_ALL, src,
   3334                        soc_mem_entry_null(unit, offset_mem));
   3335     BCM_IF_ERROR_RETURN(rv);
   3336 
   3337     rv = soc_mem_write(unit, tcam_mem, MEM_BLOCK_ALL, src,
   3338                        soc_mem_entry_null(unit, tcam_mem));
   3339     BCM_IF_ERROR_RETURN(rv);
   3340 
   3341     /* Update hw_idx in the packet formats */
   3342     tcam_entry_arr[src].tcam_info->hw_idx = dst;
   3343 
   3344     /* Update sw structure tracking entry use. */
   3345     sal_memcpy(tcam_entry_arr + dst,
   3346                tcam_entry_arr + src,
   3347                sizeof(bcmi_xgs4_udf_tcam_entry_t));
   3348 
   3349     sal_memset(tcam_entry_arr + src, 0,
   3350                sizeof(bcmi_xgs4_udf_tcam_entry_t));
   3351 
   3352 
   3353     return (BCM_E_NONE);
   3354 }
   3355 
   3356 /*
   3357  * Function:
   3358  *     bcmi_xgs4_udf_tcam_move_up
   3359  * Purpose:
   3360  *     Moved udf tcam entries up.
   3361  * Parameters:
   3362  *     unit      - (IN) BCM device number.
   3363  *     tcam_entry_arr - (IN) Data control structure.
   3364  *     dest      - (IN) Insertion target index.
   3365  *     free_slot - (IN) Free slot.
   3366  *     pipe_num  - (IN) Pipe num
   3367  * Returns:
   3368  *     BCM_E_XXX
   3369  */
   3370 STATIC int
   3371 bcmi_xgs4_udf_tcam_move_up(int unit,
   3372                       bcmi_xgs4_udf_tcam_entry_t *tcam_entry_arr,
   3373                       int dest, int free_slot, int pipe_num)
   3374 {
   3375     int idx;          /* Entries iterator.        */
   3376     int rv;           /* Operation return status. */
   3377 
   3378     for (idx = free_slot; idx > dest; idx --) {
   3379         rv = bcmi_xgs4_udf_tcam_entry_move(unit, tcam_entry_arr,
   3380                                            idx - 1, idx, pipe_num);
   3381         BCM_IF_ERROR_RETURN(rv);
   3382     }
   3383 
   3384     return (BCM_E_NONE);
   3385 }
   3386 
   3387 /*
   3388  * Function:
   3389  *     bcmi_xgs4_udf_tcam_move_down
   3390  * Purpose:
   3391  *     Moved udf tcam entries down
   3392  * Parameters:
   3393  *     unit      - (IN) BCM device number.
   3394  *     tcam_entry_arr - (IN) Data control structure.
   3395  *     dest      - (IN) Insertion target index.
   3396  *     pipe_num  - (IN) Pipe num
   3397  *     free_slot - (IN) Free slot.
   3398  * Returns:
   3399  *     BCM_E_XXX
   3400  */
   3401 STATIC int
   3402 bcmi_xgs4_udf_tcam_move_down(int unit,
   3403                         bcmi_xgs4_udf_tcam_entry_t *tcam_entry_arr,
   3404                         int dest, int free_slot, int pipe_num)
   3405 {
   3406     int idx;          /* Entries iterator.        */
   3407     int rv;           /* Operation return status. */
   3408 
   3409     for (idx = free_slot; idx < dest; idx ++) {
   3410         rv = bcmi_xgs4_udf_tcam_entry_move(unit, tcam_entry_arr,
   3411                                            idx + 1, idx, pipe_num);
   3412         BCM_IF_ERROR_RETURN(rv);
   3413     }
   3414     return (BCM_E_NONE);
   3415 }
   3416 
   3417 STATIC int
   3418 bcmi_xgs4_udf_tcam_entries_compare(int unit,
   3419                                    uint32 *hw_entry, uint32 *sw_entry)
   3420 {
   3421     return sal_memcmp(sw_entry, hw_entry, sizeof(fp_udf_tcam_entry_t));
   3422 }
   3423 
   3424 
   3425 /*
   3426  * Function:
   3427  *     bcmi_xgs4_udf_tcam_entry_match
   3428  * Purpose:
   3429  *     Match tcam entry against currently instllaed ones
   3430  * Parameters:
   3431  *     unit     - (IN) BCM device number.
   3432  *     new      - (IN  New Tcam info structure.
   3433  *     match    - (IN  Matched Tcam info structure.
   3434  * Returns:
   3435  *     BCM_E_XXX
   3436  */
   3437 STATIC int
   3438 bcmi_xgs4_udf_tcam_entry_match(int unit, bcmi_xgs4_udf_tcam_info_t *new,
   3439                                bcmi_xgs4_udf_tcam_info_t **match)
   3440 {
   3441     uint32 *old_buf;   /* Tcam entry pointer.        */
   3442     uint32 *new_buf;   /* Tcam entry pointer.        */
   3443     bcmi_xgs4_udf_tcam_info_t *tmp;
   3444 
   3445     /* Input parameters check. */
   3446     BCM_IF_NULL_RETURN_PARAM(new);
   3447 
   3448     new_buf = (uint32 *)&(new->hw_buf);
   3449 
   3450     tmp = UDF_CTRL(unit)->tcam_info_head;
   3451 
   3452     *match = NULL;
   3453 
   3454     while (tmp != NULL) {
   3455         if (tmp == new) {
   3456             tmp = tmp->next;
   3457             continue;
   3458         }
   3459 
   3460         old_buf = (uint32 *)&(tmp->hw_buf);
   3461 
   3462         if (!bcmi_xgs4_udf_tcam_entries_compare(unit, old_buf, new_buf)) {
   3463             *match = tmp;
   3464             break;
   3465         }
   3466 
   3467         tmp = tmp->next;
   3468     }
   3469 
   3470     if (*match == NULL) {
   3471         return BCM_E_NOT_FOUND;
   3472     }
   3473 
   3474 
   3475     return BCM_E_NONE;
   3476 
   3477 }
   3478 
   3479 /*
   3480  * Function:
   3481  *      bcmi_xgs4_udf_tcam_entry_insert
   3482  * Purpose:
   3483  *     To insert an entry in UDF_TCAM at an available index.
   3484  * Parameters:
   3485  *     unit        - (IN) BCM device number.
   3486  *     tcam_new    - (IN) Tcam info to be inserted.
   3487  * Returns:
   3488  *     BCM_E_XXX
   3489  */
   3490 STATIC int
   3491 bcmi_xgs4_udf_tcam_entry_insert(int unit, bcmi_xgs4_udf_tcam_info_t *tcam_new)
   3492 {
   3493     int idx;                       /* FP UDF tcam table interator.    */
   3494     int rv;                        /* Operation return status.        */
   3495     int idx_max;                   /* FP UDF tcam table index max.    */
   3496     int idx_min;                   /* FP UDF tcam table index min.    */
   3497     int range_min;                 /* Index min for entry insertion.  */
   3498     int range_max;                 /* Index max for entry insertion.  */
   3499     int tcam_idx;
   3500     int unused_entry_min;          /* Unused entry before the range.  */
   3501     int unused_entry_max;          /* Unused entry after the range.   */
   3502     bcmi_xgs4_udf_tcam_info_t *tcam_info;
   3503     bcmi_xgs4_udf_tcam_entry_t *tcam_entry_arr; /* Tcam entries array.  */
   3504     soc_mem_t                   tcam_mem; /* tcam memory access */
   3505     int pipe_num = BCMI_XGS4_UDF_INVALID_PIPE_NUM; /* used only in pipeLocal mode */
   3506 
   3507     /* Initialization. */
   3508     idx_min = soc_mem_index_min(unit, UDF_CTRL(unit)->tcam_mem);
   3509     idx_max = soc_mem_index_max(unit, UDF_CTRL(unit)->tcam_mem);
   3510 
   3511     if ((idx_min < 0) || (idx_max < 0)) {
   3512         return BCM_E_INTERNAL;
   3513     }
   3514 
   3515     range_min = idx_min;
   3516     range_max = idx_max;
   3517     unused_entry_min = unused_entry_max = -1;
   3518 
   3519 #if defined (BCM_TOMAHAWK_SUPPORT)
   3520     if (soc_feature(unit, soc_feature_udf_multi_pipe_support) &&
   3521        (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) {
   3522         pipe_num = tcam_new->associated_pipe;
   3523         tcam_entry_arr = UDF_CTRL(unit)->tcam_entry_array_per_pipe[pipe_num];
   3524         tcam_mem = SOC_MEM_UNIQUE_ACC(unit, UDF_CTRL(unit)->tcam_mem)[pipe_num];
   3525     } else
   3526 #endif
   3527     {
   3528         tcam_entry_arr = UDF_CTRL(unit)->tcam_entry_array;
   3529         tcam_mem = UDF_CTRL(unit)->tcam_mem;
   3530     }
   3531 
   3532     /* No identical entry found try to allocate an unused entry and
   3533      * reshuffle tcam if necessary to organize entries by priority.
   3534      */
   3535     for (idx = idx_min; idx <= idx_max; idx++) {
   3536         if (0 == tcam_entry_arr[idx].valid) {
   3537             if (idx <= range_max) {
   3538                 /* Any free index below range max can be used for insertion. */
   3539                 unused_entry_min = idx;
   3540             } else {
   3541                 /* There is no point to continue after first
   3542                  * free index above range max.
   3543                  */
   3544                 unused_entry_max = idx;
   3545                 break;
   3546             }
   3547         } else {
   3548             tcam_info = tcam_entry_arr[idx].tcam_info;
   3549             /* Identify insertion range. */
   3550             /*
   3551             * Principle:
   3552             *    1. Different entries must have different priorities, unless 0
   3553             *    2. Place entry of higher priority to lower index.
   3554             *    3. If priorities are equal (0), place entry of higher
   3555             *       pkt_format_id to lower index.
   3556             *  Process:
   3557             *   If existed tcam priority is explicitly configured (non-zero),
   3558             *      find the minimum entry whose priority is more than new priority,
   3559             *      and the maximum entry priority is less than new priority.
   3560             *   If existed tcam priority is not specified (zero),
   3561             *      if new priority is non-zero, find available place;
   3562             *      if new priority is zero, find available place using pkt_format_id.
   3563             *   If new priority is non-zero and equals to exsited priority,
   3564             *      or new pkt_format_id equals to exsited pkt_format_id,
   3565             *      don't insert, return parameter error.
   3566             */
   3567             if (0 < tcam_info->priority) {
   3568                 if (tcam_info->priority > tcam_new->priority) {
   3569                     range_min = idx;
   3570                 } else if (tcam_info->priority < tcam_new->priority) {
   3571                     if (idx < range_max) {
   3572                         range_max = idx;
   3573                     }
   3574                 } else {
   3575                     return BCM_E_PARAM;
   3576                 }
   3577             } else if (0 == tcam_info->priority) {
   3578                 if (0 == tcam_new->priority) {
   3579                     if (tcam_info->pkt_format_id > tcam_new->pkt_format_id) {
   3580                         range_min = idx;
   3581                     } else if (tcam_info->pkt_format_id <
   3582                                 tcam_new->pkt_format_id) {
   3583                         if (idx < range_max) {
   3584                             range_max = idx;
   3585                         }
   3586                     } else {
   3587                         return BCM_E_PARAM;
   3588                     }
   3589                 } else if (0 < tcam_new->priority) {
   3590                     if (idx < range_max) {
   3591                         range_max = idx;
   3592                     }
   3593                 } else {
   3594                     return BCM_E_PARAM;
   3595                 }
   3596             } else {
   3597                 return BCM_E_PARAM;
   3598             }
   3599         }
   3600     }
   3601 
   3602     /* Check if tcam is completely full. */
   3603     if ((unused_entry_min == -1) && (unused_entry_max == -1)) {
   3604         return (BCM_E_FULL);
   3605     }
   3606 
   3607     /*  Tcam entries shuffling. */
   3608     if (unused_entry_min > range_min) {
   3609         tcam_idx = unused_entry_min;
   3610     } else if (unused_entry_min == -1) {
   3611         rv = bcmi_xgs4_udf_tcam_move_up(unit, tcam_entry_arr,
   3612                                          range_max, unused_entry_max,
   3613                                          pipe_num);
   3614 
   3615         BCM_IF_ERROR_RETURN(rv);
   3616         tcam_idx = range_max;
   3617     } else if (unused_entry_max == -1) {
   3618         rv = bcmi_xgs4_udf_tcam_move_down(unit, tcam_entry_arr,
   3619                                            range_min, unused_entry_min,
   3620                                            pipe_num);
   3621         BCM_IF_ERROR_RETURN(rv);
   3622         tcam_idx = range_min;
   3623     } else if ((range_min - unused_entry_min) >
   3624                (unused_entry_max - range_max)) {
   3625         rv = bcmi_xgs4_udf_tcam_move_up(unit, tcam_entry_arr,
   3626                                          range_max, unused_entry_max,
   3627                                          pipe_num);
   3628         BCM_IF_ERROR_RETURN(rv);
   3629         tcam_idx = range_max;
   3630     } else {
   3631         rv = bcmi_xgs4_udf_tcam_move_down(unit, tcam_entry_arr,
   3632                                            range_min, unused_entry_min,
   3633                                            pipe_num);
   3634         BCM_IF_ERROR_RETURN(rv);
   3635         tcam_idx = range_min;
   3636     }
   3637 
   3638     /* Install the entry into hardware */
   3639     rv = soc_mem_write(unit, tcam_mem,
   3640                        MEM_BLOCK_ALL, tcam_idx, &(tcam_new->hw_buf));
   3641     SOC_IF_ERROR_RETURN(rv);
   3642 
   3643     /* Index was successfully allocated. */
   3644     tcam_new->hw_idx = tcam_idx;
   3645     tcam_entry_arr[tcam_idx].valid = 1;
   3646     tcam_entry_arr[tcam_idx].tcam_info = tcam_new;
   3647 
   3648 #ifdef BCM_TOMAHAWK_SUPPORT
   3649     if (soc_feature(unit, soc_feature_udf_multi_pipe_support) &&
   3650         (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) {
   3651         tcam_new->hw_idx_per_pipe[tcam_new->associated_pipe] = tcam_idx;
   3652     }
   3653 #endif
   3654 
   3655     return (BCM_E_NONE);
   3656 }
   3657 
   3658 /*
   3659  * Function:
   3660  *     bcmi_xgs4_udf_tcam_entry_l3_parse
   3661  * Purpose:
   3662  *     Parse udf tcam entry l3 format match key.
   3663  * Parameters:
   3664  *     unit     - (IN) BCM device number.
   3665  *     hw_buf   - (IN) Hw buffer.
   3666  *     pkt_fmt  - (OUT) Packet format structure.
   3667  * Returns:
   3668  *     BCM_E_XXX
   3669  */
   3670 STATIC int
   3671 bcmi_xgs4_udf_tcam_entry_l3_parse(int unit, uint32 *hw_buf,
   3672                                   bcm_udf_pkt_format_info_t *pkt_fmt)
   3673 {
   3674     uint32 ethertype = -1;
   3675     uint32 inner_iptype = -1;
   3676     uint32 ethertype_mask = -1;
   3677     uint32 outer_iptype = -1;
   3678     uint32 outer_iptype_ip4_val = -1;
   3679     uint32 outer_iptype_ip6_val = -1;
   3680     uint32 outer_iptype_mask = -1;
   3681     uint32 inner_iptype_mask = -1;
   3682     uint32 l3fields = -1;
   3683     uint32 l3fields_mask = -1;
   3684     soc_mem_t mem = UDF_CTRL(unit)->tcam_mem;
   3685     uint32 iptype_none_val = 0;
   3686     uint8  fc_header_encode = 0;
   3687     uint8  fc_hdr_encode_mask = 0;
   3688 
   3689     /* Input parameters check. */
   3690     BCM_IF_NULL_RETURN_PARAM(hw_buf);
   3691     BCM_IF_NULL_RETURN_PARAM(pkt_fmt);
   3692 
   3693     if (SOC_IS_TD_TT(unit)
   3694         || SOC_IS_KATANAX(unit)
   3695         || SOC_IS_TRIUMPH3(unit)) {
   3696         iptype_none_val = 2;
   3697     }
   3698     if ((ethertype_mask =
   3699             soc_mem_field32_get(unit, mem, hw_buf, L2_ETHER_TYPE_MASKf))) {
   3700         ethertype = soc_mem_field32_get(unit, mem, hw_buf, L2_ETHER_TYPEf);
   3701     }
   3702 
   3703     if ((inner_iptype_mask =
   3704             soc_mem_field32_get(unit, mem, hw_buf, INNER_IP_TYPE_MASKf))) {
   3705         inner_iptype = soc_mem_field32_get(unit, mem, hw_buf, INNER_IP_TYPEf);
   3706     }
   3707 
   3708     outer_iptype = soc_mem_field32_get(unit, mem, hw_buf, OUTER_IP_TYPEf);
   3709     outer_iptype_mask =  soc_mem_field32_get(unit, mem,
   3710                                           hw_buf, OUTER_IP_TYPE_MASKf);
   3711 
   3712     if (soc_mem_field32_get(unit, mem, hw_buf, L3_FIELDS_MASKf)) {
   3713         l3fields = soc_mem_field32_get(unit, mem, hw_buf, L3_FIELDSf);
   3714         l3fields_mask = soc_mem_field32_get(unit, mem, hw_buf, L3_FIELDS_MASKf);
   3715         if (0x8847 != ethertype) {
   3716            /* MPLS_ANY has L3_FIELDSf == 0 */
   3717            pkt_fmt->ip_protocol = (l3fields >> 16);
   3718            pkt_fmt->ip_protocol_mask = (l3fields_mask >> 16);
   3719         }
   3720     }
   3721 
   3722     outer_iptype_ip4_val = OUTER_IP4_TYPE_VAL(unit);
   3723     outer_iptype_ip6_val = OUTER_IP6_TYPE_VAL(unit);
   3724 
   3725     pkt_fmt->ethertype = ethertype;
   3726     pkt_fmt->ethertype_mask = ethertype_mask;
   3727 
   3728     /*
   3729      * Logic below implicitly checks Ethertype value for IP, MPLS and FCoE
   3730      * frames.
   3731      * 0x0800 - IPv4, 0x86DD - IPv6, 0x8847 - MPLS , 0x8906 + 0x8914 - FCoE
   3732      */
   3733 
   3734     if ((ethertype == 0x800) && (outer_iptype == outer_iptype_ip4_val)) {
   3735         pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_NONE;
   3736         pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP4_WITH_OPTIONS;
   3737         pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP_NONE;
   3738     } else if ((ethertype == 0x86dd) &&
   3739                (outer_iptype == outer_iptype_ip6_val)) {
   3740         pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_NONE;
   3741         pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP6_WITH_OPTIONS;
   3742         pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP_NONE;
   3743     } else if ((ethertype == 0x800) && (inner_iptype ==  iptype_none_val)) {
   3744         pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_NONE;
   3745         pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP4;
   3746         pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP_NONE;
   3747     } else if ((ethertype == 0x86dd) && (inner_iptype ==  iptype_none_val)) {
   3748         pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_NONE;
   3749         pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP6;
   3750         pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP_NONE;
   3751     } else if ((ethertype == 0x800) && (l3fields ==  0x40000)) {
   3752         pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_IP_IN_IP;
   3753         pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP4;
   3754         pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP4;
   3755     } else if ((ethertype == 0x800) && (l3fields ==  0x290000)) {
   3756         pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_IP_IN_IP;
   3757         pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP4;
   3758         pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP6;
   3759     } else if ((ethertype == 0x86dd) && (l3fields ==  0x40000)) {
   3760         pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_IP_IN_IP;
   3761         pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP6;
   3762         pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP4;
   3763     } else if ((ethertype == 0x86dd) && (l3fields ==  0x290000)) {
   3764         pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_IP_IN_IP;
   3765         pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP6;
   3766         pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP6;
   3767     } else if ((ethertype == 0x800) && (l3fields ==  0x2f0800)) {
   3768         pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_GRE;
   3769         pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP4;
   3770         pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP4;
   3771     } else if ((ethertype == 0x800) && (l3fields ==  0x2f86dd)) {
   3772         pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_GRE;
   3773         pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP4;
   3774         pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP6;
   3775     } else if ((ethertype == 0x86dd) && (l3fields ==  0x2f0800)) {
   3776         pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_GRE;
   3777         pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP6;
   3778         pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP4;
   3779     } else if ((ethertype == 0x86dd) && (l3fields ==  0x2f86dd)) {
   3780         pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_GRE;
   3781         pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP6;
   3782         pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP6;
   3783     } else if ((ethertype == 0x800) && (l3fields & 0xffff)) {
   3784         pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_GRE;
   3785         pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP4;
   3786         pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP_NONE;
   3787         pkt_fmt->inner_protocol = (uint16)(l3fields & 0xffff);
   3788         pkt_fmt->inner_protocol_mask = (uint16)(l3fields_mask & 0xffff);
   3789     } else if ((ethertype == 0x86dd) && (l3fields & 0xffff)) {
   3790         pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_GRE;
   3791         pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP6;
   3792         pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP_NONE;
   3793         pkt_fmt->inner_protocol = (uint16)(l3fields & 0xffff);
   3794         pkt_fmt->inner_protocol_mask = (uint16)(l3fields_mask & 0xffff);
   3795     } else if ((ethertype == 0x8847)) {
   3796         pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_MPLS;
   3797 
   3798         switch (l3fields & 0xf) {
   3799 
   3800             case 1:
   3801                 pkt_fmt->mpls = BCM_PKT_FORMAT_MPLS_ONE_LABEL;
   3802                 break;
   3803             case 2:
   3804                 pkt_fmt->mpls = BCM_PKT_FORMAT_MPLS_TWO_LABELS;
   3805                 break;
   3806             case 3:
   3807                 pkt_fmt->mpls = BCM_PKT_FORMAT_MPLS_THREE_LABELS;
   3808                 break;
   3809             case 4:
   3810                 pkt_fmt->mpls = BCM_PKT_FORMAT_MPLS_FOUR_LABELS;
   3811                 break;
   3812             case 5:
   3813                 pkt_fmt->mpls = BCM_PKT_FORMAT_MPLS_FIVE_LABELS;
   3814                 break;
   3815             default :
   3816                 pkt_fmt->mpls = BCM_PKT_FORMAT_MPLS_ANY;
   3817                 break;
   3818         }
   3819 #if defined (BCM_TOMAHAWK3_SUPPORT)
   3820         if (SOC_IS_TOMAHAWK3(unit)) {
   3821             pkt_fmt->first_2bytes_after_mpls_bos
   3822                  = ((l3fields >> MPLS_LABEL_COUNT_WIDTH_FOR_UDF_L3_FIELDS)
   3823                     & 0xffff);
   3824             pkt_fmt->first_2bytes_after_mpls_bos_mask
   3825                  = ((l3fields_mask
   3826                    >> MPLS_LABEL_COUNT_WIDTH_FOR_UDF_L3_FIELDS)
   3827                    & 0xffff);
   3828         }
   3829 #endif
   3830 
   3831     } else if (ethertype == 0x8906 || ethertype == 0x8914) {
   3832         pkt_fmt->tunnel = (ethertype == 0x8906)
   3833             ? BCM_PKT_FORMAT_TUNNEL_FCOE
   3834             : BCM_PKT_FORMAT_TUNNEL_FCOE_INIT;
   3835 
   3836         fc_header_encode = soc_mem_field32_get(unit, mem, hw_buf,
   3837                                 FC_HDR_ENCODE_1f);
   3838         fc_hdr_encode_mask = soc_mem_field32_get(unit, mem, hw_buf,
   3839                                 FC_HDR_ENCODE_1_MASKf);
   3840 
   3841         if (0 != fc_header_encode && 0 != fc_hdr_encode_mask) {
   3842 
   3843             switch (fc_header_encode & fc_hdr_encode_mask) {
   3844                 case 1:
   3845                     pkt_fmt->fibre_chan_outer
   3846                         = BCM_PKT_FORMAT_FIBRE_CHAN;
   3847                     break;
   3848                 case 2:
   3849                     pkt_fmt->fibre_chan_outer
   3850                         = BCM_PKT_FORMAT_FIBRE_CHAN_VIRTUAL;
   3851                     break;
   3852                 case 3:
   3853                     pkt_fmt->fibre_chan_outer
   3854                         = BCM_PKT_FORMAT_FIBRE_CHAN_ENCAP;
   3855                     break;
   3856                 case 4:
   3857                     pkt_fmt->fibre_chan_outer
   3858                         = BCM_PKT_FORMAT_FIBRE_CHAN_ROUTED;
   3859                     break;
   3860                 default:
   3861                     return (BCM_E_INTERNAL);
   3862             }
   3863         }
   3864 
   3865         fc_header_encode = soc_mem_field32_get(unit, mem, hw_buf,
   3866                                 FC_HDR_ENCODE_2f);
   3867         fc_hdr_encode_mask = soc_mem_field32_get(unit, mem, hw_buf,
   3868                                 FC_HDR_ENCODE_2_MASKf);
   3869         if (0 != fc_header_encode && 0 != fc_hdr_encode_mask) {
   3870 
   3871             switch (fc_header_encode & fc_hdr_encode_mask) {
   3872                 case 1:
   3873                     pkt_fmt->fibre_chan_inner
   3874                         = BCM_PKT_FORMAT_FIBRE_CHAN;
   3875                     break;
   3876                 case 2:
   3877                     pkt_fmt->fibre_chan_inner
   3878                         = BCM_PKT_FORMAT_FIBRE_CHAN_VIRTUAL;
   3879                     break;
   3880                 case 3:
   3881                     pkt_fmt->fibre_chan_inner
   3882                         = BCM_PKT_FORMAT_FIBRE_CHAN_ENCAP;
   3883                     break;
   3884                 case 4:
   3885                     pkt_fmt->fibre_chan_inner
   3886                         = BCM_PKT_FORMAT_FIBRE_CHAN_ROUTED;
   3887                     break;
   3888                 default:
   3889                     return (BCM_E_INTERNAL);
   3890             }
   3891         }
   3892     } else if (outer_iptype_mask == 0x7) {
   3893         /*
   3894          * For Non-IP traffic: OUTER_IP_TYPE_MASK = 0x7 and
   3895          * outer_ip_type_val = 0 (TR2) or 2 (Trident, Katana).
   3896          */
   3897         pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_NONE;
   3898         pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP_NONE;
   3899         pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP_NONE;
   3900     } else if (0x0 == ethertype_mask && 0x0 == inner_iptype_mask
   3901                 && 0x0 == outer_iptype_mask) {
   3902         /*
   3903          * Do not care about IP headers and Tunnel Type.
   3904          */
   3905         pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_ANY;
   3906         pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP_ANY;
   3907         pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP_ANY;
   3908     } else if (outer_iptype_mask == 0x0) {
   3909         /*
   3910          * Do not care about Outer IP. Inner IP is not valid
   3911          * as its not a Tunnel.
   3912          */
   3913         pkt_fmt->tunnel = BCM_PKT_FORMAT_TUNNEL_NONE;
   3914         pkt_fmt->outer_ip = BCM_PKT_FORMAT_IP_ANY;
   3915         pkt_fmt->inner_ip = BCM_PKT_FORMAT_IP_NONE;
   3916     } else {
   3917         return (BCM_E_INTERNAL);
   3918     }
   3919 
   3920 
   3921     return (BCM_E_NONE);
   3922 }
   3923 
   3924 /*
   3925  * Function:
   3926  *     bcmi_xgs4_udf_tcam_entry_l3_init
   3927  * Purpose:
   3928  *     Initialize udf tcam entry l2 format match key.
   3929  * Parameters:
   3930  *     unit     - (IN) BCM device number.
   3931  *     pkt_fmt  - (IN) Packet format structure.
   3932  *     hw_buf   - (IN/OUT) Hw buffer.
   3933  * Returns:
   3934  *     BCM_E_XXX
   3935  */
   3936 STATIC int
   3937 bcmi_xgs4_udf_tcam_entry_l3_init(int unit,
   3938                                  bcm_udf_pkt_format_info_t *pkt_fmt,
   3939                                  uint32 *hw_buf)
   3940 {
   3941     uint32 iptype_none_val = 0;
   3942     uint32 outer_iptype_ip4_val = 0;
   3943     uint32 outer_iptype_ip6_val = 0;
   3944 
   3945     uint16 l2_ethertype_val    = 0;
   3946     uint16 l2_ethertype_mask   = 0;
   3947     uint32 l3_fields_val       = 0;
   3948     uint32 l3_fields_mask      = 0;
   3949     uint32 inner_ip_type_val   = 0;
   3950     uint32 inner_ip_type_mask  = 0;
   3951     uint32 outer_ip_type_val   = 0;
   3952     uint32 outer_ip_type_mask  = 0;
   3953     uint32 inner_chn_key       = 0;
   3954     uint32 inner_chn_mask      = 0;
   3955     uint32 outer_chn_key       = 0;
   3956     uint32 outer_chn_mask      = 0;
   3957 #if defined (BCM_TOMAHAWK3_SUPPORT)
   3958     uint16 first_2bytes_after_mpls_bos = 0;
   3959     uint16 first_2bytes_after_mpls_bos_mask = 0;
   3960 #endif
   3961     soc_mem_t tcam_mem         = UDF_CTRL(unit)->tcam_mem;
   3962 
   3963 
   3964     /* Input parameters check. */
   3965     BCM_IF_NULL_RETURN_PARAM(hw_buf);
   3966     BCM_IF_NULL_RETURN_PARAM(pkt_fmt);
   3967 
   3968     if (SOC_IS_TD_TT(unit)
   3969         || SOC_IS_KATANAX(unit)
   3970         || SOC_IS_TRIUMPH3(unit)) {
   3971         iptype_none_val = 2;
   3972     }
   3973 
   3974     outer_iptype_ip4_val = OUTER_IP4_TYPE_VAL(unit);
   3975     outer_iptype_ip6_val = OUTER_IP6_TYPE_VAL(unit);
   3976 
   3977     if (pkt_fmt->tunnel == BCM_PKT_FORMAT_TUNNEL_NONE) {
   3978 
   3979         /* inner ip type (none). */
   3980         inner_ip_type_val   = iptype_none_val;
   3981         inner_ip_type_mask  = 0x7;
   3982 
   3983 
   3984         switch (pkt_fmt->outer_ip) {
   3985 
   3986             case BCM_PKT_FORMAT_IP4_WITH_OPTIONS:
   3987                 l2_ethertype_val     = 0x800;
   3988                 l2_ethertype_mask   = 0xffff;
   3989                 outer_ip_type_val = outer_iptype_ip4_val;
   3990                 outer_ip_type_mask     = 0x7;
   3991                 break;
   3992 
   3993             case BCM_PKT_FORMAT_IP6_WITH_OPTIONS:
   3994                 l2_ethertype_val     = 0x86dd;
   3995                 l2_ethertype_mask   = 0xffff;
   3996                 outer_ip_type_val = outer_iptype_ip6_val;
   3997                 outer_ip_type_mask     = 0x7;
   3998                 break;
   3999 
   4000             case BCM_PKT_FORMAT_IP4:
   4001                 l2_ethertype_val = 0x0800;
   4002                 l2_ethertype_mask   = 0xffff;
   4003                 break;
   4004 
   4005             case BCM_PKT_FORMAT_IP6:
   4006                 l2_ethertype_val = 0x86dd;
   4007                 l2_ethertype_mask   = 0xffff;
   4008                 break;
   4009 
   4010             case BCM_PKT_FORMAT_IP_NONE:
   4011                 outer_ip_type_val = iptype_none_val;
   4012                 outer_ip_type_mask     = 0x7;
   4013                 break;
   4014 
   4015             default:
   4016                 outer_ip_type_mask = 0x0;
   4017         }
   4018     } else if (pkt_fmt->tunnel == BCM_PKT_FORMAT_TUNNEL_IP_IN_IP) {
   4019         l2_ethertype_mask = 0xffff;
   4020         l3_fields_mask    = 0xff0000;
   4021         if (pkt_fmt->inner_ip == BCM_PKT_FORMAT_IP4) {
   4022             /* Inner ip protocol v4. */
   4023             l3_fields_val  = 0x40000;
   4024         } else if (pkt_fmt->inner_ip == BCM_PKT_FORMAT_IP6) {
   4025             /* Inner ip protocol v6. */
   4026             l3_fields_val  = 0x290000;
   4027         } else {
   4028             return (BCM_E_UNAVAIL);
   4029         }
   4030 
   4031         if (pkt_fmt->outer_ip == BCM_PKT_FORMAT_IP4) {
   4032             /* L2 ether type 0x800 */
   4033             l2_ethertype_val     = 0x800;
   4034         } else if (pkt_fmt->outer_ip == BCM_PKT_FORMAT_IP6) {
   4035             /* L2 ether type 0x86dd */
   4036             l2_ethertype_val     = 0x86dd;
   4037         } else {
   4038             return (BCM_E_UNAVAIL);
   4039         }
   4040     } else if (pkt_fmt->tunnel == BCM_PKT_FORMAT_TUNNEL_GRE) {
   4041 
   4042         l2_ethertype_mask = 0xffff;
   4043         l3_fields_mask    = 0xffffff;
   4044         if (pkt_fmt->inner_ip == BCM_PKT_FORMAT_IP4) {
   4045             /* Inner ip protocol gre, gre ethertype 0x800. */
   4046             l3_fields_val  = 0x2f0800;
   4047         } else if (pkt_fmt->inner_ip == BCM_PKT_FORMAT_IP6) {
   4048             /* Inner ip protocol gre, gre ethertype 0x86dd. */
   4049             l3_fields_val  = 0x2f86dd;
   4050         } else if (pkt_fmt->inner_ip == BCM_PKT_FORMAT_IP_NONE) {
   4051             /*when set inner_ip to IP_NONE, inner_protocal should not be IPV4 and IPV6*/
   4052             if (pkt_fmt->inner_protocol == 0x0800 ||
   4053                 pkt_fmt->inner_protocol == 0x86dd) {
   4054                 return BCM_E_PARAM;
   4055             }
   4056             l3_fields_val = (pkt_fmt->inner_protocol & 0xffff);
   4057             l3_fields_mask = (pkt_fmt->inner_protocol_mask & 0xffff);
   4058         } else {
   4059             return (BCM_E_UNAVAIL);
   4060         }
   4061 
   4062         if (pkt_fmt->outer_ip == BCM_PKT_FORMAT_IP4) {
   4063             l2_ethertype_val     = 0x0800;
   4064         } else if (pkt_fmt->outer_ip == BCM_PKT_FORMAT_IP6) {
   4065             /* L2 ether type 0x86dd */
   4066             l2_ethertype_val     = 0x86dd;
   4067         } else {
   4068             return (BCM_E_UNAVAIL);
   4069         }
   4070     } else if (pkt_fmt->tunnel == BCM_PKT_FORMAT_TUNNEL_MPLS) {
   4071 
   4072         l3_fields_mask = 0x0f;
   4073         switch (pkt_fmt->mpls) {
   4074 
   4075             case BCM_PKT_FORMAT_MPLS_ONE_LABEL:
   4076                 l3_fields_val = 0x01;
   4077                 break;
   4078 
   4079             case BCM_PKT_FORMAT_MPLS_TWO_LABELS:
   4080                 l3_fields_val = 0x02;
   4081                 break;
   4082 
   4083 #ifdef MPLS_FIVE_LABELS_SUPPORT
   4084             
   4085             case BCM_PKT_FORMAT_MPLS_THREE_LABELS:
   4086                 l3_fields_val = 0x03;
   4087                 break;
   4088 
   4089             case BCM_PKT_FORMAT_MPLS_FOUR_LABELS:
   4090                 l3_fields_val = 0x04;
   4091                 break;
   4092 
   4093             case BCM_PKT_FORMAT_MPLS_FIVE_LABELS:
   4094                 l3_fields_val = 0x05;
   4095                 break;
   4096 #endif /* MPLS_FIVE_LABELS_SUPPORT */
   4097             case BCM_PKT_FORMAT_MPLS_ANY:
   4098                 l3_fields_val = 0x0;
   4099                 l3_fields_mask   = 0x0;
   4100                 break;
   4101 
   4102             default:
   4103                 return (BCM_E_UNAVAIL);
   4104         }
   4105 
   4106         l2_ethertype_val = 0x8847;
   4107         l2_ethertype_mask = 0xffff;
   4108 
   4109 #if defined (BCM_TOMAHAWK3_SUPPORT)
   4110     if (SOC_IS_TOMAHAWK3(unit)) {
   4111         if (pkt_fmt->first_2bytes_after_mpls_bos_mask != 0) {
   4112             first_2bytes_after_mpls_bos = soc_mem_field32_get(unit, tcam_mem,
   4113                                             hw_buf, L3_FIELDSf);
   4114             first_2bytes_after_mpls_bos_mask = soc_mem_field32_get(unit, tcam_mem,
   4115                                                  hw_buf, L3_FIELDS_MASKf);
   4116 
   4117             first_2bytes_after_mpls_bos
   4118                = ((first_2bytes_after_mpls_bos
   4119                  >> MPLS_LABEL_COUNT_WIDTH_FOR_UDF_L3_FIELDS)
   4120                  & 0xffff);
   4121             first_2bytes_after_mpls_bos_mask
   4122                = ((first_2bytes_after_mpls_bos_mask
   4123                  >> MPLS_LABEL_COUNT_WIDTH_FOR_UDF_L3_FIELDS)
   4124                  & 0xffff);
   4125 
   4126             if ((first_2bytes_after_mpls_bos_mask != 0) &&
   4127                 ((first_2bytes_after_mpls_bos & first_2bytes_after_mpls_bos_mask) !=
   4128                 (pkt_fmt->first_2bytes_after_mpls_bos
   4129                 & pkt_fmt->first_2bytes_after_mpls_bos_mask))) {
   4130                 return BCM_E_CONFIG;
   4131 
   4132             } else {
   4133                 l3_fields_val = (((pkt_fmt->first_2bytes_after_mpls_bos & 0xffff)
   4134                                     << MPLS_LABEL_COUNT_WIDTH_FOR_UDF_L3_FIELDS) |
   4135                                     (l3_fields_val & 0xf));
   4136                 l3_fields_mask = (((pkt_fmt->first_2bytes_after_mpls_bos_mask
   4137                                      & 0xffff) << MPLS_LABEL_COUNT_WIDTH_FOR_UDF_L3_FIELDS) |
   4138                                      (l3_fields_mask & 0xf));
   4139             }
   4140         }
   4141     }
   4142 #endif
   4143 
   4144     } else if (pkt_fmt->tunnel == BCM_PKT_FORMAT_TUNNEL_FCOE ||
   4145                pkt_fmt->tunnel == BCM_PKT_FORMAT_TUNNEL_FCOE_INIT) {
   4146         if (!SOC_MEM_FIELD_VALID(unit, tcam_mem, FC_HDR_ENCODE_1f)) {
   4147             return BCM_E_UNAVAIL;
   4148         }
   4149 
   4150         l2_ethertype_val = ((pkt_fmt->tunnel ==
   4151                             BCM_PKT_FORMAT_TUNNEL_FCOE) ?
   4152                             0x8906 : 0x8914);
   4153 
   4154         l2_ethertype_mask = 0xffff;
   4155 
   4156         outer_chn_mask = 0x7;
   4157         switch (pkt_fmt->fibre_chan_outer) {
   4158             case BCM_PKT_FORMAT_FIBRE_CHAN:
   4159                 outer_chn_key = 1;
   4160                 break;
   4161             case BCM_PKT_FORMAT_FIBRE_CHAN_ENCAP:
   4162                 outer_chn_key = 3;
   4163                 break;
   4164             case BCM_PKT_FORMAT_FIBRE_CHAN_VIRTUAL:
   4165                 outer_chn_key = 2;
   4166                 break;
   4167             case BCM_PKT_FORMAT_FIBRE_CHAN_ROUTED:
   4168                 outer_chn_key = 4;
   4169                 break;
   4170             case BCM_PKT_FORMAT_FIBRE_CHAN_ANY:
   4171                 outer_chn_key = 0;
   4172                 outer_chn_mask = 0;
   4173                 break;
   4174             default:
   4175                 return BCM_E_UNAVAIL;
   4176         }
   4177 
   4178         /* Entry matching on two extended headers has higher priority */
   4179         inner_chn_mask = 0x07;
   4180 
   4181         switch (pkt_fmt->fibre_chan_inner) {
   4182             case BCM_PKT_FORMAT_FIBRE_CHAN:
   4183                 inner_chn_key = 1;
   4184                 break;
   4185             case BCM_PKT_FORMAT_FIBRE_CHAN_ENCAP:
   4186                 inner_chn_key = 3;
   4187                 break;
   4188             case BCM_PKT_FORMAT_FIBRE_CHAN_VIRTUAL:
   4189                 inner_chn_key = 2;
   4190                 break;
   4191             case BCM_PKT_FORMAT_FIBRE_CHAN_ROUTED:
   4192                 inner_chn_key = 4;
   4193                 break;
   4194             case BCM_PKT_FORMAT_FIBRE_CHAN_ANY:
   4195                 inner_chn_key = 0;
   4196                 inner_chn_mask = 0;
   4197                 break;
   4198             default:
   4199                 return BCM_E_UNAVAIL;
   4200         }
   4201 
   4202     } else if (BCM_PKT_FORMAT_TUNNEL_ANY == pkt_fmt->tunnel
   4203                 && BCM_PKT_FORMAT_IP_ANY == pkt_fmt->outer_ip
   4204                 && BCM_PKT_FORMAT_IP_ANY == pkt_fmt->inner_ip) {
   4205 
   4206         l2_ethertype_val = 0;
   4207         l2_ethertype_mask = 0;
   4208         l3_fields_val = 0;
   4209         l3_fields_mask = 0;
   4210         outer_ip_type_val = 0;
   4211         outer_ip_type_mask = 0;
   4212         inner_ip_type_val = 0;
   4213         inner_ip_type_mask = 0;
   4214         inner_chn_key =0;
   4215         inner_chn_mask =0;
   4216         outer_chn_key =0;
   4217         outer_chn_mask =0;
   4218 
   4219     } else {
   4220         return (BCM_E_UNAVAIL);
   4221     }
   4222 
   4223     /* Configure ip_protocol/mask fields */
   4224     if ((pkt_fmt->tunnel != BCM_PKT_FORMAT_TUNNEL_MPLS)) {
   4225         l3_fields_val |= (pkt_fmt->ip_protocol << 16);
   4226         l3_fields_mask |= (pkt_fmt->ip_protocol_mask << 16);
   4227     }
   4228 
   4229     /* ALL the keys are configured. Now set them in entry */
   4230     soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4231                         L2_ETHER_TYPEf, l2_ethertype_val);
   4232     soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4233                         L2_ETHER_TYPE_MASKf, l2_ethertype_mask);
   4234     soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4235                         L3_FIELDSf, l3_fields_val);
   4236     soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4237                         L3_FIELDS_MASKf, l3_fields_mask);
   4238     soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4239                         OUTER_IP_TYPEf, outer_ip_type_val);
   4240     soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4241                         OUTER_IP_TYPE_MASKf, outer_ip_type_mask);
   4242     soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4243                         INNER_IP_TYPEf, inner_ip_type_val);
   4244     soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4245                         INNER_IP_TYPE_MASKf,inner_ip_type_mask);
   4246 
   4247     if (SOC_MEM_FIELD_VALID(unit, tcam_mem,FC_HDR_ENCODE_1f)) {
   4248         soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4249                             FC_HDR_ENCODE_1f, outer_chn_key);
   4250     }
   4251     if (SOC_MEM_FIELD_VALID(unit, tcam_mem,FC_HDR_ENCODE_1_MASKf)) {
   4252         soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4253                             FC_HDR_ENCODE_1_MASKf, outer_chn_mask);
   4254     }
   4255     if (SOC_MEM_FIELD_VALID(unit, tcam_mem,FC_HDR_ENCODE_2f)) {
   4256         soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4257                             FC_HDR_ENCODE_2f, inner_chn_key);
   4258     }
   4259     if (SOC_MEM_FIELD_VALID(unit, tcam_mem,FC_HDR_ENCODE_2_MASKf)) {
   4260         soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4261                             FC_HDR_ENCODE_2_MASKf, inner_chn_mask);
   4262     }
   4263 
   4264     return (BCM_E_NONE);
   4265 }
   4266 
   4267 
   4268 /* Converts the misc packet format flags to fields in the UDF_TCAM */
   4269 STATIC int
   4270 bcmi_xgs4_udf_tcam_misc_format_to_hw_fields(
   4271     int unit, int type,
   4272     soc_field_t *data_f, soc_field_t *mask_f,
   4273     int *present, int *none, int *any, int *support)
   4274 {
   4275 
   4276     soc_field_t hw_fields_f[2][7] = {
   4277             {
   4278                 HIGIGf,        CNTAG_PRESENTf,
   4279                 ICNM_PACKETf,  VNTAG_PRESENTf,
   4280                 ETAG_PACKETf,  SUBPORT_TAG_PRESENTf,
   4281                 INT_PKTf
   4282             },
   4283             {
   4284                 HIGIG_MASKf,        CNTAG_PRESENT_MASKf,
   4285                 ICNM_PACKET_MASKf,  VNTAG_PRESENT_MASKf,
   4286                 ETAG_PACKET_MASKf,  SUBPORT_TAG_PRESENT_MASKf,
   4287                 INT_PKT_MASKf
   4288             }
   4289         };
   4290     int sw_flags[3][7] = {
   4291             {
   4292                 BCM_PKT_FORMAT_HIGIG_PRESENT,
   4293                 BCM_PKT_FORMAT_CNTAG_PRESENT,
   4294                 BCM_PKT_FORMAT_ICNM_PRESENT,
   4295                 BCM_PKT_FORMAT_VNTAG_PRESENT,
   4296                 BCM_PKT_FORMAT_ETAG_PRESENT,
   4297                 BCM_PKT_FORMAT_SUBPORT_TAG_PRESENT,
   4298                 BCM_PKT_FORMAT_INT_PKT_PRESENT,
   4299             },
   4300             {
   4301                 BCM_PKT_FORMAT_HIGIG_NONE,
   4302                 BCM_PKT_FORMAT_CNTAG_NONE,
   4303                 BCM_PKT_FORMAT_ICNM_NONE,
   4304                 BCM_PKT_FORMAT_VNTAG_NONE,
   4305                 BCM_PKT_FORMAT_ETAG_NONE,
   4306                 BCM_PKT_FORMAT_SUBPORT_TAG_NONE,
   4307                 BCM_PKT_FORMAT_INT_PKT_NONE,
   4308             },
   4309             {
   4310                 BCM_PKT_FORMAT_HIGIG_ANY,
   4311                 BCM_PKT_FORMAT_CNTAG_ANY,
   4312                 BCM_PKT_FORMAT_ICNM_ANY,
   4313                 BCM_PKT_FORMAT_VNTAG_ANY,
   4314                 BCM_PKT_FORMAT_ETAG_ANY,
   4315                 BCM_PKT_FORMAT_SUBPORT_TAG_ANY,
   4316                 BCM_PKT_FORMAT_INT_PKT_ANY,
   4317             }
   4318         };
   4319     int ctrl_flags[1][7] = {
   4320             {
   4321                 BCMI_XGS4_UDF_CTRL_TCAM_HIGIG,
   4322                 BCMI_XGS4_UDF_CTRL_TCAM_CNTAG,
   4323                 BCMI_XGS4_UDF_CTRL_TCAM_ICNM,
   4324                 BCMI_XGS4_UDF_CTRL_TCAM_VNTAG,
   4325                 BCMI_XGS4_UDF_CTRL_TCAM_ETAG,
   4326                 BCMI_XGS4_UDF_CTRL_TCAM_SUBPORT_TAG,
   4327                 BCMI_XGS4_UDF_CTRL_INT_PKT,
   4328             }
   4329         };
   4330 
   4331     *data_f     = hw_fields_f[0][type];
   4332     *mask_f     = hw_fields_f[1][type];
   4333     *present    = sw_flags[0][type];
   4334     *none       = sw_flags[1][type];
   4335     *any        = sw_flags[2][type];
   4336     *support    = ctrl_flags[0][type];
   4337 
   4338     return BCM_E_NONE;
   4339 }
   4340 
   4341 /*
   4342  * Function:
   4343  *     bcmi_xgs4_udf_tcam_entry_misc_parse
   4344  * Purpose:
   4345  *     Parse udf tcam entry flags format match key.
   4346  * Parameters:
   4347  *     unit     - (IN) BCM device number.
   4348  *     hw_buf   - (IN) Hw buffer.
   4349  *     flags    - (OUT) BCM_PKT_FORMAT_F_XXX
   4350  * Returns:
   4351  *     BCM_E_XXX
   4352  */
   4353 STATIC int
   4354 bcmi_xgs4_udf_tcam_entry_misc_parse(int unit, int type,
   4355                                     uint32 *hw_buf, uint16 *flags)
   4356 {
   4357     int rv;
   4358     soc_mem_t mem;
   4359     uint32 data, mask;
   4360     soc_field_t data_f, mask_f;
   4361     int present, none, any, support;
   4362 
   4363     /* Input parameters check. */
   4364     BCM_IF_NULL_RETURN_PARAM(hw_buf);
   4365     BCM_IF_NULL_RETURN_PARAM(flags);
   4366 
   4367     mem = UDF_CTRL(unit)->tcam_mem;
   4368 
   4369     rv = bcmi_xgs4_udf_tcam_misc_format_to_hw_fields(unit, type,
   4370              &data_f, &mask_f, &present, &none, &any, &support);
   4371     BCM_IF_ERROR_RETURN(rv);
   4372 
   4373     /* If the field is not supported, return ANY */
   4374     if (!(UDF_CTRL(unit)->flags & support)) {
   4375         *flags = any;
   4376         return BCM_E_NONE;
   4377     }
   4378 
   4379     if (soc_mem_field32_get(unit, mem, hw_buf, mask_f)) {
   4380         data = soc_mem_field32_get(unit, mem, hw_buf, data_f);
   4381         mask = soc_mem_field32_get(unit, mem, hw_buf, mask_f);
   4382         *flags |= ((mask == 0) ? any : ((data == 1) ? present : none));
   4383     }
   4384 
   4385     return (BCM_E_NONE);
   4386 }
   4387 
   4388 /*
   4389  * Function:
   4390  *     bcmi_xgs4_udf_tcam_entry_misc_init
   4391  * Purpose:
   4392  *     Initialize udf tcam entry flags match key.
   4393  * Parameters:
   4394  *     unit     - (IN) BCM device number.
   4395  *     flags    - (IN) BCM_PKT_FORMAT_F_XXX
   4396  *     hw_buf   - (OUT) Hw buffer.
   4397  * Returns:
   4398  *     BCM_E_XXX
   4399  */
   4400 STATIC int
   4401 bcmi_xgs4_udf_tcam_entry_misc_init(int unit, int type,
   4402                                    uint16 flags, uint32 *hw_buf)
   4403 {
   4404     int rv;
   4405     soc_mem_t mem;
   4406     soc_field_t data_f, mask_f;
   4407     int present, none, any, support;
   4408 
   4409 
   4410     /* Input parameters check. */
   4411     BCM_IF_NULL_RETURN_PARAM(hw_buf);
   4412 
   4413     mem = UDF_CTRL(unit)->tcam_mem;
   4414 
   4415     rv = bcmi_xgs4_udf_tcam_misc_format_to_hw_fields(unit, type,
   4416              &data_f, &mask_f, &present, &none, &any, &support);
   4417     BCM_IF_ERROR_RETURN(rv);
   4418 
   4419     /* If the field is not supported, only ANY is allowed,
   4420      * hw_buf should not be set */
   4421     if (!(UDF_CTRL(unit)->flags & support)) {
   4422         if (flags != any) {
   4423             return BCM_E_PARAM;
   4424         } else {
   4425             return BCM_E_NONE;
   4426         }
   4427     }
   4428 
   4429     /* Both PRESENT and NONE flags cannot be set
   4430      * If it is required to match on all packets, set ANY */
   4431     if ((flags & present) && (flags & none)) {
   4432         return BCM_E_PARAM;
   4433     }
   4434 
   4435     if ((flags & present) || (flags & none)) {
   4436         soc_mem_field32_set(unit, mem, hw_buf, mask_f, 1);
   4437         soc_mem_field32_set(unit, mem, hw_buf, data_f, (flags & present) ? 1:0);
   4438     } else {
   4439         /* any */
   4440         soc_mem_field32_set(unit, mem, hw_buf, data_f, 0);
   4441         soc_mem_field32_set(unit, mem, hw_buf, mask_f, 0);
   4442     }
   4443 
   4444     return BCM_E_NONE;
   4445 
   4446 }
   4447 
   4448 /*
   4449  * Function:
   4450  *     bcmi_xgs4_udf_tcam_entry_l2format_init
   4451  * Purpose:
   4452  *     Initialize udf tcam entry l2 format match key.
   4453  * Parameters:
   4454  *     unit     - (IN) BCM device number.
   4455  *     l2format - (IN) BCM_PKT_FORMAT_L2_XXX
   4456  *     hw_buf   - (OUT) Hw buffer.
   4457  * Returns:
   4458  *     BCM_E_XXX
   4459  */
   4460 STATIC int
   4461 bcmi_xgs4_udf_tcam_entry_l2format_init(int unit,
   4462                                        bcm_udf_pkt_format_info_t *pkt_fmt,
   4463                                        uint32 *hw_buf)
   4464 {
   4465     uint16 l2format = pkt_fmt->l2;
   4466     soc_mem_t tcam_mem = UDF_CTRL(unit)->tcam_mem;  /* UDF_TCAM memory   */
   4467 
   4468     /* Input parameters check. */
   4469     BCM_IF_NULL_RETURN_PARAM(hw_buf);
   4470     BCM_IF_NULL_RETURN_PARAM(pkt_fmt);
   4471 
   4472     /* Translate L2 flag bits to index */
   4473     switch (l2format) {
   4474       case BCM_PKT_FORMAT_L2_ETH_II:
   4475           /* L2 Format . */
   4476           soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4477                               L2_TYPEf, 0);
   4478           soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4479                               L2_TYPE_MASKf, 0x3);
   4480 
   4481           break;
   4482       case BCM_PKT_FORMAT_L2_SNAP:
   4483           /* L2 Format . */
   4484           soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4485                               L2_TYPEf, 1);
   4486           soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4487                               L2_TYPE_MASKf, 0x3);
   4488 
   4489           break;
   4490       case BCM_PKT_FORMAT_L2_LLC:
   4491           /* L2 Format . */
   4492           soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4493                               L2_TYPEf, 2);
   4494           soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4495                               L2_TYPE_MASKf, 0x3);
   4496 
   4497           break;
   4498       case BCM_PKT_FORMAT_L2_ANY:
   4499           /* L2 Format . */
   4500           soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4501                               L2_TYPEf, 0);
   4502           soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4503                               L2_TYPE_MASKf, 0);
   4504           break;
   4505       default:
   4506           return (BCM_E_PARAM);
   4507     }
   4508     return (BCM_E_NONE);
   4509 }
   4510 
   4511 /*
   4512  * Function:
   4513  *     bcmi_xgs4_udf_tcam_entry_l2format_parse
   4514  * Purpose:
   4515  *     Parse udf tcam entry l2 format match key.
   4516  * Parameters:
   4517  *     unit     - (IN) BCM device number.
   4518  *     hw_buf   - (IN) Hw buffer.
   4519  *     l2format - (OUT) BCM_PKT_FORMAT_L2_XXX
   4520  * Returns:
   4521  *     BCM_E_XXX
   4522  */
   4523 STATIC int
   4524 bcmi_xgs4_udf_tcam_entry_l2format_parse(int unit, uint32 *hw_buf,
   4525                                         bcm_udf_pkt_format_info_t *pkt_fmt)
   4526 {
   4527     uint32 l2type;
   4528     uint16 *l2format = &pkt_fmt->l2;
   4529     soc_mem_t tcam_mem = UDF_CTRL(unit)->tcam_mem;  /* UDF_TCAM memory   */
   4530 
   4531     /* Input parameters check. */
   4532     BCM_IF_NULL_RETURN_PARAM(hw_buf);
   4533     BCM_IF_NULL_RETURN_PARAM(pkt_fmt);
   4534 
   4535     if (soc_mem_field32_get(unit, tcam_mem, hw_buf, L2_TYPE_MASKf)) {
   4536         l2type = soc_mem_field32_get(unit, tcam_mem, hw_buf, L2_TYPEf);
   4537         switch (l2type) {
   4538           case 0:
   4539               *l2format = BCM_PKT_FORMAT_L2_ETH_II;
   4540               break;
   4541           case 1:
   4542               *l2format = BCM_PKT_FORMAT_L2_SNAP;
   4543               break;
   4544           case 2:
   4545               *l2format = BCM_PKT_FORMAT_L2_LLC;
   4546               break;
   4547           default:
   4548               break;
   4549         }
   4550     } else {
   4551         *l2format = BCM_PKT_FORMAT_L2_ANY;
   4552     }
   4553     return (BCM_E_NONE);
   4554 }
   4555 
   4556 /*
   4557  * Function:
   4558  *     bcmi_xgs4_udf_tcam_entry_vlanformat_parse
   4559  * Purpose:
   4560  *     Parse udf tcam entry l2 format match key.
   4561  * Parameters:
   4562  *     unit     - (IN) BCM device number.
   4563  *     hw_buf   - (IN) Hw buffer.
   4564  *     vlanformat - (OUT) BCM_PKT_FORMAT_L2_XXX
   4565  * Returns:
   4566  *     BCM_E_XXX
   4567  */
   4568 STATIC int
   4569 bcmi_xgs4_udf_tcam_entry_vlanformat_parse(int unit, uint32 *hw_buf,
   4570                                           bcm_udf_pkt_format_info_t *pkt_fmt)
   4571 {
   4572     uint32 tag_status;
   4573     uint16 *vlanformat = &pkt_fmt->vlan_tag;
   4574     soc_mem_t tcam_mem = UDF_CTRL(unit)->tcam_mem;  /* UDF_TCAM memory   */
   4575 
   4576     /* Input parameters check. */
   4577     BCM_IF_NULL_RETURN_PARAM(hw_buf);
   4578     BCM_IF_NULL_RETURN_PARAM(pkt_fmt);
   4579 
   4580     if (soc_mem_field32_get(unit, tcam_mem, hw_buf, L2_TAG_STATUS_MASKf)) {
   4581         tag_status = soc_mem_field32_get(unit, tcam_mem, hw_buf,
   4582                                          L2_TAG_STATUSf);
   4583         switch (tag_status) {
   4584           case 0:
   4585               *vlanformat = BCM_PKT_FORMAT_VLAN_TAG_NONE;
   4586               break;
   4587           case 1:
   4588               *vlanformat = BCM_PKT_FORMAT_VLAN_TAG_SINGLE;
   4589               break;
   4590           case 2:
   4591               *vlanformat = BCM_PKT_FORMAT_VLAN_TAG_DOUBLE;
   4592               break;
   4593           default:
   4594               break;
   4595         }
   4596     } else {
   4597         *vlanformat = BCM_PKT_FORMAT_VLAN_TAG_ANY;
   4598     }
   4599     return (BCM_E_NONE);
   4600 }
   4601 
   4602 /*
   4603  * Function:
   4604  *     bcmi_xgs4_udf_tcam_entry_vlanformat_init
   4605  * Purpose:
   4606  *     Initialize udf tcam entry vlan tag format match key.
   4607  * Parameters:
   4608  *     unit       - (IN) BCM device number.
   4609  *     vlanformat - (IN) BCM_PKT_FORMAT_L2_XXX
   4610  *     hw_buf     - (IN/OUT) Hw buffer.
   4611  * Returns:
   4612  *     BCM_E_XXX
   4613  */
   4614 STATIC int
   4615 bcmi_xgs4_udf_tcam_entry_vlanformat_init(int unit,
   4616                                          bcm_udf_pkt_format_info_t *pkt_fmt,
   4617                                          uint32 *hw_buf)
   4618 {
   4619     uint16 vlanformat = pkt_fmt->vlan_tag;
   4620     soc_mem_t tcam_mem = UDF_CTRL(unit)->tcam_mem;  /* UDF_TCAM memory   */
   4621 
   4622     /* Input parameters check. */
   4623     BCM_IF_NULL_RETURN_PARAM(hw_buf);
   4624     BCM_IF_NULL_RETURN_PARAM(pkt_fmt);
   4625 
   4626     /* Translate L2 flag bits to index */
   4627     switch (vlanformat) {
   4628         case BCM_PKT_FORMAT_VLAN_TAG_NONE:
   4629             /* L2 Format . */
   4630             soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4631                                 L2_TAG_STATUSf, 0);
   4632             if (soc_feature(unit, soc_feature_fp_no_inner_vlan_support)) {
   4633                 soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4634                                     L2_TAG_STATUS_MASKf, 0x1);
   4635             } else {
   4636                 soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4637                                     L2_TAG_STATUS_MASKf, 0x3);
   4638             }
   4639 
   4640           break;
   4641         case BCM_PKT_FORMAT_VLAN_TAG_SINGLE:
   4642             /* L2 Format . */
   4643             soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4644                                 L2_TAG_STATUSf, 1);
   4645             if (soc_feature(unit, soc_feature_fp_no_inner_vlan_support)) {
   4646                 soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4647                                     L2_TAG_STATUS_MASKf, 0x1);
   4648             } else {
   4649                 soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4650                                     L2_TAG_STATUS_MASKf, 0x3);
   4651             }
   4652 
   4653         break;
   4654         case BCM_PKT_FORMAT_VLAN_TAG_DOUBLE:
   4655             if (soc_feature(unit, soc_feature_fp_no_inner_vlan_support)) {
   4656                 return (BCM_E_UNAVAIL);
   4657             } else {
   4658                 /* L2 Format . */
   4659                 soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4660                                     L2_TAG_STATUSf, 2);
   4661                 soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4662                                     L2_TAG_STATUS_MASKf, 0x3);
   4663             }
   4664 
   4665         break;
   4666         case BCM_PKT_FORMAT_VLAN_TAG_ANY:
   4667           /* L2 Format . */
   4668             soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4669                                 L2_TAG_STATUSf, 0);
   4670             soc_mem_field32_set(unit, tcam_mem, hw_buf,
   4671                                 L2_TAG_STATUS_MASKf, 0);
   4672         break;
   4673         default:
   4674             return (BCM_E_PARAM);
   4675     }
   4676     return (BCM_E_NONE);
   4677 }
   4678 
   4679 
   4680 /*
   4681  * Function:
   4682  *     bcmi_xgs4_udf_tcam_entry_lb_pkt_type_parse
   4683  * Purpose:
   4684  *     Parse udf tcam entry loopback pkt type match key.
   4685  * Parameters:
   4686  *     unit     - (IN) BCM device number.
   4687  *     hw_buf   - (IN) Hw buffer.
   4688  *     lb_pkt_type - (OUT) BCM_PKT_FORMAT_LB_TYPE_XXX
   4689  * Returns:
   4690  *     BCM_E_XXX
   4691  */
   4692 STATIC int
   4693 bcmi_xgs4_udf_tcam_entry_lb_pkt_type_parse(int unit, uint32 *hw_buf,
   4694                                           bcm_udf_pkt_format_info_t *pkt_fmt)
   4695 {
   4696     uint32 type;
   4697     uint8 *lb_pkt_type = &pkt_fmt->lb_pkt_type;
   4698     soc_mem_t tcam_mem = UDF_CTRL(unit)->tcam_mem;  /* UDF_TCAM memory   */
   4699 
   4700     /* Input parameters check. */
   4701     BCM_IF_NULL_RETURN_PARAM(hw_buf);
   4702     BCM_IF_NULL_RETURN_PARAM(pkt_fmt);
   4703 
   4704     if (soc_mem_field32_get(unit, tcam_mem, hw_buf, LOOPBACK_PKT_TYPE_MASKf)) {
   4705         type = soc_mem_field32_get(unit, tcam_mem, hw_buf,
   4706                                          LOOPBACK_PKT_TYPEf);
   4707         switch (type) {
   4708           case 1:
   4709               if (SOC_IS_TOMAHAWK3(unit)) {
   4710                   *lb_pkt_type = BCM_PKT_FORMAT_LB_TYPE_GENERIC;
   4711               } else {
   4712                   *lb_pkt_type = BCM_PKT_FORMAT_LB_TYPE_MIM;
   4713               }
   4714               break;
   4715           default:
   4716               break;
   4717         }
   4718     } else {
   4719         *lb_pkt_type = BCM_PKT_FORMAT_LB_TYPE_ANY;
   4720     }
   4721 
   4722     return (BCM_E_NONE);
   4723 }
   4724 
   4725 /*
   4726  * Function:
   4727  *     bcmi_xgs4_udf_tcam_entry_l4_dst_port_parse
   4728  * Purpose:
   4729  *     Parse udf tcam entry loopback pkt type match key.
   4730  * Parameters:
   4731  *     unit     - (IN) BCM device number.
   4732  *     hw_buf   - (IN) Hw buffer.
   4733  *     l4_dst_port - (OUT) BCM_PKT_FORMAT_LB_TYPE_XXX
   4734  * Returns:
   4735  *     BCM_E_XXX
   4736  */
   4737 STATIC int
   4738 bcmi_xgs4_udf_tcam_entry_l4_dst_port_parse(int unit, uint32 *hw_buf,
   4739                                           bcm_udf_pkt_format_info_t *pkt_fmt)
   4740 {
   4741     soc_mem_t tcam_mem = UDF_CTRL(unit)->tcam_mem;  /* UDF_TCAM memory   */
   4742 
   4743     /* Input parameters check. */
   4744     BCM_IF_NULL_RETURN_PARAM(hw_buf);
   4745     BCM_IF_NULL_RETURN_PARAM(pkt_fmt);
   4746 
   4747     pkt_fmt->l4_dst_port = soc_mem_field32_get(unit, tcam_mem, hw_buf,
   4748                                                L4_DST_PORTf);
   4749     pkt_fmt->l4_dst_port_mask = soc_mem_field32_get(unit, tcam_mem, hw_buf,
   4750                                                L4_DST_PORT_MASKf);
   4751 
   4752     return (BCM_E_NONE);
   4753 
   4754 }
   4755 
   4756 /*
   4757  * Function:
   4758  *     bcmi_xgs4_udf_tcam_entry_opaque_tag_type_parse
   4759  * Purpose:
   4760  *     Parse udf tcam entry loopback pkt type match key.
   4761  * Parameters:
   4762  *     unit     - (IN) BCM device number.
   4763  *     hw_buf   - (IN) Hw buffer.
   4764  *     opaque_tag_type - (OUT) BCM_PKT_FORMAT_LB_TYPE_XXX
   4765  * Returns:
   4766  *     BCM_E_XXX
   4767  */
   4768 STATIC int
   4769 bcmi_xgs4_udf_tcam_entry_opaque_tag_type_parse(int unit, uint32 *hw_buf,
   4770                                           bcm_udf_pkt_format_info_t *pkt_fmt)
   4771 {
   4772     soc_mem_t tcam_mem = UDF_CTRL(unit)->tcam_mem;  /* UDF_TCAM memory   */
   4773 
   4774     /* Input parameters check. */
   4775     BCM_IF_NULL_RETURN_PARAM(hw_buf);
   4776     BCM_IF_NULL_RETURN_PARAM(pkt_fmt);
   4777 
   4778 
   4779     pkt_fmt->opaque_tag_type = soc_mem_field32_get(unit, tcam_mem, hw_buf,
   4780                                                    OPAQUE_TAG_TYPEf);
   4781     pkt_fmt->opaque_tag_type_mask = soc_mem_field32_get(unit, tcam_mem, hw_buf,
   4782                                                         OPAQUE_TAG_TYPE_MASKf);
   4783 
   4784     return (BCM_E_NONE);
   4785 
   4786 }
   4787 
   4788 /*
   4789  * Function:
   4790  *     bcmi_xgs4_udf_tcam_entry_src_port_parse
   4791  * Purpose:
   4792  *     Parse udf tcam entry loopback pkt type match key.
   4793  * Parameters:
   4794  *     unit     - (IN) BCM device number.
   4795  *     hw_buf   - (IN) Hw buffer.
   4796  *     src_port - (OUT) BCM_PKT_FORMAT_LB_TYPE_XXX
   4797  * Returns:
   4798  *     BCM_E_XXX
   4799  */
   4800 STATIC int
   4801 bcmi_xgs4_udf_tcam_entry_src_port_parse(int unit, uint32 *hw_buf,
   4802                                           bcm_udf_pkt_format_info_t *pkt_fmt)
   4803 {
   4804     soc_mem_t tcam_mem = UDF_CTRL(unit)->tcam_mem;  /* UDF_TCAM memory   */
   4805 
   4806     /* Input parameters check. */
   4807     BCM_IF_NULL_RETURN_PARAM(hw_buf);
   4808     BCM_IF_NULL_RETURN_PARAM(pkt_fmt);
   4809 
   4810     pkt_fmt->src_port = soc_mem_field32_get(unit, tcam_mem, hw_buf,
   4811                                             SOURCE_PORT_NUMBERf);
   4812     pkt_fmt->src_port_mask = soc_mem_field32_get(unit, tcam_mem, hw_buf,
   4813                                              SOURCE_PORT_NUMBER_MASKf);
   4814 
   4815     return (BCM_E_NONE);
   4816 
   4817 
   4818 }
   4819 
   4820 /*
   4821  * Function:
   4822  *     bcmi_xgs4_udf_tcam_entry_parse
   4823  * Purpose:
   4824  *     Parse udf tcam entry key to packet format info
   4825  * Parameters:
   4826  *     unit     - (IN) BCM device number.
   4827  *     hw_buf   - (IN) Hw buffer.
   4828  *     pkt_fmt  - (OUT) Packet format to be filled in.
   4829  * Returns:
   4830  *     BCM_E_XXX
   4831  */
   4832 
   4833 STATIC int
   4834 bcmi_xgs4_udf_tcam_entry_parse(int unit, uint32 *hw_buf,
   4835                                bcm_udf_pkt_format_info_t *pkt_fmt)
   4836 {
   4837     int rv;
   4838     soc_mem_t tcam_mem = UDF_CTRL(unit)->tcam_mem;  /* UDF_TCAM memory   */
   4839 
   4840     /* Input parameters check. */
   4841     BCM_IF_NULL_RETURN_PARAM(hw_buf);
   4842 
   4843     bcm_udf_pkt_format_info_t_init(pkt_fmt);
   4844 
   4845     /* If entry not valid, return empty pkt_format. */
   4846     if (!soc_mem_field32_get(unit, tcam_mem, hw_buf, VALIDf)) {
   4847         return (BCM_E_NONE);
   4848     }
   4849 
   4850     /* Parse vlan_tag format.*/
   4851     rv = bcmi_xgs4_udf_tcam_entry_vlanformat_parse(unit, hw_buf, pkt_fmt);
   4852     BCM_IF_ERROR_RETURN(rv);
   4853 
   4854     /* Parse l2 format.*/
   4855     rv = bcmi_xgs4_udf_tcam_entry_l2format_parse(unit, hw_buf, pkt_fmt);
   4856     BCM_IF_ERROR_RETURN(rv);
   4857 
   4858     /* Parse l3 fields.*/
   4859     rv = bcmi_xgs4_udf_tcam_entry_l3_parse(unit, hw_buf, pkt_fmt);
   4860     BCM_IF_ERROR_RETURN(rv);
   4861 
   4862     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_HIGIG) {
   4863        rv = bcmi_xgs4_udf_tcam_entry_misc_parse(unit, bcmiUdfPktFormatHigig,
   4864                                              hw_buf, (uint16 *)&pkt_fmt->higig);
   4865        BCM_IF_ERROR_RETURN(rv);
   4866     }
   4867 
   4868     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_VNTAG) {
   4869        rv = bcmi_xgs4_udf_tcam_entry_misc_parse(unit, bcmiUdfPktFormatVntag,
   4870                                              hw_buf, (uint16 *)&pkt_fmt->vntag);
   4871        BCM_IF_ERROR_RETURN(rv);
   4872     }
   4873 
   4874     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_ETAG) {
   4875        rv = bcmi_xgs4_udf_tcam_entry_misc_parse(unit, bcmiUdfPktFormatEtag,
   4876                                              hw_buf, (uint16 *)&pkt_fmt->etag);
   4877        BCM_IF_ERROR_RETURN(rv);
   4878     }
   4879 
   4880     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_CNTAG) {
   4881        rv = bcmi_xgs4_udf_tcam_entry_misc_parse(unit, bcmiUdfPktFormatCntag,
   4882                                              hw_buf, (uint16 *)&pkt_fmt->cntag);
   4883        BCM_IF_ERROR_RETURN(rv);
   4884     }
   4885 
   4886     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_ICNM) {
   4887        rv = bcmi_xgs4_udf_tcam_entry_misc_parse(unit, bcmiUdfPktFormatIcnm,
   4888                                              hw_buf, (uint16 *)&pkt_fmt->icnm);
   4889        BCM_IF_ERROR_RETURN(rv);
   4890     }
   4891 
   4892     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_SUBPORT_TAG) {
   4893        rv = bcmi_xgs4_udf_tcam_entry_misc_parse(unit, bcmiUdfPktFormatSubportTag,
   4894                                              hw_buf, (uint16 *)&pkt_fmt->subport_tag);
   4895        BCM_IF_ERROR_RETURN(rv);
   4896     }
   4897 
   4898     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_INT_PKT) {
   4899        rv = bcmi_xgs4_udf_tcam_entry_misc_parse(unit, bcmiUdfPktFormatIntPkt,
   4900                                                 hw_buf, (uint16 *)&pkt_fmt->int_pkt);
   4901        BCM_IF_ERROR_RETURN(rv);
   4902     }
   4903 
   4904     /* Parse lb_pkt_type fields.*/
   4905     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_LB_PKT_TYPE) {
   4906        rv = bcmi_xgs4_udf_tcam_entry_lb_pkt_type_parse(unit, hw_buf, pkt_fmt);
   4907        BCM_IF_ERROR_RETURN(rv);
   4908     }
   4909 
   4910     /* Parse l4_dst_port fields.*/
   4911     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_L4_DST_PORT) {
   4912        rv = bcmi_xgs4_udf_tcam_entry_l4_dst_port_parse(unit, hw_buf, pkt_fmt);
   4913        BCM_IF_ERROR_RETURN(rv);
   4914     }
   4915 
   4916     /* Parse opaque_tag_type fields.*/
   4917     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_OPAQUE_TAG_TYPE) {
   4918        rv = bcmi_xgs4_udf_tcam_entry_opaque_tag_type_parse(unit, hw_buf, pkt_fmt);
   4919        BCM_IF_ERROR_RETURN(rv);
   4920     }
   4921 
   4922     /* Parse src_port fields.*/
   4923     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_SRC_PORT) {
   4924        rv = bcmi_xgs4_udf_tcam_entry_src_port_parse(unit, hw_buf, pkt_fmt);
   4925        BCM_IF_ERROR_RETURN(rv);
   4926     }
   4927 
   4928     return (BCM_E_NONE);
   4929 }
   4930 
   4931 /* Parse ethertype and mask from pkt_format to hw_buf */
   4932 STATIC int
   4933 bcmi_xgs4_udf_tcam_ethertype_init(int unit,
   4934         bcm_udf_pkt_format_info_t *pkt_format, uint32 *hw_buf)
   4935 {
   4936     soc_mem_t mem;
   4937     bcm_ethertype_t ethertype;
   4938     bcm_ethertype_t ethertype_mask;
   4939 
   4940     mem = UDF_CTRL(unit)->tcam_mem;
   4941 
   4942     if (pkt_format->ethertype_mask != 0) {
   4943         ethertype = soc_mem_field32_get(unit, mem,
   4944                                         hw_buf, L2_ETHER_TYPEf);
   4945         ethertype_mask = soc_mem_field32_get(unit, mem,
   4946                                              hw_buf, L2_ETHER_TYPE_MASKf);
   4947 
   4948         if ((ethertype_mask != 0) &&
   4949             ((ethertype & ethertype_mask) !=
   4950              (pkt_format->ethertype & pkt_format->ethertype_mask))) {
   4951             return BCM_E_CONFIG;
   4952         } else {
   4953             soc_mem_field32_set(unit, mem, hw_buf,
   4954                                L2_ETHER_TYPEf, pkt_format->ethertype);
   4955             soc_mem_field32_set(unit, mem, hw_buf,
   4956                                L2_ETHER_TYPE_MASKf, pkt_format->ethertype_mask);
   4957         }
   4958     }
   4959 
   4960     return BCM_E_NONE;
   4961 }
   4962 
   4963 /* Parse l4_dst_port and mask from pkt_format to hw_buf */
   4964 STATIC int
   4965 bcmi_xgs4_udf_tcam_entry_l4_dst_port_init(int unit,
   4966         bcm_udf_pkt_format_info_t *pkt_format, uint32 *hw_buf)
   4967 {
   4968     soc_mem_t mem;
   4969     uint32 l4_dst_port;
   4970     uint32 l4_dst_port_mask;
   4971 
   4972     mem = UDF_CTRL(unit)->tcam_mem;
   4973 
   4974     if (pkt_format->l4_dst_port_mask != 0) {
   4975         l4_dst_port = soc_mem_field32_get(unit, mem,
   4976                                         hw_buf, L4_DST_PORTf);
   4977         l4_dst_port_mask = soc_mem_field32_get(unit, mem,
   4978                                              hw_buf, L4_DST_PORT_MASKf);
   4979 
   4980         if ((l4_dst_port_mask != 0) &&
   4981             ((l4_dst_port & l4_dst_port_mask) !=
   4982              (pkt_format->l4_dst_port & pkt_format->l4_dst_port_mask))) {
   4983             return BCM_E_CONFIG;
   4984         } else {
   4985             soc_mem_field32_set(unit, mem, hw_buf,
   4986                                L4_DST_PORTf, pkt_format->l4_dst_port);
   4987             soc_mem_field32_set(unit, mem, hw_buf,
   4988                                L4_DST_PORT_MASKf, pkt_format->l4_dst_port_mask);
   4989         }
   4990     }
   4991 
   4992     return BCM_E_NONE;
   4993 }
   4994 
   4995 /* Parse opaque_tag_type and mask from pkt_format to hw_buf */
   4996 STATIC int
   4997 bcmi_xgs4_udf_tcam_entry_opaque_tag_type_init(int unit,
   4998         bcm_udf_pkt_format_info_t *pkt_format, uint32 *hw_buf)
   4999 {
   5000     soc_mem_t mem;
   5001     uint8 opaque_tag_type;
   5002     uint8 opaque_tag_type_mask;
   5003 
   5004     mem = UDF_CTRL(unit)->tcam_mem;
   5005 
   5006     if (pkt_format->opaque_tag_type_mask != 0) {
   5007         opaque_tag_type = soc_mem_field32_get(unit, mem,
   5008                                         hw_buf, OPAQUE_TAG_TYPEf);
   5009         opaque_tag_type_mask = soc_mem_field32_get(unit, mem,
   5010                                              hw_buf, OPAQUE_TAG_TYPE_MASKf);
   5011 
   5012         if ((opaque_tag_type_mask != 0) &&
   5013             ((opaque_tag_type & opaque_tag_type_mask) !=
   5014              (pkt_format->opaque_tag_type & pkt_format->opaque_tag_type_mask))) {
   5015             return BCM_E_CONFIG;
   5016         } else {
   5017             soc_mem_field32_set(unit, mem, hw_buf,
   5018                                OPAQUE_TAG_TYPEf, pkt_format->opaque_tag_type);
   5019             soc_mem_field32_set(unit, mem, hw_buf,
   5020                                OPAQUE_TAG_TYPE_MASKf, pkt_format->opaque_tag_type_mask);
   5021         }
   5022     }
   5023 
   5024     return BCM_E_NONE;
   5025 }
   5026 
   5027 /* Parse src_port and mask from pkt_format to hw_buf */
   5028 STATIC int
   5029 bcmi_xgs4_udf_tcam_entry_src_port_init(int unit,
   5030         bcm_udf_pkt_format_info_t *pkt_format, uint32 *hw_buf)
   5031 {
   5032     soc_mem_t mem;
   5033     uint8 src_port;
   5034     uint8 src_port_mask;
   5035 
   5036     mem = UDF_CTRL(unit)->tcam_mem;
   5037 
   5038     if (pkt_format->src_port_mask != 0) {
   5039         src_port = soc_mem_field32_get(unit, mem,
   5040                                         hw_buf, SOURCE_PORT_NUMBERf);
   5041         src_port_mask = soc_mem_field32_get(unit, mem,
   5042                                              hw_buf, SOURCE_PORT_NUMBER_MASKf);
   5043 
   5044         if ((src_port_mask != 0) &&
   5045             ((src_port & src_port_mask) !=
   5046              (pkt_format->src_port & pkt_format->src_port_mask))) {
   5047             return BCM_E_CONFIG;
   5048         } else {
   5049             soc_mem_field32_set(unit, mem, hw_buf,
   5050                                SOURCE_PORT_NUMBERf, pkt_format->src_port);
   5051             soc_mem_field32_set(unit, mem, hw_buf,
   5052                                SOURCE_PORT_NUMBER_MASKf, pkt_format->src_port_mask);
   5053         }
   5054     }
   5055 
   5056     return BCM_E_NONE;
   5057 }
   5058 
   5059 
   5060 /*
   5061  * Function:
   5062  *     bcmi_xgs4_udf_tcam_entry_lb_pkt_type_init
   5063  * Purpose:
   5064  *     Initialize udf tcam entry loopback packet type match key.
   5065  * Parameters:
   5066  *     unit     - (IN) BCM device number.
   5067  *     l2format - (IN) BCM_PKT_FORMAT_LB_TYPE_XXX
   5068  *     hw_buf   - (OUT) Hw buffer.
   5069  * Returns:
   5070  *     BCM_E_XXX
   5071  */
   5072 STATIC int
   5073 bcmi_xgs4_udf_tcam_entry_lb_pkt_type_init(int unit,
   5074                                        bcm_udf_pkt_format_info_t *pkt_fmt,
   5075                                        uint32 *hw_buf)
   5076 {
   5077     uint16 type = pkt_fmt->lb_pkt_type;
   5078     soc_mem_t tcam_mem = UDF_CTRL(unit)->tcam_mem;  /* UDF_TCAM memory   */
   5079 
   5080     /* Input parameters check. */
   5081     BCM_IF_NULL_RETURN_PARAM(hw_buf);
   5082     BCM_IF_NULL_RETURN_PARAM(pkt_fmt);
   5083 
   5084     /* Translate L2 flag bits to index */
   5085     switch (type) {
   5086       case BCM_PKT_FORMAT_LB_TYPE_MIM:
   5087           /* L2 Format . */
   5088           if (SOC_IS_TOMAHAWK3(unit)) {
   5089               return (BCM_E_PARAM);
   5090           } else {
   5091               soc_mem_field32_set(unit, tcam_mem, hw_buf,
   5092                                   LOOPBACK_PKT_TYPEf, 1);
   5093               soc_mem_field32_set(unit, tcam_mem, hw_buf,
   5094                                   LOOPBACK_PKT_TYPE_MASKf, 0x3);
   5095           }
   5096           break;
   5097       case BCM_PKT_FORMAT_LB_TYPE_GENERIC:
   5098           /* L2 Format . */
   5099           if (SOC_IS_TOMAHAWK3(unit)) {
   5100               soc_mem_field32_set(unit, tcam_mem, hw_buf,
   5101                                   LOOPBACK_PKT_TYPEf, 1);
   5102               soc_mem_field32_set(unit, tcam_mem, hw_buf,
   5103                                   LOOPBACK_PKT_TYPE_MASKf, 0x3);
   5104           } else {
   5105               return (BCM_E_PARAM);
   5106           }
   5107           break;
   5108       case BCM_PKT_FORMAT_LB_TYPE_ANY:
   5109           soc_mem_field32_set(unit, tcam_mem, hw_buf,
   5110                               LOOPBACK_PKT_TYPEf, 0);
   5111           soc_mem_field32_set(unit, tcam_mem, hw_buf,
   5112                               LOOPBACK_PKT_TYPE_MASKf, 0);
   5113 
   5114           break;
   5115       default:
   5116           return (BCM_E_PARAM);
   5117     }
   5118     return (BCM_E_NONE);
   5119 }
   5120 
   5121 /*
   5122  * Function:
   5123  *      _field_trx2_data_qualifier_etype_tcam_key_init
   5124  * Purpose:
   5125  *      Initialize ethertype based udf tcam entry.
   5126  * Parameters:
   5127  *      unit       - (IN) bcm device.
   5128  *      pkt_format - (IN) Packet format info
   5129  *      hw_buf     - (OUT) Hardware buffer.
   5130  * Returns:
   5131  *      BCM_E_XXX
   5132  */
   5133 STATIC int
   5134 bcmi_xgs4_udf_pkt_format_tcam_key_init(int unit,
   5135                                        bcm_udf_pkt_format_info_t *pkt_format,
   5136                                        uint32 *hw_buf)
   5137 {
   5138     int rv;
   5139     soc_mem_t tcam_mem = UDF_CTRL(unit)->tcam_mem;  /* UDF_TCAM memory   */
   5140 
   5141     /* Input parameters check. */
   5142     BCM_IF_NULL_RETURN_PARAM(hw_buf);
   5143     BCM_IF_NULL_RETURN_PARAM(pkt_format);
   5144 
   5145     /* Set valid bit. */
   5146     soc_mem_field32_set(unit, tcam_mem, hw_buf, VALIDf, 1);
   5147 
   5148     /* Set l2 format. */
   5149     rv = bcmi_xgs4_udf_tcam_entry_l2format_init(unit, pkt_format, hw_buf);
   5150     BCM_IF_ERROR_RETURN(rv);
   5151 
   5152     /* Set vlan tag format. */
   5153     rv = bcmi_xgs4_udf_tcam_entry_vlanformat_init(unit, pkt_format, hw_buf);
   5154     BCM_IF_ERROR_RETURN(rv);
   5155 
   5156     /* Set l3 packet format. */
   5157     rv = bcmi_xgs4_udf_tcam_entry_l3_init(unit, pkt_format, hw_buf);
   5158     BCM_IF_ERROR_RETURN(rv);
   5159 
   5160     /* Set HiGig packet formats */
   5161     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_HIGIG) {
   5162         rv = bcmi_xgs4_udf_tcam_entry_misc_init(unit, bcmiUdfPktFormatHigig,
   5163                                                 pkt_format->higig, hw_buf);
   5164         BCM_IF_ERROR_RETURN(rv);
   5165     }
   5166 
   5167     /* Set VNTAG packet formats */
   5168     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_VNTAG) {
   5169         rv = bcmi_xgs4_udf_tcam_entry_misc_init(unit, bcmiUdfPktFormatVntag,
   5170                                                 pkt_format->vntag, hw_buf);
   5171         BCM_IF_ERROR_RETURN(rv);
   5172     }
   5173 
   5174     /* Set ETAG packet formats */
   5175     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_ETAG) {
   5176         rv = bcmi_xgs4_udf_tcam_entry_misc_init(unit, bcmiUdfPktFormatEtag,
   5177                                                 pkt_format->etag, hw_buf);
   5178         BCM_IF_ERROR_RETURN(rv);
   5179     }
   5180 
   5181     /* Set CNTAG packet formats */
   5182     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_CNTAG) {
   5183         rv = bcmi_xgs4_udf_tcam_entry_misc_init(unit, bcmiUdfPktFormatCntag,
   5184                                                 pkt_format->cntag, hw_buf);
   5185         BCM_IF_ERROR_RETURN(rv);
   5186     }
   5187 
   5188     /* Set ICNM packet formats */
   5189     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_ICNM) {
   5190         rv = bcmi_xgs4_udf_tcam_entry_misc_init(unit, bcmiUdfPktFormatIcnm,
   5191                                                pkt_format->icnm, hw_buf);
   5192         BCM_IF_ERROR_RETURN(rv);
   5193     }
   5194 
   5195     /* Set Subport tag packet formats */
   5196     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_SUBPORT_TAG) {
   5197         rv = bcmi_xgs4_udf_tcam_entry_misc_init(unit, bcmiUdfPktFormatSubportTag,
   5198                                                 pkt_format->subport_tag, hw_buf);
   5199         BCM_IF_ERROR_RETURN(rv);
   5200     }
   5201 
   5202     /* Set Inband Telemetry Pkt packet formats */
   5203     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_INT_PKT) {
   5204         rv = bcmi_xgs4_udf_tcam_entry_misc_init(unit, bcmiUdfPktFormatIntPkt,
   5205                                                 pkt_format->int_pkt, hw_buf);
   5206         BCM_IF_ERROR_RETURN(rv);
   5207     }
   5208 
   5209     /* Set L4 Dst Port packet formats */
   5210     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_L4_DST_PORT) {
   5211         rv = bcmi_xgs4_udf_tcam_entry_l4_dst_port_init(unit, pkt_format, hw_buf);
   5212         BCM_IF_ERROR_RETURN(rv);
   5213     }
   5214 
   5215     /* Set Opaque Tag Type packet formats */
   5216     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_OPAQUE_TAG_TYPE) {
   5217         rv = bcmi_xgs4_udf_tcam_entry_opaque_tag_type_init(unit, pkt_format, hw_buf);
   5218         BCM_IF_ERROR_RETURN(rv);
   5219     }
   5220 
   5221 
   5222     /* Set Source Port packet formats */
   5223     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_SRC_PORT) {
   5224         rv = bcmi_xgs4_udf_tcam_entry_src_port_init(unit, pkt_format, hw_buf);
   5225         BCM_IF_ERROR_RETURN(rv);
   5226     }
   5227 
   5228     /* Set Loopback Packet Type packet formats */
   5229     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_LB_PKT_TYPE) {
   5230         rv = bcmi_xgs4_udf_tcam_entry_lb_pkt_type_init(unit, pkt_format, hw_buf);
   5231         BCM_IF_ERROR_RETURN(rv);
   5232     }
   5233 
   5234 
   5235     rv = bcmi_xgs4_udf_tcam_ethertype_init(unit, pkt_format, hw_buf);
   5236     BCM_IF_ERROR_RETURN(rv);
   5237 
   5238     return (rv);
   5239 }
   5240 
   5241 /*
   5242  * Function:
   5243  *      bcmi_xgs4_udf_offset_node_get
   5244  * Purpose:
   5245  *      Fetches UDF offset node given udf id.
   5246  * Parameters:
   5247  *      unit            - (IN)      Unit number.
   5248  *      udf_id          - (IN)      UDF Id.
   5249  *      offset_info     - (INOUT)   Fecthed udf offset info.
   5250  * Returns:
   5251  *      BCM_E_XXX
   5252  * Notes:
   5253  */
   5254 int
   5255 bcmi_xgs4_udf_offset_node_get(int unit, bcm_udf_id_t udf_id,
   5256                               bcmi_xgs4_udf_offset_info_t **cur)
   5257 {
   5258     bcmi_xgs4_udf_offset_info_t *tmp;
   5259 
   5260     tmp = UDF_CTRL(unit)->offset_info_head;
   5261 
   5262     while (tmp != NULL) {
   5263         if (tmp->udf_id == udf_id) {
   5264             break;
   5265         }
   5266         tmp = tmp->next;
   5267     }
   5268 
   5269     /* Reached end of the list */
   5270     if (tmp == NULL) {
   5271         *cur = NULL;
   5272         return BCM_E_NOT_FOUND;
   5273     }
   5274 
   5275     *cur = tmp;
   5276 
   5277     return BCM_E_NONE;
   5278 }
   5279 
   5280 
   5281 /*
   5282  * Function:
   5283  *      bcmi_xgs4_udf_tcam_node_get
   5284  * Purpose:
   5285  *      Fetches UDF tcam node given packet format id.
   5286  * Parameters:
   5287  *      unit            - (IN)      Unit number.
   5288  *      pkt_format_id   - (IN)      UDF Packet format Id.
   5289  *      offset_info     - (INOUT)   Fecthed udf tcam info.
   5290  * Returns:
   5291  *      BCM_E_XXX
   5292  * Notes:
   5293  */
   5294 int
   5295 bcmi_xgs4_udf_tcam_node_get(int unit,
   5296                             bcm_udf_pkt_format_id_t pkt_format_id,
   5297                             bcmi_xgs4_udf_tcam_info_t **cur)
   5298 {
   5299     bcmi_xgs4_udf_tcam_info_t *tmp;
   5300 
   5301     tmp = UDF_CTRL(unit)->tcam_info_head;
   5302 
   5303     while (tmp != NULL) {
   5304         if (tmp->pkt_format_id == pkt_format_id) {
   5305             break;
   5306         }
   5307         tmp = tmp->next;
   5308     }
   5309 
   5310     /* Reached end of the list */
   5311     if (tmp == NULL) {
   5312         *cur = NULL;
   5313         return BCM_E_NOT_FOUND;
   5314     }
   5315 
   5316     *cur = tmp;
   5317 
   5318     return BCM_E_NONE;
   5319 }
   5320 
   5321 /*
   5322  * Function:
   5323  *      bcmi_xgs4_udf_detach
   5324  * Purpose:
   5325  *      Detaches udf module and cleans software state.
   5326  * Parameters:
   5327  *      unit            - (IN)      Unit number.
   5328  * Returns:
   5329  *      BCM_E_XXX
   5330  * Notes:
   5331  */
   5332 int
   5333 bcmi_xgs4_udf_detach(int unit)
   5334 {
   5335     UDF_INIT_CHECK(unit);
   5336 
   5337     /* Free resources related to UDF module */
   5338     BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_ctrl_free(unit, UDF_CTRL(unit)));
   5339 
   5340     /* Reset udf module init state */
   5341 
   5342     return BCM_E_NONE;
   5343 }
   5344 
   5345 /*
   5346  * Function:
   5347  *      bcmi_xgs4_udf_init
   5348  * Purpose:
   5349  *      initializes/ReInitializes the UDF module.
   5350  * Parameters:
   5351  *      unit            - (IN)      Unit number.
   5352  * Returns:
   5353  *      BCM_E_XXX
   5354  * Notes:
   5355  */
   5356 int
   5357 bcmi_xgs4_udf_init(int unit)
   5358 {
   5359     int rv;
   5360 
   5361 #if defined (BCM_TOMAHAWK_SUPPORT)
   5362         if (soc_feature(unit, soc_feature_udf_multi_pipe_support)) {
   5363             bcmi_xgs4_udf_oper_mode[unit] = bcmUdfOperModeGlobal;
   5364         }
   5365 #endif
   5366 
   5367     /* Init control structures */
   5368     rv = bcmi_xgs4_udf_ctrl_init(unit);
   5369     BCM_IF_ERROR_RETURN(rv);
   5370 
   5371 #if defined (BCM_WARM_BOOT_SUPPORT)
   5372     if (SOC_WARM_BOOT(unit)) {
   5373         rv = bcmi_xgs4_udf_reinit(unit);
   5374         BCM_IF_ERROR_RETURN(rv);
   5375     } else
   5376 #endif /* BCM_WARM_BOOT_SUPPORT */
   5377     {
   5378         rv = bcmi_xgs4_udf_hw_init(unit);
   5379         BCM_IF_ERROR_RETURN(rv);
   5380 
   5381 #if defined (BCM_WARM_BOOT_SUPPORT)
   5382         rv = bcmi_xgs4_udf_wb_alloc(unit);
   5383         BCM_IF_ERROR_RETURN(rv);
   5384 #endif /* BCM_WARM_BOOT_SUPPORT */
   5385 
   5386     }
   5387 
   5388     return BCM_E_NONE;
   5389 }
   5390 
   5391 /* To sanitize udf_info/pkt_format_info input structures */
   5392 STATIC int
   5393 bcmi_xgs4_udf_sanitize_inputs(int unit, bcm_udf_t *udf_info,
   5394                               bcm_udf_alloc_hints_t *hints,
   5395                               bcm_udf_pkt_format_info_t *pkt_format)
   5396 {
   5397 #if defined (BCM_TOMAHAWK_SUPPORT)
   5398         int port_count = 0, port = 0, first_pipe = BCMI_XGS4_UDF_INVALID_PIPE_NUM;
   5399         soc_info_t  *si;
   5400         si = &SOC_INFO(unit);
   5401 #endif
   5402 
   5403     if (udf_info != NULL) {
   5404 
   5405         /* start and width should be at byte boundary */
   5406         if (((udf_info->start % 8) != 0) || ((udf_info->width % 8) != 0)) {
   5407             return BCM_E_PARAM;
   5408         }
   5409 
   5410         /* start and width should be less than max byte selection */
   5411         if (BITS2BYTES(udf_info->start + udf_info->width) >
   5412             UDF_CTRL(unit)->max_parse_bytes) {
   5413             return BCM_E_PARAM;
   5414         }
   5415 
   5416         /* flags in udf_info is currently not used; must be 0 */
   5417         if (udf_info->flags != 0) {
   5418             return BCM_E_PARAM;
   5419         }
   5420 
   5421         /* check if layer is in known range */
   5422         if ((udf_info->layer < bcmUdfLayerL2Header) ||
   5423             (udf_info->layer >= bcmUdfLayerCount)) {
   5424             return BCM_E_PARAM;
   5425         }
   5426 
   5427         
   5428         if (udf_info->layer == bcmUdfLayerUserPayload) {
   5429             return BCM_E_PARAM;
   5430         }
   5431 
   5432 #if defined (BCM_TOMAHAWK_SUPPORT)
   5433         /* get the pipe where the entry will be configured */
   5434         if (soc_feature(unit, soc_feature_udf_multi_pipe_support) &&
   5435            (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) {
   5436 
   5437             BCM_PBMP_COUNT(udf_info->ports, port_count);
   5438             if (port_count == 0) {
   5439                 return BCM_E_PARAM;
   5440             }
   5441 
   5442             SOC_PBMP_ITER(udf_info->ports, port) {
   5443                 if (first_pipe == BCMI_XGS4_UDF_INVALID_PIPE_NUM ) {
   5444                     first_pipe =  si->port_pipe[port];
   5445                 } else if (first_pipe != si->port_pipe[port]) {
   5446                     return BCM_E_PARAM;
   5447                 }
   5448             }
   5449         }
   5450 #endif
   5451     }
   5452 
   5453     if (hints != NULL) {
   5454         /* check if chip support flex hash */
   5455         if ((hints->flags & BCM_UDF_CREATE_O_FLEXHASH) &&
   5456             (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_FLEXHASH))) {
   5457             return BCM_E_PARAM;
   5458         }
   5459         /* check if chip support policer group */
   5460         if ((hints->flags & BCM_UDF_CREATE_O_POLICER_GROUP) &&
   5461             (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_POLICER_GROUP))) {
   5462             return BCM_E_PARAM;
   5463         }
   5464         /* check if chip support udf hash */
   5465         if ((hints->flags & BCM_UDF_CREATE_O_UDFHASH) &&
   5466             (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_UDFHASH))) {
   5467             return BCM_E_PARAM;
   5468         }
   5469         /* check create udf if withid is used together with replace*/
   5470         if (((hints->flags & BCM_UDF_CREATE_O_WITHID) &&
   5471             !(hints->flags & BCM_UDF_CREATE_O_REPLACE)) ||
   5472             (!(hints->flags & BCM_UDF_CREATE_O_WITHID) &&
   5473             (hints->flags & BCM_UDF_CREATE_O_REPLACE))) {
   5474             return BCM_E_PARAM;
   5475         }
   5476         /* shared udf id should be valid */
   5477         if ((hints->flags & BCM_UDF_CREATE_O_SHARED_HWID) &&
   5478             ((hints->shared_udf < BCMI_XGS4_UDF_ID_MIN) ||
   5479              (hints->shared_udf > BCMI_XGS4_UDF_ID_MAX))) {
   5480             return BCM_E_PARAM;
   5481         }
   5482         /* check if chip supports Range Check */
   5483         if ((hints->flags & BCM_UDF_CREATE_O_RANGE_CHECK) &&
   5484            (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_RANGE_CHECK))) {
   5485             return BCM_E_PARAM;
   5486         }
   5487         /* check if chip support flex counter */
   5488         if ((hints->flags & BCM_UDF_CREATE_O_FLEX_COUNTER) &&
   5489             (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_FLEX_COUNTER))) {
   5490             return BCM_E_PARAM;
   5491         }
   5492     }
   5493 
   5494     if (pkt_format != NULL) {
   5495 
   5496         if ((pkt_format->prio < 0) || (pkt_format->prio > 0xffff)) {
   5497             /* Soft restriction - prio maintained as 'short' integer */
   5498             return BCM_E_PARAM;
   5499         }
   5500         if ((!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_HIGIG) &&
   5501              (pkt_format->higig > 0)) ||
   5502              (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_VNTAG) &&
   5503              (pkt_format->vntag > 0)) ||
   5504              (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_ETAG) &&
   5505              (pkt_format->etag > 0)) ||
   5506              (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_ICNM) &&
   5507              (pkt_format->icnm > 0)) ||
   5508              (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_CNTAG) &&
   5509              (pkt_format->cntag > 0)) ||
   5510              (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_TCAM_SUBPORT_TAG) &&
   5511              (pkt_format->subport_tag > 0)) ||
   5512              (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_L4_DST_PORT) &&
   5513              (pkt_format->l4_dst_port > 0)) ||
   5514              (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_OPAQUE_TAG_TYPE) &&
   5515              (pkt_format->opaque_tag_type > 0)) ||
   5516              (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_INT_PKT) &&
   5517              (pkt_format->int_pkt > 0)) ||
   5518              (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_SRC_PORT) &&
   5519              (pkt_format->src_port > 0)) ||
   5520              (!(UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_CTRL_LB_PKT_TYPE) &&
   5521              (pkt_format->lb_pkt_type > 0))) {
   5522             return BCM_E_UNAVAIL;
   5523         }
   5524 #if defined (BCM_TOMAHAWK_SUPPORT)
   5525         if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_PKT_FORMAT_CLASS_ID) {
   5526             if ((pkt_format->class_id < 0) || (pkt_format->class_id > 255)) {
   5527                 return BCM_E_PARAM;
   5528             }
   5529         }
   5530 #endif
   5531     }
   5532 
   5533     return BCM_E_NONE;
   5534 }
   5535 
   5536 /*
   5537  * Function:
   5538  *      bcm_udf_create
   5539  * Purpose:
   5540  *      Creates a UDF object
   5541  * Parameters:
   5542  *      unit - (IN) Unit number.
   5543  *      hints - (IN) Hints to UDF allocator
   5544  *      udf_info - (IN) UDF structure
   5545  *      udf_id - (IN/OUT) UDF ID
   5546  * Returns:
   5547  *      BCM_E_NONE          UDF created successfully.
   5548  *      BCM_E_EXISTS        Entry already exists.
   5549  *      BCM_E_FULL          UDF table full.
   5550  *      BCM_E_UNIT          Invalid BCM Unit number.
   5551  *      BCM_E_INIT          UDF module not initialized.
   5552  *      BCM_E_UNAVAIL       Feature not supported.
   5553  *      BCM_E_XXX           Standard error code.
   5554  * Notes:
   5555  */
   5556 int
   5557 bcmi_xgs4_udf_create(
   5558     int unit,
   5559     bcm_udf_alloc_hints_t *hints,
   5560     bcm_udf_t *udf_info,
   5561     bcm_udf_id_t *udf_id)
   5562 {
   5563     int i;
   5564     int gran;
   5565     int max_chunks;
   5566     int id_running_allocated = 0;
   5567     int rv = BCM_E_NONE;
   5568     bcmi_xgs4_udf_offset_info_t *offset_del = NULL;
   5569     bcmi_xgs4_udf_offset_info_t *offset_info = NULL;
   5570     bcmi_xgs4_udf_offset_entry_t *offset_entry_array;
   5571     uint32 offset[MAX_UDF_OFFSET_CHUNKS] = {0};
   5572 
   5573     /* UDF Module Init check */
   5574     UDF_INIT_CHECK(unit);
   5575 
   5576     /* NULL check; hints can be NULL */
   5577     BCM_IF_NULL_RETURN_PARAM(udf_id);
   5578     BCM_IF_NULL_RETURN_PARAM(udf_info);
   5579 
   5580     gran = BCMI_XGS4_UDF_CTRL_OFFSET_GRAN(unit);
   5581 
   5582     /* Sanitize input parameters */
   5583     rv = bcmi_xgs4_udf_sanitize_inputs(unit, udf_info, hints, NULL);
   5584     BCM_IF_ERROR_RETURN(rv);
   5585 
   5586     /* UDF Module Lock */
   5587     UDF_LOCK(unit);
   5588 
   5589     if (UDF_CTRL(unit)->udf_used_by_module == UDF_USED_BY_FIELD_MODULE) {
   5590         LOG_CLI((BSL_META("Udf resource is used by FIELD module. \n")));
   5591         UDF_UNLOCK(unit);
   5592         return BCM_E_RESOURCE;
   5593     }
   5594 
   5595     max_chunks = BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit);
   5596 
   5597     /* Check if similar entry already existing */
   5598     if ((hints != NULL) && (hints->flags & BCM_UDF_CREATE_O_WITHID)) {
   5599 
   5600         UDF_ID_VALIDATE_UNLOCK(unit, *udf_id);
   5601 
   5602         /* Fetch the udf offset info;  get should be successful */
   5603         rv = bcmi_xgs4_udf_offset_node_get(unit, *udf_id, &offset_info);
   5604 
   5605         if ((BCM_FAILURE(rv)) || (offset_info == NULL)) {
   5606             UDF_UNLOCK(unit);
   5607             return BCM_E_NOT_FOUND;
   5608         }
   5609 
   5610         if ((hints->flags & BCM_UDF_CREATE_O_REPLACE)) {
   5611             if (offset_info->num_pkt_formats >= 1) {
   5612                 /* UDF already in use */
   5613                 UDF_UNLOCK(unit);
   5614                 return BCM_E_CONFIG;
   5615             }
   5616 
   5617             for (i = 0; i < max_chunks; i++) {
   5618                 SHR_BITCOPY_RANGE(&offset[i], 0, &(offset_info->byte_bmap),
   5619                                   i*gran, gran);
   5620             }
   5621 
   5622             /* unreserve the offset chunks */
   5623             rv = bcmi_xgs4_udf_offset_unreserve(unit, max_chunks, (int *)offset,
   5624                                                 offset_info->associated_pipe);
   5625             if (BCM_FAILURE(rv)) {
   5626                 UDF_UNLOCK(unit);
   5627                 return rv;
   5628             }
   5629 
   5630             /* Delete the UDF entry and recreate one */
   5631             rv = bcmi_xgs4_udf_offset_node_delete(unit, *udf_id, &offset_del);
   5632             if (BCM_FAILURE(rv)) {
   5633                 UDF_UNLOCK(unit);
   5634                 return rv;
   5635             }
   5636         } else {
   5637             UDF_UNLOCK(unit);
   5638             return BCM_E_PARAM;
   5639         }
   5640     } else {
   5641         /* Fresh udf creation */
   5642 
   5643         /* Allocate udf id */
   5644         rv = bcmi_xgs4_udf_id_running_id_alloc(unit, bcmiUdfObjectUdf, udf_id);
   5645         if (BCM_FAILURE(rv)) {
   5646             UDF_UNLOCK(unit);
   5647             return rv;
   5648         } else {
   5649             id_running_allocated = 1;
   5650         }
   5651     }
   5652 
   5653     /* Add udf info structure to linked list */
   5654     rv = bcmi_xgs4_udf_offset_info_add(unit, udf_info, &offset_info);
   5655     if ((BCM_FAILURE(rv)) || (offset_info == NULL)) {
   5656         UDF_UNLOCK(unit);
   5657         return BCM_E_MEMORY;
   5658     }
   5659 
   5660     if ((UDF_CTRL(unit)->num_udfs + 1) == UDF_CTRL(unit)->max_udfs) {
   5661         rv = BCM_E_RESOURCE;
   5662     }
   5663     UDF_IF_ERROR_CLEANUP(rv);
   5664 
   5665     offset_entry_array = UDF_CTRL(unit)->offset_entry_array;
   5666 #if defined (BCM_TOMAHAWK_SUPPORT)
   5667     if (soc_feature(unit, soc_feature_udf_multi_pipe_support) &&
   5668        (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) {
   5669         offset_entry_array =
   5670             UDF_CTRL(unit)->offset_entry_array_per_pipe[offset_info->associated_pipe];
   5671     }
   5672 #endif
   5673 
   5674     /* For shared hwid, just copy the hw details */
   5675     if ((hints != NULL) && (hints->flags & BCM_UDF_CREATE_O_SHARED_HWID)) {
   5676         bcmi_xgs4_udf_offset_info_t *offset_shared;
   5677 
   5678         rv = bcmi_xgs4_udf_offset_node_get(unit, hints->shared_udf,
   5679                                            &offset_shared);
   5680         UDF_IF_ERROR_CLEANUP(rv);
   5681 
   5682         /* A shared udf should also should use the same width */
   5683         if (offset_info->width != offset_shared->width) {
   5684             rv = BCM_E_CONFIG;
   5685         }
   5686 
   5687         /* Shared offset should 'start' at the same byte boundary
   5688          * Otherwise the chunks allocated may not suffice the requirement
   5689          */
   5690         if ((offset_info->start % gran) != (offset_shared->start % gran)) {
   5691             rv = BCM_E_CONFIG;
   5692         }
   5693 
   5694         /* In Old devices with gran 4, if base offset is packet start
   5695          * then extra check is need for layer also as bcmUdfLayerL2Header
   5696          * have negative offset adjustment of 2 */
   5697         if (gran == UDF_OFFSET_GRAN4) {
   5698             if (offset_info->start == bcmUdfLayerL2Header) {
   5699                 if (offset_shared->start != bcmUdfLayerL2Header) {
   5700                     rv = BCM_E_CONFIG;
   5701                 }
   5702             } else {
   5703                 if(offset_shared->start == bcmUdfLayerL2Header) {
   5704                     rv = BCM_E_CONFIG;
   5705                 }
   5706             }
   5707         }
   5708 
   5709         UDF_IF_ERROR_CLEANUP(rv);
   5710 
   5711         /* Since shared, copy the same chunk bitmap */
   5712         offset_info->grp_id = offset_shared->grp_id;
   5713         offset_info->hw_bmap = offset_shared->hw_bmap;
   5714         offset_info->byte_bmap = offset_shared->byte_bmap;
   5715         offset_info->byte_offset = offset_shared->byte_offset;
   5716 
   5717         offset_info->flags |= BCMI_XGS4_UDF_OFFSET_INFO_SHARED;
   5718         offset_shared->flags |= BCMI_XGS4_UDF_OFFSET_INFO_SHARED;
   5719 
   5720         /* Mark the entry as shared */
   5721         for (i = 0; i < max_chunks; i ++) {
   5722             if (SHR_BITGET(&(offset_info->hw_bmap), i)) {
   5723                 offset_entry_array[i].grp_id = offset_info->grp_id;
   5724                 offset_entry_array[i].num_udfs += 1;
   5725                 offset_entry_array[i].flags |=
   5726                     BCMI_XGS4_UDF_OFFSET_ENTRY_SHARED;
   5727             }
   5728         }
   5729     } else {
   5730 
   5731         /* allocate udf chunks */
   5732         rv = bcmi_xgs4_udf_offset_hw_alloc(unit, hints, offset_info);
   5733         UDF_IF_ERROR_CLEANUP(rv);
   5734 
   5735     }
   5736 
   5737     /* update udf_id in the offset_info */
   5738     offset_info->udf_id = *udf_id;
   5739 
   5740     if (hints != NULL) {
   5741         if (hints->flags & BCM_UDF_CREATE_O_FLEXHASH) {
   5742             offset_info->flags |= BCMI_XGS4_UDF_OFFSET_FLEXHASH;
   5743         }
   5744         if (hints->flags & BCM_UDF_CREATE_O_FIELD_INGRESS) {
   5745             offset_info->flags |= BCMI_XGS4_UDF_OFFSET_IFP;
   5746         }
   5747         if (hints->flags & BCM_UDF_CREATE_O_FIELD_LOOKUP) {
   5748             offset_info->flags |= BCMI_XGS4_UDF_OFFSET_VFP;
   5749         }
   5750         if (hints->flags & BCM_UDF_CREATE_O_POLICER_GROUP) {
   5751             offset_info->flags |= BCMI_XGS4_UDF_OFFSET_POLICER;
   5752         }
   5753         if (hints->flags & BCM_UDF_CREATE_O_UDFHASH) {
   5754             offset_info->flags |= BCMI_XGS4_UDF_OFFSET_UDFHASH;
   5755         }
   5756         if (hints->flags & BCM_UDF_CREATE_O_RANGE_CHECK) {
   5757             offset_info->flags |= BCMI_XGS4_UDF_OFFSET_RANGE_CHECK;
   5758         }
   5759     }
   5760 
   5761     /* Increment num udfs */
   5762     if ((hints != NULL) && !(hints->flags & BCM_UDF_CREATE_O_REPLACE)) {
   5763         UDF_CTRL(unit)->num_udfs += 1;
   5764     }
   5765 
   5766     UDF_CTRL(unit)->udf_used_by_module = UDF_USED_BY_UDF_MODULE;
   5767 
   5768 cleanup:
   5769 
   5770 
   5771     if (BCM_FAILURE(rv)) {
   5772 
   5773         if ((id_running_allocated == 1) &&
   5774             (UDF_CTRL(unit)->udf_id_running != BCMI_XGS4_UDF_ID_MAX)) {
   5775             /* Decrement the running udf id */
   5776             UDF_CTRL(unit)->udf_id_running -= 1;
   5777         }
   5778 
   5779         /* Delete the offset node */
   5780         if (offset_info != NULL) {
   5781             UDF_UNLINK_OFFSET_NODE(offset_info);
   5782             sal_free(offset_info);
   5783         }
   5784     }
   5785 
   5786     /* Release UDF mutex */
   5787     UDF_UNLOCK(unit);
   5788 
   5789 
   5790     return rv;
   5791 }
   5792 
   5793 /*
   5794  * Function:
   5795  *      bcm_udf_pkt_format_create
   5796  * Purpose:
   5797  *      Create a packet format entry
   5798  * Parameters:
   5799  *      unit - (IN) Unit number.
   5800  *      options - (IN) API Options.
   5801  *      pkt_format - (IN) UDF packet format info structure
   5802  *      pkt_format_id - (OUT) Packet format ID
   5803  * Returns:
   5804  *      BCM_E_NONE          UDF packet format entry created
   5805  *                          successfully.
   5806  *      BCM_E_UNIT          Invalid BCM Unit number.
   5807  *      BCM_E_INIT          UDF module not initialized.
   5808  *      BCM_E_UNAVAIL       Feature not supported.
   5809  *      BCM_E_XXX           Standard error code.
   5810  * Notes:
   5811  */
   5812 int
   5813 bcmi_xgs4_udf_pkt_format_create(
   5814     int unit,
   5815     bcm_udf_pkt_format_options_t options,
   5816     bcm_udf_pkt_format_info_t *pkt_format_info,
   5817     bcm_udf_pkt_format_id_t *pkt_format_id)
   5818 {
   5819     int id_running_allocated = 0;
   5820     bcmi_xgs4_udf_tcam_info_t *tcam_info_match = NULL;
   5821     bcmi_xgs4_udf_tcam_info_t *tcam_info_local = NULL;
   5822 
   5823     int rv = BCM_E_NONE;
   5824 
   5825     /* UDF Module Init check */
   5826     UDF_INIT_CHECK(unit);
   5827 
   5828 
   5829     /* Input parameters check. */
   5830     BCM_IF_NULL_RETURN_PARAM(pkt_format_id);
   5831     BCM_IF_NULL_RETURN_PARAM(pkt_format_info);
   5832 
   5833     /* Sanitize input parameters */
   5834     rv = bcmi_xgs4_udf_sanitize_inputs(unit, NULL, NULL, pkt_format_info);
   5835     BCM_IF_ERROR_RETURN(rv);
   5836 
   5837     /* UDF Module Lock */
   5838     UDF_LOCK(unit);
   5839 
   5840     /* Check if similar entry already existing */
   5841     if (options & BCM_UDF_PKT_FORMAT_CREATE_O_WITHID) {
   5842 
   5843         UDF_PKT_FORMAT_ID_VALIDATE_UNLOCK(unit, *pkt_format_id);
   5844 
   5845         /* Fetch the tcam info;  get should be successful */
   5846         rv = bcmi_xgs4_udf_tcam_node_get(unit, *pkt_format_id,
   5847                                          &tcam_info_local);
   5848 
   5849         if (BCM_FAILURE(rv)) {
   5850             UDF_UNLOCK(unit);
   5851             return rv;
   5852         }
   5853 
   5854         if ((options & BCM_UDF_PKT_FORMAT_CREATE_O_REPLACE)) {
   5855             if (tcam_info_local->num_udfs >= 1) {
   5856                 /* UDF Pkt format entry already in use */
   5857                 UDF_UNLOCK(unit);
   5858                 return BCM_E_CONFIG;
   5859             }
   5860             /* Delete the UDF pkt format entry and recreate one */
   5861             rv = bcmi_xgs4_udf_tcam_node_delete(unit, *pkt_format_id,
   5862                                                 &tcam_info_match);
   5863             if (BCM_FAILURE(rv)) {
   5864                 UDF_UNLOCK(unit);
   5865                 return rv;
   5866             }
   5867 
   5868             /* Free tcam node */
   5869             sal_free(tcam_info_match);
   5870         }
   5871     } else {
   5872 
   5873         /* Allocate new id */
   5874         rv = bcmi_xgs4_udf_id_running_id_alloc(unit, bcmiUdfObjectPktFormat,
   5875                                                pkt_format_id);
   5876         if (BCM_FAILURE(rv)) {
   5877             UDF_UNLOCK(unit);
   5878             return rv;
   5879         } else {
   5880             id_running_allocated = 1;
   5881         }
   5882     }
   5883 
   5884     /* Insert the packet format entry in the linked list */
   5885     rv = bcmi_xgs4_udf_tcam_info_add(unit, pkt_format_info, &tcam_info_local);
   5886     UDF_IF_ERROR_CLEANUP(rv);
   5887 
   5888     if ((UDF_CTRL(unit)->num_pkt_formats + 1) ==
   5889          BCMI_XGS4_UDF_CTRL_MAX_UDF_ENTRIES(unit)) {
   5890         rv = BCM_E_RESOURCE;
   5891     }
   5892     UDF_IF_ERROR_CLEANUP(rv);
   5893 
   5894 
   5895     /*
   5896      * The packet format matching hardware is a tcam and hence
   5897      * there is no point in allowing to create more than one entry
   5898      * of similar configuration. Search for a matching entry in
   5899      * list of already installed objects and return error appropriately.
   5900      */
   5901 
   5902     rv = bcmi_xgs4_udf_tcam_entry_match(unit,
   5903                                         tcam_info_local, &tcam_info_match);
   5904     if (BCM_SUCCESS(rv)) {
   5905         if (tcam_info_match->priority == pkt_format_info->prio) {
   5906             rv = BCM_E_EXISTS;
   5907         } else {
   5908             rv = BCM_E_RESOURCE;
   5909         }
   5910     } else {
   5911         if (rv == BCM_E_NOT_FOUND) {
   5912             rv = BCM_E_NONE;
   5913         }
   5914 
   5915     }
   5916     UDF_IF_ERROR_CLEANUP(rv);
   5917 
   5918     /* Increment num udfs */
   5919     UDF_CTRL(unit)->num_pkt_formats += 1;
   5920 
   5921     /* update pkt_format_id in the tcam_info */
   5922     tcam_info_local->pkt_format_id = *pkt_format_id;
   5923 
   5924 cleanup:
   5925 
   5926     if (BCM_FAILURE(rv)) {
   5927         if ((id_running_allocated) &&
   5928             (UDF_CTRL(unit)->udf_pkt_format_id_running !=
   5929              BCMI_XGS4_UDF_PKT_FORMAT_ID_MAX)) {
   5930             /* Decrement the running pkt format id */
   5931             UDF_CTRL(unit)->udf_pkt_format_id_running -= 1;
   5932         }
   5933 
   5934         /* Delete the offset node */
   5935         if (tcam_info_local != NULL) {
   5936             UDF_UNLINK_TCAM_NODE(tcam_info_local);
   5937             sal_free(tcam_info_local);
   5938         }
   5939     }
   5940 
   5941     /* Release UDF mutex */
   5942     UDF_UNLOCK(unit);
   5943 
   5944 
   5945     return rv;
   5946 }
   5947 
   5948 
   5949 /*
   5950  * Function:
   5951  *      bcm_udf_pkt_format_destroy
   5952  * Purpose:
   5953  *      Destroy existing packet format entry
   5954  * Parameters:
   5955  *      unit - (IN) Unit number.
   5956  *      pkt_format_id - (IN) Packet format ID
   5957  *      pkt_format - (IN) UDF packet format info structure
   5958  * Returns:
   5959  *      BCM_E_NONE          Destroy packet format entry.
   5960  *      BCM_E_NOT_FOUND     Packet format ID does not exist.
   5961  *      BCM_E_UNIT          Invalid BCM Unit number.
   5962  *      BCM_E_INIT          UDF module not initialized.
   5963  *      BCM_E_UNAVAIL       Feature not supported.
   5964  *      BCM_E_XXX           Standard error code.
   5965  * Notes:
   5966  */
   5967 int
   5968 bcmi_xgs4_udf_pkt_format_destroy(int unit,
   5969                                  bcm_udf_pkt_format_id_t pkt_format_id)
   5970 {
   5971     int rv;
   5972     bcmi_xgs4_udf_tcam_info_t *tcam_info = NULL;
   5973 
   5974     /* UDF Module Init check */
   5975     UDF_INIT_CHECK(unit);
   5976 
   5977     /* UDF Module Lock */
   5978     UDF_LOCK(unit);
   5979 
   5980     /* Retrieve the node indexed by pkt_format_id */
   5981     rv = bcmi_xgs4_udf_tcam_node_get(unit, pkt_format_id, &tcam_info);
   5982     if (BCM_FAILURE(rv)) {
   5983         UDF_UNLOCK(unit);
   5984         return rv;
   5985     }
   5986 
   5987     /* Delete the software object */
   5988     if (tcam_info->num_udfs >= 1) {
   5989         UDF_UNLOCK(unit);
   5990         return BCM_E_BUSY;
   5991     } else {
   5992         UDF_UNLINK_TCAM_NODE(tcam_info);
   5993 
   5994         /* Decrement num pkt_formats */
   5995         UDF_CTRL(unit)->num_pkt_formats -= 1;
   5996 
   5997         /* Free the tcam node */
   5998         sal_free(tcam_info);
   5999     }
   6000 
   6001     /* Release UDF mutex */
   6002     UDF_UNLOCK(unit);
   6003 
   6004     return BCM_E_NONE;
   6005 }
   6006 
   6007 
   6008 /*
   6009  * Function:
   6010  *      bcm_udf_pkt_format_info_get
   6011  * Purpose:
   6012  *      Retrieve packet format info given the packet format Id
   6013  * Parameters:
   6014  *      unit - (IN) Unit number.
   6015  *      pkt_format_id - (IN) Packet format ID
   6016  *      pkt_format - (OUT) UDF packet format info structure
   6017  * Returns:
   6018  *      BCM_E_NONE          Packet format get successful.
   6019  *      BCM_E_NOT_FOUND     Packet format entry does not exist.
   6020  *      BCM_E_UNIT          Invalid BCM Unit number.
   6021  *      BCM_E_INIT          UDF module not initialized.
   6022  *      BCM_E_UNAVAIL       Feature not supported.
   6023  *      BCM_E_XXX           Standard error code.
   6024  * Notes:
   6025  */
   6026 int
   6027 bcmi_xgs4_udf_pkt_format_info_get(
   6028     int unit,
   6029     bcm_udf_pkt_format_id_t pkt_format_id,
   6030     bcm_udf_pkt_format_info_t *pkt_format_info)
   6031 {
   6032     int rv;
   6033     bcmi_xgs4_udf_tcam_info_t *tcam_info = NULL;
   6034 
   6035     /* UDF Module Init check */
   6036     UDF_INIT_CHECK(unit);
   6037 
   6038     BCM_IF_NULL_RETURN_PARAM(pkt_format_info);
   6039 
   6040     /* UDF Module Lock */
   6041     UDF_LOCK(unit);
   6042 
   6043     /* Retrieve the node indexed by pkt_format_id */
   6044     rv = bcmi_xgs4_udf_tcam_node_get(unit, pkt_format_id, &tcam_info);
   6045     if (BCM_FAILURE(rv)) {
   6046         UDF_UNLOCK(unit);
   6047         return rv;
   6048     }
   6049 
   6050     /* Fetch the tcam entry info and convert to user-readable form */
   6051     rv = bcmi_xgs4_udf_tcam_entry_parse(unit,
   6052              (uint32 *)&(tcam_info->hw_buf), pkt_format_info);
   6053     if (BCM_FAILURE(rv)) {
   6054         UDF_UNLOCK(unit);
   6055         return rv;
   6056     }
   6057 
   6058     pkt_format_info->prio = tcam_info->priority;
   6059 
   6060 #if defined (BCM_TOMAHAWK_SUPPORT)
   6061     if (UDF_CTRL(unit)->flags & BCMI_XGS4_UDF_PKT_FORMAT_CLASS_ID) {
   6062         pkt_format_info->class_id = tcam_info->class_id;
   6063     }
   6064 #endif
   6065 
   6066     /* Release UDF mutex */
   6067     UDF_UNLOCK(unit);
   6068 
   6069 
   6070     return BCM_E_NONE;
   6071 }
   6072 
   6073 /*
   6074  * Function:
   6075  *      bcm_udf_pkt_format_add
   6076  * Purpose:
   6077  *      Adds packet format entry to UDF object
   6078  * Parameters:
   6079  *      unit - (IN) Unit number.
   6080  *      udf_id - (IN) UDF ID
   6081  *      pkt_format_id - (IN) Packet format ID
   6082  * Returns:
   6083  *      BCM_E_NONE          Packet format entry added to UDF
   6084  *                          successfully.
   6085  *      BCM_E_NOT_FOUND     UDF Id or packet format entry does not
   6086  *                          exist.
   6087  *      BCM_E_UNIT          Invalid BCM Unit number.
   6088  *      BCM_E_INIT          UDF module not initialized.
   6089  *      BCM_E_UNAVAIL       Feature not supported.
   6090  *      BCM_E_XXX           Standard error code.
   6091  * Notes:
   6092  */
   6093 int
   6094 bcmi_xgs4_udf_pkt_format_add(
   6095     int unit,
   6096     bcm_udf_id_t udf_id,
   6097     bcm_udf_pkt_format_id_t pkt_format_id)
   6098 {
   6099     int rv;
   6100     int idx;
   6101     int base = 0;
   6102     int offset = 0;
   6103     int num_udfs = 0;
   6104     uint32 offset_bmap;
   6105     bcmi_xgs4_udf_offset_entry_t *offset_entry;
   6106     bcmi_xgs4_udf_offset_info_t *offset_info = NULL;
   6107     bcmi_xgs4_udf_tcam_info_t *tcam_info = NULL;
   6108 
   6109     /* UDF Module Init check */
   6110     UDF_INIT_CHECK(unit);
   6111 
   6112     /* Sanitize input params */
   6113     UDF_ID_VALIDATE(udf_id);
   6114     UDF_PKT_FORMAT_ID_VALIDATE(pkt_format_id);
   6115 
   6116     /* UDF Module Lock */
   6117     UDF_LOCK(unit);
   6118 
   6119     /* Retrieve the node indexed by pkt_format_id */
   6120     rv = bcmi_xgs4_udf_tcam_node_get(unit, pkt_format_id, &tcam_info);
   6121     if (BCM_FAILURE(rv)) {
   6122         UDF_UNLOCK(unit);
   6123         return rv;
   6124     }
   6125 
   6126     /* Read UDF info */
   6127     rv = bcmi_xgs4_udf_offset_node_get(unit, udf_id, &offset_info);
   6128     if (BCM_FAILURE(rv)) {
   6129         UDF_UNLOCK(unit);
   6130         return rv;
   6131     }
   6132 
   6133     /* Convert udf layer+start to udf_offset info */
   6134     rv = bcmi_xgs4_udf_layer_to_offset_base(unit, offset_info,
   6135                                             tcam_info, &base, &offset);
   6136     if (BCM_FAILURE(rv)) {
   6137         UDF_UNLOCK(unit);
   6138         return rv;
   6139     }
   6140 
   6141     if ((offset_info->num_pkt_formats + 1) >= MAX_UDF_TCAM_ENTRIES) {
   6142         UDF_UNLOCK(unit);
   6143         return  BCM_E_RESOURCE;
   6144     }
   6145 
   6146 #ifdef BCM_TOMAHAWK_SUPPORT
   6147     if (soc_feature(unit, soc_feature_udf_multi_pipe_support) &&
   6148        (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) {
   6149         if (offset_info->associated_pipe >= SOC_MAX_NUM_PIPES) {
   6150             UDF_UNLOCK(unit);
   6151             return BCM_E_PARAM;
   6152         }
   6153 
   6154         tcam_info->associated_pipe = offset_info->associated_pipe;
   6155         tcam_info->associated_pipes[offset_info->associated_pipe] =
   6156             offset_info->associated_pipe;
   6157 
   6158         num_udfs = tcam_info->num_udfs_per_pipe[tcam_info->associated_pipe];
   6159         offset_bmap = tcam_info->offset_bmap_per_pipe[tcam_info->associated_pipe];
   6160     } else
   6161 #endif
   6162     {
   6163         num_udfs = tcam_info->num_udfs;
   6164         offset_bmap = tcam_info->offset_bmap;
   6165     }
   6166 
   6167     if (offset_bmap & offset_info->hw_bmap) {
   6168         /* Packet format object is already using the bmap */
   6169         UDF_UNLOCK(unit);
   6170         return BCM_E_EXISTS;
   6171     }
   6172 
   6173     if ((num_udfs + 1) > MAX_UDF_OFFSET_CHUNKS) {
   6174         UDF_UNLOCK(unit);
   6175         return BCM_E_RESOURCE;
   6176     }
   6177 
   6178     /* Packet format is associated with the first UDF, install it */
   6179     if (num_udfs == 0) {
   6180         rv = bcmi_xgs4_udf_tcam_entry_insert(unit, tcam_info);
   6181         if (BCM_FAILURE(rv)) {
   6182             UDF_UNLOCK(unit);
   6183             return rv;
   6184         }
   6185     }
   6186 
   6187 #ifdef BCM_TOMAHAWK_SUPPORT
   6188     if (soc_feature(unit, soc_feature_udf_multi_pipe_support) &&
   6189         (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) {
   6190         tcam_info->hw_idx =
   6191             tcam_info->hw_idx_per_pipe[tcam_info->associated_pipe];
   6192     }
   6193 #endif
   6194 
   6195     /* Add the udf offset info to the UDF_OFFSET entry */
   6196     rv = bcmi_xgs4_udf_offset_install(unit, tcam_info->hw_idx,
   6197                                       offset_info->hw_bmap, base, offset,
   6198                                       tcam_info->associated_pipe,
   6199                                       tcam_info->class_id,
   6200                                       offset_info->flags);
   6201 
   6202     if (BCM_FAILURE(rv)) {
   6203         UDF_UNLOCK(unit);
   6204         return rv;
   6205     }
   6206 
   6207     /* set the offset_bmap */
   6208     tcam_info->num_udfs++;
   6209     offset_info->num_pkt_formats++;
   6210     tcam_info->offset_info_list[offset_info->grp_id] = offset_info;
   6211 
   6212     for (idx = 0; idx < MAX_UDF_ID_LIST; idx++) {
   6213         if (tcam_info->udf_id_list[idx] == 0) {
   6214             tcam_info->udf_id_list[idx] = udf_id;
   6215             break;
   6216         }
   6217     }
   6218 
   6219 #ifdef BCM_TOMAHAWK_SUPPORT
   6220     if (soc_feature(unit, soc_feature_udf_multi_pipe_support) &&
   6221         (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) {
   6222         tcam_info->num_udfs_per_pipe[tcam_info->associated_pipe]++;
   6223         tcam_info->offset_bmap_per_pipe[tcam_info->associated_pipe] |= offset_info->hw_bmap;
   6224         offset_entry = &(UDF_CTRL(unit)->offset_entry_array_per_pipe[offset_info->associated_pipe][(offset_info->grp_id)]);
   6225     } else
   6226 #endif
   6227     {
   6228         tcam_info->offset_bmap |= (offset_info->hw_bmap);
   6229         offset_entry = &(UDF_CTRL(unit)->offset_entry_array[(offset_info->grp_id)]);
   6230     }
   6231 
   6232     offset_entry->num_pkt_formats++;
   6233 
   6234     /* Release UDF mutex */
   6235     UDF_UNLOCK(unit);
   6236 
   6237     return BCM_E_NONE;
   6238 }
   6239 
   6240 /*
   6241  * Function:
   6242  *      bcm_udf_pkt_format_delete
   6243  * Purpose:
   6244  *      Deletes packet format spec associated with the UDF
   6245  * Parameters:
   6246  *      unit - (IN) Unit number.
   6247  *      udf_id - (IN) UDF ID
   6248  *      pkt_format_id - (IN) Packet format ID
   6249  * Returns:
   6250  *      BCM_E_NONE          Packet format configuration successfully
   6251  *                          deleted from UDF.
   6252  *      BCM_E_NOT_FOUND     UDF Id or packet format entry does not
   6253  *                          exist.
   6254  *      BCM_E_UNIT          Invalid BCM Unit number.
   6255  *      BCM_E_INIT          UDF module not initialized.
   6256  *      BCM_E_UNAVAIL       Feature not supported.
   6257  *      BCM_E_XXX           Standard error code.
   6258  * Notes:
   6259  */
   6260 int
   6261 bcmi_xgs4_udf_pkt_format_delete(
   6262     int unit,
   6263     bcm_udf_id_t udf_id,
   6264     bcm_udf_pkt_format_id_t pkt_format_id)
   6265 {
   6266     int rv;
   6267     int idx;
   6268     int hw_idx;
   6269     int *num_udfs;
   6270     uint32 *offset_bmap;
   6271     soc_mem_t tcam_mem;
   6272     bcmi_xgs4_udf_tcam_entry_t *tcam_entry;
   6273     bcmi_xgs4_udf_offset_entry_t *offset_entry;
   6274     bcmi_xgs4_udf_offset_info_t *offset_info = NULL;
   6275     bcmi_xgs4_udf_tcam_info_t *tcam_info = NULL;
   6276 
   6277 #if defined (BCM_TOMAHAWK_SUPPORT)
   6278     int pipe_num = BCMI_XGS4_UDF_INVALID_PIPE_NUM;
   6279 #endif
   6280 
   6281     /* UDF Module Init check */
   6282     UDF_INIT_CHECK(unit);
   6283 
   6284     /* Sanitize input params */
   6285     UDF_ID_VALIDATE(udf_id);
   6286     UDF_PKT_FORMAT_ID_VALIDATE(pkt_format_id);
   6287 
   6288     /* UDF Module Lock */
   6289     UDF_LOCK(unit);
   6290 
   6291     /* Retrieve the node indexed by pkt_format_id */
   6292     rv = bcmi_xgs4_udf_tcam_node_get(unit, pkt_format_id, &tcam_info);
   6293     if (BCM_FAILURE(rv)) {
   6294         UDF_UNLOCK(unit);
   6295         return rv;
   6296     }
   6297 
   6298     /* Read UDF info */
   6299     rv = bcmi_xgs4_udf_offset_node_get(unit, udf_id, &offset_info);
   6300     if (BCM_FAILURE(rv)) {
   6301         UDF_UNLOCK(unit);
   6302         return rv;
   6303     }
   6304 
   6305     /* Either of the entry is not installed to the hardware yet */
   6306     if (offset_info->num_pkt_formats == 0) {
   6307         UDF_UNLOCK(unit);
   6308         return BCM_E_CONFIG;
   6309     }
   6310 
   6311 #if defined (BCM_TOMAHAWK_SUPPORT)
   6312     if (soc_feature(unit, soc_feature_udf_multi_pipe_support) &&
   6313        (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) {
   6314         if (offset_info->associated_pipe >= SOC_MAX_NUM_PIPES) {
   6315             UDF_UNLOCK(unit);
   6316             return BCM_E_PARAM;
   6317         }
   6318 
   6319         pipe_num = tcam_info->associated_pipes[offset_info->associated_pipe];
   6320         if (pipe_num == BCMI_XGS4_UDF_INVALID_PIPE_NUM) {
   6321             UDF_UNLOCK(unit);
   6322             return BCM_E_PARAM;
   6323         }
   6324 
   6325         hw_idx = tcam_info->hw_idx_per_pipe[pipe_num];
   6326         num_udfs = &(tcam_info->num_udfs_per_pipe[pipe_num]);
   6327         offset_bmap = &(tcam_info->offset_bmap_per_pipe[pipe_num]);
   6328     } else
   6329 #endif
   6330     {
   6331         hw_idx = tcam_info->hw_idx;
   6332         num_udfs = &(tcam_info->num_udfs);
   6333         offset_bmap = &(tcam_info->offset_bmap);
   6334     }
   6335 
   6336     /* Unrelated packet format id and udf id */
   6337     if (!(*offset_bmap & offset_info->hw_bmap)) {
   6338         UDF_UNLOCK(unit);
   6339         return BCM_E_CONFIG;
   6340     }
   6341 
   6342     if (*num_udfs == 0) {
   6343         UDF_UNLOCK(unit);
   6344         return BCM_E_CONFIG;
   6345     }
   6346 
   6347 #if defined (BCM_TOMAHAWK_SUPPORT)
   6348     if (soc_feature(unit, soc_feature_udf_multi_pipe_support) &&
   6349        (bcmi_xgs4_udf_oper_mode[unit] == bcmUdfOperModePipeLocal)) {
   6350         tcam_mem = SOC_MEM_UNIQUE_ACC(unit, UDF_CTRL(unit)->tcam_mem)[pipe_num];
   6351         tcam_entry = &(UDF_CTRL(unit)->tcam_entry_array_per_pipe[pipe_num][hw_idx]);
   6352         offset_entry = &(UDF_CTRL(unit)->offset_entry_array_per_pipe[pipe_num][offset_info->grp_id]);
   6353         tcam_info->num_udfs--;
   6354     } else
   6355 #endif
   6356     {
   6357         tcam_mem   = UDF_CTRL(unit)->tcam_mem;
   6358         tcam_entry = &(UDF_CTRL(unit)->tcam_entry_array[hw_idx]);
   6359         offset_entry = &(UDF_CTRL(unit)->offset_entry_array[(offset_info->grp_id)]);
   6360     }
   6361 
   6362     *num_udfs = *num_udfs - 1;
   6363     offset_info->num_pkt_formats -= 1;
   6364     offset_entry->num_pkt_formats -= 1;
   6365     tcam_info->offset_info_list[offset_info->grp_id] = NULL;
   6366 
   6367     for (idx = 0; idx < MAX_UDF_ID_LIST; idx++) {
   6368         if (tcam_info->udf_id_list[idx] == udf_id) {
   6369             tcam_info->udf_id_list[idx] = 0;
   6370             break;
   6371         }
   6372     }
   6373 
   6374     /* Packet format is dissociated with the first UDF, uninstall it */
   6375     if (*num_udfs == 0) {
   6376 
   6377         /* Install the entry into hardware */
   6378         rv = soc_mem_write(unit, tcam_mem,
   6379                            MEM_BLOCK_ALL, hw_idx,
   6380                            soc_mem_entry_null(unit, UDF_CTRL(unit)->tcam_mem));
   6381 
   6382         if (SOC_FAILURE(rv)) {
   6383             UDF_UNLOCK(unit);
   6384             return rv;
   6385         }
   6386 
   6387         tcam_entry->valid = 0;
   6388         tcam_entry->tcam_info = NULL;
   6389     }
   6390 
   6391     /* clear the offset_bmap */
   6392     *offset_bmap &= ~(offset_info->hw_bmap);
   6393 
   6394     /* Remove the udf offset info to the UDF_OFFSET entry */
   6395     rv = bcmi_xgs4_udf_offset_uninstall(unit, hw_idx,
   6396                                         offset_info->hw_bmap,
   6397                                         offset_info->associated_pipe);
   6398     if (BCM_FAILURE(rv)) {
   6399         UDF_UNLOCK(unit);
   6400         return rv;
   6401     }
   6402 
   6403     /* Release UDF mutex */
   6404     UDF_UNLOCK(unit);
   6405 
   6406     return BCM_E_NONE;
   6407 }
   6408 
   6409 /*
   6410  * Function:
   6411  *      bcm_udf_pkt_format_get_all
   6412  * Purpose:
   6413  *      Retrieves the user defined format specification configuration
   6414  *      from UDF
   6415  * Parameters:
   6416  *      unit - (IN) Unit number.
   6417  *      udf_id - (IN) UDF ID
   6418  *      max - (IN) Max Packet formats attached to a UDF object
   6419  *      pkt_format_id_list - (OUT) List of packet format entries added to udf id
   6420  *      actual - (OUT) Actual number of Packet formats retrieved
   6421  * Returns:
   6422  *      BCM_E_NONE          Success.
   6423  *      BCM_E_NOT_FOUND     Either the UDF or packet format entry does
   6424  *                          not exist.
   6425  *      BCM_E_UNIT          Invalid BCM Unit number.
   6426  *      BCM_E_INIT          UDF module not initialized.
   6427  *      BCM_E_UNAVAIL       Feature not supported.
   6428  *      BCM_E_XXX           Standard error code.
   6429  * Notes:
   6430  */
   6431 int
   6432 bcmi_xgs4_udf_pkt_format_get_all(
   6433     int unit,
   6434     bcm_udf_id_t udf_id,
   6435     int max,
   6436     bcm_udf_pkt_format_id_t *pkt_format_id_list,
   6437     int *actual)
   6438 {
   6439     int i;
   6440     int rv;
   6441     bcmi_xgs4_udf_offset_info_t *offset_info = NULL;
   6442     bcmi_xgs4_udf_tcam_info_t *tcam_info = NULL;
   6443 
   6444     /* UDF Module Init check */
   6445     UDF_INIT_CHECK(unit);
   6446 
   6447     BCM_IF_NULL_RETURN_PARAM(actual);
   6448 
   6449     /* Sanitize input params */
   6450     UDF_ID_VALIDATE(udf_id);
   6451 
   6452     /* UDF Module Lock */
   6453     UDF_LOCK(unit);
   6454 
   6455     /* Read UDF info */
   6456     rv = bcmi_xgs4_udf_offset_node_get(unit, udf_id, &offset_info);
   6457     if (BCM_FAILURE(rv)) {
   6458         UDF_UNLOCK(unit);
   6459         return rv;
   6460     }
   6461 
   6462     if ((max == 0) || (pkt_format_id_list == NULL)) {
   6463         *actual = offset_info->num_pkt_formats;
   6464         UDF_UNLOCK(unit);
   6465         return BCM_E_NONE;
   6466     }
   6467 
   6468     tcam_info = UDF_CTRL(unit)->tcam_info_head;
   6469     while (tcam_info) {
   6470         for (i = 0; i < MAX_UDF_ID_LIST; i++) {
   6471             if (tcam_info->udf_id_list[i] == udf_id) {
   6472                 if (*actual < max) {
   6473                     pkt_format_id_list[*actual] = tcam_info->pkt_format_id;
   6474                 }
   6475 
   6476                 (*actual) += 1;
   6477                 break;
   6478             }
   6479         }
   6480 
   6481         tcam_info = tcam_info->next;
   6482     }
   6483 
   6484     /* Release UDF mutex */
   6485     UDF_UNLOCK(unit);
   6486 
   6487     return BCM_E_NONE;
   6488 }
   6489 
   6490 /*
   6491  * Function:
   6492  *      bcm_udf_pkt_format_delete_all
   6493  * Purpose:
   6494  *      Deletes all packet format specs associated with the UDF
   6495  * Parameters:
   6496  *      unit - (IN) Unit number.
   6497  *      udf_id - (IN) UDF ID
   6498  * Returns:
   6499  *      BCM_E_NONE          Deletes all packet formats associated with
   6500  *                          the UDF.
   6501  *      BCM_E_NOT_FOUND     UDF Id does not exist.
   6502  *      BCM_E_UNIT          Invalid BCM Unit number.
   6503  *      BCM_E_INIT          UDF module not initialized.
   6504  *      BCM_E_UNAVAIL       Feature not supported.
   6505  *      BCM_E_XXX           Standard error code.
   6506  * Notes:
   6507  */
   6508 int
   6509 bcmi_xgs4_udf_pkt_format_delete_all(
   6510     int unit, bcm_udf_id_t udf_id)
   6511 {
   6512     int i;
   6513     int rv;
   6514     bcmi_xgs4_udf_tcam_info_t *tcam_info = NULL;
   6515 
   6516     /* UDF Module Init check */
   6517     UDF_INIT_CHECK(unit);
   6518 
   6519     /* Sanitize input params */
   6520     UDF_ID_VALIDATE(udf_id);
   6521 
   6522     /* UDF Module Lock */
   6523     UDF_LOCK(unit);
   6524 
   6525     tcam_info = UDF_CTRL(unit)->tcam_info_head;
   6526     while (tcam_info) {
   6527         for (i = 0; i < MAX_UDF_ID_LIST; i++) {
   6528             if (tcam_info->udf_id_list[i] == udf_id) {
   6529                 rv = bcmi_xgs4_udf_pkt_format_delete(unit, udf_id,
   6530                                                      tcam_info->pkt_format_id);
   6531 
   6532                 if (BCM_FAILURE(rv)) {
   6533                     UDF_UNLOCK(unit);
   6534                     return rv;
   6535                 }
   6536                 break;
   6537             }
   6538         }
   6539 
   6540         tcam_info = tcam_info->next;
   6541     }
   6542 
   6543     /* Release UDF mutex */
   6544     UDF_UNLOCK(unit);
   6545 
   6546     return BCM_E_NONE;
   6547 }
   6548 
   6549 
   6550 /*
   6551  * Function:
   6552  *      bcm_udf_pkt_format_get
   6553  * Purpose:
   6554  *      Fetches all UDFs that share the common packet format entry.
   6555  * Parameters:
   6556  *      unit - (IN) Unit number.
   6557  *      pkt_format_id - (IN) Packet format ID.
   6558  *      max - (IN) Max number of UDF IDs
   6559  *      udf_id_list - (OUT) List of UDF IDs
   6560  *      actual - (OUT) Actual udfs retrieved
   6561  * Returns:
   6562  *      BCM_E_NONE          Success.
   6563  *      BCM_E_UNIT          Invalid BCM Unit number.
   6564  *      BCM_E_INIT          UDF module not initialized.
   6565  *      BCM_E_UNAVAIL       Feature not supported.
   6566  *      BCM_E_XXX           Standard error code.
   6567  * Notes:
   6568  */
   6569 int
   6570 bcmi_xgs4_udf_pkt_format_get(
   6571     int unit,
   6572     bcm_udf_pkt_format_id_t pkt_format_id,
   6573     int max,
   6574     bcm_udf_id_t *udf_id_list,
   6575     int *actual)
   6576 {
   6577     int i;
   6578     int rv;
   6579     uint16 udf_id;
   6580     bcmi_xgs4_udf_tcam_info_t *tcam_info = NULL;
   6581 
   6582     /* UDF Module Init check */
   6583     UDF_INIT_CHECK(unit);
   6584 
   6585     BCM_IF_NULL_RETURN_PARAM(actual);
   6586 
   6587     /* Sanitize input params */
   6588     UDF_PKT_FORMAT_ID_VALIDATE(pkt_format_id);
   6589 
   6590     /* UDF Module Lock */
   6591     UDF_LOCK(unit);
   6592 
   6593 
   6594     /* Read UDF info */
   6595     rv = bcmi_xgs4_udf_tcam_node_get(unit, pkt_format_id, &tcam_info);
   6596     if (BCM_FAILURE(rv)) {
   6597         UDF_UNLOCK(unit);
   6598         return rv;
   6599     }
   6600 
   6601     if ((udf_id_list == NULL) || (max == 0)) {
   6602         *actual = tcam_info->num_udfs;
   6603         UDF_UNLOCK(unit);
   6604         return rv;
   6605     }
   6606 
   6607     for (i = 0; i < MAX_UDF_ID_LIST; i++) {
   6608         udf_id = tcam_info->udf_id_list[i];
   6609         if (udf_id > 0) {
   6610             if (*actual < max) {
   6611                 udf_id_list[*actual] = udf_id;
   6612             }
   6613 
   6614             (*actual) += 1;
   6615         }
   6616     }
   6617 
   6618     /* Release UDF mutex */
   6619     UDF_UNLOCK(unit);
   6620 
   6621     return BCM_E_NONE;
   6622 }
   6623 
   6624 
   6625 /*
   6626  * Function:
   6627  *      bcmi_xgs4_udf_hash_config_add
   6628  * Purpose:
   6629  *      Add UDF id into hashing list and configure it
   6630  * Parameters:
   6631  *      unit            (IN) BCM unit number
   6632  *      options         (IN) See BCM_UDF_HASH_ADD_O_xxx.
   6633  *                           Currently not supported,
   6634  *                           reserved for future usage.
   6635  *      config          (IN) UDF hashing configuration info
   6636  * Returns:
   6637  *      BCM_E_NONE      UDF hashing added successfully
   6638  *      BCM_E_XXX       Standard error code
   6639  * Notes:
   6640  */
   6641 int
   6642 bcmi_xgs4_udf_hash_config_add(
   6643     int unit,
   6644     uint32 options,
   6645     bcm_udf_hash_config_t *config)
   6646 {
   6647     int rv;
   6648     bcmi_xgs4_udf_offset_info_t *offset_info = NULL;
   6649 
   6650     /* UDF Module Init check */
   6651     UDF_INIT_CHECK(unit);
   6652 
   6653     /* UDF Module Lock */
   6654     UDF_LOCK(unit);
   6655 
   6656     if ((config == NULL)) {
   6657         UDF_UNLOCK(unit);
   6658         return BCM_E_PARAM;
   6659     }
   6660 
   6661     rv = bcmi_xgs4_udf_offset_node_get(unit, config->udf_id, &offset_info);
   6662     if (BCM_FAILURE(rv)) {
   6663         UDF_UNLOCK(unit);
   6664         return BCM_E_PARAM;
   6665     }
   6666 
   6667     rv = bcmi_xgs4_udf_hash_config_set(unit, config, offset_info);
   6668     if (BCM_FAILURE(rv)) {
   6669         UDF_UNLOCK(unit);
   6670         return rv;
   6671     }
   6672 
   6673     /* Set flag to indicate the object is in the list that
   6674        participates in hash calculation */
   6675     offset_info->flags |= BCMI_XGS4_UDF_OFFSET_UDFHASH_CONFIG;
   6676 
   6677     /* Release UDF mutex */
   6678     UDF_UNLOCK(unit);
   6679 
   6680     return BCM_E_NONE;
   6681 }
   6682 
   6683 /*
   6684  * Function:
   6685  *      bcmi_xgs4_udf_hash_config_delete
   6686  * Purpose:
   6687  *      Delete UDF id from hashing list
   6688  * Parameters:
   6689  *      unit            (IN) BCM unit number
   6690  *      config          (IN) UDF hashing configuration info
   6691  * Returns:
   6692  *      BCM_E_NONE      UDF hashing added successfully
   6693  *      BCM_E_XXX       Standard error code
   6694  * Notes:
   6695  */
   6696 int
   6697 bcmi_xgs4_udf_hash_config_delete(
   6698     int unit,
   6699     bcm_udf_hash_config_t *config)
   6700 {
   6701     int rv;
   6702     bcmi_xgs4_udf_offset_info_t *offset_info = NULL;
   6703 
   6704     /* UDF Module Init check */
   6705     UDF_INIT_CHECK(unit);
   6706 
   6707     /* UDF Module Lock */
   6708     UDF_LOCK(unit);
   6709 
   6710     if ((config == NULL)) {
   6711         return BCM_E_PARAM;
   6712         UDF_UNLOCK(unit);
   6713     }
   6714 
   6715     rv = bcmi_xgs4_udf_offset_node_get(unit, config->udf_id, &offset_info);
   6716     if (BCM_FAILURE(rv)) {
   6717         UDF_UNLOCK(unit);
   6718         return BCM_E_BADID;
   6719     }
   6720 
   6721     /* set mask to zero */
   6722     sal_memset(config->hash_mask, 0, sizeof(config->hash_mask));
   6723     config->mask_length = offset_info->width;
   6724     rv = bcmi_xgs4_udf_hash_config_set(unit, config, offset_info);
   6725     if (BCM_FAILURE(rv)) {
   6726         UDF_UNLOCK(unit);
   6727         return rv;
   6728     }
   6729 
   6730     /* Clear flag */
   6731     offset_info->flags &= ~BCMI_XGS4_UDF_OFFSET_UDFHASH_CONFIG;
   6732 
   6733     /* Release UDF mutex */
   6734     UDF_UNLOCK(unit);
   6735 
   6736     return BCM_E_NONE;
   6737 }
   6738 
   6739 
   6740 /*
   6741  * Function:
   6742  *      bcmi_xgs4_udf_hash_config_delete_all
   6743  * Purpose:
   6744  *      Delete all UDF id from hashing list
   6745  * Parameters:
   6746  *      unit            (IN) BCM unit number
   6747  * Returns:
   6748  *      BCM_E_NONE      UDF hashing added successfully
   6749  *      BCM_E_XXX       Standard error code
   6750  * Notes:
   6751  */
   6752 int
   6753 bcmi_xgs4_udf_hash_config_delete_all(
   6754     int unit)
   6755 {
   6756     bcmi_xgs4_udf_offset_info_t *tmp;
   6757     bcm_udf_hash_config_t config;
   6758     int rv;
   6759 
   6760     /* UDF Module Init check */
   6761     UDF_INIT_CHECK(unit);
   6762 
   6763     tmp = UDF_CTRL(unit)->offset_info_head;
   6764 
   6765     while (tmp != NULL) {
   6766         if (tmp->flags & BCMI_XGS4_UDF_OFFSET_UDFHASH_CONFIG) {
   6767             /* the udf id is in the list, set mask to zero */
   6768             sal_memset((&config)->hash_mask, 0, sizeof((&config)->hash_mask));
   6769             (&config)->mask_length = tmp->width;
   6770             (&config)->udf_id = tmp->udf_id;
   6771             rv = bcmi_xgs4_udf_hash_config_set(unit, &config, tmp);
   6772             if (BCM_FAILURE(rv)) {
   6773                 UDF_UNLOCK(unit);
   6774                 return rv;
   6775             }
   6776 
   6777             /* Clear flag */
   6778             tmp->flags &= ~BCMI_XGS4_UDF_OFFSET_UDFHASH_CONFIG;
   6779         }
   6780 
   6781         tmp = tmp->next;
   6782     }
   6783 
   6784     return BCM_E_NONE;
   6785 }
   6786 
   6787 
   6788 /*
   6789  * Function:
   6790  *      bcmi_xgs4_udf_hash_config_set
   6791  * Purpose:
   6792  *      Set udf hash configuration to hw
   6793  * Parameters:
   6794  *      unit            (IN) BCM unit number
   6795  *      config          (IN) UDF hashing configuration info
   6796  *      offset_info     (IN) Offset info node in offset link
   6797  * Returns:
   6798  *      BCM_E_NONE      UDF hashing added successfully
   6799  *      BCM_E_BADID     UDF id does not exist or is not for UDF hashing usage
   6800  *      BCM_E_XXX       Standard error code
   6801  * Notes:
   6802  */
   6803 STATIC int
   6804 bcmi_xgs4_udf_hash_config_set(
   6805     int unit,
   6806     bcm_udf_hash_config_t *config,
   6807     bcmi_xgs4_udf_offset_info_t *offset_info)
   6808 {
   6809     int i, j, rv;
   6810     bcmi_xgs4_udf_offset_info_t *offset_match = NULL;
   6811     bcmi_xgs4_udf_tcam_info_t *tcam_info = NULL;
   6812     soc_mem_t mem;
   6813     fp_udf_offset_entry_t offset_buf;
   6814     uint8 udf_hash_1, udf_hash_2;
   6815     uint32 mask;
   6816     uint16 mask_1, mask_2, mask_en_1, mask_en_2;
   6817     int byte_map[] = {13, 12, 15, 14};
   6818 
   6819     if ((config == NULL)
   6820         || (config->mask_length > BCM_UDF_HASH_MAX_LENGTH)) {
   6821         return BCM_E_PARAM;
   6822     }
   6823 
   6824     udf_hash_1 = UDF_CTRL(unit)->udf_hash_1;
   6825     udf_hash_2 = UDF_CTRL(unit)->udf_hash_2;
   6826     if (!(offset_info->flags & BCMI_XGS4_UDF_OFFSET_UDFHASH) ||
   6827         !(offset_info->hw_bmap & ((1 << udf_hash_1) | (1 << udf_hash_2))) ||
   6828         (offset_info->width != config->mask_length)) {
   6829         return BCM_E_PARAM;
   6830     }
   6831 
   6832     mask = 0;
   6833     /* mask[0]~[3] reflect to the order in byte_map */
   6834     for (i = 0, j = 0; i < BCM_UDF_HASH_MAX_LENGTH; i++) {
   6835         if (offset_info->byte_bmap & (1 << byte_map[i])) {
   6836             mask |= (config->hash_mask[j++] << (8 * (3 - i)));
   6837         }
   6838     }
   6839     mask_1 = (mask & 0xFFFF0000) >> 16;
   6840     mask_2 = mask & 0x0000FFFF;
   6841     mask_en_1 = (offset_info->hw_bmap & (1 << udf_hash_1)) ? 1 : 0;
   6842     mask_en_2 = (offset_info->hw_bmap & (1 << udf_hash_2)) ? 1 : 0;
   6843 
   6844     tcam_info = UDF_CTRL(unit)->tcam_info_head;
   6845     mem = UDF_CTRL(unit)->offset_mem;
   6846 
   6847     while (tcam_info != NULL) {
   6848         for (i = 0; i < BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit); i++) {
   6849             offset_match = tcam_info->offset_info_list[i];
   6850             /* Set same mask to all entries related to the UDF id */
   6851             if (offset_info == offset_match) {
   6852                 rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   6853                     tcam_info->hw_idx, &offset_buf);
   6854                 if (BCM_FAILURE(rv)) {
   6855                     return rv;
   6856                 }
   6857 
   6858                 if (mask_en_1) {
   6859                     soc_mem_field32_set(unit, mem, &offset_buf,
   6860                         HASH_MASK_1f, mask_1);
   6861                 }
   6862                 if (mask_en_2) {
   6863                     soc_mem_field32_set(unit, mem, &offset_buf,
   6864                         HASH_MASK_2f, mask_2);
   6865                 }
   6866 
   6867                 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL,
   6868                     tcam_info->hw_idx, &offset_buf);
   6869                 if (BCM_FAILURE(rv)) {
   6870                     return rv;
   6871                 }
   6872                 break;
   6873             }
   6874         }
   6875 
   6876         tcam_info = tcam_info->next;
   6877     }
   6878 
   6879     return BCM_E_NONE;
   6880 }
   6881 
   6882 
   6883 /*
   6884  * Function:
   6885  *      bcmi_xgs4_udf_hash_config_get
   6886  * Purpose:
   6887  *      Get UDF hashing configuration of a certain id
   6888  * Parameters:
   6889  *      unit            (IN) BCM unit number
   6890  *      config          (INOUT) UDF hashing configuration info
   6891  * Returns:
   6892  *      BCM_E_NONE      UDF hashing added successfully
   6893  *      BCM_E_NOT_FOUND Requested UDF hashing info does not exist
   6894  *      BCM_E_XXX       Standard error code
   6895  * Notes:
   6896  */
   6897 int
   6898 bcmi_xgs4_udf_hash_config_get(
   6899     int unit,
   6900     bcm_udf_hash_config_t *config)
   6901 {
   6902     int i, j, found = 0, rv;
   6903     bcmi_xgs4_udf_offset_info_t *offset_info = NULL;
   6904     bcmi_xgs4_udf_offset_info_t *offset_match = NULL;
   6905     bcmi_xgs4_udf_tcam_info_t *tcam_info = NULL;
   6906     soc_mem_t mem;
   6907     fp_udf_offset_entry_t offset_buf;
   6908     uint8 udf_hash_1, udf_hash_2;
   6909     uint32 mask, mask_1 = 0, mask_2 = 0;
   6910     int byte_map[] = {13, 12, 15, 14};
   6911 
   6912     /* UDF Module Init check */
   6913     UDF_INIT_CHECK(unit);
   6914 
   6915     /* UDF Module Lock */
   6916     UDF_LOCK(unit);
   6917 
   6918     if ((config == NULL)) {
   6919         UDF_UNLOCK(unit);
   6920         return BCM_E_PARAM;
   6921     }
   6922 
   6923     rv = bcmi_xgs4_udf_offset_node_get(unit, config->udf_id, &offset_info);
   6924     if (BCM_FAILURE(rv)) {
   6925         UDF_UNLOCK(unit);
   6926         return rv;
   6927     }
   6928 
   6929     udf_hash_1 = UDF_CTRL(unit)->udf_hash_1;
   6930     udf_hash_2 = UDF_CTRL(unit)->udf_hash_2;
   6931     if (!(offset_info->flags & BCMI_XGS4_UDF_OFFSET_UDFHASH) ||
   6932         !(offset_info->flags & BCMI_XGS4_UDF_OFFSET_UDFHASH_CONFIG) ||
   6933         !(offset_info->hw_bmap & ((1 << udf_hash_1) | (1 << udf_hash_2)))) {
   6934         UDF_UNLOCK(unit);
   6935         return BCM_E_PARAM;
   6936     }
   6937 
   6938     mem = UDF_CTRL(unit)->offset_mem;
   6939 
   6940     tcam_info = UDF_CTRL(unit)->tcam_info_head;
   6941 
   6942     while (tcam_info != NULL) {
   6943         /* Get the first entry related to the UDF id */
   6944         for (i = 0; i < BCMI_XGS4_UDF_CTRL_MAX_UDF_CHUNKS(unit); i++) {
   6945             offset_match = tcam_info->offset_info_list[i];
   6946             if (offset_info == offset_match) {
   6947                 rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   6948                     tcam_info->hw_idx, &offset_buf);
   6949                 if (BCM_FAILURE(rv)) {
   6950                     UDF_UNLOCK(unit);
   6951                     return rv;
   6952                 }
   6953 
   6954                 mask_1 = soc_mem_field32_get(unit, mem, &offset_buf,
   6955                     HASH_MASK_1f);
   6956                 mask_2 = soc_mem_field32_get(unit, mem, &offset_buf,
   6957                     HASH_MASK_2f);
   6958 
   6959                 found = 1;
   6960                 break;
   6961             }
   6962         }
   6963 
   6964         if (found) {
   6965             break;
   6966         }
   6967         tcam_info = tcam_info->next;
   6968     }
   6969 
   6970     mask = (mask_1 << 16) | (mask_2 & 0xFFFF);
   6971 
   6972     /* mask[0]~[3] reflect to the order in byte_bmap */
   6973     for (i = 0, j = 0; i < BCM_UDF_HASH_MAX_LENGTH; i++) {
   6974         if (offset_info->byte_bmap & (1 << byte_map[i])) {
   6975             config->hash_mask[j++] = (mask >> (8 * (3 - i))) & 0xFF;
   6976         }
   6977     }
   6978     config->mask_length = offset_info->width;
   6979     config->flags = 0;
   6980 
   6981     /* Release UDF mutex */
   6982     UDF_UNLOCK(unit);
   6983 
   6984     return BCM_E_NONE;
   6985 }
   6986 
   6987 
   6988 /*
   6989  * Function:
   6990  *      bcmi_xgs4_udf_hash_config_get_all
   6991  * Purpose:
   6992  *      Get all added UDF ids from list
   6993  * Parameters:
   6994  *      unit                  (IN) BCM unit number
   6995  *      max                   (IN) Max count of UDF ids in the list.
   6996  *      udf_hash_config_list  (OUT) List of UDF hashing configuration
   6997  *      actual                (OUT) Actual count of UDF ids
   6998  * Returns:
   6999  *      BCM_E_NONE      UDF hashing added successfully
   7000  *      BCM_E_XXX       Standard error code
   7001  * Notes:
   7002  */
   7003 int
   7004 bcmi_xgs4_udf_hash_config_get_all(
   7005     int unit,
   7006     int max,
   7007     bcm_udf_hash_config_t *udf_hash_config_list,
   7008     int *actual)
   7009 {
   7010     bcmi_xgs4_udf_offset_info_t *tmp;
   7011     bcm_udf_hash_config_t config;
   7012     int rv;
   7013 
   7014     /* UDF Module Init check */
   7015     UDF_INIT_CHECK(unit);
   7016 
   7017     BCM_IF_NULL_RETURN_PARAM(actual);
   7018 
   7019     /* UDF Module Lock */
   7020     UDF_LOCK(unit);
   7021 
   7022     *actual = 0;
   7023     tmp = UDF_CTRL(unit)->offset_info_head;
   7024 
   7025     while (tmp != NULL) {
   7026         /* the udf id is in the list, get its config */
   7027         if (tmp->flags & BCMI_XGS4_UDF_OFFSET_UDFHASH_CONFIG) {
   7028             if ((*actual < max) && (udf_hash_config_list != NULL)) {
   7029                 (&config)->udf_id = tmp->udf_id;
   7030                 rv = bcmi_xgs4_udf_hash_config_get(unit, &config);
   7031                 if (BCM_FAILURE(rv)) {
   7032                     UDF_UNLOCK(unit);
   7033                     return rv;
   7034                 }
   7035                 sal_memcpy((udf_hash_config_list + (*actual)), &config,
   7036                     sizeof(bcm_udf_hash_config_t));
   7037             }
   7038 
   7039             (*actual) += 1;
   7040         }
   7041 
   7042         tmp = tmp->next;
   7043     }
   7044 
   7045     /* Release UDF mutex */
   7046     UDF_UNLOCK(unit);
   7047 
   7048     return BCM_E_NONE;
   7049 }
   7050 
   7051 #if defined (BCM_TOMAHAWK_SUPPORT)
   7052 /*
   7053  * Function:
   7054  *      bcmi_xgs4_udf_oper_mode_set
   7055  * Purpose:
   7056  *      Configure udf operation mode
   7057  * Parameters:
   7058  *      unit - (IN) Unit number.
   7059  *      oper_mode - (IN) operation mode.
   7060  * Returns:
   7061  *      BCM_E_NONE - Operation successful
   7062  *      BCM_E_PARAM - Invalid operational mode
   7063  *      BCM_E_INIT - BCM unit not initialized
   7064  *      BCM_E_BUSY - UDF tcam or offset memory has a valid entry configured
   7065  * Notes:
   7066  */
   7067 int
   7068 bcmi_xgs4_udf_oper_mode_set(
   7069     int unit,
   7070     bcm_udf_oper_mode_t mode)
   7071 {
   7072     if (!(soc_feature(unit, soc_feature_udf_multi_pipe_support))) {
   7073         return BCM_E_UNAVAIL;
   7074     }
   7075 
   7076     /* UDF Module Init check */
   7077     UDF_INIT_CHECK(unit);
   7078 
   7079     if ((mode != bcmUdfOperModeGlobal) &&
   7080        (mode != bcmUdfOperModePipeLocal)) {
   7081         return BCM_E_PARAM;
   7082     }
   7083 
   7084     if (bcmi_xgs4_udf_oper_mode[unit] == mode) {
   7085         return BCM_E_NONE;
   7086     }
   7087 
   7088     if (UDF_CTRL(unit)->num_udfs > 0 ||
   7089         UDF_CTRL(unit)->num_pkt_formats > 0) {
   7090         return BCM_E_BUSY;
   7091     }
   7092 
   7093     if (UDF_CTRL(unit)->udf_used_by_module == UDF_USED_BY_FIELD_MODULE) {
   7094         return BCM_E_BUSY;
   7095     }
   7096 
   7097     bcmi_xgs4_udf_oper_mode[unit] = mode;
   7098 
   7099     BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_ser_init(unit, mode));
   7100 
   7101     BCM_IF_ERROR_RETURN(bcmi_xgs4_udf_ctrl_init(unit));
   7102 
   7103     UDF_CTRL(unit)->udf_used_by_module = UDF_USED_BY_UDF_MODULE;
   7104     return BCM_E_NONE;
   7105 }
   7106 
   7107 /*
   7108  * Function:
   7109  *      bcmi_xgs4_udf_oper_mode_get
   7110  * Purpose:
   7111  *      Retrieve udf operation mode
   7112  * Parameters:
   7113  *      unit - (IN) Unit number.
   7114  *      oper_mode - (INOUT) operation mode.
   7115  * Returns:
   7116  *      BCM_E_NONE - Operation successful
   7117  *      BCM_E_INIT - BCM unit not initialized
   7118  *      BCM_E_UNAVAIL - Feature is not available
   7119 * Notes:
   7120  */
   7121 int
   7122 bcmi_xgs4_udf_oper_mode_get(
   7123     int unit,
   7124     bcm_udf_oper_mode_t *mode)
   7125 {
   7126     if (!(soc_feature(unit, soc_feature_udf_multi_pipe_support))) {
   7127         return BCM_E_UNAVAIL;
   7128     }
   7129     /* UDF Module Init check */
   7130     UDF_INIT_CHECK(unit);
   7131 
   7132     *mode = bcmi_xgs4_udf_oper_mode[unit];
   7133 
   7134     return BCM_E_NONE;
   7135 }
   7136 
   7137 /*
   7138  * Function:
   7139  *      bcmi_xgs4_udf_ser_init
   7140  * Purpose:
   7141  *      Initialize the SER for the given operational mode
   7142  *
   7143  * Parameters:
   7144  *      unit    - (IN) BCM Device number.
   7145  *      mode    - (IN) UDF Operational Mode enum value.
   7146  * Returns:
   7147  *      BCM_E_NONE   - Operation successful.
   7148  *      BCM_E_PARAM  - Invalid operational mode.
   7149  *      BCM_E_XXX    - For others.
   7150  *
   7151  * Notes:
   7152  */
   7153 int
   7154 bcmi_xgs4_udf_ser_init(
   7155     int unit,
   7156     bcm_udf_oper_mode_t mode)
   7157 {
   7158     int               ser_mode;     /* SER mode */
   7159     int               rv;           /* Return Value */
   7160 
   7161     /* Validate input parameters */
   7162     if ((mode != bcmUdfOperModeGlobal) &&
   7163         (mode != bcmUdfOperModePipeLocal)) {
   7164         return BCM_E_PARAM;
   7165     }
   7166 
   7167     /* Update the SER mode */
   7168     ser_mode = (mode == bcmUdfOperModeGlobal) ?
   7169                _SOC_SER_MEM_MODE_GLOBAL:_SOC_SER_MEM_MODE_PIPE_UNIQUE;
   7170 
   7171     SOC_IF_ERROR_RETURN(soc_generic_ser_mem_scan_stop(unit));
   7172     rv = soc_generic_ser_mem_update(unit, FP_UDF_TCAMm, 7, ser_mode);
   7173     if (SOC_FAILURE(rv)) {
   7174         LOG_CLI((BSL_META("Udf TCAM SER memory update fail \n")));
   7175         return rv;
   7176     }
   7177 
   7178     rv = soc_generic_ser_mem_update(unit, FP_UDF_OFFSETm, -1, ser_mode);
   7179     if (SOC_FAILURE(rv)) {
   7180         LOG_CLI((BSL_META("Udf OFFSET SER memory update fail \n")));
   7181         return rv;
   7182     }
   7183     SOC_IF_ERROR_RETURN(soc_generic_ser_mem_scan_start(unit));
   7184 
   7185    return BCM_E_NONE;
   7186 }
   7187 
   7188 #endif