12f345d8eSLuigi Rizzo /*- 2*291a1934SXin LI * Copyright (C) 2013 Emulex 32f345d8eSLuigi Rizzo * All rights reserved. 42f345d8eSLuigi Rizzo * 52f345d8eSLuigi Rizzo * Redistribution and use in source and binary forms, with or without 62f345d8eSLuigi Rizzo * modification, are permitted provided that the following conditions are met: 72f345d8eSLuigi Rizzo * 82f345d8eSLuigi Rizzo * 1. Redistributions of source code must retain the above copyright notice, 92f345d8eSLuigi Rizzo * this list of conditions and the following disclaimer. 102f345d8eSLuigi Rizzo * 112f345d8eSLuigi Rizzo * 2. Redistributions in binary form must reproduce the above copyright 122f345d8eSLuigi Rizzo * notice, this list of conditions and the following disclaimer in the 132f345d8eSLuigi Rizzo * documentation and/or other materials provided with the distribution. 142f345d8eSLuigi Rizzo * 152f345d8eSLuigi Rizzo * 3. Neither the name of the Emulex Corporation nor the names of its 162f345d8eSLuigi Rizzo * contributors may be used to endorse or promote products derived from 172f345d8eSLuigi Rizzo * this software without specific prior written permission. 182f345d8eSLuigi Rizzo * 192f345d8eSLuigi Rizzo * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 202f345d8eSLuigi Rizzo * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 212f345d8eSLuigi Rizzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 222f345d8eSLuigi Rizzo * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 232f345d8eSLuigi Rizzo * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 242f345d8eSLuigi Rizzo * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 252f345d8eSLuigi Rizzo * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 262f345d8eSLuigi Rizzo * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 272f345d8eSLuigi Rizzo * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 282f345d8eSLuigi Rizzo * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 292f345d8eSLuigi Rizzo * POSSIBILITY OF SUCH DAMAGE. 302f345d8eSLuigi Rizzo * 312f345d8eSLuigi Rizzo * Contact Information: 322f345d8eSLuigi Rizzo * freebsd-drivers@emulex.com 332f345d8eSLuigi Rizzo * 342f345d8eSLuigi Rizzo * Emulex 352f345d8eSLuigi Rizzo * 3333 Susan Street 362f345d8eSLuigi Rizzo * Costa Mesa, CA 92626 372f345d8eSLuigi Rizzo */ 382f345d8eSLuigi Rizzo 39cdaba892SXin LI 40cdaba892SXin LI 412f345d8eSLuigi Rizzo /* $FreeBSD$ */ 422f345d8eSLuigi Rizzo 43cdaba892SXin LI 442f345d8eSLuigi Rizzo #include "oce_if.h" 452f345d8eSLuigi Rizzo 462f345d8eSLuigi Rizzo /***************************************************** 472f345d8eSLuigi Rizzo * local queue functions 482f345d8eSLuigi Rizzo *****************************************************/ 492f345d8eSLuigi Rizzo 502f345d8eSLuigi Rizzo static struct oce_wq *oce_wq_init(POCE_SOFTC sc, 512f345d8eSLuigi Rizzo uint32_t q_len, uint32_t wq_type); 522f345d8eSLuigi Rizzo static int oce_wq_create(struct oce_wq *wq, struct oce_eq *eq); 532f345d8eSLuigi Rizzo static void oce_wq_free(struct oce_wq *wq); 542f345d8eSLuigi Rizzo static void oce_wq_del(struct oce_wq *wq); 552f345d8eSLuigi Rizzo static struct oce_rq *oce_rq_init(POCE_SOFTC sc, 562f345d8eSLuigi Rizzo uint32_t q_len, 572f345d8eSLuigi Rizzo uint32_t frag_size, 582f345d8eSLuigi Rizzo uint32_t mtu, uint32_t rss); 592f345d8eSLuigi Rizzo static int oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq); 602f345d8eSLuigi Rizzo static void oce_rq_free(struct oce_rq *rq); 612f345d8eSLuigi Rizzo static void oce_rq_del(struct oce_rq *rq); 622f345d8eSLuigi Rizzo static struct oce_eq *oce_eq_create(POCE_SOFTC sc, 632f345d8eSLuigi Rizzo uint32_t q_len, 642f345d8eSLuigi Rizzo uint32_t item_size, 652f345d8eSLuigi Rizzo uint32_t eq_delay, 662f345d8eSLuigi Rizzo uint32_t vector); 672f345d8eSLuigi Rizzo static void oce_eq_del(struct oce_eq *eq); 682f345d8eSLuigi Rizzo static struct oce_mq *oce_mq_create(POCE_SOFTC sc, 692f345d8eSLuigi Rizzo struct oce_eq *eq, uint32_t q_len); 702f345d8eSLuigi Rizzo static void oce_mq_free(struct oce_mq *mq); 712f345d8eSLuigi Rizzo static int oce_destroy_q(POCE_SOFTC sc, struct oce_mbx 722f345d8eSLuigi Rizzo *mbx, size_t req_size, enum qtype qtype); 732f345d8eSLuigi Rizzo struct oce_cq *oce_cq_create(POCE_SOFTC sc, 742f345d8eSLuigi Rizzo struct oce_eq *eq, 752f345d8eSLuigi Rizzo uint32_t q_len, 762f345d8eSLuigi Rizzo uint32_t item_size, 772f345d8eSLuigi Rizzo uint32_t sol_event, 782f345d8eSLuigi Rizzo uint32_t is_eventable, 792f345d8eSLuigi Rizzo uint32_t nodelay, uint32_t ncoalesce); 802f345d8eSLuigi Rizzo static void oce_cq_del(POCE_SOFTC sc, struct oce_cq *cq); 812f345d8eSLuigi Rizzo 822f345d8eSLuigi Rizzo 832f345d8eSLuigi Rizzo 842f345d8eSLuigi Rizzo /** 852f345d8eSLuigi Rizzo * @brief Create and initialize all the queues on the board 862f345d8eSLuigi Rizzo * @param sc software handle to the device 872f345d8eSLuigi Rizzo * @returns 0 if successful, or error 882f345d8eSLuigi Rizzo **/ 892f345d8eSLuigi Rizzo int 902f345d8eSLuigi Rizzo oce_queue_init_all(POCE_SOFTC sc) 912f345d8eSLuigi Rizzo { 922f345d8eSLuigi Rizzo int rc = 0, i, vector; 932f345d8eSLuigi Rizzo struct oce_wq *wq; 942f345d8eSLuigi Rizzo struct oce_rq *rq; 95cdaba892SXin LI struct oce_aic_obj *aic; 962f345d8eSLuigi Rizzo 972f345d8eSLuigi Rizzo /* alloc TX/RX queues */ 982f345d8eSLuigi Rizzo for_all_wq_queues(sc, wq, i) { 992f345d8eSLuigi Rizzo sc->wq[i] = oce_wq_init(sc, sc->tx_ring_size, 1002f345d8eSLuigi Rizzo NIC_WQ_TYPE_STANDARD); 1012f345d8eSLuigi Rizzo if (!sc->wq[i]) 1022f345d8eSLuigi Rizzo goto error; 1032f345d8eSLuigi Rizzo 1042f345d8eSLuigi Rizzo } 1052f345d8eSLuigi Rizzo 1062f345d8eSLuigi Rizzo for_all_rq_queues(sc, rq, i) { 1072f345d8eSLuigi Rizzo sc->rq[i] = oce_rq_init(sc, sc->rx_ring_size, sc->rq_frag_size, 1082f345d8eSLuigi Rizzo OCE_MAX_JUMBO_FRAME_SIZE, 109*291a1934SXin LI (i == 0) ? 0 : is_rss_enabled(sc)); 1102f345d8eSLuigi Rizzo if (!sc->rq[i]) 1112f345d8eSLuigi Rizzo goto error; 1122f345d8eSLuigi Rizzo } 1132f345d8eSLuigi Rizzo 1142f345d8eSLuigi Rizzo /* Create network interface on card */ 1152f345d8eSLuigi Rizzo if (oce_create_nw_interface(sc)) 1162f345d8eSLuigi Rizzo goto error; 1172f345d8eSLuigi Rizzo 1182f345d8eSLuigi Rizzo /* create all of the event queues */ 1192f345d8eSLuigi Rizzo for (vector = 0; vector < sc->intr_count; vector++) { 120cdaba892SXin LI /* setup aic defaults for each event queue */ 121cdaba892SXin LI aic = &sc->aic_obj[vector]; 122cdaba892SXin LI aic->max_eqd = OCE_MAX_EQD; 123cdaba892SXin LI aic->min_eqd = OCE_MIN_EQD; 124cdaba892SXin LI aic->et_eqd = OCE_MIN_EQD; 125cdaba892SXin LI aic->enable = TRUE; 126cdaba892SXin LI 1272f345d8eSLuigi Rizzo sc->eq[vector] = oce_eq_create(sc, EQ_LEN_1024, EQE_SIZE_4, 1282f345d8eSLuigi Rizzo 0, vector); 1292f345d8eSLuigi Rizzo if (!sc->eq[vector]) 1302f345d8eSLuigi Rizzo goto error; 1312f345d8eSLuigi Rizzo } 1322f345d8eSLuigi Rizzo 1332f345d8eSLuigi Rizzo /* create Tx, Rx and mcc queues */ 1342f345d8eSLuigi Rizzo for_all_wq_queues(sc, wq, i) { 1352f345d8eSLuigi Rizzo rc = oce_wq_create(wq, sc->eq[i]); 1362f345d8eSLuigi Rizzo if (rc) 1372f345d8eSLuigi Rizzo goto error; 1382f345d8eSLuigi Rizzo wq->queue_index = i; 1392f345d8eSLuigi Rizzo TASK_INIT(&wq->txtask, 1, oce_tx_task, wq); 1402f345d8eSLuigi Rizzo } 1412f345d8eSLuigi Rizzo 1422f345d8eSLuigi Rizzo for_all_rq_queues(sc, rq, i) { 1432f345d8eSLuigi Rizzo rc = oce_rq_create(rq, sc->if_id, 1442f345d8eSLuigi Rizzo sc->eq[(i == 0) ? 0:(i-1)]); 1452f345d8eSLuigi Rizzo if (rc) 1462f345d8eSLuigi Rizzo goto error; 1472f345d8eSLuigi Rizzo rq->queue_index = i; 1482f345d8eSLuigi Rizzo } 1492f345d8eSLuigi Rizzo 1502f345d8eSLuigi Rizzo sc->mq = oce_mq_create(sc, sc->eq[0], 64); 1512f345d8eSLuigi Rizzo if (!sc->mq) 1522f345d8eSLuigi Rizzo goto error; 1532f345d8eSLuigi Rizzo 1542f345d8eSLuigi Rizzo return rc; 1552f345d8eSLuigi Rizzo 1562f345d8eSLuigi Rizzo error: 1572f345d8eSLuigi Rizzo oce_queue_release_all(sc); 1582f345d8eSLuigi Rizzo return 1; 1592f345d8eSLuigi Rizzo } 1602f345d8eSLuigi Rizzo 1612f345d8eSLuigi Rizzo 1622f345d8eSLuigi Rizzo 1632f345d8eSLuigi Rizzo /** 1642f345d8eSLuigi Rizzo * @brief Releases all mailbox queues created 1652f345d8eSLuigi Rizzo * @param sc software handle to the device 1662f345d8eSLuigi Rizzo */ 1672f345d8eSLuigi Rizzo void 1682f345d8eSLuigi Rizzo oce_queue_release_all(POCE_SOFTC sc) 1692f345d8eSLuigi Rizzo { 1702f345d8eSLuigi Rizzo int i = 0; 1712f345d8eSLuigi Rizzo struct oce_wq *wq; 1722f345d8eSLuigi Rizzo struct oce_rq *rq; 1732f345d8eSLuigi Rizzo struct oce_eq *eq; 1742f345d8eSLuigi Rizzo 1752f345d8eSLuigi Rizzo for_all_rq_queues(sc, rq, i) { 1762f345d8eSLuigi Rizzo if (rq) { 1772f345d8eSLuigi Rizzo oce_rq_del(sc->rq[i]); 1782f345d8eSLuigi Rizzo oce_rq_free(sc->rq[i]); 1792f345d8eSLuigi Rizzo } 1802f345d8eSLuigi Rizzo } 1812f345d8eSLuigi Rizzo 1822f345d8eSLuigi Rizzo for_all_wq_queues(sc, wq, i) { 1832f345d8eSLuigi Rizzo if (wq) { 1842f345d8eSLuigi Rizzo oce_wq_del(sc->wq[i]); 1852f345d8eSLuigi Rizzo oce_wq_free(sc->wq[i]); 1862f345d8eSLuigi Rizzo } 1872f345d8eSLuigi Rizzo } 1882f345d8eSLuigi Rizzo 1892f345d8eSLuigi Rizzo if (sc->mq) 1902f345d8eSLuigi Rizzo oce_mq_free(sc->mq); 1912f345d8eSLuigi Rizzo 1922f345d8eSLuigi Rizzo for_all_evnt_queues(sc, eq, i) { 1932f345d8eSLuigi Rizzo if (eq) 1942f345d8eSLuigi Rizzo oce_eq_del(sc->eq[i]); 1952f345d8eSLuigi Rizzo } 1962f345d8eSLuigi Rizzo } 1972f345d8eSLuigi Rizzo 1982f345d8eSLuigi Rizzo 1992f345d8eSLuigi Rizzo 2002f345d8eSLuigi Rizzo /** 2012f345d8eSLuigi Rizzo * @brief Function to create a WQ for NIC Tx 2022f345d8eSLuigi Rizzo * @param sc software handle to the device 2032f345d8eSLuigi Rizzo * @param qlen number of entries in the queue 2042f345d8eSLuigi Rizzo * @param wq_type work queue type 2052f345d8eSLuigi Rizzo * @returns the pointer to the WQ created or NULL on failure 2062f345d8eSLuigi Rizzo */ 2072f345d8eSLuigi Rizzo static struct 2082f345d8eSLuigi Rizzo oce_wq *oce_wq_init(POCE_SOFTC sc, uint32_t q_len, uint32_t wq_type) 2092f345d8eSLuigi Rizzo { 2102f345d8eSLuigi Rizzo struct oce_wq *wq; 2112f345d8eSLuigi Rizzo int rc = 0, i; 2122f345d8eSLuigi Rizzo 2132f345d8eSLuigi Rizzo /* q_len must be min 256 and max 2k */ 2142f345d8eSLuigi Rizzo if (q_len < 256 || q_len > 2048) { 2152f345d8eSLuigi Rizzo device_printf(sc->dev, 2162f345d8eSLuigi Rizzo "Invalid q length. Must be " 2172f345d8eSLuigi Rizzo "[256, 2000]: 0x%x\n", q_len); 2182f345d8eSLuigi Rizzo return NULL; 2192f345d8eSLuigi Rizzo } 2202f345d8eSLuigi Rizzo 2212f345d8eSLuigi Rizzo /* allocate wq */ 2222f345d8eSLuigi Rizzo wq = malloc(sizeof(struct oce_wq), M_DEVBUF, M_NOWAIT | M_ZERO); 2232f345d8eSLuigi Rizzo if (!wq) 2242f345d8eSLuigi Rizzo return NULL; 2252f345d8eSLuigi Rizzo 2262f345d8eSLuigi Rizzo /* Set the wq config */ 2272f345d8eSLuigi Rizzo wq->cfg.q_len = q_len; 2282f345d8eSLuigi Rizzo wq->cfg.wq_type = (uint8_t) wq_type; 2292f345d8eSLuigi Rizzo wq->cfg.eqd = OCE_DEFAULT_WQ_EQD; 2302f345d8eSLuigi Rizzo wq->cfg.nbufs = 2 * wq->cfg.q_len; 2312f345d8eSLuigi Rizzo wq->cfg.nhdl = 2 * wq->cfg.q_len; 2322f345d8eSLuigi Rizzo 2332f345d8eSLuigi Rizzo wq->parent = (void *)sc; 2342f345d8eSLuigi Rizzo 2352f345d8eSLuigi Rizzo rc = bus_dma_tag_create(bus_get_dma_tag(sc->dev), 2362f345d8eSLuigi Rizzo 1, 0, 2372f345d8eSLuigi Rizzo BUS_SPACE_MAXADDR, 2382f345d8eSLuigi Rizzo BUS_SPACE_MAXADDR, 2392f345d8eSLuigi Rizzo NULL, NULL, 2402f345d8eSLuigi Rizzo OCE_MAX_TX_SIZE, 2412f345d8eSLuigi Rizzo OCE_MAX_TX_ELEMENTS, 2422f345d8eSLuigi Rizzo PAGE_SIZE, 0, NULL, NULL, &wq->tag); 2432f345d8eSLuigi Rizzo 2442f345d8eSLuigi Rizzo if (rc) 2452f345d8eSLuigi Rizzo goto free_wq; 2462f345d8eSLuigi Rizzo 2472f345d8eSLuigi Rizzo 2482f345d8eSLuigi Rizzo for (i = 0; i < OCE_WQ_PACKET_ARRAY_SIZE; i++) { 2492f345d8eSLuigi Rizzo rc = bus_dmamap_create(wq->tag, 0, &wq->pckts[i].map); 2502f345d8eSLuigi Rizzo if (rc) 2512f345d8eSLuigi Rizzo goto free_wq; 2522f345d8eSLuigi Rizzo } 2532f345d8eSLuigi Rizzo 2542f345d8eSLuigi Rizzo wq->ring = oce_create_ring_buffer(sc, q_len, NIC_WQE_SIZE); 2552f345d8eSLuigi Rizzo if (!wq->ring) 2562f345d8eSLuigi Rizzo goto free_wq; 2572f345d8eSLuigi Rizzo 2582f345d8eSLuigi Rizzo 2592f345d8eSLuigi Rizzo LOCK_CREATE(&wq->tx_lock, "TX_lock"); 2602f345d8eSLuigi Rizzo 2612f345d8eSLuigi Rizzo #if __FreeBSD_version >= 800000 2622f345d8eSLuigi Rizzo /* Allocate buf ring for multiqueue*/ 2632f345d8eSLuigi Rizzo wq->br = buf_ring_alloc(4096, M_DEVBUF, 2642f345d8eSLuigi Rizzo M_WAITOK, &wq->tx_lock.mutex); 2652f345d8eSLuigi Rizzo if (!wq->br) 2662f345d8eSLuigi Rizzo goto free_wq; 2672f345d8eSLuigi Rizzo #endif 2682f345d8eSLuigi Rizzo return wq; 2692f345d8eSLuigi Rizzo 2702f345d8eSLuigi Rizzo 2712f345d8eSLuigi Rizzo free_wq: 2722f345d8eSLuigi Rizzo device_printf(sc->dev, "Create WQ failed\n"); 2732f345d8eSLuigi Rizzo oce_wq_free(wq); 2742f345d8eSLuigi Rizzo return NULL; 2752f345d8eSLuigi Rizzo } 2762f345d8eSLuigi Rizzo 2772f345d8eSLuigi Rizzo 2782f345d8eSLuigi Rizzo 2792f345d8eSLuigi Rizzo /** 2802f345d8eSLuigi Rizzo * @brief Frees the work queue 2812f345d8eSLuigi Rizzo * @param wq pointer to work queue to free 2822f345d8eSLuigi Rizzo */ 2832f345d8eSLuigi Rizzo static void 2842f345d8eSLuigi Rizzo oce_wq_free(struct oce_wq *wq) 2852f345d8eSLuigi Rizzo { 2862f345d8eSLuigi Rizzo POCE_SOFTC sc = (POCE_SOFTC) wq->parent; 2872f345d8eSLuigi Rizzo int i; 2882f345d8eSLuigi Rizzo 2892f345d8eSLuigi Rizzo taskqueue_drain(taskqueue_swi, &wq->txtask); 2902f345d8eSLuigi Rizzo 2912f345d8eSLuigi Rizzo if (wq->ring != NULL) { 2922f345d8eSLuigi Rizzo oce_destroy_ring_buffer(sc, wq->ring); 2932f345d8eSLuigi Rizzo wq->ring = NULL; 2942f345d8eSLuigi Rizzo } 2952f345d8eSLuigi Rizzo 2962f345d8eSLuigi Rizzo for (i = 0; i < OCE_WQ_PACKET_ARRAY_SIZE; i++) { 2972f345d8eSLuigi Rizzo if (wq->pckts[i].map != NULL) { 2982f345d8eSLuigi Rizzo bus_dmamap_unload(wq->tag, wq->pckts[i].map); 2992f345d8eSLuigi Rizzo bus_dmamap_destroy(wq->tag, wq->pckts[i].map); 3002f345d8eSLuigi Rizzo wq->pckts[i].map = NULL; 3012f345d8eSLuigi Rizzo } 3022f345d8eSLuigi Rizzo } 3032f345d8eSLuigi Rizzo 3042f345d8eSLuigi Rizzo if (wq->tag != NULL) 3052f345d8eSLuigi Rizzo bus_dma_tag_destroy(wq->tag); 3062f345d8eSLuigi Rizzo if (wq->br != NULL) 3072f345d8eSLuigi Rizzo buf_ring_free(wq->br, M_DEVBUF); 3082f345d8eSLuigi Rizzo 3092f345d8eSLuigi Rizzo LOCK_DESTROY(&wq->tx_lock); 3102f345d8eSLuigi Rizzo free(wq, M_DEVBUF); 3112f345d8eSLuigi Rizzo } 3122f345d8eSLuigi Rizzo 3132f345d8eSLuigi Rizzo 3142f345d8eSLuigi Rizzo 3152f345d8eSLuigi Rizzo /** 3162f345d8eSLuigi Rizzo * @brief Create a work queue 3172f345d8eSLuigi Rizzo * @param wq pointer to work queue 3182f345d8eSLuigi Rizzo * @param eq pointer to associated event queue 3192f345d8eSLuigi Rizzo */ 3202f345d8eSLuigi Rizzo static int 3212f345d8eSLuigi Rizzo oce_wq_create(struct oce_wq *wq, struct oce_eq *eq) 3222f345d8eSLuigi Rizzo { 3232f345d8eSLuigi Rizzo POCE_SOFTC sc = wq->parent; 3242f345d8eSLuigi Rizzo struct oce_cq *cq; 3252f345d8eSLuigi Rizzo int rc = 0; 3262f345d8eSLuigi Rizzo 3272f345d8eSLuigi Rizzo /* create the CQ */ 3282f345d8eSLuigi Rizzo cq = oce_cq_create(sc, 3292f345d8eSLuigi Rizzo eq, 3302f345d8eSLuigi Rizzo CQ_LEN_1024, 3312f345d8eSLuigi Rizzo sizeof(struct oce_nic_tx_cqe), 0, 1, 0, 3); 3322f345d8eSLuigi Rizzo if (!cq) 3332f345d8eSLuigi Rizzo return ENXIO; 3342f345d8eSLuigi Rizzo 3352f345d8eSLuigi Rizzo 3362f345d8eSLuigi Rizzo wq->cq = cq; 3372f345d8eSLuigi Rizzo 3382f345d8eSLuigi Rizzo rc = oce_mbox_create_wq(wq); 3392f345d8eSLuigi Rizzo if (rc) 3402f345d8eSLuigi Rizzo goto error; 3412f345d8eSLuigi Rizzo 3422f345d8eSLuigi Rizzo wq->qstate = QCREATED; 3432f345d8eSLuigi Rizzo wq->wq_free = wq->cfg.q_len; 3442f345d8eSLuigi Rizzo wq->ring->cidx = 0; 3452f345d8eSLuigi Rizzo wq->ring->pidx = 0; 3462f345d8eSLuigi Rizzo 3472f345d8eSLuigi Rizzo eq->cq[eq->cq_valid] = cq; 3482f345d8eSLuigi Rizzo eq->cq_valid++; 3492f345d8eSLuigi Rizzo cq->cb_arg = wq; 3502f345d8eSLuigi Rizzo cq->cq_handler = oce_wq_handler; 3512f345d8eSLuigi Rizzo 3522f345d8eSLuigi Rizzo return 0; 3532f345d8eSLuigi Rizzo 3542f345d8eSLuigi Rizzo error: 3552f345d8eSLuigi Rizzo device_printf(sc->dev, "WQ create failed\n"); 3562f345d8eSLuigi Rizzo oce_wq_del(wq); 3572f345d8eSLuigi Rizzo return rc; 3582f345d8eSLuigi Rizzo } 3592f345d8eSLuigi Rizzo 3602f345d8eSLuigi Rizzo 3612f345d8eSLuigi Rizzo 3622f345d8eSLuigi Rizzo 3632f345d8eSLuigi Rizzo /** 3642f345d8eSLuigi Rizzo * @brief Delete a work queue 3652f345d8eSLuigi Rizzo * @param wq pointer to work queue 3662f345d8eSLuigi Rizzo */ 3672f345d8eSLuigi Rizzo static void 3682f345d8eSLuigi Rizzo oce_wq_del(struct oce_wq *wq) 3692f345d8eSLuigi Rizzo { 3702f345d8eSLuigi Rizzo struct oce_mbx mbx; 3712f345d8eSLuigi Rizzo struct mbx_delete_nic_wq *fwcmd; 3722f345d8eSLuigi Rizzo POCE_SOFTC sc = (POCE_SOFTC) wq->parent; 3732f345d8eSLuigi Rizzo 3742f345d8eSLuigi Rizzo if (wq->qstate == QCREATED) { 3752f345d8eSLuigi Rizzo bzero(&mbx, sizeof(struct oce_mbx)); 3762f345d8eSLuigi Rizzo /* now fill the command */ 3772f345d8eSLuigi Rizzo fwcmd = (struct mbx_delete_nic_wq *)&mbx.payload; 3782f345d8eSLuigi Rizzo fwcmd->params.req.wq_id = wq->wq_id; 3792f345d8eSLuigi Rizzo (void)oce_destroy_q(sc, &mbx, 3802f345d8eSLuigi Rizzo sizeof(struct mbx_delete_nic_wq), QTYPE_WQ); 3812f345d8eSLuigi Rizzo wq->qstate = QDELETED; 3822f345d8eSLuigi Rizzo } 3832f345d8eSLuigi Rizzo 3842f345d8eSLuigi Rizzo if (wq->cq != NULL) { 3852f345d8eSLuigi Rizzo oce_cq_del(sc, wq->cq); 3862f345d8eSLuigi Rizzo wq->cq = NULL; 3872f345d8eSLuigi Rizzo } 3882f345d8eSLuigi Rizzo } 3892f345d8eSLuigi Rizzo 3902f345d8eSLuigi Rizzo 3912f345d8eSLuigi Rizzo 3922f345d8eSLuigi Rizzo /** 3932f345d8eSLuigi Rizzo * @brief function to allocate receive queue resources 3942f345d8eSLuigi Rizzo * @param sc software handle to the device 3952f345d8eSLuigi Rizzo * @param q_len length of receive queue 3962f345d8eSLuigi Rizzo * @param frag_size size of an receive queue fragment 3972f345d8eSLuigi Rizzo * @param mtu maximum transmission unit 3982f345d8eSLuigi Rizzo * @param rss is-rss-queue flag 3992f345d8eSLuigi Rizzo * @returns the pointer to the RQ created or NULL on failure 4002f345d8eSLuigi Rizzo */ 4012f345d8eSLuigi Rizzo static struct 4022f345d8eSLuigi Rizzo oce_rq *oce_rq_init(POCE_SOFTC sc, 4032f345d8eSLuigi Rizzo uint32_t q_len, 4042f345d8eSLuigi Rizzo uint32_t frag_size, 4052f345d8eSLuigi Rizzo uint32_t mtu, uint32_t rss) 4062f345d8eSLuigi Rizzo { 4072f345d8eSLuigi Rizzo struct oce_rq *rq; 4082f345d8eSLuigi Rizzo int rc = 0, i; 4092f345d8eSLuigi Rizzo 4102f345d8eSLuigi Rizzo if (OCE_LOG2(frag_size) <= 0) 4112f345d8eSLuigi Rizzo return NULL; 4122f345d8eSLuigi Rizzo 4132f345d8eSLuigi Rizzo if ((q_len == 0) || (q_len > 1024)) 4142f345d8eSLuigi Rizzo return NULL; 4152f345d8eSLuigi Rizzo 4162f345d8eSLuigi Rizzo /* allocate the rq */ 4172f345d8eSLuigi Rizzo rq = malloc(sizeof(struct oce_rq), M_DEVBUF, M_NOWAIT | M_ZERO); 4182f345d8eSLuigi Rizzo if (!rq) 4192f345d8eSLuigi Rizzo return NULL; 4202f345d8eSLuigi Rizzo 4212f345d8eSLuigi Rizzo 4222f345d8eSLuigi Rizzo rq->cfg.q_len = q_len; 4232f345d8eSLuigi Rizzo rq->cfg.frag_size = frag_size; 4242f345d8eSLuigi Rizzo rq->cfg.mtu = mtu; 4252f345d8eSLuigi Rizzo rq->cfg.eqd = 0; 4262f345d8eSLuigi Rizzo rq->lro_pkts_queued = 0; 4272f345d8eSLuigi Rizzo rq->cfg.is_rss_queue = rss; 4282f345d8eSLuigi Rizzo rq->packets_in = 0; 4292f345d8eSLuigi Rizzo rq->packets_out = 0; 4302f345d8eSLuigi Rizzo rq->pending = 0; 4312f345d8eSLuigi Rizzo 4322f345d8eSLuigi Rizzo rq->parent = (void *)sc; 4332f345d8eSLuigi Rizzo 4342f345d8eSLuigi Rizzo rc = bus_dma_tag_create(bus_get_dma_tag(sc->dev), 4352f345d8eSLuigi Rizzo 1, 0, 4362f345d8eSLuigi Rizzo BUS_SPACE_MAXADDR, 4372f345d8eSLuigi Rizzo BUS_SPACE_MAXADDR, 4382f345d8eSLuigi Rizzo NULL, NULL, 4392f345d8eSLuigi Rizzo OCE_MAX_RX_SIZE, 4402f345d8eSLuigi Rizzo 1, PAGE_SIZE, 0, NULL, NULL, &rq->tag); 4412f345d8eSLuigi Rizzo 4422f345d8eSLuigi Rizzo if (rc) 4432f345d8eSLuigi Rizzo goto free_rq; 4442f345d8eSLuigi Rizzo 4452f345d8eSLuigi Rizzo for (i = 0; i < OCE_RQ_PACKET_ARRAY_SIZE; i++) { 4462f345d8eSLuigi Rizzo rc = bus_dmamap_create(rq->tag, 0, &rq->pckts[i].map); 4472f345d8eSLuigi Rizzo if (rc) 4482f345d8eSLuigi Rizzo goto free_rq; 4492f345d8eSLuigi Rizzo } 4502f345d8eSLuigi Rizzo 4512f345d8eSLuigi Rizzo /* create the ring buffer */ 4522f345d8eSLuigi Rizzo rq->ring = oce_create_ring_buffer(sc, q_len, 4532f345d8eSLuigi Rizzo sizeof(struct oce_nic_rqe)); 4542f345d8eSLuigi Rizzo if (!rq->ring) 4552f345d8eSLuigi Rizzo goto free_rq; 4562f345d8eSLuigi Rizzo 4572f345d8eSLuigi Rizzo LOCK_CREATE(&rq->rx_lock, "RX_lock"); 4582f345d8eSLuigi Rizzo 4592f345d8eSLuigi Rizzo return rq; 4602f345d8eSLuigi Rizzo 4612f345d8eSLuigi Rizzo free_rq: 4622f345d8eSLuigi Rizzo device_printf(sc->dev, "Create RQ failed\n"); 4632f345d8eSLuigi Rizzo oce_rq_free(rq); 4642f345d8eSLuigi Rizzo return NULL; 4652f345d8eSLuigi Rizzo } 4662f345d8eSLuigi Rizzo 4672f345d8eSLuigi Rizzo 4682f345d8eSLuigi Rizzo 4692f345d8eSLuigi Rizzo 4702f345d8eSLuigi Rizzo /** 4712f345d8eSLuigi Rizzo * @brief Free a receive queue 4722f345d8eSLuigi Rizzo * @param rq pointer to receive queue 4732f345d8eSLuigi Rizzo */ 4742f345d8eSLuigi Rizzo static void 4752f345d8eSLuigi Rizzo oce_rq_free(struct oce_rq *rq) 4762f345d8eSLuigi Rizzo { 4772f345d8eSLuigi Rizzo POCE_SOFTC sc = (POCE_SOFTC) rq->parent; 4782f345d8eSLuigi Rizzo int i = 0 ; 4792f345d8eSLuigi Rizzo 4802f345d8eSLuigi Rizzo if (rq->ring != NULL) { 4812f345d8eSLuigi Rizzo oce_destroy_ring_buffer(sc, rq->ring); 4822f345d8eSLuigi Rizzo rq->ring = NULL; 4832f345d8eSLuigi Rizzo } 4842f345d8eSLuigi Rizzo for (i = 0; i < OCE_RQ_PACKET_ARRAY_SIZE; i++) { 4852f345d8eSLuigi Rizzo if (rq->pckts[i].map != NULL) { 4862f345d8eSLuigi Rizzo bus_dmamap_unload(rq->tag, rq->pckts[i].map); 4872f345d8eSLuigi Rizzo bus_dmamap_destroy(rq->tag, rq->pckts[i].map); 4882f345d8eSLuigi Rizzo rq->pckts[i].map = NULL; 4892f345d8eSLuigi Rizzo } 4902f345d8eSLuigi Rizzo if (rq->pckts[i].mbuf) { 4912f345d8eSLuigi Rizzo m_free(rq->pckts[i].mbuf); 4922f345d8eSLuigi Rizzo rq->pckts[i].mbuf = NULL; 4932f345d8eSLuigi Rizzo } 4942f345d8eSLuigi Rizzo } 4952f345d8eSLuigi Rizzo 4962f345d8eSLuigi Rizzo if (rq->tag != NULL) 4972f345d8eSLuigi Rizzo bus_dma_tag_destroy(rq->tag); 4982f345d8eSLuigi Rizzo 4992f345d8eSLuigi Rizzo LOCK_DESTROY(&rq->rx_lock); 5002f345d8eSLuigi Rizzo free(rq, M_DEVBUF); 5012f345d8eSLuigi Rizzo } 5022f345d8eSLuigi Rizzo 5032f345d8eSLuigi Rizzo 5042f345d8eSLuigi Rizzo 5052f345d8eSLuigi Rizzo 5062f345d8eSLuigi Rizzo /** 5072f345d8eSLuigi Rizzo * @brief Create a receive queue 5082f345d8eSLuigi Rizzo * @param rq receive queue 5092f345d8eSLuigi Rizzo * @param if_id interface identifier index` 5102f345d8eSLuigi Rizzo * @param eq pointer to event queue 5112f345d8eSLuigi Rizzo */ 5122f345d8eSLuigi Rizzo static int 5132f345d8eSLuigi Rizzo oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq) 5142f345d8eSLuigi Rizzo { 5152f345d8eSLuigi Rizzo POCE_SOFTC sc = rq->parent; 5162f345d8eSLuigi Rizzo struct oce_cq *cq; 5172f345d8eSLuigi Rizzo 5182f345d8eSLuigi Rizzo cq = oce_cq_create(sc, 5192f345d8eSLuigi Rizzo eq, 5202f345d8eSLuigi Rizzo CQ_LEN_1024, 5212f345d8eSLuigi Rizzo sizeof(struct oce_nic_rx_cqe), 0, 1, 0, 3); 5222f345d8eSLuigi Rizzo if (!cq) 5232f345d8eSLuigi Rizzo return ENXIO; 5242f345d8eSLuigi Rizzo 5252f345d8eSLuigi Rizzo rq->cq = cq; 5262f345d8eSLuigi Rizzo rq->cfg.if_id = if_id; 5272f345d8eSLuigi Rizzo 5282f345d8eSLuigi Rizzo /* Dont create RQ here. Create in if_activate */ 5292f345d8eSLuigi Rizzo rq->qstate = 0; 5302f345d8eSLuigi Rizzo rq->ring->cidx = 0; 5312f345d8eSLuigi Rizzo rq->ring->pidx = 0; 5322f345d8eSLuigi Rizzo eq->cq[eq->cq_valid] = cq; 5332f345d8eSLuigi Rizzo eq->cq_valid++; 5342f345d8eSLuigi Rizzo cq->cb_arg = rq; 5352f345d8eSLuigi Rizzo cq->cq_handler = oce_rq_handler; 5362f345d8eSLuigi Rizzo 5372f345d8eSLuigi Rizzo return 0; 5382f345d8eSLuigi Rizzo 5392f345d8eSLuigi Rizzo } 5402f345d8eSLuigi Rizzo 5412f345d8eSLuigi Rizzo 5422f345d8eSLuigi Rizzo 5432f345d8eSLuigi Rizzo 5442f345d8eSLuigi Rizzo /** 5452f345d8eSLuigi Rizzo * @brief Delete a receive queue 5462f345d8eSLuigi Rizzo * @param rq receive queue 5472f345d8eSLuigi Rizzo */ 5482f345d8eSLuigi Rizzo static void 5492f345d8eSLuigi Rizzo oce_rq_del(struct oce_rq *rq) 5502f345d8eSLuigi Rizzo { 5512f345d8eSLuigi Rizzo POCE_SOFTC sc = (POCE_SOFTC) rq->parent; 5522f345d8eSLuigi Rizzo struct oce_mbx mbx; 5532f345d8eSLuigi Rizzo struct mbx_delete_nic_rq *fwcmd; 5542f345d8eSLuigi Rizzo 5552f345d8eSLuigi Rizzo if (rq->qstate == QCREATED) { 5562f345d8eSLuigi Rizzo bzero(&mbx, sizeof(mbx)); 5572f345d8eSLuigi Rizzo 5582f345d8eSLuigi Rizzo fwcmd = (struct mbx_delete_nic_rq *)&mbx.payload; 5592f345d8eSLuigi Rizzo fwcmd->params.req.rq_id = rq->rq_id; 5602f345d8eSLuigi Rizzo (void)oce_destroy_q(sc, &mbx, 5612f345d8eSLuigi Rizzo sizeof(struct mbx_delete_nic_rq), QTYPE_RQ); 5622f345d8eSLuigi Rizzo rq->qstate = QDELETED; 5632f345d8eSLuigi Rizzo } 5642f345d8eSLuigi Rizzo 5652f345d8eSLuigi Rizzo if (rq->cq != NULL) { 5662f345d8eSLuigi Rizzo oce_cq_del(sc, rq->cq); 5672f345d8eSLuigi Rizzo rq->cq = NULL; 5682f345d8eSLuigi Rizzo } 5692f345d8eSLuigi Rizzo } 5702f345d8eSLuigi Rizzo 5712f345d8eSLuigi Rizzo 5722f345d8eSLuigi Rizzo 5732f345d8eSLuigi Rizzo /** 5742f345d8eSLuigi Rizzo * @brief function to create an event queue 5752f345d8eSLuigi Rizzo * @param sc software handle to the device 5762f345d8eSLuigi Rizzo * @param q_len length of event queue 5772f345d8eSLuigi Rizzo * @param item_size size of an event queue item 5782f345d8eSLuigi Rizzo * @param eq_delay event queue delay 5792f345d8eSLuigi Rizzo * @retval eq success, pointer to event queue 5802f345d8eSLuigi Rizzo * @retval NULL failure 5812f345d8eSLuigi Rizzo */ 5822f345d8eSLuigi Rizzo static struct 5832f345d8eSLuigi Rizzo oce_eq *oce_eq_create(POCE_SOFTC sc, uint32_t q_len, 5842f345d8eSLuigi Rizzo uint32_t item_size, 5852f345d8eSLuigi Rizzo uint32_t eq_delay, 5862f345d8eSLuigi Rizzo uint32_t vector) 5872f345d8eSLuigi Rizzo { 5882f345d8eSLuigi Rizzo struct oce_eq *eq; 5892f345d8eSLuigi Rizzo int rc = 0; 5902f345d8eSLuigi Rizzo 5912f345d8eSLuigi Rizzo /* allocate an eq */ 5922f345d8eSLuigi Rizzo eq = malloc(sizeof(struct oce_eq), M_DEVBUF, M_NOWAIT | M_ZERO); 5932f345d8eSLuigi Rizzo if (eq == NULL) 5942f345d8eSLuigi Rizzo return NULL; 5952f345d8eSLuigi Rizzo 5962f345d8eSLuigi Rizzo eq->parent = (void *)sc; 5972f345d8eSLuigi Rizzo eq->eq_id = 0xffff; 5982f345d8eSLuigi Rizzo eq->ring = oce_create_ring_buffer(sc, q_len, item_size); 5992f345d8eSLuigi Rizzo if (!eq->ring) 6002f345d8eSLuigi Rizzo goto free_eq; 6012f345d8eSLuigi Rizzo 6022f345d8eSLuigi Rizzo eq->eq_cfg.q_len = q_len; 6032f345d8eSLuigi Rizzo eq->eq_cfg.item_size = item_size; 6042f345d8eSLuigi Rizzo eq->eq_cfg.cur_eqd = (uint8_t) eq_delay; 6052f345d8eSLuigi Rizzo 6062f345d8eSLuigi Rizzo rc = oce_mbox_create_eq(eq); 6072f345d8eSLuigi Rizzo if (rc) 6082f345d8eSLuigi Rizzo goto free_eq; 6092f345d8eSLuigi Rizzo 6102f345d8eSLuigi Rizzo sc->intrs[sc->neqs++].eq = eq; 6112f345d8eSLuigi Rizzo 6122f345d8eSLuigi Rizzo return eq; 6132f345d8eSLuigi Rizzo 6142f345d8eSLuigi Rizzo free_eq: 6152f345d8eSLuigi Rizzo oce_eq_del(eq); 6162f345d8eSLuigi Rizzo return NULL; 6172f345d8eSLuigi Rizzo } 6182f345d8eSLuigi Rizzo 6192f345d8eSLuigi Rizzo 6202f345d8eSLuigi Rizzo 6212f345d8eSLuigi Rizzo 6222f345d8eSLuigi Rizzo /** 6232f345d8eSLuigi Rizzo * @brief Function to delete an event queue 6242f345d8eSLuigi Rizzo * @param eq pointer to an event queue 6252f345d8eSLuigi Rizzo */ 6262f345d8eSLuigi Rizzo static void 6272f345d8eSLuigi Rizzo oce_eq_del(struct oce_eq *eq) 6282f345d8eSLuigi Rizzo { 6292f345d8eSLuigi Rizzo struct oce_mbx mbx; 6302f345d8eSLuigi Rizzo struct mbx_destroy_common_eq *fwcmd; 6312f345d8eSLuigi Rizzo POCE_SOFTC sc = (POCE_SOFTC) eq->parent; 6322f345d8eSLuigi Rizzo 6332f345d8eSLuigi Rizzo if (eq->eq_id != 0xffff) { 6342f345d8eSLuigi Rizzo bzero(&mbx, sizeof(mbx)); 6352f345d8eSLuigi Rizzo fwcmd = (struct mbx_destroy_common_eq *)&mbx.payload; 6362f345d8eSLuigi Rizzo fwcmd->params.req.id = eq->eq_id; 6372f345d8eSLuigi Rizzo (void)oce_destroy_q(sc, &mbx, 6382f345d8eSLuigi Rizzo sizeof(struct mbx_destroy_common_eq), QTYPE_EQ); 6392f345d8eSLuigi Rizzo } 6402f345d8eSLuigi Rizzo 6412f345d8eSLuigi Rizzo if (eq->ring != NULL) { 6422f345d8eSLuigi Rizzo oce_destroy_ring_buffer(sc, eq->ring); 6432f345d8eSLuigi Rizzo eq->ring = NULL; 6442f345d8eSLuigi Rizzo } 6452f345d8eSLuigi Rizzo 6462f345d8eSLuigi Rizzo free(eq, M_DEVBUF); 6472f345d8eSLuigi Rizzo 6482f345d8eSLuigi Rizzo } 6492f345d8eSLuigi Rizzo 6502f345d8eSLuigi Rizzo 6512f345d8eSLuigi Rizzo 6522f345d8eSLuigi Rizzo 6532f345d8eSLuigi Rizzo /** 6542f345d8eSLuigi Rizzo * @brief Function to create an MQ 6552f345d8eSLuigi Rizzo * @param sc software handle to the device 6562f345d8eSLuigi Rizzo * @param eq the EQ to associate with the MQ for event notification 6572f345d8eSLuigi Rizzo * @param q_len the number of entries to create in the MQ 6582f345d8eSLuigi Rizzo * @returns pointer to the created MQ, failure otherwise 6592f345d8eSLuigi Rizzo */ 6602f345d8eSLuigi Rizzo static struct oce_mq * 6612f345d8eSLuigi Rizzo oce_mq_create(POCE_SOFTC sc, struct oce_eq *eq, uint32_t q_len) 6622f345d8eSLuigi Rizzo { 6632f345d8eSLuigi Rizzo struct oce_mbx mbx; 6649bd3250aSLuigi Rizzo struct mbx_create_common_mq_ex *fwcmd = NULL; 6652f345d8eSLuigi Rizzo struct oce_mq *mq = NULL; 6662f345d8eSLuigi Rizzo int rc = 0; 6672f345d8eSLuigi Rizzo struct oce_cq *cq; 6689bd3250aSLuigi Rizzo oce_mq_ext_ctx_t *ctx; 6692f345d8eSLuigi Rizzo uint32_t num_pages; 6702f345d8eSLuigi Rizzo uint32_t page_size; 671cdaba892SXin LI int version; 6722f345d8eSLuigi Rizzo 6732f345d8eSLuigi Rizzo cq = oce_cq_create(sc, eq, CQ_LEN_256, 6742f345d8eSLuigi Rizzo sizeof(struct oce_mq_cqe), 1, 1, 0, 0); 6752f345d8eSLuigi Rizzo if (!cq) 6762f345d8eSLuigi Rizzo return NULL; 6772f345d8eSLuigi Rizzo 6782f345d8eSLuigi Rizzo /* allocate the mq */ 6792f345d8eSLuigi Rizzo mq = malloc(sizeof(struct oce_mq), M_DEVBUF, M_NOWAIT | M_ZERO); 6802f345d8eSLuigi Rizzo if (!mq) { 6812f345d8eSLuigi Rizzo oce_cq_del(sc, cq); 6822f345d8eSLuigi Rizzo goto error; 6832f345d8eSLuigi Rizzo } 6842f345d8eSLuigi Rizzo 6852f345d8eSLuigi Rizzo mq->parent = sc; 6862f345d8eSLuigi Rizzo 6872f345d8eSLuigi Rizzo mq->ring = oce_create_ring_buffer(sc, q_len, sizeof(struct oce_mbx)); 6882f345d8eSLuigi Rizzo if (!mq->ring) 6892f345d8eSLuigi Rizzo goto error; 6902f345d8eSLuigi Rizzo 6912f345d8eSLuigi Rizzo bzero(&mbx, sizeof(struct oce_mbx)); 6922f345d8eSLuigi Rizzo 693cdaba892SXin LI IS_XE201(sc) ? (version = OCE_MBX_VER_V1) : (version = OCE_MBX_VER_V0); 6949bd3250aSLuigi Rizzo fwcmd = (struct mbx_create_common_mq_ex *)&mbx.payload; 6952f345d8eSLuigi Rizzo mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 6962f345d8eSLuigi Rizzo MBX_SUBSYSTEM_COMMON, 6979bd3250aSLuigi Rizzo OPCODE_COMMON_CREATE_MQ_EXT, 6982f345d8eSLuigi Rizzo MBX_TIMEOUT_SEC, 6999bd3250aSLuigi Rizzo sizeof(struct mbx_create_common_mq_ex), 7002f345d8eSLuigi Rizzo version); 7012f345d8eSLuigi Rizzo 7022f345d8eSLuigi Rizzo num_pages = oce_page_list(mq->ring, &fwcmd->params.req.pages[0]); 7032f345d8eSLuigi Rizzo page_size = mq->ring->num_items * mq->ring->item_size; 7042f345d8eSLuigi Rizzo 7052f345d8eSLuigi Rizzo ctx = &fwcmd->params.req.context; 706cdaba892SXin LI 707cdaba892SXin LI if (IS_XE201(sc)) { 708cdaba892SXin LI ctx->v1.num_pages = num_pages; 709cdaba892SXin LI ctx->v1.ring_size = OCE_LOG2(q_len) + 1; 710cdaba892SXin LI ctx->v1.cq_id = cq->cq_id; 711cdaba892SXin LI ctx->v1.valid = 1; 712cdaba892SXin LI ctx->v1.async_cq_id = cq->cq_id; 713cdaba892SXin LI ctx->v1.async_cq_valid = 1; 714cdaba892SXin LI /* Subscribe to Link State and Group 5 Events(bits 1 & 5 set) */ 715cdaba892SXin LI ctx->v1.async_evt_bitmap |= LE_32(0x00000022); 716cdaba892SXin LI ctx->v1.async_evt_bitmap |= LE_32(1 << ASYNC_EVENT_CODE_DEBUG); 717cdaba892SXin LI ctx->v1.async_evt_bitmap |= 718cdaba892SXin LI LE_32(1 << ASYNC_EVENT_CODE_SLIPORT); 719cdaba892SXin LI } 720cdaba892SXin LI else { 7212f345d8eSLuigi Rizzo ctx->v0.num_pages = num_pages; 7222f345d8eSLuigi Rizzo ctx->v0.cq_id = cq->cq_id; 7232f345d8eSLuigi Rizzo ctx->v0.ring_size = OCE_LOG2(q_len) + 1; 7242f345d8eSLuigi Rizzo ctx->v0.valid = 1; 725cdaba892SXin LI /* Subscribe to Link State and Group5 Events(bits 1 & 5 set) */ 7269bd3250aSLuigi Rizzo ctx->v0.async_evt_bitmap = 0xffffffff; 727cdaba892SXin LI } 7282f345d8eSLuigi Rizzo 7292f345d8eSLuigi Rizzo mbx.u0.s.embedded = 1; 7309bd3250aSLuigi Rizzo mbx.payload_length = sizeof(struct mbx_create_common_mq_ex); 7312f345d8eSLuigi Rizzo DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 7322f345d8eSLuigi Rizzo 7332f345d8eSLuigi Rizzo rc = oce_mbox_post(sc, &mbx, NULL); 734cdaba892SXin LI if (!rc) 735cdaba892SXin LI rc = fwcmd->hdr.u0.rsp.status; 736cdaba892SXin LI if (rc) { 737cdaba892SXin LI device_printf(sc->dev,"%s failed - cmd status: %d\n", 738cdaba892SXin LI __FUNCTION__, rc); 7392f345d8eSLuigi Rizzo goto error; 740cdaba892SXin LI } 7412f345d8eSLuigi Rizzo mq->mq_id = LE_16(fwcmd->params.rsp.mq_id); 7422f345d8eSLuigi Rizzo mq->cq = cq; 7432f345d8eSLuigi Rizzo eq->cq[eq->cq_valid] = cq; 7442f345d8eSLuigi Rizzo eq->cq_valid++; 7452f345d8eSLuigi Rizzo mq->cq->eq = eq; 7462f345d8eSLuigi Rizzo mq->cfg.q_len = (uint8_t) q_len; 7472f345d8eSLuigi Rizzo mq->cfg.eqd = 0; 7482f345d8eSLuigi Rizzo mq->qstate = QCREATED; 7492f345d8eSLuigi Rizzo 7502f345d8eSLuigi Rizzo mq->cq->cb_arg = mq; 7512f345d8eSLuigi Rizzo mq->cq->cq_handler = oce_mq_handler; 7522f345d8eSLuigi Rizzo 7532f345d8eSLuigi Rizzo return mq; 7542f345d8eSLuigi Rizzo 7552f345d8eSLuigi Rizzo error: 7562f345d8eSLuigi Rizzo device_printf(sc->dev, "MQ create failed\n"); 7572f345d8eSLuigi Rizzo oce_mq_free(mq); 7582f345d8eSLuigi Rizzo mq = NULL; 7592f345d8eSLuigi Rizzo return mq; 7602f345d8eSLuigi Rizzo } 7612f345d8eSLuigi Rizzo 7622f345d8eSLuigi Rizzo 7632f345d8eSLuigi Rizzo 7642f345d8eSLuigi Rizzo 7652f345d8eSLuigi Rizzo 7662f345d8eSLuigi Rizzo /** 7672f345d8eSLuigi Rizzo * @brief Function to free a mailbox queue 7682f345d8eSLuigi Rizzo * @param mq pointer to a mailbox queue 7692f345d8eSLuigi Rizzo */ 7702f345d8eSLuigi Rizzo static void 7712f345d8eSLuigi Rizzo oce_mq_free(struct oce_mq *mq) 7722f345d8eSLuigi Rizzo { 7732f345d8eSLuigi Rizzo POCE_SOFTC sc = (POCE_SOFTC) mq->parent; 7742f345d8eSLuigi Rizzo struct oce_mbx mbx; 7752f345d8eSLuigi Rizzo struct mbx_destroy_common_mq *fwcmd; 7762f345d8eSLuigi Rizzo 7772f345d8eSLuigi Rizzo if (!mq) 7782f345d8eSLuigi Rizzo return; 7792f345d8eSLuigi Rizzo 7802f345d8eSLuigi Rizzo if (mq->ring != NULL) { 7812f345d8eSLuigi Rizzo oce_destroy_ring_buffer(sc, mq->ring); 7822f345d8eSLuigi Rizzo mq->ring = NULL; 7832f345d8eSLuigi Rizzo if (mq->qstate == QCREATED) { 7842f345d8eSLuigi Rizzo bzero(&mbx, sizeof (struct oce_mbx)); 7852f345d8eSLuigi Rizzo fwcmd = (struct mbx_destroy_common_mq *)&mbx.payload; 7862f345d8eSLuigi Rizzo fwcmd->params.req.id = mq->mq_id; 7872f345d8eSLuigi Rizzo (void) oce_destroy_q(sc, &mbx, 7882f345d8eSLuigi Rizzo sizeof (struct mbx_destroy_common_mq), 7892f345d8eSLuigi Rizzo QTYPE_MQ); 7902f345d8eSLuigi Rizzo } 7912f345d8eSLuigi Rizzo mq->qstate = QDELETED; 7922f345d8eSLuigi Rizzo } 7932f345d8eSLuigi Rizzo 7942f345d8eSLuigi Rizzo if (mq->cq != NULL) { 7952f345d8eSLuigi Rizzo oce_cq_del(sc, mq->cq); 7962f345d8eSLuigi Rizzo mq->cq = NULL; 7972f345d8eSLuigi Rizzo } 7982f345d8eSLuigi Rizzo 7992f345d8eSLuigi Rizzo free(mq, M_DEVBUF); 8002f345d8eSLuigi Rizzo mq = NULL; 8012f345d8eSLuigi Rizzo } 8022f345d8eSLuigi Rizzo 8032f345d8eSLuigi Rizzo 8042f345d8eSLuigi Rizzo 8052f345d8eSLuigi Rizzo /** 8062f345d8eSLuigi Rizzo * @brief Function to delete a EQ, CQ, MQ, WQ or RQ 8072f345d8eSLuigi Rizzo * @param sc sofware handle to the device 8082f345d8eSLuigi Rizzo * @param mbx mailbox command to send to the fw to delete the queue 8092f345d8eSLuigi Rizzo * (mbx contains the queue information to delete) 8102f345d8eSLuigi Rizzo * @param req_size the size of the mbx payload dependent on the qtype 8112f345d8eSLuigi Rizzo * @param qtype the type of queue i.e. EQ, CQ, MQ, WQ or RQ 8122f345d8eSLuigi Rizzo * @returns 0 on success, failure otherwise 8132f345d8eSLuigi Rizzo */ 8142f345d8eSLuigi Rizzo static int 8152f345d8eSLuigi Rizzo oce_destroy_q(POCE_SOFTC sc, struct oce_mbx *mbx, size_t req_size, 8162f345d8eSLuigi Rizzo enum qtype qtype) 8172f345d8eSLuigi Rizzo { 8182f345d8eSLuigi Rizzo struct mbx_hdr *hdr = (struct mbx_hdr *)&mbx->payload; 8192f345d8eSLuigi Rizzo int opcode; 8202f345d8eSLuigi Rizzo int subsys; 8212f345d8eSLuigi Rizzo int rc = 0; 8222f345d8eSLuigi Rizzo 8232f345d8eSLuigi Rizzo switch (qtype) { 8242f345d8eSLuigi Rizzo case QTYPE_EQ: 8252f345d8eSLuigi Rizzo opcode = OPCODE_COMMON_DESTROY_EQ; 8262f345d8eSLuigi Rizzo subsys = MBX_SUBSYSTEM_COMMON; 8272f345d8eSLuigi Rizzo break; 8282f345d8eSLuigi Rizzo case QTYPE_CQ: 8292f345d8eSLuigi Rizzo opcode = OPCODE_COMMON_DESTROY_CQ; 8302f345d8eSLuigi Rizzo subsys = MBX_SUBSYSTEM_COMMON; 8312f345d8eSLuigi Rizzo break; 8322f345d8eSLuigi Rizzo case QTYPE_MQ: 8332f345d8eSLuigi Rizzo opcode = OPCODE_COMMON_DESTROY_MQ; 8342f345d8eSLuigi Rizzo subsys = MBX_SUBSYSTEM_COMMON; 8352f345d8eSLuigi Rizzo break; 8362f345d8eSLuigi Rizzo case QTYPE_WQ: 8372f345d8eSLuigi Rizzo opcode = NIC_DELETE_WQ; 8382f345d8eSLuigi Rizzo subsys = MBX_SUBSYSTEM_NIC; 8392f345d8eSLuigi Rizzo break; 8402f345d8eSLuigi Rizzo case QTYPE_RQ: 8412f345d8eSLuigi Rizzo opcode = NIC_DELETE_RQ; 8422f345d8eSLuigi Rizzo subsys = MBX_SUBSYSTEM_NIC; 8432f345d8eSLuigi Rizzo break; 8442f345d8eSLuigi Rizzo default: 8452f345d8eSLuigi Rizzo return EINVAL; 8462f345d8eSLuigi Rizzo } 8472f345d8eSLuigi Rizzo 8482f345d8eSLuigi Rizzo mbx_common_req_hdr_init(hdr, 0, 0, subsys, 8492f345d8eSLuigi Rizzo opcode, MBX_TIMEOUT_SEC, req_size, 8502f345d8eSLuigi Rizzo OCE_MBX_VER_V0); 8512f345d8eSLuigi Rizzo 8522f345d8eSLuigi Rizzo mbx->u0.s.embedded = 1; 8532f345d8eSLuigi Rizzo mbx->payload_length = (uint32_t) req_size; 8542f345d8eSLuigi Rizzo DW_SWAP(u32ptr(mbx), mbx->payload_length + OCE_BMBX_RHDR_SZ); 8552f345d8eSLuigi Rizzo 8562f345d8eSLuigi Rizzo rc = oce_mbox_post(sc, mbx, NULL); 857cdaba892SXin LI if (!rc) 858cdaba892SXin LI rc = hdr->u0.rsp.status; 859cdaba892SXin LI if (rc) 860cdaba892SXin LI device_printf(sc->dev,"%s failed - cmd status: %d\n", 861cdaba892SXin LI __FUNCTION__, rc); 8622f345d8eSLuigi Rizzo return rc; 8632f345d8eSLuigi Rizzo } 8642f345d8eSLuigi Rizzo 8652f345d8eSLuigi Rizzo 8662f345d8eSLuigi Rizzo 8672f345d8eSLuigi Rizzo /** 8682f345d8eSLuigi Rizzo * @brief Function to create a completion queue 8692f345d8eSLuigi Rizzo * @param sc software handle to the device 8702f345d8eSLuigi Rizzo * @param eq optional eq to be associated with to the cq 8712f345d8eSLuigi Rizzo * @param q_len length of completion queue 8722f345d8eSLuigi Rizzo * @param item_size size of completion queue items 8732f345d8eSLuigi Rizzo * @param sol_event command context event 8742f345d8eSLuigi Rizzo * @param is_eventable event table 8752f345d8eSLuigi Rizzo * @param nodelay no delay flag 8762f345d8eSLuigi Rizzo * @param ncoalesce no coalescence flag 8772f345d8eSLuigi Rizzo * @returns pointer to the cq created, NULL on failure 8782f345d8eSLuigi Rizzo */ 8792f345d8eSLuigi Rizzo struct oce_cq * 8802f345d8eSLuigi Rizzo oce_cq_create(POCE_SOFTC sc, struct oce_eq *eq, 8812f345d8eSLuigi Rizzo uint32_t q_len, 8822f345d8eSLuigi Rizzo uint32_t item_size, 8832f345d8eSLuigi Rizzo uint32_t sol_event, 8842f345d8eSLuigi Rizzo uint32_t is_eventable, 8852f345d8eSLuigi Rizzo uint32_t nodelay, uint32_t ncoalesce) 8862f345d8eSLuigi Rizzo { 8872f345d8eSLuigi Rizzo struct oce_cq *cq = NULL; 8882f345d8eSLuigi Rizzo int rc = 0; 8892f345d8eSLuigi Rizzo 8902f345d8eSLuigi Rizzo cq = malloc(sizeof(struct oce_cq), M_DEVBUF, M_NOWAIT | M_ZERO); 8912f345d8eSLuigi Rizzo if (!cq) 8922f345d8eSLuigi Rizzo return NULL; 8932f345d8eSLuigi Rizzo 8942f345d8eSLuigi Rizzo cq->ring = oce_create_ring_buffer(sc, q_len, item_size); 8952f345d8eSLuigi Rizzo if (!cq->ring) 8962f345d8eSLuigi Rizzo goto error; 8972f345d8eSLuigi Rizzo 8982f345d8eSLuigi Rizzo cq->parent = sc; 8992f345d8eSLuigi Rizzo cq->eq = eq; 9002f345d8eSLuigi Rizzo cq->cq_cfg.q_len = q_len; 9012f345d8eSLuigi Rizzo cq->cq_cfg.item_size = item_size; 9022f345d8eSLuigi Rizzo cq->cq_cfg.nodelay = (uint8_t) nodelay; 9032f345d8eSLuigi Rizzo 9042f345d8eSLuigi Rizzo rc = oce_mbox_cq_create(cq, ncoalesce, is_eventable); 9052f345d8eSLuigi Rizzo if (rc) 9062f345d8eSLuigi Rizzo goto error; 9072f345d8eSLuigi Rizzo 9082f345d8eSLuigi Rizzo sc->cq[sc->ncqs++] = cq; 9092f345d8eSLuigi Rizzo 9102f345d8eSLuigi Rizzo return cq; 9112f345d8eSLuigi Rizzo 9122f345d8eSLuigi Rizzo error: 9132f345d8eSLuigi Rizzo device_printf(sc->dev, "CQ create failed\n"); 9142f345d8eSLuigi Rizzo oce_cq_del(sc, cq); 9152f345d8eSLuigi Rizzo return NULL; 9162f345d8eSLuigi Rizzo } 9172f345d8eSLuigi Rizzo 9182f345d8eSLuigi Rizzo 9192f345d8eSLuigi Rizzo 9202f345d8eSLuigi Rizzo /** 9212f345d8eSLuigi Rizzo * @brief Deletes the completion queue 9222f345d8eSLuigi Rizzo * @param sc software handle to the device 9232f345d8eSLuigi Rizzo * @param cq pointer to a completion queue 9242f345d8eSLuigi Rizzo */ 9252f345d8eSLuigi Rizzo static void 9262f345d8eSLuigi Rizzo oce_cq_del(POCE_SOFTC sc, struct oce_cq *cq) 9272f345d8eSLuigi Rizzo { 9282f345d8eSLuigi Rizzo struct oce_mbx mbx; 9292f345d8eSLuigi Rizzo struct mbx_destroy_common_cq *fwcmd; 9302f345d8eSLuigi Rizzo 9312f345d8eSLuigi Rizzo if (cq->ring != NULL) { 9322f345d8eSLuigi Rizzo 9332f345d8eSLuigi Rizzo bzero(&mbx, sizeof(struct oce_mbx)); 9342f345d8eSLuigi Rizzo /* now fill the command */ 9352f345d8eSLuigi Rizzo fwcmd = (struct mbx_destroy_common_cq *)&mbx.payload; 9362f345d8eSLuigi Rizzo fwcmd->params.req.id = cq->cq_id; 9372f345d8eSLuigi Rizzo (void)oce_destroy_q(sc, &mbx, 9382f345d8eSLuigi Rizzo sizeof(struct mbx_destroy_common_cq), QTYPE_CQ); 9392f345d8eSLuigi Rizzo /*NOW destroy the ring */ 9402f345d8eSLuigi Rizzo oce_destroy_ring_buffer(sc, cq->ring); 9412f345d8eSLuigi Rizzo cq->ring = NULL; 9422f345d8eSLuigi Rizzo } 9432f345d8eSLuigi Rizzo 9442f345d8eSLuigi Rizzo free(cq, M_DEVBUF); 9452f345d8eSLuigi Rizzo cq = NULL; 9462f345d8eSLuigi Rizzo } 9472f345d8eSLuigi Rizzo 9482f345d8eSLuigi Rizzo 9492f345d8eSLuigi Rizzo 9502f345d8eSLuigi Rizzo /** 9512f345d8eSLuigi Rizzo * @brief Start a receive queue 9522f345d8eSLuigi Rizzo * @param rq pointer to a receive queue 9532f345d8eSLuigi Rizzo */ 9542f345d8eSLuigi Rizzo int 9552f345d8eSLuigi Rizzo oce_start_rq(struct oce_rq *rq) 9562f345d8eSLuigi Rizzo { 9572f345d8eSLuigi Rizzo int rc; 9582f345d8eSLuigi Rizzo 9592f345d8eSLuigi Rizzo rc = oce_alloc_rx_bufs(rq, rq->cfg.q_len); 9602f345d8eSLuigi Rizzo 9612f345d8eSLuigi Rizzo if (rc == 0) 9622f345d8eSLuigi Rizzo oce_arm_cq(rq->parent, rq->cq->cq_id, 0, TRUE); 9632f345d8eSLuigi Rizzo return rc; 9642f345d8eSLuigi Rizzo } 9652f345d8eSLuigi Rizzo 9662f345d8eSLuigi Rizzo 9672f345d8eSLuigi Rizzo 9682f345d8eSLuigi Rizzo /** 9692f345d8eSLuigi Rizzo * @brief Start a work queue 9702f345d8eSLuigi Rizzo * @param wq pointer to a work queue 9712f345d8eSLuigi Rizzo */ 9722f345d8eSLuigi Rizzo int 9732f345d8eSLuigi Rizzo oce_start_wq(struct oce_wq *wq) 9742f345d8eSLuigi Rizzo { 9752f345d8eSLuigi Rizzo oce_arm_cq(wq->parent, wq->cq->cq_id, 0, TRUE); 9762f345d8eSLuigi Rizzo return 0; 9772f345d8eSLuigi Rizzo } 9782f345d8eSLuigi Rizzo 9792f345d8eSLuigi Rizzo 9802f345d8eSLuigi Rizzo 9812f345d8eSLuigi Rizzo /** 9822f345d8eSLuigi Rizzo * @brief Start a mailbox queue 9832f345d8eSLuigi Rizzo * @param mq pointer to a mailbox queue 9842f345d8eSLuigi Rizzo */ 9852f345d8eSLuigi Rizzo int 9862f345d8eSLuigi Rizzo oce_start_mq(struct oce_mq *mq) 9872f345d8eSLuigi Rizzo { 9882f345d8eSLuigi Rizzo oce_arm_cq(mq->parent, mq->cq->cq_id, 0, TRUE); 9892f345d8eSLuigi Rizzo return 0; 9902f345d8eSLuigi Rizzo } 9912f345d8eSLuigi Rizzo 9922f345d8eSLuigi Rizzo 9932f345d8eSLuigi Rizzo 9942f345d8eSLuigi Rizzo /** 9952f345d8eSLuigi Rizzo * @brief Function to arm an EQ so that it can generate events 9962f345d8eSLuigi Rizzo * @param sc software handle to the device 9972f345d8eSLuigi Rizzo * @param qid id of the EQ returned by the fw at the time of creation 9982f345d8eSLuigi Rizzo * @param npopped number of EQEs to arm 9992f345d8eSLuigi Rizzo * @param rearm rearm bit enable/disable 10002f345d8eSLuigi Rizzo * @param clearint bit to clear the interrupt condition because of which 10012f345d8eSLuigi Rizzo * EQEs are generated 10022f345d8eSLuigi Rizzo */ 10032f345d8eSLuigi Rizzo void 10042f345d8eSLuigi Rizzo oce_arm_eq(POCE_SOFTC sc, 10052f345d8eSLuigi Rizzo int16_t qid, int npopped, uint32_t rearm, uint32_t clearint) 10062f345d8eSLuigi Rizzo { 10072f345d8eSLuigi Rizzo eq_db_t eq_db = { 0 }; 10082f345d8eSLuigi Rizzo 10092f345d8eSLuigi Rizzo eq_db.bits.rearm = rearm; 10102f345d8eSLuigi Rizzo eq_db.bits.event = 1; 10112f345d8eSLuigi Rizzo eq_db.bits.num_popped = npopped; 10122f345d8eSLuigi Rizzo eq_db.bits.clrint = clearint; 10132f345d8eSLuigi Rizzo eq_db.bits.qid = qid; 10142f345d8eSLuigi Rizzo OCE_WRITE_REG32(sc, db, PD_EQ_DB, eq_db.dw0); 10152f345d8eSLuigi Rizzo 10162f345d8eSLuigi Rizzo } 10172f345d8eSLuigi Rizzo 10182f345d8eSLuigi Rizzo 10192f345d8eSLuigi Rizzo 10202f345d8eSLuigi Rizzo 10212f345d8eSLuigi Rizzo /** 10222f345d8eSLuigi Rizzo * @brief Function to arm a CQ with CQEs 10232f345d8eSLuigi Rizzo * @param sc software handle to the device 10242f345d8eSLuigi Rizzo * @param qid id of the CQ returned by the fw at the time of creation 10252f345d8eSLuigi Rizzo * @param npopped number of CQEs to arm 10262f345d8eSLuigi Rizzo * @param rearm rearm bit enable/disable 10272f345d8eSLuigi Rizzo */ 10282f345d8eSLuigi Rizzo void oce_arm_cq(POCE_SOFTC sc, int16_t qid, int npopped, uint32_t rearm) 10292f345d8eSLuigi Rizzo { 10302f345d8eSLuigi Rizzo cq_db_t cq_db = { 0 }; 10312f345d8eSLuigi Rizzo 10322f345d8eSLuigi Rizzo cq_db.bits.rearm = rearm; 10332f345d8eSLuigi Rizzo cq_db.bits.num_popped = npopped; 10342f345d8eSLuigi Rizzo cq_db.bits.event = 0; 10352f345d8eSLuigi Rizzo cq_db.bits.qid = qid; 10362f345d8eSLuigi Rizzo OCE_WRITE_REG32(sc, db, PD_CQ_DB, cq_db.dw0); 10372f345d8eSLuigi Rizzo 10382f345d8eSLuigi Rizzo } 10392f345d8eSLuigi Rizzo 10402f345d8eSLuigi Rizzo 10412f345d8eSLuigi Rizzo 10422f345d8eSLuigi Rizzo 10432f345d8eSLuigi Rizzo /* 10442f345d8eSLuigi Rizzo * @brief function to cleanup the eqs used during stop 10452f345d8eSLuigi Rizzo * @param eq pointer to event queue structure 10462f345d8eSLuigi Rizzo * @returns the number of EQs processed 10472f345d8eSLuigi Rizzo */ 10482f345d8eSLuigi Rizzo void 10492f345d8eSLuigi Rizzo oce_drain_eq(struct oce_eq *eq) 10502f345d8eSLuigi Rizzo { 10512f345d8eSLuigi Rizzo 10522f345d8eSLuigi Rizzo struct oce_eqe *eqe; 10532f345d8eSLuigi Rizzo uint16_t num_eqe = 0; 10542f345d8eSLuigi Rizzo POCE_SOFTC sc = eq->parent; 10552f345d8eSLuigi Rizzo 10562f345d8eSLuigi Rizzo do { 10572f345d8eSLuigi Rizzo eqe = RING_GET_CONSUMER_ITEM_VA(eq->ring, struct oce_eqe); 10582f345d8eSLuigi Rizzo if (eqe->evnt == 0) 10592f345d8eSLuigi Rizzo break; 10602f345d8eSLuigi Rizzo eqe->evnt = 0; 10612f345d8eSLuigi Rizzo bus_dmamap_sync(eq->ring->dma.tag, eq->ring->dma.map, 10622f345d8eSLuigi Rizzo BUS_DMASYNC_POSTWRITE); 10632f345d8eSLuigi Rizzo num_eqe++; 10642f345d8eSLuigi Rizzo RING_GET(eq->ring, 1); 10652f345d8eSLuigi Rizzo 10662f345d8eSLuigi Rizzo } while (TRUE); 10672f345d8eSLuigi Rizzo 10682f345d8eSLuigi Rizzo oce_arm_eq(sc, eq->eq_id, num_eqe, FALSE, TRUE); 10692f345d8eSLuigi Rizzo 10702f345d8eSLuigi Rizzo } 10712f345d8eSLuigi Rizzo 10722f345d8eSLuigi Rizzo 10732f345d8eSLuigi Rizzo 10742f345d8eSLuigi Rizzo void 10752f345d8eSLuigi Rizzo oce_drain_wq_cq(struct oce_wq *wq) 10762f345d8eSLuigi Rizzo { 10772f345d8eSLuigi Rizzo POCE_SOFTC sc = wq->parent; 10782f345d8eSLuigi Rizzo struct oce_cq *cq = wq->cq; 10792f345d8eSLuigi Rizzo struct oce_nic_tx_cqe *cqe; 10802f345d8eSLuigi Rizzo int num_cqes = 0; 10812f345d8eSLuigi Rizzo 10822f345d8eSLuigi Rizzo bus_dmamap_sync(cq->ring->dma.tag, cq->ring->dma.map, 10832f345d8eSLuigi Rizzo BUS_DMASYNC_POSTWRITE); 10842f345d8eSLuigi Rizzo 10852f345d8eSLuigi Rizzo do { 10862f345d8eSLuigi Rizzo cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_tx_cqe); 10872f345d8eSLuigi Rizzo if (cqe->u0.dw[3] == 0) 10882f345d8eSLuigi Rizzo break; 10892f345d8eSLuigi Rizzo cqe->u0.dw[3] = 0; 10902f345d8eSLuigi Rizzo bus_dmamap_sync(cq->ring->dma.tag, cq->ring->dma.map, 10912f345d8eSLuigi Rizzo BUS_DMASYNC_POSTWRITE); 10922f345d8eSLuigi Rizzo RING_GET(cq->ring, 1); 10932f345d8eSLuigi Rizzo num_cqes++; 10942f345d8eSLuigi Rizzo 10952f345d8eSLuigi Rizzo } while (TRUE); 10962f345d8eSLuigi Rizzo 10972f345d8eSLuigi Rizzo oce_arm_cq(sc, cq->cq_id, num_cqes, FALSE); 10982f345d8eSLuigi Rizzo 10992f345d8eSLuigi Rizzo } 11002f345d8eSLuigi Rizzo 11012f345d8eSLuigi Rizzo 11022f345d8eSLuigi Rizzo /* 11032f345d8eSLuigi Rizzo * @brief function to drain a MCQ and process its CQEs 11042f345d8eSLuigi Rizzo * @param dev software handle to the device 11052f345d8eSLuigi Rizzo * @param cq pointer to the cq to drain 11062f345d8eSLuigi Rizzo * @returns the number of CQEs processed 11072f345d8eSLuigi Rizzo */ 11082f345d8eSLuigi Rizzo void 11092f345d8eSLuigi Rizzo oce_drain_mq_cq(void *arg) 11102f345d8eSLuigi Rizzo { 11112f345d8eSLuigi Rizzo /* TODO: additional code. */ 11122f345d8eSLuigi Rizzo return; 11132f345d8eSLuigi Rizzo } 11142f345d8eSLuigi Rizzo 11152f345d8eSLuigi Rizzo 11162f345d8eSLuigi Rizzo 11172f345d8eSLuigi Rizzo /** 11182f345d8eSLuigi Rizzo * @brief function to process a Recieve queue 11192f345d8eSLuigi Rizzo * @param arg pointer to the RQ to charge 11202f345d8eSLuigi Rizzo * @return number of cqes processed 11212f345d8eSLuigi Rizzo */ 11222f345d8eSLuigi Rizzo void 11232f345d8eSLuigi Rizzo oce_drain_rq_cq(struct oce_rq *rq) 11242f345d8eSLuigi Rizzo { 11252f345d8eSLuigi Rizzo struct oce_nic_rx_cqe *cqe; 11262f345d8eSLuigi Rizzo uint16_t num_cqe = 0; 11272f345d8eSLuigi Rizzo struct oce_cq *cq; 11282f345d8eSLuigi Rizzo POCE_SOFTC sc; 11292f345d8eSLuigi Rizzo 11302f345d8eSLuigi Rizzo sc = rq->parent; 11312f345d8eSLuigi Rizzo cq = rq->cq; 11322f345d8eSLuigi Rizzo cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_rx_cqe); 11332f345d8eSLuigi Rizzo /* dequeue till you reach an invalid cqe */ 11342f345d8eSLuigi Rizzo while (RQ_CQE_VALID(cqe)) { 11352f345d8eSLuigi Rizzo RQ_CQE_INVALIDATE(cqe); 11362f345d8eSLuigi Rizzo RING_GET(cq->ring, 1); 11372f345d8eSLuigi Rizzo cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, 11382f345d8eSLuigi Rizzo struct oce_nic_rx_cqe); 11392f345d8eSLuigi Rizzo num_cqe++; 11402f345d8eSLuigi Rizzo } 11412f345d8eSLuigi Rizzo oce_arm_cq(sc, cq->cq_id, num_cqe, FALSE); 11422f345d8eSLuigi Rizzo 11432f345d8eSLuigi Rizzo return; 11442f345d8eSLuigi Rizzo } 11452f345d8eSLuigi Rizzo 11462f345d8eSLuigi Rizzo 11472f345d8eSLuigi Rizzo void 11482f345d8eSLuigi Rizzo oce_free_posted_rxbuf(struct oce_rq *rq) 11492f345d8eSLuigi Rizzo { 11502f345d8eSLuigi Rizzo struct oce_packet_desc *pd; 11512f345d8eSLuigi Rizzo 11522f345d8eSLuigi Rizzo while (rq->pending) { 11532f345d8eSLuigi Rizzo 11542f345d8eSLuigi Rizzo pd = &rq->pckts[rq->packets_out]; 11552f345d8eSLuigi Rizzo bus_dmamap_sync(rq->tag, pd->map, BUS_DMASYNC_POSTWRITE); 11562f345d8eSLuigi Rizzo bus_dmamap_unload(rq->tag, pd->map); 11572f345d8eSLuigi Rizzo if (pd->mbuf != NULL) { 11582f345d8eSLuigi Rizzo m_freem(pd->mbuf); 11592f345d8eSLuigi Rizzo pd->mbuf = NULL; 11602f345d8eSLuigi Rizzo } 11612f345d8eSLuigi Rizzo 11622f345d8eSLuigi Rizzo if ((rq->packets_out + 1) == OCE_RQ_PACKET_ARRAY_SIZE) 11632f345d8eSLuigi Rizzo rq->packets_out = 0; 11642f345d8eSLuigi Rizzo else 11652f345d8eSLuigi Rizzo rq->packets_out++; 11662f345d8eSLuigi Rizzo 11672f345d8eSLuigi Rizzo rq->pending--; 11682f345d8eSLuigi Rizzo } 11692f345d8eSLuigi Rizzo 11702f345d8eSLuigi Rizzo } 11712f345d8eSLuigi Rizzo 11722f345d8eSLuigi Rizzo void 11732f345d8eSLuigi Rizzo oce_stop_rx(POCE_SOFTC sc) 11742f345d8eSLuigi Rizzo { 11752f345d8eSLuigi Rizzo struct oce_mbx mbx; 11762f345d8eSLuigi Rizzo struct mbx_delete_nic_rq *fwcmd; 11772f345d8eSLuigi Rizzo struct oce_rq *rq; 11782f345d8eSLuigi Rizzo int i = 0; 11792f345d8eSLuigi Rizzo 11802f345d8eSLuigi Rizzo for_all_rq_queues(sc, rq, i) { 11812f345d8eSLuigi Rizzo if (rq->qstate == QCREATED) { 11822f345d8eSLuigi Rizzo /* Delete rxq in firmware */ 11832f345d8eSLuigi Rizzo 11842f345d8eSLuigi Rizzo bzero(&mbx, sizeof(mbx)); 11852f345d8eSLuigi Rizzo fwcmd = (struct mbx_delete_nic_rq *)&mbx.payload; 11862f345d8eSLuigi Rizzo fwcmd->params.req.rq_id = rq->rq_id; 11872f345d8eSLuigi Rizzo 11882f345d8eSLuigi Rizzo (void)oce_destroy_q(sc, &mbx, 11892f345d8eSLuigi Rizzo sizeof(struct mbx_delete_nic_rq), QTYPE_RQ); 11902f345d8eSLuigi Rizzo 11912f345d8eSLuigi Rizzo rq->qstate = QDELETED; 11922f345d8eSLuigi Rizzo 11932f345d8eSLuigi Rizzo DELAY(1); 11942f345d8eSLuigi Rizzo 11952f345d8eSLuigi Rizzo /* Free posted RX buffers that are not used */ 11962f345d8eSLuigi Rizzo oce_free_posted_rxbuf(rq); 11972f345d8eSLuigi Rizzo 11982f345d8eSLuigi Rizzo } 11992f345d8eSLuigi Rizzo } 12002f345d8eSLuigi Rizzo } 12012f345d8eSLuigi Rizzo 12022f345d8eSLuigi Rizzo 12032f345d8eSLuigi Rizzo 12042f345d8eSLuigi Rizzo int 12052f345d8eSLuigi Rizzo oce_start_rx(POCE_SOFTC sc) 12062f345d8eSLuigi Rizzo { 12072f345d8eSLuigi Rizzo struct oce_rq *rq; 12082f345d8eSLuigi Rizzo int rc = 0, i; 12092f345d8eSLuigi Rizzo 12102f345d8eSLuigi Rizzo for_all_rq_queues(sc, rq, i) { 12112f345d8eSLuigi Rizzo if (rq->qstate == QCREATED) 12122f345d8eSLuigi Rizzo continue; 12132f345d8eSLuigi Rizzo rc = oce_mbox_create_rq(rq); 12142f345d8eSLuigi Rizzo if (rc) 12152f345d8eSLuigi Rizzo goto error; 12162f345d8eSLuigi Rizzo /* reset queue pointers */ 12172f345d8eSLuigi Rizzo rq->qstate = QCREATED; 12182f345d8eSLuigi Rizzo rq->pending = 0; 12192f345d8eSLuigi Rizzo rq->ring->cidx = 0; 12202f345d8eSLuigi Rizzo rq->ring->pidx = 0; 12212f345d8eSLuigi Rizzo rq->packets_in = 0; 12222f345d8eSLuigi Rizzo rq->packets_out = 0; 12232f345d8eSLuigi Rizzo } 12242f345d8eSLuigi Rizzo 12252f345d8eSLuigi Rizzo DELAY(1); 12262f345d8eSLuigi Rizzo 12272f345d8eSLuigi Rizzo /* RSS config */ 1228*291a1934SXin LI if (is_rss_enabled(sc)) { 12292f345d8eSLuigi Rizzo rc = oce_config_nic_rss(sc, (uint8_t) sc->if_id, RSS_ENABLE); 12302f345d8eSLuigi Rizzo if (rc) 12312f345d8eSLuigi Rizzo goto error; 12322f345d8eSLuigi Rizzo 12332f345d8eSLuigi Rizzo } 12342f345d8eSLuigi Rizzo 12352f345d8eSLuigi Rizzo return rc; 12362f345d8eSLuigi Rizzo error: 12372f345d8eSLuigi Rizzo device_printf(sc->dev, "Start RX failed\n"); 12382f345d8eSLuigi Rizzo return rc; 12392f345d8eSLuigi Rizzo 12402f345d8eSLuigi Rizzo } 12412f345d8eSLuigi Rizzo 12422f345d8eSLuigi Rizzo 12432f345d8eSLuigi Rizzo 1244