1 /* 2 * Copyright (c) 2008-2015 Solarflare Communications Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * The views and conclusions contained in the software and documentation are 27 * those of the authors and should not be interpreted as representing official 28 * policies, either expressed or implied, of the FreeBSD Project. 29 */ 30 31 #include <sys/types.h> 32 #include <sys/ddi.h> 33 #include <sys/sunddi.h> 34 #include <sys/stream.h> 35 #include <sys/strsun.h> 36 #include <sys/strsubr.h> 37 #include <sys/dlpi.h> 38 #include <sys/ksynch.h> 39 #include <sys/cpuvar.h> 40 #include <sys/cpu.h> 41 42 #include <inet/tcp.h> 43 44 #include "sfxge.h" 45 46 /* A vlan tag is 4 bytes */ 47 #define SFXGE_VLAN_TAGSZ 4 48 49 void 50 sfxge_gld_link_update(sfxge_t *sp) 51 { 52 sfxge_mac_t *smp = &(sp->s_mac); 53 link_state_t link; 54 55 switch (smp->sm_link_mode) { 56 case EFX_LINK_UNKNOWN: 57 link = LINK_STATE_UNKNOWN; 58 break; 59 case EFX_LINK_DOWN: 60 link = LINK_STATE_DOWN; 61 break; 62 default: 63 link = LINK_STATE_UP; 64 } 65 66 mac_link_update(sp->s_mh, link); 67 } 68 69 void 70 sfxge_gld_mtu_update(sfxge_t *sp) 71 { 72 #ifdef _USE_MTU_UPDATE 73 (void) mac_maxsdu_update(sp->s_mh, sp->s_mtu); 74 #else 75 _NOTE(ARGUNUSED(sp)); 76 #endif 77 } 78 79 void 80 sfxge_gld_rx_post(sfxge_t *sp, unsigned int index, mblk_t *mp) 81 { 82 _NOTE(ARGUNUSED(index)) 83 84 mac_rx(sp->s_mh, NULL, mp); 85 } 86 87 88 void 89 sfxge_gld_rx_push(sfxge_t *sp) 90 { 91 _NOTE(ARGUNUSED(sp)) 92 } 93 94 95 static uint64_t 96 sfxge_phy_dfl_cap_test64(sfxge_t *sp, uint32_t field) 97 { 98 return (sfxge_phy_cap_test(sp, EFX_PHY_CAP_DEFAULT, field, NULL) ? 99 1ull : 0ull); 100 } 101 102 103 static uint64_t 104 sfxge_phy_cur_cap_test64(sfxge_t *sp, uint32_t field) 105 { 106 return (sfxge_phy_cap_test(sp, EFX_PHY_CAP_CURRENT, field, NULL) ? 107 1ull : 0ull); 108 } 109 110 static uint64_t 111 sfxge_phy_lp_cap_test64(sfxge_t *sp, uint32_t field) 112 { 113 return (sfxge_phy_lp_cap_test(sp, field) ? 1ull : 0ull); 114 } 115 116 static int 117 sfxge_gld_getstat(void *arg, unsigned int id, uint64_t *valp) 118 { 119 sfxge_t *sp = arg; 120 efx_nic_t *enp = sp->s_enp; 121 int rc; 122 123 if (sp->s_mac.sm_state != SFXGE_MAC_STARTED) { 124 rc = ENODEV; 125 goto fail1; 126 } 127 128 switch (id) { 129 case MAC_STAT_IFSPEED: { 130 unsigned int speed; 131 132 sfxge_mac_link_speed_get(sp, &speed); 133 134 *valp = (uint64_t)speed * 1000000ull; 135 break; 136 } 137 case ETHER_STAT_LINK_DUPLEX: { 138 sfxge_link_duplex_t duplex; 139 140 sfxge_mac_link_duplex_get(sp, &duplex); 141 142 switch (duplex) { 143 case SFXGE_LINK_DUPLEX_UNKNOWN: 144 *valp = LINK_DUPLEX_UNKNOWN; 145 break; 146 147 case SFXGE_LINK_DUPLEX_HALF: 148 *valp = LINK_DUPLEX_HALF; 149 break; 150 151 case SFXGE_LINK_DUPLEX_FULL: 152 *valp = LINK_DUPLEX_FULL; 153 break; 154 155 default: 156 ASSERT(B_FALSE); 157 break; 158 } 159 break; 160 } 161 162 case ETHER_STAT_CAP_40GFDX: 163 *valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_40000FDX); 164 break; 165 case ETHER_STAT_CAP_10GFDX: 166 *valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_10000FDX); 167 break; 168 case ETHER_STAT_CAP_1000FDX: 169 *valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_1000FDX); 170 break; 171 case ETHER_STAT_CAP_1000HDX: 172 *valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_1000HDX); 173 break; 174 case ETHER_STAT_CAP_100FDX: 175 *valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_100FDX); 176 break; 177 case ETHER_STAT_CAP_100HDX: 178 *valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_100HDX); 179 break; 180 case ETHER_STAT_CAP_10FDX: 181 *valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_10FDX); 182 break; 183 case ETHER_STAT_CAP_10HDX: 184 *valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_10HDX); 185 break; 186 case ETHER_STAT_CAP_ASMPAUSE: 187 *valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_ASYM); 188 break; 189 case ETHER_STAT_CAP_PAUSE: 190 *valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_PAUSE); 191 break; 192 case ETHER_STAT_CAP_AUTONEG: 193 *valp = sfxge_phy_dfl_cap_test64(sp, EFX_PHY_CAP_AN); 194 break; 195 case ETHER_STAT_ADV_CAP_40GFDX: 196 *valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_40000FDX); 197 break; 198 case ETHER_STAT_ADV_CAP_10GFDX: 199 *valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_10000FDX); 200 break; 201 case ETHER_STAT_ADV_CAP_1000FDX: 202 *valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_1000FDX); 203 break; 204 case ETHER_STAT_ADV_CAP_1000HDX: 205 *valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_1000HDX); 206 break; 207 case ETHER_STAT_ADV_CAP_100FDX: 208 *valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_100FDX); 209 break; 210 case ETHER_STAT_ADV_CAP_100HDX: 211 *valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_100HDX); 212 break; 213 case ETHER_STAT_ADV_CAP_10FDX: 214 *valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_10FDX); 215 break; 216 case ETHER_STAT_ADV_CAP_10HDX: 217 *valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_10HDX); 218 break; 219 case ETHER_STAT_ADV_CAP_ASMPAUSE: 220 *valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_ASYM); 221 break; 222 case ETHER_STAT_ADV_CAP_PAUSE: 223 *valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_PAUSE); 224 break; 225 case ETHER_STAT_ADV_CAP_AUTONEG: 226 *valp = sfxge_phy_cur_cap_test64(sp, EFX_PHY_CAP_AN); 227 break; 228 case ETHER_STAT_LP_CAP_40GFDX: 229 *valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_40000FDX); 230 break; 231 case ETHER_STAT_LP_CAP_10GFDX: 232 *valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_10000FDX); 233 break; 234 case ETHER_STAT_LP_CAP_1000FDX: 235 *valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_1000FDX); 236 break; 237 case ETHER_STAT_LP_CAP_1000HDX: 238 *valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_1000HDX); 239 break; 240 case ETHER_STAT_LP_CAP_100FDX: 241 *valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_100FDX); 242 break; 243 case ETHER_STAT_LP_CAP_100HDX: 244 *valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_100HDX); 245 break; 246 case ETHER_STAT_LP_CAP_10FDX: 247 *valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_10FDX); 248 break; 249 case ETHER_STAT_LP_CAP_10HDX: 250 *valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_10HDX); 251 break; 252 case ETHER_STAT_LP_CAP_ASMPAUSE: 253 *valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_ASYM); 254 break; 255 case ETHER_STAT_LP_CAP_PAUSE: 256 *valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_PAUSE); 257 break; 258 case ETHER_STAT_LP_CAP_AUTONEG: 259 *valp = sfxge_phy_lp_cap_test64(sp, EFX_PHY_CAP_AN); 260 break; 261 262 case ETHER_STAT_XCVR_ADDR: { 263 const efx_nic_cfg_t *encp = efx_nic_cfg_get(enp); 264 *valp = encp->enc_port; 265 break; 266 } 267 case ETHER_STAT_XCVR_ID: { 268 uint32_t oui; 269 270 if ((rc = efx_phy_oui_get(sp->s_enp, &oui)) != 0) 271 goto fail2; 272 *valp = oui; 273 break; 274 } 275 case MAC_STAT_MULTIRCV: 276 sfxge_mac_stat_get(sp, EFX_MAC_RX_MULTICST_PKTS, valp); 277 break; 278 279 case MAC_STAT_BRDCSTRCV: 280 sfxge_mac_stat_get(sp, EFX_MAC_RX_BRDCST_PKTS, valp); 281 break; 282 283 case MAC_STAT_MULTIXMT: 284 sfxge_mac_stat_get(sp, EFX_MAC_TX_MULTICST_PKTS, valp); 285 break; 286 287 case MAC_STAT_BRDCSTXMT: 288 sfxge_mac_stat_get(sp, EFX_MAC_TX_BRDCST_PKTS, valp); 289 break; 290 291 case MAC_STAT_IERRORS: 292 sfxge_mac_stat_get(sp, EFX_MAC_RX_ERRORS, valp); 293 break; 294 295 case MAC_STAT_OERRORS: 296 sfxge_mac_stat_get(sp, EFX_MAC_TX_ERRORS, valp); 297 break; 298 299 case MAC_STAT_RBYTES: 300 sfxge_mac_stat_get(sp, EFX_MAC_RX_OCTETS, valp); 301 break; 302 303 case MAC_STAT_IPACKETS: 304 sfxge_mac_stat_get(sp, EFX_MAC_RX_PKTS, valp); 305 break; 306 307 case MAC_STAT_OBYTES: 308 sfxge_mac_stat_get(sp, EFX_MAC_TX_OCTETS, valp); 309 break; 310 311 case MAC_STAT_OPACKETS: 312 sfxge_mac_stat_get(sp, EFX_MAC_TX_PKTS, valp); 313 break; 314 315 case MAC_STAT_NORCVBUF: 316 sfxge_mac_stat_get(sp, EFX_MAC_RX_DROP_EVENTS, valp); 317 break; 318 319 case ETHER_STAT_FCS_ERRORS: 320 sfxge_mac_stat_get(sp, EFX_MAC_RX_FCS_ERRORS, valp); 321 break; 322 323 default: 324 rc = ENOTSUP; 325 goto fail3; 326 } 327 328 return (0); 329 fail3: 330 DTRACE_PROBE(fail3); 331 fail2: 332 DTRACE_PROBE(fail2); 333 fail1: 334 DTRACE_PROBE1(fail1, int, rc); 335 336 return (rc); 337 } 338 339 static int 340 sfxge_gld_start(void *arg) 341 { 342 sfxge_t *sp = arg; 343 int rc; 344 345 if ((rc = sfxge_start(sp, B_FALSE)) != 0) 346 goto fail1; 347 348 return (0); 349 350 fail1: 351 DTRACE_PROBE1(fail1, int, rc); 352 353 return (rc); 354 } 355 356 static void 357 sfxge_gld_stop(void *arg) 358 { 359 sfxge_t *sp = arg; 360 361 sfxge_stop(sp); 362 } 363 364 static int 365 sfxge_gld_setpromisc(void *arg, boolean_t on) 366 { 367 sfxge_t *sp = arg; 368 369 return sfxge_mac_promisc_set(sp, 370 (on) ? SFXGE_PROMISC_ALL_PHYS : SFXGE_PROMISC_OFF); 371 } 372 373 static int 374 sfxge_gld_multicst(void *arg, boolean_t add, const uint8_t *addr) 375 { 376 sfxge_t *sp = arg; 377 int rc; 378 379 if (add) { 380 if ((rc = sfxge_mac_multicst_add(sp, addr)) != 0) 381 goto fail1; 382 } else { 383 if ((rc = sfxge_mac_multicst_remove(sp, addr)) != 0) 384 goto fail2; 385 } 386 387 return (0); 388 389 fail2: 390 DTRACE_PROBE(fail2); 391 fail1: 392 DTRACE_PROBE1(fail1, int, rc); 393 return (rc); 394 } 395 396 static int 397 sfxge_gld_unicst(void *arg, const uint8_t *addr) 398 { 399 sfxge_t *sp = arg; 400 int rc; 401 402 if ((rc = sfxge_mac_unicst_set(sp, (uint8_t *)addr)) != 0) 403 goto fail1; 404 405 return (0); 406 407 fail1: 408 DTRACE_PROBE1(fail1, int, rc); 409 410 return (rc); 411 } 412 413 static void 414 sfxge_gld_ioctl(void *arg, queue_t *wq, mblk_t *mp) 415 { 416 sfxge_t *sp = arg; 417 418 sfxge_ioctl(sp, wq, mp); 419 } 420 421 422 static mblk_t * 423 sfxge_gld_tx(void *arg, mblk_t *mp) 424 { 425 sfxge_t *sp = arg; 426 mblk_t *next; 427 428 /* Walk the packet chain */ 429 do { 430 /* Break the packet out of the chain */ 431 next = mp->b_next; 432 mp->b_next = NULL; 433 434 if (next != NULL) 435 prefetch_read_many(next); 436 437 /* Post the packet in the appropriate transmit queue */ 438 if (sfxge_tx_packet_add(sp, mp) == ENOSPC) { 439 mp->b_next = next; 440 return (mp); 441 } 442 443 mp = next; 444 } while (mp != NULL); 445 446 return (NULL); 447 } 448 449 static boolean_t sfxge_lso = B_TRUE; 450 451 static boolean_t 452 sfxge_gld_getcapab(void *arg, mac_capab_t cap, void *cap_arg) 453 { 454 int rc; 455 456 _NOTE(ARGUNUSED(arg)) 457 458 switch (cap) { 459 case MAC_CAPAB_LSO: { 460 mac_capab_lso_t *lsop = cap_arg; 461 462 /* Check whether LSO is disabled */ 463 if (!sfxge_lso) { 464 rc = ENOTSUP; 465 goto fail1; 466 } 467 468 DTRACE_PROBE(lso); 469 470 lsop->lso_flags = LSO_TX_BASIC_TCP_IPV4; 471 lsop->lso_basic_tcp_ipv4.lso_max = TCP_MAX_LSO_LENGTH; 472 break; 473 } 474 case MAC_CAPAB_HCKSUM: { 475 uint32_t *hcksump = cap_arg; 476 477 DTRACE_PROBE(cksum); 478 479 *hcksump = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM; 480 break; 481 } 482 default: 483 rc = ENOTSUP; 484 goto fail1; 485 } 486 487 return (B_TRUE); 488 489 fail1: 490 DTRACE_PROBE1(fail1, int, rc); 491 492 return (B_FALSE); 493 } 494 495 /* 496 * GLDv3 driver-private property names must be preceded by an underscore - see 497 * mc_getprop(9E). 498 */ 499 #define SFXGE_PRIV_PROP_NAME(s) ("_" #s) 500 501 #define SFXGE_XSTR(s) SFXGE_STR(s) 502 #define SFXGE_STR(s) #s 503 504 static void 505 sfxge_gld_priv_prop_info(sfxge_t *sp, const char *name, 506 mac_prop_info_handle_t handle) 507 { 508 _NOTE(ARGUNUSED(sp)); 509 510 /* 511 * Using mac_prop_info_set_default_str rather than the the corresponding 512 * mac_prop_info_set_default_uint32 etc as it gives readable output in 513 * "dladm show-linkprop" commands for private properties. Note this does 514 * not break "dladm reset-linkprop" as might have been expected. 515 */ 516 if (strcmp(name, SFXGE_PRIV_PROP_NAME(rx_coalesce_mode)) == 0) { 517 mac_prop_info_set_default_str(handle, 518 SFXGE_XSTR(SFXGE_RX_COALESCE_OFF)); 519 mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW); 520 return; 521 } 522 523 if (strcmp(name, SFXGE_PRIV_PROP_NAME(rx_scale_count)) == 0) { 524 mac_prop_info_set_default_str(handle, 525 SFXGE_XSTR(SFXGE_RX_SCALE_MAX)); 526 mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW); 527 return; 528 } 529 530 if (strcmp(name, SFXGE_PRIV_PROP_NAME(intr_moderation)) == 0) { 531 mac_prop_info_set_default_str(handle, 532 SFXGE_XSTR(SFXGE_DEFAULT_MODERATION)); 533 mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW); 534 return; 535 } 536 537 #if EFSYS_OPT_MCDI_LOGGING 538 if (strcmp(name, SFXGE_PRIV_PROP_NAME(mcdi_logging)) == 0) { 539 mac_prop_info_set_default_str(handle, 540 SFXGE_XSTR(0)); 541 mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW); 542 return; 543 } 544 #endif 545 DTRACE_PROBE(unknown_priv_prop); 546 } 547 548 549 static int 550 sfxge_gld_priv_prop_get(sfxge_t *sp, const char *name, 551 unsigned int size, void *valp) 552 { 553 long val; 554 int rc; 555 556 if (strcmp(name, SFXGE_PRIV_PROP_NAME(rx_coalesce_mode)) == 0) { 557 sfxge_rx_coalesce_mode_t mode; 558 559 sfxge_rx_coalesce_mode_get(sp, &mode); 560 561 val = (long)mode; 562 goto done; 563 } 564 565 if (strcmp(name, SFXGE_PRIV_PROP_NAME(rx_scale_count)) == 0) { 566 unsigned int count; 567 568 if (sfxge_rx_scale_count_get(sp, &count) != 0) 569 count = 0; 570 571 val = (long)count; 572 goto done; 573 } 574 575 if (strcmp(name, SFXGE_PRIV_PROP_NAME(intr_moderation)) == 0) { 576 unsigned int us; 577 578 sfxge_ev_moderation_get(sp, &us); 579 580 val = (long)us; 581 goto done; 582 } 583 584 #if EFSYS_OPT_MCDI_LOGGING 585 if (strcmp(name, SFXGE_PRIV_PROP_NAME(mcdi_logging)) == 0) { 586 val = (long)sp->s_mcdi_logging; 587 goto done; 588 } 589 #endif 590 591 rc = ENOTSUP; 592 goto fail1; 593 594 done: 595 (void) snprintf(valp, size, "%ld", val); 596 597 return (0); 598 599 fail1: 600 DTRACE_PROBE1(fail1, int, rc); 601 602 return (rc); 603 } 604 605 606 static int 607 sfxge_gld_priv_prop_set(sfxge_t *sp, const char *name, unsigned int size, 608 const void *valp) 609 { 610 long val; 611 int rc = 0; 612 613 _NOTE(ARGUNUSED(size)) 614 615 (void) ddi_strtol(valp, (char **)NULL, 0, &val); 616 617 if (strcmp(name, SFXGE_PRIV_PROP_NAME(rx_coalesce_mode)) == 0) { 618 if ((rc = sfxge_rx_coalesce_mode_set(sp, 619 (sfxge_rx_coalesce_mode_t)val)) != 0) 620 goto fail1; 621 622 goto done; 623 } 624 625 if (strcmp(name, SFXGE_PRIV_PROP_NAME(rx_scale_count)) == 0) { 626 if ((rc = sfxge_rx_scale_count_set(sp, (unsigned int)val)) != 0) 627 goto fail1; 628 629 goto done; 630 } 631 632 if (strcmp(name, SFXGE_PRIV_PROP_NAME(intr_moderation)) == 0) { 633 if ((rc = sfxge_ev_moderation_set(sp, (unsigned int) val)) != 0) 634 goto fail1; 635 636 goto done; 637 } 638 639 #if EFSYS_OPT_MCDI_LOGGING 640 if (strcmp(name, SFXGE_PRIV_PROP_NAME(mcdi_logging)) == 0) { 641 sp->s_mcdi_logging = (int)val; 642 goto done; 643 } 644 #endif 645 646 647 rc = ENOTSUP; 648 goto fail1; 649 650 done: 651 return (0); 652 653 fail1: 654 DTRACE_PROBE1(fail1, int, rc); 655 656 return (rc); 657 } 658 659 660 #if EFSYS_OPT_MCDI_LOGGING 661 #define SFXGE_N_NAMED_PROPS 4 662 #else 663 #define SFXGE_N_NAMED_PROPS 3 664 #endif 665 666 static void 667 sfxge_gld_priv_prop_init(sfxge_t *sp) 668 { 669 sfxge_mac_priv_prop_t *mac_priv_props; 670 unsigned int nprops = 0; 671 672 /* 673 * We have nnamed_props (3 or 4) named properties and the structure must 674 * be finished by a NULL pointer. 675 */ 676 sp->s_mac_priv_props_alloc = SFXGE_N_NAMED_PROPS + 1; 677 sp->s_mac_priv_props = kmem_zalloc(sizeof (sfxge_mac_priv_prop_t) * 678 sp->s_mac_priv_props_alloc, 679 KM_SLEEP); 680 681 /* 682 * Driver-private property names start with an underscore - see 683 * mc_getprop(9E). 684 */ 685 686 mac_priv_props = sp->s_mac_priv_props; 687 688 *mac_priv_props = kmem_zalloc(MAXLINKPROPNAME, KM_SLEEP); 689 (void) snprintf(*mac_priv_props, MAXLINKPROPNAME - 1, 690 SFXGE_PRIV_PROP_NAME(rx_coalesce_mode)); 691 mac_priv_props++; 692 nprops++; 693 694 *mac_priv_props = kmem_zalloc(MAXLINKPROPNAME, KM_SLEEP); 695 (void) snprintf(*mac_priv_props, MAXLINKPROPNAME - 1, 696 SFXGE_PRIV_PROP_NAME(rx_scale_count)); 697 mac_priv_props++; 698 nprops++; 699 700 *mac_priv_props = kmem_zalloc(MAXLINKPROPNAME, KM_SLEEP); 701 (void) snprintf(*mac_priv_props, MAXLINKPROPNAME - 1, 702 SFXGE_PRIV_PROP_NAME(intr_moderation)); 703 mac_priv_props++; 704 nprops++; 705 706 #if EFSYS_OPT_MCDI_LOGGING 707 *mac_priv_props = kmem_zalloc(MAXLINKPROPNAME, KM_SLEEP); 708 (void) snprintf(*mac_priv_props, MAXLINKPROPNAME - 1, 709 SFXGE_PRIV_PROP_NAME(mcdi_logging)); 710 mac_priv_props++; 711 nprops++; 712 #endif 713 714 ASSERT3U((nprops + 1), ==, sp->s_mac_priv_props_alloc); 715 716 /* Terminated by a NULL pointer */ 717 *mac_priv_props = NULL; 718 } 719 720 static void 721 sfxge_gld_priv_prop_fini(sfxge_t *sp) 722 { 723 char **mac_priv_props; 724 unsigned int id; 725 726 mac_priv_props = sp->s_mac_priv_props; 727 728 for (id = 0; id < SFXGE_N_NAMED_PROPS; id++) { 729 kmem_free(*mac_priv_props, MAXLINKPROPNAME); 730 mac_priv_props++; 731 } 732 733 kmem_free(sp->s_mac_priv_props, sizeof (sfxge_mac_priv_prop_t) * 734 sp->s_mac_priv_props_alloc); 735 sp->s_mac_priv_props = NULL; 736 } 737 738 739 static int 740 sfxge_gld_getprop(void *arg, const char *name, mac_prop_id_t id, 741 unsigned int size, void *valp) 742 { 743 sfxge_t *sp = arg; 744 uint32_t flag = EFX_PHY_CAP_CURRENT; 745 uint8_t *v8 = ((uint8_t *)valp); 746 int rc; 747 748 /* check size */ 749 switch (id) { 750 case MAC_PROP_DUPLEX: 751 if (size < sizeof (link_duplex_t)) { 752 rc = EINVAL; 753 goto fail1; 754 } 755 break; 756 case MAC_PROP_FLOWCTRL: 757 if (size < sizeof (link_flowctrl_t)) { 758 rc = EINVAL; 759 goto fail1; 760 } 761 break; 762 case MAC_PROP_SPEED: 763 case MAC_PROP_STATUS: 764 if (size < sizeof (uint64_t)) { 765 rc = EINVAL; 766 goto fail1; 767 } 768 break; 769 case MAC_PROP_MTU: 770 if (size < sizeof (uint32_t)) { 771 rc = EINVAL; 772 goto fail1; 773 } 774 break; 775 case MAC_PROP_EN_AUTONEG: 776 case MAC_PROP_AUTONEG: 777 case MAC_PROP_EN_40GFDX_CAP: 778 case MAC_PROP_ADV_40GFDX_CAP: 779 case MAC_PROP_EN_10GFDX_CAP: 780 case MAC_PROP_ADV_10GFDX_CAP: 781 case MAC_PROP_EN_1000FDX_CAP: 782 case MAC_PROP_ADV_1000FDX_CAP: 783 case MAC_PROP_EN_1000HDX_CAP: 784 case MAC_PROP_ADV_1000HDX_CAP: 785 case MAC_PROP_EN_100FDX_CAP: 786 case MAC_PROP_ADV_100FDX_CAP: 787 case MAC_PROP_EN_100HDX_CAP: 788 case MAC_PROP_ADV_100HDX_CAP: 789 case MAC_PROP_EN_10FDX_CAP: 790 case MAC_PROP_ADV_10FDX_CAP: 791 case MAC_PROP_EN_10HDX_CAP: 792 case MAC_PROP_ADV_10HDX_CAP: 793 if (size < sizeof (uint8_t)) { 794 rc = EINVAL; 795 goto fail1; 796 } 797 break; 798 case MAC_PROP_PRIVATE: 799 /* sfxge_gld_priv_prop_get should do any size checking */ 800 break; 801 default: 802 rc = ENOTSUP; 803 goto fail1; 804 } 805 806 switch (id) { 807 case MAC_PROP_DUPLEX: { 808 sfxge_link_duplex_t duplex; 809 810 sfxge_mac_link_duplex_get(sp, &duplex); 811 812 switch (duplex) { 813 case SFXGE_LINK_DUPLEX_UNKNOWN: 814 *((link_duplex_t *)valp) = LINK_DUPLEX_UNKNOWN; 815 break; 816 817 case SFXGE_LINK_DUPLEX_HALF: 818 *((link_duplex_t *)valp) = LINK_DUPLEX_HALF; 819 break; 820 821 case SFXGE_LINK_DUPLEX_FULL: 822 *((link_duplex_t *)valp) = LINK_DUPLEX_FULL; 823 break; 824 825 default: 826 ASSERT(B_FALSE); 827 break; 828 } 829 830 break; 831 } 832 case MAC_PROP_SPEED: { 833 unsigned int speed; 834 835 sfxge_mac_link_speed_get(sp, &speed); 836 837 *((uint64_t *)valp) = (uint64_t)speed * 1000000ull; 838 839 break; 840 } 841 case MAC_PROP_STATUS: { 842 boolean_t up; 843 844 sfxge_mac_link_check(sp, &up); 845 846 *((link_state_t *)valp) = (up) ? 847 LINK_STATE_UP : LINK_STATE_DOWN; 848 849 break; 850 } 851 case MAC_PROP_EN_AUTONEG: 852 case MAC_PROP_AUTONEG: 853 *v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_AN, NULL); 854 break; 855 case MAC_PROP_EN_40GFDX_CAP: 856 case MAC_PROP_ADV_40GFDX_CAP: 857 *v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_40000FDX, NULL); 858 break; 859 case MAC_PROP_EN_10GFDX_CAP: 860 case MAC_PROP_ADV_10GFDX_CAP: 861 *v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_10000FDX, NULL); 862 break; 863 case MAC_PROP_EN_1000FDX_CAP: 864 case MAC_PROP_ADV_1000FDX_CAP: 865 *v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_1000FDX, NULL); 866 break; 867 case MAC_PROP_EN_1000HDX_CAP: 868 case MAC_PROP_ADV_1000HDX_CAP: 869 *v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_1000HDX, NULL); 870 break; 871 case MAC_PROP_EN_100FDX_CAP: 872 case MAC_PROP_ADV_100FDX_CAP: 873 *v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_100FDX, NULL); 874 break; 875 case MAC_PROP_EN_100HDX_CAP: 876 case MAC_PROP_ADV_100HDX_CAP: 877 *v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_100HDX, NULL); 878 break; 879 case MAC_PROP_EN_10FDX_CAP: 880 case MAC_PROP_ADV_10FDX_CAP: 881 *v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_10FDX, NULL); 882 break; 883 case MAC_PROP_EN_10HDX_CAP: 884 case MAC_PROP_ADV_10HDX_CAP: 885 *v8 = sfxge_phy_cap_test(sp, flag, EFX_PHY_CAP_10HDX, NULL); 886 break; 887 case MAC_PROP_MTU: 888 *((uint32_t *)valp) = (uint32_t)(sp->s_mtu); 889 break; 890 891 case MAC_PROP_FLOWCTRL: { 892 unsigned int fcntl; 893 894 sfxge_mac_fcntl_get(sp, &fcntl); 895 896 switch (fcntl) { 897 case 0: 898 *((link_flowctrl_t *)valp) = LINK_FLOWCTRL_NONE; 899 break; 900 901 case EFX_FCNTL_GENERATE: 902 *((link_flowctrl_t *)valp) = LINK_FLOWCTRL_RX; 903 break; 904 905 case EFX_FCNTL_RESPOND: 906 *((link_flowctrl_t *)valp) = LINK_FLOWCTRL_TX; 907 break; 908 909 case (EFX_FCNTL_GENERATE | EFX_FCNTL_RESPOND): 910 *((link_flowctrl_t *)valp) = LINK_FLOWCTRL_BI; 911 break; 912 913 default: 914 ASSERT(B_FALSE); 915 break; 916 } 917 break; 918 } 919 case MAC_PROP_PRIVATE: 920 if ((rc = sfxge_gld_priv_prop_get(sp, name, size, valp)) != 0) 921 goto fail2; 922 break; 923 default: 924 rc = ENOTSUP; 925 goto fail3; 926 } 927 928 return (0); 929 930 fail3: 931 DTRACE_PROBE(fail3); 932 933 fail2: 934 DTRACE_PROBE(fail2); 935 936 fail1: 937 DTRACE_PROBE1(fail1, int, rc); 938 939 return (rc); 940 } 941 942 943 static int 944 sfxge_gld_setprop(void *arg, const char *name, mac_prop_id_t id, 945 unsigned int size, const void *valp) 946 { 947 sfxge_t *sp = arg; 948 int v8 = *(uint8_t *)valp; 949 int rc; 950 951 /* get size checks out fo the way */ 952 switch (id) { 953 /* 954 * On Sol11 (no updates) dladm seems to be using MAC_PROP_AUTONEG to set 955 * the autoneg parameter. This does not match the scheme suggested in 956 * mac(9E) but as they both map to the same think in the driver and in 957 * dladm it doesn't matter. 958 */ 959 case MAC_PROP_AUTONEG: 960 case MAC_PROP_EN_AUTONEG: 961 case MAC_PROP_EN_40GFDX_CAP: 962 case MAC_PROP_EN_10GFDX_CAP: 963 case MAC_PROP_EN_1000FDX_CAP: 964 case MAC_PROP_EN_1000HDX_CAP: 965 case MAC_PROP_EN_100FDX_CAP: 966 case MAC_PROP_EN_100HDX_CAP: 967 case MAC_PROP_EN_10FDX_CAP: 968 case MAC_PROP_EN_10HDX_CAP: 969 if (size < sizeof (uint8_t)) { 970 rc = EINVAL; 971 goto fail1; 972 } 973 break; 974 case MAC_PROP_MTU: 975 if (size < sizeof (uint32_t)) { 976 rc = EINVAL; 977 goto fail1; 978 } 979 break; 980 case MAC_PROP_FLOWCTRL: 981 if (size < sizeof (link_flowctrl_t)) { 982 rc = EINVAL; 983 goto fail1; 984 } 985 break; 986 case MAC_PROP_PRIVATE: 987 /* sfxge_gld_priv_prop_set should do any size checking */ 988 break; 989 default: 990 rc = ENOTSUP; 991 goto fail1; 992 } 993 994 switch (id) { 995 /* 996 * It is unclear which of MAC_PROP_AUTONEG and MAC_PROP_EN_AUTONEG is 997 * used. Try both. 998 */ 999 case MAC_PROP_AUTONEG: 1000 case MAC_PROP_EN_AUTONEG: 1001 if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_AN, v8)) != 0) 1002 goto fail2; 1003 break; 1004 case MAC_PROP_EN_40GFDX_CAP: 1005 if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_40000FDX, v8)) != 0) 1006 goto fail2; 1007 break; 1008 case MAC_PROP_EN_10GFDX_CAP: { 1009 if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_10000FDX, v8)) != 0) 1010 goto fail2; 1011 break; 1012 } 1013 case MAC_PROP_EN_1000FDX_CAP: { 1014 if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_1000FDX, v8)) != 0) 1015 goto fail2; 1016 break; 1017 } 1018 case MAC_PROP_EN_1000HDX_CAP: { 1019 if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_1000HDX, v8)) != 0) 1020 goto fail2; 1021 break; 1022 } 1023 case MAC_PROP_EN_100FDX_CAP: { 1024 if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_100FDX, v8)) != 0) 1025 goto fail2; 1026 break; 1027 } 1028 case MAC_PROP_EN_100HDX_CAP: { 1029 if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_100HDX, v8)) != 0) 1030 goto fail2; 1031 break; 1032 } 1033 case MAC_PROP_EN_10FDX_CAP: { 1034 if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_10FDX, v8)) != 0) 1035 goto fail2; 1036 break; 1037 } 1038 case MAC_PROP_EN_10HDX_CAP: { 1039 if ((rc = sfxge_phy_cap_set(sp, EFX_PHY_CAP_10HDX, v8)) != 0) 1040 goto fail2; 1041 break; 1042 } 1043 case MAC_PROP_MTU: { 1044 size_t mtu = (size_t)(*((uint32_t *)valp)); 1045 1046 if (mtu > EFX_MAC_SDU_MAX) { 1047 rc = EINVAL; 1048 goto fail2; 1049 } 1050 1051 sp->s_mtu = mtu; 1052 1053 DTRACE_PROBE(restart_mtu); 1054 (void) sfxge_restart_dispatch(sp, DDI_SLEEP, SFXGE_HW_OK, 1055 "MTU changing", (uint32_t)mtu); 1056 1057 break; 1058 } 1059 case MAC_PROP_FLOWCTRL: { 1060 unsigned int fcntl = 0; 1061 1062 switch (*((link_flowctrl_t *)valp)) { 1063 case LINK_FLOWCTRL_NONE: 1064 fcntl = 0; 1065 break; 1066 1067 case LINK_FLOWCTRL_RX: 1068 fcntl = EFX_FCNTL_GENERATE; 1069 break; 1070 1071 case LINK_FLOWCTRL_TX: 1072 fcntl = EFX_FCNTL_RESPOND; 1073 break; 1074 1075 case LINK_FLOWCTRL_BI: 1076 fcntl = EFX_FCNTL_GENERATE | EFX_FCNTL_RESPOND; 1077 break; 1078 1079 default: 1080 rc = EINVAL; 1081 goto fail2; 1082 } 1083 1084 if ((rc = sfxge_mac_fcntl_set(sp, fcntl)) != 0) 1085 goto fail3; 1086 1087 break; 1088 } 1089 case MAC_PROP_PRIVATE: 1090 if ((rc = sfxge_gld_priv_prop_set(sp, name, size, valp)) != 0) 1091 goto fail4; 1092 1093 break; 1094 default: 1095 rc = ENOTSUP; 1096 goto fail5; 1097 } 1098 1099 return (0); 1100 1101 fail5: 1102 DTRACE_PROBE(fail5); 1103 1104 fail4: 1105 DTRACE_PROBE(fail4); 1106 1107 fail3: 1108 DTRACE_PROBE(fail3); 1109 1110 fail2: 1111 DTRACE_PROBE(fail2); 1112 1113 fail1: 1114 DTRACE_PROBE1(fail1, int, rc); 1115 1116 return (rc); 1117 } 1118 1119 static void 1120 sfxge_gld_propinfo(void *arg, const char *name, mac_prop_id_t id, 1121 mac_prop_info_handle_t handle) 1122 { 1123 sfxge_t *sp = arg; 1124 efx_phy_cap_type_t phy_cap = EFX_PHY_CAP_INVALID; 1125 switch (id) { 1126 case MAC_PROP_DUPLEX: 1127 mac_prop_info_set_perm(handle, MAC_PROP_PERM_READ); 1128 return; 1129 case MAC_PROP_FLOWCTRL: 1130 mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW); 1131 mac_prop_info_set_default_link_flowctrl(handle, 1132 LINK_FLOWCTRL_BI); 1133 return; 1134 case MAC_PROP_SPEED: 1135 mac_prop_info_set_perm(handle, MAC_PROP_PERM_READ); 1136 return; 1137 case MAC_PROP_STATUS: 1138 mac_prop_info_set_perm(handle, MAC_PROP_PERM_READ); 1139 return; 1140 case MAC_PROP_MTU: { 1141 uint32_t mtu_default; 1142 mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW); 1143 mtu_default = ddi_prop_get_int(DDI_DEV_T_ANY, 1144 sp->s_dip, DDI_PROP_DONTPASS, "mtu", ETHERMTU); 1145 mac_prop_info_set_default_uint32(handle, mtu_default); 1146 return; 1147 } 1148 case MAC_PROP_PRIVATE: 1149 sfxge_gld_priv_prop_info(sp, name, handle); 1150 return; 1151 case MAC_PROP_EN_AUTONEG: 1152 case MAC_PROP_AUTONEG: 1153 phy_cap = EFX_PHY_CAP_AN; 1154 break; 1155 case MAC_PROP_EN_10GFDX_CAP: 1156 case MAC_PROP_ADV_10GFDX_CAP: 1157 phy_cap = EFX_PHY_CAP_10000FDX; 1158 break; 1159 case MAC_PROP_EN_1000FDX_CAP: 1160 case MAC_PROP_ADV_1000FDX_CAP: 1161 phy_cap = EFX_PHY_CAP_1000FDX; 1162 break; 1163 case MAC_PROP_EN_1000HDX_CAP: 1164 case MAC_PROP_ADV_1000HDX_CAP: 1165 phy_cap = EFX_PHY_CAP_1000HDX; 1166 break; 1167 case MAC_PROP_EN_100FDX_CAP: 1168 case MAC_PROP_ADV_100FDX_CAP: 1169 phy_cap = EFX_PHY_CAP_100FDX; 1170 break; 1171 case MAC_PROP_EN_100HDX_CAP: 1172 case MAC_PROP_ADV_100HDX_CAP: 1173 phy_cap = EFX_PHY_CAP_100HDX; 1174 break; 1175 case MAC_PROP_EN_10FDX_CAP: 1176 case MAC_PROP_ADV_10FDX_CAP: 1177 phy_cap = EFX_PHY_CAP_10FDX; 1178 break; 1179 case MAC_PROP_EN_10HDX_CAP: 1180 case MAC_PROP_ADV_10HDX_CAP: 1181 phy_cap = EFX_PHY_CAP_10HDX; 1182 break; 1183 default: 1184 DTRACE_PROBE(unknown_prop); 1185 return; 1186 } 1187 if (phy_cap != EFX_PHY_CAP_INVALID) { 1188 boolean_t rw; 1189 uint8_t cap_default; 1190 cap_default = sfxge_phy_cap_test(sp, EFX_PHY_CAP_DEFAULT, 1191 phy_cap, &rw); 1192 if (rw == B_TRUE) 1193 mac_prop_info_set_perm(handle, MAC_PROP_PERM_RW); 1194 else 1195 mac_prop_info_set_perm(handle, MAC_PROP_PERM_READ); 1196 mac_prop_info_set_default_uint8(handle, cap_default); 1197 } 1198 } 1199 1200 int 1201 sfxge_gld_register(sfxge_t *sp) 1202 { 1203 mac_callbacks_t *mcp; 1204 mac_register_t *mrp; 1205 mac_handle_t mh; 1206 int rc; 1207 1208 /* 1209 * NOTE: mac_register_t has additional fields in later kernels, 1210 * so the buffer returned by mac_alloc(9F) changes size. This 1211 * is not a problem for forward compatibility (a driver binary 1212 * built with older headers/libs running on a newer kernel). 1213 * 1214 * For Solaris 10, we build the sfxge driver on s10u9 to run on 1215 * s10u8, and later. This requries backward compatibility and 1216 * causes a problem. The mac_register_t in s10u8 is smaller than 1217 * the version in s10u9, so writing to the mc_margin field causes 1218 * a buffer overflow (and a hard-to-debug panic). 1219 * 1220 * Work around this problem by allocating mac_register_t using 1221 * kmem_alloc(9F) so it has the size expected by the driver. The 1222 * running kernel ignores the additional fields. 1223 * 1224 * Replace mac_alloc() with kmem_zalloc() and then set m_version. 1225 * Replace mac_free() with kmem_free(). 1226 * 1227 * See bug 33189 and bug33213 for details. 1228 */ 1229 if ((mrp = kmem_zalloc(sizeof (mac_register_t), KM_SLEEP)) == NULL) { 1230 rc = ENOMEM; 1231 goto fail1; 1232 } 1233 mrp->m_version = MAC_VERSION; 1234 1235 mrp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 1236 mrp->m_driver = sp; 1237 mrp->m_dip = sp->s_dip; 1238 1239 /* Set up the callbacks */ 1240 mcp = &(sp->s_mc); 1241 bzero(mcp, sizeof (mac_callbacks_t)); 1242 1243 mcp->mc_getstat = sfxge_gld_getstat; 1244 mcp->mc_start = sfxge_gld_start; 1245 mcp->mc_stop = sfxge_gld_stop; 1246 mcp->mc_setpromisc = sfxge_gld_setpromisc; 1247 mcp->mc_multicst = sfxge_gld_multicst; 1248 mcp->mc_unicst = sfxge_gld_unicst; 1249 mcp->mc_tx = sfxge_gld_tx; 1250 1251 mcp->mc_callbacks |= MC_IOCTL; 1252 mcp->mc_ioctl = sfxge_gld_ioctl; 1253 1254 mcp->mc_callbacks |= MC_GETCAPAB; 1255 mcp->mc_getcapab = sfxge_gld_getcapab; 1256 1257 /* NOTE: mc_setprop, mc_getprop, mc_propinfo added in s10u9 */ 1258 mcp->mc_callbacks |= MC_SETPROP; 1259 mcp->mc_setprop = sfxge_gld_setprop; 1260 1261 mcp->mc_callbacks |= MC_GETPROP; 1262 mcp->mc_getprop = sfxge_gld_getprop; 1263 1264 mcp->mc_callbacks |= MC_PROPINFO; 1265 mcp->mc_propinfo = sfxge_gld_propinfo; 1266 1267 mrp->m_callbacks = mcp; 1268 1269 mrp->m_src_addr = kmem_alloc(ETHERADDRL, KM_SLEEP); 1270 1271 if ((rc = sfxge_mac_unicst_get(sp, SFXGE_UNICST_BIA, 1272 mrp->m_src_addr)) != 0) 1273 goto fail2; 1274 1275 mrp->m_min_sdu = 0; 1276 mrp->m_max_sdu = sp->s_mtu; 1277 1278 mrp->m_margin = SFXGE_VLAN_TAGSZ; 1279 1280 /* Set up the private properties */ 1281 /* NOTE: m_priv_props added in s10u9 */ 1282 mrp->m_priv_props = sp->s_mac_priv_props; 1283 sfxge_gld_priv_prop_init(sp); 1284 1285 /* NOTE: m_flags added in s11.0 */ 1286 /* NOTE: m_multicast_sdu added in s11.0 */ 1287 1288 /* Register the interface */ 1289 if ((rc = mac_register(mrp, &mh)) != 0) 1290 goto fail3; 1291 1292 kmem_free(mrp->m_src_addr, ETHERADDRL); 1293 1294 /* Free the stack registration object */ 1295 kmem_free(mrp, sizeof (mac_register_t)); 1296 1297 sp->s_mh = mh; 1298 1299 return (0); 1300 fail3: 1301 DTRACE_PROBE(fail3); 1302 fail2: 1303 DTRACE_PROBE(fail2); 1304 1305 kmem_free(mrp->m_src_addr, ETHERADDRL); 1306 1307 /* Free the stack registration object */ 1308 kmem_free(mrp, sizeof (mac_register_t)); 1309 1310 /* Tear down the private properties */ 1311 sfxge_gld_priv_prop_fini(sp); 1312 1313 /* Clear the callbacks */ 1314 bzero(&(sp->s_mc), sizeof (mac_callbacks_t)); 1315 1316 fail1: 1317 DTRACE_PROBE1(fail1, int, rc); 1318 1319 return (rc); 1320 } 1321 1322 int 1323 sfxge_gld_unregister(sfxge_t *sp) 1324 { 1325 mac_handle_t mh = sp->s_mh; 1326 int rc; 1327 1328 if ((rc = mac_unregister(mh)) != 0) 1329 goto fail1; 1330 1331 sp->s_mh = NULL; 1332 1333 /* Tear down the private properties */ 1334 sfxge_gld_priv_prop_fini(sp); 1335 1336 /* Clear the callbacks */ 1337 bzero(&(sp->s_mc), sizeof (mac_callbacks_t)); 1338 1339 return (0); 1340 1341 fail1: 1342 DTRACE_PROBE1(fail1, int, rc); 1343 1344 return (rc); 1345 }