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

multicast.c (23976B)


      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:        multicast.c
      8  * Purpose:     Tomahawk multicast functions
      9  */
     10 
     11 #include <soc/defs.h>
     12 #include <sal/core/libc.h>
     13 #include <shared/bsl.h>
     14 #if defined(BCM_TOMAHAWK_SUPPORT) && defined(INCLUDE_L3)
     15 #include <soc/drv.h>
     16 #include <soc/scache_dictionary.h>
     17 #include <bcm/error.h>
     18 #include <bcm/types.h>
     19 #include <bcm_int/esw/tomahawk.h>
     20 
     21 #ifdef BCM_TOMAHAWK3_SUPPORT
     22 #include <bcm_int/esw/tomahawk3.h>
     23 #endif
     24 
     25 #define _TH_NUM_TRUNKS(unit) \
     26         (SOC_IS_TOMAHAWK3(unit) ? 144 : 1024)
     27 #define _TH_NUM_AGGID_PER_PIPE(unit)  \
     28         (SOC_IS_TOMAHAWK3(unit) ? \
     29         (soc_mem_field_length(unit, MMU_REPL_GROUP_INFO_TBLm, MEMBER_BMPf)) : \
     30         (soc_mem_field_length(unit, MMU_REPL_GROUP_INFO_TBLm, PIPE_MEMBER_BMPf)))
     31 #define _TH_MAX_NUM_TRUNKS 1024
     32 
     33 typedef struct _bcm_th_aggid_used_bmp_per_pipe_s {
     34     SHR_BITDCL* pipe_aggid_bmp;
     35 } _bcm_th_aggid_used_bmp_per_pipe_t;
     36 
     37 STATIC _bcm_th_aggid_used_bmp_per_pipe_t *th_aggid_used_bmp[BCM_MAX_NUM_UNITS];
     38 
     39 typedef struct _bcm_th_trunk_aggid_info_s {
     40     int agg_id;
     41     int ref_cnt;
     42 } _bcm_th_trunk_aggid_info_t;
     43 
     44 typedef struct _bcm_th_trunk_aggid_per_pipe_info_s {
     45     _bcm_th_trunk_aggid_info_t trunk_aggid_info[_TH_MAX_NUM_TRUNKS];
     46 } _bcm_th_trunk_aggid_per_pipe_info_t;
     47 
     48 typedef struct _bcm_th_port_aggid_info_s {
     49     int agg_id;
     50     int ref_cnt;   /* The number of the pair <mc group, nexthop> pointing to it. */
     51     int trunk_id;
     52 } _bcm_th_port_aggid_info_t;
     53 
     54 STATIC _bcm_th_trunk_aggid_per_pipe_info_t *th_trunk_aggid[BCM_MAX_NUM_UNITS];
     55 
     56 STATIC _bcm_th_port_aggid_info_t *th_port_aggid[BCM_MAX_NUM_UNITS];
     57 
     58 
     59 /*
     60  * Function:
     61  *      bcm_th_aggid_info_detach
     62  * Purpose:
     63  *      Free aggregation ID list.
     64  * Parameters:
     65  *      unit  - (IN) Unit number.
     66  * Returns:
     67  *      BCM_E_XXX
     68  */
     69 int
     70 bcm_th_aggid_info_detach(int unit)
     71 {
     72     int num_pipes;
     73     int i;
     74     SHR_BITDCL *pipe_aggid_bmp;
     75 
     76     num_pipes = NUM_PIPE(unit);
     77 #ifdef BCM_TOMAHAWK3_SUPPORT
     78     if(SOC_IS_TOMAHAWK3(unit)) {
     79         /* IPMC repl is pipe independent in TH3 */
     80         num_pipes = 1;
     81     }
     82 #endif
     83     if (th_aggid_used_bmp[unit] != NULL) {
     84         for (i = 0; i < num_pipes; i++) {
     85             pipe_aggid_bmp = th_aggid_used_bmp[unit][i].pipe_aggid_bmp;
     86             if (pipe_aggid_bmp != NULL) {
     87                 sal_free(pipe_aggid_bmp);
     88                 pipe_aggid_bmp = NULL;
     89             }
     90         }
     91         sal_free(th_aggid_used_bmp[unit]);
     92         th_aggid_used_bmp[unit] = NULL;
     93     }
     94 
     95 	if (th_trunk_aggid[unit] != NULL) {
     96         sal_free(th_trunk_aggid[unit]);
     97 		th_trunk_aggid[unit] = NULL;
     98 	}
     99 
    100 	if (th_port_aggid[unit] != NULL) {
    101 		sal_free(th_port_aggid[unit]);
    102 		th_port_aggid[unit] = NULL;
    103 	}
    104 
    105     return BCM_E_NONE;
    106 }
    107 
    108 /*
    109  * Function:
    110  *      bcm_th_aggid_info_init
    111  * Purpose:
    112  *      Initialize aggregation ID to trunk map array.
    113  * Parameters:
    114  *      unit  - (IN) Unit number.
    115  * Returns:
    116  *      BCM_E_XXX
    117  */
    118 int
    119 bcm_th_aggid_info_init(int unit)
    120 {
    121     int   num_pipes;
    122     int   i, j;
    123     _bcm_th_trunk_aggid_info_t *trunk_aggid_info;
    124     _bcm_th_port_aggid_info_t *port_aggid_info;
    125 
    126 
    127     if (!SOC_UNIT_VALID(unit)) {
    128         return BCM_E_UNIT;
    129     }
    130 
    131     num_pipes = NUM_PIPE(unit);
    132 
    133 #ifdef BCM_TOMAHAWK3_SUPPORT
    134     if(SOC_IS_TOMAHAWK3(unit)) {
    135         /* IPMC repl is pipe independent in TH3 */
    136         num_pipes = 1;
    137     }
    138 #endif
    139     bcm_th_aggid_info_detach(unit);
    140 
    141 
    142     th_aggid_used_bmp[unit] =
    143         sal_alloc((num_pipes * sizeof(_bcm_th_aggid_used_bmp_per_pipe_t)),
    144                   "aggid_used_bmp_info");
    145     if (th_aggid_used_bmp[unit] == NULL) {
    146         return BCM_E_MEMORY;
    147     }
    148     for (i = 0; i < num_pipes; i++) {
    149         th_aggid_used_bmp[unit][i].pipe_aggid_bmp =
    150             sal_alloc(SHR_BITALLOCSIZE(_TH_NUM_AGGID_PER_PIPE(unit)),
    151                       "aggid_used_bmp_per_piep_info");
    152         if (th_aggid_used_bmp[unit][i].pipe_aggid_bmp == NULL) {
    153             bcm_th_aggid_info_detach(unit);
    154             return BCM_E_MEMORY;
    155         }
    156         sal_memset(th_aggid_used_bmp[unit][i].pipe_aggid_bmp, 0,
    157                    SHR_BITALLOCSIZE(_TH_NUM_AGGID_PER_PIPE(unit)));
    158     }
    159 
    160     /* Init trunk aggid info. */
    161     th_trunk_aggid[unit] =
    162         sal_alloc((num_pipes * sizeof(_bcm_th_trunk_aggid_per_pipe_info_t)),
    163                   "trunk_aggid_info");
    164     if (th_trunk_aggid[unit] == NULL) {
    165         bcm_th_aggid_info_detach(unit);
    166         return BCM_E_MEMORY;
    167     }
    168     for (i = 0; i < num_pipes; i++) {
    169         for (j = 0; j < _TH_NUM_TRUNKS(unit); j++) {
    170             trunk_aggid_info = &(th_trunk_aggid[unit][i].trunk_aggid_info[j]);
    171             trunk_aggid_info->agg_id = TH_AGG_ID_INVALID;
    172             trunk_aggid_info->ref_cnt = 0;
    173         }
    174     }
    175 
    176     /* Init port aggid info. */
    177     th_port_aggid[unit] =
    178         sal_alloc((SOC_MAX_NUM_PORTS * sizeof(_bcm_th_port_aggid_info_t)),
    179                    "port_aggid_info");
    180     if (th_port_aggid[unit] == NULL) {
    181         bcm_th_aggid_info_detach(unit);
    182         return BCM_E_MEMORY;
    183     }
    184     for (i = 0; i < SOC_MAX_NUM_PORTS; i++) {
    185         port_aggid_info = &th_port_aggid[unit][i];
    186         port_aggid_info->agg_id = TH_AGG_ID_INVALID;
    187         port_aggid_info->ref_cnt = 0;
    188         port_aggid_info->trunk_id = BCM_TRUNK_INVALID;
    189     }
    190 
    191     return BCM_E_NONE;
    192 }
    193 
    194 /*
    195  * Function:
    196  *      bcm_th_get_free_aggid
    197  * Purpose:
    198  *      Get a free aggid for given pipe.
    199  * Parameters:
    200  *      unit  - (IN)  Unit number.
    201  *      pipe  - (IN)  Pipe id.
    202  *      aggid - (OUT) Returned aggid.
    203  * Returns:
    204  *      BCM_E_XXX
    205  */
    206 STATIC int
    207 bcm_th_get_free_aggid(int unit, int pipe, int *aggid)
    208 {
    209     SHR_BITDCL *aggid_bmp;
    210     int i;
    211 
    212     aggid_bmp = th_aggid_used_bmp[unit][pipe].pipe_aggid_bmp;
    213     for (i = 0; i < _TH_NUM_AGGID_PER_PIPE(unit); i++) {
    214         if (!SHR_BITGET(aggid_bmp, i)) {
    215             *aggid = i;
    216             SHR_BITSET(aggid_bmp, i);
    217             return BCM_E_NONE;
    218         }
    219     }
    220 
    221     if (i == _TH_NUM_AGGID_PER_PIPE(unit)) {
    222         return BCM_E_FULL;
    223     }
    224 
    225     return BCM_E_NONE;
    226 
    227 }
    228 
    229 /*
    230  * Function:
    231  *      bcm_th_set_free_aggid
    232  * Purpose:
    233  *      Free aggid for given pipe.
    234  * Parameters:
    235  *      unit  - (IN)  Unit number.
    236  *      pipe  - (IN)  Pipe id.
    237  *      aggid - (IN)  Aggregation ID.
    238  * Returns:
    239  *      BCM_E_XXX
    240  */
    241 STATIC int
    242 bcm_th_set_free_aggid(int unit, int pipe, int aggid)
    243 {
    244     SHR_BITDCL *aggid_bmp;
    245 
    246     aggid_bmp = th_aggid_used_bmp[unit][pipe].pipe_aggid_bmp;
    247     if (aggid >= _TH_NUM_AGGID_PER_PIPE(unit)) {
    248         return BCM_E_PARAM;
    249     }
    250     SHR_BITCLR(aggid_bmp, aggid);
    251 
    252     return BCM_E_NONE;
    253 }
    254 
    255 /*
    256  * Function:
    257  *      bcm_th_set_port_hw_agg_map
    258  * Purpose:
    259  *      Set HW aggid map register for a port.
    260  * Parameters:
    261  *      unit  - (IN) Unit number.
    262  *      port  - (IN) Logical Port.
    263  *      aggid - (IN) Aggregation ID.
    264  * Returns:
    265  *      BCM_E_XXX
    266  */
    267 int
    268 bcm_th_set_port_hw_agg_map(int unit, bcm_port_t port, int aggid)
    269 {
    270     uint32 regval;
    271 #ifdef BCM_TOMAHAWK3_SUPPORT
    272     if(SOC_IS_TOMAHAWK3(unit)) {
    273         BCM_IF_ERROR_RETURN(READ_MMU_RQE_REPL_PORT_AGG_MAPr(unit, port,
    274                                                             &regval));
    275         soc_reg_field_set(unit, MMU_RQE_REPL_PORT_AGG_MAPr, &regval,
    276                                     L3MC_PORT_AGG_IDf, aggid);
    277         SOC_IF_ERROR_RETURN(
    278             soc_reg32_set(unit, MMU_RQE_REPL_PORT_AGG_MAPr, port, 0, regval));
    279         return BCM_E_NONE;
    280     }
    281 #endif
    282     BCM_IF_ERROR_RETURN(READ_MMU_DQS_REPL_PORT_AGG_MAPr(unit, port, &regval));
    283     soc_reg_field_set(unit, MMU_DQS_REPL_PORT_AGG_MAPr, &regval,
    284                       L3MC_PORT_AGG_IDf, aggid);
    285     SOC_IF_ERROR_RETURN(
    286         soc_reg32_set(unit, MMU_DQS_REPL_PORT_AGG_MAPr, port, 0, regval));
    287 
    288     return BCM_E_NONE;
    289 }
    290 
    291 /*
    292  * Function:
    293  *      bcm_th_aggid_add
    294  * Purpose:
    295  *      Increase aggid refcnt of a independ port or trunk.
    296  * Parameters:
    297  *      unit  - (IN)  Unit number.
    298  *      port  - (IN)  Logical Port.
    299  *      tgid  - (IN)  Trunk id.
    300  *      aggid - (OUT) Returned aggid.
    301  * Returns:
    302  *      BCM_E_XXX
    303  */
    304 STATIC int
    305 bcm_th_aggid_add(int unit, bcm_port_t port, bcm_trunk_t tgid, int *aggid)
    306 {
    307     int rv = BCM_E_NONE;
    308     int pipe;
    309     _bcm_th_trunk_aggid_info_t *trunk_aggid_info;
    310     _bcm_th_port_aggid_info_t *port_aggid_info;
    311 
    312     if (((tgid != BCM_TRUNK_INVALID) && (tgid < 0 || tgid >= _TH_NUM_TRUNKS(unit))) ||
    313         (port < 0 || port >= SOC_MAX_NUM_PORTS) ||
    314         (aggid == NULL)) {
    315         return BCM_E_PARAM;
    316     }
    317 
    318     pipe = SOC_INFO(unit).port_pipe[port];
    319 #ifdef BCM_TOMAHAWK3_SUPPORT
    320     if(SOC_IS_TOMAHAWK3(unit)) {
    321         pipe = 0;
    322     }
    323 #endif
    324     if (tgid != BCM_TRUNK_INVALID) {
    325         trunk_aggid_info = &(th_trunk_aggid[unit][pipe].trunk_aggid_info[tgid]);
    326         if (trunk_aggid_info->agg_id == TH_AGG_ID_INVALID) {
    327             BCM_IF_ERROR_RETURN(bcm_th_get_free_aggid(unit, pipe, aggid));
    328             trunk_aggid_info->agg_id = *aggid;
    329             trunk_aggid_info->ref_cnt = 1;
    330         } else {
    331             *aggid = trunk_aggid_info->agg_id;
    332             trunk_aggid_info->ref_cnt++;
    333         }
    334     } else {
    335         port_aggid_info = &(th_port_aggid[unit][port]);
    336         if (port_aggid_info->agg_id == TH_AGG_ID_INVALID) {
    337             BCM_IF_ERROR_RETURN(bcm_th_get_free_aggid(unit, pipe, aggid));
    338             rv = bcm_th_set_port_hw_agg_map(unit, port, *aggid);
    339             if (BCM_FAILURE(rv)) {
    340                 bcm_th_set_free_aggid(unit, pipe, *aggid);
    341                 return rv;
    342             }
    343             port_aggid_info->agg_id = *aggid;
    344             port_aggid_info->ref_cnt = 1;
    345             port_aggid_info->trunk_id = BCM_TRUNK_INVALID;
    346         } else {
    347             *aggid = port_aggid_info->agg_id;
    348             port_aggid_info->ref_cnt++;
    349         }
    350     }
    351 
    352     return BCM_E_NONE;
    353 }
    354 
    355 /*
    356  * Function:
    357  *      bcm_th_aggid_del
    358  * Purpose:
    359  *      Decrease aggid refcnt of a independ port or trunk.
    360  * Parameters:
    361  *      unit  - (IN)  Unit number.
    362  *      port  - (IN)  Logical Port.
    363  * Returns:
    364  *      BCM_E_XXX
    365  */
    366 STATIC int
    367 bcm_th_aggid_del(int unit, bcm_port_t port)
    368 {
    369     int pipe;
    370     bcm_trunk_t tgid;
    371     int rv;
    372     _bcm_th_trunk_aggid_info_t *trunk_aggid_info;
    373     _bcm_th_port_aggid_info_t *port_aggid_info;
    374 
    375     if ((port < 0) || (port >= SOC_MAX_NUM_PORTS)) {
    376         return BCM_E_PARAM;
    377     }
    378     port_aggid_info = &(th_port_aggid[unit][port]);
    379     tgid = port_aggid_info->trunk_id;
    380     pipe = SOC_INFO(unit).port_pipe[port];
    381 #ifdef BCM_TOMAHAWK3_SUPPORT
    382     if(SOC_IS_TOMAHAWK3(unit)) {
    383         pipe = 0;
    384     }
    385 #endif
    386     if (tgid != BCM_TRUNK_INVALID) {
    387         trunk_aggid_info = &(th_trunk_aggid[unit][pipe].trunk_aggid_info[tgid]);
    388         if (trunk_aggid_info->ref_cnt <= 0) {
    389             return BCM_E_PARAM;
    390         }
    391         trunk_aggid_info->ref_cnt--;
    392         if (trunk_aggid_info->ref_cnt == 0) {
    393             bcm_th_set_free_aggid(unit, pipe, trunk_aggid_info->agg_id);
    394             trunk_aggid_info->agg_id = TH_AGG_ID_INVALID;
    395         }
    396         if (port_aggid_info->ref_cnt == 0) {
    397             port_aggid_info->trunk_id = BCM_TRUNK_INVALID;
    398         }
    399     } else {
    400         if (port_aggid_info->ref_cnt <= 0) {
    401             return BCM_E_PARAM;
    402         }
    403         port_aggid_info->ref_cnt--;
    404         if (port_aggid_info->ref_cnt == 0) {
    405 #ifdef BCM_TOMAHAWK3_SUPPORT
    406             if (SOC_IS_TOMAHAWK3(unit)) {
    407                rv = bcm_th_set_port_hw_agg_map(unit, port, TH3_AGG_ID_HW_INVALID);
    408 
    409             } else
    410 #endif
    411             {
    412                 rv = bcm_th_set_port_hw_agg_map(unit, port, TH_AGG_ID_HW_INVALID);
    413             }
    414             if (BCM_FAILURE(rv)) {
    415                 port_aggid_info->ref_cnt++;
    416                 return rv;
    417             }
    418             bcm_th_set_free_aggid(unit, pipe, port_aggid_info->agg_id);
    419             port_aggid_info->agg_id = TH_AGG_ID_INVALID;
    420         }
    421     }
    422 
    423     return BCM_E_NONE;
    424 }
    425 
    426 
    427 /*
    428  * Function:
    429  *      bcm_th_aggid_ref_inc_for_member
    430  * Purpose:
    431  *      Increase aggid refcount for a trunk member port.
    432  * Parameters:
    433  *      unit  - (IN)  Unit number.
    434  *      port  - (IN)  Logical Port.
    435  *      tgid  - (IN)  Trunk id.
    436  * Returns:
    437  *      BCM_E_XXX
    438  */
    439 STATIC int
    440 bcm_th_aggid_ref_inc_for_member(int unit, bcm_port_t port, bcm_trunk_t tgid)
    441 {
    442     int aggid, pipe;
    443     _bcm_th_port_aggid_info_t *port_aggid_info;
    444 
    445     if (port < 0 || port >= SOC_MAX_NUM_PORTS) {
    446         return BCM_E_PARAM;
    447     }
    448 
    449     port_aggid_info = &(th_port_aggid[unit][port]);
    450     if (port_aggid_info->agg_id != TH_AGG_ID_INVALID) {
    451         return BCM_E_PARAM;
    452     }
    453 
    454     if (port_aggid_info->trunk_id == BCM_TRUNK_INVALID) {
    455         /* This is the first time that member port joined trunk tgid.
    456          * For member port, it just uses trunk's agg_id not itself.
    457          */
    458         if (port_aggid_info->ref_cnt != 0) {
    459             return BCM_E_PARAM;
    460         }
    461         port_aggid_info->trunk_id = tgid;
    462         port_aggid_info->ref_cnt = 1;
    463         pipe = SOC_INFO(unit).port_pipe[port];
    464 #ifdef BCM_TOMAHAWK3_SUPPORT
    465         if (SOC_IS_TOMAHAWK3(unit)) {
    466             pipe = 0;
    467         }
    468 #endif
    469         aggid = th_trunk_aggid[unit][pipe].trunk_aggid_info[tgid].agg_id;
    470         BCM_IF_ERROR_RETURN(bcm_th_set_port_hw_agg_map(unit, port, aggid));
    471     } else {
    472         /* member port has joined one trunk. */
    473         if (port_aggid_info->trunk_id != tgid) {
    474             return BCM_E_PARAM;
    475         }
    476         port_aggid_info->ref_cnt++;
    477     }
    478 
    479     return BCM_E_NONE;
    480 }
    481 
    482 /*
    483  * Function:
    484  *      bcm_th_aggid_ref_dec_for_member
    485  * Purpose:
    486  *      Decrease aggid refcount for a trunk member port.
    487  * Parameters:
    488  *      unit  - (IN) Unit number.
    489  *      port  - (IN)  Logical Port.
    490  * Returns:
    491  *      BCM_E_XXX
    492  */
    493 STATIC int
    494 bcm_th_aggid_ref_dec_for_member(int unit, bcm_port_t port)
    495 {
    496     _bcm_th_port_aggid_info_t *port_aggid_info;
    497     int rv;
    498 
    499     if (port < 0 || port >= SOC_MAX_NUM_PORTS) {
    500         return BCM_E_PARAM;
    501     }
    502 
    503     port_aggid_info = &(th_port_aggid[unit][port]);
    504     if (port_aggid_info->trunk_id == BCM_TRUNK_INVALID) {
    505         return BCM_E_PARAM;
    506     }
    507 
    508     if (port_aggid_info->ref_cnt <= 0) {
    509         return BCM_E_PARAM;
    510     }
    511 
    512     port_aggid_info->ref_cnt--;
    513     if (port_aggid_info->ref_cnt == 0) {
    514         /* All (port, mc group) has can leave the trunk.
    515          * Do not set port_aggid_info->trunk_id to BCM_TRUNK_INVALID here.
    516          */
    517 #ifdef BCM_TOMAHAWK3_SUPPORT
    518         if (SOC_IS_TOMAHAWK3(unit)) {
    519             rv = bcm_th_set_port_hw_agg_map(unit, port, TH3_AGG_ID_HW_INVALID);
    520         } else
    521 #endif
    522         {
    523             rv = bcm_th_set_port_hw_agg_map(unit, port, TH_AGG_ID_HW_INVALID);
    524         }
    525         if (BCM_FAILURE(rv)) {
    526             port_aggid_info->ref_cnt++;
    527             return rv;
    528         }
    529     }
    530 
    531     return BCM_E_NONE;
    532 }
    533 
    534 /*
    535  * Function:
    536  *      bcm_th_port_aggid_add
    537  * Purpose:
    538  *      Add a aggid for a logical port.
    539  * Parameters:
    540  *      unit  - (IN)  Unit number.
    541  *      port  - (IN)  Logical Port.
    542  *      tgid  - (IN)  Trunk id.
    543  *      aggid - (OUT) Returned aggid.
    544  * Returns:
    545  *      BCM_E_XXX
    546  */
    547 int
    548 bcm_th_port_aggid_add(int unit, bcm_port_t port, bcm_trunk_t tgid, int *aggid)
    549 {
    550     int rv;
    551 
    552     if (tgid != BCM_TRUNK_INVALID) {
    553         rv = bcm_th_aggid_add(unit, port, tgid, aggid);
    554         if (BCM_FAILURE(rv)) {
    555             return rv;
    556         }
    557         rv = bcm_th_aggid_ref_inc_for_member(unit, port, tgid);
    558         if (BCM_FAILURE(rv)) {
    559             bcm_th_aggid_del(unit, port);
    560             return rv;
    561         }
    562     } else {
    563         rv = bcm_th_aggid_add(unit, port, tgid, aggid);
    564         if (BCM_FAILURE(rv)) {
    565             return rv;
    566         }
    567     }
    568 
    569     return BCM_E_NONE;
    570 }
    571 
    572 /*
    573  * Function:
    574  *      bcm_th_port_aggid_del
    575  * Purpose:
    576  *      Del aggid of a logical port.
    577  * Parameters:
    578  *      unit  - (IN)  Unit number.
    579  *      port  - (IN)  Logical Port.
    580  * Returns:
    581  *      BCM_E_XXX
    582  */
    583 int
    584 bcm_th_port_aggid_del(int unit, bcm_port_t port)
    585 {
    586     _bcm_th_port_aggid_info_t *port_aggid_info;
    587     bcm_trunk_t tgid;
    588     int rv;
    589 
    590     if (port < 0 || port >= SOC_MAX_NUM_PORTS) {
    591         return BCM_E_PARAM;
    592     }
    593 
    594     port_aggid_info = &(th_port_aggid[unit][port]);
    595     tgid = port_aggid_info->trunk_id;
    596 
    597     if (tgid != BCM_TRUNK_INVALID) {
    598         rv = bcm_th_aggid_ref_dec_for_member(unit, port);
    599         if (BCM_FAILURE(rv)) {
    600             return rv;
    601         }
    602         rv = bcm_th_aggid_del(unit, port);
    603         if (BCM_FAILURE(rv)) {
    604             bcm_th_aggid_ref_inc_for_member(unit, port, tgid);
    605             return rv;
    606         }
    607     } else {
    608         rv = bcm_th_aggid_del(unit, port);
    609         if (BCM_FAILURE(rv)) {
    610             return rv;
    611         }
    612     }
    613 
    614     return BCM_E_NONE;
    615 }
    616 
    617 /*
    618  * Function:
    619  *      bcm_th_port_trunkid_get
    620  * Purpose:
    621  *      When port has been removed from trunk in trunk module,
    622  *      we could only get trunkid of port from previous saved DB.
    623  * Parameters:
    624  *      unit  - (IN) Unit number.
    625  *      port  - (IN) Logical Port
    626  *      tgid  - (OUT) returned Trunk id.
    627  * Returns:
    628  *      BCM_E_XXX
    629  * Note: This function only can be used when deleting port from trunk.
    630  */
    631 int
    632 bcm_th_port_trunkid_get(int unit, bcm_port_t port, int *tgid)
    633 {
    634     _bcm_th_port_aggid_info_t *port_aggid_info;
    635 
    636     if ((port < 0 || port >= SOC_MAX_NUM_PORTS) ||
    637         (tgid == NULL)) {
    638         return BCM_E_PARAM;
    639     }
    640 
    641     port_aggid_info = &(th_port_aggid[unit][port]);
    642     *tgid = port_aggid_info->trunk_id;
    643 
    644     return BCM_E_NONE;
    645 }
    646 
    647 /*
    648  * Function:
    649  *      bcm_th_port_last_member_check
    650  * Purpose:
    651  *      Check whether a member port is the last member of its trunk.
    652  * Parameters:
    653  *      unit  - (IN)  Unit number.
    654  *      port  - (IN)  Logical Port
    655  *      val   - (OUT) returned val.
    656  * Returns:
    657  *      BCM_E_XXX
    658  */
    659 int
    660 bcm_th_port_last_member_check(int unit, bcm_port_t port, int *val)
    661 {
    662     int pipe;
    663     bcm_trunk_t tgid;
    664     _bcm_th_port_aggid_info_t *port_aggid_info;
    665     int i;
    666     int member_cnt = 0;
    667 
    668     if (port < 0 || port >= SOC_MAX_NUM_PORTS) {
    669         return BCM_E_PARAM;
    670     }
    671 
    672     pipe = SOC_INFO(unit).port_pipe[port];
    673 
    674     port_aggid_info = &(th_port_aggid[unit][port]);
    675     tgid = port_aggid_info->trunk_id;
    676     if (tgid == BCM_TRUNK_INVALID) {
    677         return BCM_E_PARAM;
    678     }
    679 
    680     for (i = 0; i < SOC_MAX_NUM_PORTS; i++) {
    681         if (member_cnt > 1) {
    682             *val = FALSE;
    683             return BCM_E_NONE;
    684         }
    685         port_aggid_info = &(th_port_aggid[unit][i]);
    686 #ifdef BCM_TOMAHAWK3_SUPPORT
    687        if (SOC_IS_TOMAHAWK3(unit)) {
    688            if (port_aggid_info->trunk_id == tgid) {
    689                member_cnt++;
    690            }
    691        } else
    692 #endif
    693         if ((port_aggid_info->trunk_id == tgid) &&
    694             (SOC_INFO(unit).port_pipe[i] == pipe)) {
    695             member_cnt++;
    696         }
    697     }
    698 
    699     if (member_cnt > 1) {
    700         *val = FALSE;
    701     } else {
    702         *val = TRUE;
    703     }
    704 
    705     return BCM_E_NONE;
    706 }
    707 
    708 /*
    709  * Function:
    710  *      bcm_th_port_to_aggid
    711  * Purpose:
    712  *      Get aggid value for a logical port.
    713  * Parameters:
    714  *      unit  - (IN)  Unit number.
    715  *      aggid - (OUT) Returned aggid.
    716  * Returns:
    717  *      BCM_E_XXX
    718  */
    719 int
    720 bcm_th_port_to_aggid(int unit, bcm_port_t port, int *aggid)
    721 {
    722     int pipe;
    723     bcm_trunk_t tgid;
    724     _bcm_th_port_aggid_info_t *port_aggid_info;
    725     _bcm_th_trunk_aggid_info_t *trunk_aggid_info;
    726 
    727     if (port < 0 || port >= SOC_MAX_NUM_PORTS) {
    728         return BCM_E_PARAM;
    729     }
    730 
    731     pipe = SOC_INFO(unit).port_pipe[port];
    732 #ifdef BCM_TOMAHAWK3_SUPPORT
    733     if(SOC_IS_TOMAHAWK3(unit)) {
    734         pipe = 0;
    735     }
    736 #endif
    737     port_aggid_info = &(th_port_aggid[unit][port]);
    738     tgid = port_aggid_info->trunk_id;
    739     if (tgid == BCM_TRUNK_INVALID) {
    740         *aggid = port_aggid_info->agg_id;
    741     } else {
    742         trunk_aggid_info = &(th_trunk_aggid[unit][pipe].trunk_aggid_info[tgid]);
    743         *aggid = trunk_aggid_info->agg_id;
    744     }
    745     if (*aggid == TH_AGG_ID_INVALID) {
    746         return BCM_E_INTERNAL;
    747     }
    748 
    749     return BCM_E_NONE;
    750 }
    751 
    752 
    753 #ifdef BCM_WARM_BOOT_SUPPORT
    754 /*
    755  * Function:
    756  *      bcm_th_ipmc_aggid_info_scache_size_get
    757  * Purpose:
    758  *      Get the required scache size for storing aggid info.
    759  * Parameters:
    760  *      unit - (IN)  StrataSwitch unit #
    761  *      size - (OUT) Number of bytes
    762  * Returns:
    763  *      BCM_E_xxx
    764  */
    765 int
    766 bcm_th_ipmc_aggid_info_scache_size_get(
    767     int unit, uint32 *size)
    768 {
    769     int   num_pipes;
    770     int aggid_used_bmp_size, trunk_aggid_size, port_aggid_size;
    771 
    772     *size = 0;
    773 
    774     num_pipes = NUM_PIPE(unit);
    775 #ifdef BCM_TOMAHAWK3_SUPPORT
    776     if(SOC_IS_TOMAHAWK3(unit)) {
    777         /* IPMC repl is pipe independent in TH3 */
    778         num_pipes = 1;
    779     }
    780 #endif
    781     aggid_used_bmp_size =
    782         num_pipes * SHR_BITALLOCSIZE(_TH_NUM_AGGID_PER_PIPE(unit));
    783     *size += aggid_used_bmp_size;
    784 
    785     trunk_aggid_size =
    786         num_pipes * (_TH_NUM_TRUNKS(unit) * sizeof(_bcm_th_trunk_aggid_info_t));
    787     *size += trunk_aggid_size;
    788 
    789     port_aggid_size = SOC_MAX_NUM_PORTS * sizeof(_bcm_th_port_aggid_info_t);
    790     *size += port_aggid_size;
    791 
    792     return BCM_E_NONE;
    793 }
    794 
    795 /*
    796  * Function:
    797  *      bcm_th_ipmc_aggid_info_sync
    798  * Purpose:
    799  *      Sync aggid info to scache.
    800  * Parameters:
    801  *      unit       - (IN)     StrataSwitch unit #
    802  *      scache_ptr - (IN/OUT) Scache pointer
    803  * Returns:
    804  *      BCM_E_xxx
    805  */
    806 int bcm_th_ipmc_aggid_info_sync(int unit, uint8 **scache_ptr)
    807 {
    808     int num_pipes;
    809     int aggid_used_bmp_size, trunk_aggid_size, port_aggid_size;
    810     int i;
    811 
    812     num_pipes = NUM_PIPE(unit);
    813 #ifdef BCM_TOMAHAWK3_SUPPORT
    814     if(SOC_IS_TOMAHAWK3(unit)) {
    815         /* IPMC repl is pipe independent in TH3 */
    816         num_pipes = 1;
    817     }
    818 #endif
    819     aggid_used_bmp_size = SHR_BITALLOCSIZE(_TH_NUM_AGGID_PER_PIPE(unit));
    820     for (i = 0; i < num_pipes; i++) {
    821         sal_memcpy((*scache_ptr), th_aggid_used_bmp[unit][i].pipe_aggid_bmp,
    822                    aggid_used_bmp_size);
    823         (*scache_ptr) += aggid_used_bmp_size;
    824     }
    825 
    826     trunk_aggid_size = _TH_NUM_TRUNKS(unit) * sizeof(_bcm_th_trunk_aggid_info_t);
    827     for (i = 0; i < num_pipes; i++) {
    828         sal_memcpy((*scache_ptr), th_trunk_aggid[unit] + i, trunk_aggid_size);
    829         (*scache_ptr) += trunk_aggid_size;
    830     }
    831 
    832     port_aggid_size = SOC_MAX_NUM_PORTS * sizeof(_bcm_th_port_aggid_info_t);
    833     sal_memcpy((*scache_ptr), th_port_aggid[unit], port_aggid_size);
    834     (*scache_ptr) += port_aggid_size;
    835 
    836     return BCM_E_NONE;
    837 }
    838 
    839 
    840 /*
    841  * Function:
    842  *      bcm_th_ipmc_aggid_info_recover
    843  * Purpose:
    844  *      Recover aggid info from scache.
    845  * Parameters:
    846  *      unit       - (IN)     StrataSwitch unit #
    847  *      scache_ptr - (IN/OUT) Scache pointer
    848  * Returns:
    849  *      BCM_E_xxx
    850  */
    851 int
    852 bcm_th_ipmc_aggid_info_recover(int unit, uint8 **scache_ptr)
    853 {
    854     int   num_pipes;
    855     int aggid_used_bmp_size, trunk_aggid_size, port_aggid_size;
    856     int i;
    857     int max_num_ports, scache_sz;
    858 
    859     max_num_ports = soc_scache_dictionary_entry_get(unit, 
    860                                  ssden_SOC_MAX_NUM_PORTS,
    861                                  SOC_MAX_NUM_PORTS);
    862     num_pipes = NUM_PIPE(unit);
    863 #ifdef BCM_TOMAHAWK3_SUPPORT
    864     if(SOC_IS_TOMAHAWK3(unit)) {
    865         /* IPMC repl is pipe independent in TH3 */
    866         num_pipes = 1;
    867     }
    868 #endif
    869     aggid_used_bmp_size = SHR_BITALLOCSIZE(_TH_NUM_AGGID_PER_PIPE(unit));
    870     for (i = 0; i < num_pipes; i++) {
    871         sal_memcpy(th_aggid_used_bmp[unit][i].pipe_aggid_bmp,
    872                    (*scache_ptr), aggid_used_bmp_size);
    873         (*scache_ptr) += aggid_used_bmp_size;
    874     }
    875 
    876     trunk_aggid_size = _TH_NUM_TRUNKS(unit) * sizeof(_bcm_th_trunk_aggid_info_t);
    877     for (i = 0; i < num_pipes; i++) {
    878         sal_memcpy(th_trunk_aggid[unit] + i, (*scache_ptr), trunk_aggid_size);
    879         (*scache_ptr) += trunk_aggid_size;
    880     }
    881 
    882     port_aggid_size = SOC_MAX_NUM_PORTS * sizeof(_bcm_th_port_aggid_info_t);
    883     scache_sz = max_num_ports * sizeof(_bcm_th_port_aggid_info_t);
    884 
    885     SOC_SCACHE_SIZE_MIN_RECOVER(*scache_ptr, th_port_aggid[unit], 
    886                                 scache_sz, port_aggid_size);
    887 
    888     return BCM_E_NONE;
    889 }
    890 
    891 #endif /* BCM_WARM_BOOT_SUPPORT */
    892 
    893 #endif
    894