xref: /freebsd/sys/dev/oce/oce_queue.c (revision 291a1934fa36be527bba60f5d24688687118b29a)
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