oob.c (89032B)
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 * OOB Flow Control and OOB Stats 8 * Purpose: API to set different OOB Flow Control and OOB Stats registers. 9 */ 10 11 #include <sal/core/libc.h> 12 13 #include <shared/bsl.h> 14 #include <soc/defs.h> 15 16 #if defined(BCM_TRIDENT3_SUPPORT) 17 #include <soc/drv.h> 18 #include <soc/mem.h> 19 #include <soc/profile_mem.h> 20 #include <soc/debug.h> 21 #include <soc/trident3.h> 22 23 #include <bcm/error.h> 24 #include <bcm/oob.h> 25 26 #include <bcm_int/esw/mbcm.h> 27 #include <bcm_int/esw/trident3.h> 28 29 #include <bcm_int/esw_dispatch.h> 30 #include <bcm_int/esw/stat.h> 31 32 #ifdef BCM_WARM_BOOT_SUPPORT 33 #include <bcm_int/esw/switch.h> 34 #endif /* BCM_WARM_BOOT_SUPPORT */ 35 36 /* Number of Traffic Class */ 37 #define _TD3_NUM_TC 8 38 /* Number of OOB FC Rx Interface */ 39 #define _TD3_NUM_OOB_FC_RX_INTF 4 40 /* Maximum Value of Channel Base Value */ 41 #define _TD3_MAX_CHANNEL_BASE 63 42 43 /* Total number of Indexes in OOBFC RX memory */ 44 #define _TD3_MAX_RX_MEM_ENTRY 96 45 46 /* Maximum Value of OOB Stats Config_ID */ 47 #define _TD3_MAX_STATS_CONFIG_ID 3 48 49 /* Total number of Indexes in OOB Stats Service Pool List */ 50 #define _TD3_MAX_IDX_STATS_POOL_LIST 8 51 52 /* Total number of Indexes in OOB Stats UC Queue List */ 53 #define _TD3_MAX_IDX_STATS_QUEUE_LIST 1320 54 55 /* Total number of UC Queue per port. */ 56 #define _TD3_NUM_UCAST_QUEUE_PER_PORT 10 57 58 /* Total number of pipes per slice */ 59 #define _TD3_NUM_PIPE_PER_SLICE 2 60 61 /* 0xF is the end of reporting of OOB Pool Stats */ 62 #define _TD3_OOB_STATS_END_POOL_REPORT 0xF 63 64 /* 0x7FF is the end of reporting of OOB Queue Stats */ 65 #define _TD3_OOB_STATS_END_QUEUE_REPORT 0x7FF 66 67 /* if OOBFC_CHANNEL_BASE.POOL_EN is not valid then use 68 * OOBFC_CHANNEL_BASE.MC_EN; functionality is same based on 69 * Architecture team*/ 70 #define _TD3_OOB_FC_TX_POOL_EN_SUPPORT 0 71 #define _TD3_OOB_FC_TX_MC_EN_SUPPORT 1 72 73 typedef struct _bcm_td3_oob_fc_rx_intf_info_s { 74 uint32 channel_base; /* HCFC channel base */ 75 int enable; /* Interface enable */ 76 uint8 num_ports; /* Number of ports monitored */ 77 uint8 lookup_base; /* Look up base in the OOB FC Rx Memory */ 78 } _bcm_td3_oob_fc_rx_intf_info_t; 79 80 /* 81 * Function: 82 * _bcm_td3_oob_fc_tx_config_flags_set 83 * Purpose: 84 * Set OOB FC Tx enable flags 85 * Parameters: 86 * unit - (IN) StrataSwitch unit number. 87 * flags - (IN) OOB FC Tx flags 88 * Returns: 89 * BCM_E_XXX 90 */ 91 STATIC int 92 _bcm_td3_oob_fc_tx_config_flags_set(int unit, uint32 flags) 93 { 94 uint32 rval = 0; 95 uint64 rval64; 96 uint64 field64; 97 98 COMPILER_64_ZERO(rval64); 99 COMPILER_64_ZERO(field64); 100 101 if (flags & BCM_OOB_FC_TX_FCN_EN) { 102 BCM_IF_ERROR_RETURN 103 (soc_reg32_get(unit, INTFO_FCN_ENr, 0, 0, &rval)); 104 soc_reg_field_set(unit, INTFO_FCN_ENr, &rval, ENf, 0x1); 105 BCM_IF_ERROR_RETURN 106 (soc_reg32_set(unit, INTFO_FCN_ENr, 0, 0, rval)); 107 } else { 108 BCM_IF_ERROR_RETURN 109 (soc_reg32_get(unit, INTFO_FCN_ENr, 0, 0, &rval)); 110 soc_reg_field_set(unit, INTFO_FCN_ENr, &rval, ENf, 0x0); 111 BCM_IF_ERROR_RETURN 112 (soc_reg32_set(unit, INTFO_FCN_ENr, 0, 0, rval)); 113 } 114 115 BCM_IF_ERROR_RETURN 116 (soc_reg64_get(unit, OOBFC_CHANNEL_BASE_64r, 117 0, 0, &rval64)); 118 if (flags & BCM_OOB_FC_TX_ING_EN) { 119 COMPILER_64_SET(field64, 0, 1); 120 } 121 soc_reg64_field_set(unit, OOBFC_CHANNEL_BASE_64r, &rval64, 122 ING_ENf, field64); 123 124 COMPILER_64_ZERO(field64); 125 if (flags & BCM_OOB_FC_TX_EGR_EN) { 126 COMPILER_64_SET(field64, 0, 1); 127 } 128 soc_reg64_field_set(unit, OOBFC_CHANNEL_BASE_64r, &rval64, 129 ENG_ENf, field64); 130 if (_TD3_OOB_FC_TX_POOL_EN_SUPPORT) { 131 COMPILER_64_ZERO(field64); 132 if (flags & BCM_OOB_FC_TX_POOL_EN) { 133 COMPILER_64_SET(field64, 0, 1); 134 } 135 soc_reg64_field_set(unit, OOBFC_CHANNEL_BASE_64r, &rval64, 136 POOL_ENf, field64); 137 138 BCM_IF_ERROR_RETURN 139 (soc_reg64_set(unit, OOBFC_CHANNEL_BASE_64r, 0, 0, rval64)); 140 } else if (_TD3_OOB_FC_TX_MC_EN_SUPPORT) { 141 COMPILER_64_ZERO(field64); 142 if (flags & BCM_OOB_FC_TX_POOL_EN) { 143 COMPILER_64_SET(field64, 0, 1); 144 } 145 soc_reg64_field_set(unit, OOBFC_CHANNEL_BASE_64r, &rval64, 146 MC_ENf, field64); 147 148 BCM_IF_ERROR_RETURN 149 (soc_reg64_set(unit, OOBFC_CHANNEL_BASE_64r, 0, 0, rval64)); 150 } 151 return BCM_E_NONE; 152 } 153 154 /* 155 * Function: 156 * _bcm_td3_oob_fc_tx_config_ipg_set 157 * Purpose: 158 * Set OOB FC Tx inter packet gap 159 * Parameters: 160 * unit - (IN) StrataSwitch unit number. 161 * ipg - (IN) OOB FC Tx inter packet gap 162 * Returns: 163 * BCM_E_XXX 164 */ 165 STATIC int 166 _bcm_td3_oob_fc_tx_config_ipg_set(int unit, uint8 ipg) 167 { 168 uint32 rval; 169 170 BCM_IF_ERROR_RETURN 171 (soc_reg32_get(unit, OOBFC_TX_IDLEr, 0, 0, &rval)); 172 soc_reg_field_set(unit, OOBFC_TX_IDLEr, &rval, 173 IDLE_GAPf, ipg); 174 BCM_IF_ERROR_RETURN 175 (soc_reg32_set(unit, OOBFC_TX_IDLEr, 0, 0, rval)); 176 return BCM_E_NONE; 177 } 178 179 /* 180 * Function: 181 * _bcm_td3_oob_fc_tx_config_gcs_id_set 182 * Purpose: 183 * Set OOB FC Tx global congestion reporting 184 * service pool id 185 * Parameters: 186 * unit - (IN) StrataSwitch unit number. 187 * id - (IN) OOB FC Tx global congestion service pool id 188 * Returns: 189 * BCM_E_XXX 190 */ 191 STATIC int 192 _bcm_td3_oob_fc_tx_config_gcs_id_set(int unit, 193 bcm_service_pool_id_t id) 194 { 195 uint32 rval; 196 197 BCM_IF_ERROR_RETURN 198 (soc_reg32_get(unit, OOBFC_GCSr, 0, 0, &rval)); 199 soc_reg_field_set(unit, OOBFC_GCSr, &rval, 200 GCS_IDf, id); 201 BCM_IF_ERROR_RETURN 202 (soc_reg32_set(unit, OOBFC_GCSr, 0, 0, rval)); 203 204 return BCM_E_NONE; 205 } 206 207 /* 208 * Function: 209 * _bcm_td3_oob_fc_tx_config_egr_mode_set 210 * Purpose: 211 * Set OOB FC Tx egress congestion reporting mode 212 * Parameters: 213 * unit - (IN) StrataSwitch unit number. 214 * mode - (IN) OOB FC Tx egress congestion reporting mode 215 * Returns: 216 * BCM_E_XXX 217 */ 218 STATIC int 219 _bcm_td3_oob_fc_tx_config_egr_mode_set(int unit, 220 bcm_oob_egress_mode_t mode) 221 { 222 uint64 rval64; 223 uint64 field64; 224 225 COMPILER_64_ZERO(field64); 226 227 BCM_IF_ERROR_RETURN 228 (soc_reg64_get(unit, OOBFC_CHANNEL_BASE_64r, 229 0, 0, &rval64)); 230 COMPILER_64_SET(field64, 0, mode); 231 soc_reg64_field_set(unit, OOBFC_CHANNEL_BASE_64r, &rval64, 232 ENG_MODEf, field64); 233 BCM_IF_ERROR_RETURN 234 (soc_reg64_set(unit, OOBFC_CHANNEL_BASE_64r, 235 0, 0, rval64)); 236 237 return BCM_E_NONE; 238 } 239 240 /* 241 * Function: 242 * _bcm_td3_oob_fc_tx_config_flags_get 243 * Purpose: 244 * Get OOB FC Tx enable status 245 * Parameters: 246 * unit - (IN) StrataSwitch unit number. 247 * config - (OUT) OOB FC Tx configuration 248 * Returns: 249 * BCM_E_XXX 250 */ 251 STATIC int 252 _bcm_td3_oob_fc_tx_config_flags_get(int unit, 253 bcm_oob_fc_tx_config_t *config) 254 { 255 uint32 rval = 0; 256 uint64 rval64; 257 uint64 regval64; 258 259 COMPILER_64_ZERO(rval64); 260 COMPILER_64_ZERO(regval64); 261 262 config->flags = 0x0; 263 264 BCM_IF_ERROR_RETURN 265 (soc_reg32_get(unit, INTFO_FCN_ENr, 0, 0, &rval)); 266 267 if (soc_reg_field_get(unit, INTFO_FCN_ENr, rval, ENf)) { 268 config->flags |= BCM_OOB_FC_TX_FCN_EN; 269 } 270 271 BCM_IF_ERROR_RETURN 272 (soc_reg64_get(unit, OOBFC_CHANNEL_BASE_64r, 273 0, 0, &rval64)); 274 275 regval64 = soc_reg64_field_get(unit, OOBFC_CHANNEL_BASE_64r, 276 rval64, ING_ENf); 277 if (!COMPILER_64_IS_ZERO(regval64)) { 278 config->flags |= BCM_OOB_FC_TX_ING_EN; 279 } 280 281 regval64 = soc_reg64_field_get(unit, OOBFC_CHANNEL_BASE_64r, 282 rval64, ENG_ENf); 283 if (!COMPILER_64_IS_ZERO(regval64)) { 284 config->flags |= BCM_OOB_FC_TX_EGR_EN; 285 } 286 if (_TD3_OOB_FC_TX_POOL_EN_SUPPORT) { 287 regval64 = soc_reg64_field_get(unit, OOBFC_CHANNEL_BASE_64r, 288 rval64, POOL_ENf); 289 if (!COMPILER_64_IS_ZERO(regval64)) { 290 config->flags |= BCM_OOB_FC_TX_POOL_EN; 291 } 292 } else if (_TD3_OOB_FC_TX_MC_EN_SUPPORT) { 293 regval64 = soc_reg64_field_get(unit, OOBFC_CHANNEL_BASE_64r, 294 rval64, MC_ENf); 295 if (!COMPILER_64_IS_ZERO(regval64)) { 296 config->flags |= BCM_OOB_FC_TX_POOL_EN; 297 } 298 } 299 300 return BCM_E_NONE; 301 } 302 303 /* 304 * Function: 305 * _bcm_td3_oob_fc_tx_config_ipg_get 306 * Purpose: 307 * Get OOB FC Tx inter packet gap 308 * Parameters: 309 * unit - (IN) StrataSwitch unit number. 310 * config - (OUT) OOB FC Tx configuration 311 * Returns: 312 * BCM_E_XXX 313 */ 314 STATIC int 315 _bcm_td3_oob_fc_tx_config_ipg_get(int unit, 316 bcm_oob_fc_tx_config_t *config) 317 { 318 uint32 rval; 319 320 BCM_IF_ERROR_RETURN 321 (soc_reg32_get(unit, OOBFC_TX_IDLEr, 0, 0, &rval)); 322 323 config->inter_pkt_gap = soc_reg_field_get(unit, OOBFC_TX_IDLEr, 324 rval, IDLE_GAPf); 325 326 return BCM_E_NONE; 327 } 328 329 /* 330 * Function: 331 * _bcm_td3_oob_fc_tx_config_gcs_id_get 332 * Purpose: 333 * Get OOB FC Tx global congestion reporting 334 * service pool id 335 * Parameters: 336 * unit - (IN) StrataSwitch unit number. 337 * config - (OUT) OOB FC Tx configuration 338 * Returns: 339 * BCM_E_XXX 340 */ 341 STATIC int 342 _bcm_td3_oob_fc_tx_config_gcs_id_get(int unit, 343 bcm_oob_fc_tx_config_t *config) 344 { 345 uint32 rval; 346 347 BCM_IF_ERROR_RETURN 348 (soc_reg32_get(unit, OOBFC_GCSr, 0, 0, &rval)); 349 350 config->gcs_id = soc_reg_field_get(unit, OOBFC_GCSr, rval, 351 GCS_IDf); 352 353 return BCM_E_NONE; 354 } 355 356 /* 357 * Function: 358 * _bcm_td3_oob_fc_tx_config_egr_mode_get 359 * Purpose: 360 * Get OOB FC Tx egress congestion reporting mode 361 * Parameters: 362 * unit - (IN) StrataSwitch unit number. 363 * config - (OUT) OOB FC Tx configuration 364 * Returns: 365 * BCM_E_XXX 366 */ 367 STATIC int 368 _bcm_td3_oob_fc_tx_config_egr_mode_get(int unit, 369 bcm_oob_fc_tx_config_t *config) 370 { 371 uint64 rval64; 372 373 BCM_IF_ERROR_RETURN 374 (soc_reg64_get(unit, OOBFC_CHANNEL_BASE_64r, 375 0, 0, &rval64)); 376 377 config->egr_mode = soc_reg64_field32_get(unit, OOBFC_CHANNEL_BASE_64r, 378 rval64, ENG_MODEf); 379 380 return BCM_E_NONE; 381 } 382 383 /* 384 * Function: 385 * _bcm_td3_oob_localport_resolve 386 * Purpose: 387 * Get the logical port from modport gport 388 * Parameters: 389 * unit - (IN) StrataSwitch unit number. 390 * gport - (IN) Modport gport. 391 * local_port - (OUT) Logical port number. 392 * Returns: 393 * BCM_E_XXX 394 */ 395 STATIC int 396 _bcm_td3_oob_localport_resolve(int unit, bcm_gport_t gport, 397 bcm_port_t *local_port) 398 { 399 bcm_module_t module; 400 bcm_port_t port; 401 bcm_trunk_t trunk; 402 int id, result; 403 404 if (!BCM_GPORT_IS_SET(gport)) { 405 if (!SOC_PORT_VALID(unit, gport)) { 406 return BCM_E_PORT; 407 } 408 *local_port = gport; 409 return BCM_E_NONE; 410 } 411 412 BCM_IF_ERROR_RETURN 413 (_bcm_esw_gport_resolve(unit, gport, &module, &port, &trunk, &id)); 414 415 BCM_IF_ERROR_RETURN(_bcm_esw_modid_is_local(unit, module, &result)); 416 if (result == FALSE) { 417 return BCM_E_PARAM; 418 } 419 420 *local_port = port; 421 422 return BCM_E_NONE; 423 } 424 425 /* 426 * Function: 427 * _bcm_td3_oob_fc_rx_get_intf_info 428 * Purpose: 429 * Get the per OOBFC Rx interface info structure 430 * Parameters: 431 * unit - (IN) StrataSwitch unit number. 432 * info - (OUT) Per OOBFC RX interface info structure. 433 * intf_id - (IN) OOBFC Rx Interface ID. 434 * Returns: 435 * BCM_E_XXX 436 */ 437 STATIC int 438 _bcm_td3_oob_fc_rx_get_intf_info(int unit, _bcm_td3_oob_fc_rx_intf_info_t *info, 439 bcm_oob_fc_rx_intf_id_t intf_id) 440 { 441 uint32 rval = 0x0; 442 soc_reg_t cfg_reg[_TD3_NUM_OOB_FC_RX_INTF] = {OOBFC_CHIF_CFG0r, 443 OOBFC_CHIF_CFG1r, 444 OOBFC_CHIF_CFG2r, 445 OOBFC_CHIF_CFG3r}; 446 447 BCM_IF_ERROR_RETURN 448 (soc_reg32_get(unit, cfg_reg[intf_id], 0, 0, &rval)); 449 450 info->enable = soc_reg_field_get(unit, cfg_reg[intf_id], rval, 451 OOBFC_CH_ENf); 452 if (info->enable == 1) { 453 info->num_ports = soc_reg_field_get(unit, cfg_reg[intf_id], rval, 454 CH_PORT_NUMf); 455 info->lookup_base = soc_reg_field_get(unit, cfg_reg[intf_id], rval, 456 LOOKUP_BASEf); 457 info->channel_base = soc_reg_field_get(unit, cfg_reg[intf_id], rval, 458 OOBFC_CH_BASEf); 459 } 460 return BCM_E_NONE; 461 } 462 463 /* 464 * Function: 465 * _bcm_td3_oob_fc_rx_disable_intf 466 * Purpose: 467 * Disable OOBFC Rx interface. 468 * Parameters: 469 * unit - (IN) StrataSwitch unit number. 470 * intf_id - (IN) OOBFC Rx Interface ID. 471 * Returns: 472 * BCM_E_XXX 473 */ 474 STATIC int 475 _bcm_td3_oob_fc_rx_disable_intf(int unit, 476 bcm_oob_fc_rx_intf_id_t intf_id) 477 { 478 uint32 rval = 0x0; 479 soc_reg_t cfg_reg[_TD3_NUM_OOB_FC_RX_INTF] = {OOBFC_CHIF_CFG0r, 480 OOBFC_CHIF_CFG1r, 481 OOBFC_CHIF_CFG2r, 482 OOBFC_CHIF_CFG3r}; 483 484 BCM_IF_ERROR_RETURN 485 (soc_reg32_get(unit, cfg_reg[intf_id], 0, 0, &rval)); 486 soc_reg_field_set(unit, cfg_reg[intf_id], &rval, 487 OOBFC_CH_ENf, 0); 488 BCM_IF_ERROR_RETURN 489 (soc_reg32_set(unit, cfg_reg[intf_id], 0, 0, rval)); 490 491 return BCM_E_NONE; 492 } 493 494 /* 495 * Function: 496 * _bcm_td3_oob_fc_rx_enable_intf 497 * Purpose: 498 * Enable OOBFC Rx interface. 499 * Parameters: 500 * unit - (IN) StrataSwitch unit number. 501 * intf_id - (IN) OOBFC Rx Interface ID. 502 * Returns: 503 * BCM_E_XXX 504 */ 505 STATIC int 506 _bcm_td3_oob_fc_rx_enable_intf(int unit, 507 bcm_oob_fc_rx_intf_id_t intf_id) 508 { 509 uint32 rval = 0x0; 510 soc_reg_t cfg_reg[_TD3_NUM_OOB_FC_RX_INTF] = {OOBFC_CHIF_CFG0r, 511 OOBFC_CHIF_CFG1r, 512 OOBFC_CHIF_CFG2r, 513 OOBFC_CHIF_CFG3r}; 514 515 BCM_IF_ERROR_RETURN 516 (soc_reg32_get(unit, cfg_reg[intf_id], 0, 0, &rval)); 517 518 soc_reg_field_set(unit, cfg_reg[intf_id], &rval, 519 OOBFC_CH_ENf, 1); 520 BCM_IF_ERROR_RETURN 521 (soc_reg32_set(unit, cfg_reg[intf_id], 0, 0, rval)); 522 523 return BCM_E_NONE; 524 } 525 526 /* 527 * Function: 528 * _bcm_td3_oob_fc_rx_intf_get_lookup_base 529 * Purpose: 530 * Get the look base in OOBFC Rx Memory for 531 * given OOBFC Rx interface. 532 * Parameters: 533 * unit - (IN) StrataSwitch unit number. 534 * intf_id - (IN) OOBFC Rx Interface ID. 535 * look_base - (OUT) Lookup base in OOBFC Rx Memory 536 * Returns: 537 * BCM_E_XXX 538 */ 539 STATIC int 540 _bcm_td3_oob_fc_rx_intf_get_lookup_base(int unit, 541 bcm_oob_fc_rx_intf_id_t intf_id, 542 uint32 *lookup_base) 543 { 544 uint32 rval = 0x0; 545 soc_reg_t cfg_reg[_TD3_NUM_OOB_FC_RX_INTF] = {OOBFC_CHIF_CFG0r, 546 OOBFC_CHIF_CFG1r, 547 OOBFC_CHIF_CFG2r, 548 OOBFC_CHIF_CFG3r}; 549 550 BCM_IF_ERROR_RETURN 551 (soc_reg32_get(unit, cfg_reg[intf_id], 0, 0, &rval)); 552 553 *lookup_base = soc_reg_field_get(unit, cfg_reg[intf_id], rval, 554 LOOKUP_BASEf); 555 556 return BCM_E_NONE; 557 } 558 559 560 /* 561 * Function: 562 * bcm_td3_oob_fc_tx_config_set 563 * Purpose: 564 * Set OOB FC Tx global configuration. 565 * Parameters: 566 * unit - (IN) StrataSwitch unit number. 567 * config - (IN) OOB FC Tx global configuration 568 * Returns: 569 * BCM_E_XXX 570 */ 571 int 572 bcm_td3_oob_fc_tx_config_set(int unit, 573 bcm_oob_fc_tx_config_t *config) 574 { 575 if (config == NULL) { 576 return BCM_E_PARAM; 577 } 578 579 if ((config->gcs_id < 0) && (config->gcs_id >= _TD3_MMU_NUM_POOL)) { 580 return BCM_E_PARAM; 581 } 582 583 if ((config->egr_mode < 0) && (config->egr_mode >= bcmOOBFCTxReportCount)) { 584 return BCM_E_PARAM; 585 } 586 587 /* Enabling/Disabling FCN, OOBFC Tx Ingress, Egress and Service Pool */ 588 BCM_IF_ERROR_RETURN 589 (_bcm_td3_oob_fc_tx_config_flags_set(unit, config->flags)); 590 591 /* Setting Inter packet Gap between two HCFC message */ 592 BCM_IF_ERROR_RETURN 593 (_bcm_td3_oob_fc_tx_config_ipg_set(unit, config->inter_pkt_gap)); 594 595 /* Setting service pool id whose congestion state will be 596 reported in every HCFC message */ 597 BCM_IF_ERROR_RETURN 598 (_bcm_td3_oob_fc_tx_config_gcs_id_set(unit, config->gcs_id)); 599 600 /* Setting Egress mode for reporting OOBFC message. */ 601 BCM_IF_ERROR_RETURN 602 (_bcm_td3_oob_fc_tx_config_egr_mode_set(unit, config->egr_mode)); 603 604 return BCM_E_NONE; 605 } 606 607 /* 608 * Function: 609 * bcm_td3_oob_fc_tx_config_get 610 * Purpose: 611 * Get OOB FC Tx global configuration. 612 * Parameters: 613 * unit - (IN) StrataSwitch unit number. 614 * config - (OUT) OOB FC Tx global configuration 615 * Returns: 616 * BCM_E_XXX 617 */ 618 int 619 bcm_td3_oob_fc_tx_config_get(int unit, 620 bcm_oob_fc_tx_config_t *config) 621 { 622 if (config == NULL) { 623 return BCM_E_PARAM; 624 } 625 626 /* Get the congestion state reporting status of FCN, 627 OOBFC Tx Ingress, Egress and Service Pool */ 628 BCM_IF_ERROR_RETURN 629 (_bcm_td3_oob_fc_tx_config_flags_get(unit, config)); 630 631 /* Get the configured Inter Packet Gap between OOBFC Tx message.*/ 632 BCM_IF_ERROR_RETURN 633 (_bcm_td3_oob_fc_tx_config_ipg_get(unit, config)); 634 635 /* Setting service pool id whose congestion state will be 636 reported in every HCFC message */ 637 BCM_IF_ERROR_RETURN 638 (_bcm_td3_oob_fc_tx_config_gcs_id_get(unit, config)); 639 640 /* Get the configured Egress mode of OOBFC Tx side */ 641 BCM_IF_ERROR_RETURN 642 (_bcm_td3_oob_fc_tx_config_egr_mode_get(unit, config)); 643 644 return BCM_E_NONE; 645 } 646 647 /* 648 * Function: 649 * _bcm_td3_oob_fc_tx_port_control_set 650 * Purpose: 651 * Set OOB FC Tx Port configuration. 652 * Parameters: 653 * unit - (IN) StrataSwitch unit number. 654 * gport - (IN) Modport Gport 655 * status - (IN) Status of Congestion State reporting 656 * dir - (IN) Direction 0 = Ingreess, 1 = Egress 657 * Returns: 658 * BCM_E_XXX 659 */ 660 int 661 _bcm_td3_oob_fc_tx_port_control_set(int unit, bcm_port_t localport, 662 int status, int dir) 663 { 664 uint32 rval = 0; 665 uint64 rval64; 666 static const soc_field_t field[2] = {ING_PORT_ENf, ENG_PORT_ENf}; 667 static const soc_reg_t reg[2][3] = { 668 {OOBFC_ING_PORT_EN0_64r, OOBFC_ING_PORT_EN1_64r, OOBFC_ING_PORT_EN2r}, 669 {OOBFC_ENG_PORT_EN0_64r, OOBFC_ENG_PORT_EN1_64r, OOBFC_ENG_PORT_EN2r}}; 670 671 if ((status != 1) && (status != 0)) { 672 return BCM_E_PARAM; 673 } 674 675 if (dir > 1) { 676 return BCM_E_PARAM; 677 } 678 679 COMPILER_64_ZERO(rval64); 680 681 if ((localport >= 0) && (localport < 64)) { 682 /* For logical port 0-63 */ 683 if (dir == 1) { 684 /* Setting per egress port QSEL only for the first time when 685 enable/disable congestion state reporting of OOBFC */ 686 BCM_IF_ERROR_RETURN 687 (soc_reg64_get(unit, OOBFC_ENG_PORT_QSEL0_64r, 688 0, 0, &rval64)); 689 if (!COMPILER_64_BITTEST(rval64, localport)) { 690 COMPILER_64_BITSET(rval64, localport); 691 soc_reg64_field_set(unit, OOBFC_ENG_PORT_QSEL0_64r, &rval64, 692 ENG_PORT_QSELf, rval64); 693 BCM_IF_ERROR_RETURN 694 (soc_reg64_set(unit, OOBFC_ENG_PORT_QSEL0_64r, 695 0, 0, rval64)); 696 } 697 } 698 699 BCM_IF_ERROR_RETURN 700 (soc_reg64_get(unit, reg[dir][0], 0, 0, &rval64)); 701 if (((status == 1) && (!COMPILER_64_BITTEST(rval64, localport))) || 702 ((status == 0) && (COMPILER_64_BITTEST(rval64, localport)))) { 703 if (status == 1) { 704 COMPILER_64_BITSET(rval64, localport); 705 } else { 706 COMPILER_64_BITCLR(rval64, localport); 707 } 708 soc_reg64_field_set(unit, reg[dir][0], &rval64, 709 field[dir], rval64); 710 BCM_IF_ERROR_RETURN 711 (soc_reg64_set(unit, reg[dir][0], 0, 0, rval64)); 712 } 713 } else if ((localport >= 64) && (localport < 128)) { 714 /* For logical port 64-127 */ 715 if (dir == 1) { 716 /* Setting per egress port QSEL only for the first time when 717 enable/disable congestion state reporting of OOBFC */ 718 BCM_IF_ERROR_RETURN 719 (soc_reg64_get(unit, OOBFC_ENG_PORT_QSEL1_64r, 720 0, 0, &rval64)); 721 if (!COMPILER_64_BITTEST(rval64, (localport % 64))) { 722 COMPILER_64_BITSET(rval64, (localport % 64)); 723 soc_reg64_field_set(unit, OOBFC_ENG_PORT_QSEL1_64r, &rval64, 724 ENG_PORT_QSELf, rval64); 725 BCM_IF_ERROR_RETURN 726 (soc_reg64_set(unit, OOBFC_ENG_PORT_QSEL1_64r, 727 0, 0, rval64)); 728 } 729 } 730 731 BCM_IF_ERROR_RETURN 732 (soc_reg64_get(unit, reg[dir][1], 0, 0, &rval64)); 733 if (((status == 1) && (!COMPILER_64_BITTEST(rval64, (localport % 64)))) || 734 ((status == 0) && (COMPILER_64_BITTEST(rval64, (localport % 64))))) { 735 if (status == 1) { 736 COMPILER_64_BITSET(rval64, (localport % 64)); 737 } else { 738 COMPILER_64_BITCLR(rval64, (localport % 64)); 739 } 740 soc_reg64_field_set(unit, reg[dir][1], &rval64, 741 field[dir], rval64); 742 BCM_IF_ERROR_RETURN 743 (soc_reg64_set(unit, reg[dir][1], 0, 0, rval64)); 744 } 745 } else if ((localport >= 128) && (localport < 136)) { 746 /* For logical port 128-135 */ 747 if (dir == 1) { 748 /* Setting per egress port QSEL only for the first time when 749 enable/disable congestion state reporting of OOBFC */ 750 BCM_IF_ERROR_RETURN 751 (soc_reg32_get(unit, OOBFC_ENG_PORT_QSEL2r, 752 0, 0, &rval)); 753 if (!(rval & (0x1 << (localport % 128)))) { 754 rval |= 0x1 << (localport % 128); 755 rval &= 0xFF; 756 soc_reg_field_set(unit, OOBFC_ENG_PORT_QSEL2r, &rval, 757 ENG_PORT_QSELf, rval); 758 BCM_IF_ERROR_RETURN 759 (soc_reg32_set(unit, OOBFC_ENG_PORT_QSEL2r, 760 0, 0, rval)); 761 } 762 } 763 764 BCM_IF_ERROR_RETURN 765 (soc_reg32_get(unit, reg[dir][2], 0, 0, &rval)); 766 if (((status == 1) && (!(rval & (0x1 << (localport % 128))))) || 767 ((status == 0) && ((rval & (0x1 << (localport % 128)))))) { 768 if (status == 1) { 769 rval |= 0x1 << (localport % 128); 770 rval &= 0xFF; 771 } else { 772 rval &= ~(0x1 << (localport % 128)); 773 rval &= 0xFF; 774 } 775 soc_reg_field_set(unit, reg[dir][2], &rval, field[dir], rval); 776 777 BCM_IF_ERROR_RETURN 778 (soc_reg32_set(unit, reg[dir][2], 0, 0, rval)); 779 } 780 } else { 781 return BCM_E_PARAM; 782 } 783 784 return BCM_E_NONE; 785 } 786 787 /* 788 * Function: 789 * _bcm_td3_oob_fc_tx_port_control_get 790 * Purpose: 791 * Get OOB FC Tx side Port configuration. 792 * Parameters: 793 * unit - (IN) StrataSwitch unit number. 794 * gport - (IN) Modport Gport 795 * status - (OUT) Status of Congestion State reporting 796 * dir - (IN) Direction 0 = Ingreess, 1 = Egress 797 * Returns: 798 * BCM_E_XXX 799 */ 800 int 801 _bcm_td3_oob_fc_tx_port_control_get(int unit, bcm_port_t localport, 802 int *status, int dir) 803 { 804 uint32 rval = 0; 805 uint64 rval64; 806 static const soc_reg_t reg[2][3] = { 807 {OOBFC_ING_PORT_EN0_64r, OOBFC_ING_PORT_EN1_64r, OOBFC_ING_PORT_EN2r}, 808 {OOBFC_ENG_PORT_EN0_64r, OOBFC_ENG_PORT_EN1_64r, OOBFC_ENG_PORT_EN2r}}; 809 810 if (dir > 1) { 811 return BCM_E_PARAM; 812 } 813 814 COMPILER_64_ZERO(rval64); 815 816 if ((localport >= 0) && (localport < 64)) { 817 /* For logical port 0-63 */ 818 BCM_IF_ERROR_RETURN 819 (soc_reg64_get(unit, reg[dir][0], 0, 0, &rval64)); 820 if (COMPILER_64_BITTEST(rval64, localport)) { 821 *status = 0x1; 822 } else { 823 *status = 0x0; 824 } 825 } else if ((localport >= 64) && (localport < 128)) { 826 /* For logical port 64-127 */ 827 BCM_IF_ERROR_RETURN 828 (soc_reg64_get(unit, reg[dir][1], 0, 0, &rval64)); 829 830 if (COMPILER_64_BITTEST(rval64, (localport % 64))) { 831 *status = 0x1; 832 } else { 833 *status = 0x0; 834 } 835 } else if ((localport >= 128) && (localport < 136)) { 836 /* For logical port 128-135 */ 837 BCM_IF_ERROR_RETURN 838 (soc_reg32_get(unit, reg[dir][2], 0, 0, &rval)); 839 if (rval & (0x1 << (localport % 128))) { 840 *status = 0x1; 841 } else { 842 *status = 0x0; 843 } 844 } else { 845 return BCM_E_PARAM; 846 } 847 848 return BCM_E_NONE; 849 } 850 851 /* 852 * Function: 853 * bcm_td3_oob_fc_tx_info_get 854 * Purpose: 855 * Get OOB FC Tx global information. 856 * Parameters: 857 * unit - (IN) StrataSwitch unit number. 858 * info - (OUT) OOB FC Tx global information 859 * Returns: 860 * BCM_E_XXX 861 */ 862 int 863 bcm_td3_oob_fc_tx_info_get(int unit, bcm_oob_fc_tx_info_t *info) 864 { 865 uint64 rval64; 866 867 if (info == NULL) { 868 return BCM_E_PARAM; 869 } 870 871 BCM_IF_ERROR_RETURN 872 (soc_reg64_get(unit, OOBFC_CHANNEL_BASE_64r, 873 0, 0, &rval64)); 874 875 /* Get the Channel base value for HCFC messages containing 876 congestion state of different resources */ 877 /* Ingress Ports */ 878 info->ing_base = (uint8)soc_reg64_field32_get(unit, OOBFC_CHANNEL_BASE_64r, 879 rval64, ING_BASEf); 880 881 /* Egress Unicast Queue */ 882 info->ucast_base = (uint8)soc_reg64_field32_get(unit, OOBFC_CHANNEL_BASE_64r, 883 rval64, ENGU_BASEf); 884 885 /* Egress Multicast Queue */ 886 info->mcast_base = (uint8)soc_reg64_field32_get(unit, OOBFC_CHANNEL_BASE_64r, 887 rval64, ENGM_BASEf); 888 889 /* Egress Cos Queue */ 890 info->cos_base = (uint8)soc_reg64_field32_get(unit, OOBFC_CHANNEL_BASE_64r, 891 rval64, ENGG_BASEf); 892 if (_TD3_OOB_FC_TX_POOL_EN_SUPPORT) { 893 /* Ingress and Egress Service Pool Congestion */ 894 info->pool_base = (uint8)soc_reg64_field32_get(unit, OOBFC_CHANNEL_BASE_64r, 895 rval64, POOL_BASEf); 896 } else if (_TD3_OOB_FC_TX_MC_EN_SUPPORT) { 897 info->pool_base = (uint8)soc_reg64_field32_get(unit, OOBFC_CHANNEL_BASE_64r, 898 rval64, MC_BASEf); 899 } 900 return BCM_E_NONE; 901 } 902 903 /* 904 * Function: 905 * _bcm_td3_oob_fc_rx_config_enable_set 906 * Purpose: 907 * Enable and configure the given OOB FC Rx Interface 908 * Parameters: 909 * unit - (IN) StrataSwitch unit number 910 * intf_id - (IN) OOB FC Rx Interface Number 911 * channel_base - (IN) HCFC channel base 912 * array_count - (IN) Number of gports in the gport array 913 * gport_array - (IN) Array of modport type gport 914 * Returns: 915 * BCM_E_XXX 916 */ 917 STATIC int 918 _bcm_td3_oob_fc_rx_config_enable_set(int unit, 919 bcm_oob_fc_rx_intf_id_t intf_id, 920 uint8 channel_base, 921 int array_count, 922 bcm_gport_t *gport_array) 923 { 924 _bcm_td3_oob_fc_rx_intf_info_t info[_TD3_NUM_OOB_FC_RX_INTF]; 925 char *sysport_buf, *tc2pri_buf; 926 uint32 sysport_list[_TD3_MAX_RX_MEM_ENTRY]; 927 int rv = BCM_E_INTERNAL; 928 void *pentry1, *pentry2; 929 uint32 rval = 0x0; 930 int mem_wsz = 0; 931 int i = 0, total_num_ports = 0; 932 bcm_port_t localport; 933 uint64 tc_to_pri_mapping; 934 uint32 tc_to_pri_mapping_low = 0x0; 935 uint32 tc_to_pri_mapping_high = 0x0; 936 soc_reg_t cfg_reg[_TD3_NUM_OOB_FC_RX_INTF] = {OOBFC_CHIF_CFG0r, 937 OOBFC_CHIF_CFG1r, 938 OOBFC_CHIF_CFG2r, 939 OOBFC_CHIF_CFG3r}; 940 941 COMPILER_64_ZERO(tc_to_pri_mapping); 942 943 sal_memset(info, 0, sizeof(_bcm_td3_oob_fc_rx_intf_info_t) * 944 _TD3_NUM_OOB_FC_RX_INTF); 945 sal_memset(sysport_list, 0, sizeof(uint32) * 946 _TD3_MAX_RX_MEM_ENTRY); 947 948 /* Backup the per OOBFC Rx interface configuration */ 949 for (i = 0; i < _TD3_NUM_OOB_FC_RX_INTF; i++) { 950 BCM_IF_ERROR_RETURN 951 (_bcm_td3_oob_fc_rx_get_intf_info(unit, &info[i], i)); 952 /* Compute the total number of ports which is 953 already configured */ 954 if (info[i].enable == 1) { 955 total_num_ports += info[i].num_ports; 956 } 957 } 958 959 /* Return error if trying to enable already enabled 960 OOBFC Rx Interface */ 961 if (info[intf_id].enable == 1) { 962 return BCM_E_PARAM; 963 } 964 965 /* Return error if there is no room in memory to accomodate 966 the list of ports which need to programmed in memory */ 967 if ((total_num_ports + array_count) > _TD3_MAX_RX_MEM_ENTRY) { 968 return BCM_E_PARAM; 969 } 970 971 /* Read the MMU_CHFC_SYSPORT_MAPPING memory into sysport_buf */ 972 mem_wsz = sizeof(uint32) * 973 soc_mem_entry_words(unit, MMU_CHFC_SYSPORT_MAPPINGm); 974 sysport_buf = soc_cm_salloc(unit, _TD3_MAX_RX_MEM_ENTRY * mem_wsz, 975 "oob sysport_buf"); 976 if (sysport_buf == NULL) { 977 return BCM_E_MEMORY; 978 } 979 980 if (soc_mem_read_range(unit, MMU_CHFC_SYSPORT_MAPPINGm, MEM_BLOCK_ALL, 981 0, _TD3_MAX_RX_MEM_ENTRY - 1, sysport_buf)) { 982 rv = BCM_E_INTERNAL; 983 soc_cm_sfree(unit, sysport_buf); 984 return rv; 985 } 986 987 /* Read the MMU_INTFO_TC2PRI_MAPPING memory into tc2pri_buf */ 988 mem_wsz = sizeof(uint32) * 989 soc_mem_entry_words(unit, MMU_INTFO_TC2PRI_MAPPINGm); 990 tc2pri_buf = soc_cm_salloc(unit, _TD3_MAX_RX_MEM_ENTRY * mem_wsz, 991 "oob tc2pri_buf"); 992 if (tc2pri_buf == NULL) { 993 rv = BCM_E_MEMORY; 994 soc_cm_sfree(unit, sysport_buf); 995 return rv; 996 } 997 998 if (soc_mem_read_range(unit, MMU_INTFO_TC2PRI_MAPPINGm, MEM_BLOCK_ALL, 999 0, _TD3_MAX_RX_MEM_ENTRY - 1, tc2pri_buf)) { 1000 rv = BCM_E_INTERNAL; 1001 soc_cm_sfree(unit, tc2pri_buf); 1002 soc_cm_sfree(unit, sysport_buf); 1003 return rv; 1004 } 1005 1006 /* Creating a list of logical port number from a list of 1007 modport gport */ 1008 for (i = 0; i < array_count; i++) { 1009 rv = _bcm_td3_oob_localport_resolve(unit, gport_array[i], 1010 &localport); 1011 if (rv != BCM_E_NONE) { 1012 soc_cm_sfree(unit, tc2pri_buf); 1013 soc_cm_sfree(unit, sysport_buf); 1014 return rv; 1015 } 1016 sysport_list[i] = localport; 1017 } 1018 1019 /* Fill the info structure for the given interface */ 1020 info[intf_id].enable = 1; 1021 info[intf_id].channel_base = channel_base; 1022 info[intf_id].lookup_base = total_num_ports; 1023 info[intf_id].num_ports = array_count; 1024 1025 /* Program sysport_list in MMU_CHFC_SYSPORT_MAPPING */ 1026 /* Program default value into MMU_INTFO_TC2PRI_MAPPING */ 1027 for (i = 0; i < array_count; i++) { 1028 pentry1 = soc_mem_table_idx_to_pointer(unit, 1029 MMU_CHFC_SYSPORT_MAPPINGm, 1030 void*, sysport_buf, 1031 (total_num_ports + i)); 1032 pentry2 = soc_mem_table_idx_to_pointer(unit, 1033 MMU_INTFO_TC2PRI_MAPPINGm, 1034 void*, tc2pri_buf, 1035 (total_num_ports + i)); 1036 soc_mem_field32_set(unit, MMU_CHFC_SYSPORT_MAPPINGm, pentry1, 1037 SYS_PORTf, sysport_list[i]); 1038 /* TC to PRI Mapping Default Value is unity mapped 1039 TC=7 mapped PRI=7 0x80 (bits 63-56) 1040 TC=6 mapped PRI=6 0x40 (bits 55-48) 1041 TC=5 mapped PRI=5 0x20 (bits 47-40) 1042 TC=4 mapped PRI=4 0x10 (bits 39-32) 1043 TC=3 mapped PRI=3 0x08 (bits 31-24) 1044 TC=2 mapped PRI=2 0x04 (bits 23-16) 1045 TC=1 mapped PRI=1 0x02 (bits 15-8) 1046 TC=0 mapped PRI=0 0x01 (bits 7-0) 1047 */ 1048 tc_to_pri_mapping_high |= 0x80 << 24; 1049 tc_to_pri_mapping_high |= 0x40 << 16; 1050 tc_to_pri_mapping_high |= 0x20 << 8; 1051 tc_to_pri_mapping_high |= 0x10; 1052 tc_to_pri_mapping_low |= 0x08 << 24; 1053 tc_to_pri_mapping_low |= 0x04 << 16; 1054 tc_to_pri_mapping_low |= 0x02 << 8; 1055 tc_to_pri_mapping_low |= 0x01; 1056 1057 COMPILER_64_SET(tc_to_pri_mapping, tc_to_pri_mapping_high, 1058 tc_to_pri_mapping_low); 1059 1060 soc_mem_field64_set(unit, MMU_INTFO_TC2PRI_MAPPINGm, 1061 pentry2, PRI_BMPf, tc_to_pri_mapping); 1062 } 1063 1064 if (soc_mem_write_range(unit, MMU_CHFC_SYSPORT_MAPPINGm, MEM_BLOCK_ALL, 1065 0, _TD3_MAX_RX_MEM_ENTRY - 1, sysport_buf)) { 1066 rv = BCM_E_INTERNAL; 1067 soc_cm_sfree(unit, tc2pri_buf); 1068 soc_cm_sfree(unit, sysport_buf); 1069 return rv; 1070 } 1071 1072 if (soc_mem_write_range(unit, MMU_INTFO_TC2PRI_MAPPINGm, MEM_BLOCK_ALL, 1073 0, _TD3_MAX_RX_MEM_ENTRY - 1, tc2pri_buf)) { 1074 rv = BCM_E_INTERNAL; 1075 soc_cm_sfree(unit, tc2pri_buf); 1076 soc_cm_sfree(unit, sysport_buf); 1077 return rv; 1078 } 1079 1080 /* Program the given interface configuration register.*/ 1081 rv = soc_reg32_get(unit, cfg_reg[intf_id], 1082 0, 0, &rval); 1083 if (rv != BCM_E_NONE) { 1084 soc_cm_sfree(unit, tc2pri_buf); 1085 soc_cm_sfree(unit, sysport_buf); 1086 return rv; 1087 } 1088 soc_reg_field_set(unit, cfg_reg[intf_id], &rval, 1089 OOBFC_CH_ENf, info[intf_id].enable); 1090 soc_reg_field_set(unit, cfg_reg[intf_id], &rval, 1091 OOBFC_CH_BASEf, info[intf_id].channel_base); 1092 soc_reg_field_set(unit, cfg_reg[intf_id], &rval, 1093 LOOKUP_BASEf, info[intf_id].lookup_base); 1094 soc_reg_field_set(unit, cfg_reg[intf_id], &rval, 1095 CH_PORT_NUMf, info[intf_id].num_ports); 1096 rv = soc_reg32_set(unit, cfg_reg[intf_id], 1097 0, 0, rval); 1098 if (rv != BCM_E_NONE) { 1099 soc_cm_sfree(unit, tc2pri_buf); 1100 soc_cm_sfree(unit, sysport_buf); 1101 return rv; 1102 } 1103 1104 rv = BCM_E_NONE; 1105 soc_cm_sfree(unit, tc2pri_buf); 1106 soc_cm_sfree(unit, sysport_buf); 1107 return rv; 1108 } 1109 1110 /* 1111 * Function: 1112 * _bcm_td3_oob_fc_rx_port_offset_get 1113 * Purpose: 1114 * Get the channel offset value for a given port 1115 * in the HCFC message received on a given OOB FC 1116 * Rx Interface 1117 * Parameters: 1118 * unit - (IN) StrataSwitch unit number 1119 * intf_id - (IN) OOB FC Rx Interface Number 1120 * gport - (IN) Modport gport 1121 * offset - (OUT) Channel offset value 1122 * Returns: 1123 * BCM_E_XXX 1124 */ 1125 STATIC int 1126 _bcm_td3_oob_fc_rx_port_offset_get(int unit, 1127 bcm_oob_fc_rx_intf_id_t intf_id, 1128 bcm_gport_t gport, 1129 uint32 *offset) 1130 { 1131 bcm_oob_fc_rx_config_t config; 1132 bcm_gport_t gport_array[_TD3_MAX_RX_MEM_ENTRY] = {0x0}; 1133 int array_count = 0, i = 0; 1134 1135 /* Get the configured list of gport array 1136 and array count*/ 1137 BCM_IF_ERROR_RETURN 1138 (bcm_td3_oob_fc_rx_config_get(unit, intf_id, &config, 1139 _TD3_MAX_RX_MEM_ENTRY, gport_array, 1140 &array_count)); 1141 1142 if (config.enable == 0) { 1143 return BCM_E_PARAM; 1144 } 1145 1146 /* Get the Channel offset of the port in HCFC message */ 1147 for (i = 0; i < array_count; i++) { 1148 if (gport == gport_array[i]) { 1149 break; 1150 } 1151 } 1152 1153 /* Return error if gport is not there in the list */ 1154 if (i == array_count) { 1155 return BCM_E_NOT_FOUND; 1156 } 1157 1158 *offset = i; 1159 1160 return BCM_E_NONE; 1161 } 1162 1163 /* 1164 * Function: 1165 * _bcm_td3_oob_fc_rx_tc_mapping_get 1166 * Purpose: 1167 * Get the traffic class to priority 1168 * mapping for given OOB FC Rx Interface at 1169 * given idx in the memory. 1170 * Parameters: 1171 * unit - (IN) StrataSwitch unit number 1172 * intf_id - (IN) OOB FC Rx Interface Number 1173 * tc - (IN) Traffic Class array[0-7] 1174 * pri_bmp - (OUT) Priority Bitmap[0-7] 1175 * idx - (IN) Index in TC to PRI mapping memory 1176 * Returns: 1177 * BCM_E_XXX 1178 */ 1179 STATIC int 1180 _bcm_td3_oob_fc_rx_tc_mapping_get(int unit, 1181 bcm_oob_fc_rx_intf_id_t intf_id, 1182 uint32 tc, uint32 *pri_bmp, 1183 uint32 idx) 1184 { 1185 char *tc2pri_buf; 1186 uint64 tc2pri; 1187 void *pentry; 1188 int mem_wsz = 0; 1189 1190 COMPILER_64_ZERO(tc2pri); 1191 1192 /* Read the MMU_INTFO_TC2PRI_MAPPING memory into tc2pri_buf */ 1193 mem_wsz = sizeof(uint32) * 1194 soc_mem_entry_words(unit, MMU_INTFO_TC2PRI_MAPPINGm); 1195 tc2pri_buf = soc_cm_salloc(unit, _TD3_MAX_RX_MEM_ENTRY * mem_wsz, 1196 "oob tc2pri_buf"); 1197 if (tc2pri_buf == NULL) { 1198 return BCM_E_MEMORY; 1199 } 1200 1201 if (soc_mem_read_range(unit, MMU_INTFO_TC2PRI_MAPPINGm, MEM_BLOCK_ALL, 1202 0, _TD3_MAX_RX_MEM_ENTRY - 1, tc2pri_buf)) { 1203 soc_cm_sfree(unit, tc2pri_buf); 1204 return BCM_E_INTERNAL; 1205 } 1206 1207 /* Get the pointer to the given index. */ 1208 pentry = soc_mem_table_idx_to_pointer(unit, 1209 MMU_INTFO_TC2PRI_MAPPINGm, 1210 void*, tc2pri_buf, idx); 1211 1212 soc_mem_field64_get(unit, MMU_INTFO_TC2PRI_MAPPINGm, 1213 pentry, PRI_BMPf, &tc2pri); 1214 1215 /* Get tc2pri value */ 1216 COMPILER_64_SHR(tc2pri, (8 * tc)); 1217 *pri_bmp = COMPILER_64_LO(tc2pri) & 0xFF; 1218 1219 soc_cm_sfree(unit, tc2pri_buf); 1220 return BCM_E_NONE; 1221 } 1222 1223 /* 1224 * Function: 1225 * _bcm_td3_oob_fc_rx_tc_mapping_set 1226 * Purpose: 1227 * Set the traffic class to priority 1228 * mapping for given OOB FC Rx Interface at 1229 * given idx in the memory. 1230 * Parameters: 1231 * unit - (IN) StrataSwitch unit number 1232 * intf_id - (IN) OOB FC Rx Interface Number 1233 * tc - (IN) Traffic Class array[0-7] 1234 * pri_bmp - (IN) Priority Bitmap[0-7] 1235 * idx - (IN) Index in TC to PRI mapping memory 1236 * Returns: 1237 * BCM_E_XXX 1238 */ 1239 STATIC int 1240 _bcm_td3_oob_fc_rx_tc_mapping_set(int unit, 1241 bcm_oob_fc_rx_intf_id_t intf_id, uint32 tc, 1242 uint32 pri_bmp, uint32 idx) 1243 { 1244 char *tc2pri_buf; 1245 uint64 tc2pri; 1246 uint64 mask64; 1247 uint64 pri_bmp64; 1248 int rv = BCM_E_INTERNAL; 1249 void *pentry; 1250 int mem_wsz = 0; 1251 1252 COMPILER_64_ZERO(tc2pri); 1253 COMPILER_64_ZERO(mask64); 1254 COMPILER_64_ZERO(pri_bmp64); 1255 1256 /* Read the MMU_INTFO_TC2PRI_MAPPING memory into tc2pri_buf */ 1257 mem_wsz = sizeof(uint32) * 1258 soc_mem_entry_words(unit, MMU_INTFO_TC2PRI_MAPPINGm); 1259 tc2pri_buf = soc_cm_salloc(unit, _TD3_MAX_RX_MEM_ENTRY * mem_wsz, 1260 "oob tc2pri_buf"); 1261 if (tc2pri_buf == NULL) { 1262 return BCM_E_MEMORY; 1263 } 1264 1265 if (soc_mem_read_range(unit, MMU_INTFO_TC2PRI_MAPPINGm, MEM_BLOCK_ALL, 1266 0, _TD3_MAX_RX_MEM_ENTRY - 1, tc2pri_buf)) { 1267 rv = BCM_E_INTERNAL; 1268 soc_cm_sfree(unit, tc2pri_buf); 1269 return rv; 1270 } 1271 1272 /* Get the pointer to the given index. */ 1273 pentry = soc_mem_table_idx_to_pointer(unit, 1274 MMU_INTFO_TC2PRI_MAPPINGm, 1275 void*, tc2pri_buf, idx); 1276 1277 soc_mem_field64_get(unit, MMU_INTFO_TC2PRI_MAPPINGm, 1278 pentry, PRI_BMPf, &tc2pri); 1279 1280 1281 /* Disable the given OOBFC Rx interface */ 1282 rv = _bcm_td3_oob_fc_rx_disable_intf(unit, intf_id); 1283 if (rv != BCM_E_NONE) { 1284 soc_cm_sfree(unit, tc2pri_buf); 1285 return rv; 1286 } 1287 1288 /* Update tc2pri value */ 1289 COMPILER_64_SET(pri_bmp64, 0, pri_bmp); 1290 COMPILER_64_SHL(pri_bmp64, (tc * 8)); 1291 COMPILER_64_MASK_CREATE(mask64, 8, (tc * 8)); 1292 COMPILER_64_NOT(mask64); 1293 COMPILER_64_AND(tc2pri, mask64); 1294 COMPILER_64_OR(tc2pri, pri_bmp64); 1295 1296 /* Program tc2pri MMU_INTFO_TC2PRI_MAPPING */ 1297 soc_mem_field64_set(unit, MMU_INTFO_TC2PRI_MAPPINGm, 1298 pentry, PRI_BMPf, tc2pri); 1299 1300 if (soc_mem_write_range(unit, MMU_INTFO_TC2PRI_MAPPINGm, MEM_BLOCK_ALL, 1301 0, _TD3_MAX_RX_MEM_ENTRY - 1, tc2pri_buf)) { 1302 rv = BCM_E_INTERNAL; 1303 soc_cm_sfree(unit, tc2pri_buf); 1304 return rv; 1305 } 1306 1307 /* Enable the given OOBFC Rx interface back */ 1308 rv = _bcm_td3_oob_fc_rx_enable_intf(unit, intf_id); 1309 if (rv != BCM_E_NONE) { 1310 soc_cm_sfree(unit, tc2pri_buf); 1311 return rv; 1312 } 1313 1314 rv = BCM_E_NONE; 1315 soc_cm_sfree(unit, tc2pri_buf); 1316 return rv; 1317 } 1318 1319 /* 1320 * Function: 1321 * _bcm_td3_oob_fc_rx_config_disable_set 1322 * Purpose: 1323 * Disable and reset the configuration of the 1324 * given OOB FC Rx Interface 1325 * Parameters: 1326 * unit - (IN) StrataSwitch unit number 1327 * intf_id - (IN) OOB FC Rx Interface Number 1328 * Returns: 1329 * BCM_E_XXX 1330 */ 1331 STATIC int 1332 _bcm_td3_oob_fc_rx_config_disable_set(int unit, 1333 bcm_oob_fc_rx_intf_id_t intf_id) 1334 { 1335 _bcm_td3_oob_fc_rx_intf_info_t old_info[_TD3_NUM_OOB_FC_RX_INTF]; 1336 _bcm_td3_oob_fc_rx_intf_info_t new_info[_TD3_NUM_OOB_FC_RX_INTF]; 1337 char *sysport_buf, *tc2pri_buf; 1338 uint32 old_sysport_list[_TD3_MAX_RX_MEM_ENTRY]; 1339 uint64 old_tc2pri_list[_TD3_MAX_RX_MEM_ENTRY]; 1340 uint32 new_sysport_list[_TD3_MAX_RX_MEM_ENTRY]; 1341 uint64 new_tc2pri_list[_TD3_MAX_RX_MEM_ENTRY]; 1342 int rv = BCM_E_INTERNAL; 1343 int mem_wsz = 0; 1344 int i = 0, j = 0, k = 0; 1345 void *pentry; 1346 uint32 rval = 0x0; 1347 soc_reg_t cfg_reg[_TD3_NUM_OOB_FC_RX_INTF] = {OOBFC_CHIF_CFG0r, 1348 OOBFC_CHIF_CFG1r, 1349 OOBFC_CHIF_CFG2r, 1350 OOBFC_CHIF_CFG3r}; 1351 1352 sal_memset(old_info, 0, sizeof(_bcm_td3_oob_fc_rx_intf_info_t) * 1353 _TD3_NUM_OOB_FC_RX_INTF); 1354 sal_memset(new_info, 0, sizeof(_bcm_td3_oob_fc_rx_intf_info_t) * 1355 _TD3_NUM_OOB_FC_RX_INTF); 1356 sal_memset(old_sysport_list, 0, sizeof(uint32) * 1357 _TD3_MAX_RX_MEM_ENTRY); 1358 sal_memset(new_sysport_list, 0, sizeof(uint32) * 1359 _TD3_MAX_RX_MEM_ENTRY); 1360 sal_memset(old_tc2pri_list, 0, sizeof(uint64) * 1361 _TD3_MAX_RX_MEM_ENTRY); 1362 sal_memset(new_tc2pri_list, 0, sizeof(uint64) * 1363 _TD3_MAX_RX_MEM_ENTRY); 1364 1365 /* Store all the OOBFC Rx interface configuration */ 1366 for (i = 0; i < _TD3_NUM_OOB_FC_RX_INTF; i++) { 1367 BCM_IF_ERROR_RETURN 1368 (_bcm_td3_oob_fc_rx_get_intf_info(unit, &old_info[i], i)); 1369 } 1370 1371 /* Read the MMU_CHFC_SYSPORT_MAPPING memory into sysport_buf */ 1372 mem_wsz = sizeof(uint32) * 1373 soc_mem_entry_words(unit, MMU_CHFC_SYSPORT_MAPPINGm); 1374 sysport_buf = soc_cm_salloc(unit, _TD3_MAX_RX_MEM_ENTRY * mem_wsz, 1375 "oob sysport_buf"); 1376 if (sysport_buf == NULL) { 1377 return BCM_E_MEMORY; 1378 } 1379 1380 if (soc_mem_read_range(unit, MMU_CHFC_SYSPORT_MAPPINGm, MEM_BLOCK_ALL, 1381 0, _TD3_MAX_RX_MEM_ENTRY - 1, sysport_buf)) { 1382 rv = BCM_E_INTERNAL; 1383 soc_cm_sfree(unit, sysport_buf); 1384 return rv; 1385 } 1386 1387 /* Store the sysport_buf in old_sysport_list */ 1388 for (i = 0; i < _TD3_MAX_RX_MEM_ENTRY; i++) { 1389 pentry = soc_mem_table_idx_to_pointer(unit, 1390 MMU_CHFC_SYSPORT_MAPPINGm, 1391 void*, sysport_buf, i); 1392 old_sysport_list[i] = soc_mem_field32_get(unit, 1393 MMU_CHFC_SYSPORT_MAPPINGm, 1394 pentry, SYS_PORTf); 1395 } 1396 1397 /* Read the MMU_INTFO_TC2PRI_MAPPING memory into tc2pri_list */ 1398 mem_wsz = sizeof(uint32) * 1399 soc_mem_entry_words(unit, MMU_INTFO_TC2PRI_MAPPINGm); 1400 tc2pri_buf = soc_cm_salloc(unit, _TD3_MAX_RX_MEM_ENTRY * mem_wsz, 1401 "oob tc2pri_buf"); 1402 if (tc2pri_buf == NULL) { 1403 rv = BCM_E_MEMORY; 1404 soc_cm_sfree(unit, sysport_buf); 1405 return rv; 1406 } 1407 1408 if (soc_mem_read_range(unit, MMU_INTFO_TC2PRI_MAPPINGm, MEM_BLOCK_ALL, 1409 0, _TD3_MAX_RX_MEM_ENTRY - 1, tc2pri_buf)) { 1410 rv = BCM_E_INTERNAL; 1411 soc_cm_sfree(unit, tc2pri_buf); 1412 soc_cm_sfree(unit, sysport_buf); 1413 return rv; 1414 } 1415 1416 /* Store the tc2pri_buf in old_tc2pri_list */ 1417 for (i = 0; i < _TD3_MAX_RX_MEM_ENTRY; i++) { 1418 pentry = soc_mem_table_idx_to_pointer(unit, 1419 MMU_INTFO_TC2PRI_MAPPINGm, 1420 void*, tc2pri_buf, i); 1421 soc_mem_field64_get(unit, MMU_INTFO_TC2PRI_MAPPINGm, 1422 pentry, PRI_BMPf, &old_tc2pri_list[i]); 1423 } 1424 1425 /* Disable all the OOBFC Rx interface */ 1426 for (i = 0; i < _TD3_NUM_OOB_FC_RX_INTF; i++) { 1427 if (old_info[i].enable == 1) { 1428 rv = _bcm_td3_oob_fc_rx_disable_intf(unit, i); 1429 if (rv != BCM_E_NONE) { 1430 soc_cm_sfree(unit, tc2pri_buf); 1431 soc_cm_sfree(unit, sysport_buf); 1432 return rv; 1433 } 1434 } 1435 } 1436 1437 /* Generate new_info */ 1438 /* Genrate new_sysport_list */ 1439 /* Genrate new_tc2pri_list */ 1440 j = 0; 1441 k = 0; 1442 for (i = 0; i < _TD3_NUM_OOB_FC_RX_INTF; i++) { 1443 if (i != intf_id) { 1444 new_info[i].enable = old_info[i].enable; 1445 new_info[i].channel_base = old_info[i].channel_base; 1446 new_info[i].num_ports = old_info[i].num_ports; 1447 if (new_info[i].enable) { 1448 new_info[i].lookup_base = j; 1449 } else { 1450 new_info[i].lookup_base = 0x0; 1451 } 1452 for (k = 0; k < new_info[i].num_ports; k++) { 1453 new_sysport_list[j] = old_sysport_list[old_info[i].lookup_base + k]; 1454 new_tc2pri_list[j] = old_tc2pri_list[old_info[i].lookup_base + k]; 1455 j++; 1456 } 1457 } else { 1458 new_info[i].enable = 0; 1459 new_info[i].channel_base = 0; 1460 new_info[i].lookup_base = 0; 1461 new_info[i].num_ports = 0; 1462 } 1463 } 1464 1465 /* Program new_tc2pri_list in MMU_INTFO_TC2PRI_MAPPING */ 1466 for (i = 0; i < _TD3_MAX_RX_MEM_ENTRY; i++) { 1467 pentry = soc_mem_table_idx_to_pointer(unit, 1468 MMU_INTFO_TC2PRI_MAPPINGm, 1469 void*, tc2pri_buf, i); 1470 soc_mem_field64_set(unit, MMU_INTFO_TC2PRI_MAPPINGm, 1471 pentry, PRI_BMPf, new_tc2pri_list[i]); 1472 } 1473 1474 if (soc_mem_write_range(unit, MMU_INTFO_TC2PRI_MAPPINGm, MEM_BLOCK_ALL, 1475 0, _TD3_MAX_RX_MEM_ENTRY - 1, tc2pri_buf)) { 1476 rv = BCM_E_INTERNAL; 1477 soc_cm_sfree(unit, tc2pri_buf); 1478 soc_cm_sfree(unit, sysport_buf); 1479 return rv; 1480 } 1481 1482 /* Program new_sysport_list MMU_CHFC_SYSPORT_MAPPING */ 1483 for (i = 0; i < _TD3_MAX_RX_MEM_ENTRY; i++) { 1484 pentry = soc_mem_table_idx_to_pointer(unit, 1485 MMU_CHFC_SYSPORT_MAPPINGm, 1486 void*, sysport_buf, i); 1487 soc_mem_field32_set(unit, MMU_CHFC_SYSPORT_MAPPINGm, pentry, 1488 SYS_PORTf, new_sysport_list[i]); 1489 } 1490 1491 if (soc_mem_write_range(unit, MMU_CHFC_SYSPORT_MAPPINGm, MEM_BLOCK_ALL, 1492 0, _TD3_MAX_RX_MEM_ENTRY - 1, sysport_buf)) { 1493 rv = BCM_E_INTERNAL; 1494 soc_cm_sfree(unit, tc2pri_buf); 1495 soc_cm_sfree(unit, sysport_buf); 1496 return rv; 1497 } 1498 1499 /* Program all the OOBFC Rx interface configuration register */ 1500 for (i = 0; i < _TD3_NUM_OOB_FC_RX_INTF; i++) { 1501 rv = soc_reg32_get(unit, cfg_reg[i], 1502 0, 0, &rval); 1503 if (rv != BCM_E_NONE) { 1504 soc_cm_sfree(unit, tc2pri_buf); 1505 soc_cm_sfree(unit, sysport_buf); 1506 return rv; 1507 } 1508 soc_reg_field_set(unit, cfg_reg[i], &rval, 1509 OOBFC_CH_ENf, new_info[i].enable); 1510 soc_reg_field_set(unit, cfg_reg[i], &rval, 1511 OOBFC_CH_BASEf, new_info[i].channel_base); 1512 soc_reg_field_set(unit, cfg_reg[i], &rval, 1513 LOOKUP_BASEf, new_info[i].lookup_base); 1514 soc_reg_field_set(unit, cfg_reg[i], &rval, 1515 CH_PORT_NUMf, new_info[i].num_ports); 1516 rv = soc_reg32_set(unit, cfg_reg[i], 1517 0, 0, rval); 1518 if (rv != BCM_E_NONE) { 1519 soc_cm_sfree(unit, tc2pri_buf); 1520 soc_cm_sfree(unit, sysport_buf); 1521 return rv; 1522 } 1523 } 1524 1525 rv = BCM_E_NONE; 1526 soc_cm_sfree(unit, tc2pri_buf); 1527 soc_cm_sfree(unit, sysport_buf); 1528 return rv; 1529 } 1530 1531 /* 1532 * Function: 1533 * _bcm_td3_oob_fc_rx_config_get 1534 * Purpose: 1535 * Get the configuration and status 1536 * each OOB FC Rx Interface. 1537 * Parameters: 1538 * unit - (IN) StrataSwitch unit number 1539 * intf_id - (IN) OOB FC Rx Interface Number 1540 * config - (OUT) OOB FC Rx Interface Config 1541 * array_max - (IN) Maximum Lenght of Gport array passed 1542 * gport_array - (OUT) Array of modport type gport 1543 * array_count - (OUT) Number of gports returned in the gport array 1544 * Returns: 1545 * BCM_E_XXX 1546 */ 1547 STATIC int 1548 _bcm_td3_oob_fc_rx_config_get(int unit, 1549 bcm_oob_fc_rx_intf_id_t intf_id, 1550 bcm_oob_fc_rx_config_t *config, 1551 int array_max, 1552 bcm_gport_t *gport_array, 1553 int *array_count) 1554 { 1555 _bcm_td3_oob_fc_rx_intf_info_t info; 1556 int rv = BCM_E_INTERNAL; 1557 char *sysport_buf; 1558 void *pentry; 1559 int mem_wsz = 0; 1560 int i = 0 , j = 0; 1561 bcm_gport_t gport; 1562 uint32 new_sysport_list[_TD3_MAX_RX_MEM_ENTRY]; 1563 1564 sal_memset(&info, 0, sizeof(_bcm_td3_oob_fc_rx_intf_info_t)); 1565 sal_memset(new_sysport_list, 0, sizeof(uint32) * 1566 _TD3_MAX_RX_MEM_ENTRY); 1567 1568 /* Store all the OOBFC Rx interface configuration */ 1569 BCM_IF_ERROR_RETURN 1570 (_bcm_td3_oob_fc_rx_get_intf_info(unit, &info, intf_id)); 1571 1572 /* If given OOBFC Rx Interface is not enabled then 1573 return empty gport array */ 1574 if (info.enable == 0) { 1575 sal_memset(config, 0, sizeof(bcm_oob_fc_rx_config_t)); 1576 sal_memset(gport_array, 0, sizeof(bcm_gport_t) * array_max); 1577 *array_count = 0; 1578 return BCM_E_NONE; 1579 } else { 1580 config->enable = info.enable; 1581 config->channel_base = info.channel_base; 1582 /* Read the MMU_CHFC_SYSPORT_MAPPING memory into sysport_buf */ 1583 mem_wsz = sizeof(uint32) * 1584 soc_mem_entry_words(unit, MMU_CHFC_SYSPORT_MAPPINGm); 1585 sysport_buf = soc_cm_salloc(unit, _TD3_MAX_RX_MEM_ENTRY * mem_wsz, 1586 "oob sysport_buf"); 1587 if (sysport_buf == NULL) { 1588 return BCM_E_MEMORY; 1589 } 1590 1591 if (soc_mem_read_range(unit, MMU_CHFC_SYSPORT_MAPPINGm, MEM_BLOCK_ALL, 1592 0, _TD3_MAX_RX_MEM_ENTRY - 1, sysport_buf)) { 1593 rv = BCM_E_INTERNAL; 1594 soc_cm_sfree(unit, sysport_buf); 1595 return rv; 1596 } 1597 1598 if (array_max >= info.num_ports) { 1599 *array_count = info.num_ports; 1600 } else { 1601 *array_count = array_max; 1602 } 1603 1604 /* Store the required number of indexes into a sysport_list */ 1605 for (i = info.lookup_base, j = 0; 1606 i < (info.lookup_base + *array_count); i++, j++) { 1607 pentry = soc_mem_table_idx_to_pointer(unit, 1608 MMU_CHFC_SYSPORT_MAPPINGm, 1609 void*, sysport_buf, i); 1610 new_sysport_list[j] = soc_mem_field32_get(unit, 1611 MMU_CHFC_SYSPORT_MAPPINGm, 1612 pentry, SYS_PORTf); 1613 } 1614 1615 /* Convert the sysport list into a modport gport list */ 1616 for (i = 0; i < *array_count; i++) { 1617 rv = bcm_esw_port_gport_get(unit, new_sysport_list[i], 1618 &gport); 1619 if (rv != BCM_E_NONE) { 1620 soc_cm_sfree(unit, sysport_buf); 1621 return rv; 1622 } 1623 gport_array[i] = gport; 1624 } 1625 1626 } 1627 1628 rv = BCM_E_NONE; 1629 soc_cm_sfree(unit, sysport_buf); 1630 return rv; 1631 } 1632 1633 /* 1634 * Function: 1635 * bcm_td3_oob_fc_rx_config_set 1636 * Purpose: 1637 * Set the configuration and enable 1638 * each OOB FC Rx Interface. 1639 * Parameters: 1640 * unit - (IN) StrataSwitch unit number 1641 * intf_id - (IN) OOB FC Rx Interface Number 1642 * config - (IN) OOB FC Rx Interface Config 1643 * array_count - (IN) Number of gports in the gport array 1644 * gport_array - (IN) Array of modport type gport 1645 * Returns: 1646 * BCM_E_XXX 1647 */ 1648 int 1649 bcm_td3_oob_fc_rx_config_set(int unit, 1650 bcm_oob_fc_rx_intf_id_t intf_id, 1651 bcm_oob_fc_rx_config_t *config, 1652 int array_count, 1653 bcm_gport_t *gport_array) 1654 { 1655 if ((intf_id < 0) || (intf_id >= _TD3_NUM_OOB_FC_RX_INTF)) { 1656 return BCM_E_PARAM; 1657 } 1658 1659 if (config == NULL) { 1660 return BCM_E_PARAM; 1661 } 1662 1663 if ((config->enable != 0) && (config->enable != 1)) { 1664 return BCM_E_PARAM; 1665 } 1666 1667 if ((config->enable == 1) && 1668 ((array_count == 0) || (gport_array == NULL) || 1669 (array_count > _TD3_MAX_RX_MEM_ENTRY))) { 1670 return BCM_E_PARAM; 1671 } 1672 1673 if ((config->enable == 1) && 1674 ((config->channel_base > _TD3_MAX_CHANNEL_BASE))) { 1675 return BCM_E_PARAM; 1676 } 1677 1678 if (config->enable == 1) { 1679 /* Add entries into MMU_CHFC_SYSPORT_MAPPING memory */ 1680 BCM_IF_ERROR_RETURN 1681 (_bcm_td3_oob_fc_rx_config_enable_set(unit, intf_id, 1682 config->channel_base, 1683 array_count, gport_array)); 1684 } else { 1685 /* Remove entries from MMU_CHFC_SYSPORT_MAPPING memory */ 1686 BCM_IF_ERROR_RETURN 1687 (_bcm_td3_oob_fc_rx_config_disable_set(unit, intf_id)); 1688 } 1689 1690 return BCM_E_NONE; 1691 } 1692 1693 /* 1694 * Function: 1695 * bcm_td3_oob_fc_rx_config_get 1696 * Purpose: 1697 * Get the configuration and status 1698 * each OOB FC Rx Interface. 1699 * Parameters: 1700 * unit - (IN) StrataSwitch unit number 1701 * intf_id - (IN) OOB FC Rx Interface Number 1702 * config - (OUT) OOB FC Rx Interface Config 1703 * array_max - (IN) Maximum Lenght of Gport array passed 1704 * gport_array - (OUT) Array of modport type gport 1705 * array_count - (OUT) Number of gports returned in the gport array 1706 * Returns: 1707 * BCM_E_XXX 1708 */ 1709 int 1710 bcm_td3_oob_fc_rx_config_get(int unit, 1711 bcm_oob_fc_rx_intf_id_t intf_id, 1712 bcm_oob_fc_rx_config_t *config, 1713 int array_max, 1714 bcm_gport_t *gport_array, 1715 int *array_count) 1716 { 1717 if ((intf_id < 0) || (intf_id >= _TD3_NUM_OOB_FC_RX_INTF)) { 1718 return BCM_E_PARAM; 1719 } 1720 1721 if ((gport_array == NULL) || 1722 (config == NULL) || 1723 (array_count == NULL)) { 1724 return BCM_E_PARAM; 1725 } 1726 1727 BCM_IF_ERROR_RETURN 1728 (_bcm_td3_oob_fc_rx_config_get(unit, intf_id, 1729 config, array_max, 1730 gport_array, 1731 array_count)); 1732 1733 return BCM_E_NONE; 1734 } 1735 1736 /* 1737 * Function: 1738 * bcm_td3_oob_fc_rx_port_tc_mapping_multi_set 1739 * Purpose: 1740 * Set the per port traffic class to priority 1741 * mapping for each OOB FC Rx Interface. 1742 * Parameters: 1743 * unit - (IN) StrataSwitch unit number 1744 * intf_id - (IN) OOB FC Rx Interface Number 1745 * gport - (IN) Modport type gport 1746 * array_count - (IN) Number of elements in Traffic Class array 1747 * tc - (IN) Traffic Class array[0-7] 1748 * pri_bmp - (IN) Priority Bitmap Array[0-7] 1749 * Returns: 1750 * BCM_E_XXX 1751 */ 1752 int 1753 bcm_td3_oob_fc_rx_port_tc_mapping_multi_set(int unit, 1754 bcm_oob_fc_rx_intf_id_t intf_id, 1755 bcm_gport_t gport, 1756 int array_count, 1757 uint32 *tc, 1758 uint32 *pri_bmp) 1759 { 1760 int i = 0; 1761 1762 if ((intf_id < 0) || (intf_id >= _TD3_NUM_OOB_FC_RX_INTF)) { 1763 return BCM_E_PARAM; 1764 } 1765 1766 if ((array_count < 1) || (array_count > _TD3_NUM_TC)) { 1767 return BCM_E_PARAM; 1768 } 1769 1770 if ((tc == NULL) || (pri_bmp == NULL)) { 1771 return BCM_E_PARAM; 1772 } 1773 1774 for (i = 0; i < array_count; i++) { 1775 if ((tc[i] > (_TD3_NUM_TC - 1)) || (pri_bmp[i] > 0xFF)) { 1776 return BCM_E_PARAM; 1777 } 1778 } 1779 1780 for (i = 0; i < array_count; i++) { 1781 BCM_IF_ERROR_RETURN 1782 (bcm_td3_oob_fc_rx_port_tc_mapping_set(unit, intf_id, 1783 gport, tc[i], 1784 pri_bmp[i])); 1785 } 1786 1787 return BCM_E_NONE; 1788 } 1789 1790 /* 1791 * Function: 1792 * bcm_td3_oob_fc_rx_port_tc_mapping_multi_get 1793 * Purpose: 1794 * Get the per port traffic class to priority 1795 * mapping for each OOB FC Rx Interface. 1796 * Parameters: 1797 * unit - (IN) StrataSwitch unit number 1798 * intf_id - (IN) OOB FC Rx Interface Number 1799 * gport - (IN) Modport type gport 1800 * array_max - (IN) Maximum Length tc and pri_bmp array 1801 * tc - (OUT) Traffic Class array[0-7] 1802 * pri_bmp - (OUT) Priority Bitmap Array[0-7] 1803 * array_count - (OUT) Number of elements in Traffic Class array 1804 * Returns: 1805 * BCM_E_XXX 1806 */ 1807 int 1808 bcm_td3_oob_fc_rx_port_tc_mapping_multi_get(int unit, 1809 bcm_oob_fc_rx_intf_id_t intf_id, 1810 bcm_gport_t gport, 1811 int array_max, 1812 uint32 *tc, 1813 uint32 *pri_bmp, 1814 int *array_count) 1815 { 1816 int i = 0; 1817 1818 if ((intf_id < 0) || (intf_id >= _TD3_NUM_OOB_FC_RX_INTF)) { 1819 return BCM_E_PARAM; 1820 } 1821 1822 if (array_max < 1) { 1823 return BCM_E_PARAM; 1824 } 1825 1826 if ((array_count == NULL) || 1827 (tc == NULL) || 1828 (pri_bmp == NULL)) { 1829 return BCM_E_PARAM; 1830 } 1831 1832 if (array_max > _TD3_NUM_TC) { 1833 *array_count = _TD3_NUM_TC; 1834 } else { 1835 *array_count = array_max; 1836 } 1837 1838 for (i = 0; i < *array_count; i++) { 1839 if (tc[i] > (_TD3_NUM_TC - 1)) { 1840 return BCM_E_PARAM; 1841 } 1842 } 1843 1844 for (i = 0; i < *array_count; i++) { 1845 BCM_IF_ERROR_RETURN 1846 (bcm_td3_oob_fc_rx_port_tc_mapping_get(unit, intf_id, 1847 gport, tc[i], 1848 &pri_bmp[i])); 1849 } 1850 return BCM_E_NONE; 1851 } 1852 1853 1854 /* 1855 * Function: 1856 * bcm_td3_oob_fc_rx_port_tc_mapping_set 1857 * Purpose: 1858 * Set the per port traffic class to priority 1859 * mapping for each OOB FC Rx Interface. 1860 * Parameters: 1861 * unit - (IN) StrataSwitch unit number 1862 * intf_id - (IN) OOB FC Rx Interface Number 1863 * gport - (IN) Modport type gport 1864 * tc - (IN) Traffic Class array[0-7] 1865 * pri_bmp - (IN) Priority Bitmap[0-7] 1866 * Returns: 1867 * BCM_E_XXX 1868 */ 1869 int 1870 bcm_td3_oob_fc_rx_port_tc_mapping_set(int unit, 1871 bcm_oob_fc_rx_intf_id_t intf_id, 1872 bcm_gport_t gport, 1873 uint32 tc, 1874 uint32 pri_bmp) 1875 { 1876 uint32 idx = 0; 1877 uint32 offset = 0; 1878 uint32 lookup_base = 0; 1879 1880 if ((intf_id < 0) || (intf_id >= _TD3_NUM_OOB_FC_RX_INTF)) { 1881 return BCM_E_PARAM; 1882 } 1883 1884 if ((tc > (_TD3_NUM_TC - 1)) || (pri_bmp > 0xFF)) { 1885 return BCM_E_PARAM; 1886 } 1887 1888 BCM_IF_ERROR_RETURN 1889 (_bcm_td3_oob_fc_rx_port_offset_get(unit, intf_id, 1890 gport, &offset)); 1891 1892 /* Get lookup base */ 1893 BCM_IF_ERROR_RETURN 1894 (_bcm_td3_oob_fc_rx_intf_get_lookup_base(unit, intf_id, 1895 &lookup_base)); 1896 1897 idx = offset + lookup_base; 1898 1899 BCM_IF_ERROR_RETURN 1900 (_bcm_td3_oob_fc_rx_tc_mapping_set(unit, intf_id, tc, 1901 pri_bmp, idx)); 1902 1903 return BCM_E_NONE; 1904 } 1905 1906 /* 1907 * Function: 1908 * bcm_td3_oob_fc_rx_port_tc_mapping_get 1909 * Purpose: 1910 * Set the per port traffic class to priority 1911 * mapping for each OOB FC Rx Interface. 1912 * Parameters: 1913 * unit - (IN) StrataSwitch unit number 1914 * intf_id - (IN) OOB FC Rx Interface Number 1915 * gport - (IN) Modport type gport 1916 * tc - (IN) Traffic Class array[0-7] 1917 * pri_bmp - (OUT) Priority Bitmap[0-7] 1918 * Returns: 1919 * BCM_E_XXX 1920 */ 1921 int 1922 bcm_td3_oob_fc_rx_port_tc_mapping_get(int unit, 1923 bcm_oob_fc_rx_intf_id_t intf_id, 1924 bcm_gport_t gport, 1925 uint32 tc, 1926 uint32 *pri_bmp) 1927 { 1928 uint32 idx = 0; 1929 uint32 offset = 0; 1930 uint32 lookup_base = 0; 1931 1932 if ((intf_id < 0) || (intf_id >= _TD3_NUM_OOB_FC_RX_INTF)) { 1933 return BCM_E_PARAM; 1934 } 1935 1936 if (tc > (_TD3_NUM_TC - 1)) { 1937 return BCM_E_PARAM; 1938 } 1939 1940 BCM_IF_ERROR_RETURN 1941 (_bcm_td3_oob_fc_rx_port_offset_get(unit, intf_id, 1942 gport, &offset)); 1943 1944 /* Get lookup base */ 1945 BCM_IF_ERROR_RETURN 1946 (_bcm_td3_oob_fc_rx_intf_get_lookup_base(unit, intf_id, 1947 &lookup_base)); 1948 1949 idx = offset + lookup_base; 1950 1951 BCM_IF_ERROR_RETURN 1952 (_bcm_td3_oob_fc_rx_tc_mapping_get(unit, intf_id, tc, 1953 pri_bmp, idx)); 1954 1955 return BCM_E_NONE; 1956 } 1957 1958 /* 1959 * Function: 1960 * bcm_td3_oob_fc_rx_port_offset_get 1961 * Purpose: 1962 * Get the Channel offset value for a given port 1963 * on given OOB FC Rx Interface. 1964 * Parameters: 1965 * unit - (IN) StrataSwitch unit number 1966 * intf_id - (IN) OOB FC Rx Interface Number 1967 * gport - (IN) Modport type gport 1968 * offset - (OUT) Channel offset value in HCFC message 1969 * Returns: 1970 * BCM_E_XXX 1971 */ 1972 int 1973 bcm_td3_oob_fc_rx_port_offset_get(int unit, 1974 bcm_oob_fc_rx_intf_id_t intf_id, 1975 bcm_gport_t gport, 1976 uint32 *offset) 1977 { 1978 if ((intf_id < 0) || (intf_id >= _TD3_NUM_OOB_FC_RX_INTF)) { 1979 return BCM_E_PARAM; 1980 } 1981 1982 BCM_IF_ERROR_RETURN 1983 (_bcm_td3_oob_fc_rx_port_offset_get(unit, intf_id, 1984 gport, offset)); 1985 1986 return BCM_E_NONE; 1987 } 1988 1989 1990 /* 1991 * Function: 1992 * _bcm_td3_oob_stats_config_flags_set 1993 * Purpose: 1994 * Set the enable control for OOB STATS. 1995 * Parameters: 1996 * unit - (IN) StrataSwitch unit number 1997 * flags - (IN) OOB Stats Enable controls 1998 * Returns: 1999 * BCM_E_XXX 2000 */ 2001 STATIC int 2002 _bcm_td3_oob_stats_config_flags_set(int unit, uint32 flags) 2003 { 2004 uint32 rval = 0; 2005 2006 BCM_IF_ERROR_RETURN 2007 (soc_reg32_get(unit, STATS_INTF_REPORT_ENr, 0, 0, &rval)); 2008 2009 soc_reg_field_set(unit, STATS_INTF_REPORT_ENr, &rval, TIMESTAMP_ENf, 2010 ((flags & BCM_OOB_STATS_TIMESTAMP_EN) ? 0x1 : 0x0)); 2011 2012 soc_reg_field_set(unit, STATS_INTF_REPORT_ENr, &rval, INST_SERV_POOL_SIZE_ENf, 2013 ((flags & BCM_OOB_STATS_POOL_EN) ? 0x1 : 0x0)); 2014 2015 soc_reg_field_set(unit, STATS_INTF_REPORT_ENr, &rval, INST_UC_QSIZE_ENf, 2016 ((flags & BCM_OOB_STATS_QUEUE_EN) ? 0x1 : 0x0)); 2017 2018 BCM_IF_ERROR_RETURN 2019 (soc_reg32_set(unit, STATS_INTF_REPORT_ENr, 0, 0, rval)); 2020 2021 return BCM_E_NONE; 2022 } 2023 2024 /* 2025 * Function: 2026 * _bcm_td3_oob_stats_config_ipg_set 2027 * Purpose: 2028 * Set the inter packet gap for OOB STATS. 2029 * Parameters: 2030 * unit - (IN) StrataSwitch unit number 2031 * ipg - (IN) OOB Stats inter packet gap(clock cycles) 2032 * can range from 0-255 2033 * Returns: 2034 * BCM_E_XXX 2035 */ 2036 STATIC int 2037 _bcm_td3_oob_stats_config_ipg_set(int unit, uint8 ipg) 2038 { 2039 uint32 rval = 0; 2040 2041 BCM_IF_ERROR_RETURN 2042 (soc_reg32_get(unit, OOB_STATS_TX_IDLEr, 0, 0, &rval)); 2043 soc_reg_field_set(unit, OOB_STATS_TX_IDLEr, &rval, 2044 IDLE_GAPf, ipg); 2045 BCM_IF_ERROR_RETURN 2046 (soc_reg32_set(unit, OOB_STATS_TX_IDLEr, 0, 0, rval)); 2047 2048 return BCM_E_NONE; 2049 } 2050 2051 /* 2052 * Function: 2053 * _bcm_td3_oob_stats_config_cfg_id_set 2054 * Purpose: 2055 * Set the inter packet gap for OOB STATS. 2056 * Parameters: 2057 * unit - (IN) StrataSwitch unit number 2058 * cfg_id - (IN) OOB Stats config ID. 2059 * Returns: 2060 * BCM_E_XXX 2061 */ 2062 STATIC int 2063 _bcm_td3_oob_stats_config_cfg_id_set(int unit, uint8 cfg_id) 2064 { 2065 uint32 rval = 0; 2066 2067 BCM_IF_ERROR_RETURN 2068 (soc_reg32_get(unit, STATS_INTF_CONFIG_IDr, 0, 0, &rval)); 2069 soc_reg_field_set(unit, STATS_INTF_CONFIG_IDr, &rval, 2070 CONFIG_IDf, cfg_id); 2071 BCM_IF_ERROR_RETURN 2072 (soc_reg32_set(unit, STATS_INTF_CONFIG_IDr, 0, 0, rval)); 2073 2074 return BCM_E_NONE; 2075 } 2076 2077 /* 2078 * Function: 2079 * _bcm_td3_oob_stats_config_flags_get 2080 * Purpose: 2081 * Get the enable control for OOB STATS. 2082 * Parameters: 2083 * unit - (IN) StrataSwitch unit number 2084 * config - (OUT) OOB Stats Configuration structure 2085 * Returns: 2086 * BCM_E_XXX 2087 */ 2088 STATIC int 2089 _bcm_td3_oob_stats_config_flags_get(int unit, 2090 bcm_oob_stats_config_t *config) 2091 { 2092 uint32 rval = 0; 2093 2094 config->flags = 0x0; 2095 2096 BCM_IF_ERROR_RETURN 2097 (soc_reg32_get(unit, STATS_INTF_REPORT_ENr, 0, 0, &rval)); 2098 2099 if (soc_reg_field_get(unit, STATS_INTF_REPORT_ENr, 2100 rval, TIMESTAMP_ENf)) { 2101 config->flags |= BCM_OOB_STATS_TIMESTAMP_EN; 2102 } 2103 2104 if (soc_reg_field_get(unit, STATS_INTF_REPORT_ENr, 2105 rval, INST_SERV_POOL_SIZE_ENf)) { 2106 config->flags |= BCM_OOB_STATS_POOL_EN; 2107 } 2108 2109 if (soc_reg_field_get(unit, STATS_INTF_REPORT_ENr, 2110 rval, INST_UC_QSIZE_ENf)) { 2111 config->flags |= BCM_OOB_STATS_QUEUE_EN; 2112 } 2113 2114 return BCM_E_NONE; 2115 } 2116 2117 /* 2118 * Function: 2119 * _bcm_td3_oob_stats_config_ipg_get 2120 * Purpose: 2121 * Get the inter packet gap for OOB STATS. 2122 * Parameters: 2123 * unit - (IN) StrataSwitch unit number 2124 * config - (OUT) OOB Stats Configuration structure 2125 * Returns: 2126 * BCM_E_XXX 2127 */ 2128 STATIC int 2129 _bcm_td3_oob_stats_config_ipg_get(int unit, 2130 bcm_oob_stats_config_t *config) 2131 { 2132 uint32 rval = 0; 2133 2134 config->inter_pkt_gap = 0x0; 2135 2136 BCM_IF_ERROR_RETURN 2137 (soc_reg32_get(unit, OOB_STATS_TX_IDLEr, 0, 0, &rval)); 2138 2139 config->inter_pkt_gap = soc_reg_field_get(unit, OOB_STATS_TX_IDLEr, 2140 rval, IDLE_GAPf); 2141 return BCM_E_NONE; 2142 } 2143 2144 /* 2145 * Function: 2146 * _bcm_td3_oob_stats_config_cfg_id_get 2147 * Purpose: 2148 * Get the Config ID for OOB STATS. 2149 * Parameters: 2150 * unit - (IN) StrataSwitch unit number 2151 * config - (OUT) OOB Stats Configuration structure 2152 * Returns: 2153 * BCM_E_XXX 2154 */ 2155 STATIC int 2156 _bcm_td3_oob_stats_config_cfg_id_get(int unit, 2157 bcm_oob_stats_config_t *config) 2158 { 2159 uint32 rval = 0; 2160 2161 config->config_id = 0x0; 2162 2163 BCM_IF_ERROR_RETURN 2164 (soc_reg32_get(unit, STATS_INTF_CONFIG_IDr, 0, 0, &rval)); 2165 2166 config->config_id = soc_reg_field_get(unit, STATS_INTF_CONFIG_IDr, 2167 rval, CONFIG_IDf); 2168 2169 return BCM_E_NONE; 2170 } 2171 2172 /* 2173 * Function: 2174 * _bcm_td3_oob_stats_pool_mapping_set 2175 * Purpose: 2176 * Set the service pool id at a given index in the memory 2177 * so that OOB Stats will be reported in the same order 2178 * as the service pool ids are programmed in the memory. 2179 * Parameters: 2180 * unit - (IN) StrataSwitch unit number 2181 * offset - (IN) Index at which service pool 2182 * in the service pool list needs to be added 2183 * spid - (IN) Specifies the service pool for which the corresponding pool 2184 * size should be reported. Mapping as follows: 2185 * 0-3: Report stats for ingress service pool ID 0-3 2186 * 4-7: Report stats for egress service pool ID 0-3 2187 * 15: End reporting round 2188 * Reset Value: 0xF 2189 * Returns: 2190 * BCM_E_XXX 2191 */ 2192 STATIC int 2193 _bcm_td3_oob_stats_pool_mapping_set(int unit, 2194 int offset, uint32 spid) 2195 { 2196 uint32 entry[SOC_MAX_MEM_WORDS]; 2197 2198 sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS); 2199 2200 /* Read the STATS_INTF_SERVPOOL_LIST memory into entry buffer */ 2201 SOC_IF_ERROR_RETURN 2202 (soc_mem_read(unit, STATS_INTF_SERVPOOL_LISTm, MEM_BLOCK_ALL, 2203 offset, entry)); 2204 2205 soc_mem_field32_set(unit, STATS_INTF_SERVPOOL_LISTm, entry, 2206 SPIDf, spid); 2207 2208 /* Write the entry buffer into STATS_INTF_SERVPOOL_LIST memory */ 2209 SOC_IF_ERROR_RETURN 2210 (soc_mem_write(unit, STATS_INTF_SERVPOOL_LISTm, MEM_BLOCK_ALL, 2211 offset, entry)); 2212 2213 return BCM_E_NONE; 2214 } 2215 2216 /* 2217 * Function: 2218 * _bcm_td3_oob_stats_pool_mapping_get 2219 * Purpose: 2220 * Get the service pool id at a given index in the memory. 2221 * OOB Stats will be reported in the same order 2222 * as the service pool ids are programmed in the memory. 2223 * Parameters: 2224 * unit - (IN) StrataSwitch unit number 2225 * offset - (IN) Index at which service pool 2226 * in the service pool list needs to be added 2227 * spid - (OUT) Specifies the service pool for which the corresponding pool 2228 * size should be reported. Mapping as follows: 2229 * 0-3: Report stats for ingress service pool ID 0-3 2230 * 4-7: Report stats for egress service pool ID 0-3 2231 * 15: End reporting round 2232 * Reset Value: 0xF 2233 * Returns: 2234 * BCM_E_XXX 2235 */ 2236 STATIC int 2237 _bcm_td3_oob_stats_pool_mapping_get(int unit, 2238 int offset, uint32 *spid) 2239 { 2240 uint32 entry[SOC_MAX_MEM_WORDS]; 2241 2242 sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS); 2243 2244 /* Read the STATS_INTF_SERVPOOL_LIST memory entry buffer */ 2245 SOC_IF_ERROR_RETURN 2246 (soc_mem_read(unit, STATS_INTF_SERVPOOL_LISTm, MEM_BLOCK_ALL, 2247 offset, entry)); 2248 2249 *spid = soc_mem_field32_get(unit, STATS_INTF_SERVPOOL_LISTm, entry, 2250 SPIDf); 2251 2252 return BCM_E_NONE; 2253 } 2254 2255 /* 2256 * Function: 2257 * _bcm_td3_oob_stats_queue_mapping_set 2258 * Purpose: 2259 * Set the queue id at a given index in the memory 2260 * so that OOB Stats will be reported in the same order 2261 * as the queue ids are programmed in the memory. 2262 * Parameters: 2263 * unit - (IN) StrataSwitch unit number 2264 * offset - (IN) Index at which Queue Id 2265 * in the queue list needs to be added 2266 * pipe_id - (IN) pipe ID 2267 * queue_id - (IN) logical queue ID 2268 * Returns: 2269 * BCM_E_XXX 2270 */ 2271 STATIC int 2272 _bcm_td3_oob_stats_queue_mapping_set(int unit, 2273 int offset, int pipe_id, int queue_id) 2274 { 2275 uint32 entry[SOC_MAX_MEM_WORDS]; 2276 2277 sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS); 2278 2279 /* Read the STATS_INTF_QUEUE_LIST memory entry buffer */ 2280 SOC_IF_ERROR_RETURN 2281 (soc_mem_read(unit, STATS_INTF_QUEUE_LISTm, MEM_BLOCK_ALL, 2282 offset, entry)); 2283 2284 soc_mem_field32_set(unit, STATS_INTF_QUEUE_LISTm, entry, 2285 PIPE_IDf, pipe_id); 2286 soc_mem_field32_set(unit, STATS_INTF_QUEUE_LISTm, entry, 2287 LOGICAL_QUEUE_IDf, queue_id); 2288 2289 /* Write the entry buffer into STATS_INTF_QUEUE_LIST memory */ 2290 SOC_IF_ERROR_RETURN 2291 (soc_mem_write(unit, STATS_INTF_QUEUE_LISTm, MEM_BLOCK_ALL, 2292 offset, entry)); 2293 2294 return BCM_E_NONE; 2295 } 2296 2297 /* 2298 * Function: 2299 * _bcm_td3_oob_stats_queue_mapping_get 2300 * Purpose: 2301 * Get the UC queue id at a given index in the memory. 2302 * OOB Stats will be reported in the same order 2303 * as the UC queue ids are programmed in the memory. 2304 * Parameters: 2305 * unit - (IN) StrataSwitch unit number 2306 * offset - (IN) Index at which Queue Id 2307 * in the queue list needs to be added 2308 * gport - (OUT) UC Queue gport 2309 * Returns: 2310 * BCM_E_XXX 2311 */ 2312 STATIC int 2313 _bcm_td3_oob_stats_queue_mapping_get(int unit, int offset, 2314 bcm_gport_t *gport) 2315 { 2316 int logical_queue_id = -1; 2317 int pipe_id = -1; 2318 bcm_cos_t cosq = -1; 2319 soc_info_t *si; 2320 int mmu_port = 1, phy_port = -1, logical_port = -1; 2321 uint32 entry[SOC_MAX_MEM_WORDS]; 2322 2323 sal_memset(entry, 0, sizeof(uint32)*SOC_MAX_MEM_WORDS); 2324 2325 /* Read the STATS_INTF_QUEUE_LIST memory entry buffer */ 2326 SOC_IF_ERROR_RETURN 2327 (soc_mem_read(unit, STATS_INTF_QUEUE_LISTm, MEM_BLOCK_ALL, 2328 offset, entry)); 2329 2330 logical_queue_id = soc_mem_field32_get(unit, STATS_INTF_QUEUE_LISTm, entry, 2331 LOGICAL_QUEUE_IDf); 2332 2333 pipe_id = soc_mem_field32_get(unit, STATS_INTF_QUEUE_LISTm, entry, 2334 PIPE_IDf); 2335 2336 if (logical_queue_id == _TD3_OOB_STATS_END_QUEUE_REPORT) { 2337 *gport = _TD3_OOB_STATS_END_QUEUE_REPORT; 2338 } else { 2339 si = &SOC_INFO(unit); 2340 2341 if (si == NULL) { 2342 return BCM_E_INTERNAL; 2343 } 2344 2345 cosq = logical_queue_id % _TD3_NUM_UCAST_QUEUE_PER_PORT; 2346 mmu_port = (pipe_id * (SOC_TD3_MMU_PORT_STRIDE + 1)) 2347 + (logical_queue_id / _TD3_NUM_UCAST_QUEUE_PER_PORT); 2348 2349 phy_port = si->port_m2p_mapping[mmu_port]; 2350 logical_port = si->port_p2l_mapping[phy_port]; 2351 BCM_IF_ERROR_RETURN 2352 (_bcm_td3_cosq_port_cos_resolve(unit, logical_port, cosq, 2353 _BCM_TD3_COSQ_INDEX_STYLE_UCAST_QUEUE, 2354 gport)); 2355 } 2356 2357 return BCM_E_NONE; 2358 } 2359 2360 /* 2361 * Function: 2362 * bcm_td3_oob_stats_config_set 2363 * Purpose: 2364 * Set the global configuration setting 2365 * for OOB STATS. 2366 * Parameters: 2367 * unit - (IN) StrataSwitch unit number 2368 * config - (IN) OOB Stats Configuration structure 2369 * Returns: 2370 * BCM_E_XXX 2371 */ 2372 int bcm_td3_oob_stats_config_set(int unit, 2373 bcm_oob_stats_config_t *config) 2374 { 2375 if (config == NULL) { 2376 return BCM_E_PARAM; 2377 } 2378 2379 if (config->config_id > _TD3_MAX_STATS_CONFIG_ID) { 2380 return BCM_E_PARAM; 2381 } 2382 2383 BCM_IF_ERROR_RETURN 2384 (_bcm_td3_oob_stats_config_flags_set(unit, config->flags)); 2385 2386 BCM_IF_ERROR_RETURN 2387 (_bcm_td3_oob_stats_config_ipg_set(unit, 2388 config->inter_pkt_gap)); 2389 2390 BCM_IF_ERROR_RETURN 2391 (_bcm_td3_oob_stats_config_cfg_id_set(unit, 2392 config->config_id)); 2393 2394 return BCM_E_NONE; 2395 } 2396 2397 /* 2398 * Function: 2399 * bcm_td3_oob_stats_config_get 2400 * Purpose: 2401 * Get the global configuration setting 2402 * for OOB STATS. 2403 * Parameters: 2404 * unit - (IN) StrataSwitch unit number 2405 * config - (OUT) OOB Stats Configuration structure 2406 * Returns: 2407 * BCM_E_XXX 2408 */ 2409 int bcm_td3_oob_stats_config_get(int unit, 2410 bcm_oob_stats_config_t *config) 2411 { 2412 if (config == NULL) { 2413 return BCM_E_PARAM; 2414 } 2415 2416 BCM_IF_ERROR_RETURN 2417 (_bcm_td3_oob_stats_config_flags_get(unit, config)); 2418 2419 BCM_IF_ERROR_RETURN 2420 (_bcm_td3_oob_stats_config_ipg_get(unit, config)); 2421 2422 BCM_IF_ERROR_RETURN 2423 (_bcm_td3_oob_stats_config_cfg_id_get(unit, config)); 2424 2425 return BCM_E_NONE; 2426 } 2427 2428 2429 /* 2430 * Function: 2431 * bcm_td3_oob_stats_pool_mapping_multi_set 2432 * Purpose: 2433 * Set the service pool id at a given index in the memory 2434 * so that OOB Stats will be reported in the same order 2435 * as the service pool ids are programmed in the memory. 2436 * Parameters: 2437 * unit - (IN) StrataSwitch unit number 2438 * array_count - (IN) Number of elements in array 2439 * offset_array - (IN) Indexes at which service pool 2440 * in the service pool list needs to be added 2441 * dir_array - (IN) Direction array 2442 * pool_array - (IN) Service Pool ID array 2443 * Returns: 2444 * BCM_E_XXX 2445 */ 2446 int bcm_td3_oob_stats_pool_mapping_multi_set(int unit, 2447 int array_count, int *offset_array, 2448 uint8 *dir_array, bcm_service_pool_id_t *pool_array) 2449 { 2450 int idx = 0; 2451 2452 if ((array_count < 0) || (array_count > _TD3_MAX_IDX_STATS_POOL_LIST)) { 2453 return BCM_E_PARAM; 2454 } 2455 2456 if ((offset_array == NULL) || 2457 (dir_array == NULL) || 2458 (pool_array == NULL)) { 2459 return BCM_E_PARAM; 2460 } 2461 2462 for (idx = 0; idx < array_count; idx++) { 2463 if ((offset_array[idx] < 0) && 2464 (offset_array[idx] >= _TD3_MAX_IDX_STATS_POOL_LIST)) { 2465 return BCM_E_PARAM; 2466 } 2467 } 2468 2469 for (idx = 0; idx < array_count; idx++) { 2470 BCM_IF_ERROR_RETURN 2471 (bcm_td3_oob_stats_pool_mapping_set(unit, offset_array[idx], 2472 dir_array[idx], 2473 pool_array[idx])); 2474 } 2475 2476 return BCM_E_NONE; 2477 } 2478 2479 /* 2480 * Function: 2481 * bcm_td3_oob_stats_pool_mapping_multi_get 2482 * Purpose: 2483 * Get the service pool id at a given index in the memory. 2484 * OOB Stats will be reported in the same order 2485 * as the service pool ids are programmed in the memory. 2486 * Parameters: 2487 * unit - (IN) StrataSwitch unit number 2488 * array_max - (IN) Number of elements in array 2489 * offset_array - (IN) Indexes at which service pool 2490 * in the service pool list needs to be added 2491 * dir_array - (OUT) Direction array 2492 * pool_array - (OUT) Service Pool ID array 2493 * array_count - (OUT) Number of elements returned in the array 2494 * Returns: 2495 * BCM_E_XXX 2496 */ 2497 int bcm_td3_oob_stats_pool_mapping_multi_get(int unit, 2498 int array_max, int *offset_array, uint8 *dir_array, 2499 bcm_service_pool_id_t *pool_array, int *array_count) 2500 { 2501 int idx = 0; 2502 2503 if ((offset_array == NULL) || 2504 (dir_array == NULL) || 2505 (pool_array == NULL) || 2506 (array_count == NULL)) { 2507 return BCM_E_PARAM; 2508 } 2509 2510 if ((array_max >= 0) && (array_max <= _TD3_MAX_IDX_STATS_POOL_LIST)) { 2511 *array_count = array_max; 2512 } else if (array_max > _TD3_MAX_IDX_STATS_POOL_LIST) { 2513 *array_count = _TD3_MAX_IDX_STATS_POOL_LIST; 2514 } else { 2515 return BCM_E_PARAM; 2516 } 2517 2518 for (idx = 0; idx < *array_count; idx++) { 2519 if ((offset_array[idx] < 0) && 2520 (offset_array[idx] >= _TD3_MAX_IDX_STATS_POOL_LIST)) { 2521 return BCM_E_PARAM; 2522 } 2523 } 2524 2525 for (idx = 0; idx < *array_count; idx++) { 2526 BCM_IF_ERROR_RETURN 2527 (bcm_td3_oob_stats_pool_mapping_get(unit, offset_array[idx], 2528 &dir_array[idx], 2529 &pool_array[idx])); 2530 2531 } 2532 2533 return BCM_E_NONE; 2534 } 2535 2536 /* 2537 * Function: 2538 * bcm_td3_oob_stats_pool_mapping_set 2539 * Purpose: 2540 * Set the service pool id at a given index in the memory 2541 * so that OOB Stats will be reported in the same order 2542 * as the service pool ids are programmed in the memory. 2543 * Parameters: 2544 * unit - (IN) StrataSwitch unit number 2545 * offset - (IN) Index at which service pool 2546 * in the service pool list needs to be added 2547 * dir - (IN) Direction 2548 * pool - (IN) Service Pool ID 2549 * Returns: 2550 * BCM_E_XXX 2551 */ 2552 int bcm_td3_oob_stats_pool_mapping_set(int unit, 2553 int offset, uint8 dir, 2554 bcm_service_pool_id_t pool) 2555 { 2556 uint32 spid = 0x0; 2557 2558 if (((pool < 0) || (pool >= _TD3_MMU_NUM_POOL)) && 2559 (pool != _TD3_OOB_STATS_END_POOL_REPORT)) { 2560 return BCM_E_PARAM; 2561 } 2562 2563 if ((offset < 0) || (offset >= _TD3_MAX_IDX_STATS_POOL_LIST)) { 2564 return BCM_E_PARAM; 2565 } 2566 2567 if ((dir != BCM_OOB_STATS_INGRESS) && 2568 (dir != BCM_OOB_STATS_EGRESS)) { 2569 if (pool != _TD3_OOB_STATS_END_POOL_REPORT) { 2570 return BCM_E_PARAM; 2571 } 2572 } 2573 2574 if ((dir == BCM_OOB_STATS_EGRESS) && 2575 (pool != _TD3_OOB_STATS_END_POOL_REPORT)) { 2576 /* Egress Service Pool spid value [4, ..., 7]*/ 2577 spid = pool | 0x4; 2578 } else { 2579 /* Ingress Service Pool spid value [0, ..., 3]*/ 2580 spid = pool; 2581 } 2582 2583 BCM_IF_ERROR_RETURN 2584 (_bcm_td3_oob_stats_pool_mapping_set(unit, offset, spid)); 2585 2586 return BCM_E_NONE; 2587 } 2588 2589 /* 2590 * Function: 2591 * bcm_td3_oob_stats_pool_mapping_get 2592 * Purpose: 2593 * Get the service pool id at a given index in the memory. 2594 * OOB Stats will be reported in the same order 2595 * as the service pool ids are programmed in the memory. 2596 * Parameters: 2597 * unit - (IN) StrataSwitch unit number 2598 * offset - (IN) Index at which service pool 2599 * in the service pool list needs to be added 2600 * dir - (OUT) Direction 2601 * pool - (OUT) Service Pool ID 2602 * Returns: 2603 * BCM_E_XXX 2604 */ 2605 int bcm_td3_oob_stats_pool_mapping_get(int unit, 2606 int offset, uint8 *dir, 2607 bcm_service_pool_id_t *pool) 2608 { 2609 uint32 spid = 0x0; 2610 2611 if ((offset < 0) || (offset >= _TD3_MAX_IDX_STATS_POOL_LIST)) { 2612 return BCM_E_PARAM; 2613 } 2614 2615 BCM_IF_ERROR_RETURN 2616 (_bcm_td3_oob_stats_pool_mapping_get(unit, offset, &spid)); 2617 2618 if (spid == _TD3_OOB_STATS_END_POOL_REPORT) { 2619 *pool = _TD3_OOB_STATS_END_POOL_REPORT; 2620 } else { 2621 /* Ingress Service Pool spid value [0, ..., 3]*/ 2622 /* Egress Service Pool spid value [4, ..., 7]*/ 2623 *pool = spid & 0x3; 2624 if (spid & 0x4) { 2625 *dir = BCM_OOB_STATS_EGRESS; 2626 } else { 2627 *dir = BCM_OOB_STATS_INGRESS; 2628 } 2629 } 2630 2631 return BCM_E_NONE; 2632 } 2633 2634 /* 2635 * Function: 2636 * bcm_td3_oob_stats_queue_mapping_multi_set 2637 * Purpose: 2638 * Set the queue id at a given index in the memory 2639 * so that OOB Stats will be reported in the same order 2640 * as the service pool ids are programmed in the memory. 2641 * Parameters: 2642 * unit - (IN) StrataSwitch unit number 2643 * array_count - (IN) Number of elements in array 2644 * offset_array - (IN) Indexes at which Queue Id 2645 * in the queue list needs to be added 2646 * gport_array - (IN) Queue gport array 2647 * Returns: 2648 * BCM_E_XXX 2649 */ 2650 int bcm_td3_oob_stats_queue_mapping_multi_set(int unit, 2651 int array_count, int *offset_array, 2652 bcm_gport_t *gport_array) 2653 { 2654 int idx = 0; 2655 2656 if ((array_count < 0) || (array_count > _TD3_MAX_IDX_STATS_QUEUE_LIST)) { 2657 return BCM_E_PARAM; 2658 } 2659 2660 if ((offset_array == NULL) || 2661 (gport_array == NULL)) { 2662 return BCM_E_PARAM; 2663 } 2664 2665 for (idx = 0; idx < array_count; idx++) { 2666 if ((offset_array[idx] < 0) && 2667 (offset_array[idx] >= _TD3_MAX_IDX_STATS_QUEUE_LIST)) { 2668 return BCM_E_PARAM; 2669 } 2670 } 2671 2672 for (idx = 0; idx < array_count; idx++) { 2673 BCM_IF_ERROR_RETURN 2674 (bcm_td3_oob_stats_queue_mapping_set(unit, offset_array[idx], 2675 gport_array[idx])); 2676 } 2677 2678 return BCM_E_NONE; 2679 } 2680 2681 /* 2682 * Function: 2683 * bcm_td3_oob_stats_queue_mapping_multi_get 2684 * Purpose: 2685 * Get the queue id at a given index in the memory. 2686 * OOB Stats will be reported in the same order 2687 * as the queue ids are programmed in the memory. 2688 * Parameters: 2689 * unit - (IN) StrataSwitch unit number 2690 * array_max - (IN) Maximum number of elements in array 2691 * offset_array - (IN) Indexes at which Queue Id 2692 * in the queue list needs to be added 2693 * gport_array - (OUT) Queue gport array 2694 * array_count - (OUT) Number of elements in array 2695 * Returns: 2696 * BCM_E_XXX 2697 */ 2698 int bcm_td3_oob_stats_queue_mapping_multi_get(int unit, 2699 int array_max, int *offset_array, 2700 bcm_gport_t *gport_array, int *array_count) 2701 { 2702 int idx = 0; 2703 2704 if ((offset_array == NULL) || 2705 (gport_array == NULL) || 2706 (array_count == NULL)) { 2707 return BCM_E_PARAM; 2708 } 2709 2710 if ((array_max >= 0) && (array_max <= _TD3_MAX_IDX_STATS_QUEUE_LIST)) { 2711 *array_count = array_max; 2712 } else if (array_max > _TD3_MAX_IDX_STATS_QUEUE_LIST) { 2713 *array_count = _TD3_MAX_IDX_STATS_QUEUE_LIST; 2714 } else { 2715 return BCM_E_PARAM; 2716 } 2717 2718 for (idx = 0; idx < *array_count; idx++) { 2719 BCM_IF_ERROR_RETURN 2720 (bcm_td3_oob_stats_queue_mapping_get(unit, offset_array[idx], 2721 &gport_array[idx])); 2722 } 2723 2724 return BCM_E_NONE; 2725 } 2726 2727 2728 /* 2729 * Function: 2730 * bcm_td3_oob_stats_queue_mapping_set 2731 * Purpose: 2732 * Set the queue id at a given index in the memory 2733 * so that OOB Stats will be reported in the same order 2734 * as the service pool ids are programmed in the memory. 2735 * Parameters: 2736 * unit - (IN) StrataSwitch unit number 2737 * offset - (IN) Index at which Queue Id 2738 * in the queue list needs to be added 2739 * gport - (IN) Queue gport 2740 * Returns: 2741 * BCM_E_XXX 2742 */ 2743 int bcm_td3_oob_stats_queue_mapping_set(int unit, 2744 int offset, bcm_gport_t gport) 2745 { 2746 bcm_port_t local_port = -1; 2747 int logical_queue_id = -1; 2748 int hw_index = -1; 2749 int mmu_port, phy_port; 2750 soc_info_t *si; 2751 int pipe = -1; 2752 2753 if ((offset < 0) || (offset >= _TD3_MAX_IDX_STATS_QUEUE_LIST)) { 2754 return BCM_E_PARAM; 2755 } 2756 2757 if (gport == _TD3_OOB_STATS_END_QUEUE_REPORT) { 2758 logical_queue_id = _TD3_OOB_STATS_END_QUEUE_REPORT; 2759 } else { 2760 si = &SOC_INFO(unit); 2761 2762 if (si == NULL) { 2763 return BCM_E_INTERNAL; 2764 } 2765 2766 BCM_IF_ERROR_RETURN 2767 (_bcm_td3_cosq_index_resolve(unit, gport, -1, 2768 _BCM_TD3_COSQ_INDEX_STYLE_UCAST_QUEUE, 2769 &local_port, &hw_index, NULL)); 2770 2771 phy_port = si->port_l2p_mapping[local_port]; 2772 mmu_port = si->port_p2m_mapping[phy_port]; 2773 2774 pipe = si->port_pipe[local_port]; 2775 logical_queue_id = ((mmu_port % (SOC_TD3_MMU_PORT_STRIDE + 1)) * 2776 _TD3_NUM_UCAST_QUEUE_PER_PORT) + 2777 (hw_index % _TD3_NUM_UCAST_QUEUE_PER_PORT); 2778 } 2779 2780 BCM_IF_ERROR_RETURN 2781 (_bcm_td3_oob_stats_queue_mapping_set(unit, offset, pipe, 2782 logical_queue_id)); 2783 2784 return BCM_E_NONE; 2785 } 2786 2787 /* 2788 * Function: 2789 * bcm_td3_oob_stats_queue_mapping_get 2790 * Purpose: 2791 * Get the queue id at a given index in the memory. 2792 * OOB Stats will be reported in the same order 2793 * as the queue ids are programmed in the memory. 2794 * Parameters: 2795 * unit - (IN) StrataSwitch unit number 2796 * offset - (IN) Index at which Queue Id 2797 * in the queue list needs to be added 2798 * gport - (OUT) Queue gport 2799 * Returns: 2800 * BCM_E_XXX 2801 */ 2802 int bcm_td3_oob_stats_queue_mapping_get(int unit, 2803 int offset, bcm_gport_t *gport) 2804 { 2805 if ((offset < 0) || (offset >= _TD3_MAX_IDX_STATS_QUEUE_LIST)) { 2806 return BCM_E_PARAM; 2807 } 2808 2809 if (gport == NULL) { 2810 return BCM_E_PARAM; 2811 } 2812 2813 BCM_IF_ERROR_RETURN 2814 (_bcm_td3_oob_stats_queue_mapping_get(unit, offset, gport)); 2815 2816 return BCM_E_NONE; 2817 } 2818 2819 #endif /* BCM_TRIDENT3_SUPPORT */