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