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


      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:     Triumph3 IPMC implementation.
      9  */
     10 
     11 #include <soc/defs.h>
     12 #include <sal/core/libc.h>
     13 #include <shared/bsl.h>
     14 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_KATANA2_SUPPORT) 
     15 #if defined(INCLUDE_L3)
     16 
     17 #include <soc/drv.h>
     18 #include <soc/mem.h>
     19 
     20 #include <bcm/error.h>
     21 #include <bcm/l3.h>
     22 #include <bcm/types.h>
     23 
     24 #include <bcm_int/esw_dispatch.h>
     25 #include <bcm_int/esw/ipmc.h>
     26 #include <bcm_int/esw/firebolt.h>
     27 
     28 #ifdef BCM_KATANA2_SUPPORT
     29 #include <bcm_int/esw/katana2.h>
     30 #include <bcm_int/esw/subport.h>
     31 #include <soc/katana2.h>
     32 #endif /* BCM_KATANA2_SUPPORT */
     33 
     34 #ifdef BCM_SABER2_SUPPORT
     35 #include <soc/saber2.h>
     36 #include <bcm_int/esw/saber2.h>
     37 #endif
     38 #if defined(BCM_METROLITE_SUPPORT)
     39 #include <soc/metrolite.h>
     40 #endif
     41 #ifdef BCM_KATANA_SUPPORT
     42 #include <bcm_int/esw/katana.h>
     43 #endif /* BCM_KATANA_SUPPORT */
     44 
     45 #ifdef BCM_TRIDENT2PLUS_SUPPORT
     46 #include <bcm_int/esw/trident2plus.h>
     47 #include <bcm_int/esw/multicast.h>
     48 #include <bcm_int/common/multicast.h>
     49 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
     50 #if defined(BCM_HGPROXY_COE_SUPPORT)
     51 #include <bcm_int/esw/xgs5.h>
     52 #endif /* BCM_HGPROXY_COE_SUPPORT */
     53 
     54 /* Structures for managing REPL_HEAD table resources */
     55 int _bcm_kt_ipmc_subscriber_queues_get(int unit, int ipmc_id,
     56                                        SHR_BITDCL *q_vec,
     57                                        uint32 *q_repl_ptrs,
     58                                        int *q_num);
     59 
     60 typedef struct _tr3_repl_head_free_block_s {
     61     int index; /* Starting index of a free block of REPL_HEAD table entries */
     62     int size;  /* Number of entries in the free block */
     63     struct _tr3_repl_head_free_block_s *next; /* Pointer to next free block */
     64 } _tr3_repl_head_free_block_t;
     65 
     66 typedef struct _tr3_repl_head_info_s {
     67     _tr3_repl_head_free_block_t **free_list_array;
     68                               /* Array of lists of free blocks */
     69     int array_size;           /* Number of lists in the array */
     70 } _tr3_repl_head_info_t;
     71 
     72 typedef struct _kt2_repl_grp_info_s {
     73    int mb_index;
     74    int lb_index;
     75    soc_mem_t mb_mem;
     76    soc_mem_t lb_mem;
     77    soc_field_t mbmp;
     78    soc_field_t lbmp;
     79 } _kt2_repl_grp_info_t;
     80 
     81 typedef struct _tr3_if_updated_s {
     82     bcm_if_t *if_array_del;   /* the interface array to be deleted */   
     83     int       if_count_del;   /* size of the interface array to be deleted */
     84     bcm_if_t *if_array_new;   /* the new interface array to be added */
     85     int       if_count_new;   /* size of the new interface array to be added */
     86 } _tr3_if_updated_t;
     87 static _tr3_repl_head_info_t *_tr3_repl_head_info[BCM_MAX_NUM_UNITS];
     88 
     89 #define REPL_HEAD_FREE_LIST(_unit_, _index_) \
     90     _tr3_repl_head_info[_unit_]->free_list_array[_index_]
     91 
     92 /* Structures for managing REPL_LIST table resources */
     93 
     94 typedef struct _tr3_repl_list_entry_info_s {
     95     SHR_BITDCL *bitmap_entries_used; /* A bitmap indicating which REPL_LIST
     96                                         entries are used */
     97     int num_entries; /* Total number of entries in REPL_LIST table */
     98 } _tr3_repl_list_entry_info_t;
     99 
    100 static _tr3_repl_list_entry_info_t \
    101            *_tr3_repl_list_entry_info[BCM_MAX_NUM_UNITS];
    102 
    103 static uint8 reserve_multicast_resources[BCM_MAX_NUM_UNITS] = {0};
    104 
    105 #define REPL_LIST_ENTRY_USED_GET(_u_, _i_) \
    106         SHR_BITGET(_tr3_repl_list_entry_info[_u_]->bitmap_entries_used, _i_)
    107 #define REPL_LIST_ENTRY_USED_SET(_u_, _i_) \
    108         SHR_BITSET(_tr3_repl_list_entry_info[_u_]->bitmap_entries_used, _i_)
    109 #define REPL_LIST_ENTRY_USED_CLR(_u_, _i_) \
    110         SHR_BITCLR(_tr3_repl_list_entry_info[_u_]->bitmap_entries_used, _i_)
    111 
    112 /* Structures containing replication info */
    113 
    114 typedef struct _tr3_repl_port_info_s {
    115     int *intf_count; /* Array of interface counts, one per replication group */
    116 } _tr3_repl_port_info_t;
    117 
    118 typedef struct _tr3_repl_info_s {
    119     int num_repl_groups; /* Number of replication groups on this device */
    120     uint32 num_intf;     /* Number of interfaces on this device */
    121     _bcm_repl_list_info_t *repl_list_info;
    122                          /* Linked list of replication lists */
    123 #if defined(BCM_ESW_SUPPORT) && (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS)
    124     _tr3_repl_port_info_t *port_info[SOC_MAX_NUM_PP_PORTS];
    125 #else
    126     _tr3_repl_port_info_t *port_info[SOC_MAX_NUM_PORTS];
    127 #endif
    128                          /* Per port replication info */
    129     int *l3_intf_next_hop_ipmc; /* Array of next hop indices, one for each
    130                             L3 interface that's added to an IPMC group */ 
    131     int *l3_intf_next_hop_trill; /* Array of next hop indices, one for each
    132                             L3 interface that's added to a Trill group */ 
    133 } _tr3_repl_info_t;
    134 
    135 static _tr3_repl_info_t *_tr3_repl_info[BCM_MAX_NUM_UNITS];
    136 
    137 #ifdef BCM_KATANA2_SUPPORT
    138 typedef struct _kt2_rep_regs_s {
    139       soc_field_t last_ptr;
    140       soc_mem_t   mem;
    141 }_kt2_rep_regs_t;
    142 
    143 _kt2_rep_regs_t kt2_rqe_rep_regs[] = { 
    144    { INVALIDf,    INVALIDm},
    145     {PORT1_LASTf, MMU_IPMC_GROUP_TBL0m},
    146     {PORT2_LASTf, MMU_IPMC_GROUP_TBL0m},
    147     {PORT3_LASTf, MMU_IPMC_GROUP_TBL0m},
    148     {PORT4_LASTf, MMU_IPMC_GROUP_TBL0m},
    149     {PORT5_LASTf, MMU_IPMC_GROUP_TBL0m},
    150     {PORT6_LASTf, MMU_IPMC_GROUP_TBL0m},
    151     {PORT7_LASTf, MMU_IPMC_GROUP_TBL0m},
    152     {PORT8_LASTf, MMU_IPMC_GROUP_TBL0m},
    153     {PORT9_LASTf, MMU_IPMC_GROUP_TBL0m},
    154     {PORT10_LASTf, MMU_IPMC_GROUP_TBL0m},
    155     {PORT11_LASTf, MMU_IPMC_GROUP_TBL0m},
    156     {PORT12_LASTf, MMU_IPMC_GROUP_TBL0m},
    157     {PORT13_LASTf, MMU_IPMC_GROUP_TBL0m},
    158     {PORT14_LASTf, MMU_IPMC_GROUP_TBL0m},
    159     {PORT15_LASTf, MMU_IPMC_GROUP_TBL0m},
    160     {PORT16_LASTf, MMU_IPMC_GROUP_TBL0m},
    161     {PORT17_LASTf, MMU_IPMC_GROUP_TBL0m},
    162     {PORT18_LASTf, MMU_IPMC_GROUP_TBL0m},
    163     {PORT19_LASTf, MMU_IPMC_GROUP_TBL0m},
    164     {PORT20_LASTf, MMU_IPMC_GROUP_TBL0m},
    165     {PORT21_LASTf, MMU_IPMC_GROUP_TBL0m},
    166     {PORT22_LASTf, MMU_IPMC_GROUP_TBL0m},
    167     {PORT23_LASTf, MMU_IPMC_GROUP_TBL0m},
    168     {PORT24_LASTf, MMU_IPMC_GROUP_TBL0m},
    169     {PORT25_LASTf, MMU_IPMC_GROUP_TBL0m},
    170     {PORT26_LASTf, MMU_IPMC_GROUP_TBL0m},
    171     {PORT27_LASTf, MMU_IPMC_GROUP_TBL0m},
    172     {PORT28_LASTf, MMU_IPMC_GROUP_TBL0m},
    173     {PORT29_LASTf, MMU_IPMC_GROUP_TBL0m},
    174     {PORT30_LASTf, MMU_IPMC_GROUP_TBL0m},
    175     {PORT31_LASTf, MMU_IPMC_GROUP_TBL0m},
    176     {PORT32_LASTf, MMU_IPMC_GROUP_TBL0m},
    177     {PORT33_LASTf, MMU_IPMC_GROUP_TBL0m},
    178     {PORT34_LASTf, MMU_IPMC_GROUP_TBL0m},
    179     {PORT35_LASTf, MMU_IPMC_GROUP_TBL1m},
    180     {PORT36_LASTf, MMU_IPMC_GROUP_TBL1m},
    181     {PORT37_LASTf, MMU_IPMC_GROUP_TBL1m},
    182     {PORT38_LASTf, MMU_IPMC_GROUP_TBL1m},
    183     {PORT39_LASTf, MMU_IPMC_GROUP_TBL1m},
    184     {PORT40_LASTf, MMU_IPMC_GROUP_TBL1m},
    185     {PORT41_LASTf, MMU_IPMC_GROUP_TBL1m},
    186     {PORT42_LASTf, MMU_IPMC_GROUP_TBL1m},
    187     {PORT43_LASTf, MMU_IPMC_GROUP_TBL1m},
    188     {PORT44_LASTf, MMU_IPMC_GROUP_TBL1m},
    189     {PORT45_LASTf, MMU_IPMC_GROUP_TBL1m},
    190     {PORT46_LASTf, MMU_IPMC_GROUP_TBL1m},
    191     {PORT47_LASTf, MMU_IPMC_GROUP_TBL1m},
    192     {PORT48_LASTf, MMU_IPMC_GROUP_TBL1m},
    193     {PORT49_LASTf, MMU_IPMC_GROUP_TBL1m},
    194     {PORT50_LASTf, MMU_IPMC_GROUP_TBL1m},
    195     {PORT51_LASTf, MMU_IPMC_GROUP_TBL1m},
    196     {PORT52_LASTf, MMU_IPMC_GROUP_TBL1m},
    197     {PORT53_LASTf, MMU_IPMC_GROUP_TBL1m},
    198     {PORT54_LASTf, MMU_IPMC_GROUP_TBL1m},
    199     {PORT55_LASTf, MMU_IPMC_GROUP_TBL1m},
    200     {PORT56_LASTf, MMU_IPMC_GROUP_TBL1m},
    201     {PORT57_LASTf, MMU_IPMC_GROUP_TBL1m},
    202     {PORT58_LASTf, MMU_IPMC_GROUP_TBL1m},
    203     {PORT59_LASTf, MMU_IPMC_GROUP_TBL1m},
    204     {PORT60_LASTf, MMU_IPMC_GROUP_TBL1m},
    205     {PORT61_LASTf, MMU_IPMC_GROUP_TBL1m},
    206     {PORT62_LASTf, MMU_IPMC_GROUP_TBL1m},
    207     {PORT63_LASTf, MMU_IPMC_GROUP_TBL1m},
    208     {PORT64_LASTf, MMU_IPMC_GROUP_TBL1m},
    209     {PORT65_LASTf, MMU_IPMC_GROUP_TBL1m},
    210     {PORT66_LASTf, MMU_IPMC_GROUP_TBL1m},
    211     {PORT67_LASTf, MMU_IPMC_GROUP_TBL1m},
    212     {PORT68_LASTf, MMU_IPMC_GROUP_TBL1m},
    213     {PORT69_LASTf, MMU_IPMC_GROUP_TBL2m},
    214     {PORT70_LASTf, MMU_IPMC_GROUP_TBL2m},
    215     {PORT71_LASTf, MMU_IPMC_GROUP_TBL2m},
    216     {PORT72_LASTf, MMU_IPMC_GROUP_TBL2m},
    217     {PORT73_LASTf, MMU_IPMC_GROUP_TBL2m},
    218     {PORT74_LASTf, MMU_IPMC_GROUP_TBL2m},
    219     {PORT75_LASTf, MMU_IPMC_GROUP_TBL2m},
    220     {PORT76_LASTf, MMU_IPMC_GROUP_TBL2m},
    221     {PORT77_LASTf, MMU_IPMC_GROUP_TBL2m},
    222     {PORT78_LASTf, MMU_IPMC_GROUP_TBL2m},
    223     {PORT79_LASTf, MMU_IPMC_GROUP_TBL2m},
    224     {PORT80_LASTf, MMU_IPMC_GROUP_TBL2m},
    225     {PORT81_LASTf, MMU_IPMC_GROUP_TBL2m},
    226     {PORT82_LASTf, MMU_IPMC_GROUP_TBL2m},
    227     {PORT83_LASTf, MMU_IPMC_GROUP_TBL2m},
    228     {PORT84_LASTf, MMU_IPMC_GROUP_TBL2m},
    229     {PORT85_LASTf, MMU_IPMC_GROUP_TBL2m},
    230     {PORT86_LASTf, MMU_IPMC_GROUP_TBL2m},
    231     {PORT87_LASTf, MMU_IPMC_GROUP_TBL2m},
    232     {PORT88_LASTf, MMU_IPMC_GROUP_TBL2m},
    233     {PORT89_LASTf, MMU_IPMC_GROUP_TBL2m},
    234     {PORT90_LASTf, MMU_IPMC_GROUP_TBL2m},
    235     {PORT91_LASTf, MMU_IPMC_GROUP_TBL2m},
    236     {PORT92_LASTf, MMU_IPMC_GROUP_TBL2m},
    237     {PORT93_LASTf, MMU_IPMC_GROUP_TBL2m},
    238     {PORT94_LASTf, MMU_IPMC_GROUP_TBL2m},
    239     {PORT95_LASTf, MMU_IPMC_GROUP_TBL2m},
    240     {PORT96_LASTf, MMU_IPMC_GROUP_TBL2m},
    241     {PORT97_LASTf, MMU_IPMC_GROUP_TBL2m},
    242     {PORT98_LASTf, MMU_IPMC_GROUP_TBL2m},
    243     {PORT99_LASTf, MMU_IPMC_GROUP_TBL2m},
    244     {PORT100_LASTf, MMU_IPMC_GROUP_TBL2m},
    245     {PORT101_LASTf, MMU_IPMC_GROUP_TBL2m},
    246     {PORT102_LASTf, MMU_IPMC_GROUP_TBL2m},
    247     {PORT103_LASTf, MMU_IPMC_GROUP_TBL3m},
    248     {PORT104_LASTf, MMU_IPMC_GROUP_TBL3m},
    249     {PORT105_LASTf, MMU_IPMC_GROUP_TBL3m},
    250     {PORT106_LASTf, MMU_IPMC_GROUP_TBL3m},
    251     {PORT107_LASTf, MMU_IPMC_GROUP_TBL3m},
    252     {PORT108_LASTf, MMU_IPMC_GROUP_TBL3m},
    253     {PORT109_LASTf, MMU_IPMC_GROUP_TBL3m},
    254     {PORT110_LASTf, MMU_IPMC_GROUP_TBL3m},
    255     {PORT111_LASTf, MMU_IPMC_GROUP_TBL3m},
    256     {PORT112_LASTf, MMU_IPMC_GROUP_TBL3m},
    257     {PORT113_LASTf, MMU_IPMC_GROUP_TBL3m},
    258     {PORT114_LASTf, MMU_IPMC_GROUP_TBL3m},
    259     {PORT115_LASTf, MMU_IPMC_GROUP_TBL3m},
    260     {PORT116_LASTf, MMU_IPMC_GROUP_TBL3m},
    261     {PORT117_LASTf, MMU_IPMC_GROUP_TBL3m},
    262     {PORT118_LASTf, MMU_IPMC_GROUP_TBL3m},
    263     {PORT119_LASTf, MMU_IPMC_GROUP_TBL3m},
    264     {PORT120_LASTf, MMU_IPMC_GROUP_TBL3m},
    265     {PORT121_LASTf, MMU_IPMC_GROUP_TBL3m},
    266     {PORT122_LASTf, MMU_IPMC_GROUP_TBL3m},
    267     {PORT123_LASTf, MMU_IPMC_GROUP_TBL3m},
    268     {PORT124_LASTf, MMU_IPMC_GROUP_TBL3m},
    269     {PORT125_LASTf, MMU_IPMC_GROUP_TBL3m},
    270     {PORT126_LASTf, MMU_IPMC_GROUP_TBL3m},
    271     {PORT127_LASTf, MMU_IPMC_GROUP_TBL3m},
    272     {PORT128_LASTf, MMU_IPMC_GROUP_TBL3m},
    273     {PORT129_LASTf, MMU_IPMC_GROUP_TBL3m},
    274     {PORT130_LASTf, MMU_IPMC_GROUP_TBL3m},
    275     {PORT131_LASTf, MMU_IPMC_GROUP_TBL3m},
    276     {PORT132_LASTf, MMU_IPMC_GROUP_TBL3m},
    277     {PORT133_LASTf, MMU_IPMC_GROUP_TBL3m},
    278     {PORT134_LASTf, MMU_IPMC_GROUP_TBL3m},
    279     {PORT135_LASTf, MMU_IPMC_GROUP_TBL3m},
    280     {PORT136_LASTf, MMU_IPMC_GROUP_TBL3m},
    281     {PORT137_LASTf, MMU_IPMC_GROUP_TBL4m},
    282     {PORT138_LASTf, MMU_IPMC_GROUP_TBL4m},
    283     {PORT139_LASTf, MMU_IPMC_GROUP_TBL4m},
    284     {PORT140_LASTf, MMU_IPMC_GROUP_TBL4m},
    285     {PORT141_LASTf, MMU_IPMC_GROUP_TBL4m},
    286     {PORT142_LASTf, MMU_IPMC_GROUP_TBL4m},
    287     {PORT143_LASTf, MMU_IPMC_GROUP_TBL4m},
    288     {PORT144_LASTf, MMU_IPMC_GROUP_TBL4m},
    289     {PORT145_LASTf, MMU_IPMC_GROUP_TBL4m},
    290     {PORT146_LASTf, MMU_IPMC_GROUP_TBL4m},
    291     {PORT147_LASTf, MMU_IPMC_GROUP_TBL4m},
    292     {PORT148_LASTf, MMU_IPMC_GROUP_TBL4m},
    293     {PORT149_LASTf, MMU_IPMC_GROUP_TBL4m},
    294     {PORT150_LASTf, MMU_IPMC_GROUP_TBL4m},
    295     {PORT151_LASTf, MMU_IPMC_GROUP_TBL4m},
    296     {PORT152_LASTf, MMU_IPMC_GROUP_TBL4m},
    297     {PORT153_LASTf, MMU_IPMC_GROUP_TBL4m},
    298     {PORT154_LASTf, MMU_IPMC_GROUP_TBL4m},
    299     {PORT155_LASTf, MMU_IPMC_GROUP_TBL4m},
    300     {PORT156_LASTf, MMU_IPMC_GROUP_TBL4m},
    301     {PORT157_LASTf, MMU_IPMC_GROUP_TBL4m},
    302     {PORT158_LASTf, MMU_IPMC_GROUP_TBL4m},
    303     {PORT159_LASTf, MMU_IPMC_GROUP_TBL4m},
    304     {PORT160_LASTf, MMU_IPMC_GROUP_TBL4m},
    305     {PORT161_LASTf, MMU_IPMC_GROUP_TBL4m},
    306     {PORT162_LASTf, MMU_IPMC_GROUP_TBL4m},
    307     {PORT163_LASTf, MMU_IPMC_GROUP_TBL4m},
    308     {PORT164_LASTf, MMU_IPMC_GROUP_TBL4m},
    309     {PORT165_LASTf, MMU_IPMC_GROUP_TBL4m},
    310     {PORT166_LASTf, MMU_IPMC_GROUP_TBL4m},
    311     {PORT167_LASTf, MMU_IPMC_GROUP_TBL4m},
    312     {PORT168_LASTf, MMU_IPMC_GROUP_TBL4m},
    313     {PORT169_LASTf, MMU_IPMC_GROUP_TBL4m},
    314 };
    315 #endif 
    316 
    317 #ifdef BCM_SABER2_SUPPORT
    318 _kt2_rep_regs_t sb2_rqe_rep_regs[] = { 
    319    { INVALIDf,    INVALIDm},
    320     {PORT1_LASTf, MMU_IPMC_GROUP_TBLm},
    321     {PORT2_LASTf, MMU_IPMC_GROUP_TBLm},
    322     {PORT3_LASTf, MMU_IPMC_GROUP_TBLm},
    323     {PORT4_LASTf, MMU_IPMC_GROUP_TBLm},
    324     {PORT5_LASTf, MMU_IPMC_GROUP_TBLm},
    325     {PORT6_LASTf, MMU_IPMC_GROUP_TBLm},
    326     {PORT7_LASTf, MMU_IPMC_GROUP_TBLm},
    327     {PORT8_LASTf, MMU_IPMC_GROUP_TBLm},
    328     {PORT9_LASTf, MMU_IPMC_GROUP_TBLm},
    329     {PORT10_LASTf, MMU_IPMC_GROUP_TBLm},
    330     {PORT11_LASTf, MMU_IPMC_GROUP_TBLm},
    331     {PORT12_LASTf, MMU_IPMC_GROUP_TBLm},
    332     {PORT13_LASTf, MMU_IPMC_GROUP_TBLm},
    333     {PORT14_LASTf, MMU_IPMC_GROUP_TBLm},
    334     {PORT15_LASTf, MMU_IPMC_GROUP_TBLm},
    335     {PORT16_LASTf, MMU_IPMC_GROUP_TBLm},
    336     {PORT17_LASTf, MMU_IPMC_GROUP_TBLm},
    337     {PORT18_LASTf, MMU_IPMC_GROUP_TBLm},
    338     {PORT19_LASTf, MMU_IPMC_GROUP_TBLm},
    339     {PORT20_LASTf, MMU_IPMC_GROUP_TBLm},
    340     {PORT21_LASTf, MMU_IPMC_GROUP_TBLm},
    341     {PORT22_LASTf, MMU_IPMC_GROUP_TBLm},
    342     {PORT23_LASTf, MMU_IPMC_GROUP_TBLm},
    343     {PORT24_LASTf, MMU_IPMC_GROUP_TBLm},
    344     {PORT25_LASTf, MMU_IPMC_GROUP_TBLm},
    345     {PORT26_LASTf, MMU_IPMC_GROUP_TBLm},
    346     {PORT27_LASTf, MMU_IPMC_GROUP_TBLm},
    347     {PORT28_LASTf, MMU_IPMC_GROUP_TBLm},
    348     {PORT29_LASTf, MMU_IPMC_GROUP_TBLm},
    349     {PORT30_LASTf, MMU_IPMC_GROUP_TBLm},
    350     {PORT31_LASTf, MMU_IPMC_GROUP_TBLm},
    351     {PORT32_LASTf, MMU_IPMC_GROUP_TBLm},
    352     {PORT33_LASTf, MMU_IPMC_GROUP_TBLm},
    353     {PORT34_LASTf, MMU_IPMC_GROUP_TBLm},
    354     {PORT35_LASTf, MMU_IPMC_GROUP_TBLm},
    355     {PORT36_LASTf, MMU_IPMC_GROUP_TBLm},
    356     {PORT37_LASTf, MMU_IPMC_GROUP_TBLm},
    357     {PORT38_LASTf, MMU_IPMC_GROUP_TBLm},
    358     {PORT39_LASTf, MMU_IPMC_GROUP_TBLm},
    359     {PORT40_LASTf, MMU_IPMC_GROUP_TBLm},
    360     {PORT41_LASTf, MMU_IPMC_GROUP_TBLm},
    361     {PORT42_LASTf, MMU_IPMC_GROUP_TBLm},
    362     {PORT43_LASTf, MMU_IPMC_GROUP_TBLm},
    363     {PORT44_LASTf, MMU_IPMC_GROUP_TBLm},
    364     {PORT45_LASTf, MMU_IPMC_GROUP_TBLm},
    365     {PORT46_LASTf, MMU_IPMC_GROUP_TBLm},
    366     {PORT47_LASTf, MMU_IPMC_GROUP_TBLm},
    367     {PORT48_LASTf, MMU_IPMC_GROUP_TBLm},
    368     {PORT49_LASTf, MMU_IPMC_GROUP_TBLm},
    369     {PORT50_LASTf, MMU_IPMC_GROUP_TBLm},
    370     {PORT51_LASTf, MMU_IPMC_GROUP_TBLm},
    371     {PORT52_LASTf, MMU_IPMC_GROUP_TBLm},
    372     {PORT53_LASTf, MMU_IPMC_GROUP_TBLm},
    373     {PORT54_LASTf, MMU_IPMC_GROUP_TBLm},
    374     {PORT55_LASTf, MMU_IPMC_GROUP_TBLm},
    375     {PORT56_LASTf, MMU_IPMC_GROUP_TBLm},
    376     {PORT57_LASTf, MMU_IPMC_GROUP_TBLm},
    377     {PORT58_LASTf, MMU_IPMC_GROUP_TBLm},
    378     {PORT59_LASTf, MMU_IPMC_GROUP_TBLm},
    379     {PORT60_LASTf, MMU_IPMC_GROUP_TBLm},
    380     {PORT61_LASTf, MMU_IPMC_GROUP_TBLm},
    381     {PORT62_LASTf, MMU_IPMC_GROUP_TBLm},
    382     {PORT63_LASTf, MMU_IPMC_GROUP_TBLm},
    383     {PORT64_LASTf, MMU_IPMC_GROUP_TBLm},
    384     {PORT65_LASTf, MMU_IPMC_GROUP_TBLm},
    385     {PORT66_LASTf, MMU_IPMC_GROUP_TBLm},
    386     {PORT67_LASTf, MMU_IPMC_GROUP_TBLm},
    387     {PORT68_LASTf, MMU_IPMC_GROUP_TBLm},
    388     {PORT69_LASTf, MMU_IPMC_GROUP_TBLm},
    389     {PORT70_LASTf, MMU_IPMC_GROUP_TBLm},
    390     {PORT71_LASTf, MMU_IPMC_GROUP_TBLm},
    391     {PORT72_LASTf, MMU_IPMC_GROUP_TBLm},
    392     {PORT73_LASTf, MMU_IPMC_GROUP_TBLm},
    393     {PORT74_LASTf, MMU_IPMC_GROUP_TBLm},
    394     {PORT75_LASTf, MMU_IPMC_GROUP_TBLm},
    395     {PORT76_LASTf, MMU_IPMC_GROUP_TBLm},
    396     {PORT77_LASTf, MMU_IPMC_GROUP_TBLm},
    397     {PORT78_LASTf, MMU_IPMC_GROUP_TBLm},
    398     {PORT79_LASTf, MMU_IPMC_GROUP_TBLm},
    399     {PORT80_LASTf, MMU_IPMC_GROUP_TBLm},
    400     {PORT81_LASTf, MMU_IPMC_GROUP_TBLm},
    401     {PORT82_LASTf, MMU_IPMC_GROUP_TBLm},
    402     {PORT83_LASTf, MMU_IPMC_GROUP_TBLm},
    403     {PORT84_LASTf, MMU_IPMC_GROUP_TBLm},
    404     {PORT85_LASTf, MMU_IPMC_GROUP_TBLm},
    405     {PORT86_LASTf, MMU_IPMC_GROUP_TBLm},
    406     {PORT87_LASTf, MMU_IPMC_GROUP_TBLm},
    407     {PORT88_LASTf, MMU_IPMC_GROUP_TBLm},
    408     {PORT89_LASTf, MMU_IPMC_GROUP_TBLm},
    409     {PORT90_LASTf, MMU_IPMC_GROUP_TBLm},
    410     {PORT91_LASTf, MMU_IPMC_GROUP_TBLm},
    411     {PORT92_LASTf, MMU_IPMC_GROUP_TBLm},
    412     {PORT93_LASTf, MMU_IPMC_GROUP_TBLm},
    413     {PORT94_LASTf, MMU_IPMC_GROUP_TBLm},
    414     {PORT95_LASTf, MMU_IPMC_GROUP_TBLm},
    415 };
    416 typedef struct _sb2_repl_queue_info_s {
    417   int32 *queue_count;           /* # VLANs the queue repl to */
    418   int32 *queue_count_int;       /* # Count of internally buffered queues */
    419   int32 *queue_count_ext;       /* # Count of externally buffered queues */
    420 }  _sb2_repl_queue_info_t;
    421 typedef struct _sb2_extq_repl_info_s {
    422    int ipmc_size;
    423    uint32 queue_num;
    424    uint32 extq_list_total;
    425    uint32 extq_repl_max;
    426    uint32 *bitmap_entries_used; /* free entries of
    427    MMU_EXT_MC_QUEUE_LIST  table */
    428    _bcm_repl_list_info_t *repl_extq_list_info;
    429    _sb2_repl_queue_info_t *mcgroup_info;
    430    _sb2_repl_queue_info_t *port_info[SOC_MAX_NUM_PP_PORTS];
    431    _bcm_ext_q_ipmc_t *ext_ipmc_list;
    432 } _sb2_extq_repl_info_t;
    433 static _sb2_extq_repl_info_t *_sb2_extq_repl_info[BCM_MAX_NUM_UNITS];
    434 
    435 
    436 
    437 
    438 #define IPMC_SB2_NHOP_ID_MIN 16384 
    439 #define IPMC_SB2_EGRESS_ID_MIN 8192 
    440 #define IPMC_SB2_REPLICATION_INDEX_MAX 32767 
    441 #define IPMC_EXTQ_ID(_u_, _id_) \
    442         if ((_id_ < 0) || (_id_ >= _sb2_extq_repl_info[_u_]->queue_num)) \
    443             { return BCM_E_PARAM; }
    444 #define IPMC_EXTQ_REPL_INIT(unit) \
    445         if (_sb2_extq_repl_info[unit] == NULL) { return BCM_E_INIT; }
    446 #define IPMC_EXTQ_LIST_TOTAL(_u_) \
    447         _sb2_extq_repl_info[_u_]->extq_list_total
    448 #define IPMC_EXTQ_REPL_MAX(_u_) \
    449         _sb2_extq_repl_info[_u_]->extq_repl_max
    450 #define IPMC_EXTQ_TOTAL(_u_) \
    451         _sb2_extq_repl_info[_u_]->queue_num
    452 #define IPMC_EXTQ_REPL_VE_USED_GET(_u_, _i_) \
    453         SHR_BITGET(_sb2_extq_repl_info[_u_]->bitmap_entries_used, _i_)
    454 #define IPMC_EXTQ_REPL_VE_USED_SET(_u_, _i_) \
    455         SHR_BITSET(_sb2_extq_repl_info[_u_]->bitmap_entries_used, _i_)
    456 #define IPMC_EXTQ_REPL_VE_USED_CLR(_u_, _i_) \
    457         SHR_BITCLR(_sb2_extq_repl_info[_u_]->bitmap_entries_used, _i_)
    458 #define IPMC_EXTQ_REPL_LIST_INFO(_u_) \
    459     _sb2_extq_repl_info[_u_]->repl_extq_list_info
    460 #define IPMC_EXTQ_GROUP_INFO(_u_) 		\
    461 	_sb2_extq_repl_info[_u_]->mcgroup_info
    462 #define IPMC_EXTQ_REPL_QUEUE_COUNT(_u_, _ipmc_id_) \
    463         _sb2_extq_repl_info[_u_]->mcgroup_info->queue_count[_ipmc_id_]
    464 #define IPMC_EXTQ_REPL_QUEUE_COUNT_INT(_u_, _ipmc_id_) \
    465         _sb2_extq_repl_info[_u_]->mcgroup_info->queue_count_int[_ipmc_id_]
    466 #define IPMC_EXTQ_REPL_QUEUE_COUNT_EXT(_u_, _ipmc_id_) \
    467         _sb2_extq_repl_info[_u_]->mcgroup_info->queue_count_ext[_ipmc_id_]
    468 #define IPMC_EXTQ_REPL_PORT_INFO(_u_, _p_) \
    469         _sb2_extq_repl_info[_u_]->port_info[_p_]
    470 #define IPMC_EXTQ_REPL_PORT_QUEUE_COUNT(_u_, _p_, _ipmc_id_) \
    471         _sb2_extq_repl_info[_u_]->port_info[_p_]->queue_count[_ipmc_id_]
    472 
    473 int
    474 _bcm_sb2_ipmc_subscriber_qvec_get(int unit, int ipmc_id, 
    475                                   SHR_BITDCL *q_vec);
    476 int
    477 _bcm_sb2_ipmc_subscriber_add_queue_node(int unit, int ipmc_id, int queue_id,  
    478                                     _bcm_ext_repl_q_list_t *queue_node) ;
    479 #endif
    480 int
    481 bcm_tr3_ipmc_repl_detach(int unit);
    482 #define REPL_LOCK(_u_)                         \
    483     {                                          \
    484         soc_mem_lock(_u_, MMU_REPL_LIST_TBLm); \
    485     }
    486 #define REPL_UNLOCK(_u_)                         \
    487     {                                            \
    488         soc_mem_unlock(_u_, MMU_REPL_LIST_TBLm); \
    489     }
    490 
    491 #define REPL_INIT(unit) \
    492         if (_tr3_repl_info[unit] == NULL) { return BCM_E_INIT; }
    493 
    494 #define REPL_GROUP_ID(_u_, _id_) \
    495         if ((_id_ < 0) || (_id_ >= _tr3_repl_info[_u_]->num_repl_groups)) \
    496             { return BCM_E_PARAM; }
    497 
    498 #define REPL_INTF_TOTAL(_u_) _tr3_repl_info[_u_]->num_intf
    499 
    500 #define REPL_LIST_INFO(_u_) _tr3_repl_info[_u_]->repl_list_info
    501 
    502 #define REPL_PORT_GROUP_INTF_COUNT(_u_, _p_, _group_id_) \
    503     _tr3_repl_info[_u_]->port_info[_p_]->intf_count[_group_id_]
    504 
    505 #define REPL_L3_INTF_NEXT_HOP_IPMC(_u_, _intf_) \
    506     _tr3_repl_info[_u_]->l3_intf_next_hop_ipmc[_intf_]
    507 #define REPL_L3_INTF_NEXT_HOP_TRILL(_u_, _intf_) \
    508     _tr3_repl_info[_u_]->l3_intf_next_hop_trill[_intf_]
    509 
    510 #if defined(BCM_KATANA2_SUPPORT)
    511 #define REPL_PORT_CHECK(unit, port) \
    512     { \
    513         if (SOC_IS_KATANA2(unit)) { \
    514             if (!IS_PORT(unit, port) && \
    515                 !IS_AXP_PORT(unit, port) && \
    516                 !(port >= SOC_INFO(unit).pp_port_index_min) && \
    517                 !(port <= SOC_INFO(unit).pp_port_index_max)) { \
    518                 return BCM_E_PARAM; \
    519             } \
    520         }  else { \
    521             if (!IS_PORT(unit, port) && !IS_AXP_PORT(unit, port)) { \
    522                 return BCM_E_PARAM; \
    523             } \
    524         } \
    525     }
    526 #else
    527 #define REPL_PORT_CHECK(unit, port) \
    528     { \
    529         if (!IS_PORT(unit, port) && !IS_AXP_PORT(unit, port)) { \
    530             return BCM_E_PARAM; \
    531         } \
    532     }
    533 #endif
    534 
    535 #define _BCM_QOS_MAP_TYPE_MASK                  0x3ff
    536 #define _BCM_QOS_MAP_SHIFT                      10
    537 #define _BCM_QOS_MAP_TYPE_RQE_QUEUE_OFFSET_MAP  7
    538 
    539 #define REPL_NH_INDEX_UNALLOCATED -1
    540 #define REPL_NH_INDEX_L3_EGRESS_ALLOCATED -2
    541 
    542 /* --------------------------------------------------------------
    543  * The following set of routines manage REPL_HEAD table resource.
    544  * --------------------------------------------------------------
    545  */
    546 
    547 /*
    548  * Function:
    549  *      _bcm_tr3_repl_head_info_deinit
    550  * Purpose:
    551  *      De-initialize replication head info.
    552  * Parameters:
    553  *      unit - (IN)SOC unit number. 
    554  * Returns:
    555  *      None
    556  */
    557 STATIC void 
    558 _bcm_tr3_repl_head_info_deinit(int unit)
    559 {
    560     int i;
    561     _tr3_repl_head_free_block_t *block_ptr;
    562     _tr3_repl_head_free_block_t *next_block_ptr;
    563 
    564     if (NULL != _tr3_repl_head_info[unit]) {
    565         if (NULL != _tr3_repl_head_info[unit]->free_list_array) {
    566             for (i = 0; i < _tr3_repl_head_info[unit]->array_size; i++) {
    567                 block_ptr = REPL_HEAD_FREE_LIST(unit, i);
    568                 while (NULL != block_ptr) {
    569                     next_block_ptr = block_ptr->next;
    570                     sal_free(block_ptr);
    571                     block_ptr = next_block_ptr;
    572                 }
    573                 REPL_HEAD_FREE_LIST(unit, i) = NULL;
    574             }
    575             sal_free(_tr3_repl_head_info[unit]->free_list_array);
    576             _tr3_repl_head_info[unit]->free_list_array = NULL;
    577             _tr3_repl_head_info[unit]->array_size = 0;
    578         }
    579         sal_free(_tr3_repl_head_info[unit]);
    580         _tr3_repl_head_info[unit] = NULL;
    581     }
    582 }
    583 
    584 /*
    585  * Function:
    586  *      _bcm_tr3_repl_head_info_init
    587  * Purpose:
    588  *      Initialize replication head info.
    589  * Parameters:
    590  *      unit - (IN)SOC unit number. 
    591  * Returns:
    592  *      BCM_E_xxx
    593  */
    594 STATIC int 
    595 _bcm_tr3_repl_head_info_init(int unit)
    596 {
    597     int max_array_index = 0;
    598     int num_of_ports = 0;
    599 
    600     if (NULL == _tr3_repl_head_info[unit]) {
    601         _tr3_repl_head_info[unit] = sal_alloc(sizeof(_tr3_repl_head_info_t),
    602                 "repl_head_info");
    603         if (NULL == _tr3_repl_head_info[unit]) {
    604             _bcm_tr3_repl_head_info_deinit(unit);
    605             return BCM_E_MEMORY;
    606         }
    607     }
    608     sal_memset(_tr3_repl_head_info[unit], 0, sizeof(_tr3_repl_head_info_t));
    609 
    610     if (NULL == _tr3_repl_head_info[unit]->free_list_array) {
    611         /* Each element of the array is a linked list of free blocks.
    612          * Array element N is a linked list of free blocks of size N.
    613          * When allocating a block of REPL_HEAD table entries, the max number
    614          * of entries needed is equal to the max number of members in a
    615          * replication group. This will also be the max index of the array. 
    616          * Of course, the REPL_HEAD table may contain bigger blocks of free
    617          * entries. Array element 0 wil be a linked list of free blocks with 
    618          * size greater than the max number of members in a replication group.
    619          */
    620         if (SOC_IS_APACHE(unit)) {
    621             max_array_index = soc_mem_field_length(unit,
    622                                   MMU_REPL_GROUP_INFO0m, PIPE_MEMBER_BMPf);
    623         } else
    624         if (soc_mem_field_valid(unit, MMU_REPL_GROUP_INFO0m, PIPE_MEMBER_BMPf) &&
    625             soc_mem_field_valid(unit, MMU_REPL_GROUP_INFO1m, PIPE_MEMBER_BMPf)) {
    626             max_array_index =
    627                 soc_mem_field_length(unit, MMU_REPL_GROUP_INFO0m,
    628                         PIPE_MEMBER_BMPf) +
    629                 soc_mem_field_length(unit, MMU_REPL_GROUP_INFO1m,
    630                         PIPE_MEMBER_BMPf);
    631                 
    632         } else if (soc_mem_field_valid(unit, MMU_REPL_GRP_TBL0m, MEMBER_BMP_PORTS_119_0f) &&
    633                 soc_mem_field_valid(unit, MMU_REPL_GRP_TBL1m, MEMBER_BMP_PORTS_169_120f)) {
    634                 max_array_index =
    635                 (soc_mem_field_length(unit, MMU_REPL_GRP_TBL0m,
    636                                       MEMBER_BMP_PORTS_119_0f) +
    637                  soc_mem_field_length(unit, MMU_REPL_GRP_TBL1m,
    638                                        MEMBER_BMP_PORTS_169_120f));
    639         } else if (soc_mem_field_valid(unit, MMU_REPL_GRP_TBL0m, MEMBER_BMP_PORTSf)){       
    640             max_array_index = soc_mem_field_length(unit, MMU_REPL_GRP_TBL0m,
    641                     MEMBER_BMP_PORTSf);
    642 	}else if (soc_mem_field_valid(unit, MMU_REPL_GRP_TBLm, MEMBER_BMP_PORTSf)){       
    643             max_array_index = soc_mem_field_length(unit, MMU_REPL_GRP_TBLm,
    644                     MEMBER_BMP_PORTSf);
    645 	}else{  
    646                 max_array_index = soc_mem_field_length(unit, MMU_REPL_GROUPm,
    647                         MEMBER_BITMAPf);
    648             }
    649         _tr3_repl_head_info[unit]->free_list_array =
    650             sal_alloc(sizeof(_tr3_repl_head_free_block_t *) *
    651                       (max_array_index + 1), "repl head free list array");
    652         if (NULL == _tr3_repl_head_info[unit]->free_list_array) {
    653             _bcm_tr3_repl_head_info_deinit(unit);
    654             return BCM_E_MEMORY;
    655         }
    656         _tr3_repl_head_info[unit]->array_size = max_array_index + 1;
    657     }
    658     sal_memset(_tr3_repl_head_info[unit]->free_list_array, 0,
    659             sizeof(_tr3_repl_head_free_block_t *) *
    660             _tr3_repl_head_info[unit]->array_size);
    661 
    662     if (soc_feature(unit, soc_feature_static_repl_head_alloc)) {
    663         if (!SOC_WARM_BOOT(unit)) {
    664             /* Clear replication head table */
    665             SOC_IF_ERROR_RETURN
    666                 (soc_mem_clear(unit, MMU_REPL_HEAD_TBLm, MEM_BLOCK_ALL, 0));
    667         }
    668     } else {
    669         REPL_HEAD_FREE_LIST(unit, 0) = 
    670             sal_alloc(sizeof(_tr3_repl_head_free_block_t), "repl head free block");
    671         if (NULL == REPL_HEAD_FREE_LIST(unit, 0)) {
    672             _bcm_tr3_repl_head_info_deinit(unit);
    673             return BCM_E_MEMORY;
    674         }
    675         
    676         /* Initially, there is only one free block, starting at entry 
    677          * (1 + max_array_index) of the REPL_HEAD table and ending 
    678          * at the last entry. Entry 0 is reserved.
    679          * Entries from (soc_mem_index_max(unit,MMU_REPL_HEAD_TBLm) - 
    680          * count + 1) to  soc_mem_index_max(unit,MMU_REPL_HEAD_TBLm) 
    681          * are reserved for swapping the REPL_HEADm of a replication group 
    682          * when there is no resource for deleting a port 
    683          * from the replication group.
    684          */
    685         reserve_multicast_resources[unit] =
    686             soc_property_get(unit, spn_RESERVE_MULTICAST_RESOURCES, 0) ? 1 : 0;
    687         if (reserve_multicast_resources[unit]) {
    688             BCM_PBMP_COUNT(PBMP_ALL(unit), num_of_ports);
    689         }
    690         REPL_HEAD_FREE_LIST(unit, 0)->index = 1;
    691         REPL_HEAD_FREE_LIST(unit, 0)->size = soc_mem_index_max(unit,
    692                 MMU_REPL_HEAD_TBLm) - num_of_ports;
    693         REPL_HEAD_FREE_LIST(unit, 0)->next = NULL;
    694 
    695         /* Clear entry 0 of REPL_HEAD table */
    696         SOC_IF_ERROR_RETURN(soc_mem_write(unit, MMU_REPL_HEAD_TBLm, MEM_BLOCK_ALL,
    697                     0, soc_mem_entry_null(unit, MMU_REPL_HEAD_TBLm)));
    698     }
    699 
    700     return BCM_E_NONE;
    701 }
    702 
    703 /*
    704  * Function:
    705  *      _bcm_tr3_repl_head_block_free
    706  * Purpose:
    707  *      Free a block of REPL_HEAD table entries.
    708  * Parameters:
    709  *      unit  - (IN) SOC unit number. 
    710  *      index - (IN) Index of the first entry of the block.
    711  *      size  - (IN) Size of the block.
    712  * Returns:
    713  *      BCM_E_xxx
    714  */
    715 STATIC int 
    716 _bcm_tr3_repl_head_block_free(int unit, int index, int size)
    717 {
    718     int i;
    719     int block_index, block_size;
    720     int coalesced_index, coalesced_size;
    721     _tr3_repl_head_free_block_t *block_ptr;
    722     _tr3_repl_head_free_block_t *prev_block_ptr;
    723     _tr3_repl_head_free_block_t *next_block_ptr;
    724     _tr3_repl_head_free_block_t *coalesced_block_ptr;
    725 
    726     if (size <= 0) {
    727         return BCM_E_INTERNAL;
    728     }
    729 
    730     /* First, coalesce the block with any existing free blocks
    731      * that are contiguous with the block.
    732      */ 
    733     coalesced_index = index;
    734     coalesced_size = size;
    735     for (i = 0; i < _tr3_repl_head_info[unit]->array_size; i++) {
    736         block_ptr = REPL_HEAD_FREE_LIST(unit, i);
    737         prev_block_ptr = NULL;
    738         while (NULL != block_ptr) {
    739             block_index = block_ptr->index;
    740             block_size = block_ptr->size;
    741             next_block_ptr = block_ptr->next;
    742             if ((block_index + block_size) == coalesced_index) {
    743                 coalesced_index = block_index;
    744                 coalesced_size += block_size;
    745                 if (block_ptr == REPL_HEAD_FREE_LIST(unit, i)) {
    746                     REPL_HEAD_FREE_LIST(unit, i) = next_block_ptr;
    747                 } else {
    748                     /* 
    749                      * In the following line of code, Coverity thinks the
    750                      * prev_block_ptr may still be NULL when dereferenced.
    751                      * This situation will never occur because 
    752                      * if block_ptr is not pointing to the head of the 
    753                      * linked list, prev_block_ptr would not be NULL.
    754                      */
    755                     /* coverity[var_deref_op : FALSE] */
    756                     prev_block_ptr->next = next_block_ptr;
    757                 } 
    758                 sal_free(block_ptr);
    759             } else if ((coalesced_index + coalesced_size) == block_index) {
    760                 coalesced_size += block_size;
    761                 if (block_ptr == REPL_HEAD_FREE_LIST(unit, i)) {
    762                     REPL_HEAD_FREE_LIST(unit, i) = next_block_ptr;
    763                 } else {
    764                     /* 
    765                      * In the following line of code, Coverity thinks the
    766                      * prev_block_ptr may still be NULL when dereferenced.
    767                      * This situation will never occur because 
    768                      * if block_ptr is not pointing to the head of the 
    769                      * linked list, prev_block_ptr would not be NULL.
    770                      */
    771                     /* coverity[var_deref_op : FALSE] */
    772                     prev_block_ptr->next = next_block_ptr;
    773                 } 
    774                 sal_free(block_ptr);
    775             } else {
    776                 prev_block_ptr = block_ptr;
    777             }
    778             block_ptr = next_block_ptr;
    779         }
    780     }
    781 
    782     /* Insert coalesced free block */
    783     coalesced_block_ptr = sal_alloc(sizeof(_tr3_repl_head_free_block_t),
    784             "coalesced repl head free block");
    785     if (NULL == coalesced_block_ptr) {
    786         return BCM_E_MEMORY;
    787     }
    788     coalesced_block_ptr->index = coalesced_index;
    789     coalesced_block_ptr->size = coalesced_size;
    790     if (coalesced_size > (_tr3_repl_head_info[unit]->array_size - 1)) {
    791         /* Insert into free list 0 */
    792         coalesced_block_ptr->next = REPL_HEAD_FREE_LIST(unit, 0);
    793         REPL_HEAD_FREE_LIST(unit, 0) = coalesced_block_ptr;
    794     } else {
    795         coalesced_block_ptr->next = REPL_HEAD_FREE_LIST(unit, coalesced_size);
    796         REPL_HEAD_FREE_LIST(unit, coalesced_size) = coalesced_block_ptr;
    797     }
    798 
    799     return BCM_E_NONE;
    800 }
    801 
    802 /*
    803  * Function:
    804  *      _bcm_tr3_repl_head_block_alloc
    805  * Purpose:
    806  *      Allocate a free block of REPL_HEAD table entries.
    807  * Parameters:
    808  *      unit - (IN) SOC unit number. 
    809  *      size - (IN) Size of free block requested.
    810  *      index - (OUT) Index of the first entry of the free block.
    811  * Returns:
    812  *      BCM_E_xxx
    813  */
    814 STATIC int 
    815 _bcm_tr3_repl_head_block_alloc(int unit, int size, int *index)
    816 {
    817     int max_array_index;
    818     int i;
    819     int block_index, block_size;
    820     _tr3_repl_head_free_block_t *next_block_ptr;
    821 
    822     if (size == 0) {
    823         return BCM_E_PARAM;
    824     }
    825     if (NULL == index) {
    826         return BCM_E_PARAM;
    827     }
    828 
    829     max_array_index = _tr3_repl_head_info[unit]->array_size - 1;
    830     for (i = size; i <= max_array_index; i++) {
    831         if (NULL != REPL_HEAD_FREE_LIST(unit, i)) {
    832            block_index = REPL_HEAD_FREE_LIST(unit, i)->index; 
    833            block_size = REPL_HEAD_FREE_LIST(unit, i)->size; 
    834            next_block_ptr = REPL_HEAD_FREE_LIST(unit, i)->next; 
    835            sal_free(REPL_HEAD_FREE_LIST(unit, i));
    836            REPL_HEAD_FREE_LIST(unit, i) = next_block_ptr;
    837 
    838            /* If the obtained free block contains more entries
    839             * than requested, insert the remainder back into
    840             * the free list array.
    841             */
    842            if (block_size > size) {
    843                BCM_IF_ERROR_RETURN(_bcm_tr3_repl_head_block_free(unit,
    844                            block_index + size, block_size - size));
    845            }
    846 
    847            *index = block_index;
    848            return BCM_E_NONE;
    849         }
    850     }
    851 
    852     /* Get free block from free list 0 */
    853     if (NULL != REPL_HEAD_FREE_LIST(unit, 0)) {
    854         block_index = REPL_HEAD_FREE_LIST(unit, 0)->index;
    855         block_size = REPL_HEAD_FREE_LIST(unit, 0)->size;
    856         next_block_ptr = REPL_HEAD_FREE_LIST(unit, 0)->next;
    857         if (block_size < size) {
    858             /* Free blocks on list 0 should never be
    859              * smaller than requested size.
    860              */
    861             return BCM_E_INTERNAL;
    862         } 
    863 
    864         sal_free(REPL_HEAD_FREE_LIST(unit, 0));
    865         REPL_HEAD_FREE_LIST(unit, 0) = next_block_ptr;
    866 
    867         /* If the obtained free block contains more entries
    868          * than requested, insert the remainder back into
    869          * the free list array.
    870          */
    871         if (block_size > size) {
    872             BCM_IF_ERROR_RETURN(_bcm_tr3_repl_head_block_free(unit,
    873                         block_index + size, block_size - size));
    874         }
    875 
    876         *index = block_index;
    877         return BCM_E_NONE;
    878     }
    879 
    880     /* No free block of sufficient size can be found */
    881     return BCM_E_RESOURCE;
    882 }
    883 
    884 #ifdef BCM_WARM_BOOT_SUPPORT
    885 /*
    886  * Function:
    887  *      _bcm_tr3_repl_head_block_insert
    888  * Purpose:
    889  *      Insert a free block of REPL_HEAD table entries into free array list.
    890  * Parameters:
    891  *      unit - (IN) SOC unit number. 
    892  *      index - (IN) Index of the first entry of the block.
    893  *      size - (IN) Size of block.
    894  * Returns:
    895  *      BCM_E_xxx
    896  */
    897 STATIC int 
    898 _bcm_tr3_repl_head_block_insert(int unit, int index, int size)
    899 {
    900     _tr3_repl_head_free_block_t *block_ptr;
    901 
    902     block_ptr = sal_alloc(sizeof(_tr3_repl_head_free_block_t),
    903             "repl head free block");
    904     if (NULL == block_ptr) {
    905         return BCM_E_MEMORY;
    906     }
    907     block_ptr->index = index;
    908     block_ptr->size = size;
    909     if (size > (_tr3_repl_head_info[unit]->array_size - 1)) {
    910         /* Insert into free list 0 */
    911         block_ptr->next = REPL_HEAD_FREE_LIST(unit, 0);
    912         REPL_HEAD_FREE_LIST(unit, 0) = block_ptr;
    913     } else {
    914         block_ptr->next = REPL_HEAD_FREE_LIST(unit, size);
    915         REPL_HEAD_FREE_LIST(unit, size) = block_ptr;
    916     }
    917 
    918     return BCM_E_NONE;
    919 }
    920 
    921 /*
    922  * Function:
    923  *      _bcm_tr3_repl_head_block_used_set
    924  * Purpose:
    925  *      Mark a block of REPL_HEAD table entries as used.
    926  * Parameters:
    927  *      unit - (IN) SOC unit number. 
    928  *      index - (IN) Index of the first entry of the block.
    929  *      size - (IN) Size of block.
    930  * Returns:
    931  *      BCM_E_xxx
    932  */
    933 STATIC int 
    934 _bcm_tr3_repl_head_block_used_set(int unit, int index, int size)
    935 {
    936     int i;
    937     _tr3_repl_head_free_block_t *prev_block_ptr;
    938     _tr3_repl_head_free_block_t *block_ptr;
    939     int block_index, block_size, sub_block_size;
    940 
    941     for (i = 0; i < _tr3_repl_head_info[unit]->array_size; i++) {
    942         block_ptr = REPL_HEAD_FREE_LIST(unit, i);
    943         prev_block_ptr = NULL;
    944         while (NULL != block_ptr) {
    945             block_index = block_ptr->index;
    946             block_size = block_ptr->size;
    947             if ((index >= block_index) &&
    948                     ((index + size) <= (block_index + block_size))) {
    949 
    950                 /* This free block contains the block to be marked as used.
    951                  * Remove this free block from linked list.
    952                  */
    953                 if (block_ptr == REPL_HEAD_FREE_LIST(unit, i)) {
    954                     REPL_HEAD_FREE_LIST(unit, i) = block_ptr->next;
    955                 } else {
    956                     /* 
    957                      * In the following line of code, Coverity thinks the
    958                      * prev_block_ptr may still be NULL when dereferenced.
    959                      * This situation will never occur because 
    960                      * if block_ptr is not pointing to the head of the 
    961                      * linked list, prev_block_ptr would not be NULL.
    962                      */
    963                     /* coverity[var_deref_op : FALSE] */
    964                     prev_block_ptr->next = block_ptr->next;
    965                 }
    966                 sal_free(block_ptr);
    967 
    968                 /* This free block contains up to 3 sub-blocks: the sub-block
    969                  * to be marked as used, and the sub-blocks before and after
    970                  * it. The sub-blocks before and after the used sub-block
    971                  * need to be inserted back into the free list array.
    972                  */
    973 
    974                 /* Insert the sub-block before the used sub-block back into
    975                  * the free list array.
    976                  */
    977                 sub_block_size = index - block_index;
    978                 if (sub_block_size > 0) {
    979                     BCM_IF_ERROR_RETURN
    980                         (_bcm_tr3_repl_head_block_insert(unit, block_index,
    981                                                          sub_block_size));
    982                 }
    983 
    984                 /* Insert the sub-block after the used sub-block back into
    985                  * the free list array.
    986                  */
    987                 sub_block_size = (block_index + block_size) - (index + size);
    988                 if (sub_block_size > 0) {
    989                     BCM_IF_ERROR_RETURN
    990                         (_bcm_tr3_repl_head_block_insert(unit, index + size,
    991                                                          sub_block_size));
    992                 }
    993 
    994                 return BCM_E_NONE;
    995             }
    996 
    997             prev_block_ptr = block_ptr;
    998             block_ptr = block_ptr->next;
    999         }
   1000     }
   1001 
   1002     /* The block to be marked used is not found among the free blocks. */
   1003     return BCM_E_NOT_FOUND;
   1004 }
   1005 #endif /* BCM_WARM_BOOT_SUPPORT */
   1006 
   1007 /*
   1008  * Function:
   1009  *      _bcm_tr3_repl_head_entry_info_get
   1010  * Purpose:
   1011  *      Get replication head table size and number of entries in the free block.
   1012  * Parameters:
   1013  *      unit - (IN) SOC unit number. 
   1014  *      size - (out) Replication head table size.
   1015  *      free - (out) Number of entries in the Replication head table.
   1016  * Returns:
   1017  *      BCM_E_xxx
   1018  */
   1019 int
   1020 _bcm_tr3_repl_head_entry_info_get(int unit, int *free)
   1021 {
   1022     int temp_free = 0;
   1023     _tr3_repl_head_free_block_t *free_block;
   1024     int i = 0;
   1025 
   1026     if (NULL == free) {
   1027         return BCM_E_PARAM;
   1028     } 
   1029 
   1030     if (soc_feature(unit, soc_feature_static_repl_head_alloc)) {
   1031         return BCM_E_UNAVAIL;
   1032     }
   1033 
   1034     IPMC_LOCK(unit);  
   1035     if (_tr3_repl_head_info[unit] != NULL) {
   1036         if (_tr3_repl_head_info[unit]->free_list_array != NULL) {
   1037             for (i = 0; i < _tr3_repl_head_info[unit]->array_size; i++) {
   1038                 free_block = REPL_HEAD_FREE_LIST(unit, i);
   1039                 while (NULL != free_block){
   1040                     temp_free  = temp_free + free_block->size;
   1041                     free_block = free_block->next;
   1042                 }
   1043             }
   1044         }
   1045     }
   1046     IPMC_UNLOCK(unit);
   1047 
   1048     if (0 > temp_free){        
   1049         return BCM_E_INTERNAL;
   1050     }
   1051 
   1052     *free = temp_free;
   1053     
   1054     return BCM_E_NONE;
   1055 }
   1056 
   1057 
   1058 /* --------------------------------------------------------------
   1059  * The following set of routines manage REPL_LIST table resource.
   1060  * --------------------------------------------------------------
   1061  */
   1062 
   1063 /*
   1064  * Function:
   1065  *      _bcm_tr3_repl_list_entry_info_deinit
   1066  * Purpose:
   1067  *      De-initialize replication list entry info.
   1068  * Parameters:
   1069  *      unit - (IN)SOC unit number. 
   1070  * Returns:
   1071  *      None
   1072  */
   1073 STATIC void 
   1074 _bcm_tr3_repl_list_entry_info_deinit(int unit)
   1075 {
   1076     if (NULL != _tr3_repl_list_entry_info[unit]) {
   1077         if (NULL != _tr3_repl_list_entry_info[unit]->bitmap_entries_used) {
   1078             sal_free(_tr3_repl_list_entry_info[unit]->bitmap_entries_used);
   1079             _tr3_repl_list_entry_info[unit]->bitmap_entries_used = NULL;
   1080         }
   1081         sal_free(_tr3_repl_list_entry_info[unit]);
   1082         _tr3_repl_list_entry_info[unit] = NULL;
   1083     }
   1084 }
   1085 
   1086 /*
   1087  * Function:
   1088  *      _bcm_tr3_repl_list_entry_info_init
   1089  * Purpose:
   1090  *      Initialize replication list entry info.
   1091  * Parameters:
   1092  *      unit - (IN)SOC unit number. 
   1093  * Returns:
   1094  *      BCM_E_xxx
   1095  */
   1096 STATIC int 
   1097 _bcm_tr3_repl_list_entry_info_init(int unit)
   1098 {
   1099     int alloc_size;
   1100 
   1101     if (NULL == _tr3_repl_list_entry_info[unit]) {
   1102         _tr3_repl_list_entry_info[unit] =
   1103             sal_alloc(sizeof(_tr3_repl_list_entry_info_t),
   1104                     "repl_list_entry_info");
   1105         if (NULL == _tr3_repl_list_entry_info[unit]) {
   1106             _bcm_tr3_repl_list_entry_info_deinit(unit);
   1107             return BCM_E_MEMORY;
   1108         }
   1109     }
   1110     sal_memset(_tr3_repl_list_entry_info[unit], 0,
   1111             sizeof(_tr3_repl_list_entry_info_t));
   1112 
   1113     _tr3_repl_list_entry_info[unit]->num_entries = soc_mem_index_count(unit,
   1114                 MMU_REPL_LIST_TBLm);
   1115     alloc_size = SHR_BITALLOCSIZE(_tr3_repl_list_entry_info[unit]->num_entries);
   1116     if (NULL == _tr3_repl_list_entry_info[unit]->bitmap_entries_used) {
   1117         _tr3_repl_list_entry_info[unit]->bitmap_entries_used =
   1118             sal_alloc(alloc_size, "repl list bitmap_entries_used");
   1119         if (NULL == _tr3_repl_list_entry_info[unit]->bitmap_entries_used) {
   1120             _bcm_tr3_repl_list_entry_info_deinit(unit);
   1121             return BCM_E_MEMORY;
   1122         }
   1123     }
   1124     sal_memset(_tr3_repl_list_entry_info[unit]->bitmap_entries_used, 0,
   1125             alloc_size);
   1126 
   1127     /* Reserve REPL_LIST table entry 0 */
   1128     REPL_LIST_ENTRY_USED_SET(unit, 0);
   1129 
   1130     /* Clear entry 0 of REPL_LIST table */
   1131     SOC_IF_ERROR_RETURN(soc_mem_write(unit, MMU_REPL_LIST_TBLm, MEM_BLOCK_ALL,
   1132                 0, soc_mem_entry_null(unit, MMU_REPL_LIST_TBLm)));
   1133 
   1134     return BCM_E_NONE;
   1135 }
   1136 
   1137 /*
   1138  * Function:
   1139  *      _bcm_tr3_repl_list_entry_free
   1140  * Purpose:
   1141  *      Free a REPL_LIST table entry.
   1142  * Parameters:
   1143  *      unit - (IN)SOC unit number. 
   1144  *      entry_index - (IN)Index of the entry to be freed.
   1145  * Returns:
   1146  *      BCM_E_xxx
   1147  */
   1148 STATIC int
   1149 _bcm_tr3_repl_list_entry_free(int unit, int entry_index)
   1150 {
   1151     if (!REPL_LIST_ENTRY_USED_GET(unit, entry_index)) {
   1152         return BCM_E_INTERNAL;
   1153     }
   1154 
   1155     REPL_LIST_ENTRY_USED_CLR(unit, entry_index);
   1156     return BCM_E_NONE;
   1157 }
   1158 
   1159 /*
   1160  * Function:
   1161  *      _bcm_tr3_repl_list_entry_alloc
   1162  * Purpose:
   1163  *      Allocate a free entry from REPL_LIST table.
   1164  * Parameters:
   1165  *      unit - (IN)SOC unit number. 
   1166  *      entry_index - (OUT)Index of a free entry.
   1167  * Returns:
   1168  *      BCM_E_xxx
   1169  */
   1170 STATIC int 
   1171 _bcm_tr3_repl_list_entry_alloc(int unit, int *entry_index)
   1172 {
   1173     int i;
   1174 
   1175     for (i = 0; i < _tr3_repl_list_entry_info[unit]->num_entries; i++) {
   1176         if (!REPL_LIST_ENTRY_USED_GET(unit, i)) {
   1177             *entry_index = i;
   1178             REPL_LIST_ENTRY_USED_SET(unit, i);
   1179             return BCM_E_NONE;
   1180         }
   1181     }
   1182 
   1183     *entry_index = -1;
   1184     return BCM_E_RESOURCE;
   1185 }
   1186 
   1187 #ifdef BCM_WARM_BOOT_SUPPORT
   1188 /*
   1189  * Function:
   1190  *      _bcm_tr3_repl_list_entry_used_set
   1191  * Purpose:
   1192  *      Mark the REPL_LIST table entry as used.
   1193  * Parameters:
   1194  *      unit - (IN)SOC unit number. 
   1195  *      entry_index - (IN)Index of the entry to be marked.
   1196  * Returns:
   1197  *      BCM_E_xxx
   1198  */
   1199 STATIC int
   1200 _bcm_tr3_repl_list_entry_used_set(int unit, int entry_index)
   1201 {
   1202     REPL_LIST_ENTRY_USED_SET(unit, entry_index);
   1203     return BCM_E_NONE;
   1204 }
   1205 
   1206 /*
   1207  * Function:
   1208  *      _bcm_tr3_repl_list_entry_used_get
   1209  * Purpose:
   1210  *      Get used status of a REPL_LIST table entry.
   1211  * Parameters:
   1212  *      unit - (IN)SOC unit number. 
   1213  *      entry_index - (IN)Index of the entry.
   1214  *      used - (OUT)Used status.
   1215  * Returns:
   1216  *      TRUE if used, else FALSE.
   1217  */
   1218 STATIC int
   1219 _bcm_tr3_repl_list_entry_used_get(int unit, int entry_index)
   1220 {
   1221     if (REPL_LIST_ENTRY_USED_GET(unit, entry_index)) {
   1222         return TRUE;
   1223     }
   1224     return FALSE;
   1225 }
   1226 #endif /* BCM_WARM_BOOT_SUPPORT */
   1227 
   1228 #ifdef BCM_METROLITE_SUPPORT
   1229 /* Function:
   1230  *      _bcm_metorlite_repl_list_tbl_ptr_get
   1231  * Purpose:
   1232  *      Get the appropriate MMU replication tables and intended
   1233  *      member bitmap last bitmap fields for  for port
   1234  * Parameters:
   1235  *      unit       - StrataSwitch PCI device unit number.
   1236  *      port       - (IN) port.
   1237  *      info       - (OUT) MMU group table info
   1238 *                     mem, pbmp, index corresponding to the port.
   1239  * Returns:
   1240  *      BCM_E_XXX
   1241  */
   1242     STATIC int
   1243 _bcm_metrolite_repl_list_tbl_ptr_get(int unit, bcm_port_t port,
   1244         _kt2_repl_grp_info_t *info)
   1245 {
   1246     if (port < 32) {
   1247         info->mb_mem =  MMU_REPL_GRP_TBLm;
   1248         info->mbmp = MEMBER_BMP_PORTSf;
   1249         info->lb_mem = MMU_REPL_GRP_TBLm;
   1250         info->lbmp =  LAST_BMP_PORTSf;
   1251         info->mb_index = port;
   1252         info->lb_index = port;
   1253     } else {
   1254         LOG_ERROR(BSL_LS_BCM_COMMON,
   1255                   (BSL_META_U(unit, "REPL_GRP_TBL invalid port\n")));
   1256         return BCM_E_PARAM;
   1257     }
   1258     return BCM_E_NONE;
   1259 }
   1260 #endif
   1261 #ifdef BCM_SABER2_SUPPORT
   1262 /* Function:
   1263  *      _bcm_sb2_repl_list_tbl_ptr_get
   1264  * Purpose:
   1265  *      Get the appropriate MMU replication tables and intended 
   1266  *      member bitmap last bitmap fields for  for port
   1267  * Parameters:
   1268  *      unit       - StrataSwitch PCI device unit number.
   1269  *      port       - (IN) port. 
   1270  *      info       - (OUT) MMU group table info 
   1271 *                     mem, pbmp, index corresponding to the port.
   1272  * Returns:
   1273  *      BCM_E_XXX
   1274  */
   1275     STATIC int
   1276 _bcm_sb2_repl_list_tbl_ptr_get(int unit, bcm_port_t port,
   1277         _kt2_repl_grp_info_t *info)
   1278 {
   1279     if ((port >= 0) && (port < 24)) {
   1280         info->mb_mem =  MMU_REPL_GRP_TBL0m;
   1281         info->mbmp = MEMBER_BMP_PORTSf;
   1282         info->lb_mem = MMU_REPL_GRP_TBL0m;
   1283         info->lbmp =  LAST_BMP_PORTS_23_0f;
   1284         info->mb_index = port;
   1285         info->lb_index = port;
   1286     } else if ((port >= 24) && (port < 96)) {
   1287         info->mb_mem =  MMU_REPL_GRP_TBL0m;
   1288         info->mbmp = MEMBER_BMP_PORTSf;
   1289         info->lb_mem = MMU_REPL_GRP_TBL1m;
   1290         info->lbmp =  LAST_BMP_PORTS_95_24f;
   1291         info->mb_index = port;
   1292         info->lb_index = port - 24;
   1293     } else {
   1294         LOG_ERROR(BSL_LS_BCM_COMMON,
   1295                 (BSL_META_U(unit,
   1296                             "REPL_GRP_TBL invalid port\n")));
   1297         return BCM_E_PARAM;
   1298     }
   1299     return BCM_E_NONE;
   1300 }
   1301 #ifdef BCM_METROLITE_SUPPORT
   1302 /* Function:
   1303  *      _bcm_metrolite_repl_group_info_set
   1304  * Purpose:
   1305  *      Set replication group info.
   1306  * Parameters:
   1307  *      unit       - StrataSwitch PCI device unit number.
   1308  *      repl_group - (IN) The replication group number.
   1309  *      port       - (IN) port.
   1310  *      mbmp       - (IN) Member bitmap.
   1311  *      lbmp       - (IN) Last Member bitmap.
   1312  *      head_index - (IN) Base pointer to REPL_HEAD table.
   1313  * Returns:
   1314  *      BCM_E_XXX
   1315  */
   1316 STATIC int
   1317 _bcm_metrolite_repl_group_info_set(int unit, int repl_group, bcm_port_t port,
   1318         soc_pbmp_t mbmp, soc_pbmp_t lbmp, int head_index)
   1319 {
   1320     mmu_repl_grp_tbl_entry_t repl_grp_tbl_entry;
   1321     _kt2_repl_grp_info_t kt2_repl_grp_info;
   1322     uint32 fldbuf[SOC_PBMP_WORD_MAX];
   1323     int i;
   1324 
   1325     sal_memset(&repl_grp_tbl_entry, 0, sizeof(repl_grp_tbl_entry));
   1326     sal_memset(&kt2_repl_grp_info, 0, sizeof(kt2_repl_grp_info));
   1327 
   1328     BCM_IF_ERROR_RETURN(_bcm_metrolite_repl_list_tbl_ptr_get (unit, port,
   1329                 &kt2_repl_grp_info));
   1330 
   1331     sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   1332 
   1333     for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   1334         fldbuf[i] = SOC_PBMP_WORD_GET(lbmp, i);
   1335     }
   1336 
   1337     soc_mem_field_set(unit, kt2_repl_grp_info.lb_mem,
   1338                 (uint32 *)&repl_grp_tbl_entry, kt2_repl_grp_info.lbmp, fldbuf);
   1339     soc_MMU_REPL_GRP_TBLm_field32_set(unit, &repl_grp_tbl_entry,
   1340             BASE_PTRf, head_index);
   1341 
   1342     sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   1343     for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   1344         fldbuf[i] = SOC_PBMP_WORD_GET(mbmp, i);
   1345     }
   1346 
   1347     soc_MMU_REPL_GRP_TBLm_field_set(unit, &repl_grp_tbl_entry,
   1348             MEMBER_BMP_PORTSf, fldbuf);
   1349     SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_GRP_TBLm(unit,
   1350                 MEM_BLOCK_ALL, repl_group, &repl_grp_tbl_entry));
   1351     return BCM_E_NONE;
   1352 }
   1353 #endif
   1354 /* Function:
   1355  *      _bcm_sb2_repl_group_info_set
   1356  * Purpose:
   1357  *      Set replication group info.
   1358  * Parameters:
   1359  *      unit       - StrataSwitch PCI device unit number.
   1360  *      repl_group - (IN) The replication group number.
   1361  *      port       - (IN) port.
   1362  *      mbmp       - (IN) Member bitmap.
   1363  *      lbmp       - (IN) Last Member bitmap.
   1364  *      head_index - (IN) Base pointer to REPL_HEAD table.
   1365  * Returns:
   1366  *      BCM_E_XXX
   1367  */
   1368 STATIC int
   1369 _bcm_sb2_repl_group_info_set(int unit, int repl_group, bcm_port_t port,
   1370         soc_pbmp_t mbmp, soc_pbmp_t lbmp, int head_index)
   1371 {
   1372     mmu_repl_grp_tbl0_entry_t repl_grp_tbl0_entry;
   1373     mmu_repl_grp_tbl1_entry_t repl_grp_tbl1_entry;
   1374     _kt2_repl_grp_info_t kt2_repl_grp_info;
   1375     uint32 fldbuf[SOC_PBMP_WORD_MAX];
   1376     int i;
   1377 
   1378     sal_memset(&repl_grp_tbl0_entry, 0, sizeof(repl_grp_tbl0_entry));
   1379     sal_memset(&repl_grp_tbl1_entry, 0, sizeof(repl_grp_tbl1_entry));
   1380     sal_memset(&kt2_repl_grp_info, 0, sizeof(kt2_repl_grp_info));
   1381 
   1382     BCM_IF_ERROR_RETURN(_bcm_sb2_repl_list_tbl_ptr_get (unit, port,
   1383                 &kt2_repl_grp_info));
   1384 
   1385     sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   1386 
   1387     for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   1388         fldbuf[i] = SOC_PBMP_WORD_GET(lbmp, i);
   1389     }
   1390 
   1391     if (port >=24) {
   1392         soc_mem_field_set(unit, kt2_repl_grp_info.lb_mem,
   1393                 (uint32 *)&repl_grp_tbl1_entry, kt2_repl_grp_info.lbmp, fldbuf);
   1394     } else {
   1395         soc_mem_field_set(unit, kt2_repl_grp_info.lb_mem,
   1396                 (uint32 *)&repl_grp_tbl0_entry, kt2_repl_grp_info.lbmp, fldbuf);
   1397     }
   1398     soc_MMU_REPL_GRP_TBL1m_field32_set(unit, &repl_grp_tbl1_entry,
   1399             BASE_PTRf, head_index);
   1400 
   1401 
   1402     sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   1403     for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   1404         fldbuf[i] = SOC_PBMP_WORD_GET(mbmp, i);
   1405     }
   1406 
   1407     soc_MMU_REPL_GRP_TBL0m_field_set(unit, &repl_grp_tbl0_entry,
   1408             MEMBER_BMP_PORTSf, fldbuf);
   1409     SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_GRP_TBL1m(unit,
   1410                 MEM_BLOCK_ALL, repl_group, &repl_grp_tbl1_entry));
   1411     SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_GRP_TBL0m(unit,
   1412                 MEM_BLOCK_ALL, repl_group, &repl_grp_tbl0_entry));
   1413     return BCM_E_NONE;
   1414 }
   1415 
   1416 
   1417 /* Function:
   1418  *     _bcm_sb2_ipmc_subscriber_node_max_get 
   1419  * Purpose:
   1420  *     calculate the maximum hardware qlist indexes
   1421  *     needed based on the replication count . 
   1422  *     Each hardware index can take two pair of (queueid,nexthopid)
   1423  *     but the both the queue id cannot be same  in given index 
   1424  *     This function tries to find the optimum index required given the
   1425  *     above restriction.
   1426  *     it tries to pair  (queueid,encapid) such that the two queues are 
   1427  *     not same           
   1428  *     eg if let there be 3 queues and 3 replication on each queue       
   1429  *     queue 1 requires 3 indexes but there are 3 open positions in 
   1430  *     these index  so queue 2 is paired with queue 1 and 3 indexes
   1431  *     are filled and queue 3 will require futher 3 indexes.So the total is
   1432  *     6. 
   1433  *     calculation based on the code below 
   1434  *     iinitialy we need 3 for queue1 so 
   1435  *     index0 = 3 
   1436  *     then we need 3 for queue 2 but we can use the index1 entry
   1437  *     index1 = 3 
   1438  *     check if index1 >= index0 (3 >= 3) 
   1439  *     if true we have found count of index0 pairs and index0 valus is
   1440  *     added to max_count and diffrence between index1 and index0 is kept
   1441  *     in index0 as we have yet to find pairs for them . 
   1442  *     this is continued till all the replications are taken in account 
   1443  *     At the end whatever that remains in the index0  count does not have  
   1444  *     pairs and will use up seperate index, hence added to max_count . 
   1445  * Parameters:
   1446  *      unit       - StrataSwitch PCI device unit number.
   1447  *      ipmc_id    - (IN) ipmc_id
   1448  *      node_max   -  (OUT) max indexes  
   1449  * Returns:
   1450  *      BCM_E_XXX
   1451  */
   1452 int
   1453 _bcm_sb2_ipmc_subscriber_node_max_get( int unit, int ipmc_id, int *node_max)
   1454 {
   1455 
   1456     _bcm_ext_q_ipmc_t  *ipmc_node = &_sb2_extq_repl_info[unit]->
   1457                                           ext_ipmc_list[ipmc_id];  
   1458     _bcm_ext_repl_q_list_t *startq;
   1459 
   1460     int index0, index1 ;
   1461     index0 = index1 = 0;
   1462     *node_max = 0; 
   1463     startq = ipmc_node->first_q_ptr;
   1464     if (!startq) {
   1465         *node_max = 0 ;         
   1466         return BCM_E_INTERNAL; 
   1467     }
   1468     index0 = startq->repl_count ;
   1469     startq = startq->next ;
   1470     for (; startq ; startq = startq->next) {
   1471          index1 += startq->repl_count;
   1472          if (index1 >= index0) {                  
   1473              *node_max += index0 ; 
   1474              index0 = (index1 - index0) ;
   1475              index1 = 0; 
   1476          } 
   1477     }
   1478     *node_max += index0;    
   1479     return BCM_E_NONE;  
   1480 }
   1481 
   1482  /*
   1483   * Function:
   1484   *    _bcm_sb2_extq__repl_list_free
   1485   * Description:
   1486   *    Release the MMU_EXT_MC_QUEUE_LIST entries in the HW list starting
   1487   *     at extq_ptr.
   1488   */
   1489 
   1490 STATIC int
   1491 _bcm_sb2_extq_repl_list_free(int unit, int extq_ptr)
   1492 {
   1493      int     rv = BCM_E_NONE;
   1494      int     next_ptr1, next_ptr2;
   1495      mmu_ext_mc_queue_list4_entry_t     qlist4_entry;
   1496      mmu_ext_mc_queue_list0_entry_t     qlist0_entry;
   1497 
   1498      if ((rv = READ_MMU_EXT_MC_QUEUE_LIST4m(unit, MEM_BLOCK_ANY,
   1499                                      extq_ptr, &qlist4_entry)) < 0) {
   1500           goto repl_list_free_done;
   1501      }
   1502      if ((rv = READ_MMU_EXT_MC_QUEUE_LIST0m(unit, MEM_BLOCK_ANY,
   1503                                      extq_ptr, &qlist0_entry)) < 0) {
   1504           goto repl_list_free_done;
   1505      }
   1506      next_ptr1 = soc_MMU_EXT_MC_QUEUE_LIST4m_field32_get(unit,
   1507                                       &qlist4_entry, EXT_Q_NXT_PTR1f);
   1508      next_ptr2 = soc_MMU_EXT_MC_QUEUE_LIST4m_field32_get(unit,
   1509                                       &qlist4_entry, EXT_Q_NXT_PTR2f);
   1510      IPMC_EXTQ_REPL_VE_USED_CLR(unit, extq_ptr);
   1511 
   1512      sal_memset (&qlist0_entry, 0,
   1513          sizeof(mmu_ext_mc_queue_list0_entry_t));
   1514      sal_memset (&qlist4_entry, 0, 
   1515                 sizeof(mmu_ext_mc_queue_list4_entry_t));    
   1516 
   1517      rv = WRITE_MMU_EXT_MC_QUEUE_LIST0m(unit, MEM_BLOCK_ANY,
   1518                              extq_ptr, &qlist0_entry);
   1519      rv =  WRITE_MMU_EXT_MC_QUEUE_LIST4m(unit, MEM_BLOCK_ANY,
   1520                              extq_ptr, &qlist4_entry);
   1521 
   1522      if (next_ptr1 != extq_ptr) {
   1523          if ((rv = _bcm_sb2_extq_repl_list_free(unit, next_ptr1)) < 0) {
   1524               goto repl_list_free_done;
   1525          }
   1526      }
   1527 
   1528      if (next_ptr2 != extq_ptr) {
   1529          if ((rv = _bcm_sb2_extq_repl_list_free(unit, next_ptr2)) < 0) {
   1530               goto repl_list_free_done;
   1531          }
   1532      }
   1533 
   1534  repl_list_free_done:
   1535      return rv;
   1536 
   1537 }
   1538 
   1539 #ifdef BCM_SABER2_SUPPORT
   1540 void
   1541 bcm_sb2_ipmc_repl_extq_port_free(int unit, bcm_port_t port) {
   1542    if (_sb2_extq_repl_info[unit]->port_info[port] != NULL) {
   1543         if (_sb2_extq_repl_info[unit]->port_info[port]->queue_count
   1544                 != NULL) {
   1545             sal_free(
   1546                     _sb2_extq_repl_info[unit]->port_info[port]->queue_count);
   1547             _sb2_extq_repl_info[unit]->port_info[port]->queue_count = NULL;
   1548         }
   1549         sal_free(_sb2_extq_repl_info[unit]->port_info[port]);
   1550     }
   1551     _sb2_extq_repl_info[unit]->port_info[port] = NULL;
   1552 }
   1553 #endif
   1554 
   1555 /*
   1556  * Function:
   1557  *      bcm_sb2_ipmc_repl_detach
   1558  * Purpose:
   1559  *      Cleanup routing to deinit ipmc 
   1560  * Parameters:
   1561  *      unit     - SOC unit #
   1562  * Returns:
   1563  *      BCM_E_XXX
   1564  */
   1565 int
   1566 bcm_sb2_ipmc_repl_detach(int unit)
   1567 {
   1568     _bcm_repl_list_info_t *rli_current, *rli_free;
   1569     bcm_port_t            port;
   1570     bcm_pbmp_t            pbmp_pp;
   1571 
   1572     BCM_PBMP_CLEAR(pbmp_pp);
   1573     BCM_PBMP_ASSIGN(pbmp_pp, PBMP_PP_ALL(unit));
   1574 
   1575     if (soc_feature(unit, soc_feature_linkphy_coe) ||
   1576         soc_feature(unit, soc_feature_subtag_coe)) {
   1577         _bcm_kt2_subport_pbmp_update(unit, &pbmp_pp);
   1578     }
   1579     if (SOC_IS_KATANA2(unit)) {
   1580         BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update (unit, &pbmp_pp));
   1581     }
   1582     
   1583     if (_sb2_extq_repl_info[unit] != NULL) {
   1584         PBMP_ITER(pbmp_pp, port) {
   1585             if (port >= SOC_MAX_NUM_PP_PORTS) {
   1586                 LOG_ERROR(BSL_LS_BCM_COMMON,
   1587                         (BSL_META_U(unit,
   1588                                     "bcm_sb2_ipmc_repl_detach invalid PP port %d\n"),port));
   1589                 break;
   1590             }
   1591 
   1592             bcm_sb2_ipmc_repl_extq_port_free(unit, port); 
   1593         }
   1594 
   1595         if (_sb2_extq_repl_info[unit]->mcgroup_info != NULL) {
   1596             if (_sb2_extq_repl_info[unit]->mcgroup_info->queue_count 
   1597                                             != NULL) {
   1598                 sal_free(_sb2_extq_repl_info[unit]->
   1599                          mcgroup_info->queue_count);
   1600             }
   1601             if (_sb2_extq_repl_info[unit]->mcgroup_info->queue_count_int
   1602                                             != NULL) {
   1603                 sal_free(_sb2_extq_repl_info[unit]->
   1604                          mcgroup_info->queue_count_int);
   1605             }
   1606             if (_sb2_extq_repl_info[unit]->mcgroup_info->queue_count_ext
   1607                                             != NULL) {
   1608                 sal_free(_sb2_extq_repl_info[unit]->
   1609                          mcgroup_info->queue_count_ext);
   1610             }
   1611             sal_free(_sb2_extq_repl_info[unit]->mcgroup_info);
   1612         }
   1613         if (_sb2_extq_repl_info[unit]->ext_ipmc_list) {
   1614             sal_free(_sb2_extq_repl_info[unit]->ext_ipmc_list);
   1615 
   1616         }
   1617         if (_sb2_extq_repl_info[unit]->bitmap_entries_used != NULL) {
   1618             sal_free(_sb2_extq_repl_info[unit]->bitmap_entries_used);
   1619         }
   1620 
   1621 
   1622         if (_sb2_extq_repl_info[unit]->repl_extq_list_info != NULL) {
   1623             rli_current = IPMC_EXTQ_REPL_LIST_INFO(unit);
   1624             while (rli_current != NULL) {
   1625                    rli_free = rli_current;
   1626                    rli_current = rli_current->next;
   1627                    sal_free(rli_free);
   1628             }
   1629         }
   1630 
   1631         sal_free(_sb2_extq_repl_info[unit]);
   1632         _sb2_extq_repl_info[unit] = NULL;
   1633     }
   1634 
   1635     return BCM_E_NONE;
   1636 }
   1637 
   1638 
   1639 
   1640  STATIC int
   1641 _bcm_sb2_extq_repl_next_free_ptr(int unit)
   1642  {
   1643      int                 ix, bit;
   1644      SHR_BITDCL          not_ptrs;
   1645 
   1646      for (ix = 0; ix < _SHR_BITDCLSIZE(IPMC_EXTQ_LIST_TOTAL(unit)); ix++) {
   1647          not_ptrs = ~_sb2_extq_repl_info[unit]->bitmap_entries_used[ix];
   1648          if (not_ptrs) {
   1649              for (bit = 0; bit < SHR_BITWID; bit++) {
   1650                   if (not_ptrs & (1 << bit)) {
   1651                       return (ix * SHR_BITWID) + bit;
   1652                   }
   1653              }
   1654          }
   1655      }
   1656 
   1657      return -1;
   1658 }
   1659 
   1660 
   1661  STATIC int
   1662  _sb2_extq_mc_group_ptr(int unit,int ipmc_id,
   1663                    int *extq_ptr, int last, int set)
   1664 {
   1665    int         rv = BCM_E_NONE;
   1666    mmu_ext_mc_group_map_entry_t mc_group_entry;
   1667    soc_mem_t mem = MMU_EXT_MC_GROUP_MAPm;
   1668    int remap_id;
   1669 
   1670    soc_mem_lock(unit, mem);
   1671    if ((rv = soc_mem_read(unit, mem, MEM_BLOCK_ALL,
   1672                          ipmc_id, &mc_group_entry)) < 0) {
   1673         soc_mem_unlock(unit, mem);
   1674         return rv;
   1675    }
   1676 
   1677    if (set) {
   1678        soc_mem_field32_set(unit, mem, &mc_group_entry,
   1679        EXT_Q_FIRST_PTRf, *extq_ptr);
   1680        soc_mem_field32_set(unit, mem, &mc_group_entry,
   1681        EXT_Q_LAST_LASTf, last ? 1 : 0);
   1682  
   1683        if ((rv = _bcm_kt_ipmc_mmu_mc_remap_ptr(unit, ipmc_id,
   1684                                     &remap_id, FALSE)) < 0) {
   1685             soc_mem_unlock(unit, mem);
   1686             return rv;
   1687        }
   1688        /* update the new chain in the remapped id */
   1689        if ((rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, remap_id,
   1690                                    &mc_group_entry)) < 0) {
   1691        soc_mem_unlock(unit, mem);
   1692        return rv;
   1693        }
   1694   
   1695    } else {
   1696        *extq_ptr = soc_mem_field32_get(unit, mem, &mc_group_entry,
   1697                                               EXT_Q_FIRST_PTRf);
   1698    }
   1699    soc_mem_unlock(unit, mem);
   1700    return rv;
   1701 }
   1702 
   1703 
   1704 int 
   1705 _bcm_sb2_ipmc_set_remap_group(int unit, int ipmc_id, 
   1706                             bcm_port_t port, int count)
   1707 {
   1708     int rv = BCM_E_NONE;
   1709     int int_mem = 0, ext_mem = 0;
   1710     uint32 entry[SOC_MAX_MEM_FIELD_WORDS];
   1711     bcm_pbmp_t destination_pbmp;
   1712     int port_ext_queue_count = 0;
   1713     soc_mem_t dest_pbm_mem;
   1714 
   1715 
   1716 
   1717 
   1718     
   1719     BCM_IF_ERROR_RETURN(soc_mem_read(unit, L3_IPMCm, MEM_BLOCK_ANY,
   1720                                      ipmc_id, entry));
   1721 
   1722     /*
   1723      * Get extended queue_count_int and extended queue_count_ext
   1724      * If there is at least one extended queue replication that
   1725      * requires external buffer, EXT_Q_EXTERNALf is set to 1.
   1726      * If there is at least one extended queue replication that
   1727      * requires internal buffer, EXT_Q_INTERNALf is set to 1.
   1728      */
   1729     int_mem = IPMC_EXTQ_REPL_QUEUE_COUNT_INT(unit, ipmc_id) ? 1 : 0;
   1730     ext_mem = IPMC_EXTQ_REPL_QUEUE_COUNT_EXT(unit, ipmc_id) ? 1 : 0;
   1731 
   1732        soc_mem_field32_set(unit, L3_IPMCm, entry, EXT_Q_INTERNALf, 
   1733             int_mem);
   1734         soc_mem_field32_set(unit, L3_IPMCm, entry, EXT_Q_EXTERNALf, 
   1735             ext_mem);
   1736     soc_mem_field32_set(unit, L3_IPMCm, entry, EXT_Q_NUM_COPIESf, 
   1737                                                           count);
   1738     
   1739     soc_mem_field32_set(unit, L3_IPMCm, entry, VALIDf, 1);
   1740     BCM_IF_ERROR_RETURN(soc_mem_write(unit, L3_IPMCm, MEM_BLOCK_ANY,
   1741                                      ipmc_id, entry));
   1742 
   1743     BCM_PBMP_CLEAR(destination_pbmp);
   1744 
   1745     if (SOC_MEM_IS_VALID(unit ,L3_IPMC_2m)) {
   1746         /* For Katana2 */
   1747         dest_pbm_mem = L3_IPMC_2m ;
   1748     } else {
   1749         /* Saber2, Katana */
   1750         dest_pbm_mem = L3_IPMCm;
   1751     }
   1752 
   1753     if (SOC_MEM_FIELD_VALID(unit, dest_pbm_mem, DESTINATION_PBMf)) {
   1754 
   1755         port_ext_queue_count = IPMC_EXTQ_REPL_PORT_QUEUE_COUNT(unit,
   1756                                    port, ipmc_id);
   1757 
   1758         BCM_IF_ERROR_RETURN(soc_mem_read(unit, dest_pbm_mem, MEM_BLOCK_ANY,
   1759                                      ipmc_id, entry));
   1760 
   1761         /* Extract Destination_pbm for egress mirror support on extended queues. */
   1762         soc_mem_pbmp_field_get(unit,
   1763             dest_pbm_mem, entry, DESTINATION_PBMf, &destination_pbmp);
   1764         if (port_ext_queue_count) {
   1765             BCM_PBMP_PORT_ADD(destination_pbmp, port);
   1766         } else {
   1767             if (BCM_PBMP_MEMBER(destination_pbmp, port)) {
   1768                 BCM_PBMP_PORT_REMOVE(destination_pbmp, port);
   1769             }
   1770         }
   1771         soc_mem_pbmp_field_set(unit,
   1772             dest_pbm_mem, entry, DESTINATION_PBMf, &destination_pbmp);
   1773 
   1774         BCM_IF_ERROR_RETURN(soc_mem_write(unit, dest_pbm_mem, MEM_BLOCK_ANY,
   1775                                      ipmc_id, entry));
   1776     }
   1777 
   1778 
   1779     return rv;
   1780 }
   1781 
   1782 
   1783 /*
   1784  * Function:
   1785  *     _bcm_sb2_ipmc_subscriber_find_ipmc 
   1786  * Purpose:
   1787  *      For the given hardware start index find a matching ipmc
   1788  *      that uses that hardware start index .  
   1789  * Parameters:
   1790  *      unit     - SOC unit #
   1791  *      start_index - (IN) hardware start index 
   1792  *      ipmc_id      - (OUT) ipmc_id
   1793  * Returns:
   1794  *      BCM_E_XXX
   1795  */
   1796 int
   1797 _bcm_sb2_ipmc_subscriber_find_ipmc(int unit ,int start_index, int *ipmc_id) 
   1798 {
   1799 
   1800   _bcm_ext_q_ipmc_t  *ipmc_node ; 
   1801                                   
   1802   int max_ipmc;
   1803   int i = 0; 
   1804   
   1805   max_ipmc = soc_mem_index_count(unit, L3_IPMCm);   
   1806   for (i = 0; i < max_ipmc; i++) {
   1807        ipmc_node = &_sb2_extq_repl_info[unit]->
   1808                                  ext_ipmc_list[i];  
   1809        if(ipmc_node->list_start_index == start_index) {
   1810           *ipmc_id = i;
   1811           break;  
   1812        }
   1813   }
   1814   return BCM_E_NONE; 
   1815 }
   1816 
   1817 /*
   1818  * Function:
   1819  *     _bcm_sb2_extq_compare_nh_nodes 
   1820  * Purpose:
   1821  *     Compare all the nh_nodes for the given two queue nodes    
   1822  *      
   1823  * Parameters:
   1824  *      unit     - SOC unit #
   1825  *      startq   -  
   1826  *      queue_node   - 
   1827  * Returns:
   1828  *      BCM_E_XXX
   1829  */
   1830 
   1831 int
   1832  _bcm_sb2_extq_compare_nh_nodes(_bcm_ext_repl_q_list_t *startq,
   1833                                   _bcm_ext_repl_q_list_t *queue_node)
   1834 {
   1835 
   1836     _bcm_ext_nh_list_t *nh_nodenew, *nh_node;
   1837     int nh_node_found = 0;
   1838 
   1839      for (nh_nodenew = startq->first_nh_ptr ; nh_nodenew ;
   1840                                  nh_nodenew = nh_nodenew->next) {
   1841           nh_node_found = 0 ; 
   1842           for (nh_node = queue_node->first_nh_ptr ; nh_node ;
   1843                                  nh_node = nh_node->next) {
   1844                if (nh_nodenew->encap_id == nh_node->encap_id) {
   1845                    nh_node_found = 1 ;
   1846                    break ; 
   1847                }
   1848           }
   1849           if (!nh_node_found) {
   1850               return BCM_E_NOT_FOUND; 
   1851           }
   1852      }
   1853      return BCM_E_NONE; 
   1854 }
   1855 
   1856 
   1857 /*
   1858  * Function:
   1859  *     _bcm_sb2_extq_repl_list_compare 
   1860  * Purpose:
   1861  *     Compare the two ipmc tree and find if they are similar 
   1862  * Parameters:
   1863  *      unit     - SOC unit #
   1864  *      startq   -  
   1865  *      queue_node   - 
   1866  * Returns:
   1867  *      BCM_E_XXX
   1868  */
   1869 int
   1870 _bcm_sb2_extq_repl_list_compare(int unit , int new_ipmc_id ,int ipmc_id)
   1871 {
   1872 
   1873     _bcm_ext_q_ipmc_t  *ipmc_node = &(_sb2_extq_repl_info[unit]->
   1874                                          ext_ipmc_list[ipmc_id]);  
   1875     _bcm_ext_repl_q_list_t *startq,*queue_node;
   1876     _bcm_ext_q_ipmc_t  *ipmc_nodenew = &(_sb2_extq_repl_info[unit]->
   1877                                          ext_ipmc_list[new_ipmc_id]);  
   1878     int rv = 0;
   1879     if (ipmc_id == new_ipmc_id) {
   1880         return BCM_E_NOT_FOUND; 
   1881     }
   1882     /*compare queue hash*/ 
   1883     if ( ipmc_nodenew->queue_hash 
   1884         != ipmc_node->queue_hash) {
   1885          return BCM_E_NOT_FOUND; 
   1886     }
   1887     startq = ipmc_nodenew->first_q_ptr; 
   1888     
   1889     for (; startq; startq = startq->next) {
   1890 
   1891        for (queue_node = ipmc_node->first_q_ptr ;
   1892             queue_node ; queue_node = queue_node->next) {
   1893             if(startq->queue_id == queue_node->queue_id) {
   1894                break; 
   1895            }
   1896        }
   1897        if (!queue_node) {
   1898            return BCM_E_NOT_FOUND;
   1899        }
   1900        if (startq->repl_hash != queue_node->repl_hash) {
   1901           return BCM_E_NOT_FOUND; 
   1902        }
   1903        rv =  _bcm_sb2_extq_compare_nh_nodes(startq, queue_node);  
   1904        if (rv < 0) { 
   1905            break ; 
   1906        }
   1907     }
   1908     return rv; 
   1909 }
   1910 
   1911 /*
   1912  * Function:
   1913  *   _bcm_sb2_subscriber_ipmc_index_validate   
   1914  * Purpose:
   1915  *     verifies if we have suffcient hardware indexes
   1916  * Parameters:
   1917  *      unit     - SOC unit #
   1918  *      ipmc_id   -  
   1919  * Returns:
   1920  *      BCM_E_XXX
   1921  */
   1922 int 
   1923 _bcm_sb2_subscriber_ipmc_index_validate(int unit, int ipmc_id)
   1924 {
   1925 
   1926      int node_max = 0; 
   1927      int *index; 
   1928      int rv = 0;
   1929      int i = 0 ; 
   1930      
   1931      _bcm_sb2_ipmc_subscriber_node_max_get(unit, ipmc_id, &node_max);
   1932      index = sal_alloc(node_max * sizeof(int),"list of index");
   1933      for (i = 0; i < node_max; i++) {
   1934           index[i] = _bcm_sb2_extq_repl_next_free_ptr(unit);
   1935           if (index[i] < 0) {
   1936               rv = BCM_E_RESOURCE;
   1937               goto clean_up;
   1938           }
   1939           IPMC_EXTQ_REPL_VE_USED_SET(unit, index[i]);
   1940     }
   1941      
   1942 clean_up:
   1943     i--;    
   1944     for ( ; i >= 0; i--) {
   1945          IPMC_EXTQ_REPL_VE_USED_CLR(unit,index[i]); 
   1946     }
   1947     sal_free(index); 
   1948     return rv; 
   1949 }
   1950 
   1951 
   1952 /*
   1953  * Function:
   1954  *    _bcm_sb2_extq_repl_list_write   
   1955  * Purpose:
   1956  *    Writes the data in given ipmc tree in hardware 
   1957  * Parameters:
   1958  *      unit     - SOC unit #
   1959  *      ipmc_id   -  
   1960  *      extq_index - (OUT) start of index in hardware 
   1961  *      count      -(OUT)  count of hardware index used 
   1962  * Returns:
   1963  *      BCM_E_XXX
   1964  */
   1965 STATIC int
   1966 _bcm_sb2_extq_repl_list_write(int unit, int ipmc_id, 
   1967            int *extq_index, int *count)  
   1968 {
   1969     int     node_max, alloc_size;
   1970     int     next1, next2;
   1971     int     i, repl_count = 0;
   1972     int     rv = BCM_E_NONE;
   1973     int     copy, last, buf_type, vlan_last;
   1974     int     reset_val  = 1;
   1975     int     encap_id = 0 ;
   1976     int     repl_index = 0;
   1977     int     next_ptr_allocated = 0 ;
   1978     int     queue_id = 0;
   1979     _bcm_repl_list_info_t *list_array = NULL;
   1980     _bcm_repl_list_info_t *cur_node, *next, *fast_node, *start_node;
   1981     _bcm_ext_q_ipmc_t  *ipmc_node = &_sb2_extq_repl_info[unit]->
   1982                                           ext_ipmc_list[ipmc_id];  
   1983     _bcm_ext_repl_q_list_t *startq;
   1984     mmu_ext_mc_queue_list0_entry_t     *qlist0_entry = NULL;
   1985     mmu_ext_mc_queue_list4_entry_t     *qlist4_entry = NULL;
   1986     soc_field_t        base_qid[] = { BASE_QID0f, BASE_QID1f };
   1987     soc_field_t        profile_idx[] = { Q_OFFSET_PROF0f, Q_OFFSET_PROF1f };
   1988     soc_field_t        repl_ptr[] = { L3_REPL_PTR0f, L3_REPL_PTR1f };    
   1989     soc_field_t        l2_copy[]  = { L2_COPY0f, L2_COPY1f };
   1990     soc_field_t        l3_last[] = { L3_LAST0f, L3_LAST1f };     
   1991     soc_field_t        buff_type[] = { BUFF_TYPE0f, BUFF_TYPE1f };
   1992     soc_field_t        reset_field[] = { L3_REPL_TYPE0f, L3_REPL_TYPE1f };   
   1993     _bcm_ext_nh_list_t *startnh; 
   1994     
   1995     reset_val = 0x4000;
   1996     for (i = 0; i < 2; i++) {
   1997          reset_field[i] = repl_ptr[i];
   1998     }
   1999     node_max = 0;  
   2000     _bcm_sb2_ipmc_subscriber_node_max_get(unit, ipmc_id, &node_max);
   2001 
   2002     alloc_size = node_max * sizeof(_bcm_repl_list_info_t);
   2003     list_array = sal_alloc(alloc_size, "IPMC repl node array");
   2004 
   2005     if (list_array == NULL) {
   2006         return BCM_E_MEMORY;
   2007     }
   2008     sal_memset(list_array, 0, alloc_size);
   2009 
   2010     qlist0_entry = sal_alloc(node_max * 
   2011                                sizeof(mmu_ext_mc_queue_list0_entry_t),
   2012                                    "IPMC repl entry0 array ");
   2013     if (qlist0_entry == NULL) {
   2014         rv = BCM_E_MEMORY;
   2015         goto clean_up;
   2016     }
   2017 
   2018     qlist4_entry = sal_alloc(node_max *
   2019                       sizeof(mmu_ext_mc_queue_list4_entry_t),
   2020                                    "IPMC repl entry0 array ");
   2021     if (qlist4_entry == NULL) {
   2022         rv = BCM_E_MEMORY;
   2023         goto clean_up;
   2024     }
   2025     /* create a link list of entries with free qlist pointers */    
   2026     for (i = 0; i < node_max; i++) {
   2027          sal_memset(&qlist0_entry[i], 0,
   2028              sizeof(mmu_ext_mc_queue_list0_entry_t));
   2029          sal_memset(&qlist4_entry[i], 0, 
   2030                     sizeof(mmu_ext_mc_queue_list4_entry_t));    
   2031          cur_node = &list_array[i];
   2032          cur_node->index = _bcm_sb2_extq_repl_next_free_ptr(unit);
   2033          if (cur_node->index < 0) {
   2034              rv = BCM_E_RESOURCE;
   2035              goto clean_up;
   2036          }
   2037          IPMC_EXTQ_REPL_VE_USED_SET(unit, cur_node->index);
   2038          if (i < (node_max - 1)) { /* create a chain till penultimate node */
   2039              cur_node->next = &list_array[i+1];
   2040          }
   2041     }    
   2042 
   2043     /* copy back the stored contents into qlist entries */
   2044     fast_node = cur_node = &list_array[0];
   2045     *extq_index = cur_node->index;
   2046 
   2047     *count = 0;
   2048     repl_count = 0 ; 
   2049     repl_index = 0 ; 
   2050     start_node = cur_node; 
   2051     for (startq = ipmc_node->first_q_ptr ; startq; startq = startq->next) {
   2052          for (startnh = startq->first_nh_ptr; startnh ; startnh=startnh->next) {
   2053               soc_MMU_EXT_MC_QUEUE_LIST0m_field32_set(unit,
   2054                                                 &qlist0_entry[repl_index], 
   2055                                      base_qid[repl_count],startq->queue_id);
   2056               soc_MMU_EXT_MC_QUEUE_LIST0m_field32_set(unit,
   2057                                                       &qlist0_entry[repl_index],
   2058                                                       profile_idx[repl_count],
   2059                                                       startq->profile_id & 0x3);
   2060               copy = startq->l2_copy; 
   2061               buf_type = startq->buf_type;
   2062               vlan_last = 1;
   2063               soc_MMU_EXT_MC_QUEUE_LIST0m_field32_set(unit,
   2064                                             &qlist0_entry[repl_index], 
   2065                                              l2_copy[repl_count], copy);
   2066               if (soc_feature(unit, soc_feature_ddr3)) {
   2067                   soc_MMU_EXT_MC_QUEUE_LIST0m_field32_set(unit,
   2068                                               &qlist0_entry[repl_index], 
   2069                                         buff_type[repl_count], buf_type);
   2070               }
   2071               soc_MMU_EXT_MC_QUEUE_LIST0m_field32_set(unit, 
   2072                                                     &qlist0_entry[repl_index],
   2073                                                      l3_last[repl_count],
   2074                                                      vlan_last);
   2075                                  
   2076               if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, startnh->encap_id)) {
   2077                   /* L3 interface is used */
   2078                   encap_id = startnh->encap_id + IPMC_SB2_EGRESS_ID_MIN ;
   2079               } else {
   2080                  /* Next hop is used */
   2081                   encap_id =   startnh->encap_id -
   2082                            BCM_XGS3_DVP_EGRESS_IDX_MIN(unit) + IPMC_SB2_NHOP_ID_MIN;
   2083               }
   2084               soc_MMU_EXT_MC_QUEUE_LIST0m_field32_set(unit, 
   2085                                                    &qlist0_entry[repl_index],
   2086                                                         repl_ptr[repl_count],
   2087                                                         encap_id);
   2088               if (!next_ptr_allocated)  {
   2089                   last = 0;
   2090                   if ((repl_index < 2) || (repl_index % 2) != 0) {
   2091                       next = fast_node->next;
   2092                       if (next != NULL) {
   2093                           next1 = next->index;
   2094                           fast_node = next;
   2095                           if (fast_node->next != NULL) {
   2096                               next2 = fast_node->next->index;
   2097                               fast_node = fast_node->next;
   2098        /* need to set the last flag now, if this is the last enrty */
   2099                               if (fast_node->next == NULL) {
   2100                                   last = 1;
   2101                               }
   2102                          } else {
   2103                              next2 = cur_node->index;
   2104                              last = 1;
   2105                          }
   2106                      } else {
   2107                          next1 = cur_node->index;
   2108                          next2 = next1;
   2109                      }    
   2110                  } else {
   2111                     next1 = cur_node->index;
   2112                     next2 = next1;
   2113                  }
   2114                  soc_MMU_EXT_MC_QUEUE_LIST4m_field32_set(unit,
   2115                                                  &qlist4_entry[repl_index], 
   2116                                                     EXT_Q_NXT_PTR1f, next1);
   2117                  soc_MMU_EXT_MC_QUEUE_LIST4m_field32_set(unit, 
   2118                                                   &qlist4_entry[repl_index], 
   2119                                                     EXT_Q_NXT_PTR2f, next2);
   2120                  soc_MMU_EXT_MC_QUEUE_LIST4m_field32_set(unit,  
   2121                                                   &qlist4_entry[repl_index],
   2122                                                     EXT_Q_LAST_LASTf, last);
   2123                  cur_node = cur_node->next; 
   2124              }
   2125              repl_index++;  
   2126              if (repl_index == node_max)  {
   2127                  *count = repl_index ;
   2128                  repl_index = 0; 
   2129                  repl_count = 1 ; 
   2130                  next_ptr_allocated = 1 ;  
   2131              }
   2132           }
   2133       }
   2134       cur_node = start_node; 
   2135       for ( i = 0 ; i < node_max ; i++)   {
   2136            if ((queue_id = soc_MMU_EXT_MC_QUEUE_LIST0m_field32_get(unit, 
   2137                                     &qlist0_entry[i], base_qid[1])) == 0) {
   2138                 soc_MMU_EXT_MC_QUEUE_LIST0m_field32_set(unit, 
   2139                                                    &qlist0_entry[i],
   2140                                                    reset_field[1], 
   2141                                                    reset_val);
   2142            }
   2143            if ((rv = WRITE_MMU_EXT_MC_QUEUE_LIST0m(unit, MEM_BLOCK_ANY,
   2144                                   cur_node->index, &qlist0_entry[i])) < 0) {
   2145                 goto clean_up;
   2146            }
   2147            if ((rv = WRITE_MMU_EXT_MC_QUEUE_LIST4m(unit, MEM_BLOCK_ANY,
   2148                                    cur_node->index, &qlist4_entry[i])) < 0) {
   2149                 goto clean_up;
   2150            }
   2151 
   2152            cur_node = cur_node->next;
   2153      }
   2154             
   2155 clean_up:
   2156     if (list_array != NULL) {
   2157         sal_free(list_array);
   2158     }
   2159     if (qlist0_entry) {
   2160         sal_free(qlist0_entry);
   2161     }
   2162     if (qlist4_entry) {
   2163         sal_free(qlist4_entry);
   2164     }
   2165     return rv;
   2166 }
   2167 
   2168 int
   2169 _bcm_sb2_ipmc_delete_extq_list(int unit ,int prev_start_ptr, int ipmc_id) 
   2170 {
   2171 
   2172      int new_ipmc_id = 0;
   2173      _bcm_repl_list_info_t *rli_start, *rli_current, *rli_prev;
   2174      if (!prev_start_ptr ) {
   2175          return BCM_E_INTERNAL; 
   2176 
   2177      } 
   2178      rli_start = IPMC_EXTQ_REPL_LIST_INFO(unit);
   2179      rli_prev = NULL;
   2180      for (rli_current = rli_start; rli_current != NULL;
   2181           rli_current = rli_current->next) {
   2182           if (prev_start_ptr == rli_current->index) {
   2183               (rli_current->refcount)--;
   2184               if (rli_current->refcount &&
   2185                      (rli_current->first_ipmc == ipmc_id)) {
   2186                   _bcm_sb2_ipmc_subscriber_find_ipmc(unit, rli_current->index,
   2187                                                                   &new_ipmc_id);
   2188                    rli_current->first_ipmc = new_ipmc_id;
   2189               }
   2190               if (rli_current->refcount == 0) {
   2191                   /* Free these linked list entries */
   2192                   _bcm_sb2_extq_repl_list_free(unit, prev_start_ptr);
   2193                   /* If we have an error, we'll fall out anyway */
   2194                   if (rli_prev == NULL) {
   2195                       IPMC_EXTQ_REPL_LIST_INFO(unit) = rli_current->next;
   2196                   } else {
   2197                       rli_prev->next = rli_current->next;
   2198                   }
   2199                   sal_free(rli_current);
   2200               }
   2201                     break;
   2202           }
   2203           rli_prev = rli_current;
   2204      }
   2205      return BCM_E_NONE;
   2206 }
   2207 
   2208 
   2209 int
   2210 _bcm_sb2_ipmc_subscriber_extq_update(int unit, int ipmc_id, int *qlist_deleted)
   2211                                         
   2212 {
   2213     int     rv = BCM_E_NONE;
   2214     int     list_start_ptr, prev_start_ptr;
   2215     int     alloc_size, extq_hash, last_flag;
   2216     int     queue_count = 0;
   2217     SHR_BITDCL *q_vec = NULL;
   2218     _bcm_ext_q_ipmc_t  *ipmc_node = &_sb2_extq_repl_info[unit]->
   2219         ext_ipmc_list[ipmc_id];
   2220     _bcm_repl_list_info_t *rli_start, *rli_current;
   2221 
   2222     /* Check previous group pointer */
   2223     if ((rv = _sb2_extq_mc_group_ptr(unit, ipmc_id,
   2224                     &prev_start_ptr, 0, 0)) < 0) {
   2225         goto list_update_done;
   2226     }
   2227     alloc_size = SHR_BITALLOCSIZE(IPMC_EXTQ_TOTAL(unit));
   2228     q_vec = sal_alloc(alloc_size, "IPMC extq replication vector");
   2229     if (q_vec == NULL) {
   2230         return BCM_E_MEMORY;
   2231     }
   2232     sal_memset(q_vec, 0, alloc_size);
   2233     if((rv = _bcm_sb2_ipmc_subscriber_qvec_get(unit, ipmc_id, q_vec)) < 0 ) {
   2234         goto list_update_done;
   2235 
   2236     }
   2237     /* Search for list already in table */
   2238     rli_start = IPMC_EXTQ_REPL_LIST_INFO(unit);
   2239 
   2240     extq_hash =
   2241         _shr_crc32b(0, (uint8 *)q_vec, IPMC_EXTQ_TOTAL(unit));
   2242 
   2243     for (rli_current = rli_start; rli_current != NULL;
   2244             rli_current = rli_current->next) {
   2245          if (extq_hash == rli_current->hash) {
   2246              rv = _bcm_sb2_extq_repl_list_compare(unit, ipmc_id,
   2247                     rli_current->first_ipmc);
   2248              if (rv == BCM_E_NOT_FOUND) {
   2249                  continue; /* Not a match */
   2250              } else if (rv < 0) {
   2251                  goto list_update_done; /* Access error */
   2252              } else {
   2253                  break; /* Match */
   2254              }
   2255          }
   2256     }
   2257 
   2258     if (rli_current != NULL) {
   2259         /* Found a match, point to here and increase reference count */
   2260         if (prev_start_ptr == rli_current->index) {
   2261             /* We're already pointing to this list, so done */
   2262             rv = BCM_E_NONE;
   2263             goto list_update_done;
   2264         } else {
   2265             list_start_ptr = rli_current->index;
   2266             queue_count = rli_current->list_size;
   2267         }
   2268     } else {
   2269         /* Not a match, make a new chain */
   2270         rv = _bcm_sb2_subscriber_ipmc_index_validate(unit, ipmc_id); 
   2271         if (rv < 0) {
   2272             if (prev_start_ptr) {
   2273                 _bcm_sb2_ipmc_delete_extq_list(unit, prev_start_ptr, ipmc_id);
   2274                 *qlist_deleted = 1;   
   2275             } 
   2276             rv = _bcm_sb2_subscriber_ipmc_index_validate(unit, ipmc_id); 
   2277             if ( rv < 0 ) {
   2278                 goto list_update_done; 
   2279             }
   2280         }
   2281         if ((rv = _bcm_sb2_extq_repl_list_write(unit, ipmc_id , 
   2282                         &list_start_ptr,
   2283                         &queue_count)) < 0 ) {
   2284             goto list_update_done;
   2285         }
   2286 
   2287         if (queue_count > 0) {
   2288             /* Update data structures */
   2289             alloc_size = sizeof(_bcm_repl_list_info_t);
   2290             rli_current = sal_alloc(alloc_size, "IPMC extq repl list info");
   2291             if (rli_current == NULL) {
   2292                 /* Release list */
   2293                 _bcm_sb2_extq_repl_list_free(unit, list_start_ptr);
   2294                 rv = BCM_E_MEMORY;
   2295                 goto list_update_done;
   2296             }
   2297             sal_memset(rli_current, 0, alloc_size);
   2298             rli_current->index = list_start_ptr;
   2299             rli_current->hash = extq_hash;
   2300             rli_current->next = rli_start;
   2301             rli_current->list_size = queue_count;
   2302             rli_current->first_ipmc = ipmc_id;
   2303             IPMC_EXTQ_REPL_LIST_INFO(unit) = rli_current;
   2304             rli_start = rli_current;
   2305         }
   2306     } 
   2307     last_flag = (queue_count == 1);
   2308 
   2309     if (queue_count > 0) {
   2310         if ((rv = _sb2_extq_mc_group_ptr(unit, ipmc_id, 
   2311                         &list_start_ptr, last_flag, 1)) < 0) {
   2312             if (rli_current->refcount == 0) {
   2313                 /* This was new */
   2314                 _bcm_sb2_extq_repl_list_free(unit, list_start_ptr);
   2315                 IPMC_EXTQ_REPL_LIST_INFO(unit) = rli_current->next;
   2316                 sal_free(rli_current);
   2317             }
   2318             goto list_update_done;
   2319         }
   2320 
   2321         (rli_current->refcount)++;
   2322         ipmc_node->list_start_index = list_start_ptr;            
   2323         /* we don't need this rli_current anymore */
   2324     } else if (prev_start_ptr != 0) {
   2325         list_start_ptr = 0;
   2326         if ((rv = _sb2_extq_mc_group_ptr(unit, ipmc_id,
   2327                         &list_start_ptr, last_flag, 1)) < 0) {
   2328             goto list_update_done;
   2329         }
   2330     }
   2331     IPMC_EXTQ_REPL_QUEUE_COUNT(unit, ipmc_id) = queue_count;
   2332     if (!(*qlist_deleted)) { 
   2333         _bcm_sb2_ipmc_delete_extq_list(unit, prev_start_ptr, ipmc_id);
   2334     }
   2335 
   2336 list_update_done:
   2337     if (q_vec != NULL) {
   2338         sal_free(q_vec);
   2339     }
   2340     return rv;
   2341 
   2342 }
   2343 
   2344 int
   2345 _bcm_sb2_ipmc_subscriber_qvec_get(int unit, int ipmc_id, 
   2346                                   SHR_BITDCL *q_vec)
   2347 {
   2348     _bcm_ext_q_ipmc_t  *ipmc_node = &_sb2_extq_repl_info[unit]->
   2349                                         ext_ipmc_list[ipmc_id];
   2350     _bcm_ext_repl_q_list_t *startq; 
   2351     
   2352     for (startq = ipmc_node->first_q_ptr; startq;
   2353                           startq = startq->next) {
   2354          SHR_BITSET(q_vec, startq->queue_id);
   2355     }
   2356     return BCM_E_NONE ; 
   2357 }
   2358 
   2359 
   2360 int
   2361 _bcm_sb2_ipmc_update_queue_hash(int unit, int ipmc_id) 
   2362 {
   2363 
   2364     _bcm_ext_q_ipmc_t  *ipmc_node = &_sb2_extq_repl_info[unit]->
   2365                                            ext_ipmc_list[ipmc_id];
   2366     int alloc_size = 0;  
   2367     int rv = 0 ; 
   2368     SHR_BITDCL *q_vec = NULL;
   2369 
   2370     alloc_size = SHR_BITALLOCSIZE(IPMC_EXTQ_TOTAL(unit));
   2371     q_vec = sal_alloc(alloc_size, "IPMC extq replication vector");
   2372     if (q_vec == NULL) {
   2373         return BCM_E_MEMORY;
   2374     }
   2375     sal_memset(q_vec, 0, alloc_size);
   2376     if ((rv = _bcm_sb2_ipmc_subscriber_qvec_get(unit, ipmc_id, q_vec)) < 0 ) {
   2377          goto clean_up; 
   2378 
   2379     }
   2380     ipmc_node->queue_hash =  
   2381                _shr_crc32b(0, (uint8 *)q_vec, IPMC_EXTQ_TOTAL(unit));
   2382 clean_up :
   2383     if (q_vec != NULL) {
   2384         sal_free(q_vec);
   2385     }
   2386     return rv;
   2387 }
   2388 
   2389 int
   2390 _bcm_sb2_ipmc_subscriber_queue_node_get(int unit, int ipmc_id, 
   2391                                         int queue_id,
   2392                                         _bcm_ext_repl_q_list_t **queue_node) 
   2393 {
   2394     _bcm_ext_q_ipmc_t  *ipmc_node = &_sb2_extq_repl_info[unit]->
   2395                                          ext_ipmc_list[ipmc_id];
   2396     _bcm_ext_repl_q_list_t *startq; 
   2397 
   2398     if (!queue_node) { 
   2399         return BCM_E_INTERNAL;  
   2400     }
   2401     *queue_node = NULL ; 
   2402     for (startq = ipmc_node->first_q_ptr ; startq;
   2403                           startq = startq->next) {
   2404          if (queue_id == startq->queue_id ) {
   2405              *queue_node = startq ; 
   2406               break ; 
   2407          }
   2408     }
   2409     return BCM_E_NONE ;
   2410 }
   2411 
   2412 int
   2413 _bcm_sb2_ipmc_subscriber_add_queue_node(int unit, int ipmc_id, int queue_id,  
   2414                                     _bcm_ext_repl_q_list_t *queue_node) 
   2415 
   2416 {
   2417     _bcm_ext_q_ipmc_t  *ipmc_node  = &_sb2_extq_repl_info[unit]->
   2418                                                   ext_ipmc_list[ipmc_id];
   2419     
   2420     if (!queue_node) {
   2421         return BCM_E_INTERNAL; 
   2422     }
   2423     if (!ipmc_node->first_q_ptr) {
   2424         ipmc_node->first_q_ptr = queue_node ;
   2425         ipmc_node->last_q_ptr = queue_node ;
   2426     } else {
   2427         ipmc_node->last_q_ptr->next = queue_node ;
   2428         ipmc_node->last_q_ptr = queue_node ;
   2429     }
   2430     queue_node->queue_id = queue_id; 
   2431     _bcm_sb2_ipmc_update_queue_hash(unit, ipmc_id ) ;
   2432     return BCM_E_NONE; 
   2433 
   2434 }
   2435 int
   2436 _bcm_sb2_ipmc_subscriber_nexthop_node_get(int unit, int encap_id, 
   2437                                           _bcm_ext_repl_q_list_t *queue_node,
   2438                                           _bcm_ext_nh_list_t **nh_node) 
   2439 {
   2440     _bcm_ext_nh_list_t *startnh; 
   2441 
   2442     if (!queue_node) {
   2443         return BCM_E_INTERNAL; 
   2444 
   2445     }
   2446     if(!nh_node) {  
   2447        return BCM_E_INTERNAL; 
   2448     }
   2449 
   2450     *nh_node = NULL; 
   2451     for (startnh = queue_node->first_nh_ptr; startnh ; startnh=startnh->next) {
   2452         if (startnh->encap_id == encap_id) {
   2453             *nh_node = startnh;
   2454             break;  
   2455         }
   2456     }
   2457     return BCM_E_NONE;
   2458 }
   2459 
   2460 int
   2461  _bcm_sb2_ipmc_update_nh_hash(int unit, _bcm_ext_repl_q_list_t *queue_node) 
   2462 
   2463  {
   2464 
   2465     _bcm_ext_nh_list_t *startnh; 
   2466     int partition = 0 ; 
   2467     SHR_BITDCL *intf_vec = NULL;
   2468     int alloc_size = 0; 
   2469     int rv = 0; 
   2470 
   2471     if (!queue_node) {
   2472         rv = BCM_E_INTERNAL;
   2473         goto clean_up; 
   2474     }
   2475     alloc_size =  REPL_INTF_TOTAL(unit); 
   2476     intf_vec = sal_alloc(alloc_size, "Repl interface vector");
   2477     if (intf_vec == NULL) {
   2478         rv = BCM_E_MEMORY;
   2479         goto clean_up;
   2480     }
   2481     sal_memset(intf_vec, 0, alloc_size);
   2482 
   2483     partition = soc_mem_index_count(unit, EGR_L3_INTFm);
   2484     for (startnh = queue_node->first_nh_ptr; startnh ;
   2485                                startnh = startnh->next) {
   2486          if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, startnh->encap_id) &&
   2487              (uint32)(startnh->encap_id) > partition) {
   2488              rv = BCM_E_PARAM;
   2489              goto clean_up;
   2490          }
   2491          if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, startnh->encap_id)) {
   2492              /* L3 interface is used */
   2493              SHR_BITSET(intf_vec,startnh->encap_id);
   2494          } else {
   2495              /* Next hop is used */
   2496              SHR_BITSET(intf_vec, partition  + startnh->encap_id -
   2497                               BCM_XGS3_DVP_EGRESS_IDX_MIN(unit));
   2498          }
   2499     }
   2500     queue_node->repl_hash = 
   2501            _shr_crc32b(0, (uint8 *)intf_vec, alloc_size); 
   2502  clean_up: 
   2503     if (intf_vec != NULL) {
   2504         sal_free(intf_vec);
   2505     }
   2506     return rv; 
   2507 
   2508 }
   2509 
   2510 
   2511 int
   2512  _bcm_ipmc_subscriber_update_nh_node(int unit, int ipmc_id, 
   2513                                      _bcm_ext_repl_q_list_t *queue_node,
   2514                                      _bcm_ext_nh_list_t *nh_node,
   2515                                       int encap_id)
   2516 {
   2517 
   2518     _bcm_ext_q_ipmc_t  *ipmc_node = &_sb2_extq_repl_info[unit]->
   2519                                        ext_ipmc_list[ipmc_id];  
   2520     if (!queue_node || !nh_node) {
   2521         return BCM_E_INTERNAL; 
   2522     }
   2523     if (queue_node->first_nh_ptr) { 
   2524         queue_node->last_nh_ptr->next = nh_node ; 
   2525         queue_node->last_nh_ptr =nh_node ;
   2526     } else { 
   2527         queue_node->first_nh_ptr = nh_node ; 
   2528         queue_node->last_nh_ptr = nh_node ;  
   2529     }
   2530     queue_node->repl_count++;
   2531     ipmc_node->repl_count++;
   2532     nh_node->encap_id = encap_id; 
   2533     _bcm_sb2_ipmc_update_nh_hash(unit, queue_node) ; 
   2534 
   2535      return BCM_E_NONE;
   2536 }
   2537 
   2538 
   2539 int
   2540 _bcm_sb2_ipmc_subscriber_remove_nh_node(int unit, int ipmc_id, 
   2541                                         _bcm_ext_repl_q_list_t *queue_node,
   2542                                        int id) 
   2543 {
   2544 
   2545     _bcm_ext_q_ipmc_t  *ipmc_node = &_sb2_extq_repl_info[unit]->
   2546                                        ext_ipmc_list[ipmc_id];  
   2547     _bcm_ext_nh_list_t *nh_node, *prev_node;
   2548     
   2549     prev_node = NULL;
   2550     if (!queue_node) {
   2551         return BCM_E_INTERNAL; 
   2552     }
   2553     
   2554    for(nh_node = queue_node->first_nh_ptr; nh_node;
   2555                             nh_node = prev_node->next) {
   2556        if (nh_node->encap_id == id) {
   2557            if(!prev_node) {
   2558                queue_node->first_nh_ptr = nh_node->next;
   2559                if (!queue_node->first_nh_ptr) {
   2560                    queue_node->last_nh_ptr = 
   2561                                 queue_node->first_nh_ptr ;
   2562                }
   2563            } else {
   2564              prev_node->next = nh_node->next ; 
   2565              if (queue_node->last_nh_ptr == nh_node ) 
   2566              {
   2567                  queue_node->last_nh_ptr = prev_node;                    
   2568              }
   2569            }
   2570            queue_node->repl_count--;
   2571            ipmc_node->repl_count--;  
   2572            _bcm_sb2_ipmc_update_nh_hash(unit, queue_node );  
   2573            sal_free(nh_node);  
   2574            break ;      
   2575       }
   2576       prev_node = nh_node ; 
   2577 
   2578    }
   2579    return BCM_E_NONE; 
   2580 }
   2581 
   2582 int
   2583 _bcm_sb2_ipmc_subscriber_remove_queue_node(int unit,
   2584                          int ipmc_id, int queue_id) 
   2585 
   2586 {
   2587 
   2588     _bcm_ext_q_ipmc_t  *ipmc_node = &_sb2_extq_repl_info[unit]->
   2589                                      ext_ipmc_list[ipmc_id];  
   2590     _bcm_ext_repl_q_list_t *queue_node, *prev_node; 
   2591     
   2592     prev_node = NULL;
   2593     queue_node = ipmc_node->first_q_ptr; 
   2594 
   2595     for (; queue_node; queue_node = prev_node->next) {
   2596          if (queue_node->queue_id == queue_id) {
   2597              if (queue_node->repl_count) {
   2598                  return BCM_E_INTERNAL; 
   2599              }
   2600              if (!prev_node) {
   2601                  ipmc_node->first_q_ptr = queue_node->next;
   2602                  if (!ipmc_node->first_q_ptr) {
   2603                       ipmc_node->last_q_ptr = 
   2604                                  ipmc_node->first_q_ptr ;
   2605                  }
   2606              } else {
   2607                prev_node->next = queue_node->next; 
   2608                if (ipmc_node->last_q_ptr == queue_node ) {
   2609                    ipmc_node->last_q_ptr = prev_node ;                     
   2610                }
   2611              }
   2612              _bcm_sb2_ipmc_update_queue_hash(unit, ipmc_id);
   2613              sal_free(queue_node);
   2614              break; 
   2615          }
   2616          prev_node = queue_node; 
   2617     }
   2618     return BCM_E_NONE; 
   2619 }
   2620 
   2621 
   2622 int
   2623 _bcm_sb2_ipmc_subscriber_egress_intf_get(int unit, int ipmc_id, int if_max,
   2624                                          bcm_gport_t *port_array,
   2625                                          bcm_if_t *if_array,
   2626                                          bcm_gport_t *subs_array,
   2627                                          int *count)
   2628 {
   2629 
   2630 
   2631     _bcm_ext_q_ipmc_t  *ipmc_node = &_sb2_extq_repl_info[unit]->
   2632                                            ext_ipmc_list[ipmc_id];  
   2633     _bcm_ext_repl_q_list_t *queue_node; 
   2634     _bcm_ext_nh_list_t *nh_node; 
   2635     int repl_count = 0 ;
   2636     int intf_max = IPMC_EXTQ_REPL_MAX(unit);;   
   2637     BCM_IF_ERROR_RETURN(_bcm_kt2_init_check(unit, ipmc_id));
   2638     if (if_max <= 0 ) {
   2639         return BCM_E_PARAM;
   2640     }
   2641 
   2642     for (queue_node = ipmc_node->first_q_ptr;
   2643          queue_node; queue_node = queue_node->next) {
   2644          for (nh_node = queue_node->first_nh_ptr ; 
   2645               nh_node; nh_node = nh_node->next) {
   2646               if_array[repl_count] = nh_node->encap_id;
   2647               subs_array[repl_count] = queue_node->queue_id; 
   2648               repl_count++; 
   2649               if (repl_count == intf_max) {
   2650                   goto intf_get_done;                         
   2651               }
   2652          }
   2653     }
   2654 intf_get_done: 
   2655     *count = repl_count ;  
   2656     return BCM_E_NONE;     
   2657 }
   2658 
   2659 
   2660 /*
   2661  * Function:
   2662  *   _bcm_sb2_ipmc_subscriber_egress_intf_add     
   2663  * Purpose:
   2664  *     Adds the given encapid to the given queue in the given ipmc  
   2665  * Parameters:
   2666  *      unit     - SOC unit #
   2667  *      ipmc_id   - ipmc_id 
   2668  *      port     - physical port
   2669  *      id       - next hop encap id 
   2670  *      subscriber_queue - queue where replication need to happen
   2671  *      is_l3    - set to true if its a l3 replication
   2672  *      queue_count - replication count for the ipmc 
   2673  *      qcount_increases - set to true if the replication count has changed
   2674  * Returns:
   2675  *      BCM_E_XXX
   2676  */
   2677 int
   2678 _bcm_sb2_ipmc_subscriber_egress_intf_add(int unit, int ipmc_id,
   2679                                         bcm_port_t port, 
   2680                                         int id,
   2681                                         bcm_gport_t subscriber_queue,
   2682                                         int is_l3,
   2683                                         int *queue_count,
   2684                                         int *q_count_increased
   2685                                         )
   2686 {
   2687     _bcm_ext_repl_q_list_t *queue_node; 
   2688     _bcm_ext_nh_list_t *nh_node ; 
   2689     int queue_found = 0;
   2690     int queue_id = 0;
   2691     int qlist_deleted = 0; 
   2692     int rv  = 0 ;
   2693     int list_start_ptr = 0 ;
   2694     int encap_id = 0 ;
   2695     _bcm_ext_q_ipmc_t  *ipmc_node = &_sb2_extq_repl_info[unit]->
   2696                                            ext_ipmc_list[ipmc_id];  
   2697     REPL_PORT_CHECK(unit, port);
   2698     BCM_IF_ERROR_RETURN(_bcm_kt2_init_check(unit, ipmc_id));
   2699      
   2700     if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, id)) {
   2701         /* L3 interface is used */
   2702          encap_id = id + IPMC_SB2_EGRESS_ID_MIN ;
   2703     } else {
   2704     /* Next hop is used */
   2705          encap_id =   id  -
   2706             BCM_XGS3_DVP_EGRESS_IDX_MIN(unit) + IPMC_SB2_NHOP_ID_MIN;
   2707     }
   2708     if (encap_id > IPMC_SB2_REPLICATION_INDEX_MAX) { 
   2709         return BCM_E_PORT;  
   2710     }
   2711     if ((rv = _bcm_kt2_cosq_index_resolve(unit,  subscriber_queue, 0,
   2712                                 _BCM_KT2_COSQ_INDEX_STYLE_QUEUE_REPLICATION,
   2713                                 NULL,  &queue_id, NULL)) < 0) {
   2714           return rv;  
   2715     }
   2716 
   2717     BCM_IF_ERROR_RETURN (
   2718     _bcm_sb2_ipmc_subscriber_queue_node_get( unit, ipmc_id, 
   2719                                                  queue_id, &queue_node));    
   2720     if (queue_node)  { 
   2721         queue_found = 1 ;
   2722     } else { 
   2723        queue_node = sal_alloc(sizeof(_bcm_ext_repl_q_list_t), 
   2724                      "IPMC extended replication queue node ");
   2725        if (!queue_node) { 
   2726             return BCM_E_MEMORY; 
   2727        }
   2728        sal_memset(queue_node, 0, sizeof(_bcm_ext_repl_q_list_t));
   2729     }
   2730     if (!queue_found ) {
   2731         _bcm_sb2_ipmc_subscriber_add_queue_node(unit, ipmc_id, queue_id, 
   2732                                                              queue_node);
   2733     }
   2734     if (IS_EXT_MEM_PORT(unit, port)) {
   2735         queue_node->buf_type = 1; 
   2736     } 
   2737     rv = _bcm_sb2_ipmc_subscriber_nexthop_node_get(unit, id, queue_node,
   2738                                                            &nh_node);
   2739     if (rv < 0 ) { 
   2740         goto cleanup; 
   2741     }
   2742     if (nh_node ) {
   2743         /* nhop is already present just return */ 
   2744         return BCM_E_EXISTS ;   
   2745 
   2746     }
   2747     else { 
   2748        nh_node = sal_alloc(sizeof(_bcm_ext_nh_list_t),
   2749                    "IPMC extended replication ");
   2750 
   2751        if (!nh_node) { 
   2752           rv = BCM_E_MEMORY;
   2753           goto cleanup ;  
   2754        }
   2755        sal_memset(nh_node, 0, sizeof(_bcm_ext_nh_list_t));
   2756        _bcm_ipmc_subscriber_update_nh_node(unit, ipmc_id, queue_node, 
   2757                                                        nh_node, id);
   2758     }
   2759 
   2760     rv = _bcm_sb2_ipmc_subscriber_extq_update( unit, ipmc_id, 
   2761                                               &qlist_deleted);
   2762     if (rv < 0) {  
   2763         goto cleanup; 
   2764     } 
   2765     *q_count_increased = 1;
   2766     *queue_count = ipmc_node->repl_count;
   2767     return BCM_E_NONE; 
   2768 cleanup :
   2769    if (nh_node) { 
   2770        _bcm_sb2_ipmc_subscriber_remove_nh_node(unit, ipmc_id, queue_node, id);  
   2771    }
   2772    if (!queue_found)
   2773    {
   2774        _bcm_sb2_ipmc_subscriber_remove_queue_node(unit, ipmc_id, queue_id);  
   2775    }
   2776    if (qlist_deleted) {
   2777        list_start_ptr = 0;
   2778        _sb2_extq_mc_group_ptr(unit, ipmc_id,
   2779                         &list_start_ptr, 0, 1) ;
   2780        qlist_deleted = 0 ; 
   2781        _bcm_sb2_ipmc_subscriber_extq_update( unit, ipmc_id, 
   2782                                               &qlist_deleted);
   2783    }
   2784    return rv ; 
   2785 }
   2786 STATIC int
   2787 _bcm_sb2_ipmc_subscriber_egress_cleanup(int unit, int ipmc_id, int id,
   2788                                     int queue_removed, int nh_removed,
   2789                                     _bcm_ext_repl_q_list_t *queue_node, 
   2790                                     int queue_id ) 
   2791 {
   2792     _bcm_ext_nh_list_t *nh_node ;
   2793     bcm_port_t temp_port ; 
   2794     if (queue_removed) { 
   2795         queue_node = sal_alloc(sizeof(_bcm_ext_repl_q_list_t), 
   2796                 "IPMC extended replication queue node ");
   2797         if (!queue_node) { 
   2798             return BCM_E_MEMORY; 
   2799         }
   2800         sal_memset(queue_node, 0, sizeof(_bcm_ext_repl_q_list_t));
   2801         _bcm_sb2_ipmc_subscriber_add_queue_node(unit, ipmc_id,queue_id, queue_node);
   2802   
   2803         BCM_IF_ERROR_RETURN(bcm_kt2_cosq_port_get(unit, queue_id, &temp_port));
   2804         if (IS_EXT_MEM_PORT(unit, temp_port)) {
   2805             queue_node->buf_type = 1; 
   2806         } 
   2807     }
   2808     if (nh_removed) {
   2809         nh_node = sal_alloc(sizeof(_bcm_ext_nh_list_t), "IPMC extended replication" 
   2810                 "replication node ");
   2811         if(!nh_node ) { 
   2812             return BCM_E_MEMORY;
   2813 
   2814         }
   2815         sal_memset(nh_node, 0, sizeof(_bcm_ext_nh_list_t));
   2816         _bcm_ipmc_subscriber_update_nh_node(unit, ipmc_id, queue_node, 
   2817                 nh_node, id);
   2818     }
   2819     return BCM_E_NONE;
   2820 } 
   2821 
   2822 int 
   2823 _bcm_sb2_ipmc_subscriber_egress_intf_delete_all(int unit, int ipmc_id,
   2824                                            bcm_port_t *port_array,
   2825                                            int *encap_array,
   2826                                            bcm_if_t *q_array,
   2827                                            int *q_count_increased)
   2828 {
   2829     _bcm_ext_repl_q_list_t *queue_node, *n_queue_node;
   2830     int index = 0;
   2831     int rv = 0;
   2832     int nh_removed = 0;
   2833     int queue_removed = 0;
   2834     int qlist_deleted = 0 ;
   2835     int list_start_ptr = 0;
   2836     _bcm_ext_q_ipmc_t  *ipmc_node = &_sb2_extq_repl_info[unit]->
   2837                                         ext_ipmc_list[ipmc_id];  
   2838 
   2839 
   2840     /*getting the ipmc_node and perform deletion task for all queues */
   2841     queue_node = ipmc_node->first_q_ptr;
   2842     while (queue_node) {
   2843         n_queue_node = queue_node->next;
   2844         rv = _bcm_sb2_ipmc_subscriber_remove_nh_node(unit, ipmc_id, 
   2845                                         queue_node, encap_array[index]); 
   2846         if (rv < 0) {
   2847             if (rv == BCM_E_NOT_FOUND) { 
   2848                 rv = BCM_E_PARAM;
   2849             }  
   2850             return rv;
   2851         }
   2852         nh_removed = 1;
   2853 
   2854         if (!queue_node->repl_count) {
   2855             rv =  _bcm_sb2_ipmc_subscriber_remove_queue_node
   2856                 (unit, ipmc_id, queue_node->queue_id);  
   2857             if (BCM_FAILURE(rv)){
   2858                 _bcm_sb2_ipmc_subscriber_egress_cleanup(unit,ipmc_id,encap_array[index] ,
   2859                         queue_removed, nh_removed,
   2860                         queue_node, queue_node->queue_id);
   2861                 return rv;
   2862             }
   2863             queue_removed = 1 ; 
   2864         }   
   2865         rv = _bcm_sb2_ipmc_subscriber_extq_update(unit, ipmc_id, &qlist_deleted);
   2866         if (BCM_FAILURE(rv)) {
   2867             _bcm_sb2_ipmc_subscriber_egress_cleanup(unit,ipmc_id,encap_array[index] ,
   2868                     queue_removed, nh_removed,
   2869                     queue_node, queue_node->queue_id);
   2870             if (qlist_deleted) {
   2871                 list_start_ptr = 0;
   2872                 _sb2_extq_mc_group_ptr(unit, ipmc_id,
   2873                         &list_start_ptr, 0, 1) ;
   2874                 qlist_deleted = 0 ;        
   2875                 _bcm_sb2_ipmc_subscriber_extq_update(unit, ipmc_id, &qlist_deleted);
   2876             }    
   2877             return rv;
   2878         }
   2879         index++;
   2880         queue_node = n_queue_node;
   2881     }
   2882     *q_count_increased = 1;
   2883     return rv; 
   2884 }
   2885 
   2886 
   2887 /*
   2888  * Function:
   2889  *   _bcm_sb2_ipmc_subscriber_egress_intf_delete    
   2890  * Purpose:
   2891  *     Adds the given encapid to the given queue in the given ipmc  
   2892  * Parameters:
   2893  *      unit     - SOC unit #
   2894  *      ipmc_id   - ipmc_id 
   2895  *      port     - physical port
   2896  *      id       - next hop encap id 
   2897  *      subscriber_queue - queue where replication need to happen
   2898  *      is_l3    - set to true if its a l3 replication
   2899  *      queue_count - replication count for the ipmc 
   2900  *      qcount_increases - set to true if the replication count has changed
   2901  * Returns:
   2902  *      BCM_E_XXX
   2903  */ 
   2904 int
   2905 _bcm_sb2_ipmc_subscriber_egress_intf_delete(int unit, int ipmc_id,
   2906                                         bcm_port_t port, 
   2907                                         int id,
   2908                                         bcm_gport_t subscriber_queue,
   2909                                         int *queue_count,
   2910                                         int *q_count_increased
   2911                                         )
   2912 {
   2913 
   2914     _bcm_ext_repl_q_list_t *queue_node ; 
   2915     _bcm_ext_nh_list_t *nh_node ; 
   2916     int queue_id = 0;
   2917     int rv = 0;
   2918     int nh_removed = 0;
   2919     int queue_removed = 0;
   2920     int qlist_deleted = 0 ;
   2921     int list_start_ptr = 0;
   2922     _bcm_ext_q_ipmc_t  *ipmc_node = &_sb2_extq_repl_info[unit]->
   2923                                            ext_ipmc_list[ipmc_id];  
   2924     REPL_PORT_CHECK(unit, port);
   2925     BCM_IF_ERROR_RETURN(_bcm_kt2_init_check(unit, ipmc_id));
   2926 
   2927     if ((rv = _bcm_kt2_cosq_index_resolve(unit,  subscriber_queue, 0,
   2928                                 _BCM_KT2_COSQ_INDEX_STYLE_QUEUE_REPLICATION,
   2929                                 NULL,  &queue_id, NULL)) < 0) {
   2930           return rv;  
   2931     }
   2932 
   2933     BCM_IF_ERROR_RETURN (
   2934     _bcm_sb2_ipmc_subscriber_queue_node_get( unit , ipmc_id, 
   2935                                                  queue_id, &queue_node));    
   2936     if (!queue_node)  { 
   2937         return BCM_E_NOT_FOUND;
   2938     }
   2939 
   2940     rv = _bcm_sb2_ipmc_subscriber_remove_nh_node(unit, ipmc_id, queue_node, id); 
   2941     if (rv < 0) {
   2942         if (rv == BCM_E_NOT_FOUND) { 
   2943             rv = BCM_E_PARAM;
   2944         }  
   2945         return rv;
   2946     }
   2947     nh_removed = 1 ; 
   2948     if (!queue_node->repl_count) {
   2949         rv =  _bcm_sb2_ipmc_subscriber_remove_queue_node
   2950                  (unit, ipmc_id, queue_id);  
   2951         if (rv < 0) {
   2952             goto clean_up;         
   2953         }
   2954         queue_removed = 1 ; 
   2955     }
   2956     rv = _bcm_sb2_ipmc_subscriber_extq_update(unit, ipmc_id, &qlist_deleted);
   2957     if (rv < 0) {  
   2958         goto clean_up; 
   2959     }
   2960     *q_count_increased = 1;
   2961     *queue_count = ipmc_node->repl_count;
   2962     return BCM_E_NONE; 
   2963 
   2964 clean_up:
   2965     if (queue_removed) { 
   2966         queue_node = sal_alloc(sizeof(_bcm_ext_repl_q_list_t), 
   2967                      "IPMC extended replication queue node ");
   2968         if (!queue_node) { 
   2969             return BCM_E_MEMORY; 
   2970         }
   2971         sal_memset(queue_node, 0, sizeof(_bcm_ext_repl_q_list_t));
   2972         _bcm_sb2_ipmc_subscriber_add_queue_node(unit, ipmc_id,queue_id, queue_node);
   2973         if (IS_EXT_MEM_PORT(unit, port)) {
   2974             queue_node->buf_type = 1; 
   2975         } 
   2976     }
   2977     if (nh_removed) {
   2978         nh_node = sal_alloc(sizeof(_bcm_ext_nh_list_t), "IPMC extended replication" 
   2979                                                               "replication node ");
   2980         if(!nh_node ) { 
   2981            return BCM_E_MEMORY;
   2982 
   2983         }
   2984         sal_memset(nh_node, 0, sizeof(_bcm_ext_nh_list_t));
   2985         _bcm_ipmc_subscriber_update_nh_node(unit, ipmc_id, queue_node, 
   2986                                                        nh_node, id);
   2987     }
   2988     if (qlist_deleted)   {
   2989         list_start_ptr = 0;
   2990         _sb2_extq_mc_group_ptr(unit, ipmc_id,
   2991                         &list_start_ptr, 0, 1) ;
   2992         qlist_deleted = 0 ;        
   2993         _bcm_sb2_ipmc_subscriber_extq_update(unit, ipmc_id, &qlist_deleted);
   2994 
   2995     }
   2996     return rv; 
   2997 }
   2998 
   2999 
   3000 /*
   3001  * Function:
   3002  *   _bcm_sb2_ipmc_subscriber_egress_intf_delete    
   3003  * Purpose:
   3004  *      This is used to recover the software data from hardware
   3005  *      in case of warmboot
   3006  * Parameters:
   3007  *      unit     - SOC unit #
   3008  *      ipmc_id   - ipmc_id 
   3009  *      extq_ptr  - first index in hardware
   3010  *      q_vec     - q_vec for the given ipmc   
   3011  * Returns:
   3012  *      BCM_E_XXX
   3013  */
   3014 int
   3015 _bcm_sb2_recover_subscriber_queue_entries(int unit, int extq_ptr, 
   3016                                      SHR_BITDCL *q_vec, int ipmc_id,
   3017                                      int *q_num)
   3018 {
   3019     int     rv = BCM_E_NONE;
   3020     int     i;
   3021     int     next_ptr1, next_ptr2;
   3022     int     queue_id;
   3023     int     ptr, copy, buf_type=0; 
   3024     mmu_ext_mc_queue_list0_entry_t     qlist0_entry;
   3025     mmu_ext_mc_queue_list1_entry_t     qlist1_entry; 
   3026     mmu_ext_mc_queue_list4_entry_t     qlist4_entry;
   3027     soc_field_t        base_qid[]  = { BASE_QID0f, BASE_QID1f }; 
   3028     soc_field_t        repl_ptr[]  = { L3_REPL_PTR0f, L3_REPL_PTR1f };    
   3029     soc_field_t        l2_copy[]   = { L2_COPY0f, L2_COPY1f };
   3030     soc_field_t        buff_type[]  = { BUFF_TYPE0f, BUFF_TYPE1f };
   3031     soc_field_t   profile_idx[] = { Q_OFFSET_PROF0f, Q_OFFSET_PROF1f };
   3032     _bcm_ext_repl_q_list_t *queue_node = 0; 
   3033     _bcm_ext_nh_list_t *nh_node = 0 ; 
   3034     int queue_not_found = 0 ;
   3035 
   3036     if ((rv = READ_MMU_EXT_MC_QUEUE_LIST0m(unit, MEM_BLOCK_ANY,
   3037                                           extq_ptr, &qlist0_entry)) < 0) {
   3038         goto q_entries_done;
   3039     }
   3040     if (SOC_MEM_IS_VALID(unit, MMU_EXT_MC_QUEUE_LIST1m)) {
   3041         if ((rv = READ_MMU_EXT_MC_QUEUE_LIST1m(unit, MEM_BLOCK_ANY,
   3042                         extq_ptr, &qlist1_entry)) < 0) {
   3043             goto q_entries_done;
   3044         }
   3045     } 
   3046     if ((rv = READ_MMU_EXT_MC_QUEUE_LIST4m(unit, MEM_BLOCK_ANY,
   3047                                           extq_ptr, &qlist4_entry)) < 0) {
   3048         goto q_entries_done;
   3049     }
   3050 
   3051     /* store the content of queue list entries */
   3052     for (i = 0; i < 2; i++) {
   3053         queue_node = 0; 
   3054         nh_node = 0 ;
   3055         queue_not_found = 0; 
   3056         if ((queue_id = soc_MMU_EXT_MC_QUEUE_LIST0m_field32_get(unit, 
   3057                                     &qlist0_entry, base_qid[i])) != 0) {    
   3058             _bcm_sb2_ipmc_subscriber_queue_node_get( unit, ipmc_id,
   3059                                  queue_id, &queue_node);
   3060             if (!queue_node) {
   3061                 queue_not_found = 1;  
   3062                 queue_node = sal_alloc(sizeof(_bcm_ext_repl_q_list_t),
   3063                              "IPMC extended replication queue node ");
   3064                 if (!queue_node) {
   3065                     rv = BCM_E_MEMORY;  
   3066                     goto q_entries_done;
   3067                     
   3068                 }
   3069                 sal_memset(queue_node, 0, sizeof(_bcm_ext_repl_q_list_t));
   3070                  _bcm_sb2_ipmc_subscriber_add_queue_node(unit, ipmc_id, queue_id,
   3071                                                         queue_node); 
   3072             }
   3073             ptr = soc_MMU_EXT_MC_QUEUE_LIST0m_field32_get(unit, &qlist0_entry, 
   3074                                                            repl_ptr[i]);
   3075             if (ptr > IPMC_SB2_NHOP_ID_MIN) {
   3076                  ptr =  (ptr - IPMC_SB2_NHOP_ID_MIN 
   3077                               + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit)) ;
   3078                  
   3079             }
   3080             else { 
   3081                 ptr = ptr - IPMC_SB2_EGRESS_ID_MIN ;                  
   3082             }
   3083 
   3084 
   3085             copy = soc_MMU_EXT_MC_QUEUE_LIST0m_field32_get(unit, &qlist0_entry, 
   3086                                                            l2_copy[i]);
   3087             if (soc_feature(unit, soc_feature_ddr3)) {
   3088                 buf_type = soc_MMU_EXT_MC_QUEUE_LIST0m_field32_get(unit, &qlist0_entry,
   3089                                                             buff_type[i]);
   3090             }
   3091             nh_node = sal_alloc(sizeof(_bcm_ext_nh_list_t), "IPMC extended replication"
   3092                                                                     "replication node ");
   3093             if (!nh_node) {
   3094                 rv = BCM_E_MEMORY;
   3095                 goto q_entries_done ;
   3096             }
   3097             sal_memset(nh_node, 0, sizeof(_bcm_ext_nh_list_t));
   3098             queue_node->l2_copy = copy ;  
   3099             queue_node->buf_type = buf_type ;
   3100             queue_node->profile_id = soc_MMU_EXT_MC_QUEUE_LIST0m_field32_get(unit, &qlist0_entry,
   3101                                                                              profile_idx[i]);
   3102             SHR_BITSET(q_vec, queue_id);
   3103             if (queue_not_found) {
   3104                 (*q_num)++;
   3105             }
   3106             _bcm_ipmc_subscriber_update_nh_node(unit, ipmc_id,
   3107                               queue_node, nh_node, ptr);
   3108 
   3109        }
   3110     }
   3111     next_ptr1 = soc_MMU_EXT_MC_QUEUE_LIST4m_field32_get(unit, 
   3112                                      &qlist4_entry, EXT_Q_NXT_PTR1f);
   3113     next_ptr2 = soc_MMU_EXT_MC_QUEUE_LIST4m_field32_get(unit, 
   3114                                      &qlist4_entry, EXT_Q_NXT_PTR2f);
   3115     
   3116     if (next_ptr1 != extq_ptr) {
   3117         if ((rv = _bcm_sb2_recover_subscriber_queue_entries(unit, next_ptr1, q_vec, 
   3118                                                   ipmc_id, q_num)) < 0) {
   3119             goto q_entries_done;                                                                                                
   3120         }                                                    
   3121     } 
   3122            
   3123     if (next_ptr2 != extq_ptr) {
   3124         if ((rv = _bcm_sb2_recover_subscriber_queue_entries(unit, next_ptr2, q_vec, 
   3125                                                    ipmc_id, q_num)) < 0) {
   3126             goto q_entries_done;                                                                                                        
   3127         }                                                
   3128     }    
   3129     return BCM_E_NONE; 
   3130 
   3131 q_entries_done:
   3132     if (nh_node) {
   3133        sal_free(nh_node);
   3134     }
   3135     if (queue_not_found && queue_node) {
   3136         sal_free(nh_node); 
   3137     }
   3138     return rv;
   3139 }
   3140 
   3141 
   3142 #ifdef BCM_WARM_BOOT_SUPPORT
   3143 STATIC int
   3144 _bcm_sb2_extq_repl_list_get(int unit, int extq_ptr,
   3145                            int *list_ptr, 
   3146                            int *list_num)
   3147 {
   3148     int     rv = BCM_E_NONE;
   3149     int     next_ptr1, next_ptr2;
   3150     mmu_ext_mc_queue_list4_entry_t     qlist4_entry;
   3151     
   3152     if ((rv = READ_MMU_EXT_MC_QUEUE_LIST4m(unit, MEM_BLOCK_ANY,
   3153                                     extq_ptr, &qlist4_entry)) < 0) {
   3154         goto repl_list_get_done;
   3155     }
   3156 
   3157     next_ptr1 = soc_MMU_EXT_MC_QUEUE_LIST4m_field32_get(unit, 
   3158                                      &qlist4_entry, EXT_Q_NXT_PTR1f);
   3159     next_ptr2 = soc_MMU_EXT_MC_QUEUE_LIST4m_field32_get(unit, 
   3160                                      &qlist4_entry, EXT_Q_NXT_PTR2f);
   3161     IPMC_EXTQ_REPL_VE_USED_SET(unit, extq_ptr);
   3162     list_ptr[*list_num] = extq_ptr;
   3163     (*list_num)++;
   3164     
   3165     if (next_ptr1 != extq_ptr) {
   3166         if ((rv = _bcm_sb2_extq_repl_list_get(unit, next_ptr1, list_ptr, 
   3167              list_num)) < 0) {
   3168             goto repl_list_get_done;   
   3169         }                                                    
   3170     } 
   3171            
   3172     if (next_ptr2 != extq_ptr) {
   3173         if ((rv = _bcm_sb2_extq_repl_list_get(unit, next_ptr2, list_ptr,
   3174              list_num)) < 0) {  
   3175             goto repl_list_get_done; 
   3176         }                                                
   3177     }
   3178 
   3179 repl_list_get_done:
   3180     return rv;
   3181 
   3182 }
   3183 
   3184 STATIC int
   3185 _bcm_sb2_extq_repl_reload(int unit, int ipmc_id) 
   3186 {
   3187     SHR_BITDCL *q_vec = NULL;
   3188     int *extq_list_ptr;
   3189     int q_max, q_num = 0;
   3190     int list_max, list_num = 0;
   3191     int alloc_size;
   3192     int rv = BCM_E_NONE;
   3193     int extq_ptr, extq_hash; 
   3194     _bcm_repl_list_info_t *rli_start, *rli_current;
   3195     int list_start_ptr, remap_id;
   3196     int queue_count = 0;
   3197     int queue_id, count = 0;
   3198     bcm_port_t port;
   3199     int list_size = 0;
   3200 
   3201     if ((rv = _bcm_kt_ipmc_mmu_mc_remap_ptr(unit, ipmc_id, 
   3202                     &remap_id, FALSE)) < 0) {
   3203          return rv;                
   3204     }
   3205 
   3206     if ((rv = _sb2_extq_mc_group_ptr(unit, remap_id,
   3207                                 &extq_ptr, 0, 0)) < 0) {
   3208         return rv;
   3209     }
   3210 
   3211     if (extq_ptr == 0) {
   3212         return rv;
   3213     }
   3214     q_max = IPMC_EXTQ_TOTAL(unit);
   3215     rli_start = IPMC_EXTQ_REPL_LIST_INFO(unit);
   3216     if (IPMC_EXTQ_REPL_VE_USED_GET(unit, extq_ptr)) {
   3217         /* We've already traversed this list, just note it */
   3218         for (rli_current = rli_start; rli_current != NULL;
   3219              rli_current = rli_current->next) {
   3220              if (rli_current->index == extq_ptr) {
   3221                  (rli_current->refcount)++;
   3222                  IPMC_EXTQ_REPL_QUEUE_COUNT(unit, ipmc_id) =
   3223                      rli_current->list_size;
   3224                  break;
   3225              }
   3226         }
   3227         if (rli_current == NULL) {
   3228             /* Table out of sync.  Not good. */
   3229             bcm_tr3_ipmc_repl_detach(unit);
   3230             bcm_sb2_ipmc_repl_detach(unit);
   3231             return BCM_E_INTERNAL;
   3232         } else {
   3233             return rv;
   3234         }
   3235     }
   3236 
   3237 
   3238     list_max = IPMC_EXTQ_LIST_TOTAL(unit);
   3239     alloc_size = list_max * sizeof(int);
   3240     extq_list_ptr = sal_alloc(alloc_size, "IPMC extq list array");
   3241     if (extq_list_ptr == NULL) {
   3242         return BCM_E_MEMORY;
   3243     }    
   3244     sal_memset(extq_list_ptr, 0, alloc_size);
   3245     if ((rv = _bcm_sb2_extq_repl_list_get(unit, extq_ptr, extq_list_ptr, 
   3246                                          &list_num)) < 0 ) {
   3247         goto reload_done;
   3248     }    
   3249         
   3250     alloc_size = SHR_BITALLOCSIZE(IPMC_EXTQ_TOTAL(unit));
   3251     q_vec = sal_alloc(alloc_size, "IPMC extq replication vector");
   3252     if (q_vec == NULL) {
   3253         sal_free(extq_list_ptr);
   3254         return BCM_E_MEMORY;
   3255     }
   3256     sal_memset(q_vec, 0, alloc_size);
   3257 
   3258     if ((rv = _bcm_sb2_recover_subscriber_queue_entries(unit, extq_ptr, q_vec, 
   3259                                           ipmc_id, &q_num)) < 0 ) {
   3260         goto reload_done;
   3261     }
   3262     
   3263     if (q_num > q_max) {
   3264         rv = BCM_E_PARAM;
   3265         goto reload_done;
   3266     }
   3267 
   3268     /* Search for list already in table */
   3269     extq_hash =
   3270         _shr_crc32b(0, (uint8 *)q_vec, IPMC_EXTQ_TOTAL(unit));
   3271 
   3272     for (rli_current = rli_start; rli_current != NULL;
   3273          rli_current = rli_current->next) {
   3274          if (extq_hash == rli_current->hash) {
   3275              rv = _bcm_sb2_extq_repl_list_compare(unit, ipmc_id,
   3276                                             rli_current->first_ipmc);
   3277              if (rv == BCM_E_NOT_FOUND) {
   3278                  continue; /* Not a match */
   3279              } else if (rv < 0) {
   3280                  goto reload_done; /* Access error */
   3281              } else {
   3282                  break; /* Match */
   3283              }
   3284         }
   3285     }
   3286 
   3287     if (rli_current != NULL) {
   3288         /* Found a match, point to here and increase reference count */
   3289         if (extq_ptr == rli_current->index) {
   3290             /* We're already pointing to this list, so done */
   3291             rv = BCM_E_NONE;
   3292             goto reload_done;
   3293         } else {
   3294             list_start_ptr = rli_current->index;
   3295             queue_count = rli_current->list_size;  
   3296         }
   3297     } else {
   3298         /* Not a match, make a new chain */
   3299         list_start_ptr = extq_ptr;
   3300         list_size = (q_num % 2) ? ((q_num / 2) + 1) : (q_num / 2);
   3301         queue_count = q_num;
   3302 
   3303         if (queue_count > 0) {
   3304             /* Update data structures */
   3305             alloc_size = sizeof(_bcm_repl_list_info_t);
   3306             rli_current = sal_alloc(alloc_size, "IPMC extq repl list info");
   3307             if (rli_current == NULL) {
   3308                 rv = BCM_E_MEMORY;
   3309                 goto reload_done;
   3310             }
   3311             sal_memset(rli_current, 0, alloc_size);
   3312             rli_current->index = list_start_ptr;
   3313             rli_current->hash = extq_hash;
   3314             rli_current->next = rli_start;
   3315             rli_current->list_size = list_size;
   3316             rli_current->first_ipmc = ipmc_id ;
   3317             IPMC_EXTQ_REPL_LIST_INFO(unit) = rli_current;
   3318             rli_start = rli_current;
   3319             (rli_current->refcount)++;
   3320         }
   3321     }
   3322 
   3323     IPMC_EXTQ_REPL_QUEUE_COUNT(unit, ipmc_id) = list_size;
   3324 
   3325     count = 0;
   3326     for (queue_id = 0; ((queue_id < q_max) && (count < queue_count));
   3327         queue_id++) {
   3328         if (SHR_BITGET(q_vec, queue_id)) {
   3329             count++;
   3330             if ((rv = bcm_kt2_cosq_port_get(unit, queue_id, &port)) < 0) {
   3331                 goto reload_done;
   3332             }
   3333             _bcm_sb2_ipmc_port_ext_queue_count_increment(unit, ipmc_id, port);
   3334         }
   3335     }
   3336 
   3337 reload_done:
   3338     if (extq_list_ptr != NULL) {
   3339         sal_free(extq_list_ptr);
   3340     }    
   3341     if (q_vec != NULL) {
   3342         sal_free(q_vec);
   3343     }
   3344 
   3345     return rv; 
   3346 }
   3347 #endif 
   3348 
   3349 int
   3350 _bcm_sb2_ipmc_subscriber_egress_intf_set(int unit, int ipmc_id,
   3351                                         bcm_port_t port, int if_count, 
   3352                                         int *id,
   3353                                         bcm_gport_t subscriber_queue,
   3354                                         int is_l3,
   3355                                         int *queue_count,
   3356                                         int *q_count_increased) 
   3357 {
   3358 
   3359    int i = 0 ; 
   3360    int rv = 0 ; 
   3361    for (i = 0; i < if_count; i++) 
   3362    {
   3363        rv =  _bcm_sb2_ipmc_subscriber_egress_intf_add(unit, ipmc_id, port,
   3364                                          id[i], subscriber_queue, is_l3,
   3365                                       queue_count, q_count_increased);
   3366        if ( rv < 0) {
   3367             return rv; 
   3368        }
   3369    }
   3370    return BCM_E_NONE; 
   3371 }
   3372 
   3373 
   3374 void _bcm_sb2_ipmc_port_ext_queue_count_increment(int unit,
   3375                                       int ipmc_id, bcm_port_t port)
   3376 {
   3377      if ((IPMC_EXTQ_REPL_PORT_INFO(unit, port) != NULL) &&
   3378          (IPMC_EXTQ_REPL_PORT_INFO(unit, port)->queue_count != NULL)) {
   3379      IPMC_EXTQ_REPL_PORT_QUEUE_COUNT(unit, port, ipmc_id)++;
   3380      }
   3381      if (IS_EXT_MEM_PORT(unit, port)) {
   3382         IPMC_EXTQ_REPL_QUEUE_COUNT_EXT(unit, ipmc_id)++;
   3383      } else {
   3384         IPMC_EXTQ_REPL_QUEUE_COUNT_INT(unit, ipmc_id)++;
   3385      }
   3386      return;
   3387 }
   3388 
   3389 void _bcm_sb2_ipmc_port_ext_queue_count_decrement(int unit,
   3390                                      int ipmc_id, bcm_port_t port)
   3391 {
   3392      if ((IPMC_EXTQ_REPL_PORT_INFO(unit, port) != NULL) &&
   3393          (IPMC_EXTQ_REPL_PORT_INFO(unit, port)->queue_count != NULL)) {
   3394      IPMC_EXTQ_REPL_PORT_QUEUE_COUNT(unit, port, ipmc_id)--;
   3395      }
   3396      if (IS_EXT_MEM_PORT(unit, port)) {
   3397         IPMC_EXTQ_REPL_QUEUE_COUNT_EXT(unit, ipmc_id)--;
   3398      } else {
   3399         IPMC_EXTQ_REPL_QUEUE_COUNT_INT(unit, ipmc_id)--;
   3400      }
   3401      return;
   3402 }
   3403 
   3404 int _bcm_sb2_ipmc_port_ext_queue_count(int unit,
   3405                                       int ipmc_id, bcm_port_t port)
   3406 {
   3407      /* coverity[overrun-local : FALSE] */
   3408      if (SOC_PORT_VALID(unit, port)) {
   3409      return IPMC_EXTQ_REPL_PORT_QUEUE_COUNT(unit, port, ipmc_id);
   3410      } else {
   3411          return BCM_E_PORT;
   3412      }
   3413 }
   3414 
   3415 #endif
   3416 
   3417 #ifdef BCM_KATANA2_SUPPORT
   3418 
   3419 /* Function:
   3420  *      _bcm_kt2_repl_list_tbl_ptr_get
   3421  * Purpose:
   3422  *      Get the appropriate MMU replication tables and intended 
   3423  *      member bitmap last bitmap fields for  for port
   3424  * Parameters:
   3425  *      unit       - StrataSwitch PCI device unit number.
   3426  *      port       - (IN) port. 
   3427  *      info       - (OUT) MMU group table info 
   3428 *                     mem, pbmp, index corresponding to the port.
   3429  * Returns:
   3430  *      BCM_E_XXX
   3431  */
   3432 STATIC int
   3433 _bcm_kt2_repl_list_tbl_ptr_get(int unit, bcm_port_t port,
   3434                                _kt2_repl_grp_info_t *info)
   3435 {
   3436 #ifdef BCM_SABER2_SUPPORT
   3437     if (soc_mem_field_valid(unit, MMU_REPL_GRP_TBL0m, MEMBER_BMP_PORTSf)) {
   3438         /* saber2 */
   3439         return (_bcm_sb2_repl_list_tbl_ptr_get (unit, port, info));
   3440     }
   3441 #endif
   3442 #ifdef BCM_METROLITE_SUPPORT
   3443     if (SOC_IS_METROLITE(unit)) {
   3444         return _bcm_metrolite_repl_list_tbl_ptr_get(unit, port, info);
   3445     }
   3446 #endif
   3447     if (info == NULL)
   3448     {
   3449        return BCM_E_PARAM;
   3450     }
   3451     if ((port >= 0) && (port < 70))
   3452     {
   3453         info->mb_mem =  MMU_REPL_GRP_TBL0m;
   3454         info->mbmp = MEMBER_BMP_PORTS_119_0f;
   3455         info->lb_mem = MMU_REPL_GRP_TBL1m;
   3456         info->lbmp =  LAST_BMP_PORTS_69_0f;
   3457         info->mb_index = port;
   3458         info->lb_index = port;
   3459     } else if ((port >= 70) && (port < 120)) {
   3460         info->mb_mem =  MMU_REPL_GRP_TBL0m;
   3461         info->mbmp = MEMBER_BMP_PORTS_119_0f;
   3462         info->lb_mem = MMU_REPL_GRP_TBL2m;
   3463         info->lbmp =  LAST_BMP_PORTS_169_70f;
   3464         info->mb_index = port;
   3465         info->lb_index = port - 70;
   3466     } else if ((port >= 120) && (port < 170)) {
   3467         info->mb_mem =  MMU_REPL_GRP_TBL1m;
   3468         info->mbmp = MEMBER_BMP_PORTS_169_120f;
   3469         info->lb_mem = MMU_REPL_GRP_TBL2m;
   3470         info->lbmp =  LAST_BMP_PORTS_169_70f;
   3471         info->mb_index = port - 120;
   3472         info->lb_index = port - 70;
   3473     }
   3474 
   3475     return BCM_E_NONE;
   3476 }
   3477 
   3478 /* Function:
   3479  *      _bcm_kt2_repl_group_info_set
   3480  * Purpose:
   3481  *      Set replication group info.
   3482  * Parameters:
   3483  *      unit       - StrataSwitch PCI device unit number.
   3484  *      repl_group - (IN) The replication group number.
   3485  *      port       - (IN) port.
   3486  *      mbmp       - (IN) Member bitmap.
   3487  *      lbmp       - (IN) Last Member bitmap.
   3488  *      head_index - (IN) Base pointer to REPL_HEAD table.
   3489  * Returns:
   3490  *      BCM_E_XXX
   3491  */
   3492 STATIC int
   3493 _bcm_kt2_repl_group_info_set(int unit, int repl_group, bcm_port_t port,
   3494         soc_pbmp_t mbmp, soc_pbmp_t lbmp, int head_index)
   3495 {
   3496 
   3497     mmu_repl_grp_tbl0_entry_t repl_grp_tbl0_entry;
   3498     mmu_repl_grp_tbl1_entry_t repl_grp_tbl1_entry;
   3499     mmu_repl_grp_tbl2_entry_t repl_grp_tbl2_entry;
   3500     _kt2_repl_grp_info_t kt2_repl_grp_info;
   3501     int member_bitmap_width0;
   3502     int member_bitmap_width1;
   3503     soc_pbmp_t member_bitmap0, member_bitmap1;
   3504     uint32 fldbuf[SOC_PBMP_WORD_MAX];
   3505     int i;
   3506 
   3507 #ifdef BCM_SABER2_SUPPORT
   3508     if (soc_mem_field_valid(unit, MMU_REPL_GRP_TBL0m, MEMBER_BMP_PORTSf)) {
   3509         /* saber2 */
   3510         return (_bcm_sb2_repl_group_info_set(unit, 
   3511                     repl_group, port, mbmp,
   3512                     lbmp, head_index)); 
   3513     }
   3514 #endif
   3515 #ifdef BCM_METROLITE_SUPPORT
   3516     if (SOC_IS_METROLITE(unit)) {
   3517         return (_bcm_metrolite_repl_group_info_set(unit,
   3518                     repl_group, port, mbmp,
   3519                     lbmp, head_index));
   3520     }
   3521 #endif
   3522     sal_memset(&repl_grp_tbl0_entry, 0, sizeof(repl_grp_tbl0_entry));
   3523     sal_memset(&repl_grp_tbl1_entry, 0, sizeof(repl_grp_tbl1_entry));
   3524     sal_memset(&repl_grp_tbl2_entry, 0, sizeof(repl_grp_tbl2_entry));
   3525     sal_memset(&kt2_repl_grp_info, 0, sizeof(kt2_repl_grp_info));
   3526 
   3527     BCM_IF_ERROR_RETURN(_bcm_kt2_repl_list_tbl_ptr_get (unit, port,
   3528                &kt2_repl_grp_info));
   3529      
   3530     member_bitmap_width0 =  soc_mem_field_length(unit,
   3531                 MMU_REPL_GRP_TBL0m, MEMBER_BMP_PORTS_119_0f);
   3532 
   3533     member_bitmap_width1 =  soc_mem_field_length(unit,
   3534                 MMU_REPL_GRP_TBL1m, MEMBER_BMP_PORTS_169_120f);
   3535 
   3536     sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   3537 
   3538     for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   3539         fldbuf[i] = SOC_PBMP_WORD_GET(lbmp, i);
   3540     }
   3541     if (port >=70) {
   3542         soc_mem_field_set(unit, kt2_repl_grp_info.lb_mem,
   3543            (uint32 *)&repl_grp_tbl2_entry, kt2_repl_grp_info.lbmp, fldbuf);
   3544     } else {
   3545         soc_mem_field_set(unit, kt2_repl_grp_info.lb_mem,
   3546             (uint32 *)&repl_grp_tbl1_entry, kt2_repl_grp_info.lbmp, fldbuf);
   3547     }
   3548 
   3549     soc_MMU_REPL_GRP_TBL2m_field32_set(unit, &repl_grp_tbl2_entry,
   3550                         BASE_PTRf, head_index);
   3551 
   3552     SOC_PBMP_CLEAR(member_bitmap0);
   3553     for (i = 0; i < member_bitmap_width0; i++) {
   3554         if (SOC_PBMP_MEMBER(mbmp, i)) {
   3555             SOC_PBMP_PORT_ADD(member_bitmap0, i);
   3556         }
   3557     }
   3558 
   3559     sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   3560     for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   3561         fldbuf[i] = SOC_PBMP_WORD_GET(member_bitmap0, i);
   3562     }
   3563 
   3564     soc_MMU_REPL_GRP_TBL0m_field_set(unit, &repl_grp_tbl0_entry,
   3565             MEMBER_BMP_PORTS_119_0f, fldbuf);
   3566 
   3567     SOC_PBMP_CLEAR(member_bitmap1);
   3568     for (i = member_bitmap_width0;
   3569          i < (member_bitmap_width0 + member_bitmap_width1);
   3570          i++) {
   3571         if (SOC_PBMP_MEMBER(mbmp, i)) {
   3572             SOC_PBMP_PORT_ADD(member_bitmap1, (i - member_bitmap_width0));
   3573         }
   3574     }
   3575 
   3576     sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   3577     for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   3578         fldbuf[i] = SOC_PBMP_WORD_GET(member_bitmap1, i);
   3579     }
   3580 
   3581     soc_MMU_REPL_GRP_TBL1m_field_set(unit, &repl_grp_tbl1_entry,
   3582             MEMBER_BMP_PORTS_169_120f, fldbuf);
   3583 
   3584     SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_GRP_TBL1m(unit,
   3585                     MEM_BLOCK_ALL, repl_group, &repl_grp_tbl1_entry));
   3586     SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_GRP_TBL2m(unit,
   3587                     MEM_BLOCK_ALL, repl_group, &repl_grp_tbl2_entry));
   3588     SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_GRP_TBL0m(unit,
   3589                     MEM_BLOCK_ALL, repl_group, &repl_grp_tbl0_entry));
   3590 
   3591     return BCM_E_NONE;
   3592 }
   3593 
   3594 #endif /* BCM_KATANA2_SUPPORT*/
   3595 
   3596 /* --------------------------------------------------------------
   3597  * The following set of routines manage replication lists.
   3598  * --------------------------------------------------------------
   3599  */
   3600 /*
   3601  * Function:
   3602  *      bcm_tr3_ipmc_repl_detach
   3603  * Purpose:
   3604  *      Deinitialize replication.
   3605  * Parameters:
   3606  *      unit - SOC unit #
   3607  * Returns:
   3608  *      BCM_E_XXX
   3609  */
   3610 int
   3611 bcm_tr3_ipmc_repl_detach(int unit)
   3612 {
   3613     bcm_port_t          port;
   3614     _bcm_repl_list_info_t *rli_current, *rli_free;
   3615     bcm_pbmp_t            pbmp_all;
   3616 
   3617     BCM_PBMP_CLEAR(pbmp_all);
   3618     BCM_PBMP_ASSIGN(pbmp_all, PBMP_ALL(unit));
   3619 
   3620 #if defined(BCM_KATANA2_SUPPORT)
   3621     if (soc_feature(unit, soc_feature_linkphy_coe) ||
   3622         soc_feature(unit, soc_feature_subtag_coe)) {
   3623         _bcm_kt2_subport_pbmp_update(unit, &pbmp_all);
   3624     }
   3625     if (SOC_IS_KATANA2(unit)) {
   3626         BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update (unit, &pbmp_all));
   3627         BCM_IF_ERROR_RETURN(bcm_kt_ipmc_repl_detach(unit));
   3628     }
   3629 #endif
   3630 
   3631     if (_tr3_repl_info[unit] != NULL) {
   3632         PBMP_ITER(pbmp_all, port) {
   3633             /* Coverity issue ignored:
   3634              * Maximum port number used in PBMP_PORT_ALL
   3635              * should never exceed SOC_MAX_NUM_PP_PORTS */
   3636             /* coverity[overrun-local : FALSE] */
   3637             if (_tr3_repl_info[unit]->port_info[port] != NULL) {
   3638                 if (_tr3_repl_info[unit]->
   3639                         port_info[port]->intf_count != NULL) {
   3640                     sal_free(_tr3_repl_info[unit]->
   3641                             port_info[port]->intf_count);
   3642                 }
   3643                 sal_free(_tr3_repl_info[unit]->port_info[port]);
   3644             }
   3645         }
   3646 
   3647         if (_tr3_repl_info[unit]->repl_list_info != NULL) {
   3648             rli_current = _tr3_repl_info[unit]->repl_list_info;
   3649             while (rli_current != NULL) {
   3650                 rli_free = rli_current;
   3651                 rli_current = rli_current->next;
   3652                 sal_free(rli_free);
   3653             }
   3654         }
   3655 
   3656         if (_tr3_repl_info[unit]->l3_intf_next_hop_ipmc != NULL) {
   3657             sal_free(_tr3_repl_info[unit]->l3_intf_next_hop_ipmc);
   3658         }
   3659         if (_tr3_repl_info[unit]->l3_intf_next_hop_trill != NULL) {
   3660             sal_free(_tr3_repl_info[unit]->l3_intf_next_hop_trill);
   3661         }
   3662 
   3663         sal_free(_tr3_repl_info[unit]);
   3664         _tr3_repl_info[unit] = NULL;
   3665     }
   3666 
   3667     _bcm_tr3_repl_head_info_deinit(unit);
   3668     _bcm_tr3_repl_list_entry_info_deinit(unit);
   3669 
   3670 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   3671     if (SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_APACHE(unit)) {
   3672         if (soc_property_get(unit, spn_MULTICAST_PER_TRUNK_REPLICATION, 0)) {
   3673             BCM_IF_ERROR_RETURN(bcm_td2p_aggid_info_detach(unit));
   3674         }
   3675     }
   3676 #endif
   3677 
   3678     return BCM_E_NONE;
   3679 }
   3680 
   3681 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   3682 /*
   3683  * Function:
   3684  *      _bcm_td2p_repl_port_agg_map_init
   3685  * Purpose:
   3686  *      Initialize L3MC Port Agg Map.
   3687  *      From Trident 2 Plus MMU uArch Spec Chapter 5. TD2PLUS MMU - L3MC Replication
   3688  *      Software must initialize this table on boot time.
   3689  *      Software should initialize every L3MC-Port-Agg-ID to be the same
   3690  *      value as the MMU port to retain backward compatibility to Trident2 functionality.
   3691  *      Since L3MC-Port-Agg-ID is used per egress pipe,
   3692  *      the maximum L3MC-Port-Agg-IDs needed matches the
   3693  *      maximum number of ports per pipe which is 53.
   3694  *      Therefore, only the lower six bits are needed for L3MC-Port-Agg-ID by the hardware.
   3695  *      But for registers in the ENQ stage used in cut-through mode,
   3696  *      PIPE_NUM field must be programmed because L3MC-Port-Agg-ID is used for
   3697  *      whole port space.
   3698  * Parameters:
   3699  *      unit - (IN)SOC unit number. 
   3700  * Returns:
   3701  *      BCM_E_xxx
   3702  */
   3703 STATIC int
   3704 _bcm_td2p_repl_port_agg_map_init(int unit)
   3705 {
   3706     soc_info_t *si;
   3707     int phy_port, mmu_port;
   3708     bcm_port_t port;
   3709     uint32 regval;
   3710     int max_ports = 0 ;
   3711     si = &SOC_INFO(unit);
   3712 #ifdef BCM_APACHE_SUPPORT
   3713     if(SOC_IS_APACHE(unit))
   3714     {
   3715         max_ports = 74 ;
   3716     } else 
   3717 #endif 
   3718     {
   3719         max_ports = 64 ;
   3720     }
   3721 
   3722 
   3723     if (soc_property_get(unit, spn_MULTICAST_PER_TRUNK_REPLICATION, 0)) {
   3724         BCM_MC_PER_TRUNK_REPL_MODE(unit) = TRUE;
   3725         BCM_IF_ERROR_RETURN(bcm_td2p_aggid_info_init(unit));
   3726     } else {
   3727         BCM_MC_PER_TRUNK_REPL_MODE(unit) = FALSE;
   3728     }
   3729 
   3730     if (SOC_WARM_BOOT(unit)) {
   3731         return BCM_E_NONE;
   3732     }
   3733     PBMP_ITER(PBMP_ALL(unit), port) {
   3734         if (IS_RDB_PORT(unit, port)) {
   3735             continue;
   3736         }
   3737         /* Coverity issue ignored:
   3738          * Maximum port number used in PBMP_ALL
   3739          * should never exceed SOC_MAX_NUM_PP_PORTS */
   3740         /* coverity[value_overwrite] */
   3741         /* coverity[overrun-local : FALSE] */
   3742 
   3743         phy_port = si->port_l2p_mapping[port];
   3744         mmu_port = si->port_p2m_mapping[phy_port];
   3745 
   3746         /* configure mmu port to repl aggregateId map */
   3747         regval = 0;
   3748         soc_reg_field_set(unit, MMU_TOQ_REPL_PORT_AGG_MAPr, &regval,
   3749                 L3MC_PORT_AGG_IDf,
   3750                 BCM_MC_PER_TRUNK_REPL_MODE(unit) ? TD2P_AGG_ID_HW_INVALID :
   3751                 (mmu_port % max_ports));
   3752         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, MMU_TOQ_REPL_PORT_AGG_MAPr,
   3753                     port,0,regval));
   3754         regval = 0;
   3755         soc_reg_field_set(unit, MMU_ENQ_REPL_PORT_AGG_MAPr, &regval,
   3756                           L3MC_PORT_AGG_IDf,
   3757                           BCM_MC_PER_TRUNK_REPL_MODE(unit) ?
   3758                           TD2P_AGG_ID_HW_INVALID : mmu_port);
   3759         SOC_IF_ERROR_RETURN(soc_reg32_set(unit, MMU_ENQ_REPL_PORT_AGG_MAPr,
   3760                             port, 0, regval));
   3761         regval = 0;
   3762         soc_reg_field_set(unit, MMU_ENQ_LOGICAL_PORT_TO_PORT_AGG_MAPr, &regval,
   3763                           L3MC_PORT_AGG_IDf,
   3764                           BCM_MC_PER_TRUNK_REPL_MODE(unit) ?
   3765                           TD2P_AGG_ID_HW_INVALID : mmu_port);
   3766         SOC_IF_ERROR_RETURN(WRITE_MMU_ENQ_LOGICAL_PORT_TO_PORT_AGG_MAPr(unit,
   3767                             port, regval));
   3768 
   3769     }
   3770 
   3771     return BCM_E_NONE;
   3772 }
   3773 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   3774 
   3775 #ifdef BCM_SABER2_SUPPORT
   3776 int
   3777 bcm_sb2_ipmc_repl_extq_port_alloc(int unit, bcm_port_t port) {
   3778     int alloc_size;
   3779 
   3780     alloc_size = sizeof(_sb2_repl_queue_info_t);
   3781     /* Coverity issue ignored:
   3782      * Maximum port number used in PBMP_PORT_ALL
   3783      * should never exceed SOC_MAX_NUM_PP_PORTS */
   3784     /* coverity[overrun-local : FALSE] */
   3785     if (!IPMC_EXTQ_REPL_PORT_INFO(unit, port)) {      
   3786         IPMC_EXTQ_REPL_PORT_INFO(unit, port) =
   3787             sal_alloc(alloc_size, "IPMC Extq repl port info");
   3788         if (IPMC_EXTQ_REPL_PORT_INFO(unit, port) == NULL) {
   3789             bcm_tr3_ipmc_repl_detach(unit); 
   3790             bcm_sb2_ipmc_repl_detach(unit);
   3791             return BCM_E_MEMORY;
   3792         }
   3793     } 
   3794     sal_memset(IPMC_EXTQ_REPL_PORT_INFO(unit, port), 0, alloc_size);
   3795 
   3796     alloc_size = sizeof(int32) * soc_mem_index_count(unit, L3_IPMCm);
   3797     if (!IPMC_EXTQ_REPL_PORT_INFO(unit, port)->queue_count) { 
   3798         IPMC_EXTQ_REPL_PORT_INFO(unit, port)->queue_count =
   3799             sal_alloc(alloc_size, "IPMC Extq repl port queue count");
   3800         if (IPMC_EXTQ_REPL_PORT_INFO(unit, port)->queue_count == NULL) {
   3801             bcm_tr3_ipmc_repl_detach(unit); 
   3802             bcm_sb2_ipmc_repl_detach(unit);
   3803             return BCM_E_MEMORY;
   3804         }
   3805     }
   3806     sal_memset(IPMC_EXTQ_REPL_PORT_INFO(unit, port)->queue_count,
   3807                                   0, alloc_size);
   3808     return BCM_E_NONE; 
   3809 }
   3810 #endif
   3811 
   3812 /*
   3813  * Function:
   3814  *      _bcm_tr3_ipmc_repl_init
   3815  * Purpose:
   3816  *      Initialize replication.
   3817  * Parameters:
   3818  *      unit - SOC unit #
   3819  * Returns:
   3820  *      BCM_E_XXX
   3821  */
   3822 int
   3823 bcm_tr3_ipmc_repl_init(int unit)
   3824 {
   3825     soc_info_t *si;
   3826     int member_count;
   3827     int phy_port, mmu_port;
   3828     bcm_port_t port;
   3829     int alloc_size;
   3830     int i;
   3831     int rv = BCM_E_NONE;
   3832     soc_pbmp_t member_bitmap;
   3833     int member_bitmap_index;
   3834     uint32 fldbuf[SOC_PBMP_WORD_MAX];
   3835     mmu_repl_group_entry_t repl_group_entry;
   3836     uint32 regval;
   3837     int num_lanes, count_width;
   3838 #ifdef BCM_KATANA2_SUPPORT 
   3839     mmu_repl_map_tbl_entry_t map_entry;
   3840     uint32 pp_port = 0;
   3841     uint32 repl_map_idx_pp = 0;
   3842     uint32 repl_map_port_ct = 0;
   3843     uint32 toq_entry = 0;
   3844 #endif
   3845     bcm_pbmp_t          pbmp_all;
   3846 #ifdef BCM_SABER2_SUPPORT    
   3847     uint32 entry[SOC_MAX_MEM_FIELD_WORDS];
   3848 #endif
   3849     BCM_PBMP_CLEAR (pbmp_all);
   3850     BCM_PBMP_ASSIGN(pbmp_all, PBMP_ALL(unit));
   3851 
   3852 #if defined(BCM_KATANA2_SUPPORT)
   3853     if (soc_feature(unit, soc_feature_linkphy_coe) ||
   3854         soc_feature(unit, soc_feature_subtag_coe)) {
   3855         _bcm_kt2_subport_pbmp_update(unit, &pbmp_all);
   3856     }
   3857     if (SOC_IS_KATANA2(unit)) {
   3858         BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update (unit, &pbmp_all));
   3859     }
   3860 #endif
   3861 
   3862     bcm_tr3_ipmc_repl_detach(unit);
   3863 
   3864     if (NULL == _tr3_repl_info[unit]) {
   3865        _tr3_repl_info[unit] = sal_alloc(sizeof(_tr3_repl_info_t), "repl info");
   3866        if (NULL == _tr3_repl_info[unit]) {
   3867            bcm_tr3_ipmc_repl_detach(unit);
   3868            return BCM_E_MEMORY;
   3869        }
   3870     }
   3871     sal_memset(_tr3_repl_info[unit], 0, sizeof(_tr3_repl_info_t));
   3872 
   3873     _tr3_repl_info[unit]->num_repl_groups = soc_mem_index_count(unit, L3_IPMCm);
   3874 
   3875     if (soc_feature(unit, soc_feature_static_repl_head_alloc)) {
   3876         /* Each replication group is statically allocated a region
   3877          * in REPL_HEAD table. The size of the region depends on the
   3878          * maximum number of valid ports. Thus, the max number of
   3879          * replication groups is limited to number of REPL_HEAD entries
   3880          * divided by the max number of valid ports.
   3881          */
   3882         si = &SOC_INFO(unit);
   3883         member_count = 0;
   3884         PBMP_ITER(SOC_CONTROL(unit)->repl_eligible_pbmp, port) {
   3885         if (SOC_IS_KATANA2(unit)) {
   3886             phy_port = port;
   3887             mmu_port = port;
   3888         } else {
   3889             /* Coverity issue ignored:
   3890              * Maximum port number used in repl_eligible_pbmp
   3891              * should never exceed SOC_MAX_NUM_PP_PORTS */
   3892             /* coverity[value_overwrite] */
   3893             /* coverity[overrun-local : FALSE] */
   3894             phy_port = si->port_l2p_mapping[port];
   3895             mmu_port = si->port_p2m_mapping[phy_port];
   3896         }
   3897             if ((!SOC_IS_KATANA2(unit)) && 
   3898                 ((mmu_port == 57) || (mmu_port == 59) || 
   3899                  (mmu_port == 61) || (mmu_port == 62))) {
   3900                 /* No replication on MMU ports 57, 59, 61 and 62 */
   3901                 continue;
   3902             }
   3903             member_count++;
   3904         }
   3905         if (member_count > 0) {
   3906             _tr3_repl_info[unit]->num_repl_groups =
   3907                 soc_mem_index_count(unit, MMU_REPL_HEAD_TBLm) / member_count;
   3908             if (_tr3_repl_info[unit]->num_repl_groups > 
   3909                     soc_mem_index_count(unit, L3_IPMCm)) {
   3910                 _tr3_repl_info[unit]->num_repl_groups =
   3911                     soc_mem_index_count(unit, L3_IPMCm);
   3912             }
   3913         }
   3914     }
   3915 
   3916     /* The total number of replication interfaces equals to the total
   3917      * number of next hops. Unlike previous XGS3 devices, each L3 inteface
   3918      * will be associated with a next hop index.
   3919      */
   3920 #ifdef BCM_KATANA2_SUPPORT
   3921     if (SOC_IS_KATANA2(unit))
   3922     {
   3923         _tr3_repl_info[unit]->num_intf = 
   3924             (soc_mem_index_count(unit, EGR_L3_NEXT_HOPm) + 
   3925              soc_mem_index_count(unit, EGR_L3_INTFm));
   3926         if (!SOC_IS_SABER2(unit)) {
   3927             rv = bcm_kt2_ipmc_repl_init(unit);
   3928             if (BCM_FAILURE(rv)) {
   3929                 bcm_tr3_ipmc_repl_detach(unit);
   3930                 return rv;
   3931              }  
   3932         }
   3933     } else 
   3934 #endif /* BCM_KATANA2_SUPPORT */
   3935     {
   3936         _tr3_repl_info[unit]->num_intf = soc_mem_index_count(unit,
   3937             EGR_L3_NEXT_HOPm);
   3938 
   3939         if (NULL == _tr3_repl_info[unit]->l3_intf_next_hop_ipmc) {
   3940             _tr3_repl_info[unit]->l3_intf_next_hop_ipmc =
   3941                 sal_alloc(sizeof(int) * soc_mem_index_count(unit, EGR_L3_INTFm),
   3942                         "l3_intf_next_hop_ipmc");
   3943             if (NULL == _tr3_repl_info[unit]->l3_intf_next_hop_ipmc) {
   3944                 bcm_tr3_ipmc_repl_detach(unit);
   3945                 return BCM_E_MEMORY;
   3946             }
   3947         }
   3948         for (i = 0; i < soc_mem_index_count(unit, EGR_L3_INTFm); i++) {
   3949             _tr3_repl_info[unit]->l3_intf_next_hop_ipmc[i] = REPL_NH_INDEX_UNALLOCATED;
   3950         }
   3951 
   3952         if (NULL == _tr3_repl_info[unit]->l3_intf_next_hop_trill) {
   3953             _tr3_repl_info[unit]->l3_intf_next_hop_trill =
   3954                 sal_alloc(sizeof(int) * soc_mem_index_count(unit, EGR_L3_INTFm),
   3955                         "l3_intf_next_hop_trill");
   3956             if (NULL == _tr3_repl_info[unit]->l3_intf_next_hop_trill) {
   3957                 bcm_tr3_ipmc_repl_detach(unit);
   3958                 return BCM_E_MEMORY;
   3959             }
   3960         }
   3961         for (i = 0; i < soc_mem_index_count(unit, EGR_L3_INTFm); i++) {
   3962             _tr3_repl_info[unit]->l3_intf_next_hop_trill[i] = -1;
   3963         }
   3964 
   3965     }
   3966 
   3967     /* PBMP_ITER(PBMP_ALL(unit), port)  */
   3968     SOC_PBMP_ITER(pbmp_all, port) { 
   3969         /* Coverity issue ignored:
   3970          * Maximum port number used in PBMP_PORT_ALL
   3971          * should never exceed SOC_MAX_NUM_PP_PORTS */
   3972         /* coverity[overrun-local : FALSE] */
   3973         if (NULL == _tr3_repl_info[unit]->port_info[port]) {
   3974             _tr3_repl_info[unit]->port_info[port] =
   3975                 sal_alloc(sizeof(_tr3_repl_port_info_t), "repl port info");
   3976             if (NULL == _tr3_repl_info[unit]->port_info[port]) {
   3977                 bcm_tr3_ipmc_repl_detach(unit);
   3978                 return BCM_E_MEMORY;
   3979             }
   3980         }
   3981         sal_memset(_tr3_repl_info[unit]->port_info[port], 0,
   3982                 sizeof(_tr3_repl_port_info_t));
   3983 
   3984         alloc_size = sizeof(int) * _tr3_repl_info[unit]->num_repl_groups;
   3985         if (NULL == _tr3_repl_info[unit]->port_info[port]->intf_count) {
   3986             _tr3_repl_info[unit]->port_info[port]->intf_count = 
   3987                 sal_alloc(alloc_size, "repl port intf count");
   3988             if (NULL == _tr3_repl_info[unit]->port_info[port]->intf_count) {
   3989                 bcm_tr3_ipmc_repl_detach(unit);
   3990                 return BCM_E_MEMORY;
   3991             }
   3992         }
   3993         sal_memset(_tr3_repl_info[unit]->port_info[port]->intf_count, 0,
   3994                 alloc_size);
   3995     }
   3996 
   3997 
   3998     rv = _bcm_tr3_repl_head_info_init(unit);
   3999     if (BCM_FAILURE(rv)) {
   4000         bcm_tr3_ipmc_repl_detach(unit);
   4001         return rv;
   4002     }
   4003 
   4004     rv = _bcm_tr3_repl_list_entry_info_init(unit);
   4005     if (BCM_FAILURE(rv)) {
   4006         bcm_tr3_ipmc_repl_detach(unit);
   4007         return rv;
   4008     }
   4009 
   4010 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   4011     if (SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_APACHE(unit)) {
   4012         rv = _bcm_td2p_repl_port_agg_map_init(unit);
   4013         if (BCM_FAILURE(rv)) {
   4014             return rv;
   4015         }
   4016     }
   4017 #endif
   4018 
   4019     if (!SOC_WARM_BOOT(unit)) {
   4020         if (soc_feature(unit, soc_feature_static_repl_head_alloc)) {
   4021 
   4022             /* Set MEMBER_BITMAP and LAST_BITMAP fields */
   4023             si = &SOC_INFO(unit);
   4024             SOC_PBMP_CLEAR(member_bitmap);
   4025             member_count = 0;
   4026             PBMP_ITER(SOC_CONTROL(unit)->repl_eligible_pbmp, port) {
   4027                 phy_port = si->port_l2p_mapping[port];
   4028                 mmu_port = si->port_p2m_mapping[phy_port];
   4029 
   4030                 if ((mmu_port == 57) || (mmu_port == 59) ||
   4031                     (mmu_port == 61) || (mmu_port == 62)) {
   4032                     /* No replication on MMU ports 57, 59, 61, and 62 */
   4033                     continue;
   4034                 } else if (mmu_port == 60) {
   4035                     member_bitmap_index = 59;
   4036                 } else {
   4037                     member_bitmap_index = mmu_port;
   4038                 }
   4039 
   4040                 SOC_PBMP_PORT_ADD(member_bitmap, member_bitmap_index);
   4041                 member_count++;
   4042             }
   4043 
   4044  
   4045             for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   4046                 fldbuf[i] = SOC_PBMP_WORD_GET(member_bitmap, i);
   4047             }
   4048  
   4049             sal_memset(&repl_group_entry, 0, sizeof(mmu_repl_group_entry_t));
   4050             soc_MMU_REPL_GROUPm_field_set(unit, &repl_group_entry,
   4051                       MEMBER_BITMAPf, fldbuf);
   4052             soc_MMU_REPL_GROUPm_field_set(unit, &repl_group_entry,
   4053                       LAST_BITMAPf, fldbuf);
   4054 
   4055             /* Set HEAD_INDEXf field */
   4056             for (i = 0; i < _tr3_repl_info[unit]->num_repl_groups; i++) {
   4057                 soc_MMU_REPL_GROUPm_field32_set(unit, &repl_group_entry,
   4058                           HEAD_INDEXf, i * member_count);
   4059                 SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_GROUPm(unit, MEM_BLOCK_ALL,
   4060                               i, &repl_group_entry));
   4061             }
   4062 
   4063         } else {
   4064             /* Clear replication group table */
   4065             if (soc_mem_is_valid(unit, MMU_REPL_GROUP_INFO0m)) {
   4066                 SOC_IF_ERROR_RETURN
   4067                     (soc_mem_clear(unit, MMU_REPL_GROUP_INFO0m, MEM_BLOCK_ALL,
   4068                                    0));
   4069 
   4070                 /* APACHE does not have MMU_REPL_GROUP_INFO1m */
   4071                 if (soc_mem_is_valid(unit, MMU_REPL_GROUP_INFO1m)) {
   4072                 SOC_IF_ERROR_RETURN
   4073                     (soc_mem_clear(unit, MMU_REPL_GROUP_INFO1m, MEM_BLOCK_ALL,
   4074                                    0));
   4075                 }
   4076             } else {
   4077 #ifdef  BCM_METROLITE_SUPPORT 
   4078                 if (SOC_IS_METROLITE(unit)) {
   4079                     SOC_IF_ERROR_RETURN
   4080                         (soc_mem_clear(unit, MMU_REPL_GRP_TBLm, MEM_BLOCK_ALL, 0));
   4081                     repl_map_idx_pp =  _BCM_ML_MAX_EXT_STREAMS_PER_LINKPHY_PORT;
   4082                     repl_map_port_ct =  ML_MAX_LOGICAL_PORTS;
   4083                     sal_memset(&map_entry, 0, sizeof(mmu_repl_map_tbl_entry_t));
   4084                     for (i = repl_map_idx_pp;((i < repl_map_port_ct + repl_map_idx_pp) && 
   4085                                              (i < soc_mem_index_count(unit,MMU_REPL_MAP_TBLm)));
   4086                                               i++) {
   4087                         pp_port = i - repl_map_idx_pp;
   4088                         soc_MMU_REPL_MAP_TBLm_field_set(unit, &map_entry,
   4089                                                        DEST_PPPf, &pp_port);
   4090                         SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_MAP_TBLm(unit,
   4091                                    MEM_BLOCK_ALL, i, &map_entry));
   4092                     }          
   4093 	        } else
   4094 #endif
   4095 #ifdef  BCM_KATANA2_SUPPORT 
   4096                 if (SOC_IS_KATANA2(unit)) {
   4097                     SOC_IF_ERROR_RETURN(soc_mem_clear(unit,
   4098                                         MMU_REPL_GRP_TBL1m, MEM_BLOCK_ALL, 0));
   4099                     if (soc_mem_is_valid(unit, MMU_REPL_GRP_TBL2m)) {
   4100                     SOC_IF_ERROR_RETURN(soc_mem_clear(unit, 
   4101                                         MMU_REPL_GRP_TBL2m, MEM_BLOCK_ALL, 0));
   4102                         repl_map_idx_pp =  (soc_mem_index_count(unit,
   4103                                MMU_REPL_MAP_TBLm) - SOC_INFO(unit).pp_port_index_min);
   4104                     } 
   4105                     SOC_IF_ERROR_RETURN(soc_mem_clear(unit,
   4106                                         MMU_REPL_GRP_TBL0m, MEM_BLOCK_ALL, 0));
   4107                     sal_memset(&map_entry, 0, sizeof(mmu_repl_map_tbl_entry_t));
   4108                     repl_map_port_ct = KT2_MAX_LOGICAL_PORTS;
   4109                     READ_TOQ_GEN_CFGr(unit, &toq_entry);
   4110                     soc_reg_field_set(unit, TOQ_GEN_CFGr,
   4111                             &toq_entry, CFG_REPL_GRP_ATOMIC_ENf,1);
   4112                     WRITE_TOQ_GEN_CFGr(unit, toq_entry);
   4113 
   4114                     /* MMU_REPL_MAP_TBL table is programmed to map 256 - 297 
   4115                      * indices to pp ports 1-41 
   4116                      */
   4117 
   4118 #ifdef BCM_SABER2_SUPPORT
   4119                     /* 0-63 are for Link phy ports */
   4120                     if (SOC_IS_SABER2(unit)) {
   4121                         repl_map_idx_pp =  SOC_INFO(unit).subport_port_max;
   4122                         repl_map_port_ct =  SB2_MAX_LOGICAL_PORTS;
   4123                     }
   4124 #endif
   4125 
   4126                     for (i = repl_map_idx_pp;((i < repl_map_port_ct + repl_map_idx_pp) && (i < soc_mem_index_count(unit,MMU_REPL_MAP_TBLm)));
   4127                             i++) {
   4128                         pp_port = i - repl_map_idx_pp;
   4129                         soc_MMU_REPL_MAP_TBLm_field_set(unit, &map_entry, 
   4130                                                        DEST_PPPf, &pp_port);
   4131                         SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_MAP_TBLm(unit,
   4132                                    MEM_BLOCK_ALL, i, &map_entry));
   4133                     }  
   4134                 } else 
   4135 #endif /* BCM_KATANA2_SUPPORT */
   4136                 { 
   4137                     SOC_IF_ERROR_RETURN
   4138                         (soc_mem_clear(unit, MMU_REPL_GROUPm, MEM_BLOCK_ALL, 0));
   4139 
   4140                 }
   4141             }
   4142  
   4143             /* Clear replication group initial count table */
   4144             if (soc_mem_is_valid(unit, MMU_REPL_GROUP_INITIAL_COPY_COUNTm)) {
   4145                 SOC_IF_ERROR_RETURN
   4146                     (soc_mem_clear(unit, MMU_REPL_GROUP_INITIAL_COPY_COUNTm,
   4147                                    MEM_BLOCK_ALL, 0));
   4148             }
   4149 
   4150             /* Initialize PORT_INITIAL_COPY_COUNT_WIDTH registers */
   4151             if (SOC_REG_IS_VALID(unit, PORT_INITIAL_COPY_COUNT_WIDTHr)) {
   4152                 PBMP_ITER(PBMP_ALL(unit), port) {
   4153                     if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port)) {
   4154                         count_width = 2;
   4155                     } else if (IS_RDB_PORT(unit, port)) {
   4156                         continue;
   4157                     } else if (SOC_IS_APACHE(unit)) {
   4158                         if (SOC_INFO(unit).port_speed_max[port] < 25000) {
   4159                             count_width = 1; /* 1 ICC bit  */
   4160                         } else if (SOC_INFO(unit).port_speed_max[port] <= 53000) {
   4161                             count_width = 2; /* 2 ICC bits  */
   4162                         } else {
   4163                             count_width = 3; /* 3 ICC bits  */
   4164                         }
   4165                     } else if (SOC_IS_TRIDENT2PLUS(unit)) {
   4166                         if (SOC_INFO(unit).port_speed_max[port] <= 11000) {
   4167                             /* max speed could be 11G */
   4168                             count_width = 1; /* 1 ICC bit  */
   4169                         } else if (SOC_INFO(unit).port_speed_max[port] <= 42000) {
   4170                             /* max speed could be 42G */
   4171                             count_width = 2; /* 2 ICC bits  */
   4172                         } else {
   4173                             count_width = 3; /* 3 ICC bits  */
   4174                         }
   4175                     } else {
   4176                         num_lanes = SOC_INFO(unit).port_num_lanes[port];
   4177                         switch (num_lanes) {
   4178                             case 1: count_width = 1;
   4179                                     break;
   4180                             case 2: count_width = 2;
   4181                                     break;
   4182                             case 4: count_width = 3;
   4183                                     break;
   4184                             default: count_width = 0;
   4185                                      break;
   4186                         }
   4187                     }
   4188                     regval = 0;
   4189                     soc_reg_field_set(unit, PORT_INITIAL_COPY_COUNT_WIDTHr,
   4190                             &regval, BIT_WIDTHf,
   4191                             count_width ? (count_width - 1) : 0);
   4192                     SOC_IF_ERROR_RETURN
   4193                         (WRITE_PORT_INITIAL_COPY_COUNT_WIDTHr(unit, port,
   4194                                                               regval));
   4195                 }
   4196             }
   4197         }
   4198     } 
   4199 #ifdef BCM_SABER2_SUPPORT
   4200      if (SOC_IS_SABER2(unit)) {
   4201 
   4202          /* Release SB2 ipmc structures for re-allocation */
   4203          bcm_sb2_ipmc_repl_detach(unit);
   4204 
   4205          if (!_sb2_extq_repl_info[unit]) {  
   4206              /* Allocate struct for IPMC Extq replication bookkeeping */
   4207              alloc_size = sizeof(_sb2_extq_repl_info_t);
   4208              _sb2_extq_repl_info[unit] = sal_alloc(alloc_size, "IPMC Extq repl info");
   4209              if (_sb2_extq_repl_info[unit] == NULL) {
   4210                  bcm_tr3_ipmc_repl_detach(unit); 
   4211                  return BCM_E_MEMORY;
   4212              }
   4213              sal_memset(_sb2_extq_repl_info[unit], 0, alloc_size);
   4214              _sb2_extq_repl_info[unit]->ipmc_size =
   4215                            soc_mem_index_count(unit, L3_IPMCm);
   4216          } 
   4217 
   4218          alloc_size = soc_mem_index_count(unit, L3_IPMCm); 
   4219          if (!_sb2_extq_repl_info[unit]->ext_ipmc_list) {   
   4220              _sb2_extq_repl_info[unit]->ext_ipmc_list = 
   4221                   sal_alloc(alloc_size * sizeof(_bcm_ext_q_ipmc_t),
   4222                                     "Extended queue ipmc nodes");
   4223              if (!_sb2_extq_repl_info[unit]->ext_ipmc_list) {
   4224                  bcm_tr3_ipmc_repl_detach(unit);
   4225                  bcm_sb2_ipmc_repl_detach(unit);
   4226                  return BCM_E_MEMORY;  
   4227              }
   4228          } 
   4229          sal_memset(_sb2_extq_repl_info[unit]->ext_ipmc_list, 0,
   4230                              alloc_size * sizeof(_bcm_ext_q_ipmc_t));
   4231 
   4232          IPMC_EXTQ_REPL_MAX(unit) = (1 << soc_mem_field_length(unit, L3_IPMCm,
   4233                                      EXT_Q_NUM_COPIESf)) - 1;
   4234          IPMC_EXTQ_TOTAL(unit) = 1024;
   4235          IPMC_EXTQ_LIST_TOTAL(unit) = soc_mem_index_count(unit, MMU_EXT_MC_QUEUE_LIST0m);
   4236 
   4237          alloc_size = SHR_BITALLOCSIZE(IPMC_EXTQ_LIST_TOTAL(unit));
   4238          if (!_sb2_extq_repl_info[unit]->bitmap_entries_used) {  
   4239              _sb2_extq_repl_info[unit]->bitmap_entries_used =
   4240              sal_alloc(alloc_size, "IPMC Extq repl entries used");
   4241              if (_sb2_extq_repl_info[unit]->bitmap_entries_used == NULL) {
   4242                  bcm_tr3_ipmc_repl_detach(unit); 
   4243                  bcm_sb2_ipmc_repl_detach(unit);
   4244                  return BCM_E_MEMORY;
   4245              } 
   4246          }
   4247          sal_memset(_sb2_extq_repl_info[unit]->bitmap_entries_used, 0, alloc_size);
   4248     
   4249          alloc_size = sizeof(_sb2_repl_queue_info_t);
   4250          /* Always reserve slot 0 */
   4251          IPMC_EXTQ_REPL_VE_USED_SET(unit, 0);
   4252          if (!_sb2_extq_repl_info[unit]->mcgroup_info) {
   4253               _sb2_extq_repl_info[unit]->mcgroup_info =
   4254              sal_alloc(alloc_size, "IPMC MC group info");
   4255              if (_sb2_extq_repl_info[unit]->mcgroup_info == NULL) {
   4256                   bcm_tr3_ipmc_repl_detach(unit) ;
   4257                   bcm_sb2_ipmc_repl_detach(unit);
   4258                   return BCM_E_MEMORY;
   4259              }
   4260          }
   4261          sal_memset(_sb2_extq_repl_info[unit]->mcgroup_info, 0, alloc_size);
   4262      
   4263          alloc_size = sizeof(int32) * soc_mem_index_count(unit, L3_IPMCm);
   4264          if (!IPMC_EXTQ_GROUP_INFO(unit)->queue_count) {   
   4265               IPMC_EXTQ_GROUP_INFO(unit)->queue_count =
   4266                   sal_alloc(alloc_size, "IPMC Extq queue count");
   4267               if (IPMC_EXTQ_GROUP_INFO(unit)->queue_count == NULL) {
   4268                   bcm_tr3_ipmc_repl_detach(unit);
   4269                   bcm_sb2_ipmc_repl_detach(unit);
   4270                   return BCM_E_MEMORY;
   4271               }
   4272          } 
   4273          sal_memset(IPMC_EXTQ_GROUP_INFO(unit)->queue_count,
   4274                                   0, alloc_size);
   4275          if (!IPMC_EXTQ_GROUP_INFO(unit)->queue_count_int) {
   4276               IPMC_EXTQ_GROUP_INFO(unit)->queue_count_int=
   4277                   sal_alloc(alloc_size, "IPMC Extq queue count");
   4278               if (IPMC_EXTQ_GROUP_INFO(unit)->queue_count_int== NULL) {
   4279                   bcm_tr3_ipmc_repl_detach(unit);
   4280                   bcm_sb2_ipmc_repl_detach(unit);
   4281                   return BCM_E_MEMORY;
   4282               }
   4283          } 
   4284          if (!IPMC_EXTQ_GROUP_INFO(unit)->queue_count_ext) {
   4285               IPMC_EXTQ_GROUP_INFO(unit)->queue_count_ext=
   4286                   sal_alloc(alloc_size, "IPMC Extq queue count");
   4287               if (IPMC_EXTQ_GROUP_INFO(unit)->queue_count_ext== NULL) {
   4288                   bcm_tr3_ipmc_repl_detach(unit);
   4289                   bcm_sb2_ipmc_repl_detach(unit);
   4290                   return BCM_E_MEMORY;
   4291               }
   4292          }
   4293               
   4294          SOC_PBMP_ITER(pbmp_all, port) { 
   4295             /* Coverity issue ignored:
   4296              * Maximum port number used in PBMP_PORT_ALL
   4297              * should never exceed SOC_MAX_NUM_PP_PORTS */
   4298             /* coverity[overrun-call : FALSE] */
   4299             BCM_IF_ERROR_RETURN(bcm_sb2_ipmc_repl_extq_port_alloc(unit, port)); 
   4300          }
   4301          
   4302            /* reserve ipmc index 0 & 1 for extended queue work around */
   4303            BCM_IF_ERROR_RETURN(bcm_xgs3_ipmc_id_alloc(unit, 0));
   4304            BCM_IF_ERROR_RETURN(bcm_xgs3_ipmc_id_alloc(unit, 1));
   4305        
   4306             /* Read L3 ipmc table. */
   4307             BCM_IF_ERROR_RETURN(soc_mem_read(unit, L3_IPMCm, MEM_BLOCK_ANY,
   4308                                            0, entry));
   4309             /* use 1 as initial redirection pointer */
   4310             soc_mem_field32_set(unit, L3_IPMCm, entry,
   4311                                      MMU_MC_REDIRECTION_PTRf, 1);
   4312             BCM_IF_ERROR_RETURN(soc_mem_write(unit, L3_IPMCm, MEM_BLOCK_ALL,
   4313                                          0, &entry));
   4314      }
   4315 #endif 
   4316 
   4317     return rv;
   4318 }
   4319 
   4320 /* Function:
   4321  *	_bcm_tr3_repl_head_ptr_replace
   4322  * Purpose:
   4323  *      Replace REPL_HEAD pointers in MMU multicast queues.
   4324  * Parameters:
   4325  *	unit       - StrataSwitch PCI device unit number.
   4326  *	old_head_index    - Starting index of old REPL_HEAD block.
   4327  *	old_member_bitmap - Old replication group member bitmap.
   4328  *	new_head_index    - Starting index of new REPL_HEAD block.
   4329  *	new_member_bitmap - New replication group member bitmap.
   4330  *	new_last_bitmap   - New replication group last indication bitmap.
   4331  * Returns:
   4332  *	BCM_E_XXX
   4333  */
   4334 STATIC int
   4335 _bcm_tr3_repl_head_ptr_replace(int unit, int old_head_index,
   4336         soc_pbmp_t old_member_bitmap, int new_head_index,
   4337         soc_pbmp_t new_member_bitmap, soc_pbmp_t new_last_bitmap)
   4338 {
   4339     int member_bitmap_width;
   4340     int old_member_id, new_member_id;
   4341     int i;
   4342     int old_repl_head_ptr, new_repl_head_ptr;
   4343     int new_l3_last;
   4344     int mmu_port;
   4345     uint64 regval_64;
   4346     int timeout_usec;
   4347     soc_timeout_t to;
   4348     int replace_done;
   4349     soc_info_t *si;
   4350     bcm_port_t phy_port, port;
   4351 
   4352 
   4353     si = &SOC_INFO(unit);
   4354 
   4355     member_bitmap_width = soc_mem_field_length(unit, MMU_REPL_GROUPm,
   4356             MEMBER_BITMAPf);
   4357 
   4358     old_member_id = 0;
   4359     new_member_id = 0;
   4360     for (i = 0; i < member_bitmap_width; i++) {
   4361         if (SOC_PBMP_MEMBER(old_member_bitmap, i)) {
   4362 
   4363             /* Compute index to old block of REPL_HEAD entries */
   4364             old_repl_head_ptr = old_head_index + old_member_id;
   4365 
   4366             if (SOC_PBMP_MEMBER(new_member_bitmap, i)) {
   4367                 /* Compute index to new block of REPL_HEAD entries */
   4368                 new_repl_head_ptr = new_head_index + new_member_id;
   4369                 new_l3_last = SOC_PBMP_MEMBER(new_last_bitmap, i) ? 1 : 0;
   4370             } else {
   4371                 new_repl_head_ptr = 0;
   4372                 new_l3_last = 1;
   4373             }
   4374 
   4375             /* Convert member bitmap index to MMU port */
   4376             if (i == 59) {
   4377                 mmu_port = 60;
   4378             } else {
   4379                 mmu_port = i;
   4380             }
   4381 
   4382             /* Convert MMU port to logical port */
   4383             phy_port = si->port_m2p_mapping[mmu_port];
   4384             port = si->port_p2l_mapping[phy_port];
   4385 
   4386             /* Replace old_repl_head_ptr with new_repl_head_ptr
   4387              * in multicast queues.
   4388              */
   4389             COMPILER_64_ZERO(regval_64);
   4390             soc_reg64_field32_set(unit, REPL_HEAD_PTR_REPLACEr, &regval_64,
   4391                     OLD_REPL_HEAD_PTRf, old_repl_head_ptr);
   4392             soc_reg64_field32_set(unit, REPL_HEAD_PTR_REPLACEr, &regval_64,
   4393                     NEW_REPL_HEAD_PTRf, new_repl_head_ptr);
   4394             soc_reg64_field32_set(unit, REPL_HEAD_PTR_REPLACEr, &regval_64,
   4395                     NEW_L3_LASTf, new_l3_last);
   4396             soc_reg64_field32_set(unit, REPL_HEAD_PTR_REPLACEr, &regval_64,
   4397                     REPLACE_ENf, 1);
   4398             SOC_IF_ERROR_RETURN(soc_reg_set(unit, REPL_HEAD_PTR_REPLACEr,
   4399                         port, 0, regval_64));
   4400 
   4401             /* Wait for replacement done */
   4402             timeout_usec = 1000000;
   4403             soc_timeout_init(&to, timeout_usec, 0);
   4404             while (TRUE) {
   4405                 SOC_IF_ERROR_RETURN(soc_reg_get(unit, REPL_HEAD_PTR_REPLACEr,
   4406                             port, 0, &regval_64));
   4407                 replace_done = soc_reg64_field32_get(unit,
   4408                         REPL_HEAD_PTR_REPLACEr, regval_64, REPLACE_DONEf);
   4409                 if (replace_done) {
   4410                     break;
   4411                 }
   4412 
   4413                 if (soc_timeout_check(&to)) {
   4414                     return BCM_E_TIMEOUT;
   4415                 }
   4416             }
   4417 
   4418             old_member_id++;
   4419         }
   4420 
   4421         if (SOC_PBMP_MEMBER(new_member_bitmap, i)) {
   4422             new_member_id++;
   4423         }
   4424     }
   4425 
   4426     return BCM_E_NONE;
   4427 }
   4428 
   4429 #ifdef BCM_TRIDENT2_SUPPORT
   4430 
   4431 /* Function:
   4432  *	_bcm_td2_repl_icc_set
   4433  * Purpose:
   4434  *      Set replication initial copy count.
   4435  * Parameters:
   4436  *	unit       - StrataSwitch PCI device unit number.
   4437  *	repl_group - The replication group number.
   4438  *	port       - Port.
   4439  *	intf_count - Replication list's interface count.
   4440  * Returns:
   4441  *	BCM_E_XXX
   4442  */
   4443 STATIC int
   4444 _bcm_td2_repl_icc_set (int unit, int repl_group, bcm_port_t port,
   4445                 int intf_count, int count_width, int copy_count)
   4446 {
   4447     soc_info_t *si;
   4448     uint32 copy_count_buf[2];
   4449     uint32 count_mask, count_shift;
   4450     mmu_repl_group_initial_copy_count_entry_t initial_copy_count_entry;
   4451     bcm_port_t phy_port;
   4452 
   4453     si = &SOC_INFO(unit);
   4454     if (SOC_IS_KATANA2(unit)) {
   4455         phy_port = port;
   4456     } else {
   4457         phy_port = si->port_l2p_mapping[port];
   4458     }
   4459 
   4460     SOC_IF_ERROR_RETURN(READ_MMU_REPL_GROUP_INITIAL_COPY_COUNTm(unit,
   4461                 MEM_BLOCK_ANY, repl_group, &initial_copy_count_entry));
   4462     if (IS_LB_PORT(unit, port)) {
   4463         soc_MMU_REPL_GROUP_INITIAL_COPY_COUNTm_field32_set(unit,
   4464                 &initial_copy_count_entry, ICC_BIT_131_130f, copy_count);
   4465     } else if (IS_CPU_PORT(unit, port)) {
   4466         soc_MMU_REPL_GROUP_INITIAL_COPY_COUNTm_field32_set(unit,
   4467                 &initial_copy_count_entry, ICC_BIT_129_128f, copy_count);
   4468     } else if ((phy_port <= 128) && (phy_port >= 65)) {
   4469         soc_MMU_REPL_GROUP_INITIAL_COPY_COUNTm_field_get(unit,
   4470                 &initial_copy_count_entry, ICC_BIT_127_64f, copy_count_buf);
   4471         count_mask = (1 << count_width) - 1;
   4472         count_shift = (phy_port - 65) % 32;
   4473         copy_count_buf[(phy_port - 65) / 32] &= ~(count_mask << count_shift);
   4474         copy_count_buf[(phy_port - 65) / 32] |= (copy_count << count_shift);
   4475         soc_MMU_REPL_GROUP_INITIAL_COPY_COUNTm_field_set(unit,
   4476                 &initial_copy_count_entry, ICC_BIT_127_64f, copy_count_buf);
   4477     } else if (phy_port <= 64) {
   4478         soc_MMU_REPL_GROUP_INITIAL_COPY_COUNTm_field_get(unit,
   4479                 &initial_copy_count_entry, ICC_BIT_63_0f, copy_count_buf);
   4480         count_mask = (1 << count_width) - 1;
   4481         count_shift = (phy_port - 1) % 32;
   4482         copy_count_buf[(phy_port - 1)/32] &= ~(count_mask << count_shift);
   4483         copy_count_buf[(phy_port - 1)/32] |= (copy_count << count_shift);
   4484         soc_MMU_REPL_GROUP_INITIAL_COPY_COUNTm_field_set(unit,
   4485                 &initial_copy_count_entry, ICC_BIT_63_0f, copy_count_buf);
   4486     } else {
   4487         return BCM_E_PORT;
   4488     }
   4489     SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_GROUP_INITIAL_COPY_COUNTm(unit,
   4490                 MEM_BLOCK_ALL, repl_group, &initial_copy_count_entry));
   4491 
   4492     return BCM_E_NONE;
   4493 
   4494 }
   4495 
   4496 /* Function:
   4497  *	_bcm_apache_repl_icc_set
   4498  * Purpose:
   4499  *      Set replication initial copy count.
   4500  * Parameters:
   4501  *	unit       - StrataSwitch PCI device unit number.
   4502  *	repl_group - The replication group number.
   4503  *	port       - Port.
   4504  *	intf_count - Replication list's interface count.
   4505  * Returns:
   4506  *	BCM_E_XXX
   4507  */
   4508 STATIC int
   4509 _bcm_apache_repl_icc_set (int unit, int repl_group, bcm_port_t port,
   4510                 int intf_count, int count_width, int copy_count)
   4511 {
   4512     soc_info_t *si;
   4513     uint32 copy_count_buf;
   4514     uint32 count_mask, count_shift;
   4515     mmu_repl_group_initial_copy_count_entry_t initial_copy_count_entry;
   4516     bcm_port_t phy_port;
   4517 
   4518     si = &SOC_INFO(unit);
   4519     phy_port = si->port_l2p_mapping[port];
   4520 
   4521     SOC_IF_ERROR_RETURN(READ_MMU_REPL_GROUP_INITIAL_COPY_COUNTm(unit,
   4522                 MEM_BLOCK_ANY, repl_group, &initial_copy_count_entry));
   4523     if (IS_LB_PORT(unit, port)) {
   4524         soc_MMU_REPL_GROUP_INITIAL_COPY_COUNTm_field32_set(unit,
   4525                 &initial_copy_count_entry, ICC_BIT_92_90f, copy_count);
   4526     } else if (IS_CPU_PORT(unit, port)) {
   4527         soc_MMU_REPL_GROUP_INITIAL_COPY_COUNTm_field32_set(unit,
   4528                 &initial_copy_count_entry, ICC_BIT_89_88f, copy_count);
   4529     } else if ((phy_port <= 72) && (phy_port >= 65)) {
   4530         copy_count_buf =
   4531             soc_MMU_REPL_GROUP_INITIAL_COPY_COUNTm_field32_get(unit,
   4532                     &initial_copy_count_entry, ICC_BIT_87_72f);
   4533 
   4534         count_mask = (1 << count_width) - 1;
   4535         count_shift = (phy_port - 65) * 2;
   4536         copy_count_buf &= ~(count_mask << count_shift);
   4537         copy_count_buf |= (copy_count << count_shift);
   4538 
   4539         soc_MMU_REPL_GROUP_INITIAL_COPY_COUNTm_field32_set(unit,
   4540                 &initial_copy_count_entry, ICC_BIT_87_72f, copy_count_buf);
   4541     } else if ((phy_port <= 64) && (phy_port >= 37)) {
   4542         copy_count_buf =
   4543             soc_MMU_REPL_GROUP_INITIAL_COPY_COUNTm_field32_get(unit,
   4544                     &initial_copy_count_entry, ICC_BIT_71_44f);
   4545 
   4546         count_mask = (1 << count_width) - 1;
   4547         count_shift = (phy_port - 37);
   4548         copy_count_buf &= ~(count_mask << count_shift);
   4549         copy_count_buf |= (copy_count << count_shift);
   4550 
   4551         soc_MMU_REPL_GROUP_INITIAL_COPY_COUNTm_field32_set(unit,
   4552                 &initial_copy_count_entry, ICC_BIT_71_44f, copy_count_buf);
   4553     } else if ((phy_port <= 36) && (phy_port >= 29)) {
   4554         copy_count_buf =
   4555             soc_MMU_REPL_GROUP_INITIAL_COPY_COUNTm_field32_get(unit,
   4556                     &initial_copy_count_entry, ICC_BIT_43_28f);
   4557 
   4558         count_mask = (1 << count_width) - 1;
   4559         count_shift = ((phy_port - 29) * 2);
   4560         copy_count_buf &= ~(count_mask << count_shift);
   4561         copy_count_buf |= (copy_count << count_shift);
   4562 
   4563         soc_MMU_REPL_GROUP_INITIAL_COPY_COUNTm_field32_set(unit,
   4564                 &initial_copy_count_entry, ICC_BIT_43_28f, copy_count_buf);
   4565     } else if (phy_port <= 28) {
   4566         copy_count_buf =
   4567             soc_MMU_REPL_GROUP_INITIAL_COPY_COUNTm_field32_get(unit,
   4568                     &initial_copy_count_entry, ICC_BIT_27_0f);
   4569 
   4570         count_mask = (1 << count_width) - 1;
   4571         count_shift = (phy_port - 1);
   4572         copy_count_buf &= ~(count_mask << count_shift);
   4573         copy_count_buf |= (copy_count << count_shift);
   4574 
   4575         soc_MMU_REPL_GROUP_INITIAL_COPY_COUNTm_field32_set(unit,
   4576                 &initial_copy_count_entry, ICC_BIT_27_0f, copy_count_buf);
   4577     } else {
   4578         return BCM_E_PORT;
   4579     }
   4580     SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_GROUP_INITIAL_COPY_COUNTm(unit,
   4581                 MEM_BLOCK_ALL, repl_group, &initial_copy_count_entry));
   4582 
   4583 
   4584     return BCM_E_NONE;
   4585 }
   4586 
   4587 /* Function:
   4588  *	_bcm_td2_repl_initial_copy_count_set
   4589  * Purpose:
   4590  *      Set replication initial copy count.
   4591  * Parameters:
   4592  *	unit       - StrataSwitch PCI device unit number.
   4593  *	repl_group - The replication group number.
   4594  *	port       - Port.
   4595  *	intf_count - Replication list's interface count.
   4596  * Returns:
   4597  *	BCM_E_XXX
   4598  */
   4599 STATIC int
   4600 _bcm_td2_repl_initial_copy_count_set(int unit, int repl_group, bcm_port_t port,
   4601                 int intf_count)
   4602 {
   4603     uint32 regval;
   4604     int count_width, copy_count;
   4605     int rv;
   4606  
   4607     SOC_IF_ERROR_RETURN(READ_PORT_INITIAL_COPY_COUNT_WIDTHr(unit,
   4608                 port, &regval));
   4609     count_width = 1 + soc_reg_field_get(unit,
   4610             PORT_INITIAL_COPY_COUNT_WIDTHr, regval, BIT_WIDTHf);
   4611     copy_count = 0;
   4612     switch (count_width) {
   4613         case 1:
   4614             if (intf_count <= 1) {
   4615                 copy_count = intf_count;
   4616             } 
   4617             break;
   4618         case 2:
   4619             if (intf_count <= 3) {
   4620                 copy_count = intf_count;
   4621             }
   4622             break;
   4623         case 3:
   4624             if (intf_count <= 5) {
   4625                 copy_count = intf_count;
   4626             }
   4627             break;
   4628         default:
   4629             return BCM_E_INTERNAL;
   4630             break;
   4631     }
   4632 
   4633     
   4634     if (SOC_IS_MONTEREY(unit)) {
   4635         rv = BCM_E_NONE;
   4636     } else if (SOC_IS_APACHE(unit)) {
   4637         rv = _bcm_apache_repl_icc_set(unit, repl_group, port, intf_count,
   4638                 count_width, copy_count);
   4639     } else {
   4640         rv = _bcm_td2_repl_icc_set(unit, repl_group, port, intf_count,
   4641                 count_width, copy_count);
   4642     }
   4643 
   4644     return rv;
   4645 }
   4646 
   4647 /* Function:
   4648  *	_bcm_td2_repl_group_info_set
   4649  * Purpose:
   4650  *      Set replication group info.
   4651  * Parameters:
   4652  *	unit       - StrataSwitch PCI device unit number.
   4653  *	repl_group - The replication group number.
   4654  *	member_bitmap - Member bitmap.
   4655  *	head_index    - Base pointer to REPL_HEAD table.
   4656  * Returns:
   4657  *	BCM_E_XXX
   4658  */
   4659 STATIC int
   4660 _bcm_td2_repl_group_info_set(int unit, int repl_group,
   4661         soc_pbmp_t member_bitmap, int head_index)
   4662 {
   4663     int rv = BCM_E_NONE;
   4664     soc_pbmp_t xpipe_member_bitmap, ypipe_member_bitmap;
   4665     int xpipe_member_bitmap_width, ypipe_member_bitmap_width = 0;
   4666     int xpipe_member_count, ypipe_member_count;
   4667     int i;
   4668     uint32 fldbuf[SOC_PBMP_WORD_MAX];
   4669     mmu_repl_group_info0_entry_t repl_group_info0_entry;
   4670     mmu_repl_group_info1_entry_t repl_group_info1_entry;
   4671     soc_info_t *si;
   4672     soc_pbmp_t l3_pbmp;
   4673     bcm_port_t mmu_port, phy_port, port;
   4674     int cut_through_eligible;
   4675     ipmc_entry_t l3_ipmc_entry;
   4676 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   4677     bcm_multicast_t  group = 0;
   4678 #endif
   4679 
   4680     /* Configure X-pipe REPL_GROUP table */
   4681 
   4682     SOC_PBMP_CLEAR(xpipe_member_bitmap);
   4683     xpipe_member_bitmap_width = soc_mem_field_length(unit,
   4684                 MMU_REPL_GROUP_INFO0m, PIPE_MEMBER_BMPf);
   4685     xpipe_member_count = 0;
   4686     for (i = 0; i < xpipe_member_bitmap_width; i++) {
   4687         if (SOC_PBMP_MEMBER(member_bitmap, i)) {
   4688             SOC_PBMP_PORT_ADD(xpipe_member_bitmap, i);
   4689             xpipe_member_count++;
   4690         }
   4691     }
   4692     for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   4693         fldbuf[i] = SOC_PBMP_WORD_GET(xpipe_member_bitmap, i);
   4694     }
   4695     sal_memset(&repl_group_info0_entry, 0, sizeof(repl_group_info0_entry));
   4696     soc_MMU_REPL_GROUP_INFO0m_field_set(unit, &repl_group_info0_entry,
   4697             PIPE_MEMBER_BMPf, fldbuf);
   4698     soc_MMU_REPL_GROUP_INFO0m_field32_set(unit, &repl_group_info0_entry,
   4699             PIPE_BASE_PTRf, head_index);
   4700     SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_GROUP_INFO0m(unit, MEM_BLOCK_ALL,
   4701                 repl_group, &repl_group_info0_entry));
   4702 
   4703     SOC_PBMP_CLEAR(ypipe_member_bitmap);
   4704     if (soc_feature(unit, soc_feature_split_repl_group_table)) {
   4705         /* Configure Y-pipe REPL_GROUP table */
   4706 
   4707         SOC_PBMP_CLEAR(ypipe_member_bitmap);
   4708         ypipe_member_bitmap_width = soc_mem_field_length(unit,
   4709                 MMU_REPL_GROUP_INFO1m, PIPE_MEMBER_BMPf);
   4710         ypipe_member_count = 0;
   4711         for (i = xpipe_member_bitmap_width;
   4712              i < (xpipe_member_bitmap_width + ypipe_member_bitmap_width);
   4713              i++) {
   4714              if (SOC_PBMP_MEMBER(member_bitmap, i)) {
   4715                  SOC_PBMP_PORT_ADD(ypipe_member_bitmap,
   4716                          (i - xpipe_member_bitmap_width));
   4717                  ypipe_member_count++;
   4718              }
   4719         }
   4720         for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   4721              fldbuf[i] = SOC_PBMP_WORD_GET(ypipe_member_bitmap, i);
   4722         }
   4723         sal_memset(&repl_group_info1_entry, 0, sizeof(repl_group_info1_entry));
   4724         soc_MMU_REPL_GROUP_INFO1m_field_set(unit, &repl_group_info1_entry,
   4725                 PIPE_MEMBER_BMPf, fldbuf);
   4726         if (ypipe_member_count > 0) {
   4727             soc_MMU_REPL_GROUP_INFO1m_field32_set(unit, &repl_group_info1_entry,
   4728                     PIPE_BASE_PTRf, (head_index + xpipe_member_count));
   4729         } else {
   4730             soc_MMU_REPL_GROUP_INFO1m_field32_set(unit, &repl_group_info1_entry,
   4731                     PIPE_BASE_PTRf, 0);
   4732         }
   4733         SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_GROUP_INFO1m(unit, MEM_BLOCK_ALL,
   4734                     repl_group, &repl_group_info1_entry));
   4735     }
   4736 
   4737     /* When MMU is in cut-through mode, REPL_GROUP table is not read.
   4738      * Instead, MMU gets the REPL_HEAD base pointer and L3 bitmap from
   4739      * the L3_IPMC table in ingress pipeline.
   4740      */
   4741     if (soc_mem_field_valid(unit, L3_IPMCm, REPL_HEAD_BASE_PTRf)) {
   4742         /* Convert MMU member bitmap to logical port bitmap.
   4743          * X-pipe contains mmu ports 0-52. Y-pipe contains mmu ports 64-116.
   4744          */  
   4745         si = &SOC_INFO(unit);
   4746         SOC_PBMP_CLEAR(l3_pbmp);
   4747         for (i = 0; i < xpipe_member_bitmap_width; i++) {
   4748             if (SOC_PBMP_MEMBER(xpipe_member_bitmap, i)) {
   4749                 mmu_port = i;
   4750                 phy_port = si->port_m2p_mapping[mmu_port];
   4751                 port = si->port_p2l_mapping[phy_port];
   4752                 if (port != -1) {
   4753                     SOC_PBMP_PORT_ADD(l3_pbmp, port);
   4754                 }
   4755             }
   4756         }
   4757         if (soc_feature(unit, soc_feature_split_repl_group_table)) {
   4758             for (i = 0; i < ypipe_member_bitmap_width; i++) {
   4759                  if (SOC_PBMP_MEMBER(ypipe_member_bitmap, i)) {
   4760                      mmu_port = i + 64;
   4761                      phy_port = si->port_m2p_mapping[mmu_port];
   4762                      port = si->port_p2l_mapping[phy_port];
   4763                      SOC_PBMP_PORT_ADD(l3_pbmp, port);
   4764                  }
   4765             }
   4766         }
   4767 
   4768         /* Determine cut-through eligibility. An IPMC group is eligible
   4769          * for cut-through only if there is a single replication per
   4770          * L3 port.
   4771          */
   4772         cut_through_eligible = TRUE;
   4773 #if defined(BCM_TRIDENT2PLUS_SUPPORT)
   4774         /* For VXLAN IPMC, cut-through is always disabled.
   4775         *  The IP header for the tunnel needs the entire length of
   4776         *  the IP payload. This implies that the MMU must store the
   4777         *  entire packet, determining its length and then forward it
   4778         *  to the EP.
   4779         */
   4780         (void)_bcm_tr_multicast_ipmc_group_type_get(unit, repl_group, &group);
   4781         if ((SOC_IS_TRIDENT2PLUS(unit) || SOC_IS_APACHE(unit)) &&
   4782             (_BCM_MULTICAST_TYPE_VXLAN == _BCM_MULTICAST_TYPE_GET( group))){
   4783             cut_through_eligible = FALSE;
   4784         } else
   4785 #endif
   4786         {
   4787             SOC_PBMP_ITER(l3_pbmp, port) {
   4788                 /* Coverity issue ignored:
   4789                  * Maximum port number used in l3_pbmp
   4790                  * should never exceed SOC_MAX_NUM_PP_PORTS */
   4791                 /* coverity[overrun-local : FALSE] */
   4792                 if (REPL_PORT_GROUP_INTF_COUNT(unit, port, repl_group) > 1) {
   4793                         cut_through_eligible = FALSE;
   4794                     break;
   4795                 }
   4796             }
   4797         }
   4798 
   4799         /* Write to L3_IPMC table */
   4800         soc_mem_lock(unit, L3_IPMCm);
   4801         rv = READ_L3_IPMCm(unit, MEM_BLOCK_ANY, repl_group, &l3_ipmc_entry);
   4802         if (BCM_SUCCESS(rv)) {
   4803             if (!soc_L3_IPMCm_field32_get(unit, &l3_ipmc_entry, VALIDf)) {
   4804                 sal_memset(&l3_ipmc_entry, 0, sizeof(ipmc_entry_t));
   4805                 soc_L3_IPMCm_field32_set(unit, &l3_ipmc_entry, VALIDf, 1);
   4806             }
   4807             soc_L3_IPMCm_field32_set(unit, &l3_ipmc_entry, REPL_HEAD_BASE_PTRf,
   4808                     head_index);
   4809             soc_L3_IPMCm_field32_set(unit, &l3_ipmc_entry, DO_NOT_CUT_THROUGHf,
   4810                     !cut_through_eligible);
   4811             rv = WRITE_L3_IPMCm(unit, MEM_BLOCK_ALL, repl_group, &l3_ipmc_entry);
   4812         }
   4813         soc_mem_unlock(unit, L3_IPMCm);
   4814     }
   4815 
   4816     return rv;
   4817 }
   4818 
   4819 #endif /* BCM_TRIDENT2_SUPPORT */
   4820 
   4821 /* Function:
   4822  *	_bcm_tr3_repl_list_start_ptr_set
   4823  * Purpose:
   4824  *      Set replication list start pointer for given (repl_group, port).
   4825  * Parameters:
   4826  *	unit       - StrataSwitch PCI device unit number.
   4827  *	repl_group - The replication group number.
   4828  *	port       - Port.
   4829  *	start_ptr  - Replication list's start pointer.
   4830  *	intf_count - Replication list's interface count.
   4831  * Returns:
   4832  *	BCM_E_XXX
   4833  */
   4834 STATIC int
   4835 _bcm_tr3_repl_list_start_ptr_set(int unit, int repl_group, bcm_port_t port,
   4836                 int start_ptr, int intf_count)
   4837 {
   4838     int add_member;
   4839     soc_info_t *si;
   4840     bcm_port_t phy_port, mmu_port;
   4841     int member_bitmap_index = 0;
   4842     mmu_repl_group_entry_t repl_group_entry;
   4843     uint32 fldbuf[SOC_PBMP_WORD_MAX];
   4844     soc_pbmp_t old_member_bitmap, old_last_bitmap;
   4845     soc_pbmp_t new_member_bitmap, new_last_bitmap;
   4846     int i;
   4847     int old_member_count = 0, new_member_count = 0;
   4848     int member_id, member, old_member_id, new_member_id;
   4849     int old_head_index = 0 , new_head_index = 0;
   4850     mmu_repl_head_tbl_entry_t repl_head_entry, old_repl_head_entry;
   4851 #ifdef BCM_KATANA2_SUPPORT
   4852     mmu_repl_grp_tbl0_entry_t repl_grp_tbl0_entry;
   4853     mmu_repl_grp_tbl1_entry_t repl_grp_tbl1_entry;
   4854     mmu_repl_grp_tbl2_entry_t repl_grp_tbl2_entry;
   4855     mmu_repl_grp_tbl_entry_t repl_grp_tbl_entry;
   4856     _kt2_repl_grp_info_t kt2_repl_grp_info;    
   4857     int last_member_bitmap_index = 0;
   4858     soc_pbmp_t member_bitmap0, member_bitmap1;
   4859     int member_bitmap_width0 = 0;
   4860     int remap_grp_id = 0;
   4861 #endif
   4862     int rv = BCM_E_NONE;
   4863     int reserved_resources_used = 0, loop, num_of_ports = 0;
   4864 
   4865 #ifdef BCM_TRIDENT2_SUPPORT
   4866     int new_head_index_2 = 0, rv2 = BCM_E_NONE;
   4867 #endif
   4868     if (start_ptr > 0) {
   4869         add_member = TRUE;
   4870     } else {
   4871         add_member = FALSE;
   4872     }
   4873    
   4874     si = &SOC_INFO(unit);
   4875 #ifdef BCM_KATANA2_SUPPORT
   4876     if (SOC_IS_KATANA2(unit)) {
   4877 
   4878         sal_memset(&repl_grp_tbl0_entry, 0, sizeof(mmu_repl_grp_tbl0_entry_t));
   4879         sal_memset(&repl_grp_tbl1_entry, 0, sizeof(mmu_repl_grp_tbl1_entry_t));
   4880         sal_memset(&repl_grp_tbl2_entry, 0, sizeof(mmu_repl_grp_tbl2_entry_t));
   4881         sal_memset(&kt2_repl_grp_info, 0, sizeof(kt2_repl_grp_info));
   4882 
   4883         phy_port = port;
   4884         mmu_port = port;
   4885         /* Get the REMAP ID for IPMC index if any */
   4886         BCM_IF_ERROR_RETURN
   4887         (_bcm_kt_ipmc_mmu_mc_remap_ptr(unit, repl_group, &remap_grp_id, FALSE));
   4888 
   4889 
   4890         BCM_IF_ERROR_RETURN(_bcm_kt2_repl_list_tbl_ptr_get (unit, mmu_port,
   4891                &kt2_repl_grp_info));      
   4892 
   4893         member_bitmap_index = mmu_port;
   4894         last_member_bitmap_index = kt2_repl_grp_info.lb_index;
   4895 
   4896         if (soc_mem_field_valid(unit, kt2_repl_grp_info.mb_mem, MEMBER_BMP_PORTSf)) {
   4897             member_bitmap_width0 =  soc_mem_field_length(unit,
   4898                     kt2_repl_grp_info.mb_mem, MEMBER_BMP_PORTSf);
   4899         } else {
   4900         member_bitmap_width0 =  soc_mem_field_length(unit,
   4901                 MMU_REPL_GRP_TBL0m, MEMBER_BMP_PORTS_119_0f);
   4902         }
   4903 
   4904     } else 
   4905 #endif /*BCM_KATANA2_SUPPORT */
   4906     {
   4907         phy_port = si->port_l2p_mapping[port];
   4908         mmu_port = si->port_p2m_mapping[phy_port];
   4909     }
   4910 #ifdef BCM_TRIDENT2_SUPPORT
   4911     if (soc_feature(unit, soc_feature_split_repl_group_table)) {
   4912         int xpipe_member_bitmap_width;
   4913         mmu_repl_group_info0_entry_t repl_group_info0_entry;
   4914         mmu_repl_group_info1_entry_t repl_group_info1_entry;
   4915         soc_pbmp_t xpipe_member_bitmap, ypipe_member_bitmap;
   4916 
   4917         /* In Trident2, REPL_GROUP table is split into 2 halves,
   4918          * one for each pipeline. The X-pipe REPL_GROUP table's
   4919          * member bitmap contains MMU ports 0-52. The Y-pipe REPL_GROUP
   4920          * table's member bitmap contains MMU ports 64-116.
   4921          * These two member bitmaps will be concatenated to form a
   4922          * single 106-bit member bitmap.
   4923          */
   4924         xpipe_member_bitmap_width = soc_mem_field_length(unit,
   4925                 MMU_REPL_GROUP_INFO0m, PIPE_MEMBER_BMPf);
   4926 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   4927         if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) {
   4928             int aggid = TD2P_AGG_ID_INVALID;
   4929             BCM_IF_ERROR_RETURN(bcm_td2p_port_to_aggid(unit, port, &aggid));
   4930                 if (mmu_port >= 64) {
   4931                     member_bitmap_index = aggid + xpipe_member_bitmap_width;
   4932                 } else {
   4933                     member_bitmap_index = aggid;
   4934                 }
   4935         } else
   4936 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   4937         {
   4938             if (mmu_port >= 64) {
   4939                 member_bitmap_index = mmu_port - 64 + xpipe_member_bitmap_width;
   4940             } else {
   4941                 member_bitmap_index = mmu_port;
   4942             }
   4943         }
   4944 
   4945         SOC_IF_ERROR_RETURN(READ_MMU_REPL_GROUP_INFO0m(unit, MEM_BLOCK_ANY,
   4946                     repl_group, &repl_group_info0_entry));
   4947         sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   4948         soc_MMU_REPL_GROUP_INFO0m_field_get(unit, &repl_group_info0_entry,
   4949                 PIPE_MEMBER_BMPf, fldbuf);
   4950         for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   4951             SOC_PBMP_WORD_SET(xpipe_member_bitmap, i, fldbuf[i]);
   4952         }
   4953         old_head_index = soc_MMU_REPL_GROUP_INFO0m_field32_get(unit,
   4954                 &repl_group_info0_entry, PIPE_BASE_PTRf);
   4955 
   4956         SOC_IF_ERROR_RETURN(READ_MMU_REPL_GROUP_INFO1m(unit, MEM_BLOCK_ANY,
   4957                     repl_group, &repl_group_info1_entry));
   4958         sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   4959         soc_MMU_REPL_GROUP_INFO1m_field_get(unit, &repl_group_info1_entry,
   4960                 PIPE_MEMBER_BMPf, fldbuf);
   4961         for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   4962             SOC_PBMP_WORD_SET(ypipe_member_bitmap, i, fldbuf[i]);
   4963         }
   4964         SOC_PBMP_CLEAR(old_member_bitmap);
   4965         SOC_PBMP_OR(old_member_bitmap, xpipe_member_bitmap);
   4966         SOC_PBMP_ITER(ypipe_member_bitmap, member) {
   4967             SOC_PBMP_PORT_ADD(old_member_bitmap,
   4968                     (member + xpipe_member_bitmap_width));
   4969         }
   4970 
   4971         SOC_PBMP_ASSIGN(new_member_bitmap, old_member_bitmap);
   4972         SOC_PBMP_COUNT(old_member_bitmap, old_member_count);
   4973 
   4974     } else if (SOC_IS_APACHE(unit)) {
   4975         mmu_repl_group_info0_entry_t repl_group_info0_entry;
   4976         soc_pbmp_t                   xpipe_member_bitmap;
   4977 
   4978 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   4979         if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) {
   4980             int aggid = TD2P_AGG_ID_INVALID;
   4981             BCM_IF_ERROR_RETURN(bcm_td2p_port_to_aggid(unit, port, &aggid));
   4982             member_bitmap_index = aggid;
   4983         } else
   4984 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   4985         {
   4986             member_bitmap_index = mmu_port;
   4987         }
   4988         SOC_IF_ERROR_RETURN(READ_MMU_REPL_GROUP_INFO0m(unit, MEM_BLOCK_ANY,
   4989                                                        repl_group, 
   4990                                                        &repl_group_info0_entry));
   4991         sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   4992         soc_MMU_REPL_GROUP_INFO0m_field_get(unit, &repl_group_info0_entry,
   4993                                             PIPE_MEMBER_BMPf, fldbuf);
   4994         for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   4995             SOC_PBMP_WORD_SET(xpipe_member_bitmap, i, fldbuf[i]);
   4996         }
   4997         old_head_index = soc_MMU_REPL_GROUP_INFO0m_field32_get(unit,
   4998                           &repl_group_info0_entry, PIPE_BASE_PTRf);
   4999 
   5000         SOC_PBMP_CLEAR(old_member_bitmap);
   5001         SOC_PBMP_OR(old_member_bitmap, xpipe_member_bitmap);
   5002         
   5003         SOC_PBMP_ASSIGN(new_member_bitmap, old_member_bitmap);
   5004         SOC_PBMP_COUNT(old_member_bitmap, old_member_count);
   5005     } else
   5006 #endif /* BCM_TRIDENT2_SUPPORT */
   5007 #ifdef BCM_KATANA2_SUPPORT
   5008     if (SOC_IS_KATANA2(unit)) {
   5009 
   5010         /* Read all the group Tables 
   5011          * read all the member_bitmap and concatenate to get 
   5012          *  the member_bitmap for all the ports
   5013          */
   5014 
   5015         if (SOC_MEM_IS_VALID(unit, MMU_REPL_GRP_TBL0m) && (SOC_MEM_IS_VALID(unit, MMU_REPL_GRP_TBL1m))
   5016                 && (SOC_MEM_IS_VALID(unit, MMU_REPL_GRP_TBL2m))) {
   5017         SOC_IF_ERROR_RETURN(READ_MMU_REPL_GRP_TBL0m(unit, MEM_BLOCK_ANY,
   5018                         remap_grp_id, &repl_grp_tbl0_entry));
   5019        
   5020         SOC_IF_ERROR_RETURN(READ_MMU_REPL_GRP_TBL1m(unit, MEM_BLOCK_ANY,
   5021                         remap_grp_id, &repl_grp_tbl1_entry));
   5022  
   5023         SOC_IF_ERROR_RETURN(READ_MMU_REPL_GRP_TBL2m(unit, MEM_BLOCK_ANY,
   5024                         remap_grp_id, &repl_grp_tbl2_entry));
   5025 
   5026         sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));            
   5027         soc_MMU_REPL_GRP_TBL0m_field_get(unit, &repl_grp_tbl0_entry,
   5028                 MEMBER_BMP_PORTS_119_0f, fldbuf);
   5029         for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   5030             SOC_PBMP_WORD_SET(member_bitmap0, i, fldbuf[i]);
   5031         }
   5032 
   5033         sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   5034         soc_MMU_REPL_GRP_TBL1m_field_get(unit, &repl_grp_tbl1_entry,
   5035                 MEMBER_BMP_PORTS_169_120f, fldbuf);
   5036         for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   5037             SOC_PBMP_WORD_SET(member_bitmap1, i, fldbuf[i]);
   5038         }
   5039    
   5040         SOC_PBMP_CLEAR(old_member_bitmap);
   5041         SOC_PBMP_OR(old_member_bitmap, member_bitmap0);
   5042         SOC_PBMP_ITER(member_bitmap1, member) {
   5043             SOC_PBMP_PORT_ADD(old_member_bitmap,
   5044                     (member + member_bitmap_width0));
   5045         }
   5046 
   5047         SOC_PBMP_ASSIGN(new_member_bitmap, old_member_bitmap);
   5048         SOC_PBMP_COUNT(old_member_bitmap, old_member_count); 
   5049 
   5050         sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   5051         if (mmu_port >= 70)
   5052         {
   5053             soc_mem_field_get(unit, kt2_repl_grp_info.lb_mem, 
   5054                (uint32 *)&repl_grp_tbl2_entry, kt2_repl_grp_info.lbmp, fldbuf);
   5055         } else {
   5056             soc_mem_field_get(unit, kt2_repl_grp_info.lb_mem,
   5057                (uint32 *)&repl_grp_tbl1_entry, kt2_repl_grp_info.lbmp, fldbuf);
   5058         }
   5059     
   5060         for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   5061             SOC_PBMP_WORD_SET(old_last_bitmap, i, fldbuf[i]);
   5062         }
   5063 
   5064         SOC_PBMP_ASSIGN(new_last_bitmap, old_last_bitmap);
   5065 
   5066         old_head_index = soc_MMU_REPL_GRP_TBL2m_field32_get(unit,
   5067                     &repl_grp_tbl2_entry, BASE_PTRf);
   5068         } else if (soc_mem_field_valid(unit, MMU_REPL_GRP_TBL0m, MEMBER_BMP_PORTSf)) {
   5069             /* saber2 */
   5070             SOC_IF_ERROR_RETURN(READ_MMU_REPL_GRP_TBL0m(unit, MEM_BLOCK_ANY,
   5071                         remap_grp_id, &repl_grp_tbl0_entry));
   5072 
   5073             SOC_IF_ERROR_RETURN(READ_MMU_REPL_GRP_TBL1m(unit, MEM_BLOCK_ANY,
   5074                         remap_grp_id, &repl_grp_tbl1_entry));
   5075 
   5076             sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   5077             soc_MMU_REPL_GRP_TBL0m_field_get(unit, &repl_grp_tbl0_entry,
   5078                     MEMBER_BMP_PORTSf, fldbuf);
   5079             for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   5080                 SOC_PBMP_WORD_SET(member_bitmap0, i, fldbuf[i]);
   5081             }
   5082 
   5083             SOC_PBMP_CLEAR(old_member_bitmap);
   5084             SOC_PBMP_OR(old_member_bitmap, member_bitmap0);
   5085             SOC_PBMP_ASSIGN(new_member_bitmap, old_member_bitmap);
   5086             SOC_PBMP_COUNT(old_member_bitmap, old_member_count); 
   5087 
   5088             sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   5089             if (mmu_port >= 24) {
   5090                 soc_mem_field_get(unit, kt2_repl_grp_info.lb_mem, 
   5091                         (uint32 *)&repl_grp_tbl1_entry, kt2_repl_grp_info.lbmp, fldbuf);
   5092             } else {
   5093                 soc_mem_field_get(unit, kt2_repl_grp_info.lb_mem,
   5094                         (uint32 *)&repl_grp_tbl0_entry, kt2_repl_grp_info.lbmp, fldbuf);
   5095             }
   5096             for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   5097                 SOC_PBMP_WORD_SET(old_last_bitmap, i, fldbuf[i]);
   5098             }
   5099             SOC_PBMP_ASSIGN(new_last_bitmap, old_last_bitmap);
   5100             old_head_index = soc_MMU_REPL_GRP_TBL1m_field32_get(unit,
   5101                     &repl_grp_tbl1_entry, BASE_PTRf);
   5102 
   5103         } else if (SOC_IS_METROLITE(unit)) {
   5104 
   5105             SOC_IF_ERROR_RETURN(READ_MMU_REPL_GRP_TBLm(unit, MEM_BLOCK_ANY,
   5106                                           remap_grp_id, &repl_grp_tbl_entry));
   5107             sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   5108             soc_MMU_REPL_GRP_TBLm_field_get(unit, &repl_grp_tbl_entry,
   5109                     MEMBER_BMP_PORTSf, fldbuf);
   5110             for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   5111                 SOC_PBMP_WORD_SET(member_bitmap0, i, fldbuf[i]);
   5112             }
   5113 
   5114             SOC_PBMP_CLEAR(old_member_bitmap);
   5115             SOC_PBMP_OR(old_member_bitmap, member_bitmap0);
   5116             SOC_PBMP_ASSIGN(new_member_bitmap, old_member_bitmap);
   5117             SOC_PBMP_COUNT(old_member_bitmap, old_member_count);
   5118 
   5119             sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   5120             soc_mem_field_get(unit, kt2_repl_grp_info.lb_mem,
   5121                    (uint32 *)&repl_grp_tbl_entry, kt2_repl_grp_info.lbmp, fldbuf);
   5122             for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   5123                 SOC_PBMP_WORD_SET(old_last_bitmap, i, fldbuf[i]);
   5124             }
   5125             SOC_PBMP_ASSIGN(new_last_bitmap, old_last_bitmap);
   5126             old_head_index = soc_MMU_REPL_GRP_TBLm_field32_get(unit,
   5127                     &repl_grp_tbl_entry, BASE_PTRf);
   5128 
   5129         } else {
   5130 
   5131             LOG_ERROR(BSL_LS_BCM_COMMON,
   5132                       (BSL_META_U(unit,
   5133                                   "REPL_GRP_TBL invalid memory\n")));
   5134             return BCM_E_INTERNAL;
   5135         }
   5136     } else
   5137 #endif /* BCM_KATANA2_SUPPORT*/
   5138     {
   5139          /* Triumph3 MMU does not support replication on
   5140           * ports 57, 59, 61 and 62 */
   5141         if ((mmu_port == 57) || (mmu_port == 59) || 
   5142             (mmu_port == 61) || (mmu_port == 62)) {
   5143             return BCM_E_PORT;
   5144         } else if (mmu_port == 60) {
   5145             member_bitmap_index = 59;
   5146         } else {
   5147             member_bitmap_index = mmu_port;
   5148         } 
   5149         SOC_IF_ERROR_RETURN(READ_MMU_REPL_GROUPm(unit, MEM_BLOCK_ANY, 
   5150                         repl_group,&repl_group_entry));
   5151 
   5152         sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   5153         soc_MMU_REPL_GROUPm_field_get(unit, &repl_group_entry, MEMBER_BITMAPf,
   5154                     fldbuf);
   5155         for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   5156             SOC_PBMP_WORD_SET(old_member_bitmap, i, fldbuf[i]);
   5157         }
   5158         SOC_PBMP_ASSIGN(new_member_bitmap, old_member_bitmap);
   5159         SOC_PBMP_COUNT(old_member_bitmap, old_member_count);
   5160 
   5161         sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   5162         soc_MMU_REPL_GROUPm_field_get(unit, &repl_group_entry, LAST_BITMAPf,
   5163                     fldbuf);
   5164         for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   5165             SOC_PBMP_WORD_SET(old_last_bitmap, i, fldbuf[i]);
   5166         }
   5167         SOC_PBMP_ASSIGN(new_last_bitmap, old_last_bitmap);
   5168         old_head_index = soc_MMU_REPL_GROUPm_field32_get(unit, 
   5169                     &repl_group_entry, HEAD_INDEXf);
   5170     }
   5171 
   5172     if (add_member) {
   5173 
   5174         /* Update REPL_HEAD table */
   5175 
   5176         sal_memset(&repl_head_entry, 0, sizeof(mmu_repl_head_tbl_entry_t));
   5177         soc_MMU_REPL_HEAD_TBLm_field32_set(unit, &repl_head_entry,
   5178                 HEAD_PTRf, start_ptr);
   5179         if (soc_mem_field_valid(unit, MMU_REPL_HEAD_TBLm, ADDL_REPSf)) {
   5180             if (intf_count > 4) {
   5181                 soc_MMU_REPL_HEAD_TBLm_field32_set(unit, &repl_head_entry,
   5182                         ADDL_REPSf, 3);
   5183             } else if (intf_count > 1) {
   5184                 soc_MMU_REPL_HEAD_TBLm_field32_set(unit, &repl_head_entry,
   5185                         ADDL_REPSf, intf_count - 2);
   5186             } else {
   5187                 soc_MMU_REPL_HEAD_TBLm_field32_set(unit, &repl_head_entry,
   5188                         ADDL_REPSf, 0);
   5189             }
   5190         }
   5191 
   5192         if (SOC_PBMP_MEMBER(old_member_bitmap, member_bitmap_index)) {
   5193             /* Port is already a member of the group */
   5194             member_id = 0; 
   5195             SOC_PBMP_ITER(old_member_bitmap, member) {
   5196                 if (member == member_bitmap_index) {
   5197                     break;
   5198                 }
   5199                 member_id++;
   5200             }
   5201             SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_HEAD_TBLm(unit, MEM_BLOCK_ALL,
   5202                         old_head_index + member_id, &repl_head_entry));
   5203             new_head_index = old_head_index;
   5204         } else {
   5205             if (soc_feature(unit, soc_feature_static_repl_head_alloc)) {
   5206                 /* If REPL_HEAD entries are statically allocated to
   5207                  * replication groups, the port should already be set
   5208                  * in member_bitmap.
   5209                  */
   5210                 return BCM_E_PORT;
   5211             }
   5212             SOC_PBMP_PORT_ADD(new_member_bitmap, member_bitmap_index);
   5213             new_member_count = old_member_count + 1;
   5214             BCM_IF_ERROR_RETURN(_bcm_tr3_repl_head_block_alloc(unit,
   5215                         new_member_count, &new_head_index));
   5216             old_member_id = 0;
   5217             new_member_id = 0;
   5218             SOC_PBMP_ITER(new_member_bitmap, member) {
   5219                 if (member == member_bitmap_index) {
   5220                    SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_HEAD_TBLm(unit,
   5221                                 MEM_BLOCK_ALL, new_head_index + new_member_id,
   5222                                 &repl_head_entry));
   5223                 } else {
   5224                     SOC_IF_ERROR_RETURN(READ_MMU_REPL_HEAD_TBLm(unit,
   5225                                 MEM_BLOCK_ANY, old_head_index + old_member_id,
   5226                                 &old_repl_head_entry));
   5227                     SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_HEAD_TBLm(unit,
   5228                                 MEM_BLOCK_ALL, new_head_index + new_member_id,
   5229                                 &old_repl_head_entry));
   5230                     old_member_id++;
   5231                 }
   5232                 new_member_id++;
   5233             }           
   5234         }
   5235  
   5236         /* Update REPL_GROUP entry */
   5237 
   5238 #ifdef BCM_TRIDENT2_SUPPORT
   5239         if ((soc_feature(unit, soc_feature_split_repl_group_table)) ||
   5240             SOC_IS_APACHE(unit)) {
   5241             BCM_IF_ERROR_RETURN(_bcm_td2_repl_initial_copy_count_set(unit,
   5242                         repl_group, port, intf_count));
   5243             BCM_IF_ERROR_RETURN(_bcm_td2_repl_group_info_set(unit,
   5244                         repl_group, new_member_bitmap, new_head_index));
   5245         } else
   5246 #endif /* BCM_TRIDENT2_SUPPORT */
   5247 #ifdef BCM_KATANA2_SUPPORT
   5248         if (SOC_IS_KATANA2(unit)) {
   5249 
   5250             if (intf_count == 1) {
   5251                 SOC_PBMP_PORT_ADD(new_last_bitmap, last_member_bitmap_index);
   5252             } else {
   5253                 SOC_PBMP_PORT_REMOVE(new_last_bitmap, last_member_bitmap_index);
   5254             }
   5255             
   5256             BCM_IF_ERROR_RETURN(_bcm_kt2_repl_group_info_set(unit, 
   5257                          remap_grp_id, port, new_member_bitmap,
   5258                          new_last_bitmap, new_head_index)); 
   5259 
   5260        } else 
   5261 #endif
   5262         {
   5263             for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   5264                 fldbuf[i] = SOC_PBMP_WORD_GET(new_member_bitmap, i);
   5265             }
   5266             soc_MMU_REPL_GROUPm_field_set(unit, &repl_group_entry,
   5267                         MEMBER_BITMAPf, fldbuf);
   5268            
   5269             if (intf_count == 1) {
   5270                 SOC_PBMP_PORT_ADD(new_last_bitmap, member_bitmap_index);
   5271             } else {
   5272                 SOC_PBMP_PORT_REMOVE(new_last_bitmap, member_bitmap_index);
   5273             }
   5274 
   5275             for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   5276                 fldbuf[i] = SOC_PBMP_WORD_GET(new_last_bitmap, i);
   5277             }
   5278             soc_MMU_REPL_GROUPm_field_set(unit, &repl_group_entry,
   5279                         LAST_BITMAPf, fldbuf);
   5280 
   5281             soc_MMU_REPL_GROUPm_field32_set(unit, &repl_group_entry,
   5282                         HEAD_INDEXf, new_head_index);
   5283 
   5284             SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_GROUPm(unit, MEM_BLOCK_ALL,
   5285                             repl_group, &repl_group_entry));
   5286         }
   5287 
   5288         /* Release old block of REPL_HEAD entries */
   5289         if (old_member_count > 0 && old_head_index != new_head_index) {
   5290             if (soc_feature(unit, soc_feature_repl_head_ptr_replace)) {
   5291                 BCM_IF_ERROR_RETURN(_bcm_tr3_repl_head_ptr_replace(unit,
   5292                             old_head_index, old_member_bitmap,
   5293                             new_head_index, new_member_bitmap,
   5294                             new_last_bitmap));
   5295             }
   5296             BCM_IF_ERROR_RETURN(_bcm_tr3_repl_head_block_free(unit,
   5297                         old_head_index, old_member_count));
   5298         }
   5299 
   5300 #ifdef BCM_TRIDENT2_SUPPORT
   5301         /*
   5302          * If we are here then we have already allocated a new index for
   5303          * head_block. But as the algorithm tries to add members in scaled
   5304          * system, fragmentation occurs in table which results in
   5305          * under utilization of replication tables.
   5306          * To solve that problem, a quick solution is done here
   5307          * to try to re-allocate an index from list after freeing
   5308          * old indexes and if smaller index is found, then allocate
   5309          * that index.
   5310          */
   5311         if (soc_feature(unit, soc_feature_mmu_repl_alloc_unfrag)) {
   5312             if (!SOC_PBMP_MEMBER(old_member_bitmap, member_bitmap_index)) {
   5313                 rv2 = _bcm_tr3_repl_head_block_alloc(unit,
   5314                         new_member_count, &new_head_index_2);
   5315 
   5316                 if (BCM_SUCCESS(rv2)) {
   5317 
   5318                     if (new_head_index_2 < new_head_index) {
   5319                         old_member_id = 0;
   5320                         new_member_id = 0;
   5321 
   5322                         SOC_PBMP_ITER(new_member_bitmap, member) {
   5323                             SOC_IF_ERROR_RETURN(READ_MMU_REPL_HEAD_TBLm(unit,
   5324                                 MEM_BLOCK_ANY, new_head_index + old_member_id,
   5325                                 &old_repl_head_entry));
   5326                             SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_HEAD_TBLm(unit,
   5327                                 MEM_BLOCK_ALL, new_head_index_2 + new_member_id,
   5328                                 &old_repl_head_entry));
   5329                             old_member_id++;
   5330                             new_member_id++;
   5331                         }
   5332 
   5333 
   5334                         BCM_IF_ERROR_RETURN(_bcm_td2_repl_group_info_set(unit,
   5335                             repl_group, new_member_bitmap, new_head_index_2));
   5336 
   5337                         _bcm_tr3_repl_head_block_free(unit,
   5338                             new_head_index, new_member_count);
   5339 
   5340                     } else {
   5341                         _bcm_tr3_repl_head_block_free(unit,
   5342                             new_head_index_2, new_member_count);
   5343                     }
   5344                 }
   5345             }
   5346         }
   5347 #endif
   5348     } else {
   5349         /* Remove member from replication group */
   5350 
   5351         if (soc_feature(unit, soc_feature_static_repl_head_alloc)) {
   5352             /* Clear REPL_HEAD entry */
   5353             member_id = 0; 
   5354             SOC_PBMP_ITER(old_member_bitmap, member) {
   5355                 if (member == member_bitmap_index) {
   5356                     break;
   5357                 }
   5358                 member_id++;
   5359             }
   5360             SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_HEAD_TBLm(unit,
   5361                         MEM_BLOCK_ALL, old_head_index + member_id,
   5362                         soc_mem_entry_null(unit, MMU_REPL_HEAD_TBLm)));
   5363 
   5364             /* Set bit in LAST_BITMAP */
   5365             SOC_PBMP_PORT_ADD(new_last_bitmap, member_bitmap_index);
   5366             for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   5367                 fldbuf[i] = SOC_PBMP_WORD_GET(new_last_bitmap, i);
   5368             }
   5369 
   5370             soc_MMU_REPL_GROUPm_field_set(unit, &repl_group_entry,
   5371                         LAST_BITMAPf, fldbuf);
   5372             SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_GROUPm(unit, MEM_BLOCK_ALL,
   5373                             repl_group, &repl_group_entry));
   5374             return BCM_E_NONE;
   5375         }
   5376 
   5377         if (!SOC_PBMP_MEMBER(old_member_bitmap, member_bitmap_index)) {
   5378             /* Port is not a member. Nothing more to do. */
   5379             return BCM_E_NONE;
   5380         }
   5381 
   5382         /* Update REPL_HEAD table */
   5383 
   5384         new_member_count = old_member_count - 1;
   5385         for (loop = 0; loop < 2; loop++) {
   5386             if (new_member_count > 0) {
   5387                 rv = _bcm_tr3_repl_head_block_alloc(unit,
   5388                                                     new_member_count,
   5389                                                     &new_head_index);
   5390                 if (BCM_FAILURE(rv)) {
   5391                     if (!reserve_multicast_resources[unit]) {
   5392                         return rv; 
   5393                     }
   5394                     BCM_PBMP_COUNT(PBMP_ALL(unit), num_of_ports);
   5395                     new_head_index = 
   5396                         soc_mem_index_max(unit, MMU_REPL_HEAD_TBLm)
   5397                                      - num_of_ports + 1;
   5398                     reserved_resources_used = 1;
   5399                 }
   5400                 old_member_id = 0;
   5401                 new_member_id = 0;
   5402                 SOC_PBMP_ITER(old_member_bitmap, member) {
   5403                     if (member != member_bitmap_index) {
   5404                         SOC_IF_ERROR_RETURN(READ_MMU_REPL_HEAD_TBLm(unit,
   5405                                 MEM_BLOCK_ANY, old_head_index + old_member_id,
   5406                                 &old_repl_head_entry));
   5407                         SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_HEAD_TBLm(unit,
   5408                                 MEM_BLOCK_ALL, new_head_index + new_member_id,
   5409                                 &old_repl_head_entry));
   5410                         new_member_id++;
   5411                     }
   5412                     old_member_id++;
   5413                 }
   5414             } else {
   5415                 new_head_index = 0;
   5416             }
   5417 
   5418             if (loop == 0) {
   5419                 SOC_PBMP_PORT_REMOVE(new_member_bitmap, member_bitmap_index);
   5420             }
   5421 
   5422         /* Update REPL_GROUP entry */
   5423 
   5424 #ifdef BCM_TRIDENT2_SUPPORT
   5425             if (soc_feature(unit, soc_feature_split_repl_group_table) ||
   5426                 (SOC_IS_APACHE(unit))) {
   5427                 BCM_IF_ERROR_RETURN(_bcm_td2_repl_initial_copy_count_set(unit,
   5428                             repl_group, port, 0));
   5429                 BCM_IF_ERROR_RETURN(_bcm_td2_repl_group_info_set(unit,
   5430                             repl_group, new_member_bitmap, new_head_index));
   5431             } else
   5432 #endif /* BCM_TRIDENT2_SUPPORT */
   5433 #ifdef BCM_KATANA2_SUPPORT
   5434             if (SOC_IS_KATANA2(unit)) {
   5435                 if (loop == 0) {
   5436                     SOC_PBMP_PORT_REMOVE(new_last_bitmap, 
   5437                                               last_member_bitmap_index);
   5438                 }
   5439                 
   5440                 BCM_IF_ERROR_RETURN(_bcm_kt2_repl_group_info_set(unit,
   5441                              remap_grp_id, port, new_member_bitmap,
   5442                              new_last_bitmap, new_head_index));
   5443             } else 
   5444 #endif /*BCM_KATANA2_SUPPORT */
   5445             {
   5446                 for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   5447                     fldbuf[i] = SOC_PBMP_WORD_GET(new_member_bitmap, i);
   5448                 }
   5449                 soc_MMU_REPL_GROUPm_field_set(unit, &repl_group_entry,
   5450                          MEMBER_BITMAPf, fldbuf);
   5451 
   5452                 SOC_PBMP_PORT_REMOVE(new_last_bitmap, member_bitmap_index);
   5453                 for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   5454                     fldbuf[i] = SOC_PBMP_WORD_GET(new_last_bitmap, i);
   5455                 }
   5456                 soc_MMU_REPL_GROUPm_field_set(unit, &repl_group_entry,
   5457                             LAST_BITMAPf, fldbuf);
   5458 
   5459                 soc_MMU_REPL_GROUPm_field32_set(unit, &repl_group_entry,
   5460                             HEAD_INDEXf, new_head_index);
   5461 
   5462                 SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_GROUPm(unit, MEM_BLOCK_ALL,
   5463                                 repl_group, &repl_group_entry));
   5464             }
   5465 
   5466         /* Release old block of REPL_HEAD entries */
   5467             if (soc_feature(unit, soc_feature_repl_head_ptr_replace)) {
   5468                 BCM_IF_ERROR_RETURN(_bcm_tr3_repl_head_ptr_replace(unit,
   5469                             old_head_index, old_member_bitmap,
   5470                             new_head_index, new_member_bitmap,
   5471                             new_last_bitmap));
   5472             }
   5473 
   5474             if (loop == 0) {
   5475                 BCM_IF_ERROR_RETURN(_bcm_tr3_repl_head_block_free(unit,
   5476                             old_head_index, old_member_count));
   5477             }
   5478 
   5479             if (!reserved_resources_used) {
   5480                 break;
   5481             }
   5482 
   5483             old_head_index = new_head_index;
   5484             BCM_PBMP_ASSIGN(old_member_bitmap, new_member_bitmap);            
   5485         }
   5486     }
   5487 
   5488     return BCM_E_NONE;
   5489 }
   5490 
   5491 /*
   5492  * Function:
   5493  *	_bcm_tr3_repl_list_start_ptr_get
   5494  * Purpose:
   5495  *      Get replication list start pointer for given (repl_group, port).
   5496  * Parameters:
   5497  *	unit       - StrataSwitch PCI device unit number.
   5498  *	repl_group - The replication group number.
   5499  *	port       - Port.
   5500  *	start_ptr  - (OUT) Replication list's start pointer to
   5501  *	             REPL_LIST table.
   5502  * Returns:
   5503  *	BCM_E_XXX
   5504  */
   5505 STATIC int
   5506 _bcm_tr3_repl_list_start_ptr_get(int unit, int repl_group, bcm_port_t port,
   5507         int *start_ptr)
   5508 {
   5509     soc_info_t *si;
   5510     bcm_port_t phy_port, mmu_port;
   5511     int member_bitmap_index;
   5512     soc_mem_t repl_group_table;
   5513     soc_field_t member_bitmap_f, head_index_f; 
   5514     uint32 repl_group_entry[SOC_MAX_MEM_FIELD_WORDS];
   5515     uint32 fldbuf[SOC_PBMP_WORD_MAX];
   5516     soc_pbmp_t member_bitmap;
   5517     int i;
   5518     int member_id = 0;
   5519     int member;
   5520     int head_index;
   5521     mmu_repl_head_tbl_entry_t repl_head_entry;
   5522 #ifdef BCM_KATANA2_SUPPORT
   5523     _kt2_repl_grp_info_t kt2_repl_grp_info;
   5524     mmu_repl_grp_tbl0_entry_t repl_grp_tbl0_entry;
   5525     soc_pbmp_t member_bitmap0;
   5526     mmu_repl_grp_tbl2_entry_t repl_group_base_ptr_entry;
   5527     int remap_grp_id = 0;
   5528 
   5529     sal_memset(&repl_grp_tbl0_entry, 0, sizeof(mmu_repl_grp_tbl0_entry_t));
   5530     sal_memset(&member_bitmap0, 0, sizeof(member_bitmap0));
   5531 #endif /* BCM_KATANA2_SUPPORT */
   5532 
   5533     si = &SOC_INFO(unit);
   5534     sal_memset(&member_bitmap, 0, sizeof(member_bitmap));
   5535     sal_memset(&repl_group_table, 0, sizeof(repl_group_table));
   5536 
   5537 #ifdef BCM_KATANA2_SUPPORT
   5538     if (SOC_IS_KATANA2(unit)) {
   5539         phy_port = port;
   5540         mmu_port = port;
   5541         BCM_IF_ERROR_RETURN
   5542         (_bcm_kt_ipmc_mmu_mc_remap_ptr(unit, repl_group, &remap_grp_id, FALSE));
   5543     } else 
   5544 #endif /* BCM_KATANA2_SUPPORT */
   5545     {
   5546         phy_port = si->port_l2p_mapping[port];
   5547         mmu_port = si->port_p2m_mapping[phy_port];
   5548     }
   5549 
   5550 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   5551     if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) {
   5552         int aggid = TD2P_AGG_ID_INVALID;
   5553         BCM_IF_ERROR_RETURN(bcm_td2p_port_to_aggid(unit, port, &aggid));
   5554         member_bitmap_index = aggid;
   5555     } else
   5556 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   5557     {
   5558         member_bitmap_index = mmu_port;
   5559     }
   5560 #ifdef BCM_APACHE_SUPPORT
   5561     if (SOC_IS_APACHE(unit)) {
   5562         repl_group_table = MMU_REPL_GROUP_INFO0m;
   5563         member_bitmap_f = PIPE_MEMBER_BMPf;
   5564         head_index_f = PIPE_BASE_PTRf;
   5565     } else
   5566 #endif /* BCM_APACHE_SUPPORT */
   5567 #ifdef BCM_TRIDENT2_SUPPORT
   5568     if (soc_feature(unit, soc_feature_split_repl_group_table)) {
   5569         /* Trident2 has 108 MMU ports: port 0-53 in X pipe, 64-117 in Y pipe.
   5570          * MMU ports 53 and 117 are purge ports.
   5571          */
   5572 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   5573         if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) {
   5574             if (mmu_port >= 64) {
   5575                 repl_group_table = MMU_REPL_GROUP_INFO1m;
   5576             } else {
   5577                 repl_group_table = MMU_REPL_GROUP_INFO0m;
   5578             }
   5579         } else
   5580 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   5581         {
   5582             if (mmu_port >= 64) {
   5583                 member_bitmap_index = mmu_port - 64;
   5584                 repl_group_table = MMU_REPL_GROUP_INFO1m;
   5585             } else {
   5586                 repl_group_table = MMU_REPL_GROUP_INFO0m;
   5587             }
   5588         }
   5589         member_bitmap_f = PIPE_MEMBER_BMPf;
   5590         head_index_f = PIPE_BASE_PTRf;
   5591     } else
   5592 #endif /* BCM_TRIDENT2_SUPPORT */
   5593     {
   5594 #ifdef BCM_KATANA2_SUPPORT
   5595         if (SOC_IS_KATANA2(unit)) {
   5596             sal_memset(&kt2_repl_grp_info, 0, sizeof(kt2_repl_grp_info));
   5597             BCM_IF_ERROR_RETURN(_bcm_kt2_repl_list_tbl_ptr_get (unit, mmu_port,
   5598                &kt2_repl_grp_info));
   5599             repl_group_table  = kt2_repl_grp_info.mb_mem;
   5600             member_bitmap_f = kt2_repl_grp_info.mbmp;
   5601             head_index_f = BASE_PTRf;
   5602         } else 
   5603 #endif /* BCM_KATANA2_SUPPORT */
   5604         { 
   5605             repl_group_table = MMU_REPL_GROUPm;
   5606             member_bitmap_f = MEMBER_BITMAPf;
   5607             head_index_f = HEAD_INDEXf;
   5608  
   5609             /* Triumph3 MMU does not support replication on ports 57, 59, 61 and 62 */
   5610             if ((mmu_port == 57) || (mmu_port == 59) || (mmu_port == 61) || (mmu_port == 62)) {
   5611                 return BCM_E_PORT;
   5612             } else if (mmu_port == 60) {
   5613                 member_bitmap_index = 59;
   5614             }   
   5615         }
   5616     }
   5617 
   5618 #ifdef BCM_KATANA2_SUPPORT
   5619     if (SOC_IS_KATANA2(unit)) {
   5620         if (mmu_port >=120) {
   5621             /* when port added to the replication list  >=120,
   5622              * the IPMC_VLAN pointer is calculated based on number of
   5623              * ports added to the multicast group, both the port members
   5624              * in range 0-119 and 120-169
   5625              */
   5626             member_bitmap_index = mmu_port - 120;
   5627             SOC_IF_ERROR_RETURN(READ_MMU_REPL_GRP_TBL0m(unit, MEM_BLOCK_ANY,
   5628                         remap_grp_id, &repl_grp_tbl0_entry));
   5629             sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   5630             soc_MMU_REPL_GRP_TBL0m_field_get(unit, &repl_grp_tbl0_entry,
   5631                    MEMBER_BMP_PORTS_119_0f, fldbuf);
   5632             for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   5633                 SOC_PBMP_WORD_SET(member_bitmap0, i, fldbuf[i]);
   5634             }
   5635 
   5636             SOC_PBMP_ITER(member_bitmap0, member) {
   5637                 member_id++;
   5638             }
   5639         }
   5640         SOC_IF_ERROR_RETURN(soc_mem_read(unit, repl_group_table, MEM_BLOCK_ANY,
   5641                   remap_grp_id, repl_group_entry));
   5642     } else
   5643 #endif /* BCM_KATANA2_SUPPORT */
   5644     {
   5645         SOC_IF_ERROR_RETURN(soc_mem_read(unit, repl_group_table, MEM_BLOCK_ANY,
   5646                 repl_group, repl_group_entry));
   5647     } 
   5648 
   5649     sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   5650     soc_mem_field_get(unit, repl_group_table, repl_group_entry,
   5651             member_bitmap_f, fldbuf);
   5652     for (i = 0; i < SOC_PBMP_WORD_MAX; i++) {
   5653         SOC_PBMP_WORD_SET(member_bitmap, i, fldbuf[i]);
   5654     }
   5655     if (!SOC_PBMP_MEMBER(member_bitmap, member_bitmap_index)) {
   5656         /* Port is not set in member_bitmap */
   5657         *start_ptr = 0;
   5658         return BCM_E_NONE;
   5659     }
   5660 
   5661     SOC_PBMP_ITER(member_bitmap, member) {
   5662         if (member == member_bitmap_index) {
   5663             break;
   5664         }
   5665         member_id++;
   5666     }
   5667 #ifdef BCM_KATANA2_SUPPORT
   5668     if (SOC_IS_KATANA2(unit)) {
   5669         if (soc_mem_is_valid(unit, MMU_REPL_GRP_TBL2m)) {
   5670         SOC_IF_ERROR_RETURN(soc_mem_read(unit, MMU_REPL_GRP_TBL2m, MEM_BLOCK_ANY,
   5671                     remap_grp_id, &repl_group_base_ptr_entry));
   5672         head_index = member_id + soc_mem_field32_get(unit, MMU_REPL_GRP_TBL2m,
   5673                 &repl_group_base_ptr_entry, head_index_f);
   5674         } else if (soc_mem_is_valid(unit, MMU_REPL_GRP_TBL1m)) {
   5675             SOC_IF_ERROR_RETURN(soc_mem_read(unit, MMU_REPL_GRP_TBL1m, MEM_BLOCK_ANY,
   5676                         remap_grp_id, &repl_group_base_ptr_entry));
   5677             head_index = member_id + soc_mem_field32_get(unit, MMU_REPL_GRP_TBL1m,
   5678                     &repl_group_base_ptr_entry, head_index_f);
   5679         } else {
   5680             SOC_IF_ERROR_RETURN(soc_mem_read(unit, MMU_REPL_GRP_TBLm, MEM_BLOCK_ANY,
   5681                         remap_grp_id, &repl_group_base_ptr_entry));
   5682             head_index = member_id + soc_mem_field32_get(unit, MMU_REPL_GRP_TBLm,
   5683                     &repl_group_base_ptr_entry, head_index_f);
   5684         }
   5685     } else
   5686 #endif /* BCM_KATANA2_SUPPORT */
   5687     {
   5688         head_index = member_id + soc_mem_field32_get(unit, repl_group_table,
   5689                 repl_group_entry, head_index_f);
   5690     }
   5691     SOC_IF_ERROR_RETURN(READ_MMU_REPL_HEAD_TBLm(unit, MEM_BLOCK_ANY, head_index,
   5692                 &repl_head_entry));
   5693     *start_ptr = soc_MMU_REPL_HEAD_TBLm_field32_get(unit, &repl_head_entry,
   5694             HEAD_PTRf);
   5695 
   5696     return BCM_E_NONE;
   5697 }
   5698 
   5699 /*
   5700  * Function:
   5701  *	_bcm_tr3_repl_list_free
   5702  * Purpose:
   5703  *	Free the REPL_LIST entries in the HW list starting at start_ptr.
   5704  * Parameters:
   5705  *	unit      - StrataSwitch PCI device unit number.
   5706  *	start_ptr - Replication list's start pointer to
   5707  *	            REPL_LIST table.
   5708  * Returns:
   5709  *	BCM_E_XXX
   5710  */
   5711 STATIC int
   5712 _bcm_tr3_repl_list_free(int unit, int start_ptr)
   5713 {
   5714     mmu_repl_list_tbl_entry_t repl_list_entry;
   5715     int	prev_repl_entry_ptr, repl_entry_ptr;
   5716 
   5717     prev_repl_entry_ptr = -1;
   5718     repl_entry_ptr = start_ptr;
   5719 
   5720     while (repl_entry_ptr != prev_repl_entry_ptr) {
   5721         SOC_IF_ERROR_RETURN
   5722             (READ_MMU_REPL_LIST_TBLm(unit, MEM_BLOCK_ANY,
   5723                                      repl_entry_ptr, &repl_list_entry));
   5724         BCM_IF_ERROR_RETURN
   5725             (_bcm_tr3_repl_list_entry_free(unit, repl_entry_ptr)); 
   5726         prev_repl_entry_ptr = repl_entry_ptr;
   5727         repl_entry_ptr = soc_MMU_REPL_LIST_TBLm_field32_get(unit,
   5728                 &repl_list_entry, NEXTPTRf);
   5729     }
   5730 
   5731     return BCM_E_NONE;
   5732 }
   5733 
   5734 #ifdef BCM_KATANA2_SUPPORT
   5735 /*
   5736  * Function:
   5737  *      _bcm_kt2_repl_list_write
   5738  * Purpose:
   5739  *      Write the replication list contained in intf_vec into REPL_LIST table.
   5740  *      Return the start_ptr and total interface count.
   5741  * Parameters:
   5742  *      unit       - StrataSwitch PCI device unit number.
   5743  *      intf_vec   - (IN) Vector of interfaces.
   5744  *      nh_count   - (IN) Next hop count.
   5745  *      start_ptr  - (OUT) Replication list's start pointer to
   5746  *                   REPL_LIST table.
   5747  *      intf_count - (OUT) Interface count.
   5748  * Returns:
   5749  *      BCM_E_XXX
   5750  */
   5751 STATIC int
   5752 _bcm_kt2_repl_list_write(int unit, SHR_BITDCL *intf_vec, 
   5753                          uint32 nh_count, int *start_ptr, int *intf_count)
   5754 {
   5755     int i;
   5756     int remaining_count;
   5757     int prev_repl_entry_ptr, repl_entry_ptr;
   5758     uint32 msb_max, msb;
   5759     uint32 ls_bits[2];
   5760     int rv = BCM_E_NONE;
   5761     int no_more_free_repl_entries;
   5762     mmu_repl_list_tbl_entry_t repl_list_entry;
   5763     int if_cnt, nh_cnt, offset;
   5764     uint32 ms_bit;
   5765     uint32 repl_type =0;
   5766 
   5767     if_cnt = soc_mem_index_count(unit, EGR_L3_INTFm);
   5768     nh_cnt = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
   5769     *intf_count = 0;
   5770 
   5771     for (i = 0; i < _SHR_BITDCLSIZE(REPL_INTF_TOTAL(unit)); i++) {
   5772         *intf_count += _shr_popcount(intf_vec[i]);
   5773     }
   5774 
   5775     if (*intf_count == 0) {
   5776         return BCM_E_NONE;
   5777     }
   5778 
   5779     if (nh_count > 0) {
   5780         repl_type = 1;
   5781         msb_max = _SHR_BITDCLSIZE(nh_cnt) / 2; /* 32 -> 64 */
   5782     } else {
   5783         msb_max = _SHR_BITDCLSIZE(if_cnt) / 2; /* 32 -> 64 */
   5784     }
   5785 
   5786     offset = (repl_type == 0)? 0 : _SHR_BITDCLSIZE(if_cnt);
   5787 
   5788     remaining_count = *intf_count;
   5789     prev_repl_entry_ptr = -1;
   5790 
   5791 
   5792     for (msb = 0; msb < msb_max; msb++) {
   5793 
   5794         ls_bits[0] = intf_vec[offset + 2 * msb + 0];
   5795         ls_bits[1] = intf_vec[offset + 2 * msb + 1];
   5796         if ((ls_bits[0] != 0) || (ls_bits[1] != 0)) {
   5797             rv = _bcm_tr3_repl_list_entry_alloc(unit, &repl_entry_ptr);
   5798             if (rv == BCM_E_RESOURCE) {
   5799                 no_more_free_repl_entries = TRUE;
   5800             } else if (BCM_FAILURE(rv)) {
   5801                 return rv;
   5802             } else {
   5803                 no_more_free_repl_entries = FALSE;
   5804             }
   5805             if (prev_repl_entry_ptr == -1) {
   5806                 if (no_more_free_repl_entries) {
   5807                     return BCM_E_RESOURCE;
   5808                 }
   5809                 *start_ptr = repl_entry_ptr;
   5810             } else {
   5811                 if (no_more_free_repl_entries) {
   5812                     /* Terminate replication list */
   5813                     soc_MMU_REPL_LIST_TBLm_field32_set(unit, &repl_list_entry,
   5814                             NEXTPTRf, prev_repl_entry_ptr);
   5815                 } else {
   5816                     soc_MMU_REPL_LIST_TBLm_field32_set(unit, &repl_list_entry,
   5817                             NEXTPTRf, repl_entry_ptr);
   5818                 }
   5819                 SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_LIST_TBLm(unit,
   5820                             MEM_BLOCK_ALL, prev_repl_entry_ptr,
   5821                             &repl_list_entry));
   5822                 if (no_more_free_repl_entries) {
   5823                     /* Free the list already written */
   5824                     _bcm_tr3_repl_list_free(unit, *start_ptr);
   5825                     return BCM_E_RESOURCE;
   5826                 }
   5827             }
   5828             prev_repl_entry_ptr = repl_entry_ptr;
   5829 
   5830             sal_memset(&repl_list_entry, 0, sizeof(repl_list_entry));
   5831             if (repl_type == 1) {
   5832                 /* Replication is over next hops */
   5833                 /* coverity[large_shift : FALSE] */
   5834                 ms_bit = msb + (1 << (soc_mem_field_length(unit, 
   5835                                       MMU_REPL_LIST_TBLm, MSB_VLANf) - 1));
   5836             } else {
   5837                 /* Replication is over interfaces */
   5838                 ms_bit = msb;
   5839             }
   5840             soc_MMU_REPL_LIST_TBLm_field32_set(unit, &repl_list_entry,
   5841                     MSB_VLANf, ms_bit);
   5842             soc_MMU_REPL_LIST_TBLm_field_set(unit, &repl_list_entry,
   5843                     LSB_VLAN_BMf, ls_bits);
   5844 
   5845             remaining_count -= (_shr_popcount(ls_bits[0]) +
   5846                     _shr_popcount(ls_bits[1]));
   5847              if (remaining_count > 4) {
   5848                /* Set the RMNG_REPS field to all ones */
   5849                 soc_MMU_REPL_LIST_TBLm_field32_set(unit, &repl_list_entry,
   5850                         RMNG_REPSf, (1 << soc_mem_field_length(unit,
   5851                         MMU_REPL_LIST_TBLm, RMNG_REPSf)) - 1);
   5852              } else if (remaining_count > 0) {
   5853                 soc_MMU_REPL_LIST_TBLm_field32_set(unit, &repl_list_entry,
   5854                             RMNG_REPSf, remaining_count - 1);
   5855 
   5856              } else { /* No more intefaces left to be written */
   5857                 break;
   5858              }
   5859         }
   5860     }
   5861 
   5862     if (prev_repl_entry_ptr > 0) {
   5863         /* Write final entry */
   5864         soc_MMU_REPL_LIST_TBLm_field32_set(unit,
   5865                           &repl_list_entry, NEXTPTRf, prev_repl_entry_ptr);
   5866         SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_LIST_TBLm(unit,
   5867                    MEM_BLOCK_ALL, prev_repl_entry_ptr, &repl_list_entry));
   5868     }
   5869 
   5870     return BCM_E_NONE;
   5871 }
   5872 
   5873 /*
   5874  * Function:
   5875  *      _bcm_kt2_repl_list_compare
   5876  * Purpose:
   5877  *      Compare replication list starting at given pointer to
   5878  *      the interface list contained in intf_vec.
   5879  * Parameters:
   5880  *      unit      - StrataSwitch PCI device unit number.
   5881  *      start_ptr - (IN) Replication list's start pointer to REPL_LIST table.
   5882  *      intf_vec  - (IN) Vector of interfaces.
   5883  *      nh_count  - (IN) next hops count
   5884  * Returns:
   5885  *      BCM_E_XXX
   5886  */
   5887 STATIC int
   5888 _bcm_kt2_repl_list_compare(int unit, int start_ptr,
   5889                           SHR_BITDCL *intf_vec, uint32 nh_count)
   5890 {
   5891     uint32              msb, msb_val, hw_msb, msb_max;
   5892     uint32              ls_bits[2], hw_ls_bits[2];
   5893     mmu_repl_list_tbl_entry_t repl_list_entry;
   5894     int                 repl_entry_ptr, prev_repl_entry_ptr;
   5895     uint32   offset, if_cnt, nh_cnt;
   5896     uint32 repl_type =0;
   5897     prev_repl_entry_ptr = -1;
   5898     repl_entry_ptr = start_ptr;
   5899 
   5900     if_cnt = soc_mem_index_count(unit, EGR_L3_INTFm);
   5901     nh_cnt = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm);
   5902 
   5903 
   5904     if (nh_count > 0) {
   5905         repl_type = 1;
   5906         msb_max = _SHR_BITDCLSIZE(nh_cnt) / 2; /* 32 -> 64 */
   5907     } else {
   5908         msb_max = _SHR_BITDCLSIZE(if_cnt) / 2; /* 32 -> 64 */
   5909     }
   5910 
   5911     offset = (repl_type == 0)? 0 : _SHR_BITDCLSIZE(if_cnt);
   5912 
   5913     for (msb = 0; msb < msb_max; msb++) {
   5914         ls_bits[0] = intf_vec[offset + 2 * msb + 0];
   5915         ls_bits[1] = intf_vec[offset + 2 * msb + 1];
   5916         if ((ls_bits[0] != 0) || (ls_bits[1] != 0)) {
   5917             if (repl_entry_ptr == prev_repl_entry_ptr) { /* HW list end */
   5918                 return BCM_E_NOT_FOUND;
   5919             }
   5920             SOC_IF_ERROR_RETURN(READ_MMU_REPL_LIST_TBLm(unit, MEM_BLOCK_ANY,
   5921                         repl_entry_ptr, &repl_list_entry));
   5922             hw_msb = soc_MMU_REPL_LIST_TBLm_field32_get(unit,
   5923                     &repl_list_entry, MSB_VLANf);
   5924             soc_MMU_REPL_LIST_TBLm_field_get(unit, &repl_list_entry,
   5925                     LSB_VLAN_BMf, hw_ls_bits);
   5926 
   5927             if (repl_type == 1) {
   5928                 /* coverity[large_shift : FALSE] */
   5929                 msb_val = msb + (1 << (soc_mem_field_length(unit,
   5930                                       MMU_REPL_LIST_TBLm, MSB_VLANf) - 1)); 
   5931             } else {
   5932                 msb_val = msb;
   5933             }
   5934             if ((hw_msb != msb_val) || (ls_bits[0] != hw_ls_bits[0]) ||
   5935                     (ls_bits[1] != hw_ls_bits[1])) {
   5936                 return BCM_E_NOT_FOUND;
   5937             }
   5938             prev_repl_entry_ptr = repl_entry_ptr;
   5939             repl_entry_ptr = soc_MMU_REPL_LIST_TBLm_field32_get(unit,
   5940                     &repl_list_entry, NEXTPTRf);
   5941         }
   5942     }
   5943     /*
   5944      * Make sure that h/w has also reached to end.
   5945      * only then we can say that this is a matched entry.
   5946      */
   5947     if (repl_entry_ptr != prev_repl_entry_ptr) {
   5948         return BCM_E_NOT_FOUND;
   5949     }
   5950 
   5951 
   5952     return BCM_E_NONE;
   5953 }
   5954 
   5955 /*
   5956  * Function:
   5957  *      _bcm_kt2_repl_intf_vec_construct
   5958  * Purpose:
   5959  *      Construct replication interface vector.
   5960  * Parameters:
   5961  *      unit       - StrataSwitch PCI device unit number.
   5962  *      port       - (IN) Port.
   5963  *      if_count   - (IN) Number of interfaces in replication list.
   5964  *      if_array   - (IN) List of interface numbers.
   5965  *      is_l3      - (IN) Indicates if interfaces are IPMC interfaces.
   5966  *      check_port - (IN) If if_array consists of L3 interfaces, this parameter
   5967  *                   controls whether to check the given port is a member
   5968  *                   in each L3 interface's VLAN. This check should be
   5969  *                   disabled when not needed, in order to improve
   5970  *                   performance.
   5971  *      intf_vec   - (OUT) Vector of interfaces.
   5972  *      nh_count   - (OUT) Next hop Count
   5973  * Returns:
   5974  *      BCM_E_XXX
   5975  */
   5976 STATIC int
   5977 _bcm_kt2_repl_intf_vec_construct(int unit, bcm_port_t port, int if_count,
   5978         bcm_if_t *if_array, int is_l3, int check_port, SHR_BITDCL *intf_vec,
   5979         uint32 *nh_count)
   5980 {
   5981     int if_num;
   5982     bcm_l3_intf_t l3_intf;
   5983     uint32 partition;
   5984     uint32 nextHop = 0;
   5985 
   5986     partition =  soc_mem_index_count(unit, EGR_L3_INTFm);
   5987 
   5988     for (if_num = 0; if_num < if_count; if_num++) {
   5989         if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, if_array[if_num])) {
   5990             /* L3 interface is used */
   5991 
   5992             if (if_array[if_num] > soc_mem_index_max(unit, EGR_L3_INTFm)) {
   5993                 return BCM_E_PARAM;
   5994             }
   5995 
   5996             if (check_port) {
   5997                 bcm_l3_intf_t_init(&l3_intf);
   5998                 l3_intf.l3a_intf_id = if_array[if_num];
   5999                 BCM_IF_ERROR_RETURN(bcm_esw_l3_intf_get(unit, &l3_intf));
   6000             }
   6001 
   6002             /* Get a next hop index if the L3 inteface is not already
   6003              * associated with one.
   6004              */
   6005             if (is_l3) { /* L3 interface is being added to IPMC group */
   6006                 SHR_BITSET(intf_vec, if_array[if_num]);
   6007             }
   6008         } else {
   6009             /* Next hop is used */
   6010             SHR_BITSET(intf_vec, partition + if_array[if_num] -
   6011                        BCM_XGS3_DVP_EGRESS_IDX_MIN(unit));
   6012             nextHop++;
   6013         }
   6014     }
   6015     *nh_count = nextHop;
   6016 
   6017     return BCM_E_NONE;
   6018 }
   6019 
   6020 #endif /* BCM_KATANA2_SUPPORT */
   6021 /*
   6022  * Function:
   6023  *	_bcm_tr3_repl_list_write
   6024  * Purpose:
   6025  *	Write the replication list contained in intf_vec into REPL_LIST table.
   6026  *      Return the start_ptr and total interface count.
   6027  * Parameters:
   6028  *	unit       - StrataSwitch PCI device unit number.
   6029  *	start_ptr  - (OUT) Replication list's start pointer to
   6030  *	             REPL_LIST table.
   6031  *      intf_count - (OUT) Interface count.
   6032  *	intf_vec   - (IN) Vector of interfaces.
   6033  * Returns:
   6034  *	BCM_E_XXX
   6035  */
   6036 STATIC int
   6037 _bcm_tr3_repl_list_write(int unit, int *start_ptr, int *intf_count,
   6038                         SHR_BITDCL *intf_vec)
   6039 {
   6040     int i;
   6041     int remaining_count;
   6042     int prev_repl_entry_ptr, repl_entry_ptr;
   6043     uint32 msb_max, msb;
   6044     uint32 ls_bits[2];
   6045     int rv = BCM_E_NONE;
   6046     int no_more_free_repl_entries;
   6047     mmu_repl_list_tbl_entry_t repl_list_entry;
   6048 
   6049     *intf_count = 0;
   6050     for (i = 0; i < _SHR_BITDCLSIZE(REPL_INTF_TOTAL(unit)); i++) {
   6051         *intf_count += _shr_popcount(intf_vec[i]);
   6052     }
   6053 
   6054     if (*intf_count == 0) {
   6055         return BCM_E_NONE;
   6056     }
   6057 
   6058     remaining_count = *intf_count;
   6059     prev_repl_entry_ptr = -1;
   6060     msb_max = _SHR_BITDCLSIZE(REPL_INTF_TOTAL(unit)) / 2; /* 32 -> 64 */
   6061     for (msb = 0; msb < msb_max; msb++) {
   6062         ls_bits[0] = intf_vec[2 * msb + 0];
   6063         ls_bits[1] = intf_vec[2 * msb + 1];
   6064         if ((ls_bits[0] != 0) || (ls_bits[1] != 0)) {
   6065             rv = _bcm_tr3_repl_list_entry_alloc(unit, &repl_entry_ptr);
   6066             if (rv == BCM_E_RESOURCE) {
   6067                 no_more_free_repl_entries = TRUE;
   6068             } else if (BCM_FAILURE(rv)) {
   6069                 return rv;
   6070             } else {
   6071                 no_more_free_repl_entries = FALSE;
   6072             }
   6073             if (prev_repl_entry_ptr == -1) {
   6074                 if (no_more_free_repl_entries) {
   6075                     return BCM_E_RESOURCE;
   6076                 }
   6077                 *start_ptr = repl_entry_ptr;
   6078             } else {
   6079                 if (no_more_free_repl_entries) {
   6080                     /* Terminate replication list */
   6081                     soc_MMU_REPL_LIST_TBLm_field32_set(unit, &repl_list_entry,
   6082                             NEXTPTRf, prev_repl_entry_ptr);
   6083                 } else {
   6084                     soc_MMU_REPL_LIST_TBLm_field32_set(unit, &repl_list_entry,
   6085                             NEXTPTRf, repl_entry_ptr);
   6086                 }
   6087                 SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_LIST_TBLm(unit,
   6088                             MEM_BLOCK_ALL, prev_repl_entry_ptr,
   6089                             &repl_list_entry));
   6090                 if (no_more_free_repl_entries) {
   6091                     /* Free the list already written */
   6092                     _bcm_tr3_repl_list_free(unit, *start_ptr);
   6093                     return BCM_E_RESOURCE;
   6094                 }
   6095             } 
   6096             prev_repl_entry_ptr = repl_entry_ptr;
   6097 
   6098             sal_memset(&repl_list_entry, 0, sizeof(repl_list_entry));
   6099             soc_MMU_REPL_LIST_TBLm_field32_set(unit, &repl_list_entry,
   6100                     MSB_VLANf, msb);
   6101             soc_MMU_REPL_LIST_TBLm_field_set(unit, &repl_list_entry,
   6102                     LSB_VLAN_BMf, ls_bits);
   6103 
   6104             remaining_count -= (_shr_popcount(ls_bits[0]) +
   6105                     _shr_popcount(ls_bits[1]));
   6106 #ifdef BCM_TRIDENT2_SUPPORT
   6107             if (SOC_IS_TD2_TT2(unit)) {
   6108                 if (remaining_count > 5) {
   6109                     /* Set the RMNG_REPS field to all zeroes */
   6110                     soc_MMU_REPL_LIST_TBLm_field32_set(unit, &repl_list_entry,
   6111                             RMNG_REPSf, 0);
   6112                 } else if (remaining_count > 0) {
   6113                     soc_MMU_REPL_LIST_TBLm_field32_set(unit, &repl_list_entry,
   6114                             RMNG_REPSf, remaining_count);
   6115                 } else { /* No more intefaces left to be written */
   6116                     break;
   6117                 }
   6118             } else
   6119 #endif /* BCM_TRIDENT2_SUPPORT */
   6120             {
   6121                 if (remaining_count > 4) {
   6122                     /* Set the RMNG_REPS field to all ones */
   6123                     soc_MMU_REPL_LIST_TBLm_field32_set(unit, &repl_list_entry,
   6124                             RMNG_REPSf, (1 << soc_mem_field_length(unit,
   6125                                     MMU_REPL_LIST_TBLm, RMNG_REPSf)) - 1);
   6126                 } else if (remaining_count > 0) {
   6127                     soc_MMU_REPL_LIST_TBLm_field32_set(unit, &repl_list_entry,
   6128                             RMNG_REPSf, remaining_count - 1);
   6129 
   6130                 } else { /* No more intefaces left to be written */
   6131                     break;
   6132                 }
   6133             }
   6134         }
   6135     }
   6136 
   6137     if (prev_repl_entry_ptr > 0) {
   6138         /* Write final entry */
   6139         soc_MMU_REPL_LIST_TBLm_field32_set(unit,
   6140                           &repl_list_entry, NEXTPTRf, prev_repl_entry_ptr);
   6141         SOC_IF_ERROR_RETURN(WRITE_MMU_REPL_LIST_TBLm(unit,
   6142                    MEM_BLOCK_ALL, prev_repl_entry_ptr, &repl_list_entry));
   6143     }
   6144 
   6145     return BCM_E_NONE;
   6146 }
   6147 
   6148 /*
   6149  * Function:
   6150  *	_bcm_tr3_repl_list_compare
   6151  * Purpose:
   6152  *	Compare replication list starting at given pointer to
   6153  *	the interface list contained in intf_vec.
   6154  * Parameters:
   6155  *	unit - StrataSwitch PCI device unit number.
   6156  *	start_ptr - Replication list's start pointer to REPL_LIST table.
   6157  *	intf_vec - Vector of interfaces.
   6158  * Returns:
   6159  *	BCM_E_XXX
   6160  */
   6161 STATIC int
   6162 _bcm_tr3_repl_list_compare(int unit, int start_ptr,
   6163                           SHR_BITDCL *intf_vec)
   6164 {
   6165     uint32                    hw_msb;
   6166     uint32                    hw_ls_bits[2];
   6167     int                       repl_entry_ptr, prev_repl_entry_ptr;
   6168     SHR_BITDCL                *hw_vec = NULL;
   6169     int                       alloc_sz;
   6170     int                       rv;
   6171     mmu_repl_list_tbl_entry_t repl_list_entry;
   6172 
   6173     prev_repl_entry_ptr = -1;
   6174     repl_entry_ptr = start_ptr;
   6175     alloc_sz = SHR_BITALLOCSIZE(REPL_INTF_TOTAL(unit));
   6176 
   6177     hw_vec = sal_alloc(alloc_sz, "hw_vec");
   6178     if (hw_vec == NULL ) {
   6179         return SOC_E_MEMORY;
   6180     }
   6181     sal_memset(hw_vec, 0, alloc_sz);
   6182 
   6183     while (repl_entry_ptr != prev_repl_entry_ptr) {
   6184         rv = READ_MMU_REPL_LIST_TBLm(unit, MEM_BLOCK_ANY,
   6185                                      repl_entry_ptr, &repl_list_entry);
   6186         if(BCM_FAILURE(rv)) {
   6187             sal_free(hw_vec);
   6188             return rv;
   6189         }
   6190 
   6191         hw_msb = soc_MMU_REPL_LIST_TBLm_field32_get(unit, &repl_list_entry,
   6192                                                     MSB_VLANf);
   6193         soc_MMU_REPL_LIST_TBLm_field_get(unit, &repl_list_entry, LSB_VLAN_BMf,
   6194                                          hw_ls_bits);
   6195         hw_vec[2 * hw_msb + 0] = hw_ls_bits[0];
   6196         hw_vec[2 * hw_msb + 1] = hw_ls_bits[1];
   6197         prev_repl_entry_ptr = repl_entry_ptr;
   6198         repl_entry_ptr = soc_MMU_REPL_LIST_TBLm_field32_get(unit,
   6199                                                             &repl_list_entry,
   6200                                                             NEXTPTRf);
   6201     }
   6202 
   6203     if (SHR_BITEQ_RANGE(intf_vec, hw_vec, 0, REPL_INTF_TOTAL(unit))) {
   6204         sal_free(hw_vec);
   6205         return BCM_E_NONE;
   6206     }
   6207 
   6208     sal_free(hw_vec);
   6209     return BCM_E_NOT_FOUND;
   6210 }
   6211 
   6212 /*
   6213  * Function:
   6214  *	_bcm_tr3_repl_intf_vec_construct
   6215  * Purpose:
   6216  *	Construct replication interface vector.
   6217  * Parameters:
   6218  *	unit       - StrataSwitch PCI device unit number.
   6219  *	port       - Port.
   6220  *	if_count   - Number of interfaces in replication list.
   6221  *  if_array   - (IN) List of interface numbers.
   6222  *  if_updated - (IN) interfaces info to be updated including
   6223  *                    interfaces which is new to the group and port
   6224  *                    and interfaces to be deleted.
   6225  *  is_l3      - (IN) Indicates if interfaces are IPMC interfaces.
   6226  *  check_port - If if_array consists of L3 interfaces, this parameter 
   6227  *                   controls whether to check the given port is a member
   6228  *                   in each L3 interface's VLAN. This check should be  
   6229  *                   disabled when not needed, in order to improve
   6230  *                   performance.
   6231  *  intf_vec   - (OUT) Vector of interfaces.
   6232  * Returns:
   6233  *	BCM_E_XXX
   6234  */
   6235 STATIC int
   6236 _bcm_tr3_repl_intf_vec_construct(
   6237      int unit, bcm_port_t port, int if_count, bcm_if_t *if_array,
   6238      _tr3_if_updated_t *if_updated, int is_l3, int check_port,
   6239      SHR_BITDCL *intf_vec)
   6240 {
   6241     int if_num;
   6242     bcm_l3_intf_t l3_intf;
   6243     uint32 nh_flags;
   6244     bcm_l3_egress_t nh_info;
   6245     int nh_index;
   6246     egr_l3_next_hop_entry_t egr_nh;
   6247     int mac_oui, mac_non_oui;
   6248     bcm_mac_t rbridge_mac;
   6249 #if defined(BCM_HGPROXY_COE_SUPPORT)
   6250     bcm_port_t port_in = port;
   6251 #endif
   6252 
   6253 
   6254 #if defined(BCM_HGPROXY_COE_SUPPORT)
   6255     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   6256         BCM_GPORT_IS_SET(port) &&
   6257         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) {
   6258             BCM_IF_ERROR_RETURN(
   6259                 _bcmi_coe_subport_physical_port_get(unit, port, &port));
   6260     }
   6261 #endif
   6262 
   6263     if (is_l3) {
   6264         bcm_if_t intf;
   6265         int ref_count = 0;
   6266         for (if_num = 0; if_num < if_updated->if_count_del; if_num++) {
   6267             intf = if_updated->if_array_del[if_num];
   6268             if (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, intf)) {
   6269                 continue;
   6270             }
   6271 
   6272             if (REPL_L3_INTF_NEXT_HOP_IPMC(unit, intf) == 
   6273                 REPL_NH_INDEX_L3_EGRESS_ALLOCATED) {
   6274                 /* This next hop attached to the intf is allocated 
   6275                  * by bcm_l3_egress_create. 
   6276                  */
   6277                 continue;
   6278             }
   6279             
   6280             if (intf > soc_mem_index_max(unit, EGR_L3_INTFm)) {
   6281                 return BCM_E_PARAM;
   6282             }
   6283             /* Decrease the NH ref count when the intf is deleted
   6284              * from <group, port>. 
   6285              */
   6286             nh_index = REPL_L3_INTF_NEXT_HOP_IPMC(unit, intf);
   6287             BCM_IF_ERROR_RETURN(bcm_xgs3_nh_del(unit, 0, nh_index));
   6288             BCM_IF_ERROR_RETURN(
   6289                 bcm_xgs3_nh_ref_count_get(unit, nh_index, &ref_count));
   6290             if (ref_count == 0) {
   6291                 REPL_L3_INTF_NEXT_HOP_IPMC(unit, intf) = 
   6292                     REPL_NH_INDEX_UNALLOCATED;
   6293             }                
   6294         }
   6295     }
   6296     
   6297     for (if_num = 0; if_num < if_count; if_num++) {
   6298         if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, if_array[if_num])) {
   6299             /* L3 interface is used */
   6300 
   6301             if (if_array[if_num] > soc_mem_index_max(unit, EGR_L3_INTFm)) {
   6302                 return BCM_E_PARAM;
   6303             }
   6304 
   6305             if (check_port) {
   6306                 bcm_l3_intf_t_init(&l3_intf);
   6307                 l3_intf.l3a_intf_id = if_array[if_num];
   6308                 BCM_IF_ERROR_RETURN(bcm_esw_l3_intf_get(unit, &l3_intf));
   6309             }
   6310 
   6311             if (is_l3) { /* L3 interface is being added to IPMC group */
   6312                 if (REPL_L3_INTF_NEXT_HOP_IPMC(unit, if_array[if_num]) ==
   6313                         REPL_NH_INDEX_UNALLOCATED) {
   6314                     /* A next hop index has not been allocated for the L3
   6315                      * inteface yet. Allocate a new next hop index.
   6316                      */
   6317                     bcm_l3_egress_t_init(&nh_info);
   6318                     nh_flags = _BCM_L3_SHR_MATCH_DISABLE |
   6319                         _BCM_L3_SHR_WRITE_DISABLE;
   6320                     BCM_IF_ERROR_RETURN
   6321                         (bcm_xgs3_nh_add(unit, nh_flags, &nh_info, &nh_index));
   6322 
   6323                     sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t));
   6324                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   6325                             ENTRY_TYPEf, 7);
   6326                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   6327                             L3MC__INTF_NUMf, if_array[if_num]);
   6328                     if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
   6329                                 L3MC__L2_MC_DA_DISABLEf)) {
   6330                         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   6331                                 L3MC__L2_MC_DA_DISABLEf, 1);
   6332                     }
   6333                     if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
   6334                                 L3MC__L2_MC_SA_DISABLEf)) {
   6335                         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   6336                                 L3MC__L2_MC_SA_DISABLEf, 1);
   6337                     }
   6338                     if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
   6339                                 L3MC__L2_MC_VLAN_DISABLEf)) {
   6340                         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   6341                                 L3MC__L2_MC_VLAN_DISABLEf, 1);
   6342                     }
   6343 #if defined(BCM_HGPROXY_COE_SUPPORT)
   6344                     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   6345                         BCM_GPORT_IS_SET(port_in) &&
   6346                         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port_in)) {
   6347                         bcm_module_t mod_out;
   6348                         bcm_port_t port_out;
   6349                         bcm_trunk_t trunk_id;
   6350                         int local_id;
   6351 
   6352                         BCM_IF_ERROR_RETURN(
   6353                             _bcm_esw_gport_resolve(unit, port_in,
   6354                                                    &mod_out, &port_out,
   6355                                                    &trunk_id, &local_id));
   6356                         if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
   6357                                                 L3MC__USE_MAC_DA_PROFILEf)) {
   6358                             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   6359                                                 L3MC__USE_MAC_DA_PROFILEf,
   6360                                                 TRUE);
   6361                         }
   6362                         if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
   6363                                                 L3MC__HG_MC_DST_PORT_NUMf)) {
   6364                             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   6365                                                 L3MC__HG_MC_DST_PORT_NUMf,
   6366                                                 port_out);
   6367                         }
   6368                         if (soc_mem_field_valid(unit, EGR_L3_NEXT_HOPm,
   6369                                                 L3MC__HG_MC_DST_MODIDf)) {
   6370                             soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   6371                                                 L3MC__HG_MC_DST_MODIDf,
   6372                                                 mod_out);
   6373                         }
   6374                     }
   6375 #endif
   6376                     SOC_IF_ERROR_RETURN(soc_mem_write(unit, EGR_L3_NEXT_HOPm,
   6377                                 MEM_BLOCK_ALL, nh_index, &egr_nh));
   6378 
   6379                     REPL_L3_INTF_NEXT_HOP_IPMC(unit, if_array[if_num]) =
   6380                         nh_index;
   6381                 } else if (REPL_L3_INTF_NEXT_HOP_IPMC(unit, if_array[if_num]) ==
   6382                         REPL_NH_INDEX_L3_EGRESS_ALLOCATED) {
   6383                     /* A next hop index has already been allocated for this
   6384                      * L3 interface by the bcm_l3_egress_create API. Adding
   6385                      * such L3 interface directly to the IPMC group is not
   6386                      * allowed. To add the L3 egress object to an IPMC group,
   6387                      * first call bcm_multicast_egress_object_encap_get to get
   6388                      * an encap ID, then add the encap ID to the group.
   6389                      */
   6390                     return BCM_E_CONFIG;
   6391                 } else {
   6392                     /* IPMC module had already silently allocated a next hop
   6393                      * index for this L3 interface.
   6394                      * But the next hop reference count should be increased
   6395                      * if the intf is new to the <group, port>.
   6396                      */
   6397                     int if_num_new;
   6398                     for (if_num_new = 0; if_num_new < if_updated->if_count_new;
   6399                          if_num_new++) {
   6400                         if (if_array[if_num] == 
   6401                             if_updated->if_array_new[if_num_new]) {
   6402                             nh_index = 
   6403                                 REPL_L3_INTF_NEXT_HOP_IPMC(unit,
   6404                                                            if_array[if_num]);
   6405                             _bcm_xgs3_nh_ref_cnt_incr(unit, nh_index);
   6406                             break;
   6407                         }
   6408                     }
   6409                 }
   6410 
   6411                 SHR_BITSET(intf_vec,
   6412                     REPL_L3_INTF_NEXT_HOP_IPMC(unit, if_array[if_num]));
   6413 
   6414             } else { /* L3 interface is being added to Trill group */
   6415                 if (REPL_L3_INTF_NEXT_HOP_TRILL(unit, if_array[if_num]) == -1) {
   6416                     bcm_l3_egress_t_init(&nh_info);
   6417                     nh_flags = _BCM_L3_SHR_MATCH_DISABLE |
   6418                         _BCM_L3_SHR_WRITE_DISABLE;
   6419                     BCM_IF_ERROR_RETURN
   6420                         (bcm_xgs3_nh_add(unit, nh_flags, &nh_info, &nh_index));
   6421 
   6422                     sal_memset(&egr_nh, 0, sizeof(egr_l3_next_hop_entry_t));
   6423 #ifdef BCM_TRIDENT2_SUPPORT
   6424                     if (SOC_IS_TD2_TT2(unit)) {
   6425                         /*
   6426                          * TD2 needs to set the entry_type to 0x7 (L3MC) 
   6427                          * in order to use trill_all_rbridges_macda as the DA 
   6428                          * in TRILL header 
   6429                          */
   6430                         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   6431                                 ENTRY_TYPEf, 7);
   6432                     } else
   6433 #endif /* BCM_TRIDENT2_SUPPORT */                        
   6434                     {
   6435                         soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   6436                                 ENTRY_TYPEf, 0);
   6437                     }
   6438                     soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   6439                             L3__INTF_NUMf, if_array[if_num]);
   6440 
   6441                     /* Get and Set rbridge mac */
   6442                     BCM_IF_ERROR_RETURN(bcm_esw_switch_control_get(unit,
   6443                             bcmSwitchTrillBroadcastDestMacOui, &mac_oui)); 
   6444                     BCM_IF_ERROR_RETURN(bcm_esw_switch_control_get(unit,
   6445                             bcmSwitchTrillBroadcastDestMacNonOui, &mac_non_oui)); 
   6446                     rbridge_mac[0] = (mac_oui >> 16) & 0xff;
   6447                     rbridge_mac[1] = (mac_oui >> 8) & 0xff;
   6448                     rbridge_mac[2] = mac_oui & 0xff;
   6449                     rbridge_mac[3] = (mac_non_oui >> 16) & 0xff;
   6450                     rbridge_mac[4] = (mac_non_oui >> 8) & 0xff;
   6451                     rbridge_mac[5] = mac_non_oui & 0xff;
   6452                     soc_mem_mac_addr_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   6453                             L3__MAC_ADDRESSf, rbridge_mac);
   6454 
   6455                     SOC_IF_ERROR_RETURN(soc_mem_write(unit, EGR_L3_NEXT_HOPm,
   6456                                 MEM_BLOCK_ALL, nh_index, &egr_nh));
   6457 
   6458                     REPL_L3_INTF_NEXT_HOP_TRILL(unit, if_array[if_num]) =
   6459                         nh_index;
   6460                 }
   6461                 SHR_BITSET(intf_vec,
   6462                     REPL_L3_INTF_NEXT_HOP_TRILL(unit, if_array[if_num]));
   6463             }
   6464         } else {
   6465             /* Next hop is used */
   6466             SHR_BITSET(intf_vec,
   6467                     if_array[if_num] - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit));
   6468         }
   6469     }
   6470 
   6471     return BCM_E_NONE;
   6472 }
   6473 
   6474 /*
   6475  * Function:
   6476  *	_bcm_tr3_ipmc_egress_intf_set
   6477  * Purpose:
   6478  *	Assign set of egress interfaces to port's replication list for chosen
   6479  *	replication group.
   6480  * Parameters:
   6481  *	unit       - StrataSwitch PCI device unit number.
   6482  *	repl_group - The replication group number.
   6483  *	port       - Port to assign replication list.
   6484  *	if_count   - Number of interfaces in replication list.
   6485  *  if_array   - (IN) List of interface numbers.
   6486  *  if_updated - (IN) interfaces info to be updated including
   6487  *                    interfaces which is new to the group and port
   6488  *                    and interfaces to be deleted.
   6489  *  is_l3      - (IN) Indicates if multicast group is of type IPMC.
   6490  *  check_port - (IN) If if_array consists of L3 interfaces, this parameter 
   6491  *                        controls whether to check the given port is a member
   6492  *                        in each L3 interface's VLAN. This check should be  
   6493  *                        disabled when not needed, in order to improve
   6494  *                        performance.
   6495  *  prev_start_ptr - (IN) Start pointer of existing replication list.
   6496  * Returns:
   6497  *	BCM_E_XXX
   6498  */
   6499 STATIC int
   6500 _bcm_tr3_ipmc_egress_intf_set(
   6501     int unit, int repl_group, bcm_port_t port, int if_count,
   6502     bcm_if_t *if_array, _tr3_if_updated_t *if_updated,
   6503     int is_l3, int check_port, int prev_start_ptr)
   6504 {
   6505     int rv = BCM_E_NONE;
   6506     int set_repl_list;
   6507     int list_start_ptr=0;
   6508     int alloc_size;
   6509     SHR_BITDCL *intf_vec = NULL;
   6510     int repl_hash;
   6511     _bcm_repl_list_info_t *rli_current, *rli_prev;
   6512     int intf_count;
   6513     int new_repl_list = FALSE;
   6514 #ifdef BCM_KATANA2_SUPPORT
   6515     soc_field_t  last_ptr = INVALIDf;
   6516     soc_mem_t    rqe_mem = INVALIDm;
   6517     mmu_ipmc_group_tbl0_entry_t rqe_entry;
   6518     uint32 nh_count =0;
   6519     _kt2_rep_regs_t     *rqe_arr_ptr;
   6520     int ipmc_id = 0 ;
   6521     int last = 0;
   6522 #endif /* BCM_KATANA2_SUPPORT */
   6523     int repl_intf_total;
   6524     int intf_cnt_old = 0;
   6525     bcm_port_t port_in = port;
   6526 
   6527 
   6528     REPL_INIT(unit);
   6529     REPL_GROUP_ID(unit, repl_group);
   6530 
   6531 #if defined(BCM_HGPROXY_COE_SUPPORT)
   6532     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   6533         BCM_GPORT_IS_SET(port) &&
   6534         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) {
   6535             BCM_IF_ERROR_RETURN(
   6536                 _bcmi_coe_subport_physical_port_get(unit, port, &port));
   6537     }
   6538 #endif
   6539 
   6540     /* Replication is allowed on CPU ports, only on TD2 */
   6541     if (IS_CPU_PORT(unit, port)) {
   6542         if (!SOC_IS_TRIDENT2X(unit)) {
   6543             return BCM_E_PARAM;
   6544         }
   6545     } else {   
   6546         REPL_PORT_CHECK(unit, port);
   6547     }
   6548 
   6549     repl_intf_total = REPL_INTF_TOTAL(unit);
   6550     if (if_count > repl_intf_total) {
   6551         return BCM_E_PARAM;
   6552     } else if (if_count > 0) {
   6553         set_repl_list = TRUE;
   6554     } else {
   6555         set_repl_list = FALSE;
   6556     }
   6557 
   6558     intf_cnt_old = REPL_PORT_GROUP_INTF_COUNT(unit, port, repl_group);
   6559     if (set_repl_list) {
   6560         /* Set new replication list for given (repl_group, port) */
   6561 
   6562         alloc_size = SHR_BITALLOCSIZE(repl_intf_total);
   6563         intf_vec = sal_alloc(alloc_size, "Repl interface vector");
   6564         if (intf_vec == NULL) {
   6565             rv = BCM_E_MEMORY;
   6566             goto intf_set_done;
   6567         }
   6568         sal_memset(intf_vec, 0, alloc_size);
   6569 
   6570         /* Interface validation and vector construction */
   6571 #ifdef BCM_KATANA2_SUPPORT
   6572         if (SOC_IS_KATANA2(unit)) {
   6573             rv = _bcm_kt2_repl_intf_vec_construct(unit, port, if_count, 
   6574                       if_array, is_l3, check_port, intf_vec, &nh_count);
   6575         }
   6576         else
   6577 #endif /* BCM_KATANA2_SUPPORT */
   6578         {
   6579             rv = _bcm_tr3_repl_intf_vec_construct(unit, port_in, if_count,
   6580                                                   if_array, if_updated,
   6581                                                   is_l3, check_port, intf_vec);
   6582         }
   6583         if (BCM_FAILURE(rv)) {
   6584             goto intf_set_done;
   6585         }
   6586 
   6587         /* Search for matching replication list */
   6588         if ((_shr_popcount(*(uint32 *)intf_vec) == if_count) && 
   6589             (repl_intf_total >= SHR_BITWID)) {
   6590             repl_hash = _shr_crc32b(0, (uint8 *)intf_vec, SHR_BITWID);
   6591         } else {
   6592             repl_hash = _shr_crc32b(0, (uint8 *)intf_vec, repl_intf_total);
   6593         }
   6594         for (rli_current = REPL_LIST_INFO(unit); rli_current != NULL;
   6595                 rli_current = rli_current->next) {
   6596             if (repl_hash == rli_current->hash) {
   6597 #ifdef BCM_KATANA2_SUPPORT
   6598                 if (SOC_IS_KATANA2(unit)) {
   6599                     rv = _bcm_kt2_repl_list_compare(unit, rli_current->index,
   6600                           intf_vec, nh_count);
   6601                 } else 
   6602 #endif /* BCM_KATANA2_SUPPORT */
   6603                 {    
   6604                     rv = _bcm_tr3_repl_list_compare(unit, rli_current->index,
   6605                         intf_vec);
   6606                 }
   6607                 if (rv == BCM_E_NOT_FOUND) {
   6608                     continue; /* Not a match */
   6609                 } else if (BCM_FAILURE(rv)) {
   6610                     goto intf_set_done; 
   6611                 } else {
   6612                     break; /* Match */
   6613                 }
   6614             }
   6615         }
   6616 
   6617         if (rli_current != NULL) {
   6618             /* Found a match */
   6619             if (prev_start_ptr == rli_current->index) {
   6620                 /* (repl_group, port) already points to this list, so done */
   6621                 rv = BCM_E_NONE;
   6622                 goto intf_set_done;
   6623             } else {
   6624                 list_start_ptr = rli_current->index;
   6625                 intf_count = rli_current->list_size;
   6626             }
   6627         } else {
   6628             /* Not a match, make a new chain */
   6629 #ifdef BCM_KATANA2_SUPPORT
   6630             if (SOC_IS_KATANA2(unit)) {
   6631                rv = _bcm_kt2_repl_list_write(unit,
   6632                      intf_vec, nh_count, &list_start_ptr, &intf_count);
   6633             } else 
   6634 #endif /* BCM_KATANA2_SUPPORT */
   6635             {
   6636                rv = _bcm_tr3_repl_list_write(unit, &list_start_ptr,
   6637                      &intf_count, intf_vec);
   6638             }
   6639             if (BCM_FAILURE(rv)) {
   6640                 goto intf_set_done;
   6641             }
   6642 
   6643             if (intf_count > 0) {
   6644                 /* Update data structures */
   6645                 alloc_size = sizeof(_bcm_repl_list_info_t);
   6646                 rli_current = sal_alloc(alloc_size, "IPMC repl list info");
   6647                 if (rli_current == NULL) {
   6648                     /* Release list */
   6649                     _bcm_tr3_repl_list_free(unit, list_start_ptr);
   6650                     rv = BCM_E_MEMORY;
   6651                     goto intf_set_done;
   6652                 }
   6653                 sal_memset(rli_current, 0, alloc_size);
   6654                 rli_current->index = list_start_ptr;
   6655                 rli_current->hash = repl_hash;
   6656                 rli_current->list_size = intf_count;
   6657                 rli_current->next = REPL_LIST_INFO(unit);
   6658                 REPL_LIST_INFO(unit) = rli_current;
   6659                 new_repl_list = TRUE;
   6660             } else {
   6661                 rv = BCM_E_INTERNAL;
   6662                 goto intf_set_done;
   6663             }
   6664         }
   6665 
   6666         /* Update the interface count before updating replication list
   6667          * start pointer, since _bcm_tr3_repl_list_start_ptr_set
   6668          * depends on correct interface count.
   6669          */
   6670         REPL_PORT_GROUP_INTF_COUNT(unit, port, repl_group) = intf_count;
   6671 
   6672 #ifdef BCM_KATANA2_SUPPORT
   6673         if (SOC_IS_KATANA2(unit)) {
   6674             if (SOC_IS_SABER2(unit)) {
   6675 #ifdef BCM_SABER2_SUPPORT
   6676                 rqe_arr_ptr = sb2_rqe_rep_regs;
   6677 #endif
   6678             } else { 
   6679                 rqe_arr_ptr = kt2_rqe_rep_regs;
   6680             }
   6681             rqe_mem = rqe_arr_ptr[port].mem;
   6682             last_ptr = rqe_arr_ptr[port].last_ptr;
   6683             last = ((intf_count == 1) ? 1 : 0);
   6684             rv = _bcm_kt_ipmc_mmu_mc_remap_ptr(unit,repl_group, 
   6685                                                &ipmc_id, FALSE);
   6686             if (rv < 0) { 
   6687                 goto intf_set_done;
   6688             }
   6689             soc_mem_lock(unit, rqe_mem);
   6690             if ((rv = soc_mem_read(unit, rqe_mem, MEM_BLOCK_ALL,
   6691                                     ipmc_id, &rqe_entry)) < 0) {
   6692                  soc_mem_unlock(unit, rqe_mem);
   6693                  goto intf_set_done;
   6694             }
   6695             soc_mem_field32_set(unit, rqe_mem, &rqe_entry, last_ptr, last ? 1 : 0); 
   6696             if ((rv = soc_mem_write(unit, rqe_mem, MEM_BLOCK_ALL, ipmc_id,
   6697                                                    &rqe_entry)) < 0) {
   6698                  soc_mem_unlock(unit, rqe_mem);
   6699                  goto intf_set_done;
   6700             }
   6701             soc_mem_unlock(unit, rqe_mem);
   6702         }
   6703 #endif 
   6704         /* Update replication list start pointer */
   6705         rv = _bcm_tr3_repl_list_start_ptr_set(unit, repl_group, port,
   6706                 list_start_ptr, intf_count);
   6707         if (BCM_FAILURE(rv)) {
   6708             if (new_repl_list) {
   6709                 _bcm_tr3_repl_list_free(unit, list_start_ptr);
   6710                 REPL_LIST_INFO(unit) = rli_current->next;
   6711                 sal_free(rli_current);
   6712             }
   6713             REPL_PORT_GROUP_INTF_COUNT(unit, port, repl_group) = intf_cnt_old;
   6714             goto intf_set_done;
   6715         }
   6716         (rli_current->refcount)++;
   6717        
   6718 
   6719     } else { 
   6720         if (!SOC_IS_KATANA2(unit)) {
   6721             rv = _bcm_tr3_repl_intf_vec_construct(unit, port, if_count,
   6722                                                   if_array, if_updated,
   6723                                                   is_l3, check_port, NULL);
   6724         }
   6725         /* Delete replication list for given (repl_group, port) */
   6726         REPL_PORT_GROUP_INTF_COUNT(unit, port, repl_group) = 0;
   6727         if (prev_start_ptr != 0) {
   6728             rv = _bcm_tr3_repl_list_start_ptr_set(unit, repl_group, port, 0, 0);
   6729             if (BCM_FAILURE(rv)) {
   6730                 REPL_PORT_GROUP_INTF_COUNT(unit, port,
   6731                                            repl_group) = intf_cnt_old;
   6732                 goto intf_set_done;
   6733             }
   6734         }        
   6735     }
   6736 
   6737     /* Delete old replication list */
   6738     if (prev_start_ptr != 0) {
   6739         rli_prev = NULL;
   6740         for (rli_current = REPL_LIST_INFO(unit); rli_current != NULL;
   6741                 rli_current = rli_current->next) {
   6742             if (prev_start_ptr == rli_current->index) {
   6743                 (rli_current->refcount)--;
   6744                 if (rli_current->refcount == 0) {
   6745                     /* Free these linked list entries */
   6746                     _bcm_tr3_repl_list_free(unit, prev_start_ptr);
   6747                     if (rli_prev == NULL) {
   6748                         REPL_LIST_INFO(unit) = rli_current->next;
   6749                     } else {
   6750                         rli_prev->next = rli_current->next;
   6751                     }
   6752                     sal_free(rli_current);
   6753                 }
   6754                 break;
   6755             }
   6756             rli_prev = rli_current;
   6757         }
   6758     }
   6759 
   6760 intf_set_done:
   6761 
   6762     if (intf_vec != NULL) {
   6763         sal_free(intf_vec);
   6764     }
   6765 
   6766     return rv;
   6767 }
   6768 #ifdef BCM_KATANA2_SUPPORT
   6769 /*
   6770  * Function:
   6771  *      _bcm_kt2_init_check
   6772  * Purpose:
   6773  *      Katana2 initialization 
   6774  *      unit         - StrataSwitch PCI device unit number.
   6775  *      ipmc_id      - The replication group number.
   6776  * Returns:
   6777  *      BCM_E_XXX
   6778  */
   6779 int
   6780 _bcm_kt2_init_check(int unit, int ipmc_id)
   6781 {
   6782    REPL_INIT(unit);
   6783    REPL_GROUP_ID(unit, ipmc_id);
   6784    return BCM_E_NONE;
   6785 
   6786 }
   6787 
   6788 /*
   6789  * Function:
   6790  *	_bcm_kt2_ipmc_egress_intf_set
   6791  * Purpose:
   6792  *	Assign set of egress interfaces to port's replication list for chosen
   6793  *	replication group.
   6794  * Parameters:
   6795  *	unit         - StrataSwitch PCI device unit number.
   6796  *	repl_group   - The replication group number.
   6797  *	port         - Port to assign replication list.
   6798  *      ipmc_ptr     - 
   6799  *	if_count     - Number of interfaces in replication list.
   6800  *      if_array     - (IN) List of interface numbers.
   6801  *      new_ipmc_ptr - (OUT) repl_ptr 
   6802  *      last_ipmc_flag - (OUT) flag indicating last replication
   6803  *      check_port - (IN) If if_array consists of L3 interfaces, this parameter 
   6804  *                        controls whether to check the given port is a member
   6805  *                        in each L3 interface's VLAN. This check should be  
   6806  *                        disabled when not needed, in order to improve
   6807  *                        performance.
   6808  * Returns:
   6809  *	BCM_E_XXX
   6810  */
   6811 int
   6812 _bcm_kt2_ipmc_egress_intf_set(int unit, int repl_group, bcm_port_t port,
   6813                              int ipmc_ptr, int if_count, bcm_if_t *if_array, 
   6814                              int *new_ipmc_ptr, int *last_ipmc_flag,
   6815                              int check_port)
   6816 {
   6817     int rv = BCM_E_NONE;
   6818     int prev_start_ptr, list_start_ptr=0;
   6819     int alloc_size;
   6820     SHR_BITDCL *intf_vec = NULL;
   6821     int repl_hash;
   6822     _bcm_repl_list_info_t *rli_current, *rli_prev;
   6823     int intf_count = 0;
   6824     int last_flag;
   6825     uint32 nh_count = 0;
   6826     int if_num, partition;
   6827     bcm_l3_intf_t       l3_intf;
   6828     pbmp_t              pbmp, ubmp;
   6829     int set_repl_list;
   6830 
   6831 
   6832     REPL_INIT(unit);
   6833     REPL_GROUP_ID(unit, repl_group);
   6834     REPL_PORT_CHECK(unit, port);
   6835 
   6836     if (if_count > REPL_INTF_TOTAL(unit)) {
   6837         return BCM_E_PARAM;
   6838     } else if (if_count > 0) {
   6839         set_repl_list = TRUE;
   6840     } else {
   6841         set_repl_list = FALSE;
   6842     }
   6843 
   6844     REPL_LOCK(unit);
   6845 
   6846     prev_start_ptr = ipmc_ptr;
   6847 
   6848     if (set_repl_list == FALSE) {
   6849         *new_ipmc_ptr = 0;
   6850     } else {
   6851 
   6852         partition = soc_mem_index_count(unit, EGR_L3_INTFm);
   6853 
   6854         alloc_size = SHR_BITALLOCSIZE(REPL_INTF_TOTAL(unit));
   6855         intf_vec = sal_alloc(alloc_size, "Repl interface vector");
   6856         if (intf_vec == NULL) {
   6857             rv = BCM_E_MEMORY;
   6858             goto intf_set_done;
   6859         }
   6860         sal_memset(intf_vec, 0, alloc_size);
   6861 
   6862         /* Interface validation and vector construction */
   6863         for (if_num = 0; if_num < if_count; if_num++) {
   6864             if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, if_array[if_num]) &&
   6865                 (uint32)(if_array[if_num]) > partition) {
   6866                 rv = BCM_E_PARAM;
   6867                 goto intf_set_done;
   6868             }
   6869             if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, if_array[if_num])) {
   6870                 /* L3 interface is used */
   6871                 if (check_port) {
   6872                     bcm_l3_intf_t_init(&l3_intf);
   6873                     l3_intf.l3a_intf_id = if_array[if_num];
   6874                     if ((rv = bcm_esw_l3_intf_get(unit, &l3_intf)) < 0) {
   6875                         goto intf_set_done;
   6876                     }
   6877                     if ((rv = bcm_esw_vlan_port_get(unit, l3_intf.l3a_vid,
   6878                                     &pbmp, &ubmp)) < 0) {
   6879                         goto intf_set_done;
   6880                     }
   6881                     if (!BCM_PBMP_MEMBER(pbmp, port)) {
   6882                         rv = BCM_E_PARAM;
   6883                         goto intf_set_done;
   6884                     }
   6885                 }
   6886                 SHR_BITSET(intf_vec, if_array[if_num]);
   6887                 intf_count++;
   6888             } else {
   6889                 /* Next hop is used */
   6890                 SHR_BITSET(intf_vec, partition + if_array[if_num] -
   6891                            BCM_XGS3_DVP_EGRESS_IDX_MIN(unit));
   6892                 nh_count++;
   6893             }
   6894         }
   6895 
   6896         /* Search for list already in table */
   6897         repl_hash = _shr_crc32b(0, (uint8 *)intf_vec, REPL_INTF_TOTAL(unit));
   6898         for (rli_current = REPL_LIST_INFO(unit); rli_current != NULL;
   6899             rli_current = rli_current->next) {
   6900             if (repl_hash == rli_current->hash) {
   6901                 rv = _bcm_kt2_repl_list_compare(unit, rli_current->index,
   6902                           intf_vec, nh_count);
   6903                 if (rv == BCM_E_NOT_FOUND) {
   6904                     continue; /* Not a match */
   6905                 } else if (BCM_FAILURE(rv)) {
   6906                     goto intf_set_done;
   6907                 } else {
   6908                     break; /* Match */
   6909                 }
   6910             }
   6911         }
   6912 
   6913         if (rli_current != NULL) {
   6914             /* Found a match */
   6915             if (prev_start_ptr == rli_current->index) {
   6916                 /* (repl_group, port) already points to this list, so done */
   6917                 rv = BCM_E_NONE;
   6918                 goto intf_set_done;
   6919             } else {
   6920                 list_start_ptr = rli_current->index;
   6921                 intf_count = rli_current->list_size;
   6922             }
   6923         } else {
   6924             /* Not a match, make a new chain */
   6925             rv = _bcm_kt2_repl_list_write(unit,
   6926                      intf_vec, nh_count, &list_start_ptr, &intf_count);
   6927             if (BCM_FAILURE(rv)) {
   6928                 goto intf_set_done;
   6929             }
   6930 
   6931             if (intf_count > 0) {
   6932                 /* Update data structures */
   6933                 alloc_size = sizeof(_bcm_repl_list_info_t);
   6934                 rli_current = sal_alloc(alloc_size, "IPMC repl list info");
   6935                 if (rli_current == NULL) {
   6936                     /* Release list */
   6937                     _bcm_tr3_repl_list_free(unit, list_start_ptr);
   6938                     rv = BCM_E_MEMORY;
   6939                     goto intf_set_done;
   6940                 }
   6941                 sal_memset(rli_current, 0, alloc_size);
   6942                 rli_current->index = list_start_ptr;
   6943                 rli_current->hash = repl_hash;
   6944                 rli_current->list_size = intf_count;
   6945                 rli_current->next = REPL_LIST_INFO(unit);
   6946                 REPL_LIST_INFO(unit) = rli_current;
   6947             } else {
   6948                 rv = BCM_E_INTERNAL;
   6949                 goto intf_set_done;
   6950             }
   6951         }
   6952 
   6953         last_flag = (intf_count == 1);
   6954         *last_ipmc_flag = last_flag;
   6955         if (intf_count > 0) {
   6956             (rli_current->refcount)++;
   6957         } else if (prev_start_ptr != 0) {
   6958             list_start_ptr = 0;
   6959         }
   6960         *new_ipmc_ptr = list_start_ptr;
   6961 
   6962     }
   6963 
   6964     /* Delete old replication list */
   6965     if (prev_start_ptr != 0) {
   6966         rli_prev = NULL;
   6967         for (rli_current = REPL_LIST_INFO(unit); rli_current != NULL;
   6968                 rli_current = rli_current->next) {
   6969             if (prev_start_ptr == rli_current->index) {
   6970                 (rli_current->refcount)--;
   6971                 if (rli_current->refcount == 0) {
   6972                     /* Free these linked list entries */
   6973                     _bcm_tr3_repl_list_free(unit, prev_start_ptr);
   6974                     if (rli_prev == NULL) {
   6975                         REPL_LIST_INFO(unit) = rli_current->next;
   6976                     } else {
   6977                         rli_prev->next = rli_current->next;
   6978                     }
   6979                     sal_free(rli_current);
   6980                 }
   6981                 break;
   6982             }
   6983             rli_prev = rli_current;
   6984         }
   6985     }
   6986 
   6987 intf_set_done:
   6988 
   6989     REPL_UNLOCK(unit);
   6990 
   6991     if (intf_vec != NULL) {
   6992         sal_free(intf_vec);
   6993     }
   6994 
   6995     return rv;
   6996 }
   6997 
   6998 /*
   6999  * Function:
   7000  *      _bcm_kt2_ipmc_egress_intf_add
   7001  * Purpose:
   7002  *      Add L3 interface to selected ports' replication list for chosen
   7003  *      IPMC group.
   7004  * Parameters:
   7005  *      unit         - StrataSwitch PCI device unit number.
   7006  *      ipmc_id      - IPMC group number.
   7007  *      port         - port to add.
   7008  *      ipmc_ptr     - replication pointer.
   7009  *      id           - encap_id.
   7010  *      new_ipmc_ptr - (OUT) repl_ptr
   7011  *      last_ipmc_flag - (OUT) flag indicating last replication
   7012  * Returns:
   7013  *      BCM_E_XXX
   7014  */
   7015 int
   7016 _bcm_kt2_ipmc_egress_intf_add(int unit, int ipmc_id, bcm_port_t port,
   7017                               int ipmc_ptr, int id, int  *new_ipmc_ptr,
   7018                               int *last_flag)
   7019 {
   7020     bcm_if_t *if_array = NULL;
   7021     int  intf_num, intf_max, alloc_size, rv = BCM_E_NONE;
   7022     pbmp_t pbmp, ubmp;
   7023     int                 partition;
   7024     bcm_l3_intf_t       l3_intf;
   7025     int i = 0;
   7026 
   7027     REPL_PORT_CHECK(unit, port);
   7028     BCM_IF_ERROR_RETURN(_bcm_kt2_init_check(unit, ipmc_id));
   7029 
   7030     intf_max = REPL_INTF_TOTAL(unit);
   7031     alloc_size = intf_max * sizeof(bcm_if_t);
   7032     if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   7033     if (if_array == NULL) {
   7034         return BCM_E_MEMORY;
   7035     }
   7036 
   7037     REPL_LOCK(unit);
   7038     rv = _bcm_kt2_ipmc_egress_intf_get(unit, ipmc_id, ipmc_ptr,
   7039                                        if_array, &intf_num);
   7040     if (BCM_SUCCESS(rv)) {
   7041 
   7042         for (i = 0 ;i < intf_num ; i++ ) {
   7043              if (if_array[i] == id) { 
   7044                  rv =  BCM_E_EXISTS;
   7045                  goto intf_add_done;
   7046              }
   7047         }
   7048         if (intf_num < intf_max) {
   7049             if_array[intf_num++] = id;
   7050 
   7051             /* For IPMC, check port is a member of the L3 interface's VLAN.
   7052              * Performing this check here is more efficient than performing
   7053              * it in bcm_tr2_ipmc_egress_intf_set.
   7054              */
   7055             if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, id)) {
   7056                 /* L3 interface is used */
   7057                 partition = soc_mem_index_count(unit, EGR_L3_INTFm);
   7058                 if (id > partition) {
   7059                     rv = BCM_E_PARAM;
   7060                     goto intf_add_done;
   7061                 }
   7062 
   7063                 bcm_l3_intf_t_init(&l3_intf);
   7064                 l3_intf.l3a_intf_id = id;
   7065                 if ((rv = bcm_esw_l3_intf_get(unit, &l3_intf)) < 0) {
   7066                     goto intf_add_done;
   7067                 }
   7068                 if ((rv = bcm_esw_vlan_port_get(unit, l3_intf.l3a_vid,
   7069                                 &pbmp, &ubmp)) < 0) {
   7070                     goto intf_add_done;
   7071                 }
   7072                 if (!BCM_PBMP_MEMBER(pbmp, port)) {
   7073                     rv = BCM_E_PARAM;
   7074                     goto intf_add_done;
   7075                 }
   7076             }
   7077 
   7078             rv = _bcm_kt2_ipmc_egress_intf_set(unit, ipmc_id, port, 
   7079                                                ipmc_ptr, intf_num, if_array, 
   7080                                                new_ipmc_ptr, last_flag, FALSE);
   7081         } else {
   7082             rv = BCM_E_FULL;
   7083         }
   7084     }
   7085 
   7086 intf_add_done:
   7087     REPL_UNLOCK(unit);
   7088     sal_free(if_array);
   7089     return rv;
   7090 }
   7091 
   7092 /*
   7093  * Function:
   7094  *      bcm_kt2_ipmc_egress_intf_get
   7095  * Purpose:
   7096  *      Retrieve set of egress interfaces to port's replication list for chosen
   7097  *      replication list.
   7098  * Parameters:
   7099  *      unit       - StrataSwitch PCI device unit number.
   7100  *      repl_group - The replication group number.
   7101  *      ipmc_ptr   - Relication pointer
   7102  *      if_array   - (OUT) List of interface numbers.
   7103  *      if_count   - (OUT) Number of interfaces in replication list.
   7104  * Returns:
   7105  *      BCM_E_XXX
   7106  * Notes:
   7107  *      If the input parameter if_max = 0, return in the output parameter
   7108  *      if_count the total number of interfaces in the specified multicast
   7109  *      group's replication list.
   7110  */
   7111 int 
   7112 _bcm_kt2_ipmc_egress_intf_get(int unit, int repl_group, 
   7113                              int ipmc_ptr, bcm_if_t *if_array, 
   7114                              int *if_count)
   7115 {
   7116     int rv = BCM_E_NONE;
   7117     int prev_repl_entry_ptr, repl_entry_ptr;
   7118     int intf_count;
   7119     int intf_base;
   7120     int ls_pos;
   7121     uint32 ls_bits[2];
   7122     mmu_repl_list_tbl_entry_t repl_list_entry;
   7123     uint32 nh_offset = 0;
   7124     uint32  is_len = 0;
   7125     int if_max =0;
   7126 
   7127 
   7128     BCM_IF_ERROR_RETURN(_bcm_kt2_init_check(unit, repl_group));
   7129 
   7130     REPL_LOCK(unit);
   7131 
   7132     is_len = soc_mem_field_length(unit, MMU_REPL_LIST_TBLm, LSB_VLAN_BMf);
   7133     /* coverity[large_shift : FALSE] */
   7134     nh_offset = (1 << (soc_mem_field_length(unit, MMU_REPL_LIST_TBLm,
   7135                                                 MSB_VLANf) - 1)) * is_len;
   7136     if_max = REPL_INTF_TOTAL(unit);
   7137 
   7138     if (if_max < 0) {
   7139         return BCM_E_PARAM;
   7140     } else if (if_max > 0 && NULL == if_array) {
   7141         return BCM_E_PARAM;
   7142     }
   7143 
   7144     if (NULL == if_count) {
   7145         return BCM_E_PARAM;
   7146     }
   7147 
   7148     prev_repl_entry_ptr = -1;
   7149     intf_count = 0;
   7150     repl_entry_ptr = ipmc_ptr;
   7151 
   7152     while (repl_entry_ptr != prev_repl_entry_ptr) {
   7153         rv = READ_MMU_REPL_LIST_TBLm(unit, MEM_BLOCK_ANY,
   7154                 repl_entry_ptr, &repl_list_entry);
   7155         if (BCM_FAILURE(rv)) {
   7156             goto intf_get_done;
   7157         }
   7158         /* Each MSB represents 64 entries in LSB bitmap */
   7159         intf_base = soc_MMU_REPL_LIST_TBLm_field32_get(unit, &repl_list_entry,
   7160                 MSB_VLANf) * 64;
   7161         soc_MMU_REPL_LIST_TBLm_field_get(unit, &repl_list_entry,
   7162                 LSB_VLAN_BMf, ls_bits);
   7163 
   7164         for (ls_pos = 0; ls_pos < 64; ls_pos++) {
   7165             if (ls_bits[ls_pos / 32] & (1 << (ls_pos % 32))) {
   7166                 if (if_max == 0) {
   7167                     intf_count++;
   7168                 } else {
   7169                         /* check if L3 interface or nexthop */
   7170                         if (intf_base >= nh_offset) {
   7171                             /* Entry contains next hops */
   7172                             if_array[intf_count] = intf_base - nh_offset +
   7173                                 ls_pos + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   7174                         } else {
   7175                             /* Entry contains interfaces */
   7176                             if_array[intf_count] = intf_base + ls_pos;
   7177                         }
   7178                     intf_count++;
   7179                     if (intf_count == if_max) {
   7180                         *if_count = intf_count;
   7181                         goto intf_get_done;
   7182                     }
   7183                 }
   7184             } 
   7185         } 
   7186         prev_repl_entry_ptr = repl_entry_ptr;
   7187         repl_entry_ptr = soc_MMU_REPL_LIST_TBLm_field32_get(unit,
   7188                 &repl_list_entry, NEXTPTRf);
   7189     }
   7190 
   7191     *if_count = intf_count;
   7192 
   7193 intf_get_done:
   7194     REPL_UNLOCK(unit);
   7195     return rv;
   7196 
   7197 }
   7198 
   7199 #if defined(BCM_KATANA2_SUPPORT)
   7200 int
   7201 _bcm_kt2_ipmc_egress_intf_delete_all( int unit, int ipmc_id, int ipmc_ptr)
   7202 {
   7203     bcm_if_t *if_array = NULL;
   7204     int alloc_size, intf_max, if_count, rv = BCM_E_NONE;
   7205     SHR_BITDCL *intf_vec = NULL;
   7206     int if_num, partition;
   7207     int intf_count= 0, repl_hash;
   7208     _bcm_repl_list_info_t *rli_start,*rli_current, *rli_prev = NULL;
   7209     uint32 nh_count = 0;
   7210 
   7211     partition = soc_mem_index_count(unit, EGR_L3_INTFm);
   7212     intf_max = REPL_INTF_TOTAL(unit);
   7213     alloc_size = intf_max *sizeof(bcm_if_t);
   7214     if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   7215     if (if_array == NULL) {
   7216         return BCM_E_MEMORY;
   7217     }
   7218 
   7219     alloc_size = SHR_BITALLOCSIZE(REPL_INTF_TOTAL(unit));
   7220     intf_vec = sal_alloc(alloc_size, "Repl interface vector");
   7221     if (intf_vec == NULL) {
   7222         sal_free(if_array);
   7223         return BCM_E_MEMORY;
   7224     }
   7225     sal_memset(intf_vec, 0, alloc_size);
   7226     REPL_LOCK(unit);
   7227     rv = _bcm_kt2_ipmc_egress_intf_get (unit, ipmc_id, ipmc_ptr,
   7228             if_array, &if_count);
   7229     if (BCM_SUCCESS(rv)) {
   7230         /*prepare the interface vector and find out the refrence count */
   7231         for (if_num = 0; if_num < if_count; if_num++) {
   7232             if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, if_array[if_num]) &&
   7233                     (uint32)(if_array[if_num]) > partition) {
   7234                 rv = BCM_E_PARAM;
   7235                 break;
   7236             }
   7237             if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, if_array[if_num])) {
   7238                 /* L3 interface is used */
   7239                 SHR_BITSET(intf_vec, if_array[if_num]);
   7240                 intf_count++;
   7241             } else {
   7242                 /* Next hop is used */
   7243                 SHR_BITSET(intf_vec, partition + if_array[if_num] -
   7244                         BCM_XGS3_DVP_EGRESS_IDX_MIN(unit));
   7245                 nh_count++;
   7246             }
   7247         }
   7248         rli_start = REPL_LIST_INFO(unit);
   7249         repl_hash =
   7250             _shr_crc32b(0, (uint8 *)intf_vec, REPL_INTF_TOTAL(unit));
   7251 
   7252         for (rli_current = rli_start; rli_current != NULL;
   7253                 rli_current = rli_current->next) {
   7254             if (repl_hash == rli_current->hash) {
   7255                 rv = _bcm_kt2_repl_list_compare(unit, rli_current->index,
   7256                         intf_vec, nh_count);
   7257                 if (rv == BCM_E_NOT_FOUND) {
   7258                     continue; /* Not a match */
   7259                 } else if (rv < 0) {
   7260                     goto error; /* Access error */
   7261                 } else {
   7262                     break; /* Match */
   7263                 }
   7264             }   
   7265             rli_prev = rli_current;
   7266         }
   7267 
   7268         if (rli_current){
   7269             rli_current->refcount-- ;
   7270             if (rli_current->refcount == 0){
   7271                 rv = _bcm_tr3_repl_list_free(unit, rli_current->index);
   7272                 /* If we have an error, we'll fall out anyway */
   7273                 if (rli_prev == NULL) {
   7274                     REPL_LIST_INFO(unit) = rli_current->next;
   7275                 } else {
   7276                     rli_prev->next = rli_current->next;
   7277                 }
   7278                 sal_free(rli_current);
   7279             }
   7280         }
   7281     }
   7282 error:
   7283     sal_free(if_array);
   7284     sal_free(intf_vec);
   7285     REPL_UNLOCK(unit);
   7286     return rv;
   7287 }
   7288 #endif
   7289 
   7290 /*
   7291  * Function:
   7292  *      bcm_kt2_ipmc_egress_intf_delete
   7293  * Purpose:
   7294  *      Remove L3 interface from selected ports' replication list for chosen
   7295  *      Relication list.
   7296  * Parameters:
   7297  *      unit     - StrataSwitch PCI device unit number.
   7298  *      ipmc_id  - IPMC group number.
   7299  *      ipmc_ptr     - replication pointer.
   7300  *      id           - encap_id.
   7301  *      new_ipmc_ptr - (OUT) repl_ptr
   7302  *      last_ipmc_flag - (OUT) flag indicating last replication
   7303  * Returns:
   7304  *      BCM_E_XXX
   7305  */
   7306 int
   7307 _bcm_kt2_ipmc_egress_intf_delete(int unit, int ipmc_id, bcm_port_t port,
   7308                                 int ipmc_ptr, int id, int  *new_ipmc_ptr,
   7309                                 int *last_flag)
   7310 {
   7311     bcm_if_t *if_array = NULL;
   7312     int alloc_size, intf_max, if_count, if_cur, match, rv = BCM_E_NONE;
   7313 
   7314     REPL_INIT(unit);
   7315     REPL_GROUP_ID(unit, ipmc_id);
   7316     REPL_PORT_CHECK(unit, port);
   7317 
   7318     intf_max = REPL_INTF_TOTAL(unit);
   7319     alloc_size = intf_max * sizeof(bcm_if_t);
   7320     if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   7321     if (if_array == NULL) {
   7322         return BCM_E_MEMORY;
   7323     }
   7324 
   7325     REPL_LOCK(unit);
   7326     rv = _bcm_kt2_ipmc_egress_intf_get(unit, ipmc_id, ipmc_ptr,
   7327                                        if_array, &if_count);
   7328     if (BCM_SUCCESS(rv)) {
   7329         match = FALSE;
   7330         for (if_cur = 0; if_cur < if_count; if_cur++) {
   7331             if (match) {
   7332                 if_array[if_cur - 1] = if_array[if_cur];
   7333             } else {
   7334                 if (if_array[if_cur] == id) {
   7335                     match = TRUE;
   7336                 }
   7337             }
   7338         }
   7339         if (match) {
   7340             if_count--;
   7341             rv = _bcm_kt2_ipmc_egress_intf_set(unit, ipmc_id, port,
   7342                                              ipmc_ptr, if_count, if_array,
   7343                                             new_ipmc_ptr, last_flag, FALSE);
   7344         } else {
   7345             rv = BCM_E_NOT_FOUND;
   7346         }
   7347     }
   7348 
   7349     REPL_UNLOCK(unit);
   7350     sal_free(if_array);
   7351     return rv;
   7352 }
   7353 
   7354 #endif
   7355 /*
   7356  * Function:
   7357  *      _bcm_tr3_ipmc_egress_intf_get
   7358  * Purpose:
   7359  *	Retrieve set of egress interfaces to port's replication list for chosen
   7360  *	replication group.
   7361  * Parameters:
   7362  *	unit       - StrataSwitch PCI device unit number.
   7363  *	repl_group - The replication group number.
   7364  *	port       - Port from which to get replication list.
   7365  *	if_max     - Maximum number of interfaces in replication list.
   7366  *      if_array   - (OUT) List of interface numbers.
   7367  *	if_count   - (OUT) Number of interfaces in replication list.
   7368  * repl_start_ptr - (OUT) Start pointer of existing replication list.
   7369  * Returns:
   7370  *	BCM_E_XXX
   7371  * Notes:
   7372  *      If the input parameter if_max = 0, return in the output parameter
   7373  *      if_count the total number of interfaces in the specified multicast 
   7374  *      group's replication list.
   7375  */
   7376 int
   7377 _bcm_tr3_ipmc_egress_intf_get(int unit, int repl_group, bcm_port_t port,
   7378                               int if_max, bcm_if_t *if_array, int *if_count,
   7379                               int *repl_start_ptr)
   7380 {
   7381     int rv = BCM_E_NONE;
   7382     int prev_repl_entry_ptr, repl_entry_ptr;
   7383     int intf_count;
   7384     int l3_intf, intf_base;
   7385     int ls_pos;
   7386     uint32 ls_bits[2];
   7387     mmu_repl_list_tbl_entry_t repl_list_entry;
   7388     int next_hop_index;
   7389     int entry_type;
   7390     egr_l3_next_hop_entry_t egr_nh;
   7391 #if defined (BCM_KATANA2_SUPPORT)
   7392     uint32 nh_offset = 0;
   7393     uint32  is_len = 0;
   7394 #endif
   7395 
   7396 
   7397     REPL_INIT(unit);
   7398     REPL_GROUP_ID(unit, repl_group);
   7399     /* Replication is allowed on CPU ports, only on TD2 */
   7400     if(IS_CPU_PORT(unit, port)) {
   7401         if(!SOC_IS_TRIDENT2X(unit)) {
   7402             return BCM_E_PARAM;
   7403         }
   7404     }
   7405     else
   7406     {   
   7407         REPL_PORT_CHECK(unit, port);
   7408     }
   7409 
   7410 #ifdef BCM_KATANA2_SUPPORT
   7411     if (SOC_IS_KATANA2(unit)) {
   7412         is_len = soc_mem_field_length(unit, MMU_REPL_LIST_TBLm, LSB_VLAN_BMf);
   7413         /* coverity[negative_shift : FALSE] */
   7414         nh_offset = (1 << (soc_mem_field_length(unit, MMU_REPL_LIST_TBLm,
   7415                                                 MSB_VLANf) - 1)) * is_len;
   7416     }
   7417 #endif
   7418 
   7419     if (if_max < 0) {
   7420         return BCM_E_PARAM;
   7421     } else if (if_max > 0 && NULL == if_array) {
   7422         return BCM_E_PARAM;
   7423     }
   7424 
   7425     if (NULL == if_count) {
   7426         return BCM_E_PARAM;
   7427     }
   7428 
   7429     if (REPL_PORT_GROUP_INTF_COUNT(unit, port, repl_group) == 0) {
   7430         *if_count = 0;
   7431         return BCM_E_NONE;
   7432     }
   7433 
   7434     rv = _bcm_tr3_repl_list_start_ptr_get(unit, repl_group, port,
   7435             &repl_entry_ptr);
   7436     if (BCM_FAILURE(rv)) {
   7437         goto intf_get_done;
   7438     } else {
   7439         *repl_start_ptr = repl_entry_ptr;
   7440     }
   7441 
   7442     prev_repl_entry_ptr = -1;
   7443     intf_count = 0;
   7444     while (repl_entry_ptr != prev_repl_entry_ptr) {
   7445         rv = READ_MMU_REPL_LIST_TBLm(unit, MEM_BLOCK_ANY,
   7446                 repl_entry_ptr, &repl_list_entry);
   7447         if (BCM_FAILURE(rv)) {
   7448             goto intf_get_done;
   7449         }
   7450         /* Each MSB represents 64 entries in LSB bitmap */
   7451         intf_base = soc_MMU_REPL_LIST_TBLm_field32_get(unit, &repl_list_entry,
   7452                 MSB_VLANf) * 64;
   7453         soc_MMU_REPL_LIST_TBLm_field_get(unit, &repl_list_entry,
   7454                 LSB_VLAN_BMf, ls_bits);
   7455 
   7456         for (ls_pos = 0; ls_pos < 64; ls_pos++) {
   7457             if (ls_bits[ls_pos / 32] & (1 << (ls_pos % 32))) {
   7458                 if (if_max == 0) {
   7459                     intf_count++;
   7460                 } else {
   7461 #if defined(BCM_KATANA2_SUPPORT)
   7462                     if (SOC_IS_KATANA2(unit))
   7463                     {
   7464                         /* check if L3 interface or nexthop */
   7465                         if (intf_base >= nh_offset) {
   7466                             /* Entry contains next hops */
   7467                             if_array[intf_count] = intf_base - nh_offset +
   7468                                 ls_pos + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   7469                         } else {
   7470                             /* Entry contains interfaces */
   7471                             if_array[intf_count] = intf_base + ls_pos;
   7472                         }
   7473                     }
   7474                     else
   7475 #endif
   7476                     {
   7477 
   7478                         /* Check if L3 interfaces or next hop */
   7479                     
   7480                         next_hop_index = intf_base + ls_pos;
   7481                         if_array[intf_count] = next_hop_index +
   7482                          BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);                
   7483 
   7484                         /* Check if next hop index corresponds to
   7485                          * an IPMC or Trill interface.
   7486                          */
   7487                         rv = READ_EGR_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY,
   7488                              next_hop_index, &egr_nh);
   7489                         if (BCM_FAILURE(rv)) {
   7490                             goto intf_get_done;
   7491                         }
   7492                         entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   7493                                      &egr_nh, ENTRY_TYPEf);
   7494                         if (entry_type == 0) {
   7495                             l3_intf = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   7496                                 &egr_nh, L3__INTF_NUMf);
   7497                             if (REPL_L3_INTF_NEXT_HOP_TRILL(unit, l3_intf) ==
   7498                                 next_hop_index) {
   7499                                 if_array[intf_count] = l3_intf;
   7500                             } 
   7501                         }
   7502                         else if (entry_type == 7) {
   7503                             l3_intf = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   7504                                   &egr_nh, L3MC__INTF_NUMf);
   7505                             if (REPL_L3_INTF_NEXT_HOP_IPMC(unit, l3_intf) ==
   7506                                   next_hop_index) {
   7507                                if_array[intf_count] = l3_intf;
   7508                             } 
   7509                         }
   7510                     } /* end - if not KATANA2*/
   7511                     intf_count++;
   7512                     if (intf_count == if_max) {
   7513                         *if_count = intf_count;
   7514                         goto intf_get_done;
   7515                     }
   7516                 }
   7517             } 
   7518         } 
   7519         prev_repl_entry_ptr = repl_entry_ptr;
   7520         repl_entry_ptr = soc_MMU_REPL_LIST_TBLm_field32_get(unit,
   7521                 &repl_list_entry, NEXTPTRf);
   7522         if (intf_count >= REPL_PORT_GROUP_INTF_COUNT(unit, port, repl_group)) {
   7523             break;
   7524         }
   7525     }
   7526 
   7527     *if_count = intf_count;
   7528 
   7529 intf_get_done:
   7530     return rv;
   7531 }
   7532 
   7533 /*
   7534  * Function:
   7535  *      bcm_tr3_ipmc_egress_intf_get
   7536  * Purpose:
   7537  *      Retrieve set of egress interfaces to port's replication list for chosen
   7538  *      replication group.
   7539  * Parameters:
   7540  *      unit       - StrataSwitch PCI device unit number.
   7541  *      repl_group - The replication group number.
   7542  *      port       - Port from which to get replication list.
   7543  *      if_max     - Maximum number of interfaces in replication list.
   7544  *      if_array   - (OUT) List of interface numbers.
   7545  *      if_count   - (OUT) Number of interfaces in replication list.
   7546  * Returns:
   7547  *      BCM_E_XXX
   7548  * Notes:
   7549  *      If the input parameter if_max = 0, return in the output parameter
   7550  *      if_count the total number of interfaces in the specified multicast
   7551  *      group's replication list.
   7552  */
   7553 int
   7554 bcm_tr3_ipmc_egress_intf_get(int unit, int repl_group, bcm_port_t port,
   7555                              int if_max, bcm_if_t *if_array, int *if_count)
   7556 {
   7557     int rv = BCM_E_NONE;
   7558     int repl_start_ptr = 0;
   7559 
   7560     REPL_LOCK(unit);
   7561     rv = _bcm_tr3_ipmc_egress_intf_get(unit, repl_group, port,
   7562                                        if_max, if_array, if_count,
   7563                                        &repl_start_ptr);
   7564     REPL_UNLOCK(unit);
   7565 
   7566     return rv;
   7567 }
   7568 
   7569 /*
   7570  * Function:
   7571  *	bcm_tr3_ipmc_egress_intf_set
   7572  * Purpose:
   7573  *	Assign set of egress interfaces to port's replication list for chosen
   7574  *	replication group.
   7575  * Parameters:
   7576  *	unit       - StrataSwitch PCI device unit number.
   7577  *	repl_group - The replication group number.
   7578  *	port       - Port to assign replication list.
   7579  *	if_count   - Number of interfaces in replication list.
   7580  *  if_array   - (IN) List of interface numbers.
   7581  *  is_l3      - (IN) Indicates if multicast group is of type IPMC.
   7582  *  check_port - (IN) If if_array consists of L3 interfaces, this parameter 
   7583  *                        controls whether to check the given port is a member
   7584  *                        in each L3 interface's VLAN. This check should be  
   7585  *                        disabled when not needed, in order to improve
   7586  *                        performance.
   7587  * Returns:
   7588  *	BCM_E_XXX
   7589  */
   7590 int 
   7591 bcm_tr3_ipmc_egress_intf_set(
   7592     int unit, int repl_group, bcm_port_t port,
   7593     int if_count, bcm_if_t *if_array, int is_l3, int check_port)
   7594 {
   7595     int rv = BCM_E_NONE;
   7596     _tr3_if_updated_t  if_updated;
   7597     bcm_if_t *if_array_cur = NULL;
   7598     int intf_num_cur, intf_max, alloc_size;
   7599     int if_index, if_cur_index;
   7600     int repl_start_ptr = 0;
   7601 
   7602     REPL_INIT(unit);
   7603     REPL_GROUP_ID(unit, repl_group);
   7604 
   7605     if (IS_CPU_PORT(unit, port)) {
   7606         if (!SOC_IS_TRIDENT2X(unit)) {
   7607             return BCM_E_PARAM;
   7608         }
   7609     } else {
   7610         REPL_PORT_CHECK(unit, port);
   7611     }
   7612 
   7613     if ((if_count == 0) &&
   7614         (REPL_PORT_GROUP_INTF_COUNT(unit, port, repl_group) == 0)) {
   7615         return BCM_E_NONE;
   7616     }
   7617 
   7618     sal_memset(&if_updated, 0 , sizeof(if_updated));
   7619     
   7620     intf_max = REPL_INTF_TOTAL(unit);
   7621     alloc_size = intf_max * sizeof(bcm_if_t);
   7622     
   7623     if_array_cur = sal_alloc(alloc_size, "IPMC intf array current");
   7624     if (if_array_cur == NULL) {
   7625         rv = BCM_E_MEMORY;
   7626         goto intf_cleanup;
   7627     }
   7628 
   7629     if_updated.if_array_new = sal_alloc(if_count * sizeof(bcm_if_t),
   7630                                         "IPMC intf array new");
   7631     if (if_updated.if_array_new == NULL) {
   7632         rv = BCM_E_MEMORY;   
   7633         goto intf_cleanup;
   7634     }
   7635 
   7636     REPL_LOCK(unit);
   7637     rv = _bcm_tr3_ipmc_egress_intf_get(unit, repl_group, port,
   7638                                        intf_max, if_array_cur, &intf_num_cur,
   7639                                        &repl_start_ptr);
   7640     if (BCM_FAILURE(rv)) {
   7641         REPL_UNLOCK(unit);
   7642         goto intf_cleanup;
   7643     }
   7644     
   7645     if_updated.if_array_del = sal_alloc(intf_num_cur * sizeof(bcm_if_t),
   7646                                         "IPMC intf array del");
   7647     if (if_updated.if_array_del == NULL) {
   7648         REPL_UNLOCK(unit);
   7649         rv = BCM_E_MEMORY;
   7650         goto intf_cleanup;
   7651     }
   7652 
   7653     /* Get the new if array for <group, port> and 
   7654      * the if array deleted from <group, port>.
   7655      */
   7656     for (if_index = 0; if_index < if_count; if_index++) {
   7657         for (if_cur_index = 0; if_cur_index < intf_num_cur; if_cur_index++) {
   7658             if (if_array[if_index] == if_array_cur[if_cur_index]) {
   7659                 /* The if_array[if_index] has been already
   7660                  * attached to <group, port>. 
   7661                  */ 
   7662                 if_array_cur[if_cur_index] = -1;
   7663                 break;
   7664             }
   7665         }
   7666         
   7667         if (if_cur_index == intf_num_cur) {
   7668             /* The if_array[if_index] is new for <group, port>. */
   7669             if_updated.if_array_new[if_updated.if_count_new++] = 
   7670                 if_array[if_index];
   7671         }        
   7672     }
   7673 
   7674     for (if_cur_index = 0; if_cur_index < intf_num_cur; if_cur_index++) {
   7675         if (if_array_cur[if_cur_index] == -1) {
   7676             continue;
   7677         }
   7678         if_updated.if_array_del[if_updated.if_count_del++] = 
   7679             if_array_cur[if_cur_index];
   7680     }
   7681 
   7682     if ((if_updated.if_count_new == 0) && (if_updated.if_count_del == 0)) {
   7683         REPL_UNLOCK(unit);
   7684         rv = BCM_E_NONE;
   7685         goto intf_cleanup;
   7686     }
   7687 
   7688     rv = _bcm_tr3_ipmc_egress_intf_set(unit, repl_group, port,
   7689                                        if_count,if_array, &if_updated,
   7690                                        is_l3, check_port, repl_start_ptr);
   7691     REPL_UNLOCK(unit);
   7692 intf_cleanup:
   7693     if (if_array_cur) {
   7694         sal_free(if_array_cur);
   7695     }
   7696     if (if_updated.if_array_new) {
   7697         sal_free(if_updated.if_array_new);
   7698     }
   7699     if (if_updated.if_array_del) {
   7700         sal_free(if_updated.if_array_del);
   7701     }
   7702     return rv;
   7703 }
   7704 
   7705 
   7706 /*
   7707  * Function:
   7708  *      bcm_tr3_ipmc_egress_intf_add
   7709  * Purpose:
   7710  *      Add L3 interface to selected ports' replication list for chosen
   7711  *      IPMC group.
   7712  * Parameters:
   7713  *      unit     - StrataSwitch PCI device unit number.
   7714  *      ipmc_id  - IPMC group number.
   7715  *      port     - port to add.
   7716  *      l3_intf  - L3 interface to replicate.
   7717  * Returns:
   7718  *      BCM_E_XXX
   7719  */
   7720 int
   7721 bcm_tr3_ipmc_egress_intf_add(int unit, int ipmc_id, bcm_port_t port,
   7722                             bcm_l3_intf_t *l3_intf)
   7723 {
   7724     bcm_if_t *if_array = NULL;
   7725     int  intf_num, intf_max, alloc_size, rv = BCM_E_NONE;
   7726     pbmp_t pbmp, ubmp;
   7727     bcm_if_t intf_add;
   7728     _tr3_if_updated_t if_updated;
   7729     int repl_start_ptr = 0;
   7730 
   7731     REPL_INIT(unit);
   7732     REPL_GROUP_ID(unit, ipmc_id);
   7733     REPL_PORT_CHECK(unit, port);
   7734 
   7735     /* Check if port belongs to this VLAN */
   7736     BCM_IF_ERROR_RETURN
   7737         (bcm_esw_vlan_port_get(unit, l3_intf->l3a_vid, &pbmp, &ubmp));
   7738     if (!SOC_PBMP_MEMBER(pbmp, port)) {
   7739         return BCM_E_PARAM;
   7740     }
   7741 
   7742     intf_max = REPL_INTF_TOTAL(unit);
   7743     alloc_size = intf_max * sizeof(bcm_if_t);
   7744     if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   7745     if (if_array == NULL) {
   7746         return BCM_E_MEMORY;
   7747     }
   7748 
   7749     REPL_LOCK(unit);
   7750     rv = _bcm_tr3_ipmc_egress_intf_get(unit, ipmc_id, port, intf_max,
   7751                                        if_array, &intf_num, &repl_start_ptr);
   7752     if (BCM_SUCCESS(rv)) {
   7753         if (intf_num < intf_max) {
   7754             if_array[intf_num++] = l3_intf->l3a_intf_id;
   7755             intf_add = l3_intf->l3a_intf_id;
   7756             if_updated.if_array_new = &intf_add;
   7757             if_updated.if_count_new = 1;            
   7758             rv = _bcm_tr3_ipmc_egress_intf_set(unit, ipmc_id,
   7759                                                port,intf_num,if_array,
   7760                                                &if_updated, TRUE, FALSE,
   7761                                                repl_start_ptr);
   7762         } else {
   7763             rv = BCM_E_EXISTS;
   7764         }
   7765     }
   7766 
   7767     REPL_UNLOCK(unit);
   7768     sal_free(if_array);
   7769     return rv;
   7770 }
   7771 
   7772 /*
   7773  * Function:
   7774  *      bcm_tr3_ipmc_egress_intf_delete
   7775  * Purpose:
   7776  *      Remove L3 interface from selected ports' replication list for chosen
   7777  *      IPMC group.
   7778  * Parameters:
   7779  *      unit     - StrataSwitch PCI device unit number.
   7780  *      ipmc_id  - IPMC group number.
   7781  *      port     - port to remove.
   7782  *      l3_intf  - L3 interface to delete from replication.
   7783  * Returns:
   7784  *      BCM_E_XXX
   7785  */
   7786 int
   7787 bcm_tr3_ipmc_egress_intf_delete(int unit, int ipmc_id, bcm_port_t port,
   7788                                bcm_l3_intf_t *l3_intf)
   7789 {
   7790     bcm_if_t *if_array = NULL;
   7791     int alloc_size, intf_max, if_count, if_cur, match, rv = BCM_E_NONE;
   7792     _tr3_if_updated_t if_updated;
   7793     bcm_if_t intf_del;
   7794     int repl_start_ptr;
   7795     
   7796     REPL_INIT(unit);
   7797     REPL_GROUP_ID(unit, ipmc_id);
   7798     /* Replication is allowed on CPU ports, only on TD2 */
   7799     if(IS_CPU_PORT(unit, port)) {
   7800         if(!SOC_IS_TRIDENT2X(unit)) {
   7801             return BCM_E_PARAM;
   7802         }
   7803     }
   7804     else
   7805     {   
   7806         REPL_PORT_CHECK(unit, port);
   7807     }
   7808 
   7809     if (!REPL_PORT_GROUP_INTF_COUNT(unit, port, ipmc_id)) {
   7810         return BCM_E_NOT_FOUND;
   7811     }
   7812 
   7813     intf_max = REPL_INTF_TOTAL(unit);
   7814     alloc_size = intf_max * sizeof(bcm_if_t);
   7815     if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   7816     if (if_array == NULL) {
   7817         return BCM_E_MEMORY;
   7818     }
   7819 
   7820     REPL_LOCK(unit);
   7821     rv = _bcm_tr3_ipmc_egress_intf_get(unit, ipmc_id, port, intf_max,
   7822                                        if_array, &if_count, &repl_start_ptr);
   7823     if (BCM_SUCCESS(rv)) {
   7824         match = FALSE;
   7825         for (if_cur = 0; if_cur < if_count; if_cur++) {
   7826             if (match) {
   7827                 if_array[if_cur - 1] = if_array[if_cur];
   7828             } else {
   7829                 if (if_array[if_cur] == l3_intf->l3a_intf_id) {
   7830                     match = TRUE;
   7831                 }
   7832             }
   7833         }
   7834         if (match) {
   7835             if_count--;
   7836             intf_del = l3_intf->l3a_intf_id;
   7837             if_updated.if_count_del = 1;
   7838             if_updated.if_array_del = &intf_del;
   7839             rv = _bcm_tr3_ipmc_egress_intf_set(unit, ipmc_id, port,
   7840                                                if_count, if_array,
   7841                                                &if_updated,TRUE, FALSE,
   7842                                                repl_start_ptr);
   7843         } else {
   7844             rv = BCM_E_NOT_FOUND;
   7845         }
   7846     }
   7847 
   7848     REPL_UNLOCK(unit);
   7849     sal_free(if_array);
   7850     return rv;
   7851 }
   7852 
   7853 /*
   7854  * Function:
   7855  *      _bcm_tr3_ipmc_repl_get
   7856  * Purpose:
   7857  *      Return set of VLANs selected for port's replication list for chosen
   7858  *      IPMC group.
   7859  * Parameters:
   7860  *      unit     - StrataSwitch PCI device unit number.
   7861  *      ipmc_id  - IPMC group number.
   7862  *      port     - port to list.
   7863  *      vlan_vec - (OUT) vector of replicated VLANs common to selected ports.
   7864  * Returns:
   7865  *      BCM_E_XXX
   7866  */
   7867 int
   7868 bcm_tr3_ipmc_repl_get(int unit, int ipmc_id, bcm_port_t port,
   7869                         bcm_vlan_vector_t vlan_vec)
   7870 {
   7871     int rv = BCM_E_NONE;
   7872     uint32 ls_bits[2];
   7873     int prev_repl_entry_ptr, repl_entry_ptr;
   7874     int intf_base;
   7875     int ls_pos;
   7876     mmu_repl_list_tbl_entry_t repl_list_entry;
   7877     int next_hop_index;
   7878     int entry_type;
   7879     bcm_l3_intf_t l3_intf;
   7880     bcm_l3_egress_t egress_object;
   7881     bcm_if_t egr_if;
   7882     int vlan_count;
   7883     egr_l3_next_hop_entry_t egr_nh;
   7884 #ifdef BCM_KATANA2_SUPPORT
   7885     uint32 nh_offset = 0;
   7886     uint32 ls_len = 0;
   7887 #endif /* BCM_KATANA2_SUPPORT*/
   7888 
   7889     REPL_INIT(unit);
   7890     REPL_GROUP_ID(unit, ipmc_id);
   7891     REPL_PORT_CHECK(unit, port);
   7892 
   7893     BCM_VLAN_VEC_ZERO(vlan_vec);
   7894 
   7895 #ifdef BCM_KATANA2_SUPPORT
   7896     if (SOC_IS_KATANA2(unit))
   7897     {
   7898         ls_len  = soc_mem_field_length(unit, MMU_REPL_LIST_TBLm, LSB_VLAN_BMf);
   7899         /* coverity[large_shift : FALSE] */
   7900         nh_offset = (1 << (soc_mem_field_length(unit, MMU_REPL_LIST_TBLm,
   7901                                                 MSB_VLANf) - 1)) * ls_len;
   7902     }
   7903 #endif
   7904 
   7905     REPL_LOCK(unit);
   7906     if (REPL_PORT_GROUP_INTF_COUNT(unit, port, ipmc_id) == 0) {
   7907         REPL_UNLOCK(unit);
   7908         return BCM_E_NONE;
   7909     }
   7910 
   7911     rv = _bcm_tr3_repl_list_start_ptr_get(unit, ipmc_id, port,
   7912             &repl_entry_ptr);
   7913     if (BCM_FAILURE(rv)) {
   7914         goto vlan_get_done;
   7915     }
   7916 
   7917     prev_repl_entry_ptr = -1;
   7918     vlan_count = 0;
   7919     while (repl_entry_ptr != prev_repl_entry_ptr) {
   7920         rv = READ_MMU_REPL_LIST_TBLm(unit, MEM_BLOCK_ANY,
   7921                 repl_entry_ptr, &repl_list_entry);
   7922         if (BCM_FAILURE(rv)) {
   7923             goto vlan_get_done;
   7924         }
   7925         /* Each MSB represents 64 entries in LSB bitmap */
   7926         intf_base = soc_MMU_REPL_LIST_TBLm_field32_get(unit, &repl_list_entry,
   7927                 MSB_VLANf) * 64;
   7928         soc_MMU_REPL_LIST_TBLm_field_get(unit, &repl_list_entry,
   7929                 LSB_VLAN_BMf, ls_bits);
   7930         for (ls_pos = 0; ls_pos < 64; ls_pos++) {
   7931             if (ls_bits[ls_pos / 32] & (1 << (ls_pos % 32))) {
   7932 #ifdef BCM_KATANA2_SUPPORT
   7933                 if (SOC_IS_KATANA2(unit)) {
   7934                     bcm_l3_intf_t_init(&l3_intf);
   7935                     if (intf_base >= nh_offset) {
   7936                         /* Next hop */
   7937                         next_hop_index = intf_base - nh_offset + ls_pos +
   7938                         BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   7939                         /* Coverity: egress_object.intf is initialized above
   7940                          * by bcm_esw_l3_egress_get. */
   7941                         /* coverity[uninit_use : FALSE] */
   7942                         rv = bcm_esw_l3_egress_get(unit, next_hop_index, 
   7943                                                    &egress_object);
   7944                         if (BCM_FAILURE(rv)) {
   7945                             goto vlan_get_done;
   7946                         }
   7947                         l3_intf.l3a_intf_id = egress_object.intf;
   7948 
   7949                     } else {
   7950                         /* L3 Interface */
   7951                         l3_intf.l3a_intf_id  = intf_base + ls_pos;
   7952                     }                    
   7953                 } else 
   7954 #endif
   7955                 {
   7956                     next_hop_index = intf_base + ls_pos;
   7957                     rv = READ_EGR_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY,
   7958                           next_hop_index, &egr_nh);
   7959                     if (BCM_FAILURE(rv)) {
   7960                         goto vlan_get_done;
   7961                     }
   7962                     entry_type = soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   7963                           &egr_nh, ENTRY_TYPEf);
   7964                     bcm_l3_intf_t_init(&l3_intf);
   7965                     if (entry_type == 7) {
   7966                         l3_intf.l3a_intf_id = 
   7967                         soc_EGR_L3_NEXT_HOPm_field32_get(unit,
   7968                                &egr_nh, L3MC__INTF_NUMf);
   7969                     } else {
   7970                         egr_if = next_hop_index + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit);
   7971                         rv = bcm_esw_l3_egress_get(unit, 
   7972                                egr_if, &egress_object);
   7973                         if (BCM_FAILURE(rv)) {
   7974                             goto vlan_get_done;
   7975                         }
   7976                         l3_intf.l3a_intf_id = egress_object.intf;
   7977                     }
   7978                 } /* END of if not KATANA2 */
   7979                 rv = bcm_esw_l3_intf_get(unit, &l3_intf);
   7980                 if (BCM_FAILURE(rv)) {
   7981                     goto vlan_get_done;
   7982                 }
   7983                 BCM_VLAN_VEC_SET(vlan_vec, l3_intf.l3a_vid);
   7984                 vlan_count++;
   7985                
   7986             }
   7987         }
   7988         prev_repl_entry_ptr = repl_entry_ptr;
   7989         repl_entry_ptr = soc_MMU_REPL_LIST_TBLm_field32_get(unit,
   7990                 &repl_list_entry, NEXTPTRf);
   7991         if (vlan_count >= REPL_PORT_GROUP_INTF_COUNT(unit, port, ipmc_id)) {
   7992             break;
   7993         }
   7994     }
   7995 
   7996 vlan_get_done:
   7997     REPL_UNLOCK(unit);
   7998     return rv;
   7999 }
   8000 
   8001 /*
   8002  * Function:
   8003  *      _bcm_tr3_ipmc_repl_add
   8004  * Purpose:
   8005  *      Add VLAN to selected ports' replication list for chosen
   8006  *      IPMC group.
   8007  *Parameters:
   8008  *      unit     - StrataSwitch PCI device unit number.
   8009  *      ipmc_id  - IPMC group number.
   8010  *      port     - port to add.
   8011  *      vlan     - VLAN to replicate.
   8012  * Returns:
   8013  *      BCM_E_XXX
   8014  */
   8015 int
   8016 bcm_tr3_ipmc_repl_add(int unit, int ipmc_id, bcm_port_t port,
   8017                      bcm_vlan_t vlan)
   8018 {
   8019     int alloc_size, intf_max, if_count, rv = BCM_E_NONE;
   8020     bcm_if_t *if_array = NULL;
   8021     pbmp_t pbmp, ubmp;
   8022     bcm_l3_intf_t l3_intf;
   8023     bcm_if_t intf_add;
   8024     _tr3_if_updated_t if_updated;
   8025     int repl_start_ptr = 0;
   8026     
   8027     REPL_INIT(unit);
   8028     REPL_GROUP_ID(unit, ipmc_id);
   8029     REPL_PORT_CHECK(unit, port);
   8030 
   8031     /* Check if port belongs to this VLAN */
   8032     BCM_IF_ERROR_RETURN
   8033         (bcm_esw_vlan_port_get(unit, vlan, &pbmp, &ubmp));
   8034     if (!SOC_PBMP_MEMBER(pbmp, port)) {
   8035         return BCM_E_PARAM;
   8036     }
   8037 
   8038     bcm_l3_intf_t_init(&l3_intf);
   8039     l3_intf.l3a_vid = vlan;
   8040     if (bcm_esw_l3_intf_find_vlan(unit, &l3_intf) < 0) {
   8041         return BCM_E_PARAM;
   8042     }
   8043 
   8044     REPL_LOCK(unit);
   8045 
   8046     intf_max = 1 + REPL_PORT_GROUP_INTF_COUNT(unit, port, ipmc_id);
   8047     alloc_size = intf_max * sizeof(bcm_if_t);
   8048     if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   8049     if (if_array == NULL) {
   8050         REPL_UNLOCK(unit);
   8051         return BCM_E_MEMORY;
   8052     }
   8053 
   8054     rv = _bcm_tr3_ipmc_egress_intf_get(unit, ipmc_id, port, intf_max,
   8055                                        if_array, &if_count, &repl_start_ptr);
   8056     if (BCM_SUCCESS(rv)) {
   8057         if (if_count < intf_max) {
   8058             if_array[if_count++] = l3_intf.l3a_intf_id;
   8059             intf_add = l3_intf.l3a_intf_id;
   8060             if_updated.if_array_new = &intf_add;
   8061             if_updated.if_count_new = 1;
   8062             rv = _bcm_tr3_ipmc_egress_intf_set(unit, ipmc_id, port,
   8063                                                if_count, if_array,
   8064                                                &if_updated,TRUE, FALSE,
   8065                                                repl_start_ptr);
   8066         } else {
   8067             rv = BCM_E_EXISTS;
   8068         }
   8069     }
   8070 
   8071     REPL_UNLOCK(unit);
   8072     sal_free(if_array);
   8073     return rv;
   8074 }
   8075 
   8076 /*
   8077  * Function:
   8078  *      _bcm_tr3_ipmc_repl_delete
   8079  * Purpose:
   8080  *      Remove VLAN from selected ports' replication list for chosen
   8081  *      IPMC group.
   8082  * Parameters:
   8083  *      unit     - StrataSwitch PCI device unit number.
   8084  *      ipmc_id  - IPMC group number.
   8085  *      port     - port to remove.
   8086  *      vlan     - VLAN to delete from replication.
   8087  * Returns:
   8088  *      BCM_E_XXX
   8089  */
   8090 
   8091 int
   8092 bcm_tr3_ipmc_repl_delete(int unit, int ipmc_id, bcm_port_t port,
   8093                         bcm_vlan_t vlan)
   8094 {
   8095     int alloc_size, intf_max, if_count, if_cur, match, rv = BCM_E_NONE;
   8096     bcm_if_t *if_array = NULL;
   8097     bcm_l3_intf_t l3_intf;
   8098     bcm_if_t intf_del;
   8099     _tr3_if_updated_t if_updated;
   8100     int repl_start_ptr = 0;
   8101 
   8102     REPL_INIT(unit);
   8103     REPL_GROUP_ID(unit, ipmc_id);
   8104     REPL_PORT_CHECK(unit, port);
   8105 
   8106     if (!REPL_PORT_GROUP_INTF_COUNT(unit, port, ipmc_id)) {
   8107         return BCM_E_NOT_FOUND;
   8108     }
   8109 
   8110     bcm_l3_intf_t_init(&l3_intf);
   8111     l3_intf.l3a_vid = vlan;
   8112     if (bcm_esw_l3_intf_find_vlan(unit, &l3_intf) < 0) {
   8113         return BCM_E_PARAM;
   8114     }
   8115 
   8116     REPL_LOCK(unit);
   8117     intf_max = REPL_PORT_GROUP_INTF_COUNT(unit, port, ipmc_id);
   8118     alloc_size = intf_max * sizeof(bcm_if_t);
   8119     if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   8120     if (if_array == NULL) {
   8121         REPL_UNLOCK(unit);
   8122         return BCM_E_MEMORY;
   8123     }
   8124 
   8125     rv = _bcm_tr3_ipmc_egress_intf_get(unit, ipmc_id, port, intf_max,
   8126                                        if_array, &if_count, &repl_start_ptr);
   8127     if (BCM_SUCCESS(rv)) {
   8128         match = FALSE;
   8129         for (if_cur = 0; if_cur < if_count; if_cur++) {
   8130             if (match) {
   8131                 if_array[if_cur - 1] = if_array[if_cur];
   8132             } else {
   8133                 if (if_array[if_cur] == l3_intf.l3a_intf_id) {
   8134                     match = TRUE;
   8135                 }
   8136             }
   8137         }
   8138         if (match) {
   8139             if_count--;
   8140             intf_del = l3_intf.l3a_intf_id;
   8141             if_updated.if_count_del = 1;
   8142             if_updated.if_array_del = &intf_del;
   8143             rv = _bcm_tr3_ipmc_egress_intf_set(unit, ipmc_id, port,
   8144                                                if_count, if_array,
   8145                                                &if_updated, TRUE, FALSE,
   8146                                                repl_start_ptr);
   8147         } else {
   8148             rv = BCM_E_NOT_FOUND;
   8149         }
   8150     }
   8151     REPL_UNLOCK(unit);
   8152     sal_free(if_array);
   8153     return rv;
   8154 }
   8155 
   8156 /*
   8157  * Function:
   8158  *      bcm_tr3_ipmc_repl_delete_all
   8159  * Purpose:
   8160  *      Remove all VLANs from selected ports' replication list for chosen
   8161  *      IPMC group.
   8162  * Parameters:
   8163  *      unit     - StrataSwitch PCI device unit number.
   8164  *      ipmc_id  - The MC index number.
   8165  *      port     - port from which to remove VLANs.
   8166  * Returns:
   8167  *      BCM_E_XXX
   8168  */
   8169 int
   8170 bcm_tr3_ipmc_repl_delete_all(int unit, int ipmc_id, bcm_port_t port)
   8171 {
   8172     REPL_INIT(unit);
   8173     REPL_GROUP_ID(unit, ipmc_id);
   8174     REPL_PORT_CHECK(unit, port);
   8175 
   8176     if (!REPL_PORT_GROUP_INTF_COUNT(unit, port, ipmc_id)) {
   8177         /* Nothing to do */
   8178         return BCM_E_NONE;
   8179     }
   8180 
   8181     return bcm_tr3_ipmc_egress_intf_set(unit, ipmc_id, port, 0, NULL,
   8182                                         TRUE, FALSE);
   8183 }
   8184 
   8185 /*
   8186  * Function:
   8187  *      bcm_tr3_ipmc_repl_set
   8188  * Purpose:
   8189  *      Assign set of VLANs provided to port's replication list for chosen
   8190  *      IPMC group.
   8191  * Parameters:
   8192  *      unit     - StrataSwitch PCI device unit number.
   8193  *      ipmc_id  - The index number.
   8194  *      port     - port to list.
   8195  *      vlan_vec - (IN) vector of replicated VLANs common to selected ports.
   8196  * Returns:
   8197  *      BCM_E_XXX
   8198  */
   8199 int
   8200 bcm_tr3_ipmc_repl_set(int unit, int ipmc_id, bcm_port_t port,
   8201                      bcm_vlan_vector_t vlan_vec)
   8202 {
   8203     int rv = BCM_E_NONE;
   8204     bcm_if_t *if_array = NULL;
   8205     bcm_l3_intf_t l3_intf;
   8206     pbmp_t pbmp, ubmp;
   8207     int  intf_num, intf_max, alloc_size, vid;
   8208 
   8209     REPL_INIT(unit);
   8210     REPL_GROUP_ID(unit, ipmc_id);
   8211     REPL_PORT_CHECK(unit, port);
   8212 
   8213     intf_max = BCM_VLAN_MAX - BCM_VLAN_MIN + 1;
   8214     alloc_size = intf_max * sizeof(bcm_if_t);
   8215     if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   8216     if (if_array == NULL) {
   8217         return BCM_E_MEMORY;
   8218     }
   8219 
   8220     sal_memset(if_array, 0, alloc_size);
   8221     intf_num = 0;
   8222     for (vid = BCM_VLAN_MIN; vid < BCM_VLAN_MAX; vid++) {
   8223         if (BCM_VLAN_VEC_GET(vlan_vec, vid)) {
   8224             rv = bcm_esw_vlan_port_get(unit, vid, &pbmp, &ubmp);
   8225             if (BCM_FAILURE(rv)) {
   8226                 sal_free(if_array);
   8227                 return rv;
   8228             }
   8229             if (!BCM_PBMP_MEMBER(pbmp, port)) {
   8230                 sal_free(if_array);
   8231                 return BCM_E_PARAM;
   8232             }
   8233             bcm_l3_intf_t_init(&l3_intf);
   8234             l3_intf.l3a_vid = vid;
   8235             if ((rv = bcm_esw_l3_intf_find_vlan(unit, &l3_intf)) < 0) {
   8236                 sal_free(if_array);
   8237                 return rv;
   8238             }
   8239             if_array[intf_num++] = l3_intf.l3a_intf_id;
   8240         }
   8241     }
   8242 
   8243     rv = bcm_tr3_ipmc_egress_intf_set(unit, ipmc_id, port,
   8244                                      intf_num, if_array, TRUE, FALSE);
   8245 
   8246     sal_free(if_array);
   8247     return rv;
   8248 }
   8249 
   8250 /*
   8251  * Function:
   8252  *      _bcm_tr3_ipmc_egress_intf_add
   8253  * Purpose:
   8254  *      Add encap ID to selected ports' replication list for chosen
   8255  *      IPMC group.
   8256  * Parameters:
   8257  *      unit     - StrataSwitch PCI device unit number.
   8258  *      ipmc_id  - IPMC group number.
   8259  *      port     - port to add.
   8260  *      encap_id - Encap ID.
   8261  *      is_l3    - Indicates if multicast group type is IPMC.
   8262  * Returns:
   8263  *      BCM_E_XXX
   8264  */
   8265 int
   8266 _bcm_tr3_ipmc_egress_intf_add(int unit, int ipmc_id, bcm_port_t port,
   8267                             int encap_id, int is_l3)
   8268 {
   8269     bcm_if_t *if_array = NULL;
   8270     int  intf_num, intf_max, alloc_size, rv = BCM_E_NONE;
   8271     bcm_l3_intf_t l3_intf;
   8272     _tr3_if_updated_t if_updated;
   8273     bcm_if_t intf_add;
   8274     bcm_port_t port_in = port;
   8275     int repl_start_ptr = 0;
   8276 
   8277     REPL_INIT(unit);
   8278     REPL_GROUP_ID(unit, ipmc_id);
   8279 
   8280 #if defined(BCM_HGPROXY_COE_SUPPORT)
   8281     if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) &&
   8282         BCM_GPORT_IS_SET(port) &&
   8283         _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) {
   8284             BCM_IF_ERROR_RETURN(
   8285                 _bcmi_coe_subport_physical_port_get(unit, port, &port));
   8286     }
   8287 #endif
   8288 
   8289     /* Replication is allowed on CPU ports, only on TD2 */
   8290     if(IS_CPU_PORT(unit, port)) {
   8291         if(!SOC_IS_TRIDENT2X(unit)) {
   8292             return BCM_E_PARAM;
   8293         }
   8294     }
   8295     else
   8296     {   
   8297         REPL_PORT_CHECK(unit, port);
   8298     }
   8299 
   8300 #if defined (BCM_TRIDENT2PLUS_SUPPORT)
   8301     if ((BCM_MC_PER_TRUNK_REPL_MODE(unit)) &&
   8302         encap_id == BCM_ENCAP_TRUNK_MEMBER) {
   8303         /* For TH_MC_PER_TRUNK_REPL mode, indentical replication list
   8304          * is set for all the members of a trunk.
   8305          */
   8306         return BCM_E_NONE;
   8307     }
   8308 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   8309     intf_max = REPL_INTF_TOTAL(unit);
   8310     alloc_size = intf_max * sizeof(bcm_if_t);
   8311     if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   8312     if (if_array == NULL) {
   8313         return BCM_E_MEMORY;
   8314     }
   8315 
   8316     REPL_LOCK(unit);
   8317     rv = _bcm_tr3_ipmc_egress_intf_get(unit, ipmc_id, port, intf_max,
   8318                                        if_array, &intf_num, &repl_start_ptr);
   8319     if (BCM_SUCCESS(rv)) {
   8320         if (intf_num < intf_max) {
   8321             if_array[intf_num++] = encap_id;
   8322 
   8323             /* For IPMC and Trill, check port is a member of the L3 interface's 
   8324              * VLAN. Performing this check here is more efficient than doing 
   8325              * it in bcm_tr3_ipmc_egress_intf_set.
   8326              */ 
   8327             if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, encap_id)) {
   8328                 /* L3 interface is used */
   8329 
   8330                 if (encap_id > soc_mem_index_max(unit, EGR_L3_INTFm)) {
   8331                     rv = BCM_E_PARAM;
   8332                     goto intf_add_done;
   8333                 }
   8334 
   8335                 bcm_l3_intf_t_init(&l3_intf);
   8336                 l3_intf.l3a_intf_id = encap_id;
   8337                 rv = bcm_esw_l3_intf_get(unit, &l3_intf);
   8338                 if (BCM_FAILURE(rv)) {
   8339                     goto intf_add_done;
   8340                 }
   8341             }
   8342             
   8343             sal_memset(&if_updated, 0, sizeof(if_updated));
   8344             intf_add = encap_id;
   8345             if_updated.if_array_new = &intf_add;
   8346             if_updated.if_count_new = 1;
   8347             rv = _bcm_tr3_ipmc_egress_intf_set(unit, ipmc_id,
   8348                                                port_in, intf_num, if_array,
   8349                                                &if_updated, is_l3, FALSE,
   8350                                                repl_start_ptr);
   8351         } else {
   8352             rv = BCM_E_EXISTS;
   8353         }
   8354     }
   8355 
   8356 intf_add_done:
   8357 
   8358     REPL_UNLOCK(unit);
   8359     sal_free(if_array);
   8360     return rv;
   8361 }
   8362 
   8363 /*
   8364  * Function:
   8365  *      _bcm_tr3_ipmc_egress_intf_delete
   8366  * Purpose:
   8367  *      Remove encap ID from selected ports' replication list for chosen
   8368  *      IPMC group.
   8369  * Parameters:
   8370  *      unit     - StrataSwitch PCI device unit number.
   8371  *      ipmc_id  - IPMC group number.
   8372  *      port     - port to remove.
   8373  *      if_max   - Maximal interface.
   8374  *      encap_id - Encap ID to delete from replication.
   8375  *      is_l3    - Indicates if multicast group type is IPMC.
   8376  * Returns:
   8377  *      BCM_E_XXX
   8378  */
   8379 int
   8380 _bcm_tr3_ipmc_egress_intf_delete(int unit, int ipmc_id, bcm_port_t port,
   8381                                int if_max, int encap_id, int is_l3)
   8382 {
   8383     bcm_if_t *if_array = NULL;
   8384     int alloc_size, if_count, if_cur, match, rv = BCM_E_NONE;
   8385     _tr3_if_updated_t if_updated;
   8386     bcm_if_t intf_del;
   8387     int repl_start_ptr = 0;
   8388     
   8389     REPL_INIT(unit);
   8390     REPL_GROUP_ID(unit, ipmc_id);
   8391 
   8392     /* Replication is allowed on CPU ports, only on TD2 */
   8393     if(IS_CPU_PORT(unit, port)) {
   8394         if(!SOC_IS_TRIDENT2X(unit)) {
   8395             return BCM_E_PARAM;
   8396         }
   8397     }
   8398     else
   8399     {   
   8400         REPL_PORT_CHECK(unit, port);
   8401     }
   8402 
   8403 #if defined (BCM_TRIDENT2PLUS_SUPPORT)
   8404     if ((BCM_MC_PER_TRUNK_REPL_MODE(unit)) &&
   8405         encap_id == BCM_ENCAP_TRUNK_MEMBER) {
   8406         /* For MC_PER_TRUNK_REPL mode, indentical replication list
   8407          * is set for all the members of a trunk.
   8408          */
   8409         return BCM_E_NONE;
   8410     }
   8411 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   8412 
   8413     if (!REPL_PORT_GROUP_INTF_COUNT(unit, port, ipmc_id)) {
   8414         return BCM_E_NOT_FOUND;
   8415     }
   8416 
   8417     if ((if_max <= 0) || ((uint32)if_max > REPL_INTF_TOTAL(unit))) {
   8418         return BCM_E_PARAM;
   8419     }
   8420 
   8421     alloc_size = if_max * sizeof(bcm_if_t);
   8422     if_array = sal_alloc(alloc_size, "IPMC repl interface array");
   8423     if (if_array == NULL) {
   8424         return BCM_E_MEMORY;
   8425     }
   8426 
   8427     REPL_LOCK(unit);
   8428     rv = _bcm_tr3_ipmc_egress_intf_get(unit, ipmc_id, port, if_max,
   8429                                        if_array, &if_count, &repl_start_ptr);
   8430     if (BCM_SUCCESS(rv)) {
   8431         match = FALSE;
   8432         for (if_cur = 0; if_cur < if_count; if_cur++) {
   8433             if (match) {
   8434                 if_array[if_cur - 1] = if_array[if_cur];
   8435             } else {
   8436                 if (if_array[if_cur] == encap_id) {
   8437                     match = TRUE;
   8438                 }
   8439             }
   8440         }
   8441         if (match) {
   8442             if_count--;
   8443             sal_memset(&if_updated, 0, sizeof(if_updated));
   8444             intf_del = encap_id;
   8445             if_updated.if_count_del = 1;
   8446             if_updated.if_array_del = &intf_del;
   8447             rv = _bcm_tr3_ipmc_egress_intf_set(unit, ipmc_id, port, 
   8448                                                if_count, if_array,
   8449                                                &if_updated, is_l3, FALSE,
   8450                                                repl_start_ptr);
   8451         } else {
   8452             rv = BCM_E_NOT_FOUND;
   8453         }
   8454     }
   8455 
   8456     REPL_UNLOCK(unit);
   8457     sal_free(if_array);
   8458     return rv;
   8459 }
   8460 
   8461 /*
   8462  * Function:
   8463  *      bcm_tr3_ipmc_trill_mac_update
   8464  * Purpose:
   8465  *      Update the Trill MAC address in next hop entries that are
   8466  *      in Trill multicast replication list. 
   8467  * Parameters:
   8468  *      unit      - (IN) SOC unit #
   8469  *      mac_field - (IN) MAC address
   8470  *      flag      - (IN) 0 = Set the lower 24 bits of MAC address,
   8471  *                       1 = Set the higher 24 bits of MAC address.
   8472  * Returns:
   8473  *      BCM_E_XXX
   8474  */
   8475 int
   8476 bcm_tr3_ipmc_trill_mac_update(int unit, uint32 mac_field, uint8 flag)
   8477 {
   8478     int intf, nh_index;
   8479     egr_l3_next_hop_entry_t egr_nh;
   8480     uint32 entry_type;
   8481     bcm_mac_t mac;
   8482 
   8483     for (intf = 0; intf < soc_mem_index_count(unit, EGR_L3_INTFm); intf++) {
   8484         nh_index = REPL_L3_INTF_NEXT_HOP_TRILL(unit, intf);
   8485         if (nh_index >= 0) {
   8486             SOC_IF_ERROR_RETURN(soc_mem_read(unit, EGR_L3_NEXT_HOPm,
   8487                         MEM_BLOCK_ANY, nh_index, &egr_nh));
   8488             entry_type = soc_mem_field32_get(unit, EGR_L3_NEXT_HOPm,
   8489                     &egr_nh, ENTRY_TYPEf);
   8490             if (entry_type == 0) { /* normal entry type */
   8491                 soc_mem_mac_addr_get(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   8492                         L3__MAC_ADDRESSf, mac);
   8493                 if (!flag) {
   8494                     /* Set the low-order bytes */
   8495                     mac[3] = (uint8) (mac_field >> 16 & 0xff);
   8496                     mac[4] = (uint8) (mac_field >> 8 & 0xff);
   8497                     mac[5] = (uint8) (mac_field & 0xff);
   8498                 } else {
   8499                     /* Set the High-order bytes */
   8500                     mac[0] = (uint8) (mac_field >> 16 & 0xff);
   8501                     mac[1] = (uint8) (mac_field >> 8 & 0xff);
   8502                     mac[2] = (uint8) (mac_field & 0xff);
   8503                 }
   8504                 soc_mem_mac_addr_set(unit, EGR_L3_NEXT_HOPm, &egr_nh,
   8505                         L3__MAC_ADDRESSf, mac);
   8506             }
   8507         }
   8508     }
   8509 
   8510     return BCM_E_NONE;
   8511 }
   8512 
   8513 /*
   8514  * Function:
   8515  *      bcm_tr3_ipmc_l3_intf_next_hop_free
   8516  * Purpose:
   8517  *      Free the next hop index associated with the given L3 interface.
   8518  * Parameters:
   8519  *      unit - (IN) SOC unit #
   8520  *      intf - (IN) L3 interface ID
   8521  * Returns:
   8522  *      BCM_E_XXX
   8523  */
   8524 int
   8525 bcm_tr3_ipmc_l3_intf_next_hop_free(int unit, int intf)
   8526 {
   8527     int nh_index;
   8528 
   8529     if (_tr3_repl_info[unit] == NULL) {
   8530         /* IPMC replication is not initialized. There is no next hop
   8531          * index to free.
   8532          */
   8533         return BCM_E_NONE;
   8534     }
   8535 
   8536     nh_index = REPL_L3_INTF_NEXT_HOP_TRILL(unit, intf);
   8537     if (nh_index >= 0) {
   8538         SOC_IF_ERROR_RETURN
   8539             (WRITE_EGR_L3_NEXT_HOPm(unit, MEM_BLOCK_ALL, nh_index,
   8540                                     soc_mem_entry_null(unit, EGR_L3_NEXT_HOPm)));
   8541         BCM_IF_ERROR_RETURN
   8542             (bcm_xgs3_nh_del(unit, _BCM_L3_SHR_WRITE_DISABLE, nh_index));
   8543         REPL_L3_INTF_NEXT_HOP_TRILL(unit, intf) = -1;
   8544     }
   8545 
   8546     return BCM_E_NONE;
   8547 }
   8548 
   8549 /*
   8550  * Function:
   8551  *      bcm_tr3_ipmc_l3_intf_next_hop_get
   8552  * Purpose:
   8553  *      Get the next hop index that was silently allocated to the L3 interface.
   8554  * Parameters:
   8555  *      unit - (IN) SOC unit #
   8556  *      intf - (IN) L3 interface ID
   8557  *      nh_index - (OUT) Next hop index
   8558  * Returns:
   8559  *      BCM_E_XXX
   8560  */
   8561 int
   8562 bcm_tr3_ipmc_l3_intf_next_hop_get(int unit, int intf, int *nh_index)
   8563 {
   8564     *nh_index = REPL_L3_INTF_NEXT_HOP_IPMC(unit, intf);
   8565 
   8566     if (*nh_index == REPL_NH_INDEX_UNALLOCATED ||
   8567         *nh_index == REPL_NH_INDEX_L3_EGRESS_ALLOCATED) {
   8568         return BCM_E_NOT_FOUND;
   8569     }
   8570 
   8571     return BCM_E_NONE;
   8572 }
   8573 
   8574 /*
   8575  * Function:
   8576  *      bcm_tr3_ipmc_l3_intf_next_hop_l3_egress_set
   8577  * Purpose:
   8578  *      Inform the IPMC module that a next hop index has been allocated
   8579  *      for the given L3 interface by the bcm_l3_egress_create API.
   8580  * Parameters:
   8581  *      unit - (IN) SOC unit #
   8582  *      intf - (IN) L3 interface ID
   8583  * Returns:
   8584  *      BCM_E_XXX
   8585  */
   8586 int
   8587 bcm_tr3_ipmc_l3_intf_next_hop_l3_egress_set(int unit, int intf)
   8588 {
   8589     int nh_index;
   8590 
   8591     nh_index = REPL_L3_INTF_NEXT_HOP_IPMC(unit, intf);
   8592 
   8593     if (nh_index == REPL_NH_INDEX_UNALLOCATED) {
   8594         REPL_L3_INTF_NEXT_HOP_IPMC(unit, intf) =
   8595             REPL_NH_INDEX_L3_EGRESS_ALLOCATED;
   8596     } else if (nh_index == REPL_NH_INDEX_L3_EGRESS_ALLOCATED) {
   8597         /* Do nothing. Users are allowed to create multiple L3
   8598          * egress objects based on the same L3 interface.
   8599          */
   8600     } else {
   8601         /* IPMC module had already silently allocated a next hop index
   8602          * for this L3 interface.
   8603          */
   8604         return BCM_E_CONFIG;
   8605     }
   8606         
   8607     return BCM_E_NONE;
   8608 }
   8609 #ifdef BCM_WARM_BOOT_SUPPORT
   8610 
   8611 /*
   8612  * Function:
   8613  *      bcm_tr3_ipmc_repl_l3_intf_scache_size_get
   8614  * Purpose:
   8615  *      Get the required scache size for storing a bitmap
   8616  *      of L3 interfaces.
   8617  * Parameters:
   8618  *      unit - StrataSwitch unit #
   8619  *      size - (OUT) Number of bytes
   8620  * Returns:
   8621  *      BCM_E_xxx
   8622  */
   8623 int 
   8624 bcm_tr3_ipmc_repl_l3_intf_scache_size_get(
   8625     int unit, 
   8626     uint32 *size)
   8627 {
   8628     int num_l3_intf;
   8629 
   8630     *size = 0;
   8631     num_l3_intf = soc_mem_index_count(unit, EGR_L3_INTFm);
   8632     *size += SHR_BITALLOCSIZE(num_l3_intf);
   8633 
   8634     return BCM_E_NONE;
   8635 }
   8636 
   8637 /*
   8638  * Function:
   8639  *      bcm_tr3_ipmc_repl_l3_intf_sync
   8640  * Purpose:
   8641  *      Record L3 interface bitmap into the scache.
   8642  * Parameters:
   8643  *      unit - StrataSwitch unit #
   8644  *      scache_ptr - (IN/OUT) Scache pointer
   8645  * Returns:
   8646  *      BCM_E_xxx
   8647  */
   8648 int 
   8649 bcm_tr3_ipmc_repl_l3_intf_sync(
   8650     int unit, 
   8651     uint8 **scache_ptr)
   8652 {
   8653     int num_l3_intf, i;
   8654     SHR_BITDCL *l3_intf_bitmap = NULL;
   8655 
   8656     REPL_INIT(unit);
   8657 
   8658     /* Create a bitmap of L3 interfaces */
   8659     num_l3_intf = soc_mem_index_count(unit, EGR_L3_INTFm);
   8660     l3_intf_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_l3_intf),
   8661             "L3 interface bitmap");
   8662     if (NULL == l3_intf_bitmap) {
   8663         return BCM_E_MEMORY;
   8664     }
   8665     sal_memset(l3_intf_bitmap, 0, SHR_BITALLOCSIZE(num_l3_intf));
   8666 
   8667     /* For the L3 interfaces that were allocated next hop indices by
   8668      * bcm_l3_egress_create API, set the bit in the bitmap.
   8669      */
   8670     for (i = 0; i < num_l3_intf; i++) {
   8671         if (REPL_L3_INTF_NEXT_HOP_IPMC(unit, i) ==
   8672                 REPL_NH_INDEX_L3_EGRESS_ALLOCATED) {
   8673             SHR_BITSET(l3_intf_bitmap, i);
   8674         }
   8675     }
   8676 
   8677     /* Store the bitmap into scache */
   8678     sal_memcpy((*scache_ptr), l3_intf_bitmap, SHR_BITALLOCSIZE(num_l3_intf));
   8679     (*scache_ptr) += SHR_BITALLOCSIZE(num_l3_intf);
   8680 
   8681     sal_free(l3_intf_bitmap);
   8682     return BCM_E_NONE;
   8683 }
   8684 
   8685 /*
   8686  * Function:
   8687  *      bcm_tr3_ipmc_repl_l3_intf_scache_recover
   8688  * Purpose:
   8689  *      Recover L3 interface bitmap from scache.
   8690  * Parameters:
   8691  *      unit - (IN) SOC unit number.
   8692  *      scache_ptr - (IN/OUT) Scache pointer
   8693  * Returns:
   8694  *      BCM_E_XXX
   8695  */
   8696 int
   8697 bcm_tr3_ipmc_repl_l3_intf_scache_recover(int unit, uint8 **scache_ptr)
   8698 {
   8699     int num_l3_intf, i;
   8700     SHR_BITDCL *l3_intf_bitmap = NULL;
   8701 
   8702     /* Recover L3 interface bitmap */
   8703     num_l3_intf = soc_mem_index_count(unit, EGR_L3_INTFm);
   8704     l3_intf_bitmap = sal_alloc(SHR_BITALLOCSIZE(num_l3_intf),
   8705             "L3 interface bitmap");
   8706     if (NULL == l3_intf_bitmap) {
   8707         return BCM_E_MEMORY;
   8708     }
   8709     sal_memcpy(l3_intf_bitmap, (*scache_ptr), SHR_BITALLOCSIZE(num_l3_intf));
   8710     (*scache_ptr) += SHR_BITALLOCSIZE(num_l3_intf);
   8711 
   8712     for (i = 0; i < num_l3_intf; i++) {
   8713         if (SHR_BITGET(l3_intf_bitmap, i)) {
   8714             REPL_L3_INTF_NEXT_HOP_IPMC(unit, i) =
   8715                 REPL_NH_INDEX_L3_EGRESS_ALLOCATED;
   8716         }
   8717     }
   8718 
   8719     sal_free(l3_intf_bitmap);
   8720     return BCM_E_NONE;
   8721 }
   8722 
   8723 /*
   8724  * Function:
   8725  *      bcm_tr3_ipmc_repl_l3_intf_nh_map_scache_size_get
   8726  * Purpose:
   8727  *      Get the required scache size for storing map from L3 interfaces
   8728  *      to SDK managed next hop.
   8729  * Parameters:
   8730  *      unit - StrataSwitch unit #
   8731  *      size - (OUT) Number of bytes
   8732  * Returns:
   8733  *      BCM_E_xxx
   8734  */
   8735 int
   8736 bcm_tr3_ipmc_repl_l3_intf_nh_map_scache_size_get(
   8737     int unit,
   8738     uint32 *size)
   8739 {
   8740     int num_l3_intf;
   8741 
   8742     *size = 0;
   8743     num_l3_intf = soc_mem_index_count(unit, EGR_L3_INTFm);
   8744     *size += (num_l3_intf * sizeof(int));
   8745 
   8746     return BCM_E_NONE;
   8747 }
   8748 
   8749 /*
   8750  * Function:
   8751  *      bcm_tr3_ipmc_repl_l3_intf_nh_map_sync
   8752  * Purpose:
   8753  *      Record L3 interface map to SDK managed nexthop into the scache.
   8754  * Parameters:
   8755  *      unit - StrataSwitch unit #
   8756  *      scache_ptr - (IN/OUT) Scache pointer
   8757  * Returns:
   8758  *      BCM_E_xxx
   8759  */
   8760 int
   8761 bcm_tr3_ipmc_repl_l3_intf_nh_map_sync(
   8762     int unit,
   8763     uint8 **scache_ptr)
   8764 {
   8765     int num_l3_intf, i;
   8766 
   8767     REPL_INIT(unit);
   8768 
   8769     num_l3_intf = soc_mem_index_count(unit, EGR_L3_INTFm);
   8770 
   8771     for (i = 0; i < num_l3_intf; i++) {
   8772         *(int *) (*scache_ptr) = REPL_L3_INTF_NEXT_HOP_IPMC(unit, i);
   8773         (*scache_ptr) += sizeof(int);
   8774     }
   8775 
   8776     return BCM_E_NONE;
   8777 }
   8778 
   8779 /*
   8780  * Function:
   8781  *      bcm_tr3_ipmc_repl_l3_intf_nh_map_scache_recover
   8782  * Purpose:
   8783  *      Recover L3 interface nexthop map from scache.
   8784  * Parameters:
   8785  *      unit - (IN) SOC unit number.
   8786  *      scache_ptr - (IN/OUT) Scache pointer
   8787  * Returns:
   8788  *      BCM_E_XXX
   8789  */
   8790 int
   8791 bcm_tr3_ipmc_repl_l3_intf_nh_map_scache_recover(int unit, uint8 **scache_ptr)
   8792 {
   8793     int  num_l3_intf, i;
   8794 
   8795     num_l3_intf = soc_mem_index_count(unit, EGR_L3_INTFm);
   8796 
   8797     for (i = 0; i < num_l3_intf; i++) {
   8798         REPL_L3_INTF_NEXT_HOP_IPMC(unit, i) = *(int *)(*scache_ptr);
   8799         (*scache_ptr) += sizeof(int);
   8800     }
   8801 
   8802     return BCM_E_NONE;
   8803 }
   8804 
   8805 /*
   8806  * Function:
   8807  *      bcm_tr3_ipmc_repl_l3_intf_trill_nh_map_scache_size_get
   8808  * Purpose:
   8809  *      Get the required scache size for storing map from L3 interfaces
   8810  *      to SDK managed trill next hop.
   8811  * Parameters:
   8812  *      unit - StrataSwitch unit #
   8813  *      size - (OUT) Number of bytes
   8814  * Returns:
   8815  *      BCM_E_xxx
   8816  */
   8817 int
   8818 bcm_tr3_ipmc_repl_l3_intf_trill_nh_map_scache_size_get(
   8819     int unit,
   8820     uint32 *size)
   8821 {
   8822     int num_l3_intf;
   8823 
   8824     *size = 0;
   8825     num_l3_intf = soc_mem_index_count(unit, EGR_L3_INTFm);
   8826     *size += (num_l3_intf * sizeof(int));
   8827 
   8828     return BCM_E_NONE;
   8829 }
   8830 
   8831 /*
   8832  * Function:
   8833  *      bcm_tr3_ipmc_repl_l3_intf_trill_nh_map_sync
   8834  * Purpose:
   8835  *      Record L3 interface map to SDK managed trill nexthop into the scache.
   8836  * Parameters:
   8837  *      unit - StrataSwitch unit #
   8838  *      scache_ptr - (IN/OUT) Scache pointer
   8839  * Returns:
   8840  *      BCM_E_xxx
   8841  */
   8842 int
   8843 bcm_tr3_ipmc_repl_l3_intf_trill_nh_map_sync(
   8844     int unit,
   8845     uint8 **scache_ptr)
   8846 {
   8847     int num_l3_intf, i;
   8848 
   8849     REPL_INIT(unit);
   8850 
   8851     num_l3_intf = soc_mem_index_count(unit, EGR_L3_INTFm);
   8852 
   8853     for (i = 0; i < num_l3_intf; i++) {
   8854         *(int *) (*scache_ptr) = REPL_L3_INTF_NEXT_HOP_TRILL(unit, i);
   8855         (*scache_ptr) += sizeof(int);
   8856     }
   8857 
   8858     return BCM_E_NONE;
   8859 }
   8860 
   8861 /*
   8862  * Function:
   8863  *      bcm_tr3_ipmc_repl_l3_intf_trill_nh_map_scache_recover
   8864  * Purpose:
   8865  *      Recover L3 interface trill nexthop map from scache.
   8866  * Parameters:
   8867  *      unit - (IN) SOC unit number.
   8868  *      scache_ptr - (IN/OUT) Scache pointer
   8869  * Returns:
   8870  *      BCM_E_XXX
   8871  */
   8872 int
   8873 bcm_tr3_ipmc_repl_l3_intf_trill_nh_map_scache_recover(int unit, uint8 **scache_ptr)
   8874 {
   8875     int  num_l3_intf, i;
   8876 
   8877     num_l3_intf = soc_mem_index_count(unit, EGR_L3_INTFm);
   8878 
   8879     for (i = 0; i < num_l3_intf; i++) {
   8880         REPL_L3_INTF_NEXT_HOP_TRILL(unit, i) = *(int *)(*scache_ptr);
   8881         (*scache_ptr) += sizeof(int);
   8882     }
   8883 
   8884     return BCM_E_NONE;
   8885 }
   8886 
   8887 
   8888 
   8889 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   8890 STATIC int
   8891 bcm_td2p_set_port_intf_cnt(int unit, int pipe, int aggid,
   8892                            int repl_group, int intf_cnt)
   8893 {
   8894     int port_iter, aggid_iter, pipe_iter;
   8895     uint32 regval;
   8896     bcm_pbmp_t            pbmp_all;
   8897 
   8898     BCM_PBMP_CLEAR(pbmp_all);
   8899     BCM_PBMP_ASSIGN(pbmp_all, PBMP_ALL(unit));
   8900 
   8901     PBMP_ITER(pbmp_all, port_iter) {
   8902         if (IS_RDB_PORT(unit, port_iter)) {
   8903             continue;
   8904         }
   8905         BCM_IF_ERROR_RETURN(
   8906             READ_MMU_TOQ_REPL_PORT_AGG_MAPr(unit, port_iter, &regval));
   8907         aggid_iter = soc_reg_field_get(unit, MMU_TOQ_REPL_PORT_AGG_MAPr, regval,
   8908                                        L3MC_PORT_AGG_IDf);
   8909         /* coverity[overrun-local:FALSE] */
   8910         pipe_iter = SOC_INFO(unit).port_pipe[port_iter];
   8911         if ((aggid_iter == aggid) && (pipe_iter == pipe)) {
   8912             /* coverity[overrun-local:FALSE] */
   8913             REPL_PORT_GROUP_INTF_COUNT(unit, port_iter, repl_group) = intf_cnt;
   8914         }
   8915     }
   8916 
   8917     return BCM_E_NONE;
   8918 }
   8919 
   8920 STATIC int
   8921 bcm_td2p_add_port_intf_cnt(int unit, int pipe, int aggid,
   8922                            int repl_group, int intf_cnt)
   8923 {
   8924     int port_iter, aggid_iter, pipe_iter;
   8925     uint32 regval;
   8926     bcm_pbmp_t            pbmp_all;
   8927 
   8928     BCM_PBMP_CLEAR(pbmp_all);
   8929     BCM_PBMP_ASSIGN(pbmp_all, PBMP_ALL(unit));
   8930 
   8931     PBMP_ITER(pbmp_all, port_iter) {
   8932         if (IS_RDB_PORT(unit, port_iter)) {
   8933             continue;
   8934         }
   8935         BCM_IF_ERROR_RETURN(
   8936             READ_MMU_TOQ_REPL_PORT_AGG_MAPr(unit, port_iter, &regval));
   8937         aggid_iter = soc_reg_field_get(unit, MMU_TOQ_REPL_PORT_AGG_MAPr, regval,
   8938                                        L3MC_PORT_AGG_IDf);
   8939         /* coverity[overrun-local:FALSE] */
   8940         pipe_iter = SOC_INFO(unit).port_pipe[port_iter];
   8941         if ((aggid_iter == aggid) && (pipe_iter == pipe)) {
   8942             /* coverity[overrun-local:FALSE] */
   8943             REPL_PORT_GROUP_INTF_COUNT(unit, port_iter, repl_group) += intf_cnt;
   8944         }
   8945     }
   8946 
   8947     return BCM_E_NONE;
   8948 }
   8949 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
   8950 
   8951 /*
   8952  * Function:
   8953  *      _bcm_tr3_ipmc_repl_reload
   8954  * Purpose:
   8955  *      Re-Initialize replication software to state consistent with
   8956  *      hardware.
   8957  * Parameters:
   8958  *      unit - SOC unit #
   8959  * Returns:
   8960  *      BCM_E_XXX
   8961  */
   8962 int
   8963 _bcm_tr3_ipmc_repl_reload(int unit)
   8964 {
   8965     uint8 *repl_group_buf = NULL;
   8966     uint8 *repl_group_buf2 = NULL;
   8967     int index_min, index_max;
   8968     int rv = BCM_E_NONE;
   8969     int intf_vec_alloc_size;
   8970     SHR_BITDCL *intf_vec = NULL;
   8971     int i, j;
   8972     uint32 *repl_group_entry;
   8973     int head_index;
   8974     uint32 fldbuf[SOC_PBMP_WORD_MAX];
   8975     int member_count;
   8976     soc_info_t *si;
   8977     int member_id, member;
   8978     bcm_port_t mmu_port, phy_port, port = -1;
   8979     mmu_repl_head_tbl_entry_t repl_head_entry;
   8980     int start_ptr;
   8981     _bcm_repl_list_info_t *rli_current;
   8982     int prev_repl_entry_ptr, repl_entry_ptr;
   8983     mmu_repl_list_tbl_entry_t repl_list_entry;
   8984     int msb;
   8985     uint32 ls_bits[2];
   8986     uint8 flags;
   8987     soc_pbmp_t member_bitmap;
   8988     soc_mem_t repl_group_table;
   8989     soc_field_t base_idx_f;
   8990     soc_field_t member_bitmap_f;
   8991 #ifdef BCM_TRIDENT2_SUPPORT
   8992     soc_mem_t repl_group_table2 = MMU_REPL_GROUP_INFO1m;
   8993     int member_bitmap2_offset = 0;
   8994 #endif
   8995 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   8996     int pipe = -1, aggid = -1, intf_cnt = 0;
   8997 #endif
   8998 
   8999 
   9000     /* Initialize internal data structures */
   9001     BCM_IF_ERROR_RETURN(bcm_tr3_ipmc_repl_init(unit));
   9002 
   9003     /* Recover internal state by traversing replication lists */
   9004 #ifdef BCM_APACHE_SUPPORT
   9005     if (SOC_IS_APACHE(unit)) {
   9006         repl_group_table = MMU_REPL_GROUP_INFO0m;
   9007         base_idx_f = PIPE_BASE_PTRf;
   9008         member_bitmap_f = PIPE_MEMBER_BMPf;
   9009 
   9010     } else
   9011 #endif /* BCM_APACHE_SUPPORT */
   9012 #ifdef BCM_TRIDENT2_SUPPORT
   9013     if (soc_feature(unit, soc_feature_split_repl_group_table)) {
   9014         repl_group_table = MMU_REPL_GROUP_INFO0m;
   9015         repl_group_table2 = MMU_REPL_GROUP_INFO1m;
   9016         base_idx_f = PIPE_BASE_PTRf;
   9017         member_bitmap_f = PIPE_MEMBER_BMPf;
   9018         member_bitmap2_offset = soc_mem_field_length(unit,
   9019                 repl_group_table, member_bitmap_f);
   9020     } else
   9021 #endif /* BCM_TRIDENT2_SUPPORT */
   9022     {
   9023         repl_group_table = MMU_REPL_GROUPm;
   9024         base_idx_f = HEAD_INDEXf;
   9025         member_bitmap_f = MEMBER_BITMAPf;
   9026     }
   9027 
   9028     /* Read replication group table */
   9029     repl_group_buf = soc_cm_salloc(unit,
   9030             SOC_MEM_TABLE_BYTES(unit, repl_group_table), "repl group buf");
   9031     if (NULL == repl_group_buf) {
   9032         rv = BCM_E_MEMORY;
   9033         goto cleanup;
   9034     }
   9035     index_min = soc_mem_index_min(unit, repl_group_table);
   9036     index_max = soc_mem_index_max(unit, repl_group_table);
   9037     rv = soc_mem_read_range(unit, repl_group_table, MEM_BLOCK_ANY,
   9038             index_min, index_max, repl_group_buf);
   9039     if (SOC_FAILURE(rv)) {
   9040         goto cleanup;
   9041     }
   9042 
   9043 
   9044 #ifdef BCM_TRIDENT2_SUPPORT
   9045     /* Read replication group table of Y-pipe */
   9046     else if (soc_feature(unit, soc_feature_split_repl_group_table)) {
   9047         repl_group_buf2 = soc_cm_salloc(unit,
   9048                 SOC_MEM_TABLE_BYTES(unit, repl_group_table2), "repl group buf2");
   9049         if (NULL == repl_group_buf2) {
   9050             rv = BCM_E_MEMORY;
   9051             goto cleanup;
   9052         }
   9053         index_min = soc_mem_index_min(unit, repl_group_table2);
   9054         index_max = soc_mem_index_max(unit, repl_group_table2);
   9055         rv = soc_mem_read_range(unit, repl_group_table2, MEM_BLOCK_ANY,
   9056                 index_min, index_max, repl_group_buf2);
   9057         if (SOC_FAILURE(rv)) {
   9058             goto cleanup;
   9059         }
   9060     }
   9061 #endif /* BCM_TRIDENT2_SUPPORT */
   9062 
   9063     intf_vec_alloc_size = SHR_BITALLOCSIZE(REPL_INTF_TOTAL(unit));
   9064     intf_vec = sal_alloc(intf_vec_alloc_size, "Repl interface vector");
   9065     if (intf_vec == NULL) {
   9066         rv = BCM_E_MEMORY;
   9067         goto cleanup;
   9068     }
   9069     sal_memset(intf_vec, 0, intf_vec_alloc_size);
   9070 
   9071     for (i = index_min; i <= index_max; i++) {
   9072         repl_group_entry = soc_mem_table_idx_to_pointer(unit,
   9073                 repl_group_table, uint32 *, repl_group_buf, i);
   9074 
   9075         /* Get the head index */
   9076         head_index = soc_mem_field32_get(unit, repl_group_table,
   9077                     repl_group_entry, base_idx_f);
   9078         if (0 == head_index &&
   9079                 !soc_feature(unit, soc_feature_static_repl_head_alloc)) {
   9080             continue; /* with next replication group */
   9081         }
   9082 
   9083         /* Get the member bitmap */
   9084         sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   9085         soc_mem_field_get(unit, repl_group_table, repl_group_entry,
   9086                     member_bitmap_f, fldbuf);
   9087         for (j = 0; j < SOC_PBMP_WORD_MAX; j++) {
   9088             SOC_PBMP_WORD_SET(member_bitmap, j, fldbuf[j]);
   9089         }
   9090 #ifdef BCM_TRIDENT2_SUPPORT
   9091         /* Get the member bitmap of Y-pipe */
   9092         if (soc_feature(unit, soc_feature_split_repl_group_table)) {
   9093             uint32 *repl_group_entry2;
   9094             soc_pbmp_t member_bitmap2;
   9095 
   9096             if (NULL != repl_group_buf2) {
   9097                 repl_group_entry2 = soc_mem_table_idx_to_pointer(unit,
   9098                         repl_group_table2, uint32 *, repl_group_buf2, i);
   9099                 soc_mem_field_get(unit, repl_group_table2, repl_group_entry2,
   9100                         member_bitmap_f, fldbuf);
   9101                 for (j = 0; j < SOC_PBMP_WORD_MAX; j++) {
   9102                     SOC_PBMP_WORD_SET(member_bitmap2, j, fldbuf[j]);
   9103                 }
   9104                 SOC_PBMP_ITER(member_bitmap2, member) {
   9105                     SOC_PBMP_PORT_ADD(member_bitmap,
   9106                             (member + member_bitmap2_offset));
   9107                 }
   9108             }
   9109         }
   9110 #endif /* BCM_TRIDENT2_SUPPORT */
   9111         SOC_PBMP_COUNT(member_bitmap, member_count);
   9112         if (0 == member_count) {
   9113             continue; /* with next replication group */
   9114         }
   9115 
   9116         member_id = 0;
   9117         SOC_PBMP_ITER(member_bitmap, member) {
   9118             /* Convert member to mmu port, then to physical port, and
   9119              * finally to logical port */
   9120 #ifdef BCM_TRIDENT2_SUPPORT
   9121             if (soc_feature(unit, soc_feature_split_repl_group_table)) {
   9122                 if (member_bitmap2_offset > 0 && member >= member_bitmap2_offset) {
   9123                     mmu_port = member - member_bitmap2_offset + 64;
   9124                 } else {
   9125                     mmu_port = member;
   9126                 }
   9127             } else
   9128 #endif /* BCM_TRIDENT2_SUPPORT */
   9129             {
   9130                 /* In Triumph3, mmu port 60 is mapped to member 59 */
   9131                 if (59 == member && SOC_IS_TRIUMPH3(unit)) {
   9132                     mmu_port = 60;
   9133                 } else {
   9134                     mmu_port = member;
   9135                 }
   9136             }
   9137             /* Add code to check MMU port is less than SOC_MAX_NUM_PORTS,
   9138              * in order to prevent false Coverity warning that the
   9139              * si->port_m2p_mapping array may be overrun.
   9140              */
   9141             if (mmu_port >= SOC_MAX_NUM_PORTS) {
   9142                 rv = BCM_E_INTERNAL;
   9143                 goto cleanup;
   9144             }
   9145 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   9146             if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) {
   9147                 if (mmu_port >= 64) {
   9148                     aggid = mmu_port - 64;
   9149                     pipe = 1;
   9150                 } else {
   9151                     aggid = mmu_port;
   9152                     pipe = 0;
   9153                 }
   9154             } else
   9155 #endif
   9156             {
   9157                 si = &SOC_INFO(unit);
   9158                 phy_port = si->port_m2p_mapping[mmu_port];
   9159                 port = si->port_p2l_mapping[phy_port];
   9160            }
   9161 
   9162             /* Get replication list start pointer */
   9163             rv = READ_MMU_REPL_HEAD_TBLm(unit, MEM_BLOCK_ANY,
   9164                     head_index + member_id, &repl_head_entry);
   9165             if (SOC_FAILURE(rv)) {
   9166                 goto cleanup;
   9167             }
   9168             member_id++;
   9169             start_ptr = soc_MMU_REPL_HEAD_TBLm_field32_get(unit,
   9170                     &repl_head_entry, HEAD_PTRf);
   9171             if (0 == start_ptr) {
   9172                 continue; /* with next member */
   9173             }
   9174 
   9175             if (_bcm_tr3_repl_list_entry_used_get(unit, start_ptr)) {
   9176                 /* Already traversed this replication list */
   9177                 for (rli_current = REPL_LIST_INFO(unit); rli_current != NULL;
   9178                         rli_current = rli_current->next) {
   9179                     if (rli_current->index == start_ptr) {
   9180                         (rli_current->refcount)++;
   9181 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   9182                         if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) {
   9183                             intf_cnt = rli_current->list_size;
   9184                             bcm_td2p_set_port_intf_cnt(unit, pipe, aggid,
   9185                                                        i, intf_cnt);
   9186                         } else
   9187 #endif
   9188                         {
   9189                             REPL_PORT_GROUP_INTF_COUNT(unit, port, i) =
   9190                                 rli_current->list_size;
   9191                         }
   9192                         break;
   9193                     }
   9194                 }
   9195                 if (rli_current == NULL) {
   9196                     /* Unexpected */
   9197                     rv = BCM_E_INTERNAL;
   9198                     goto cleanup;
   9199                 } else {
   9200                     continue; /* with next member */
   9201                 }
   9202             }
   9203 
   9204             /* Traverse the replication list table */
   9205             sal_memset(intf_vec, 0, intf_vec_alloc_size);
   9206             prev_repl_entry_ptr = -1;
   9207             repl_entry_ptr = start_ptr;
   9208 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   9209             if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) {
   9210                 intf_cnt = 0;
   9211             }
   9212 #endif
   9213             while (repl_entry_ptr != prev_repl_entry_ptr) {
   9214                 rv = READ_MMU_REPL_LIST_TBLm(unit, MEM_BLOCK_ANY,
   9215                         repl_entry_ptr, &repl_list_entry);
   9216                 if (BCM_FAILURE(rv)) {
   9217                     goto cleanup;
   9218                 }
   9219                 msb = soc_MMU_REPL_LIST_TBLm_field32_get(unit,
   9220                         &repl_list_entry, MSB_VLANf);
   9221                 soc_MMU_REPL_LIST_TBLm_field_get(unit, &repl_list_entry,
   9222                         LSB_VLAN_BMf, ls_bits);
   9223                 intf_vec[2 * msb + 0] = ls_bits[0];
   9224                 intf_vec[2 * msb + 1] = ls_bits[1];
   9225 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   9226                 if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) {
   9227                     intf_cnt += (_shr_popcount(ls_bits[0]) +
   9228                                  _shr_popcount(ls_bits[1]));
   9229                 } else
   9230 #endif
   9231                 {
   9232                     REPL_PORT_GROUP_INTF_COUNT(unit, port, i) +=
   9233                         _shr_popcount(ls_bits[0]) + _shr_popcount(ls_bits[1]);
   9234                 }
   9235                 rv = _bcm_tr3_repl_list_entry_used_set(unit, repl_entry_ptr);
   9236                 if (BCM_FAILURE(rv)) {
   9237                     goto cleanup;
   9238                 }
   9239                 prev_repl_entry_ptr = repl_entry_ptr;
   9240                 repl_entry_ptr = soc_MMU_REPL_LIST_TBLm_field32_get(unit,
   9241                         &repl_list_entry, NEXTPTRf);
   9242             }
   9243 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   9244             if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) {
   9245                 bcm_td2p_add_port_intf_cnt(unit, pipe, aggid, i, intf_cnt);
   9246             }
   9247 #endif
   9248 
   9249             /* Insert a new replication list into linked list */
   9250             rli_current = sal_alloc(sizeof(_bcm_repl_list_info_t),
   9251                     "repl list info");
   9252             if (rli_current == NULL) {
   9253                 rv = BCM_E_MEMORY;
   9254                 goto cleanup;
   9255             }
   9256             sal_memset(rli_current, 0, sizeof(_bcm_repl_list_info_t));
   9257             rli_current->index = start_ptr;
   9258 #ifdef BCM_TRIDENT2PLUS_SUPPORT
   9259             if (BCM_MC_PER_TRUNK_REPL_MODE(unit)) {
   9260                 if ((_shr_popcount(*(uint32 *)intf_vec) == intf_cnt) &&
   9261                     (REPL_INTF_TOTAL(unit) >= SHR_BITWID)) {
   9262                     rli_current->hash = _shr_crc32b(0, (uint8 *)intf_vec, SHR_BITWID);
   9263                 } else {
   9264                     rli_current->hash = _shr_crc32b(0, (uint8 *)intf_vec,
   9265                         REPL_INTF_TOTAL(unit));
   9266                 }
   9267                 rli_current->list_size = intf_cnt;
   9268             } else
   9269 #endif
   9270             {
   9271                 if ((_shr_popcount(*(uint32 *)intf_vec) ==
   9272                          REPL_PORT_GROUP_INTF_COUNT(unit, port, i)) &&
   9273                     (REPL_INTF_TOTAL(unit) >= SHR_BITWID)) {
   9274                     rli_current->hash = _shr_crc32b(0, (uint8 *)intf_vec, SHR_BITWID);
   9275                 } else {
   9276                     rli_current->hash = _shr_crc32b(0, (uint8 *)intf_vec,
   9277                         REPL_INTF_TOTAL(unit));
   9278                 }
   9279                 rli_current->list_size = REPL_PORT_GROUP_INTF_COUNT(unit, port, i);
   9280             }
   9281             (rli_current->refcount)++;
   9282             rli_current->next = REPL_LIST_INFO(unit);
   9283             REPL_LIST_INFO(unit) = rli_current;
   9284         }
   9285 
   9286         /* Update REPL_HEAD table usage */
   9287         if (!soc_feature(unit, soc_feature_static_repl_head_alloc)) {
   9288             rv = _bcm_tr3_repl_head_block_used_set(unit, head_index, member_count);
   9289             if (BCM_FAILURE(rv)) {
   9290                 goto cleanup;
   9291             }
   9292         }
   9293     }
   9294     soc_cm_sfree(unit, repl_group_buf);
   9295     repl_group_buf = NULL;
   9296     if (repl_group_buf2) {
   9297         soc_cm_sfree(unit, repl_group_buf2);
   9298         repl_group_buf2 = NULL;
   9299     }
   9300     sal_free(intf_vec);
   9301     intf_vec = NULL;
   9302 
   9303     /* Recover REPL list mode from HW cache */
   9304     rv = _bcm_esw_ipmc_repl_wb_flags_get(unit,
   9305                                          _BCM_IPMC_WB_REPL_LIST, &flags);
   9306     if (flags) {
   9307         SOC_IPMCREPLSHR_SET(unit, 1);
   9308     }
   9309 
   9310 cleanup:
   9311     if (repl_group_buf) {
   9312         soc_cm_sfree(unit, repl_group_buf);
   9313     }
   9314     if (repl_group_buf2) {
   9315         soc_cm_sfree(unit, repl_group_buf2);
   9316     }
   9317     if (intf_vec) {
   9318         sal_free(intf_vec);
   9319     }
   9320 
   9321     if (BCM_FAILURE(rv)) {
   9322         bcm_tr3_ipmc_repl_detach(unit);
   9323     }
   9324 
   9325     return rv;
   9326 }
   9327 #ifdef BCM_SABER2_SUPPORT
   9328 /*
   9329  * Function:
   9330  *      _bcm_sb2_ipmc_repl_reload
   9331  * Purpose:
   9332  *      Re-Initialize replication software to state consistent with
   9333  *      hardware.
   9334  * Parameters:
   9335  *      unit - SOC unit #
   9336  * Returns:
   9337  *      BCM_E_XXX
   9338  */
   9339 int
   9340 _bcm_sb2_ipmc_repl_reload(int unit)
   9341 {
   9342     uint8 *repl_group_buf0 = NULL;
   9343     uint8 *repl_group_base_ptr_buf = NULL;
   9344     int index_min, index_max;
   9345     int rv = BCM_E_NONE;
   9346     int intf_vec_alloc_size;
   9347     SHR_BITDCL *intf_vec = NULL;
   9348     int i, j;
   9349     uint32 *repl_group_entry0;
   9350     uint32 *repl_group_base_ptr_entry;
   9351     int head_index;
   9352     uint32 fldbuf[SOC_PBMP_WORD_MAX];
   9353     int member_count;
   9354     int member_id, member;
   9355     bcm_port_t mmu_port, phy_port, port;
   9356     mmu_repl_head_tbl_entry_t repl_head_entry;
   9357     int start_ptr;
   9358     _bcm_repl_list_info_t *rli_current;
   9359     int prev_repl_entry_ptr, repl_entry_ptr;
   9360     mmu_repl_list_tbl_entry_t repl_list_entry;
   9361     int msb;
   9362     uint32 ls_bits[2];
   9363     uint8 flags;
   9364     soc_pbmp_t member_bitmap;
   9365     soc_mem_t repl_group_table0 = INVALIDm;
   9366     soc_mem_t repl_group_base_ptr_table = INVALIDm;
   9367     soc_field_t base_idx_f;
   9368     uint32 nh_offset , is_len, offset;
   9369     soc_field_t mbmp;
   9370     int intf_base;
   9371 
   9372     /* Initialize internal data structures */
   9373     BCM_IF_ERROR_RETURN(bcm_tr3_ipmc_repl_init(unit));
   9374 
   9375     is_len = soc_mem_field_length(unit, MMU_REPL_LIST_TBLm, LSB_VLAN_BMf);
   9376     /* coverity[large_shift : FALSE] */
   9377     nh_offset = (1 << (soc_mem_field_length(unit, MMU_REPL_LIST_TBLm,
   9378                                                 MSB_VLANf) - 1)) * is_len;
   9379     /* Recover internal state by traversing replication lists */
   9380 #if defined(BCM_METROLITE_SUPPORT)
   9381     if (SOC_IS_METROLITE(unit)) {
   9382         repl_group_table0 = MMU_REPL_GRP_TBLm;
   9383         repl_group_base_ptr_table = MMU_REPL_GRP_TBLm;
   9384     } else
   9385 #endif
   9386     {
   9387         repl_group_table0 = MMU_REPL_GRP_TBL0m;
   9388         repl_group_base_ptr_table = MMU_REPL_GRP_TBL1m;
   9389     }
   9390 
   9391     base_idx_f = BASE_PTRf;
   9392     mbmp = MEMBER_BMP_PORTSf;
   9393 
   9394     /* Read replication group table MMU_REPL_GRP_TBL0 */
   9395     repl_group_buf0 = soc_cm_salloc(unit,
   9396             SOC_MEM_TABLE_BYTES(unit, repl_group_table0), "repl group buf");
   9397 
   9398     if (NULL == repl_group_buf0) {
   9399         rv = BCM_E_MEMORY;
   9400         goto cleanup;
   9401     }
   9402 
   9403 
   9404     repl_group_base_ptr_buf = soc_cm_salloc(unit,
   9405           SOC_MEM_TABLE_BYTES(unit, repl_group_base_ptr_table), 
   9406                               "repl group base ptr buf");
   9407 
   9408     if (NULL == repl_group_base_ptr_buf) {
   9409         rv = BCM_E_MEMORY;
   9410         goto cleanup;
   9411     }
   9412 
   9413     index_min = soc_mem_index_min(unit, repl_group_table0);
   9414     index_max = soc_mem_index_max(unit, repl_group_table0);
   9415     rv = soc_mem_read_range(unit, repl_group_table0, MEM_BLOCK_ANY,
   9416             index_min, index_max, repl_group_buf0);
   9417     if (SOC_FAILURE(rv)) {
   9418         goto cleanup;
   9419     }
   9420 
   9421 
   9422     index_min = soc_mem_index_min(unit, repl_group_base_ptr_table);
   9423     index_max = soc_mem_index_max(unit, repl_group_base_ptr_table);
   9424     rv = soc_mem_read_range(unit, repl_group_base_ptr_table, MEM_BLOCK_ANY,
   9425                 index_min, index_max, repl_group_base_ptr_buf); 
   9426     if (SOC_FAILURE(rv)) {
   9427         goto cleanup;
   9428     }
   9429 
   9430     intf_vec_alloc_size = SHR_BITALLOCSIZE(REPL_INTF_TOTAL(unit));
   9431     intf_vec = sal_alloc(intf_vec_alloc_size * sizeof(SHR_BITDCL),
   9432                          "Repl interface vector");
   9433     if (intf_vec == NULL) {
   9434         rv = BCM_E_MEMORY;
   9435         goto cleanup;
   9436     }
   9437     sal_memset(intf_vec, 0, intf_vec_alloc_size);
   9438 
   9439     for (i = index_min; i <= index_max; i++) {
   9440         repl_group_entry0 = soc_mem_table_idx_to_pointer(unit,
   9441                 repl_group_table0, uint32 *, repl_group_buf0, i);
   9442 
   9443         /* Get the head index */
   9444         repl_group_base_ptr_entry = soc_mem_table_idx_to_pointer(unit,
   9445                     repl_group_base_ptr_table, uint32 *,
   9446                     repl_group_base_ptr_buf, i);
   9447 
   9448         head_index = soc_mem_field32_get(unit, repl_group_base_ptr_table,
   9449                     repl_group_base_ptr_entry, base_idx_f);
   9450 
   9451         /* Get the member bitmap */
   9452         sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   9453         soc_mem_field_get(unit, repl_group_table0, repl_group_entry0,
   9454                     mbmp, fldbuf);
   9455          
   9456 
   9457         for (j = 0; j < SOC_PBMP_WORD_MAX; j++) {
   9458             SOC_PBMP_WORD_SET(member_bitmap, j, fldbuf[j]);
   9459         }
   9460 
   9461         SOC_PBMP_COUNT(member_bitmap, member_count);
   9462 
   9463         if (0 == member_count) {
   9464             continue; /* with next replication group */
   9465         }
   9466 
   9467         member_id = 0;
   9468         SOC_PBMP_ITER(member_bitmap, member) {
   9469             /* Convert member to mmu port, then to physical port, and
   9470              * finally to logical port */
   9471 
   9472             mmu_port = member;
   9473             phy_port = mmu_port;
   9474             port = phy_port;
   9475 
   9476             /* Get replication list start pointer */
   9477             rv = READ_MMU_REPL_HEAD_TBLm(unit, MEM_BLOCK_ANY,
   9478                     head_index + member_id, &repl_head_entry);
   9479             if (SOC_FAILURE(rv)) {
   9480                 goto cleanup;
   9481             }
   9482             member_id++;
   9483 
   9484             start_ptr = soc_MMU_REPL_HEAD_TBLm_field32_get(unit,
   9485                     &repl_head_entry, HEAD_PTRf);
   9486             if (0 == start_ptr) {
   9487                 continue; /* with next member */
   9488             }
   9489 
   9490             if (_bcm_tr3_repl_list_entry_used_get(unit, start_ptr)) {
   9491                 /* Already traversed this replication list */
   9492                 for (rli_current = REPL_LIST_INFO(unit); rli_current != NULL;
   9493                         rli_current = rli_current->next) {
   9494                     if (rli_current->index == start_ptr) {
   9495                         (rli_current->refcount)++;
   9496                         REPL_PORT_GROUP_INTF_COUNT(unit, port, i) =
   9497                             rli_current->list_size;
   9498                         break;
   9499                     }
   9500                 }
   9501                 if (rli_current == NULL) {
   9502                     /* Unexpected */
   9503                     rv = BCM_E_INTERNAL;
   9504                     goto cleanup;
   9505                 } else {
   9506                     continue; /* with next member */
   9507                 }
   9508             }
   9509 
   9510             /* Traverse the replication list table */
   9511             sal_memset(intf_vec, 0, intf_vec_alloc_size);
   9512             prev_repl_entry_ptr = -1;
   9513             repl_entry_ptr = start_ptr;
   9514             while (repl_entry_ptr != prev_repl_entry_ptr) {
   9515                 rv = READ_MMU_REPL_LIST_TBLm(unit, MEM_BLOCK_ANY,
   9516                         repl_entry_ptr, &repl_list_entry);
   9517                 if (BCM_FAILURE(rv)) {
   9518                     goto cleanup;
   9519                 }
   9520        
   9521                 msb = soc_MMU_REPL_LIST_TBLm_field32_get(unit,
   9522                         &repl_list_entry, MSB_VLANf);
   9523                 soc_MMU_REPL_LIST_TBLm_field_get(unit, &repl_list_entry,
   9524                         LSB_VLAN_BMf, ls_bits);
   9525 
   9526                 intf_base = msb *64;
   9527 
   9528                 if (intf_base >= nh_offset)
   9529                 {
   9530                     /* replication on next hops  */
   9531                     offset = _SHR_BITDCLSIZE(soc_mem_index_count(unit, 
   9532                                              EGR_L3_INTFm)); 
   9533                 } else {
   9534                     /* replication on L3 interface */
   9535                     offset = 0;
   9536                 }
   9537                 intf_vec[offset + 2 * msb + 0] = ls_bits[0];
   9538                 intf_vec[offset + 2 * msb + 1] = ls_bits[1];
   9539 
   9540                 REPL_PORT_GROUP_INTF_COUNT(unit, port, i) +=
   9541                     _shr_popcount(ls_bits[0]) + _shr_popcount(ls_bits[1]);
   9542                 rv = _bcm_tr3_repl_list_entry_used_set(unit, repl_entry_ptr);
   9543                 if (BCM_FAILURE(rv)) {
   9544                     goto cleanup;
   9545                 }
   9546                 prev_repl_entry_ptr = repl_entry_ptr;
   9547                 repl_entry_ptr = soc_MMU_REPL_LIST_TBLm_field32_get(unit,
   9548                         &repl_list_entry, NEXTPTRf);
   9549             }
   9550 
   9551             /* Insert a new replication list into linked list */
   9552             rli_current = sal_alloc(sizeof(_bcm_repl_list_info_t),
   9553                     "repl list info");
   9554             if (rli_current == NULL) {
   9555                 rv = BCM_E_MEMORY;
   9556                 goto cleanup;
   9557             }
   9558             sal_memset(rli_current, 0, sizeof(_bcm_repl_list_info_t));
   9559             rli_current->index = start_ptr;
   9560             rli_current->hash = _shr_crc32b(0, (uint8 *)intf_vec,
   9561                     REPL_INTF_TOTAL(unit));
   9562             rli_current->list_size = REPL_PORT_GROUP_INTF_COUNT(unit, port, i);
   9563             (rli_current->refcount)++;
   9564             rli_current->next = REPL_LIST_INFO(unit);
   9565             REPL_LIST_INFO(unit) = rli_current;
   9566         }
   9567     }
   9568     
   9569 
   9570     if (SOC_IS_SABER2(unit)) 
   9571     { 
   9572         for (i = soc_mem_index_min(unit, L3_IPMCm);
   9573              i <= soc_mem_index_max(unit, L3_IPMCm); i++) {
   9574              if (i > 1) {
   9575                  rv = _bcm_sb2_extq_repl_reload(unit, i); 
   9576                  if (rv < 0) 
   9577                  {
   9578                      goto cleanup; 
   9579                  }
   9580              }
   9581        }
   9582    } 
   9583 
   9584     soc_cm_sfree(unit, repl_group_buf0);
   9585     repl_group_buf0 = NULL;
   9586     
   9587     soc_cm_sfree(unit, repl_group_base_ptr_buf);
   9588     repl_group_base_ptr_buf = NULL;
   9589     
   9590     sal_free(intf_vec);
   9591     intf_vec = NULL;
   9592 
   9593     /* Recover REPL list mode from HW cache */
   9594     rv = _bcm_esw_ipmc_repl_wb_flags_get(unit,
   9595                                          _BCM_IPMC_WB_REPL_LIST, &flags);
   9596     if (flags) {
   9597         SOC_IPMCREPLSHR_SET(unit, 1);
   9598     }
   9599 
   9600 cleanup:
   9601     if (repl_group_buf0) {
   9602         soc_cm_sfree(unit, repl_group_buf0);
   9603     }
   9604     if (repl_group_base_ptr_buf) {
   9605         soc_cm_sfree(unit, repl_group_base_ptr_buf);
   9606     }
   9607     if (intf_vec) {
   9608         sal_free(intf_vec);
   9609     }
   9610     if (BCM_FAILURE(rv)) {
   9611         bcm_tr3_ipmc_repl_detach(unit);
   9612     }
   9613 
   9614     return rv;
   9615 }
   9616 #endif /* BCM_SABER2_SUPPORT*/
   9617 
   9618 
   9619 #ifdef BCM_KATANA2_SUPPORT
   9620 /*
   9621  * Function:
   9622  *      _bcm_kt2_ipmc_repl_reload
   9623  * Purpose:
   9624  *      Re-Initialize replication software to state consistent with
   9625  *      hardware.
   9626  * Parameters:
   9627  *      unit - SOC unit #
   9628  * Returns:
   9629  *      BCM_E_XXX
   9630  */
   9631 int
   9632 _bcm_kt2_ipmc_repl_reload(int unit)
   9633 {
   9634     uint8 *repl_group_buf0 = NULL;
   9635     uint8 *repl_group_buf1 = NULL;
   9636     uint8 *repl_group_base_ptr_buf = NULL;
   9637     int index_min, index_max;
   9638     int rv = BCM_E_NONE;
   9639     int intf_vec_alloc_size;
   9640     SHR_BITDCL *intf_vec = NULL;
   9641     int i, j;
   9642     uint32 *repl_group_entry0;
   9643     uint32 *repl_group_entry1;
   9644     uint32 *repl_group_base_ptr_entry;
   9645     int head_index;
   9646     uint32 fldbuf[SOC_PBMP_WORD_MAX];
   9647     int member_count;
   9648     int member_id, member;
   9649     bcm_port_t mmu_port, phy_port, port;
   9650     mmu_repl_head_tbl_entry_t repl_head_entry;
   9651     int start_ptr;
   9652     _bcm_repl_list_info_t *rli_current;
   9653     int prev_repl_entry_ptr, repl_entry_ptr;
   9654     mmu_repl_list_tbl_entry_t repl_list_entry;
   9655     int msb;
   9656     uint32 ls_bits[2];
   9657     uint8 flags;
   9658     soc_pbmp_t member_bitmap;
   9659     soc_pbmp_t member_bitmap0;
   9660     soc_pbmp_t member_bitmap1;
   9661     soc_mem_t repl_group_table0;
   9662     soc_mem_t repl_group_table1;
   9663     soc_mem_t repl_group_base_ptr_table = INVALIDm;
   9664     soc_field_t base_idx_f;
   9665     uint32 nh_offset , is_len, offset;
   9666     soc_field_t mbmp0, mbmp1;
   9667     int intf_base;
   9668     int member_bitmap_width0;
   9669 
   9670     /* Initialize internal data structures */
   9671     BCM_IF_ERROR_RETURN(bcm_tr3_ipmc_repl_init(unit));
   9672  
   9673     is_len = soc_mem_field_length(unit, MMU_REPL_LIST_TBLm, LSB_VLAN_BMf);
   9674     /* coverity[large_shift : FALSE] */
   9675     nh_offset = (1 << (soc_mem_field_length(unit, MMU_REPL_LIST_TBLm,
   9676                                                 MSB_VLANf) - 1)) * is_len;
   9677     member_bitmap_width0 =  soc_mem_field_length(unit,
   9678                 MMU_REPL_GRP_TBL0m, MEMBER_BMP_PORTS_119_0f);
   9679     /* Recover internal state by traversing replication lists */
   9680     repl_group_table0 = MMU_REPL_GRP_TBL0m;
   9681     repl_group_table1 = MMU_REPL_GRP_TBL1m;
   9682     repl_group_base_ptr_table = MMU_REPL_GRP_TBL2m;
   9683     base_idx_f = BASE_PTRf;
   9684     mbmp0 = MEMBER_BMP_PORTS_119_0f;
   9685     mbmp1 = MEMBER_BMP_PORTS_169_120f;
   9686 
   9687     /* Read replication group table MMU_REPL_GRP_TBL0 */
   9688     repl_group_buf0 = soc_cm_salloc(unit,
   9689             SOC_MEM_TABLE_BYTES(unit, repl_group_table0), "repl group buf");
   9690 
   9691     if (NULL == repl_group_buf0) {
   9692         rv = BCM_E_MEMORY;
   9693         goto cleanup;
   9694     }
   9695 
   9696     /* Read replication group table MMU_REPL_GRP_TBL1 */
   9697     repl_group_buf1 = soc_cm_salloc(unit,
   9698             SOC_MEM_TABLE_BYTES(unit, repl_group_table1), "repl group buf");
   9699 
   9700     if (NULL == repl_group_buf1) {
   9701         rv = BCM_E_MEMORY;
   9702         goto cleanup;
   9703     }
   9704 
   9705     repl_group_base_ptr_buf = soc_cm_salloc(unit,
   9706           SOC_MEM_TABLE_BYTES(unit, repl_group_base_ptr_table), 
   9707                               "repl group base ptr buf");
   9708 
   9709     if (NULL == repl_group_base_ptr_buf) {
   9710         rv = BCM_E_MEMORY;
   9711         goto cleanup;
   9712     }
   9713 
   9714     index_min = soc_mem_index_min(unit, repl_group_table0);
   9715     index_max = soc_mem_index_max(unit, repl_group_table0);
   9716     rv = soc_mem_read_range(unit, repl_group_table0, MEM_BLOCK_ANY,
   9717             index_min, index_max, repl_group_buf0);
   9718     if (SOC_FAILURE(rv)) {
   9719         goto cleanup;
   9720     }
   9721 
   9722     index_min = soc_mem_index_min(unit, repl_group_table1);
   9723     index_max = soc_mem_index_max(unit, repl_group_table1);
   9724     rv = soc_mem_read_range(unit, repl_group_table1, MEM_BLOCK_ANY,
   9725             index_min, index_max, repl_group_buf1);
   9726     if (SOC_FAILURE(rv)) {
   9727         goto cleanup;
   9728     }
   9729 
   9730 
   9731     index_min = soc_mem_index_min(unit, repl_group_base_ptr_table);
   9732     index_max = soc_mem_index_max(unit, repl_group_base_ptr_table);
   9733     rv = soc_mem_read_range(unit, repl_group_base_ptr_table, MEM_BLOCK_ANY,
   9734                 index_min, index_max, repl_group_base_ptr_buf); 
   9735     if (SOC_FAILURE(rv)) {
   9736         goto cleanup;
   9737     }
   9738 
   9739     intf_vec_alloc_size = SHR_BITALLOCSIZE(REPL_INTF_TOTAL(unit));
   9740     intf_vec = sal_alloc(intf_vec_alloc_size * sizeof(SHR_BITDCL),
   9741                          "Repl interface vector");
   9742     if (intf_vec == NULL) {
   9743         rv = BCM_E_MEMORY;
   9744         goto cleanup;
   9745     }
   9746     sal_memset(intf_vec, 0, intf_vec_alloc_size);
   9747 
   9748     for (i = index_min; i <= index_max; i++) {
   9749         repl_group_entry0 = soc_mem_table_idx_to_pointer(unit,
   9750                 repl_group_table0, uint32 *, repl_group_buf0, i);
   9751 
   9752         repl_group_entry1 = soc_mem_table_idx_to_pointer(unit,
   9753                 repl_group_table1, uint32 *, repl_group_buf1, i);
   9754  
   9755         /* Get the head index */
   9756         repl_group_base_ptr_entry = soc_mem_table_idx_to_pointer(unit,
   9757                     repl_group_base_ptr_table, uint32 *,
   9758                     repl_group_base_ptr_buf, i);
   9759 
   9760         head_index = soc_mem_field32_get(unit, repl_group_base_ptr_table,
   9761                     repl_group_base_ptr_entry, base_idx_f);
   9762 
   9763         /* Get the member bitmap */
   9764         sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   9765         soc_mem_field_get(unit, repl_group_table0, repl_group_entry0,
   9766                     mbmp0, fldbuf);
   9767         for (j = 0; j < SOC_PBMP_WORD_MAX; j++) {
   9768             SOC_PBMP_WORD_SET(member_bitmap0, j, fldbuf[j]);
   9769         }
   9770          
   9771         sal_memset(fldbuf, 0, SOC_PBMP_WORD_MAX * sizeof(uint32));
   9772         soc_mem_field_get(unit, repl_group_table1, repl_group_entry1,
   9773                           mbmp1, fldbuf);
   9774         for (j = 0; j < SOC_PBMP_WORD_MAX; j++) {
   9775             SOC_PBMP_WORD_SET(member_bitmap1, j, fldbuf[j]);
   9776         }
   9777 
   9778         SOC_PBMP_CLEAR(member_bitmap);
   9779         SOC_PBMP_OR(member_bitmap, member_bitmap0);
   9780 
   9781         SOC_PBMP_ITER(member_bitmap1, member) {
   9782            SOC_PBMP_PORT_ADD(member_bitmap,
   9783                     (member + member_bitmap_width0));
   9784         }
   9785 
   9786         SOC_PBMP_COUNT(member_bitmap, member_count);
   9787 
   9788         if (0 == member_count) {
   9789             continue; /* with next replication group */
   9790         }
   9791 
   9792         member_id = 0;
   9793         SOC_PBMP_ITER(member_bitmap, member) {
   9794             /* Convert member to mmu port, then to physical port, and
   9795              * finally to logical port */
   9796 
   9797             mmu_port = member;
   9798             phy_port = mmu_port;
   9799             port = phy_port;
   9800 
   9801             /* Get replication list start pointer */
   9802             rv = READ_MMU_REPL_HEAD_TBLm(unit, MEM_BLOCK_ANY,
   9803                     head_index + member_id, &repl_head_entry);
   9804             if (SOC_FAILURE(rv)) {
   9805                 goto cleanup;
   9806             }
   9807             member_id++;
   9808 
   9809             start_ptr = soc_MMU_REPL_HEAD_TBLm_field32_get(unit,
   9810                     &repl_head_entry, HEAD_PTRf);
   9811             if (0 == start_ptr) {
   9812                 continue; /* with next member */
   9813             }
   9814 
   9815             if (_bcm_tr3_repl_list_entry_used_get(unit, start_ptr)) {
   9816                 /* Already traversed this replication list */
   9817                 for (rli_current = REPL_LIST_INFO(unit); rli_current != NULL;
   9818                         rli_current = rli_current->next) {
   9819                     if (rli_current->index == start_ptr) {
   9820                         (rli_current->refcount)++;
   9821                         REPL_PORT_GROUP_INTF_COUNT(unit, port, i) =
   9822                             rli_current->list_size;
   9823                         break;
   9824                     }
   9825                 }
   9826                 if (rli_current == NULL) {
   9827                     /* Unexpected */
   9828                     rv = BCM_E_INTERNAL;
   9829                     goto cleanup;
   9830                 } else {
   9831                     continue; /* with next member */
   9832                 }
   9833             }
   9834 
   9835             /* Traverse the replication list table */
   9836             sal_memset(intf_vec, 0, intf_vec_alloc_size);
   9837             prev_repl_entry_ptr = -1;
   9838             repl_entry_ptr = start_ptr;
   9839             while (repl_entry_ptr != prev_repl_entry_ptr) {
   9840                 rv = READ_MMU_REPL_LIST_TBLm(unit, MEM_BLOCK_ANY,
   9841                         repl_entry_ptr, &repl_list_entry);
   9842                 if (BCM_FAILURE(rv)) {
   9843                     goto cleanup;
   9844                 }
   9845        
   9846                 msb = soc_MMU_REPL_LIST_TBLm_field32_get(unit,
   9847                         &repl_list_entry, MSB_VLANf);
   9848                 soc_MMU_REPL_LIST_TBLm_field_get(unit, &repl_list_entry,
   9849                         LSB_VLAN_BMf, ls_bits);
   9850 
   9851                 intf_base = msb *64;
   9852 
   9853                 if (intf_base >= nh_offset)
   9854                 {
   9855                     /* replication on next hops  */
   9856                     offset = _SHR_BITDCLSIZE(soc_mem_index_count(unit, 
   9857                                              EGR_L3_INTFm)); 
   9858                 } else {
   9859                     /* replication on L3 interface */
   9860                     offset = 0;
   9861                 }
   9862                 intf_vec[offset + 2 * msb + 0] = ls_bits[0];
   9863                 intf_vec[offset + 2 * msb + 1] = ls_bits[1];
   9864 
   9865                 REPL_PORT_GROUP_INTF_COUNT(unit, port, i) +=
   9866                     _shr_popcount(ls_bits[0]) + _shr_popcount(ls_bits[1]);
   9867                 rv = _bcm_tr3_repl_list_entry_used_set(unit, repl_entry_ptr);
   9868                 if (BCM_FAILURE(rv)) {
   9869                     goto cleanup;
   9870                 }
   9871                 prev_repl_entry_ptr = repl_entry_ptr;
   9872                 repl_entry_ptr = soc_MMU_REPL_LIST_TBLm_field32_get(unit,
   9873                         &repl_list_entry, NEXTPTRf);
   9874             }
   9875 
   9876             /* Insert a new replication list into linked list */
   9877             rli_current = sal_alloc(sizeof(_bcm_repl_list_info_t),
   9878                     "repl list info");
   9879             if (rli_current == NULL) {
   9880                 rv = BCM_E_MEMORY;
   9881                 goto cleanup;
   9882             }
   9883             sal_memset(rli_current, 0, sizeof(_bcm_repl_list_info_t));
   9884             rli_current->index = start_ptr;
   9885             rli_current->hash = _shr_crc32b(0, (uint8 *)intf_vec,
   9886                     REPL_INTF_TOTAL(unit));
   9887             rli_current->list_size = REPL_PORT_GROUP_INTF_COUNT(unit, port, i);
   9888             (rli_current->refcount)++;
   9889             rli_current->next = REPL_LIST_INFO(unit);
   9890             REPL_LIST_INFO(unit) = rli_current;
   9891         }
   9892 
   9893     }
   9894     soc_cm_sfree(unit, repl_group_buf0);
   9895     repl_group_buf0 = NULL;
   9896     
   9897     soc_cm_sfree(unit, repl_group_buf1);
   9898     repl_group_buf1 = NULL;
   9899    
   9900    
   9901     soc_cm_sfree(unit, repl_group_base_ptr_buf);
   9902     repl_group_base_ptr_buf = NULL;
   9903     
   9904     sal_free(intf_vec);
   9905     intf_vec = NULL;
   9906 
   9907     /* Recover subscriber REPL from HW cache */
   9908     rv = _bcm_kt2_extq_repl_reload(unit);
   9909     if (BCM_FAILURE(rv)) {
   9910         goto cleanup;
   9911     }
   9912 
   9913     /* Recover REPL list mode from HW cache */
   9914     rv = _bcm_esw_ipmc_repl_wb_flags_get(unit,
   9915                                          _BCM_IPMC_WB_REPL_LIST, &flags);
   9916     if (flags) {
   9917         SOC_IPMCREPLSHR_SET(unit, 1);
   9918     }
   9919 
   9920 cleanup:
   9921     if (repl_group_buf0) {
   9922         soc_cm_sfree(unit, repl_group_buf0);
   9923     }
   9924     if (repl_group_buf1) {
   9925         soc_cm_sfree(unit, repl_group_buf1);
   9926     }
   9927     if (repl_group_base_ptr_buf) {
   9928         soc_cm_sfree(unit, repl_group_base_ptr_buf);
   9929     }
   9930     if (intf_vec) {
   9931         sal_free(intf_vec);
   9932     }
   9933     if (BCM_FAILURE(rv)) {
   9934         bcm_tr3_ipmc_repl_detach(unit);
   9935     }
   9936 
   9937     return rv;
   9938 }
   9939 #endif /* BCM_KATANA2_SUPPORT*/
   9940 
   9941 #endif /* BCM_WARM_BOOT_SUPPORT */
   9942 
   9943 #ifndef BCM_SW_STATE_DUMP_DISABLE
   9944 
   9945 #ifdef BCM_SABER2_SUPPORT 
   9946 
   9947 /*
   9948  * Function:
   9949  *     bcm_kt2_ipmc_subscriber_sw_dump
   9950  * Purpose:
   9951  *     Displays IPMC Subscriber replication information 
   9952  *     maintained by software.
   9953  * Parameters:
   9954  *     unit - Device unit number
   9955  * Returns:
   9956  *     None
   9957  */
   9958 void 
   9959 bcm_sb2_ipmc_subscriber_sw_dump(int unit)
   9960 {
   9961     int                   i, j;
   9962     uint32                *bitmap;
   9963     _bcm_repl_list_info_t *rli_start, *rli_current;
   9964     _sb2_repl_queue_info_t  *group_info;
   9965     _sb2_extq_repl_info_t   *extq_info;
   9966 
   9967 
   9968     /*
   9969      * _sb2_extq_repl_info
   9970      */
   9971 
   9972     LOG_CLI((BSL_META_U(unit,
   9973                         "  IPMC EXTQ REPL Info -\n")));
   9974     extq_info = _sb2_extq_repl_info[unit];
   9975     LOG_CLI((BSL_META_U(unit,
   9976                         "    IPMC Size    : %d\n"), extq_info->ipmc_size));
   9977     LOG_CLI((BSL_META_U(unit,
   9978                         "    Queue Num    : %d\n"), extq_info->queue_num));
   9979     LOG_CLI((BSL_META_U(unit,
   9980                         "    Extq total   : %d\n"), extq_info->extq_list_total));
   9981 
   9982     LOG_CLI((BSL_META_U(unit,
   9983                         "    Bitmap (index:value-hex) :")));
   9984     if (extq_info->bitmap_entries_used != NULL) {
   9985         bitmap =  extq_info->bitmap_entries_used;
   9986         for (i = 0, j = 0;
   9987              i < _SHR_BITDCLSIZE(extq_info->extq_list_total); i++) {
   9988             /* If zero, skip print */
   9989             if (bitmap[i] == 0) {
   9990                 continue;
   9991             }
   9992             if (!(j % 4)) {
   9993                 LOG_CLI((BSL_META_U(unit,
   9994                                     "\n    ")));
   9995             }
   9996             LOG_CLI((BSL_META_U(unit,
   9997                                 "  %5d:%8.8x"), i, bitmap[i]));
   9998             j++;
   9999         }
  10000     }
  10001     LOG_CLI((BSL_META_U(unit,
  10002                         "\n")));
  10003 
  10004     group_info = extq_info->mcgroup_info;
  10005     for (i = 0, j = 0; i < extq_info->ipmc_size; i++) {
  10006         /* If zero, skip print */
  10007         if (group_info->queue_count[i] == 0) {
  10008             continue;
  10009         }
  10010         if ((j > 0) && !(j % 4)) {
  10011             LOG_CLI((BSL_META_U(unit,
  10012                                 "\n         ")));
  10013         }
  10014         LOG_CLI((BSL_META_U(unit,
  10015                             " %5d:%-4d"), i, group_info->queue_count[i]));
  10016         j++;
  10017     }
  10018     LOG_CLI((BSL_META_U(unit,
  10019                         "\n")));
  10020     
  10021     rli_start = IPMC_EXTQ_REPL_LIST_INFO(unit);
  10022     LOG_CLI((BSL_META_U(unit,
  10023                         "    List Info    -\n")));
  10024     for (rli_current = rli_start; rli_current != NULL;
  10025          rli_current = rli_current->next) {
  10026         LOG_CLI((BSL_META_U(unit,
  10027                             "    Hash:  0x%08x\n"), rli_current->hash));
  10028         LOG_CLI((BSL_META_U(unit,
  10029                             "    Index: %4d\n"), rli_current->index));
  10030         LOG_CLI((BSL_META_U(unit,
  10031                             "    Size:  %4d\n"), rli_current->list_size));
  10032         LOG_CLI((BSL_META_U(unit,
  10033                             "    Refs:  %4d\n"), rli_current->refcount));
  10034     }
  10035 }
  10036 
  10037 #endif 
  10038 
  10039 
  10040 /*
  10041  * Function:
  10042  *     _bcm_tr3_ipmc_repl_sw_dump
  10043  * Purpose:
  10044  *     Displays IPMC replication information maintained by software.
  10045  * Parameters:
  10046  *     unit - Device unit number
  10047  * Returns:
  10048  *     None
  10049  */
  10050 void
  10051 _bcm_tr3_ipmc_repl_sw_dump(int unit)
  10052 {
  10053     _tr3_repl_info_t *repl_info;
  10054     bcm_port_t port;
  10055     _tr3_repl_port_info_t *port_info;
  10056     int i, j;
  10057     _bcm_repl_list_info_t *rli_start, *rli_current;
  10058     SHR_BITDCL *bitmap;
  10059     _tr3_repl_head_free_block_t *free_block;
  10060     int num_of_ports          = 0;
  10061     int repl_head_total_free  = 0;
  10062 
  10063     LOG_CLI((BSL_META_U(unit,
  10064                         "  IPMC REPL Info -\n")));
  10065     repl_info = _tr3_repl_info[unit];
  10066     if (repl_info != NULL) {
  10067         LOG_CLI((BSL_META_U(unit,
  10068                             "    Replication Group Size : %d\n"),
  10069                  repl_info->num_repl_groups));
  10070         LOG_CLI((BSL_META_U(unit,
  10071                             "    Replication Intf Size  : %d\n"),
  10072                  repl_info->num_intf));
  10073 
  10074         LOG_CLI((BSL_META_U(unit,
  10075                             "    Port Info    -\n")));
  10076         LOG_CLI((BSL_META_U(unit,
  10077                             "    port (index:intf-count) :\n")));
  10078         for (port = 0; port < ((SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS) ? 
  10079             SOC_MAX_NUM_PP_PORTS : SOC_MAX_NUM_PORTS); port++) {    
  10080             port_info = repl_info->port_info[port];
  10081             LOG_CLI((BSL_META_U(unit,
  10082                                 "    %3d -"), port));
  10083             if (port_info == NULL) {
  10084                 LOG_CLI((BSL_META_U(unit,
  10085                                     " null\n")));
  10086                 continue;
  10087             }
  10088             for (i = 0, j = 0; i < repl_info->num_repl_groups; i++) {
  10089                 /* If zero, skip print */
  10090                 if (port_info->intf_count[i] == 0) {
  10091                     continue;
  10092                 }
  10093                 if ((j > 0) && !(j % 4)) {
  10094                     LOG_CLI((BSL_META_U(unit,
  10095                                         "\n         ")));
  10096                 }
  10097                 LOG_CLI((BSL_META_U(unit,
  10098                                     " %5d:%-5d"), i, port_info->intf_count[i]));
  10099                 j++;
  10100             }
  10101             LOG_CLI((BSL_META_U(unit,
  10102                                 "\n")));
  10103         }
  10104 
  10105         rli_start = REPL_LIST_INFO(unit);
  10106         LOG_CLI((BSL_META_U(unit,
  10107                             "    List Info    -\n")));
  10108         for (rli_current = rli_start; rli_current != NULL;
  10109              rli_current = rli_current->next) {
  10110             LOG_CLI((BSL_META_U(unit,
  10111                                 "    Hash:  0x%08x\n"), rli_current->hash));
  10112             LOG_CLI((BSL_META_U(unit,
  10113                                 "    Index: %4d\n"), rli_current->index));
  10114             LOG_CLI((BSL_META_U(unit,
  10115                                 "    Size:  %4d\n"), rli_current->list_size));
  10116             LOG_CLI((BSL_META_U(unit,
  10117                                 "    Refs:  %4d\n"), rli_current->refcount));
  10118         }
  10119 
  10120       if (repl_info->l3_intf_next_hop_ipmc != NULL) {
  10121         LOG_CLI((BSL_META_U(unit,
  10122                             "    L3 Interface Next Hop IPMC Info -\n")));
  10123         for (i = 0; i < soc_mem_index_count(unit, EGR_L3_INTFm); i++) {
  10124            if (repl_info->l3_intf_next_hop_ipmc[i] ==
  10125                    REPL_NH_INDEX_UNALLOCATED) {
  10126               continue;
  10127            }
  10128            if (repl_info->l3_intf_next_hop_ipmc[i] ==
  10129                    REPL_NH_INDEX_L3_EGRESS_ALLOCATED) {
  10130               continue;
  10131            }
  10132           LOG_CLI((BSL_META_U(unit,
  10133                               "      L3 Interface %4d: Next Hop Index %5d\n"), i,
  10134                    repl_info->l3_intf_next_hop_ipmc[i]));
  10135         }
  10136       }
  10137 
  10138      if (repl_info->l3_intf_next_hop_trill != NULL) {
  10139 
  10140         LOG_CLI((BSL_META_U(unit,
  10141                             "    L3 Interface Next Hop Trill Info -\n")));
  10142         for (i = 0; i < soc_mem_index_count(unit, EGR_L3_INTFm); i++) {
  10143            if (repl_info->l3_intf_next_hop_trill[i] == -1) {
  10144               continue;
  10145            }
  10146           LOG_CLI((BSL_META_U(unit,
  10147                               "      L3 Interface %4d: Next Hop Index %5d\n"), i,
  10148                    repl_info->l3_intf_next_hop_trill[i]));
  10149         }
  10150      }
  10151     }
  10152 
  10153     if (_tr3_repl_list_entry_info[unit] != NULL) {
  10154         LOG_CLI((BSL_META_U(unit,
  10155                             "    Replication List Table Size : %d\n"),
  10156                  _tr3_repl_list_entry_info[unit]->num_entries));
  10157         LOG_CLI((BSL_META_U(unit,
  10158                             "    Replication List Table Usage Bitmap (index:value-hex) :")));
  10159         if (_tr3_repl_list_entry_info[unit]->bitmap_entries_used != NULL) {
  10160             bitmap = _tr3_repl_list_entry_info[unit]->bitmap_entries_used;
  10161             for (i = 0, j = 0;
  10162                     i < _SHR_BITDCLSIZE(_tr3_repl_list_entry_info[unit]->num_entries);
  10163                     i++) {
  10164                 /* If zero, skip print */
  10165                 if (bitmap[i] == 0) {
  10166                     continue;
  10167                 }
  10168                 if (!(j % 4)) {
  10169                     LOG_CLI((BSL_META_U(unit,
  10170                                         "\n    ")));
  10171                 }
  10172                 LOG_CLI((BSL_META_U(unit,
  10173                                     "  %5d:%8.8x"), i, bitmap[i]));
  10174                 j++;
  10175             }
  10176         }
  10177         LOG_CLI((BSL_META_U(unit,
  10178                             "\n")));
  10179     }
  10180 
  10181     if (_tr3_repl_head_info[unit] != NULL) {
  10182         LOG_CLI((BSL_META_U(unit,
  10183                             "    Replication Head Table Size : %d\n"),
  10184                  soc_mem_index_count(unit, MMU_REPL_HEAD_TBLm)));
  10185         if (soc_property_get(unit, spn_RESERVE_MULTICAST_RESOURCES, 0)) { 
  10186             BCM_PBMP_COUNT(PBMP_ALL(unit), num_of_ports); 
  10187             LOG_CLI(
  10188                 (BSL_META_U(unit,
  10189                             " Unit %d Replication Head reserved entries: %d\n"),
  10190                  unit, num_of_ports)); 
  10191         } 
  10192         
  10193         LOG_CLI((BSL_META_U(unit,
  10194                             "    Replication Head Free List Array:\n")));
  10195         if (_tr3_repl_head_info[unit]->free_list_array != NULL) {
  10196             for (i = 0; i < _tr3_repl_head_info[unit]->array_size; i++) {
  10197                 LOG_CLI((BSL_META_U(unit,
  10198                                     "      Free List %2d:"), i));
  10199                 free_block = REPL_HEAD_FREE_LIST(unit, i);
  10200                 j = 0;
  10201                 while (NULL != free_block) {
  10202                     if (j > 0 && !(j % 4)) {
  10203                         LOG_CLI((BSL_META_U(unit,
  10204                                             "\n                   ")));
  10205                     }
  10206                     LOG_CLI((BSL_META_U(unit,
  10207                                         "  %7d:%-7d"), free_block->index,
  10208                              free_block->size));
  10209                     free_block = free_block->next;
  10210                     j++;
  10211                 }
  10212                 LOG_CLI((BSL_META_U(unit,
  10213                                     "\n")));
  10214             }
  10215         }
  10216     }
  10217     (void)_bcm_tr3_repl_head_entry_info_get(unit, &repl_head_total_free); 
  10218     LOG_CLI((BSL_META_U(unit,
  10219                         " Unit %d Replication Head total available: %d\n"), 
  10220              unit, repl_head_total_free)); 
  10221 
  10222 #ifdef BCM_KATANA2_SUPPORT
  10223     /*
  10224      * _kt_extq_repl_info
  10225      */
  10226 #ifdef BCM_SABER2_SUPPORT 
  10227 
  10228     if (SOC_IS_SABER2(unit) && (repl_info != NULL)) { 
  10229         bcm_sb2_ipmc_subscriber_sw_dump( unit);
  10230     } else
  10231 #endif
  10232     { 
  10233 #ifndef BCM_SW_STATE_DUMP_DISABLE  
  10234         if (SOC_IS_KATANA2(unit) && (repl_info != NULL)) { 
  10235             bcm_kt2_ipmc_subscriber_sw_dump(unit);
  10236         }
  10237 #endif /* BCM_SW_STATE_DUMP_DISABLE */
  10238     } 
  10239 #endif
  10240 
  10241     return;
  10242 }
  10243 #endif /* BCM_SW_STATE_DUMP_DISABLE */
  10244 
  10245 /*
  10246  * Function:
  10247  *      bcm_tr3_ipmc_port_attach_repl_init
  10248  * Purpose:
  10249  *      Initialize IPMC replication for the specified port. This function is
  10250  *      called during Flexport operation on TD2+.
  10251  * Parameters:
  10252  *      unit - SOC unit #
  10253  *      port - Port number on which ipmc replication has to be initialized
  10254  * Returns:
  10255  *      BCM_E_XXX
  10256  * Notes:
  10257  * This function assumes that 'port' value has been validated
  10258  * This function should not be called during Warmboot
  10259  * Called during port attach operation
  10260  */
  10261 int
  10262 bcm_tr3_ipmc_port_attach_repl_init(int unit, bcm_port_t port)
  10263 {
  10264     int alloc_size;
  10265 
  10266     REPL_INIT(unit);
  10267 
  10268     if (NULL == _tr3_repl_info[unit]->port_info[port]) {
  10269 
  10270         _tr3_repl_info[unit]->port_info[port] =
  10271             sal_alloc(sizeof(_tr3_repl_port_info_t), "repl port info");
  10272 
  10273         if (NULL == _tr3_repl_info[unit]->port_info[port]) {
  10274             LOG_VERBOSE(BSL_LS_BCM_PORT,
  10275                         (BSL_META_U(unit,
  10276                         "Port ipmc repl port info's alloc failed."
  10277                         " unit=%d port=%d(%s)\n"),
  10278                         unit, port, SOC_PORT_NAME(unit, port)));
  10279             return BCM_E_MEMORY;
  10280         }
  10281     }
  10282 
  10283     sal_memset(_tr3_repl_info[unit]->port_info[port], 0,
  10284                 sizeof(_tr3_repl_port_info_t));
  10285 
  10286     alloc_size = sizeof(int) * _tr3_repl_info[unit]->num_repl_groups;
  10287 
  10288     if (NULL == _tr3_repl_info[unit]->port_info[port]->intf_count) {
  10289 
  10290         _tr3_repl_info[unit]->port_info[port]->intf_count =
  10291             sal_alloc(alloc_size, "repl port intf count");
  10292 
  10293         if (NULL == _tr3_repl_info[unit]->port_info[port]->intf_count) {
  10294             LOG_VERBOSE(BSL_LS_BCM_PORT,
  10295                         (BSL_META_U(unit,
  10296                         "Port ipmc repl port intf count's alloc failed."
  10297                         " unit=%d port=%d(%s)\n"),
  10298                         unit, port, SOC_PORT_NAME(unit, port)));
  10299 
  10300             /* Free previously allocated memory */
  10301             sal_free(_tr3_repl_info[unit]->port_info[port]);
  10302             _tr3_repl_info[unit]->port_info[port] = NULL;
  10303 
  10304             return BCM_E_MEMORY;
  10305         }
  10306     }
  10307 
  10308     sal_memset(_tr3_repl_info[unit]->port_info[port]->intf_count, 0,
  10309                alloc_size);
  10310 
  10311     /* Note: Programming of port agg map init. is done under mmu_set function,
  10312      * by calling soc_td2p_repl_port_agg_map_init()
  10313      * Also, programming of PORT_INITIAL_COPY_COUNT_WIDTHr is done under
  10314      * mmu_set by calling soc_td2p_port_icc_width_set()
  10315      */
  10316 
  10317     return BCM_E_NONE;
  10318 }
  10319 
  10320 /*
  10321  * Function:
  10322  *      bcm_tr3_ipmc_port_detach_repl_deinit
  10323  * Purpose:
  10324  *      Deinitialize replication data for a port. This function is called
  10325  *      during TD2+ Flexport operation
  10326  * Parameters:
  10327  *      unit - SOC unit #
  10328  *      port - Port for which replication data has to be cleared, or removed
  10329  * Returns:
  10330  *      BCM_E_XXX
  10331  * Notes:
  10332  * This function assumes that 'port' value has been validated
  10333  * Called during TD2+ Flexport port detach operation
  10334  * This function should not be called during Warmboot
  10335  */
  10336 int
  10337 bcm_tr3_ipmc_port_detach_repl_deinit(int unit, bcm_port_t port)
  10338 {
  10339     if (_tr3_repl_info[unit] != NULL) {
  10340         if (_tr3_repl_info[unit]->port_info[port] != NULL) {
  10341             if (_tr3_repl_info[unit]->port_info[port]->intf_count != NULL) {
  10342                 sal_free(_tr3_repl_info[unit]->port_info[port]->intf_count);
  10343                 _tr3_repl_info[unit]->port_info[port]->intf_count = NULL;
  10344             }
  10345              sal_free(_tr3_repl_info[unit]->port_info[port]);
  10346             _tr3_repl_info[unit]->port_info[port] = NULL;
  10347         }
  10348     }
  10349 
  10350     return BCM_E_NONE;
  10351 }
  10352 
  10353 #if defined(BCM_SABER2_SUPPORT)
  10354 
  10355 int
  10356 _bcm_sb2_ipmc_subscriber_egress_queue_qos_map(int unit, int extq_ptr,
  10357                                              int base_queue_id,
  10358                                              int *map_id,
  10359                                              int set)
  10360 {
  10361     int rv = BCM_E_NOT_FOUND;
  10362     int next_ptr1, next_ptr2;
  10363     int queue_id;
  10364     int i;
  10365     int profile = 0;
  10366     mmu_ext_mc_queue_list0_entry_t qlist0_entry;
  10367     mmu_ext_mc_queue_list4_entry_t qlist4_entry;
  10368     soc_field_t   base_qid[] = { BASE_QID0f, BASE_QID1f };
  10369     soc_field_t   profile_idx[] = { Q_OFFSET_PROF0f, Q_OFFSET_PROF1f };
  10370 
  10371 
  10372     if (map_id == NULL) {
  10373         return BCM_E_INTERNAL;
  10374     }
  10375 
  10376     if (set) {
  10377         if ((*map_id >> _BCM_QOS_MAP_SHIFT) !=
  10378             _BCM_QOS_MAP_TYPE_RQE_QUEUE_OFFSET_MAP) {
  10379            return BCM_E_PARAM;
  10380         }
  10381         /* Extract the profile_offset from QOS MAP*/
  10382         profile = *map_id & _BCM_QOS_MAP_TYPE_MASK;
  10383 
  10384         if ((profile < SB2_MIN_RQE_PROFILE_INDEX ) ||
  10385             (profile > SB2_MAX_RQE_PROFILE_INDEX)) {
  10386             return BCM_E_PARAM;
  10387         }
  10388     }
  10389 
  10390     if ((rv = READ_MMU_EXT_MC_QUEUE_LIST0m(unit, MEM_BLOCK_ANY,
  10391                                       extq_ptr, &qlist0_entry)) < 0) {
  10392         goto extq_list_done;
  10393     }
  10394     if ((rv = READ_MMU_EXT_MC_QUEUE_LIST4m(unit, MEM_BLOCK_ANY,
  10395                                       extq_ptr, &qlist4_entry)) < 0) {
  10396         goto extq_list_done;
  10397     }
  10398 
  10399     for (i = 0; i < 2; i++) {
  10400         if ((queue_id = soc_MMU_EXT_MC_QUEUE_LIST0m_field32_get(unit,
  10401                                     &qlist0_entry, base_qid[i])) != 0) {
  10402 
  10403             if (base_queue_id == queue_id) {
  10404                 if (set) {
  10405 
  10406                     /* set the profile index of the queue list entry */
  10407                     soc_MMU_EXT_MC_QUEUE_LIST0m_field32_set(unit,
  10408                                         &qlist0_entry,
  10409                                         profile_idx[i], profile);
  10410 
  10411                     rv = WRITE_MMU_EXT_MC_QUEUE_LIST0m(unit,
  10412                                           MEM_BLOCK_ANY,
  10413                                           extq_ptr, &qlist0_entry);
  10414                 } else {
  10415                     profile = soc_mem_field32_get(unit,
  10416                                     MMU_EXT_MC_QUEUE_LIST0m,
  10417                                     &qlist0_entry, profile_idx[i]);
  10418                     *map_id = profile | (_BCM_QOS_MAP_TYPE_RQE_QUEUE_OFFSET_MAP
  10419                                                      << _BCM_QOS_MAP_SHIFT);
  10420 
  10421                     rv = BCM_E_NONE;
  10422                 }
  10423             }
  10424         }
  10425     }
  10426 
  10427     next_ptr1 = soc_MMU_EXT_MC_QUEUE_LIST4m_field32_get(unit,
  10428                             &qlist4_entry, EXT_Q_NXT_PTR1f);
  10429     next_ptr2 = soc_MMU_EXT_MC_QUEUE_LIST4m_field32_get(unit,
  10430                             &qlist4_entry, EXT_Q_NXT_PTR2f);
  10431 
  10432     if (next_ptr1 != extq_ptr) {
  10433         rv = _bcm_sb2_ipmc_subscriber_egress_queue_qos_map(unit, next_ptr1,
  10434                                                  base_queue_id, map_id, set);
  10435     }
  10436 
  10437     if (next_ptr2 != extq_ptr) {
  10438         rv = _bcm_sb2_ipmc_subscriber_egress_queue_qos_map(unit, next_ptr2,
  10439                                                  base_queue_id, map_id, set);
  10440     }
  10441 
  10442 extq_list_done:
  10443     return rv;
  10444 
  10445 }
  10446 
  10447 STATIC
  10448 int _bcm_sb2_ipmc_egress_qos_profile_update(int unit, int ipmc_id,
  10449                                             int queue_id, int qos_map_id)
  10450 {
  10451     _bcm_ext_repl_q_list_t *queue_node;
  10452     _bcm_ext_q_ipmc_t  *ipmc_node = &_sb2_extq_repl_info[unit]->
  10453                                           ext_ipmc_list[ipmc_id];
  10454 
  10455     queue_node = ipmc_node->first_q_ptr;
  10456     while (queue_node != NULL) {
  10457            if (queue_node->queue_id == queue_id) {
  10458                queue_node->profile_id = qos_map_id;
  10459                break;
  10460            }
  10461            queue_node = queue_node->next;
  10462     }
  10463     if (queue_node == NULL) {
  10464         return BCM_E_NOT_FOUND;
  10465     }
  10466     return BCM_E_NONE;
  10467 }
  10468 
  10469 /*
  10470  * Function:
  10471  *    _bcm_sb2_ipmc_subscriber_egress_intf_qos_map_set
  10472  * Purpose:
  10473  *    Assign the complete set of egress GPORTs in the
  10474  *   replication list for the specified multicast index.
  10475  * Parameters:
  10476  *   unit              - (IN) Device Number
  10477  *   group             - (IN) Multicast group ID
  10478  *   port              - (IN) GPORT Identifier
  10479  *   subscriber queue  - (IN) Subscriber queue group GPORT Identifiers
  10480  *   qos_map_id        - (IN) Qos Map ID
  10481  * Returns:
  10482  *    BCM_E_XXX
  10483  */
  10484 int
  10485 _bcm_sb2_ipmc_subscriber_egress_intf_qos_map_set(int unit,
  10486                                         int ipmc_id,
  10487                                         bcm_gport_t port,
  10488                                         bcm_gport_t subscriber_queue,
  10489                                         int qos_map_id)
  10490 {
  10491 
  10492     int         rv = BCM_E_NONE;
  10493     int         extq_ptr;
  10494     int         queue_id;
  10495 
  10496     REPL_PORT_CHECK(unit, port);
  10497     BCM_IF_ERROR_RETURN(_bcm_kt2_init_check(unit, ipmc_id));
  10498 
  10499     if ((rv = _bcm_kt2_cosq_index_resolve(unit,  subscriber_queue, 0,
  10500                            _BCM_KT2_COSQ_INDEX_STYLE_QUEUE_REPLICATION,
  10501                            NULL,  &queue_id, NULL)) < 0) {
  10502         goto clean_up;
  10503     }
  10504 
  10505     REPL_LOCK(unit);
  10506     if ((rv = _sb2_extq_mc_group_ptr(unit, ipmc_id,
  10507                                 &extq_ptr, 0, 0)) < 0) {
  10508         goto clean_up;
  10509     }
  10510 
  10511     if (extq_ptr == 0) {
  10512         rv = BCM_E_INTERNAL;
  10513         goto clean_up;
  10514     }
  10515 
  10516     rv = _bcm_sb2_ipmc_subscriber_egress_queue_qos_map(unit, extq_ptr,
  10517                                                   queue_id, &qos_map_id, 1);
  10518     if (BCM_FAILURE(rv)) {
  10519        LOG_ERROR(BSL_LS_BCM_COMMON,
  10520           (BSL_META_U(unit,"Failure - setting subscriber queue %d Qos Map %d\n"),
  10521                            subscriber_queue, qos_map_id));
  10522     }
  10523     /* Update profile id */
  10524     rv = _bcm_sb2_ipmc_egress_qos_profile_update(unit, ipmc_id, queue_id, qos_map_id);
  10525 
  10526     if (BCM_FAILURE(rv)) {
  10527        LOG_ERROR(BSL_LS_BCM_COMMON,
  10528           (BSL_META_U(unit,"Failure - queue %d not found for IPMC id %d\n"),
  10529                            queue_id, ipmc_id));
  10530     }
  10531 
  10532 clean_up:
  10533     REPL_UNLOCK(unit);
  10534     return rv;
  10535 
  10536 }
  10537 
  10538 /*
  10539  * Function:
  10540  *    _bcm_sb2_ipmc_subscriber_egress_intf_qos_map_get
  10541  * Purpose:
  10542  *    Assign the complete set of egress GPORTs in the
  10543  *   replication list for the specified multicast index.
  10544  * Parameters:
  10545  *   unit              - (IN) Device Number
  10546  *   group             - (IN) Multicast group ID
  10547  *   port              - (IN) GPORT Identifier
  10548  *   subscriber queue  - (IN) Subscriber queue group GPORT Identifiers
  10549  *   qos_map_id        - (OUT) Qos Map ID
  10550  * Returns:
  10551  *    BCM_E_XXX
  10552  */
  10553 int
  10554 _bcm_sb2_ipmc_subscriber_egress_intf_qos_map_get(int unit,
  10555                                         int ipmc_id,
  10556                                         bcm_gport_t port,
  10557                                         bcm_gport_t subscriber_queue,
  10558                                         int *qos_map_id)
  10559 {
  10560     int         rv = BCM_E_NONE;
  10561     int         extq_ptr;
  10562     int         queue_id;
  10563 
  10564     REPL_PORT_CHECK(unit, port);
  10565     BCM_IF_ERROR_RETURN(_bcm_kt_init_check(unit, ipmc_id));
  10566 
  10567     if (qos_map_id == NULL) {
  10568         return BCM_E_INTERNAL;
  10569     }
  10570 
  10571     REPL_LOCK(unit);
  10572     if ((rv = _bcm_kt2_cosq_index_resolve(unit,  subscriber_queue, 0,
  10573                            _BCM_KT2_COSQ_INDEX_STYLE_QUEUE_REPLICATION,
  10574                            NULL,  &queue_id, NULL)) < 0) {
  10575         goto clean_up;
  10576     }
  10577 
  10578     if ((rv = _sb2_extq_mc_group_ptr(unit, ipmc_id,
  10579                                 &extq_ptr, 0, 0)) < 0) {
  10580         goto clean_up;
  10581     }
  10582 
  10583     if (extq_ptr == 0) {
  10584         rv = BCM_E_INTERNAL;
  10585         goto clean_up;
  10586     }
  10587 
  10588     rv = _bcm_sb2_ipmc_subscriber_egress_queue_qos_map(unit, extq_ptr,
  10589                                                   queue_id, qos_map_id, 0);
  10590     if (BCM_FAILURE(rv)) {
  10591        LOG_ERROR(BSL_LS_BCM_COMMON,
  10592           (BSL_META_U(unit,"Failure - getting subscriber queue %d\n"),
  10593                            subscriber_queue));
  10594     }
  10595 
  10596 clean_up:
  10597     REPL_UNLOCK(unit);
  10598     return rv;
  10599 
  10600 }
  10601 
  10602 
  10603 #endif /* BCM_SABER2_SUPPORT */
  10604 
  10605 #ifdef BCM_TRIDENT2PLUS_SUPPORT
  10606 STATIC int
  10607 _bcm_td2p_ipmc_egress_intf_set_for_trunk_first_member(
  10608     int unit, int repl_group, bcm_port_t port,
  10609     int if_count, bcm_if_t *if_array, int is_l3,
  10610     int check_port, bcm_trunk_t tgid)
  10611 {
  10612     int old_intf_count, new_intf_count;
  10613     int aggid;
  10614 
  10615     old_intf_count = REPL_PORT_GROUP_INTF_COUNT(unit, port, repl_group);
  10616     if ((old_intf_count == 0) && (if_count > 0)) {
  10617         BCM_IF_ERROR_RETURN(bcm_td2p_port_aggid_add(unit, port, tgid, &aggid));
  10618     }
  10619 
  10620     BCM_IF_ERROR_RETURN(
  10621         _bcm_esw_ipmc_egress_intf_set(
  10622             unit, repl_group, port, if_count, if_array, is_l3, check_port));
  10623 
  10624     new_intf_count = REPL_PORT_GROUP_INTF_COUNT(unit, port, repl_group);
  10625     if ((old_intf_count > 0) && (new_intf_count == 0)) {
  10626         BCM_IF_ERROR_RETURN(bcm_td2p_port_aggid_del(unit, port));
  10627     }
  10628 
  10629     return BCM_E_NONE;
  10630 }
  10631 
  10632 
  10633 STATIC int
  10634 _bcm_td2p_ipmc_egress_intf_set_for_same_pipe_member(
  10635     int unit, int repl_group, bcm_port_t port,
  10636     bcm_port_t first_port, bcm_trunk_t tgid)
  10637 {
  10638     int aggid;
  10639     int old_intf_count, new_intf_count;
  10640 
  10641     old_intf_count = REPL_PORT_GROUP_INTF_COUNT(unit, port, repl_group);
  10642     new_intf_count = REPL_PORT_GROUP_INTF_COUNT(unit, first_port, repl_group);
  10643     if (old_intf_count == new_intf_count) {
  10644         return BCM_E_NONE;
  10645     }
  10646 
  10647     BCM_IF_ERROR_RETURN(
  10648         _bcm_td2_repl_initial_copy_count_set(unit, repl_group,
  10649                                              port, new_intf_count));
  10650 
  10651     if ((old_intf_count == 0) && (new_intf_count > 0)) {
  10652         BCM_IF_ERROR_RETURN(bcm_td2p_port_aggid_add(unit, port, tgid, &aggid));
  10653     } else if ((old_intf_count > 0) && (new_intf_count == 0)) {
  10654         BCM_IF_ERROR_RETURN(bcm_td2p_port_aggid_del(unit, port));
  10655     }
  10656 
  10657     REPL_PORT_GROUP_INTF_COUNT(unit, port, repl_group) = new_intf_count;
  10658 
  10659     return BCM_E_NONE;
  10660 }
  10661 
  10662 STATIC int
  10663 _bcm_td2p_ipmc_egress_intf_add_in_per_trunk_mode(int unit, int repl_group,
  10664     bcm_port_t port, int encap_id, int is_l3)
  10665 {
  10666     int aggid;
  10667 
  10668     if (REPL_PORT_GROUP_INTF_COUNT(unit, port, repl_group) == 0) {
  10669         BCM_IF_ERROR_RETURN(
  10670             bcm_td2p_port_aggid_add(unit, port, BCM_TRUNK_INVALID, &aggid));
  10671     }
  10672 
  10673     BCM_IF_ERROR_RETURN(
  10674         _bcm_esw_ipmc_egress_intf_add(
  10675             unit, repl_group, port, encap_id, is_l3));
  10676 
  10677     return BCM_E_NONE;
  10678 }
  10679 
  10680 STATIC int
  10681 _bcm_td2p_ipmc_egress_intf_del_in_per_trunk_mode(int unit, int repl_group,
  10682     bcm_port_t port, int if_max, int encap_id, int is_l3)
  10683 {
  10684 
  10685     int old_intf_count, new_intf_count;
  10686 
  10687     old_intf_count = REPL_PORT_GROUP_INTF_COUNT(unit, port, repl_group);
  10688     BCM_IF_ERROR_RETURN(
  10689         _bcm_esw_ipmc_egress_intf_delete(
  10690             unit, repl_group, port, if_max, encap_id, is_l3));
  10691     new_intf_count = REPL_PORT_GROUP_INTF_COUNT(unit, port, repl_group);
  10692     if (new_intf_count == 0 && old_intf_count > 0) {
  10693         BCM_IF_ERROR_RETURN(bcm_td2p_port_aggid_del(unit, port));
  10694     }
  10695 
  10696     return BCM_E_NONE;
  10697 }
  10698 
  10699 
  10700 STATIC int
  10701 _bcm_td2p_ipmc_egress_intf_add_for_trunk(int unit, int repl_group,
  10702     bcm_trunk_t tgid, int encap_id, int is_l3)
  10703 {
  10704 #if defined(BCM_ESW_SUPPORT) && (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS)
  10705     bcm_port_t      trunk_local_member_ports[SOC_MAX_NUM_PP_PORTS] = {0};
  10706     int             max_num_ports = SOC_MAX_NUM_PP_PORTS;
  10707 #else
  10708     bcm_port_t      trunk_local_member_ports[SOC_MAX_NUM_PORTS] = {0};
  10709     int             max_num_ports = SOC_MAX_NUM_PORTS;
  10710 #endif
  10711 
  10712     int idx;
  10713     int member_count, port_iter;
  10714     bcm_port_t trunk_pipe_first_port_array[BCM_PIPES_MAX];
  10715     int aggid, pipe;
  10716 
  10717     BCM_IF_ERROR_RETURN(
  10718         _bcm_esw_trunk_local_members_get(unit, tgid, max_num_ports,
  10719                                          trunk_local_member_ports,
  10720                                          &member_count));
  10721 
  10722     for (idx = 0; idx < BCM_PIPES_MAX; idx++) {
  10723         trunk_pipe_first_port_array[idx] = -1;
  10724     }
  10725     for (idx = 0; idx < member_count; idx++) {
  10726         port_iter = trunk_local_member_ports[idx];
  10727         pipe      = SOC_INFO(unit).port_pipe[port_iter];
  10728         if (trunk_pipe_first_port_array[pipe] == -1) {
  10729             if (REPL_PORT_GROUP_INTF_COUNT(unit, port_iter, repl_group) == 0) {
  10730                 BCM_IF_ERROR_RETURN(
  10731                     bcm_td2p_port_aggid_add(unit, port_iter, tgid, &aggid));
  10732             }
  10733             BCM_IF_ERROR_RETURN(
  10734                 _bcm_esw_ipmc_egress_intf_add(
  10735                     unit, repl_group, port_iter, encap_id, is_l3));
  10736             trunk_pipe_first_port_array[pipe] = port_iter;
  10737         } else {
  10738             BCM_IF_ERROR_RETURN(
  10739                 _bcm_td2p_ipmc_egress_intf_set_for_same_pipe_member(
  10740                     unit, repl_group, port_iter,
  10741                     trunk_pipe_first_port_array[pipe], tgid));
  10742         }
  10743     }
  10744 
  10745     return BCM_E_NONE;
  10746 }
  10747 
  10748 STATIC int
  10749 _bcm_td2p_ipmc_egress_intf_del_for_trunk(int unit, int repl_group,
  10750     bcm_trunk_t tgid, int if_max, int encap_id, int is_l3)
  10751 {
  10752 #if defined(BCM_ESW_SUPPORT) && (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS)
  10753     bcm_port_t      trunk_local_member_ports[SOC_MAX_NUM_PP_PORTS] = {0};
  10754     int             max_num_ports = SOC_MAX_NUM_PP_PORTS;
  10755 #else
  10756     bcm_port_t      trunk_local_member_ports[SOC_MAX_NUM_PORTS] = {0};
  10757     int             max_num_ports = SOC_MAX_NUM_PORTS;
  10758 #endif
  10759 
  10760     int idx;
  10761     int member_count, port_iter;
  10762     bcm_port_t trunk_pipe_first_port_array[BCM_PIPES_MAX];
  10763     int pipe;
  10764     int old_intf_count, new_intf_count;
  10765 
  10766     BCM_IF_ERROR_RETURN(
  10767         _bcm_esw_trunk_local_members_get(unit, tgid, max_num_ports,
  10768                                          trunk_local_member_ports,
  10769                                          &member_count));
  10770 
  10771     for (idx = 0; idx < BCM_PIPES_MAX; idx++) {
  10772         trunk_pipe_first_port_array[idx] = -1;
  10773     }
  10774 
  10775     for (idx = 0; idx < member_count; idx++) {
  10776         port_iter = trunk_local_member_ports[idx];
  10777         pipe      = SOC_INFO(unit).port_pipe[port_iter];
  10778         if (trunk_pipe_first_port_array[pipe] == -1) {
  10779             old_intf_count = REPL_PORT_GROUP_INTF_COUNT(unit, port_iter, repl_group);
  10780             BCM_IF_ERROR_RETURN(
  10781                 _bcm_esw_ipmc_egress_intf_delete(
  10782                      unit, repl_group, trunk_local_member_ports[idx],
  10783                      if_max, encap_id, is_l3));
  10784             new_intf_count = REPL_PORT_GROUP_INTF_COUNT(unit, port_iter, repl_group);
  10785             if (new_intf_count == 0 && old_intf_count > 0) {
  10786                 BCM_IF_ERROR_RETURN(
  10787                     bcm_td2p_port_aggid_del(unit, port_iter));
  10788             }
  10789             trunk_pipe_first_port_array[pipe] = port_iter;
  10790         } else {
  10791             BCM_IF_ERROR_RETURN(
  10792                 _bcm_td2p_ipmc_egress_intf_set_for_same_pipe_member(
  10793                     unit, repl_group, port_iter,
  10794                     trunk_pipe_first_port_array[pipe], tgid));
  10795         }
  10796     }
  10797 
  10798     return BCM_E_NONE;
  10799 }
  10800 
  10801 STATIC int
  10802 _bcm_td2p_ipmc_egress_intf_add_trunk_member(int unit, int repl_group,
  10803                                             bcm_port_t port)
  10804 {
  10805 #if defined(BCM_ESW_SUPPORT) && (SOC_MAX_NUM_PP_PORTS > SOC_MAX_NUM_PORTS)
  10806     bcm_port_t      trunk_local_member_ports[SOC_MAX_NUM_PP_PORTS] = {0};
  10807     int             max_num_ports = SOC_MAX_NUM_PP_PORTS;
  10808 #else
  10809     bcm_port_t      trunk_local_member_ports[SOC_MAX_NUM_PORTS] = {0};
  10810     int             max_num_ports = SOC_MAX_NUM_PORTS;
  10811 #endif
  10812 
  10813     int local_modid;
  10814     int trunk_local_ports;
  10815     int intf_count, if_count, old_intf_count;
  10816     int same_pipe_port = -1, diff_pipe_port = -1;
  10817     int i, rv;
  10818     bcm_port_t port_iter;
  10819     bcm_if_t *if_array;
  10820     bcm_trunk_t tgid;
  10821     int aggid;
  10822 
  10823     /* Member port belongs to an existing trunk, it needs to share
  10824      * identical replication list as other members of this trunk in
  10825      * same pipe.
  10826      */
  10827     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &local_modid));
  10828     BCM_IF_ERROR_RETURN(
  10829         bcm_esw_trunk_find(unit, local_modid, port, &tgid));
  10830     BCM_IF_ERROR_RETURN(
  10831         _bcm_esw_trunk_local_members_get(unit, tgid, max_num_ports,
  10832                                          trunk_local_member_ports,
  10833                                          &trunk_local_ports));
  10834 
  10835     for (i = 0; i < trunk_local_ports; i++) {
  10836         port_iter = trunk_local_member_ports[i];
  10837         if (port != port_iter) {
  10838             intf_count =
  10839                 REPL_PORT_GROUP_INTF_COUNT(unit, port_iter, repl_group);
  10840             if (intf_count > 0) {
  10841                 if (SOC_INFO(unit).port_pipe[port] ==
  10842                     SOC_INFO(unit).port_pipe[port_iter]) {
  10843                     same_pipe_port = port_iter;
  10844                     break;
  10845                 } else {
  10846                     if (diff_pipe_port == -1) {
  10847                         diff_pipe_port = port_iter;
  10848                     }
  10849                 }
  10850             }
  10851         }
  10852     }
  10853 
  10854     /* or return BCM_E_PARAM? */
  10855     if (same_pipe_port == -1 && diff_pipe_port == -1) {
  10856         return BCM_E_NONE;
  10857     }
  10858 
  10859     if (same_pipe_port != -1) {
  10860         BCM_IF_ERROR_RETURN(
  10861             _bcm_td2p_ipmc_egress_intf_set_for_same_pipe_member(
  10862                 unit, repl_group, port, same_pipe_port, tgid));
  10863     } else {
  10864         intf_count = REPL_PORT_GROUP_INTF_COUNT(unit, diff_pipe_port,
  10865                                                 repl_group);
  10866         if_array = sal_alloc(sizeof(bcm_if_t) * intf_count,
  10867                              "if_array pointers");
  10868         if (if_array == NULL) {
  10869             return BCM_E_MEMORY;
  10870         }
  10871 
  10872         rv = bcm_tr3_ipmc_egress_intf_get(unit, repl_group, diff_pipe_port,
  10873                                           intf_count, if_array, &if_count);
  10874         if (BCM_FAILURE(rv)) {
  10875             sal_free(if_array);
  10876             return rv;
  10877         }
  10878 
  10879         old_intf_count = REPL_PORT_GROUP_INTF_COUNT(unit, port, repl_group);
  10880         if ((old_intf_count == 0) && (intf_count > 0)) {
  10881             rv = bcm_td2p_port_aggid_add(unit, port, tgid, &aggid);
  10882             if (BCM_FAILURE(rv)) {
  10883                 sal_free(if_array);
  10884                 return rv;
  10885             }
  10886         }
  10887         rv = _bcm_esw_ipmc_egress_intf_set(unit, repl_group, port,
  10888                                            if_count, if_array, TRUE, FALSE);
  10889         if (BCM_FAILURE(rv)) {
  10890             sal_free(if_array);
  10891             return rv;
  10892         }
  10893         sal_free(if_array);
  10894     }
  10895 
  10896     return BCM_E_NONE;
  10897 }
  10898 
  10899 STATIC int
  10900 _bcm_td2p_ipmc_egress_intf_del_trunk_member(int unit, int repl_group,
  10901                                             bcm_port_t port)
  10902 {
  10903     int is_last_member;
  10904     int old_intf_count;
  10905 
  10906     BCM_IF_ERROR_RETURN(
  10907         bcm_td2p_port_last_member_check(unit, port, &is_last_member));
  10908 
  10909     old_intf_count = REPL_PORT_GROUP_INTF_COUNT(unit, port, repl_group);
  10910     if (is_last_member) {
  10911         BCM_IF_ERROR_RETURN(
  10912             bcm_tr3_ipmc_egress_intf_set(
  10913                 unit, repl_group, port, 0, NULL, TRUE, FALSE));
  10914     } else {
  10915         BCM_IF_ERROR_RETURN(
  10916             _bcm_td2_repl_initial_copy_count_set(
  10917                 unit, repl_group, port, 0));
  10918         REPL_PORT_GROUP_INTF_COUNT(unit, port, repl_group) = 0;
  10919     }
  10920 
  10921     if (old_intf_count > 0) {
  10922         BCM_IF_ERROR_RETURN(bcm_td2p_port_aggid_del(unit, port));
  10923     }
  10924 
  10925     return BCM_E_NONE;
  10926 }
  10927 
  10928 /*
  10929  * Function:
  10930  *      bcm_td2p_ipmc_egress_intf_set_for_trunk_first_member
  10931  * Purpose:
  10932  *      Assign set of egress interfaces to the first port of a trunk.
  10933  *      or to the only one non-trunk port.
  10934  * Parameters:
  10935  *  unit       - (IN) StrataSwitch PCI device unit number.
  10936  *  repl_group - (IN) The replication group number.
  10937  *  port       - (IN) Port to assign replication list.
  10938  *  if_count   - (IN) Number of interfaces in replication list.
  10939  *  if_array   - (IN) List of interface numbers.
  10940  *  if_updated - (IN) interfaces info to be updated including
  10941  *                    interfaces which is new to the group and port
  10942  *                    and interfaces to be deleted.
  10943  *  is_l3      - (IN) Indicates if multicast group is of type IPMC.
  10944  *  check_port - (IN) If if_array consists of L3 interfaces, this parameter
  10945  *                    controls whether to check the given port is a member
  10946  *                    in each L3 interface's VLAN. This check should be
  10947  *                    disabled when not needed, in order to improve
  10948  *                    performance.
  10949  *  tgid       - (IN) trunk id or BCM_TRUNK_INVALID for non-trunk port.
  10950  *
  10951  * Returns:
  10952  *      BCM_E_XXX
  10953  */
  10954 int
  10955 bcm_td2p_ipmc_egress_intf_set_for_trunk_first_member(
  10956     int unit, int repl_group, bcm_port_t port,
  10957     int if_count, bcm_if_t *if_array, int is_l3,
  10958     int check_port, bcm_trunk_t tgid)
  10959 {
  10960     int rv = BCM_E_NONE;
  10961 
  10962     IPMC_LOCK(unit);
  10963     rv = _bcm_td2p_ipmc_egress_intf_set_for_trunk_first_member(
  10964              unit, repl_group, port, if_count, if_array,
  10965              is_l3, check_port, tgid);
  10966     IPMC_UNLOCK(unit);
  10967 
  10968     return rv;
  10969 }
  10970 
  10971 /*
  10972  * Function:
  10973  *      bcm_td2p_ipmc_egress_intf_set_for_same_pipe_member
  10974  * Purpose:
  10975  *      Align egress intf of same pipe port with the first port of trunk.
  10976  * Parameters:
  10977  *  unit       - (IN) StrataSwitch PCI device unit number.
  10978  *  repl_group - (IN) The replication group number.
  10979  *  port       - (IN) Port to assign replication list.
  10980  *  first_port - (IN) The first member port of the trunk.
  10981  *  tgid       - (IN) trunk id.
  10982  *
  10983  * Returns:
  10984  *      BCM_E_XXX
  10985  */
  10986 int
  10987 bcm_td2p_ipmc_egress_intf_set_for_same_pipe_member(
  10988     int unit, int repl_group, bcm_port_t port,
  10989     bcm_port_t first_port, bcm_trunk_t tgid)
  10990 {
  10991     int rv = BCM_E_NONE;
  10992 
  10993     IPMC_LOCK(unit);
  10994     rv = _bcm_td2p_ipmc_egress_intf_set_for_same_pipe_member(
  10995              unit, repl_group, port, first_port, tgid);
  10996     IPMC_UNLOCK(unit);
  10997 
  10998     return rv;
  10999 }
  11000 
  11001 /*
  11002  * Function:
  11003  *      bcm_td2p_ipmc_egress_intf_add_in_per_trunk_mode
  11004  * Purpose:
  11005  *      Add encap ID to selected ports' replication list for chosen
  11006  *      IPMC group in mc per trunk repl mode.
  11007  *      It is used for non-trunk port.
  11008  * Parameters:
  11009  *  unit       - (IN) StrataSwitch PCI device unit number.
  11010  *  repl_group - (IN) The replication group number.
  11011  *  port       - (IN) Port to assign replication list.
  11012  *  encap_id   - (IN) Encap ID.
  11013  *  is_l3      - (IN) Indicates if multicast group type is IPMC.
  11014  *
  11015  * Returns:
  11016  *      BCM_E_XXX
  11017  */
  11018 int
  11019 bcm_td2p_ipmc_egress_intf_add_in_per_trunk_mode(int unit, int repl_group,
  11020     bcm_port_t port, int encap_id, int is_l3)
  11021 {
  11022     int rv = BCM_E_NONE;
  11023 
  11024     IPMC_LOCK(unit);
  11025     rv = _bcm_td2p_ipmc_egress_intf_add_in_per_trunk_mode(
  11026              unit, repl_group, port, encap_id, is_l3);
  11027     IPMC_UNLOCK(unit);
  11028 
  11029     return rv;
  11030 }
  11031 
  11032 /*
  11033  * Function:
  11034  *      bcm_td2p_ipmc_egress_intf_del_in_per_trunk_mode
  11035  * Purpose:
  11036  *      Remove encap ID from selected ports' replication list for chosen
  11037  *      IPMC group in mc per trunk repl mode.
  11038  *      It is used for non-trunk port.
  11039  * Parameters:
  11040  *  unit       - (IN) StrataSwitch PCI device unit number.
  11041  *  repl_group - (IN) The replication group number.
  11042  *  port       - (IN) Port to assign replication list.
  11043  *  if_max     - (IN) Maximal interface.
  11044  *  encap_id   - (IN) Encap ID.
  11045  *  is_l3      - (IN) Indicates if multicast group type is IPMC.
  11046  * Returns:
  11047  *      BCM_E_XXX
  11048  */
  11049 int
  11050 bcm_td2p_ipmc_egress_intf_del_in_per_trunk_mode(int unit, int repl_group,
  11051     bcm_port_t port, int if_max, int encap_id, int is_l3)
  11052 {
  11053     int rv = BCM_E_NONE;
  11054 
  11055     IPMC_LOCK(unit);
  11056     rv = _bcm_td2p_ipmc_egress_intf_del_in_per_trunk_mode(
  11057              unit, repl_group, port, if_max, encap_id, is_l3);
  11058     IPMC_UNLOCK(unit);
  11059 
  11060     return rv;
  11061 }
  11062 
  11063 /*
  11064  * Function:
  11065  *      bcm_td2p_ipmc_egress_intf_add_for_trunk
  11066  * Purpose:
  11067  *      Add encap ID to a trunk.
  11068  * Parameters:
  11069  *  unit       - (IN) StrataSwitch PCI device unit number.
  11070  *  repl_group - (IN) The replication group number.
  11071  *  tgid       - (IN) Trunk ID.
  11072  *  encap_id   - (IN) Encap ID.
  11073  *  is_l3      - (IN) Indicates if multicast group type is IPMC.
  11074  *
  11075  * Returns:
  11076  *      BCM_E_XXX
  11077  */
  11078 int
  11079 bcm_td2p_ipmc_egress_intf_add_for_trunk(int unit, int repl_group,
  11080     bcm_trunk_t tgid, int encap_id, int is_l3)
  11081 {
  11082     int rv = BCM_E_NONE;
  11083 
  11084     IPMC_LOCK(unit);
  11085     rv = _bcm_td2p_ipmc_egress_intf_add_for_trunk(
  11086              unit, repl_group, tgid, encap_id, is_l3);
  11087     IPMC_UNLOCK(unit);
  11088 
  11089     return rv;
  11090 }
  11091 
  11092 /*
  11093  * Function:
  11094  *      bcm_td2p_ipmc_egress_intf_del_for_trunk
  11095  * Purpose:
  11096  *      Remove encap ID from a trunk.
  11097  * Parameters:
  11098  *  unit       - (IN) StrataSwitch PCI device unit number.
  11099  *  repl_group - (IN) The replication group number.
  11100  *  tgid       - (IN) Trunk ID.
  11101  *  if_max     - (IN) Maximal interface.
  11102  *  encap_id   - (IN) Encap ID.
  11103  *  is_l3      - (IN) Indicates if multicast group type is IPMC.
  11104  *
  11105  * Returns:
  11106  *      BCM_E_XXX
  11107  */
  11108 int
  11109 bcm_td2p_ipmc_egress_intf_del_for_trunk(int unit, int repl_group,
  11110     bcm_trunk_t tgid, int if_max, int encap_id, int is_l3)
  11111 {
  11112     int rv = BCM_E_NONE;
  11113 
  11114     IPMC_LOCK(unit);
  11115     rv = _bcm_td2p_ipmc_egress_intf_del_for_trunk(
  11116              unit, repl_group, tgid, if_max, encap_id, is_l3);
  11117     IPMC_UNLOCK(unit);
  11118 
  11119     return rv;
  11120 }
  11121 
  11122 /*
  11123  * Function:
  11124  *      bcm_td2p_ipmc_egress_intf_add_trunk_member
  11125  * Purpose:
  11126  *      Add a port member to a trunk for chosen IPMC group.
  11127  * Parameters:
  11128  *  unit       - (IN) StrataSwitch PCI device unit number.
  11129  *  repl_group - (IN) The replication group number.
  11130  *  port       - (IN) Trunk member port.
  11131  *
  11132  * Returns:
  11133  *      BCM_E_XXX
  11134  */
  11135 int
  11136 bcm_td2p_ipmc_egress_intf_add_trunk_member(int unit, int repl_group,
  11137                                            bcm_port_t port)
  11138 {
  11139     int rv = BCM_E_NONE;
  11140 
  11141     IPMC_LOCK(unit);
  11142     rv = _bcm_td2p_ipmc_egress_intf_add_trunk_member(
  11143              unit, repl_group, port);
  11144     IPMC_UNLOCK(unit);
  11145 
  11146     return rv;
  11147 }
  11148 
  11149 
  11150 /*
  11151  * Function:
  11152  *      bcm_td2p_ipmc_egress_intf_del_trunk_member
  11153  * Purpose:
  11154  *      Remove a port member from a trunk for chosen IPMC group.
  11155  * Parameters:
  11156  *  unit       - (IN) StrataSwitch PCI device unit number.
  11157  *  repl_group - (IN) The replication group number.
  11158  *  port       - (IN) Trunk member port.
  11159  *
  11160  * Returns:
  11161  *      BCM_E_XXX
  11162  */
  11163 int
  11164 bcm_td2p_ipmc_egress_intf_del_trunk_member(int unit, int repl_group,
  11165                                            bcm_port_t port)
  11166 {
  11167     int rv = BCM_E_NONE;
  11168 
  11169     IPMC_LOCK(unit);
  11170     rv = _bcm_td2p_ipmc_egress_intf_del_trunk_member(
  11171              unit, repl_group, port);
  11172     IPMC_UNLOCK(unit);
  11173 
  11174     return rv;
  11175 }
  11176 
  11177 #endif /* BCM_TRIDENT2PLUS_SUPPORT */
  11178 
  11179 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_L3 */
  11180 #endif