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 }