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