port.c (174334B)
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: port.c 8 * Purpose: XGS3 port function implementations 9 * 10 * int bcm_xgs3_port_cfg_init(int unit, bcm_port_t port, bcm_vlan_data_t *vd) 11 * int bcm_xgs3_port_cfg_get(int unit, bcm_port_t port, bcm_port_cfg_t *cfg) 12 * int bcm_xgs3_port_cfg_set(int unit, bcm_port_t port, bcm_port_cfg_t *cfg) 13 */ 14 15 #include <soc/defs.h> 16 17 #if defined(BCM_FIREBOLT_SUPPORT) 18 19 #include <sal/core/libc.h> 20 21 #include <soc/mem.h> 22 #include <soc/debug.h> 23 #include <soc/cm.h> 24 #include <soc/drv.h> 25 #include <soc/register.h> 26 #include <soc/memory.h> 27 #include <soc/ll.h> 28 #include <soc/ptable.h> 29 #include <soc/l2x.h> 30 31 #include <bcm/port.h> 32 #include <bcm/mirror.h> 33 #include <bcm/error.h> 34 35 #include <bcm_int/common/lock.h> 36 #include <bcm_int/esw/mbcm.h> 37 #include <bcm_int/esw/firebolt.h> 38 #include <bcm_int/esw/triumph.h> 39 #include <bcm_int/esw/mirror.h> 40 #include <bcm_int/esw/stack.h> 41 #include <bcm_int/esw/port.h> 42 43 #ifdef BCM_TRIDENT_SUPPORT 44 #include <bcm_int/esw/trident.h> 45 #endif /* BCM_TRIDENT_SUPPORT */ 46 47 #ifdef BCM_TRIDENT2_SUPPORT 48 #include <bcm_int/esw/trident2.h> 49 #endif /* BCM_TRIDENT2_SUPPORT */ 50 51 #ifdef BCM_TRIDENT2PLUS_SUPPORT 52 #include <bcm_int/esw/trident2plus.h> 53 #endif /* BCM_TRIDENT2PLUS_SUPPORT */ 54 55 #ifdef BCM_HGPROXY_COE_SUPPORT 56 #include <bcm_int/esw/subport.h> 57 #include <bcm_int/esw/xgs5.h> 58 #endif /* BCM_HGPROXY_COE_SUPPORT */ 59 60 #ifdef BCM_HURRICANE3_SUPPORT 61 #include <bcm_int/esw/hurricane3.h> 62 #endif /* BCM_HURRICANE3_SUPPORT */ 63 64 #ifdef BCM_TRX_SUPPORT 65 #include <bcm_int/esw/trx.h> 66 #endif /* BCM_TRX_SUPPORT */ 67 68 #include <bcm_int/esw_dispatch.h> 69 70 71 /* 72 * Function: 73 * _bcm_xgs3_port_table_read 74 * Purpose: 75 * Read port table entry and parse it to a common 76 * (bcm_port_cfg_t) structure. 77 * Parameters: 78 * unit - (IN)SOC unit number. 79 * port - (IN)Port number. 80 * port_cfg - (OUT)API port information structure. 81 * Returns: 82 * BCM_E_XXX 83 * Notes: 84 * The following port configuration settings 85 * do not apply to FB/ER ports: 86 * 87 * port_cfg->pc_frame_type 88 * port_cfg->pc_ether_type 89 * port_cfg->pc_stp_state 90 * port_cfg->pc_cpu 91 * port_cfg->pc_ptype 92 * port_cfg->pc_pbm 93 * port_cfg->pc_ut_pbm 94 * port_cfg->pc_trunk 95 * port_cfg->pc_pfm 96 * The following port configuration do not apply to ER 97 * port_cfg->pc_nni_port 98 */ 99 STATIC int 100 _bcm_xgs3_port_table_read(int unit, bcm_port_t port, 101 bcm_port_cfg_t *port_cfg) 102 { 103 port_tab_entry_t ptab_entry; /* Port table entry. */ 104 int discard_tag; /* Discard tagged packets bit. */ 105 int discard_untag; /* Discard untagged packets bit. */ 106 soc_mem_t mem = PORT_TABm; /* Port table memory. */ 107 int tbl_index = port; /* Port table index. */ 108 int rv; /* Operation return status. */ 109 110 if (BCM_GPORT_IS_SET(port)) { 111 BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, port, &port)); 112 } 113 tbl_index = port; 114 115 #if defined(BCM_TRIDENT3_SUPPORT) 116 if (SOC_MEM_IS_VALID(unit, ING_DEVICE_PORTm)) { 117 mem = ING_DEVICE_PORTm; 118 } 119 #endif 120 121 soc_mem_lock(unit, mem); 122 123 /* Read port table entry from HW. */ 124 rv = BCM_XGS3_MEM_READ(unit, mem, tbl_index, &ptab_entry); 125 if (BCM_FAILURE(rv)) { 126 soc_mem_unlock(unit, mem); 127 return (rv); 128 } 129 130 /* If port cpu managed learning is not frozen read it from port. */ 131 if (!soc_feature(unit, soc_feature_no_learning) && 132 soc_l2x_frozen_cml_get(unit, port, &port_cfg->pc_cml, &port_cfg->pc_cml_move) < 0) { 133 #ifdef BCM_TRX_SUPPORT 134 if (SOC_IS_TRX(unit)) { 135 port_cfg->pc_cml = 136 soc_mem_field32_get(unit, mem, &ptab_entry, CML_FLAGS_NEWf); 137 port_cfg->pc_cml_move = 138 soc_mem_field32_get(unit, mem, &ptab_entry, CML_FLAGS_MOVEf); 139 } else 140 #endif /* BCM_TRX_SUPPORT */ 141 { 142 port_cfg->pc_cml = soc_mem_field32_get(unit, mem, &ptab_entry, CMLf); 143 } 144 } 145 soc_mem_unlock(unit, mem); 146 147 /* Get drop all tagged packets flag. */ 148 discard_tag = soc_mem_field32_get(unit, mem, &ptab_entry, PORT_DIS_TAGf); 149 150 /* Get drop all untagged packets flag. */ 151 discard_untag = 152 soc_mem_field32_get(unit, mem, &ptab_entry, PORT_DIS_UNTAGf); 153 154 if (discard_tag && discard_untag) { 155 port_cfg->pc_disc = BCM_PORT_DISCARD_ALL; 156 } else if (discard_tag) { 157 port_cfg->pc_disc = BCM_PORT_DISCARD_TAG; 158 } else if (discard_untag) { 159 port_cfg->pc_disc = BCM_PORT_DISCARD_UNTAG; 160 } else { 161 port_cfg->pc_disc = BCM_PORT_DISCARD_NONE; 162 } 163 164 /* Get drop bpdu's on ingress flag. */ 165 port_cfg->pc_bpdu_disable = 166 soc_mem_field32_get(unit, mem, &ptab_entry, DROP_BPDUf); 167 168 /* Get enable mirroring flag. */ 169 if (soc_feature(unit, soc_feature_mirror_flexible)) { 170 /* Multi-bit field */ 171 port_cfg->pc_mirror_ing = 172 soc_mem_field32_get(unit, mem, &ptab_entry, MIRRORf); 173 } else if (!soc_feature(unit, soc_feature_no_mirror) && 174 soc_mem_field32_get(unit, mem, &ptab_entry, MIRRORf)) { 175 port_cfg->pc_mirror_ing |= BCM_MIRROR_MTP_ONE; 176 } 177 178 179 /* Get port default vlan id (pvid). */ 180 port_cfg->pc_vlan = soc_mem_field32_get(unit, mem, &ptab_entry, PORT_VIDf); 181 182 #ifdef BCM_TRX_SUPPORT 183 if (SOC_IS_TRX(unit)) { 184 if (SOC_MEM_FIELD_VALID(unit, mem, IVIDf)) { 185 port_cfg->pc_ivlan = soc_mem_field32_get(unit, mem, &ptab_entry, IVIDf); 186 } 187 port_cfg->pc_vlan_action = soc_mem_field32_get(unit, mem, &ptab_entry, 188 TAG_ACTION_PROFILE_PTRf); 189 } else 190 #endif /* BCM_TRX_SUPPORT */ 191 { 192 port_cfg->pc_ivlan = 0; 193 port_cfg->pc_vlan_action = 0; 194 } 195 196 /* Get L3 IPv4 forwarding enable bit. */ 197 if (SOC_MEM_FIELD_VALID(unit, mem, V4L3_ENABLEf)) { 198 if (soc_mem_field32_get(unit, mem, &ptab_entry, V4L3_ENABLEf)) { 199 port_cfg->pc_l3_flags |= BCM_PORT_L3_V4_ENABLE; 200 } 201 } 202 203 /* Get L3 IPv6 forwarding enable bit. */ 204 if (SOC_MEM_FIELD_VALID(unit, mem, V6L3_ENABLEf)) { 205 if (soc_mem_field32_get(unit, mem, &ptab_entry, V6L3_ENABLEf)) { 206 port_cfg->pc_l3_flags |= BCM_PORT_L3_V6_ENABLE; 207 } 208 } 209 210 /* Get port default priority.*/ 211 if (soc_feature(unit, soc_feature_vlan_pri_cfi_action)) { 212 port_cfg->pc_new_opri = 213 soc_mem_field32_get(unit, mem, &ptab_entry, OPRIf); 214 port_cfg->pc_new_ocfi = 215 soc_mem_field32_get(unit, mem, &ptab_entry, OCFIf); 216 if (SOC_MEM_FIELD_VALID(unit, mem, IPRIf)) { 217 port_cfg->pc_new_ipri = 218 soc_mem_field32_get(unit, mem, &ptab_entry, IPRIf); 219 } 220 if (SOC_MEM_FIELD_VALID(unit, mem, ICFIf)) { 221 port_cfg->pc_new_icfi = 222 soc_mem_field32_get(unit, mem, &ptab_entry, ICFIf); 223 } 224 } else { 225 port_cfg->pc_new_opri = 226 soc_mem_field32_get(unit, mem, &ptab_entry, PORT_PRIf); 227 } 228 229 /* Get incoming packet overwrite/map priority. */ 230 if (SOC_MEM_FIELD_VALID(unit, mem, MAP_TAG_PKT_PRIORITYf)) { 231 port_cfg->pc_remap_pri_en = 232 soc_mem_field32_get(unit, mem, &ptab_entry, MAP_TAG_PKT_PRIORITYf); 233 } else { 234 port_cfg->pc_remap_pri_en = 0; 235 } 236 237 /* Get ingress port is trusted port, trust incoming IPv4 DSCP bit. */ 238 if (SOC_MEM_FIELD_VALID(unit, mem, TRUST_DSCP_V4f)) { 239 port_cfg->pc_dse_mode = 240 soc_mem_field32_get(unit, mem, &ptab_entry, TRUST_DSCP_V4f); 241 } 242 243 /* Get ingress port is trusted port, trust incoming IPv6 DSCP bit. */ 244 if (SOC_MEM_FIELD_VALID(unit, mem, TRUST_DSCP_V6f)) { 245 port_cfg->pc_dse_mode_ipv6 = 246 soc_mem_field32_get(unit, mem, &ptab_entry, TRUST_DSCP_V6f); 247 } 248 249 port_cfg->pc_dscp_prio = (port_cfg->pc_dse_mode | 250 port_cfg->pc_dse_mode_ipv6); 251 port_cfg->pc_dscp = -1; 252 253 /* Get enable ingress filtering bit. */ 254 port_cfg->pc_en_ifilter = 255 soc_mem_field32_get(unit, mem, &ptab_entry, EN_IFILTERf); 256 257 /* Get enable L2 bridging on the incoming port. */ 258 if (SOC_MEM_FIELD_VALID(unit, mem, PORT_BRIDGEf)) { 259 port_cfg->pc_bridge_port = 260 soc_mem_field32_get(unit, mem, &ptab_entry, PORT_BRIDGEf); 261 } 262 263 /* Get network to network port flag. (QinQ) */ 264 if (SOC_MEM_FIELD_VALID(unit, mem, NNI_PORTf)) { 265 port_cfg->pc_nni_port = 266 soc_mem_field32_get(unit, mem, &ptab_entry, NNI_PORTf); 267 } 268 #if defined(BCM_TRX_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT) 269 /* Unicast rpf mode. */ 270 if (SOC_MEM_FIELD_VALID(unit, mem, URPF_MODEf)) { 271 port_cfg->pc_urpf_mode = soc_mem_field32_get(unit, mem, &ptab_entry, 272 URPF_MODEf); 273 } 274 275 /* Unicast rpf default gateway check. */ 276 if (SOC_MEM_FIELD_VALID(unit, mem, URPF_DEFAULTROUTECHECKf)) { 277 port_cfg->pc_urpf_def_gw_check = 278 soc_mem_field32_get(unit, mem, &ptab_entry, URPF_DEFAULTROUTECHECKf); 279 } 280 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT */ 281 #if defined(BCM_TRX_SUPPORT) 282 /* private VALN enable */ 283 if (SOC_MEM_FIELD_VALID(unit, mem, PVLAN_ENABLEf)) { 284 port_cfg->pc_pvlan_enable = soc_mem_field32_get(unit, mem, &ptab_entry, 285 PVLAN_ENABLEf); 286 } 287 288 /* Get enable mirroring destination 2 flag. */ 289 if (SOC_MEM_FIELD_VALID(unit, mem, MIRROR1f)) { 290 if (soc_mem_field32_get(unit, mem, &ptab_entry, MIRROR1f)) { 291 port_cfg->pc_mirror_ing |= BCM_MIRROR_MTP_TWO; 292 } 293 } 294 #endif /* BCM_TRX_SUPPORT */ 295 296 return (BCM_E_NONE); 297 } 298 299 /* 300 * Function: 301 * _bcm_xgs3_port_table_write 302 * Purpose: 303 * Prepare & write port table entry 304 * Parameters: 305 * unit - (IN)SOC unit number. 306 * port - (IN)Port number. 307 * port_cfg - (IN)API port information structure. 308 * Returns: 309 * BCM_E_XXX 310 */ 311 STATIC int 312 _bcm_xgs3_port_table_write(int unit, bcm_port_t port, 313 bcm_port_cfg_t *port_cfg) 314 { 315 int cml; /* CPU managed learning mode. */ 316 int repl_cml, repl_cml_move; /* CPU managed learning mode. */ 317 #ifdef BCM_TRX_SUPPORT 318 int cml_move; /* CPU managed learning mode. */ 319 #endif 320 321 port_tab_entry_t ptab_entry; /* Port table entry. */ 322 soc_mem_t mem = PORT_TABm; /* Port table memory. */ 323 int tbl_index = port; /* Port table index. */ 324 int rv; 325 int cpu_hg_index = 0; 326 327 if (BCM_GPORT_IS_SET(port)) { 328 BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, port, &port)); 329 } 330 tbl_index = port; 331 332 #if defined(BCM_TRIDENT3_SUPPORT) 333 if (SOC_MEM_IS_VALID(unit, ING_DEVICE_PORTm)) { 334 mem = ING_DEVICE_PORTm; 335 } 336 #endif 337 338 soc_mem_lock(unit, mem); /* Lock port table */ 339 340 /* Read current port table entry from HW. */ 341 rv = BCM_XGS3_MEM_READ(unit, mem, tbl_index, &ptab_entry); 342 if (BCM_FAILURE(rv)) { 343 soc_mem_unlock(unit, mem); 344 return rv; 345 } 346 /* Set drop all tagged/untagged packets flag. */ 347 switch (port_cfg->pc_disc) { 348 case BCM_PORT_DISCARD_NONE: 349 soc_mem_field32_set(unit, mem, &ptab_entry, PORT_DIS_TAGf, 0); 350 soc_mem_field32_set(unit, mem, &ptab_entry, PORT_DIS_UNTAGf, 0); 351 break; 352 case BCM_PORT_DISCARD_ALL: 353 soc_mem_field32_set(unit, mem, &ptab_entry, PORT_DIS_TAGf, 1); 354 soc_mem_field32_set(unit, mem, &ptab_entry, PORT_DIS_UNTAGf, 1); 355 break; 356 case BCM_PORT_DISCARD_UNTAG: 357 soc_mem_field32_set(unit, mem, &ptab_entry, PORT_DIS_TAGf, 0); 358 soc_mem_field32_set(unit, mem, &ptab_entry, PORT_DIS_UNTAGf, 1); 359 break; 360 case BCM_PORT_DISCARD_TAG: 361 soc_mem_field32_set(unit, mem, &ptab_entry, PORT_DIS_TAGf, 1); 362 soc_mem_field32_set(unit, mem, &ptab_entry, PORT_DIS_UNTAGf, 0); 363 break; 364 } 365 366 /* Set drop bpdu's on ingress flag. */ 367 soc_mem_field32_set(unit, mem, &ptab_entry, DROP_BPDUf, 368 port_cfg->pc_bpdu_disable); 369 370 /* Set ingress mirroring flag. */ 371 if (soc_feature(unit, soc_feature_mirror_flexible)) { 372 soc_mem_field32_set(unit, mem, &ptab_entry, MIRRORf, 373 (port_cfg->pc_mirror_ing & BCM_TR2_MIRROR_MTP_MASK)); 374 } else if (!soc_feature(unit, soc_feature_no_mirror)) { 375 soc_mem_field32_set(unit, mem, &ptab_entry, MIRRORf, 376 (port_cfg->pc_mirror_ing & BCM_MIRROR_MTP_ONE)); 377 } 378 379 /* 380 * Set cpu managed learning (cml). 381 * if unit is not frozen set the same value to port table. 382 * else set port table (cml) to PVP_CML_FORWARD. 383 */ 384 if (soc_l2x_frozen_cml_set(unit, port, port_cfg->pc_cml, 385 port_cfg->pc_cml_move, &repl_cml, &repl_cml_move) < 0) { 386 cml = port_cfg->pc_cml; 387 #ifdef BCM_TRX_SUPPORT 388 cml_move = port_cfg->pc_cml_move; 389 #endif 390 } else { 391 cml = repl_cml; 392 #ifdef BCM_TRX_SUPPORT 393 cml_move = repl_cml_move; 394 #endif 395 } 396 397 #ifdef BCM_TRX_SUPPORT 398 if (SOC_IS_TRX(unit)) { 399 if (SOC_MEM_FIELD_VALID(unit, mem, CML_FLAGS_NEWf)) { 400 soc_mem_field32_set(unit, mem, &ptab_entry, CML_FLAGS_MOVEf, cml_move); 401 soc_mem_field32_set(unit, mem, &ptab_entry, CML_FLAGS_NEWf, cml); 402 } 403 if (SOC_MEM_FIELD_VALID(unit, mem, IVIDf)) { 404 soc_mem_field32_set(unit, mem, &ptab_entry, IVIDf, port_cfg->pc_ivlan); 405 } 406 soc_mem_field32_set(unit, mem, &ptab_entry, TAG_ACTION_PROFILE_PTRf, 407 port_cfg->pc_vlan_action); 408 } else 409 #endif /* BCM_TRX_SUPPORT */ 410 { 411 soc_mem_field32_set(unit, mem, &ptab_entry, CMLf, cml); 412 } 413 414 /* Set port default vlan id (pvid). */ 415 soc_mem_field32_set(unit, mem, &ptab_entry, PORT_VIDf, port_cfg->pc_vlan); 416 417 /* Set L3 IPv4 forwarding enable bit. */ 418 if (SOC_MEM_FIELD_VALID(unit, mem, V4L3_ENABLEf)) { 419 soc_mem_field32_set(unit, mem, &ptab_entry, V4L3_ENABLEf, 420 (port_cfg->pc_l3_flags & BCM_PORT_L3_V4_ENABLE) ? 1 : 0); 421 } 422 423 /* Set L3 IPv6 forwarding enable bit. */ 424 if (SOC_MEM_FIELD_VALID(unit, mem, V6L3_ENABLEf)) { 425 soc_mem_field32_set(unit, mem, &ptab_entry, V6L3_ENABLEf, 426 (port_cfg->pc_l3_flags & BCM_PORT_L3_V6_ENABLE) ? 1 : 0); 427 } 428 429 /* Set new port default priority.*/ 430 if (soc_feature(unit, soc_feature_vlan_pri_cfi_action)) { 431 soc_mem_field32_set(unit, mem, &ptab_entry, PORT_PRIf, 432 port_cfg->pc_new_opri); 433 soc_mem_field32_set(unit, mem, &ptab_entry, OCFIf, 434 port_cfg->pc_new_ocfi); 435 if (SOC_MEM_FIELD_VALID(unit, mem, IPRIf)) { 436 soc_mem_field32_set(unit, mem, &ptab_entry, IPRIf, 437 port_cfg->pc_new_ipri); 438 } 439 if (SOC_MEM_FIELD_VALID(unit, mem, ICFIf)) { 440 soc_mem_field32_set(unit, mem, &ptab_entry, ICFIf, 441 port_cfg->pc_new_icfi); 442 } 443 } else { 444 soc_mem_field32_set(unit, mem, &ptab_entry, PORT_PRIf, 445 port_cfg->pc_new_opri); 446 } 447 448 /* Set incoming packet overwrite/map priority. */ 449 if (SOC_MEM_FIELD_VALID(unit, mem, MAP_TAG_PKT_PRIORITYf)) { 450 soc_mem_field32_set(unit, mem, &ptab_entry, MAP_TAG_PKT_PRIORITYf, 451 port_cfg->pc_remap_pri_en); 452 } 453 454 /* Set ingress port is trusted port, trust incoming IPv4 DSCP bit. */ 455 if (SOC_MEM_FIELD_VALID(unit, mem, TRUST_DSCP_V4f)) { 456 soc_mem_field32_set(unit, mem, &ptab_entry, TRUST_DSCP_V4f, 457 port_cfg->pc_dse_mode ? 1 : 0); 458 } 459 460 /* Set ingress port is trusted port, trust incoming IPv6 DSCP bit. */ 461 if (SOC_MEM_FIELD_VALID(unit, mem, TRUST_DSCP_V6f)) { 462 soc_mem_field32_set(unit, mem, &ptab_entry, TRUST_DSCP_V6f, 463 port_cfg->pc_dse_mode_ipv6 ? 1 : 0); 464 } 465 466 /* Set enable ingress filtering. */ 467 soc_mem_field32_set(unit, mem, &ptab_entry, EN_IFILTERf, 468 port_cfg->pc_en_ifilter); 469 470 /* Set enable ingress filtering. */ 471 if (SOC_MEM_FIELD_VALID(unit, mem, PORT_BRIDGEf)) { 472 soc_mem_field32_set(unit, mem, &ptab_entry, PORT_BRIDGEf, 473 port_cfg->pc_bridge_port); 474 } 475 476 if (SOC_MEM_FIELD_VALID(unit, mem, NNI_PORTf)) { 477 /* Set network to network port flag. */ 478 soc_mem_field32_set(unit, mem, &ptab_entry, NNI_PORTf, 479 port_cfg->pc_nni_port); 480 } 481 482 #if defined(BCM_TRX_SUPPORT) || defined(BCM_FIREBOLT2_SUPPORT) 483 /* Unicast rpf mode. */ 484 if (SOC_MEM_FIELD_VALID(unit, mem, URPF_MODEf)) { 485 soc_mem_field32_set(unit, mem, &ptab_entry, URPF_MODEf, 486 port_cfg->pc_urpf_mode); 487 } 488 489 /* Unicast rpf default gateway check. */ 490 if (SOC_MEM_FIELD_VALID(unit, mem, URPF_DEFAULTROUTECHECKf)) { 491 soc_mem_field32_set(unit, mem, &ptab_entry, URPF_DEFAULTROUTECHECKf, 492 port_cfg->pc_urpf_def_gw_check); 493 } 494 #endif /* BCM_TRX_SUPPORT || BCM_FIREBOLT2_SUPPORT */ 495 #if defined(BCM_TRX_SUPPORT) 496 /* private VALN enable */ 497 if (SOC_MEM_FIELD_VALID(unit, mem, PVLAN_ENABLEf)) { 498 soc_mem_field32_set(unit, mem, &ptab_entry, PVLAN_ENABLEf, 499 port_cfg->pc_pvlan_enable); 500 } 501 502 /* Set ingress mirroring destination 2 enable flag. */ 503 if (SOC_MEM_FIELD_VALID(unit, mem, MIRROR1f)) { 504 soc_mem_field32_set(unit, mem, &ptab_entry, MIRROR1f, 505 ((port_cfg->pc_mirror_ing & BCM_MIRROR_MTP_TWO) ? 1 : 0)); 506 507 } 508 #endif /* BCM_TRX_SUPPORT */ 509 510 /* Write entry to hw. */ 511 rv = BCM_XGS3_MEM_WRITE(unit, mem, tbl_index, &ptab_entry); 512 if (BCM_FAILURE(rv)) { 513 soc_mem_unlock(unit, mem); 514 return rv; 515 } 516 517 /* 518 * Set config to IPORT_TABLEm for the CPU port. 519 * IPORT table's higig_packet field must be 1. 520 */ 521 cpu_hg_index = SOC_IS_KATANA2(unit) ? 522 SOC_INFO(unit).cpu_hg_pp_port_index : 523 SOC_INFO(unit).cpu_hg_index; 524 if (IS_CPU_PORT(unit, port)) { 525 int value = 0; 526 soc_mem_t cpu_hg_mem = INVALIDm; 527 port_tab_entry_t iptab_entry; 528 if (SOC_MEM_FIELD_VALID(unit, mem, HIGIG_PACKETf)) { 529 soc_mem_field32_set(unit, mem, &ptab_entry, HIGIG_PACKETf, 1); 530 } else if (SOC_MEM_FIELD_VALID(unit, mem, PORT_TYPEf)) { 531 soc_mem_field32_set(unit, mem, &ptab_entry, PORT_TYPEf, 1); 532 } 533 534 if (SOC_MEM_IS_VALID(unit, IPORT_TABLEm)) { 535 cpu_hg_mem = IPORT_TABLEm; 536 tbl_index = port; 537 } else if (cpu_hg_index != -1) { 538 cpu_hg_mem = mem; 539 tbl_index = cpu_hg_index; 540 } 541 542 if(cpu_hg_mem != INVALIDm) { 543 rv = soc_mem_read(unit, cpu_hg_mem, MEM_BLOCK_ANY, tbl_index, &iptab_entry); 544 if (BCM_FAILURE(rv)) { 545 soc_mem_unlock(unit, mem); 546 return rv; 547 } 548 549 if (SOC_MEM_FIELD_VALID(unit, cpu_hg_mem, DISABLE_VLAN_CHECKSf)) { 550 value = soc_mem_field32_get(unit, cpu_hg_mem, &iptab_entry, DISABLE_VLAN_CHECKSf); 551 soc_mem_field32_set(unit, cpu_hg_mem, &ptab_entry, DISABLE_VLAN_CHECKSf, value); 552 } 553 554 /* 555 * If other fields like DISABLE_VLAN_CHECKSf, add to here. 556 */ 557 rv = soc_mem_write(unit, cpu_hg_mem, MEM_BLOCK_ALL, tbl_index, &ptab_entry); 558 if (BCM_FAILURE(rv)) { 559 soc_mem_unlock(unit, mem); 560 return rv; 561 } 562 } 563 } 564 565 soc_mem_unlock(unit, mem); /* Unlock port table */ 566 567 return BCM_E_NONE; 568 } 569 570 /* 571 * Function: 572 * _bcm_xgs3_trunk_table_read 573 * Purpose: 574 * Read trunk table entry and parse it to common 575 * (bcm_port_cfg_t) structure. 576 * Parameters: 577 * unit - (IN)SOC unit number. 578 * port - (IN)Port number. 579 * tid - (OUT)Trunk group ID. 580 * Returns: 581 * BCM_E_XXX 582 */ 583 int 584 _bcm_xgs3_trunk_table_read(int unit, bcm_port_t port, int *tid) 585 { 586 int my_modid; 587 int src_trk_idx = 0; /*Source Trunk table index.*/ 588 source_trunk_map_table_entry_t trunk_map_entry;/*Trunk table entry buffer.*/ 589 soc_field_t tgid_fld = TGIDf; 590 591 if (SOC_MEM_FIELD_VALID(unit, SOURCE_TRUNK_MAP_TABLEm, SRC_TGIDf)) { 592 tgid_fld = SRC_TGIDf; 593 } 594 595 /* Get module id for unit. */ 596 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 597 598 /* Get index to source trunk map table */ 599 BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, my_modid, 600 port, &src_trk_idx)); 601 602 /* Read source trunk map table. */ 603 SOC_IF_ERROR_RETURN (BCM_XGS3_MEM_READ(unit, SOURCE_TRUNK_MAP_TABLEm, 604 src_trk_idx, &trunk_map_entry)); 605 606 /* Get trunk group id. */ 607 *tid = 0; 608 if (1 == soc_mem_field32_get(unit, SOURCE_TRUNK_MAP_TABLEm, 609 &trunk_map_entry, PORT_TYPEf)) { 610 *tid = soc_mem_field32_get(unit, SOURCE_TRUNK_MAP_TABLEm, 611 &trunk_map_entry, tgid_fld); 612 } 613 614 return (BCM_E_NONE); 615 } 616 617 /* 618 * Function: 619 * _bcm_xgs3_trunk_table_write 620 * Purpose: 621 * Write trunk table entry. 622 * Parameters: 623 * unit - (IN)SOC unit number. 624 * port - (IN)Port number. 625 * tid - (IN)Trunk group ID. 626 * Returns: 627 * BCM_E_XXX 628 */ 629 int 630 _bcm_xgs3_trunk_table_write(int unit, bcm_port_t port, int tid) 631 { 632 int rv; 633 int tgid; 634 int port_type; 635 int my_modid; 636 int src_trk_idx = 0; /*Source Trunk table index.*/ 637 source_trunk_map_table_entry_t trunk_map_entry;/*Trunk table entry buffer.*/ 638 soc_field_t tgid_fld = TGIDf; 639 640 if (SOC_MEM_FIELD_VALID(unit, SOURCE_TRUNK_MAP_TABLEm, SRC_TGIDf)) { 641 tgid_fld = SRC_TGIDf; 642 } 643 644 if (tid != BCM_TRUNK_INVALID) { 645 tgid = tid; 646 port_type = 1; 647 } else { 648 tgid = 0; 649 port_type = 0; 650 } 651 652 /* Get module id for unit. */ 653 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 654 655 /* Get index to source trunk map table */ 656 BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, my_modid, 657 port, &src_trk_idx)); 658 659 soc_mem_lock(unit, SOURCE_TRUNK_MAP_TABLEm); 660 661 /* Read source trunk map table. */ 662 rv = BCM_XGS3_MEM_READ(unit, SOURCE_TRUNK_MAP_TABLEm, 663 src_trk_idx, &trunk_map_entry); 664 if (BCM_FAILURE(rv)) { 665 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 666 return rv; 667 } 668 669 /* Set trunk group id. */ 670 soc_mem_field32_set(unit, SOURCE_TRUNK_MAP_TABLEm, &trunk_map_entry, 671 tgid_fld, tgid); 672 673 /* Set port is part of trunk flag. */ 674 soc_mem_field32_set(unit, SOURCE_TRUNK_MAP_TABLEm, &trunk_map_entry, 675 PORT_TYPEf, port_type); 676 677 /* Write entry to hw. */ 678 rv = BCM_XGS3_MEM_WRITE(unit, SOURCE_TRUNK_MAP_TABLEm, 679 src_trk_idx, &trunk_map_entry); 680 681 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 682 683 return rv; 684 } 685 686 #ifdef BCM_FIREBOLT_SUPPORT 687 /* 688 * Function: 689 * _bcm_fb_port_cfg_init 690 * Purpose: 691 * Initialize port configuration according to Initial System 692 * Configuration (see init.c) 693 * Parameters: 694 * unit - (IN)StrataSwitch unit number. 695 * port - (IN)Port number. 696 * vlan_data - (IN)Initial VLAN data information 697 * Returns: 698 * BCM_E_XXX 699 */ 700 int 701 _bcm_fb_port_cfg_init(int unit, bcm_port_t port, bcm_vlan_data_t *vlan_data) 702 { 703 port_tab_entry_t ptab; /* Port table entry. */ 704 soc_field_t field_ids[SOC_MAX_MEM_FIELD_WORDS], port_type_field; 705 uint32 field_values[SOC_MAX_MEM_FIELD_WORDS], port_type; 706 soc_field_t lp_field_ids[SOC_MAX_MEM_FIELD_WORDS]; 707 uint32 lp_field_values[SOC_MAX_MEM_FIELD_WORDS]; 708 soc_reg_t egr_port_reg = EGR_PORTr; 709 soc_reg_t iegr_port_reg = IEGR_PORTr; 710 int field_count; 711 int lp_field_count = 0; 712 int cpu_hg_index = 0; 713 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT) 714 int rtag7_profile_idx = 0; 715 #endif /* BCM_TRIDENT2PLUS_SUPPORT || BCM_GREYHOUND2_SUPPORT */ 716 #ifdef BCM_TRX_SUPPORT 717 int key_type_value; 718 #endif 719 soc_mem_t mem = PORT_TABm; 720 int rv = BCM_E_NONE; 721 722 #ifdef BCM_TRIUMPH_SUPPORT 723 int dual_modid = 0; 724 725 if ((SOC_IS_TR_VL(unit)) && (NUM_MODID(unit) >= 2)) { 726 dual_modid = 1; 727 } 728 729 if (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 730 SOC_IS_VALKYRIE2(unit) || SOC_IS_GREYHOUND(unit) || 731 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 732 egr_port_reg = EGR_PORT_64r; 733 iegr_port_reg = IEGR_PORT_64r; 734 } 735 #endif 736 737 if (SOC_MEM_IS_VALID(unit, ING_DEVICE_PORTm)) { 738 mem = ING_DEVICE_PORTm; 739 } 740 741 if (SOC_MEM_FIELD_VALID(unit, mem, PORT_TYPEf)) { 742 port_type_field = PORT_TYPEf; 743 } else { 744 port_type_field = HIGIG_PACKETf; 745 } 746 747 if (IS_ST_PORT(unit, port)) { 748 port_type = 1; 749 } else if (IS_LB_PORT(unit, port)) { 750 port_type = 2; 751 } else { 752 port_type = 0; 753 } 754 755 field_ids[0] = port_type_field; 756 field_values[0] = port_type; 757 field_ids[1] = EN_EFILTERf; 758 field_values[1] = 1; 759 field_count = 2; 760 761 #ifdef BCM_TRIUMPH_SUPPORT 762 if (SOC_IS_TR_VL(unit)) { 763 /* Enable/disable dual-modid */ 764 if (soc_reg_field_valid(unit, egr_port_reg, DUAL_MODID_ENABLEf)) { 765 field_ids[field_count] = DUAL_MODID_ENABLEf; 766 field_values[field_count] = dual_modid; 767 field_count++; 768 } else if (SOC_MEM_FIELD_VALID(unit, EGR_PORTm, DUAL_MODID_ENABLEf)) { 769 BCM_IF_ERROR_RETURN 770 (soc_mem_field32_modify(unit, EGR_PORTm, port, DUAL_MODID_ENABLEf, 771 dual_modid)); 772 } 773 if (IS_XE_PORT(unit, port)) { 774 if (soc_reg_field_valid(unit, XMODID_DUAL_ENr, DUAL_MODID_ENf)) { 775 BCM_IF_ERROR_RETURN 776 (soc_reg_field32_modify(unit, XMODID_DUAL_ENr, port, 777 DUAL_MODID_ENf, dual_modid)); 778 } else if (soc_reg_field_valid(unit, XMODID_ENr, DUAL_MODID_ENf)) { 779 BCM_IF_ERROR_RETURN 780 (soc_reg_field32_modify(unit, XMODID_ENr, port, 781 DUAL_MODID_ENf, dual_modid)); 782 } 783 } 784 785 #ifdef BCM_MONTEREY_SUPPORT 786 if (SOC_IS_MONTEREY(unit)) { 787 if (port < 67) { 788 BCM_IF_ERROR_RETURN 789 (soc_mem_field32_modify(unit, EGR_PORTm, port, MISC_PORT_PROFILE_INDEXf, 790 port)); 791 BCM_IF_ERROR_RETURN 792 (soc_mem_field32_modify(unit, EGR_LPORT_PROFILEm, port + 1, 793 MISC_PORT_PROFILE_INDEXf, port)); 794 BCM_IF_ERROR_RETURN 795 (soc_mem_field32_modify(unit, EGR_LPORT_PROFILEm, port + 1, 796 EN_EFILTERf, 1)); 797 } 798 } 799 #endif 800 801 } 802 #endif 803 #ifdef BCM_TRX_SUPPORT 804 if (SOC_IS_TRX(unit) && !SOC_IS_TOMAHAWK3(unit)) { 805 /* Initialize egress vlan translation port class with identity mapping */ 806 field_ids[field_count] = VT_PORT_GROUP_IDf; 807 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) { 808 uint32 gid; 809 uint32 max_gid; 810 811 /* VT_PORT_GROUP_IDf cannot fit entire valid port number. 812 * any port number greater than max group id 813 * will be set as max group id. 814 */ 815 max_gid = soc_mem_field_length(unit, EGR_PORTm, 816 VT_PORT_GROUP_IDf); 817 if (max_gid > 31) { 818 return BCM_E_INTERNAL; 819 } 820 max_gid = (1 << max_gid) - 1; 821 if (port < max_gid) { 822 gid = port; 823 } else { 824 gid = max_gid; 825 } 826 field_values[field_count] = gid; 827 } else { 828 field_values[field_count] = port; 829 } 830 field_count++; 831 } 832 #endif 833 834 #if defined(BCM_RAPTOR_SUPPORT) || defined(BCM_TRIDENT_SUPPORT) 835 /* For some devices, directed mirroring will always be 1 */ 836 if (soc_feature(unit, soc_feature_directed_mirror_only)) { 837 field_ids[field_count] = EM_SRCMOD_CHANGEf; 838 field_values[field_count] = 1; 839 field_count++; 840 } 841 #endif 842 843 #ifdef BCM_SHADOW_SUPPORT 844 /* EGR_PORT fields are Unsupported in shadow */ 845 if (SOC_IS_SHADOW(unit)) { 846 field_count = 0; 847 } 848 #endif 849 850 if (SOC_MEM_IS_VALID(unit, EGR_PORTm)) { 851 BCM_IF_ERROR_RETURN 852 (soc_mem_fields32_modify(unit, EGR_PORTm, port, field_count, 853 field_ids, field_values)); 854 } else { 855 /* Update EGR_PORTr register. */ 856 BCM_IF_ERROR_RETURN 857 (soc_reg_fields32_modify(unit, egr_port_reg, port, field_count, 858 field_ids, field_values)); 859 } 860 861 #define LPORT_TAB_SYNC(_u_, _p_, _fld_, _val_) \ 862 { \ 863 if (!IS_CPU_PORT(_u_, _p_)) { \ 864 if (SOC_IS_TOMAHAWKX(_u_) || \ 865 SOC_IS_TD2P_TT2P(_u_)) { \ 866 if (SOC_MEM_IS_VALID(_u_, LPORT_TABm)) { \ 867 lp_field_ids[lp_field_count] = _fld_; \ 868 lp_field_values[lp_field_count] = _val_; \ 869 lp_field_count ++; \ 870 } \ 871 } \ 872 } \ 873 } \ 874 875 /* Write PORT_TABm memory */ 876 sal_memcpy(&ptab, soc_mem_entry_null(unit, mem), sizeof (ptab)); 877 878 /* Set default vlan id(pvid) for port. */ 879 soc_mem_field32_set(unit, mem, &ptab, PORT_VIDf, vlan_data->vlan_tag); 880 LPORT_TAB_SYNC(unit, port, PORT_VIDf, vlan_data->vlan_tag); 881 882 /* Switching VLAN. */ 883 if (SOC_MEM_FIELD_VALID(unit, mem, OUTER_TPIDf)) { 884 soc_mem_field32_set(unit, mem, &ptab, OUTER_TPIDf, 0x8100); 885 LPORT_TAB_SYNC(unit, port, OUTER_TPIDf, 0x8100); 886 } 887 888 /* Enable mac based vlan classification. */ 889 if (SOC_MEM_FIELD_VALID(unit, mem, MAC_BASED_VID_ENABLEf)) { 890 soc_mem_field32_set(unit, mem, &ptab, MAC_BASED_VID_ENABLEf, 1); 891 LPORT_TAB_SYNC(unit, port, MAC_BASED_VID_ENABLEf, 1); 892 } 893 894 /* Enable subned based vlan classification. */ 895 if (SOC_MEM_FIELD_VALID(unit, mem, SUBNET_BASED_VID_ENABLEf)) { 896 soc_mem_field32_set(unit, mem, &ptab, SUBNET_BASED_VID_ENABLEf, 1); 897 LPORT_TAB_SYNC(unit, port, SUBNET_BASED_VID_ENABLEf, 1); 898 } 899 900 /* Set port type. */ 901 soc_mem_field32_set(unit, mem, &ptab, port_type_field, port_type); 902 LPORT_TAB_SYNC(unit, port, port_type_field, port_type); 903 904 #if defined(BCM_RAVEN_SUPPORT) || defined(BCM_TRX_SUPPORT) 905 if (SOC_MEM_FIELD_VALID(unit, mem, TRUST_INCOMING_VIDf)) { 906 soc_mem_field32_set(unit, mem, &ptab, TRUST_INCOMING_VIDf, 1); 907 LPORT_TAB_SYNC(unit, port, TRUST_INCOMING_VIDf, 1); 908 } 909 #endif /* BCM_RAVEN_SUPPORT || BCM_TRX_SUPPORT */ 910 911 #ifdef BCM_TRX_SUPPORT 912 /* Set identify mapping for pri/cfi re-mapping */ 913 if (SOC_MEM_FIELD_VALID(unit, mem, PRI_MAPPINGf)) { 914 soc_mem_field32_set(unit, mem, &ptab, PRI_MAPPINGf, 0xfac688); 915 LPORT_TAB_SYNC(unit, port, PRI_MAPPINGf, 0xfac688); 916 soc_mem_field32_set(unit, mem, &ptab, CFI_0_MAPPINGf, 0); 917 LPORT_TAB_SYNC(unit, port, CFI_0_MAPPINGf, 0); 918 soc_mem_field32_set(unit, mem, &ptab, CFI_1_MAPPINGf, 1); 919 LPORT_TAB_SYNC(unit, port, CFI_1_MAPPINGf, 1); 920 } 921 922 #if defined(BCM_KATANA_SUPPORT) || defined(BCM_TRIUMPH3_SUPPORT) 923 /* Set identify mapping for ipri/icfi re-mapping */ 924 if (SOC_MEM_FIELD_VALID(unit, mem, IPRI_MAPPINGf)) { 925 soc_mem_field32_set(unit, mem, &ptab, IPRI_MAPPINGf, 0xfac688); 926 soc_mem_field32_set(unit, mem, &ptab, ICFI_0_MAPPINGf, 0); 927 soc_mem_field32_set(unit, mem, &ptab, ICFI_1_MAPPINGf, 1); 928 } 929 #endif 930 931 /* Set the CML to PVP_CML_SWITCH by default (hw learn and forward) */ 932 if (SOC_MEM_FIELD_VALID(unit, mem, CML_FLAGS_NEWf)) { 933 soc_mem_field32_set(unit, mem, &ptab, CML_FLAGS_NEWf, 0x8); 934 LPORT_TAB_SYNC(unit, port, CML_FLAGS_NEWf, 0x8); 935 soc_mem_field32_set(unit, mem, &ptab, CML_FLAGS_MOVEf, 0x8); 936 LPORT_TAB_SYNC(unit, port, CML_FLAGS_MOVEf, 0x8); 937 } 938 939 /* Set first VLAN_XLATE key-type to {outer,port}. 940 * Set second VLAN_XLATE key-type to {inner,port}. 941 */ 942 if (SOC_MEM_FIELD_VALID(unit, mem, VT_KEY_TYPEf)) { 943 BCM_IF_ERROR_RETURN 944 (_bcm_esw_pt_vtkey_type_value_get(unit, 945 VLXLT_HASH_KEY_TYPE_OVID,&key_type_value)); 946 soc_mem_field32_set(unit, mem, &ptab, VT_KEY_TYPEf, 947 key_type_value); 948 #if defined(BCM_GREYHOUND2_SUPPORT) 949 if (soc_feature(unit, soc_feature_vxlan_lite_riot)) { 950 if (!IS_CPU_PORT(unit, port)) { 951 lp_field_ids[lp_field_count] = VT_KEY_TYPEf; 952 lp_field_values[lp_field_count] = key_type_value; 953 lp_field_count++; 954 } 955 } else 956 #endif /* BCM_GREYHOUND2_SUPPORT */ 957 { 958 LPORT_TAB_SYNC(unit, port, VT_KEY_TYPEf, key_type_value); 959 } 960 961 if (SOC_IS_KATANA(unit)) { 962 BCM_IF_ERROR_RETURN 963 (_bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_NONE, 964 VT_KEY_TYPEf, key_type_value)); 965 966 } 967 } 968 if (SOC_MEM_FIELD_VALID(unit, mem, VT_KEY_TYPE_USE_GLPf)) { 969 soc_mem_field32_set(unit, mem, &ptab, VT_KEY_TYPE_USE_GLPf, 1); 970 #if defined(BCM_GREYHOUND2_SUPPORT) 971 if (soc_feature(unit, soc_feature_vxlan_lite_riot)) { 972 if (!IS_CPU_PORT(unit, port)) { 973 lp_field_ids[lp_field_count] = VT_KEY_TYPE_USE_GLPf; 974 lp_field_values[lp_field_count] = 1; 975 lp_field_count++; 976 } 977 } else 978 #endif /* BCM_GREYHOUND2_SUPPORT */ 979 { 980 LPORT_TAB_SYNC(unit, port, VT_KEY_TYPE_USE_GLPf, 1); 981 } 982 983 if (SOC_IS_KATANA(unit)) { 984 BCM_IF_ERROR_RETURN 985 (_bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_NONE, 986 VT_KEY_TYPE_USE_GLPf, 1)); 987 } 988 } 989 if (SOC_MEM_FIELD_VALID(unit, mem, VT_PORT_TYPE_SELECTf)) { 990 soc_mem_field32_set(unit, mem, &ptab, VT_PORT_TYPE_SELECTf, 1); 991 LPORT_TAB_SYNC(unit, port, VT_PORT_TYPE_SELECTf, 1); 992 } 993 if (SOC_MEM_FIELD_VALID(unit, mem, VT_KEY_TYPE_2f)) { 994 BCM_IF_ERROR_RETURN 995 (_bcm_esw_pt_vtkey_type_value_get(unit, 996 VLXLT_HASH_KEY_TYPE_IVID,&key_type_value)); 997 soc_mem_field32_set(unit, mem, &ptab, VT_KEY_TYPE_2f, 998 key_type_value); 999 #if defined(BCM_GREYHOUND2_SUPPORT) 1000 if (soc_feature(unit, soc_feature_vxlan_lite_riot)) { 1001 if (!IS_CPU_PORT(unit, port)) { 1002 lp_field_ids[lp_field_count] = VT_KEY_TYPE_2f; 1003 lp_field_values[lp_field_count] = key_type_value; 1004 lp_field_count++; 1005 } 1006 } else 1007 #endif /* BCM_GREYHOUND2_SUPPORT */ 1008 { 1009 LPORT_TAB_SYNC(unit, port, VT_KEY_TYPE_2f, key_type_value); 1010 } 1011 1012 if (SOC_IS_KATANA(unit)) { 1013 BCM_IF_ERROR_RETURN 1014 (_bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_NONE, 1015 VT_KEY_TYPE_2f, key_type_value)); 1016 } 1017 } 1018 if (SOC_MEM_FIELD_VALID(unit, mem, VT_KEY_TYPE_2_USE_GLPf)) { 1019 soc_mem_field32_set(unit, mem, &ptab, VT_KEY_TYPE_2_USE_GLPf, 1); 1020 #if defined(BCM_GREYHOUND2_SUPPORT) 1021 if (soc_feature(unit, soc_feature_vxlan_lite_riot)) { 1022 if (!IS_CPU_PORT(unit, port)) { 1023 lp_field_ids[lp_field_count] = VT_KEY_TYPE_2_USE_GLPf; 1024 lp_field_values[lp_field_count] = 1; 1025 lp_field_count++; 1026 } 1027 } else 1028 #endif /* BCM_GREYHOUND2_SUPPORT */ 1029 { 1030 LPORT_TAB_SYNC(unit, port, VT_KEY_TYPE_2_USE_GLPf, 1); 1031 } 1032 1033 if (SOC_IS_KATANA(unit)) { 1034 BCM_IF_ERROR_RETURN 1035 (_bcm_esw_port_tab_set(unit, port, _BCM_CPU_TABS_NONE, 1036 VT_KEY_TYPE_2_USE_GLPf, 1)); 1037 } 1038 } 1039 if (SOC_MEM_FIELD_VALID(unit, mem, VT_PORT_TYPE_SELECT_2f)) { 1040 soc_mem_field32_set(unit, mem, &ptab, VT_PORT_TYPE_SELECT_2f, 1); 1041 LPORT_TAB_SYNC(unit, port, VT_PORT_TYPE_SELECT_2f, 1); 1042 } 1043 1044 /* Trust the outer tag pri/cfi (to be backwards compatible) */ 1045 if (SOC_MEM_FIELD_VALID(unit, mem, TRUST_OUTER_DOT1Pf)) { 1046 soc_mem_field32_set(unit, mem, &ptab, TRUST_OUTER_DOT1Pf, 1); 1047 LPORT_TAB_SYNC(unit, port, TRUST_OUTER_DOT1Pf, 1); 1048 } 1049 1050 if (SOC_MEM_FIELD_VALID(unit, mem, SRC_SYS_PORT_IDf)) { 1051 soc_mem_field32_set(unit, mem, &ptab, SRC_SYS_PORT_IDf, port); 1052 LPORT_TAB_SYNC(unit, port, SRC_SYS_PORT_IDf, port); 1053 } 1054 1055 #ifdef BCM_TRIUMPH_SUPPORT 1056 if (SOC_IS_TR_VL(unit)) { 1057 if (SOC_MEM_FIELD_VALID(unit, mem, DUAL_MODID_ENABLEf)) { 1058 soc_mem_field32_set(unit, mem, &ptab, DUAL_MODID_ENABLEf, dual_modid); 1059 LPORT_TAB_SYNC(unit, port, DUAL_MODID_ENABLEf, dual_modid); 1060 } 1061 } 1062 #endif 1063 #endif 1064 1065 #ifdef BCM_RCPU_SUPPORT 1066 if (SOC_IS_RCPU_ONLY(unit) && 1067 SOC_MEM_FIELD_VALID(unit, mem, OUTER_TPID_ENABLEf)) { 1068 /* Required if rcpu vlan is not default vlan */ 1069 if (IS_CPU_PORT(unit,port) || IS_RCPU_PORT(unit,port)) { 1070 soc_mem_field32_set(unit, mem, &ptab, OUTER_TPID_ENABLEf, 0x1); 1071 } 1072 } 1073 #endif /* BCM_RCPU_SUPPORT */ 1074 1075 #ifdef BCM_MONTEREY_SUPPORT 1076 if (SOC_IS_MONTEREY(unit)) { 1077 if (port < 67) { 1078 soc_PORT_TABm_field32_set(unit, &ptab, MISC_PORT_PROFILE_INDEXf, port); 1079 } 1080 } 1081 #endif 1082 1083 #if defined(BCM_TRIDENT2PLUS_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT) 1084 if (soc_feature(unit, soc_feature_separate_ing_lport_rtag7_profile)) { 1085 /* Last set of entries reserved for Front-Panel ports, 1086 * hence adjusting the RTAG7 profile index. 1087 */ 1088 rtag7_profile_idx = 1089 ((soc_mem_index_max(unit, RTAG7_PORT_BASED_HASHm) - 1090 soc_mem_index_max(unit, mem)) + port); 1091 soc_mem_field32_set(unit, mem, &ptab, RTAG7_PORT_PROFILE_INDEXf, rtag7_profile_idx); 1092 1093 } 1094 #endif /* BCM_TRIDENT2PLUS_SUPPORT || BCM_GREYHOUND2_SUPPORT */ 1095 1096 BCM_IF_ERROR_RETURN(BCM_XGS3_MEM_WRITE(unit, mem, port, &ptab)); 1097 if (lp_field_count > 0) { 1098 PORT_LOCK(unit); 1099 rv = bcm_esw_port_lport_fields_set(unit, port, LPORT_PROFILE_LPORT_TAB, 1100 lp_field_count, lp_field_ids, 1101 lp_field_values); 1102 PORT_UNLOCK(unit); 1103 if (BCM_FAILURE(rv)) { 1104 return rv; 1105 } 1106 } 1107 #undef LPORT_TAB_SYNC 1108 1109 #ifdef BCM_TRX_SUPPORT 1110 if (SOC_MEM_FIELD_VALID(unit, SOURCE_TRUNK_MAP_TABLEm, OUTER_TPID_ENABLEf)) { 1111 BCM_IF_ERROR_RETURN( 1112 _bcm_trx_source_trunk_map_set(unit, port, OUTER_TPID_ENABLEf, 1)); 1113 } 1114 #endif 1115 1116 /* 1117 * Replicate port information to IPORT_TABLE and IEGR_PORT register 1118 * for CPU port. 1119 */ 1120 cpu_hg_index = SOC_IS_KATANA2(unit) ? 1121 SOC_INFO(unit).cpu_hg_pp_port_index : 1122 SOC_INFO(unit).cpu_hg_index; 1123 if (IS_CPU_PORT(unit,port)) { 1124 soc_mem_field32_set(unit, mem, &ptab, port_type_field, 1); 1125 if (SOC_MEM_IS_VALID(unit, IPORT_TABLEm)) { 1126 /* IPORT and PORT have identical formats */ 1127 BCM_IF_ERROR_RETURN 1128 (soc_mem_write(unit, IPORT_TABLEm, MEM_BLOCK_ALL, port, 1129 &ptab)); 1130 } else if (cpu_hg_index != -1) { 1131 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, 1132 cpu_hg_index, &ptab)); 1133 } 1134 1135 field_values[0] = 1; 1136 if (SOC_REG_IS_VALID(unit, iegr_port_reg)) { 1137 /* IEGR_PORT and EGR_PORT have identical formats */ 1138 BCM_IF_ERROR_RETURN 1139 (soc_reg_fields32_modify(unit, iegr_port_reg, port, 1140 field_count, field_ids, 1141 field_values)); 1142 } else if (SOC_INFO(unit).cpu_hg_index != -1 && 1143 soc_mem_index_max(unit, EGR_PORTm) == 1144 SOC_INFO(unit).cpu_hg_index) { 1145 BCM_IF_ERROR_RETURN 1146 (soc_mem_fields32_modify(unit, EGR_PORTm, 1147 SOC_INFO(unit).cpu_hg_index, 1148 field_count, field_ids, 1149 field_values)); 1150 } 1151 } 1152 1153 return (BCM_E_NONE); 1154 } 1155 1156 /* 1157 * Function: 1158 * _bcm_fb_port_rate_ingress_set 1159 * Purpose: 1160 * Set ingress rate limiting parameters 1161 * Parameters: 1162 * unit - (IN)SOC unit number. 1163 * port - (IN)Port number. 1164 * kbits_sec - (IN)Rate in kilobits (1000 bits) per second. 1165 * Rate of 0 disables rate limiting. 1166 * kbits_burst - (IN)Maximum burst size in kilobits (1000 bits). 1167 * Returns: 1168 * BCM_E_XXX 1169 * Notes: 1170 * Rate-based pause frames automatically will be enabled 1171 * whenever ingress rate metering is enabled. Since the 1172 * pause frame behavior also affects the discard/accept 1173 * behavior of the ingress meter, the pause frame behavior 1174 * is set such that the discard/accept hysteresis is as 1175 * small as possible. 1176 */ 1177 1178 /* 1179 * Please consult the Programmer's Register Reference Guide for 1180 * a description of the following settings and resultant values. 1181 */ 1182 #define DISCARD_THD_BITS 3 1183 #define RESUME_THD_BITS 0 1184 1185 STATIC int 1186 _bcm_fb_port_rate_ingress_set(int unit, bcm_port_t port, 1187 uint32 kbits_sec, uint32 kbits_burst) 1188 { 1189 uint32 kbits_pause; /* Pause frame rate. */ 1190 uint32 regval = 0; /* Register value. */ 1191 uint32 refresh_rate, bucketsize; 1192 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) || \ 1193 defined (BCM_SCORPION_SUPPORT) || defined(BCM_HURRICANE_SUPPORT) || \ 1194 defined (BCM_HURRICANE2_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 1195 uint32 granularity = 3; 1196 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT || BCM_SCORPION_SUPPORT */ 1197 #if defined (BCM_HURRICANE3_SUPPORT) 1198 uint32 fval = 0; 1199 soc_reg_t meter_ing_port_reg = INVALIDr; 1200 soc_field_t meter_ing_port_field = INVALIDf; 1201 bcm_port_t port_value; 1202 #endif /* BCM_HURRICANE3_SUPPORT */ 1203 1204 /* Disable ingress metering and pause frames for this port */ 1205 BCM_IF_ERROR_RETURN(WRITE_BKPMETERINGCONFIGr(unit, port, regval)); 1206 1207 /*reset the BKPMETERING BUCKET Registers*/ 1208 BCM_IF_ERROR_RETURN(WRITE_BKPMETERINGBUCKETr(unit, port, regval)); 1209 1210 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) || \ 1211 defined(BCM_HURRICANE_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 1212 if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit) || 1213 SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) || 1214 SOC_IS_GREYHOUND2(unit)) { 1215 BCM_IF_ERROR_RETURN(WRITE_BKPMETERINGCONFIG_EXTr(unit, port, regval)); 1216 } 1217 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */ 1218 1219 /* If metering is disabled on this ingress port we are done.*/ 1220 if (!kbits_sec || !kbits_burst) { 1221 return (BCM_E_NONE); 1222 } 1223 1224 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) || \ 1225 defined(BCM_HURRICANE_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 1226 if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit) || 1227 SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) || 1228 SOC_IS_GREYHOUND2(unit)) { 1229 uint32 regval_ext = 0; 1230 BCM_IF_ERROR_RETURN 1231 (READ_BKPMETERINGCONFIG_EXTr(unit, port, ®val_ext)); 1232 /* As below, but for in different register */ 1233 soc_reg_field_set(unit, BKPMETERINGCONFIG_EXTr, ®val_ext, 1234 BKPDISCARD_ENf, 1); 1235 1236 /* Turn off backward compatability default */ 1237 soc_reg_field_set(unit, BKPMETERINGCONFIG_EXTr, ®val_ext, 1238 BKPDISCARD_ACCT_ENf, 0); 1239 1240 soc_reg_field_set(unit, BKPMETERINGCONFIG_EXTr, ®val_ext, 1241 DISCARD_THDf, DISCARD_THD_BITS); 1242 soc_reg_field_set(unit, BKPMETERINGCONFIG_EXTr, ®val_ext, 1243 RESUME_THDf, RESUME_THD_BITS); 1244 1245 BCM_IF_ERROR_RETURN 1246 (WRITE_BKPMETERINGCONFIG_EXTr(unit, port, regval_ext)); 1247 } else 1248 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */ 1249 { 1250 /* Enable metering (rate-based discarding) */ 1251 soc_reg_field_set(unit, BKPMETERINGCONFIGr, ®val, 1252 BKPDISCARD_ENf, 1); 1253 1254 /* 1255 * BKPMETERINGCONFIGr.BKPDISCARD_ACCT_ENf was cleared when we wrote 1256 * 0 to the BKPMETERINGCONFIGr register above, so we don't need 1257 * to clear it here. 1258 */ 1259 1260 /* 1261 * Set the "automatic" pause frame behavior. Because the 1262 * metering and pause frame behavior controls are intertwined, 1263 * truly independent control of both is not possible. Therefore, 1264 * the pause frame behavior will be hardcoded so that the metering 1265 * functionality (API) is preserved as much as possible. 1266 * The smallest drop/resume hysteresis window should be used. 1267 */ 1268 soc_reg_field_set(unit, BKPMETERINGCONFIGr, ®val, 1269 DISCARD_THDf, DISCARD_THD_BITS); 1270 soc_reg_field_set(unit, BKPMETERINGCONFIGr, ®val, 1271 RESUME_THDf, RESUME_THD_BITS); 1272 } 1273 1274 /* Pre-check kbits_burst upper limit for upcoming math */ 1275 if (kbits_burst > (0xFFFFFFFF / 8)) { 1276 kbits_burst = (0xFFFFFFFF / 8); 1277 } 1278 /* 1279 * Convert requested burst size into the appropriate 1280 * PAUSE_THD field setting. Based on the above hysteresis 1281 * window, convert the requested burst size to the 1282 * associated PAUSE_THD value. 1283 */ 1284 #if (DISCARD_THD_BITS==0) 1285 kbits_pause = (kbits_burst * 4) / 7; 1286 #endif 1287 #if (DISCARD_THD_BITS==1) 1288 kbits_pause = (kbits_burst * 2) / 3; 1289 #endif 1290 #if (DISCARD_THD_BITS==2) 1291 kbits_pause = (kbits_burst * 4) / 5; 1292 #endif 1293 #if (DISCARD_THD_BITS==3) 1294 kbits_pause = (kbits_burst * 8) / 9; 1295 #endif 1296 1297 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) || \ 1298 defined (BCM_SCORPION_SUPPORT) || defined (BCM_HURRICANE_SUPPORT) || \ 1299 defined(BCM_GREYHOUND_SUPPORT) 1300 if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) || 1301 SOC_IS_HAWKEYE(unit) || SOC_IS_SC_CQ(unit) || 1302 SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) || 1303 SOC_IS_GREYHOUND2(unit)) { 1304 uint32 miscval, flags = 0; 1305 int refresh_bitsize = 0; 1306 int bucket_bitsize = 0; 1307 if (soc_reg_field_valid(unit, MISCCONFIGr, ITU_MODE_SELf)) { 1308 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &miscval)); 1309 if (soc_reg_field_get(unit, MISCCONFIGr, 1310 miscval, ITU_MODE_SELf)) { 1311 flags |= _BCM_XGS_METER_FLAG_NON_LINEAR; 1312 } 1313 } 1314 if (soc_reg_field_valid(unit, BKPMETERINGCONFIGr, METER_GRANf)) { 1315 flags |= _BCM_XGS_METER_FLAG_GRANULARITY; 1316 } 1317 1318 if (SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 1319 flags |= _BCM_XGS_METER_FLAG_GRANULARITY_SELECTIVE; 1320 flags |= _BCM_XGS_METER_FLAG_GRANULARITY_SELECT3; 1321 flags |= _BCM_XGS_METER_FLAG_GRANULARITY_SELECT5; 1322 flags |= _BCM_XGS_METER_FLAG_BUCKET_IN_8KB; 1323 } 1324 1325 if (soc_reg_field_valid(unit, BKPMETERINGCONFIGr, REFRESHCOUNTf)) { 1326 refresh_bitsize = soc_reg_field_length(unit, BKPMETERINGCONFIGr, 1327 REFRESHCOUNTf); 1328 } else 1329 /*coverity[result_independent_of_operands]*/ 1330 if (SOC_REG_IS_VALID(unit, BKPMETERINGCONFIG1r) && 1331 soc_reg_field_valid(unit, BKPMETERINGCONFIG1r, 1332 REFRESHCOUNTf)) { 1333 refresh_bitsize = soc_reg_field_length(unit, BKPMETERINGCONFIG1r, 1334 REFRESHCOUNTf); 1335 } 1336 bucket_bitsize = soc_reg_field_length(unit, BKPMETERINGCONFIGr, 1337 PAUSE_THDf); 1338 BCM_IF_ERROR_RETURN 1339 (_bcm_xgs_kbits_to_bucket_encoding(kbits_sec, kbits_pause, flags, 1340 refresh_bitsize, bucket_bitsize, 1341 &refresh_rate, &bucketsize, &granularity)); 1342 } else 1343 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */ 1344 { 1345 /* Calculate adj_rate rate. */ 1346 BCM_XGS3_PORT_RATE_64KBIT_QUANTUM(kbits_sec, refresh_rate); 1347 bucketsize = _bcm_fb_kbits_to_bucketsize(kbits_pause); 1348 } 1349 1350 soc_reg_field_set(unit, BKPMETERINGCONFIGr, ®val, 1351 PAUSE_THDf, bucketsize); 1352 /* Set adjasted rate to port config register. */ 1353 if (soc_reg_field_valid(unit,BKPMETERINGCONFIGr,REFRESHCOUNTf)) { 1354 soc_reg_field_set(unit, BKPMETERINGCONFIGr, ®val, 1355 REFRESHCOUNTf, refresh_rate); 1356 } 1357 1358 #if defined(BCM_SCORPION_SUPPORT) 1359 /*coverity[result_independent_of_operands]*/ 1360 if (SOC_REG_IS_VALID(unit, BKPMETERINGCONFIG1r)) { 1361 if (soc_reg_field_valid(unit,BKPMETERINGCONFIG1r,REFRESHCOUNTf)) { 1362 BCM_IF_ERROR_RETURN( 1363 soc_reg_field32_modify(unit, BKPMETERINGCONFIG1r, port, 1364 REFRESHCOUNTf, refresh_rate)); 1365 } 1366 } 1367 1368 if (soc_reg_field_valid(unit, BKPMETERINGCONFIGr, METER_GRANf)) { 1369 soc_reg_field_set(unit, BKPMETERINGCONFIGr, ®val, METER_GRANf, 1370 granularity); 1371 } 1372 #endif /* BCM_SCORPION_SUPPORT */ 1373 1374 /* Enable ingress metering and pause frames for this port */ 1375 BCM_IF_ERROR_RETURN(WRITE_BKPMETERINGCONFIGr(unit, port, regval)); 1376 1377 #if defined(BCM_HURRICANE3_SUPPORT) 1378 meter_ing_port_reg = METER_ING_PORT_GRANr; 1379 meter_ing_port_field = METER_ING_PORT_GRANf; 1380 port_value = port; 1381 if (SOC_IS_GREYHOUND2(unit)) { 1382 int mmu_port; 1383 int phy_port; 1384 soc_info_t *si; 1385 1386 /* For Greyhound2, program MMU port index */ 1387 si = &SOC_INFO(unit); 1388 phy_port = si->port_l2p_mapping[port]; 1389 mmu_port = si->port_p2m_mapping[phy_port]; 1390 1391 if (mmu_port < 32) { 1392 meter_ing_port_reg = METER_ING_PORT_GRAN_0r; 1393 port_value = mmu_port; 1394 } else if (mmu_port < 64) { 1395 meter_ing_port_reg = METER_ING_PORT_GRAN_1r; 1396 port_value = mmu_port - 32; 1397 } else { 1398 meter_ing_port_reg = METER_ING_PORT_GRAN_2r; 1399 port_value = mmu_port - 64; 1400 } 1401 } 1402 1403 if (soc_reg_field_valid(unit, meter_ing_port_reg, meter_ing_port_field)) { 1404 BCM_IF_ERROR_RETURN( 1405 soc_reg32_get(unit, meter_ing_port_reg, REG_PORT_ANY, 0, ®val)); 1406 fval = soc_reg_field_get(unit, meter_ing_port_reg, 1407 regval, meter_ing_port_field); 1408 if (granularity == 5) { 1409 fval |= (1 << port_value); 1410 } else { 1411 fval &= ~(1 << port_value); 1412 } 1413 soc_reg_field_set(unit, meter_ing_port_reg, ®val, 1414 meter_ing_port_field, fval); 1415 BCM_IF_ERROR_RETURN( 1416 soc_reg32_set(unit, meter_ing_port_reg, REG_PORT_ANY, 0, regval)); 1417 } 1418 #endif /* BCM_HURRICANE3_SUPPORT */ 1419 1420 /* MISCCONFIG.METERING_CLK_EN is set by chip init */ 1421 1422 return (BCM_E_NONE); 1423 } 1424 1425 #ifdef BCM_TRIUMPH_SUPPORT 1426 STATIC int 1427 _bcm_tr_port_rate_ingress_set(int unit, bcm_port_t port, 1428 uint32 kbits_sec, uint32 kbits_burst) 1429 { 1430 uint32 miscval; 1431 uint32 delta=0; 1432 uint32 kbits_Rburst=0; /* Adjusted burst value */ 1433 uint32 kbits_cburst=0; /* Re computed burst value */ 1434 uint32 kbits_pause; /* Pause frame rate. */ 1435 uint32 regval = 0; /* Register value. */ 1436 uint64 regval_64; /* 64-bit Register value. */ 1437 uint32 refresh_rate, bucketsize, granularity = 3, flags = 0; 1438 int refresh_bitsize, bucket_bitsize; 1439 1440 /* Disable ingress metering and pause frames for this port */ 1441 COMPILER_64_ZERO(regval_64); 1442 BCM_IF_ERROR_RETURN(WRITE_BKPMETERINGCONFIG_64r(unit, port, regval_64)); 1443 1444 /*reset the BKPMETERING BUCKET Registers*/ 1445 BCM_IF_ERROR_RETURN(WRITE_BKPMETERINGBUCKETr(unit, port, regval)); 1446 1447 /* If metering is disabled on this ingress port we are done.*/ 1448 if (!kbits_sec || !kbits_burst) { 1449 return (BCM_E_NONE); 1450 } 1451 1452 /* Enable metering (rate-based discarding) */ 1453 soc_reg64_field32_set(unit, BKPMETERINGCONFIG_64r, ®val_64, 1454 BKPDISCARD_ENf, 1); 1455 1456 /* 1457 * Set the "automatic" pause frame behavior. Because the 1458 * metering and pause frame behavior controls are intertwined, 1459 * truly independent control of both is not possible. Therefore, 1460 * the pause frame behavior will be hardcoded so that the metering 1461 * functionality (API) is preserved as much as possible. 1462 * The smallest drop/resume hysteresis window should be used. 1463 */ 1464 soc_reg64_field32_set(unit, BKPMETERINGCONFIG_64r, ®val_64, 1465 DISCARD_THDf, DISCARD_THD_BITS); 1466 soc_reg64_field32_set(unit, BKPMETERINGCONFIG_64r, ®val_64, 1467 RESUME_THDf, RESUME_THD_BITS); 1468 1469 /* Pre-check kbits_burst upper limit for upcoming math */ 1470 if (kbits_burst > (0xFFFFFFFF / 8)) { 1471 kbits_burst = (0xFFFFFFFF / 8); 1472 } 1473 1474 /* 1475 * Convert requested burst size into the appropriate 1476 * PAUSE_THD field setting. Based on the above hysteresis 1477 * window, convert the requested burst size to the 1478 * associated PAUSE_THD value. 1479 */ 1480 #if (DISCARD_THD_BITS==0) 1481 kbits_pause = (kbits_burst * 4) / 7; 1482 kbits_cburst = (kbits_pause * 7 ) / 4; 1483 #endif 1484 #if (DISCARD_THD_BITS==1) 1485 kbits_pause = (kbits_burst * 2) / 3; 1486 kbits_cburst = (kbits_pause * 3 ) / 2; 1487 #endif 1488 #if (DISCARD_THD_BITS==2) 1489 kbits_pause = (kbits_burst * 4) / 5; 1490 kbits_cburst = (kbits_pause * 5 ) / 4; 1491 #endif 1492 #if (DISCARD_THD_BITS==3) 1493 kbits_pause = (kbits_burst * 8) / 9; 1494 kbits_cburst = (kbits_pause * 9 ) / 8; 1495 #endif 1496 /* 1497 compute back the burst. 1498 Add (burst- computed burst) delta to org_burst to get new burst and use it for kbits_pause. 1499 */ 1500 delta = kbits_burst - kbits_cburst; 1501 kbits_Rburst = kbits_burst + delta; 1502 1503 #if (DISCARD_THD_BITS==0) 1504 kbits_pause = (kbits_Rburst * 4) / 7; 1505 #endif 1506 #if (DISCARD_THD_BITS==1) 1507 kbits_pause = (kbits_Rburst * 2) / 3; 1508 #endif 1509 #if (DISCARD_THD_BITS==2) 1510 kbits_pause = (kbits_Rburst * 4) / 5; 1511 #endif 1512 #if (DISCARD_THD_BITS==3) 1513 kbits_pause = (kbits_Rburst * 8) / 9; 1514 #endif 1515 1516 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &miscval)); 1517 if (soc_reg_field_get(unit, MISCCONFIGr, miscval, ITU_MODE_SELf)) { 1518 flags |= _BCM_XGS_METER_FLAG_NON_LINEAR; 1519 } 1520 flags |= _BCM_XGS_METER_FLAG_GRANULARITY; 1521 1522 if (SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit)) { 1523 flags |= _BCM_XGS_METER_FLAG_DOUBLE_REFRESH_FREQ; 1524 } 1525 refresh_bitsize = soc_reg_field_length(unit, BKPMETERINGCONFIG_64r, 1526 REFRESHCOUNTf); 1527 bucket_bitsize = soc_reg_field_length(unit, BKPMETERINGCONFIG_64r, 1528 PAUSE_THDf); 1529 BCM_IF_ERROR_RETURN 1530 (_bcm_xgs_kbits_to_bucket_encoding(kbits_sec, kbits_pause, flags, 1531 refresh_bitsize, bucket_bitsize, 1532 &refresh_rate, &bucketsize, &granularity)); 1533 1534 /* Commit values to fields */ 1535 soc_reg64_field32_set(unit, BKPMETERINGCONFIG_64r, ®val_64, 1536 PAUSE_THDf, bucketsize); 1537 /* Set adjasted rate to port config register. */ 1538 soc_reg64_field32_set(unit, BKPMETERINGCONFIG_64r, ®val_64, 1539 REFRESHCOUNTf, refresh_rate); 1540 soc_reg64_field32_set(unit, BKPMETERINGCONFIG_64r, ®val_64, 1541 METER_GRANULARITYf, granularity); 1542 1543 /* Enable ingress metering and pause frames for this port */ 1544 BCM_IF_ERROR_RETURN(WRITE_BKPMETERINGCONFIG_64r(unit, port, regval_64)); 1545 1546 /* MISCCONFIG.METERING_CLK_EN is set by chip init */ 1547 1548 return (BCM_E_NONE); 1549 } 1550 #endif 1551 #undef DISCARD_THD_BITS 1552 #undef RESUME_THD_BITS 1553 1554 /* 1555 * Function: 1556 * _bcm_fb_port_rate_ingress_get 1557 * Purpose: 1558 * Get ingress rate limiting parameters 1559 * Parameters: 1560 * unit - (IN)SOC unit number. 1561 * port - (IN)Port number. 1562 * kbits_sec - (OUT) Rate in kilobits (1000 bits) per second, or 1563 * zero if rate limiting is disabled. 1564 * kbits_burst - (OUT) Maximum burst size in kilobits (1000 bits). 1565 * Returns: 1566 * BCM_E_XXX 1567 */ 1568 1569 int 1570 _bcm_fb_port_rate_ingress_get(int unit, bcm_port_t port, 1571 uint32 *kbits_sec, uint32 *kbits_burst) 1572 { 1573 uint32 kbits_pause; /* Pause frame rate. */ 1574 uint32 regval; /* Register value. */ 1575 int bpkdiscard_en, discard_thd; 1576 uint32 refresh_rate = 0, bucketsize = 0; 1577 1578 /* Read ingress port metering configuration. */ 1579 BCM_IF_ERROR_RETURN(READ_BKPMETERINGCONFIGr(unit, port, ®val)); 1580 1581 /* Extract pause frame rate. */ 1582 bucketsize = soc_reg_field_get(unit, BKPMETERINGCONFIGr, 1583 regval, PAUSE_THDf); 1584 1585 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) || \ 1586 defined(BCM_HURRICANE_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 1587 if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit) || 1588 SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) || 1589 SOC_IS_GREYHOUND2(unit)) { 1590 uint32 regval_ext; 1591 BCM_IF_ERROR_RETURN 1592 (READ_BKPMETERINGCONFIG_EXTr(unit, port, ®val_ext)); 1593 bpkdiscard_en = soc_reg_field_get(unit, BKPMETERINGCONFIG_EXTr, 1594 regval_ext, BKPDISCARD_ENf); 1595 discard_thd = soc_reg_field_get(unit, BKPMETERINGCONFIG_EXTr, 1596 regval_ext, DISCARD_THDf); 1597 } else 1598 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */ 1599 { 1600 bpkdiscard_en = soc_reg_field_get(unit, BKPMETERINGCONFIGr, 1601 regval, BKPDISCARD_ENf); 1602 discard_thd = soc_reg_field_get(unit, BKPMETERINGCONFIGr, 1603 regval, DISCARD_THDf); 1604 } 1605 1606 if (!bpkdiscard_en || !bucketsize) { 1607 *kbits_sec = *kbits_burst = 0; 1608 } else { 1609 if (soc_reg_field_valid(unit, BKPMETERINGCONFIGr, REFRESHCOUNTf)) { 1610 refresh_rate = soc_reg_field_get(unit, BKPMETERINGCONFIGr, 1611 regval, REFRESHCOUNTf); 1612 } 1613 #if defined(BCM_SCORPION_SUPPORT) 1614 /*coverity[result_independent_of_operands]*/ 1615 if (SOC_REG_IS_VALID(unit, BKPMETERINGCONFIG1r)) { 1616 uint32 val; 1617 BCM_IF_ERROR_RETURN(READ_BKPMETERINGCONFIG1r(unit, port, &val)); 1618 if (soc_reg_field_valid(unit, BKPMETERINGCONFIG1r, REFRESHCOUNTf)) { 1619 refresh_rate = soc_reg_field_get(unit, BKPMETERINGCONFIG1r, 1620 val, REFRESHCOUNTf); 1621 } 1622 } 1623 #endif 1624 1625 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) || \ 1626 defined(BCM_SCORPION_SUPPORT) || defined (BCM_HURRICANE_SUPPORT) || \ 1627 defined(BCM_GREYHOUND_SUPPORT) 1628 if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) || 1629 SOC_IS_HAWKEYE(unit) || SOC_IS_SC_CQ(unit) || 1630 SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) || 1631 SOC_IS_GREYHOUND2(unit)) { 1632 uint32 miscval, granularity = 3, flags = 0; 1633 #if defined (BCM_HURRICANE3_SUPPORT) 1634 uint32 fval = 0; 1635 soc_reg_t meter_ing_port_reg = INVALIDr; 1636 soc_field_t meter_ing_port_field = INVALIDf; 1637 bcm_port_t port_value; 1638 #endif /* BCM_HURRICANE3_SUPPORT */ 1639 1640 if (soc_reg_field_valid(unit, MISCCONFIGr, ITU_MODE_SELf)) { 1641 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &miscval)); 1642 if (soc_reg_field_get(unit, MISCCONFIGr, 1643 miscval, ITU_MODE_SELf)) { 1644 flags |= _BCM_XGS_METER_FLAG_NON_LINEAR; 1645 } 1646 } 1647 if (soc_reg_field_valid(unit, BKPMETERINGCONFIGr, METER_GRANf)) { 1648 flags |= _BCM_XGS_METER_FLAG_GRANULARITY; 1649 granularity = soc_reg_field_get(unit, BKPMETERINGCONFIGr, 1650 regval, METER_GRANf); 1651 } 1652 1653 #if defined (BCM_HURRICANE3_SUPPORT) 1654 meter_ing_port_reg = METER_ING_PORT_GRANr; 1655 meter_ing_port_field = METER_ING_PORT_GRANf; 1656 port_value = port; 1657 if (SOC_IS_GREYHOUND2(unit)) { 1658 int mmu_port; 1659 int phy_port; 1660 soc_info_t *si; 1661 1662 /* For Greyhound2, program MMU port index */ 1663 si = &SOC_INFO(unit); 1664 phy_port = si->port_l2p_mapping[port]; 1665 mmu_port = si->port_p2m_mapping[phy_port]; 1666 1667 if (mmu_port < 32) { 1668 meter_ing_port_reg = METER_ING_PORT_GRAN_0r; 1669 port_value = mmu_port; 1670 } else if (mmu_port < 64) { 1671 meter_ing_port_reg = METER_ING_PORT_GRAN_1r; 1672 port_value = mmu_port - 32; 1673 } else { 1674 meter_ing_port_reg = METER_ING_PORT_GRAN_2r; 1675 port_value = mmu_port - 64; 1676 } 1677 } 1678 1679 if (soc_reg_field_valid(unit, meter_ing_port_reg, 1680 meter_ing_port_field)) { 1681 flags |= _BCM_XGS_METER_FLAG_GRANULARITY; 1682 1683 BCM_IF_ERROR_RETURN( 1684 soc_reg32_get(unit, meter_ing_port_reg, 1685 REG_PORT_ANY, 0, ®val)); 1686 fval = soc_reg_field_get(unit, meter_ing_port_reg, 1687 regval, meter_ing_port_field); 1688 1689 if (fval & (1 << port_value)) { 1690 granularity = 5; 1691 } 1692 } 1693 #endif /* BCM_HURRICANE3_SUPPORT */ 1694 BCM_IF_ERROR_RETURN 1695 (_bcm_xgs_bucket_encoding_to_kbits(refresh_rate, bucketsize, 1696 granularity, flags, 1697 kbits_sec, &kbits_pause)); 1698 } else 1699 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */ 1700 { 1701 if (soc_reg_field_valid(unit, BKPMETERINGCONFIGr, REFRESHCOUNTf)) { 1702 *kbits_sec = 64 * refresh_rate; 1703 } 1704 kbits_pause = _bcm_fb_bucketsize_to_kbits(bucketsize); 1705 } 1706 1707 switch (discard_thd) { 1708 case 0: 1709 *kbits_burst = (kbits_pause * 7) / 4; 1710 break; 1711 case 1: 1712 *kbits_burst = (kbits_pause * 3) / 2; 1713 break; 1714 case 2: 1715 *kbits_burst = (kbits_pause * 5) / 4; 1716 break; 1717 case 3: 1718 *kbits_burst = (kbits_pause * 9) / 8; 1719 break; 1720 default: 1721 /* Should never happen */ 1722 *kbits_burst = 0; 1723 break; 1724 } 1725 } 1726 return (BCM_E_NONE); 1727 } 1728 1729 #ifdef BCM_TRIUMPH_SUPPORT 1730 int 1731 _bcm_tr_port_rate_ingress_get(int unit, bcm_port_t port, 1732 uint32 *kbits_sec, uint32 *kbits_burst) 1733 { 1734 uint32 miscval; 1735 uint32 kbits_pause; /* Pause frame rate. */ 1736 uint64 regval; /* Register value. */ 1737 int bpkdiscard_en, discard_thd; 1738 uint32 refresh_rate = 0, bucketsize = 0, granularity = 3, flags = 0; 1739 1740 /* Read ingress port metering configuration. */ 1741 BCM_IF_ERROR_RETURN(READ_BKPMETERINGCONFIG_64r(unit, port, ®val)); 1742 1743 /* Extract pause frame rate. */ 1744 bucketsize = soc_reg64_field32_get(unit, BKPMETERINGCONFIG_64r, 1745 regval, PAUSE_THDf); 1746 bpkdiscard_en = soc_reg64_field32_get(unit, BKPMETERINGCONFIG_64r, 1747 regval, BKPDISCARD_ENf); 1748 discard_thd = soc_reg64_field32_get(unit, BKPMETERINGCONFIG_64r, 1749 regval, DISCARD_THDf); 1750 1751 if (!bpkdiscard_en || !bucketsize) { 1752 *kbits_sec = *kbits_burst = 0; 1753 } else { 1754 refresh_rate = soc_reg64_field32_get(unit, BKPMETERINGCONFIG_64r, 1755 regval, REFRESHCOUNTf); 1756 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &miscval)); 1757 if (soc_reg_field_get(unit, MISCCONFIGr, miscval, ITU_MODE_SELf)) { 1758 flags |= _BCM_XGS_METER_FLAG_NON_LINEAR; 1759 } 1760 flags |= _BCM_XGS_METER_FLAG_GRANULARITY; 1761 granularity = soc_reg64_field32_get(unit, BKPMETERINGCONFIG_64r, 1762 regval, METER_GRANULARITYf); 1763 if (SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit)) { 1764 flags |= _BCM_XGS_METER_FLAG_DOUBLE_REFRESH_FREQ; 1765 } 1766 BCM_IF_ERROR_RETURN 1767 (_bcm_xgs_bucket_encoding_to_kbits(refresh_rate, bucketsize, 1768 granularity, flags, 1769 kbits_sec, &kbits_pause)); 1770 1771 switch (discard_thd) { 1772 case 0: 1773 *kbits_burst = (kbits_pause * 7) / 4; 1774 break; 1775 case 1: 1776 *kbits_burst = (kbits_pause * 3) / 2; 1777 break; 1778 case 2: 1779 *kbits_burst = (kbits_pause * 5) / 4; 1780 break; 1781 case 3: 1782 *kbits_burst = (kbits_pause * 9) / 8; 1783 break; 1784 default: 1785 /* Should never happen */ 1786 *kbits_burst = 0; 1787 break; 1788 } 1789 } 1790 return (BCM_E_NONE); 1791 } 1792 #endif 1793 1794 /* 1795 * For Firebolt, there is no software support for bcm_port_rate_pause_set(). 1796 * However, there is support for bcm_port_rate_pause_get(). 1797 */ 1798 1799 /* 1800 * Function: 1801 * bcm_fb_port_rate_pause_get 1802 * Purpose: 1803 * Get ingress rate limiting pause frame control parameters 1804 * Parameters: 1805 * unit - (IN)SOC unit number. 1806 * port - (IN)Port number. 1807 * kbits_pause - (OUT) Pause threshold in kbits (1000 bits). 1808 * Zero indicates the pause/resume mechanism is disabled. 1809 * kbits_resume - (OUT) Resume threshold in kbits (1000 bits). 1810 * Returns: 1811 * BCM_E_XXX 1812 * Notes: 1813 * For Firebolt, these values are returned for informational 1814 * purposes only. In order to retain the ingress metering 1815 * behavior (as much as possible), the pause frame behavior 1816 * is hard-coded, and is not configurable. 1817 * Rate-based pause frames are automatically enabled whenever 1818 * ingress rate metering is enabled. 1819 */ 1820 int 1821 bcm_fb_port_rate_pause_get(int unit, bcm_port_t port, 1822 uint32 *kbits_pause, uint32 *kbits_resume) 1823 { 1824 uint32 regval = 0; 1825 uint32 pause_thd_setting = 0; 1826 uint32 pause = 0; 1827 uint32 bucket = 0; 1828 uint32 resume = 0; 1829 soc_reg_t reg; 1830 1831 1832 BCM_IF_ERROR_RETURN(READ_BKPMETERINGCONFIGr(unit, port, ®val)); 1833 1834 pause_thd_setting = soc_reg_field_get(unit, BKPMETERINGCONFIGr, 1835 regval, PAUSE_THDf); 1836 1837 if (!pause_thd_setting) { 1838 *kbits_pause = *kbits_resume = 0; 1839 return (BCM_E_NONE); 1840 } 1841 1842 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) || defined (BCM_SCORPION_SUPPORT) || defined (BCM_HURRICANE_SUPPORT) 1843 if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) || 1844 SOC_IS_HAWKEYE(unit) || SOC_IS_SC_CQ(unit) || 1845 SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND2(unit)) { 1846 uint32 fval = 0; 1847 uint32 miscval, rate, granularity = 3, flags = 0; 1848 if (soc_reg_field_valid(unit, MISCCONFIGr, ITU_MODE_SELf)) { 1849 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &miscval)); 1850 if (soc_reg_field_get(unit, MISCCONFIGr, 1851 miscval, ITU_MODE_SELf)) { 1852 flags |= _BCM_XGS_METER_FLAG_NON_LINEAR; 1853 } 1854 } 1855 if (soc_reg_field_valid(unit, BKPMETERINGCONFIGr, METER_GRANf)) { 1856 flags |= _BCM_XGS_METER_FLAG_GRANULARITY; 1857 granularity = soc_reg_field_get(unit, BKPMETERINGCONFIGr, 1858 regval, METER_GRANf); 1859 } 1860 1861 if (soc_reg_field_valid(unit, METER_ING_PORT_GRANr, 1862 METER_ING_PORT_GRANf)) { 1863 flags |= _BCM_XGS_METER_FLAG_GRANULARITY; 1864 1865 SOC_IF_ERROR_RETURN(READ_METER_ING_PORT_GRANr(unit, ®val)); 1866 fval = soc_reg_field_get(unit, METER_ING_PORT_GRANr, 1867 regval, METER_ING_PORT_GRANf); 1868 1869 if (fval & (1 << port)) { 1870 granularity = 5; 1871 } 1872 } 1873 1874 BCM_IF_ERROR_RETURN 1875 (_bcm_xgs_bucket_encoding_to_kbits(0, pause_thd_setting, 1876 granularity, flags, 1877 &rate, &pause)); 1878 } else 1879 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */ 1880 { 1881 pause = _bcm_fb_bucketsize_to_kbits(pause_thd_setting); 1882 } 1883 1884 reg = soc_reg_field_valid(unit, BKPMETERINGCONFIGr, DISCARD_THDf) ? 1885 BKPMETERINGCONFIGr : BKPMETERINGCONFIG_EXTr; 1886 1887 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, ®val)); 1888 1889 switch (soc_reg_field_get(unit, reg, 1890 regval, DISCARD_THDf)) { 1891 case 0: 1892 bucket = (pause * 7) / 4; 1893 break; 1894 case 1: 1895 bucket = (pause * 3) / 2; 1896 break; 1897 case 2: 1898 bucket = (pause * 5) / 4; 1899 break; 1900 case 3: 1901 bucket = (pause * 9) / 8; 1902 break; 1903 default: 1904 /* Should never happen */ 1905 return (BCM_E_INTERNAL); 1906 break; 1907 } 1908 1909 switch (soc_reg_field_get(unit, reg, 1910 regval, RESUME_THDf)) { 1911 case 0: 1912 resume = (pause * 3) / 4; 1913 break; 1914 case 1: 1915 resume = pause / 2; 1916 break; 1917 case 2: 1918 resume = pause / 4; 1919 break; 1920 case 3: 1921 resume = pause / 8; 1922 break; 1923 default: 1924 /* Should never happen */ 1925 return (BCM_E_INTERNAL); 1926 break; 1927 } 1928 1929 /* 1930 * The API assumes a "token bucket", i.e. # tokens in the 1931 * bucket is proportional to the available bandwidth. But 1932 * Firebolt uses a "leaky bucket", where # tokens is 1933 * inversely proportional to available bandwidth. 1934 * Convert "leaky bucket" thresholds to "token bucket"-like 1935 * values. 1936 */ 1937 *kbits_pause = bucket - pause; 1938 *kbits_resume = bucket - resume; 1939 1940 return (BCM_E_NONE); 1941 } 1942 1943 #ifdef BCM_TRIUMPH_SUPPORT 1944 int 1945 bcm_tr_port_rate_pause_get(int unit, bcm_port_t port, 1946 uint32 *kbits_pause, uint32 *kbits_resume) 1947 { 1948 uint64 regval; 1949 uint32 miscval, pause_thd_setting, pause, bucket, resume; 1950 uint32 granularity = 3, rate, flags = 0; 1951 1952 BCM_IF_ERROR_RETURN(READ_BKPMETERINGCONFIG_64r(unit, port, ®val)); 1953 1954 pause_thd_setting = soc_reg64_field32_get(unit, BKPMETERINGCONFIG_64r, 1955 regval, PAUSE_THDf); 1956 1957 if (!pause_thd_setting) { 1958 *kbits_pause = *kbits_resume = 0; 1959 return (BCM_E_NONE); 1960 } 1961 1962 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &miscval)); 1963 if (soc_reg_field_get(unit, MISCCONFIGr, miscval, ITU_MODE_SELf)) { 1964 flags |= _BCM_XGS_METER_FLAG_NON_LINEAR; 1965 } 1966 flags |= _BCM_XGS_METER_FLAG_GRANULARITY; 1967 if (soc_reg_field_valid(unit,BKPMETERINGCONFIG_64r, METER_GRANf)) { 1968 granularity = soc_reg64_field32_get(unit, BKPMETERINGCONFIG_64r, 1969 regval, METER_GRANf); 1970 } else if (soc_reg_field_valid(unit, BKPMETERINGCONFIG_64r, 1971 METER_GRANULARITYf)) { 1972 granularity = soc_reg64_field32_get(unit, BKPMETERINGCONFIG_64r, 1973 regval, METER_GRANULARITYf); 1974 } 1975 if (SOC_IS_TD_TT(unit) || SOC_IS_KATANAX(unit)) { 1976 flags |= _BCM_XGS_METER_FLAG_DOUBLE_REFRESH_FREQ; 1977 } 1978 BCM_IF_ERROR_RETURN 1979 (_bcm_xgs_bucket_encoding_to_kbits(0, pause_thd_setting, 1980 granularity, flags, 1981 &rate, &pause)); 1982 1983 switch (soc_reg64_field32_get(unit, BKPMETERINGCONFIG_64r, 1984 regval, DISCARD_THDf)) { 1985 case 0: 1986 bucket = (pause * 7) / 4; 1987 break; 1988 case 1: 1989 bucket = (pause * 3) / 2; 1990 break; 1991 case 2: 1992 bucket = (pause * 5) / 4; 1993 break; 1994 case 3: 1995 bucket = (pause * 9) / 8; 1996 break; 1997 default: 1998 /* Should never happen */ 1999 return (BCM_E_INTERNAL); 2000 break; 2001 } 2002 2003 switch (soc_reg64_field32_get(unit, BKPMETERINGCONFIG_64r, 2004 regval, RESUME_THDf)) { 2005 case 0: 2006 resume = (pause * 3) / 4; 2007 break; 2008 case 1: 2009 resume = pause / 2; 2010 break; 2011 case 2: 2012 resume = pause / 4; 2013 break; 2014 case 3: 2015 resume = pause / 8; 2016 break; 2017 default: 2018 /* Should never happen */ 2019 return (BCM_E_INTERNAL); 2020 break; 2021 } 2022 2023 /* 2024 * The API assumes a "token bucket", i.e. # tokens in the 2025 * bucket is proportional to the available bandwidth. But 2026 * Firebolt uses a "leaky bucket", where # tokens is 2027 * inversely proportional to available bandwidth. 2028 * Convert "leaky bucket" thresholds to "token bucket"-like 2029 * values. 2030 */ 2031 *kbits_pause = bucket - pause; 2032 *kbits_resume = bucket - resume; 2033 2034 return (BCM_E_NONE); 2035 } 2036 #endif 2037 2038 /* 2039 * Function: 2040 * bcm_fb_port_rate_egress_set 2041 * Purpose: 2042 * Set egress rate limiting parameters for the Firebolt chip. 2043 * Parameters: 2044 * unit - (IN)SOC unit number 2045 * port - (IN)Port number 2046 * kbits_sec - (IN)Rate in kilobits (1000 bits) per second. 2047 * Rate of 0 disables rate limiting. 2048 * kbits_burst -(IN)Maximum burst size in kilobits (1000 bits). 2049 * Returns: 2050 * BCM_E_XXX 2051 */ 2052 int 2053 bcm_fb_port_rate_egress_set(int unit, bcm_port_t port, 2054 uint32 kbits_sec, uint32 kbits_burst, uint32 mode) 2055 { 2056 int rv = BCM_E_NONE; 2057 uint32 refresh_rate, bucketsize; 2058 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) || \ 2059 defined(BCM_SCORPION_SUPPORT) || defined(BCM_HURRICANE_SUPPORT) || \ 2060 defined(BCM_HURRICANE2_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 2061 uint32 granularity = 3, flags = 0; 2062 #endif 2063 2064 #if defined (BCM_HURRICANE3_SUPPORT) 2065 uint32 fval = 0; 2066 uint32 regval = 0; 2067 soc_reg_t meter_egr_port_reg = INVALIDr; 2068 soc_field_t meter_egr_port_field = INVALIDf; 2069 bcm_port_t port_value; 2070 #endif /* BCM_HURRICANE3_SUPPORT */ 2071 2072 #if defined(BCM_GREYHOUND_SUPPORT) 2073 if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) || 2074 SOC_IS_GREYHOUND2(unit)) { 2075 /* GH support Byte mode only */ 2076 if (mode != _BCM_PORT_RATE_BYTE_MODE) { 2077 return BCM_E_UNAVAIL; 2078 } 2079 } 2080 #endif /* BCM_GREYHOUND_SUPPORT */ 2081 2082 /* Take lock if IPMC repl freeze is required */ 2083 if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) { 2084 SOC_EGRESS_METERING_LOCK(unit); 2085 } 2086 2087 /* 2088 * The procedure followed is first disable the egress metering i.e. 2089 * reset EGRMETERINGCONFIG, then clear the buckets and re-enable the 2090 * egress metering. Finally enable the MISCCONFING,Metering clocking 2091 * 2092 * NOTE: During the period of disabling and re-enabling the Egress metering 2093 * may be in-effective for couple of cycles 2094 */ 2095 2096 /* Disable egress metering for this port */ 2097 if (soc_reg_field_valid(unit, EGRMETERINGCONFIGr, REFRESHf)) { 2098 rv = soc_reg_field32_modify(unit, EGRMETERINGCONFIGr, port, 2099 REFRESHf, 0); 2100 } 2101 #if defined(BCM_SCORPION_SUPPORT) 2102 else if (soc_reg_field_valid(unit, EGRMETERINGCONFIG1r, REFRESHf)) { 2103 rv = soc_reg_field32_modify(unit, EGRMETERINGCONFIG1r, port, 2104 REFRESHf, 0); 2105 } 2106 #endif /* BCM_SCORPION_SUPPORT */ 2107 2108 if (BCM_FAILURE(rv)) { 2109 if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) { 2110 SOC_EGRESS_METERING_UNLOCK(unit); 2111 } 2112 return rv; 2113 } 2114 2115 if (soc_reg_field_valid(unit, EGRMETERINGCONFIGr, THD_SELf)) { 2116 rv = soc_reg_field32_modify(unit, EGRMETERINGCONFIGr, port, 2117 THD_SELf, 0); 2118 } 2119 2120 if (BCM_FAILURE(rv)) { 2121 if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) { 2122 SOC_EGRESS_METERING_UNLOCK(unit); 2123 } 2124 return rv; 2125 } 2126 2127 /* Reset metering bucket. */ 2128 rv = WRITE_EGRMETERINGBUCKETr(unit, port, 0); 2129 if (BCM_FAILURE(rv)) { 2130 if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) { 2131 SOC_EGRESS_METERING_UNLOCK(unit); 2132 } 2133 return rv; 2134 } 2135 2136 /* If kbits_sec=0, metering is disabled on this egress port */ 2137 if (kbits_sec) { 2138 /* Enable metering for this port */ 2139 2140 2141 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) || \ 2142 defined(BCM_SCORPION_SUPPORT) || defined(BCM_HURRICANE_SUPPORT) || \ 2143 defined(BCM_GREYHOUND_SUPPORT) 2144 if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) || 2145 SOC_IS_HAWKEYE(unit) || SOC_IS_SC_CQ(unit) || 2146 SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) || 2147 SOC_IS_GREYHOUND2(unit)) { 2148 uint32 miscval = 0; 2149 int refresh_bitsize = 0; 2150 int bucket_bitsize = 0; 2151 2152 rv = READ_MISCCONFIGr(unit, &miscval); 2153 if (BCM_FAILURE(rv)) { 2154 if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) { 2155 SOC_EGRESS_METERING_UNLOCK(unit); 2156 } 2157 return rv; 2158 } 2159 if (soc_reg_field_valid(unit, MISCCONFIGr, ITU_MODE_SELf)) { 2160 if (soc_reg_field_get(unit, MISCCONFIGr, 2161 miscval, ITU_MODE_SELf)) { 2162 flags |= _BCM_XGS_METER_FLAG_NON_LINEAR; 2163 } 2164 } 2165 2166 if (soc_reg_field_valid(unit, EGRMETERINGCONFIGr, METER_GRANf)) { 2167 flags |= _BCM_XGS_METER_FLAG_GRANULARITY; 2168 } 2169 2170 if (SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 2171 flags |= _BCM_XGS_METER_FLAG_GRANULARITY_SELECTIVE; 2172 flags |= _BCM_XGS_METER_FLAG_GRANULARITY_SELECT3; 2173 flags |= _BCM_XGS_METER_FLAG_GRANULARITY_SELECT5; 2174 flags |= _BCM_XGS_METER_FLAG_BUCKET_IN_8KB; 2175 } 2176 2177 if (soc_reg_field_valid(unit, EGRMETERINGCONFIGr, 2178 REFRESHf)) { 2179 refresh_bitsize = soc_reg_field_length(unit, 2180 EGRMETERINGCONFIGr, REFRESHf); 2181 } else if (SOC_REG_IS_VALID(unit, EGRMETERINGCONFIG1r) && 2182 soc_reg_field_valid(unit, EGRMETERINGCONFIG1r, 2183 REFRESHf)) { 2184 refresh_bitsize = soc_reg_field_length(unit, 2185 EGRMETERINGCONFIG1r, REFRESHf); 2186 } 2187 bucket_bitsize = soc_reg_field_length(unit, EGRMETERINGCONFIGr, 2188 THD_SELf); 2189 rv = _bcm_xgs_kbits_to_bucket_encoding(kbits_sec, kbits_burst, 2190 flags, refresh_bitsize, bucket_bitsize, 2191 &refresh_rate, &bucketsize, &granularity); 2192 if (BCM_FAILURE(rv)) { 2193 if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) { 2194 SOC_EGRESS_METERING_UNLOCK(unit); 2195 } 2196 return rv; 2197 } 2198 } else 2199 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */ 2200 { 2201 /* Calculate kbits rate in 64bit quantum equivalent. */ 2202 BCM_XGS3_PORT_RATE_64KBIT_QUANTUM(kbits_sec, refresh_rate); 2203 bucketsize = _bcm_fb_kbits_to_bucketsize(kbits_burst); 2204 } 2205 2206 if (soc_reg_field_valid(unit, EGRMETERINGCONFIGr, REFRESHf)) { 2207 rv = soc_reg_field32_modify(unit, EGRMETERINGCONFIGr, port, 2208 REFRESHf, refresh_rate); 2209 } 2210 #if defined(BCM_SCORPION_SUPPORT) 2211 else if (soc_reg_field_valid(unit, EGRMETERINGCONFIG1r, REFRESHf)) { 2212 rv = soc_reg_field32_modify(unit, EGRMETERINGCONFIG1r, port, 2213 REFRESHf, refresh_rate); 2214 } 2215 2216 if (soc_reg_field_valid(unit, EGRMETERINGCONFIGr, METER_GRANf) && 2217 (BCM_SUCCESS(rv))) { 2218 rv = soc_reg_field32_modify(unit, EGRMETERINGCONFIGr, port, 2219 METER_GRANf, granularity); 2220 } 2221 #endif /* BCM_SCORPION_SUPPORT */ 2222 2223 if (BCM_FAILURE(rv)) { 2224 if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) { 2225 SOC_EGRESS_METERING_UNLOCK(unit); 2226 } 2227 return rv; 2228 } 2229 2230 if (soc_reg_field_valid(unit, EGRMETERINGCONFIGr, THD_SELf)) { 2231 rv = soc_reg_field32_modify(unit, EGRMETERINGCONFIGr, port, 2232 THD_SELf, bucketsize); 2233 } 2234 2235 #if defined(BCM_HURRICANE3_SUPPORT) 2236 meter_egr_port_reg = METER_EGR_PORT_GRANr; 2237 meter_egr_port_field = METER_EGR_PORT_GRANf; 2238 port_value = port; 2239 if (SOC_IS_GREYHOUND2(unit)) { 2240 int mmu_port; 2241 int phy_port; 2242 soc_info_t *si; 2243 2244 /* For Greyhound2, program MMU port index */ 2245 si = &SOC_INFO(unit); 2246 phy_port = si->port_l2p_mapping[port]; 2247 mmu_port = si->port_p2m_mapping[phy_port]; 2248 2249 if (mmu_port < 32) { 2250 meter_egr_port_reg = METER_EGR_PORT_GRAN_0r; 2251 port_value = mmu_port; 2252 } else if (mmu_port < 64) { 2253 meter_egr_port_reg = METER_EGR_PORT_GRAN_1r; 2254 port_value = mmu_port - 32; 2255 } else { 2256 meter_egr_port_reg = METER_EGR_PORT_GRAN_2r; 2257 port_value = mmu_port - 64; 2258 } 2259 } 2260 2261 if (soc_reg_field_valid(unit, meter_egr_port_reg, 2262 meter_egr_port_field)) { 2263 rv = soc_reg32_get(unit, meter_egr_port_reg, 2264 REG_PORT_ANY, 0, ®val); 2265 if (BCM_FAILURE(rv)) { 2266 if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) { 2267 SOC_EGRESS_METERING_UNLOCK(unit); 2268 } 2269 return rv; 2270 } 2271 2272 fval = soc_reg_field_get(unit, meter_egr_port_reg, 2273 regval, meter_egr_port_field); 2274 if (granularity == 5) { 2275 fval |= (1 << port_value); 2276 } else { 2277 fval &= ~(1 << port_value); 2278 } 2279 soc_reg_field_set(unit, meter_egr_port_reg, ®val, 2280 meter_egr_port_field, fval); 2281 rv = soc_reg32_set(unit, meter_egr_port_reg, 2282 REG_PORT_ANY, 0, regval); 2283 if (BCM_FAILURE(rv)) { 2284 if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) { 2285 SOC_EGRESS_METERING_UNLOCK(unit); 2286 } 2287 return rv; 2288 } 2289 } 2290 #endif /* BCM_HURRICANE3_SUPPORT */ 2291 } 2292 2293 /* MISCCONFIG.METERING_CLK_EN is set by chip init */ 2294 2295 /* Release lock if IPMC repl freeze is required */ 2296 if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) { 2297 SOC_EGRESS_METERING_UNLOCK(unit); 2298 } 2299 2300 return rv; 2301 } 2302 2303 /* 2304 * Function: 2305 * bcm_fb_port_rate_egress_get 2306 * Purpose: 2307 * Get egress rate limiting parameters from the Firebolt chip. 2308 * Parameters: 2309 * unit - (IN)SOC unit number. 2310 * port - (IN)Port number. 2311 * kbits_sec - (OUT)Rate in kilobits (1000 bits) per second, or 2312 * zero if rate limiting is disabled. 2313 * kbits_burst -(OUT) Maximum burst size in kilobits (1000 bits). 2314 * Returns: 2315 * BCM_E_XXX 2316 */ 2317 int 2318 bcm_fb_port_rate_egress_get(int unit, bcm_port_t port, 2319 uint32 *kbits_sec, uint32 *kbits_burst, uint32 *mode) 2320 { 2321 uint32 regval = 0; /* EGRMETERINGCONFIGr register value. */ 2322 int rv = BCM_E_NONE; /* Operation return status. */ 2323 uint32 refresh_rate = 0, bucketsize = 0; 2324 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAPTOR_SUPPORT) || \ 2325 defined(BCM_SCORPION_SUPPORT) || defined(BCM_HURRICANE_SUPPORT) || \ 2326 defined(BCM_HURRICANE2_SUPPORT) || defined(BCM_GREYHOUND_SUPPORT) 2327 uint32 granularity = 3, flags = 0; 2328 #endif 2329 2330 /* Input parameters check. */ 2331 if (!kbits_sec || !kbits_burst) { 2332 return (BCM_E_PARAM); 2333 } 2334 2335 /* Take lock if IPMC repl freeze is required */ 2336 if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) { 2337 SOC_EGRESS_METERING_LOCK(unit); 2338 } 2339 2340 rv = READ_EGRMETERINGCONFIGr(unit, port, ®val); 2341 2342 /* Release lock if IPMC repl freeze is required */ 2343 if (soc_feature(unit, soc_feature_ipmc_repl_freeze)) { 2344 SOC_EGRESS_METERING_UNLOCK(unit); 2345 } 2346 2347 if (rv < 0) { 2348 return rv; 2349 } 2350 2351 if (!soc_reg_field_get(unit, EGRMETERINGCONFIGr, regval, THD_SELf)) { 2352 *kbits_sec = *kbits_burst = 0; 2353 } else { 2354 /* Convert the REFRESH field to kbits/sec (1000 bits/sec). */ 2355 if (soc_reg_field_valid(unit, EGRMETERINGCONFIGr, REFRESHf)) { 2356 refresh_rate = 2357 soc_reg_field_get(unit, EGRMETERINGCONFIGr, regval, REFRESHf); 2358 } 2359 #if defined(BCM_SCORPION_SUPPORT) 2360 else if (soc_reg_field_valid(unit, EGRMETERINGCONFIG1r, REFRESHf)) { 2361 uint32 val; 2362 SOC_IF_ERROR_RETURN 2363 (READ_EGRMETERINGCONFIG1r(unit, port, &val)); 2364 refresh_rate = 2365 soc_reg_field_get(unit, EGRMETERINGCONFIG1r, val, REFRESHf); 2366 } 2367 #endif /* BCM_SCORPION_SUPPORT */ 2368 /* Convert the THD_SEL field to burst size in kbits. */ 2369 2370 if (soc_reg_field_valid(unit, EGRMETERINGCONFIGr, THD_SELf)) { 2371 bucketsize = 2372 soc_reg_field_get(unit, EGRMETERINGCONFIGr, regval, THD_SELf); 2373 } 2374 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAPTOR_SUPPORT) || \ 2375 defined(BCM_SCORPION_SUPPORT) || defined(BCM_HURRICANE_SUPPORT) || \ 2376 defined(BCM_GREYHOUND_SUPPORT) 2377 if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) || 2378 SOC_IS_HAWKEYE(unit) || SOC_IS_SC_CQ(unit) || 2379 SOC_IS_HURRICANEX(unit) || SOC_IS_GREYHOUND(unit) || 2380 SOC_IS_GREYHOUND2(unit)) { 2381 uint32 miscval; 2382 #if defined(BCM_HURRICANE3_SUPPORT) 2383 uint32 fval = 0; 2384 soc_reg_t meter_egr_port_reg = INVALIDr; 2385 soc_field_t meter_egr_port_field = INVALIDf; 2386 bcm_port_t port_value; 2387 #endif /* BCM_HURRICANE3_SUPPORT */ 2388 if (soc_reg_field_valid(unit, MISCCONFIGr, ITU_MODE_SELf)) { 2389 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &miscval)); 2390 if (soc_reg_field_get(unit, MISCCONFIGr, 2391 miscval, ITU_MODE_SELf)) { 2392 flags |= _BCM_XGS_METER_FLAG_NON_LINEAR; 2393 } 2394 } 2395 if (soc_reg_field_valid(unit, EGRMETERINGCONFIGr, METER_GRANf)) { 2396 flags |= _BCM_XGS_METER_FLAG_GRANULARITY; 2397 granularity = soc_reg_field_get(unit, EGRMETERINGCONFIGr, 2398 regval, METER_GRANf); 2399 } 2400 2401 #if defined(BCM_HURRICANE3_SUPPORT) 2402 meter_egr_port_reg = METER_EGR_PORT_GRANr; 2403 meter_egr_port_field = METER_EGR_PORT_GRANf; 2404 port_value = port; 2405 2406 if (SOC_IS_GREYHOUND2(unit)) { 2407 int mmu_port; 2408 int phy_port; 2409 soc_info_t *si; 2410 2411 /* For Greyhound2, program MMU port index */ 2412 si = &SOC_INFO(unit); 2413 phy_port = si->port_l2p_mapping[port]; 2414 mmu_port = si->port_p2m_mapping[phy_port]; 2415 if (mmu_port < 32) { 2416 meter_egr_port_reg = METER_EGR_PORT_GRAN_0r; 2417 port_value = mmu_port; 2418 } else if (mmu_port < 64) { 2419 meter_egr_port_reg = METER_EGR_PORT_GRAN_1r; 2420 port_value = mmu_port - 32; 2421 } else { 2422 meter_egr_port_reg = METER_EGR_PORT_GRAN_2r; 2423 port_value = mmu_port - 64; 2424 } 2425 } 2426 2427 if (soc_reg_field_valid(unit, meter_egr_port_reg, 2428 meter_egr_port_field)) { 2429 flags |= _BCM_XGS_METER_FLAG_GRANULARITY; 2430 2431 BCM_IF_ERROR_RETURN(soc_reg32_get(unit, meter_egr_port_reg, 2432 REG_PORT_ANY, 0, ®val)); 2433 fval = soc_reg_field_get(unit, meter_egr_port_reg, 2434 regval, meter_egr_port_field); 2435 2436 if (fval & (1 << port_value)) { 2437 granularity = 5; 2438 } 2439 } 2440 #endif /* BCM_HURRICANE3_SUPPORT */ 2441 BCM_IF_ERROR_RETURN 2442 (_bcm_xgs_bucket_encoding_to_kbits(refresh_rate, bucketsize, 2443 granularity, flags, 2444 kbits_sec, kbits_burst)); 2445 #if defined(BCM_GREYHOUND_SUPPORT) 2446 if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) || 2447 SOC_IS_GREYHOUND2(unit)) { 2448 *mode = _BCM_PORT_RATE_BYTE_MODE; 2449 } 2450 #endif /* BCM_GREYHOUND_SUPPORT */ 2451 } else 2452 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */ 2453 { 2454 *kbits_sec = 64 * refresh_rate; 2455 *kbits_burst = _bcm_fb_bucketsize_to_kbits(bucketsize); 2456 } 2457 } 2458 return (BCM_E_NONE); 2459 } 2460 #endif /* BCM_FIREBOLT_SUPPORT */ 2461 2462 #ifdef BCM_TRIUMPH_SUPPORT 2463 /* 2464 * Function: 2465 * bcm_tr_port_rate_egress_set 2466 * Purpose: 2467 * Set egress rate limiting parameters for the Triumph chip. 2468 * Parameters: 2469 * unit - (IN)SOC unit number 2470 * port - (IN)Port number 2471 * kbits_sec - (IN)Rate in kilobits (1000 bits) per second. 2472 * Rate of 0 disables rate limiting. 2473 * kbits_burst -(IN)Maximum burst size in kilobits (1000 bits). 2474 * Returns: 2475 * BCM_E_XXX 2476 */ 2477 int 2478 bcm_tr_port_rate_egress_set(int unit, bcm_port_t port, 2479 uint32 kbits_sec, uint32 kbits_burst, uint32 mode) 2480 { 2481 uint32 miscval; 2482 uint64 regval; 2483 uint32 refresh_rate, bucketsize, granularity = 3, flags = 0; 2484 int refresh_bitsize, bucket_bitsize; 2485 2486 if (mode == _BCM_PORT_RATE_PPS_MODE) { 2487 return bcm_tr_port_pps_rate_egress_set( 2488 unit, port, kbits_sec, kbits_burst); 2489 } 2490 2491 /* 2492 * The procedure followed is first disable the egress metering i.e. 2493 * reset EGRMETERINGCONFIG, then clear the buckets and re-enable the 2494 * egress metering. Finally enable the MISCCONFING,Metering clocking 2495 * 2496 * NOTE: During the period of disabling and re-enabling the Egress metering 2497 * may be in-effective for couple of cycles 2498 */ 2499 2500 /* Disable egress metering for this port */ 2501 BCM_IF_ERROR_RETURN(READ_EGRMETERINGCONFIG_64r(unit, port, ®val)); 2502 soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, ®val, REFRESHf, 0); 2503 soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, ®val, THD_SELf, 0); 2504 if (soc_reg_field_valid(unit, EGRMETERINGCONFIG_64r, MODEf)) { 2505 soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, ®val, MODEf, 0); 2506 } 2507 BCM_IF_ERROR_RETURN(WRITE_EGRMETERINGCONFIG_64r(unit, port, regval)); 2508 2509 /* Reset metering bucket. */ 2510 BCM_IF_ERROR_RETURN(WRITE_EGRMETERINGBUCKETr(unit, port, 0)); 2511 2512 /* If kbits_sec=0, metering is disabled on this egress port*/ 2513 if (kbits_sec) { 2514 /* Enable metering for this port */ 2515 2516 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &miscval)); 2517 if (soc_reg_field_get(unit, MISCCONFIGr, miscval, ITU_MODE_SELf)) { 2518 flags |= _BCM_XGS_METER_FLAG_NON_LINEAR; 2519 } 2520 flags |= _BCM_XGS_METER_FLAG_GRANULARITY; 2521 if (SOC_IS_TD_TT(unit)) { 2522 flags |= _BCM_XGS_METER_FLAG_DOUBLE_REFRESH_FREQ; 2523 } 2524 refresh_bitsize = soc_reg_field_length(unit, EGRMETERINGCONFIG_64r, 2525 REFRESHf); 2526 bucket_bitsize = soc_reg_field_length(unit, EGRMETERINGCONFIG_64r, 2527 THD_SELf); 2528 BCM_IF_ERROR_RETURN 2529 (_bcm_xgs_kbits_to_bucket_encoding(kbits_sec, kbits_burst, flags, 2530 refresh_bitsize, bucket_bitsize, 2531 &refresh_rate, &bucketsize, &granularity)); 2532 if (soc_reg_field_valid(unit, EGRMETERINGCONFIG_64r, MODEf)) { 2533 soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, ®val, 2534 MODEf, 0); 2535 } 2536 if (soc_reg_field_valid(unit, EGRMETERINGCONFIG_64r, METER_GRANf)) { 2537 soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, ®val, 2538 METER_GRANf, granularity); 2539 } 2540 soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, ®val, 2541 REFRESHf, refresh_rate); 2542 soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, ®val, 2543 THD_SELf, bucketsize); 2544 BCM_IF_ERROR_RETURN(WRITE_EGRMETERINGCONFIG_64r(unit, port, regval)); 2545 } 2546 2547 /* MISCCONFIG.METERING_CLK_EN is set by chip init */ 2548 2549 return BCM_E_NONE; 2550 } 2551 2552 /* 2553 * Function: 2554 * bcm_tr_port_rate_egress_get 2555 * Purpose: 2556 * Get egress rate limiting parameters from the Triumph chip. 2557 * Parameters: 2558 * unit - (IN)SOC unit number. 2559 * port - (IN)Port number. 2560 * kbits_sec - (OUT)Rate in kilobits (1000 bits) per second, or 2561 * zero if rate limiting is disabled. 2562 * kbits_burst -(OUT) Maximum burst size in kilobits (1000 bits). 2563 * Returns: 2564 * BCM_E_XXX 2565 */ 2566 int 2567 bcm_tr_port_rate_egress_get(int unit, bcm_port_t port, 2568 uint32 *kbits_sec, uint32 *kbits_burst, uint32 *mode) 2569 { 2570 uint64 regval; /* EGRMETERINGCONFIGr register value. */ 2571 uint32 miscval; 2572 uint32 refresh_rate = 0, bucketsize = 0, granularity = 3, flags = 0; 2573 2574 COMPILER_64_ZERO(regval); 2575 2576 /* Input parameters check. */ 2577 if (!kbits_sec || !kbits_burst) { 2578 return (BCM_E_PARAM); 2579 } 2580 2581 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &miscval)); 2582 if (soc_reg_field_get(unit, MISCCONFIGr, miscval, ITU_MODE_SELf)) { 2583 flags |= _BCM_XGS_METER_FLAG_NON_LINEAR; 2584 } 2585 2586 BCM_IF_ERROR_RETURN(READ_EGRMETERINGCONFIG_64r(unit, port, ®val)); 2587 2588 if (soc_reg_field_valid(unit, EGRMETERINGCONFIG_64r, MODEf)) { 2589 if (1 == soc_reg64_field32_get(unit, EGRMETERINGCONFIG_64r, 2590 regval, MODEf)) { 2591 *mode = _BCM_PORT_RATE_PPS_MODE; 2592 return bcm_tr_port_pps_rate_egress_get(unit, port, 2593 kbits_sec, kbits_burst); 2594 } 2595 } 2596 2597 bucketsize = soc_reg64_field32_get(unit, EGRMETERINGCONFIG_64r, 2598 regval, THD_SELf); 2599 refresh_rate = soc_reg64_field32_get(unit, EGRMETERINGCONFIG_64r, 2600 regval, REFRESHf); 2601 flags |= _BCM_XGS_METER_FLAG_GRANULARITY; 2602 if (SOC_IS_TD_TT(unit)) { 2603 flags |= _BCM_XGS_METER_FLAG_DOUBLE_REFRESH_FREQ; 2604 } 2605 2606 if (soc_reg_field_valid(unit, EGRMETERINGCONFIG_64r, METER_GRANf)) { 2607 granularity = soc_reg64_field32_get(unit, EGRMETERINGCONFIG_64r, 2608 regval, METER_GRANf); 2609 } 2610 BCM_IF_ERROR_RETURN 2611 (_bcm_xgs_bucket_encoding_to_kbits(refresh_rate, bucketsize, 2612 granularity, flags, 2613 kbits_sec, kbits_burst)); 2614 2615 return (BCM_E_NONE); 2616 } 2617 2618 int 2619 bcm_tr_port_pps_rate_egress_set(int unit, bcm_port_t port, 2620 uint32 pps, uint32 burst) 2621 { 2622 uint32 miscval; 2623 uint64 regval; 2624 uint32 refresh_rate, bucketsize, granularity = 3, flags = 0; 2625 int refresh_bitsize, bucket_bitsize; 2626 2627 /* 2628 * The procedure followed is first disable the egress metering i.e. 2629 * reset EGRMETERINGCONFIG, then clear the buckets and re-enable the 2630 * egress metering. Finally enable the MISCCONFING,Metering clocking 2631 * 2632 * NOTE: During the period of disabling and re-enabling the Egress metering 2633 * may be in-effective for couple of cycles 2634 */ 2635 2636 /* Disable egress metering for this port */ 2637 BCM_IF_ERROR_RETURN(READ_EGRMETERINGCONFIG_64r(unit, port, ®val)); 2638 soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, ®val, REFRESHf, 0); 2639 soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, ®val, THD_SELf, 0); 2640 if (soc_reg_field_valid(unit, EGRMETERINGCONFIG_64r, MODEf)) { 2641 soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, ®val, MODEf, 0); 2642 } 2643 BCM_IF_ERROR_RETURN(WRITE_EGRMETERINGCONFIG_64r(unit, port, regval)); 2644 2645 /* Reset metering bucket. */ 2646 BCM_IF_ERROR_RETURN(WRITE_EGRMETERINGBUCKETr(unit, port, 0)); 2647 2648 /* If pps=0, metering is disabled on this egress port*/ 2649 if (pps) { 2650 /* Enable metering for this port */ 2651 2652 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &miscval)); 2653 if (soc_reg_field_get(unit, MISCCONFIGr, miscval, ITU_MODE_SELf)) { 2654 flags |= _BCM_XGS_METER_FLAG_NON_LINEAR; 2655 } 2656 flags |= _BCM_XGS_METER_FLAG_PACKET_MODE; 2657 flags |= _BCM_XGS_METER_FLAG_GRANULARITY; 2658 if (SOC_IS_TD_TT(unit)) { 2659 flags |= _BCM_XGS_METER_FLAG_DOUBLE_REFRESH_FREQ; 2660 } 2661 refresh_bitsize = soc_reg_field_length(unit, EGRMETERINGCONFIG_64r, 2662 REFRESHf); 2663 bucket_bitsize = soc_reg_field_length(unit, EGRMETERINGCONFIG_64r, 2664 THD_SELf); 2665 BCM_IF_ERROR_RETURN 2666 (_bcm_xgs_kbits_to_bucket_encoding(pps, burst, flags, 2667 refresh_bitsize, bucket_bitsize, 2668 &refresh_rate, &bucketsize, &granularity)); 2669 2670 if (soc_reg_field_valid(unit, EGRMETERINGCONFIG_64r, MODEf)) { 2671 soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, ®val, 2672 MODEf, 1); 2673 } 2674 if (soc_reg_field_valid(unit, EGRMETERINGCONFIG_64r, METER_GRANf)) { 2675 soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, ®val, 2676 METER_GRANf, granularity); 2677 } 2678 soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, ®val, 2679 REFRESHf, refresh_rate); 2680 soc_reg64_field32_set(unit, EGRMETERINGCONFIG_64r, ®val, 2681 THD_SELf, bucketsize); 2682 BCM_IF_ERROR_RETURN(WRITE_EGRMETERINGCONFIG_64r(unit, port, regval)); 2683 } 2684 2685 /* MISCCONFIG.METERING_CLK_EN is set by chip init */ 2686 2687 return BCM_E_NONE; 2688 } 2689 2690 int 2691 bcm_tr_port_pps_rate_egress_get(int unit, bcm_port_t port, 2692 uint32 *pps, uint32 *burst) 2693 { 2694 uint64 regval; /* EGRMETERINGCONFIGr register value. */ 2695 uint32 miscval; 2696 uint32 refresh_rate = 0, bucketsize = 0, granularity = 3, flags = 0; 2697 2698 COMPILER_64_ZERO(regval); 2699 2700 /* Input parameters check. */ 2701 if (!pps || !burst) { 2702 return (BCM_E_PARAM); 2703 } 2704 2705 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &miscval)); 2706 if (soc_reg_field_get(unit, MISCCONFIGr, miscval, ITU_MODE_SELf)) { 2707 flags |= _BCM_XGS_METER_FLAG_NON_LINEAR; 2708 } 2709 2710 BCM_IF_ERROR_RETURN(READ_EGRMETERINGCONFIG_64r(unit, port, ®val)); 2711 2712 bucketsize = soc_reg64_field32_get(unit, EGRMETERINGCONFIG_64r, 2713 regval, THD_SELf); 2714 refresh_rate = soc_reg64_field32_get(unit, EGRMETERINGCONFIG_64r, 2715 regval, REFRESHf); 2716 flags |= _BCM_XGS_METER_FLAG_PACKET_MODE; 2717 flags |= _BCM_XGS_METER_FLAG_GRANULARITY; 2718 if (SOC_IS_TD_TT(unit)) { 2719 flags |= _BCM_XGS_METER_FLAG_DOUBLE_REFRESH_FREQ; 2720 } 2721 2722 if (soc_reg_field_valid(unit, EGRMETERINGCONFIG_64r, METER_GRANf)) { 2723 granularity = soc_reg64_field32_get(unit, EGRMETERINGCONFIG_64r, 2724 regval, METER_GRANf); 2725 } 2726 BCM_IF_ERROR_RETURN 2727 (_bcm_xgs_bucket_encoding_to_kbits(refresh_rate, bucketsize, 2728 granularity, flags, 2729 pps, burst)); 2730 2731 return (BCM_E_NONE); 2732 } 2733 2734 #endif /* BCM_TRIUMPH_SUPPORT */ 2735 2736 /* 2737 * Function: 2738 * bcm_xgs3_port_cfg_get 2739 * Purpose: 2740 * Get port configuration. 2741 * Parameters: 2742 * unit - (IN)SOC unit number. 2743 * port - (IN)Port number. 2744 * port_cfg - (OUT)API port information structure. 2745 * Returns: 2746 * BCM_E_XXX 2747 */ 2748 int 2749 bcm_xgs3_port_cfg_get(int unit, bcm_port_t port, bcm_port_cfg_t *port_cfg) 2750 { 2751 /* Input parameters check.*/ 2752 if (NULL == port_cfg) { 2753 return (BCM_E_PARAM); 2754 } 2755 2756 sal_memset(port_cfg, 0, sizeof(bcm_port_cfg_t)); 2757 2758 /* Read port table entry. */ 2759 BCM_IF_ERROR_RETURN(_bcm_xgs3_port_table_read(unit, port, port_cfg)); 2760 2761 return(BCM_E_NONE); 2762 } 2763 2764 /* 2765 * Function: 2766 * bcm_xgs3_port_cfg_set 2767 * Purpose: 2768 * Set port configuration. 2769 * Parameters: 2770 * unit - (IN)SOC unit number. 2771 * port - (IN)Port number. 2772 * port_cfg - (IN)API port information structure. 2773 * Returns: 2774 * BCM_E_XXX 2775 */ 2776 int 2777 bcm_xgs3_port_cfg_set(int unit, bcm_port_t port, bcm_port_cfg_t *port_cfg) 2778 { 2779 /* Input parameters check.*/ 2780 if (NULL == port_cfg) { 2781 return (BCM_E_PARAM); 2782 } 2783 2784 /* Write port table entry. */ 2785 BCM_IF_ERROR_RETURN(_bcm_xgs3_port_table_write(unit, port, port_cfg)); 2786 2787 return (BCM_E_NONE); 2788 } 2789 2790 /* 2791 * Function: 2792 * bcm_xgs3_port_cfg_init 2793 * Purpose: 2794 * Initialize the port configuration according to Initial System 2795 * Configuration (see init.c) 2796 * Parameters: 2797 * unit - (IN)StrataSwitch unit number. 2798 * port - (IN)Port number. 2799 * vlan_data - (IN)Initial VLAN data information 2800 * Returns: 2801 * BCM_E_XXX 2802 */ 2803 int 2804 bcm_xgs3_port_cfg_init(int unit, bcm_port_t port, bcm_vlan_data_t *vlan_data) 2805 { 2806 #ifdef BCM_FIREBOLT_SUPPORT 2807 if(SOC_IS_FBX(unit)) { 2808 return _bcm_fb_port_cfg_init(unit, port, vlan_data); 2809 } 2810 #endif /* BCM_FIREBOLT_SUPPORT */ 2811 return (BCM_E_NONE); 2812 } 2813 2814 /* 2815 * Function: 2816 * bcm_xgs3_port_rate_ingress_set 2817 * Purpose: 2818 * Set ingress rate limiting parameters 2819 * Parameters: 2820 * unit - (IN) SOC unit number. 2821 * port - (IN) Port number. 2822 * kbits_sec - (IN) Rate in kilobits (1000 bits) per second. 2823 * Rate of 0 disables rate limiting. 2824 * kbits_burst - (IN) Maximum burst size in kilobits (1000 bits). 2825 * Returns: 2826 * BCM_E_XXX 2827 * Notes: 2828 * Rate-based pause frames automatically will be enabled 2829 * whenever ingress rate metering is enabled. Since the 2830 * pause frame behavior also affects the discard/accept 2831 * behavior of the ingress meter, the pause frame behavior 2832 * is set such that the discard/accept hysteresis is as 2833 * small as possible. 2834 */ 2835 int 2836 bcm_xgs3_port_rate_ingress_set(int unit, bcm_port_t port, 2837 uint32 kbits_sec, uint32 kbits_burst) 2838 { 2839 #ifdef BCM_MONTEREY_SUPPORT 2840 if (SOC_IS_MONTEREY(unit)) { 2841 return BCM_E_UNAVAIL; 2842 } else 2843 #endif 2844 #ifdef BCM_TOMAHAWK_SUPPORT 2845 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) { 2846 return BCM_E_UNAVAIL; 2847 } else 2848 #endif 2849 #ifdef BCM_TRIDENT2_SUPPORT 2850 if (SOC_IS_TD2_TT2(unit)) { 2851 return bcm_td2_port_rate_ingress_set(unit, port, kbits_sec, 2852 kbits_burst); 2853 } else 2854 #endif 2855 #ifdef BCM_TRIUMPH_SUPPORT 2856 if(SOC_IS_TR_VL(unit) && !SOC_IS_HURRICANEX(unit) && 2857 !SOC_IS_GREYHOUND(unit) && !SOC_IS_GREYHOUND2(unit)) { 2858 return _bcm_tr_port_rate_ingress_set(unit, port, 2859 kbits_sec, kbits_burst); 2860 } else 2861 #endif 2862 #ifdef BCM_FIREBOLT_SUPPORT 2863 if(SOC_IS_FBX(unit)) { 2864 return _bcm_fb_port_rate_ingress_set(unit, port, 2865 kbits_sec, kbits_burst); 2866 } 2867 #endif /* BCM_FIREBOLT_SUPPORT */ 2868 return (BCM_E_UNAVAIL); 2869 } 2870 2871 /* 2872 * Function: 2873 * bcm_xgs3_port_rate_ingress_get 2874 * Purpose: 2875 * Get ingress rate limiting parameters 2876 * Parameters: 2877 * unit - (IN)SOC unit number. 2878 * port - (IN)Port number. 2879 * kbits_sec - (OUT) Rate in kilobits (1000 bits) per second, or 2880 * zero if rate limiting is disabled. 2881 * kbits_burst - (OUT) Maximum burst size in kilobits (1000 bits). 2882 * Returns: 2883 * BCM_E_XXX 2884 */ 2885 int 2886 bcm_xgs3_port_rate_ingress_get(int unit, bcm_port_t port, 2887 uint32 *kbits_sec, uint32 *kbits_burst) 2888 { 2889 2890 #ifdef BCM_MONTEREY_SUPPORT 2891 if (SOC_IS_MONTEREY(unit)) { 2892 return BCM_E_UNAVAIL; 2893 } else 2894 #endif 2895 #ifdef BCM_TOMAHAWK_SUPPORT 2896 if (SOC_IS_TOMAHAWKX(unit) || SOC_IS_TRIDENT3X(unit)) { 2897 return BCM_E_UNAVAIL; 2898 } else 2899 #endif 2900 #ifdef BCM_TRIDENT2_SUPPORT 2901 if (SOC_IS_TD2_TT2(unit)) { 2902 return bcm_td2_port_rate_ingress_get(unit, port, kbits_sec, 2903 kbits_burst); 2904 } else 2905 #endif 2906 #ifdef BCM_TRIUMPH_SUPPORT 2907 if(SOC_IS_TR_VL(unit) && !SOC_IS_HURRICANEX(unit) && 2908 !SOC_IS_GREYHOUND(unit) && !SOC_IS_GREYHOUND2(unit)) { 2909 return _bcm_tr_port_rate_ingress_get(unit, port, 2910 kbits_sec, kbits_burst); 2911 } else 2912 #endif 2913 #ifdef BCM_FIREBOLT_SUPPORT 2914 if(SOC_IS_FBX(unit)) { 2915 return _bcm_fb_port_rate_ingress_get(unit, port, 2916 kbits_sec, kbits_burst); 2917 } 2918 #endif /* BCM_FIREBOLT_SUPPORT */ 2919 return (BCM_E_UNAVAIL); 2920 } 2921 2922 /* 2923 * MAX_SFLOW_RANGE is used for converting a sampling rate to a threshold 2924 * value used for comparison with the sFlow random number for a port. 2925 * If the random number is less than the threshold value, an sFlow 2926 * sample record is sent to the CPU. 2927 */ 2928 #define MAX_SFLOW_RANGE (1 << (SFLOW_RANGE_MAX(unit))) 2929 2930 /* 2931 * Function: 2932 * _bcm_xgs3_port_sample_rate_set 2933 * Purpose: 2934 * Set rate sampling parameters for XGS3 family chip. 2935 * Parameters: 2936 * unit - (IN)SOC unit number. 2937 * port - (IN)Port number. 2938 * rate - (IN)Every 1/rate a packet will be sampled 2939 * 1 indicating sample all. 2940 * 0 indicating sample none. 2941 * rate_reg - (IN)Ingress/Egress rate register. 2942 * Returns: 2943 * BCM_E_XXX 2944 */ 2945 int 2946 _bcm_xgs3_port_sample_rate_set(int unit, bcm_port_t port, 2947 int rate, soc_reg_t reg) 2948 { 2949 soc_field_t fields[2] = {ENABLEf, THRESHOLDf}; 2950 uint32 values[2] = {0, 0}; 2951 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 2952 sflow_ing_data_source_entry_t sflow_entry; 2953 soc_counter_non_dma_t *non_dma = NULL; 2954 soc_control_t *soc; 2955 uint32 count = 0, subset_ct = 0; 2956 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_TRIDENT3_SUPPORT */ 2957 2958 /* Setup 'enable' and 'threshold' fields for register. */ 2959 if (rate > 0) { 2960 2961 /* Enable sFlow */ 2962 values[0] = 1; 2963 2964 /* Set sampling threshold */ 2965 if (rate == 1) { 2966 /* Needs special handling to avoid register overflow */ 2967 values[1] = MAX_SFLOW_RANGE - 1; 2968 } else { 2969 /* Calculate threshold based on sampling rate */ 2970 values[1] = MAX_SFLOW_RANGE / rate; 2971 } 2972 2973 /* 2974 * For early sFlow implementations the 16-bit threshold value 2975 * is compared to bits [23:8] of the sFlow random number. 2976 */ 2977 if (soc_feature(unit, soc_feature_sample_offset8)) { 2978 values[1] >>= 8; 2979 } 2980 2981 /* Cut the value in case 16 bit threshold can not accomodate it. */ 2982 if (soc_feature(unit, soc_feature_sample_thresh16)) { 2983 if (values[1] >= (1 << 16)) { 2984 values[1] = (1 << 16) - 1; 2985 } 2986 } 2987 } 2988 2989 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 2990 /* Update Ingress rate limiting data table. */ 2991 if((reg == SFLOW_ING_THRESHOLDr) && 2992 soc_feature(unit, soc_feature_sflow_ing_mem)) { 2993 BCM_IF_ERROR_RETURN( 2994 READ_SFLOW_ING_DATA_SOURCEm(unit, MEM_BLOCK_ANY, port, 2995 &sflow_entry)); 2996 soc_SFLOW_ING_DATA_SOURCEm_field_set(unit, &sflow_entry, fields[0], 2997 &values[0]); 2998 soc_SFLOW_ING_DATA_SOURCEm_field_set(unit, &sflow_entry, fields[1], 2999 &values[1]); 3000 soc_SFLOW_ING_DATA_SOURCEm_field_set(unit, &sflow_entry, CPUf, 3001 &values[0]); 3002 BCM_IF_ERROR_RETURN( 3003 WRITE_SFLOW_ING_DATA_SOURCEm(unit, MEM_BLOCK_ANY, port, 3004 &sflow_entry)); 3005 3006 /* Enable counter thread for Ingress sFlow samplers */ 3007 if (values[0] == 1) { 3008 soc = SOC_CONTROL(unit); 3009 non_dma = &soc->counter_non_dma[SOC_COUNTER_NON_DMA_SFLOW_ING_PKT - 3010 SOC_COUNTER_NON_DMA_START]; 3011 if (non_dma && !(non_dma->flags & _SOC_COUNTER_NON_DMA_VALID)) { 3012 /* Do PACKET_CTRf and BYTE_CTRf sequentially. Hence 2x loop */ 3013 subset_ct = non_dma->extra_ctr_ct << 1; 3014 non_dma->flags |= _SOC_COUNTER_NON_DMA_VALID; 3015 non_dma = non_dma->extra_ctrs; 3016 3017 if (non_dma) { 3018 do { 3019 non_dma->flags |= _SOC_COUNTER_NON_DMA_VALID; 3020 /* BYTE_CTRf not currently supported */ 3021 count += 2; 3022 non_dma += 2; 3023 } while (non_dma && (count < subset_ct)); 3024 } 3025 } 3026 } 3027 return BCM_E_NONE; 3028 } else if (!SOC_REG_IS_VALID(unit, reg)) { 3029 return BCM_E_UNAVAIL; 3030 } 3031 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_TRIDENT3_SUPPORT */ 3032 3033 /* Update rate limiting regster values. */ 3034 return soc_reg_fields32_modify(unit, reg, port, 3035 sizeof(fields)/sizeof(uint32), 3036 fields, values); 3037 } 3038 3039 /* 3040 * Function: 3041 * bcm_xgs3_port_sample_rate_set 3042 * Purpose: 3043 * Set rate sampling parameters for XGS3 family chip. 3044 * Parameters: 3045 * unit - (IN)SOC unit number. 3046 * port - (IN)Port number. 3047 * ingress_rate - (IN)Every 1/ingress_rate a packet will be sampled 3048 * 1 indicating sample all. 3049 * 0 indicating sample none. 3050 * egress_rate - (IN)Every 1/egress_rate a packet will be sampled 3051 * 1 indicating sample all. 3052 * 0 indicating sample none. 3053 * Returns: 3054 * BCM_E_XXX 3055 */ 3056 int 3057 bcm_xgs3_port_sample_rate_set(int unit, bcm_port_t port, 3058 int ingress_rate, int egress_rate ) 3059 { 3060 /* Set ingress rate limiting. */ 3061 BCM_IF_ERROR_RETURN 3062 (_bcm_xgs3_port_sample_rate_set(unit, port, ingress_rate, 3063 SFLOW_ING_THRESHOLDr)); 3064 3065 /* Set egress rate limiting. */ 3066 return _bcm_xgs3_port_sample_rate_set(unit, port, egress_rate, 3067 SFLOW_EGR_THRESHOLDr); 3068 } 3069 3070 /* 3071 * Function: 3072 * bcm_xgs3_port_sample_rate_get 3073 * Purpose: 3074 * Get rate sampling parameters from the hw. 3075 * Parameters: 3076 * unit - (IN)SOC unit number. 3077 * port - (IN)Port number. 3078 * ingress_rate - (OUT)Every 1/ingress_rate a packet will be sampled 3079 * 1 indicating sample all. 3080 * 0 indicating sample none. 3081 * egress_rate - (OUT)Every 1/egress_rate a packet will be sampled 3082 * 1 indicating sample all. 3083 * 0 indicating sample none. 3084 * Returns: 3085 * BCM_E_XXX 3086 */ 3087 int 3088 bcm_xgs3_port_sample_rate_get(int unit, bcm_port_t port, 3089 int *ingress_rate, int *egress_rate ) 3090 { 3091 uint32 ingress_regval = 0; 3092 uint32 ingress_field_enable = 0; 3093 uint32 ingress_field_thresh; 3094 uint32 egress_regval; 3095 uint32 egress_field_enable; 3096 uint32 egress_field_thresh; 3097 #ifdef BCM_TOMAHAWK_SUPPORT 3098 sflow_ing_data_source_entry_t sflow_entry; 3099 #endif /* BCM_TOMAHAWK_SUPPORT */ 3100 3101 /* Input parameters sanity. */ 3102 if ((NULL == ingress_rate) || (NULL == egress_rate)) { 3103 return (BCM_E_PARAM); 3104 } 3105 3106 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 3107 if (soc_feature(unit, soc_feature_sflow_ing_mem)) { 3108 BCM_IF_ERROR_RETURN( 3109 READ_SFLOW_ING_DATA_SOURCEm(unit, MEM_BLOCK_ANY, port, 3110 &sflow_entry)); 3111 } else 3112 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_TRIDENT3_SUPPORT */ 3113 3114 #if defined(BCM_TOMAHAWK_SUPPORT) 3115 if (SOC_REG_IS_VALID(unit,SFLOW_ING_THRESHOLDr)){ 3116 BCM_IF_ERROR_RETURN(READ_SFLOW_ING_THRESHOLDr(unit, port, 3117 &ingress_regval)); 3118 } else { 3119 return BCM_E_UNAVAIL; 3120 } 3121 #else 3122 BCM_IF_ERROR_RETURN(READ_SFLOW_ING_THRESHOLDr(unit, port, &ingress_regval)); 3123 #endif 3124 BCM_IF_ERROR_RETURN(READ_SFLOW_EGR_THRESHOLDr(unit, port, &egress_regval)); 3125 3126 /* read 'enable' and 'threshold' fields for ingress and egress ports */ 3127 #if defined(BCM_TOMAHAWK_SUPPORT) || defined(BCM_TRIDENT3_SUPPORT) 3128 if (soc_feature(unit, soc_feature_sflow_ing_mem)) { 3129 soc_SFLOW_ING_DATA_SOURCEm_field_get(unit, &sflow_entry, ENABLEf, 3130 &ingress_field_enable); 3131 soc_SFLOW_ING_DATA_SOURCEm_field_get(unit, &sflow_entry, THRESHOLDf, 3132 &ingress_field_thresh); 3133 } else 3134 #endif /* BCM_TOMAHAWK_SUPPORT || BCM_TRIDENT3_SUPPORT */ 3135 { 3136 ingress_field_enable = soc_reg_field_get(unit, SFLOW_ING_THRESHOLDr, 3137 ingress_regval, ENABLEf); 3138 ingress_field_thresh = soc_reg_field_get(unit, SFLOW_ING_THRESHOLDr, 3139 ingress_regval, THRESHOLDf); 3140 } 3141 egress_field_enable = soc_reg_field_get(unit, SFLOW_EGR_THRESHOLDr, 3142 egress_regval, ENABLEf); 3143 egress_field_thresh = soc_reg_field_get(unit, SFLOW_EGR_THRESHOLDr, 3144 egress_regval, THRESHOLDf); 3145 3146 /* 3147 * For early sFlow implementations the 16-bit threshold value 3148 * is compared to bits [23:8] of the sFlow random number. 3149 */ 3150 if (soc_feature(unit, soc_feature_sample_offset8)) { 3151 ingress_field_thresh <<= 8; 3152 egress_field_thresh <<= 8; 3153 } 3154 3155 /* Translate fields into ingress and egress rates */ 3156 if (ingress_field_enable) { 3157 if (ingress_field_thresh) { 3158 *ingress_rate = MAX_SFLOW_RANGE / ingress_field_thresh; 3159 } else { 3160 *ingress_rate = MAX_SFLOW_RANGE; 3161 } 3162 } 3163 else { 3164 *ingress_rate = 0; 3165 if (ingress_field_thresh) { 3166 return (BCM_E_INTERNAL); 3167 } 3168 } 3169 3170 if (egress_field_enable) { 3171 if (egress_field_thresh) { 3172 *egress_rate = MAX_SFLOW_RANGE / egress_field_thresh; 3173 } else { 3174 *egress_rate = MAX_SFLOW_RANGE; 3175 } 3176 } 3177 else { 3178 *egress_rate = 0; 3179 if (egress_field_thresh) { 3180 return (BCM_E_INTERNAL); 3181 } 3182 } 3183 3184 return (BCM_E_NONE); 3185 } 3186 #undef MAX_SFLOW_RANGE 3187 /* 3188 * Function: 3189 * _bcm_fb_port_protocol_vlan_add 3190 * Purpose: 3191 * Adds a protocol based vlan to a port. The protocol 3192 * is matched by frame type and ether type. 3193 * Parameters: 3194 * unit - (IN) BCM device number 3195 * port - (IN) Port number 3196 * frame - (IN) one of BCM_PORT_FRAMETYPE_{ETHER2,8023,LLC} 3197 * ether - (IN) 16 bit Ethernet type field 3198 * vid - (IN)VLAN ID 3199 * Returns: 3200 * BCM_E_XXX 3201 */ 3202 int 3203 _bcm_fb_port_protocol_vlan_add(int unit, 3204 bcm_port_t port, 3205 bcm_port_frametype_t frame, 3206 bcm_port_ethertype_t ether, 3207 bcm_vlan_t vid) 3208 { 3209 bcm_port_frametype_t ft; 3210 bcm_port_ethertype_t et; 3211 bcm_port_t p; 3212 _bcm_port_info_t *pinfo; 3213 vlan_protocol_entry_t vpe; 3214 vlan_protocol_data_entry_t vde; 3215 int idxmin, idxmax; 3216 int vlan_prot_entries; 3217 int vpentry, vdentry; 3218 bcm_pbmp_t switched_pbm; 3219 int i; 3220 int empty; 3221 3222 idxmin = soc_mem_index_min(unit, VLAN_PROTOCOLm); 3223 idxmax = soc_mem_index_max(unit, VLAN_PROTOCOLm); 3224 vlan_prot_entries = idxmax + 1; 3225 vpentry = empty = -1; 3226 for (i = idxmin; i <= idxmax; i++) { 3227 SOC_IF_ERROR_RETURN 3228 (READ_VLAN_PROTOCOLm(unit, MEM_BLOCK_ANY, i, &vpe)); 3229 ft = 0; 3230 if (soc_VLAN_PROTOCOLm_field32_get(unit, &vpe, ETHERIIf)) { 3231 ft |= BCM_PORT_FRAMETYPE_ETHER2; 3232 } 3233 if (soc_VLAN_PROTOCOLm_field32_get(unit, &vpe, SNAPf)) { 3234 ft |= BCM_PORT_FRAMETYPE_8023; 3235 } 3236 if (soc_VLAN_PROTOCOLm_field32_get(unit, &vpe, LLCf)) { 3237 ft |= BCM_PORT_FRAMETYPE_LLC; 3238 } 3239 et = soc_VLAN_PROTOCOLm_field32_get(unit, &vpe, ETHERTYPEf); 3240 if (empty < 0 && ft == 0) { 3241 empty = i; 3242 } 3243 if (ft == frame && et == ether) { 3244 vpentry = i; 3245 break; 3246 } 3247 } 3248 if (vpentry < 0 && empty < 0) { 3249 return BCM_E_FULL; 3250 } 3251 if (vpentry < 0) { 3252 sal_memset(&vpe, 0, sizeof(vpe)); 3253 soc_VLAN_PROTOCOLm_field32_set(unit, &vpe, ETHERTYPEf, ether); 3254 if (frame & BCM_PORT_FRAMETYPE_ETHER2) { 3255 soc_VLAN_PROTOCOLm_field32_set(unit, &vpe, ETHERIIf, 1); 3256 } 3257 if (frame & BCM_PORT_FRAMETYPE_8023) { 3258 soc_VLAN_PROTOCOLm_field32_set(unit, &vpe, SNAPf, 1); 3259 } 3260 if (frame & BCM_PORT_FRAMETYPE_LLC) { 3261 soc_VLAN_PROTOCOLm_field32_set(unit, &vpe, LLCf, 1); 3262 } 3263 soc_VLAN_PROTOCOLm_field32_set(unit, &vpe, MATCHUPPERf, 1); 3264 soc_VLAN_PROTOCOLm_field32_set(unit, &vpe, MATCHLOWERf, 1); 3265 SOC_IF_ERROR_RETURN 3266 (WRITE_VLAN_PROTOCOLm(unit, MEM_BLOCK_ALL, empty, &vpe)); 3267 vpentry = empty; 3268 } 3269 3270 /* 3271 * Set VLAN ID for target port. For all other ethernet ports, 3272 * make sure entries indexed by the matched entry in VLAN_PROTOCOL 3273 * have initialized values (either default or explicit VID). 3274 */ 3275 switched_pbm = PBMP_E_ALL(unit); 3276 if (soc_feature(unit, soc_feature_cpuport_switched)) { 3277 BCM_PBMP_OR(switched_pbm, PBMP_CMIC(unit)); 3278 } 3279 3280 BCM_PBMP_ITER(switched_pbm, p) { 3281 bcm_vlan_t cvid, defvid, wvid; 3282 vdentry = (p * vlan_prot_entries) 3283 + vpentry; 3284 SOC_IF_ERROR_RETURN 3285 (READ_VLAN_PROTOCOL_DATAm(unit, MEM_BLOCK_ANY, 3286 vdentry, &vde)); 3287 wvid = vid; 3288 cvid = soc_VLAN_PROTOCOL_DATAm_field32_get(unit, &vde, VLAN_IDf); 3289 BCM_IF_ERROR_RETURN 3290 (bcm_esw_port_untagged_vlan_get(unit, p, &defvid)); 3291 3292 BCM_IF_ERROR_RETURN(_bcm_port_info_get(unit, p, &pinfo)); 3293 if (p == port) { 3294 if (_BCM_PORT_VD_PBVL_IS_SET(pinfo, vpentry)) { 3295 /* Already explicit VID; must remove first. */ 3296 return BCM_E_EXISTS; 3297 } 3298 /* Set as explicit VID */ 3299 _BCM_PORT_VD_PBVL_SET(pinfo, vpentry); 3300 if (cvid == vid) { 3301 /* Current (default) VID same as explicit VID */ 3302 continue; 3303 } 3304 } else { 3305 /* 3306 * For all other ports, if no non-zero VID already set, 3307 * set to default VLAN ID. 3308 */ 3309 if (cvid != 0) { 3310 continue; 3311 } 3312 wvid = defvid; 3313 _BCM_PORT_VD_PBVL_CLEAR(pinfo, vpentry); 3314 } 3315 3316 sal_memset(&vde, 0, sizeof(vde)); 3317 soc_VLAN_PROTOCOL_DATAm_field32_set(unit, &vde, VLAN_IDf, wvid); 3318 soc_VLAN_PROTOCOL_DATAm_field32_set(unit, &vde, PRIf, pinfo->p_ut_prio); 3319 SOC_IF_ERROR_RETURN 3320 (WRITE_VLAN_PROTOCOL_DATAm(unit, MEM_BLOCK_ALL, 3321 vdentry, &vde)); 3322 } 3323 return BCM_E_NONE; 3324 } 3325 3326 /* 3327 * Function: 3328 * _bcm_fb_port_protocol_vlan_delete 3329 * Purpose: 3330 * Remove an already created proto protocol based vlan 3331 * on a port. 3332 * Parameters: 3333 * unit - (IN) BCM device number 3334 * port - (IN) Port number 3335 * frame - (IN) one of BCM_PORT_FRAMETYPE_{ETHER2,8023,LLC} 3336 * ether - (IN) 16 bit Ethernet type field 3337 * Returns: 3338 * BCM_E_XXX 3339 */ 3340 3341 int 3342 _bcm_fb_port_protocol_vlan_delete(int unit, 3343 bcm_port_t port, 3344 bcm_port_frametype_t frame, 3345 bcm_port_ethertype_t ether) 3346 { 3347 bcm_port_frametype_t ft; 3348 bcm_port_ethertype_t et; 3349 vlan_protocol_entry_t vpe; 3350 vlan_protocol_data_entry_t vde; 3351 bcm_vlan_t cvid, defvid; 3352 int idxmin, idxmax; 3353 int vlan_prot_entries; 3354 int vpentry, vdentry, p, valid; 3355 bcm_pbmp_t switched_pbm; 3356 _bcm_port_info_t *pinfo; 3357 int i; 3358 3359 idxmin = soc_mem_index_min(unit, VLAN_PROTOCOLm); 3360 idxmax = soc_mem_index_max(unit, VLAN_PROTOCOLm); 3361 vlan_prot_entries = idxmax + 1; 3362 vpentry = -1; 3363 for (i = idxmin; i <= idxmax; i++) { 3364 SOC_IF_ERROR_RETURN 3365 (READ_VLAN_PROTOCOLm(unit, MEM_BLOCK_ANY, i, &vpe)); 3366 ft = 0; 3367 if (soc_VLAN_PROTOCOLm_field32_get(unit, &vpe, ETHERIIf)) { 3368 ft |= BCM_PORT_FRAMETYPE_ETHER2; 3369 } 3370 if (soc_VLAN_PROTOCOLm_field32_get(unit, &vpe, SNAPf)) { 3371 ft |= BCM_PORT_FRAMETYPE_8023; 3372 } 3373 if (soc_VLAN_PROTOCOLm_field32_get(unit, &vpe, LLCf)) { 3374 ft |= BCM_PORT_FRAMETYPE_LLC; 3375 } 3376 et = soc_VLAN_PROTOCOLm_field32_get(unit, &vpe, ETHERTYPEf); 3377 if (ft == frame && et == ether) { 3378 vpentry = i; 3379 break; 3380 } 3381 } 3382 if (vpentry < 0) { 3383 return BCM_E_NOT_FOUND; 3384 } 3385 vdentry = (port * vlan_prot_entries) + vpentry; 3386 SOC_IF_ERROR_RETURN 3387 (READ_VLAN_PROTOCOL_DATAm(unit, MEM_BLOCK_ANY, vdentry, &vde)); 3388 cvid = soc_VLAN_PROTOCOL_DATAm_field32_get(unit, &vde, VLAN_IDf); 3389 BCM_IF_ERROR_RETURN 3390 (bcm_esw_port_untagged_vlan_get(unit, port, &defvid)); 3391 /* 3392 * Entry is initialized (undefined) if VLAN ID is 0. 3393 * Otherwise, entry is a default VID entry if not programmed. 3394 * Since we are attempting to remove an "explicit" VID entry, 3395 * the indexed VLAN_PROTOCOL_DATA entry must be defined and 3396 * not merely a default VID entry. 3397 */ 3398 BCM_IF_ERROR_RETURN(_bcm_port_info_get(unit, port, &pinfo)); 3399 if (cvid == 0 || 3400 (cvid == defvid && (!_BCM_PORT_VD_PBVL_IS_SET(pinfo, vpentry)))) { 3401 return BCM_E_NOT_FOUND; 3402 } 3403 sal_memset(&vde, 0, sizeof(vde)); 3404 /* set to default VLAN ID and mark it as not programmed */ 3405 soc_VLAN_PROTOCOL_DATAm_field32_set(unit, &vde, VLAN_IDf, defvid); 3406 _BCM_PORT_VD_PBVL_CLEAR(pinfo, vpentry); 3407 SOC_IF_ERROR_RETURN 3408 (WRITE_VLAN_PROTOCOL_DATAm(unit, MEM_BLOCK_ALL, vdentry, &vde)); 3409 /* 3410 * See if any other port has an explicit vlan_protocol_data 3411 * entry for the indicated protocol. 3412 */ 3413 valid = 0; 3414 switched_pbm = PBMP_E_ALL(unit); 3415 if (soc_feature(unit, soc_feature_cpuport_switched)) { 3416 BCM_PBMP_OR(switched_pbm, PBMP_CMIC(unit)); 3417 } 3418 3419 BCM_PBMP_ITER(switched_pbm, p) { 3420 if (p == port) { /* skip the entry we just "defaulted" */ 3421 continue; 3422 } 3423 BCM_IF_ERROR_RETURN(_bcm_port_info_get(unit, p, &pinfo)); 3424 /* Check for explicit VID entry */ 3425 if (_BCM_PORT_VD_PBVL_IS_SET(pinfo, vpentry)) { 3426 valid = 1; 3427 break; 3428 } 3429 } 3430 if (!valid) { 3431 /* 3432 * Clear all ports' VLAN_PROTOCOL_DATA entries 3433 * associated with this protocol. 3434 */ 3435 BCM_PBMP_ITER(switched_pbm, p) { 3436 vdentry = (p * vlan_prot_entries) + vpentry; 3437 sal_memset(&vde, 0, sizeof(vde)); 3438 SOC_IF_ERROR_RETURN 3439 (WRITE_VLAN_PROTOCOL_DATAm(unit, MEM_BLOCK_ALL, 3440 vdentry, &vde)); 3441 BCM_IF_ERROR_RETURN(_bcm_port_info_get(unit, p, &pinfo)); 3442 _BCM_PORT_VD_PBVL_CLEAR(pinfo, vpentry); 3443 } 3444 /* clear VLAN_PROTOCOL entry */ 3445 sal_memset(&vpe, 0, sizeof(vpe)); 3446 SOC_IF_ERROR_RETURN 3447 (WRITE_VLAN_PROTOCOLm(unit, MEM_BLOCK_ALL, vpentry, &vpe)); 3448 } 3449 return BCM_E_NONE; 3450 } 3451 3452 /* 3453 * Function: 3454 * _bcm_fb_port_untagged_vlan_data_update 3455 * Purpose: 3456 * Update VLAN_PROTOCOL_DATA with new default VLAN ID for port 3457 * Parameters: 3458 * unit - StrataSwitch unit number. 3459 * port - StrataSwitch port number of port to get info for 3460 * pdvid- Previous default VLAN ID 3461 * ndvid- New default VLAN ID 3462 * Returns: 3463 * BCM_XX_NONE 3464 */ 3465 int 3466 _bcm_fb_port_untagged_vlan_data_update(int unit, bcm_port_t port, 3467 bcm_vlan_t pdvid, bcm_vlan_t ndvid) 3468 { 3469 vlan_protocol_data_entry_t vde; 3470 _bcm_port_info_t *pinfo; 3471 int idx; 3472 int vlan_prot_entries, vlan_data_prot_start; 3473 3474 vlan_prot_entries = soc_mem_index_count(unit, VLAN_PROTOCOLm); 3475 vlan_data_prot_start = (port * vlan_prot_entries); 3476 for (idx = 0; idx < vlan_prot_entries; idx++) { 3477 SOC_IF_ERROR_RETURN 3478 (READ_VLAN_PROTOCOL_DATAm(unit, MEM_BLOCK_ANY, 3479 vlan_data_prot_start + idx, &vde)); 3480 /* 3481 * Update entry with new default VLAN ID if not a programmed 3482 * VLAN ID and entry has previous default VLAN ID 3483 */ 3484 BCM_IF_ERROR_RETURN(_bcm_port_info_get(unit, port, &pinfo)); 3485 if ( (!(_BCM_PORT_VD_PBVL_IS_SET(pinfo, idx))) && 3486 (soc_VLAN_PROTOCOL_DATAm_field32_get(unit, &vde, VLAN_IDf) 3487 == pdvid) ) { 3488 soc_VLAN_PROTOCOL_DATAm_field32_set(unit, &vde, VLAN_IDf, ndvid); 3489 SOC_IF_ERROR_RETURN 3490 (WRITE_VLAN_PROTOCOL_DATAm(unit, MEM_BLOCK_ALL, 3491 vlan_data_prot_start + idx, &vde)); 3492 } 3493 } 3494 return BCM_E_NONE; 3495 } 3496 3497 /* 3498 * Function: 3499 * _bcm_fb_port_tpid_get 3500 * Description: 3501 * Get the default Tag Protocol ID for a port. 3502 * Parameters: 3503 * unit - Device number 3504 * port - Port number 3505 * tpid - Tag Protocol ID 3506 * Return Value: 3507 * BCM_E_XXX 3508 */ 3509 int 3510 _bcm_fb_port_tpid_get(int unit, bcm_port_t port, uint16 *tpid) 3511 { 3512 port_tab_entry_t ptab; 3513 int rv; 3514 3515 rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, port, &ptab); 3516 BCM_IF_ERROR_RETURN(rv); 3517 3518 *tpid = soc_PORT_TABm_field32_get(unit, &ptab, OUTER_TPIDf); 3519 return (BCM_E_NONE); 3520 } 3521 3522 /* 3523 * Function: 3524 * _bcm_fb_port_tpid_set 3525 * Description: 3526 * Set the default Tag Protocol ID for a port. 3527 * Parameters: 3528 * unit - Device number 3529 * port - Port number 3530 * tpid - Tag Protocol ID 3531 * Return Value: 3532 * BCM_E_XXX 3533 */ 3534 3535 int 3536 _bcm_fb_port_tpid_set(int unit, bcm_port_t port, uint16 tpid) 3537 { 3538 port_tab_entry_t ptab; 3539 int rv; 3540 3541 rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, port, &ptab); 3542 BCM_IF_ERROR_RETURN(rv); 3543 3544 soc_PORT_TABm_field32_set(unit, &ptab, OUTER_TPIDf, tpid); 3545 rv = soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL, port, &ptab); 3546 BCM_IF_ERROR_RETURN(rv); 3547 3548 #ifdef BCM_TRIDENT2PLUS_SUPPORT 3549 if (soc_feature(unit, soc_feature_egr_vlan_control_is_memory)) { 3550 if (soc_feature(unit, soc_feature_egr_all_profile)) { 3551 BCM_IF_ERROR_RETURN(bcm_esw_port_egr_lport_field_set(unit, 3552 port, EGR_VLAN_CONTROL_1m, OUTER_TPIDf, tpid)); 3553 } else { 3554 SOC_IF_ERROR_RETURN(soc_mem_field32_modify(unit, 3555 EGR_VLAN_CONTROL_1m, port, OUTER_TPIDf, tpid)); 3556 } 3557 } else 3558 #endif 3559 { 3560 rv = soc_reg_field32_modify(unit, EGR_VLAN_CONTROL_1r, port, 3561 OUTER_TPIDf, tpid); 3562 } 3563 return rv; 3564 } 3565 3566 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_TRX_SUPPORT) || \ 3567 defined(BCM_RAVEN_SUPPORT) 3568 int 3569 _bcm_fb2_port_tpid_enable_get(int unit, bcm_port_t port, uint32 *tpid_enable) 3570 { 3571 #ifdef BCM_TRIDENT2PLUS_SUPPORT 3572 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 3573 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 3574 int modid = _BCM_SUBPORT_COE_PORT_ID_MOD_GET(port); 3575 int mod_port = _BCM_SUBPORT_COE_PORT_ID_PORT_GET(port); 3576 BCM_IF_ERROR_RETURN( 3577 _bcm_td_mod_port_tpid_enable_read( 3578 unit, modid, mod_port, (int*)tpid_enable)); 3579 } else 3580 #endif 3581 #if defined(BCM_TRX_SUPPORT) 3582 if (SOC_MEM_FIELD_VALID(unit, SOURCE_TRUNK_MAP_TABLEm, OUTER_TPID_ENABLEf)) { 3583 BCM_IF_ERROR_RETURN( 3584 _bcm_trx_source_trunk_map_get(unit, port, OUTER_TPID_ENABLEf, 3585 tpid_enable)); 3586 } else 3587 #endif 3588 { 3589 port_tab_entry_t ptab; 3590 SOC_IF_ERROR_RETURN( 3591 soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, port, &ptab)); 3592 *tpid_enable = soc_mem_field32_get(unit, PORT_TABm, 3593 &ptab, OUTER_TPID_ENABLEf); 3594 } 3595 3596 return BCM_E_NONE; 3597 } 3598 3599 int 3600 _bcm_fb2_port_tpid_enable_set(int unit, bcm_port_t port, uint32 tpid_enable) 3601 { 3602 #ifdef BCM_TRIDENT2PLUS_SUPPORT 3603 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 3604 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 3605 int modid = _BCM_SUBPORT_COE_PORT_ID_MOD_GET(port); 3606 int mod_port = _BCM_SUBPORT_COE_PORT_ID_PORT_GET(port); 3607 BCM_IF_ERROR_RETURN( 3608 _bcm_td_mod_port_tpid_enable_write( 3609 unit, modid, mod_port, tpid_enable)); 3610 } else 3611 #endif 3612 #ifdef BCM_TRX_SUPPORT 3613 if (SOC_MEM_FIELD_VALID(unit, SOURCE_TRUNK_MAP_TABLEm, OUTER_TPID_ENABLEf)) { 3614 BCM_IF_ERROR_RETURN( 3615 _bcm_trx_source_trunk_map_set(unit, port, OUTER_TPID_ENABLEf, 3616 tpid_enable)); 3617 } else 3618 #endif 3619 { 3620 port_tab_entry_t ptab; 3621 SOC_IF_ERROR_RETURN( 3622 soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, port, &ptab)); 3623 soc_PORT_TABm_field32_set(unit, &ptab, OUTER_TPID_ENABLEf, tpid_enable); 3624 SOC_IF_ERROR_RETURN( 3625 soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL, port, &ptab)); 3626 } 3627 3628 return BCM_E_NONE; 3629 } 3630 3631 int 3632 _bcm_fb2_egr_vlan_control_field_get(int unit, bcm_port_t port, soc_field_t field, uint32 *value) 3633 { 3634 #ifdef BCM_TRIDENT2PLUS_SUPPORT 3635 if (soc_feature(unit, soc_feature_egr_vlan_control_is_memory)) { 3636 if (soc_feature(unit, soc_feature_egr_all_profile) || 3637 (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 3638 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port))) { 3639 BCM_IF_ERROR_RETURN( 3640 bcm_esw_port_egr_lport_field_get( 3641 unit, port, EGR_VLAN_CONTROL_1m, 3642 field, value)); 3643 } else { 3644 egr_vlan_control_1_entry_t entry; 3645 SOC_IF_ERROR_RETURN( 3646 READ_EGR_VLAN_CONTROL_1m(unit, MEM_BLOCK_ANY, port, &entry)); 3647 *value = soc_EGR_VLAN_CONTROL_1m_field32_get(unit, &entry, field); 3648 } 3649 } else 3650 #endif 3651 { 3652 uint32 vctrl = 0; 3653 SOC_IF_ERROR_RETURN(READ_EGR_VLAN_CONTROL_1r(unit, port, &vctrl)); 3654 *value = soc_reg_field_get(unit, EGR_VLAN_CONTROL_1r, vctrl, field); 3655 } 3656 3657 return BCM_E_NONE; 3658 } 3659 3660 int 3661 _bcm_fb2_egr_vlan_control_field_set(int unit, bcm_port_t port, soc_field_t field, uint32 value) 3662 { 3663 #ifdef BCM_TRIDENT2PLUS_SUPPORT 3664 if (soc_feature(unit, soc_feature_egr_vlan_control_is_memory)) { 3665 if (soc_feature(unit, soc_feature_egr_all_profile) || 3666 (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 3667 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port))) { 3668 BCM_IF_ERROR_RETURN( 3669 bcm_esw_port_egr_lport_field_set( 3670 unit, port, EGR_VLAN_CONTROL_1m, 3671 field, value)); 3672 } else { 3673 egr_vlan_control_1_entry_t entry; 3674 SOC_IF_ERROR_RETURN( 3675 READ_EGR_VLAN_CONTROL_1m(unit, MEM_BLOCK_ANY, port, &entry)); 3676 soc_EGR_VLAN_CONTROL_1m_field32_set(unit, &entry, field, value); 3677 SOC_IF_ERROR_RETURN( 3678 WRITE_EGR_VLAN_CONTROL_1m(unit, MEM_BLOCK_ANY, port, &entry)); 3679 } 3680 } else 3681 #endif 3682 { 3683 uint32 vctrl = 0; 3684 SOC_IF_ERROR_RETURN(READ_EGR_VLAN_CONTROL_1r(unit, port, &vctrl)); 3685 soc_reg_field_set(unit, EGR_VLAN_CONTROL_1r, &vctrl, field, value); 3686 SOC_IF_ERROR_RETURN(WRITE_EGR_VLAN_CONTROL_1r(unit, port, vctrl)); 3687 } 3688 3689 return BCM_E_NONE; 3690 } 3691 3692 /* 3693 * Function: 3694 * _bcm_fb2_port_tpid_get 3695 * Description: 3696 * Get the default Tag Protocol ID for a port. 3697 * Parameters: 3698 * unit - Device number 3699 * port - Port number 3700 * tpid - Tag Protocol ID 3701 * Return Value: 3702 * BCM_E_XXX 3703 */ 3704 int 3705 _bcm_fb2_port_tpid_get(int unit, bcm_port_t port, uint16 *tpid) 3706 { 3707 int index = 0; 3708 BCM_IF_ERROR_RETURN( 3709 _bcm_fb2_egr_vlan_control_field_get( 3710 unit, port, OUTER_TPID_INDEXf, (uint32*)&index)); 3711 3712 _bcm_fb2_outer_tpid_entry_get(unit, tpid, index); 3713 return (BCM_E_NONE); 3714 } 3715 3716 #ifdef BCM_TRIUMPH2_SUPPORT 3717 /* 3718 * Function: 3719 * _bcm_fb2_mod_port_tpid_enable_write 3720 * Description: 3721 * Write the Tag Protocol ID enables for a (module, port). 3722 * Parameters: 3723 * unit - Device number 3724 * mod - Module ID 3725 * port - Port number 3726 * tpid_enable - Tag Protocol ID enables 3727 * Return Value: 3728 * BCM_E_XXX 3729 */ 3730 STATIC int 3731 _bcm_fb2_mod_port_tpid_enable_write(int unit, bcm_module_t mod, 3732 bcm_port_t port, int tpid_enable) 3733 { 3734 #ifdef BCM_HURRICANE3_SUPPORT 3735 if (SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 3736 return _bcm_hr3_mod_port_tpid_enable_write(unit, mod, port, 3737 tpid_enable); 3738 } else 3739 #endif /* BCM_HURRICANE3_SUPPORT */ 3740 #ifdef BCM_TRIDENT_SUPPORT 3741 { 3742 return _bcm_td_mod_port_tpid_enable_write(unit, mod, port, 3743 tpid_enable); 3744 } 3745 #endif /* BCM_TRIDENT_SUPPORT */ 3746 return BCM_E_UNAVAIL; 3747 } 3748 #endif /* BCM_TRIUMPH2_SUPPORT */ 3749 3750 /* 3751 * Function: 3752 * _bcm_fb2_port_tpid_set 3753 * Description: 3754 * Set the default Tag Protocol ID for a port. 3755 * Parameters: 3756 * unit - Device number 3757 * port - Port number 3758 * tpid - Tag Protocol ID 3759 * Return Value: 3760 * BCM_E_XXX 3761 */ 3762 int 3763 _bcm_fb2_port_tpid_set(int unit, bcm_port_t port, uint16 tpid, int *index) 3764 { 3765 int old_tpid_index; 3766 uint32 tpid_enable; 3767 int tpid_index; 3768 uint16 old_tpid; 3769 int rv = BCM_E_NONE; 3770 #ifdef BCM_TRIUMPH2_SUPPORT 3771 bcm_module_t modid = 0; 3772 bcm_port_t mod_port = port; 3773 #endif 3774 3775 _bcm_fb2_outer_tpid_tab_lock(unit); 3776 3777 #ifdef BCM_TRIUMPH2_SUPPORT 3778 rv = bcm_esw_stk_my_modid_get(unit, &modid); 3779 if (BCM_FAILURE(rv)) { 3780 _bcm_fb2_outer_tpid_tab_unlock(unit); 3781 return (rv); 3782 } 3783 #endif 3784 3785 #ifdef BCM_TRIDENT2PLUS_SUPPORT 3786 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 3787 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 3788 modid = _BCM_SUBPORT_COE_PORT_ID_MOD_GET(port); 3789 mod_port = _BCM_SUBPORT_COE_PORT_ID_PORT_GET(port); 3790 } 3791 #endif 3792 3793 /* Delete the TPID referenced by EGR_VLAN_CONTROL_1r */ 3794 rv = _bcm_fb2_egr_vlan_control_field_get( 3795 unit, port, OUTER_TPID_INDEXf, (uint32*)&old_tpid_index); 3796 if (BCM_FAILURE(rv)) { 3797 _bcm_fb2_outer_tpid_tab_unlock(unit); 3798 return (rv); 3799 } 3800 3801 rv = _bcm_fb2_outer_tpid_entry_get(unit, &old_tpid, old_tpid_index); 3802 if (BCM_FAILURE(rv)) { 3803 _bcm_fb2_outer_tpid_tab_unlock(unit); 3804 return (rv); 3805 } 3806 3807 /* Add TPID reference for EGR_VLAN_CONTROL_1r. */ 3808 rv = _bcm_fb2_outer_tpid_entry_add(unit, tpid, &tpid_index); 3809 if (BCM_FAILURE(rv)) { 3810 _bcm_fb2_outer_tpid_tab_unlock(unit); 3811 return (rv); 3812 } 3813 3814 /* Delete the TPID referenced by PORT and EGR_SRC_PORT 3815 * tables. We keep only one reference for both table because 3816 * the outer TPID enabled will be the same. 3817 */ 3818 3819 rv = _bcm_fb2_port_tpid_enable_get(unit, port, &tpid_enable); 3820 if (BCM_FAILURE(rv)) { 3821 _bcm_fb2_outer_tpid_tab_unlock(unit); 3822 return (rv); 3823 } 3824 3825 tpid_index = 0; 3826 while (tpid_enable) { 3827 if (tpid_enable & 1) { 3828 rv = _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index); 3829 if (BCM_FAILURE(rv)) { 3830 _bcm_fb2_outer_tpid_tab_unlock(unit); 3831 return (rv); 3832 } 3833 } 3834 tpid_enable = tpid_enable >> 1; 3835 tpid_index++; 3836 } 3837 3838 /* Add TPID reference for EGR_SRC_PORT and PORT tables. 3839 * The first insertion and second insertion will return 3840 * the same status because we are adding the same TPID value. 3841 */ 3842 rv = _bcm_fb2_outer_tpid_entry_add(unit, tpid, &tpid_index); 3843 if (BCM_FAILURE(rv)) { 3844 _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index); 3845 _bcm_fb2_outer_tpid_tab_unlock(unit); 3846 return (rv); 3847 } 3848 3849 /* Delete reference to old tpid entry after adding the new one */ 3850 rv = _bcm_fb2_outer_tpid_entry_delete(unit, old_tpid_index); 3851 if (BCM_FAILURE(rv)) { 3852 _bcm_fb2_outer_tpid_tab_unlock(unit); 3853 return (rv); 3854 } 3855 3856 rv = _bcm_fb2_egr_vlan_control_field_set( 3857 unit, port, OUTER_TPID_INDEXf, tpid_index); 3858 if (BCM_FAILURE(rv)) { 3859 _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index); 3860 _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index); 3861 _bcm_fb2_outer_tpid_tab_unlock(unit); 3862 return (rv); 3863 } 3864 3865 tpid_enable = 1 << tpid_index; 3866 rv = _bcm_fb2_port_tpid_enable_set(unit, port, tpid_enable); 3867 if (BCM_FAILURE(rv)) { 3868 _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index); 3869 _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index); 3870 _bcm_fb2_outer_tpid_tab_unlock(unit); 3871 return (rv); 3872 } 3873 *index = tpid_index; 3874 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 3875 if (soc_feature(unit, soc_feature_td2p_style_egr_outer_tpid)) { 3876 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 3877 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 3878 rv = bcm_esw_port_egr_lport_field_set( 3879 unit, port, EGR_PORT_1m, 3880 OUTER_TPID_ENABLEf, tpid_enable); 3881 } else { 3882 rv = soc_mem_field32_modify(unit, EGR_PORT_1m, port, 3883 OUTER_TPID_ENABLEf, tpid_enable); 3884 } 3885 } else 3886 #endif 3887 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_ENDURO_SUPPORT) 3888 if (SOC_REG_FIELD_VALID(unit, EGR_PORT_1r, OUTER_TPID_ENABLEf)) { 3889 rv = soc_reg_field32_modify(unit, EGR_PORT_1r, port, 3890 OUTER_TPID_ENABLEf, tpid_enable); 3891 } else 3892 #endif 3893 if (SOC_REG_IS_VALID(unit, EGR_SRC_PORTr)) { 3894 rv = soc_reg_field32_modify(unit, EGR_SRC_PORTr, port, 3895 OUTER_TPID_ENABLEf, tpid_enable); 3896 } 3897 3898 #if defined(BCM_TRIUMPH2_SUPPORT) 3899 /* For Triumph2 and Apollo, also need to program the SYSTEM_CONFIG_TABLE 3900 * for second-pass packets. These are treated as Higig-lookup packets */ 3901 if (BCM_SUCCESS(rv) && !SOC_IS_TRIDENT3X(unit) && 3902 (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 3903 SOC_IS_VALKYRIE2(unit) || SOC_IS_ENDURO(unit) || 3904 SOC_IS_HURRICANEX(unit) || SOC_IS_TD_TT(unit) || 3905 SOC_IS_GREYHOUND(unit)|| SOC_IS_GREYHOUND2(unit))) { 3906 if (soc_mem_is_valid(unit, SYSTEM_CONFIG_TABLE_MODBASEm)) { 3907 rv = _bcm_fb2_mod_port_tpid_enable_write(unit, modid, mod_port, 3908 tpid_enable); 3909 } else if (soc_mem_is_valid(unit, SYSTEM_CONFIG_TABLEm)) { 3910 int sys_index = 0; 3911 system_config_table_entry_t systab; 3912 3913 sys_index = modid * 64 + mod_port; 3914 rv = READ_SYSTEM_CONFIG_TABLEm(unit, MEM_BLOCK_ANY, sys_index, 3915 &systab); 3916 if (BCM_SUCCESS(rv)) { 3917 soc_SYSTEM_CONFIG_TABLEm_field32_set(unit, &systab, 3918 OUTER_TPID_ENABLEf, tpid_enable); 3919 rv = WRITE_SYSTEM_CONFIG_TABLEm(unit, MEM_BLOCK_ALL, 3920 sys_index, &systab); 3921 } 3922 } 3923 } 3924 #endif /* BCM_TRIUMPH2_SUPPORT */ 3925 3926 #if defined(BCM_TRX_SUPPORT) 3927 if (BCM_SUCCESS(rv) && 3928 soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm, OUTER_TPID_ENABLEf)) { 3929 rv = _bcm_trx_source_trunk_map_set(unit, port, OUTER_TPID_ENABLEf, 3930 tpid_enable); 3931 } 3932 #endif 3933 3934 if (BCM_FAILURE(rv)) { 3935 _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index); 3936 _bcm_fb2_outer_tpid_entry_delete(unit, tpid_index); 3937 _bcm_fb2_outer_tpid_tab_unlock(unit); 3938 return (rv); 3939 } 3940 3941 #if defined(BCM_HGPROXY_COE_SUPPORT) 3942 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 3943 BCM_GPORT_IS_SET(port) && 3944 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 3945 if(!_bcm_xgs5_subport_coe_gport_local(unit, port)) { 3946 rv = BCM_E_PORT; 3947 } else { 3948 rv = _bcmi_coe_subport_physical_port_get(unit, port, &port); 3949 } 3950 if (BCM_FAILURE(rv)) { 3951 _bcm_fb2_outer_tpid_tab_unlock(unit); 3952 return (rv); 3953 } 3954 } 3955 #endif 3956 3957 /* Set TPID to be used for untagged packets */ 3958 if (SOC_REG_IS_VALID(unit, EGR_INGRESS_PORT_TPID_SELECTr)) { 3959 rv = WRITE_EGR_INGRESS_PORT_TPID_SELECTr(unit, port, tpid_index); 3960 } 3961 _bcm_fb2_outer_tpid_tab_unlock(unit); 3962 return (rv); 3963 } 3964 3965 /* 3966 * Function: 3967 * bcm_fb2_port_tpid_add 3968 * Description: 3969 * Add allowed TPID for a port. 3970 * Parameters: 3971 * unit - (IN) Device number 3972 * port - (IN) Port number 3973 * tpid - (IN) Tag Protocol ID 3974 * color_select - (IN) Color mode for TPID 3975 * Return Value: 3976 * BCM_E_XXX 3977 */ 3978 int 3979 _bcm_fb2_port_tpid_add(int unit, bcm_port_t port, 3980 uint16 tpid, int color_select) 3981 { 3982 int rv; 3983 int index; 3984 uint32 tpid_enable; 3985 uint32 cfi_cng; 3986 uint32 tpid_mask; 3987 uint8 remove_tpid; 3988 port_tab_entry_t ptab; 3989 int is_subport = 0; 3990 #ifdef BCM_TRIUMPH2_SUPPORT 3991 bcm_module_t modid = 0; 3992 bcm_port_t mod_port = port; 3993 #endif 3994 3995 #if defined(BCM_TRX_SUPPORT) 3996 /* 3997 * TRX devices only support OUTER_CFI to be mapped to CNG 3998 */ 3999 if (color_select == BCM_COLOR_INNER_CFI && SOC_IS_TRX(unit)) { 4000 return BCM_E_UNAVAIL; 4001 } 4002 #endif 4003 4004 remove_tpid = FALSE; 4005 _bcm_fb2_outer_tpid_tab_lock(unit); 4006 4007 #ifdef BCM_TRIUMPH2_SUPPORT 4008 rv = bcm_esw_stk_my_modid_get(unit, &modid); 4009 if (BCM_FAILURE(rv)) { 4010 _bcm_fb2_outer_tpid_tab_unlock(unit); 4011 return (rv); 4012 } 4013 #endif 4014 4015 #ifdef BCM_TRIDENT2PLUS_SUPPORT 4016 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 4017 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 4018 is_subport = TRUE; 4019 modid = _BCM_SUBPORT_COE_PORT_ID_MOD_GET(port); 4020 mod_port = _BCM_SUBPORT_COE_PORT_ID_PORT_GET(port); 4021 } 4022 #endif 4023 4024 rv = _bcm_fb2_port_tpid_enable_get(unit, port, &tpid_enable); 4025 if (BCM_FAILURE(rv)) { 4026 _bcm_fb2_outer_tpid_tab_unlock(unit); 4027 return (rv); 4028 } 4029 4030 /* Add new TPID to cached table */ 4031 rv = _bcm_fb2_outer_tpid_lkup(unit, tpid, &index); 4032 4033 /* If the new TPID is not allowed on the requested port, 4034 * add the port. 4035 */ 4036 if (rv == BCM_E_NOT_FOUND || !(tpid_enable & (1 << index))) { 4037 rv = _bcm_fb2_outer_tpid_entry_add(unit, tpid, &index); 4038 if (BCM_FAILURE(rv)) { 4039 _bcm_fb2_outer_tpid_tab_unlock(unit); 4040 return (rv); 4041 } 4042 remove_tpid = TRUE; 4043 } 4044 4045 /* Update registers */ 4046 4047 tpid_mask = 1 << index; 4048 4049 /* Updat allowed TPID per port */ 4050 tpid_enable |= tpid_mask; 4051 4052 /* Update color selection per TPID per port */ 4053 rv = _bcm_fb2_egr_vlan_control_field_get(unit, port, CFI_AS_CNGf, &cfi_cng); 4054 if (BCM_FAILURE(rv)) { 4055 if (remove_tpid) { 4056 _bcm_fb2_outer_tpid_entry_delete(unit, index); 4057 } 4058 _bcm_fb2_outer_tpid_tab_unlock(unit); 4059 return (rv); 4060 } 4061 4062 switch (color_select) { 4063 case BCM_COLOR_PRIORITY: 4064 cfi_cng &= ~tpid_mask; 4065 break; 4066 case BCM_COLOR_INNER_CFI: 4067 cfi_cng = 0x1; 4068 break; 4069 case BCM_COLOR_OUTER_CFI: 4070 cfi_cng |= tpid_mask; 4071 break; 4072 default: 4073 /* Already checked color_select param */ 4074 /* Should never get here */ 4075 break; 4076 } 4077 4078 /* Update Registers */ 4079 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 4080 if (soc_feature(unit, soc_feature_td2p_style_egr_outer_tpid)) { 4081 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 4082 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 4083 rv = bcm_esw_port_egr_lport_field_set( 4084 unit, port, EGR_PORT_1m, 4085 OUTER_TPID_ENABLEf, tpid_enable); 4086 } else { 4087 rv = soc_mem_field32_modify(unit, EGR_PORT_1m, port, 4088 OUTER_TPID_ENABLEf, tpid_enable); 4089 } 4090 } else 4091 #endif 4092 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_ENDURO_SUPPORT) 4093 if (SOC_REG_FIELD_VALID(unit, EGR_PORT_1r, OUTER_TPID_ENABLEf)) { 4094 rv = soc_reg_field32_modify(unit, EGR_PORT_1r, port, 4095 OUTER_TPID_ENABLEf, tpid_enable); 4096 } else 4097 #endif 4098 if (SOC_REG_IS_VALID(unit, EGR_SRC_PORTr)) { 4099 rv = soc_reg_field32_modify(unit, EGR_SRC_PORTr, port, 4100 OUTER_TPID_ENABLEf, tpid_enable); 4101 } 4102 if (BCM_FAILURE(rv)) { 4103 if (remove_tpid) { 4104 _bcm_fb2_outer_tpid_entry_delete(unit, index); 4105 } 4106 _bcm_fb2_outer_tpid_tab_unlock(unit); 4107 return (rv); 4108 } 4109 #if defined(BCM_TRIUMPH2_SUPPORT) 4110 /* For Triumph2 and Apollo, also need to program the SYSTEM_CONFIG_TABLE 4111 * for second-pass packets. These are treated as Higig-lookup packets */ 4112 if (!SOC_IS_TRIDENT3X(unit) && 4113 (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 4114 SOC_IS_VALKYRIE2(unit) || SOC_IS_ENDURO(unit) || 4115 SOC_IS_HURRICANEX(unit) || SOC_IS_TD_TT(unit) || 4116 SOC_IS_GREYHOUND(unit) || SOC_IS_GREYHOUND2(unit))) { 4117 if (soc_mem_is_valid(unit, SYSTEM_CONFIG_TABLE_MODBASEm)) { 4118 rv = _bcm_fb2_mod_port_tpid_enable_write(unit, modid, mod_port, 4119 tpid_enable); 4120 } else if (soc_mem_is_valid(unit, SYSTEM_CONFIG_TABLEm)) { 4121 int sys_index = 0; 4122 system_config_table_entry_t systab; 4123 4124 sys_index = modid * 64 + mod_port; 4125 rv = READ_SYSTEM_CONFIG_TABLEm(unit, MEM_BLOCK_ANY, sys_index, 4126 &systab); 4127 if (BCM_SUCCESS(rv)) { 4128 soc_SYSTEM_CONFIG_TABLEm_field32_set(unit, &systab, 4129 OUTER_TPID_ENABLEf, tpid_enable); 4130 rv = WRITE_SYSTEM_CONFIG_TABLEm(unit, MEM_BLOCK_ALL, 4131 sys_index, &systab); 4132 } 4133 } 4134 } 4135 #endif 4136 4137 #if defined(BCM_TRX_SUPPORT) 4138 if (BCM_SUCCESS(rv) && 4139 soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm, OUTER_TPID_ENABLEf)) { 4140 rv = _bcm_trx_source_trunk_map_set(unit, port, OUTER_TPID_ENABLEf, 4141 tpid_enable); 4142 } 4143 #endif 4144 4145 if (BCM_FAILURE(rv)) { 4146 if (remove_tpid) { 4147 _bcm_fb2_outer_tpid_entry_delete(unit, index); 4148 } 4149 _bcm_fb2_outer_tpid_tab_unlock(unit); 4150 return (rv); 4151 } 4152 4153 rv = _bcm_fb2_port_tpid_enable_set(unit, port, tpid_enable); 4154 if (BCM_FAILURE(rv)) { 4155 if (remove_tpid) { 4156 _bcm_fb2_outer_tpid_entry_delete(unit, index); 4157 } 4158 _bcm_fb2_outer_tpid_tab_unlock(unit); 4159 return (rv); 4160 } 4161 4162 rv = _bcm_fb2_egr_vlan_control_field_set(unit, port, CFI_AS_CNGf, cfi_cng); 4163 if (BCM_FAILURE(rv)) { 4164 if (remove_tpid) { 4165 _bcm_fb2_outer_tpid_entry_delete(unit, index); 4166 } 4167 _bcm_fb2_outer_tpid_tab_unlock(unit); 4168 return (rv); 4169 } 4170 4171 if (!is_subport) { 4172 if (!(SOC_IS_TRIDENT3X(unit))) { 4173 rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, port, &ptab); 4174 if (BCM_SUCCESS(rv)) { 4175 soc_PORT_TABm_field32_set(unit, &ptab, CFI_AS_CNGf, cfi_cng); 4176 rv = WRITE_PORT_TABm(unit, MEM_BLOCK_ALL, port, &ptab); 4177 } 4178 } 4179 if (BCM_FAILURE(rv)) { 4180 if (remove_tpid) { 4181 _bcm_fb2_outer_tpid_entry_delete(unit, index); 4182 } 4183 } 4184 } 4185 4186 _bcm_fb2_outer_tpid_tab_unlock(unit); 4187 4188 return rv; 4189 } 4190 4191 /* 4192 * Function: 4193 * _bcm_fb2_port_tpid_get_all 4194 * Description: 4195 * Retrieve a list of TPIDs available for the port. 4196 * Parameters: 4197 * unit - (IN) Device number 4198 * port - (IN) Port number 4199 * size - (IN) size of the buffer arrays 4200 * tpid_array - (OUT) tpid buffer array 4201 * color_array - (OUT) color buffer array 4202 * count - (OUT) actual number of tpids/colors retrieved 4203 * Return Value: 4204 * BCM_E_XXX 4205 */ 4206 int 4207 _bcm_fb2_port_tpid_get_all(int unit, bcm_port_t port, 4208 int size, uint16 *tpid_array, 4209 int *color_array, int *count) 4210 { 4211 int rv; 4212 int index; 4213 uint32 tpid_enable; 4214 uint32 cfi_cng; 4215 int cnt; 4216 uint32 tpid = 0; 4217 int num_entries; 4218 4219 cnt = 0; 4220 rv = _bcm_fb2_port_tpid_enable_get(unit, port, &tpid_enable); 4221 if (BCM_FAILURE(rv)) { 4222 return (rv); 4223 } 4224 4225 /* max tpid entries limited by width of this field */ 4226 if (SOC_MEM_FIELD_VALID(unit, SOURCE_TRUNK_MAP_TABLEm, OUTER_TPID_ENABLEf)) { 4227 num_entries = soc_mem_field_length(unit, SOURCE_TRUNK_MAP_TABLEm, 4228 OUTER_TPID_ENABLEf); 4229 } else { 4230 num_entries = soc_mem_field_length(unit,PORT_TABm,OUTER_TPID_ENABLEf); 4231 } 4232 4233 if (size == 0) { 4234 for (index = 0; index < num_entries; index++) { 4235 if (tpid_enable & (1 << index)) { 4236 cnt++; 4237 } 4238 } 4239 *count = cnt; 4240 return BCM_E_NONE; 4241 } 4242 4243 rv = _bcm_fb2_egr_vlan_control_field_get(unit, port, CFI_AS_CNGf, &cfi_cng); 4244 if (BCM_FAILURE(rv)) { 4245 return (rv); 4246 } 4247 4248 for (index = 0; index < num_entries; index++) { 4249 if (cnt < size) { 4250 if (tpid_enable & (1 << index)) { 4251 rv = READ_EGR_OUTER_TPIDr(unit, index, &tpid); 4252 if (BCM_FAILURE(rv)) { 4253 return (rv); 4254 } 4255 tpid_array[cnt] = (uint16)tpid; 4256 if (cfi_cng & (1 << index)) { 4257 color_array[cnt] = BCM_COLOR_OUTER_CFI; 4258 } else { 4259 color_array[cnt] = BCM_COLOR_PRIORITY; 4260 } 4261 cnt++; 4262 } 4263 } 4264 } 4265 *count = cnt; 4266 4267 return rv; 4268 } 4269 4270 /* 4271 * Function: 4272 * bcm_fb2_port_tpid_delete 4273 * Description: 4274 * Delete allowed TPID for a port. 4275 * Parameters: 4276 * unit - (IN) Device number 4277 * port - (IN) Port number 4278 * tpid - (IN) Tag Protocol ID 4279 * Return Value: 4280 * BCM_E_XXX 4281 */ 4282 int 4283 _bcm_fb2_port_tpid_delete(int unit, bcm_port_t port, uint16 tpid) 4284 { 4285 int rv; 4286 int index; 4287 uint32 tpid_enable = 0; 4288 uint16 default_tpid; 4289 int default_tpid_index; 4290 _bcm_port_info_t *pinfo; 4291 #ifdef BCM_TRIUMPH2_SUPPORT 4292 bcm_module_t modid = 0; 4293 bcm_port_t mod_port = port; 4294 #endif 4295 4296 _bcm_fb2_outer_tpid_tab_lock(unit); 4297 4298 rv = _bcm_fb2_outer_tpid_lkup(unit, tpid, &index); 4299 if (BCM_FAILURE(rv)) { 4300 _bcm_fb2_outer_tpid_tab_unlock(unit); 4301 return (rv); 4302 } 4303 4304 #ifdef BCM_TRIUMPH2_SUPPORT 4305 rv = bcm_esw_stk_my_modid_get(unit, &modid); 4306 if (BCM_FAILURE(rv)) { 4307 _bcm_fb2_outer_tpid_tab_unlock(unit); 4308 return (rv); 4309 } 4310 #endif 4311 4312 #ifdef BCM_TRIDENT2PLUS_SUPPORT 4313 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 4314 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 4315 modid = _BCM_SUBPORT_COE_PORT_ID_MOD_GET(port); 4316 mod_port = _BCM_SUBPORT_COE_PORT_ID_PORT_GET(port); 4317 } 4318 #endif 4319 4320 rv = _bcm_fb2_port_tpid_enable_get(unit, port, &tpid_enable); 4321 if (BCM_FAILURE(rv)) { 4322 _bcm_fb2_outer_tpid_tab_unlock(unit); 4323 return (rv); 4324 } 4325 4326 if (tpid_enable & (1 << index)) { 4327 tpid_enable &= ~(1 << index); 4328 rv = _bcm_fb2_port_tpid_enable_set(unit, port, tpid_enable); 4329 #if defined(BCM_TRIUMPH2_SUPPORT) 4330 /* For Triumph2 and Apollo, also need to program the SYSTEM_CONFIG_TABLE 4331 * for second-pass packets. These are treated as Higig-lookup packets */ 4332 if (!SOC_IS_TRIDENT3X(unit) && 4333 (BCM_SUCCESS(rv) && (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 4334 SOC_IS_VALKYRIE2(unit) || SOC_IS_ENDURO(unit) || 4335 SOC_IS_HURRICANEX(unit) || SOC_IS_TD_TT(unit) || 4336 SOC_IS_GREYHOUND2(unit)))) { 4337 if (soc_mem_is_valid(unit, SYSTEM_CONFIG_TABLE_MODBASEm)) { 4338 rv = _bcm_fb2_mod_port_tpid_enable_write(unit, modid, mod_port, 4339 tpid_enable); 4340 } else if (soc_mem_is_valid(unit, SYSTEM_CONFIG_TABLEm)) { 4341 int sys_index = 0; 4342 system_config_table_entry_t systab; 4343 4344 sys_index = modid * 64 + mod_port; 4345 rv = READ_SYSTEM_CONFIG_TABLEm(unit, MEM_BLOCK_ANY, sys_index, 4346 &systab); 4347 if (BCM_SUCCESS(rv)) { 4348 soc_SYSTEM_CONFIG_TABLEm_field32_set(unit, &systab, 4349 OUTER_TPID_ENABLEf, tpid_enable); 4350 rv = WRITE_SYSTEM_CONFIG_TABLEm(unit, MEM_BLOCK_ALL, 4351 sys_index, &systab); 4352 } 4353 } 4354 } 4355 #endif 4356 #if defined(BCM_TRX_SUPPORT) 4357 if (BCM_SUCCESS(rv) && 4358 soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm, 4359 OUTER_TPID_ENABLEf)) { 4360 rv = _bcm_trx_source_trunk_map_set(unit, port, OUTER_TPID_ENABLEf, 4361 tpid_enable); 4362 } 4363 #endif 4364 } else { 4365 rv = BCM_E_NOT_FOUND; 4366 } 4367 if (BCM_FAILURE(rv)) { 4368 _bcm_fb2_outer_tpid_tab_unlock(unit); 4369 return (rv); 4370 } 4371 4372 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 4373 if (soc_feature(unit, soc_feature_td2p_style_egr_outer_tpid)) { 4374 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 4375 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 4376 rv = bcm_esw_port_egr_lport_field_set( 4377 unit, port, EGR_PORT_1m, 4378 OUTER_TPID_ENABLEf, tpid_enable); 4379 } else { 4380 rv = soc_mem_field32_modify(unit, EGR_PORT_1m, port, 4381 OUTER_TPID_ENABLEf, tpid_enable); 4382 } 4383 } else 4384 #endif 4385 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_ENDURO_SUPPORT) 4386 if (SOC_REG_FIELD_VALID(unit, EGR_PORT_1r, OUTER_TPID_ENABLEf)) { 4387 rv = soc_reg_field32_modify(unit, EGR_PORT_1r, port, 4388 OUTER_TPID_ENABLEf, tpid_enable); 4389 } else 4390 #endif 4391 if (SOC_REG_IS_VALID(unit, EGR_SRC_PORTr)) { 4392 rv = soc_reg_field32_modify(unit, EGR_SRC_PORTr, port, 4393 OUTER_TPID_ENABLEf, tpid_enable); 4394 } 4395 if (BCM_FAILURE(rv)) { 4396 _bcm_fb2_outer_tpid_tab_unlock(unit); 4397 return (rv); 4398 } 4399 4400 rv = _bcm_fb2_egr_vlan_control_field_get( 4401 unit, port, OUTER_TPID_INDEXf, (uint32*)&index); 4402 if (BCM_FAILURE(rv)) { 4403 _bcm_fb2_outer_tpid_tab_unlock(unit); 4404 return (rv); 4405 } 4406 4407 /* If the current port tpid is not default tpid then 4408 * add the default tpid to the port before deleting current port tpid */ 4409 default_tpid = _bcm_fb2_outer_tpid_default_get(unit); 4410 rv = _bcm_fb2_outer_tpid_entry_add(unit, default_tpid, 4411 &default_tpid_index); 4412 if (BCM_FAILURE(rv)) { 4413 _bcm_fb2_outer_tpid_tab_unlock(unit); 4414 return (rv); 4415 } 4416 4417 rv = _bcm_fb2_egr_vlan_control_field_set( 4418 unit, port, OUTER_TPID_INDEXf, default_tpid_index); 4419 if (BCM_FAILURE(rv)) { 4420 _bcm_fb2_outer_tpid_tab_unlock(unit); 4421 return (rv); 4422 } 4423 4424 if (!(SOC_IS_APOLLO(unit) || SOC_IS_HURRICANE2(unit) || 4425 SOC_IS_SCORPION(unit) || SOC_IS_RAVEN(unit))) { 4426 rv = _bcm_port_info_get(unit, port, &pinfo); 4427 BCM_IF_ERROR_RETURN(rv); 4428 if (pinfo->dtag_mode & BCM_PORT_DTAG_MODE_EXTERNAL) { 4429 /*For DT mode external ports, don't enable outer TPIDs*/ 4430 } else { 4431 /*Enable outer_tpid field for default tpid and add entry*/ 4432 tpid_enable = 1 << default_tpid_index; 4433 rv = _bcm_fb2_port_tpid_enable_set(unit, port, tpid_enable); 4434 if (BCM_FAILURE(rv)) { 4435 _bcm_fb2_outer_tpid_tab_unlock(unit); 4436 return (rv); 4437 } 4438 rv = _bcm_fb2_outer_tpid_entry_add(unit, default_tpid, 4439 &default_tpid_index); 4440 if (BCM_FAILURE(rv)) { 4441 _bcm_fb2_outer_tpid_tab_unlock(unit); 4442 return (rv); 4443 } 4444 } 4445 } 4446 4447 /* Delete function called twice to set it to the appropriate 4448 * default value since the set function calls the entry_add 4449 * function twice resulting in the reference count to 4450 * to be incremented twice for EGR_VLAN_CONTROL_1r and PORT tables. 4451 */ 4452 rv = _bcm_fb2_outer_tpid_entry_delete(unit, index); 4453 if (BCM_FAILURE(rv)) { 4454 _bcm_fb2_outer_tpid_tab_unlock(unit); 4455 return (rv); 4456 } 4457 /* Delete the cached entry only after the hardware is 4458 * successfully updated. 4459 */ 4460 rv = _bcm_fb2_outer_tpid_entry_delete(unit, index); 4461 _bcm_fb2_outer_tpid_tab_unlock(unit); 4462 return rv; 4463 } 4464 4465 /* 4466 * Function: 4467 * bcm_fb2_port_tpid_delete_all 4468 * Description: 4469 * Delete all allowed TPID for a port. 4470 * Parameters: 4471 * unit - (IN) Device number 4472 * port - (IN) Port number 4473 * Return Value: 4474 * BCM_E_XXX 4475 */ 4476 int 4477 _bcm_fb2_port_tpid_delete_all(int unit, bcm_port_t port) 4478 { 4479 uint32 tpid_enable; 4480 int index = 0; 4481 int rv; 4482 uint16 default_tpid; 4483 int default_tpid_index; 4484 _bcm_port_info_t *pinfo; 4485 #ifdef BCM_TRIUMPH2_SUPPORT 4486 bcm_module_t modid = 0; 4487 bcm_port_t mod_port = port; 4488 #endif 4489 4490 _bcm_fb2_outer_tpid_tab_lock(unit); 4491 4492 #ifdef BCM_TRIUMPH2_SUPPORT 4493 rv = bcm_esw_stk_my_modid_get(unit, &modid); 4494 if (BCM_FAILURE(rv)) { 4495 _bcm_fb2_outer_tpid_tab_unlock(unit); 4496 return (rv); 4497 } 4498 #endif 4499 4500 #ifdef BCM_TRIDENT2PLUS_SUPPORT 4501 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 4502 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 4503 modid = _BCM_SUBPORT_COE_PORT_ID_MOD_GET(port); 4504 mod_port = _BCM_SUBPORT_COE_PORT_ID_PORT_GET(port); 4505 } 4506 #endif 4507 4508 rv = _bcm_fb2_port_tpid_enable_get(unit, port, &tpid_enable); 4509 if (BCM_FAILURE(rv)) { 4510 _bcm_fb2_outer_tpid_tab_unlock(unit); 4511 return (rv); 4512 } 4513 4514 rv = _bcm_fb2_port_tpid_enable_set(unit, port, 0); 4515 if (BCM_FAILURE(rv)) { 4516 _bcm_fb2_outer_tpid_tab_unlock(unit); 4517 return (rv); 4518 } 4519 4520 #if defined(BCM_TRIUMPH2_SUPPORT) 4521 if (!SOC_IS_TRIDENT3X(unit) && 4522 (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 4523 SOC_IS_VALKYRIE2(unit) || SOC_IS_ENDURO(unit) || 4524 SOC_IS_HURRICANEX(unit) || SOC_IS_TD_TT(unit) || 4525 SOC_IS_GREYHOUND(unit) || SOC_IS_GREYHOUND2(unit))) { 4526 if (soc_mem_is_valid(unit, SYSTEM_CONFIG_TABLE_MODBASEm)) { 4527 rv = _bcm_fb2_mod_port_tpid_enable_write(unit, modid, mod_port, 0); 4528 } else if (soc_mem_is_valid(unit, SYSTEM_CONFIG_TABLEm)) { 4529 int sys_index = 0; 4530 system_config_table_entry_t systab; 4531 4532 sys_index = modid * 64 + mod_port; 4533 rv = READ_SYSTEM_CONFIG_TABLEm(unit, MEM_BLOCK_ANY, sys_index, 4534 &systab); 4535 if (BCM_SUCCESS(rv)) { 4536 soc_SYSTEM_CONFIG_TABLEm_field32_set(unit, &systab, 4537 OUTER_TPID_ENABLEf, 0); 4538 rv = WRITE_SYSTEM_CONFIG_TABLEm(unit, MEM_BLOCK_ALL, 4539 sys_index, &systab); 4540 } 4541 } 4542 4543 #if defined(BCM_TRX_SUPPORT) 4544 if (BCM_SUCCESS(rv) && 4545 soc_mem_field_valid(unit, SOURCE_TRUNK_MAP_TABLEm, 4546 OUTER_TPID_ENABLEf)) { 4547 rv = _bcm_trx_source_trunk_map_set(unit, port, OUTER_TPID_ENABLEf, 0); 4548 } 4549 #endif 4550 } 4551 #endif /* BCM_TRIUMPH2_SUPPORT */ 4552 if (BCM_FAILURE(rv)) { 4553 _bcm_fb2_outer_tpid_tab_unlock(unit); 4554 return (rv); 4555 } 4556 4557 #if defined(BCM_TRIDENT2PLUS_SUPPORT) 4558 if (soc_feature(unit, soc_feature_td2p_style_egr_outer_tpid)) { 4559 if (soc_feature(unit, soc_feature_hgproxy_subtag_coe) && 4560 _BCM_COE_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, port)) { 4561 rv = bcm_esw_port_egr_lport_field_set( 4562 unit, port, EGR_PORT_1m, 4563 OUTER_TPID_ENABLEf, 0); 4564 } else { 4565 rv = soc_mem_field32_modify(unit, EGR_PORT_1m, port, 4566 OUTER_TPID_ENABLEf, 0); 4567 } 4568 } else 4569 #endif 4570 #if defined(BCM_TRIUMPH2_SUPPORT) || defined(BCM_ENDURO_SUPPORT) 4571 if (SOC_REG_FIELD_VALID(unit, EGR_PORT_1r, OUTER_TPID_ENABLEf)) { 4572 rv = soc_reg_field32_modify(unit, EGR_PORT_1r, port, 4573 OUTER_TPID_ENABLEf, 0); 4574 } else 4575 #endif 4576 if (SOC_REG_IS_VALID(unit, EGR_SRC_PORTr)) { 4577 rv = soc_reg_field32_modify(unit, EGR_SRC_PORTr, port, 4578 OUTER_TPID_ENABLEf, tpid_enable); 4579 } 4580 if (BCM_FAILURE(rv)) { 4581 _bcm_fb2_outer_tpid_tab_unlock(unit); 4582 return (rv); 4583 } 4584 4585 rv = _bcm_fb2_egr_vlan_control_field_get( 4586 unit, port, OUTER_TPID_INDEXf, (uint32*)&index); 4587 if (BCM_FAILURE(rv)) { 4588 _bcm_fb2_outer_tpid_tab_unlock(unit); 4589 return (rv); 4590 } 4591 4592 /* If the current port tpid is not default tpid then 4593 * add the default tpid to the port before deleting current port tpid */ 4594 default_tpid = _bcm_fb2_outer_tpid_default_get(unit); 4595 rv = _bcm_fb2_outer_tpid_entry_add(unit, default_tpid, 4596 &default_tpid_index); 4597 if (BCM_FAILURE(rv)) { 4598 _bcm_fb2_outer_tpid_tab_unlock(unit); 4599 return (rv); 4600 } 4601 4602 rv = _bcm_fb2_egr_vlan_control_field_set( 4603 unit, port, OUTER_TPID_INDEXf, default_tpid_index); 4604 4605 if (BCM_FAILURE(rv)) { 4606 _bcm_fb2_outer_tpid_tab_unlock(unit); 4607 return (rv); 4608 } 4609 4610 4611 /* Delete the cached entries only after the hardware is 4612 * successfully updated. 4613 */ 4614 rv = _bcm_fb2_outer_tpid_entry_delete(unit, index); 4615 if (BCM_FAILURE(rv)) { 4616 _bcm_fb2_outer_tpid_tab_unlock(unit); 4617 return (rv); 4618 } 4619 4620 index = 0; 4621 while (tpid_enable) { 4622 if (tpid_enable & 1) { 4623 rv = _bcm_fb2_outer_tpid_entry_delete(unit, index); 4624 if (BCM_FAILURE(rv)) { 4625 _bcm_fb2_outer_tpid_tab_unlock(unit); 4626 return (rv); 4627 } 4628 } 4629 tpid_enable = tpid_enable >> 1; 4630 index++; 4631 } 4632 4633 /* After deleting all the TPID entries, enable the default TPID * 4634 * else reference count for even the default TPID will be cleared*/ 4635 if (!(SOC_IS_APOLLO(unit) || SOC_IS_HURRICANE2(unit) || 4636 SOC_IS_SCORPION(unit) || SOC_IS_RAVEN(unit))) { 4637 rv = _bcm_port_info_get(unit, port, &pinfo); 4638 BCM_IF_ERROR_RETURN(rv); 4639 if (pinfo->dtag_mode & BCM_PORT_DTAG_MODE_EXTERNAL) { 4640 /* For DT mode external ports, don't enable outer TPIDs */ 4641 } else { 4642 /* Enable outer_tpid field for default tpid and add entry*/ 4643 tpid_enable = 1 << default_tpid_index; 4644 rv = _bcm_fb2_port_tpid_enable_set(unit, port, tpid_enable); 4645 if (BCM_FAILURE(rv)) { 4646 _bcm_fb2_outer_tpid_tab_unlock(unit); 4647 return (rv); 4648 } 4649 rv = _bcm_fb2_outer_tpid_entry_add(unit, default_tpid, 4650 &default_tpid_index); 4651 if (BCM_FAILURE(rv)) { 4652 _bcm_fb2_outer_tpid_tab_unlock(unit); 4653 return (rv); 4654 } 4655 } 4656 } 4657 4658 _bcm_fb2_outer_tpid_tab_unlock(unit); 4659 return (rv); 4660 } 4661 4662 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_TRX_SUPPORT || BCM_RAVEN_SUPPORT */ 4663 4664 /* 4665 * Function: 4666 * _bcm_fb_port_dtag_mode_set 4667 * Description: 4668 * Set the double-tagging mode of a port. 4669 * Parameters: 4670 * unit - (IN) BCM device number 4671 * port - (IN) Port number 4672 * mode - (IN) Double-tagging mode, one of: 4673 * BCM_PORT_DTAG_MODE_NONE No double tagging 4674 * BCM_PORT_DTAG_MODE_INTERNAL Service Provider port 4675 * BCM_PORT_DTAG_MODE_EXTERNAL Customer port 4676 * BCM_PORT_DTAG_REMOVE_EXTERNAL_TAG Remove customer tag 4677 * BCM_PORT_DTAG_ADD_EXTERNAL_TAG Add customer tag 4678 * dt_mode - (IN) True/False double tagged port. 4679 * ignore_tag - (IN) Ignore outer tag. 4680 * Return Value: 4681 * BCM_E_XXX 4682 * Notes: 4683 * BCM_PORT_DTAG_MODE_INTERNAL is for service provider ports. 4684 * A tag will be added if the packet does not already 4685 * have the internal TPID (see bcm_port_tpid_set below). 4686 * Internally this sets DT_MODE and clears IGNORE_TAG. 4687 * BCM_PORT_DTAG_MODE_EXTERNAL is for customer ports. 4688 * The service provider TPID will always be added 4689 * (see bcm_port_tpid_set below). 4690 * Internally this sets DT_MODE and sets IGNORE_TAG. 4691 */ 4692 int 4693 _bcm_fb_port_dtag_mode_set(int unit, bcm_port_t port, int mode, 4694 int dt_mode, int ignore_tag) 4695 { 4696 uint32 config, oconfig; 4697 uint64 config64, oconfig64; 4698 _bcm_port_info_t *pinfo; 4699 bcm_port_cfg_t pcfg; 4700 int rv; 4701 4702 BCM_IF_ERROR_RETURN(_bcm_port_info_get(unit, port, &pinfo)); 4703 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) 4704 if (SOC_IS_FIREBOLT2(unit) || SOC_IS_RAVEN(unit) || SOC_IS_HAWKEYE(unit)) { 4705 rv = soc_reg_field32_modify(unit, EGR_SRC_PORTr, port, 4706 ADD_INNER_TAGf, 4707 (mode & BCM_PORT_DTAG_ADD_EXTERNAL_TAG)? 1 : 0); 4708 BCM_IF_ERROR_RETURN(rv); 4709 4710 #ifdef BCM_TRIDENT2PLUS_SUPPORT 4711 if (soc_feature(unit, soc_feature_egr_vlan_control_is_memory)) { 4712 if (soc_feature(unit, soc_feature_egr_all_profile)) { 4713 BCM_IF_ERROR_RETURN( 4714 bcm_esw_port_egr_lport_field_set( 4715 unit, port, EGR_VLAN_CONTROL_1m, 4716 REMOVE_INNER_TAGf, 4717 (mode & BCM_PORT_DTAG_REMOVE_EXTERNAL_TAG) ? 1 : 0)); 4718 } else { 4719 rv = soc_mem_field32_modify(unit, EGR_VLAN_CONTROL_1m, port, 4720 REMOVE_INNER_TAGf, 4721 (mode & BCM_PORT_DTAG_REMOVE_EXTERNAL_TAG)? 1 : 0); 4722 } 4723 } else 4724 #endif 4725 { 4726 rv = soc_reg_field32_modify(unit, EGR_VLAN_CONTROL_1r, port, 4727 REMOVE_INNER_TAGf, 4728 (mode & BCM_PORT_DTAG_REMOVE_EXTERNAL_TAG)? 1 : 0); 4729 } 4730 BCM_IF_ERROR_RETURN(rv); 4731 } 4732 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */ 4733 4734 4735 SOC_IF_ERROR_RETURN(READ_ING_CONFIGr(unit, &config)); 4736 oconfig = config; 4737 soc_reg_field_set(unit, ING_CONFIGr, &config, 4738 DT_MODEf, dt_mode); 4739 if (config != oconfig) { 4740 SOC_IF_ERROR_RETURN(WRITE_ING_CONFIGr(unit, config)); 4741 } 4742 4743 SOC_IF_ERROR_RETURN(READ_EGR_CONFIGr(unit, &config)); 4744 oconfig = config; 4745 soc_reg_field_set(unit, EGR_CONFIGr, &config, DT_MODEf, dt_mode); 4746 if (config != oconfig) { 4747 SOC_IF_ERROR_RETURN(WRITE_EGR_CONFIGr(unit, config)); 4748 } 4749 /* Record double tag mode for use in DCBs */ 4750 SOC_DT_MODE(unit) = (dt_mode != 0); 4751 4752 if (SOC_REG_IS_VALID(unit, EGR_PORT_64r)) { 4753 SOC_IF_ERROR_RETURN(READ_EGR_PORT_64r(unit, port, &config64)); 4754 oconfig64 = config64; 4755 soc_reg64_field32_set(unit, EGR_PORT_64r, &config64, NNI_PORTf, !ignore_tag); 4756 if (COMPILER_64_NE(config64, oconfig64)) { 4757 SOC_IF_ERROR_RETURN(WRITE_EGR_PORT_64r(unit, port, config64)); 4758 } 4759 } else { 4760 SOC_IF_ERROR_RETURN(READ_EGR_PORTr(unit, port, &config)); 4761 oconfig = config; 4762 soc_reg_field_set(unit, EGR_PORTr, &config, NNI_PORTf, !ignore_tag); 4763 if (config != oconfig) { 4764 SOC_IF_ERROR_RETURN(WRITE_EGR_PORTr(unit, port, config)); 4765 } 4766 } 4767 4768 soc_mem_lock(unit, PORT_TABm); 4769 4770 rv = mbcm_driver[unit]->mbcm_port_cfg_get(unit, port, &pcfg); 4771 if (BCM_SUCCESS(rv) && (pcfg.pc_nni_port == ignore_tag)) { 4772 pcfg.pc_nni_port = !ignore_tag; 4773 rv = mbcm_driver[unit]->mbcm_port_cfg_set(unit, port, &pcfg); 4774 } 4775 4776 soc_mem_unlock(unit, PORT_TABm); 4777 return rv; 4778 } 4779 4780 /* 4781 * Function: 4782 * _bcm_fb_port_dtag_mode_get 4783 * Description: 4784 * Return the current double-tagging mode of a port. 4785 * Parameters: 4786 * unit - (IN) BCM device number 4787 * port - (IN) Port number 4788 * mode - (OUT) Double-tagging mode 4789 * Return Value: 4790 * BCM_E_XXX 4791 */ 4792 int 4793 _bcm_fb_port_dtag_mode_get(int unit, bcm_port_t port, int *mode) 4794 { 4795 uint32 config; 4796 bcm_port_cfg_t pcfg; 4797 int rv; 4798 4799 SOC_IF_ERROR_RETURN(READ_ING_CONFIGr(unit, &config)); 4800 if (soc_reg_field_get(unit, ING_CONFIGr, config, DT_MODEf) == 0) { 4801 *mode = BCM_PORT_DTAG_MODE_NONE; 4802 } else { 4803 rv = mbcm_driver[unit]->mbcm_port_cfg_get(unit, port, &pcfg); 4804 BCM_IF_ERROR_RETURN(rv); 4805 4806 if (pcfg.pc_nni_port) { 4807 *mode = BCM_PORT_DTAG_MODE_INTERNAL; 4808 } else { 4809 *mode = BCM_PORT_DTAG_MODE_EXTERNAL; 4810 } 4811 } 4812 4813 #if defined(BCM_FIREBOLT2_SUPPORT) || defined(BCM_RAVEN_SUPPORT) 4814 if (SOC_REG_FIELD_VALID(unit, EGR_SRC_PORTr, ADD_INNER_TAGf)) { 4815 uint32 value; 4816 4817 SOC_IF_ERROR_RETURN(READ_EGR_SRC_PORTr(unit, port, &value)); 4818 if (soc_reg_field_get(unit, EGR_SRC_PORTr, 4819 value, ADD_INNER_TAGf)) { 4820 *mode |= BCM_PORT_DTAG_ADD_EXTERNAL_TAG; 4821 } 4822 #ifdef BCM_TRIDENT2PLUS_SUPPORT 4823 if (soc_feature(unit, soc_feature_egr_vlan_control_is_memory)) { 4824 if (soc_feature(unit, soc_feature_egr_all_profile)) { 4825 uint32 val = 0; 4826 BCM_IF_ERROR_RETURN(bcm_esw_port_egr_lport_field_get(unit, 4827 port, EGR_VLAN_CONTROL_1m, REMOVE_INNER_TAGf, &val)); 4828 if (val) { 4829 *mode |= BCM_PORT_DTAG_REMOVE_EXTERNAL_TAG; 4830 } 4831 } else { 4832 egr_vlan_control_1_entry_t entry; 4833 SOC_IF_ERROR_RETURN( 4834 READ_EGR_VLAN_CONTROL_1m(unit, MEM_BLOCK_ANY, port, &entry)); 4835 if (soc_EGR_VLAN_CONTROL_1m_field32_get(unit, &entry, 4836 REMOVE_INNER_TAGf)) { 4837 *mode |= BCM_PORT_DTAG_REMOVE_EXTERNAL_TAG; 4838 } 4839 } 4840 } else 4841 #endif 4842 { 4843 SOC_IF_ERROR_RETURN 4844 (READ_EGR_VLAN_CONTROL_1r(unit, port, &value)); 4845 if (soc_reg_field_get(unit, EGR_VLAN_CONTROL_1r, 4846 value, REMOVE_INNER_TAGf)) { 4847 *mode |= BCM_PORT_DTAG_REMOVE_EXTERNAL_TAG; 4848 } 4849 } 4850 } 4851 #endif /* BCM_FIREBOLT2_SUPPORT || BCM_RAVEN_SUPPORT */ 4852 return BCM_E_NONE; 4853 } 4854 4855 #endif /* BCM_FIREBOLT_SUPPORT */