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