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