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