port.c (179925B)
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: Apache SOC Port driver. 9 * 10 * Contains information and interfaces for the 11 * physical port in the device. 12 */ 13 14 #include <shared/bsl.h> 15 #include <soc/defs.h> 16 17 #if defined(BCM_MONTEREY_SUPPORT) 18 #include <soc/drv.h> 19 #include <soc/scache.h> 20 #include <soc/error.h> 21 #include <soc/monterey.h> 22 #include <soc/apache.h> 23 #include <soc/esw/port.h> 24 #include <soc/esw/portctrl.h> 25 #include <soc/portmod/portmod_legacy_phy.h> 26 #include <soc/mem.h> 27 #include <sal/appl/sal.h> 28 #include <soc/portmod/portmod_defs.h> 29 30 #define MN_PORTS_PER_TSC 4 31 #define MN_NUM_PGWS 2 32 #define MN_TSCS_PER_PGW 8 33 34 #define PORT_BLOCK_BASE_PORT(port) \ 35 (1 + ((SOC_INFO(unit).port_l2p_mapping[port] - 1) & ~0x3)); 36 37 #ifdef BCM_WARM_BOOT_SUPPORT 38 39 #define SOC_FLEXPORT_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 40 #define SOC_FLEXPORT_WB_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 41 #define SOC_FLEXPORT_WB_DEFAULT_VERSION SOC_FLEXPORT_WB_VERSION_1_1 42 43 #endif 44 extern int 45 soc_monterey_port_is_falcon(int unit, int phy_port); 46 47 /* 48 * Physical Port Information 49 * 50 * Some information are defined in HW and others are defined 51 * through SOC properties during configuration time. 52 */ 53 typedef struct mn_phy_port_s { 54 /* 55 * The following fields are defined in HW 56 */ 57 soc_port_lane_info_t lane_info; /* Lane information in PGW block */ 58 uint32 lanes_valid; /* Lanes capabilities */ 59 int pipe; /* unused */ 60 int sisters_ports[MN_PORTS_PER_TSC]; 61 /* Ports part of the XLPORT/XLMAC/TSC-4 62 where the physical port resides */ 63 64 /* 65 * The following fields are configurable throught SOC properties 66 */ 67 uint16 prio_mask; /* Packet priority to priority 68 group mapping mask */ 69 int flex; /* Flex enable by SOC property 70 'port_flex_enable' */ 71 } mn_phy_port_t; 72 73 /* 74 * Physical Device information 75 */ 76 typedef struct mn_info_s { 77 mn_phy_port_t phy_port[SOC_MAX_NUM_PORTS]; 78 int phy_ports_max; /* Max physical ports in device */ 79 uint32 speed_valid[SOC_PORT_RESOURCE_LANES_MAX+1]; 80 /* Port rate ability on serdes lane */ 81 int speed_max; /* Max speed on any port in device */ 82 int port_max; /* Max logical ports */ 83 84 /* 85 * The following fields are configurable throught SOC properties 86 */ 87 int mmu_lossless; /* MMU lossless */ 88 int flex_legacy; /* Flex enable by legacy ':i' in 89 SOC property 'portmap' */ 90 91 } mn_info_t; 92 93 /* 94 * Contains information corresponding to each physical port. 95 * This information is fixed in a device and is calculated 96 * only during init time. 97 */ 98 static mn_info_t *mn_info[SOC_MAX_NUM_DEVICES]; 99 100 #define MN_INFO(_u) (mn_info[(_u)]) 101 #define MN_PHY_PORT(_u, _p) (MN_INFO(_u)->phy_port[(_p)]) 102 #define MN_PHY_PORT_LANE(_u, _p) (MN_PHY_PORT(_u, _p).lane_info) 103 104 105 /* Lanes support */ 106 #define MN_PHY_XLPORT_LANES_1 (1 << 0) 107 #define MN_PHY_XLPORT_LANES_2 (1 << 1) 108 #define MN_PHY_XLPORT_LANES_4 (1 << 2) 109 #define MN_PHY_XLPORT_LANES_10 (1 << 3) 110 #define MN_PHY_XLPORT_LANES_12 (1 << 4) 111 112 113 /* Port Rate support */ 114 /* Ethernet */ 115 #define MN_PHY_PORT_RATE_1 (1 << 0) 116 #define MN_PHY_PORT_RATE_2_5 (1 << 1) 117 #define MN_PHY_PORT_RATE_5 (1 << 2) 118 #define MN_PHY_PORT_RATE_10 (1 << 3) 119 #define MN_PHY_PORT_RATE_20 (1 << 4) 120 #define MN_PHY_PORT_RATE_25 (1 << 5) 121 #define MN_PHY_PORT_RATE_40 (1 << 6) 122 #define MN_PHY_PORT_RATE_50 (1 << 7) 123 #define MN_PHY_PORT_RATE_100 (1 << 8) 124 /* HG */ 125 #define MN_PHY_PORT_RATE_11 (1 << 9) 126 #define MN_PHY_PORT_RATE_21 (1 << 10) 127 #define MN_PHY_PORT_RATE_27 (1 << 11) 128 #define MN_PHY_PORT_RATE_42 (1 << 12) 129 #define MN_PHY_PORT_RATE_53 (1 << 13) 130 #define MN_PHY_PORT_RATE_106 (1 << 14) 131 #define MN_PHY_PORT_RATE_127 (1 << 15) 132 133 134 /* Default for the max port speed configured for device */ 135 #define MN_FLEX_MAX_NUM_PORTS 67 136 #define MN_FLEX_SPEED_MAX_DEFAULT 106000 137 138 /* 100GE Mode Lanes */ 139 #define MONTEREY_100GE_MLD_MAP_4_4_2_STR "0xff9876543210" 140 #define MONTEREY_100GE_MLD_MAP_3_4_3_STR "0xf9876543f210" 141 #define MONTEREY_100GE_MLD_MAP_2_4_4_STR "0x98765432ff10" 142 #define PORT_IS_FALCON(pport) \ 143 ((((pport >= 1) && (pport <= 20)) || ((pport >= 45 ) && (pport <= 64 ))) ? TRUE : FALSE) 144 145 /* 146 * Define: 147 * MN_INFO_INIT_CHECK 148 * Purpose: 149 * Causes a routine to return SOC_E_INIT if module is not yet initialized. 150 */ 151 #define MN_INFO_INIT_CHECK(_u) \ 152 if (mn_info[_u] == NULL) { return SOC_E_INIT; } 153 154 /* 155 * Define: 156 * MN_PHY_PORT_ADDRESSABLE 157 * Purpose: 158 * Checks that physical port is addressable (within valid range). 159 */ 160 #define MN_PHY_PORT_ADDRESSABLE(_u, _phy_port) \ 161 (soc_mn_phy_port_addressable((_u), (_phy_port)) == SOC_E_NONE) 162 163 164 /* 165 * Miscellaneous SOC port data used for validation 166 * 167 * Most fields are equivalent to the fields in the SOC_INFO data 168 * structure. Use same field names. 169 */ 170 typedef struct soc_info_mn_misc_s { 171 int port_l2p_mapping[SOC_MAX_NUM_PORTS]; /* Logic to phys */ 172 int port_p2l_mapping[SOC_MAX_NUM_PORTS]; /* Phys to logic */ 173 int port_speed_max[SOC_MAX_NUM_PORTS]; /* Max speed */ 174 int port_speed[SOC_MAX_NUM_PORTS]; /* Current speed */ 175 int port_num_lanes[SOC_MAX_NUM_PORTS]; /* lanes */ 176 soc_encap_mode_t port_encap[SOC_MAX_NUM_PORTS]; /* Encap mode */ 177 int bandwidth; 178 pbmp_t oversub_pbm; /* Oversubscription */ 179 pbmp_t disabled_bitmap; /* Disabled ports */ 180 } soc_info_mn_misc_t; 181 int 182 soc_mn_port_ovs_speed_group_validate(int unit); 183 STATIC int 184 _soc_mn_port_resource_ovs_speed_group_validate(int unit, soc_info_mn_misc_t *post_si); 185 /* 186 * Function: 187 * _soc_mn_phy_port_lane_info_init 188 * Purpose: 189 * Initialize the physical port lane information in the 190 * SW device information data structure. 191 * Parameters: 192 * unit - (IN) Unit number. 193 * Returns: 194 * SOC_E_XXX 195 * Note: 196 * Assumes SW data structure memory is valid. 197 */ 198 STATIC int 199 _soc_mn_phy_port_lane_info_init(int unit) 200 { 201 int i; 202 int tsc, pgw; 203 int blk, bindex; 204 int phy_port, phy_port_base; 205 206 /* Set information to invalid */ 207 for (phy_port = 0; phy_port < SOC_MAX_NUM_PORTS; phy_port++) { 208 MN_PHY_PORT(unit, phy_port).pipe = -1; 209 MN_PHY_PORT_LANE(unit, phy_port).pgw = -1; 210 MN_PHY_PORT_LANE(unit, phy_port).xlp = -1; 211 MN_PHY_PORT_LANE(unit, phy_port).port_index = -1; 212 } 213 214 for (phy_port = 0; phy_port < SOC_MAX_NUM_PORTS; phy_port++) { 215 216 /* Check for end of port list */ 217 if (SOC_PORT_BLOCK(unit, phy_port) < 0 && 218 SOC_PORT_BINDEX(unit, phy_port) < 0) { 219 break; 220 } 221 222 /* Skip internal ports */ 223 if ((phy_port == MN_PHY_PORT_CPU) || 224 (phy_port == MN_PHY_PORT_MACSEC) || 225 (phy_port == MN_PHY_PORT_LB)) { 226 continue; 227 } 228 229 /* Set lane information */ 230 for (i = 0; i < SOC_DRIVER(unit)->port_num_blktype; i++) { 231 /* Find PGW block */ 232 blk = SOC_PORT_IDX_BLOCK(unit, phy_port, i); 233 bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, i); 234 235 if ((blk < 0) || (bindex < 0)) { 236 continue; 237 } 238 239 /* Set PGW block information for lane */ 240 if (SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_PGW_CL) { 241 /* Get PGW, TSC and Port Index values */ 242 MN_PHY_PORT_LANE(unit, phy_port).pgw = 243 SOC_BLOCK_NUMBER(unit, blk); 244 MN_PHY_PORT_LANE(unit, phy_port).tsc = 245 bindex / MN_PORTS_PER_TSC; 246 MN_PHY_PORT_LANE(unit, phy_port).port_index = 247 bindex % MN_PORTS_PER_TSC; 248 } 249 250 /* Set port lane capabilites */ 251 if ((SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_XLPORT) || 252 (SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_XLPORTB0)) { 253 MN_PHY_PORT(unit, phy_port).lanes_valid = 254 MN_PHY_XLPORT_LANES_1; 255 if (bindex == 0) { 256 MN_PHY_PORT(unit, phy_port).lanes_valid |= 257 MN_PHY_XLPORT_LANES_2 | MN_PHY_XLPORT_LANES_4; 258 } else if (bindex == 2) { 259 MN_PHY_PORT(unit, phy_port).lanes_valid |= 260 MN_PHY_XLPORT_LANES_2; 261 } 262 } else if ((SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_CLPORT) || 263 (SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_CLG2PORT)) { 264 MN_PHY_PORT(unit, phy_port).lanes_valid = 265 MN_PHY_XLPORT_LANES_1; 266 if (bindex == 0) { 267 MN_PHY_PORT(unit, phy_port).lanes_valid |= 268 MN_PHY_XLPORT_LANES_2 | MN_PHY_XLPORT_LANES_4; 269 } else if (bindex == 2) { 270 MN_PHY_PORT(unit, phy_port).lanes_valid |= 271 MN_PHY_XLPORT_LANES_2; 272 } 273 } 274 275 if (SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_CXXPORT) { 276 MN_PHY_PORT(unit, phy_port).lanes_valid |= 277 MN_PHY_XLPORT_LANES_10 | MN_PHY_XLPORT_LANES_12; 278 } 279 280 } /* for port_num_blktype */ 281 282 } /* for phy_port */ 283 284 /* Set total number of physical ports in device */ 285 MN_INFO(unit)->phy_ports_max = phy_port; 286 287 /* 288 * Fill sisters ports 289 * This logic assumes a given physical layout in the device 290 */ 291 for (phy_port = 0; phy_port < MN_INFO(unit)->phy_ports_max;) { 292 293 if (MN_PHY_PORT_LANE(unit, phy_port).pgw == -1) { 294 phy_port++; 295 continue; 296 } 297 298 pgw = MN_PHY_PORT_LANE(unit, phy_port).pgw; 299 tsc = MN_PHY_PORT_LANE(unit, phy_port).tsc; 300 phy_port_base = phy_port; 301 while ((MN_PHY_PORT_LANE(unit, phy_port).pgw == pgw) && 302 (MN_PHY_PORT_LANE(unit, phy_port).tsc == tsc)) { 303 for (i = 0; i < MN_PORTS_PER_TSC; i++) { 304 MN_PHY_PORT(unit, phy_port).sisters_ports[i] = 305 phy_port_base + i; 306 } 307 phy_port++; 308 } 309 } 310 311 return SOC_E_NONE; 312 } 313 314 315 316 /* 317 * Function: 318 * _soc_mn_prio_mask_init 319 * Purpose: 320 * Initialize the packet priority to priority group mapping mask 321 * for physical ports in the SW device information data structure. 322 * Parameters: 323 * unit - (IN) Unit number. 324 * Returns: 325 * SOC_E_XXX 326 * Note: 327 * Assumes SW data structure memory is valid. 328 */ 329 STATIC int 330 _soc_mn_prio_mask_init(int unit) 331 { 332 int phy_port; 333 uint16 prio_mask; 334 335 for (phy_port = 0; phy_port < SOC_MAX_NUM_PORTS; phy_port++) { 336 /* Skip ports not addressable */ 337 if (!MN_PHY_PORT_ADDRESSABLE(unit, phy_port)) { 338 continue; 339 } 340 341 prio_mask = 0xffff; 342 /* 343 * Check per physical port property first. 344 * If property is not available on physical port, 345 * use property on logical port. 346 */ 347 348 /* 349 * TBD once SOC property is approved. 350 * if (property_physical) { 351 * ... 352 * } else { 353 * ... logical property 354 * } 355 */ 356 357 #if 0 358 /* Set based on logical port property */ 359 port = si->port_p2l_mapping[phy_port]; 360 if (port != -1) { 361 SOC_IF_ERROR_RETURN 362 (soc_mn_get_prio_map(unit, port, &prio_mask)); 363 } 364 #endif 365 366 MN_PHY_PORT(unit, phy_port).prio_mask = prio_mask; 367 } 368 369 return SOC_E_NONE; 370 } 371 372 373 /* 374 * Function: 375 * _soc_mn_flex_enable_init 376 * Purpose: 377 * Initialize the flex enable capability 378 * for physical ports in the SW device information data structure. 379 * 380 * The flexing capabality on a port is defined based on 381 * these SOC properties: 382 * 383 * (1) 'portmap' with ':i' option (inactive ports) 384 * When defined, this allows flexing in the entire device. 385 * This sets MN_INFO(unit)->flex_legacy 386 * 387 * (2) 'port_flex_enable' 388 * This SOC property is set per TSC. 389 * When set, FlexPort operations are allowed in the TSC. 390 * Property should be specified in the base physical port of a TSC. 391 * This sets MN_PHY_PORT(unit, phy_port).flex 392 * 393 * The defined SDK behaviour is that if both, (1) and (2) are true, 394 * (1) takes precedence. 395 * 396 * Parameters: 397 * unit - (IN) Unit number. 398 * Returns: 399 * SOC_E_XXX 400 * Note: 401 * Assumes SW data structure memory is valid. 402 * Assumes _soc_monterey_phy_port_lane_info_init() has been called. 403 */ 404 STATIC int 405 _soc_mn_flex_enable_init(int unit) 406 { 407 int phy_port; 408 int port_base; 409 int flex; 410 int i; 411 soc_info_t *si = &SOC_INFO(unit); 412 413 /* 414 * This field is set in SOC_INFO if inactive ports are specified 415 * in the SOC property 'portmap' with the ':i' option. 416 */ 417 MN_INFO(unit)->flex_legacy = si->flex_eligible; 418 419 for (phy_port = 0; phy_port < SOC_MAX_NUM_PORTS;) { 420 /* Skip ports not addressable, CPU and Loopback ports */ 421 if (!MN_PHY_PORT_ADDRESSABLE(unit, phy_port) || 422 (phy_port == MN_PHY_PORT_CPU) || 423 (phy_port == MN_PHY_PORT_MACSEC) || 424 (phy_port == MN_PHY_PORT_LB)) { 425 phy_port++; 426 continue; 427 } 428 429 /* Check for flex ability in 'port_flex_enable' SOC property */ 430 port_base = MN_PHY_PORT(unit, phy_port).sisters_ports[0]; 431 flex = soc_property_phys_port_get(unit, port_base, 432 spn_PORT_FLEX_ENABLE, 0); 433 /* 434 * Set flex ability in all ports in the TSC based on 435 * property set on base port in TSC 436 * 437 * Assumes Apache specific physical device layout 438 */ 439 for (i = 0; i < MN_PORTS_PER_TSC; i++) { 440 MN_PHY_PORT(unit, phy_port).flex = flex; 441 phy_port++; 442 if (phy_port >= SOC_MAX_NUM_PORTS) { 443 break; 444 } 445 } 446 } 447 448 return SOC_E_NONE; 449 } 450 451 /* 452 * Function: 453 * soc_mn_soc_info_mn_misc_t_init 454 * Purpose: 455 * Initialize soc_info_mn_misc_t structure by the current SOC_INFO(unit). 456 * Parameters: 457 * unit - StrataSwitch Unit #. 458 * si_m - soc_info_misc data 459 * Note: 460 * port_speed is initialized by si->port_speed_max 461 */ 462 STATIC void 463 _soc_mn_soc_info_mn_misc_t_init(int unit, soc_info_mn_misc_t *si_m) 464 { 465 soc_info_t *si = &SOC_INFO(unit); 466 int i; 467 int logic_port; 468 int phy_port; 469 int speed; 470 sal_memset(si_m, 0, sizeof(*si_m)); 471 472 /* Get current information */ 473 for (i = 0; i < SOC_MAX_NUM_PORTS; i++) { 474 si_m->port_l2p_mapping[i] = si->port_l2p_mapping[i]; 475 si_m->port_p2l_mapping[i] = si->port_p2l_mapping[i]; 476 si_m->port_speed_max[i] = si->port_speed_max[i]; 477 si_m->port_num_lanes[i] = si->port_num_lanes[i]; 478 si_m->port_speed[i] = -1; 479 si_m->port_encap[i] = -1; 480 481 logic_port = i; 482 phy_port = si->port_l2p_mapping[logic_port]; 483 484 /* Skip ports not defined, LB, CPU, etc. */ 485 if (!SOC_PORT_ADDRESSABLE(unit, logic_port) || 486 !((phy_port >= 0) && (phy_port <= SOC_MAX_NUM_PORTS)) || 487 IS_LB_PORT(unit, logic_port) || 488 IS_MACSEC_PORT(unit, logic_port) || 489 IS_CPU_PORT (unit, logic_port)) { 490 continue; 491 } 492 493 /* Get current port speed */ 494 speed = si->port_speed_max[logic_port]; 495 si_m->port_speed[logic_port] = speed; 496 497 /* 498 * Get encapsulation mode 499 * 500 * Validate need to differentiate between HG and non-HG modes, 501 * so using SOC_ENCAP_HIGIG2 and SOC_ENCAP_IEEE will suffice 502 * to indicate HG vs non-HG. 503 */ 504 if (IS_HG_PORT(unit, logic_port)) { 505 si_m->port_encap[logic_port] = SOC_ENCAP_HIGIG2; 506 } else if (IS_CPRI_PORT(unit, logic_port)) { 507 si_m->port_encap[logic_port] = SOC_ENCAP_CPRI; 508 } else if (IS_RSVD4_PORT(unit, logic_port)) { 509 si_m->port_encap[logic_port] = SOC_ENCAP_RSVD4; 510 } else { 511 si_m->port_encap[logic_port] = SOC_ENCAP_IEEE; 512 } 513 } 514 si_m->bandwidth = si->bandwidth; 515 SOC_PBMP_ASSIGN(si_m->oversub_pbm, si->oversub_pbm); 516 SOC_PBMP_ASSIGN(si_m->disabled_bitmap, si->all.disabled_bitmap); 517 518 return; 519 } 520 521 /* 522 * Function: 523 * soc_mn_port_oversub_get 524 * Purpose: 525 * Get the Oversub for given port. 526 * Parameters: 527 * unit - (IN) Unit number. 528 * phy_port - (IN) Physical port number, used 529 * for NEW property. 530 * logical_port - (IN) Logical port number. 531 * This is used for LEGACY property in 532 * case the NEW property is not present. 533 * oversub - (OUT) Returns TRUE if port is set for Oversub, 534 * FALSE otherwise. 535 * Returns: 536 * SOC_E_XXX 537 * Notes: 538 * Assumes port is valid. 539 */ 540 STATIC int 541 soc_mn_port_oversub_get(int unit, int phy_port, soc_port_t logical_port, int *oversub) 542 { 543 soc_pbmp_t pbmp; 544 int oversub_mode = 0; 545 546 SOC_PBMP_CLEAR(pbmp); 547 548 oversub_mode = soc_property_get(unit, spn_OVERSUBSCRIBE_MODE, 0); 549 550 if (oversub_mode == 0) { 551 *oversub = 0; 552 } else if (oversub_mode == 1) { 553 *oversub = 1; 554 } else if (oversub_mode == 2) { 555 /* 556 * Check per physical port property first. 557 * If property is not available on physical port, 558 * use property on logical port. 559 */ 560 *oversub = soc_property_phys_port_get(unit, phy_port, 561 spn_PORT_OVERSUBSCRIBE, 0xFFFFFFFF); 562 if (*oversub == 0xFFFFFFFF) { 563 *oversub = 0; 564 if (logical_port != -1) { 565 pbmp = soc_property_get_pbmp(unit, spn_PBMP_OVERSUBSCRIBE, 0); 566 if (SOC_PBMP_MEMBER(pbmp, logical_port)) { 567 *oversub = 1; 568 } 569 } 570 } 571 } 572 return SOC_E_NONE; 573 } 574 575 /* 576 * Function: 577 * _soc_mn_post_soc_info_get 578 * Purpose: 579 * Get the post FlexPort SOC INFO port information (subset). 580 * 581 * Certain validations need the post FlexPort information for all 582 * the ports at the same time (mostly contained in SOC_INFO). 583 * The global SOC_INFO is updated after the validation phase so 584 * the information is not available yet. 585 * Parameters: 586 * unit - (IN) Unit number. 587 * nport - (IN) Number of elements in array resource. 588 * resource - (IN/OUT) Port Resource FlexPort configuration. 589 * post_si - (OUT) Returns the new SOC port information 590 * after FlexPort. Note that this does NOT 591 * modify the global SOC_INFO SW database. 592 * Returns: 593 * SOC_E_XXX 594 * Note: 595 * This function does NOT modify the global SOC_INFO SW database, 596 * the post information is returned in the local argument. 597 * 598 * Assumes values in resource are valid (logical port, etc.) 599 */ 600 STATIC int 601 _soc_mn_post_soc_info_get(int unit, 602 int nport, 603 soc_port_resource_t *resource, 604 soc_info_mn_misc_t *post_si) 605 { 606 int rv; 607 soc_info_t *si = &SOC_INFO(unit); 608 soc_port_resource_t *pr; 609 int i; 610 int oversub; 611 int logic_port; 612 int phy_port; 613 614 _soc_mn_soc_info_mn_misc_t_init(unit, post_si); 615 616 /* First process 'delete' mappings */ 617 for (i = 0, pr = &resource[0]; 618 (i < nport) && (pr->physical_port == -1); 619 i++, pr++) { 620 logic_port = pr->logical_port; 621 phy_port = si->port_l2p_mapping[logic_port]; 622 623 if (pr->flags & SOC_PORT_RESOURCE_I_MAP) { 624 SOC_PBMP_PORT_ADD(post_si->disabled_bitmap, logic_port); 625 continue; 626 } 627 628 post_si->port_l2p_mapping[logic_port] = -1; 629 if (phy_port >= 0) { 630 post_si->port_p2l_mapping[phy_port] = -1; 631 } 632 post_si->port_speed_max[logic_port] = -1; 633 post_si->port_speed[logic_port] = -1; 634 post_si->port_num_lanes[logic_port] = -1; 635 post_si->port_encap[logic_port] = -1; 636 637 SOC_PBMP_PORT_REMOVE(post_si->oversub_pbm, logic_port); 638 SOC_PBMP_PORT_REMOVE(post_si->disabled_bitmap, logic_port); 639 } 640 641 /* Continue with 'add' mappings in rest of array */ 642 for (; i < nport; i++, pr++) { 643 logic_port = pr->logical_port; 644 phy_port = pr->physical_port; 645 646 post_si->port_l2p_mapping[logic_port] = phy_port; 647 post_si->port_p2l_mapping[phy_port] = logic_port; 648 post_si->port_speed_max[logic_port] = pr->speed; 649 post_si->port_speed[logic_port] = pr->speed; 650 post_si->port_num_lanes[logic_port] = pr->num_lanes; 651 post_si->port_encap[logic_port] = pr->encap; 652 653 rv = soc_mn_port_oversub_get(unit, phy_port, logic_port, &oversub); 654 if (SOC_FAILURE(rv)) { 655 LOG_ERROR(BSL_LS_SOC_PORT, 656 (BSL_META_U(unit, 657 "Cannot get oversubscription mode, " 658 "logical_port=%d physical_port=%d rv=%d\n"), 659 logic_port, phy_port, rv)); 660 return SOC_E_INTERNAL; 661 } 662 if (oversub) { 663 SOC_PBMP_PORT_ADD(post_si->oversub_pbm, logic_port); 664 } else { 665 SOC_PBMP_PORT_REMOVE(post_si->oversub_pbm, logic_port); 666 } 667 668 SOC_PBMP_PORT_REMOVE(post_si->disabled_bitmap, logic_port); 669 } 670 671 672 LOG_VERBOSE(BSL_LS_SOC_PORT, 673 (BSL_META_U(unit, 674 "\n--- SOC INFO Post FlexPort Data ---\n"))); 675 LOG_VERBOSE(BSL_LS_SOC_PORT, 676 (BSL_META_U(unit, 677 "Index L2P P2L MaxSpeed Speed " 678 "Encap Ovs Disabled\n"))); 679 for (i = 0; i < SOC_MAX_NUM_PORTS; i++) { 680 if ((post_si->port_l2p_mapping[i] == -1) && 681 (post_si->port_p2l_mapping[i] == -1)) { 682 continue; 683 } 684 if (!MN_PHY_PORT_ADDRESSABLE(unit, i)) { 685 continue; 686 } 687 LOG_VERBOSE(BSL_LS_SOC_PORT, 688 (BSL_META_U(unit, 689 " %3d %3d %3d %6d %6d " 690 "%3s %1d %1d\n"), 691 i, 692 post_si->port_l2p_mapping[i], 693 post_si->port_p2l_mapping[i], 694 post_si->port_speed_max[i], 695 post_si->port_speed[i], 696 (post_si->port_encap[i] == SOC_ENCAP_HIGIG2) ? 697 "HG" : "!HG", 698 SOC_PBMP_MEMBER(post_si->oversub_pbm, i) ? 1 : 0, 699 SOC_PBMP_MEMBER(post_si->disabled_bitmap, i) ? 1 : 0)); 700 } 701 LOG_VERBOSE(BSL_LS_SOC_PORT, 702 (BSL_META_U(unit, 703 "\n"))); 704 705 return SOC_E_NONE; 706 } 707 708 709 /* 710 * Function: 711 * _soc_mn_speed_valid_init 712 * Purpose: 713 * Initialize the SW device information data structure 714 * for the valid port rates according to the number of serdes lanes. 715 * Parameters: 716 * unit - (IN) Unit number. 717 * Returns: 718 * SOC_E_XXX 719 * Note: 720 * - Assumes SW data structure memory is valid. 721 */ 722 STATIC int 723 _soc_mn_speed_valid_init(int unit) 724 { 725 int lanes; 726 uint32 speed_valid; 727 728 /* Set port rate based on number of serdes lanes */ 729 for (lanes = 0; lanes <= SOC_PORT_RESOURCE_LANES_MAX; lanes++) { 730 731 if (lanes == 1) { 732 speed_valid = 733 MN_PHY_PORT_RATE_1 | 734 MN_PHY_PORT_RATE_2_5 | 735 MN_PHY_PORT_RATE_5 | 736 MN_PHY_PORT_RATE_10 | 737 MN_PHY_PORT_RATE_20 | 738 MN_PHY_PORT_RATE_11 | 739 MN_PHY_PORT_RATE_21 | 740 MN_PHY_PORT_RATE_25 | 741 MN_PHY_PORT_RATE_27 ; 742 743 } else if (lanes == 2) { 744 speed_valid = 745 MN_PHY_PORT_RATE_10 | 746 MN_PHY_PORT_RATE_11 | 747 MN_PHY_PORT_RATE_20 | 748 MN_PHY_PORT_RATE_21 | 749 MN_PHY_PORT_RATE_25 | 750 MN_PHY_PORT_RATE_40 | 751 MN_PHY_PORT_RATE_42 | 752 MN_PHY_PORT_RATE_50 | 753 MN_PHY_PORT_RATE_53 ; 754 755 } else if (lanes == 4) { 756 speed_valid = 757 MN_PHY_PORT_RATE_10 | 758 MN_PHY_PORT_RATE_20 | 759 MN_PHY_PORT_RATE_40 | 760 MN_PHY_PORT_RATE_11 | 761 MN_PHY_PORT_RATE_42 | 762 MN_PHY_PORT_RATE_21 | 763 MN_PHY_PORT_RATE_25 | 764 MN_PHY_PORT_RATE_100 | 765 MN_PHY_PORT_RATE_106; 766 767 } else if (lanes == 10) { 768 speed_valid = 769 MN_PHY_PORT_RATE_100 | 770 MN_PHY_PORT_RATE_106; 771 772 } else if (lanes == 12) { 773 speed_valid = 774 MN_PHY_PORT_RATE_127; 775 776 } else { 777 speed_valid = 0; 778 } 779 780 MN_INFO(unit)->speed_valid[lanes] = speed_valid; 781 } 782 783 return SOC_E_NONE; 784 } 785 786 787 /* 788 * Function: 789 * _soc_mn_ports_pipe_max_init 790 * Purpose: 791 * Initialize the SW device information data structure for: 792 * - speed_max : Maximum allowed port speed in device. 793 * - port_max : Maximum logical port number. 794 * 795 * 796 * Parameters: 797 * unit - (IN) Unit number. 798 * Returns: 799 * SOC_E_XXX 800 * Note: 801 * - Assumes SW data structure memory is valid. 802 * - Assumes SOC information is initialized. 803 */ 804 STATIC int 805 _soc_mn_ports_pipe_max_init(int unit) 806 { 807 808 int speed_max; 809 810 /* Get speed from SOC property */ 811 speed_max = soc_property_get(unit, spn_PORT_FLEX_SPEED_MAX, 812 MN_FLEX_SPEED_MAX_DEFAULT); 813 MN_INFO(unit)->speed_max = speed_max; 814 MN_INFO(unit)->port_max = 66; 815 return SOC_E_NONE; 816 } 817 818 819 /* 820 * Function: 821 * _soc_mn_mmu_lossless_init 822 * Purpose: 823 * Initialize the SW device information data structure 824 * for the MMU lossless. 825 * Parameters: 826 * unit - (IN) Unit number. 827 * Returns: 828 * SOC_E_XXX 829 * Note: 830 * Assumes SW data structure memory is valid. 831 */ 832 STATIC int 833 _soc_mn_mmu_lossless_init(int unit) 834 { 835 MN_INFO(unit)->mmu_lossless = 836 soc_property_get(unit, spn_MMU_LOSSLESS, 0); 837 838 return SOC_E_NONE; 839 } 840 841 842 /* 843 * Function: 844 * soc_mn_phy_info_init 845 * Purpose: 846 * Initialize the main SW device information data structure. 847 * 848 * It populates the information of the device that are relevant 849 * to the physical port interface such as, 850 * PGW, XLP, port index, lane capabilities, speed, etc. 851 * 852 * Information is derived from the HW port design specification 853 * and configuration properties on a physical port. 854 * 855 * This routine does not modify any HW. It only 856 * modifies the SW data structure. 857 * Parameters: 858 * unit - (IN) Unit number. 859 * Returns: 860 * SOC_E_XXX 861 * Notes: 862 * - Assumes SOC Control information has been initialized. 863 * - Must be called after the AP port configuration init routine 864 * soc_monterey_port_config_init(). 865 */ 866 int 867 soc_mn_phy_info_init(int unit) 868 { 869 int phy_port; /* Physical port */ 870 int lanes; /* Serdes lane */ 871 872 /* Allocate memory for main SW data structure */ 873 if (mn_info[unit] == NULL) { 874 mn_info[unit] = sal_alloc(sizeof(mn_info_t), "mn_info"); 875 if (mn_info[unit] == NULL) { 876 LOG_ERROR(BSL_LS_SOC_PORT, 877 (BSL_META_U(unit, 878 "Unable to allocate memory for " 879 "monterey_info"))); 880 return SOC_E_MEMORY; 881 } 882 } 883 884 /* Clear data structure */ 885 sal_memset(mn_info[unit], 0, sizeof(mn_info_t)); 886 887 /* Initialize device information */ 888 SOC_IF_ERROR_RETURN(_soc_mn_phy_port_lane_info_init(unit)); 889 890 SOC_IF_ERROR_RETURN(_soc_mn_prio_mask_init(unit)); 891 892 SOC_IF_ERROR_RETURN(_soc_mn_flex_enable_init(unit)); 893 894 SOC_IF_ERROR_RETURN(_soc_mn_speed_valid_init(unit)); 895 896 SOC_IF_ERROR_RETURN(_soc_mn_ports_pipe_max_init(unit)); 897 898 SOC_IF_ERROR_RETURN(_soc_mn_mmu_lossless_init(unit)); 899 900 /* Debug output */ 901 LOG_VERBOSE(BSL_LS_SOC_PORT, 902 (BSL_META_U(unit, 903 "Physical ports max: %d speed_max=%d " 904 "port_max=%d mmu_lossless=%d flex_legacy=%d\n\n"), 905 MN_INFO(unit)->phy_ports_max, 906 MN_INFO(unit)->speed_max, 907 MN_INFO(unit)->port_max, 908 MN_INFO(unit)->mmu_lossless, 909 MN_INFO(unit)->flex_legacy)); 910 911 for (phy_port = 0; phy_port < MN_INFO(unit)->phy_ports_max; phy_port++) { 912 LOG_VERBOSE(BSL_LS_SOC_PORT, 913 (BSL_META_U(unit, 914 "Phy port=%d pgw=%d tsc=%d index=%d " 915 "valid=0x%x " 916 "prio_mask=0x%x flex=%d\n"), 917 phy_port, 918 MN_PHY_PORT_LANE(unit, phy_port).pgw, 919 MN_PHY_PORT_LANE(unit, phy_port).tsc, 920 MN_PHY_PORT_LANE(unit, phy_port).port_index, 921 MN_PHY_PORT(unit, phy_port).lanes_valid, 922 MN_PHY_PORT(unit, phy_port).prio_mask, 923 MN_PHY_PORT(unit, phy_port).flex)); 924 LOG_VERBOSE(BSL_LS_SOC_PORT, 925 (BSL_META_U(unit, 926 " sisters_ports={%d,%d,%d,%d}\n"), 927 MN_PHY_PORT(unit, phy_port).sisters_ports[0], 928 MN_PHY_PORT(unit, phy_port).sisters_ports[1], 929 MN_PHY_PORT(unit, phy_port).sisters_ports[2], 930 MN_PHY_PORT(unit, phy_port).sisters_ports[3])); 931 932 } 933 934 for (lanes = 0; lanes <= SOC_PORT_RESOURCE_LANES_MAX; lanes++) { 935 LOG_VERBOSE(BSL_LS_SOC_PORT, 936 (BSL_META_U(unit, 937 "Serdes lane=%d port_rate=0x%x\n"), 938 lanes, MN_INFO(unit)->speed_valid[lanes])); 939 } 940 941 return SOC_E_NONE; 942 } 943 944 /* 945 * Function: 946 * soc_mn_phy_info_deinit 947 * Purpose: 948 * Free mn_info data structure. 949 * 950 * Parameters: 951 * unit - (IN) Unit number. 952 * Returns: 953 * SOC_E_XXX 954 */ 955 int 956 soc_mn_phy_info_deinit(int unit) 957 { 958 /* Allocate memory for main SW data structure */ 959 if (mn_info[unit] != NULL) { 960 sal_free(mn_info[unit]); 961 mn_info[unit] = NULL; 962 } 963 964 return SOC_E_NONE; 965 } 966 967 968 969 970 /* 971 * Function: 972 * _soc_mn_phy_port_flex_valid 973 * Purpose: 974 * Check that FlexPort operation is valid on given physical port. 975 * Parameters: 976 * unit - (IN) Unit number. 977 * phy_port - (IN) Physical port number. 978 * Returns: 979 * SOC_E_XXX 980 */ 981 STATIC int 982 _soc_mn_phy_port_flex_valid(int unit, int phy_port) 983 { 984 if (!MN_INFO(unit)->flex_legacy && 985 !MN_PHY_PORT(unit, phy_port).flex) { 986 LOG_ERROR(BSL_LS_SOC_PORT, 987 (BSL_META_U(unit, 988 "FlexPort operation is not enabled on " 989 "physical port %d\n"), 990 phy_port)); 991 return SOC_E_CONFIG; 992 } 993 994 return SOC_E_NONE; 995 } 996 997 998 /* 999 * Function: 1000 * soc_monterey_is_flex_enable 1001 * Purpose: 1002 * Check that FlexPort operation is valid on the unit. 1003 * Checks for both legacy and new flex operation. 1004 * Parameters: 1005 * unit - (IN) Unit number. 1006 * Returns: 1007 * TRUE or FALSE. 1008 */ 1009 int 1010 soc_monterey_is_flex_enable(int unit) 1011 { 1012 int phy_port, num_phy_port; 1013 soc_info_t *si = &SOC_INFO(unit); 1014 1015 num_phy_port = 130; 1016 if (si->flex_eligible) { 1017 return TRUE; 1018 } else { 1019 for (phy_port = 0; phy_port < num_phy_port; 1020 phy_port++) { 1021 if (soc_property_phys_port_get(unit, 1022 phy_port, 1023 spn_PORT_FLEX_ENABLE, 0)) { 1024 return TRUE; 1025 } 1026 } 1027 } 1028 return FALSE; 1029 } 1030 1031 /* 1032 * Function: 1033 * soc_monterey_subsidiary_ports_get 1034 * Purpose: 1035 * Given a controlling port, return a set of ancillary ports 1036 * belonging to the group (port block) that can be configured to operate 1037 * either as a single high-speed port or multiple low speed ports. If the input 1038 * port is not a controlling port, SOC_E_PORT error will be returned. 1039 * Parameters: 1040 * unit - (IN) Unit number. 1041 * port - (IN) Port 1042 * pbmp - (OUT) Set of ancillary ports 1043 * Returns: 1044 * SOC_E_XXX 1045 */ 1046 soc_error_t 1047 soc_monterey_subsidiary_ports_get(int unit, soc_port_t port, soc_pbmp_t *pbmp) 1048 { 1049 soc_info_t *si = &SOC_INFO(unit); 1050 soc_port_t phy_port_base, phy_port; 1051 soc_pbmp_t pbm; 1052 int max_subport; 1053 1054 if (!SOC_PORT_VALID(unit, port) || IS_CPU_PORT(unit, port) || 1055 IS_LB_PORT(unit, port) || IS_MACSEC_PORT(unit, port)) { 1056 /* CPU, LB, RDB ports do not support flexport */ 1057 return SOC_E_PORT; 1058 } 1059 1060 phy_port = si->port_l2p_mapping[port]; 1061 phy_port_base = PORT_BLOCK_BASE_PORT(port); 1062 1063 /* Only lane 0 and lane 2 of a PM can be controlling ports */ 1064 if ((phy_port_base != phy_port) && ((phy_port_base + 2) != phy_port)) { 1065 /* Not a controlling port */ 1066 return SOC_E_PORT; 1067 } 1068 max_subport = phy_port + (4 - ((phy_port - 1) % 4)); 1069 SOC_PBMP_CLEAR(pbm); 1070 for (; phy_port < max_subport; phy_port++) { 1071 if (si->port_p2l_mapping[phy_port] == -1) { 1072 continue; 1073 } 1074 SOC_PBMP_PORT_ADD(pbm, si->port_p2l_mapping[phy_port]); 1075 } 1076 SOC_PBMP_ASSIGN(*pbmp, pbm); 1077 1078 return SOC_E_NONE; 1079 } 1080 1081 /* 1082 * Function: 1083 * soc_monterey_port_lane_config_get 1084 * Purpose: 1085 * Get the mode lane configuration for given physical port. 1086 * This is only applicable on 100GE ports. 1087 * Parameters: 1088 * unit - (IN) Unit number. 1089 * phy_port - (IN) Physical port number. 1090 * mode_lane - (OUT) Returns the lane distribution for given port 1091 * SOC_LANE_CONFIG_100G_XYZ 1092 * found - (OUT) Returns TRUE if property is specified, 1093 * FALSE if property is not found. 1094 * Returns: 1095 * SOC_E_XXX 1096 * Notes: 1097 * Assumes physical port is valid. 1098 */ 1099 int 1100 soc_monterey_port_lane_config_get(int unit, int phy_port, int *mode_lane, 1101 int *found) 1102 { 1103 char *str; 1104 1105 /* 1106 * The PHY_MLD_MAP SOC property (Multi Lane Distribution) value 1107 * is interpreted as follows: 1108 * 1109 * Each nibble-index is the TSC lane number (0..11) and 1110 * the nibble value is the 100GE port lane number. 1111 * A nibble value of "f" indicates the TSC lane is not used. 1112 * 1113 * Supported 100GE lane distributions: 1114 * TSC 100g 4-4-2 mode: phy_mld_map{x} = 0xff9876543210 1115 * TSC 100g 3-4-3 mode: phy_mld_map{x} = 0xf9876543f210 1116 * TSC 100g 2-4-4 mode: phy_mld_map{x} = 0x98765432ff10 1117 * 1118 * Default is 4-4-2 1119 * This matches Apache port init soc_monterey_port_config_init(). 1120 */ 1121 str = soc_property_phy_get_str(unit, phy_port, -1, -1, -1, 1122 spn_PHY_MLD_MAP); 1123 1124 /* Return default if property is not found */ 1125 if (str == NULL) { 1126 *mode_lane = SOC_LANE_CONFIG_100G_DEFAULT; 1127 *found = FALSE; 1128 return SOC_E_NONE; 1129 } 1130 1131 *found = TRUE; 1132 if (!sal_strcasecmp(str, MONTEREY_100GE_MLD_MAP_4_4_2_STR)) { 1133 *mode_lane = SOC_LANE_CONFIG_100G_4_4_2; 1134 } else if (!sal_strcasecmp(str, MONTEREY_100GE_MLD_MAP_3_4_3_STR)) { 1135 *mode_lane = SOC_LANE_CONFIG_100G_3_4_3; 1136 } else if (!sal_strcasecmp(str, MONTEREY_100GE_MLD_MAP_2_4_4_STR)) { 1137 *mode_lane = SOC_LANE_CONFIG_100G_2_4_4; 1138 } else { 1139 LOG_WARN(BSL_LS_SOC_PORT, 1140 (BSL_META_U(unit, 1141 "Physical Port %d: " 1142 "Invalid lane configuration.\n" 1143 "Using default lane mode.\n"), 1144 phy_port)); 1145 *mode_lane = SOC_LANE_CONFIG_100G_DEFAULT; 1146 *found = FALSE; 1147 } 1148 1149 return SOC_E_NONE; 1150 } 1151 1152 /* 1153 * Function: 1154 * soc_monterey_port_autoneg_core_get 1155 * Purpose: 1156 * Get the autoneg configuration for given physical port. 1157 * This is only applicable on 100GE ports. 1158 * Parameters: 1159 * unit - (IN) Unit number. 1160 * phy_port - (IN) Physical port number. 1161 * an_core - (OUT) Returns the an_core index for given port 1162 * found - (OUT) Returns TRUE if property is specified, 1163 * FALSE if property is not found. 1164 * Returns: 1165 * SOC_E_XXX 1166 * Notes: 1167 * Assumes physical port is valid. 1168 */ 1169 int 1170 soc_monterey_port_autoneg_core_get(int unit, int phy_port, int *an_core, 1171 int *found) 1172 { 1173 *found = TRUE; 1174 *an_core = soc_property_phy_get(unit, phy_port, -1, -1, -1, 1175 spn_PHY_AN_CORE_NUM, 1176 -1); 1177 if (*an_core < 0 || *an_core > 2) { 1178 *an_core = SOC_LANE_CONFIG_100G_AN_CORE_DEFAULT; 1179 *found = FALSE; 1180 } 1181 1182 return SOC_E_NONE; 1183 } 1184 1185 1186 /* 1187 * Function: 1188 * _soc_mn_speed_valid 1189 * Purpose: 1190 * Check that given speed is valid for the number of 1191 * serdes lanes. 1192 * Parameters: 1193 * unit - (IN) Unit number. 1194 * phy_port - (IN) Physical port number. 1195 * lanes - (IN) Number of PHY lanes. 1196 * speed - (IN) Port rate to check. 1197 * Returns: 1198 * SOC_E_XXX 1199 */ 1200 STATIC int 1201 _soc_mn_speed_valid(int unit, int phy_port, int lanes, int speed) 1202 { 1203 uint32 speed_mask = 0; 1204 int speed_max; 1205 1206 SOC_IF_ERROR_RETURN 1207 (soc_mn_port_resource_speed_max_get(unit, &speed_max)); 1208 1209 if (speed > speed_max) { 1210 LOG_ERROR(BSL_LS_SOC_PORT, 1211 (BSL_META_U(unit, 1212 "Invalid speed configuration for " 1213 "physical_port=%d, speed=%d, max=%d\n"), 1214 phy_port, speed, speed_max)); 1215 return SOC_E_CONFIG; 1216 } 1217 1218 if (lanes == 1) { 1219 switch (speed) { 1220 case 10: 1221 case 100: 1222 speed_mask = PORT_IS_FALCON(phy_port) ? 0 : MN_PHY_PORT_RATE_1; 1223 break; 1224 case 1000: 1225 speed_mask = MN_PHY_PORT_RATE_1; 1226 break; 1227 case 2500: 1228 speed_mask = MN_PHY_PORT_RATE_2_5; 1229 break; 1230 case 5000: 1231 speed_mask = MN_PHY_PORT_RATE_5; 1232 break; 1233 case 10000: 1234 speed_mask = MN_PHY_PORT_RATE_10; 1235 break; 1236 case 11000: 1237 speed_mask = MN_PHY_PORT_RATE_11; 1238 break; 1239 case 25000: 1240 speed_mask = PORT_IS_FALCON(phy_port) ? MN_PHY_PORT_RATE_25 : 0; 1241 break; 1242 case 27000: 1243 speed_mask = PORT_IS_FALCON(phy_port) ? MN_PHY_PORT_RATE_27 : 0; 1244 break; 1245 } 1246 } else if (lanes == 2) { 1247 switch (speed) { 1248 case 10000: 1249 speed_mask = PORT_IS_FALCON(phy_port) ? 0 : MN_PHY_PORT_RATE_10; 1250 break; 1251 case 11000: 1252 speed_mask = PORT_IS_FALCON(phy_port) ? 0 : MN_PHY_PORT_RATE_11; 1253 break; 1254 case 20000: 1255 speed_mask = MN_PHY_PORT_RATE_20; 1256 break; 1257 case 21000: 1258 speed_mask = MN_PHY_PORT_RATE_21; 1259 break; 1260 case 40000: 1261 speed_mask = PORT_IS_FALCON(phy_port) ? MN_PHY_PORT_RATE_40 : 0; 1262 break; 1263 case 42000: 1264 speed_mask = PORT_IS_FALCON(phy_port) ? MN_PHY_PORT_RATE_42 : 0; 1265 break; 1266 case 50000: 1267 speed_mask = PORT_IS_FALCON(phy_port) ? MN_PHY_PORT_RATE_50 : 0; 1268 break; 1269 case 53000: 1270 speed_mask = PORT_IS_FALCON(phy_port) ? MN_PHY_PORT_RATE_53 : 0; 1271 break; 1272 } 1273 } else if (lanes == 4) { 1274 switch (speed) { 1275 case 10000: 1276 speed_mask = PORT_IS_FALCON(phy_port) ? 0 : MN_PHY_PORT_RATE_10; 1277 break; 1278 case 11000: 1279 speed_mask = PORT_IS_FALCON(phy_port) ? 0 : MN_PHY_PORT_RATE_11; 1280 break; 1281 case 20000: 1282 speed_mask = PORT_IS_FALCON(phy_port) ? 0 : MN_PHY_PORT_RATE_20; 1283 break; 1284 case 21000: 1285 speed_mask = PORT_IS_FALCON(phy_port) ? 0 : MN_PHY_PORT_RATE_21; 1286 break; 1287 case 25000: 1288 speed_mask = PORT_IS_FALCON(phy_port) ? 0 : MN_PHY_PORT_RATE_25; 1289 break; 1290 case 40000: 1291 speed_mask = MN_PHY_PORT_RATE_40; 1292 break; 1293 case 42000: 1294 speed_mask = MN_PHY_PORT_RATE_42; 1295 break; 1296 case 100000: 1297 speed_mask = PORT_IS_FALCON(phy_port) ? MN_PHY_PORT_RATE_100 : 0; 1298 break; 1299 case 106000: 1300 speed_mask = PORT_IS_FALCON(phy_port) ? MN_PHY_PORT_RATE_106 : 0; 1301 break; 1302 } 1303 } 1304 if (!(MN_INFO(unit)->speed_valid[lanes] & speed_mask)) { 1305 LOG_ERROR(BSL_LS_SOC_PORT, 1306 (BSL_META_U(unit, 1307 "Invalid speed configuration for " 1308 "physical_port=%d, speed=%d\n"), 1309 phy_port, speed)); 1310 return SOC_E_CONFIG; 1311 } 1312 1313 return SOC_E_NONE; 1314 } 1315 1316 1317 /* 1318 * Function: 1319 * _soc_mn_phy_port_lanes_valid 1320 * Purpose: 1321 * Check that given lane setting is valid for physical port. 1322 * Parameters: 1323 * unit - (IN) Unit number. 1324 * port - (IN) Base physical port. 1325 * lanes - (IN) Number of PHY lanes. 1326 * Returns: 1327 * SOC_E_XXX 1328 */ 1329 STATIC int 1330 _soc_mn_phy_port_lanes_valid(int unit, int phy_port, int lanes) 1331 { 1332 uint32 lane_mask = 0; 1333 1334 if (lanes == 1) { 1335 lane_mask = MN_PHY_XLPORT_LANES_1; 1336 } else if (lanes == 2) { 1337 lane_mask = MN_PHY_XLPORT_LANES_2; 1338 } else if (lanes == 4) { 1339 lane_mask = MN_PHY_XLPORT_LANES_4; 1340 } else if (lanes == 10) { 1341 lane_mask = MN_PHY_XLPORT_LANES_10; 1342 } else if (lanes == 12) { 1343 lane_mask = MN_PHY_XLPORT_LANES_12; 1344 } else { 1345 LOG_ERROR(BSL_LS_SOC_PORT, 1346 (BSL_META_U(unit, 1347 "Invalid number of lanes for " 1348 "physical_port=%d, lanes=%d\n"), 1349 phy_port, lanes)); 1350 return SOC_E_CONFIG; 1351 } 1352 1353 if (!(MN_PHY_PORT(unit, phy_port).lanes_valid & lane_mask)) { 1354 LOG_ERROR(BSL_LS_SOC_PORT, 1355 (BSL_META_U(unit, 1356 "Invalid lane configuration for " 1357 "physical port %d, lane=%d, " 1358 "valid_lanes=%s %s %s %s %s\n"), 1359 phy_port, lanes, 1360 (MN_PHY_PORT(unit, phy_port).lanes_valid & 1361 MN_PHY_XLPORT_LANES_1) ? "1" : "", 1362 (MN_PHY_PORT(unit, phy_port).lanes_valid & 1363 MN_PHY_XLPORT_LANES_2) ? "2" : "", 1364 (MN_PHY_PORT(unit, phy_port).lanes_valid & 1365 MN_PHY_XLPORT_LANES_4) ? "4" : "", 1366 (MN_PHY_PORT(unit, phy_port).lanes_valid & 1367 MN_PHY_XLPORT_LANES_10) ? "10" : "", 1368 (MN_PHY_PORT(unit, phy_port).lanes_valid & 1369 MN_PHY_XLPORT_LANES_12) ? "12" : "")); 1370 1371 return SOC_E_CONFIG; 1372 } 1373 1374 return SOC_E_NONE; 1375 } 1376 1377 1378 /* 1379 * Function: 1380 * soc_mn_port_lanes_valid 1381 * Purpose: 1382 * Check that given lane setting is valid for logical port. 1383 * Parameters: 1384 * unit - (IN) Unit number. 1385 * port - (IN) Logical port. 1386 * lanes - (IN) Number of PHY lanes. 1387 * Returns: 1388 * SOC_E_XXX 1389 */ 1390 int 1391 soc_mn_port_lanes_valid(int unit, soc_port_t port, int lanes) 1392 { 1393 soc_info_t *si = &SOC_INFO(unit); 1394 int phy_port; 1395 1396 MN_INFO_INIT_CHECK(unit); 1397 1398 phy_port = si->port_l2p_mapping[port]; 1399 if (phy_port == -1) { 1400 LOG_ERROR(BSL_LS_SOC_PORT, 1401 (BSL_META_U(unit, 1402 "Invalid physical port for logical port %d\n"), 1403 port)); 1404 return SOC_E_PORT; 1405 } 1406 1407 return _soc_mn_phy_port_lanes_valid(unit, phy_port, lanes); 1408 } 1409 1410 1411 /* 1412 * Function: 1413 * soc_mn_port_resource_speed_max_get 1414 * Purpose: 1415 * Get the maximum allowed speed in the device. 1416 * 1417 * This information is used to determine the total number of 1418 * logical ports allowed in the system as well as the 1419 * pre-allocation of MMU port numbers. 1420 * Parameters: 1421 * unit - (IN) Unit number. 1422 * speed - (OUT) Maximum speed of any port in device. 1423 * Returns: 1424 * SOC_E_XXX 1425 * Note: 1426 */ 1427 int 1428 soc_mn_port_resource_speed_max_get(int unit, int *speed) 1429 { 1430 MN_INFO_INIT_CHECK(unit); 1431 1432 *speed = MN_INFO(unit)->speed_max; 1433 1434 return SOC_E_NONE; 1435 } 1436 1437 1438 /* 1439 * Function: 1440 * soc_mn_port_addressable 1441 * Purpose: 1442 * Check that given logical port number is addressable. 1443 * Parameters: 1444 * unit - (IN) Unit number. 1445 * port - (IN) Logical port number. 1446 * Returns: 1447 * SOC_E_NONE - If logical port number is addressable 1448 * SOC_E_PORT - If logical port number is not addressable. 1449 * NOTE: 1450 * This routine only checks that the logical port number is 1451 * within the valid range. It does NOT check whether the logical 1452 * port has a valid port mapping. 1453 */ 1454 int 1455 soc_mn_port_addressable(int unit, soc_port_t port) 1456 { 1457 MN_INFO_INIT_CHECK(unit); 1458 1459 if ((port < 0) || 1460 (port > MN_INFO(unit)->port_max)) { 1461 LOG_ERROR(BSL_LS_SOC_PORT, 1462 (BSL_META_U(unit, 1463 "Invalid logical port number %d. " 1464 "Valid logical ports are %d to %d.\n"), 1465 port, 0, MN_INFO(unit)->port_max)); 1466 return SOC_E_PORT; 1467 } 1468 1469 return SOC_E_NONE; 1470 } 1471 1472 /* 1473 * Function: 1474 * soc_mn_phy_port_addressable 1475 * Purpose: 1476 * Check that given physical port number is addressable. 1477 * Parameters: 1478 * unit - (IN) Unit number. 1479 * phy_port - (IN) Physical port number. 1480 * Returns: 1481 * SOC_E_NONE - If physical port number is addressable 1482 * SOC_E_PORT - If physical port number is not addressable. 1483 * NOTE: 1484 * This routine only checks that the physical port number is 1485 * within the valid range. It does NOT check whether the physical 1486 * port has a port mapping. 1487 */ 1488 int 1489 soc_mn_phy_port_addressable(int unit, int phy_port) 1490 { 1491 MN_INFO_INIT_CHECK(unit); 1492 1493 if ((phy_port < 0) || 1494 (phy_port >= MN_INFO(unit)->phy_ports_max)) { 1495 return SOC_E_PORT; 1496 } 1497 1498 return SOC_E_NONE; 1499 } 1500 1501 1502 /* 1503 * Function: 1504 * soc_mn_phy_port_pgw_info_get 1505 * Purpose: 1506 * Provide the PGW information for given physical port. 1507 * Parameters: 1508 * unit - (IN) Unit number. 1509 * phy_port - (IN) Physical port number. 1510 * pgw - (OUT) PGW instance where port resides. 1511 * tsc - (OUT) TSC number within PGW 1512 * port_index - (OUT) Port index within TSC 1513 * Returns: 1514 * SOC_E_XXX 1515 */ 1516 int 1517 soc_mn_phy_port_pgw_info_get(int unit, int phy_port, 1518 int *pgw, int *tsc, int *port_index) 1519 { 1520 MN_INFO_INIT_CHECK(unit); 1521 1522 if (phy_port == -1) { 1523 LOG_ERROR(BSL_LS_SOC_PORT, 1524 (BSL_META_U(unit, 1525 "Invalid physical port %d\n"), 1526 phy_port)); 1527 return SOC_E_PORT; 1528 } 1529 1530 *pgw = MN_PHY_PORT_LANE(unit, phy_port).pgw; 1531 *tsc = MN_PHY_PORT_LANE(unit, phy_port).tsc; 1532 *port_index = MN_PHY_PORT_LANE(unit, phy_port).port_index; 1533 1534 return SOC_E_NONE; 1535 } 1536 1537 1538 /* 1539 * Function: 1540 * _soc_mn_logic_ports_max_validate 1541 * Purpose: 1542 * Check that number of logical ports do not exceed maximum allowed 1543 * based on physical port mappings provided in bitmap. 1544 * Parameters: 1545 * unit - (IN) Unit number. 1546 * phy_pbmp - (IN) Bitmap of physical ports. 1547 * A bit set indicates physical port is mapped. 1548 * Returns: 1549 * SOC_E_XXX 1550 * Note: 1551 */ 1552 STATIC int 1553 _soc_mn_logic_ports_max_validate(int unit, portmod_pbmp_t phy_pbmp ) 1554 { 1555 int phy_port; 1556 int ports_max; 1557 int port_count = 0; 1558 1559 /* Get maximum number of logical ports allowed */ 1560 ports_max = MN_INFO(unit)->port_max; 1561 1562 /* Check number of logical ports do not exceed maximum allowed */ 1563 /* coverity[overrun-local] */ 1564 1565 for (phy_port = 0; phy_port < SOC_MAX_NUM_PORTS; phy_port++) { 1566 /* Skip CPU, Loopback */ 1567 if ((phy_port == MN_PHY_PORT_CPU) || 1568 (phy_port == MN_PHY_PORT_LB) || 1569 (phy_port == MN_PHY_PORT_MACSEC)) { 1570 continue; 1571 } 1572 if (!PORTMOD_PBMP_MEMBER(phy_pbmp, phy_port)) { 1573 continue; 1574 } 1575 1576 port_count++; 1577 } 1578 1579 if (port_count > ports_max) { 1580 LOG_ERROR(BSL_LS_SOC_PORT, 1581 (BSL_META_U(unit, 1582 "Number of logical ports exceeds " 1583 "max allowed: port_coun=%d ports_max=%d\n"), 1584 port_count, ports_max)); 1585 return SOC_E_RESOURCE; 1586 } 1587 1588 LOG_VERBOSE(BSL_LS_SOC_PORT, 1589 (BSL_META_U(unit, 1590 "Number of logical ports exceeds " 1591 "max allowed: port_coun=%d ports_max=%d\n"), 1592 port_count, ports_max)); 1593 1594 return SOC_E_NONE; 1595 } 1596 1597 1598 /* 1599 * Function: 1600 * _soc_mn_port_resource_tdm_config_validate 1601 * Purpose: 1602 * Validate that the given port configuration is a 1603 * standard configuration supported by the TDM. 1604 * Parameters: 1605 * unit - (IN) Unit number. 1606 * nport - (IN) Number of elements in array resource. 1607 * resource - (IN) Port resource configuration array. 1608 * phy_pbm - (IN) Physical port bitmap. A bit set indicates 1609 * physical port is defined (mapped). 1610 * Returns: 1611 * SOC_E_XXX 1612 * Note: 1613 * - Resource is not NULL. 1614 * - Assumes array order is correct 1615 * ('delete' operations are first in array). 1616 * - Ports are not replicated. 1617 */ 1618 STATIC int 1619 _soc_mn_port_resource_tdm_config_validate(int unit, 1620 int nport, 1621 soc_port_resource_t *resource, 1622 portmod_pbmp_t phy_pbmp) 1623 { 1624 soc_info_t *si = &SOC_INFO(unit); 1625 soc_port_resource_t *pr; 1626 int xlport_mask[MN_NUM_PGWS][MN_TSCS_PER_PGW]; 1627 int xlport_validated[MN_NUM_PGWS][MN_TSCS_PER_PGW]; 1628 int pgw; 1629 int tsc; 1630 int port_index; 1631 int phy_port; 1632 int i; 1633 1634 LOG_VERBOSE(BSL_LS_SOC_PORT, 1635 (BSL_META_U(unit, 1636 "--- VALIDATE: TDM configuration\n"))); 1637 1638 /* Clear data */ 1639 for (pgw = 0; pgw < MN_NUM_PGWS; pgw++) { 1640 for (tsc = 0; tsc < MN_TSCS_PER_PGW; tsc++) { 1641 xlport_mask[pgw][tsc] = 0x0; 1642 xlport_validated[pgw][tsc] = 0; 1643 } 1644 } 1645 1646 /* 1647 * Determine configuration on each XLPORT (PortMacro or TSC-4) 1648 * 1649 * A bit set means physical port is defined (mapped). 1650 */ 1651 for (phy_port = 0; phy_port < SOC_MAX_NUM_PORTS; phy_port++) { 1652 pgw = MN_PHY_PORT_LANE(unit, phy_port).pgw; 1653 if (pgw == -1) { 1654 continue; 1655 } 1656 1657 tsc = MN_PHY_PORT_LANE(unit, phy_port).tsc; 1658 port_index = MN_PHY_PORT_LANE(unit, phy_port).port_index; 1659 1660 /* Check if physical port is mapped */ 1661 /* coverity[overrun-local] */ 1662 if (PORTMOD_PBMP_MEMBER(phy_pbmp, phy_port)) { 1663 xlport_mask[pgw][tsc] |= 1 << port_index; 1664 } 1665 } 1666 1667 LOG_VERBOSE(BSL_LS_SOC_PORT, 1668 (BSL_META_U(unit, "Check Port Configuration block\n"))); 1669 for (pgw = 0; pgw < MN_NUM_PGWS; pgw++) { 1670 LOG_VERBOSE(BSL_LS_SOC_PORT, 1671 (BSL_META_U(unit, " PGW_%d:"), pgw)); 1672 for (tsc = 0; tsc < MN_TSCS_PER_PGW; tsc++) { 1673 LOG_VERBOSE(BSL_LS_SOC_PORT, 1674 (BSL_META_U(unit, 1675 " tsc_%d=0x%x"), tsc, 1676 xlport_mask[pgw][tsc])); 1677 } 1678 LOG_VERBOSE(BSL_LS_SOC_PORT, 1679 (BSL_META_U(unit, "\n"))); 1680 } 1681 1682 /* 1683 * Check configuration only on blocks where ports are being flexed. 1684 * Assume configuration on other blocks is valid. 1685 */ 1686 for (i = 0, pr = &resource[0]; i < nport; i++, pr++) { 1687 if (pr->physical_port == -1) { 1688 phy_port = si->port_l2p_mapping[pr->logical_port]; 1689 } else { 1690 phy_port = pr->physical_port; 1691 } 1692 1693 pgw = MN_PHY_PORT_LANE(unit, phy_port).pgw; 1694 tsc = MN_PHY_PORT_LANE(unit, phy_port).tsc; 1695 1696 if (pgw == -1) { 1697 LOG_ERROR(BSL_LS_SOC_PORT, 1698 (BSL_META_U(unit, 1699 "Invalid PGW block -1 for " 1700 "physical port %d\n"), 1701 phy_port)); 1702 return SOC_E_INTERNAL; 1703 } 1704 1705 if (xlport_validated[pgw][tsc]) { 1706 /* Configuration in block was already validated. skip */ 1707 continue; 1708 } 1709 1710 1711 xlport_validated[pgw][tsc] = 1; 1712 } 1713 1714 return SOC_E_NONE; 1715 } 1716 1717 1718 /* 1719 * Function: 1720 * _soc_mn_port_mapping_validate 1721 * Purpose: 1722 * Validate: 1723 * - Port numbers are available and mappings are not replicated. 1724 * - Number of logical port numbers do not exceed max allowed. 1725 * - Port configuration mode is valid (based on valid TDM cases). 1726 * Parameters: 1727 * unit - (IN) Unit number. 1728 * nport - (IN) Number of elements in array resource. 1729 * resource - (IN) Port resource configuration array. 1730 * Returns: 1731 * SOC_E_XXX 1732 * Note: 1733 * - Resource is not NULL. 1734 * - Assumes array order is correct 1735 * ('delete' operations are first in array). 1736 */ 1737 STATIC int 1738 _soc_mn_port_mapping_validate(int unit, 1739 int nport, 1740 soc_port_resource_t *resource) 1741 { 1742 soc_info_t *si = &SOC_INFO(unit); 1743 soc_port_resource_t *pr; 1744 char phy_pfmt[SOC_PBMP_FMT_LEN]; 1745 char logic_pfmt[SOC_PBMP_FMT_LEN]; 1746 portmod_pbmp_t phy_pbmp; 1747 pbmp_t logic_pbmp; 1748 pbmp_t phy_pbmp_tmp; 1749 int phy_port; 1750 int i; 1751 int lane; 1752 int num_lanes; 1753 1754 LOG_VERBOSE(BSL_LS_SOC_PORT, 1755 (BSL_META_U(unit, 1756 "--- VALIDATE: Port mappings\n"))); 1757 /* 1758 * Determine bitmaps of used/mapped logical ports and 1759 * physical ports. 1760 * 1761 * A bit set indicates port is mapped. 1762 */ 1763 PORTMOD_PBMP_CLEAR(phy_pbmp); 1764 SOC_PBMP_CLEAR(logic_pbmp); 1765 1766 /* Get current port assignment */ 1767 for (phy_port = 0; phy_port < SOC_MAX_NUM_PORTS; phy_port++) { 1768 /* Skip not-addressable and invalid ports */ 1769 if (!MN_PHY_PORT_ADDRESSABLE(unit, phy_port) || 1770 (si->port_p2l_mapping[phy_port] == -1)) { 1771 continue; 1772 } 1773 1774 /* coverity[overrun-local] */ 1775 SOC_PBMP_PORT_ADD(logic_pbmp, si->port_p2l_mapping[phy_port]); 1776 /* coverity[overrun-local] */ 1777 PORTMOD_PBMP_PORT_ADD(phy_pbmp, phy_port); 1778 } 1779 1780 /* First 'delete' mappings */ 1781 for (i = 0, pr = &resource[0]; 1782 (i < nport) && (pr->physical_port == -1); 1783 i++, pr++) { 1784 phy_port = si->port_l2p_mapping[pr->logical_port]; 1785 if (phy_port == -1) { 1786 LOG_ERROR(BSL_LS_SOC_PORT, 1787 (BSL_META_U(unit, 1788 "Logical port %d is not currently mapped\n"), 1789 pr->logical_port)); 1790 return SOC_E_CONFIG; 1791 } 1792 SOC_PBMP_PORT_REMOVE(logic_pbmp, pr->logical_port); 1793 SOC_PBMP_PORT_REMOVE(phy_pbmp, phy_port); 1794 } 1795 1796 /* Continue with 'add' mappings in rest of array */ 1797 for (; i < nport; i++, pr++) { 1798 /* Check that port number is 'available' */ 1799 if (SOC_PBMP_MEMBER(logic_pbmp, pr->logical_port) || 1800 PORTMOD_PBMP_MEMBER(phy_pbmp, pr->physical_port)) { 1801 LOG_ERROR(BSL_LS_SOC_PORT, 1802 (BSL_META_U(unit, 1803 "Either Logical port %d or " 1804 "Physical port %d is already mapped\n"), 1805 pr->logical_port, pr->physical_port)); 1806 return SOC_E_BUSY; 1807 } 1808 1809 SOC_PBMP_PORT_ADD(logic_pbmp, pr->logical_port); 1810 PORTMOD_PBMP_PORT_ADD(phy_pbmp, pr->physical_port); 1811 } 1812 SOC_PBMP_CLEAR(phy_pbmp_tmp); 1813 PORTMOD_PBMP_OR(phy_pbmp_tmp, phy_pbmp); 1814 LOG_VERBOSE(BSL_LS_SOC_PORT, 1815 (BSL_META_U(unit, 1816 "New port bitmap\n" 1817 " logical = %s\n" 1818 " physical = %s\n"), 1819 SOC_PBMP_FMT(logic_pbmp, logic_pfmt), 1820 SOC_PBMP_FMT(phy_pbmp_tmp, phy_pfmt))); 1821 1822 /* Check maximum number of logical ports allowed */ 1823 SOC_IF_ERROR_RETURN 1824 (_soc_mn_logic_ports_max_validate(unit, phy_pbmp)); 1825 1826 1827 /* 1828 * Lanes availability 1829 * 1830 * Check that lanes needed by the physical port are not 1831 * not being used by any other port. 1832 * 1833 * Assume physical port numbers are consecutive in device 1834 * with respect of the lanes. 1835 */ 1836 LOG_VERBOSE(BSL_LS_SOC_PORT, 1837 (BSL_META_U(unit, 1838 "--- VALIDATE: Port lanes assignment\n"))); 1839 for (i = 0, pr = &resource[0]; i < nport; i++, pr++) { 1840 /* Skip delete entries */ 1841 if (pr->physical_port == -1) { 1842 continue; 1843 } 1844 1845 /* 1846 * For 100GE or more, we need to check all 12 lanes 1847 * even though only 10 lanes are actually used. 1848 */ 1849 num_lanes = pr->num_lanes; 1850 if ((pr->speed >= 100000) && IS_CXX_PORT(unit, pr->logical_port)) { 1851 num_lanes = 12; 1852 } 1853 1854 for (lane = 1; lane < num_lanes; lane++) { 1855 /* Check lane is not being used */ 1856 if (PORTMOD_PBMP_MEMBER(phy_pbmp, pr->physical_port + lane)) { 1857 LOG_ERROR(BSL_LS_SOC_PORT, 1858 (BSL_META_U(unit, 1859 "Port=%d physical_port=%d, lane on " 1860 "physical port %d is being used\n"), 1861 pr->logical_port, pr->physical_port, 1862 pr->physical_port + lane)); 1863 return SOC_E_BUSY; 1864 } 1865 } 1866 } 1867 if (!(SAL_BOOT_BCMSIM || SAL_BOOT_XGSSIM) && 1868 !soc_property_get(unit, "skip_tdm_init", 0)) { 1869 /* Check TDM port configuration */ 1870 SOC_IF_ERROR_RETURN 1871 (_soc_mn_port_resource_tdm_config_validate(unit, 1872 nport, resource, 1873 phy_pbmp)); 1874 } 1875 return SOC_E_NONE; 1876 } 1877 1878 /* 1879 * Function: 1880 * _soc_mn_port_resource_mixed_sister_validate 1881 * Purpose: 1882 * Validate Oversubscription mode: 1883 * - Ports with speed 100GE or more are not in oversubscription mode. 1884 * - Line rate or Oversub is the same in all ports within the same 1885 * Port Macro (non-mixed mode in sister ports). 1886 * Parameters: 1887 * unit - (IN) Unit number. 1888 * nport - (IN) Number of elements in array resource. 1889 * resource - (IN) Port resource configuration array. 1890 * post_si - (IN) SOC_INFO data after FlexPort. 1891 * Returns: 1892 * SOC_E_XXX 1893 * Note: 1894 * - Resource is not NULL. 1895 * - Assumes array order is correct 1896 * ('delete' operations are first in array). 1897 */ 1898 STATIC int 1899 _soc_mn_port_resource_mixed_sisters_validate(int unit, 1900 int nport, 1901 soc_port_resource_t *resource, 1902 soc_info_mn_misc_t *post_si) 1903 { 1904 1905 soc_port_resource_t *pr; 1906 int i; 1907 int j; 1908 int logic_port; 1909 int phy_port ; 1910 int sister_port; 1911 int speed; 1912 int spd_cls, sister_spd_cls; 1913 uint32 sp_spacing = 0; 1914 int sister_speed,lanes_sister[MN_PORTS_PER_TSC]; 1915 int encap_sister[MN_PORTS_PER_TSC]; 1916 int speed_sister[MN_PORTS_PER_TSC]; 1917 int size = 0; 1918 int rv = 0; 1919 int type; 1920 LOG_VERBOSE(BSL_LS_SOC_PORT, 1921 (BSL_META_U(unit, 1922 "--- VALIDATE: Mixed speed sister ports\n"))); 1923 1924 for (i = 0, pr = &resource[0]; i < nport; i++, pr++) { 1925 phy_port = pr->physical_port; 1926 1927 /* Skip delete entries */ 1928 if (phy_port == -1) { 1929 continue; 1930 } 1931 1932 sister_port = MN_PHY_PORT(unit, phy_port).sisters_ports[0]; 1933 1934 1935 phy_port = pr->physical_port; 1936 speed = pr->speed; 1937 1938 size = 0 ; 1939 for (j = 0; j < MN_PORTS_PER_TSC; j++) { 1940 sister_port = MN_PHY_PORT(unit, phy_port).sisters_ports[j]; 1941 logic_port = post_si->port_p2l_mapping[sister_port]; 1942 1943 if (logic_port < 0) { 1944 continue; /* Skip if port is not defined */ 1945 } 1946 if (SOC_PBMP_MEMBER(post_si->disabled_bitmap, logic_port)) { 1947 continue; /* Skip inactive ports */ 1948 } 1949 lanes_sister[size] = post_si->port_num_lanes[logic_port]; 1950 encap_sister[size] = post_si->port_encap[logic_port]; 1951 speed_sister[size] = post_si->port_speed[logic_port]; 1952 size++; 1953 } 1954 SOC_IF_ERROR_RETURN(soc_mn_portctrl_pm_type_get(unit, phy_port, &type)); 1955 1956 if (type != portmodDispatchTypePm4x10) { 1957 rv = soc_esw_portmod_port_vcos_get(unit , phy_port, type, lanes_sister, 1958 speed_sister , encap_sister, size); 1959 } 1960 if (rv != SOC_E_NONE) { 1961 LOG_ERROR(BSL_LS_SOC_PORT, (BSL_META_U(unit, 1962 "TSC PLL no availabe pll to support the speed " 1963 "%d \n"), phy_port)); 1964 return SOC_E_CONFIG; 1965 } 1966 1967 /* Skip Line Rate ports */ 1968 if (!SOC_PBMP_MEMBER(post_si->oversub_pbm, pr->logical_port)) { 1969 continue; 1970 } 1971 1972 /* 1973 * Check that Oversub sister ports (ports within a Port Macro) 1974 * have the same speed class 1975 */ 1976 speed = pr->speed; 1977 SOC_IF_ERROR_RETURN(_soc_monterey_mmu_ovs_speed_class_map_get(unit, 1978 &speed, &spd_cls, &sp_spacing)); 1979 1980 for (j = 0; j < MN_PORTS_PER_TSC; j++) { 1981 sister_port = MN_PHY_PORT(unit, phy_port).sisters_ports[j]; 1982 logic_port = post_si->port_p2l_mapping[sister_port]; 1983 1984 if (logic_port < 0) { 1985 continue; /* Skip if port is not defined */ 1986 } 1987 if (SOC_PBMP_MEMBER(post_si->disabled_bitmap, logic_port)) { 1988 continue; /* Skip inactive ports */ 1989 } 1990 1991 sister_speed = post_si->port_speed[logic_port]; 1992 if (sister_speed <= 0) { 1993 continue; 1994 } 1995 SOC_IF_ERROR_RETURN(_soc_monterey_mmu_ovs_speed_class_map_get(unit, 1996 &sister_speed, &sister_spd_cls, &sp_spacing)); 1997 if (((speed == 10000) && (post_si->port_speed[logic_port] <= 5000)) || 1998 ((pr->speed <= 5000) && (sister_speed == 10000))) { 1999 continue; 2000 } 2001 2002 if (spd_cls != sister_spd_cls) { 2003 2004 LOG_ERROR(BSL_LS_SOC_PORT, 2005 (BSL_META_U(unit, 2006 "Speed class must be the same on " 2007 "oversub sister physical ports " 2008 "%d %d %d %d\n"), 2009 MN_PHY_PORT(unit, phy_port).sisters_ports[0], 2010 MN_PHY_PORT(unit, phy_port).sisters_ports[1], 2011 MN_PHY_PORT(unit, phy_port).sisters_ports[2], 2012 MN_PHY_PORT(unit, phy_port).sisters_ports[3])); 2013 LOG_ERROR(BSL_LS_SOC_PORT, 2014 (BSL_META_U(unit, 2015 "Speed class mismatch: \n" 2016 " logical_port=%d physical_port=%d " 2017 "speed=%d\n" 2018 " logical_port=%d physical_port=%d " 2019 "speed=%d\n"), 2020 pr->logical_port, pr->physical_port, speed, 2021 logic_port, sister_port, sister_speed)); 2022 return SOC_E_CONFIG; 2023 } 2024 } 2025 } 2026 2027 return SOC_E_NONE; 2028 } 2029 2030 /* 2031 * Function: 2032 * soc_mn_port_mixed_sister_speed_validate 2033 * Purpose: 2034 * Check all sister ports has same speed in oversub mode 2035 * Parameters: 2036 * unit - (IN) Unit number. 2037 * Returns: 2038 * SOC_E_XXX 2039 * Note: 2040 * Assumes that this function is called at early stage of initialization 2041 * (For example, soc_apache_port_config_init). 2042 * Because portctrl/portmod API is not ready to use, 2043 * use port_speed_max or port_init_speed instead. 2044 */ 2045 int 2046 soc_mn_port_mixed_sister_speed_validate(int unit) 2047 { 2048 int i,j; 2049 int lport, sister_lport, phy_port, sister_port; 2050 int speed, sister_speed; 2051 int spd_cls, sister_spd_cls ; 2052 soc_info_t *si = &SOC_INFO(unit); 2053 uint32 sp_spacing = 0; 2054 int speed_sister[MN_PORTS_PER_TSC]={0}; 2055 int lanes_sister[MN_PORTS_PER_TSC]={0}; 2056 int encap_sister[MN_PORTS_PER_TSC]={0}; 2057 int size = 0; 2058 int rv = 0; 2059 int type; 2060 int roe_speed_rsvd4, roe_speed_cpri; 2061 soc_pbmp_t pbmp_xport_cpri; 2062 SOC_PBMP_CLEAR(pbmp_xport_cpri); 2063 pbmp_xport_cpri = soc_property_get_pbmp_default(unit, spn_PBMP_XPORT_CPRI, 2064 pbmp_xport_cpri); 2065 /* Loop for 1st physical port in PortMacro */ 2066 for (phy_port = 1; phy_port < SOC_MAX_NUM_PORTS; phy_port += MN_PORTS_PER_TSC) { 2067 2068 lport = si->port_p2l_mapping[phy_port]; 2069 if (lport < 0) { 2070 continue; 2071 } 2072 if (si->port_speed_max[lport] < 0) { 2073 continue; 2074 } 2075 2076 sister_port = MN_PHY_PORT(unit, phy_port).sisters_ports[0]; 2077 size = 0; 2078 for (j = phy_port; j <( phy_port + MN_PORTS_PER_TSC); j++) { 2079 2080 /* coverity[overrun-local] */ 2081 sister_lport = si->port_p2l_mapping[j]; 2082 2083 if (sister_lport < 0) { 2084 continue; /* Skip if port is not defined */ 2085 } 2086 if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, sister_lport)) { 2087 continue; /* Skip inactive ports */ 2088 } 2089 lanes_sister[size] = si->port_num_lanes[sister_lport]; 2090 roe_speed_cpri = soc_property_port_get(unit, sister_lport, spn_CPRI_PORT_INIT_SPEED_ID, -1); 2091 roe_speed_rsvd4 = soc_property_port_get(unit, sister_lport, spn_RSVD4_PORT_INIT_SPEED_ID, -1); 2092 if (IS_HG_PORT(unit,sister_lport)) { 2093 encap_sister[size] = SOC_ENCAP_HIGIG; 2094 speed_sister[size] = si->port_speed_max[sister_lport]; 2095 } else if ((SOC_PBMP_MEMBER(pbmp_xport_cpri, sister_lport)) && (roe_speed_cpri > 0)) { 2096 encap_sister[size] = SOC_ENCAP_CPRI; 2097 speed_sister[size] = roe_speed_cpri; 2098 } else if ((SOC_PBMP_MEMBER(pbmp_xport_cpri, sister_lport)) && (roe_speed_rsvd4 > 0)) { 2099 encap_sister[size] = SOC_ENCAP_RSVD4; 2100 speed_sister[size] = roe_speed_rsvd4; 2101 } else { 2102 encap_sister[size] = SOC_ENCAP_IEEE; 2103 speed_sister[size] = si->port_speed_max[sister_lport]; 2104 } 2105 size++; 2106 } 2107 SOC_IF_ERROR_RETURN(soc_mn_portctrl_pm_type_get(unit, phy_port, &type)); 2108 2109 if (type != portmodDispatchTypePm4x10) { 2110 rv = soc_esw_portmod_port_vcos_get(unit, phy_port, type, lanes_sister, 2111 speed_sister ,encap_sister, size); 2112 } 2113 if (rv != SOC_E_NONE) { 2114 LOG_VERBOSE(BSL_LS_SOC_PORT, (BSL_META_U(unit, 2115 "TSC PLL no availabe pll to support the speed " 2116 "%d \n"), phy_port)); 2117 return SOC_E_CONFIG; 2118 } 2119 2120 /* Skip Line Rate ports 2121 Assumes mixed oversub mode is already checked */ 2122 if (!SOC_PBMP_MEMBER(si->oversub_pbm, lport)) { 2123 continue; 2124 } 2125 2126 /* 2127 * Check that Oversub sister ports (ports within a Port Macro) 2128 * have the same speed class 2129 */ 2130 speed = si->port_speed_max[lport]; 2131 SOC_IF_ERROR_RETURN(_soc_monterey_mmu_ovs_speed_class_map_get(unit, 2132 &speed, &spd_cls, &sp_spacing)); 2133 2134 for (i = 1; i < MN_PORTS_PER_TSC; i++) { 2135 sister_port = MN_PHY_PORT(unit, phy_port).sisters_ports[i]; 2136 sister_lport = si->port_p2l_mapping[sister_port]; 2137 if (sister_lport < 0) { 2138 continue; 2139 } 2140 2141 if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, sister_lport)) { 2142 continue; 2143 } 2144 2145 sister_speed = si->port_speed_max[sister_lport]; 2146 2147 SOC_IF_ERROR_RETURN(_soc_monterey_mmu_ovs_speed_class_map_get(unit, 2148 &sister_speed, &sister_spd_cls, &sp_spacing)); 2149 2150 if (((speed == 10000) && (si->port_speed_max[sister_lport] <= 5000)) || 2151 ((si->port_speed_max[lport] <= 5000) && (sister_speed ==10000))) { 2152 continue; 2153 } 2154 if (spd_cls != sister_spd_cls) { 2155 2156 LOG_ERROR(BSL_LS_SOC_PORT, (BSL_META_U(unit, 2157 "Mixed port speed is not acceptable in oversub mode " 2158 "on physical ports %d %d %d %d\n"), 2159 MN_PHY_PORT(unit, phy_port).sisters_ports[0], 2160 MN_PHY_PORT(unit, phy_port).sisters_ports[1], 2161 MN_PHY_PORT(unit, phy_port).sisters_ports[2], 2162 MN_PHY_PORT(unit, phy_port).sisters_ports[3])); 2163 return SOC_E_CONFIG; 2164 } 2165 } 2166 } 2167 2168 return SOC_E_NONE; 2169 } 2170 2171 /* 2172 * Function: 2173 * _soc_mn_port_resource_validate_output 2174 * Purpose: 2175 * Debug output for given port resource array. 2176 * Parameters: 2177 * unit - (IN) Unit number. 2178 * nport - (IN) Number of elements in array resource. 2179 * resource - (IN) Port Resource FlexPort configuration. 2180 * Returns: 2181 * SOC_E_XXX 2182 */ 2183 STATIC void 2184 _soc_mn_port_resource_validate_output(int unit, 2185 int nport, 2186 soc_port_resource_t *resource) 2187 { 2188 int i; 2189 soc_port_resource_t *pr; 2190 2191 LOG_VERBOSE(BSL_LS_SOC_PORT, 2192 (BSL_META_U(unit, 2193 "--- SOC Port Resource Input Array ---\n"))); 2194 2195 LOG_VERBOSE(BSL_LS_SOC_PORT, 2196 (BSL_META_U(unit, 2197 "Logical Physical Speed Lanes " 2198 "Encap Flags\n"))); 2199 2200 for (i = 0, pr = &resource[0]; i < nport; i++, pr++) { 2201 2202 LOG_VERBOSE(BSL_LS_SOC_PORT, 2203 (BSL_META_U(unit, 2204 " %3d %3d "), 2205 pr->logical_port, pr->physical_port)); 2206 if (pr->physical_port == -1) { 2207 LOG_VERBOSE(BSL_LS_SOC_PORT, 2208 (BSL_META_U(unit, 2209 "--------------------- 0x%8.8x\n"), 2210 pr->flags)); 2211 continue; 2212 } 2213 2214 LOG_VERBOSE(BSL_LS_SOC_PORT, 2215 (BSL_META_U(unit, 2216 "%6d %2d %6s 0x%8.8x\n"), 2217 pr->speed, pr->num_lanes, 2218 (pr->encap == BCM_PORT_ENCAP_HIGIG2) ? "HG" : "!HG", 2219 pr->flags)); 2220 } 2221 2222 return; 2223 } 2224 2225 /* 2226 * Function: 2227 * soc_mn_port_resource_validate 2228 * Purpose: 2229 * Validate that the given FlexPort configuration is valid. 2230 * Parameters: 2231 * unit - (IN) Unit number. 2232 * nport - (IN) Number of elements in array resource. 2233 * resource - (IN) Port resource configuration array. 2234 * Returns: 2235 * SOC_E_XXX 2236 * Note: 2237 */ 2238 int 2239 soc_mn_port_resource_validate(int unit, int nport, soc_port_resource_t *resource) 2240 { 2241 int i, rv; 2242 soc_port_resource_t *pr; 2243 soc_info_mn_misc_t *post_si; 2244 int is_speed_set = FALSE; 2245 2246 LOG_VERBOSE(BSL_LS_SOC_PORT, 2247 (BSL_META_U(unit, 2248 "\n=============================================\n" 2249 "========= SOC PORT RESOURCE VALIDATE ========\n" 2250 "=============================================\n" 2251 ))); 2252 _soc_mn_port_resource_validate_output(unit, nport, resource); 2253 /* 2254 * Check lanes and speed assignment 2255 */ 2256 LOG_VERBOSE(BSL_LS_SOC_PORT, 2257 (BSL_META_U(unit, 2258 "--- VALIDATE: Port flex enable, lanes, speed\n"))); 2259 for (i = 0, pr = &resource[0]; i < nport; i++, pr++) { 2260 /* Skip delete entries */ 2261 2262 if (!(pr->flags & SOC_PORT_RESOURCE_SPEED)) { 2263 if (pr->physical_port == -1) { 2264 /* Check if flex operation is enabled on old phy port */ 2265 SOC_IF_ERROR_RETURN(_soc_mn_phy_port_flex_valid 2266 (unit, SOC_INFO(unit).port_l2p_mapping[pr->logical_port])); 2267 /* Skip delete entries */ 2268 continue; 2269 } else { 2270 /* Check if flex operation is enabled on new phy port */ 2271 SOC_IF_ERROR_RETURN(_soc_mn_phy_port_flex_valid 2272 (unit, pr->physical_port)); 2273 } 2274 /* Check if flex is enabled on port */ 2275 SOC_IF_ERROR_RETURN(_soc_mn_phy_port_flex_valid(unit, pr->physical_port)); 2276 2277 if ( !soc_feature(unit,soc_feature_rsvd4_support) && (pr->encap == SOC_ENCAP_RSVD4)) { 2278 return SOC_E_UNAVAIL; 2279 } 2280 /* Check lane assignment */ 2281 SOC_IF_ERROR_RETURN(_soc_mn_phy_port_lanes_valid(unit, pr->physical_port, 2282 pr->num_lanes)); 2283 if ((pr->encap != SOC_ENCAP_CPRI) && (pr->encap != SOC_ENCAP_RSVD4)) { 2284 /* Check speed (port rate) */ 2285 SOC_IF_ERROR_RETURN(_soc_mn_speed_valid(unit, pr->physical_port, 2286 pr->num_lanes, pr->speed)); 2287 } 2288 } else { 2289 is_speed_set = TRUE; 2290 } 2291 } 2292 2293 /* Check port mappings */ 2294 if (is_speed_set != TRUE) { 2295 SOC_IF_ERROR_RETURN(_soc_mn_port_mapping_validate(unit, nport, resource)); 2296 } 2297 2298 post_si = sal_alloc(sizeof(soc_info_mn_misc_t), "soc_info_mn_misc"); 2299 if (NULL == post_si) { 2300 return SOC_E_MEMORY; 2301 } 2302 2303 /* 2304 * Get additional port information needed for validation, 2305 * Post FlexPort SOC INFO port data 2306 * 2307 * NOTE that this is a local subset of the global SOC_INFO 2308 * which at this point should not be updated yet. 2309 */ 2310 rv = _soc_mn_post_soc_info_get(unit, nport, resource, post_si); 2311 2312 if (SOC_SUCCESS(rv)) { 2313 /* Validate oversub speed group limits */ 2314 rv = _soc_mn_port_resource_ovs_speed_group_validate(unit, post_si); 2315 } 2316 /* Check mixed speed on sister ports */ 2317 if (SOC_SUCCESS(rv)) { 2318 rv = _soc_mn_port_resource_mixed_sisters_validate(unit, nport, resource, post_si); 2319 } 2320 2321 sal_free(post_si); 2322 return rv; 2323 } 2324 2325 2326 2327 2328 /* 2329 * Function: 2330 * _soc_mn_port_resource_data_cleanup 2331 * Purpose: 2332 * Cleanup give data structure (deallocate memory). 2333 * Parameters: 2334 * unit - (IN) Unit number. 2335 * pre_resource - (IN/OUT) Memory to deallocate. 2336 * Returns: 2337 * None 2338 * Note: 2339 */ 2340 STATIC void 2341 _soc_mn_port_resource_data_cleanup(soc_port_resource_t **pre_resource) 2342 { 2343 if (*pre_resource != NULL) { 2344 sal_free(*pre_resource); 2345 *pre_resource = NULL; 2346 } 2347 2348 return; 2349 } 2350 2351 /* 2352 * Function: 2353 * soc_monterey_port_mode_get 2354 * Description: 2355 * Get port mode by giving first logical port of TSC4 2356 * Parameters: 2357 * unit - Device number 2358 * port - Logical port 2359 * int* - Port Mode 2360 * 2361 * Each TSC4 can be configured into following 5 mode: 2362 * Lane number 0 1 2 3 2363 * ------------ --- --- --- --- 2364 * quad port 10G 10G 10G 10G 2365 * tri_012 port 10G 10G 20G x 2366 * tri_023 port 20G x 10G 10G 2367 * dual port 20G x 20G x 2368 * single port 40G x x x 2369 */ 2370 int 2371 soc_monterey_port_mode_get(int unit, int logical_port, int *mode) 2372 { 2373 soc_info_t *si; 2374 int lane; 2375 int port, first_phyport, phy_port; 2376 int num_lanes[MN_PORTS_PER_TSC]; 2377 2378 si = &SOC_INFO(unit); 2379 /* Each core is 4 lane core to get the first divide by 4 then multiply by 4 2380 * physical port is 2 => ((2-1)/4)*4+1 = 1 2381 * physical port is 9 => ((12-1)/4)*4+1 = 9 2382 */ 2383 first_phyport = (((si->port_l2p_mapping[logical_port]-1)/4)*4)+1; 2384 2385 for (lane = 0; lane < MN_PORTS_PER_TSC; lane++) { 2386 phy_port = first_phyport + lane; 2387 port = si->port_p2l_mapping[phy_port]; 2388 if (port == -1 || SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) { 2389 num_lanes[lane] = -1; 2390 } else { 2391 num_lanes[lane] = si->port_num_lanes[port]; 2392 } 2393 } 2394 2395 if (num_lanes[0] == 4) { 2396 *mode = SOC_MONTEREY_PORT_MODE_QUAD; 2397 } else if (num_lanes[0] == 2 && num_lanes[2] == 2) { 2398 *mode = SOC_MONTEREY_PORT_MODE_DUAL; 2399 } else if (num_lanes[0] == 2 && num_lanes[2] == 1 && num_lanes[3] == 1) { 2400 *mode = SOC_MONTEREY_PORT_MODE_TRI_023; 2401 } else if (num_lanes[0] == 1 && num_lanes[1] == 1 && num_lanes[2] == 2) { 2402 *mode = SOC_MONTEREY_PORT_MODE_TRI_012; 2403 } else { 2404 *mode = SOC_MONTEREY_PORT_MODE_SINGLE; 2405 } 2406 2407 return SOC_E_NONE; 2408 } 2409 #if 0 2410 /* 2411 * Function: 2412 * _soc_mn_port_mode_get 2413 * Description: 2414 * Get port mode by giving first logical port of TSC4 2415 * Same as above function but uses post soc info to calculate mode 2416 * Parameters: 2417 * unit - Device number 2418 * logical_port - Logical port 2419 * post_si - Post Soc info 2420 * int* - Port Mode 2421 * 2422 * Each TSC4 can be configured into following 5 mode: 2423 * Lane number 0 1 2 3 2424 * ------------ --- --- --- --- 2425 * quad port 10G 10G 10G 10G 2426 * tri_012 port 10G 10G 20G x 2427 * tri_023 port 20G x 10G 10G 2428 * dual port 20G x 20G x 2429 * single port 40G x x x 2430 */ 2431 STATIC int 2432 _soc_mn_port_mode_get(int unit, int logical_port, soc_info_mn_misc_t *post_si, int *mode) 2433 { 2434 int lane; 2435 int port, first_phyport, phy_port; 2436 int num_lanes[MN_PORTS_PER_TSC]; 2437 2438 first_phyport = post_si->port_l2p_mapping[logical_port]; 2439 2440 for (lane = 0; lane < MN_PORTS_PER_TSC; lane++) { 2441 phy_port = first_phyport + lane; 2442 port = post_si->port_p2l_mapping[phy_port]; 2443 if (port == -1 || SOC_PBMP_MEMBER(post_si->disabled_bitmap, port)) { 2444 num_lanes[lane] = -1; 2445 } else { 2446 num_lanes[lane] = post_si->port_num_lanes[port]; 2447 } 2448 } 2449 2450 if (num_lanes[0] == 4) { 2451 *mode = SOC_MONTEREY_PORT_MODE_QUAD; 2452 } else if (num_lanes[0] == 2 && num_lanes[2] == 2) { 2453 *mode = SOC_MONTEREY_PORT_MODE_DUAL; 2454 } else if (num_lanes[0] == 2 && num_lanes[2] == 1 && num_lanes[3] == 1) { 2455 *mode = SOC_MONTEREY_PORT_MODE_TRI_023; 2456 } else if (num_lanes[0] == 1 && num_lanes[1] == 1 && num_lanes[2] == 2) { 2457 *mode = SOC_MONTEREY_PORT_MODE_TRI_012; 2458 } else { 2459 *mode = SOC_MONTEREY_PORT_MODE_SINGLE; 2460 } 2461 2462 return SOC_E_NONE; 2463 } 2464 #endif 2465 2466 2467 /* 2468 * Function: 2469 * _soc_mn_port_resource_mode_get 2470 * Purpose: 2471 * Get and return the port mode in the given 2472 * Port Resource configuration structure. 2473 * Parameters: 2474 * unit - (IN) Unit number. 2475 * nport - (IN) Number of elements in array resource. 2476 * resource - (IN/OUT) Port Resource FlexPort configuration. 2477 * Returns: 2478 * SOC_E_XXX 2479 * Note: 2480 * If some ports are not present (inactive), routine will 2481 * try to figure out best match. 2482 */ 2483 STATIC int 2484 _soc_mn_port_resource_mode_get(int unit, 2485 int nport, 2486 soc_port_resource_t *resource) 2487 { 2488 soc_info_t *si = &SOC_INFO(unit); 2489 soc_port_resource_t *pr; 2490 int i; 2491 int j; 2492 int logic_port; 2493 int phy_port; 2494 int sister_port; 2495 int num_lanes[MN_PORTS_PER_TSC]; 2496 int one_active_lane; 2497 int two_active_lane; 2498 int four_active_lane; 2499 char *modes_str[] = {"Quad", "Tri_012", "Tri_023", "Dual", "Single"}; 2500 2501 soc_pbmp_t new_disabled_bitmap; 2502 int new_port_p2l_mapping[SOC_MAX_NUM_PORTS]; 2503 int new_port_num_lanes[SOC_MAX_NUM_PORTS]; 2504 2505 /* 2506 * Build information needed to determine port mode 2507 */ 2508 2509 LOG_VERBOSE(BSL_LS_SOC_PORT, 2510 (BSL_META_U(unit, 2511 "--- Get Port Mode\n"))); 2512 2513 /* Get current information */ 2514 for (i = 0; i < SOC_MAX_NUM_PORTS; i++) { 2515 new_port_p2l_mapping[i] = si->port_p2l_mapping[i]; 2516 new_port_num_lanes[i] = si->port_num_lanes[i]; 2517 } 2518 SOC_PBMP_ASSIGN(new_disabled_bitmap, si->all.disabled_bitmap); 2519 2520 /* First 'delete' mappings */ 2521 for (i = 0, pr = &resource[0]; 2522 (i < nport) && (pr->physical_port == -1); 2523 i++, pr++) { 2524 logic_port = pr->logical_port; 2525 2526 if (pr->flags & SOC_PORT_RESOURCE_I_MAP) { 2527 SOC_PBMP_PORT_ADD(new_disabled_bitmap, logic_port); 2528 continue; 2529 } 2530 2531 SOC_PBMP_PORT_REMOVE(new_disabled_bitmap, logic_port); 2532 new_port_p2l_mapping[si->port_l2p_mapping[logic_port]] = -1; 2533 new_port_num_lanes[logic_port] = -1; 2534 } 2535 2536 /* Continue with 'add' mappings in rest of array */ 2537 for (; i < nport; i++, pr++) { 2538 logic_port = pr->logical_port; 2539 phy_port = pr->physical_port; 2540 2541 SOC_PBMP_PORT_REMOVE(new_disabled_bitmap, logic_port); 2542 new_port_p2l_mapping[phy_port] = logic_port; 2543 new_port_num_lanes[logic_port] = pr->num_lanes; 2544 } 2545 2546 2547 /* 2548 * Determine port mode based on sister ports lane configuration 2549 */ 2550 for (i = 0, pr = &resource[0]; i < nport; i++, pr++) { 2551 /* Skip delete entries (assume these to be first in array) */ 2552 if (pr->physical_port == -1) { 2553 continue; 2554 } 2555 2556 one_active_lane = 0; 2557 two_active_lane = 0; 2558 four_active_lane = 0; 2559 2560 /* Get number of active lanes on sister ports */ 2561 phy_port = pr->physical_port; 2562 2563 2564 for (j = 0; j < MN_PORTS_PER_TSC; j++) { 2565 sister_port = MN_PHY_PORT(unit, phy_port).sisters_ports[j]; 2566 logic_port = new_port_p2l_mapping[sister_port]; 2567 2568 if (logic_port < 0) { 2569 num_lanes[j] = 0; 2570 continue; 2571 } 2572 2573 if (SOC_PBMP_MEMBER(new_disabled_bitmap, logic_port)) { 2574 num_lanes[j] = 0; 2575 } else { 2576 num_lanes[j] = new_port_num_lanes[logic_port]; 2577 } 2578 } 2579 2580 2581 /* 2582 * Quad: Lane0, Lane1, Lane2, Lane3 are active (individually) 2583 * Dual: Lane0, Lane2, are active (Lane0 and Lane2 are dual) 2584 * Single: Lane0 is active, one physical port using all lanes, 4/10/12 2585 * Tri_012: Lane0, Lane1, Lane2 are active (Lane2 is dual) 2586 * Tri_023: Lane0, Lane2, Lane3 are active (Lane0 is dual) 2587 * 2588 * If any lane is -1, make best guess. 2589 */ 2590 2591 /* Count active lanes */ 2592 for (j = 0; j < MN_PORTS_PER_TSC; j++) { 2593 if (num_lanes[j] == 1) { 2594 one_active_lane++; 2595 } else if (num_lanes[j] == 2) { 2596 two_active_lane++; 2597 } else if (num_lanes[j] >= 4) { 2598 /* No more checking is needed */ 2599 four_active_lane++; 2600 break; 2601 } 2602 } 2603 2604 /* Get mode based on active lanes */ 2605 if (four_active_lane) { 2606 pr->mode = SOC_MONTEREY_PORT_MODE_SINGLE; 2607 } else if (one_active_lane && !two_active_lane) { 2608 pr->mode = SOC_MONTEREY_PORT_MODE_QUAD; 2609 } else if (!one_active_lane && two_active_lane) { 2610 pr->mode = SOC_MONTEREY_PORT_MODE_DUAL; 2611 } else if (one_active_lane && two_active_lane) { 2612 if (num_lanes[0] == 1) { 2613 pr->mode = SOC_MONTEREY_PORT_MODE_TRI_012; 2614 } else { 2615 pr->mode = SOC_MONTEREY_PORT_MODE_TRI_023; 2616 } 2617 } else { 2618 LOG_ERROR(BSL_LS_SOC_PORT, 2619 (BSL_META_U(unit, 2620 "Invalid number of lanes " 2621 "logical_port=%d physical_port=%d " 2622 "num_lanes=%d\n"), 2623 pr->logical_port, pr->physical_port, pr->num_lanes)); 2624 return SOC_E_INTERNAL; 2625 } 2626 2627 LOG_VERBOSE(BSL_LS_SOC_PORT, 2628 (BSL_META_U(unit, 2629 "Port mode is %s for " 2630 "logical_port=%d physical_port=%d\n"), 2631 modes_str[pr->mode], 2632 pr->logical_port, pr->physical_port)); 2633 } 2634 2635 return SOC_E_NONE; 2636 } 2637 2638 2639 /* 2640 * Function: 2641 * _soc_mn_port_resource_output 2642 * Purpose: 2643 * Debug output for given port resource array. 2644 * Parameters: 2645 * unit - (IN) Unit number. 2646 * header - (IN) Header outout string. 2647 * nport - (IN) Number of elements in array resource. 2648 * resource - (IN) Port Resource FlexPort configuration. 2649 * Returns: 2650 * SOC_E_XXX 2651 */ 2652 STATIC void 2653 _soc_mn_port_resource_output(int unit, char *header, 2654 int nport, soc_port_resource_t *resource) 2655 { 2656 int i; 2657 int lane; 2658 soc_port_resource_t *pr; 2659 char *modes_str[] = {"Quad", "T012", "T023", "Dual", "Sngl"}; 2660 char *mode_str; 2661 2662 LOG_VERBOSE(BSL_LS_SOC_PORT, 2663 (BSL_META_U(unit, 2664 "%s\n"), header)); 2665 2666 LOG_VERBOSE(BSL_LS_SOC_PORT, 2667 (BSL_META_U(unit, 2668 "Logical Physical MMU " 2669 "Speed Lanes Mode Ovs PrioMask Flags " 2670 "PGW XLP PIDX\n"))); 2671 2672 for (i = 0, pr = &resource[0]; i < nport; i++, pr++) { 2673 LOG_VERBOSE(BSL_LS_SOC_PORT, 2674 (BSL_META_U(unit, 2675 " %3d %3d "), 2676 pr->logical_port, pr->physical_port)); 2677 if (pr->physical_port == -1) { 2678 LOG_VERBOSE(BSL_LS_SOC_PORT, 2679 (BSL_META_U(unit, 2680 "------------------------------------- " 2681 "0x%8.8x\n"), 2682 pr->flags)); 2683 continue; 2684 } 2685 2686 /* 2687 * This arrays used to determine the 'string' assumes 2688 * certain values on the Port Modes defined in soc_monterey_port_mode_e. 2689 */ 2690 if ((pr->mode < 0) || (pr->mode > 4)) { 2691 mode_str = "----"; 2692 } else { 2693 mode_str = modes_str[pr->mode]; 2694 } 2695 LOG_VERBOSE(BSL_LS_SOC_PORT, 2696 (BSL_META_U(unit, 2697 " %3d " 2698 "%6d %2d %4s %1d 0x%4.4x 0x%8.8x"), 2699 pr->mmu_port, pr->speed, pr->num_lanes, mode_str, 2700 pr->oversub, pr->prio_mask, pr->flags)); 2701 if (pr->num_lanes == 0) { 2702 LOG_VERBOSE(BSL_LS_SOC_PORT, 2703 (BSL_META_U(unit, 2704 " %2d %2d %2d\n"), 2705 -1, -1, -1)); 2706 } else { 2707 for (lane = 0; lane < pr->num_lanes; lane++) { 2708 if (lane > 0) { 2709 LOG_VERBOSE(BSL_LS_SOC_PORT, 2710 (BSL_META_U(unit, "%65s"), " ")); 2711 } 2712 LOG_VERBOSE(BSL_LS_SOC_PORT, 2713 (BSL_META_U(unit, 2714 " %2d %2d %2d\n"), 2715 pr->lane_info[lane]->pgw, 2716 pr->lane_info[lane]->tsc, 2717 pr->lane_info[lane]->port_index)); 2718 } 2719 } 2720 } 2721 2722 return; 2723 } 2724 2725 2726 /* 2727 * Function: 2728 * _soc_mn_port_resource_data_output 2729 * Purpose: 2730 * Debug output. 2731 * Parameters: 2732 * unit - (IN) Unit number. 2733 * nport - (IN) Number of elements in array resource. 2734 * resource - (IN) Port Resource FlexPort configuration. 2735 * pre_count - (IN) Array size for pre-FlexPort array. 2736 * pre_resource - (IN) Pre-FlexPort configuration array. 2737 * post_count - (IN) Array size for post-FlexPort array. 2738 * post_resource - (IN) Pre-FlexPort configuration array. 2739 * Returns: 2740 * SOC_E_XXX 2741 */ 2742 STATIC void 2743 _soc_mn_port_resource_data_output(int unit, 2744 int nport, soc_port_resource_t *resource, 2745 int pre_count, 2746 soc_port_resource_t *pre_resource, 2747 int post_count, 2748 soc_port_resource_t *post_resource) 2749 { 2750 LOG_VERBOSE(BSL_LS_SOC_PORT, 2751 (BSL_META_U(unit, 2752 "\n=============================================\n" 2753 "=========== SOC PORT RESOURCE DATA ==========\n" 2754 "=============================================\n" 2755 ))); 2756 2757 LOG_VERBOSE(BSL_LS_SOC_PORT, 2758 (BSL_META_U(unit, "\n"))); 2759 _soc_mn_port_resource_output(unit, 2760 "=== FlexPort Port Resource Data ===", 2761 nport, resource); 2762 2763 LOG_VERBOSE(BSL_LS_SOC_PORT, 2764 (BSL_META_U(unit, "\n"))); 2765 _soc_mn_port_resource_output(unit, 2766 "=== Pre-FlexPort Port Resource Data ===", 2767 pre_count, pre_resource); 2768 2769 LOG_VERBOSE(BSL_LS_SOC_PORT, 2770 (BSL_META_U(unit, "\n"))); 2771 _soc_mn_port_resource_output(unit, 2772 "=== Post-FlexPort Port Resource Data ===", 2773 post_count, post_resource); 2774 2775 LOG_VERBOSE(BSL_LS_SOC_PORT, 2776 (BSL_META_U(unit, "\n"))); 2777 return; 2778 } 2779 2780 2781 /* 2782 * Function: 2783 * _soc_mn_port_resource_data_init 2784 * Purpose: 2785 * Allocate and get pre and post FlexPort Port Resource 2786 * information for given FlexPort configuration. 2787 * Parameters: 2788 * unit - (IN) Unit number. 2789 * nport - (IN) Number of elements in array resource. 2790 * resource - (IN/OUT) Port Resource FlexPort configuration. 2791 * pre_count - (OUT) Array size for pre-FlexPort array. 2792 * pre_resource - (OUT) Pre-FlexPort configuration array. 2793 * post_count - (OUT) Array size for post-FlexPort array. 2794 * post_resource - (OUT) Pre-FlexPort configuration array. 2795 * pre_soc_info - (OUT) A subset of the SOC_INFO information 2796 * before the FlexPort operation. 2797 * Returns: 2798 * SOC_E_XXX 2799 * Note: 2800 * - Assumes data is Port Resource has been validated. 2801 * - Assumes array order is correct (deletes are first in array). 2802 * - Assumes pointer parameters are not null. 2803 * - Assumes the following fields have been filled already in input 2804 * SOC Port Resource data structure: 2805 * flags 2806 * logical_port 2807 * physical_port 2808 * speed 2809 * num_lanes 2810 * 2811 * 2812 * The 'resource' or main-FlexPort list contains both, all the elements 2813 * in the pre-FlexPort list followed by the elements in the post-FlexPort 2814 * list (in that order): 2815 * resource = pre_resource + post_resource 2816 * 2817 * The pre-FlexPort and post-FlexPort operation arrays are filled 2818 * out as follows: 2819 * 2820 * Pre-FlexPort array 2821 * This is the array of 'old' ports. 2822 * It contains current information for ports that are configured in the 2823 * system and are to be modified after the FlexPort operation. 2824 * This should include all mappings where ports are deleted/cleared 2825 * (i.e. physical_port is -1). 2826 * NOTE that even though the port is set to be 'deleted', 2827 * the actual final port mapping (after FlexPort) may 2828 * result to be the same, destroyed, or remapped based on what the rest 2829 * of the array configuration. 2830 * 2831 * Post-FlexPort array 2832 * This is the array of 'new' ports. 2833 * It contains the configuration information on the new ports that will 2834 * be configured in the system and are active (present) after 2835 * the FlexPort operation. 2836 * This should include mappings where the physical ports are not (-1). 2837 * The actual ports mappings can result to be the same, remapped or new, 2838 * based on the rest of the array information. 2839 * 2840 * Example: 2841 * 2842 * Logical_port --> Physical_port 2843 * 2844 * Main FlexPort array ('resource') 2845 * L1 --> -1 (current mapped to P1), mapping is SAME 2846 * L2 --> -1 (current mapped to P2), mapping is REMAP 2847 * L3 --> -1 (current mapped to P3), mapping is DESTROY 2848 * L1 --> P1 , mapping is SAME 2849 * L2 --> P5 , mapping is REMAP 2850 * L9 --> P9 , mapping is NEW 2851 * 2852 * Pre-FlexPort array 2853 * L1 --> P1 mapping is SAME 2854 * L2 --> P2 mapping is REMAP 2855 * L3 --> P3 mapping is DESTROY 2856 * 2857 * Post-FlexPort array 2858 * L1 --> P1 mapping is SAME 2859 * L2 --> P5 mapping is REMAP 2860 * L9 --> P9 mapping is NEW 2861 */ 2862 STATIC int 2863 _soc_mn_port_resource_data_init(int unit, 2864 int nport, soc_port_resource_t *resource, 2865 int *pre_count, 2866 soc_port_resource_t **pre_resource, 2867 int *post_count, 2868 soc_port_resource_t **post_resource, 2869 soc_mn_info_t *pre_soc_info) 2870 { 2871 int i; 2872 int lane; 2873 int num_lanes; 2874 int phy_port; 2875 int delete_count = 0; 2876 soc_port_resource_t *pr; 2877 soc_port_resource_t *pre_pr; 2878 soc_info_t *si = &SOC_INFO(unit); 2879 2880 /* Init parameters */ 2881 *pre_count = 0; 2882 *pre_resource = NULL; 2883 *post_count = 0; 2884 *post_resource = NULL; 2885 2886 2887 /************************************* 2888 * Fill main FlexPort information 2889 */ 2890 2891 2892 LOG_VERBOSE(BSL_LS_SOC_PORT, 2893 (BSL_META_U(unit, 2894 "\n====== SOC PORT RESOURCE DATA GATHER =====\n"))); 2895 2896 /* Get rest of SOC FlexPort information */ 2897 for (i = 0, pr = &resource[0]; i < nport; i++, pr++) { 2898 pr->mode = -1; 2899 /* Skip delete entries (assume these to be first in array) */ 2900 if (pr->physical_port == -1) { 2901 delete_count++; 2902 continue; 2903 } 2904 2905 phy_port = pr->physical_port; 2906 pr->prio_mask = MN_PHY_PORT(unit, phy_port).prio_mask; 2907 SOC_IF_ERROR_RETURN 2908 (soc_mn_port_oversub_get(unit, phy_port, pr->logical_port, 2909 &pr->oversub)); 2910 2911 /* 2912 * Get Lanes information 2913 * Assume lanes are arranged consecutively with respect to 2914 * the physical port number. 2915 */ 2916 for (lane = 0; lane < pr->num_lanes; lane++) { 2917 pr->lane_info[lane] = &MN_PHY_PORT_LANE(unit, phy_port + lane); 2918 } 2919 } 2920 2921 /* 2922 * Get port mode (quad, dual, single, tri) into 'resource' array. 2923 */ 2924 SOC_IF_ERROR_RETURN 2925 (_soc_mn_port_resource_mode_get(unit, 2926 nport, resource)); 2927 2928 /* Set count for pre and post FlexPort arrays */ 2929 *pre_count = delete_count; 2930 *post_count = nport - delete_count; 2931 2932 2933 /******************************** 2934 * Pre-FlexPort array 2935 */ 2936 /* Allocate memory */ 2937 if ((*pre_count) > 0) { 2938 *pre_resource = sal_alloc(sizeof(soc_port_resource_t) * (*pre_count), 2939 "pre_port_resource"); 2940 if (*pre_resource == NULL) { 2941 LOG_ERROR(BSL_LS_SOC_PORT, 2942 (BSL_META_U(unit, 2943 "Unable to allocate memory for pre resource " 2944 "array in FlexPort operation\n"))); 2945 return SOC_E_MEMORY; 2946 } 2947 sal_memset(*pre_resource, 0, 2948 sizeof(soc_port_resource_t) * (*pre_count)); 2949 } 2950 /* Fill information */ 2951 for (i = 0, pre_pr = *pre_resource, pr = &resource[0]; 2952 i < *pre_count; 2953 i++, pre_pr++, pr++) { 2954 2955 /* Assume physical port is valid */ 2956 phy_port = si->port_l2p_mapping[pr->logical_port]; 2957 2958 pre_pr->flags = pr->flags; 2959 pre_pr->logical_port = pr->logical_port; 2960 pre_pr->physical_port = phy_port; 2961 pre_pr->mmu_port = si->port_p2m_mapping[phy_port]; 2962 pre_pr->num_lanes = si->port_num_lanes[pr->logical_port]; 2963 pre_pr->prio_mask = MN_PHY_PORT(unit, phy_port).prio_mask; 2964 pre_pr->oversub = 2965 SOC_PBMP_MEMBER(si->oversub_pbm, pre_pr->logical_port) ? 1 : 0; 2966 2967 pre_pr->speed = si->port_speed_max[pr->logical_port]; 2968 /* Set inactive flag to indicate port is disabled */ 2969 if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, pr->logical_port)) { 2970 pre_pr->flags |= SOC_PORT_RESOURCE_INACTIVE; 2971 2972 pre_pr->mode = -1; 2973 } else { 2974 SOC_IF_ERROR_RETURN 2975 (soc_portctrl_port_mode_get(unit, pr->logical_port, 2976 &(pre_pr->mode), &num_lanes)); 2977 } 2978 2979 /* 2980 * Get Lanes information 2981 * Assume lanes are arranged consecutively with respect to 2982 * the physical port number. 2983 */ 2984 for (lane = 0; lane < pre_pr->num_lanes; lane++) { 2985 pre_pr->lane_info[lane] = 2986 &MN_PHY_PORT_LANE(unit, phy_port + lane); 2987 } 2988 2989 } 2990 2991 2992 /******************************** 2993 * Post-FlexPort array 2994 * 2995 * Just use the main FlexPort array since this has 2996 * all the new information that is needed for the 'post' array. 2997 */ 2998 if ((*post_count) > 0) { 2999 *post_resource = &resource[(*pre_count)]; 3000 } 3001 3002 3003 /******************************** 3004 * Pre-FlexPort SOC info data 3005 * 3006 * This contains partial information of the current 3007 * SOC information (pre-FlexPort) needed during later 3008 * stages of the FlexPort reconfiguration sequence. 3009 */ 3010 sal_memset(pre_soc_info, 0, sizeof(*pre_soc_info)); 3011 for (i = 0; i < SOC_MAX_NUM_PORTS; i++) { 3012 pre_soc_info->port_l2p_mapping[i] = si->port_l2p_mapping[i]; 3013 pre_soc_info->port_p2l_mapping[i] = si->port_p2l_mapping[i]; 3014 pre_soc_info->port_p2m_mapping[i] = si->port_p2m_mapping[i]; 3015 pre_soc_info->port_m2p_mapping[i] = si->port_m2p_mapping[i]; 3016 pre_soc_info->port_group[i] = si->port_group[i]; 3017 pre_soc_info->port_speed_max[i] = si->port_speed_max[i]; 3018 pre_soc_info->port_num_lanes[i] = si->port_num_lanes[i]; 3019 } 3020 3021 SOC_PBMP_ASSIGN(pre_soc_info->xpipe_pbm, si->xpipe_pbm); 3022 SOC_PBMP_ASSIGN(pre_soc_info->oversub_pbm, si->oversub_pbm); 3023 3024 return SOC_E_NONE; 3025 } 3026 3027 /* 3028 * Function: 3029 * _soc_mn_soc_info_ptype_update 3030 * Purpose: 3031 * Update the SOC_INFO ptype information and port names based 3032 * on the port type bitmaps. 3033 * Parameters: 3034 * unit - (IN) Unit number. 3035 * Returns: 3036 * SOC_E_XXX 3037 * Notes: 3038 * Assumes linkscan is paused, COUNTER_LOCK and SOC_CONTROL_LOCK 3039 * locks are taken. 3040 */ 3041 STATIC int 3042 _soc_mn_soc_info_ptype_update(int unit) 3043 { 3044 soc_info_t *si = &SOC_INFO(unit); 3045 int phy_port; 3046 int logic_port; 3047 int blk; 3048 int bindex; 3049 int port_idx; 3050 3051 /* 3052 * Update ptype information 3053 */ 3054 #define RECONFIGURE_PORT_TYPE_INFO(ptype) \ 3055 si->ptype.num = 0; \ 3056 si->ptype.min = si->ptype.max = -1; \ 3057 sal_memset(si->ptype.port, 0, sizeof(si->ptype.port)); \ 3058 PBMP_ITER(si->ptype.bitmap, logic_port) { \ 3059 si->port_offset[logic_port] = si->ptype.num; \ 3060 si->ptype.port[si->ptype.num++] = logic_port; \ 3061 if (si->ptype.min < 0) { \ 3062 si->ptype.min = logic_port; \ 3063 } \ 3064 if (logic_port > si->ptype.max) { \ 3065 si->ptype.max = logic_port; \ 3066 } \ 3067 } 3068 3069 RECONFIGURE_PORT_TYPE_INFO(ge); 3070 RECONFIGURE_PORT_TYPE_INFO(xe); 3071 RECONFIGURE_PORT_TYPE_INFO(cxx); 3072 RECONFIGURE_PORT_TYPE_INFO(ce); 3073 RECONFIGURE_PORT_TYPE_INFO(xl); 3074 RECONFIGURE_PORT_TYPE_INFO(cl); 3075 RECONFIGURE_PORT_TYPE_INFO(gx); 3076 RECONFIGURE_PORT_TYPE_INFO(ether); 3077 RECONFIGURE_PORT_TYPE_INFO(hg); 3078 RECONFIGURE_PORT_TYPE_INFO(st); 3079 RECONFIGURE_PORT_TYPE_INFO(port); 3080 RECONFIGURE_PORT_TYPE_INFO(all); 3081 RECONFIGURE_PORT_TYPE_INFO(cpri); 3082 RECONFIGURE_PORT_TYPE_INFO(rsvd4); 3083 3084 #undef RECONFIGURE_PORT_TYPE_INFO 3085 3086 3087 /* 3088 * Update block port 3089 * Use first logical port on block (logic follows ESW driver 3090 * soc_info_config(). 3091 */ 3092 for (phy_port = 0; ; phy_port++) { 3093 3094 blk = SOC_PORT_IDX_BLOCK(unit, phy_port, 0); 3095 bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, 0); 3096 if (blk < 0 && bindex < 0) { /* End of port list */ 3097 break; 3098 } 3099 3100 logic_port = si->port_p2l_mapping[phy_port]; 3101 if (logic_port < 0) { 3102 continue; 3103 } 3104 3105 for (port_idx = 0; port_idx < SOC_DRIVER(unit)->port_num_blktype; port_idx++) { 3106 blk = SOC_PORT_IDX_BLOCK(unit, phy_port, port_idx); 3107 if (blk < 0) { /* End of block list of each port */ 3108 break; 3109 } 3110 3111 if (si->block_port[blk] < 0) { 3112 si->block_port[blk] = logic_port; 3113 } 3114 } 3115 } 3116 3117 /* Update user port mappings (includes port names update) */ 3118 soc_esw_dport_init(unit); 3119 3120 return SOC_E_NONE; 3121 } 3122 3123 #define PORT_IS_CXX(pport) FALSE 3124 3125 /* 3126 * Function: 3127 * _soc_mn_soc_info_ptype_ports_add 3128 * Purpose: 3129 * Set the port type bitmaps and block information in SOC_INFO 3130 * for ports to be configured during the FlexPort operation. 3131 * Parameters: 3132 * unit - (IN) Unit number. 3133 * post_count - (IN) Array size. 3134 * post_resource - (IN) Array of ports to add. 3135 * Returns: 3136 * SOC_E_XXX 3137 * Notes: 3138 * Assumes linkscan is paused, COUNTER_LOCK and SOC_CONTROL_LOCK 3139 * locks are taken. 3140 */ 3141 STATIC int 3142 _soc_mn_soc_info_ptype_ports_add(int unit, 3143 int post_count, 3144 soc_port_resource_t *post_resource) 3145 { 3146 soc_info_t *si = &SOC_INFO(unit); 3147 soc_port_resource_t *pr; 3148 int i; 3149 int phy_port; 3150 int logic_port; 3151 int blk; 3152 int bindex; 3153 int blktype; 3154 int old_blktype; 3155 int port_idx; 3156 3157 /* 3158 * Add to port type bitmaps and block information 3159 */ 3160 for (i = 0, pr = &post_resource[0]; i < post_count; i++, pr++) { 3161 3162 logic_port = pr->logical_port; 3163 phy_port = pr->physical_port; 3164 3165 if (!si->port_speed_max[logic_port]) { 3166 LOG_ERROR(BSL_LS_SOC_PORT, (BSL_META_U(unit, 3167 "Invalid speed %d for " 3168 "logical port %d\n"), 3169 si->port_speed_max[logic_port], logic_port)); 3170 return SOC_E_INTERNAL; 3171 } 3172 3173 /* Clear bitmaps */ 3174 SOC_PBMP_PORT_REMOVE(si->cl.bitmap, logic_port); 3175 SOC_PBMP_PORT_REMOVE(si->cxx.bitmap, logic_port); 3176 SOC_PBMP_PORT_REMOVE(si->clg2.bitmap, logic_port); 3177 SOC_PBMP_PORT_REMOVE(si->xl.bitmap, logic_port); 3178 SOC_PBMP_PORT_REMOVE(si->xlb0.bitmap, logic_port); 3179 SOC_PBMP_PORT_REMOVE(si->ether.bitmap, logic_port); 3180 SOC_PBMP_PORT_REMOVE(si->hg.bitmap, logic_port); 3181 SOC_PBMP_PORT_REMOVE(si->xe.bitmap, logic_port); 3182 SOC_PBMP_PORT_REMOVE(si->ce.bitmap, logic_port); 3183 SOC_PBMP_PORT_REMOVE(si->ge.bitmap, logic_port); 3184 SOC_PBMP_PORT_REMOVE(si->st.bitmap, logic_port); 3185 3186 if (pr->encap == SOC_ENCAP_IEEE) { 3187 if (si->port_speed_max[logic_port] >= 100000) { /* CE */ 3188 SOC_PBMP_PORT_ADD(si->ce.bitmap, logic_port); 3189 } else if (si->port_speed_max[logic_port] < 10000) { /* GE */ 3190 SOC_PBMP_PORT_ADD(si->ge.bitmap, logic_port); 3191 } else { /* XE */ 3192 SOC_PBMP_PORT_ADD(si->xe.bitmap, logic_port); 3193 } 3194 SOC_PBMP_PORT_ADD(si->ether.bitmap, logic_port); 3195 } else if ((pr->encap == SOC_ENCAP_CPRI) || (pr->encap == SOC_ENCAP_RSVD4)) { 3196 SOC_PBMP_PORT_ADD(si->cpri.bitmap, logic_port); 3197 } else { /* HG */ 3198 SOC_PBMP_PORT_ADD(si->hg.bitmap, logic_port); 3199 SOC_PBMP_PORT_ADD(si->st.bitmap, logic_port); 3200 } 3201 3202 SOC_PBMP_PORT_ADD(si->port.bitmap, logic_port); 3203 SOC_PBMP_PORT_ADD(si->all.bitmap, logic_port); 3204 SOC_PBMP_PORT_ADD(si->gx.bitmap, logic_port); 3205 3206 3207 blk = SOC_PORT_IDX_BLOCK(unit, phy_port, 0); 3208 bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, 0); 3209 if (blk < 0 && bindex < 0) { /* End of regsfile port list */ 3210 continue; 3211 } 3212 3213 blktype = -1; 3214 for (port_idx = 0; port_idx < SOC_DRIVER(unit)->port_num_blktype; port_idx++) { 3215 3216 blk = SOC_PORT_IDX_BLOCK(unit, phy_port, port_idx); 3217 if (blk < 0) { /* End of block list of each port */ 3218 break; 3219 } 3220 3221 old_blktype = blktype; 3222 blktype = SOC_BLOCK_INFO(unit, blk).type; 3223 3224 switch (blktype) { 3225 3226 case SOC_BLK_CLPORT: 3227 if (PORT_IS_FALCON(phy_port) || 3228 ((PORT_IS_CXX(phy_port) && (si->port_speed_max[logic_port] >= 100000)))) { 3229 /*PM4x25 or PM12x10 in CAUI10 mode */ 3230 SOC_PBMP_PORT_ADD(si->cl.bitmap, logic_port); 3231 } else { 3232 blktype = old_blktype; 3233 continue; 3234 } 3235 break; 3236 3237 case SOC_BLK_CLG2PORT: 3238 if (PORT_IS_FALCON(phy_port)) { 3239 SOC_PBMP_PORT_ADD(si->clg2.bitmap, logic_port); 3240 } else { 3241 blktype = old_blktype; 3242 continue; 3243 } 3244 break; 3245 3246 case SOC_BLK_XLPORT: 3247 if ((PORT_IS_CXX(phy_port)) && (si->port_speed_max[logic_port] >= 100000)) { 3248 /* In CAUI10 mode, enable XLPORT block for all 3 cores */ 3249 if (si->block_port[blk] < 0) { 3250 si->block_port[blk] = logic_port; 3251 } 3252 if (si->block_port[blk + 1] < 0) { 3253 si->block_port[blk + 1] = logic_port; 3254 } 3255 if (si->block_port[blk + 2] < 0) { 3256 si->block_port[blk + 2] = logic_port; 3257 } 3258 si->block_valid[blk] += 1; 3259 si->block_valid[blk + 1] += 1; 3260 si->block_valid[blk + 2] += 1; 3261 /* No need to add in bitmap */ 3262 continue; 3263 } else { 3264 SOC_PBMP_PORT_ADD(si->xl.bitmap, logic_port); 3265 } 3266 break; 3267 3268 case SOC_BLK_PGW_CL: 3269 /* Don't use the name from this block */ 3270 blktype = old_blktype; 3271 break; 3272 3273 default: 3274 break; 3275 } 3276 /* Block info is still intact in case of legacy flexport 3277 * Only update port bitmaps and continue 3278 */ 3279 if (pr->flags & SOC_PORT_RESOURCE_I_MAP) { 3280 continue; 3281 } 3282 /* Update block information */ 3283 si->block_valid[blk] += 1; 3284 3285 if (si->block_port[blk] < 0) { 3286 si->block_port[blk] = logic_port; 3287 } 3288 SOC_PBMP_PORT_ADD(si->block_bitmap[blk], logic_port); 3289 3290 } /* For each block in the given port */ 3291 3292 /* Block info is still intact, so skip updating it in case of legacy flexport 3293 */ 3294 if (pr->flags & SOC_PORT_RESOURCE_I_MAP) { 3295 continue; 3296 } 3297 3298 si->port_type[logic_port] = blktype; 3299 si->port_num++; 3300 3301 /* Update CXXPORT block information */ 3302 if (SOC_SUCCESS(soc_monterey_port_reg_blk_index_get 3303 (unit, logic_port, SOC_BLK_CXXPORT, &blk))) { 3304 si->block_valid[blk] += 1; 3305 3306 if (si->block_port[blk] < 0) si->block_port[blk] = logic_port; 3307 } 3308 3309 } /* For each port */ 3310 3311 /* Need to update rest of ptype information */ 3312 SOC_IF_ERROR_RETURN(_soc_mn_soc_info_ptype_update(unit)); 3313 3314 return SOC_E_NONE; 3315 } 3316 3317 3318 /* 3319 * Function: 3320 * _soc_mn_soc_info_ptype_ports_delete 3321 * Purpose: 3322 * Clear the port type bitmaps and block information in SOC_INFO 3323 * for ports to be removed during the FlexPort operation. 3324 * Parameters: 3325 * unit - (IN) Unit number. 3326 * pre_count - (IN) Array size. 3327 * pre_resource - (IN) Array for ports to delete. 3328 * Returns: 3329 * SOC_E_XXX 3330 * Notes: 3331 * Assumes linkscan is paused, COUNTER_LOCK and SOC_CONTROL_LOCK 3332 * locks are taken. 3333 */ 3334 STATIC int 3335 _soc_mn_soc_info_ptype_ports_delete(int unit, 3336 int pre_count, 3337 soc_port_resource_t *pre_resource) 3338 { 3339 soc_info_t *si = &SOC_INFO(unit); 3340 soc_port_resource_t *pr; 3341 int i; 3342 int phy_port; 3343 int logic_port; 3344 int blk; 3345 int blktype; 3346 int bindex; 3347 int port_idx; 3348 3349 /* 3350 * Clear port bitmaps and block information 3351 */ 3352 for (i = 0, pr = &pre_resource[0]; i < pre_count; i++, pr++) { 3353 3354 /* Skip deletion of block info in case of legacy flexport 3355 * Port bitmaps will be cleared and updated in _soc_ap_soc_info_ptype_ports_add 3356 * as per post_resource 3357 */ 3358 3359 if (pr->flags & SOC_PORT_RESOURCE_I_MAP) { 3360 continue; 3361 } 3362 3363 logic_port = pr->logical_port; 3364 phy_port = pr->physical_port; 3365 3366 /* 3367 * Clear port from all possible port bitmaps where a flexed port 3368 * can be a member of. 3369 */ 3370 3371 if (phy_port == -1) { 3372 continue; 3373 } 3374 3375 blk = SOC_PORT_IDX_BLOCK(unit, phy_port, 0); 3376 bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, 0); 3377 if (blk < 0 && bindex < 0) { /* End of regsfile port list */ 3378 continue; 3379 } 3380 3381 blktype = -1; 3382 /* Clear block information */ 3383 for (port_idx = 0; port_idx < SOC_DRIVER(unit)->port_num_blktype; port_idx++) { 3384 3385 blk = SOC_PORT_IDX_BLOCK(unit, phy_port, port_idx); 3386 blktype = SOC_BLOCK_INFO(unit, blk).type; 3387 if (blk < 0) { /* End of block list of each port */ 3388 break; 3389 } 3390 3391 /* Update block information */ 3392 if (si->block_valid[blk] > 0) { 3393 si->block_valid[blk] -= 1; 3394 } 3395 if (si->block_port[blk] == logic_port) { 3396 si->block_port[blk] = REG_PORT_ANY; 3397 } 3398 if (blktype == SOC_BLK_XLPORT) { 3399 /* Disable XLPORT block for last 2 cores in case CAUI10 port is being deleted */ 3400 if (PORT_IS_CXX(phy_port) && (si->port_speed_max[logic_port] >= 100000)) { 3401 if (si->block_valid[blk + 1] > 0) { 3402 si->block_valid[blk + 1] -= 1; 3403 } 3404 if (si->block_valid[blk + 2] > 0) { 3405 si->block_valid[blk + 2] -= 1; 3406 } 3407 if (si->block_port[blk + 1] == logic_port) { 3408 si->block_port[blk + 1] = REG_PORT_ANY; 3409 } 3410 if (si->block_port[blk + 2] == logic_port) { 3411 si->block_port[blk + 2] = REG_PORT_ANY; 3412 } 3413 } 3414 } 3415 3416 SOC_PBMP_PORT_REMOVE(si->block_bitmap[blk], logic_port); 3417 3418 } /* For each block in the given port */ 3419 3420 si->port_type[logic_port] = 0; 3421 si->port_offset[logic_port] = 0; 3422 3423 if (si->port_num > 0) { 3424 si->port_num--; 3425 } 3426 /* Clear CXXPORT block information */ 3427 if (SOC_SUCCESS(soc_monterey_port_reg_blk_index_get 3428 (unit, logic_port, SOC_BLK_CXXPORT, &blk))) { 3429 if (si->block_valid[blk] > 0) { 3430 si->block_valid[blk] -= 1; 3431 } 3432 if (si->block_port[blk] == logic_port) { 3433 si->block_port[blk] = REG_PORT_ANY; 3434 } 3435 } 3436 /* 3437 * Clear port from all possible port bitmaps where a flexed port 3438 * can be a member of. 3439 */ 3440 SOC_PBMP_PORT_REMOVE(si->ge.bitmap, logic_port); 3441 SOC_PBMP_PORT_REMOVE(si->xe.bitmap, logic_port); 3442 SOC_PBMP_PORT_REMOVE(si->cxx.bitmap, logic_port); 3443 SOC_PBMP_PORT_REMOVE(si->ce.bitmap, logic_port); 3444 SOC_PBMP_PORT_REMOVE(si->xl.bitmap, logic_port); 3445 SOC_PBMP_PORT_REMOVE(si->xlb0.bitmap, logic_port); 3446 SOC_PBMP_PORT_REMOVE(si->cl.bitmap, logic_port); 3447 SOC_PBMP_PORT_REMOVE(si->clg2.bitmap, logic_port); 3448 SOC_PBMP_PORT_REMOVE(si->gx.bitmap, logic_port); 3449 SOC_PBMP_PORT_REMOVE(si->ether.bitmap, logic_port); 3450 SOC_PBMP_PORT_REMOVE(si->cpri.bitmap, logic_port); 3451 SOC_PBMP_PORT_REMOVE(si->hg.bitmap, logic_port); 3452 SOC_PBMP_PORT_REMOVE(si->st.bitmap, logic_port); 3453 SOC_PBMP_PORT_REMOVE(si->port.bitmap, logic_port); 3454 SOC_PBMP_PORT_REMOVE(si->all.bitmap, logic_port); 3455 3456 } /* For each port */ 3457 3458 /* Update rest of ptype information */ 3459 SOC_IF_ERROR_RETURN(_soc_mn_soc_info_ptype_update(unit)); 3460 3461 return SOC_E_NONE; 3462 } 3463 3464 3465 /* 3466 * Function: 3467 * _soc_mn_soc_counter_ports_add 3468 * Purpose: 3469 * Add ports to SOC counter map. 3470 * Parameters: 3471 * unit - (IN) Unit number. 3472 * post_count - (IN) Array size. 3473 * post_resource - (IN) Array of ports to add. 3474 * Returns: 3475 * SOC_E_XXX 3476 * Notes: 3477 * Assumes linkscan is paused, COUNTER_LOCK and SOC_CONTROL_LOCK 3478 * locks are taken. 3479 */ 3480 STATIC int 3481 _soc_mn_soc_counter_ports_add(int unit, 3482 int post_count, 3483 soc_port_resource_t *post_resource) 3484 { 3485 soc_control_t *soc = SOC_CONTROL(unit); 3486 soc_port_resource_t *pr; 3487 int i; 3488 int phy_port; 3489 int logic_port; 3490 int blk; 3491 int bindex; 3492 int blktype; 3493 int port_idx; 3494 soc_ctr_type_t ctype; 3495 int rv = SOC_E_NONE; 3496 3497 for (i = 0, pr = &post_resource[0]; i < post_count; i++, pr++) { 3498 logic_port = pr->logical_port; 3499 phy_port = pr->physical_port; 3500 3501 blk = SOC_PORT_IDX_BLOCK(unit, phy_port, 0); 3502 bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, 0); 3503 if (blk < 0 && bindex < 0) { /* End of regsfile port list */ 3504 continue; 3505 } 3506 3507 for (port_idx = 0; port_idx < SOC_DRIVER(unit)->port_num_blktype; port_idx++) { 3508 blk = SOC_PORT_IDX_BLOCK(unit, phy_port, port_idx); 3509 if (blk < 0) { /* End of block list of each port */ 3510 break; 3511 } 3512 3513 blktype = SOC_BLOCK_INFO(unit, blk).type; 3514 3515 switch (blktype) { 3516 case SOC_BLK_CLPORT: 3517 case SOC_BLK_XLPORT: 3518 case SOC_BLK_XLPORTB0: 3519 ctype = SOC_CTR_TYPE_XE; 3520 break; 3521 case SOC_BLK_CLG2PORT: 3522 ctype = SOC_CTR_TYPE_CE; 3523 break; 3524 case SOC_BLK_CPRI: 3525 if(IS_CPRI_PORT(unit, logic_port) && 3526 SOC_IS_MONTEREY(unit) ) { 3527 ctype = SOC_CTR_TYPE_CPU; 3528 } else 3529 { 3530 ctype = -1; 3531 } 3532 break; 3533 default: 3534 ctype = -1; 3535 break; 3536 } 3537 3538 if (ctype != -1) { 3539 /* Adding of dma counter descriptors is only necessary when the 3540 * counter thread is running 3541 * this check is necessary to avoid reallocating the dma descriptos 3542 * when the conter thread is stopped running before the 3543 * flex operation 3544 */ 3545 if (soc->counter_interval) { 3546 rv = soc_counter_port_sbusdma_desc_alloc(unit, logic_port); 3547 if (SOC_FAILURE(rv)) { 3548 LOG_ERROR(BSL_LS_SOC_PORT, 3549 (BSL_META_U(unit, 3550 "Error! Unable to allocate SBUS DMA descriptors per" 3551 " logical_port %d \n"), 3552 logic_port)); 3553 return rv; 3554 } 3555 } 3556 SOC_IF_ERROR_RETURN 3557 (soc_port_cmap_set(unit, logic_port, ctype)); 3558 SOC_PBMP_PORT_ADD(soc->counter_pbmp, logic_port); 3559 break; 3560 } 3561 } /* For each block in the given port */ 3562 3563 } /* For each port */ 3564 3565 return SOC_E_NONE; 3566 } 3567 3568 3569 /* 3570 * Function: 3571 * _soc_mn_soc_counter_ports_delete 3572 * Purpose: 3573 * Delete ports from SOC counter map. 3574 * Parameters: 3575 * unit - (IN) Unit number. 3576 * pre_count - (IN) Array size. 3577 * pre_resource - (IN) Array of ports to delete. 3578 * Returns: 3579 * SOC_E_XXX 3580 * Notes: 3581 * Assumes linkscan is paused, COUNTER_LOCK and SOC_CONTROL_LOCK 3582 * locks are taken. 3583 */ 3584 STATIC int 3585 _soc_mn_soc_counter_ports_delete(int unit, 3586 int pre_count, 3587 soc_port_resource_t *pre_resource) 3588 { 3589 soc_control_t *soc = SOC_CONTROL(unit); 3590 soc_port_resource_t *pr; 3591 int i; 3592 int phy_port; 3593 int logic_port; 3594 int rv = SOC_E_NONE; 3595 3596 /* Clear counter */ 3597 for (i = 0, pr = &pre_resource[0]; i < pre_count; i++, pr++) { 3598 logic_port = pr->logical_port; 3599 phy_port = pr->physical_port; 3600 3601 if (phy_port == -1) { 3602 continue; 3603 } 3604 3605 /* Delete the counter dma descriptors */ 3606 rv = soc_counter_port_sbusdma_desc_free(unit, logic_port); 3607 if (SOC_FAILURE(rv)) { 3608 LOG_ERROR(BSL_LS_SOC_PORT, 3609 (BSL_META_U(unit, 3610 "Error! Unable to delete SBUS DMA descriptors per" 3611 " logical_port %d \n"), 3612 logic_port)); 3613 return rv; 3614 } 3615 3616 /* 3617 * If 'inactive' flag, don't do anything 3618 */ 3619 if (pr->flags & SOC_PORT_RESOURCE_I_MAP) { 3620 continue; 3621 } 3622 3623 soc->counter_map[logic_port] = 0; 3624 SOC_PBMP_PORT_REMOVE(soc->counter_pbmp, logic_port); 3625 } 3626 3627 return SOC_E_NONE; 3628 } 3629 3630 3631 /* 3632 * Function: 3633 * _soc_mn_soc_info_ports_add 3634 * Purpose: 3635 * Add ports to the SOC_INFO and SOC data structures. 3636 * 3637 * Set information for mappings that are: 3638 * - Same : logical to physical mapping are the same. 3639 * - Remapped : different port mapping assignment, logical port existed. 3640 * - New : logical port did not exist prior to FlexPort. 3641 * 3642 * Parameters: 3643 * unit - (IN) Unit number. 3644 * pre_count - (IN) Array size. 3645 * pre_resource - (IN) Array for ports to delete. 3646 * Returns: 3647 * SOC_E_XXX 3648 * Notes: 3649 * Assumes linkscan is paused, COUNTER_LOCK and SOC_CONTROL_LOCK 3650 * locks are taken. 3651 */ 3652 STATIC int 3653 _soc_mn_soc_info_ports_add(int unit, 3654 int post_count, 3655 soc_port_resource_t *post_resource) 3656 { 3657 soc_info_t *si = &SOC_INFO(unit); 3658 soc_port_resource_t *pr; 3659 int i; 3660 int logic_port; 3661 int phy_port, port_is_hsp; 3662 3663 LOG_VERBOSE(BSL_LS_SOC_PORT, 3664 (BSL_META_U(unit, 3665 "SOC_INFO Ports Add\n"))); 3666 3667 3668 for (i = 0, pr = &post_resource[0]; i < post_count; i++, pr++) { 3669 logic_port = pr->logical_port; 3670 phy_port = pr->physical_port; 3671 3672 LOG_VERBOSE(BSL_LS_SOC_PORT, 3673 (BSL_META_U(unit, 3674 " SOC_INFO: " 3675 "Add logical=%d physical=%d\n"), 3676 logic_port, phy_port)); 3677 3678 3679 /* Always remove from disabled bitmap */ 3680 SOC_PBMP_PORT_REMOVE(si->all.disabled_bitmap, logic_port); 3681 3682 /* Port Mapping related information */ 3683 si->port_l2p_mapping[logic_port] = phy_port; 3684 si->port_p2l_mapping[phy_port] = logic_port; 3685 3686 /* Pipeline */ 3687 SOC_PBMP_PORT_ADD(si->xpipe_pbm, logic_port); 3688 si->port_pipe[logic_port] = 0; 3689 3690 /* Port data information */ 3691 /* Port data information */ 3692 if (!(pr->flags & SOC_PORT_RESOURCE_SPEED)) { 3693 si->port_init_speed[logic_port] = pr->speed; 3694 } 3695 si->port_speed_max[logic_port] = pr->speed; 3696 si->port_num_lanes[logic_port] = pr->num_lanes; 3697 si->port_group[logic_port] = MN_PHY_PORT_LANE(unit, phy_port).pgw; 3698 si->port_serdes[logic_port] = (phy_port - 1) / MN_PORTS_PER_TSC; 3699 if (pr->roe_compression) { 3700 SOC_PBMP_PORT_ADD(si->roe_compression, logic_port); 3701 } 3702 if (pr->oversub) { 3703 SOC_PBMP_PORT_ADD(si->oversub_pbm, logic_port); 3704 } else { 3705 SOC_PBMP_PORT_REMOVE(si->oversub_pbm, logic_port); 3706 } 3707 if (pr->encap == SOC_ENCAP_CPRI) { 3708 SOC_PBMP_PORT_ADD(si->cpri.bitmap, logic_port); 3709 SOC_PBMP_PORT_REMOVE(si->rsvd4.bitmap, logic_port); 3710 } else if (pr->encap == SOC_ENCAP_RSVD4) { 3711 SOC_PBMP_PORT_ADD(si->cpri.bitmap, logic_port); 3712 SOC_PBMP_PORT_ADD(si->rsvd4.bitmap, logic_port); 3713 } else { 3714 SOC_PBMP_PORT_REMOVE(si->cpri.bitmap, logic_port); 3715 SOC_PBMP_PORT_REMOVE(si->rsvd4.bitmap, logic_port); 3716 } 3717 if ((pr->encap == SOC_ENCAP_CPRI) || (pr->encap == SOC_ENCAP_RSVD4)) { 3718 si->port_init_speed[logic_port] = pr->speed; 3719 } 3720 3721 if (pr->encap == SOC_ENCAP_IEEE) { 3722 SOC_PBMP_PORT_ADD(si->xe.bitmap, logic_port); 3723 } else { 3724 SOC_PBMP_PORT_REMOVE(si->xe.bitmap, logic_port); 3725 } 3726 3727 /* If this is a high speed port, we need to add it to the extended 3728 queues port bitmap so that nodes and queues will be able to be 3729 assigned properly. */ 3730 port_is_hsp = (soc_property_port_get(unit, logic_port, spn_PORT_SCHED_HSP, -1)); 3731 if (port_is_hsp == -1) { 3732 port_is_hsp = soc_monterey_mmu_hsp_port_reserve(unit, logic_port, pr->speed); 3733 } 3734 3735 if (port_is_hsp) { 3736 SOC_PBMP_PORT_ADD(si->eq_pbm, logic_port); 3737 } else { 3738 SOC_PBMP_PORT_REMOVE(si->eq_pbm, logic_port); 3739 } 3740 } 3741 3742 SOC_PBMP_ASSIGN(si->pipe_pbm[0], si->xpipe_pbm); 3743 3744 3745 /* Add to port ptype bitmap and block information */ 3746 SOC_IF_ERROR_RETURN 3747 (_soc_mn_soc_info_ptype_ports_add(unit, 3748 post_count, post_resource)); 3749 3750 /* Add to counter map */ 3751 SOC_IF_ERROR_RETURN 3752 (_soc_mn_soc_counter_ports_add(unit, 3753 post_count, post_resource)); 3754 3755 return SOC_E_NONE; 3756 } 3757 3758 3759 /* 3760 * Function: 3761 * _soc_mn_soc_info_ports_delete 3762 * Purpose: 3763 * Delete ports from the SOC_INFO and SOC data structures. 3764 * 3765 * This would be called to clear information for mappings that are: 3766 * - Same : logical to physical mapping are the same after FlexPort. 3767 * - Remapped : different port mapping assignment, logical port existed. 3768 * - Destroyed: logical port do no longer exist after FlexPort. 3769 * 3770 * Parameters: 3771 * unit - (IN) Unit number. 3772 * pre_count - (IN) Array size. 3773 * pre_resource - (IN) Array for ports to delete. 3774 * Returns: 3775 * SOC_E_XXX 3776 * Notes: 3777 * Assumes linkscan is paused, COUNTER_LOCK and SOC_CONTROL_LOCK 3778 * locks are taken. 3779 */ 3780 STATIC int 3781 _soc_mn_soc_info_ports_delete(int unit, 3782 int pre_count, 3783 soc_port_resource_t *pre_resource) 3784 { 3785 soc_info_t *si = &SOC_INFO(unit); 3786 soc_port_resource_t *pr; 3787 int i; 3788 int logic_port; 3789 int phy_port; 3790 3791 LOG_VERBOSE(BSL_LS_SOC_PORT, 3792 (BSL_META_U(unit, 3793 "SOC_INFO Ports Delete\n"))); 3794 3795 3796 /* Delete from counter map */ 3797 SOC_IF_ERROR_RETURN 3798 (_soc_mn_soc_counter_ports_delete(unit, 3799 pre_count, pre_resource)); 3800 3801 /* Delete from port ptype bitmap and block information */ 3802 SOC_IF_ERROR_RETURN 3803 (_soc_mn_soc_info_ptype_ports_delete(unit, 3804 pre_count, pre_resource)); 3805 3806 /* Port Mapping related information */ 3807 for (i = 0, pr = &pre_resource[0]; i < pre_count; i++, pr++) { 3808 logic_port = pr->logical_port; 3809 phy_port = pr->physical_port; 3810 3811 LOG_VERBOSE(BSL_LS_SOC_PORT, 3812 (BSL_META_U(unit, 3813 " SOC_INFO: " 3814 "Delete logical=%d physical=%d\n"), 3815 logic_port, phy_port)); 3816 3817 /* 3818 * If 'inactive' flag, just add port to disabled bitmap. 3819 * This is part of the legacy API behavior. 3820 */ 3821 if (pr->flags & SOC_PORT_RESOURCE_I_MAP) { 3822 SOC_PBMP_PORT_ADD(si->all.disabled_bitmap, logic_port); 3823 continue; 3824 } 3825 3826 /* Remove from disabled bitmap */ 3827 SOC_PBMP_PORT_REMOVE(si->all.disabled_bitmap, logic_port); 3828 3829 /* Port Mapping related information */ 3830 si->port_l2p_mapping[logic_port] = -1; 3831 if (phy_port != -1) { 3832 si->port_p2l_mapping[phy_port] = -1; 3833 } 3834 3835 /* Pipeline */ 3836 if (phy_port != -1) { 3837 SOC_PBMP_PORT_REMOVE(si->xpipe_pbm, logic_port); 3838 } 3839 3840 if (SOC_PBMP_MEMBER(si->eq_pbm, logic_port)) { 3841 SOC_PBMP_PORT_REMOVE(si->eq_pbm, logic_port); 3842 } 3843 3844 /* Logical port related information */ 3845 if (!(pr->flags & SOC_PORT_RESOURCE_SPEED)) { 3846 si->port_init_speed[logic_port] = -1; 3847 } 3848 si->port_speed_max[logic_port] = -1; 3849 si->port_num_lanes[logic_port] = -1; 3850 si->port_group[logic_port] = -1; 3851 si->port_serdes[logic_port] = -1; 3852 SOC_PBMP_PORT_ADD(si->roe_compression, logic_port); 3853 SOC_PBMP_PORT_REMOVE(si->oversub_pbm, logic_port); 3854 } 3855 3856 SOC_PBMP_ASSIGN(si->pipe_pbm[0], si->xpipe_pbm); 3857 3858 3859 3860 return SOC_E_NONE; 3861 } 3862 3863 3864 /* 3865 * Function: 3866 * _soc_mn_clear_enabled_port_data 3867 * Purpose: 3868 * Clear set of HW register in order to have correct parity value. 3869 * Parameters: 3870 * unit - (IN) Unit number. 3871 * port - (IN) Logical Port to clear. 3872 * Returns: 3873 * SOC_E_XXX 3874 */ 3875 STATIC int 3876 _soc_mn_clear_enabled_port_data(int unit, soc_port_t port) 3877 { 3878 uint64 rval64; 3879 uint32 evc = 0; 3880 egr_vlan_control_1_entry_t entry_1; 3881 egr_vlan_control_2_entry_t entry_2; 3882 egr_vlan_control_3_entry_t entry_3; 3883 3884 /* Some registers are implemented in memory, need to clear them in order 3885 * to have correct parity value */ 3886 COMPILER_64_ZERO(rval64); 3887 3888 sal_memset(&entry_1, 0, sizeof(entry_1)); 3889 sal_memset(&entry_2, 0, sizeof(entry_2)); 3890 sal_memset(&entry_3, 0, sizeof(entry_3)); 3891 3892 SOC_IF_ERROR_RETURN 3893 (WRITE_EGR_VLAN_CONTROL_1m(unit, MEM_BLOCK_ANY, port, &entry_1)); 3894 SOC_IF_ERROR_RETURN 3895 (WRITE_EGR_VLAN_CONTROL_2m(unit, MEM_BLOCK_ANY, port, &entry_2)); 3896 SOC_IF_ERROR_RETURN 3897 (WRITE_EGR_VLAN_CONTROL_3m(unit, MEM_BLOCK_ANY, port, &entry_3)); 3898 3899 SOC_IF_ERROR_RETURN(WRITE_EGR_PVLAN_EPORT_CONTROLr(unit, port, 0)); 3900 SOC_IF_ERROR_RETURN(WRITE_EGR_SF_SRC_MODID_CHECKr(unit, port, rval64)); 3901 SOC_IF_ERROR_RETURN(WRITE_EGR_1588_LINK_DELAY_64r(unit, port, rval64)); 3902 SOC_IF_ERROR_RETURN(WRITE_EGR_IPMC_CFG2m(unit, MEM_BLOCK_ALL, port, &evc)); 3903 SOC_IF_ERROR_RETURN(WRITE_STORM_CONTROL_METER_CONFIGr(unit, port, 0)); 3904 SOC_IF_ERROR_RETURN(WRITE_SFLOW_ING_THRESHOLDr(unit, port, 0)); 3905 3906 return SOC_E_NONE; 3907 } 3908 3909 3910 /* 3911 * Function: 3912 * _soc_monterey_misc_port_attach 3913 * Purpose: 3914 * Initialize HW for new attached port. 3915 * This routine covers the port initialization performed by 3916 * the SOC MISC routine soc_misc_init() 3917 * Parameters: 3918 * unit - (IN) Unit number. 3919 * port - (IN) Logical Port. 3920 * Returns: 3921 * SOC_E_XXX 3922 */ 3923 STATIC int 3924 _soc_monterey_misc_port_attach(int unit, soc_port_t port) 3925 { 3926 soc_info_t *si; 3927 int phy_port; 3928 uint32 rval; 3929 soc_pbmp_t pbmp; 3930 egr_ing_port_entry_t egr_ing_entry; 3931 ing_en_efilter_bitmap_entry_t ing_en_efilter_entry; 3932 egr_vlan_control_1_entry_t egr_vlan_entry; 3933 int higig2; 3934 int rv = SOC_E_NONE; 3935 soc_control_t *soc = SOC_CONTROL(unit); 3936 3937 LOG_VERBOSE(BSL_LS_SOC_PORT, 3938 (BSL_META_U(unit, 3939 " SOC MISC attach unit=%d port=%d(%s)\n"), 3940 unit, port, SOC_PORT_NAME(unit, port))); 3941 3942 si = &SOC_INFO(unit); 3943 3944 if (IS_LB_PORT(unit, port) || IS_CPU_PORT (unit, port) || 3945 IS_TDM_PORT(unit, port)) { 3946 LOG_ERROR(BSL_LS_SOC_PORT, 3947 (BSL_META_U(unit, 3948 "Port cannot be a Loopback, CPU, or TDM port " 3949 "unit=%d port=%d\n"), 3950 unit, port)); 3951 return SOC_E_PORT; 3952 } 3953 3954 phy_port = si->port_l2p_mapping[port]; 3955 if (!MN_PHY_PORT_ADDRESSABLE(unit, phy_port)) { 3956 LOG_ERROR(BSL_LS_SOC_PORT, 3957 (BSL_META_U(unit, 3958 "Invalid physical port " 3959 "unit=%d port=%d physical=%d\n"), 3960 unit, port, phy_port)); 3961 return SOC_E_INTERNAL; 3962 } 3963 3964 3965 /***************** 3966 * Clear port data */ 3967 SOC_IF_ERROR_RETURN 3968 (_soc_mn_clear_enabled_port_data(unit, port)); 3969 3970 3971 /***************** 3972 * Port Mappings 3973 * 3974 * NOTE: This only covers IFP_GM_LOGICAL_TO_PHYSICAL_MAPPING. 3975 * It does NOT set the IP or EP port mappings. These 3976 * are covered in the following functions as specified by the 3977 * FlexPort uArch specs: 3978 * - soc_mn_port_resource_ip_set() 3979 * - soc_mn_port_resource_ep_set() 3980 */ 3981 rval = 0; 3982 soc_reg_field_set(unit, IFP_GM_LOGICAL_TO_PHYSICAL_MAPPINGr, &rval, 3983 VALIDf, 1); 3984 if (SOC_PBMP_MEMBER(si->ypipe_pbm, port)) { /* Y pipe */ 3985 soc_reg_field_set(unit, IFP_GM_LOGICAL_TO_PHYSICAL_MAPPINGr, 3986 &rval, Y_PIPEf, 1); 3987 } 3988 /* 3989 * IFP_GM_LOGICAL_TO_PHYSICAL_MAPPING.PHYSICAL_PORT_NUM is 3990 * merely a unique stream ID, it's not physical port number. 3991 */ 3992 soc_reg_field_set(unit, IFP_GM_LOGICAL_TO_PHYSICAL_MAPPINGr, &rval, 3993 PHYSICAL_PORT_NUMf, 3994 si->port_p2m_mapping[phy_port] & 0x7f); 3995 MEM_LOCK(unit,FP_GLOBAL_MASK_TCAMm); 3996 rv = WRITE_IFP_GM_LOGICAL_TO_PHYSICAL_MAPPINGr(unit, port, rval); 3997 if (rv < 0) { 3998 MEM_UNLOCK(unit,FP_GLOBAL_MASK_TCAMm); 3999 return rv; 4000 } 4001 soc_mem_fp_global_mask_tcam_cache_update_set(unit, TRUE); 4002 MEM_UNLOCK(unit,FP_GLOBAL_MASK_TCAMm); 4003 sal_sem_give(soc->mem_scan_notify); 4004 4005 /***************** 4006 * Ingress Port egress configuration 4007 */ 4008 sal_memset(&egr_ing_entry, 0, sizeof(egr_ing_port_entry_t)); 4009 if (IS_HG_PORT(unit, port)) { 4010 soc_mem_field32_set(unit, EGR_ING_PORTm, &egr_ing_entry, 4011 PORT_TYPEf, 1); 4012 higig2 = soc_property_port_get(unit, port, spn_HIGIG2_HDR_MODE, 4013 soc_feature(unit, soc_feature_no_higig_plus) ? 1 : 0) ? 1 : 0; 4014 soc_mem_field32_set(unit, EGR_ING_PORTm, &egr_ing_entry, 4015 HIGIG2f, higig2); 4016 } 4017 SOC_IF_ERROR_RETURN 4018 (WRITE_EGR_ING_PORTm(unit, MEM_BLOCK_ALL, port, &egr_ing_entry)); 4019 4020 4021 4022 4023 /***************** 4024 * VLAN Controls 4025 * The HW defaults for EGR_VLAN_CONTROL_1.VT_MISS_UNTAG == 1, which 4026 * causes the outer tag to be removed from packets that don't have 4027 * a hit in the egress vlan tranlation table. Set to 0 to disable this. 4028 */ 4029 sal_memset(&egr_vlan_entry, 0, sizeof(egr_vlan_control_1_entry_t)); 4030 soc_mem_field32_set(unit, EGR_VLAN_CONTROL_1m, &egr_vlan_entry, 4031 VT_MISS_UNTAGf, 0); 4032 /* Enable pri/cfi remarking on egress ports. */ 4033 soc_mem_field32_set(unit, EGR_VLAN_CONTROL_1m, &egr_vlan_entry, 4034 REMARK_OUTER_DOT1Pf, 1); 4035 SOC_IF_ERROR_RETURN 4036 (WRITE_EGR_VLAN_CONTROL_1m(unit, MEM_BLOCK_ALL, port, 4037 &egr_vlan_entry)); 4038 4039 /* Ingress port VLAN membership check */ 4040 SOC_IF_ERROR_RETURN 4041 (READ_ING_EN_EFILTER_BITMAPm(unit, MEM_BLOCK_ANY, 0, 4042 &ing_en_efilter_entry)); 4043 soc_mem_pbmp_field_get(unit, ING_EN_EFILTER_BITMAPm, 4044 &ing_en_efilter_entry, BITMAPf, &pbmp); 4045 SOC_PBMP_PORT_ADD(pbmp, port); 4046 soc_mem_pbmp_field_set(unit, ING_EN_EFILTER_BITMAPm, 4047 &ing_en_efilter_entry, BITMAPf, &pbmp); 4048 SOC_IF_ERROR_RETURN 4049 (WRITE_ING_EN_EFILTER_BITMAPm(unit, MEM_BLOCK_ANY, 0, 4050 &ing_en_efilter_entry)); 4051 4052 return SOC_E_NONE; 4053 } 4054 4055 4056 /* 4057 * Function: 4058 * _soc_monterey_misc_port_detach 4059 * Purpose: 4060 * Clear HW for port to be detached. 4061 * This routine clears what is programmed during during 4062 * the equivalent attach routine _soc_monterey_misc_port_attach(). 4063 * Parameters: 4064 * unit - (IN) Unit number. 4065 * port - (IN) Logical Port. 4066 * Returns: 4067 * SOC_E_XXX 4068 */ 4069 STATIC int 4070 _soc_monterey_misc_port_detach(int unit, soc_port_t port) 4071 { 4072 soc_info_t *si; 4073 int phy_port; 4074 uint32 rval; 4075 soc_pbmp_t pbmp; 4076 egr_ing_port_entry_t egr_ing_entry; 4077 ing_en_efilter_bitmap_entry_t ing_en_efilter_entry; 4078 int rv = SOC_E_NONE; 4079 soc_control_t *soc = SOC_CONTROL(unit); 4080 4081 LOG_VERBOSE(BSL_LS_SOC_PORT, 4082 (BSL_META_U(unit, 4083 " SOC MISC detach unit=%d port=%d(%s)\n"), 4084 unit, port, SOC_PORT_NAME(unit, port))); 4085 4086 si = &SOC_INFO(unit); 4087 4088 if (IS_LB_PORT(unit, port) || IS_CPU_PORT (unit, port) || 4089 IS_TDM_PORT(unit, port)) { 4090 LOG_ERROR(BSL_LS_SOC_PORT, 4091 (BSL_META_U(unit, 4092 "Port cannot be a Loopback, CPU, or TDM port " 4093 "unit=%d port=%d\n"), 4094 unit, port)); 4095 return SOC_E_PORT; 4096 } 4097 4098 phy_port = si->port_l2p_mapping[port]; 4099 if (!MN_PHY_PORT_ADDRESSABLE(unit, phy_port)) { 4100 LOG_ERROR(BSL_LS_SOC_PORT, 4101 (BSL_META_U(unit, 4102 "Invalid physical port " 4103 "unit=%d port=%d physical=%d\n"), 4104 unit, port, phy_port)); 4105 return SOC_E_INTERNAL; 4106 } 4107 4108 4109 /***************** 4110 * Clear port data */ 4111 SOC_IF_ERROR_RETURN 4112 (_soc_mn_clear_enabled_port_data(unit, port)); 4113 4114 4115 /***************** 4116 * Port Mappings 4117 * 4118 * NOTE: This only covers IFP_GM_LOGICAL_TO_PHYSICAL_MAPPING. 4119 * It does NOT set the IP or EP port mappings. These 4120 * are covered in the following functions as specified by the 4121 * FlexPort uArch specs: 4122 * - soc_mn_port_resource_ip_set() 4123 * - soc_mn_port_resource_ep_set() 4124 */ 4125 rval = 0; 4126 SOC_IF_ERROR_RETURN 4127 (WRITE_IFP_GM_LOGICAL_TO_PHYSICAL_MAPPINGr(unit, port, rval)); 4128 MEM_LOCK(unit,FP_GLOBAL_MASK_TCAMm); 4129 rv = WRITE_IFP_GM_LOGICAL_TO_PHYSICAL_MAPPINGr(unit, port, rval); 4130 if (rv < 0) { 4131 MEM_UNLOCK(unit,FP_GLOBAL_MASK_TCAMm); 4132 return rv; 4133 } 4134 soc_mem_fp_global_mask_tcam_cache_update_set(unit, TRUE); 4135 MEM_UNLOCK(unit,FP_GLOBAL_MASK_TCAMm); 4136 sal_sem_give(soc->mem_scan_notify); 4137 4138 /***************** 4139 * Ingress Port egress configuration 4140 */ 4141 sal_memset(&egr_ing_entry, 0, sizeof(egr_ing_port_entry_t)); 4142 SOC_IF_ERROR_RETURN 4143 (WRITE_EGR_ING_PORTm(unit, MEM_BLOCK_ALL, port, &egr_ing_entry)); 4144 4145 4146 /***************** 4147 * VLAN Controls 4148 */ 4149 /* Ingress port VLAN membership check */ 4150 SOC_IF_ERROR_RETURN 4151 (READ_ING_EN_EFILTER_BITMAPm(unit, MEM_BLOCK_ANY, 0, 4152 &ing_en_efilter_entry)); 4153 soc_mem_pbmp_field_get(unit, ING_EN_EFILTER_BITMAPm, 4154 &ing_en_efilter_entry, BITMAPf, &pbmp); 4155 SOC_PBMP_PORT_REMOVE(pbmp, port); 4156 soc_mem_pbmp_field_set(unit, ING_EN_EFILTER_BITMAPm, 4157 &ing_en_efilter_entry, BITMAPf, &pbmp); 4158 SOC_IF_ERROR_RETURN 4159 (WRITE_ING_EN_EFILTER_BITMAPm(unit, MEM_BLOCK_ANY, 0, 4160 &ing_en_efilter_entry)); 4161 4162 return SOC_E_NONE; 4163 } 4164 4165 4166 /* 4167 * Function: 4168 * _soc_mn_port_resource_misc_attach 4169 * Purpose: 4170 * Initialize the SOC MISC area for given set of ports. 4171 * It covers HW programming that is done during SOC MISC. 4172 * 4173 * Parameters: 4174 * unit - (IN) Unit number. 4175 * nport - (IN) Number of elements in array resource. 4176 * resource - (IN) Port Resource FlexPort configuration. 4177 * Returns: 4178 * SOC_E_XXX 4179 * Notes: 4180 * - Assumes this is NOT called during Warmboot. 4181 * - Assumes SOC_INFO is current. 4182 */ 4183 STATIC int 4184 _soc_mn_port_resource_misc_attach(int unit, 4185 int nport, 4186 soc_port_resource_t *resource) 4187 { 4188 int rv = SOC_E_NONE; 4189 soc_port_resource_t *pr; 4190 int i; 4191 4192 LOG_VERBOSE(BSL_LS_SOC_PORT, 4193 (BSL_META_U(unit, 4194 "SOC MISC Attach\n"))); 4195 4196 for (i = 0, pr = &resource[0]; i < nport; i++, pr++) { 4197 if (pr->flags & SOC_PORT_RESOURCE_ATTACH) { 4198 rv = _soc_monterey_misc_port_attach(unit, pr->logical_port); 4199 if (SOC_FAILURE(rv)) { 4200 LOG_ERROR(BSL_LS_SOC_PORT, 4201 (BSL_META_U(unit, 4202 "Error: Unable to initialize SOC MISC " 4203 "unit=%d port=%d rv=%d\n"), 4204 unit, pr->logical_port, rv)); 4205 return rv; 4206 } 4207 } 4208 } 4209 4210 return SOC_E_NONE; 4211 } 4212 4213 4214 /* 4215 * Function: 4216 * _soc_mn_port_resource_misc_detach 4217 * Purpose: 4218 * Clears the SOC MISC area for given set of ports. 4219 * It covers HW programming that is done during SOC MISC. 4220 * 4221 * Parameters: 4222 * unit - (IN) Unit number. 4223 * nport - (IN) Number of elements in array resource. 4224 * resource - (IN) Port Resource FlexPort configuration. 4225 * Returns: 4226 * SOC_E_XXX 4227 * Notes: 4228 * - Assumes this is NOT called during Warmboot. 4229 * - Assumes SOC_INFO is current. 4230 */ 4231 STATIC int 4232 _soc_mn_port_resource_misc_detach(int unit, 4233 int nport, 4234 soc_port_resource_t *resource) 4235 { 4236 int rv = SOC_E_NONE; 4237 soc_port_resource_t *pr; 4238 int i; 4239 4240 LOG_VERBOSE(BSL_LS_SOC_PORT, 4241 (BSL_META_U(unit, 4242 "SOC MISC Detach\n"))); 4243 4244 for (i = 0, pr = &resource[0]; i < nport; i++, pr++) { 4245 if (pr->flags & SOC_PORT_RESOURCE_DETACH) { 4246 rv = _soc_monterey_misc_port_detach(unit, pr->logical_port); 4247 if (SOC_FAILURE(rv)) { 4248 LOG_ERROR(BSL_LS_SOC_PORT, 4249 (BSL_META_U(unit, 4250 "Error: Unable to clear SOC MISC " 4251 "unit=%d port=%d rv=%d\n"), 4252 unit, pr->logical_port, rv)); 4253 return rv; 4254 } 4255 } 4256 } 4257 4258 return SOC_E_NONE; 4259 } 4260 4261 /* 4262 * Function: 4263 * _soc_mn_port_resource_speed_set 4264 * Purpose: 4265 * Execute the Speed Set operation 4266 * 4267 * This function is very similar with _soc_mn_port_resource_execute 4268 * which execute full flex operation. 4269 * Following functions are not called. 4270 * - soc_esw_portctrl_pm_ports_delete 4271 * - soc_esw_portctrl_pm_ports_add 4272 * - _soc_mn_port_resource_misc_detach 4273 * - _soc_mn_port_resource_misc_attach 4274 * - soc_mn_port_resource_pgw_set 4275 * - soc_mn_port_resource_ip_set 4276 * - soc_mn_port_resource_ep_set 4277 * But speed set operation may re-assign MMU port. 4278 * So speed_set operation also requires to call 4279 * - _soc_mn_soc_info_ports_delete 4280 * - _soc_mn_soc_info_ports_add 4281 * 4282 * Parameters: 4283 * unit - (IN) Unit number. 4284 * nport - (IN) Number of elements in array resource. 4285 * resource - (IN) Port Resource FlexPort configuration. 4286 * pre_count - (IN) Array size for pre-FlexPort array. 4287 * pre_resource - (IN) Pre-FlexPort configuration array. 4288 * post_count - (IN) Array size for post-FlexPort array. 4289 * post_resource - (IN) Pre-FlexPort configuration array. 4290 * Returns: 4291 * SOC_E_XXX 4292 * Note: 4293 * - Assumes all data is Port Resource arrays has been validated. 4294 */ 4295 STATIC int 4296 _soc_mn_port_resource_speed_set(int unit, 4297 int nport, soc_port_resource_t *resource, 4298 int pre_count, 4299 soc_port_resource_t *pre_resource, 4300 int post_count, 4301 soc_port_resource_t *post_resource, 4302 soc_mn_info_t *pre_soc_info) 4303 { 4304 int delete_count; 4305 4306 LOG_VERBOSE(BSL_LS_SOC_PORT, 4307 (BSL_META_U(unit, 4308 "\n====== SOC PORT RESOURCE SPEED SET ======\n"))); 4309 4310 delete_count = pre_count; 4311 4312 /* Clear MMU Port Mappings */ 4313 SOC_IF_ERROR_RETURN 4314 (soc_mn_port_resource_mmu_mapping_set(unit, 4315 delete_count, resource)); 4316 4317 SOC_IF_ERROR_RETURN 4318 (_soc_mn_soc_info_ports_delete(unit, 4319 pre_count, pre_resource)); 4320 4321 /* Add ports to SOC SW */ 4322 SOC_IF_ERROR_RETURN 4323 (_soc_mn_soc_info_ports_add(unit, 4324 post_count, post_resource)); 4325 4326 /* 4327 * Note: At this point, the SOC_INFO data structure reflects 4328 * the new information for all the ports. 4329 */ 4330 4331 4332 LOG_VERBOSE(BSL_LS_SOC_PORT, 4333 (BSL_META_U(unit, 4334 "\n--- SOC FLEXPORT RECONFIGURE ---\n"))); 4335 /* Check speed class is same */ 4336 if (!soc_esw_portctrl_is_same_speed_class(unit, pre_resource[0].speed, 4337 post_resource[0].speed)) { 4338 if (!(SAL_BOOT_BCMSIM || SAL_BOOT_XGSSIM) && 4339 !soc_property_get(unit, "skip_tdm_init", 0)) { 4340 4341 /* Reconfigure Schedulers */ 4342 LOG_VERBOSE(BSL_LS_SOC_PORT, 4343 (BSL_META_U(unit, 4344 "--- TDM Reconfigure\n"))); 4345 SOC_IF_ERROR_RETURN 4346 (soc_mn_port_resource_tdm_set(unit, 4347 pre_count, pre_resource, 4348 post_count, post_resource, 4349 pre_soc_info, 4350 MN_INFO(unit)->mmu_lossless)); 4351 } 4352 4353 } 4354 4355 /* Reconfigure MMU */ 4356 LOG_VERBOSE(BSL_LS_SOC_PORT, 4357 (BSL_META_U(unit, 4358 "--- MMU Reconfigure\n"))); 4359 4360 SOC_IF_ERROR_RETURN 4361 (soc_mn_port_resource_mmu_set(unit, post_count, post_resource)); 4362 4363 return SOC_E_NONE; 4364 } 4365 4366 /* 4367 * Function: 4368 * _soc_mn_port_resource_execute 4369 * Purpose: 4370 * Execute the FlexPort operation. 4371 * 4372 * This function updates the main SOC_INFO SW data structure and 4373 * makes changes to HW. 4374 * 4375 * If any error occurs the operation, changes cannot be undone. 4376 * Parameters: 4377 * unit - (IN) Unit number. 4378 * nport - (IN) Number of elements in array resource. 4379 * resource - (IN) Port Resource FlexPort configuration. 4380 * pre_count - (IN) Array size for pre-FlexPort array. 4381 * pre_resource - (IN) Pre-FlexPort configuration array. 4382 * post_count - (IN) Array size for post-FlexPort array. 4383 * post_resource - (IN) Pre-FlexPort configuration array. 4384 * Returns: 4385 * SOC_E_XXX 4386 * Note: 4387 * - Assumes all data is Port Resource arrays has been validated. 4388 */ 4389 STATIC int 4390 _soc_mn_port_resource_execute(int unit, 4391 int nport, soc_port_resource_t *resource, 4392 int pre_count, 4393 soc_port_resource_t *pre_resource, 4394 int post_count, 4395 soc_port_resource_t *post_resource, 4396 soc_mn_info_t *pre_soc_info) 4397 { 4398 int delete_count; 4399 /********************************************** 4400 * Execution Flow 4401 * 4402 * The flow consists of the following high level steps, 4403 * the order is important. 4404 * 4405 * - Detach 'old' ports from SOC layer: 4406 * + These are all ports to be cleared/deleted (indicated by physical 4407 * port -1), EXCEPT those that will become inactive after the 4408 * FlexPort operation (this is only true with legacy API). 4409 * + Clear ports in HW MISC 4410 * + Clearing any other port references in HW 4411 * + Delete ports from Port Macro 4412 * + Clear port information in SOC_INFO SW 4413 * - Attach ports in SOC layer 4414 * + These are all ports that are active after the FlexPort operation. 4415 * + Add port information in SOC_INFO SW 4416 * + Init ports in HW MISC 4417 * + Add ports to Port Macro 4418 * - Execute FlexPort operation as defined by HW specs 4419 * 4420 * ------------------ 4421 * Port Mapping 4422 * ------------ 4423 * A logical to physical port mapping is given as part of the port resource 4424 * array. This can lead to the following operations: 4425 * - Port Mapping Delete (or clear) 4426 * This is indicated when the physical port is set to (-1) and 4427 * the port to be flexed is considered an 'old' port. 4428 * The logical port in the array entry must always be valid. 4429 * A 'delete' may result in the following actions for a port mapping: 4430 * (1) Destroyed 4431 * (2) Same 4432 * (3) Remapped 4433 * 4434 * - Port Mapping Add (or set) 4435 * This is indicated when the physical port is set to a valid 4436 * physical port number (>=0). 4437 * The logical port in the array entry must always be valid. 4438 * An 'add' may result in the following actions for a port mapping: 4439 * (1) New 4440 * (2) Same 4441 * (3) Remapped 4442 * 4443 * Destroyed: Logical port no longer exist after FlexPort. 4444 * Remapped: Logical port will continue to exist after FlexPort 4445 * but is mapped to a different physical port. 4446 * New: Logical port did not exist before FlexPort. 4447 * Same: Logical to physical port mapping remains the same. 4448 * 4449 * NOTE that the 'PortMacro' module handles things 4450 * a bit different. The Port Macro requires ALL ports, including 4451 * those going inactive, to always be 'deleted' 4452 * and 'added' back. 4453 * 4454 * ------------------ 4455 * SOC_INFO Update 4456 * --------------- 4457 * Some HW updates need to be performed BEFORE the 4458 * SOC_INFO structure is updated, and some AFTER. 4459 * 4460 * Once the SOC_INFO structure is updated, the SOC register 4461 * functions will no longer be able to access addresses of 4462 * ports that were 'deleted' from SOC_INFO. The mapping will 4463 * either not be available or not be correct (remapped to a new port). 4464 * 4465 * For example, the soc_reg_addr_get() figures out the 4466 * correct index/address looking into the 'l2p' or 'p2m' in SOC_INFO. 4467 * 4468 * Another example is the Port Macro reconfiguration: 4469 * This operation needs to done in two steps: 4470 * (1) Deletion of ports from the Port Macro needs to be done 4471 * BEFORE the SOC_INFO is updated. PortMod needs to 4472 * access the port mappings before the pre-FlexPort to clear 4473 * old ports. 4474 * 4475 * (2) Addition of new ports to the Port Macro needs to be done 4476 * AFTER the SOC_INFO is updated. PortMod needs to 4477 * access the new ports using the new port mappings. 4478 * 4479 * In general: 4480 * - HW programming on 'older' ports needs to be done BEFORE 4481 * the SOC_INFO is updated. 4482 * - HW programming on 'new' ports needs to be done AFTER 4483 * the SOC_INFO is updated. 4484 */ 4485 LOG_VERBOSE(BSL_LS_SOC_PORT, 4486 (BSL_META_U(unit, 4487 "\n====== SOC PORT RESOURCE EXECUTE ======\n"))); 4488 4489 /********************************************** 4490 * 4491 * DELETE 4492 * 4493 * Clear ports to be marked as 'delete'. 4494 * These operations must take place BEFORE SOC_INFO is updated. 4495 */ 4496 LOG_VERBOSE(BSL_LS_SOC_PORT, 4497 (BSL_META_U(unit, 4498 "--- SOC DETACH PORTS ---\n"))); 4499 delete_count = pre_count; 4500 4501 /* Clear SOC MISC */ 4502 SOC_IF_ERROR_RETURN 4503 (_soc_mn_port_resource_misc_detach(unit, 4504 nport, resource)); 4505 /* Clear MMU Port Mappings */ 4506 SOC_IF_ERROR_RETURN 4507 (soc_mn_port_resource_mmu_mapping_set(unit, 4508 delete_count, resource)); 4509 /* Delete ports from Port Macro */ 4510 SOC_IF_ERROR_RETURN 4511 (soc_esw_portctrl_pm_ports_delete(unit, delete_count, pre_resource)); 4512 4513 /* 4514 * Delete ports from SOC SW 4515 * This must happen last during the 'delete' process 4516 */ 4517 SOC_IF_ERROR_RETURN 4518 (_soc_mn_soc_info_ports_delete(unit, 4519 pre_count, pre_resource)); 4520 4521 4522 /********************************************** 4523 * 4524 * ADD 4525 * 4526 * Configure ports to be added. 4527 */ 4528 LOG_VERBOSE(BSL_LS_SOC_PORT, 4529 (BSL_META_U(unit, 4530 "\n--- SOC ATTACH PORTS ---\n"))); 4531 4532 /* 4533 * Add ports to SOC SW 4534 * This must happen first during the 'add' process 4535 */ 4536 SOC_IF_ERROR_RETURN 4537 (_soc_mn_soc_info_ports_add(unit, 4538 post_count, post_resource)); 4539 /* Enable/Disable used/unused TSCs */ 4540 if (soc_property_get(unit, "disable_unused_port_blocks", TRUE)) { 4541 SOC_IF_ERROR_RETURN(soc_monterey_tsc_disable(unit)); 4542 } 4543 /* 4544 * Verify if the TDM will satisfy the new port config 4545 */ 4546 SOC_IF_ERROR_RETURN(soc_monterey_port_config_bandwidth_check(unit)); 4547 /* 4548 * Note: At this point, the SOC_INFO data structure reflects 4549 * the new information for all the ports. 4550 */ 4551 4552 /* Init SOC MISC */ 4553 SOC_IF_ERROR_RETURN 4554 (_soc_mn_port_resource_misc_attach(unit, 4555 nport, resource)); 4556 4557 /* Add ports to Port Macro */ 4558 SOC_IF_ERROR_RETURN 4559 (soc_esw_portctrl_pm_ports_add(unit, nport, resource)); 4560 4561 4562 /********************************************** 4563 * 4564 * FLEXPORT 4565 * 4566 * Device reconfiguration as defined by specs. 4567 */ 4568 LOG_VERBOSE(BSL_LS_SOC_PORT, 4569 (BSL_META_U(unit, 4570 "\n--- SOC FLEXPORT RECONFIGURE ---\n"))); 4571 /* Reconfigure Schedulers */ 4572 LOG_VERBOSE(BSL_LS_SOC_PORT, 4573 (BSL_META_U(unit, 4574 "--- TDM Reconfigure\n"))); 4575 if (!(SAL_BOOT_BCMSIM || SAL_BOOT_XGSSIM) && 4576 !soc_property_get(unit, "skip_tdm_init", 0)) { 4577 4578 SOC_IF_ERROR_RETURN 4579 (soc_mn_port_resource_tdm_set(unit, 4580 pre_count, pre_resource, 4581 post_count, post_resource, 4582 pre_soc_info, 4583 MN_INFO(unit)->mmu_lossless)); 4584 } 4585 4586 /* Reconfigure PGW */ 4587 LOG_VERBOSE(BSL_LS_SOC_PORT, 4588 (BSL_META_U(unit, 4589 "--- PGW Reconfigure\n"))); 4590 SOC_IF_ERROR_RETURN 4591 (soc_mn_port_resource_pgw_set(unit, 4592 pre_count, pre_resource, 4593 post_count, post_resource, 4594 MN_INFO(unit)->mmu_lossless)); 4595 4596 /* Reconfigure IP */ 4597 LOG_VERBOSE(BSL_LS_SOC_PORT, 4598 (BSL_META_U(unit, 4599 "--- IP Reconfigure\n"))); 4600 SOC_IF_ERROR_RETURN 4601 (soc_mn_port_resource_ip_set(unit, 4602 pre_count, pre_resource, 4603 post_count, post_resource, 4604 pre_soc_info)); 4605 4606 /* Reconfigure EP */ 4607 LOG_VERBOSE(BSL_LS_SOC_PORT, 4608 (BSL_META_U(unit, 4609 "--- EP Reconfigure\n"))); 4610 SOC_IF_ERROR_RETURN 4611 (soc_mn_port_resource_ep_set(unit, 4612 pre_count, pre_resource, 4613 post_count, post_resource, 4614 pre_soc_info)); 4615 4616 /* Reconfigure MMU */ 4617 LOG_VERBOSE(BSL_LS_SOC_PORT, 4618 (BSL_META_U(unit, 4619 "--- MMU Reconfigure\n"))); 4620 4621 SOC_IF_ERROR_RETURN 4622 (soc_mn_port_resource_mmu_set(unit, post_count, post_resource)); 4623 4624 return SOC_E_NONE; 4625 } 4626 4627 4628 /* 4629 * Function: 4630 * soc_mn_port_resource_configure 4631 * Purpose: 4632 * Configure device ports based on given FlexPort information. 4633 * 4634 * This routine validates that the given FlexPort configuration 4635 * is valid and if successful, executes the FlexPort operation. 4636 * Parameters: 4637 * unit - (IN) Unit number. 4638 * nport - (IN) Number of elements in array resource. 4639 * resource - (IN) Port resource configuration array. 4640 * flag - (IN) Check if Full flex sequence or speed set sequence 4641 * Returns: 4642 * SOC_E_XXX 4643 * Note: 4644 * Assumes: 4645 * - Input has been validated. 4646 * E.g. 4647 * . Array is in order (deletes are first) 4648 * . Logical and physical ports are addressable 4649 * . Speeds and lanes are valid for physical port. 4650 * . etc. 4651 * - Caller has lock. 4652 */ 4653 int 4654 soc_mn_port_resource_configure(int unit, int nport, 4655 soc_port_resource_t *resource, 4656 int flag) 4657 { 4658 int rv; 4659 int pre_count; 4660 int post_count; 4661 soc_port_resource_t *pre_resource; 4662 soc_port_resource_t *post_resource; 4663 soc_mn_info_t *pre_soc_info = NULL; 4664 4665 MN_INFO_INIT_CHECK(unit); 4666 4667 pre_soc_info = sal_alloc(sizeof(soc_mn_info_t), "pre_soc_info"); 4668 4669 if (pre_soc_info == NULL) { 4670 LOG_ERROR(BSL_LS_SOC_PORT, 4671 (BSL_META_U(unit, "Memory Allocation Failure"))); 4672 rv = SOC_E_MEMORY; 4673 return rv; 4674 } 4675 4676 LOG_VERBOSE(BSL_LS_SOC_PORT, 4677 (BSL_META_U(unit, 4678 "\n=============================================\n" 4679 "======== SOC PORT RESOURCE CONFIGURE ========\n" 4680 "=============================================\n" 4681 ))); 4682 4683 /* Get all Port Resource information needed for operation */ 4684 rv = _soc_mn_port_resource_data_init(unit, nport, resource, 4685 &pre_count, &pre_resource, 4686 &post_count, &post_resource, 4687 pre_soc_info); 4688 if (SOC_FAILURE(rv)) { 4689 _soc_mn_port_resource_data_cleanup(&pre_resource); 4690 sal_free(pre_soc_info); 4691 return rv; 4692 } 4693 /* Pause linkscan */ 4694 soc_linkscan_pause(unit); 4695 4696 /* Pause counter collection */ 4697 COUNTER_LOCK(unit); 4698 4699 /* Lock the SOC structures */ 4700 SOC_CONTROL_LOCK(unit); 4701 4702 /* 4703 * Execute FlexPort operation 4704 * 4705 * At this point: 4706 * - Validation is successfull 4707 * - FlexPort information is ready 4708 * 4709 * Changes are done to the to the SOC_INFO SW data structure and HW. 4710 * If any error occurs the operation, changes cannot be undone. 4711 */ 4712 if (flag == SOC_PORT_RESOURCE_CONFIGURE_FLEX) { 4713 rv = _soc_mn_port_resource_execute(unit, nport, resource, 4714 pre_count, pre_resource, 4715 post_count, post_resource, 4716 pre_soc_info); 4717 } else { 4718 rv = _soc_mn_port_resource_speed_set(unit, nport, resource, 4719 pre_count, pre_resource, 4720 post_count, post_resource, 4721 pre_soc_info); 4722 } 4723 /* Unlock the SOC structures */ 4724 SOC_CONTROL_UNLOCK(unit); 4725 4726 /* Resume counter collection */ 4727 COUNTER_UNLOCK(unit); 4728 4729 /* Resume linkscan */ 4730 soc_linkscan_continue(unit); 4731 4732 /* Debug output */ 4733 _soc_mn_port_resource_data_output(unit, 4734 nport, resource, 4735 pre_count, pre_resource, 4736 post_count, post_resource); 4737 4738 if (SOC_FAILURE(rv)) { 4739 LOG_ERROR(BSL_LS_SOC_PORT, 4740 (BSL_META_U(unit, 4741 "Error executing FlexPort operation (%d)\n"), 4742 rv)); 4743 LOG_ERROR(BSL_LS_SOC_PORT, 4744 (BSL_META_U(unit, 4745 "Changes to device may have been partially " 4746 "executed. System may be unstable.\n"))); 4747 } 4748 4749 /* Deallocate memory */ 4750 _soc_mn_port_resource_data_cleanup(&pre_resource); 4751 sal_free(pre_soc_info); 4752 4753 return rv; 4754 } 4755 #define MONTEREY_MAX_OVS_SPG 8 4756 /* 4757 * Function: 4758 * _soc_mn_port_resource_ovs_speed_group_validate 4759 * Purpose: 4760 * Validate oversub speed group of all ports: 4761 * Total number of oversub speed groups cannot exceed 4 at any given time 4762 * 4763 * Parameters: 4764 * unit - (IN) Unit number. 4765 * post_si - (IN) Post SOC INFO information 4766 * Returns: 4767 * SOC_E_XXX 4768 */ 4769 STATIC int 4770 _soc_mn_port_resource_ovs_speed_group_validate(int unit, soc_info_mn_misc_t *post_si) 4771 { 4772 int i, j, found; 4773 int logic_port, phy_port; 4774 int speed, spd_cls ,spg_count =0; 4775 int spg_num[MONTEREY_MAX_OVS_SPG] = {0}; 4776 uint32 sp_spacing = 0; 4777 4778 LOG_VERBOSE(BSL_LS_SOC_PORT, 4779 (BSL_META_U(unit, 4780 "--- VALIDATE: Oversub Speed groups\n"))); 4781 4782 for (i = 0; i < SOC_MAX_NUM_PORTS; i++) { 4783 logic_port = i; 4784 phy_port = post_si->port_l2p_mapping[logic_port]; 4785 4786 /* Skip ports not defined, LB, CPU, etc. */ 4787 if (!SOC_PORT_ADDRESSABLE(unit, logic_port) || 4788 !((phy_port >= 0) && (phy_port <= SOC_MAX_NUM_PORTS)) || 4789 IS_LB_PORT(unit, logic_port) || 4790 IS_RDB_PORT(unit, logic_port) || 4791 IS_CPU_PORT (unit, logic_port)) { 4792 continue; 4793 } 4794 4795 /* Skip Line Rate ports */ 4796 if (!SOC_PBMP_MEMBER(post_si->oversub_pbm, logic_port)) { 4797 continue; 4798 } 4799 4800 /* Skip inactive ports */ 4801 if (SOC_PBMP_MEMBER(post_si->disabled_bitmap, logic_port)) { 4802 continue; 4803 } 4804 4805 4806 /* Get speed class */ 4807 speed = post_si->port_speed[logic_port]; 4808 SOC_IF_ERROR_RETURN(_soc_monterey_mmu_ovs_speed_class_map_get(unit, 4809 &speed, &spd_cls, &sp_spacing)); 4810 found = 0; 4811 for (j = 0; j < MONTEREY_MAX_OVS_SPG; j++) { 4812 /* Check if speed group already exists */ 4813 if (spd_cls == spg_num[j]) { 4814 found = 1; 4815 break; 4816 } 4817 } 4818 if (!found) { 4819 if (spg_count == MONTEREY_MAX_OVS_SPG) { 4820 LOG_ERROR(BSL_LS_SOC_PORT, (BSL_META_U(unit, 4821 "More than %d oversub speed groups not supported\n"), 4822 MONTEREY_MAX_OVS_SPG)); 4823 return SOC_E_CONFIG; 4824 } 4825 /* Keep track of all speed groups */ 4826 spg_num[spg_count++] = spd_cls; 4827 } 4828 } 4829 4830 return SOC_E_NONE; 4831 } 4832 4833 /* 4834 * Function: 4835 * soc_mn_port_ovs_speed_group_validate 4836 * Purpose: 4837 * Validate oversub speed group of all ports: 4838 * Total number of oversub speed groups cannot exceed 4 at any given time 4839 * 4840 * Parameters: 4841 * unit - (IN) Unit number. 4842 * post_si - (IN) Post SOC INFO information 4843 * Returns: 4844 * SOC_E_XXX 4845 * Note: 4846 * Assumes that this function is called at early stage of initialization 4847 * (For example, soc_apache_port_config_init). 4848 * Because portctrl/portmod API is not ready to use, 4849 * use port_speed_max or port_init_speed instead. 4850 */ 4851 int 4852 soc_mn_port_ovs_speed_group_validate(int unit) 4853 { 4854 int i, j, found; 4855 int logic_port, phy_port; 4856 int speed, spd_cls, spg_count = 0; 4857 int spg_num[MONTEREY_MAX_OVS_SPG] = {0}; 4858 uint32 sp_spacing = 0; 4859 soc_info_t *si = &SOC_INFO(unit); 4860 4861 LOG_VERBOSE(BSL_LS_SOC_PORT, 4862 (BSL_META_U(unit, 4863 "--- VALIDATE: Oversub Speed groups\n"))); 4864 4865 for (i = 0; i < SOC_MAX_NUM_PORTS; i++) { 4866 logic_port = i; 4867 phy_port = si->port_l2p_mapping[logic_port]; 4868 4869 /* Skip ports not defined, LB, CPU, etc. */ 4870 if (!SOC_PORT_ADDRESSABLE(unit, logic_port) || 4871 !((phy_port >= 0) && (phy_port <= SOC_MAX_NUM_PORTS)) || 4872 IS_LB_PORT(unit, logic_port) || 4873 IS_MACSEC_PORT(unit, logic_port) || 4874 IS_CPU_PORT (unit, logic_port)) { 4875 continue; 4876 } 4877 4878 /* Skip Line Rate ports */ 4879 if (!SOC_PBMP_MEMBER(si->oversub_pbm, logic_port)) { 4880 continue; 4881 } 4882 4883 /* Skip inactive ports */ 4884 if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, logic_port)) { 4885 continue; 4886 } 4887 4888 4889 /* Get speed class */ 4890 speed = si->port_speed_max[logic_port]; 4891 SOC_IF_ERROR_RETURN(_soc_monterey_mmu_ovs_speed_class_map_get(unit, 4892 &speed, &spd_cls, &sp_spacing)); 4893 found = 0; 4894 for (j = 0; j < MONTEREY_MAX_OVS_SPG; j++) { 4895 /* Check if speed group already exists */ 4896 if (spd_cls == spg_num[j]) { 4897 found = 1; 4898 break; 4899 } 4900 } 4901 if (!found) { 4902 if (spg_count == MONTEREY_MAX_OVS_SPG) { 4903 LOG_ERROR(BSL_LS_SOC_PORT, (BSL_META_U(unit, 4904 "More than %d oversub speed groups not supported\n"), 4905 MONTEREY_MAX_OVS_SPG)); 4906 return SOC_E_CONFIG; 4907 } 4908 /* Keep track of all speed groups */ 4909 spg_num[spg_count++] = spd_cls; 4910 } 4911 } 4912 4913 return SOC_E_NONE; 4914 } 4915 #ifdef BCM_WARM_BOOT_SUPPORT 4916 int 4917 soc_monterey_flexport_scache_allocate(int unit) 4918 { 4919 int rv = SOC_E_NONE; 4920 uint8 *flexport_scache_ptr; 4921 soc_scache_handle_t scache_handle; 4922 uint32 alloc_get = 0; 4923 uint32 alloc_size = 0; 4924 int stable_size; 4925 int default_ver = SOC_FLEXPORT_WB_DEFAULT_VERSION; 4926 4927 4928 alloc_size = (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* phy to logical*/ 4929 (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* logical to phy */ 4930 (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* phy to mmu */ 4931 (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* mmu to phy */ 4932 (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* num lanes */ 4933 (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* group number */ 4934 (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* serdes number */ 4935 (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* max port speed */ 4936 (sizeof(pbmp_t)) + /* oversub pbm */ 4937 (sizeof(pbmp_t)) +/* Disabled bitmap */ 4938 (sizeof(pbmp_t)); /* roe compression bitmap */ 4939 4940 alloc_get = alloc_size; 4941 4942 SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_FLEXIO_HANDLE, 0); 4943 4944 /* check to see if an scache table has been configured */ 4945 rv = soc_stable_size_get(unit, &stable_size); 4946 if (SOC_FAILURE(rv) || stable_size <= 0) { 4947 return rv; 4948 } 4949 4950 rv = soc_versioned_scache_ptr_get(unit, scache_handle, TRUE, &alloc_get, 4951 &flexport_scache_ptr, default_ver, NULL); 4952 4953 if (rv == SOC_E_CONFIG) { 4954 /* Probably Level1 */ 4955 return SOC_E_NONE; 4956 } 4957 4958 if (NULL == flexport_scache_ptr) { 4959 LOG_ERROR(BSL_LS_SOC_COMMON, 4960 (BSL_META_U(unit, 4961 "ERROR: scache memory not allocated for flexport" 4962 "%s()[LINE:%d] DONE \n"),FUNCTION_NAME(), __LINE__)); 4963 return SOC_E_MEMORY; 4964 } 4965 4966 LOG_VERBOSE(BSL_LS_SOC_COMMON, 4967 (BSL_META_U(unit, 4968 "%s()[LINE:%d] DONE \n"),FUNCTION_NAME(), __LINE__)); 4969 4970 return SOC_E_NONE; 4971 } 4972 4973 int 4974 soc_monterey_flexport_scache_sync(int unit) 4975 { 4976 uint8 *flexport_scache_ptr; 4977 soc_scache_handle_t scache_handle; 4978 uint32 alloc_get=0; 4979 uint32 alloc_size = 0; 4980 soc_info_t *si = &SOC_INFO(unit); 4981 uint32 scache_offset=0; 4982 uint32 var_size, hole_size; 4983 int rv = 0; 4984 4985 4986 alloc_size = (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* phy to logical*/ 4987 (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* logical to phy */ 4988 (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* phy to mmu */ 4989 (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* mmu to phy */ 4990 (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* num lanes */ 4991 (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* group number */ 4992 (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* serdes number */ 4993 (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* max port speed */ 4994 (sizeof(pbmp_t)) + /* oversub pbm */ 4995 (sizeof(pbmp_t)) + /* Disabled bitmap */ 4996 (sizeof(pbmp_t)); /* roe compression bitmap */ 4997 4998 hole_size = (sizeof(int)); 4999 var_size = (sizeof(int) * (MN_FLEX_MAX_NUM_PORTS - 1)); 5000 alloc_get = alloc_size; 5001 5002 SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_FLEXIO_HANDLE, 0); 5003 5004 rv = soc_versioned_scache_ptr_get(unit, scache_handle, FALSE, &alloc_get, &flexport_scache_ptr, 5005 SOC_FLEXPORT_WB_DEFAULT_VERSION, NULL); 5006 if (rv == SOC_E_NOT_FOUND) { 5007 /* Probably Level1 */ 5008 return SOC_E_NONE; 5009 } 5010 5011 if (alloc_get != alloc_size) { 5012 /* Expected size doesn't match retrieved size */ 5013 LOG_ERROR(BSL_LS_SOC_COMMON, 5014 (BSL_META_U(unit, 5015 "ERROR: scache memory for flexport size mismatch" 5016 "%s()[LINE:%d] DONE \n"),FUNCTION_NAME(), __LINE__)); 5017 return SOC_E_INTERNAL; 5018 } 5019 5020 if (NULL == flexport_scache_ptr) { 5021 LOG_ERROR(BSL_LS_SOC_COMMON, 5022 (BSL_META_U(unit, 5023 "ERROR: scache memory not allocated for flexport" 5024 "%s()[LINE:%d] DONE \n"),FUNCTION_NAME(), __LINE__)); 5025 return SOC_E_MEMORY; 5026 } 5027 5028 /* Physical to logical port mapping */ 5029 sal_memcpy(&flexport_scache_ptr[scache_offset], 5030 si->port_p2l_mapping, var_size); 5031 scache_offset += (var_size + hole_size); 5032 5033 /* Logical to Physical port mapping */ 5034 sal_memcpy(&flexport_scache_ptr[scache_offset], 5035 si->port_l2p_mapping, var_size); 5036 scache_offset += (var_size + hole_size); 5037 5038 /* Physical to mmu port mapping */ 5039 sal_memcpy(&flexport_scache_ptr[scache_offset], 5040 si->port_p2m_mapping, var_size); 5041 scache_offset += (var_size + hole_size); 5042 5043 /* MMU to Physical port mapping */ 5044 sal_memcpy(&flexport_scache_ptr[scache_offset], 5045 si->port_m2p_mapping, var_size); 5046 scache_offset += (var_size + hole_size); 5047 5048 /* Num lanes per port */ 5049 sal_memcpy(&flexport_scache_ptr[scache_offset], 5050 si->port_num_lanes, var_size); 5051 scache_offset += (var_size + hole_size); 5052 5053 /* Port Group */ 5054 sal_memcpy(&flexport_scache_ptr[scache_offset], 5055 si->port_group, var_size); 5056 scache_offset += (var_size + hole_size); 5057 5058 /* Port Serdes */ 5059 sal_memcpy(&flexport_scache_ptr[scache_offset], 5060 si->port_serdes, var_size); 5061 scache_offset += (var_size + hole_size); 5062 5063 /* Max port speed */ 5064 sal_memcpy(&flexport_scache_ptr[scache_offset], 5065 si->port_speed_max, var_size); 5066 scache_offset += (var_size + hole_size); 5067 5068 /* Oversub pbm */ 5069 sal_memcpy(&flexport_scache_ptr[scache_offset], 5070 &si->oversub_pbm, sizeof(pbmp_t)); 5071 scache_offset += sizeof(pbmp_t); 5072 5073 /* Disabled Port Bitmap */ 5074 sal_memcpy(&flexport_scache_ptr[scache_offset], 5075 &si->all.disabled_bitmap, sizeof(pbmp_t)); 5076 scache_offset += sizeof(pbmp_t); 5077 sal_memcpy(&flexport_scache_ptr[scache_offset], 5078 &si->roe_compression, sizeof(pbmp_t)); 5079 scache_offset += sizeof(pbmp_t); 5080 5081 5082 LOG_VERBOSE(BSL_LS_SOC_COMMON, 5083 (BSL_META_U(unit, 5084 "%s()[LINE:%d] \n"),FUNCTION_NAME(), __LINE__)); 5085 5086 return SOC_E_NONE; 5087 } 5088 5089 int 5090 soc_monterey_flexport_scache_recovery(int unit) 5091 { 5092 uint32 alloc_get=0; 5093 uint32 alloc_size = 0; 5094 uint32 additional_scache_size = 0; 5095 int rv = SOC_E_NONE; 5096 int phy_port; 5097 uint8 *flexport_scache_ptr = NULL; 5098 soc_scache_handle_t scache_handle; 5099 uint32 scache_offset=0; 5100 uint32 var_size, hole_size; 5101 uint16 recovered_ver = 0; 5102 soc_info_t *si = &SOC_INFO(unit); 5103 5104 5105 alloc_size = (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* phy to logical*/ 5106 (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* logical to phy */ 5107 (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* phy to mmu */ 5108 (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* mmu to phy */ 5109 (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* num lanes */ 5110 (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* group number */ 5111 (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* serdes number */ 5112 (sizeof(int) * MN_FLEX_MAX_NUM_PORTS) + /* max port speed */ 5113 (sizeof(pbmp_t)) + /* oversub pbm */ 5114 (sizeof(pbmp_t)) + /* Disabled bitmap */ 5115 (sizeof(pbmp_t)); /* roe compression */ 5116 5117 hole_size = (sizeof(int)); 5118 var_size = (sizeof(int) * (MN_FLEX_MAX_NUM_PORTS - 1)); 5119 alloc_get = alloc_size; 5120 5121 SOC_SCACHE_HANDLE_SET(scache_handle, unit, SOC_SCACHE_FLEXIO_HANDLE, 0); 5122 rv = soc_versioned_scache_ptr_get(unit, scache_handle, FALSE, &alloc_get, 5123 &flexport_scache_ptr, SOC_FLEXPORT_WB_DEFAULT_VERSION, 5124 &recovered_ver); 5125 5126 if (SOC_FAILURE(rv)) { 5127 if ((rv == SOC_E_CONFIG) || 5128 (rv == SOC_E_NOT_FOUND)) { 5129 /* warmboot file does not contain this 5130 * module, or the warmboot state does not exist. 5131 * in this case return SOC_E_NOT_FOUND 5132 */ 5133 return SOC_E_NOT_FOUND; 5134 } else { 5135 /* Only Level2 - flexport treat this as a error */ 5136 LOG_ERROR(BSL_LS_SOC_COMMON, 5137 (BSL_META_U(unit, 5138 "Failed to recover scache data - %s\n"),soc_errmsg(rv))); 5139 return rv; 5140 } 5141 } 5142 5143 if (alloc_get != alloc_size) { 5144 /* Expected size doesn't match retrieved size */ 5145 LOG_ERROR(BSL_LS_SOC_COMMON, 5146 (BSL_META_U(unit, 5147 "ERROR: scache recovery for flexport" 5148 "%s()[LINE:%d] DONE \n"), 5149 FUNCTION_NAME(), __LINE__)); 5150 return SOC_E_INTERNAL; 5151 } 5152 5153 if (NULL == flexport_scache_ptr) { 5154 LOG_ERROR(BSL_LS_SOC_COMMON, 5155 (BSL_META_U(unit, 5156 "ERROR: scache recovery for flexport" 5157 "%s()[LINE:%d] DONE \n"), 5158 FUNCTION_NAME(), __LINE__)); 5159 return SOC_E_MEMORY; 5160 } 5161 5162 /* Physical to logical port mapping */ 5163 sal_memcpy(si->port_p2l_mapping, 5164 &flexport_scache_ptr[scache_offset], 5165 var_size); 5166 scache_offset += (var_size + hole_size); 5167 5168 /* Logical to Physical port mapping */ 5169 sal_memcpy(si->port_l2p_mapping, 5170 &flexport_scache_ptr[scache_offset], 5171 var_size); 5172 scache_offset += (var_size + hole_size); 5173 5174 /* Physical to mmu port mapping */ 5175 sal_memcpy(si->port_p2m_mapping, 5176 &flexport_scache_ptr[scache_offset], 5177 var_size); 5178 scache_offset += (var_size + hole_size); 5179 5180 /* MMU to Physical port mapping */ 5181 sal_memcpy(si->port_m2p_mapping, 5182 &flexport_scache_ptr[scache_offset], 5183 var_size); 5184 scache_offset += (var_size + hole_size); 5185 5186 /* Num lanes per port */ 5187 sal_memcpy(si->port_num_lanes, 5188 &flexport_scache_ptr[scache_offset], 5189 var_size); 5190 scache_offset += (var_size + hole_size); 5191 5192 /* Port Group */ 5193 sal_memcpy(si->port_group, 5194 &flexport_scache_ptr[scache_offset], 5195 var_size); 5196 scache_offset += (var_size + hole_size); 5197 5198 /* Port Serdes */ 5199 sal_memcpy(si->port_serdes, 5200 &flexport_scache_ptr[scache_offset], 5201 var_size); 5202 scache_offset += (var_size + hole_size); 5203 5204 /* Max port speed */ 5205 sal_memcpy(si->port_speed_max, 5206 &flexport_scache_ptr[scache_offset], 5207 var_size); 5208 scache_offset += (var_size + hole_size); 5209 5210 /* Oversub pbm */ 5211 sal_memcpy(&si->oversub_pbm, 5212 &flexport_scache_ptr[scache_offset], 5213 sizeof(pbmp_t)); 5214 scache_offset += sizeof(pbmp_t); 5215 5216 /* Disabled Port Bitmap */ 5217 sal_memcpy(&si->all.disabled_bitmap, 5218 &flexport_scache_ptr[scache_offset], 5219 sizeof(pbmp_t)); 5220 scache_offset += sizeof(pbmp_t); 5221 if (recovered_ver > SOC_FLEXPORT_WB_VERSION_1_0) { 5222 sal_memcpy(&si->roe_compression, 5223 &flexport_scache_ptr[scache_offset], 5224 sizeof(pbmp_t)); 5225 scache_offset += sizeof(pbmp_t); 5226 } else { 5227 additional_scache_size += sizeof(pbmp_t); 5228 } 5229 if (additional_scache_size > 0) { 5230 SOC_IF_ERROR_RETURN(soc_scache_realloc(unit, scache_handle, 5231 additional_scache_size)); 5232 } 5233 5234 SOC_PBMP_CLEAR(si->xpipe_pbm); 5235 SOC_PBMP_CLEAR(si->pipe_pbm[0]); 5236 5237 for (phy_port = 1; phy_port < SOC_MAX_NUM_PORTS; phy_port++) { 5238 if (si->port_p2l_mapping[phy_port] == -1) { 5239 continue; 5240 } 5241 SOC_PBMP_PORT_ADD(si->xpipe_pbm, si->port_p2l_mapping[phy_port]); 5242 SOC_PBMP_PORT_ADD(si->pipe_pbm[0], si->port_p2l_mapping[phy_port]); 5243 } 5244 5245 LOG_VERBOSE(BSL_LS_SOC_COMMON, 5246 (BSL_META_U(unit, 5247 "%s()[LINE:%d] \n"),FUNCTION_NAME(), __LINE__)); 5248 5249 return SOC_E_NONE; 5250 } 5251 #endif /* BCM_WARM_BOOT_SUPPORT */ 5252 5253 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP 5254 void 5255 soc_monterey_flexport_sw_dump(int unit) { 5256 int port; 5257 int portGroup; 5258 int portSerdes; 5259 int portLanes; 5260 int bandwidth; 5261 int l2p; 5262 int p2m; 5263 int m2p; 5264 int p2l; 5265 char pfmt[SOC_PBMP_FMT_LEN]; 5266 int phy_port, mmu_port, cosq, numq, uc_cosq, uc_numq; 5267 5268 LOG_CLI((BSL_META_U(unit, 5269 " logical p2l " 5270 "l2p p2m m2p ucast_Qbase/Numq mcast_Qbase/Numq\n"))); 5271 for (phy_port = 1; phy_port < SOC_MAX_NUM_PORTS; phy_port++) { 5272 port = SOC_INFO(unit).port_p2l_mapping[phy_port]; 5273 if (port == -1) { 5274 continue; 5275 } 5276 mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port]; 5277 cosq = SOC_INFO(unit).port_cosq_base[port]; 5278 numq = SOC_INFO(unit).port_num_cosq[port]; 5279 uc_cosq = SOC_INFO(unit).port_uc_cosq_base[port]; 5280 uc_numq = SOC_INFO(unit).port_num_uc_cosq[port]; 5281 cosq = soc_monterey_logical_qnum_hw_qnum(unit, port, cosq, 0); 5282 uc_cosq = soc_monterey_logical_qnum_hw_qnum(unit, port, uc_cosq, 5283 1); 5284 l2p = phy_port; 5285 p2m = mmu_port; 5286 5287 m2p = SOC_INFO(unit).port_m2p_mapping[mmu_port]; 5288 p2l = SOC_INFO(unit).port_p2l_mapping[phy_port]; 5289 LOG_CLI((BSL_META_U(unit, 5290 " %8s %3d %3d " 5291 "%3d %3d %3d %4d/%-4d %4d/%-4d\n"), 5292 SOC_INFO(unit).port_name[port], port, 5293 p2l, l2p, p2m, m2p, 5294 uc_cosq, uc_numq, cosq, numq)); 5295 } 5296 LOG_CLI((BSL_META_U(unit, 5297 "\nlogical physical bandwidth " 5298 "portLanes portGroup portSerdes "))); 5299 5300 for (phy_port = 1; phy_port < SOC_MAX_NUM_PORTS; phy_port++) { 5301 port = SOC_INFO(unit).port_p2l_mapping[phy_port]; 5302 if (port == -1) { 5303 continue; 5304 } 5305 bandwidth = SOC_INFO(unit).port_speed_max[port]; 5306 portLanes = SOC_INFO(unit).port_num_lanes[port]; 5307 portGroup = SOC_INFO(unit).port_group[port]; 5308 portSerdes = SOC_INFO(unit).port_serdes[port]; 5309 LOG_CLI((BSL_META_U(unit, 5310 "\n%3d %3d " 5311 "%9d " 5312 "%3d " 5313 "%3d " 5314 "%3d "), 5315 port, phy_port, bandwidth, 5316 portLanes, portGroup, portSerdes)); 5317 } 5318 5319 LOG_CLI((BSL_META_U(unit, 5320 "\n Oversub Bitmap: %s"), 5321 SOC_PBMP_FMT(SOC_INFO(unit).oversub_pbm, pfmt))); 5322 LOG_CLI((BSL_META_U(unit, 5323 "\n Disabled Bitmap: %s \n"), 5324 SOC_PBMP_FMT(SOC_INFO(unit).all.disabled_bitmap, pfmt))); 5325 5326 5327 } 5328 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */ 5329 5330 5331 #endif /* BCM_MONTEREY_SUPPORT */