2 * Copyright (c) 2010-2016 Solarflare Communications Inc.
5 * This software was developed in part by Philip Paeps under contract for
6 * Solarflare Communications, Inc.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
11 * 1. Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
27 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * The views and conclusions contained in the software and documentation are
30 * those of the authors and should not be interpreted as representing official
31 * policies, either expressed or implied, of the FreeBSD Project.
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
37 #include <sys/param.h>
38 #include <sys/systm.h>
40 #include "common/efx.h"
45 sfxge_ev_qcomplete(struct sfxge_evq *evq, boolean_t eop)
47 struct sfxge_softc *sc;
49 struct sfxge_rxq *rxq;
50 struct sfxge_txq *txq;
52 SFXGE_EVQ_LOCK_ASSERT_OWNED(evq);
58 if ((txq = evq->txq) != NULL) {
60 evq->txqs = &(evq->txq);
63 struct sfxge_txq *next;
68 KASSERT(txq->evq_index == index,
69 ("txq->evq_index != index"));
71 if (txq->pending != txq->completed)
72 sfxge_tx_qcomplete(txq, evq);
75 } while (txq != NULL);
78 if (rxq->pending != rxq->completed)
79 sfxge_rx_qcomplete(rxq, eop);
82 static struct sfxge_rxq *
83 sfxge_get_rxq_by_label(struct sfxge_evq *evq, uint32_t label)
85 struct sfxge_rxq *rxq;
87 KASSERT(label == 0, ("unexpected rxq label != 0"));
89 rxq = evq->sc->rxq[evq->index];
91 KASSERT(rxq != NULL, ("rxq == NULL"));
92 KASSERT(evq->index == rxq->index, ("evq->index != rxq->index"));
98 sfxge_ev_rx(void *arg, uint32_t label, uint32_t id, uint32_t size,
101 struct sfxge_evq *evq;
102 struct sfxge_softc *sc;
103 struct sfxge_rxq *rxq;
106 struct sfxge_rx_sw_desc *rx_desc;
109 SFXGE_EVQ_LOCK_ASSERT_OWNED(evq);
116 rxq = sfxge_get_rxq_by_label(evq, label);
117 if (__predict_false(rxq->init_state != SFXGE_RXQ_STARTED))
120 stop = (id + 1) & rxq->ptr_mask;
121 id = rxq->pending & rxq->ptr_mask;
122 delta = (stop >= id) ? (stop - id) : (rxq->entries - id + stop);
123 rxq->pending += delta;
127 (delta > efx_nic_cfg_get(sc->enp)->enc_rx_batch_max)) {
128 evq->exception = B_TRUE;
130 device_printf(sc->dev, "RX completion out of order"
131 " (id=%#x delta=%u flags=%#x); resetting\n",
133 sfxge_schedule_reset(sc);
139 rx_desc = &rxq->queue[id];
141 prefetch_read_many(rx_desc->mbuf);
143 for (; id != stop; id = (id + 1) & rxq->ptr_mask) {
144 rx_desc = &rxq->queue[id];
145 KASSERT(rx_desc->flags == EFX_DISCARD,
146 ("rx_desc->flags != EFX_DISCARD"));
147 rx_desc->flags = flags;
149 KASSERT(size < (1 << 16), ("size > (1 << 16)"));
150 rx_desc->size = (uint16_t)size;
155 if (rxq->pending - rxq->completed >= SFXGE_RX_BATCH)
156 sfxge_ev_qcomplete(evq, B_FALSE);
159 return (evq->rx_done >= SFXGE_EV_BATCH);
163 sfxge_ev_exception(void *arg, uint32_t code, uint32_t data)
165 struct sfxge_evq *evq;
166 struct sfxge_softc *sc;
168 evq = (struct sfxge_evq *)arg;
169 SFXGE_EVQ_LOCK_ASSERT_OWNED(evq);
173 DBGPRINT(sc->dev, "[%d] %s", evq->index,
174 (code == EFX_EXCEPTION_RX_RECOVERY) ? "RX_RECOVERY" :
175 (code == EFX_EXCEPTION_RX_DSC_ERROR) ? "RX_DSC_ERROR" :
176 (code == EFX_EXCEPTION_TX_DSC_ERROR) ? "TX_DSC_ERROR" :
177 (code == EFX_EXCEPTION_UNKNOWN_SENSOREVT) ? "UNKNOWN_SENSOREVT" :
178 (code == EFX_EXCEPTION_FWALERT_SRAM) ? "FWALERT_SRAM" :
179 (code == EFX_EXCEPTION_UNKNOWN_FWALERT) ? "UNKNOWN_FWALERT" :
180 (code == EFX_EXCEPTION_RX_ERROR) ? "RX_ERROR" :
181 (code == EFX_EXCEPTION_TX_ERROR) ? "TX_ERROR" :
182 (code == EFX_EXCEPTION_EV_ERROR) ? "EV_ERROR" :
185 evq->exception = B_TRUE;
187 if (code != EFX_EXCEPTION_UNKNOWN_SENSOREVT) {
188 device_printf(sc->dev,
189 "hardware exception (code=%u); resetting\n",
191 sfxge_schedule_reset(sc);
198 sfxge_ev_rxq_flush_done(void *arg, uint32_t rxq_index)
200 struct sfxge_evq *evq;
201 struct sfxge_softc *sc;
202 struct sfxge_rxq *rxq;
206 evq = (struct sfxge_evq *)arg;
207 SFXGE_EVQ_LOCK_ASSERT_OWNED(evq);
210 rxq = sc->rxq[rxq_index];
212 KASSERT(rxq != NULL, ("rxq == NULL"));
214 /* Resend a software event on the correct queue */
216 if (index == evq->index) {
217 sfxge_rx_qflush_done(rxq);
221 evq = sc->evq[index];
222 magic = sfxge_sw_ev_rxq_magic(SFXGE_SW_EV_RX_QFLUSH_DONE, rxq);
224 KASSERT(evq->init_state == SFXGE_EVQ_STARTED,
225 ("evq not started"));
226 efx_ev_qpost(evq->common, magic);
232 sfxge_ev_rxq_flush_failed(void *arg, uint32_t rxq_index)
234 struct sfxge_evq *evq;
235 struct sfxge_softc *sc;
236 struct sfxge_rxq *rxq;
240 evq = (struct sfxge_evq *)arg;
241 SFXGE_EVQ_LOCK_ASSERT_OWNED(evq);
244 rxq = sc->rxq[rxq_index];
246 KASSERT(rxq != NULL, ("rxq == NULL"));
248 /* Resend a software event on the correct queue */
250 evq = sc->evq[index];
251 magic = sfxge_sw_ev_rxq_magic(SFXGE_SW_EV_RX_QFLUSH_FAILED, rxq);
253 KASSERT(evq->init_state == SFXGE_EVQ_STARTED,
254 ("evq not started"));
255 efx_ev_qpost(evq->common, magic);
260 static struct sfxge_txq *
261 sfxge_get_txq_by_label(struct sfxge_evq *evq, enum sfxge_txq_type label)
265 KASSERT((evq->index == 0 && label < SFXGE_TXQ_NTYPES) ||
266 (label == SFXGE_TXQ_IP_TCP_UDP_CKSUM), ("unexpected txq label"));
267 index = (evq->index == 0) ? label : (evq->index - 1 + SFXGE_TXQ_NTYPES);
268 return (evq->sc->txq[index]);
272 sfxge_ev_tx(void *arg, uint32_t label, uint32_t id)
274 struct sfxge_evq *evq;
275 struct sfxge_txq *txq;
279 evq = (struct sfxge_evq *)arg;
280 SFXGE_EVQ_LOCK_ASSERT_OWNED(evq);
282 txq = sfxge_get_txq_by_label(evq, label);
284 KASSERT(txq != NULL, ("txq == NULL"));
285 KASSERT(evq->index == txq->evq_index,
286 ("evq->index != txq->evq_index"));
288 if (__predict_false(txq->init_state != SFXGE_TXQ_STARTED))
291 stop = (id + 1) & txq->ptr_mask;
292 id = txq->pending & txq->ptr_mask;
294 delta = (stop >= id) ? (stop - id) : (txq->entries - id + stop);
295 txq->pending += delta;
299 if (txq->next == NULL &&
300 evq->txqs != &(txq->next)) {
302 evq->txqs = &(txq->next);
305 if (txq->pending - txq->completed >= SFXGE_TX_BATCH)
306 sfxge_tx_qcomplete(txq, evq);
309 return (evq->tx_done >= SFXGE_EV_BATCH);
313 sfxge_ev_txq_flush_done(void *arg, uint32_t txq_index)
315 struct sfxge_evq *evq;
316 struct sfxge_softc *sc;
317 struct sfxge_txq *txq;
320 evq = (struct sfxge_evq *)arg;
321 SFXGE_EVQ_LOCK_ASSERT_OWNED(evq);
324 txq = sc->txq[txq_index];
326 KASSERT(txq != NULL, ("txq == NULL"));
327 KASSERT(txq->init_state == SFXGE_TXQ_INITIALIZED,
328 ("txq not initialized"));
330 if (txq->evq_index == evq->index) {
331 sfxge_tx_qflush_done(txq);
335 /* Resend a software event on the correct queue */
336 evq = sc->evq[txq->evq_index];
337 magic = sfxge_sw_ev_txq_magic(SFXGE_SW_EV_TX_QFLUSH_DONE, txq);
339 KASSERT(evq->init_state == SFXGE_EVQ_STARTED,
340 ("evq not started"));
341 efx_ev_qpost(evq->common, magic);
347 sfxge_ev_software(void *arg, uint16_t magic)
349 struct sfxge_evq *evq;
350 struct sfxge_softc *sc;
353 evq = (struct sfxge_evq *)arg;
354 SFXGE_EVQ_LOCK_ASSERT_OWNED(evq);
358 label = magic & SFXGE_MAGIC_DMAQ_LABEL_MASK;
359 magic &= ~SFXGE_MAGIC_DMAQ_LABEL_MASK;
362 case SFXGE_SW_EV_MAGIC(SFXGE_SW_EV_RX_QFLUSH_DONE):
363 sfxge_rx_qflush_done(sfxge_get_rxq_by_label(evq, label));
366 case SFXGE_SW_EV_MAGIC(SFXGE_SW_EV_RX_QFLUSH_FAILED):
367 sfxge_rx_qflush_failed(sfxge_get_rxq_by_label(evq, label));
370 case SFXGE_SW_EV_MAGIC(SFXGE_SW_EV_RX_QREFILL):
371 sfxge_rx_qrefill(sfxge_get_rxq_by_label(evq, label));
374 case SFXGE_SW_EV_MAGIC(SFXGE_SW_EV_TX_QFLUSH_DONE): {
375 struct sfxge_txq *txq = sfxge_get_txq_by_label(evq, label);
377 KASSERT(txq != NULL, ("txq == NULL"));
378 KASSERT(evq->index == txq->evq_index,
379 ("evq->index != txq->evq_index"));
381 sfxge_tx_qflush_done(txq);
392 sfxge_ev_sram(void *arg, uint32_t code)
398 case EFX_SRAM_UPDATE:
399 EFSYS_PROBE(sram_update);
403 EFSYS_PROBE(sram_clear);
406 case EFX_SRAM_ILLEGAL_CLEAR:
407 EFSYS_PROBE(sram_illegal_clear);
411 KASSERT(B_FALSE, ("Impossible SRAM event"));
419 sfxge_ev_timer(void *arg, uint32_t index)
428 sfxge_ev_wake_up(void *arg, uint32_t index)
439 sfxge_ev_stat_update(struct sfxge_softc *sc)
441 struct sfxge_evq *evq;
445 SFXGE_ADAPTER_LOCK(sc);
447 if (__predict_false(sc->evq[0]->init_state != SFXGE_EVQ_STARTED))
451 if (now - sc->ev_stats_update_time < hz)
454 sc->ev_stats_update_time = now;
456 /* Add event counts from each event queue in turn */
457 for (index = 0; index < sc->evq_count; index++) {
458 evq = sc->evq[index];
460 efx_ev_qstats_update(evq->common, sc->ev_stats);
461 SFXGE_EVQ_UNLOCK(evq);
464 SFXGE_ADAPTER_UNLOCK(sc);
468 sfxge_ev_stat_handler(SYSCTL_HANDLER_ARGS)
470 struct sfxge_softc *sc = arg1;
471 unsigned int id = arg2;
473 sfxge_ev_stat_update(sc);
475 return (SYSCTL_OUT(req, &sc->ev_stats[id], sizeof(sc->ev_stats[id])));
479 sfxge_ev_stat_init(struct sfxge_softc *sc)
481 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->dev);
482 struct sysctl_oid_list *stat_list;
486 stat_list = SYSCTL_CHILDREN(sc->stats_node);
488 for (id = 0; id < EV_NQSTATS; id++) {
489 snprintf(name, sizeof(name), "ev_%s",
490 efx_ev_qstat_name(sc->enp, id));
493 OID_AUTO, name, CTLTYPE_U64|CTLFLAG_RD,
494 sc, id, sfxge_ev_stat_handler, "Q",
499 #endif /* EFSYS_OPT_QSTATS */
502 sfxge_ev_qmoderate(struct sfxge_softc *sc, unsigned int idx, unsigned int us)
504 struct sfxge_evq *evq;
510 KASSERT(evq->init_state == SFXGE_EVQ_STARTED,
511 ("evq->init_state != SFXGE_EVQ_STARTED"));
513 (void)efx_ev_qmoderate(eep, us);
517 sfxge_int_mod_handler(SYSCTL_HANDLER_ARGS)
519 struct sfxge_softc *sc = arg1;
520 struct sfxge_intr *intr = &sc->intr;
521 unsigned int moderation;
525 SFXGE_ADAPTER_LOCK(sc);
527 if (req->newptr != NULL) {
528 if ((error = SYSCTL_IN(req, &moderation, sizeof(moderation)))
532 /* We may not be calling efx_ev_qmoderate() now,
533 * so we have to range-check the value ourselves.
536 efx_nic_cfg_get(sc->enp)->enc_evq_timer_max_us) {
541 sc->ev_moderation = moderation;
542 if (intr->state == SFXGE_INTR_STARTED) {
543 for (index = 0; index < sc->evq_count; index++)
544 sfxge_ev_qmoderate(sc, index, moderation);
547 error = SYSCTL_OUT(req, &sc->ev_moderation,
548 sizeof(sc->ev_moderation));
552 SFXGE_ADAPTER_UNLOCK(sc);
558 sfxge_ev_initialized(void *arg)
560 struct sfxge_evq *evq;
562 evq = (struct sfxge_evq *)arg;
563 SFXGE_EVQ_LOCK_ASSERT_OWNED(evq);
565 /* Init done events may be duplicated on 7xxx */
566 KASSERT(evq->init_state == SFXGE_EVQ_STARTING ||
567 evq->init_state == SFXGE_EVQ_STARTED,
568 ("evq not starting"));
570 evq->init_state = SFXGE_EVQ_STARTED;
576 sfxge_ev_link_change(void *arg, efx_link_mode_t link_mode)
578 struct sfxge_evq *evq;
579 struct sfxge_softc *sc;
581 evq = (struct sfxge_evq *)arg;
582 SFXGE_EVQ_LOCK_ASSERT_OWNED(evq);
586 sfxge_mac_link_update(sc, link_mode);
591 static const efx_ev_callbacks_t sfxge_ev_callbacks = {
592 .eec_initialized = sfxge_ev_initialized,
593 .eec_rx = sfxge_ev_rx,
594 .eec_tx = sfxge_ev_tx,
595 .eec_exception = sfxge_ev_exception,
596 .eec_rxq_flush_done = sfxge_ev_rxq_flush_done,
597 .eec_rxq_flush_failed = sfxge_ev_rxq_flush_failed,
598 .eec_txq_flush_done = sfxge_ev_txq_flush_done,
599 .eec_software = sfxge_ev_software,
600 .eec_sram = sfxge_ev_sram,
601 .eec_wake_up = sfxge_ev_wake_up,
602 .eec_timer = sfxge_ev_timer,
603 .eec_link_change = sfxge_ev_link_change,
608 sfxge_ev_qpoll(struct sfxge_evq *evq)
614 if (__predict_false(evq->init_state != SFXGE_EVQ_STARTING &&
615 evq->init_state != SFXGE_EVQ_STARTED)) {
620 /* Synchronize the DMA memory for reading */
621 bus_dmamap_sync(evq->mem.esm_tag, evq->mem.esm_map,
622 BUS_DMASYNC_POSTREAD);
624 KASSERT(evq->rx_done == 0, ("evq->rx_done != 0"));
625 KASSERT(evq->tx_done == 0, ("evq->tx_done != 0"));
626 KASSERT(evq->txq == NULL, ("evq->txq != NULL"));
627 KASSERT(evq->txqs == &evq->txq, ("evq->txqs != &evq->txq"));
630 efx_ev_qpoll(evq->common, &evq->read_ptr, &sfxge_ev_callbacks, evq);
635 /* Perform any pending completion processing */
636 sfxge_ev_qcomplete(evq, B_TRUE);
638 /* Re-prime the event queue for interrupts */
639 if ((rc = efx_ev_qprime(evq->common, evq->read_ptr)) != 0)
642 SFXGE_EVQ_UNLOCK(evq);
647 SFXGE_EVQ_UNLOCK(evq);
652 sfxge_ev_qstop(struct sfxge_softc *sc, unsigned int index)
654 struct sfxge_evq *evq;
656 evq = sc->evq[index];
658 KASSERT(evq->init_state == SFXGE_EVQ_STARTED,
659 ("evq->init_state != SFXGE_EVQ_STARTED"));
662 evq->init_state = SFXGE_EVQ_INITIALIZED;
664 evq->exception = B_FALSE;
667 /* Add event counts before discarding the common evq state */
668 efx_ev_qstats_update(evq->common, sc->ev_stats);
671 efx_ev_qdestroy(evq->common);
672 efx_sram_buf_tbl_clear(sc->enp, evq->buf_base_id,
673 EFX_EVQ_NBUFS(evq->entries));
674 SFXGE_EVQ_UNLOCK(evq);
678 sfxge_ev_qstart(struct sfxge_softc *sc, unsigned int index)
680 struct sfxge_evq *evq;
685 evq = sc->evq[index];
688 KASSERT(evq->init_state == SFXGE_EVQ_INITIALIZED,
689 ("evq->init_state != SFXGE_EVQ_INITIALIZED"));
691 /* Clear all events. */
692 (void)memset(esmp->esm_base, 0xff, EFX_EVQ_SIZE(evq->entries));
694 /* Program the buffer table. */
695 if ((rc = efx_sram_buf_tbl_set(sc->enp, evq->buf_base_id, esmp,
696 EFX_EVQ_NBUFS(evq->entries))) != 0)
699 /* Create the common code event queue. */
700 if ((rc = efx_ev_qcreate(sc->enp, index, esmp, evq->entries,
701 evq->buf_base_id, sc->ev_moderation, &evq->common)) != 0)
706 /* Prime the event queue for interrupts */
707 if ((rc = efx_ev_qprime(evq->common, evq->read_ptr)) != 0)
710 evq->init_state = SFXGE_EVQ_STARTING;
712 SFXGE_EVQ_UNLOCK(evq);
714 /* Wait for the initialization event */
717 /* Pause for 100 ms */
718 pause("sfxge evq init", hz / 10);
720 /* Check to see if the test event has been processed */
721 if (evq->init_state == SFXGE_EVQ_STARTED)
724 } while (++count < 20);
734 evq->init_state = SFXGE_EVQ_INITIALIZED;
736 SFXGE_EVQ_UNLOCK(evq);
737 efx_ev_qdestroy(evq->common);
739 efx_sram_buf_tbl_clear(sc->enp, evq->buf_base_id,
740 EFX_EVQ_NBUFS(evq->entries));
746 sfxge_ev_stop(struct sfxge_softc *sc)
748 struct sfxge_intr *intr;
755 KASSERT(intr->state == SFXGE_INTR_STARTED,
756 ("Interrupts not started"));
758 /* Stop the event queue(s) */
759 index = sc->evq_count;
761 sfxge_ev_qstop(sc, index);
763 /* Tear down the event module */
768 sfxge_ev_start(struct sfxge_softc *sc)
770 struct sfxge_intr *intr;
776 KASSERT(intr->state == SFXGE_INTR_STARTED,
777 ("intr->state != SFXGE_INTR_STARTED"));
779 /* Initialize the event module */
780 if ((rc = efx_ev_init(sc->enp)) != 0)
783 /* Start the event queues */
784 for (index = 0; index < sc->evq_count; index++) {
785 if ((rc = sfxge_ev_qstart(sc, index)) != 0)
792 /* Stop the event queue(s) */
794 sfxge_ev_qstop(sc, index);
796 /* Tear down the event module */
797 efx_ev_fini(sc->enp);
803 sfxge_ev_qfini(struct sfxge_softc *sc, unsigned int index)
805 struct sfxge_evq *evq;
807 evq = sc->evq[index];
809 KASSERT(evq->init_state == SFXGE_EVQ_INITIALIZED,
810 ("evq->init_state != SFXGE_EVQ_INITIALIZED"));
811 KASSERT(evq->txqs == &evq->txq, ("evq->txqs != &evq->txq"));
813 sfxge_dma_free(&evq->mem);
815 sc->evq[index] = NULL;
817 SFXGE_EVQ_LOCK_DESTROY(evq);
823 sfxge_ev_qinit(struct sfxge_softc *sc, unsigned int index)
825 struct sfxge_evq *evq;
829 KASSERT(index < SFXGE_RX_SCALE_MAX, ("index >= SFXGE_RX_SCALE_MAX"));
831 evq = malloc(sizeof(struct sfxge_evq), M_SFXGE, M_ZERO | M_WAITOK);
834 sc->evq[index] = evq;
837 /* Build an event queue with room for one event per tx and rx buffer,
838 * plus some extra for link state events and MCDI completions.
839 * There are three tx queues in the first event queue and one in
844 ROUNDUP_POW_OF_TWO(sc->rxq_entries +
845 3 * sc->txq_entries +
849 ROUNDUP_POW_OF_TWO(sc->rxq_entries +
853 /* Initialise TX completion list */
854 evq->txqs = &evq->txq;
856 /* Allocate DMA space. */
857 if ((rc = sfxge_dma_alloc(sc, EFX_EVQ_SIZE(evq->entries), esmp)) != 0)
860 /* Allocate buffer table entries. */
861 sfxge_sram_buf_tbl_alloc(sc, EFX_EVQ_NBUFS(evq->entries),
864 SFXGE_EVQ_LOCK_INIT(evq, device_get_nameunit(sc->dev), index);
866 evq->init_state = SFXGE_EVQ_INITIALIZED;
872 sfxge_ev_fini(struct sfxge_softc *sc)
874 struct sfxge_intr *intr;
879 KASSERT(intr->state == SFXGE_INTR_INITIALIZED,
880 ("intr->state != SFXGE_INTR_INITIALIZED"));
882 sc->ev_moderation = 0;
884 /* Tear down the event queue(s). */
885 index = sc->evq_count;
887 sfxge_ev_qfini(sc, index);
893 sfxge_ev_init(struct sfxge_softc *sc)
895 struct sysctl_ctx_list *sysctl_ctx = device_get_sysctl_ctx(sc->dev);
896 struct sysctl_oid *sysctl_tree = device_get_sysctl_tree(sc->dev);
897 struct sfxge_intr *intr;
903 sc->evq_count = intr->n_alloc;
905 KASSERT(intr->state == SFXGE_INTR_INITIALIZED,
906 ("intr->state != SFXGE_INTR_INITIALIZED"));
908 /* Set default interrupt moderation; add a sysctl to
909 * read and change it.
911 sc->ev_moderation = SFXGE_MODERATION;
912 SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
913 OID_AUTO, "int_mod", CTLTYPE_UINT|CTLFLAG_RW,
914 sc, 0, sfxge_int_mod_handler, "IU",
915 "sfxge interrupt moderation (us)");
918 * Initialize the event queue(s) - one per interrupt.
920 for (index = 0; index < sc->evq_count; index++) {
921 if ((rc = sfxge_ev_qinit(sc, index)) != 0)
926 sfxge_ev_stat_init(sc);
933 sfxge_ev_qfini(sc, index);