The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/sfxge/sfxge_ev.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2010-2011 Solarflare Communications, Inc.
    3  * All rights reserved.
    4  *
    5  * This software was developed in part by Philip Paeps under contract for
    6  * Solarflare Communications, Inc.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD: releng/9.2/sys/dev/sfxge/sfxge_ev.c 227569 2011-11-16 17:11:13Z philip $");
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 
   36 #include "common/efx.h"
   37 
   38 #include "sfxge.h"
   39 
   40 static void
   41 sfxge_ev_qcomplete(struct sfxge_evq *evq, boolean_t eop)
   42 {
   43         struct sfxge_softc *sc;
   44         unsigned int index;
   45         struct sfxge_rxq *rxq;
   46         struct sfxge_txq *txq;
   47 
   48         sc = evq->sc;
   49         index = evq->index;
   50         rxq = sc->rxq[index];
   51 
   52         if ((txq = evq->txq) != NULL) {
   53                 evq->txq = NULL;
   54                 evq->txqs = &(evq->txq);
   55 
   56                 do {
   57                         struct sfxge_txq *next;
   58 
   59                         next = txq->next;
   60                         txq->next = NULL;
   61 
   62                         KASSERT(txq->evq_index == index,
   63                             ("txq->evq_index != index"));
   64 
   65                         if (txq->pending != txq->completed)
   66                                 sfxge_tx_qcomplete(txq);
   67 
   68                         txq = next;
   69                 } while (txq != NULL);
   70         }
   71 
   72         if (rxq->pending != rxq->completed)
   73                 sfxge_rx_qcomplete(rxq, eop);
   74 }
   75 
   76 static boolean_t
   77 sfxge_ev_rx(void *arg, uint32_t label, uint32_t id, uint32_t size,
   78     uint16_t flags)
   79 {
   80         struct sfxge_evq *evq;
   81         struct sfxge_softc *sc;
   82         struct sfxge_rxq *rxq;
   83         unsigned int expected;
   84         struct sfxge_rx_sw_desc *rx_desc;
   85 
   86         evq = arg;
   87         sc = evq->sc;
   88 
   89         if (evq->exception)
   90                 goto done;
   91 
   92         rxq = sc->rxq[label];
   93         KASSERT(rxq != NULL, ("rxq == NULL"));
   94         KASSERT(evq->index == rxq->index,
   95             ("evq->index != rxq->index"));
   96 
   97         if (rxq->init_state != SFXGE_RXQ_STARTED)
   98                 goto done;
   99 
  100         expected = rxq->pending++ & (SFXGE_NDESCS - 1);
  101         if (id != expected) {
  102                 evq->exception = B_TRUE;
  103 
  104                 device_printf(sc->dev, "RX completion out of order"
  105                               " (id=%#x expected=%#x flags=%#x); resetting\n",
  106                               id, expected, flags);
  107                 sfxge_schedule_reset(sc);
  108 
  109                 goto done;
  110         }
  111 
  112         rx_desc = &rxq->queue[id];
  113 
  114         KASSERT(rx_desc->flags == EFX_DISCARD,
  115             ("rx_desc->flags != EFX_DISCARD"));
  116         rx_desc->flags = flags;
  117 
  118         KASSERT(size < (1 << 16), ("size > (1 << 16)"));
  119         rx_desc->size = (uint16_t)size;
  120         prefetch_read_many(rx_desc->mbuf);
  121 
  122         evq->rx_done++;
  123 
  124         if (rxq->pending - rxq->completed >= SFXGE_RX_BATCH)
  125                 sfxge_ev_qcomplete(evq, B_FALSE);
  126 
  127 done:
  128         return (evq->rx_done >= SFXGE_EV_BATCH);
  129 }
  130 
  131 static boolean_t
  132 sfxge_ev_exception(void *arg, uint32_t code, uint32_t data)
  133 {
  134         struct sfxge_evq *evq;
  135         struct sfxge_softc *sc;
  136 
  137         evq = (struct sfxge_evq *)arg;
  138         sc = evq->sc;
  139 
  140         evq->exception = B_TRUE;
  141 
  142         if (code != EFX_EXCEPTION_UNKNOWN_SENSOREVT) {
  143                 device_printf(sc->dev,
  144                               "hardware exception (code=%u); resetting\n",
  145                               code);
  146                 sfxge_schedule_reset(sc);
  147         }
  148 
  149         return (B_FALSE);
  150 }
  151 
  152 static boolean_t
  153 sfxge_ev_rxq_flush_done(void *arg, uint32_t label)
  154 {
  155         struct sfxge_evq *evq;
  156         struct sfxge_softc *sc;
  157         struct sfxge_rxq *rxq;
  158         unsigned int index;
  159         uint16_t magic;
  160 
  161         evq = (struct sfxge_evq *)arg;
  162         sc = evq->sc;
  163         rxq = sc->rxq[label];
  164 
  165         KASSERT(rxq != NULL, ("rxq == NULL"));
  166 
  167         /* Resend a software event on the correct queue */
  168         index = rxq->index;
  169         evq = sc->evq[index];
  170 
  171         KASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label,
  172             ("(label & SFXGE_MAGIC_DMAQ_LABEL_MASK) != level"));
  173         magic = SFXGE_MAGIC_RX_QFLUSH_DONE | label;
  174 
  175         KASSERT(evq->init_state == SFXGE_EVQ_STARTED,
  176             ("evq not started"));
  177         efx_ev_qpost(evq->common, magic);
  178 
  179         return (B_FALSE);
  180 }
  181 
  182 static boolean_t
  183 sfxge_ev_rxq_flush_failed(void *arg, uint32_t label)
  184 {
  185         struct sfxge_evq *evq;
  186         struct sfxge_softc *sc;
  187         struct sfxge_rxq *rxq;
  188         unsigned int index;
  189         uint16_t magic;
  190 
  191         evq = (struct sfxge_evq *)arg;
  192         sc = evq->sc;
  193         rxq = sc->rxq[label];
  194 
  195         KASSERT(rxq != NULL, ("rxq == NULL"));
  196 
  197         /* Resend a software event on the correct queue */
  198         index = rxq->index;
  199         evq = sc->evq[index];
  200 
  201         KASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label,
  202             ("(label & SFXGE_MAGIC_DMAQ_LABEL_MASK) != label"));
  203         magic = SFXGE_MAGIC_RX_QFLUSH_FAILED | label;
  204 
  205         KASSERT(evq->init_state == SFXGE_EVQ_STARTED,
  206             ("evq not started"));
  207         efx_ev_qpost(evq->common, magic);
  208 
  209         return (B_FALSE);
  210 }
  211 
  212 static boolean_t
  213 sfxge_ev_tx(void *arg, uint32_t label, uint32_t id)
  214 {
  215         struct sfxge_evq *evq;
  216         struct sfxge_softc *sc;
  217         struct sfxge_txq *txq;
  218         unsigned int stop;
  219         unsigned int delta;
  220 
  221         evq = (struct sfxge_evq *)arg;
  222         sc = evq->sc;
  223         txq = sc->txq[label];
  224 
  225         KASSERT(txq != NULL, ("txq == NULL"));
  226         KASSERT(evq->index == txq->evq_index,
  227             ("evq->index != txq->evq_index"));
  228 
  229         if (txq->init_state != SFXGE_TXQ_STARTED)
  230                 goto done;
  231 
  232         stop = (id + 1) & (SFXGE_NDESCS - 1);
  233         id = txq->pending & (SFXGE_NDESCS - 1);
  234 
  235         delta = (stop >= id) ? (stop - id) : (SFXGE_NDESCS - id + stop);
  236         txq->pending += delta;
  237 
  238         evq->tx_done++;
  239 
  240         if (txq->next == NULL &&
  241             evq->txqs != &(txq->next)) {
  242                 *(evq->txqs) = txq;
  243                 evq->txqs = &(txq->next);
  244         }
  245 
  246         if (txq->pending - txq->completed >= SFXGE_TX_BATCH)
  247                 sfxge_tx_qcomplete(txq);
  248 
  249 done:
  250         return (evq->tx_done >= SFXGE_EV_BATCH);
  251 }
  252 
  253 static boolean_t
  254 sfxge_ev_txq_flush_done(void *arg, uint32_t label)
  255 {
  256         struct sfxge_evq *evq;
  257         struct sfxge_softc *sc;
  258         struct sfxge_txq *txq;
  259         uint16_t magic;
  260 
  261         evq = (struct sfxge_evq *)arg;
  262         sc = evq->sc;
  263         txq = sc->txq[label];
  264 
  265         KASSERT(txq != NULL, ("txq == NULL"));
  266         KASSERT(txq->init_state == SFXGE_TXQ_INITIALIZED,
  267             ("txq not initialized"));
  268 
  269         /* Resend a software event on the correct queue */
  270         evq = sc->evq[txq->evq_index];
  271 
  272         KASSERT((label & SFXGE_MAGIC_DMAQ_LABEL_MASK) == label,
  273             ("(label & SFXGE_MAGIC_DMAQ_LABEL_MASK) != label"));
  274         magic = SFXGE_MAGIC_TX_QFLUSH_DONE | label;
  275 
  276         KASSERT(evq->init_state == SFXGE_EVQ_STARTED,
  277             ("evq not started"));
  278         efx_ev_qpost(evq->common, magic);
  279 
  280         return (B_FALSE);
  281 }
  282 
  283 static boolean_t
  284 sfxge_ev_software(void *arg, uint16_t magic)
  285 {
  286         struct sfxge_evq *evq;
  287         struct sfxge_softc *sc;
  288         unsigned int label;
  289 
  290         evq = (struct sfxge_evq *)arg;
  291         sc = evq->sc;
  292 
  293         label = magic & SFXGE_MAGIC_DMAQ_LABEL_MASK;
  294         magic &= ~SFXGE_MAGIC_DMAQ_LABEL_MASK;
  295 
  296         switch (magic) {
  297         case SFXGE_MAGIC_RX_QFLUSH_DONE: {
  298                 struct sfxge_rxq *rxq = sc->rxq[label];
  299 
  300                 KASSERT(rxq != NULL, ("rxq == NULL"));
  301                 KASSERT(evq->index == rxq->index,
  302                     ("evq->index != rxq->index"));
  303 
  304                 sfxge_rx_qflush_done(rxq);
  305                 break;
  306         }
  307         case SFXGE_MAGIC_RX_QFLUSH_FAILED: {
  308                 struct sfxge_rxq *rxq = sc->rxq[label];
  309 
  310                 KASSERT(rxq != NULL, ("rxq == NULL"));
  311                 KASSERT(evq->index == rxq->index,
  312                     ("evq->index != rxq->index"));
  313 
  314                 sfxge_rx_qflush_failed(rxq);
  315                 break;
  316         }
  317         case SFXGE_MAGIC_RX_QREFILL: {
  318                 struct sfxge_rxq *rxq = sc->rxq[label];
  319 
  320                 KASSERT(rxq != NULL, ("rxq == NULL"));
  321                 KASSERT(evq->index == rxq->index,
  322                     ("evq->index != rxq->index"));
  323 
  324                 sfxge_rx_qrefill(rxq);
  325                 break;
  326         }
  327         case SFXGE_MAGIC_TX_QFLUSH_DONE: {
  328                 struct sfxge_txq *txq = sc->txq[label];
  329 
  330                 KASSERT(txq != NULL, ("txq == NULL"));
  331                 KASSERT(evq->index == txq->evq_index,
  332                     ("evq->index != txq->evq_index"));
  333 
  334                 sfxge_tx_qflush_done(txq);
  335                 break;
  336         }
  337         default:
  338                 break;
  339         }
  340 
  341         return (B_FALSE);
  342 }
  343 
  344 static boolean_t
  345 sfxge_ev_sram(void *arg, uint32_t code)
  346 {
  347         (void)arg;
  348         (void)code;
  349 
  350         switch (code) {
  351         case EFX_SRAM_UPDATE:
  352                 EFSYS_PROBE(sram_update);
  353                 break;
  354 
  355         case EFX_SRAM_CLEAR:
  356                 EFSYS_PROBE(sram_clear);
  357                 break;
  358 
  359         case EFX_SRAM_ILLEGAL_CLEAR:
  360                 EFSYS_PROBE(sram_illegal_clear);
  361                 break;
  362 
  363         default:
  364                 KASSERT(B_FALSE, ("Impossible SRAM event"));
  365                 break;
  366         }
  367 
  368         return (B_FALSE);
  369 }
  370 
  371 static boolean_t
  372 sfxge_ev_timer(void *arg, uint32_t index)
  373 {
  374         (void)arg;
  375         (void)index;
  376 
  377         return (B_FALSE);
  378 }
  379 
  380 static boolean_t
  381 sfxge_ev_wake_up(void *arg, uint32_t index)
  382 {
  383         (void)arg;
  384         (void)index;
  385 
  386         return (B_FALSE);
  387 }
  388 
  389 static void
  390 sfxge_ev_stat_update(struct sfxge_softc *sc)
  391 {
  392         struct sfxge_evq *evq;
  393         unsigned int index;
  394         clock_t now;
  395 
  396         sx_xlock(&sc->softc_lock);
  397 
  398         if (sc->evq[0]->init_state != SFXGE_EVQ_STARTED)
  399                 goto out;
  400 
  401         now = ticks;
  402         if (now - sc->ev_stats_update_time < hz)
  403                 goto out;
  404 
  405         sc->ev_stats_update_time = now;
  406 
  407         /* Add event counts from each event queue in turn */
  408         for (index = 0; index < sc->intr.n_alloc; index++) {
  409                 evq = sc->evq[index];
  410                 mtx_lock(&evq->lock);
  411                 efx_ev_qstats_update(evq->common, sc->ev_stats);
  412                 mtx_unlock(&evq->lock);
  413         }
  414 out:
  415         sx_xunlock(&sc->softc_lock);
  416 }
  417 
  418 static int
  419 sfxge_ev_stat_handler(SYSCTL_HANDLER_ARGS)
  420 {
  421         struct sfxge_softc *sc = arg1;
  422         unsigned int id = arg2;
  423 
  424         sfxge_ev_stat_update(sc);
  425 
  426         return SYSCTL_OUT(req, &sc->ev_stats[id], sizeof(sc->ev_stats[id]));
  427 }
  428 
  429 static void
  430 sfxge_ev_stat_init(struct sfxge_softc *sc)
  431 {
  432         struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->dev);
  433         struct sysctl_oid_list *stat_list;
  434         unsigned int id;
  435         char name[40];
  436 
  437         stat_list = SYSCTL_CHILDREN(sc->stats_node);
  438 
  439         for (id = 0; id < EV_NQSTATS; id++) {
  440                 snprintf(name, sizeof(name), "ev_%s",
  441                          efx_ev_qstat_name(sc->enp, id));
  442                 SYSCTL_ADD_PROC(
  443                         ctx, stat_list,
  444                         OID_AUTO, name, CTLTYPE_U64|CTLFLAG_RD,
  445                         sc, id, sfxge_ev_stat_handler, "Q",
  446                         "");
  447         }
  448 }
  449 
  450 static void
  451 sfxge_ev_qmoderate(struct sfxge_softc *sc, unsigned int idx, unsigned int us)
  452 {
  453         struct sfxge_evq *evq;
  454         efx_evq_t *eep;
  455 
  456         evq = sc->evq[idx];
  457         eep = evq->common;
  458 
  459         KASSERT(evq->init_state == SFXGE_EVQ_STARTED,
  460             ("evq->init_state != SFXGE_EVQ_STARTED"));
  461 
  462         (void)efx_ev_qmoderate(eep, us);
  463 }
  464 
  465 static int
  466 sfxge_int_mod_handler(SYSCTL_HANDLER_ARGS)
  467 {
  468         struct sfxge_softc *sc = arg1;
  469         struct sfxge_intr *intr = &sc->intr;
  470         unsigned int moderation;
  471         int error;
  472         int index;
  473 
  474         sx_xlock(&sc->softc_lock);
  475 
  476         if (req->newptr) {
  477                 if ((error = SYSCTL_IN(req, &moderation, sizeof(moderation)))
  478                     != 0)
  479                         goto out;
  480 
  481                 /* We may not be calling efx_ev_qmoderate() now,
  482                  * so we have to range-check the value ourselves.
  483                  */
  484                 if (moderation >
  485                     efx_nic_cfg_get(sc->enp)->enc_evq_moderation_max) {
  486                         error = EINVAL;
  487                         goto out;
  488                 }
  489 
  490                 sc->ev_moderation = moderation;
  491                 if (intr->state == SFXGE_INTR_STARTED) {
  492                         for (index = 0; index < intr->n_alloc; index++)
  493                                 sfxge_ev_qmoderate(sc, index, moderation);
  494                 }
  495         } else {
  496                 error = SYSCTL_OUT(req, &sc->ev_moderation,
  497                                    sizeof(sc->ev_moderation));
  498         }
  499 
  500 out:
  501         sx_xunlock(&sc->softc_lock);
  502 
  503         return error;
  504 }
  505 
  506 static boolean_t
  507 sfxge_ev_initialized(void *arg)
  508 {
  509         struct sfxge_evq *evq;
  510         
  511         evq = (struct sfxge_evq *)arg;
  512 
  513         KASSERT(evq->init_state == SFXGE_EVQ_STARTING,
  514             ("evq not starting"));
  515 
  516         evq->init_state = SFXGE_EVQ_STARTED;
  517 
  518         return (0);
  519 }
  520 
  521 static boolean_t
  522 sfxge_ev_link_change(void *arg, efx_link_mode_t link_mode)
  523 {
  524         struct sfxge_evq *evq;
  525         struct sfxge_softc *sc;
  526 
  527         evq = (struct sfxge_evq *)arg;
  528         sc = evq->sc;
  529 
  530         sfxge_mac_link_update(sc, link_mode);
  531 
  532         return (0);
  533 }
  534 
  535 static const efx_ev_callbacks_t sfxge_ev_callbacks = {
  536         .eec_initialized        = sfxge_ev_initialized,
  537         .eec_rx                 = sfxge_ev_rx,
  538         .eec_tx                 = sfxge_ev_tx,
  539         .eec_exception          = sfxge_ev_exception,
  540         .eec_rxq_flush_done     = sfxge_ev_rxq_flush_done,
  541         .eec_rxq_flush_failed   = sfxge_ev_rxq_flush_failed,
  542         .eec_txq_flush_done     = sfxge_ev_txq_flush_done,
  543         .eec_software           = sfxge_ev_software,
  544         .eec_sram               = sfxge_ev_sram,
  545         .eec_wake_up            = sfxge_ev_wake_up,
  546         .eec_timer              = sfxge_ev_timer,
  547         .eec_link_change        = sfxge_ev_link_change,
  548 };
  549 
  550 
  551 int
  552 sfxge_ev_qpoll(struct sfxge_softc *sc, unsigned int index)
  553 {
  554         struct sfxge_evq *evq;
  555         int rc;
  556 
  557         evq = sc->evq[index];
  558 
  559         mtx_lock(&evq->lock);
  560 
  561         if (evq->init_state != SFXGE_EVQ_STARTING &&
  562             evq->init_state != SFXGE_EVQ_STARTED) {
  563                 rc = EINVAL;
  564                 goto fail;
  565         }
  566 
  567         /* Synchronize the DMA memory for reading */
  568         bus_dmamap_sync(evq->mem.esm_tag, evq->mem.esm_map,
  569             BUS_DMASYNC_POSTREAD);
  570 
  571         KASSERT(evq->rx_done == 0, ("evq->rx_done != 0"));
  572         KASSERT(evq->tx_done == 0, ("evq->tx_done != 0"));
  573         KASSERT(evq->txq == NULL, ("evq->txq != NULL"));
  574         KASSERT(evq->txqs == &evq->txq, ("evq->txqs != &evq->txq"));
  575 
  576         /* Poll the queue */
  577         efx_ev_qpoll(evq->common, &evq->read_ptr, &sfxge_ev_callbacks, evq);
  578 
  579         evq->rx_done = 0;
  580         evq->tx_done = 0;
  581 
  582         /* Perform any pending completion processing */
  583         sfxge_ev_qcomplete(evq, B_TRUE);
  584 
  585         /* Re-prime the event queue for interrupts */
  586         if ((rc = efx_ev_qprime(evq->common, evq->read_ptr)) != 0)
  587                 goto fail;
  588 
  589         mtx_unlock(&evq->lock);
  590 
  591         return (0);
  592 
  593 fail:
  594         mtx_unlock(&(evq->lock));
  595         return (rc);
  596 }
  597 
  598 static void
  599 sfxge_ev_qstop(struct sfxge_softc *sc, unsigned int index)
  600 {
  601         struct sfxge_evq *evq;
  602 
  603         evq = sc->evq[index];
  604 
  605         KASSERT(evq->init_state == SFXGE_EVQ_STARTED,
  606             ("evq->init_state != SFXGE_EVQ_STARTED"));
  607 
  608         mtx_lock(&evq->lock);
  609         evq->init_state = SFXGE_EVQ_INITIALIZED;
  610         evq->read_ptr = 0;
  611         evq->exception = B_FALSE;
  612 
  613         /* Add event counts before discarding the common evq state */
  614         efx_ev_qstats_update(evq->common, sc->ev_stats);
  615 
  616         efx_ev_qdestroy(evq->common);
  617         efx_sram_buf_tbl_clear(sc->enp, evq->buf_base_id,
  618             EFX_EVQ_NBUFS(SFXGE_NEVS));
  619         mtx_unlock(&evq->lock);
  620 }
  621 
  622 static int
  623 sfxge_ev_qstart(struct sfxge_softc *sc, unsigned int index)
  624 {
  625         struct sfxge_evq *evq;
  626         efsys_mem_t *esmp;
  627         int count;
  628         int rc;
  629 
  630         evq = sc->evq[index];
  631         esmp = &evq->mem;
  632 
  633         KASSERT(evq->init_state == SFXGE_EVQ_INITIALIZED,
  634             ("evq->init_state != SFXGE_EVQ_INITIALIZED"));
  635 
  636         /* Clear all events. */
  637         (void)memset(esmp->esm_base, 0xff, EFX_EVQ_SIZE(SFXGE_NEVS));
  638 
  639         /* Program the buffer table. */
  640         if ((rc = efx_sram_buf_tbl_set(sc->enp, evq->buf_base_id, esmp,
  641             EFX_EVQ_NBUFS(SFXGE_NEVS))) != 0)
  642                 return rc;
  643 
  644         /* Create the common code event queue. */
  645         if ((rc = efx_ev_qcreate(sc->enp, index, esmp, SFXGE_NEVS,
  646             evq->buf_base_id, &evq->common)) != 0)
  647                 goto fail;
  648 
  649         mtx_lock(&evq->lock);
  650 
  651         /* Set the default moderation */
  652         (void)efx_ev_qmoderate(evq->common, sc->ev_moderation);
  653 
  654         /* Prime the event queue for interrupts */
  655         if ((rc = efx_ev_qprime(evq->common, evq->read_ptr)) != 0)
  656                 goto fail2;
  657 
  658         evq->init_state = SFXGE_EVQ_STARTING;
  659 
  660         mtx_unlock(&evq->lock);
  661 
  662         /* Wait for the initialization event */
  663         count = 0;
  664         do {
  665                 /* Pause for 100 ms */
  666                 pause("sfxge evq init", hz / 10);
  667 
  668                 /* Check to see if the test event has been processed */
  669                 if (evq->init_state == SFXGE_EVQ_STARTED)
  670                         goto done;
  671 
  672         } while (++count < 20);
  673 
  674         rc = ETIMEDOUT;
  675         goto fail3;
  676 
  677 done:
  678         return (0);
  679 
  680 fail3:
  681         mtx_lock(&evq->lock);
  682         evq->init_state = SFXGE_EVQ_INITIALIZED;
  683 fail2:
  684         mtx_unlock(&evq->lock);
  685         efx_ev_qdestroy(evq->common);
  686 fail:
  687         efx_sram_buf_tbl_clear(sc->enp, evq->buf_base_id,
  688             EFX_EVQ_NBUFS(SFXGE_NEVS));
  689 
  690         return (rc);
  691 }
  692 
  693 void
  694 sfxge_ev_stop(struct sfxge_softc *sc)
  695 {
  696         struct sfxge_intr *intr;
  697         efx_nic_t *enp;
  698         int index;
  699 
  700         intr = &sc->intr;
  701         enp = sc->enp;
  702 
  703         KASSERT(intr->state == SFXGE_INTR_STARTED,
  704             ("Interrupts not started"));
  705 
  706         /* Stop the event queue(s) */
  707         index = intr->n_alloc;
  708         while (--index >= 0)
  709                 sfxge_ev_qstop(sc, index);
  710 
  711         /* Tear down the event module */
  712         efx_ev_fini(enp);
  713 }
  714 
  715 int
  716 sfxge_ev_start(struct sfxge_softc *sc)
  717 {
  718         struct sfxge_intr *intr;
  719         int index;
  720         int rc;
  721 
  722         intr = &sc->intr;
  723 
  724         KASSERT(intr->state == SFXGE_INTR_STARTED,
  725             ("intr->state != SFXGE_INTR_STARTED"));
  726 
  727         /* Initialize the event module */
  728         if ((rc = efx_ev_init(sc->enp)) != 0)
  729                 return rc;
  730 
  731         /* Start the event queues */
  732         for (index = 0; index < intr->n_alloc; index++) {
  733                 if ((rc = sfxge_ev_qstart(sc, index)) != 0)
  734                         goto fail;
  735         }
  736 
  737         return (0);
  738 
  739 fail:
  740         /* Stop the event queue(s) */
  741         while (--index >= 0)
  742                 sfxge_ev_qstop(sc, index);
  743 
  744         /* Tear down the event module */
  745         efx_ev_fini(sc->enp);
  746 
  747         return (rc);
  748 }
  749 
  750 static void
  751 sfxge_ev_qfini(struct sfxge_softc *sc, unsigned int index)
  752 {
  753         struct sfxge_evq *evq;
  754 
  755         evq = sc->evq[index];
  756 
  757         KASSERT(evq->init_state == SFXGE_EVQ_INITIALIZED,
  758             ("evq->init_state != SFXGE_EVQ_INITIALIZED"));
  759         KASSERT(evq->txqs == &evq->txq, ("evq->txqs != &evq->txq"));
  760 
  761         sfxge_dma_free(&evq->mem);
  762 
  763         sc->evq[index] = NULL;
  764 
  765         mtx_destroy(&evq->lock);
  766 
  767         free(evq, M_SFXGE);
  768 }
  769 
  770 static int
  771 sfxge_ev_qinit(struct sfxge_softc *sc, unsigned int index)
  772 {
  773         struct sfxge_evq *evq;
  774         efsys_mem_t *esmp;
  775         int rc;
  776 
  777         KASSERT(index < SFXGE_RX_SCALE_MAX, ("index >= SFXGE_RX_SCALE_MAX"));
  778 
  779         evq = malloc(sizeof(struct sfxge_evq), M_SFXGE, M_ZERO | M_WAITOK);
  780         evq->sc = sc;
  781         evq->index = index;
  782         sc->evq[index] = evq;
  783         esmp = &evq->mem;
  784 
  785         /* Initialise TX completion list */
  786         evq->txqs = &evq->txq;
  787 
  788         /* Allocate DMA space. */
  789         if ((rc = sfxge_dma_alloc(sc, EFX_EVQ_SIZE(SFXGE_NEVS), esmp)) != 0)
  790                 return (rc);
  791 
  792         /* Allocate buffer table entries. */
  793         sfxge_sram_buf_tbl_alloc(sc, EFX_EVQ_NBUFS(SFXGE_NEVS),
  794                                  &evq->buf_base_id);
  795 
  796         mtx_init(&evq->lock, "evq", NULL, MTX_DEF);
  797 
  798         evq->init_state = SFXGE_EVQ_INITIALIZED;
  799 
  800         return (0);
  801 }
  802 
  803 void
  804 sfxge_ev_fini(struct sfxge_softc *sc)
  805 {
  806         struct sfxge_intr *intr;
  807         int index;
  808 
  809         intr = &sc->intr;
  810 
  811         KASSERT(intr->state == SFXGE_INTR_INITIALIZED,
  812             ("intr->state != SFXGE_INTR_INITIALIZED"));
  813 
  814         sc->ev_moderation = 0;
  815 
  816         /* Tear down the event queue(s). */
  817         index = intr->n_alloc;
  818         while (--index >= 0)
  819                 sfxge_ev_qfini(sc, index);
  820 }
  821 
  822 int
  823 sfxge_ev_init(struct sfxge_softc *sc)
  824 {
  825         struct sysctl_ctx_list *sysctl_ctx = device_get_sysctl_ctx(sc->dev);
  826         struct sysctl_oid *sysctl_tree = device_get_sysctl_tree(sc->dev);
  827         struct sfxge_intr *intr;
  828         int index;
  829         int rc;
  830 
  831         intr = &sc->intr;
  832 
  833         KASSERT(intr->state == SFXGE_INTR_INITIALIZED,
  834             ("intr->state != SFXGE_INTR_INITIALIZED"));
  835 
  836         /* Set default interrupt moderation; add a sysctl to
  837          * read and change it.
  838          */
  839         sc->ev_moderation = 30;
  840         SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
  841                         OID_AUTO, "int_mod", CTLTYPE_UINT|CTLFLAG_RW,
  842                         sc, 0, sfxge_int_mod_handler, "IU",
  843                         "sfxge interrupt moderation (us)");
  844 
  845         /*
  846          * Initialize the event queue(s) - one per interrupt.
  847          */
  848         for (index = 0; index < intr->n_alloc; index++) {
  849                 if ((rc = sfxge_ev_qinit(sc, index)) != 0)
  850                         goto fail;
  851         }
  852 
  853         sfxge_ev_stat_init(sc);
  854 
  855         return (0);
  856 
  857 fail:
  858         while (--index >= 0)
  859                 sfxge_ev_qfini(sc, index);
  860 
  861         return (rc);
  862 }

Cache object: 394bb49ad4cf391dae9453627646a31d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.