1 /* 2 * Copyright 2014-2017 Cavium, Inc. 3 * The contents of this file are subject to the terms of the Common Development 4 * and Distribution License, v.1, (the "License"). 5 * 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the License at available 9 * at http://opensource.org/licenses/CDDL-1.0 10 * 11 * See the License for the specific language governing permissions and 12 * limitations under the License. 13 */ 14 15 /* 16 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 17 * Copyright (c) 2019, Joyent, Inc. 18 */ 19 20 #include "bnx.h" 21 #include "bnx_mm.h" 22 #include "bnxgld.h" 23 #include "bnxsnd.h" 24 #include "bnxtmr.h" 25 #include "bnxcfg.h" 26 #include "serdes.h" 27 28 #include "shmem.h" 29 30 #define MII_REG(_type, _field) (OFFSETOF(_type, _field)/2) 31 32 ddi_dma_attr_t bnx_std_dma_attrib = { 33 DMA_ATTR_V0, /* dma_attr_version */ 34 0, /* dma_attr_addr_lo */ 35 0xffffffffffffffff, /* dma_attr_addr_hi */ 36 0x0ffffff, /* dma_attr_count_max */ 37 BNX_DMA_ALIGNMENT, /* dma_attr_align */ 38 0xffffffff, /* dma_attr_burstsizes */ 39 1, /* dma_attr_minxfer */ 40 0x00ffffff, /* dma_attr_maxxfer */ 41 0xffffffff, /* dma_attr_seg */ 42 1, /* dma_attr_sgllen */ 43 1, /* dma_attr_granular */ 44 0, /* dma_attr_flags */ 45 }; 46 47 48 static ddi_dma_attr_t bnx_page_dma_attrib = { 49 DMA_ATTR_V0, /* dma_attr_version */ 50 0, /* dma_attr_addr_lo */ 51 0xffffffffffffffff, /* dma_attr_addr_hi */ 52 0x0ffffff, /* dma_attr_count_max */ 53 LM_PAGE_SIZE, /* dma_attr_align */ 54 0xffffffff, /* dma_attr_burstsizes */ 55 1, /* dma_attr_minxfer */ 56 0x00ffffff, /* dma_attr_maxxfer */ 57 0xffffffff, /* dma_attr_seg */ 58 1, /* dma_attr_sgllen */ 59 1, /* dma_attr_granular */ 60 0, /* dma_attr_flags */ 61 }; 62 63 64 65 /* 66 * Name: mm_wait 67 * 68 * Input: ptr to LM's device structure, 69 * delay value in micro-secs 70 * 71 * Return: None. 72 * 73 * Description: This funtion will be in a busy loop for specified number of 74 * micro-seconds and will return only after the time is elasped. 75 */ 76 void 77 mm_wait(lm_device_t *pdev, u32_t delay_us) 78 { 79 FLUSHPOSTEDWRITES(pdev); 80 drv_usecwait(delay_us * 10); 81 } /* mm_wait */ 82 83 84 85 /* 86 * Name: mm_read_pci 87 * 88 * Input: ptr to LM's device structure, 89 * register offset into config space, 90 * ptr to u32 where the register value is returned 91 * 92 * Return: LM_STATUS_SUCCESS, if successful 93 * LM_STATUS_FAILURE, if BAR register veiw is not mapped 94 * 95 * Description: This routine reads the PCI config space for the given device 96 * by calling pci_config_get32(). 97 */ 98 lm_status_t 99 mm_read_pci(lm_device_t *pdev, u32_t pci_reg, u32_t *reg_value) 100 { 101 um_device_t *udevp = (um_device_t *)pdev; 102 103 *reg_value = pci_config_get32(udevp->os_param.pci_cfg_handle, 104 (off_t)pci_reg); 105 106 return (LM_STATUS_SUCCESS); 107 } /* mm_read_pci */ 108 109 110 111 /* 112 * Name: mm_write_pci 113 * 114 * Input: ptr to LM's device structure, 115 * register offset into config space, 116 * u32 value to be written to PCI config register 117 * 118 * Return: LM_STATUS_SUCCESS, if successful 119 * LM_STATUS_FAILURE, if BAR register veiw is not mapped 120 * 121 * Description: This routine writes to PCI config register using DDI call, 122 * pci_config_put32(). 123 */ 124 lm_status_t 125 mm_write_pci(lm_device_t *pdev, u32_t pci_reg, u32_t reg_value) 126 { 127 um_device_t *udevp = (um_device_t *)pdev; 128 129 pci_config_put32(udevp->os_param.pci_cfg_handle, 130 (off_t)pci_reg, (uint32_t)reg_value); 131 132 return (LM_STATUS_SUCCESS); 133 } /* mm_write_pci */ 134 135 136 137 /* 138 * Name: mm_map_io_base 139 * 140 * Input: ptr to LM's device structure, 141 * physical address of the BAR reg 142 * (not used in this implementation), 143 * size of the register window 144 * 145 * Return: ptr to mapped virtual memory 146 * 147 * Description: This routine maps the BAR register window and returns the 148 * virtual address in the CPU address scape 149 */ 150 void * 151 mm_map_io_base(lm_device_t *pdev, lm_address_t base_addr, u32_t size) 152 { 153 um_device_t *udevp = (um_device_t *)pdev; 154 155 pdev->vars.dmaRegAccHandle = udevp->os_param.reg_acc_handle; 156 157 return ((void *)(udevp->os_param.regs_addr)); 158 } /* mm_map_io_base */ 159 160 161 162 /* 163 * Name: mm_desc_size 164 * 165 * Input: ptr to LM's device structure, 166 * descriptor type 167 * 168 * Return: size of the descriptor structure 169 * 170 * Description: This routine currently returns the size of packet descriptor 171 * as defined by the UM module (lm_pkt_t is embedded in this 172 * struct). This is used by LM's init routines trying to allocate 173 * memory for TX/RX descriptor queues. 174 */ 175 u32_t 176 mm_desc_size(lm_device_t *pdev, u32_t desc_type) 177 { 178 u32_t desc_size; 179 180 switch (desc_type) { 181 case DESC_TYPE_L2RX_PACKET: 182 desc_size = sizeof (um_rxpacket_t); 183 break; 184 185 default: 186 desc_size = 0; 187 break; 188 } 189 190 desc_size = ALIGN_VALUE_TO_WORD_BOUNDARY(desc_size); 191 192 return (desc_size); 193 } /* mm_desc_size */ 194 195 196 197 /* 198 * Name: mm_get_user_config 199 * 200 * Input: ptr to LM's device structure 201 * 202 * Return: SUCCESS 203 * 204 * Description: This rotuine maps user option to corresponding parameters in 205 * LM and UM device structures. 206 */ 207 lm_status_t 208 mm_get_user_config(lm_device_t *pdev) 209 { 210 u32_t keep_vlan_tag = 0; 211 u32_t offset; 212 u32_t val; 213 um_device_t *umdevice = (um_device_t *)pdev; 214 215 bnx_cfg_init(umdevice); 216 217 bnx_cfg_map_phy(umdevice); 218 219 /* 220 * If Management Firmware is running ensure that we don't 221 * keep the VLAN tag, this is for older firmware 222 */ 223 offset = pdev->hw_info.shmem_base; 224 offset += OFFSETOF(shmem_region_t, 225 dev_info.port_feature_config.config); 226 REG_RD_IND(pdev, offset, &val); 227 228 if (!(val & PORT_FEATURE_MFW_ENABLED)) 229 keep_vlan_tag = 1; 230 231 /* 232 * Newer versions of the firmware can handle VLAN tags 233 * check to see if this version of the firmware can handle them 234 */ 235 offset = pdev->hw_info.shmem_base; 236 offset += OFFSETOF(shmem_region_t, drv_fw_cap_mb.fw_cap_mb); 237 REG_RD_IND(pdev, offset, &val); 238 239 if ((val & FW_CAP_SIGNATURE) == FW_CAP_SIGNATURE) { 240 if ((val & (FW_CAP_MFW_CAN_KEEP_VLAN | 241 FW_CAP_BC_CAN_UPDATE_VLAN)) == 242 (FW_CAP_MFW_CAN_KEEP_VLAN | FW_CAP_BC_CAN_UPDATE_VLAN)) { 243 offset = pdev->hw_info.shmem_base; 244 offset += OFFSETOF(shmem_region_t, 245 drv_fw_cap_mb.drv_ack_cap_mb); 246 REG_WR_IND(pdev, offset, DRV_ACK_CAP_SIGNATURE | 247 FW_CAP_MFW_CAN_KEEP_VLAN | 248 FW_CAP_BC_CAN_UPDATE_VLAN); 249 250 keep_vlan_tag = 1; 251 } 252 } 253 254 pdev->params.keep_vlan_tag = keep_vlan_tag; 255 256 return (LM_STATUS_SUCCESS); 257 } /* mm_get_user_config */ 258 259 260 261 /* 262 * Name: mm_alloc_mem 263 * 264 * Input: ptr to LM's device structure, 265 * size of the memory block to be allocated 266 * 267 * Return: ptr to newly allocated memory region 268 * 269 * Description: This routine allocates memory region, updates the 270 * resource list to reflect this newly allocated memory. 271 */ 272 void * 273 mm_alloc_mem(lm_device_t *pdev, u32_t mem_size, void *resc_list) 274 { 275 void *memptr; 276 bnx_memreq_t *memreq; 277 um_device_t *umdevice; 278 279 (void) resc_list; 280 281 umdevice = (um_device_t *)pdev; 282 283 if (mem_size == 0) { 284 return (NULL); 285 } 286 287 if (umdevice->memcnt == BNX_MAX_MEMREQS) { 288 cmn_err(CE_WARN, "%s: Lower module memreq overflow.\n", 289 umdevice->dev_name); 290 return (NULL); 291 } 292 293 memptr = kmem_zalloc(mem_size, KM_NOSLEEP); 294 if (memptr == NULL) { 295 cmn_err(CE_WARN, "%s: Failed to allocate local memory.\n", 296 umdevice->dev_name); 297 return (NULL); 298 } 299 300 memreq = &umdevice->memreq[umdevice->memcnt]; 301 302 memreq->addr = memptr; 303 memreq->size = mem_size; 304 305 umdevice->memcnt++; 306 307 return (memptr); 308 } /* mm_alloc_mem */ 309 310 311 312 /* 313 * Name: mm_alloc_phys_mem 314 * 315 * Input: ptr to LM's device structure, 316 * size of the memory block to be allocated, 317 * pointer to store phys address, 318 * memory type 319 * 320 * Return: virtual memory ptr to newly allocated memory region 321 * 322 * Description: This routine allocates memory region, updates the 323 * resource list to reflect this newly allocated memory. 324 * This function returns physical address in addition the 325 * virtual address pointer. 326 */ 327 void * 328 mm_alloc_phys_mem(lm_device_t *pdev, u32_t mem_size, lm_address_t *phys_mem, 329 u8_t mem_type, void *resc_list) 330 { 331 int rc; 332 caddr_t pbuf; 333 um_device_t *udevp; 334 size_t real_len; 335 unsigned int count; 336 ddi_dma_attr_t *dma_attrib; 337 ddi_dma_handle_t *dma_handle; 338 ddi_acc_handle_t *acc_handle; 339 ddi_dma_cookie_t cookie; 340 341 (void) mem_type; 342 (void) resc_list; 343 344 udevp = (um_device_t *)pdev; 345 346 if (mem_size == 0) { 347 return (NULL); 348 } 349 350 if (udevp->os_param.dma_handles_used == BNX_MAX_PHYS_MEMREQS) { 351 cmn_err(CE_WARN, "%s: %s: Lower module phys memreq overflow.\n", 352 udevp->dev_name, __func__); 353 return (NULL); 354 } 355 356 if (!(mem_size & LM_PAGE_MASK)) { 357 /* Size is multiple of page size. */ 358 dma_attrib = &bnx_page_dma_attrib; 359 } else { 360 dma_attrib = &bnx_std_dma_attrib; 361 } 362 363 rc = udevp->os_param.dma_handles_used; 364 dma_handle = &udevp->os_param.dma_handle[rc]; 365 acc_handle = &udevp->os_param.dma_acc_handle[rc]; 366 367 rc = ddi_dma_alloc_handle(udevp->os_param.dip, dma_attrib, 368 DDI_DMA_DONTWAIT, (void *)0, dma_handle); 369 if (rc != DDI_SUCCESS) { 370 cmn_err(CE_WARN, "%s: %s: Failed to alloc phys dma handle.\n", 371 udevp->dev_name, __func__); 372 return (NULL); 373 } 374 375 rc = ddi_dma_mem_alloc(*dma_handle, (size_t)mem_size + 376 BNX_DMA_ALIGNMENT, &bnxAccessAttribBUF, DDI_DMA_CONSISTENT, 377 DDI_DMA_DONTWAIT, (void *)0, &pbuf, &real_len, acc_handle); 378 if (rc != DDI_SUCCESS) { 379 cmn_err(CE_WARN, "%s: %s: Failed to alloc phys memory.\n", 380 udevp->dev_name, __func__); 381 goto error1; 382 } 383 384 rc = ddi_dma_addr_bind_handle(*dma_handle, (struct as *)0, pbuf, 385 real_len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, 386 (void *)0, &cookie, &count); 387 if (rc != DDI_SUCCESS) { 388 cmn_err(CE_WARN, "%s: %s: Failed to bind DMA address.\n", 389 udevp->dev_name, __func__); 390 goto error2; 391 } 392 393 phys_mem->as_u64 = (u64_t)cookie.dmac_laddress; 394 395 /* 396 * Save the virtual memory address so 397 * we can get the dma_handle later. 398 */ 399 udevp->os_param.dma_virt[udevp->os_param.dma_handles_used] = pbuf; 400 401 udevp->os_param.dma_handles_used++; 402 403 /* Zero the memory... */ 404 bzero(pbuf, real_len); 405 406 /* ...and make sure the new contents are flushed back to main memory. */ 407 (void) ddi_dma_sync(*dma_handle, 0, real_len, DDI_DMA_SYNC_FORDEV); 408 409 return (pbuf); 410 411 error2: 412 ddi_dma_mem_free(acc_handle); 413 414 error1: 415 ddi_dma_free_handle(dma_handle); 416 417 return (NULL); 418 } /* mm_alloc_phys_mem */ 419 420 421 422 /* 423 * Name: mm_indicate_tx 424 * 425 * Input: ptr to LM's device structure, 426 * TX chain index, 427 * array of pointers to packet descriptors, 428 * number of packet descriptors in array 429 * 430 * Return: None 431 * 432 * Description: 433 * Lower module calls this API function to return transmit packet 434 * buffers to the system, and to allow the driver to reclaim 435 * transmit resources. This function is only called upon transmit 436 * abort and so is not in the fast path. 437 */ 438 void 439 mm_indicate_tx(lm_device_t *pdev, u32_t chain_idx, 440 struct _lm_packet_t *packet_arr[], u32_t num_packets) 441 { 442 um_txpacket_t **pkt_ptr; 443 um_txpacket_t *pkt; 444 s_list_t comp_list; 445 446 pkt_ptr = (um_txpacket_t **)packet_arr; 447 448 s_list_init(&comp_list, NULL, NULL, 0); 449 450 while (num_packets) { 451 pkt = *pkt_ptr; 452 453 s_list_push_tail(&comp_list, &(pkt->lm_pkt.link)); 454 455 pkt_ptr++; 456 num_packets--; 457 } 458 459 bnx_xmit_ring_reclaim((um_device_t *)pdev, chain_idx, &comp_list); 460 } /* mm_indicate_tx */ 461 462 463 464 /* 465 * Description: 466 * 467 * Return: 468 */ 469 static void 470 bnx_display_link_msg(um_device_t * const umdevice) 471 { 472 char *media; 473 char linkstr[128]; 474 475 if (umdevice->dev_var.isfiber) { 476 media = "Fiber"; 477 } else { 478 media = "Copper"; 479 } 480 481 if (umdevice->nddcfg.link_speed != 0) { 482 (void) strlcpy(linkstr, "up (", sizeof (linkstr)); 483 484 switch (umdevice->nddcfg.link_speed) { 485 case 2500: 486 (void) strlcat(linkstr, "2500Mbps, ", sizeof (linkstr)); 487 break; 488 case 1000: 489 (void) strlcat(linkstr, "1000Mbps, ", sizeof (linkstr)); 490 break; 491 case 100: 492 (void) strlcat(linkstr, "100Mbps, ", sizeof (linkstr)); 493 break; 494 case 10: 495 (void) strlcat(linkstr, "10Mbps, ", sizeof (linkstr)); 496 break; 497 default: 498 (void) strlcat(linkstr, "0Mbps, ", sizeof (linkstr)); 499 } 500 501 if (umdevice->nddcfg.link_duplex) { 502 (void) strlcat(linkstr, "Full Duplex", 503 sizeof (linkstr)); 504 } else { 505 (void) strlcat(linkstr, "Half Duplex", 506 sizeof (linkstr)); 507 } 508 509 if (umdevice->nddcfg.link_tx_pause || 510 umdevice->nddcfg.link_rx_pause) { 511 (void) strlcat(linkstr, ", ", sizeof (linkstr)); 512 if (umdevice->nddcfg.link_tx_pause) { 513 (void) strlcat(linkstr, "Tx", sizeof (linkstr)); 514 if (umdevice->nddcfg.link_rx_pause) { 515 (void) strlcat(linkstr, " & Rx", 516 sizeof (linkstr)); 517 } 518 } else { 519 (void) strlcat(linkstr, "Rx", sizeof (linkstr)); 520 } 521 (void) strlcat(linkstr, " Flow Control ON", 522 sizeof (linkstr)); 523 } 524 (void) strlcat(linkstr, ")", sizeof (linkstr)); 525 } else { 526 (void) snprintf(linkstr, sizeof (linkstr), "down"); 527 } 528 529 cmn_err(CE_NOTE, "!%s: %s link is %s", umdevice->dev_name, media, 530 linkstr); 531 } /* bnx_display_link_msg */ 532 533 534 535 /* 536 * Name: bnx_update_lp_cap 537 * 538 * Input: ptr to device structure 539 * 540 * Return: None 541 * 542 * Description: This function is updates link partners advertised 543 * capabilities. 544 */ 545 static void 546 bnx_update_lp_cap(um_device_t *const umdevice) 547 { 548 u32_t miireg; 549 lm_status_t lmstatus; 550 lm_device_t *lmdevice; 551 552 lmdevice = &(umdevice->lm_dev); 553 554 if (umdevice->dev_var.isfiber) { 555 lmstatus = lm_mread(lmdevice, lmdevice->params.phy_addr, 556 MII_REG(serdes_reg_t, mii_aneg_nxt_pg_rcv1), &miireg); 557 if (lmstatus == LM_STATUS_SUCCESS) { 558 if (miireg & MII_ANEG_NXT_PG_RCV1_2G5) { 559 umdevice->remote.param_2500fdx = B_TRUE; 560 } 561 } 562 563 lmstatus = lm_mread(lmdevice, lmdevice->params.phy_addr, 564 PHY_LINK_PARTNER_ABILITY_REG, &miireg); 565 if (lmstatus == LM_STATUS_SUCCESS) { 566 miireg &= MII_ABILITY_PAUSE; 567 if (miireg == MII_ADVERT_SYM_PAUSE) { 568 umdevice->remote.param_tx_pause = B_TRUE; 569 umdevice->remote.param_rx_pause = B_TRUE; 570 } else if (miireg == MII_ADVERT_ASYM_PAUSE) { 571 umdevice->remote.param_tx_pause = B_TRUE; 572 } 573 574 if (miireg & MII_ABILITY_FULL) { 575 umdevice->remote.param_1000fdx = B_TRUE; 576 } 577 578 if (miireg & MII_ABILITY_HALF) { 579 umdevice->remote.param_1000hdx = B_TRUE; 580 } 581 } 582 } else { 583 /* Copper */ 584 lmstatus = lm_mread(lmdevice, lmdevice->params.phy_addr, 585 PHY_1000BASET_STATUS_REG, &miireg); 586 if (lmstatus == LM_STATUS_SUCCESS) { 587 if (miireg & PHY_LINK_PARTNER_1000BASET_FULL) { 588 umdevice->remote.param_1000fdx = B_TRUE; 589 } 590 591 if (miireg & PHY_LINK_PARTNER_1000BASET_HALF) { 592 umdevice->remote.param_1000hdx = B_TRUE; 593 } 594 } 595 596 lmstatus = lm_mread(lmdevice, lmdevice->params.phy_addr, 597 PHY_LINK_PARTNER_ABILITY_REG, &miireg); 598 if (lmstatus == LM_STATUS_SUCCESS) { 599 if (miireg & PHY_LINK_PARTNER_PAUSE_CAPABLE) { 600 umdevice->remote.param_tx_pause = B_TRUE; 601 umdevice->remote.param_rx_pause = B_TRUE; 602 } else if (miireg & PHY_LINK_PARTNER_ASYM_PAUSE) { 603 umdevice->remote.param_tx_pause = B_TRUE; 604 } 605 606 if (miireg & PHY_LINK_PARTNER_100BASETX_FULL) { 607 umdevice->remote.param_100fdx = B_TRUE; 608 } 609 610 if (miireg & PHY_LINK_PARTNER_100BASETX_HALF) { 611 umdevice->remote.param_100hdx = B_TRUE; 612 } 613 614 if (miireg & PHY_LINK_PARTNER_10BASET_FULL) { 615 umdevice->remote.param_10fdx = B_TRUE; 616 } 617 618 if (miireg & PHY_LINK_PARTNER_10BASET_HALF) { 619 umdevice->remote.param_10hdx = B_TRUE; 620 } 621 } 622 } 623 624 #if 0 625 /* 626 * If we can gather _any_ information about our link partner, then 627 * because this information is exchanged through autonegotiation, we 628 * know that our link partner supports autonegotiation. 629 * 630 * FIXME -- Find a more authoritative way to update link_autoneg. I'm 631 * not sure it is legal, but it sounds possible to have autonegotiation 632 * enabled on the remote end with no capabilities advertised. 633 */ 634 if (umdevice->remote.param_2500fdx || 635 umdevice->remote.param_1000fdx || 636 umdevice->remote.param_1000hdx || 637 umdevice->remote.param_100fdx || 638 umdevice->remote.param_100hdx || 639 umdevice->remote.param_10fdx || 640 umdevice->remote.param_10hdx || 641 umdevice->remote.param_tx_pause || 642 umdevice->remote.param_rx_pause) { 643 umdevice->remote.param_autoneg = B_TRUE; 644 } 645 #else 646 lmstatus = lm_mread(lmdevice, lmdevice->params.phy_addr, 647 BCM540X_AUX_STATUS_REG, &miireg); 648 if (lmstatus == LM_STATUS_SUCCESS) { 649 if (miireg & BIT_12) { 650 umdevice->remote.link_autoneg = B_TRUE; 651 } 652 } 653 #endif 654 } /* bnx_update_lp_cap */ 655 656 657 658 /* 659 * Name: mm_indicate_link 660 * 661 * Input: ptr to LM's device structure, 662 * link status, 663 * lm_medium_t struct 664 * 665 * Return: None 666 * 667 * Description: Lower module calls this function when ever there is a network 668 * link status change. This routine updates the driver data 669 * structure as well calls gld_linkstate() to notify event to GLD. 670 */ 671 void 672 mm_indicate_link(lm_device_t *lmdevice, lm_status_t link, lm_medium_t medium) 673 { 674 int link_speed; 675 um_device_t *umdevice; 676 677 umdevice = (um_device_t *)lmdevice; 678 679 if (umdevice->link_updates_ok == B_FALSE) { 680 return; 681 } 682 683 /* ignore link status if it has not changed since the last indicate */ 684 if ((umdevice->dev_var.indLink == link) && 685 (umdevice->dev_var.indMedium == medium)) { 686 return; 687 } 688 689 umdevice->dev_var.indLink = link; 690 umdevice->dev_var.indMedium = medium; 691 692 switch (GET_MEDIUM_SPEED(medium)) { 693 case LM_MEDIUM_SPEED_10MBPS: 694 link_speed = 10; 695 break; 696 697 case LM_MEDIUM_SPEED_100MBPS: 698 link_speed = 100; 699 break; 700 701 case LM_MEDIUM_SPEED_1000MBPS: 702 link_speed = 1000; 703 break; 704 705 case LM_MEDIUM_SPEED_2500MBPS: 706 link_speed = 2500; 707 break; 708 709 default: 710 link_speed = 0; 711 break; 712 } 713 714 /* 715 * Validate the linespeed against known hardware capabilities. 716 * This is a common occurance. 717 */ 718 if (umdevice->dev_var.isfiber) { 719 if (link_speed != 2500 && link_speed != 1000) { 720 link_speed = 0; 721 } 722 } 723 724 if (link_speed == 0) { 725 link = LM_STATUS_LINK_DOWN; 726 } 727 728 /* 729 * If neither link-up or link-down flag is present, then there must 730 * have been multiple link events. Do the right thing. 731 */ 732 if (link != LM_STATUS_LINK_ACTIVE && link != LM_STATUS_LINK_DOWN) { 733 /* Fill in the missing information. */ 734 if (link_speed != 0) { 735 link = LM_STATUS_LINK_ACTIVE; 736 } else { 737 link = LM_STATUS_LINK_DOWN; 738 } 739 } 740 741 #if 0 742 if (((umdevice->nddcfg.link_speed == 0) && 743 (link != LM_STATUS_LINK_ACTIVE)) || 744 ((umdevice->nddcfg.link_speed != 0) && 745 (link != LM_STATUS_LINK_DOWN))) { 746 /* This is a false notification. */ 747 return; 748 } 749 #endif 750 751 if (umdevice->timer_link_check_interval) { 752 if (link == LM_STATUS_LINK_ACTIVE) { 753 if (lmdevice->vars.serdes_fallback_status) { 754 /* 755 * Start the timer to poll the serdes for 756 * reception of configs from the link partner. 757 * When this happens the remote has autoneg 758 * enabled and we'll restart our autoneg. 759 */ 760 bnx_link_timer_restart(umdevice); 761 } 762 } else { 763 if (umdevice->timer_link_check_counter) { 764 bnx_link_timer_restart(umdevice); 765 } 766 } 767 } 768 769 if (link == LM_STATUS_LINK_DOWN) { 770 umdevice->nddcfg.link_speed = 0; 771 umdevice->nddcfg.link_duplex = B_FALSE; 772 umdevice->nddcfg.link_tx_pause = B_FALSE; 773 umdevice->nddcfg.link_rx_pause = B_FALSE; 774 775 umdevice->remote.link_autoneg = B_FALSE; 776 umdevice->remote.param_2500fdx = B_FALSE; 777 umdevice->remote.param_1000fdx = B_FALSE; 778 umdevice->remote.param_1000hdx = B_FALSE; 779 umdevice->remote.param_100fdx = B_FALSE; 780 umdevice->remote.param_100hdx = B_FALSE; 781 umdevice->remote.param_10fdx = B_FALSE; 782 umdevice->remote.param_10hdx = B_FALSE; 783 umdevice->remote.param_tx_pause = B_FALSE; 784 umdevice->remote.param_rx_pause = B_FALSE; 785 786 bnx_display_link_msg(umdevice); 787 788 bnx_gld_link(umdevice, LINK_STATE_DOWN); 789 } else if (link == LM_STATUS_LINK_ACTIVE) { 790 umdevice->nddcfg.link_speed = link_speed; 791 792 if (GET_MEDIUM_DUPLEX(medium)) { 793 /* half duplex */ 794 umdevice->nddcfg.link_duplex = B_FALSE; 795 } else { 796 /* full duplex */ 797 umdevice->nddcfg.link_duplex = B_TRUE; 798 } 799 800 if (lmdevice->vars.flow_control & 801 LM_FLOW_CONTROL_TRANSMIT_PAUSE) { 802 umdevice->nddcfg.link_tx_pause = B_TRUE; 803 } else { 804 umdevice->nddcfg.link_tx_pause = B_FALSE; 805 } 806 807 if (lmdevice->vars.flow_control & 808 LM_FLOW_CONTROL_RECEIVE_PAUSE) { 809 umdevice->nddcfg.link_rx_pause = B_TRUE; 810 } else { 811 umdevice->nddcfg.link_rx_pause = B_FALSE; 812 } 813 814 if (umdevice->curcfg.lnkcfg.link_autoneg == B_TRUE) { 815 bnx_update_lp_cap(umdevice); 816 } 817 818 bnx_display_link_msg(umdevice); 819 820 bnx_gld_link(umdevice, LINK_STATE_UP); 821 } 822 } /* mm_indicate_link */ 823 824 825 826 /* 827 * Description: 828 * 829 * Return: 830 */ 831 void 832 mm_acquire_ind_reg_lock(struct _lm_device_t *pdev) 833 { 834 um_device_t *umdevice; 835 836 umdevice = (um_device_t *)pdev; 837 838 mutex_enter(&umdevice->os_param.ind_mutex); 839 } /* mm_acquire_ind_reg_lock */ 840 841 842 843 /* 844 * Description: 845 * 846 * Return: 847 */ 848 void 849 mm_release_ind_reg_lock(struct _lm_device_t *pdev) 850 { 851 um_device_t *umdevice; 852 853 umdevice = (um_device_t *)pdev; 854 855 mutex_exit(&umdevice->os_param.ind_mutex); 856 } /* mm_release_ind_reg_lock */ 857