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 (7315B)


      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 Hercules VLAN resources
      9  */
     10 
     11 #include <soc/defs.h>
     12 #if defined(BCM_HERCULES_SUPPORT)
     13 #include <sal/core/boot.h>
     14 #include <shared/bsl.h>
     15 #include <soc/drv.h>
     16 #include <soc/mem.h>
     17 #include <soc/debug.h>
     18 
     19 #include <bcm/error.h>
     20 #include <bcm/vlan.h>
     21 #include <bcm/port.h>
     22 #include <bcm/trunk.h>
     23 
     24 #include <bcm_int/esw/mbcm.h>
     25 #include <bcm_int/esw/hercules.h>
     26 
     27 /*
     28  * Function:
     29  *	bcm_hercules_vlan_init
     30  * Purpose:
     31  *	Initialize the VLAN tables with the default entry in it.
     32  */
     33 
     34 int
     35 bcm_hercules_vlan_init(int unit, bcm_vlan_data_t *vd)
     36 {
     37     mem_vid_entry_t	ve;
     38 
     39     if ((!SAL_BOOT_PLISIM) && (!SAL_BOOT_QUICKTURN)) {  /* Way too slow! */
     40         SOC_IF_ERROR_RETURN
     41 	    (soc_mem_clear(unit, MEM_VIDm, MEM_BLOCK_ALL, TRUE));
     42     } else {
     43         LOG_CLI((BSL_META_U(unit,
     44                             "SIMULATION: skipped VLAN table clear "
     45                             "(assuming hardware did it)\n")));
     46     }
     47 
     48     /* Initialize VLAN 1 */
     49 
     50     sal_memcpy(&ve, soc_mem_entry_null(unit, MEM_VIDm), sizeof (ve));
     51 
     52     soc_MEM_VIDm_field32_set(unit, &ve, VIDBITMAPf,
     53 			     SOC_PBMP_WORD_GET(vd->port_bitmap, 0));
     54 
     55     SOC_IF_ERROR_RETURN
     56 	(soc_mem_write(unit, MEM_VIDm, MEM_BLOCK_ALL, vd->vlan_tag, &ve));
     57 
     58     return BCM_E_NONE;
     59 }
     60 
     61 /*
     62  * Function:
     63  *      bcm_hercules_vlan_reload
     64  * Purpose:
     65  *	Return a list of VLANs currently installed in the hardware.
     66  */
     67 
     68 int
     69 bcm_hercules_vlan_reload(int unit, vbmp_t *bmp, int *count)
     70 {
     71     mem_vid_entry_t 	ve;
     72     uint32 		bmval;
     73     int 		index;
     74     int 		blk;
     75 
     76     (*count) = 0;
     77 
     78     for (index = soc_mem_index_min(unit, MEM_VIDm);
     79          index <= soc_mem_index_max(unit, MEM_VIDm);
     80 	 index++) {
     81 
     82         SOC_MEM_BLOCK_ITER(unit, MEM_VIDm, blk) {
     83 
     84             SOC_IF_ERROR_RETURN(READ_MEM_VIDm(unit, blk, index, &ve));
     85             soc_MEM_VIDm_field_get(unit, &ve, VIDBITMAPf, &bmval);
     86 
     87             if (bmval) {
     88                 SHR_BITSET(bmp->w, index);
     89                 (*count)++;
     90                 break;
     91             }
     92         }
     93     }
     94 
     95     return BCM_E_NONE;
     96 }
     97 
     98 /*
     99  * Function:
    100  *	bcm_hercules_vlan_create
    101  * Purpose:
    102  *	Create a VLAN entry in MEM_VID
    103  */
    104 
    105 int
    106 bcm_hercules_vlan_create(int unit, bcm_vlan_t vid)
    107 {
    108     mem_vid_entry_t	ve;
    109 
    110     /* Clear initial port bitmap */
    111     sal_memset(&ve, 0, sizeof ve);
    112 
    113     if (vlan_info[unit].vlan_auto_stack) {
    114         soc_MEM_VIDm_field32_set(unit, &ve, VIDBITMAPf,
    115                                  SOC_PBMP_WORD_GET(PBMP_HG_ALL(unit), 0));
    116     }
    117 
    118     SOC_IF_ERROR_RETURN(WRITE_MEM_VIDm(unit, MEM_BLOCK_ALL, vid, &ve));
    119 
    120     return BCM_E_NONE;
    121 }
    122 
    123 /*
    124  * Function:
    125  *	bcm_hercules_vlan_destroy
    126  * Purpose:
    127  *	Clear a VLAN entry in MEM_VID
    128  */
    129 
    130 int
    131 bcm_hercules_vlan_destroy(int unit, bcm_vlan_t vid)
    132 {
    133     mem_vid_entry_t	ve;
    134     int			rv;
    135 
    136     soc_mem_lock(unit, MEM_VIDm);
    137 
    138     if ((rv = READ_MEM_VIDm(unit, MEM_BLOCK_ANY, vid, &ve)) >= 0) {
    139 	soc_MEM_VIDm_field32_set(unit, &ve, VIDBITMAPf, 0);
    140 
    141 	rv = WRITE_MEM_VIDm(unit, MEM_BLOCK_ALL, vid, &ve);
    142     }
    143 
    144     soc_mem_unlock(unit, MEM_VIDm);
    145 
    146     return rv;
    147 }
    148 
    149 /*
    150  * Function:
    151  *	bcm_hercules_vlan_port_update
    152  * Purpose:
    153  *	Add/remove ports to the VLAN bitmap in a MEM_VID entry.
    154  * Notes:
    155  *      Each port has its own forwarding port mask for all VLANs.
    156  *	If a port is not a member of a VLAN, the corresponding
    157  *      forwarding port mask is set to zero. This way the table
    158  *      also acts as an ingress VLAN filter.
    159  */
    160 
    161 STATIC int
    162 bcm_hercules_vlan_port_update(int unit, bcm_vlan_t vid, pbmp_t pbmp, int add)
    163 {
    164     mem_vid_entry_t	ve[SOC_MAX_NUM_BLKS];
    165     int			port, blk;
    166     uint32		bmval = 0;
    167     int                 rv;
    168 
    169     soc_mem_lock(unit, MEM_VIDm);
    170 
    171     /* Read VLAN entries for all blocks */
    172     SOC_MEM_BLOCK_ITER(unit, MEM_VIDm, blk) {
    173 
    174         rv = READ_MEM_VIDm(unit, blk, vid, &ve[blk]);
    175 
    176         if (SOC_FAILURE(rv)) {
    177             soc_mem_unlock(unit, MEM_VIDm);
    178             return rv;
    179         }
    180 
    181         if (bmval == 0) {
    182             /* Pick up ports from existing VLAN member */
    183             soc_MEM_VIDm_field_get(unit, &ve[blk], VIDBITMAPf, &bmval);
    184         }
    185     }
    186 
    187     if (add) {
    188         bmval |= SOC_PBMP_WORD_GET(pbmp, 0);
    189     } else {
    190         bmval &= ~SOC_PBMP_WORD_GET(pbmp, 0);
    191     }
    192 
    193     /* Write non-zero entries for VLAN members only */
    194     SOC_MEM_BLOCK_ITER(unit, MEM_VIDm, blk) {
    195         port = SOC_BLOCK_PORT(unit, blk);
    196         soc_MEM_VIDm_field32_set(unit, &ve[blk], VIDBITMAPf, 
    197                                  (bmval & (1 << port)) ? bmval : 0);
    198         rv = WRITE_MEM_VIDm(unit, blk, vid, &ve[blk]);
    199         if (SOC_FAILURE(rv)){
    200             soc_mem_unlock(unit, MEM_VIDm);
    201             return (rv);
    202         }
    203     }
    204 
    205     soc_mem_unlock(unit, MEM_VIDm);
    206 
    207     return BCM_E_NONE;
    208 }
    209 
    210 /*
    211  * Function:
    212  *	bcm_hercules_vlan_port_add
    213  * Purpose:
    214  *	Add ports to the VLAN bitmap in a MEM_VID entry.
    215  */
    216 
    217 int
    218 bcm_hercules_vlan_port_add(int unit, bcm_vlan_t vid, pbmp_t pbmp, pbmp_t ubmp,
    219                            pbmp_t ing_pbmp)
    220 {
    221     BCM_PBMP_OR(pbmp, ing_pbmp);
    222 
    223     return bcm_hercules_vlan_port_update(unit, vid, pbmp, 1);
    224 }
    225 
    226 /*
    227  * Function:
    228  *	bcm_hercules_vlan_port_remove
    229  * Purpose:
    230  *	Remove ports from the VLAN bitmap in a MEM_VID entry.
    231  */
    232 
    233 int
    234 bcm_hercules_vlan_port_remove(int unit, bcm_vlan_t vid, pbmp_t pbmp,
    235                               pbmp_t ubmp, pbmp_t ing_pbmp)
    236 {
    237     return bcm_hercules_vlan_port_update(unit, vid, pbmp, 0);
    238 }
    239 
    240 /*
    241  * Function:
    242  *	bcm_hercules_vlan_port_get
    243  * Purpose:
    244  *	Read the port bitmap from a MEM_VID entry.
    245  */
    246 
    247 int
    248 bcm_hercules_vlan_port_get(int unit, bcm_vlan_t vid, pbmp_t *pbmp,
    249                            pbmp_t *ubmp, pbmp_t *ing_pbmp)
    250 {
    251     mem_vid_entry_t	ve;
    252     int			blk;
    253     uint32		bmval = 0;
    254     int rv;
    255 
    256     soc_mem_lock(unit, MEM_VIDm);
    257 
    258     SOC_MEM_BLOCK_ITER(unit, MEM_VIDm, blk) {
    259 
    260         rv = READ_MEM_VIDm(unit, blk, vid, &ve);
    261 
    262         if (SOC_FAILURE(rv)) {
    263             soc_mem_unlock(unit, MEM_VIDm);
    264             return rv;
    265         }
    266 
    267         bmval = soc_MEM_VIDm_field32_get(unit, &ve, VIDBITMAPf);
    268         if (bmval) {
    269             break;
    270         }
    271     }
    272 
    273     if (pbmp != NULL) {
    274 	SOC_PBMP_CLEAR(*pbmp);
    275 	SOC_PBMP_WORD_SET(*pbmp, 0, bmval);
    276     }
    277 
    278     if (ubmp != NULL) {
    279 	SOC_PBMP_CLEAR(*ubmp);
    280     }
    281 
    282     if (ing_pbmp != NULL) {
    283 	SOC_PBMP_CLEAR(*ing_pbmp);
    284 	SOC_PBMP_WORD_SET(*ing_pbmp, 0, bmval);
    285     }
    286 
    287     soc_mem_unlock(unit, MEM_VIDm);
    288 
    289     return BCM_E_NONE;
    290 }
    291 
    292 /*
    293  * Function:
    294  *	bcm_hercules_vlan_stg_get
    295  * Purpose:
    296  *	Stub out STG on Hercules
    297  */
    298 
    299 int
    300 bcm_hercules_vlan_stg_get(int unit, bcm_vlan_t vid, bcm_stg_t *stg_ptr)
    301 {
    302     COMPILER_REFERENCE(unit);
    303     COMPILER_REFERENCE(vid);
    304 
    305     *stg_ptr = 1;	/* Only one "STG" on Hercules */
    306 
    307     return BCM_E_NONE;
    308 }
    309 
    310 /*
    311  * Function:
    312  *	bcm_hercules_vlan_stg_set
    313  * Purpose:
    314  *	Stub out STG on Hercules
    315  */
    316 
    317 int
    318 bcm_hercules_vlan_stg_set(int unit, bcm_vlan_t vid, bcm_stg_t stg)
    319 {
    320     COMPILER_REFERENCE(unit);
    321     COMPILER_REFERENCE(vid);
    322 
    323     /* Only one "STG" on Hercules */
    324 
    325     return (stg == 1) ? BCM_E_NONE : BCM_E_BADID;
    326 }
    327 #else /* BCM_HERCULES_SUPPORT */
    328 int _hercules_vlan_not_empty;
    329 #endif /* BCM_HERCULES_SUPPORT */