port.c (60996B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: port.c 8 * Purpose: Port driver. 9 */ 10 11 #include <shared/bsl.h> 12 13 #include <soc/defs.h> 14 15 #if defined(BCM_APACHE_SUPPORT) 16 #include <soc/drv.h> 17 #include <soc/types.h> 18 #include <soc/apache.h> 19 #include <bcm_int/esw_dispatch.h> 20 #include <bcm_int/esw/port.h> 21 #include <bcm_int/esw/stack.h> 22 #include <bcm_int/esw/portctrl.h> 23 #include <bcm_int/esw/xgs5.h> 24 #include <bcm_int/esw/trident2.h> 25 #include <bcm_int/esw/trident2plus.h> 26 #include <bcm_int/esw/apache.h> 27 #include <bcm/error.h> 28 #include <bcm/port.h> 29 30 #define AP_FLEX_MAX_NUM_PORTS 76 31 32 #define IS_AP_HSP_PORT(u,p) \ 33 ((_soc_apache_port_sched_type_get((u),(p)) == SOC_APACHE_SCHED_HSP) ? 1 : 0) 34 35 /* 36 * Function: 37 * _bcm_apache_port_mac_get 38 * Description: 39 * Get EGR_PORT/LPORT table mac address 40 * Parameters: 41 * unit - (IN) BCM device number 42 * port - (IN) Port number if valid. 43 * oui - (IN) Indicates mac field is OUI/Non-OUI 44 * mac - (OUT) OUI/Non-OUI part of MAC-ADDRESS 45 * Return Value: 46 * BCM_E_XXX 47 */ 48 int 49 _bcm_apache_port_mac_get(int unit, bcm_port_t port, int oui, uint32* mac) 50 { 51 egr_port_entry_t egr_port_entry; 52 bcm_module_t modid; 53 bcm_port_t local_port; 54 bcm_trunk_t tgid; 55 int id; 56 int is_local = FALSE; 57 soc_field_t field; 58 59 if (oui) { 60 field = MAC_ADDRESS_UPPERf; 61 } else { 62 field = MAC_ADDRESS_LOWERf; 63 } 64 65 if (BCM_GPORT_IS_SET(port)) { 66 67 /* GPORT Validations */ 68 BCM_IF_ERROR_RETURN( 69 _bcm_esw_gport_resolve( 70 unit, port, &modid, &local_port, &tgid, &id)); 71 72 if (-1 == local_port) { 73 return BCM_E_PARAM; 74 } 75 76 BCM_IF_ERROR_RETURN( 77 _bcm_esw_modid_is_local(unit, modid, &is_local)); 78 if (!is_local) { 79 return BCM_E_PARAM; 80 } 81 82 /* For subports get from EGR_LPORT_PROFILE table */ 83 if (BCM_GPORT_IS_SUBPORT_PORT(port)) { 84 return bcm_esw_port_egr_lport_field_get(unit, 85 port, 86 EGR_LPORT_PROFILEm, 87 field, 88 mac); 89 } 90 91 92 } else { 93 BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, port, &local_port)); 94 } 95 96 SOC_IF_ERROR_RETURN( 97 READ_EGR_PORTm(unit, MEM_BLOCK_ANY, local_port, &egr_port_entry)); 98 99 *mac = soc_EGR_PORTm_field32_get(unit, &egr_port_entry, field); 100 101 return BCM_E_NONE; 102 } 103 104 /* 105 * Function: 106 * _bcm_apache_port_mac_set 107 * Description: 108 * Configure EGR_PORT/LPORT table mac address 109 * Parameters: 110 * unit - (IN) BCM device number 111 * port - (IN) Port number if valid. 112 * oui - (IN) Indicates mac field is OUI/Non-OUI 113 * mac - (IN) OUI/Non-OUI part of MAC-ADDRESS 114 * Return Value: 115 * BCM_E_XXX 116 */ 117 int 118 _bcm_apache_port_mac_set(int unit, bcm_port_t port, int oui, uint32 mac) 119 { 120 egr_port_entry_t egr_port_entry; 121 bcm_module_t modid; 122 bcm_port_t local_port; 123 bcm_trunk_t tgid; 124 int id; 125 int is_local = FALSE; 126 soc_field_t field; 127 128 if (oui) { 129 field = MAC_ADDRESS_UPPERf; 130 } else { 131 field = MAC_ADDRESS_LOWERf; 132 } 133 134 if (BCM_GPORT_IS_SET(port)) { 135 136 /* GPORT Validations */ 137 BCM_IF_ERROR_RETURN( 138 _bcm_esw_gport_resolve( 139 unit, port, &modid, &local_port, &tgid, &id)); 140 141 if (-1 == local_port) { 142 return BCM_E_PARAM; 143 } 144 145 BCM_IF_ERROR_RETURN( 146 _bcm_esw_modid_is_local(unit, modid, &is_local)); 147 if (!is_local) { 148 return BCM_E_PARAM; 149 } 150 151 /* For subports set the EGR_LPORT_PROFILE table */ 152 if (BCM_GPORT_IS_SUBPORT_PORT(port)) { 153 return bcm_esw_port_egr_lport_field_set(unit, 154 port, 155 EGR_LPORT_PROFILEm, 156 field, 157 mac); 158 } 159 160 } else { 161 BCM_IF_ERROR_RETURN(_bcm_esw_port_gport_validate(unit, port, &local_port)); 162 } 163 164 165 SOC_IF_ERROR_RETURN( 166 READ_EGR_PORTm(unit, MEM_BLOCK_ANY, port, &egr_port_entry)); 167 168 soc_EGR_PORTm_field_set(unit, &egr_port_entry, field, &mac); 169 170 SOC_IF_ERROR_RETURN( 171 WRITE_EGR_PORTm(unit, MEM_BLOCK_ALL, port, &egr_port_entry)); 172 173 return BCM_E_NONE; 174 } 175 176 177 178 /* 179 * FlexPort Operations Changes 180 * 181 * Flags to be used to determine the type of operations required 182 * when the FlexPort API multi_set() is called. 183 * 184 * OP_NONE - No changes. 185 * OP_PMAP - Change in port mapping. It requires FlexPort sequence. 186 * OP_LANES - Change in lanes. It requires FlexPort sequence. 187 * OP_SPEED - Change in speed. This is covered in a FlexPort sequence. 188 * A change in speed may require a FlexPort sequence. 189 * If it is not required, then calling the 'speed' set 190 * function is sufficient. 191 * OP_ENCAP - Change in encap mode. It is NOT covered in a FlexPort 192 * sequence, so an explicit call must be made to change 193 * the encap mode. 194 * OP_ALL - All the above. It requires FlexPort sequence. 195 */ 196 #define BCM_AP_PORT_RESOURCE_OP_NONE 0 197 #define BCM_AP_PORT_RESOURCE_OP_PMAP (1 << 0) 198 #define BCM_AP_PORT_RESOURCE_OP_LANES (1 << 1) 199 #define BCM_AP_PORT_RESOURCE_OP_SPEED (1 << 2) 200 #define BCM_AP_PORT_RESOURCE_OP_ENCAP (1 << 3) 201 #define BCM_AP_PORT_RESOURCE_OP_ALL \ 202 (BCM_AP_PORT_RESOURCE_OP_PMAP | \ 203 BCM_AP_PORT_RESOURCE_OP_LANES | \ 204 BCM_AP_PORT_RESOURCE_OP_SPEED | \ 205 BCM_AP_PORT_RESOURCE_OP_ENCAP) 206 207 /* 208 * Internal BCM Port Resource Configuration 209 */ 210 typedef struct bcm_apache_port_resource_s { 211 uint32 flags; /* SOC_PORT_RESOURCE_XXX */ 212 bcm_gport_t port; /* Local logical port number to connect to 213 the given physical port */ 214 int physical_port; /* Local physical port, -1 if the logical to 215 physical mapping is to be deleted */ 216 int speed; /* Initial speed after FlexPort operation */ 217 int lanes; /* Number of PHY lanes for this physical port */ 218 bcm_port_encap_t encap; /* Encapsulation mode for port */ 219 } bcm_apache_port_resource_t; 220 221 222 223 /* 224 * Forward static function declaration 225 */ 226 STATIC int 227 _bcm_apache_port_resource_multi_set(int unit, 228 int nport, bcm_port_resource_t *resource); 229 STATIC int 230 _bcm_apache_port_resource_speed_set(int unit, bcm_port_t port, int speed); 231 232 233 /* 234 * Device Specific HW Tables 235 */ 236 237 /* Egr port table */ 238 static bcmi_xgs5_port_redirection_egr_port_table_t 239 bcmi_apache_port_redirection_egr_port_table = { 240 /* mem */ EGR_PORTm, 241 /* dest_type */ ER_REDIR_DEST_TYPEf, 242 /* dest_value */ ER_REDIR_DESTINATIONf, 243 /* drop_original */ ER_REDIR_DROP_ORIGINALf, 244 /* pkt_priority */ ER_REDIR_NEW_PRIf, 245 /* pkt_change_priority */ ER_REDIR_CHANGE_PRIf, 246 /* pkt_color */ ER_REDIR_NEW_COLORf, 247 /* pkt_change_color */ ER_REDIR_CHANGE_COLORf, 248 /* strength */ ER_REDIR_STRENGTHf, 249 /* buffer_priority */ ER_REDIR_RDB_PRIORITYf, 250 /* action */ ER_REDIR_ACTIONf, 251 /* redir_pkt_source */ ER_REDIR_SOURCEf, 252 /* redir_pkt_truncate */ ER_REDIR_FIRST_CELL_ONLYf 253 }; 254 255 /* HW Definitions */ 256 static bcmi_xgs5_port_hw_defs_t bcmi_apache_port_hw_defs; 257 258 259 /* 260 * Function Vector 261 */ 262 static bcm_esw_port_drv_t bcm_apache_port_drv = { 263 /* fn_drv_init */ bcmi_apache_port_fn_drv_init, 264 /* resource_set */ bcmi_xgs5_port_resource_set, 265 /* resource_get */ bcmi_xgs5_port_resource_get, 266 /* resource_multi_set */ _bcm_apache_port_resource_multi_set, 267 /* resource_speed_set */ _bcm_apache_port_resource_speed_set, 268 /* resource_traverse */ bcmi_xgs5_port_resource_traverse, 269 /* port_redirect_set */ bcmi_xgs5_port_redirect_config_set, 270 /* port_redirect_get */ bcmi_xgs5_port_redirect_config_get, 271 /* port_enable_set */ NULL, 272 /* encap_speed_check */ bcmi_xgs5_port_encap_speed_check, 273 /* force_lb_set */ NULL, 274 /* force_lb_check */ NULL, 275 /* resource_status_update */ bcmi_xgs5_port_resource_status_update 276 }; 277 278 279 /* 280 * Function: 281 * bcmi_apache_port_fn_drv_init 282 * Purpose: 283 * Initialize the Port function driver. 284 * Parameters: 285 * unit - (IN) Unit number. 286 * Returns: 287 * BCM_E_xxx 288 * Notes: 289 */ 290 int 291 bcmi_apache_port_fn_drv_init(int unit) 292 { 293 /* HW Definition Tables */ 294 sal_memset(&bcmi_apache_port_hw_defs, 0, 295 sizeof(bcmi_apache_port_hw_defs)); 296 bcmi_apache_port_hw_defs.egr_port = 297 &bcmi_apache_port_redirection_egr_port_table; 298 299 /* Initialize Common XGS5 Port module */ 300 BCM_IF_ERROR_RETURN 301 (bcmi_xgs5_port_fn_drv_init(unit, &bcm_apache_port_drv, NULL, 302 &bcmi_apache_port_hw_defs)); 303 304 return BCM_E_NONE; 305 } 306 307 308 /* 309 * Function: 310 * _bcm_apache_port_attach 311 * Purpose: 312 * Attach given port to the BCM layer and initialize it 313 * to its default state. 314 * Parameters: 315 * unit - (IN) Unit number. 316 * port - (IN) Logical port, BCM format. 317 * Returns: 318 * BCM_E_XXX 319 * Note: 320 * - Assumes port is a valid BCM logical port. 321 * - Assumes function is called when a new port is added into the system, 322 * so it is not called during WarmBoot. 323 * - Assumes BCM PORT module initialization routine has 324 * been called. 325 * - Assumes this is NOT called during Warmboot. 326 */ 327 STATIC int 328 _bcm_apache_port_attach(int unit, bcm_port_t port) 329 { 330 int rv = BCM_E_NONE; 331 332 BCM_IF_ERROR_RETURN(bcm_esw_td2p_flexport_port_attach(unit, port)); 333 334 rv = bcm_ap_cosq_default_llfc_profile_attach(unit, port); 335 if (BCM_FAILURE(rv)) { 336 LOG_ERROR(BSL_LS_BCM_PORT, 337 (BSL_META_U(unit, 338 "Unable to add default entries for PRIO2COS_PROFILE" 339 "register profile unit=%d port=%d rv=%d\n"), 340 unit, port, rv)); 341 return rv; 342 } 343 344 BCM_IF_ERROR_RETURN(bcm_ap_cosq_flex_port_update( unit , port , TRUE)); 345 346 /* Setup CosQ hierarchy */ 347 if (!IS_AP_HSP_PORT(unit, port)) { 348 rv = _bcm_ap_port_lls_config_set(unit, port); 349 if (BCM_FAILURE(rv)) { 350 LOG_ERROR(BSL_LS_BCM_PORT, 351 (BSL_META_U(unit, 352 "Error: Unable to setup LLS sched tree " 353 "unit=%d port=%d rv=%d\n"), 354 unit, port, rv)); 355 return rv; 356 } 357 if (soc_ap_is_skip_default_lls_creation(unit)) { 358 SOC_IF_ERROR_RETURN( 359 soc_apache_port_mmu_tx_enable_set(unit, port, 0)); 360 } 361 362 363 } else { 364 rv = soc_apache_cosq_enable_hsp_sched(unit,port); 365 if (BCM_FAILURE(rv)) { 366 LOG_ERROR(BSL_LS_BCM_PORT, 367 (BSL_META_U(unit, 368 "Error: Unable to setup HSP sched tree " 369 "unit=%d port=%d rv=%d\n"), 370 unit, port, rv)); 371 return rv; 372 } 373 374 rv = _bcm_ap_port_hsp_config_set(unit, port); 375 if (BCM_FAILURE(rv)) { 376 LOG_ERROR(BSL_LS_BCM_PORT, 377 (BSL_META_U(unit, 378 "Error: Unable config HSP node " 379 "unit=%d port=%d rv=%d\n"), 380 unit, port, rv)); 381 return rv; 382 } 383 if (soc_ap_is_skip_default_lls_creation(unit)) { 384 SOC_IF_ERROR_RETURN( 385 soc_apache_port_mmu_tx_enable_set(unit, port, 1)); 386 } 387 388 } 389 390 rv = soc_apache_mmu_config_init(unit, 0, port); 391 BCM_IF_ERROR_RETURN(rv); 392 393 394 return BCM_E_NONE; 395 } 396 397 398 /* 399 * Function: 400 * _bcm_apache_port_detach 401 * Purpose: 402 * Detach given port from the BCM layer and clear any data 403 * that is normally configured when a port is initialized. 404 * Parameters: 405 * unit - (IN) Unit number. 406 * port - (IN) Logical port, BCM format. 407 * Returns: 408 * BCM_E_XXX 409 * Note: 410 * - Assumes port is a valid BCM logical port. 411 * - Assumes this is NOT called during Warmboot. 412 */ 413 STATIC int 414 _bcm_apache_port_detach(int unit, bcm_port_t port) 415 { 416 bcm_gport_t gport; 417 int rv = BCM_E_NONE; 418 419 rv = bcm_esw_td2p_flexport_port_detach(unit, port); 420 if (BCM_FAILURE(rv)) { 421 LOG_ERROR(BSL_LS_BCM_PORT, 422 (BSL_META_U(unit, 423 "Error: Unable to detach BCM port " 424 "unit=%d port=%d rv=%d\n"), 425 unit, port, rv)); 426 return rv; 427 } 428 429 rv = bcm_ap_cosq_llfc_profile_detach(unit, port); 430 if (BCM_FAILURE(rv)) { 431 LOG_ERROR(BSL_LS_BCM_PORT, 432 (BSL_META_U(unit, 433 "Unable to delete default entries for PRIO2COS_PROFILE" 434 "register profile unit=%d port=%d rv=%d\n"), 435 unit, port, rv)); 436 return rv; 437 } 438 439 if (IS_AP_HSP_PORT(unit, port)) { 440 /* Clear HSP port bitmap */ 441 SOC_IF_ERROR_RETURN(soc_apache_cosq_disable_hsp_sched(unit, port)); 442 } 443 /* Delete CoS queue tree */ 444 rv = bcm_esw_port_gport_get(unit, port, &gport); 445 if (BCM_FAILURE(rv)) { 446 LOG_ERROR(BSL_LS_BCM_PORT, 447 (BSL_META_U(unit, 448 "Error: Unable to retrieve gport " 449 "unit=%d port=%d rv=%d\n"), 450 unit, port, rv)); 451 return rv; 452 } 453 454 rv = bcm_ap_cosq_gport_delete(unit, gport); 455 if (BCM_FAILURE(rv)) { 456 LOG_ERROR(BSL_LS_BCM_PORT, 457 (BSL_META_U(unit, 458 "Error: Unable to destroy LLS tree " 459 "unit=%d port=%d rv=%d\n"), 460 unit, port, rv)); 461 return rv; 462 } 463 BCM_IF_ERROR_RETURN( 464 bcm_ap_cosq_flex_port_update( unit , port , FALSE)); 465 466 return BCM_E_NONE; 467 } 468 469 470 /* 471 * Function: 472 * bcm_apache_flexport_pbmp_update 473 * Description: 474 * Returns bitmap of max valid ports 475 * Parameters: 476 * unit - (IN) BCM device number 477 * pbmp - (IN/OUT) port bit map 478 */ 479 480 int 481 bcm_apache_flexport_pbmp_update(int unit, bcm_pbmp_t *pbmp) 482 { 483 bcm_port_t port; 484 485 if (NULL == pbmp) { 486 return BCM_E_PARAM; 487 } 488 for (port = 0; port < AP_FLEX_MAX_NUM_PORTS; port++) { 489 BCM_PBMP_PORT_ADD(*pbmp, port); 490 } 491 return BCM_E_NONE; 492 } 493 494 495 496 /* 497 * Function: 498 * _bcm_apache_port_resource_attach 499 * Purpose: 500 * Attach ports to the BCM layer and initialize them 501 * to the default state. 502 * 503 * Parameters: 504 * unit - (IN) Unit number. 505 * nport - (IN) Number of elements in array resource. 506 * resource - (IN) Port Resource FlexPort configuration. 507 * Returns: 508 * BCM_E_XXX 509 * Notes: 510 * - Assumes caller have detached any ports that will be attached 511 * in this routine. 512 * - Assumes this is NOT called during Warmboot. 513 * - Set current MY_MODID for all newly attached ports. 514 */ 515 STATIC int 516 _bcm_apache_port_resource_attach(int unit, 517 int nport, 518 bcm_apache_port_resource_t *resource) 519 { 520 int rv = BCM_E_NONE; 521 bcm_apache_port_resource_t *pr; 522 int i; 523 int my_modid; 524 525 LOG_VERBOSE(BSL_LS_BCM_PORT, 526 (BSL_META_U(unit, 527 "--- BCM Attach ---\n"))); 528 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 529 530 531 for (i = 0, pr = &resource[0]; i < nport; i++, pr++) { 532 if (pr->flags & SOC_PORT_RESOURCE_ATTACH) { 533 rv = _bcm_apache_port_attach(unit, pr->port); 534 if (BCM_FAILURE(rv)) { 535 LOG_ERROR(BSL_LS_BCM_PORT, 536 (BSL_META_U(unit, 537 "Error: Unable to attach BCM port " 538 "unit=%d port=%d rv=%d\n"), 539 unit, pr->port, rv)); 540 return rv; 541 } 542 } 543 } 544 545 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_set(unit, my_modid)); 546 547 return BCM_E_NONE; 548 } 549 550 551 /* 552 * Function: 553 * _bcm_apache_port_resource_detach 554 * Purpose: 555 * Detach ports from the BCM layer. 556 * 557 * It clears any HW or SW state that was programmed 558 * by the SDK initialization routines. It does NOT clear 559 * references to logical ports that have been programmed by the 560 * application. Applications are responsible for doing that. 561 * 562 * Parameters: 563 * unit - (IN) Unit number. 564 * nport - (IN) Number of elements in array resource. 565 * resource - (IN) Port Resource FlexPort configuration. 566 * Returns: 567 * BCM_E_XXX 568 * Notes: 569 * - Assumes this is NOT called during Warmboot. 570 */ 571 STATIC int 572 _bcm_apache_port_resource_detach(int unit, 573 int nport, 574 bcm_apache_port_resource_t *resource) 575 { 576 int rv = BCM_E_NONE; 577 bcm_apache_port_resource_t *pr; 578 int i; 579 580 LOG_VERBOSE(BSL_LS_BCM_PORT, 581 (BSL_META_U(unit, 582 "--- BCM Detach ---\n"))); 583 584 for (i = 0, pr = &resource[0]; i < nport; i++, pr++) { 585 if (pr->flags & SOC_PORT_RESOURCE_DETACH) { 586 rv = _bcm_apache_port_detach(unit, pr->port); 587 if (BCM_FAILURE(rv)) { 588 LOG_ERROR(BSL_LS_BCM_PORT, 589 (BSL_META_U(unit, 590 "Error: Unable to detach BCM port " 591 "unit=%d port=%d rv=%d\n"), 592 unit, pr->port, rv)); 593 return rv; 594 } 595 } 596 } 597 598 return BCM_E_NONE; 599 } 600 601 602 /* 603 * Function: 604 * _bcm_apache_port_resource_resolve 605 * Purpose: 606 * Convert logical port number GPORT to BCM local port format and 607 * validate port numbers: 608 * - Logical and physical port numbers are within the valid range. 609 * - Ports must not be CPU or Loopback ports. 610 * Parameters: 611 * unit - (IN) Unit number. 612 * nport - (IN) Number of elements in array resource. 613 * resource - (IN/OUT) Port resource configuration array. 614 * Returns: 615 * BCM_E_XXX 616 * Note: 617 * - Assumes caller has lock. 618 * - Resource is not NULL. 619 */ 620 STATIC int 621 _bcm_apache_port_resource_resolve(int unit, 622 int nport, 623 bcm_apache_port_resource_t *resource) 624 { 625 int i; 626 bcm_apache_port_resource_t *pr; 627 soc_info_t *si = &SOC_INFO(unit); 628 629 for (i = 0, pr = &resource[0]; i < nport; i++, pr++) { 630 631 /* Check that logical port number is addressable and convert */ 632 BCM_IF_ERROR_RETURN 633 (bcmi_xgs5_port_addressable_local_get(unit, 634 pr->port, 635 &pr->port)); 636 637 /* 638 * Check that logical port number is valid for Apache 639 * (above check is generic) 640 */ 641 SOC_IF_ERROR_RETURN 642 (soc_ap_port_addressable(unit, pr->port)); 643 644 /* Check that physical port is within the valid range */ 645 if (pr->physical_port != -1) { 646 SOC_IF_ERROR_RETURN 647 (soc_ap_phy_port_addressable(unit, pr->physical_port)); 648 } 649 650 /* Check that ports, logical and physical, are not a management port */ 651 if ((si->port_l2p_mapping[pr->port] == AP_PHY_PORT_CPU) || 652 (si->port_l2p_mapping[pr->port] == AP_PHY_PORT_LB) || 653 (pr->physical_port == AP_PHY_PORT_CPU) || 654 (pr->physical_port == AP_PHY_PORT_LB)) { 655 LOG_ERROR(BSL_LS_BCM_PORT, 656 (BSL_META_U(unit, 657 "Port cannot be CPU, LB, or RDB port " 658 "unit=%d port=%d\n"), 659 unit, pr->port)); 660 return BCM_E_PORT; 661 } 662 } 663 664 return BCM_E_NONE; 665 } 666 667 668 /* 669 * Function: 670 * _bcm_apache_port_resource_input_validate 671 * Purpose: 672 * Validate function input requirements. 673 * 674 * This routine checks for function semantics and guidelines 675 * from the API perspective: 676 * - Check the order of elements in array, 'delete' operations must 677 * be placed first in array. 678 * - Ports must not be CPU or Loopback ports. 679 * - Ports must be disabled. 680 * - Ports linkscan mode must be NONE. 681 * Parameters: 682 * unit - (IN) Unit number. 683 * nport - (IN) Number of elements in array resource. 684 * resource - (IN/OUT) Port resource configuration array. 685 * Returns: 686 * BCM_E_XXX 687 * Note: 688 * - Assumes caller has lock. 689 * - Resource is not NULL. 690 * - Assumes port values has been validated. 691 */ 692 STATIC int 693 _bcm_apache_port_resource_input_validate(int unit, 694 int nport, 695 bcm_apache_port_resource_t *resource) 696 { 697 int i; 698 bcm_apache_port_resource_t *pr; 699 int delete = 1; 700 int enable; 701 soc_info_t *si = &SOC_INFO(unit); 702 703 /* Check array order and port state disable */ 704 for (i = 0, pr = &resource[0]; i < nport; i++, pr++) { 705 706 /* Skip check for speed change */ 707 if (pr->flags & SOC_PORT_RESOURCE_SPEED) { 708 continue; 709 } 710 711 /* Check that delete operations are first */ 712 if (pr->physical_port != -1) { /* First non-delete found */ 713 delete = 0; 714 } else if ((pr->physical_port == -1) && !delete) { 715 LOG_ERROR(BSL_LS_BCM_PORT, 716 (BSL_META_U(unit, 717 "Delete operations must be " 718 "first in array\n"))); 719 return BCM_E_CONFIG; 720 } 721 722 if ((pr->encap != BCM_PORT_ENCAP_IEEE) && 723 (pr->encap != BCM_PORT_ENCAP_HIGIG2)) { 724 LOG_ERROR(BSL_LS_BCM_PORT, 725 (BSL_META_U(unit, 726 "Encap modes can only be IEEE or HIGIG2 " 727 "unit=%d port=%d\n"), 728 unit, pr->port)); 729 return BCM_E_CONFIG; 730 } 731 732 /* Skip ports that are not currently defined */ 733 if (si->port_l2p_mapping[pr->port] == -1) { 734 continue; 735 } 736 737 /* Check that ports are disabled */ 738 BCM_IF_ERROR_RETURN 739 (bcm_esw_port_enable_get(unit, pr->port, &enable)); 740 if (enable) { 741 LOG_ERROR(BSL_LS_BCM_PORT, 742 (BSL_META_U(unit, 743 "Port %d needs to be disabled\n"), 744 pr->port)); 745 return BCM_E_BUSY; 746 } 747 748 /* 749 * Check that ports to be 'detached' do not 750 * have linkscan mode set. See _bcm_apache_port_resource_pmap_get(). 751 */ 752 if (pr->flags & SOC_PORT_RESOURCE_DETACH) { 753 if (bcm_esw_linkscan_enable_port_get(unit, pr->port) != 754 BCM_E_DISABLED) { 755 LOG_ERROR(BSL_LS_BCM_PORT, 756 (BSL_META_U(unit, 757 "Linkscan mode needs to be " 758 "disabled on ports to be detached, " 759 "port=%d\n"), 760 pr->port)); 761 return BCM_E_BUSY; 762 } 763 } 764 } 765 766 return BCM_E_NONE; 767 } 768 769 770 771 /* 772 * Function: 773 * _bcm_apache_port_resource_pmap_get 774 * Purpose: 775 * Determine the type of port mapping changes, if any, 776 * as a result of the FlexPort operation. In addition, it 777 * determines whether the port needs to go through the attach 778 * and/or detach process. 779 * 780 * All ports that are being flexed will be detached except for those 781 * that will become inactive (this is only for legacy mode). 782 * All ports that are active after flexed are always attached (this is 783 * for new and legacy mode). 784 * 785 * When a port is 'marked' as 'delete' (physical port is -1), 786 * this does not mean the logical port will be destroyed. Depending 787 * on the rest of the information in the array, the port mapping 788 * may be the same, remapped, or it may no longer exist after FlexPort. 789 * 790 * Likewise, when a valid port mapping is given, the port may 791 * not be necessarily new. 792 * 793 * Example: 794 * 795 * Main FlexPort array ('resource') (application input) 796 * L1 --> -1 (current mapped to P1), mapping is SAME 797 * L2 --> -1 (current mapped to P2), mapping is REMAP 798 * L3 --> -1 (current mapped to P3), mapping is DESTROY 799 * L1 --> P1 , mapping is SAME 800 * L2 --> P5 , mapping is REMAP 801 * L9 --> P9 , mapping is NEW 802 * 803 * Parameters: 804 * unit - (IN) Unit number. 805 * nport - (IN) Number of elements in array resource. 806 * resource - (IN/OUT) Port Resource FlexPort configuration. 807 * Returns: 808 * SOC_E_XXX 809 * Notes: 810 * Assumes all 'delete' elements are first in array. 811 */ 812 STATIC int 813 _bcm_apache_port_resource_pmap_get(int unit, int nport, 814 bcm_apache_port_resource_t *resource) 815 { 816 int i; 817 int j; 818 bcm_apache_port_resource_t *pr; 819 soc_info_t *si = &SOC_INFO(unit); 820 821 for (i = 0, pr = &resource[0]; i < nport; i++, pr++) { 822 823 if (pr->physical_port == -1) { 824 /* 825 * Find if port is given in later elements. 826 * If so, check if port is remapped. 827 * If not found, port is marked to be destroyed 828 * (port will no longer exist after FlexPort) 829 * 830 * Note that all the 'delete' ports must always first 831 * in array. 832 */ 833 for (j = i; j < nport; j++) { 834 if (resource[j].physical_port == -1) { 835 continue; 836 } 837 if (resource[j].port == pr->port) { /* Found */ 838 int cur_encap; 839 /* Get current port encap */ 840 BCM_IF_ERROR_RETURN(bcm_esw_port_encap_get(unit, pr->port, 841 &cur_encap)); 842 /* Check if mapping is same */ 843 if (resource[j].physical_port != 844 si->port_l2p_mapping[pr->port]) { 845 pr->flags |= SOC_PORT_RESOURCE_REMAP; 846 if (resource[j].flags & SOC_PORT_RESOURCE_SPEED) { 847 LOG_ERROR(BSL_LS_BCM_PORT,(BSL_META_U 848 (unit, "Port Mapping doesn't match\n"))); 849 return BCM_E_CONFIG; 850 } 851 } 852 853 /* Check if lanes and encap mode are same */ 854 if ((si->port_num_lanes[pr->port] != resource[j].lanes) || 855 (cur_encap != resource[j].encap)) { 856 if (resource[j].flags & SOC_PORT_RESOURCE_SPEED) { 857 LOG_ERROR(BSL_LS_BCM_PORT,(BSL_META_U 858 (unit, "Lanes or Encap mode doesn't match\n"))); 859 return BCM_E_CONFIG; 860 } 861 } 862 break; 863 } 864 } 865 866 if (j >= nport) { /* Not found */ 867 pr->flags |= SOC_PORT_RESOURCE_DESTROY; 868 if (pr->flags & SOC_PORT_RESOURCE_SPEED) { 869 LOG_ERROR(BSL_LS_BCM_PORT,(BSL_META_U 870 (unit, "Port Mapping doesn't match\n"))); 871 return BCM_E_CONFIG; 872 } 873 } 874 875 /* 876 * Detach only if the port is not becoming inactive (legacy). 877 * 878 * A port that is becoming inactive after flex is indicated 879 * when both of the following flags are set: 880 * DESTROY 881 * I_MAP 882 */ 883 if (!(pr->flags & SOC_PORT_RESOURCE_DESTROY) || 884 !(pr->flags & SOC_PORT_RESOURCE_I_MAP)) { 885 pr->flags |= SOC_PORT_RESOURCE_DETACH; 886 } 887 888 } else { 889 890 /* 891 * Check if logical port is new (port does exist), or 892 * port is being remapped. 893 */ 894 if (si->port_l2p_mapping[pr->port] == -1) { 895 pr->flags |= SOC_PORT_RESOURCE_NEW; 896 pr->flags &= ~SOC_PORT_RESOURCE_SPEED; 897 } else if (pr->physical_port != si->port_l2p_mapping[pr->port]) { 898 pr->flags |= SOC_PORT_RESOURCE_REMAP; 899 pr->flags &= ~SOC_PORT_RESOURCE_SPEED; 900 } 901 902 /* All active ports after flexed are always attached */ 903 pr->flags |= SOC_PORT_RESOURCE_ATTACH; 904 } 905 906 } 907 908 return BCM_E_NONE; 909 } 910 911 /* 912 * Function: 913 * _bcm_apache_port_resource_op_get 914 * Purpose: 915 * Get the type of FlexPort operations/changes: 916 * none, port-mapping, lanes, speed, encap. 917 * 918 * Some operations only need speed or encap changes. In this 919 * case, the actual FlexPort operation is not necessary and 920 * only calls to set to speed and/or encap mode are made. 921 * 922 * Parameters: 923 * unit - (IN) Unit number. 924 * nport - (IN) Number of elements in array resource. 925 * resource - (IN) Port resource configuration array. 926 * op - (OUT) FlexPort operation BCM_AP_PORT_RESOURCE_OP_... 927 * Returns: 928 * BCM_E_XXX 929 * Note: 930 * Assumes caller has lock. 931 * Resource is not NULL. 932 * Logical port in 'resource' is in BCM port format (non GPORT). 933 */ 934 STATIC int 935 _bcm_apache_port_resource_op_get(int unit, int nport, 936 bcm_apache_port_resource_t *resource, int *op) 937 { 938 int i; 939 bcm_apache_port_resource_t *pr; 940 soc_info_t *si = &SOC_INFO(unit); 941 int speed = 0; 942 int encap = 0; 943 944 *op = BCM_AP_PORT_RESOURCE_OP_NONE; 945 946 for (i = 0, pr = &resource[0]; i < nport; i++, pr++) { 947 948 /* Check port speed */ 949 if (pr->flags & SOC_PORT_RESOURCE_SPEED) { 950 /* 951 * NOTE: speed_set sequence 952 * 953 * pr->flags & SOC_PORT_RESOURCE_SPEED is set by speed_set API. 954 * No logical-physical port mapping changes. 955 * OP_PMAP flag doesn't need to be set in this case. 956 * _bcm_ap_port_resource_speed_execute will be called. 957 */ 958 *op |= BCM_AP_PORT_RESOURCE_OP_SPEED; 959 LOG_VERBOSE(BSL_LS_BCM_PORT, 960 (BSL_META_U(unit, 961 "Speed change detected: " 962 "logical=%d physical=%d\n"), 963 pr->port, pr->physical_port)); 964 continue; 965 } 966 967 /* Check port mapping change */ 968 if (pr->flags & 969 (SOC_PORT_RESOURCE_NEW | SOC_PORT_RESOURCE_DESTROY | 970 SOC_PORT_RESOURCE_REMAP)) { 971 *op |= BCM_AP_PORT_RESOURCE_OP_PMAP; 972 973 LOG_VERBOSE(BSL_LS_BCM_PORT, 974 (BSL_META_U(unit, 975 "Port map change detected: " 976 "%s %s %s l=%d p=%d\n"), 977 (pr->flags & SOC_PORT_RESOURCE_NEW) ? "new" : "", 978 (pr->flags & SOC_PORT_RESOURCE_DESTROY) ? 979 "destroy" : "", 980 (pr->flags & SOC_PORT_RESOURCE_REMAP) ? "remap" : "", 981 pr->port, pr->physical_port)); 982 } 983 984 /* Skip ports that are being deleted or not defined */ 985 if ((pr->physical_port == -1) || 986 (si->port_l2p_mapping[pr->port] == -1)) { 987 continue; 988 } 989 990 /* 991 * NOTE: Execute full flex operation if speed is different 992 */ 993 if (!(*op & BCM_AP_PORT_RESOURCE_OP_SPEED)) { 994 BCM_IF_ERROR_RETURN(bcm_esw_port_speed_get(unit, pr->port, &speed)); 995 if (pr->speed != speed) { 996 *op |= BCM_AP_PORT_RESOURCE_OP_PMAP; 997 } 998 } 999 1000 /* Check port lanes */ 1001 if (!(*op & BCM_AP_PORT_RESOURCE_OP_LANES)) { 1002 if (pr->lanes != si->port_num_lanes[pr->port]) { 1003 *op |= BCM_AP_PORT_RESOURCE_OP_LANES; 1004 } 1005 } 1006 1007 /* Check port encap */ 1008 if (!(*op & BCM_AP_PORT_RESOURCE_OP_ENCAP)) { 1009 BCM_IF_ERROR_RETURN(bcm_esw_port_encap_get(unit, pr->port, &encap)); 1010 if (pr->encap != encap) { 1011 *op |= BCM_AP_PORT_RESOURCE_OP_ENCAP; 1012 } 1013 } 1014 1015 /* If all are set, no more checking is necessary */ 1016 if (*op == BCM_AP_PORT_RESOURCE_OP_ALL) { 1017 break; 1018 } 1019 } 1020 1021 return BCM_E_NONE; 1022 } 1023 1024 1025 /* 1026 * Function: 1027 * _bcm_apache_port_resource_loopback_clear 1028 * Purpose: 1029 * Clear the loopback mode for the given set of ports. 1030 * 1031 * Parameters: 1032 * unit - (IN) Unit number. 1033 * nport - (IN) Number of elements in array resource. 1034 * resource - (IN) Port Resource FlexPort configuration. 1035 * Returns: 1036 * SOC_E_XXX 1037 * Notes: 1038 * Assumes all 'delete' elements are first in array. 1039 */ 1040 STATIC int 1041 _bcm_apache_port_resource_loopback_clear(int unit, 1042 int nport, 1043 bcm_apache_port_resource_t *resource) 1044 { 1045 int i; 1046 int loopback; 1047 bcm_apache_port_resource_t *pr; 1048 1049 for (i = 0, pr = &resource[0]; i < nport; i++, pr++) { 1050 if (pr->physical_port == -1) { 1051 BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_loopback_get(unit, 1052 pr->port, &loopback)); 1053 if (loopback != BCM_PORT_LOOPBACK_NONE) { 1054 BCM_IF_ERROR_RETURN(bcmi_esw_portctrl_loopback_set(unit, 1055 pr->port, 1056 BCM_PORT_LOOPBACK_NONE)); 1057 } 1058 } 1059 } 1060 1061 return BCM_E_NONE; 1062 1063 } 1064 1065 /* 1066 * Function: 1067 * _bcm_apache_port_resource_speed_execute 1068 * Purpose: 1069 * Perform a speed set operation. 1070 * This includes speed change only 1071 * 1072 * Parameters: 1073 * unit - (IN) Unit number. 1074 * nport - (IN) Number of elements in array resource. 1075 * resource - (IN) Port resource configuration array. 1076 * Returns: 1077 * BCM_E_XXX 1078 * Note: 1079 * Assumes caller has lock. 1080 * Assumes BCM data has been validated (basic API semantics) 1081 * 1082 * Details: 1083 * This function is pretty similar as _bcm_apache_port_resource_execute. 1084 * But speed set doesn't change logical-physical port mapping. 1085 * So this function should skip detach, attach function calls. 1086 * _bcm_apache_port_resource_detach 1087 * _bcm_apache_port_resource_attach 1088 * Also this calls soc_apache_port_resource_configure with 1089 * the flag:SOC_PORT_RESOURCE_CONFIGURE_SPEED_SET to make slightly 1090 * different sequence from full flex operation. 1091 */ 1092 STATIC int 1093 _bcm_apache_port_resource_speed_execute(int unit, 1094 int nport, bcm_apache_port_resource_t *resource) 1095 { 1096 int rv; 1097 int i; 1098 soc_port_resource_t *soc_resource; 1099 1100 soc_resource = sal_alloc(sizeof(soc_port_resource_t) * nport, 1101 "port_resource"); 1102 if (soc_resource == NULL) { 1103 LOG_ERROR(BSL_LS_BCM_PORT, 1104 (BSL_META_U(unit, 1105 "Unable to allocate memory for SOC FlexPort " 1106 "array\n"))); 1107 return BCM_E_MEMORY; 1108 } 1109 1110 /* Clear data structure */ 1111 sal_memset(soc_resource, 0, sizeof(soc_port_resource_t) * nport); 1112 1113 /* Copy initial information */ 1114 for (i = 0; i < nport; i++) { 1115 soc_resource[i].flags = resource[i].flags; 1116 soc_resource[i].logical_port = resource[i].port; 1117 soc_resource[i].physical_port = resource[i].physical_port; 1118 soc_resource[i].speed = resource[i].speed; 1119 soc_resource[i].num_lanes = resource[i].lanes; 1120 soc_resource[i].encap = resource[i].encap; 1121 /* Use CL91 settings in case it is already enabled on the port */ 1122 rv = bcmi_esw_portctrl_phy_control_get(unit, resource[i].port, 1123 BCM_PORT_PHY_CONTROL_FORWARD_ERROR_CORRECTION_CL91, 1124 &(soc_resource[i].cl91_enabled)); 1125 if (BCM_FAILURE(rv)) { 1126 /* All PHYs don't support CL91 */ 1127 soc_resource[i].cl91_enabled = 0; 1128 } 1129 } 1130 1131 rv = soc_ap_port_resource_validate(unit, nport, soc_resource); 1132 if (SOC_FAILURE(rv)) { 1133 sal_free(soc_resource); 1134 return rv; 1135 } 1136 1137 /* SOC Port Resource Configure */ 1138 rv = soc_ap_port_resource_configure(unit, nport, soc_resource, 1139 SOC_PORT_RESOURCE_CONFIGURE_SPEED_ONLY); 1140 1141 if (BCM_FAILURE(rv)) { 1142 LOG_ERROR(BSL_LS_BCM_PORT, 1143 (BSL_META_U(unit, 1144 "Changes to device may have been partially " 1145 "executed. System may be unstable.\n"))); 1146 } 1147 1148 sal_free(soc_resource); 1149 1150 return rv; 1151 } 1152 1153 /* 1154 * Function: 1155 * _bcm_apache_port_resource_execute 1156 * Purpose: 1157 * Perform a FlexPort operation. 1158 * This includes changes that involve: 1159 * - Logical to physical port mapping 1160 * - Speed 1161 * - Number of PHY lanes 1162 * 1163 * Parameters: 1164 * unit - (IN) Unit number. 1165 * nport - (IN) Number of elements in array resource. 1166 * resource - (IN) Port resource configuration array. 1167 * Returns: 1168 * BCM_E_XXX 1169 * Note: 1170 * Assumes caller has lock. 1171 * Assumes BCM data has been validated (basic API semantics) 1172 * 1173 * Details: 1174 * 1175 * Port Mapping 1176 * ------------ 1177 * A logical to physical port mapping is given as part of the port resource 1178 * array. This can lead to the following operations: 1179 * - Port Mapping Delete (or clear) 1180 * This is indicated when the physical port is set to (-1) and 1181 * the port to be flexed is considered an 'old' port. 1182 * The logical port in the array entry must always be valid. 1183 * A 'delete' may result in the following actions for a port mapping: 1184 * (1) Destroyed 1185 * (2) Same 1186 * (3) Remapped 1187 * 1188 * - Port Mapping Add (or set) 1189 * This is indicated when the physical port is set to a valid 1190 * physical port number (>=0). 1191 * The logical port in the array entry must always be valid. 1192 * An 'add' may result in the following actions for a port mapping: 1193 * (1) New 1194 * (2) Same 1195 * (3) Remapped 1196 * 1197 * Destroyed: Logical port no longer exist after FlexPort. 1198 * Remapped: Logical port will continue to exist after FlexPort 1199 * but is mapped to a different physical port. 1200 * New: Logical port did not exist before FlexPort. 1201 * Same: Logical to physical port mapping remains the same. 1202 */ 1203 STATIC int 1204 _bcm_apache_port_resource_execute(int unit, 1205 int nport, bcm_apache_port_resource_t *resource) 1206 { 1207 int rv; 1208 int i; 1209 soc_port_resource_t *soc_resource; 1210 1211 /* 1212 * Main FlexPort Sequence 1213 * 1214 * - SOC Validation: 1215 * + More validation takes place in the SOC layer. 1216 * + These check for abilities and configurations based on 1217 * the physical aspects of the device. 1218 * 1219 * NOTE: Up to this point, no changes has taken place in SW 1220 * data structures or HW. 1221 * From this point forward, HW and SW data will be modified, 1222 * any errors will leave the system unstabled. 1223 * 1224 * - Clear any port related settings in BCM layer as needed. 1225 * 1226 * - Detach 'old' ports from BCM layer: 1227 * + These are all ports to be cleared/deleted (indicated by physical 1228 * port -1), EXCEPT those that will become inactive after the 1229 * FlexPort operation (this is only true with legacy API). 1230 * + The port state should be the same as the state of a 1231 * port that was never configured during SDK initialization. 1232 * + This involves SW and HW changes. 1233 * 1234 * - SOC Port Resource Configure: 1235 * Takes place in the SOC layer. 1236 * It consists primarliy of these steps: 1237 * + Delete ports in SOC layer (SOC_INFO SW, HW update). 1238 * + Add ports in SOC layer (SOC_INFO SW, HW update). 1239 * + Execute FlexPort operation as defined by HW specs. 1240 * 1241 * - Attach 'new' ports to BCM layer: 1242 * + These are all ports that are active after the FlexPort operation. 1243 * + Ports are initialized to a default state 1244 * (same state when a port is brought up after SDK is initialized). 1245 * + This involves SW and HW changes. 1246 * 1247 * - Set BCM properties on flexed ports as needed. 1248 */ 1249 1250 /* 1251 * SOC Port Structure initialization 1252 */ 1253 /* Allocate memory for SOC Port Resource array data structure */ 1254 soc_resource = sal_alloc(sizeof(soc_port_resource_t) * nport, 1255 "port_resource"); 1256 if (soc_resource == NULL) { 1257 LOG_ERROR(BSL_LS_BCM_PORT, 1258 (BSL_META_U(unit, 1259 "Unable to allocate memory for SOC FlexPort " 1260 "array\n"))); 1261 return BCM_E_MEMORY; 1262 } 1263 1264 /* Clear data structure */ 1265 sal_memset(soc_resource, 0, sizeof(soc_port_resource_t) * nport); 1266 1267 /* Copy initial information */ 1268 for (i = 0; i < nport; i++) { 1269 soc_resource[i].flags = resource[i].flags; 1270 soc_resource[i].logical_port = resource[i].port; 1271 soc_resource[i].physical_port = resource[i].physical_port; 1272 soc_resource[i].speed = resource[i].speed; 1273 soc_resource[i].num_lanes = resource[i].lanes; 1274 soc_resource[i].encap = resource[i].encap; 1275 /* In case full flexport sequence is required assume cl91 is disabled. 1276 * If user wants to enable CL91 on new ports, it is expected that call to 1277 * bcmi_esw_portctrl_phy_control_set() will be followed by a speed_set() 1278 */ 1279 soc_resource[i].cl91_enabled = 0; 1280 } 1281 1282 /* SOC Validation */ 1283 rv = soc_ap_port_resource_validate(unit, nport, soc_resource); 1284 if (SOC_FAILURE(rv)) { 1285 sal_free(soc_resource); 1286 return rv; 1287 } 1288 1289 /* Detach ports from BCM layer */ 1290 rv = _bcm_apache_port_resource_detach(unit, nport, resource); 1291 1292 /* SOC Port Resource Configure */ 1293 if (BCM_SUCCESS(rv)) { 1294 rv = soc_ap_port_resource_configure(unit, nport, soc_resource, 1295 SOC_PORT_RESOURCE_CONFIGURE_FLEX); 1296 } 1297 1298 /* Attach ports to BCM layer */ 1299 if (BCM_SUCCESS(rv)) { 1300 rv = _bcm_apache_port_resource_attach(unit, nport, resource); 1301 } 1302 1303 if (BCM_FAILURE(rv)) { 1304 LOG_ERROR(BSL_LS_BCM_PORT, 1305 (BSL_META_U(unit, 1306 "Changes to device may have been partially " 1307 "executed. System may be unstable.\n"))); 1308 } 1309 1310 sal_free(soc_resource); 1311 1312 return rv; 1313 } 1314 1315 1316 /* 1317 * Function: 1318 * _bcm_apache_port_resource_configure 1319 * Purpose: 1320 * Modify the following port resources: 1321 * - Logical to physical port mapping 1322 * - Speed 1323 * - Number of PHY lanes 1324 * - Encapsulation mode 1325 * Parameters: 1326 * unit - (IN) Unit number. 1327 * nport - (IN) Number of elements in array resource. 1328 * resource - (IN/OUT) Port resource configuration array. 1329 * Returns: 1330 * BCM_E_XXX 1331 * Note: 1332 * - Assumes caller has lock. 1333 * - The data is modified by the function. 1334 * - It takes the internal bcm_apache_port_resource_t data type. 1335 */ 1336 STATIC int 1337 _bcm_apache_port_resource_configure(int unit, 1338 int nport, 1339 bcm_apache_port_resource_t *resource) 1340 { 1341 int op; 1342 int i; 1343 1344 /* Convert port format and validate logical and physical port numbers */ 1345 BCM_IF_ERROR_RETURN 1346 (_bcm_apache_port_resource_resolve(unit, 1347 nport, resource)); 1348 1349 /* Get port mapping change */ 1350 BCM_IF_ERROR_RETURN 1351 (_bcm_apache_port_resource_pmap_get(unit, nport, resource)); 1352 1353 /* clear loopback */ 1354 BCM_IF_ERROR_RETURN 1355 (_bcm_apache_port_resource_loopback_clear(unit, nport, resource)); 1356 1357 /* 1358 * Validate function input requirements 1359 * 1360 * This steps checks for function semantics and guidelines 1361 * from the API perspective. 1362 */ 1363 BCM_IF_ERROR_RETURN 1364 (_bcm_apache_port_resource_input_validate(unit, nport, resource)); 1365 1366 /* 1367 * FlexPort operations types: 1368 * NONE => Nothing to do 1369 * PMAP or LANES => FlexPort sequence 1370 * ENCAP => Encap set 1371 * SPEED, but not PMAP or LANES => Speed set 1372 */ 1373 BCM_IF_ERROR_RETURN 1374 (_bcm_apache_port_resource_op_get(unit, nport, resource, &op)); 1375 1376 1377 LOG_VERBOSE(BSL_LS_BCM_PORT, 1378 (BSL_META_U(unit, 1379 "FlexPort operations 0x%x: %s %s %s %s\n"), 1380 op, 1381 (op & BCM_AP_PORT_RESOURCE_OP_PMAP) ? "pmap" : "", 1382 (op & BCM_AP_PORT_RESOURCE_OP_SPEED) ? "speed" : "", 1383 (op & BCM_AP_PORT_RESOURCE_OP_LANES) ? "lanes" : "", 1384 (op & BCM_AP_PORT_RESOURCE_OP_ENCAP) ? "encap" : "")); 1385 1386 if (op == BCM_AP_PORT_RESOURCE_OP_NONE) { 1387 return BCM_E_NONE; /* No changes, just return */ 1388 } 1389 1390 /* 1391 * Port Mapping / Lane 1392 * 1393 * These changes always require a FlexPort operation. 1394 */ 1395 if ((op & BCM_AP_PORT_RESOURCE_OP_PMAP) || 1396 (op & BCM_AP_PORT_RESOURCE_OP_LANES)) { 1397 LOG_VERBOSE(BSL_LS_BCM_PORT, 1398 (BSL_META_U(unit, 1399 "--- Execute FlexPort sequence ---\n"))); 1400 BCM_IF_ERROR_RETURN 1401 (_bcm_apache_port_resource_execute(unit, 1402 nport, resource)); 1403 for (i = 0; i < nport; i++) { 1404 if (resource[i].physical_port == -1) { 1405 continue; 1406 } 1407 1408 /* Bring new ports down to ensure port state is proper */ 1409 BCM_IF_ERROR_RETURN 1410 (bcmi_esw_portctrl_enable_set(unit, resource[i].port, 0)); 1411 } 1412 1413 } else if (op & BCM_AP_PORT_RESOURCE_OP_SPEED) { 1414 LOG_VERBOSE(BSL_LS_BCM_PORT, 1415 (BSL_META_U(unit, 1416 "--- Execute Speed Set sequence ---\n"))); 1417 BCM_IF_ERROR_RETURN 1418 (_bcm_apache_port_resource_speed_execute(unit, 1419 nport, resource)); 1420 } 1421 1422 /* 1423 * Encap 1424 */ 1425 if (op & BCM_AP_PORT_RESOURCE_OP_ENCAP) { 1426 LOG_VERBOSE(BSL_LS_BCM_PORT, 1427 (BSL_META_U(unit, 1428 "Execute Encap change\n"))); 1429 for (i = 0; i < nport; i++) { 1430 if (resource[i].physical_port == -1) { 1431 continue; 1432 } 1433 1434 BCM_IF_ERROR_RETURN 1435 (bcmi_esw_portctrl_encap_set(unit, resource[i].port, 1436 resource[i].encap, TRUE)); 1437 } 1438 } 1439 1440 return BCM_E_NONE; 1441 } 1442 1443 1444 /* 1445 * Function: 1446 * _bcm_apache_port_resource_multi_set 1447 * Purpose: 1448 * Modify the following port resources: 1449 * - Logical to physical port mapping 1450 * - Speed 1451 * - Number of PHY lanes 1452 * - Encapsulation mode 1453 * Parameters: 1454 * unit - (IN) Unit number. 1455 * nport - (IN) Number of elements in array resource. 1456 * resource - (IN) Port resource configuration array. 1457 * Returns: 1458 * BCM_E_XXX 1459 * Note: 1460 * - Assumes caller has lock. 1461 * - This is to be called by the API dispatch driver. 1462 * - It takes the public bcm_apache_port_resource_t data type. 1463 */ 1464 STATIC int 1465 _bcm_apache_port_resource_multi_set(int unit, 1466 int nport, 1467 bcm_port_resource_t *resource) 1468 { 1469 int rv; 1470 int i; 1471 bcm_apache_port_resource_t *port_resource; 1472 1473 if (resource == NULL) { 1474 return BCM_E_PARAM; 1475 } 1476 1477 /* 1478 * Use internal port resource structure type. 1479 * Called routines will be modifying the data, so 1480 * having a copy avoids modifying user's data. 1481 */ 1482 port_resource = sal_alloc(sizeof(bcm_apache_port_resource_t) * nport, 1483 "port_resource"); 1484 if (port_resource == NULL) { 1485 LOG_ERROR(BSL_LS_BCM_PORT, 1486 (BSL_META_U(unit, 1487 "Unable to allocate memory for internal " 1488 "FlexPort array\n"))); 1489 return BCM_E_MEMORY; 1490 } 1491 1492 /* Clear data structure */ 1493 sal_memset(port_resource, 0, sizeof(bcm_apache_port_resource_t) * nport); 1494 1495 /* Copy initial information */ 1496 for (i = 0; i < nport; i++) { 1497 /* 1498 * Translate from public to internal flags. 1499 */ 1500 if (resource[i].flags & BCM_PORT_RESOURCE_SPEED_ONLY) { 1501 port_resource[i].flags = SOC_PORT_RESOURCE_SPEED; 1502 } 1503 port_resource[i].port = resource[i].port; 1504 port_resource[i].physical_port = resource[i].physical_port; 1505 port_resource[i].speed = resource[i].speed; 1506 port_resource[i].lanes = resource[i].lanes; 1507 port_resource[i].encap = resource[i].encap; 1508 } 1509 1510 rv = _bcm_apache_port_resource_configure(unit, nport, port_resource); 1511 if (BCM_FAILURE(rv)) { 1512 sal_free(port_resource); 1513 return rv; 1514 } 1515 1516 for (i = 0; i < nport; i++) { 1517 if ((port_resource[i].physical_port == -1) || 1518 !(port_resource[i].flags & SOC_PORT_RESOURCE_SPEED)) { 1519 continue; 1520 } 1521 1522 /* Need to follow remaining speed_set() sequence. 1523 * Will not lead to another flexport operation since 1524 * speed change is already done and soc structures have been updated above 1525 */ 1526 rv = bcmi_esw_portctrl_speed_set(unit, resource[i].port, resource[i].speed); 1527 if (BCM_FAILURE(rv)) { 1528 sal_free(port_resource); 1529 return rv; 1530 } 1531 } 1532 1533 sal_free(port_resource); 1534 1535 return rv; 1536 } 1537 1538 /* 1539 * Function: 1540 * _bcm_apache_port_resource_speed_set 1541 * Purpose: 1542 * Changes the speed but keeps the same number of lanes 1543 * Parameters: 1544 * unit - (IN) Unit number 1545 * port - (IN) Logical port number(bcm_port_t, not bcm_gport_t) 1546 * speed - (IN) Port speed 1547 * Returns: 1548 * BCM_E_XXX 1549 * Note: 1550 * - Assumes caller has lock. 1551 * - This is to be called by the bcmi_esw_portctrl_speed_set(). 1552 */ 1553 STATIC int 1554 _bcm_apache_port_resource_speed_set(int unit, bcm_port_t port, int speed) 1555 { 1556 soc_info_t *si = &SOC_INFO(unit); 1557 bcm_apache_port_resource_t resource[2]; /* resource for pre and post */ 1558 int cur_encap; 1559 int phy_port; 1560 1561 /* si->port_speed_max is the current speed at which MMU/TDM is configured */ 1562 if ((si->port_speed_max[port] == speed) || (speed == 0)) { 1563 LOG_VERBOSE(BSL_LS_BCM_PORT, 1564 (BSL_META_U(unit, 1565 "Speed is already configured as %d\n"), si->port_speed_max[port])); 1566 return BCM_E_NONE; 1567 } 1568 1569 /* Get current port encap */ 1570 BCM_IF_ERROR_RETURN(bcm_esw_port_encap_get(unit, port, &cur_encap)); 1571 1572 /* 1573 * Clear mapping for physical ports involved in FlexPort operation. 1574 */ 1575 phy_port = si->port_l2p_mapping[port]; 1576 /* Check valid physical port */ 1577 if (phy_port == -1) { 1578 LOG_ERROR(BSL_LS_BCM_PORT, 1579 (BSL_META_U(unit, 1580 "Invalid physical port " 1581 "for logical port %d\n"), 1582 port)); 1583 return BCM_E_INTERNAL; 1584 } 1585 1586 resource[0].flags = SOC_PORT_RESOURCE_SPEED; 1587 resource[0].port = port; 1588 resource[0].physical_port = -1; 1589 1590 resource[1].flags = SOC_PORT_RESOURCE_SPEED; 1591 resource[1].port = port; 1592 resource[1].physical_port = phy_port; 1593 resource[1].speed = speed; 1594 resource[1].lanes = si->port_num_lanes[port]; 1595 resource[1].encap = cur_encap; 1596 1597 BCM_IF_ERROR_RETURN(_bcm_apache_port_resource_configure(unit, 2, resource)); 1598 1599 return BCM_E_NONE; 1600 } 1601 1602 /* 1603 * Function: 1604 * bcmi_apache_port_lanes_get 1605 * Purpose: 1606 * Get the number of PHY lanes for the given port. 1607 * Parameters: 1608 * unit - (IN) Unit number. 1609 * port - (IN) Logical port. 1610 * lanes - (OUT) Returns number of lanes for port. 1611 * Returns: 1612 * BCM_E_XXX 1613 */ 1614 int 1615 bcmi_apache_port_lanes_get(int unit, bcm_port_t port, int *lanes) 1616 { 1617 bcm_port_resource_t resource; 1618 1619 BCM_IF_ERROR_RETURN(bcm_esw_port_resource_get(unit, port, &resource)); 1620 1621 *lanes = resource.lanes; 1622 1623 return BCM_E_NONE; 1624 } 1625 1626 /* 1627 * Function: 1628 * bcmi_apache_port_lanes_set 1629 * Purpose: 1630 * Set the number of PHY lanes for the given port. 1631 * 1632 * This function should only be used to support the legacy 1633 * FlexPort API bcm_port_control_set(... , bcmPortControlLanes). 1634 * 1635 * The legacy API does not delete the port mappings when flexing 1636 * to fewer lanes. Ports which lanes are used by the base 1637 * physical port becomes inactive. 1638 * 1639 * Parameters: 1640 * unit - (IN) Unit number. 1641 * port - (IN) Logical port. 1642 * lanes - (IN) Number of lanes to set on given port. 1643 * Returns: 1644 * BCM_E_XXX 1645 * Notes: 1646 * - Only to be used by legacy API to support TD2 behavior 1647 * bcm_port_control_set(... , bcmPortControlLanes). 1648 * - Supports only up to 4 lanes (TSC-4). 1649 * - 'port' must be in BCM port format (non-GPORT) and mapped to 1650 * the base physical port. 1651 * - Several calls to legacy API may be required to 1652 * achieve desired configuration. 1653 */ 1654 int 1655 bcmi_apache_port_lanes_set(int unit, bcm_port_t port, int lanes) 1656 { 1657 soc_info_t *si = &SOC_INFO(unit); 1658 bcm_apache_port_resource_t resource[8]; /* Max size to support up to 4 lanes */ 1659 int max_array_cnt; 1660 int i; 1661 int cur_lanes; 1662 int cur_speed; 1663 int cur_encap = 0; 1664 int phy_port; 1665 int speed; 1666 int num_ports_clear; 1667 int num_ports_new; 1668 1669 /* Support legacy API up to 4 lanes */ 1670 if ((lanes != 1) && (lanes != 2) && (lanes != 4)) { 1671 return BCM_E_PARAM; 1672 } 1673 1674 /* Check current number of lanes */ 1675 cur_lanes = si->port_num_lanes[port]; 1676 if (cur_lanes == lanes) { 1677 return BCM_E_NONE; 1678 } 1679 1680 /* Check that port can support number of lanes specified */ 1681 SOC_IF_ERROR_RETURN(soc_ap_port_lanes_valid(unit, port, lanes)); 1682 1683 /* Get current port speed */ 1684 BCM_IF_ERROR_RETURN(bcm_esw_port_speed_get(unit, port, &cur_speed)); 1685 1686 /* Get current port encap */ 1687 BCM_IF_ERROR_RETURN(bcm_esw_port_encap_get(unit, port, &cur_encap)); 1688 1689 /* Clear array */ 1690 max_array_cnt = COUNTOF(resource); 1691 sal_memset(resource, 0, sizeof(resource)); 1692 1693 /* 1694 * Build port resource array 1695 * Certain information is derived from 'best' guess, 1696 * similar to the legacy behaviour. 1697 */ 1698 1699 /* 1700 * Select speed based on number of lanes 1701 * 1702 * For HG, if the current HG speed is the higher speed 1703 * (i.e. 42 vs 40) select the higher HG speed for the number of lanes. 1704 * Example 1705 * 1xHG[42] --> 4xHG[11] 1706 * 1xHG[40] --> 4xHG[10] 1707 * 1708 * Notes: Assumes encap is HIGIG2 if it is not IEEE 1709 */ 1710 switch(lanes) { 1711 case 1: 1712 if (cur_encap == BCM_PORT_ENCAP_IEEE) { /* IEEE */ 1713 speed = PORT_IS_PM4x25_PORT(unit, port) ? 25000: 10000; 1714 } else { /* HG2 */ 1715 speed = PORT_IS_PM4x25_PORT(unit, port) ? 27000: 11000; 1716 } 1717 break; 1718 case 2: 1719 if (cur_encap == BCM_PORT_ENCAP_IEEE) { /* IEEE */ 1720 speed = PORT_IS_PM4x25_PORT(unit, port) ? 50000: 20000; 1721 } else { /* HG2 */ 1722 speed = PORT_IS_PM4x25_PORT(unit, port) ? 53000: 21000; 1723 } 1724 1725 break; 1726 case 4: 1727 if (cur_encap == BCM_PORT_ENCAP_IEEE) { /* IEEE */ 1728 speed = PORT_IS_PM4x25_PORT(unit, port) ? 100000: 40000; 1729 } else { /* HG2 */ 1730 speed = PORT_IS_PM4x25_PORT(unit, port) ? 106000: 42000; 1731 } 1732 break; 1733 /* 1734 * COVERITY 1735 * 1736 * Case for default is intentional as a defensive check. 1737 */ 1738 /* coverity[dead_error_begin] */ 1739 1740 default: 1741 return BCM_E_PARAM; 1742 break; 1743 } 1744 1745 switch (cur_lanes) { 1746 case 1: 1747 /* 1748 * 2x10 flex to: 2 lanes -> 1x20 1749 * 4x10 flex to: 4 lanes -> 1x40 1750 */ 1751 if (lanes == 2) { 1752 num_ports_clear = 2; 1753 num_ports_new = 1; 1754 } else { 1755 num_ports_clear = 4; 1756 num_ports_new = 1; 1757 } 1758 break; 1759 case 2: 1760 /* 1761 * 1x20 flex to: 1 lane -> 2x10 1762 * 2x20 flex to: 4 lanes -> 1x40 1763 */ 1764 if (lanes == 1) { 1765 num_ports_clear = 2; 1766 num_ports_new = 2; 1767 } else { 1768 num_ports_clear = 4; 1769 num_ports_new = 1; 1770 } 1771 break; 1772 case 4: 1773 /* 1774 * 1x40 flex to: 1 lane -> 4x10 1775 * 2 lanes -> 2x20 1776 */ 1777 if (lanes == 1) { 1778 num_ports_clear = 4; 1779 num_ports_new = 4; 1780 } else { 1781 num_ports_clear = 4; 1782 num_ports_new = 2; 1783 } 1784 break; 1785 default: 1786 return BCM_E_CONFIG; 1787 break; 1788 } 1789 1790 if ((num_ports_clear + num_ports_new) > max_array_cnt) { 1791 LOG_ERROR(BSL_LS_BCM_PORT, 1792 (BSL_META_U(unit, 1793 "Invalid array FlexPort calculation " 1794 "num_ports_clear=%d num_ports_new=%d " 1795 "max_array=%d\n"), 1796 num_ports_clear, num_ports_new, max_array_cnt)); 1797 return BCM_E_INTERNAL; 1798 } 1799 1800 /* 1801 * Clear mapping for physical ports involved in FlexPort operation. 1802 * Assume physical ports are numbered consecutively in device. 1803 */ 1804 phy_port = si->port_l2p_mapping[port]; 1805 for (i = 0; i < num_ports_clear; i++) { 1806 resource[i].flags = SOC_PORT_RESOURCE_I_MAP; 1807 resource[i].port = si->port_p2l_mapping[phy_port++]; 1808 resource[i].physical_port = -1; 1809 } 1810 1811 1812 /* 1813 * Map new ports 1814 * 1815 * Legacy API requires that logical-physical port mapping 1816 * is valid in the SOC_INFO SW data. 1817 */ 1818 phy_port = si->port_l2p_mapping[port]; 1819 for (; i < (num_ports_clear + num_ports_new); i++) { 1820 /* Check valid physical port */ 1821 if (phy_port == -1) { 1822 LOG_ERROR(BSL_LS_BCM_PORT, 1823 (BSL_META_U(unit, 1824 "Invalid physical port " 1825 "for logical port %d\n"), 1826 port)); 1827 return BCM_E_INTERNAL; 1828 } 1829 1830 resource[i].flags = SOC_PORT_RESOURCE_I_MAP; 1831 resource[i].port = si->port_p2l_mapping[phy_port]; 1832 resource[i].physical_port = phy_port; 1833 resource[i].lanes = lanes; 1834 resource[i].speed = speed; 1835 resource[i].encap = cur_encap; 1836 phy_port += lanes; 1837 } 1838 1839 1840 BCM_IF_ERROR_RETURN 1841 (_bcm_apache_port_resource_configure(unit, 1842 (num_ports_clear + num_ports_new), 1843 resource)); 1844 1845 return BCM_E_NONE; 1846 } 1847 1848 /* 1849 * Function: 1850 * _bcm_apache_port_drain_cells 1851 * Purpose: 1852 * To drain cells associated to the port. 1853 * Parameters: 1854 * unit - (IN) unit number 1855 * port - (IN) Port 1856 * Returns: 1857 * BCM_E_XXX 1858 */ 1859 STATIC int 1860 _bcm_apache_port_drain_cells(int unit, int port) 1861 { 1862 return bcmi_esw_portctrl_egress_queue_drain(unit, port); 1863 } 1864 1865 int 1866 bcm_apache_port_drain_cells(int unit, int port) 1867 { 1868 return (_bcm_apache_port_drain_cells(unit, port)); 1869 } 1870 1871 #else /* BCM_APACHE_SUPPORT */ 1872 int bcm_esw_ap_port_not_empty; 1873 #endif /* BCM_APACHE_SUPPORT */