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/dpaa/if_dtsec_rm.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) 2012 Semihalf.
    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
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD: releng/12.0/sys/dev/dpaa/if_dtsec_rm.c 326004 2017-11-20 04:32:01Z jhibbits $");
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/kernel.h>
   33 #include <sys/module.h>
   34 #include <sys/bus.h>
   35 #include <sys/rman.h>
   36 #include <sys/malloc.h>
   37 #include <sys/mbuf.h>
   38 #include <sys/socket.h>
   39 #include <sys/sysctl.h>
   40 #include <sys/sockio.h>
   41 
   42 #include <net/ethernet.h>
   43 #include <net/if.h>
   44 #include <net/if_dl.h>
   45 #include <net/if_media.h>
   46 #include <net/if_types.h>
   47 #include <net/if_arp.h>
   48 
   49 #include <dev/mii/mii.h>
   50 #include <dev/mii/miivar.h>
   51 
   52 #include "miibus_if.h"
   53 
   54 #include <contrib/ncsw/inc/integrations/dpaa_integration_ext.h>
   55 #include <contrib/ncsw/inc/Peripherals/fm_ext.h>
   56 #include <contrib/ncsw/inc/Peripherals/fm_mac_ext.h>
   57 #include <contrib/ncsw/inc/Peripherals/fm_port_ext.h>
   58 #include <contrib/ncsw/inc/xx_ext.h>
   59 
   60 #include "fman.h"
   61 #include "bman.h"
   62 #include "qman.h"
   63 #include "if_dtsec.h"
   64 #include "if_dtsec_rm.h"
   65 
   66 
   67 /**
   68  * @group dTSEC RM private defines.
   69  * @{
   70  */
   71 #define DTSEC_BPOOLS_USED       (1)
   72 #define DTSEC_MAX_TX_QUEUE_LEN  256
   73 
   74 struct dtsec_rm_frame_info {
   75         struct mbuf                     *fi_mbuf;
   76         t_DpaaSGTE                      fi_sgt[DPAA_NUM_OF_SG_TABLE_ENTRY];
   77 };
   78 
   79 enum dtsec_rm_pool_params {
   80         DTSEC_RM_POOL_RX_LOW_MARK       = 16,
   81         DTSEC_RM_POOL_RX_HIGH_MARK      = 64,
   82         DTSEC_RM_POOL_RX_MAX_SIZE       = 256,
   83 
   84         DTSEC_RM_POOL_FI_LOW_MARK       = 16,
   85         DTSEC_RM_POOL_FI_HIGH_MARK      = 64,
   86         DTSEC_RM_POOL_FI_MAX_SIZE       = 256,
   87 };
   88 
   89 enum dtsec_rm_fqr_params {
   90         DTSEC_RM_FQR_RX_CHANNEL         = e_QM_FQ_CHANNEL_POOL1,
   91         DTSEC_RM_FQR_RX_WQ              = 1,
   92         DTSEC_RM_FQR_TX_CONF_CHANNEL    = e_QM_FQ_CHANNEL_SWPORTAL0,
   93         DTSEC_RM_FQR_TX_WQ              = 1,
   94         DTSEC_RM_FQR_TX_CONF_WQ         = 1
   95 };
   96 /** @} */
   97 
   98 
   99 /**
  100  * @group dTSEC Frame Info routines.
  101  * @{
  102  */
  103 void
  104 dtsec_rm_fi_pool_free(struct dtsec_softc *sc)
  105 {
  106 
  107         if (sc->sc_fi_zone != NULL)
  108                 uma_zdestroy(sc->sc_fi_zone);
  109 }
  110 
  111 int
  112 dtsec_rm_fi_pool_init(struct dtsec_softc *sc)
  113 {
  114 
  115         snprintf(sc->sc_fi_zname, sizeof(sc->sc_fi_zname), "%s: Frame Info",
  116             device_get_nameunit(sc->sc_dev));
  117 
  118         sc->sc_fi_zone = uma_zcreate(sc->sc_fi_zname,
  119             sizeof(struct dtsec_rm_frame_info), NULL, NULL, NULL, NULL,
  120             UMA_ALIGN_PTR, 0);
  121         if (sc->sc_fi_zone == NULL)
  122                 return (EIO);
  123 
  124         return (0);
  125 }
  126 
  127 static struct dtsec_rm_frame_info *
  128 dtsec_rm_fi_alloc(struct dtsec_softc *sc)
  129 {
  130         struct dtsec_rm_frame_info *fi;
  131 
  132         fi = uma_zalloc(sc->sc_fi_zone, M_NOWAIT);
  133 
  134         return (fi);
  135 }
  136 
  137 static void
  138 dtsec_rm_fi_free(struct dtsec_softc *sc, struct dtsec_rm_frame_info *fi)
  139 {
  140 
  141         uma_zfree(sc->sc_fi_zone, fi);
  142 }
  143 /** @} */
  144 
  145 
  146 /**
  147  * @group dTSEC FMan PORT routines.
  148  * @{
  149  */
  150 int
  151 dtsec_rm_fm_port_rx_init(struct dtsec_softc *sc, int unit)
  152 {
  153         t_FmPortParams params;
  154         t_FmPortRxParams *rx_params;
  155         t_FmExtPools *pool_params;
  156         t_Error error;
  157 
  158         memset(&params, 0, sizeof(params));
  159 
  160         params.baseAddr = sc->sc_fm_base + sc->sc_port_rx_hw_id;
  161         params.h_Fm = sc->sc_fmh;
  162         params.portType = dtsec_fm_port_rx_type(sc->sc_eth_dev_type);
  163         params.portId = sc->sc_eth_id;
  164         params.independentModeEnable = false;
  165         params.liodnBase = FM_PORT_LIODN_BASE;
  166         params.f_Exception = dtsec_fm_port_rx_exception_callback;
  167         params.h_App = sc;
  168 
  169         rx_params = &params.specificParams.rxParams;
  170         rx_params->errFqid = sc->sc_rx_fqid;
  171         rx_params->dfltFqid = sc->sc_rx_fqid;
  172         rx_params->liodnOffset = 0;
  173 
  174         pool_params = &rx_params->extBufPools;
  175         pool_params->numOfPoolsUsed = DTSEC_BPOOLS_USED;
  176         pool_params->extBufPool->id = sc->sc_rx_bpid;
  177         pool_params->extBufPool->size = FM_PORT_BUFFER_SIZE;
  178 
  179         sc->sc_rxph = FM_PORT_Config(&params);
  180         if (sc->sc_rxph == NULL) {
  181                 device_printf(sc->sc_dev, "couldn't configure FM Port RX.\n");
  182                 return (ENXIO);
  183         }
  184 
  185         error = FM_PORT_Init(sc->sc_rxph);
  186         if (error != E_OK) {
  187                 device_printf(sc->sc_dev, "couldn't initialize FM Port RX.\n");
  188                 FM_PORT_Free(sc->sc_rxph);
  189                 return (ENXIO);
  190         }
  191 
  192         if (bootverbose)
  193                 device_printf(sc->sc_dev, "RX hw port 0x%02x initialized.\n",
  194                     sc->sc_port_rx_hw_id);
  195 
  196         return (0);
  197 }
  198 
  199 int
  200 dtsec_rm_fm_port_tx_init(struct dtsec_softc *sc, int unit)
  201 {
  202         t_FmPortParams params;
  203         t_FmPortNonRxParams *tx_params;
  204         t_Error error;
  205 
  206         memset(&params, 0, sizeof(params));
  207 
  208         params.baseAddr = sc->sc_fm_base + sc->sc_port_tx_hw_id;
  209         params.h_Fm = sc->sc_fmh;
  210         params.portType = dtsec_fm_port_tx_type(sc->sc_eth_dev_type);
  211         params.portId = sc->sc_eth_id;
  212         params.independentModeEnable = false;
  213         params.liodnBase = FM_PORT_LIODN_BASE;
  214         params.f_Exception = dtsec_fm_port_tx_exception_callback;
  215         params.h_App = sc;
  216 
  217         tx_params = &params.specificParams.nonRxParams;
  218         tx_params->errFqid = sc->sc_tx_conf_fqid;
  219         tx_params->dfltFqid = sc->sc_tx_conf_fqid;
  220         tx_params->qmChannel = sc->sc_port_tx_qman_chan;
  221 #ifdef FM_OP_PARTITION_ERRATA_FMANx8
  222         tx_params->opLiodnOffset = 0;
  223 #endif
  224 
  225         sc->sc_txph = FM_PORT_Config(&params);
  226         if (sc->sc_txph == NULL) {
  227                 device_printf(sc->sc_dev, "couldn't configure FM Port TX.\n");
  228                 return (ENXIO);
  229         }
  230 
  231         error = FM_PORT_Init(sc->sc_txph);
  232         if (error != E_OK) {
  233                 device_printf(sc->sc_dev, "couldn't initialize FM Port TX.\n");
  234                 FM_PORT_Free(sc->sc_txph);
  235                 return (ENXIO);
  236         }
  237 
  238         if (bootverbose)
  239                 device_printf(sc->sc_dev, "TX hw port 0x%02x initialized.\n",
  240                     sc->sc_port_tx_hw_id);
  241 
  242         return (0);
  243 }
  244 /** @} */
  245 
  246 
  247 /**
  248  * @group dTSEC buffer pools routines.
  249  * @{
  250  */
  251 static t_Error
  252 dtsec_rm_pool_rx_put_buffer(t_Handle h_BufferPool, uint8_t *buffer,
  253     t_Handle context)
  254 {
  255         struct dtsec_softc *sc;
  256 
  257         sc = h_BufferPool;
  258         uma_zfree(sc->sc_rx_zone, buffer);
  259 
  260         return (E_OK);
  261 }
  262 
  263 static uint8_t *
  264 dtsec_rm_pool_rx_get_buffer(t_Handle h_BufferPool, t_Handle *context)
  265 {
  266         struct dtsec_softc *sc;
  267         uint8_t *buffer;
  268 
  269         sc = h_BufferPool;
  270         buffer = uma_zalloc(sc->sc_rx_zone, M_NOWAIT);
  271 
  272         return (buffer);
  273 }
  274 
  275 static void
  276 dtsec_rm_pool_rx_depleted(t_Handle h_App, bool in)
  277 {
  278         struct dtsec_softc *sc;
  279         unsigned int count;
  280 
  281         sc = h_App;
  282 
  283         if (!in)
  284                 return;
  285 
  286         while (1) {
  287                 count = bman_count(sc->sc_rx_pool);
  288                 if (count > DTSEC_RM_POOL_RX_HIGH_MARK)
  289                         return;
  290 
  291                 bman_pool_fill(sc->sc_rx_pool, DTSEC_RM_POOL_RX_HIGH_MARK);
  292         }
  293 }
  294 
  295 void
  296 dtsec_rm_pool_rx_free(struct dtsec_softc *sc)
  297 {
  298 
  299         if (sc->sc_rx_pool != NULL)
  300                 bman_pool_destroy(sc->sc_rx_pool);
  301 
  302         if (sc->sc_rx_zone != NULL)
  303                 uma_zdestroy(sc->sc_rx_zone);
  304 }
  305 
  306 int
  307 dtsec_rm_pool_rx_init(struct dtsec_softc *sc)
  308 {
  309 
  310         /* FM_PORT_BUFFER_SIZE must be less than PAGE_SIZE */
  311         CTASSERT(FM_PORT_BUFFER_SIZE < PAGE_SIZE);
  312 
  313         snprintf(sc->sc_rx_zname, sizeof(sc->sc_rx_zname), "%s: RX Buffers",
  314             device_get_nameunit(sc->sc_dev));
  315 
  316         sc->sc_rx_zone = uma_zcreate(sc->sc_rx_zname, FM_PORT_BUFFER_SIZE, NULL,
  317             NULL, NULL, NULL, FM_PORT_BUFFER_SIZE - 1, 0);
  318         if (sc->sc_rx_zone == NULL)
  319                 return (EIO);
  320 
  321         sc->sc_rx_pool = bman_pool_create(&sc->sc_rx_bpid, FM_PORT_BUFFER_SIZE,
  322             0, 0, DTSEC_RM_POOL_RX_MAX_SIZE, dtsec_rm_pool_rx_get_buffer,
  323             dtsec_rm_pool_rx_put_buffer, DTSEC_RM_POOL_RX_LOW_MARK,
  324             DTSEC_RM_POOL_RX_HIGH_MARK, 0, 0, dtsec_rm_pool_rx_depleted, sc, NULL,
  325             NULL);
  326         if (sc->sc_rx_pool == NULL) {
  327                 device_printf(sc->sc_dev, "NULL rx pool  somehow\n");
  328                 dtsec_rm_pool_rx_free(sc);
  329                 return (EIO);
  330         }
  331 
  332         return (0);
  333 }
  334 /** @} */
  335 
  336 
  337 /**
  338  * @group dTSEC Frame Queue Range routines.
  339  * @{
  340  */
  341 static void
  342 dtsec_rm_fqr_mext_free(struct mbuf *m)
  343 {
  344         struct dtsec_softc *sc;
  345         void *buffer;
  346 
  347         buffer = m->m_ext.ext_arg1;
  348         sc = m->m_ext.ext_arg2;
  349         if (bman_count(sc->sc_rx_pool) <= DTSEC_RM_POOL_RX_MAX_SIZE)
  350                 bman_put_buffer(sc->sc_rx_pool, buffer);
  351         else
  352                 dtsec_rm_pool_rx_put_buffer(sc, buffer, NULL);
  353 }
  354 
  355 static e_RxStoreResponse
  356 dtsec_rm_fqr_rx_callback(t_Handle app, t_Handle fqr, t_Handle portal,
  357     uint32_t fqid_off, t_DpaaFD *frame)
  358 {
  359         struct dtsec_softc *sc;
  360         struct mbuf *m;
  361         void *frame_va;
  362 
  363         m = NULL;
  364         sc = app;
  365 
  366         frame_va = DPAA_FD_GET_ADDR(frame);
  367         KASSERT(DPAA_FD_GET_FORMAT(frame) == e_DPAA_FD_FORMAT_TYPE_SHORT_SBSF,
  368             ("%s(): Got unsupported frame format 0x%02X!", __func__,
  369             DPAA_FD_GET_FORMAT(frame)));
  370 
  371         KASSERT(DPAA_FD_GET_OFFSET(frame) == 0,
  372             ("%s(): Only offset 0 is supported!", __func__));
  373 
  374         if (DPAA_FD_GET_STATUS(frame) != 0) {
  375                 device_printf(sc->sc_dev, "RX error: 0x%08X\n",
  376                     DPAA_FD_GET_STATUS(frame));
  377                 goto err;
  378         }
  379 
  380         m = m_gethdr(M_NOWAIT, MT_HEADER);
  381         if (m == NULL)
  382                 goto err;
  383 
  384         m_extadd(m, frame_va, FM_PORT_BUFFER_SIZE,
  385             dtsec_rm_fqr_mext_free, frame_va, sc, 0,
  386             EXT_NET_DRV);
  387 
  388         m->m_pkthdr.rcvif = sc->sc_ifnet;
  389         m->m_len = DPAA_FD_GET_LENGTH(frame);
  390         m_fixhdr(m);
  391 
  392         (*sc->sc_ifnet->if_input)(sc->sc_ifnet, m);
  393 
  394         return (e_RX_STORE_RESPONSE_CONTINUE);
  395 
  396 err:
  397         bman_put_buffer(sc->sc_rx_pool, frame_va);
  398         if (m != NULL)
  399                 m_freem(m);
  400 
  401         return (e_RX_STORE_RESPONSE_CONTINUE);
  402 }
  403 
  404 static e_RxStoreResponse
  405 dtsec_rm_fqr_tx_confirm_callback(t_Handle app, t_Handle fqr, t_Handle portal,
  406     uint32_t fqid_off, t_DpaaFD *frame)
  407 {
  408         struct dtsec_rm_frame_info *fi;
  409         struct dtsec_softc *sc;
  410         unsigned int qlen;
  411         t_DpaaSGTE *sgt0;
  412 
  413         sc = app;
  414 
  415         if (DPAA_FD_GET_STATUS(frame) != 0)
  416                 device_printf(sc->sc_dev, "TX error: 0x%08X\n",
  417                     DPAA_FD_GET_STATUS(frame));
  418 
  419         /*
  420          * We are storing struct dtsec_rm_frame_info in first entry
  421          * of scatter-gather table.
  422          */
  423         sgt0 = DPAA_FD_GET_ADDR(frame);
  424         fi = DPAA_SGTE_GET_ADDR(sgt0);
  425 
  426         /* Free transmitted frame */
  427         m_freem(fi->fi_mbuf);
  428         dtsec_rm_fi_free(sc, fi);
  429 
  430         qlen = qman_fqr_get_counter(sc->sc_tx_conf_fqr, 0,
  431             e_QM_FQR_COUNTERS_FRAME);
  432 
  433         if (qlen == 0) {
  434                 DTSEC_LOCK(sc);
  435 
  436                 if (sc->sc_tx_fqr_full) {
  437                         sc->sc_tx_fqr_full = 0;
  438                         dtsec_rm_if_start_locked(sc);
  439                 }
  440 
  441                 DTSEC_UNLOCK(sc);
  442         }
  443 
  444         return (e_RX_STORE_RESPONSE_CONTINUE);
  445 }
  446 
  447 void
  448 dtsec_rm_fqr_rx_free(struct dtsec_softc *sc)
  449 {
  450 
  451         if (sc->sc_rx_fqr)
  452                 qman_fqr_free(sc->sc_rx_fqr);
  453 }
  454 
  455 int
  456 dtsec_rm_fqr_rx_init(struct dtsec_softc *sc)
  457 {
  458         t_Error error;
  459         t_Handle fqr;
  460 
  461         /* Default Frame Queue */
  462         fqr = qman_fqr_create(1, DTSEC_RM_FQR_RX_CHANNEL, DTSEC_RM_FQR_RX_WQ,
  463             false, 0, false, false, true, false, 0, 0, 0);
  464         if (fqr == NULL) {
  465                 device_printf(sc->sc_dev, "could not create default RX queue"
  466                     "\n");
  467                 return (EIO);
  468         }
  469 
  470         sc->sc_rx_fqr = fqr;
  471         sc->sc_rx_fqid = qman_fqr_get_base_fqid(fqr);
  472 
  473         error = qman_fqr_register_cb(fqr, dtsec_rm_fqr_rx_callback, sc);
  474         if (error != E_OK) {
  475                 device_printf(sc->sc_dev, "could not register RX callback\n");
  476                 dtsec_rm_fqr_rx_free(sc);
  477                 return (EIO);
  478         }
  479 
  480         return (0);
  481 }
  482 
  483 void
  484 dtsec_rm_fqr_tx_free(struct dtsec_softc *sc)
  485 {
  486 
  487         if (sc->sc_tx_fqr)
  488                 qman_fqr_free(sc->sc_tx_fqr);
  489 
  490         if (sc->sc_tx_conf_fqr)
  491                 qman_fqr_free(sc->sc_tx_conf_fqr);
  492 }
  493 
  494 int
  495 dtsec_rm_fqr_tx_init(struct dtsec_softc *sc)
  496 {
  497         t_Error error;
  498         t_Handle fqr;
  499 
  500         /* TX Frame Queue */
  501         fqr = qman_fqr_create(1, sc->sc_port_tx_qman_chan,
  502             DTSEC_RM_FQR_TX_WQ, false, 0, false, false, true, false, 0, 0, 0);
  503         if (fqr == NULL) {
  504                 device_printf(sc->sc_dev, "could not create default TX queue"
  505                     "\n");
  506                 return (EIO);
  507         }
  508 
  509         sc->sc_tx_fqr = fqr;
  510 
  511         /* TX Confirmation Frame Queue */
  512         fqr = qman_fqr_create(1, DTSEC_RM_FQR_TX_CONF_CHANNEL,
  513             DTSEC_RM_FQR_TX_CONF_WQ, false, 0, false, false, true, false, 0, 0,
  514             0);
  515         if (fqr == NULL) {
  516                 device_printf(sc->sc_dev, "could not create TX confirmation "
  517                     "queue\n");
  518                 dtsec_rm_fqr_tx_free(sc);
  519                 return (EIO);
  520         }
  521 
  522         sc->sc_tx_conf_fqr = fqr;
  523         sc->sc_tx_conf_fqid = qman_fqr_get_base_fqid(fqr);
  524 
  525         error = qman_fqr_register_cb(fqr, dtsec_rm_fqr_tx_confirm_callback, sc);
  526         if (error != E_OK) {
  527                 device_printf(sc->sc_dev, "could not register TX confirmation "
  528                     "callback\n");
  529                 dtsec_rm_fqr_tx_free(sc);
  530                 return (EIO);
  531         }
  532 
  533         return (0);
  534 }
  535 /** @} */
  536 
  537 
  538 /**
  539  * @group dTSEC IFnet routines.
  540  * @{
  541  */
  542 void
  543 dtsec_rm_if_start_locked(struct dtsec_softc *sc)
  544 {
  545         vm_size_t dsize, psize, ssize;
  546         struct dtsec_rm_frame_info *fi;
  547         unsigned int qlen, i;
  548         struct mbuf *m0, *m;
  549         vm_offset_t vaddr;
  550         t_DpaaFD fd;
  551 
  552         DTSEC_LOCK_ASSERT(sc);
  553         /* TODO: IFF_DRV_OACTIVE */
  554 
  555         if ((sc->sc_mii->mii_media_status & IFM_ACTIVE) == 0)
  556                 return;
  557 
  558         if ((sc->sc_ifnet->if_drv_flags & IFF_DRV_RUNNING) != IFF_DRV_RUNNING)
  559                 return;
  560 
  561         while (!IFQ_DRV_IS_EMPTY(&sc->sc_ifnet->if_snd)) {
  562                 /* Check length of the TX queue */
  563                 qlen = qman_fqr_get_counter(sc->sc_tx_fqr, 0,
  564                     e_QM_FQR_COUNTERS_FRAME);
  565 
  566                 if (qlen >= DTSEC_MAX_TX_QUEUE_LEN) {
  567                         sc->sc_tx_fqr_full = 1;
  568                         return;
  569                 }
  570 
  571                 fi = dtsec_rm_fi_alloc(sc);
  572                 if (fi == NULL)
  573                         return;
  574 
  575                 IFQ_DRV_DEQUEUE(&sc->sc_ifnet->if_snd, m0);
  576                 if (m0 == NULL) {
  577                         dtsec_rm_fi_free(sc, fi);
  578                         return;
  579                 }
  580 
  581                 i = 0;
  582                 m = m0;
  583                 psize = 0;
  584                 dsize = 0;
  585                 fi->fi_mbuf = m0;
  586                 while (m && i < DPAA_NUM_OF_SG_TABLE_ENTRY) {
  587                         if (m->m_len == 0)
  588                                 continue;
  589 
  590                         /*
  591                          * First entry in scatter-gather table is used to keep
  592                          * pointer to frame info structure.
  593                          */
  594                         DPAA_SGTE_SET_ADDR(&fi->fi_sgt[i], (void *)fi);
  595                         DPAA_SGTE_SET_LENGTH(&fi->fi_sgt[i], 0);
  596 
  597                         DPAA_SGTE_SET_EXTENSION(&fi->fi_sgt[i], 0);
  598                         DPAA_SGTE_SET_FINAL(&fi->fi_sgt[i], 0);
  599                         DPAA_SGTE_SET_BPID(&fi->fi_sgt[i], 0);
  600                         DPAA_SGTE_SET_OFFSET(&fi->fi_sgt[i], 0);
  601                         i++;
  602 
  603                         dsize = m->m_len;
  604                         vaddr = (vm_offset_t)m->m_data;
  605                         while (dsize > 0 && i < DPAA_NUM_OF_SG_TABLE_ENTRY) {
  606                                 ssize = PAGE_SIZE - (vaddr & PAGE_MASK);
  607                                 if (m->m_len < ssize)
  608                                         ssize = m->m_len;
  609 
  610                                 DPAA_SGTE_SET_ADDR(&fi->fi_sgt[i],
  611                                     (void *)vaddr);
  612                                 DPAA_SGTE_SET_LENGTH(&fi->fi_sgt[i], ssize);
  613 
  614                                 DPAA_SGTE_SET_EXTENSION(&fi->fi_sgt[i], 0);
  615                                 DPAA_SGTE_SET_FINAL(&fi->fi_sgt[i], 0);
  616                                 DPAA_SGTE_SET_BPID(&fi->fi_sgt[i], 0);
  617                                 DPAA_SGTE_SET_OFFSET(&fi->fi_sgt[i], 0);
  618 
  619                                 dsize -= ssize;
  620                                 vaddr += ssize;
  621                                 psize += ssize;
  622                                 i++;
  623                         }
  624 
  625                         if (dsize > 0)
  626                                 break;
  627 
  628                         m = m->m_next;
  629                 }
  630 
  631                 /* Check if SG table was constructed properly */
  632                 if (m != NULL || dsize != 0) {
  633                         dtsec_rm_fi_free(sc, fi);
  634                         m_freem(m0);
  635                         continue;
  636                 }
  637 
  638                 DPAA_SGTE_SET_FINAL(&fi->fi_sgt[i-1], 1);
  639 
  640                 DPAA_FD_SET_ADDR(&fd, fi->fi_sgt);
  641                 DPAA_FD_SET_LENGTH(&fd, psize);
  642                 DPAA_FD_SET_FORMAT(&fd, e_DPAA_FD_FORMAT_TYPE_SHORT_MBSF);
  643 
  644                 fd.liodn = 0;
  645                 fd.bpid = 0;
  646                 fd.elion = 0;
  647                 DPAA_FD_SET_OFFSET(&fd, 0);
  648                 DPAA_FD_SET_STATUS(&fd, 0);
  649 
  650                 DTSEC_UNLOCK(sc);
  651                 if (qman_fqr_enqueue(sc->sc_tx_fqr, 0, &fd) != E_OK) {
  652                         dtsec_rm_fi_free(sc, fi);
  653                         m_freem(m0);
  654                 }
  655                 DTSEC_LOCK(sc);
  656         }
  657 }
  658 /** @} */

Cache object: b8cb832d25e2c93f578bea3118e941bd


[ 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.