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

ipmc.c (207303B)


      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:        ipmc.c
      8  * Purpose:     Tracks and manages IPMC tables.
      9  */
     10 
     11 #ifdef INCLUDE_L3
     12 #include <shared/bsl.h>
     13 #include <soc/l3x.h>
     14 #if defined(BCM_BRADLEY_SUPPORT)
     15 #include <soc/bradley.h>
     16 #endif /* BCM_BRADLEY_SUPPORT */
     17 
     18 #include <bcm/error.h>
     19 #include <bcm/stack.h>
     20 
     21 #include <bcm_int/esw/ipmc.h>
     22 #include <bcm_int/esw/mbcm.h>
     23 #include <bcm_int/esw/firebolt.h>
     24 #include <bcm_int/esw/stack.h>
     25 #include <bcm_int/common/multicast.h>
     26 #include <bcm_int/esw/multicast.h>
     27 #include <bcm_int/esw_dispatch.h>
     28 #if defined(BCM_BRADLEY_SUPPORT)
     29 #include <bcm_int/esw/bradley.h>
     30 #endif /* BCM_BRADLEY_SUPPORT */
     31 
     32 #include <bcm_int/esw_dispatch.h>
     33 
     34 #define REPL_PORT_CHECK(unit, port) \
     35     if (!IS_PORT(unit, port)) { return BCM_E_PARAM; }
     36 
     37 #if defined(BCM_FIREBOLT_SUPPORT)
     38 typedef struct _fb_repl_port_info_s {
     39     uint32 *vlan_count;                       /* # VLANs the port repl to */
     40     uint32 emc_val;                           /* EGRMETERINGCONFIG value */
     41 } _fb_repl_port_info_t;
     42 
     43 typedef struct _fb_repl_info_s {
     44     int ipmc_size;
     45     uint32 intf_num;              /* Number of interfaces on this device */
     46     uint16 ipmc_vlan_total;       /* Keep track of total and */
     47     uint32 *bitmap_entries_used;  /* free entries of IPMC_VLAN table */
     48     _bcm_repl_list_info_t *repl_list_info;
     49     _fb_repl_port_info_t *port_info[SOC_MAX_NUM_PORTS];
     50 
     51     /* Per port replication info */
     52     int *l3_intf_to_l3_nh_ipmc; /* L3_NH array : for L3_INTF based IPMC repl */
     53     int *l3_nh_to_l3_intf_ipmc;
     54 } _fb_repl_info_t;
     55 
     56 static _fb_repl_info_t *_fb_repl_info[BCM_MAX_NUM_UNITS];
     57 
     58 #define IPMC_REPL_LOCK(_u_)                    \
     59     {                                          \
     60         soc_mem_lock(_u_, MMU_IPMC_VLAN_TBLm); \
     61     }
     62 #define IPMC_REPL_UNLOCK(_u_)                    \
     63     {                                            \
     64         soc_mem_unlock(_u_, MMU_IPMC_VLAN_TBLm); \
     65     }
     66 #define IPMC_REPL_ID(_u_, _id_) \
     67         if ((_id_ < 0) || (_id_ >= _fb_repl_info[_u_]->ipmc_size)) \
     68             { return BCM_E_PARAM; }
     69 #define IPMC_REPL_INIT(unit) \
     70         if (_fb_repl_info[unit] == NULL) { return BCM_E_INIT; }
     71 #define IPMC_REPL_TOTAL(_u_) \
     72         _fb_repl_info[_u_]->ipmc_vlan_total
     73 #define IPMC_REPL_GROUP_NUM(_u_) \
     74         _fb_repl_info[_u_]->ipmc_size
     75 #define IPMC_REPL_INTF_TOTAL(_u_) \
     76         _fb_repl_info[_u_]->intf_num
     77 #define IPMC_REPL_VE_USED_GET(_u_, _i_) \
     78         SHR_BITGET(_fb_repl_info[_u_]->bitmap_entries_used, _i_)
     79 #define IPMC_REPL_VE_USED_SET(_u_, _i_) \
     80         SHR_BITSET(_fb_repl_info[_u_]->bitmap_entries_used, _i_)
     81 #define IPMC_REPL_VE_USED_CLR(_u_, _i_) \
     82         SHR_BITCLR(_fb_repl_info[_u_]->bitmap_entries_used, _i_)
     83 
     84 #define IPMC_REPL_LIST_INFO(_u_) \
     85 	_fb_repl_info[_u_]->repl_list_info
     86 #define IPMC_REPL_PORT_INFO(_u_, _p_) \
     87         _fb_repl_info[_u_]->port_info[_p_]
     88 #define IPMC_REPL_PORT_VLAN_COUNT(_u_, _p_, _ipmc_id_) \
     89         _fb_repl_info[_u_]->port_info[_p_]->vlan_count[_ipmc_id_]
     90 
     91 #define IPMC_REPL_L3_INTF_TO_L3_NH_IPMC(_u_, _intf_) \
     92         _fb_repl_info[(_u_)]->l3_intf_to_l3_nh_ipmc[(_intf_)]
     93 
     94 #define IPMC_REPL_L3_NH_TO_L3_INTF_IPMC(_u_, nh_id) \
     95         _fb_repl_info[(_u_)]->l3_nh_to_l3_intf_ipmc[(nh_id)]
     96 
     97 #define REPL_NH_INDEX_UNALLOCATED (-1)
     98 #define REPL_L3_INTF_UNALLOCATED (-1)
     99 
    100 
    101 typedef struct _rep_regs_s {
    102     soc_field_t port_ptr;
    103     soc_field_t last_ptr;
    104     soc_mem_t   mem;
    105 }_rep_regs_t;
    106 
    107 
    108 _rep_regs_t fb_rep_regs[28] = { {PORT0_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    109                                 {PORT1_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    110                                 {PORT2_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    111                                 {PORT3_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    112                                 {PORT4_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    113                                 {PORT5_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    114                                 {PORT6_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    115                                 {PORT7_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    116                                 {PORT8_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    117                                 {PORT9_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    118                                 {PORT10_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m},
    119                                 {PORT11_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL1m},
    120                                 {PORT12_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL2m},
    121                                 {PORT13_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL2m},
    122                                 {PORT14_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL2m},
    123                                 {PORT15_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL2m},
    124                                 {PORT16_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL2m},
    125                                 {PORT17_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL2m},
    126                                 {PORT18_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL3m},
    127                                 {PORT19_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL3m},
    128                                 {PORT20_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL3m},
    129                                 {PORT21_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL3m},
    130                                 {PORT22_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL3m},
    131                                 {PORT23_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL3m},
    132                                 {PORT24_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL4m},
    133                                 {PORT25_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL5m},
    134                                 {PORT26_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL6m},
    135                                 {PORT27_1STPTRf, INVALIDf, MMU_IPMC_GROUP_TBL7m}
    136 };
    137 #if defined(BCM_HB_GW_SUPPORT)
    138 _rep_regs_t hbgw_rep_regs[20] = { {PORT0_1STPTRf,  PORT0_LASTf, MMU_IPMC_GROUP_TBL0m},
    139                                   {PORT1_1STPTRf,  PORT1_LASTf, MMU_IPMC_GROUP_TBL0m},
    140                                   {PORT2_1STPTRf,  PORT2_LASTf, MMU_IPMC_GROUP_TBL0m},
    141                                   {PORT3_1STPTRf,  PORT3_LASTf, MMU_IPMC_GROUP_TBL0m},
    142                                   {PORT4_1STPTRf,  PORT4_LASTf, MMU_IPMC_GROUP_TBL0m},
    143                                   {PORT5_1STPTRf,  PORT5_LASTf, MMU_IPMC_GROUP_TBL1m},
    144                                   {PORT6_1STPTRf,  PORT6_LASTf, MMU_IPMC_GROUP_TBL1m},
    145                                   {PORT7_1STPTRf,  PORT7_LASTf, MMU_IPMC_GROUP_TBL1m},
    146                                   {PORT8_1STPTRf,  PORT8_LASTf, MMU_IPMC_GROUP_TBL1m},
    147                                   {PORT9_1STPTRf,  PORT9_LASTf, MMU_IPMC_GROUP_TBL1m},
    148                                   {PORT10_1STPTRf,  PORT10_LASTf, MMU_IPMC_GROUP_TBL2m},
    149                                   {PORT11_1STPTRf,  PORT11_LASTf, MMU_IPMC_GROUP_TBL2m},
    150                                   {PORT12_1STPTRf,  PORT12_LASTf, MMU_IPMC_GROUP_TBL2m},
    151                                   {PORT13_1STPTRf,  PORT13_LASTf, MMU_IPMC_GROUP_TBL2m},
    152                                   {PORT14_1STPTRf,  PORT14_LASTf, MMU_IPMC_GROUP_TBL2m},
    153                                   {PORT15_1STPTRf,  PORT15_LASTf, MMU_IPMC_GROUP_TBL3m},
    154                                   {PORT16_1STPTRf,  PORT16_LASTf, MMU_IPMC_GROUP_TBL3m},
    155                                   {PORT17_1STPTRf,  PORT17_LASTf, MMU_IPMC_GROUP_TBL3m},
    156                                   {PORT18_1STPTRf,  PORT18_LASTf, MMU_IPMC_GROUP_TBL3m},
    157                                   {PORT19_1STPTRf,  PORT19_LASTf, MMU_IPMC_GROUP_TBL3m}
    158 };
    159 #endif 
    160 #if defined (BCM_SCORPION_SUPPORT)
    161 _rep_regs_t sco_rep_regs[29] = {  {INVALIDf,       INVALIDf,    INVALIDm},
    162                                   {PORT1_1STPTRf,  PORT1_LASTf, MMU_IPMC_GROUP_TBL0m},
    163                                   {PORT2_1STPTRf,  PORT2_LASTf, MMU_IPMC_GROUP_TBL0m},
    164                                   {PORT3_1STPTRf,  PORT3_LASTf, MMU_IPMC_GROUP_TBL0m},
    165                                   {PORT4_1STPTRf,  PORT4_LASTf, MMU_IPMC_GROUP_TBL0m},
    166                                   {PORT5_1STPTRf,  PORT5_LASTf, MMU_IPMC_GROUP_TBL1m},
    167                                   {PORT6_1STPTRf,  PORT6_LASTf, MMU_IPMC_GROUP_TBL1m},
    168                                   {PORT7_1STPTRf,  PORT7_LASTf, MMU_IPMC_GROUP_TBL1m},
    169                                   {PORT8_1STPTRf,  PORT8_LASTf, MMU_IPMC_GROUP_TBL1m},
    170                                   {PORT9_1STPTRf,  PORT9_LASTf, MMU_IPMC_GROUP_TBL2m},
    171                                   {PORT10_1STPTRf,  PORT10_LASTf, MMU_IPMC_GROUP_TBL2m},
    172                                   {PORT11_1STPTRf,  PORT11_LASTf, MMU_IPMC_GROUP_TBL2m},
    173                                   {PORT12_1STPTRf,  PORT12_LASTf, MMU_IPMC_GROUP_TBL2m},
    174                                   {PORT13_1STPTRf,  PORT13_LASTf, MMU_IPMC_GROUP_TBL3m},
    175                                   {PORT14_1STPTRf,  PORT14_LASTf, MMU_IPMC_GROUP_TBL3m},
    176                                   {PORT15_1STPTRf,  PORT15_LASTf, MMU_IPMC_GROUP_TBL3m},
    177                                   {PORT16_1STPTRf,  PORT16_LASTf, MMU_IPMC_GROUP_TBL3m},
    178                                   {PORT17_1STPTRf,  PORT17_LASTf, MMU_IPMC_GROUP_TBL4m},
    179                                   {PORT18_1STPTRf,  PORT18_LASTf, MMU_IPMC_GROUP_TBL4m},
    180                                   {PORT19_1STPTRf,  PORT19_LASTf, MMU_IPMC_GROUP_TBL4m},
    181                                   {PORT20_1STPTRf,  PORT20_LASTf, MMU_IPMC_GROUP_TBL4m},
    182                                   {PORT21_1STPTRf,  PORT21_LASTf, MMU_IPMC_GROUP_TBL5m},
    183                                   {PORT22_1STPTRf,  PORT22_LASTf, MMU_IPMC_GROUP_TBL5m},
    184                                   {PORT23_1STPTRf,  PORT23_LASTf, MMU_IPMC_GROUP_TBL5m},
    185                                   {PORT24_1STPTRf,  PORT24_LASTf, MMU_IPMC_GROUP_TBL5m},
    186                                   {PORT25_1STPTRf,  PORT25_LASTf, MMU_IPMC_GROUP_TBL6m},
    187                                   {PORT26_1STPTRf,  PORT26_LASTf, MMU_IPMC_GROUP_TBL6m},
    188                                   {PORT27_1STPTRf,  PORT27_LASTf, MMU_IPMC_GROUP_TBL6m},
    189                                   {PORT28_1STPTRf,  PORT28_LASTf, MMU_IPMC_GROUP_TBL6m}
    190 };
    191 #endif 
    192 #if defined(BCM_RAVEN_SUPPORT)
    193 _rep_regs_t rvn_rep_regs[30] = {  {INVALIDf,       INVALIDf, INVALIDm},
    194                                   {PORT1_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    195                                   {PORT2_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    196                                   {PORT3_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    197                                   {PORT4_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    198                                   {PORT5_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    199                                   {PORT6_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    200                                   {PORT7_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    201                                   {PORT8_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    202                                   {PORT9_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    203                                   {PORT10_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    204                                   {PORT11_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    205                                   {PORT12_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    206                                   {PORT13_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    207                                   {PORT14_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    208                                   {PORT15_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    209                                   {PORT16_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    210                                   {PORT17_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    211                                   {PORT18_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    212                                   {PORT19_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    213                                   {PORT20_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    214                                   {PORT21_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL2m},
    215                                   {PORT22_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL2m},
    216                                   {PORT23_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL2m},
    217                                   {PORT24_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL2m},
    218                                   {PORT25_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL2m},
    219                                   {PORT26_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL2m},
    220                                   {PORT27_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL2m},
    221                                   {PORT28_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL2m},
    222                                   {PORT29_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL2m}
    223 };
    224 #endif /* BCM_RAVEN_SUPPORT */
    225 #if defined(BCM_TRIUMPH_SUPPORT)
    226 _rep_regs_t tr_rep_regs[55] = { {INVALIDf,       INVALIDf,    INVALIDm},
    227                                 {PORT1_1STPTRf,  PORT1_LASTf, MMU_IPMC_GROUP_TBL0m},
    228                                 {PORT2_1STPTRf,  PORT2_LASTf, MMU_IPMC_GROUP_TBL0m},
    229                                 {PORT3_1STPTRf,  PORT3_LASTf, MMU_IPMC_GROUP_TBL0m},
    230                                 {PORT4_1STPTRf,  PORT4_LASTf, MMU_IPMC_GROUP_TBL0m},
    231                                 {PORT5_1STPTRf,  PORT5_LASTf, MMU_IPMC_GROUP_TBL0m},
    232                                 {PORT6_1STPTRf,  PORT6_LASTf, MMU_IPMC_GROUP_TBL0m},
    233                                 {PORT7_1STPTRf,  PORT7_LASTf, MMU_IPMC_GROUP_TBL1m},
    234                                 {PORT8_1STPTRf,  PORT8_LASTf, MMU_IPMC_GROUP_TBL1m},
    235                                 {PORT9_1STPTRf,  PORT9_LASTf, MMU_IPMC_GROUP_TBL1m},
    236                                 {PORT10_1STPTRf,  PORT10_LASTf, MMU_IPMC_GROUP_TBL1m},
    237                                 {PORT11_1STPTRf,  PORT11_LASTf, MMU_IPMC_GROUP_TBL1m},
    238                                 {PORT12_1STPTRf,  PORT12_LASTf, MMU_IPMC_GROUP_TBL1m},
    239                                 {PORT13_1STPTRf,  PORT13_LASTf, MMU_IPMC_GROUP_TBL2m},
    240                                 {PORT14_1STPTRf,  PORT14_LASTf, MMU_IPMC_GROUP_TBL2m},
    241                                 {PORT15_1STPTRf,  PORT15_LASTf, MMU_IPMC_GROUP_TBL2m},
    242                                 {PORT16_1STPTRf,  PORT16_LASTf, MMU_IPMC_GROUP_TBL2m},
    243                                 {PORT17_1STPTRf,  PORT17_LASTf, MMU_IPMC_GROUP_TBL2m},
    244                                 {PORT18_1STPTRf,  PORT18_LASTf, MMU_IPMC_GROUP_TBL2m},
    245                                 {PORT19_1STPTRf,  PORT19_LASTf, MMU_IPMC_GROUP_TBL3m},
    246                                 {PORT20_1STPTRf,  PORT20_LASTf, MMU_IPMC_GROUP_TBL3m},
    247                                 {PORT21_1STPTRf,  PORT21_LASTf, MMU_IPMC_GROUP_TBL3m},
    248                                 {PORT22_1STPTRf,  PORT22_LASTf, MMU_IPMC_GROUP_TBL3m},
    249                                 {PORT23_1STPTRf,  PORT23_LASTf, MMU_IPMC_GROUP_TBL3m},
    250                                 {PORT24_1STPTRf,  PORT24_LASTf, MMU_IPMC_GROUP_TBL3m},
    251                                 {PORT25_1STPTRf,  PORT25_LASTf, MMU_IPMC_GROUP_TBL4m},
    252                                 {PORT26_1STPTRf,  PORT26_LASTf, MMU_IPMC_GROUP_TBL4m},
    253                                 {PORT27_1STPTRf,  PORT27_LASTf, MMU_IPMC_GROUP_TBL4m},
    254                                 {PORT28_1STPTRf,  PORT28_LASTf, MMU_IPMC_GROUP_TBL4m},
    255                                 {PORT29_1STPTRf,  PORT29_LASTf, MMU_IPMC_GROUP_TBL4m},
    256                                 {PORT30_1STPTRf,  PORT30_LASTf, MMU_IPMC_GROUP_TBL4m},
    257                                 {PORT31_1STPTRf,  PORT31_LASTf, MMU_IPMC_GROUP_TBL5m},
    258                                 {PORT32_1STPTRf,  PORT32_LASTf, MMU_IPMC_GROUP_TBL5m},
    259                                 {PORT33_1STPTRf,  PORT33_LASTf, MMU_IPMC_GROUP_TBL5m},
    260                                 {PORT34_1STPTRf,  PORT34_LASTf, MMU_IPMC_GROUP_TBL5m},
    261                                 {PORT35_1STPTRf,  PORT35_LASTf, MMU_IPMC_GROUP_TBL5m},
    262                                 {PORT36_1STPTRf,  PORT36_LASTf, MMU_IPMC_GROUP_TBL5m},
    263                                 {PORT37_1STPTRf,  PORT37_LASTf, MMU_IPMC_GROUP_TBL6m},
    264                                 {PORT38_1STPTRf,  PORT38_LASTf, MMU_IPMC_GROUP_TBL6m},
    265                                 {PORT39_1STPTRf,  PORT39_LASTf, MMU_IPMC_GROUP_TBL6m},
    266                                 {PORT40_1STPTRf,  PORT40_LASTf, MMU_IPMC_GROUP_TBL6m},
    267                                 {PORT41_1STPTRf,  PORT41_LASTf, MMU_IPMC_GROUP_TBL6m},
    268                                 {PORT42_1STPTRf,  PORT42_LASTf, MMU_IPMC_GROUP_TBL6m},
    269                                 {PORT43_1STPTRf,  PORT43_LASTf, MMU_IPMC_GROUP_TBL7m},
    270                                 {PORT44_1STPTRf,  PORT44_LASTf, MMU_IPMC_GROUP_TBL7m},
    271                                 {PORT45_1STPTRf,  PORT45_LASTf, MMU_IPMC_GROUP_TBL7m},
    272                                 {PORT46_1STPTRf,  PORT46_LASTf, MMU_IPMC_GROUP_TBL7m},
    273                                 {PORT47_1STPTRf,  PORT47_LASTf, MMU_IPMC_GROUP_TBL7m},
    274                                 {PORT48_1STPTRf,  PORT48_LASTf, MMU_IPMC_GROUP_TBL7m},
    275                                 {PORT49_1STPTRf,  PORT49_LASTf, MMU_IPMC_GROUP_TBL8m},
    276                                 {PORT50_1STPTRf,  PORT50_LASTf, MMU_IPMC_GROUP_TBL8m},
    277                                 {PORT51_1STPTRf,  PORT51_LASTf, MMU_IPMC_GROUP_TBL8m},
    278                                 {PORT52_1STPTRf,  PORT52_LASTf, MMU_IPMC_GROUP_TBL8m},
    279                                 {PORT53_1STPTRf,  PORT53_LASTf, MMU_IPMC_GROUP_TBL8m},
    280 };
    281 #endif
    282 
    283 #if defined(BCM_ENDURO_SUPPORT)
    284 _rep_regs_t en_rep_regs[] = { {INVALIDf,       INVALIDf,    INVALIDm},
    285                               {INVALIDf,       INVALIDf,    INVALIDm},
    286                               {PORT2_1STPTRf,  PORT2_LASTf, MMU_IPMC_GROUP_TBL0m},
    287                               {PORT3_1STPTRf,  PORT3_LASTf, MMU_IPMC_GROUP_TBL0m}, 
    288                               {PORT4_1STPTRf,  PORT4_LASTf, MMU_IPMC_GROUP_TBL0m}, 
    289                               {PORT5_1STPTRf,  PORT5_LASTf, MMU_IPMC_GROUP_TBL0m},
    290                               {PORT6_1STPTRf,  PORT6_LASTf, MMU_IPMC_GROUP_TBL0m},
    291                               {PORT7_1STPTRf,  PORT7_LASTf, MMU_IPMC_GROUP_TBL0m},
    292                               {PORT8_1STPTRf,  PORT8_LASTf, MMU_IPMC_GROUP_TBL0m},
    293                               {PORT9_1STPTRf,  PORT9_LASTf, MMU_IPMC_GROUP_TBL1m},
    294                               {PORT10_1STPTRf,  PORT10_LASTf, MMU_IPMC_GROUP_TBL1m},
    295                               {PORT11_1STPTRf,  PORT11_LASTf, MMU_IPMC_GROUP_TBL1m},
    296                               {PORT12_1STPTRf,  PORT12_LASTf, MMU_IPMC_GROUP_TBL1m},
    297                               {PORT13_1STPTRf,  PORT13_LASTf, MMU_IPMC_GROUP_TBL1m},
    298                               {PORT14_1STPTRf,  PORT14_LASTf, MMU_IPMC_GROUP_TBL1m},
    299                               {PORT15_1STPTRf,  PORT15_LASTf, MMU_IPMC_GROUP_TBL1m},
    300                               {PORT16_1STPTRf,  PORT16_LASTf, MMU_IPMC_GROUP_TBL2m},
    301                               {PORT17_1STPTRf,  PORT17_LASTf, MMU_IPMC_GROUP_TBL2m},
    302                               {PORT18_1STPTRf,  PORT18_LASTf, MMU_IPMC_GROUP_TBL2m},
    303                               {PORT19_1STPTRf,  PORT19_LASTf, MMU_IPMC_GROUP_TBL2m},
    304                               {PORT20_1STPTRf,  PORT20_LASTf, MMU_IPMC_GROUP_TBL2m},
    305                               {PORT21_1STPTRf,  PORT21_LASTf, MMU_IPMC_GROUP_TBL2m},
    306                               {PORT22_1STPTRf,  PORT22_LASTf, MMU_IPMC_GROUP_TBL2m},
    307                               {PORT23_1STPTRf,  PORT23_LASTf, MMU_IPMC_GROUP_TBL3m},                         
    308                               {PORT24_1STPTRf,  PORT24_LASTf, MMU_IPMC_GROUP_TBL3m},
    309                               {PORT25_1STPTRf,  PORT25_LASTf, MMU_IPMC_GROUP_TBL3m},
    310                               {PORT26_1STPTRf,  PORT26_LASTf, MMU_IPMC_GROUP_TBL3m},
    311                               {PORT27_1STPTRf,  PORT27_LASTf, MMU_IPMC_GROUP_TBL3m},
    312                               {PORT28_1STPTRf,  PORT28_LASTf, MMU_IPMC_GROUP_TBL3m},
    313                               {PORT29_1STPTRf,  PORT29_LASTf, MMU_IPMC_GROUP_TBL3m},
    314 };
    315 #endif
    316 #if defined(BCM_HURRICANE_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT)
    317 _rep_regs_t hu_rep_regs[30] = {  {INVALIDf,       INVALIDf, INVALIDm},
    318                                   {INVALIDf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    319                                   {PORT2_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    320                                   {PORT3_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    321                                   {PORT4_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    322                                   {PORT5_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    323                                   {PORT6_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    324                                   {PORT7_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    325                                   {PORT8_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    326                                   {PORT9_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    327                                   {PORT10_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    328                                   {PORT11_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    329                                   {PORT12_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    330                                   {PORT13_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL0m},
    331                                   {PORT14_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    332                                   {PORT15_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    333                                   {PORT16_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    334                                   {PORT17_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    335                                   {PORT18_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    336                                   {PORT19_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    337                                   {PORT20_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    338                                   {PORT21_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    339                                   {PORT22_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    340                                   {PORT23_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    341                                   {PORT24_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    342                                   {PORT25_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL1m},
    343                                   {PORT26_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL2m},
    344                                   {PORT27_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL3m},
    345                                   {PORT28_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL4m},
    346                                   {PORT29_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL5m}
    347 };
    348 #endif /* BCM_HURRICANE_SUPPORT */
    349 
    350 #if defined(BCM_GREYHOUND_SUPPORT)
    351 _rep_regs_t gh_rep_regs[30] = {  {INVALIDf,     INVALIDf, INVALIDm},
    352                                   {INVALIDf,    INVALIDf, INVALIDm},
    353                                   {PORT2_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL2m},
    354                                   {PORT3_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL3m},
    355                                   {PORT4_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL4m},
    356                                   {PORT5_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL5m},
    357                                   {PORT6_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL6m},
    358                                   {PORT7_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL7m},
    359                                   {PORT8_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL8m},
    360                                   {PORT9_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL9m},
    361                                   {PORT10_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL10m},
    362                                   {PORT11_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL11m},
    363                                   {PORT12_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL12m},
    364                                   {PORT13_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL13m},
    365                                   {PORT14_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL14m},
    366                                   {PORT15_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL15m},
    367                                   {PORT16_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL16m},
    368                                   {PORT17_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL17m},
    369                                   {PORT18_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL18m},
    370                                   {PORT19_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL19m},
    371                                   {PORT20_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL20m},
    372                                   {PORT21_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL21m},
    373                                   {PORT22_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL22m},
    374                                   {PORT23_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL23m},
    375                                   {PORT24_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL24m},
    376                                   {PORT25_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL25m},
    377                                   {PORT26_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL26m},
    378                                   {PORT27_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL27m},
    379                                   {PORT28_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL28m},
    380                                   {PORT29_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL29m}
    381 };
    382 #endif /* BCM_GREYHOUND_SUPPORT */
    383 
    384 #if defined(BCM_HURRICANE3_SUPPORT)
    385 _rep_regs_t hr3_rep_regs[32] = {  {INVALIDf,     INVALIDf, INVALIDm},
    386                                   {INVALIDf,    INVALIDf, INVALIDm},
    387                                   {PORT2_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL2m},
    388                                   {PORT3_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL3m},
    389                                   {PORT4_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL4m},
    390                                   {PORT5_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL5m},
    391                                   {PORT6_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL6m},
    392                                   {PORT7_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL7m},
    393                                   {PORT8_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL8m},
    394                                   {PORT9_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL9m},
    395                                   {PORT10_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL10m},
    396                                   {PORT11_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL11m},
    397                                   {PORT12_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL12m},
    398                                   {PORT13_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL13m},
    399                                   {PORT14_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL14m},
    400                                   {PORT15_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL15m},
    401                                   {PORT16_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL16m},
    402                                   {PORT17_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL17m},
    403                                   {PORT18_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL18m},
    404                                   {PORT19_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL19m},
    405                                   {PORT20_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL20m},
    406                                   {PORT21_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL21m},
    407                                   {PORT22_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL22m},
    408                                   {PORT23_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL23m},
    409                                   {PORT24_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL24m},
    410                                   {PORT25_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL25m},
    411                                   {PORT26_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL26m},
    412                                   {PORT27_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL27m},
    413                                   {PORT28_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL28m},
    414                                   {PORT29_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL29m},
    415                                   {PORT30_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL30m},
    416                                   {PORT31_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL31m}
    417 };
    418 #endif /* BCM_HURRICANE3_SUPPORT */
    419 #if defined(BCM_GREYHOUND2_SUPPORT)
    420 _rep_regs_t gh2_rep_regs[66] = {  {INVALIDf,     INVALIDf, INVALIDm},
    421                                   {INVALIDf,    INVALIDf, INVALIDm},
    422                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL2m},
    423                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL3m},
    424                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL4m},
    425                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL5m},
    426                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL6m},
    427                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL7m},
    428                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL8m},
    429                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL9m},
    430                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL10m},
    431                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL11m},
    432                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL12m},
    433                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL13m},
    434                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL14m},
    435                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL15m},
    436                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL16m},
    437                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL17m},
    438                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL18m},
    439                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL19m},
    440                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL20m},
    441                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL21m},
    442                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL22m},
    443                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL23m},
    444                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL24m},
    445                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL25m},
    446                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL26m},
    447                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL27m},
    448                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL28m},
    449                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL29m},
    450                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL30m},
    451                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL31m},
    452                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL32m},
    453                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL33m},
    454                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL34m},
    455                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL35m},
    456                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL36m},
    457                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL37m},
    458                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL38m},
    459                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL39m},
    460                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL40m},
    461                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL41m},
    462                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL42m},
    463                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL43m},
    464                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL44m},
    465                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL45m},
    466                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL46m},
    467                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL47m},
    468                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL48m},
    469                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL49m},
    470                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL50m},
    471                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL51m},
    472                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL52m},
    473                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL53m},
    474                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL54m},
    475                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL55m},
    476                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL56m},
    477                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL57m},
    478                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL58m},
    479                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL59m},
    480                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL60m},
    481                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL61m},
    482                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL62m},
    483                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL63m},
    484                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL64m},
    485                                   {PORT_1STPTRf,  INVALIDf, MMU_IPMC_GROUP_TBL65m}
    486 };
    487 #endif /* BCM_GREYHOUND2_SUPPORT */
    488 STATIC int
    489 _fb_ipmc_vlan_ptr(int unit,int ipmc_id,
    490                   bcm_port_t port, int *vptr, int last, int set)
    491 {
    492     soc_field_t  port_ptr = INVALIDf;
    493     soc_field_t  last_ptr = INVALIDf;
    494     soc_mem_t    mem = INVALIDm;
    495     mmu_ipmc_group_tbl0_entry_t gentry;
    496     int rv;
    497     _rep_regs_t     *rep_arr_ptr;
    498 #if defined(BCM_GREYHOUND2_SUPPORT)
    499     int mmu_port, phy_port = 0;
    500     const soc_field_t port_ptrf[8] = {
    501         PORT_1STPTR_0f, PORT_1STPTR_1f, PORT_1STPTR_2f, PORT_1STPTR_3f,
    502         PORT_1STPTR_4f, PORT_1STPTR_5f, PORT_1STPTR_6f, PORT_1STPTR_7f};
    503 #endif
    504 
    505     rep_arr_ptr = NULL;
    506     if (SOC_IS_FB_FX_HX(unit)) {
    507         rep_arr_ptr = fb_rep_regs;
    508     }
    509 #if defined(BCM_HB_GW_SUPPORT)
    510     if (SOC_IS_HB_GW(unit)) {
    511         rep_arr_ptr = hbgw_rep_regs;
    512     }
    513 #endif
    514 #if defined(BCM_RAVEN_SUPPORT)
    515     if (SOC_IS_RAVEN(unit)) {
    516         rep_arr_ptr = rvn_rep_regs;
    517     }
    518 #endif /* BCM_RAVEN_SUPPORT */
    519 #if defined(BCM_TRIUMPH_SUPPORT)
    520 #if defined(BCM_HURRICANE_SUPPORT)
    521     if (SOC_IS_HURRICANE(unit) || SOC_IS_HURRICANE2(unit)) {
    522         rep_arr_ptr = hu_rep_regs;
    523     } else 
    524 #endif /* BCM_HURRICANE_SUPPORT */
    525     if (SOC_IS_TR_VL(unit)) {
    526         rep_arr_ptr = tr_rep_regs;
    527     }
    528 #endif
    529 #if defined (BCM_SCORPION_SUPPORT)
    530     if (SOC_IS_SC_CQ(unit)) {
    531         rep_arr_ptr = sco_rep_regs;
    532     }
    533 #endif
    534 #if defined(BCM_ENDURO_SUPPORT)
    535     if (SOC_IS_ENDURO(unit)) {
    536       rep_arr_ptr = en_rep_regs;
    537     }
    538 #endif
    539 #if defined(BCM_GREYHOUND_SUPPORT)
    540     if (SOC_IS_GREYHOUND(unit)) {
    541       rep_arr_ptr = gh_rep_regs;
    542     }
    543 #endif
    544 #if defined(BCM_HURRICANE3_SUPPORT)
    545     if (SOC_IS_HURRICANE3(unit)) {
    546       rep_arr_ptr = hr3_rep_regs;
    547     }
    548 #endif
    549 #if defined(BCM_GREYHOUND2_SUPPORT)
    550     if (SOC_IS_GREYHOUND2(unit)) {
    551       rep_arr_ptr = gh2_rep_regs;
    552     }
    553 #endif
    554     if (NULL == rep_arr_ptr) {
    555         return BCM_E_UNIT;
    556     }
    557 
    558 #if defined(BCM_GREYHOUND2_SUPPORT)
    559     if (SOC_IS_GREYHOUND2(unit)) {
    560         phy_port = SOC_INFO(unit).port_l2p_mapping[port];
    561         mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port];
    562     } else {
    563         mmu_port = port;
    564     }
    565     mem = rep_arr_ptr[mmu_port].mem;
    566     port_ptr = rep_arr_ptr[mmu_port].port_ptr;
    567     last_ptr = rep_arr_ptr[mmu_port].last_ptr;
    568 #else
    569     mem = rep_arr_ptr[port].mem;
    570     port_ptr = rep_arr_ptr[port].port_ptr;
    571     last_ptr = rep_arr_ptr[port].last_ptr;
    572 #endif  /* BCM_GREYHOUND2_SUPPORT */
    573 
    574     if ((INVALIDm == mem) || (INVALIDf == port_ptr)){
    575         return BCM_E_PARAM;
    576     }
    577     soc_mem_lock(unit, mem);
    578 #if defined(BCM_GREYHOUND2_SUPPORT)
    579     if (SOC_MEM_FIELD_VALID(unit, mem, port_ptrf[0])) {
    580         /* length of ipmc_id exceed 10 bits using different hw structure */
    581         if ((rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL,
    582                                (ipmc_id >> 3), &gentry)) < 0) {
    583             soc_mem_unlock(unit, mem);
    584             return rv;
    585         }
    586     } else
    587 #endif /* BCM_GREYHOUND2_SUPPORT */
    588     {
    589         if ((rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL,
    590                                ipmc_id, &gentry)) < 0) {
    591             soc_mem_unlock(unit, mem);
    592             return rv;
    593         }
    594     }
    595     if (set) {
    596 #if defined(BCM_GREYHOUND2_SUPPORT)
    597         if (SOC_MEM_FIELD_VALID(unit, mem, port_ptrf[0])) {
    598             soc_mem_field32_set(unit, mem, &gentry, port_ptrf[(ipmc_id & 0x7)],
    599                                 *vptr);
    600             if (soc_feature(unit, soc_feature_ipmc_repl_penultimate)) {
    601                 soc_mem_field32_set(unit, mem, &gentry, last_ptr,last ? 1 : 0);
    602             }
    603             if ((rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, (ipmc_id >> 3),
    604                                     &gentry)) < 0) {
    605                 soc_mem_unlock(unit, mem);
    606                 return rv;
    607             }
    608         } else
    609 #endif /* BCM_GREYHOUND2_SUPPORT */
    610         {
    611             soc_mem_field32_set(unit, mem, &gentry, port_ptr, *vptr);
    612             if (soc_feature(unit, soc_feature_ipmc_repl_penultimate)) {
    613                 soc_mem_field32_set(unit, mem, &gentry, last_ptr,last ? 1 : 0);
    614             }
    615             if ((rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, ipmc_id,
    616                                     &gentry)) < 0) {
    617                 soc_mem_unlock(unit, mem);
    618                 return rv;
    619             }
    620         }
    621         LOG_VERBOSE(BSL_LS_SOC_COMMON,
    622                     (BSL_META_U(unit,
    623                                 "set IPMC_GROUPm(port=%d,group=%d,ptr=%d)\n"),
    624                      port, ipmc_id, *vptr));
    625 
    626 
    627     } else {
    628 #if defined(BCM_GREYHOUND2_SUPPORT)
    629         if (SOC_MEM_FIELD_VALID(unit, mem, port_ptrf[0])) {
    630             *vptr = soc_mem_field32_get(unit, mem, &gentry,
    631                                         port_ptrf[(ipmc_id & 0x7)]);
    632         } else
    633 #endif /* BCM_GREYHOUND2_SUPPORT */
    634         {
    635             *vptr = soc_mem_field32_get(unit, mem, &gentry, port_ptr);
    636         }
    637     }
    638     soc_mem_unlock(unit, mem);
    639 
    640     return BCM_E_NONE;
    641 }
    642 
    643 /*
    644  * Function:
    645  *      _bcm_fb_ipmc_repl_freeze
    646  * Purpose:
    647  *      Pause IPMC replication (actually all traffic) before reconfiging
    648  * Parameters:
    649  *      unit     - SOC unit #
    650  * Returns:
    651  *      BCM_E_XXX
    652  */
    653 STATIC int
    654 _bcm_fb_ipmc_repl_freeze(int unit)
    655 {
    656     int                 rv = BCM_E_NONE;
    657     uint32              rval;
    658     uint32              op_verify;
    659     soc_port_t          port;
    660     uint32              emb_set, emb_get, emc_set;
    661 
    662     /* MISCCONFIG.METERING_CLK_EN is set by chip init */
    663 
    664     /* This is a lock, so it must be released! */
    665     SOC_EGRESS_METERING_LOCK(unit);
    666 
    667     emc_set = 0;
    668     soc_reg_field_set(unit, EGRMETERINGCONFIGr, &emc_set, REFRESHf, 0);
    669     soc_reg_field_set(unit, EGRMETERINGCONFIGr, &emc_set, THD_SELf, 1);
    670 
    671     emb_set = 0;
    672     soc_reg_field_set(unit, EGRMETERINGBUCKETr, &emb_set, BUCKETf, 0xffffff);
    673 
    674     PBMP_E_ITER(unit, port) {
    675         if ((rv = READ_EGRMETERINGCONFIGr(unit, port, &rval)) < 0) {
    676             break;
    677         }
    678         IPMC_REPL_PORT_INFO(unit, port)->emc_val = rval;
    679         if ((rv = WRITE_EGRMETERINGCONFIGr(unit, port, emc_set)) < 0) {
    680             break;
    681         }
    682 
    683         /* Write to EGRMETERINGBUCKET register might be stomped by
    684          * traffic.  Verify that the IN_PROFILE_FLAG is successfully set. */
    685         do {
    686             if ((rv = WRITE_EGRMETERINGBUCKETr(unit, port, emb_set)) < 0) {
    687                 break;
    688             }
    689 
    690             if (!SAL_BOOT_SIMULATION) {
    691                 if ((rv = READ_EGRMETERINGBUCKETr(unit, port, &emb_get)) < 0) {
    692                     break;
    693                 }
    694 
    695                 op_verify = soc_reg_field_get(unit, EGRMETERINGBUCKETr,
    696                                               emb_get, IN_PROFILE_FLAGf);
    697             } else {
    698                 op_verify = 1;
    699             }
    700         } while (op_verify != 1);
    701 
    702         if (rv < 0) {
    703             break;
    704         }
    705     }
    706 
    707     if (rv < 0) {
    708         SOC_EGRESS_METERING_UNLOCK(unit);
    709     }
    710 
    711     return rv;
    712 }
    713 
    714 /*
    715  * Function:
    716  *      _bcm_fb_ipmc_repl_thaw
    717  * Purpose:
    718  *      Start IPMC replication (actually all traffic) after reconfiging
    719  * Parameters:
    720  *      unit     - SOC unit #
    721  * Returns:
    722  *      BCM_E_XXX
    723  */
    724 STATIC int
    725 _bcm_fb_ipmc_repl_thaw(int unit)
    726 {
    727     int                 rv = BCM_E_NONE;
    728     uint32              rval;
    729     soc_port_t          port;
    730 
    731     PBMP_E_ITER(unit, port) {
    732         rval = 0;
    733         /*
    734          * all fields in "rval" are already zero
    735          * soc_reg_field_set(unit, EGRMETERINGBUCKETr, &rval,
    736          *                   IN_PROFILE_FLAGf, 0);
    737          * soc_reg_field_set(unit, EGRMETERINGBUCKETr, &rval, BUCKETf, 0);
    738          */
    739         if ((rv = WRITE_EGRMETERINGBUCKETr(unit, port, rval)) < 0) {
    740             break;
    741         }
    742 
    743         rval = IPMC_REPL_PORT_INFO(unit, port)->emc_val;
    744         if ((rv = WRITE_EGRMETERINGCONFIGr(unit, port, rval)) < 0) {
    745             break;
    746         }
    747     }
    748 
    749     /* Must thaw here to release lock from freeze */
    750     SOC_EGRESS_METERING_UNLOCK(unit);
    751     
    752     return rv;
    753 }
    754 
    755 #ifdef BCM_WARM_BOOT_SUPPORT
    756 /*
    757  * Function:
    758  *      _bcm_xgs3_ipmc_repl_reload
    759  * Purpose:
    760  *      Re-Initialize IPMC replication software to state consistent with
    761  *      hardware
    762  * Parameters:
    763  *      unit     - SOC unit #
    764  * Returns:
    765  *      BCM_E_XXX
    766  */
    767 int
    768 _bcm_xgs3_ipmc_repl_reload(int unit)
    769 {
    770     mmu_ipmc_vlan_tbl_entry_t vlan_entry;
    771     uint32 ms_bit, ls_bits[2];
    772     bcm_port_t port;
    773     int ipmc_id, alloc_size, intf_alloc_size;
    774     int vlan_ptr, next_vlan_ptr, first_vlan_ptr;
    775     SHR_BITDCL          *intf_vec = NULL;
    776     SHR_BITDCL          *intf_vec_egr = NULL;
    777     _bcm_repl_list_info_t *rli_start, *rli_current;
    778     uint8 flags;
    779     int rv;
    780     int i;
    781     int egr_id;
    782     bcm_l3_egress_t egr_nh;
    783 
    784     bcm_fb_ipmc_repl_detach(unit);
    785     /* TD3TBD */
    786     if (SOC_IS_TRIDENT3X(unit)) {
    787         return BCM_E_NONE;
    788     }
    789 
    790     /* Allocate struct for IPMC replication booking keeping */
    791     alloc_size = sizeof(_fb_repl_info_t);
    792     _fb_repl_info[unit] = sal_alloc(alloc_size, "IPMC repl info");
    793     if (_fb_repl_info[unit] == NULL) {
    794         return BCM_E_MEMORY;
    795     }
    796     sal_memset(_fb_repl_info[unit], 0, alloc_size);
    797 
    798     IPMC_REPL_GROUP_NUM(unit) = soc_mem_index_count(unit, L3_IPMCm);
    799 
    800 #ifdef BCM_TRIUMPH_SUPPORT
    801     if (SOC_IS_TR_VL(unit) && !SOC_IS_HURRICANEX(unit) && 
    802             !SOC_IS_GREYHOUND(unit) && !SOC_IS_GREYHOUND2(unit)) {
    803         /* For VPLS, can replicate to 16k next-hop entries */
    804         IPMC_REPL_INTF_TOTAL(unit) = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
    805     } else
    806 #endif
    807     {
    808         IPMC_REPL_INTF_TOTAL(unit) = soc_mem_index_count(unit, EGR_L3_INTFm);
    809     }
    810 
    811     /*
    812      * soc_feature_l3mc_use_egress_next_hop use EGR_L3_NEXT_HOP as
    813      * replication interface instead of using EGR_L3_INTF.
    814      */
    815     if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) {
    816         IPMC_REPL_INTF_TOTAL(unit) = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
    817     }
    818 
    819     IPMC_REPL_TOTAL(unit) = soc_mem_index_count(unit, MMU_IPMC_VLAN_TBLm);
    820     alloc_size = SHR_BITALLOCSIZE(IPMC_REPL_TOTAL(unit));
    821     _fb_repl_info[unit]->bitmap_entries_used =
    822         sal_alloc(alloc_size, "IPMC repl entries used");
    823     if (_fb_repl_info[unit]->bitmap_entries_used == NULL) {
    824         bcm_fb_ipmc_repl_detach(unit);
    825         return BCM_E_MEMORY;
    826     }
    827     sal_memset(_fb_repl_info[unit]->bitmap_entries_used, 0, alloc_size);
    828 
    829     if (NULL == _fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc) {
    830         _fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc =
    831             sal_alloc(sizeof(int) * soc_mem_index_count(unit, EGR_L3_INTFm),
    832                       "l3_intf_to_next_hop_ipmc");
    833         if (NULL == _fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc) {
    834             bcm_fb_ipmc_repl_detach(unit);
    835             return BCM_E_MEMORY;
    836         }
    837     }
    838     for (i = 0; i < soc_mem_index_count(unit, EGR_L3_INTFm); i++) {
    839         _fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc[i] =
    840             REPL_NH_INDEX_UNALLOCATED;
    841     }
    842 
    843     /* Always reserve slot 0 (because 0 means NULL pointer) */
    844     IPMC_REPL_VE_USED_SET(unit, 0);
    845 
    846     PBMP_ITER(PBMP_PORT_ALL(unit), port) {
    847         alloc_size = sizeof(_fb_repl_port_info_t);
    848         IPMC_REPL_PORT_INFO(unit, port) =
    849             sal_alloc(alloc_size, "IPMC repl port info");
    850         if (IPMC_REPL_PORT_INFO(unit, port) == NULL) {
    851             bcm_fb_ipmc_repl_detach(unit);
    852             return BCM_E_MEMORY;
    853         }
    854         sal_memset(IPMC_REPL_PORT_INFO(unit, port), 0, alloc_size);
    855 
    856         alloc_size = sizeof(int32) * IPMC_REPL_GROUP_NUM(unit);
    857         IPMC_REPL_PORT_INFO(unit, port)->vlan_count =
    858             sal_alloc(alloc_size, "IPMC repl port vlan count");
    859         if (IPMC_REPL_PORT_INFO(unit, port)->vlan_count == NULL) {
    860             bcm_fb_ipmc_repl_detach(unit);
    861             return BCM_E_MEMORY;
    862         }
    863         sal_memset(IPMC_REPL_PORT_INFO(unit, port)->vlan_count,
    864                    0, alloc_size);
    865     }
    866     /*
    867      * HR3 and GH family use L3_EGR_NH table instead of L3_INTF when indexed by IPMC_VLAN.
    868      * And it uses soc_feature_l3mc_use_egress_next_hop to distinquish this
    869      */
    870     if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) {
    871         alloc_size = SHR_BITALLOCSIZE(soc_mem_index_count(unit,
    872                                                           EGR_L3_NEXT_HOPm));
    873     } else {
    874         alloc_size = SHR_BITALLOCSIZE(IPMC_REPL_INTF_TOTAL(unit));
    875     }
    876     intf_vec = sal_alloc(alloc_size, "IPMC repl interface vector");
    877     if (intf_vec == NULL) {
    878         bcm_fb_ipmc_repl_detach(unit);
    879         return BCM_E_MEMORY;
    880     }
    881     intf_alloc_size = alloc_size;
    882     rli_start = IPMC_REPL_LIST_INFO(unit);
    883 
    884     /*
    885      * Read IPMC group and IPMC VLAN tables to build up software state
    886      */
    887     for (ipmc_id = soc_mem_index_min(unit, L3_IPMCm);
    888          ipmc_id <= soc_mem_index_max(unit, L3_IPMCm); ipmc_id++) {
    889 
    890         PBMP_ITER (PBMP_PORT_ALL(unit), port) {
    891             rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, port, &first_vlan_ptr, 0, 0);
    892             if (BCM_FAILURE(rv)) {
    893                 sal_free(intf_vec);
    894                 bcm_fb_ipmc_repl_detach(unit);
    895                 return rv;
    896             }
    897             if (first_vlan_ptr == 0) {
    898                 continue;
    899             }
    900             if (IPMC_REPL_VE_USED_GET(unit, first_vlan_ptr)) {
    901                 /* We've already traversed this list, just note it */
    902                 for (rli_current = rli_start; rli_current != NULL;
    903                      rli_current = rli_current->next) {
    904                     if (rli_current->index == first_vlan_ptr) {
    905                         (rli_current->refcount)++;
    906                         IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id) = 
    907                             rli_current->list_size;
    908                         break;
    909                     }
    910                 }
    911                 if (rli_current == NULL) {
    912                     /* Table out of sync.  Not good. */
    913                     sal_free(intf_vec);
    914                     bcm_fb_ipmc_repl_detach(unit);
    915                     return BCM_E_INTERNAL;
    916                 } else {
    917                     continue;
    918                 }
    919             }
    920             sal_memset(intf_vec, 0, intf_alloc_size);
    921             next_vlan_ptr = first_vlan_ptr;
    922             vlan_ptr = 0;
    923             while (vlan_ptr != next_vlan_ptr) {
    924                 vlan_ptr = next_vlan_ptr;
    925                 rv = READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL,
    926                                              vlan_ptr, &vlan_entry);
    927                 if (BCM_FAILURE(rv)) {
    928                     sal_free(intf_vec);
    929                     bcm_fb_ipmc_repl_detach(unit);
    930                     return rv;
    931                 }
    932                 soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry,
    933                                                  LSB_VLAN_BMf, ls_bits);
    934                 ms_bit = soc_MMU_IPMC_VLAN_TBLm_field32_get(
    935                     unit, &vlan_entry, MSB_VLANf);
    936                 intf_vec[2 * ms_bit + 0] = ls_bits[0];
    937                 intf_vec[2 * ms_bit + 1] = ls_bits[1];
    938                 IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id) +=
    939                       _shr_popcount(ls_bits[0]) + _shr_popcount(ls_bits[1]);
    940                 IPMC_REPL_VE_USED_SET(unit, vlan_ptr);
    941                 next_vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
    942                                                   &vlan_entry, NEXTPTRf);
    943             }
    944 
    945             /* Create new list element */
    946             alloc_size = sizeof(_bcm_repl_list_info_t);
    947             rli_current = sal_alloc(alloc_size, "IPMC repl list info");
    948             if (rli_current == NULL) {
    949                 sal_free(intf_vec);
    950                 bcm_fb_ipmc_repl_detach(unit);
    951                 return BCM_E_MEMORY;
    952             }
    953             sal_memset(rli_current, 0, alloc_size);
    954             rli_current->index = first_vlan_ptr;
    955             if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) {
    956                 /*
    957                  * Previous intf_vef is derived from egr_l3_next_hop,
    958                  * now need to transfer l3_intf to l3_intf_egr.
    959                  */
    960                 intf_vec_egr  =
    961                     sal_alloc(SHR_BITALLOCSIZE(IPMC_REPL_INTF_TOTAL(unit)),
    962                               "IPMC repl interface vector, l3mc use egr nh");
    963                 if (intf_vec_egr == NULL) {
    964                     sal_free(intf_vec);
    965                     sal_free(rli_current);
    966                     bcm_fb_ipmc_repl_detach(unit);
    967                     return BCM_E_MEMORY;
    968                 }
    969                 sal_memset(intf_vec_egr, 0,
    970                            SHR_BITALLOCSIZE(IPMC_REPL_INTF_TOTAL(unit)));
    971                 SHR_BIT_ITER(intf_vec, soc_mem_index_count(
    972                                          unit, EGR_L3_NEXT_HOPm), egr_id) {
    973                     rv = bcm_xgs3_nh_get(unit, egr_id, &egr_nh);
    974                         /* SW data not recover, will always return BCM_E_NOT_FOUND */
    975                     if (BCM_FAILURE(rv) && rv != BCM_E_NOT_FOUND) {
    976                         sal_free(intf_vec_egr);
    977                         sal_free(intf_vec);
    978                         sal_free(rli_current);
    979                         bcm_fb_ipmc_repl_detach(unit);
    980                         return rv;
    981                     }
    982                     SHR_BITSET(intf_vec_egr, egr_nh.intf);
    983                 }
    984                 rli_current->hash =
    985                     _shr_crc32b(0, (uint8 *)intf_vec_egr,
    986                                 IPMC_REPL_INTF_TOTAL(unit));
    987                 sal_free(intf_vec_egr);
    988                 intf_vec_egr = NULL;
    989             } else {
    990                 rli_current->hash =
    991                     _shr_crc32b(0, (uint8 *)intf_vec,
    992                                 IPMC_REPL_INTF_TOTAL(unit));
    993             }
    994             rli_current->next = rli_start;
    995             rli_current->list_size =
    996             IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id);
    997             IPMC_REPL_LIST_INFO(unit) = rli_current;
    998             rli_start = rli_current;
    999             (rli_current->refcount)++;
   1000         }
   1001     }
   1002 
   1003     /* Recover REPL list mode from HW cache */
   1004     rv = _bcm_esw_ipmc_repl_wb_flags_get(unit,
   1005                                          _BCM_IPMC_WB_REPL_LIST, &flags);
   1006     if (flags) {
   1007         SOC_IPMCREPLSHR_SET(unit, 1);
   1008     }
   1009 
   1010     sal_free(intf_vec);
   1011 
   1012     /* Init the nexthop to l3 intf sw structure */
   1013     if (NULL == _fb_repl_info[unit]->l3_nh_to_l3_intf_ipmc) {
   1014         _fb_repl_info[unit]->l3_nh_to_l3_intf_ipmc =
   1015             sal_alloc(sizeof(int) * soc_mem_index_count(unit, EGR_L3_NEXT_HOPm),
   1016                       "next_hop_to_l3_intf_ipmc");
   1017 
   1018         if (NULL == _fb_repl_info[unit]->l3_nh_to_l3_intf_ipmc) {
   1019             bcm_fb_ipmc_repl_detach(unit);
   1020             return BCM_E_MEMORY;
   1021         }
   1022     }
   1023     for (i = 0; i < soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); i++) {
   1024         _fb_repl_info[unit]->l3_nh_to_l3_intf_ipmc[i] =
   1025             REPL_L3_INTF_UNALLOCATED;
   1026     }
   1027 
   1028     if (NULL == _fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc) {
   1029         _fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc =
   1030             sal_alloc(sizeof(int) * soc_mem_index_count(unit, EGR_L3_INTFm),
   1031                       "l3_intf_to_next_hop_ipmc");
   1032 
   1033         if (NULL == _fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc) {
   1034             bcm_fb_ipmc_repl_detach(unit);
   1035             return BCM_E_MEMORY;
   1036         }
   1037     }
   1038     for (i = 0; i < soc_mem_index_count(unit, EGR_L3_INTFm); i++) {
   1039         _fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc[i] =
   1040             REPL_NH_INDEX_UNALLOCATED;
   1041     }
   1042 
   1043     return BCM_E_NONE;
   1044 }
   1045 #endif /* BCM_WARM_BOOT_SUPPORT */
   1046 #endif /* BCM_FIREBOLT_SUPPORT */
   1047 
   1048 #if defined(BCM_FIREBOLT_SUPPORT)
   1049 /*
   1050  * Function:
   1051  *      _bcm_xgs3_ipmc_l3entry_list_add
   1052  * Purpose:
   1053  *      Add a L3 entry to IPMC group's linked list of L3 entries
   1054  * Parameters:
   1055  *      unit       - (IN) BCM device number.
   1056  *      ipmc_index - (IN) IPMC group ID.
   1057  *      _bcm_l3_cfg_t - (IN) l3 config structure
   1058  * Returns:
   1059  *      BCM_E_XXX
   1060  */
   1061 static int
   1062 _bcm_xgs3_ipmc_l3entry_list_add(int unit, int ipmc_index,
   1063                                 _bcm_l3_cfg_t *l3cfg)
   1064 {
   1065     _bcm_esw_ipmc_l3entry_t *ipmc_l3entry;
   1066    
   1067     ipmc_l3entry = sal_alloc(sizeof(_bcm_esw_ipmc_l3entry_t), "IPMC L3 entry");
   1068     if (ipmc_l3entry == NULL) {
   1069         return BCM_E_MEMORY;
   1070     }
   1071     ipmc_l3entry->ip6 = (l3cfg->l3c_flags & BCM_L3_IP6) ? 1 : 0;
   1072     ipmc_l3entry->l3info.flags = l3cfg->l3c_flags;
   1073     ipmc_l3entry->l3info.vrf = l3cfg->l3c_vrf;
   1074     ipmc_l3entry->l3info.ip_addr = l3cfg->l3c_ipmc_group;
   1075     ipmc_l3entry->l3info.src_ip_addr = l3cfg->l3c_src_ip_addr;
   1076     sal_memcpy(ipmc_l3entry->l3info.ip6, l3cfg->l3c_ip6, BCM_IP6_ADDRLEN);
   1077     sal_memcpy(ipmc_l3entry->l3info.sip6, l3cfg->l3c_sip6, BCM_IP6_ADDRLEN);
   1078     ipmc_l3entry->l3info.vid = l3cfg->l3c_vid;
   1079     ipmc_l3entry->l3info.prio = l3cfg->l3c_prio;
   1080     ipmc_l3entry->l3info.ipmc_ptr = l3cfg->l3c_ipmc_ptr;
   1081     ipmc_l3entry->l3info.lookup_class = l3cfg->l3c_lookup_class;
   1082     ipmc_l3entry->next = IPMC_GROUP_INFO(unit, ipmc_index)->l3entry_list;
   1083     IPMC_GROUP_INFO(unit, ipmc_index)->l3entry_list = ipmc_l3entry;
   1084 
   1085     return BCM_E_NONE;
   1086 }
   1087 
   1088 /*
   1089  * Function:
   1090  *      _bcm_xgs3_ipmc_l3entry_list_del
   1091  * Purpose:
   1092  *      Delete a L3 entry from IPMC group's linked list of L3 entries
   1093  * Parameters:
   1094  *      unit       - (IN) BCM device number.
   1095  *      ipmc_index - (IN) IPMC group ID.
   1096  *      _bcm_l3_cfg_t - (IN) l3 config structure
   1097  * Returns:
   1098  *      BCM_E_XXX
   1099  */
   1100 STATIC int
   1101 _bcm_xgs3_ipmc_l3entry_list_del(int unit, int ipmc_index,
   1102                                 _bcm_l3_cfg_t *l3cfg)
   1103 {
   1104     _bcm_esw_ipmc_l3entry_t *ipmc_l3entry;
   1105     _bcm_esw_ipmc_l3entry_t *prev_ipmc_l3entry = NULL;
   1106    
   1107     ipmc_l3entry = IPMC_GROUP_INFO(unit, ipmc_index)->l3entry_list;
   1108     while (ipmc_l3entry != NULL) {
   1109         if ((ipmc_l3entry->l3info.ip_addr == l3cfg->l3c_ip_addr) &&
   1110             (ipmc_l3entry->l3info.src_ip_addr == l3cfg->l3c_src_ip_addr) && 
   1111             (!sal_memcmp(ipmc_l3entry->l3info.ip6, l3cfg->l3c_ip6, BCM_IP6_ADDRLEN)) &&
   1112             (!sal_memcmp(ipmc_l3entry->l3info.sip6, l3cfg->l3c_sip6, BCM_IP6_ADDRLEN)) &&
   1113             (ipmc_l3entry->l3info.vid == l3cfg->l3c_vid) &&
   1114             (ipmc_l3entry->l3info.vrf == l3cfg->l3c_vrf)) {
   1115            if (ipmc_l3entry == IPMC_GROUP_INFO(unit, ipmc_index)->l3entry_list) {
   1116                IPMC_GROUP_INFO(unit, ipmc_index)->l3entry_list = ipmc_l3entry->next;
   1117            } else {
   1118                /* 
   1119                 * In the following line of code, Coverity thinks the
   1120                 * prev_ipmc_l3entry pointer may still be NULL when 
   1121                 * dereferenced. This situation will never occur because 
   1122                 * if ipmc_l3entry is not pointing to the head of the 
   1123                 * linked list, prev_ipmc_l3entry would not be NULL.
   1124                 */
   1125                /* coverity[var_deref_op : FALSE] */
   1126                prev_ipmc_l3entry->next = ipmc_l3entry->next;
   1127            }
   1128            sal_free(ipmc_l3entry);
   1129            break;
   1130         }
   1131         prev_ipmc_l3entry = ipmc_l3entry;
   1132         ipmc_l3entry = ipmc_l3entry->next;
   1133     }
   1134 
   1135     if (ipmc_l3entry == NULL) {
   1136         return BCM_E_NOT_FOUND;
   1137     }
   1138 
   1139     return BCM_E_NONE;
   1140 }
   1141 
   1142 STATIC int
   1143 _bcm_xgs3_ipmc_l3entry_list_update(int unit, int ipmc_index,
   1144                                    _bcm_l3_cfg_t *l3cfg)
   1145 {
   1146     _bcm_esw_ipmc_l3entry_t *ipmc_l3entry;
   1147    
   1148     ipmc_l3entry = IPMC_GROUP_INFO(unit, ipmc_index)->l3entry_list;
   1149     while (ipmc_l3entry != NULL) {
   1150         if ((ipmc_l3entry->l3info.ip_addr == l3cfg->l3c_ip_addr) &&
   1151             (ipmc_l3entry->l3info.src_ip_addr == l3cfg->l3c_src_ip_addr) && 
   1152             (!sal_memcmp(ipmc_l3entry->l3info.ip6, l3cfg->l3c_ip6, BCM_IP6_ADDRLEN)) &&
   1153             (!sal_memcmp(ipmc_l3entry->l3info.sip6, l3cfg->l3c_sip6, BCM_IP6_ADDRLEN)) &&
   1154             (ipmc_l3entry->l3info.vid == l3cfg->l3c_vid)) {
   1155             ipmc_l3entry->l3info.flags = l3cfg->l3c_flags;
   1156             ipmc_l3entry->l3info.vrf = l3cfg->l3c_vrf;
   1157             ipmc_l3entry->l3info.prio = l3cfg->l3c_prio;
   1158             ipmc_l3entry->l3info.ipmc_ptr = l3cfg->l3c_ipmc_ptr;
   1159             ipmc_l3entry->l3info.lookup_class = l3cfg->l3c_lookup_class;
   1160             break;
   1161         }
   1162         ipmc_l3entry = ipmc_l3entry->next;
   1163     }
   1164 
   1165     if (ipmc_l3entry == NULL) {
   1166         return BCM_E_NOT_FOUND;
   1167     }
   1168 
   1169     return BCM_E_NONE;
   1170 }
   1171 
   1172 /*
   1173  * Function:
   1174  *      _bcm_xgs3_ipmc_l3entry_list_size_get
   1175  * Purpose:
   1176  *      Get the number of L3 entries in IPMC group's linked list.
   1177  * Parameters:
   1178  *      unit       - (IN) BCM device number.
   1179  *      ipmc_index - (IN) IPMC group ID.
   1180  *      size       - (OUT) Number of L3 entries.
   1181  * Returns:
   1182  *      BCM_E_XXX
   1183  */
   1184 STATIC int
   1185 _bcm_xgs3_ipmc_l3entry_list_size_get(int unit, int ipmc_index,
   1186         int *size)
   1187 {
   1188     if (IPMC_USED_ISSET(unit, ipmc_index)) {
   1189         *size = IPMC_GROUP_INFO(unit, ipmc_index)->ref_count - 1;
   1190     } else {
   1191         *size = 0;
   1192     }
   1193 
   1194     return BCM_E_NONE;
   1195 }
   1196 
   1197 #endif /* BCM_FIREBOLT_SUPPORT */
   1198 
   1199 /*
   1200  * Function:
   1201  *      bcm_xgs3_ipmc_create
   1202  * Purpose:
   1203  *      Create an ipmc entry.
   1204  */
   1205 
   1206 int
   1207 bcm_xgs3_ipmc_create(int unit, int *ipmc_id)
   1208 {
   1209     int i;
   1210 
   1211     IPMC_LOCK(unit);
   1212     for (i = 0; i < IPMC_GROUP_NUM(unit); i++) {
   1213         if (!IPMC_USED_ISSET(unit, i)) {
   1214             IPMC_USED_SET(unit, i);
   1215             *ipmc_id = i;
   1216             IPMC_UNLOCK(unit);
   1217             return BCM_E_NONE;
   1218         }
   1219     }
   1220     IPMC_UNLOCK(unit);
   1221 
   1222     return (BCM_E_FULL);
   1223 }
   1224 
   1225 /*
   1226  * Function:
   1227  *      bcm_xgs3_ipmc_id_alloc
   1228  * Purpose:
   1229  *      allocate the given ipmc entry.
   1230  */
   1231 
   1232 int
   1233 bcm_xgs3_ipmc_id_alloc(int unit, int ipmc_id)
   1234 {
   1235     IPMC_LOCK(unit);
   1236     IPMC_USED_SET(unit, ipmc_id);
   1237     IPMC_UNLOCK(unit);
   1238     return BCM_E_NONE;
   1239 }
   1240 
   1241 /*
   1242  * Function:
   1243  *      bcm_xgs3_ipmc_id_free
   1244  * Purpose:
   1245  *      Delete an ipmc entry.
   1246  */
   1247 
   1248 int
   1249 bcm_xgs3_ipmc_id_free(int unit, int ipmc_id)
   1250 {
   1251     IPMC_INIT(unit);
   1252     IPMC_ID(unit, ipmc_id);
   1253 
   1254     IPMC_LOCK(unit);
   1255     if (IPMC_USED_ISSET(unit, ipmc_id)) {
   1256         IPMC_USED_CLR(unit, ipmc_id);
   1257     }
   1258     IPMC_UNLOCK(unit);
   1259 
   1260     return BCM_E_NONE;
   1261 }
   1262 
   1263 /*
   1264  * Function:
   1265  *      bcm_xgs3_ipmc_id_is_set
   1266  * Purpose:
   1267  *      Verify an ipmc entry.
   1268  */
   1269 
   1270 int
   1271 bcm_xgs3_ipmc_id_is_set(int unit, int ipmc_id, int *is_set)
   1272 {
   1273     IPMC_INIT(unit);
   1274     IPMC_ID(unit, ipmc_id);
   1275 
   1276     IPMC_LOCK(unit);
   1277     *is_set = (0 != IPMC_USED_ISSET(unit, ipmc_id));
   1278     IPMC_UNLOCK(unit);
   1279 
   1280     return BCM_E_NONE;
   1281 }
   1282 
   1283 /*
   1284  * Function:
   1285  *      _xgs3_ipmc_info_get
   1286  * Purpose:
   1287  *      Fill information to bcm_ipmc_addr_t struct.
   1288  */
   1289 
   1290 STATIC int
   1291 _xgs3_ipmc_info_get(int unit, int hw_index, int index, int er_index_get,
   1292                     bcm_ipmc_addr_t *ipmc, ipmc_entry_t *entry, 
   1293                     uint8 do_l3_lkup, 
   1294                     _bcm_esw_ipmc_l3entry_t *use_ipmc_l3entry)
   1295 {
   1296     uint32              mod, port_tgid, is_trunk;
   1297     uint32              chk_val;
   1298     int                 no_src_check = FALSE;
   1299 #if defined(BCM_FIREBOLT_SUPPORT)
   1300     _bcm_esw_ipmc_l3entry_t *ipmc_l3entry = NULL;
   1301 #endif
   1302 
   1303     ipmc->v = soc_L3_IPMCm_field32_get(unit, entry, VALIDf);
   1304 
   1305     chk_val = SOC_IS_RAVEN(unit) ? 0x7f : 0x3f;
   1306     if (soc_feature(unit, soc_feature_trunk_group_overlay)) {
   1307         is_trunk = soc_L3_IPMCm_field32_get(unit, entry, Tf);
   1308         mod = soc_L3_IPMCm_field32_get(unit, entry, MODULE_IDf);
   1309         port_tgid = soc_L3_IPMCm_field32_get(unit, entry, PORT_NUMf);
   1310         if (is_trunk) {
   1311             if ((port_tgid == chk_val) && ((int)mod == SOC_MODID_MAX(unit))) {
   1312                 no_src_check = TRUE;
   1313             } else {
   1314                 mod = 0;
   1315                 port_tgid = soc_L3_IPMCm_field32_get(unit, entry, TGIDf);
   1316             }
   1317         }
   1318     } else {
   1319         mod = soc_L3_IPMCm_field32_get(unit, entry, MODULE_IDf);
   1320         port_tgid = soc_L3_IPMCm_field32_get(unit, entry, PORT_TGIDf);
   1321         is_trunk = port_tgid & BCM_TGID_TRUNK_INDICATOR(unit);
   1322         if ((port_tgid == chk_val) && ((int)mod == SOC_MODID_MAX(unit))) {
   1323             no_src_check = TRUE;
   1324         } else if (is_trunk) {
   1325             port_tgid = BCM_MODIDf_TGIDf_TO_TRUNK(unit, mod, port_tgid);
   1326         }
   1327     }
   1328     if (no_src_check) {
   1329         ipmc->ts = 0;
   1330         ipmc->mod_id = -1;
   1331         ipmc->port_tgid = -1;
   1332         ipmc->flags |= BCM_IPMC_SOURCE_PORT_NOCHECK;
   1333     } else if (is_trunk) {
   1334         ipmc->ts = 1;
   1335         ipmc->mod_id = 0;
   1336         ipmc->port_tgid = port_tgid;
   1337     } else {
   1338         bcm_module_t    mod_in, mod_out;
   1339         bcm_port_t      port_in, port_out;
   1340 
   1341         mod_in = mod;
   1342         port_in = port_tgid;
   1343         BCM_IF_ERROR_RETURN
   1344             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_GET,
   1345                                     mod_in, port_in,
   1346                                     &mod_out, &port_out));
   1347         ipmc->ts = 0;
   1348         ipmc->mod_id = mod_out;
   1349         ipmc->port_tgid = port_out;
   1350     }
   1351 
   1352     if (ipmc->v) {
   1353         if (SOC_IS_FBX(unit) && do_l3_lkup) {
   1354 #if defined(BCM_FIREBOLT_SUPPORT)
   1355             if (use_ipmc_l3entry) {
   1356                 /* use the passed in l3 info */
   1357                 ipmc_l3entry = use_ipmc_l3entry;
   1358             } else {
   1359                 /* Note: this simply picks up the first l3 info */
   1360                 ipmc_l3entry = IPMC_GROUP_INFO(unit, index)->l3entry_list;
   1361                 if (NULL == ipmc_l3entry) {
   1362                     /* No entries in Multicast host table */
   1363                     return BCM_E_EMPTY;
   1364                 }
   1365             }
   1366             if (ipmc_l3entry->ip6) {
   1367                 ipmc->flags |= BCM_IPMC_IP6;
   1368             } else {
   1369                 ipmc->flags &= ~BCM_IPMC_IP6;
   1370             }
   1371 #endif /* BCM_FIREBOLT_SUPPORT */
   1372         }
   1373 
   1374         if (SOC_IS_FBX(unit) && do_l3_lkup) {
   1375 #if defined(BCM_FIREBOLT_SUPPORT)
   1376             _bcm_l3_cfg_t l3cfg;
   1377             sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t));
   1378 
   1379             l3cfg.l3c_flags = BCM_L3_IPMC;
   1380             l3cfg.l3c_vrf = ipmc_l3entry->l3info.vrf;
   1381             if (soc_feature(unit, soc_feature_l3_sgv)) {
   1382                 ipmc->vid = ipmc_l3entry->l3info.vid;
   1383                 l3cfg.l3c_vid = ipmc_l3entry->l3info.vid;
   1384             }
   1385 
   1386             if (ipmc->flags & BCM_IPMC_HIT_CLEAR) {
   1387                 l3cfg.l3c_flags |= BCM_L3_HIT_CLEAR;
   1388             }
   1389 
   1390             if (ipmc->flags & BCM_IPMC_IP6) {
   1391                 sal_memcpy(ipmc->s_ip6_addr, &ipmc_l3entry->l3info.sip6, BCM_IP6_ADDRLEN);
   1392                 sal_memcpy(ipmc->mc_ip6_addr, &ipmc_l3entry->l3info.ip6, BCM_IP6_ADDRLEN);
   1393                 sal_memcpy(l3cfg.l3c_sip6, &ipmc_l3entry->l3info.sip6, BCM_IP6_ADDRLEN);
   1394                 sal_memcpy(l3cfg.l3c_ip6, &ipmc_l3entry->l3info.ip6, BCM_IP6_ADDRLEN);
   1395                 l3cfg.l3c_flags |= BCM_L3_IP6;
   1396                 BCM_IF_ERROR_RETURN(mbcm_driver[unit]->mbcm_l3_ip6_get(unit, &l3cfg));
   1397             } else {
   1398                 ipmc->s_ip_addr = ipmc_l3entry->l3info.src_ip_addr;
   1399                 ipmc->mc_ip_addr = ipmc_l3entry->l3info.ipmc_group;
   1400                 l3cfg.l3c_src_ip_addr = ipmc_l3entry->l3info.src_ip_addr;
   1401                 l3cfg.l3c_ipmc_group = ipmc_l3entry->l3info.ipmc_group;
   1402                 BCM_IF_ERROR_RETURN(mbcm_driver[unit]->mbcm_l3_ip4_get(unit, &l3cfg));
   1403             }
   1404             if (l3cfg.l3c_flags & BCM_L3_HIT) {
   1405                 ipmc->flags |= BCM_IPMC_HIT;
   1406             }
   1407 
   1408             if (ipmc_l3entry->l3info.flags & BCM_L3_RPE) {
   1409                 ipmc->cos = ipmc_l3entry->l3info.prio;
   1410                 ipmc->flags |= BCM_IPMC_SETPRI;
   1411             } else {
   1412                 ipmc->cos = -1;
   1413                 ipmc->flags &= ~BCM_IPMC_SETPRI;
   1414             }
   1415             ipmc->group = index;
   1416             ipmc->lookup_class = ipmc_l3entry->l3info.lookup_class;
   1417             ipmc->vrf = ipmc_l3entry->l3info.vrf;
   1418 #endif /* BCM_FIREBOLT_SUPPORT */
   1419         }
   1420     }
   1421 
   1422     return BCM_E_NONE;
   1423 }
   1424 
   1425 /*
   1426  * Function:
   1427  *      _xgs3_ipmc_read
   1428  * Purpose:
   1429  *      Read an ipmc entry.
   1430  */
   1431 
   1432 STATIC INLINE int
   1433 _xgs3_ipmc_read(int unit, int ipmc_id, ipmc_entry_t *ipmc_entry)
   1434 {
   1435     int rv;
   1436 
   1437     rv = soc_mem_read(unit, L3_IPMCm, MEM_BLOCK_ANY, ipmc_id, ipmc_entry);
   1438 
   1439     return (rv);
   1440 }
   1441 
   1442 /*
   1443  * Function:
   1444  *      _xgs3_ipmc_write
   1445  * Purpose:
   1446  *      Write an ipmc entry from bcm_ipmc_addr_t struct.
   1447  */
   1448 
   1449 STATIC int
   1450 _xgs3_ipmc_write(int unit, int ipmc_id, bcm_ipmc_addr_t *ipmc)
   1451 {
   1452     int                 rv;
   1453     ipmc_entry_t        entry;
   1454     int                 mod, port_tgid, is_trunk, no_src_check = FALSE;
   1455 
   1456     BCM_IF_ERROR_RETURN
   1457         (soc_mem_read(unit, L3_IPMCm, MEM_BLOCK_ANY, ipmc_id, &entry));
   1458 
   1459     soc_L3_IPMCm_field32_set(unit, &entry, VALIDf, ipmc->v);
   1460 
   1461     if ((ipmc->flags & BCM_IPMC_SOURCE_PORT_NOCHECK) ||
   1462         (ipmc->port_tgid < 0)) {                        /* no source port */
   1463         no_src_check = TRUE;
   1464         is_trunk = 0;
   1465         mod = SOC_MODID_MAX(unit);
   1466 #ifdef BCM_RAVEN_SUPPORT
   1467         if (SOC_IS_RAVEN(unit)) {
   1468             port_tgid = 0x7f;
   1469         } else
   1470 #endif
   1471         {
   1472             port_tgid = 0x3f;
   1473         }
   1474     } else if (ipmc->ts) {                              /* trunk source port */
   1475         is_trunk = 1;
   1476         mod = 0;
   1477         port_tgid = ipmc->port_tgid;
   1478     } else {                                            /* source port */
   1479         bcm_module_t    mod_in, mod_out;
   1480         bcm_port_t      port_in, port_out;
   1481 
   1482         mod_in = ipmc->mod_id;
   1483         port_in = ipmc->port_tgid;
   1484         BCM_IF_ERROR_RETURN
   1485             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET,
   1486                                     mod_in, port_in,
   1487                                     &mod_out, &port_out));
   1488         /* Check parameters, since above is an application callback */
   1489         if (!SOC_MODID_ADDRESSABLE(unit, mod_out)) {
   1490             return BCM_E_BADID;
   1491         }
   1492         if (!SOC_PORT_ADDRESSABLE(unit, port_out)) {
   1493             return BCM_E_PORT;
   1494         }
   1495         is_trunk = 0;
   1496         mod = mod_out;
   1497         port_tgid = port_out;
   1498     }
   1499 
   1500     if (soc_feature(unit, soc_feature_trunk_group_overlay)) {
   1501         if (is_trunk) {
   1502             soc_L3_IPMCm_field32_set(unit, &entry, Tf, 1);
   1503             soc_L3_IPMCm_field32_set(unit, &entry, TGIDf, port_tgid);
   1504         } else {
   1505             soc_L3_IPMCm_field32_set(unit, &entry, MODULE_IDf, mod);
   1506             soc_L3_IPMCm_field32_set(unit, &entry, PORT_NUMf, port_tgid);
   1507             if (no_src_check) {
   1508                 soc_L3_IPMCm_field32_set(unit, &entry, Tf, 1);
   1509             } else {
   1510                 soc_L3_IPMCm_field32_set(unit, &entry, Tf, 0);
   1511             }
   1512         }
   1513     } else {
   1514         if (is_trunk) {
   1515             mod = BCM_TRUNK_TO_MODIDf(unit, port_tgid);
   1516             port_tgid = BCM_TRUNK_TO_TGIDf(unit, port_tgid);
   1517         }
   1518         soc_L3_IPMCm_field32_set(unit, &entry, MODULE_IDf, mod);
   1519         soc_L3_IPMCm_field32_set(unit, &entry, PORT_TGIDf, port_tgid);
   1520     }
   1521 
   1522     rv = soc_mem_write(unit, L3_IPMCm, MEM_BLOCK_ALL, ipmc_id, &entry);
   1523 
   1524     return (rv);
   1525 }
   1526 
   1527 /*
   1528  * Function:
   1529  *      _xgs3_ipmc_enable
   1530  * Purpose:
   1531  *      Enable/disable IPMC support.
   1532  * Parameters:
   1533  *      unit - StrataSwitch PCI device unit number (driver internal).
   1534  *      enable - TRUE: enable IPMC support.
   1535  *               FALSE: disable IPMC support.
   1536  * Returns:
   1537  *      BCM_E_XXX
   1538  */
   1539 
   1540 STATIC int
   1541 _xgs3_ipmc_enable(int unit, int enable)
   1542 {
   1543     int                 port, do_vlan;
   1544     bcm_pbmp_t          port_pbmp;
   1545 
   1546     enable = enable ? 1 : 0;
   1547     do_vlan = soc_property_get(unit, spn_IPMC_DO_VLAN, 1);
   1548 
   1549     BCM_PBMP_CLEAR(port_pbmp);
   1550     BCM_PBMP_ASSIGN(port_pbmp, PBMP_PORT_ALL(unit));
   1551     BCM_PBMP_OR(port_pbmp, PBMP_CMIC(unit));
   1552 
   1553     PBMP_ITER(port_pbmp, port) {
   1554         BCM_IF_ERROR_RETURN
   1555             (_bcm_esw_port_config_set(unit, port,
   1556                                       _bcmPortIpmcV4Enable, enable));
   1557         BCM_IF_ERROR_RETURN
   1558             (_bcm_esw_port_config_set(unit, port,
   1559                                       _bcmPortIpmcV6Enable, enable));
   1560         BCM_IF_ERROR_RETURN
   1561             (_bcm_esw_port_config_set(unit, port,
   1562                                       _bcmPortIpmcVlanKey,
   1563                                       (enable && do_vlan) ? 1 : 0));
   1564     }
   1565 
   1566     return BCM_E_NONE;
   1567 }
   1568 
   1569 /*
   1570  * Function:
   1571  *      bcm_fb_er_ipmc_init
   1572  * Purpose:
   1573  *      Initialize the IPMC module and enable IPMC support.
   1574  * Parameters:
   1575  *      unit - StrataSwitch PCI device unit number (driver internal).
   1576  * Returns:
   1577  *      BCM_E_XXX
   1578  * Notes:
   1579  *      This function has to be called before any other IPMC functions.
   1580  */
   1581 
   1582 int
   1583 bcm_fb_er_ipmc_init(int unit)
   1584 {
   1585     _bcm_esw_ipmc_t  *info = IPMC_INFO(unit);
   1586 
   1587     BCM_IF_ERROR_RETURN(bcm_fb_er_ipmc_detach(unit));
   1588     BCM_IF_ERROR_RETURN(_xgs3_ipmc_enable(unit, TRUE));
   1589 
   1590     IPMC_GROUP_NUM(unit) = soc_mem_index_count(unit, L3_IPMCm);
   1591 
   1592 #ifdef BCM_BRADLEY_SUPPORT
   1593     if (SOC_IS_HBX(unit)) {
   1594         int ipmc_base, ipmc_size;
   1595         
   1596         SOC_IF_ERROR_RETURN
   1597             (soc_hbx_ipmc_size_get(unit, &ipmc_base, &ipmc_size));
   1598 
   1599         if (IPMC_GROUP_NUM(unit) > ipmc_size) {
   1600             /* Reduce to fix allocated table space */
   1601             IPMC_GROUP_NUM(unit) = ipmc_size;
   1602         }
   1603     }
   1604 #endif
   1605 
   1606     info->ipmc_count = 0;
   1607 
   1608     info->ipmc_group_info =
   1609         sal_alloc(IPMC_GROUP_NUM(unit) * sizeof(_bcm_esw_ipmc_group_info_t),
   1610                   "IPMC group info");
   1611     if (info->ipmc_group_info == NULL) {
   1612         return (BCM_E_MEMORY);
   1613     }
   1614     sal_memset(info->ipmc_group_info, 0, 
   1615                IPMC_GROUP_NUM(unit) * sizeof(_bcm_esw_ipmc_group_info_t));
   1616 
   1617     info->ipmc_initialized = TRUE;
   1618 
   1619     return BCM_E_NONE;
   1620 }
   1621 
   1622 /*
   1623  * Function:
   1624  *      bcm_fb_er_ipmc_detach
   1625  * Purpose:
   1626  *      Detach the IPMC module.
   1627  * Parameters:
   1628  *      unit - StrataSwitch PCI device unit number (driver internal).
   1629  * Returns:
   1630  *      BCM_E_XXX
   1631  */
   1632 
   1633 int
   1634 bcm_fb_er_ipmc_detach(int unit)
   1635 {
   1636     _bcm_esw_ipmc_t *info = IPMC_INFO(unit);
   1637     _bcm_esw_ipmc_l3entry_t *ipmc_l3entry; 
   1638     int i, rv;
   1639 
   1640     if (info->ipmc_initialized) {
   1641         /* Delete all IPMC entries. BCM_E_NOT_FOUND or BCM_E_FAIL may be
   1642          * returned by bcm_fb_er_ipmc_delete_all since L3 module
   1643          * clears L3 tables during initialization.
   1644          */
   1645         rv = bcm_fb_er_ipmc_delete_all(unit);
   1646         if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND) && (rv != BCM_E_FAIL)) {
   1647             return rv;
   1648         }
   1649 
   1650         BCM_IF_ERROR_RETURN(_xgs3_ipmc_enable(unit, FALSE));
   1651 
   1652         if (info->ipmc_group_info != NULL) {
   1653             for (i = 0; i < IPMC_GROUP_NUM(unit); i++) {
   1654                 ipmc_l3entry = IPMC_GROUP_INFO(unit, i)->l3entry_list;
   1655                 while (ipmc_l3entry != NULL) {
   1656                     IPMC_GROUP_INFO(unit, i)->l3entry_list = ipmc_l3entry->next;
   1657                     sal_free(ipmc_l3entry);
   1658                     ipmc_l3entry = IPMC_GROUP_INFO(unit, i)->l3entry_list;
   1659                 }
   1660             }
   1661             sal_free(info->ipmc_group_info);
   1662             info->ipmc_group_info = NULL;
   1663         }
   1664 
   1665         info->ipmc_initialized = FALSE;
   1666     }
   1667 
   1668     return BCM_E_NONE;
   1669 }
   1670 
   1671 /*
   1672  * Function:
   1673  *      bcm_fb_er_ipmc_get
   1674  * Purpose:
   1675  *      Get an IPMC entry by index.
   1676  * Parameters:
   1677  *      unit - StrataSwitch PCI device unit number (driver internal).
   1678  *      index - The index number.
   1679  *      ipmc - (OUT) IPMC entry information.
   1680  * Returns:
   1681  *      BCM_E_XXX
   1682  */
   1683 
   1684 int
   1685 bcm_fb_er_ipmc_get(int unit, int index, bcm_ipmc_addr_t *ipmc)
   1686 {
   1687     ipmc_entry_t        ipmc_entry;
   1688     int                 rv;
   1689     int                 l3index = 0;
   1690 
   1691     IPMC_INIT(unit);
   1692     IPMC_ID(unit, index);
   1693 
   1694     if (IPMC_USED_ISSET(unit, index)) {
   1695         SOC_IF_ERROR_RETURN
   1696             (soc_mem_read(unit, L3_IPMCm, MEM_BLOCK_ANY, index, &ipmc_entry));
   1697 
   1698         rv = _xgs3_ipmc_info_get(unit, l3index, index, TRUE, ipmc, &ipmc_entry, 
   1699                                  1, NULL);
   1700         ipmc->group = index;
   1701 
   1702         return rv;
   1703     } 
   1704 
   1705     return BCM_E_NOT_FOUND;
   1706 }
   1707 
   1708 /*
   1709  * Function:
   1710  *      _bcm_fb_er_ipmc_find
   1711  * Purpose:
   1712  *      Look up an IPMC entry by sip, mcip and vid
   1713  * Parameters:
   1714  *      unit - StrataSwitch PCI device unit number (driver internal).
   1715  *      ipmc - (IN) IPMC entry information.
   1716  *      l3cfg - (OUT) The index number.
   1717  * Returns:
   1718  *      BCM_E_XXX
   1719  */
   1720 
   1721 STATIC int
   1722 _bcm_fb_er_ipmc_find(int unit, bcm_ipmc_addr_t *ipmc, _bcm_l3_cfg_t *l3cfg)
   1723 {
   1724     if (SOC_IS_FBX(unit)) {
   1725         sal_memset(l3cfg, 0, sizeof(_bcm_l3_cfg_t));
   1726         l3cfg->l3c_vid = ipmc->vid;
   1727         l3cfg->l3c_flags = BCM_L3_IPMC;
   1728         l3cfg->l3c_vrf = ipmc->vrf;
   1729         
   1730         if (ipmc->flags & BCM_IPMC_HIT_CLEAR) {
   1731             l3cfg->l3c_flags |= BCM_L3_HIT_CLEAR;
   1732         }
   1733 
   1734         if (ipmc->flags & BCM_IPMC_IP6) {
   1735             sal_memcpy(l3cfg->l3c_sip6, ipmc->s_ip6_addr, BCM_IP6_ADDRLEN);
   1736             sal_memcpy(l3cfg->l3c_ip6, ipmc->mc_ip6_addr, BCM_IP6_ADDRLEN);
   1737             l3cfg->l3c_flags |= BCM_L3_IP6;
   1738             BCM_IF_ERROR_RETURN(mbcm_driver[unit]->mbcm_l3_ip6_get(unit, l3cfg));
   1739         } else {
   1740             l3cfg->l3c_src_ip_addr = ipmc->s_ip_addr;
   1741             l3cfg->l3c_ipmc_group = ipmc->mc_ip_addr;
   1742             BCM_IF_ERROR_RETURN(mbcm_driver[unit]->mbcm_l3_ip4_get(unit, l3cfg));
   1743         }
   1744     }
   1745 
   1746     return BCM_E_NONE;
   1747 }
   1748 
   1749 /*
   1750  * Function:
   1751  *      bcm_fb_er_ipmc_lookup
   1752  * Purpose:
   1753  *      Look up an IPMC entry by sip, mcip and vid
   1754  * Parameters:
   1755  *      unit - StrataSwitch PCI device unit number (driver internal).
   1756  *      index - (OUT) The index number.
   1757  *      ipmc - (IN, OUT) IPMC entry information.
   1758  * Returns:
   1759  *      BCM_E_XXX
   1760  */
   1761 
   1762 int
   1763 bcm_fb_er_ipmc_lookup(int unit, int *index, bcm_ipmc_addr_t *ipmc)
   1764 {
   1765     ipmc_entry_t  ipmc_entry;
   1766     _bcm_l3_cfg_t l3cfg;
   1767     int           l3_id, ipmc_id;
   1768 
   1769     IPMC_INIT(unit);
   1770 
   1771     BCM_IF_ERROR_RETURN(
   1772         _bcm_fb_er_ipmc_find(unit, ipmc, &l3cfg));
   1773 
   1774     ipmc_id = SOC_IS_FBX(unit) ? l3cfg.l3c_ipmc_ptr : ipmc->group;
   1775     BCM_IF_ERROR_RETURN
   1776         (_xgs3_ipmc_read(unit, ipmc_id, &ipmc_entry));
   1777 
   1778     l3_id = SOC_IS_FBX(unit) ? l3cfg.l3c_hw_index : ipmc->group;
   1779     BCM_IF_ERROR_RETURN
   1780         (_xgs3_ipmc_info_get(unit, l3_id, ipmc_id, FALSE, ipmc, &ipmc_entry,
   1781                              0, NULL));
   1782     if (SOC_IS_FBX(unit) && ipmc->v) {
   1783         ipmc->group = l3cfg.l3c_ipmc_ptr;
   1784         ipmc->lookup_class = l3cfg.l3c_lookup_class;
   1785         if (l3cfg.l3c_flags & BCM_L3_HIT) {
   1786             ipmc->flags |= BCM_IPMC_HIT;
   1787         }
   1788         if (l3cfg.l3c_flags & BCM_L3_RPE) {
   1789             ipmc->cos =  l3cfg.l3c_prio;
   1790             ipmc->flags |= BCM_IPMC_SETPRI;
   1791         } else {
   1792             ipmc->cos = -1;
   1793             ipmc->flags &= ~BCM_IPMC_SETPRI;
   1794         }
   1795     }
   1796     if (index != NULL) {
   1797         *index = SOC_IS_FBX(unit) ? l3cfg.l3c_ipmc_ptr : ipmc->group;
   1798     }
   1799 
   1800     return BCM_E_NONE;
   1801 }
   1802 
   1803 #if defined(BCM_FIREBOLT_SUPPORT)
   1804 
   1805 /*
   1806  * Function:
   1807  *      _bcm_fb_ipmc_add
   1808  * Purpose:
   1809  *      Add a new entry to the L3 table.
   1810  * Parameters:
   1811  *      unit - (IN) BCM device number.
   1812  *      ipmc - (IN)IPMC entry information.
   1813  * Returns:
   1814  *      BCM_E_XXX
   1815  */
   1816 
   1817 int
   1818 _bcm_fb_ipmc_add(int unit, bcm_ipmc_addr_t *ipmc)
   1819 {
   1820     _bcm_l3_cfg_t       l3cfg; /* L3 ipmc entry.           */
   1821     int                 rv;    /* Operation return status. */
   1822 
   1823     sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t));
   1824 
   1825     l3cfg.l3c_vid = ipmc->vid;
   1826     l3cfg.l3c_flags = BCM_L3_IPMC;
   1827     l3cfg.l3c_vrf = ipmc->vrf;
   1828     l3cfg.l3c_lookup_class = ipmc->lookup_class;
   1829     if (ipmc->flags & BCM_IPMC_SETPRI) {
   1830         l3cfg.l3c_flags |= BCM_L3_RPE;
   1831         l3cfg.l3c_prio = ipmc->cos;
   1832     }
   1833     if (ipmc->flags & BCM_IPMC_IP6) {
   1834         if (!BCM_IP6_MULTICAST(ipmc->mc_ip6_addr)) {
   1835             return BCM_E_PARAM;
   1836         }
   1837         sal_memcpy(l3cfg.l3c_sip6, ipmc->s_ip6_addr, BCM_IP6_ADDRLEN);
   1838         sal_memcpy(l3cfg.l3c_ip6, ipmc->mc_ip6_addr, BCM_IP6_ADDRLEN);
   1839         l3cfg.l3c_flags |= BCM_L3_IP6;
   1840     } else {
   1841         if (!BCM_IP4_MULTICAST(ipmc->mc_ip_addr)) {
   1842             return BCM_E_PARAM;
   1843         }
   1844         l3cfg.l3c_src_ip_addr = ipmc->s_ip_addr;
   1845         l3cfg.l3c_ipmc_group = ipmc->mc_ip_addr;
   1846     }
   1847 
   1848     l3cfg.l3c_ipmc_ptr = ipmc->group;
   1849     l3cfg.l3c_flags |=  BCM_L3_HIT;
   1850 
   1851     if (soc_feature(unit, soc_feature_l3_sgv)) {
   1852         l3cfg.l3c_vid = ipmc->vid;
   1853     }
   1854 
   1855     if (ipmc->flags & BCM_IPMC_REPLACE) {
   1856         l3cfg.l3c_flags |= BCM_L3_REPLACE;
   1857     }
   1858 
   1859     /* Write mcast entry to hw. */
   1860     l3cfg.l3c_hw_index = BCM_XGS3_L3_INVALID_INDEX;/* Add /No overrite. */
   1861 
   1862     if (ipmc->flags & BCM_IPMC_IP6) {
   1863         rv = mbcm_driver[unit]->mbcm_l3_ip6_add(unit, &l3cfg);
   1864     } else {
   1865         rv = mbcm_driver[unit]->mbcm_l3_ip4_add(unit, &l3cfg);
   1866     }
   1867 
   1868     if (BCM_SUCCESS(rv)) {
   1869         rv = _bcm_xgs3_ipmc_l3entry_list_add(unit, ipmc->group, 
   1870                                              &l3cfg); 
   1871     }
   1872     
   1873     return (rv);
   1874 }
   1875 
   1876 /*
   1877  * Function:
   1878  *      _bcm_fb_ipmc_del
   1879  * Purpose:
   1880  *      Remove an  entry from the L3 table.
   1881  * Parameters:
   1882  *      unit - (IN) BCM device number.
   1883  *      ipmc - (IN)IPMC entry information.
   1884  *      modify_l3entry_list - (IN) Controls whether to modify IPMC group's
   1885  *                                 L3 entry list.
   1886  * Returns:
   1887  *      BCM_E_XXX
   1888  */
   1889 
   1890 int
   1891 _bcm_fb_ipmc_del(int unit, bcm_ipmc_addr_t *ipmc, int modify_l3entry_list)
   1892 {
   1893     _bcm_l3_cfg_t       l3cfg; /* L3 ipmc entry.           */
   1894     int                 rv;    /* Operation return status. */
   1895     int                 ipmc_index = 0;
   1896 
   1897     sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t));
   1898 
   1899     l3cfg.l3c_vid = ipmc->vid;
   1900     l3cfg.l3c_flags = BCM_L3_IPMC;
   1901     l3cfg.l3c_vrf = ipmc->vrf;
   1902 
   1903     if (ipmc->flags & BCM_IPMC_IP6) {
   1904         if (!BCM_IP6_MULTICAST(ipmc->mc_ip6_addr)) {
   1905             return BCM_E_PARAM;
   1906         }
   1907         sal_memcpy(l3cfg.l3c_sip6, ipmc->s_ip6_addr, BCM_IP6_ADDRLEN);
   1908         sal_memcpy(l3cfg.l3c_ip6, ipmc->mc_ip6_addr, BCM_IP6_ADDRLEN);
   1909         l3cfg.l3c_flags |= BCM_L3_IP6;
   1910     } else {
   1911         if (!BCM_IP4_MULTICAST(ipmc->mc_ip_addr)) {
   1912             return BCM_E_PARAM;
   1913         }
   1914         l3cfg.l3c_src_ip_addr = ipmc->s_ip_addr;
   1915         l3cfg.l3c_ipmc_group = ipmc->mc_ip_addr;
   1916     }
   1917 
   1918     if (soc_feature(unit, soc_feature_l3_sgv)) {
   1919         l3cfg.l3c_vid = ipmc->vid;
   1920     }
   1921 
   1922     if (ipmc->flags & BCM_IPMC_IP6) {
   1923         rv = mbcm_driver[unit]->mbcm_l3_ip6_get(unit, &l3cfg);
   1924         if (BCM_SUCCESS(rv)) {
   1925             ipmc_index = l3cfg.l3c_ipmc_ptr;
   1926             rv = mbcm_driver[unit]->mbcm_l3_ip6_delete(unit, &l3cfg);
   1927         }
   1928     } else {
   1929         rv = mbcm_driver[unit]->mbcm_l3_ip4_get(unit, &l3cfg);
   1930         if (BCM_SUCCESS(rv)) {
   1931             ipmc_index = l3cfg.l3c_ipmc_ptr;
   1932             rv = mbcm_driver[unit]->mbcm_l3_ip4_delete(unit, &l3cfg);
   1933         }
   1934     }
   1935 
   1936     if (BCM_SUCCESS(rv) && modify_l3entry_list) {
   1937         rv = _bcm_xgs3_ipmc_l3entry_list_del(unit, ipmc_index, 
   1938                                              &l3cfg); 
   1939     }
   1940 
   1941     return (rv);
   1942 }
   1943 /*
   1944  * Function:
   1945  *      _bcm_fb_ipmc_replace
   1946  * Purpose:
   1947  *      Overwrite an entry in the IPMC table.
   1948  * Parameters:
   1949  *      unit - StrataSwitch PCI device unit number (driver internal).
   1950  *      ipmc - New IPMC entry information.
   1951  *      old_l3cfg - Old IPMC configuration information.
   1952  * Returns:
   1953  *      BCM_E_XXX
   1954  */
   1955 STATIC int
   1956 _bcm_fb_ipmc_replace(int unit, bcm_ipmc_addr_t *ipmc, _bcm_l3_cfg_t *old_l3cfg)
   1957 {
   1958     _bcm_l3_cfg_t l3cfg;
   1959     int old_ipmc_index;
   1960 
   1961     l3cfg = *old_l3cfg;
   1962     old_ipmc_index = l3cfg.l3c_ipmc_ptr;
   1963     
   1964     if (!(ipmc->flags & BCM_IPMC_SETPRI)) {
   1965         l3cfg.l3c_flags &= ~BCM_L3_RPE;
   1966         l3cfg.l3c_prio = 0;
   1967     } else {
   1968         l3cfg.l3c_flags |= BCM_L3_RPE;
   1969         l3cfg.l3c_prio = ipmc->cos;
   1970     }
   1971     l3cfg.l3c_ipmc_ptr = ipmc->group;
   1972 
   1973     BCM_IF_ERROR_RETURN
   1974         (bcm_xgs3_l3_replace(unit, &l3cfg));
   1975     
   1976     if (old_ipmc_index != ipmc->group) {
   1977         BCM_IF_ERROR_RETURN
   1978             (_bcm_xgs3_ipmc_l3entry_list_del(unit, old_ipmc_index,
   1979                                              &l3cfg)); 
   1980         BCM_IF_ERROR_RETURN
   1981             (_bcm_xgs3_ipmc_l3entry_list_add(unit, ipmc->group,
   1982                                              &l3cfg)); 
   1983     } else {
   1984         BCM_IF_ERROR_RETURN
   1985             (_bcm_xgs3_ipmc_l3entry_list_update(unit, old_ipmc_index,
   1986                                              &l3cfg));
   1987     }
   1988 
   1989     return BCM_E_NONE;
   1990 }
   1991 #endif /* BCM_FIREBOLT_SUPPORT */
   1992 
   1993 /*
   1994  * Function:
   1995  *      _bcm_xgs3_ipmc_src_port_compare
   1996  * Purpose:
   1997  *      Compare the IPMC source port parameters.
   1998  * Parameters:
   1999  *      unit - StrataSwitch PCI device unit number (driver internal).
   2000  *      ipmc_index - IPMC index to be shared.
   2001  *      ipmc - IPMC address entry info.
   2002  *      match - (OUT) Match indication.
   2003  * Returns:
   2004  *      BCM_E_XXX
   2005  */
   2006 STATIC int
   2007 _bcm_xgs3_ipmc_src_port_compare(int unit, int ipmc_index,
   2008         bcm_ipmc_addr_t *ipmc, int *match)
   2009 {
   2010     ipmc_entry_t entry;
   2011     int t_f, tgid_f, mod_f, port_f, port_tgid_f;
   2012     int no_src_check, is_trunk, tgid, mod, port;
   2013 
   2014     BCM_IF_ERROR_RETURN
   2015         (soc_mem_read(unit, L3_IPMCm, MEM_BLOCK_ANY, ipmc_index, &entry));
   2016 
   2017     no_src_check = FALSE;
   2018     is_trunk = 0;
   2019     tgid = -1;
   2020     mod = -1;
   2021     port = -1;
   2022     if (soc_feature(unit, soc_feature_trunk_group_overlay)) {
   2023         t_f = soc_L3_IPMCm_field32_get(unit, &entry, Tf);
   2024         tgid_f = soc_L3_IPMCm_field32_get(unit, &entry, TGIDf);
   2025         mod_f = soc_L3_IPMCm_field32_get(unit, &entry, MODULE_IDf);
   2026         port_f = soc_L3_IPMCm_field32_get(unit, &entry, PORT_NUMf);
   2027 
   2028         if ((t_f == 1) && (mod_f == SOC_MODID_MAX(unit)) &&
   2029                 (port_f == (SOC_IS_RAVEN(unit) ? 0x7f : 0x3f))) {
   2030             no_src_check = TRUE;
   2031         } else if (t_f == 1) {
   2032             is_trunk = 1;
   2033             tgid = tgid_f;
   2034         } else {
   2035             mod = mod_f;
   2036             port = port_f;
   2037         }
   2038     } else {
   2039         mod_f = soc_L3_IPMCm_field32_get(unit, &entry, MODULE_IDf);
   2040         port_tgid_f = soc_L3_IPMCm_field32_get(unit, &entry, PORT_TGIDf);
   2041 
   2042         if ((mod_f == SOC_MODID_MAX(unit)) &&
   2043                 (port_tgid_f == (SOC_IS_RAVEN(unit) ? 0x7f : 0x3f))) {
   2044             no_src_check = TRUE;
   2045         } else if (BCM_TGID_TRUNK_INDICATOR(unit) & port_tgid_f) {
   2046             is_trunk = 1;
   2047             tgid = BCM_MODIDf_TGIDf_TO_TRUNK(unit, mod_f, port_tgid_f);
   2048         } else {
   2049             mod = mod_f;
   2050             port = port_tgid_f;
   2051         }
   2052     }
   2053 
   2054     *match = FALSE;
   2055     if ((ipmc->flags & BCM_IPMC_SOURCE_PORT_NOCHECK) ||
   2056         (ipmc->port_tgid < 0)) {                        /* no source port */
   2057         if (no_src_check) {
   2058             *match = TRUE;
   2059         }
   2060     } else if (ipmc->ts) {                              /* trunk source port */
   2061         if (is_trunk && (tgid == ipmc->port_tgid)) {
   2062             *match = TRUE;
   2063         }
   2064     } else {                                            /* source port */
   2065         bcm_module_t    mod_in, mod_out;
   2066         bcm_port_t      port_in, port_out;
   2067 
   2068         mod_in = ipmc->mod_id;
   2069         port_in = ipmc->port_tgid;
   2070         BCM_IF_ERROR_RETURN
   2071             (_bcm_esw_stk_modmap_map(unit, BCM_STK_MODMAP_SET,
   2072                                     mod_in, port_in,
   2073                                     &mod_out, &port_out));
   2074         /* Check parameters, since above is an application callback */
   2075         if (!SOC_MODID_ADDRESSABLE(unit, mod_out)) {
   2076             return BCM_E_BADID;
   2077         }
   2078         if (!SOC_PORT_ADDRESSABLE(unit, port_out)) {
   2079             return BCM_E_PORT;
   2080         }
   2081 
   2082         if ((mod == mod_out) && (port == port_out)) {
   2083             *match = TRUE;
   2084         }
   2085     }
   2086 
   2087     return BCM_E_NONE;
   2088 }
   2089 
   2090 /*
   2091  * Function:
   2092  *      _bcm_xgs3_ipmc_src_port_consistency_check
   2093  * Purpose:
   2094  *      When multiple IPMC address entries share the same IPMC
   2095  *      index, they must also have the same port parameter
   2096  *      for the purpose of IPMC source port checking. This
   2097  *      procedure makes sure this is the case.
   2098  * Parameters:
   2099  *      unit - StrataSwitch PCI device unit number (driver internal).
   2100  *      ipmc_index - IPMC index to be shared.
   2101  *      ipmc - IPMC address entry info.
   2102  *      already_used - Indicates if the given IPMC address entry is
   2103  *                     already using the ipmc index to be shared.
   2104  * Returns:
   2105  *      BCM_E_XXX
   2106  */
   2107 STATIC int
   2108 _bcm_xgs3_ipmc_src_port_consistency_check(int unit, int ipmc_index,
   2109         bcm_ipmc_addr_t *ipmc, int already_used, int *need_write)
   2110 {
   2111     int l3entry_list_size = 0;
   2112     int match;
   2113 
   2114     *need_write = TRUE;
   2115 
   2116     if (SOC_IS_FBX(unit)) {
   2117 #if defined(BCM_FIREBOLT_SUPPORT)
   2118         BCM_IF_ERROR_RETURN(_bcm_xgs3_ipmc_l3entry_list_size_get(unit,
   2119                     ipmc_index, &l3entry_list_size));
   2120 #endif /* BCM_FIREBOLT_SUPPORT */
   2121     } 
   2122         
   2123     if ((already_used && (l3entry_list_size > 1)) ||
   2124             (!already_used && (l3entry_list_size > 0))) {
   2125         /* If there are IPMC address entries other than the given IPMC address
   2126          * entry that are pointing the given ipmc index, verify that the IPMC
   2127          * source port check parameters are the same. If not, the ipmc index
   2128          * cannot be shared.
   2129          */ 
   2130         BCM_IF_ERROR_RETURN(_bcm_xgs3_ipmc_src_port_compare(unit,
   2131                     ipmc_index, ipmc, &match));
   2132         if (!match) {
   2133             return BCM_E_PARAM;
   2134         } 
   2135 
   2136         *need_write = FALSE;
   2137     }
   2138 
   2139     return BCM_E_NONE;
   2140 }
   2141 
   2142 /*
   2143  * Function:
   2144  *      bcm_fb_er_ipmc_add
   2145  * Purpose:
   2146  *      Add a new entry to the IPMC table.
   2147  * Parameters:
   2148  *      unit - StrataSwitch PCI device unit number (driver internal).
   2149  *      ipmc - IPMC entry information.
   2150  * Returns:
   2151  *      BCM_E_XXX
   2152  */
   2153 
   2154 int
   2155 bcm_fb_er_ipmc_add(int unit, bcm_ipmc_addr_t *ipmc)
   2156 {
   2157     _bcm_l3_cfg_t   l3cfg;
   2158     int             old_ipmc_index;
   2159     int new_entry, rv, need_write;
   2160 
   2161     IPMC_INIT(unit);
   2162     IPMC_ID(unit, ipmc->group);
   2163 
   2164     if (!IPMC_USED_ISSET(unit, ipmc->group)) {
   2165         return BCM_E_PARAM;
   2166     }
   2167 
   2168     /* Check if IPMC entry already exists.
   2169      * In case of BCM_IPMC_REPLACE flag being set,
   2170      * if entry is already present, the entry will be replaced,
   2171      * else new entry will be created. This is the expected behaviour
   2172      */
   2173     rv = _bcm_fb_er_ipmc_find(unit, ipmc, &l3cfg);
   2174     old_ipmc_index = SOC_IS_FBX(unit) ? l3cfg.l3c_ipmc_ptr : ipmc->group;
   2175     if (BCM_SUCCESS(rv)) { 
   2176         if (!(ipmc->flags & BCM_IPMC_REPLACE)) {
   2177            return (BCM_E_EXISTS);
   2178         } else {
   2179             new_entry = FALSE;
   2180         }
   2181     } else {
   2182         /* Return if error occured. */
   2183         if (rv != BCM_E_NOT_FOUND) {
   2184             return (rv);
   2185         }
   2186         new_entry = TRUE;
   2187     }
   2188 
   2189     if (new_entry) { 
   2190         BCM_IF_ERROR_RETURN(_bcm_xgs3_ipmc_src_port_consistency_check(unit,
   2191                     ipmc->group, ipmc, 0, &need_write));
   2192 
   2193         /* Increment the reference count of the given ipmc_index. */
   2194         BCM_IF_ERROR_RETURN(bcm_xgs3_ipmc_id_alloc(unit, ipmc->group));
   2195     } else {
   2196         if (ipmc->group != old_ipmc_index) {
   2197             BCM_IF_ERROR_RETURN
   2198                 (_bcm_xgs3_ipmc_src_port_consistency_check(unit,
   2199                                                            ipmc->group,
   2200                                                            ipmc, 0, &need_write));
   2201             /* Increment the reference count of the given ipmc_index. */
   2202             BCM_IF_ERROR_RETURN(bcm_xgs3_ipmc_id_alloc(unit, ipmc->group));
   2203 
   2204             /* Decrement the reference count of the old ipmc_index. */
   2205             BCM_IF_ERROR_RETURN(bcm_xgs3_ipmc_id_free(unit, old_ipmc_index));
   2206             if (!IPMC_USED_ISSET(unit, old_ipmc_index)) {
   2207                 /* Reference count should not be zero yet. */
   2208                 return BCM_E_INTERNAL;
   2209             }
   2210         } else {
   2211             BCM_IF_ERROR_RETURN
   2212                 (_bcm_xgs3_ipmc_src_port_consistency_check(unit,
   2213                                                            ipmc->group,
   2214                                                            ipmc, 1, &need_write));
   2215         }
   2216     } 
   2217 
   2218     ipmc->v = (ipmc->flags & BCM_IPMC_ADD_DISABLED) ? 0 : 1;
   2219 
   2220     if (new_entry) {
   2221         if (need_write) {
   2222             /* Write L3_IPMC table entry. */
   2223             rv = _xgs3_ipmc_write(unit, ipmc->group, ipmc);
   2224             if (BCM_FAILURE(rv)) {
   2225                 bcm_xgs3_ipmc_id_free(unit, ipmc->group);
   2226                 return (rv);
   2227             }
   2228         }
   2229 
   2230         /* Add new L3 table entry */
   2231         if (SOC_IS_FBX(unit)) {
   2232 #if defined(BCM_FIREBOLT_SUPPORT)
   2233             rv = _bcm_fb_ipmc_add(unit, ipmc);
   2234 #endif /* BCM_FIREBOLT_SUPPORT */
   2235         }
   2236         if (BCM_FAILURE(rv)) {
   2237             bcm_xgs3_ipmc_id_free(unit, ipmc->group);
   2238             if (!IPMC_USED_ISSET(unit, ipmc->group)) {
   2239                 /* Reference count should not be zero yet. */
   2240                 return BCM_E_INTERNAL;
   2241             }
   2242             return (rv);
   2243         }
   2244     } else {
   2245         if (need_write) {
   2246             /* Write L3_IPMC table entry. */
   2247             rv = _xgs3_ipmc_write(unit, ipmc->group, ipmc);
   2248             if (BCM_FAILURE(rv)) {
   2249                 if (SOC_IS_FBX(unit)) {
   2250 #if defined(BCM_FIREBOLT_SUPPORT)
   2251                     _bcm_fb_ipmc_del(unit, ipmc, TRUE);
   2252 #endif /* BCM_FIREBOLT_SUPPORT */
   2253                 }
   2254                 bcm_xgs3_ipmc_id_free(unit, ipmc->group);
   2255                 return (rv);
   2256             }
   2257         }
   2258 
   2259         /* Update existing IPMC entry */
   2260         rv = _bcm_fb_ipmc_replace(unit, ipmc, &l3cfg);
   2261         if (BCM_FAILURE(rv)) {
   2262             if (SOC_IS_FBX(unit)) {
   2263 #if defined(BCM_FIREBOLT_SUPPORT)
   2264                 _bcm_fb_ipmc_del(unit, ipmc, TRUE);
   2265 #endif /* BCM_FIREBOLT_SUPPORT */
   2266             }
   2267             bcm_xgs3_ipmc_id_free(unit, ipmc->group);
   2268             return rv;
   2269         }
   2270     } 
   2271 
   2272     return BCM_E_NONE;
   2273 }
   2274 
   2275 /*
   2276  * Function:
   2277  *      bcm_fb_er_ipmc_put
   2278  * Purpose:
   2279  *      Overwrite an entry in the IPMC table.
   2280  * Parameters:
   2281  *      unit - StrataSwitch PCI device unit number (driver internal).
   2282  *      index - Table index to overwrite.
   2283  *      data - IPMC entry information.
   2284  * Returns:
   2285  *      BCM_E_XXX
   2286  */
   2287 
   2288 int
   2289 bcm_fb_er_ipmc_put(int unit, int index, bcm_ipmc_addr_t *ipmc)
   2290 {
   2291     IPMC_INIT(unit);
   2292     IPMC_ID(unit, index); 
   2293 
   2294     BCM_IF_ERROR_RETURN(_xgs3_ipmc_write(unit, index, ipmc));
   2295 
   2296     if (SOC_IS_FBX(unit)) {
   2297 #if defined(BCM_FIREBOLT_SUPPORT)
   2298         _bcm_l3_cfg_t   l3cfg;
   2299 
   2300         sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t));
   2301         l3cfg.l3c_vid = ipmc->vid;
   2302         l3cfg.l3c_flags = BCM_L3_IPMC;
   2303         l3cfg.l3c_vrf = ipmc->vrf;
   2304         l3cfg.l3c_lookup_class = ipmc->lookup_class;
   2305         if (ipmc->flags & BCM_IPMC_IP6) {
   2306             sal_memcpy(l3cfg.l3c_sip6, ipmc->s_ip6_addr, BCM_IP6_ADDRLEN);
   2307             sal_memcpy(l3cfg.l3c_ip6, ipmc->mc_ip6_addr, BCM_IP6_ADDRLEN);
   2308             l3cfg.l3c_flags |= BCM_L3_IP6;
   2309             BCM_IF_ERROR_RETURN
   2310                 (mbcm_driver[unit]->mbcm_l3_ip6_get(unit, &l3cfg));
   2311         } else {
   2312             l3cfg.l3c_src_ip_addr = ipmc->s_ip_addr;
   2313             l3cfg.l3c_ipmc_group = ipmc->mc_ip_addr;
   2314             BCM_IF_ERROR_RETURN
   2315                 (mbcm_driver[unit]->mbcm_l3_ip4_get(unit, &l3cfg));
   2316         }
   2317 
   2318         return _bcm_fb_ipmc_replace(unit, ipmc, &l3cfg);
   2319 #endif /* BCM_FIREBOLT_SUPPORT */
   2320     }
   2321 
   2322     return BCM_E_NONE;
   2323 }
   2324 
   2325 /*
   2326  * Function:
   2327  *      _bcm_fb_er_ipmc_delete
   2328  * Purpose:
   2329  *      Delete an entry from the IPMC table.
   2330  * Parameters:
   2331  *      unit - StrataSwitch PCI device unit number (driver internal).
   2332  *      data - IPMC entry information.
   2333  *      modify_l3entry_list - Control whether to modify IPMC group's linked
   2334  *                            list of L3 entries.
   2335  * Returns:
   2336  *      BCM_E_XXX
   2337  * Notes:
   2338  *      If BCM_IPMC_KEEP_ENTRY is true, the entry valid bit is cleared
   2339  *      but the entry is not deleted from the table.
   2340  */
   2341 
   2342 STATIC int
   2343 _bcm_fb_er_ipmc_delete(int unit, bcm_ipmc_addr_t *ipmc, int modify_l3entry_list)
   2344 {
   2345     int                 ipmc_id;
   2346     _bcm_l3_cfg_t       l3cfg;
   2347 
   2348     IPMC_INIT(unit);
   2349 
   2350     if (SOC_IS_FBX(unit)) {
   2351 #if defined(BCM_FIREBOLT_SUPPORT)
   2352         sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t));
   2353         l3cfg.l3c_vid = ipmc->vid;
   2354         l3cfg.l3c_flags = BCM_L3_IPMC;
   2355         l3cfg.l3c_vrf = ipmc->vrf;
   2356         if (ipmc->flags & BCM_IPMC_IP6) {
   2357             sal_memcpy(l3cfg.l3c_sip6, ipmc->s_ip6_addr, BCM_IP6_ADDRLEN);
   2358             sal_memcpy(l3cfg.l3c_ip6, ipmc->mc_ip6_addr, BCM_IP6_ADDRLEN);
   2359             l3cfg.l3c_flags |= BCM_L3_IP6;
   2360             BCM_IF_ERROR_RETURN(
   2361                 mbcm_driver[unit]->mbcm_l3_ip6_get(unit, &l3cfg));
   2362         } else {
   2363             l3cfg.l3c_src_ip_addr = ipmc->s_ip_addr;
   2364             l3cfg.l3c_ipmc_group = ipmc->mc_ip_addr;
   2365             BCM_IF_ERROR_RETURN(
   2366                 mbcm_driver[unit]->mbcm_l3_ip4_get(unit, &l3cfg));
   2367         }
   2368 #endif /* BCM_FIREBOLT_SUPPORT */
   2369     }
   2370     ipmc_id = SOC_IS_FBX(unit) ? l3cfg.l3c_ipmc_ptr : ipmc->group;
   2371 
   2372     if (!(ipmc->flags & BCM_IPMC_KEEP_ENTRY)) {
   2373 
   2374         if (SOC_IS_FBX(unit)) {
   2375 #if defined(BCM_FIREBOLT_SUPPORT)
   2376             BCM_IF_ERROR_RETURN(_bcm_fb_ipmc_del(unit, ipmc, modify_l3entry_list));
   2377 #endif /* BCM_FIREBOLT_SUPPORT */
   2378         }
   2379 
   2380         bcm_xgs3_ipmc_id_free(unit, ipmc_id);
   2381         if (!IPMC_USED_ISSET(unit, ipmc_id)) {
   2382             /* Reference count should not be zero yet. */
   2383             return BCM_E_INTERNAL;
   2384         }
   2385     }
   2386 
   2387     return BCM_E_NONE;
   2388 }
   2389 
   2390 /*
   2391  * Function:
   2392  *      bcm_fb_er_ipmc_delete
   2393  * Purpose:
   2394  *      Delete an entry from the IPMC table.
   2395  * Parameters:
   2396  *      unit - StrataSwitch PCI device unit number (driver internal).
   2397  *      data - IPMC entry information.
   2398  * Returns:
   2399  *      BCM_E_XXX
   2400  * Notes:
   2401  *      If BCM_IPMC_KEEP_ENTRY is true, the entry valid bit is cleared
   2402  *      but the entry is not deleted from the table.
   2403  */
   2404 
   2405 int
   2406 bcm_fb_er_ipmc_delete(int unit, bcm_ipmc_addr_t *ipmc)
   2407 {
   2408     return _bcm_fb_er_ipmc_delete(unit, ipmc, TRUE);
   2409 }
   2410 
   2411 /*
   2412  * Function:
   2413  *      bcm_fb_er_ipmc_delete_all
   2414  * Purpose:
   2415  *      Delete all entries from the IPMC table.
   2416  * Parameters:
   2417  *      unit - StrataSwitch PCI device unit number (driver internal).
   2418  * Returns:
   2419  *      BCM_E_XXX
   2420  */
   2421 
   2422 int
   2423 bcm_fb_er_ipmc_delete_all(int unit)
   2424 {
   2425     _bcm_esw_ipmc_l3entry_t *ipmc_l3entry; 
   2426     int rv = BCM_E_NONE, i;
   2427 #if defined(BCM_FIREBOLT_SUPPORT)
   2428     _bcm_l3_cfg_t l3cfg;
   2429 #endif /* BCM_FIREBOLT_SUPPORT */
   2430 
   2431     IPMC_INIT(unit);
   2432 
   2433     IPMC_LOCK(unit);
   2434     for (i = 0; i < IPMC_GROUP_NUM(unit); i++) {
   2435         if (IPMC_USED_ISSET(unit, i)) {
   2436             ipmc_l3entry = IPMC_GROUP_INFO(unit, i)->l3entry_list;
   2437             while (ipmc_l3entry != NULL) {
   2438                 if (SOC_IS_FBX(unit)) {
   2439 #if defined(BCM_FIREBOLT_SUPPORT)
   2440                     sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t));
   2441                     l3cfg.l3c_vid = ipmc_l3entry->l3info.vid;
   2442                     l3cfg.l3c_flags = BCM_L3_IPMC;
   2443                     l3cfg.l3c_vrf = ipmc_l3entry->l3info.vrf;
   2444                     if (ipmc_l3entry->l3info.flags & BCM_L3_IP6) {
   2445                         sal_memcpy(l3cfg.l3c_sip6, ipmc_l3entry->l3info.sip6, BCM_IP6_ADDRLEN);
   2446                         sal_memcpy(l3cfg.l3c_ip6, ipmc_l3entry->l3info.ip6, BCM_IP6_ADDRLEN);
   2447                         l3cfg.l3c_flags |= BCM_L3_IP6;
   2448                     } else {
   2449                         l3cfg.l3c_src_ip_addr = ipmc_l3entry->l3info.src_ip_addr;
   2450                         l3cfg.l3c_ipmc_group = ipmc_l3entry->l3info.ip_addr;
   2451                     }
   2452                     rv = bcm_xgs3_l3_del(unit, &l3cfg);
   2453                     if (BCM_FAILURE(rv)) {
   2454                         IPMC_UNLOCK(unit);
   2455                         return rv;
   2456                     }
   2457 #endif /* BCM_FIREBOLT_SUPPORT */
   2458                 }
   2459                 IPMC_GROUP_INFO(unit, i)->l3entry_list = ipmc_l3entry->next;
   2460                 sal_free(ipmc_l3entry);
   2461                 ipmc_l3entry = IPMC_GROUP_INFO(unit, i)->l3entry_list;
   2462             }
   2463 
   2464             /* For IPMC groups that have non-zero reference counts,
   2465              * decrease reference count to 1, meaning the IPMC group
   2466              * is only referenced by bcm_multicast_egress APIs.
   2467              */
   2468             IPMC_USED_ONE(unit, i);
   2469         }
   2470     }
   2471 
   2472     IPMC_UNLOCK(unit);
   2473 
   2474     return rv;
   2475 }
   2476 
   2477 
   2478 /*
   2479  * Function:
   2480  *      bcm_xgs3_ipmc_age
   2481  * Purpose:
   2482  *      Age out the ipmc entry by clearing the HIT bit when appropriate,
   2483  *      the ipmc entry itself is removed if HIT bit is not set.
   2484  * Parameters:
   2485  *      unit       -  (IN) BCM device number.
   2486  *      flags      -  (IN) The criteria used to age out ipmc table.
   2487  *                         IPv6/IPv4
   2488  *      age_cb     -  (IN) Call back routine.
   2489  *      user_data  -  (IN) User provided cookie for callback.
   2490  * Returns:
   2491  *      BCM_E_XXX 
   2492  */
   2493 int
   2494 bcm_xgs3_ipmc_age(int unit, uint32 flags, bcm_ipmc_traverse_cb age_cb, 
   2495                  void *user_data)
   2496 {
   2497     int idx;                   /* Ipmc table iteration index. */
   2498     bcm_ipmc_addr_t entry;     /* Ipmc entry iterator.        */
   2499     int rv = BCM_E_NONE;       /* Operation return status.    */
   2500     ipmc_entry_t ipmc_entry;
   2501     _bcm_esw_ipmc_l3entry_t *ipmc_l3entry;
   2502     _bcm_esw_ipmc_l3entry_t *prev_ipmc_l3entry = NULL;
   2503     int l3index = 0;
   2504 
   2505     IPMC_INIT(unit);
   2506     IPMC_LOCK(unit);
   2507 
   2508     for (idx = 0; idx < IPMC_GROUP_NUM(unit); idx++) {
   2509         if (IPMC_USED_ISSET(unit, idx)) {
   2510 
   2511             rv = soc_mem_read(unit, L3_IPMCm, MEM_BLOCK_ANY, idx, &ipmc_entry);
   2512             if (BCM_FAILURE(rv)) {
   2513                 goto age_done;
   2514             }
   2515 
   2516             ipmc_l3entry = IPMC_GROUP_INFO(unit, idx)->l3entry_list;
   2517             while (ipmc_l3entry != NULL) {
   2518                 sal_memset(&entry, 0, sizeof(bcm_ipmc_addr_t));
   2519                 rv = _xgs3_ipmc_info_get(unit, l3index, idx, TRUE, &entry, 
   2520                                          &ipmc_entry, 1, ipmc_l3entry);
   2521                 if (BCM_FAILURE(rv)) {
   2522                     goto age_done;
   2523                 }
   2524 
   2525                 /* Make sure update only ipv4 or ipv6 entries. */
   2526                 if ((flags & BCM_IPMC_IP6) != (entry.flags & BCM_IPMC_IP6)) {
   2527                     prev_ipmc_l3entry = ipmc_l3entry;
   2528                     ipmc_l3entry = ipmc_l3entry->next;
   2529                     continue;
   2530                 }
   2531 
   2532                 if (entry.flags & BCM_IPMC_HIT) {
   2533                     if (SOC_IS_FBX(unit)) {
   2534                         _bcm_l3_cfg_t l3cfg;
   2535                         /* Clear hit bit on used entry (by doing a lookup !!) */
   2536                         sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t));
   2537                         l3cfg.l3c_flags |= BCM_L3_HIT_CLEAR;
   2538                         l3cfg.l3c_vid = ipmc_l3entry->l3info.vid;
   2539                         l3cfg.l3c_flags |= BCM_L3_IPMC;
   2540                         l3cfg.l3c_vrf = ipmc_l3entry->l3info.vrf;
   2541                         l3cfg.l3c_vid = ipmc_l3entry->l3info.vid;
   2542 
   2543                         if (ipmc_l3entry->ip6) {
   2544                             sal_memcpy(l3cfg.l3c_sip6, &ipmc_l3entry->l3info.sip6, 
   2545                                        BCM_IP6_ADDRLEN);
   2546                             sal_memcpy(l3cfg.l3c_ip6, &ipmc_l3entry->l3info.ip6, 
   2547                                        BCM_IP6_ADDRLEN);
   2548                             l3cfg.l3c_flags |= BCM_L3_IP6;
   2549                             rv = (mbcm_driver[unit]->mbcm_l3_ip6_get(unit, &l3cfg));
   2550                         } else {
   2551                             l3cfg.l3c_src_ip_addr = ipmc_l3entry->l3info.src_ip_addr;
   2552                             l3cfg.l3c_ipmc_group = ipmc_l3entry->l3info.ipmc_group;
   2553                             rv = (mbcm_driver[unit]->mbcm_l3_ip4_get(unit, &l3cfg));
   2554                         }
   2555                     } else {  
   2556                         /* Clear hit bit on used entry. */
   2557                         entry.flags |= BCM_IPMC_HIT_CLEAR;
   2558                         rv = _xgs3_ipmc_info_get(unit, l3index, idx, TRUE, &entry, 
   2559                                                  &ipmc_entry, 0, NULL);
   2560                     }
   2561                     if (BCM_FAILURE(rv)) {
   2562                         goto age_done;
   2563                     }
   2564                     prev_ipmc_l3entry = ipmc_l3entry;
   2565                     ipmc_l3entry = ipmc_l3entry->next;
   2566                 } else {
   2567                     /* Delete IPMC L3 entry. Inhibit modification of IPMC group's
   2568                      * l3entry_list by _bcm_fb_er_ipmc_delete.
   2569                      */
   2570                     rv = _bcm_fb_er_ipmc_delete(unit, &entry, FALSE);
   2571                     if (BCM_FAILURE(rv)) {
   2572                         goto age_done;
   2573                     }
   2574 
   2575                     /* Delete from IPMC group's l3entry_list */
   2576                     if (ipmc_l3entry == IPMC_GROUP_INFO(unit, idx)->l3entry_list) {
   2577                         IPMC_GROUP_INFO(unit, idx)->l3entry_list = ipmc_l3entry->next;
   2578                         sal_free(ipmc_l3entry);
   2579                         ipmc_l3entry = IPMC_GROUP_INFO(unit, idx)->l3entry_list;
   2580                     } else {
   2581                         /* 
   2582                          * In the following line of code, Coverity thinks the
   2583                          * prev_ipmc_l3entry pointer may still be NULL when 
   2584                          * dereferenced. This situation will never occur because 
   2585                          * if ipmc_l3entry is not pointing to the head of the 
   2586                          * linked list, prev_ipmc_l3entry would not be NULL.
   2587                          */
   2588                         /* coverity[var_deref_op : FALSE] */
   2589                         prev_ipmc_l3entry->next = ipmc_l3entry->next;
   2590                         sal_free(ipmc_l3entry);
   2591                         ipmc_l3entry = prev_ipmc_l3entry->next;
   2592                     }
   2593 
   2594                     /* Invoke user callback. */
   2595                     if (NULL != age_cb) {
   2596                         _BCM_MULTICAST_GROUP_SET(entry.group,
   2597                                 _BCM_MULTICAST_TYPE_L3, entry.group);
   2598                         rv = (*age_cb)(unit, &entry, user_data);
   2599 #ifdef BCM_CB_ABORT_ON_ERR
   2600                         if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   2601                             goto age_done;
   2602                         }
   2603 #endif
   2604                     }
   2605                 }
   2606             }
   2607         }
   2608     }
   2609 
   2610 age_done:
   2611     IPMC_UNLOCK(unit);
   2612     return (rv);
   2613 }
   2614 
   2615 /*
   2616  * Function:
   2617  *      bcm_xgs3_ipmc_traverse
   2618  * Purpose:
   2619  *      Go through all valid ipmc entries, and call the callback function
   2620  *      at each entry
   2621  * Parameters:
   2622  *      unit      - (IN) BCM device number.
   2623  *      flags     - (IN) The criteria used to age out ipmc table.
   2624  *      cb        - (IN) User supplied callback function.
   2625  *      user_data - (IN) User supplied cookie used in parameter 
   2626  *                       in callback function.
   2627  * Returns:
   2628  *      BCM_E_XXX
   2629  */
   2630 int
   2631 bcm_xgs3_ipmc_traverse(int unit, uint32 flags, bcm_ipmc_traverse_cb cb,
   2632                        void *user_data)
   2633 {
   2634     int idx;                   /* Ipmc table iteration index. */
   2635     bcm_ipmc_addr_t entry;     /* Ipmc entry iterator.        */
   2636     int rv = BCM_E_NONE;       /* Operation return status.    */
   2637     ipmc_entry_t ipmc_entry;
   2638     _bcm_esw_ipmc_l3entry_t *ipmc_l3entry;
   2639     int l3index = 0;
   2640 
   2641     IPMC_INIT(unit);
   2642     IPMC_LOCK(unit);
   2643 
   2644     for (idx = 0; idx < IPMC_GROUP_NUM(unit); idx++) {
   2645         if (IPMC_USED_ISSET(unit, idx)) {
   2646 
   2647             rv = soc_mem_read(unit, L3_IPMCm, MEM_BLOCK_ANY, idx, &ipmc_entry);
   2648             if (BCM_FAILURE(rv)) {
   2649                 goto traverse_done;
   2650             }
   2651 
   2652             ipmc_l3entry = IPMC_GROUP_INFO(unit, idx)->l3entry_list;
   2653             while (ipmc_l3entry != NULL) {
   2654                 sal_memset(&entry, 0, sizeof(bcm_ipmc_addr_t));
   2655                 rv = _xgs3_ipmc_info_get(unit, l3index, idx, TRUE, &entry, 
   2656                                          &ipmc_entry, 1, ipmc_l3entry);
   2657                 if (BCM_FAILURE(rv)) {
   2658                     goto traverse_done;
   2659                 }
   2660 
   2661                 if ((flags & BCM_IPMC_IP6) != (entry.flags & BCM_IPMC_IP6)) {
   2662                     ipmc_l3entry = ipmc_l3entry->next;
   2663                     continue;
   2664                 }
   2665 
   2666                 /* Get the pointer to next ipmc_l3entry before callback,
   2667                  * since callback may delete the current ipmc_l3entry.
   2668                  */
   2669                 ipmc_l3entry = ipmc_l3entry->next;
   2670 
   2671                 /* Invoke user callback. */
   2672                 _BCM_MULTICAST_GROUP_SET(entry.group,
   2673                                 _BCM_MULTICAST_TYPE_L3, entry.group);
   2674                 rv = (*cb)(unit, &entry, user_data);
   2675 #ifdef BCM_CB_ABORT_ON_ERR
   2676                 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) {
   2677                     goto traverse_done;
   2678                 }
   2679 #endif
   2680             }
   2681         }
   2682     }
   2683 
   2684 traverse_done:
   2685     IPMC_UNLOCK(unit);
   2686     return (rv);
   2687 }
   2688 
   2689 
   2690 /*
   2691  * Function:
   2692  *      bcm_fb_er_ipmc_enable
   2693  * Purpose:
   2694  *      Enable or disable IPMC chip functions.
   2695  * Parameters:
   2696  *      unit - Unit number
   2697  *      enable - TRUE to enable; FALSE to disable
   2698  * Returns:
   2699  *      BCM_E_XXX
   2700  */
   2701 
   2702 int
   2703 bcm_fb_er_ipmc_enable(int unit, int enable)
   2704 {
   2705     IPMC_INIT(unit);
   2706 
   2707     return _xgs3_ipmc_enable(unit, enable);
   2708 }
   2709 
   2710 /*
   2711  * Function:
   2712  *      _bcm_xgs3_ipmc_valid_as_hit_get
   2713  * Purpose:
   2714  *      Check if IPMC valid bit as hit bit mode is enabled.
   2715  * Parameters:
   2716  *      unit - Unit number
   2717  *      valid_as_hit - (OUT) TRUE for hit bit; FALSE for valid bit
   2718  * Returns:
   2719  *      BCM_E_XXX
   2720  */
   2721 
   2722 int
   2723 _bcm_xgs3_ipmc_valid_as_hit_get(int unit, int *valid_as_hit)
   2724 {
   2725     IPMC_INIT(unit);
   2726     *valid_as_hit = IPMC_VALID_AS_HIT(unit);
   2727     return BCM_E_NONE;
   2728 }
   2729 
   2730 /*
   2731  * Function:
   2732  *      bcm_fb_er_ipmc_src_port_check
   2733  * Purpose:
   2734  *      Enable or disable Source Port checking in IPMC lookups.
   2735  * Parameters:
   2736  *      unit - Unit number
   2737  *      enable - TRUE to enable; FALSE to disable
   2738  * Returns:
   2739  *      BCM_E_XXX
   2740  */
   2741 
   2742 int
   2743 bcm_fb_er_ipmc_src_port_check(int unit, int enable)
   2744 {
   2745     IPMC_INIT(unit);
   2746 
   2747     return BCM_E_UNAVAIL;
   2748 }
   2749 
   2750 /*
   2751  * Function:
   2752  *      bcm_fb_er_ipmc_src_ip_search
   2753  * Purpose:
   2754  *      Enable or disable Source IP significance in IPMC lookups.
   2755  * Parameters:
   2756  *      unit - Unit number
   2757  *      enable - TRUE to enable; FALSE to disable
   2758  * Returns:
   2759  *      BCM_E_XXX
   2760  */
   2761 
   2762 int
   2763 bcm_fb_er_ipmc_src_ip_search(int unit, int enable)
   2764 {
   2765     IPMC_INIT(unit);
   2766 
   2767     if (enable) {
   2768         return BCM_E_NONE;  /* always on */
   2769     } else {
   2770         return BCM_E_FAIL;  /* cannot be disabled */
   2771     }
   2772 }
   2773 
   2774 
   2775 /*
   2776  * Function:
   2777  *      bcm_fb_er_ipmc_egress_port_set
   2778  * Purpose:
   2779  *      Configure the IP Multicast egress properties
   2780  * Parameters:
   2781  *      unit - StrataSwitch PCI device unit number (driver internal).
   2782  *      port - port to config.
   2783  *      mac  - MAC address.
   2784  *      untag - 1: The IP multicast packet is transmitted as untagged packet.
   2785  *              0: The IP multicast packet is transmitted as tagged packet
   2786  *              with VLAN tag vid.
   2787  *      vid  - VLAN ID.
   2788  *      ttl  - 1 to disable the TTL decrement, 0 otherwise.
   2789  * Returns:
   2790  *      BCM_E_XXX
   2791  */
   2792 
   2793 int
   2794 bcm_fb_er_ipmc_egress_port_set(int unit, bcm_port_t port,
   2795                                const bcm_mac_t mac, int untag,
   2796                                bcm_vlan_t vid, int ttl)
   2797 {
   2798     uint32      cfg2;
   2799 
   2800 #if defined(BCM_RAPTOR_SUPPORT)
   2801     if (SOC_IS_RAPTOR(unit) || SOC_IS_HAWKEYE(unit)) {
   2802         return BCM_E_UNAVAIL;
   2803     }
   2804 #endif
   2805 
   2806     if (!SOC_PBMP_PORT_VALID(port) || !IS_PORT(unit, port)) {
   2807         return BCM_E_BADID;
   2808     }
   2809 
   2810     cfg2 = 0;
   2811 
   2812     soc_reg_field_set(unit, EGR_IPMC_CFG2r, &cfg2,
   2813                       UNTAGf, untag ? 1 : 0);
   2814     soc_reg_field_set(unit, EGR_IPMC_CFG2r, &cfg2,
   2815                       VIDf, vid);
   2816     soc_reg_field_set(unit, EGR_IPMC_CFG2r, &cfg2,
   2817                       DISABLE_SA_REPLACEf, 0);
   2818 
   2819     SOC_IF_ERROR_RETURN(WRITE_EGR_IPMC_CFG2r(unit, port, cfg2));
   2820 
   2821     return BCM_E_NONE;
   2822 }
   2823 
   2824 /*
   2825  * Function:
   2826  *      bcm_fb_er_ipmc_egress_port_get
   2827  * Purpose:
   2828  *      Return the IP Multicast egress properties
   2829  * Parameters:
   2830  *      unit - StrataSwitch PCI device unit number (driver internal).
   2831  *      port - port to config.
   2832  *      mac - (OUT) MAC address.
   2833  *      untag - (OUT) 1: The IP multicast packet is transmitted as
   2834  *                       untagged packet.
   2835  *                    0: The IP multicast packet is transmitted as tagged
   2836  *                       packet with VLAN tag vid.
   2837  *      vid - (OUT) VLAN ID.
   2838  *      ttl_thresh - (OUT) Drop IPMC packets if TTL <= ttl_thresh.
   2839  * Returns:
   2840  *      BCM_E_XXX
   2841  */
   2842 
   2843 int
   2844 bcm_fb_er_ipmc_egress_port_get(int unit, bcm_port_t port, sal_mac_addr_t mac,
   2845                             int *untag, bcm_vlan_t *vid, int *ttl_thresh)
   2846 {
   2847     uint32              cfg2;
   2848 
   2849 #if defined(BCM_RAPTOR_SUPPORT)
   2850     if (SOC_IS_RAPTOR(unit) || SOC_IS_HAWKEYE(unit)) {
   2851         return BCM_E_UNAVAIL;
   2852     }
   2853 #endif
   2854 
   2855     if (!SOC_PBMP_PORT_VALID(port) || !IS_PORT(unit, port)) {
   2856         return BCM_E_BADID;
   2857     }
   2858 
   2859 
   2860     SOC_IF_ERROR_RETURN(READ_EGR_IPMC_CFG2r(unit, port, &cfg2));
   2861 
   2862     *untag = soc_reg_field_get(unit, EGR_IPMC_CFG2r, cfg2, UNTAGf);
   2863     *vid = soc_reg_field_get(unit, EGR_IPMC_CFG2r, cfg2, VIDf);
   2864     *ttl_thresh = -1;
   2865 
   2866     return BCM_E_NONE;
   2867 }
   2868 
   2869 #if defined(BCM_FIREBOLT_SUPPORT)
   2870 /*
   2871  * Function:
   2872  *      bcm_fb_ipmc_repl_init
   2873  * Purpose:
   2874  *      Initialize IPMC replication.
   2875  * Parameters:
   2876  *      unit     - SOC unit #
   2877  * Returns:
   2878  *      BCM_E_XXX
   2879  */
   2880 
   2881 int
   2882 bcm_fb_ipmc_repl_init(int unit)
   2883 {
   2884     bcm_port_t          port;
   2885     int                 alloc_size;
   2886     int                 act_port;
   2887 #if defined(BCM_GREYHOUND2_SUPPORT)
   2888     int                 mmu_port, phy_port = 0;
   2889 #endif
   2890     int                 i;
   2891 
   2892     bcm_fb_ipmc_repl_detach(unit);
   2893 
   2894     /* Allocate struct for IPMC replication bookkeeping */
   2895     alloc_size = sizeof(_fb_repl_info_t);
   2896     _fb_repl_info[unit] = sal_alloc(alloc_size, "IPMC repl info");
   2897     if (_fb_repl_info[unit] == NULL) {
   2898         return BCM_E_MEMORY;
   2899     }
   2900     sal_memset(_fb_repl_info[unit], 0, alloc_size);
   2901     _fb_repl_info[unit]->ipmc_size = soc_mem_index_count(unit, L3_IPMCm);
   2902 
   2903 #ifdef BCM_BRADLEY_SUPPORT
   2904     if (SOC_IS_HBX(unit)) {
   2905         int ipmc_base, ipmc_size;
   2906         
   2907         SOC_IF_ERROR_RETURN
   2908             (soc_hbx_ipmc_size_get(unit, &ipmc_base, &ipmc_size));
   2909 
   2910         if (_fb_repl_info[unit]->ipmc_size > ipmc_size) {
   2911             /* Reduce to fix allocated table space */
   2912             _fb_repl_info[unit]->ipmc_size = ipmc_size;
   2913         }
   2914     }
   2915 #endif
   2916 
   2917 #ifdef BCM_TRIUMPH_SUPPORT
   2918     if (SOC_IS_TR_VL(unit) && !SOC_IS_HURRICANEX(unit) && 
   2919             !SOC_IS_GREYHOUND(unit) && !SOC_IS_GREYHOUND2(unit)) {
   2920         /* For VPLS, can replicate to 16k next-hop entries */
   2921         IPMC_REPL_INTF_TOTAL(unit) = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
   2922     } else
   2923 #endif
   2924     {
   2925         /* for GH case, eventhough the L3MC egress logic changed to goto 
   2926          * EGR_L3_NEXT_HOPm before EGR_L3_INTFm, the maximum replication still 
   2927          * be limited of EGR_L3_INTFm size.
   2928          */
   2929         IPMC_REPL_INTF_TOTAL(unit) = soc_mem_index_count(unit, EGR_L3_INTFm);
   2930     }
   2931 
   2932     /*
   2933      * soc_feature_l3mc_use_egress_next_hop use EGR_L3_NEXT_HOP as
   2934      * replication interface instead of using EGR_L3_INTF.
   2935      */
   2936     if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) {
   2937         IPMC_REPL_INTF_TOTAL(unit) = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
   2938     }
   2939 
   2940     IPMC_REPL_TOTAL(unit) = soc_mem_index_count(unit, MMU_IPMC_VLAN_TBLm);
   2941     alloc_size = SHR_BITALLOCSIZE(IPMC_REPL_TOTAL(unit));
   2942     _fb_repl_info[unit]->bitmap_entries_used =
   2943         sal_alloc(alloc_size, "IPMC repl entries used");
   2944     if (_fb_repl_info[unit]->bitmap_entries_used == NULL) {
   2945         bcm_fb_ipmc_repl_detach(unit);
   2946         return BCM_E_MEMORY;
   2947     }
   2948     sal_memset(_fb_repl_info[unit]->bitmap_entries_used, 0, alloc_size);
   2949 
   2950     if (NULL == _fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc) {
   2951         _fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc =
   2952             sal_alloc(sizeof(int) * soc_mem_index_count(unit, EGR_L3_INTFm),
   2953                       "l3_intf_to_next_hop_ipmc");
   2954         if (NULL == _fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc) {
   2955             bcm_fb_ipmc_repl_detach(unit);
   2956             return BCM_E_MEMORY;
   2957         }
   2958     }
   2959     for (i = 0; i < soc_mem_index_count(unit, EGR_L3_INTFm); i++) {
   2960         _fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc[i] =
   2961             REPL_NH_INDEX_UNALLOCATED;
   2962     }
   2963 
   2964     if (NULL == _fb_repl_info[unit]->l3_nh_to_l3_intf_ipmc) {
   2965         _fb_repl_info[unit]->l3_nh_to_l3_intf_ipmc =
   2966             sal_alloc(sizeof(int) * soc_mem_index_count(unit, EGR_L3_NEXT_HOPm),
   2967                       "next_hop_to_l3_intf_ipmc");
   2968 
   2969         if (NULL == _fb_repl_info[unit]->l3_nh_to_l3_intf_ipmc) {
   2970             bcm_fb_ipmc_repl_detach(unit);
   2971             return BCM_E_MEMORY;
   2972         }
   2973     }
   2974     for (i = 0; i < soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); i++) {
   2975         _fb_repl_info[unit]->l3_nh_to_l3_intf_ipmc[i] =
   2976             REPL_L3_INTF_UNALLOCATED;
   2977     }
   2978 
   2979     /* Always reserve slot 0 */
   2980     IPMC_REPL_VE_USED_SET(unit, 0);
   2981 
   2982     PBMP_ITER(PBMP_PORT_ALL(unit), port) {
   2983         act_port = port;
   2984         alloc_size = sizeof(_fb_repl_port_info_t);
   2985         IPMC_REPL_PORT_INFO(unit, act_port) =
   2986             sal_alloc(alloc_size, "IPMC repl port info");
   2987         if (IPMC_REPL_PORT_INFO(unit, act_port) == NULL) {
   2988             bcm_fb_ipmc_repl_detach(unit);
   2989             return BCM_E_MEMORY;
   2990         }
   2991         sal_memset(IPMC_REPL_PORT_INFO(unit, act_port), 0, alloc_size);
   2992        
   2993         alloc_size = sizeof(int32) * soc_mem_index_count(unit, L3_IPMCm);
   2994         IPMC_REPL_PORT_INFO(unit, act_port)->vlan_count =
   2995             sal_alloc(alloc_size, "IPMC repl port vlan count");
   2996         if (IPMC_REPL_PORT_INFO(unit, act_port)->vlan_count == NULL) {
   2997             bcm_fb_ipmc_repl_detach(unit);
   2998             return BCM_E_MEMORY;
   2999         }
   3000         sal_memset(IPMC_REPL_PORT_INFO(unit, act_port)->vlan_count,
   3001                    0, alloc_size);
   3002     }
   3003 
   3004     if (!SAL_BOOT_QUICKTURN) {
   3005 #ifdef BCM_GREYHOUND_SUPPORT
   3006         /* to clear all MMU_IPMC_GROUP_TBLm
   3007          * 
   3008          *  Note : Greyhound device changed these tables from system to 
   3009          *          port based tables. 
   3010          */
   3011         if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)){
   3012             _rep_regs_t *ipmc_group_tbl = gh_rep_regs;
   3013 
   3014 #if defined(BCM_HURRICANE3_SUPPORT)
   3015             if (SOC_IS_HURRICANE3(unit)) {
   3016                 ipmc_group_tbl = hr3_rep_regs;
   3017             }
   3018 #endif  /* HURRICANE3 */
   3019 #if defined(BCM_GREYHOUND2_SUPPORT)
   3020             if (SOC_IS_GREYHOUND2(unit)) {
   3021                 ipmc_group_tbl = gh2_rep_regs;
   3022             }
   3023 #endif  /* HURRICANE3 */
   3024 
   3025             PBMP_ITER(PBMP_PORT_ALL(unit), port) {
   3026 #if defined(BCM_GREYHOUND2_SUPPORT)
   3027                 if (SOC_IS_GREYHOUND2(unit)) {
   3028                     phy_port = SOC_INFO(unit).port_l2p_mapping[port];
   3029                     mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port];
   3030                     act_port = mmu_port;
   3031                 } else 
   3032 #endif
   3033                 {
   3034                     act_port = port;
   3035                 }
   3036                 if (ipmc_group_tbl[act_port].mem == INVALIDm) {
   3037                     continue;
   3038                 }
   3039 
   3040                 SOC_IF_ERROR_RETURN(soc_mem_clear(unit, 
   3041                         ipmc_group_tbl[act_port].mem, COPYNO_ALL, FALSE));
   3042             }
   3043         } else 
   3044 #endif  /* BCM_GREYHOUND_SUPPORT */
   3045         {
   3046 
   3047         SOC_IF_ERROR_RETURN
   3048             (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL0m, COPYNO_ALL, FALSE));
   3049         SOC_IF_ERROR_RETURN
   3050             (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL1m, COPYNO_ALL, FALSE));
   3051         SOC_IF_ERROR_RETURN
   3052             (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL2m, COPYNO_ALL, FALSE));
   3053         if (!SOC_IS_RAVEN(unit)) {
   3054             SOC_IF_ERROR_RETURN
   3055                 (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL3m, COPYNO_ALL, FALSE));
   3056         }
   3057         if (!SOC_IS_HB_GW(unit) && !SOC_IS_RAVEN(unit) && !SOC_IS_ENDURO(unit)) {
   3058             SOC_IF_ERROR_RETURN
   3059                 (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL4m, COPYNO_ALL, FALSE));
   3060             SOC_IF_ERROR_RETURN
   3061                 (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL5m, COPYNO_ALL, FALSE));
   3062 			if(!SOC_IS_HURRICANEX(unit)) {
   3063                 SOC_IF_ERROR_RETURN
   3064                     (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL6m, COPYNO_ALL, FALSE));
   3065 			}
   3066             if (!SOC_IS_SC_CQ(unit) && !SOC_IS_HURRICANEX(unit)) {
   3067                 SOC_IF_ERROR_RETURN
   3068                     (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL7m, COPYNO_ALL, 
   3069                                    FALSE));
   3070             }
   3071         }
   3072 #ifdef BCM_TRIUMPH_SUPPORT
   3073         if (SOC_MEM_IS_VALID(unit, MMU_IPMC_GROUP_TBL8m)) {
   3074             SOC_IF_ERROR_RETURN
   3075                 (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL8m, COPYNO_ALL, FALSE));
   3076         }
   3077 #endif
   3078 
   3079         SOC_IF_ERROR_RETURN
   3080             (soc_mem_clear(unit, MMU_IPMC_VLAN_TBLm, COPYNO_ALL, FALSE));
   3081 
   3082         } /* if (SOC_IS_GREYHOUND) */
   3083     }
   3084     
   3085     return BCM_E_NONE;
   3086 
   3087 }
   3088 
   3089 /*
   3090  * Function:
   3091  *      bcm_fb_ipmc_repl_detach
   3092  * Purpose:
   3093  *      Initialize IPMC replication.
   3094  * Parameters:
   3095  *      unit     - SOC unit #
   3096  * Returns:
   3097  *      BCM_E_XXX
   3098  */
   3099 
   3100 int
   3101 bcm_fb_ipmc_repl_detach(int unit)
   3102 {
   3103     bcm_port_t          port;
   3104     _bcm_repl_list_info_t *rli_current, *rli_free;
   3105 
   3106     if (_fb_repl_info[unit] != NULL) {
   3107         PBMP_ITER(PBMP_PORT_ALL(unit), port) {
   3108             if (_fb_repl_info[unit]->port_info[port] != NULL) {
   3109                 if (_fb_repl_info[unit]->
   3110                     port_info[port]->vlan_count != NULL) {
   3111                     sal_free(_fb_repl_info[unit]->
   3112                              port_info[port]->vlan_count);
   3113                 }
   3114                 sal_free(_fb_repl_info[unit]->port_info[port]);
   3115             }
   3116         }
   3117 
   3118         if (_fb_repl_info[unit]->bitmap_entries_used != NULL) {
   3119             sal_free(_fb_repl_info[unit]->bitmap_entries_used);
   3120         }
   3121 
   3122         if (_fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc != NULL) {
   3123             sal_free(_fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc);
   3124         }
   3125 
   3126         if (_fb_repl_info[unit]->l3_nh_to_l3_intf_ipmc != NULL) {
   3127             sal_free(_fb_repl_info[unit]->l3_nh_to_l3_intf_ipmc);
   3128         }
   3129 
   3130         if (_fb_repl_info[unit]->repl_list_info != NULL) {
   3131             rli_current = IPMC_REPL_LIST_INFO(unit);
   3132             while (rli_current != NULL) {
   3133                 rli_free = rli_current;
   3134                 rli_current = rli_current->next;
   3135                 sal_free(rli_free);
   3136             }
   3137         }
   3138 
   3139         sal_free(_fb_repl_info[unit]);
   3140         _fb_repl_info[unit] = NULL;
   3141     }
   3142 
   3143     return BCM_E_NONE;
   3144 }
   3145 
   3146 /*
   3147  * Function:
   3148  *      bcm_fb_ipmc_repl_get
   3149  * Purpose:
   3150  *      Return set of VLANs selected for port's replication list for chosen
   3151  *      IPMC group.
   3152  * Parameters:
   3153  *      unit     - StrataSwitch PCI device unit number.
   3154  *      ipmc_id  - The index number.
   3155  *      port     - port to list.
   3156  *      vlan_vec - (OUT) vector of replicated VLANs common to selected ports.
   3157  * Returns:
   3158  *      BCM_E_XXX
   3159  */
   3160 
   3161 int
   3162 bcm_fb_ipmc_repl_get(int unit, int ipmc_id, bcm_port_t port,
   3163                         bcm_vlan_vector_t vlan_vec)
   3164 {
   3165     int                 rv = BCM_E_NONE;
   3166     uint32              ms_bit;
   3167     uint32              ls_bits[2];
   3168     mmu_ipmc_vlan_tbl_entry_t vlan_entry;
   3169     bcm_l3_intf_t       l3_intf;
   3170     int                 vlan_ptr, last_vlan_ptr;
   3171     uint32              vlan_count;
   3172     int                 ls_pos;
   3173     int                 rvth = BCM_E_NONE;
   3174 
   3175     IPMC_REPL_INIT(unit);
   3176 
   3177     IPMC_REPL_ID(unit, ipmc_id);
   3178 
   3179     REPL_PORT_CHECK(unit, port);
   3180 
   3181     BCM_VLAN_VEC_ZERO(vlan_vec);
   3182 
   3183     IPMC_REPL_LOCK(unit);
   3184     if (IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id) == 0) {
   3185         IPMC_REPL_UNLOCK(unit);
   3186         return rvth;
   3187     }
   3188 
   3189     if (soc_feature(unit, soc_feature_ipmc_repl_freeze) && 
   3190         ((rv = _bcm_fb_ipmc_repl_freeze(unit)) < 0)) {
   3191         IPMC_REPL_UNLOCK(unit);
   3192         return rv;
   3193     }
   3194 
   3195     if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, port, &vlan_ptr, 0, 0)) < 0) {
   3196         goto get_done;
   3197     }
   3198     last_vlan_ptr = -1;
   3199     vlan_count = 0;
   3200     while (vlan_ptr != last_vlan_ptr) {
   3201         if ((rv = READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL,
   3202                                           vlan_ptr, &vlan_entry)) < 0) {
   3203             goto get_done;
   3204         }
   3205         ms_bit = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   3206                                                     &vlan_entry, MSB_VLANf);
   3207         soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry,
   3208                                          LSB_VLAN_BMf, ls_bits);
   3209         last_vlan_ptr = vlan_ptr;
   3210         vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   3211                                                       &vlan_entry, NEXTPTRf);
   3212 
   3213         /* Translate the HW L3 interfaces into the corresponding VLANs.
   3214          * Note, this may result in some loss of information.
   3215          */
   3216         for (ls_pos = 0; ls_pos < 64; ls_pos++) {
   3217             if (ls_bits[ls_pos / 32] & (1 << (ls_pos % 32))) {
   3218                 bcm_l3_intf_t_init(&l3_intf);
   3219                 l3_intf.l3a_intf_id =
   3220                     (ms_bit << 6) + ls_pos;
   3221                 if ((rv = bcm_esw_l3_intf_get(unit, &l3_intf)) < 0) {
   3222                     goto get_done;
   3223                 }
   3224                 BCM_VLAN_VEC_SET(vlan_vec, l3_intf.l3a_vid);
   3225                 vlan_count++;
   3226             }
   3227         }
   3228         if (vlan_count >= IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) {
   3229             break;
   3230         }
   3231     }
   3232 
   3233  get_done:
   3234     if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) {
   3235         rvth = _bcm_fb_ipmc_repl_thaw(unit);
   3236         rv = (rv < 0) ? rv : rvth;
   3237     }
   3238     IPMC_REPL_UNLOCK(unit);
   3239     return rv;
   3240 }
   3241 
   3242 STATIC int
   3243 _fb_ipmc_repl_next_free_ptr(int unit)
   3244 {
   3245     int                 ix, bit;
   3246     SHR_BITDCL          not_ptrs;
   3247 
   3248     for (ix = 0; ix < _SHR_BITDCLSIZE(IPMC_REPL_TOTAL(unit)); ix++) {
   3249         not_ptrs = ~_fb_repl_info[unit]->bitmap_entries_used[ix];
   3250         if (not_ptrs) {
   3251             for (bit = 0; bit < SHR_BITWID; bit++) {
   3252                 if (not_ptrs & (1 << bit)) {
   3253                     return (ix * SHR_BITWID) + bit;
   3254                 }
   3255             }
   3256         }
   3257     }
   3258 
   3259     return -1;
   3260 }
   3261 
   3262 /*
   3263  * Function:
   3264  *      bcm_fb_ipmc_repl_add
   3265  * Purpose:
   3266  *      Add VLAN to selected ports' replication list for chosen
   3267  *      IPMC group.
   3268  *Parameters:
   3269  *      unit     - StrataSwitch PCI device unit number.
   3270  *      ipmc_id  - The index number.
   3271  *      port     - port to add.
   3272  *      vlan     - VLAN to replicate.
   3273  * Returns:
   3274  *      BCM_E_XXX
   3275  */
   3276 
   3277 int
   3278 bcm_fb_ipmc_repl_add(int unit, int ipmc_id, bcm_port_t port,
   3279                      bcm_vlan_t vlan)
   3280 {
   3281     int                 rv = BCM_E_NONE;
   3282     uint32              ls_bits[2];
   3283     mmu_ipmc_vlan_tbl_entry_t vlan_entry;
   3284     int                 ms_bit, target_ms_bit, ls_bit;
   3285     int                 vlan_ptr, last_vlan_ptr;
   3286     pbmp_t pbmp, ubmp;
   3287     bcm_l3_intf_t l3_intf;
   3288     uint32              vlan_count;
   3289     int                 rvth = BCM_E_NONE;
   3290 
   3291     IPMC_REPL_INIT(unit);
   3292     IPMC_REPL_ID(unit, ipmc_id);
   3293     REPL_PORT_CHECK(unit, port);
   3294 
   3295     /* Check if port belongs to this VLAN */
   3296     BCM_IF_ERROR_RETURN
   3297         (bcm_esw_vlan_port_get(unit, vlan, &pbmp, &ubmp));
   3298     if (!SOC_PBMP_MEMBER(pbmp, port)) {
   3299         return BCM_E_PARAM;
   3300     }
   3301 
   3302     bcm_l3_intf_t_init(&l3_intf);
   3303     l3_intf.l3a_vid = vlan;
   3304     if (bcm_esw_l3_intf_find_vlan(unit, &l3_intf) < 0) {
   3305         return BCM_E_PARAM;
   3306     }
   3307 
   3308     if (SOC_IPMCREPLSHR_GET(unit) ||
   3309             soc_feature(unit, soc_feature_ipmc_repl_penultimate)) {
   3310         int alloc_size, intf_max, if_count, rv = BCM_E_NONE;
   3311         bcm_if_t *if_array = NULL;
   3312         
   3313         intf_max = IPMC_REPL_INTF_TOTAL(unit);
   3314         alloc_size = intf_max * sizeof(bcm_if_t);
   3315         if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   3316         if (if_array == NULL) {
   3317             return BCM_E_MEMORY;
   3318         }
   3319 
   3320         IPMC_REPL_LOCK(unit);
   3321         rv = bcm_fb_ipmc_egress_intf_get(unit, ipmc_id, port, intf_max,
   3322                                          if_array, &if_count);
   3323         if (BCM_SUCCESS(rv)) {
   3324             if (if_count < intf_max) {
   3325                 if_array[if_count++] = l3_intf.l3a_intf_id;
   3326                 rv = bcm_fb_ipmc_egress_intf_set(unit, ipmc_id, port,
   3327                                                  if_count, if_array, 1, FALSE);
   3328             } else {
   3329                 rv = BCM_E_EXISTS;
   3330             }
   3331         }
   3332 
   3333         IPMC_REPL_UNLOCK(unit);
   3334         sal_free(if_array);
   3335         return rv;
   3336     }
   3337 
   3338     IPMC_REPL_LOCK(unit);
   3339     if (soc_feature(unit, soc_feature_ipmc_repl_freeze) && 
   3340         ((rv = _bcm_fb_ipmc_repl_freeze(unit)) < 0)) {
   3341         IPMC_REPL_UNLOCK(unit);
   3342         return rv;
   3343     }
   3344 
   3345     if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, port, &vlan_ptr, 0, 0)) < 0) {
   3346         goto add_done;
   3347     }
   3348 
   3349     target_ms_bit = (l3_intf.l3a_intf_id >> 6) & 0x3f;
   3350     ls_bit = l3_intf.l3a_intf_id & 0x3f;
   3351 
   3352     last_vlan_ptr = -1;
   3353     vlan_count = 0;
   3354     ms_bit = -1;
   3355 
   3356     if (IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) {
   3357         /*
   3358          * Add to existing chain
   3359          */
   3360         while (vlan_ptr != last_vlan_ptr) {
   3361             if ((rv = READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL,
   3362                                               vlan_ptr, &vlan_entry)) < 0) {
   3363                 goto add_done;
   3364             }
   3365 
   3366             ms_bit = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   3367                                        &vlan_entry, MSB_VLANf);
   3368 
   3369             if (ms_bit == target_ms_bit) {
   3370                 /* Add to existing entry */
   3371                 break;
   3372             }
   3373 
   3374             last_vlan_ptr = vlan_ptr;
   3375             vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   3376                                               &vlan_entry, NEXTPTRf);
   3377 
   3378             soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry,
   3379                                              LSB_VLAN_BMf, ls_bits);
   3380             vlan_count +=
   3381                 _shr_popcount(ls_bits[0]) + _shr_popcount(ls_bits[1]);
   3382             if (vlan_count >= IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) {
   3383                 break;
   3384             }
   3385         }
   3386     }
   3387 
   3388     if (ms_bit != target_ms_bit) {
   3389         /* New entry, find slot */
   3390         vlan_ptr = _fb_ipmc_repl_next_free_ptr(unit);
   3391         if (vlan_ptr < 0) {
   3392             /* Out of LS entries */
   3393             rv = BCM_E_RESOURCE;
   3394             goto add_done;
   3395         }
   3396 
   3397         if (last_vlan_ptr < 0) {
   3398             /* Update group table */
   3399             if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id,
   3400                                           port, &vlan_ptr, 0, 1)) < 0) {
   3401                 goto add_done;
   3402             }
   3403         } else {
   3404             /* Update last entry */
   3405             soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry,
   3406                                                NEXTPTRf, vlan_ptr);
   3407             if ((rv = WRITE_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL,
   3408                                           last_vlan_ptr, &vlan_entry)) < 0) {
   3409                 goto add_done;
   3410             }
   3411         }
   3412 
   3413         sal_memset(&vlan_entry, 0, sizeof(vlan_entry));
   3414         soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry,
   3415                                            MSB_VLANf, target_ms_bit);
   3416         /* Point to self */
   3417         soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry,
   3418                                            NEXTPTRf, vlan_ptr);
   3419 
   3420         IPMC_REPL_VE_USED_SET(unit, vlan_ptr);
   3421     }
   3422 
   3423     /* Insert replacement */
   3424     soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry,
   3425                                      LSB_VLAN_BMf, ls_bits);
   3426     if (ls_bits[ls_bit / 32] & (1 << (ls_bit % 32))) {
   3427         /* Already exists! */
   3428         rv = BCM_E_EXISTS;
   3429         goto add_done;
   3430     }
   3431     ls_bits[ls_bit / 32] |= 1 << (ls_bit % 32);
   3432     soc_MMU_IPMC_VLAN_TBLm_field_set(unit, &vlan_entry,
   3433                                      LSB_VLAN_BMf, ls_bits);
   3434 
   3435 
   3436     if ((rv = WRITE_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL,
   3437                                        vlan_ptr, &vlan_entry)) < 0) {
   3438         goto add_done;
   3439     }
   3440 
   3441     IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)++;
   3442 
   3443  add_done:
   3444     if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) {
   3445         rvth = _bcm_fb_ipmc_repl_thaw(unit);
   3446         rv = (rv < 0) ? rv : rvth;
   3447     }
   3448     IPMC_REPL_UNLOCK(unit);
   3449     return rv;
   3450 }
   3451 
   3452 /*
   3453  * Function:
   3454  *      bcm_fb_ipmc_repl_delete
   3455  * Purpose:
   3456  *      Remove VLAN from selected ports' replication list for chosen
   3457  *      IPMC group.
   3458  * Parameters:
   3459  *      unit     - StrataSwitch PCI device unit number.
   3460  *      ipmc_id  - The index number.
   3461  *      port     - port to remove.
   3462  *      vlan     - VLAN to delete from replication.
   3463  * Returns:
   3464  *      BCM_E_XXX
   3465  */
   3466 
   3467 int
   3468 bcm_fb_ipmc_repl_delete(int unit, int ipmc_id, bcm_port_t port,
   3469                         bcm_vlan_t vlan)
   3470 {
   3471     int                 rv = BCM_E_NONE;
   3472     uint32              ls_bits[2];
   3473     mmu_ipmc_vlan_tbl_entry_t vlan_entry, prev_vlan_entry;
   3474     int                 ms_bit, target_ms_bit, ls_bit;
   3475     int                 vlan_ptr, last_vlan_ptr, next_vlan_ptr;
   3476     bcm_l3_intf_t       l3_intf;
   3477     uint32              vlan_count;
   3478     int                 rvth = BCM_E_NONE;
   3479 
   3480     IPMC_REPL_INIT(unit);
   3481     IPMC_REPL_ID(unit, ipmc_id);
   3482     REPL_PORT_CHECK(unit, port);
   3483 
   3484     if (!IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) {
   3485         return BCM_E_NOT_FOUND;
   3486     }
   3487 
   3488     bcm_l3_intf_t_init(&l3_intf);
   3489     l3_intf.l3a_vid = vlan;
   3490     if (bcm_esw_l3_intf_find_vlan(unit, &l3_intf) < 0) {
   3491         return BCM_E_PARAM;
   3492     }
   3493 
   3494     if (SOC_IPMCREPLSHR_GET(unit) ||
   3495             soc_feature(unit, soc_feature_ipmc_repl_penultimate)) {
   3496         int alloc_size, intf_max, if_count, if_cur, match, rv = BCM_E_NONE;
   3497         bcm_if_t *if_array = NULL;
   3498         
   3499         intf_max = IPMC_REPL_INTF_TOTAL(unit);
   3500         alloc_size = intf_max * sizeof(bcm_if_t);
   3501         if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   3502         if (if_array == NULL) {
   3503             return BCM_E_MEMORY;
   3504         }
   3505 
   3506         IPMC_REPL_LOCK(unit);
   3507         rv = bcm_fb_ipmc_egress_intf_get(unit, ipmc_id, port, intf_max,
   3508                                          if_array, &if_count);
   3509         if (BCM_SUCCESS(rv)) {
   3510             match = FALSE;
   3511             for (if_cur = 0; if_cur < if_count; if_cur++) {
   3512                 if (match) {
   3513                     if_array[if_cur - 1] = if_array[if_cur];
   3514                 } else {
   3515                     if (if_array[if_cur] == l3_intf.l3a_intf_id) {
   3516                         match = TRUE;
   3517                     }
   3518                 }
   3519             }
   3520             if (match) {
   3521                 if_count--;
   3522                 rv = bcm_fb_ipmc_egress_intf_set(unit, ipmc_id, port,
   3523                                                  if_count, if_array, 1, FALSE);
   3524             } else {
   3525                 rv = BCM_E_NOT_FOUND;
   3526             }
   3527         }
   3528         IPMC_REPL_UNLOCK(unit);
   3529         sal_free(if_array);
   3530         return rv;
   3531     }
   3532 
   3533     IPMC_REPL_LOCK(unit);
   3534     if (soc_feature(unit, soc_feature_ipmc_repl_freeze) && 
   3535         ((rv = _bcm_fb_ipmc_repl_freeze(unit)) < 0)) {
   3536         IPMC_REPL_UNLOCK(unit);
   3537         return rv;
   3538     }
   3539 
   3540     if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, port, &vlan_ptr, 0, 0)) < 0) {
   3541         goto del_done;
   3542     }
   3543 
   3544     target_ms_bit = (l3_intf.l3a_intf_id >> 6) & 0x3f;
   3545     ls_bit = l3_intf.l3a_intf_id & 0x3f;
   3546 
   3547     last_vlan_ptr = 0; /* Since ptr 0 should never be used! */
   3548     vlan_count = 0;
   3549     ms_bit = -1;
   3550 
   3551     while (vlan_ptr != last_vlan_ptr) {
   3552         if ((rv = READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL,
   3553                                           vlan_ptr, &vlan_entry)) < 0) {
   3554             goto del_done;
   3555         }
   3556 
   3557         ms_bit = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   3558                                         &vlan_entry, MSB_VLANf);
   3559         if (ms_bit == target_ms_bit) {
   3560             /* Delete existing entry */
   3561             soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry,
   3562                                              LSB_VLAN_BMf, ls_bits);
   3563             if (!(ls_bits[ls_bit / 32] & (1 << (ls_bit % 32)))) {
   3564                 /* Doesn't exist! */
   3565                 rv = BCM_E_NOT_FOUND;
   3566                 goto del_done;
   3567             }
   3568             ls_bits[ls_bit / 32] &= ~(1 << (ls_bit % 32));
   3569             soc_MMU_IPMC_VLAN_TBLm_field_set(unit, &vlan_entry,
   3570                                              LSB_VLAN_BMf, ls_bits);
   3571 
   3572             if ((ls_bits[0] == 0) && (ls_bits[1] == 0)) {
   3573                 /* Wiped out the entry */
   3574                 /* Record before overwrite */
   3575                 next_vlan_ptr =
   3576                     soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   3577                                            &vlan_entry, NEXTPTRf);
   3578                 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit,
   3579                                             &vlan_entry, MSB_VLANf, 0);
   3580                 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit,
   3581                                             &vlan_entry, NEXTPTRf, 0);
   3582                 if (last_vlan_ptr == 0) {
   3583                     /* First entry for this (group, port) */
   3584                     if (vlan_ptr == next_vlan_ptr) {
   3585                         /* Only link in chain */
   3586                         next_vlan_ptr = 0;
   3587                     }
   3588                     if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id,
   3589                                        port, &next_vlan_ptr, 0, 1)) < 0) {
   3590                        goto del_done;
   3591                     }
   3592                 } else {
   3593                     /* Link over with last entry */
   3594                     if (vlan_ptr == next_vlan_ptr) {
   3595                         /* If this is end of chain, end on previous link */
   3596                         next_vlan_ptr = last_vlan_ptr;
   3597                     }
   3598                     soc_MMU_IPMC_VLAN_TBLm_field32_set(unit,
   3599                             &prev_vlan_entry, NEXTPTRf, next_vlan_ptr);
   3600                     if ((rv = WRITE_MMU_IPMC_VLAN_TBLm(unit,
   3601                                     MEM_BLOCK_ALL, last_vlan_ptr,
   3602                                     &prev_vlan_entry)) < 0) {
   3603                         goto del_done;
   3604                     }
   3605                 }
   3606 
   3607                 IPMC_REPL_VE_USED_CLR(unit, vlan_ptr);
   3608             }
   3609 
   3610             if ((rv = WRITE_MMU_IPMC_VLAN_TBLm(unit,
   3611                                 MEM_BLOCK_ALL, vlan_ptr, &vlan_entry)) < 0) {
   3612                 goto del_done;
   3613             }
   3614 
   3615             IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)--;
   3616 
   3617             goto del_done;
   3618         }
   3619 
   3620         last_vlan_ptr = vlan_ptr;
   3621         vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   3622                                           &vlan_entry, NEXTPTRf);
   3623         sal_memcpy(&prev_vlan_entry, &vlan_entry,
   3624                    sizeof(mmu_ipmc_vlan_tbl_entry_t));
   3625 
   3626         soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry,
   3627                                                LSB_VLAN_BMf, ls_bits);
   3628         vlan_count +=
   3629             _shr_popcount(ls_bits[0]) + _shr_popcount(ls_bits[1]);
   3630         if (vlan_count >= IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) {
   3631             rv = BCM_E_NOT_FOUND;
   3632             goto del_done;
   3633         }
   3634     }
   3635 
   3636     rv = BCM_E_NOT_FOUND;
   3637 
   3638  del_done:
   3639     if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) {
   3640         rvth = _bcm_fb_ipmc_repl_thaw(unit);
   3641         rv = (rv < 0) ? rv : rvth;
   3642     }
   3643     IPMC_REPL_UNLOCK(unit);
   3644     return rv;
   3645 }
   3646 
   3647 /*
   3648  * Function:
   3649  *      bcm_fb_ipmc_repl_delete_all
   3650  * Purpose:
   3651  *      Remove all VLANs from selected ports' replication list for chosen
   3652  *      IPMC group.
   3653  * Parameters:
   3654  *      unit     - StrataSwitch PCI device unit number.
   3655  *      ipmc_id  - The MC index number.
   3656  *      port     - port from which to remove VLANs.
   3657  * Returns:
   3658  *      BCM_E_XXX
   3659  */
   3660 
   3661 int
   3662 bcm_fb_ipmc_repl_delete_all(int unit, int ipmc_id, bcm_port_t port)
   3663 {
   3664     int                 rv = BCM_E_NONE;
   3665     uint32              ls_bits[2];
   3666     mmu_ipmc_vlan_tbl_entry_t vlan_entry;
   3667     int                 vlan_ptr, last_vlan_ptr;
   3668     int                 rvth = BCM_E_NONE;
   3669     int                 num_vlans;
   3670 
   3671     IPMC_REPL_INIT(unit);
   3672     IPMC_REPL_ID(unit, ipmc_id);
   3673     REPL_PORT_CHECK(unit, port);
   3674 
   3675     if (!IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) {
   3676         /* Nothing to do */
   3677         return BCM_E_NONE;
   3678     }
   3679 
   3680     if (SOC_IPMCREPLSHR_GET(unit) ||
   3681             soc_feature(unit, soc_feature_ipmc_repl_penultimate)) {
   3682         return bcm_fb_ipmc_egress_intf_set(unit, ipmc_id, port, 0, NULL, 1, FALSE);
   3683     }
   3684 
   3685     IPMC_REPL_LOCK(unit);
   3686     if (soc_feature(unit, soc_feature_ipmc_repl_freeze) && 
   3687         ((rv = _bcm_fb_ipmc_repl_freeze(unit)) < 0)) {
   3688         IPMC_REPL_UNLOCK(unit);
   3689         return rv;
   3690     }
   3691 
   3692     if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id,
   3693                                   port, &vlan_ptr, 0, 0)) < 0) {
   3694         goto del_all_done;
   3695     }
   3696     last_vlan_ptr = 0;
   3697     if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id,
   3698                                   port, &last_vlan_ptr, 0, 1)) < 0) {
   3699         goto del_all_done;
   3700     }
   3701 
   3702     while (vlan_ptr != last_vlan_ptr) {
   3703         if ((rv = READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL,
   3704                                           vlan_ptr, &vlan_entry)) < 0) {
   3705             goto del_all_done;
   3706         }
   3707 
   3708         if ((rv = WRITE_MMU_IPMC_VLAN_TBLm(unit,
   3709                         MEM_BLOCK_ALL, vlan_ptr, soc_mem_entry_null(unit,
   3710                             MMU_IPMC_VLAN_TBLm))) < 0) {
   3711             goto del_all_done;
   3712         }
   3713 
   3714         IPMC_REPL_VE_USED_CLR(unit, vlan_ptr);
   3715 
   3716         last_vlan_ptr = vlan_ptr;
   3717         vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   3718                                                &vlan_entry, NEXTPTRf);
   3719 
   3720         soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry,
   3721                                                LSB_VLAN_BMf, ls_bits);
   3722         num_vlans = _shr_popcount(ls_bits[0]) + _shr_popcount(ls_bits[1]);
   3723         if (IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id) < num_vlans) {
   3724             IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id) = 0;
   3725             goto del_all_done;
   3726         }
   3727         IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id) -= num_vlans;
   3728     }
   3729 
   3730  del_all_done:
   3731     if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) {
   3732         rvth = _bcm_fb_ipmc_repl_thaw(unit);
   3733         rv = (rv < 0) ? rv : rvth;
   3734     }
   3735     IPMC_REPL_UNLOCK(unit);
   3736     return rv;
   3737 }
   3738 
   3739 /*
   3740  * Function:
   3741  *      bcm_fb_ipmc_egress_intf_add
   3742  * Purpose:
   3743  *      Add L3 interface to selected ports' replication list for chosen
   3744  *      IPMC group.
   3745  * Parameters:
   3746  *      unit     - StrataSwitch PCI device unit number.
   3747  *      ipmc_id  - The index number.
   3748  *      port     - port to add.
   3749  *      l3_intf  - L3 interface to replicate.
   3750  * Returns:
   3751  *      BCM_E_XXX
   3752  */
   3753 int
   3754 bcm_fb_ipmc_egress_intf_add(int unit, int ipmc_id, bcm_port_t port,
   3755                             bcm_l3_intf_t *l3_intf)
   3756 {
   3757     int                 rv = BCM_E_NONE;
   3758     uint32              ls_bits[2];
   3759     mmu_ipmc_vlan_tbl_entry_t vlan_entry;
   3760     int                 ms_bit, target_ms_bit, ls_bit;
   3761     int                 vlan_ptr, last_vlan_ptr;
   3762     pbmp_t pbmp, ubmp;
   3763     uint32              vlan_count;
   3764     int                 rvth = BCM_E_NONE;
   3765 
   3766     IPMC_REPL_INIT(unit);
   3767     IPMC_REPL_ID(unit, ipmc_id);
   3768     REPL_PORT_CHECK(unit, port);
   3769 
   3770     /* Check if port belongs to this VLAN */
   3771     BCM_IF_ERROR_RETURN
   3772         (bcm_esw_vlan_port_get(unit, l3_intf->l3a_vid, &pbmp, &ubmp));
   3773     if (!SOC_PBMP_MEMBER(pbmp, port)) {
   3774         return BCM_E_PARAM;
   3775     }
   3776 
   3777     if (SOC_IPMCREPLSHR_GET(unit) ||
   3778             soc_feature(unit, soc_feature_ipmc_repl_penultimate)) {
   3779         bcm_if_t *if_array = NULL;
   3780         int  intf_num, intf_max, alloc_size, rv = BCM_E_NONE;
   3781 
   3782         intf_max = IPMC_REPL_INTF_TOTAL(unit);
   3783         alloc_size = intf_max * sizeof(bcm_if_t);
   3784         if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   3785         if (if_array == NULL) {
   3786             return BCM_E_MEMORY;
   3787         }
   3788 
   3789         IPMC_REPL_LOCK(unit);
   3790         rv = bcm_fb_ipmc_egress_intf_get(unit, ipmc_id, port, intf_max,
   3791                                          if_array, &intf_num);
   3792         if (BCM_SUCCESS(rv)) {
   3793             if (intf_num < intf_max) {
   3794                 if_array[intf_num++] = l3_intf->l3a_intf_id;
   3795                 rv = bcm_fb_ipmc_egress_intf_set(unit, ipmc_id, port,
   3796                                                  intf_num, if_array, 1, FALSE);
   3797             } else {
   3798                 rv = BCM_E_EXISTS;
   3799             }
   3800         }
   3801 
   3802         IPMC_REPL_UNLOCK(unit);
   3803         sal_free(if_array);
   3804         return rv;
   3805     }
   3806 
   3807     IPMC_REPL_LOCK(unit);
   3808     if (soc_feature(unit, soc_feature_ipmc_repl_freeze) && 
   3809         ((rv = _bcm_fb_ipmc_repl_freeze(unit)) < 0)) {
   3810         IPMC_REPL_UNLOCK(unit);
   3811         return rv;
   3812     }
   3813 
   3814     if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, port, &vlan_ptr, 0, 0)) < 0) {
   3815         goto add_done;
   3816     }
   3817 
   3818     target_ms_bit = (l3_intf->l3a_intf_id >> 6) & 0x3f;
   3819     ls_bit = l3_intf->l3a_intf_id & 0x3f;
   3820 
   3821     last_vlan_ptr = -1;
   3822     vlan_count = 0;
   3823     ms_bit = -1;
   3824 
   3825     if (IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) {
   3826         /*
   3827          * Add to existing chain
   3828          */
   3829         while (vlan_ptr != last_vlan_ptr) {
   3830             if ((rv = READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL,
   3831                                               vlan_ptr, &vlan_entry)) < 0) {
   3832                 goto add_done;
   3833             }
   3834 
   3835             ms_bit = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   3836                                        &vlan_entry, MSB_VLANf);
   3837 
   3838             if (ms_bit == target_ms_bit) {
   3839                 /* Add to existing entry */
   3840                 break;
   3841             }
   3842 
   3843             last_vlan_ptr = vlan_ptr;
   3844             vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   3845                                               &vlan_entry, NEXTPTRf);
   3846 
   3847             soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry,
   3848                                              LSB_VLAN_BMf, ls_bits);
   3849             vlan_count +=
   3850                 _shr_popcount(ls_bits[0]) + _shr_popcount(ls_bits[1]);
   3851             if (vlan_count >= IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) {
   3852                 break;
   3853             }
   3854         }
   3855     }
   3856 
   3857     if (ms_bit != target_ms_bit) {
   3858         /* New entry, find slot */
   3859         vlan_ptr = _fb_ipmc_repl_next_free_ptr(unit);
   3860         if (vlan_ptr < 0) {
   3861             /* Out of LS entries */
   3862             rv = BCM_E_RESOURCE;
   3863             goto add_done;
   3864         }
   3865 
   3866         if (last_vlan_ptr < 0) {
   3867             /* Update group table */
   3868             if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id,
   3869                                           port, &vlan_ptr, 0, 1)) < 0) {
   3870                 goto add_done;
   3871             }
   3872         } else {
   3873             /* Update last entry */
   3874             soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry,
   3875                                                NEXTPTRf, vlan_ptr);
   3876             if ((rv = WRITE_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL,
   3877                                           last_vlan_ptr, &vlan_entry)) < 0) {
   3878                 goto add_done;
   3879             }
   3880         }
   3881 
   3882         sal_memset(&vlan_entry, 0, sizeof(vlan_entry));
   3883         soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry,
   3884                                            MSB_VLANf, target_ms_bit);
   3885         /* Point to self */
   3886         soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry,
   3887                                            NEXTPTRf, vlan_ptr);
   3888 
   3889         IPMC_REPL_VE_USED_SET(unit, vlan_ptr);
   3890     }
   3891 
   3892     /* Insert replacement */
   3893     soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry,
   3894                                      LSB_VLAN_BMf, ls_bits);
   3895     if (ls_bits[ls_bit / 32] & (1 << (ls_bit % 32))) {
   3896         /* Already exists! */
   3897         rv = BCM_E_EXISTS;
   3898         goto add_done;
   3899     }
   3900     ls_bits[ls_bit / 32] |= 1 << (ls_bit % 32);
   3901     soc_MMU_IPMC_VLAN_TBLm_field_set(unit, &vlan_entry,
   3902                                      LSB_VLAN_BMf, ls_bits);
   3903 
   3904 
   3905     if ((rv = WRITE_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL,
   3906                                        vlan_ptr, &vlan_entry)) < 0) {
   3907         goto add_done;
   3908     }
   3909 
   3910     IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)++;
   3911 
   3912  add_done:
   3913     if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) {
   3914         rvth = _bcm_fb_ipmc_repl_thaw(unit);
   3915         rv = (rv < 0) ? rv : rvth;
   3916     }
   3917     IPMC_REPL_UNLOCK(unit);
   3918     return rv;
   3919 }
   3920 
   3921 /*
   3922  * Function:
   3923  *      bcm_fb_ipmc_egress_intf_delete
   3924  * Purpose:
   3925  *      Remove L3 interface from selected ports' replication list for chosen
   3926  *      IPMC group.
   3927  * Parameters:
   3928  *      unit     - StrataSwitch PCI device unit number.
   3929  *      ipmc_id  - The index number.
   3930  *      port     - port to remove.
   3931  *      l3_intf  - L3 interface to delete from replication.
   3932  * Returns:
   3933  *      BCM_E_XXX
   3934  */
   3935 int
   3936 bcm_fb_ipmc_egress_intf_delete(int unit, int ipmc_id, bcm_port_t port,
   3937                                bcm_l3_intf_t *l3_intf)
   3938 {
   3939     int                 rv = BCM_E_NONE;
   3940     uint32              ls_bits[2];
   3941     mmu_ipmc_vlan_tbl_entry_t vlan_entry, prev_vlan_entry;
   3942     int                 ms_bit, target_ms_bit, ls_bit;
   3943     int                 vlan_ptr, last_vlan_ptr, next_vlan_ptr;
   3944     uint32              vlan_count;
   3945     int                 rvth = BCM_E_NONE;
   3946 
   3947     IPMC_REPL_INIT(unit);
   3948     IPMC_REPL_ID(unit, ipmc_id);
   3949     REPL_PORT_CHECK(unit, port);
   3950 
   3951     if (!IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) {
   3952         return BCM_E_NOT_FOUND;
   3953     }
   3954 
   3955     if (SOC_IPMCREPLSHR_GET(unit) ||
   3956             soc_feature(unit, soc_feature_ipmc_repl_penultimate)) {
   3957         bcm_if_t *if_array = NULL;
   3958         int alloc_size, intf_max, if_count, if_cur, match, rv = BCM_E_NONE;
   3959 
   3960         intf_max = IPMC_REPL_INTF_TOTAL(unit);
   3961         alloc_size = intf_max * sizeof(bcm_if_t);
   3962         if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   3963         if (if_array == NULL) {
   3964             return BCM_E_MEMORY;
   3965         }
   3966 
   3967         IPMC_REPL_LOCK(unit);
   3968         rv = bcm_fb_ipmc_egress_intf_get(unit, ipmc_id, port, intf_max,
   3969                                          if_array, &if_count);
   3970         if (BCM_SUCCESS(rv)) {
   3971             match = FALSE;
   3972             for (if_cur = 0; if_cur < if_count; if_cur++) {
   3973                 if (match) {
   3974                     if_array[if_cur - 1] = if_array[if_cur];
   3975                 } else {
   3976                     if (if_array[if_cur] == l3_intf->l3a_intf_id) {
   3977                         match = TRUE;
   3978                     }
   3979                 }
   3980             }
   3981             if (match) {
   3982                 if_count--;
   3983                 rv = bcm_fb_ipmc_egress_intf_set(unit, ipmc_id, port,
   3984                                                  if_count, if_array, 1, FALSE);
   3985             } else {
   3986                 rv = BCM_E_NOT_FOUND;
   3987             }
   3988         }
   3989 
   3990         IPMC_REPL_UNLOCK(unit);
   3991         sal_free(if_array);
   3992         return rv;
   3993     }
   3994 
   3995     IPMC_REPL_LOCK(unit);
   3996     if (soc_feature(unit, soc_feature_ipmc_repl_freeze) && 
   3997         ((rv = _bcm_fb_ipmc_repl_freeze(unit)) < 0)) {
   3998         IPMC_REPL_UNLOCK(unit);
   3999         return rv;
   4000     }
   4001 
   4002     if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, port, &vlan_ptr, 0, 0)) < 0) {
   4003         goto del_done;
   4004     }
   4005 
   4006     target_ms_bit = (l3_intf->l3a_intf_id >> 6) & 0x3f;
   4007     ls_bit = l3_intf->l3a_intf_id & 0x3f;
   4008 
   4009     last_vlan_ptr = 0; /* Since ptr 0 should never be used! */
   4010     vlan_count = 0;
   4011     ms_bit = -1;
   4012 
   4013     while (vlan_ptr != last_vlan_ptr) {
   4014         if ((rv = READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL,
   4015                                           vlan_ptr, &vlan_entry)) < 0) {
   4016             goto del_done;
   4017         }
   4018 
   4019         ms_bit = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   4020                                         &vlan_entry, MSB_VLANf);
   4021         if (ms_bit == target_ms_bit) {
   4022             /* Delete existing entry */
   4023             soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry,
   4024                                              LSB_VLAN_BMf, ls_bits);
   4025             if (!(ls_bits[ls_bit / 32] & (1 << (ls_bit % 32)))) {
   4026                 /* Doesn't exist! */
   4027                 rv = BCM_E_NOT_FOUND;
   4028                 goto del_done;
   4029             }
   4030             ls_bits[ls_bit / 32] &= ~(1 << (ls_bit % 32));
   4031             soc_MMU_IPMC_VLAN_TBLm_field_set(unit, &vlan_entry,
   4032                                              LSB_VLAN_BMf, ls_bits);
   4033 
   4034             if ((ls_bits[0] == 0) && (ls_bits[1] == 0)) {
   4035                 /* Wiped out the entry */
   4036                 /* Record before overwrite */
   4037                 next_vlan_ptr =
   4038                     soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   4039                                            &vlan_entry, NEXTPTRf);
   4040                 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit,
   4041                                             &vlan_entry, MSB_VLANf, 0);
   4042                 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit,
   4043                                             &vlan_entry, NEXTPTRf, 0);
   4044                 if (last_vlan_ptr == 0) {
   4045                     /* First entry for this (group, port) */
   4046                     if (vlan_ptr == next_vlan_ptr) {
   4047                         /* Only link in chain */
   4048                         next_vlan_ptr = 0;
   4049                     }
   4050                     if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, port,
   4051                                                 &next_vlan_ptr, 0, 1)) < 0) {
   4052                        goto del_done;
   4053                     }
   4054                 } else {
   4055                     /* Link over with last entry */
   4056                     if (vlan_ptr == next_vlan_ptr) {
   4057                         /* If this is end of chain, end on previous link */
   4058                         next_vlan_ptr = last_vlan_ptr;
   4059                     }
   4060                     soc_MMU_IPMC_VLAN_TBLm_field32_set(unit,
   4061                             &prev_vlan_entry, NEXTPTRf, next_vlan_ptr);
   4062                     if ((rv = WRITE_MMU_IPMC_VLAN_TBLm(unit,
   4063                                     MEM_BLOCK_ALL, last_vlan_ptr,
   4064                                     &prev_vlan_entry)) < 0) {
   4065                         goto del_done;
   4066                     }
   4067                 }
   4068 
   4069                 IPMC_REPL_VE_USED_CLR(unit, vlan_ptr);
   4070             }
   4071 
   4072             if ((rv = WRITE_MMU_IPMC_VLAN_TBLm(unit,
   4073                                 MEM_BLOCK_ALL, vlan_ptr, &vlan_entry)) < 0) {
   4074                 goto del_done;
   4075             }
   4076 
   4077             IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)--;
   4078 
   4079             goto del_done;
   4080         }
   4081 
   4082         last_vlan_ptr = vlan_ptr;
   4083         vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   4084                                           &vlan_entry, NEXTPTRf);
   4085         sal_memcpy(&prev_vlan_entry, &vlan_entry,
   4086                    sizeof(mmu_ipmc_vlan_tbl_entry_t));
   4087 
   4088         soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry,
   4089                                                LSB_VLAN_BMf, ls_bits);
   4090         vlan_count +=
   4091             _shr_popcount(ls_bits[0]) + _shr_popcount(ls_bits[1]);
   4092         if (vlan_count >= IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) {
   4093             rv = BCM_E_NOT_FOUND;
   4094             goto del_done;
   4095         }
   4096     }
   4097 
   4098     rv = BCM_E_NOT_FOUND;
   4099 
   4100 del_done:
   4101     if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) {
   4102         rvth = _bcm_fb_ipmc_repl_thaw(unit);
   4103         rv = (rv < 0) ? rv : rvth;
   4104     }
   4105     IPMC_REPL_UNLOCK(unit);
   4106     return rv;
   4107 }
   4108 
   4109 
   4110 int
   4111 _bcm_fb_ipmc_egress_intf_add(int unit, int ipmc_id, bcm_port_t port,
   4112                              int id, int is_l3)
   4113 {
   4114     int *if_array = NULL;
   4115     int intf_num, intf_max, alloc_size, rv = BCM_E_NONE;
   4116     bcm_l3_intf_t       l3_intf;
   4117     int         is_l3_intf = 0, int_l3_nh_created = -1;
   4118     int         intf_index = 0, nh_index = 0;
   4119     uint32      nh_flags;
   4120     bcm_l3_egress_t         nh_info;
   4121     egr_l3_next_hop_entry_t egr_nh;
   4122 
   4123     if (!SOC_IPMCREPLSHR_GET(unit) && !SOC_IS_TRX(unit) &&
   4124         !soc_feature(unit, soc_feature_ipmc_repl_penultimate)) {
   4125         return BCM_E_UNAVAIL;
   4126     }
   4127 
   4128     IPMC_REPL_INIT(unit);
   4129     IPMC_REPL_ID(unit, ipmc_id);
   4130     REPL_PORT_CHECK(unit, port);
   4131 
   4132     intf_max = IPMC_REPL_INTF_TOTAL(unit);
   4133     alloc_size = intf_max * sizeof(int);
   4134     if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   4135     if (if_array == NULL) {
   4136         return BCM_E_MEMORY;
   4137     }
   4138 
   4139     IPMC_REPL_LOCK(unit);
   4140     rv = bcm_fb_ipmc_egress_intf_get(unit, ipmc_id, port, intf_max,
   4141                                      if_array, &intf_num);
   4142     if (BCM_SUCCESS(rv)) {
   4143         if (intf_num < intf_max) {
   4144             if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) {
   4145                 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, id)) {
   4146                     id = id - BCM_XGS3_EGRESS_IDX_MIN(unit);
   4147                 } else {
   4148                     /*
   4149                      *  SDK-111244: to request L3 INTF index format for
   4150                      * adding L3MC replication as well.
   4151                      *
   4152                      * Due to the L3_INTF can be shared by L3_NH, once user
   4153                      *  request IPMC replication through L3_INTF index, an
   4154                      *  internal L3_NH entry will always created internally
   4155                      *  for such request.
   4156                      */
   4157                     is_l3_intf = TRUE;
   4158                     intf_index = id;
   4159 
   4160                     /* index validation */
   4161                     if (intf_index >= BCM_XGS3_L3_IF_TBL_SIZE(unit)) {
   4162                         rv = BCM_E_PARAM;
   4163                         goto intf_add_done;
   4164                     } else if (!BCM_L3_INTF_USED_GET(unit, intf_index)) {
   4165                         rv = BCM_E_NOT_FOUND;
   4166                         goto intf_add_done;
   4167                     }
   4168 
   4169                     if (IPMC_REPL_L3_INTF_TO_L3_NH_IPMC(unit, intf_index) !=
   4170                             REPL_NH_INDEX_UNALLOCATED) {
   4171                         id = IPMC_REPL_L3_INTF_TO_L3_NH_IPMC(unit, intf_index);
   4172                         _bcm_xgs3_nh_ref_cnt_incr(unit, id);
   4173                     } else {
   4174                         bcm_l3_egress_t_init(&nh_info);
   4175                         nh_flags = _BCM_L3_SHR_MATCH_DISABLE |
   4176                                     _BCM_L3_SHR_WRITE_DISABLE;
   4177                         rv = bcm_xgs3_nh_add(unit, nh_flags, &nh_info,
   4178                                                 &nh_index);
   4179                         if (BCM_FAILURE(rv)) {
   4180                             goto intf_add_done;
   4181                         }
   4182 
   4183                         int_l3_nh_created = nh_index;
   4184 
   4185                         sal_memset(&egr_nh, 0,
   4186                                     sizeof(egr_l3_next_hop_entry_t));
   4187                         /* ENTRY_TYPEf=7 is for L3MC view */
   4188                         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   4189                                             ENTRY_TYPEf, 7);
   4190 
   4191                         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   4192                                             L3MC__INTF_NUMf, id);
   4193 
   4194                         rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm,
   4195                                     MEM_BLOCK_ALL, nh_index, &egr_nh);
   4196                         if (BCM_FAILURE(rv)) {
   4197                             goto intf_add_done;
   4198                         }
   4199 
   4200                         LOG_VERBOSE(BSL_LS_BCM_IPMC, (BSL_META_U(unit,
   4201                                     "unit %d, IPMC replication for L3_INTF(id=%d):"
   4202                                     "L3_NH(id=%d) is created!\n"),
   4203                                     unit, id, nh_index));
   4204 
   4205                         /* change id from L3_INTF to L3_NH index */
   4206                         id = nh_index;
   4207                         IPMC_REPL_L3_INTF_TO_L3_NH_IPMC(unit, intf_index) = id;
   4208                         IPMC_REPL_L3_NH_TO_L3_INTF_IPMC(unit, id) = intf_index;
   4209                     }
   4210                 }
   4211             } else {
   4212                 if (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, id)) {
   4213                     id = id - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   4214                 }
   4215             }
   4216             if_array[intf_num++] = id;
   4217 
   4218             /* For IPMC, check port is a member of the L3 interface's VLAN.
   4219              * Performing this check here is more efficient than performing
   4220              * it in bcm_fb_ipmc_egress_intf_set.
   4221              */ 
   4222             if ((uint32)id > IPMC_REPL_INTF_TOTAL(unit)) {
   4223                 rv = BCM_E_PARAM;
   4224                 goto intf_add_done;
   4225             }
   4226 
   4227             if (is_l3) {
   4228                 bcm_l3_intf_t_init(&l3_intf);
   4229                 
   4230                 if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) {
   4231                     if (is_l3_intf){
   4232                         l3_intf.l3a_intf_id = intf_index;
   4233                     } else {
   4234                         bcm_l3_egress_t egr_nh;
   4235 
   4236                         rv = bcm_xgs3_nh_get(unit, id, &egr_nh);
   4237                         if (BCM_FAILURE(rv)) {
   4238                             goto intf_add_done;
   4239                         }
   4240                         l3_intf.l3a_intf_id = egr_nh.intf;
   4241                     }
   4242                 } else {
   4243                     l3_intf.l3a_intf_id = id;
   4244                 }
   4245                 
   4246                 if ((rv = bcm_esw_l3_intf_get(unit, &l3_intf)) < 0) {
   4247                     goto intf_add_done;
   4248                 }
   4249             }
   4250 
   4251             rv = bcm_fb_ipmc_egress_intf_set(unit, ipmc_id, port,
   4252                                              intf_num, if_array, is_l3, FALSE);
   4253         } else {
   4254             rv = BCM_E_EXISTS;
   4255         }
   4256     }
   4257 
   4258 intf_add_done:
   4259 
   4260     IPMC_REPL_UNLOCK(unit);
   4261     sal_free(if_array); 
   4262 
   4263     if (BCM_FAILURE(rv) && (int_l3_nh_created != -1)) {
   4264         nh_index = int_l3_nh_created;
   4265         if (bcm_xgs3_nh_del(unit, 0, nh_index) != BCM_E_NONE) {
   4266             LOG_VERBOSE(BSL_LS_BCM_IPMC, (BSL_META_U(unit,
   4267                         "unit %d, can't delete internal L3_NH(id=%d)!\n"),
   4268                         unit, nh_index));
   4269         }
   4270     }
   4271 
   4272     return rv;
   4273 }
   4274 
   4275 int
   4276 _bcm_fb_ipmc_egress_intf_delete(int unit, int ipmc_id, bcm_port_t port,
   4277                                 int if_max, int id, int is_l3)
   4278 {
   4279     int  intf_index = 0;
   4280     int  *if_array = NULL;
   4281     int  alloc_size, if_count, if_cur, match, rv = BCM_E_NONE;
   4282 
   4283     if (!SOC_IPMCREPLSHR_GET(unit) && !SOC_IS_TRX(unit) &&
   4284         !soc_feature(unit, soc_feature_ipmc_repl_penultimate)) {
   4285         return BCM_E_CONFIG;
   4286     }
   4287 
   4288     IPMC_REPL_INIT(unit);
   4289     IPMC_REPL_ID(unit, ipmc_id);
   4290     REPL_PORT_CHECK(unit, port);
   4291 
   4292     if (!IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) {
   4293         return BCM_E_NOT_FOUND;
   4294     } else if ((if_max <= 0) || ((uint32)if_max > IPMC_REPL_INTF_TOTAL(unit))) {
   4295         return BCM_E_PARAM;
   4296     }
   4297     alloc_size = if_max * sizeof(int);
   4298     if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   4299     if (if_array == NULL) {
   4300         return BCM_E_MEMORY;
   4301     }
   4302 
   4303     IPMC_REPL_LOCK(unit);
   4304     rv = bcm_fb_ipmc_egress_intf_get(unit, ipmc_id, port, if_max,
   4305                                      if_array, &if_count);
   4306     if (BCM_SUCCESS(rv)) {
   4307         /* id now is still at encap_id format. Need to modify for GH case. */
   4308         if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) {
   4309             if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, id)) {
   4310                 id = id - BCM_XGS3_EGRESS_IDX_MIN(unit);
   4311             } else {
   4312                 /*
   4313                  *  SDK-111244 : to request L3 INTF index format for
   4314                  * deleting L3MC replication as well.
   4315                  */
   4316                 intf_index = id;
   4317 
   4318                 /* index validation */
   4319                 if (intf_index >= BCM_XGS3_L3_IF_TBL_SIZE(unit)) {
   4320                     rv = BCM_E_PARAM;
   4321                     goto intf_del_done;
   4322                 } else if (!BCM_L3_INTF_USED_GET(unit, intf_index)) {
   4323                     rv = BCM_E_NOT_FOUND;
   4324                     goto intf_del_done;
   4325                 }
   4326 
   4327                 if (IPMC_REPL_L3_INTF_TO_L3_NH_IPMC(unit, intf_index) ==
   4328                             REPL_NH_INDEX_UNALLOCATED) {
   4329                     rv = BCM_E_NOT_FOUND;
   4330                     goto intf_del_done;
   4331                 }
   4332 
   4333                 /* reassign "id" for further delete process */
   4334                 id = IPMC_REPL_L3_INTF_TO_L3_NH_IPMC(unit, intf_index);
   4335             }
   4336         }
   4337 
   4338         match = FALSE;
   4339         for (if_cur = 0; if_cur < if_count; if_cur++) {
   4340             if (match) {
   4341                 if_array[if_cur - 1] = if_array[if_cur];
   4342             } else {
   4343                 if (if_array[if_cur] == id) {
   4344                     match = TRUE;
   4345                 }
   4346             }
   4347         }
   4348         if (match) {
   4349             if_count--;
   4350             rv = bcm_fb_ipmc_egress_intf_set(unit, ipmc_id, port,
   4351                                              if_count, if_array, is_l3, FALSE);
   4352         } else {
   4353             rv = BCM_E_NOT_FOUND;
   4354         }
   4355     }
   4356 
   4357 intf_del_done:
   4358 
   4359     IPMC_REPL_UNLOCK(unit);
   4360     sal_free(if_array);
   4361     return rv;
   4362 }
   4363 
   4364 /*
   4365  * Function:
   4366  *	_bcm_fb_repl_list_compare
   4367  * Description:
   4368  *	Compare HW list starting at vlan_index to the VLAN list contained
   4369  *      in vlan_vec.
   4370  */
   4371 
   4372 STATIC int
   4373 _bcm_fb_repl_list_compare(int unit, int vlan_index,
   4374                           SHR_BITDCL *intf_vec)
   4375 {
   4376     uint32		ms_bit, hw_ms_bit, ms_max;
   4377     uint32		ls_bits[2], hw_ls_bits[2];
   4378     mmu_ipmc_vlan_tbl_entry_t vlan_entry;
   4379     int	                vlan_ptr, last_vlan_ptr;
   4380     int  intf_less32 = 0; /* L3_INTF support <=32 */
   4381 
   4382     last_vlan_ptr = -1;
   4383     vlan_ptr = vlan_index;
   4384     ms_max = _SHR_BITDCLSIZE(IPMC_REPL_INTF_TOTAL(unit))/2; /* 32 -> 64 */
   4385 
   4386     if (ms_max == 0) {
   4387         intf_less32 = 1;
   4388         ms_max = 1;
   4389     }
   4390 
   4391     for (ms_bit = 0; ms_bit < ms_max; ms_bit++) {
   4392         ls_bits[0] = intf_vec[2 * ms_bit + 0];
   4393         if (intf_less32) {
   4394             ls_bits[1] = 0;
   4395         } else {
   4396             ls_bits[1] = intf_vec[2 * ms_bit + 1];
   4397         }
   4398 
   4399         if ((ls_bits[0] != 0) || (ls_bits[1] != 0)) {
   4400             if (vlan_ptr == last_vlan_ptr) { /* HW list end, not app list */
   4401                 return BCM_E_NOT_FOUND;
   4402             }
   4403             SOC_IF_ERROR_RETURN
   4404                 (READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ANY,
   4405                                                    vlan_ptr, &vlan_entry));
   4406             hw_ms_bit = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   4407                                        &vlan_entry, MSB_VLANf);
   4408             soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry,
   4409                                                    LSB_VLAN_BMf, hw_ls_bits);
   4410             if ((hw_ms_bit != ms_bit) || (ls_bits[0] != hw_ls_bits[0]) ||
   4411                 (ls_bits[1] != hw_ls_bits[1])) {
   4412                 return BCM_E_NOT_FOUND;
   4413             }
   4414             last_vlan_ptr = vlan_ptr;
   4415             vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   4416                                           &vlan_entry, NEXTPTRf);
   4417         }
   4418     }
   4419     return BCM_E_NONE;
   4420 }
   4421 
   4422 /*
   4423  * Function:
   4424  *	_bcm_fb_repl_list_free
   4425  * Description:
   4426  *	Release the IPMC_VLAN entries in the HW list starting at start_ptr.
   4427  */
   4428 
   4429 STATIC int
   4430 _bcm_fb_repl_list_free(int unit, int start_ptr)
   4431 {
   4432     mmu_ipmc_vlan_tbl_entry_t vlan_entry;
   4433     int	                vlan_ptr, last_vlan_ptr;
   4434 
   4435     last_vlan_ptr = -1;
   4436     vlan_ptr = start_ptr;
   4437 
   4438     while (vlan_ptr != last_vlan_ptr) {
   4439         SOC_IF_ERROR_RETURN
   4440             (READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ANY,
   4441                                                vlan_ptr, &vlan_entry));
   4442         last_vlan_ptr = vlan_ptr;
   4443         vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   4444                                           &vlan_entry, NEXTPTRf);
   4445         IPMC_REPL_VE_USED_CLR(unit, last_vlan_ptr);
   4446     }
   4447 
   4448     return BCM_E_NONE;
   4449 }
   4450 
   4451 /*
   4452  * Function:
   4453  *	_bcm_fb_repl_list_write
   4454  * Description:
   4455  *	Write the VLAN list contained in vlan_vec into the HW table.
   4456  *      Return the start_index and total VLAN count.
   4457  */
   4458 
   4459 STATIC int
   4460 _bcm_fb_repl_list_write(int unit, int *start_index, int *count,
   4461                         SHR_BITDCL *intf_vec)
   4462 {
   4463     uint32		ms_bit, ms_max;
   4464     uint32		ls_bits[2];
   4465     mmu_ipmc_vlan_tbl_entry_t vlan_entry;
   4466     int	                vlan_ptr, last_vlan_ptr;
   4467 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT)
   4468     int  last_write_ptr = -1;
   4469 #endif
   4470     int                 vlan_count = 0;
   4471 
   4472     int  intf_less32 = 0; /* L3_INTF support <=32 */
   4473     last_vlan_ptr = -1;
   4474 
   4475     ms_max = _SHR_BITDCLSIZE(IPMC_REPL_INTF_TOTAL(unit)) / 2; /* 32 -> 64 */
   4476 
   4477     if (ms_max == 0) {
   4478         intf_less32 = 1;
   4479         ms_max = 1;
   4480     }
   4481 
   4482     for (ms_bit = 0; ms_bit < ms_max; ms_bit++) {
   4483         ls_bits[0] = intf_vec[2 * ms_bit + 0];
   4484         if (intf_less32) {
   4485             ls_bits[1] = 0;
   4486         } else {
   4487             ls_bits[1] = intf_vec[2 * ms_bit + 1];
   4488         }
   4489 
   4490         if ((ls_bits[0] != 0) || (ls_bits[1] != 0)) {
   4491             vlan_ptr = _fb_ipmc_repl_next_free_ptr(unit);
   4492             if (last_vlan_ptr > 0) {
   4493                 /* Write previous non-zero entry */
   4494                 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit,
   4495                         &vlan_entry, NEXTPTRf,
   4496                         (vlan_ptr > 0) ? vlan_ptr : last_vlan_ptr);
   4497                 /* If vlan_ptr <= 0, terminate so
   4498                  * later cleanup can remove the chain. */
   4499                 SOC_IF_ERROR_RETURN
   4500                     (WRITE_MMU_IPMC_VLAN_TBLm(unit,
   4501                         MEM_BLOCK_ALL, last_vlan_ptr, &vlan_entry));
   4502 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT)
   4503                 last_write_ptr = last_vlan_ptr;
   4504 #endif
   4505                 if (vlan_ptr < 0) {
   4506                     _bcm_fb_repl_list_free(unit, *start_index);
   4507                     return BCM_E_RESOURCE;
   4508                 }
   4509             } else {
   4510                 if (vlan_ptr < 0) {
   4511                     return BCM_E_RESOURCE;
   4512                 }
   4513                 *start_index = vlan_ptr;
   4514             }
   4515             sal_memset(&vlan_entry, 0, sizeof(vlan_entry));
   4516             soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry,
   4517                                                MSB_VLANf, ms_bit);
   4518             soc_MMU_IPMC_VLAN_TBLm_field_set(unit, &vlan_entry,
   4519                                              LSB_VLAN_BMf, ls_bits);
   4520             IPMC_REPL_VE_USED_SET(unit, vlan_ptr);
   4521             vlan_count +=
   4522                 _shr_popcount(ls_bits[0]) + _shr_popcount(ls_bits[1]);
   4523             last_vlan_ptr = vlan_ptr;
   4524         }
   4525     }
   4526     if (last_vlan_ptr > 0) {
   4527         /* Write final entry */
   4528         soc_MMU_IPMC_VLAN_TBLm_field32_set(unit,
   4529                           &vlan_entry, NEXTPTRf, last_vlan_ptr);
   4530         SOC_IF_ERROR_RETURN
   4531             (WRITE_MMU_IPMC_VLAN_TBLm(unit,
   4532                    MEM_BLOCK_ALL, last_vlan_ptr, &vlan_entry));
   4533         
   4534 #if defined(BCM_BRADLEY_SUPPORT) || defined(BCM_TRIUMPH_SUPPORT)
   4535         if (soc_feature(unit, soc_feature_ipmc_repl_penultimate) &&
   4536             (last_write_ptr > 0)) {
   4537             soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry,
   4538                                              LSB_VLAN_BMf, ls_bits);
   4539             if ((_shr_popcount(ls_bits[0]) +
   4540                  _shr_popcount(ls_bits[1])) == 1) {
   4541                 /* Mark previous link with "last" flag */
   4542                 SOC_IF_ERROR_RETURN
   4543                     (READ_MMU_IPMC_VLAN_TBLm(unit,
   4544                           MEM_BLOCK_ANY, last_write_ptr, &vlan_entry));
   4545                 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry,
   4546                                                    LASTf, 1);
   4547                 SOC_IF_ERROR_RETURN
   4548                     (WRITE_MMU_IPMC_VLAN_TBLm(unit,
   4549                           MEM_BLOCK_ALL, last_write_ptr, &vlan_entry));
   4550             }
   4551         }
   4552 #endif /* BCM_BRADLEY_SUPPORT || BCM_TRIUMPH_SUPPORT */
   4553     }
   4554 
   4555     *count = vlan_count;
   4556     return BCM_E_NONE;
   4557 }
   4558 
   4559 
   4560 /*
   4561  * Function:
   4562  *	_bcm_fb_ipmc_egress_intf_nh_clear
   4563  * Description:
   4564  *	clear the internal created EGR_L3_NEXT_HOP entry
   4565  *    especially for the IPMC needs.
   4566  */
   4567 
   4568 STATIC int
   4569 _bcm_fb_ipmc_egress_intf_nh_clear(
   4570     int unit,
   4571     int ipmc_id,
   4572     bcm_port_t port,
   4573     int if_count,
   4574     bcm_if_t *if_array)
   4575 {
   4576     int  *nh_array = NULL;
   4577     int rv = BCM_E_NONE, rv1 = BCM_E_NONE, match;
   4578     int if_num, nh_num, nh_count, if_max, nh_id, nh2intf;
   4579     int alloc_size;
   4580     bcm_l3_egress_t nh_info;
   4581 
   4582 
   4583     IPMC_REPL_INIT(unit);
   4584     IPMC_REPL_ID(unit, ipmc_id);
   4585     REPL_PORT_CHECK(unit, port);
   4586 
   4587     if ((uint32)if_count > IPMC_REPL_INTF_TOTAL(unit)) {
   4588         return BCM_E_PARAM;
   4589     }
   4590     if_max = IPMC_REPL_INTF_TOTAL(unit);
   4591 
   4592     alloc_size = IPMC_REPL_INTF_TOTAL(unit) * sizeof(int);
   4593     nh_array = sal_alloc(alloc_size, "IPMC repl interface array");
   4594     if (nh_array == NULL) {
   4595         return BCM_E_MEMORY;
   4596     }
   4597 
   4598 
   4599     IPMC_REPL_LOCK(unit);
   4600     /* the intf get from bellow api is NH index */
   4601     if ((rv = bcm_fb_ipmc_egress_intf_get(unit, ipmc_id, port, if_max,
   4602                                            nh_array, &nh_count)) < 0) {
   4603         goto internal_nh_del_done;
   4604     }
   4605 
   4606     /* Check whether the old if_array is included in the new if_array */
   4607     for (nh_num = 0; nh_num < nh_count; nh_num++) {
   4608         match = 0;
   4609         /* the NH index is not internally created */
   4610         if (IPMC_REPL_L3_NH_TO_L3_INTF_IPMC(unit, nh_array[nh_num]) ==
   4611                 REPL_L3_INTF_UNALLOCATED) {
   4612             continue;
   4613         }
   4614         for (if_num = 0; if_num < if_count; if_num++) {
   4615             if ((uint32)if_array[if_num] > IPMC_REPL_INTF_TOTAL(unit)) {
   4616                 rv = BCM_E_PARAM;
   4617                 goto internal_nh_del_done;
   4618             }
   4619             if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) {
   4620                 nh_id = if_array[if_num];
   4621             }
   4622             else {
   4623                 nh_id = IPMC_REPL_L3_INTF_TO_L3_NH_IPMC(unit, if_array[if_num]);
   4624             }
   4625             /* if match */
   4626             if ((nh_id != REPL_NH_INDEX_UNALLOCATED) &&
   4627                     (nh_id == nh_array[nh_num])) {
   4628                 match = 1;
   4629                 break;
   4630             }
   4631         }
   4632         /* Delete the internal created NH index*/
   4633         if (match == 0) {
   4634 
   4635             /* remove this internal created L3_NH, when ref_count=1 */
   4636             if ((rv = bcm_xgs3_nh_del(unit, 0, nh_array[nh_num])) < 0 ) {
   4637                 goto internal_nh_del_done;
   4638             }
   4639             /* make sure the NH is being deleted from HW */
   4640             bcm_l3_egress_t_init(&nh_info);
   4641             rv1 = bcm_xgs3_nh_get(unit, nh_array[nh_num], &nh_info);
   4642             if (rv1 == BCM_E_NOT_FOUND) {
   4643                 nh2intf = IPMC_REPL_L3_NH_TO_L3_INTF_IPMC(unit,
   4644                                                           nh_array[nh_num]);
   4645                 IPMC_REPL_L3_INTF_TO_L3_NH_IPMC(
   4646                     unit, nh2intf) = REPL_NH_INDEX_UNALLOCATED;
   4647                 IPMC_REPL_L3_NH_TO_L3_INTF_IPMC(
   4648                     unit, nh_array[nh_num]) = REPL_L3_INTF_UNALLOCATED;
   4649                 LOG_VERBOSE(BSL_LS_BCM_IPMC, (BSL_META_U(unit,
   4650                             "unit %d, internal L3_NH(id=%d) "
   4651                             "is deleted\n"),
   4652                             unit, nh_array[nh_num]));
   4653             }
   4654         }
   4655     }
   4656 
   4657     internal_nh_del_done:
   4658     IPMC_REPL_UNLOCK(unit);
   4659     sal_free(nh_array);
   4660     return rv;
   4661 }
   4662 
   4663 /*
   4664  * Function:
   4665  *	bcm_fb_ipmc_egress_intf_set
   4666  * Purpose:
   4667  *	Assign set of egress interfaces to port's replication list for chosen
   4668  *	IPMC group.
   4669  * Parameters:
   4670  *	unit     - StrataSwitch PCI device unit number.
   4671  *	ipmc_id  - The index number.
   4672  *	port     - port to list.
   4673  *	if_count - number of interfaces in replication list.
   4674  *      if_array - (IN) List of interface numbers.
   4675  *      is_l3    - (IN) FALSE if list contains non-L3 interface (ex. MPLS/SUBPORT)
   4676  *      check_port - (IN) If is_l3 = TRUE, this parameter controls whether to
   4677  *                        check the given port is a member in each L3 interface's 
   4678  *                        VLAN. This check should be disabled when not needed,
   4679  *                        in order to improve performance.
   4680  * Returns:
   4681  *	BCM_E_XXX
   4682  */
   4683 
   4684 int
   4685 bcm_fb_ipmc_egress_intf_set(int unit, int ipmc_id, bcm_port_t port,
   4686                             int if_count, bcm_if_t *if_array, int is_l3,
   4687                             int check_port)
   4688 {
   4689     int			rvth = BCM_E_NONE, rv = BCM_E_NONE;
   4690     SHR_BITDCL          *intf_vec = NULL;
   4691     int			list_start_ptr, prev_start_ptr;
   4692     int                 alloc_size, repl_hash, vlan_count, last_flag;
   4693     int                 if_num;
   4694     bcm_l3_intf_t       l3_intf;
   4695     _bcm_repl_list_info_t *rli_start, *rli_current, *rli_prev;
   4696 
   4697     if (!SOC_IS_FBX(unit)) {
   4698 	return BCM_E_UNAVAIL;
   4699     }
   4700 
   4701     if (!SOC_IPMCREPLSHR_GET(unit) && !SOC_IS_HURRICANEX(unit) && 
   4702             !SOC_IS_GREYHOUND(unit) && !SOC_IS_GREYHOUND2(unit) &&
   4703             !soc_feature(unit, soc_feature_ipmc_repl_penultimate)) {
   4704         return BCM_E_CONFIG;
   4705     }
   4706 
   4707     IPMC_REPL_INIT(unit);
   4708     IPMC_REPL_ID(unit, ipmc_id);
   4709     REPL_PORT_CHECK(unit, port);
   4710 
   4711     if ((uint32)if_count > IPMC_REPL_INTF_TOTAL(unit)) {
   4712         return BCM_E_PARAM;
   4713     }
   4714 
   4715     alloc_size = SHR_BITALLOCSIZE(IPMC_REPL_INTF_TOTAL(unit));
   4716     intf_vec = sal_alloc(alloc_size, "IPMC repl interface vector");
   4717     if (intf_vec == NULL) {
   4718         return BCM_E_MEMORY;
   4719     }
   4720     sal_memset(intf_vec, 0, alloc_size);
   4721 
   4722     IPMC_REPL_LOCK(unit);
   4723     if (soc_feature(unit, soc_feature_ipmc_repl_freeze) && 
   4724         ((rv = _bcm_fb_ipmc_repl_freeze(unit)) < 0)) {
   4725         IPMC_REPL_UNLOCK(unit);
   4726         sal_free(intf_vec);
   4727         return rv;
   4728     }
   4729 
   4730     /* Interface validation and vector construction */
   4731     for (if_num = 0; if_num < if_count; if_num++) {
   4732         if ((uint32)if_array[if_num] > IPMC_REPL_INTF_TOTAL(unit)) {
   4733             rv = BCM_E_PARAM;
   4734             goto intf_set_done;
   4735         }
   4736         if (is_l3 && check_port) {
   4737             bcm_l3_intf_t_init(&l3_intf);
   4738                 
   4739             if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) {
   4740                 bcm_l3_egress_t egr_nh;
   4741                     
   4742                 rv = bcm_xgs3_nh_get(unit, if_array[if_num], &egr_nh);
   4743                 if (BCM_FAILURE(rv)) {
   4744                     goto intf_set_done;
   4745                 }
   4746                 l3_intf.l3a_intf_id = egr_nh.intf;
   4747             } else {
   4748                 l3_intf.l3a_intf_id = if_array[if_num];
   4749             }
   4750             
   4751             if ((rv = bcm_esw_l3_intf_get(unit, &l3_intf)) < 0) {
   4752                 goto intf_set_done;
   4753             }
   4754         }
   4755         SHR_BITSET(intf_vec, if_array[if_num]);
   4756     }
   4757 
   4758     /* Check previous group pointer */
   4759     if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, port,
   4760                                 &prev_start_ptr, 0, 0)) < 0) {
   4761         goto intf_set_done;
   4762     }
   4763 
   4764     /* Search for list already in table */
   4765     rli_start = IPMC_REPL_LIST_INFO(unit);
   4766 
   4767     repl_hash =
   4768         _shr_crc32b(0, (uint8 *)intf_vec, IPMC_REPL_INTF_TOTAL(unit));
   4769 
   4770     for (rli_current = rli_start; rli_current != NULL;
   4771          rli_current = rli_current->next) {
   4772         if (repl_hash == rli_current->hash) {
   4773             rv = _bcm_fb_repl_list_compare(unit, rli_current->index,
   4774                                            intf_vec);
   4775             if (rv == BCM_E_NOT_FOUND) {
   4776                 continue; /* Not a match */
   4777             } else if (rv < 0) {
   4778                 goto intf_set_done; /* Access error */
   4779             } else {
   4780                 break; /* Match */
   4781             }
   4782         }
   4783     }
   4784 
   4785     if (rli_current != NULL) {
   4786         /* delete the internal created NH idx when it is removed out of IPMC*/
   4787         if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) {
   4788             if ((rv = _bcm_fb_ipmc_egress_intf_nh_clear(
   4789                         unit, ipmc_id, port, if_count, if_array)) < 0){
   4790                 goto intf_set_done;
   4791             }
   4792         }
   4793         /* Found a match, point to here and increase reference count */
   4794         if (prev_start_ptr == rli_current->index) {
   4795             /* We're already pointing to this list, so done */
   4796             rv = BCM_E_NONE;
   4797             goto intf_set_done;
   4798         } else {
   4799             list_start_ptr = rli_current->index;
   4800             vlan_count = rli_current->list_size;
   4801         }
   4802     } else {
   4803         /* Not a match, make a new chain */
   4804         if ((rv = _bcm_fb_repl_list_write(unit, &list_start_ptr,
   4805                                          &vlan_count, intf_vec)) < 0) {
   4806             goto intf_set_done;
   4807         }
   4808 
   4809         if (vlan_count > 0) {
   4810             /* Update data structures */
   4811             alloc_size = sizeof(_bcm_repl_list_info_t);
   4812             rli_current = sal_alloc(alloc_size, "IPMC repl list info");
   4813             if (rli_current == NULL) {
   4814                 /* Release list */
   4815                 _bcm_fb_repl_list_free(unit, list_start_ptr);
   4816                 rv = BCM_E_MEMORY;
   4817                 goto intf_set_done;
   4818             }
   4819             sal_memset(rli_current, 0, alloc_size);
   4820             rli_current->index = list_start_ptr;
   4821             rli_current->hash = repl_hash;
   4822             rli_current->next = rli_start;
   4823             rli_current->list_size = vlan_count;
   4824             IPMC_REPL_LIST_INFO(unit) = rli_current;
   4825             rli_start = rli_current;
   4826         }
   4827         /* delete the internal created NH idx when it is removed out of IPMC*/
   4828         if (soc_feature(unit, soc_feature_l3mc_use_egress_next_hop)) {
   4829             if ((rv = _bcm_fb_ipmc_egress_intf_nh_clear(
   4830                         unit, ipmc_id, port, if_count, if_array)) < 0){
   4831                 goto intf_set_done;
   4832             }
   4833         }
   4834     }
   4835 
   4836     last_flag = (vlan_count == 1);
   4837     if (vlan_count > 0) {
   4838         if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, port,
   4839                                     &list_start_ptr, last_flag, 1)) < 0) {
   4840             if (rli_current->refcount == 0) {
   4841                 /* This was new */
   4842                 _bcm_fb_repl_list_free(unit, list_start_ptr);
   4843                 IPMC_REPL_LIST_INFO(unit) = rli_current->next;
   4844                 sal_free(rli_current);
   4845             }
   4846             goto intf_set_done;
   4847         }
   4848 
   4849         (rli_current->refcount)++;
   4850         /* we don't need this rli_current anymore */
   4851     } else if (prev_start_ptr != 0) {
   4852         list_start_ptr = 0;
   4853         if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, port,
   4854                                     &list_start_ptr, last_flag, 1)) < 0) {
   4855             goto intf_set_done;
   4856         }
   4857     }
   4858 
   4859     IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id) = vlan_count;
   4860 
   4861     if (prev_start_ptr != 0) {
   4862         rli_prev = NULL;
   4863         for (rli_current = rli_start; rli_current != NULL;
   4864              rli_current = rli_current->next) {
   4865             if (prev_start_ptr == rli_current->index) {
   4866                 (rli_current->refcount)--;
   4867                 if (rli_current->refcount == 0) {
   4868                     /* Free these linked list entries */
   4869                     rv = _bcm_fb_repl_list_free(unit, prev_start_ptr);
   4870                     /* If we have an error, we'll fall out anyway */
   4871                     if (rli_prev == NULL) {
   4872                         IPMC_REPL_LIST_INFO(unit) = rli_current->next;
   4873                     } else {
   4874                         rli_prev->next = rli_current->next;
   4875                     }
   4876                     sal_free(rli_current);
   4877                 }
   4878                 break;
   4879             }
   4880             rli_prev = rli_current;
   4881         }
   4882     }
   4883 
   4884  intf_set_done:
   4885     if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) {
   4886         rvth = _bcm_fb_ipmc_repl_thaw(unit);
   4887         rv = (rv < 0) ? rv : rvth;
   4888     }
   4889     IPMC_REPL_UNLOCK(unit);
   4890     if (intf_vec != NULL) {
   4891         sal_free(intf_vec);
   4892     }
   4893     return rv;
   4894 }
   4895 
   4896 /*
   4897  * Function:
   4898  *	bcm_fb_ipmc_egress_intf_get
   4899  * Purpose:
   4900  *	Retreieve set of egress interfaces in port's replication list
   4901  *      for chosen IPMC group.
   4902  * Parameters:
   4903  *	unit     - StrataSwitch PCI device unit number.
   4904  *	ipmc_id  - The index number.
   4905  *	port     - port to list.
   4906  *	if_max   - maximum number of interfaces in replication list.
   4907  *      if_array - (OUT) List of interface numbers.
   4908  *	if_count - (OUT) number of interfaces returned in replication list.
   4909  * Returns:
   4910  *	BCM_E_XXX
   4911  * Notes:
   4912  *      If the input parameter if_max = 0, return in the output parameter
   4913  *      if_count the total number of interfaces in the specified multicast 
   4914  *      group's replication list.
   4915  */
   4916 
   4917 int
   4918 bcm_fb_ipmc_egress_intf_get(int unit, int ipmc_id, bcm_port_t port,
   4919                             int if_max, bcm_if_t *if_array, int *if_count)
   4920 {
   4921     int			rv = BCM_E_NONE;
   4922     uint32              ms_bit;
   4923     uint32              ls_bits[2];
   4924     mmu_ipmc_vlan_tbl_entry_t vlan_entry;
   4925     int                 vlan_ptr, last_vlan_ptr;
   4926     uint32              vlan_count;
   4927     int                 ls_pos;
   4928     int                 rvth = BCM_E_NONE;
   4929 
   4930     if (!SOC_IS_FBX(unit)) {
   4931 	return BCM_E_UNAVAIL;
   4932     }
   4933 
   4934     if (!SOC_IPMCREPLSHR_GET(unit) && !SOC_IS_HURRICANEX(unit) && 
   4935             !SOC_IS_GREYHOUND(unit) && !SOC_IS_GREYHOUND2(unit) &&
   4936             !soc_feature(unit, soc_feature_ipmc_repl_penultimate)) {
   4937         return BCM_E_CONFIG;
   4938     }
   4939 
   4940     IPMC_REPL_INIT(unit);
   4941     IPMC_REPL_ID(unit, ipmc_id);
   4942     REPL_PORT_CHECK(unit, port);
   4943 
   4944     if (if_max < 0) {
   4945         return BCM_E_PARAM;
   4946     }
   4947 
   4948     IPMC_REPL_LOCK(unit);
   4949     if (IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id) == 0) {
   4950         *if_count = 0;
   4951         IPMC_REPL_UNLOCK(unit);
   4952         return rvth;
   4953     }
   4954 
   4955     if (soc_feature(unit, soc_feature_ipmc_repl_freeze) && 
   4956         ((rv = _bcm_fb_ipmc_repl_freeze(unit)) < 0)) {
   4957         IPMC_REPL_UNLOCK(unit);
   4958         return rv;
   4959     }
   4960 
   4961     if ((rv = _fb_ipmc_vlan_ptr(unit, ipmc_id, port, &vlan_ptr, 0, 0)) < 0) {
   4962         goto intf_get_done;
   4963     }
   4964     last_vlan_ptr = -1;
   4965     vlan_count = 0;
   4966     while (vlan_ptr != last_vlan_ptr) {
   4967         if ((rv = READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ANY,
   4968                                           vlan_ptr, &vlan_entry)) < 0) {
   4969             goto intf_get_done;
   4970         }
   4971         ms_bit = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   4972                                                     &vlan_entry, MSB_VLANf);
   4973         soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry,
   4974                                          LSB_VLAN_BMf, ls_bits);
   4975         for (ls_pos = 0; ls_pos < 64; ls_pos++) {
   4976             if (ls_bits[ls_pos / 32] & (1 << (ls_pos % 32))) {
   4977                 if (if_max == 0) {
   4978                     vlan_count++;
   4979                 } else {
   4980                     if_array[vlan_count++] = (ms_bit * 64) + ls_pos;
   4981                     if (vlan_count == (uint32)if_max) {
   4982                         *if_count = vlan_count;
   4983                         goto intf_get_done;
   4984                     }
   4985                 }
   4986             }
   4987         }
   4988         last_vlan_ptr = vlan_ptr;
   4989         vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   4990                                                       &vlan_entry, NEXTPTRf);
   4991 
   4992         if (vlan_count >= IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) {
   4993             break;
   4994         }
   4995     }
   4996 
   4997     *if_count = vlan_count;
   4998 
   4999  intf_get_done:
   5000     if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) {
   5001         rvth = _bcm_fb_ipmc_repl_thaw(unit);
   5002         rv = (rv < 0) ? rv : rvth;
   5003     }
   5004     IPMC_REPL_UNLOCK(unit);
   5005     return rv;
   5006 }
   5007 
   5008 /*
   5009  * Function:
   5010  *	bcm_fb_ipmc_repl_set
   5011  * Purpose:
   5012  *	Assign set of VLANs provided to port's replication list for chosen
   5013  *	IPMC group.
   5014  * Parameters:
   5015  *	unit     - StrataSwitch PCI device unit number.
   5016  *	ipmc_id  - The index number.
   5017  *	port     - port to list.
   5018  *	vlan_vec - (IN) vector of replicated VLANs common to selected ports.
   5019  * Returns:
   5020  *	BCM_E_XXX
   5021  */
   5022 
   5023 int
   5024 bcm_fb_ipmc_repl_set(int unit, int ipmc_id, bcm_port_t port,
   5025                      bcm_vlan_vector_t vlan_vec)
   5026 {
   5027     int	rv = BCM_E_NONE;
   5028     bcm_if_t *if_array = NULL;
   5029     bcm_l3_intf_t l3_intf;
   5030     pbmp_t pbmp, ubmp;
   5031     int  intf_num, intf_max, alloc_size, vid;
   5032 
   5033     if (!SOC_IS_FBX(unit)) {
   5034 	return BCM_E_UNAVAIL;
   5035     }
   5036 
   5037     if (!SOC_IPMCREPLSHR_GET(unit) &&  !SOC_IS_HURRICANEX(unit) && 
   5038             !SOC_IS_GREYHOUND(unit) && !!SOC_IS_GREYHOUND2(unit) &&
   5039             !soc_feature(unit, soc_feature_ipmc_repl_penultimate)) {
   5040         return BCM_E_CONFIG;
   5041     }
   5042 
   5043     IPMC_REPL_INIT(unit);
   5044     IPMC_REPL_ID(unit, ipmc_id);
   5045     REPL_PORT_CHECK(unit, port);
   5046 
   5047     intf_max = IPMC_REPL_INTF_TOTAL(unit);
   5048     alloc_size = intf_max * sizeof(bcm_if_t);
   5049     if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   5050     if (if_array == NULL) {
   5051         return BCM_E_MEMORY;
   5052     }
   5053 
   5054     sal_memset(if_array, 0, alloc_size);
   5055     intf_num = 0;
   5056     for (vid = BCM_VLAN_MIN; vid < BCM_VLAN_MAX; vid++) {
   5057         if (BCM_VLAN_VEC_GET(vlan_vec, vid)) {
   5058             if ((rv = bcm_esw_vlan_port_get(unit, vid, &pbmp, &ubmp)) < 0) {
   5059                 sal_free(if_array);
   5060                 return rv;
   5061             }
   5062             if (!BCM_PBMP_MEMBER(pbmp, port)) {
   5063                 sal_free(if_array);
   5064                 return BCM_E_PARAM;
   5065             }
   5066             bcm_l3_intf_t_init(&l3_intf);
   5067             l3_intf.l3a_vid = vid;
   5068             if ((rv = bcm_esw_l3_intf_find_vlan(unit, &l3_intf)) < 0) {
   5069                 sal_free(if_array);
   5070                 return rv;
   5071             }
   5072             if_array[intf_num++] = l3_intf.l3a_intf_id;
   5073         }
   5074     }
   5075 
   5076     rv = bcm_fb_ipmc_egress_intf_set(unit, ipmc_id, port,
   5077                                      intf_num, if_array, 1, FALSE);
   5078 
   5079     sal_free(if_array);
   5080     return rv;
   5081 }
   5082 
   5083 #ifdef BCM_WARM_BOOT_SUPPORT
   5084 /*
   5085  * Reload IPMC state on XGS3 class of devices
   5086  */
   5087 int
   5088 _bcm_xgs3_ipmc_reinit(int unit)
   5089 {
   5090     int i, rv = BCM_E_NONE;
   5091     int ipmc_ptr;
   5092     int l3_min, l3_max;
   5093     _bcm_esw_ipmc_t  *info = IPMC_INFO(unit);
   5094     _bcm_esw_ipmc_l3entry_t *ipmc_l3entry;
   5095 
   5096     info->ipmc_group_info = NULL;
   5097 
   5098     IPMC_GROUP_NUM(unit) = soc_mem_index_count(unit, L3_IPMCm);
   5099 
   5100     info->ipmc_count = 0;
   5101 
   5102     info->ipmc_group_info =
   5103         sal_alloc(IPMC_GROUP_NUM(unit) * sizeof(_bcm_esw_ipmc_group_info_t),
   5104                   "IPMC group info");
   5105     if (info->ipmc_group_info == NULL) {
   5106         rv = BCM_E_MEMORY;
   5107         goto ret_err;
   5108     }
   5109     sal_memset(info->ipmc_group_info, 0, 
   5110                IPMC_GROUP_NUM(unit) * sizeof(_bcm_esw_ipmc_group_info_t));
   5111 
   5112     if (SOC_IS_FBX(unit)) {
   5113         l3_entry_ipv4_multicast_entry_t *l3x_entry, *ipmc_table;
   5114         l3_entry_ipv6_multicast_entry_t *l3x_v6entry, *ipmc6_table;
   5115         ipmc_entry_t *l3_ipmc_entry, *l3_ipmc_table;
   5116         int ipmc_tbl_sz, ipmc6_tbl_sz, l3_ipmc_tbl_sz;
   5117         uint8 flags;
   5118 
   5119         l3_min = soc_mem_index_min(unit, L3_ENTRY_IPV4_MULTICASTm);
   5120         l3_max = soc_mem_index_max(unit, L3_ENTRY_IPV4_MULTICASTm);
   5121         ipmc_tbl_sz = sizeof(l3_entry_ipv4_multicast_entry_t) * \
   5122                                 (l3_max - l3_min + 1);
   5123         ipmc_table = soc_cm_salloc(unit, ipmc_tbl_sz, "ipmc tbl dma");
   5124         if (ipmc_table == NULL) {
   5125             rv = BCM_E_MEMORY;
   5126             goto ret_err;
   5127         }
   5128 
   5129         memset((void *)ipmc_table, 0, ipmc_tbl_sz);
   5130         if ((rv = soc_mem_read_range(unit, L3_ENTRY_IPV4_MULTICASTm,
   5131                                      MEM_BLOCK_ANY,
   5132                                      l3_min, l3_max, ipmc_table)) < 0) {
   5133             soc_cm_sfree(unit, ipmc_table);
   5134             goto ret_err;
   5135         }
   5136 
   5137         for (i = l3_min; i <= l3_max; i++) {
   5138             l3x_entry = soc_mem_table_idx_to_pointer(unit,
   5139                                           L3_ENTRY_IPV4_MULTICASTm,
   5140                                           l3_entry_ipv4_multicast_entry_t *,
   5141                                           ipmc_table, i);
   5142 
   5143             if (soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, l3x_entry,
   5144                                                          VALIDf) == 0) {
   5145                 continue;
   5146             }
   5147 
   5148             if (soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, l3x_entry,
   5149                                                          IPMCf) == 0) {
   5150                 continue;
   5151             }
   5152 
   5153             if (soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit, l3x_entry,
   5154                                                          V6f)) {
   5155                 continue;
   5156             }
   5157 
   5158             ipmc_ptr = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit,
   5159                                                    l3x_entry, L3MC_INDEXf);
   5160             IPMC_USED_SET(unit, ipmc_ptr);
   5161             {
   5162 #if defined(BCM_FIREBOLT_SUPPORT)
   5163                 _bcm_l3_cfg_t l3cfg;
   5164                 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t));
   5165                 l3cfg.l3c_flags |= BCM_L3_IPMC;
   5166                 l3cfg.l3c_flags |=  BCM_L3_HIT;
   5167                 if (soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit,
   5168                                                         l3x_entry, RPEf)) {
   5169                     l3cfg.l3c_flags |=  BCM_L3_RPE;
   5170                 }
   5171                 l3cfg.l3c_ipmc_group = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit,
   5172                                                         l3x_entry, GROUP_IP_ADDRf);
   5173                 l3cfg.l3c_src_ip_addr = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit,
   5174                                                         l3x_entry, SOURCE_IP_ADDRf);
   5175                 l3cfg.l3c_vid = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit,
   5176                                                         l3x_entry, VLAN_IDf);
   5177                 l3cfg.l3c_prio = soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit,
   5178                                                         l3x_entry, PRIf);
   5179                 if (SOC_MEM_FIELD_VALID(unit, L3_ENTRY_IPV4_MULTICASTm, CLASS_IDf)) {
   5180                     l3cfg.l3c_lookup_class =
   5181                         soc_L3_ENTRY_IPV4_MULTICASTm_field32_get(unit,
   5182                                                     l3x_entry, CLASS_IDf);
   5183                 }
   5184                 rv = _bcm_xgs3_ipmc_l3entry_list_add(unit, ipmc_ptr, &l3cfg);                
   5185 #endif /* BCM_FIREBOLT_SUPPORT */
   5186             }
   5187             
   5188             if (rv < 0) {
   5189                 soc_cm_sfree(unit, ipmc_table);
   5190                 goto ret_err;
   5191             }
   5192         }
   5193         soc_cm_sfree(unit, ipmc_table);
   5194 
   5195         /*
   5196          * Deal with IPv6 multicast table now
   5197          */
   5198         l3_min = soc_mem_index_min(unit, L3_ENTRY_IPV6_MULTICASTm);
   5199         l3_max = soc_mem_index_max(unit, L3_ENTRY_IPV6_MULTICASTm);
   5200         ipmc6_tbl_sz = sizeof(l3_entry_ipv6_multicast_entry_t) * \
   5201                                        (l3_max - l3_min + 1);
   5202 
   5203         ipmc6_table = soc_cm_salloc(unit, ipmc6_tbl_sz, "ipmc v6 tbl dma");
   5204         if (ipmc6_table == NULL) {
   5205             rv = BCM_E_MEMORY;
   5206             goto ret_err;
   5207         }
   5208 
   5209         memset((void *)ipmc6_table, 0, ipmc6_tbl_sz);
   5210 
   5211         if ((rv = soc_mem_read_range(unit, L3_ENTRY_IPV6_MULTICASTm,
   5212                                      MEM_BLOCK_ANY,
   5213                                      l3_min, l3_max, ipmc6_table)) < 0) {
   5214             soc_cm_sfree(unit, ipmc6_table);
   5215             goto ret_err;
   5216         }
   5217 
   5218         for (i = l3_min; i <= l3_max; i++) {
   5219 
   5220             l3x_v6entry = soc_mem_table_idx_to_pointer(unit,
   5221                                           L3_ENTRY_IPV6_MULTICASTm,
   5222                                           l3_entry_ipv6_multicast_entry_t *,
   5223                                           ipmc6_table, i);
   5224             if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, l3x_v6entry,
   5225                                                          VALID_0f) == 0) {
   5226                 continue;
   5227             }
   5228 
   5229             if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, l3x_v6entry,
   5230                                                          VALID_1f) == 0) {
   5231                 continue;
   5232             }
   5233 
   5234             if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, l3x_v6entry,
   5235                                                          VALID_2f) == 0) {
   5236                 continue;
   5237             }
   5238 
   5239             if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, l3x_v6entry,
   5240                                                          VALID_3f) == 0) {
   5241                 continue;
   5242             }
   5243 
   5244             if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, l3x_v6entry,
   5245                                                          V6_0f) == 0) {
   5246                 continue;
   5247             }
   5248 
   5249             if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, l3x_v6entry,
   5250                                                          V6_1f) == 0) {
   5251                 continue;
   5252             }
   5253 
   5254             if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, l3x_v6entry,
   5255                                                          V6_2f) == 0) {
   5256                 continue;
   5257             }
   5258 
   5259             if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, l3x_v6entry,
   5260                                                          V6_3f) == 0) {
   5261                 continue;
   5262             }
   5263 
   5264             if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, l3x_v6entry,
   5265                                                          IPMC_0f) == 0) {
   5266                 continue;
   5267             }
   5268 
   5269             if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, l3x_v6entry,
   5270                                                          IPMC_1f) == 0) {
   5271                 continue;
   5272             }
   5273 
   5274             if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, l3x_v6entry,
   5275                                                          IPMC_2f) == 0) {
   5276                 continue;
   5277             }
   5278 
   5279             if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit, l3x_v6entry,
   5280                                                          IPMC_3f) == 0) {
   5281                 continue;
   5282             }
   5283 
   5284             ipmc_ptr = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit,
   5285                                     l3x_v6entry, L3MC_INDEX_0f);
   5286             IPMC_USED_SET(unit, ipmc_ptr);
   5287             {
   5288 #if defined(BCM_FIREBOLT_SUPPORT)
   5289                 _bcm_l3_cfg_t l3cfg;
   5290                 sal_memset(&l3cfg, 0, sizeof(_bcm_l3_cfg_t));
   5291                 l3cfg.l3c_flags |= BCM_IPMC_IP6;
   5292                 l3cfg.l3c_flags |= BCM_L3_IPMC;
   5293                 l3cfg.l3c_flags |=  BCM_L3_HIT;
   5294                 if (soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit,
   5295                                                         l3x_v6entry, RPEf)) {
   5296                     l3cfg.l3c_flags |=  BCM_L3_RPE;
   5297                 }
   5298                 /* Get group address. */
   5299                 soc_mem_ip6_addr_get(unit, L3_ENTRY_IPV6_MULTICASTm, l3x_v6entry, 
   5300                                      GROUP_IP_ADDR_LWR_64f, l3cfg.l3c_ip6, 
   5301                                      SOC_MEM_IP6_LOWER_ONLY);
   5302                 
   5303                 soc_mem_ip6_addr_get(unit, L3_ENTRY_IPV6_MULTICASTm, l3x_v6entry, 
   5304                                      GROUP_IP_ADDR_UPR_56f, l3cfg.l3c_ip6, 
   5305                                      SOC_MEM_IP6_UPPER_ONLY);
   5306                 
   5307                 /* Get source  address. */
   5308                 soc_mem_ip6_addr_get(unit, L3_ENTRY_IPV6_MULTICASTm, l3x_v6entry, 
   5309                                      SOURCE_IP_ADDR_LWR_64f, l3cfg.l3c_sip6, 
   5310                                      SOC_MEM_IP6_LOWER_ONLY);
   5311                 soc_mem_ip6_addr_get(unit, L3_ENTRY_IPV6_MULTICASTm, l3x_v6entry, 
   5312                                      SOURCE_IP_ADDR_UPR_64f, l3cfg.l3c_sip6, 
   5313                                      SOC_MEM_IP6_UPPER_ONLY);
   5314                 
   5315                 l3cfg.l3c_ip6[0] = 0xff;    /* Set entry to multicast*/ 
   5316                 l3cfg.l3c_vid = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit,
   5317                                                         l3x_v6entry, VLAN_IDf);
   5318                 l3cfg.l3c_prio = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit,
   5319                                                         l3x_v6entry, PRIf);
   5320                 l3cfg.l3c_lookup_class = soc_L3_ENTRY_IPV6_MULTICASTm_field32_get(unit,
   5321                                                 l3x_v6entry, CLASS_IDf);
   5322                 rv = _bcm_xgs3_ipmc_l3entry_list_add(unit, ipmc_ptr, &l3cfg);
   5323 #endif /* BCM_FIREBOLT_SUPPORT */
   5324             }   
   5325             if (rv < 0) {
   5326                 soc_cm_sfree(unit, ipmc6_table);
   5327                 goto ret_err;
   5328             }
   5329         }
   5330         soc_cm_sfree(unit, ipmc6_table);
   5331 
   5332         /* Recover multicast mode from HW cache */
   5333         rv = _bcm_esw_ipmc_repl_wb_flags_get(unit,
   5334                                              _BCM_IPMC_WB_MULTICAST_MODE,
   5335                                              &flags);
   5336 
   5337         if (flags) {
   5338             /*
   5339              * Increase reference count for all mulitcast groups now
   5340              */
   5341             l3_min = soc_mem_index_min(unit, L3_IPMCm);
   5342             l3_max = soc_mem_index_max(unit, L3_IPMCm);
   5343             l3_ipmc_tbl_sz = sizeof(ipmc_entry_t) * \
   5344                 (l3_max - l3_min + 1);
   5345 
   5346             l3_ipmc_table = soc_cm_salloc(unit, l3_ipmc_tbl_sz,
   5347                                           "L3 ipmc tbl dma");
   5348             if (l3_ipmc_table == NULL) {
   5349                 rv = BCM_E_MEMORY;
   5350                 goto ret_err;
   5351             }
   5352 
   5353             memset((void *)l3_ipmc_table, 0, l3_ipmc_tbl_sz);
   5354 
   5355             if ((rv = soc_mem_read_range(unit, L3_IPMCm,
   5356                                          MEM_BLOCK_ANY,
   5357                                          l3_min, l3_max,
   5358                                          l3_ipmc_table)) < 0) {
   5359                 soc_cm_sfree(unit, l3_ipmc_table);
   5360                 goto ret_err;
   5361             }
   5362 
   5363             for (i = l3_min; i <= l3_max; i++) {
   5364                 l3_ipmc_entry = soc_mem_table_idx_to_pointer(unit,
   5365                                                              L3_IPMCm,
   5366                                                          ipmc_entry_t *,
   5367                                                          l3_ipmc_table, i);
   5368                 if (0 == soc_L3_IPMCm_field32_get(unit, l3_ipmc_entry,
   5369                                                   VALIDf)) {
   5370                     continue;
   5371                 }
   5372         
   5373                 /* It's a multicast group we need to note. */
   5374                 IPMC_USED_SET(unit, i);
   5375             }
   5376             soc_cm_sfree(unit, l3_ipmc_table);
   5377         }
   5378 
   5379         /*
   5380          * Recover replication state
   5381          */
   5382         rv = _bcm_xgs3_ipmc_repl_reload(unit);
   5383     }
   5384 
   5385 ret_err:
   5386     if (BCM_FAILURE(rv)) {
   5387 
   5388         if (info->ipmc_group_info != NULL) {
   5389             for (i = 0; i < IPMC_GROUP_NUM(unit); i++) {
   5390                 ipmc_l3entry = IPMC_GROUP_INFO(unit, i)->l3entry_list;
   5391                 while (ipmc_l3entry != NULL) {
   5392                     IPMC_GROUP_INFO(unit, i)->l3entry_list = ipmc_l3entry->next;
   5393                     sal_free(ipmc_l3entry);
   5394                     ipmc_l3entry = IPMC_GROUP_INFO(unit, i)->l3entry_list;
   5395                 }
   5396             }
   5397             sal_free(info->ipmc_group_info);
   5398             info->ipmc_group_info = NULL;
   5399         }
   5400     } else {
   5401         info->ipmc_initialized = TRUE;
   5402     }
   5403 
   5404     return rv;
   5405 }
   5406 
   5407 /*
   5408  * Sync IPMC state on XGS3 class of devices
   5409  */
   5410 int
   5411 _bcm_fb_ipmc_sync(
   5412     int unit,
   5413     uint8 **scache_ptr)
   5414 {
   5415     int i;
   5416 
   5417     /* Input parameters sanity check. */
   5418     if (NULL == scache_ptr) {
   5419         return (BCM_E_PARAM);
   5420     }
   5421 
   5422     /* Synce IPMC replication info*/
   5423     for (i = 0; i < soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); i++) {
   5424         sal_memcpy((*scache_ptr),
   5425                    &(_fb_repl_info[unit]->l3_nh_to_l3_intf_ipmc[i]),
   5426                    sizeof(int));
   5427         (*scache_ptr) += sizeof(int);
   5428     }
   5429 
   5430     for (i = 0; i < soc_mem_index_count(unit, EGR_L3_INTFm); i++) {
   5431         sal_memcpy((*scache_ptr),
   5432                    &(_fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc[i]),
   5433                    sizeof(int));
   5434         (*scache_ptr) += sizeof(int);
   5435     }
   5436 
   5437     return BCM_E_NONE;
   5438 }
   5439 
   5440 int
   5441 _bcm_fb_ipmc_scahce_size_get(
   5442     int unit,
   5443     uint32 *size)
   5444 {
   5445     int num_l3_nh, num_l3_intf;
   5446 
   5447     /* Input parameters sanity check. */
   5448     if (NULL == size) {
   5449         return (BCM_E_PARAM);
   5450     }
   5451 
   5452     *size = 0;
   5453     /* Get IPMC replication info scache size*/
   5454     num_l3_nh = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
   5455     num_l3_intf = soc_mem_index_count(unit, EGR_L3_INTFm);
   5456     *size = (num_l3_nh * sizeof(int)) + (num_l3_intf * sizeof(int));
   5457 
   5458     return BCM_E_NONE;
   5459 }
   5460 
   5461 int
   5462 _bcm_fb_ipmc_repl_scache_recover(
   5463     int unit,
   5464     uint8 **scache_ptr)
   5465 {
   5466     int i;
   5467 
   5468     /* Input parameters sanity check. */
   5469     if (NULL == scache_ptr) {
   5470         return (BCM_E_PARAM);
   5471     }
   5472 
   5473     /* Recover IPMC replication info state */
   5474     for (i = 0; i < soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); i++) {
   5475         sal_memcpy(&(_fb_repl_info[unit]->l3_nh_to_l3_intf_ipmc[i]),
   5476                    (*scache_ptr),
   5477                    sizeof(int));
   5478         (*scache_ptr) += sizeof(int);
   5479     }
   5480 
   5481     for (i = 0; i < soc_mem_index_count(unit, EGR_L3_INTFm); i++) {
   5482         sal_memcpy(&(_fb_repl_info[unit]->l3_intf_to_l3_nh_ipmc[i]),
   5483                    (*scache_ptr),
   5484                    sizeof(int));
   5485         (*scache_ptr) += sizeof(int);
   5486     }
   5487 
   5488     return BCM_E_NONE;
   5489 }
   5490 
   5491 
   5492 
   5493 
   5494 
   5495 #endif /* BCM_WARM_BOOT_SUPPORT */
   5496 
   5497 #ifndef BCM_SW_STATE_DUMP_DISABLE
   5498 /*
   5499  * Function:
   5500  *     _bcm_xgs3_ipmc_repl_sw_dump
   5501  * Purpose:
   5502  *     Displays IPMC replication information maintained by software.
   5503  * Parameters:
   5504  *     unit - Device unit number
   5505  * Returns:
   5506  *     None
   5507  */
   5508 void
   5509 _bcm_xgs3_ipmc_repl_sw_dump(int unit)
   5510 {
   5511     int                   i, j, port;
   5512     _fb_repl_info_t       *repl_info;
   5513     uint32                *bitmap;
   5514     _fb_repl_port_info_t  *port_info;
   5515     _bcm_repl_list_info_t *rli_start, *rli_current;
   5516 
   5517     /*
   5518      * _fb_repl_info
   5519      */
   5520 
   5521     LOG_CLI((BSL_META_U(unit,
   5522                         "  IPMC REPL Info -\n")));
   5523     repl_info = _fb_repl_info[unit];
   5524     if (repl_info != NULL) {
   5525         LOG_CLI((BSL_META_U(unit,
   5526                             "    IPMC Size    : %d\n"), repl_info->ipmc_size));
   5527         LOG_CLI((BSL_META_U(unit,
   5528                             "    Intf Size    : %d\n"), repl_info->intf_num));
   5529         LOG_CLI((BSL_META_U(unit,
   5530                             "    Vlan total   : %d\n"), repl_info->ipmc_vlan_total));
   5531 
   5532         LOG_CLI((BSL_META_U(unit,
   5533                             "    Bitmap (index:value-hex) :")));
   5534         if (repl_info->bitmap_entries_used != NULL) {
   5535             bitmap =  repl_info->bitmap_entries_used;
   5536             for (i = 0, j = 0;
   5537                  i < _SHR_BITDCLSIZE(repl_info->ipmc_vlan_total); i++) {
   5538                 /* If zero, skip print */
   5539                 if (bitmap[i] == 0) {
   5540                     continue;
   5541                 }
   5542                 if (!(j % 4)) {
   5543                     LOG_CLI((BSL_META_U(unit,
   5544                                         "\n    ")));
   5545                 }
   5546                 LOG_CLI((BSL_META_U(unit,
   5547                                     "  %5d:%8.8x"), i, bitmap[i]));
   5548                 j++;
   5549             }
   5550         }
   5551         LOG_CLI((BSL_META_U(unit,
   5552                             "\n")));
   5553 
   5554         LOG_CLI((BSL_META_U(unit,
   5555                             "    Port Info    -\n")));
   5556         LOG_CLI((BSL_META_U(unit,
   5557                             "    port (index:vlan-count) :\n")));
   5558         for (port = 0; port < SOC_MAX_NUM_PORTS; port++) {
   5559             port_info = repl_info->port_info[port];
   5560             LOG_CLI((BSL_META_U(unit,
   5561                                 "    %3d -"), port));
   5562             if (port_info == NULL) {
   5563                 LOG_CLI((BSL_META_U(unit,
   5564                                     " null\n")));
   5565                 continue;
   5566             }
   5567             for (i = 0, j = 0; i < IPMC_GROUP_NUM(unit); i++) {
   5568                 /* If zero, skip print */
   5569                 if (port_info->vlan_count[i] == 0) {
   5570                     continue;
   5571                 }
   5572                 if ((j > 0) && !(j % 4)) {
   5573                     LOG_CLI((BSL_META_U(unit,
   5574                                         "\n         ")));
   5575                 }
   5576                 LOG_CLI((BSL_META_U(unit,
   5577                                     " %5d:%-4d"), i, port_info->vlan_count[i]));
   5578                 j++;
   5579             }
   5580             LOG_CLI((BSL_META_U(unit,
   5581                                 "\n")));
   5582         }
   5583 
   5584         
   5585         rli_start = IPMC_REPL_LIST_INFO(unit);
   5586         LOG_CLI((BSL_META_U(unit,
   5587                             "    List Info    -\n")));
   5588         for (rli_current = rli_start; rli_current != NULL;
   5589              rli_current = rli_current->next) {
   5590             LOG_CLI((BSL_META_U(unit,
   5591                                 "    Hash:  0x%08x\n"), rli_current->hash));
   5592             LOG_CLI((BSL_META_U(unit,
   5593                                 "    Index: %4d\n"), rli_current->index));
   5594             LOG_CLI((BSL_META_U(unit,
   5595                                 "    Size:  %4d\n"), rli_current->list_size));
   5596             LOG_CLI((BSL_META_U(unit,
   5597                                 "    Refs:  %4d\n"), rli_current->refcount));
   5598         }
   5599     }
   5600 
   5601     return;
   5602 }
   5603 
   5604 /*
   5605  * Function:
   5606  *     _bcm_xgs3_ipmc_sw_dump
   5607  * Purpose:
   5608  *     Displays IPMC information maintained by software.
   5609  * Parameters:
   5610  *     unit - Device unit number
   5611  * Returns:
   5612  *     None
   5613  */
   5614 void
   5615 _bcm_xgs3_ipmc_sw_dump(int unit)
   5616 {
   5617     int                   i, j;
   5618     _bcm_esw_ipmc_t      *ipmc_info;
   5619     _bcm_esw_ipmc_l3entry_t *ipmc_l3entry;
   5620 
   5621 
   5622     /*
   5623      * xgs3_ipmc_info
   5624      */
   5625 
   5626     ipmc_info = IPMC_INFO(unit);
   5627 
   5628     LOG_CLI((BSL_META_U(unit,
   5629                         "  XGS3 IPMC Info -\n")));
   5630     LOG_CLI((BSL_META_U(unit,
   5631                         "    Init        : %d\n"), ipmc_info->ipmc_initialized));
   5632     LOG_CLI((BSL_META_U(unit,
   5633                         "    Size        : %d\n"), IPMC_GROUP_NUM(unit)));
   5634     LOG_CLI((BSL_META_U(unit,
   5635                         "    Count       : %d\n"), ipmc_info->ipmc_count));
   5636 
   5637     LOG_CLI((BSL_META_U(unit,
   5638                         "    Alloc index :")));
   5639     if (ipmc_info->ipmc_group_info != NULL) {
   5640         for (i = 0, j = 0; i < IPMC_GROUP_NUM(unit); i++) {
   5641             /* If not set, skip print */
   5642             if (!IPMC_USED_ISSET(unit, i)) {
   5643                 continue;
   5644             }
   5645             if (!(j % 10)) {
   5646                 LOG_CLI((BSL_META_U(unit,
   5647                                     "\n    ")));
   5648             }
   5649             LOG_CLI((BSL_META_U(unit,
   5650                                 "  %5d"), i));
   5651             j++;
   5652         }
   5653     }
   5654     LOG_CLI((BSL_META_U(unit,
   5655                         "\n")));
   5656 
   5657     LOG_CLI((BSL_META_U(unit,
   5658                         "    Reference count (index:value) :")));
   5659     if (ipmc_info->ipmc_group_info != NULL) {
   5660         for (i = 0, j = 0; i < IPMC_GROUP_NUM(unit); i++) {
   5661             if (!IPMC_USED_ISSET(unit, i)) {
   5662                 continue;
   5663             }
   5664             if (!(j % 4)) {
   5665                 LOG_CLI((BSL_META_U(unit,
   5666                                     "\n    ")));
   5667             }
   5668             LOG_CLI((BSL_META_U(unit,
   5669                                 "  %5d:%-5d"), i, IPMC_GROUP_INFO(unit, i)->ref_count));
   5670             j++;
   5671         }
   5672     }
   5673     LOG_CLI((BSL_META_U(unit,
   5674                         "\n")));
   5675     LOG_CLI((BSL_META_U(unit,
   5676                         "    IP6 (index:value) :")));
   5677     if (ipmc_info->ipmc_group_info != NULL) {
   5678         for (i = 0, j = 0; i < IPMC_GROUP_NUM(unit); i++) {
   5679             ipmc_l3entry = IPMC_GROUP_INFO(unit, i)->l3entry_list;
   5680             while (ipmc_l3entry != NULL) {
   5681                 if (ipmc_l3entry->ip6 == 1) {
   5682                     if (!(j % 4)) {
   5683                         LOG_CLI((BSL_META_U(unit,
   5684                                             "\n    ")));
   5685                     }
   5686                     LOG_CLI((BSL_META_U(unit,
   5687                                         "  %5d:%-5d"), i, ipmc_l3entry->ip6));
   5688                     j++;
   5689                 }
   5690                 ipmc_l3entry = ipmc_l3entry->next;
   5691             }
   5692         }
   5693     }
   5694     LOG_CLI((BSL_META_U(unit,
   5695                         "\n")));
   5696 
   5697     _bcm_xgs3_ipmc_repl_sw_dump(unit);
   5698 
   5699     return;
   5700 }
   5701 #endif /*  BCM_SW_STATE_DUMP_DISABLE */
   5702 
   5703 #endif /* BCM_FIREBOLT_SUPPORT */
   5704 
   5705 #endif  /* INCLUDE_L3 */
   5706 
   5707 int _bcm_esw_firebolt_ipmc_not_empty;
   5708