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