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


      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 #include <soc/bradley.h>
     15 
     16 #include <bcm/error.h>
     17 #include <bcm/ipmc.h>
     18 
     19 #include <bcm_int/esw/ipmc.h>
     20 #include <bcm_int/esw/mbcm.h>
     21 #include <bcm_int/esw/firebolt.h>
     22 #include <bcm_int/esw/triumph2.h>
     23 #include <bcm_int/esw/bradley.h>
     24 #ifdef BCM_KATANA_SUPPORT
     25 #include <bcm_int/esw/katana.h>
     26 #endif
     27 #ifdef BCM_KATANA2_SUPPORT
     28 #include <bcm_int/esw/katana2.h>
     29 #include <bcm_int/esw/subport.h>
     30 #endif /* BCM_KATANA2_SUPPORT */
     31 #include <bcm_int/esw_dispatch.h>
     32 
     33 #if defined(BCM_KATANA2_SUPPORT)
     34 #define REPL_PORT_CHECK(unit, port) \
     35 { \
     36     if (SOC_IS_KATANA2(unit)) { \
     37         if (!IS_PORT(unit, port) && \
     38             !(port >= SOC_INFO(unit).pp_port_index_min) && \
     39             !(port <= SOC_INFO(unit).pp_port_index_max)) { \
     40             return BCM_E_PARAM; \
     41         } \
     42     } else { \
     43         if (!IS_PORT(unit, port)) { \
     44             return BCM_E_PARAM; \
     45         } \
     46     } \
     47 }
     48 #else
     49 #define REPL_PORT_CHECK(unit, port) \
     50     if (!IS_PORT(unit, port)) { \
     51         return BCM_E_PARAM; \
     52     }
     53 #endif
     54 
     55 #define _BCM_QOS_MAP_TYPE_MASK           0x3ff
     56 #define _BCM_QOS_MAP_SHIFT                  10
     57 
     58 typedef struct _tr2_repl_port_info_s {
     59     int32 *vlan_count;                        /* # VLANs the port repl to */
     60 } _tr2_repl_port_info_t;
     61 
     62 typedef struct _tr2_repl_info_s {
     63     int ipmc_size;
     64     uint32 intf_num;              /* Number of interfaces on this device */
     65     uint16 ipmc_vlan_total;       /* Keep track of total and */
     66     uint32 *bitmap_entries_used;  /* free entries of IPMC_VLAN table */
     67     _bcm_repl_list_info_t *repl_list_info;
     68     _tr2_repl_port_info_t *port_info[SOC_MAX_NUM_PORTS];
     69 } _tr2_repl_info_t;
     70 
     71 static _tr2_repl_info_t *_tr2_repl_info[BCM_MAX_NUM_UNITS];
     72 
     73 #define TD_EGR_L3_NEXT_HOP_OFFSET 8192
     74 
     75 #ifdef BCM_KATANA_SUPPORT
     76 
     77 typedef struct _kt_repl_queue_info_s {
     78     int32 *queue_count;           /* # VLANs the queue repl to */
     79     int32 *queue_count_int;       /* # Count of internally buffered queues */
     80     int32 *queue_count_ext;       /* # Count of externally buffered queues */
     81 } _kt_repl_queue_info_t;
     82 
     83 typedef struct _kt_extq_repl_info_s {
     84     int ipmc_size;
     85     uint32 queue_num;
     86     uint32 extq_list_total;
     87     uint32 extq_repl_max;
     88     uint32 *bitmap_entries_used; /* free entries of
     89                                      MMU_EXT_MC_QUEUE_LIST  table */
     90     _bcm_repl_list_info_t *repl_extq_list_info;
     91     _kt_repl_queue_info_t *mcgroup_info;
     92 #if (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS)
     93     _kt_repl_queue_info_t *port_info[SOC_MAX_NUM_PP_PORTS];
     94 #else
     95     _kt_repl_queue_info_t *port_info[SOC_MAX_NUM_PORTS];
     96 #endif
     97 } _kt_extq_repl_info_t;
     98 
     99 static _kt_extq_repl_info_t *_kt_extq_repl_info[BCM_MAX_NUM_UNITS];
    100 
    101 #endif
    102 
    103 #define IPMC_REPL_LOCK(_u_)                    \
    104     if (SOC_IS_KATANA2(unit)) {                \
    105         soc_mem_lock(_u_, MMU_REPL_LIST_TBLm); \
    106     } else {                                   \
    107         soc_mem_lock(_u_, MMU_IPMC_VLAN_TBLm); \
    108     } 
    109 #define IPMC_REPL_UNLOCK(_u_)                    \
    110     if (SOC_IS_KATANA2(unit)) {                  \
    111         soc_mem_unlock(_u_, MMU_REPL_LIST_TBLm); \
    112     } else {                                     \
    113         soc_mem_unlock(_u_, MMU_IPMC_VLAN_TBLm); \
    114     }
    115 #define IPMC_REPL_ID(_u_, _id_) \
    116         if ((_id_ < 0) || (_id_ >= _tr2_repl_info[_u_]->ipmc_size)) \
    117             { return BCM_E_PARAM; }
    118 #define IPMC_REPL_INIT(unit) \
    119         if (_tr2_repl_info[unit] == NULL) { return BCM_E_INIT; }
    120 #define IPMC_REPL_TOTAL(_u_) \
    121         _tr2_repl_info[_u_]->ipmc_vlan_total
    122 #define IPMC_REPL_INTF_TOTAL(_u_) \
    123         _tr2_repl_info[_u_]->intf_num
    124 #define IPMC_REPL_VE_USED_GET(_u_, _i_) \
    125         SHR_BITGET(_tr2_repl_info[_u_]->bitmap_entries_used, _i_)
    126 #define IPMC_REPL_VE_USED_SET(_u_, _i_) \
    127         SHR_BITSET(_tr2_repl_info[_u_]->bitmap_entries_used, _i_)
    128 #define IPMC_REPL_VE_USED_CLR(_u_, _i_) \
    129         SHR_BITCLR(_tr2_repl_info[_u_]->bitmap_entries_used, _i_)
    130 
    131 #define IPMC_REPL_LIST_INFO(_u_) \
    132 	_tr2_repl_info[_u_]->repl_list_info
    133 #define IPMC_REPL_PORT_INFO(_u_, _p_) \
    134         _tr2_repl_info[_u_]->port_info[_p_]
    135 #define IPMC_REPL_PORT_VLAN_COUNT(_u_, _p_, _ipmc_id_) \
    136         _tr2_repl_info[_u_]->port_info[_p_]->vlan_count[_ipmc_id_]
    137 
    138 #ifdef BCM_KATANA_SUPPORT
    139 #define IPMC_EXTQ_ID(_u_, _id_) \
    140         if ((_id_ < 0) || (_id_ >= _kt_extq_repl_info[_u_]->queue_num)) \
    141             { return BCM_E_PARAM; }
    142 #define IPMC_EXTQ_REPL_INIT(unit) \
    143         if (_kt_extq_repl_info[unit] == NULL) { return BCM_E_INIT; }
    144 #define IPMC_EXTQ_LIST_TOTAL(_u_) \
    145         _kt_extq_repl_info[_u_]->extq_list_total
    146 #define IPMC_EXTQ_REPL_MAX(_u_) \
    147         _kt_extq_repl_info[_u_]->extq_repl_max
    148 #define IPMC_EXTQ_TOTAL(_u_) \
    149         _kt_extq_repl_info[_u_]->queue_num
    150 #define IPMC_EXTQ_REPL_VE_USED_GET(_u_, _i_) \
    151         SHR_BITGET(_kt_extq_repl_info[_u_]->bitmap_entries_used, _i_)
    152 #define IPMC_EXTQ_REPL_VE_USED_SET(_u_, _i_) \
    153         SHR_BITSET(_kt_extq_repl_info[_u_]->bitmap_entries_used, _i_)
    154 #define IPMC_EXTQ_REPL_VE_USED_CLR(_u_, _i_) \
    155         SHR_BITCLR(_kt_extq_repl_info[_u_]->bitmap_entries_used, _i_)
    156 #define IPMC_EXTQ_REPL_LIST_INFO(_u_) \
    157     _kt_extq_repl_info[_u_]->repl_extq_list_info
    158 #define IPMC_EXTQ_GROUP_INFO(_u_) 		\
    159 	_kt_extq_repl_info[_u_]->mcgroup_info
    160 #define IPMC_EXTQ_REPL_QUEUE_COUNT(_u_, _ipmc_id_) \
    161         _kt_extq_repl_info[_u_]->mcgroup_info->queue_count[_ipmc_id_]
    162 #define IPMC_EXTQ_REPL_QUEUE_COUNT_INT(_u_, _ipmc_id_) \
    163         _kt_extq_repl_info[_u_]->mcgroup_info->queue_count_int[_ipmc_id_]
    164 #define IPMC_EXTQ_REPL_QUEUE_COUNT_EXT(_u_, _ipmc_id_) \
    165         _kt_extq_repl_info[_u_]->mcgroup_info->queue_count_ext[_ipmc_id_]
    166 #define IPMC_EXTQ_REPL_PORT_INFO(_u_, _p_) \
    167         _kt_extq_repl_info[_u_]->port_info[_p_]
    168 #define IPMC_EXTQ_REPL_PORT_QUEUE_COUNT(_u_, _p_, _ipmc_id_) \
    169         _kt_extq_repl_info[_u_]->port_info[_p_]->queue_count[_ipmc_id_]
    170 
    171 #endif
    172 
    173 typedef struct _rep_regs_s {
    174     soc_field_t ptr_type;
    175     soc_field_t port_ptr;
    176     soc_field_t last_ptr;
    177     soc_mem_t   mem;
    178 }_rep_regs_t;
    179 
    180 _rep_regs_t ch_rep_regs[55] = { {INVALIDf,  INVALIDf,       INVALIDf,    INVALIDm},
    181                                 {INVALIDf,  PORT1_1STPTRf,  PORT1_LASTf, MMU_IPMC_GROUP_TBL0m},
    182                                 {INVALIDf,  PORT2_1STPTRf,  PORT2_LASTf, MMU_IPMC_GROUP_TBL0m},
    183                                 {INVALIDf,  PORT3_1STPTRf,  PORT3_LASTf, MMU_IPMC_GROUP_TBL0m},
    184                                 {INVALIDf,  PORT4_1STPTRf,  PORT4_LASTf, MMU_IPMC_GROUP_TBL0m},
    185                                 {INVALIDf,  PORT5_1STPTRf,  PORT5_LASTf, MMU_IPMC_GROUP_TBL0m},
    186                                 {INVALIDf,  PORT6_1STPTRf,  PORT6_LASTf, MMU_IPMC_GROUP_TBL0m},
    187                                 {INVALIDf,  PORT7_1STPTRf,  PORT7_LASTf, MMU_IPMC_GROUP_TBL1m},
    188                                 {INVALIDf,  PORT8_1STPTRf,  PORT8_LASTf, MMU_IPMC_GROUP_TBL1m},
    189                                 {INVALIDf,  PORT9_1STPTRf,  PORT9_LASTf, MMU_IPMC_GROUP_TBL1m},
    190                                 {INVALIDf,  PORT10_1STPTRf,  PORT10_LASTf, MMU_IPMC_GROUP_TBL1m},
    191                                 {INVALIDf,  PORT11_1STPTRf,  PORT11_LASTf, MMU_IPMC_GROUP_TBL1m},
    192                                 {INVALIDf,  PORT12_1STPTRf,  PORT12_LASTf, MMU_IPMC_GROUP_TBL1m},
    193                                 {INVALIDf,  PORT13_1STPTRf,  PORT13_LASTf, MMU_IPMC_GROUP_TBL2m},
    194                                 {INVALIDf,  PORT14_1STPTRf,  PORT14_LASTf, MMU_IPMC_GROUP_TBL2m},
    195                                 {INVALIDf,  PORT15_1STPTRf,  PORT15_LASTf, MMU_IPMC_GROUP_TBL2m},
    196                                 {INVALIDf,  PORT16_1STPTRf,  PORT16_LASTf, MMU_IPMC_GROUP_TBL2m},
    197                                 {INVALIDf,  PORT17_1STPTRf,  PORT17_LASTf, MMU_IPMC_GROUP_TBL2m},
    198                                 {INVALIDf,  PORT18_1STPTRf,  PORT18_LASTf, MMU_IPMC_GROUP_TBL2m},
    199                                 {INVALIDf,  PORT19_1STPTRf,  PORT19_LASTf, MMU_IPMC_GROUP_TBL3m},
    200                                 {INVALIDf,  PORT20_1STPTRf,  PORT20_LASTf, MMU_IPMC_GROUP_TBL3m},
    201                                 {INVALIDf,  PORT21_1STPTRf,  PORT21_LASTf, MMU_IPMC_GROUP_TBL3m},
    202                                 {INVALIDf,  PORT22_1STPTRf,  PORT22_LASTf, MMU_IPMC_GROUP_TBL3m},
    203                                 {INVALIDf,  PORT23_1STPTRf,  PORT23_LASTf, MMU_IPMC_GROUP_TBL3m},
    204                                 {INVALIDf,  PORT24_1STPTRf,  PORT24_LASTf, MMU_IPMC_GROUP_TBL3m},
    205                                 {INVALIDf,  PORT25_1STPTRf,  PORT25_LASTf, MMU_IPMC_GROUP_TBL4m},
    206                                 {INVALIDf,  PORT26_1STPTRf,  PORT26_LASTf, MMU_IPMC_GROUP_TBL4m},
    207                                 {INVALIDf,  PORT27_1STPTRf,  PORT27_LASTf, MMU_IPMC_GROUP_TBL4m},
    208                                 {INVALIDf,  PORT28_1STPTRf,  PORT28_LASTf, MMU_IPMC_GROUP_TBL4m},
    209                                 {INVALIDf,  PORT29_1STPTRf,  PORT29_LASTf, MMU_IPMC_GROUP_TBL4m},
    210                                 {INVALIDf,  PORT30_1STPTRf,  PORT30_LASTf, MMU_IPMC_GROUP_TBL4m},
    211                                 {INVALIDf,  PORT31_1STPTRf,  PORT31_LASTf, MMU_IPMC_GROUP_TBL5m},
    212                                 {INVALIDf,  PORT32_1STPTRf,  PORT32_LASTf, MMU_IPMC_GROUP_TBL5m},
    213                                 {INVALIDf,  PORT33_1STPTRf,  PORT33_LASTf, MMU_IPMC_GROUP_TBL5m},
    214                                 {INVALIDf,  PORT34_1STPTRf,  PORT34_LASTf, MMU_IPMC_GROUP_TBL5m},
    215                                 {INVALIDf,  PORT35_1STPTRf,  PORT35_LASTf, MMU_IPMC_GROUP_TBL5m},
    216                                 {INVALIDf,  PORT36_1STPTRf,  PORT36_LASTf, MMU_IPMC_GROUP_TBL5m},
    217                                 {INVALIDf,  PORT37_1STPTRf,  PORT37_LASTf, MMU_IPMC_GROUP_TBL6m},
    218                                 {INVALIDf,  PORT38_1STPTRf,  PORT38_LASTf, MMU_IPMC_GROUP_TBL6m},
    219                                 {INVALIDf,  PORT39_1STPTRf,  PORT39_LASTf, MMU_IPMC_GROUP_TBL6m},
    220                                 {INVALIDf,  PORT40_1STPTRf,  PORT40_LASTf, MMU_IPMC_GROUP_TBL6m},
    221                                 {INVALIDf,  PORT41_1STPTRf,  PORT41_LASTf, MMU_IPMC_GROUP_TBL6m},
    222                                 {INVALIDf,  PORT42_1STPTRf,  PORT42_LASTf, MMU_IPMC_GROUP_TBL6m},
    223                                 {INVALIDf,  PORT43_1STPTRf,  PORT43_LASTf, MMU_IPMC_GROUP_TBL7m},
    224                                 {INVALIDf,  PORT44_1STPTRf,  PORT44_LASTf, MMU_IPMC_GROUP_TBL7m},
    225                                 {INVALIDf,  PORT45_1STPTRf,  PORT45_LASTf, MMU_IPMC_GROUP_TBL7m},
    226                                 {INVALIDf,  PORT46_1STPTRf,  PORT46_LASTf, MMU_IPMC_GROUP_TBL7m},
    227                                 {INVALIDf,  PORT47_1STPTRf,  PORT47_LASTf, MMU_IPMC_GROUP_TBL7m},
    228                                 {INVALIDf,  PORT48_1STPTRf,  PORT48_LASTf, MMU_IPMC_GROUP_TBL7m},
    229                                 {INVALIDf,  PORT49_1STPTRf,  PORT49_LASTf, MMU_IPMC_GROUP_TBL8m},
    230                                 {INVALIDf,  PORT50_1STPTRf,  PORT50_LASTf, MMU_IPMC_GROUP_TBL8m},
    231                                 {INVALIDf,  PORT51_1STPTRf,  PORT51_LASTf, MMU_IPMC_GROUP_TBL8m},
    232                                 {INVALIDf,  PORT52_1STPTRf,  PORT52_LASTf, MMU_IPMC_GROUP_TBL8m},
    233                                 {INVALIDf,  PORT53_1STPTRf,  PORT53_LASTf, MMU_IPMC_GROUP_TBL8m},
    234 };
    235 
    236 #ifdef BCM_TRIDENT_SUPPORT
    237 static soc_mem_t _bcm_ipmc_trident_rep_regs[] = {
    238     INVALIDm,              MMU_IPMC_GROUP_TBL1m,
    239     MMU_IPMC_GROUP_TBL2m,  MMU_IPMC_GROUP_TBL3m,
    240     MMU_IPMC_GROUP_TBL4m,  MMU_IPMC_GROUP_TBL5m,
    241     MMU_IPMC_GROUP_TBL6m,  MMU_IPMC_GROUP_TBL7m,
    242     MMU_IPMC_GROUP_TBL8m,  MMU_IPMC_GROUP_TBL9m,
    243     MMU_IPMC_GROUP_TBL10m, MMU_IPMC_GROUP_TBL11m,
    244     MMU_IPMC_GROUP_TBL12m, MMU_IPMC_GROUP_TBL13m,
    245     MMU_IPMC_GROUP_TBL14m, MMU_IPMC_GROUP_TBL15m,
    246     MMU_IPMC_GROUP_TBL16m, MMU_IPMC_GROUP_TBL17m,
    247     MMU_IPMC_GROUP_TBL18m, MMU_IPMC_GROUP_TBL19m,
    248     MMU_IPMC_GROUP_TBL20m, MMU_IPMC_GROUP_TBL21m,
    249     MMU_IPMC_GROUP_TBL22m, MMU_IPMC_GROUP_TBL23m,
    250     MMU_IPMC_GROUP_TBL24m, MMU_IPMC_GROUP_TBL25m,
    251     MMU_IPMC_GROUP_TBL26m, MMU_IPMC_GROUP_TBL27m,
    252     MMU_IPMC_GROUP_TBL28m, MMU_IPMC_GROUP_TBL29m,
    253     MMU_IPMC_GROUP_TBL30m, MMU_IPMC_GROUP_TBL31m,
    254     MMU_IPMC_GROUP_TBL32m, MMU_IPMC_GROUP_TBL33m,
    255     MMU_IPMC_GROUP_TBL34m, MMU_IPMC_GROUP_TBL35m,
    256     MMU_IPMC_GROUP_TBL36m, MMU_IPMC_GROUP_TBL37m,
    257     MMU_IPMC_GROUP_TBL38m, MMU_IPMC_GROUP_TBL39m,
    258     MMU_IPMC_GROUP_TBL40m, MMU_IPMC_GROUP_TBL41m,
    259     MMU_IPMC_GROUP_TBL42m, MMU_IPMC_GROUP_TBL43m,
    260     MMU_IPMC_GROUP_TBL44m, MMU_IPMC_GROUP_TBL45m,
    261     MMU_IPMC_GROUP_TBL46m, MMU_IPMC_GROUP_TBL47m,
    262     MMU_IPMC_GROUP_TBL48m, MMU_IPMC_GROUP_TBL49m,
    263     MMU_IPMC_GROUP_TBL50m, MMU_IPMC_GROUP_TBL51m,
    264     MMU_IPMC_GROUP_TBL52m, MMU_IPMC_GROUP_TBL53m,
    265     MMU_IPMC_GROUP_TBL54m, MMU_IPMC_GROUP_TBL55m,
    266     MMU_IPMC_GROUP_TBL56m, MMU_IPMC_GROUP_TBL57m,
    267     MMU_IPMC_GROUP_TBL58m, MMU_IPMC_GROUP_TBL59m,
    268     MMU_IPMC_GROUP_TBL60m, MMU_IPMC_GROUP_TBL61m,
    269     MMU_IPMC_GROUP_TBL62m, MMU_IPMC_GROUP_TBL63m,
    270     MMU_IPMC_GROUP_TBL64m, MMU_IPMC_GROUP_TBL65m
    271 };
    272 #endif /* BCM_TRIDENT_SUPPORT */
    273 
    274 #ifdef BCM_KATANA_SUPPORT
    275 _rep_regs_t kt_rqe_rep_regs[] = { 
    276     {INVALIDf,         INVALIDf,       INVALIDf,    INVALIDm},
    277     {PORT1_PTR_TYPEf,  PORT1_1STPTRf,  PORT1_LASTf, MMU_IPMC_GROUP_TBL0m},
    278     {PORT2_PTR_TYPEf,  PORT2_1STPTRf,  PORT2_LASTf, MMU_IPMC_GROUP_TBL0m},
    279     {PORT3_PTR_TYPEf,  PORT3_1STPTRf,  PORT3_LASTf, MMU_IPMC_GROUP_TBL0m},
    280     {PORT4_PTR_TYPEf,  PORT4_1STPTRf,  PORT4_LASTf, MMU_IPMC_GROUP_TBL0m},
    281     {PORT5_PTR_TYPEf,  PORT5_1STPTRf,  PORT5_LASTf, MMU_IPMC_GROUP_TBL0m},
    282     {PORT6_PTR_TYPEf,  PORT6_1STPTRf,  PORT6_LASTf, MMU_IPMC_GROUP_TBL0m},
    283     {PORT7_PTR_TYPEf,  PORT7_1STPTRf,  PORT7_LASTf, MMU_IPMC_GROUP_TBL0m},
    284     {PORT8_PTR_TYPEf,  PORT8_1STPTRf,  PORT8_LASTf, MMU_IPMC_GROUP_TBL1m},
    285     {PORT9_PTR_TYPEf,  PORT9_1STPTRf,  PORT9_LASTf, MMU_IPMC_GROUP_TBL1m},
    286     {PORT10_PTR_TYPEf,  PORT10_1STPTRf,  PORT10_LASTf, MMU_IPMC_GROUP_TBL1m},
    287     {PORT11_PTR_TYPEf,  PORT11_1STPTRf,  PORT11_LASTf, MMU_IPMC_GROUP_TBL1m},
    288     {PORT12_PTR_TYPEf,  PORT12_1STPTRf,  PORT12_LASTf, MMU_IPMC_GROUP_TBL1m},
    289     {PORT13_PTR_TYPEf,  PORT13_1STPTRf,  PORT13_LASTf, MMU_IPMC_GROUP_TBL1m},
    290     {PORT14_PTR_TYPEf,  PORT14_1STPTRf,  PORT14_LASTf, MMU_IPMC_GROUP_TBL1m},
    291     {PORT15_PTR_TYPEf,  PORT15_1STPTRf,  PORT15_LASTf, MMU_IPMC_GROUP_TBL2m},
    292     {PORT16_PTR_TYPEf,  PORT16_1STPTRf,  PORT16_LASTf, MMU_IPMC_GROUP_TBL2m},
    293     {PORT17_PTR_TYPEf,  PORT17_1STPTRf,  PORT17_LASTf, MMU_IPMC_GROUP_TBL2m},
    294     {PORT18_PTR_TYPEf,  PORT18_1STPTRf,  PORT18_LASTf, MMU_IPMC_GROUP_TBL2m},
    295     {PORT19_PTR_TYPEf,  PORT19_1STPTRf,  PORT19_LASTf, MMU_IPMC_GROUP_TBL2m},
    296     {PORT20_PTR_TYPEf,  PORT20_1STPTRf,  PORT20_LASTf, MMU_IPMC_GROUP_TBL2m},
    297     {PORT21_PTR_TYPEf,  PORT21_1STPTRf,  PORT21_LASTf, MMU_IPMC_GROUP_TBL2m},
    298     {PORT22_PTR_TYPEf,  PORT22_1STPTRf,  PORT22_LASTf, MMU_IPMC_GROUP_TBL3m},
    299     {PORT23_PTR_TYPEf,  PORT23_1STPTRf,  PORT23_LASTf, MMU_IPMC_GROUP_TBL3m},
    300     {PORT24_PTR_TYPEf,  PORT24_1STPTRf,  PORT24_LASTf, MMU_IPMC_GROUP_TBL3m},
    301     {PORT25_PTR_TYPEf,  PORT25_1STPTRf,  PORT25_LASTf, MMU_IPMC_GROUP_TBL3m},
    302     {PORT26_PTR_TYPEf,  PORT26_1STPTRf,  PORT26_LASTf, MMU_IPMC_GROUP_TBL3m},
    303     {PORT27_PTR_TYPEf,  PORT27_1STPTRf,  PORT27_LASTf, MMU_IPMC_GROUP_TBL3m},
    304     {PORT28_PTR_TYPEf,  PORT28_1STPTRf,  PORT28_LASTf, MMU_IPMC_GROUP_TBL3m},
    305     {PORT29_PTR_TYPEf,  PORT29_1STPTRf,  PORT29_LASTf, MMU_IPMC_GROUP_TBL4m},
    306     {PORT30_PTR_TYPEf,  PORT30_1STPTRf,  PORT30_LASTf, MMU_IPMC_GROUP_TBL4m},
    307     {PORT31_PTR_TYPEf,  PORT31_1STPTRf,  PORT31_LASTf, MMU_IPMC_GROUP_TBL4m},
    308     {PORT32_PTR_TYPEf,  PORT32_1STPTRf,  PORT32_LASTf, MMU_IPMC_GROUP_TBL4m},
    309     {PORT33_PTR_TYPEf,  PORT33_1STPTRf,  PORT33_LASTf, MMU_IPMC_GROUP_TBL4m},
    310     {PORT34_PTR_TYPEf,  PORT34_1STPTRf,  PORT34_LASTf, MMU_IPMC_GROUP_TBL4m},
    311     {PORT35_PTR_TYPEf,  PORT35_1STPTRf,  PORT35_LASTf, MMU_IPMC_GROUP_TBL4m},
    312 };
    313 
    314 _rep_regs_t kt_toq_rep_regs[] = { 
    315     {INVALIDf,         INVALIDf,       INVALIDf,    INVALIDm},
    316     {PORT1_PTR_TYPEf,  PORT1_1STPTRf,  PORT1_LASTf, MMU_TOQ_IPMC_GROUP_TBL0m},
    317     {PORT2_PTR_TYPEf,  PORT2_1STPTRf,  PORT2_LASTf, MMU_TOQ_IPMC_GROUP_TBL0m},
    318     {PORT3_PTR_TYPEf,  PORT3_1STPTRf,  PORT3_LASTf, MMU_TOQ_IPMC_GROUP_TBL0m},
    319     {PORT4_PTR_TYPEf,  PORT4_1STPTRf,  PORT4_LASTf, MMU_TOQ_IPMC_GROUP_TBL0m},
    320     {PORT5_PTR_TYPEf,  PORT5_1STPTRf,  PORT5_LASTf, MMU_TOQ_IPMC_GROUP_TBL0m},
    321     {PORT6_PTR_TYPEf,  PORT6_1STPTRf,  PORT6_LASTf, MMU_TOQ_IPMC_GROUP_TBL1m},
    322     {PORT7_PTR_TYPEf,  PORT7_1STPTRf,  PORT7_LASTf, MMU_TOQ_IPMC_GROUP_TBL1m},
    323     {PORT8_PTR_TYPEf,  PORT8_1STPTRf,  PORT8_LASTf, MMU_TOQ_IPMC_GROUP_TBL1m},
    324     {PORT9_PTR_TYPEf,  PORT9_1STPTRf,  PORT9_LASTf, MMU_TOQ_IPMC_GROUP_TBL1m},
    325     {PORT10_PTR_TYPEf,  PORT10_1STPTRf,  PORT10_LASTf, MMU_TOQ_IPMC_GROUP_TBL1m},
    326     {PORT11_PTR_TYPEf,  PORT11_1STPTRf,  PORT11_LASTf, MMU_TOQ_IPMC_GROUP_TBL2m},
    327     {PORT12_PTR_TYPEf,  PORT12_1STPTRf,  PORT12_LASTf, MMU_TOQ_IPMC_GROUP_TBL2m},
    328     {PORT13_PTR_TYPEf,  PORT13_1STPTRf,  PORT13_LASTf, MMU_TOQ_IPMC_GROUP_TBL2m},
    329     {PORT14_PTR_TYPEf,  PORT14_1STPTRf,  PORT14_LASTf, MMU_TOQ_IPMC_GROUP_TBL2m},
    330     {PORT15_PTR_TYPEf,  PORT15_1STPTRf,  PORT15_LASTf, MMU_TOQ_IPMC_GROUP_TBL2m},
    331     {PORT16_PTR_TYPEf,  PORT16_1STPTRf,  PORT16_LASTf, MMU_TOQ_IPMC_GROUP_TBL3m},
    332     {PORT17_PTR_TYPEf,  PORT17_1STPTRf,  PORT17_LASTf, MMU_TOQ_IPMC_GROUP_TBL3m},
    333     {PORT18_PTR_TYPEf,  PORT18_1STPTRf,  PORT18_LASTf, MMU_TOQ_IPMC_GROUP_TBL3m},
    334     {PORT19_PTR_TYPEf,  PORT19_1STPTRf,  PORT19_LASTf, MMU_TOQ_IPMC_GROUP_TBL3m},
    335     {PORT20_PTR_TYPEf,  PORT20_1STPTRf,  PORT20_LASTf, MMU_TOQ_IPMC_GROUP_TBL3m},
    336     {PORT21_PTR_TYPEf,  PORT21_1STPTRf,  PORT21_LASTf, MMU_TOQ_IPMC_GROUP_TBL4m},
    337     {PORT22_PTR_TYPEf,  PORT22_1STPTRf,  PORT22_LASTf, MMU_TOQ_IPMC_GROUP_TBL4m},
    338     {PORT23_PTR_TYPEf,  PORT23_1STPTRf,  PORT23_LASTf, MMU_TOQ_IPMC_GROUP_TBL4m},
    339     {PORT24_PTR_TYPEf,  PORT24_1STPTRf,  PORT24_LASTf, MMU_TOQ_IPMC_GROUP_TBL4m},
    340     {PORT25_PTR_TYPEf,  PORT25_1STPTRf,  PORT25_LASTf, MMU_TOQ_IPMC_GROUP_TBL4m},
    341     {PORT26_PTR_TYPEf,  PORT26_1STPTRf,  PORT26_LASTf, MMU_TOQ_IPMC_GROUP_TBL5m},
    342     {PORT27_PTR_TYPEf,  PORT27_1STPTRf,  PORT27_LASTf, MMU_TOQ_IPMC_GROUP_TBL5m},
    343     {PORT28_PTR_TYPEf,  PORT28_1STPTRf,  PORT28_LASTf, MMU_TOQ_IPMC_GROUP_TBL5m},
    344     {PORT29_PTR_TYPEf,  PORT29_1STPTRf,  PORT29_LASTf, MMU_TOQ_IPMC_GROUP_TBL5m},
    345     {PORT30_PTR_TYPEf,  PORT30_1STPTRf,  PORT30_LASTf, MMU_TOQ_IPMC_GROUP_TBL5m},
    346     {PORT31_PTR_TYPEf,  PORT31_1STPTRf,  PORT31_LASTf, MMU_TOQ_IPMC_GROUP_TBL6m},
    347     {PORT32_PTR_TYPEf,  PORT32_1STPTRf,  PORT32_LASTf, MMU_TOQ_IPMC_GROUP_TBL6m},
    348     {PORT33_PTR_TYPEf,  PORT33_1STPTRf,  PORT33_LASTf, MMU_TOQ_IPMC_GROUP_TBL6m},
    349     {PORT34_PTR_TYPEf,  PORT34_1STPTRf,  PORT34_LASTf, MMU_TOQ_IPMC_GROUP_TBL6m},
    350     {PORT35_PTR_TYPEf,  PORT35_1STPTRf,  PORT35_LASTf, MMU_TOQ_IPMC_GROUP_TBL6m},
    351 };
    352 
    353 #ifdef BCM_KATANA_SUPPORT
    354 uint32 *sw_to_hw_queue[BCM_MAX_NUM_UNITS];
    355 #endif
    356 
    357 STATIC int
    358 _kt_ipmc_vlan_ptr(int unit,int mc_index,
    359                   bcm_port_t port, int *vptr, int last, int set)
    360 {
    361     soc_field_t  port_ptr = INVALIDf;
    362     soc_field_t  last_ptr = INVALIDf;
    363     soc_field_t  ptr_type = INVALIDf;
    364     soc_mem_t    rqe_mem = INVALIDm;
    365     soc_mem_t    toq_mem = INVALIDm;
    366     mmu_ipmc_group_tbl0_entry_t rqe_entry;
    367     mmu_toq_ipmc_group_tbl0_entry_t toq_entry;
    368     int rv;
    369     _rep_regs_t     *rqe_arr_ptr;
    370     _rep_regs_t     *toq_arr_ptr;
    371     int ipmc_ptr;
    372     int ipmc_id = 0;
    373 
    374     rqe_arr_ptr = kt_rqe_rep_regs;
    375     rqe_mem = rqe_arr_ptr[port].mem;
    376     toq_arr_ptr = kt_toq_rep_regs;
    377     toq_mem = toq_arr_ptr[port].mem;    
    378     
    379     port_ptr = rqe_arr_ptr[port].port_ptr;
    380     last_ptr = rqe_arr_ptr[port].last_ptr;
    381     ptr_type = rqe_arr_ptr[port].ptr_type;
    382 
    383     if ((INVALIDm == rqe_mem) || (INVALIDf == port_ptr)){
    384         return BCM_E_PARAM;
    385     }
    386 
    387     BCM_IF_ERROR_RETURN
    388     (_bcm_kt_ipmc_mmu_mc_remap_ptr(unit, mc_index, &ipmc_id, FALSE));
    389 
    390     soc_mem_lock(unit, rqe_mem);
    391 
    392     if ((rv = soc_mem_read(unit, rqe_mem, MEM_BLOCK_ALL, 
    393                            ipmc_id, &rqe_entry)) < 0) {
    394         soc_mem_unlock(unit, rqe_mem);
    395         return rv;
    396     }
    397 
    398     if (!SOC_MEM_IS_VALID(unit, toq_mem)) {
    399         if (set) {
    400             soc_mem_field32_set(unit, rqe_mem, &rqe_entry, port_ptr, *vptr);
    401             soc_mem_field32_set(unit, rqe_mem, &rqe_entry, last_ptr,last ? 1 : 0);
    402             if (INVALIDf != ptr_type) {
    403                 soc_mem_field32_set(unit, rqe_mem, &rqe_entry, ptr_type, 0);
    404             }
    405             if ((rv = soc_mem_write(unit, rqe_mem, MEM_BLOCK_ALL, ipmc_id, 
    406                                     &rqe_entry)) < 0) {
    407                 soc_mem_unlock(unit, rqe_mem);
    408                 return rv;
    409             }
    410         } else {
    411             *vptr =  soc_mem_field32_get(unit, rqe_mem, &rqe_entry, port_ptr);
    412         }
    413     } else {
    414         if ((rv = soc_mem_read(unit, toq_mem, MEM_BLOCK_ALL, 
    415                                ipmc_id, &toq_entry)) < 0) {
    416             soc_mem_unlock(unit, rqe_mem);
    417             return rv;
    418         }
    419         
    420         if (set) {
    421             /* encode port_ptr as { 2'b01, MC_INDEX[11:0] } */
    422             ipmc_ptr = (ipmc_id & 0xFFF) | (0x1 << 12);
    423             soc_mem_field32_set(unit, rqe_mem, &rqe_entry, port_ptr, ipmc_ptr);
    424             soc_mem_field32_set(unit, rqe_mem, &rqe_entry, last_ptr, last ? 1 : 0);
    425             if (INVALIDf != ptr_type) {
    426                 soc_mem_field32_set(unit, rqe_mem, &rqe_entry, ptr_type, 0);
    427             }
    428             port_ptr = toq_arr_ptr[port].port_ptr;
    429             last_ptr = toq_arr_ptr[port].last_ptr;
    430             ptr_type = toq_arr_ptr[port].ptr_type;
    431             soc_mem_field32_set(unit, toq_mem, &toq_entry, port_ptr, *vptr);
    432             if (!soc_feature(unit, soc_feature_ipmc_reduced_table_size)) {
    433                 soc_mem_field32_set(unit, toq_mem, &toq_entry, last_ptr, 
    434                                     last ? 1 : 0);
    435             } else {
    436                 soc_mem_field32_set(unit, toq_mem, &toq_entry, last_ptr, 0);
    437             }
    438             if (INVALIDf != ptr_type) {
    439                 soc_mem_field32_set(unit, toq_mem, &toq_entry, ptr_type, 0);
    440             }    
    441             if ((rv = soc_mem_write(unit, toq_mem, MEM_BLOCK_ALL, ipmc_id, 
    442                                     &toq_entry)) < 0) {
    443                 soc_mem_unlock(unit, rqe_mem);
    444                 return rv;
    445             }
    446             if (soc_feature(unit, soc_feature_ipmc_reduced_table_size)) {
    447                 /* set port ptr = start vlan_ptr at index of start vlan ptr */
    448                 if ((rv = soc_mem_read(unit, toq_mem, MEM_BLOCK_ALL, 
    449                                        *vptr, &toq_entry)) < 0) {
    450                     soc_mem_unlock(unit, rqe_mem);
    451                     return rv;
    452                 }	
    453                 port_ptr = toq_arr_ptr[port].port_ptr;
    454                 soc_mem_field32_set(unit, toq_mem, &toq_entry, port_ptr, *vptr);
    455                 if ((rv = soc_mem_write(unit, toq_mem, MEM_BLOCK_ALL, *vptr, 
    456                                         &toq_entry)) < 0) {
    457                     soc_mem_unlock(unit, rqe_mem);
    458                     return rv;
    459                 }
    460             }
    461             if ((rv = soc_mem_write(unit, rqe_mem, MEM_BLOCK_ALL, ipmc_id, 
    462                                     &rqe_entry)) < 0) {
    463                 soc_mem_unlock(unit, rqe_mem);
    464                 return rv;
    465             }
    466         } else {
    467             port_ptr = toq_arr_ptr[port].port_ptr;
    468             *vptr =  soc_mem_field32_get(unit, toq_mem, &toq_entry, port_ptr);
    469         }    
    470     }
    471     soc_mem_unlock(unit, rqe_mem);
    472 
    473     return BCM_E_NONE;
    474 }
    475 
    476 STATIC int
    477 _kt_ipmc_group_entry_clear(int unit, int start_ptr)
    478 {
    479     soc_mem_t    toq_mem = INVALIDm;
    480     mmu_toq_ipmc_group_tbl0_entry_t toq_entry;
    481     int rv;
    482     _rep_regs_t     *toq_arr_ptr;
    483     bcm_port_t port;
    484 
    485     toq_arr_ptr = kt_toq_rep_regs;
    486     sal_memset(&toq_entry, 0, sizeof(toq_entry));
    487 	
    488     for (port = 0; port < 36; port++) {
    489         if (toq_mem != toq_arr_ptr[port].mem) {
    490             toq_mem = toq_arr_ptr[port].mem;
    491             soc_mem_lock(unit, toq_mem);
    492             if ((rv = soc_mem_write(unit, toq_mem, MEM_BLOCK_ALL, start_ptr, 
    493                                     &toq_entry)) < 0) {
    494                 soc_mem_unlock(unit, toq_mem);
    495                 return rv;
    496             }
    497             soc_mem_unlock(unit, toq_mem);
    498         }
    499     }
    500 
    501     return BCM_E_NONE;
    502 }
    503 
    504 #endif
    505 
    506 STATIC int
    507 _tr2_ipmc_vlan_ptr(int unit,int ipmc_id,
    508                   bcm_port_t port, int *vptr, int last, int set)
    509 {
    510     soc_field_t  port_ptr = INVALIDf;
    511     soc_field_t  last_ptr = INVALIDf;
    512     soc_mem_t    mem = INVALIDm;
    513     mmu_ipmc_group_tbl0_entry_t gentry;
    514     int rv;
    515     _rep_regs_t     *rep_arr_ptr;
    516 
    517 #ifdef BCM_TRIDENT_SUPPORT
    518     if (SOC_IS_TRIDENT(unit)) {
    519         soc_info_t *si;
    520         bcm_port_t phy_port, mmu_port;
    521 
    522         /* Convert logical port to physical port to mmu port */
    523         si = &SOC_INFO(unit);
    524         phy_port = si->port_l2p_mapping[port];
    525         mmu_port = si->port_p2m_mapping[phy_port];
    526 
    527         mem = _bcm_ipmc_trident_rep_regs[mmu_port];
    528         port_ptr = PORT_1STPTRf;
    529         last_ptr = PORT_LASTf;
    530     } else 
    531 #endif /* BCM_TRIDENT_SUPPORT */
    532 #ifdef BCM_KATANA_SUPPORT
    533     if (SOC_IS_KATANAX(unit)) {
    534         return _kt_ipmc_vlan_ptr(unit, ipmc_id, port,
    535                                  vptr, last, set);
    536     } else 
    537 #endif /* BCM_KATANA_SUPPORT */
    538     {
    539         rep_arr_ptr = ch_rep_regs;
    540         mem = rep_arr_ptr[port].mem;
    541         port_ptr = rep_arr_ptr[port].port_ptr;
    542         last_ptr = rep_arr_ptr[port].last_ptr;
    543     }
    544 
    545     if ((INVALIDm == mem) || (INVALIDf == port_ptr)){
    546         return BCM_E_PARAM;
    547     }
    548 
    549     soc_mem_lock(unit, mem);
    550     if ((rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL, 
    551                            ipmc_id, &gentry)) < 0) {
    552         soc_mem_unlock(unit, mem);
    553         return rv;
    554     }
    555     if (set) {
    556         soc_mem_field32_set(unit, mem, &gentry, port_ptr, *vptr);
    557         soc_mem_field32_set(unit, mem, &gentry, last_ptr,last ? 1 : 0);
    558         if ((rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, ipmc_id, 
    559                                 &gentry)) < 0) {
    560             soc_mem_unlock(unit, mem);
    561             return rv;
    562         }
    563     } else {
    564         *vptr =  soc_mem_field32_get(unit, mem, &gentry, port_ptr);
    565     }
    566     soc_mem_unlock(unit, mem);
    567 
    568     return BCM_E_NONE;
    569 }
    570 
    571 
    572 #ifdef BCM_KATANA_SUPPORT
    573 
    574 STATIC int
    575 _kt_extq_mc_group_ptr(int unit,int ipmc_id,
    576                   int *extq_ptr, int last, int set)
    577 {
    578     int         rv = BCM_E_NONE;
    579     mmu_ext_mc_group_map_entry_t mc_group_entry;
    580     soc_mem_t mem = MMU_EXT_MC_GROUP_MAPm;
    581     int remap_id;
    582 
    583     soc_mem_lock(unit, mem);
    584     if ((rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL,
    585                           ipmc_id, &mc_group_entry)) < 0) {
    586        soc_mem_unlock(unit, mem);
    587        return rv;
    588     }
    589     
    590     if (set) {
    591        soc_mem_field32_set(unit, mem, &mc_group_entry, 
    592                            EXT_Q_FIRST_PTRf, *extq_ptr);
    593        soc_mem_field32_set(unit, mem, &mc_group_entry, 
    594                            EXT_Q_LAST_LASTf, last ? 1 : 0);
    595 
    596        if ((rv = _bcm_kt_ipmc_mmu_mc_remap_ptr(unit, 0, 
    597                        &remap_id, FALSE)) < 0) {
    598             soc_mem_unlock(unit, mem);
    599             return rv;                
    600        }
    601        /* update the new chain in the remapped id */
    602        if ((rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, remap_id,
    603                                 &mc_group_entry)) < 0) {
    604             soc_mem_unlock(unit, mem);
    605             return rv;
    606         }
    607        
    608     } else {
    609         *extq_ptr = soc_mem_field32_get(unit, mem, &mc_group_entry, 
    610                                            EXT_Q_FIRST_PTRf);
    611     }
    612     soc_mem_unlock(unit, mem);
    613     
    614     return rv;
    615 }
    616 
    617 /*
    618  * Function:
    619  *    _bcm_kt_extq_repl_list_compare
    620  * Description:
    621  *    Compare HW list starting at extq_index to the queue list contained
    622  *      in vlan_vec.
    623  */
    624 
    625 STATIC int
    626 _bcm_kt_extq_repl_list_compare(int unit, int extq_ptr,
    627                                SHR_BITDCL *q_vec, 
    628                                uint32 *q_repl_ptr)
    629 {
    630     int             rv = BCM_E_NONE;
    631     int             q_num, q_max, ptr_alloc_size;
    632     int             vec_alloc_size;
    633     uint32          *curr_repl_ptr = NULL;
    634     SHR_BITDCL      *curr_vec = NULL;
    635 
    636     q_max = IPMC_EXTQ_TOTAL(unit);
    637     ptr_alloc_size = q_max * sizeof(int);
    638     curr_repl_ptr = sal_alloc(ptr_alloc_size, "IPMC repl interface array");
    639     if (curr_repl_ptr == NULL) {
    640         return BCM_E_MEMORY;
    641     }
    642     sal_memset(curr_repl_ptr, 0, ptr_alloc_size);
    643 
    644     vec_alloc_size = SHR_BITALLOCSIZE(IPMC_EXTQ_TOTAL(unit));
    645     curr_vec = sal_alloc(vec_alloc_size, "IPMC extq replication vector");
    646     if (curr_vec == NULL) {
    647         sal_free(curr_repl_ptr);
    648         return BCM_E_MEMORY;
    649     }
    650     sal_memset(curr_vec, 0, vec_alloc_size);    
    651 
    652     if (extq_ptr != 0) {
    653         rv = _bcm_kt_get_subscriber_queue_entries(unit, extq_ptr, curr_vec, 
    654                                                   curr_repl_ptr, &q_num);
    655     }
    656 
    657     if (sal_memcmp(q_vec, curr_vec, vec_alloc_size) != 0) {
    658         rv = BCM_E_NOT_FOUND;
    659         goto list_compare_done;
    660     }
    661 
    662     if (sal_memcmp(q_repl_ptr, curr_repl_ptr, ptr_alloc_size) != 0) {
    663         rv = BCM_E_NOT_FOUND;
    664         goto list_compare_done;
    665     }
    666 
    667 list_compare_done:
    668     sal_free(curr_repl_ptr);
    669     sal_free(curr_vec);
    670     return rv;
    671 }
    672 
    673 #endif
    674 
    675 #ifdef BCM_WARM_BOOT_SUPPORT
    676 
    677 #ifdef BCM_KATANA_SUPPORT
    678 
    679 STATIC int
    680 _bcm_kt_extq_repl_list_get(int unit, int extq_ptr,
    681                            int *list_ptr, 
    682                            int *list_num)
    683 {
    684     int     rv = BCM_E_NONE;
    685     int     next_ptr1, next_ptr2;
    686     mmu_ext_mc_queue_list4_entry_t     qlist4_entry;
    687     
    688     if ((rv = READ_MMU_EXT_MC_QUEUE_LIST4m(unit, MEM_BLOCK_ANY,
    689                                     extq_ptr, &qlist4_entry)) < 0) {
    690         goto repl_list_get_done;
    691     }
    692 
    693     next_ptr1 = soc_MMU_EXT_MC_QUEUE_LIST4m_field32_get(unit, 
    694                                      &qlist4_entry, EXT_Q_NXT_PTR1f);
    695     next_ptr2 = soc_MMU_EXT_MC_QUEUE_LIST4m_field32_get(unit, 
    696                                      &qlist4_entry, EXT_Q_NXT_PTR2f);
    697     IPMC_EXTQ_REPL_VE_USED_SET(unit, extq_ptr);
    698     list_ptr[*list_num] = extq_ptr;
    699     (*list_num)++;
    700     
    701     if (next_ptr1 != extq_ptr) {
    702         if ((rv = _bcm_kt_extq_repl_list_get(unit, next_ptr1, list_ptr, 
    703              list_num)) < 0) {
    704             goto repl_list_get_done;   
    705         }                                                    
    706     } 
    707            
    708     if (next_ptr2 != extq_ptr) {
    709         if ((rv = _bcm_kt_extq_repl_list_get(unit, next_ptr2, list_ptr,
    710              list_num)) < 0) {  
    711             goto repl_list_get_done; 
    712         }                                                
    713     }
    714 
    715 repl_list_get_done:
    716     return rv;
    717 
    718 }
    719 
    720 STATIC int
    721 _bcm_kt_extq_repl_reload(int unit, int ipmc_id) 
    722 {
    723     SHR_BITDCL *q_vec = NULL;
    724     uint32 *q_repl_ptr = NULL;
    725     int *extq_list_ptr;
    726     int q_max, q_num = 0;
    727     int list_max, list_num = 0;
    728     int alloc_size;
    729     int rv = BCM_E_NONE;
    730     int extq_ptr, extq_hash; 
    731     _bcm_repl_list_info_t *rli_start, *rli_current;
    732     int list_start_ptr, remap_id;
    733     int queue_count = 0;
    734     int list_size = 0;
    735     int queue_id, count = 0;
    736     bcm_port_t port;
    737 
    738     if ((rv = _bcm_kt_ipmc_mmu_mc_remap_ptr(unit, ipmc_id, 
    739                     &remap_id, FALSE)) < 0) {
    740          return rv;                
    741     }
    742 
    743     if ((rv = _kt_extq_mc_group_ptr(unit, remap_id,
    744                                 &extq_ptr, 0, 0)) < 0) {
    745         return rv;
    746     }
    747 
    748     if (extq_ptr == 0) {
    749         return rv;
    750     }
    751 
    752     rli_start = IPMC_EXTQ_REPL_LIST_INFO(unit);
    753     if (IPMC_EXTQ_REPL_VE_USED_GET(unit, extq_ptr)) {
    754         /* We've already traversed this list, just note it */
    755         for (rli_current = rli_start; rli_current != NULL;
    756              rli_current = rli_current->next) {
    757             if (rli_current->index == extq_ptr) {
    758                 (rli_current->refcount)++;
    759                 IPMC_EXTQ_REPL_QUEUE_COUNT(unit, ipmc_id) =
    760                     rli_current->list_size;
    761                 break;
    762             }
    763         }
    764         if (rli_current == NULL) {
    765             /* Table out of sync.  Not good. */
    766             bcm_kt_ipmc_repl_detach(unit);
    767             return BCM_E_INTERNAL;
    768         } else {
    769             return rv;
    770         }
    771     }
    772 
    773     list_max = IPMC_EXTQ_LIST_TOTAL(unit);
    774     alloc_size = list_max * sizeof(int);
    775     extq_list_ptr = sal_alloc(alloc_size, "IPMC extq list array");
    776     if (extq_list_ptr == NULL) {
    777         return BCM_E_MEMORY;
    778     }    
    779     sal_memset(extq_list_ptr, 0, alloc_size);
    780     if ((rv = _bcm_kt_extq_repl_list_get(unit, extq_ptr, extq_list_ptr, 
    781                                          &list_num)) < 0 ) {
    782         goto reload_done;
    783     }    
    784         
    785     q_max = IPMC_EXTQ_TOTAL(unit);
    786     alloc_size = q_max * sizeof(int);
    787     q_repl_ptr = sal_alloc(alloc_size, "IPMC repl interface array");
    788     if (q_repl_ptr == NULL) {
    789         return BCM_E_MEMORY;
    790     }
    791     sal_memset(q_repl_ptr, 0, alloc_size);
    792 
    793     alloc_size = SHR_BITALLOCSIZE(IPMC_EXTQ_TOTAL(unit));
    794     q_vec = sal_alloc(alloc_size, "IPMC extq replication vector");
    795     if (q_vec == NULL) {
    796         sal_free(q_repl_ptr);
    797         return BCM_E_MEMORY;
    798     }
    799     sal_memset(q_vec, 0, alloc_size);
    800 
    801     if ((rv = _bcm_kt_get_subscriber_queue_entries(unit, extq_ptr, q_vec, 
    802                                                   q_repl_ptr, &q_num)) < 0 ) {
    803         goto reload_done;
    804     }
    805     
    806     if (q_num > q_max) {
    807         rv = BCM_E_PARAM;
    808         goto reload_done;
    809     }
    810 
    811     /* Search for list already in table */
    812     extq_hash =
    813         _shr_crc32b(0, (uint8 *)q_vec, IPMC_EXTQ_TOTAL(unit));
    814 
    815     for (rli_current = rli_start; rli_current != NULL;
    816          rli_current = rli_current->next) {
    817          if (extq_hash == rli_current->hash) {
    818              rv = _bcm_kt_extq_repl_list_compare(unit, rli_current->index,
    819                                              q_vec, q_repl_ptr);
    820              if (rv == BCM_E_NOT_FOUND) {
    821                  continue; /* Not a match */
    822              } else if (rv < 0) {
    823                  goto reload_done; /* Access error */
    824              } else {
    825                  break; /* Match */
    826              }
    827         }
    828     }
    829 
    830     if (rli_current != NULL) {
    831         /* Found a match, point to here and increase reference count */
    832         if (extq_ptr == rli_current->index) {
    833             /* We're already pointing to this list, so done */
    834             rv = BCM_E_NONE;
    835             goto reload_done;
    836         } else {
    837             list_start_ptr = rli_current->index;
    838             queue_count = rli_current->list_size;
    839         }
    840     } else {
    841         /* Not a match, make a new chain */
    842         list_start_ptr = extq_ptr;
    843         list_size = (q_num % 4) ? ((q_num / 4) + 1) : (q_num / 4);
    844         queue_count = q_num;
    845 
    846         if (queue_count > 0) {
    847             /* Update data structures */
    848             alloc_size = sizeof(_bcm_repl_list_info_t);
    849             rli_current = sal_alloc(alloc_size, "IPMC extq repl list info");
    850             if (rli_current == NULL) {
    851                 rv = BCM_E_MEMORY;
    852                 goto reload_done;
    853             }
    854             sal_memset(rli_current, 0, alloc_size);
    855             rli_current->index = list_start_ptr;
    856             rli_current->hash = extq_hash;
    857             rli_current->next = rli_start;
    858             rli_current->list_size = list_size;
    859             IPMC_EXTQ_REPL_LIST_INFO(unit) = rli_current;
    860             rli_start = rli_current;
    861             (rli_current->refcount)++;
    862 
    863         }
    864     }
    865 
    866     IPMC_EXTQ_REPL_QUEUE_COUNT(unit, ipmc_id) = list_size;
    867 
    868     count = 0;
    869     for (queue_id = 0; ((queue_id < q_max) && (count < queue_count));
    870         queue_id++) {
    871         if (SHR_BITGET(q_vec, queue_id)) {
    872             count++;
    873 #ifdef BCM_KATANA2_SUPPORT
    874             if (SOC_IS_KATANA2(unit)) {
    875                 if ((rv = bcm_kt2_cosq_port_get(unit, queue_id, &port)) < 0) {
    876                     goto reload_done;
    877                 }
    878             } else 
    879 
    880 #endif
    881             {  
    882                 if ((rv = bcm_kt_cosq_port_get(unit, queue_id, &port)) < 0) {
    883                     goto reload_done;
    884                 }
    885             }
    886 
    887             if (SOC_PORT_VALID(unit, port)) {
    888                 _bcm_kt_ipmc_port_ext_queue_count_increment(unit, ipmc_id,
    889                                                             port);
    890             }
    891         }
    892     }
    893 
    894 reload_done:
    895     if (extq_list_ptr != NULL) {
    896         sal_free(extq_list_ptr);
    897     }    
    898     if (q_repl_ptr != NULL) {
    899         sal_free(q_repl_ptr);
    900     }
    901     if (q_vec != NULL) {
    902         sal_free(q_vec);
    903     }
    904 
    905     return rv; 
    906 }
    907 #endif
    908 
    909 #ifdef BCM_KATANA2_SUPPORT
    910 /*
    911  * Function:
    912  *      _bcm_kt2_extq_repl_reload
    913  * Purpose:
    914  *      Re-Initialize IPMC extq replication software to state consistent with
    915  *      hardware
    916  * Parameters:
    917  *      unit     - SOC unit #
    918  * Returns:
    919  *      BCM_E_XXX
    920  */
    921 int
    922 _bcm_kt2_extq_repl_reload(int unit)
    923 {
    924     bcm_port_t port;
    925     int ipmc_id, alloc_size;
    926     int rv;
    927     bcm_pbmp_t            pbmp_all;
    928 
    929     BCM_PBMP_CLEAR(pbmp_all);
    930     BCM_PBMP_ASSIGN(pbmp_all, PBMP_ALL(unit));
    931 
    932     if (soc_feature(unit, soc_feature_linkphy_coe) ||
    933         soc_feature(unit, soc_feature_subtag_coe)) {
    934         _bcm_kt2_subport_pbmp_update(unit, &pbmp_all);
    935     }
    936     BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update (unit, &pbmp_all));
    937 
    938     /* Allocate struct for IPMC Extq replication bookkeeping */
    939     alloc_size = sizeof(_kt_extq_repl_info_t);
    940     _kt_extq_repl_info[unit] = sal_alloc(alloc_size, "IPMC Extq repl info");
    941     if (_kt_extq_repl_info[unit] == NULL) {
    942         return BCM_E_MEMORY;
    943     }
    944     sal_memset(_kt_extq_repl_info[unit], 0, alloc_size);
    945     _kt_extq_repl_info[unit]->ipmc_size = soc_mem_index_count(unit, L3_IPMCm);
    946 
    947     IPMC_EXTQ_REPL_MAX(unit) = (1 << soc_mem_field_length(unit, L3_IPMCm,
    948                                 EXT_Q_NUM_COPIESf)) - 1;
    949     IPMC_EXTQ_TOTAL(unit) = 4096;
    950     IPMC_EXTQ_LIST_TOTAL(unit) = soc_mem_index_count(unit, MMU_EXT_MC_QUEUE_LIST0m);
    951     alloc_size = SHR_BITALLOCSIZE(IPMC_EXTQ_LIST_TOTAL(unit));
    952     _kt_extq_repl_info[unit]->bitmap_entries_used =
    953     sal_alloc(alloc_size, "IPMC Extq repl entries used");
    954     if (_kt_extq_repl_info[unit]->bitmap_entries_used == NULL) {
    955         bcm_kt_ipmc_repl_detach(unit);
    956         return BCM_E_MEMORY;
    957     }
    958     sal_memset(_kt_extq_repl_info[unit]->bitmap_entries_used, 0, alloc_size);
    959 
    960     /* Always reserve slot 0 */
    961     IPMC_EXTQ_REPL_VE_USED_SET(unit, 0);
    962 
    963     alloc_size = sizeof(_kt_repl_queue_info_t);
    964     _kt_extq_repl_info[unit]->mcgroup_info =
    965         sal_alloc(alloc_size, "IPMC MC group info");
    966     if (_kt_extq_repl_info[unit]->mcgroup_info == NULL) {
    967         bcm_kt_ipmc_repl_detach(unit);
    968         return BCM_E_MEMORY;
    969     }
    970     sal_memset(_kt_extq_repl_info[unit]->mcgroup_info, 0, alloc_size);
    971 
    972     alloc_size = sizeof(int32) * soc_mem_index_count(unit, L3_IPMCm);
    973     IPMC_EXTQ_GROUP_INFO(unit)->queue_count =
    974         sal_alloc(alloc_size, "IPMC Extq queue count");
    975     if (IPMC_EXTQ_GROUP_INFO(unit)->queue_count == NULL) {
    976         bcm_kt_ipmc_repl_detach(unit);
    977         return BCM_E_MEMORY;
    978     }
    979     sal_memset(IPMC_EXTQ_GROUP_INFO(unit)->queue_count,
    980                0, alloc_size);
    981 
    982     IPMC_EXTQ_GROUP_INFO(unit)->queue_count_int =
    983         sal_alloc(alloc_size, "IPMC Extq queue count internal");
    984     if (IPMC_EXTQ_GROUP_INFO(unit)->queue_count_int == NULL) {
    985         bcm_kt_ipmc_repl_detach(unit);
    986         return BCM_E_MEMORY;
    987     }
    988     sal_memset(IPMC_EXTQ_GROUP_INFO(unit)->queue_count_int,
    989             0, alloc_size);
    990 
    991     IPMC_EXTQ_GROUP_INFO(unit)->queue_count_ext =
    992         sal_alloc(alloc_size, "IPMC Extq queue count external");
    993     if (IPMC_EXTQ_GROUP_INFO(unit)->queue_count_ext == NULL) {
    994         bcm_kt_ipmc_repl_detach(unit);
    995         return BCM_E_MEMORY;
    996     }
    997     sal_memset(IPMC_EXTQ_GROUP_INFO(unit)->queue_count_ext,
    998             0, alloc_size);
    999 
   1000     PBMP_ITER(pbmp_all, port) {
   1001         alloc_size = sizeof(_kt_repl_queue_info_t);
   1002         IPMC_EXTQ_REPL_PORT_INFO(unit, port) =
   1003             sal_alloc(alloc_size, "IPMC Extq repl port info");
   1004         if (IPMC_EXTQ_REPL_PORT_INFO(unit, port) == NULL) {
   1005             bcm_kt_ipmc_repl_detach(unit);
   1006             return BCM_E_MEMORY;
   1007         }
   1008         sal_memset(IPMC_EXTQ_REPL_PORT_INFO(unit, port), 0, alloc_size);
   1009 
   1010         alloc_size = sizeof(int32) * soc_mem_index_count(unit, L3_IPMCm);
   1011         IPMC_EXTQ_REPL_PORT_INFO(unit, port)->queue_count =
   1012             sal_alloc(alloc_size, "IPMC Extq repl port queue count");
   1013         if (IPMC_EXTQ_REPL_PORT_INFO(unit, port)->queue_count == NULL) {
   1014             bcm_kt_ipmc_repl_detach(unit);
   1015             return BCM_E_MEMORY;
   1016         }
   1017         sal_memset(IPMC_EXTQ_REPL_PORT_INFO(unit, port)->queue_count,
   1018                    0, alloc_size);
   1019     }
   1020 
   1021     /* reserve ipmc index 0 & 1 for extended queue work around */
   1022     BCM_IF_ERROR_RETURN(bcm_xgs3_ipmc_id_alloc(unit, 0));
   1023     BCM_IF_ERROR_RETURN(bcm_xgs3_ipmc_id_alloc(unit, 1));
   1024     /*
   1025      * Read IPMC group and IPMC VLAN tables to build up software state
   1026      */
   1027     for (ipmc_id = soc_mem_index_min(unit, L3_IPMCm);
   1028          ipmc_id <= soc_mem_index_max(unit, L3_IPMCm); ipmc_id++) {
   1029 #ifdef BCM_KATANA_SUPPORT
   1030         if (SOC_IS_KATANAX(unit)) {
   1031             if (ipmc_id > 1) {
   1032                 rv = _bcm_kt_extq_repl_reload(unit, ipmc_id);
   1033                 if (BCM_FAILURE(rv)) {
   1034                     bcm_kt_ipmc_repl_detach(unit);
   1035                     return rv;
   1036                 }
   1037             }
   1038         }
   1039 #endif
   1040     }
   1041     return BCM_E_NONE;
   1042 }
   1043 
   1044 #endif
   1045 
   1046 /*
   1047  * Function:
   1048  *      _bcm_tr2_ipmc_repl_reload
   1049  * Purpose:
   1050  *      Re-Initialize IPMC replication software to state consistent with
   1051  *      hardware
   1052  * Parameters:
   1053  *      unit     - SOC unit #
   1054  * Returns:
   1055  *      BCM_E_XXX
   1056  */
   1057 int
   1058 _bcm_tr2_ipmc_repl_reload(int unit)
   1059 {
   1060     mmu_ipmc_vlan_tbl_entry_t vlan_entry;
   1061     uint32 ms_bit, ls_bits[2];
   1062     bcm_port_t port;
   1063     int ipmc_id, alloc_size, intf_alloc_size;
   1064     int vlan_ptr, next_vlan_ptr, first_vlan_ptr;
   1065     SHR_BITDCL          *intf_vec = NULL;
   1066     _bcm_repl_list_info_t *rli_start, *rli_current;
   1067     uint8 flags;
   1068     int rv;
   1069 
   1070 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   1071     uint32 if_cnt = 0;
   1072     uint32 nh_offset = 0;
   1073     uint32 offset = 0;
   1074     uint32 ms_max = 0;
   1075 #endif
   1076 
   1077 #ifdef BCM_KATANA_SUPPORT
   1078     if (SOC_IS_KATANAX(unit)) {
   1079         bcm_kt_ipmc_repl_detach(unit);
   1080         if_cnt = soc_mem_index_count(unit, EGR_L3_INTFm);
   1081         /* coverity[large_shift : FALSE] */
   1082         nh_offset = (1 << (soc_mem_field_length(unit, MMU_IPMC_VLAN_TBLm,
   1083                                     MSB_VLANf) - 1));
   1084     } else
   1085 #endif
   1086     {
   1087 #ifdef BCM_TRIDENT_SUPPORT
   1088         if (SOC_IS_TD_TT(unit)) {
   1089             if_cnt = soc_mem_index_count(unit, EGR_L3_INTFm);
   1090             nh_offset = TD_EGR_L3_NEXT_HOP_OFFSET/64;
   1091         }
   1092 #endif
   1093     }
   1094     bcm_tr2_ipmc_repl_detach(unit);
   1095 
   1096     /* Allocate struct for IPMC replication booking keeping */
   1097     alloc_size = sizeof(_tr2_repl_info_t);
   1098     _tr2_repl_info[unit] = sal_alloc(alloc_size, "IPMC repl info");
   1099     if (_tr2_repl_info[unit] == NULL) {
   1100         return BCM_E_MEMORY;
   1101     }
   1102     sal_memset(_tr2_repl_info[unit], 0, alloc_size);
   1103 
   1104     _tr2_repl_info[unit]->ipmc_size = soc_mem_index_count(unit, L3_IPMCm);
   1105     IPMC_REPL_INTF_TOTAL(unit) = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm) +
   1106                                  soc_mem_index_count(unit, EGR_L3_INTFm);
   1107 
   1108     IPMC_REPL_TOTAL(unit) = soc_mem_index_count(unit, MMU_IPMC_VLAN_TBLm);
   1109     alloc_size = SHR_BITALLOCSIZE(IPMC_REPL_TOTAL(unit));
   1110     _tr2_repl_info[unit]->bitmap_entries_used =
   1111         sal_alloc(alloc_size, "IPMC repl entries used");
   1112     if (_tr2_repl_info[unit]->bitmap_entries_used == NULL) {
   1113         bcm_tr2_ipmc_repl_detach(unit);
   1114         return BCM_E_MEMORY;
   1115     }
   1116     sal_memset(_tr2_repl_info[unit]->bitmap_entries_used, 0, alloc_size);
   1117 
   1118     /* Always reserve slot 0 (because 0 means NULL pointer) */
   1119     IPMC_REPL_VE_USED_SET(unit, 0);
   1120 
   1121     if (soc_feature(unit, soc_feature_ipmc_reduced_table_size)) {
   1122         IPMC_REPL_TOTAL(unit) = soc_mem_index_count(unit, MMU_IPMC_VLAN_TBLm) / 2;
   1123         /* reserve slot 1 for null entry for dynamic update */
   1124         IPMC_REPL_VE_USED_SET(unit, 1);
   1125     }
   1126 
   1127 #ifdef BCM_KATANA_SUPPORT    
   1128     if (SOC_IS_KATANAX(unit)) {            
   1129         /* Allocate struct for IPMC Extq replication bookkeeping */
   1130         alloc_size = sizeof(_kt_extq_repl_info_t);
   1131         _kt_extq_repl_info[unit] = sal_alloc(alloc_size, "IPMC Extq repl info");
   1132         if (_kt_extq_repl_info[unit] == NULL) {
   1133             bcm_tr2_ipmc_repl_detach(unit);
   1134             return BCM_E_MEMORY;
   1135         }
   1136         sal_memset(_kt_extq_repl_info[unit], 0, alloc_size);
   1137         _kt_extq_repl_info[unit]->ipmc_size = soc_mem_index_count(unit, L3_IPMCm);
   1138     
   1139         IPMC_EXTQ_REPL_MAX(unit) = (1 << soc_mem_field_length(unit, L3_IPMCm, 
   1140                                     EXT_Q_NUM_COPIESf)) - 1; 
   1141         IPMC_EXTQ_TOTAL(unit) = 4096;     
   1142         IPMC_EXTQ_LIST_TOTAL(unit) = soc_mem_index_count(unit, MMU_EXT_MC_QUEUE_LIST0m);
   1143         alloc_size = SHR_BITALLOCSIZE(IPMC_EXTQ_LIST_TOTAL(unit));
   1144         _kt_extq_repl_info[unit]->bitmap_entries_used =
   1145         sal_alloc(alloc_size, "IPMC Extq repl entries used");
   1146         if (_kt_extq_repl_info[unit]->bitmap_entries_used == NULL) {
   1147             bcm_tr2_ipmc_repl_detach(unit);
   1148             bcm_kt_ipmc_repl_detach(unit);
   1149             return BCM_E_MEMORY;
   1150         }
   1151         sal_memset(_kt_extq_repl_info[unit]->bitmap_entries_used, 0, alloc_size);
   1152             
   1153         /* Always reserve slot 0 */
   1154         IPMC_EXTQ_REPL_VE_USED_SET(unit, 0);
   1155     
   1156         alloc_size = sizeof(_kt_repl_queue_info_t);
   1157         _kt_extq_repl_info[unit]->mcgroup_info = 
   1158             sal_alloc(alloc_size, "IPMC MC group info");
   1159         if (_kt_extq_repl_info[unit]->mcgroup_info == NULL) {
   1160             bcm_tr2_ipmc_repl_detach(unit);
   1161             bcm_kt_ipmc_repl_detach(unit);
   1162             return BCM_E_MEMORY;
   1163         }
   1164         sal_memset(_kt_extq_repl_info[unit]->mcgroup_info, 0, alloc_size);
   1165             
   1166         alloc_size = sizeof(int32) * soc_mem_index_count(unit, L3_IPMCm);
   1167         IPMC_EXTQ_GROUP_INFO(unit)->queue_count =
   1168             sal_alloc(alloc_size, "IPMC Extq queue count");
   1169         if (IPMC_EXTQ_GROUP_INFO(unit)->queue_count == NULL) {
   1170             bcm_tr2_ipmc_repl_detach(unit);
   1171             bcm_kt_ipmc_repl_detach(unit);
   1172             return BCM_E_MEMORY;
   1173         }
   1174         sal_memset(IPMC_EXTQ_GROUP_INFO(unit)->queue_count,
   1175                    0, alloc_size);
   1176 
   1177         IPMC_EXTQ_GROUP_INFO(unit)->queue_count_int =
   1178             sal_alloc(alloc_size, "IPMC Extq queue count internal");
   1179         if (IPMC_EXTQ_GROUP_INFO(unit)->queue_count_int == NULL) {
   1180             bcm_tr2_ipmc_repl_detach(unit);
   1181             bcm_kt_ipmc_repl_detach(unit);
   1182             return BCM_E_MEMORY;
   1183         }
   1184         sal_memset(IPMC_EXTQ_GROUP_INFO(unit)->queue_count_int,
   1185                    0, alloc_size);
   1186 
   1187         IPMC_EXTQ_GROUP_INFO(unit)->queue_count_ext =
   1188             sal_alloc(alloc_size, "IPMC Extq queue count external");
   1189         if (IPMC_EXTQ_GROUP_INFO(unit)->queue_count_ext == NULL) {
   1190             bcm_tr2_ipmc_repl_detach(unit);
   1191             bcm_kt_ipmc_repl_detach(unit);
   1192             return BCM_E_MEMORY;
   1193         }
   1194         sal_memset(IPMC_EXTQ_GROUP_INFO(unit)->queue_count_ext,
   1195                    0, alloc_size);
   1196 
   1197         PBMP_ITER(PBMP_PORT_ALL(unit), port) {
   1198             alloc_size = sizeof(_kt_repl_queue_info_t);
   1199             IPMC_EXTQ_REPL_PORT_INFO(unit, port) =
   1200                 sal_alloc(alloc_size, "IPMC Extq repl port info");
   1201             if (IPMC_EXTQ_REPL_PORT_INFO(unit, port) == NULL) {
   1202                 bcm_tr2_ipmc_repl_detach(unit);
   1203                 bcm_kt_ipmc_repl_detach(unit);
   1204                 return BCM_E_MEMORY;
   1205             }
   1206             sal_memset(IPMC_EXTQ_REPL_PORT_INFO(unit, port), 0, alloc_size);
   1207 
   1208             alloc_size = sizeof(int32) * soc_mem_index_count(unit, L3_IPMCm);
   1209             IPMC_EXTQ_REPL_PORT_INFO(unit, port)->queue_count =
   1210                 sal_alloc(alloc_size, "IPMC Extq repl port queue count");
   1211             if (IPMC_EXTQ_REPL_PORT_INFO(unit, port)->queue_count == NULL) {
   1212                 bcm_tr2_ipmc_repl_detach(unit);
   1213                 bcm_kt_ipmc_repl_detach(unit);
   1214                 return BCM_E_MEMORY;
   1215             }
   1216             sal_memset(IPMC_EXTQ_REPL_PORT_INFO(unit, port)->queue_count,
   1217                        0, alloc_size);
   1218         }
   1219 
   1220         /* reserve ipmc index 0 & 1 for extended queue work around */
   1221         BCM_IF_ERROR_RETURN(bcm_xgs3_ipmc_id_alloc(unit, 0));
   1222         BCM_IF_ERROR_RETURN(bcm_xgs3_ipmc_id_alloc(unit, 1));    
   1223         sw_to_hw_queue[unit] =
   1224            sal_alloc(IPMC_EXTQ_TOTAL(unit) * sizeof(uint32),
   1225                     "SW to HW queue");
   1226         if (sw_to_hw_queue[unit] == NULL) {
   1227             bcm_kt_ipmc_repl_detach(unit);
   1228             return (BCM_E_MEMORY);
   1229         }
   1230         sal_memset(sw_to_hw_queue[unit], 0,
   1231            IPMC_EXTQ_TOTAL(unit) * sizeof(uint32));
   1232     }
   1233 #endif
   1234 
   1235     PBMP_ITER(PBMP_PORT_ALL(unit), port) {
   1236         alloc_size = sizeof(_tr2_repl_port_info_t);
   1237         IPMC_REPL_PORT_INFO(unit, port) =
   1238             sal_alloc(alloc_size, "IPMC repl port info");
   1239         if (IPMC_REPL_PORT_INFO(unit, port) == NULL) {
   1240             bcm_tr2_ipmc_repl_detach(unit);
   1241             return BCM_E_MEMORY;
   1242         }
   1243         sal_memset(IPMC_REPL_PORT_INFO(unit, port), 0, alloc_size);
   1244 
   1245         alloc_size = sizeof(int32) * _tr2_repl_info[unit]->ipmc_size;
   1246         IPMC_REPL_PORT_INFO(unit, port)->vlan_count =
   1247             sal_alloc(alloc_size, "IPMC repl port vlan count");
   1248         if (IPMC_REPL_PORT_INFO(unit, port)->vlan_count == NULL) {
   1249             bcm_tr2_ipmc_repl_detach(unit);
   1250             return BCM_E_MEMORY;
   1251         }
   1252         sal_memset(IPMC_REPL_PORT_INFO(unit, port)->vlan_count,
   1253                    0, alloc_size);
   1254     }
   1255 
   1256     alloc_size = SHR_BITALLOCSIZE(IPMC_REPL_INTF_TOTAL(unit));
   1257     intf_vec = sal_alloc(alloc_size, "IPMC repl interface vector");
   1258     if (intf_vec == NULL) {
   1259         bcm_tr2_ipmc_repl_detach(unit);
   1260         return BCM_E_MEMORY;
   1261     }
   1262     intf_alloc_size = alloc_size;
   1263 
   1264     rli_start = IPMC_REPL_LIST_INFO(unit);
   1265 
   1266     /*
   1267      * Read IPMC group and IPMC VLAN tables to build up software state
   1268      */
   1269     for (ipmc_id = soc_mem_index_min(unit, L3_IPMCm);
   1270          ipmc_id <= soc_mem_index_max(unit, L3_IPMCm); ipmc_id++) {
   1271 
   1272         PBMP_ITER (PBMP_PORT_ALL(unit), port) {
   1273             rv = _tr2_ipmc_vlan_ptr(unit, ipmc_id, port, &first_vlan_ptr, 0, 0);
   1274             if (BCM_FAILURE(rv)) {
   1275                 sal_free(intf_vec);
   1276                 bcm_tr2_ipmc_repl_detach(unit);
   1277                 return rv;
   1278             }
   1279             if (first_vlan_ptr == 0) {
   1280                 continue;
   1281             }
   1282 
   1283             if (IPMC_REPL_VE_USED_GET(unit, first_vlan_ptr)) {
   1284                 /* We've already traversed this list, just note it */
   1285                 for (rli_current = rli_start; rli_current != NULL;
   1286                      rli_current = rli_current->next) {
   1287                     if (rli_current->index == first_vlan_ptr) {
   1288                         (rli_current->refcount)++;
   1289                         IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id) = 
   1290                             rli_current->list_size;
   1291                         break;
   1292                     }
   1293                 }
   1294                 if (rli_current == NULL) {
   1295                     /* Table out of sync.  Not good. */
   1296                     sal_free(intf_vec);
   1297                     bcm_tr2_ipmc_repl_detach(unit);
   1298                     return BCM_E_INTERNAL;
   1299                 } else {
   1300                     continue;
   1301                 }
   1302             }
   1303 
   1304             sal_memset(intf_vec, 0, intf_alloc_size);
   1305             next_vlan_ptr = first_vlan_ptr;
   1306             vlan_ptr = 0;
   1307             while (vlan_ptr != next_vlan_ptr) {
   1308                 vlan_ptr = next_vlan_ptr;
   1309                 rv = READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL,
   1310                                              vlan_ptr, &vlan_entry);
   1311                 if (BCM_FAILURE(rv)) {
   1312                     sal_free(intf_vec);
   1313                     bcm_tr2_ipmc_repl_detach(unit);
   1314                     return rv;
   1315                 }
   1316                 soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry,
   1317                                        LSB_VLAN_BMf, ls_bits);
   1318 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIDENT_SUPPORT)
   1319                 if (SOC_IS_KATANAX(unit) || SOC_IS_TD_TT(unit)) {
   1320                     ms_max = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   1321                                        &vlan_entry, MSB_VLANf);
   1322                     if (ms_max >= nh_offset) {
   1323                         /* Replication is on Nexthops */
   1324                         offset = _SHR_BITDCLSIZE(if_cnt);
   1325                         ms_bit = ms_max - nh_offset;
   1326                     } else {
   1327                         /* Replication is on L3 Interface */
   1328                         offset = 0;
   1329                         ms_bit = ms_max;
   1330                     }
   1331                     intf_vec[offset + 2 * ms_bit + 0] = ls_bits[0];
   1332                     intf_vec[offset + 2 * ms_bit + 1] = ls_bits[1];
   1333                 } else
   1334 #endif
   1335                 {
   1336                     ms_bit = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   1337                                        &vlan_entry, MSB_VLANf);
   1338                     intf_vec[2 * ms_bit + 0] = ls_bits[0];
   1339                     intf_vec[2 * ms_bit + 1] = ls_bits[1];
   1340                 }
   1341 
   1342                 IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id) +=
   1343                       _shr_popcount(ls_bits[0]) + _shr_popcount(ls_bits[1]);
   1344                 IPMC_REPL_VE_USED_SET(unit, vlan_ptr);
   1345                 next_vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   1346                                                   &vlan_entry, NEXTPTRf);
   1347                 if (soc_feature(unit, soc_feature_ipmc_reduced_table_size)) {
   1348                     if (vlan_ptr == first_vlan_ptr && next_vlan_ptr == 1) {
   1349                         next_vlan_ptr = vlan_ptr;
   1350                     }	
   1351                 }
   1352             }   
   1353 
   1354             /* Create new list element */
   1355             alloc_size = sizeof(_bcm_repl_list_info_t);
   1356             rli_current = sal_alloc(alloc_size, "IPMC repl list info");
   1357             if (rli_current == NULL) {
   1358                 sal_free(intf_vec);
   1359                 bcm_tr2_ipmc_repl_detach(unit);
   1360                 return BCM_E_MEMORY;
   1361             }
   1362             sal_memset(rli_current, 0, alloc_size);
   1363             rli_current->index = first_vlan_ptr;
   1364             rli_current->hash =
   1365                 _shr_crc32b(0, (uint8 *)intf_vec,
   1366                             IPMC_REPL_INTF_TOTAL(unit));
   1367             rli_current->next = rli_start;
   1368             rli_current->list_size =
   1369                 IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id);
   1370             IPMC_REPL_LIST_INFO(unit) = rli_current;
   1371             rli_start = rli_current;
   1372             (rli_current->refcount)++;
   1373         }
   1374 
   1375 #ifdef BCM_KATANA_SUPPORT
   1376         if (SOC_IS_KATANAX(unit)) {
   1377             if (ipmc_id > 1) {
   1378                 rv = _bcm_kt_extq_repl_reload(unit, ipmc_id);
   1379                 if (BCM_FAILURE(rv)) {
   1380                     sal_free(intf_vec);
   1381                     bcm_tr2_ipmc_repl_detach(unit);
   1382                     bcm_kt_ipmc_repl_detach(unit);
   1383                     return rv;
   1384                 }    
   1385             }
   1386         }    
   1387 #endif
   1388     }
   1389 
   1390     /* Recover REPL list mode from HW cache */
   1391     rv = _bcm_esw_ipmc_repl_wb_flags_get(unit,
   1392                                          _BCM_IPMC_WB_REPL_LIST, &flags);
   1393     if (flags) {
   1394         SOC_IPMCREPLSHR_SET(unit, 1);
   1395     }
   1396 
   1397     sal_free(intf_vec);
   1398     return BCM_E_NONE;
   1399 }
   1400 
   1401 #ifdef BCM_KATANA_SUPPORT
   1402 /*
   1403  * Function:
   1404  *      _bcm_kt_ipmc_hw_queue_info_scache_size_get
   1405  * Purpose:
   1406  *      Get the required scache size for storing hw queue info.
   1407  * Parameters:
   1408  *      unit - (IN)  StrataSwitch unit #
   1409  *      size - (OUT) Number of bytes
   1410  * Returns:
   1411  *      BCM_E_xxx
   1412  */
   1413 int
   1414 _bcm_kt_ipmc_hw_queue_info_scache_size_get(int unit, uint32 *size)
   1415 {
   1416     int hw_queue_size;
   1417 
   1418     *size = 0;
   1419     hw_queue_size = IPMC_EXTQ_TOTAL(unit) * sizeof(uint32);
   1420     *size += hw_queue_size;
   1421 
   1422     return BCM_E_NONE;
   1423 }
   1424 
   1425 /*
   1426  * Function:
   1427  *      _bcm_kt_ipmc_hw_queue_info_sync
   1428  * Purpose:
   1429  *      Sync hw queue info to scache.
   1430  * Parameters:
   1431  *      unit       - (IN)     StrataSwitch unit #
   1432  *      scache_ptr - (IN/OUT) Scache pointer
   1433  * Returns:
   1434  *      BCM_E_xxx
   1435  */
   1436 int
   1437 _bcm_kt_ipmc_hw_queue_info_sync(int unit, uint8 **scache_ptr)
   1438 {
   1439     int hw_queue_size;
   1440 
   1441     hw_queue_size = IPMC_EXTQ_TOTAL(unit) * sizeof(uint32);
   1442     sal_memcpy((*scache_ptr), sw_to_hw_queue[unit], hw_queue_size);
   1443     (*scache_ptr) += hw_queue_size;
   1444 
   1445     return BCM_E_NONE;
   1446 }
   1447 
   1448 /*
   1449  * Function:
   1450  *      _bcm_kt_ipmc_hw_queue_info_recover
   1451  * Purpose:
   1452  *      Recover hw queue info from scache.
   1453  * Parameters:
   1454  *      unit       - (IN)     StrataSwitch unit #
   1455  *      scache_ptr - (IN/OUT) Scache pointer
   1456  * Returns:
   1457  *      BCM_E_xxx
   1458  */
   1459 int
   1460 _bcm_kt_ipmc_hw_queue_info_recover(int unit, uint8 **scache_ptr)
   1461 {
   1462     int hw_queue_size;
   1463 
   1464     hw_queue_size = IPMC_EXTQ_TOTAL(unit) * sizeof(uint32);
   1465     sal_memcpy(sw_to_hw_queue[unit], (*scache_ptr), hw_queue_size);
   1466     (*scache_ptr) += hw_queue_size;
   1467 
   1468     return BCM_E_NONE;
   1469 }
   1470 #endif /* BCM_KATANA_SUPPORT */
   1471 
   1472 #endif /* BCM_WARM_BOOT_SUPPORT */
   1473 
   1474 /*
   1475  * Function:
   1476  *      bcm_tr2_ipmc_repl_init
   1477  * Purpose:
   1478  *      Initialize IPMC replication.
   1479  * Parameters:
   1480  *      unit     - SOC unit #
   1481  * Returns:
   1482  *      BCM_E_XXX
   1483  */
   1484 
   1485 int
   1486 bcm_tr2_ipmc_repl_init(int unit)
   1487 {
   1488     bcm_port_t          port;
   1489     int                 alloc_size;
   1490     uint32              rval;
   1491 #ifdef BCM_KATANA_SUPPORT
   1492     uint32 entry[SOC_MAX_MEM_FIELD_WORDS];
   1493 #endif
   1494 
   1495     if (SOC_IS_TRIDENT2X(unit)) { 
   1496         return BCM_E_NONE;
   1497     }
   1498 
   1499     bcm_tr2_ipmc_repl_detach(unit);
   1500 #ifdef BCM_KATANA_SUPPORT
   1501     if (SOC_IS_KATANAX(unit)) {
   1502         bcm_kt_ipmc_repl_detach(unit);
   1503     }
   1504 #endif
   1505 
   1506     /* Allocate struct for IPMC replication bookkeeping */
   1507     alloc_size = sizeof(_tr2_repl_info_t);
   1508     _tr2_repl_info[unit] = sal_alloc(alloc_size, "IPMC repl info");
   1509     if (_tr2_repl_info[unit] == NULL) {
   1510         return BCM_E_MEMORY;
   1511     }
   1512     sal_memset(_tr2_repl_info[unit], 0, alloc_size);
   1513     _tr2_repl_info[unit]->ipmc_size = soc_mem_index_count(unit, L3_IPMCm);
   1514 
   1515 #ifdef BCM_BRADLEY_SUPPORT
   1516     if (SOC_REG_FIELD_VALID(unit, MC_CONTROL_5r, SHARED_TABLE_IPMC_SIZEf)) {
   1517         int ipmc_base, ipmc_size;
   1518         
   1519         SOC_IF_ERROR_RETURN
   1520             (soc_hbx_ipmc_size_get(unit, &ipmc_base, &ipmc_size));
   1521 
   1522         if (_tr2_repl_info[unit]->ipmc_size > ipmc_size) {
   1523             /* Reduce to fix allocated table space */
   1524             _tr2_repl_info[unit]->ipmc_size = ipmc_size;
   1525         }
   1526     }
   1527 #endif
   1528 
   1529     IPMC_REPL_INTF_TOTAL(unit) = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm) + 
   1530                                  soc_mem_index_count(unit, EGR_L3_INTFm);
   1531 
   1532 #if defined(BCM_KATANA2_SUPPORT)
   1533     
   1534     if (SOC_IS_KATANA2(unit)) {
   1535         IPMC_REPL_TOTAL(unit) = soc_mem_index_count(unit, MMU_REPL_LIST_TBLm);
   1536     } else
   1537 #endif
   1538     {
   1539         IPMC_REPL_TOTAL(unit) = soc_mem_index_count(unit, MMU_IPMC_VLAN_TBLm);
   1540     }
   1541     alloc_size = SHR_BITALLOCSIZE(IPMC_REPL_TOTAL(unit));
   1542     _tr2_repl_info[unit]->bitmap_entries_used =
   1543         sal_alloc(alloc_size, "IPMC repl entries used");
   1544     if (_tr2_repl_info[unit]->bitmap_entries_used == NULL) {
   1545         bcm_tr2_ipmc_repl_detach(unit);
   1546         return BCM_E_MEMORY;
   1547     }
   1548     sal_memset(_tr2_repl_info[unit]->bitmap_entries_used, 0, alloc_size);
   1549 
   1550     /* Always reserve slot 0 */
   1551     IPMC_REPL_VE_USED_SET(unit, 0);
   1552 
   1553     PBMP_ITER(PBMP_PORT_ALL(unit), port) {
   1554         alloc_size = sizeof(_tr2_repl_port_info_t);
   1555         IPMC_REPL_PORT_INFO(unit, port) =
   1556             sal_alloc(alloc_size, "IPMC repl port info");
   1557         if (IPMC_REPL_PORT_INFO(unit, port) == NULL) {
   1558             bcm_tr2_ipmc_repl_detach(unit);
   1559             return BCM_E_MEMORY;
   1560         }
   1561         sal_memset(IPMC_REPL_PORT_INFO(unit, port), 0, alloc_size);
   1562 
   1563         alloc_size = sizeof(int32) * soc_mem_index_count(unit, L3_IPMCm);
   1564 
   1565         IPMC_REPL_PORT_INFO(unit, port)->vlan_count =
   1566             sal_alloc(alloc_size, "IPMC repl port vlan count");
   1567         if (IPMC_REPL_PORT_INFO(unit, port)->vlan_count == NULL) {
   1568             bcm_tr2_ipmc_repl_detach(unit);
   1569             return BCM_E_MEMORY;
   1570         }
   1571         sal_memset(IPMC_REPL_PORT_INFO(unit, port)->vlan_count,
   1572                    0, alloc_size);
   1573     }
   1574 
   1575     if (soc_feature(unit, soc_feature_ipmc_reduced_table_size)) {
   1576         IPMC_REPL_TOTAL(unit) = soc_mem_index_count(unit, MMU_IPMC_VLAN_TBLm) / 2;
   1577         /* reserve slot 1 for null entry for dynamic update */
   1578         IPMC_REPL_VE_USED_SET(unit, 1);
   1579     }
   1580 
   1581 
   1582 #ifdef BCM_KATANA_SUPPORT
   1583     if (SOC_IS_KATANAX(unit)) {
   1584         /* Allocate struct for IPMC Extq replication bookkeeping */
   1585         alloc_size = sizeof(_kt_extq_repl_info_t);
   1586         _kt_extq_repl_info[unit] = sal_alloc(alloc_size, "IPMC Extq repl info");
   1587         if (_kt_extq_repl_info[unit] == NULL) {
   1588             bcm_tr2_ipmc_repl_detach(unit);
   1589             return BCM_E_MEMORY;
   1590         }
   1591         sal_memset(_kt_extq_repl_info[unit], 0, alloc_size);
   1592         _kt_extq_repl_info[unit]->ipmc_size = soc_mem_index_count(unit, L3_IPMCm);
   1593 
   1594         IPMC_EXTQ_REPL_MAX(unit) = (1 << soc_mem_field_length(unit, L3_IPMCm, 
   1595                                     EXT_Q_NUM_COPIESf)) - 1; 
   1596         IPMC_EXTQ_TOTAL(unit) = 4096;    
   1597         IPMC_EXTQ_LIST_TOTAL(unit) = soc_mem_index_count(unit, MMU_EXT_MC_QUEUE_LIST0m);
   1598         alloc_size = SHR_BITALLOCSIZE(IPMC_EXTQ_LIST_TOTAL(unit));
   1599         _kt_extq_repl_info[unit]->bitmap_entries_used =
   1600         sal_alloc(alloc_size, "IPMC Extq repl entries used");
   1601         if (_kt_extq_repl_info[unit]->bitmap_entries_used == NULL) {
   1602             bcm_tr2_ipmc_repl_detach(unit);
   1603             bcm_kt_ipmc_repl_detach(unit);
   1604             return BCM_E_MEMORY;
   1605         }
   1606         sal_memset(_kt_extq_repl_info[unit]->bitmap_entries_used, 0, alloc_size);
   1607 
   1608         /* Always reserve slot 0 */
   1609         IPMC_EXTQ_REPL_VE_USED_SET(unit, 0);
   1610 
   1611         alloc_size = sizeof(_kt_repl_queue_info_t);
   1612         _kt_extq_repl_info[unit]->mcgroup_info = 
   1613             sal_alloc(alloc_size, "IPMC MC group info");
   1614         if (_kt_extq_repl_info[unit]->mcgroup_info == NULL) {
   1615             bcm_tr2_ipmc_repl_detach(unit);
   1616             bcm_kt_ipmc_repl_detach(unit);
   1617             return BCM_E_MEMORY;
   1618         }
   1619         sal_memset(_kt_extq_repl_info[unit]->mcgroup_info, 0, alloc_size);
   1620 
   1621         alloc_size = sizeof(int32) * soc_mem_index_count(unit, L3_IPMCm);
   1622         IPMC_EXTQ_GROUP_INFO(unit)->queue_count =
   1623             sal_alloc(alloc_size, "IPMC Extq queue count");
   1624         if (IPMC_EXTQ_GROUP_INFO(unit)->queue_count == NULL) {
   1625             bcm_tr2_ipmc_repl_detach(unit);
   1626             bcm_kt_ipmc_repl_detach(unit);
   1627             return BCM_E_MEMORY;
   1628         }
   1629         sal_memset(IPMC_EXTQ_GROUP_INFO(unit)->queue_count,
   1630                    0, alloc_size);
   1631 
   1632         IPMC_EXTQ_GROUP_INFO(unit)->queue_count_int =
   1633             sal_alloc(alloc_size, "IPMC Extq queue count internal");
   1634         if (IPMC_EXTQ_GROUP_INFO(unit)->queue_count_int == NULL) {
   1635             bcm_tr2_ipmc_repl_detach(unit);
   1636             bcm_kt_ipmc_repl_detach(unit);
   1637             return BCM_E_MEMORY;
   1638         }
   1639         sal_memset(IPMC_EXTQ_GROUP_INFO(unit)->queue_count_int,
   1640                    0, alloc_size);
   1641 
   1642         IPMC_EXTQ_GROUP_INFO(unit)->queue_count_ext =
   1643             sal_alloc(alloc_size, "IPMC Extq queue count external");
   1644         if (IPMC_EXTQ_GROUP_INFO(unit)->queue_count_ext == NULL) {
   1645             bcm_tr2_ipmc_repl_detach(unit);
   1646             bcm_kt_ipmc_repl_detach(unit);
   1647             return BCM_E_MEMORY;
   1648         }
   1649         sal_memset(IPMC_EXTQ_GROUP_INFO(unit)->queue_count_ext,
   1650                    0, alloc_size);
   1651 
   1652         PBMP_ITER(PBMP_PORT_ALL(unit), port) {
   1653             alloc_size = sizeof(_kt_repl_queue_info_t);
   1654             IPMC_EXTQ_REPL_PORT_INFO(unit, port) =
   1655                 sal_alloc(alloc_size, "IPMC Extq repl port info");
   1656             if (IPMC_EXTQ_REPL_PORT_INFO(unit, port) == NULL) {
   1657                 bcm_tr2_ipmc_repl_detach(unit);
   1658                 bcm_kt_ipmc_repl_detach(unit);
   1659                 return BCM_E_MEMORY;
   1660             }
   1661             sal_memset(IPMC_EXTQ_REPL_PORT_INFO(unit, port), 0, alloc_size);
   1662 
   1663             alloc_size = sizeof(int32) * soc_mem_index_count(unit, L3_IPMCm);
   1664             IPMC_EXTQ_REPL_PORT_INFO(unit, port)->queue_count =
   1665                 sal_alloc(alloc_size, "IPMC Extq repl port queue count");
   1666             if (IPMC_EXTQ_REPL_PORT_INFO(unit, port)->queue_count == NULL) {
   1667                 bcm_tr2_ipmc_repl_detach(unit);
   1668                 bcm_kt_ipmc_repl_detach(unit);
   1669                 return BCM_E_MEMORY;
   1670             }
   1671             sal_memset(IPMC_EXTQ_REPL_PORT_INFO(unit, port)->queue_count,
   1672                        0, alloc_size);
   1673         }
   1674 
   1675 
   1676         /* reserve ipmc index 0 & 1 for extended queue work around */
   1677         BCM_IF_ERROR_RETURN(bcm_xgs3_ipmc_id_alloc(unit, 0));
   1678         BCM_IF_ERROR_RETURN(bcm_xgs3_ipmc_id_alloc(unit, 1));
   1679 
   1680             /* Read L3 ipmc table. */
   1681         BCM_IF_ERROR_RETURN(soc_mem_read(unit, L3_IPMCm, MEM_BLOCK_ANY,
   1682                                      0, entry));
   1683             /* use 1 as initial redirection pointer */
   1684         soc_mem_field32_set(unit, L3_IPMCm, entry, 
   1685                                     MMU_MC_REDIRECTION_PTRf, 1);
   1686         BCM_IF_ERROR_RETURN(soc_mem_write(unit, L3_IPMCm, MEM_BLOCK_ALL, 
   1687                                     0, &entry));
   1688         sw_to_hw_queue[unit] =
   1689            sal_alloc(IPMC_EXTQ_TOTAL(unit) * sizeof(uint32),
   1690                     "SW to HW queue");
   1691         if (sw_to_hw_queue[unit] == NULL) {
   1692             bcm_kt_ipmc_repl_detach(unit);
   1693             return (BCM_E_MEMORY);
   1694         }
   1695         sal_memset(sw_to_hw_queue[unit], 0,
   1696            IPMC_EXTQ_TOTAL(unit) * sizeof(uint32));
   1697     }
   1698 #endif
   1699 
   1700     if (soc_property_get(unit, spn_IPMC_INDEPENDENT_MODE, 0)) {
   1701         BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval));
   1702         soc_reg_field_set(unit, MISCCONFIGr, &rval, IPMC_IND_MODEf, 1);
   1703         BCM_IF_ERROR_RETURN(WRITE_MISCCONFIGr(unit, rval));
   1704     }
   1705     if (!SAL_BOOT_QUICKTURN && !SAL_BOOT_BCMSIM && !SAL_BOOT_XGSSIM) {
   1706         /* Hardware has already cleared the table during reset for Tridnet */
   1707         if (!SOC_IS_TD_TT(unit)) {
   1708             SOC_IF_ERROR_RETURN
   1709                 (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL0m, COPYNO_ALL, FALSE));
   1710             SOC_IF_ERROR_RETURN
   1711                 (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL1m, COPYNO_ALL, FALSE));
   1712             SOC_IF_ERROR_RETURN
   1713                 (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL2m, COPYNO_ALL, FALSE));
   1714             SOC_IF_ERROR_RETURN
   1715                 (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL3m, COPYNO_ALL, FALSE));
   1716             SOC_IF_ERROR_RETURN
   1717                 (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL4m, COPYNO_ALL, FALSE));
   1718             if (SOC_MEM_IS_VALID(unit, MMU_IPMC_GROUP_TBL5m)) {
   1719                 SOC_IF_ERROR_RETURN
   1720                     (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL5m, COPYNO_ALL, FALSE));
   1721             }
   1722             if (SOC_MEM_IS_VALID(unit, MMU_IPMC_GROUP_TBL6m)) {
   1723                 SOC_IF_ERROR_RETURN
   1724                     (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL6m, COPYNO_ALL, FALSE));
   1725             }
   1726             if (SOC_MEM_IS_VALID(unit, MMU_IPMC_GROUP_TBL7m)) {
   1727                 SOC_IF_ERROR_RETURN
   1728                     (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL7m, COPYNO_ALL, FALSE));
   1729             }
   1730             if (SOC_MEM_IS_VALID(unit, MMU_IPMC_GROUP_TBL8m)) {
   1731                 SOC_IF_ERROR_RETURN
   1732                     (soc_mem_clear(unit, MMU_IPMC_GROUP_TBL8m, COPYNO_ALL, FALSE));
   1733             }
   1734             if (SOC_MEM_IS_VALID(unit, MMU_IPMC_VLAN_TBLm)) {
   1735                 SOC_IF_ERROR_RETURN
   1736                     (soc_mem_clear(unit, MMU_IPMC_VLAN_TBLm, COPYNO_ALL, FALSE));
   1737             }
   1738         }
   1739     }
   1740     
   1741     return BCM_E_NONE;
   1742 
   1743 }
   1744 
   1745 /*
   1746  * Function:
   1747  *      bcm_tr2_ipmc_repl_detach
   1748  * Purpose:
   1749  *      Initialize IPMC replication.
   1750  * Parameters:
   1751  *      unit     - SOC unit #
   1752  * Returns:
   1753  *      BCM_E_XXX
   1754  */
   1755 
   1756 int
   1757 bcm_tr2_ipmc_repl_detach(int unit)
   1758 {
   1759     bcm_port_t          port;
   1760     _bcm_repl_list_info_t *rli_current, *rli_free;
   1761 
   1762 #ifdef BCM_KATANA_SUPPORT
   1763     if (SOC_IS_KATANA(unit)) {
   1764         BCM_IF_ERROR_RETURN(bcm_kt_ipmc_repl_detach(unit));
   1765     }
   1766 #endif
   1767 
   1768     if (_tr2_repl_info[unit] != NULL) {
   1769         PBMP_ITER(PBMP_PORT_ALL(unit), port) {
   1770             if (_tr2_repl_info[unit]->port_info[port] != NULL) {
   1771                 if (_tr2_repl_info[unit]->
   1772                     port_info[port]->vlan_count != NULL) {
   1773                     sal_free(_tr2_repl_info[unit]->
   1774                              port_info[port]->vlan_count);
   1775                 }
   1776                 sal_free(_tr2_repl_info[unit]->port_info[port]);
   1777             }
   1778         }
   1779 
   1780         if (_tr2_repl_info[unit]->bitmap_entries_used != NULL) {
   1781             sal_free(_tr2_repl_info[unit]->bitmap_entries_used);
   1782         }
   1783 
   1784         if (_tr2_repl_info[unit]->repl_list_info != NULL) {
   1785             rli_current = IPMC_REPL_LIST_INFO(unit);
   1786             while (rli_current != NULL) {
   1787                 rli_free = rli_current;
   1788                 rli_current = rli_current->next;
   1789                 sal_free(rli_free);
   1790             }
   1791         }
   1792 
   1793         sal_free(_tr2_repl_info[unit]);
   1794         _tr2_repl_info[unit] = NULL;
   1795     }
   1796 
   1797     return BCM_E_NONE;
   1798 }
   1799 
   1800 int
   1801 _bcm_tr2_ipmc_egress_intf_add(int unit, int ipmc_id, bcm_port_t port,
   1802                              int id)
   1803 {
   1804     int *if_array = NULL;
   1805     int intf_num, intf_max, alloc_size, rv = BCM_E_NONE;
   1806     int                 partition;
   1807     bcm_l3_intf_t       l3_intf;
   1808 
   1809     IPMC_REPL_INIT(unit);
   1810     IPMC_REPL_ID(unit, ipmc_id);
   1811     REPL_PORT_CHECK(unit, port);
   1812 
   1813     intf_max = IPMC_REPL_INTF_TOTAL(unit);
   1814     alloc_size = intf_max * sizeof(int);
   1815     if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   1816     if (if_array == NULL) {
   1817         return BCM_E_MEMORY;
   1818     }
   1819 
   1820     IPMC_REPL_LOCK(unit);
   1821     rv = bcm_tr2_ipmc_egress_intf_get(unit, ipmc_id, port, intf_max,
   1822                                      if_array, &intf_num);
   1823     if (BCM_SUCCESS(rv)) {
   1824         if (intf_num < intf_max) {
   1825             if_array[intf_num++] = id;
   1826 
   1827             /* For IPMC, check port is a member of the L3 interface's VLAN.
   1828              * Performing this check here is more efficient than performing
   1829              * it in bcm_tr2_ipmc_egress_intf_set.
   1830              */ 
   1831             if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, id)) {
   1832                 /* L3 interface is used */
   1833                 partition = soc_mem_index_count(unit, EGR_L3_INTFm);
   1834                 if (id > partition) {
   1835                     rv = BCM_E_PARAM;
   1836                     goto intf_add_done;
   1837                 }
   1838 
   1839                 bcm_l3_intf_t_init(&l3_intf);
   1840                 l3_intf.l3a_intf_id = id;
   1841                 if ((rv = bcm_esw_l3_intf_get(unit, &l3_intf)) < 0) {
   1842                     goto intf_add_done;
   1843                 }
   1844             } 
   1845 
   1846             rv = bcm_tr2_ipmc_egress_intf_set(unit, ipmc_id, port,
   1847                                              intf_num, if_array, FALSE);
   1848         } else {
   1849             rv = BCM_E_EXISTS;
   1850         }
   1851     }
   1852 
   1853 intf_add_done:
   1854 
   1855     IPMC_REPL_UNLOCK(unit);
   1856     sal_free(if_array); 
   1857     return rv;
   1858 }
   1859 
   1860 int
   1861 _bcm_tr2_ipmc_egress_intf_delete(int unit, int ipmc_id, bcm_port_t port,
   1862                                 int if_max, int id)
   1863 {
   1864     int  *if_array = NULL;
   1865     int  alloc_size, if_count, if_cur, match, rv = BCM_E_NONE;
   1866 
   1867     IPMC_REPL_INIT(unit);
   1868     IPMC_REPL_ID(unit, ipmc_id);
   1869     REPL_PORT_CHECK(unit, port);
   1870 
   1871     if (!IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) {
   1872         return BCM_E_NOT_FOUND;
   1873     } else if ((if_max <= 0) ||
   1874                ((uint32)if_max > IPMC_REPL_INTF_TOTAL(unit))) {
   1875         return BCM_E_PARAM;
   1876     }
   1877     alloc_size = if_max * sizeof(int);
   1878     if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   1879     if (if_array == NULL) {
   1880         return BCM_E_MEMORY;
   1881     }
   1882 
   1883     IPMC_REPL_LOCK(unit);
   1884     rv = bcm_tr2_ipmc_egress_intf_get(unit, ipmc_id, port, if_max,
   1885                                      if_array, &if_count);
   1886     if (BCM_SUCCESS(rv)) {
   1887         match = FALSE;
   1888         for (if_cur = 0; if_cur < if_count; if_cur++) {
   1889             if (match) {
   1890                 if_array[if_cur - 1] = if_array[if_cur];
   1891             } else {
   1892                 if (if_array[if_cur] == id) {
   1893                     match = TRUE;
   1894                 }
   1895             }
   1896         }
   1897         if (match) {
   1898             if_count--;
   1899             rv = bcm_tr2_ipmc_egress_intf_set(unit, ipmc_id, port,
   1900                                              if_count, if_array, FALSE);
   1901         } else { 
   1902             rv = BCM_E_NOT_FOUND;
   1903         }
   1904     }
   1905     
   1906     IPMC_REPL_UNLOCK(unit);
   1907     sal_free(if_array);
   1908     return rv;
   1909 }
   1910 
   1911 /*
   1912  * Function:
   1913  *	_bcm_tr2_repl_list_compare
   1914  * Description:
   1915  *	Compare HW list starting at vlan_index to the VLAN list contained
   1916  *      in vlan_vec.
   1917  */
   1918 
   1919 STATIC int
   1920 _bcm_tr2_repl_list_compare(int unit, int vlan_index,
   1921                           SHR_BITDCL *intf_vec)
   1922 {
   1923     uint32		ms_bit, hw_ms_bit, ms_max, msb;
   1924     uint32		ls_bits[2], hw_ls_bits[2];
   1925     mmu_ipmc_vlan_tbl_entry_t vlan_entry;
   1926     int	                vlan_ptr, last_vlan_ptr;
   1927     int                 repl_type;
   1928     int                 ls_len, if_cnt, nh_cnt, offset;
   1929     int                 nh_offset;
   1930 
   1931     if_cnt = soc_mem_index_count(unit, EGR_L3_INTFm);
   1932     nh_cnt = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
   1933     last_vlan_ptr = -1;
   1934     vlan_ptr = vlan_index;
   1935     ls_len = soc_mem_field_length(unit, MMU_IPMC_VLAN_TBLm, LSB_VLAN_BMf);
   1936     if (SOC_IS_TD_TT(unit)) {
   1937         nh_offset = TD_EGR_L3_NEXT_HOP_OFFSET;
   1938     } else {
   1939         /* coverity[large_shift : FALSE] */
   1940         /* coverity[negative_shift : FALSE] */
   1941         nh_offset = (1 << (soc_mem_field_length(unit, MMU_IPMC_VLAN_TBLm,
   1942                                                    MSB_VLANf) - 1)) * ls_len;
   1943     }
   1944     /* Iterate over the two replication types - interfaces and next hops */
   1945     for (repl_type = 0; repl_type < 2; repl_type++) {
   1946         if (repl_type == 0) {
   1947             ms_max = _SHR_BITDCLSIZE(if_cnt) / 2; /* 32 -> 64 */
   1948             offset = 0;
   1949         } else {
   1950             ms_max = _SHR_BITDCLSIZE(nh_cnt) / 2; /* 32 -> 64 */
   1951             offset = _SHR_BITDCLSIZE(if_cnt);
   1952         }
   1953         for (ms_bit = 0; ms_bit < ms_max; ms_bit++) {
   1954             ls_bits[0] = intf_vec[offset + 2 * ms_bit + 0];
   1955             ls_bits[1] = intf_vec[offset + 2 * ms_bit + 1];
   1956             if ((ls_bits[0] != 0) || (ls_bits[1] != 0)) {
   1957                 if (vlan_ptr == last_vlan_ptr) { /* HW list end, not app list */
   1958                     return BCM_E_NOT_FOUND;
   1959                 }
   1960                 SOC_IF_ERROR_RETURN
   1961                     (READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ANY,
   1962                                                        vlan_ptr, &vlan_entry));
   1963                 hw_ms_bit = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   1964                                            &vlan_entry, MSB_VLANf);
   1965                 soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry,
   1966                                                        LSB_VLAN_BMf, hw_ls_bits);
   1967 
   1968                 if (repl_type == 1) {
   1969                     /* Replication is over next hops */
   1970                     msb = ms_bit + nh_offset / 64;
   1971                 } else {
   1972                     /* Replication is over interfaces */
   1973                     msb = ms_bit;
   1974                 }
   1975 
   1976                 if ((hw_ms_bit != msb) || (ls_bits[0] != hw_ls_bits[0]) ||
   1977                     (ls_bits[1] != hw_ls_bits[1])) {
   1978                     return BCM_E_NOT_FOUND;
   1979                 }
   1980                 last_vlan_ptr = vlan_ptr;
   1981                 vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   1982                                               &vlan_entry, NEXTPTRf);
   1983             }
   1984         }
   1985     }
   1986 
   1987     return BCM_E_NONE;
   1988 }
   1989 
   1990 /*
   1991  * Function:
   1992  *	_bcm_tr2_repl_list_free
   1993  * Description:
   1994  *	Release the IPMC_VLAN entries in the HW list starting at start_ptr.
   1995  */
   1996 
   1997 STATIC int
   1998 _bcm_tr2_repl_list_free(int unit, int start_ptr)
   1999 {
   2000     mmu_ipmc_vlan_tbl_entry_t vlan_entry;
   2001     int	                vlan_ptr, last_vlan_ptr;
   2002 
   2003     last_vlan_ptr = -1;
   2004     vlan_ptr = start_ptr;
   2005 
   2006     while (vlan_ptr != last_vlan_ptr) {
   2007         SOC_IF_ERROR_RETURN
   2008             (READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ANY,
   2009                                                vlan_ptr, &vlan_entry));
   2010         last_vlan_ptr = vlan_ptr;
   2011         vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   2012                                           &vlan_entry, NEXTPTRf);
   2013 
   2014         if (soc_feature(unit, soc_feature_ipmc_reduced_table_size)) {
   2015             if (last_vlan_ptr == start_ptr && vlan_ptr == 1) {
   2016                 vlan_ptr = last_vlan_ptr;
   2017             }	
   2018         }
   2019 		
   2020         IPMC_REPL_VE_USED_CLR(unit, last_vlan_ptr);
   2021     }
   2022 
   2023 #ifdef BCM_KATANA_SUPPORT
   2024     if (soc_feature(unit, soc_feature_ipmc_reduced_table_size)) {
   2025         return _kt_ipmc_group_entry_clear(unit, start_ptr);
   2026     }	
   2027 #endif
   2028 	
   2029     return BCM_E_NONE;
   2030 }
   2031 
   2032 STATIC int
   2033 _tr2_ipmc_repl_next_free_ptr(int unit)
   2034 {
   2035     int                 ix, bit;
   2036     SHR_BITDCL          not_ptrs;
   2037 
   2038     for (ix = 0; ix < _SHR_BITDCLSIZE(IPMC_REPL_TOTAL(unit)); ix++) {
   2039         not_ptrs = ~_tr2_repl_info[unit]->bitmap_entries_used[ix];
   2040         if (not_ptrs) {
   2041             for (bit = 0; bit < SHR_BITWID; bit++) {
   2042                 if (not_ptrs & (1 << bit)) {
   2043                     return (ix * SHR_BITWID) + bit;
   2044                 }
   2045             }
   2046         }
   2047     }
   2048 
   2049     return -1;
   2050 }
   2051 
   2052 STATIC int
   2053 _kt_ipmc_repl_next_free_ptr(int unit, int head)
   2054 {
   2055     int                 ix, bit;
   2056     int                 start_ix, end_ix;
   2057     SHR_BITDCL          not_ptrs;
   2058 
   2059     start_ix = (head == 1) ? IPMC_REPL_TOTAL(unit) : 0;
   2060     end_ix = start_ix + IPMC_REPL_TOTAL(unit);
   2061 
   2062     for (ix = _SHR_BITDCLSIZE(start_ix); ix < _SHR_BITDCLSIZE(end_ix); ix++) {
   2063         not_ptrs = ~_tr2_repl_info[unit]->bitmap_entries_used[ix];
   2064         if (not_ptrs) {
   2065             for (bit = 0; bit < SHR_BITWID; bit++) {
   2066                 if (not_ptrs & (1 << bit)) {
   2067                     return (ix * SHR_BITWID) + bit;
   2068                 }
   2069             }
   2070         }
   2071     }
   2072 
   2073     return -1;
   2074 }
   2075 
   2076 /*
   2077  * Function:
   2078  *	_bcm_tr2_repl_list_write
   2079  * Description:
   2080  *	Write the VLAN list contained in vlan_vec into the HW table.
   2081  *      Return the start_index and total VLAN count.
   2082  */
   2083 
   2084 STATIC int
   2085 _bcm_tr2_repl_list_write(int unit, int *start_index, int *count,
   2086                         SHR_BITDCL *intf_vec)
   2087 {
   2088     uint32		ms_bit, ms_max, msb;
   2089     uint32		ls_bits[2];
   2090     mmu_ipmc_vlan_tbl_entry_t vlan_entry;
   2091     int	                vlan_ptr, last_vlan_ptr, last_write_ptr;
   2092     int                 vlan_count = 0;
   2093     int                 repl_type;
   2094     int                 ls_len, if_cnt, nh_cnt, offset;
   2095     int                 nh_offset;
   2096     
   2097     if_cnt = soc_mem_index_count(unit, EGR_L3_INTFm);
   2098     nh_cnt = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
   2099     last_vlan_ptr = -1;
   2100     last_write_ptr = -1;
   2101     ls_len = soc_mem_field_length(unit, MMU_IPMC_VLAN_TBLm, LSB_VLAN_BMf);
   2102     if (SOC_IS_TD_TT(unit)) {
   2103         nh_offset = TD_EGR_L3_NEXT_HOP_OFFSET;
   2104     } else {
   2105         /* coverity[large_shift : FALSE] */
   2106         nh_offset = (1 << (soc_mem_field_length(unit, MMU_IPMC_VLAN_TBLm,
   2107                                                    MSB_VLANf) - 1)) * ls_len;
   2108     }
   2109     /* Iterate over the two replication types - interfaces and next hops */
   2110     for (repl_type = 0; repl_type < 2; repl_type++) {
   2111         if (repl_type == 0) {
   2112             ms_max = _SHR_BITDCLSIZE(if_cnt) / 2; /* 32 -> 64 */
   2113         } else {
   2114             ms_max = _SHR_BITDCLSIZE(nh_cnt) / 2; /* 32 -> 64 */
   2115         }
   2116         for (ms_bit = 0; ms_bit < ms_max; ms_bit++) {
   2117             offset = (repl_type == 0) ? 0 : _SHR_BITDCLSIZE(if_cnt);
   2118             ls_bits[0] = intf_vec[offset + 2 * ms_bit + 0];
   2119             ls_bits[1] = intf_vec[offset + 2 * ms_bit + 1];
   2120             if ((ls_bits[0] != 0) || (ls_bits[1] != 0)) {
   2121                 vlan_ptr = _tr2_ipmc_repl_next_free_ptr(unit);
   2122                 if (last_vlan_ptr > 0) {
   2123                     /* Write previous non-zero entry */
   2124                     soc_MMU_IPMC_VLAN_TBLm_field32_set(unit,
   2125                             &vlan_entry, NEXTPTRf,
   2126                             (vlan_ptr > 0) ? vlan_ptr : last_vlan_ptr);
   2127                     /* If vlan_ptr <= 0, terminate so
   2128                      * later cleanup can remove the chain. */
   2129                     SOC_IF_ERROR_RETURN
   2130                         (WRITE_MMU_IPMC_VLAN_TBLm(unit,
   2131                             MEM_BLOCK_ALL, last_vlan_ptr, &vlan_entry));
   2132                     last_write_ptr = last_vlan_ptr;
   2133                     if (vlan_ptr < 0) {
   2134                         _bcm_tr2_repl_list_free(unit, *start_index);
   2135                         return BCM_E_RESOURCE;
   2136                     }
   2137                 } else {
   2138                     if (vlan_ptr < 0) {
   2139                         return BCM_E_RESOURCE;
   2140                     }
   2141                     *start_index = vlan_ptr;
   2142                 }
   2143                 sal_memset(&vlan_entry, 0, sizeof(vlan_entry));
   2144                 if (repl_type == 1) {
   2145                     /* Replication is over next hops */
   2146                     msb = ms_bit + nh_offset / 64;
   2147                 } else {
   2148                     /* Replication is over interfaces */
   2149                     msb = ms_bit;
   2150                 }
   2151                 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry,
   2152                                                    MSB_VLANf, msb);
   2153                 soc_MMU_IPMC_VLAN_TBLm_field_set(unit, &vlan_entry,
   2154                                                  LSB_VLAN_BMf, ls_bits);
   2155                 IPMC_REPL_VE_USED_SET(unit, vlan_ptr);
   2156                 vlan_count +=
   2157                     _shr_popcount(ls_bits[0]) + _shr_popcount(ls_bits[1]);
   2158                 last_vlan_ptr = vlan_ptr;
   2159             }
   2160         }
   2161     }
   2162 
   2163     if (last_vlan_ptr > 0) {
   2164         /* Write final entry */
   2165         soc_MMU_IPMC_VLAN_TBLm_field32_set(unit,
   2166                           &vlan_entry, NEXTPTRf, last_vlan_ptr);
   2167         SOC_IF_ERROR_RETURN
   2168             (WRITE_MMU_IPMC_VLAN_TBLm(unit,
   2169                    MEM_BLOCK_ALL, last_vlan_ptr, &vlan_entry));
   2170         
   2171         if (last_write_ptr > 0) {
   2172             soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry,
   2173                                              LSB_VLAN_BMf, ls_bits);
   2174             if ((_shr_popcount(ls_bits[0]) +
   2175                  _shr_popcount(ls_bits[1])) == 1) {
   2176                 /* Mark previous link with "last" flag */
   2177                 SOC_IF_ERROR_RETURN
   2178                     (READ_MMU_IPMC_VLAN_TBLm(unit,
   2179                           MEM_BLOCK_ANY, last_write_ptr, &vlan_entry));
   2180                 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry,
   2181                                                    LASTf, 1);
   2182                 SOC_IF_ERROR_RETURN
   2183                     (WRITE_MMU_IPMC_VLAN_TBLm(unit,
   2184                           MEM_BLOCK_ALL, last_write_ptr, &vlan_entry));
   2185             }
   2186         }
   2187     }
   2188 
   2189     *count = vlan_count;
   2190     return BCM_E_NONE;
   2191 }
   2192 
   2193 /*
   2194  * Function:
   2195  *    _bcm_kt_repl_list_write
   2196  * Description:
   2197  *    Write the VLAN list contained in vlan_vec into the HW table.
   2198  *    Return the start_index and total VLAN count.
   2199  */
   2200 
   2201 STATIC int
   2202 _bcm_kt_repl_list_write(int unit, int *start_index, int *count,
   2203                         SHR_BITDCL *intf_vec, int intf_count, 
   2204                         int nh_count)
   2205 {
   2206     uint32        ms_bit, ms_max, msb;
   2207     uint32        ls_bits[2];
   2208     mmu_ipmc_vlan_tbl_entry_t vlan_entry;
   2209     int                 vlan_ptr, last_vlan_ptr, last_write_ptr;
   2210     int                 vlan_count = 0;
   2211     int                 repl_type = 0;
   2212     int                 if_cnt, nh_cnt, offset;
   2213     int                 nh_offset;
   2214     int                 head = 1;
   2215 
   2216     if_cnt = soc_mem_index_count(unit, EGR_L3_INTFm);
   2217     nh_cnt = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
   2218     last_vlan_ptr = -1;
   2219     last_write_ptr = -1;
   2220 
   2221     /* coverity[large_shift : FALSE] */
   2222     nh_offset = (1 << (soc_mem_field_length(unit, MMU_IPMC_VLAN_TBLm,
   2223                                             MSB_VLANf) - 1)) * 64;
   2224 
   2225     if ((intf_count > 0) && (nh_count > 0)) {
   2226         /* there is no need to have a mixed replication types in a given
   2227          * mcast grpup */
   2228         return BCM_E_PARAM;
   2229     }
   2230 
   2231     if (nh_count > 0) {
   2232         repl_type = 1;
   2233         ms_max = _SHR_BITDCLSIZE(nh_cnt) / 2; /* 32 -> 64 */
   2234     } else {
   2235         ms_max = _SHR_BITDCLSIZE(if_cnt) / 2; /* 32 -> 64 */ 
   2236     }
   2237 
   2238     offset = (repl_type == 0) ? 0 : _SHR_BITDCLSIZE(if_cnt);
   2239     for (ms_bit = 0; ms_bit < ms_max; ms_bit++) {
   2240         ls_bits[0] = intf_vec[offset + 2 * ms_bit + 0];
   2241         ls_bits[1] = intf_vec[offset + 2 * ms_bit + 1];
   2242         if ((ls_bits[0] != 0) || (ls_bits[1] != 0)) {
   2243             if (soc_feature(unit, soc_feature_ipmc_reduced_table_size)) {
   2244                 vlan_ptr = _kt_ipmc_repl_next_free_ptr(unit, head);
   2245                 head = 0;
   2246             } else {
   2247                 vlan_ptr = _tr2_ipmc_repl_next_free_ptr(unit);
   2248             }
   2249             if (last_vlan_ptr > 0) {
   2250                 /* Write previous non-zero entry */
   2251                 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit,
   2252                         &vlan_entry, NEXTPTRf,
   2253                         (vlan_ptr > 0) ? vlan_ptr : last_vlan_ptr);
   2254                 /* If vlan_ptr <= 0, terminate so
   2255                              * later cleanup can remove the chain. */
   2256                 SOC_IF_ERROR_RETURN
   2257                     (WRITE_MMU_IPMC_VLAN_TBLm(unit,
   2258                         MEM_BLOCK_ALL, last_vlan_ptr, &vlan_entry));
   2259                 last_write_ptr = last_vlan_ptr;
   2260                 if (vlan_ptr < 0) {
   2261                     _bcm_tr2_repl_list_free(unit, *start_index);
   2262                     return BCM_E_RESOURCE;
   2263                 }
   2264             } else {
   2265                 if (vlan_ptr < 0) {
   2266                     return BCM_E_RESOURCE;
   2267                 }
   2268                 *start_index = vlan_ptr;
   2269             }
   2270             sal_memset(&vlan_entry, 0, sizeof(vlan_entry));
   2271             if (repl_type == 1) {
   2272                 /* Replication is over next hops */
   2273                 msb = ms_bit + nh_offset / 64;
   2274             } else {
   2275                 /* Replication is over interfaces */
   2276                 msb = ms_bit;
   2277             }
   2278             soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry,
   2279                                                MSB_VLANf, msb);
   2280             soc_MMU_IPMC_VLAN_TBLm_field_set(unit, &vlan_entry,
   2281                                              LSB_VLAN_BMf, ls_bits);
   2282             IPMC_REPL_VE_USED_SET(unit, vlan_ptr);
   2283             vlan_count +=
   2284                 _shr_popcount(ls_bits[0]) + _shr_popcount(ls_bits[1]);
   2285             last_vlan_ptr = vlan_ptr;
   2286         }
   2287     }
   2288 
   2289     if (last_vlan_ptr > 0) {
   2290         /* Write final entry */
   2291         if (soc_feature(unit, soc_feature_ipmc_reduced_table_size) &&
   2292             vlan_count == 1) {
   2293             soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry, 
   2294                                                NEXTPTRf, 1);
   2295             soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry, 
   2296                                                LASTf, 1);
   2297 			
   2298         } else {
   2299             soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry, 
   2300                                                NEXTPTRf, last_vlan_ptr);
   2301         }
   2302         SOC_IF_ERROR_RETURN
   2303             (WRITE_MMU_IPMC_VLAN_TBLm(unit,
   2304                    MEM_BLOCK_ALL, last_vlan_ptr, &vlan_entry));
   2305 
   2306         if (last_write_ptr > 0) {
   2307             soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry,
   2308                                              LSB_VLAN_BMf, ls_bits);
   2309             if ((_shr_popcount(ls_bits[0]) +
   2310                  _shr_popcount(ls_bits[1])) == 1) {
   2311                 /* Mark previous link with "last" flag */
   2312                 SOC_IF_ERROR_RETURN
   2313                     (READ_MMU_IPMC_VLAN_TBLm(unit,
   2314                           MEM_BLOCK_ANY, last_write_ptr, &vlan_entry));
   2315                 soc_MMU_IPMC_VLAN_TBLm_field32_set(unit, &vlan_entry,
   2316                                                    LASTf, 1);
   2317                 SOC_IF_ERROR_RETURN
   2318                     (WRITE_MMU_IPMC_VLAN_TBLm(unit,
   2319                           MEM_BLOCK_ALL, last_write_ptr, &vlan_entry));
   2320             }
   2321         }
   2322     }
   2323 
   2324     *count = vlan_count;
   2325     return BCM_E_NONE;
   2326 }
   2327 
   2328 /*
   2329  * Function:
   2330  *	bcm_tr2_ipmc_egress_intf_set
   2331  * Purpose:
   2332  *	Assign set of egress interfaces to port's replication list for chosen
   2333  *	IPMC group.
   2334  * Parameters:
   2335  *	unit     - StrataSwitch PCI device unit number.
   2336  *	ipmc_id  - The index number.
   2337  *	port     - port to list.
   2338  *	if_count - number of interfaces in replication list.
   2339  *      if_array - (IN) List of interface numbers.
   2340  *      check_port - (IN) If if_array consists of L3 interfaces, this parameter 
   2341  *                        controls whether to check the given port is a member
   2342  *                        in each L3 interface's VLAN. This check should be  
   2343  *                        disabled when not needed, in order to improve
   2344  *                        performance.
   2345  * Returns:
   2346  *	BCM_E_XXX
   2347  */
   2348 
   2349 int
   2350 bcm_tr2_ipmc_egress_intf_set(int unit, int ipmc_id, bcm_port_t port,
   2351                             int if_count, bcm_if_t *if_array, int check_port)
   2352 {
   2353     int			rv = BCM_E_NONE;
   2354     SHR_BITDCL          *intf_vec = NULL;
   2355     int			list_start_ptr, prev_start_ptr;
   2356     int                 alloc_size, repl_hash, vlan_count, last_flag;
   2357     int                 if_num, partition;
   2358     int                 intf_count = 0;
   2359     int                 nh_count = 0;
   2360     bcm_l3_intf_t       l3_intf;
   2361     _bcm_repl_list_info_t *rli_start, *rli_current, *rli_prev;
   2362 
   2363     IPMC_REPL_INIT(unit);
   2364     IPMC_REPL_ID(unit, ipmc_id);
   2365     REPL_PORT_CHECK(unit, port);
   2366 
   2367     if ((uint32)if_count > IPMC_REPL_INTF_TOTAL(unit)) {
   2368         return BCM_E_PARAM;
   2369     }
   2370 
   2371     /* Partition between L3 interfaces and NHIs in the intf_vec
   2372      * intf_vec = [L3 interfaces, NHIs] */
   2373     partition = soc_mem_index_count(unit, EGR_L3_INTFm);
   2374 
   2375     alloc_size = SHR_BITALLOCSIZE(IPMC_REPL_INTF_TOTAL(unit));
   2376     intf_vec = sal_alloc(alloc_size, "IPMC repl interface vector");
   2377     if (intf_vec == NULL) {
   2378         return BCM_E_MEMORY;
   2379     }
   2380     sal_memset(intf_vec, 0, alloc_size);
   2381 
   2382     IPMC_REPL_LOCK(unit);
   2383     if ((if_count == 0) && 
   2384         IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id) == 0) {
   2385         goto intf_set_done;
   2386     }
   2387 
   2388     /* Interface validation and vector construction */
   2389     for (if_num = 0; if_num < if_count; if_num++) {
   2390         if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, if_array[if_num]) && 
   2391             (uint32)(if_array[if_num]) > partition) {
   2392             rv = BCM_E_PARAM;
   2393             goto intf_set_done;
   2394         }
   2395         if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, if_array[if_num])) {
   2396             /* L3 interface is used */
   2397             if (check_port) {
   2398                 bcm_l3_intf_t_init(&l3_intf);
   2399                 l3_intf.l3a_intf_id = if_array[if_num];
   2400                 if ((rv = bcm_esw_l3_intf_get(unit, &l3_intf)) < 0) {
   2401                     goto intf_set_done;
   2402                 }
   2403             }
   2404             SHR_BITSET(intf_vec, if_array[if_num]);
   2405             intf_count++;
   2406         } else {
   2407             /* Next hop is used */
   2408             SHR_BITSET(intf_vec, partition + if_array[if_num] - 
   2409                        BCM_XGS3_DVP_EGRESS_IDX_MIN(unit));
   2410             nh_count++;
   2411         }
   2412     }
   2413 
   2414     /* Check previous group pointer */
   2415     if ((rv = _tr2_ipmc_vlan_ptr(unit, ipmc_id, port,
   2416                                 &prev_start_ptr, 0, 0)) < 0) {
   2417         goto intf_set_done;
   2418     }
   2419 
   2420     /* Search for list already in table */
   2421     rli_start = IPMC_REPL_LIST_INFO(unit);
   2422 
   2423     repl_hash =
   2424         _shr_crc32b(0, (uint8 *)intf_vec, IPMC_REPL_INTF_TOTAL(unit));
   2425 
   2426     for (rli_current = rli_start; rli_current != NULL;
   2427          rli_current = rli_current->next) {
   2428         if (repl_hash == rli_current->hash) {
   2429             rv = _bcm_tr2_repl_list_compare(unit, rli_current->index,
   2430                                            intf_vec);
   2431             if (rv == BCM_E_NOT_FOUND) {
   2432                 continue; /* Not a match */
   2433             } else if (rv < 0) {
   2434                 goto intf_set_done; /* Access error */
   2435             } else {
   2436                 break; /* Match */
   2437             }
   2438         }
   2439     }
   2440 
   2441     if (rli_current != NULL) {
   2442         /* Found a match, point to here and increase reference count */
   2443         if (prev_start_ptr == rli_current->index) {
   2444             /* We're already pointing to this list, so done */
   2445             rv = BCM_E_NONE;
   2446             goto intf_set_done;
   2447         } else {
   2448             list_start_ptr = rli_current->index;
   2449             vlan_count = rli_current->list_size;
   2450         }
   2451     } else {
   2452         /* Not a match, make a new chain */
   2453         if (!SOC_IS_KATANAX(unit)) {
   2454             if ((rv = _bcm_tr2_repl_list_write(unit, &list_start_ptr,
   2455                                              &vlan_count, intf_vec)) < 0) {
   2456                 goto intf_set_done;
   2457             }
   2458         } else {
   2459             if ((rv = _bcm_kt_repl_list_write(unit, &list_start_ptr,
   2460                                              &vlan_count, intf_vec,
   2461                                              intf_count, nh_count)) < 0) {
   2462                 goto intf_set_done;
   2463             }
   2464         }
   2465 
   2466         if (vlan_count > 0) {
   2467             /* Update data structures */
   2468             alloc_size = sizeof(_bcm_repl_list_info_t);
   2469             rli_current = sal_alloc(alloc_size, "IPMC repl list info");
   2470             if (rli_current == NULL) {
   2471                 /* Release list */
   2472                 _bcm_tr2_repl_list_free(unit, list_start_ptr);
   2473                 rv = BCM_E_MEMORY;
   2474                 goto intf_set_done;
   2475             }
   2476             sal_memset(rli_current, 0, alloc_size);
   2477             rli_current->index = list_start_ptr;
   2478             rli_current->hash = repl_hash;
   2479             rli_current->next = rli_start;
   2480             rli_current->list_size = vlan_count;
   2481             IPMC_REPL_LIST_INFO(unit) = rli_current;
   2482             rli_start = rli_current;
   2483         }
   2484     }
   2485 
   2486     last_flag = (vlan_count == 1);
   2487 
   2488     if (vlan_count > 0) {
   2489         if ((rv = _tr2_ipmc_vlan_ptr(unit, ipmc_id, port,
   2490                                     &list_start_ptr, last_flag, 1)) < 0) {
   2491             if (rli_current->refcount == 0) {
   2492                 /* This was new */
   2493                 _bcm_tr2_repl_list_free(unit, list_start_ptr);
   2494                 IPMC_REPL_LIST_INFO(unit) = rli_current->next;
   2495                 sal_free(rli_current);
   2496             }
   2497             goto intf_set_done;
   2498         }
   2499 
   2500         (rli_current->refcount)++;
   2501         /* we don't need this rli_current anymore */
   2502     } else if (prev_start_ptr != 0) {
   2503         list_start_ptr = 0;
   2504         if ((rv = _tr2_ipmc_vlan_ptr(unit, ipmc_id, port,
   2505                                     &list_start_ptr, last_flag, 1)) < 0) {
   2506             goto intf_set_done;
   2507         }
   2508     }
   2509     IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id) = vlan_count;
   2510 
   2511     if (prev_start_ptr != 0) {
   2512         rli_prev = NULL;
   2513         for (rli_current = rli_start; rli_current != NULL;
   2514              rli_current = rli_current->next) {
   2515             if (prev_start_ptr == rli_current->index) {
   2516                 (rli_current->refcount)--;
   2517                 if (rli_current->refcount == 0) {
   2518                     /* Free these linked list entries */
   2519                     rv = _bcm_tr2_repl_list_free(unit, prev_start_ptr);
   2520                     /* If we have an error, we'll fall out anyway */
   2521                     if (rli_prev == NULL) {
   2522                         IPMC_REPL_LIST_INFO(unit) = rli_current->next;
   2523                     } else {
   2524                         rli_prev->next = rli_current->next;
   2525                     }
   2526                     sal_free(rli_current);
   2527                 }
   2528                 break;
   2529             }
   2530             rli_prev = rli_current;
   2531         }
   2532     }
   2533 
   2534  intf_set_done:
   2535     IPMC_REPL_UNLOCK(unit);
   2536     if (intf_vec != NULL) {
   2537         sal_free(intf_vec);
   2538     }
   2539     return rv;
   2540 }
   2541 
   2542 /*
   2543  * Function:
   2544  *	bcm_tr2_ipmc_egress_intf_get
   2545  * Purpose:
   2546  *	Retreieve set of egress interfaces in port's replication list
   2547  *      for chosen IPMC group.
   2548  * Parameters:
   2549  *	unit     - StrataSwitch PCI device unit number.
   2550  *	ipmc_id  - The index number.
   2551  *	port     - port to list.
   2552  *	if_max   - maximum number of interfaces in replication list.
   2553  *      if_array - (OUT) List of interface numbers.
   2554  *	if_count - (OUT) number of interfaces returned in replication list.
   2555  * Returns:
   2556  *	BCM_E_XXX
   2557  * Notes:
   2558  *      If the input parameter if_max = 0, return in the output parameter
   2559  *      if_count the total number of interfaces in the specified multicast 
   2560  *      group's replication list.
   2561  */
   2562 
   2563 int
   2564 bcm_tr2_ipmc_egress_intf_get(int unit, int ipmc_id, bcm_port_t port,
   2565                             int if_max, bcm_if_t *if_array, int *if_count)
   2566 {
   2567     int			rv = BCM_E_NONE;
   2568     uint32              ls_bits[2];
   2569     mmu_ipmc_vlan_tbl_entry_t vlan_entry;
   2570     int                 vlan_ptr, last_vlan_ptr;
   2571     uint32              vlan_count;
   2572     int                 ls_pos, ls_len;
   2573     int                 rvth = BCM_E_NONE;
   2574     int                 intf_base, nh_offset;
   2575 
   2576     IPMC_REPL_INIT(unit);
   2577     IPMC_REPL_ID(unit, ipmc_id);
   2578     REPL_PORT_CHECK(unit, port);
   2579 
   2580     if (if_max < 0) {
   2581         return BCM_E_PARAM;
   2582     }
   2583 
   2584     IPMC_REPL_LOCK(unit);
   2585     if (IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id) == 0) {
   2586         *if_count = 0;
   2587         IPMC_REPL_UNLOCK(unit);
   2588         return rvth;
   2589     }
   2590 
   2591     if ((rv = _tr2_ipmc_vlan_ptr(unit, ipmc_id, port, &vlan_ptr, 0, 0)) < 0) {
   2592         goto intf_get_done;
   2593     }
   2594     last_vlan_ptr = -1;
   2595     vlan_count = 0;
   2596     ls_len = soc_mem_field_length(unit, MMU_IPMC_VLAN_TBLm, LSB_VLAN_BMf);
   2597     if (SOC_IS_TD_TT(unit)) {
   2598         nh_offset = TD_EGR_L3_NEXT_HOP_OFFSET;
   2599     } else {
   2600         /* coverity[large_shift : FALSE] */
   2601         nh_offset = (1 << (soc_mem_field_length(unit, MMU_IPMC_VLAN_TBLm,
   2602                                                 MSB_VLANf) - 1)) * ls_len;
   2603     }
   2604     while (vlan_ptr != last_vlan_ptr) {
   2605         if ((rv = READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ANY,
   2606                                           vlan_ptr, &vlan_entry)) < 0) {
   2607             goto intf_get_done;
   2608         }
   2609         /* Each MSB represents 64 entries in LSB bitmap */
   2610         intf_base = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, &vlan_entry,
   2611                                                        MSB_VLANf) * ls_len;
   2612         soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry,
   2613                                          LSB_VLAN_BMf, ls_bits);
   2614         /* Using MSB, check if L3 interface or next hop */
   2615         
   2616         for (ls_pos = 0; ls_pos < ls_len; ls_pos++) {
   2617             if (ls_bits[ls_pos / 32] & (1 << (ls_pos % 32))) {
   2618                 if (if_max == 0) {
   2619                     vlan_count++;
   2620                 } else {
   2621                     /* Check if L3 interface or next hop */
   2622                     if (intf_base >= nh_offset) {
   2623                         /* Entry contains next hops */
   2624                         if_array[vlan_count++] = intf_base - nh_offset +
   2625                             ls_pos + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   2626                     } else {
   2627                         /* Entry contains interfaces */
   2628                         if_array[vlan_count++] = intf_base + ls_pos;
   2629                     }
   2630                     if (vlan_count == (uint32)if_max) {
   2631                         *if_count = vlan_count;
   2632                         goto intf_get_done;
   2633                     }
   2634                 }
   2635             }
   2636         }
   2637         last_vlan_ptr = vlan_ptr;
   2638         vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   2639                                                       &vlan_entry, NEXTPTRf);
   2640 
   2641         if (vlan_count >= IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) {
   2642             break;
   2643         }
   2644     }
   2645 
   2646     *if_count = vlan_count;
   2647 
   2648  intf_get_done:
   2649     IPMC_REPL_UNLOCK(unit);
   2650     return rv;
   2651 }
   2652 
   2653 /*
   2654  * Function:
   2655  *      bcm_tr2_ipmc_repl_add
   2656  * Purpose:
   2657  *      Add VLAN to selected ports' replication list for chosen
   2658  *      IPMC group.
   2659  *Parameters:
   2660  *      unit     - StrataSwitch PCI device unit number.
   2661  *      ipmc_id  - The index number.
   2662  *      port     - port to add.
   2663  *      vlan     - VLAN to replicate.
   2664  * Returns:
   2665  *      BCM_E_XXX
   2666  */
   2667 int
   2668 bcm_tr2_ipmc_repl_add(int unit, int ipmc_id, bcm_port_t port,
   2669                      bcm_vlan_t vlan)
   2670 {
   2671     int alloc_size, intf_max, if_count, rv = BCM_E_NONE;
   2672     bcm_if_t *if_array = NULL;
   2673     pbmp_t pbmp, ubmp;
   2674     bcm_l3_intf_t l3_intf;
   2675 
   2676     IPMC_REPL_INIT(unit);
   2677     IPMC_REPL_ID(unit, ipmc_id);
   2678     REPL_PORT_CHECK(unit, port);
   2679 
   2680     /* Check if port belongs to this VLAN */
   2681     BCM_IF_ERROR_RETURN
   2682         (bcm_esw_vlan_port_get(unit, vlan, &pbmp, &ubmp));
   2683     if (!SOC_PBMP_MEMBER(pbmp, port)) {
   2684         return BCM_E_PARAM;
   2685     }
   2686 
   2687     bcm_l3_intf_t_init(&l3_intf);
   2688     l3_intf.l3a_vid = vlan;
   2689     if (bcm_esw_l3_intf_find_vlan(unit, &l3_intf) < 0) {
   2690         return BCM_E_PARAM;
   2691     }
   2692 
   2693     intf_max = IPMC_REPL_INTF_TOTAL(unit);
   2694     alloc_size = intf_max * sizeof(bcm_if_t);
   2695     if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   2696     if (if_array == NULL) {
   2697         return BCM_E_MEMORY;
   2698     }
   2699 
   2700     IPMC_REPL_LOCK(unit);
   2701     rv = bcm_tr2_ipmc_egress_intf_get(unit, ipmc_id, port, intf_max,
   2702                                      if_array, &if_count);
   2703     if (BCM_SUCCESS(rv)) {
   2704         if (if_count < intf_max) {
   2705             if_array[if_count++] = l3_intf.l3a_intf_id;
   2706             rv = bcm_tr2_ipmc_egress_intf_set(unit, ipmc_id, port,
   2707                                              if_count, if_array, FALSE);
   2708         } else {
   2709             rv = BCM_E_EXISTS;
   2710         }
   2711     }
   2712 
   2713     IPMC_REPL_UNLOCK(unit);
   2714     sal_free(if_array);
   2715     return rv;
   2716 }
   2717 
   2718 /*
   2719  * Function:
   2720  *      bcm_tr2_ipmc_repl_delete
   2721  * Purpose:
   2722  *      Remove VLAN from selected ports' replication list for chosen
   2723  *      IPMC group.
   2724  * Parameters:
   2725  *      unit     - StrataSwitch PCI device unit number.
   2726  *      ipmc_id  - The index number.
   2727  *      port     - port to remove.
   2728  *      vlan     - VLAN to delete from replication.
   2729  * Returns:
   2730  *      BCM_E_XXX
   2731  */
   2732 
   2733 int
   2734 bcm_tr2_ipmc_repl_delete(int unit, int ipmc_id, bcm_port_t port,
   2735                         bcm_vlan_t vlan)
   2736 {
   2737     int alloc_size, intf_max, if_count, if_cur, match, rv = BCM_E_NONE;
   2738     bcm_if_t *if_array = NULL;
   2739     bcm_l3_intf_t       l3_intf;
   2740 
   2741     IPMC_REPL_INIT(unit);
   2742     IPMC_REPL_ID(unit, ipmc_id);
   2743     REPL_PORT_CHECK(unit, port);
   2744 
   2745     if (!IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) {
   2746         return BCM_E_NOT_FOUND;
   2747     }
   2748 
   2749     bcm_l3_intf_t_init(&l3_intf);
   2750     l3_intf.l3a_vid = vlan;
   2751     if (bcm_esw_l3_intf_find_vlan(unit, &l3_intf) < 0) {
   2752         return BCM_E_PARAM;
   2753     }
   2754 
   2755 
   2756     intf_max = IPMC_REPL_INTF_TOTAL(unit);
   2757     alloc_size = intf_max * sizeof(bcm_if_t);
   2758     if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   2759     if (if_array == NULL) {
   2760         return BCM_E_MEMORY;
   2761     }
   2762 
   2763     IPMC_REPL_LOCK(unit);
   2764     rv = bcm_tr2_ipmc_egress_intf_get(unit, ipmc_id, port, intf_max,
   2765                                      if_array, &if_count);
   2766     if (BCM_SUCCESS(rv)) {
   2767         match = FALSE;
   2768         for (if_cur = 0; if_cur < if_count; if_cur++) {
   2769             if (match) {
   2770                 if_array[if_cur - 1] = if_array[if_cur];
   2771             } else {
   2772                 if (if_array[if_cur] == l3_intf.l3a_intf_id) {
   2773                     match = TRUE;
   2774                 }
   2775             }
   2776         }
   2777         if (match) {
   2778             if_count--;
   2779             rv = bcm_tr2_ipmc_egress_intf_set(unit, ipmc_id, port,
   2780                                              if_count, if_array, FALSE);
   2781         } else {
   2782             rv = BCM_E_NOT_FOUND;
   2783         }
   2784     }
   2785     IPMC_REPL_UNLOCK(unit);
   2786     sal_free(if_array);
   2787     return rv;
   2788 }
   2789 
   2790 /*
   2791  * Function:
   2792  *      bcm_tr2_ipmc_repl_set
   2793  * Purpose:
   2794  *      Assign set of VLANs provided to port's replication list for chosen
   2795  *      IPMC group.
   2796  * Parameters:
   2797  *      unit     - StrataSwitch PCI device unit number.
   2798  *      ipmc_id  - The index number.
   2799  *      port     - port to list.
   2800  *      vlan_vec - (IN) vector of replicated VLANs common to selected ports.
   2801  * Returns:
   2802  *      BCM_E_XXX
   2803  */
   2804 
   2805 int
   2806 bcm_tr2_ipmc_repl_set(int unit, int ipmc_id, bcm_port_t port,
   2807                      bcm_vlan_vector_t vlan_vec)
   2808 {
   2809     int rv = BCM_E_NONE;
   2810     bcm_if_t *if_array = NULL;
   2811     bcm_l3_intf_t l3_intf;
   2812     pbmp_t pbmp, ubmp;
   2813     int  intf_num, intf_max, alloc_size, vid;
   2814 
   2815     if (!SOC_IPMCREPLSHR_GET(unit) &&
   2816         !soc_feature(unit, soc_feature_ipmc_repl_penultimate)) {
   2817         return BCM_E_CONFIG;
   2818     }
   2819 
   2820     IPMC_REPL_INIT(unit);
   2821     IPMC_REPL_ID(unit, ipmc_id);
   2822     REPL_PORT_CHECK(unit, port);
   2823 
   2824     intf_max = IPMC_REPL_INTF_TOTAL(unit);
   2825     alloc_size = intf_max * sizeof(bcm_if_t);
   2826     if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   2827     if (if_array == NULL) {
   2828         return BCM_E_MEMORY;
   2829     }
   2830 
   2831     sal_memset(if_array, 0, alloc_size);
   2832     intf_num = 0;
   2833     for (vid = BCM_VLAN_MIN; vid < BCM_VLAN_MAX; vid++) {
   2834         if (BCM_VLAN_VEC_GET(vlan_vec, vid)) {
   2835             rv = bcm_esw_vlan_port_get(unit, vid, &pbmp, &ubmp);
   2836             if (BCM_FAILURE(rv)) {
   2837                 sal_free(if_array);
   2838                 return rv;
   2839             }
   2840             if (!BCM_PBMP_MEMBER(pbmp, port)) {
   2841                 sal_free(if_array);
   2842                 return BCM_E_PARAM;
   2843             }
   2844             bcm_l3_intf_t_init(&l3_intf);
   2845             l3_intf.l3a_vid = vid;
   2846             if ((rv = bcm_esw_l3_intf_find_vlan(unit, &l3_intf)) < 0) {
   2847                 sal_free(if_array);
   2848                 return rv;
   2849             }
   2850             if_array[intf_num++] = l3_intf.l3a_intf_id;
   2851         }
   2852     }
   2853 
   2854     rv = bcm_tr2_ipmc_egress_intf_set(unit, ipmc_id, port,
   2855                                      intf_num, if_array, FALSE);
   2856 
   2857     sal_free(if_array);
   2858     return rv;
   2859 }
   2860 
   2861 /*
   2862  * Function:
   2863  *      bcm_tr2_ipmc_repl_get
   2864  * Purpose:
   2865  *      Return set of VLANs selected for port's replication list for chosen
   2866  *      IPMC group.
   2867  * Parameters:
   2868  *      unit     - StrataSwitch PCI device unit number.
   2869  *      ipmc_id  - The index number.
   2870  *      port     - port to list.
   2871  *      vlan_vec - (OUT) vector of replicated VLANs common to selected ports.
   2872  * Returns:
   2873  *      BCM_E_XXX
   2874  */
   2875 
   2876 int
   2877 bcm_tr2_ipmc_repl_get(int unit, int ipmc_id, bcm_port_t port,
   2878                         bcm_vlan_vector_t vlan_vec)
   2879 {
   2880     int                 rv = BCM_E_NONE;
   2881     uint32              ls_bits[2];
   2882     mmu_ipmc_vlan_tbl_entry_t vlan_entry;
   2883     bcm_l3_intf_t       l3_intf;
   2884     bcm_l3_egress_t     egress_object;
   2885     int                 vlan_ptr, last_vlan_ptr;
   2886     uint32              vlan_count;
   2887     int                 ls_pos, ls_len, nh_idx;
   2888     int                 rvth = BCM_E_NONE;
   2889     int                 intf_base, nh_offset;
   2890 
   2891     IPMC_REPL_INIT(unit);
   2892 
   2893     IPMC_REPL_ID(unit, ipmc_id);
   2894 
   2895     REPL_PORT_CHECK(unit, port);
   2896 
   2897     BCM_VLAN_VEC_ZERO(vlan_vec);
   2898 
   2899     IPMC_REPL_LOCK(unit);
   2900     if (IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id) == 0) {
   2901         IPMC_REPL_UNLOCK(unit);
   2902         return rvth;
   2903     }
   2904 
   2905     if ((rv = _tr2_ipmc_vlan_ptr(unit, ipmc_id, port, &vlan_ptr, 0, 0)) < 0) {
   2906         goto get_done;
   2907     }
   2908     last_vlan_ptr = -1;
   2909     vlan_count = 0;
   2910     ls_len = soc_mem_field_length(unit, MMU_IPMC_VLAN_TBLm, LSB_VLAN_BMf);
   2911     if (SOC_IS_TD_TT(unit)) {
   2912         nh_offset = TD_EGR_L3_NEXT_HOP_OFFSET;
   2913     } else {
   2914         /* coverity[large_shift : FALSE] */
   2915         nh_offset = (1 << (soc_mem_field_length(unit, MMU_IPMC_VLAN_TBLm,
   2916                                                 MSB_VLANf) - 1)) * ls_len;
   2917     }
   2918     while (vlan_ptr != last_vlan_ptr) {
   2919         if ((rv = READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ALL,
   2920                                           vlan_ptr, &vlan_entry)) < 0) {
   2921             goto get_done;
   2922         }
   2923         /* Each MSB represents 64 entries in LSB bitmap */
   2924         intf_base = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, &vlan_entry,
   2925                                                        MSB_VLANf) * ls_len;
   2926         soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry,
   2927                                          LSB_VLAN_BMf, ls_bits);
   2928         last_vlan_ptr = vlan_ptr;
   2929         vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   2930                                                       &vlan_entry, NEXTPTRf);
   2931 
   2932         /* Translate the HW L3 interfaces into the corresponding VLANs.
   2933          * Note, this may result in some loss of information.
   2934          */
   2935         for (ls_pos = 0; ls_pos < ls_len; ls_pos++) {
   2936             if (ls_bits[ls_pos / 32] & (1 << (ls_pos % 32))) {
   2937                 bcm_l3_intf_t_init(&l3_intf);
   2938                 if (intf_base >= nh_offset) {
   2939                     /* Next hop */
   2940                     nh_idx = intf_base - nh_offset + ls_pos +
   2941                         BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   2942                     if ((rv = bcm_esw_l3_egress_get(unit, nh_idx,
   2943                                                     &egress_object)) < 0) {
   2944                         goto get_done;
   2945                     }
   2946                     /* Coverity: egress_object.intf is initialized above
   2947                      * by bcm_esw_l3_egress_get. */
   2948                     /* coverity[uninit_use : FALSE] */
   2949                     l3_intf.l3a_intf_id = egress_object.intf;
   2950                 } else {
   2951                     /* L3 Interface */
   2952                     l3_intf.l3a_intf_id = intf_base + ls_pos;
   2953                 }
   2954                 if ((rv = bcm_esw_l3_intf_get(unit, &l3_intf)) < 0) {
   2955                     goto get_done;
   2956                 }
   2957                 BCM_VLAN_VEC_SET(vlan_vec, l3_intf.l3a_vid);
   2958                 vlan_count++;
   2959             }
   2960         }
   2961         if (vlan_count >= IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) {
   2962             break;
   2963         }
   2964     }
   2965 
   2966  get_done:
   2967     IPMC_REPL_UNLOCK(unit);
   2968     return rv;
   2969 }
   2970 
   2971 /*
   2972  * Function:
   2973  *      bcm_tr2_ipmc_repl_delete_all
   2974  * Purpose:
   2975  *      Remove all VLANs from selected ports' replication list for chosen
   2976  *      IPMC group.
   2977  * Parameters:
   2978  *      unit     - StrataSwitch PCI device unit number.
   2979  *      ipmc_id  - The MC index number.
   2980  *      port     - port from which to remove VLANs.
   2981  * Returns:
   2982  *      BCM_E_XXX
   2983  */
   2984 
   2985 int
   2986 bcm_tr2_ipmc_repl_delete_all(int unit, int ipmc_id, bcm_port_t port)
   2987 {
   2988     IPMC_REPL_INIT(unit);
   2989     IPMC_REPL_ID(unit, ipmc_id);
   2990     REPL_PORT_CHECK(unit, port);
   2991 
   2992     if (!IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) {
   2993         /* Nothing to do */
   2994         return BCM_E_NONE;
   2995     }
   2996 
   2997     return bcm_tr2_ipmc_egress_intf_set(unit, ipmc_id, port, 0, NULL, FALSE);
   2998 }
   2999 
   3000 /*
   3001  * Function:
   3002  *      bcm_tr2_ipmc_egress_intf_add
   3003  * Purpose:
   3004  *      Add L3 interface to selected ports' replication list for chosen
   3005  *      IPMC group.
   3006  * Parameters:
   3007  *      unit     - StrataSwitch PCI device unit number.
   3008  *      ipmc_id  - The index number.
   3009  *      port     - port to add.
   3010  *      l3_intf  - L3 interface to replicate.
   3011  * Returns:
   3012  *      BCM_E_XXX
   3013  */
   3014 int
   3015 bcm_tr2_ipmc_egress_intf_add(int unit, int ipmc_id, bcm_port_t port,
   3016                             bcm_l3_intf_t *l3_intf)
   3017 {
   3018     bcm_if_t *if_array = NULL;
   3019     int  intf_num, intf_max, alloc_size, rv = BCM_E_NONE;
   3020     pbmp_t pbmp, ubmp;
   3021 
   3022     IPMC_REPL_INIT(unit);
   3023     IPMC_REPL_ID(unit, ipmc_id);
   3024     REPL_PORT_CHECK(unit, port);
   3025 
   3026     /* Check if port belongs to this VLAN */
   3027     BCM_IF_ERROR_RETURN
   3028         (bcm_esw_vlan_port_get(unit, l3_intf->l3a_vid, &pbmp, &ubmp));
   3029     if (!SOC_PBMP_MEMBER(pbmp, port)) {
   3030         return BCM_E_PARAM;
   3031     }
   3032 
   3033     intf_max = IPMC_REPL_INTF_TOTAL(unit);
   3034     alloc_size = intf_max * sizeof(bcm_if_t);
   3035     if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   3036     if (if_array == NULL) {
   3037         return BCM_E_MEMORY;
   3038     }
   3039 
   3040     IPMC_REPL_LOCK(unit);
   3041     rv = bcm_tr2_ipmc_egress_intf_get(unit, ipmc_id, port, intf_max,
   3042                                      if_array, &intf_num);
   3043     if (BCM_SUCCESS(rv)) {
   3044         if (intf_num < intf_max) {
   3045             if_array[intf_num++] = l3_intf->l3a_intf_id;
   3046             rv = bcm_tr2_ipmc_egress_intf_set(unit, ipmc_id, port,
   3047                                              intf_num, if_array, FALSE);
   3048         } else {
   3049             rv = BCM_E_EXISTS;
   3050         }
   3051     }
   3052 
   3053     IPMC_REPL_UNLOCK(unit);
   3054     sal_free(if_array);
   3055     return rv;
   3056 }
   3057 
   3058 /*
   3059  * Function:
   3060  *      bcm_tr2_ipmc_egress_intf_delete
   3061  * Purpose:
   3062  *      Remove L3 interface from selected ports' replication list for chosen
   3063  *      IPMC group.
   3064  * Parameters:
   3065  *      unit     - StrataSwitch PCI device unit number.
   3066  *      ipmc_id  - The index number.
   3067  *      port     - port to remove.
   3068  *      l3_intf  - L3 interface to delete from replication.
   3069  * Returns:
   3070  *      BCM_E_XXX
   3071  */
   3072 int
   3073 bcm_tr2_ipmc_egress_intf_delete(int unit, int ipmc_id, bcm_port_t port,
   3074                                bcm_l3_intf_t *l3_intf)
   3075 {
   3076     bcm_if_t *if_array = NULL;
   3077     int alloc_size, intf_max, if_count, if_cur, match, rv = BCM_E_NONE;
   3078 
   3079     IPMC_REPL_INIT(unit);
   3080     IPMC_REPL_ID(unit, ipmc_id);
   3081     REPL_PORT_CHECK(unit, port);
   3082 
   3083     if (!IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) {
   3084         return BCM_E_NOT_FOUND;
   3085     }
   3086 
   3087 
   3088     intf_max = IPMC_REPL_INTF_TOTAL(unit);
   3089     alloc_size = intf_max * sizeof(bcm_if_t);
   3090     if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   3091     if (if_array == NULL) {
   3092         return BCM_E_MEMORY;
   3093     }
   3094 
   3095     IPMC_REPL_LOCK(unit);
   3096     rv = bcm_tr2_ipmc_egress_intf_get(unit, ipmc_id, port, intf_max,
   3097                                      if_array, &if_count);
   3098     if (BCM_SUCCESS(rv)) {
   3099         match = FALSE;
   3100         for (if_cur = 0; if_cur < if_count; if_cur++) {
   3101             if (match) {
   3102                 if_array[if_cur - 1] = if_array[if_cur];
   3103             } else {
   3104                 if (if_array[if_cur] == l3_intf->l3a_intf_id) {
   3105                     match = TRUE;
   3106                 }
   3107             }
   3108         }
   3109         if (match) {
   3110             if_count--;
   3111             rv = bcm_tr2_ipmc_egress_intf_set(unit, ipmc_id, port,
   3112                                              if_count, if_array, FALSE);
   3113         } else {
   3114             rv = BCM_E_NOT_FOUND;
   3115         }
   3116     }
   3117 
   3118     IPMC_REPL_UNLOCK(unit);
   3119     sal_free(if_array);
   3120     return rv;
   3121 }
   3122 
   3123 /*
   3124  * Function:
   3125  *      bcm_tr2_ipmc_repl_availability_get
   3126  * Purpose:
   3127  *      Get the percentage of IPMC repilication table that's free.
   3128  * Parameters:
   3129  *      unit - (IN) Device Number
   3130  *      available_percent - (OUT) Available percentage
   3131  * Returns:
   3132  *      BCM_E_XXX
   3133  */
   3134 int
   3135 bcm_tr2_ipmc_repl_availability_get(int unit, int *available_percent)
   3136 {
   3137     int                 ix, bit;
   3138     SHR_BITDCL          not_ptrs;
   3139     int                 num_available_entries;
   3140 
   3141     num_available_entries = 0;
   3142     for (ix = 0; ix < _SHR_BITDCLSIZE(IPMC_REPL_TOTAL(unit)); ix++) {
   3143         not_ptrs = ~_tr2_repl_info[unit]->bitmap_entries_used[ix];
   3144         if (not_ptrs) {
   3145             for (bit = 0; bit < SHR_BITWID; bit++) {
   3146                 if (not_ptrs & (1 << bit)) {
   3147                     num_available_entries++;
   3148                 }
   3149             }
   3150         }
   3151     }
   3152 
   3153     *available_percent = (100 * num_available_entries) / IPMC_REPL_TOTAL(unit);
   3154 
   3155     return BCM_E_NONE;
   3156 }
   3157 
   3158 /*
   3159  * Function:
   3160  *      bcm_tr2_ipmc_repl_list_split
   3161  * Purpose:
   3162  *      Split the list of encap ids into sublists that match existing
   3163  *      replication lists. The sublists do not overlap with each other.
   3164  * Parameters:
   3165  *      unit - (IN) Device Number
   3166  *      array_size       - (IN) Number of valid elements in encap_id_array and
   3167  *                              sublist_id_array
   3168  *      encap_id_array   - (IN) Array of encap ids
   3169  *      sublist_id_array - (OUT) Sublist id each encap id is assigned to
   3170  *      sublist_max   - (IN)  Max number of sublists allowed
   3171  *      sublist_count - (OUT) Number of sublists of used
   3172  * Returns:
   3173  *      BCM_E_XXX
   3174  */
   3175 int
   3176 bcm_tr2_ipmc_repl_list_split(int unit, int array_size,
   3177                     bcm_if_t *encap_id_array, int *sublist_id_array, 
   3178                     int sublist_max, int *sublist_count)
   3179 {
   3180     int rv = BCM_E_NONE;
   3181     int alloc_size;
   3182     SHR_BITDCL *intf_vec = NULL;
   3183     SHR_BITDCL *subset_intf_vec = NULL;
   3184     int partition;
   3185     int i;
   3186     int sublist_id;
   3187     int intf_vec_size, subset_size;
   3188     _bcm_repl_list_info_t *rli_current = NULL;
   3189     int vlan_ptr, last_vlan_ptr;
   3190     int is_subset;
   3191     uint32 ms_bit, hi_bit;
   3192     uint32 ls_bits[2];
   3193     mmu_ipmc_vlan_tbl_entry_t vlan_entry;
   3194     int ls_pos;
   3195     bcm_if_t encap_id;
   3196 
   3197     /* Input parameter check */
   3198 
   3199     if (array_size <= 0) {
   3200        return BCM_E_PARAM;
   3201     }
   3202 
   3203     if ((NULL == encap_id_array) || (NULL == sublist_id_array)) {
   3204        return BCM_E_PARAM;
   3205     }
   3206 
   3207     if (sublist_max <= 0) {
   3208         return BCM_E_PARAM;
   3209     }
   3210 
   3211     IPMC_REPL_LOCK(unit);
   3212 
   3213     /* Construct interface vector from encap_id_array */
   3214 
   3215     alloc_size = SHR_BITALLOCSIZE(IPMC_REPL_INTF_TOTAL(unit));
   3216     intf_vec = sal_alloc(alloc_size, "IPMC repl interface vector");
   3217     if (intf_vec == NULL) {
   3218         rv = BCM_E_MEMORY;
   3219         goto done;
   3220     }
   3221     sal_memset(intf_vec, 0, alloc_size);
   3222 
   3223     /* Partition between L3 interfaces and NHIs in the intf_vec
   3224      * intf_vec = [L3 interfaces, NHIs] */
   3225     partition = soc_mem_index_count(unit, EGR_L3_INTFm);
   3226 
   3227     for (i = 0; i < array_size; i++) {
   3228         if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, encap_id_array[i]) && 
   3229             (uint32)(encap_id_array[i]) > partition) {
   3230             rv = BCM_E_PARAM;
   3231             goto done;
   3232         }
   3233         if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, encap_id_array[i])) {
   3234             /* L3 interface is used */
   3235             SHR_BITSET(intf_vec, encap_id_array[i]);
   3236         } else {
   3237             /* Next hop is used */
   3238             SHR_BITSET(intf_vec, partition + encap_id_array[i] - 
   3239                        BCM_XGS3_DVP_EGRESS_IDX_MIN(unit));
   3240         }
   3241     }
   3242 
   3243     /* Traverse existing replication lists to find those that match subsets of
   3244      * the interface vector. As matching subsets are found, they are removed 
   3245      * from the interface vector. 
   3246      */
   3247 
   3248     subset_intf_vec = sal_alloc(alloc_size, "Subset IPMC repl interface vector");
   3249     if (subset_intf_vec == NULL) {
   3250         rv = BCM_E_MEMORY;
   3251         goto done;
   3252     }
   3253     sal_memset(subset_intf_vec, 0, alloc_size);
   3254 
   3255     sublist_id = 0;
   3256     SHR_BITCOUNT_RANGE(intf_vec, intf_vec_size, 0, IPMC_REPL_INTF_TOTAL(unit));
   3257 
   3258     for (rli_current = IPMC_REPL_LIST_INFO(unit);
   3259             rli_current != NULL;
   3260             rli_current = rli_current->next) {
   3261 
   3262         if (rli_current->list_size == 0) {
   3263             continue;
   3264         }
   3265 
   3266         if (rli_current->list_size > intf_vec_size) {
   3267             /* If the current list's size is greater than the number of
   3268              * set bits in interface vector, the current list cannot be
   3269              * a subset.
   3270              */
   3271             continue;
   3272         }
   3273 
   3274         vlan_ptr = rli_current->index;
   3275         last_vlan_ptr = -1;
   3276         /* coverity[large_shift : FALSE] */
   3277         hi_bit = (1 << (soc_mem_field_length(unit, MMU_IPMC_VLAN_TBLm,
   3278                         MSB_VLANf) - 1));
   3279         is_subset = TRUE;
   3280         sal_memset(subset_intf_vec, 0, alloc_size);
   3281         while (vlan_ptr != last_vlan_ptr) {
   3282             rv = READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ANY,
   3283                             vlan_ptr, &vlan_entry);
   3284             if (BCM_FAILURE(rv)) {
   3285                 goto done;
   3286             }
   3287 
   3288             ms_bit = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   3289                     &vlan_entry, MSB_VLANf);
   3290             soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry,
   3291                     LSB_VLAN_BMf, ls_bits);
   3292 
   3293             for (ls_pos = 0; ls_pos < 64; ls_pos++) {
   3294                 if (ls_bits[ls_pos / 32] & (1 << (ls_pos % 32))) {
   3295                     /* Using MSB, check if L3 interface or next hop */
   3296                     if (ms_bit & hi_bit) {
   3297                         /* Entry contains next hops */
   3298                         encap_id = ((ms_bit & (hi_bit - 1)) * 64) + ls_pos +
   3299                             BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   3300                         if (SHR_BITGET(intf_vec, partition + encap_id - 
   3301                                     BCM_XGS3_DVP_EGRESS_IDX_MIN(unit))) {
   3302                             SHR_BITSET(subset_intf_vec, partition + encap_id - 
   3303                                     BCM_XGS3_DVP_EGRESS_IDX_MIN(unit));
   3304                         } else {
   3305                             /* Not found in interface vector, 
   3306                              * the current list cannot be a subset.
   3307                              */ 
   3308                             is_subset = FALSE;
   3309                             break;
   3310                         } 
   3311                     } else {
   3312                         /* Entry contains L3 interfaces */
   3313                         encap_id = (ms_bit * 64) + ls_pos;
   3314                         if (SHR_BITGET(intf_vec, encap_id)) {
   3315                             SHR_BITSET(subset_intf_vec, encap_id);
   3316                         } else {
   3317                             /* Not found in interface vector, 
   3318                              * the current list cannot be a subset.
   3319                              */ 
   3320                             is_subset = FALSE;
   3321                             break;
   3322                         }
   3323                     }
   3324                 }
   3325             }
   3326             if (!is_subset) {
   3327                 break;
   3328             }
   3329 
   3330             last_vlan_ptr = vlan_ptr;
   3331             vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   3332                     &vlan_entry, NEXTPTRf);
   3333         }
   3334 
   3335         if (is_subset) {
   3336             /* Make sure subset_intf_vec is not all zeroes */
   3337             SHR_BITCOUNT_RANGE(subset_intf_vec, subset_size, 0,
   3338                     IPMC_REPL_INTF_TOTAL(unit));
   3339             if (subset_size > 0) {
   3340                 /* Set sublist id for those encap ids in encap_id_array that
   3341                  * belong to the subset.
   3342                  */
   3343                 for (i = 0; i < array_size; i++) {
   3344                     if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, encap_id_array[i])) {
   3345                         /* L3 interface is used */
   3346                         if (SHR_BITGET(subset_intf_vec, encap_id_array[i])) {
   3347                             sublist_id_array[i] = sublist_id;
   3348                         }
   3349                     } else {
   3350                         /* Next hop is used */
   3351                         if (SHR_BITGET(subset_intf_vec, partition + 
   3352                                     encap_id_array[i] -
   3353                                     BCM_XGS3_DVP_EGRESS_IDX_MIN(unit))) {
   3354                             sublist_id_array[i] = sublist_id;
   3355                         }
   3356                     }
   3357                 }
   3358 
   3359                 /* Update sublist id */
   3360                 sublist_id++;
   3361                 if (sublist_id == sublist_max) {
   3362                     break;
   3363                 }
   3364 
   3365                 /* Remove the found subset from interface vector */
   3366                 for (i = 0; i < IPMC_REPL_INTF_TOTAL(unit); i++) {
   3367                     if (SHR_BITGET(subset_intf_vec, i)) {
   3368                         SHR_BITCLR(intf_vec, i);
   3369                         intf_vec_size--;
   3370                         subset_size--;
   3371                         if (subset_size == 0) {
   3372                             break;
   3373                         }
   3374                     }
   3375                 }
   3376                 if (intf_vec_size == 0) {
   3377                     break;
   3378                 }
   3379             }
   3380         }
   3381     }
   3382 
   3383     if (NULL != sublist_count) {
   3384         *sublist_count = sublist_id;
   3385     }
   3386 
   3387 done:
   3388     if (intf_vec) {
   3389         sal_free(intf_vec);
   3390     }
   3391     if (subset_intf_vec) {
   3392         sal_free(subset_intf_vec);
   3393     }
   3394     IPMC_REPL_UNLOCK(unit);
   3395     return rv;
   3396 }
   3397 #ifdef BCM_KATANA2_SUPPORT
   3398 /*
   3399  * Function:
   3400  *      bcm_kt2_ipmc_repl_init
   3401  * Purpose:
   3402  *      Initialize IPMC replication.
   3403  * Parameters:
   3404  *      unit     - SOC unit #
   3405  * Returns:
   3406  *      BCM_E_XXX
   3407  */
   3408 int bcm_kt2_ipmc_repl_init(int unit) 
   3409 {
   3410     int    alloc_size;
   3411     uint32 entry[SOC_MAX_MEM_FIELD_WORDS];
   3412     bcm_port_t port;
   3413     bcm_pbmp_t            pbmp_all;
   3414 
   3415     BCM_PBMP_CLEAR(pbmp_all);
   3416     BCM_PBMP_ASSIGN(pbmp_all, PBMP_ALL(unit));
   3417 
   3418     if (soc_feature(unit, soc_feature_linkphy_coe) ||
   3419         soc_feature(unit, soc_feature_subtag_coe)) {
   3420         _bcm_kt2_subport_pbmp_update(unit, &pbmp_all);
   3421     }
   3422     BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update (unit, &pbmp_all));
   3423 
   3424     /* Allocate struct for IPMC Extq replication bookkeeping */
   3425     alloc_size = sizeof(_kt_extq_repl_info_t);
   3426     _kt_extq_repl_info[unit] = sal_alloc(alloc_size, "IPMC Extq repl info");
   3427     if (_kt_extq_repl_info[unit] == NULL) {
   3428         return BCM_E_MEMORY;
   3429     }
   3430     sal_memset(_kt_extq_repl_info[unit], 0, alloc_size);
   3431     _kt_extq_repl_info[unit]->ipmc_size = soc_mem_index_count(unit, L3_IPMCm);
   3432 
   3433     IPMC_EXTQ_REPL_MAX(unit) = (1 << soc_mem_field_length(unit, L3_IPMCm,
   3434                                 EXT_Q_NUM_COPIESf)) - 1;
   3435     IPMC_EXTQ_TOTAL(unit) = 4096;
   3436     IPMC_EXTQ_LIST_TOTAL(unit) = soc_mem_index_count(unit, MMU_EXT_MC_QUEUE_LIST0m);
   3437     alloc_size = SHR_BITALLOCSIZE(IPMC_EXTQ_LIST_TOTAL(unit));
   3438     _kt_extq_repl_info[unit]->bitmap_entries_used =
   3439     sal_alloc(alloc_size, "IPMC Extq repl entries used");
   3440     if (_kt_extq_repl_info[unit]->bitmap_entries_used == NULL) {
   3441         bcm_kt_ipmc_repl_detach(unit);
   3442         return BCM_E_MEMORY;
   3443     }
   3444     sal_memset(_kt_extq_repl_info[unit]->bitmap_entries_used, 0, alloc_size);
   3445 
   3446     /* Always reserve slot 0 */
   3447     IPMC_EXTQ_REPL_VE_USED_SET(unit, 0);
   3448 
   3449     alloc_size = sizeof(_kt_repl_queue_info_t);
   3450     _kt_extq_repl_info[unit]->mcgroup_info =
   3451         sal_alloc(alloc_size, "IPMC MC group info");
   3452     if (_kt_extq_repl_info[unit]->mcgroup_info == NULL) {
   3453         bcm_kt_ipmc_repl_detach(unit);
   3454         return BCM_E_MEMORY;
   3455     }
   3456     sal_memset(_kt_extq_repl_info[unit]->mcgroup_info, 0, alloc_size);
   3457 
   3458     alloc_size = sizeof(int32) * soc_mem_index_count(unit, L3_IPMCm);
   3459     IPMC_EXTQ_GROUP_INFO(unit)->queue_count =
   3460         sal_alloc(alloc_size, "IPMC Extq queue count");
   3461     if (IPMC_EXTQ_GROUP_INFO(unit)->queue_count == NULL) {
   3462         bcm_kt_ipmc_repl_detach(unit);
   3463         return BCM_E_MEMORY;
   3464     }
   3465     sal_memset(IPMC_EXTQ_GROUP_INFO(unit)->queue_count,
   3466                0, alloc_size);
   3467 
   3468     IPMC_EXTQ_GROUP_INFO(unit)->queue_count_int =
   3469         sal_alloc(alloc_size, "IPMC Extq queue count internal");
   3470     if (IPMC_EXTQ_GROUP_INFO(unit)->queue_count_int == NULL) {
   3471         bcm_kt_ipmc_repl_detach(unit);
   3472         return BCM_E_MEMORY;
   3473     }
   3474     sal_memset(IPMC_EXTQ_GROUP_INFO(unit)->queue_count_int,
   3475                0, alloc_size);
   3476 
   3477     IPMC_EXTQ_GROUP_INFO(unit)->queue_count_ext =
   3478         sal_alloc(alloc_size, "IPMC Extq queue count external");
   3479     if (IPMC_EXTQ_GROUP_INFO(unit)->queue_count_ext == NULL) {
   3480         bcm_kt_ipmc_repl_detach(unit);
   3481         return BCM_E_MEMORY;
   3482     }
   3483     sal_memset(IPMC_EXTQ_GROUP_INFO(unit)->queue_count_ext,
   3484                0, alloc_size);
   3485 
   3486     sw_to_hw_queue[unit] =
   3487       sal_alloc(IPMC_EXTQ_TOTAL(unit) * sizeof(uint32),
   3488                 "SW to HW queue");
   3489     if (sw_to_hw_queue[unit] == NULL) {
   3490         bcm_kt_ipmc_repl_detach(unit);
   3491         return (BCM_E_MEMORY);
   3492     }
   3493     sal_memset(sw_to_hw_queue[unit], 0,
   3494                IPMC_EXTQ_TOTAL(unit) * sizeof(uint32));
   3495 
   3496     PBMP_ITER(pbmp_all, port) {
   3497         alloc_size = sizeof(_kt_repl_queue_info_t);
   3498         IPMC_EXTQ_REPL_PORT_INFO(unit, port) =
   3499             sal_alloc(alloc_size, "IPMC Extq repl port info");
   3500         if (IPMC_EXTQ_REPL_PORT_INFO(unit, port) == NULL) {
   3501             bcm_kt_ipmc_repl_detach(unit);
   3502             return BCM_E_MEMORY;
   3503         }
   3504         sal_memset(IPMC_EXTQ_REPL_PORT_INFO(unit, port), 0, alloc_size);
   3505 
   3506         alloc_size = sizeof(int32) * soc_mem_index_count(unit, L3_IPMCm);
   3507         IPMC_EXTQ_REPL_PORT_INFO(unit, port)->queue_count =
   3508             sal_alloc(alloc_size, "IPMC Extq repl port queue count");
   3509         if (IPMC_EXTQ_REPL_PORT_INFO(unit, port)->queue_count == NULL) {
   3510             bcm_kt_ipmc_repl_detach(unit);
   3511             return BCM_E_MEMORY;
   3512         }
   3513         sal_memset(IPMC_EXTQ_REPL_PORT_INFO(unit, port)->queue_count,
   3514                    0, alloc_size);
   3515     }
   3516 
   3517     /* reserve ipmc index 0 & 1 for extended queue work around */
   3518     BCM_IF_ERROR_RETURN(bcm_xgs3_ipmc_id_alloc(unit, 0));
   3519     BCM_IF_ERROR_RETURN(bcm_xgs3_ipmc_id_alloc(unit, 1));
   3520 
   3521         /* Read L3 ipmc table. */
   3522     BCM_IF_ERROR_RETURN(soc_mem_read(unit, L3_IPMCm, MEM_BLOCK_ANY,
   3523                                  0, entry));
   3524         /* use 1 as initial redirection pointer */
   3525     soc_mem_field32_set(unit, L3_IPMCm, entry,
   3526                                 MMU_MC_REDIRECTION_PTRf, 1);
   3527     BCM_IF_ERROR_RETURN(soc_mem_write(unit, L3_IPMCm, MEM_BLOCK_ALL,
   3528                                 0, &entry));
   3529     return BCM_E_NONE;
   3530 }
   3531 
   3532 #endif
   3533 #ifdef BCM_KATANA_SUPPORT
   3534 /*
   3535  * Function:
   3536  *      _bcm_kt_init_check
   3537  * Purpose:
   3538  *      Katana initialization
   3539  *      unit         - StrataSwitch PCI device unit number.
   3540  *      ipmc_id      - The replication group number.
   3541  * Returns:
   3542  *      BCM_E_XXX
   3543  */
   3544 int
   3545 _bcm_kt_init_check(int unit, int ipmc_id)
   3546 {
   3547     if (SOC_IS_KATANA(unit)) {
   3548        IPMC_REPL_INIT(unit);
   3549        IPMC_REPL_ID(unit, ipmc_id);
   3550     } 
   3551 #ifdef BCM_KATANA2_SUPPORT
   3552     if (SOC_IS_KATANA2(unit)) {
   3553        BCM_IF_ERROR_RETURN(_bcm_kt2_init_check(unit, ipmc_id));
   3554     }
   3555 #endif
   3556 
   3557     return BCM_E_NONE;
   3558 }
   3559 
   3560 /*
   3561  * Function:
   3562  *      bcm_kt_ipmc_repl_detach
   3563  * Purpose:
   3564  *      Initialize IPMC replication.
   3565  * Parameters:
   3566  *      unit     - SOC unit #
   3567  * Returns:
   3568  *      BCM_E_XXX
   3569  */
   3570 int
   3571 bcm_kt_ipmc_repl_detach(int unit)
   3572 {
   3573     _bcm_repl_list_info_t *rli_current, *rli_free;
   3574     bcm_port_t port;
   3575     bcm_pbmp_t            pbmp_all;
   3576 
   3577     BCM_PBMP_CLEAR(pbmp_all);
   3578     BCM_PBMP_ASSIGN(pbmp_all, PBMP_ALL(unit));
   3579 
   3580 #if defined(BCM_KATANA2_SUPPORT)
   3581     if (soc_feature(unit, soc_feature_linkphy_coe) ||
   3582         soc_feature(unit, soc_feature_subtag_coe)) {
   3583         _bcm_kt2_subport_pbmp_update(unit, &pbmp_all);
   3584     }
   3585     if (SOC_IS_KATANA2(unit)) {
   3586         BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update (unit, &pbmp_all));
   3587     }
   3588 #endif
   3589 
   3590     if (_kt_extq_repl_info[unit] != NULL) {
   3591          PBMP_ITER(pbmp_all, port) {
   3592             if (_kt_extq_repl_info[unit]->port_info[port] != NULL) {
   3593                 if (_kt_extq_repl_info[unit]->port_info[port]->queue_count
   3594                     != NULL) {
   3595                     sal_free(
   3596                         _kt_extq_repl_info[unit]->port_info[port]->queue_count);
   3597                 }
   3598                 sal_free(_kt_extq_repl_info[unit]->port_info[port]);
   3599             }
   3600         }
   3601 
   3602         if (_kt_extq_repl_info[unit]->mcgroup_info != NULL) {
   3603             if (_kt_extq_repl_info[unit]->mcgroup_info->queue_count 
   3604                                             != NULL) {
   3605                 sal_free(_kt_extq_repl_info[unit]->
   3606                          mcgroup_info->queue_count);
   3607             }
   3608             if (_kt_extq_repl_info[unit]->mcgroup_info->queue_count_int
   3609                                             != NULL) {
   3610                 sal_free(_kt_extq_repl_info[unit]->
   3611                          mcgroup_info->queue_count_int);
   3612             }
   3613             if (_kt_extq_repl_info[unit]->mcgroup_info->queue_count_ext
   3614                                             != NULL) {
   3615                 sal_free(_kt_extq_repl_info[unit]->
   3616                          mcgroup_info->queue_count_ext);
   3617             }
   3618             sal_free(_kt_extq_repl_info[unit]->mcgroup_info);
   3619         }
   3620 
   3621         if (_kt_extq_repl_info[unit]->bitmap_entries_used != NULL) {
   3622             sal_free(_kt_extq_repl_info[unit]->bitmap_entries_used);
   3623         }
   3624 
   3625         if (_kt_extq_repl_info[unit]->repl_extq_list_info != NULL) {
   3626             rli_current = IPMC_EXTQ_REPL_LIST_INFO(unit);
   3627             while (rli_current != NULL) {
   3628                 rli_free = rli_current;
   3629                 rli_current = rli_current->next;
   3630                 sal_free(rli_free);
   3631             }
   3632         }
   3633 
   3634         sal_free(_kt_extq_repl_info[unit]);
   3635         _kt_extq_repl_info[unit] = NULL;
   3636     }
   3637 
   3638     if (sw_to_hw_queue[unit] != NULL) {
   3639         sal_free(sw_to_hw_queue[unit]);
   3640         sw_to_hw_queue[unit] = NULL;
   3641     }
   3642 
   3643     return BCM_E_NONE;
   3644 }
   3645 
   3646 
   3647 int
   3648 _bcm_kt_ipmc_mmu_mc_remap_ptr(int unit, int ipmc_id, 
   3649                         int *remap_id, int set)
   3650 {
   3651     int rv = BCM_E_NONE;
   3652     uint32 entry[SOC_MAX_MEM_FIELD_WORDS];
   3653     soc_mem_t mem = L3_IPMCm;
   3654 
   3655     soc_mem_lock(unit, mem);
   3656     
   3657     if ((rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY,
   3658                                      ipmc_id, entry)) < 0) {
   3659         soc_mem_unlock(unit, mem);
   3660            return rv;
   3661     }                                 
   3662 
   3663     if (set) {
   3664         soc_mem_field32_set(unit, mem, entry, 
   3665                            MMU_MC_REDIRECTION_PTRf, *remap_id);
   3666        if ((rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, ipmc_id,
   3667                                 entry)) < 0) {
   3668             soc_mem_unlock(unit, mem);
   3669             return rv;
   3670         }        
   3671     } else {     
   3672         *remap_id = soc_mem_field32_get(unit, mem, entry, 
   3673                                         MMU_MC_REDIRECTION_PTRf);
   3674         if (*remap_id == 0) {
   3675             *remap_id = ipmc_id;
   3676         }
   3677     }    
   3678 
   3679     soc_mem_unlock(unit, mem);
   3680     
   3681     return rv;
   3682 }
   3683 
   3684 int 
   3685 _bcm_kt_ipmc_update_group(int unit, soc_mem_t mem, int ipmc_id,
   3686                           mmu_ipmc_group_tbl0_entry_t *entry)
   3687 {
   3688     int rv = BCM_E_NONE;
   3689     _rep_regs_t *rqe_arr_ptr;
   3690     int port, port_ptr = 0;
   3691 
   3692     rqe_arr_ptr = kt_rqe_rep_regs;
   3693     for (port = 0; port < 36; port++) {
   3694         if (rqe_arr_ptr[port].mem == mem) {
   3695             port_ptr = soc_mem_field32_get(unit, mem, entry, 
   3696                                            rqe_arr_ptr[port].port_ptr);
   3697             if (port_ptr) {
   3698                 /* encode new port_ptr as { 2'b01, MC_INDEX[11:0] } */
   3699                 soc_mem_field32_set(unit, mem, entry, rqe_arr_ptr[port].port_ptr, 
   3700                                     ((ipmc_id & 0xFFF) | (0x1 << 12)));
   3701             }
   3702         }
   3703     }
   3704 
   3705     return rv;
   3706 }
   3707 
   3708 int _bcm_kt_ipmc_port_ext_queue_count(int unit,
   3709                                      int ipmc_id, bcm_port_t port)
   3710 {
   3711     if (SOC_PORT_VALID(unit, port)) {
   3712         return IPMC_EXTQ_REPL_PORT_QUEUE_COUNT(unit, port, ipmc_id);
   3713     } else {
   3714         return BCM_E_PORT;
   3715     }
   3716 }
   3717 
   3718 void _bcm_kt_ipmc_port_ext_queue_count_increment(int unit,
   3719                                      int ipmc_id, bcm_port_t port)
   3720 {
   3721     if ((IPMC_EXTQ_REPL_PORT_INFO(unit, port) != NULL) &&
   3722         (IPMC_EXTQ_REPL_PORT_INFO(unit, port)->queue_count != NULL)) {
   3723         IPMC_EXTQ_REPL_PORT_QUEUE_COUNT(unit, port, ipmc_id)++;
   3724     }
   3725     if (IS_EXT_MEM_PORT(unit, port)) {
   3726         IPMC_EXTQ_REPL_QUEUE_COUNT_EXT(unit, ipmc_id)++;
   3727     } else {
   3728         IPMC_EXTQ_REPL_QUEUE_COUNT_INT(unit, ipmc_id)++;
   3729     }
   3730     return;
   3731 }
   3732 
   3733 void _bcm_kt_ipmc_port_ext_queue_count_decrement(int unit,
   3734                                      int ipmc_id, bcm_port_t port)
   3735 {
   3736     if ((IPMC_EXTQ_REPL_PORT_INFO(unit, port) != NULL) &&
   3737         (IPMC_EXTQ_REPL_PORT_INFO(unit, port)->queue_count != NULL)) {
   3738         IPMC_EXTQ_REPL_PORT_QUEUE_COUNT(unit, port, ipmc_id)--;
   3739     }
   3740     if (IS_EXT_MEM_PORT(unit, port)) {
   3741         IPMC_EXTQ_REPL_QUEUE_COUNT_EXT(unit, ipmc_id)--;
   3742     } else {
   3743         IPMC_EXTQ_REPL_QUEUE_COUNT_INT(unit, ipmc_id)--;
   3744     }
   3745     return;
   3746 }
   3747 
   3748 
   3749 int 
   3750 _bcm_kt_ipmc_set_remap_group(int unit, int ipmc_id, 
   3751                             bcm_port_t port, int count)
   3752 {
   3753     int rv = BCM_E_NONE;
   3754     int i, int_mem = 0, ext_mem = 0;
   3755     int new_remap_id, old_remap_id;
   3756     int flush_active = 0;
   3757     uint32 rval = 0;
   3758     uint32 entry[SOC_MAX_MEM_FIELD_WORDS];
   3759     uint32 timeout_val;
   3760     soc_timeout_t timeout;
   3761     mmu_ipmc_group_tbl0_entry_t ipmc_group_entry;
   3762     mmu_toq_ipmc_group_tbl0_entry_t toq_group_entry;
   3763     bcm_pbmp_t destination_pbmp;
   3764     int port_ext_queue_count = 0;
   3765     soc_mem_t dest_pbm_mem;
   3766 
   3767 #ifdef BCM_KATANA2_SUPPORT
   3768     mmu_repl_grp_tbl0_entry_t repl_group_entry;
   3769     soc_mem_t repl_grp_mem[] = {
   3770                                  MMU_REPL_GRP_TBL0m,
   3771                                  MMU_REPL_GRP_TBL1m,
   3772                                  MMU_REPL_GRP_TBL2m
   3773                                };
   3774 #endif
   3775 
   3776     soc_mem_t ipmc_mem[] = {
   3777                             MMU_IPMC_GROUP_TBL0m,
   3778                             MMU_IPMC_GROUP_TBL1m,
   3779                             MMU_IPMC_GROUP_TBL2m,
   3780                             MMU_IPMC_GROUP_TBL3m,
   3781                             MMU_IPMC_GROUP_TBL4m 
   3782                             };
   3783     soc_mem_t toq_mem[] = {
   3784                             MMU_TOQ_IPMC_GROUP_TBL0m,
   3785                             MMU_TOQ_IPMC_GROUP_TBL1m,
   3786                             MMU_TOQ_IPMC_GROUP_TBL2m,
   3787                             MMU_TOQ_IPMC_GROUP_TBL3m,
   3788                             MMU_TOQ_IPMC_GROUP_TBL4m,
   3789                             MMU_TOQ_IPMC_GROUP_TBL5m,
   3790                             MMU_TOQ_IPMC_GROUP_TBL6m
   3791                           };
   3792     /*
   3793       *  Workaround for extended queues 
   3794       *  update the redirection ptr, memory type information in L3_IPMC,
   3795       *  copy the ipmc group table from the current locationt to
   3796       *  redirected location.
   3797       */
   3798 
   3799     BCM_IF_ERROR_RETURN
   3800     (_bcm_kt_ipmc_mmu_mc_remap_ptr(unit, 0, &new_remap_id, FALSE));
   3801     BCM_IF_ERROR_RETURN
   3802     (_bcm_kt_ipmc_mmu_mc_remap_ptr(unit, ipmc_id, &old_remap_id, FALSE));
   3803     /* Saber2 doesn't have MMU_IPMC_GROUP_TBL 1-4 */
   3804     for (i = 0; i <= 4; i++) {
   3805         if (SOC_MEM_IS_VALID(unit, ipmc_mem[i])) {
   3806             BCM_IF_ERROR_RETURN(soc_mem_read(unit, ipmc_mem[i], MEM_BLOCK_ANY,
   3807                         old_remap_id, &ipmc_group_entry));
   3808 
   3809             if (SOC_MEM_IS_VALID(unit, toq_mem[0])) {
   3810                 BCM_IF_ERROR_RETURN
   3811                     (_bcm_kt_ipmc_update_group(unit, ipmc_mem[i], new_remap_id, 
   3812                                                &ipmc_group_entry));
   3813             }
   3814             BCM_IF_ERROR_RETURN(soc_mem_write(unit, ipmc_mem[i], MEM_BLOCK_ANY,
   3815                         new_remap_id, &ipmc_group_entry));
   3816         }    
   3817     }    
   3818 
   3819     if (SOC_MEM_IS_VALID(unit, toq_mem[0])) {
   3820         for (i = 0; i <= 6; i++) {
   3821             BCM_IF_ERROR_RETURN(soc_mem_read(unit, toq_mem[i], MEM_BLOCK_ANY,
   3822                                          old_remap_id, &toq_group_entry));
   3823 
   3824             BCM_IF_ERROR_RETURN(soc_mem_write(unit, toq_mem[i], MEM_BLOCK_ANY,
   3825                                          new_remap_id, &toq_group_entry));
   3826         }    
   3827     }
   3828 #ifdef BCM_KATANA2_SUPPORT
   3829         for (i = 2; i >= 0; i--) {
   3830         if (SOC_MEM_IS_VALID(unit, repl_grp_mem[i])) {
   3831             BCM_IF_ERROR_RETURN(soc_mem_read(unit, repl_grp_mem[i], MEM_BLOCK_ANY,
   3832                                          old_remap_id, &repl_group_entry));
   3833 
   3834             BCM_IF_ERROR_RETURN(soc_mem_write(unit, repl_grp_mem[i], MEM_BLOCK_ANY,
   3835                                          new_remap_id, &repl_group_entry));
   3836         }
   3837     }
   3838 #endif
   3839     
   3840     BCM_IF_ERROR_RETURN(soc_mem_read(unit, L3_IPMCm, MEM_BLOCK_ANY,
   3841                                      ipmc_id, entry));
   3842     soc_mem_field32_set(unit, L3_IPMCm, entry, MMU_MC_REDIRECTION_PTRf, 
   3843                                     new_remap_id);
   3844 
   3845     /*
   3846      * Get extended queue_count_int and extended queue_count_ext
   3847      * If there is at least one extended queue replication that
   3848      * requires external buffer, EXT_Q_EXTERNALf is set to 1.
   3849      * If there is at least one extended queue replication that
   3850      * requires internal buffer, EXT_Q_INTERNALf is set to 1.
   3851      */
   3852     int_mem = IPMC_EXTQ_REPL_QUEUE_COUNT_INT(unit, ipmc_id) ? 1 : 0;
   3853     ext_mem = IPMC_EXTQ_REPL_QUEUE_COUNT_EXT(unit, ipmc_id) ? 1 : 0;
   3854 
   3855     soc_mem_field32_set(unit, L3_IPMCm, entry, EXT_Q_INTERNALf,
   3856             int_mem);
   3857     soc_mem_field32_set(unit, L3_IPMCm, entry, EXT_Q_EXTERNALf,
   3858             ext_mem);
   3859     soc_mem_field32_set(unit, L3_IPMCm, entry, EXT_Q_NUM_COPIESf,
   3860                         count);
   3861     soc_mem_field32_set(unit, L3_IPMCm, entry, VALIDf, 1);
   3862     BCM_IF_ERROR_RETURN(soc_mem_write(unit, L3_IPMCm, MEM_BLOCK_ANY,
   3863                                      ipmc_id, entry));
   3864 
   3865     BCM_PBMP_CLEAR(destination_pbmp);
   3866 
   3867     if (SOC_MEM_IS_VALID(unit ,L3_IPMC_2m)) {
   3868         /* For Katana2 */
   3869         dest_pbm_mem = L3_IPMC_2m ;
   3870     } else {
   3871         /* Saber2, Katana */
   3872         dest_pbm_mem = L3_IPMCm;
   3873     }
   3874 
   3875     if (SOC_MEM_FIELD_VALID(unit, dest_pbm_mem, DESTINATION_PBMf)) {
   3876 
   3877         port_ext_queue_count = IPMC_EXTQ_REPL_PORT_QUEUE_COUNT(unit,
   3878                                    port, ipmc_id);
   3879 
   3880         BCM_IF_ERROR_RETURN(soc_mem_read(unit, dest_pbm_mem, MEM_BLOCK_ANY,
   3881                                      ipmc_id, entry));
   3882 
   3883         /* Extract Destination_pbm for egress mirror support on extended queues. */
   3884         soc_mem_pbmp_field_get(unit,
   3885             dest_pbm_mem, entry, DESTINATION_PBMf, &destination_pbmp);
   3886         if (port_ext_queue_count) {
   3887             BCM_PBMP_PORT_ADD(destination_pbmp, port);
   3888         } else {
   3889             if (BCM_PBMP_MEMBER(destination_pbmp, port)) {
   3890                 BCM_PBMP_PORT_REMOVE(destination_pbmp, port);
   3891             }
   3892         }
   3893         soc_mem_pbmp_field_set(unit,
   3894             dest_pbm_mem, entry, DESTINATION_PBMf, &destination_pbmp);
   3895 
   3896         BCM_IF_ERROR_RETURN(soc_mem_write(unit, dest_pbm_mem, MEM_BLOCK_ANY,
   3897                                      ipmc_id, entry));
   3898     }
   3899 
   3900     if (!(SAL_BOOT_SIMULATION || SAL_BOOT_BCMSIM  || SAL_BOOT_XGSSIM)) {
   3901     /* flush the old entry */
   3902     if (SOC_REG_IS_VALID(unit, TOQ_QUEUE_FLUSH0r)) {
   3903         soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval, Q_FLUSH_ID0f, 0xfff);
   3904         soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval, Q_FLUSH_NUMf, 1);
   3905         soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval, Q_FLUSH_ACTIVEf, 1);
   3906         soc_reg_field_set(unit, TOQ_QUEUE_FLUSH0r, &rval, Q_FLUSH_EXTERNALf, 
   3907                           ext_mem);
   3908         BCM_IF_ERROR_RETURN(WRITE_TOQ_QUEUE_FLUSH0r(unit, rval));
   3909     }
   3910  
   3911     if (SOC_REG_IS_VALID(unit, TOQ_FLUSH0r)) {
   3912         soc_reg_field_set(unit, TOQ_FLUSH0r, &rval,
   3913                 FLUSH_TYPEf, 0);
   3914         if (SOC_IS_SABER2(unit)) {
   3915             soc_reg_field_set(unit, TOQ_FLUSH0r, &rval,
   3916                     FLUSH_ID0f, 0x3ff);
   3917         } else {
   3918             soc_reg_field_set(unit, TOQ_FLUSH0r, &rval,
   3919                     FLUSH_ID0f, 0xfff);
   3920         }
   3921         soc_reg_field_set(unit, TOQ_FLUSH0r, &rval,
   3922                 FLUSH_NUMf, 1);
   3923         soc_reg_field_set(unit, TOQ_FLUSH0r, &rval,
   3924                 FLUSH_ACTIVEf, 1);
   3925         soc_reg_field_set(unit, TOQ_FLUSH0r, &rval,
   3926                 FLUSH_EXTERNALf, ext_mem);
   3927         BCM_IF_ERROR_RETURN(WRITE_TOQ_FLUSH0r(unit, rval));
   3928     }
   3929 
   3930     /* wait for flush to complete */
   3931     flush_active = 1;
   3932     timeout_val = soc_property_get(unit, spn_MMU_QUEUE_FLUSH_TIMEOUT, 200000);
   3933     soc_timeout_init(&timeout, timeout_val, 0);
   3934 
   3935     while (flush_active) { 
   3936         if (SOC_REG_IS_VALID(unit, TOQ_QUEUE_FLUSH0r)) {
   3937             BCM_IF_ERROR_RETURN(READ_TOQ_QUEUE_FLUSH0r(unit, &rval)); 
   3938             flush_active = soc_reg_field_get(unit, TOQ_QUEUE_FLUSH0r, rval, 
   3939                                              Q_FLUSH_ACTIVEf);
   3940         }
   3941         if (SOC_REG_IS_VALID(unit, TOQ_FLUSH0r)) {
   3942             BCM_IF_ERROR_RETURN(READ_TOQ_FLUSH0r(unit, &rval)); 
   3943             flush_active = soc_reg_field_get(unit, TOQ_FLUSH0r, rval, 
   3944                                              FLUSH_ACTIVEf);
   3945         }
   3946 
   3947         if (soc_timeout_check(&timeout)) {
   3948              LOG_CLI((BSL_META_U(unit,
   3949                                  "ERROR: Queue  flush operation failed \n")));
   3950             return (BCM_E_TIMEOUT);
   3951         }
   3952     }
   3953     
   3954     }
   3955     /* reclaim the old entry for remapping */
   3956     BCM_IF_ERROR_RETURN
   3957     (_bcm_kt_ipmc_mmu_mc_remap_ptr(unit, 0, &old_remap_id, TRUE));
   3958 
   3959     return rv;
   3960 }
   3961 
   3962 int
   3963 _bcm_kt_ipmc_egress_intf_set(int unit, int ipmc_id, bcm_port_t port, 
   3964                              int ipmc_ptr, int if_count, bcm_if_t *if_array, 
   3965                              int *new_ipmc_ptr, int *last_ipmc_flag, 
   3966                              int check_port)
   3967 {
   3968     int                 rv = BCM_E_NONE;
   3969     int                 list_start_ptr, prev_start_ptr;
   3970     int                 alloc_size, repl_hash, vlan_count, last_flag;
   3971     int                 if_num, partition;
   3972     int                 intf_count = 0;
   3973     int                 nh_count = 0;
   3974     bcm_l3_intf_t       l3_intf;
   3975     pbmp_t              pbmp, ubmp;
   3976     SHR_BITDCL          *intf_vec = NULL;
   3977     _bcm_repl_list_info_t *rli_start, *rli_current, *rli_prev;
   3978     int remap_id;
   3979 
   3980     IPMC_REPL_INIT(unit);
   3981     IPMC_REPL_ID(unit, ipmc_id);
   3982     REPL_PORT_CHECK(unit, port);
   3983 
   3984     if ((uint32)if_count > IPMC_REPL_INTF_TOTAL(unit)) {
   3985         return BCM_E_PARAM;
   3986     }
   3987 
   3988     /* Partition between L3 interfaces and NHIs in the intf_vec
   3989      * intf_vec = [L3 interfaces, NHIs] */
   3990     partition = soc_mem_index_count(unit, EGR_L3_INTFm);
   3991 
   3992     alloc_size = SHR_BITALLOCSIZE(IPMC_REPL_INTF_TOTAL(unit));
   3993     intf_vec = sal_alloc(alloc_size, "IPMC repl interface vector");
   3994     if (intf_vec == NULL) {
   3995         return BCM_E_MEMORY;
   3996     }
   3997     sal_memset(intf_vec, 0, alloc_size);
   3998 
   3999     IPMC_REPL_LOCK(unit);
   4000 
   4001     /* Interface validation and vector construction */
   4002     for (if_num = 0; if_num < if_count; if_num++) {
   4003         if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, if_array[if_num]) &&
   4004             (uint32)(if_array[if_num]) > partition) {
   4005             rv = BCM_E_PARAM;
   4006             goto intf_set_done;
   4007         }
   4008         if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, if_array[if_num])) {
   4009             /* L3 interface is used */
   4010             if (check_port) {
   4011                 bcm_l3_intf_t_init(&l3_intf);
   4012                 l3_intf.l3a_intf_id = if_array[if_num];
   4013                 if ((rv = bcm_esw_l3_intf_get(unit, &l3_intf)) < 0) {
   4014                     goto intf_set_done;
   4015                 }
   4016                 if ((rv = bcm_esw_vlan_port_get(unit, l3_intf.l3a_vid,
   4017                                 &pbmp, &ubmp)) < 0) {
   4018                     goto intf_set_done;
   4019                 }
   4020                 if (!BCM_PBMP_MEMBER(pbmp, port)) {
   4021                     rv = BCM_E_PARAM;
   4022                     goto intf_set_done;
   4023                 }
   4024             }
   4025             SHR_BITSET(intf_vec, if_array[if_num]);
   4026             intf_count++;
   4027         } else {
   4028             /* Next hop is used */
   4029             SHR_BITSET(intf_vec, partition + if_array[if_num] -
   4030                        BCM_XGS3_DVP_EGRESS_IDX_MIN(unit));
   4031             nh_count++;
   4032         }
   4033     }
   4034 
   4035     prev_start_ptr = ipmc_ptr;
   4036 
   4037     /* Search for list already in table */
   4038     rli_start = IPMC_REPL_LIST_INFO(unit);
   4039 
   4040     repl_hash =
   4041         _shr_crc32b(0, (uint8 *)intf_vec, IPMC_REPL_INTF_TOTAL(unit));
   4042 
   4043     for (rli_current = rli_start; rli_current != NULL;
   4044          rli_current = rli_current->next) {
   4045         if (repl_hash == rli_current->hash) {
   4046             rv = _bcm_tr2_repl_list_compare(unit, rli_current->index,
   4047                                            intf_vec);
   4048             if (rv == BCM_E_NOT_FOUND) {
   4049                 continue; /* Not a match */
   4050             } else if (rv < 0) {
   4051                 goto intf_set_done; /* Access error */
   4052             } else {
   4053                 break; /* Match */
   4054             }
   4055         }
   4056     }
   4057 
   4058     if (rli_current != NULL) {
   4059         /* Found a match, point to here and increase reference count */
   4060         if (prev_start_ptr == rli_current->index) {
   4061             /* We're already pointing to this list, so done */
   4062             rv = BCM_E_NONE;
   4063             goto intf_set_done;
   4064         } else {
   4065             list_start_ptr = rli_current->index;
   4066             vlan_count = rli_current->list_size;
   4067         }
   4068     } else {
   4069         /* Not a match, make a new chain */
   4070         if ((rv = _bcm_kt_repl_list_write(unit, &list_start_ptr,
   4071                                          &vlan_count, intf_vec,
   4072                                          intf_count, nh_count)) < 0) {
   4073             goto intf_set_done;
   4074         }
   4075 
   4076         if (vlan_count > 0) {
   4077             /* Update data structures */
   4078             alloc_size = sizeof(_bcm_repl_list_info_t);
   4079             rli_current = sal_alloc(alloc_size, "IPMC repl list info");
   4080             if (rli_current == NULL) {
   4081                 /* Release list */
   4082                 _bcm_tr2_repl_list_free(unit, list_start_ptr);
   4083                 rv = BCM_E_MEMORY;
   4084                 goto intf_set_done;
   4085             }
   4086             sal_memset(rli_current, 0, alloc_size);
   4087             rli_current->index = list_start_ptr;
   4088             rli_current->hash = repl_hash;
   4089             rli_current->next = rli_start;
   4090             rli_current->list_size = vlan_count;
   4091             IPMC_REPL_LIST_INFO(unit) = rli_current;
   4092             rli_start = rli_current;
   4093         }
   4094     }
   4095 
   4096     last_flag = (vlan_count == 1);
   4097     *last_ipmc_flag = last_flag;
   4098 
   4099     if (vlan_count > 0) {
   4100         (rli_current->refcount)++;
   4101         /* we don't need this rli_current anymore */
   4102     } else if (prev_start_ptr != 0) {
   4103         list_start_ptr = 0;
   4104     }
   4105     *new_ipmc_ptr = list_start_ptr;        
   4106     /* update the vlan count to remapped index */
   4107     /* need to updated the vlan count is proper index in IPMC_REPL_PORT_VLAN_COUNT
   4108        without this change vlan count is updated  in invalid array index
   4109        this will cause _bcm_kt_ipmc_egress_intf_delete to fail in below condition.
   4110        Refer to SDK-108543 for more info.
   4111     */
   4112     if ((rv = _bcm_kt_ipmc_mmu_mc_remap_ptr(unit, 
   4113                           0, &remap_id, FALSE)) < 0) {
   4114         goto intf_set_done;
   4115     }
   4116     IPMC_REPL_PORT_VLAN_COUNT(unit, port, remap_id) = vlan_count;
   4117     if ((rv = _bcm_kt_ipmc_mmu_mc_remap_ptr(unit, 
   4118                           ipmc_id, &remap_id, FALSE)) < 0) {
   4119         goto intf_set_done;
   4120     }
   4121     IPMC_REPL_PORT_VLAN_COUNT(unit, port, remap_id) = vlan_count;
   4122 
   4123     if (prev_start_ptr != 0) {
   4124         rli_prev = NULL;
   4125         for (rli_current = rli_start; rli_current != NULL;
   4126              rli_current = rli_current->next) {
   4127             if (prev_start_ptr == rli_current->index) {
   4128                 (rli_current->refcount)--;
   4129                 if (rli_current->refcount == 0) {
   4130                     /* Free these linked list entries */
   4131                     rv = _bcm_tr2_repl_list_free(unit, prev_start_ptr);
   4132                     /* If we have an error, we'll fall out anyway */
   4133                     if (rli_prev == NULL) {
   4134                         IPMC_REPL_LIST_INFO(unit) = rli_current->next;
   4135                     } else {
   4136                         rli_prev->next = rli_current->next;
   4137                     }
   4138                     sal_free(rli_current);
   4139                 }
   4140                 break;
   4141             }
   4142             rli_prev = rli_current;
   4143         }
   4144     }
   4145 
   4146  intf_set_done:
   4147     IPMC_REPL_UNLOCK(unit);
   4148     if (intf_vec != NULL) {
   4149         sal_free(intf_vec);
   4150     }
   4151     return rv;
   4152 }
   4153 
   4154 int
   4155 _bcm_kt_ipmc_egress_intf_get(int unit, int ipmc_id, bcm_port_t port,  
   4156                              int ipmc_ptr, int if_max, bcm_if_t *if_array, 
   4157                              int *if_count)
   4158 {
   4159     int                 rv = BCM_E_NONE;
   4160     int                 vlan_ptr, last_vlan_ptr;
   4161     int                 ls_pos;
   4162     int                 rvth = BCM_E_NONE;
   4163     int                 intf_base, nh_offset;
   4164     uint32              ls_bits[2];
   4165     uint32              vlan_count;
   4166     mmu_ipmc_vlan_tbl_entry_t vlan_entry;
   4167 
   4168     IPMC_REPL_INIT(unit);
   4169     IPMC_REPL_ID(unit, ipmc_id);
   4170     REPL_PORT_CHECK(unit, port);
   4171 
   4172     if (if_max < 0) {
   4173         return BCM_E_PARAM;
   4174     }
   4175 
   4176     IPMC_REPL_LOCK(unit);
   4177     if (IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id) == 0) {
   4178         *if_count = 0;
   4179         IPMC_REPL_UNLOCK(unit);
   4180         return rvth;
   4181     }
   4182 
   4183     vlan_ptr = ipmc_ptr;
   4184     last_vlan_ptr = -1;
   4185     vlan_count = 0;
   4186     if (SOC_IS_TD_TT(unit)) {
   4187         nh_offset = TD_EGR_L3_NEXT_HOP_OFFSET;
   4188     } else {
   4189         /* coverity[large_shift : FALSE] */
   4190         nh_offset = (1 << (soc_mem_field_length(unit, MMU_IPMC_VLAN_TBLm,
   4191                                                 MSB_VLANf) - 1)) * 64;
   4192     }
   4193     while (vlan_ptr != last_vlan_ptr) {
   4194         if ((rv = READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ANY,
   4195                                           vlan_ptr, &vlan_entry)) < 0) {
   4196             goto intf_get_done;
   4197         }
   4198         /* Each MSB represents 64 entries in LSB bitmap */
   4199         intf_base = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, &vlan_entry,
   4200                                                        MSB_VLANf) * 64;
   4201         soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry,
   4202                                          LSB_VLAN_BMf, ls_bits);
   4203         /* Using MSB, check if L3 interface or next hop */
   4204 
   4205         for (ls_pos = 0; ls_pos < 64; ls_pos++) {
   4206             if (ls_bits[ls_pos / 32] & (1 << (ls_pos % 32))) {
   4207                 if (if_max == 0) {
   4208                     vlan_count++;
   4209                 } else {
   4210                     /* Check if L3 interface or next hop */
   4211                     if (intf_base >= nh_offset) {
   4212                         /* Entry contains next hops */
   4213                         if_array[vlan_count++] = intf_base - nh_offset +
   4214                             ls_pos + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   4215                     } else {
   4216                         /* Entry contains interfaces */
   4217                         if_array[vlan_count++] = intf_base + ls_pos;
   4218                     }
   4219                     if (vlan_count == (uint32)if_max) {
   4220                         *if_count = vlan_count;
   4221                         goto intf_get_done;
   4222                     }
   4223                 }
   4224             }
   4225         }
   4226         last_vlan_ptr = vlan_ptr;
   4227         vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   4228                                                       &vlan_entry, NEXTPTRf);
   4229 
   4230         if (vlan_count >= IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) {
   4231             break;
   4232         }
   4233     }
   4234 
   4235     *if_count = vlan_count;
   4236 
   4237  intf_get_done:
   4238     IPMC_REPL_UNLOCK(unit);
   4239     return rv;
   4240 }
   4241 
   4242 int
   4243 _bcm_kt_ipmc_egress_intf_add(int unit, int ipmc_id, bcm_port_t port, 
   4244                              int ipmc_ptr, int id, int  *new_ipmc_ptr, 
   4245                              int *last_flag)
   4246 {
   4247     int                 rv = BCM_E_NONE;
   4248     int                 *if_array = NULL;
   4249     int                 intf_num, intf_max, alloc_size;
   4250     int                 partition;
   4251     bcm_l3_intf_t       l3_intf;
   4252     pbmp_t              pbmp, ubmp;
   4253     int                 i = 0;    
   4254     IPMC_REPL_INIT(unit);
   4255     IPMC_REPL_ID(unit, ipmc_id);
   4256     REPL_PORT_CHECK(unit, port);
   4257 
   4258     intf_max = IPMC_REPL_INTF_TOTAL(unit);
   4259     alloc_size = intf_max * sizeof(int);
   4260     if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   4261     if (if_array == NULL) {
   4262         return BCM_E_MEMORY;
   4263     }
   4264 
   4265     IPMC_REPL_LOCK(unit);
   4266     rv = _bcm_kt_ipmc_egress_intf_get(unit, ipmc_id, port, ipmc_ptr, intf_max,
   4267                                      if_array, &intf_num);
   4268     if (BCM_SUCCESS(rv)) {
   4269 
   4270         for (i = 0 ;i < intf_num ; i++ ) {
   4271              if (if_array[i] == id) {
   4272                  rv = BCM_E_EXISTS;
   4273                  goto intf_add_done;
   4274              }
   4275         }
   4276 
   4277         if (intf_num < intf_max) {
   4278             if_array[intf_num++] = id;
   4279 
   4280             /* For IPMC, check port is a member of the L3 interface's VLAN.
   4281              * Performing this check here is more efficient than performing
   4282              * it in bcm_tr2_ipmc_egress_intf_set.
   4283              */
   4284             if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, id)) {
   4285                 /* L3 interface is used */
   4286                 partition = soc_mem_index_count(unit, EGR_L3_INTFm);
   4287                 if (id > partition) {
   4288                     rv = BCM_E_PARAM;
   4289                     goto intf_add_done;
   4290                 }
   4291 
   4292                 bcm_l3_intf_t_init(&l3_intf);
   4293                 l3_intf.l3a_intf_id = id;
   4294                 if ((rv = bcm_esw_l3_intf_get(unit, &l3_intf)) < 0) {
   4295                     goto intf_add_done;
   4296                 }
   4297                 if ((rv = bcm_esw_vlan_port_get(unit, l3_intf.l3a_vid,
   4298                                 &pbmp, &ubmp)) < 0) {
   4299                     goto intf_add_done;
   4300                 }
   4301                 if (!BCM_PBMP_MEMBER(pbmp, port)) {
   4302                     rv = BCM_E_PARAM;
   4303                     goto intf_add_done;
   4304                 }
   4305             }
   4306 
   4307             rv = _bcm_kt_ipmc_egress_intf_set(unit, ipmc_id, port, ipmc_ptr,
   4308                                              intf_num, if_array, 
   4309                                              new_ipmc_ptr, last_flag, FALSE);
   4310         } else {
   4311             rv = BCM_E_FULL;
   4312         }
   4313     }
   4314 
   4315 intf_add_done:
   4316 
   4317     IPMC_REPL_UNLOCK(unit);
   4318     sal_free(if_array);
   4319     return rv;
   4320 }
   4321 
   4322 int
   4323 _bcm_kt_ipmc_egress_intf_delete(int unit, int ipmc_id, bcm_port_t port,
   4324                                 int ipmc_ptr, int id, int  *new_ipmc_ptr, 
   4325                                 int *last_flag)
   4326 {
   4327     int  rv = BCM_E_NONE;
   4328     int  *if_array = NULL;
   4329     int  alloc_size, if_count, if_cur, match;
   4330     int  intf_max;
   4331 
   4332     IPMC_REPL_INIT(unit);
   4333     IPMC_REPL_ID(unit, ipmc_id);
   4334     REPL_PORT_CHECK(unit, port);
   4335 
   4336     if (!IPMC_REPL_PORT_VLAN_COUNT(unit, port, ipmc_id)) {
   4337         return BCM_E_NOT_FOUND;
   4338     } 
   4339 
   4340     intf_max = IPMC_REPL_INTF_TOTAL(unit);
   4341     alloc_size = intf_max * sizeof(int);
   4342     if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   4343     if (if_array == NULL) {
   4344         return BCM_E_MEMORY;
   4345     }
   4346 
   4347     IPMC_REPL_LOCK(unit);
   4348     rv = _bcm_kt_ipmc_egress_intf_get(unit, ipmc_id, port, ipmc_ptr, 
   4349                                       intf_max, if_array, &if_count);
   4350     if (BCM_SUCCESS(rv)) {
   4351         match = FALSE;
   4352         for (if_cur = 0; if_cur < if_count; if_cur++) {
   4353             if (match) {
   4354                 if_array[if_cur - 1] = if_array[if_cur];
   4355             } else {
   4356                 if (if_array[if_cur] == id) {
   4357                     match = TRUE;
   4358                 }
   4359             }
   4360         }
   4361         if (match) {
   4362             if_count--;
   4363             rv = _bcm_kt_ipmc_egress_intf_set(unit, ipmc_id, port, ipmc_ptr,
   4364                                              if_count, if_array, new_ipmc_ptr, 
   4365                                              last_flag, FALSE);
   4366         } else {
   4367             rv = BCM_E_NOT_FOUND;
   4368         }
   4369     }
   4370 
   4371     IPMC_REPL_UNLOCK(unit);
   4372     sal_free(if_array);
   4373     return rv;
   4374 }
   4375 
   4376 int 
   4377 _bcm_kt_ipmc_subscriber_egress_intf_traverse(int unit, int extq_ptr, 
   4378                                              int *baseq_id, 
   4379                                              int *ptr_array, int *q_num) 
   4380 {
   4381     int rv = BCM_E_NOT_FOUND;
   4382     int next_ptr1, next_ptr2;
   4383     int queue_id;
   4384     int ptr, type, i;
   4385     mmu_ext_mc_queue_list0_entry_t qlist0_entry;
   4386     mmu_ext_mc_queue_list1_entry_t qlist1_entry; 
   4387     mmu_ext_mc_queue_list4_entry_t qlist4_entry;
   4388     soc_field_t        base_qid[] = { BASE_QID0f, BASE_QID1f };    
   4389     soc_field_t        repl_ptr[] = { L3_REPL_PTR0f, L3_REPL_PTR1f };    
   4390     soc_field_t        ptr_type[] = { L3_REPL_TYPE0f, L3_REPL_TYPE1f };
   4391 
   4392     if ((rv = READ_MMU_EXT_MC_QUEUE_LIST0m(unit, MEM_BLOCK_ANY,
   4393                                       extq_ptr, &qlist0_entry)) < 0) {
   4394         goto extq_list_done;
   4395     }
   4396     if (SOC_MEM_IS_VALID(unit, MMU_EXT_MC_QUEUE_LIST1m)) {
   4397         if ((rv = READ_MMU_EXT_MC_QUEUE_LIST1m(unit, MEM_BLOCK_ANY,
   4398                         extq_ptr, &qlist1_entry)) < 0) {
   4399             goto extq_list_done;
   4400         }
   4401     }
   4402     if ((rv = READ_MMU_EXT_MC_QUEUE_LIST4m(unit, MEM_BLOCK_ANY,
   4403                                       extq_ptr, &qlist4_entry)) < 0) {
   4404         goto extq_list_done;
   4405     }
   4406     
   4407     for (i = 0; i < 2; i++) {     
   4408         if ((queue_id = soc_MMU_EXT_MC_QUEUE_LIST0m_field32_get(unit, 
   4409                                     &qlist0_entry, base_qid[i])) != 0) {
   4410             ptr = soc_MMU_EXT_MC_QUEUE_LIST0m_field32_get(unit, 
   4411                                     &qlist0_entry, repl_ptr[i]);
   4412             if (SOC_MEM_FIELD_VALID(unit, MMU_EXT_MC_QUEUE_LIST0m, 
   4413                                     L3_REPL_TYPE0f) || 
   4414                 SOC_MEM_FIELD_VALID(unit, MMU_EXT_MC_QUEUE_LIST0m,
   4415                                     L3_REPL_TYPE1f)) {
   4416                 /* KATANA */
   4417                 type = soc_MMU_EXT_MC_QUEUE_LIST0m_field32_get(unit,
   4418                                     &qlist0_entry, ptr_type[i]);
   4419                 ptr = ptr | (type << 14);
   4420             }
   4421 
   4422             baseq_id[*q_num] = queue_id;
   4423             ptr_array[*q_num] = ptr ;
   4424             (*q_num)++;
   4425          }
   4426        }    
   4427     if (SOC_MEM_IS_VALID(unit, MMU_EXT_MC_QUEUE_LIST1m)) {
   4428         for (i = 0; i < 2; i++) {    
   4429             if ((queue_id = soc_MMU_EXT_MC_QUEUE_LIST1m_field32_get(unit, 
   4430                             &qlist1_entry, base_qid[i])) != 0) {
   4431                 ptr = soc_MMU_EXT_MC_QUEUE_LIST1m_field32_get(unit, 
   4432                         &qlist1_entry, repl_ptr[i]);
   4433                 if (SOC_MEM_FIELD_VALID(unit, MMU_EXT_MC_QUEUE_LIST1m,
   4434                             L3_REPL_TYPE0f) ||
   4435                         SOC_MEM_FIELD_VALID(unit, MMU_EXT_MC_QUEUE_LIST1m,
   4436                             L3_REPL_TYPE1f)) {
   4437                     /* KATANA */
   4438                     type = soc_MMU_EXT_MC_QUEUE_LIST1m_field32_get(unit,
   4439                             &qlist1_entry, ptr_type[i]);
   4440                     ptr = ptr | (type << 14);
   4441                 }
   4442                 baseq_id[*q_num] = queue_id;
   4443                 ptr_array[*q_num] = ptr ;
   4444                 (*q_num)++;                 
   4445             }
   4446         }
   4447     }
   4448          
   4449     next_ptr1 = soc_MMU_EXT_MC_QUEUE_LIST4m_field32_get(unit, 
   4450                             &qlist4_entry, EXT_Q_NXT_PTR1f);
   4451     next_ptr2 = soc_MMU_EXT_MC_QUEUE_LIST4m_field32_get(unit, 
   4452                             &qlist4_entry, EXT_Q_NXT_PTR2f);
   4453            
   4454     if (next_ptr1 != extq_ptr) {
   4455         rv = _bcm_kt_ipmc_subscriber_egress_intf_traverse(unit, next_ptr1, 
   4456                                                  baseq_id, ptr_array, q_num);
   4457     } 
   4458   
   4459     if (next_ptr2 != extq_ptr) {
   4460         rv = _bcm_kt_ipmc_subscriber_egress_intf_traverse(unit, next_ptr2, 
   4461                                                  baseq_id, ptr_array, q_num);
   4462     }    
   4463     
   4464 extq_list_done:
   4465     return rv;
   4466 }
   4467 
   4468 #ifdef BCM_KATANA2_SUPPORT
   4469 int
   4470 _bcm_kt2_ipmc_sub_egress_intf_trav_ext_set(int unit, int extq_ptr,
   4471                                              int port,
   4472                                              int ext_mem_enable)
   4473 {
   4474     int rv = BCM_E_NOT_FOUND;
   4475     int next_ptr1, next_ptr2;
   4476     int queue_id;
   4477     int i, port_get;
   4478     mmu_ext_mc_queue_list0_entry_t qlist0_entry;
   4479     mmu_ext_mc_queue_list1_entry_t qlist1_entry;
   4480     mmu_ext_mc_queue_list4_entry_t qlist4_entry;
   4481     soc_field_t        base_qid[] = { BASE_QID0f, BASE_QID1f };
   4482     soc_field_t        buff_type[]  = { BUFF_TYPE0f, BUFF_TYPE1f };
   4483 
   4484     if ((rv = READ_MMU_EXT_MC_QUEUE_LIST0m(unit, MEM_BLOCK_ANY,
   4485                                       extq_ptr, &qlist0_entry)) < 0) {
   4486         goto extq_list_done;
   4487     }
   4488     if (SOC_MEM_IS_VALID(unit, MMU_EXT_MC_QUEUE_LIST1m)) {
   4489         if ((rv = READ_MMU_EXT_MC_QUEUE_LIST1m(unit, MEM_BLOCK_ANY,
   4490                         extq_ptr, &qlist1_entry)) < 0) {
   4491             goto extq_list_done;
   4492         }
   4493     }
   4494     if ((rv = READ_MMU_EXT_MC_QUEUE_LIST4m(unit, MEM_BLOCK_ANY,
   4495                                       extq_ptr, &qlist4_entry)) < 0) {
   4496         goto extq_list_done;
   4497     }
   4498 
   4499     for (i = 0; i < 2; i++) {
   4500         if ((queue_id = soc_MMU_EXT_MC_QUEUE_LIST0m_field32_get(unit,
   4501                                     &qlist0_entry, base_qid[i])) != 0) {
   4502             BCM_IF_ERROR_RETURN
   4503                 (bcm_kt2_cosq_port_get(unit, queue_id, &port_get));
   4504             if (port_get == port) {
   4505                 if (!ext_mem_enable) {
   4506                     soc_MMU_EXT_MC_QUEUE_LIST0m_field32_set(unit,
   4507                         &qlist0_entry,
   4508                         buff_type[i], 0);
   4509                 } else {
   4510                     soc_MMU_EXT_MC_QUEUE_LIST0m_field32_set(unit,
   4511                         &qlist0_entry,
   4512                         buff_type[i], 1);
   4513                 }
   4514             }
   4515         }
   4516     }
   4517     if (SOC_MEM_IS_VALID(unit, MMU_EXT_MC_QUEUE_LIST1m)) {
   4518         for (i = 0; i < 2; i++) {
   4519             if ((queue_id = soc_MMU_EXT_MC_QUEUE_LIST1m_field32_get(unit,
   4520                             &qlist1_entry, base_qid[i])) != 0) {
   4521                 BCM_IF_ERROR_RETURN
   4522                     (bcm_kt2_cosq_port_get(unit, queue_id, &port_get));
   4523                 if (port_get == port) {
   4524                     if (!ext_mem_enable) {
   4525                          soc_MMU_EXT_MC_QUEUE_LIST1m_field32_set(unit,
   4526                              &qlist1_entry,
   4527                              buff_type[i], 0);
   4528                      } else {
   4529                          soc_MMU_EXT_MC_QUEUE_LIST1m_field32_set(unit,
   4530                              &qlist1_entry,
   4531                              buff_type[i], 1);
   4532                      }
   4533                 }
   4534             }
   4535         }
   4536     }
   4537     BCM_IF_ERROR_RETURN(WRITE_MMU_EXT_MC_QUEUE_LIST0m(unit,
   4538         MEM_BLOCK_ANY,
   4539         extq_ptr, &qlist0_entry));
   4540     BCM_IF_ERROR_RETURN(WRITE_MMU_EXT_MC_QUEUE_LIST1m(unit,
   4541         MEM_BLOCK_ANY,
   4542         extq_ptr, &qlist1_entry));
   4543     next_ptr1 = soc_MMU_EXT_MC_QUEUE_LIST4m_field32_get(unit,
   4544                             &qlist4_entry, EXT_Q_NXT_PTR1f);
   4545     next_ptr2 = soc_MMU_EXT_MC_QUEUE_LIST4m_field32_get(unit,
   4546                             &qlist4_entry, EXT_Q_NXT_PTR2f);
   4547 
   4548     if (next_ptr1 != extq_ptr) {
   4549         rv = _bcm_kt2_ipmc_sub_egress_intf_trav_ext_set(unit, next_ptr1,
   4550                                                  port, ext_mem_enable);
   4551     }
   4552 
   4553     if (next_ptr2 != extq_ptr) {
   4554         rv = _bcm_kt2_ipmc_sub_egress_intf_trav_ext_set(unit, next_ptr2,
   4555                                                  port, ext_mem_enable);
   4556     }
   4557 
   4558 extq_list_done:
   4559     return rv;
   4560 }
   4561 
   4562 int
   4563 _bcm_kt2_ipmc_subscriber_egress_queue_ext_set(int unit, int port, int ipmc_id, int ext_mem_enable)
   4564 {
   4565     int extq_ptr;
   4566 
   4567     BCM_IF_ERROR_RETURN(_kt_extq_mc_group_ptr(unit, ipmc_id,
   4568                         &extq_ptr, 0, 0));
   4569     if (extq_ptr != 0) {
   4570         BCM_IF_ERROR_RETURN(_bcm_kt2_ipmc_sub_egress_intf_trav_ext_set(unit, extq_ptr,
   4571                                                                       port, ext_mem_enable));
   4572     }
   4573      return BCM_E_NONE;
   4574 }
   4575 #endif
   4576 
   4577 int
   4578 _bcm_kt_get_subscriber_queue_entries(int unit, int extq_ptr, 
   4579                                      SHR_BITDCL *q_vec, 
   4580                                      uint32  *q_repl_ptr, 
   4581                                      int *q_num)
   4582 {
   4583     int     rv = BCM_E_NONE;
   4584     int     i;
   4585     int     next_ptr1, next_ptr2;
   4586     int     queue_id;
   4587     int     ptr, type, copy, buf_type, vlan_last;
   4588     mmu_ext_mc_queue_list0_entry_t     qlist0_entry;
   4589     mmu_ext_mc_queue_list1_entry_t     qlist1_entry; 
   4590     mmu_ext_mc_queue_list4_entry_t     qlist4_entry;
   4591     soc_field_t        base_qid[]  = { BASE_QID0f, BASE_QID1f }; 
   4592     soc_field_t        repl_ptr[]  = { L3_REPL_PTR0f, L3_REPL_PTR1f };    
   4593     soc_field_t        l3_last[]   = { L3_LAST0f, L3_LAST1f };
   4594     soc_field_t        ipmc_last[] = { IPMC_VLAN_LAST0f, IPMC_VLAN_LAST1f };
   4595     soc_field_t        ptr_type[]  = { L3_REPL_TYPE0f, L3_REPL_TYPE1f };
   4596     soc_field_t        l2_copy[]   = { L2_COPY0f, L2_COPY1f };
   4597     soc_field_t        buff_type[]  = { BUFF_TYPE0f, BUFF_TYPE1f };
   4598     soc_field_t        profile_idx[] = { Q_OFFSET_PROF0f, Q_OFFSET_PROF1f };
   4599     int profile = 0;
   4600     
   4601     if ((rv = READ_MMU_EXT_MC_QUEUE_LIST0m(unit, MEM_BLOCK_ANY,
   4602                                           extq_ptr, &qlist0_entry)) < 0) {
   4603         goto q_entries_done;
   4604     }
   4605     if (SOC_MEM_IS_VALID(unit, MMU_EXT_MC_QUEUE_LIST1m)) {
   4606         if ((rv = READ_MMU_EXT_MC_QUEUE_LIST1m(unit, MEM_BLOCK_ANY,
   4607                         extq_ptr, &qlist1_entry)) < 0) {
   4608             goto q_entries_done;
   4609         }
   4610     } 
   4611     if ((rv = READ_MMU_EXT_MC_QUEUE_LIST4m(unit, MEM_BLOCK_ANY,
   4612                                           extq_ptr, &qlist4_entry)) < 0) {
   4613         goto q_entries_done;
   4614     }
   4615 
   4616     /* store the content of queue list entries */
   4617     for (i = 0; i < 2; i++) {     
   4618         if ((queue_id = soc_MMU_EXT_MC_QUEUE_LIST0m_field32_get(unit, 
   4619                                     &qlist0_entry, base_qid[i])) != 0) {    
   4620             ptr = soc_MMU_EXT_MC_QUEUE_LIST0m_field32_get(unit, &qlist0_entry, 
   4621                                                            repl_ptr[i]);
   4622             copy = soc_MMU_EXT_MC_QUEUE_LIST0m_field32_get(unit, &qlist0_entry, 
   4623                                                            l2_copy[i]);
   4624             buf_type = soc_MMU_EXT_MC_QUEUE_LIST0m_field32_get(unit, &qlist0_entry, 
   4625                                                            buff_type[i]);
   4626             if (SOC_MEM_FIELD_VALID(unit, MMU_EXT_MC_QUEUE_LIST0m,             
   4627                 L3_REPL_TYPE0f)) {
   4628                 /* KATANA */
   4629                 type = soc_MMU_EXT_MC_QUEUE_LIST0m_field32_get(unit,
   4630                                                                &qlist0_entry,
   4631                                                                ptr_type[i]);
   4632                 vlan_last = soc_MMU_EXT_MC_QUEUE_LIST0m_field32_get(unit, &qlist0_entry,
   4633                                                            ipmc_last[i]);
   4634                 ptr |= ((type << 14) | (copy << 15) | (buf_type << 16) \
   4635                     | (vlan_last << 17));
   4636             } else {
   4637                 /* KATANA2 */
   4638                 profile = soc_MMU_EXT_MC_QUEUE_LIST0m_field32_get(unit, &qlist0_entry,
   4639                                                               profile_idx[i]);
   4640                 vlan_last = soc_MMU_EXT_MC_QUEUE_LIST0m_field32_get(unit, &qlist0_entry,
   4641                                                            l3_last[i]);
   4642                 ptr |= ((copy << 15) | (buf_type << 16) |
   4643                         (vlan_last << 17) | (profile << 18));
   4644             }
   4645             q_repl_ptr[queue_id] = ptr;
   4646             SHR_BITSET(q_vec, queue_id);
   4647             (*q_num)++;
   4648         }
   4649     }
   4650     if (SOC_MEM_IS_VALID(unit, MMU_EXT_MC_QUEUE_LIST1m)) {
   4651         for (i = 0; i < 2; i++) {     
   4652             if ((queue_id = soc_MMU_EXT_MC_QUEUE_LIST1m_field32_get(unit, 
   4653                             &qlist1_entry, base_qid[i])) != 0) {    
   4654                 ptr = soc_MMU_EXT_MC_QUEUE_LIST1m_field32_get(unit, &qlist1_entry, 
   4655                         repl_ptr[i]);
   4656                 copy = soc_MMU_EXT_MC_QUEUE_LIST1m_field32_get(unit, &qlist1_entry, 
   4657                         l2_copy[i]);
   4658                 buf_type = soc_MMU_EXT_MC_QUEUE_LIST1m_field32_get(unit, &qlist1_entry, 
   4659                         buff_type[i]);
   4660                 if (SOC_MEM_FIELD_VALID(unit, MMU_EXT_MC_QUEUE_LIST1m,
   4661                             L3_REPL_TYPE0f)) {
   4662                     /* KATANA */
   4663                     vlan_last = soc_MMU_EXT_MC_QUEUE_LIST1m_field32_get(unit, &qlist1_entry,
   4664                             ipmc_last[i]);
   4665                     type = soc_MMU_EXT_MC_QUEUE_LIST1m_field32_get(unit, &qlist1_entry,
   4666                             ptr_type[i]);
   4667                     ptr |= ((type << 14) | (copy << 15) | (buf_type << 16) \
   4668                         | (vlan_last << 17));
   4669 
   4670                 } else {
   4671                     /* KATANA2 */            
   4672                     vlan_last = soc_MMU_EXT_MC_QUEUE_LIST1m_field32_get(unit, &qlist1_entry, 
   4673                             l3_last[i]);
   4674                     profile = soc_MMU_EXT_MC_QUEUE_LIST1m_field32_get(unit, &qlist1_entry,
   4675                             profile_idx[i]);
   4676                     ptr |= ((copy << 15) | (buf_type << 16) | 
   4677                             (vlan_last << 17)| (profile << 18));
   4678                 }
   4679 
   4680                 q_repl_ptr[queue_id] = ptr;    
   4681                 SHR_BITSET(q_vec, queue_id);
   4682                 (*q_num)++;
   4683             }
   4684         }
   4685     }
   4686     next_ptr1 = soc_MMU_EXT_MC_QUEUE_LIST4m_field32_get(unit, 
   4687                                      &qlist4_entry, EXT_Q_NXT_PTR1f);
   4688     next_ptr2 = soc_MMU_EXT_MC_QUEUE_LIST4m_field32_get(unit, 
   4689                                      &qlist4_entry, EXT_Q_NXT_PTR2f);
   4690     
   4691     if (next_ptr1 != extq_ptr) {
   4692         if ((rv = _bcm_kt_get_subscriber_queue_entries(unit, next_ptr1, q_vec, 
   4693                                                        q_repl_ptr, q_num)) < 0) {
   4694             goto q_entries_done;                                                                                                
   4695         }                                                    
   4696     } 
   4697            
   4698     if (next_ptr2 != extq_ptr) {
   4699         if ((rv = _bcm_kt_get_subscriber_queue_entries(unit, next_ptr2, q_vec, 
   4700                                                        q_repl_ptr, q_num)) < 0) {
   4701             goto q_entries_done;                                                                                                        
   4702         }                                                
   4703     }    
   4704 
   4705 q_entries_done:
   4706     return rv;
   4707 }
   4708 
   4709 int _bcm_kt_ipmc_subscriber_queues_get(int unit, int ipmc_id, 
   4710                                        SHR_BITDCL *q_vec, 
   4711                                        uint32 *q_repl_ptrs,
   4712                                        int *q_num)
   4713 {
   4714     int         rv = BCM_E_NONE;
   4715     int         extq_ptr;    
   4716 
   4717     if ((rv = _kt_extq_mc_group_ptr(unit, ipmc_id,
   4718                                 &extq_ptr, 0, 0)) < 0) {
   4719         return rv;
   4720     }
   4721     
   4722     if (extq_ptr != 0) {
   4723         rv = _bcm_kt_get_subscriber_queue_entries(unit, extq_ptr, q_vec,
   4724                                                   q_repl_ptrs, q_num);
   4725     }
   4726     
   4727     return rv;
   4728 }
   4729 
   4730 /*
   4731  * Function:
   4732  *    _bcm_kt_extq__repl_list_free
   4733  * Description:
   4734  *    Release the MMU_EXT_MC_QUEUE_LIST entries in the HW list starting 
   4735  *     at extq_ptr.
   4736  */
   4737 STATIC int
   4738 _bcm_kt_extq_repl_list_free(int unit, int extq_ptr)
   4739 {
   4740     int     rv = BCM_E_NONE;
   4741     int     next_ptr1, next_ptr2;
   4742     mmu_ext_mc_queue_list4_entry_t     qlist4_entry;
   4743     
   4744     if ((rv = READ_MMU_EXT_MC_QUEUE_LIST4m(unit, MEM_BLOCK_ANY,
   4745                                     extq_ptr, &qlist4_entry)) < 0) {
   4746         goto repl_list_free_done;
   4747     }
   4748 
   4749     next_ptr1 = soc_MMU_EXT_MC_QUEUE_LIST4m_field32_get(unit, 
   4750                                      &qlist4_entry, EXT_Q_NXT_PTR1f);
   4751     next_ptr2 = soc_MMU_EXT_MC_QUEUE_LIST4m_field32_get(unit, 
   4752                                      &qlist4_entry, EXT_Q_NXT_PTR2f);
   4753     IPMC_EXTQ_REPL_VE_USED_CLR(unit, extq_ptr);
   4754     
   4755     if (next_ptr1 != extq_ptr) {
   4756         if ((rv = _bcm_kt_extq_repl_list_free(unit, next_ptr1)) < 0) {
   4757             goto repl_list_free_done;   
   4758         }                                                    
   4759     } 
   4760            
   4761     if (next_ptr2 != extq_ptr) {
   4762         if ((rv = _bcm_kt_extq_repl_list_free(unit, next_ptr2)) < 0) {  
   4763             goto repl_list_free_done; 
   4764         }                                                
   4765     }
   4766 
   4767 repl_list_free_done:
   4768     return rv;
   4769 
   4770 }
   4771 
   4772 STATIC int
   4773 _bcm_kt_extq_repl_next_free_ptr(int unit)
   4774 {
   4775     int                 ix, bit;
   4776     SHR_BITDCL          not_ptrs;
   4777 
   4778     for (ix = 0; ix < _SHR_BITDCLSIZE(IPMC_EXTQ_LIST_TOTAL(unit)); ix++) {
   4779         not_ptrs = ~_kt_extq_repl_info[unit]->bitmap_entries_used[ix];
   4780         if (not_ptrs) {
   4781             for (bit = 0; bit < SHR_BITWID; bit++) {
   4782                 if (not_ptrs & (1 << bit)) {
   4783                     return (ix * SHR_BITWID) + bit;
   4784                 }
   4785             }
   4786         }
   4787     }
   4788 
   4789     return -1;
   4790 }
   4791 
   4792 /*
   4793  * Function:
   4794  *    _bcm_kt_extq_repl_list_write
   4795  * Description:
   4796  *    Write the extq list contained in q_vec into the HW table.
   4797  *      Return the start_index and total VLAN count.
   4798  */
   4799 
   4800 STATIC int
   4801 _bcm_kt_extq_repl_list_write(int unit, int q_num, 
   4802                         SHR_BITDCL *q_vec, uint32 *q_repl_ptr,
   4803                         int *extq_index, int *count)
   4804 {
   4805     int     node_max, alloc_size;
   4806     int     next1, next2;
   4807     int     i, q_count = 0;
   4808     int     rv = BCM_E_NONE;
   4809     int     type, copy, last, buf_type, vlan_last;
   4810     int     reset_val  = 1;
   4811     _bcm_repl_list_info_t *list_array = NULL;
   4812     _bcm_repl_list_info_t *cur_node, *next, *fast_node;
   4813     mmu_ext_mc_queue_list0_entry_t     qlist0_entry;
   4814     mmu_ext_mc_queue_list1_entry_t     qlist1_entry; 
   4815     mmu_ext_mc_queue_list4_entry_t     qlist4_entry;
   4816     soc_field_t        base_qid[] = { BASE_QID0f, BASE_QID1f }; 
   4817     soc_field_t        repl_ptr[] = { L3_REPL_PTR0f, L3_REPL_PTR1f };    
   4818     soc_field_t        l2_copy[]  = { L2_COPY0f, L2_COPY1f };
   4819     soc_field_t        l3_last[] = { L3_LAST0f, L3_LAST1f };     
   4820     soc_field_t        ipmc_last[] = { IPMC_VLAN_LAST0f, IPMC_VLAN_LAST1f };     
   4821     soc_field_t        ptr_type[] = { L3_REPL_TYPE0f, L3_REPL_TYPE1f };
   4822     soc_field_t        buff_type[] = { BUFF_TYPE0f, BUFF_TYPE1f };
   4823     soc_field_t        reset_field[] = { L3_REPL_TYPE0f, L3_REPL_TYPE1f };
   4824     soc_field_t        profile_idx[] = { Q_OFFSET_PROF0f, Q_OFFSET_PROF1f };
   4825     int profile;
   4826 
   4827     if (q_num == 0) {
   4828         /* nothing to be written into extended queue list */
   4829         *count = q_count;
   4830         return BCM_E_NONE;
   4831     }    
   4832     
   4833     if (SOC_IS_KATANA2(unit)) {
   4834         reset_val = 0x4000;
   4835         for (i = 0; i < 2; i++) {
   4836             reset_field[i] = repl_ptr[i];
   4837         }
   4838     } 
   4839 
   4840     node_max = (q_num % 4) ? (q_num / 4 + 1) : q_num / 4;
   4841     alloc_size = node_max * sizeof(_bcm_repl_list_info_t);
   4842     list_array = sal_alloc(alloc_size, "IPMC repl node array");
   4843     if (list_array == NULL) {
   4844         return BCM_E_MEMORY;
   4845     }
   4846     sal_memset(list_array, 0, alloc_size);
   4847 
   4848     /* create a link list of entries with free qlist pointers */    
   4849     for (i = 0; i < node_max; i++) {
   4850         cur_node = &list_array[i];
   4851         cur_node->index = _bcm_kt_extq_repl_next_free_ptr(unit);
   4852         if (cur_node->index < 0) {
   4853             rv = BCM_E_RESOURCE;
   4854             goto clean_up;
   4855         }
   4856         IPMC_EXTQ_REPL_VE_USED_SET(unit, cur_node->index);
   4857         if (i < (node_max - 1)) { /* create a chain till penultimate node */
   4858             cur_node->next = &list_array[i+1];
   4859         }
   4860     }    
   4861 
   4862     /* copy back the stored contents into qlist entries */
   4863     fast_node = cur_node = &list_array[0];
   4864     *extq_index = cur_node->index;
   4865 
   4866     sal_memset(&qlist0_entry, 0, sizeof(mmu_ext_mc_queue_list0_entry_t));
   4867     sal_memset(&qlist1_entry, 0, sizeof(mmu_ext_mc_queue_list1_entry_t));    
   4868     sal_memset(&qlist4_entry, 0, sizeof(mmu_ext_mc_queue_list4_entry_t));    
   4869 
   4870     *count = 0;
   4871     for (i = 0; i < IPMC_EXTQ_TOTAL(unit); i++) {
   4872         if (q_repl_ptr[i] != 0) {
   4873             if (q_count < 2) {
   4874                 soc_MMU_EXT_MC_QUEUE_LIST0m_field32_set(unit, &qlist0_entry, 
   4875                                                         base_qid[q_count], i);
   4876                 copy = (q_repl_ptr[i] >> 15) & 1;
   4877                 buf_type = (q_repl_ptr[i] >> 16) & 1;
   4878                 vlan_last = (q_repl_ptr[i] >> 17) & 1;
   4879                 soc_MMU_EXT_MC_QUEUE_LIST0m_field32_set(unit, &qlist0_entry, 
   4880                                                         l2_copy[q_count], copy);
   4881                 soc_MMU_EXT_MC_QUEUE_LIST0m_field32_set(unit, &qlist0_entry, 
   4882                                                         buff_type[q_count], buf_type);
   4883                 if (SOC_MEM_FIELD_VALID(unit, MMU_EXT_MC_QUEUE_LIST0m,
   4884                                         L3_REPL_TYPE0f)) {
   4885                     /* KATANA */
   4886                     type = (q_repl_ptr[i] >> 14) & 1;
   4887                     soc_MMU_EXT_MC_QUEUE_LIST0m_field32_set(unit, &qlist0_entry,
   4888                                                         ipmc_last[q_count], 
   4889                                                         vlan_last);
   4890                     soc_MMU_EXT_MC_QUEUE_LIST0m_field32_set(unit, &qlist0_entry,
   4891                                                         ptr_type[q_count], type);
   4892                     soc_MMU_EXT_MC_QUEUE_LIST0m_field32_set(unit, &qlist0_entry,
   4893                                                         repl_ptr[q_count],
   4894                                                         q_repl_ptr[i] & 0x3fff);
   4895                 } else {
   4896                     /* KATANA2 */
   4897                     profile = (q_repl_ptr[i] >> 18) & 3;
   4898                     soc_MMU_EXT_MC_QUEUE_LIST0m_field32_set(unit, &qlist0_entry,
   4899                                                         l3_last[q_count],
   4900                                                         vlan_last);
   4901                     soc_MMU_EXT_MC_QUEUE_LIST0m_field32_set(unit, &qlist0_entry,
   4902                                                         profile_idx[q_count],
   4903                                                         profile);
   4904                     soc_MMU_EXT_MC_QUEUE_LIST0m_field32_set(unit, &qlist0_entry,
   4905                                                         repl_ptr[q_count],
   4906                                                         q_repl_ptr[i] & 0x7fff);
   4907                 }
   4908 
   4909              } else {
   4910 
   4911                  if (SOC_MEM_IS_VALID(unit, MMU_EXT_MC_QUEUE_LIST1m)) {
   4912                      soc_MMU_EXT_MC_QUEUE_LIST1m_field32_set(unit, &qlist1_entry,
   4913                              base_qid[(q_count % 2)], i);
   4914                      copy = (q_repl_ptr[i] >> 15) & 1;
   4915                      buf_type = (q_repl_ptr[i] >> 16) & 1;
   4916                      vlan_last = (q_repl_ptr[i] >> 17) & 1;
   4917                      soc_MMU_EXT_MC_QUEUE_LIST1m_field32_set(unit, &qlist1_entry,
   4918                              l2_copy[(q_count % 2)], copy);
   4919                      soc_MMU_EXT_MC_QUEUE_LIST1m_field32_set(unit, &qlist1_entry,
   4920                              buff_type[(q_count % 2)], buf_type);
   4921                      if (SOC_MEM_FIELD_VALID(unit, MMU_EXT_MC_QUEUE_LIST1m,
   4922                                  L3_REPL_TYPE0f)) {
   4923                          /* KATANA */
   4924                          type = (q_repl_ptr[i] >> 14) & 1;
   4925                          soc_MMU_EXT_MC_QUEUE_LIST1m_field32_set(unit, &qlist1_entry,
   4926                                  ipmc_last[(q_count % 2)], 
   4927                                  vlan_last);
   4928                          soc_MMU_EXT_MC_QUEUE_LIST1m_field32_set(unit, &qlist1_entry,
   4929                                  ptr_type[(q_count % 2)], type);
   4930                          soc_MMU_EXT_MC_QUEUE_LIST1m_field32_set(unit, &qlist1_entry,
   4931                                  repl_ptr[(q_count % 2)],
   4932                                  q_repl_ptr[i] & 0x3fff);
   4933                      } else {
   4934                          /* KATANA2 */
   4935                          profile = (q_repl_ptr[i] >> 18) & 3;
   4936                          soc_MMU_EXT_MC_QUEUE_LIST1m_field32_set(unit, &qlist1_entry,
   4937                                  l3_last[(q_count % 2)],
   4938                                  vlan_last);
   4939                          soc_MMU_EXT_MC_QUEUE_LIST1m_field32_set(unit, &qlist1_entry,
   4940                                                         profile_idx[q_count % 2],
   4941                                                          profile);
   4942                          soc_MMU_EXT_MC_QUEUE_LIST1m_field32_set(unit, &qlist1_entry,
   4943                                  repl_ptr[(q_count % 2)],
   4944                                  q_repl_ptr[i] & 0x7fff);
   4945                      }
   4946                  }
   4947             }
   4948             q_count++;
   4949             last = 0;
   4950             if (q_count % 4 == 0) { 
   4951                 if ((*count < 2) || (*count % 2) != 0) {
   4952                     next = fast_node->next;
   4953                     if (next != NULL) {
   4954                         next1 = next->index;
   4955                         fast_node = next;
   4956                         if (fast_node->next != NULL) {
   4957                             next2 = fast_node->next->index;
   4958                             fast_node = fast_node->next;
   4959                             /* need to set the last flag now, if this is the last enrty */
   4960                             if (fast_node->next == NULL) {
   4961                                 last = 1;
   4962                             }
   4963                         } else {
   4964                             next2 = cur_node->index;
   4965                             last = 1;
   4966                         }
   4967                     } else {
   4968                         next1 = cur_node->index;
   4969                         next2 = next1;
   4970                     }    
   4971                 } else {
   4972                     next1 = cur_node->index;
   4973                     next2 = next1;
   4974                 }
   4975 
   4976                 soc_MMU_EXT_MC_QUEUE_LIST4m_field32_set(unit, &qlist4_entry, 
   4977                                                     EXT_Q_NXT_PTR1f, next1);
   4978                 soc_MMU_EXT_MC_QUEUE_LIST4m_field32_set(unit, &qlist4_entry, 
   4979                                                     EXT_Q_NXT_PTR2f, next2);
   4980                 soc_MMU_EXT_MC_QUEUE_LIST4m_field32_set(unit, &qlist4_entry,
   4981                                                     EXT_Q_LAST_LASTf, last);
   4982                 
   4983                 if ((rv = WRITE_MMU_EXT_MC_QUEUE_LIST0m(unit, MEM_BLOCK_ANY,
   4984                                           cur_node->index, &qlist0_entry)) < 0) {
   4985                     goto clean_up;
   4986                 }
   4987                 if (SOC_MEM_IS_VALID(unit, MMU_EXT_MC_QUEUE_LIST1m)) {
   4988                     if ((rv = WRITE_MMU_EXT_MC_QUEUE_LIST1m(unit, MEM_BLOCK_ANY,
   4989                                     cur_node->index, &qlist1_entry)) < 0) {
   4990                         goto clean_up;
   4991                     }
   4992                 }
   4993                 if ((rv = WRITE_MMU_EXT_MC_QUEUE_LIST4m(unit, MEM_BLOCK_ANY,
   4994                                           cur_node->index, &qlist4_entry)) < 0) {
   4995                     goto clean_up;
   4996                 }
   4997 
   4998                 sal_memset(&qlist0_entry, 0, sizeof(mmu_ext_mc_queue_list0_entry_t));
   4999                 sal_memset(&qlist1_entry, 0, sizeof(mmu_ext_mc_queue_list1_entry_t));    
   5000                 sal_memset(&qlist4_entry, 0, sizeof(mmu_ext_mc_queue_list4_entry_t));
   5001                 cur_node = cur_node->next;
   5002                 *count += 1;
   5003                 q_count = 0;
   5004             }
   5005             
   5006         }    
   5007 
   5008     }    
   5009 
   5010     if (q_count != 0) {
   5011         soc_MMU_EXT_MC_QUEUE_LIST4m_field32_set(unit, &qlist4_entry, 
   5012                                                 EXT_Q_NXT_PTR1f, cur_node->index);
   5013         soc_MMU_EXT_MC_QUEUE_LIST4m_field32_set(unit, &qlist4_entry, 
   5014                                                 EXT_Q_NXT_PTR2f, cur_node->index);
   5015         
   5016         /* disable other unused queue entries in the list */
   5017         /* KATANA2 set L2_COPY==0 AND L3_REPL_PTR 0x4000 */
   5018         /* KATANA set  L2==0 AND L3_REPL_TYPE==1 AND L3_REPL_PTR==0 to disable */         
   5019         switch (q_count) {
   5020         case 1:
   5021             soc_MMU_EXT_MC_QUEUE_LIST0m_field32_set(unit, &qlist0_entry,
   5022                                                     reset_field[1], 
   5023                                                     reset_val);
   5024             if (SOC_MEM_IS_VALID(unit, MMU_EXT_MC_QUEUE_LIST1m)) {
   5025                 soc_MMU_EXT_MC_QUEUE_LIST1m_field32_set(unit, &qlist1_entry,
   5026                         reset_field[0], 
   5027                         reset_val);
   5028                 soc_MMU_EXT_MC_QUEUE_LIST1m_field32_set(unit, &qlist1_entry,
   5029                         reset_field[1],
   5030                         reset_val);
   5031             }
   5032             break;
   5033         case 2:
   5034             if (SOC_MEM_IS_VALID(unit, MMU_EXT_MC_QUEUE_LIST1m)) {
   5035                 soc_MMU_EXT_MC_QUEUE_LIST1m_field32_set(unit, &qlist1_entry,
   5036                         reset_field[0],
   5037                         reset_val);
   5038                 soc_MMU_EXT_MC_QUEUE_LIST1m_field32_set(unit, &qlist1_entry,
   5039                         reset_field[1], 
   5040                         reset_val);
   5041             }
   5042             break;
   5043         case 3:
   5044             if (SOC_MEM_IS_VALID(unit, MMU_EXT_MC_QUEUE_LIST1m)) {
   5045                 soc_MMU_EXT_MC_QUEUE_LIST1m_field32_set(unit, &qlist1_entry,
   5046                         reset_field[1], 
   5047                         reset_val);
   5048             }
   5049             break;
   5050         default:
   5051             rv = BCM_E_INTERNAL;
   5052             goto clean_up;
   5053         }
   5054   
   5055         if ((rv = WRITE_MMU_EXT_MC_QUEUE_LIST0m(unit, MEM_BLOCK_ANY,
   5056                                          cur_node->index, &qlist0_entry)) < 0) {
   5057             goto clean_up;
   5058         }
   5059         if (SOC_MEM_IS_VALID(unit, MMU_EXT_MC_QUEUE_LIST1m)) {
   5060             if ((rv = WRITE_MMU_EXT_MC_QUEUE_LIST1m(unit, MEM_BLOCK_ANY,
   5061                             cur_node->index, &qlist1_entry)) < 0) {
   5062                 goto clean_up;
   5063             }
   5064         }
   5065         if ((rv = WRITE_MMU_EXT_MC_QUEUE_LIST4m(unit, MEM_BLOCK_ANY,
   5066                                          cur_node->index, &qlist4_entry)) < 0) {
   5067             goto clean_up;
   5068         }
   5069         *count += 1;
   5070 
   5071     }    
   5072 
   5073 clean_up:
   5074     if (list_array != NULL) {
   5075         sal_free(list_array);
   5076     }
   5077     return rv;
   5078 
   5079 }    
   5080 
   5081 #if defined(BCM_KATANA_SUPPORT)
   5082 int 
   5083 _bcm_kt_ipmc_extq_list_update_all(int unit, int ipmc_id, int q_num,
   5084                                        SHR_BITDCL *q_vec, uint32 *q_repl_ptr)
   5085 {
   5086     int rv = BCM_E_NONE;
   5087     int prev_start_ptr, list_start_ptr;
   5088     _bcm_repl_list_info_t *rli_start, *rli_current, *rli_prev;
   5089     int queue_count = 0;
   5090     
   5091 
   5092     /*Check previous group pointer*/
   5093     if ((rv = _kt_extq_mc_group_ptr(unit, ipmc_id, &prev_start_ptr, 0, 0)) < 0 ){
   5094         return rv;
   5095     }  
   5096 
   5097     rli_start =  IPMC_EXTQ_REPL_LIST_INFO(unit);
   5098     if ((rv = _bcm_kt_extq_repl_list_write(unit, q_num, q_vec, q_repl_ptr,
   5099                     &list_start_ptr,&queue_count)) < 0) {
   5100         return rv;
   5101     }
   5102 
   5103     if (prev_start_ptr != 0) {
   5104         list_start_ptr = 0;
   5105         if ((rv = _kt_extq_mc_group_ptr(unit, ipmc_id,
   5106                         &list_start_ptr, 0, 1)) < 0) {
   5107             return rv;
   5108         }
   5109     }
   5110 
   5111     IPMC_EXTQ_REPL_QUEUE_COUNT(unit, ipmc_id) = queue_count;
   5112 
   5113     if (prev_start_ptr != 0) {
   5114         rli_prev = NULL;
   5115         for (rli_current = rli_start; rli_current != NULL;
   5116                 rli_current = rli_current->next) {
   5117             if (prev_start_ptr == rli_current->index) {
   5118                 (rli_current->refcount)--;
   5119                 if (rli_current->refcount == 0) {
   5120                     /* Free these linked list entries */
   5121                     rv = _bcm_kt_extq_repl_list_free(unit, prev_start_ptr);
   5122                     /* If we have an error, we'll fall out anyway */
   5123                     if (rli_prev == NULL) {
   5124                         IPMC_EXTQ_REPL_LIST_INFO(unit) = rli_current->next;
   5125                     } else {
   5126                         rli_prev->next = rli_current->next;
   5127                     }
   5128                     sal_free(rli_current);
   5129                 }
   5130                 break;
   5131             }
   5132             rli_prev = rli_current;
   5133         }
   5134     }
   5135     return rv;
   5136 }
   5137 #endif
   5138 
   5139 int
   5140 _bcm_kt_ipmc_extq_list_update(int unit, int ipmc_id, bcm_port_t port, 
   5141                               int q_num, SHR_BITDCL *q_vec, 
   5142                               uint32 *q_repl_ptr)
   5143 {
   5144     int     rv = BCM_E_NONE;
   5145     int     list_start_ptr, prev_start_ptr;
   5146     int     alloc_size, extq_hash, last_flag;
   5147     int     queue_count = 0;
   5148     _bcm_repl_list_info_t *rli_start, *rli_current, *rli_prev;
   5149 
   5150     /* Check previous group pointer */
   5151     if ((rv = _kt_extq_mc_group_ptr(unit, ipmc_id,
   5152                                 &prev_start_ptr, 0, 0)) < 0) {
   5153         goto list_update_done;
   5154     }
   5155 
   5156     /* Search for list already in table */
   5157     rli_start = IPMC_EXTQ_REPL_LIST_INFO(unit);
   5158 
   5159     extq_hash =
   5160       _shr_crc32b(0, (uint8 *)q_vec, IPMC_EXTQ_TOTAL(unit));
   5161 
   5162       for (rli_current = rli_start; rli_current != NULL;
   5163            rli_current = rli_current->next) {
   5164           if (extq_hash == rli_current->hash) {
   5165               rv = _bcm_kt_extq_repl_list_compare(unit, rli_current->index,
   5166                                              q_vec, q_repl_ptr);
   5167               if (rv == BCM_E_NOT_FOUND) {
   5168                   continue; /* Not a match */
   5169               } else if (rv < 0) {
   5170                   goto list_update_done; /* Access error */
   5171               } else {
   5172                   break; /* Match */
   5173               }
   5174           }
   5175       }
   5176 
   5177       if (rli_current != NULL) {
   5178           /* Found a match, point to here and increase reference count */
   5179           if (prev_start_ptr == rli_current->index) {
   5180               /* We're already pointing to this list, so done */
   5181               rv = BCM_E_NONE;
   5182               goto list_update_done;
   5183           } else {
   5184               list_start_ptr = rli_current->index;
   5185               queue_count = rli_current->list_size;
   5186           }
   5187       } else {
   5188           /* Not a match, make a new chain */
   5189           if ((rv = _bcm_kt_extq_repl_list_write(unit, q_num, 
   5190                                                 q_vec, q_repl_ptr,
   5191                                                 &list_start_ptr,
   5192                                                 &queue_count)) < 0) {
   5193           goto list_update_done;
   5194           }
   5195 
   5196           if (queue_count > 0) {
   5197               /* Update data structures */
   5198               alloc_size = sizeof(_bcm_repl_list_info_t);
   5199               rli_current = sal_alloc(alloc_size, "IPMC extq repl list info");
   5200               if (rli_current == NULL) {
   5201                   /* Release list */
   5202                   _bcm_kt_extq_repl_list_free(unit, list_start_ptr);
   5203                   rv = BCM_E_MEMORY;
   5204                   goto list_update_done;
   5205               }
   5206               sal_memset(rli_current, 0, alloc_size);
   5207               rli_current->index = list_start_ptr;
   5208               rli_current->hash = extq_hash;
   5209               rli_current->next = rli_start;
   5210               rli_current->list_size = queue_count;
   5211               IPMC_EXTQ_REPL_LIST_INFO(unit) = rli_current;
   5212               rli_start = rli_current;
   5213           }
   5214       }
   5215 
   5216       last_flag = (queue_count == 1);
   5217 
   5218       if (queue_count > 0) {
   5219           if ((rv = _kt_extq_mc_group_ptr(unit, ipmc_id, 
   5220                                   &list_start_ptr, last_flag, 1)) < 0) {
   5221           if (rli_current->refcount == 0) {
   5222               /* This was new */
   5223               _bcm_kt_extq_repl_list_free(unit, list_start_ptr);
   5224               IPMC_EXTQ_REPL_LIST_INFO(unit) = rli_current->next;
   5225               sal_free(rli_current);
   5226           }
   5227           goto list_update_done;
   5228           }
   5229 
   5230           (rli_current->refcount)++;
   5231           /* we don't need this rli_current anymore */
   5232       } else if (prev_start_ptr != 0) {
   5233           list_start_ptr = 0;
   5234           if ((rv = _kt_extq_mc_group_ptr(unit, ipmc_id,
   5235                                   &list_start_ptr, last_flag, 1)) < 0) {
   5236           goto list_update_done;
   5237           }
   5238       }
   5239       
   5240       IPMC_EXTQ_REPL_QUEUE_COUNT(unit, ipmc_id) = queue_count;
   5241 
   5242       if (prev_start_ptr != 0) {
   5243           rli_prev = NULL;
   5244           for (rli_current = rli_start; rli_current != NULL;
   5245                rli_current = rli_current->next) {
   5246               if (prev_start_ptr == rli_current->index) {
   5247                   (rli_current->refcount)--;
   5248                   if (rli_current->refcount == 0) {
   5249                       /* Free these linked list entries */
   5250                       rv = _bcm_kt_extq_repl_list_free(unit, prev_start_ptr);
   5251                       /* If we have an error, we'll fall out anyway */
   5252                       if (rli_prev == NULL) {
   5253                           IPMC_EXTQ_REPL_LIST_INFO(unit) = rli_current->next;
   5254                       } else {
   5255                           rli_prev->next = rli_current->next;
   5256                       }
   5257                       sal_free(rli_current);
   5258                   }
   5259                   break;
   5260               }
   5261               rli_prev = rli_current;
   5262           }
   5263       }
   5264 
   5265     list_update_done:
   5266     return rv;
   5267 }
   5268 
   5269 #ifdef BCM_KATANA2_SUPPORT
   5270 int
   5271 _bcm_kt2_ipmc_subscriber_egress_queue_qos_map(int unit, int extq_ptr,
   5272                                              int base_queue_id,
   5273                                              int *map_id,
   5274                                              int set)
   5275 {
   5276     int rv = BCM_E_NOT_FOUND;
   5277     int next_ptr1, next_ptr2;
   5278     int queue_id;
   5279     int i;
   5280     int profile = 0;
   5281     mmu_ext_mc_queue_list0_entry_t qlist0_entry;
   5282     mmu_ext_mc_queue_list1_entry_t qlist1_entry;
   5283     mmu_ext_mc_queue_list4_entry_t qlist4_entry;
   5284     soc_field_t   base_qid[] = { BASE_QID0f, BASE_QID1f };
   5285     soc_field_t   profile_idx[] = { Q_OFFSET_PROF0f, Q_OFFSET_PROF1f };
   5286 
   5287 
   5288     if (map_id == NULL) {
   5289         return BCM_E_INTERNAL;
   5290     }
   5291 
   5292     if (set) {
   5293         if ((*map_id >> _BCM_QOS_MAP_SHIFT) !=
   5294             _BCM_QOS_MAP_TYPE_RQE_QUEUE_OFFSET_MAP) {
   5295            return BCM_E_PARAM;
   5296         }
   5297         /* Extract the profile_offset from QOS MAP*/
   5298         profile = *map_id & _BCM_QOS_MAP_TYPE_MASK;
   5299 
   5300         if ((profile < KT2_MIN_RQE_PROFILE_INDEX ) ||
   5301             (profile > KT2_MAX_RQE_PROFILE_INDEX)) {
   5302             return BCM_E_PARAM;
   5303         }
   5304     }
   5305 
   5306     if ((rv = READ_MMU_EXT_MC_QUEUE_LIST0m(unit, MEM_BLOCK_ANY,
   5307                                       extq_ptr, &qlist0_entry)) < 0) {
   5308         goto extq_list_done;
   5309     }
   5310     if ((rv = READ_MMU_EXT_MC_QUEUE_LIST1m(unit, MEM_BLOCK_ANY,
   5311                                       extq_ptr, &qlist1_entry)) < 0) {
   5312         goto extq_list_done;
   5313     }
   5314     if ((rv = READ_MMU_EXT_MC_QUEUE_LIST4m(unit, MEM_BLOCK_ANY,
   5315                                       extq_ptr, &qlist4_entry)) < 0) {
   5316         goto extq_list_done;
   5317     }
   5318 
   5319     for (i = 0; i < 2; i++) {
   5320         if ((queue_id = soc_MMU_EXT_MC_QUEUE_LIST0m_field32_get(unit,
   5321                                     &qlist0_entry, base_qid[i])) != 0) {
   5322 
   5323             if (base_queue_id == queue_id) {
   5324                 if (set) {
   5325 
   5326                     /* set the profile index of the queue list entry */
   5327                     soc_MMU_EXT_MC_QUEUE_LIST0m_field32_set(unit,
   5328                                         &qlist0_entry,
   5329                                         profile_idx[i], profile);
   5330 
   5331                     rv = WRITE_MMU_EXT_MC_QUEUE_LIST0m(unit,
   5332                                           MEM_BLOCK_ANY,
   5333                                           extq_ptr, &qlist0_entry);
   5334                 } else {
   5335                     profile = soc_mem_field32_get(unit,
   5336                                     MMU_EXT_MC_QUEUE_LIST0m,
   5337                                     &qlist0_entry, profile_idx[i]);
   5338                     *map_id = profile | (_BCM_QOS_MAP_TYPE_RQE_QUEUE_OFFSET_MAP
   5339                                                      << _BCM_QOS_MAP_SHIFT);
   5340 
   5341                     rv = BCM_E_NONE;
   5342                 }
   5343 
   5344                 goto extq_list_done;
   5345             }
   5346         }
   5347     }
   5348     for (i = 0; i < 2; i++) {
   5349         if ((queue_id = soc_MMU_EXT_MC_QUEUE_LIST1m_field32_get(unit,
   5350                                     &qlist1_entry, base_qid[i])) != 0) {
   5351             if (base_queue_id == queue_id) {
   5352                 if (set) {
   5353 
   5354                     /* set the profile index of the queue list entry */
   5355                     soc_MMU_EXT_MC_QUEUE_LIST0m_field32_set(unit,
   5356                                         &qlist0_entry,
   5357                                         profile_idx[i], profile);
   5358 
   5359                     rv = WRITE_MMU_EXT_MC_QUEUE_LIST0m(unit,
   5360                                           MEM_BLOCK_ANY,
   5361                                           extq_ptr, &qlist0_entry);
   5362                 } else {
   5363                     profile = soc_mem_field32_get(unit,
   5364                                     MMU_EXT_MC_QUEUE_LIST0m,
   5365                                     &qlist0_entry, profile_idx[i]);
   5366                     *map_id = profile | (_BCM_QOS_MAP_TYPE_RQE_QUEUE_OFFSET_MAP
   5367                                                      << _BCM_QOS_MAP_SHIFT);
   5368                     rv = BCM_E_NONE;
   5369                 }
   5370 
   5371                 goto extq_list_done;
   5372             }
   5373         }
   5374     }
   5375 
   5376     next_ptr1 = soc_MMU_EXT_MC_QUEUE_LIST4m_field32_get(unit,
   5377                             &qlist4_entry, EXT_Q_NXT_PTR1f);
   5378     next_ptr2 = soc_MMU_EXT_MC_QUEUE_LIST4m_field32_get(unit,
   5379                             &qlist4_entry, EXT_Q_NXT_PTR2f);
   5380 
   5381     if (next_ptr1 != extq_ptr) {
   5382         rv = _bcm_kt2_ipmc_subscriber_egress_queue_qos_map(unit, next_ptr1,
   5383                                                  base_queue_id, map_id, set);
   5384     }
   5385 
   5386     if (next_ptr2 != extq_ptr) {
   5387         rv = _bcm_kt2_ipmc_subscriber_egress_queue_qos_map(unit, next_ptr2,
   5388                                                  base_queue_id, map_id, set);
   5389     }
   5390 
   5391 extq_list_done:
   5392     return rv;
   5393 }
   5394 
   5395 /*
   5396  * Function:
   5397  *    _bcm_kt2_ipmc_subscriber_egress_intf_qos_map_set
   5398  * Purpose:
   5399  *    Assign the complete set of egress GPORTs in the
   5400  *   replication list for the specified multicast index.
   5401  * Parameters:
   5402  *   unit              - (IN) Device Number
   5403  *   group             - (IN) Multicast group ID
   5404  *   port              - (IN) GPORT Identifier
   5405  *   subscriber queue  - (IN) Subscriber queue group GPORT Identifiers
   5406  *   qos_map_id        - (IN) Qos Map ID
   5407  * Returns:
   5408  *    BCM_E_XXX
   5409  */
   5410 int
   5411 _bcm_kt2_ipmc_subscriber_egress_intf_qos_map_set(int unit,
   5412                                         int ipmc_id,
   5413                                         bcm_gport_t port,
   5414                                         bcm_gport_t subscriber_queue,
   5415                                         int qos_map_id)
   5416 {
   5417     int         rv = BCM_E_NONE;
   5418     int         extq_ptr;
   5419     int         queue_id;
   5420 
   5421 
   5422     /*
   5423      1. For ipmc_id traverse the queue list
   5424      2. if queue matches the list entry set the profile
   5425      3. else error
   5426      */
   5427     REPL_PORT_CHECK(unit, port);
   5428     BCM_IF_ERROR_RETURN(_bcm_kt_init_check(unit, ipmc_id));
   5429 
   5430     if ((rv = _bcm_kt2_cosq_index_resolve(unit,  subscriber_queue, 0,
   5431                            _BCM_KT2_COSQ_INDEX_STYLE_QUEUE_REPLICATION,
   5432                            NULL,  &queue_id, NULL)) < 0) {
   5433         goto clean_up;
   5434     }
   5435 
   5436     IPMC_REPL_LOCK(unit);
   5437     if ((rv = _kt_extq_mc_group_ptr(unit, ipmc_id,
   5438                                 &extq_ptr, 0, 0)) < 0) {
   5439         goto clean_up;
   5440     }
   5441 
   5442     if (extq_ptr == 0) {
   5443         rv = BCM_E_INTERNAL;
   5444         goto clean_up;
   5445     }
   5446 
   5447     rv = _bcm_kt2_ipmc_subscriber_egress_queue_qos_map(unit, extq_ptr,
   5448                                                   queue_id,
   5449                                                   &qos_map_id,
   5450                                                   1);
   5451 
   5452     if (BCM_FAILURE(rv)) {
   5453        LOG_ERROR(BSL_LS_BCM_COMMON,
   5454                       (BSL_META_U(unit,"\n unit %d: Failure - setting subscriber queue %d Qos Map profile %d"),
   5455                            unit, subscriber_queue, qos_map_id));
   5456     } 
   5457 clean_up:
   5458     IPMC_REPL_UNLOCK(unit);
   5459     return rv;
   5460 }
   5461 
   5462 /*
   5463  * Function:
   5464  *    _bcm_kt2_ipmc_subscriber_egress_intf_qos_map_get
   5465  * Purpose:
   5466  *    Assign the complete set of egress GPORTs in the
   5467  *   replication list for the specified multicast index.
   5468  * Parameters:
   5469  *   unit              - (IN) Device Number
   5470  *   group             - (IN) Multicast group ID
   5471  *   port              - (IN) GPORT Identifier
   5472  *   subscriber queue  - (IN) Subscriber queue group GPORT Identifiers
   5473  *   qos_map_id        - (OUT) Qos Map ID
   5474  * Returns:
   5475  *    BCM_E_XXX
   5476  */
   5477 int
   5478 _bcm_kt2_ipmc_subscriber_egress_intf_qos_map_get(int unit,
   5479                                         int ipmc_id,
   5480                                         bcm_gport_t port,
   5481                                         bcm_gport_t subscriber_queue,
   5482                                         int *qos_map_id)
   5483 {
   5484     int         rv = BCM_E_NONE;
   5485     int         extq_ptr;
   5486     int         queue_id;
   5487 
   5488 
   5489     /*
   5490      1. For ipmc_id traverse the queue list
   5491      2. if queue matches the list entry set the profile
   5492      3. else error
   5493      */
   5494     REPL_PORT_CHECK(unit, port);
   5495     BCM_IF_ERROR_RETURN(_bcm_kt_init_check(unit, ipmc_id));
   5496 
   5497     if (qos_map_id == NULL) {
   5498         return BCM_E_INTERNAL;
   5499     }
   5500     IPMC_REPL_LOCK(unit);
   5501 
   5502     if ((rv = _bcm_kt2_cosq_index_resolve(unit,  subscriber_queue, 0,
   5503                            _BCM_KT2_COSQ_INDEX_STYLE_QUEUE_REPLICATION,
   5504                            NULL,  &queue_id, NULL)) < 0) {
   5505         goto clean_up;
   5506     }
   5507     if ((rv = _kt_extq_mc_group_ptr(unit, ipmc_id,
   5508                                 &extq_ptr, 0, 0)) < 0) {
   5509         goto clean_up;
   5510     }
   5511 
   5512     if (extq_ptr == 0) {
   5513         rv = BCM_E_INTERNAL;
   5514         goto clean_up;
   5515     }
   5516 
   5517     rv = _bcm_kt2_ipmc_subscriber_egress_queue_qos_map(unit, extq_ptr,
   5518                                                   queue_id,
   5519                                                   qos_map_id,
   5520                                                   0);
   5521 
   5522     if (BCM_FAILURE(rv)) {
   5523        LOG_ERROR(BSL_LS_BCM_COMMON,
   5524                       (BSL_META_U(unit,
   5525         "unit %d: Failure - getting subscriber queue %d Qos Map profile %d"),
   5526                            unit, subscriber_queue, *qos_map_id));
   5527     }
   5528 clean_up:
   5529     IPMC_REPL_UNLOCK(unit);
   5530     return rv;
   5531 }
   5532 #endif /* BCM_KATANA2_SUPPORT */
   5533 /*
   5534  * Function:
   5535  *    _bcm_kt_ipmc_subscriber_egress_intf_set
   5536  * Purpose:
   5537  *    Assign set of egress interfaces to port's replication list for chosen
   5538  *    IPMC group.
   5539  * Parameters:
   5540  *    unit     - StrataSwitch PCI device unit number.
   5541  *    ipmc_id  - The index number.
   5542  *    port     - port to list.
   5543  *    subscriber_queue - subscriber's gport
   5544  *    if_count - number of interfaces in replication list.
   5545  *    if_array - (IN) List of interface numbers.
   5546  *      check_port - (IN) If if_array consists of L3 interfaces, this parameter
   5547  *                        controls whether to check the given port is a member
   5548  *                        in each L3 interface's VLAN. This check should be
   5549  *                        disabled when not needed, in order to improve
   5550  *                        performance.
   5551  * Returns:
   5552  *    BCM_E_XXX
   5553  */
   5554 int
   5555 _bcm_kt_ipmc_subscriber_egress_intf_set(int unit, int ipmc_id,
   5556                                         bcm_port_t port, int if_count,
   5557                                         int *id,
   5558                                         bcm_gport_t subscriber_queue,
   5559                                         int is_l3,
   5560                                         int *queue_count,
   5561                                         int *q_count_increased)
   5562 {
   5563     int     *if_array = NULL;
   5564     int     q_num = 0;
   5565     int     alloc_size;
   5566     int     rv = BCM_E_NONE;
   5567     int     queue_id;
   5568     int     q_found = 0;
   5569     int     q_max, ptr_type = 1;
   5570     int     ipmc_ptr, i;
   5571     int     new_ipmc_ptr = 0;
   5572     int     last_ipmc_flag = 0;
   5573     uint32     *q_repl_ptr = NULL;
   5574     SHR_BITDCL *q_vec = NULL;
   5575     int     partition = TD_EGR_L3_NEXT_HOP_OFFSET;
   5576     int     nh_index = 0;
   5577     int     port_qcount_increased = 0;
   5578     uint16  sw_index = 0;
   5579     REPL_PORT_CHECK(unit, port);
   5580     BCM_IF_ERROR_RETURN(_bcm_kt_init_check(unit, ipmc_id));
   5581 
   5582     /* Hardware decides the replication on L3 interfaces or
   5583      * Next hop based on L3_REPL_PTRX 13th bit
   5584      * < 8k replication on Nexthop
   5585      * > 8k replication on L3 interfaces
   5586      */
   5587     partition = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
   5588 
   5589     q_max = IPMC_EXTQ_TOTAL(unit);
   5590     alloc_size = q_max * sizeof(int);
   5591     q_repl_ptr = sal_alloc(alloc_size, "IPMC repl interface array");
   5592     if (q_repl_ptr == NULL) {
   5593         return BCM_E_MEMORY;
   5594     }
   5595     sal_memset(q_repl_ptr, 0, alloc_size);
   5596 
   5597     alloc_size = SHR_BITALLOCSIZE(IPMC_EXTQ_TOTAL(unit));
   5598     q_vec = sal_alloc(alloc_size, "IPMC extq replication vector");
   5599     if (q_vec == NULL) {
   5600         sal_free(q_repl_ptr);
   5601         return BCM_E_MEMORY;
   5602     }
   5603     sal_memset(q_vec, 0, alloc_size);
   5604 
   5605     IPMC_REPL_LOCK(unit);    
   5606 
   5607     if ((rv = _bcm_kt_ipmc_subscriber_queues_get(unit, ipmc_id, q_vec, 
   5608                             q_repl_ptr, &q_num)) < 0 ) {
   5609         goto intf_add_done;                            
   5610     }
   5611     
   5612     if (q_num > q_max) {
   5613         rv = BCM_E_PARAM;
   5614         goto intf_add_done;                            
   5615     }
   5616     if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(subscriber_queue)) {
   5617         sw_index = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(
   5618                       subscriber_queue);
   5619     } else if (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(subscriber_queue)) {
   5620         sw_index = BCM_GPORT_MCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(
   5621                       subscriber_queue);
   5622     } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(subscriber_queue)) {
   5623         sw_index = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(subscriber_queue);
   5624     } else {
   5625         rv = BCM_E_PARAM;
   5626         goto intf_add_done;
   5627     }
   5628     if (sw_index >= IPMC_EXTQ_TOTAL(unit)) {
   5629         rv = BCM_E_PARAM;
   5630         goto intf_add_done;
   5631     }
   5632 #ifdef BCM_KATANA2_SUPPORT
   5633     if (SOC_IS_KATANA2(unit)) {
   5634         if ((rv = _bcm_kt2_cosq_index_resolve(unit,  subscriber_queue, 0,
   5635                                  _BCM_KT2_COSQ_INDEX_STYLE_QUEUE_REPLICATION,
   5636                                  NULL,  &queue_id, NULL)) < 0) {
   5637             goto intf_add_done;
   5638         }
   5639     } else /* BCM_KATANA2_SUPPORT */
   5640 #endif
   5641     {
   5642         if ((rv = _bcm_kt_cosq_index_resolve(unit,  subscriber_queue, 0,
   5643                                 _BCM_KT_COSQ_INDEX_STYLE_QUEUE_REPLICATION,
   5644                                 NULL,  &queue_id, NULL)) < 0) {
   5645             goto intf_add_done;
   5646         }
   5647     }
   5648     sw_to_hw_queue[unit][sw_index] = (queue_id << 8) | port;
   5649 
   5650     if (SHR_BITGET(q_vec, queue_id)) {
   5651         q_found = 1;
   5652         if (SOC_IS_KATANA2(unit)) {         
   5653             ptr_type = (q_repl_ptr[queue_id] >> 13) & 0x3;  
   5654         } else {
   5655             ptr_type = (q_repl_ptr[queue_id] >> 14) & 1; 
   5656         }
   5657     }
   5658 
   5659     if (q_found) {
   5660         if (SOC_IS_KATANA2(unit)) {
   5661             ipmc_ptr = q_repl_ptr[queue_id] & 0x1fff;
   5662             
   5663         } else {
   5664             ipmc_ptr = q_repl_ptr[queue_id] & 0x3fff;
   5665         }
   5666         if (ptr_type == 0) {
   5667             /* already ipmc ptr */
   5668             /* add this interface into ipmc chain */
   5669 #ifdef BCM_KATANA2_SUPPORT
   5670             if (SOC_IS_KATANA2(unit)) {
   5671                 if (if_count == 1) {
   5672                 rv = _bcm_kt2_ipmc_egress_intf_add(unit, ipmc_id, port,
   5673                                                  ipmc_ptr, *id,
   5674                                                  &new_ipmc_ptr,
   5675                                                  &last_ipmc_flag);
   5676                 } else {
   5677                   rv =  _bcm_kt2_ipmc_egress_intf_set(unit, ipmc_id, port,
   5678                                                  ipmc_ptr, if_count,
   5679                                                  id, &new_ipmc_ptr,
   5680                                                  &last_ipmc_flag, FALSE);
   5681 
   5682                 }
   5683                 if (rv) { 
   5684                     goto intf_add_done;
   5685                 }
   5686 
   5687             } 
   5688 #endif
   5689             if (SOC_IS_KATANA(unit)) {
   5690                 if (if_count == 1) {
   5691                      rv = _bcm_kt_ipmc_egress_intf_add(unit, ipmc_id, port,
   5692                                                  ipmc_ptr, *id,
   5693                                                  &new_ipmc_ptr,
   5694                                                  &last_ipmc_flag);
   5695 
   5696                 } else {
   5697                    rv = _bcm_kt_ipmc_egress_intf_set(unit, ipmc_id, port,
   5698                                                  ipmc_ptr, if_count,
   5699                                                  id, &new_ipmc_ptr,
   5700                                                  &last_ipmc_flag, FALSE);
   5701 
   5702                 }            
   5703 
   5704                 if (rv) { 
   5705                     goto intf_add_done;
   5706                 } 
   5707             }
   5708             q_repl_ptr[queue_id] = (q_repl_ptr[queue_id] & (~0 << 14)) +
   5709                                    new_ipmc_ptr;
   5710             if (last_ipmc_flag) {
   5711                 q_repl_ptr[queue_id] |= (last_ipmc_flag << 17);
   5712             }
   5713             else { 
   5714                 q_repl_ptr[queue_id] &= ~(1 << 17);
   5715             }
   5716         } else {
   5717             /* this piece of code should only execute for KATANA  
   5718                as ptr_type will always set to 0 for KATANA2
   5719              */
   5720             /* its a l3 or nh entry */
   5721             alloc_size =  (if_count + 1) * sizeof(int);
   5722             if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   5723             if (if_array == NULL) {
   5724                 rv = BCM_E_MEMORY;
   5725                 goto intf_add_done;
   5726             }
   5727             if (ipmc_ptr < partition) {
   5728                 if_array[0] = ipmc_ptr + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   5729             } else {
   5730                 if_array[0] = ipmc_ptr - partition;
   5731             }
   5732             for (i = 0; i < if_count; i++) {
   5733                 if_array[1+i] = id[i];
   5734             }
   5735             _bcm_kt_ipmc_egress_intf_set(unit, ipmc_id, port, 0, (if_count + 1),
   5736                                         if_array, &new_ipmc_ptr, &last_ipmc_flag, 
   5737                                         FALSE);
   5738             /* replace the ptr_type */
   5739             q_repl_ptr[queue_id] = (q_repl_ptr[queue_id] & (~0 << 15)) + 
   5740                                    new_ipmc_ptr; 
   5741             
   5742             if (last_ipmc_flag) {
   5743                 q_repl_ptr[queue_id] |= (last_ipmc_flag << 17);
   5744             }
   5745             else { 
   5746                 q_repl_ptr[queue_id] &= ~(1 << 17);
   5747             }
   5748         }
   5749     }
   5750 
   5751     if (q_found == 0) {
   5752         SHR_BITSET(q_vec, queue_id);
   5753 #ifdef BCM_KATANA2_SUPPORT
   5754         if (SOC_IS_KATANA2(unit)) {
   5755             if (if_count == 1) {
   5756                 _bcm_kt2_ipmc_egress_intf_add(unit, ipmc_id, port,
   5757                                               0, *id,
   5758                                               &new_ipmc_ptr,
   5759                                               &last_ipmc_flag);
   5760             } else {
   5761                 _bcm_kt2_ipmc_egress_intf_set(unit, ipmc_id, port,
   5762                                               0, if_count,
   5763                                               id, &new_ipmc_ptr,
   5764                                               &last_ipmc_flag, FALSE);
   5765 
   5766             }                 
   5767             q_repl_ptr[queue_id] = new_ipmc_ptr;
   5768             q_repl_ptr[queue_id] |= (last_ipmc_flag << 17);
   5769         } 
   5770 #endif
   5771         if (SOC_IS_KATANA(unit)) {
   5772             /* set interface accordingly, the ptr_type = 1 */        
   5773             if (if_count == 1) {
   5774                 /* Replication is next hop or L3 interface */                                 
   5775                 if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, *id)) {
   5776                     /* L3 interface */
   5777                     nh_index = partition + *id;
   5778                 } else {
   5779                     /* Next hop entry */
   5780                     nh_index = *id - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit) ;
   5781                 }
   5782                 q_repl_ptr[queue_id] = (1 << 14) + nh_index;
   5783             } else {
   5784                 _bcm_kt_ipmc_egress_intf_set(unit, ipmc_id, port, 0, if_count , id, 
   5785                                           &new_ipmc_ptr, &last_ipmc_flag, FALSE);
   5786                 q_repl_ptr[queue_id] = new_ipmc_ptr; /* replace the ptr_type */
   5787                 q_repl_ptr[queue_id] |= (last_ipmc_flag << 17);
   5788 
   5789             }
   5790         }
   5791         q_num++;
   5792         port_qcount_increased = 1;
   5793     }
   5794 
   5795     if (q_num > IPMC_EXTQ_REPL_MAX(unit)) {
   5796         rv = BCM_E_PARAM;
   5797         goto intf_add_done;                                            
   5798     }
   5799 
   5800     if (IS_EXT_MEM_PORT(unit, port)) {
   5801         q_repl_ptr[queue_id] |= (1 << 16);
   5802     }
   5803 
   5804     if ((rv = _bcm_kt_ipmc_extq_list_update(unit, ipmc_id, port, q_num, 
   5805                                             q_vec, q_repl_ptr)) < 0 ) {
   5806         goto intf_add_done;                                            
   5807     }
   5808 #ifdef BCM_KATANA2_SUPPORT
   5809     if (SOC_IS_KATANA2(unit) && !SOC_IS_SABER2(unit)) {
   5810         rv = _bcm_kt2_intf_ref_cnt_increment(unit, sw_index, if_count);
   5811     } else
   5812 #endif
   5813     {
   5814         rv = _bcm_kt_intf_ref_cnt_increment(unit, sw_index, if_count);
   5815     }
   5816 
   5817     if (queue_count != NULL) {
   5818         *queue_count = q_num;
   5819     }
   5820 
   5821     if (q_count_increased != NULL) {
   5822         *q_count_increased = port_qcount_increased;
   5823     }
   5824 
   5825 intf_add_done:
   5826     IPMC_REPL_UNLOCK(unit);
   5827     if (q_repl_ptr != NULL) {
   5828         sal_free(q_repl_ptr);
   5829     }
   5830     if (q_vec != NULL) {
   5831         sal_free(q_vec);
   5832     }
   5833     if (if_array != NULL) {
   5834         sal_free(if_array);
   5835     }
   5836     return rv;
   5837 
   5838 }
   5839 
   5840 /*
   5841  * Function:
   5842  *    bcm_kt_ipmc_subscriber_egress_intf_get
   5843  * Purpose:
   5844  *    Retreieve set of egress interfaces in extended  queue's replication list
   5845  *      for chosen IPMC group.
   5846  * Parameters:
   5847  *    unit     - StrataSwitch PCI device unit number.
   5848  *    ipmc_id  - The index number.
   5849  *    port     - port to list.
   5850  *    subscriber_queue - subscriber gport 
   5851  *    if_max   - maximum number of interfaces in replication list.
   5852  *      if_array - (OUT) List of interface numbers.
   5853  *    if_count - (OUT) number of interfaces returned in replication list.
   5854  * Returns:
   5855  *    BCM_E_XXX
   5856  * Notes:
   5857  *      If the input parameter if_max = 0, return in the output parameter
   5858  *      if_count the total number of interfaces in the specified multicast
   5859  *      group's replication list.
   5860  */
   5861 int
   5862 _bcm_kt_ipmc_subscriber_egress_intf_get(int unit, int ipmc_id, int if_max, 
   5863                                         bcm_gport_t *port_array, 
   5864                                         bcm_if_t *if_array, 
   5865                                         bcm_gport_t *subs_array, 
   5866                                         int *count)
   5867 {
   5868        int             rv = BCM_E_NONE;
   5869        int             alloc_size;
   5870        int             vlan_ptr, last_vlan_ptr;
   5871        int             extq_ptr;    
   5872        int             vlan_count;
   5873        int             ls_pos;
   5874        int             intf_base, nh_offset;
   5875        int             i;    
   5876        int             *baseq_array = NULL;
   5877        int             *repl_ptr_array = NULL;
   5878        int             q_count = 0;
   5879        int             id = 0;
   5880        int             partition = TD_EGR_L3_NEXT_HOP_OFFSET;
   5881 #ifdef BCM_KATANA2_SUPPORT
   5882        int             temp_count = 0;    
   5883        int             j = 0 ;  
   5884 #endif
   5885        uint32          ls_bits[2];    
   5886        mmu_ipmc_vlan_tbl_entry_t vlan_entry;
   5887           
   5888        
   5889        BCM_IF_ERROR_RETURN(_bcm_kt_init_check(unit, ipmc_id));
   5890 
   5891        /* Hardware decides the replication on L3 interfaces or
   5892         * Next hop based on L3_REPL_PTRX 13th bit
   5893         * < 8k replication on Nexthop
   5894         * > 8k replication on L3 interfaces
   5895         */
   5896        partition = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
   5897  
   5898        if (if_max < 0 || if_max > IPMC_EXTQ_TOTAL(unit)) {
   5899            return BCM_E_PARAM;
   5900        }
   5901     
   5902        alloc_size =  IPMC_EXTQ_REPL_MAX(unit) * sizeof(int);
   5903        baseq_array = sal_alloc(alloc_size, "IPMC repl base queue array");
   5904        if (baseq_array == NULL) {
   5905             return BCM_E_MEMORY;
   5906        }    
   5907        repl_ptr_array = sal_alloc(alloc_size, "IPMC repl interface array");
   5908        if (repl_ptr_array == NULL) {
   5909             sal_free(baseq_array);
   5910             return BCM_E_MEMORY;
   5911        }    
   5912            
   5913        IPMC_REPL_LOCK(unit);
   5914 
   5915        if ((rv = _kt_extq_mc_group_ptr(unit, ipmc_id,
   5916                                 &extq_ptr, 0, 0)) < 0) {
   5917             goto intf_get_done;
   5918         }
   5919 
   5920         if (extq_ptr != 0) {
   5921            rv = _bcm_kt_ipmc_subscriber_egress_intf_traverse(unit, extq_ptr, 
   5922                                       baseq_array, repl_ptr_array, &q_count);
   5923         }
   5924 
   5925        vlan_count = 0;    
   5926        for (i = 0; i < q_count; i++) {
   5927 #ifdef BCM_KATANA2_SUPPORT
   5928             if (SOC_IS_KATANA2(unit)) {
   5929                 if ((repl_ptr_array[i] >> 13) & 0x3) {
   5930                     rv = BCM_E_INTERNAL;
   5931                     goto intf_get_done;
   5932                 } else {
   5933                     vlan_ptr = repl_ptr_array[i]  & 0x1fff;
   5934                    
   5935                     rv = _bcm_kt2_ipmc_egress_intf_get (unit, ipmc_id, 
   5936                                                   vlan_ptr,
   5937                                                   &if_array[vlan_count], &temp_count);
   5938                     if(rv != BCM_E_NONE)
   5939                        goto intf_get_done;
   5940                     j = vlan_count;  
   5941                     vlan_count += temp_count;
   5942                      
   5943                     if(vlan_count > if_max) 
   5944                        goto intf_get_done;
   5945                     for( ; j < vlan_count; j++) 
   5946                     {
   5947                         subs_array[j] = baseq_array[i] ; 
   5948                     }
   5949                 }
   5950             
   5951             } 
   5952 #endif
   5953             if (SOC_IS_KATANA(unit)) {
   5954                 if ((repl_ptr_array[i] >> 14) & 1) { /* if its a nh or l3 intf */
   5955 
   5956                     id = repl_ptr_array[i] & ~(1 << 14);
   5957                     if (id < partition)
   5958                     {
   5959                         /* Next hop */
   5960                         if_array[vlan_count] =  id + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   5961                     } else {
   5962                         /* L3 interface */
   5963                         if_array[vlan_count] =  id - partition;
   5964                     }
   5965                     subs_array[vlan_count++] = baseq_array[i]; 
   5966 
   5967                     if (vlan_count == (uint32)if_max) {
   5968                         *count = vlan_count;
   5969                         goto intf_get_done;
   5970                     }
   5971                 } else { /* its a ipmc ptr */
   5972                     vlan_ptr = repl_ptr_array[i]  & 0x3fff; 
   5973                     last_vlan_ptr = -1;
   5974                     if (SOC_IS_TD_TT(unit)) {
   5975                         nh_offset = TD_EGR_L3_NEXT_HOP_OFFSET;
   5976                     } else {
   5977                         /* coverity[large_shift : FALSE] */
   5978                         nh_offset = (1 << (soc_mem_field_length(unit, 
   5979                                                       MMU_IPMC_VLAN_TBLm,
   5980                                                       MSB_VLANf) - 1)) * 64;
   5981                     }
   5982                     while (vlan_ptr != last_vlan_ptr) {
   5983                         if ((rv = READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ANY,
   5984                                                      vlan_ptr, &vlan_entry)) < 0) {
   5985                             goto intf_get_done;
   5986                         }
   5987                         /* Each MSB represents 64 entries in LSB bitmap */
   5988                         intf_base = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, &vlan_entry,
   5989                                                               MSB_VLANf) * 64;
   5990                         soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry,
   5991                                                         LSB_VLAN_BMf, ls_bits);
   5992                         /* Using MSB, check if L3 interface or next hop */
   5993     
   5994                         for (ls_pos = 0; ls_pos < 64; ls_pos++) {
   5995                             if (ls_bits[ls_pos / 32] & (1 << (ls_pos % 32))) {
   5996                                 if (if_max == 0) {
   5997                                     vlan_count++;
   5998                                 } else {
   5999                                     subs_array[vlan_count] = baseq_array[i];
   6000                                     /* Check if L3 interface or next hop */
   6001                                     if (intf_base >= nh_offset) {
   6002                                     /* Entry contains next hops */
   6003                                     if_array[vlan_count++] = intf_base - nh_offset +
   6004                                                                 ls_pos + 
   6005                                                                 BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   6006                                     } else {
   6007                                         /* Entry contains interfaces */
   6008                                         if_array[vlan_count++] = intf_base + ls_pos;
   6009                                     }
   6010                                     if (vlan_count == (uint32)if_max) {
   6011                                         *count = vlan_count;
   6012                                         goto intf_get_done;
   6013                                     }
   6014                                 }
   6015                             }
   6016                         }
   6017                         last_vlan_ptr = vlan_ptr;
   6018                         vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   6019                                                          &vlan_entry, NEXTPTRf);
   6020                     }        
   6021                 }
   6022             } 
   6023        }
   6024 
   6025        *count = vlan_count;
   6026     
   6027     intf_get_done:
   6028        IPMC_REPL_UNLOCK(unit);
   6029        if (baseq_array != NULL) {
   6030            sal_free(baseq_array);
   6031        }
   6032        if (repl_ptr_array != NULL) {
   6033            sal_free(repl_ptr_array);
   6034        }    
   6035        return rv;
   6036 }
   6037 
   6038 #if defined(BCM_KATANA_SUPPORT)
   6039 int
   6040 _bcm_kt_ipmc_egress_intf_delete_all( int unit, int ipmc_id, int ipmc_ptr)
   6041 {
   6042     bcm_if_t *if_array = NULL;
   6043     int alloc_size, intf_max, if_count = 0, rv = BCM_E_NONE;
   6044     SHR_BITDCL *intf_vec = NULL;
   6045     int if_num, partition;
   6046     int intf_count= 0, repl_hash;
   6047     int nh_offset, intf_base;
   6048     uint32 ls_bits[2];
   6049     int ls_pos; 
   6050     int vlan_ptr, last_vlan_ptr;
   6051     mmu_ipmc_vlan_tbl_entry_t vlan_entry;
   6052     _bcm_repl_list_info_t *rli_start,*rli_current, *rli_prev = NULL;
   6053     uint32 nh_count = 0;
   6054 
   6055     partition = soc_mem_index_count(unit, EGR_L3_INTFm);
   6056     intf_max = IPMC_REPL_INTF_TOTAL(unit);
   6057     alloc_size = intf_max *sizeof(bcm_if_t);
   6058     if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   6059     if (if_array == NULL) {
   6060         return BCM_E_MEMORY;
   6061     }
   6062     alloc_size = SHR_BITALLOCSIZE(intf_max);
   6063     intf_vec = sal_alloc(alloc_size, "Repl interface vector");
   6064     if (intf_vec == NULL) {
   6065         sal_free(if_array);
   6066         return BCM_E_MEMORY;
   6067     }
   6068     sal_memset(intf_vec, 0, alloc_size);
   6069     IPMC_REPL_LOCK(unit);
   6070     vlan_ptr = ipmc_ptr;
   6071     last_vlan_ptr = -1;
   6072 
   6073     if (SOC_IS_TD_TT(unit)) {
   6074         nh_offset = TD_EGR_L3_NEXT_HOP_OFFSET;
   6075     } else {
   6076         /* coverity[large_shift : FALSE] */
   6077         /* coverity[negative_shift : FALSE] */
   6078         nh_offset = (1 << (soc_mem_field_length(unit, MMU_IPMC_VLAN_TBLm,
   6079                         MSB_VLANf) - 1)) * 64;
   6080     }
   6081     while (vlan_ptr != last_vlan_ptr) {
   6082         if ((rv = READ_MMU_IPMC_VLAN_TBLm(unit, MEM_BLOCK_ANY,
   6083                         vlan_ptr, &vlan_entry)) < 0) {
   6084             goto error;
   6085         }
   6086         /* Each MSB represents 64 entries in LSB bitmap */
   6087         intf_base = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit, &vlan_entry,
   6088                 MSB_VLANf) * 64;
   6089         soc_MMU_IPMC_VLAN_TBLm_field_get(unit, &vlan_entry,
   6090                 LSB_VLAN_BMf, ls_bits);
   6091         /* Using MSB, check if L3 interface or next hop */
   6092 
   6093         for (ls_pos = 0; ls_pos < 64; ls_pos++) {
   6094             if (ls_bits[ls_pos / 32] & (1 << (ls_pos % 32))) {
   6095                 if (intf_max == 0) {
   6096                     if_count++;
   6097                 } else {
   6098                     /* Check if L3 interface or next hop */
   6099                     if (intf_base >= nh_offset) {
   6100                         /* Entry contains next hops */
   6101                         if_array[if_count++] = intf_base - nh_offset +
   6102                             ls_pos + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   6103                     } else {
   6104                         /* Entry contains interfaces */
   6105                         if_array[if_count++] = intf_base + ls_pos;
   6106                     }
   6107                     if (if_count == (uint32)intf_max) {
   6108                         break;
   6109                     }
   6110                 }
   6111             }
   6112         }
   6113         last_vlan_ptr = vlan_ptr;
   6114         vlan_ptr = soc_MMU_IPMC_VLAN_TBLm_field32_get(unit,
   6115                 &vlan_entry, NEXTPTRf);
   6116 
   6117     } 
   6118     /*prepare the interface vector and find out the refrence count */
   6119     for (if_num = 0; if_num < if_count; if_num++) {
   6120         if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, if_array[if_num]) &&
   6121                 (uint32)(if_array[if_num]) > partition) {
   6122             rv = BCM_E_PARAM;
   6123             break;
   6124         }
   6125         if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, if_array[if_num])) {
   6126             /* L3 interface is used */
   6127             SHR_BITSET(intf_vec, if_array[if_num]);
   6128             intf_count++;
   6129         } else {
   6130             /* Next hop is used */
   6131             SHR_BITSET(intf_vec, partition + if_array[if_num] -
   6132                     BCM_XGS3_DVP_EGRESS_IDX_MIN(unit));
   6133             nh_count++;
   6134         }
   6135     }
   6136     rli_start = IPMC_REPL_LIST_INFO(unit);
   6137     repl_hash =
   6138         _shr_crc32b(0, (uint8 *)intf_vec, IPMC_REPL_INTF_TOTAL(unit));
   6139     for (rli_current = rli_start; rli_current != NULL;
   6140             rli_current = rli_current->next) {
   6141         if (repl_hash == rli_current->hash) {
   6142             rv = _bcm_tr2_repl_list_compare(unit, rli_current->index,
   6143                     intf_vec);
   6144             if (rv == BCM_E_NOT_FOUND) {
   6145                 continue; /* Not a match */
   6146             } else if (rv < 0) {
   6147                 goto error; /* Access error */
   6148             } else {
   6149                 break; /* Match */
   6150             }
   6151         }
   6152         rli_prev = rli_current;
   6153     }
   6154 
   6155     if (rli_current){
   6156         rli_current->refcount-- ;
   6157         if (rli_current->refcount == 0){
   6158             rv = _bcm_tr2_repl_list_free(unit, rli_current->index);
   6159             /* If we have an error, we'll fall out anyway */
   6160             if (rli_prev == NULL) {
   6161                 IPMC_REPL_LIST_INFO(unit) = rli_current->next;
   6162             } else {
   6163                 rli_prev->next = rli_current->next;
   6164             }
   6165             sal_free(rli_current);
   6166         }
   6167     }
   6168 error:
   6169     sal_free(if_array);
   6170     sal_free(intf_vec);
   6171     IPMC_REPL_UNLOCK(unit);
   6172     return rv;
   6173 }
   6174 
   6175 
   6176 int
   6177 _bcm_kt_ipmc_subscriber_egress_intf_delete_all(int unit, int ipmc_id,
   6178                                            int port_count,
   6179                                            bcm_port_t *port_array,
   6180                                            int *encap_array,
   6181                                            bcm_if_t *q_array,
   6182                                            int *q_count_decreased)
   6183 {
   6184     bcm_error_t rv = BCM_E_NONE;
   6185     int alloc_size, q_max;
   6186     uint32 *q_repl_ptr = NULL;
   6187     SHR_BITDCL *q_vec = NULL;
   6188     int q_num = 0;
   6189     int queue_id;
   6190     int ipmc_ptr, ptr_type = 0;
   6191     int i, sw_index = 0;
   6192     bcm_port_t port = 0;
   6193 
   6194     q_max = _kt_extq_repl_info[unit]->queue_num;
   6195     /*queue replication pointers array*/
   6196     alloc_size = q_max * sizeof(int);
   6197     q_repl_ptr = sal_alloc(alloc_size, "IPMC repl interface array");
   6198     if (q_repl_ptr == NULL) {
   6199         return BCM_E_MEMORY;
   6200     }
   6201     sal_memset(q_repl_ptr, 0, alloc_size);
   6202 
   6203     alloc_size = SHR_BITALLOCSIZE(q_max);
   6204     q_vec = sal_alloc(alloc_size, "IPMC extq replication vector");
   6205     if (q_vec == NULL) {
   6206         sal_free(q_repl_ptr);
   6207         return BCM_E_MEMORY;
   6208     }
   6209     sal_memset(q_vec, 0, alloc_size);
   6210 
   6211     IPMC_REPL_LOCK(unit);
   6212     /*get the queue vector for the ipmc id */
   6213     if ((rv = _bcm_kt_ipmc_subscriber_queues_get(unit, ipmc_id, q_vec,
   6214                     q_repl_ptr, &q_num)) < 0 ) {
   6215         goto intf_add_done;
   6216     }
   6217 
   6218     if (q_num > q_max) {
   6219         rv = BCM_E_PARAM;
   6220         goto intf_add_done;
   6221     }
   6222     for (i = 0; i < port_count; i++) {
   6223         /* get ipmc ptr and delete all interfaces associated with it */
   6224         queue_id = q_array[i];
   6225         if (queue_id == q_array[i+1]) {
   6226             continue;
   6227         }
   6228         if (SOC_IS_KATANA2(unit)) {
   6229             ptr_type = (q_repl_ptr[queue_id] >> 13) & 0x3;
   6230             ipmc_ptr = q_repl_ptr[queue_id] & 0x1fff;
   6231         } else {
   6232             ptr_type = (q_repl_ptr[queue_id] >> 14) & 1;
   6233             ipmc_ptr = q_repl_ptr[queue_id] & 0x3fff;
   6234         }
   6235 
   6236         if (ptr_type == 0) {
   6237 #ifdef BCM_KATANA2_SUPPORT
   6238             if (SOC_IS_KATANA2 (unit)) {
   6239                 rv = _bcm_kt2_ipmc_egress_intf_delete_all(unit, ipmc_id,
   6240                                                           ipmc_ptr);
   6241             } else
   6242 #endif /* BCM_KATANA2_SUPPORT */
   6243             {
   6244                 rv = _bcm_kt_ipmc_egress_intf_delete_all(unit, ipmc_id,
   6245                                                          ipmc_ptr);
   6246             }
   6247             if (BCM_FAILURE(rv)) {
   6248                 goto intf_add_done;
   6249             }
   6250         }
   6251         q_repl_ptr[queue_id] = 0; 
   6252     }
   6253     alloc_size = SHR_BITALLOCSIZE(q_max);
   6254     sal_memset(q_vec, 0, alloc_size);
   6255     *q_count_decreased = q_num;
   6256     q_num = 0;
   6257     rv = _bcm_kt_ipmc_extq_list_update_all(unit, ipmc_id, q_num,
   6258             q_vec, q_repl_ptr);
   6259     if (BCM_FAILURE(rv)) {
   6260         goto intf_add_done;
   6261     }
   6262     for (i = 0; i < port_count; i++) {
   6263         sw_index = q_array[i];
   6264         rv = _bcm_kt_hw_to_sw_queue(unit, &sw_index, &port);
   6265         if (BCM_FAILURE(rv)) {
   6266             goto intf_add_done;
   6267         }
   6268 #ifdef BCM_KATANA2_SUPPORT
   6269         if (SOC_IS_KATANA2(unit) && !SOC_IS_SABER2(unit)) {
   6270             rv = _bcm_kt2_intf_ref_cnt_decrement(unit, sw_index, 1);
   6271             if (BCM_FAILURE(rv)) {
   6272                 goto intf_add_done;
   6273             }
   6274         } else
   6275 #endif
   6276         {
   6277             rv = _bcm_kt_intf_ref_cnt_decrement(unit, sw_index, 1);
   6278             if (BCM_FAILURE(rv)) {
   6279                 goto intf_add_done;
   6280             }
   6281         }
   6282     }
   6283 intf_add_done:
   6284     IPMC_REPL_UNLOCK(unit);
   6285     if (q_repl_ptr != NULL) {
   6286         sal_free(q_repl_ptr);
   6287     }
   6288     if (q_vec != NULL) {
   6289         sal_free(q_vec);
   6290     }
   6291     return rv;
   6292 }
   6293 #endif
   6294 
   6295 /*
   6296  * Function:
   6297  *    bcm_kt_ipmc_subscriber_egress_intf_delete
   6298  * Purpose:
   6299  *    Assign set of egress interfaces to port's replication list for chosen
   6300  *    IPMC group.
   6301  * Parameters:
   6302  *    unit     - StrataSwitch PCI device unit number.
   6303  *    ipmc_id  - The index number.
   6304  *    port     - port to list.
   6305  *    subscriber_queue - subscriber's gport
   6306  *    encap_id - (IN) List of interface numbers.
   6307  *      check_port - (IN) If if_array consists of L3 interfaces, this parameter
   6308  *                        controls whether to check the given port is a member
   6309  *                        in each L3 interface's VLAN. This check should be
   6310  *                        disabled when not needed, in order to improve
   6311  *                        performance.
   6312  * Returns:
   6313  *    BCM_E_XXX
   6314  */
   6315 int
   6316 _bcm_kt_ipmc_subscriber_egress_intf_delete(int unit, int ipmc_id,
   6317                                            bcm_port_t port, 
   6318                                            int id,
   6319                                            bcm_gport_t subscriber_queue,
   6320                                            int *queue_count,
   6321                                            int *q_count_decreased)
   6322 {
   6323     int     q_num = 0;
   6324     int     alloc_size;
   6325     int     rv = BCM_E_NONE;
   6326     int     queue_id;
   6327     int     q_found = 0;
   6328     int     q_max, ptr_type = 0;
   6329     int     ipmc_ptr;
   6330     int     new_ipmc_ptr = 0;
   6331     int     last_ipmc_flag = 0;
   6332     uint32     *q_repl_ptr = NULL;
   6333     SHR_BITDCL *q_vec = NULL;
   6334     int     nh_index = 0;
   6335     int     partition = TD_EGR_L3_NEXT_HOP_OFFSET;
   6336     int     port_qcount_decreased = 0;
   6337     uint16  sw_index = 0;
   6338 
   6339     REPL_PORT_CHECK(unit, port);
   6340     BCM_IF_ERROR_RETURN(_bcm_kt_init_check(unit, ipmc_id));
   6341 
   6342     /* Hardware decides the replication on L3 interfaces or
   6343      * Next hop based on L3_REPL_PTRX 13th bit
   6344      * < 8k replication on Nexthop
   6345      * > 8k replication on L3 interfaces
   6346      */
   6347     partition = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
   6348  
   6349     q_max = IPMC_EXTQ_TOTAL(unit);
   6350     alloc_size = q_max * sizeof(int);
   6351     q_repl_ptr = sal_alloc(alloc_size, "IPMC repl interface array");
   6352     if (q_repl_ptr == NULL) {
   6353         return BCM_E_MEMORY;
   6354     }
   6355     sal_memset(q_repl_ptr, 0, alloc_size);
   6356 
   6357     alloc_size = SHR_BITALLOCSIZE(IPMC_EXTQ_TOTAL(unit));
   6358     q_vec = sal_alloc(alloc_size, "IPMC extq replication vector");
   6359     if (q_vec == NULL) {
   6360         sal_free(q_repl_ptr);
   6361         return BCM_E_MEMORY;
   6362     }
   6363     sal_memset(q_vec, 0, alloc_size);
   6364 
   6365     IPMC_REPL_LOCK(unit);    
   6366 
   6367     if ((rv = _bcm_kt_ipmc_subscriber_queues_get(unit, ipmc_id, q_vec, 
   6368                             q_repl_ptr, &q_num)) < 0 ) {
   6369         goto intf_add_done;
   6370     }
   6371     
   6372     if (q_num > q_max) {
   6373         rv = BCM_E_PARAM;
   6374         goto intf_add_done;
   6375     }
   6376     if (BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(subscriber_queue)) {
   6377         sw_index = BCM_GPORT_UCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(
   6378                       subscriber_queue);
   6379     } else if (BCM_GPORT_IS_MCAST_SUBSCRIBER_QUEUE_GROUP(subscriber_queue)) {
   6380         sw_index = BCM_GPORT_MCAST_SUBSCRIBER_QUEUE_GROUP_QID_GET(
   6381                       subscriber_queue);
   6382     } else if (BCM_GPORT_IS_UCAST_QUEUE_GROUP(subscriber_queue)) {
   6383         sw_index = BCM_GPORT_UCAST_QUEUE_GROUP_QID_GET(subscriber_queue);
   6384     } else {
   6385         rv = BCM_E_PARAM;
   6386         goto intf_add_done;
   6387     }
   6388     if (sw_index >= IPMC_EXTQ_TOTAL(unit)) {
   6389         rv = BCM_E_PARAM;
   6390         goto intf_add_done;
   6391     }
   6392 #ifdef BCM_KATANA2_SUPPORT
   6393     if (SOC_IS_KATANA2(unit)) {
   6394         if ((rv = _bcm_kt2_cosq_index_resolve(unit,  subscriber_queue, 0,
   6395                                  _BCM_KT2_COSQ_INDEX_STYLE_QUEUE_REPLICATION,
   6396                                  NULL,  &queue_id, NULL)) < 0) {
   6397             if (rv == BCM_E_NOT_FOUND) {
   6398                 queue_id = sw_to_hw_queue[unit][sw_index] >> 8;
   6399             } else {
   6400                 goto intf_add_done;
   6401             }
   6402         }
   6403 
   6404     } else
   6405 #endif /* BCM_KATANA2_SUPPORT */
   6406     {
   6407         if ((rv = _bcm_kt_cosq_index_resolve(unit,  subscriber_queue, 0,
   6408                                 _BCM_KT_COSQ_INDEX_STYLE_QUEUE_REPLICATION,
   6409                                 NULL,  &queue_id, NULL)) < 0) {
   6410             if (rv == BCM_E_NOT_FOUND) {
   6411                 queue_id = sw_to_hw_queue[unit][sw_index] >> 8;
   6412             } else {
   6413                 goto intf_add_done;
   6414             }
   6415         }
   6416     }
   6417 
   6418     if (SHR_BITGET(q_vec, queue_id)) {
   6419         q_found = 1;
   6420         if (SOC_IS_KATANA2(unit)) {
   6421             ptr_type = (q_repl_ptr[queue_id] >> 13) & 0x3; 
   6422             ipmc_ptr = q_repl_ptr[queue_id] & 0x1fff;
   6423         } else {
   6424             ptr_type = (q_repl_ptr[queue_id] >> 14) & 1;
   6425             ipmc_ptr = q_repl_ptr[queue_id] & 0x3fff;
   6426         } 
   6427     }
   6428 
   6429     if (q_found == 0) {
   6430         rv = BCM_E_NOT_FOUND;
   6431         goto intf_add_done;
   6432     }
   6433     
   6434     if (ptr_type == 0) {
   6435         /* already ipmc ptr */        
   6436 #ifdef BCM_KATANA2_SUPPORT
   6437         if (SOC_IS_KATANA2(unit)) {
   6438             _bcm_kt2_ipmc_egress_intf_delete(unit, ipmc_id, port, ipmc_ptr, id, 
   6439                                              &new_ipmc_ptr, &last_ipmc_flag);
   6440         } 
   6441 #endif
   6442         if (SOC_IS_KATANA(unit)) {
   6443             _bcm_kt_ipmc_egress_intf_delete(unit, ipmc_id, port, ipmc_ptr, id, 
   6444                                             &new_ipmc_ptr, &last_ipmc_flag);         
   6445         }
   6446         if (new_ipmc_ptr != 0) {
   6447             q_repl_ptr[queue_id] = (q_repl_ptr[queue_id] & (~0 << 14)) +
   6448                                     new_ipmc_ptr;
   6449             q_repl_ptr[queue_id] |= (last_ipmc_flag << 17);
   6450         } else { 
   6451             /* this is the last entry */
   6452             q_repl_ptr[queue_id] = 0;
   6453             SHR_BITCLR(q_vec, queue_id);
   6454             q_num--;
   6455             port_qcount_decreased = 1;
   6456         }
   6457 
   6458     } else {
   6459         /* its a l3 or nh entry */
   6460         if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, id)) {
   6461             /* L3 interface */
   6462             nh_index = id + partition;
   6463         } else {
   6464             /* Next hop entry */
   6465             nh_index = id - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   6466         }
   6467         if (nh_index != ipmc_ptr) {
   6468             /* encap id does not exist */
   6469             rv = BCM_E_PARAM;
   6470             goto intf_add_done;
   6471         }
   6472         q_repl_ptr[queue_id] = 0;
   6473         SHR_BITCLR(q_vec, queue_id); 
   6474         q_num--;
   6475         port_qcount_decreased = 1;
   6476     }
   6477 
   6478     if ((rv = _bcm_kt_ipmc_extq_list_update(unit, ipmc_id, port, q_num, 
   6479                                             q_vec, q_repl_ptr)) < 0 ) {
   6480         goto intf_add_done;
   6481     }
   6482 #ifdef BCM_KATANA2_SUPPORT
   6483     if (SOC_IS_KATANA2(unit) && !SOC_IS_SABER2(unit)) {
   6484         rv = _bcm_kt2_intf_ref_cnt_decrement(unit, sw_index, 1);
   6485     } else
   6486 #endif
   6487     {
   6488         rv = _bcm_kt_intf_ref_cnt_decrement(unit, sw_index, 1);
   6489     }
   6490 
   6491     if (queue_count != NULL) {
   6492         *queue_count = q_num;
   6493     }
   6494 
   6495     if (q_count_decreased != NULL) {
   6496         *q_count_decreased = port_qcount_decreased;
   6497     }
   6498 
   6499 intf_add_done:
   6500     IPMC_REPL_UNLOCK(unit);
   6501     if (q_repl_ptr != NULL) {
   6502         sal_free(q_repl_ptr);
   6503     }
   6504     if (q_vec != NULL) {
   6505         sal_free(q_vec);
   6506     }
   6507     return rv;
   6508 }
   6509 
   6510 /*
   6511  * Function:
   6512  *      _bcm_kt_hw_to_sw_queue
   6513  * Purpose:
   6514  *      Finds sw queue index for the corresponding hw queue
   6515  * Parameters:
   6516  *      unit        - (IN) StrataSwitch unit #
   6517  *      queue_array - (IN/OUT) Queue array pointer
   6518  *      port        - (OUT) Pointer to Port
   6519  * Returns:
   6520  *      BCM_E_xxx
   6521  */
   6522 int
   6523 _bcm_kt_hw_to_sw_queue(int unit, int *queue_array, bcm_port_t *port)
   6524 {
   6525     int index;
   6526     for (index = 0; index < IPMC_EXTQ_TOTAL(unit); index++) {
   6527          if ((sw_to_hw_queue[unit][index] >> 8) == *queue_array) {
   6528              *queue_array = index;
   6529              *port = sw_to_hw_queue[unit][index] & 0xff;
   6530              return BCM_E_NONE;
   6531          }
   6532     }
   6533     *queue_array = -1;
   6534     *port = -1;
   6535     return BCM_E_NOT_FOUND;
   6536 }
   6537 
   6538 #endif
   6539 
   6540 #ifndef BCM_SW_STATE_DUMP_DISABLE
   6541 #ifdef BCM_KATANA2_SUPPORT
   6542 /*
   6543  * Function:
   6544  *     bcm_kt2_ipmc_subscriber_sw_dump
   6545  * Purpose:
   6546  *     Displays IPMC Subscriber replication information 
   6547  *     maintained by software.
   6548  * Parameters:
   6549  *     unit - Device unit number
   6550  * Returns:
   6551  *     None
   6552  */
   6553 void 
   6554 bcm_kt2_ipmc_subscriber_sw_dump(int unit)
   6555 {
   6556     int                   i, j;
   6557     uint32                *bitmap;
   6558     _bcm_repl_list_info_t *rli_start, *rli_current;
   6559     _kt_repl_queue_info_t  *group_info;
   6560     _kt_extq_repl_info_t   *extq_info;
   6561 
   6562 
   6563     /*
   6564      * _kt_extq_repl_info
   6565      */
   6566 
   6567     LOG_CLI((BSL_META_U(unit,
   6568                         "  IPMC EXTQ REPL Info -\n")));
   6569     extq_info = _kt_extq_repl_info[unit];
   6570     LOG_CLI((BSL_META_U(unit,
   6571                         "    IPMC Size    : %d\n"), extq_info->ipmc_size));
   6572     LOG_CLI((BSL_META_U(unit,
   6573                         "    Queue Num    : %d\n"), extq_info->queue_num));
   6574     LOG_CLI((BSL_META_U(unit,
   6575                         "    Extq total   : %d\n"), extq_info->extq_list_total));
   6576 
   6577     LOG_CLI((BSL_META_U(unit,
   6578                         "    Bitmap (index:value-hex) :")));
   6579     if (extq_info->bitmap_entries_used != NULL) {
   6580         bitmap =  extq_info->bitmap_entries_used;
   6581         for (i = 0, j = 0;
   6582              i < _SHR_BITDCLSIZE(extq_info->extq_list_total); i++) {
   6583             /* If zero, skip print */
   6584             if (bitmap[i] == 0) {
   6585                 continue;
   6586             }
   6587             if (!(j % 4)) {
   6588                 LOG_CLI((BSL_META_U(unit,
   6589                                     "\n    ")));
   6590             }
   6591             LOG_CLI((BSL_META_U(unit,
   6592                                 "  %5d:%8.8x"), i, bitmap[i]));
   6593             j++;
   6594         }
   6595     }
   6596     LOG_CLI((BSL_META_U(unit,
   6597                         "\n")));
   6598 
   6599     group_info = extq_info->mcgroup_info;
   6600     for (i = 0, j = 0; i < extq_info->ipmc_size; i++) {
   6601         /* If zero, skip print */
   6602         if (group_info->queue_count[i] == 0) {
   6603             continue;
   6604         }
   6605         if ((j > 0) && !(j % 4)) {
   6606             LOG_CLI((BSL_META_U(unit,
   6607                                 "\n         ")));
   6608         }
   6609         LOG_CLI((BSL_META_U(unit,
   6610                             " %5d:%-4d"), i, group_info->queue_count[i]));
   6611         j++;
   6612     }
   6613     LOG_CLI((BSL_META_U(unit,
   6614                         "\n")));
   6615    
   6616     rli_start = IPMC_EXTQ_REPL_LIST_INFO(unit);
   6617     LOG_CLI((BSL_META_U(unit,
   6618                         "    List Info    -\n")));
   6619     for (rli_current = rli_start; rli_current != NULL;
   6620          rli_current = rli_current->next) {
   6621         LOG_CLI((BSL_META_U(unit,
   6622                             "    Hash:  0x%08x\n"), rli_current->hash));
   6623         LOG_CLI((BSL_META_U(unit,
   6624                             "    Index: %4d\n"), rli_current->index));
   6625         LOG_CLI((BSL_META_U(unit,
   6626                             "    Size:  %4d\n"), rli_current->list_size));
   6627         LOG_CLI((BSL_META_U(unit,
   6628                             "    Refs:  %4d\n"), rli_current->refcount));
   6629     }
   6630 }
   6631 
   6632 #endif
   6633 /*
   6634  * Function:
   6635  *     _bcm_tr2_ipmc_repl_sw_dump
   6636  * Purpose:
   6637  *     Displays IPMC replication information maintained by software.
   6638  * Parameters:
   6639  *     unit - Device unit number
   6640  * Returns:
   6641  *     None
   6642  */
   6643 void
   6644 _bcm_tr2_ipmc_repl_sw_dump(int unit)
   6645 {
   6646     int                   i, j, port;
   6647     _tr2_repl_info_t       *repl_info;
   6648     uint32                *bitmap;
   6649     _tr2_repl_port_info_t  *port_info;
   6650     _bcm_repl_list_info_t *rli_start, *rli_current;
   6651 #ifdef BCM_KATANA_SUPPORT
   6652     _kt_repl_queue_info_t  *group_info;
   6653     _kt_extq_repl_info_t   *extq_info;
   6654 #endif
   6655     /*
   6656      * _tr2_repl_info
   6657      */
   6658 
   6659     LOG_CLI((BSL_META_U(unit,
   6660                         "  IPMC REPL Info -\n")));
   6661     repl_info = _tr2_repl_info[unit];
   6662     if (repl_info != NULL) {
   6663         LOG_CLI((BSL_META_U(unit,
   6664                             "    IPMC Size    : %d\n"), repl_info->ipmc_size));
   6665         LOG_CLI((BSL_META_U(unit,
   6666                             "    Intf Size    : %d\n"), repl_info->intf_num));
   6667         LOG_CLI((BSL_META_U(unit,
   6668                             "    Vlan total   : %d\n"), repl_info->ipmc_vlan_total));
   6669 
   6670         LOG_CLI((BSL_META_U(unit,
   6671                             "    Bitmap (index:value-hex) :")));
   6672         if (repl_info->bitmap_entries_used != NULL) {
   6673             bitmap =  repl_info->bitmap_entries_used;
   6674             for (i = 0, j = 0;
   6675                  i < _SHR_BITDCLSIZE(repl_info->ipmc_vlan_total); i++) {
   6676                 /* If zero, skip print */
   6677                 if (bitmap[i] == 0) {
   6678                     continue;
   6679                 }
   6680                 if (!(j % 4)) {
   6681                     LOG_CLI((BSL_META_U(unit,
   6682                                         "\n    ")));
   6683                 }
   6684                 LOG_CLI((BSL_META_U(unit,
   6685                                     "  %5d:%8.8x"), i, bitmap[i]));
   6686                 j++;
   6687             }
   6688         }
   6689         LOG_CLI((BSL_META_U(unit,
   6690                             "\n")));
   6691 
   6692         LOG_CLI((BSL_META_U(unit,
   6693                             "    Port Info    -\n")));
   6694         LOG_CLI((BSL_META_U(unit,
   6695                             "    port (index:vlan-count) :\n")));
   6696         for (port = 0; port < SOC_MAX_NUM_PORTS; port++) {
   6697             port_info = repl_info->port_info[port];
   6698             LOG_CLI((BSL_META_U(unit,
   6699                                 "    %3d -"), port));
   6700             if (port_info == NULL) {
   6701                 LOG_CLI((BSL_META_U(unit,
   6702                                     " null\n")));
   6703                 continue;
   6704             }
   6705             for (i = 0, j = 0; i < repl_info->ipmc_size; i++) {
   6706                 /* If zero, skip print */
   6707                 if (port_info->vlan_count[i] == 0) {
   6708                     continue;
   6709                 }
   6710                 if ((j > 0) && !(j % 4)) {
   6711                     LOG_CLI((BSL_META_U(unit,
   6712                                         "\n         ")));
   6713                 }
   6714                 LOG_CLI((BSL_META_U(unit,
   6715                                     " %5d:%-4d"), i, port_info->vlan_count[i]));
   6716                 j++;
   6717             }
   6718             LOG_CLI((BSL_META_U(unit,
   6719                                 "\n")));
   6720         }
   6721 
   6722         
   6723         rli_start = IPMC_REPL_LIST_INFO(unit);
   6724         LOG_CLI((BSL_META_U(unit,
   6725                             "    List Info    -\n")));
   6726         for (rli_current = rli_start; rli_current != NULL;
   6727              rli_current = rli_current->next) {
   6728             LOG_CLI((BSL_META_U(unit,
   6729                                 "    Hash:  0x%08x\n"), rli_current->hash));
   6730             LOG_CLI((BSL_META_U(unit,
   6731                                 "    Index: %4d\n"), rli_current->index));
   6732             LOG_CLI((BSL_META_U(unit,
   6733                                 "    Size:  %4d\n"), rli_current->list_size));
   6734             LOG_CLI((BSL_META_U(unit,
   6735                                 "    Refs:  %4d\n"), rli_current->refcount));
   6736         }
   6737     }
   6738 
   6739 #ifdef BCM_KATANA_SUPPORT
   6740     if (SOC_IS_KATANAX(unit)) {
   6741         /*
   6742          * _kt_extq_repl_info
   6743          */
   6744 
   6745         LOG_CLI((BSL_META_U(unit,
   6746                             "  IPMC EXTQ REPL Info -\n")));
   6747         extq_info = _kt_extq_repl_info[unit];
   6748         if (repl_info != NULL) {
   6749             LOG_CLI((BSL_META_U(unit,
   6750                                 "    IPMC Size    : %d\n"), extq_info->ipmc_size));
   6751             LOG_CLI((BSL_META_U(unit,
   6752                                 "    Queue Num    : %d\n"), extq_info->queue_num));
   6753             LOG_CLI((BSL_META_U(unit,
   6754                                 "    Extq total   : %d\n"), extq_info->extq_list_total));
   6755 
   6756             LOG_CLI((BSL_META_U(unit,
   6757                                 "    Bitmap (index:value-hex) :")));
   6758             if (extq_info->bitmap_entries_used != NULL) {
   6759                 bitmap =  extq_info->bitmap_entries_used;
   6760                 for (i = 0, j = 0;
   6761                      i < _SHR_BITDCLSIZE(extq_info->extq_list_total); i++) {
   6762                     /* If zero, skip print */
   6763                     if (bitmap[i] == 0) {
   6764                         continue;
   6765                     }
   6766                     if (!(j % 4)) {
   6767                         LOG_CLI((BSL_META_U(unit,
   6768                                             "\n    ")));
   6769                     }
   6770                     LOG_CLI((BSL_META_U(unit,
   6771                                         "  %5d:%8.8x"), i, bitmap[i]));
   6772                     j++;
   6773                 }
   6774             }
   6775             LOG_CLI((BSL_META_U(unit,
   6776                                 "\n")));
   6777 
   6778             group_info = extq_info->mcgroup_info;
   6779             for (i = 0, j = 0; i < extq_info->ipmc_size; i++) {
   6780                 /* If zero, skip print */
   6781                 if (group_info->queue_count[i] == 0) {
   6782                     continue;
   6783                 }
   6784                 if ((j > 0) && !(j % 4)) {
   6785                     LOG_CLI((BSL_META_U(unit,
   6786                                         "\n         ")));
   6787                 }
   6788                 LOG_CLI((BSL_META_U(unit,
   6789                                     " %5d:%-4d"), i, group_info->queue_count[i]));
   6790                 j++;
   6791             }
   6792             LOG_CLI((BSL_META_U(unit,
   6793                                 "\n")));
   6794             
   6795             rli_start = IPMC_EXTQ_REPL_LIST_INFO(unit);
   6796             LOG_CLI((BSL_META_U(unit,
   6797                                 "    List Info    -\n")));
   6798             for (rli_current = rli_start; rli_current != NULL;
   6799                  rli_current = rli_current->next) {
   6800                 LOG_CLI((BSL_META_U(unit,
   6801                                     "    Hash:  0x%08x\n"), rli_current->hash));
   6802                 LOG_CLI((BSL_META_U(unit,
   6803                                     "    Index: %4d\n"), rli_current->index));
   6804                 LOG_CLI((BSL_META_U(unit,
   6805                                     "    Size:  %4d\n"), rli_current->list_size));
   6806                 LOG_CLI((BSL_META_U(unit,
   6807                                     "    Refs:  %4d\n"), rli_current->refcount));
   6808             }
   6809         }
   6810         
   6811     }    
   6812 #endif
   6813 
   6814     return;
   6815 }
   6816 #endif /* BCM_SW_STATE_DUMP_DISABLE */
   6817 
   6818 #endif /* INCLUDE_L3 */