port.c (22967B)
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: Port Management 9 */ 10 11 #include <soc/defs.h> 12 #if defined(BCM_TRIDENT2_SUPPORT) 13 #include <soc/drv.h> 14 #include <bcm/port.h> 15 #include <bcm/error.h> 16 #include <bcm_int/esw/port.h> 17 #include <bcm_int/esw/trident.h> 18 #include <bcm_int/common/lock.h> 19 #include <bcm_int/esw/trident2.h> 20 #include <bcm_int/esw/trident2plus.h> 21 #include <bcm_int/esw/portctrl.h> 22 23 int 24 bcm_td2_port_rate_ingress_set(int unit, bcm_port_t port, uint32 bandwidth, 25 uint32 burst) 26 { 27 int phy_port, mmu_port, index; 28 static soc_mem_t config_mem[] = { 29 MMU_MTRI_BKPMETERINGCONFIG_MEM_0m, 30 MMU_MTRI_BKPMETERINGCONFIG_MEM_1m 31 }; 32 soc_mem_t mem; 33 uint32 rval; 34 mmu_mtri_bkpmeteringconfig_mem_0_entry_t entry; 35 uint32 pause, refresh_rate, bucketsize, granularity, flags; 36 int refresh_bitsize, bucket_bitsize; 37 soc_info_t *si; 38 39 si = &SOC_INFO(unit); 40 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 41 mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port]; 42 if (SOC_PBMP_MEMBER(si->ypipe_pbm, port)) { 43 mem = config_mem[1]; 44 index = mmu_port & 0x3f; 45 } else { 46 mem = config_mem[0]; 47 index = mmu_port; 48 } 49 50 sal_memset(&entry, 0, sizeof(entry)); 51 52 /* If metering is disabled on this ingress port we are done. */ 53 if (!bandwidth || !burst) { 54 SOC_IF_ERROR_RETURN 55 (soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, &entry)); 56 return BCM_E_NONE; 57 } 58 59 flags = 0; 60 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval)); 61 if (soc_reg_field_get(unit, MISCCONFIGr, rval, ITU_MODE_SELf)) { 62 flags |= _BCM_TD_METER_FLAG_NON_LINEAR; 63 } 64 65 /* Discard threshold will be set to 12.5 % above pause threshold */ 66 pause = (burst * 8) / 9; 67 refresh_bitsize = soc_mem_field_length(unit, mem, REFRESHCOUNTf); 68 bucket_bitsize = soc_mem_field_length(unit, mem, PAUSE_THDf); 69 BCM_IF_ERROR_RETURN 70 (_bcm_td_rate_to_bucket_encoding(unit, bandwidth, pause, flags, 71 refresh_bitsize, bucket_bitsize, 72 &refresh_rate, &bucketsize, 73 &granularity)); 74 75 soc_mem_field32_set(unit, mem, &entry, METER_GRANULARITYf, granularity); 76 soc_mem_field32_set(unit, mem, &entry, REFRESHCOUNTf, refresh_rate); 77 soc_mem_field32_set(unit, mem, &entry, PAUSE_THDf, bucketsize); 78 soc_mem_field32_set(unit, mem, &entry, BKPDISCARD_ENf, 1); 79 /* Set discard threshold to 12.5 % above pause threshold */ 80 soc_mem_field32_set(unit, mem, &entry, DISCARD_THDf, 3); 81 /* Set resume threshold to 75% above pause threshold */ 82 /* RESUME_THD field in entry is 0 */ 83 84 SOC_IF_ERROR_RETURN 85 (soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, &entry)); 86 87 return BCM_E_NONE; 88 } 89 90 int 91 bcm_td2_port_rate_ingress_get(int unit, bcm_port_t port, uint32 *bandwidth, 92 uint32 *burst) 93 { 94 int phy_port, mmu_port, index; 95 static soc_mem_t config_mem[] = { 96 MMU_MTRI_BKPMETERINGCONFIG_MEM_0m, 97 MMU_MTRI_BKPMETERINGCONFIG_MEM_1m 98 }; 99 soc_mem_t mem; 100 uint32 rval; 101 mmu_mtri_bkpmeteringconfig_mem_0_entry_t entry; 102 uint32 pause, refresh_rate, bucketsize, granularity, flags; 103 soc_info_t *si; 104 105 if (bandwidth == NULL || burst == NULL) { 106 return BCM_E_PARAM; 107 } 108 109 si = &SOC_INFO(unit); 110 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 111 mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port]; 112 if (SOC_PBMP_MEMBER(si->ypipe_pbm, port)) { 113 mem = config_mem[1]; 114 index = mmu_port & 0x3f; 115 } else { 116 mem = config_mem[0]; 117 index = mmu_port; 118 } 119 120 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &entry)); 121 122 if (!soc_mem_field32_get(unit, mem, &entry, BKPDISCARD_ENf)) { 123 *bandwidth = *burst = 0; 124 return BCM_E_NONE; 125 } 126 127 refresh_rate = soc_mem_field32_get(unit, mem, &entry, REFRESHCOUNTf); 128 bucketsize = soc_mem_field32_get(unit, mem, &entry, PAUSE_THDf); 129 granularity = soc_mem_field32_get(unit, mem, &entry, METER_GRANULARITYf); 130 131 flags = 0; 132 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval)); 133 if (soc_reg_field_get(unit, MISCCONFIGr, rval, ITU_MODE_SELf)) { 134 flags |= _BCM_TD_METER_FLAG_NON_LINEAR; 135 } 136 137 BCM_IF_ERROR_RETURN 138 (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize, 139 granularity, flags, bandwidth, 140 &pause)); 141 142 switch (soc_mem_field32_get(unit, mem, &entry, DISCARD_THDf)) { 143 case 0: 144 *burst = pause * 7 / 4; /* 75% above PAUSE_THD */ 145 break; 146 case 1: 147 *burst = pause * 3 / 2; /* 50% above PAUSE_THD */ 148 break; 149 case 2: 150 *burst = pause * 5 / 4; /* 25% above PAUSE_THD */ 151 break; 152 case 3: 153 *burst = pause * 9 / 8; /* 12.5% above PAUSE_THD */ 154 break; 155 default: 156 /* Should never happen */ 157 *burst = 0; 158 break; 159 } 160 161 return BCM_E_NONE; 162 } 163 164 int 165 bcm_td2_port_rate_pause_get(int unit, bcm_port_t port, uint32 *pause, 166 uint32 *resume) 167 { 168 int phy_port, mmu_port, index; 169 static soc_mem_t config_mem[] = { 170 MMU_MTRI_BKPMETERINGCONFIG_MEM_0m, 171 MMU_MTRI_BKPMETERINGCONFIG_MEM_1m 172 }; 173 soc_mem_t mem; 174 uint32 rval; 175 mmu_mtri_bkpmeteringconfig_mem_0_entry_t entry; 176 uint32 burst, bandwidth, bucketsize, granularity, flags; 177 soc_info_t *si; 178 179 if (pause == NULL || resume == NULL) { 180 return BCM_E_PARAM; 181 } 182 183 si = &SOC_INFO(unit); 184 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 185 mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port]; 186 if (SOC_PBMP_MEMBER(si->ypipe_pbm, port)) { 187 mem = config_mem[1]; 188 index = mmu_port & 0x3f; 189 } else { 190 mem = config_mem[0]; 191 index = mmu_port; 192 } 193 194 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &entry)); 195 196 if (!soc_mem_field32_get(unit, mem, &entry, BKPDISCARD_ENf)) { 197 *pause = *resume = 0; 198 return BCM_E_NONE; 199 } 200 201 bucketsize = soc_mem_field32_get(unit, mem, &entry, PAUSE_THDf); 202 granularity = soc_mem_field32_get(unit, mem, &entry, METER_GRANULARITYf); 203 204 flags = 0; 205 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval)); 206 if (soc_reg_field_get(unit, MISCCONFIGr, rval, ITU_MODE_SELf)) { 207 flags |= _BCM_TD_METER_FLAG_NON_LINEAR; 208 } 209 210 BCM_IF_ERROR_RETURN 211 (_bcm_td_bucket_encoding_to_rate(unit, 0, bucketsize, granularity, 212 flags, &bandwidth, pause)); 213 214 switch (soc_mem_field32_get(unit, mem, &entry, RESUME_THDf)) { 215 case 0: 216 *resume = *pause * 3 / 4; /* 75% of PAUSE_THD */ 217 break; 218 case 1: 219 *resume = *pause * 1 / 2; /* 50% of PAUSE_THD */ 220 break; 221 case 2: 222 *resume = *pause * 1 / 4; /* 25% of PAUSE_THD */ 223 break; 224 case 3: 225 *resume = *pause * 1 / 8; /* 12.5% of PAUSE_THD */ 226 break; 227 default: 228 /* Should never happen */ 229 *resume = 0; 230 break; 231 } 232 233 switch (soc_mem_field32_get(unit, mem, &entry, DISCARD_THDf)) { 234 case 0: 235 burst = *pause * 7 / 4; /* 75% above PAUSE_THD */ 236 break; 237 case 1: 238 burst = *pause * 3 / 2; /* 50% above PAUSE_THD */ 239 break; 240 case 2: 241 burst = *pause * 5 / 4; /* 25% above PAUSE_THD */ 242 break; 243 case 3: 244 burst = *pause * 9 / 8; /* 12.5% above PAUSE_THD */ 245 break; 246 default: 247 /* Should never happen */ 248 burst = 0; 249 break; 250 } 251 252 *pause = burst - *pause; 253 *resume = burst - *resume; 254 255 return BCM_E_NONE; 256 } 257 258 /* 259 * Function: 260 * bcm_td2_port_rate_egress_get 261 * Purpose: 262 * Get egress metering information 263 * Parameters: 264 * unit - (IN) Unit number 265 * port - (IN) Port number 266 * bandwidth - (IN) Kilobits per second or packets per second 267 * zero if rate limiting is disabled 268 * burst - (IN) Maximum burst size in kilobits or packets 269 * mode - (IN) _BCM_PORT_RATE_BYTE_MODE or _BCM_PORT_RATE_PPS_MODE 270 * Returns: 271 * BCM_E_XXX 272 */ 273 int 274 bcm_td2_port_rate_egress_set(int unit, bcm_port_t port, uint32 bandwidth, 275 uint32 burst, uint32 mode) 276 { 277 int phy_port, mmu_port, index; 278 static soc_mem_t config_mem[] = { 279 MMU_MTRO_EGRMETERINGCONFIG_MEM_0m, 280 MMU_MTRO_EGRMETERINGCONFIG_MEM_1m 281 }; 282 soc_mem_t mem; 283 uint32 rval; 284 mmu_mtro_egrmeteringconfig_mem_0_entry_t entry; 285 uint32 refresh_rate, bucketsize, granularity, flags; 286 int refresh_bitsize, bucket_bitsize; 287 soc_info_t *si; 288 289 si = &SOC_INFO(unit); 290 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 291 mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port]; 292 if (SOC_PBMP_MEMBER(si->ypipe_pbm, port)) { 293 mem = config_mem[1]; 294 index = mmu_port & 0x3f; 295 } else { 296 mem = config_mem[0]; 297 index = mmu_port; 298 } 299 if (SOC_IS_MONTEREY(unit)) { 300 mem = MMU_MTRO_EGRMETERINGCONFIG_MEMm; 301 } 302 303 /* 304 * The procedure followed is first disable the egress metering, then 305 * re-enable the egress metering. 306 * 307 * NOTE: During the period of disabling and re-enabling the Egress metering 308 * may be in-effective for couple of cycles 309 */ 310 sal_memset(&entry, 0, sizeof(entry)); 311 SOC_IF_ERROR_RETURN 312 (soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, &entry)); 313 314 /* If metering is disabled on this ingress port we are done. */ 315 if (!bandwidth || !burst) { 316 return BCM_E_NONE; 317 } 318 319 flags = mode == _BCM_PORT_RATE_PPS_MODE ? 320 _BCM_TD_METER_FLAG_PACKET_MODE : 0; 321 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval)); 322 if (soc_reg_field_get(unit, MISCCONFIGr, rval, ITU_MODE_SELf)) { 323 flags |= _BCM_TD_METER_FLAG_NON_LINEAR; 324 } 325 326 refresh_bitsize = soc_mem_field_length(unit, mem, REFRESHf); 327 bucket_bitsize = soc_mem_field_length(unit, mem, THD_SELf); 328 BCM_IF_ERROR_RETURN 329 (_bcm_td_rate_to_bucket_encoding(unit, bandwidth, burst, flags, 330 refresh_bitsize, bucket_bitsize, 331 &refresh_rate, &bucketsize, 332 &granularity)); 333 soc_mem_field32_set(unit, mem, &entry, MODEf, 334 mode == _BCM_PORT_RATE_PPS_MODE ? 1 : 0); 335 soc_mem_field32_set(unit, mem, &entry, METER_GRANf, granularity); 336 soc_mem_field32_set(unit, mem, &entry, REFRESHf, refresh_rate); 337 soc_mem_field32_set(unit, mem, &entry, THD_SELf, bucketsize); 338 339 SOC_IF_ERROR_RETURN 340 (soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, &entry)); 341 342 return BCM_E_NONE; 343 } 344 345 /* 346 * Function: 347 * bcm_td2_port_rate_egress_get 348 * Purpose: 349 * Get egress metering information 350 * Parameters: 351 * unit - (IN) Unit number 352 * port - (IN) Port number 353 * bandwidth - (OUT) Kilobits per second or packets per second 354 * zero if rate limiting is disabled 355 * burst - (OUT) Maximum burst size in kilobits or packets 356 * mode - (OUT) _BCM_PORT_RATE_BYTE_MODE or _BCM_PORT_RATE_PPS_MODE 357 * Returns: 358 * BCM_E_XXX 359 */ 360 int 361 bcm_td2_port_rate_egress_get(int unit, bcm_port_t port, uint32 *bandwidth, 362 uint32 *burst, uint32 *mode) 363 { 364 int phy_port, mmu_port, index; 365 static soc_mem_t config_mem[] = { 366 MMU_MTRO_EGRMETERINGCONFIG_MEM_0m, 367 MMU_MTRO_EGRMETERINGCONFIG_MEM_1m 368 }; 369 soc_mem_t mem; 370 uint32 rval; 371 mmu_mtri_bkpmeteringconfig_mem_0_entry_t entry; 372 uint32 refresh_rate, bucketsize, granularity, flags; 373 soc_info_t *si; 374 375 376 if (bandwidth == NULL || burst == NULL) { 377 return BCM_E_PARAM; 378 } 379 380 si = &SOC_INFO(unit); 381 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 382 mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port]; 383 384 if (SOC_PBMP_MEMBER(si->ypipe_pbm, port)) { 385 mem = config_mem[1]; 386 index = mmu_port & 0x3f; 387 } else { 388 mem = config_mem[0]; 389 index = mmu_port; 390 } 391 392 if (SOC_IS_MONTEREY(unit)) { 393 mem = MMU_MTRO_EGRMETERINGCONFIG_MEMm; 394 } 395 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &entry)); 396 397 refresh_rate = soc_mem_field32_get(unit, mem, &entry, REFRESHf); 398 bucketsize = soc_mem_field32_get(unit, mem, &entry, THD_SELf); 399 granularity = soc_mem_field32_get(unit, mem, &entry, METER_GRANf); 400 401 flags = soc_mem_field32_get(unit, mem, &entry, MODEf) ? 402 _BCM_TD_METER_FLAG_PACKET_MODE : 0; 403 BCM_IF_ERROR_RETURN(READ_MISCCONFIGr(unit, &rval)); 404 if (soc_reg_field_get(unit, MISCCONFIGr, rval, ITU_MODE_SELf)) { 405 flags |= _BCM_TD_METER_FLAG_NON_LINEAR; 406 } 407 408 BCM_IF_ERROR_RETURN 409 (_bcm_td_bucket_encoding_to_rate(unit, refresh_rate, bucketsize, 410 granularity, flags, bandwidth, 411 burst)); 412 *mode = flags & _BCM_TD_METER_FLAG_PACKET_MODE ? 413 _BCM_PORT_RATE_PPS_MODE : _BCM_PORT_RATE_BYTE_MODE; 414 415 return BCM_E_NONE; 416 } 417 418 /* 419 * Function: 420 * _bcm_td2_port_drain_cells 421 * Purpose: 422 * To drain cells associated to the port. 423 * Parameters: 424 * unit - (IN) unit number 425 * port - (IN) Port 426 * Returns: 427 * BCM_E_XXX 428 */ 429 int _bcm_td2_port_drain_cells(int unit, int port) 430 { 431 mac_driver_t *macd; 432 int rv = BCM_E_NONE; 433 434 /* Call Port Control module */ 435 if (SOC_USE_PORTCTRL(unit)) { 436 return bcmi_esw_portctrl_egress_queue_drain(unit, port); 437 } 438 439 if (IS_CPU_PORT(unit, port)) { 440 return BCM_E_PORT; 441 } 442 443 PORT_LOCK(unit); 444 rv = soc_mac_probe(unit, port, &macd); 445 446 if (BCM_SUCCESS(rv)) { 447 rv = MAC_CONTROL_SET(macd, unit, port, SOC_MAC_CONTROL_EGRESS_DRAIN, 1); 448 449 } 450 PORT_UNLOCK(unit); 451 return rv; 452 } 453 454 int bcm_td2_port_drain_cells(int unit, int port) 455 { 456 BCM_IF_ERROR_RETURN 457 (_bcm_td2_port_drain_cells(unit, port)); 458 459 BCM_IF_ERROR_RETURN 460 (_bcm_td2_cosq_port_queue_state_check(unit, port)); 461 462 return BCM_E_NONE; 463 } 464 465 /* Port table field programming - assumes PORT_LOCK is taken */ 466 int 467 _bcm_td2_egr_port_set(int unit, bcm_port_t port, 468 soc_field_t field, int value) 469 470 { 471 egr_port_entry_t pent; 472 soc_mem_t mem = EGR_PORTm; 473 int rv, cur_val; 474 475 if (!SOC_MEM_FIELD_VALID(unit, mem, field)) { 476 return (BCM_E_UNAVAIL); 477 } 478 sal_memset(&pent, 0, sizeof(egr_port_entry_t)); 479 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, port, &pent); 480 481 if (BCM_SUCCESS(rv)) { 482 cur_val = soc_EGR_PORTm_field32_get(unit, &pent, field); 483 if (value != cur_val) { 484 soc_EGR_PORTm_field32_set(unit, &pent, field, value); 485 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, port, &pent); 486 } 487 } 488 return rv; 489 } 490 491 int 492 _bcm_td2_egr_port_get(int unit, bcm_port_t port, 493 soc_field_t field, int *value) 494 495 { 496 egr_port_entry_t pent; 497 soc_mem_t mem = EGR_PORTm; 498 499 if (!SOC_MEM_FIELD_VALID(unit, mem, field)) { 500 return (BCM_E_UNAVAIL); 501 } 502 if (value == NULL) { 503 return (BCM_E_PARAM); 504 } 505 506 sal_memset(&pent, 0, sizeof(egr_port_entry_t)); 507 BCM_IF_ERROR_RETURN 508 (READ_EGR_PORTm(unit, MEM_BLOCK_ANY, port, &pent)); 509 *value = soc_EGR_PORTm_field32_get(unit, &pent, field); 510 511 return BCM_E_NONE; 512 } 513 514 int 515 bcm_td2p_port_coe_e2ecc(int unit, bcm_port_t port, 516 bcm_port_congestion_config_t *config) 517 { 518 uint32 regval = 0; 519 int e2ecc_enable = 0; 520 uint32 field_val; 521 int index; 522 int copy_to_cpu = 0; 523 mmu_intfi_st_trans_tbl_entry_t st_trans_entry; 524 525 if (config->flags & BCM_PORT_CONGESTION_CONFIG_E2ECC_COE_FLEX_MODE) { 526 return BCM_E_UNAVAIL; 527 } 528 /* 529 * e2ecc_enable here denotes the coe flow control mode we are operating 530 * 0 = flow control messages treated as normal data frames. 531 * 1 = subtending ports send E2ECC pause frames only (only strict mode is supported) 532 * 2 = subtending ports send VLAN pause frames . 533 * 3 = reserved 534 */ 535 if ((config->flags & 536 BCM_PORT_CONGESTION_CONFIG_E2ECC_COE_STRICT_MODE) && 537 (config->flags & BCM_PORT_CONGESTION_CONFIG_RX)) { 538 e2ecc_enable = 1; 539 } else if ((config->flags & 540 BCM_PORT_CONGESTION_CONFIG_VLAN_PAUSE_COE) && 541 (config->flags & BCM_PORT_CONGESTION_CONFIG_RX)) { 542 e2ecc_enable = 2; 543 } 544 545 if (config->flags & 546 BCM_PORT_CONGESTION_CONFIG_COPY_TO_CPU) { 547 copy_to_cpu = 1 ; 548 } 549 550 SOC_IF_ERROR_RETURN( 551 READ_COE_FLOW_CONTROL_CONFIGr (unit, port, ®val)); 552 /* Enable the Flow control and E2ECC mode 553 * 1. When there is enable request 554 */ 555 soc_reg_field_set(unit, COE_FLOW_CONTROL_CONFIGr, ®val, 556 FLOW_CONTROL_FORMATf, e2ecc_enable); 557 soc_reg_field_set(unit, COE_FLOW_CONTROL_CONFIGr, ®val, 558 COPY_TO_CPUf, copy_to_cpu); 559 SOC_IF_ERROR_RETURN( 560 WRITE_COE_FLOW_CONTROL_CONFIGr (unit, port, regval)); 561 562 if (e2ecc_enable == 1) { 563 /* Configure E2ECC-FC to receive MAC-DA, Length/Type, and Opcode. 564 * HW will match these settings so that we can get the subport tag 565 * from 12 bits of MAC SA 566 */ 567 field_val = (config->dest_mac[0] << 8) | /* MAC-DA[47:40] */ 568 (config->dest_mac[1]); /* MAC-DA[39:32] */ 569 SOC_IF_ERROR_RETURN(READ_ING_VOQFC_MACDA_MSr(unit, ®val)); 570 soc_reg_field_set(unit, ING_VOQFC_MACDA_MSr, ®val, DAf, field_val); 571 SOC_IF_ERROR_RETURN(WRITE_ING_VOQFC_MACDA_MSr(unit, regval)); 572 573 field_val = (config->dest_mac[2] << 24) | /* MAC-DA[31:24] */ 574 (config->dest_mac[3] << 16) | /* MAC-DA[23:16] */ 575 (config->dest_mac[4] << 8) | /* MAC-DA[15:8] */ 576 (config->dest_mac[5]); /* MAC-DA[7:0] */ 577 578 SOC_IF_ERROR_RETURN(READ_ING_VOQFC_MACDA_LSr(unit, ®val)); 579 soc_reg_field_set(unit, ING_VOQFC_MACDA_LSr, ®val, DAf, field_val); 580 SOC_IF_ERROR_RETURN(WRITE_ING_VOQFC_MACDA_LSr(unit, regval)); 581 582 583 SOC_IF_ERROR_RETURN(READ_ING_VOQFC_IDr(unit, ®val)); 584 soc_reg_field_set(unit, ING_VOQFC_IDr, ®val, 585 LENGTH_TYPEf, config->ethertype); 586 soc_reg_field_set(unit, ING_VOQFC_IDr, ®val, 587 OPCODEf, config->opcode); 588 SOC_IF_ERROR_RETURN(WRITE_ING_VOQFC_IDr(unit, regval)); 589 590 591 /* 592 * Hardcoding the MMU_INTFI_ST_TRANS_TBL so the 593 * congestion data is written as it is 594 * in FC_ST_TABLE, This we are doing so that 595 * congestion data is updated as it is 596 * it recevied 597 */ 598 599 for (index=0 ; index < soc_mem_index_count(unit, 600 MMU_INTFI_ST_TRANS_TBLm); index++) { 601 SOC_IF_ERROR_RETURN(READ_MMU_INTFI_ST_TRANS_TBLm( 602 unit, MEM_BLOCK_ALL,index, 603 &st_trans_entry)); 604 soc_mem_field32_set(unit, MMU_INTFI_ST_TRANS_TBLm, 605 &st_trans_entry, FC_ST_XLATEf,index%16); 606 SOC_IF_ERROR_RETURN(WRITE_MMU_INTFI_ST_TRANS_TBLm( 607 unit, MEM_BLOCK_ALL, index, 608 &st_trans_entry)); 609 } 610 /* 611 * FC_WIDTH is set to 2 so that 4 bits of i 612 * congestion data is read on each cycle 613 */ 614 SOC_IF_ERROR_RETURN 615 (soc_reg_field32_modify(unit, INTFI_CFGr, REG_PORT_ANY, 616 FC_WIDTHf, 2)); 617 /* 618 * MERGE_EN is set to 0, for COE messages 619 * to bypass the DMVOQ merge block 620 */ 621 622 SOC_IF_ERROR_RETURN 623 (soc_reg_field32_modify(unit, INTFI_CFGr, REG_PORT_ANY, 624 MERGE_ENf, 0)); 625 /* MODE_SEL is set to 1 to specify the message is of type 626 * DMVOQ/E2ECC 627 */ 628 SOC_IF_ERROR_RETURN 629 (soc_reg_field32_modify(unit, INTFI_CFGr, REG_PORT_ANY, 630 MODE_SELf, 1)); 631 632 /* Setting VOQFC_Enable to false so that it will identify CoE 633 * E2ECC messsages rather than VOQFC 634 */ 635 SOC_IF_ERROR_RETURN(READ_IE2E_CONTROLr(unit, port, ®val)); 636 if (soc_reg_field_get(unit, IE2E_CONTROLr, regval, 637 VOQFC_ENABLEf)) { 638 soc_reg_field_set(unit, IE2E_CONTROLr, ®val, 639 VOQFC_ENABLEf, 0); 640 SOC_IF_ERROR_RETURN(WRITE_IE2E_CONTROLr(unit, port, regval)); 641 } 642 643 /* set CONGESTION_STATE_BYTES to 1 because we're only expecting 1 644 * byte per interface */ 645 for (index = 0 ; index < SOC_REG_NUMELS(unit, CONGESTION_STATE_BYTESr) 646 ; index++) { 647 soc_reg_field_set(unit, CONGESTION_STATE_BYTESr, ®val, 648 DATAf, 1); 649 SOC_IF_ERROR_RETURN(WRITE_CONGESTION_STATE_BYTESr(unit, 650 index, regval)); 651 } 652 } else if(e2ecc_enable == 2){ 653 654 field_val = (config->dest_mac[0] << 8) | /* MAC-DA[47:40] */ 655 (config->dest_mac[1]); /* MAC-DA[39:32] */ 656 657 SOC_IF_ERROR_RETURN(READ_COE_VLAN_PAUSE_MACDA_MSr(unit, ®val)); 658 soc_reg_field_set(unit, COE_VLAN_PAUSE_MACDA_MSr, ®val, DAf, field_val); 659 SOC_IF_ERROR_RETURN(WRITE_COE_VLAN_PAUSE_MACDA_MSr(unit, regval)); 660 661 field_val = (config->dest_mac[2] << 24) | /* MAC-DA[31:24] */ 662 (config->dest_mac[3] << 16) | /* MAC-DA[23:16] */ 663 (config->dest_mac[4] << 8) | /* MAC-DA[15:8] */ 664 (config->dest_mac[5]); /* MAC-DA[7:0] */ 665 666 SOC_IF_ERROR_RETURN(READ_COE_VLAN_PAUSE_MACDA_LSr(unit, ®val)); 667 soc_reg_field_set(unit, COE_VLAN_PAUSE_MACDA_LSr, ®val, DAf, field_val); 668 SOC_IF_ERROR_RETURN(WRITE_COE_VLAN_PAUSE_MACDA_LSr(unit, regval)); 669 SOC_IF_ERROR_RETURN(READ_COE_VLAN_PAUSE_IDr(unit, ®val)); 670 soc_reg_field_set(unit, COE_VLAN_PAUSE_IDr, ®val, 671 LENGTH_TYPEf, config->ethertype); 672 soc_reg_field_set(unit, COE_VLAN_PAUSE_IDr, ®val, 673 OPCODEf, config->opcode); 674 SOC_IF_ERROR_RETURN(WRITE_COE_VLAN_PAUSE_IDr(unit, regval)); 675 676 SOC_IF_ERROR_RETURN 677 (soc_reg_field32_modify(unit, INTFI_CFGr, REG_PORT_ANY, 678 FC_WIDTHf, 2)); 679 } 680 681 return BCM_E_NONE; 682 } 683 684 #else /* BCM_TRIDENT2_SUPPORT */ 685 int _td2_port_not_empty; 686 #endif /* BCM_TRIDENT2_SUPPORT */