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

fcoe.c (220978B)


      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:        fcoe.c
      8  * Purpose:     Trident2 FCoE functions
      9  */
     10 #include <soc/defs.h>
     11 
     12 #if defined(BCM_TRIDENT2_SUPPORT)
     13 
     14 #include <assert.h>
     15 #include <shared/bsl.h>
     16 #include <sal/core/libc.h>
     17 
     18 #include <soc/mem.h>
     19 #include <soc/debug.h>
     20 #include <soc/cm.h>
     21 #include <soc/drv.h>
     22 #include <soc/register.h>
     23 #include <soc/memory.h>
     24 #include <soc/hash.h>
     25 #include <soc/l2x.h>
     26 #include <soc/l3x.h>
     27 #include <soc/lpm.h>
     28 #include <soc/trident2.h>
     29 #include <bcm/l2.h>
     30 #include <bcm/l3.h>
     31 #include <bcm/error.h>
     32 #include <bcm/fcoe.h>
     33 #include <bcm/switch.h>
     34 #include <bcm_int/esw/trx.h>
     35 #include <bcm_int/esw/l2.h>
     36 #include <bcm_int/esw/l3.h>
     37 #include <bcm_int/esw/fcoe.h>
     38 #include <bcm_int/esw/trident.h>
     39 #include <bcm_int/esw/trident2.h>
     40 #include <bcm_int/esw/qos.h>
     41 #include <bcm_int/esw/vlan.h>
     42 #include <bcm_int/esw/trx.h>
     43 #include <shared/idxres_fl.h>
     44 #include <soc/scache.h>
     45 
     46 #ifdef BCM_TRIDENT3_SUPPORT
     47 #include <soc/trident3.h>
     48 #endif /* BCM_TRIDENT3_SUPPORT */
     49 typedef uint32 L2_ENTRY_T[SOC_MAX_MEM_FIELD_WORDS];
     50 
     51 /* VSAN resource manager */
     52 STATIC shr_idxres_list_handle_t vsan_id_list[BCM_MAX_NUM_UNITS] = {NULL};
     53 
     54 #define FCOE_MAX_VSAN_ID       0xfff
     55 #define FCOE_MAX_SRC_DEST_ID   0xffffff
     56 #define FCOE_ZONE_MAX_CLASS_ID 0x3f
     57 
     58 #ifdef BCM_WARM_BOOT_SUPPORT
     59 /* VSAN ID reserve state */
     60 #define FCOE_VSAN_ID_BYTES     512   /* 4096 IDs, 1 bits per id = 512 bytes */
     61 typedef struct {
     62     uint8 state[FCOE_VSAN_ID_BYTES];  /* 1 bits per VSAN ID */
     63 } _vsan_id_reserve_state;
     64 
     65 STATIC _vsan_id_reserve_state _vsan_id_state[BCM_MAX_NUM_UNITS];
     66 
     67 #define BCM_WB_VERSION_1_0                SOC_SCACHE_VERSION(1,0)
     68 #define BCM_WB_VERSION_1_1                SOC_SCACHE_VERSION(1,1)
     69 #define BCM_WB_DEFAULT_VERSION            BCM_WB_VERSION_1_1
     70 
     71 #endif
     72 
     73 typedef int (*fcoe_traverse_cb_f)(int unit, soc_mem_t mem, uint32 *buf,
     74                                   bcm_fcoe_route_t *route);
     75 
     76 #define VFT_NUM_ENTRIES  1  /* 1 entry per set in EGR_VFT_FIELDS_PROFILE */
     77 #define VFT_NUM_PROFILES 8  /* 8 profiles available in EGR_VFT_FIELDS_PROFILE */
     78 
     79 /* Hardware values for FC_HDR_ENCODE field defined in architecture spec */
     80 #define FC_HEADER_TYPE_NOT_PRESENT   0
     81 #define FC_HEADER_TYPE_STANDARD      1
     82 #define FC_HEADER_TYPE_VFT           2
     83 #define FC_HEADER_TYPE_ENCAPSULATION 3
     84 #define FC_HEADER_TYPE_IFR           4
     85 #define FC_HEADER_TYPE_UNKNOWN       6
     86 
     87 /* Values for EGR_L3_INTF.FCOE_VFT_ACTION */
     88 #define FCOE_VFT_ACTION_DO_NOT_MODIFY       0
     89 #define FCOE_VFT_ACTION_ADD_REPLACE         1
     90 #define FCOE_VFT_ACTION_DELETE              2
     91 
     92 /* Values for EGR_L3_INTF.FCOE_FABRIC_ID_SEL */
     93 #define FCOE_FABRIC_ID_SEL_SET              0
     94 #define FCOE_FABRIC_ID_SEL_INTERNAL         1
     95 #define FCOE_FABRIC_ID_SEL_INNER_VLAN       2
     96 #define FCOE_FABRIC_ID_SEL_OUTER_VLAN       3
     97 
     98 /* Values for EGR_L3_INTF.FCOE_FABRIC_PRI_SEL */
     99 #define FCOE_FABRIC_PRI_SEL_SET             0
    100 #define FCOE_FABRIC_PRI_SEL_INTERNAL        1
    101 #define FCOE_FABRIC_PRI_SEL_REMARK          2
    102 #define FCOE_ROUTE_READ_RETURN_L3_INTF 0
    103 #define FCOE_ROUTE_READ_RETURN_NHID 1
    104 
    105 #define CHECK_FLAGS_NOT_SET(flags, values) \
    106     if (((flags) & (values)) != 0) { \
    107         return BCM_E_PARAM; \
    108     }
    109 
    110 typedef struct _bcm_td2_fcoe_bookkeeping_s {
    111     uint8 profile_use_refcnt[VFT_NUM_PROFILES];
    112 } _bcm_td2_fcoe_bookkeeping_t;
    113 
    114 static _bcm_td2_fcoe_bookkeeping_t _bcm_td2_fcoe_bk_info[BCM_MAX_NUM_UNITS];
    115 
    116 /*
    117  * Function:    bcm_td2_fcoe_init
    118  * Purpose:     Initialize the FCOE module.
    119  * Parameters:  unit - SOC unit number.
    120  * Returns:     BCM_E_XXX
    121  */
    122 int
    123 bcm_td2_fcoe_init(int unit)
    124 {
    125 #ifdef BCM_WARM_BOOT_SUPPORT
    126     int                 fcoe_scache_size;
    127     soc_scache_handle_t scache_handle;
    128     uint8               *fcoe_scache_ptr;
    129 #endif
    130     int rv = BCM_E_NONE;
    131 
    132 #ifdef BCM_WARM_BOOT_SUPPORT
    133     if (SOC_WARM_BOOT(unit)) {
    134         return _bcm_td2_fcoe_reinit(unit);
    135     }
    136 #endif
    137 
    138     /* create vsan id list manager */
    139     rv = shr_idxres_list_create(&vsan_id_list[unit], 0, FCOE_MAX_VSAN_ID,
    140                                 0, FCOE_MAX_VSAN_ID, "VSAN ID");
    141     if (rv != BCM_E_NONE) {
    142         return rv;
    143     }
    144 
    145 #ifdef BCM_WARM_BOOT_SUPPORT
    146 
    147     memset(&_vsan_id_state[unit], 0, sizeof(_vsan_id_reserve_state));
    148 
    149     fcoe_scache_size = sizeof(_vsan_id_reserve_state) * BCM_MAX_NUM_UNITS;
    150 
    151     fcoe_scache_size += sizeof(_bcm_td2_fcoe_bookkeeping_t);
    152 
    153     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FCOE, 0);
    154 
    155     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE,
    156                                  fcoe_scache_size, &fcoe_scache_ptr,
    157                                  BCM_WB_DEFAULT_VERSION, NULL);
    158 
    159     if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
    160         return rv;
    161     }
    162 
    163 #endif
    164 
    165     memset(&_bcm_td2_fcoe_bk_info[unit].profile_use_refcnt, 0, 
    166            sizeof _bcm_td2_fcoe_bk_info[unit].profile_use_refcnt);
    167 
    168     return BCM_E_NONE;
    169 }
    170 
    171 #ifdef BCM_WARM_BOOT_SUPPORT
    172 
    173 STATIC int
    174 _bcm_td2_vsan_id_creation_state_get(int unit, int vsan_id)
    175 {
    176     uint32 byte_index;
    177     uint32 bit_index;
    178     uint8  state_val;
    179     uint8  tmp = 0;
    180 
    181     /* find corresponding bit for vsan id */
    182     byte_index = vsan_id / 8;
    183     bit_index = vsan_id % 8;
    184     tmp = 1 << bit_index;
    185     state_val = _vsan_id_state[unit].state[byte_index];
    186 
    187     if ((state_val & tmp) != 0) {   /* state bit is 1 */
    188         return 1;
    189     } else {
    190         return 0;
    191     }
    192 }
    193 
    194 STATIC void
    195 _bcm_td2_vsan_id_creation_state_set(int unit, int vsan_id, int state)
    196 {
    197     uint32 byte_index;
    198     uint32 bit_index;
    199     uint8  state_val;
    200     uint8  tmp = 0;
    201 
    202     /* find corresponding bit for vsan id */
    203     byte_index = vsan_id / 8;
    204     bit_index = vsan_id % 8;
    205     tmp = 1 << bit_index;
    206     state_val = _vsan_id_state[unit].state[byte_index];
    207 
    208     if (state == 0) { 
    209         /* clear state */
    210         state_val = state_val & ~tmp;
    211 
    212     } else {
    213         /* set state */
    214         state_val = state_val | tmp;
    215     }
    216     /* update table */
    217     _vsan_id_state[unit].state[byte_index] = state_val;
    218 }
    219 
    220 STATIC int
    221 _bcm_td2_recreate_reserved_entries(int unit)
    222 {
    223     uint32 vsan_id;
    224     int    rv;
    225     int index;
    226     soc_mem_t mem = ING_VSANm;
    227     ing_vsan_entry_t vsan_entry;
    228 
    229     /* release VSAN list manager */
    230     if (vsan_id_list[unit] != NULL) {
    231         /* the following can be failed if we have stale pointer. Igonre it */
    232         (void)shr_idxres_list_destroy(vsan_id_list[unit]);
    233         vsan_id_list[unit] = NULL;
    234     }
    235 
    236     /* re-create vsan id list manager */
    237     rv = shr_idxres_list_create(&vsan_id_list[unit], 0, FCOE_MAX_VSAN_ID,
    238                                 0, FCOE_MAX_VSAN_ID, "VSAN ID");
    239     if (rv != BCM_E_NONE) {
    240         return rv;
    241     }
    242 
    243     for (vsan_id = 0; vsan_id <= FCOE_MAX_VSAN_ID; vsan_id++) {
    244         if (_bcm_td2_vsan_id_creation_state_get(unit, vsan_id) != 0) {
    245             /*reserve entry */
    246             BCM_IF_ERROR_RETURN(
    247                 shr_idxres_list_reserve(vsan_id_list[unit], vsan_id, vsan_id));
    248 
    249             /* Recover FC_MAP_PROFILE references */
    250             BCM_IF_ERROR_RETURN(
    251                 soc_mem_read(unit, mem, MEM_BLOCK_ANY, vsan_id, &vsan_entry));
    252             index = soc_mem_field32_get(unit,mem, &vsan_entry,
    253                                         FCOE_FC_MAP_INDEXf);
    254             BCM_IF_ERROR_RETURN(
    255                 _bcm_fc_map_profile_entry_reference(unit, index, 1));
    256         }
    257     }
    258     return BCM_E_NONE;
    259 }
    260 
    261 int
    262 _bcm_td2_fcoe_sync(int unit)
    263 {
    264     soc_scache_handle_t scache_handle;
    265     uint8               *fcoe_scache_ptr;
    266     int                 rv;
    267 
    268     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FCOE, 0);
    269 
    270     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, 
    271                                  &fcoe_scache_ptr,
    272                                  BCM_WB_DEFAULT_VERSION, NULL);
    273 
    274     /* Note : If no storage is configured, the above function will return
    275      *        with BCM_E_NOT_FOUND. This is the correct behavior for
    276      *        UNSYNCHRONIZED mode.
    277      */
    278 
    279     if (rv == BCM_E_NONE) {
    280         /* copy data to cache */
    281         sal_memcpy(fcoe_scache_ptr, &_vsan_id_state[unit], 
    282                    sizeof(_vsan_id_reserve_state));
    283         fcoe_scache_ptr += sizeof(_vsan_id_reserve_state) * BCM_MAX_NUM_UNITS;
    284 
    285         /* BCM_WB_VERSION_1_1 */
    286         sal_memcpy(fcoe_scache_ptr, &_bcm_td2_fcoe_bk_info[unit],
    287                    sizeof(_bcm_td2_fcoe_bookkeeping_t));
    288         fcoe_scache_ptr += sizeof(_bcm_td2_fcoe_bookkeeping_t);
    289     }
    290 
    291     return BCM_E_NONE;
    292 }
    293 
    294 int
    295 _bcm_td2_fcoe_reinit(int unit)
    296 {
    297     int rv;
    298     soc_scache_handle_t scache_handle;
    299     uint8               *fcoe_scache_ptr;
    300     uint16 recovered_ver = 0;
    301     uint32 additional_scache_size = 0;
    302     int index;
    303     int refcnt = 0;
    304 
    305     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_FCOE, 0);
    306 
    307     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, 
    308                                  &fcoe_scache_ptr,
    309                                  BCM_WB_DEFAULT_VERSION, &recovered_ver);
    310     if (rv == BCM_E_NOT_FOUND) {
    311         fcoe_scache_ptr = NULL;
    312 
    313     } else if (SOC_FAILURE(rv)) {
    314         return rv;
    315     } else {
    316         /* success, recover data (copy data from cache) */
    317         sal_memcpy(&_vsan_id_state[unit], fcoe_scache_ptr, 
    318                    sizeof(_vsan_id_reserve_state));
    319         fcoe_scache_ptr += sizeof(_vsan_id_reserve_state) * BCM_MAX_NUM_UNITS;
    320         if (recovered_ver >=  BCM_WB_VERSION_1_1) {
    321             sal_memcpy(&_bcm_td2_fcoe_bk_info[unit], fcoe_scache_ptr,
    322                        sizeof(_bcm_td2_fcoe_bookkeeping_t));
    323             fcoe_scache_ptr += sizeof(_bcm_td2_fcoe_bookkeeping_t);
    324             for (index = 0; index < VFT_NUM_PROFILES; index++) {
    325                 if (_bcm_td2_fcoe_bk_info[unit].profile_use_refcnt[index]) {
    326                     refcnt = _bcm_td2_fcoe_bk_info[unit].profile_use_refcnt[index];
    327                     while (refcnt--) {
    328                         _bcm_egr_vft_fields_entry_reference(unit, index, 1);
    329                     }
    330                 }
    331             }
    332         } else {
    333             additional_scache_size += sizeof(_bcm_td2_fcoe_bookkeeping_t);
    334         }
    335         if (additional_scache_size > 0) {
    336             SOC_IF_ERROR_RETURN
    337                 (soc_scache_realloc(unit, scache_handle, additional_scache_size));
    338         }
    339 
    340         BCM_IF_ERROR_RETURN(_bcm_td2_recreate_reserved_entries(unit));
    341     }
    342 
    343     return BCM_E_NONE;
    344 }
    345 
    346 #endif
    347 
    348 /*
    349  * Function:    bcm_td2_fcoe_cleanup
    350  * Purpose:     Cleanup the FCOE module.
    351  * Parameters:  unit - SOC unit number.
    352  * Returns:     BCM_E_XXX
    353  */
    354 int
    355 bcm_td2_fcoe_cleanup(int unit)
    356 {
    357     int rv = BCM_E_NONE;
    358 
    359     /* free vsan id list manager */
    360     if (vsan_id_list[unit] != NULL) {
    361         rv = shr_idxres_list_destroy(vsan_id_list[unit]);
    362 
    363         if (rv != BCM_E_NONE) {
    364             return rv;
    365         } else {
    366             vsan_id_list[unit] = NULL;
    367         }
    368     }
    369 
    370     
    371 
    372     return rv;
    373 }
    374 
    375 /* mark vsan ID as Reserved */
    376 STATIC int
    377 _bcm_fcoe_reserve_vsan_id (int unit, uint32 vsan_id)
    378 {
    379 #ifdef BCM_WARM_BOOT_SUPPORT
    380     SOC_CONTROL_LOCK(unit);
    381     SOC_CONTROL(unit)->scache_dirty = 1;
    382     SOC_CONTROL_UNLOCK(unit);
    383 
    384     /* mark as created */
    385     _bcm_td2_vsan_id_creation_state_set(unit, vsan_id, 1);
    386 #endif
    387 
    388     return shr_idxres_list_reserve(vsan_id_list[unit], vsan_id, vsan_id);
    389 }
    390 
    391 /* unreserve vsan ID */
    392 STATIC int
    393 _bcm_fcoe_unreserve_vsan_id (int unit, uint32 vsan_id)
    394 {
    395 #ifdef BCM_WARM_BOOT_SUPPORT
    396     SOC_CONTROL_LOCK(unit);
    397     SOC_CONTROL(unit)->scache_dirty = 1;
    398     SOC_CONTROL_UNLOCK(unit);
    399 
    400     _bcm_td2_vsan_id_creation_state_set(unit, vsan_id, 0);
    401 #endif
    402 
    403     return shr_idxres_list_free(vsan_id_list[unit], vsan_id);
    404 }
    405 
    406 STATIC int
    407 _bcm_fcoe_zone_validate(bcm_fcoe_zone_entry_t *zone)
    408 {
    409     if ((zone->vsan_id > FCOE_MAX_VSAN_ID)        ||  /* 12 bits */
    410         (zone->d_id > FCOE_MAX_SRC_DEST_ID)       ||  /* 24 bits */
    411         (zone->s_id > FCOE_MAX_SRC_DEST_ID)       ||  /* 24 bits */
    412         (zone->class_id < 0)                      ||
    413         (zone->class_id > FCOE_ZONE_MAX_CLASS_ID) ||  /* 6 bits */
    414         (zone->action > bcmFcoeZoneActionRedirect)) {
    415         return BCM_E_PARAM;
    416     }
    417     return BCM_E_NONE;
    418 }
    419 
    420 /*
    421  * Purpose:
    422  *      Add FCoE zoning entry
    423  * Parameters:
    424  *      unit       - Device unit number
    425  *      zone       - zone entry
    426  * Returns:
    427  *      BCM_E_NONE - Success.
    428  *      BCM_E_XXX
    429  */
    430 int
    431 bcm_td2_fcoe_zone_add(int unit, bcm_fcoe_zone_entry_t *zone)
    432 {
    433     L2_ENTRY_T  l2_entry;
    434     L2_ENTRY_T  l2_lookup;
    435     soc_mem_t   mem;
    436     soc_field_t field_key;
    437     int         rv = BCM_E_NONE;
    438     int         l2_index = 0, valid_f;
    439 
    440     if (_bcm_fcoe_zone_validate(zone) != BCM_E_NONE) {
    441         return BCM_E_PARAM;
    442     }
    443 
    444     sal_memset(&l2_entry, 0, sizeof (l2_entry));
    445     sal_memset(&l2_lookup, 0, sizeof (l2_lookup));
    446 
    447     mem = L2Xm;
    448     valid_f = VALIDf;
    449 
    450 #ifdef BCM_TRIDENT3_SUPPORT
    451     if (SOC_IS_TRIDENT3X(unit)) 
    452         valid_f = BASE_VALIDf;
    453 #endif
    454 
    455     field_key = TD2_L2_HASH_KEY_TYPE_FCOE_ZONE;
    456 
    457     soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    458                         valid_f, 1);                             /* [1] */
    459     soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    460                                  KEY_TYPEf, field_key);         /* fcoe type */
    461     soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    462                         FCOE_ZONE__VSAN_IDf, zone->vsan_id);    /* vsan ID */
    463     soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    464                         FCOE_ZONE__D_IDf, zone->d_id);          /* D_ID */
    465     soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    466                         FCOE_ZONE__S_IDf, zone->s_id);          /* S_ID */
    467     soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    468                         FCOE_ZONE__CLASS_IDf, zone->class_id);  /* CLASS_ID */
    469     soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    470                         FCOE_ZONE__STATIC_BITf, 1);
    471 
    472     /*
    473      * set action field  & copy_to_cpu field
    474      */
    475     switch (zone->action) {
    476         case bcmFcoeZoneActionAllow:
    477             soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    478                                 FCOE_ZONE__ACTIONf, 1);
    479             break;
    480         case bcmFcoeZoneActionDeny:
    481             /* action field is already 0 */
    482             break;
    483         case bcmFcoeZoneActionCopyToCpu:
    484 #ifdef BCM_TRIDENT3_SUPPORT
    485             if (SOC_IS_TRIDENT3X(unit)) {
    486                 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    487                                 FCOE_ZONE__CPUf, 1);
    488             } else 
    489 #endif /* BCM_TRIDENT3_SUPPORT */
    490             {
    491                 soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    492                                     FCOE_ZONE__COPY_TO_CPUf, 1);
    493             }
    494             break;
    495         case bcmFcoeZoneActionRedirect:
    496             /* fallthru */
    497         default:
    498             return BCM_E_UNAVAIL;
    499             break;
    500     }
    501 
    502     /* See if the entry already exists */
    503     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &l2_index,
    504                         (void *)&l2_entry, (void *)&l2_lookup, 0);
    505 
    506     if (rv == SOC_E_NONE) {
    507         /*
    508          * entry already exist. (l2_index gets the location)
    509          * rewrite using new data
    510          */
    511         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, l2_index, &l2_entry);
    512     } else if (rv == SOC_E_NOT_FOUND) {
    513         /* Not found,  add entry */
    514         rv = soc_mem_insert(unit, mem, MEM_BLOCK_ANY, (void *)&l2_entry);
    515     } else {
    516         return rv;
    517     }
    518     return rv;
    519 }
    520 
    521 
    522 /*
    523  * Purpose:
    524  *      Delete Zone check entry
    525  * Parameters:
    526  *      unit       - Device unit number
    527  *      zone       - zone entry to be deleted
    528  * Returns:
    529  *      BCM_E_NONE - Success.
    530  *      BCM_E_XXX
    531  */
    532 int
    533 bcm_td2_fcoe_zone_delete(int unit, bcm_fcoe_zone_entry_t *zone)
    534 {
    535     L2_ENTRY_T  l2_entry;
    536     L2_ENTRY_T  l2_lookup;
    537     soc_mem_t   mem;
    538     soc_field_t field_key;
    539     int         rv = BCM_E_NONE;
    540     int         l2_index = 0;
    541 
    542     sal_memset(&l2_entry, 0, sizeof (l2_entry));
    543     sal_memset(&l2_lookup, 0, sizeof (l2_lookup));
    544 
    545     mem = L2Xm;
    546 
    547     field_key = TD2_L2_HASH_KEY_TYPE_FCOE_ZONE;
    548 
    549     soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    550                                  KEY_TYPEf, field_key);         /* fcoe type */
    551     soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    552                         FCOE_ZONE__VSAN_IDf, zone->vsan_id);    /* vsan ID */
    553     soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    554                         FCOE_ZONE__D_IDf, zone->d_id);          /* D_ID */
    555     soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
    556                         FCOE_ZONE__S_IDf, zone->s_id);          /* S_ID */
    557 
    558 
    559     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &l2_index,
    560                         (void *)&l2_entry, (void *)&l2_lookup, 0);
    561 
    562     if ((rv < 0) && (rv != BCM_E_NOT_FOUND)) {
    563         return rv;
    564     }
    565 
    566     rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, (void *)&l2_entry);
    567     return rv;
    568 }
    569 
    570 
    571 /*
    572  * Description:
    573  *      Delete all zone check entries
    574  * Parameters:
    575  *     unit             - device number
    576  * Return:
    577  *     BCM_E_XXX
    578  */
    579 int
    580 bcm_td2_fcoe_zone_delete_all (int unit)
    581 {
    582     int           ix;
    583     int           key_type;
    584     int           chnk_end;
    585     int           chunksize;
    586     int           chunk;
    587     int           chunk_max;
    588     int            mem_idx_max;
    589     L2_ENTRY_T    *l2e;
    590     L2_ENTRY_T    *l2ep;
    591     soc_control_t *soc = SOC_CONTROL(unit);
    592     soc_mem_t     mem;
    593     int           rv = BCM_E_NONE, valid_f;
    594 
    595     chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS,
    596                                  L2_MEM_CHUNKS_DEFAULT);
    597 
    598     mem = L2Xm;
    599     valid_f  = VALIDf;
    600 
    601 #ifdef BCM_TRIDENT3_SUPPORT
    602     if (SOC_IS_TRIDENT3X(unit)) 
    603         valid_f = BASE_VALIDf;
    604 #endif
    605 
    606     l2e = soc_cm_salloc(unit, chunksize * sizeof(*l2e), "l2entrydel_chunk");
    607 
    608     if (l2e == NULL) {
    609         return BCM_E_MEMORY;
    610     }
    611 
    612     mem_idx_max = soc_mem_index_max(unit, mem);
    613 
    614     soc_mem_lock(unit, mem);
    615 
    616     for (chunk = soc_mem_index_min(unit, mem); chunk <= mem_idx_max;
    617          chunk += chunksize) {
    618 
    619         chunk_max = chunk + chunksize - 1;
    620 
    621         if (chunk_max > mem_idx_max) {
    622             chunk_max = mem_idx_max;
    623         }
    624 
    625         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
    626                                 chunk, chunk_max, l2e);
    627         if (rv < 0) {
    628             break;
    629         }
    630 
    631         chnk_end = (chunk_max - chunk);
    632 
    633         for (ix = 0; ix <= chnk_end; ix++) {
    634             l2ep = soc_mem_table_idx_to_pointer(unit, mem,
    635                                                  L2_ENTRY_T *, l2e, ix);
    636             if (!soc_mem_field32_get(unit, mem, l2ep, valid_f)) {
    637                 continue;
    638             }
    639 
    640             /* we won't check set/check FCOE_ZONE__STATIC_BITf for now...
    641             if (soc_mem_field32_get(unit, mem, l2ep, FCOE_ZONE__STATIC_BITf)) {
    642                 continue;
    643             }*/
    644 
    645             /* Match the Key Type to FCOE */
    646             key_type = soc_mem_field32_get(unit, mem, l2ep, KEY_TYPEf);
    647 
    648             if (key_type != TD2_L2_HASH_KEY_TYPE_FCOE_ZONE) {
    649                 continue;
    650             }
    651 
    652             if (SOC_L2_DEL_SYNC_LOCK(soc) < 0) {
    653                 rv = BCM_E_RESOURCE;
    654                 break;
    655             }
    656 
    657             if (((rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL, l2ep)) < 0) ||
    658                 ((rv = soc_l2x_sync_delete(unit, (uint32 *) l2ep,
    659                                            (chunk + ix), 0)) < 0)) {
    660                 SOC_L2_DEL_SYNC_UNLOCK(soc);
    661                 break;
    662             }
    663 
    664             SOC_L2_DEL_SYNC_UNLOCK(soc);
    665         }
    666 
    667         if (rv < 0) {
    668             break;
    669         }
    670     }
    671 
    672     soc_mem_unlock(unit, mem);
    673     soc_cm_sfree(unit, l2e);
    674 
    675     return rv;
    676 }
    677 
    678 
    679 /*
    680  * Description:
    681  *      Delete all zone check entries matching VSAN ID
    682  * Parameters:
    683  *      unit       - device number
    684  *      zone       - zone entry with VSAN ID to be deleted
    685  * Return:
    686  *      BCM_E_XXX
    687  */
    688 int
    689 bcm_td2_fcoe_zone_delete_by_vsan (int unit, bcm_fcoe_zone_entry_t *zone)
    690 {
    691     int           ix;
    692     int           key_type;
    693     int           chnk_end;
    694     int           chunksize;
    695     int           chunk;
    696     int           chunk_max;
    697     int            mem_idx_max;
    698     L2_ENTRY_T    *l2e;
    699     L2_ENTRY_T    *l2ep;
    700     soc_control_t *soc = SOC_CONTROL(unit);
    701     soc_mem_t     mem;
    702     int           rv = BCM_E_NONE, valid_f;
    703     uint32        vsan_id;
    704 
    705     chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS,
    706                                  L2_MEM_CHUNKS_DEFAULT);
    707 
    708     mem = L2Xm;
    709     valid_f = VALIDf;
    710 
    711 #ifdef BCM_TRIDENT3_SUPPORT
    712     if (SOC_IS_TRIDENT3X(unit)) 
    713         valid_f = BASE_VALIDf;
    714 #endif
    715 
    716     l2e = soc_cm_salloc(unit, chunksize * sizeof(*l2e), "l2entrydel_chunk");
    717 
    718     if (l2e == NULL) {
    719         return BCM_E_MEMORY;
    720     }
    721 
    722     mem_idx_max = soc_mem_index_max(unit, mem);
    723 
    724     soc_mem_lock(unit, mem);
    725 
    726     for (chunk = soc_mem_index_min(unit, mem); chunk <= mem_idx_max;
    727          chunk += chunksize) {
    728 
    729         chunk_max = chunk + chunksize - 1;
    730 
    731         if (chunk_max > mem_idx_max) {
    732             chunk_max = mem_idx_max;
    733         }
    734 
    735         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
    736                                 chunk, chunk_max, l2e);
    737         if (rv < 0) {
    738             break;
    739         }
    740 
    741         chnk_end = (chunk_max - chunk);
    742 
    743         for (ix = 0; ix <= chnk_end; ix++) {
    744             l2ep = soc_mem_table_idx_to_pointer(unit, mem,
    745                                                  L2_ENTRY_T *, l2e, ix);
    746             if (!soc_mem_field32_get(unit, mem, l2ep, valid_f)) {
    747                 continue;
    748             }
    749 
    750             /* we won't check set/check FCOE_ZONE__STATIC_BITf for now...
    751             if (soc_mem_field32_get(unit, mem, l2ep, FCOE_ZONE__STATIC_BITf)) {
    752                 continue;
    753             }*/
    754 
    755             /* Match the Key Type to FCOE */
    756             key_type = soc_mem_field32_get(unit, mem, l2ep, KEY_TYPEf);
    757 
    758             if (key_type != TD2_L2_HASH_KEY_TYPE_FCOE_ZONE) {
    759                 continue;
    760             }
    761 
    762             /* match vsan id */
    763             vsan_id = soc_mem_field32_get(unit, mem, l2ep, FCOE_ZONE__VSAN_IDf);
    764 
    765             if (vsan_id != zone->vsan_id) {
    766                 continue;
    767             }
    768 
    769             if (SOC_L2_DEL_SYNC_LOCK(soc) < 0) {
    770                 rv = BCM_E_RESOURCE;
    771                 break;
    772             }
    773 
    774             if (((rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL, l2ep)) < 0) ||
    775                 ((rv = soc_l2x_sync_delete(unit, (uint32 *) l2ep,
    776                                            (chunk + ix), 0)) < 0)) {
    777                 SOC_L2_DEL_SYNC_UNLOCK(soc);
    778                 break;
    779             }
    780 
    781             SOC_L2_DEL_SYNC_UNLOCK(soc);
    782         }
    783 
    784         if (rv < 0) {
    785             break;
    786         }
    787     }
    788 
    789     soc_mem_unlock(unit, mem);
    790     soc_cm_sfree(unit, l2e);
    791 
    792     return rv;
    793 }
    794 
    795 
    796 /*
    797  * Description:
    798  *      Delete all zone check entries matching Source ID
    799  * Parameters:
    800  *      unit       - device number
    801  *      zone       - zone entry with S_ID to be deleted
    802  * Return:
    803  *      BCM_E_XXX
    804  */
    805 int
    806 bcm_td2_fcoe_zone_delete_by_sid (int unit, bcm_fcoe_zone_entry_t *zone)
    807 {
    808     int           ix;
    809     int           key_type;
    810     int           chnk_end;
    811     int           chunksize;
    812     int           chunk;
    813     int           chunk_max;
    814     int            mem_idx_max;
    815     L2_ENTRY_T    *l2e;
    816     L2_ENTRY_T    *l2ep;
    817     soc_control_t *soc = SOC_CONTROL(unit);
    818     soc_mem_t     mem;
    819     int           rv = BCM_E_NONE, valid_f;
    820     uint32        s_id;
    821 
    822     chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS,
    823                                  L2_MEM_CHUNKS_DEFAULT);
    824 
    825     mem = L2Xm;
    826     valid_f = VALIDf;
    827 
    828 #ifdef BCM_TRIDENT3_SUPPORT
    829     if (SOC_IS_TRIDENT3X(unit))
    830         valid_f = BASE_VALIDf;
    831 #endif
    832 
    833     l2e = soc_cm_salloc(unit, chunksize * sizeof(*l2e), "l2entrydel_chunk");
    834 
    835     if (l2e == NULL) {
    836         return BCM_E_MEMORY;
    837     }
    838 
    839     mem_idx_max = soc_mem_index_max(unit, mem);
    840 
    841     soc_mem_lock(unit, mem);
    842 
    843     for (chunk = soc_mem_index_min(unit, mem); chunk <= mem_idx_max;
    844          chunk += chunksize) {
    845 
    846         chunk_max = chunk + chunksize - 1;
    847 
    848         if (chunk_max > mem_idx_max) {
    849             chunk_max = mem_idx_max;
    850         }
    851 
    852         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
    853                                 chunk, chunk_max, l2e);
    854         if (rv < 0) {
    855             break;
    856         }
    857 
    858         chnk_end = (chunk_max - chunk);
    859 
    860         for (ix = 0; ix <= chnk_end; ix++) {
    861             l2ep = soc_mem_table_idx_to_pointer(unit, mem,
    862                                                  L2_ENTRY_T *, l2e, ix);
    863             if (!soc_mem_field32_get(unit, mem, l2ep, valid_f)) {
    864                 continue;
    865             }
    866 
    867             /* we won't check set/check FCOE_ZONE__STATIC_BITf for now...
    868             if (soc_mem_field32_get(unit, mem, l2ep, FCOE_ZONE__STATIC_BITf)) {
    869                 continue;
    870             }*/
    871 
    872             /* Match the Key Type to FCOE */
    873             key_type = soc_mem_field32_get(unit, mem, l2ep, KEY_TYPEf);
    874 
    875             if (key_type != TD2_L2_HASH_KEY_TYPE_FCOE_ZONE) {
    876                 continue;
    877             }
    878 
    879             /* match s_id */
    880             s_id = soc_mem_field32_get(unit, mem, l2ep, FCOE_ZONE__S_IDf);
    881 
    882             if (s_id != zone->s_id) {
    883                 continue;
    884             }
    885 
    886             if (SOC_L2_DEL_SYNC_LOCK(soc) < 0) {
    887                 rv = BCM_E_RESOURCE;
    888                 break;
    889             }
    890 
    891             if (((rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL, l2ep)) < 0) ||
    892                 ((rv = soc_l2x_sync_delete(unit, (uint32 *) l2ep,
    893                                            (chunk + ix), 0)) < 0)) {
    894                 SOC_L2_DEL_SYNC_UNLOCK(soc);
    895                 break;
    896             }
    897 
    898             SOC_L2_DEL_SYNC_UNLOCK(soc);
    899         }
    900 
    901         if (rv < 0) {
    902             break;
    903         }
    904     }
    905 
    906     soc_mem_unlock(unit, mem);
    907     soc_cm_sfree(unit, l2e);
    908 
    909     return rv;
    910 }
    911 
    912 
    913 /*
    914  * Description:
    915  *      Delete all zone check entries matching Destination ID
    916  * Parameters:
    917  *      unit       - device number
    918  *      zone       - zone entry with D_ID to be deleted
    919  * Return:
    920  *      BCM_E_XXX
    921  */
    922 int
    923 bcm_td2_fcoe_zone_delete_by_did (int unit, bcm_fcoe_zone_entry_t *zone)
    924 {
    925     int           ix;
    926     int           key_type;
    927     int           chnk_end;
    928     int           chunksize;
    929     int           chunk;
    930     int           chunk_max;
    931     int            mem_idx_max;
    932     L2_ENTRY_T    *l2e;
    933     L2_ENTRY_T    *l2ep;
    934     soc_control_t *soc = SOC_CONTROL(unit);
    935     soc_mem_t     mem;
    936     int           rv = BCM_E_NONE, valid_f;
    937     uint32        d_id;
    938 
    939     chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS,
    940                                  L2_MEM_CHUNKS_DEFAULT);
    941 
    942     mem = L2Xm;
    943     valid_f = VALIDf;
    944 
    945 #ifdef BCM_TRIDENT3_SUPPORT
    946     if (SOC_IS_TRIDENT3X(unit))
    947         valid_f = BASE_VALIDf;
    948 #endif
    949 
    950     l2e = soc_cm_salloc(unit, chunksize * sizeof(*l2e), "l2entrydel_chunk");
    951 
    952     if (l2e == NULL) {
    953         return BCM_E_MEMORY;
    954     }
    955 
    956     mem_idx_max = soc_mem_index_max(unit, mem);
    957 
    958     soc_mem_lock(unit, mem);
    959 
    960     for (chunk = soc_mem_index_min(unit, mem); chunk <= mem_idx_max;
    961          chunk += chunksize) {
    962 
    963         chunk_max = chunk + chunksize - 1;
    964 
    965         if (chunk_max > mem_idx_max) {
    966             chunk_max = mem_idx_max;
    967         }
    968 
    969         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
    970                                 chunk, chunk_max, l2e);
    971         if (rv < 0) {
    972             break;
    973         }
    974 
    975         chnk_end = (chunk_max - chunk);
    976 
    977         for (ix = 0; ix <= chnk_end; ix++) {
    978             l2ep = soc_mem_table_idx_to_pointer(unit, mem,
    979                                                  L2_ENTRY_T *, l2e, ix);
    980             if (!soc_mem_field32_get(unit, mem, l2ep, valid_f)) {
    981                 continue;
    982             }
    983 
    984             /* we won't check set/check FCOE_ZONE__STATIC_BITf for now...
    985             if (soc_mem_field32_get(unit, mem, l2ep, FCOE_ZONE__STATIC_BITf)) {
    986                 continue;
    987             }*/
    988 
    989             /* Match the Key Type to FCOE */
    990             key_type = soc_mem_field32_get(unit, mem, l2ep, KEY_TYPEf);
    991 
    992             if (key_type != TD2_L2_HASH_KEY_TYPE_FCOE_ZONE) {
    993                 continue;
    994             }
    995 
    996             /* match d_id */
    997             d_id = soc_mem_field32_get(unit, mem, l2ep, FCOE_ZONE__D_IDf);
    998 
    999             if (d_id != zone->d_id) {
   1000                 continue;
   1001             }
   1002 
   1003             if (SOC_L2_DEL_SYNC_LOCK(soc) < 0) {
   1004                 rv = BCM_E_RESOURCE;
   1005                 break;
   1006             }
   1007 
   1008             if (((rv = soc_mem_delete(unit, mem, MEM_BLOCK_ALL, l2ep)) < 0) ||
   1009                 ((rv = soc_l2x_sync_delete(unit, (uint32 *) l2ep,
   1010                                            (chunk + ix), 0)) < 0)) {
   1011                 SOC_L2_DEL_SYNC_UNLOCK(soc);
   1012                 break;
   1013             }
   1014 
   1015             SOC_L2_DEL_SYNC_UNLOCK(soc);
   1016         }
   1017 
   1018         if (rv < 0) {
   1019             break;
   1020         }
   1021     }
   1022 
   1023     soc_mem_unlock(unit, mem);
   1024     soc_cm_sfree(unit, l2e);
   1025 
   1026     return rv;
   1027 }
   1028 
   1029 
   1030 /*
   1031  * Description:
   1032  *      Retrieve Zone info
   1033  * Parameters:
   1034  *      unit       - device number
   1035  *      zone       - zone entry
   1036  * Return:
   1037  *      BCM_E_XXX
   1038  */
   1039 int
   1040 bcm_td2_fcoe_zone_get (int unit, bcm_fcoe_zone_entry_t *zone)
   1041 {
   1042     L2_ENTRY_T  l2_entry;
   1043     L2_ENTRY_T  l2_lookup;
   1044     soc_mem_t   mem;
   1045     soc_field_t field_key;
   1046     int         rv = BCM_E_NONE;
   1047     int         l2_index = 0;
   1048     uint32      action;
   1049     uint32      copy_to_cpu;
   1050 
   1051     sal_memset(&l2_entry, 0, sizeof (l2_entry));
   1052     sal_memset(&l2_lookup, 0, sizeof (l2_lookup));
   1053 
   1054     mem = L2Xm;
   1055 
   1056     field_key = TD2_L2_HASH_KEY_TYPE_FCOE_ZONE;
   1057 
   1058     soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
   1059                                  KEY_TYPEf, field_key);         /* fcoe type */
   1060     soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
   1061                         FCOE_ZONE__VSAN_IDf, zone->vsan_id);    /* vsan ID */
   1062     soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
   1063                         FCOE_ZONE__D_IDf, zone->d_id);          /* D_ID */
   1064     soc_mem_field32_set(unit, mem, (uint32 *)&l2_entry,
   1065                         FCOE_ZONE__S_IDf, zone->s_id);          /* S_ID */
   1066 
   1067 
   1068     /* See if the entry exists */
   1069     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &l2_index,
   1070                         (void *)&l2_entry, (void *)&l2_lookup, 0);
   1071 
   1072     if (rv == SOC_E_NONE) {
   1073         /* entry found */
   1074         zone->class_id = (int)soc_mem_field32_get(unit, mem,
   1075                                                   (void *)&l2_lookup,
   1076                                                   FCOE_ZONE__CLASS_IDf);
   1077         action = soc_mem_field32_get(unit, mem, (void *)&l2_lookup,
   1078                                      FCOE_ZONE__ACTIONf);
   1079 #ifdef BCM_TRIDENT3_SUPPORT
   1080         if (SOC_IS_TRIDENT3X(unit)) {
   1081             copy_to_cpu = soc_mem_field32_get(unit, mem, (void *)&l2_lookup,
   1082                                           FCOE_ZONE__CPUf);
   1083         } else 
   1084 #endif /* BCM_TRIDENT3_SUPPORT */
   1085         {
   1086             copy_to_cpu = soc_mem_field32_get(unit, mem, (void *)&l2_lookup,
   1087                                               FCOE_ZONE__COPY_TO_CPUf);
   1088         }
   1089 
   1090         /*
   1091          * now, combine action & copy_to_cpu and generate a
   1092          * bcm_fcoe_zone_action_t.
   1093          * It means bcmFcoeZoneActionAllow and bcmFcoeZoneActionCopyToCpu are
   1094          * mutually exclusive. If not, zone action API definition need to be
   1095          * changed. BTW, 'redirect' action is not defined in register spec...
   1096          */
   1097         if (action == 1) {
   1098             zone->action = bcmFcoeZoneActionAllow;
   1099         } else {  /* action is 0 (deny) */
   1100             zone->action = bcmFcoeZoneActionDeny;
   1101             if (copy_to_cpu == 1) {
   1102                 zone->action = bcmFcoeZoneActionCopyToCpu;
   1103             }
   1104         }
   1105     }
   1106 
   1107     return rv;
   1108 }
   1109 
   1110 #ifdef INCLUDE_L3
   1111 
   1112 /*
   1113  * Description:
   1114  *     Allocate a next hop if needed or if incoming route->intf is an l3 egress
   1115  *     object then retrieve the HW nh index
   1116  * Parameters:
   1117  *     unit      - (IN) device number
   1118  *     route     - (IN) route information to be used
   1119  *     index     - (OUT) Index of nexthop info added
   1120  * Returns:
   1121  *     BCM_E_XXX
   1122  */
   1123 STATIC int
   1124 _bcm_fcoe_add_nh_entry(int unit, bcm_fcoe_route_t *route, bcm_if_t *index)
   1125 {
   1126     _bcm_l3_cfg_t l3cfg;
   1127     int rv = BCM_E_NONE;
   1128 
   1129     memset(&l3cfg, 0, sizeof l3cfg);
   1130 
   1131     if (route->flags & BCM_FCOE_COPY_TO_CPU) {
   1132         l3cfg.l3c_flags |= BCM_L3_L2TOCPU;
   1133     }
   1134     if (route->flags & BCM_FCOE_DST_DISCARD) {
   1135         l3cfg.l3c_flags |= BCM_L3_DST_DISCARD;
   1136     }
   1137     if (route->flags & BCM_FCOE_SRC_DISCARD) {
   1138         l3cfg.l3c_flags |= BCM_L3_SRC_DISCARD;
   1139     }
   1140     if (route->flags & BCM_FCOE_NO_HOP_COUNT_CHANGE) {
   1141         l3cfg.l3c_flags |= BCM_L3_KEEP_TTL;
   1142     }
   1143     if (route->flags & BCM_FCOE_MULTIPATH) {
   1144         l3cfg.l3c_ecmp = 1;
   1145     }
   1146 
   1147     l3cfg.l3c_vrf = route->vrf;
   1148     l3cfg.l3c_port_tgid = BCM_GPORT_MODPORT_PORT_GET(route->port);
   1149     l3cfg.l3c_modid = BCM_GPORT_MODPORT_MODID_GET(route->port);
   1150     l3cfg.l3c_prio = route->pri;
   1151     l3cfg.l3c_lookup_class = route->lookup_class;
   1152     l3cfg.l3c_intf = route->intf;
   1153 
   1154 #ifdef BCM_TRIDENT3_SUPPORT
   1155     if (SOC_IS_TRIDENT3X(unit)) {
   1156         l3cfg.l3c_flags2 |= BCM_L3_FLAGS2_FCOE_ONLY;
   1157     }
   1158 #endif /* BCM_TRIDENT3_SUPPORT */
   1159     memcpy(&l3cfg.l3c_mac_addr, route->nexthop_mac, sizeof route->nexthop_mac);
   1160     rv = _bcm_xgs3_nh_init_add(unit, &l3cfg, NULL, index);
   1161 
   1162     return rv;
   1163 }
   1164 
   1165 /*
   1166  * Description:
   1167  *     Create a key for the L3 table (FCOE_EXT view) based on the incoming
   1168  *     route structure
   1169  * Parameters:
   1170  *     unit      - (IN) device number
   1171  *     mem       - (IN) memory to be used
   1172  *     table_row - (OUT) buffer containing a table row to modify
   1173  *     route     - (IN) route information to be used
   1174  * Returns:
   1175  *     BCM_E_XXX
   1176  */
   1177 STATIC int
   1178 _bcm_fcoe_route_construct_key_ext(int unit, soc_mem_t mem, uint32 *table_row,
   1179                                   bcm_fcoe_route_t *route)
   1180 {
   1181     int key_type;
   1182     int key_field;
   1183     int key_value;
   1184 
   1185     if (route->vrf >= SOC_VRF_MAX(unit) || route->vrf == 0)
   1186         return BCM_E_PARAM;
   1187 
   1188     soc_mem_field32_set(unit, mem, table_row, FCOE_EXT__VRF_IDf, route->vrf);
   1189 
   1190 #ifdef BCM_TRIDENT3_SUPPORT
   1191     if (SOC_IS_TRIDENT3X(unit)) {
   1192         int data_type;
   1193         if (route->flags & BCM_FCOE_HOST_ROUTE) {
   1194             key_type  = (int)TD3_L3_HASH_KEY_TYPE_FCOE_HOST_EXT;
   1195             data_type = (int)TD3_L3_HASH_DATA_TYPE_FCOE_HOST_EXT;
   1196             key_field = FCOE_EXT__D_IDf;
   1197             key_value = route->nport_id;
   1198         } else if (route->flags & BCM_FCOE_SOURCE_ROUTE) {
   1199             key_type  = (int)TD3_L3_HASH_KEY_TYPE_FCOE_SOURCE_MAP_EXT;
   1200             data_type = (int)TD3_L3_HASH_DATA_TYPE_FCOE_SOURCE_MAP_EXT;
   1201             key_field = FCOE_EXT__S_IDf;
   1202             key_value = route->nport_id;
   1203         } else if (route->flags & BCM_FCOE_DOMAIN_ROUTE) {
   1204             key_type  = (int)TD3_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT;
   1205             data_type = (int)TD3_L3_HASH_DATA_TYPE_FCOE_DOMAIN_EXT;
   1206             key_field = FCOE_EXT__MASKED_D_IDf;
   1207             key_value = route->nport_id & route->nport_id_mask;
   1208         } else {
   1209             /* route must be either host, source, or domain */
   1210             return BCM_E_PARAM;
   1211         }
   1212 
   1213         soc_mem_field32_set(unit, mem, table_row, KEY_TYPEf, key_type);
   1214         soc_mem_field32_set(unit, mem, table_row, DATA_TYPEf, data_type);
   1215         soc_mem_field32_set(unit, mem, table_row, key_field, key_value);
   1216         soc_mem_field32_set(unit, mem, table_row, BASE_VALID_0f, 1);
   1217         soc_mem_field32_set(unit, mem, table_row, BASE_VALID_1f, 7);
   1218     } else
   1219 #endif
   1220     {
   1221         if (route->flags & BCM_FCOE_HOST_ROUTE) {
   1222             key_type  = (int)TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT;
   1223             key_field = FCOE_EXT__D_IDf;
   1224             key_value = route->nport_id;
   1225         } else if (route->flags & BCM_FCOE_SOURCE_ROUTE) {
   1226             key_type  = (int)TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT;
   1227             key_field = FCOE_EXT__S_IDf;
   1228             key_value = route->nport_id;
   1229         } else if (route->flags & BCM_FCOE_DOMAIN_ROUTE) {
   1230             key_type  = (int)TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT;
   1231             key_field = FCOE_EXT__MASKED_D_IDf;
   1232             key_value = route->nport_id & route->nport_id_mask;
   1233         } else {
   1234             /* route must be either host, source, or domain */
   1235             return BCM_E_PARAM;
   1236         }
   1237 
   1238         soc_mem_field32_set(unit, mem, table_row, KEY_TYPE_0f, key_type);
   1239         soc_mem_field32_set(unit, mem, table_row, KEY_TYPE_1f, key_type);
   1240         soc_mem_field32_set(unit, mem, table_row, key_field, key_value);
   1241         soc_mem_field32_set(unit, mem, table_row, VALID_0f, 1);
   1242         soc_mem_field32_set(unit, mem, table_row, VALID_1f, 1);
   1243     }
   1244 
   1245     return BCM_E_NONE;
   1246 }
   1247 
   1248 /*
   1249  * Description:
   1250  *     Construct an L3 table key (FCOE view) from the given route
   1251  * Parameters:
   1252  *     unit      - (IN) device number
   1253  *     mem       - (IN) memory (table) used
   1254  *     table_row - (OUT) buffer holding a table row
   1255  *     index     - (IN) Index of nexthop info added
   1256  * Returns:
   1257  *     BCM_E_XXX
   1258  */
   1259 STATIC int
   1260 _bcm_fcoe_route_construct_key_normal(int unit, soc_mem_t mem, uint32 *table_row,
   1261                                      bcm_fcoe_route_t *route)
   1262 {
   1263     if (route->vrf >= SOC_VRF_MAX(unit) || route->vrf == 0)
   1264         return BCM_E_PARAM;
   1265 
   1266     soc_mem_field32_set(unit, mem, table_row, FCOE__VRF_IDf, route->vrf);
   1267 
   1268 #ifdef BCM_TRIDENT3_SUPPORT
   1269     if (SOC_IS_TRIDENT3X(unit)) {
   1270         if (route->flags & BCM_FCOE_HOST_ROUTE) {
   1271             soc_mem_field32_set(unit, mem, table_row, DATA_TYPEf,
   1272                                 TD3_L3_HASH_DATA_TYPE_FCOE_HOST);
   1273             soc_mem_field32_set(unit, mem, table_row, KEY_TYPEf,
   1274                                 TD3_L3_HASH_KEY_TYPE_FCOE_HOST);
   1275             soc_mem_field32_set(unit, mem, table_row, FCOE__D_IDf,
   1276                                 route->nport_id);
   1277         } else if (route->flags & BCM_FCOE_SOURCE_ROUTE) {
   1278             soc_mem_field32_set(unit, mem, table_row, DATA_TYPEf,
   1279                                 TD3_L3_HASH_DATA_TYPE_FCOE_SOURCE_MAP);
   1280             soc_mem_field32_set(unit, mem, table_row, KEY_TYPEf,
   1281                                 TD3_L3_HASH_KEY_TYPE_FCOE_SOURCE_MAP);
   1282             soc_mem_field32_set(unit, mem, table_row, FCOE__S_IDf,
   1283                                 route->nport_id);
   1284         } else if (route->flags & BCM_FCOE_DOMAIN_ROUTE) {
   1285             soc_mem_field32_set(unit, mem, table_row, DATA_TYPEf,
   1286                                 TD3_L3_HASH_DATA_TYPE_FCOE_DOMAIN);
   1287             soc_mem_field32_set(unit, mem, table_row, KEY_TYPEf,
   1288                                 TD3_L3_HASH_KEY_TYPE_FCOE_DOMAIN);
   1289             soc_mem_field32_set(unit, mem, table_row, FCOE__MASKED_D_IDf,
   1290                                 route->nport_id & route->nport_id_mask);
   1291         } else {
   1292             /* route must be either host, source, or domain */
   1293             return BCM_E_PARAM;
   1294         }
   1295     } else
   1296 #endif /* BCM_TRIDENT3_SUPPORT */
   1297     {
   1298         if (route->flags & BCM_FCOE_HOST_ROUTE) {
   1299             soc_mem_field32_set(unit, mem, table_row, KEY_TYPEf,
   1300                                 TD2_L3_HASH_KEY_TYPE_FCOE_HOST);
   1301             soc_mem_field32_set(unit, mem, table_row, FCOE__D_IDf,
   1302                                 route->nport_id);
   1303         } else if (route->flags & BCM_FCOE_SOURCE_ROUTE) {
   1304             soc_mem_field32_set(unit, mem, table_row, KEY_TYPEf,
   1305                                 TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP);
   1306             soc_mem_field32_set(unit, mem, table_row, FCOE__S_IDf,
   1307                                 route->nport_id);
   1308         } else if (route->flags & BCM_FCOE_DOMAIN_ROUTE) {
   1309             soc_mem_field32_set(unit, mem, table_row, KEY_TYPEf,
   1310                                 TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN);
   1311             soc_mem_field32_set(unit, mem, table_row, FCOE__MASKED_D_IDf,
   1312                                 route->nport_id & route->nport_id_mask);
   1313         } else {
   1314             /* route must be either host, source, or domain */
   1315             return BCM_E_PARAM;
   1316         }
   1317     }
   1318 
   1319 #ifdef BCM_TRIDENT3_SUPPORT
   1320     if (SOC_IS_TRIDENT3X(unit)) {
   1321         soc_mem_field32_set(unit, mem, table_row, BASE_VALIDf, 1);
   1322     } else
   1323 #endif
   1324     {
   1325         soc_mem_field32_set(unit, mem, table_row, VALIDf, 1);
   1326     }
   1327 
   1328     return BCM_E_NONE;
   1329 }
   1330 
   1331 
   1332 /* 
   1333  * _bcm_td2_fcoe_number_bits_set
   1334  *   Return the number of bits set in the input parameter i. It works, trust me.
   1335  */
   1336 STATIC int
   1337 _bcm_td2_fcoe_number_bits_set(uint32 i)
   1338 {
   1339     i = i - ((i >> 1) & 0x55555555);
   1340     i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
   1341     return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
   1342 }
   1343 
   1344 /*
   1345  * _bcm_td2_fcoe_route_is_prefix:
   1346  *    Return TRUE for domain prefix routes, and FALSE for all other routes
   1347  */
   1348 STATIC int
   1349 _bcm_td2_fcoe_route_is_prefix(int unit, bcm_fcoe_route_t *route)
   1350 {
   1351     int domainPrefixLength = 0;
   1352     int routeBitsSet = 0;
   1353     int rv = bcm_esw_switch_control_get(unit, 
   1354                                         bcmSwitchFcoeDomainRoutePrefixLength,
   1355                                         &domainPrefixLength);
   1356 
   1357     if (BCM_FAILURE(rv)) {
   1358         return FALSE;
   1359     }
   1360 
   1361     routeBitsSet = _bcm_td2_fcoe_number_bits_set(route->nport_id_mask);
   1362 
   1363     return (route->flags & BCM_FCOE_DOMAIN_ROUTE) 
   1364            && (domainPrefixLength == routeBitsSet);
   1365 }
   1366 
   1367 /*
   1368  * Description:
   1369  *     Convert modport-gport into the hardware specific global logical port
   1370  * Parameters:
   1371  *     port      - (IN) port
   1372  *     glp       - (OUT) resulting global logical port
   1373  * Returns:
   1374  *     BCM_E_XXX
   1375  */
   1376 STATIC int
   1377 _bcm_fcoe_port_to_glp(bcm_gport_t port, int *glp)
   1378 {
   1379     int base_port = BCM_GPORT_MODPORT_PORT_GET(port);
   1380     int base_modid = BCM_GPORT_MODPORT_MODID_GET(port);
   1381 
   1382     int port_id = (_BCM_TD2_L3_PORT_MASK & base_port);
   1383     int modid   = (_BCM_TD2_L3_MODID_MASK & base_modid)
   1384                   << _BCM_TD2_L3_MODID_SHIFT;
   1385 
   1386     if (!BCM_GPORT_IS_MODPORT(port)) {
   1387         return BCM_E_PARAM;
   1388     }
   1389 
   1390     *glp = (modid | port_id);
   1391     return BCM_E_NONE;
   1392 }
   1393 
   1394 /*
   1395  * Description:
   1396  *     Convert modport-gport into the hardware specific global logical port
   1397  * Parameters:
   1398  *     port      - (IN) port
   1399  *     glp       - (OUT) resulting global logical port
   1400  * Returns:
   1401  *     BCM_E_XXX
   1402  */
   1403 STATIC int
   1404 _bcm_fcoe_glp_to_port(int glp, bcm_gport_t *port)
   1405 {
   1406     int glp_port_id = (_BCM_TD2_L3_PORT_MASK & glp);
   1407     int glp_modid   = (glp >> _BCM_TD2_L3_MODID_SHIFT) & _BCM_TD2_L3_MODID_MASK;
   1408 
   1409     BCM_GPORT_MODPORT_SET(*port, glp_modid, glp_port_id);
   1410 
   1411     return BCM_E_NONE;
   1412 }
   1413 
   1414 /*
   1415  * Description:
   1416  *     Validate elements of the route bcm_fcoe_route_t structure when adding
   1417  *     a route
   1418  * Parameters:
   1419  *     unit      - (IN) unit number
   1420  *     route     - (IN) route to be validated
   1421  * Returns:
   1422  *     BCM_E_XXX
   1423  */
   1424 STATIC int
   1425 _bcm_fcoe_validate_route(int unit, bcm_fcoe_route_t *route)
   1426 {
   1427     if ((route->flags & (BCM_FCOE_HOST_ROUTE
   1428                         | BCM_FCOE_DOMAIN_ROUTE
   1429                         | BCM_FCOE_SOURCE_ROUTE)) == 0) {
   1430         return BCM_E_PARAM;
   1431     }
   1432 
   1433     if (BCM_XGS3_L3_EGRESS_MODE_ISSET(unit) == 0) {
   1434         bcm_l3_intf_t find_if;
   1435 
   1436         bcm_l3_intf_t_init(&find_if);
   1437         find_if.l3a_intf_id = route->intf;
   1438         BCM_IF_ERROR_RETURN(bcm_esw_l3_intf_get(unit, &find_if));
   1439 
   1440         if (BCM_MAC_IS_ZERO(route->nexthop_mac))
   1441             return BCM_E_PARAM;
   1442 
   1443         if (!BCM_GPORT_IS_MODPORT(route->port))
   1444             return BCM_E_PARAM;
   1445     }
   1446 
   1447     if (route->vrf >= SOC_VRF_MAX(unit) || route->vrf < BCM_L3_VRF_DEFAULT)
   1448         return BCM_E_PARAM;
   1449 
   1450     if (route->nport_id == 0)
   1451         return BCM_E_PARAM;
   1452 
   1453     if (route->nport_id > FCOE_MAX_SRC_DEST_ID)
   1454         return BCM_E_PARAM;
   1455 
   1456     if (route->lookup_class < 0 || route->lookup_class > FCOE_ZONE_MAX_CLASS_ID)
   1457         return BCM_E_PARAM;
   1458 
   1459     return BCM_E_NONE;
   1460 }
   1461 
   1462 STATIC int _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(int unit)
   1463 {
   1464 #ifdef BCM_TRIDENT3_SUPPORT
   1465     if (SOC_IS_TRIDENT3X(unit)) {   
   1466         return (L3_ENTRY_SINGLEm);
   1467     }
   1468 #endif
   1469     return (L3_ENTRY_IPV4_UNICASTm);
   1470 }
   1471 
   1472 STATIC int _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(int unit)
   1473 {
   1474 #ifdef BCM_TRIDENT3_SUPPORT
   1475     if (SOC_IS_TRIDENT3X(unit)) {   
   1476         return (L3_ENTRY_DOUBLEm);
   1477     }
   1478 #endif
   1479     return (L3_ENTRY_IPV4_MULTICASTm);
   1480 }
   1481 /*
   1482  * Description:
   1483  *     Add a route to the L3 table (FCOE view)
   1484  * Parameters:
   1485  *     unit      - (IN) unit number
   1486  *     route     - (IN) route to be added
   1487  * Returns:
   1488  *     BCM_E_XXX
   1489  */
   1490 STATIC int
   1491 _bcm_td2_fcoe_route_add_normal(int unit, bcm_fcoe_route_t *route, 
   1492                                bcm_if_t nh_idx)
   1493 {
   1494     l3_entry_ipv4_unicast_entry_t l3_entry[2];
   1495 
   1496     soc_mem_t  mem      = _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit);
   1497     uint32     *buf     = (uint32 *)&l3_entry[0];
   1498     uint32     *lookup  = (uint32 *)&l3_entry[1];
   1499     int        existing_index = 0;
   1500     int        rv;
   1501 
   1502     if (route->flags & BCM_FCOE_NO_HOP_COUNT_CHANGE) {
   1503         return BCM_E_PARAM;
   1504     }
   1505 
   1506     memset(&l3_entry, 0, sizeof l3_entry);
   1507 
   1508     BCM_IF_ERROR_RETURN(_bcm_fcoe_validate_route(unit, route));
   1509     BCM_IF_ERROR_RETURN(_bcm_fcoe_route_construct_key_normal(unit, mem, buf,
   1510                                                              route));
   1511 
   1512     soc_mem_field32_set(unit, mem, buf, FCOE__DST_DISCARDf,
   1513                         (route->flags & BCM_FCOE_DST_DISCARD) ? 1 : 0);
   1514     soc_mem_field32_set(unit, mem, buf, FCOE__PRIf, route->pri);
   1515     soc_mem_field32_set(unit, mem, buf, FCOE__RPEf,
   1516                         (route->flags & BCM_FCOE_RPE) ? 1 : 0);
   1517     soc_mem_field32_set(unit, mem, buf, FCOE__CLASS_IDf, route->lookup_class);
   1518 
   1519     /* BCM_FCOE_LOCAL_ADDRESS is only valid in host route mode */
   1520     if ((route->flags & BCM_FCOE_HOST_ROUTE)
   1521         && (route->flags & BCM_FCOE_LOCAL_ADDRESS)) {
   1522         soc_mem_field32_set(unit, mem, buf, FCOE__LOCAL_ADDRESSf, 1);
   1523     }
   1524 
   1525     if (route->flags & BCM_FCOE_MULTIPATH) {
   1526 #ifdef BCM_TRIDENT3_SUPPORT 
   1527         if (SOC_IS_TRIDENT3X(unit)) {
   1528             soc_mem_field32_dest_set(unit, mem, buf, FCOE__DESTINATIONf,
   1529                                      SOC_MEM_FIF_DEST_ECMP, nh_idx);
   1530 
   1531         } else
   1532 #endif
   1533         {
   1534             soc_mem_field32_set(unit, mem, buf, FCOE__ECMP_PTR0f, nh_idx);
   1535             soc_mem_field32_set(unit, mem, buf, FCOE__ECMPf, 1);
   1536         }
   1537     } else {
   1538 #ifdef BCM_TRIDENT3_SUPPORT 
   1539         if (SOC_IS_TRIDENT3X(unit)) {
   1540             soc_mem_field32_dest_set(unit, mem, buf, FCOE__DESTINATIONf,
   1541                                      SOC_MEM_FIF_DEST_NEXTHOP, nh_idx);
   1542         } else
   1543 #endif
   1544         {
   1545             soc_mem_field32_set(unit, mem, buf, FCOE__NEXT_HOP_INDEXf, nh_idx);
   1546         }
   1547     }
   1548 
   1549     /* Search for this key in the existing database */
   1550     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &existing_index, buf,
   1551                         (void *)lookup, 0);
   1552 
   1553     /*
   1554      * If the entry exists, overwrite it with the new data, otherwise insert
   1555      * a new entry
   1556      */
   1557     if (rv == SOC_E_NONE) {
   1558         /*
   1559          * Route exists, and the reference count of old nhi should be adjusted.
   1560          * The current route will be updated to new nhi.
   1561          */
   1562         bcm_if_t old_nh_idx = 0;
   1563 #ifdef BCM_TRIDENT3_SUPPORT 
   1564         if (SOC_IS_TRIDENT3X(unit)) {
   1565             uint32 dest_type = SOC_MEM_FIF_DEST_INVALID;
   1566 
   1567             old_nh_idx = soc_mem_field32_dest_get(unit, mem, lookup,
   1568                                          DESTINATIONf, &dest_type);
   1569             if (dest_type == SOC_MEM_FIF_DEST_ECMP) {
   1570                 BCM_IF_ERROR_RETURN(bcm_xgs3_ecmp_group_del(unit, old_nh_idx, 0));
   1571             } else {
   1572                 BCM_IF_ERROR_RETURN(bcm_xgs3_nh_del(unit, 0, old_nh_idx));
   1573             }
   1574         } else
   1575 #endif
   1576         {
   1577             if (soc_mem_field32_get(unit, mem, lookup, FCOE__ECMPf)) {
   1578                 old_nh_idx = soc_mem_field32_get(unit, mem, 
   1579                                                  lookup, FCOE__ECMP_PTR0f);
   1580                 BCM_IF_ERROR_RETURN(bcm_xgs3_ecmp_group_del(unit, old_nh_idx, 0));
   1581             } else {
   1582                 old_nh_idx= soc_mem_field32_get(unit, mem, lookup,
   1583                                             FCOE__NEXT_HOP_INDEXf);
   1584                 BCM_IF_ERROR_RETURN(bcm_xgs3_nh_del(unit, 0, old_nh_idx));
   1585             }
   1586         }
   1587     }
   1588 
   1589     L3_LOCK(unit);
   1590     if (rv == SOC_E_NONE) {
   1591         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, existing_index, buf);
   1592     } else if (rv == SOC_E_NOT_FOUND) {
   1593         rv = soc_mem_insert(unit, mem, MEM_BLOCK_ANY, buf);
   1594     }
   1595     L3_UNLOCK(unit);
   1596 
   1597     return rv;
   1598 }
   1599 
   1600 /*
   1601  * Description:
   1602  *     Add a route to the L3 table (FCOE_EXT view)
   1603  * Parameters:
   1604  *     unit      - (IN) unit number
   1605  *     route     - (IN) route to be added
   1606  * Returns:
   1607  *     BCM_E_XXX
   1608  */
   1609 STATIC int
   1610 _bcm_td2_fcoe_route_add_ext(int unit, bcm_fcoe_route_t *route)
   1611 {
   1612     l3_entry_ipv4_multicast_entry_t l3_ext_entry[2];
   1613 
   1614     soc_mem_t  mem            = _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit);
   1615     uint32     *buf           = (uint32 *)&l3_ext_entry[0];
   1616     uint32     *lookup        = (uint32 *)&l3_ext_entry[1];
   1617     int        existing_index = 0;
   1618     int        rv;
   1619     int        glp;
   1620 
   1621     memset(&l3_ext_entry, 0, sizeof l3_ext_entry);
   1622 
   1623     BCM_IF_ERROR_RETURN(_bcm_fcoe_validate_route(unit, route));
   1624     BCM_IF_ERROR_RETURN(_bcm_fcoe_route_construct_key_ext(unit, mem, buf,
   1625                                                           route));
   1626 
   1627     soc_mem_field32_set(unit, mem, buf, FCOE_EXT__DST_DISCARDf,
   1628                         (route->flags & BCM_FCOE_DST_DISCARD) ? 1 : 0);
   1629     soc_mem_field32_set(unit, mem, buf, FCOE_EXT__PRIf, route->pri);
   1630     soc_mem_field32_set(unit, mem, buf, FCOE_EXT__RPEf,
   1631                         (route->flags & BCM_FCOE_RPE) ? 1 : 0);
   1632     soc_mem_field32_set(unit, mem, buf, FCOE_EXT__CLASS_IDf,
   1633                         route->lookup_class);
   1634 
   1635     /* BCM_FCOE_LOCAL_ADDRESS is only valid in host route mode */
   1636     if ((route->flags & BCM_FCOE_HOST_ROUTE)
   1637         && (route->flags & BCM_FCOE_LOCAL_ADDRESS)) {
   1638 
   1639         soc_mem_field32_set(unit, mem, buf, FCOE_EXT__LOCAL_ADDRESSf, 1);
   1640     }
   1641 
   1642     BCM_IF_ERROR_RETURN(_bcm_fcoe_port_to_glp(route->port, &glp));
   1643 
   1644     soc_mem_field32_set(unit, mem, buf, FCOE_EXT__L3_INTF_NUMf,
   1645                         route->intf);
   1646     soc_mem_mac_addr_set(unit, mem, buf, FCOE_EXT__MAC_ADDRf,
   1647                         route->nexthop_mac);
   1648     soc_mem_field32_set(unit, mem, buf, FCOE_EXT__COPY_TO_CPUf,
   1649                         (route->flags & BCM_FCOE_COPY_TO_CPU) ? 1 : 0);
   1650 #ifdef BCM_TRIDENT3_SUPPORT
   1651     if (SOC_IS_TRIDENT3X(unit)) {
   1652         uint32 physical_port;
   1653         soc_mem_field32_set(unit, mem, buf, FCOE_EXT__DO_NOT_DECREMENT_TTLf,
   1654                         (route->flags & BCM_FCOE_NO_HOP_COUNT_CHANGE)
   1655                             ? 1 : 0);
   1656 
   1657         physical_port = (BCM_GPORT_MODPORT_MODID_GET(route->port) << 
   1658                          SOC_MEM_FIF_DGPP_MOD_ID_SHIFT_BITS) |
   1659                          BCM_GPORT_MODPORT_PORT_GET(route->port);
   1660 
   1661         soc_mem_field32_dest_set(unit, mem, buf, FCOE_EXT__DESTINATIONf,
   1662                                      SOC_MEM_FIF_DEST_DGPP, physical_port);
   1663     } else
   1664 #endif
   1665     {
   1666         soc_mem_field32_set(unit, mem, buf, FCOE_EXT__DO_NOT_CHANGE_TTLf,
   1667                             (route->flags & BCM_FCOE_NO_HOP_COUNT_CHANGE)
   1668                             ? 1 : 0);
   1669         soc_mem_field32_set(unit, mem, buf, FCOE_EXT__GLPf, glp);
   1670     }
   1671 
   1672     /* Search for this key in the existing database */
   1673     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &existing_index, buf,
   1674                         (void *)lookup, 0);
   1675 
   1676     /*
   1677      * If the entry exists, overwrite it with the new data, otherwise insert
   1678      * a new entry
   1679      */
   1680     L3_LOCK(unit);
   1681     if (rv == SOC_E_NONE) {
   1682         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, existing_index, buf);
   1683     } else if (rv == SOC_E_NOT_FOUND) {
   1684         rv = soc_mem_insert(unit, mem, MEM_BLOCK_ANY, buf);
   1685     }
   1686     L3_UNLOCK(unit);
   1687 
   1688     return rv;
   1689 }
   1690 
   1691 STATIC int
   1692 _bcm_fcoe_route_to_defip(int unit, bcm_fcoe_route_t *route, 
   1693                          _bcm_defip_cfg_t *lpm_cfg)
   1694 {
   1695     int rv = BCM_E_NONE;
   1696     _bcm_defip_cfg_t entry;
   1697     int nh_ecmp_index;
   1698 
   1699     sal_memset(lpm_cfg, 0, sizeof *lpm_cfg);
   1700 
   1701     if (route->flags & BCM_FCOE_COPY_TO_CPU) {
   1702         lpm_cfg->defip_flags |= BCM_L3_L2TOCPU;
   1703     }
   1704     if (route->flags & BCM_FCOE_DST_DISCARD) {
   1705         lpm_cfg->defip_flags |= BCM_L3_DST_DISCARD;
   1706     }
   1707     if (route->flags & BCM_FCOE_SRC_DISCARD) {
   1708         lpm_cfg->defip_flags |= BCM_L3_SRC_DISCARD;
   1709     }
   1710     if (route->flags & BCM_FCOE_NO_HOP_COUNT_CHANGE) {
   1711         lpm_cfg->defip_flags |= BCM_L3_KEEP_TTL;
   1712     }
   1713     if (route->flags & BCM_FCOE_MULTIPATH) {
   1714         lpm_cfg->defip_ecmp = 1;
   1715         lpm_cfg->defip_flags |= BCM_L3_MULTIPATH;
   1716     }
   1717 
   1718     lpm_cfg->defip_vrf = route->vrf;
   1719     lpm_cfg->defip_port_tgid = BCM_GPORT_MODPORT_PORT_GET(route->port);
   1720     lpm_cfg->defip_modid = BCM_GPORT_MODPORT_MODID_GET(route->port);
   1721     lpm_cfg->defip_prio = route->pri;
   1722     lpm_cfg->defip_lookup_class = route->lookup_class;
   1723     lpm_cfg->defip_intf = route->intf;
   1724     lpm_cfg->defip_entry_type = bcmDefipEntryTypeFcoe;
   1725     lpm_cfg->defip_fcoe_d_id = route->nport_id & route->nport_id_mask;
   1726     lpm_cfg->defip_fcoe_d_id_mask = route->nport_id_mask;
   1727 
   1728     memcpy(&lpm_cfg->defip_mac_addr, route->nexthop_mac, 
   1729            sizeof route->nexthop_mac);
   1730     entry = *lpm_cfg;
   1731     rv = _bcm_fb_lpm_get(unit, &entry, &nh_ecmp_index);
   1732     if (BCM_SUCCESS(rv)) {
   1733         /* Save route entry index in hw to indicate  */
   1734         lpm_cfg->defip_index = entry.defip_index;
   1735     } else if (rv == BCM_E_NOT_FOUND){
   1736         /* New route. */
   1737         lpm_cfg->defip_index = BCM_XGS3_L3_INVALID_INDEX;
   1738         rv = BCM_E_NONE;
   1739     }
   1740 
   1741     return rv;
   1742 }
   1743 
   1744 STATIC int
   1745 _bcm_fcoe_defip_to_route(int unit, _bcm_defip_cfg_t *lpm_cfg, 
   1746                          bcm_fcoe_route_t *route)
   1747 {
   1748     int rv = BCM_E_NONE;
   1749 
   1750     sal_memset(route, 0, sizeof *route);
   1751 
   1752     route->flags = BCM_FCOE_DOMAIN_ROUTE;
   1753     
   1754     if (lpm_cfg->defip_flags & BCM_L3_L2TOCPU) {
   1755         route->flags |= BCM_FCOE_COPY_TO_CPU;
   1756     }
   1757 
   1758     if (lpm_cfg->defip_flags & BCM_L3_DST_DISCARD) {
   1759         route->flags |= BCM_FCOE_DST_DISCARD;
   1760     }
   1761 
   1762     if (lpm_cfg->defip_flags & BCM_L3_SRC_DISCARD) {
   1763         route->flags |= BCM_FCOE_SRC_DISCARD;
   1764     }
   1765 
   1766     if (lpm_cfg->defip_flags & BCM_L3_KEEP_TTL) {
   1767         route->flags |= BCM_FCOE_NO_HOP_COUNT_CHANGE;
   1768     }
   1769 
   1770     if (lpm_cfg->defip_ecmp == 1) {
   1771         route->flags |= BCM_FCOE_MULTIPATH;
   1772     }
   1773 
   1774     route->vrf = lpm_cfg->defip_vrf;
   1775     BCM_GPORT_MODPORT_SET(route->port, lpm_cfg->defip_modid, 
   1776                           lpm_cfg->defip_port_tgid);
   1777 
   1778     route->pri = lpm_cfg->defip_prio;
   1779     route->lookup_class = lpm_cfg->defip_lookup_class;
   1780     route->intf = lpm_cfg->defip_intf;
   1781     route->nport_id = lpm_cfg->defip_fcoe_d_id;
   1782     route->nport_id_mask = lpm_cfg->defip_fcoe_d_id_mask;
   1783 
   1784     memcpy(route->nexthop_mac, &lpm_cfg->defip_mac_addr, 
   1785            sizeof route->nexthop_mac);
   1786 
   1787     return rv;
   1788 }
   1789 
   1790 STATIC int
   1791 _bcm_td2_fcoe_route_add_prefix(int unit, bcm_fcoe_route_t *route)
   1792 {
   1793     _bcm_defip_cfg_t lpm_cfg;
   1794     int              nh_idx         = 0;
   1795     int              rv             = BCM_E_NONE;
   1796     int              old_nh_idx     = 0;
   1797     _bcm_defip_cfg_t old_lpm_cfg;
   1798 
   1799     sal_memset(&lpm_cfg, 0, sizeof lpm_cfg);
   1800 
   1801     BCM_IF_ERROR_RETURN(_bcm_fcoe_validate_route(unit, route));
   1802     BCM_IF_ERROR_RETURN(_bcm_fcoe_route_to_defip(unit, route, &lpm_cfg));
   1803     sal_memcpy(&old_lpm_cfg, &lpm_cfg, sizeof(_bcm_defip_cfg_t));
   1804     rv = _bcm_fb_lpm_get(unit, &old_lpm_cfg, &old_nh_idx);
   1805     if (BCM_SUCCESS(rv)) {
   1806         /*
   1807          * Route exists, and the reference count of old nhi should be adjusted.
   1808          * The current route is updated to new nhi.
   1809          */
   1810         if (old_lpm_cfg.defip_flags & BCM_L3_MULTIPATH) {
   1811             BCM_IF_ERROR_RETURN(bcm_xgs3_ecmp_group_del(unit, old_nh_idx, 0));
   1812         } else {
   1813             BCM_IF_ERROR_RETURN(bcm_xgs3_nh_del(unit, 0, old_nh_idx));
   1814         }
   1815     }
   1816     BCM_IF_ERROR_RETURN(_bcm_xgs3_nh_init_add(unit, NULL, &lpm_cfg, &nh_idx));
   1817 
   1818     rv = _bcm_fb_lpm_add(unit, &lpm_cfg, nh_idx);
   1819     if (BCM_FAILURE(rv)) {
   1820         if (route->flags & BCM_FCOE_MULTIPATH) {
   1821             (void) bcm_xgs3_ecmp_group_del(unit, nh_idx, 0);
   1822         } else {
   1823             (void) bcm_xgs3_nh_del(unit, 0, nh_idx);
   1824         }
   1825         return rv;
   1826     }
   1827 
   1828     return BCM_E_NONE;
   1829 }
   1830 
   1831 /*
   1832  * Description: 
   1833  *      Add an entry into FCOE host routing table. Supports add for both
   1834  *      normal (with next-hop) and extended views (embedded nh)
   1835  * Parameters: 
   1836  *      unit    - device number
   1837  *      route   - route information to be added
   1838  * Returns: 
   1839  *      BCM_E_XXX  
   1840  */
   1841 STATIC int
   1842 _bcm_td2_fcoe_route_add_host(int unit, bcm_fcoe_route_t *route)
   1843 {
   1844     int         rv = BCM_E_NONE;
   1845     bcm_if_t    nh_idx;                                    
   1846 
   1847     BCM_IF_ERROR_RETURN(_bcm_fcoe_add_nh_entry(unit, route, &nh_idx));
   1848 
   1849     if (BCM_TD2_L3_USE_EMBEDDED_NEXT_HOP(unit, route->intf, nh_idx)) {
   1850         rv = _bcm_td2_fcoe_route_add_ext(unit, route);
   1851     } else {
   1852         rv = _bcm_td2_fcoe_route_add_normal(unit, route, nh_idx);
   1853     }
   1854 
   1855     if (BCM_FAILURE(rv) && (nh_idx != BCM_XGS3_L3_INVALID_INDEX) && 
   1856         !(route->flags & BCM_FCOE_MULTIPATH)) {
   1857         (void)bcm_xgs3_nh_del(unit, 0, nh_idx);
   1858     }
   1859 
   1860     return rv;
   1861 }
   1862 
   1863 #endif
   1864 
   1865 /*
   1866  * Description:
   1867  *     Add an entry into the FCOE routing table.  This API supports all
   1868  *     three routes:
   1869  *       - Host, source-map, Domain (goes in L3_ENTRY table)
   1870  *       - Prefix (goes in DEFIP table)
   1871  * Parameters:
   1872  *     unit      - device number
   1873  *     route     - route information to be added
   1874  * Returns:
   1875  *     BCM_E_XXX
   1876  */
   1877 int
   1878 bcm_td2_fcoe_route_add(int unit, bcm_fcoe_route_t *route)
   1879 {
   1880 #ifdef INCLUDE_L3
   1881     if (_bcm_td2_fcoe_route_is_prefix(unit, route)) {
   1882         return _bcm_td2_fcoe_route_add_prefix(unit, route);
   1883     } else {
   1884         return _bcm_td2_fcoe_route_add_host(unit, route);
   1885     }
   1886 #else
   1887     return BCM_E_UNAVAIL;
   1888 #endif
   1889 }
   1890 
   1891 #ifdef INCLUDE_L3
   1892 
   1893 /*
   1894  * Description:
   1895  *     Delete a route from the DEFIP table
   1896  * Parameters:
   1897  *     unit      - (IN) unit number
   1898  *     route     - (IN) route to be deleted
   1899  * Returns:
   1900  *     BCM_E_XXX
   1901  */
   1902 STATIC int
   1903 _bcm_td2_fcoe_route_delete_prefix(int unit, uint32 *lookup)
   1904 {
   1905     int nh_idx = 0;
   1906     _bcm_defip_cfg_t lpm_cfg;
   1907 
   1908     sal_memset(&lpm_cfg, 0, sizeof lpm_cfg);
   1909 
   1910 #ifdef BCM_TRIDENT3_SUPPORT
   1911     if (SOC_IS_TRIDENT3X(unit)) {
   1912         uint32 dest_type;
   1913 
   1914         /* delete the left half if it's a valid FCOE entry */
   1915         if (soc_L3_DEFIPm_field32_get(unit, lookup, VALID0f)
   1916             && (soc_L3_DEFIPm_field32_get(unit, lookup, DATA_TYPE0f) == 3)) {
   1917 
   1918             BCM_IF_ERROR_RETURN(
   1919                 _bcm_fb_lpm_ent_parse(unit, &lpm_cfg, &nh_idx,
   1920                                       (uint32 *)lookup, NULL));
   1921             lpm_cfg.defip_index = BCM_XGS3_L3_INVALID_INDEX;
   1922             BCM_IF_ERROR_RETURN(_bcm_fb_lpm_del(unit, &lpm_cfg));
   1923             BCM_IF_ERROR_RETURN(bcm_xgs3_nh_del(unit, 0, nh_idx));
   1924         }
   1925 
   1926         /* 
   1927          * if the right half is a valid FCOE entry, copy it to the left half and
   1928          * then delete 
   1929          */
   1930         if (soc_L3_DEFIPm_field32_get(unit, lookup, VALID1f)
   1931             && (soc_L3_DEFIPm_field32_get(unit, lookup, DATA_TYPE1f) == 3)) {
   1932             nh_idx = soc_mem_field32_dest_get(unit, L3_DEFIPm, lookup,
   1933                                          DESTINATIONf, &dest_type);
   1934             BCM_IF_ERROR_RETURN(soc_fb_lpm_ip4entry1_to_0(unit, lookup, lookup, 0));
   1935             BCM_IF_ERROR_RETURN(soc_fb_lpm_delete(unit, lookup));
   1936             BCM_IF_ERROR_RETURN(bcm_xgs3_nh_del(unit, 0, nh_idx));
   1937         }
   1938     } else 
   1939 #endif
   1940     {
   1941         /* delete the left half if it's a valid FCOE entry */
   1942         if (soc_L3_DEFIPm_field32_get(unit, lookup, VALID0f)
   1943             && (soc_L3_DEFIPm_field32_get(unit, lookup, ENTRY_TYPE0f) == 1)) {
   1944     
   1945             BCM_IF_ERROR_RETURN(
   1946                 _bcm_fb_lpm_ent_parse(unit, &lpm_cfg, &nh_idx,
   1947                                       (uint32 *)lookup, NULL));
   1948     
   1949             lpm_cfg.defip_index = BCM_XGS3_L3_INVALID_INDEX;
   1950             BCM_IF_ERROR_RETURN(_bcm_fb_lpm_del(unit, &lpm_cfg));
   1951             BCM_IF_ERROR_RETURN(bcm_xgs3_nh_del(unit, 0, nh_idx));
   1952         }
   1953     
   1954         /* 
   1955          * if the right half is a valid FCOE entry, copy it to the left half and
   1956          * then delete 
   1957          */
   1958         if (soc_L3_DEFIPm_field32_get(unit, lookup, VALID1f)
   1959             && (soc_L3_DEFIPm_field32_get(unit, lookup, ENTRY_TYPE1f) == 1)) {
   1960 
   1961             nh_idx = soc_L3_DEFIPm_field32_get(unit, lookup, NEXT_HOP_INDEX1f);
   1962             BCM_IF_ERROR_RETURN(soc_fb_lpm_ip4entry1_to_0(unit, lookup, lookup, 0));
   1963             BCM_IF_ERROR_RETURN(soc_fb_lpm_delete(unit, lookup));
   1964             BCM_IF_ERROR_RETURN(bcm_xgs3_nh_del(unit, 0, nh_idx));
   1965         }
   1966     }
   1967 
   1968     return BCM_E_NONE;
   1969 }
   1970 
   1971 /*
   1972  * Description:
   1973  *     Delete a route from hardware.  If the route has a corresponding nexthop
   1974  *     index, delete that too (or decrement refcount).
   1975  * Parameters:
   1976  *     unit      - (IN) unit number
   1977  *     mem       - (IN) memory to be deleted from
   1978  *     lookup    - (IN) table lookup result to be deleted
   1979  * Returns:
   1980  *     BCM_E_XXX
   1981  */
   1982 STATIC int
   1983 _bcm_td2_fcoe_internal_delete_route(int unit, bcm_fcoe_route_t *route, 
   1984                                     soc_mem_t mem, uint32 *lookup) 
   1985 {
   1986     int rv = BCM_E_NONE;
   1987     int next_hop_index = 0;
   1988     int nh_field = FCOE__NEXT_HOP_INDEXf;
   1989 
   1990     if (mem == L3_DEFIPm) {
   1991         return _bcm_td2_fcoe_route_delete_prefix(unit, lookup);
   1992     }
   1993 
   1994 #ifdef BCM_TRIDENT3_SUPPORT
   1995     if (SOC_IS_TRIDENT3X(unit)) {
   1996         nh_field = DESTINATIONf;
   1997     }
   1998 #endif
   1999 
   2000     if (SOC_MEM_FIELD_VALID(unit, mem, nh_field)) {
   2001 #ifdef BCM_TRIDENT3_SUPPORT
   2002         if (SOC_IS_TRIDENT3X(unit)) {
   2003             uint32 dest_type;
   2004             next_hop_index = soc_mem_field32_dest_get(unit, mem, lookup,
   2005                                          nh_field, &dest_type);
   2006             if (dest_type == SOC_MEM_FIF_DEST_ECMP){
   2007                 if ((route != NULL) && !(route->flags & BCM_FCOE_MULTIPATH)) {
   2008                     return BCM_E_PARAM;
   2009                 }
   2010                 rv = bcm_xgs3_ecmp_group_del(unit, next_hop_index, 0);
   2011             } else {
   2012                 rv = bcm_xgs3_nh_del(unit, 0, next_hop_index);
   2013             }
   2014         } else 
   2015 #endif
   2016         {
   2017             next_hop_index = soc_mem_field32_get(unit, mem, lookup, nh_field);
   2018             if (SOC_MEM_FIELD_VALID(unit, mem, FCOE__ECMPf) &&
   2019                 soc_mem_field32_get(unit, mem, lookup, FCOE__ECMPf)) {
   2020                 if ((route != NULL) && !(route->flags & BCM_FCOE_MULTIPATH)) {
   2021                     return BCM_E_PARAM;
   2022                 }
   2023                 rv = bcm_xgs3_ecmp_group_del(unit, next_hop_index, 0);
   2024             } else {
   2025                 rv = bcm_xgs3_nh_del(unit, 0, next_hop_index);
   2026             }
   2027         }
   2028     }
   2029 
   2030     if (BCM_SUCCESS(rv)) {
   2031         L3_LOCK(unit);
   2032         rv = soc_mem_delete(unit, mem, MEM_BLOCK_ANY, (void *)lookup);
   2033         L3_UNLOCK(unit);
   2034     }
   2035 
   2036     return rv;
   2037 }
   2038 
   2039 /*
   2040  * Description:
   2041  *     Delete a route from the L3 table (FCOE view)
   2042  * Parameters:
   2043  *     unit      - (IN) unit number
   2044  *     route     - (IN) route to be deleted
   2045  * Returns:
   2046  *     BCM_E_XXX
   2047  */
   2048 STATIC int
   2049 _bcm_td2_fcoe_route_delete_normal(int unit, bcm_fcoe_route_t *route)
   2050 {
   2051     l3_entry_ipv4_unicast_entry_t   l3_entry[2];
   2052 
   2053     soc_mem_t  mem      = _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit);
   2054     uint32     *buf     = (uint32 *)&l3_entry[0];
   2055     uint32     *lookup  = (uint32 *)&l3_entry[1];
   2056     int        existing_index = 0;
   2057     int        rv;
   2058 
   2059     memset(&l3_entry, 0, sizeof l3_entry);
   2060 
   2061     BCM_IF_ERROR_RETURN(_bcm_fcoe_route_construct_key_normal(unit, mem, buf,
   2062                                                              route));
   2063 
   2064     /* Search for this key in the existing database */
   2065     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &existing_index, buf,
   2066                         (void *)lookup, 0);
   2067     switch (rv) {
   2068         case SOC_E_NOT_FOUND: return BCM_E_NOT_FOUND;
   2069         case SOC_E_NONE: break;
   2070         default: return BCM_E_PARAM;
   2071     }
   2072 
   2073     return _bcm_td2_fcoe_internal_delete_route(unit, route, mem, lookup);
   2074 }
   2075 
   2076 /*
   2077  * Description:
   2078  *     Delete a route from the L3 table (FCOE_EXT view)
   2079  * Parameters:
   2080  *     unit      - (IN) unit number
   2081  *     route     - (IN) route to be deleted
   2082  * Returns:
   2083  *     BCM_E_XXX
   2084  */
   2085 STATIC int
   2086 _bcm_td2_fcoe_route_delete_ext(int unit, bcm_fcoe_route_t *route)
   2087 {
   2088     l3_entry_ipv4_multicast_entry_t l3_ext_entry[2];
   2089 
   2090     soc_mem_t  mem      = _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit);
   2091     uint32     *buf     = (uint32 *)&l3_ext_entry[0];
   2092     uint32     *lookup  = (uint32 *)&l3_ext_entry[1];
   2093     int        existing_index = 0;
   2094     int        rv;
   2095 
   2096     memset(&l3_ext_entry, 0, sizeof l3_ext_entry);
   2097 
   2098     BCM_IF_ERROR_RETURN(_bcm_fcoe_route_construct_key_ext(unit, mem, buf,
   2099                                                           route));
   2100 
   2101     /* Search for this key in the existing database */
   2102     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &existing_index, buf,
   2103                         (void *)lookup, 0);
   2104     switch (rv) {
   2105         case SOC_E_NOT_FOUND: return BCM_E_NOT_FOUND;
   2106         case SOC_E_NONE: break;
   2107         default: return BCM_E_PARAM;
   2108     }
   2109 
   2110     return _bcm_td2_fcoe_internal_delete_route(unit, route, mem, lookup);
   2111 }
   2112 
   2113 STATIC int
   2114 _bcm_td2_find_and_delete_defip(int unit, bcm_fcoe_route_t *route)
   2115 {
   2116     _bcm_defip_cfg_t lpm_cfg;
   2117     int nh_idx;
   2118 
   2119     sal_memset(&lpm_cfg, 0, sizeof lpm_cfg);
   2120     
   2121     BCM_IF_ERROR_RETURN(_bcm_fcoe_route_to_defip(unit, route, &lpm_cfg));
   2122     BCM_IF_ERROR_RETURN(_bcm_fb_lpm_get(unit, &lpm_cfg, &nh_idx));
   2123     BCM_IF_ERROR_RETURN(_bcm_fb_lpm_del(unit, &lpm_cfg));
   2124     if (route->flags & BCM_FCOE_MULTIPATH) {
   2125         BCM_IF_ERROR_RETURN(
   2126             bcm_xgs3_ecmp_group_del(unit, nh_idx, 0));
   2127     } else {
   2128         BCM_IF_ERROR_RETURN(bcm_xgs3_nh_del(unit, 0, nh_idx));
   2129     }
   2130 
   2131     return BCM_E_NONE;
   2132 }
   2133 
   2134 #endif
   2135 
   2136 /*
   2137  * Description:
   2138  *     Delete a route from the L3 table
   2139  * Parameters:
   2140  *     unit      - (IN) unit number
   2141  *     route     - (IN) route to be added
   2142  * Returns:
   2143  *     BCM_E_XXX
   2144  */
   2145 int
   2146 bcm_td2_fcoe_route_delete(int unit, bcm_fcoe_route_t *route)
   2147 {
   2148     int rv = BCM_E_UNAVAIL;
   2149 
   2150 #ifdef INCLUDE_L3
   2151     if (route == NULL) {
   2152         return BCM_E_NONE;
   2153     }
   2154 
   2155     if (_bcm_td2_fcoe_route_is_prefix(unit, route)) {
   2156         return _bcm_td2_find_and_delete_defip(unit, route);
   2157     } else {
   2158         rv = _bcm_td2_fcoe_route_delete_ext(unit, route);
   2159         if (rv == BCM_E_NOT_FOUND) {
   2160             rv = _bcm_td2_fcoe_route_delete_normal(unit, route);
   2161         }
   2162     }
   2163 #endif
   2164 
   2165     return rv;
   2166 }
   2167 
   2168 #ifdef INCLUDE_L3
   2169 
   2170 /*
   2171  * Description:
   2172  *     Given a buffer holding a table row, retrieve the VRF
   2173  * Parameters:
   2174  *     unit      - (IN) unit number
   2175  *     mem       - (IN) table type
   2176  *     buf       - (IN) buffer holding table data
   2177  *     vrf       - (OUT) VRF from table
   2178  * Returns:
   2179  *     BCM_E_XXX
   2180  */
   2181 STATIC int
   2182 _bcm_td2_mem_get_vrf(int unit, soc_mem_t mem, uint32 *buf, int *vrf)
   2183 {
   2184     if (mem == _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit)) {
   2185         *vrf = soc_mem_field32_get(unit, mem, buf, FCOE_EXT__VRF_IDf);
   2186     } else if (mem == _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit)) {
   2187         *vrf = soc_mem_field32_get(unit, mem, buf, FCOE__VRF_IDf);
   2188     } else if (mem == L3_DEFIPm) {
   2189         int entry_type = soc_mem_field32_get(unit, mem, buf, ENTRY_TYPE0f);
   2190         if (entry_type == 1) {
   2191             *vrf = soc_mem_field32_get(unit, mem, buf, VRF_ID_0f);
   2192         } else {
   2193             *vrf = soc_mem_field32_get(unit, mem, buf, VRF_ID_1f);
   2194         }
   2195     } else {
   2196         return BCM_E_FAIL;
   2197     }
   2198 
   2199     return BCM_E_NONE;
   2200 }
   2201 
   2202 /*
   2203  * Description:
   2204  *     Given a buffer holding a table row, retrieve the L3 interface number
   2205  * Parameters:
   2206  *     unit      - (IN) unit number
   2207  *     mem       - (IN) table type
   2208  *     buf       - (IN) buffer holding table data
   2209  *     intf      - (OUT) L3_INTF_NUM from table
   2210  * Returns:
   2211  *     BCM_E_XXX
   2212  */
   2213 STATIC int
   2214 _bcm_td2_mem_get_intf(int unit, soc_mem_t mem, uint32 *buf, int *intf)
   2215 {
   2216     if (mem == _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit)) {
   2217         *intf = soc_mem_field32_get(unit, mem, buf, FCOE_EXT__L3_INTF_NUMf);
   2218         return BCM_E_NONE;
   2219     } else {
   2220         return BCM_E_FAIL;
   2221     }
   2222 }
   2223 
   2224 /*
   2225  * Description:
   2226  *     Given a buffer holding a table row, retrieve the key type
   2227  * Parameters:
   2228  *     unit      - (IN) unit number
   2229  *     mem       - (IN) table type
   2230  *     buf       - (IN) buffer holding table data
   2231  *     key_type  - (OUT) KEY_TYPE from table
   2232  * Returns:
   2233  *     BCM_E_XXX
   2234  */
   2235 STATIC int
   2236 _bcm_td2_mem_get_key_type(int unit, soc_mem_t mem, uint32 *buf, int *key_type)
   2237 {
   2238     if (mem == _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit)) {
   2239 #ifdef BCM_TRIDENT3_SUPPORT
   2240         if (SOC_IS_TRIDENT3X(unit)) {
   2241             *key_type = soc_mem_field32_get(unit, mem, buf, KEY_TYPEf);
   2242         } else
   2243 #endif
   2244         {
   2245             *key_type = soc_mem_field32_get(unit, mem, buf, KEY_TYPE_0f);
   2246         }
   2247     } else if (mem == _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit)) {
   2248         *key_type = soc_mem_field32_get(unit, mem, buf, KEY_TYPEf);
   2249     } else if (mem == L3_DEFIPm) {
   2250         *key_type = TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN;
   2251     } else {
   2252         return BCM_E_FAIL;
   2253     }
   2254 
   2255     return BCM_E_NONE;
   2256 }
   2257 
   2258 /*
   2259  * Description:
   2260  *     Given a buffer holding a table row, retrieve the nport_id
   2261  * Parameters:
   2262  *     unit      - (IN) unit number
   2263  *     mem       - (IN) table type
   2264  *     buf       - (IN) buffer holding table data
   2265  *     id        - (OUT) D_ID or S_ID from table
   2266  * Returns:
   2267  *     BCM_E_XXX
   2268  */
   2269 STATIC int
   2270 _bcm_td2_mem_get_id(int unit, soc_mem_t mem, uint32 *buf, uint32 *id)
   2271 {
   2272     int key_type;
   2273     int id_key;
   2274 
   2275     BCM_IF_ERROR_RETURN(_bcm_td2_mem_get_key_type(unit, mem, buf, &key_type));
   2276 
   2277     if (mem == L3_DEFIPm) {
   2278         int entry_type = soc_mem_field32_get(unit, mem, buf, ENTRY_TYPE0f);
   2279         if (entry_type == 1) {
   2280             id_key = D_ID0f;
   2281         } else {
   2282             id_key = D_ID1f;
   2283         }
   2284     } else {
   2285         switch (key_type) {
   2286 
   2287             case TD2_L3_HASH_KEY_TYPE_FCOE_HOST:
   2288             case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT:
   2289                 id_key = (mem == _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit))
   2290                          ? FCOE_EXT__D_IDf : FCOE__D_IDf;
   2291                 break;
   2292             case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN:
   2293             case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT:
   2294                 id_key = (mem == _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit))
   2295                          ? FCOE_EXT__MASKED_D_IDf : FCOE__MASKED_D_IDf;
   2296                 break;
   2297             case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP:
   2298             case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT:
   2299                 id_key = (mem == _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit))
   2300                          ? FCOE_EXT__S_IDf : FCOE__S_IDf;
   2301                 break;
   2302             default:
   2303                 return BCM_E_PARAM;
   2304         }
   2305     }
   2306 
   2307     *id = soc_mem_field32_get(unit, mem, buf, id_key);
   2308 
   2309     return BCM_E_NONE;
   2310 }
   2311 /*
   2312  * Description:
   2313  *     Determine if the given key type is an FCOE key for the given table.
   2314  * Parameters:
   2315  *     mem           - (IN) table type
   2316  *     key_type      - (IN) key type field from the table row
   2317  * Returns:
   2318  *     0 indicates "not an FCOE key"
   2319  *     1 indicates "is an FCOE key"
   2320  */
   2321 #ifdef BCM_TRIDENT3_SUPPORT
   2322 STATIC int
   2323 _bcm_td3_key_type_is_fcoe(int unit, soc_mem_t mem, int key_type_0, int key_type_1)
   2324 {
   2325     if (mem == _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit)) {
   2326         if ((key_type_0 == (int)TD3_L3_HASH_KEY_TYPE_FCOE_HOST) &&
   2327             (key_type_1 == (int)TD3_L3_HASH_DATA_TYPE_FCOE_HOST_EXT))
   2328             return (1);
   2329 
   2330         if ((key_type_0 == (int)TD3_L3_HASH_KEY_TYPE_FCOE_DOMAIN) &&
   2331             (key_type_1 == (int)TD3_L3_HASH_DATA_TYPE_FCOE_DOMAIN_EXT))
   2332             return (1);
   2333 
   2334         if ((key_type_0 == (int)TD3_L3_HASH_KEY_TYPE_FCOE_SOURCE_MAP) &&
   2335             (key_type_1 == (int)TD3_L3_HASH_DATA_TYPE_FCOE_SOURCE_MAP_EXT))
   2336             return (1);
   2337     } else if (mem == _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit)) {
   2338         if ((key_type_0 == (int)TD3_L3_HASH_KEY_TYPE_FCOE_HOST) &&
   2339             (key_type_1 == (int)TD3_L3_HASH_KEY_TYPE_FCOE_HOST_EXT))
   2340             return (1);
   2341 
   2342         if ((key_type_0 == (int)TD3_L3_HASH_KEY_TYPE_FCOE_DOMAIN) &&
   2343             (key_type_1 == (int)TD3_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT))
   2344             return (1);
   2345 
   2346         if ((key_type_0 == (int)TD3_L3_HASH_KEY_TYPE_FCOE_SOURCE_MAP) &&
   2347             (key_type_1 == (int)TD3_L3_HASH_KEY_TYPE_FCOE_SOURCE_MAP_EXT))
   2348             return (1);
   2349     } 
   2350 
   2351     return 0;
   2352 }
   2353 #endif
   2354 
   2355 /*
   2356  * Description:
   2357  *     Determine if the given key type is an FCOE key for the given table.
   2358  * Parameters:
   2359  *     mem           - (IN) table type
   2360  *     key_type      - (IN) key type field from the table row
   2361  * Returns:
   2362  *     0 indicates "not an FCOE key"
   2363  *     1 indicates "is an FCOE key"
   2364  */
   2365 STATIC int
   2366 _bcm_td2_key_type_is_fcoe(int unit, soc_mem_t mem, int key_type)
   2367 {
   2368     if (mem == _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit)) {
   2369         return (key_type == TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT)
   2370                || (key_type == TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT)
   2371                || (key_type == TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT);
   2372     } else if (mem == _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit)) {
   2373         return (key_type == TD2_L3_HASH_KEY_TYPE_FCOE_HOST)
   2374                || (key_type == TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN)
   2375                || (key_type == TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP);
   2376     } else {
   2377         return 0;
   2378     }
   2379 }
   2380 
   2381 /*
   2382  * Description:
   2383  *     Traverse the contents of a given memory (either L3 unicast or L3 mcast).
   2384  *     For each row, call the given function and supply the given route
   2385  *     as a parameter.
   2386  * Parameters:
   2387  *     unit          - (IN) unit number
   2388  *     mem           - (IN) table type
   2389  *     traverse_func - (IN) callback function
   2390  *     route         - (IN) route to be passed to callback
   2391  * Returns:
   2392  *     BCM_E_XXX
   2393  */
   2394 STATIC int
   2395 _bcm_td2_fcoe_traverse_table(int unit, soc_mem_t mem,
   2396                              fcoe_traverse_cb_f traverse_func,
   2397                              bcm_fcoe_route_t *route)
   2398 {
   2399     l3_entry_ipv4_multicast_entry_t l3_ext_entry;
   2400 
   2401     uint32      *buf = (uint32 *)&l3_ext_entry;
   2402     int         idx;
   2403     int         idx_max;
   2404     int         key_type_0;
   2405     int         key_type_1;
   2406     int         rv = BCM_E_NONE;
   2407 
   2408     idx_max = soc_mem_index_max(unit, mem);
   2409 
   2410     soc_mem_lock(unit, mem);
   2411 
   2412     for (idx = 0; idx < idx_max; idx++) {
   2413         sal_memset(buf, 0, sizeof l3_ext_entry);
   2414 
   2415         rv = BCM_XGS3_MEM_READ(unit, mem, idx, buf);
   2416         if (BCM_FAILURE(rv)) {
   2417             break;
   2418         }
   2419 
   2420         if (mem == _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit)) {
   2421 #ifdef BCM_TRIDENT3_SUPPORT
   2422             if (SOC_IS_TRIDENT3X(unit)) {
   2423                 if (!soc_mem_field32_get(unit, mem, buf, BASE_VALIDf)) {
   2424                     continue;
   2425                 }
   2426                 key_type_0 = soc_mem_field32_get(unit, mem, buf,
   2427                                                  KEY_TYPEf);
   2428                 key_type_1 = soc_mem_field32_get(unit, mem, buf,
   2429                                                      DATA_TYPEf);
   2430             } else 
   2431 #endif         
   2432             {
   2433                 if (!soc_mem_field32_get(unit, mem, buf, VALIDf)) {
   2434                     continue;
   2435                 }
   2436                 key_type_0 = soc_mem_field32_get(unit, mem, buf,
   2437                                                  KEY_TYPEf);
   2438                 key_type_1 = key_type_0; 
   2439             }
   2440         } else {
   2441 #ifdef BCM_TRIDENT3_SUPPORT
   2442             if (SOC_IS_TRIDENT3X(unit)) {
   2443                 if (!soc_mem_field32_get(unit, mem, buf, BASE_VALID_0f)
   2444                     || !soc_mem_field32_get(unit, mem, buf, BASE_VALID_1f)) {
   2445                     continue;
   2446                 }
   2447                 key_type_0 = soc_mem_field32_get(unit, mem, buf,
   2448                                                  KEY_TYPEf);
   2449                 key_type_1 = soc_mem_field32_get(unit, mem, buf,
   2450                                                  DATA_TYPEf);
   2451             } else
   2452 #endif
   2453             {
   2454                 if (!soc_mem_field32_get(unit, mem, buf, VALID_0f)
   2455                    || !soc_mem_field32_get(unit, mem, buf, VALID_1f)) {
   2456                     continue;
   2457                 }
   2458                 key_type_0 = soc_mem_field32_get(unit, mem, buf,
   2459                                                  KEY_TYPE_0f);
   2460                 key_type_1 = soc_mem_field32_get(unit, mem, buf,
   2461                                                  KEY_TYPE_1f);
   2462             }
   2463         }
   2464 #ifdef BCM_TRIDENT3_SUPPORT
   2465         if (SOC_IS_TRIDENT3X(unit)) {
   2466             if (!_bcm_td3_key_type_is_fcoe(unit, mem, key_type_0, key_type_1)) {
   2467                 continue;
   2468             }
   2469         } else
   2470 #endif
   2471         {
   2472             if (!_bcm_td2_key_type_is_fcoe(unit, mem, key_type_0)
   2473                 || (key_type_0 != key_type_1)) {
   2474                 continue;
   2475             }
   2476         }
   2477 
   2478         rv = traverse_func(unit, mem, buf, route);
   2479         if (rv != BCM_E_NONE) {
   2480             break;
   2481         }
   2482     }
   2483 
   2484     /* coverity[overrun-local] */
   2485     soc_mem_unlock(unit, mem);
   2486 
   2487     return rv;
   2488 }
   2489 
   2490 STATIC int
   2491 _bcm_td2_fcoe_traverse_defip(int unit, fcoe_traverse_cb_f traverse_func,
   2492                              bcm_fcoe_route_t *route)
   2493 {
   2494     soc_mem_t   mem = L3_DEFIPm;
   2495     int         idx;
   2496     int         rv = BCM_E_NONE;
   2497     char        *defip_tbl_ptr = NULL;
   2498     int         defip_table_size = 0;
   2499     defip_entry_t *lpm_entry;
   2500 
   2501     soc_mem_lock(unit, mem);
   2502 
   2503     rv = bcm_xgs3_l3_tbl_dma(unit, mem, BCM_XGS3_L3_ENT_SZ(unit, defip),
   2504                              "lpm_tbl", &defip_tbl_ptr, &defip_table_size);
   2505     if (BCM_FAILURE(rv)) {
   2506         soc_mem_unlock(unit, mem);
   2507         return rv;
   2508     }
   2509 
   2510     for (idx = 0; idx < defip_table_size; idx++) {
   2511         lpm_entry = soc_mem_table_idx_to_pointer(unit, mem,
   2512                                                  defip_entry_t *,
   2513                                                  defip_tbl_ptr, idx);
   2514 
   2515         if ((soc_mem_field32_get(unit, mem, (uint32 *)lpm_entry, VALID0f) &&
   2516             soc_mem_field32_get(unit, mem, (uint32 *)lpm_entry, ENTRY_TYPE0f))
   2517             || (soc_mem_field32_get(unit, mem, (uint32 *)lpm_entry, VALID1f) &&
   2518             soc_mem_field32_get(unit, mem, (uint32 *)lpm_entry, ENTRY_TYPE1f))
   2519             ) {
   2520             rv = traverse_func(unit, mem, (uint32 *)lpm_entry, route);
   2521             if (rv != BCM_E_NONE) {
   2522                 break;
   2523             }
   2524         }
   2525     }
   2526     soc_cm_sfree(unit, defip_tbl_ptr);
   2527     soc_mem_unlock(unit, mem);
   2528 
   2529     return rv;
   2530 }
   2531 
   2532 /*
   2533  * Description:
   2534  *     Traverse the contents of the L3 unicast and L3 mcast memories.
   2535  *     For each row, call the given function and supply the given route
   2536  *     as a parameter.
   2537  * Parameters:
   2538  *     unit          - (IN) unit number
   2539  *     traverse_func - (IN) callback function
   2540  *     route         - (IN) route to be passed to callback
   2541  * Returns:
   2542  *     BCM_E_XXX
   2543  */
   2544 STATIC int
   2545 _bcm_td2_fcoe_traverse_tables(int unit, fcoe_traverse_cb_f traverse_func,
   2546                               bcm_fcoe_route_t *route)
   2547 {
   2548     int rv = _bcm_td2_fcoe_traverse_table(unit, _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit),
   2549                                           traverse_func, route);
   2550     if (BCM_SUCCESS(rv)) {
   2551         rv = _bcm_td2_fcoe_traverse_table(unit, _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit),
   2552                                           traverse_func, route);
   2553     }
   2554 
   2555     if (BCM_SUCCESS(rv)) {
   2556         rv = _bcm_td2_fcoe_traverse_defip(unit, traverse_func, route);
   2557     }
   2558     return rv;
   2559 }
   2560 
   2561 /*
   2562  * Description:
   2563  *     Callback function used in bcm_td2_fcoe_route_delete_by_prefix for each
   2564  *     table row
   2565  * Parameters:
   2566  *     unit      - device number
   2567  *     mem       - memory being accessed
   2568  *     buf       - buffer holding table data
   2569  *     route     - route information to be checked
   2570  * Returns:
   2571  *     BCM_E_XXX
   2572  */
   2573 STATIC int
   2574 _bcm_td2_fcoe_route_delete_by_prefix_cb(int unit, soc_mem_t mem, uint32 *buf,
   2575                                         bcm_fcoe_route_t *route)
   2576 {
   2577     int searching_prefix = route->nport_id & route->nport_id_mask;
   2578     int vrf;
   2579     uint32 id;
   2580     int rv = BCM_E_NONE;
   2581 
   2582     BCM_IF_ERROR_RETURN(_bcm_td2_mem_get_id(unit, mem, buf, &id));
   2583     BCM_IF_ERROR_RETURN(_bcm_td2_mem_get_vrf(unit, mem, buf, &vrf));
   2584 
   2585     if (route->vrf != vrf) {
   2586         return BCM_E_NONE;
   2587     }
   2588 
   2589     if ((id & route->nport_id_mask) == searching_prefix) {
   2590         rv = _bcm_td2_fcoe_internal_delete_route(unit, route, mem, buf);
   2591 
   2592         if (rv != SOC_E_NONE) {
   2593             return BCM_E_FAIL;
   2594         }
   2595     }
   2596 
   2597     return BCM_E_NONE;
   2598 }
   2599 
   2600 #endif
   2601 
   2602 /*
   2603  * Description:
   2604  *     Delete FCOE entries based on Masked Domain prefix (network)
   2605  * Parameters:
   2606  *     unit      - device number
   2607  *     route     - route information to be deleted
   2608  * Returns:
   2609  *     BCM_E_XXX
   2610  */
   2611 int
   2612 bcm_td2_fcoe_route_delete_by_prefix(int unit, bcm_fcoe_route_t *route)
   2613 {
   2614 #ifdef INCLUDE_L3
   2615     return _bcm_td2_fcoe_traverse_tables(unit,
   2616                                     &_bcm_td2_fcoe_route_delete_by_prefix_cb,
   2617                                     route);
   2618 #else
   2619     return BCM_E_UNAVAIL;
   2620 #endif
   2621 }
   2622 
   2623 #ifdef INCLUDE_L3
   2624 
   2625 STATIC int
   2626 _bcm_fcoe_read_nexthop_into_route(int unit, int nexthop,
   2627                                   bcm_fcoe_route_t *route, int flag);
   2628 
   2629 /*
   2630  * Description:
   2631  *     Callback function used in bcm_td2_fcoe_route_delete_by_interface for each
   2632  *     table row
   2633  * Parameters:
   2634  *     unit      - device number
   2635  *     mem       - memory being accessed
   2636  *     buf       - buffer holding table data
   2637  *     route     - route information to be checked
   2638  * Returns:
   2639  *     BCM_E_XXX
   2640  */
   2641 STATIC int
   2642 _bcm_td2_fcoe_route_delete_by_intf_cb(int unit, soc_mem_t mem, uint32 *buf,
   2643                                       bcm_fcoe_route_t *route)
   2644 {
   2645     int vrf;
   2646     int intf;
   2647     int nexthop;
   2648     bcm_fcoe_route_t tbl_route;
   2649     int rv = BCM_E_NONE;
   2650 
   2651     if (mem == _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit)) {
   2652         BCM_IF_ERROR_RETURN(_bcm_td2_mem_get_vrf(unit, mem, buf, &vrf));
   2653         BCM_IF_ERROR_RETURN(_bcm_td2_mem_get_intf(unit, mem, buf, &intf));
   2654 
   2655         if (route->vrf == vrf && route->intf == intf) {
   2656             rv = _bcm_td2_fcoe_internal_delete_route(unit, route, mem, buf);
   2657 
   2658             if (rv != SOC_E_NONE) {
   2659                 return BCM_E_FAIL;
   2660             }
   2661         }
   2662     } else {
   2663         BCM_IF_ERROR_RETURN(_bcm_td2_mem_get_vrf(unit, mem, buf, &vrf));
   2664 #ifdef BCM_TRIDENT3_SUPPORT
   2665         if (SOC_IS_TRIDENT3X(unit)) {
   2666             uint32 dest_type;
   2667             nexthop = soc_mem_field32_dest_get(unit, mem, buf,
   2668                                          DESTINATIONf, &dest_type);
   2669         } else
   2670 #endif
   2671         {
   2672             nexthop = soc_mem_field32_get(unit, mem, buf, FCOE__NEXT_HOP_INDEXf);
   2673         }
   2674 
   2675 
   2676         sal_memset(&tbl_route, 0x0, sizeof(tbl_route));
   2677 
   2678         BCM_IF_ERROR_RETURN(
   2679             _bcm_fcoe_read_nexthop_into_route(unit, nexthop, &tbl_route,
   2680                                               FCOE_ROUTE_READ_RETURN_L3_INTF));
   2681 
   2682         if (route->vrf == vrf && route->intf == tbl_route.intf) {
   2683             rv = _bcm_td2_fcoe_internal_delete_route(unit, route, mem, buf);
   2684 
   2685             if (rv != SOC_E_NONE) {
   2686                 return BCM_E_FAIL;
   2687             }
   2688         }
   2689     }
   2690 
   2691     return rv;
   2692 }
   2693 
   2694 #endif
   2695 
   2696 /*
   2697  * Description:
   2698  *     Delete FCOE entries that do/don't match a specified L3 interface
   2699  * Parameters:
   2700  *     unit      - device number
   2701  *     route     - route information to be deleted
   2702  * Returns:
   2703  *     BCM_E_XXX
   2704  */
   2705 int
   2706 bcm_td2_fcoe_route_delete_by_interface(int unit, bcm_fcoe_route_t *route)
   2707 {
   2708 #ifdef INCLUDE_L3
   2709     return _bcm_td2_fcoe_traverse_tables(unit, 
   2710                                         &_bcm_td2_fcoe_route_delete_by_intf_cb,
   2711                                         route);
   2712 #else
   2713     return BCM_E_UNAVAIL;
   2714 #endif
   2715 }
   2716 
   2717 #ifdef INCLUDE_L3
   2718 /*
   2719  * Description:
   2720  *     Callback function used in bcm_td2_fcoe_route_delete_all for each
   2721  *     table row
   2722  * Parameters:
   2723  *     unit      - device number
   2724  *     mem       - memory being accessed
   2725  *     buf       - buffer holding table data
   2726  *     route     - route information to be checked
   2727  * Returns:
   2728  *     BCM_E_XXX
   2729  */
   2730 STATIC int
   2731 _bcm_td2_fcoe_route_delete_all_cb(int unit, soc_mem_t mem, uint32 *buf,
   2732                                   bcm_fcoe_route_t *route)
   2733 {
   2734     int rv = _bcm_td2_fcoe_internal_delete_route(unit, route, mem, buf);
   2735 
   2736     if (rv != SOC_E_NONE) {
   2737         return BCM_E_FAIL;
   2738     }
   2739 
   2740     return BCM_E_NONE;
   2741 }
   2742 #endif
   2743 
   2744 /*
   2745  * Description:
   2746  *     Deletes all FCOE routing table entries
   2747  * Parameters:
   2748  *     unit      - device number
   2749  * Returns:
   2750  *     BCM_E_XXX
   2751  */
   2752 int
   2753 bcm_td2_fcoe_route_delete_all(int unit)
   2754 {
   2755 #ifdef INCLUDE_L3
   2756     return _bcm_td2_fcoe_traverse_tables(unit,
   2757                                          &_bcm_td2_fcoe_route_delete_all_cb,
   2758                                          NULL);
   2759 #else
   2760     return BCM_E_UNAVAIL;
   2761 #endif
   2762 }
   2763 
   2764 #ifdef INCLUDE_L3
   2765 /*
   2766  * Description:
   2767  *     Read the nexthop table and convert relevant info into the fcoe route
   2768  *     structure
   2769  * Parameters:
   2770  *     unit      - device number
   2771  *     nexthop   - table index
   2772  *     route     - route information to be filled in
   2773  *     flag      - internal flag indicates return l3 intf or nexthop index
   2774  * Returns:
   2775  *     BCM_E_XXX
   2776  */
   2777 STATIC int
   2778 _bcm_fcoe_read_nexthop_into_route(int unit, int nexthop,
   2779                                   bcm_fcoe_route_t *route, int flag)
   2780 {
   2781     bcm_l3_egress_t nh_entry;
   2782     int rv;
   2783 
   2784     if (BCM_XGS3_L3_HWCALL_CHECK(unit, nh_get)) {
   2785         rv = BCM_XGS3_L3_HWCALL_EXEC(unit, nh_get) (unit, nexthop, &nh_entry);
   2786     } else {
   2787         rv = BCM_E_FAIL;
   2788     }
   2789 
   2790     BCM_IF_ERROR_RETURN(rv);
   2791 
   2792     if (nh_entry.flags & BCM_L3_L2TOCPU) {
   2793         route->flags |= BCM_FCOE_COPY_TO_CPU;
   2794     }
   2795 
   2796     if (nh_entry.flags & BCM_L3_DST_DISCARD) {
   2797         route->flags |= BCM_FCOE_DST_DISCARD;
   2798     }
   2799 
   2800     if (nh_entry.flags & BCM_L3_SRC_DISCARD) {
   2801         route->flags |= BCM_FCOE_SRC_DISCARD;
   2802     }
   2803 
   2804     if (nh_entry.flags & BCM_L3_KEEP_TTL) {
   2805         route->flags |= BCM_FCOE_NO_HOP_COUNT_CHANGE;
   2806     }
   2807 
   2808     BCM_IF_ERROR_RETURN(_bcm_fcoe_glp_to_port(nh_entry.port, &route->port));
   2809     if (flag == FCOE_ROUTE_READ_RETURN_NHID) {
   2810         if (BCM_XGS3_L3_EGRESS_MODE_ISSET(unit)) {
   2811             if (route->flags & BCM_FCOE_MULTIPATH) {
   2812                 route->intf = nexthop + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit);
   2813             } else {
   2814                 route->intf = nexthop + BCM_XGS3_EGRESS_IDX_MIN(unit);
   2815             }
   2816             return BCM_E_NONE;
   2817         }
   2818     }
   2819     if (flag != FCOE_ROUTE_READ_RETURN_L3_INTF) {
   2820         return BCM_E_INTERNAL; 
   2821     }
   2822     route->intf = nh_entry.intf;
   2823 
   2824     return BCM_E_NONE;
   2825 }
   2826 
   2827 /*
   2828  * Description:
   2829  *     Read a buffer from the L3 hardware table into a fcoe route structure
   2830  * Parameters:
   2831  *     unit      - device number
   2832  *     mem       - table to be used
   2833  *     buf       - buffer holding the table row
   2834  *     route     - route information to be created
   2835  * Returns:
   2836  *     BCM_E_XXX
   2837  */
   2838 STATIC int
   2839 _bcm_fcoe_read_mem_into_route(int unit, soc_mem_t mem, uint32 *buf,
   2840                                   bcm_fcoe_route_t *route)
   2841 {
   2842     int key_type;
   2843 #ifdef BCM_TRIDENT3_SUPPORT
   2844     uint32 dest_type = 0;
   2845 #endif
   2846 
   2847     BCM_IF_ERROR_RETURN(_bcm_td2_mem_get_key_type(unit, mem, buf, &key_type));
   2848     BCM_IF_ERROR_RETURN(_bcm_td2_mem_get_id(unit, mem, buf,
   2849                                             &route->nport_id));
   2850 
   2851     switch (key_type) {
   2852         case TD2_L3_HASH_KEY_TYPE_FCOE_HOST:
   2853         case TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT:
   2854             route->flags = BCM_FCOE_HOST_ROUTE;
   2855             break;
   2856 
   2857         case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP:
   2858         case TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT:
   2859             route->flags = BCM_FCOE_SOURCE_ROUTE;
   2860             break;
   2861 
   2862         case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN:
   2863         case TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT:
   2864             route->flags = BCM_FCOE_DOMAIN_ROUTE;
   2865             break;
   2866 
   2867         default:
   2868             return BCM_E_FAIL;
   2869     }
   2870 
   2871     if (mem == _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit)) {
   2872         int port;
   2873 
   2874         if (soc_mem_field32_get(unit, mem, buf, FCOE_EXT__DST_DISCARDf)) {
   2875             route->flags |= BCM_FCOE_DST_DISCARD;
   2876         }
   2877         if (soc_mem_field32_get(unit, mem, buf, FCOE_EXT__RPEf)) {
   2878             route->flags |= BCM_FCOE_RPE;
   2879         }
   2880 
   2881         route->pri = soc_mem_field32_get(unit, mem, buf, FCOE_EXT__PRIf);
   2882         route->lookup_class = soc_mem_field32_get(unit, mem, buf,
   2883                                                   FCOE_EXT__CLASS_IDf);
   2884 
   2885         if ((route->flags & BCM_FCOE_HOST_ROUTE)
   2886             && soc_mem_field32_get(unit, mem, buf, FCOE_EXT__LOCAL_ADDRESSf)) {
   2887             route->flags |= BCM_FCOE_LOCAL_ADDRESS;
   2888         }
   2889 
   2890         BCM_IF_ERROR_RETURN(_bcm_td2_mem_get_intf(unit, mem, buf,
   2891                                                   &route->intf));
   2892 
   2893         soc_mem_mac_addr_get(unit, mem, buf, FCOE_EXT__MAC_ADDRf,
   2894                              route->nexthop_mac);
   2895 
   2896         if (soc_mem_field32_get(unit, mem, buf, FCOE_EXT__COPY_TO_CPUf)) {
   2897             route->flags |= BCM_FCOE_COPY_TO_CPU;
   2898         }
   2899 
   2900 
   2901 #ifdef BCM_TRIDENT3_SUPPORT
   2902         if (SOC_IS_TRIDENT3X(unit)) {
   2903             uint32 dest;
   2904             if (soc_mem_field32_get(unit, mem, buf, FCOE_EXT__DO_NOT_DECREMENT_TTLf)) {
   2905                 route->flags |= BCM_FCOE_NO_HOP_COUNT_CHANGE;
   2906             }
   2907             dest = soc_mem_field32_dest_get(unit, mem, buf, FCOE_EXT__DESTINATIONf,
   2908                                      &dest_type);
   2909             if (dest_type == SOC_MEM_FIF_DEST_DGPP) {
   2910                 port = BCM_GPORT_MODPORT_PORT_GET(dest);
   2911             } else {
   2912                 return BCM_E_INTERNAL;
   2913             }
   2914         } else
   2915 #endif /* BCM_TRIDENT3_SUPPORT */
   2916         {
   2917             if (soc_mem_field32_get(unit, mem, buf, FCOE_EXT__DO_NOT_CHANGE_TTLf)) {
   2918                 route->flags |= BCM_FCOE_NO_HOP_COUNT_CHANGE;
   2919             }
   2920 
   2921             port = soc_mem_field32_get(unit, mem, buf, FCOE_EXT__GLPf);
   2922             BCM_IF_ERROR_RETURN(_bcm_fcoe_glp_to_port(port, &route->port));
   2923         }
   2924     } else {
   2925         int nexthop;
   2926 
   2927 #ifdef BCM_TRIDENT3_SUPPORT
   2928         if (SOC_IS_TRIDENT3X(unit)) {
   2929             nexthop = soc_mem_field32_dest_get(unit, mem, buf, DESTINATIONf, &dest_type);
   2930         } else
   2931 #endif
   2932         {
   2933             nexthop = soc_mem_field32_get(unit, mem, buf, FCOE__NEXT_HOP_INDEXf);
   2934         }
   2935 
   2936         route->pri = soc_mem_field32_get(unit, mem, buf, FCOE__PRIf);
   2937         route->lookup_class = soc_mem_field32_get(unit, mem, buf,
   2938                                                   FCOE__CLASS_IDf);
   2939 
   2940         if ((route->flags & BCM_FCOE_HOST_ROUTE)
   2941             && soc_mem_field32_get(unit, mem, buf, FCOE__LOCAL_ADDRESSf)) {
   2942             route->flags |= BCM_FCOE_LOCAL_ADDRESS;
   2943         }
   2944 
   2945         if (soc_mem_field32_get(unit, mem, buf, FCOE__DST_DISCARDf)) {
   2946             route->flags |= BCM_FCOE_DST_DISCARD;
   2947         }
   2948         if (soc_mem_field32_get(unit, mem, buf, FCOE__RPEf)) {
   2949             route->flags |= BCM_FCOE_RPE;
   2950         }
   2951 #ifdef BCM_TRIDENT3_SUPPORT
   2952         if (SOC_IS_TRIDENT3X(unit)) {
   2953             if (dest_type == SOC_MEM_FIF_DEST_ECMP){
   2954                 route->flags |= BCM_FCOE_MULTIPATH;
   2955             }
   2956         } else
   2957 #endif
   2958         {
   2959             if (soc_mem_field32_get(unit, mem, buf, FCOE__ECMPf)) {  
   2960                 route->flags |= BCM_FCOE_MULTIPATH;
   2961             }
   2962         }
   2963 
   2964         BCM_IF_ERROR_RETURN(
   2965             _bcm_fcoe_read_nexthop_into_route(unit, nexthop, route,
   2966                                               FCOE_ROUTE_READ_RETURN_NHID));
   2967     }
   2968 
   2969     return BCM_E_NONE;
   2970 }
   2971 
   2972 /*
   2973  * Description:
   2974  *     Look up an FCOE routing table entry based on nport id
   2975  * Parameters:
   2976  *     unit      - device number
   2977  *     route     - route information to be deleted
   2978  * Returns:
   2979  *     BCM_E_XXX
   2980  */
   2981 STATIC int
   2982 _bcm_td2_fcoe_route_find_ext(int unit, bcm_fcoe_route_t *route)
   2983 {
   2984     l3_entry_ipv4_multicast_entry_t l3_ext_entry[2];
   2985 
   2986     soc_mem_t  mem = _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit);
   2987     uint32     *buf = (uint32 *)&l3_ext_entry[0];
   2988     uint32     *lookup = (uint32 *)&l3_ext_entry[1];
   2989     int        existing_index = 0;
   2990     int        rv;
   2991 
   2992     memset(&l3_ext_entry, 0, sizeof l3_ext_entry);
   2993 
   2994     BCM_IF_ERROR_RETURN(_bcm_fcoe_route_construct_key_ext(unit, mem, buf,
   2995                                                           route));
   2996 
   2997     /* Search for this key in the existing database */
   2998     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &existing_index, buf,
   2999                         (void *)lookup, 0);
   3000     if (rv == SOC_E_NOT_FOUND) {
   3001         return BCM_E_NOT_FOUND;
   3002     }
   3003 
   3004     _bcm_fcoe_read_mem_into_route(unit, mem, lookup, route);
   3005 
   3006     return BCM_E_NONE;
   3007 }
   3008 
   3009 /*
   3010  * Description:
   3011  *     Look up an FCOE routing table entry based on nport id
   3012  * Parameters:
   3013  *     unit      - device number
   3014  *     route     - route information to be deleted
   3015  * Returns:
   3016  *     BCM_E_XXX
   3017  */
   3018 STATIC int
   3019 _bcm_td2_fcoe_route_find_normal(int unit, bcm_fcoe_route_t *route)
   3020 {
   3021     l3_entry_ipv4_unicast_entry_t   l3_entry[2];
   3022 
   3023     soc_mem_t  mem = _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit);
   3024     uint32     *buf = (uint32 *)&l3_entry[0];
   3025     uint32     *lookup = (uint32 *)&l3_entry[1];
   3026     int        existing_index = 0;
   3027     int        rv;
   3028 
   3029     memset(&l3_entry, 0, sizeof l3_entry);
   3030 
   3031     BCM_IF_ERROR_RETURN(_bcm_fcoe_route_construct_key_normal(unit, mem, buf,
   3032                                                              route));
   3033 
   3034     /* Search for this key in the existing database */
   3035     rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &existing_index, buf,
   3036                         (void *)lookup, 0);
   3037     if (rv == SOC_E_NOT_FOUND) {
   3038         return BCM_E_NOT_FOUND;
   3039     }
   3040 
   3041     _bcm_fcoe_read_mem_into_route(unit, mem, lookup, route);
   3042 
   3043     return BCM_E_NONE;
   3044 }
   3045 
   3046 /*
   3047  * Description:
   3048  *     Look up an FCOE route in the L3_DEFIP table
   3049  * Parameters:
   3050  *     unit      - device number
   3051  *     route     - route information to be deleted
   3052  * Returns:
   3053  *     BCM_E_XXX
   3054  */
   3055 STATIC int
   3056 _bcm_td2_fcoe_route_find_defip(int unit, bcm_fcoe_route_t *route)
   3057 {
   3058     _bcm_defip_cfg_t lpm_cfg;
   3059     int nh_idx = 0;
   3060 
   3061     sal_memset(&lpm_cfg, 0, sizeof lpm_cfg);
   3062 
   3063     BCM_IF_ERROR_RETURN(_bcm_fcoe_route_to_defip(unit, route, &lpm_cfg));
   3064     BCM_IF_ERROR_RETURN(_bcm_fb_lpm_get(unit, &lpm_cfg, &nh_idx));
   3065     BCM_IF_ERROR_RETURN(_bcm_fcoe_defip_to_route(unit, &lpm_cfg, route));
   3066     if (BCM_XGS3_L3_EGRESS_MODE_ISSET(unit)) {
   3067         if (route->flags & BCM_FCOE_MULTIPATH) {
   3068             route->intf = nh_idx + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit);
   3069         } else {
   3070             route->intf = nh_idx + BCM_XGS3_EGRESS_IDX_MIN(unit);
   3071         }
   3072     }
   3073     return BCM_E_NONE;
   3074 }
   3075 #endif
   3076 
   3077 /*
   3078  * Description:
   3079  *     Look up an FCOE routing table entry based on nport id
   3080  * Parameters:
   3081  *     unit      - device number
   3082  *     route     - route information to be deleted
   3083  * Returns:
   3084  *     BCM_E_XXX
   3085  */
   3086 int
   3087 bcm_td2_fcoe_route_find(int unit, bcm_fcoe_route_t *route)
   3088 {
   3089 #ifdef INCLUDE_L3
   3090     int rv = _bcm_td2_fcoe_route_find_normal(unit, route);
   3091 
   3092     if (rv != BCM_E_NONE) {
   3093         rv = _bcm_td2_fcoe_route_find_ext(unit, route);
   3094     }
   3095 
   3096     if (rv != BCM_E_NONE) {
   3097         rv = _bcm_td2_fcoe_route_find_defip(unit, route);
   3098     }
   3099 #else
   3100     int rv = BCM_E_UNAVAIL;
   3101 #endif
   3102     
   3103     return rv;
   3104 }
   3105 
   3106 /* validate vsan entry input */
   3107 STATIC int
   3108 _bcm_fcoe_vsan_param_validate (bcm_fcoe_vsan_t *vsan, bcm_fcoe_vsan_id_t vsan_id)
   3109 {
   3110     if ((vsan_id > FCOE_MAX_VSAN_ID) ||
   3111         (vsan->fcmap > 0xffffff)) {     /* fcmap is 24 bits */
   3112         return BCM_E_PARAM;
   3113     }
   3114     return BCM_E_NONE;
   3115 }
   3116 
   3117 /* return fcmap value for given index */
   3118 STATIC int
   3119 _bcm_fcoe_fc_profile_map_value_get (int unit, int index,
   3120                                     bcm_fcoe_fcmap_t *fcmap)
   3121 {
   3122     int       rv;
   3123     uint32    entry[SOC_MAX_MEM_FIELD_WORDS];
   3124     void      *entries[1];
   3125 
   3126     entries[0] = entry;
   3127     rv = _bcm_fc_map_profile_entry_get(unit, index, 1, entries);
   3128 
   3129     if (rv == BCM_E_NONE) {
   3130         *fcmap = entry[0];
   3131     }
   3132 
   3133     return rv;
   3134 }
   3135 
   3136 /* Allocate and configure a VSAN */
   3137 int 
   3138 bcm_td2_fcoe_vsan_create (int unit, uint32 options, bcm_fcoe_vsan_t *vsan,
   3139                           bcm_fcoe_vsan_id_t *vsan_id)
   3140 {
   3141     ing_vsan_entry_t  vsan_entry;
   3142     soc_mem_t         mem = ING_VSANm;
   3143     int               rv = BCM_E_NONE;
   3144     int               index = *vsan_id;
   3145     uint32            fcmap_index = 0;
   3146     void              *entries[1];
   3147     uint32            fcmap_to_set;
   3148 
   3149     rv = _bcm_fcoe_vsan_param_validate(vsan, *vsan_id);
   3150     if (rv != BCM_E_NONE) {
   3151         return rv;
   3152     }
   3153 
   3154     /* check if vsan id is already created */
   3155     if (shr_idxres_list_elem_state(vsan_id_list[unit], *vsan_id) !=
   3156             BCM_E_NOT_FOUND) {
   3157         /* exception : if intention is to replace existing ID, overwrite
   3158          * existing entry */
   3159         if ((options & BCM_FCOE_VSAN_OPTION_REPLACE) == 0) {
   3160             return BCM_E_EXISTS;
   3161         }
   3162     }
   3163 
   3164     fcmap_to_set = vsan->fcmap;
   3165     entries[0] = &fcmap_to_set;
   3166 
   3167     rv = _bcm_fc_map_profile_entry_add(unit, entries, 1, &fcmap_index);
   3168 
   3169     if (rv != SOC_E_NONE) {
   3170         return rv;
   3171     }
   3172 
   3173     /* read table entry */
   3174     soc_mem_lock(unit, mem);
   3175     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &vsan_entry);
   3176     if (rv != BCM_E_NONE) {
   3177         soc_mem_unlock(unit, mem);
   3178         return rv;
   3179     }
   3180 
   3181     if (vsan->config_flags & BCM_FCOE_VSAN_CONFIG_NORMALIZED_ZONE_CHECK) {
   3182         soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry,
   3183                             ZONE_CHECK_NORMALIZEDf, 1);
   3184     } else {
   3185         soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry,
   3186                             ZONE_CHECK_NORMALIZEDf, 0);
   3187     }
   3188     if (vsan->config_flags & BCM_FCOE_VSAN_CONFIG_FCOE_ROUTE_ENABLE) {
   3189         soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry,
   3190                             FCOE_ROUTE_ENABLEf, 1);
   3191     } else {
   3192         soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry,
   3193                             FCOE_ROUTE_ENABLEf, 0);
   3194     }
   3195 
   3196     soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry,
   3197                         L3_IIFf, vsan->l3_intf_id);
   3198     soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry,
   3199                         FCOE_FC_MAP_INDEXf, fcmap_index);
   3200 
   3201     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &vsan_entry);
   3202 
   3203     soc_mem_unlock(unit, mem);
   3204 
   3205     if (rv == BCM_E_NONE) {
   3206         /* mark this vsan id as "created" */
   3207         if (shr_idxres_list_elem_state(vsan_id_list[unit], *vsan_id) ==
   3208             BCM_E_NOT_FOUND) {
   3209             return _bcm_fcoe_reserve_vsan_id(unit, *vsan_id);
   3210         }
   3211     }
   3212     return rv;
   3213 }
   3214 
   3215 /* Destroy a VSAN */
   3216 int 
   3217 bcm_td2_fcoe_vsan_destroy (int unit,  bcm_fcoe_vsan_id_t vsan_id)
   3218 {
   3219     ing_vsan_entry_t  vsan_entry;
   3220     soc_mem_t         mem = ING_VSANm;
   3221     int               rv = BCM_E_NONE;
   3222     int               index = vsan_id;
   3223     int               fcmap_index;
   3224 
   3225     /* check if vsan id is existing */
   3226     if (shr_idxres_list_elem_state(vsan_id_list[unit], vsan_id) !=
   3227             BCM_E_EXISTS) {
   3228         return BCM_E_NOT_FOUND;
   3229     }
   3230 
   3231     /* read table entry */
   3232     soc_mem_lock(unit, mem);
   3233     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &vsan_entry);
   3234     if (rv != BCM_E_NONE) {
   3235         soc_mem_unlock(unit, mem);
   3236         return rv;
   3237     }
   3238 
   3239     /* delete fc map entry */
   3240     fcmap_index = soc_mem_field32_get(unit,mem, &vsan_entry, FCOE_FC_MAP_INDEXf);
   3241     rv = _bcm_fc_map_profile_entry_delete(unit, fcmap_index);
   3242     if (rv != BCM_E_NONE) {
   3243         soc_mem_unlock(unit, mem);
   3244         return rv;
   3245     }
   3246 
   3247     /* NOTE : zero out all fields (including flex counter fields)
   3248      */ 
   3249     soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 
   3250                         FLEX_CTR_OFFSET_MODEf, 0);
   3251     soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 
   3252                         FLEX_CTR_POOL_NUMBERf, 0);
   3253     soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 
   3254                         FLEX_CTR_BASE_COUNTER_IDXf, 0);
   3255     soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 
   3256                         FCOE_ROUTE_ENABLEf, 0);
   3257     soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 
   3258                         ZONE_CHECK_NORMALIZEDf, 0);
   3259     soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, L3_IIFf, 0);
   3260     soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 
   3261                         FCOE_FC_MAP_INDEXf, 0);
   3262 
   3263     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &vsan_entry);
   3264 
   3265     soc_mem_unlock(unit, mem);
   3266 
   3267     if (rv == BCM_E_NONE) {
   3268         /* unreserve this vsan id */
   3269         return _bcm_fcoe_unreserve_vsan_id(unit, vsan_id);
   3270     }
   3271     return rv;
   3272 }
   3273 
   3274 /* Destroy all VSANs */
   3275 int 
   3276 bcm_td2_fcoe_vsan_destroy_all (int unit)
   3277 {
   3278     ing_vsan_entry_t  vsan_entry;
   3279     soc_mem_t         mem = ING_VSANm;
   3280     int               rv = BCM_E_NONE;
   3281     int               index;
   3282     int               fcmap_index;
   3283 
   3284     soc_mem_lock(unit, mem);
   3285     for (index = 0; index <= FCOE_MAX_VSAN_ID; index++) {
   3286 
   3287         /* check if vsan id is existing */
   3288         if (shr_idxres_list_elem_state(vsan_id_list[unit], index) !=
   3289                 BCM_E_EXISTS) {
   3290             continue;
   3291         }
   3292 
   3293         /* read table entry */
   3294         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &vsan_entry);
   3295         if (rv != BCM_E_NONE) {
   3296             break;
   3297         }
   3298 
   3299         /* delete fc map entry */
   3300         fcmap_index = soc_mem_field32_get(unit,mem, &vsan_entry, 
   3301                                           FCOE_FC_MAP_INDEXf);
   3302         rv = _bcm_fc_map_profile_entry_delete(unit, fcmap_index);
   3303         if (rv != BCM_E_NONE) {
   3304             soc_mem_unlock(unit, mem);
   3305             return rv;
   3306         }
   3307 
   3308         /* NOTE : zero out all fields (including flex counter fields)
   3309          */ 
   3310         soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 
   3311                             FLEX_CTR_OFFSET_MODEf, 0);
   3312         soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 
   3313                             FLEX_CTR_POOL_NUMBERf, 0);
   3314         soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 
   3315                             FLEX_CTR_BASE_COUNTER_IDXf, 0);
   3316         soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 
   3317                             FCOE_ROUTE_ENABLEf, 0);
   3318         soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 
   3319                             ZONE_CHECK_NORMALIZEDf, 0);
   3320         soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, L3_IIFf, 0);
   3321         soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 
   3322                             FCOE_FC_MAP_INDEXf, 0);
   3323 
   3324         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &vsan_entry);
   3325 
   3326         if (rv == BCM_E_NONE) {
   3327             /* unreserve this vsan id */
   3328             rv = _bcm_fcoe_unreserve_vsan_id(unit, index);
   3329             if (rv != BCM_E_NONE) {
   3330                 break;
   3331             }
   3332         } else {
   3333             break;
   3334         }
   3335     }
   3336 
   3337     soc_mem_unlock(unit, mem);
   3338     return rv;
   3339 }
   3340 
   3341 /* Get VSAN controls */
   3342 int 
   3343 bcm_td2_fcoe_control_vsan_get (int unit,  
   3344                                bcm_fcoe_vsan_id_t vsan_id, 
   3345                                bcm_fcoe_vsan_control_t type, 
   3346                                int *arg)
   3347 {
   3348     ing_vsan_entry_t  vsan_entry;
   3349     soc_mem_t         mem = ING_VSANm;
   3350     int               rv = BCM_E_NONE;
   3351     int               index = vsan_id;
   3352 
   3353     if (vsan_id > FCOE_MAX_VSAN_ID) {
   3354         return BCM_E_PARAM;
   3355     }
   3356 
   3357     /* read table entry */
   3358     soc_mem_lock(unit, mem);
   3359     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &vsan_entry);
   3360     if (rv != BCM_E_NONE) {
   3361         soc_mem_unlock(unit, mem);
   3362         return rv;
   3363     }
   3364     soc_mem_unlock(unit, mem);
   3365 
   3366     switch (type) {
   3367         case bcmFcoeVsanNormalizedZoneCheck:
   3368             *arg = soc_mem_field32_get(unit, mem, (uint32 *)&vsan_entry, 
   3369                                        ZONE_CHECK_NORMALIZEDf);
   3370             break;
   3371 
   3372         case bcmFcoeVsanRouteEnable:
   3373             *arg = soc_mem_field32_get(unit, mem, (uint32 *)&vsan_entry, 
   3374                                       FCOE_ROUTE_ENABLEf);
   3375             break;
   3376 
   3377         default:
   3378             rv = BCM_E_PARAM;
   3379             break;
   3380     }
   3381 
   3382     return rv;
   3383 }
   3384 
   3385 /* Set VSAN controls */
   3386 int 
   3387 bcm_td2_fcoe_control_vsan_set (int unit, 
   3388                                bcm_fcoe_vsan_id_t vsan_id, 
   3389                                bcm_fcoe_vsan_control_t type, 
   3390                                int arg)
   3391 {
   3392     ing_vsan_entry_t  vsan_entry;
   3393     soc_mem_t         mem = ING_VSANm;
   3394     int               rv = BCM_E_NONE;
   3395     int               index = vsan_id;
   3396 
   3397     if (vsan_id > FCOE_MAX_VSAN_ID) {
   3398         return BCM_E_PARAM;
   3399     }
   3400 
   3401     /* read table entry */
   3402     soc_mem_lock(unit, mem);
   3403     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &vsan_entry);
   3404     if (rv != BCM_E_NONE) {
   3405         soc_mem_unlock(unit, mem);
   3406         return rv;
   3407     }
   3408 
   3409     switch (type) {
   3410         case bcmFcoeVsanNormalizedZoneCheck:
   3411             soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 
   3412                                 ZONE_CHECK_NORMALIZEDf, (arg != 0) ? 1 : 0);
   3413             break;
   3414 
   3415         case bcmFcoeVsanRouteEnable:
   3416             soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 
   3417                                 FCOE_ROUTE_ENABLEf, (arg != 0) ? 1 : 0);
   3418             break;
   3419 
   3420         default:
   3421             rv = BCM_E_PARAM;
   3422             break;
   3423     }
   3424 
   3425     if (rv == BCM_E_NONE) {
   3426         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &vsan_entry);
   3427     }
   3428     soc_mem_unlock(unit, mem);
   3429     return rv;
   3430 }
   3431 
   3432 /* Get VSAN properties associated with a VSAN ID */
   3433 int 
   3434 bcm_td2_fcoe_vsan_get (int unit, bcm_fcoe_vsan_id_t vsan_id, 
   3435                        bcm_fcoe_vsan_t *vsan)
   3436 {
   3437     ing_vsan_entry_t  vsan_entry;
   3438     soc_mem_t         mem = ING_VSANm;
   3439     int               rv = BCM_E_NONE;
   3440     int               index = vsan_id;
   3441     int               flag = 0;
   3442     int               fcmap_index = 0;
   3443     bcm_fcoe_fcmap_t  fcmap;
   3444 
   3445     if (vsan_id > FCOE_MAX_VSAN_ID) {
   3446         return BCM_E_PARAM;
   3447     }
   3448 
   3449     /* NOTE : for now, reading a not-initialized(not created) entry is not
   3450      *        allowed. we may change this behavior....
   3451      */
   3452     if (shr_idxres_list_elem_state(vsan_id_list[unit], vsan_id) !=
   3453             BCM_E_EXISTS) {
   3454         return BCM_E_NOT_FOUND;
   3455     }
   3456 
   3457     /* read table entry */
   3458     soc_mem_lock(unit, mem);
   3459     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &vsan_entry);
   3460     soc_mem_unlock(unit, mem);
   3461     if (rv != BCM_E_NONE) {
   3462         return rv;
   3463     }
   3464 
   3465     fcmap_index = soc_mem_field32_get(unit, mem, (uint32 *)&vsan_entry,
   3466                                       FCOE_FC_MAP_INDEXf);
   3467     /* get fcmap value for fcmap index */
   3468     rv = _bcm_fcoe_fc_profile_map_value_get (unit, fcmap_index, &fcmap);
   3469     if (rv != BCM_E_NONE) {
   3470         return rv;
   3471     }
   3472     vsan->fcmap = fcmap;
   3473 
   3474     vsan->config_flags = 0;
   3475     flag = soc_mem_field32_get(unit, mem, (uint32 *)&vsan_entry, 
   3476                                ZONE_CHECK_NORMALIZEDf);
   3477     if (flag) {
   3478         vsan->config_flags |= BCM_FCOE_VSAN_CONFIG_NORMALIZED_ZONE_CHECK;
   3479     }
   3480     flag = soc_mem_field32_get(unit, mem, (uint32 *)&vsan_entry, 
   3481                                FCOE_ROUTE_ENABLEf);
   3482     if (flag) {
   3483         vsan->config_flags |= BCM_FCOE_VSAN_CONFIG_FCOE_ROUTE_ENABLE;
   3484     }
   3485 
   3486     vsan->l3_intf_id = soc_mem_field32_get(unit, mem, (uint32 *)&vsan_entry,
   3487                                            L3_IIFf);
   3488     vsan->fcmap = fcmap;
   3489 
   3490     return rv;
   3491 }
   3492 
   3493 /* Update VSAN properties associated with a VSAN ID */
   3494 int 
   3495 bcm_td2_fcoe_vsan_set (int unit, bcm_fcoe_vsan_id_t vsan_id, 
   3496                        bcm_fcoe_vsan_t *vsan)
   3497 {
   3498     ing_vsan_entry_t  vsan_entry;
   3499     soc_mem_t         mem = ING_VSANm;
   3500     int               rv = BCM_E_NONE;
   3501     int               index = vsan_id;
   3502     uint32            fcmap_index = 0;
   3503     int               old_fcmap_index;
   3504     void              *entries[1];
   3505     uint32            fcmap_to_set;
   3506 
   3507     if (vsan_id > FCOE_MAX_VSAN_ID) {
   3508         return BCM_E_PARAM;
   3509     }
   3510 
   3511     /* check if vsan id is already created */
   3512     if (shr_idxres_list_elem_state(vsan_id_list[unit], vsan_id) !=
   3513             BCM_E_EXISTS) {
   3514         return BCM_E_NOT_FOUND;
   3515     }
   3516 
   3517     /* read table entry */
   3518     soc_mem_lock(unit, mem);
   3519     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &vsan_entry);
   3520     if (rv != BCM_E_NONE) {
   3521         soc_mem_unlock(unit, mem);
   3522         return rv;
   3523     }
   3524 
   3525     old_fcmap_index = soc_mem_field32_get(unit, mem, (uint32 *)&vsan_entry,
   3526                                           FCOE_FC_MAP_INDEXf);
   3527     fcmap_to_set = vsan->fcmap;
   3528     entries[0] = &fcmap_to_set;
   3529 
   3530     rv = _bcm_fc_map_profile_entry_add(unit, entries, 1, &fcmap_index);
   3531 
   3532     if (rv != SOC_E_NONE) {
   3533         soc_mem_unlock(unit, mem);
   3534         return rv;
   3535     }
   3536 
   3537     if (vsan->config_flags & BCM_FCOE_VSAN_CONFIG_NORMALIZED_ZONE_CHECK) {
   3538         soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 
   3539                             ZONE_CHECK_NORMALIZEDf, 1);
   3540     } else {
   3541         soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 
   3542                             ZONE_CHECK_NORMALIZEDf, 0);
   3543     }
   3544     if (vsan->config_flags & BCM_FCOE_VSAN_CONFIG_FCOE_ROUTE_ENABLE) {
   3545         soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 
   3546                             FCOE_ROUTE_ENABLEf, 1);
   3547     } else {
   3548         soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry, 
   3549                             FCOE_ROUTE_ENABLEf, 0);
   3550     }
   3551 
   3552     soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry,
   3553                         L3_IIFf, vsan->l3_intf_id);
   3554     soc_mem_field32_set(unit, mem, (uint32 *)&vsan_entry,
   3555                         FCOE_FC_MAP_INDEXf, fcmap_index);
   3556 
   3557     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, &vsan_entry);
   3558 
   3559     if (rv == BCM_E_NONE) {
   3560         rv = _bcm_fc_map_profile_entry_delete(unit, old_fcmap_index);
   3561     }
   3562 
   3563     soc_mem_unlock(unit, mem);
   3564 
   3565     return rv;
   3566 }
   3567 
   3568 /*
   3569  * Description:
   3570  *      Check that parameters sent to bcm_td2_fcoe_fc_header_type_* functions
   3571  *      are valid.
   3572  * Parameters:
   3573  *      flags      - (IN) BCM_FCOE_FC_HEADER_TYPE_INGRESS/EGRESS
   3574  *      hdr_type   - (IN) Header type to force this value of r_ctl to use
   3575  * Returns:
   3576  *      BCM_E_XXX
   3577  */
   3578 STATIC int
   3579 _bcm_td2_fcoe_fc_header_sanity_check(uint32 flags, 
   3580                                      bcm_fcoe_fc_header_type_t hdr_type)
   3581 {
   3582     int rv = BCM_E_NONE;
   3583 
   3584     if (hdr_type > bcmFcoeFcHeaderTypeCount 
   3585         || hdr_type < bcmFcoeFcHeaderTypeNone) {
   3586         rv = BCM_E_PARAM;
   3587     }
   3588 
   3589     if (!(flags & BCM_FCOE_FC_HEADER_TYPE_INGRESS)
   3590         && !(flags & BCM_FCOE_FC_HEADER_TYPE_EGRESS)) {
   3591         rv = BCM_E_PARAM;
   3592     }
   3593 
   3594     return rv;
   3595 }
   3596 
   3597 /*
   3598  * Description:
   3599  *      Convert a hardware value of header type to the corresponding
   3600  *      bcm_fcoe_fc_header_type_t enum
   3601  * Parameters:
   3602  *      encoded_value - (IN) hardware value to convert
   3603  *      hdr_type      - (OUT) resulting header type enum
   3604  * Returns:
   3605  *      BCM_E_XXX
   3606  */
   3607 STATIC int
   3608 _bcm_td2_fcoe_hdr_encode_to_hdr_type(uint32 encoded_value, 
   3609                                      bcm_fcoe_fc_header_type_t *hdr_type)
   3610 {
   3611     int rv = BCM_E_NONE;
   3612 
   3613     switch (encoded_value) {
   3614         case FC_HEADER_TYPE_NOT_PRESENT:
   3615             *hdr_type = bcmFcoeFcHeaderTypeNone;
   3616             break;
   3617 
   3618         case FC_HEADER_TYPE_STANDARD:
   3619             *hdr_type = bcmFcoeFcHeaderTypeStd;
   3620             break;
   3621 
   3622         case FC_HEADER_TYPE_ENCAPSULATION:
   3623             *hdr_type = bcmFcoeFcHeaderTypeEncap;
   3624             break;
   3625 
   3626         case FC_HEADER_TYPE_VFT:
   3627             *hdr_type = bcmFcoeFcHeaderTypeVft;
   3628             break;
   3629 
   3630         case FC_HEADER_TYPE_IFR:
   3631             *hdr_type = bcmFcoeFcHeaderTypeIfr;
   3632             break;
   3633 
   3634         case FC_HEADER_TYPE_UNKNOWN:
   3635             *hdr_type = bcmFcoeFcHeaderTypeUnknown;
   3636             break;
   3637 
   3638         default:
   3639             rv = BCM_E_PARAM;
   3640             break;
   3641     }
   3642 
   3643     return rv;
   3644 }
   3645 
   3646 /*
   3647  * Description:
   3648  *      Convert a bcm_fcoe_fc_header_type_t enum to the corresponding value that
   3649  *      should be programmed to hardware
   3650  * Parameters:
   3651  *      hdr_type      - (IN) header type enum to convert
   3652  *      encoded_value - (OUT) resulting hardware value
   3653  * Returns:
   3654  *      BCM_E_XXX
   3655  */
   3656 STATIC int
   3657 _bcm_td2_fcoe_hdr_type_to_hdr_encode(bcm_fcoe_fc_header_type_t hdr_type, 
   3658                                      uint32 *encoded_value)
   3659 {
   3660     int rv = BCM_E_NONE;
   3661 
   3662     switch (hdr_type) {
   3663         case bcmFcoeFcHeaderTypeNone:
   3664             *encoded_value = FC_HEADER_TYPE_NOT_PRESENT;
   3665             break;
   3666 
   3667         case bcmFcoeFcHeaderTypeStd:
   3668             *encoded_value = FC_HEADER_TYPE_STANDARD;
   3669             break;
   3670 
   3671         case bcmFcoeFcHeaderTypeEncap:
   3672             *encoded_value = FC_HEADER_TYPE_ENCAPSULATION;
   3673             break;
   3674 
   3675         case bcmFcoeFcHeaderTypeVft:
   3676             *encoded_value = FC_HEADER_TYPE_VFT;
   3677             break;
   3678 
   3679         case bcmFcoeFcHeaderTypeIfr:
   3680             *encoded_value = FC_HEADER_TYPE_IFR;
   3681             break;
   3682 
   3683         case bcmFcoeFcHeaderTypeUnknown:
   3684             *encoded_value = FC_HEADER_TYPE_UNKNOWN;
   3685             break;
   3686 
   3687         default:
   3688             rv = BCM_E_PARAM;
   3689             break;
   3690     }
   3691 
   3692     return rv;
   3693 }
   3694 
   3695 /*
   3696  * Description:
   3697  *      Write header type to hardware
   3698  * Parameters:
   3699  *      unit       - (IN) device number
   3700  *      mem        - (IN) device memory to write
   3701  *      r_ctl      - (IN) [0-255] value of r_ctl to write
   3702  *      hdr_encode - (IN) Header type to store at this r_ctl value
   3703  * Return:
   3704  *      BCM_E_XXX
   3705  */
   3706 STATIC int
   3707 _bcm_td2_fcoe_fc_program_header(int unit, soc_mem_t mem, uint8 r_ctl, 
   3708                                 uint32 hdr_encode)
   3709 {
   3710     ing_fc_header_type_entry_t ing_entry;
   3711     egr_fc_header_type_entry_t egr_entry;
   3712     uint32                     *buf = NULL;
   3713     int                        rv = BCM_E_NONE;
   3714 
   3715     sal_memset(&ing_entry, 0, sizeof ing_entry);
   3716     sal_memset(&egr_entry, 0, sizeof egr_entry);
   3717 
   3718     if ((mem == ING_FC_HEADER_TYPEm) ||
   3719         (mem == PARSER1_ING_FC_HEADER_TYPEm) ||
   3720         (mem == PARSER2_ING_FC_HEADER_TYPEm)) {
   3721         buf = (uint32 *)&ing_entry;
   3722     } else if (mem == EGR_FC_HEADER_TYPEm) {
   3723         buf = (uint32 *)&egr_entry;
   3724     } else {
   3725         rv = BCM_E_PARAM;
   3726     }
   3727 
   3728     if (rv == BCM_E_NONE) {
   3729         soc_mem_field32_set(unit, mem, buf, FC_HDR_ENCODEf, hdr_encode);
   3730     }
   3731 
   3732     if (rv == BCM_E_NONE) {
   3733         soc_mem_lock(unit, mem);
   3734         rv = BCM_XGS3_MEM_WRITE(unit, mem, r_ctl, buf);
   3735         soc_mem_unlock(unit, mem);
   3736     }
   3737 
   3738     return rv;
   3739 }
   3740 
   3741 /*
   3742  * Description:
   3743  *      Read header type from hardware and return it
   3744  * Parameters:
   3745  *      unit       - (IN) device number
   3746  *      mem        - (IN) device memory to read
   3747  *      r_ctl      - (IN) [0-255] value of r_ctl to read
   3748  *      hdr_encode - (OUT) Header type stored at this r_ctl value
   3749  * Return:
   3750  *      BCM_E_XXX
   3751  */
   3752 STATIC int
   3753 _bcm_td2_fcoe_fc_read_header(int unit, soc_mem_t mem, uint8 r_ctl, 
   3754                              uint32 *hdr_encode)
   3755 {
   3756     ing_fc_header_type_entry_t ing_entry;
   3757     egr_fc_header_type_entry_t egr_entry;
   3758     uint32                     *buf = NULL;
   3759     int                        rv = BCM_E_NONE;
   3760 
   3761     if ((mem == ING_FC_HEADER_TYPEm) ||
   3762         (mem == PARSER1_ING_FC_HEADER_TYPEm) ||
   3763         (mem == PARSER2_ING_FC_HEADER_TYPEm)) {
   3764         buf = (uint32 *)&ing_entry;
   3765     } else if (mem == EGR_FC_HEADER_TYPEm) {
   3766         buf = (uint32 *)&egr_entry;
   3767     } else {
   3768         rv = BCM_E_PARAM;
   3769     }
   3770 
   3771     if (rv == BCM_E_NONE) {
   3772         soc_mem_lock(unit, mem);
   3773         rv = BCM_XGS3_MEM_READ(unit, mem, r_ctl, buf);
   3774         soc_mem_unlock(unit, mem);
   3775     }
   3776 
   3777     if (rv == BCM_E_NONE) {
   3778         *hdr_encode = soc_mem_field32_get(unit, mem, buf, FC_HDR_ENCODEf);
   3779     }
   3780 
   3781     return rv;
   3782 }
   3783 
   3784 /*
   3785  * Description:
   3786  *      Set FC header type
   3787  * Parameters:
   3788  *      unit       - (IN) device number
   3789  *      flags      - (IN) BCM_FCOE_FC_HEADER_TYPE_INGRESS/EGRESS
   3790  *      r_ctl      - (IN) [0-255] value of r_ctl to modify
   3791  *      hdr_type   - (IN) Header type to force this value of r_ctl to use
   3792  * Return:
   3793  *      BCM_E_XXX
   3794  */
   3795  int
   3796  bcm_td2_fcoe_fc_header_type_set(int unit, uint32 flags, uint8 r_ctl, 
   3797                                  bcm_fcoe_fc_header_type_t hdr_type)
   3798 {
   3799     int rv = BCM_E_NONE;
   3800     uint32 encoded_value = 0;
   3801 
   3802     rv = _bcm_td2_fcoe_fc_header_sanity_check(flags, hdr_type);
   3803 
   3804     if (rv == BCM_E_NONE) {
   3805         rv = _bcm_td2_fcoe_hdr_type_to_hdr_encode(hdr_type, &encoded_value);
   3806     }
   3807 
   3808     if ((rv == BCM_E_NONE) && (flags & BCM_FCOE_FC_HEADER_TYPE_INGRESS)) {
   3809 #ifdef BCM_TRIDENT3_SUPPORT
   3810         if (SOC_IS_TRIDENT3X(unit)) {
   3811             rv = _bcm_td2_fcoe_fc_program_header(unit, PARSER1_ING_FC_HEADER_TYPEm, 
   3812                                                  r_ctl, encoded_value);
   3813             if (rv == BCM_E_NONE) {
   3814                 rv = _bcm_td2_fcoe_fc_program_header(unit, PARSER2_ING_FC_HEADER_TYPEm, 
   3815                                                  r_ctl, encoded_value);
   3816             }
   3817         } else
   3818 #endif /* BCM_TRIDENT3_SUPPORT */
   3819         {
   3820             rv = _bcm_td2_fcoe_fc_program_header(unit, ING_FC_HEADER_TYPEm, 
   3821                                                  r_ctl, encoded_value);
   3822         }
   3823     }
   3824 
   3825     if ((rv == BCM_E_NONE) && (flags & BCM_FCOE_FC_HEADER_TYPE_EGRESS)) {
   3826 #ifdef BCM_TRIDENT3_SUPPORT
   3827         if (!(SOC_IS_TRIDENT3X(unit)))
   3828 #endif /* BCM_TRIDENT3_SUPPORT */
   3829         {
   3830             rv = _bcm_td2_fcoe_fc_program_header(unit, EGR_FC_HEADER_TYPEm, 
   3831                                              r_ctl, encoded_value);
   3832         }
   3833     }
   3834 
   3835     return rv;
   3836 }
   3837 
   3838 /*
   3839  * Description:
   3840  *      Retrieve FC header type
   3841  * Parameters:
   3842  *      unit       - (IN) device number
   3843  *      flags      - (IN) BCM_FCOE_FC_HEADER_TYPE_INGRESS/EGRESS
   3844  *      r_ctl      - (IN) [0-255] value of r_ctl to retrieve
   3845  *      hdr_type   - (OUT) Header type that this value of r_ctl is forced to
   3846  * Return:
   3847  *      BCM_E_XXX
   3848  */
   3849  int
   3850  bcm_td2_fcoe_fc_header_type_get(int unit, uint32 flags, uint8 r_ctl, 
   3851                                  bcm_fcoe_fc_header_type_t *hdr_type)
   3852 {
   3853     int rv = BCM_E_NONE, mem;
   3854     uint32 encoded_value = 0;
   3855 
   3856     if ((flags & BCM_FCOE_FC_HEADER_TYPE_INGRESS)
   3857         && (flags & BCM_FCOE_FC_HEADER_TYPE_EGRESS)) {
   3858         return (BCM_E_PARAM);
   3859     }
   3860 
   3861     if (flags & BCM_FCOE_FC_HEADER_TYPE_INGRESS) {
   3862         mem = (SOC_IS_TRIDENT3X(unit)) ?  PARSER1_ING_FC_HEADER_TYPEm :
   3863                                          ING_FC_HEADER_TYPEm;
   3864     } else if (flags & BCM_FCOE_FC_HEADER_TYPE_EGRESS) {
   3865         mem = (SOC_IS_TRIDENT3X(unit)) ? PARSER2_ING_FC_HEADER_TYPEm :
   3866                                        EGR_FC_HEADER_TYPEm;
   3867     } else {
   3868         return (BCM_E_PARAM);
   3869     }
   3870     rv = _bcm_td2_fcoe_fc_read_header(unit, mem, r_ctl, &encoded_value);
   3871 
   3872     if (rv == BCM_E_NONE) {
   3873         rv = _bcm_td2_fcoe_hdr_encode_to_hdr_type(encoded_value, hdr_type);
   3874     }
   3875 
   3876     return rv;
   3877 }
   3878 
   3879 /*
   3880  * Provides relevant flex table information(table-name,index with
   3881  *  direction) for given VSAN ID.
   3882  */
   3883 STATIC bcm_error_t 
   3884 _bcm_td2_vsan_stat_get_table_info (int                        unit,
   3885                                    bcm_fcoe_vsan_id_t         vsan,
   3886                                    uint32                     *num_of_tables,
   3887                                    bcm_stat_flex_table_info_t *table_info)
   3888 {
   3889     int index = 0;
   3890 
   3891     if (!soc_feature(unit,soc_feature_advanced_flex_counter)) {
   3892         return BCM_E_UNAVAIL;
   3893     }
   3894 
   3895     /* Get index into ING_VSAN table. VSAN ID is index (12 bits). */
   3896     if (vsan > 0xfff) {
   3897         return BCM_E_PARAM;
   3898     }
   3899     index = (int)vsan;
   3900 
   3901     /* Ingress VSAN */
   3902     table_info[*num_of_tables].table=ING_VSANm;
   3903     table_info[*num_of_tables].index=index;
   3904     table_info[*num_of_tables].direction=bcmStatFlexDirectionIngress;
   3905     (*num_of_tables)++;
   3906 
   3907     return BCM_E_NONE;
   3908 }
   3909 
   3910 /* Allocate flex counter and assign counter index/offset for
   3911  * FCOE VSAN ID
   3912  */
   3913 int 
   3914 bcm_td2_fcoe_vsan_stat_attach (int                 unit,
   3915                                bcm_fcoe_vsan_id_t  vsan,
   3916                                uint32              stat_counter_id)
   3917 {
   3918     int                        rv = BCM_E_NONE;
   3919     int                        counter_flag = 0;
   3920     soc_mem_t                  table = 0;
   3921     bcm_stat_flex_direction_t  direction = bcmStatFlexDirectionIngress;
   3922     uint32                     pool_number = 0;
   3923     uint32                     base_index = 0;
   3924     bcm_stat_flex_mode_t       offset_mode = 0;
   3925     bcm_stat_object_t          object = bcmStatObjectIngPort;
   3926     bcm_stat_group_mode_t      group_mode = bcmStatGroupModeSingle;
   3927     uint32                     count = 0;
   3928     uint32                     actual_num_tables = 0;
   3929     uint32                     num_of_tables = 0;
   3930     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   3931 
   3932 
   3933     /* Get pool, base index group mode and offset modes from stat counter id */
   3934     _bcm_esw_stat_get_counter_id_info(
   3935                   unit, stat_counter_id,
   3936                   &group_mode, &object, &offset_mode, &pool_number, 
   3937                   &base_index);
   3938 
   3939     /* Validate object and group mode */
   3940     BCM_IF_ERROR_RETURN(
   3941         _bcm_esw_stat_validate_object(unit, object, &direction));
   3942     BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_group(unit, group_mode));
   3943 
   3944     /* Get Table index to attach flexible counter */
   3945     BCM_IF_ERROR_RETURN(_bcm_esw_stat_flex_get_table_info(
   3946                         unit, object, 1, &actual_num_tables, &table, 
   3947                         &direction));
   3948     BCM_IF_ERROR_RETURN(_bcm_td2_vsan_stat_get_table_info(
   3949                         unit, vsan, &num_of_tables, &table_info[0]));
   3950 
   3951     for (count = 0; count < num_of_tables; count++) {
   3952          if ((table_info[count].direction == direction) &&
   3953              (table_info[count].table == table) ) {
   3954               if (direction == bcmStatFlexDirectionIngress) {
   3955                   counter_flag = 1;
   3956                   rv = _bcm_esw_stat_flex_attach_ingress_table_counters(
   3957                          unit,
   3958                          table_info[count].table,
   3959                          table_info[count].index,
   3960                          offset_mode,
   3961                          base_index,
   3962                          pool_number);
   3963 
   3964                 if(BCM_FAILURE(rv)) {
   3965                         break;
   3966                   }
   3967 
   3968               } else {
   3969                   /* no egress table...*/
   3970               } 
   3971          }
   3972     }
   3973 
   3974     if (counter_flag == 0) {
   3975         rv = BCM_E_NOT_FOUND;
   3976     }
   3977     
   3978     return rv;
   3979 }
   3980 
   3981 /* Detach flex counter for FCOE VSAN ID  */
   3982 int 
   3983 bcm_td2_fcoe_vsan_stat_detach (int unit, bcm_fcoe_vsan_id_t  vsan)
   3984 {
   3985     int                        counter_flag = 0;
   3986     uint32                     count = 0;
   3987     uint32                     num_of_tables = 0;
   3988     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   3989     int                        rv = BCM_E_NONE;
   3990     
   3991 
   3992     /* Get the table index to be detached */
   3993     BCM_IF_ERROR_RETURN(_bcm_td2_vsan_stat_get_table_info(
   3994                    unit, vsan, &num_of_tables, &table_info[0]));
   3995 
   3996     for (count = 0; count < num_of_tables; count++) {
   3997          if (table_info[count].direction == bcmStatFlexDirectionIngress) {
   3998              counter_flag = 1;
   3999              rv = _bcm_esw_stat_flex_detach_ingress_table_counters(
   4000                         unit, table_info[count].table, table_info[count].index);
   4001          } else {
   4002              /* no egress table...*/
   4003          }
   4004     }
   4005 
   4006     if (counter_flag == 0) {
   4007         return BCM_E_NOT_FOUND;
   4008     }
   4009 
   4010     return rv;
   4011 }
   4012 
   4013 /* Get flex counter for FCOE VSAN ID */                          
   4014 int 
   4015 bcm_td2_fcoe_vsan_stat_counter_get (int                  unit, 
   4016                                     int                  sync_mode,
   4017                                     bcm_fcoe_vsan_id_t   vsan,
   4018                                     bcm_fcoe_vsan_stat_t stat, 
   4019                                     uint32               num_entries, 
   4020                                     uint32               *counter_indexes, 
   4021                                     bcm_stat_value_t     *counter_values)
   4022 {
   4023     uint32                     table_count = 0;
   4024     uint32                     index_count = 0;
   4025     uint32                     num_of_tables = 0;
   4026     bcm_stat_flex_direction_t  direction = bcmStatFlexDirectionIngress;
   4027     uint32                     byte_flag = 0;
   4028     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   4029 
   4030     if ((stat == bcmFcoeVsanInPackets) ||
   4031         (stat == bcmFcoeVsanInBytes)) {
   4032          direction = bcmStatFlexDirectionIngress;
   4033     } else {
   4034          return BCM_E_PARAM;
   4035     }
   4036     if (stat == bcmFcoeVsanInBytes) {
   4037         byte_flag = 1;
   4038     }
   4039 
   4040     /*  Get Table index to read the flex counter */
   4041     BCM_IF_ERROR_RETURN(_bcm_td2_vsan_stat_get_table_info(
   4042                         unit, vsan, &num_of_tables, &table_info[0]));
   4043 
   4044     /* Get the flex counter for the attached table index */
   4045     for (table_count = 0; table_count < num_of_tables ; table_count++) {
   4046          if (table_info[table_count].direction == direction) {
   4047              for (index_count = 0; index_count < num_entries ; index_count++) {
   4048                   BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_get(
   4049                                       unit, sync_mode,
   4050                                       table_info[table_count].index,
   4051                                       table_info[table_count].table,
   4052                                       0,
   4053                                       byte_flag,
   4054                                       counter_indexes[index_count],
   4055                                       &counter_values[index_count]));
   4056              }
   4057          }
   4058     }
   4059 
   4060     return BCM_E_NONE;
   4061 }
   4062 
   4063 /* Set flex counter for FCOE VSAN ID */                               
   4064 int 
   4065 bcm_td2_fcoe_vsan_stat_counter_set (int                  unit, 
   4066                                     bcm_fcoe_vsan_id_t   vsan,
   4067                                     bcm_fcoe_vsan_stat_t stat, 
   4068                                     uint32               num_entries, 
   4069                                     uint32               *counter_indexes, 
   4070                                     bcm_stat_value_t     *counter_values)
   4071 {
   4072     uint32                     table_count = 0;
   4073     uint32                     index_count = 0;
   4074     uint32                     num_of_tables = 0;
   4075     bcm_stat_flex_direction_t  direction = bcmStatFlexDirectionIngress;
   4076     uint32                     byte_flag = 0;
   4077     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   4078 
   4079     if ((stat == bcmFcoeVsanInPackets) ||
   4080         (stat == bcmFcoeVsanInBytes)) {
   4081          direction = bcmStatFlexDirectionIngress;
   4082     } else {
   4083          return BCM_E_PARAM;
   4084     }
   4085     if (stat == bcmFcoeVsanInBytes) {
   4086         byte_flag = 1;
   4087     }
   4088    
   4089     /*  Get Table index to read the flex counter */
   4090     BCM_IF_ERROR_RETURN(_bcm_td2_vsan_stat_get_table_info(
   4091                         unit, vsan, &num_of_tables, &table_info[0]));
   4092 
   4093     /* Set the flex counter for the attached table index */
   4094     for (table_count = 0; table_count < num_of_tables ; table_count++) {
   4095          if (table_info[table_count].direction == direction) {
   4096              for (index_count = 0; index_count < num_entries; index_count++) {
   4097                   BCM_IF_ERROR_RETURN(_bcm_esw_stat_counter_set(
   4098                                       unit,
   4099                                       table_info[table_count].index,
   4100                                       table_info[table_count].table,
   4101                                       0,
   4102                                       byte_flag,
   4103                                       counter_indexes[index_count],
   4104                                       &counter_values[index_count]));
   4105              }
   4106          }
   4107     }
   4108     return BCM_E_NONE;
   4109 }
   4110 
   4111 /* Get stat counter ID for FCOE VSAN ID */                               
   4112 int 
   4113 bcm_td2_fcoe_vsan_stat_id_get (int                  unit,
   4114                                bcm_fcoe_vsan_id_t   vsan,
   4115                                bcm_fcoe_vsan_stat_t stat, 
   4116                                uint32               *stat_counter_id)
   4117 {
   4118     bcm_stat_flex_direction_t  direction = bcmStatFlexDirectionIngress;
   4119     uint32                     num_of_tables = 0;
   4120     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   4121     uint32                     index = 0;
   4122     uint32                     num_stat_counter_ids = 0;
   4123 
   4124     if ((stat == bcmFcoeVsanInPackets) ||
   4125         (stat == bcmFcoeVsanInBytes)) {
   4126          direction = bcmStatFlexDirectionIngress;
   4127     } else {
   4128          return BCM_E_PARAM;
   4129     }
   4130 
   4131     /*  Get Tables, for which flex counter are attached  */
   4132     BCM_IF_ERROR_RETURN(
   4133         _bcm_td2_vsan_stat_get_table_info(unit, vsan, &num_of_tables, 
   4134                                           &table_info[0]));
   4135 
   4136     /* Retrieve stat counter id */
   4137     for (index = 0; index < num_of_tables ; index++) {
   4138          if (table_info[index].direction == direction) {
   4139              return _bcm_esw_stat_flex_get_counter_id(
   4140                                   unit, 1, &table_info[index],
   4141                                   &num_stat_counter_ids, stat_counter_id);
   4142          }
   4143     }
   4144     return BCM_E_NOT_FOUND;
   4145 }
   4146                                
   4147 #if defined (INCLUDE_L3)
   4148 
   4149 STATIC int
   4150 _bcm_td2_fcoe_route_index_get_ext(int unit, bcm_fcoe_route_t *route, int *index)
   4151 {
   4152     l3_entry_ipv4_multicast_entry_t l3_ext_entry[2];
   4153 
   4154     soc_mem_t  mem = _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit);
   4155     uint32     *buf = (uint32 *)&l3_ext_entry[0];
   4156     uint32     *lookup = (uint32 *)&l3_ext_entry[1];
   4157 
   4158     memset(&l3_ext_entry, 0, sizeof l3_ext_entry);
   4159 
   4160     BCM_IF_ERROR_RETURN(_bcm_fcoe_route_construct_key_ext(unit, mem, buf,
   4161                                                           route));
   4162 
   4163     /* Search for this key in the existing database */
   4164     return soc_mem_search(unit, mem, MEM_BLOCK_ANY, index, buf,
   4165                           (void *)lookup, 0);
   4166 }
   4167 
   4168 
   4169 STATIC int
   4170 _bcm_td2_fcoe_route_index_get_normal(int unit, bcm_fcoe_route_t *route, int *index)
   4171 {
   4172     l3_entry_ipv4_unicast_entry_t   l3_entry[2];
   4173 
   4174     soc_mem_t  mem = _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit);
   4175     uint32     *buf = (uint32 *)&l3_entry[0];
   4176     uint32     *lookup = (uint32 *)&l3_entry[1];
   4177 
   4178     memset(&l3_entry, 0, sizeof l3_entry);
   4179 
   4180     BCM_IF_ERROR_RETURN(_bcm_fcoe_route_construct_key_normal(unit, mem, buf,
   4181                                                              route));
   4182 
   4183     /* Search for this key in the existing database */
   4184     return soc_mem_search(unit, mem, MEM_BLOCK_ANY, index, buf,
   4185                           (void *)lookup, 0);
   4186 }
   4187 
   4188 
   4189 STATIC int
   4190 _bcm_td2_fcoe_route_index_get(int unit, bcm_fcoe_route_t *route, int *index)
   4191 {
   4192     int rv;
   4193 
   4194     rv = _bcm_td2_fcoe_route_index_get_normal(unit, route, index);
   4195 
   4196     if (rv != BCM_E_NONE) {
   4197         rv = _bcm_td2_fcoe_route_index_get_ext(unit, route, index);
   4198     }
   4199 
   4200     return rv;
   4201 }
   4202 
   4203 /*
   4204  * Provides relevant flex table information(table-name,index with
   4205  *  direction)  for given route info.
   4206  */
   4207 STATIC bcm_error_t 
   4208 _bcm_td2_fcoe_route_stat_get_table_info (
   4209                                    int                        unit,
   4210                                    bcm_fcoe_route_t           *route,
   4211                                    uint32                     *num_of_tables,
   4212                                    bcm_stat_flex_table_info_t *table_info)
   4213 {
   4214     int index = 0;
   4215 
   4216     if (!soc_feature(unit,soc_feature_advanced_flex_counter)) {
   4217         return BCM_E_UNAVAIL;
   4218     }
   4219 
   4220     /* Get unique index for the route info.
   4221      * Support all fcoe types: FCOE_DOMAIN_EXT, FCOE_HOST_EXT,
   4222      *                         FCOE_SOURCE_MAP_EXT
   4223      */
   4224     if (_bcm_td2_fcoe_route_index_get(unit, route, &index) != BCM_E_NONE) {
   4225         return BCM_E_NOT_FOUND;
   4226     }
   4227 
   4228     /* Ingress FCOE */
   4229     table_info[*num_of_tables].table = _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit);
   4230     table_info[*num_of_tables].index = (uint32)index;
   4231     table_info[*num_of_tables].direction = bcmStatFlexDirectionIngress;
   4232     (*num_of_tables)++;
   4233 
   4234     return BCM_E_NONE;
   4235 }
   4236 #endif  /* INCLUDE_L3*/
   4237 
   4238 /* Allocate flex counter and assign counter index/offset for  
   4239  * FCOE Route
   4240  */
   4241 int 
   4242 bcm_td2_fcoe_route_stat_attach (int                 unit,
   4243                                 bcm_fcoe_route_t    *route,
   4244                                 uint32              stat_counter_id)
   4245 {
   4246 #if defined(INCLUDE_L3)
   4247 
   4248     int                        rv = BCM_E_NONE;
   4249     int                        counter_flag = 0;
   4250     soc_mem_t                  table = 0;
   4251     bcm_stat_flex_direction_t  direction = bcmStatFlexDirectionIngress;
   4252     uint32                     pool_number = 0;
   4253     uint32                     base_index = 0;
   4254     bcm_stat_flex_mode_t       offset_mode = 0;
   4255     bcm_stat_object_t          object = bcmStatObjectIngPort;
   4256     bcm_stat_group_mode_t      group_mode = bcmStatGroupModeSingle;
   4257     uint32                     count = 0;
   4258     uint32                     actual_num_tables = 0;
   4259     uint32                     num_of_tables = 0;
   4260     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   4261 
   4262     if (!BCM_XGS3_L3_EGRESS_MODE_ISSET(unit) ||
   4263         (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, route->intf)) ||
   4264         (BCM_XGS3_L3_MPATH_EGRESS_IDX_VALID(unit, route->intf)) ||
   4265         (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, route->intf)) ||
   4266         (BCM_XGS3_PROXY_EGRESS_IDX_VALID(unit, route->intf))) {
   4267         return BCM_E_PARAM;
   4268     }
   4269 
   4270     /* Get pool, base index group mode and offset modes from stat counter id */
   4271     _bcm_esw_stat_get_counter_id_info(unit, stat_counter_id, &group_mode, &object, 
   4272                                       &offset_mode, &pool_number, &base_index);
   4273 
   4274     /* Validate object and group mode */
   4275     BCM_IF_ERROR_RETURN(
   4276         _bcm_esw_stat_validate_object(unit, object, &direction));
   4277     BCM_IF_ERROR_RETURN(_bcm_esw_stat_validate_group(unit, group_mode));
   4278 
   4279     /* Get Table index to attach flexible counter */
   4280     BCM_IF_ERROR_RETURN(
   4281         _bcm_esw_stat_flex_get_table_info(unit, object, 1, &actual_num_tables, 
   4282                                           &table, &direction));
   4283     BCM_IF_ERROR_RETURN(
   4284         _bcm_td2_fcoe_route_stat_get_table_info(unit, route, &num_of_tables, 
   4285                                           &table_info[0]));
   4286 
   4287     for (count = 0; count < num_of_tables; count++) {
   4288          if ((table_info[count].direction == direction) &&
   4289              (table_info[count].table == table) ) {
   4290               if (direction == bcmStatFlexDirectionIngress) {
   4291                   counter_flag = 1;
   4292                   rv = _bcm_esw_stat_flex_attach_ingress_table_counters(
   4293                          unit,
   4294                          table_info[count].table,
   4295                          table_info[count].index,
   4296                          offset_mode,
   4297                          base_index,
   4298                          pool_number);
   4299                 if(BCM_FAILURE(rv)) {
   4300                         break;
   4301                   }
   4302               } else {
   4303                   /* shouldn't reach here, only ingress is supported */
   4304               } 
   4305          }
   4306     }
   4307 
   4308     if (counter_flag == 0) {
   4309         rv = BCM_E_NOT_FOUND;
   4310     }
   4311 
   4312     return rv;
   4313 #else
   4314     return BCM_E_UNAVAIL;
   4315 #endif  /* INCLUDE_L3 */
   4316 }
   4317 
   4318 /* Detach flex counter for FCOE Route */                                
   4319 int 
   4320 bcm_td2_fcoe_route_stat_detach (int unit, bcm_fcoe_route_t *route)
   4321 {
   4322 #if defined(INCLUDE_L3)
   4323     int                        counter_flag = 0;
   4324     uint32                     count = 0;
   4325     uint32                     num_of_tables = 0;
   4326     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   4327     int                        rv = BCM_E_NONE;
   4328 
   4329     /* Get the table index to be detached */
   4330     BCM_IF_ERROR_RETURN(_bcm_td2_fcoe_route_stat_get_table_info(
   4331                         unit, route, &num_of_tables, &table_info[0]));
   4332 
   4333     for (count = 0; count < num_of_tables; count++) {
   4334          if (table_info[count].direction == bcmStatFlexDirectionIngress) {
   4335              counter_flag = 1;
   4336              rv = _bcm_esw_stat_flex_detach_ingress_table_counters(
   4337                         unit, table_info[count].table, table_info[count].index);
   4338          } else {
   4339              /* no egress support */
   4340          }
   4341     }
   4342 
   4343     if (counter_flag == 0) {
   4344         return BCM_E_NOT_FOUND;
   4345     }
   4346 
   4347     return rv;
   4348 #else
   4349     return BCM_E_UNAVAIL;
   4350 #endif  /* INCLUDE_L3 */
   4351 }
   4352 
   4353 /* Get flex counter for FCOE Route */                                
   4354 int 
   4355 bcm_td2_fcoe_route_stat_counter_get (int                   unit, 
   4356                                      int                   sync_mode, 
   4357                                      bcm_fcoe_route_t      *route,
   4358                                      bcm_fcoe_route_stat_t stat, 
   4359                                      uint32                num_entries, 
   4360                                      uint32                *counter_indexes, 
   4361                                      bcm_stat_value_t      *counter_values)
   4362 {
   4363 #if defined(INCLUDE_L3)
   4364     uint32                     table_count = 0;
   4365     uint32                     index_count = 0;
   4366     uint32                     num_of_tables = 0;
   4367     bcm_stat_flex_direction_t  direction = bcmStatFlexDirectionIngress;
   4368     uint32                     byte_flag = 0;
   4369     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   4370 
   4371     if ((stat != bcmFcoeRouteInPackets) && (stat != bcmFcoeRouteInBytes)) {
   4372         return BCM_E_PARAM;
   4373     }
   4374 
   4375     if (stat == bcmFcoeRouteInBytes) {
   4376         byte_flag = 1;
   4377     }
   4378    
   4379     /*  Get Table index to read the flex counter */
   4380     BCM_IF_ERROR_RETURN(
   4381         _bcm_td2_fcoe_route_stat_get_table_info(unit, route, &num_of_tables, 
   4382                                           &table_info[0]));
   4383 
   4384     /* Get the flex counter for the attached table index */
   4385     for (table_count = 0; table_count < num_of_tables ; table_count++) {
   4386          if (table_info[table_count].direction == direction) {
   4387              for (index_count = 0; index_count < num_entries ; index_count++) {
   4388                   BCM_IF_ERROR_RETURN(
   4389                       _bcm_esw_stat_counter_get(unit, sync_mode,
   4390                                                 table_info[table_count].index,
   4391                                                 table_info[table_count].table,
   4392                                                 0,
   4393                                                 byte_flag,
   4394                                                 counter_indexes[index_count],
   4395                                                 &counter_values[index_count]));
   4396              }
   4397          }
   4398     }
   4399 
   4400     return BCM_E_NONE;
   4401 #else
   4402     return BCM_E_UNAVAIL;
   4403 #endif  /* INCLUDE_L3 */
   4404 }
   4405 
   4406 /* Set flex counter for FCOE Route */
   4407 int 
   4408 bcm_td2_fcoe_route_stat_counter_set (int                   unit, 
   4409                                      bcm_fcoe_route_t      *route,
   4410                                      bcm_fcoe_route_stat_t stat, 
   4411                                      uint32                num_entries, 
   4412                                      uint32                *counter_indexes, 
   4413                                      bcm_stat_value_t      *counter_values)
   4414 {
   4415 #if defined(INCLUDE_L3)
   4416     uint32                     table_count = 0;
   4417     uint32                     index_count = 0;
   4418     uint32                     num_of_tables = 0;
   4419     bcm_stat_flex_direction_t  direction = bcmStatFlexDirectionIngress;
   4420     uint32                     byte_flag = 0;
   4421     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   4422 
   4423     if ((stat != bcmFcoeRouteInPackets) && (stat != bcmFcoeRouteInBytes)) {
   4424         return BCM_E_PARAM;
   4425     }
   4426 
   4427     if (stat == bcmFcoeRouteInBytes) {
   4428         byte_flag = 1;
   4429     }
   4430    
   4431     /*  Get Table index to read the flex counter */
   4432     BCM_IF_ERROR_RETURN(
   4433         _bcm_td2_fcoe_route_stat_get_table_info(unit, route, &num_of_tables, 
   4434                                           &table_info[0]));
   4435 
   4436     /* Get the flex counter for the attached table index */
   4437     for (table_count = 0; table_count < num_of_tables ; table_count++) {
   4438          if (table_info[table_count].direction == direction) {
   4439              for (index_count = 0; index_count < num_entries; index_count++) {
   4440                   BCM_IF_ERROR_RETURN(
   4441                       _bcm_esw_stat_counter_set(unit,
   4442                                                 table_info[table_count].index,
   4443                                                 table_info[table_count].table,
   4444                                                 0,
   4445                                                 byte_flag,
   4446                                                 counter_indexes[index_count],
   4447                                                 &counter_values[index_count]));
   4448              }
   4449          }
   4450     }
   4451     return BCM_E_NONE;
   4452 #else
   4453     return BCM_E_UNAVAIL;
   4454 #endif  /* INCLUDE_L3 */
   4455 }
   4456        
   4457 /* Get stat counter ID for FCOE Route */       
   4458 int 
   4459 bcm_td2_fcoe_route_stat_id_get (int                   unit,
   4460                                 bcm_fcoe_route_t      *route,
   4461                                 bcm_fcoe_route_stat_t stat, 
   4462                                 uint32                *stat_counter_id)
   4463 {
   4464 #if defined(INCLUDE_L3)
   4465     bcm_stat_flex_direction_t  direction = bcmStatFlexDirectionIngress;
   4466     uint32                     num_of_tables = 0;
   4467     bcm_stat_flex_table_info_t table_info[BCM_STAT_FLEX_COUNTER_MAX_DIRECTION];
   4468     uint32                     index = 0;
   4469     uint32                     num_stat_counter_ids = 0;
   4470 
   4471     if ((stat != bcmFcoeRouteInPackets) && (stat != bcmFcoeRouteInBytes)) {
   4472         return BCM_E_PARAM;
   4473     }
   4474 
   4475     /*  Get Tables, for which flex counter are attached  */
   4476     BCM_IF_ERROR_RETURN(
   4477         _bcm_td2_fcoe_route_stat_get_table_info(unit, route, &num_of_tables, 
   4478                                           &table_info[0]));
   4479 
   4480     /* Retrieve stat counter id */
   4481     for (index = 0; index < num_of_tables ; index++) {
   4482          if (table_info[index].direction == direction)
   4483              return _bcm_esw_stat_flex_get_counter_id(unit, 
   4484                                                       1, 
   4485                                                       &table_info[index],
   4486                                                       &num_stat_counter_ids,
   4487                                                       stat_counter_id);
   4488     }
   4489     return BCM_E_NOT_FOUND;
   4490 #else
   4491     return BCM_E_UNAVAIL;
   4492 #endif  /* INCLUDE_L3 */
   4493 }
   4494 
   4495 #ifdef INCLUDE_L3
   4496 
   4497 /* 
   4498  * Purpose:
   4499  *   Require exactly 1 of the following 3 flags:
   4500  *     BCM_FCOE_INTF_VFT_DO_NOT_MODIFY
   4501  *     BCM_FCOE_INTF_VFT_ADD_REPLACE
   4502  *     BCM_FCOE_INTF_VFT_DELETE
   4503  *
   4504  * Parameters: 
   4505  *   flags      - (IN)  flags given by the application
   4506  *   vft_action - (OUT) the option that was chosen
   4507  *
   4508  * Returns:
   4509  *   BCM_E_XXX
   4510  */
   4511 STATIC int
   4512 _bcm_td2_vft_action_from_flags(uint32 flags, int *vft_action)
   4513 {
   4514     if (flags & BCM_FCOE_INTF_VFT_DO_NOT_MODIFY) {
   4515         CHECK_FLAGS_NOT_SET(flags, BCM_FCOE_INTF_VFT_ADD_REPLACE
   4516                                    | BCM_FCOE_INTF_VFT_DELETE);
   4517         *vft_action = FCOE_VFT_ACTION_DO_NOT_MODIFY;
   4518     } else if (flags & BCM_FCOE_INTF_VFT_ADD_REPLACE) {
   4519         CHECK_FLAGS_NOT_SET(flags, BCM_FCOE_INTF_VFT_DO_NOT_MODIFY
   4520                                    | BCM_FCOE_INTF_VFT_DELETE);
   4521         *vft_action = FCOE_VFT_ACTION_ADD_REPLACE;
   4522     } else if (flags & BCM_FCOE_INTF_VFT_DELETE) {
   4523         CHECK_FLAGS_NOT_SET(flags, BCM_FCOE_INTF_VFT_DO_NOT_MODIFY
   4524                                    | BCM_FCOE_INTF_VFT_ADD_REPLACE);
   4525         *vft_action = FCOE_VFT_ACTION_DELETE;
   4526     } else {
   4527         return BCM_E_PARAM;
   4528     }
   4529 
   4530     return BCM_E_NONE;
   4531 }
   4532 
   4533 STATIC int
   4534 _bcm_td2_fcoe_vsan_id_sel_check(bcm_fcoe_intf_vsan_id_source_t src,
   4535                                 int *fabric_id_sel)
   4536 {
   4537     if (src == bcmFcoeIntfVsanSet) {
   4538         *fabric_id_sel = FCOE_FABRIC_ID_SEL_SET;
   4539     } else if (src == bcmFcoeIntfVsanInternal) {
   4540         *fabric_id_sel = FCOE_FABRIC_ID_SEL_INTERNAL;
   4541     } else if (src == bcmFcoeIntfVsanInnerVlan) {
   4542         *fabric_id_sel = FCOE_FABRIC_ID_SEL_INNER_VLAN;
   4543     } else if (src == bcmFcoeIntfVsanOuterVlan) {
   4544         *fabric_id_sel = FCOE_FABRIC_ID_SEL_OUTER_VLAN;
   4545     } else {
   4546         return BCM_E_PARAM;
   4547     }
   4548 
   4549     return BCM_E_NONE;
   4550 }
   4551 
   4552 STATIC int
   4553 _bcm_td2_fcoe_vsan_pri_sel_check(bcm_fcoe_intf_vsan_pri_source_t src,
   4554                                  int *fabric_pri_sel)
   4555 {
   4556     if (src == bcmFcoeIntfVsanPriSet) {
   4557         *fabric_pri_sel = FCOE_FABRIC_PRI_SEL_SET;
   4558     } else if (src == bcmFcoeIntfVsanPriInternal) {
   4559         *fabric_pri_sel = FCOE_FABRIC_PRI_SEL_INTERNAL;
   4560     } else if (src == bcmFcoeIntfVsanPriRemark) {
   4561         *fabric_pri_sel = FCOE_FABRIC_PRI_SEL_REMARK;
   4562     } else {
   4563         return BCM_E_PARAM;
   4564     }
   4565 
   4566     return BCM_E_NONE;
   4567 }
   4568 
   4569 #endif
   4570 
   4571 /* 
   4572  * _bcm_td2_add_vft_fields_profile
   4573  *    Add data in *cfg to EGR_VFT_FIELDS_PROFILE and store the index used into
   4574  *    vft_fields_idx
   4575  */
   4576 STATIC int
   4577 _bcm_td2_add_vft_fields_profile(int unit, bcm_fcoe_vsan_vft_t *cfg,
   4578                                 uint32 *vft_fields_idx)
   4579 {
   4580     int     rv;
   4581     soc_mem_t mem = EGR_VFT_FIELDS_PROFILEm;
   4582     egr_vft_fields_profile_entry_t entry;
   4583     void    *entries = (void *)&entry;
   4584 
   4585     sal_memset(&entry, 0, sizeof entry);
   4586 
   4587     soc_mem_field32_set(unit, mem, (uint32 *)&entry, FCOE_VFT_R_CTLf, 
   4588                         cfg->r_ctl);
   4589     soc_mem_field32_set(unit, mem, (uint32 *)&entry, FCOE_VFT_VERSIONf, 
   4590                         cfg->version);
   4591     soc_mem_field32_set(unit, mem, (uint32 *)&entry, FCOE_VFT_TYPEf, 
   4592                         cfg->type);
   4593     soc_mem_field32_set(unit, mem, (uint32 *)&entry, FCOE_VFT_HOP_COUNTf, 
   4594                         cfg->hop_count);
   4595 
   4596     soc_mem_field32_set(unit, mem, (uint32 *)&entry, FCOE_VFT_R1f, 0);
   4597     soc_mem_field32_set(unit, mem, (uint32 *)&entry, FCOE_VFT_R2f, 0);
   4598     soc_mem_field32_set(unit, mem, (uint32 *)&entry, FCOE_VFT_Ef, 0);
   4599 
   4600     rv = _bcm_egr_vft_fields_entry_add(unit, &entries, VFT_NUM_ENTRIES, 
   4601                                        vft_fields_idx);
   4602     return rv;
   4603 }
   4604 
   4605 /* 
   4606  * _bcm_td2_inc_vft_profile_refcnt
   4607  *    Increment the reference count for the given vft fields index
   4608  */
   4609 STATIC int
   4610 _bcm_td2_inc_vft_profile_refcnt(int unit, uint32 index)
   4611 {
   4612     _bcm_td2_fcoe_bk_info[unit].profile_use_refcnt[index]++;
   4613     return BCM_E_NONE;
   4614 }
   4615 
   4616 /* 
   4617  * _bcm_td2_dec_vft_profile_refcnt
   4618  *    Decrement the reference count for the given vft fields index.  Delete the
   4619  *    table entry if the counter reaches zero.
   4620  */
   4621 STATIC int
   4622 _bcm_td2_dec_vft_profile_refcnt(int unit, uint32 index)
   4623 {
   4624     _bcm_td2_fcoe_bk_info[unit].profile_use_refcnt[index]--;
   4625 
   4626     if (_bcm_td2_fcoe_bk_info[unit].profile_use_refcnt[index] == 0) {
   4627         return _bcm_egr_vft_fields_entry_del(unit, index);
   4628     }   
   4629 
   4630     return BCM_E_NONE;
   4631 }
   4632 
   4633 #ifdef INCLUDE_L3
   4634 
   4635 /* 
   4636  * _bcm_td2_vft_fields_profile_sanity
   4637  *    Sanity check for the values in a bcm_fcoe_vsan_vft_t structure.  They're 
   4638  *    all uint8s, so only check the 2 values that don't allow all 8 bits to be 
   4639  *    used.
   4640  */
   4641 STATIC int
   4642 _bcm_td2_vft_fields_profile_sanity(bcm_fcoe_vsan_vft_t *cfg)
   4643 {
   4644     if ((cfg->version > 3) || (cfg->type > 15)) {
   4645         return BCM_E_PARAM;
   4646     }
   4647 
   4648     return BCM_E_NONE;
   4649 }
   4650 
   4651 /* 
   4652  * _bcm_td2_set_intf_config
   4653  *    Store values into the EGR_L3_INTF table
   4654  */
   4655 STATIC int
   4656 _bcm_td2_set_intf_config(int unit, bcm_if_t intf, bcm_fcoe_intf_config_t *cfg, 
   4657                          uint32 vft_fields_idx, int vft_action, 
   4658                          int fabric_id_sel, int fabric_pri_sel)
   4659 {
   4660     egr_l3_intf_entry_t intf_entry;
   4661     uint32              *buf = (uint32 *)&intf_entry;
   4662     int                 rv = BCM_E_NONE;
   4663     soc_mem_t           mem = EGR_L3_INTFm;
   4664     int                 old_fields_idx;
   4665     int                 qos_map_hwidx;
   4666 
   4667     if (intf >= soc_mem_index_max(unit, mem)) {
   4668         return BCM_E_PARAM;
   4669     }
   4670 
   4671     if (fabric_pri_sel == FCOE_FABRIC_PRI_SEL_REMARK) {
   4672         BCM_IF_ERROR_RETURN(bcm_td2_qos_get_egr_vsan_hw_idx(unit, cfg->qos_map_id,
   4673                                                              &qos_map_hwidx));
   4674 
   4675     }
   4676 
   4677     sal_memset(buf, 0, sizeof intf_entry);
   4678 
   4679     soc_mem_lock(unit, mem);
   4680     rv = BCM_XGS3_MEM_READ(unit, mem, intf, buf);
   4681     if (BCM_FAILURE(rv)) {
   4682         soc_mem_unlock(unit, mem);
   4683         return rv;
   4684     }
   4685 
   4686     old_fields_idx = soc_mem_field32_get(unit, mem, buf, 
   4687                                         FCOE_VFT_FIELDS_PROFILE_INDEXf);
   4688     if ((old_fields_idx != vft_fields_idx) && (old_fields_idx != 0)) {
   4689         rv = _bcm_td2_dec_vft_profile_refcnt(unit, old_fields_idx);
   4690         if (BCM_FAILURE(rv)) {
   4691             soc_mem_unlock(unit, mem);
   4692             return rv;
   4693         }
   4694     }
   4695 
   4696     soc_mem_field32_set(unit, mem, buf, FCOE_VFT_ACTIONf, vft_action);
   4697     soc_mem_field32_set(unit, mem, buf, FCOE_FABRIC_ID_SELf, fabric_id_sel);
   4698     soc_mem_field32_set(unit, mem, buf, FCOE_FABRIC_PRI_SELf, fabric_pri_sel);
   4699     soc_mem_field32_set(unit, mem, buf, FCOE_VSAN_IDf, cfg->vsan);
   4700     if (fabric_pri_sel == FCOE_FABRIC_PRI_SEL_SET) {
   4701         soc_mem_field32_set(unit, mem, buf, FCOE_VSAN_PRIf, cfg->vsan_pri);
   4702     } else if (fabric_pri_sel == FCOE_FABRIC_PRI_SEL_REMARK) {
   4703         soc_mem_field32_set(unit, mem, buf, FCOE_VSAN_PRI_MAPPING_PROFILEf,
   4704                             qos_map_hwidx);
   4705     }
   4706     soc_mem_field32_set(unit, mem, buf, FCOE_VFT_FIELDS_PROFILE_INDEXf, 
   4707                         vft_fields_idx);
   4708 
   4709     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, intf, buf);
   4710 
   4711     soc_mem_unlock(unit, mem);
   4712 
   4713     return rv;
   4714 }
   4715 
   4716 
   4717 /* Set parameters for FCOE L3 interface */
   4718 int
   4719 bcm_td2_fcoe_intf_config_set(int unit, uint32 flags, bcm_if_t intf, 
   4720                              bcm_fcoe_intf_config_t *cfg)
   4721 {
   4722     int rv             = BCM_E_NONE;
   4723     int vft_action     = 0;
   4724     int fabric_id_sel  = 0;
   4725     int fabric_pri_sel = 0;
   4726     uint32 vft_fields_idx = 0;
   4727 
   4728     /* Translate flags into hardware values and test validity */
   4729     BCM_IF_ERROR_RETURN(_bcm_td2_vft_action_from_flags(cfg->flags,
   4730                                                        &vft_action));
   4731     BCM_IF_ERROR_RETURN(_bcm_td2_fcoe_vsan_pri_sel_check(cfg->vsan_pri_source,
   4732                                                          &fabric_pri_sel));
   4733     BCM_IF_ERROR_RETURN(_bcm_td2_fcoe_vsan_id_sel_check(cfg->vsan_source,
   4734                                                         &fabric_id_sel));
   4735 
   4736     /* Check that the VFT profile is valid, and add it */
   4737     BCM_IF_ERROR_RETURN(_bcm_td2_vft_fields_profile_sanity(&cfg->vft));
   4738     BCM_IF_ERROR_RETURN(_bcm_td2_add_vft_fields_profile(unit, &cfg->vft, 
   4739                                                         &vft_fields_idx));
   4740     BCM_IF_ERROR_RETURN(_bcm_td2_inc_vft_profile_refcnt(unit, vft_fields_idx));
   4741 
   4742     /* Set interface properties */
   4743     rv = _bcm_td2_set_intf_config(unit, intf, cfg, vft_fields_idx, vft_action,
   4744                                   fabric_id_sel, fabric_pri_sel);
   4745     if (BCM_FAILURE(rv)) {
   4746         BCM_IF_ERROR_RETURN(_bcm_td2_dec_vft_profile_refcnt(unit, 
   4747                                                             vft_fields_idx));
   4748         return rv;
   4749     }
   4750 
   4751     return rv;
   4752 }
   4753 
   4754 #endif
   4755 
   4756 /* Read data out of the EGR_VFT_FIELDS_PROFILE table and store it in a 
   4757  * bcm_fcoe_vsan_vft_t structure */
   4758 STATIC int
   4759 _bcm_td2_get_fields_profile(int unit, int vft_fields_idx, 
   4760                             bcm_fcoe_vsan_vft_t *vft)
   4761 {
   4762     soc_mem_t mem = EGR_VFT_FIELDS_PROFILEm;
   4763     egr_vft_fields_profile_entry_t entry;
   4764     void    *entries = (void *)&entry;
   4765 
   4766     sal_memset(&entry, 0, sizeof entry);
   4767     BCM_IF_ERROR_RETURN(_bcm_egr_vft_fields_entry_get(unit, vft_fields_idx, 
   4768                                                       VFT_NUM_ENTRIES, 
   4769                                                       &entries));
   4770 
   4771     vft->r_ctl = soc_mem_field32_get(unit, mem, &entry, FCOE_VFT_R_CTLf);
   4772     vft->version = soc_mem_field32_get(unit, mem, &entry, FCOE_VFT_VERSIONf);
   4773     vft->type = soc_mem_field32_get(unit, mem, &entry, FCOE_VFT_TYPEf);
   4774     vft->hop_count = soc_mem_field32_get(unit, mem, &entry, FCOE_VFT_HOP_COUNTf);
   4775 
   4776     return BCM_E_NONE;
   4777 }
   4778 
   4779 #ifdef INCLUDE_L3
   4780 
   4781 /* Get parameters for FCOE L3 interface */
   4782 int
   4783 bcm_td2_fcoe_intf_config_get(int unit, uint32 flags, bcm_if_t intf, 
   4784                              bcm_fcoe_intf_config_t *cfg)
   4785 {
   4786     egr_l3_intf_entry_t intf_entry;
   4787     uint32              *buf = (uint32 *)&intf_entry;
   4788     int                 rv = BCM_E_NONE;
   4789     soc_mem_t           mem = EGR_L3_INTFm;
   4790     int                 vft_fields_idx = 0;
   4791     int                 qos_map_hwidx = 0;
   4792 
   4793     BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_READ(unit, mem, intf, buf));
   4794 
   4795     vft_fields_idx = soc_mem_field32_get(unit, mem, buf, 
   4796                                         FCOE_VFT_FIELDS_PROFILE_INDEXf);
   4797 
   4798     switch (soc_mem_field32_get(unit, mem, buf, FCOE_VFT_ACTIONf)) {
   4799         case FCOE_VFT_ACTION_DO_NOT_MODIFY: 
   4800             cfg->flags |= BCM_FCOE_INTF_VFT_DO_NOT_MODIFY;
   4801             break;
   4802 
   4803         case FCOE_VFT_ACTION_ADD_REPLACE:
   4804             cfg->flags |= BCM_FCOE_INTF_VFT_ADD_REPLACE;
   4805             break;
   4806 
   4807         case FCOE_VFT_ACTION_DELETE:
   4808             cfg->flags |= BCM_FCOE_INTF_VFT_DELETE;
   4809             break;
   4810 
   4811         default:
   4812             return BCM_E_FAIL;
   4813     }
   4814 
   4815     switch (soc_mem_field32_get(unit, mem, buf, FCOE_FABRIC_ID_SELf)) {
   4816         case FCOE_FABRIC_ID_SEL_SET:
   4817             cfg->vsan_source = bcmFcoeIntfVsanSet;
   4818             break;
   4819 
   4820         case FCOE_FABRIC_ID_SEL_INTERNAL:
   4821             cfg->vsan_source = bcmFcoeIntfVsanInternal;
   4822             break;
   4823 
   4824         case FCOE_FABRIC_ID_SEL_INNER_VLAN:
   4825             cfg->vsan_source = bcmFcoeIntfVsanInnerVlan;
   4826             break;
   4827 
   4828         case FCOE_FABRIC_ID_SEL_OUTER_VLAN:
   4829             cfg->vsan_source = bcmFcoeIntfVsanOuterVlan;
   4830             break;
   4831 
   4832         default:
   4833             return BCM_E_FAIL;
   4834     }
   4835 
   4836     switch (soc_mem_field32_get(unit, mem, buf, FCOE_FABRIC_PRI_SELf)) {
   4837         case FCOE_FABRIC_PRI_SEL_SET:
   4838             cfg->vsan_pri_source = bcmFcoeIntfVsanPriSet;
   4839             break;
   4840 
   4841         case FCOE_FABRIC_PRI_SEL_INTERNAL:
   4842             cfg->vsan_pri_source = bcmFcoeIntfVsanPriInternal;
   4843             break;
   4844 
   4845         case FCOE_FABRIC_PRI_SEL_REMARK:
   4846             cfg->vsan_pri_source = bcmFcoeIntfVsanPriRemark;
   4847             break;
   4848 
   4849         default:
   4850             return BCM_E_FAIL;
   4851     }
   4852 
   4853     cfg->vsan = soc_mem_field32_get(unit, mem, buf, FCOE_VSAN_IDf);
   4854     vft_fields_idx = soc_mem_field32_get(unit, mem, buf, 
   4855                                          FCOE_VFT_FIELDS_PROFILE_INDEXf);
   4856     if (cfg->vsan_pri_source == bcmFcoeIntfVsanPriSet) {
   4857         cfg->vsan_pri = soc_mem_field32_get(unit, mem, buf, FCOE_VSAN_PRIf);
   4858     } else if (cfg->vsan_pri_source == bcmFcoeIntfVsanPriRemark) {
   4859         qos_map_hwidx = soc_mem_field32_get(unit, mem, buf,
   4860                                             FCOE_VSAN_PRI_MAPPING_PROFILEf);
   4861         BCM_IF_ERROR_RETURN(bcm_td2_vsan_profile_to_qos_id(unit, qos_map_hwidx,
   4862                                                            &cfg->qos_map_id));
   4863     }
   4864 
   4865     BCM_IF_ERROR_RETURN(_bcm_td2_get_fields_profile(unit, vft_fields_idx, 
   4866                                                     &cfg->vft));
   4867 
   4868     return rv;
   4869 }
   4870 
   4871 #endif /* INCLUDE_L3 */
   4872 
   4873 
   4874 /* construct a key for VLAN_XLATE table search */
   4875 STATIC int
   4876 _bcm_td2_fcoe_ing_vlan_translate_entry_assemble(
   4877                                 int                                  unit, 
   4878                                 void                                 *vent,
   4879                                 bcm_fcoe_vsan_translate_key_config_t *key)
   4880 {
   4881     if (soc_feature(unit, soc_feature_fcoe)) {
   4882         bcm_module_t    mod_out;
   4883         bcm_port_t      port_out;
   4884         bcm_trunk_t     trunk_out;
   4885         int             tmp_id;
   4886         int             key_type_value;
   4887         int             key_type;
   4888         int             use_glp = 1;
   4889         int             mem = VLAN_XLATEm;
   4890 
   4891         if (SOC_MEM_IS_VALID(unit, VLAN_XLATE_1_DOUBLEm)) {
   4892             mem = VLAN_XLATE_1_DOUBLEm;
   4893         }
   4894 
   4895         switch (key->key_type) {
   4896             case bcmFcoeVsanTranslateKeyDouble:
   4897                 use_glp = 0;
   4898                 key_type = VLXLT_HASH_KEY_TYPE_IVID_OVID;
   4899                 soc_mem_field32_set(unit, mem, vent, XLATE__OVIDf,
   4900                                             key->outer_vlan);
   4901                 soc_mem_field32_set(unit, mem, vent, XLATE__IVIDf,
   4902                                             key->inner_vlan);
   4903                 break;
   4904 
   4905             case bcmFcoeVsanTranslateKeyOuter:
   4906                 use_glp = 0;
   4907                 key_type = VLXLT_HASH_KEY_TYPE_OVID;
   4908                 soc_mem_field32_set(unit, mem, vent, XLATE__OVIDf,
   4909                                             key->outer_vlan);
   4910                 break;
   4911 
   4912             case bcmFcoeVsanTranslateKeyInner:
   4913                 use_glp = 0;
   4914                 key_type = VLXLT_HASH_KEY_TYPE_IVID;
   4915                 soc_mem_field32_set(unit, mem, vent, XLATE__IVIDf,
   4916                                             key->inner_vlan);
   4917                 break;
   4918 
   4919             case bcmFcoeVsanTranslateKeyOuterTag:
   4920                 use_glp = 0;
   4921                 key_type = VLXLT_HASH_KEY_TYPE_OTAG;
   4922 
   4923                 /* vlan id should also have PRI/CFI bits */
   4924                 soc_mem_field32_set(unit, mem, vent, XLATE__OTAGf,
   4925                                             key->outer_vlan);
   4926                 break;
   4927 
   4928             case bcmFcoeVsanTranslateKeyInnerTag:
   4929                 use_glp = 0;
   4930                 key_type = VLXLT_HASH_KEY_TYPE_ITAG;
   4931                 /* vlan id should also have PRI/CFI bits */
   4932                 soc_mem_field32_set(unit, mem, vent, XLATE__ITAGf,
   4933                                             key->inner_vlan);
   4934                 break;
   4935 
   4936             case bcmFcoeVsanTranslateKeyOuterPri:
   4937                 use_glp = 0;
   4938                 key_type = VLXLT_HASH_KEY_TYPE_PRI_CFI;
   4939 
   4940                 /* vlan id should have PRI/CFI bits */
   4941                 soc_mem_field32_set(unit, mem, vent, XLATE__OTAGf,
   4942                                             key->outer_vlan);
   4943                 break;
   4944 
   4945             case bcmFcoeVsanTranslateKeyPortDouble:
   4946                 key_type = VLXLT_HASH_KEY_TYPE_IVID_OVID;
   4947                 soc_mem_field32_set(unit, mem, vent, XLATE__OVIDf,
   4948                                             key->outer_vlan);
   4949                 soc_mem_field32_set(unit, mem, vent, XLATE__IVIDf,
   4950                                             key->inner_vlan);
   4951                 break;
   4952 
   4953             case bcmFcoeVsanTranslateKeyPortOuter:
   4954                 key_type = VLXLT_HASH_KEY_TYPE_OVID;
   4955                 soc_mem_field32_set(unit, mem, vent, XLATE__OVIDf,
   4956                                             key->outer_vlan);
   4957                 break;
   4958 
   4959             case bcmFcoeVsanTranslateKeyPortInner:
   4960                 key_type = VLXLT_HASH_KEY_TYPE_IVID;
   4961                 soc_mem_field32_set(unit, mem, vent, XLATE__IVIDf,
   4962                                             key->inner_vlan);
   4963                 break;
   4964 
   4965             case bcmFcoeVsanTranslateKeyPortOuterTag:
   4966                 key_type = VLXLT_HASH_KEY_TYPE_OTAG;
   4967                 /* vlan id should also have PRI/CFI bits */
   4968                 soc_mem_field32_set(unit, mem, vent, XLATE__OTAGf,
   4969                                             key->outer_vlan);
   4970                 break;
   4971 
   4972             case bcmFcoeVsanTranslateKeyPortInnerTag:
   4973                 key_type = VLXLT_HASH_KEY_TYPE_ITAG;
   4974                 /* vlan id should also have PRI/CFI bits */
   4975                 soc_mem_field32_set(unit, mem, vent, XLATE__ITAGf,
   4976                                             key->inner_vlan);
   4977                 break;
   4978 
   4979             case bcmFcoeVsanTranslateKeyPortOuterPri:
   4980                 key_type = VLXLT_HASH_KEY_TYPE_PRI_CFI;
   4981                 /* vlan id should have PRI/CFI bits */
   4982                 soc_mem_field32_set(unit, mem, vent, XLATE__OTAGf,
   4983                                             key->outer_vlan);
   4984                 break;
   4985 
   4986             case bcmFcoeVsanTranslateKeyDoubleVsan:
   4987                 use_glp = 0;
   4988                 key_type = VLXLT_HASH_KEY_TYPE_IVID_OVID_VSAN;
   4989                 soc_mem_field32_set(unit, mem, vent, XLATE__OVIDf,
   4990                                             key->outer_vlan);
   4991                 soc_mem_field32_set(unit, mem, vent, XLATE__IVIDf,
   4992                                             key->inner_vlan);
   4993                 soc_mem_field32_set(unit, mem, vent, XLATE__VSAN_IDf,
   4994                                             key->vsan);
   4995                 break;
   4996 
   4997             case bcmFcoeVsanTranslateKeyInnerVsan:
   4998                 use_glp = 0;
   4999                 key_type = VLXLT_HASH_KEY_TYPE_IVID_VSAN;
   5000                 soc_mem_field32_set(unit, mem, vent, XLATE__IVIDf,
   5001                                             key->inner_vlan);
   5002                 soc_mem_field32_set(unit, mem, vent, XLATE__VSAN_IDf,
   5003                                             key->vsan);
   5004                 break;
   5005 
   5006             case bcmFcoeVsanTranslateKeyOuterVsan:
   5007                 use_glp = 0;
   5008                 key_type = VLXLT_HASH_KEY_TYPE_OVID_VSAN;
   5009                 soc_mem_field32_set(unit, mem, vent, XLATE__OVIDf,
   5010                                             key->outer_vlan);
   5011                 soc_mem_field32_set(unit, mem, vent, XLATE__VSAN_IDf,
   5012                                             key->vsan);
   5013                 break;
   5014 
   5015             case bcmFcoeVsanTranslateKeyPortDoubleVsan:
   5016                 key_type = VLXLT_HASH_KEY_TYPE_IVID_OVID_VSAN;
   5017                 soc_mem_field32_set(unit, mem, vent, XLATE__OVIDf,
   5018                                             key->outer_vlan);
   5019                 soc_mem_field32_set(unit, mem, vent, XLATE__IVIDf,
   5020                                             key->inner_vlan);
   5021                 soc_mem_field32_set(unit, mem, vent, XLATE__VSAN_IDf,
   5022                                             key->vsan);
   5023                 break;
   5024 
   5025             case bcmFcoeVsanTranslateKeyPortInnerVsan:
   5026                 key_type = VLXLT_HASH_KEY_TYPE_IVID_VSAN;
   5027                 soc_mem_field32_set(unit, mem, vent, XLATE__IVIDf,
   5028                                             key->inner_vlan);
   5029                 soc_mem_field32_set(unit, mem, vent, XLATE__VSAN_IDf,
   5030                                             key->vsan);
   5031                 break;
   5032 
   5033             case bcmFcoeVsanTranslateKeyPortOuterVsan:
   5034                 key_type = VLXLT_HASH_KEY_TYPE_OVID_VSAN;
   5035                 soc_mem_field32_set(unit, mem, vent, XLATE__OVIDf,
   5036                                             key->outer_vlan);
   5037                 soc_mem_field32_set(unit, mem, vent, XLATE__VSAN_IDf,
   5038                                             key->vsan);
   5039                 break;
   5040 
   5041             default:
   5042                 return BCM_E_PARAM;
   5043         }
   5044 
   5045         BCM_IF_ERROR_RETURN(
   5046             _bcm_esw_vlan_xlate_key_type_value_get(unit, key_type,
   5047                                                    &key_type_value));
   5048         soc_mem_field32_set(unit, mem, vent, KEY_TYPEf, key_type_value);
   5049 
   5050 
   5051         if (use_glp) {
   5052             /* SGLP - Use SGLP {trunk, ModId(7,0), Port(6,0)} as the Source
   5053                Field */
   5054             if (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_TYPEf)) {
   5055                 soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 1);
   5056             }
   5057 
   5058             BCM_IF_ERROR_RETURN(
   5059                 _bcm_esw_gport_resolve(unit, key->port, &mod_out, &port_out,
   5060                                        &trunk_out, &tmp_id));
   5061             if (BCM_GPORT_IS_TRUNK(key->port)) {
   5062                 soc_mem_field32_set(unit, mem, vent, XLATE__Tf, 1);
   5063                 soc_mem_field32_set(unit, mem, vent, XLATE__TGIDf,
   5064                                             trunk_out);
   5065             } else {
   5066                 soc_mem_field32_set(unit, mem, vent, XLATE__MODULE_IDf,
   5067                                             mod_out);
   5068                 soc_mem_field32_set(unit, mem, vent, XLATE__PORT_NUMf,
   5069                                             port_out);
   5070             }
   5071         } else {
   5072             if (SOC_MEM_FIELD_VALID(unit, mem, SOURCE_TYPEf)) {
   5073                 soc_mem_field32_set(unit, mem, vent, SOURCE_TYPEf, 0);
   5074             }
   5075             /* incoming port not used in lookup key, set field to all 1's */
   5076             soc_mem_field32_set(unit, mem, vent, GLPf,
   5077                                         SOC_VLAN_XLATE_GLP_WILDCARD(unit));
   5078         }
   5079 
   5080         return BCM_E_NONE;
   5081     }
   5082     return BCM_E_UNAVAIL;
   5083 }
   5084 
   5085 uint32
   5086 _bcm_td2_fcoe_ing_vft_pri_action_encode(bcm_fcoe_vsan_action_t action)
   5087 {
   5088     switch (action) {
   5089         case bcmFcoeVsanActionNone:
   5090             return _BCM_TD2_ING_VFT_PRI_ACTION_NONE;
   5091         case bcmFcoeVsanActionInnerVlan:
   5092             return _BCM_TD2_ING_VFT_PRI_ACTION_USE_INNER_PRI;
   5093         case bcmFcoeVsanActionOuterVlan:
   5094             return _BCM_TD2_ING_VFT_PRI_ACTION_USE_OUTER_PRI;
   5095         case bcmFcoeVsanActionReplace:
   5096             return _BCM_TD2_ING_VFT_PRI_ACTION_REPLACE;
   5097         case bcmFcoeVsanActionDelete:
   5098         case bcmFcoeVsanActionInternal:
   5099         default:
   5100             return _BCM_TD2_ING_VFT_PRI_ACTION_NONE;
   5101     }
   5102 }
   5103 
   5104 /*
   5105  * add a new entry to vlan action profile table -- ingress
   5106  */
   5107 STATIC int
   5108 _bcm_td2_ing_vlan_action_profile_entry_add(
   5109                                        int                        unit,
   5110                                        bcm_fcoe_vsan_action_set_t *action,
   5111                                        uint32                     *index)
   5112 {   
   5113 
   5114     ing_vlan_tag_action_profile_entry_t ing_profile; 
   5115     ing_vlan_tag_action_profile_2_entry_t ing_profile_2; 
   5116     void *entry;
   5117     soc_mem_t mem;
   5118     int   ent_sz;
   5119 
   5120     if (SOC_MEM_IS_VALID(unit, ING_VLAN_TAG_ACTION_PROFILE_2m)) {
   5121         mem = ING_VLAN_TAG_ACTION_PROFILE_2m;
   5122         ent_sz = sizeof(ing_vlan_tag_action_profile_2_entry_t);
   5123         entry = &ing_profile_2;
   5124     } else {
   5125         mem = ING_VLAN_TAG_ACTION_PROFILEm;
   5126         ent_sz = sizeof(ing_vlan_tag_action_profile_entry_t);
   5127         entry = &ing_profile;
   5128     }
   5129  
   5130 
   5131     /* Note : on ingress, no VFT Tag manipulation will happen. Only Pri
   5132      *        manipulation is allowed.
   5133      *        So, mark all Tag actions to None (it is done by above sal_memset)
   5134      */
   5135 
   5136     sal_memset(entry, 0, ent_sz);
   5137     /* 3 new PRI actions */
   5138     soc_mem_field32_set(unit, mem, entry,
   5139                         DT_VT_VPRI_ACTIONf,
   5140                         _bcm_td2_fcoe_ing_vft_pri_action_encode(
   5141                                                       action->dt_vsan_pri));
   5142     soc_mem_field32_set(unit, mem, entry,
   5143                         SOT_VT_VPRI_ACTIONf,
   5144                         _bcm_td2_fcoe_ing_vft_pri_action_encode(
   5145                                                       action->ot_vsan_pri));
   5146     soc_mem_field32_set(unit, mem, entry,
   5147                         SIT_VT_VPRI_ACTIONf,
   5148                         _bcm_td2_fcoe_ing_vft_pri_action_encode(
   5149                                                       action->it_vsan_pri));
   5150 
   5151     soc_mem_field32_set(
   5152         unit, mem, entry, DT_OTAG_ACTIONf,
   5153         _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.dt_outer));
   5154     soc_mem_field32_set(
   5155         unit, mem, entry, DT_POTAG_ACTIONf,
   5156         _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.dt_outer_prio));
   5157     soc_mem_field32_set(
   5158         unit, mem, entry, DT_ITAG_ACTIONf,
   5159         _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.dt_inner));
   5160     soc_mem_field32_set(
   5161         unit, mem, entry, DT_PITAG_ACTIONf,
   5162         _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.dt_inner_prio));
   5163     soc_mem_field32_set(
   5164         unit, mem, entry, SOT_OTAG_ACTIONf,
   5165         _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.ot_outer));
   5166     soc_mem_field32_set(
   5167         unit, mem, entry, SOT_POTAG_ACTIONf,
   5168         _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.ot_outer_prio));
   5169     soc_mem_field32_set(
   5170         unit, mem, entry, SOT_ITAG_ACTIONf,
   5171         _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.ot_inner));
   5172     soc_mem_field32_set(
   5173         unit, mem, entry, SIT_OTAG_ACTIONf,
   5174         _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.it_outer));
   5175     soc_mem_field32_set(
   5176         unit, mem, entry, SIT_ITAG_ACTIONf,
   5177         _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.it_inner));
   5178     soc_mem_field32_set(
   5179         unit, mem, entry, SIT_PITAG_ACTIONf,
   5180         _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.it_inner_prio));
   5181     soc_mem_field32_set(
   5182         unit, mem, entry, UT_OTAG_ACTIONf,
   5183         _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.ut_outer));
   5184     soc_mem_field32_set(
   5185         unit, mem, entry, UT_ITAG_ACTIONf,
   5186         _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.ut_inner));
   5187 
   5188     if (soc_feature(unit, soc_feature_vlan_pri_cfi_action)) {
   5189         soc_mem_field32_set(
   5190             unit, mem, entry, DT_OPRI_ACTIONf,
   5191             _BCM_TRX_PRI_CFI_ACTION_ENCODE(
   5192             action->vlan_action.dt_outer_pkt_prio));
   5193         soc_mem_field32_set(
   5194             unit, mem, entry, DT_OCFI_ACTIONf,
   5195             _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.dt_outer_cfi));
   5196         soc_mem_field32_set(
   5197             unit, mem, entry, DT_IPRI_ACTIONf,
   5198             _BCM_TRX_PRI_CFI_ACTION_ENCODE(
   5199             action->vlan_action.dt_inner_pkt_prio));
   5200         soc_mem_field32_set(
   5201             unit, mem, entry, DT_ICFI_ACTIONf,
   5202             _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.dt_inner_cfi));
   5203         soc_mem_field32_set(
   5204             unit, mem, entry, SOT_OPRI_ACTIONf,
   5205             _BCM_TRX_PRI_CFI_ACTION_ENCODE(
   5206             action->vlan_action.ot_outer_pkt_prio));
   5207         soc_mem_field32_set(
   5208             unit, mem, entry, SOT_OCFI_ACTIONf,
   5209             _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.ot_outer_cfi));
   5210         soc_mem_field32_set(
   5211             unit, mem, entry, SOT_IPRI_ACTIONf,
   5212             _BCM_TRX_PRI_CFI_ACTION_ENCODE(
   5213             action->vlan_action.ot_inner_pkt_prio));
   5214         soc_mem_field32_set(
   5215             unit, mem, entry, SOT_ICFI_ACTIONf,
   5216             _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.ot_inner_cfi));
   5217         soc_mem_field32_set(
   5218             unit, mem, entry, SIT_OPRI_ACTIONf,
   5219             _BCM_TRX_PRI_CFI_ACTION_ENCODE(
   5220             action->vlan_action.it_outer_pkt_prio));
   5221         soc_mem_field32_set(
   5222             unit, mem, entry, SIT_OCFI_ACTIONf,
   5223             _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.it_outer_cfi));
   5224         soc_mem_field32_set(
   5225             unit, mem, entry, SIT_IPRI_ACTIONf,
   5226             _BCM_TRX_PRI_CFI_ACTION_ENCODE(
   5227             action->vlan_action.it_inner_pkt_prio));
   5228         soc_mem_field32_set(
   5229             unit, mem, entry, SIT_ICFI_ACTIONf,
   5230             _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.it_inner_cfi));
   5231         soc_mem_field32_set(
   5232             unit, mem, entry, UT_OPRI_ACTIONf,
   5233             _BCM_TRX_PRI_CFI_ACTION_ENCODE(
   5234             action->vlan_action.ut_outer_pkt_prio));
   5235         soc_mem_field32_set(
   5236             unit, mem, entry, UT_OCFI_ACTIONf,
   5237             _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.ut_outer_cfi));
   5238         soc_mem_field32_set(
   5239             unit, mem, entry, UT_IPRI_ACTIONf,
   5240             _BCM_TRX_PRI_CFI_ACTION_ENCODE(
   5241             action->vlan_action.ut_inner_pkt_prio));
   5242         soc_mem_field32_set(
   5243             unit, mem, entry, UT_ICFI_ACTIONf,
   5244             _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.ut_inner_cfi));
   5245     }
   5246 
   5247     return _bcm_trx_ing_vlan_action_profile_entry_no_mod_add(unit, entry,
   5248                                                              index);
   5249 }
   5250 
   5251 STATIC int 
   5252 _bcm_td2_fcoe_egr_vlan_translate_entry_assemble(
   5253                                 int                                  unit,
   5254                                 int                                  port_class,
   5255                                 void                                 *vent,
   5256                                 bcm_fcoe_vsan_translate_key_config_t *key)
   5257 {
   5258     int dvp_id = BCM_GPORT_INVALID;
   5259     soc_mem_t    mem = EGR_VLAN_XLATEm;
   5260     soc_field_t  ef = ENTRY_TYPEf;
   5261 
   5262     if (SOC_MEM_IS_VALID(unit, EGR_VLAN_XLATE_1_DOUBLEm)) {
   5263         mem = EGR_VLAN_XLATE_1_DOUBLEm;
   5264         sal_memset(vent, 0, sizeof(egr_vlan_xlate_1_double_entry_t));
   5265         ef = DATA_TYPEf;
   5266     } else {
   5267         sal_memset(vent, 0, sizeof(egr_vlan_xlate_entry_t));
   5268     }
   5269 
   5270     VLAN_CHK_ID(unit, key->outer_vlan);
   5271     VLAN_CHK_ID(unit, key->inner_vlan);
   5272 
   5273      if (BCM_GPORT_IS_SUBPORT_PORT(port_class)) {
   5274         if (soc_feature(unit, soc_feature_subport)) {
   5275             dvp_id = BCM_GPORT_SUBPORT_PORT_GET(port_class);
   5276         } else {
   5277             return BCM_E_PORT;
   5278         }
   5279     } else if (BCM_GPORT_IS_MIM_PORT(port_class)) {
   5280         if (soc_feature(unit, soc_feature_mim)) {
   5281             dvp_id = BCM_GPORT_MIM_PORT_ID_GET(port_class);
   5282         } else {
   5283             return BCM_E_PORT;
   5284         }
   5285         
   5286     } else if (BCM_GPORT_IS_WLAN_PORT(port_class)) {
   5287         if (soc_feature(unit, soc_feature_wlan)) {
   5288             dvp_id = BCM_GPORT_WLAN_PORT_ID_GET(port_class);
   5289         } else {
   5290             return BCM_E_PORT;
   5291         }
   5292     } else if (BCM_GPORT_IS_VLAN_PORT(port_class)) {
   5293         if (soc_feature(unit, soc_feature_vlan_vp)) {
   5294             dvp_id = BCM_GPORT_VLAN_PORT_ID_GET(port_class);
   5295         } else {
   5296             return BCM_E_PORT;
   5297         }
   5298     } else if (BCM_GPORT_IS_MPLS_PORT(port_class)) {
   5299         if (soc_feature(unit, soc_feature_mpls)) {
   5300             dvp_id = BCM_GPORT_MPLS_PORT_ID_GET(port_class);
   5301         } else {
   5302             return BCM_E_PORT;
   5303         }
   5304     }
   5305 
   5306     soc_mem_field32_set(unit, mem, vent, OVIDf, key->outer_vlan);
   5307     soc_mem_field32_set(unit, mem, vent, IVIDf, key->inner_vlan);
   5308     soc_mem_field32_set(unit, mem, vent, VSAN_IDf, key->vsan);
   5309 
   5310 
   5311     if (BCM_GPORT_INVALID != dvp_id) {
   5312         soc_mem_field32_set(unit, mem, vent, ef, 
   5313                                     TD2_EVLXLT_HASH_KEY_TYPE_FCOE_XLATE_DVP);
   5314         soc_mem_field32_set(unit, mem, vent, DVPf, dvp_id);
   5315     } else  {
   5316         soc_mem_field32_set(unit, mem, vent, PORT_GROUP_IDf, port_class);
   5317         soc_mem_field32_set(unit, mem, vent, ef, 
   5318                                         TD2_EVLXLT_HASH_KEY_TYPE_FCOE_XLATE);
   5319     }
   5320 
   5321     return BCM_E_NONE;
   5322 }
   5323 
   5324 uint32
   5325 _bcm_td2_fcoe_egr_vft_pri_action_encode(bcm_fcoe_vsan_action_t action)
   5326 {
   5327     switch (action) {
   5328         case bcmFcoeVsanActionNone:
   5329             return _BCM_TD2_EGR_VFT_PRI_ACTION_NONE;
   5330         case bcmFcoeVsanActionInnerVlan:
   5331             return _BCM_TD2_EGR_VFT_PRI_ACTION_USE_INTERNAL_IPRI;
   5332         case bcmFcoeVsanActionOuterVlan:
   5333             return _BCM_TD2_EGR_VFT_PRI_ACTION_USE_INTERNAL_OPRI;
   5334         case bcmFcoeVsanActionReplace:
   5335             return _BCM_TD2_EGR_VFT_PRI_ACTION_REPLACE;
   5336         case bcmFcoeVsanActionDelete:
   5337         case bcmFcoeVsanActionInternal:
   5338         default:
   5339             return _BCM_TD2_EGR_VFT_PRI_ACTION_NONE;
   5340     }
   5341 }
   5342 
   5343 uint32
   5344 _bcm_td2_fcoe_egr_vft_tag_action_encode(bcm_fcoe_vsan_action_t action)
   5345 {
   5346     switch (action) {
   5347         case bcmFcoeVsanActionNone:
   5348             return _BCM_TD2_EGR_VFT_TAG_ACTION_NONE;
   5349         case bcmFcoeVsanActionInnerVlan:
   5350             return _BCM_TD2_EGR_VFT_TAG_ACTION_USE_INTERNAL_IVID;
   5351         case bcmFcoeVsanActionOuterVlan:
   5352             return _BCM_TD2_EGR_VFT_TAG_ACTION_USE_INTERNAL_OVID;
   5353         case bcmFcoeVsanActionDelete:
   5354             return _BCM_TD2_EGR_VFT_TAG_ACTION_DELETE;
   5355         case bcmFcoeVsanActionInternal:
   5356             return _BCM_TD2_EGR_VFT_TAG_ACTION_USE_INTERNAL_VSAN;
   5357         case bcmFcoeVsanActionReplace:
   5358             return _BCM_TD2_EGR_VFT_TAG_ACTION_REPLACE;
   5359         default:
   5360             return _BCM_TD2_EGR_VFT_TAG_ACTION_NONE;
   5361     }
   5362 }
   5363 
   5364 /*
   5365  * add a new entry to egress vlan action profile table
   5366  */
   5367 int
   5368 _bcm_td2_fcoe_egr_vlan_action_profile_entry_add(
   5369                                             int unit,
   5370                                             bcm_fcoe_vsan_action_set_t *action,
   5371                                             uint32 *index)
   5372 {   
   5373     egr_vlan_tag_action_profile_entry_t entry;
   5374 
   5375     sal_memset(&entry, 0, sizeof(egr_vlan_tag_action_profile_entry_t));
   5376 
   5377     /* Note : 
   5378      *        Above sal_memset() will set all tag/pri/cfi actions to
   5379      *        none. We only need to set new FCOE actions.
   5380      */
   5381     soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry,
   5382                         DT_VT_VPRI_ACTIONf,   
   5383                         _bcm_td2_fcoe_egr_vft_pri_action_encode(
   5384                                                          action->dt_vsan_pri));
   5385     soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry,
   5386                         SOT_VT_VPRI_ACTIONf,   
   5387                         _bcm_td2_fcoe_egr_vft_pri_action_encode(
   5388                                                          action->ot_vsan_pri));
   5389     soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry,
   5390                         SIT_VT_VPRI_ACTIONf,   
   5391                         _bcm_td2_fcoe_egr_vft_pri_action_encode(
   5392                                                          action->it_vsan_pri));
   5393     soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry,
   5394                         UT_VT_VPRI_ACTIONf,   
   5395                         _bcm_td2_fcoe_egr_vft_pri_action_encode(
   5396                                                          action->ut_vsan_pri));
   5397     soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry,
   5398                         DT_VT_VTAG_ACTIONf,   
   5399                         _bcm_td2_fcoe_egr_vft_pri_action_encode(
   5400                                                          action->dt_vsan));
   5401     soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry,
   5402                         SOT_VT_VTAG_ACTIONf,   
   5403                         _bcm_td2_fcoe_egr_vft_pri_action_encode(
   5404                                                          action->ot_vsan));
   5405     soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry,
   5406                         SIT_VT_VTAG_ACTIONf,   
   5407                         _bcm_td2_fcoe_egr_vft_pri_action_encode(
   5408                                                          action->it_vsan));
   5409     soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry,
   5410                         UT_VT_VTAG_ACTIONf,   
   5411                         _bcm_td2_fcoe_egr_vft_pri_action_encode(
   5412                                                          action->ut_vsan));
   5413 
   5414     /* actions for no VFT header */
   5415     if (action->flags & BCM_FCOE_VSAN_ACTION_VFT_NONE) {
   5416         soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry,
   5417                             DT_NOVT_VPRI_ACTIONf,   
   5418                             _bcm_td2_fcoe_egr_vft_pri_action_encode(
   5419                                                          action->dt_vsan_pri));
   5420         soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry,
   5421                             SOT_NOVT_VPRI_ACTIONf,   
   5422                             _bcm_td2_fcoe_egr_vft_pri_action_encode(
   5423                                                          action->ot_vsan_pri));
   5424         soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry,
   5425                             SIT_NOVT_VPRI_ACTIONf,   
   5426                             _bcm_td2_fcoe_egr_vft_pri_action_encode(
   5427                                                          action->it_vsan_pri));
   5428         soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry,
   5429                             UT_NOVT_VPRI_ACTIONf,   
   5430                             _bcm_td2_fcoe_egr_vft_pri_action_encode(
   5431                                                          action->ut_vsan_pri));
   5432         soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry,
   5433                             DT_NOVT_VTAG_ACTIONf,   
   5434                             _bcm_td2_fcoe_egr_vft_pri_action_encode(
   5435                                                          action->dt_vsan));
   5436         soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry,
   5437                             SOT_NOVT_VTAG_ACTIONf,   
   5438                             _bcm_td2_fcoe_egr_vft_pri_action_encode(
   5439                                                          action->ot_vsan));
   5440         soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry,
   5441                             SIT_NOVT_VTAG_ACTIONf,   
   5442                             _bcm_td2_fcoe_egr_vft_pri_action_encode(
   5443                                                          action->it_vsan));
   5444         soc_mem_field32_set(unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry,
   5445                             UT_NOVT_VTAG_ACTIONf,   
   5446                             _bcm_td2_fcoe_egr_vft_pri_action_encode(
   5447                                                          action->ut_vsan));
   5448     }
   5449 
   5450     soc_mem_field32_set(
   5451         unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, DT_OTAG_ACTIONf,
   5452         _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.dt_outer));
   5453     soc_mem_field32_set(
   5454         unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, DT_POTAG_ACTIONf,
   5455         _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.dt_outer_prio));
   5456     soc_mem_field32_set(
   5457         unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, DT_ITAG_ACTIONf,
   5458         _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.dt_inner));
   5459     soc_mem_field32_set(
   5460         unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, DT_PITAG_ACTIONf,
   5461         _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.dt_inner_prio));
   5462     soc_mem_field32_set(
   5463         unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SOT_OTAG_ACTIONf,
   5464         _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.ot_outer));
   5465     soc_mem_field32_set(
   5466         unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SOT_POTAG_ACTIONf,
   5467         _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.ot_outer_prio));
   5468     soc_mem_field32_set(
   5469         unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SOT_ITAG_ACTIONf,
   5470         _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.ot_inner));
   5471     soc_mem_field32_set(
   5472         unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SIT_OTAG_ACTIONf,
   5473         _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.it_outer));
   5474     soc_mem_field32_set(
   5475         unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SIT_ITAG_ACTIONf,
   5476         _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.it_inner));
   5477     soc_mem_field32_set(
   5478         unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SIT_PITAG_ACTIONf,
   5479         _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.it_inner_prio));
   5480     soc_mem_field32_set(
   5481         unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, UT_OTAG_ACTIONf,
   5482         _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.ut_outer));
   5483     soc_mem_field32_set(
   5484         unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, UT_ITAG_ACTIONf,
   5485         _BCM_TRX_TAG_ACTION_ENCODE(action->vlan_action.ut_inner));
   5486 
   5487     if (soc_feature(unit, soc_feature_vlan_pri_cfi_action)) {
   5488         soc_mem_field32_set(
   5489             unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, DT_OPRI_ACTIONf,
   5490             _BCM_TRX_PRI_CFI_ACTION_ENCODE(
   5491             action->vlan_action.dt_outer_pkt_prio));
   5492         soc_mem_field32_set(
   5493             unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, DT_OCFI_ACTIONf,
   5494             _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.dt_outer_cfi));
   5495         soc_mem_field32_set(
   5496             unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, DT_IPRI_ACTIONf,
   5497             _BCM_TRX_PRI_CFI_ACTION_ENCODE(
   5498             action->vlan_action.dt_inner_pkt_prio));
   5499         soc_mem_field32_set(
   5500             unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, DT_ICFI_ACTIONf,
   5501             _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.dt_inner_cfi));
   5502         soc_mem_field32_set(
   5503             unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SOT_OPRI_ACTIONf,
   5504             _BCM_TRX_PRI_CFI_ACTION_ENCODE(
   5505             action->vlan_action.ot_outer_pkt_prio));
   5506         soc_mem_field32_set(
   5507             unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SOT_OCFI_ACTIONf,
   5508             _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.ot_outer_cfi));
   5509         soc_mem_field32_set(
   5510             unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SOT_IPRI_ACTIONf,
   5511             _BCM_TRX_PRI_CFI_ACTION_ENCODE(
   5512             action->vlan_action.ot_inner_pkt_prio));
   5513         soc_mem_field32_set(
   5514             unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SOT_ICFI_ACTIONf,
   5515             _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.ot_inner_cfi));
   5516         soc_mem_field32_set(
   5517             unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SIT_OPRI_ACTIONf,
   5518             _BCM_TRX_PRI_CFI_ACTION_ENCODE(
   5519             action->vlan_action.it_outer_pkt_prio));
   5520         soc_mem_field32_set(
   5521             unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SIT_OCFI_ACTIONf,
   5522             _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.it_outer_cfi));
   5523         soc_mem_field32_set(
   5524             unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SIT_IPRI_ACTIONf,
   5525             _BCM_TRX_PRI_CFI_ACTION_ENCODE(
   5526             action->vlan_action.it_inner_pkt_prio));
   5527         soc_mem_field32_set(
   5528             unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, SIT_ICFI_ACTIONf,
   5529             _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.it_inner_cfi));
   5530         soc_mem_field32_set(
   5531             unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, UT_OPRI_ACTIONf,
   5532             _BCM_TRX_PRI_CFI_ACTION_ENCODE(
   5533             action->vlan_action.ut_outer_pkt_prio));
   5534         soc_mem_field32_set(
   5535             unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, UT_OCFI_ACTIONf,
   5536             _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.ut_outer_cfi));
   5537         soc_mem_field32_set(
   5538             unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, UT_IPRI_ACTIONf,
   5539             _BCM_TRX_PRI_CFI_ACTION_ENCODE(
   5540             action->vlan_action.ut_inner_pkt_prio));
   5541         soc_mem_field32_set(
   5542             unit, EGR_VLAN_TAG_ACTION_PROFILEm, &entry, UT_ICFI_ACTIONf,
   5543             _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->vlan_action.ut_inner_cfi));
   5544     }
   5545 
   5546     return _bcm_trx_egr_vlan_action_profile_entry_no_mod_add(unit, &entry,
   5547                                                              index);
   5548 }
   5549 
   5550 
   5551 /* Add VSAN translate action */
   5552 int 
   5553 bcm_td2_fcoe_vsan_translate_action_add (
   5554                                     int unit, 
   5555                                     bcm_fcoe_vsan_translate_key_config_t *key, 
   5556                                     bcm_fcoe_vsan_action_set_t *action)
   5557 {
   5558     int                rv = BCM_E_NONE;
   5559     int  mem = VLAN_XLATEm;
   5560     int  vf  = VALIDf;
   5561     int  ent_sz = sizeof(vlan_xlate_entry_t);
   5562  
   5563     if (SOC_MEM_IS_VALID(unit, VLAN_XLATE_1_DOUBLEm)) {
   5564         mem = VLAN_XLATE_1_DOUBLEm;
   5565         vf = BASE_VALID_0f; /* TD3TBD */
   5566         ent_sz = sizeof(vlan_xlate_1_double_entry_t);
   5567     }
   5568 
   5569     if (action->flags & BCM_FCOE_VSAN_ACTION_INGRESS) {
   5570 
   5571         uint32             profile_idx; 
   5572         int                search_rv;
   5573         int                old_profile_idx = 0;
   5574         int                index;
   5575         void               *vent, *search_vent;
   5576         vlan_xlate_entry_t vx_ent;
   5577         vlan_xlate_entry_t search_vx_ent;
   5578 
   5579 #ifdef BCM_TRIDENT3_SUPPORT
   5580         vlan_xlate_1_double_entry_t vx1d_ent;
   5581         vlan_xlate_1_double_entry_t search_vx1d_ent;
   5582 
   5583         if (SOC_IS_TRIDENT3X(unit)) {
   5584             vent = &vx1d_ent;
   5585             search_vent= &search_vx1d_ent;
   5586             ent_sz = sizeof(vx1d_ent);
   5587         } else
   5588 #endif
   5589         {
   5590             vent = &vx_ent;
   5591             search_vent= &search_vx_ent;
   5592             ent_sz = sizeof(vx_ent);
   5593         }
   5594 
   5595         sal_memset(vent, 0, ent_sz);
   5596 
   5597         /* first, search VLAN_XLATE table using provided key */
   5598         BCM_IF_ERROR_RETURN(
   5599             _bcm_td2_fcoe_ing_vlan_translate_entry_assemble(unit, vent, 
   5600                                                             key)); 
   5601     
   5602         sal_memcpy(search_vent, vent, ent_sz);
   5603      
   5604         search_rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index,
   5605                                    search_vent, vent, 0);
   5606     
   5607         if (search_rv == SOC_E_NONE) {   /* already exist */
   5608             old_profile_idx = soc_mem_field32_get(unit, mem, vent, 
   5609                                               XLATE__TAG_ACTION_PROFILE_PTRf);
   5610         }
   5611     
   5612         soc_mem_field32_set(unit, mem, vent, NEW_IVIDf,
   5613                             action->vlan_action.new_inner_vlan);
   5614         soc_mem_field32_set(unit, mem, vent, NEW_OVIDf,
   5615                             action->vlan_action.new_outer_vlan);
   5616         if (soc_feature(unit, soc_feature_vlan_pri_cfi_action)) {
   5617             if (action->vlan_action.priority >= BCM_PRIO_MIN &&
   5618                 action->vlan_action.priority <= BCM_PRIO_MAX) {
   5619                 soc_mem_field32_set(unit, mem, vent, NEW_OPRIf,
   5620                                     action->vlan_action.priority);
   5621             }
   5622             soc_mem_field32_set(unit, mem, vent, NEW_OCFIf,
   5623                                 action->vlan_action.new_outer_cfi);
   5624             soc_mem_field32_set(unit, mem, vent, NEW_IPRIf,
   5625                                 action->vlan_action.new_inner_pkt_prio);
   5626             soc_mem_field32_set(unit, mem, vent, NEW_ICFIf,
   5627                                 action->vlan_action.new_inner_cfi);
   5628         }
   5629 
   5630         /* update or fill in the vlan xlate entry*/
   5631         BCM_IF_ERROR_RETURN(
   5632             _bcm_td2_ing_vlan_action_profile_entry_add(unit, action, 
   5633                                                        &profile_idx));
   5634 
   5635         /* update table index */
   5636         soc_mem_field32_set(unit, mem, vent, XLATE__TAG_ACTION_PROFILE_PTRf,
   5637                                     profile_idx);
   5638 
   5639         /* mark action is valid */
   5640         if (SOC_MEM_FIELD_VALID(unit, mem, XLATE__VLAN_ACTION_VALIDf)) {
   5641             soc_mem_field32_set(unit, mem, vent, 
   5642                                         XLATE__VLAN_ACTION_VALIDf, 1);
   5643         }
   5644 
   5645         /* VSAN ID & Pri. VSAN ID is not used for ingress VSAN translation...*/
   5646         soc_mem_field32_set(unit, mem, vent, XLATE__FCOE_VSAN_IDf, 
   5647                                     action->new_vsan);
   5648         soc_mem_field32_set(unit, mem, vent, XLATE__FCOE_VSAN_PRIf, 
   5649                                     action->new_vsan_pri);
   5650 
   5651         /* mark this entry(VLAN_XLATE) is valid */
   5652         if (mem == VLAN_XLATEm) {
   5653             soc_mem_field32_set(unit, mem, vent, vf, 1);
   5654         } else {
   5655             soc_mem_field32_set(unit, mem, vent, vf, 3);
   5656             soc_mem_field32_set(unit, mem, vent, BASE_VALID_1f, 7);
   5657         }
   5658 
   5659         /* NOTE : action->vft (remaining field of VFT header) is not used
   5660          *  on ingress side.
   5661          */
   5662 
   5663         /* write entry into table */
   5664         if (search_rv == SOC_E_NONE) {
   5665             /* overrides existing one */
   5666             rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, vent);
   5667         } else { /* case search_rv == SOC_E_NOT_FOUND */
   5668            rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, vent);
   5669         }
   5670     
   5671         if (BCM_FAILURE(rv)) {
   5672             /* Delete the allocated vlan translate profile entry */
   5673             profile_idx = soc_mem_field32_get(unit, mem, vent,
   5674                                              XLATE__TAG_ACTION_PROFILE_PTRf);
   5675             (void) _bcm_trx_vlan_action_profile_entry_delete(unit, profile_idx);
   5676         } else {
   5677             /* delete the old profile entry */
   5678             if (search_rv == SOC_E_NONE) {
   5679                 rv = _bcm_trx_vlan_action_profile_entry_delete(unit,
   5680                                                                old_profile_idx);
   5681             }
   5682         }
   5683 
   5684         if (rv != BCM_E_NONE) {
   5685             return rv;
   5686         }
   5687     }
   5688 
   5689 
   5690     if (action->flags & BCM_FCOE_VSAN_ACTION_EGRESS) {
   5691         uint32                 profile_idx;
   5692         uint32                 old_profile_idx = 0;
   5693         uint32                 vent[SOC_MAX_MEM_FIELD_WORDS];
   5694         uint32                 vent_old[SOC_MAX_MEM_FIELD_WORDS];
   5695         uint32                 *vent_ptr;
   5696         int                    index;
   5697         uint32                 vft_profile_index = 0;
   5698         uint32                 old_vft_profile_index = 0;
   5699         uint32                 port_class;
   5700         int                    search_rv, vf = VALIDf;
   5701         soc_mem_t              egr_mem = EGR_VLAN_XLATEm;
   5702  
   5703         if (SOC_MEM_IS_VALID(unit, EGR_VLAN_XLATE_1_DOUBLEm)) {
   5704             egr_mem = EGR_VLAN_XLATE_1_DOUBLEm;
   5705             vf = BASE_VALID_0f;
   5706         }
   5707     
   5708         BCM_IF_ERROR_RETURN(
   5709             bcm_esw_port_class_get(unit, key->port, 
   5710                                bcmPortClassVlanTranslateEgress, &port_class));
   5711 
   5712         vent_ptr = vent;
   5713         BCM_IF_ERROR_RETURN(
   5714             _bcm_td2_fcoe_egr_vlan_translate_entry_assemble(unit, port_class,
   5715                                                             vent_ptr, key));
   5716 
   5717         soc_mem_lock(unit, egr_mem);
   5718         /* check if the entry with same key already exists */
   5719         search_rv = soc_mem_search(unit, egr_mem, MEM_BLOCK_ANY, &index,
   5720                                    vent_ptr, vent_old, 0);
   5721 
   5722         if (search_rv == SOC_E_NONE) {
   5723             /* alredy exists, update on the existing one, so the flex
   5724             * counter related fields in TR3/Katana can be preserved.
   5725             */
   5726             vent_ptr = vent_old;
   5727             old_profile_idx = soc_mem_field32_get(unit, egr_mem, vent_ptr,
   5728                                                TAG_ACTION_PROFILE_PTRf); 
   5729             old_vft_profile_index = 
   5730                 soc_mem_field32_get(unit, egr_mem,  vent_ptr,
   5731                                                FCOE_VFT_FIELDS_PROFILE_INDEXf); 
   5732         } else if (search_rv != SOC_E_NOT_FOUND) {
   5733             soc_mem_unlock(unit, egr_mem);
   5734             return rv;  /* error condition */
   5735         } else {
   5736             /* doesn't exist, update the new entry */
   5737             vent_ptr = vent; 
   5738         }
   5739  
   5740         /* new VSAN & PRI */
   5741         soc_mem_field32_set(unit, egr_mem, vent_ptr, FCOE_VSAN_IDf, 
   5742                                         action->new_vsan);
   5743         soc_mem_field32_set(unit, egr_mem, vent_ptr, FCOE_VSAN_PRIf, 
   5744                                         action->new_vsan_pri);
   5745 
   5746 
   5747         soc_mem_field32_set(unit, egr_mem, vent_ptr, NEW_IVIDf,
   5748                             action->vlan_action.new_inner_vlan);
   5749         soc_mem_field32_set(unit, egr_mem, vent_ptr, NEW_OVIDf,
   5750                             action->vlan_action.new_outer_vlan);
   5751         if (soc_feature(unit, soc_feature_vlan_pri_cfi_action)) {
   5752             if (action->vlan_action.priority >= BCM_PRIO_MIN &&
   5753                 action->vlan_action.priority <= BCM_PRIO_MAX) {
   5754                 soc_mem_field32_set(unit, egr_mem, vent_ptr, NEW_OPRIf,
   5755                                     action->vlan_action.priority);
   5756             }
   5757             soc_mem_field32_set(unit, egr_mem, vent_ptr, NEW_OCFIf,
   5758                                 action->vlan_action.new_outer_cfi);
   5759             soc_mem_field32_set(unit, egr_mem, vent_ptr, NEW_IPRIf,
   5760                                 action->vlan_action.new_inner_pkt_prio);
   5761             soc_mem_field32_set(unit, egr_mem, vent_ptr, NEW_ICFIf,
   5762                                 action->vlan_action.new_inner_cfi);
   5763         }
   5764         /* action profile index */
   5765         rv = _bcm_td2_fcoe_egr_vlan_action_profile_entry_add(unit, action,
   5766                                                             &profile_idx);
   5767         if (rv != SOC_E_NONE) {
   5768             soc_mem_unlock(unit, egr_mem);
   5769             return rv;
   5770         }
   5771         soc_mem_field32_set(unit, egr_mem, vent_ptr, TAG_ACTION_PROFILE_PTRf,
   5772                                         profile_idx);
   5773 
   5774         /* new FCOE_VFT_FIELDS_PROFILE_INDEX, creaate one if not exist  */
   5775         rv = _bcm_td2_add_vft_fields_profile(unit, &action->vft, 
   5776                                             &vft_profile_index);
   5777         if (rv != SOC_E_NONE) {
   5778             soc_mem_unlock(unit, egr_mem);
   5779             return rv;
   5780         }
   5781 
   5782         rv = _bcm_td2_inc_vft_profile_refcnt(unit, vft_profile_index);
   5783         if (rv != SOC_E_NONE) {
   5784             soc_mem_unlock(unit, egr_mem);
   5785             return rv;
   5786         }
   5787 
   5788         soc_mem_field32_set(unit, egr_mem, vent_ptr, NEW_OTAG_VPTAG_SELf, 0);
   5789         if (vf == VALIDf) {
   5790             soc_mem_field32_set(unit, egr_mem, vent_ptr, vf, 1);
   5791         } else {
   5792             soc_mem_field32_set(unit, egr_mem, vent_ptr, vf, 3);
   5793             soc_mem_field32_set(unit, egr_mem, vent_ptr, BASE_VALID_1f, 7);
   5794         }
   5795 
   5796         if (search_rv == SOC_E_NONE) {
   5797             /* write back the existing one */
   5798             rv = soc_mem_write(unit, egr_mem,
   5799                                MEM_BLOCK_ALL, index, vent_ptr);
   5800             if (rv == SOC_E_NONE) {
   5801                 /* write was succeful */
   5802                 rv = _bcm_trx_egr_vlan_action_profile_entry_delete(unit,
   5803                                                               old_profile_idx);
   5804                 if (old_vft_profile_index != vft_profile_index) {
   5805                     rv += _bcm_td2_dec_vft_profile_refcnt(unit, 
   5806                                                          old_vft_profile_index);
   5807                 }
   5808             }
   5809         } else {
   5810             /* insert new one */
   5811             rv = soc_mem_insert(unit, egr_mem, MEM_BLOCK_ALL, vent_ptr);
   5812         }
   5813 
   5814         soc_mem_unlock(unit, egr_mem);
   5815 
   5816         return rv;
   5817     }
   5818 
   5819     return BCM_E_NONE;
   5820 }
   5821 
   5822 /* Delete VSAN translate action */
   5823 int 
   5824 bcm_td2_fcoe_vsan_translate_action_delete (
   5825                                     int unit, 
   5826                                     bcm_fcoe_vsan_translate_key_config_t *key) 
   5827 {
   5828     int                    rv = BCM_E_NONE; 
   5829     int                    search_rv;
   5830     int                    index;
   5831     uint32                 port_class;
   5832     vlan_xlate_entry_t     ing_vent;
   5833     uint32                 ing_profile_idx;
   5834     uint32                 egr_profile_idx;
   5835     uint32                 egr_vft_profile_idx;
   5836     soc_mem_t              mem = VLAN_XLATEm;
   5837     soc_mem_t              egr_mem = EGR_VLAN_XLATEm;
   5838     int                    ent_sz, vf = VALIDf;
   5839     vlan_xlate_1_double_entry_t     ing_1d_vent;
   5840     void                   *in_vent;
   5841     uint32                 egr_vent[SOC_MAX_MEM_FIELD_WORDS];
   5842 
   5843     in_vent = &ing_vent;
   5844     ent_sz = sizeof(ing_vent);
   5845 
   5846     if (SOC_MEM_IS_VALID(unit, VLAN_XLATE_1_DOUBLEm)) {
   5847         mem = VLAN_XLATE_1_DOUBLEm;
   5848         egr_mem = EGR_VLAN_XLATE_1_DOUBLEm;
   5849         vf  = BASE_VALID_0f;
   5850         in_vent = &ing_1d_vent;
   5851         ent_sz = sizeof(ing_1d_vent);
   5852     }
   5853 
   5854     /* ingress */
   5855     sal_memset(in_vent, 0, ent_sz);
   5856     BCM_IF_ERROR_RETURN(
   5857         _bcm_td2_fcoe_ing_vlan_translate_entry_assemble(unit, in_vent, 
   5858                                                         key)); 
   5859     
   5860     search_rv = soc_mem_search(unit, mem, MEM_BLOCK_ANY, &index,
   5861                                in_vent, in_vent, 0);
   5862     
   5863     if (search_rv == SOC_E_NONE) {   /* exist */
   5864         ing_profile_idx = soc_mem_field32_get(unit, mem, in_vent, 
   5865                                               XLATE__TAG_ACTION_PROFILE_PTRf);
   5866         /* mark entry as invalid */
   5867         if (mem == VLAN_XLATEm) {
   5868             soc_mem_field32_set(unit, mem, in_vent, vf, 0);
   5869         } else {
   5870             soc_mem_field32_set(unit, mem, in_vent, vf, 0);
   5871             soc_mem_field32_set(unit, mem, in_vent, BASE_VALID_1f, 0);
   5872         }
   5873         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, in_vent);
   5874 
   5875         if (rv == BCM_E_NONE) {
   5876             /* Delete the old vlan action profile entry */
   5877             rv = _bcm_trx_vlan_action_profile_entry_delete(unit, 
   5878                                                            ing_profile_idx);
   5879         }
   5880     } else if (search_rv == BCM_E_NOT_FOUND) {
   5881         rv = BCM_E_NONE;    /* if INGRESS flag was not used when adding action,
   5882                              * this is an expected return 
   5883                              */
   5884     }
   5885 
   5886     if (rv != BCM_E_NONE) {
   5887         return rv;
   5888     }
   5889 
   5890     /* egress */
   5891 
   5892     BCM_IF_ERROR_RETURN(
   5893         bcm_esw_port_class_get(unit, key->port, bcmPortClassVlanTranslateEgress,
   5894                            &port_class));
   5895 
   5896     sal_memset(egr_vent, 0, SOC_MAX_MEM_FIELD_WORDS * sizeof(uint32));
   5897     BCM_IF_ERROR_RETURN(
   5898             _bcm_td2_fcoe_egr_vlan_translate_entry_assemble(unit, port_class,
   5899                                                             egr_vent, key));
   5900 
   5901     soc_mem_lock(unit, egr_mem);
   5902 
   5903     /* check if the entry with same key already exists */
   5904     rv = soc_mem_search(unit, egr_mem, MEM_BLOCK_ANY, &index,
   5905                         egr_vent, egr_vent, 0);
   5906 
   5907     if (rv == SOC_E_NONE) {
   5908         /* exists */
   5909         egr_profile_idx = soc_mem_field32_get(unit, egr_mem, egr_vent,
   5910                                                      TAG_ACTION_PROFILE_PTRf); 
   5911         egr_vft_profile_idx =  soc_mem_field32_get(unit, egr_mem, egr_vent,
   5912                                                FCOE_VFT_FIELDS_PROFILE_INDEXf); 
   5913 
   5914         /* mark entry as invalid */
   5915         if (egr_mem == EGR_VLAN_XLATEm) {
   5916             soc_mem_field32_set(unit, egr_mem, egr_vent, vf, 0);
   5917         } else {
   5918             soc_mem_field32_set(unit, egr_mem, egr_vent, vf, 0);
   5919             soc_mem_field32_set(unit, egr_mem, egr_vent, BASE_VALID_1f, 0);
   5920         }
   5921         rv = soc_mem_write(unit, egr_mem, MEM_BLOCK_ALL, index, egr_vent);
   5922 
   5923         if (rv == BCM_E_NONE) {
   5924 
   5925             /* Delete vlan action profile entry */
   5926             rv = _bcm_trx_egr_vlan_action_profile_entry_delete(unit, 
   5927                                                                egr_profile_idx);
   5928             /* delete vft profile entry */
   5929             rv += _bcm_td2_dec_vft_profile_refcnt(unit, egr_vft_profile_idx);
   5930         }
   5931     } else if (rv == BCM_E_NOT_FOUND) {
   5932         rv = BCM_E_NONE;    /* if EGRESS flag was not used when adding action,
   5933                              * this is an expected return 
   5934                              */
   5935     }
   5936     soc_mem_unlock(unit, egr_mem);
   5937     return rv;
   5938 }
   5939 
   5940 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP
   5941 void 
   5942 _bcm_td2_fcoe_sw_dump(int unit)
   5943 {
   5944     uint32 vsan_id;
   5945     int valid = 0;
   5946     int count = 0;
   5947 
   5948     LOG_CLI((BSL_META_U(unit,
   5949                         "\nSW Information FCOE - Unit %d\n"), unit));
   5950 
   5951     LOG_CLI((BSL_META_U(unit,
   5952                         "VSAN ID Creation State : \n")));
   5953     for (vsan_id = 0; vsan_id <= FCOE_MAX_VSAN_ID; vsan_id++) {
   5954         valid = _bcm_td2_vsan_id_creation_state_get(unit, vsan_id);
   5955         if (valid) {
   5956             count++;
   5957             LOG_CLI((BSL_META_U(unit, "%4d "), vsan_id));
   5958             if (count == 16) {
   5959                 count = 0;
   5960                 LOG_CLI((BSL_META_U(unit, "\n")));
   5961             }
   5962         }
   5963     }
   5964     LOG_CLI((BSL_META_U(unit, "\n")));
   5965 }
   5966 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */
   5967 
   5968 /* traverse zone entries and call user callback function */
   5969 int 
   5970 bcm_td2_fcoe_zone_traverse(int unit,
   5971                            uint32 flags,
   5972                            bcm_fcoe_zone_traverse_cb trav_fn,
   5973                            void *user_data)
   5974 {
   5975     int           ix;
   5976     int           key_type;
   5977     int           chnk_end;
   5978     int           chunksize;
   5979     int           chunk;
   5980     int           chunk_max;
   5981     int            mem_idx_max;
   5982     L2_ENTRY_T    *l2e;
   5983     L2_ENTRY_T    *l2ep;
   5984     soc_mem_t     mem;
   5985     uint32        action;
   5986     uint32        copy_to_cpu;
   5987     int           rv = BCM_E_NONE;
   5988     bcm_fcoe_zone_entry_t zone;
   5989 
   5990     /* note : flags parameter is not used at the moment */
   5991 
   5992     chunksize = soc_property_get(unit, spn_L2DELETE_CHUNKS,
   5993                                  L2_MEM_CHUNKS_DEFAULT);
   5994 
   5995     mem = L2Xm;
   5996 
   5997     l2e = soc_cm_salloc(unit, chunksize * sizeof(*l2e), "l2entrydel_chunk");
   5998 
   5999     if (l2e == NULL) {
   6000         return BCM_E_MEMORY;
   6001     }
   6002 
   6003     mem_idx_max = soc_mem_index_max(unit, mem);
   6004 
   6005     soc_mem_lock(unit, mem);
   6006 
   6007     for (chunk = soc_mem_index_min(unit, mem); chunk <= mem_idx_max;
   6008          chunk += chunksize) {
   6009 
   6010         chunk_max = chunk + chunksize - 1;
   6011 
   6012         if (chunk_max > mem_idx_max) {
   6013             chunk_max = mem_idx_max;
   6014         }
   6015 
   6016         rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY,
   6017                                 chunk, chunk_max, l2e);
   6018         if (rv < 0) {
   6019             break;
   6020         }
   6021 
   6022         chnk_end = (chunk_max - chunk);
   6023 
   6024         for (ix = 0; ix <= chnk_end; ix++) {
   6025             l2ep = soc_mem_table_idx_to_pointer(unit, mem,
   6026                                                  L2_ENTRY_T *, l2e, ix);
   6027 #ifdef BCM_TRIDENT3_SUPPORT
   6028             if (SOC_IS_TRIDENT3X(unit)) {
   6029                 if (!soc_mem_field32_get(unit, mem, l2ep, BASE_VALIDf)) {
   6030                     continue;
   6031                 }
   6032             } else
   6033 #endif
   6034             {
   6035                 if (!soc_mem_field32_get(unit, mem, l2ep, VALIDf)) {
   6036                     continue;
   6037                 }
   6038             }
   6039 
   6040             /* Match the Key Type to FCOE */
   6041             key_type = soc_mem_field32_get(unit, mem, l2ep, KEY_TYPEf);
   6042 
   6043             if (key_type != TD2_L2_HASH_KEY_TYPE_FCOE_ZONE) {
   6044                 continue;
   6045             }
   6046 
   6047             /* found zone entry */
   6048            sal_memset(&zone, 0, sizeof(bcm_fcoe_zone_entry_t));
   6049            zone.vsan_id = soc_mem_field32_get(unit, mem, l2ep, 
   6050                                               FCOE_ZONE__VSAN_IDf); 
   6051            zone.d_id = soc_mem_field32_get(unit, mem, l2ep, FCOE_ZONE__D_IDf);
   6052            zone.s_id = soc_mem_field32_get(unit, mem, l2ep, FCOE_ZONE__S_IDf);
   6053            zone.class_id = (int)soc_mem_field32_get(unit, mem, l2ep,
   6054                                                     FCOE_ZONE__CLASS_IDf);
   6055            action = soc_mem_field32_get(unit, mem, l2ep, FCOE_ZONE__ACTIONf);
   6056 #ifdef BCM_TRIDENT3_SUPPORT
   6057            if (SOC_IS_TRIDENT3X(unit)) {
   6058                copy_to_cpu = soc_mem_field32_get(unit, mem, l2ep,
   6059                                              FCOE_ZONE__CPUf);
   6060            } else 
   6061 #endif /* BCM_TRIDENT3_SUPPORT */
   6062            {
   6063                copy_to_cpu = soc_mem_field32_get(unit, mem, l2ep,
   6064                                                  FCOE_ZONE__COPY_TO_CPUf);
   6065            }
   6066 
   6067            if (action == 1) {
   6068                zone.action = bcmFcoeZoneActionAllow;
   6069            } else {  /* action is 0 (deny) */
   6070                zone.action = bcmFcoeZoneActionDeny;
   6071                if (copy_to_cpu == 1) {
   6072                    zone.action = bcmFcoeZoneActionCopyToCpu;
   6073                }
   6074            }
   6075 
   6076            /* call user callback function with a zone entry */
   6077            rv = (trav_fn)(unit, &zone, user_data);
   6078 
   6079            if (rv < 0) {
   6080                break;
   6081            }
   6082         }
   6083 
   6084         if (rv < 0) {
   6085             break;
   6086         }
   6087     }
   6088 
   6089     soc_mem_unlock(unit, mem);
   6090     soc_cm_sfree(unit, l2e);
   6091 
   6092     return rv;
   6093 }
   6094 
   6095 /* traverse vsan entries and call user callback function */
   6096 int 
   6097 bcm_td2_fcoe_vsan_traverse(int unit,
   6098                            uint32 flags,
   6099                            bcm_fcoe_vsan_traverse_cb trav_fn,
   6100                            void *user_data)
   6101 {
   6102     ing_vsan_entry_t vsan_entry;
   6103     soc_mem_t        mem = ING_VSANm;
   6104     int              rv = BCM_E_NONE;
   6105     int              index;
   6106     bcm_fcoe_vsan_t  vsan;
   6107     int              flag = 0;
   6108     int              fcmap_index = 0;
   6109     bcm_fcoe_fcmap_t fcmap;
   6110 
   6111     /* note : flags parameter is not used at the moment */
   6112 
   6113     soc_mem_lock(unit, mem);
   6114     for (index = 0; index <= FCOE_MAX_VSAN_ID; index++) {
   6115 
   6116         /* check if vsan id is existing */
   6117         if (shr_idxres_list_elem_state(vsan_id_list[unit], index) !=
   6118                 BCM_E_EXISTS) {
   6119             continue;
   6120         }
   6121 
   6122         /* read table entry */
   6123         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &vsan_entry);
   6124         if (rv != BCM_E_NONE) {
   6125             break;
   6126         }
   6127 
   6128         sal_memset(&vsan, 0, sizeof(bcm_fcoe_vsan_t));
   6129 
   6130         /* get FC MAP */
   6131         fcmap_index = soc_mem_field32_get(unit,mem, (uint32 *)&vsan_entry,
   6132                                           FCOE_FC_MAP_INDEXf);
   6133 
   6134         rv = _bcm_fcoe_fc_profile_map_value_get (unit, fcmap_index, &fcmap);
   6135         if (rv != BCM_E_NONE) {
   6136             break;
   6137         }
   6138         vsan.fcmap = fcmap;
   6139 
   6140         flag = soc_mem_field32_get(unit, mem, (uint32 *)&vsan_entry,
   6141                                    ZONE_CHECK_NORMALIZEDf);
   6142         if (flag) {
   6143             vsan.config_flags |= BCM_FCOE_VSAN_CONFIG_NORMALIZED_ZONE_CHECK;
   6144         }
   6145 
   6146         flag = soc_mem_field32_get(unit, mem, (uint32 *)&vsan_entry,
   6147                                    FCOE_ROUTE_ENABLEf);
   6148         if (flag) {
   6149             vsan.config_flags |= BCM_FCOE_VSAN_CONFIG_FCOE_ROUTE_ENABLE;
   6150         }
   6151 
   6152         vsan.l3_intf_id = soc_mem_field32_get(unit, mem, (uint32 *)&vsan_entry,
   6153                                               L3_IIFf);
   6154 
   6155         /* call user callback function with a vsan entry. index is vsan_id */
   6156         rv = (trav_fn)(unit, index, &vsan, user_data);
   6157 
   6158         if (rv < 0) {
   6159             break;
   6160         }
   6161     }
   6162 
   6163     soc_mem_unlock(unit, mem);
   6164     return rv;
   6165 }
   6166 
   6167 #ifdef INCLUDE_L3
   6168 #ifdef BCM_TRIDENT3_SUPPORT
   6169 STATIC int
   6170 _bcm_td3_fcoe_correct_key_type_for_flags(int unit, uint32    flags, 
   6171                                          soc_mem_t mem, 
   6172                                          int       key_type,
   6173                                          int       data_type)
   6174 {
   6175     int rv = BCM_E_NONE;
   6176 
   6177     if (mem == _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit)) {
   6178         if ((key_type == (int)TD3_L3_HASH_KEY_TYPE_FCOE_HOST) || 
   6179             (data_type == (int)TD3_L3_HASH_DATA_TYPE_FCOE_HOST_EXT)) {
   6180             if ((flags & BCM_FCOE_HOST_ROUTE) == 0) {
   6181                 rv = BCM_E_NOT_FOUND;
   6182             }
   6183         } else if ((key_type == (int)TD3_L3_HASH_KEY_TYPE_FCOE_DOMAIN) || 
   6184                    (data_type == (int)TD3_L3_HASH_DATA_TYPE_FCOE_DOMAIN_EXT)) {
   6185             if ((flags & BCM_FCOE_DOMAIN_ROUTE) == 0) {
   6186                 rv = BCM_E_NOT_FOUND;
   6187             }
   6188         } else if ((key_type == (int)TD3_L3_HASH_KEY_TYPE_FCOE_SOURCE_MAP) ||
   6189                    (data_type == (int)TD3_L3_HASH_DATA_TYPE_FCOE_SOURCE_MAP_EXT)) {
   6190             if ((flags & BCM_FCOE_SOURCE_ROUTE) == 0) {
   6191                 rv = BCM_E_NOT_FOUND;
   6192             }
   6193         } else {
   6194             rv = BCM_E_NOT_FOUND;
   6195         }
   6196     } else if (mem == _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit)) {
   6197         if ((key_type == (int)TD3_L3_HASH_KEY_TYPE_FCOE_HOST) || 
   6198             (data_type == (int)TD3_L3_HASH_DATA_TYPE_FCOE_HOST)) {
   6199             if ((flags & BCM_FCOE_HOST_ROUTE) == 0) {
   6200                 rv = BCM_E_NOT_FOUND;
   6201             }
   6202         } else if ((key_type == (int)TD3_L3_HASH_KEY_TYPE_FCOE_DOMAIN) ||
   6203                    (data_type == (int)TD3_L3_HASH_DATA_TYPE_FCOE_DOMAIN)) {
   6204             if ((flags & BCM_FCOE_DOMAIN_ROUTE) == 0) {
   6205                 rv = BCM_E_NOT_FOUND;
   6206             }
   6207         } else if ((key_type == (int)TD3_L3_HASH_KEY_TYPE_FCOE_SOURCE_MAP) ||
   6208                    (data_type == (int)TD3_L3_HASH_DATA_TYPE_FCOE_SOURCE_MAP)) {
   6209             if ((flags & BCM_FCOE_SOURCE_ROUTE) == 0) {
   6210                 rv = BCM_E_NOT_FOUND;
   6211             }
   6212         } else {
   6213             rv = BCM_E_NOT_FOUND;
   6214         }
   6215     } else {
   6216         rv = BCM_E_NOT_FOUND;
   6217     }
   6218 
   6219     return rv;
   6220 }
   6221 #endif /* BCM_TRIDENT3_SUPPORT */
   6222 STATIC int
   6223 _bcm_td2_fcoe_correct_key_type_for_flags(int unit, uint32    flags, 
   6224                                          soc_mem_t mem, 
   6225                                          int       key_type)
   6226 {
   6227     int rv = BCM_E_NONE;
   6228 
   6229     if (mem == _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit)) {
   6230         if (key_type == TD2_L3_HASH_KEY_TYPE_FCOE_HOST_EXT) {
   6231             if ((flags & BCM_FCOE_HOST_ROUTE) == 0) {
   6232                 rv = BCM_E_NOT_FOUND;
   6233             }
   6234         } else if (key_type == TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN_EXT) {
   6235             if ((flags & BCM_FCOE_DOMAIN_ROUTE) == 0) {
   6236                 rv = BCM_E_NOT_FOUND;
   6237             }
   6238         } else if (key_type == TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP_EXT) {
   6239             if ((flags & BCM_FCOE_SOURCE_ROUTE) == 0) {
   6240                 rv = BCM_E_NOT_FOUND;
   6241             }
   6242         } else {
   6243             rv = BCM_E_NOT_FOUND;
   6244         }
   6245     } else if (mem == _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit)) {
   6246         if (key_type == TD2_L3_HASH_KEY_TYPE_FCOE_HOST) {
   6247             if ((flags & BCM_FCOE_HOST_ROUTE) == 0) {
   6248                 rv = BCM_E_NOT_FOUND;
   6249             }
   6250         } else if (key_type == TD2_L3_HASH_KEY_TYPE_FCOE_DOMAIN) {
   6251             if ((flags & BCM_FCOE_DOMAIN_ROUTE) == 0) {
   6252                 rv = BCM_E_NOT_FOUND;
   6253             }
   6254         } else if (key_type == TD2_L3_HASH_KEY_TYPE_FCOE_SRC_MAP) {
   6255             if ((flags & BCM_FCOE_SOURCE_ROUTE) == 0) {
   6256                 rv = BCM_E_NOT_FOUND;
   6257             }
   6258         } else {
   6259             rv = BCM_E_NOT_FOUND;
   6260         }
   6261     } else {
   6262         rv = BCM_E_NOT_FOUND;
   6263     }
   6264 
   6265     return rv;
   6266 }
   6267 
   6268 STATIC int
   6269 _bcm_fcoe_route_tbl_traverse_normal(int unit, 
   6270                                     uint32 flags,
   6271                                     bcm_fcoe_route_traverse_cb trav_fn,
   6272                                     void *user_data)
   6273 {
   6274     l3_entry_ipv4_multicast_entry_t l3_ext_entry;
   6275 
   6276     soc_mem_t        mem = _bcm_fcoe_l3_entry_ipv4_unicast_mem_get(unit);
   6277     uint32           *buf = (uint32 *)&l3_ext_entry;
   6278     int              idx;
   6279     int              idx_max;
   6280     int              key_type_0;
   6281     int              rv = BCM_E_NONE;
   6282     bcm_fcoe_route_t route;
   6283 
   6284     idx_max = soc_mem_index_max(unit, mem);
   6285 
   6286     soc_mem_lock(unit, mem);
   6287 
   6288     for (idx = 0; idx < idx_max; idx++) {
   6289         sal_memset(buf, 0, sizeof l3_ext_entry);
   6290 
   6291         rv = BCM_XGS3_MEM_READ(unit, mem, idx, buf);
   6292         if (BCM_FAILURE(rv)) {
   6293             break;
   6294         }
   6295 
   6296 #ifdef BCM_TRIDENT3_SUPPORT
   6297         if (SOC_IS_TRIDENT3X(unit)) {
   6298             int key_type_1;
   6299             if (!soc_mem_field32_get(unit, mem, buf, BASE_VALIDf)) {
   6300                 continue;
   6301             }
   6302             key_type_0 = soc_mem_field32_get(unit, mem, buf,
   6303                                              KEY_TYPEf);
   6304             key_type_1 = soc_mem_field32_get(unit, mem, buf,
   6305                                              DATA_TYPEf);
   6306 
   6307             if (!_bcm_td3_key_type_is_fcoe(unit, mem, key_type_0, key_type_1)) {
   6308                 continue;
   6309             }
   6310 
   6311             if (_bcm_td3_fcoe_correct_key_type_for_flags(unit, flags, mem, key_type_0, key_type_1) != 
   6312                  BCM_E_NONE) {
   6313                 continue;
   6314             }
   6315         } else
   6316 #endif
   6317         {
   6318             if (!soc_mem_field32_get(unit, mem, buf, VALIDf)) {
   6319                continue;
   6320             }
   6321 
   6322             key_type_0 = soc_mem_field32_get(unit, mem, buf,
   6323                                              KEY_TYPEf);
   6324 
   6325             if (!_bcm_td2_key_type_is_fcoe(unit, mem, key_type_0)) {
   6326                 continue;
   6327             }
   6328 
   6329             if (_bcm_td2_fcoe_correct_key_type_for_flags(unit, flags, mem, key_type_0) != 
   6330                  BCM_E_NONE) {
   6331                 continue;
   6332             }
   6333         }
   6334 
   6335         /* build route entry */
   6336         sal_memset(&route, 0, sizeof(bcm_fcoe_route_t));
   6337 
   6338         _bcm_fcoe_read_mem_into_route(unit, mem, buf, &route);
   6339 
   6340         /* call user callback function */
   6341         rv = (trav_fn)(unit, &route, user_data);
   6342         if (rv != BCM_E_NONE) {
   6343             break;
   6344         }
   6345     }
   6346 
   6347     soc_mem_unlock(unit, mem);
   6348 
   6349     return rv;
   6350 }
   6351 
   6352 
   6353 STATIC int
   6354 _bcm_fcoe_route_tbl_traverse_ext(int unit, 
   6355                                  uint32 flags,
   6356                                  bcm_fcoe_route_traverse_cb trav_fn,
   6357                                  void *user_data)
   6358 {
   6359     l3_entry_ipv4_multicast_entry_t l3_ext_entry;
   6360 
   6361     soc_mem_t        mem = _bcm_fcoe_l3_entry_ipv4_multicast_mem_get(unit);
   6362     uint32           *buf = (uint32 *)&l3_ext_entry;
   6363     int              idx;
   6364     int              idx_max;
   6365     int              key_type_0, key_type_0f = KEY_TYPE_0f;
   6366     int              key_type_1, key_type_1f = KEY_TYPE_1f;
   6367     int              valid_0f = VALID_0f;
   6368     int              valid_1f = VALID_1f;
   6369     int              rv = BCM_E_NONE;
   6370     bcm_fcoe_route_t route;
   6371 
   6372     idx_max = soc_mem_index_max(unit, mem);
   6373 
   6374     soc_mem_lock(unit, mem);
   6375 
   6376 #ifdef BCM_TRIDENT3_SUPPORT
   6377     if (SOC_IS_TRIDENT3X(unit)) {
   6378         valid_0f = BASE_VALID_0f;
   6379         valid_1f = BASE_VALID_1f;
   6380         key_type_0f = KEY_TYPEf;
   6381         key_type_1f = DATA_TYPEf;
   6382     } 
   6383 #endif
   6384     for (idx = 0; idx < idx_max; idx++) {
   6385         sal_memset(buf, 0, sizeof l3_ext_entry);
   6386 
   6387         rv = BCM_XGS3_MEM_READ(unit, mem, idx, buf);
   6388         if (BCM_FAILURE(rv)) {
   6389             break;
   6390         }
   6391 
   6392         if (!soc_mem_field32_get(unit, mem, buf, valid_0f) ||
   6393             !soc_mem_field32_get(unit, mem, buf, valid_1f)) {
   6394             continue;
   6395         }
   6396 
   6397         key_type_0 = soc_mem_field32_get(unit, mem, buf, key_type_0f);
   6398         key_type_1 = soc_mem_field32_get(unit, mem, buf, key_type_1f);
   6399 
   6400 #ifdef BCM_TRIDENT3_SUPPORT
   6401         if (SOC_IS_TRIDENT3X(unit)) {
   6402             if (!_bcm_td3_key_type_is_fcoe(unit, mem, key_type_0, key_type_1)) {
   6403                 continue;
   6404             }
   6405             if (_bcm_td3_fcoe_correct_key_type_for_flags(unit, flags, mem, key_type_0, key_type_1) !=
   6406                  BCM_E_NONE) {
   6407                 continue;
   6408             }
   6409         } else
   6410 #endif   
   6411         {
   6412             if (!_bcm_td2_key_type_is_fcoe(unit, mem, key_type_0) ||
   6413                 (key_type_0 != key_type_1)) {
   6414                 continue;
   6415             }
   6416 
   6417             if (_bcm_td2_fcoe_correct_key_type_for_flags(unit, flags, mem, key_type_0) !=
   6418                  BCM_E_NONE) {
   6419                 continue;
   6420             }
   6421         }
   6422 
   6423         /* build route entry */
   6424         sal_memset(&route, 0, sizeof(bcm_fcoe_route_t));
   6425 
   6426         _bcm_fcoe_read_mem_into_route(unit, mem, buf, &route);
   6427 
   6428         /* call user callback function */
   6429         rv = (trav_fn)(unit, &route, user_data);
   6430         if (rv != BCM_E_NONE) {
   6431             break;
   6432         }
   6433     }
   6434 
   6435     soc_mem_unlock(unit, mem);
   6436 
   6437     return rv;
   6438 }
   6439 
   6440 STATIC int
   6441 _bcm_fcoe_route_tbl_traverse_prefix(int unit, 
   6442                                     bcm_fcoe_route_traverse_cb trav_fn,
   6443                                     void *user_data)
   6444 {
   6445     uint32    entry[SOC_MAX_MEM_WORDS];
   6446     uint32           *buf = entry;
   6447     soc_mem_t        mem = L3_DEFIPm;
   6448     int              idx;
   6449     int              idx_max;
   6450     int              rv = BCM_E_NONE;
   6451     bcm_fcoe_route_t route;
   6452     int              nh_idx = 0;
   6453     _bcm_defip_cfg_t lpm_cfg;
   6454 
   6455     idx_max = soc_mem_index_max(unit, mem);
   6456 
   6457     soc_mem_lock(unit, mem);
   6458 
   6459     for (idx = 0; idx < idx_max; idx++) {
   6460         sal_memset(buf, 0, sizeof entry);
   6461 
   6462         rv = BCM_XGS3_MEM_READ(unit, mem, idx, buf);
   6463         if (BCM_FAILURE(rv)) {
   6464             break;
   6465         }
   6466 
   6467         /* first entry */
   6468         if (soc_mem_field32_get(unit, mem, buf, VALID0f) &&
   6469             soc_mem_field32_get(unit, mem, buf, ENTRY_TYPE0f)) { 
   6470 
   6471             /* build route entry */
   6472             sal_memset(&route, 0, sizeof(bcm_fcoe_route_t));
   6473             sal_memset(&lpm_cfg , 0, sizeof(_bcm_defip_cfg_t));
   6474 
   6475             BCM_IF_ERROR_RETURN(
   6476                 _bcm_fb_lpm_ent_parse(unit, &lpm_cfg, &nh_idx,
   6477                                       buf, NULL));
   6478 
   6479             rv = _bcm_fcoe_defip_to_route(unit, &lpm_cfg, &route);
   6480 
   6481             if (rv != BCM_E_NONE) {
   6482                 break;
   6483             }
   6484 
   6485             if (BCM_XGS3_L3_EGRESS_MODE_ISSET(unit)) {
   6486                 if (route.flags & BCM_FCOE_MULTIPATH) {
   6487                     route.intf = nh_idx + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit);
   6488                 } else {
   6489                     route.intf = nh_idx + BCM_XGS3_EGRESS_IDX_MIN(unit);
   6490                 }
   6491             }
   6492 
   6493             /* call user callback function */
   6494             rv = (trav_fn)(unit, &route, user_data);
   6495 
   6496             if (rv != BCM_E_NONE) {
   6497                 break;
   6498             }
   6499         }
   6500 
   6501         /* second entry */
   6502         if (soc_mem_field32_get(unit, mem, buf, VALID1f) &&
   6503             soc_mem_field32_get(unit, mem, buf, ENTRY_TYPE1f)) {
   6504 
   6505             /* build route entry */
   6506             sal_memset(&route, 0, sizeof(bcm_fcoe_route_t));
   6507             sal_memset(&lpm_cfg , 0, sizeof(_bcm_defip_cfg_t));
   6508 
   6509             rv = soc_fb_lpm_ip4entry1_to_0(unit, buf, buf, 0);
   6510 
   6511             if (rv != BCM_E_NONE) {
   6512                 break;
   6513             }
   6514 
   6515             BCM_IF_ERROR_RETURN(
   6516             _bcm_fb_lpm_ent_parse(unit, &lpm_cfg, &nh_idx,
   6517                                   buf, NULL));
   6518 
   6519             rv = _bcm_fcoe_defip_to_route(unit, &lpm_cfg, &route);
   6520 
   6521             if (rv != BCM_E_NONE) {
   6522                 break;
   6523             }
   6524 
   6525             if (BCM_XGS3_L3_EGRESS_MODE_ISSET(unit)) {
   6526                 if (route.flags & BCM_FCOE_MULTIPATH) {
   6527                     route.intf = nh_idx + BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit);
   6528                 } else {
   6529                     route.intf = nh_idx + BCM_XGS3_EGRESS_IDX_MIN(unit);
   6530                 }
   6531             }
   6532 
   6533             /* call user callback function */
   6534             rv = (trav_fn)(unit, &route, user_data);
   6535 
   6536             if (rv != BCM_E_NONE) {
   6537                 break;
   6538             }
   6539         }
   6540     }
   6541 
   6542     soc_mem_unlock(unit, mem);
   6543 
   6544     return rv;
   6545 }
   6546 
   6547 #endif  /* INCLUDE_L3 */
   6548 
   6549 /* traverse routing entries and call user callback function */
   6550 int 
   6551 bcm_td2_fcoe_route_traverse(int unit,
   6552                             uint32 flags,
   6553                             bcm_fcoe_route_traverse_cb trav_fn,
   6554                             void *user_data)
   6555 {
   6556 #ifdef INCLUDE_L3
   6557     int rv = BCM_E_NONE;
   6558 
   6559     if (BCM_XGS3_L3_EGRESS_MODE_ISSET(unit)) {
   6560         /* search L3_ENTRY_IPV4_UNICAST table */
   6561         rv = _bcm_fcoe_route_tbl_traverse_normal(unit, flags, trav_fn, 
   6562                                                  user_data);
   6563         if (rv == BCM_E_NONE) {
   6564             /* search L3_ENTRY_IPV4_MULTICAST table */
   6565             rv = _bcm_fcoe_route_tbl_traverse_ext(unit, flags, trav_fn, 
   6566                                                   user_data);
   6567         }
   6568     } else {
   6569         /* search L3_ENTRY_IPV4_MULTICAST table */
   6570         rv = _bcm_fcoe_route_tbl_traverse_ext(unit, flags, trav_fn, user_data);
   6571     }
   6572 
   6573     if (rv != BCM_E_NONE) {
   6574         return rv;
   6575     }
   6576     
   6577     if (flags & BCM_FCOE_DOMAIN_ROUTE) {
   6578         /* L3_DEFIP table for prefix route */
   6579         rv = _bcm_fcoe_route_tbl_traverse_prefix(unit, trav_fn, user_data);
   6580     }
   6581 
   6582     return rv;
   6583 #else
   6584     return BCM_E_UNAVAIL;
   6585 #endif
   6586 }
   6587 
   6588 
   6589 #endif /* BCM_TRIDENT2_SUPORT */