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) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 17 * Copyright (c) 2019, Joyent, Inc. 18 * Copyright 2023 Oxide Computer Company 19 */ 20 21 #include "bnxgld.h" 22 #include "bnxhwi.h" 23 #include "bnxsnd.h" 24 #include "bnxrcv.h" 25 #include "bnxcfg.h" 26 27 #include <sys/mac_provider.h> 28 #include <sys/mac_ether.h> 29 #include <sys/dlpi.h> 30 #include <sys/policy.h> 31 32 /* 33 * Name: bnx_m_start 34 * 35 * Input: ptr to driver device structure. 36 * 37 * Return: DDI_SUCCESS or DDI_FAILURE 38 * 39 * Description: 40 * This routine is called by GLD to enable device for 41 * packet reception and enable interrupts. 42 */ 43 static int 44 bnx_m_start(void *arg) 45 { 46 int rc; 47 um_device_t *umdevice; 48 49 umdevice = (um_device_t *)arg; 50 51 mutex_enter(&umdevice->os_param.gld_mutex); 52 53 if (umdevice->dev_start == B_TRUE) { 54 /* We're already started. Success! */ 55 rc = 0; 56 goto done; 57 } 58 59 /* Always report the initial link state as unknown. */ 60 bnx_gld_link(umdevice, LINK_STATE_UNKNOWN); 61 62 umdevice->link_updates_ok = B_TRUE; 63 64 if (bnx_hdwr_acquire(umdevice)) { 65 rc = EIO; 66 goto done; 67 } 68 69 umdevice->dev_start = B_TRUE; 70 71 rc = 0; 72 73 done: 74 mutex_exit(&umdevice->os_param.gld_mutex); 75 76 return (rc); 77 } 78 79 /* 80 * Name: bnx_m_stop 81 * 82 * Input: ptr to driver device structure. 83 * 84 * Return: DDI_SUCCESS or DDI_FAILURE 85 * 86 * Description: 87 * This routine stops packet reception by clearing RX MASK 88 * register. Also interrupts are disabled for this device. 89 */ 90 static void 91 bnx_m_stop(void *arg) 92 { 93 um_device_t *umdevice; 94 95 umdevice = (um_device_t *)arg; 96 97 mutex_enter(&umdevice->os_param.gld_mutex); 98 99 if (umdevice->dev_start == B_TRUE) { 100 umdevice->dev_start = B_FALSE; 101 umdevice->link_updates_ok = B_FALSE; 102 103 bnx_hdwr_release(umdevice); 104 105 /* Report the link state back to unknown. */ 106 bnx_gld_link(umdevice, LINK_STATE_UNKNOWN); 107 108 umdevice->dev_var.indLink = 0; 109 umdevice->dev_var.indMedium = 0; 110 } 111 112 mutex_exit(&umdevice->os_param.gld_mutex); 113 } 114 115 116 117 /* 118 * Name: bnx_m_unicast 119 * 120 * Input: ptr to driver device structure, 121 * pointer to buffer containing MAC address. 122 * 123 * Return: DDI_SUCCESS or DDI_FAILURE 124 * 125 * Description: 126 */ 127 static int 128 bnx_m_unicast(void *arg, const uint8_t *macaddr) 129 { 130 int rc; 131 um_device_t *umdevice; 132 lm_device_t *lmdevice; 133 134 umdevice = (um_device_t *)arg; 135 lmdevice = &(umdevice->lm_dev); 136 137 mutex_enter(&umdevice->os_param.gld_mutex); 138 139 /* Validate MAC address */ 140 if (IS_ETH_MULTICAST(macaddr)) { 141 cmn_err(CE_WARN, "%s: Attempt to program a multicast / " 142 "broadcast address as a MAC address.", umdevice->dev_name); 143 rc = EINVAL; 144 goto done; 145 } 146 147 if (umdevice->dev_start == B_TRUE) { 148 if (lm_set_mac_addr(lmdevice, 0, 149 &(lmdevice->params.mac_addr[0])) != LM_STATUS_SUCCESS) { 150 cmn_err(CE_WARN, "%s: failed to program MAC address.", 151 umdevice->dev_name); 152 rc = EIO; 153 goto done; 154 } 155 } 156 157 bcopy(macaddr, &(lmdevice->params.mac_addr[0]), ETHERADDRL); 158 159 rc = 0; 160 161 done: 162 mutex_exit(&umdevice->os_param.gld_mutex); 163 164 return (rc); 165 } 166 167 static int 168 bnx_mc_add(um_device_t *umdevice, const uint8_t *const mc_addr) 169 { 170 int rc; 171 int index; 172 lm_status_t lmstatus; 173 lm_device_t *lmdevice; 174 175 lmdevice = &(umdevice->lm_dev); 176 177 index = bnx_find_mchash_collision(&(lmdevice->mc_table), mc_addr); 178 if (index == -1) { 179 lmstatus = lm_add_mc(lmdevice, (u8_t *)mc_addr); 180 if (lmstatus == LM_STATUS_SUCCESS) { 181 umdevice->dev_var.rx_filter_mask |= 182 LM_RX_MASK_ACCEPT_MULTICAST; 183 rc = 0; 184 } else { 185 rc = ENOMEM; 186 } 187 } else { 188 lmdevice->mc_table.addr_arr[index].ref_cnt++; 189 rc = 0; 190 } 191 192 return (rc); 193 } 194 195 static int 196 bnx_mc_del(um_device_t *umdevice, const uint8_t *const mc_addr) 197 { 198 int rc; 199 int index; 200 lm_status_t lmstatus; 201 lm_device_t *lmdevice; 202 203 lmdevice = &(umdevice->lm_dev); 204 205 index = bnx_find_mchash_collision(&(lmdevice->mc_table), mc_addr); 206 if (index == -1) { 207 rc = ENXIO; 208 } else { 209 lmstatus = lm_del_mc(lmdevice, 210 lmdevice->mc_table.addr_arr[index].mc_addr); 211 if (lmstatus == LM_STATUS_SUCCESS) { 212 if (lmdevice->mc_table.entry_cnt == 0) { 213 umdevice->dev_var.rx_filter_mask &= 214 ~LM_RX_MASK_ACCEPT_MULTICAST; 215 } 216 217 rc = 0; 218 } else { 219 rc = ENXIO; 220 } 221 } 222 223 return (rc); 224 } 225 226 227 228 /* 229 * Name: bnx_m_multicast 230 * 231 * Input: ptr to driver device structure, 232 * boolean describing whether to enable or disable this address, 233 * pointer to buffer containing multicast address. 234 * 235 * Return: DDI_SUCCESS or DDI_FAILURE 236 * 237 * Description: 238 * This function is used to enable or disable multicast packet 239 * reception for particular multicast addresses. 240 */ 241 static int 242 bnx_m_multicast(void * arg, boolean_t multiflag, const uint8_t *multicastaddr) 243 { 244 um_device_t *umdevice; 245 int rc; 246 247 umdevice = (um_device_t *)arg; 248 249 mutex_enter(&umdevice->os_param.gld_mutex); 250 251 if (umdevice->dev_start != B_TRUE) { 252 rc = EAGAIN; 253 goto done; 254 } 255 256 switch (multiflag) { 257 case B_TRUE: 258 rc = bnx_mc_add(umdevice, multicastaddr); 259 break; 260 261 case B_FALSE: 262 rc = bnx_mc_del(umdevice, multicastaddr); 263 break; 264 265 default: 266 rc = EINVAL; 267 break; 268 } 269 270 done: 271 mutex_exit(&umdevice->os_param.gld_mutex); 272 273 return (rc); 274 } 275 276 277 278 /* 279 * Name: bnx_m_promiscuous 280 * 281 * Input: ptr to driver device structure, 282 * boolean describing whether to enable or disable promiscuous mode. 283 * 284 * Return: DDI_SUCCESS or DDI_FAILURE 285 * 286 * Description: 287 * This function enables promiscuous mode for this device. 288 * 'flags' argument determines the type of mode being set, 289 * "PROMISC_PHY" enables reception of all packet types including 290 * bad/error packets. "PROMISC_MULTI" mode will enable all 291 * multicast packets, unicasts and broadcast packets to be 292 * received. "PROMISC_NONE" will enable only broadcast and 293 * unicast packets. 294 */ 295 static int 296 bnx_m_promiscuous(void *arg, boolean_t promiscflag) 297 { 298 int rc; 299 um_device_t *umdevice; 300 301 umdevice = (um_device_t *)arg; 302 303 mutex_enter(&umdevice->os_param.gld_mutex); 304 305 if (umdevice->dev_start != B_TRUE) { 306 rc = EAGAIN; 307 goto done; 308 } 309 310 switch (promiscflag) { 311 case B_TRUE: 312 umdevice->dev_var.rx_filter_mask |= 313 LM_RX_MASK_PROMISCUOUS_MODE; 314 break; 315 316 case B_FALSE: 317 umdevice->dev_var.rx_filter_mask &= 318 ~LM_RX_MASK_PROMISCUOUS_MODE; 319 break; 320 321 default: 322 rc = EINVAL; 323 goto done; 324 } 325 326 (void) lm_set_rx_mask(&(umdevice->lm_dev), RX_FILTER_USER_IDX0, 327 umdevice->dev_var.rx_filter_mask); 328 329 rc = 0; 330 331 done: 332 mutex_exit(&umdevice->os_param.gld_mutex); 333 334 return (rc); 335 } 336 337 338 static mblk_t * 339 bnx_m_tx(void *arg, mblk_t *mp) 340 { 341 int rc; 342 mblk_t *nmp; 343 um_device_t *umdevice; 344 345 umdevice = (um_device_t *)arg; 346 347 rw_enter(&umdevice->os_param.gld_snd_mutex, RW_READER); 348 349 if (umdevice->dev_start != B_TRUE || 350 umdevice->nddcfg.link_speed == 0) { 351 freemsgchain(mp); 352 mp = NULL; 353 goto done; 354 } 355 356 nmp = NULL; 357 358 while (mp) { 359 /* Save the next pointer, in case we do double copy. */ 360 nmp = mp->b_next; 361 mp->b_next = NULL; 362 363 rc = bnx_xmit_ring_xmit_mblk(umdevice, 0, mp); 364 365 if (rc == BNX_SEND_GOODXMIT) { 366 mp = nmp; 367 continue; 368 } 369 370 if (rc == BNX_SEND_DEFERPKT) 371 mp = nmp; 372 else 373 mp->b_next = nmp; 374 375 break; 376 } 377 378 done: 379 rw_exit(&umdevice->os_param.gld_snd_mutex); 380 381 return (mp); 382 } 383 384 385 static u64_t 386 shift_left32(u32_t val) 387 { 388 lm_u64_t tmp; 389 390 /* FIXME -- Get rid of shift_left32() */ 391 392 tmp.as_u32.low = 0; 393 tmp.as_u32.high = val; 394 395 return (tmp.as_u64); 396 } 397 398 static mac_ether_media_t 399 bnx_um_to_media(um_device_t *um) 400 { 401 if (um->nddcfg.link_speed == 0) { 402 return (ETHER_MEDIA_NONE); 403 } 404 405 /* 406 * bnx only supports 2.5G and 1G fiber. It does not support 100BASE-FX. 407 * Similarly, it is too old to support 2500BASE-T and the NetExtreme II 408 * programmer's guide makes it clear it only ever supported 100BASE-TX 409 * and never -T2 or -T4. 410 */ 411 if (um->dev_var.isfiber) { 412 switch (um->nddcfg.link_speed) { 413 case 2500: 414 return (ETHER_MEDIA_2500BASE_X); 415 case 1000: 416 return (ETHER_MEDIA_1000BASE_X); 417 default: 418 break; 419 } 420 } else { 421 switch (um->nddcfg.link_speed) { 422 case 1000: 423 return (ETHER_MEDIA_1000BASE_T); 424 case 100: 425 return (ETHER_MEDIA_100BASE_TX); 426 case 10: 427 return (ETHER_MEDIA_10BASE_T); 428 default: 429 break; 430 } 431 } 432 433 return (ETHER_MEDIA_UNKNOWN); 434 } 435 436 /* 437 * Name: bnx_m_stats 438 * 439 * Input: ptr to mac info structure, ptr to gld_stats struct 440 * 441 * Return: DDI_SUCCESS or DDI_FAILURE 442 * 443 * Description: bnx_m_stats() populates gld_stats structure elements 444 * from latest data from statistic block. 445 */ 446 static int 447 bnx_m_stats(void * arg, uint_t stat, uint64_t *val) 448 { 449 int rc; 450 um_device_t *umdevice; 451 lm_device_t *lmdevice; 452 const bnx_lnk_cfg_t *linkconf; 453 454 umdevice = (um_device_t *)arg; 455 456 if (umdevice == NULL || val == NULL) { 457 return (EINVAL); 458 } 459 460 lmdevice = &(umdevice->lm_dev); 461 462 /* FIXME -- Fix STATS collections */ 463 464 if (umdevice->dev_var.isfiber) { 465 linkconf = &bnx_serdes_config; 466 } else { 467 linkconf = &bnx_copper_config; 468 } 469 470 mutex_enter(&umdevice->os_param.gld_mutex); 471 472 if (umdevice->dev_start != B_TRUE) { 473 rc = EAGAIN; 474 goto done; 475 } 476 477 *val = 0; 478 switch (stat) { 479 case MAC_STAT_IFSPEED: 480 *val = umdevice->nddcfg.link_speed * 1000000ull; 481 break; 482 case MAC_STAT_MULTIRCV: 483 *val += shift_left32( 484 lmdevice->vars.stats_virt->stat_IfHCInMulticastPkts_hi); 485 *val += 486 lmdevice->vars.stats_virt->stat_IfHCInMulticastPkts_lo; 487 break; 488 case MAC_STAT_BRDCSTRCV: 489 *val += shift_left32( 490 lmdevice->vars.stats_virt->stat_IfHCInBroadcastPkts_hi); 491 *val += 492 lmdevice->vars.stats_virt->stat_IfHCInBroadcastPkts_lo; 493 break; 494 case MAC_STAT_MULTIXMT: 495 *val += shift_left32( 496 lmdevice->vars.stats_virt->stat_IfHCOutMulticastPkts_hi); 497 *val += 498 lmdevice->vars.stats_virt->stat_IfHCOutMulticastPkts_lo; 499 break; 500 case MAC_STAT_BRDCSTXMT: 501 *val += shift_left32( 502 lmdevice->vars.stats_virt->stat_IfHCOutBroadcastPkts_hi); 503 *val += 504 lmdevice->vars.stats_virt->stat_IfHCOutBroadcastPkts_lo; 505 break; 506 case MAC_STAT_NORCVBUF: 507 *val = lmdevice->vars.stats_virt->stat_IfInMBUFDiscards; 508 break; 509 case ETHER_STAT_MACRCV_ERRORS: 510 case MAC_STAT_IERRORS: 511 *val = lmdevice->vars.stats_virt->stat_Dot3StatsFCSErrors + 512 lmdevice->vars.stats_virt->stat_Dot3StatsAlignmentErrors + 513 lmdevice->vars.stats_virt->stat_EtherStatsUndersizePkts + 514 lmdevice->vars.stats_virt->stat_EtherStatsOverrsizePkts; 515 break; 516 case MAC_STAT_OERRORS: 517 *val = lmdevice->vars.stats_virt-> 518 stat_emac_tx_stat_dot3statsinternalmactransmiterrors; 519 break; 520 case MAC_STAT_COLLISIONS: 521 *val = lmdevice->vars.stats_virt->stat_EtherStatsCollisions; 522 break; 523 case MAC_STAT_RBYTES: 524 *val += shift_left32( 525 lmdevice->vars.stats_virt->stat_IfHCInOctets_hi); 526 *val += 527 lmdevice->vars.stats_virt->stat_IfHCInOctets_lo; 528 break; 529 case MAC_STAT_IPACKETS: 530 *val += shift_left32(lmdevice->vars.stats_virt-> 531 stat_IfHCInUcastPkts_hi); 532 *val += lmdevice->vars.stats_virt->stat_IfHCInUcastPkts_lo; 533 534 *val += shift_left32(lmdevice->vars.stats_virt-> 535 stat_IfHCInMulticastPkts_hi); 536 *val += lmdevice->vars.stats_virt->stat_IfHCInMulticastPkts_lo; 537 538 *val += shift_left32(lmdevice->vars.stats_virt-> 539 stat_IfHCInBroadcastPkts_hi); 540 *val += lmdevice->vars.stats_virt->stat_IfHCInBroadcastPkts_lo; 541 break; 542 case MAC_STAT_OBYTES: 543 *val += shift_left32( 544 lmdevice->vars.stats_virt->stat_IfHCOutOctets_hi); 545 *val += 546 lmdevice->vars.stats_virt->stat_IfHCOutOctets_lo; 547 break; 548 case MAC_STAT_OPACKETS: 549 *val += shift_left32(lmdevice->vars.stats_virt-> 550 stat_IfHCOutUcastPkts_hi); 551 *val += lmdevice->vars.stats_virt->stat_IfHCOutUcastPkts_lo; 552 553 *val += shift_left32(lmdevice->vars.stats_virt-> 554 stat_IfHCOutMulticastPkts_hi); 555 *val += lmdevice->vars.stats_virt->stat_IfHCOutMulticastPkts_lo; 556 557 *val += shift_left32(lmdevice->vars.stats_virt-> 558 stat_IfHCOutBroadcastPkts_hi); 559 *val += lmdevice->vars.stats_virt->stat_IfHCOutBroadcastPkts_lo; 560 break; 561 case ETHER_STAT_ALIGN_ERRORS: 562 *val = lmdevice->vars.stats_virt->stat_Dot3StatsAlignmentErrors; 563 break; 564 case ETHER_STAT_FCS_ERRORS: 565 *val = lmdevice->vars.stats_virt->stat_Dot3StatsFCSErrors; 566 break; 567 case ETHER_STAT_FIRST_COLLISIONS: 568 *val = lmdevice->vars.stats_virt-> 569 stat_Dot3StatsSingleCollisionFrames; 570 break; 571 case ETHER_STAT_MULTI_COLLISIONS: 572 *val = lmdevice->vars.stats_virt-> 573 stat_Dot3StatsMultipleCollisionFrames; 574 break; 575 case ETHER_STAT_DEFER_XMTS: 576 *val = lmdevice->vars.stats_virt-> 577 stat_Dot3StatsDeferredTransmissions; 578 break; 579 case ETHER_STAT_TX_LATE_COLLISIONS: 580 *val = lmdevice->vars.stats_virt-> 581 stat_Dot3StatsLateCollisions; 582 break; 583 case ETHER_STAT_EX_COLLISIONS: 584 *val = lmdevice->vars.stats_virt-> 585 stat_Dot3StatsExcessiveCollisions; 586 break; 587 case ETHER_STAT_MACXMT_ERRORS: 588 *val = lmdevice->vars.stats_virt-> 589 stat_emac_tx_stat_dot3statsinternalmactransmiterrors; 590 break; 591 case ETHER_STAT_CARRIER_ERRORS: 592 *val = lmdevice->vars.stats_virt-> 593 stat_Dot3StatsCarrierSenseErrors; 594 break; 595 case ETHER_STAT_TOOLONG_ERRORS: 596 *val = lmdevice->vars.stats_virt-> 597 stat_EtherStatsOverrsizePkts; 598 break; 599 #if (MAC_VERSION > 1) 600 case ETHER_STAT_TOOSHORT_ERRORS: 601 *val = lmdevice->vars.stats_virt-> 602 stat_EtherStatsUndersizePkts; 603 break; 604 #endif 605 case ETHER_STAT_XCVR_ADDR: 606 *val = lmdevice->params.phy_addr; 607 break; 608 case ETHER_STAT_XCVR_ID: 609 *val = lmdevice->hw_info.phy_id; 610 break; 611 case ETHER_STAT_XCVR_INUSE: 612 *val = (uint64_t)bnx_um_to_media(umdevice); 613 break; 614 case ETHER_STAT_CAP_1000FDX: 615 *val = 1; 616 break; 617 case ETHER_STAT_CAP_1000HDX: 618 *val = linkconf->param_1000hdx; 619 break; 620 case ETHER_STAT_CAP_100FDX: 621 *val = linkconf->param_100fdx; 622 break; 623 case ETHER_STAT_CAP_100HDX: 624 *val = linkconf->param_100hdx; 625 break; 626 case ETHER_STAT_CAP_10FDX: 627 *val = linkconf->param_10fdx; 628 break; 629 case ETHER_STAT_CAP_10HDX: 630 *val = linkconf->param_10hdx; 631 break; 632 case ETHER_STAT_CAP_ASMPAUSE: 633 *val = 1; 634 break; 635 case ETHER_STAT_CAP_PAUSE: 636 *val = 1; 637 break; 638 case ETHER_STAT_CAP_AUTONEG: 639 *val = 1; 640 break; 641 #if (MAC_VERSION > 1) 642 case ETHER_STAT_CAP_REMFAULT: 643 *val = 1; 644 break; 645 #endif 646 case ETHER_STAT_ADV_CAP_1000FDX: 647 *val = umdevice->curcfg.lnkcfg.param_1000fdx; 648 break; 649 case ETHER_STAT_ADV_CAP_1000HDX: 650 *val = umdevice->curcfg.lnkcfg.param_1000hdx; 651 break; 652 case ETHER_STAT_ADV_CAP_100FDX: 653 *val = umdevice->curcfg.lnkcfg.param_100fdx; 654 break; 655 case ETHER_STAT_ADV_CAP_100HDX: 656 *val = umdevice->curcfg.lnkcfg.param_100hdx; 657 break; 658 case ETHER_STAT_ADV_CAP_10FDX: 659 *val = umdevice->curcfg.lnkcfg.param_10fdx; 660 break; 661 case ETHER_STAT_ADV_CAP_10HDX: 662 *val = umdevice->curcfg.lnkcfg.param_10hdx; 663 break; 664 case ETHER_STAT_ADV_CAP_ASMPAUSE: 665 *val = 1; 666 break; 667 case ETHER_STAT_ADV_CAP_PAUSE: 668 *val = 1; 669 break; 670 case ETHER_STAT_ADV_CAP_AUTONEG: 671 *val = umdevice->curcfg.lnkcfg.link_autoneg; 672 break; 673 #if (MAC_VERSION > 1) 674 case ETHER_STAT_ADV_REMFAULT: 675 *val = 1; 676 break; 677 #endif 678 case ETHER_STAT_LP_CAP_1000FDX: 679 *val = umdevice->remote.param_1000fdx; 680 break; 681 case ETHER_STAT_LP_CAP_1000HDX: 682 *val = umdevice->remote.param_1000hdx; 683 break; 684 case ETHER_STAT_LP_CAP_100FDX: 685 *val = umdevice->remote.param_100fdx; 686 break; 687 case ETHER_STAT_LP_CAP_100HDX: 688 *val = umdevice->remote.param_100hdx; 689 break; 690 case ETHER_STAT_LP_CAP_10FDX: 691 *val = umdevice->remote.param_10fdx; 692 break; 693 case ETHER_STAT_LP_CAP_10HDX: 694 *val = umdevice->remote.param_10hdx; 695 break; 696 case ETHER_STAT_LP_CAP_ASMPAUSE: 697 /* FIXME -- Implement LP_ASYM_PAUSE stat */ 698 break; 699 case ETHER_STAT_LP_CAP_PAUSE: 700 /* FIXME -- Implement LP_PAUSE stat */ 701 break; 702 case ETHER_STAT_LP_CAP_AUTONEG: 703 *val = umdevice->remote.link_autoneg; 704 break; 705 #if (MAC_VERSION > 1) 706 case ETHER_STAT_LP_REMFAULT: 707 /* FIXME -- Implement LP_REMFAULT stat */ 708 break; 709 #endif 710 case ETHER_STAT_LINK_ASMPAUSE: 711 /* FIXME -- Implement ASMPAUSE stat */ 712 break; 713 case ETHER_STAT_LINK_PAUSE: 714 /* FIXME -- Implement PAUSE stat */ 715 break; 716 case ETHER_STAT_LINK_AUTONEG: 717 *val = umdevice->curcfg.lnkcfg.link_autoneg; 718 break; 719 case ETHER_STAT_LINK_DUPLEX: 720 *val = umdevice->nddcfg.link_duplex == B_TRUE ? 721 LINK_DUPLEX_FULL: LINK_DUPLEX_HALF; 722 break; 723 default: 724 rc = ENOTSUP; 725 } 726 727 rc = 0; 728 729 done: 730 mutex_exit(&umdevice->os_param.gld_mutex); 731 732 return (rc); 733 } 734 735 static boolean_t 736 bnx_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 737 { 738 um_device_t *umdevice; 739 740 umdevice = (um_device_t *)arg; 741 742 switch (cap) { 743 case MAC_CAPAB_HCKSUM: { 744 uint32_t *txflags = cap_data; 745 746 *txflags = 0; 747 748 if (umdevice->dev_var.enabled_oflds & 749 (LM_OFFLOAD_TX_IP_CKSUM | LM_OFFLOAD_RX_IP_CKSUM)) { 750 *txflags |= HCKSUM_IPHDRCKSUM; 751 } 752 753 if (umdevice->dev_var.enabled_oflds & 754 (LM_OFFLOAD_TX_TCP_CKSUM | LM_OFFLOAD_TX_UDP_CKSUM | 755 LM_OFFLOAD_RX_TCP_CKSUM | LM_OFFLOAD_RX_UDP_CKSUM)) { 756 *txflags |= HCKSUM_INET_FULL_V4; 757 } 758 break; 759 } 760 default: 761 return (B_FALSE); 762 } 763 764 return (B_TRUE); 765 } 766 767 static int 768 bnx_refresh_rx_tx_pkts(um_device_t *umdevice) 769 { 770 if (umdevice->os_param.active_resc_flag & DRV_RESOURCE_HDWR_REGISTER) { 771 bnx_hdwr_fini(umdevice); 772 /* 773 * Initialize the adapter resource. Mainly allocating memory 774 * needed by the driver, such as packet descriptors, shared 775 * memory, etc. 776 */ 777 if (lm_init_resc(&(umdevice->lm_dev)) != LM_STATUS_SUCCESS) { 778 return (EIO); 779 } 780 781 if (bnx_txpkts_init(umdevice)) { 782 return (EIO); 783 } 784 785 if (bnx_rxpkts_init(umdevice)) { 786 return (EIO); 787 } 788 } 789 return (0); 790 } 791 792 static int 793 bnx_set_priv_prop(um_device_t *umdevice, const char *pr_name, 794 uint_t pr_valsize, const void *pr_val) 795 { 796 boolean_t refresh = B_FALSE; 797 long result; 798 int err = 0; 799 800 if (strcmp(pr_name, "_adv_2500fdx_cap") == 0) { 801 if (lm_get_medium(&umdevice->lm_dev) != LM_MEDIUM_TYPE_FIBER) { 802 return (ENOTSUP); 803 } 804 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) { 805 return (EINVAL); 806 } 807 if (result != 1 && result != 0) { 808 return (EINVAL); 809 } 810 if (umdevice->hwinit.lnkcfg.param_2500fdx != (uint32_t)result) { 811 umdevice->hwinit.lnkcfg.param_2500fdx = 812 (uint32_t)result; 813 umdevice->curcfg.lnkcfg.param_2500fdx = 814 (uint32_t)result; 815 bnx_update_phy(umdevice); 816 } 817 } else if (strcmp(pr_name, "_checksum") == 0) { 818 if (umdevice->dev_start == B_TRUE) { 819 return (EBUSY); 820 } 821 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) { 822 return (EINVAL); 823 } 824 switch (result) { 825 case USER_OPTION_CKSUM_TX_ONLY: 826 umdevice->dev_var.enabled_oflds = 827 LM_OFFLOAD_TX_IP_CKSUM | 828 LM_OFFLOAD_TX_TCP_CKSUM | 829 LM_OFFLOAD_TX_UDP_CKSUM; 830 break; 831 832 case USER_OPTION_CKSUM_RX_ONLY: 833 umdevice->dev_var.enabled_oflds = 834 LM_OFFLOAD_RX_IP_CKSUM | 835 LM_OFFLOAD_RX_TCP_CKSUM | 836 LM_OFFLOAD_RX_UDP_CKSUM; 837 break; 838 839 case USER_OPTION_CKSUM_TX_RX: 840 umdevice->dev_var.enabled_oflds = 841 LM_OFFLOAD_TX_IP_CKSUM | 842 LM_OFFLOAD_RX_IP_CKSUM | 843 LM_OFFLOAD_TX_TCP_CKSUM | 844 LM_OFFLOAD_RX_TCP_CKSUM | 845 LM_OFFLOAD_TX_UDP_CKSUM | 846 LM_OFFLOAD_RX_UDP_CKSUM; 847 break; 848 849 case USER_OPTION_CKSUM_NONE: 850 umdevice->dev_var.enabled_oflds = 851 LM_OFFLOAD_NONE; 852 break; 853 854 default: 855 return (EINVAL); 856 } 857 } else if (strcmp(pr_name, "_tx_descriptor_count") == 0) { 858 if (umdevice->dev_start == B_TRUE) { 859 return (EBUSY); 860 } 861 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) { 862 return (EINVAL); 863 } 864 if (result < USER_OPTION_TX_DESC_CNT_MIN || 865 result > USER_OPTION_TX_DESC_CNT_MAX) { 866 return (EINVAL); 867 } 868 _TX_QINFO(umdevice, 0).desc_cnt = result; 869 umdevice->lm_dev.params.l2_tx_bd_page_cnt[0] = 870 result / MAX_BD_PER_PAGE; 871 if (result % MAX_BD_PER_PAGE) { 872 umdevice->lm_dev.params.l2_tx_bd_page_cnt[0]++; 873 } 874 if (umdevice->lm_dev.params.l2_tx_bd_page_cnt[0] > 127) { 875 umdevice->lm_dev.params.l2_tx_bd_page_cnt[0] = 127; 876 } 877 refresh = B_TRUE; 878 } else if (strcmp(pr_name, "_rx_descriptor_count") == 0) { 879 if (umdevice->dev_start == B_TRUE) { 880 return (EBUSY); 881 } 882 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) { 883 return (EINVAL); 884 } 885 if (result < USER_OPTION_RX_DESC_CNT_MIN || 886 result > USER_OPTION_RX_DESC_CNT_MAX) { 887 return (EINVAL); 888 } 889 umdevice->lm_dev.params.l2_rx_desc_cnt[0] = result; 890 result = (result * BNX_RECV_MAX_FRAGS) / MAX_BD_PER_PAGE; 891 umdevice->lm_dev.params.l2_rx_bd_page_cnt[0] = result; 892 if (result % MAX_BD_PER_PAGE) { 893 umdevice->lm_dev.params.l2_rx_bd_page_cnt[0]++; 894 } 895 refresh = B_TRUE; 896 } 897 #if 0 898 /* Initialized by init_hc() */ 899 else if (strcmp(pr_name, "_tx_coalesce_ticks") == 0) { 900 if (umdevice->dev_start == B_TRUE) { 901 return (EBUSY); 902 } 903 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) { 904 return (EINVAL); 905 } 906 if (result < USER_OPTION_TICKS_MIN || 907 result > USER_OPTION_TICKS_MAX) { 908 return (EINVAL); 909 } 910 umdevice->lm_dev.params.tx_ticks = result; 911 } else if (strcmp(pr_name, "_tx_coalesce_ticks_int") == 0) { 912 if (umdevice->dev_start == B_TRUE) { 913 return (EBUSY); 914 } 915 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) { 916 return (EINVAL); 917 } 918 if (result < USER_OPTION_TICKS_INT_MIN || 919 result > USER_OPTION_TICKS_INT_MAX) { 920 return (EINVAL); 921 } 922 umdevice->lm_dev.params.tx_ticks_int = result; 923 } else if (strcmp(pr_name, "_rx_coalesce_ticks") == 0) { 924 if (umdevice->dev_start == B_TRUE) { 925 return (EBUSY); 926 } 927 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) { 928 return (EINVAL); 929 } 930 if (result < USER_OPTION_TICKS_MIN || 931 result > USER_OPTION_TICKS_MAX) { 932 return (EINVAL); 933 } 934 umdevice->lm_dev.params.rx_ticks = result; 935 } else if (strcmp(pr_name, "_rx_coalesce_ticks_int") == 0) { 936 if (umdevice->dev_start == B_TRUE) { 937 return (EBUSY); 938 } 939 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) { 940 return (EINVAL); 941 } 942 if (result < USER_OPTION_TICKS_INT_MIN || 943 result > USER_OPTION_TICKS_INT_MAX) { 944 return (EINVAL); 945 } 946 umdevice->lm_dev.params.rx_ticks_int = result; 947 } else if (strcmp(pr_name, "_tx_coalesce_frames") == 0) { 948 if (umdevice->dev_start == B_TRUE) { 949 return (EBUSY); 950 } 951 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) { 952 return (EINVAL); 953 } 954 if (result < USER_OPTION_FRAMES_MIN || 955 result > USER_OPTION_FRAMES_MAX) { 956 return (EINVAL); 957 } 958 umdevice->lm_dev.params.tx_quick_cons_trip = result; 959 } else if (strcmp(pr_name, "_tx_coalesce_frames_int") == 0) { 960 if (umdevice->dev_start == B_TRUE) { 961 return (EBUSY); 962 } 963 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) { 964 return (EINVAL); 965 } 966 if (result < USER_OPTION_FRAMES_MIN || 967 result > USER_OPTION_FRAMES_MAX) { 968 return (EINVAL); 969 } 970 umdevice->lm_dev.params.tx_quick_cons_trip_int = result; 971 } else if (strcmp(pr_name, "_rx_coalesce_frames") == 0) { 972 if (umdevice->dev_start == B_TRUE) { 973 return (EBUSY); 974 } 975 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) { 976 return (EINVAL); 977 } 978 if (result < USER_OPTION_FRAMES_MIN || 979 result > USER_OPTION_FRAMES_MAX) { 980 return (EINVAL); 981 } 982 umdevice->lm_dev.params.rx_quick_cons_trip = result; 983 } else if (strcmp(pr_name, "_rx_coalesce_frames_int") == 0) { 984 if (umdevice->dev_start == B_TRUE) { 985 return (EBUSY); 986 } 987 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) { 988 return (EINVAL); 989 } 990 if (result < USER_OPTION_FRAMES_MIN || 991 result > USER_OPTION_FRAMES_MAX) { 992 return (EINVAL); 993 } 994 umdevice->lm_dev.params.rx_quick_cons_trip_int = result; 995 } else if (strcmp(pr_name, "_statticks") == 0) { 996 if (umdevice->dev_start == B_TRUE) { 997 return (EBUSY); 998 } 999 if (ddi_strtol(pr_val, (char **)NULL, 0, &result)) { 1000 return (EINVAL); 1001 } 1002 if (result < USER_OPTION_STATSTICKS_MIN || 1003 result > USER_OPTION_STATSTICKS_MAX) { 1004 return (EINVAL); 1005 } 1006 umdevice->lm_dev.params.stats_ticks = result; 1007 } 1008 #endif 1009 else if (strcmp(pr_name, "_disable_msix") == 0) { 1010 err = ENOTSUP; 1011 } else { 1012 err = ENOTSUP; 1013 } 1014 1015 if (!err && refresh) { 1016 err = bnx_refresh_rx_tx_pkts(umdevice); 1017 } 1018 return (err); 1019 } 1020 1021 1022 static int 1023 bnx_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, 1024 uint_t pr_valsize, const void *pr_val) 1025 { 1026 um_device_t *umdevice = arg; 1027 boolean_t reprogram = B_FALSE; 1028 boolean_t rxpause; 1029 boolean_t txpause; 1030 uint32_t mtu; 1031 link_flowctrl_t fl; 1032 int err = 0; 1033 1034 mutex_enter(&umdevice->os_param.gld_mutex); 1035 1036 if (lm_get_medium(&umdevice->lm_dev) == LM_MEDIUM_TYPE_FIBER) { 1037 if (pr_num == MAC_PROP_EN_100FDX_CAP || 1038 pr_num == MAC_PROP_EN_100HDX_CAP || 1039 pr_num == MAC_PROP_EN_10FDX_CAP || 1040 pr_num == MAC_PROP_EN_10HDX_CAP) { 1041 mutex_exit(&umdevice->os_param.gld_mutex); 1042 return (ENOTSUP); 1043 } 1044 } 1045 1046 switch (pr_num) { 1047 /* read-only properties */ 1048 case MAC_PROP_ADV_1000FDX_CAP: 1049 case MAC_PROP_ADV_1000HDX_CAP: 1050 case MAC_PROP_ADV_100FDX_CAP: 1051 case MAC_PROP_ADV_100HDX_CAP: 1052 case MAC_PROP_ADV_10FDX_CAP: 1053 case MAC_PROP_ADV_10HDX_CAP: 1054 case MAC_PROP_STATUS: 1055 case MAC_PROP_SPEED: 1056 case MAC_PROP_DUPLEX: 1057 case MAC_PROP_MEDIA: 1058 default: 1059 1060 err = ENOTSUP; 1061 break; 1062 1063 1064 /* BEGIN CSTYLED */ 1065 #define BNX_SETPROP_CASE(cap, param) \ 1066 case cap: \ 1067 if (umdevice->hwinit.lnkcfg.param != *(uint8_t *)pr_val) { \ 1068 umdevice->hwinit.lnkcfg.param = *(uint8_t *)pr_val; \ 1069 umdevice->curcfg.lnkcfg.param = *(uint8_t *)pr_val; \ 1070 reprogram = B_TRUE; \ 1071 } \ 1072 break 1073 /* END CSTYLED */ 1074 1075 1076 BNX_SETPROP_CASE(MAC_PROP_EN_1000FDX_CAP, param_1000fdx); 1077 BNX_SETPROP_CASE(MAC_PROP_EN_1000HDX_CAP, param_1000hdx); 1078 BNX_SETPROP_CASE(MAC_PROP_EN_100FDX_CAP, param_100fdx); 1079 BNX_SETPROP_CASE(MAC_PROP_EN_100HDX_CAP, param_100hdx); 1080 BNX_SETPROP_CASE(MAC_PROP_EN_10FDX_CAP, param_10fdx); 1081 BNX_SETPROP_CASE(MAC_PROP_EN_10HDX_CAP, param_10hdx); 1082 BNX_SETPROP_CASE(MAC_PROP_AUTONEG, link_autoneg); 1083 1084 case MAC_PROP_FLOWCTRL: 1085 bcopy(pr_val, &fl, sizeof (fl)); 1086 switch (fl) { 1087 case LINK_FLOWCTRL_NONE: 1088 1089 rxpause = B_FALSE; 1090 txpause = B_FALSE; 1091 break; 1092 1093 case LINK_FLOWCTRL_RX: 1094 1095 rxpause = B_TRUE; 1096 txpause = B_FALSE; 1097 break; 1098 1099 case LINK_FLOWCTRL_TX: 1100 1101 rxpause = B_FALSE; 1102 txpause = B_TRUE; 1103 break; 1104 1105 case LINK_FLOWCTRL_BI: 1106 1107 rxpause = B_TRUE; 1108 txpause = B_TRUE; 1109 break; 1110 1111 default: 1112 1113 err = ENOTSUP; 1114 break; 1115 } 1116 1117 if (err == 0) { 1118 if (umdevice->hwinit.lnkcfg.param_tx_pause != 1119 txpause || 1120 umdevice->hwinit.lnkcfg.param_rx_pause != 1121 rxpause) { 1122 umdevice->hwinit.lnkcfg.param_tx_pause = 1123 txpause; 1124 umdevice->hwinit.lnkcfg.param_rx_pause = 1125 rxpause; 1126 umdevice->curcfg.lnkcfg.param_tx_pause = 1127 txpause; 1128 umdevice->curcfg.lnkcfg.param_rx_pause = 1129 rxpause; 1130 reprogram = B_TRUE; 1131 } 1132 } 1133 1134 break; 1135 1136 case MAC_PROP_MTU: 1137 if (umdevice->dev_start == B_TRUE) { 1138 err = EBUSY; 1139 break; 1140 } 1141 1142 bcopy(pr_val, &mtu, sizeof (mtu)); 1143 1144 if (mtu < USER_OPTION_MTU_MIN || 1145 mtu > USER_OPTION_MTU_MAX) { 1146 err = EINVAL; 1147 break; 1148 } 1149 1150 if (umdevice->dev_var.mtu == mtu) { 1151 break; 1152 } 1153 1154 umdevice->dev_var.mtu = mtu; 1155 umdevice->lm_dev.params.mtu = umdevice->dev_var.mtu 1156 + sizeof (struct ether_header) + VLAN_TAGSZ; 1157 1158 if (bnx_refresh_rx_tx_pkts(umdevice) != 0) { 1159 err = EIO; 1160 } else { 1161 reprogram = B_TRUE; 1162 } 1163 break; 1164 1165 case MAC_PROP_PRIVATE: 1166 err = bnx_set_priv_prop(umdevice, pr_name, pr_valsize, 1167 pr_val); 1168 reprogram = B_TRUE; 1169 break; 1170 } 1171 1172 if (!err && reprogram) { 1173 bnx_update_phy(umdevice); 1174 } 1175 1176 mutex_exit(&umdevice->os_param.gld_mutex); 1177 1178 return (err); 1179 } 1180 1181 static int 1182 bnx_get_priv_prop(um_device_t *umdevice, const char *pr_name, 1183 uint_t pr_valsize, void *pr_val) 1184 { 1185 int value; 1186 1187 if (strcmp(pr_name, "_adv_2500fdx_cap") == 0) { 1188 if (lm_get_medium(&umdevice->lm_dev) != 1189 LM_MEDIUM_TYPE_FIBER) { 1190 return (ENOTSUP); 1191 } 1192 value = umdevice->curcfg.lnkcfg.param_2500fdx; 1193 } else if (strcmp(pr_name, "_checksum") == 0) { 1194 value = umdevice->dev_var.enabled_oflds; 1195 } else if (strcmp(pr_name, "_tx_descriptor_count") == 0) { 1196 value = _TX_QINFO(umdevice, 0).desc_cnt; 1197 } else if (strcmp(pr_name, "_rx_descriptor_count") == 0) { 1198 value = umdevice->lm_dev.params.l2_rx_desc_cnt[0]; 1199 } else if (strcmp(pr_name, "_tx_coalesce_ticks") == 0) { 1200 value = umdevice->lm_dev.params.tx_ticks; 1201 } else if (strcmp(pr_name, "_tx_coalesce_ticks_int") == 0) { 1202 value = umdevice->lm_dev.params.tx_ticks_int; 1203 } else if (strcmp(pr_name, "_rx_coalesce_ticks") == 0) { 1204 value = umdevice->lm_dev.params.rx_ticks; 1205 } else if (strcmp(pr_name, "_rx_coalesce_ticks_int") == 0) { 1206 value = umdevice->lm_dev.params.rx_ticks_int; 1207 } else if (strcmp(pr_name, "_tx_coalesce_frames") == 0) { 1208 value = umdevice->lm_dev.params.tx_quick_cons_trip; 1209 } else if (strcmp(pr_name, "_tx_coalesce_frames_int") == 0) { 1210 value = umdevice->lm_dev.params.tx_quick_cons_trip_int; 1211 } else if (strcmp(pr_name, "_rx_coalesce_frames") == 0) { 1212 value = umdevice->lm_dev.params.rx_quick_cons_trip; 1213 } else if (strcmp(pr_name, "_rx_coalesce_frames_int") == 0) { 1214 value = umdevice->lm_dev.params.rx_quick_cons_trip_int; 1215 } else if (strcmp(pr_name, "_statticks") == 0) { 1216 value = umdevice->lm_dev.params.stats_ticks; 1217 } else if (strcmp(pr_name, "_disable_msix") == 0) { 1218 value = umdevice->dev_var.disableMsix; 1219 } else { 1220 return (ENOTSUP); 1221 } 1222 1223 (void) snprintf(pr_val, pr_valsize, "%d", value); 1224 return (0); 1225 1226 } 1227 1228 static int 1229 bnx_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num, 1230 uint_t pr_valsize, void *pr_val) 1231 { 1232 um_device_t *umdevice = arg; 1233 link_duplex_t link_duplex; 1234 uint64_t link_speed; 1235 link_state_t link_state; 1236 link_flowctrl_t fl; 1237 mac_ether_media_t media; 1238 1239 if (lm_get_medium(&umdevice->lm_dev) == LM_MEDIUM_TYPE_FIBER) { 1240 if (pr_num == MAC_PROP_EN_100FDX_CAP || 1241 pr_num == MAC_PROP_EN_100HDX_CAP || 1242 pr_num == MAC_PROP_EN_10FDX_CAP || 1243 pr_num == MAC_PROP_EN_10HDX_CAP) { 1244 return (ENOTSUP); 1245 } 1246 } 1247 1248 switch (pr_num) { 1249 case MAC_PROP_DUPLEX: 1250 link_duplex = umdevice->nddcfg.link_duplex == B_TRUE ? 1251 LINK_DUPLEX_FULL: LINK_DUPLEX_HALF; 1252 1253 ASSERT(pr_valsize >= sizeof (link_duplex_t)); 1254 1255 bcopy(&link_duplex, pr_val, sizeof (link_duplex_t)); 1256 break; 1257 1258 case MAC_PROP_SPEED: 1259 link_speed = umdevice->nddcfg.link_speed * 1000000ull; 1260 1261 ASSERT(pr_valsize >= sizeof (link_speed)); 1262 1263 bcopy(&link_speed, pr_val, sizeof (link_speed)); 1264 break; 1265 1266 case MAC_PROP_STATUS: 1267 link_state = umdevice->nddcfg.link_speed ? 1268 LINK_STATE_UP : LINK_STATE_DOWN; 1269 1270 ASSERT(pr_valsize >= sizeof (link_state_t)); 1271 1272 bcopy(&link_state, pr_val, sizeof (link_state)); 1273 break; 1274 1275 case MAC_PROP_MEDIA: 1276 media = bnx_um_to_media(umdevice); 1277 1278 ASSERT(pr_valsize >= sizeof (mac_ether_media_t)); 1279 1280 bcopy(&media, pr_val, sizeof (link_state)); 1281 break; 1282 1283 case MAC_PROP_AUTONEG: 1284 *(uint8_t *)pr_val = 1285 umdevice->curcfg.lnkcfg.link_autoneg; 1286 break; 1287 1288 case MAC_PROP_FLOWCTRL: 1289 ASSERT(pr_valsize >= sizeof (fl)); 1290 1291 boolean_t txpause = 1292 umdevice->curcfg.lnkcfg.param_tx_pause; 1293 boolean_t rxpause = 1294 umdevice->curcfg.lnkcfg.param_rx_pause; 1295 if (txpause) { 1296 if (rxpause) { 1297 fl = LINK_FLOWCTRL_BI; 1298 } else { 1299 fl = LINK_FLOWCTRL_TX; 1300 } 1301 } else { 1302 if (rxpause) { 1303 fl = LINK_FLOWCTRL_RX; 1304 } else { 1305 fl = LINK_FLOWCTRL_NONE; 1306 } 1307 } 1308 bcopy(&fl, pr_val, sizeof (fl)); 1309 break; 1310 1311 case MAC_PROP_ADV_1000FDX_CAP: 1312 *(uint8_t *)pr_val = 1313 umdevice->curcfg.lnkcfg.param_1000fdx; 1314 break; 1315 1316 case MAC_PROP_EN_1000FDX_CAP: 1317 *(uint8_t *)pr_val = 1318 umdevice->curcfg.lnkcfg.param_1000fdx; 1319 break; 1320 1321 case MAC_PROP_ADV_1000HDX_CAP: 1322 *(uint8_t *)pr_val = 1323 umdevice->curcfg.lnkcfg.param_1000hdx; 1324 break; 1325 1326 case MAC_PROP_EN_1000HDX_CAP: 1327 *(uint8_t *)pr_val = 1328 umdevice->curcfg.lnkcfg.param_1000hdx; 1329 break; 1330 1331 case MAC_PROP_ADV_100FDX_CAP: 1332 *(uint8_t *)pr_val = 1333 umdevice->curcfg.lnkcfg.param_100fdx; 1334 break; 1335 1336 case MAC_PROP_EN_100FDX_CAP: 1337 *(uint8_t *)pr_val = 1338 umdevice->curcfg.lnkcfg.param_100fdx; 1339 break; 1340 1341 case MAC_PROP_ADV_100HDX_CAP: 1342 *(uint8_t *)pr_val = 1343 umdevice->curcfg.lnkcfg.param_100hdx; 1344 break; 1345 1346 case MAC_PROP_EN_100HDX_CAP: 1347 *(uint8_t *)pr_val = 1348 umdevice->curcfg.lnkcfg.param_100hdx; 1349 break; 1350 1351 case MAC_PROP_ADV_10FDX_CAP: 1352 *(uint8_t *)pr_val = 1353 umdevice->curcfg.lnkcfg.param_10fdx; 1354 break; 1355 1356 case MAC_PROP_EN_10FDX_CAP: 1357 *(uint8_t *)pr_val = 1358 umdevice->curcfg.lnkcfg.param_10fdx; 1359 break; 1360 1361 case MAC_PROP_ADV_10HDX_CAP: 1362 *(uint8_t *)pr_val = 1363 umdevice->curcfg.lnkcfg.param_10hdx; 1364 break; 1365 1366 case MAC_PROP_EN_10HDX_CAP: 1367 *(uint8_t *)pr_val = 1368 umdevice->curcfg.lnkcfg.param_10hdx; 1369 break; 1370 1371 case MAC_PROP_PRIVATE: 1372 return (bnx_get_priv_prop(umdevice, pr_name, pr_valsize, 1373 pr_val)); 1374 1375 default: 1376 1377 return (ENOTSUP); 1378 1379 } 1380 1381 return (0); 1382 1383 } 1384 1385 static void 1386 bnx_priv_propinfo(um_device_t *umdevice, const char *pr_name, 1387 mac_prop_info_handle_t prh) 1388 { 1389 char valstr[64]; 1390 int value; 1391 1392 if (strcmp(pr_name, "_adv_2500fdx_cap") == 0) { 1393 if (lm_get_medium(&umdevice->lm_dev) != LM_MEDIUM_TYPE_FIBER) { 1394 return; 1395 } 1396 value = umdevice->curcfg.lnkcfg.param_2500fdx; 1397 } else if (strcmp(pr_name, "_checksum") == 0) { 1398 value = umdevice->dev_var.enabled_oflds; 1399 } else if (strcmp(pr_name, "_tx_descriptor_count") == 0) { 1400 value = _TX_QINFO(umdevice, 0).desc_cnt; 1401 } else if (strcmp(pr_name, "_rx_descriptor_count") == 0) { 1402 value = umdevice->lm_dev.params.l2_rx_desc_cnt[0]; 1403 } else if (strcmp(pr_name, "_tx_coalesce_ticks") == 0) { 1404 value = umdevice->lm_dev.params.tx_ticks; 1405 } else if (strcmp(pr_name, "_tx_coalesce_ticks_int") == 0) { 1406 value = umdevice->lm_dev.params.tx_ticks_int; 1407 } else if (strcmp(pr_name, "_rx_coalesce_ticks") == 0) { 1408 value = umdevice->lm_dev.params.rx_ticks; 1409 } else if (strcmp(pr_name, "_rx_coalesce_ticks_int") == 0) { 1410 value = umdevice->lm_dev.params.rx_ticks_int; 1411 } else if (strcmp(pr_name, "_tx_coalesce_frames") == 0) { 1412 value = umdevice->lm_dev.params.tx_quick_cons_trip; 1413 } else if (strcmp(pr_name, "_tx_coalesce_frames_int") == 0) { 1414 value = umdevice->lm_dev.params.tx_quick_cons_trip_int; 1415 } else if (strcmp(pr_name, "_rx_coalesce_frames") == 0) { 1416 value = umdevice->lm_dev.params.rx_quick_cons_trip; 1417 } else if (strcmp(pr_name, "_rx_coalesce_frames_int") == 0) { 1418 value = umdevice->lm_dev.params.rx_quick_cons_trip_int; 1419 } else if (strcmp(pr_name, "_statticks") == 0) { 1420 value = umdevice->lm_dev.params.stats_ticks; 1421 } else if (strcmp(pr_name, "_disable_msix") == 0) { 1422 value = umdevice->dev_var.disableMsix; 1423 } else { 1424 return; 1425 } 1426 1427 (void) snprintf(valstr, sizeof (valstr), "%d", value); 1428 mac_prop_info_set_default_str(prh, valstr); 1429 1430 } 1431 1432 static void 1433 bnx_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num, 1434 mac_prop_info_handle_t prh) 1435 { 1436 um_device_t *umdevice = arg; 1437 1438 if (lm_get_medium(&umdevice->lm_dev) == LM_MEDIUM_TYPE_FIBER) { 1439 if (pr_num == MAC_PROP_EN_100FDX_CAP || 1440 pr_num == MAC_PROP_ADV_100FDX_CAP || 1441 pr_num == MAC_PROP_EN_100HDX_CAP || 1442 pr_num == MAC_PROP_ADV_100HDX_CAP || 1443 pr_num == MAC_PROP_EN_10FDX_CAP || 1444 pr_num == MAC_PROP_ADV_10FDX_CAP || 1445 pr_num == MAC_PROP_EN_10HDX_CAP || 1446 pr_num == MAC_PROP_ADV_10HDX_CAP) { 1447 mac_prop_info_set_default_uint8(prh, 0); 1448 return; 1449 } 1450 } 1451 switch (pr_num) { 1452 case MAC_PROP_ADV_1000FDX_CAP: 1453 case MAC_PROP_ADV_1000HDX_CAP: 1454 case MAC_PROP_ADV_100FDX_CAP: 1455 case MAC_PROP_ADV_100HDX_CAP: 1456 case MAC_PROP_ADV_10FDX_CAP: 1457 case MAC_PROP_ADV_10HDX_CAP: 1458 case MAC_PROP_STATUS: 1459 case MAC_PROP_SPEED: 1460 case MAC_PROP_DUPLEX: 1461 1462 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 1463 break; 1464 1465 case MAC_PROP_EN_1000FDX_CAP: 1466 1467 mac_prop_info_set_default_uint8(prh, 1); 1468 break; 1469 1470 case MAC_PROP_EN_1000HDX_CAP: 1471 case MAC_PROP_EN_100FDX_CAP: 1472 case MAC_PROP_EN_100HDX_CAP: 1473 case MAC_PROP_EN_10FDX_CAP: 1474 case MAC_PROP_EN_10HDX_CAP: 1475 1476 if (lm_get_medium(&umdevice->lm_dev) == 1477 LM_MEDIUM_TYPE_FIBER) { 1478 mac_prop_info_set_default_uint8(prh, 0); 1479 } else { 1480 mac_prop_info_set_default_uint8(prh, 1); 1481 } 1482 break; 1483 1484 case MAC_PROP_AUTONEG: 1485 1486 mac_prop_info_set_default_uint8(prh, 1); 1487 break; 1488 1489 case MAC_PROP_FLOWCTRL: 1490 1491 mac_prop_info_set_default_link_flowctrl(prh, 1492 LINK_FLOWCTRL_BI); 1493 break; 1494 1495 case MAC_PROP_MTU: 1496 1497 mac_prop_info_set_range_uint32(prh, 1498 USER_OPTION_MTU_MIN, USER_OPTION_MTU_MAX); 1499 break; 1500 1501 case MAC_PROP_PRIVATE: 1502 1503 bnx_priv_propinfo(umdevice, pr_name, prh); 1504 break; 1505 default: 1506 break; 1507 } 1508 } 1509 1510 static mac_callbacks_t bnx_callbacks = { 1511 (MC_GETCAPAB | MC_SETPROP | MC_GETPROP| MC_PROPINFO), 1512 bnx_m_stats, 1513 bnx_m_start, 1514 bnx_m_stop, 1515 bnx_m_promiscuous, 1516 bnx_m_multicast, 1517 bnx_m_unicast, 1518 bnx_m_tx, 1519 NULL, 1520 NULL, 1521 bnx_m_getcapab, 1522 NULL, 1523 NULL, 1524 bnx_m_setprop, 1525 bnx_m_getprop, 1526 bnx_m_propinfo 1527 }; 1528 1529 1530 1531 /* 1532 * Name: bnx_gld_init 1533 * 1534 * Input: ptr to device structure. 1535 * 1536 * Return: DDI_SUCCESS or DDI_FAILURE 1537 * 1538 * Description: 1539 * This routine populates mac info structure for this device 1540 * instance and registers device with GLD. 1541 */ 1542 int 1543 bnx_gld_init(um_device_t *const umdevice) 1544 { 1545 mac_register_t *macp; 1546 int rc; 1547 1548 umdevice->dev_start = B_FALSE; 1549 1550 mutex_init(&umdevice->os_param.gld_mutex, NULL, 1551 MUTEX_DRIVER, DDI_INTR_PRI(umdevice->intrPriority)); 1552 1553 rw_init(&umdevice->os_param.gld_snd_mutex, NULL, RW_DRIVER, NULL); 1554 1555 macp = mac_alloc(MAC_VERSION); 1556 if (macp == NULL) { 1557 cmn_err(CE_WARN, 1558 "%s: Failed to allocate GLD MAC memory.\n", 1559 umdevice->dev_name); 1560 goto error; 1561 } 1562 1563 macp->m_driver = umdevice; 1564 macp->m_dip = umdevice->os_param.dip; 1565 macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 1566 macp->m_callbacks = &bnx_callbacks; 1567 macp->m_min_sdu = 0; 1568 macp->m_max_sdu = umdevice->dev_var.mtu; 1569 macp->m_src_addr = &(umdevice->lm_dev.params.mac_addr[0]); 1570 1571 macp->m_margin = VLAN_TAG_SIZE; 1572 1573 /* 1574 * Call mac_register() after initializing all 1575 * the required elements of mac_t struct. 1576 */ 1577 rc = mac_register(macp, &umdevice->os_param.macp); 1578 1579 mac_free(macp); 1580 1581 if (rc != 0) { 1582 cmn_err(CE_WARN, 1583 "%s: Failed to register with GLD.\n", 1584 umdevice->dev_name); 1585 goto error; 1586 } 1587 1588 /* Always report the initial link state as unknown. */ 1589 bnx_gld_link(umdevice, LINK_STATE_UNKNOWN); 1590 1591 return (0); 1592 1593 error: 1594 rw_destroy(&umdevice->os_param.gld_snd_mutex); 1595 mutex_destroy(&umdevice->os_param.gld_mutex); 1596 1597 return (-1); 1598 } 1599 1600 void 1601 bnx_gld_link(um_device_t * const umdevice, const link_state_t linkup) 1602 { 1603 mac_link_update(umdevice->os_param.macp, linkup); 1604 } 1605 1606 int 1607 bnx_gld_fini(um_device_t * const umdevice) 1608 { 1609 if (umdevice->dev_start != B_FALSE) { 1610 cmn_err(CE_WARN, 1611 "%s: Detaching device from GLD that is still started!!!\n", 1612 umdevice->dev_name); 1613 return (-1); 1614 } 1615 1616 if (mac_unregister(umdevice->os_param.macp)) { 1617 cmn_err(CE_WARN, 1618 "%s: Failed to unregister with the GLD.\n", 1619 umdevice->dev_name); 1620 return (-1); 1621 } 1622 1623 rw_destroy(&umdevice->os_param.gld_snd_mutex); 1624 mutex_destroy(&umdevice->os_param.gld_mutex); 1625 1626 return (0); 1627 } 1628