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

vlan.c (61086B)


      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:        vlan.c
      8  * Purpose:     Provide low-level access to Tomahawk3 VLAN resources
      9  */
     10 #if defined(BCM_TOMAHAWK3_SUPPORT)
     11 #include <soc/drv.h>
     12 #include <soc/mem.h>
     13 #include <soc/profile_mem.h>
     14 #include <bcm/error.h>
     15 
     16 #include <bcm_int/esw/mbcm.h>
     17 #include <bcm_int/esw/vlan.h>
     18 #include <bcm_int/esw/port.h>
     19 #include <bcm_int/esw/trx.h>
     20 #ifdef BCM_TRX_SUPPORT
     21 #include <bcm_int/esw/triumph.h>
     22 #endif
     23 #include <bcm_int/esw/tomahawk3.h>
     24 #include <bcm_int/esw/firebolt.h>
     25 
     26 /* VLAN Cross Connect DB declaraions/definitions */
     27 typedef struct _bcm_th3_vlan_xconnect_db_s {
     28     SHR_BITDCL valid[_SHR_BITDCLSIZE(BCM_VLAN_COUNT)]; /* Valid bitmap */
     29     SHR_BITDCL dest_type[_SHR_BITDCLSIZE(BCM_VLAN_COUNT*2)]; /* TGID/Port */
     30     uint8 destination[BCM_VLAN_COUNT*2]; /* Trunk/Port ID */
     31 } _bcm_th3_vlan_xconnect_db_t;
     32 
     33 static
     34 _bcm_th3_vlan_xconnect_db_t *_bcm_th3_xconnect_db[BCM_MAX_NUM_UNITS]= {0};
     35 
     36 #define BCM_TH3_VLAN_XC_DB_DESTTYPE_OFFSET(_ovid_)  ((_ovid_) * 2)
     37 #define BCM_TH3_VLAN_XC_DB_DESTTYPE1_OFFSET(_ovid_) (((_ovid_) * 2) + 1)
     38 
     39 /* VLAN Cross Connect Mutex defintion/macros */
     40 sal_mutex_t _bcm_th3_xconnect_mtx[BCM_MAX_NUM_UNITS] = {0};
     41 
     42 #define BCM_TH3_VLAN_XCONNECT_MUTEX_ACQ(_unit_) \
     43         sal_mutex_take(_bcm_th3_xconnect_mtx[(_unit_)], sal_mutex_FOREVER);
     44 
     45 #define BCM_TH3_VLAN_XCONNECT_MUTEX_REL(_unit_) \
     46         sal_mutex_give(_bcm_th3_xconnect_mtx[(_unit_)]);
     47 
     48 #define ING_ACTION_PROFILE_DEFAULT  0
     49 /* Cache of Ingress Vlan Translate Action Profile Table */
     50 static soc_profile_mem_t *ing_action_profile[BCM_MAX_NUM_UNITS] = {NULL};
     51 
     52 /* Cache of Egress Vlan Translate Action Profile Table */
     53 static soc_profile_mem_t *egr_action_profile[BCM_MAX_NUM_UNITS] = {NULL};
     54 
     55 /* Cache of VLAN Port Bitmap Profile Table */
     56 static soc_profile_mem_t *vlan_pbmp_profile[BCM_MAX_NUM_UNITS] = {NULL};
     57 
     58 /*
     59  * Function:
     60  *      _bcm_th3_vlan_pbmp_profile_init
     61  *
     62  * Purpose:
     63  *       to initialize hardware PORT_BITMAP_PROFILE table
     64  *       and allocate memory to cache hardware tables in RAM.
     65  *
     66  * Parameters:
     67  *      unit - (IN)  Device Number
     68  *
     69  * Returns:
     70  *      BCM_E_XXX
     71  *
     72  * Notes:
     73  *      Allocate memory to cache the profile tables and initialize.
     74  *      If memory to cache the profile table is already allocated,
     75  *      just initialize the table.
     76  */
     77 int
     78 _bcm_th3_vlan_pbmp_profile_init(int unit) {
     79 
     80     uint32 profile_idx;
     81     soc_mem_t mem;
     82     int entry_dwords;
     83     bcm_pbmp_t pbmp;
     84 #if defined(BCM_WARM_BOOT_SUPPORT)
     85     int mem_idx;
     86     vlan_2_tab_entry_t vlan_2_entry;
     87     const int mem_entry_cnt = soc_mem_index_count(unit, VLAN_2_TABm);
     88 #endif /* BCM_WARM_BOOT_SUPPORT */
     89 
     90     if (!soc_feature(unit, soc_feature_vlan_pbmp_profile_mgmt)) {
     91         return BCM_E_UNAVAIL;
     92     }
     93 
     94     /* Initialize the PORT_BITMAP_PROFILE table */
     95     if (NULL == vlan_pbmp_profile[unit]) {
     96         vlan_pbmp_profile[unit] =
     97             sal_alloc(sizeof(soc_profile_mem_t), "VLAN PBMP Profile");
     98         if (NULL == vlan_pbmp_profile[unit]) {
     99             return BCM_E_MEMORY;
    100         }
    101         soc_profile_mem_t_init(vlan_pbmp_profile[unit]);
    102     }
    103 
    104     /* Create profile table cache( or re-init if it already exists */
    105     mem = PORT_BITMAP_PROFILEm;
    106     entry_dwords = sizeof(port_bitmap_profile_entry_t) / sizeof(uint32);
    107 
    108     SOC_IF_ERROR_RETURN(
    109         soc_profile_mem_create(
    110             unit, &mem, &entry_dwords, 1, vlan_pbmp_profile[unit]));
    111 
    112     /* Create a default entry with empty port bitmap */
    113     SOC_PBMP_CLEAR(pbmp);
    114     _bcm_th3_vlan_pbmp_profile_entry_add(unit, pbmp, &profile_idx);
    115 
    116 #if defined(BCM_WARM_BOOT_SUPPORT)
    117     if (SOC_WARM_BOOT(unit)) {
    118         /* Sync the SW profile data structure with actual indexes is use */
    119         for (mem_idx = 0 ; mem_idx < mem_entry_cnt ; mem_idx++) {
    120 
    121             SOC_IF_ERROR_RETURN(
    122                 READ_VLAN_2_TABm(unit, MEM_BLOCK_ANY, mem_idx, &vlan_2_entry));
    123 
    124             if (soc_mem_field32_get(unit, VLAN_2_TABm, &vlan_2_entry, VALIDf)) {
    125                 profile_idx = soc_mem_field32_get(
    126                     unit, VLAN_2_TABm, &vlan_2_entry, PORT_BITMAP_PROFILE_PTRf);
    127                 SOC_PROFILE_MEM_REFERENCE(
    128                     unit, vlan_pbmp_profile[unit], profile_idx, 1);
    129                 SOC_PROFILE_MEM_ENTRIES_PER_SET(
    130                     unit, vlan_pbmp_profile[unit], profile_idx, 1);
    131             }
    132         }
    133     }
    134 #endif /* BCM_WARM_BOOT_SUPPORT */
    135     return BCM_E_NONE;
    136 }
    137 
    138 /*
    139  * Function:
    140  *      _bcm_th3_vlan_pbmp_profile_destroy
    141  *
    142  * Purpose:
    143  *      to deinitialize hardware PORT_BITMAP_PROFILE and
    144  *      deallocate cached RAM memory for the hardware table.
    145  *
    146  * Parameters:
    147  *      unit - (IN)  Device Number
    148  *
    149  * Returns:
    150  *      BCM_E_FAIL
    151  *      BCM_E_NONE
    152  *
    153  * Notes:
    154  */
    155 int
    156 _bcm_th3_vlan_pbmp_profile_destroy(int unit) {
    157     int rv;
    158 
    159     if (vlan_pbmp_profile[unit]) {
    160         rv = soc_profile_mem_destroy(unit, vlan_pbmp_profile[unit]);
    161         if (BCM_FAILURE(rv)) {
    162             return BCM_E_FAIL;
    163         }
    164 
    165         sal_free(vlan_pbmp_profile[unit]);
    166         vlan_pbmp_profile[unit] = NULL;
    167     }
    168 
    169     return BCM_E_NONE;
    170 }
    171 
    172 /*
    173  * Function:
    174  *      _bcm_th3_vlan_pbmp_profile_entry_add
    175  *
    176  * Purpose:
    177  *      add a new entry to PORT_BITMAP_PROFILE table
    178  *
    179  * Parameters:
    180  *      unit         - (IN)  Device Number
    181  *      port_bitmap  - (IN)  Bitmap entry to be added into the memory
    182  *      index        - (OUT) Index into the profile table.
    183  *                           Only valid if the function returns BCM_E_NONE
    184  *
    185  * Returns:
    186  *      BCM_E_PARAM
    187  *      BCM_E_UNAVAIL
    188  *      BCM_E_FULL
    189  *      BCM_E_FAIL
    190  *      BCM_E_NONE
    191  *
    192  * Notes:
    193  */
    194 int
    195 _bcm_th3_vlan_pbmp_profile_entry_add(
    196     int unit, bcm_pbmp_t port_bitmap, uint32 *index) {
    197 
    198     int profile_idx;
    199     soc_error_t rv;
    200     port_bitmap_profile_entry_t vlan_pbmp_entry;
    201 
    202     /* Perform sanity checks */
    203     if (NULL == index) {
    204         return BCM_E_PARAM;
    205     }
    206     if (!soc_feature(unit, soc_feature_vlan_pbmp_profile_mgmt)) {
    207         return BCM_E_UNAVAIL;
    208     }
    209 
    210     /* Create an entry from the given port bitmap */
    211     sal_memset(&vlan_pbmp_entry, 0, sizeof(port_bitmap_profile_entry_t));
    212     soc_mem_pbmp_field_set(
    213         unit, PORT_BITMAP_PROFILEm, &vlan_pbmp_entry, BITMAPf, &port_bitmap);
    214 
    215     /* Insert the entry into the profile memory */
    216     rv = soc_profile_mem_single_table_add(
    217             unit, vlan_pbmp_profile[unit], &vlan_pbmp_entry, 1, &profile_idx);
    218 
    219     /* Convert the SOC return value to BCM return code */
    220     if (SOC_FAILURE(rv)) {
    221         return (((SOC_E_FULL == rv) || (SOC_E_RESOURCE == rv)) ?
    222                 BCM_E_FULL : BCM_E_FAIL);
    223     } else {
    224         /* Populate the given index buffer if the entry add succeeded */
    225         *index = profile_idx;
    226         return BCM_E_NONE;
    227     }
    228 }
    229 
    230 /*
    231  * Function:
    232  *      _bcm_th3_vlan_pbmp_profile_entry_delete
    233  *
    234  * Purpose:
    235  *      delete an entry from PORT_BITMAP_PROFILE table
    236  *
    237  * Parameters:
    238  *      unit         - (IN) Device Number
    239  *      index        - (IN) Index into the profile table.
    240  *
    241  * Returns:
    242  *      BCM_E_PARAM
    243  *      BCM_E_UNAVAIL
    244  *      BCM_E_NOT_FOUND
    245  *      BCM_E_FAIL
    246  *      BCM_E_NONE
    247  *
    248  * Notes:
    249  */
    250 int
    251 _bcm_th3_vlan_pbmp_profile_entry_delete(int unit, uint32 index) {
    252 
    253     soc_error_t rv;
    254 
    255     /* Perform sanity checks */
    256     if (!soc_feature(unit, soc_feature_vlan_pbmp_profile_mgmt)) {
    257         return BCM_E_UNAVAIL;
    258     }
    259 
    260     /* Call soc interface to delete an entry */
    261     rv = soc_profile_mem_delete(unit, vlan_pbmp_profile[unit], index);
    262 
    263     if (SOC_FAILURE(rv)) {
    264         return ((SOC_E_PARAM!=rv && SOC_E_NOT_FOUND!=rv) ? BCM_E_FAIL : rv);
    265     } else {
    266         return BCM_E_NONE;
    267     }
    268 }
    269 
    270 /*
    271  * Function:
    272  *      _bcm_th3_vlan_pbmp_port_entry_get
    273  *
    274  * Purpose:
    275  *      Retrieve the port bitmap for a given index.
    276  *
    277  * Parameters:
    278  *      unit     - (IN)  Device Number
    279  *      index    - (IN)  Index into the profile table.
    280  *      pbmp     - (OUT) Bitmap entry to be retrieved from the memory
    281  *
    282  * Returns:
    283  *      BCM_E_PARAM
    284  *      BCM_E_UNAVAIL
    285  *      BCM_E_NOT_FOUND
    286  *      BCM_E_FAIL
    287  *      BCM_E_NONE
    288  *
    289  * Notes:
    290  */
    291 int _bcm_th3_vlan_pbmp_profile_entry_get(
    292     int unit, uint32 index, bcm_pbmp_t *pbmp) {
    293 
    294     soc_error_t rv;
    295     port_bitmap_profile_entry_t vlan_pbmp_entry;
    296 
    297     /* Perform sanity checks */
    298     if (NULL == pbmp) {
    299         return BCM_E_PARAM;
    300     }
    301     if (!soc_feature(unit, soc_feature_vlan_pbmp_profile_mgmt)) {
    302         return BCM_E_UNAVAIL;
    303     }
    304 
    305     /* Retrieve an entry from the profile memory */
    306     sal_memset(&vlan_pbmp_entry, 0, sizeof(port_bitmap_profile_entry_t));
    307     rv = soc_profile_mem_single_table_get(
    308             unit, vlan_pbmp_profile[unit], (int) index, 1, &vlan_pbmp_entry);
    309 
    310     /* Convert the SOC return value to BCM return code */
    311     if (SOC_FAILURE(rv)) {
    312         return ((SOC_E_PARAM != rv && SOC_E_NOT_FOUND != rv) ? BCM_E_FAIL : rv);
    313     } else {
    314         /* Extract the port bitmap from the table entry */
    315         soc_mem_pbmp_field_get(
    316             unit, PORT_BITMAP_PROFILEm, &vlan_pbmp_entry, BITMAPf, pbmp);
    317         return BCM_E_NONE;
    318     }
    319 }
    320 
    321 /*
    322  * Function:
    323  *      _bcm_th3_vlan_pbmp_index_get
    324  *
    325  * Purpose:
    326  *      Retrieve the portbitmap profile memory
    327  *      index from corresponding VLAN memory
    328  *
    329  * Parameters:
    330  *      unit     - (IN)  Device Number
    331  *      vlan_id  - (IN)  VLAN Identifier
    332  *      index    - (OUT) Index into the profile table.
    333  *
    334  * Returns:
    335  *      BCM_E_PARAM
    336  *      BCM_E_UNAVAIL
    337  *      BCM_E_NOT_FOUND
    338  *      BCM_E_FAIL
    339  *      BCM_E_NONE
    340  *
    341  * Notes:
    342  *      The function assumes that the VLAN_2 memory is already locked
    343  *      and hence no locks are explicitly acquired or released
    344  */
    345 int _bcm_th3_vlan_pbmp_index_get(int unit, bcm_vlan_t vlan_id, uint32 *index) {
    346 
    347     soc_error_t         rv;
    348     vlan_2_tab_entry_t  vlan_2_entry;
    349     const soc_mem_t     mem = VLAN_2_TABm;
    350 
    351     /* Perform sanity checks */
    352     if (NULL == index || !BCM_VLAN_VALID(vlan_id)) {
    353         return BCM_E_PARAM;
    354     }
    355     if (!soc_feature(unit, soc_feature_vlan_pbmp_profile_mgmt)) {
    356         return BCM_E_UNAVAIL;
    357     }
    358 
    359     /* Read the corresponding VLAN table entry */
    360     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, (int)vlan_id, &vlan_2_entry);
    361     if (SOC_FAILURE(rv)) {
    362         return BCM_E_FAIL;
    363     }
    364 
    365     /* Check if the given VLAN is an existing one */
    366     if (!soc_mem_field32_get(unit, mem, &vlan_2_entry, VALIDf)) {
    367         return BCM_E_NOT_FOUND;
    368     }
    369 
    370     /* Populate the given buffer with the correct index value */
    371     *index =
    372         soc_mem_field32_get(unit, mem, &vlan_2_entry, PORT_BITMAP_PROFILE_PTRf);
    373 
    374     return BCM_E_NONE;
    375 }
    376 
    377 /*
    378  * Function:
    379  *      _bcm_th3_vlan_pbmp_index_set
    380  *
    381  * Purpose:
    382  *      Insert the portbitmap profile memory
    383  *      index to corresponding VLAN memory entry
    384  *
    385  * Parameters:
    386  *      unit     - (IN)  Device Number
    387  *      vlan_id  - (IN)  VLAN Identifier
    388  *      index    - (IN)  Index into the profile table.
    389  *
    390  * Returns:
    391  *      BCM_E_PARAM
    392  *      BCM_E_UNAVAIL
    393  *      BCM_E_NOT_FOUND
    394  *      BCM_E_FAIL
    395  *      BCM_E_NONE
    396  *
    397  * Notes:
    398  *      The function assumes that the VLAN_2 memory is already locked
    399  *      and hence no locks are explicitly acquired or released
    400  */
    401 int _bcm_th3_vlan_pbmp_index_set(int unit, bcm_vlan_t vlan_id, uint32 index)
    402 {
    403 
    404     soc_error_t         rv;
    405     vlan_2_tab_entry_t  vlan_2_entry;
    406     const soc_mem_t     mem = VLAN_2_TABm;
    407 
    408     /* Perform sanity checks */
    409     if (!BCM_VLAN_VALID(vlan_id)) {
    410         return BCM_E_PARAM;
    411     }
    412     
    413 
    414     if (!soc_feature(unit, soc_feature_vlan_pbmp_profile_mgmt)) {
    415         return BCM_E_UNAVAIL;
    416     }
    417 
    418     /* Read the corresponding VLAN table entry */
    419     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, (int)vlan_id, &vlan_2_entry);
    420     if (SOC_FAILURE(rv)) {
    421         return BCM_E_FAIL;
    422     }
    423 
    424     /* Check if the given VLAN is an existing one */
    425     if (!soc_mem_field32_get(unit, mem, &vlan_2_entry, VALIDf)) {
    426         return BCM_E_NOT_FOUND;
    427     }
    428 
    429     /* Populate the given buffer with the correct index value */
    430     soc_mem_field32_set(
    431         unit, mem, &vlan_2_entry, PORT_BITMAP_PROFILE_PTRf, index);
    432 
    433     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, (int) vlan_id, &vlan_2_entry);
    434 
    435     return (SOC_FAILURE(rv) ? BCM_E_FAIL : BCM_E_NONE);
    436 }
    437 
    438 /*
    439  * Function:
    440  *      _bcm_th3_vlan_pbmp_port_update
    441  *
    442  * Purpose:
    443  *      Add/Remove the ports in the given bitmap for a VLAN
    444  *      The table entry for the VLAN is provided as input
    445  *      Hence the profile index is set to the same entry
    446  *
    447  * Parameters:
    448  *      unit        - (IN)  Device Number
    449  *      vt          - (IN/OUT)  VLAN table entry.
    450  *      pbmp        - (IN) Bitmap of ports to be added/removed from the VLAN.
    451  *      operation   - (IN) 0 for Add, 1 for Remove
    452  *
    453  * Returns:
    454  *      BCM_E_PARAM
    455  *      BCM_E_UNAVAIL
    456  *      BCM_E_NOT_FOUND
    457  *      BCM_E_FAIL
    458  *      BCM_E_NONE
    459  *
    460  * Notes:
    461  */
    462 STATIC int
    463 _bcm_th3_vlan_pbmp_port_update(
    464     int unit, vlan_2_tab_entry_t *vt, bcm_pbmp_t *pbmp, uint8 operation)
    465 {
    466     int                 rv = BCM_E_NONE;
    467     uint32              old_profile_idx;
    468     uint32              new_profile_idx;
    469     bcm_pbmp_t          cur_pbmp, org_pbmp;
    470 
    471     if (0 != operation && 1 != operation) {
    472         return BCM_E_UNAVAIL;
    473     }
    474 
    475     BCM_PBMP_CLEAR(cur_pbmp);
    476 
    477     /* Retrieve the profile index from the VLAN table entry */
    478     old_profile_idx =
    479         soc_mem_field32_get(unit, VLAN_2_TABm, vt, PORT_BITMAP_PROFILE_PTRf);
    480 
    481     /* Retrieve the port bmp from the profile table given the index */
    482     BCM_IF_ERROR_RETURN(
    483         _bcm_th3_vlan_pbmp_profile_entry_get(
    484             unit, old_profile_idx, &cur_pbmp));
    485 
    486     /* Cache the retrieved port bitmap for later use */
    487     BCM_PBMP_ASSIGN(org_pbmp, cur_pbmp);
    488 
    489     /* Perform read-modify-write operation on bitmap */
    490     if (operation) {
    491         BCM_PBMP_REMOVE(cur_pbmp, *pbmp);
    492     } else {
    493         BCM_PBMP_OR(cur_pbmp, *pbmp);
    494     }
    495 
    496     /* Only perform the profile modification if the pbmp has changed */
    497     if (BCM_PBMP_NEQ(cur_pbmp, org_pbmp)) {
    498 
    499         /* First delete the old profile entry from the profile table */
    500         rv =  _bcm_th3_vlan_pbmp_profile_entry_delete(unit, old_profile_idx);
    501 
    502         if (BCM_SUCCESS(rv)) {
    503             /* Insert the modified port bitmap into the profile table */
    504             rv = _bcm_th3_vlan_pbmp_profile_entry_add(unit,
    505                                                       cur_pbmp,
    506                                                       &new_profile_idx);
    507 
    508             /* If new entry add failed then add back the old pbmp */
    509             if (BCM_FAILURE(rv)) {
    510                 if (BCM_SUCCESS(
    511                         _bcm_th3_vlan_pbmp_profile_entry_add(unit,
    512                                                         org_pbmp,
    513                                                         &old_profile_idx))) {
    514                     /* Set the old index into the given VLAN table entry */
    515                     soc_mem_field32_set(unit, VLAN_2_TABm,
    516                         vt, PORT_BITMAP_PROFILE_PTRf, old_profile_idx);
    517                 }
    518             } else {
    519                 /* Set the new profile index into the given VLAN table entry */
    520                 soc_mem_field32_set(unit,
    521                     VLAN_2_TABm, vt, PORT_BITMAP_PROFILE_PTRf, new_profile_idx);
    522             }
    523         }
    524     }
    525     return rv;
    526 }
    527 
    528 /*
    529  * Function:
    530  *      _bcm_th3_vlan_pbmp_port_add
    531  *
    532  * Purpose:
    533  *      Add the ports in the given bitmap for a VLAN
    534  *      The table entry for the VLAN is provided as input
    535  *      Hence the profile index is set to the same entry
    536  *
    537  * Parameters:
    538  *      unit    - (IN)  Device Number
    539  *      entry   - (IN/OUT)  VLAN table entry.
    540  *      pbmp    - (IN) Bitmap of ports to be added from the VLAN.
    541  *
    542  * Returns:
    543  *      BCM_E_PARAM
    544  *      BCM_E_UNAVAIL
    545  *      BCM_E_NOT_FOUND
    546  *      BCM_E_FAIL
    547  *      BCM_E_NONE
    548  *
    549  * Notes:
    550  *      It is assumed that the given vlan entry is genuine and has
    551  *      all the relevant parameters in correct state. Also the VLAN
    552  *      valid bit is assumed to be set to begin with.
    553  */
    554 int _bcm_th3_vlan_pbmp_port_add(int unit, void *entry, bcm_pbmp_t *pbmp)
    555 {
    556     /* Perform sanity checks */
    557     if (NULL == entry || NULL == pbmp) {
    558         return BCM_E_PARAM;
    559     }
    560     if (!soc_feature(unit, soc_feature_vlan_pbmp_profile_mgmt)) {
    561         return BCM_E_UNAVAIL;
    562     }
    563 
    564     return(_bcm_th3_vlan_pbmp_port_update(unit, entry, pbmp, 0));
    565 }
    566 
    567 /*
    568  * Function:
    569  *      _bcm_th3_vlan_pbmp_port_remove
    570  *
    571  * Purpose:
    572  *      Remove the ports in the given bitmap for a VLAN
    573  *      The table entry for the VLAN is provided as input
    574  *      Hence the profile index is set to the same entry
    575  *
    576  * Parameters:
    577  *      unit    - (IN)  Device Number
    578  *      entry   - (IN/OUT)  VLAN table entry.
    579  *      pbmp    - (IN) Bitmap of ports to be removed from the VLAN.
    580  *
    581  * Returns:
    582  *      BCM_E_PARAM
    583  *      BCM_E_UNAVAIL
    584  *      BCM_E_NOT_FOUND
    585  *      BCM_E_FAIL
    586  *      BCM_E_NONE
    587  *
    588  * Notes:
    589  *      It is assumed that the given vlan entry is genuine and has
    590  *      all the relevant parameters in correct state. Also the VLAN
    591  *      valid bit is assumed to be set to begin with.
    592  */
    593 int _bcm_th3_vlan_pbmp_port_remove(int unit, void *entry, bcm_pbmp_t *pbmp)
    594 {
    595     /* Perform sanity checks */
    596     if (NULL == entry || NULL == pbmp) {
    597         return BCM_E_PARAM;
    598     }
    599     if (!soc_feature(unit, soc_feature_vlan_pbmp_profile_mgmt)) {
    600         return BCM_E_UNAVAIL;
    601     }
    602 
    603     return(_bcm_th3_vlan_pbmp_port_update(unit, entry, pbmp, 1));
    604 }
    605 
    606 /*
    607  * Function:
    608  *      _bcm_th3_vlan_action_profile_init
    609  *
    610  * Purpose  : to initialize hardware ING_VLAN_TAG_ACTION_PROFILE and
    611  *            EGR_VLAN_TAG_ACTION_PROFILE tables and allocate memory
    612  *            to cache hardware tables in RAM.
    613  *
    614  * Parameters:
    615  *      unit         - (IN)  Device Number
    616  *
    617  * Returns:
    618  *      BCM_E_XXX
    619  *
    620  * Notes:
    621  *      Allocate memory to cache the profile tables and initialize.
    622  *      If memory to cache the profile table is already allocated, just
    623  *      initialize the table.
    624  */
    625 int
    626 _bcm_th3_vlan_action_profile_init(int unit)
    627 {
    628     int i, idx, num_ports;
    629     ing_vlan_tag_action_profile_entry_t ing_profile_entry;
    630     egr_vlan_tag_action_profile_entry_t egr_profile_entry;
    631     uint32 rval;
    632     soc_mem_t mem;
    633     int temp_index;
    634     int entry_idxmax;
    635     int entry_words;
    636     int entry_idxmin = 0;
    637     const uint32 ing_ent_sz = sizeof(ing_vlan_tag_action_profile_entry_t);
    638 
    639     /* Initialize the ING_VLAN_TAG_ACTION_PROFILE table */
    640     if (ing_action_profile[unit] == NULL) {
    641         ing_action_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t),
    642                                              "Ing Action Profile Mem");
    643         if (ing_action_profile[unit] == NULL) {
    644             return BCM_E_MEMORY;
    645         }
    646         soc_profile_mem_t_init(ing_action_profile[unit]);
    647     }
    648 
    649     mem = ING_VLAN_TAG_ACTION_PROFILEm;
    650     entry_idxmax = soc_mem_index_max(unit, mem);
    651     entry_words = ing_ent_sz / sizeof(uint32);
    652     if (SOC_FAILURE(
    653             soc_profile_mem_index_create(unit, &mem, &entry_words,
    654                                      &entry_idxmin, &entry_idxmax,
    655                                      NULL, 1, ing_action_profile[unit]))) {
    656         sal_free(ing_action_profile[unit]);
    657         ing_action_profile[unit] = NULL;
    658         return BCM_E_FAIL;
    659     }
    660 
    661     if (SOC_WARM_BOOT(unit)) {
    662         soc_mem_t port_mem = PORT_TABm;
    663 
    664         /* Increment the ref count for all ports */
    665         for (i = 0; i < soc_mem_index_count(unit, port_mem); i++) {
    666             SOC_IF_ERROR_RETURN(_bcm_esw_port_tab_get(unit, i,
    667                                 TAG_ACTION_PROFILE_PTRf, &idx));
    668             SOC_IF_ERROR_RETURN(
    669                 soc_profile_mem_reference(unit, ing_action_profile[unit],
    670                 idx - entry_idxmin, 1));
    671             SOC_PROFILE_MEM_ENTRIES_PER_SET(unit, ing_action_profile[unit],
    672                                             idx - entry_idxmin, 1);
    673         }
    674 
    675         /* One extra incr to preserve location ING_ACTION_PROFILE_DEFAULT */
    676         SOC_IF_ERROR_RETURN(
    677             soc_profile_mem_reference(unit, ing_action_profile[unit],
    678             ING_ACTION_PROFILE_DEFAULT, 1));
    679     } else {
    680         /* Initialize the ING_ACTION_PROFILE_DEFAULT. For untagged and
    681          * inner-tagged packets, always add an outer tag.
    682          */
    683         soc_mem_t port_mem = PORT_TABm;
    684         sal_memset(&ing_profile_entry, 0, ing_ent_sz);
    685         soc_mem_field32_set(unit, mem, &ing_profile_entry, UT_OTAG_ACTIONf,
    686                             _BCM_TRX_TAG_ACTION_ENCODE(bcmVlanActionAdd));
    687         if (soc_feature(unit, soc_feature_vlan_pri_cfi_action)) {
    688             soc_mem_field32_set(unit, mem, &ing_profile_entry, UT_OPRI_ACTIONf,
    689                                 _BCM_TRX_PRI_CFI_ACTION_ENCODE(bcmVlanActionAdd));
    690             soc_mem_field32_set(unit, mem, &ing_profile_entry, UT_OCFI_ACTIONf,
    691                                 _BCM_TRX_PRI_CFI_ACTION_ENCODE(bcmVlanActionAdd));
    692         }
    693         soc_mem_field32_set(unit, mem, &ing_profile_entry, SOT_POTAG_ACTIONf,
    694                             _BCM_TRX_TAG_ACTION_ENCODE(bcmVlanActionReplace));
    695         SOC_IF_ERROR_RETURN
    696             (soc_profile_mem_single_table_add(unit,
    697                 ing_action_profile[unit], &ing_profile_entry, 1, &temp_index));
    698 
    699         for (i = 0; i < soc_mem_index_count(unit, port_mem); i++) {
    700             SOC_IF_ERROR_RETURN(
    701                 soc_profile_mem_reference(unit, ing_action_profile[unit],
    702                 ING_ACTION_PROFILE_DEFAULT, 1));
    703         }
    704     }
    705 
    706     /* Initialize the EGR_VLAN_TAG_ACTION_PROFILE table */
    707     if (egr_action_profile[unit] == NULL) {
    708         egr_action_profile[unit] = sal_alloc(sizeof(soc_profile_mem_t),
    709                                              "Egr Action Profile Mem");
    710         if (egr_action_profile[unit] == NULL) {
    711             return BCM_E_MEMORY;
    712         }
    713         soc_profile_mem_t_init(egr_action_profile[unit]);
    714     }
    715 
    716     /* Create profile table cache (or re-init if it already exists) */
    717     mem = EGR_VLAN_TAG_ACTION_PROFILEm;
    718     entry_words = sizeof(egr_vlan_tag_action_profile_entry_t) / sizeof(uint32);
    719     SOC_IF_ERROR_RETURN(soc_profile_mem_create(unit, &mem, &entry_words, 1,
    720                                                egr_action_profile[unit]));
    721 
    722     SOC_PBMP_COUNT(PBMP_ALL(unit), num_ports);
    723     if (SOC_WARM_BOOT(unit)) {
    724         /* Increment the ref count for all ports */
    725         PBMP_ALL_ITER(unit, i) {
    726             SOC_IF_ERROR_RETURN
    727                 (READ_EGR_VLAN_CONTROL_3r(unit, i, &rval));
    728             idx = soc_reg_field_get(unit, EGR_VLAN_CONTROL_3r,
    729                     rval, TAG_ACTION_PROFILE_PTRf);
    730             SOC_PROFILE_MEM_REFERENCE(unit, egr_action_profile[unit], idx, 1);
    731             SOC_PROFILE_MEM_ENTRIES_PER_SET(
    732                 unit, egr_action_profile[unit], idx, 1);
    733         }
    734 
    735         /* 1 extra increment to preserve location EGR_ACTION_PROFILE_DEFAULT */
    736         SOC_PROFILE_MEM_REFERENCE(unit, egr_action_profile[unit],
    737                               BCM_TH3_EGR_ACTION_PROFILE_DEFAULT, 1);
    738     } else {
    739         /* Initialize the BCM_TH3_EGR_ACTION_PROFILE_DEFAULT to have all
    740          * actions as NOP (0).
    741          */
    742         sal_memset(&egr_profile_entry, 0,
    743                     sizeof(egr_vlan_tag_action_profile_entry_t));
    744         SOC_IF_ERROR_RETURN
    745             (soc_profile_mem_single_table_add(unit,
    746                 egr_action_profile[unit], &egr_profile_entry, 1, &temp_index));
    747 
    748         /* Increment the ref count for all ports */
    749         SOC_PROFILE_MEM_REFERENCE(unit, egr_action_profile[unit],
    750                                 BCM_TH3_EGR_ACTION_PROFILE_DEFAULT, num_ports);
    751     }
    752 
    753     return BCM_E_NONE;
    754 }
    755 
    756 /*
    757  * Function:
    758  *      _bcm_th3_vlan_action_profile_detach
    759  *
    760  * Purpose  : to deallocate resources for hardware
    761  *            ING_VLAN_TAG_ACTION_PROFILE and
    762  *            EGR_VLAN_TAG_ACTION_PROFILE tables and
    763  *            their caches correspondingly in RAM.
    764  *
    765  * Parameters:
    766  *      unit     - (IN)  Device Number
    767  *
    768  * Returns:
    769  *      BCM_E_XXX
    770  *
    771  * Notes:
    772  */
    773 int
    774 _bcm_th3_vlan_action_profile_detach(int unit)
    775 {
    776     int rv;
    777 
    778     /* De-initialize the ING_VLAN_TAG_ACTION_PROFILE table */
    779     if (ing_action_profile[unit]) {
    780         rv = soc_profile_mem_destroy(unit, ing_action_profile[unit]);
    781         BCM_IF_ERROR_RETURN(rv);
    782 
    783         sal_free(ing_action_profile[unit]);
    784         ing_action_profile[unit] = NULL;
    785     }
    786 
    787     /* De-initialize the EGR_VLAN_TAG_ACTION_PROFILE table */
    788     if (egr_action_profile[unit]) {
    789         rv = soc_profile_mem_destroy(unit, egr_action_profile[unit]);
    790         BCM_IF_ERROR_RETURN(rv);
    791 
    792         sal_free(egr_action_profile[unit]);
    793         egr_action_profile[unit] = NULL;
    794     }
    795 
    796     return BCM_E_NONE;
    797 }
    798 
    799 /*
    800  * Function:
    801  *      _bcm_th3_vlan_action_verify
    802  *
    803  * Purpose  : to validate all members of action structure
    804  *
    805  * Parameters:
    806  *      unit     - (IN)  Device Number
    807  *      action   - (IN)  tag actions to be verified
    808  *
    809  * Returns:
    810  *      BCM_E_NONE
    811  *      BCM_E_PARAM
    812  *
    813  * Notes:
    814  */
    815 STATIC int
    816 _bcm_th3_vlan_action_verify(int unit, bcm_vlan_action_set_t *action)
    817 {
    818     if (NULL == action) {
    819         return BCM_E_PARAM;
    820     }
    821     VLAN_CHK_ID(unit, action->new_outer_vlan);
    822 
    823     if (soc_feature(unit, soc_feature_vlan_pri_cfi_action)) {
    824         if (action->priority < -1 ||
    825             action->priority > 7 || action->new_outer_cfi > 1) {
    826             return BCM_E_PARAM;
    827         }
    828     }
    829 
    830     /* Double Tag operations not supported */
    831     if ((bcmVlanActionNone != action->dt_outer) ||
    832         (bcmVlanActionNone != action->dt_outer_prio) ||
    833         (bcmVlanActionNone != action->dt_outer_pkt_prio) ||
    834         (bcmVlanActionNone != action->dt_outer_cfi) ||
    835         (bcmVlanActionNone != action->dt_inner) ||
    836         (bcmVlanActionNone != action->dt_inner_prio) ||
    837         (bcmVlanActionNone != action->dt_inner_pkt_prio) ||
    838         (bcmVlanActionNone != action->dt_inner_cfi)) {
    839         return BCM_E_UNAVAIL;
    840     }
    841 
    842     /* Two tags not supported */
    843     if ((bcmVlanActionNone != action->ot_inner) ||
    844         (bcmVlanActionNone != action->ot_inner_pkt_prio) ||
    845         (bcmVlanActionNone != action->ot_inner_cfi) ||
    846         (bcmVlanActionNone != action->it_outer) ||
    847         (bcmVlanActionNone != action->it_outer_pkt_prio) ||
    848         (bcmVlanActionNone != action->it_outer_cfi)) {
    849         return BCM_E_UNAVAIL;
    850     }
    851 
    852     /* No Inner tag operations supported */
    853     if ((bcmVlanActionNone != action->it_inner) ||
    854         (bcmVlanActionNone != action->it_inner_prio) ||
    855         (bcmVlanActionNone != action->it_inner_pkt_prio) ||
    856         (bcmVlanActionNone != action->it_inner_cfi) ||
    857         (bcmVlanActionNone != action->ut_inner) ||
    858         (bcmVlanActionNone != action->ut_inner_pkt_prio) ||
    859         (bcmVlanActionNone != action->ut_inner_cfi)) {
    860         return BCM_E_UNAVAIL;
    861     }
    862 
    863     switch (action->ot_outer) {
    864         case bcmVlanActionNone:
    865         case bcmVlanActionReplace:
    866         case bcmVlanActionDelete:
    867             break;
    868         default:
    869             return BCM_E_PARAM;
    870     }
    871 
    872     switch (action->ot_outer_prio) {
    873         case bcmVlanActionNone:
    874         case bcmVlanActionReplace:
    875         case bcmVlanActionDelete:
    876             break;
    877         default:
    878             return BCM_E_PARAM;
    879     }
    880 
    881     switch (action->ot_outer_pkt_prio) {
    882         case bcmVlanActionNone:
    883             break;
    884         case bcmVlanActionReplace:
    885             if (!soc_feature(unit, soc_feature_vlan_pri_cfi_action)) {
    886                 return BCM_E_UNAVAIL;
    887             }
    888             break;
    889         default:
    890             return BCM_E_PARAM;
    891     }
    892 
    893     switch (action->ot_outer_cfi) {
    894         case bcmVlanActionNone:
    895             break;
    896         case bcmVlanActionReplace:
    897             if (!soc_feature(unit, soc_feature_vlan_pri_cfi_action)) {
    898                 return BCM_E_UNAVAIL;
    899             }
    900             break;
    901         default:
    902             return BCM_E_PARAM;
    903     }
    904 
    905     switch (action->ut_outer) {
    906         case bcmVlanActionNone:
    907         case bcmVlanActionAdd:
    908             break;
    909         default:
    910             return BCM_E_PARAM;
    911     }
    912 
    913     switch (action->ut_outer_pkt_prio) {
    914         case bcmVlanActionNone:
    915             break;
    916         case bcmVlanActionAdd:
    917             if (!soc_feature(unit, soc_feature_vlan_pri_cfi_action)) {
    918                 return BCM_E_UNAVAIL;
    919             }
    920             break;
    921         default:
    922             return BCM_E_PARAM;
    923     }
    924 
    925     switch (action->ut_outer_cfi) {
    926         case bcmVlanActionNone:
    927             break;
    928         case bcmVlanActionAdd:
    929             if (!soc_feature(unit, soc_feature_vlan_pri_cfi_action)) {
    930                 return BCM_E_UNAVAIL;
    931             }
    932             break;
    933         default:
    934             return BCM_E_PARAM;
    935     }
    936 
    937     return BCM_E_NONE;
    938 }
    939 
    940 /*
    941  * Function:
    942  *      _bcm_th3_vlan_action_profile_entry_add
    943  *
    944  * Purpose  : add a new entry to the given vlan
    945  *            action profile table at given index
    946  *
    947  * Parameters:
    948  *      unit     - (IN)  Device Number
    949  *      vtap_mem - (IN)  VLAN Tag Action Profile Memory
    950  *      action   - (IN)  tag actions to be added
    951  *      index    - (IN)  Index of profile memory where to add the entry
    952  *
    953  * Returns:
    954  *      BCM_E_XXX
    955  *
    956  * Notes:
    957  */
    958 STATIC int
    959 _bcm_th3_vlan_action_profile_entry_add(int unit,
    960                                         soc_mem_t vtap_mem,
    961                                         bcm_vlan_action_set_t *action,
    962                                         int *index)
    963 {
    964     soc_profile_mem_t *profile = NULL;
    965     egr_vlan_tag_action_profile_entry_t egr_vtap_entry;
    966     ing_vlan_tag_action_profile_entry_t ing_vtap_entry;
    967     void *vtap_entry = NULL;
    968 
    969     if (ING_VLAN_TAG_ACTION_PROFILEm == vtap_mem) {
    970         profile = ing_action_profile[unit];
    971         vtap_entry = (void *)&ing_vtap_entry;
    972         sal_memset(vtap_entry, 0, sizeof(ing_vlan_tag_action_profile_entry_t));
    973     } else if (EGR_VLAN_TAG_ACTION_PROFILEm ==  vtap_mem) {
    974         profile = egr_action_profile[unit];
    975         vtap_entry = (void *)&egr_vtap_entry;
    976         sal_memset(vtap_entry, 0, sizeof(egr_vlan_tag_action_profile_entry_t));
    977     } else {
    978         return BCM_E_PARAM;
    979     }
    980 
    981     soc_mem_field32_set(unit, vtap_mem, vtap_entry, SOT_OTAG_ACTIONf,
    982                         _BCM_TRX_TAG_ACTION_ENCODE(action->ot_outer));
    983     soc_mem_field32_set(unit, vtap_mem, vtap_entry, SOT_POTAG_ACTIONf,
    984                         _BCM_TRX_TAG_ACTION_ENCODE(action->ot_outer_prio));
    985     soc_mem_field32_set(unit, vtap_mem, vtap_entry, UT_OTAG_ACTIONf,
    986                         _BCM_TRX_TAG_ACTION_ENCODE(action->ut_outer));
    987 
    988     if (soc_feature(unit, soc_feature_vlan_pri_cfi_action)) {
    989         soc_mem_field32_set
    990             (unit, vtap_mem, vtap_entry, SOT_OPRI_ACTIONf,
    991              _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->ot_outer_pkt_prio));
    992         soc_mem_field32_set
    993             (unit, vtap_mem, vtap_entry, SOT_OCFI_ACTIONf,
    994              _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->ot_outer_cfi));
    995         soc_mem_field32_set
    996             (unit, vtap_mem, vtap_entry, UT_OPRI_ACTIONf,
    997              _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->ut_outer_pkt_prio));
    998         soc_mem_field32_set
    999             (unit, vtap_mem, vtap_entry, UT_OCFI_ACTIONf,
   1000              _BCM_TRX_PRI_CFI_ACTION_ENCODE(action->ut_outer_cfi));
   1001     }
   1002 
   1003     return
   1004         (soc_profile_mem_single_table_add(unit, profile, vtap_entry, 1, index));
   1005 }
   1006 
   1007 /*
   1008  * Function:
   1009  *      _bcm_th3_ing_vlan_action_profile_entry_add
   1010  *
   1011  * Purpose  : add a new entry to the ING_VLAN_TAG_ACTION_PROFILE
   1012  *            memory at given index
   1013  *
   1014  * Parameters:
   1015  *      unit     - (IN)  Device Number
   1016  *      action   - (IN)  tag actions to be added
   1017  *      index    - (IN)  Index of profile memory where to add the entry
   1018  *
   1019  * Returns:
   1020  *      BCM_E_XXX
   1021  *
   1022  * Notes:
   1023  *      It is assumed that the action data structure is thorougly scrutinized
   1024  *      before the function is called. Hence no additional checks are performed
   1025  */
   1026 int
   1027 _bcm_th3_ing_vlan_action_profile_entry_add(int unit,
   1028                                       bcm_vlan_action_set_t *action,
   1029                                       int *index)
   1030 {
   1031     return(_bcm_th3_vlan_action_profile_entry_add(unit,
   1032                                             ING_VLAN_TAG_ACTION_PROFILEm,
   1033                                             action,
   1034                                             index));
   1035 }
   1036 
   1037 /*
   1038  * Function:
   1039  *      _bcm_th3_egr_vlan_action_profile_entry_add
   1040  *
   1041  * Purpose  : add a new entry to the EGR_VLAN_TAG_ACTION_PROFILE
   1042  *            memory at given index
   1043  *
   1044  * Parameters:
   1045  *      unit     - (IN)  Device Number
   1046  *      action   - (IN)  tag actions to be added
   1047  *      index    - (IN)  Index of profile memory where to add the entry
   1048  *
   1049  * Returns:
   1050  *      BCM_E_XXX
   1051  *
   1052  * Notes:
   1053  *      It is assumed that the action data structure is thorougly scrutinized
   1054  *      before the function is called. Hence no additional checks are performed
   1055  */
   1056 int
   1057 _bcm_th3_egr_vlan_action_profile_entry_add(int unit,
   1058                                       bcm_vlan_action_set_t *action,
   1059                                       int *index)
   1060 {
   1061     return(_bcm_th3_vlan_action_profile_entry_add(unit,
   1062                                             EGR_VLAN_TAG_ACTION_PROFILEm,
   1063                                             action,
   1064                                             index));
   1065 }
   1066 
   1067 /*
   1068  * Function:
   1069  *      _bcm_th3_vlan_action_profile_entry_decode
   1070  *
   1071  * Purpose  : Decode and save the tag actions from the given
   1072  *            memory entry for the given TAG Action memory
   1073  *
   1074  * Parameters:
   1075  *      unit        - (IN)  Device Number
   1076  *      mem         - (IN)  VLAN Tag Action memory
   1077  *      vtap_entry  - (IN)  Retrieved entry from the memory 'mem'
   1078  *      action      - (OUT)  save the decoded tag actions here
   1079  *
   1080  * Returns:
   1081  *
   1082  * Notes:
   1083  */
   1084 STATIC void
   1085 _bcm_th3_vlan_action_profile_entry_decode(int unit,
   1086                                             soc_mem_t mem,
   1087                                             void *vtap_entry,
   1088                                             bcm_vlan_action_set_t *action)
   1089 {
   1090     uint32 val;
   1091 
   1092     val = soc_mem_field32_get(unit, mem, vtap_entry, SOT_OTAG_ACTIONf);
   1093     action->ot_outer = _BCM_TRX_TAG_ACTION_DECODE(val);
   1094 
   1095     val = soc_mem_field32_get(unit, mem, vtap_entry, SOT_POTAG_ACTIONf);
   1096     action->ot_outer_prio = _BCM_TRX_TAG_ACTION_DECODE(val);
   1097 
   1098     val = soc_mem_field32_get(unit, mem, vtap_entry, UT_OTAG_ACTIONf);
   1099     action->ut_outer = _BCM_TRX_TAG_ACTION_DECODE(val);
   1100 
   1101     if (soc_feature(unit, soc_feature_vlan_pri_cfi_action)) {
   1102         val = soc_mem_field32_get(unit, mem, vtap_entry, SOT_OPRI_ACTIONf);
   1103         action->ot_outer_pkt_prio = _BCM_TRX_PRI_CFI_ACTION_DECODE(val);
   1104 
   1105         val = soc_mem_field32_get(unit, mem, vtap_entry, SOT_OCFI_ACTIONf);
   1106         action->ot_outer_cfi = _BCM_TRX_PRI_CFI_ACTION_DECODE(val);
   1107 
   1108         val = soc_mem_field32_get(unit, mem, vtap_entry, UT_OPRI_ACTIONf);
   1109         action->ut_outer_pkt_prio = _BCM_TRX_PRI_CFI_ACTION_DECODE(val);
   1110 
   1111         val = soc_mem_field32_get(unit, mem, vtap_entry, UT_OCFI_ACTIONf);
   1112         action->ut_outer_cfi = _BCM_TRX_PRI_CFI_ACTION_DECODE(val);
   1113     } else {
   1114         action->ot_outer_pkt_prio = bcmVlanActionNone;
   1115         action->ot_outer_cfi = bcmVlanActionNone;
   1116         action->ut_outer_pkt_prio = bcmVlanActionNone;
   1117         action->ut_outer_cfi = bcmVlanActionNone;
   1118     }
   1119 
   1120     action->dt_outer =
   1121     action->dt_outer_prio =
   1122     action->dt_outer_pkt_prio =
   1123     action->dt_outer_cfi =
   1124     action->dt_inner =
   1125     action->dt_inner_prio =
   1126     action->dt_inner_pkt_prio =
   1127     action->dt_inner_cfi =
   1128     action->ot_inner =
   1129     action->ot_inner_pkt_prio =
   1130     action->ot_inner_cfi =
   1131     action->it_outer_pkt_prio =
   1132     action->it_outer_cfi =
   1133     action->it_outer =
   1134     action->it_inner_pkt_prio =
   1135     action->it_inner_cfi =
   1136     action->it_inner =
   1137     action->it_inner_prio =
   1138     action->ut_inner =
   1139     action->ut_inner_cfi =
   1140     action->ut_inner_pkt_prio = bcmVlanActionNone;
   1141 }
   1142 
   1143 /*
   1144  * Function:
   1145  *      _bcm_th3_ing_vlan_action_profile_entry_get
   1146  *
   1147  * Purpose  : get tag actions for given index to the Ingress VLAN Tag action
   1148  *
   1149  * Parameters:
   1150  *      unit    - (IN)  Device Number
   1151  *      action  - (OUT)  save the decoded tag actions here
   1152  *      index   - (IN)  index to the ING_VLAN_TAG_ACTION_PROFILE
   1153  *
   1154  * Returns:
   1155  *
   1156  * Notes:
   1157  */
   1158 void
   1159 _bcm_th3_ing_vlan_action_profile_entry_get(int unit,
   1160                                       bcm_vlan_action_set_t *action,
   1161                                       int index)
   1162 {
   1163     ing_vlan_tag_action_profile_entry_t ing_vtap_entry;
   1164 
   1165     sal_memset(&ing_vtap_entry, 0, sizeof(ing_vlan_tag_action_profile_entry_t));
   1166 
   1167     /* Retrieve an entry from the profile memory */
   1168     (void) soc_profile_mem_single_table_get(
   1169             unit, ing_action_profile[unit], index, 1, &ing_vtap_entry);
   1170 
   1171     _bcm_th3_vlan_action_profile_entry_decode(unit,
   1172                 ING_VLAN_TAG_ACTION_PROFILEm, &ing_vtap_entry, action);
   1173 }
   1174 
   1175 /*
   1176  * Function:
   1177  *      _bcm_th3_egr_vlan_action_profile_entry_get
   1178  *
   1179  * Purpose  : get a copy of cached vlan action profile table
   1180  *
   1181  * Parameters:
   1182  *      unit    - (IN)  Device Number
   1183  *      action  - (OUT)  save the decoded tag actions here
   1184  *      index   - (IN)  index to the ING_VLAN_TAG_ACTION_PROFILE
   1185  *
   1186  * Returns:
   1187  *
   1188  * Notes:
   1189  */
   1190 void
   1191 _bcm_th3_egr_vlan_action_profile_entry_get(int unit,
   1192                                           bcm_vlan_action_set_t *action,
   1193                                           uint32 index)
   1194 {
   1195     egr_vlan_tag_action_profile_entry_t *vtap_entry;
   1196 
   1197     vtap_entry = SOC_PROFILE_MEM_ENTRY(unit, egr_action_profile[unit],
   1198                                   egr_vlan_tag_action_profile_entry_t *,
   1199                                   index);
   1200     _bcm_th3_vlan_action_profile_entry_decode(unit,
   1201                 EGR_VLAN_TAG_ACTION_PROFILEm, vtap_entry, action);
   1202 }
   1203 
   1204 /*
   1205  * Function:
   1206  *      _bcm_th3_ing_vlan_action_profile_entry_delete
   1207  *
   1208  * Purpose  : remove an entry from Ingress vlan action profile table
   1209  *
   1210  * Parameters:
   1211  *      unit    - (IN)  Device Number
   1212  *      index   - (IN)  index of the entry to be deleted
   1213  *
   1214  * Returns:
   1215  *      BCM_E_XXX
   1216  *
   1217  * Notes:
   1218  */
   1219 int
   1220 _bcm_th3_ing_vlan_action_profile_entry_delete(int unit, uint32 index)
   1221 {
   1222     return soc_profile_mem_delete(unit, ing_action_profile[unit], index);
   1223 }
   1224 
   1225 /*
   1226  * Function:
   1227  *      _bcm_th3_egr_vlan_action_profile_entry_delete
   1228  *
   1229  * Purpose  : remove an entry from Egress vlan action profile table
   1230  *
   1231  * Parameters:
   1232  *      unit    - (IN)  Device Number
   1233  *      index   - (IN)  index of the entry to be deleted
   1234  *
   1235  * Returns:
   1236  *      BCM_E_XXX
   1237  *
   1238  * Notes:
   1239  */
   1240 int
   1241 _bcm_th3_egr_vlan_action_profile_entry_delete(int unit, uint32 index)
   1242 {
   1243     return soc_profile_mem_delete(unit, egr_action_profile[unit], index);
   1244 }
   1245 
   1246 /*
   1247  * Function:
   1248  *      _bcm_th3_egr_vlan_action_profile_entry_increment
   1249  *
   1250  * Purpose  : increment the refcount for default egr vlan action profile table
   1251  *             entry
   1252  *
   1253  * Parameters:
   1254  *      unit - (IN) BCM unit.
   1255  *      index - (IN) Profile table entry index
   1256  *
   1257  * Returns:
   1258  *
   1259  * Notes:
   1260  */
   1261 void
   1262 _bcm_th3_egr_vlan_action_profile_entry_increment(int unit, uint32 index)
   1263 {
   1264     soc_profile_mem_reference(unit, egr_action_profile[unit], index, 1);
   1265 }
   1266 
   1267 /*
   1268  * Function:
   1269  *      _bcm_th3_vlan_port_egress_default_action_set
   1270  *
   1271  * Purpose:
   1272  *      Set the egress port's default vlan tag actions
   1273  *
   1274  * Parameters:
   1275  *      unit       - (IN) BCM unit.
   1276  *      port       - (IN) Port number.
   1277  *      action     - (IN) Vlan tag actions
   1278  *
   1279  * Returns:
   1280  *      BCM_E_XXX
   1281  *
   1282  * Notes:
   1283  */
   1284 int
   1285 _bcm_th3_vlan_port_egress_default_action_set(int unit, bcm_port_t port,
   1286                                             bcm_vlan_action_set_t *action)
   1287 {
   1288     int rv;
   1289     uint32 rval;
   1290     int profile_idx, old_profile_idx;
   1291 
   1292     BCM_IF_ERROR_RETURN(_bcm_th3_vlan_action_verify(unit, action));
   1293     BCM_IF_ERROR_RETURN(
   1294         _bcm_th3_egr_vlan_action_profile_entry_add(unit, action, &profile_idx));
   1295 
   1296     rv = READ_EGR_VLAN_CONTROL_2r(unit, port, &rval);
   1297     if (rv < 0) {
   1298         goto error;
   1299     }
   1300 
   1301     if (-1 == action->priority) {
   1302         /* point to default map profile(0) for default priority action */
   1303         soc_reg_field_set(unit, EGR_VLAN_CONTROL_2r, &rval, OPRI_CFI_SELf, 1);
   1304     } else {
   1305         soc_reg_field_set(unit, EGR_VLAN_CONTROL_2r, &rval, OPRI_CFI_SELf, 0);
   1306         soc_reg_field_set(
   1307                     unit, EGR_VLAN_CONTROL_2r, &rval, OPRIf, action->priority);
   1308         soc_reg_field_set(
   1309                 unit, EGR_VLAN_CONTROL_2r, &rval, OCFIf, action->new_outer_cfi);
   1310     }
   1311     soc_reg_field_set(
   1312         unit, EGR_VLAN_CONTROL_2r, &rval, OVIDf, action->new_outer_vlan);
   1313 
   1314     rv = WRITE_EGR_VLAN_CONTROL_2r(unit, port, rval);
   1315     if (rv < 0) {
   1316         goto error;
   1317     }
   1318 
   1319     rv = READ_EGR_VLAN_CONTROL_3r(unit, port, &rval);
   1320     if (rv < 0) {
   1321         goto error;
   1322     }
   1323     old_profile_idx = soc_reg_field_get(
   1324                     unit, EGR_VLAN_CONTROL_3r, rval, TAG_ACTION_PROFILE_PTRf);
   1325     soc_reg_field_set(
   1326         unit, EGR_VLAN_CONTROL_3r, &rval, TAG_ACTION_PROFILE_PTRf, profile_idx);
   1327 
   1328     rv = WRITE_EGR_VLAN_CONTROL_3r(unit, port, rval);
   1329     if (rv < 0) {
   1330        goto error;
   1331     }
   1332 
   1333     /* Delete the old profile entry even if it is same as the new one as
   1334      * reference count has to adjust back to old value since it must have been
   1335      * bumped up by one when the profile entry was added in the very beginning
   1336      * of this function.
   1337      */
   1338     BCM_IF_ERROR_RETURN
   1339         (_bcm_th3_egr_vlan_action_profile_entry_delete(unit, old_profile_idx));
   1340 
   1341     return BCM_E_NONE;
   1342 error:
   1343     /* Undo action profile entry addition */
   1344     BCM_IF_ERROR_RETURN
   1345         (_bcm_th3_egr_vlan_action_profile_entry_delete(unit, profile_idx));
   1346     return rv;
   1347 }
   1348 
   1349 /*
   1350  * Function:
   1351  *      _bcm_th3_vlan_port_egress_default_action_get
   1352  *
   1353  * Purpose:
   1354  *      Get the egress port's default vlan tag actions
   1355  *
   1356  * Parameters:
   1357  *      unit       - (IN) BCM unit.
   1358  *      port       - (IN) Port number.
   1359  *      action     - (OUT) Vlan tag actions
   1360  *
   1361  * Returns:
   1362  *      BCM_E_XXX
   1363  *
   1364  * Notes:
   1365  */
   1366 int
   1367 _bcm_th3_vlan_port_egress_default_action_get(int unit, bcm_port_t port,
   1368                                             bcm_vlan_action_set_t *action)
   1369 {
   1370     uint32 profile_idx, rval;
   1371 
   1372     if (NULL == action) {
   1373         return BCM_E_PARAM;
   1374     }
   1375 
   1376     bcm_vlan_action_set_t_init(action);
   1377 
   1378     BCM_IF_ERROR_RETURN(READ_EGR_VLAN_CONTROL_3r(unit, port, &rval));
   1379     profile_idx =
   1380         soc_reg_field_get(unit, EGR_VLAN_CONTROL_3r,
   1381                                 rval, TAG_ACTION_PROFILE_PTRf);
   1382     _bcm_th3_egr_vlan_action_profile_entry_get(unit, action, profile_idx);
   1383 
   1384     BCM_IF_ERROR_RETURN(READ_EGR_VLAN_CONTROL_2r(unit, port, &rval));
   1385     action->new_outer_vlan =
   1386         soc_reg_field_get(unit, EGR_VLAN_CONTROL_2r, rval, OVIDf);
   1387 
   1388     if (!soc_reg_field_get(unit, EGR_VLAN_CONTROL_2r, rval, OPRI_CFI_SELf)) {
   1389         action->priority =
   1390             soc_reg_field_get(unit, EGR_VLAN_CONTROL_2r, rval, OPRIf);
   1391         action->new_outer_cfi =
   1392             soc_reg_field_get(unit, EGR_VLAN_CONTROL_2r, rval, OCFIf);
   1393     }
   1394     return BCM_E_NONE;
   1395 }
   1396 
   1397 /*
   1398  * Function:
   1399  *      _bcm_th3_vlan_port_egress_default_action_delete
   1400  *
   1401  * Purpose:
   1402  *      Deletes the egress port's default vlan tag actions
   1403  *
   1404  * Parameters:
   1405  *      unit       - (IN) BCM unit.
   1406  *      port       - (IN) Port number.
   1407  *
   1408  * Returns:
   1409  *      BCM_E_XXX
   1410  *
   1411  * Notes:
   1412  */
   1413 int
   1414 _bcm_th3_vlan_port_egress_default_action_delete(int unit, bcm_port_t port)
   1415 {
   1416     uint32 profile_idx, rval;
   1417 
   1418     BCM_IF_ERROR_RETURN(
   1419             READ_EGR_VLAN_CONTROL_3r(unit, port, &rval));
   1420     profile_idx = soc_reg_field_get(unit, EGR_VLAN_CONTROL_3r,
   1421             rval, TAG_ACTION_PROFILE_PTRf);
   1422 
   1423     BCM_IF_ERROR_RETURN(
   1424             _bcm_th3_egr_vlan_action_profile_entry_delete(unit, profile_idx));
   1425 
   1426     sal_memset(&rval, 0, sizeof(uint32));
   1427     BCM_IF_ERROR_RETURN(
   1428             WRITE_EGR_VLAN_CONTROL_3r(unit, port, rval));
   1429     BCM_IF_ERROR_RETURN(
   1430             WRITE_EGR_VLAN_CONTROL_2r(unit, port, rval));
   1431     return BCM_E_NONE;
   1432 }
   1433 
   1434 /*
   1435  * Function:
   1436  *      _bcm_th3_vlan_port_default_action_set
   1437  *
   1438  * Purpose:
   1439  *      Set the port's default vlan tag actions
   1440  *
   1441  * Parameters:
   1442  *      unit       - (IN) BCM unit.
   1443  *      port       - (IN) Port number.
   1444  *      action     - (IN) Vlan tag actions
   1445  *
   1446  * Returns:
   1447  *      BCM_E_XXX
   1448  *
   1449  * Notes:
   1450  */
   1451 int
   1452 _bcm_th3_vlan_port_default_action_set(int unit, bcm_port_t port,
   1453                                      bcm_vlan_action_set_t *action)
   1454 {
   1455     int profile_idx;
   1456     uint32 old_profile_idx;
   1457     bcm_port_cfg_t pcfg;
   1458 
   1459     BCM_IF_ERROR_RETURN(_bcm_th3_vlan_action_verify(unit, action));
   1460     BCM_IF_ERROR_RETURN(
   1461         _bcm_th3_ing_vlan_action_profile_entry_add(unit, action, &profile_idx));
   1462 
   1463     BCM_IF_ERROR_RETURN(
   1464         mbcm_driver[unit]->mbcm_port_cfg_get(unit, port, &pcfg));
   1465     old_profile_idx = pcfg.pc_vlan_action;
   1466 
   1467     pcfg.pc_vlan = action->new_outer_vlan;
   1468     pcfg.pc_vlan_action = profile_idx;
   1469     if (action->priority >= BCM_PRIO_MIN && action->priority <= BCM_PRIO_MAX) {
   1470         pcfg.pc_new_opri = action->priority;
   1471     }
   1472     pcfg.pc_new_ocfi = action->new_outer_cfi;
   1473     BCM_IF_ERROR_RETURN(
   1474         mbcm_driver[unit]->mbcm_port_cfg_set(unit, port, &pcfg));
   1475 
   1476     SOC_IF_ERROR_RETURN(
   1477         _bcm_th3_ing_vlan_action_profile_entry_delete(unit, old_profile_idx));
   1478     return BCM_E_NONE;
   1479 }
   1480 
   1481 /*
   1482  * Function:
   1483  *      _bcm_th3_vlan_port_default_action_get
   1484  *
   1485  * Purpose:
   1486  *      Get the port's default vlan tag actions
   1487  *
   1488  * Parameters:
   1489  *      unit       - (IN) BCM unit.
   1490  *      port       - (IN) Port number.
   1491  *      action     - (OUT) Vlan tag actions
   1492  *
   1493  * Returns:
   1494  *      BCM_E_XXX
   1495  *
   1496  * Notes:
   1497  */
   1498 int
   1499 _bcm_th3_vlan_port_default_action_get(int unit, bcm_port_t port,
   1500                                      bcm_vlan_action_set_t *action)
   1501 {
   1502     bcm_port_cfg_t pcfg;
   1503 
   1504     if (NULL == action) {
   1505         return BCM_E_PARAM;
   1506     }
   1507 
   1508     bcm_vlan_action_set_t_init(action);
   1509 
   1510     BCM_IF_ERROR_RETURN
   1511         (mbcm_driver[unit]->mbcm_port_cfg_get(unit, port, &pcfg));
   1512 
   1513     _bcm_th3_ing_vlan_action_profile_entry_get( unit,
   1514                                                 action,
   1515                                                 pcfg.pc_vlan_action);
   1516     action->new_outer_vlan = pcfg.pc_vlan;
   1517     action->priority = pcfg.pc_new_opri;
   1518     action->new_outer_cfi = pcfg.pc_new_ocfi;
   1519     return BCM_E_NONE;
   1520 }
   1521 
   1522 /*
   1523  * Function:
   1524  *      _bcm_th3_vlan_action_profile_entry_increment
   1525  *
   1526  * Purpose  : increment the refcount for a vlan action profile table entry
   1527  *
   1528  * Parameters:
   1529  *      unit       - (IN) BCM unit.
   1530  *      index      - (IN)
   1531  *
   1532  * Returns:
   1533  *
   1534  * Notes:
   1535  */
   1536 STATIC void
   1537 _bcm_th3_vlan_action_profile_entry_increment(int unit, uint32 index)
   1538 {
   1539     SOC_PROFILE_MEM_REFERENCE(unit, ing_action_profile[unit], index, 1);
   1540 }
   1541 
   1542 /*
   1543  * Function:
   1544  *      _bcm_th3_vlan_port_default_action_delete
   1545  *
   1546  * Purpose:
   1547  *      Deletes the port's default vlan tag actions
   1548  *
   1549  * Parameters:
   1550  *      unit       - (IN) BCM unit.
   1551  *      port       - (IN) Port number.
   1552  *
   1553  * Returns:
   1554  *      BCM_E_XXX
   1555  *
   1556  * Notes:
   1557  */
   1558 int
   1559 _bcm_th3_vlan_port_default_action_delete(int unit, bcm_port_t port)
   1560 {
   1561     uint32          old_profile_idx;
   1562     bcm_port_cfg_t  pcfg;
   1563 
   1564     BCM_IF_ERROR_RETURN
   1565         (mbcm_driver[unit]->mbcm_port_cfg_get(unit, port, &pcfg));
   1566     old_profile_idx = pcfg.pc_vlan_action;
   1567 
   1568     pcfg.pc_vlan = BCM_VLAN_DEFAULT;
   1569     pcfg.pc_vlan_action = ING_ACTION_PROFILE_DEFAULT;
   1570     BCM_IF_ERROR_RETURN
   1571         (mbcm_driver[unit]->mbcm_port_cfg_set(unit, port, &pcfg));
   1572 
   1573     _bcm_th3_vlan_action_profile_entry_increment(
   1574                             unit, ING_ACTION_PROFILE_DEFAULT);
   1575     BCM_IF_ERROR_RETURN
   1576         (_bcm_th3_ing_vlan_action_profile_entry_delete(unit, old_profile_idx));
   1577 
   1578     return (BCM_E_NONE);
   1579 }
   1580 
   1581 #if defined(BCM_WARM_BOOT_SUPPORT)
   1582 /*
   1583  * Function:
   1584  *      _bcm_th3_vlan_xconnect_db_reinit
   1585  *
   1586  * Purpose:
   1587  *       In Warmboot, fill in the Cross Connect SW cached from the L2 HW table
   1588  *
   1589  * Parameters:
   1590  *      unit       - (IN) BCM unit.
   1591  *
   1592  * Returns:
   1593  *      BCM_E_XXX
   1594  *
   1595  * Notes:
   1596  */
   1597 int _bcm_th3_vlan_xconnect_db_reinit(int unit) {
   1598     int rv = BCM_E_NONE;
   1599 
   1600     /* Allocate memory for the database */
   1601     BCM_IF_ERROR_RETURN(_bcm_th3_vlan_xconnect_db_init(unit));
   1602 
   1603     /* Acquire the Mutex */
   1604     BCM_TH3_VLAN_XCONNECT_MUTEX_ACQ(unit);
   1605 
   1606     /* Invoke appr. function to parse through L2Xm */
   1607     rv = _bcm_th3_l2_cross_connect_entry_add_all(unit);
   1608 
   1609     /* Release the Mutex */
   1610     BCM_TH3_VLAN_XCONNECT_MUTEX_REL(unit);
   1611 
   1612     return rv;
   1613 }
   1614 #endif /* BCM_WARM_BOOT_SUPPORT */
   1615 
   1616 /*
   1617  * Function:
   1618  *      _bcm_th3_vlan_xconnect_db_init
   1619  *
   1620  * Purpose:
   1621  *      Initialize/Allocate the Cross Connect SW cache
   1622  *
   1623  * Parameters:
   1624  *      unit       - (IN) BCM unit.
   1625  *
   1626  * Returns:
   1627  *      BCM_E_NONE
   1628  *      BCM_E_MEMORY
   1629  *
   1630  * Notes:
   1631  *      If the memory is already available then only task
   1632  *      done is to invalidate all entries in SW cache.
   1633  */
   1634 int _bcm_th3_vlan_xconnect_db_init(int unit) {
   1635 
   1636     /* Allocate the mutex, if not allocated yet */
   1637     if (NULL == _bcm_th3_xconnect_mtx[unit]) {
   1638         _bcm_th3_xconnect_mtx[unit] = sal_mutex_create("VlanXConnect");
   1639         if (NULL == _bcm_th3_xconnect_mtx[unit]) {
   1640             return BCM_E_MEMORY;
   1641         }
   1642     }
   1643 
   1644     /* Acquire the Mutex */
   1645     BCM_TH3_VLAN_XCONNECT_MUTEX_ACQ(unit);
   1646 
   1647     /* Allocate the database, if not yet allocated */
   1648     if (NULL == _bcm_th3_xconnect_db[unit]) {
   1649         _bcm_th3_xconnect_db[unit] =
   1650             sal_alloc(sizeof(_bcm_th3_vlan_xconnect_db_t), "XConnectDB");
   1651 
   1652         if (NULL == _bcm_th3_xconnect_db[unit]) {
   1653             sal_free(_bcm_th3_xconnect_mtx[unit]);
   1654             _bcm_th3_xconnect_mtx[unit] = NULL;
   1655             return BCM_E_MEMORY;
   1656         }
   1657     }
   1658 
   1659     /* Clear the state to begin-with */
   1660     SHR_BITCLR_RANGE(_bcm_th3_xconnect_db[unit]->valid, 0, BCM_VLAN_COUNT);
   1661 
   1662     /* Release the Mutex */
   1663     BCM_TH3_VLAN_XCONNECT_MUTEX_REL(unit);
   1664 
   1665     return BCM_E_NONE;
   1666 }
   1667 
   1668 /*
   1669  * Function:
   1670  *      _bcm_th3_vlan_xconnect_db_destroy
   1671  *
   1672  * Purpose:
   1673  *      Deallocate the Cross Connect SW cache
   1674  *
   1675  * Parameters:
   1676  *      unit       - (IN) BCM unit.
   1677  *
   1678  * Returns:
   1679  *      BCM_E_NONE
   1680  *
   1681  * Notes:
   1682  *      The Mutex is not destroyed
   1683  */
   1684 int _bcm_th3_vlan_xconnect_db_destroy(int unit) {
   1685 
   1686     /* Acquire the Mutex */
   1687     BCM_TH3_VLAN_XCONNECT_MUTEX_ACQ(unit);
   1688 
   1689     /* Deallocate memory */
   1690     if (NULL != _bcm_th3_xconnect_db[unit]) {
   1691         sal_free(_bcm_th3_xconnect_db[unit]);
   1692         _bcm_th3_xconnect_db[unit] = NULL;
   1693     }
   1694 
   1695     /* Release the Mutex */
   1696     BCM_TH3_VLAN_XCONNECT_MUTEX_REL(unit);
   1697 
   1698     return BCM_E_NONE;
   1699 }
   1700 
   1701 /*
   1702  * Function:
   1703  *      _bcm_th3_vlan_xconnect_db_entry_add
   1704  *
   1705  * Purpose:
   1706  *      Add cross connect entry to HW and SW database
   1707  *
   1708  * Parameters:
   1709  *      unit  - (IN) BCM unit.
   1710  *      ovlan - (IN) Outer VLAN ID.
   1711  *      destt - (IN) array of 2, specifies the corresponding dst is TGID or Port
   1712  *      destv - (IN) array of 2, TGID or Port corresponding to two gports
   1713  *
   1714  * Returns:
   1715  *      BCM_E_XXX
   1716  *
   1717  * Notes:
   1718  *      1) All incoming paramaters are assumed to be valid and hence no further
   1719  *          checks are performed on them
   1720  *      2) Cross Connect Mutex is acquired in the very beginning as updating the
   1721  *          HW table and SW cache has to be atomic with respect to VLAN module
   1722  */
   1723 int _bcm_th3_vlan_xconnect_db_entry_add(
   1724     int unit, bcm_vlan_t ovlan, uint8 *destt, int *destv) {
   1725 
   1726     int rv = BCM_E_NONE;
   1727 
   1728     /* Acquire the Mutex */
   1729     BCM_TH3_VLAN_XCONNECT_MUTEX_ACQ(unit);
   1730 
   1731     /* Add the entry to L2 table at first */
   1732     rv = _bcm_th3_l2_cross_connect_add(unit, ovlan, destt, destv);
   1733 
   1734     /* Only when the entry is successfully added to HW table add it to cache */
   1735     if ( BCM_SUCCESS(rv) ) {
   1736 
   1737         /* Add the destination value */
   1738         _bcm_th3_xconnect_db[unit]->destination[
   1739             BCM_TH3_VLAN_XC_DB_DESTTYPE_OFFSET(ovlan)] = (uint8) destv[0];
   1740         _bcm_th3_xconnect_db[unit]->destination[
   1741             BCM_TH3_VLAN_XC_DB_DESTTYPE1_OFFSET(ovlan)] = (uint8) destv[1];
   1742 
   1743         /* Add the distinguishing parameter - Trunk or Port */
   1744         SHR_BITWRITE(_bcm_th3_xconnect_db[unit]->dest_type,
   1745                      BCM_TH3_VLAN_XC_DB_DESTTYPE_OFFSET(ovlan), !!destt[0]);
   1746         SHR_BITWRITE(_bcm_th3_xconnect_db[unit]->dest_type,
   1747                      BCM_TH3_VLAN_XC_DB_DESTTYPE1_OFFSET(ovlan), !!destt[1]);
   1748 
   1749         /* Mark the entry valid */
   1750         SHR_BITSET(_bcm_th3_xconnect_db[unit]->valid, ovlan);
   1751     }
   1752 
   1753     /* Release the Mutex */
   1754     BCM_TH3_VLAN_XCONNECT_MUTEX_REL(unit);
   1755 
   1756     return rv;
   1757 }
   1758 
   1759 /*
   1760  * Function:
   1761  *      _bcm_th3_vlan_xconnect_db_entry_delete
   1762  *
   1763  * Purpose:
   1764  *      Delete cross connect entry from HW and SW database
   1765  *
   1766  * Parameters:
   1767  *      unit  - (IN) BCM unit.
   1768  *      ovlan - (IN) Outer VLAN ID.
   1769  *
   1770  * Returns:
   1771  *      BCM_E_XXX
   1772  *
   1773  * Notes:
   1774  *      Cross Connect Mutex is acquired in the very beginning as updating
   1775  *      the HW table and SW cache has to be atomic with respect to VLAN module
   1776  */
   1777 int _bcm_th3_vlan_xconnect_db_entry_delete(int unit, bcm_vlan_t ovlan) {
   1778 
   1779     int rv = BCM_E_NONE;
   1780 
   1781 #ifdef BCM_TRX_SUPPORT
   1782     /* Acquire the Mutex */
   1783     BCM_TH3_VLAN_XCONNECT_MUTEX_ACQ(unit);
   1784 
   1785     /* Delete the entry in L2 HW Table at first */
   1786     rv = bcm_tr_l2_cross_connect_delete(unit, ovlan, BCM_VLAN_INVALID);
   1787 
   1788     /* Invalidate the entry in SW cache, only when HW table entry is deleted */
   1789     if( BCM_SUCCESS(rv) ) {
   1790         SHR_BITCLR(_bcm_th3_xconnect_db[unit]->valid, ovlan);
   1791     }
   1792 
   1793     /* Release the Mutex */
   1794     BCM_TH3_VLAN_XCONNECT_MUTEX_REL(unit);
   1795 #else
   1796     rv = BCM_E_UNAVAIL;
   1797 #endif
   1798 
   1799     return rv;
   1800 }
   1801 
   1802 /*
   1803  * Function:
   1804  *      _bcm_th3_vlan_xconnect_db_entry_delete_all
   1805  *
   1806  * Purpose:
   1807  *      Delete all cross connect entries from HW and SW database
   1808  *
   1809  * Parameters:
   1810  *      unit  - (IN) BCM unit.
   1811  *
   1812  * Returns:
   1813  *      BCM_E_XXX
   1814  *
   1815  * Notes:
   1816  *      Cross Connect Mutex is acquired in the very beginning as updating
   1817  *      the HW table and SW cache has to be atomic with respect to VLAN module
   1818  */
   1819 int _bcm_th3_vlan_xconnect_db_entry_delete_all(int unit) {
   1820 
   1821     int rv = BCM_E_NONE;
   1822 
   1823 #ifdef BCM_TRX_SUPPORT
   1824     /* Acquire the Mutex */
   1825     BCM_TH3_VLAN_XCONNECT_MUTEX_ACQ(unit);
   1826 
   1827     /* Update L2 HW Table at first */
   1828     rv = bcm_tr_l2_cross_connect_delete_all(unit);
   1829 
   1830     /* Invalidate all entries in SW cache, only when HW is updated accord. */
   1831     if( BCM_SUCCESS(rv) ) {
   1832         SHR_BITCLR_RANGE(_bcm_th3_xconnect_db[unit]->valid, 0, BCM_VLAN_COUNT);
   1833     }
   1834 
   1835     /* Release the Mutex */
   1836     BCM_TH3_VLAN_XCONNECT_MUTEX_REL(unit);
   1837 #else
   1838     rv = BCM_E_UNAVAIL;
   1839 #endif
   1840 
   1841     return rv;
   1842 }
   1843 
   1844 /*
   1845  * Function:
   1846  *      _bcm_th3_vlan_xconnect_traverse
   1847  *
   1848  * Purpose:
   1849  *      Walks through the valid cross connect entries and
   1850  *      calls the user supplied callback function for each entry.
   1851  *
   1852  * Parameters:
   1853  *      unit       - (IN) BCM unit.
   1854  *      cb         - (IN) Callback function.
   1855  *      user_data  - (IN) User data to be passed to callback function.
   1856  *
   1857  * Returns:
   1858  *      BCM_E_XXX
   1859  *
   1860  * Notes:
   1861  */
   1862 int
   1863 _bcm_th3_vlan_xconnect_traverse(int unit,
   1864                                  bcm_vlan_cross_connect_traverse_cb cb,
   1865                                  void *user_data)
   1866 {
   1867     int rv = BCM_E_NONE;
   1868     uint32 destv;
   1869     bcm_vlan_t ovlan;
   1870     bcm_gport_t gport_1;
   1871     bcm_gport_t gport_2;
   1872     bcm_module_t local_modid;
   1873 
   1874     /* Get hold of chip local MODID */
   1875     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &local_modid));
   1876 
   1877     /* Acquire the Mutex */
   1878     BCM_TH3_VLAN_XCONNECT_MUTEX_ACQ(unit);
   1879 
   1880     /* Iterate through all valid cross connect entries */
   1881     SHR_BIT_ITER(_bcm_th3_xconnect_db[unit]->valid, BCM_VLAN_COUNT, ovlan) {
   1882 
   1883         /* Deduce the first gport */
   1884         destv = _bcm_th3_xconnect_db[unit]->
   1885                     destination[BCM_TH3_VLAN_XC_DB_DESTTYPE_OFFSET(ovlan)];
   1886         if (SHR_BITGET(_bcm_th3_xconnect_db[unit]->dest_type,
   1887                        BCM_TH3_VLAN_XC_DB_DESTTYPE_OFFSET(ovlan))) {
   1888             BCM_GPORT_TRUNK_SET(gport_1, destv);
   1889         } else {
   1890             BCM_GPORT_MODPORT_SET(gport_1, local_modid, destv);
   1891         }
   1892 
   1893         /* Deduce the second gport */
   1894         destv = _bcm_th3_xconnect_db[unit]->
   1895                     destination[BCM_TH3_VLAN_XC_DB_DESTTYPE1_OFFSET(ovlan)];
   1896         if (SHR_BITGET(_bcm_th3_xconnect_db[unit]->
   1897                 dest_type, BCM_TH3_VLAN_XC_DB_DESTTYPE1_OFFSET(ovlan))) {
   1898             BCM_GPORT_TRUNK_SET(gport_2, destv);
   1899         } else {
   1900             BCM_GPORT_MODPORT_SET(gport_2, local_modid, destv);
   1901         }
   1902 
   1903         /* Call application call-back */
   1904         rv = cb(unit, ovlan, BCM_VLAN_INVALID, gport_1, gport_2, user_data);
   1905 #ifdef BCM_CB_ABORT_ON_ERR
   1906         if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   1907             break;
   1908         }
   1909 #endif
   1910     }
   1911 
   1912     /* Release the Mutex */
   1913     BCM_TH3_VLAN_XCONNECT_MUTEX_REL(unit);
   1914 
   1915     return rv;
   1916 }
   1917 
   1918 /*
   1919  * Function:
   1920  *      bcm_th3_vlan_port_add
   1921  *
   1922  * Purpose:
   1923  *      Invokes low level functions to program the port membership bitmaps
   1924  *      in tables VLAN_2 and EGR_VLAN.
   1925  *
   1926  * Parameters:
   1927  *      unit       - (IN) BCM unit.
   1928  *      vid        - (IN) VLAN Identifier.
   1929  *      pbmp       - (IN) Egress Tagged Port Bitmap to be added to the VLAN.
   1930  *      upbmp      - (IN) Egress Untagged Port Bitmap to be added to the VLAN.
   1931  *      ing_pbmp   - (IN) Ingress Port Bitmap to be added to the VLAN.
   1932  *
   1933  * Returns:
   1934  *      BCM_E_NONE
   1935  *      BCM_E_PARAM
   1936  *      BCM_E_NOT_FOUND
   1937  *      BCM_E_FAIL
   1938  *      BCM_E_FULL
   1939  *
   1940  * Notes:
   1941  */
   1942 int
   1943 bcm_th3_vlan_port_add(int unit, bcm_vlan_t vid, pbmp_t pbmp, pbmp_t ubmp,
   1944                        pbmp_t ing_pbmp)
   1945 {
   1946     if (BCM_VLAN_VALID(vid)) {
   1947         BCM_IF_ERROR_RETURN(_bcm_xgs3_vlan_table_port_add(
   1948                 unit, vid, pbmp, ubmp, ing_pbmp, VLAN_2_TABm));
   1949 
   1950         BCM_IF_ERROR_RETURN(_bcm_xgs3_vlan_table_port_add(
   1951                 unit, vid, pbmp, ubmp, ing_pbmp, EGR_VLANm));
   1952     }
   1953 
   1954     return BCM_E_NONE;
   1955 }
   1956 
   1957 /*
   1958  * Function:
   1959  *      bcm_th3_vlan_port_remove
   1960  *
   1961  * Purpose:
   1962  *      Invokes low level functions to remove the ports in the given bitmaps
   1963  *      from tables VLAN_2 and EGR_VLAN.
   1964  *
   1965  * Parameters:
   1966  *      unit     - (IN) BCM unit.
   1967  *      vid      - (IN) VLAN Identifier.
   1968  *      pbmp     - (IN) Egress Tagged Port Bitmap to be removed from the VLAN.
   1969  *      upbmp    - (IN) Egress Untagged Port Bitmap to be removed from the VLAN.
   1970  *      ing_pbmp - (IN) Ingress Port Bitmap to be removed from the VLAN.
   1971  *
   1972  * Returns:
   1973  *      BCM_E_NONE
   1974  *      BCM_E_PARAM
   1975  *      BCM_E_NOT_FOUND
   1976  *      BCM_E_FAIL
   1977  *      BCM_E_FULL
   1978  *
   1979  * Notes:
   1980  */
   1981 int
   1982 bcm_th3_vlan_port_remove(int unit, bcm_vlan_t vid, pbmp_t pbmp, pbmp_t ubmp,
   1983                           pbmp_t ing_pbmp)
   1984 {
   1985     if (BCM_VLAN_VALID(vid)) {
   1986         BCM_IF_ERROR_RETURN(_bcm_xgs3_vlan_table_port_remove(
   1987                     unit, vid, pbmp, ubmp, ing_pbmp, VLAN_2_TABm));
   1988         BCM_IF_ERROR_RETURN(_bcm_xgs3_vlan_table_port_remove(
   1989                     unit, vid, pbmp, ubmp, ing_pbmp, EGR_VLANm));
   1990     }
   1991     return BCM_E_NONE;
   1992 }
   1993 
   1994 #ifndef BCM_SW_STATE_DUMP_DISABLE
   1995 /*
   1996  * Function:
   1997  *      _bcm_th3_vlan_sw_tag_action_profile_dump
   1998  *
   1999  * Purpose:
   2000  *      Displays VLAN Tag action information maintained by software.
   2001  *
   2002  * Parameters:
   2003  *      unit       - (IN) BCM unit.
   2004  *
   2005  * Returns:
   2006  *
   2007  * Notes:
   2008  */
   2009 void
   2010 _bcm_th3_vlan_sw_tag_action_profile_dump(int unit)
   2011 {
   2012     int         num_entries;
   2013     int         ref_count;
   2014     int         entries_per_set;
   2015     int         index, idx;
   2016     void        *entry;
   2017     soc_mem_t   mem;
   2018     soc_profile_mem_t *profile[2];
   2019 
   2020     profile[0] = ing_action_profile[unit];
   2021     profile[1] = egr_action_profile[unit];
   2022 
   2023     for (idx = 0 ; idx < 2 ; idx++) {
   2024       if (NULL != profile[idx]) {
   2025         LOG_CLI((BSL_META_U(unit,
   2026             "\nSW Information %sgress VLAN Action Profile - Unit %d\n")
   2027             , (ing_action_profile[unit] == profile[idx])?"In":"E", unit));
   2028 
   2029         mem = profile[idx]->tables[0].mem;
   2030         num_entries = soc_mem_index_count(unit, mem);
   2031         LOG_CLI((BSL_META_U(unit, " Number of entries: %d\n\n"), num_entries));
   2032         for (index = 0; index < num_entries; index ++) {
   2033             if (SOC_FAILURE(
   2034                     soc_profile_mem_ref_count_get(
   2035                         unit, profile[idx], index, &ref_count))) {
   2036                 break;
   2037             }
   2038 
   2039             /* Display entries with reference count > 0 */
   2040             if (ref_count <= 0) {
   2041                 continue;
   2042             }
   2043 
   2044             entries_per_set =
   2045                 profile[idx]->tables[0].entries[index].entries_per_set;
   2046             entry = SOC_PROFILE_MEM_ENTRY(unit, profile[idx], void *, index);
   2047 
   2048             LOG_CLI((BSL_META_U(unit, " Index           = 0x%x\n"), index));
   2049             LOG_CLI((BSL_META_U(unit, " Reference count = %d\n"), ref_count));
   2050             LOG_CLI((BSL_META_U(unit, " Entries per set = %d\n")
   2051                      , entries_per_set));
   2052             soc_mem_entry_dump(unit, mem, entry, BSL_LSS_CLI);
   2053             LOG_CLI((BSL_META_U(unit, "\n\n")));
   2054         }
   2055       }
   2056     }
   2057 
   2058     return;
   2059 }
   2060 #endif /* BCM_SW_STATE_DUMP_DISABLE */
   2061 #else /* BCM_TOMAHAWK3_SUPPORT */
   2062 int _tomahawk3_vlan_not_empty;
   2063 #endif /* BCM_TOMAHAWK3_SUPPORT */