1 /******************************************************************************* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 * 21 * Copyright 2014 QLogic Corporation 22 * The contents of this file are subject to the terms of the 23 * QLogic End User License (the "License"). 24 * You may not use this file except in compliance with the License. 25 * 26 * You can obtain a copy of the License at 27 * http://www.qlogic.com/Resources/Documents/DriverDownloadHelp/ 28 * QLogic_End_User_Software_License.txt 29 * See the License for the specific language governing permissions 30 * and limitations under the License. 31 * 32 * 33 * Module Description: 34 * 35 * 36 * History: 37 * 11/15/01 Hav Khauv Inception. 38 ******************************************************************************/ 39 40 #include "lm5710.h" 41 #include "phy_reg.h" 42 #include "license.h" 43 #include "mcp_shmem.h" 44 #include "lm_stats.h" 45 #include "577xx_int_offsets.h" 46 47 /***********************************************************/ 48 /* CLC - Common Link Component API */ 49 /***********************************************************/ 50 51 /* Driver needs to redefine the cps_cb_st_ptr ( CPS CallBack Struct Pointer ) with its own */ 52 53 #if defined(ELINK_DEBUG) && !defined(__SunOS) 54 55 void elink_cb_dbg(struct elink_dev *bp, _In_ char* fmt ) 56 { 57 DbgMessage(bp, WARNelink, fmt); 58 } 59 void elink_cb_dbg1(struct elink_dev *bp, _In_ char* fmt, u32 arg1 ) 60 { 61 DbgMessage(bp, WARNelink, fmt, arg1); 62 } 63 void elink_cb_dbg2(struct elink_dev *bp, _In_ char* fmt, u32 arg1, u32 arg2 ) 64 { 65 DbgMessage(bp, WARNelink, fmt, arg1, arg2); 66 } 67 68 void elink_cb_dbg3(struct elink_dev *bp, _In_ char* fmt, u32 arg1, u32 arg2, u32 arg3 ) 69 { 70 DbgMessage(bp, WARNelink, fmt, arg1, arg2, arg3); 71 } 72 73 #endif /* ELINK_DEBUG */ 74 75 u32 elink_cb_reg_read(struct elink_dev *cb, u32 reg_addr ) 76 { 77 return REG_RD(cb, reg_addr); 78 } 79 80 void elink_cb_reg_write(struct elink_dev *cb, u32 reg_addr, u32 val ) 81 { 82 REG_WR(cb, reg_addr, val); 83 } 84 85 /* wb_write - pointer to 2 32 bits vars to be passed to the DMAE*/ 86 void elink_cb_reg_wb_write(struct elink_dev *cb, u32 offset, u32 *wb_write, u16 len ) 87 { 88 REG_WR_DMAE_LEN(cb, offset, wb_write, len); 89 } 90 91 void elink_cb_reg_wb_read(struct elink_dev *cb, u32 offset, u32 *wb_write, u16 len ) 92 { 93 REG_RD_DMAE_LEN(cb, offset, wb_write, len); 94 } 95 96 /* mode - 0( LOW ) /1(HIGH)*/ 97 u8 elink_cb_gpio_write(struct elink_dev *cb, u16 gpio_num, u8 mode, u8 port) 98 { 99 return lm_gpio_write(cb, gpio_num, mode, port); 100 } 101 102 u8 elink_cb_gpio_mult_write(struct elink_dev *cb, u8 pins, u8 mode) 103 { 104 return lm_gpio_mult_write(cb, pins, mode); 105 } 106 107 u32 elink_cb_gpio_read(struct elink_dev *cb, u16 gpio_num, u8 port) 108 { 109 u32 val=0; 110 lm_gpio_read(cb, gpio_num, &val, port); 111 return val; 112 } 113 114 u8 elink_cb_gpio_int_write(struct elink_dev *cb, u16 gpio_num, u8 mode, u8 port) 115 { 116 return lm_gpio_int_write(cb, gpio_num, mode, port); 117 } 118 void elink_cb_udelay(struct elink_dev *cb, u32 microsecond) 119 { 120 #define MAX_WAIT_INTERVAL 50 121 122 u32_t wait_itr = (microsecond/MAX_WAIT_INTERVAL) ; 123 u32_t cnt = 0; 124 u32_t wait_time = MAX_WAIT_INTERVAL ; 125 126 if( 0 == wait_itr ) 127 { 128 wait_time = microsecond ; 129 wait_itr = 1; 130 } 131 132 for(cnt = 0; cnt < wait_itr; cnt++) 133 { 134 mm_wait(cb , wait_time ); 135 } 136 } 137 u32 elink_cb_fw_command(struct elink_dev *cb, u32 command, u32 param) 138 { 139 u32 fw_resp = 0; 140 lm_mcp_cmd_send_recieve(cb, lm_mcp_mb_header, command, param, MCP_CMD_DEFAULT_TIMEOUT, 141 &fw_resp ); 142 return fw_resp; 143 } 144 145 void elink_cb_download_progress(struct elink_dev *cb, u32 cur, u32 total) 146 { 147 UNREFERENCED_PARAMETER_(cb); 148 UNREFERENCED_PARAMETER_(cur); 149 UNREFERENCED_PARAMETER_(total); 150 151 #ifdef DOS 152 printf("Downloaded %u bytes out of %u bytes\n", cur, total ); 153 #endif // DOS 154 } 155 156 void elink_cb_event_log(struct elink_dev *cb, const elink_log_id_t elink_log_id, ...) 157 { 158 va_list ap; 159 lm_log_id_t lm_log_id = LM_LOG_ID_MAX; 160 161 switch( elink_log_id ) 162 { 163 case ELINK_LOG_ID_OVER_CURRENT: 164 lm_log_id = LM_LOG_ID_OVER_CURRENT; 165 break; 166 167 case ELINK_LOG_ID_PHY_UNINITIALIZED: 168 lm_log_id = LM_LOG_ID_PHY_UNINITIALIZED; 169 break; 170 171 case ELINK_LOG_ID_UNQUAL_IO_MODULE: 172 lm_log_id = LM_LOG_ID_UNQUAL_IO_MODULE; 173 break; 174 175 case ELINK_LOG_ID_MDIO_ACCESS_TIMEOUT: 176 lm_log_id = LM_LOG_ID_MDIO_ACCESS_TIMEOUT; 177 break; 178 179 case ELINK_LOG_ID_NON_10G_MODULE: 180 lm_log_id = LM_LOG_ID_NON_10G_MODULE; 181 break; 182 183 default: 184 DbgBreakIf(TRUE); 185 break; 186 } // elink_log_id switch 187 188 va_start(ap, elink_log_id); 189 190 mm_event_log_generic_arg_fwd( cb, lm_log_id, ap ); 191 192 va_end(ap); 193 } 194 195 u8 elink_cb_path_id(struct elink_dev *cb) 196 { 197 return PATH_ID(cb); 198 } 199 200 void elink_cb_notify_link_changed(struct elink_dev *cb) 201 { 202 REG_WR(cb, MISC_REG_AEU_GENERAL_ATTN_12 + FUNC_ID((lm_device_t *)cb)*sizeof(u32), 1); 203 } 204 /******************************************************************************* 205 * Macros. 206 ******************************************************************************/ 207 208 #define MII_REG(_type, _field) (OFFSETOF(_type, _field)/2) 209 210 #define MDIO_INDIRECT_REG_ADDR 0x1f 211 #define MDIO_SET_REG_BANK(pdev,reg_bank)\ 212 lm_mwrite(pdev,MDIO_INDIRECT_REG_ADDR, reg_bank) 213 214 #define MDIO_ACCESS_TIMEOUT 1000 215 216 #define ELINK_STATUS_TO_LM_STATUS(_rc, _lm_status) switch(_rc)\ 217 {\ 218 case ELINK_STATUS_OK:\ 219 _lm_status = LM_STATUS_SUCCESS;\ 220 break;\ 221 case ELINK_STATUS_TIMEOUT:\ 222 _lm_status = LM_STATUS_TIMEOUT;\ 223 break;\ 224 case ELINK_STATUS_NO_LINK:\ 225 _lm_status = LM_STATUS_LINK_DOWN;\ 226 break;\ 227 case ELINK_STATUS_ERROR:\ 228 default:\ 229 _lm_status = LM_STATUS_FAILURE;\ 230 break;\ 231 } 232 233 /******************************************************************************* 234 * Description: 235 * 236 * Return: 237 ******************************************************************************/ 238 lm_status_t 239 lm_mwrite( lm_device_t *pdev, 240 u32_t reg, 241 u32_t val) 242 { 243 lm_status_t lm_status; 244 u32_t tmp; 245 u32_t cnt; 246 u8_t port = PORT_ID(pdev); 247 u32_t emac_base = (port?GRCBASE_EMAC1:GRCBASE_EMAC0); 248 249 REG_WR(pdev,NIG_REG_XGXS0_CTRL_MD_ST + port*0x18, 1); 250 251 DbgMessage(pdev, INFORM, "lm_mwrite\n"); 252 253 if(pdev->params.phy_int_mode == PHY_INT_MODE_AUTO_POLLING) 254 { 255 tmp=REG_RD(pdev,emac_base+EMAC_REG_EMAC_MDIO_MODE); 256 tmp &= ~EMAC_MDIO_MODE_AUTO_POLL; 257 258 REG_WR(pdev,emac_base+EMAC_REG_EMAC_MDIO_MODE,tmp); 259 260 mm_wait(pdev, 40); 261 } 262 263 tmp = (pdev->vars.phy_addr << 21) | (reg << 16) | (val & EMAC_MDIO_COMM_DATA) | 264 EMAC_MDIO_COMM_COMMAND_WRITE_22 | 265 EMAC_MDIO_COMM_START_BUSY; 266 267 REG_WR(pdev,emac_base+EMAC_REG_EMAC_MDIO_COMM,tmp); 268 269 270 for(cnt = 0; cnt < 1000; cnt++) 271 { 272 mm_wait(pdev, 10); 273 274 tmp=REG_RD(pdev,emac_base+EMAC_REG_EMAC_MDIO_COMM); 275 if(!(tmp & EMAC_MDIO_COMM_START_BUSY)) 276 { 277 mm_wait(pdev, 5); 278 break; 279 } 280 } 281 282 if(tmp & EMAC_MDIO_COMM_START_BUSY) 283 { 284 DbgBreakMsg("Write phy register failed\n"); 285 286 lm_status = LM_STATUS_FAILURE; 287 } 288 else 289 { 290 lm_status = LM_STATUS_SUCCESS; 291 } 292 293 if(pdev->params.phy_int_mode == PHY_INT_MODE_AUTO_POLLING) 294 { 295 tmp=REG_RD(pdev,emac_base+EMAC_REG_EMAC_MDIO_MODE); 296 tmp |= EMAC_MDIO_MODE_AUTO_POLL; 297 298 REG_WR(pdev,emac_base+EMAC_REG_EMAC_MDIO_MODE,tmp); 299 } 300 REG_WR(pdev,NIG_REG_XGXS0_CTRL_MD_ST + 301 port*0x18, 0); 302 return lm_status; 303 } /* lm_mwrite */ 304 305 306 307 /******************************************************************************* 308 * Description: 309 * 310 * Return: 311 ******************************************************************************/ 312 lm_status_t 313 lm_mread( lm_device_t *pdev, 314 u32_t reg, 315 u32_t *ret_val) 316 { 317 lm_status_t lm_status; 318 u32_t val; 319 u32_t cnt; 320 u8_t port = PORT_ID(pdev); 321 u32_t emac_base = (port?GRCBASE_EMAC1:GRCBASE_EMAC0); 322 323 REG_WR(pdev,NIG_REG_XGXS0_CTRL_MD_ST + port*0x18, 1); 324 325 DbgMessage(pdev, INFORM, "lm_mread\n"); 326 327 if(pdev->params.phy_int_mode == PHY_INT_MODE_AUTO_POLLING) 328 { 329 val=REG_RD(pdev,emac_base+EMAC_REG_EMAC_MDIO_MODE); 330 val &= ~EMAC_MDIO_MODE_AUTO_POLL; 331 332 REG_WR(pdev,emac_base+EMAC_REG_EMAC_MDIO_MODE,val); 333 334 mm_wait(pdev, 40); 335 } 336 337 val = (pdev->vars.phy_addr << 21) | (reg << 16) | 338 EMAC_MDIO_COMM_COMMAND_READ_22 | 339 EMAC_MDIO_COMM_START_BUSY; 340 341 REG_WR(pdev,emac_base+EMAC_REG_EMAC_MDIO_COMM,val); 342 343 for(cnt = 0; cnt < 1000; cnt++) 344 { 345 mm_wait(pdev, 10); 346 347 val=REG_RD(pdev,emac_base+EMAC_REG_EMAC_MDIO_COMM); 348 if(!(val & EMAC_MDIO_COMM_START_BUSY)) 349 { 350 val &= EMAC_MDIO_COMM_DATA; 351 break; 352 } 353 } 354 355 if(val & EMAC_MDIO_COMM_START_BUSY) 356 { 357 DbgBreakMsg("Read phy register failed\n"); 358 359 val = 0; 360 361 lm_status = LM_STATUS_FAILURE; 362 } 363 else 364 { 365 lm_status = LM_STATUS_SUCCESS; 366 } 367 368 *ret_val = val; 369 370 if(pdev->params.phy_int_mode == PHY_INT_MODE_AUTO_POLLING) 371 { 372 val=REG_RD(pdev,emac_base+EMAC_REG_EMAC_MDIO_MODE); 373 val |= EMAC_MDIO_MODE_AUTO_POLL; 374 375 REG_WR(pdev,emac_base+EMAC_REG_EMAC_MDIO_MODE,val); 376 } 377 REG_WR(pdev,NIG_REG_XGXS0_CTRL_MD_ST + 378 port*0x18, 0); 379 return lm_status; 380 } /* lm_mread */ 381 382 /******************************************************************************* 383 * Description: 384 * 385 * Return: 386 ******************************************************************************/ 387 lm_status_t 388 lm_phy45_read( 389 lm_device_t *pdev, 390 u8_t phy_addr, 391 u8_t dev_addr, 392 u16_t reg, // offset 393 u16_t *ret_val) 394 { 395 396 u16_t rc = ELINK_STATUS_OK; 397 lm_status_t lm_status = LM_STATUS_SUCCESS; 398 399 PHY_HW_LOCK(pdev); 400 401 rc = elink_phy_read(&pdev->params.link, phy_addr, dev_addr, reg, ret_val); 402 403 PHY_HW_UNLOCK(pdev); 404 405 ELINK_STATUS_TO_LM_STATUS( rc, lm_status ); 406 407 return lm_status; 408 } 409 410 /******************************************************************************* 411 * Description: 412 * 413 * Return: 414 ******************************************************************************/ 415 lm_status_t 416 lm_phy45_write( 417 lm_device_t *pdev, 418 u8_t phy_addr, 419 u8_t dev_addr, 420 u16_t reg, // offset 421 u16_t val) 422 { 423 424 u16_t rc = ELINK_STATUS_OK; 425 lm_status_t lm_status = LM_STATUS_SUCCESS; 426 427 PHY_HW_LOCK(pdev); 428 429 rc = elink_phy_write(&pdev->params.link, phy_addr, dev_addr, reg, val); 430 431 PHY_HW_UNLOCK(pdev); 432 433 ELINK_STATUS_TO_LM_STATUS( rc, lm_status ); 434 435 return lm_status; 436 } 437 438 lm_status_t 439 lm_set_phy_addr(lm_device_t *pdev, 440 u8_t addr) 441 { 442 if (addr > 0x1f) 443 { 444 DbgBreakMsg("lm_set_phy_addr: error addr not valid\n"); 445 return LM_STATUS_FAILURE; 446 } 447 pdev->vars.phy_addr = addr; 448 return LM_STATUS_SUCCESS; 449 } 450 451 /* 452 *Function Name: lm_get_speed_real_from_elink_line_speed 453 * 454 *Parameters: IN line speed (from elink) 455 * 456 *Description: 457 * 458 *Returns: "real speed" in mbps units 459 * 460 */ 461 u32_t lm_get_speed_real_from_elink_line_speed( IN const struct elink_vars* link_vars ) 462 { 463 const u16_t line_speed = link_vars->line_speed; 464 u32_t real_speed = 0; 465 466 if( !link_vars->link_up ) 467 { 468 // probably we get here from ioc_get_driver_info in case of no link 469 // we return 0 in that case 470 return 0; 471 } 472 473 switch(line_speed) 474 { 475 case ELINK_SPEED_10: 476 real_speed = 10; 477 break; 478 479 case ELINK_SPEED_100: 480 real_speed = 100; 481 break; 482 483 case ELINK_SPEED_1000: 484 real_speed = 1000; 485 break; 486 487 case ELINK_SPEED_2500: 488 real_speed = 2500; 489 break; 490 491 case ELINK_SPEED_10000: 492 real_speed = 10000; 493 break; 494 495 case ELINK_SPEED_20000: 496 real_speed = 20000; 497 break; 498 499 default: 500 DbgBreakIf(1); 501 break; 502 } 503 return real_speed; 504 } 505 506 /* 507 *Function Name: lm_get_speed_medium_from_elink_line_speed 508 * 509 *Parameters: IN line speed (from elink) 510 * 511 *Description: 512 * 513 *Returns: "medium" translation to LM units 514 * 515 */ 516 u32_t lm_get_speed_medium_from_elink_line_speed( IN const struct elink_vars* link_vars ) 517 { 518 const u16_t line_speed = link_vars->line_speed; 519 u32_t medium = 0; 520 521 switch(line_speed) 522 { 523 case ELINK_SPEED_10: 524 medium = LM_MEDIUM_SPEED_10MBPS; 525 break; 526 527 case ELINK_SPEED_100: 528 medium = LM_MEDIUM_SPEED_100MBPS; 529 break; 530 531 case ELINK_SPEED_1000: 532 medium = LM_MEDIUM_SPEED_1000MBPS; 533 break; 534 535 case ELINK_SPEED_2500: 536 medium = LM_MEDIUM_SPEED_2500MBPS; 537 break; 538 539 case ELINK_SPEED_10000: 540 medium = LM_MEDIUM_SPEED_10GBPS; 541 break; 542 543 case ELINK_SPEED_20000: 544 medium = LM_MEDIUM_SPEED_20GBPS; 545 break; 546 547 default: 548 DbgBreakIf(1); 549 break; 550 } 551 return medium; 552 } 553 554 u32_t lm_get_port_max_speed(IN struct _lm_device_t *pdev) 555 { 556 static const u32_t PORT_SPEED_10G = 10000; 557 static const u32_t PORT_SPEED_1G = 1000; 558 559 u32_t port_default_cfg = 0; 560 561 if(!CHIP_IS_E3(pdev)) 562 { 563 return PORT_SPEED_10G; 564 } 565 566 if(LM_CHIP_PORT_MODE_4 != CHIP_PORT_MODE(pdev)) 567 { 568 return PORT_SPEED_10G; 569 } 570 571 LM_SHMEM_READ(pdev,OFFSETOF(shmem_region_t,dev_info.port_hw_config[PORT_ID(pdev)].default_cfg),&port_default_cfg); 572 573 if (GET_FLAGS(port_default_cfg, PORT_HW_CFG_NET_SERDES_IF_MASK) == PORT_HW_CFG_NET_SERDES_IF_SGMII) 574 { 575 return PORT_SPEED_1G; 576 } 577 else 578 { 579 return PORT_SPEED_10G; 580 } 581 } 582 583 /* 584 *Function Name: lm_loopback_req_meduim_convert 585 * 586 *Parameters: IN req_medium as received from upper layer 587 * 588 *Description: convert the req_meduim (recieved from diag driver / BMAPI) to relevant type according to the chip 589 * this is a little bit conusing since we override the value recieved by a new value 590 * but we need to do it for backward compatbiality. 591 *Returns: "medium" translation to LM units 592 * 593 */ 594 lm_medium_t lm_loopback_req_medium_convert( IN struct _lm_device_t *pdev, IN const lm_medium_t req_medium ) 595 { 596 u32_t default_cfg = 0; 597 lm_medium_t ret_medium = req_medium; 598 599 // Assumption bxdiag always send the following for each test type: 600 // LOOPBACK_TYPE_MAC --> LM_MEDIUM_TYPE_BMAC_LOOPBACK/LM_MEDIUM_TYPE_UMAC_LOOPBACK/LM_MEDIUM_TYPE_XMAC_LOOPBACK (bxdiag 7.0.1 only, never gold...) 601 // LOOPBACK_TYPE_PHY --> LM_MEDIUM_TYPE_XGXS_10_LOOPBACK 602 603 // Here, we'll "translate" the LM_MEDIUM_TYPE_XXX so it will work correctly in BCM578xx 604 if( CHIP_IS_E3(pdev) ) 605 { 606 LM_SHMEM_READ(pdev,OFFSETOF(shmem_region_t,dev_info.port_hw_config[PORT_ID(pdev)].default_cfg),&default_cfg); 607 default_cfg &= PORT_HW_CFG_NET_SERDES_IF_MASK; 608 } 609 610 switch(req_medium) 611 { 612 // MAC loopback test 613 case LM_MEDIUM_TYPE_BMAC_LOOPBACK: 614 case LM_MEDIUM_TYPE_UMAC_LOOPBACK: 615 case LM_MEDIUM_TYPE_XMAC_LOOPBACK: 616 case LM_MEDIUM_TYPE_MAC_LOOPBACK: 617 if( CHIP_IS_E3(pdev) ) 618 { 619 if( PORT_HW_CFG_NET_SERDES_IF_SGMII == default_cfg ) 620 { 621 ret_medium = LM_MEDIUM_TYPE_UMAC_LOOPBACK; //1GB 622 } 623 else 624 { 625 ret_medium = LM_MEDIUM_TYPE_XMAC_LOOPBACK; //10GB/20GB 626 } 627 } 628 else 629 { 630 ret_medium = LM_MEDIUM_TYPE_BMAC_LOOPBACK; 631 } 632 break; 633 634 // PHY loopback test 635 case LM_MEDIUM_TYPE_XGXS_10_LOOPBACK: 636 if( CHIP_IS_E3(pdev) ) 637 { 638 switch(default_cfg) 639 { 640 case PORT_HW_CFG_NET_SERDES_IF_SGMII: 641 ret_medium = LM_MEDIUM_TYPE_XGXS_LOOPBACK; //1GB 642 break; 643 644 case PORT_HW_CFG_NET_SERDES_IF_XFI: 645 case PORT_HW_CFG_NET_SERDES_IF_SFI: 646 case PORT_HW_CFG_NET_SERDES_IF_KR: 647 ret_medium = LM_MEDIUM_TYPE_XGXS_10_LOOPBACK; //10GB 648 break; 649 650 case PORT_HW_CFG_NET_SERDES_IF_DXGXS: 651 case PORT_HW_CFG_NET_SERDES_IF_KR2: 652 default: 653 ret_medium = req_medium; //20GB - TBD!! for T7.2 654 break; 655 } 656 } 657 else 658 { 659 ret_medium = LM_MEDIUM_TYPE_XGXS_10_LOOPBACK; //10GB 660 } 661 break; 662 663 default: 664 break; 665 } 666 667 return ret_medium; 668 } 669 670 static void get_link_params(lm_device_t *pdev) 671 { 672 u32_t real_speed = 0; // speed in 100M steps 673 u32_t medium = 0; // LM_MEDIUM_XXX 674 u16_t max_bw_in_Mbps = 0; // In Mbps steps 675 u16_t max_bw_in_100Mbps = 0; // In 100Mbps steps 676 677 if (IS_VFDEV(pdev)) 678 { 679 pdev->vars.cable_is_attached = TRUE; 680 pdev->vars.link_status = LM_STATUS_LINK_ACTIVE; 681 SET_MEDIUM_SPEED(pdev->vars.medium,LM_MEDIUM_SPEED_10GBPS); 682 return; 683 } 684 // link status 685 686 if (!pdev->vars.link.link_up) 687 { 688 pdev->vars.link_status = LM_STATUS_LINK_DOWN; 689 pdev->vars.cable_is_attached = FALSE; 690 691 } 692 else 693 { 694 // if we are in multifunction mode and function is disabled indicate OS link down (unless loopback medium is set) 695 // Note that the CLC link is up so pmf handling is still going on 696 if (IS_MULTI_VNIC(pdev) && (GET_FLAGS(pdev->hw_info.mf_info.func_mf_cfg, FUNC_MF_CFG_FUNC_DISABLED)) && 697 (!LM_MEDIUM_IS_LOOPBACK(pdev->params.req_medium))) 698 { 699 pdev->vars.link_status = LM_STATUS_LINK_DOWN; 700 pdev->vars.cable_is_attached = FALSE; 701 } 702 else 703 { 704 //in NIV mode, link_status is modified only from lm_niv_vif_set or from the FUNCTION_UPDATE completion(for loopback) 705 if(!IS_MF_AFEX_MODE(pdev)) 706 { 707 pdev->vars.link_status = LM_STATUS_LINK_ACTIVE; 708 } 709 pdev->vars.cable_is_attached = TRUE; 710 } 711 // get speed 712 713 real_speed = lm_get_speed_real_from_elink_line_speed(&pdev->vars.link); 714 real_speed = real_speed/100; 715 716 medium = lm_get_speed_medium_from_elink_line_speed(&pdev->vars.link); 717 718 SET_MEDIUM_SPEED(pdev->vars.medium, medium ); 719 720 // get duplex 721 SET_MEDIUM_DUPLEX(pdev->vars.medium,LM_MEDIUM_FULL_DUPLEX); 722 if (pdev->vars.link.duplex == DUPLEX_HALF ) 723 { 724 SET_MEDIUM_DUPLEX(pdev->vars.medium,LM_MEDIUM_HALF_DUPLEX); 725 } 726 // get flow_control 727 pdev->vars.flow_control = LM_FLOW_CONTROL_NONE; 728 if (pdev->vars.link.flow_ctrl & ELINK_FLOW_CTRL_RX) 729 { 730 pdev->vars.flow_control |= LM_FLOW_CONTROL_RECEIVE_PAUSE; 731 } 732 if (pdev->vars.link.flow_ctrl & ELINK_FLOW_CTRL_TX) 733 { 734 pdev->vars.flow_control |= LM_FLOW_CONTROL_TRANSMIT_PAUSE; 735 } 736 737 // get EEE state 738 739 if (GET_FLAGS(pdev->vars.link.eee_status,SHMEM_EEE_REQUESTED_BIT)) 740 { 741 pdev->vars.autogreeen = LM_AUTOGREEEN_ENABLED; 742 pdev->vars.eee_policy = pdev->vars.link.eee_status & SHMEM_EEE_TIMER_MASK; 743 } 744 else 745 { 746 pdev->vars.autogreeen = LM_AUTOGREEEN_DISABLED; 747 } 748 749 if (IS_MULTI_VNIC(pdev)) 750 { 751 752 max_bw_in_Mbps = lm_get_max_bw(pdev, 753 (real_speed *100), 754 VNIC_ID(pdev)); 755 756 max_bw_in_100Mbps = max_bw_in_Mbps /100; // In 100Mbps steps 757 758 if (real_speed > max_bw_in_100Mbps) 759 { 760 if (max_bw_in_100Mbps) 761 { 762 SET_MEDIUM_SPEED(pdev->vars.medium,(LM_MEDIUM_SPEED_SEQ_START + ((max_bw_in_100Mbps-1)<<8))); 763 } 764 else 765 { 766 // in case the pdev->params.max_bw[VNIC_ID(pdev)] = 0 767 SET_MEDIUM_SPEED(pdev->vars.medium,LM_MEDIUM_SPEED_SEQ_START); 768 } 769 } 770 } 771 } 772 } 773 774 void sync_link_status(lm_device_t *pdev) 775 { 776 u32_t i = 0; 777 const u8_t func_id = FUNC_ID(pdev); 778 const u8_t port_id = PORT_ID(pdev); 779 780 DbgMessage(pdev, WARN, "sync_link_status: Func %d \n", func_id ); 781 782 // inform all other port vnics not ourself 783 for( i=0; i<4 ;i++ ) 784 { 785 if (func_id != (i*2 + port_id)) 786 { 787 REG_WR(pdev,MISC_REG_AEU_GENERAL_ATTN_12 + 4*(i*2 + port_id),0x1); 788 DbgMessage(pdev, WARN, "sync_link_status: send attention to Func %d\n", (i*2 + port_id)); 789 } 790 } 791 } 792 793 void 794 lm_reset_link(lm_device_t *pdev) 795 { 796 if (IS_VFDEV(pdev)) 797 { 798 DbgMessage(pdev, FATAL, "lm_reset_link not implemented for VF\n"); 799 return; 800 801 } 802 // notify stats 803 lm_stats_on_link_update(pdev, FALSE ); 804 pdev->vars.link_status = LM_STATUS_LINK_DOWN; 805 pdev->vars.cable_is_attached = FALSE; 806 pdev->vars.mac_type = MAC_TYPE_NONE; 807 808 PHY_HW_LOCK(pdev); 809 elink_lfa_reset(&pdev->params.link,&pdev->vars.link); 810 PHY_HW_UNLOCK(pdev); 811 } 812 /** 813 * @description 814 * Configure cmng the firmware to the right CMNG values if this 815 * device is the PMF ,after link speed/ETS changes. 816 * 817 * @note This function must be called under PHY_LOCK 818 * @param pdev 819 */ 820 void lm_cmng_update(lm_device_t *pdev) 821 { 822 u32_t port_speed = 0; 823 824 /* fairness is only supported for vnics in the meantime... */ 825 if ((!IS_MULTI_VNIC(pdev)) || 826 (!pdev->vars.link.link_up)) 827 { 828 return; 829 } 830 831 if (!IS_PMF(pdev) && !IS_MF_AFEX_MODE(pdev)) 832 { 833 // in case we are not PMF we still want to run this code in AFEX mode. 834 return; 835 } 836 837 port_speed = lm_get_speed_real_from_elink_line_speed(&pdev->vars.link); 838 839 lm_cmng_init(pdev,port_speed); 840 } 841 842 void lm_reload_link_and_cmng(lm_device_t *pdev) 843 { 844 if( IS_MULTI_VNIC(pdev) && pdev->hw_info.mcp_detected ) 845 { 846 lm_cmng_get_shmem_info(pdev); 847 lm_cmng_calc_params(pdev); 848 } 849 850 get_link_params(pdev); 851 852 lm_cmng_update(pdev); 853 854 } 855 856 void lm_link_fill_reported_data( IN lm_device_t *pdev, OUT lm_reported_link_params_t *lm_reported_link_params ) 857 { 858 lm_reported_link_params->cable_is_attached = pdev->vars.cable_is_attached; 859 lm_reported_link_params->link = pdev->vars.link_status; 860 lm_reported_link_params->medium = pdev->vars.medium; 861 lm_reported_link_params->flow_ctrl = pdev->vars.flow_control; 862 lm_reported_link_params->eee_policy = (u8_t)pdev->vars.eee_policy; // one of PORT_FEAT_CFG_EEE_POWER_MODE_* 863 } 864 865 // This function is called due to link change attention for none pmf it gets the link status from the shmem 866 void lm_link_report(lm_device_t *pdev) 867 { 868 u8_t pause_ena = 0; 869 lm_reported_link_params_t current_link_params = {0}; 870 u8_t b_indicate = TRUE; 871 872 lm_reload_link_and_cmng(pdev); 873 874 // get current link params into current_link_params 875 lm_link_fill_reported_data(pdev, ¤t_link_params ); 876 877 /* Don't report link down again (if it is already down) */ 878 if( (LM_STATUS_LINK_DOWN == pdev->vars.last_reported_link_params.link) && 879 (LM_STATUS_LINK_DOWN == current_link_params.link) ) 880 { 881 b_indicate = FALSE; 882 } 883 else 884 { 885 // Don't report exact same link status twice 886 ASSERT_STATIC( sizeof(current_link_params) == sizeof(pdev->vars.last_reported_link_params) ); 887 b_indicate = ( FALSE == mm_memcmp( ¤t_link_params, &pdev->vars.last_reported_link_params, sizeof(current_link_params)) ); 888 } 889 890 if (pdev->vars.link.link_up) 891 { 892 // link up 893 // dropless flow control 894 if (IS_PMF(pdev) && pdev->params.l2_fw_flow_ctrl) 895 { 896 if (pdev->vars.link.flow_ctrl & ELINK_FLOW_CTRL_TX) 897 { 898 pause_ena = 1; 899 } 900 LM_INTMEM_WRITE16(pdev,USTORM_ETH_PAUSE_ENABLED_OFFSET(PORT_ID(pdev)), pause_ena, BAR_USTRORM_INTMEM); 901 } 902 pdev->vars.mac_type = pdev->vars.link.mac_type; 903 DbgBreakIf(pdev->vars.mac_type >= MAC_TYPE_MAX); 904 905 // indicate link up - except if we're in NIV mode where we wait for the VIF-SET/enable command from the MCP. 906 if( IS_MF_AFEX_MODE(pdev) ) 907 { 908 b_indicate = FALSE; 909 } 910 911 // indicate link up 912 if( b_indicate ) 913 { 914 mm_indicate_link(pdev, pdev->vars.link_status, pdev->vars.medium); 915 DbgMessage(pdev, WARN, "lm_link_update: indicate link %d 0x%x \n",pdev->vars.link_status,pdev->vars.medium); 916 } 917 918 // notify stats 919 lm_stats_on_link_update(pdev, TRUE ); 920 } 921 else 922 { // link down 923 // indicate link down 924 pdev->vars.mac_type = MAC_TYPE_NONE; 925 pdev->vars.stats.stats_collect.stats_hw.b_is_link_up = FALSE; 926 927 // indicate link down 928 if( b_indicate ) 929 { 930 mm_indicate_link(pdev, pdev->vars.link_status, pdev->vars.medium); 931 DbgMessage(pdev, WARN, "lm_link_update: indicate link %d 0x%x \n",pdev->vars.link_status,pdev->vars.medium); 932 } 933 } 934 935 // notify othres funcs 936 if (IS_MULTI_VNIC(pdev) && IS_PMF(pdev)) 937 { 938 sync_link_status(pdev); 939 } 940 } 941 942 // This function is called due to link change interrupt for the relevant function 943 // NOTE: this function must be called under phy lock 944 lm_status_t lm_link_update(lm_device_t *pdev) 945 { 946 if CHK_NULL( pdev ) 947 { 948 DbgBreakIf(!pdev); 949 return LM_STATUS_FAILURE; 950 } 951 // notify stats 952 lm_stats_on_link_update(pdev, FALSE ); 953 954 if( pdev->params.i2c_interval_sec ) 955 { 956 pdev->params.i2c_elink_status[I2C_SECTION_A0] = ELINK_STATUS_INVALID_IMAGE; 957 pdev->params.i2c_elink_status[I2C_SECTION_A2] = ELINK_STATUS_INVALID_IMAGE; 958 } 959 960 PHY_HW_LOCK(pdev); 961 elink_link_update(&pdev->params.link,&pdev->vars.link); 962 PHY_HW_UNLOCK(pdev); 963 lm_link_report(pdev); 964 // increment link_chng_cnt counter to indicate there was some link change. 965 pdev->vars.link_chng_cnt++; 966 return LM_STATUS_SUCCESS; 967 } 968 969 static void lm_set_phy_selection( lm_device_t *pdev, u8_t i) 970 { 971 u32 phy_sel ; 972 if (pdev->params.link.multi_phy_config & PORT_HW_CFG_PHY_SWAPPED_ENABLED) 973 { 974 phy_sel = PORT_HW_CFG_PHY_SELECTION_SECOND_PHY - (i - ELINK_EXT_PHY1); 975 } 976 else 977 { 978 phy_sel = PORT_HW_CFG_PHY_SELECTION_FIRST_PHY + (i - ELINK_EXT_PHY1); 979 } 980 RESET_FLAGS( pdev->params.link.multi_phy_config, PORT_HW_CFG_PHY_SELECTION_MASK ); 981 SET_FLAGS( pdev->params.link.multi_phy_config, phy_sel); 982 } 983 984 static void lm_set_phy_priority_selection( lm_device_t *pdev, u8_t i) 985 { 986 u32 phy_sel; 987 988 if (pdev->params.link.multi_phy_config & PORT_HW_CFG_PHY_SWAPPED_ENABLED) 989 { 990 phy_sel = PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY - (i - ELINK_EXT_PHY1); 991 } 992 else 993 { 994 phy_sel = PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY + (i - ELINK_EXT_PHY1); 995 } 996 RESET_FLAGS( pdev->params.link.multi_phy_config, PORT_HW_CFG_PHY_SELECTION_MASK ); 997 SET_FLAGS( pdev->params.link.multi_phy_config, phy_sel); 998 } 999 1000 /******************************************************************************* 1001 * Description: 1002 * 1003 * Return: 1004 ******************************************************************************/ 1005 STATIC 1006 lm_status_t lm_set_phy_priority_mode(lm_device_t *pdev) 1007 { 1008 lm_status_t lm_status = LM_STATUS_SUCCESS; 1009 u8_t i = 0; 1010 1011 if (CHK_NULL(pdev)) 1012 { 1013 return LM_STATUS_INVALID_PARAMETER; 1014 } 1015 1016 switch (pdev->params.phy_priority_mode) 1017 { 1018 case PHY_PRIORITY_MODE_HW_DEF: 1019 RESET_FLAGS( pdev->params.link.multi_phy_config, PORT_HW_CFG_PHY_SELECTION_MASK ); 1020 SET_FLAGS( pdev->params.link.multi_phy_config, pdev->hw_info.multi_phy_config); 1021 break; 1022 1023 case PHY_PRIORITY_MODE_10GBASET: 1024 i = ELINK_EXT_PHY1; 1025 while (i < ELINK_MAX_PHYS) 1026 { 1027 if (pdev->params.link.phy[i].media_type == ELINK_ETH_PHY_BASE_T) 1028 { 1029 lm_set_phy_priority_selection(pdev, i); 1030 break; 1031 } 1032 i++; 1033 } 1034 break; 1035 1036 case PHY_PRIORITY_MODE_SERDES: 1037 i = ELINK_EXT_PHY1; 1038 while (i < ELINK_MAX_PHYS) 1039 { 1040 if ((pdev->params.link.phy[i].media_type == ELINK_ETH_PHY_SFPP_10G_FIBER) || 1041 (pdev->params.link.phy[i].media_type == ELINK_ETH_PHY_SFP_1G_FIBER) || 1042 (pdev->params.link.phy[i].media_type == ELINK_ETH_PHY_XFP_FIBER) || 1043 (pdev->params.link.phy[i].media_type == ELINK_ETH_PHY_DA_TWINAX) || 1044 (pdev->params.link.phy[i].media_type == ELINK_ETH_PHY_NOT_PRESENT)) 1045 { 1046 lm_set_phy_priority_selection(pdev, i); 1047 break; 1048 } 1049 i++; 1050 } 1051 break; 1052 1053 case PHY_PRIORITY_MODE_HW_PIN: 1054 RESET_FLAGS( pdev->params.link.multi_phy_config, PORT_HW_CFG_PHY_SELECTION_MASK ); 1055 SET_FLAGS( pdev->params.link.multi_phy_config, PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT); 1056 break; 1057 1058 default: 1059 DbgBreak(); 1060 lm_status = LM_STATUS_FAILURE; 1061 break; 1062 } 1063 1064 return lm_status; 1065 } 1066 1067 /******************************************************************************* 1068 * Description: 1069 * 1070 * Return: 1071 ******************************************************************************/ 1072 STATIC 1073 lm_status_t lm_set_phy_link_params(lm_device_t *pdev, 1074 lm_medium_t req_medium, 1075 lm_flow_control_t flow_control, 1076 u8_t sw_config, 1077 u8_t phy_num) 1078 { 1079 lm_medium_t speed = GET_MEDIUM_SPEED(req_medium); 1080 lm_medium_t duplex = GET_MEDIUM_DUPLEX(req_medium); 1081 1082 DbgMessage(pdev, WARN, "lm_set_phy_link_params: speed 0x%x\n",speed); 1083 // Get speed from shared memory not registry - if mcp is detected... 1084 if(pdev->hw_info.mcp_detected && ((speed == LM_MEDIUM_SPEED_HARDWARE_DEFAULT) || (IS_MULTI_VNIC(pdev)))) 1085 { 1086 DbgMessage(pdev, WARN, "lm_init_phy: pdev->hw_info.link_config[phy_num] = 0x%x\n",pdev->hw_info.link_config[phy_num]); 1087 switch(pdev->hw_info.link_config[phy_num] & PORT_FEATURE_LINK_SPEED_MASK) 1088 { 1089 1090 case PORT_FEATURE_LINK_SPEED_10M_FULL: 1091 SET_MEDIUM_SPEED(speed,LM_MEDIUM_SPEED_10MBPS); 1092 SET_MEDIUM_DUPLEX(duplex,LM_MEDIUM_FULL_DUPLEX); 1093 break; 1094 case PORT_FEATURE_LINK_SPEED_10M_HALF: 1095 SET_MEDIUM_SPEED(speed,LM_MEDIUM_SPEED_10MBPS); 1096 SET_MEDIUM_DUPLEX(duplex,LM_MEDIUM_HALF_DUPLEX); 1097 break; 1098 case PORT_FEATURE_LINK_SPEED_100M_FULL: 1099 SET_MEDIUM_SPEED(speed,LM_MEDIUM_SPEED_100MBPS); 1100 SET_MEDIUM_DUPLEX(duplex,LM_MEDIUM_FULL_DUPLEX); 1101 break; 1102 case PORT_FEATURE_LINK_SPEED_100M_HALF: 1103 SET_MEDIUM_SPEED(speed,LM_MEDIUM_SPEED_100MBPS); 1104 SET_MEDIUM_DUPLEX(duplex,LM_MEDIUM_HALF_DUPLEX); 1105 break; 1106 case PORT_FEATURE_LINK_SPEED_1G: 1107 SET_MEDIUM_SPEED(speed,LM_MEDIUM_SPEED_1000MBPS); 1108 SET_MEDIUM_DUPLEX(duplex,LM_MEDIUM_FULL_DUPLEX); 1109 break; 1110 case PORT_FEATURE_LINK_SPEED_2_5G: 1111 SET_MEDIUM_SPEED(speed,LM_MEDIUM_SPEED_2500MBPS); 1112 SET_MEDIUM_DUPLEX(duplex,LM_MEDIUM_FULL_DUPLEX); 1113 break; 1114 case PORT_FEATURE_LINK_SPEED_10G_CX4: 1115 SET_MEDIUM_SPEED(speed,LM_MEDIUM_SPEED_10GBPS); 1116 SET_MEDIUM_DUPLEX(duplex,LM_MEDIUM_FULL_DUPLEX); 1117 break; 1118 case PORT_FEATURE_LINK_SPEED_20G: 1119 SET_MEDIUM_SPEED(speed,LM_MEDIUM_SPEED_20GBPS); 1120 SET_MEDIUM_DUPLEX(duplex,LM_MEDIUM_FULL_DUPLEX); 1121 break; 1122 case PORT_FEATURE_LINK_SPEED_AUTO: 1123 SET_MEDIUM_SPEED(speed,LM_MEDIUM_SPEED_AUTONEG); 1124 SET_MEDIUM_DUPLEX(duplex,LM_MEDIUM_FULL_DUPLEX); 1125 break; 1126 default: 1127 //Follow Teton solution:We need to do this because Microsoft's definition 1128 // is not complete, like speed 2.5gb or some other speeds. 1129 SET_MEDIUM_SPEED(speed,LM_MEDIUM_SPEED_AUTONEG); 1130 SET_MEDIUM_DUPLEX(duplex,LM_MEDIUM_FULL_DUPLEX); 1131 break; 1132 } 1133 1134 DbgMessage(pdev, WARN, "lm_set_phy_link_params: speed 0x%x duplex 0x%x\n",speed,duplex); 1135 } 1136 pdev->params.link.req_duplex[phy_num] = DUPLEX_FULL; 1137 if ( duplex == LM_MEDIUM_HALF_DUPLEX) 1138 { 1139 pdev->params.link.req_duplex[phy_num] = DUPLEX_HALF; 1140 } 1141 1142 switch (speed) 1143 { 1144 case LM_MEDIUM_SPEED_AUTONEG: 1145 pdev->params.link.req_line_speed[phy_num] = ELINK_SPEED_AUTO_NEG; 1146 break; 1147 case LM_MEDIUM_SPEED_10MBPS: 1148 pdev->params.link.req_line_speed[phy_num] = ELINK_SPEED_10; 1149 break; 1150 case LM_MEDIUM_SPEED_100MBPS: 1151 pdev->params.link.req_line_speed[phy_num] = ELINK_SPEED_100; 1152 break; 1153 case LM_MEDIUM_SPEED_1000MBPS: 1154 pdev->params.link.req_line_speed[phy_num] = ELINK_SPEED_1000; 1155 break; 1156 case LM_MEDIUM_SPEED_2500MBPS: 1157 pdev->params.link.req_line_speed[phy_num] = ELINK_SPEED_2500; 1158 break; 1159 case LM_MEDIUM_SPEED_10GBPS: 1160 pdev->params.link.req_line_speed[phy_num] = ELINK_SPEED_10000; 1161 break; 1162 case LM_MEDIUM_SPEED_20GBPS: 1163 pdev->params.link.req_line_speed[phy_num] = ELINK_SPEED_20000; 1164 break; 1165 default: 1166 DbgBreakIf(!DBG_BREAK_ON(UNDER_TEST)); 1167 return LM_STATUS_INVALID_PARAMETER; 1168 } 1169 1170 pdev->params.link.req_flow_ctrl[phy_num] = 0; 1171 if (flow_control == LM_FLOW_CONTROL_NONE) 1172 { 1173 pdev->params.link.req_flow_ctrl[phy_num] = ELINK_FLOW_CTRL_NONE; 1174 } 1175 else if (flow_control & LM_FLOW_CONTROL_AUTO_PAUSE) 1176 { 1177 pdev->params.link.req_flow_ctrl[phy_num] = ELINK_FLOW_CTRL_AUTO; 1178 } 1179 else 1180 { 1181 /* Under flow control reporting mode we */ 1182 if ((speed == LM_MEDIUM_SPEED_AUTONEG) && 1183 (pdev->params.flow_control_reporting_mode == LM_FLOW_CONTROL_REPORTING_MODE_ENABLED)) 1184 { 1185 pdev->params.link.req_flow_ctrl[phy_num] = ELINK_FLOW_CTRL_AUTO; 1186 } 1187 else 1188 { 1189 if (flow_control & LM_FLOW_CONTROL_RECEIVE_PAUSE) 1190 { 1191 pdev->params.link.req_flow_ctrl[phy_num] |= ELINK_FLOW_CTRL_RX; 1192 } 1193 if (flow_control & LM_FLOW_CONTROL_TRANSMIT_PAUSE) 1194 { 1195 pdev->params.link.req_flow_ctrl[phy_num] |= ELINK_FLOW_CTRL_TX; 1196 } 1197 } 1198 } 1199 1200 return LM_STATUS_SUCCESS; 1201 } 1202 1203 /** 1204 * @Description 1205 * this function sets the flow control auto negotiation 1206 * advertise parameter. 1207 * 1208 * @param pdev 1209 * @param flow_control 1210 */ 1211 void lm_set_fc_auto_adv_params(lm_device_t * pdev, lm_flow_control_t flow_control) 1212 { 1213 u16_t req_fc_auto_adv = ELINK_FLOW_CTRL_BOTH; 1214 u8_t mtu_above_thr = FALSE; 1215 u8_t report_mode_tx_only = FALSE; 1216 1217 /* There are two cases where we will set flow control auto adv to TX only. 1218 * 1. Has to do with a bug in E1/E1x in which we can't support rx flow control if mtu is larger than 1219 * a certain threshold. (mtu_above_th) 1220 * 2. cq CQ57772, required only under special registry key, in which we want the flow control displayed 1221 * in gui (i.e. received by ioctl) to show the resolved flow control (after auto negotiation) and not 1222 * the requested flow control (in case forced force control is used). For this purpose, if we're in auto-neg 1223 * and a forced flow control was requested, we set the request flow control to auto (later on in set_link_parameters) 1224 * if forced TX is requested, we se the adv to tx only..(report_mode_tx_only) 1225 */ 1226 mtu_above_thr = CHIP_IS_E1x(pdev) && !IS_MULTI_VNIC(pdev) && (pdev->params.mtu_max > LM_MTU_FLOW_CTRL_TX_THR); 1227 report_mode_tx_only = (pdev->params.flow_control_reporting_mode == LM_FLOW_CONTROL_REPORTING_MODE_ENABLED) && 1228 (flow_control == LM_FLOW_CONTROL_TRANSMIT_PAUSE); 1229 1230 if (mtu_above_thr || report_mode_tx_only) 1231 { 1232 req_fc_auto_adv = ELINK_FLOW_CTRL_TX; 1233 } 1234 1235 pdev->params.link.req_fc_auto_adv = req_fc_auto_adv; 1236 } 1237 /******************************************************************************* 1238 * Description: 1239 * 1240 * Return: 1241 ******************************************************************************/ 1242 lm_status_t 1243 lm_init_phy( lm_device_t *pdev, 1244 lm_medium_t req_medium, 1245 lm_flow_control_t flow_control, 1246 u32_t selective_autoneg, 1247 u32_t wire_speed, 1248 u32_t wait_link_timeout_us) 1249 { 1250 u8_t i = 0; 1251 u8_t sw_config = 0; 1252 u8_t elink_status = ELINK_STATUS_OK; 1253 lm_medium_t speed = 0; 1254 lm_medium_t type = GET_MEDIUM_TYPE(req_medium); 1255 struct elink_params *link = &pdev->params.link; 1256 lm_status_t lm_status = LM_STATUS_SUCCESS; 1257 iscsi_info_block_hdr_t iscsi_info_block_hdr = {0} ; 1258 1259 UNREFERENCED_PARAMETER_(wait_link_timeout_us); 1260 UNREFERENCED_PARAMETER_(wire_speed); 1261 UNREFERENCED_PARAMETER_(selective_autoneg); 1262 1263 if (IS_VFDEV(pdev)) 1264 { 1265 return LM_STATUS_SUCCESS; 1266 } 1267 1268 //fill clc params 1269 if CHK_NULL( pdev ) 1270 { 1271 DbgBreakIf(!pdev) ; 1272 return LM_STATUS_FAILURE; 1273 } 1274 1275 // override preemphasis for specific svid/ssid 1276 if( 0x1120 == pdev->hw_info.svid ) 1277 { 1278 switch (pdev->hw_info.ssid) 1279 { 1280 case 0x4f70: 1281 case 0x4375: 1282 { 1283 if( pdev->params.preemphasis_enable ) 1284 { 1285 // The relevant ssids are from SINGLE_MEDIA board type, so only EXT_PHY1 needs to be set. 1286 SET_FLAGS(pdev->params.link.feature_config_flags, ELINK_FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED); 1287 pdev->params.link.phy[ELINK_EXT_PHY1].rx_preemphasis[0] = (u16_t)pdev->params.preemphasis_rx_0; 1288 pdev->params.link.phy[ELINK_EXT_PHY1].rx_preemphasis[1] = (u16_t)pdev->params.preemphasis_rx_1; 1289 pdev->params.link.phy[ELINK_EXT_PHY1].rx_preemphasis[2] = (u16_t)pdev->params.preemphasis_rx_2; 1290 pdev->params.link.phy[ELINK_EXT_PHY1].rx_preemphasis[3] = (u16_t)pdev->params.preemphasis_rx_3; 1291 pdev->params.link.phy[ELINK_EXT_PHY1].tx_preemphasis[0] = (u16_t)pdev->params.preemphasis_tx_0; 1292 pdev->params.link.phy[ELINK_EXT_PHY1].tx_preemphasis[1] = (u16_t)pdev->params.preemphasis_tx_1; 1293 pdev->params.link.phy[ELINK_EXT_PHY1].tx_preemphasis[2] = (u16_t)pdev->params.preemphasis_tx_2; 1294 pdev->params.link.phy[ELINK_EXT_PHY1].tx_preemphasis[3] = (u16_t)pdev->params.preemphasis_tx_3; 1295 } 1296 } 1297 break; 1298 1299 default: 1300 break; 1301 } 1302 } 1303 1304 /* Set req_fc_auto_adv */ 1305 lm_set_fc_auto_adv_params(pdev, flow_control); 1306 1307 for (i = 0 ; i < 6 ; i++) 1308 { 1309 pdev->params.link.mac_addr[i] = pdev->params.mac_addr[i]; 1310 } 1311 1312 sw_config = (u8_t)pdev->params.sw_config; 1313 DbgMessage(pdev, WARN, "lm_init_phy: sw_config 0x%x\n",sw_config); 1314 1315 if (LM_SWCFG_HW_DEF == sw_config ) 1316 { 1317 if (CHIP_IS_E1x(pdev) || CHIP_IS_E2(pdev)) 1318 { 1319 sw_config = (u8_t)(pdev->params.link.switch_cfg>>PORT_FEATURE_CONNECTED_SWITCH_SHIFT); 1320 } 1321 else 1322 { 1323 sw_config = LM_SWCFG_10G; 1324 } 1325 DbgMessage(pdev, WARN, "lm_init_phy: sw_config 0x%x\n",sw_config); 1326 } 1327 1328 #ifndef EDIAG 1329 1330 switch( pdev->params.autogreeen ) 1331 { 1332 case LM_AUTOGREEEN_NVRAM: 1333 1334 // Use whatever is configured in the NVRAM 1335 break; 1336 1337 case LM_AUTOGREEEN_DISABLED: 1338 1339 RESET_FLAGS(pdev->params.link.feature_config_flags, ELINK_FEATURE_CONFIG_AUTOGREEEN_ENABLED ); 1340 1341 RESET_FLAGS(pdev->params.link.eee_mode, // no EEE 1342 ELINK_EEE_MODE_ENABLE_LPI | 1343 ELINK_EEE_MODE_ADV_LPI); 1344 1345 break; 1346 1347 case LM_AUTOGREEEN_ENABLED: 1348 1349 SET_FLAGS(pdev->params.link.feature_config_flags, ELINK_FEATURE_CONFIG_AUTOGREEEN_ENABLED ); 1350 1351 RESET_FLAGS(pdev->params.link.eee_mode, ELINK_EEE_MODE_OVERRIDE_NVRAM); 1352 RESET_FLAGS(pdev->params.link.eee_mode, ELINK_EEE_MODE_NVRAM_MASK); 1353 1354 switch (pdev->params.eee_policy) 1355 { 1356 case LM_EEE_CONTROL_HIGH: // enable EEE mode, advertise "AGGRESSIVE" (Registry: MaxPowerSave) 1357 1358 SET_FLAGS(pdev->params.link.eee_mode, 1359 ELINK_EEE_MODE_OVERRIDE_NVRAM | 1360 ELINK_EEE_MODE_ADV_LPI | 1361 ELINK_EEE_MODE_ENABLE_LPI | 1362 PORT_FEAT_CFG_EEE_POWER_MODE_AGGRESSIVE ); 1363 break; 1364 1365 case LM_EEE_CONTROL_MED: // enable EEE mode, advertise "BALANCED" (Registry: Balance) 1366 1367 SET_FLAGS(pdev->params.link.eee_mode, 1368 ELINK_EEE_MODE_OVERRIDE_NVRAM | 1369 ELINK_EEE_MODE_ADV_LPI | 1370 ELINK_EEE_MODE_ENABLE_LPI | 1371 PORT_FEAT_CFG_EEE_POWER_MODE_BALANCED); 1372 break; 1373 1374 case LM_EEE_CONTROL_LOW: // enable EEE mode, advertise "LOW_LATENCY" (Registry: MaxPerformace) 1375 1376 SET_FLAGS(pdev->params.link.eee_mode, 1377 ELINK_EEE_MODE_OVERRIDE_NVRAM | 1378 ELINK_EEE_MODE_ADV_LPI | 1379 ELINK_EEE_MODE_ENABLE_LPI | 1380 PORT_FEAT_CFG_EEE_POWER_MODE_LOW_LATENCY); 1381 break; 1382 1383 case LM_EEE_CONTROL_NVRAM: // use NVRAM value 1384 1385 SET_FLAGS(pdev->params.link.eee_mode, 1386 ELINK_EEE_MODE_ENABLE_LPI | 1387 ELINK_EEE_MODE_ADV_LPI); 1388 break; 1389 1390 default: 1391 1392 // break here if illegal value was read from registry (CHK version only). 1393 DbgBreakIf(1); 1394 1395 break; 1396 } 1397 1398 break; 1399 1400 default: 1401 1402 DbgBreakIf(1); // unknown value 1403 } 1404 1405 DbgMessage(pdev, WARN, "lm_init_phy: autogreeen 0x%x\n", pdev->params.autogreeen); 1406 #endif 1407 1408 switch (sw_config) 1409 { 1410 // TODO change to shmem defines 1411 case LM_SWCFG_1G: 1412 SET_MEDIUM_TYPE(pdev->vars.medium, LM_MEDIUM_TYPE_SERDES); 1413 break; 1414 case LM_SWCFG_10G: 1415 SET_MEDIUM_TYPE(pdev->vars.medium, LM_MEDIUM_TYPE_XGXS); 1416 break; 1417 default: 1418 DbgBreakIf(1); 1419 break; 1420 } 1421 // Override setting if dual media and phy type specified from miniport 1422 if ((ELINK_DUAL_MEDIA(link)) && 1423 ((type == LM_MEDIUM_TYPE_SERDES) || 1424 (type == LM_MEDIUM_TYPE_XGXS))) 1425 { 1426 SET_MEDIUM_TYPE(pdev->vars.medium, type); 1427 } 1428 1429 lm_status = lm_set_phy_link_params(pdev, req_medium, flow_control, sw_config, ELINK_INT_PHY); 1430 if (LM_STATUS_SUCCESS == lm_status) { 1431 if (ELINK_DUAL_MEDIA(link)) 1432 { 1433 lm_set_phy_link_params(pdev, req_medium, flow_control, sw_config, ELINK_EXT_PHY1); 1434 } 1435 } else { 1436 return lm_status; 1437 } 1438 1439 /* If 10G is requested and it is blocked on this KR, issue event log */ 1440 if( pdev->hw_info.no_10g_kr ) 1441 { 1442 speed = GET_MEDIUM_SPEED(req_medium); 1443 if( LM_MEDIUM_SPEED_10GBPS == speed ) 1444 { 1445 DbgMessage(pdev, WARN, "lm_init_phy: 10gb speed parameter is blocked 0x%x\n",speed); 1446 1447 // block this request (elink does not support it) & log 1448 mm_event_log_generic(pdev, LM_LOG_ID_NO_10G_SUPPORT, PORT_ID(pdev) ); 1449 return LM_STATUS_SUCCESS; 1450 } 1451 } 1452 1453 switch (type) 1454 { 1455 case LM_MEDIUM_TYPE_XGXS_LOOPBACK: 1456 pdev->params.link.loopback_mode = ELINK_LOOPBACK_XGXS; 1457 pdev->params.link.req_line_speed[0] = ELINK_SPEED_1000; 1458 break; 1459 case LM_MEDIUM_TYPE_XGXS_10_LOOPBACK: 1460 pdev->params.link.loopback_mode = ELINK_LOOPBACK_XGXS; 1461 // for bacs PHY loopback test set speed to 10G. 1462 // Otherwise do not overwrite the speed 1463 if (!pdev->params.link.req_line_speed[0]) 1464 { 1465 if (pdev->params.link.speed_cap_mask[0] & PORT_HW_CFG_SPEED_CAPABILITY2_D0_20G) 1466 { 1467 pdev->params.link.req_line_speed[0] = ELINK_SPEED_20000; 1468 } 1469 else 1470 { 1471 pdev->params.link.req_line_speed[0] = ELINK_SPEED_10000; 1472 } 1473 } 1474 break; 1475 case LM_MEDIUM_TYPE_EMAC_LOOPBACK: 1476 pdev->params.link.loopback_mode = ELINK_LOOPBACK_EMAC; 1477 break; 1478 case LM_MEDIUM_TYPE_BMAC_LOOPBACK: 1479 pdev->params.link.loopback_mode = ELINK_LOOPBACK_BMAC; 1480 break; 1481 case LM_MEDIUM_TYPE_EXT_PHY_LOOPBACK: 1482 pdev->params.link.loopback_mode = ELINK_LOOPBACK_EXT_PHY; 1483 if (pdev->params.link.speed_cap_mask[0] & PORT_HW_CFG_SPEED_CAPABILITY2_D0_20G) 1484 { 1485 pdev->params.link.req_line_speed[0] = ELINK_SPEED_20000; 1486 } 1487 else if (pdev->params.link.speed_cap_mask[0] & PORT_HW_CFG_SPEED_CAPABILITY2_D0_10G) 1488 { 1489 pdev->params.link.req_line_speed[0] = ELINK_SPEED_10000; 1490 } 1491 else 1492 { 1493 pdev->params.link.req_line_speed[0] = ELINK_SPEED_1000; 1494 } 1495 // TBD: Dual Media ext PHY loopback test for second ext PHY ? 1496 break; 1497 case LM_MEDIUM_TYPE_EXT_LOOPBACK: 1498 pdev->params.link.loopback_mode = ELINK_LOOPBACK_EXT; 1499 break; 1500 case LM_MEDIUM_TYPE_XMAC_LOOPBACK: 1501 pdev->params.link.loopback_mode = ELINK_LOOPBACK_XMAC; 1502 break; 1503 case LM_MEDIUM_TYPE_UMAC_LOOPBACK: 1504 pdev->params.link.loopback_mode = ELINK_LOOPBACK_UMAC; 1505 break; 1506 default: 1507 pdev->params.link.loopback_mode = ELINK_LOOPBACK_NONE; 1508 break; 1509 } 1510 1511 // Handle dual media boards, if phy type specified from miniport 1512 if (ELINK_DUAL_MEDIA(link)) 1513 { 1514 switch (type) 1515 { 1516 case LM_MEDIUM_TYPE_SERDES: 1517 i = ELINK_EXT_PHY1; 1518 while (i < ELINK_MAX_PHYS) 1519 { 1520 if ((pdev->params.link.phy[i].media_type == ELINK_ETH_PHY_SFPP_10G_FIBER) || 1521 (pdev->params.link.phy[i].media_type == ELINK_ETH_PHY_SFP_1G_FIBER) || 1522 (pdev->params.link.phy[i].media_type == ELINK_ETH_PHY_XFP_FIBER) || 1523 (pdev->params.link.phy[i].media_type == ELINK_ETH_PHY_DA_TWINAX)) 1524 { 1525 lm_set_phy_selection(pdev, i); 1526 break; 1527 } 1528 i++; 1529 } 1530 break; 1531 1532 case LM_MEDIUM_TYPE_XGXS: 1533 i = ELINK_EXT_PHY1; 1534 while (i < ELINK_MAX_PHYS) 1535 { 1536 if ((pdev->params.link.phy[i].media_type == ELINK_ETH_PHY_BASE_T)) 1537 { 1538 lm_set_phy_selection(pdev, i); 1539 break; 1540 } 1541 i++; 1542 } 1543 break; 1544 1545 case LM_MEDIUM_AUTO_DETECT: 1546 lm_set_phy_priority_mode(pdev); 1547 break; 1548 1549 case LM_MEDIUM_TYPE_XGXS_LOOPBACK: 1550 case LM_MEDIUM_TYPE_XGXS_10_LOOPBACK: 1551 case LM_MEDIUM_TYPE_EMAC_LOOPBACK: 1552 case LM_MEDIUM_TYPE_BMAC_LOOPBACK: 1553 case LM_MEDIUM_TYPE_EXT_PHY_LOOPBACK: 1554 case LM_MEDIUM_TYPE_EXT_LOOPBACK: 1555 case LM_MEDIUM_TYPE_XMAC_LOOPBACK: 1556 case LM_MEDIUM_TYPE_UMAC_LOOPBACK: 1557 // Do nothing. 1558 break; 1559 default: 1560 DbgBreak(); 1561 break; 1562 } 1563 } 1564 1565 DbgMessage(pdev, WARN, "lm_init_phy: loopback_mode 0x%x\n",pdev->params.link.loopback_mode); 1566 if (IS_PMF(pdev)) 1567 { 1568 if( pdev->params.i2c_interval_sec ) 1569 { 1570 pdev->params.i2c_elink_status[I2C_SECTION_A0] = ELINK_STATUS_INVALID_IMAGE; 1571 pdev->params.i2c_elink_status[I2C_SECTION_A2] = ELINK_STATUS_INVALID_IMAGE; 1572 } 1573 if (lm_get_iscsi_boot_info_block(pdev,&iscsi_info_block_hdr) == LM_STATUS_SUCCESS) 1574 { 1575 if (iscsi_info_block_hdr.boot_flags & BOOT_INFO_FLAGS_UEFI_BOOT) 1576 { 1577 SET_FLAGS(pdev->params.link.feature_config_flags,ELINK_FEATURE_CONFIG_BOOT_FROM_SAN); 1578 } 1579 } 1580 1581 PHY_HW_LOCK(pdev); 1582 elink_status = elink_phy_init(&pdev->params.link,&pdev->vars.link); 1583 PHY_HW_UNLOCK(pdev); 1584 } 1585 else 1586 { 1587 elink_link_status_update(&pdev->params.link,&pdev->vars.link); 1588 } 1589 // Emulation FPGA or LOOPBACK non pmf in multi vnic mode link might be up now 1590 lm_link_report(pdev); 1591 return LM_STATUS_SUCCESS; 1592 } /* lm_init_phy */ 1593 1594 1595 #ifndef EDIAG 1596 /* 1597 * \brief query i2c information if exists and write it to 3rd party known place 1598 * 1599 * \param pdev 1600 * 1601 * \return lm_status_t 1602 * 1603 */ 1604 lm_status_t lm_link_i2c_update(struct _lm_device_t *pdev) 1605 { 1606 elink_status_t elink_status = ELINK_STATUS_ERROR; 1607 u8_t ext_phy_type = 0; 1608 lm_status_t lm_status = LM_STATUS_SUCCESS; 1609 const u64_t current_ts = mm_query_system_time(); // get current system time ms 1610 const u64_t current_ms = current_ts/10000; // get current system time ms 1611 const u64_t interval_ms = pdev->params.i2c_interval_sec*1000; 1612 const u64_t delta_ms = current_ms - (pdev->i2c_binary_info.last_query_ts/10000); 1613 const u8_t b_need_refresh = ( interval_ms > 0 ) && ( delta_ms > interval_ms ); 1614 u8_t sff8472_comp = 0; 1615 u8_t diag_type = 0; 1616 1617 DbgBreakIf(!IS_PMF(pdev)); 1618 1619 if( !b_need_refresh ) 1620 { 1621 // that means we need nothing here... 1622 return lm_status; 1623 } 1624 1625 // Check which PHY controls the SFP+ module 1626 for( ext_phy_type = ELINK_EXT_PHY1; ext_phy_type < pdev->params.link.num_phys; ext_phy_type++ ) 1627 { 1628 if(( ELINK_ETH_PHY_SFPP_10G_FIBER == pdev->params.link.phy[ext_phy_type].media_type )|| 1629 ( ELINK_ETH_PHY_SFP_1G_FIBER == pdev->params.link.phy[ext_phy_type].media_type )|| 1630 ( ELINK_ETH_PHY_DA_TWINAX == pdev->params.link.phy[ext_phy_type].media_type )) 1631 { 1632 pdev->i2c_binary_info.last_query_ts = current_ts; 1633 1634 // Capture A0 section + static part of A2 section only once if A2 is supportd 1635 if (( pdev->params.i2c_elink_status[I2C_SECTION_A0] != ELINK_STATUS_OK) || 1636 ((pdev->params.i2c_elink_status[I2C_SECTION_A2] != ELINK_STATUS_OK) && 1637 (pdev->params.i2c_elink_status[I2C_SECTION_A2] != ELINK_OP_NOT_SUPPORTED))) 1638 { 1639 PHY_HW_LOCK(pdev); 1640 elink_status = elink_read_sfp_module_eeprom( &pdev->params.link.phy[ext_phy_type], // ELINK_INT_PHY, ELINK_EXT_PHY1, ELINK_EXT_PHY2 1641 &pdev->params.link, 1642 ELINK_I2C_DEV_ADDR_A0, 1643 0, 1644 I2C_BINARY_SIZE, 1645 pdev->i2c_binary_info.ax_data[I2C_SECTION_A0] ) ; 1646 1647 pdev->params.i2c_elink_status[I2C_SECTION_A0] = elink_status; 1648 1649 if (pdev->params.i2c_elink_status[I2C_SECTION_A0] != ELINK_STATUS_OK) 1650 { 1651 PHY_HW_UNLOCK(pdev); 1652 1653 // Set same status to A2 section and quit as A0 is mandatory 1654 pdev->params.i2c_elink_status[I2C_SECTION_A2] = elink_status; 1655 break; // Quit the loop 1656 } 1657 1658 // Check if the module is compliant with SFF8472, meaning it supports A2 section. 1659 sff8472_comp = pdev->i2c_binary_info.ax_data[I2C_SECTION_A0][ELINK_SFP_EEPROM_SFF_8472_COMP_ADDR]; 1660 diag_type = pdev->i2c_binary_info.ax_data[I2C_SECTION_A0][ELINK_SFP_EEPROM_DIAG_TYPE_ADDR]; 1661 1662 if ( (!sff8472_comp) || 1663 ( diag_type & ELINK_SFP_EEPROM_DIAG_ADDR_CHANGE_REQ) ) 1664 { 1665 // Release the HW LOCK 1666 PHY_HW_UNLOCK(pdev); 1667 1668 // Set A2 section query status to NOT SUPPORTED and quit 1669 pdev->params.i2c_elink_status[I2C_SECTION_A2] = ELINK_OP_NOT_SUPPORTED; 1670 1671 // Exit loop 1672 break; 1673 } 1674 1675 elink_status = elink_read_sfp_module_eeprom( &pdev->params.link.phy[ext_phy_type], // ELINK_INT_PHY, ELINK_EXT_PHY1, ELINK_EXT_PHY2 1676 &pdev->params.link, 1677 ELINK_I2C_DEV_ADDR_A2, 1678 I2C_A2_STATIC_OFFSET, 1679 I2C_A2_STATIC_SIZE, 1680 &pdev->i2c_binary_info.ax_data[I2C_SECTION_A2][I2C_A2_STATIC_OFFSET] ) ; 1681 PHY_HW_UNLOCK(pdev); 1682 1683 pdev->params.i2c_elink_status[I2C_SECTION_A2] = elink_status; 1684 1685 if (pdev->params.i2c_elink_status[I2C_SECTION_A2] != ELINK_STATUS_OK) 1686 { 1687 break; // no use continue if we didn't get A2 data 1688 } 1689 } // !ELINK_STATUS_OK 1690 1691 /* Avoid reading A2 section if the module doesn't support SFF8472. */ 1692 if (pdev->params.i2c_elink_status[I2C_SECTION_A2] == ELINK_OP_NOT_SUPPORTED) 1693 { 1694 break; 1695 } 1696 1697 // Capture the dynamic part of A2 1698 PHY_HW_LOCK(pdev); 1699 1700 elink_status = elink_read_sfp_module_eeprom( &pdev->params.link.phy[ext_phy_type], // ELINK_INT_PHY, ELINK_EXT_PHY1, ELINK_EXT_PHY2 1701 &pdev->params.link, 1702 ELINK_I2C_DEV_ADDR_A2, 1703 I2C_A2_DYNAMIC_OFFSET, 1704 I2C_A2_DYNAMIC_SIZE, 1705 &pdev->i2c_binary_info.ax_data[I2C_SECTION_A2][I2C_A2_DYNAMIC_OFFSET] ); 1706 1707 PHY_HW_UNLOCK(pdev); 1708 1709 // Calculate and validate I2C section checksum 1710 if( ELINK_STATUS_OK == elink_status ) 1711 { 1712 elink_status = elink_validate_cc_dmi(pdev->i2c_binary_info.ax_data[I2C_SECTION_A2]); 1713 if( ELINK_STATUS_OK != elink_status ) 1714 { 1715 pdev->params.i2c_elink_status[I2C_SECTION_A2] = ELINK_STATUS_INVALID_IMAGE; 1716 } 1717 } 1718 // only one sfp+ module is expected on board so we exit the ext_phy_type loop 1719 break; 1720 } // if( ELINK_ETH_PHY_SFPP_10G_FIBER == ... 1721 } // for "ext_phy_type" 1722 1723 // it means that there is a need to write otherwise we even didn't enter the loop 1724 // so the registry write is redundent. 1725 if ( current_ts == pdev->i2c_binary_info.last_query_ts ) 1726 { 1727 lm_status = mm_i2c_update(pdev); 1728 } 1729 return lm_status; 1730 } /* lm_link_i2c_update */ 1731 #endif 1732 1733 /** 1734 * @Description 1735 * This function is called periodically, every time the link 1736 * timer expires, it's main purpose is to call elink under 1737 * appropriate locks to perform any periodic tasks 1738 * @assumptions: 1739 * called under UM_PHY_LOCK! 1740 * 1741 * @param pdev 1742 * 1743 * @return lm_status_t 1744 */ 1745 lm_status_t lm_link_on_timer(struct _lm_device_t *pdev) 1746 { 1747 if (CHIP_REV_IS_SLOW(pdev)) 1748 { 1749 return LM_STATUS_SUCCESS; 1750 } 1751 1752 if (IS_PMF(pdev)) 1753 { 1754 PHY_HW_LOCK(pdev); 1755 1756 elink_period_func(&pdev->params.link, &pdev->vars.link); 1757 1758 PHY_HW_UNLOCK(pdev); 1759 1760 #ifndef EDIAG 1761 lm_link_i2c_update(pdev); 1762 #endif 1763 } 1764 1765 return LM_STATUS_SUCCESS; 1766 } 1767 /* 1768 *Function Name:lm_get_external_phy_fw_version 1769 * 1770 *Parameters: 1771 * 1772 *Description: 1773 * Funciton should be called under PHY_LOCK 1774 *Returns: 1775 * 1776 */ 1777 lm_status_t 1778 lm_get_external_phy_fw_version( lm_device_t *pdev, 1779 u8_t * sz_version, 1780 u8_t len ) 1781 { 1782 u8_t elink_status = ELINK_STATUS_OK; 1783 1784 if ( CHK_NULL( sz_version ) || CHK_NULL( pdev ) ) 1785 { 1786 return LM_STATUS_INVALID_PARAMETER; 1787 } 1788 1789 // reset the returned value to zero 1790 *sz_version = '\0'; 1791 1792 elink_status = elink_get_ext_phy_fw_version(&pdev->params.link, (u8_t *)sz_version, len ); 1793 1794 if (elink_status == ELINK_STATUS_OK) 1795 { 1796 // Update internal hw_info structure for debugging purpose 1797 if( len <= sizeof(pdev->hw_info.sz_ext_phy_fw_ver) ) 1798 { 1799 mm_memcpy( pdev->hw_info.sz_ext_phy_fw_ver, 1800 sz_version, 1801 min( (u32_t)sizeof(pdev->hw_info.sz_ext_phy_fw_ver), (u32_t)len) ) ; 1802 } 1803 return LM_STATUS_SUCCESS ; 1804 } 1805 else 1806 { 1807 return LM_STATUS_FAILURE; 1808 } 1809 } 1810 1811 /* 1812 *Function Name:lm_update_external_phy_fw_prepare 1813 * 1814 *Parameters: 1815 * 1816 *Description: 1817 * 1818 *Returns: 1819 * 1820 */ 1821 lm_status_t 1822 lm_update_external_phy_fw_prepare( lm_device_t *pdev ) 1823 { 1824 u8_t elink_status = ELINK_STATUS_OK; 1825 lm_status_t lm_status = LM_STATUS_SUCCESS; 1826 1827 MM_ACQUIRE_PHY_LOCK(pdev); 1828 1829 PHY_HW_LOCK(pdev); 1830 1831 do 1832 { 1833 u32_t shmem_base[MAX_PATH_NUM], shmem_base2[MAX_PATH_NUM]; 1834 shmem_base[0] = pdev->hw_info.shmem_base; 1835 shmem_base2[0] = pdev->hw_info.shmem_base2; 1836 1837 if (!CHIP_IS_E1x(pdev)) 1838 { 1839 LM_SHMEM2_READ(pdev, OFFSETOF(shmem2_region_t,other_shmem_base_addr), &shmem_base[1]); 1840 LM_SHMEM2_READ(pdev, OFFSETOF(shmem2_region_t,other_shmem2_base_addr), &shmem_base2[1]); 1841 } 1842 1843 elink_common_init_phy(pdev, shmem_base, shmem_base2, CHIP_ID(pdev), 0); 1844 elink_pre_init_phy(pdev, shmem_base[0], shmem_base2[0], CHIP_ID(pdev), 0); 1845 1846 if( ELINK_STATUS_OK != elink_status ) 1847 { 1848 break; 1849 } 1850 1851 elink_status = elink_phy_init(&pdev->params.link,&pdev->vars.link); 1852 if( ELINK_STATUS_OK != elink_status ) 1853 { 1854 break; 1855 } 1856 1857 elink_status = elink_link_reset(&pdev->params.link,&pdev->vars.link,0); 1858 1859 } while(0); 1860 1861 PHY_HW_UNLOCK(pdev); 1862 1863 lm_link_report(pdev); 1864 1865 MM_RELEASE_PHY_LOCK(pdev); 1866 1867 if( ELINK_STATUS_OK != elink_status ) 1868 { 1869 goto _exit; 1870 } 1871 1872 switch( pdev->params.link.phy[ELINK_EXT_PHY1].type ) 1873 { 1874 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: 1875 { 1876 lm_gpio_write(pdev, MISC_REGISTERS_GPIO_0, MISC_REGISTERS_GPIO_HIGH, PORT_ID(pdev) ); 1877 } 1878 break; 1879 default: 1880 break; 1881 } 1882 1883 _exit: 1884 1885 ELINK_STATUS_TO_LM_STATUS( elink_status, lm_status ); 1886 1887 return lm_status; 1888 } 1889 1890 /* 1891 *Function Name:lm_update_external_phy_fw_reinit 1892 * 1893 *Parameters: 1894 * 1895 *Description: 1896 * 1897 *Returns: 1898 * 1899 */ 1900 lm_status_t 1901 lm_update_external_phy_fw_reinit( lm_device_t *pdev ) 1902 { 1903 lm_status_t lm_status = LM_STATUS_SUCCESS; 1904 u8_t elink_status = ELINK_STATUS_OK; 1905 1906 MM_ACQUIRE_PHY_LOCK(pdev); 1907 1908 lm_reset_link(pdev); 1909 1910 PHY_HW_LOCK(pdev); 1911 elink_status = elink_phy_init(&pdev->params.link,&pdev->vars.link); 1912 PHY_HW_UNLOCK(pdev); 1913 1914 DbgBreakIf(ELINK_STATUS_OK != elink_status); 1915 1916 // Emulation FPGA or LOOPBACK non pmf in multi vnic mode link might be up now 1917 lm_link_report(pdev); 1918 1919 ELINK_STATUS_TO_LM_STATUS( elink_status, lm_status ); 1920 1921 if( LM_STATUS_SUCCESS == lm_status ) 1922 { 1923 // in case success -reset version 1924 pdev->hw_info.sz_ext_phy_fw_ver[0] = '\0'; 1925 } 1926 1927 MM_RELEASE_PHY_LOCK(pdev); 1928 1929 return lm_status; 1930 } 1931 1932 /* 1933 *Function Name:lm_update_external_phy_fw_done 1934 * 1935 *Parameters: 1936 * 1937 *Description: 1938 * 1939 *Returns: 1940 * 1941 */ 1942 lm_status_t 1943 lm_update_external_phy_fw_done( lm_device_t *pdev ) 1944 { 1945 lm_status_t lm_status = LM_STATUS_SUCCESS; 1946 u8_t ext_phy_addr = 0; 1947 u8_t b_exit = FALSE; 1948 1949 MM_ACQUIRE_PHY_LOCK(pdev); 1950 switch( pdev->params.link.phy[ELINK_EXT_PHY1].type ) 1951 { 1952 case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: 1953 break; 1954 default: 1955 b_exit = TRUE; 1956 break; 1957 } 1958 if( b_exit ) 1959 { 1960 MM_RELEASE_PHY_LOCK(pdev); 1961 return lm_status ; 1962 } 1963 1964 ext_phy_addr = pdev->params.link.phy[ELINK_EXT_PHY1].addr; 1965 1966 /* DSP Remove Download Mode */ 1967 lm_gpio_write(pdev, MISC_REGISTERS_GPIO_0, MISC_REGISTERS_GPIO_LOW, PORT_ID(pdev) ); 1968 1969 PHY_HW_LOCK(pdev); 1970 elink_sfx7101_sp_sw_reset(pdev, &pdev->params.link.phy[ELINK_EXT_PHY1] ); 1971 /* wait 0.5 sec to allow it to run */ 1972 mm_wait( pdev, 500000); 1973 elink_ext_phy_hw_reset( pdev, PORT_ID(pdev) ); 1974 mm_wait(pdev, 500000); 1975 PHY_HW_UNLOCK(pdev); 1976 1977 MM_RELEASE_PHY_LOCK(pdev); 1978 1979 return lm_status; 1980 } 1981 1982 lm_status_t lm_check_phy_link_params(lm_device_t *pdev, lm_medium_t req_medium) 1983 { 1984 lm_medium_t speed = GET_MEDIUM_SPEED(req_medium); 1985 lm_status_t lm_status = LM_STATUS_SUCCESS; 1986 1987 if (IS_VFDEV(pdev)) 1988 { 1989 return LM_STATUS_SUCCESS; 1990 } 1991 1992 DbgMessage(pdev, WARN, "lm_check_phy_link_params: speed 0x%x\n",speed); 1993 // Get speed from registry not shared memory - if mcp is not detected... 1994 if(!pdev->hw_info.mcp_detected || ((speed != LM_MEDIUM_SPEED_HARDWARE_DEFAULT) && (!IS_MULTI_VNIC(pdev)))) 1995 { 1996 switch (speed) 1997 { 1998 case LM_MEDIUM_SPEED_AUTONEG: 1999 case LM_MEDIUM_SPEED_10MBPS: 2000 case LM_MEDIUM_SPEED_100MBPS: 2001 case LM_MEDIUM_SPEED_1000MBPS: 2002 case LM_MEDIUM_SPEED_2500MBPS: 2003 case LM_MEDIUM_SPEED_10GBPS: 2004 case LM_MEDIUM_SPEED_20GBPS: 2005 break; 2006 default: 2007 DbgMessage(pdev, FATAL, "lm_check_phy_link_params: abnormal speed parameter 0x%x.\n",speed); 2008 lm_status = LM_STATUS_INVALID_PARAMETER; 2009 } 2010 } 2011 return lm_status; 2012 } 2013 2014