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, ®val, 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, ®val, 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, ®val, 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 ®val, 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, ®val_64, 4391 OLD_REPL_HEAD_PTRf, old_repl_head_ptr); 4392 soc_reg64_field32_set(unit, REPL_HEAD_PTR_REPLACEr, ®val_64, 4393 NEW_REPL_HEAD_PTRf, new_repl_head_ptr); 4394 soc_reg64_field32_set(unit, REPL_HEAD_PTR_REPLACEr, ®val_64, 4395 NEW_L3_LASTf, new_l3_last); 4396 soc_reg64_field32_set(unit, REPL_HEAD_PTR_REPLACEr, ®val_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, ®val_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, ®val)); 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, ®val)); 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, ®val)); 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