1 /*
   2  * Copyright (c) 2008-2016 Solarflare Communications Inc.
   3  * All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions are met:
   7  *
   8  * 1. Redistributions of source code must retain the above copyright notice,
   9  *    this list of conditions and the following disclaimer.
  10  * 2. Redistributions in binary form must reproduce the above copyright notice,
  11  *    this list of conditions and the following disclaimer in the documentation
  12  *    and/or other materials provided with the distribution.
  13  *
  14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  21  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  22  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  23  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  24  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25  *
  26  * The views and conclusions contained in the software and documentation are
  27  * those of the authors and should not be interpreted as representing official
  28  * policies, either expressed or implied, of the FreeBSD Project.
  29  */
  30 
  31 /*
  32  * All efx_mac_*() must be after efx_port_init()
  33  * LOCKING STRATEGY: Aquire sm_lock and test sm_state==SFXGE_MAC_STARTED
  34  * to serialise against sfxge_restart()
  35  */
  36 
  37 #include <sys/types.h>
  38 #include <sys/sysmacros.h>
  39 #include <sys/ddi.h>
  40 #include <sys/sunddi.h>
  41 
  42 #include "sfxge.h"
  43 #include "efx.h"
  44 
  45 #define SFXGE_MAC_POLL_PERIOD_MS 1000
  46 
  47 static void sfxge_mac_link_update_locked(sfxge_t *sp, efx_link_mode_t mode);
  48 
  49 
  50 /* MAC DMA attributes */
  51 static ddi_device_acc_attr_t sfxge_mac_devacc = {
  52 
  53         DDI_DEVICE_ATTR_V0,     /* devacc_attr_version */
  54         DDI_NEVERSWAP_ACC,      /* devacc_attr_endian_flags */
  55         DDI_STRICTORDER_ACC     /* devacc_attr_dataorder */
  56 };
  57 
  58 static ddi_dma_attr_t sfxge_mac_dma_attr = {
  59         DMA_ATTR_V0,            /* dma_attr_version     */
  60         0,                      /* dma_attr_addr_lo     */
  61         0xffffffffffffffffull,  /* dma_attr_addr_hi     */
  62         0xffffffffffffffffull,  /* dma_attr_count_max   */
  63         0x1000,                 /* dma_attr_align       */
  64         0xffffffff,             /* dma_attr_burstsizes  */
  65         1,                      /* dma_attr_minxfer     */
  66         0xffffffffffffffffull,  /* dma_attr_maxxfer     */
  67         0xffffffffffffffffull,  /* dma_attr_seg         */
  68         1,                      /* dma_attr_sgllen      */
  69         1,                      /* dma_attr_granular    */
  70         0                       /* dma_attr_flags       */
  71 };
  72 
  73 
  74 static void
  75 _sfxge_mac_stat_update(sfxge_mac_t *smp, int tries, int delay_usec)
  76 {
  77         sfxge_t *sp = smp->sm_sp;
  78         efsys_mem_t *esmp = &(smp->sm_mem);
  79         int i;
  80 
  81         ASSERT(mutex_owned(&(smp->sm_lock)));
  82         ASSERT3U(smp->sm_state, !=, SFXGE_MAC_UNINITIALIZED);
  83 
  84         /* if no stats pending then they are already freshly updated */
  85         if (smp->sm_mac_stats_timer_reqd && !smp->sm_mac_stats_pend)
  86                 return;
  87 
  88         for (i = 0; i < tries; i++) {
  89                 /* Try to update the cached counters */
  90                 if (efx_mac_stats_update(sp->s_enp, esmp, smp->sm_stat,
  91                     NULL) != EAGAIN)
  92                         goto done;
  93 
  94                 drv_usecwait(delay_usec);
  95         }
  96 
  97         DTRACE_PROBE(mac_stat_timeout);
  98         dev_err(sp->s_dip, CE_NOTE, SFXGE_CMN_ERR "MAC stats timeout");
  99         return;
 100 
 101 done:
 102         smp->sm_mac_stats_pend = B_FALSE;
 103         smp->sm_lbolt = ddi_get_lbolt();
 104 }
 105 
 106 static void
 107 sfxge_mac_stat_update_quick(sfxge_mac_t *smp)
 108 {
 109         /*
 110          * Update the statistics from the most recent DMA. This might race
 111          * with an inflight dma, so retry once. Otherwise get mac stat
 112          * values from the last mac_poll() or MC periodic stats.
 113          */
 114         _sfxge_mac_stat_update(smp, 2, 50);
 115 }
 116 
 117 static void
 118 sfxge_mac_stat_update_wait(sfxge_mac_t *smp)
 119 {
 120         /* Wait a max of 20 * 500us = 10ms */
 121         _sfxge_mac_stat_update(smp, 20, 500);
 122 }
 123 
 124 static int
 125 sfxge_mac_kstat_update(kstat_t *ksp, int rw)
 126 {
 127         sfxge_mac_t *smp = ksp->ks_private;
 128         kstat_named_t *knp;
 129         int rc;
 130         unsigned int val;
 131         sfxge_rx_coalesce_mode_t rxmode;
 132 
 133         if (rw != KSTAT_READ) {
 134                 rc = EACCES;
 135                 goto fail1;
 136         }
 137 
 138         ASSERT(mutex_owned(&(smp->sm_lock)));
 139 
 140         if (smp->sm_state != SFXGE_MAC_STARTED)
 141                 goto done;
 142 
 143         sfxge_mac_stat_update_quick(smp);
 144 
 145         knp = smp->sm_stat;
 146         knp += EFX_MAC_NSTATS;
 147 
 148         knp->value.ui64 = (smp->sm_link_up) ? 1 : 0;
 149         knp++;
 150 
 151         knp->value.ui64 = smp->sm_link_speed;
 152         knp++;
 153 
 154         knp->value.ui64 = smp->sm_link_duplex;
 155         knp++;
 156 
 157         knp->value.ui64 = (smp->sm_fcntl & EFX_FCNTL_GENERATE) ? 1 : 0;
 158         knp++;
 159 
 160         knp->value.ui64 = (smp->sm_fcntl & EFX_FCNTL_RESPOND) ? 1 : 0;
 161         knp++;
 162 
 163         sfxge_ev_moderation_get(smp->sm_sp, &val);
 164         knp->value.ui64 = val;
 165         knp++;
 166 
 167         sfxge_rx_coalesce_mode_get(smp->sm_sp, &rxmode);
 168         knp->value.ui64 = (uint64_t)rxmode;
 169         knp++;
 170 
 171         if (sfxge_rx_scale_count_get(smp->sm_sp, &val) != 0)
 172                 val = 0;
 173         knp->value.ui64 = val;
 174         knp++;
 175 
 176 done:
 177         return (0);
 178 
 179 fail1:
 180         DTRACE_PROBE1(fail1, int, rc);
 181 
 182         return (rc);
 183 }
 184 
 185 static int
 186 sfxge_mac_kstat_init(sfxge_t *sp)
 187 {
 188         sfxge_mac_t *smp = &(sp->s_mac);
 189         dev_info_t *dip = sp->s_dip;
 190         char name[MAXNAMELEN];
 191         kstat_t *ksp;
 192         kstat_named_t *knp;
 193         unsigned int id;
 194         int rc;
 195 
 196         /* Create the set */
 197         (void) snprintf(name, MAXNAMELEN - 1, "%s_mac", ddi_driver_name(dip));
 198 
 199         if ((ksp = kstat_create((char *)ddi_driver_name(dip),
 200             ddi_get_instance(dip), name, "mac", KSTAT_TYPE_NAMED,
 201             EFX_MAC_NSTATS + 8, 0)) == NULL) {
 202                 rc = ENOMEM;
 203                 goto fail1;
 204         }
 205 
 206         smp->sm_ksp = ksp;
 207 
 208         ksp->ks_update = sfxge_mac_kstat_update;
 209         ksp->ks_private = smp;
 210         ksp->ks_lock = &(smp->sm_lock);
 211 
 212         /* Initialise the named stats */
 213         smp->sm_stat = knp = ksp->ks_data;
 214         for (id = 0; id < EFX_MAC_NSTATS; id++) {
 215                 kstat_named_init(knp, (char *)efx_mac_stat_name(sp->s_enp, id),
 216                     KSTAT_DATA_UINT64);
 217                 knp++;
 218         }
 219 
 220         kstat_named_init(knp++, "link_up", KSTAT_DATA_UINT64);
 221         kstat_named_init(knp++, "link_speed", KSTAT_DATA_UINT64);
 222         kstat_named_init(knp++, "link_duplex", KSTAT_DATA_UINT64);
 223         kstat_named_init(knp++, "fcntl_generate", KSTAT_DATA_UINT64);
 224         kstat_named_init(knp++, "fcntl_respond", KSTAT_DATA_UINT64);
 225         kstat_named_init(knp++, "intr_moderation", KSTAT_DATA_UINT64);
 226         kstat_named_init(knp++, "rx_coalesce_mode", KSTAT_DATA_UINT64);
 227         kstat_named_init(knp++, "rx_scale_count", KSTAT_DATA_UINT64);
 228 
 229         kstat_install(ksp);
 230 
 231         return (0);
 232 
 233 fail1:
 234         DTRACE_PROBE1(fail1, int, rc);
 235 
 236         return (rc);
 237 }
 238 
 239 static void
 240 sfxge_mac_kstat_fini(sfxge_t *sp)
 241 {
 242         sfxge_mac_t *smp = &(sp->s_mac);
 243 
 244         /* Destroy the set */
 245         kstat_delete(smp->sm_ksp);
 246         smp->sm_ksp = NULL;
 247         smp->sm_stat = NULL;
 248 }
 249 
 250 void
 251 sfxge_mac_stat_get(sfxge_t *sp, unsigned int id, uint64_t *valp)
 252 {
 253         sfxge_mac_t *smp = &(sp->s_mac);
 254 
 255         /* Make sure the cached counter values are recent */
 256         mutex_enter(&(smp->sm_lock));
 257 
 258         if (smp->sm_state != SFXGE_MAC_STARTED)
 259                 goto done;
 260 
 261         sfxge_mac_stat_update_quick(smp);
 262 
 263         *valp = smp->sm_stat[id].value.ui64;
 264 
 265 done:
 266         mutex_exit(&(smp->sm_lock));
 267 }
 268 
 269 static void
 270 sfxge_mac_poll(void *arg)
 271 {
 272         sfxge_t *sp = arg;
 273         efx_nic_t *enp = sp->s_enp;
 274         sfxge_mac_t *smp = &(sp->s_mac);
 275         efsys_mem_t *esmp = &(smp->sm_mem);
 276         efx_link_mode_t mode;
 277         clock_t timeout;
 278 
 279         mutex_enter(&(smp->sm_lock));
 280         while (smp->sm_state == SFXGE_MAC_STARTED) {
 281 
 282                 /* clears smp->sm_mac_stats_pend if appropriate */
 283                 if (smp->sm_mac_stats_pend)
 284                         sfxge_mac_stat_update_wait(smp);
 285 
 286                 /* This may sleep waiting for MCDI completion */
 287                 mode = EFX_LINK_UNKNOWN;
 288                 if (efx_port_poll(enp, &mode) == 0)
 289                         sfxge_mac_link_update_locked(sp, mode);
 290 
 291                 if ((smp->sm_link_poll_reqd == B_FALSE) &&
 292                     (smp->sm_mac_stats_timer_reqd == B_FALSE))
 293                         goto done;
 294 
 295                 /* Zero the memory */
 296                 bzero(esmp->esm_base, EFX_MAC_STATS_SIZE);
 297 
 298                 /* Trigger upload the MAC statistics counters */
 299                 if (smp->sm_link_up &&
 300                     efx_mac_stats_upload(sp->s_enp, esmp) == 0)
 301                         smp->sm_mac_stats_pend = B_TRUE;
 302 
 303                 /* Wait for timeout or end of polling */
 304                 timeout = ddi_get_lbolt() + drv_usectohz(1000 *
 305                     SFXGE_MAC_POLL_PERIOD_MS);
 306                 while (smp->sm_state == SFXGE_MAC_STARTED) {
 307                         if (cv_timedwait(&(smp->sm_link_poll_kv),
 308                             &(smp->sm_lock), timeout) < 0) {
 309                                 /* Timeout - poll if polling still enabled */
 310                                 break;
 311                         }
 312                 }
 313         }
 314 done:
 315         mutex_exit(&(smp->sm_lock));
 316 
 317 }
 318 
 319 static void
 320 sfxge_mac_poll_start(sfxge_t *sp)
 321 {
 322         sfxge_mac_t *smp = &(sp->s_mac);
 323 
 324         ASSERT(mutex_owned(&(smp->sm_lock)));
 325         ASSERT3U(smp->sm_state, ==, SFXGE_MAC_STARTED);
 326 
 327         /* Schedule a poll */
 328         (void) ddi_taskq_dispatch(smp->sm_tqp, sfxge_mac_poll, sp, DDI_SLEEP);
 329 }
 330 
 331 static void
 332 sfxge_mac_poll_stop(sfxge_t *sp)
 333 {
 334         sfxge_mac_t *smp = &(sp->s_mac);
 335 
 336         ASSERT(mutex_owned(&(smp->sm_lock)));
 337         ASSERT3U(smp->sm_state, ==, SFXGE_MAC_INITIALIZED);
 338 
 339         cv_broadcast(&(smp->sm_link_poll_kv));
 340 
 341         /* Wait for link polling to cease */
 342         mutex_exit(&(smp->sm_lock));
 343         ddi_taskq_wait(smp->sm_tqp);
 344         mutex_enter(&(smp->sm_lock));
 345 
 346         /* Collect the final statistics. */
 347         sfxge_mac_stat_update_wait(smp);
 348 }
 349 
 350 int
 351 sfxge_mac_init(sfxge_t *sp)
 352 {
 353         sfxge_mac_t *smp = &(sp->s_mac);
 354         efsys_mem_t *esmp = &(smp->sm_mem);
 355         dev_info_t *dip = sp->s_dip;
 356         sfxge_dma_buffer_attr_t dma_attr;
 357         const efx_nic_cfg_t *encp;
 358         unsigned char *bytes;
 359         unsigned int n;
 360         int err, rc;
 361 
 362         SFXGE_OBJ_CHECK(smp, sfxge_mac_t);
 363 
 364         ASSERT3U(smp->sm_state, ==, SFXGE_MAC_UNINITIALIZED);
 365 
 366         smp->sm_sp = sp;
 367         encp = efx_nic_cfg_get(sp->s_enp);
 368         smp->sm_link_poll_reqd = (~encp->enc_features &
 369             EFX_FEATURE_LINK_EVENTS);
 370         smp->sm_mac_stats_timer_reqd = (~encp->enc_features &
 371             EFX_FEATURE_PERIODIC_MAC_STATS);
 372 
 373         mutex_init(&(smp->sm_lock), NULL, MUTEX_DRIVER,
 374             DDI_INTR_PRI(sp->s_intr.si_intr_pri));
 375         cv_init(&(smp->sm_link_poll_kv), NULL, CV_DRIVER, NULL);
 376 
 377         /* Create link poll taskq */
 378         smp->sm_tqp = ddi_taskq_create(dip, "mac_tq", 1, TASKQ_DEFAULTPRI, 0);
 379         if (smp->sm_tqp == NULL) {
 380                 rc = ENOMEM;
 381                 goto fail1;
 382         }
 383 
 384         if ((rc = sfxge_phy_init(sp)) != 0)
 385                 goto fail2;
 386 
 387         dma_attr.sdba_dip        = dip;
 388         dma_attr.sdba_dattrp     = &sfxge_mac_dma_attr;
 389         dma_attr.sdba_callback   = DDI_DMA_SLEEP;
 390         dma_attr.sdba_length     = EFX_MAC_STATS_SIZE;
 391         dma_attr.sdba_memflags   = DDI_DMA_CONSISTENT;
 392         dma_attr.sdba_devaccp    = &sfxge_mac_devacc;
 393         dma_attr.sdba_bindflags  = DDI_DMA_READ | DDI_DMA_CONSISTENT;
 394         dma_attr.sdba_maxcookies = 1;
 395         dma_attr.sdba_zeroinit   = B_TRUE;
 396 
 397         if ((rc = sfxge_dma_buffer_create(esmp, &dma_attr)) != 0)
 398                 goto fail3;
 399 
 400         /* Set the initial flow control values */
 401         smp->sm_fcntl = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
 402 
 403         /*
 404          * Determine the 'burnt-in' MAC address:
 405          *
 406          * A: if the "mac-address" property is set on our device node use that.
 407          * B: otherwise, use the value from NVRAM.
 408          */
 409 
 410         /* A: property  */
 411         err = ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
 412             "mac-address", &bytes, &n);
 413         switch (err) {
 414         case DDI_PROP_SUCCESS:
 415                 if (n == ETHERADDRL) {
 416                         bcopy(bytes, smp->sm_bia, ETHERADDRL);
 417                         goto done;
 418                 }
 419 
 420                 ddi_prop_free(bytes);
 421                 break;
 422 
 423         default:
 424                 break;
 425         }
 426 
 427         /* B: NVRAM */
 428         bcopy(encp->enc_mac_addr, smp->sm_bia, ETHERADDRL);
 429 
 430 done:
 431         /* Initialize the statistics */
 432         if ((rc = sfxge_mac_kstat_init(sp)) != 0)
 433                 goto fail4;
 434 
 435         if ((rc = sfxge_phy_kstat_init(sp)) != 0)
 436                 goto fail5;
 437 
 438         smp->sm_state = SFXGE_MAC_INITIALIZED;
 439 
 440         return (0);
 441 
 442 fail5:
 443         DTRACE_PROBE(fail5);
 444 
 445         sfxge_mac_kstat_fini(sp);
 446 fail4:
 447         DTRACE_PROBE(fail4);
 448 
 449         /* Tear down DMA setup */
 450         sfxge_dma_buffer_destroy(esmp);
 451 fail3:
 452         DTRACE_PROBE(fail3);
 453 
 454         sfxge_phy_fini(sp);
 455 fail2:
 456         DTRACE_PROBE(fail2);
 457 
 458         /* Destroy the link poll taskq */
 459         ddi_taskq_destroy(smp->sm_tqp);
 460         smp->sm_tqp = NULL;
 461 
 462 fail1:
 463         DTRACE_PROBE1(fail1, int, rc);
 464 
 465         cv_destroy(&(smp->sm_link_poll_kv));
 466 
 467         mutex_destroy(&(smp->sm_lock));
 468 
 469         smp->sm_sp = NULL;
 470 
 471         return (rc);
 472 }
 473 
 474 static int
 475 sfxge_mac_filter_apply(sfxge_t *sp)
 476 {
 477         efx_nic_t *enp = sp->s_enp;
 478         sfxge_mac_t *smp = &(sp->s_mac);
 479         int rc;
 480 
 481         ASSERT(mutex_owned(&(smp->sm_lock)));
 482 
 483         if (smp->sm_state == SFXGE_MAC_STARTED) {
 484                 boolean_t all_unicst;
 485                 boolean_t mulcst;
 486                 boolean_t all_mulcst;
 487                 boolean_t brdcst;
 488 
 489                 all_unicst = (smp->sm_promisc == SFXGE_PROMISC_ALL_PHYS);
 490                 mulcst = (smp->sm_mcast_count > 0);
 491                 all_mulcst = (smp->sm_promisc >= SFXGE_PROMISC_ALL_MULTI);
 492                 brdcst = B_TRUE;
 493 
 494                 if ((rc = efx_mac_filter_set(enp, all_unicst, mulcst,
 495                     all_mulcst, brdcst)) != 0) {
 496                         goto fail1;
 497                 }
 498                 if ((rc = efx_mac_multicast_list_set(enp,
 499                     smp->sm_mcast_addr, smp->sm_mcast_count)) != 0)
 500                         goto fail2;
 501         }
 502 
 503         return (0);
 504 
 505 fail2:
 506         DTRACE_PROBE(fail2);
 507 fail1:
 508         DTRACE_PROBE1(fail1, int, rc);
 509 
 510         return (rc);
 511 }
 512 
 513 int
 514 sfxge_mac_start(sfxge_t *sp, boolean_t restart)
 515 {
 516         sfxge_mac_t *smp = &(sp->s_mac);
 517         efsys_mem_t *esmp = &(smp->sm_mem);
 518         efx_nic_t *enp = sp->s_enp;
 519         size_t pdu;
 520         int rc;
 521 
 522         mutex_enter(&(smp->sm_lock));
 523 
 524         ASSERT3U(smp->sm_state, ==, SFXGE_MAC_INITIALIZED);
 525 
 526         if ((rc = efx_port_init(enp)) != 0)
 527                 goto fail1;
 528 
 529         /*
 530          * Set up the advertised capabilities that may have been asked for
 531          * before the call to efx_port_init().
 532          */
 533         if ((rc = sfxge_phy_cap_apply(sp, !restart)) != 0)
 534                 goto fail2;
 535 
 536         /* Set the SDU */
 537         pdu = EFX_MAC_PDU(sp->s_mtu);
 538         if ((rc = efx_mac_pdu_set(enp, pdu)) != 0)
 539                 goto fail3;
 540 
 541         if ((rc = efx_mac_fcntl_set(enp, smp->sm_fcntl, B_TRUE)) != 0)
 542                 goto fail4;
 543 
 544         /* Set the unicast address */
 545         if ((rc = efx_mac_addr_set(enp, (smp->sm_laa_valid) ?
 546             smp->sm_laa : smp->sm_bia)) != 0)
 547                 goto fail5;
 548 
 549         if ((rc = sfxge_mac_filter_apply(sp)) != 0)
 550                 goto fail6;
 551 
 552         if (!smp->sm_mac_stats_timer_reqd) {
 553                 if ((rc = efx_mac_stats_periodic(enp, esmp,
 554                     SFXGE_MAC_POLL_PERIOD_MS, B_FALSE)) != 0)
 555                         goto fail7;
 556         }
 557 
 558         if ((rc = efx_mac_drain(enp, B_FALSE)) != 0)
 559                 goto fail8;
 560 
 561         smp->sm_state = SFXGE_MAC_STARTED;
 562 
 563         /*
 564          * Start link state polling. For hardware that reports link change
 565          * events we still poll once to update the initial link state.
 566          */
 567         sfxge_mac_poll_start(sp);
 568 
 569         mutex_exit(&(smp->sm_lock));
 570         return (0);
 571 
 572 fail8:
 573         DTRACE_PROBE(fail8);
 574         (void) efx_mac_stats_periodic(enp, esmp, 0, B_FALSE);
 575 fail7:
 576         DTRACE_PROBE(fail7);
 577 fail6:
 578         DTRACE_PROBE(fail6);
 579 fail5:
 580         DTRACE_PROBE(fail5);
 581 fail4:
 582         DTRACE_PROBE(fail4);
 583 fail3:
 584         DTRACE_PROBE(fail3);
 585 fail2:
 586         DTRACE_PROBE(fail2);
 587         efx_port_fini(enp);
 588 fail1:
 589         DTRACE_PROBE1(fail1, int, rc);
 590 
 591         mutex_exit(&(smp->sm_lock));
 592 
 593         return (rc);
 594 }
 595 
 596 
 597 static void
 598 sfxge_mac_link_update_locked(sfxge_t *sp, efx_link_mode_t mode)
 599 {
 600         sfxge_mac_t *smp = &(sp->s_mac);
 601         const char *change, *duplex;
 602         char info[sizeof (": now 10000Mbps FULL duplex")];
 603 
 604         ASSERT(mutex_owned(&(smp->sm_lock)));
 605         if (smp->sm_state != SFXGE_MAC_STARTED)
 606                 return;
 607 
 608         if (smp->sm_link_mode == mode)
 609                 return;
 610 
 611         smp->sm_link_mode = mode;
 612         smp->sm_link_up = B_TRUE;
 613 
 614         switch (smp->sm_link_mode) {
 615         case EFX_LINK_UNKNOWN:
 616         case EFX_LINK_DOWN:
 617                 smp->sm_link_speed = 0;
 618                 smp->sm_link_duplex = SFXGE_LINK_DUPLEX_UNKNOWN;
 619                 smp->sm_link_up = B_FALSE;
 620                 break;
 621 
 622         case EFX_LINK_10HDX:
 623         case EFX_LINK_10FDX:
 624                 smp->sm_link_speed = 10;
 625                 smp->sm_link_duplex = (smp->sm_link_mode == EFX_LINK_10HDX) ?
 626                     SFXGE_LINK_DUPLEX_HALF : SFXGE_LINK_DUPLEX_FULL;
 627                 break;
 628 
 629         case EFX_LINK_100HDX:
 630         case EFX_LINK_100FDX:
 631                 smp->sm_link_speed = 100;
 632                 smp->sm_link_duplex = (smp->sm_link_mode == EFX_LINK_100HDX) ?
 633                     SFXGE_LINK_DUPLEX_HALF : SFXGE_LINK_DUPLEX_FULL;
 634                 break;
 635 
 636         case EFX_LINK_1000HDX:
 637         case EFX_LINK_1000FDX:
 638                 smp->sm_link_speed = 1000;
 639                 smp->sm_link_duplex = (smp->sm_link_mode == EFX_LINK_1000HDX) ?
 640                     SFXGE_LINK_DUPLEX_HALF : SFXGE_LINK_DUPLEX_FULL;
 641                 break;
 642 
 643         case EFX_LINK_10000FDX:
 644                 smp->sm_link_speed = 10000;
 645                 smp->sm_link_duplex = SFXGE_LINK_DUPLEX_FULL;
 646                 break;
 647 
 648         case EFX_LINK_40000FDX:
 649                 smp->sm_link_speed = 40000;
 650                 smp->sm_link_duplex = SFXGE_LINK_DUPLEX_FULL;
 651                 break;
 652 
 653         default:
 654                 ASSERT(B_FALSE);
 655                 break;
 656         }
 657 
 658         duplex = (smp->sm_link_duplex == SFXGE_LINK_DUPLEX_FULL) ?
 659             "full" : "half";
 660         change = (smp->sm_link_up) ? "UP" : "DOWN";
 661         (void) snprintf(info, sizeof (info), ": now %dMbps %s duplex",
 662             smp->sm_link_speed, duplex);
 663 
 664         dev_err(sp->s_dip, CE_NOTE, SFXGE_CMN_ERR "Link %s%s",
 665             change, smp->sm_link_up ? info : "");
 666 
 667         /* Push link state update to the OS */
 668         sfxge_gld_link_update(sp);
 669 }
 670 
 671 void
 672 sfxge_mac_link_update(sfxge_t *sp, efx_link_mode_t mode)
 673 {
 674         sfxge_mac_t *smp = &(sp->s_mac);
 675 
 676         mutex_enter(&(smp->sm_lock));
 677         sfxge_mac_link_update_locked(sp, mode);
 678         mutex_exit(&(smp->sm_lock));
 679 }
 680 
 681 void
 682 sfxge_mac_link_check(sfxge_t *sp, boolean_t *upp)
 683 {
 684         sfxge_mac_t *smp = &(sp->s_mac);
 685 
 686         mutex_enter(&(smp->sm_lock));
 687         *upp = smp->sm_link_up;
 688         mutex_exit(&(smp->sm_lock));
 689 }
 690 
 691 void
 692 sfxge_mac_link_speed_get(sfxge_t *sp, unsigned int *speedp)
 693 {
 694         sfxge_mac_t *smp = &(sp->s_mac);
 695 
 696         mutex_enter(&(smp->sm_lock));
 697         *speedp = smp->sm_link_speed;
 698         mutex_exit(&(smp->sm_lock));
 699 }
 700 
 701 void
 702 sfxge_mac_link_duplex_get(sfxge_t *sp, sfxge_link_duplex_t *duplexp)
 703 {
 704         sfxge_mac_t *smp = &(sp->s_mac);
 705 
 706         mutex_enter(&(smp->sm_lock));
 707         *duplexp = smp->sm_link_duplex;
 708         mutex_exit(&(smp->sm_lock));
 709 }
 710 
 711 void
 712 sfxge_mac_fcntl_get(sfxge_t *sp, unsigned int *fcntlp)
 713 {
 714         sfxge_mac_t *smp = &(sp->s_mac);
 715 
 716         mutex_enter(&(smp->sm_lock));
 717         *fcntlp = smp->sm_fcntl;
 718         mutex_exit(&(smp->sm_lock));
 719 }
 720 
 721 int
 722 sfxge_mac_fcntl_set(sfxge_t *sp, unsigned int fcntl)
 723 {
 724         sfxge_mac_t *smp = &(sp->s_mac);
 725         int rc;
 726 
 727         mutex_enter(&(smp->sm_lock));
 728 
 729         if (smp->sm_fcntl == fcntl)
 730                 goto done;
 731 
 732         smp->sm_fcntl = fcntl;
 733 
 734         if (smp->sm_state != SFXGE_MAC_STARTED)
 735                 goto done;
 736 
 737         if ((rc = efx_mac_fcntl_set(sp->s_enp, smp->sm_fcntl, B_TRUE)) != 0)
 738                 goto fail1;
 739 
 740 done:
 741         mutex_exit(&(smp->sm_lock));
 742 
 743         return (0);
 744 
 745 fail1:
 746         DTRACE_PROBE1(fail1, int, rc);
 747 
 748         mutex_exit(&(smp->sm_lock));
 749 
 750         return (rc);
 751 }
 752 
 753 int
 754 sfxge_mac_unicst_get(sfxge_t *sp, sfxge_unicst_type_t type, uint8_t *addr)
 755 {
 756         sfxge_mac_t *smp = &(sp->s_mac);
 757         int rc;
 758 
 759         if (type >= SFXGE_UNICST_NTYPES) {
 760                 rc = EINVAL;
 761                 goto fail1;
 762         }
 763 
 764         mutex_enter(&(smp->sm_lock));
 765 
 766         if (smp->sm_state != SFXGE_MAC_INITIALIZED &&
 767             smp->sm_state != SFXGE_MAC_STARTED) {
 768                 rc = EFAULT;
 769                 goto fail2;
 770         }
 771 
 772         switch (type) {
 773         case SFXGE_UNICST_BIA:
 774                 bcopy(smp->sm_bia, addr, ETHERADDRL);
 775                 break;
 776 
 777         case SFXGE_UNICST_LAA:
 778                 if (!(smp->sm_laa_valid)) {
 779                         rc = ENOENT;
 780                         goto fail3;
 781                 }
 782 
 783                 bcopy(smp->sm_laa, addr, ETHERADDRL);
 784                 break;
 785 
 786         default:
 787                 ASSERT(B_FALSE);
 788                 break;
 789         }
 790 
 791         mutex_exit(&(smp->sm_lock));
 792 
 793         return (0);
 794 
 795 
 796 fail3:
 797         DTRACE_PROBE(fail3);
 798 fail2:
 799         DTRACE_PROBE(fail2);
 800 
 801         mutex_exit(&(smp->sm_lock));
 802 
 803 fail1:
 804         DTRACE_PROBE1(fail1, int, rc);
 805 
 806         return (rc);
 807 }
 808 
 809 int
 810 sfxge_mac_unicst_set(sfxge_t *sp, uint8_t *addr)
 811 {
 812         sfxge_mac_t *smp = &(sp->s_mac);
 813         efx_nic_t *enp = sp->s_enp;
 814         boolean_t old_mac_valid;
 815         uint8_t old_mac[ETHERADDRL];
 816         int rc;
 817 
 818         mutex_enter(&(smp->sm_lock));
 819 
 820         old_mac_valid = smp->sm_laa_valid;
 821         if (old_mac_valid)
 822                 bcopy(smp->sm_laa, old_mac, ETHERADDRL);
 823 
 824         bcopy(addr, smp->sm_laa, ETHERADDRL);
 825         smp->sm_laa_valid = B_TRUE;
 826 
 827         if (smp->sm_state != SFXGE_MAC_STARTED)
 828                 goto done;
 829 
 830         if (efx_nic_cfg_get(enp)->enc_allow_set_mac_with_installed_filters) {
 831                 if ((rc = efx_mac_addr_set(enp, smp->sm_laa)) != 0) {
 832                         dev_err(sp->s_dip, CE_NOTE, SFXGE_CMN_ERR
 833                             "unable to set unicast MAC filter");
 834                         goto fail1;
 835                 }
 836         } else {
 837                 /* Older EF10 firmware requires a device start */
 838                 mutex_exit(&smp->sm_lock);
 839                 sfxge_stop(sp);
 840                 if ((rc = sfxge_start(sp, B_TRUE)) != 0) {
 841                         dev_err(sp->s_dip, CE_NOTE, SFXGE_CMN_ERR
 842                             "unable to restart with a new MAC");
 843                         mutex_enter(&(smp->sm_lock));
 844                         goto fail1;
 845                 }
 846                 mutex_enter(&smp->sm_lock);
 847         }
 848 
 849         if ((rc = efx_mac_addr_set(enp, smp->sm_laa)) != 0)
 850                 goto fail1;
 851 
 852 done:
 853         mutex_exit(&(smp->sm_lock));
 854 
 855         return (0);
 856 
 857 fail1:
 858         if (old_mac_valid)
 859                 bcopy(old_mac, smp->sm_laa, ETHERADDRL);
 860         else
 861                 smp->sm_laa_valid = B_FALSE;
 862 
 863         DTRACE_PROBE1(fail1, int, rc);
 864 
 865         mutex_exit(&(smp->sm_lock));
 866 
 867         return (rc);
 868 }
 869 
 870 int
 871 sfxge_mac_promisc_set(sfxge_t *sp, sfxge_promisc_type_t promisc)
 872 {
 873         sfxge_mac_t *smp = &(sp->s_mac);
 874         int rc;
 875 
 876         mutex_enter(&(smp->sm_lock));
 877 
 878         if (smp->sm_promisc == promisc)
 879                 goto done;
 880 
 881         smp->sm_promisc = promisc;
 882 
 883         if ((rc = sfxge_mac_filter_apply(sp)) != 0)
 884                 goto fail1;
 885 
 886 done:
 887         mutex_exit(&(smp->sm_lock));
 888         return (0);
 889 
 890 fail1:
 891         DTRACE_PROBE1(fail1, int, rc);
 892         mutex_exit(&(smp->sm_lock));
 893 
 894         return (rc);
 895 }
 896 
 897 int
 898 sfxge_mac_multicst_add(sfxge_t *sp, const uint8_t *addr)
 899 {
 900         sfxge_mac_t *smp = &(sp->s_mac);
 901         int i;
 902         int rc;
 903 
 904         mutex_enter(&(smp->sm_lock));
 905 
 906         if ((addr[0] & 0x1) == 0) {
 907                 rc = EINVAL;
 908                 goto fail1;
 909         }
 910 
 911         /* Check if the address is already in the list */
 912         i = 0;
 913         while (i < smp->sm_mcast_count) {
 914                 if (bcmp(smp->sm_mcast_addr + (i * ETHERADDRL),
 915                     addr, ETHERADDRL) == 0)
 916                         goto done;
 917                 else
 918                         i++;
 919         }
 920 
 921         if (smp->sm_mcast_count >= EFX_MAC_MULTICAST_LIST_MAX) {
 922                 rc = ENOENT;
 923                 goto fail1;
 924         }
 925 
 926         /* Add to the list */
 927         bcopy(addr, smp->sm_mcast_addr + (smp->sm_mcast_count++ * ETHERADDRL),
 928             ETHERADDRL);
 929 
 930         if ((rc = sfxge_mac_filter_apply(sp)) != 0)
 931                 goto fail2;
 932 
 933 done:
 934         mutex_exit(&(smp->sm_lock));
 935         return (0);
 936 
 937 fail2:
 938         DTRACE_PROBE(fail2);
 939         smp->sm_mcast_count--;
 940 fail1:
 941         DTRACE_PROBE1(fail1, int, rc);
 942         mutex_exit(&(smp->sm_lock));
 943 
 944         return (rc);
 945 }
 946 
 947 int
 948 sfxge_mac_multicst_remove(sfxge_t *sp, const uint8_t *addr)
 949 {
 950         sfxge_mac_t *smp = &(sp->s_mac);
 951         int i;
 952         int rc;
 953 
 954         mutex_enter(&(smp->sm_lock));
 955 
 956         i = 0;
 957         while (i < smp->sm_mcast_count) {
 958                 if (bcmp(smp->sm_mcast_addr + (i * ETHERADDRL),
 959                     addr, ETHERADDRL) == 0) {
 960                         (void) memmove(smp->sm_mcast_addr + (i * ETHERADDRL),
 961                             smp->sm_mcast_addr + ((i + 1) * ETHERADDRL),
 962                             (smp->sm_mcast_count - (i + 1)) * ETHERADDRL);
 963                         smp->sm_mcast_count--;
 964                 } else
 965                         i++;
 966         }
 967 
 968         if ((rc = sfxge_mac_filter_apply(sp)) != 0)
 969                 goto fail1;
 970 
 971         mutex_exit(&(smp->sm_lock));
 972         return (0);
 973 
 974 fail1:
 975         DTRACE_PROBE1(fail1, int, rc);
 976         mutex_exit(&(smp->sm_lock));
 977 
 978         return (rc);
 979 }
 980 
 981 void
 982 sfxge_mac_stop(sfxge_t *sp)
 983 {
 984         sfxge_mac_t *smp = &(sp->s_mac);
 985         efx_nic_t *enp = sp->s_enp;
 986         efsys_mem_t *esmp = &(smp->sm_mem);
 987 
 988         mutex_enter(&(smp->sm_lock));
 989 
 990         ASSERT3U(smp->sm_state, ==, SFXGE_MAC_STARTED);
 991         ASSERT3P(smp->sm_sp, ==, sp);
 992         smp->sm_state = SFXGE_MAC_INITIALIZED;
 993 
 994         /* If stopping in response to an MC reboot this may fail */
 995         if (!smp->sm_mac_stats_timer_reqd)
 996                 (void) efx_mac_stats_periodic(enp, esmp, 0, B_FALSE);
 997 
 998         sfxge_mac_poll_stop(sp);
 999 
1000         smp->sm_lbolt = 0;
1001 
1002         smp->sm_link_up = B_FALSE;
1003         smp->sm_link_speed = 0;
1004         smp->sm_link_duplex = SFXGE_LINK_DUPLEX_UNKNOWN;
1005 
1006         /* This may call MCDI */
1007         (void) efx_mac_drain(enp, B_TRUE);
1008 
1009         smp->sm_link_mode = EFX_LINK_UNKNOWN;
1010 
1011         efx_port_fini(enp);
1012 
1013         mutex_exit(&(smp->sm_lock));
1014 }
1015 
1016 void
1017 sfxge_mac_fini(sfxge_t *sp)
1018 {
1019         sfxge_mac_t *smp = &(sp->s_mac);
1020         efsys_mem_t *esmp = &(smp->sm_mem);
1021 
1022         ASSERT3U(smp->sm_state, ==, SFXGE_MAC_INITIALIZED);
1023         ASSERT3P(smp->sm_sp, ==, sp);
1024 
1025         /* Tear down the statistics */
1026         sfxge_phy_kstat_fini(sp);
1027         sfxge_mac_kstat_fini(sp);
1028 
1029         smp->sm_state = SFXGE_MAC_UNINITIALIZED;
1030         smp->sm_link_mode = EFX_LINK_UNKNOWN;
1031         smp->sm_promisc = SFXGE_PROMISC_OFF;
1032 
1033         bzero(smp->sm_mcast_addr, sizeof (smp->sm_mcast_addr));
1034         smp->sm_mcast_count = 0;
1035 
1036         bzero(smp->sm_laa, ETHERADDRL);
1037         smp->sm_laa_valid = B_FALSE;
1038 
1039         bzero(smp->sm_bia, ETHERADDRL);
1040 
1041         smp->sm_fcntl = 0;
1042 
1043         /* Finish with PHY DMA memory */
1044         sfxge_phy_fini(sp);
1045 
1046         /* Teardown the DMA */
1047         sfxge_dma_buffer_destroy(esmp);
1048 
1049         /* Destroy the link poll taskq */
1050         ddi_taskq_destroy(smp->sm_tqp);
1051         smp->sm_tqp = NULL;
1052 
1053         mutex_destroy(&(smp->sm_lock));
1054 
1055         smp->sm_sp = NULL;
1056 }