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