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