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/sysmacros.h>
  33 #include <sys/ddi.h>
  34 #include <sys/sunddi.h>
  35 #include <sys/stream.h>
  36 #include <sys/strsun.h>
  37 #include <sys/strsubr.h>
  38 #include <sys/cpu.h>
  39 #include <sys/pghw.h>
  40 
  41 #include "sfxge.h"
  42 
  43 #include "efx.h"
  44 
  45 
  46 /* Timeout to wait for DRIVER_EV_START event at EVQ startup */
  47 #define SFXGE_EV_QSTART_TIMEOUT_USEC    (2000000)
  48 
  49 
  50 /* Event queue DMA attributes */
  51 static ddi_device_acc_attr_t sfxge_evq_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_evq_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         EFX_BUF_SIZE,           /* 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 static int
  74 _sfxge_ev_qctor(sfxge_t *sp, sfxge_evq_t *sep, int kmflags, uint16_t evq_size)
  75 {
  76         efsys_mem_t *esmp = &(sep->se_mem);
  77         sfxge_dma_buffer_attr_t dma_attr;
  78         int rc;
  79 
  80         /* Compile-time structure layout checks */
  81         EFX_STATIC_ASSERT(sizeof (sep->__se_u1.__se_s1) <=
  82             sizeof (sep->__se_u1.__se_pad));
  83         EFX_STATIC_ASSERT(sizeof (sep->__se_u2.__se_s2) <=
  84             sizeof (sep->__se_u2.__se_pad));
  85         EFX_STATIC_ASSERT(sizeof (sep->__se_u3.__se_s3) <=
  86             sizeof (sep->__se_u3.__se_pad));
  87 
  88         bzero(sep, sizeof (sfxge_evq_t));
  89 
  90         sep->se_sp = sp;
  91 
  92         dma_attr.sdba_dip        = sp->s_dip;
  93         dma_attr.sdba_dattrp     = &sfxge_evq_dma_attr;
  94         dma_attr.sdba_callback   = (kmflags == KM_SLEEP) ?
  95             DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
  96         dma_attr.sdba_length     = EFX_EVQ_SIZE(evq_size);
  97         dma_attr.sdba_memflags   = DDI_DMA_CONSISTENT;
  98         dma_attr.sdba_devaccp    = &sfxge_evq_devacc;
  99         dma_attr.sdba_bindflags  = DDI_DMA_READ | DDI_DMA_CONSISTENT;
 100         dma_attr.sdba_maxcookies = 1;
 101         dma_attr.sdba_zeroinit   = B_FALSE;
 102 
 103         if ((rc = sfxge_dma_buffer_create(esmp, &dma_attr)) != 0)
 104                 goto fail1;
 105 
 106         /* Allocate some buffer table entries */
 107         if ((rc = sfxge_sram_buf_tbl_alloc(sp, EFX_EVQ_NBUFS(evq_size),
 108             &(sep->se_id))) != 0)
 109                 goto fail2;
 110 
 111         sep->se_stpp = &(sep->se_stp);
 112 
 113         return (0);
 114 
 115 fail2:
 116         DTRACE_PROBE(fail2);
 117 
 118         /* Tear down DMA setup */
 119         esmp->esm_addr = 0;
 120         sfxge_dma_buffer_destroy(esmp);
 121 
 122 fail1:
 123         DTRACE_PROBE1(fail1, int, rc);
 124 
 125         sep->se_sp = NULL;
 126 
 127         SFXGE_OBJ_CHECK(sep, sfxge_evq_t);
 128 
 129         return (-1);
 130 }
 131 
 132 static int
 133 sfxge_ev_q0ctor(void *buf, void *arg, int kmflags)
 134 {
 135         sfxge_evq_t *sep = buf;
 136         sfxge_t *sp = arg;
 137         return (_sfxge_ev_qctor(sp, sep, kmflags, sp->s_evq0_size));
 138 }
 139 
 140 static int
 141 sfxge_ev_qXctor(void *buf, void *arg, int kmflags)
 142 {
 143         sfxge_evq_t *sep = buf;
 144         sfxge_t *sp = arg;
 145         return (_sfxge_ev_qctor(sp, sep, kmflags, sp->s_evqX_size));
 146 }
 147 static void
 148 _sfxge_ev_qdtor(sfxge_t *sp, sfxge_evq_t *sep, uint16_t evq_size)
 149 {
 150         efsys_mem_t *esmp = &(sep->se_mem);
 151         ASSERT3P(sep->se_sp, ==, sp);
 152         ASSERT3P(sep->se_stpp, ==, &(sep->se_stp));
 153         sep->se_stpp = NULL;
 154 
 155         /* Free the buffer table entries */
 156         sfxge_sram_buf_tbl_free(sp, sep->se_id, EFX_EVQ_NBUFS(evq_size));
 157         sep->se_id = 0;
 158 
 159         /* Tear down DMA setup */
 160         sfxge_dma_buffer_destroy(esmp);
 161 
 162         sep->se_sp = NULL;
 163 
 164         SFXGE_OBJ_CHECK(sep, sfxge_evq_t);
 165 }
 166 
 167 static void
 168 sfxge_ev_q0dtor(void *buf, void *arg)
 169 {
 170         sfxge_evq_t *sep = buf;
 171         sfxge_t *sp = arg;
 172         _sfxge_ev_qdtor(sp, sep, sp->s_evq0_size);
 173 }
 174 
 175 static void
 176 sfxge_ev_qXdtor(void *buf, void *arg)
 177 {
 178         sfxge_evq_t *sep = buf;
 179         sfxge_t *sp = arg;
 180         _sfxge_ev_qdtor(sp, sep, sp->s_evqX_size);
 181 }
 182 
 183 static boolean_t
 184 sfxge_ev_initialized(void *arg)
 185 {
 186         sfxge_evq_t *sep = arg;
 187 
 188         ASSERT(mutex_owned(&(sep->se_lock)));
 189 
 190         /* Init done events may be duplicated on 7xxx (see SFCbug31631) */
 191         if (sep->se_state == SFXGE_EVQ_STARTED)
 192                 goto done;
 193 
 194         ASSERT3U(sep->se_state, ==, SFXGE_EVQ_STARTING);
 195         sep->se_state = SFXGE_EVQ_STARTED;
 196 
 197         cv_broadcast(&(sep->se_init_kv));
 198 
 199 done:
 200         return (B_FALSE);
 201 }
 202 
 203 static void
 204 sfxge_ev_qcomplete(sfxge_evq_t *sep, boolean_t eop)
 205 {
 206         sfxge_t *sp = sep->se_sp;
 207         unsigned int index = sep->se_index;
 208         sfxge_rxq_t *srp = sp->s_srp[index];
 209         sfxge_txq_t *stp;
 210 
 211         if ((stp = sep->se_stp) != NULL) {
 212                 sep->se_stp = NULL;
 213                 sep->se_stpp = &(sep->se_stp);
 214 
 215                 do {
 216                         sfxge_txq_t *next;
 217 
 218                         next = stp->st_next;
 219                         stp->st_next = NULL;
 220 
 221                         ASSERT3U(stp->st_evq, ==, index);
 222 
 223                         if (stp->st_pending != stp->st_completed)
 224                                 sfxge_tx_qcomplete(stp);
 225 
 226                         stp = next;
 227                 } while (stp != NULL);
 228         }
 229 
 230         if (srp != NULL) {
 231                 if (srp->sr_pending != srp->sr_completed)
 232                         sfxge_rx_qcomplete(srp, eop);
 233         }
 234 }
 235 
 236 static boolean_t
 237 sfxge_ev_rx(void *arg, uint32_t label, uint32_t id, uint32_t size,
 238     uint16_t flags)
 239 {
 240         sfxge_evq_t *sep = arg;
 241         sfxge_t *sp = sep->se_sp;
 242         sfxge_rxq_t *srp;
 243         sfxge_rx_packet_t *srpp;
 244         unsigned int prefetch;
 245         unsigned int stop;
 246         unsigned int delta;
 247 
 248         ASSERT(mutex_owned(&(sep->se_lock)));
 249 
 250         if (sep->se_exception)
 251                 goto done;
 252 
 253         srp = sp->s_srp[label];
 254         if (srp == NULL)
 255                 goto done;
 256 
 257         ASSERT3U(sep->se_index, ==, srp->sr_index);
 258         ASSERT3U(id, <, sp->s_rxq_size);
 259 
 260         /*
 261          * Note that in sfxge_stop() EVQ stopped after RXQ, and will be reset
 262          * So the return missing srp->sr_pending increase is safe
 263          */
 264         if (srp->sr_state != SFXGE_RXQ_STARTED)
 265                 goto done;
 266 
 267         stop = (id + 1) & (sp->s_rxq_size - 1);
 268         id = srp->sr_pending & (sp->s_rxq_size - 1);
 269 
 270         delta = (stop >= id) ? (stop - id) : (sp->s_rxq_size - id + stop);
 271         srp->sr_pending += delta;
 272 
 273         if (delta != 1) {
 274                 if ((!efx_nic_cfg_get(sp->s_enp)->enc_rx_batching_enabled) ||
 275                     (delta == 0) ||
 276                     (delta > efx_nic_cfg_get(sp->s_enp)->enc_rx_batch_max)) {
 277                         /*
 278                          * FIXME: This does not take into account scatter
 279                          * aborts.  See Bug40811
 280                          */
 281                         sep->se_exception = B_TRUE;
 282 
 283                         DTRACE_PROBE(restart_ev_rx_id);
 284                         /* sfxge_evq_t->se_lock held */
 285                         (void) sfxge_restart_dispatch(sp, DDI_SLEEP,
 286                             SFXGE_HW_ERR, "Out of order RX event", delta);
 287 
 288                         goto done;
 289                 }
 290         }
 291 
 292         prefetch = (id + 4) & (sp->s_rxq_size - 1);
 293         if ((srpp = srp->sr_srpp[prefetch]) != NULL)
 294                 prefetch_read_many(srpp);
 295 
 296         srpp = srp->sr_srpp[id];
 297         ASSERT(srpp != NULL);
 298         prefetch_read_many(srpp->srp_mp);
 299 
 300         for (; id != stop; id = (id + 1) & (sp->s_rxq_size - 1)) {
 301                 srpp = srp->sr_srpp[id];
 302                 ASSERT(srpp != NULL);
 303 
 304                 ASSERT3U(srpp->srp_flags, ==, EFX_DISCARD);
 305                 srpp->srp_flags = flags;
 306 
 307                 ASSERT3U(size, <, (1 << 16));
 308                 srpp->srp_size = (uint16_t)size;
 309         }
 310 
 311         sep->se_rx++;
 312 
 313         DTRACE_PROBE2(qlevel, unsigned int, srp->sr_index,
 314             unsigned int, srp->sr_added - srp->sr_pending);
 315 
 316         if (srp->sr_pending - srp->sr_completed >= SFXGE_RX_BATCH)
 317                 sfxge_ev_qcomplete(sep, B_FALSE);
 318 
 319 done:
 320         /* returning B_TRUE makes efx_ev_qpoll() stop processing events */
 321         return (sep->se_rx >= sep->se_ev_batch);
 322 }
 323 
 324 static boolean_t
 325 sfxge_ev_exception(void *arg, uint32_t code, uint32_t data)
 326 {
 327         sfxge_evq_t *sep = arg;
 328         sfxge_t *sp = sep->se_sp;
 329 
 330         _NOTE(ARGUNUSED(code))
 331         _NOTE(ARGUNUSED(data))
 332 
 333         ASSERT(mutex_owned(&(sep->se_lock)));
 334         sep->se_exception = B_TRUE;
 335 
 336         if (code != EFX_EXCEPTION_UNKNOWN_SENSOREVT) {
 337 
 338                 DTRACE_PROBE(restart_ev_exception);
 339 
 340                 /* sfxge_evq_t->se_lock held */
 341                 (void) sfxge_restart_dispatch(sp, DDI_SLEEP, SFXGE_HW_ERR,
 342                     "Unknown EV", code);
 343         }
 344 
 345         return (B_FALSE);
 346 }
 347 
 348 static boolean_t
 349 sfxge_ev_rxq_flush_done(void *arg, uint32_t rxq_index)
 350 {
 351         sfxge_evq_t *sep_targetq, *sep = arg;
 352         sfxge_t *sp = sep->se_sp;
 353         sfxge_rxq_t *srp;
 354         unsigned int index;
 355         unsigned int label;
 356         uint16_t magic;
 357 
 358         ASSERT(mutex_owned(&(sep->se_lock)));
 359 
 360         /* Ensure RXQ exists, as events may arrive after RXQ was destroyed */
 361         srp = sp->s_srp[rxq_index];
 362         if (srp == NULL)
 363                 goto done;
 364 
 365         /* Process right now if it is the correct event queue */
 366         index = srp->sr_index;
 367         if (index == sep->se_index) {
 368                 sfxge_rx_qflush_done(srp);
 369                 goto done;
 370         }
 371 
 372         /* Resend a software event on the correct queue */
 373         sep_targetq = sp->s_sep[index];
 374 
 375         if (sep_targetq->se_state != SFXGE_EVQ_STARTED)
 376                 goto done; /* TBD: state test not under the lock */
 377 
 378         label = rxq_index;
 379         ASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label);
 380         magic = SFXGE_MAGIC_RX_QFLUSH_DONE | label;
 381 
 382         efx_ev_qpost(sep_targetq->se_eep, magic);
 383 
 384 done:
 385         return (B_FALSE);
 386 }
 387 
 388 static boolean_t
 389 sfxge_ev_rxq_flush_failed(void *arg, uint32_t rxq_index)
 390 {
 391         sfxge_evq_t *sep_targetq, *sep = arg;
 392         sfxge_t *sp = sep->se_sp;
 393         sfxge_rxq_t *srp;
 394         unsigned int index;
 395         unsigned int label;
 396         uint16_t magic;
 397 
 398         ASSERT(mutex_owned(&(sep->se_lock)));
 399 
 400         /* Ensure RXQ exists, as events may arrive after RXQ was destroyed */
 401         srp = sp->s_srp[rxq_index];
 402         if (srp == NULL)
 403                 goto done;
 404 
 405         /* Process right now if it is the correct event queue */
 406         index = srp->sr_index;
 407         if (index == sep->se_index) {
 408                 sfxge_rx_qflush_failed(srp);
 409                 goto done;
 410         }
 411 
 412         /* Resend a software event on the correct queue */
 413         sep_targetq = sp->s_sep[index];
 414 
 415         label = rxq_index;
 416         ASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label);
 417         magic = SFXGE_MAGIC_RX_QFLUSH_FAILED | label;
 418 
 419         if (sep_targetq->se_state != SFXGE_EVQ_STARTED)
 420                 goto done; /* TBD: state test not under the lock */
 421 
 422         efx_ev_qpost(sep_targetq->se_eep, magic);
 423 
 424 done:
 425         return (B_FALSE);
 426 }
 427 
 428 static boolean_t
 429 sfxge_ev_tx(void *arg, uint32_t label, uint32_t id)
 430 {
 431         sfxge_evq_t *sep = arg;
 432         sfxge_txq_t *stp;
 433         unsigned int stop;
 434         unsigned int delta;
 435 
 436         ASSERT(mutex_owned(&(sep->se_lock)));
 437 
 438         stp = sep->se_label_stp[label];
 439         if (stp == NULL)
 440                 goto done;
 441 
 442         if (stp->st_state != SFXGE_TXQ_STARTED)
 443                 goto done;
 444 
 445         ASSERT3U(sep->se_index, ==, stp->st_evq);
 446 
 447         stop = (id + 1) & (SFXGE_TX_NDESCS - 1);
 448         id = stp->st_pending & (SFXGE_TX_NDESCS - 1);
 449 
 450         delta = (stop >= id) ? (stop - id) : (SFXGE_TX_NDESCS - id + stop);
 451         stp->st_pending += delta;
 452 
 453         sep->se_tx++;
 454 
 455         if (stp->st_next == NULL &&
 456             sep->se_stpp != &(stp->st_next)) {
 457                 *(sep->se_stpp) = stp;
 458                 sep->se_stpp = &(stp->st_next);
 459         }
 460 
 461         DTRACE_PROBE2(qlevel, unsigned int, stp->st_index,
 462             unsigned int, stp->st_added - stp->st_pending);
 463 
 464         if (stp->st_pending - stp->st_completed >= SFXGE_TX_BATCH)
 465                 sfxge_tx_qcomplete(stp);
 466 
 467 done:
 468         /* returning B_TRUE makes efx_ev_qpoll() stop processing events */
 469         return (sep->se_tx >= sep->se_ev_batch);
 470 }
 471 
 472 static boolean_t
 473 sfxge_ev_txq_flush_done(void *arg, uint32_t txq_index)
 474 {
 475         sfxge_evq_t *sep = arg;
 476         sfxge_t *sp = sep->se_sp;
 477         sfxge_txq_t *stp;
 478         unsigned int evq;
 479         unsigned int label;
 480         uint16_t magic;
 481 
 482         ASSERT(mutex_owned(&(sep->se_lock)));
 483 
 484         /* Ensure TXQ exists, as events may arrive after TXQ was destroyed */
 485         stp = sp->s_stp[txq_index];
 486         if (stp == NULL)
 487                 goto done;
 488 
 489         /* Process right now if it is the correct event queue */
 490         evq = stp->st_evq;
 491         if (evq == sep->se_index) {
 492                 sfxge_tx_qflush_done(stp);
 493                 goto done;
 494         }
 495 
 496         /* Resend a software event on the correct queue */
 497         sep = sp->s_sep[evq];
 498 
 499         label = stp->st_label;
 500 
 501         ASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label);
 502         magic = SFXGE_MAGIC_TX_QFLUSH_DONE | label;
 503 
 504         ASSERT3U(sep->se_state, ==, SFXGE_EVQ_STARTED);
 505         efx_ev_qpost(sep->se_eep, magic);
 506 
 507 done:
 508         return (B_FALSE);
 509 }
 510 
 511 static boolean_t
 512 sfxge_ev_software(void *arg, uint16_t magic)
 513 {
 514         sfxge_evq_t *sep = arg;
 515         sfxge_t *sp = sep->se_sp;
 516         dev_info_t *dip = sp->s_dip;
 517         unsigned int label;
 518 
 519         ASSERT(mutex_owned(&(sep->se_lock)));
 520 
 521         EFX_STATIC_ASSERT(SFXGE_MAGIC_DMAQ_LABEL_WIDTH ==
 522             FSF_AZ_RX_EV_Q_LABEL_WIDTH);
 523         EFX_STATIC_ASSERT(SFXGE_MAGIC_DMAQ_LABEL_WIDTH ==
 524             FSF_AZ_TX_EV_Q_LABEL_WIDTH);
 525 
 526         label = magic & SFXGE_MAGIC_DMAQ_LABEL_MASK;
 527         magic &= ~SFXGE_MAGIC_DMAQ_LABEL_MASK;
 528 
 529         switch (magic) {
 530         case SFXGE_MAGIC_RX_QFLUSH_DONE: {
 531                 sfxge_rxq_t *srp = sp->s_srp[label];
 532 
 533                 if (srp != NULL) {
 534                         ASSERT3U(sep->se_index, ==, srp->sr_index);
 535 
 536                         sfxge_rx_qflush_done(srp);
 537                 }
 538                 break;
 539         }
 540         case SFXGE_MAGIC_RX_QFLUSH_FAILED: {
 541                 sfxge_rxq_t *srp = sp->s_srp[label];
 542 
 543                 if (srp != NULL) {
 544                         ASSERT3U(sep->se_index, ==, srp->sr_index);
 545 
 546                         sfxge_rx_qflush_failed(srp);
 547                 }
 548                 break;
 549         }
 550         case SFXGE_MAGIC_RX_QFPP_TRIM: {
 551                 sfxge_rxq_t *srp = sp->s_srp[label];
 552 
 553                 if (srp != NULL) {
 554                         ASSERT3U(sep->se_index, ==, srp->sr_index);
 555 
 556                         sfxge_rx_qfpp_trim(srp);
 557                 }
 558                 break;
 559         }
 560         case SFXGE_MAGIC_TX_QFLUSH_DONE: {
 561                 sfxge_txq_t *stp = sep->se_label_stp[label];
 562 
 563                 if (stp != NULL) {
 564                         ASSERT3U(sep->se_index, ==, stp->st_evq);
 565 
 566                         sfxge_tx_qflush_done(stp);
 567                 }
 568                 break;
 569         }
 570         default:
 571                 dev_err(dip, CE_NOTE,
 572                     SFXGE_CMN_ERR "unknown software event 0x%x", magic);
 573                 break;
 574         }
 575 
 576         return (B_FALSE);
 577 }
 578 
 579 static boolean_t
 580 sfxge_ev_sram(void *arg, uint32_t code)
 581 {
 582         _NOTE(ARGUNUSED(arg))
 583 
 584         switch (code) {
 585         case EFX_SRAM_UPDATE:
 586                 DTRACE_PROBE(sram_update);
 587                 break;
 588 
 589         case EFX_SRAM_CLEAR:
 590                 DTRACE_PROBE(sram_clear);
 591                 break;
 592 
 593         case EFX_SRAM_ILLEGAL_CLEAR:
 594                 DTRACE_PROBE(sram_illegal_clear);
 595                 break;
 596 
 597         default:
 598                 ASSERT(B_FALSE);
 599                 break;
 600         }
 601 
 602         return (B_FALSE);
 603 }
 604 
 605 static boolean_t
 606 sfxge_ev_timer(void *arg, uint32_t index)
 607 {
 608         _NOTE(ARGUNUSED(arg, index))
 609 
 610         return (B_FALSE);
 611 }
 612 
 613 static boolean_t
 614 sfxge_ev_wake_up(void *arg, uint32_t index)
 615 {
 616         _NOTE(ARGUNUSED(arg, index))
 617 
 618         return (B_FALSE);
 619 }
 620 
 621 #if 0
 622 static boolean_t
 623 sfxge_ev_monitor(void)
 624 {
 625         _NOTE(ARGUNUSED(arg, id, value))
 626 
 627         return (B_FALSE);
 628 }
 629 #endif
 630 
 631 static boolean_t
 632 sfxge_ev_link_change(void *arg, efx_link_mode_t link_mode)
 633 {
 634         sfxge_evq_t *sep = arg;
 635         sfxge_t *sp = sep->se_sp;
 636 
 637         sfxge_mac_link_update(sp, link_mode);
 638 
 639         return (B_FALSE);
 640 }
 641 
 642 static int
 643 sfxge_ev_kstat_update(kstat_t *ksp, int rw)
 644 {
 645         sfxge_evq_t *sep = ksp->ks_private;
 646         kstat_named_t *knp;
 647         int rc;
 648 
 649         if (rw != KSTAT_READ) {
 650                 rc = EACCES;
 651                 goto fail1;
 652         }
 653 
 654         ASSERT(mutex_owned(&(sep->se_lock)));
 655 
 656         if (sep->se_state != SFXGE_EVQ_STARTED)
 657                 goto done;
 658 
 659         efx_ev_qstats_update(sep->se_eep, sep->se_stat);
 660 
 661         knp = ksp->ks_data;
 662         knp += EV_NQSTATS;
 663 
 664         knp->value.ui64 = sep->se_cpu_id;
 665 
 666 done:
 667         return (0);
 668 
 669 fail1:
 670         DTRACE_PROBE1(fail1, int, rc);
 671 
 672         return (rc);
 673 }
 674 
 675 static int
 676 sfxge_ev_kstat_init(sfxge_evq_t *sep)
 677 {
 678         sfxge_t *sp = sep->se_sp;
 679         unsigned int index = sep->se_index;
 680         dev_info_t *dip = sp->s_dip;
 681         kstat_t *ksp;
 682         kstat_named_t *knp;
 683         char name[MAXNAMELEN];
 684         unsigned int id;
 685         int rc;
 686 
 687         /* Determine the name */
 688         (void) snprintf(name, MAXNAMELEN - 1, "%s_evq%04d",
 689             ddi_driver_name(dip), index);
 690 
 691         /* Create the set */
 692         if ((ksp = kstat_create((char *)ddi_driver_name(dip),
 693             ddi_get_instance(dip), name, "queue", KSTAT_TYPE_NAMED,
 694             EV_NQSTATS + 1, 0)) == NULL) {
 695                 rc = ENOMEM;
 696                 goto fail1;
 697         }
 698 
 699         sep->se_ksp = ksp;
 700 
 701         ksp->ks_update = sfxge_ev_kstat_update;
 702         ksp->ks_private = sep;
 703         ksp->ks_lock = &(sep->se_lock);
 704 
 705         /* Initialise the named stats */
 706         sep->se_stat = knp = ksp->ks_data;
 707         for (id = 0; id < EV_NQSTATS; id++) {
 708                 kstat_named_init(knp, (char *)efx_ev_qstat_name(sp->s_enp, id),
 709                     KSTAT_DATA_UINT64);
 710                 knp++;
 711         }
 712 
 713         kstat_named_init(knp, "cpu", KSTAT_DATA_UINT64);
 714 
 715         kstat_install(ksp);
 716         return (0);
 717 
 718 fail1:
 719         DTRACE_PROBE1(fail1, int, rc);
 720 
 721         return (rc);
 722 }
 723 
 724 static void
 725 sfxge_ev_kstat_fini(sfxge_evq_t *sep)
 726 {
 727         /* Destroy the set */
 728         kstat_delete(sep->se_ksp);
 729         sep->se_ksp = NULL;
 730         sep->se_stat = NULL;
 731 }
 732 
 733 inline unsigned pow2_ge(unsigned int n) {
 734         unsigned int order = 0;
 735         ASSERT3U(n, >, 0);
 736         while ((1ul << order) < n) ++order;
 737         return (1ul << (order));
 738 }
 739 
 740 static int
 741 sfxge_ev_qinit(sfxge_t *sp, unsigned int index, unsigned int ev_batch)
 742 {
 743         sfxge_evq_t *sep;
 744         int rc;
 745 
 746         ASSERT3U(index, <, SFXGE_RX_SCALE_MAX);
 747 
 748         sep = kmem_cache_alloc(index ? sp->s_eqXc : sp->s_eq0c, KM_SLEEP);
 749         if (sep == NULL) {
 750                 rc = ENOMEM;
 751                 goto fail1;
 752         }
 753         ASSERT3U(sep->se_state, ==, SFXGE_EVQ_UNINITIALIZED);
 754 
 755         sep->se_index = index;
 756 
 757         mutex_init(&(sep->se_lock), NULL,
 758             MUTEX_DRIVER, DDI_INTR_PRI(sp->s_intr.si_intr_pri));
 759 
 760         cv_init(&(sep->se_init_kv), NULL, CV_DRIVER, NULL);
 761 
 762         /* Initialize the statistics */
 763         if ((rc = sfxge_ev_kstat_init(sep)) != 0)
 764                 goto fail2;
 765 
 766         sep->se_state = SFXGE_EVQ_INITIALIZED;
 767         sep->se_ev_batch = (uint16_t)ev_batch;
 768         sp->s_sep[index] = sep;
 769 
 770         return (0);
 771 
 772 fail2:
 773         DTRACE_PROBE(fail2);
 774 
 775         sep->se_index = 0;
 776 
 777         cv_destroy(&(sep->se_init_kv));
 778         mutex_destroy(&(sep->se_lock));
 779 
 780         kmem_cache_free(index ? sp->s_eqXc : sp->s_eq0c, sep);
 781 
 782 fail1:
 783         DTRACE_PROBE1(fail1, int, rc);
 784 
 785         return (rc);
 786 }
 787 
 788 static int
 789 sfxge_ev_qstart(sfxge_t *sp, unsigned int index)
 790 {
 791         sfxge_evq_t *sep = sp->s_sep[index];
 792         sfxge_intr_t *sip = &(sp->s_intr);
 793         efx_nic_t *enp = sp->s_enp;
 794         efx_ev_callbacks_t *eecp;
 795         efsys_mem_t *esmp;
 796         clock_t timeout;
 797         int rc;
 798         uint16_t evq_size = index ? sp->s_evqX_size : sp->s_evq0_size;
 799 
 800         mutex_enter(&(sep->se_lock));
 801         esmp = &(sep->se_mem);
 802 
 803         ASSERT3U(sep->se_state, ==, SFXGE_EVQ_INITIALIZED);
 804 
 805         /* Set the memory to all ones */
 806         (void) memset(esmp->esm_base, 0xff, EFX_EVQ_SIZE(evq_size));
 807 
 808         /* Program the buffer table */
 809         if ((rc = sfxge_sram_buf_tbl_set(sp, sep->se_id, esmp,
 810             EFX_EVQ_NBUFS(evq_size))) != 0)
 811                 goto fail1;
 812 
 813         /* Set up the event callbacks */
 814         eecp = &(sep->se_eec);
 815         eecp->eec_initialized = sfxge_ev_initialized;
 816         eecp->eec_rx = sfxge_ev_rx;
 817         eecp->eec_tx = sfxge_ev_tx;
 818         eecp->eec_exception = sfxge_ev_exception;
 819         eecp->eec_rxq_flush_done = sfxge_ev_rxq_flush_done;
 820         eecp->eec_rxq_flush_failed = sfxge_ev_rxq_flush_failed;
 821         eecp->eec_txq_flush_done = sfxge_ev_txq_flush_done;
 822         eecp->eec_software = sfxge_ev_software;
 823         eecp->eec_sram = sfxge_ev_sram;
 824         eecp->eec_wake_up = sfxge_ev_wake_up;
 825         eecp->eec_timer = sfxge_ev_timer;
 826         eecp->eec_link_change = sfxge_ev_link_change;
 827 #if 0
 828         eecp->eec_monitor = (void *)sfxge_ev_monitor;
 829 #endif
 830 
 831         /* Create the event queue */
 832         if ((rc = efx_ev_qcreate(enp, index, esmp, evq_size, sep->se_id,
 833             &(sep->se_eep))) != 0)
 834                 goto fail2;
 835 
 836         /* Set the default moderation */
 837         if ((rc = efx_ev_qmoderate(sep->se_eep, sp->s_ev_moderation)) != 0)
 838                 goto fail3;
 839 
 840         /* Check that interrupts are enabled at the NIC */
 841         if (sip->si_state != SFXGE_INTR_STARTED) {
 842                 rc = EINVAL;
 843                 goto fail4;
 844         }
 845 
 846         sep->se_state = SFXGE_EVQ_STARTING;
 847 
 848         /* Prime the event queue for interrupts */
 849         if ((rc = efx_ev_qprime(sep->se_eep, sep->se_count)) != 0)
 850                 goto fail5;
 851 
 852         /* Wait for the initialization event */
 853         timeout = ddi_get_lbolt() + drv_usectohz(SFXGE_EV_QSTART_TIMEOUT_USEC);
 854         while (sep->se_state != SFXGE_EVQ_STARTED) {
 855                 if (cv_timedwait(&(sep->se_init_kv), &(sep->se_lock),
 856                     timeout) < 0) {
 857                         /* Timeout waiting for initialization */
 858                         dev_info_t *dip = sp->s_dip;
 859 
 860                         DTRACE_PROBE(timeout);
 861                         dev_err(dip, CE_NOTE,
 862                             SFXGE_CMN_ERR "evq[%d] qstart timeout", index);
 863 
 864                         rc = ETIMEDOUT;
 865                         goto fail6;
 866                 }
 867         }
 868 
 869         mutex_exit(&(sep->se_lock));
 870         return (0);
 871 
 872 fail6:
 873         DTRACE_PROBE(fail6);
 874 
 875 fail5:
 876         DTRACE_PROBE(fail5);
 877 
 878         sep->se_state = SFXGE_EVQ_INITIALIZED;
 879 
 880 fail4:
 881         DTRACE_PROBE(fail4);
 882 
 883 fail3:
 884         DTRACE_PROBE(fail3);
 885 
 886         /* Destroy the event queue */
 887         efx_ev_qdestroy(sep->se_eep);
 888         sep->se_eep = NULL;
 889 
 890 fail2:
 891         DTRACE_PROBE(fail2);
 892 
 893         /* Zero out the event handlers */
 894         bzero(&(sep->se_eec), sizeof (efx_ev_callbacks_t));
 895 
 896         /* Clear entries from the buffer table */
 897         sfxge_sram_buf_tbl_clear(sp, sep->se_id, EFX_EVQ_NBUFS(evq_size));
 898 
 899 fail1:
 900         DTRACE_PROBE1(fail1, int, rc);
 901 
 902         mutex_exit(&(sep->se_lock));
 903 
 904         return (rc);
 905 }
 906 
 907 int
 908 sfxge_ev_qpoll(sfxge_t *sp, unsigned int index)
 909 {
 910         sfxge_evq_t *sep = sp->s_sep[index];
 911         processorid_t cpu_id;
 912         int rc;
 913         uint16_t evq_size = index ? sp->s_evqX_size : sp->s_evq0_size;
 914 
 915         mutex_enter(&(sep->se_lock));
 916 
 917         if (sep->se_state != SFXGE_EVQ_STARTING &&
 918             sep->se_state != SFXGE_EVQ_STARTED) {
 919                 rc = EINVAL;
 920                 goto fail1;
 921         }
 922 
 923         /* Make sure the CPU information is up to date */
 924         cpu_id = CPU->cpu_id;
 925 
 926         if (cpu_id != sep->se_cpu_id) {
 927                 sep->se_cpu_id = cpu_id;
 928 
 929                 /* sfxge_evq_t->se_lock held */
 930                 (void) ddi_taskq_dispatch(sp->s_tqp, sfxge_rx_scale_update, sp,
 931                     DDI_NOSLEEP);
 932         }
 933 
 934         /* Synchronize the DMA memory for reading */
 935         (void) ddi_dma_sync(sep->se_mem.esm_dma_handle,
 936             0,
 937             EFX_EVQ_SIZE(evq_size),
 938             DDI_DMA_SYNC_FORKERNEL);
 939 
 940         ASSERT3U(sep->se_rx, ==, 0);
 941         ASSERT3U(sep->se_tx, ==, 0);
 942         ASSERT3P(sep->se_stp, ==, NULL);
 943         ASSERT3P(sep->se_stpp, ==, &(sep->se_stp));
 944 
 945         /* Poll the queue */
 946         efx_ev_qpoll(sep->se_eep, &(sep->se_count), &(sep->se_eec),
 947             sep);
 948 
 949         sep->se_rx = 0;
 950         sep->se_tx = 0;
 951 
 952         /* Perform any pending completion processing */
 953         sfxge_ev_qcomplete(sep, B_TRUE);
 954 
 955         /* Re-prime the event queue for interrupts */
 956         if ((rc = efx_ev_qprime(sep->se_eep, sep->se_count)) != 0)
 957                 goto fail2;
 958 
 959         mutex_exit(&(sep->se_lock));
 960 
 961         return (0);
 962 
 963 fail2:
 964         DTRACE_PROBE(fail2);
 965 fail1:
 966         DTRACE_PROBE1(fail1, int, rc);
 967 
 968         mutex_exit(&(sep->se_lock));
 969 
 970         return (rc);
 971 }
 972 
 973 int
 974 sfxge_ev_qprime(sfxge_t *sp, unsigned int index)
 975 {
 976         sfxge_evq_t *sep = sp->s_sep[index];
 977         int rc;
 978 
 979         mutex_enter(&(sep->se_lock));
 980 
 981         if (sep->se_state != SFXGE_EVQ_STARTING &&
 982             sep->se_state != SFXGE_EVQ_STARTED) {
 983                 rc = EINVAL;
 984                 goto fail1;
 985         }
 986 
 987         if ((rc = efx_ev_qprime(sep->se_eep, sep->se_count)) != 0)
 988                 goto fail2;
 989 
 990         mutex_exit(&(sep->se_lock));
 991 
 992         return (0);
 993 
 994 fail2:
 995         DTRACE_PROBE(fail2);
 996 fail1:
 997         DTRACE_PROBE1(fail1, int, rc);
 998 
 999         mutex_exit(&(sep->se_lock));
1000 
1001         return (rc);
1002 }
1003 
1004 
1005 int
1006 sfxge_ev_qmoderate(sfxge_t *sp, unsigned int index, unsigned int us)
1007 {
1008         sfxge_evq_t *sep = sp->s_sep[index];
1009         efx_evq_t *eep = sep->se_eep;
1010 
1011         ASSERT3U(sep->se_state, ==, SFXGE_EVQ_STARTED);
1012 
1013         return (efx_ev_qmoderate(eep, us));
1014 }
1015 
1016 static void
1017 sfxge_ev_qstop(sfxge_t *sp, unsigned int index)
1018 {
1019         sfxge_evq_t *sep = sp->s_sep[index];
1020         uint16_t evq_size;
1021 
1022         mutex_enter(&(sep->se_lock));
1023         ASSERT3U(sep->se_state, ==, SFXGE_EVQ_STARTED);
1024         sep->se_state = SFXGE_EVQ_INITIALIZED;
1025         evq_size = index ? sp->s_evqX_size : sp->s_evq0_size;
1026 
1027         /* Clear the CPU information */
1028         sep->se_cpu_id = 0;
1029 
1030         /* Clear the event count */
1031         sep->se_count = 0;
1032 
1033         /* Reset the exception flag */
1034         sep->se_exception = B_FALSE;
1035 
1036         /* Destroy the event queue */
1037         efx_ev_qdestroy(sep->se_eep);
1038         sep->se_eep = NULL;
1039 
1040         mutex_exit(&(sep->se_lock));
1041 
1042         /* Zero out the event handlers */
1043         bzero(&(sep->se_eec), sizeof (efx_ev_callbacks_t));
1044 
1045         /* Clear entries from the buffer table */
1046         sfxge_sram_buf_tbl_clear(sp, sep->se_id, EFX_EVQ_NBUFS(evq_size));
1047 }
1048 
1049 static void
1050 sfxge_ev_qfini(sfxge_t *sp, unsigned int index)
1051 {
1052         sfxge_evq_t *sep = sp->s_sep[index];
1053 
1054         ASSERT3U(sep->se_state, ==, SFXGE_EVQ_INITIALIZED);
1055 
1056         sp->s_sep[index] = NULL;
1057         sep->se_state = SFXGE_EVQ_UNINITIALIZED;
1058 
1059         /* Tear down the statistics */
1060         sfxge_ev_kstat_fini(sep);
1061 
1062         cv_destroy(&(sep->se_init_kv));
1063         mutex_destroy(&(sep->se_lock));
1064 
1065         sep->se_index = 0;
1066 
1067         kmem_cache_free(index ? sp->s_eqXc : sp->s_eq0c, sep);
1068 }
1069 
1070 int
1071 sfxge_ev_txlabel_alloc(sfxge_t *sp, unsigned int evq, sfxge_txq_t *stp,
1072     unsigned int *labelp)
1073 {
1074         sfxge_evq_t *sep = sp->s_sep[evq];
1075         sfxge_txq_t **stpp;
1076         unsigned int label;
1077         int rc;
1078 
1079         mutex_enter(&(sep->se_lock));
1080 
1081         if (stp == NULL || labelp == NULL) {
1082                 rc = EINVAL;
1083                 goto fail1;
1084         }
1085 
1086         stpp = NULL;
1087         for (label = 0; label < SFXGE_TX_NLABELS; label++) {
1088                 if (sep->se_label_stp[label] == stp) {
1089                         rc = EEXIST;
1090                         goto fail2;
1091                 }
1092                 if ((stpp == NULL) && (sep->se_label_stp[label] == NULL)) {
1093                         stpp = &sep->se_label_stp[label];
1094                 }
1095         }
1096         if (stpp == NULL) {
1097                 rc = ENOSPC;
1098                 goto fail3;
1099         }
1100         *stpp = stp;
1101         label = stpp - sep->se_label_stp;
1102 
1103         ASSERT3U(label, <, SFXGE_TX_NLABELS);
1104         *labelp = label;
1105 
1106         mutex_exit(&(sep->se_lock));
1107         return (0);
1108 
1109 fail3:
1110         DTRACE_PROBE(fail3);
1111 fail2:
1112         DTRACE_PROBE(fail2);
1113 fail1:
1114         DTRACE_PROBE1(fail1, int, rc);
1115 
1116         mutex_exit(&(sep->se_lock));
1117 
1118         return (rc);
1119 }
1120 
1121 
1122 int
1123 sfxge_ev_txlabel_free(sfxge_t *sp, unsigned int evq, sfxge_txq_t *stp,
1124     unsigned int label)
1125 {
1126         sfxge_evq_t *sep = sp->s_sep[evq];
1127         int rc;
1128 
1129         mutex_enter(&(sep->se_lock));
1130 
1131         if (stp == NULL || label > SFXGE_TX_NLABELS) {
1132                 rc = EINVAL;
1133                 goto fail1;
1134         }
1135 
1136         if (sep->se_label_stp[label] != stp) {
1137                 rc = EINVAL;
1138                 goto fail2;
1139         }
1140         sep->se_label_stp[label] = NULL;
1141 
1142         mutex_exit(&(sep->se_lock));
1143 
1144         return (0);
1145 
1146 fail2:
1147         DTRACE_PROBE(fail2);
1148 fail1:
1149         DTRACE_PROBE1(fail1, int, rc);
1150 
1151         mutex_exit(&(sep->se_lock));
1152 
1153         return (rc);
1154 }
1155 
1156 
1157 static  kmem_cache_t *
1158 sfxge_ev_kmem_cache_create(sfxge_t *sp, const char *qname,
1159     int (*ctor)(void *, void *, int), void (*dtor)(void *, void *))
1160 {
1161         char name[MAXNAMELEN];
1162         kmem_cache_t *eqc;
1163 
1164         (void) snprintf(name, MAXNAMELEN - 1, "%s%d_%s_cache",
1165             ddi_driver_name(sp->s_dip), ddi_get_instance(sp->s_dip), qname);
1166 
1167         eqc = kmem_cache_create(name, sizeof (sfxge_evq_t),
1168             SFXGE_CPU_CACHE_SIZE, ctor, dtor, NULL, sp, NULL, 0);
1169         ASSERT(eqc != NULL);
1170         return (eqc);
1171 }
1172 
1173 int
1174 sfxge_ev_init(sfxge_t *sp)
1175 {
1176         sfxge_intr_t *sip = &(sp->s_intr);
1177         unsigned int evq0_size;
1178         unsigned int evqX_size;
1179         unsigned int ev_batch;
1180         int index;
1181         int rc;
1182 
1183         ASSERT3U(sip->si_state, ==, SFXGE_INTR_INITIALIZED);
1184 
1185         /*
1186          * Must account for RXQ, TXQ(s); MCDI not event completed at present
1187          * Note that common code does not completely fill descriptor queues
1188          */
1189         evqX_size = sp->s_rxq_size + SFXGE_TX_NDESCS;
1190         evq0_size = evqX_size + SFXGE_TX_NDESCS; /* only IP checksum TXQ */
1191         evq0_size += SFXGE_TX_NDESCS; /* no checksums */
1192 
1193         ASSERT3U(evqX_size, >=, EFX_EVQ_MINNEVS);
1194         ASSERT3U(evq0_size, >, evqX_size);
1195 
1196         if (evq0_size > EFX_EVQ_MAXNEVS) {
1197                 rc = EINVAL;
1198                 goto fail1;
1199         }
1200 
1201         sp->s_evq0_size = pow2_ge(evq0_size);
1202         sp->s_evqX_size = pow2_ge(evqX_size);
1203 
1204         /* Read driver parameters */
1205         sp->s_ev_moderation = ddi_prop_get_int(DDI_DEV_T_ANY, sp->s_dip,
1206             DDI_PROP_DONTPASS, "intr_moderation", SFXGE_DEFAULT_MODERATION);
1207 
1208         ev_batch = ddi_prop_get_int(DDI_DEV_T_ANY, sp->s_dip,
1209             DDI_PROP_DONTPASS, "ev_batch", SFXGE_EV_BATCH);
1210 
1211         /*
1212          * It is slightly peverse to have a cache for one item. But it allows
1213          * for simple alignment control without increasing the allocation size
1214          */
1215         sp->s_eq0c = sfxge_ev_kmem_cache_create(sp, "evq0", sfxge_ev_q0ctor,
1216             sfxge_ev_q0dtor);
1217         sp->s_eqXc = sfxge_ev_kmem_cache_create(sp, "evqX", sfxge_ev_qXctor,
1218             sfxge_ev_qXdtor);
1219 
1220         /* Initialize the event queue(s) */
1221         for (index = 0; index < sip->si_nalloc; index++) {
1222                 if ((rc = sfxge_ev_qinit(sp, index, ev_batch)) != 0)
1223                         goto fail2;
1224         }
1225 
1226         return (0);
1227 
1228 fail2:
1229         DTRACE_PROBE(fail2);
1230 
1231         while (--index >= 0)
1232                 sfxge_ev_qfini(sp, index);
1233         sp->s_ev_moderation = 0;
1234 
1235 fail1:
1236         DTRACE_PROBE1(fail1, int, rc);
1237 
1238         kmem_cache_destroy(sp->s_eqXc);
1239         kmem_cache_destroy(sp->s_eq0c);
1240         sp->s_eqXc = NULL;
1241         sp->s_eq0c = NULL;
1242 
1243         return (rc);
1244 }
1245 
1246 int
1247 sfxge_ev_start(sfxge_t *sp)
1248 {
1249         sfxge_intr_t *sip = &(sp->s_intr);
1250         efx_nic_t *enp = sp->s_enp;
1251         int index;
1252         int rc;
1253 
1254         ASSERT3U(sip->si_state, ==, SFXGE_INTR_STARTED);
1255 
1256         /* Initialize the event module */
1257         if ((rc = efx_ev_init(enp)) != 0)
1258                 goto fail1;
1259 
1260         /* Start the event queues */
1261         for (index = 0; index < sip->si_nalloc; index++) {
1262                 if ((rc = sfxge_ev_qstart(sp, index)) != 0)
1263                         goto fail2;
1264         }
1265 
1266         return (0);
1267 
1268 fail2:
1269         DTRACE_PROBE(fail2);
1270 
1271         /* Stop the event queue(s) */
1272         while (--index >= 0)
1273                 sfxge_ev_qstop(sp, index);
1274 
1275         /* Tear down the event module */
1276         efx_ev_fini(enp);
1277 
1278 fail1:
1279         DTRACE_PROBE1(fail1, int, rc);
1280 
1281         return (rc);
1282 }
1283 
1284 void
1285 sfxge_ev_moderation_get(sfxge_t *sp, unsigned int *usp)
1286 {
1287         *usp = sp->s_ev_moderation;
1288 }
1289 
1290 int
1291 sfxge_ev_moderation_set(sfxge_t *sp, unsigned int us)
1292 {
1293         sfxge_intr_t *sip = &(sp->s_intr);
1294         int index;
1295         int rc;
1296 
1297         if (sip->si_state != SFXGE_INTR_STARTED)
1298                 return (ENODEV);
1299 
1300         for (index = 0; index < sip->si_nalloc; index++) {
1301                 if ((rc = sfxge_ev_qmoderate(sp, index, us)) != 0)
1302                         goto fail1;
1303         }
1304 
1305         sp->s_ev_moderation = us;
1306         return (0);
1307 
1308 fail1:
1309         DTRACE_PROBE1(fail1, int, rc);
1310 
1311         /*  The only error path is if the value to set to is invalid. */
1312         ASSERT3U(index, ==, 0);
1313 
1314         return (rc);
1315 }
1316 
1317 void
1318 sfxge_ev_stop(sfxge_t *sp)
1319 {
1320         sfxge_intr_t *sip = &(sp->s_intr);
1321         efx_nic_t *enp = sp->s_enp;
1322         int index;
1323 
1324         ASSERT3U(sip->si_state, ==, SFXGE_INTR_STARTED);
1325 
1326         /* Stop the event queue(s) */
1327         index = sip->si_nalloc;
1328         while (--index >= 0)
1329                 sfxge_ev_qstop(sp, index);
1330 
1331         /* Tear down the event module */
1332         efx_ev_fini(enp);
1333 }
1334 
1335 void
1336 sfxge_ev_fini(sfxge_t *sp)
1337 {
1338         sfxge_intr_t *sip = &(sp->s_intr);
1339         int index;
1340 
1341         ASSERT3U(sip->si_state, ==, SFXGE_INTR_INITIALIZED);
1342 
1343         sp->s_ev_moderation = 0;
1344 
1345         /* Tear down the event queue(s) */
1346         index = sip->si_nalloc;
1347         while (--index >= 0)
1348                 sfxge_ev_qfini(sp, index);
1349 
1350         kmem_cache_destroy(sp->s_eqXc);
1351         kmem_cache_destroy(sp->s_eq0c);
1352         sp->s_eqXc = NULL;
1353         sp->s_eq0c = NULL;
1354 }