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/oce/oce_queue.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  * SPDX-License-Identifier: BSD-3-Clause
    3  *
    4  * Copyright (C) 2013 Emulex
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions are met:
    9  *
   10  * 1. Redistributions of source code must retain the above copyright notice,
   11  *    this list of conditions and the following disclaimer.
   12  *
   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  * 3. Neither the name of the Emulex Corporation nor the names of its
   18  *    contributors may be used to endorse or promote products derived from
   19  *    this software without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   31  * POSSIBILITY OF SUCH DAMAGE.
   32  *
   33  * Contact Information:
   34  * freebsd-drivers@emulex.com
   35  *
   36  * Emulex
   37  * 3333 Susan Street
   38  * Costa Mesa, CA 92626
   39  */
   40 
   41 /* $FreeBSD$ */
   42 
   43 #include "oce_if.h"
   44 
   45 /*****************************************************
   46  * local queue functions
   47  *****************************************************/
   48 
   49 static struct oce_wq *oce_wq_init(POCE_SOFTC sc,
   50                                   uint32_t q_len, uint32_t wq_type);
   51 static int oce_wq_create(struct oce_wq *wq, struct oce_eq *eq);
   52 static void oce_wq_free(struct oce_wq *wq);
   53 static void oce_wq_del(struct oce_wq *wq);
   54 static struct oce_rq *oce_rq_init(POCE_SOFTC sc,
   55                                   uint32_t q_len,
   56                                   uint32_t frag_size,
   57                                   uint32_t mtu, uint32_t rss);
   58 static int oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq);
   59 static void oce_rq_free(struct oce_rq *rq);
   60 static void oce_rq_del(struct oce_rq *rq);
   61 static struct oce_eq *oce_eq_create(POCE_SOFTC sc,
   62                                     uint32_t q_len,
   63                                     uint32_t item_size,
   64                                     uint32_t eq_delay,
   65                                     uint32_t vector);
   66 static void oce_eq_del(struct oce_eq *eq);
   67 static struct oce_mq *oce_mq_create(POCE_SOFTC sc,
   68                                     struct oce_eq *eq, uint32_t q_len);
   69 static void oce_mq_free(struct oce_mq *mq);
   70 static int oce_destroy_q(POCE_SOFTC sc, struct oce_mbx
   71                          *mbx, size_t req_size, enum qtype qtype, int version);
   72 struct oce_cq *oce_cq_create(POCE_SOFTC sc,
   73                              struct oce_eq *eq,
   74                              uint32_t q_len,
   75                              uint32_t item_size,
   76                              uint32_t sol_event,
   77                              uint32_t is_eventable,
   78                              uint32_t nodelay, uint32_t ncoalesce);
   79 static void oce_cq_del(POCE_SOFTC sc, struct oce_cq *cq);
   80 
   81 
   82 
   83 /**
   84  * @brief       Create and initialize all the queues on the board
   85  * @param sc    software handle to the device
   86  * @returns 0   if successful, or error
   87  **/
   88 int
   89 oce_queue_init_all(POCE_SOFTC sc)
   90 {
   91         int rc = 0, i, vector;
   92         struct oce_wq *wq;
   93         struct oce_rq *rq;
   94         struct oce_aic_obj *aic;
   95 
   96         /* alloc TX/RX queues */
   97         for_all_wq_queues(sc, wq, i) {
   98                 sc->wq[i] = oce_wq_init(sc, sc->tx_ring_size,
   99                                          NIC_WQ_TYPE_STANDARD);
  100                 if (!sc->wq[i]) 
  101                         goto error;
  102                 
  103         }
  104 
  105         for_all_rq_queues(sc, rq, i) {
  106                 sc->rq[i] = oce_rq_init(sc, sc->rx_ring_size, sc->rq_frag_size,
  107                                         OCE_MAX_JUMBO_FRAME_SIZE,
  108                                         (i == 0) ? 0 : is_rss_enabled(sc));
  109                 if (!sc->rq[i]) 
  110                         goto error;
  111         }
  112 
  113         /* Create network interface on card */
  114         if (oce_create_nw_interface(sc))
  115                 goto error;
  116 
  117         /* create all of the event queues */
  118         for (vector = 0; vector < sc->intr_count; vector++) {
  119                 /* setup aic defaults for each event queue */
  120                 aic = &sc->aic_obj[vector];
  121                 aic->max_eqd = OCE_MAX_EQD;
  122                 aic->min_eqd = OCE_MIN_EQD;
  123                 aic->et_eqd = OCE_MIN_EQD;
  124                 aic->enable = TRUE;
  125         
  126                 sc->eq[vector] = oce_eq_create(sc, sc->enable_hwlro ? EQ_LEN_2048 : EQ_LEN_1024,
  127                                                 EQE_SIZE_4,0, vector);  
  128 
  129                 if (!sc->eq[vector])
  130                         goto error;
  131         }
  132 
  133         /* create Tx, Rx and mcc queues */
  134         for_all_wq_queues(sc, wq, i) {
  135                 rc = oce_wq_create(wq, sc->eq[i]);
  136                 if (rc)
  137                         goto error;
  138                 wq->queue_index = i;
  139                 TASK_INIT(&wq->txtask, 1, oce_tx_task, wq);
  140         }
  141 
  142         for_all_rq_queues(sc, rq, i) {
  143                 rc = oce_rq_create(rq, sc->if_id,
  144                                         sc->eq[(i == 0) ? 0:(i-1)]);
  145                 if (rc)
  146                         goto error;
  147                 rq->queue_index = i;
  148         }
  149 
  150         sc->mq = oce_mq_create(sc, sc->eq[0], 64);
  151         if (!sc->mq)
  152                 goto error;
  153 
  154         return rc;
  155 
  156 error:
  157         oce_queue_release_all(sc);
  158         return 1;
  159 }
  160 
  161 
  162 
  163 /**
  164  * @brief Releases all mailbox queues created
  165  * @param sc            software handle to the device
  166  */
  167 void
  168 oce_queue_release_all(POCE_SOFTC sc)
  169 {
  170         int i = 0;
  171         struct oce_wq *wq;
  172         struct oce_rq *rq;
  173         struct oce_eq *eq;
  174 
  175         /* before deleting lro queues, we have to disable hwlro */
  176         if(sc->enable_hwlro)
  177                 oce_mbox_nic_set_iface_lro_config(sc, 0);
  178 
  179         for_all_rq_queues(sc, rq, i) {
  180                 if (rq) {
  181                         oce_rq_del(sc->rq[i]);
  182                         oce_rq_free(sc->rq[i]);
  183                 }
  184         }
  185 
  186         for_all_wq_queues(sc, wq, i) {
  187                 if (wq) {
  188                         oce_wq_del(sc->wq[i]);
  189                         oce_wq_free(sc->wq[i]);
  190                 }
  191         }
  192 
  193         if (sc->mq)
  194                 oce_mq_free(sc->mq);
  195 
  196         for_all_evnt_queues(sc, eq, i) {
  197                 if (eq)
  198                         oce_eq_del(sc->eq[i]);
  199         }
  200 }
  201 
  202 
  203 
  204 /**
  205  * @brief               Function to create a WQ for NIC Tx
  206  * @param sc            software handle to the device
  207  * @param qlen          number of entries in the queue
  208  * @param wq_type       work queue type
  209  * @returns             the pointer to the WQ created or NULL on failure
  210  */
  211 static struct
  212 oce_wq *oce_wq_init(POCE_SOFTC sc, uint32_t q_len, uint32_t wq_type)
  213 {
  214         struct oce_wq *wq;
  215         int rc = 0, i;
  216 
  217         /* q_len must be min 256 and max 2k */
  218         if (q_len < 256 || q_len > 2048) {
  219                 device_printf(sc->dev,
  220                           "Invalid q length. Must be "
  221                           "[256, 2000]: 0x%x\n", q_len);
  222                 return NULL;
  223         }
  224 
  225         /* allocate wq */
  226         wq = malloc(sizeof(struct oce_wq), M_DEVBUF, M_NOWAIT | M_ZERO);
  227         if (!wq)
  228                 return NULL;
  229 
  230         /* Set the wq config */
  231         wq->cfg.q_len = q_len;
  232         wq->cfg.wq_type = (uint8_t) wq_type;
  233         wq->cfg.eqd = OCE_DEFAULT_WQ_EQD;
  234         wq->cfg.nbufs = 2 * wq->cfg.q_len;
  235         wq->cfg.nhdl = 2 * wq->cfg.q_len;
  236 
  237         wq->parent = (void *)sc;
  238 
  239         rc = bus_dma_tag_create(bus_get_dma_tag(sc->dev),
  240                                 1, 0,
  241                                 BUS_SPACE_MAXADDR,
  242                                 BUS_SPACE_MAXADDR,
  243                                 NULL, NULL,
  244                                 OCE_MAX_TX_SIZE,
  245                                 OCE_MAX_TX_ELEMENTS,
  246                                 PAGE_SIZE, 0, NULL, NULL, &wq->tag);
  247 
  248         if (rc)
  249                 goto free_wq;
  250 
  251 
  252         for (i = 0; i < OCE_WQ_PACKET_ARRAY_SIZE; i++) {
  253                 rc = bus_dmamap_create(wq->tag, 0, &wq->pckts[i].map);
  254                 if (rc) 
  255                         goto free_wq;
  256         }
  257 
  258         wq->ring = oce_create_ring_buffer(sc, q_len, NIC_WQE_SIZE);
  259         if (!wq->ring)
  260                 goto free_wq;
  261 
  262 
  263         LOCK_CREATE(&wq->tx_lock, "TX_lock");
  264         LOCK_CREATE(&wq->tx_compl_lock, "WQ_HANDLER_LOCK");
  265         
  266 #if __FreeBSD_version >= 800000
  267         /* Allocate buf ring for multiqueue*/
  268         wq->br = buf_ring_alloc(4096, M_DEVBUF,
  269                         M_WAITOK, &wq->tx_lock.mutex);
  270         if (!wq->br)
  271                 goto free_wq;
  272 #endif
  273         return wq;
  274 
  275 
  276 free_wq:
  277         device_printf(sc->dev, "Create WQ failed\n");
  278         oce_wq_free(wq);
  279         return NULL;
  280 }
  281 
  282 
  283 
  284 /**
  285  * @brief               Frees the work queue
  286  * @param wq            pointer to work queue to free
  287  */
  288 static void
  289 oce_wq_free(struct oce_wq *wq)
  290 {
  291         POCE_SOFTC sc = (POCE_SOFTC) wq->parent;
  292         int i;
  293 
  294         taskqueue_drain(taskqueue_swi, &wq->txtask);
  295 
  296         if (wq->ring != NULL) {
  297                 oce_destroy_ring_buffer(sc, wq->ring);
  298                 wq->ring = NULL;
  299         }
  300 
  301         for (i = 0; i < OCE_WQ_PACKET_ARRAY_SIZE; i++) {
  302                 if (wq->pckts[i].map != NULL) {
  303                         bus_dmamap_unload(wq->tag, wq->pckts[i].map);
  304                         bus_dmamap_destroy(wq->tag, wq->pckts[i].map);
  305                         wq->pckts[i].map = NULL;
  306                 }
  307         }
  308 
  309         if (wq->tag != NULL)
  310                 bus_dma_tag_destroy(wq->tag);
  311         if (wq->br != NULL)
  312                 buf_ring_free(wq->br, M_DEVBUF);
  313 
  314         LOCK_DESTROY(&wq->tx_lock);
  315         LOCK_DESTROY(&wq->tx_compl_lock);
  316         free(wq, M_DEVBUF);
  317 }
  318 
  319 
  320 
  321 /**
  322  * @brief               Create a work queue
  323  * @param wq            pointer to work queue
  324  * @param eq            pointer to associated event queue
  325  */
  326 static int
  327 oce_wq_create(struct oce_wq *wq, struct oce_eq *eq)
  328 {
  329         POCE_SOFTC sc = wq->parent;
  330         struct oce_cq *cq;
  331         int rc = 0;
  332 
  333         /* create the CQ */
  334         cq = oce_cq_create(sc,
  335                            eq,
  336                            CQ_LEN_1024,
  337                            sizeof(struct oce_nic_tx_cqe), 0, 1, 0, 3);
  338         if (!cq)
  339                 return ENXIO;
  340 
  341 
  342         wq->cq = cq;
  343 
  344         rc = oce_mbox_create_wq(wq);
  345         if (rc)
  346                 goto error;
  347 
  348         wq->qstate = QCREATED;
  349         wq->wq_free = wq->cfg.q_len;
  350         wq->ring->cidx = 0;
  351         wq->ring->pidx = 0;
  352 
  353         eq->cq[eq->cq_valid] = cq;
  354         eq->cq_valid++;
  355         cq->cb_arg = wq;
  356         cq->cq_handler = oce_wq_handler;
  357 
  358         return 0;
  359 
  360 error:
  361         device_printf(sc->dev, "WQ create failed\n");
  362         oce_wq_del(wq);
  363         return rc;
  364 }
  365 
  366 
  367 
  368 
  369 /**
  370  * @brief               Delete a work queue
  371  * @param wq            pointer to work queue
  372  */
  373 static void
  374 oce_wq_del(struct oce_wq *wq)
  375 {
  376         struct oce_mbx mbx;
  377         struct mbx_delete_nic_wq *fwcmd;
  378         POCE_SOFTC sc = (POCE_SOFTC) wq->parent;
  379 
  380         if (wq->qstate == QCREATED) {
  381                 bzero(&mbx, sizeof(struct oce_mbx));
  382                 /* now fill the command */
  383                 fwcmd = (struct mbx_delete_nic_wq *)&mbx.payload;
  384                 fwcmd->params.req.wq_id = wq->wq_id;
  385                 (void)oce_destroy_q(sc, &mbx,
  386                                 sizeof(struct mbx_delete_nic_wq), QTYPE_WQ, 0);
  387                 wq->qstate = QDELETED;
  388         }
  389 
  390         if (wq->cq != NULL) {
  391                 oce_cq_del(sc, wq->cq);
  392                 wq->cq = NULL;
  393         }
  394 }
  395 
  396 
  397 
  398 /**
  399  * @brief               function to allocate receive queue resources
  400  * @param sc            software handle to the device
  401  * @param q_len         length of receive queue
  402  * @param frag_size     size of an receive queue fragment
  403  * @param mtu           maximum transmission unit
  404  * @param rss           is-rss-queue flag
  405  * @returns             the pointer to the RQ created or NULL on failure
  406  */
  407 static struct
  408 oce_rq *oce_rq_init(POCE_SOFTC sc,
  409                                   uint32_t q_len,
  410                                   uint32_t frag_size,
  411                                   uint32_t mtu, uint32_t rss)
  412 {
  413         struct oce_rq *rq;
  414         int rc = 0, i;
  415 
  416         if (OCE_LOG2(frag_size) <= 0)
  417                 return NULL;
  418         
  419         if ((q_len == 0) || (q_len > 1024))
  420                 return NULL;
  421 
  422         /* allocate the rq */
  423         rq = malloc(sizeof(struct oce_rq), M_DEVBUF, M_NOWAIT | M_ZERO);
  424         if (!rq) 
  425                 return NULL;
  426 
  427         
  428         rq->cfg.q_len = q_len;
  429         rq->cfg.frag_size = frag_size;
  430         rq->cfg.mtu = mtu;
  431         rq->cfg.eqd = 0;
  432         rq->lro_pkts_queued = 0;
  433         rq->cfg.is_rss_queue = rss;
  434         rq->pending = 0;
  435 
  436         rq->parent = (void *)sc;
  437 
  438         rc = bus_dma_tag_create(bus_get_dma_tag(sc->dev),
  439                         1, 0,
  440                         BUS_SPACE_MAXADDR,
  441                         BUS_SPACE_MAXADDR,
  442                         NULL, NULL,
  443                         oce_rq_buf_size,
  444                         1, oce_rq_buf_size, 0, NULL, NULL, &rq->tag);
  445         if (rc)
  446                 goto free_rq;
  447 
  448         for (i = 0; i < OCE_RQ_PACKET_ARRAY_SIZE; i++) {
  449                 rc = bus_dmamap_create(rq->tag, 0, &rq->pckts[i].map);
  450                 if (rc)
  451                         goto free_rq;
  452         }
  453 
  454         /* create the ring buffer */
  455         rq->ring = oce_create_ring_buffer(sc, q_len,
  456                                  sizeof(struct oce_nic_rqe));
  457         if (!rq->ring)
  458                 goto free_rq;
  459 
  460         LOCK_CREATE(&rq->rx_lock, "RX_lock");
  461 
  462         return rq;
  463 
  464 free_rq:
  465         device_printf(sc->dev, "Create RQ failed\n");
  466         oce_rq_free(rq);
  467         return NULL;
  468 }
  469 
  470 
  471 
  472 
  473 /**
  474  * @brief               Free a receive queue
  475  * @param rq            pointer to receive queue
  476  */
  477 static void
  478 oce_rq_free(struct oce_rq *rq)
  479 {
  480         POCE_SOFTC sc = (POCE_SOFTC) rq->parent;
  481         int i = 0 ;
  482 
  483         if (rq->ring != NULL) {
  484                 oce_destroy_ring_buffer(sc, rq->ring);
  485                 rq->ring = NULL;
  486         }
  487         for (i = 0; i < OCE_RQ_PACKET_ARRAY_SIZE; i++) {
  488                 if (rq->pckts[i].map != NULL) {
  489                         bus_dmamap_unload(rq->tag, rq->pckts[i].map);
  490                         bus_dmamap_destroy(rq->tag, rq->pckts[i].map);
  491                         rq->pckts[i].map = NULL;
  492                 }
  493                 if (rq->pckts[i].mbuf) {
  494                         m_free(rq->pckts[i].mbuf);
  495                         rq->pckts[i].mbuf = NULL;
  496                 }
  497         }
  498 
  499         if (rq->tag != NULL)
  500                 bus_dma_tag_destroy(rq->tag);
  501 
  502         LOCK_DESTROY(&rq->rx_lock);
  503         free(rq, M_DEVBUF);
  504 }
  505 
  506 
  507 
  508 
  509 /**
  510  * @brief               Create a receive queue
  511  * @param rq            receive queue
  512  * @param if_id         interface identifier index`
  513  * @param eq            pointer to event queue
  514  */
  515 static int
  516 oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq)
  517 {
  518         POCE_SOFTC sc = rq->parent;
  519         struct oce_cq *cq;
  520 
  521         cq = oce_cq_create(sc, eq,
  522                         sc->enable_hwlro ? CQ_LEN_2048 : CQ_LEN_1024,
  523                         sizeof(struct oce_nic_rx_cqe), 0, 1, 0, 3);             
  524                         
  525         if (!cq)
  526                 return ENXIO;
  527 
  528         rq->cq = cq;
  529         rq->cfg.if_id = if_id;
  530 
  531         /* Dont create RQ here. Create in if_activate */
  532         rq->qstate     = 0;
  533         rq->ring->cidx = 0;
  534         rq->ring->pidx = 0;
  535         eq->cq[eq->cq_valid] = cq;
  536         eq->cq_valid++;
  537         cq->cb_arg = rq;
  538         cq->cq_handler = oce_rq_handler;
  539 
  540         return 0;
  541 
  542 }
  543 
  544 
  545 
  546 
  547 /**
  548  * @brief               Delete a receive queue
  549  * @param rq            receive queue
  550  */
  551 static void
  552 oce_rq_del(struct oce_rq *rq)
  553 {
  554         POCE_SOFTC sc = (POCE_SOFTC) rq->parent;
  555         struct oce_mbx mbx;
  556         struct mbx_delete_nic_rq *fwcmd;
  557         struct mbx_delete_nic_rq_v1 *fwcmd1;
  558 
  559         if (rq->qstate == QCREATED) {
  560                 bzero(&mbx, sizeof(mbx));
  561                 if(!rq->islro) {
  562                         fwcmd = (struct mbx_delete_nic_rq *)&mbx.payload;
  563                         fwcmd->params.req.rq_id = rq->rq_id;
  564                         (void)oce_destroy_q(sc, &mbx, sizeof(struct mbx_delete_nic_rq), QTYPE_RQ, 0);
  565                 }else {
  566                         fwcmd1 = (struct mbx_delete_nic_rq_v1 *)&mbx.payload;
  567                         fwcmd1->params.req.rq_id = rq->rq_id;
  568                         fwcmd1->params.req.rq_flags = (NIC_RQ_FLAGS_RSS | NIC_RQ_FLAGS_LRO);
  569                         (void)oce_destroy_q(sc, &mbx, sizeof(struct mbx_delete_nic_rq_v1), QTYPE_RQ, 1);
  570                 }
  571                 rq->qstate = QDELETED;
  572         }
  573 
  574         if (rq->cq != NULL) {
  575                 oce_cq_del(sc, rq->cq);
  576                 rq->cq = NULL;
  577         }
  578 }
  579 
  580 
  581 
  582 /**
  583  * @brief               function to create an event queue
  584  * @param sc            software handle to the device
  585  * @param q_len         length of event queue
  586  * @param item_size     size of an event queue item
  587  * @param eq_delay      event queue delay
  588  * @retval eq           success, pointer to event queue
  589  * @retval NULL         failure
  590  */
  591 static struct
  592 oce_eq *oce_eq_create(POCE_SOFTC sc, uint32_t q_len,
  593                                     uint32_t item_size,
  594                                     uint32_t eq_delay,
  595                                     uint32_t vector)
  596 {
  597         struct oce_eq *eq;
  598         int rc = 0;
  599 
  600         /* allocate an eq */
  601         eq = malloc(sizeof(struct oce_eq), M_DEVBUF, M_NOWAIT | M_ZERO);
  602         if (eq == NULL)
  603                 return NULL;
  604 
  605         eq->parent = (void *)sc;
  606         eq->eq_id = 0xffff;
  607         eq->ring = oce_create_ring_buffer(sc, q_len, item_size);
  608         if (!eq->ring)
  609                 goto free_eq;
  610         
  611         eq->eq_cfg.q_len = q_len;
  612         eq->eq_cfg.item_size = item_size;
  613         eq->eq_cfg.cur_eqd = (uint8_t) eq_delay;
  614 
  615         rc = oce_mbox_create_eq(eq);
  616         if (rc)
  617                 goto free_eq;
  618 
  619         sc->intrs[sc->neqs++].eq = eq;
  620 
  621         return eq;
  622 
  623 free_eq:
  624         oce_eq_del(eq);
  625         return NULL;
  626 }
  627 
  628 
  629 
  630 
  631 /**
  632  * @brief               Function to delete an event queue
  633  * @param eq            pointer to an event queue
  634  */
  635 static void
  636 oce_eq_del(struct oce_eq *eq)
  637 {
  638         struct oce_mbx mbx;
  639         struct mbx_destroy_common_eq *fwcmd;
  640         POCE_SOFTC sc = (POCE_SOFTC) eq->parent;
  641 
  642         if (eq->eq_id != 0xffff) {
  643                 bzero(&mbx, sizeof(mbx));
  644                 fwcmd = (struct mbx_destroy_common_eq *)&mbx.payload;
  645                 fwcmd->params.req.id = eq->eq_id;
  646                 (void)oce_destroy_q(sc, &mbx,
  647                         sizeof(struct mbx_destroy_common_eq), QTYPE_EQ, 0);
  648         }
  649 
  650         if (eq->ring != NULL) {
  651                 oce_destroy_ring_buffer(sc, eq->ring);
  652                 eq->ring = NULL;
  653         }
  654 
  655         free(eq, M_DEVBUF);
  656 
  657 }
  658 
  659 
  660 
  661 
  662 /**
  663  * @brief               Function to create an MQ
  664  * @param sc            software handle to the device
  665  * @param eq            the EQ to associate with the MQ for event notification
  666  * @param q_len         the number of entries to create in the MQ
  667  * @returns             pointer to the created MQ, failure otherwise
  668  */
  669 static struct oce_mq *
  670 oce_mq_create(POCE_SOFTC sc, struct oce_eq *eq, uint32_t q_len)
  671 {
  672         struct oce_mbx mbx;
  673         struct mbx_create_common_mq_ex *fwcmd = NULL;
  674         struct oce_mq *mq = NULL;
  675         int rc = 0;
  676         struct oce_cq *cq;
  677         oce_mq_ext_ctx_t *ctx;
  678         uint32_t num_pages;
  679         uint32_t page_size;
  680         int version;
  681 
  682         cq = oce_cq_create(sc, eq, CQ_LEN_256,
  683                         sizeof(struct oce_mq_cqe), 1, 1, 0, 0);
  684         if (!cq)
  685                 return NULL;
  686 
  687         /* allocate the mq */
  688         mq = malloc(sizeof(struct oce_mq), M_DEVBUF, M_NOWAIT | M_ZERO);
  689         if (!mq) {
  690                 oce_cq_del(sc, cq);
  691                 goto error;
  692         }
  693 
  694         mq->parent = sc;
  695 
  696         mq->ring = oce_create_ring_buffer(sc, q_len, sizeof(struct oce_mbx));
  697         if (!mq->ring)
  698                 goto error;
  699 
  700         bzero(&mbx, sizeof(struct oce_mbx));
  701 
  702         IS_XE201(sc) ? (version = OCE_MBX_VER_V1) : (version = OCE_MBX_VER_V0);
  703         fwcmd = (struct mbx_create_common_mq_ex *)&mbx.payload;
  704         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
  705                                 MBX_SUBSYSTEM_COMMON,
  706                                 OPCODE_COMMON_CREATE_MQ_EXT,
  707                                 MBX_TIMEOUT_SEC,
  708                                 sizeof(struct mbx_create_common_mq_ex),
  709                                 version);
  710 
  711         num_pages = oce_page_list(mq->ring, &fwcmd->params.req.pages[0]);
  712         page_size = mq->ring->num_items * mq->ring->item_size;
  713 
  714         ctx = &fwcmd->params.req.context;
  715 
  716         if (IS_XE201(sc)) {
  717                 ctx->v1.num_pages = num_pages;
  718                 ctx->v1.ring_size = OCE_LOG2(q_len) + 1;
  719                 ctx->v1.cq_id = cq->cq_id;
  720                 ctx->v1.valid = 1;
  721                 ctx->v1.async_cq_id = cq->cq_id;
  722                 ctx->v1.async_cq_valid = 1;
  723                 /* Subscribe to Link State and Group 5 Events(bits 1 & 5 set) */
  724                 ctx->v1.async_evt_bitmap |= LE_32(0x00000022);
  725                 ctx->v1.async_evt_bitmap |= LE_32(1 << ASYNC_EVENT_CODE_DEBUG);
  726                 ctx->v1.async_evt_bitmap |=
  727                                         LE_32(1 << ASYNC_EVENT_CODE_SLIPORT);
  728         }
  729         else {
  730                 ctx->v0.num_pages = num_pages;
  731                 ctx->v0.cq_id = cq->cq_id;
  732                 ctx->v0.ring_size = OCE_LOG2(q_len) + 1;
  733                 ctx->v0.valid = 1;
  734                 /* Subscribe to Link State and Group5 Events(bits 1 & 5 set) */
  735                 ctx->v0.async_evt_bitmap = 0xffffffff;
  736         }
  737 
  738         mbx.u0.s.embedded = 1;
  739         mbx.payload_length = sizeof(struct mbx_create_common_mq_ex);
  740         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
  741 
  742         rc = oce_mbox_post(sc, &mbx, NULL);
  743         if (!rc)
  744                 rc = fwcmd->hdr.u0.rsp.status;
  745         if (rc) {
  746                 device_printf(sc->dev,"%s failed - cmd status: %d\n",
  747                               __FUNCTION__, rc);
  748                 goto error;
  749         }
  750         mq->mq_id = LE_16(fwcmd->params.rsp.mq_id);
  751         mq->cq = cq;
  752         eq->cq[eq->cq_valid] = cq;
  753         eq->cq_valid++;
  754         mq->cq->eq = eq;
  755         mq->cfg.q_len = (uint8_t) q_len;
  756         mq->cfg.eqd = 0;
  757         mq->qstate = QCREATED;
  758 
  759         mq->cq->cb_arg = mq;
  760         mq->cq->cq_handler = oce_mq_handler;
  761 
  762         return mq;
  763 
  764 error:
  765         device_printf(sc->dev, "MQ create failed\n");
  766         oce_mq_free(mq);
  767         mq = NULL;
  768         return mq;
  769 }
  770 
  771 
  772 
  773 
  774 
  775 /**
  776  * @brief               Function to free a mailbox queue
  777  * @param mq            pointer to a mailbox queue
  778  */
  779 static void
  780 oce_mq_free(struct oce_mq *mq)
  781 {
  782         POCE_SOFTC sc = (POCE_SOFTC) mq->parent;
  783         struct oce_mbx mbx;
  784         struct mbx_destroy_common_mq *fwcmd;
  785 
  786         if (!mq)
  787                 return;
  788 
  789         if (mq->ring != NULL) {
  790                 oce_destroy_ring_buffer(sc, mq->ring);
  791                 mq->ring = NULL;
  792                 if (mq->qstate == QCREATED) {
  793                         bzero(&mbx, sizeof (struct oce_mbx));
  794                         fwcmd = (struct mbx_destroy_common_mq *)&mbx.payload;
  795                         fwcmd->params.req.id = mq->mq_id;
  796                         (void) oce_destroy_q(sc, &mbx,
  797                                 sizeof (struct mbx_destroy_common_mq),
  798                                 QTYPE_MQ, 0);
  799                 }
  800                 mq->qstate = QDELETED;
  801         }
  802 
  803         if (mq->cq != NULL) {
  804                 oce_cq_del(sc, mq->cq);
  805                 mq->cq = NULL;
  806         }
  807 
  808         free(mq, M_DEVBUF);
  809         mq = NULL;
  810 }
  811 
  812 
  813 
  814 /**
  815  * @brief               Function to delete a EQ, CQ, MQ, WQ or RQ
  816  * @param sc            sofware handle to the device
  817  * @param mbx           mailbox command to send to the fw to delete the queue
  818  *                      (mbx contains the queue information to delete)
  819  * @param req_size      the size of the mbx payload dependent on the qtype
  820  * @param qtype         the type of queue i.e. EQ, CQ, MQ, WQ or RQ
  821  * @returns             0 on success, failure otherwise
  822  */
  823 static int
  824 oce_destroy_q(POCE_SOFTC sc, struct oce_mbx *mbx, size_t req_size,
  825                 enum qtype qtype, int version)
  826 {
  827         struct mbx_hdr *hdr = (struct mbx_hdr *)&mbx->payload;
  828         int opcode;
  829         int subsys;
  830         int rc = 0;
  831 
  832         switch (qtype) {
  833         case QTYPE_EQ:
  834                 opcode = OPCODE_COMMON_DESTROY_EQ;
  835                 subsys = MBX_SUBSYSTEM_COMMON;
  836                 break;
  837         case QTYPE_CQ:
  838                 opcode = OPCODE_COMMON_DESTROY_CQ;
  839                 subsys = MBX_SUBSYSTEM_COMMON;
  840                 break;
  841         case QTYPE_MQ:
  842                 opcode = OPCODE_COMMON_DESTROY_MQ;
  843                 subsys = MBX_SUBSYSTEM_COMMON;
  844                 break;
  845         case QTYPE_WQ:
  846                 opcode = NIC_DELETE_WQ;
  847                 subsys = MBX_SUBSYSTEM_NIC;
  848                 break;
  849         case QTYPE_RQ:
  850                 opcode = NIC_DELETE_RQ;
  851                 subsys = MBX_SUBSYSTEM_NIC;
  852                 break;
  853         default:
  854                 return EINVAL;
  855         }
  856 
  857         mbx_common_req_hdr_init(hdr, 0, 0, subsys,
  858                                 opcode, MBX_TIMEOUT_SEC, req_size,
  859                                 version);
  860 
  861         mbx->u0.s.embedded = 1;
  862         mbx->payload_length = (uint32_t) req_size;
  863         DW_SWAP(u32ptr(mbx), mbx->payload_length + OCE_BMBX_RHDR_SZ);
  864 
  865         rc = oce_mbox_post(sc, mbx, NULL);
  866         if (!rc)
  867                 rc = hdr->u0.rsp.status;
  868         if (rc)
  869                 device_printf(sc->dev,"%s failed - cmd status: %d\n",
  870                               __FUNCTION__, rc);
  871         return rc;
  872 }
  873 
  874 
  875 
  876 /**
  877  * @brief               Function to create a completion queue
  878  * @param sc            software handle to the device
  879  * @param eq            optional eq to be associated with to the cq
  880  * @param q_len         length of completion queue
  881  * @param item_size     size of completion queue items
  882  * @param sol_event     command context event
  883  * @param is_eventable  event table
  884  * @param nodelay       no delay flag
  885  * @param ncoalesce     no coalescence flag
  886  * @returns             pointer to the cq created, NULL on failure
  887  */
  888 struct oce_cq *
  889 oce_cq_create(POCE_SOFTC sc, struct oce_eq *eq,
  890                              uint32_t q_len,
  891                              uint32_t item_size,
  892                              uint32_t sol_event,
  893                              uint32_t is_eventable,
  894                              uint32_t nodelay, uint32_t ncoalesce)
  895 {
  896         struct oce_cq *cq = NULL;
  897         int rc = 0;
  898 
  899         cq = malloc(sizeof(struct oce_cq), M_DEVBUF, M_NOWAIT | M_ZERO);
  900         if (!cq)
  901                 return NULL;
  902 
  903         cq->ring = oce_create_ring_buffer(sc, q_len, item_size);
  904         if (!cq->ring)
  905                 goto error;
  906         
  907         cq->parent = sc;
  908         cq->eq = eq;
  909         cq->cq_cfg.q_len = q_len;
  910         cq->cq_cfg.item_size = item_size;
  911         cq->cq_cfg.nodelay = (uint8_t) nodelay;
  912 
  913         rc = oce_mbox_cq_create(cq, ncoalesce, is_eventable);
  914         if (rc)
  915                 goto error;
  916 
  917         sc->cq[sc->ncqs++] = cq;
  918 
  919         return cq;
  920 
  921 error:
  922         device_printf(sc->dev, "CQ create failed\n");
  923         oce_cq_del(sc, cq);
  924         return NULL;
  925 }
  926 
  927 
  928 
  929 /**
  930  * @brief               Deletes the completion queue
  931  * @param sc            software handle to the device
  932  * @param cq            pointer to a completion queue
  933  */
  934 static void 
  935 oce_cq_del(POCE_SOFTC sc, struct oce_cq *cq)
  936 {
  937         struct oce_mbx mbx;
  938         struct mbx_destroy_common_cq *fwcmd;
  939 
  940         if (cq->ring != NULL) {
  941 
  942                 bzero(&mbx, sizeof(struct oce_mbx));
  943                 /* now fill the command */
  944                 fwcmd = (struct mbx_destroy_common_cq *)&mbx.payload;
  945                 fwcmd->params.req.id = cq->cq_id;
  946                 (void)oce_destroy_q(sc, &mbx,
  947                         sizeof(struct mbx_destroy_common_cq), QTYPE_CQ, 0);
  948                 /*NOW destroy the ring */
  949                 oce_destroy_ring_buffer(sc, cq->ring);
  950                 cq->ring = NULL;
  951         }
  952 
  953         free(cq, M_DEVBUF);
  954         cq = NULL;
  955 }
  956 
  957 
  958 
  959 /**
  960  * @brief               Start a receive queue
  961  * @param rq            pointer to a receive queue
  962  */
  963 int
  964 oce_start_rq(struct oce_rq *rq)
  965 {
  966         POCE_SOFTC sc = (POCE_SOFTC) rq->parent;
  967         int rc;
  968 
  969         if(sc->enable_hwlro)
  970                 rc = oce_alloc_rx_bufs(rq, 960);
  971         else
  972                 rc = oce_alloc_rx_bufs(rq, rq->cfg.q_len - 1);
  973 
  974         if (rc == 0)
  975                 oce_arm_cq(rq->parent, rq->cq->cq_id, 0, TRUE);
  976 
  977         return rc;
  978 }
  979 
  980 
  981 
  982 /**
  983  * @brief               Start a work queue
  984  * @param wq            pointer to a work queue
  985  */
  986 int
  987 oce_start_wq(struct oce_wq *wq)
  988 {
  989         oce_arm_cq(wq->parent, wq->cq->cq_id, 0, TRUE);
  990         return 0;
  991 }
  992 
  993 
  994 
  995 /**
  996  * @brief               Start a mailbox queue
  997  * @param mq            pointer to a mailbox queue
  998  */
  999 int
 1000 oce_start_mq(struct oce_mq *mq)
 1001 {
 1002         oce_arm_cq(mq->parent, mq->cq->cq_id, 0, TRUE);
 1003         return 0;
 1004 }
 1005 
 1006 
 1007 
 1008 /**
 1009  * @brief               Function to arm an EQ so that it can generate events
 1010  * @param sc            software handle to the device
 1011  * @param qid           id of the EQ returned by the fw at the time of creation
 1012  * @param npopped       number of EQEs to arm
 1013  * @param rearm         rearm bit enable/disable
 1014  * @param clearint      bit to clear the interrupt condition because of which
 1015  *                      EQEs are generated
 1016  */
 1017 void
 1018 oce_arm_eq(POCE_SOFTC sc,
 1019            int16_t qid, int npopped, uint32_t rearm, uint32_t clearint)
 1020 {
 1021         eq_db_t eq_db = { 0 };
 1022 
 1023         eq_db.bits.rearm = rearm;
 1024         eq_db.bits.event = 1;
 1025         eq_db.bits.num_popped = npopped;
 1026         eq_db.bits.clrint = clearint;
 1027         eq_db.bits.qid = qid;
 1028         OCE_WRITE_REG32(sc, db, PD_EQ_DB, eq_db.dw0);
 1029 
 1030 }
 1031 
 1032 
 1033 
 1034 
 1035 /**
 1036  * @brief               Function to arm a CQ with CQEs
 1037  * @param sc            software handle to the device
 1038  * @param qid           id of the CQ returned by the fw at the time of creation
 1039  * @param npopped       number of CQEs to arm
 1040  * @param rearm         rearm bit enable/disable
 1041  */
 1042 void oce_arm_cq(POCE_SOFTC sc, int16_t qid, int npopped, uint32_t rearm)
 1043 {
 1044         cq_db_t cq_db = { 0 };
 1045 
 1046         cq_db.bits.rearm = rearm;
 1047         cq_db.bits.num_popped = npopped;
 1048         cq_db.bits.event = 0;
 1049         cq_db.bits.qid = qid;
 1050         OCE_WRITE_REG32(sc, db, PD_CQ_DB, cq_db.dw0);
 1051 
 1052 }
 1053 
 1054 
 1055 
 1056 
 1057 /*
 1058  * @brief               function to cleanup the eqs used during stop
 1059  * @param eq            pointer to event queue structure
 1060  * @returns             the number of EQs processed
 1061  */
 1062 void
 1063 oce_drain_eq(struct oce_eq *eq)
 1064 {
 1065 
 1066         struct oce_eqe *eqe;
 1067         uint16_t num_eqe = 0;
 1068         POCE_SOFTC sc = eq->parent;
 1069 
 1070         do {
 1071                 eqe = RING_GET_CONSUMER_ITEM_VA(eq->ring, struct oce_eqe);
 1072                 if (eqe->evnt == 0)
 1073                         break;
 1074                 eqe->evnt = 0;
 1075                 bus_dmamap_sync(eq->ring->dma.tag, eq->ring->dma.map,
 1076                                         BUS_DMASYNC_POSTWRITE);
 1077                 num_eqe++;
 1078                 RING_GET(eq->ring, 1);
 1079 
 1080         } while (TRUE);
 1081 
 1082         oce_arm_eq(sc, eq->eq_id, num_eqe, FALSE, TRUE);
 1083         
 1084 }
 1085 
 1086 
 1087 
 1088 void
 1089 oce_drain_wq_cq(struct oce_wq *wq)
 1090 {
 1091         POCE_SOFTC sc = wq->parent;
 1092         struct oce_cq *cq = wq->cq;
 1093         struct oce_nic_tx_cqe *cqe;
 1094         int num_cqes = 0;
 1095 
 1096         bus_dmamap_sync(cq->ring->dma.tag, cq->ring->dma.map,
 1097                                  BUS_DMASYNC_POSTWRITE);
 1098 
 1099         do {
 1100                 cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_tx_cqe);
 1101                 if (cqe->u0.dw[3] == 0)
 1102                         break;                  
 1103                 cqe->u0.dw[3] = 0;
 1104                 bus_dmamap_sync(cq->ring->dma.tag, cq->ring->dma.map,
 1105                                  BUS_DMASYNC_POSTWRITE);
 1106                 RING_GET(cq->ring, 1);
 1107                 num_cqes++;
 1108 
 1109         } while (TRUE);
 1110 
 1111         oce_arm_cq(sc, cq->cq_id, num_cqes, FALSE);
 1112 
 1113 }
 1114 
 1115 
 1116 /*
 1117  * @brief               function to drain a MCQ and process its CQEs
 1118  * @param dev           software handle to the device
 1119  * @param cq            pointer to the cq to drain
 1120  * @returns             the number of CQEs processed
 1121  */
 1122 void
 1123 oce_drain_mq_cq(void *arg)
 1124 {
 1125         /* TODO: additional code. */
 1126         return;
 1127 }
 1128 
 1129 
 1130 
 1131 /**
 1132  * @brief               function to process a Recieve queue
 1133  * @param arg           pointer to the RQ to charge
 1134  * @return              number of cqes processed
 1135  */
 1136 void
 1137 oce_drain_rq_cq(struct oce_rq *rq)
 1138 {
 1139         struct oce_nic_rx_cqe *cqe;
 1140         uint16_t num_cqe = 0;
 1141         struct oce_cq  *cq;
 1142         POCE_SOFTC sc;
 1143 
 1144         sc = rq->parent;
 1145         cq = rq->cq;
 1146         cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_rx_cqe);
 1147         /* dequeue till you reach an invalid cqe */
 1148         while (RQ_CQE_VALID(cqe)) {
 1149                 RQ_CQE_INVALIDATE(cqe);
 1150                 RING_GET(cq->ring, 1);
 1151                 cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring,
 1152                     struct oce_nic_rx_cqe);
 1153                 num_cqe++;
 1154         }
 1155         oce_arm_cq(sc, cq->cq_id, num_cqe, FALSE);
 1156 
 1157         return;
 1158 }
 1159 
 1160 
 1161 void
 1162 oce_free_posted_rxbuf(struct oce_rq *rq)
 1163 {
 1164         struct oce_packet_desc *pd;
 1165         
 1166         while (rq->pending) {
 1167 
 1168                 pd = &rq->pckts[rq->ring->cidx];
 1169                 bus_dmamap_sync(rq->tag, pd->map, BUS_DMASYNC_POSTWRITE);
 1170                 bus_dmamap_unload(rq->tag, pd->map);
 1171                 if (pd->mbuf != NULL) {
 1172                         m_freem(pd->mbuf);
 1173                         pd->mbuf = NULL;
 1174                 }
 1175 
 1176                 RING_GET(rq->ring,1);
 1177                 rq->pending--;
 1178         }
 1179 
 1180 }
 1181 
 1182 void
 1183 oce_rx_cq_clean_hwlro(struct oce_rq *rq)
 1184 {
 1185         struct oce_cq *cq = rq->cq;
 1186         POCE_SOFTC sc = rq->parent;
 1187         struct nic_hwlro_singleton_cqe *cqe;
 1188         struct nic_hwlro_cqe_part2 *cqe2;
 1189         int flush_wait = 0;
 1190         int flush_compl = 0;
 1191         int num_frags = 0;
 1192 
 1193         for (;;) {
 1194                 bus_dmamap_sync(cq->ring->dma.tag,cq->ring->dma.map, BUS_DMASYNC_POSTWRITE);
 1195                 cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct nic_hwlro_singleton_cqe);
 1196                 if(cqe->valid) {
 1197                         if(cqe->cqe_type == 0) { /* singleton cqe */
 1198                                 /* we should not get singleton cqe after cqe1 on same rq */
 1199                                 if(rq->cqe_firstpart != NULL) {
 1200                                         device_printf(sc->dev, "Got singleton cqe after cqe1 \n");
 1201                                         goto exit_rx_cq_clean_hwlro;
 1202                                 }
 1203                                 num_frags = cqe->pkt_size / rq->cfg.frag_size;
 1204                                 if(cqe->pkt_size % rq->cfg.frag_size)
 1205                                         num_frags++;
 1206                                 oce_discard_rx_comp(rq, num_frags);
 1207                                 /* Check if CQE is flush completion */
 1208                                 if(!cqe->pkt_size) 
 1209                                         flush_compl = 1;
 1210                                 cqe->valid = 0;
 1211                                 RING_GET(cq->ring, 1);
 1212                         }else if(cqe->cqe_type == 0x1) { /* first part */
 1213                                 /* we should not get cqe1 after cqe1 on same rq */
 1214                                 if(rq->cqe_firstpart != NULL) {
 1215                                         device_printf(sc->dev, "Got cqe1 after cqe1 \n");
 1216                                         goto exit_rx_cq_clean_hwlro;
 1217                                 }
 1218                                 rq->cqe_firstpart = (struct nic_hwlro_cqe_part1 *)cqe;
 1219                                 RING_GET(cq->ring, 1);
 1220                         }else if(cqe->cqe_type == 0x2) { /* second part */
 1221                                 cqe2 = (struct nic_hwlro_cqe_part2 *)cqe;
 1222                                 /* We should not get cqe2 without cqe1 */
 1223                                 if(rq->cqe_firstpart == NULL) {
 1224                                         device_printf(sc->dev, "Got cqe2 without cqe1 \n");
 1225                                         goto exit_rx_cq_clean_hwlro;
 1226                                 }
 1227                                 num_frags = cqe2->coalesced_size / rq->cfg.frag_size;
 1228                                 if(cqe2->coalesced_size % rq->cfg.frag_size)
 1229                                         num_frags++;
 1230                                 
 1231                                 /* Flush completion will always come in singleton CQE */
 1232                                 oce_discard_rx_comp(rq, num_frags);
 1233 
 1234                                 rq->cqe_firstpart->valid = 0;
 1235                                 cqe2->valid = 0;
 1236                                 rq->cqe_firstpart = NULL;
 1237                                 RING_GET(cq->ring, 1);
 1238                         }
 1239                         oce_arm_cq(sc, cq->cq_id, 1, FALSE);
 1240                         if(flush_compl)
 1241                                 break;
 1242                 }else {
 1243                         if (flush_wait++ > 100) {
 1244                                 device_printf(sc->dev, "did not receive hwlro flush compl\n");
 1245                                 break;
 1246                         }
 1247                         oce_arm_cq(sc, cq->cq_id, 0, TRUE);
 1248                         DELAY(1000);
 1249                 }
 1250         }
 1251 
 1252         /* After cleanup, leave the CQ in unarmed state */
 1253         oce_arm_cq(sc, cq->cq_id, 0, FALSE);
 1254 
 1255 exit_rx_cq_clean_hwlro:
 1256         return;
 1257 }
 1258 
 1259 
 1260 void
 1261 oce_rx_cq_clean(struct oce_rq *rq)
 1262 {
 1263         struct oce_nic_rx_cqe *cqe;
 1264         struct oce_cq  *cq;
 1265         POCE_SOFTC sc;
 1266         int flush_wait = 0;
 1267         int flush_compl = 0;
 1268         sc = rq->parent;
 1269         cq = rq->cq;
 1270         
 1271         for (;;) {
 1272                 bus_dmamap_sync(cq->ring->dma.tag,
 1273                         cq->ring->dma.map, BUS_DMASYNC_POSTWRITE);
 1274                 cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_rx_cqe);
 1275                 if(RQ_CQE_VALID(cqe)) {
 1276                         DW_SWAP((uint32_t *) cqe, sizeof(oce_rq_cqe));
 1277                         oce_discard_rx_comp(rq, cqe->u0.s.num_fragments);
 1278                         /* Check if CQE is flush completion */
 1279                         if((cqe->u0.s.num_fragments==0)&&(cqe->u0.s.pkt_size == 0)&&(cqe->u0.s.error == 0)) 
 1280                                 flush_compl = 1;
 1281                         
 1282                         RQ_CQE_INVALIDATE(cqe);
 1283                         RING_GET(cq->ring, 1);
 1284 #if defined(INET6) || defined(INET)
 1285                         if (IF_LRO_ENABLED(sc))
 1286                                 oce_rx_flush_lro(rq);
 1287 #endif
 1288                         oce_arm_cq(sc, cq->cq_id, 1, FALSE);
 1289                         if(flush_compl)
 1290                                 break;
 1291                 }else {
 1292                         if (flush_wait++ > 100) {
 1293                                 device_printf(sc->dev, "did not receive flush compl\n");
 1294                                 break;
 1295                         }
 1296                         oce_arm_cq(sc, cq->cq_id, 0, TRUE);
 1297                         DELAY(1000);
 1298                 } 
 1299         }
 1300 
 1301         /* After cleanup, leave the CQ in unarmed state */
 1302         oce_arm_cq(sc, cq->cq_id, 0, FALSE);
 1303 }
 1304 
 1305 void
 1306 oce_stop_rx(POCE_SOFTC sc)
 1307 {
 1308         struct oce_mbx mbx;
 1309         struct mbx_delete_nic_rq *fwcmd;
 1310         struct mbx_delete_nic_rq_v1 *fwcmd1;
 1311         struct oce_rq *rq;
 1312         int i = 0;
 1313  
 1314        /* before deleting disable hwlro */
 1315         if(sc->enable_hwlro)
 1316                 oce_mbox_nic_set_iface_lro_config(sc, 0);
 1317 
 1318         for_all_rq_queues(sc, rq, i) {
 1319                 if (rq->qstate == QCREATED) {
 1320                         /* Delete rxq in firmware */
 1321                         LOCK(&rq->rx_lock);
 1322 
 1323                         bzero(&mbx, sizeof(mbx));
 1324                         if(!rq->islro) {
 1325                                 fwcmd = (struct mbx_delete_nic_rq *)&mbx.payload;
 1326                                 fwcmd->params.req.rq_id = rq->rq_id;
 1327                                 (void)oce_destroy_q(sc, &mbx, sizeof(struct mbx_delete_nic_rq), QTYPE_RQ, 0);
 1328                         }else {
 1329                                 fwcmd1 = (struct mbx_delete_nic_rq_v1 *)&mbx.payload;
 1330                                 fwcmd1->params.req.rq_id = rq->rq_id;
 1331                                 fwcmd1->params.req.rq_flags = (NIC_RQ_FLAGS_RSS | NIC_RQ_FLAGS_LRO);
 1332 
 1333                                 (void)oce_destroy_q(sc,&mbx,sizeof(struct mbx_delete_nic_rq_v1),QTYPE_RQ,1);
 1334                         }
 1335                         rq->qstate = QDELETED;
 1336 
 1337                         DELAY(1000);
 1338                         
 1339                         if(!rq->islro)
 1340                                 oce_rx_cq_clean(rq);
 1341                         else
 1342                                 oce_rx_cq_clean_hwlro(rq);
 1343 
 1344                         /* Free posted RX buffers that are not used */
 1345                         oce_free_posted_rxbuf(rq);
 1346                         UNLOCK(&rq->rx_lock);
 1347                 }
 1348         }
 1349 }
 1350 
 1351 
 1352 
 1353 int
 1354 oce_start_rx(POCE_SOFTC sc)
 1355 {
 1356         struct oce_rq *rq;
 1357         int rc = 0, i;
 1358         
 1359         for_all_rq_queues(sc, rq, i) {
 1360                 if (rq->qstate == QCREATED)
 1361                         continue;
 1362                 if((i == 0) || (!sc->enable_hwlro)) {
 1363                         rc = oce_mbox_create_rq(rq);
 1364                         if (rc)
 1365                                 goto error;
 1366                         rq->islro = 0;
 1367                 }else {
 1368                         rc = oce_mbox_create_rq_v2(rq);
 1369                         if (rc)
 1370                                 goto error;
 1371                         rq->islro = 1;
 1372                 }
 1373                 /* reset queue pointers */
 1374                 rq->qstate       = QCREATED;
 1375                 rq->pending      = 0;
 1376                 rq->ring->cidx   = 0;
 1377                 rq->ring->pidx   = 0;
 1378         }
 1379         
 1380         if(sc->enable_hwlro) {
 1381                 rc = oce_mbox_nic_set_iface_lro_config(sc, 1);
 1382                 if (rc)
 1383                         goto error;
 1384         }
 1385 
 1386         DELAY(1);
 1387         
 1388         /* RSS config */
 1389         if (is_rss_enabled(sc)) {
 1390                 rc = oce_config_nic_rss(sc, (uint8_t) sc->if_id, RSS_ENABLE);
 1391                 if (rc)
 1392                         goto error;
 1393 
 1394         }
 1395 
 1396         DELAY(1);
 1397         return rc;
 1398 error:
 1399         device_printf(sc->dev, "Start RX failed\n");
 1400         return rc;
 1401 
 1402 }
 1403 
 1404 
 1405 

Cache object: 67d6ff046aa898bf68cb83f29c04e07d


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