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