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