14d0e5007SSukumar Swaminathan /*
24d0e5007SSukumar Swaminathan  * CDDL HEADER START
34d0e5007SSukumar Swaminathan  *
44d0e5007SSukumar Swaminathan  * The contents of this file are subject to the terms of the
54d0e5007SSukumar Swaminathan  * Common Development and Distribution License (the "License").
64d0e5007SSukumar Swaminathan  * You may not use this file except in compliance with the License.
74d0e5007SSukumar Swaminathan  *
84d0e5007SSukumar Swaminathan  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94d0e5007SSukumar Swaminathan  * or http://www.opensolaris.org/os/licensing.
104d0e5007SSukumar Swaminathan  * See the License for the specific language governing permissions
114d0e5007SSukumar Swaminathan  * and limitations under the License.
124d0e5007SSukumar Swaminathan  *
134d0e5007SSukumar Swaminathan  * When distributing Covered Code, include this CDDL HEADER in each
144d0e5007SSukumar Swaminathan  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154d0e5007SSukumar Swaminathan  * If applicable, add the following below this CDDL HEADER, with the
164d0e5007SSukumar Swaminathan  * fields enclosed by brackets "[]" replaced with your own identifying
174d0e5007SSukumar Swaminathan  * information: Portions Copyright [yyyy] [name of copyright owner]
184d0e5007SSukumar Swaminathan  *
194d0e5007SSukumar Swaminathan  * CDDL HEADER END
204d0e5007SSukumar Swaminathan  */
214d0e5007SSukumar Swaminathan 
22*3abb112fSGarrett D'Amore /* Copyright © 2003-2011 Emulex. All rights reserved.  */
234d0e5007SSukumar Swaminathan 
244d0e5007SSukumar Swaminathan /*
254d0e5007SSukumar Swaminathan  * Source file containing Queue handling functions
264d0e5007SSukumar Swaminathan  *
274d0e5007SSukumar Swaminathan  */
284d0e5007SSukumar Swaminathan 
294d0e5007SSukumar Swaminathan #include <oce_impl.h>
30*3abb112fSGarrett D'Amore extern struct oce_dev *oce_dev_list[];
314d0e5007SSukumar Swaminathan 
324d0e5007SSukumar Swaminathan int oce_destroy_q(struct oce_dev  *oce, struct oce_mbx  *mbx, size_t req_size,
334d0e5007SSukumar Swaminathan     enum qtype  qtype);
348d738d7dSSukumar Swaminathan /* MAil box Queue functions */
358d738d7dSSukumar Swaminathan struct oce_mq *
368d738d7dSSukumar Swaminathan oce_mq_create(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len);
374d0e5007SSukumar Swaminathan 
388d738d7dSSukumar Swaminathan /* event queue handling */
398d738d7dSSukumar Swaminathan struct oce_eq *
408d738d7dSSukumar Swaminathan oce_eq_create(struct oce_dev *dev, uint32_t q_len, uint32_t item_size,
418d738d7dSSukumar Swaminathan     uint32_t eq_delay);
428d738d7dSSukumar Swaminathan 
438d738d7dSSukumar Swaminathan /* completion queue handling */
448d738d7dSSukumar Swaminathan struct oce_cq *
458d738d7dSSukumar Swaminathan oce_cq_create(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len,
468d738d7dSSukumar Swaminathan     uint32_t item_size, boolean_t sol_event, boolean_t is_eventable,
478d738d7dSSukumar Swaminathan     boolean_t nodelay, uint32_t ncoalesce);
488d738d7dSSukumar Swaminathan 
498d738d7dSSukumar Swaminathan 
508d738d7dSSukumar Swaminathan /* Tx  WQ functions */
518d738d7dSSukumar Swaminathan static struct oce_wq *oce_wq_init(struct oce_dev *dev,  uint32_t q_len,
528d738d7dSSukumar Swaminathan     int wq_type);
538d738d7dSSukumar Swaminathan static void oce_wq_fini(struct oce_dev *dev, struct oce_wq *wq);
548d738d7dSSukumar Swaminathan static int oce_wq_create(struct oce_wq *wq, struct oce_eq *eq);
558d738d7dSSukumar Swaminathan static void oce_wq_del(struct oce_dev *dev, struct oce_wq *wq);
568d738d7dSSukumar Swaminathan /* Rx Queue functions */
578d738d7dSSukumar Swaminathan static struct oce_rq *oce_rq_init(struct oce_dev *dev, uint32_t q_len,
588d738d7dSSukumar Swaminathan     uint32_t frag_size, uint32_t mtu,
598d738d7dSSukumar Swaminathan     boolean_t rss);
608d738d7dSSukumar Swaminathan static void oce_rq_fini(struct oce_dev *dev, struct oce_rq *rq);
618d738d7dSSukumar Swaminathan static int oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq);
628d738d7dSSukumar Swaminathan static void oce_rq_del(struct oce_dev *dev, struct oce_rq *rq);
634d0e5007SSukumar Swaminathan 
644d0e5007SSukumar Swaminathan /*
654d0e5007SSukumar Swaminathan  * function to create an event queue
664d0e5007SSukumar Swaminathan  *
674d0e5007SSukumar Swaminathan  * dev - software handle to the device
684d0e5007SSukumar Swaminathan  * eqcfg - pointer to a config structure containg the eq parameters
694d0e5007SSukumar Swaminathan  *
704d0e5007SSukumar Swaminathan  * return pointer to EQ; NULL on failure
714d0e5007SSukumar Swaminathan  */
724d0e5007SSukumar Swaminathan struct oce_eq *
oce_eq_create(struct oce_dev * dev,uint32_t q_len,uint32_t item_size,uint32_t eq_delay)734d0e5007SSukumar Swaminathan oce_eq_create(struct oce_dev *dev, uint32_t q_len, uint32_t item_size,
744d0e5007SSukumar Swaminathan     uint32_t eq_delay)
754d0e5007SSukumar Swaminathan {
764d0e5007SSukumar Swaminathan 	struct oce_eq *eq;
774d0e5007SSukumar Swaminathan 	struct oce_mbx mbx;
784d0e5007SSukumar Swaminathan 	struct mbx_create_common_eq *fwcmd;
794d0e5007SSukumar Swaminathan 	int ret = 0;
804d0e5007SSukumar Swaminathan 
814d0e5007SSukumar Swaminathan 	/* allocate an eq */
824d0e5007SSukumar Swaminathan 	eq = kmem_zalloc(sizeof (struct oce_eq), KM_NOSLEEP);
838d738d7dSSukumar Swaminathan 
844d0e5007SSukumar Swaminathan 	if (eq == NULL) {
854d0e5007SSukumar Swaminathan 		return (NULL);
864d0e5007SSukumar Swaminathan 	}
874d0e5007SSukumar Swaminathan 
888d738d7dSSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
898d738d7dSSukumar Swaminathan 	/* allocate mbx */
908d738d7dSSukumar Swaminathan 	fwcmd = (struct mbx_create_common_eq *)&mbx.payload;
918d738d7dSSukumar Swaminathan 
924d0e5007SSukumar Swaminathan 	eq->ring = create_ring_buffer(dev, q_len,
934d0e5007SSukumar Swaminathan 	    item_size, DDI_DMA_CONSISTENT);
948d738d7dSSukumar Swaminathan 
954d0e5007SSukumar Swaminathan 	if (eq->ring == NULL) {
964d0e5007SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG,
97*3abb112fSGarrett D'Amore 		    "EQ ring alloc failed:0x%p", (void *)eq->ring);
984d0e5007SSukumar Swaminathan 		kmem_free(eq, sizeof (struct oce_eq));
994d0e5007SSukumar Swaminathan 		return (NULL);
1004d0e5007SSukumar Swaminathan 	}
1014d0e5007SSukumar Swaminathan 
1024d0e5007SSukumar Swaminathan 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1034d0e5007SSukumar Swaminathan 	    MBX_SUBSYSTEM_COMMON,
1044d0e5007SSukumar Swaminathan 	    OPCODE_CREATE_COMMON_EQ, MBX_TIMEOUT_SEC,
1054d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_create_common_eq));
1064d0e5007SSukumar Swaminathan 
1074d0e5007SSukumar Swaminathan 	fwcmd->params.req.num_pages = eq->ring->dbuf->num_pages;
1084d0e5007SSukumar Swaminathan 	oce_page_list(eq->ring->dbuf, &fwcmd->params.req.pages[0],
1094d0e5007SSukumar Swaminathan 	    eq->ring->dbuf->num_pages);
1104d0e5007SSukumar Swaminathan 
1114d0e5007SSukumar Swaminathan 	/* dw 0 */
1124d0e5007SSukumar Swaminathan 	fwcmd->params.req.eq_ctx.size = (item_size == 4) ? 0 : 1;
1134d0e5007SSukumar Swaminathan 	fwcmd->params.req.eq_ctx.valid = 1;
1144d0e5007SSukumar Swaminathan 	/* dw 1 */
1154d0e5007SSukumar Swaminathan 	fwcmd->params.req.eq_ctx.armed = 0;
1164d0e5007SSukumar Swaminathan 	fwcmd->params.req.eq_ctx.pd = 0;
1174d0e5007SSukumar Swaminathan 	fwcmd->params.req.eq_ctx.count = OCE_LOG2(q_len/256);
1184d0e5007SSukumar Swaminathan 
1194d0e5007SSukumar Swaminathan 	/* dw 2 */
1204d0e5007SSukumar Swaminathan 	fwcmd->params.req.eq_ctx.function = dev->fn;
1214d0e5007SSukumar Swaminathan 	fwcmd->params.req.eq_ctx.nodelay  = 0;
1224d0e5007SSukumar Swaminathan 	fwcmd->params.req.eq_ctx.phase = 0;
1234d0e5007SSukumar Swaminathan 	/* todo: calculate multiplier from max min and cur */
1244d0e5007SSukumar Swaminathan 	fwcmd->params.req.eq_ctx.delay_mult = eq_delay;
1254d0e5007SSukumar Swaminathan 
1264d0e5007SSukumar Swaminathan 	/* fill rest of mbx */
1274d0e5007SSukumar Swaminathan 	mbx.u0.s.embedded = 1;
1284d0e5007SSukumar Swaminathan 	mbx.payload_length = sizeof (struct mbx_create_common_eq);
1294d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1304d0e5007SSukumar Swaminathan 
1314d0e5007SSukumar Swaminathan 	/* now post the command */
1324d0e5007SSukumar Swaminathan 	ret = oce_mbox_post(dev, &mbx, NULL);
1334d0e5007SSukumar Swaminathan 
1344d0e5007SSukumar Swaminathan 	if (ret != 0) {
135*3abb112fSGarrett D'Amore 		oce_log(dev, CE_WARN, MOD_CONFIG, "EQ create failed: %d", ret);
1364d0e5007SSukumar Swaminathan 		destroy_ring_buffer(dev, eq->ring);
1374d0e5007SSukumar Swaminathan 		kmem_free(eq, sizeof (struct oce_eq));
1384d0e5007SSukumar Swaminathan 		return (NULL);
1394d0e5007SSukumar Swaminathan 	}
1404d0e5007SSukumar Swaminathan 
1414d0e5007SSukumar Swaminathan 	/* interpret the response */
1424d0e5007SSukumar Swaminathan 	eq->eq_id = LE_16(fwcmd->params.rsp.eq_id);
1434d0e5007SSukumar Swaminathan 	eq->eq_cfg.q_len = q_len;
1444d0e5007SSukumar Swaminathan 	eq->eq_cfg.item_size = item_size;
1454d0e5007SSukumar Swaminathan 	eq->eq_cfg.cur_eqd = (uint8_t)eq_delay;
1464d0e5007SSukumar Swaminathan 	eq->parent = (void *)dev;
1474d0e5007SSukumar Swaminathan 	atomic_inc_32(&dev->neqs);
1484d0e5007SSukumar Swaminathan 	oce_log(dev, CE_NOTE, MOD_CONFIG,
1494d0e5007SSukumar Swaminathan 	    "EQ created, eq=0x%p eq_id=0x%x", (void *)eq, eq->eq_id);
1508d738d7dSSukumar Swaminathan 	/* Save the eq pointer */
1514d0e5007SSukumar Swaminathan 	return (eq);
1524d0e5007SSukumar Swaminathan } /* oce_eq_create */
1534d0e5007SSukumar Swaminathan 
1544d0e5007SSukumar Swaminathan /*
1554d0e5007SSukumar Swaminathan  * function to delete an event queue
1564d0e5007SSukumar Swaminathan  *
1574d0e5007SSukumar Swaminathan  * dev - software handle to the device
1584d0e5007SSukumar Swaminathan  * eq - handle to the eq to be deleted
1594d0e5007SSukumar Swaminathan  *
1604d0e5007SSukumar Swaminathan  * return 0=>success, failure otherwise
1614d0e5007SSukumar Swaminathan  */
1628d738d7dSSukumar Swaminathan void
oce_eq_del(struct oce_dev * dev,struct oce_eq * eq)1634d0e5007SSukumar Swaminathan oce_eq_del(struct oce_dev *dev, struct oce_eq *eq)
1644d0e5007SSukumar Swaminathan {
1658d738d7dSSukumar Swaminathan 	struct oce_mbx mbx;
1668d738d7dSSukumar Swaminathan 	struct mbx_destroy_common_eq *fwcmd;
1678d738d7dSSukumar Swaminathan 
1688d738d7dSSukumar Swaminathan 	/* drain the residual events */
1698d738d7dSSukumar Swaminathan 	oce_drain_eq(eq);
1708d738d7dSSukumar Swaminathan 
1714d0e5007SSukumar Swaminathan 	/* destroy the ring */
1724d0e5007SSukumar Swaminathan 	destroy_ring_buffer(dev, eq->ring);
1734d0e5007SSukumar Swaminathan 	eq->ring = NULL;
1744d0e5007SSukumar Swaminathan 
1758d738d7dSSukumar Swaminathan 	/* send a command to delete the EQ */
1768d738d7dSSukumar Swaminathan 	fwcmd = (struct mbx_destroy_common_eq *)&mbx.payload;
1778d738d7dSSukumar Swaminathan 	fwcmd->params.req.id = eq->eq_id;
1788d738d7dSSukumar Swaminathan 	(void) oce_destroy_q(dev, &mbx,
1798d738d7dSSukumar Swaminathan 	    sizeof (struct mbx_destroy_common_eq),
1808d738d7dSSukumar Swaminathan 	    QTYPE_EQ);
1814d0e5007SSukumar Swaminathan 	kmem_free(eq, sizeof (struct oce_eq));
1824d0e5007SSukumar Swaminathan 	atomic_dec_32(&dev->neqs);
1838d738d7dSSukumar Swaminathan }
1844d0e5007SSukumar Swaminathan 
1854d0e5007SSukumar Swaminathan /*
1864d0e5007SSukumar Swaminathan  * function to create a completion queue
1874d0e5007SSukumar Swaminathan  *
1884d0e5007SSukumar Swaminathan  * dev - software handle to the device
1894d0e5007SSukumar Swaminathan  * eq - optional eq to be associated with to the cq
1904d0e5007SSukumar Swaminathan  * cqcfg - configuration for this queue
1914d0e5007SSukumar Swaminathan  *
1924d0e5007SSukumar Swaminathan  * return pointer to the cq created. NULL on failure
1934d0e5007SSukumar Swaminathan  */
1944d0e5007SSukumar Swaminathan struct oce_cq *
oce_cq_create(struct oce_dev * dev,struct oce_eq * eq,uint32_t q_len,uint32_t item_size,boolean_t sol_event,boolean_t is_eventable,boolean_t nodelay,uint32_t ncoalesce)1954d0e5007SSukumar Swaminathan oce_cq_create(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len,
1964d0e5007SSukumar Swaminathan     uint32_t item_size, boolean_t sol_event, boolean_t is_eventable,
1974d0e5007SSukumar Swaminathan     boolean_t nodelay, uint32_t ncoalesce)
1984d0e5007SSukumar Swaminathan {
1994d0e5007SSukumar Swaminathan 	struct oce_cq *cq = NULL;
2004d0e5007SSukumar Swaminathan 	struct oce_mbx mbx;
2014d0e5007SSukumar Swaminathan 	struct mbx_create_common_cq *fwcmd;
2024d0e5007SSukumar Swaminathan 	int ret = 0;
2034d0e5007SSukumar Swaminathan 
2044d0e5007SSukumar Swaminathan 	/* create cq */
2054d0e5007SSukumar Swaminathan 	cq = kmem_zalloc(sizeof (struct oce_cq), KM_NOSLEEP);
2064d0e5007SSukumar Swaminathan 	if (cq == NULL) {
2074d0e5007SSukumar Swaminathan 		oce_log(dev, CE_NOTE, MOD_CONFIG, "%s",
2084d0e5007SSukumar Swaminathan 		    "CQ allocation failed");
2094d0e5007SSukumar Swaminathan 		return (NULL);
2104d0e5007SSukumar Swaminathan 	}
2114d0e5007SSukumar Swaminathan 
2124d0e5007SSukumar Swaminathan 	/* create the ring buffer for this queue */
2134d0e5007SSukumar Swaminathan 	cq->ring = create_ring_buffer(dev, q_len,
2144d0e5007SSukumar Swaminathan 	    item_size, DDI_DMA_CONSISTENT);
2154d0e5007SSukumar Swaminathan 	if (cq->ring == NULL) {
2164d0e5007SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG,
2174d0e5007SSukumar Swaminathan 		    "CQ ring alloc failed:0x%p",
2184d0e5007SSukumar Swaminathan 		    (void *)cq->ring);
2194d0e5007SSukumar Swaminathan 		kmem_free(cq, sizeof (struct oce_cq));
2204d0e5007SSukumar Swaminathan 		return (NULL);
2214d0e5007SSukumar Swaminathan 	}
2228d738d7dSSukumar Swaminathan 	/* initialize mailbox */
2238d738d7dSSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
2244d0e5007SSukumar Swaminathan 	fwcmd = (struct mbx_create_common_cq *)&mbx.payload;
2254d0e5007SSukumar Swaminathan 
2264d0e5007SSukumar Swaminathan 	/* fill the command header */
2274d0e5007SSukumar Swaminathan 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
2284d0e5007SSukumar Swaminathan 	    MBX_SUBSYSTEM_COMMON,
2294d0e5007SSukumar Swaminathan 	    OPCODE_CREATE_COMMON_CQ, MBX_TIMEOUT_SEC,
2304d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_create_common_cq));
2314d0e5007SSukumar Swaminathan 
2324d0e5007SSukumar Swaminathan 	/* fill command context */
2334d0e5007SSukumar Swaminathan 	/* dw0 */
2344d0e5007SSukumar Swaminathan 	fwcmd->params.req.cq_ctx.eventable = is_eventable;
2354d0e5007SSukumar Swaminathan 	fwcmd->params.req.cq_ctx.sol_event = sol_event;
2364d0e5007SSukumar Swaminathan 	fwcmd->params.req.cq_ctx.valid = 1;
2374d0e5007SSukumar Swaminathan 	fwcmd->params.req.cq_ctx.count = OCE_LOG2(q_len/256);
2384d0e5007SSukumar Swaminathan 	fwcmd->params.req.cq_ctx.nodelay = nodelay;
2394d0e5007SSukumar Swaminathan 	fwcmd->params.req.cq_ctx.coalesce_wm = ncoalesce;
2404d0e5007SSukumar Swaminathan 
2414d0e5007SSukumar Swaminathan 	/* dw1 */
2428d738d7dSSukumar Swaminathan 	fwcmd->params.req.cq_ctx.armed = B_FALSE;
2434d0e5007SSukumar Swaminathan 	fwcmd->params.req.cq_ctx.eq_id = eq->eq_id;
2444d0e5007SSukumar Swaminathan 	fwcmd->params.req.cq_ctx.pd = 0;
2454d0e5007SSukumar Swaminathan 	/* dw2 */
2464d0e5007SSukumar Swaminathan 	fwcmd->params.req.cq_ctx.function = dev->fn;
2474d0e5007SSukumar Swaminathan 
2484d0e5007SSukumar Swaminathan 	/* fill the rest of the command */
2494d0e5007SSukumar Swaminathan 	fwcmd->params.req.num_pages = cq->ring->dbuf->num_pages;
2504d0e5007SSukumar Swaminathan 	oce_page_list(cq->ring->dbuf, &fwcmd->params.req.pages[0],
2514d0e5007SSukumar Swaminathan 	    cq->ring->dbuf->num_pages);
2524d0e5007SSukumar Swaminathan 
2534d0e5007SSukumar Swaminathan 	/* fill rest of mbx */
2544d0e5007SSukumar Swaminathan 	mbx.u0.s.embedded = 1;
2554d0e5007SSukumar Swaminathan 	mbx.payload_length = sizeof (struct mbx_create_common_cq);
2564d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
2574d0e5007SSukumar Swaminathan 
2584d0e5007SSukumar Swaminathan 	/* now send the mail box */
2594d0e5007SSukumar Swaminathan 	ret = oce_mbox_post(dev, &mbx, NULL);
2604d0e5007SSukumar Swaminathan 
2614d0e5007SSukumar Swaminathan 	if (ret != 0) {
2624d0e5007SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG,
2634d0e5007SSukumar Swaminathan 		    "CQ create failed: 0x%x", ret);
2644d0e5007SSukumar Swaminathan 		destroy_ring_buffer(dev, cq->ring);
2654d0e5007SSukumar Swaminathan 		kmem_free(cq, sizeof (struct oce_cq));
2664d0e5007SSukumar Swaminathan 		return (NULL);
2674d0e5007SSukumar Swaminathan 	}
2684d0e5007SSukumar Swaminathan 
2694d0e5007SSukumar Swaminathan 	cq->parent = dev;
2704d0e5007SSukumar Swaminathan 	cq->eq = eq; /* eq array index */
2714d0e5007SSukumar Swaminathan 	cq->cq_cfg.q_len = q_len;
2724d0e5007SSukumar Swaminathan 	cq->cq_cfg.item_size = item_size;
2734d0e5007SSukumar Swaminathan 	cq->cq_cfg.sol_eventable = (uint8_t)sol_event;
2744d0e5007SSukumar Swaminathan 	cq->cq_cfg.nodelay = (uint8_t)nodelay;
2754d0e5007SSukumar Swaminathan 	/* interpret the response */
2764d0e5007SSukumar Swaminathan 	cq->cq_id = LE_16(fwcmd->params.rsp.cq_id);
2775b9d3151SSukumar Swaminathan 	dev->cq[cq->cq_id % OCE_MAX_CQ] = cq;
2784d0e5007SSukumar Swaminathan 	atomic_inc_32(&eq->ref_count);
2794d0e5007SSukumar Swaminathan 	return (cq);
2804d0e5007SSukumar Swaminathan } /* oce_cq_create */
2814d0e5007SSukumar Swaminathan 
2824d0e5007SSukumar Swaminathan /*
2834d0e5007SSukumar Swaminathan  * function to delete a completion queue
2844d0e5007SSukumar Swaminathan  *
2854d0e5007SSukumar Swaminathan  * dev - software handle to the device
2864d0e5007SSukumar Swaminathan  * cq - handle to the CQ to delete
2874d0e5007SSukumar Swaminathan  *
2888d738d7dSSukumar Swaminathan  * return none
2894d0e5007SSukumar Swaminathan  */
2908d738d7dSSukumar Swaminathan static void
oce_cq_del(struct oce_dev * dev,struct oce_cq * cq)2914d0e5007SSukumar Swaminathan oce_cq_del(struct oce_dev *dev, struct oce_cq *cq)
2924d0e5007SSukumar Swaminathan {
2938d738d7dSSukumar Swaminathan 	struct oce_mbx mbx;
2948d738d7dSSukumar Swaminathan 	struct mbx_destroy_common_cq *fwcmd;
2958d738d7dSSukumar Swaminathan 
2964d0e5007SSukumar Swaminathan 	/* destroy the ring */
2974d0e5007SSukumar Swaminathan 	destroy_ring_buffer(dev, cq->ring);
2984d0e5007SSukumar Swaminathan 	cq->ring = NULL;
2994d0e5007SSukumar Swaminathan 
3008d738d7dSSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
3018d738d7dSSukumar Swaminathan 	/* send a command to delete the CQ */
3028d738d7dSSukumar Swaminathan 	fwcmd = (struct mbx_destroy_common_cq *)&mbx.payload;
3038d738d7dSSukumar Swaminathan 	fwcmd->params.req.id = cq->cq_id;
3048d738d7dSSukumar Swaminathan 	(void) oce_destroy_q(dev, &mbx,
3058d738d7dSSukumar Swaminathan 	    sizeof (struct mbx_destroy_common_cq),
3068d738d7dSSukumar Swaminathan 	    QTYPE_CQ);
3078d738d7dSSukumar Swaminathan 
3088d738d7dSSukumar Swaminathan 	/* Reset the handler */
3098d738d7dSSukumar Swaminathan 	cq->cq_handler = NULL;
3105b9d3151SSukumar Swaminathan 	dev->cq[cq->cq_id % OCE_MAX_CQ] = NULL;
3114d0e5007SSukumar Swaminathan 	atomic_dec_32(&cq->eq->ref_count);
3124d0e5007SSukumar Swaminathan 	mutex_destroy(&cq->lock);
3134d0e5007SSukumar Swaminathan 
3144d0e5007SSukumar Swaminathan 	/* release the eq */
3154d0e5007SSukumar Swaminathan 	kmem_free(cq, sizeof (struct oce_cq));
3164d0e5007SSukumar Swaminathan } /* oce_cq_del */
3174d0e5007SSukumar Swaminathan 
3184d0e5007SSukumar Swaminathan /*
3194d0e5007SSukumar Swaminathan  * function to create an MQ
3204d0e5007SSukumar Swaminathan  *
3214d0e5007SSukumar Swaminathan  * dev - software handle to the device
3224d0e5007SSukumar Swaminathan  * eq - the EQ to associate with the MQ for event notification
3234d0e5007SSukumar Swaminathan  * q_len - the number of entries to create in the MQ
3244d0e5007SSukumar Swaminathan  *
3254d0e5007SSukumar Swaminathan  * return pointer to the created MQ, failure otherwise
3264d0e5007SSukumar Swaminathan  */
3274d0e5007SSukumar Swaminathan struct oce_mq *
oce_mq_create(struct oce_dev * dev,struct oce_eq * eq,uint32_t q_len)3284d0e5007SSukumar Swaminathan oce_mq_create(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len)
3294d0e5007SSukumar Swaminathan {
3304d0e5007SSukumar Swaminathan 	struct oce_mbx mbx;
3314d0e5007SSukumar Swaminathan 	struct mbx_create_common_mq *fwcmd;
3324d0e5007SSukumar Swaminathan 	struct oce_mq *mq = NULL;
3334d0e5007SSukumar Swaminathan 	int ret = 0;
3344d0e5007SSukumar Swaminathan 	struct oce_cq  *cq;
3354d0e5007SSukumar Swaminathan 
3364d0e5007SSukumar Swaminathan 	/* Create the Completion Q */
3374d0e5007SSukumar Swaminathan 	cq = oce_cq_create(dev, eq, CQ_LEN_256,
3384d0e5007SSukumar Swaminathan 	    sizeof (struct oce_mq_cqe),
3394d0e5007SSukumar Swaminathan 	    B_FALSE, B_TRUE, B_TRUE, 0);
3404d0e5007SSukumar Swaminathan 	if (cq == NULL) {
3414d0e5007SSukumar Swaminathan 		return (NULL);
3424d0e5007SSukumar Swaminathan 	}
3438d738d7dSSukumar Swaminathan 
3448d738d7dSSukumar Swaminathan 
3454d0e5007SSukumar Swaminathan 	/* allocate the mq */
3464d0e5007SSukumar Swaminathan 	mq = kmem_zalloc(sizeof (struct oce_mq), KM_NOSLEEP);
3478d738d7dSSukumar Swaminathan 
3484d0e5007SSukumar Swaminathan 	if (mq == NULL) {
3498d738d7dSSukumar Swaminathan 		goto mq_alloc_fail;
3504d0e5007SSukumar Swaminathan 	}
3514d0e5007SSukumar Swaminathan 
3528d738d7dSSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
3538d738d7dSSukumar Swaminathan 	/* allocate mbx */
3548d738d7dSSukumar Swaminathan 	fwcmd = (struct mbx_create_common_mq *)&mbx.payload;
3558d738d7dSSukumar Swaminathan 
3564d0e5007SSukumar Swaminathan 	/* create the ring buffer for this queue */
3574d0e5007SSukumar Swaminathan 	mq->ring = create_ring_buffer(dev, q_len,
3585b9d3151SSukumar Swaminathan 	    sizeof (struct oce_mbx), DDI_DMA_CONSISTENT | DDI_DMA_RDWR);
3594d0e5007SSukumar Swaminathan 	if (mq->ring == NULL) {
3604d0e5007SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG,
3614d0e5007SSukumar Swaminathan 		    "MQ ring alloc failed:0x%p",
3624d0e5007SSukumar Swaminathan 		    (void *)mq->ring);
3634d0e5007SSukumar Swaminathan 		goto mq_ring_alloc;
3644d0e5007SSukumar Swaminathan 	}
3654d0e5007SSukumar Swaminathan 
3664d0e5007SSukumar Swaminathan 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
3674d0e5007SSukumar Swaminathan 	    MBX_SUBSYSTEM_COMMON,
3684d0e5007SSukumar Swaminathan 	    OPCODE_CREATE_COMMON_MQ, MBX_TIMEOUT_SEC,
3694d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_create_common_mq));
3704d0e5007SSukumar Swaminathan 
3714d0e5007SSukumar Swaminathan 	fwcmd->params.req.num_pages = mq->ring->dbuf->num_pages;
3724d0e5007SSukumar Swaminathan 	oce_page_list(mq->ring->dbuf, fwcmd->params.req.pages,
3734d0e5007SSukumar Swaminathan 	    mq->ring->dbuf->num_pages);
3744d0e5007SSukumar Swaminathan 	fwcmd->params.req.context.u0.s.cq_id = cq->cq_id;
3754d0e5007SSukumar Swaminathan 	fwcmd->params.req.context.u0.s.ring_size =
3764d0e5007SSukumar Swaminathan 	    OCE_LOG2(q_len) + 1;
3774d0e5007SSukumar Swaminathan 	fwcmd->params.req.context.u0.s.valid = 1;
3784d0e5007SSukumar Swaminathan 	fwcmd->params.req.context.u0.s.fid = dev->fn;
3794d0e5007SSukumar Swaminathan 
3804d0e5007SSukumar Swaminathan 	/* fill rest of mbx */
3814d0e5007SSukumar Swaminathan 	mbx.u0.s.embedded = 1;
3824d0e5007SSukumar Swaminathan 	mbx.payload_length = sizeof (struct mbx_create_common_mq);
3834d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
3844d0e5007SSukumar Swaminathan 
3854d0e5007SSukumar Swaminathan 	/* now send the mail box */
3864d0e5007SSukumar Swaminathan 	ret = oce_mbox_post(dev, &mbx, NULL);
3874d0e5007SSukumar Swaminathan 	if (ret != DDI_SUCCESS) {
3884d0e5007SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG,
3894d0e5007SSukumar Swaminathan 		    "MQ create failed: 0x%x", ret);
3904d0e5007SSukumar Swaminathan 		goto mq_fail;
3914d0e5007SSukumar Swaminathan 	}
3924d0e5007SSukumar Swaminathan 
3934d0e5007SSukumar Swaminathan 	/* interpret the response */
3944d0e5007SSukumar Swaminathan 	mq->mq_id = LE_16(fwcmd->params.rsp.mq_id);
3954d0e5007SSukumar Swaminathan 	mq->cq = cq;
3964d0e5007SSukumar Swaminathan 	mq->cfg.q_len = (uint8_t)q_len;
3974d0e5007SSukumar Swaminathan 	mq->cfg.eqd = 0;
3984d0e5007SSukumar Swaminathan 
3994d0e5007SSukumar Swaminathan 	/* fill rest of the mq */
4004d0e5007SSukumar Swaminathan 	mq->parent = dev;
4014d0e5007SSukumar Swaminathan 
4024d0e5007SSukumar Swaminathan 	/* set the MQCQ handlers */
4034d0e5007SSukumar Swaminathan 	cq->cq_handler = oce_drain_mq_cq;
4044d0e5007SSukumar Swaminathan 	cq->cb_arg = (void *)mq;
4058d738d7dSSukumar Swaminathan 	mutex_init(&mq->lock, NULL, MUTEX_DRIVER,
4068d738d7dSSukumar Swaminathan 	    DDI_INTR_PRI(dev->intr_pri));
4074d0e5007SSukumar Swaminathan 	return (mq);
4084d0e5007SSukumar Swaminathan 
4094d0e5007SSukumar Swaminathan mq_fail:
4104d0e5007SSukumar Swaminathan 	destroy_ring_buffer(dev, mq->ring);
4114d0e5007SSukumar Swaminathan mq_ring_alloc:
4124d0e5007SSukumar Swaminathan 	kmem_free(mq, sizeof (struct oce_mq));
4138d738d7dSSukumar Swaminathan mq_alloc_fail:
4148d738d7dSSukumar Swaminathan 	oce_cq_del(dev, cq);
4154d0e5007SSukumar Swaminathan 	return (NULL);
4164d0e5007SSukumar Swaminathan } /* oce_mq_create */
4174d0e5007SSukumar Swaminathan 
4184d0e5007SSukumar Swaminathan /*
4194d0e5007SSukumar Swaminathan  * function to delete an MQ
4204d0e5007SSukumar Swaminathan  *
4214d0e5007SSukumar Swaminathan  * dev - software handle to the device
4224d0e5007SSukumar Swaminathan  * mq - pointer to the MQ to delete
4234d0e5007SSukumar Swaminathan  *
4248d738d7dSSukumar Swaminathan  * return none
4254d0e5007SSukumar Swaminathan  */
4268d738d7dSSukumar Swaminathan static void
oce_mq_del(struct oce_dev * dev,struct oce_mq * mq)4274d0e5007SSukumar Swaminathan oce_mq_del(struct oce_dev *dev, struct oce_mq *mq)
4284d0e5007SSukumar Swaminathan {
4298d738d7dSSukumar Swaminathan 	struct oce_mbx mbx;
4308d738d7dSSukumar Swaminathan 	struct mbx_destroy_common_mq *fwcmd;
4314d0e5007SSukumar Swaminathan 
4324d0e5007SSukumar Swaminathan 	/* destroy the ring */
4334d0e5007SSukumar Swaminathan 	destroy_ring_buffer(dev, mq->ring);
4344d0e5007SSukumar Swaminathan 	mq->ring = NULL;
4358d738d7dSSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
4368d738d7dSSukumar Swaminathan 	fwcmd = (struct mbx_destroy_common_mq *)&mbx.payload;
4378d738d7dSSukumar Swaminathan 	fwcmd->params.req.id = mq->mq_id;
4388d738d7dSSukumar Swaminathan 	(void) oce_destroy_q(dev, &mbx,
4398d738d7dSSukumar Swaminathan 	    sizeof (struct mbx_destroy_common_mq),
4408d738d7dSSukumar Swaminathan 	    QTYPE_MQ);
4418d738d7dSSukumar Swaminathan 	oce_cq_del(dev, mq->cq);
4428d738d7dSSukumar Swaminathan 	mq->cq = NULL;
4438d738d7dSSukumar Swaminathan 	mutex_destroy(&mq->lock);
4444d0e5007SSukumar Swaminathan 	kmem_free(mq, sizeof (struct oce_mq));
4454d0e5007SSukumar Swaminathan } /* oce_mq_del */
4464d0e5007SSukumar Swaminathan 
4474d0e5007SSukumar Swaminathan /*
4484d0e5007SSukumar Swaminathan  * function to create a WQ for NIC Tx
4494d0e5007SSukumar Swaminathan  *
4504d0e5007SSukumar Swaminathan  * dev - software handle to the device
4514d0e5007SSukumar Swaminathan  * wqcfg - configuration structure providing WQ config parameters
4524d0e5007SSukumar Swaminathan  *
4534d0e5007SSukumar Swaminathan  * return pointer to the WQ created. NULL on failure
4544d0e5007SSukumar Swaminathan  */
4558d738d7dSSukumar Swaminathan static struct oce_wq *
oce_wq_init(struct oce_dev * dev,uint32_t q_len,int wq_type)4568d738d7dSSukumar Swaminathan oce_wq_init(struct oce_dev *dev,  uint32_t q_len, int wq_type)
4574d0e5007SSukumar Swaminathan {
4584d0e5007SSukumar Swaminathan 	struct oce_wq *wq;
4594d0e5007SSukumar Swaminathan 	char str[MAX_POOL_NAME];
4604d0e5007SSukumar Swaminathan 	int ret;
4615b9d3151SSukumar Swaminathan 	static int wq_id = 0;
4624d0e5007SSukumar Swaminathan 
4634d0e5007SSukumar Swaminathan 	ASSERT(dev != NULL);
4644d0e5007SSukumar Swaminathan 	/* q_len must be min 256 and max 2k */
4654d0e5007SSukumar Swaminathan 	if (q_len < 256 || q_len > 2048) {
4664d0e5007SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG,
4674d0e5007SSukumar Swaminathan 		    "Invalid q length. Must be "
4684d0e5007SSukumar Swaminathan 		    "[256, 2000]: 0x%x", q_len);
4694d0e5007SSukumar Swaminathan 		return (NULL);
4704d0e5007SSukumar Swaminathan 	}
4714d0e5007SSukumar Swaminathan 
4724d0e5007SSukumar Swaminathan 	/* allocate wq */
4734d0e5007SSukumar Swaminathan 	wq = kmem_zalloc(sizeof (struct oce_wq), KM_NOSLEEP);
4744d0e5007SSukumar Swaminathan 	if (wq == NULL) {
4754d0e5007SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
4764d0e5007SSukumar Swaminathan 		    "WQ allocation failed");
47712d61dabSSukumar Swaminathan 		return (NULL);
4784d0e5007SSukumar Swaminathan 	}
4794d0e5007SSukumar Swaminathan 
4804d0e5007SSukumar Swaminathan 	/* Set the wq config */
4814d0e5007SSukumar Swaminathan 	wq->cfg.q_len = q_len;
4824d0e5007SSukumar Swaminathan 	wq->cfg.wq_type = (uint8_t)wq_type;
4834d0e5007SSukumar Swaminathan 	wq->cfg.eqd = OCE_DEFAULT_WQ_EQD;
4844d0e5007SSukumar Swaminathan 	wq->cfg.nbufs = 2 * wq->cfg.q_len;
4854d0e5007SSukumar Swaminathan 	wq->cfg.nhdl = 2 * wq->cfg.q_len;
4865b9d3151SSukumar Swaminathan 	wq->cfg.buf_size = dev->tx_bcopy_limit;
4874d0e5007SSukumar Swaminathan 
4884d0e5007SSukumar Swaminathan 	/* assign parent */
4894d0e5007SSukumar Swaminathan 	wq->parent = (void *)dev;
4904d0e5007SSukumar Swaminathan 
4914d0e5007SSukumar Swaminathan 	/* Create the WQ Buffer pool */
4925b9d3151SSukumar Swaminathan 	ret  = oce_wqb_cache_create(wq, wq->cfg.buf_size);
4934d0e5007SSukumar Swaminathan 	if (ret != DDI_SUCCESS) {
4944d0e5007SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
4954d0e5007SSukumar Swaminathan 		    "WQ Buffer Pool create failed ");
4964d0e5007SSukumar Swaminathan 		goto wqb_fail;
4974d0e5007SSukumar Swaminathan 	}
4984d0e5007SSukumar Swaminathan 
4994d0e5007SSukumar Swaminathan 	/* Create a pool of memory handles */
5004d0e5007SSukumar Swaminathan 	ret = oce_wqm_cache_create(wq);
5014d0e5007SSukumar Swaminathan 	if (ret != DDI_SUCCESS) {
5024d0e5007SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
5034d0e5007SSukumar Swaminathan 		    "WQ MAP Handles Pool create failed ");
5044d0e5007SSukumar Swaminathan 		goto wqm_fail;
5054d0e5007SSukumar Swaminathan 	}
5064d0e5007SSukumar Swaminathan 
5075b9d3151SSukumar Swaminathan 	(void) snprintf(str, MAX_POOL_NAME, "%s%d%s%d", "oce_wqed_",
5085b9d3151SSukumar Swaminathan 	    dev->dev_id, "_", wq_id++);
5094d0e5007SSukumar Swaminathan 	wq->wqed_cache = kmem_cache_create(str, sizeof (oce_wqe_desc_t),
5105b9d3151SSukumar Swaminathan 	    0, NULL, NULL, NULL, NULL, NULL, 0);
5114d0e5007SSukumar Swaminathan 	if (wq->wqed_cache == NULL) {
5124d0e5007SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
5134d0e5007SSukumar Swaminathan 		    "WQ Packet Desc Pool create failed ");
5144d0e5007SSukumar Swaminathan 		goto wqed_fail;
5154d0e5007SSukumar Swaminathan 	}
5164d0e5007SSukumar Swaminathan 
5174d0e5007SSukumar Swaminathan 	/* create the ring buffer */
5184d0e5007SSukumar Swaminathan 	wq->ring = create_ring_buffer(dev, q_len,
5195b9d3151SSukumar Swaminathan 	    NIC_WQE_SIZE, DDI_DMA_CONSISTENT | DDI_DMA_RDWR);
5204d0e5007SSukumar Swaminathan 	if (wq->ring == NULL) {
5214d0e5007SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
5224d0e5007SSukumar Swaminathan 		    "Failed to create WQ ring ");
5234d0e5007SSukumar Swaminathan 		goto wq_ringfail;
5244d0e5007SSukumar Swaminathan 	}
5254d0e5007SSukumar Swaminathan 
5268d738d7dSSukumar Swaminathan 	/* Initialize WQ lock */
5278d738d7dSSukumar Swaminathan 	mutex_init(&wq->tx_lock, NULL, MUTEX_DRIVER,
5288d738d7dSSukumar Swaminathan 	    DDI_INTR_PRI(dev->intr_pri));
5298d738d7dSSukumar Swaminathan 	/* Initialize WQ lock */
5308d738d7dSSukumar Swaminathan 	mutex_init(&wq->txc_lock, NULL, MUTEX_DRIVER,
5318d738d7dSSukumar Swaminathan 	    DDI_INTR_PRI(dev->intr_pri));
5328d738d7dSSukumar Swaminathan 	atomic_inc_32(&dev->nwqs);
5338d738d7dSSukumar Swaminathan 
5348d738d7dSSukumar Swaminathan 	OCE_LIST_CREATE(&wq->wqe_desc_list, DDI_INTR_PRI(dev->intr_pri));
5358d738d7dSSukumar Swaminathan 	return (wq);
5368d738d7dSSukumar Swaminathan 
5378d738d7dSSukumar Swaminathan wqcq_fail:
5388d738d7dSSukumar Swaminathan 	destroy_ring_buffer(dev, wq->ring);
5398d738d7dSSukumar Swaminathan wq_ringfail:
5408d738d7dSSukumar Swaminathan 	kmem_cache_destroy(wq->wqed_cache);
5418d738d7dSSukumar Swaminathan wqed_fail:
5428d738d7dSSukumar Swaminathan 	oce_wqm_cache_destroy(wq);
5438d738d7dSSukumar Swaminathan wqm_fail:
5448d738d7dSSukumar Swaminathan 	oce_wqb_cache_destroy(wq);
5458d738d7dSSukumar Swaminathan wqb_fail:
5468d738d7dSSukumar Swaminathan 	kmem_free(wq, sizeof (struct oce_wq));
5478d738d7dSSukumar Swaminathan 	return (NULL);
5488d738d7dSSukumar Swaminathan } /* oce_wq_create */
5498d738d7dSSukumar Swaminathan 
5508d738d7dSSukumar Swaminathan /*
5518d738d7dSSukumar Swaminathan  * function to delete a WQ
5528d738d7dSSukumar Swaminathan  *
5538d738d7dSSukumar Swaminathan  * dev - software handle to the device
5548d738d7dSSukumar Swaminathan  * wq - WQ to delete
5558d738d7dSSukumar Swaminathan  *
5568d738d7dSSukumar Swaminathan  * return 0 => success, failure otherwise
5578d738d7dSSukumar Swaminathan  */
5588d738d7dSSukumar Swaminathan static void
oce_wq_fini(struct oce_dev * dev,struct oce_wq * wq)5598d738d7dSSukumar Swaminathan oce_wq_fini(struct oce_dev *dev, struct oce_wq *wq)
5608d738d7dSSukumar Swaminathan {
5618d738d7dSSukumar Swaminathan 	/* destroy cq */
5628d738d7dSSukumar Swaminathan 	oce_wqb_cache_destroy(wq);
5638d738d7dSSukumar Swaminathan 	oce_wqm_cache_destroy(wq);
5648d738d7dSSukumar Swaminathan 	kmem_cache_destroy(wq->wqed_cache);
5658d738d7dSSukumar Swaminathan 
5668d738d7dSSukumar Swaminathan 	/* Free the packet descriptor list */
5678d738d7dSSukumar Swaminathan 	OCE_LIST_DESTROY(&wq->wqe_desc_list);
5688d738d7dSSukumar Swaminathan 	destroy_ring_buffer(dev, wq->ring);
5698d738d7dSSukumar Swaminathan 	wq->ring = NULL;
5708d738d7dSSukumar Swaminathan 	/* Destroy the Mutex */
5718d738d7dSSukumar Swaminathan 	mutex_destroy(&wq->tx_lock);
5728d738d7dSSukumar Swaminathan 	mutex_destroy(&wq->txc_lock);
5738d738d7dSSukumar Swaminathan 	kmem_free(wq, sizeof (struct oce_wq));
5748d738d7dSSukumar Swaminathan 	atomic_dec_32(&dev->nwqs);
5758d738d7dSSukumar Swaminathan } /* oce_wq_del */
5768d738d7dSSukumar Swaminathan 
5778d738d7dSSukumar Swaminathan 
5788d738d7dSSukumar Swaminathan static int
oce_wq_create(struct oce_wq * wq,struct oce_eq * eq)5798d738d7dSSukumar Swaminathan oce_wq_create(struct oce_wq *wq, struct oce_eq *eq)
5808d738d7dSSukumar Swaminathan {
5818d738d7dSSukumar Swaminathan 
5828d738d7dSSukumar Swaminathan 	struct oce_mbx mbx;
5838d738d7dSSukumar Swaminathan 	struct mbx_create_nic_wq *fwcmd;
5848d738d7dSSukumar Swaminathan 	struct oce_dev *dev = wq->parent;
5858d738d7dSSukumar Swaminathan 	struct oce_cq *cq;
5868d738d7dSSukumar Swaminathan 	int ret;
5878d738d7dSSukumar Swaminathan 
5888d738d7dSSukumar Swaminathan 	/* create the CQ */
5898d738d7dSSukumar Swaminathan 	cq = oce_cq_create(dev, eq, CQ_LEN_1024,
5908d738d7dSSukumar Swaminathan 	    sizeof (struct oce_nic_tx_cqe),
5918d738d7dSSukumar Swaminathan 	    B_FALSE, B_TRUE, B_FALSE, 3);
5928d738d7dSSukumar Swaminathan 	if (cq == NULL) {
5938d738d7dSSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
5948d738d7dSSukumar Swaminathan 		    "WCCQ create failed ");
5958d738d7dSSukumar Swaminathan 		return (DDI_FAILURE);
5968d738d7dSSukumar Swaminathan 	}
5974d0e5007SSukumar Swaminathan 	/* now fill the command */
5988d738d7dSSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
5994d0e5007SSukumar Swaminathan 	fwcmd = (struct mbx_create_nic_wq *)&mbx.payload;
6004d0e5007SSukumar Swaminathan 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
6014d0e5007SSukumar Swaminathan 	    MBX_SUBSYSTEM_NIC,
6024d0e5007SSukumar Swaminathan 	    OPCODE_CREATE_NIC_WQ, MBX_TIMEOUT_SEC,
6034d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_create_nic_wq));
6044d0e5007SSukumar Swaminathan 
6058d738d7dSSukumar Swaminathan 	fwcmd->params.req.nic_wq_type = (uint8_t)wq->cfg.wq_type;
6064d0e5007SSukumar Swaminathan 	fwcmd->params.req.num_pages = wq->ring->dbuf->num_pages;
6074d0e5007SSukumar Swaminathan 	oce_log(dev, CE_NOTE, MOD_CONFIG, "NUM_PAGES = 0x%d size = %lu",
6084d0e5007SSukumar Swaminathan 	    (uint32_t)wq->ring->dbuf->num_pages,
6094d0e5007SSukumar Swaminathan 	    wq->ring->dbuf->size);
6104d0e5007SSukumar Swaminathan 
6114d0e5007SSukumar Swaminathan 	/* workaround: fill 0x01 for ulp_mask in rsvd0 */
6124d0e5007SSukumar Swaminathan 	fwcmd->params.req.rsvd0 = 0x01;
6138d738d7dSSukumar Swaminathan 	fwcmd->params.req.wq_size = OCE_LOG2(wq->cfg.q_len) + 1;
6144d0e5007SSukumar Swaminathan 	fwcmd->params.req.valid = 1;
6154d0e5007SSukumar Swaminathan 	fwcmd->params.req.pd_id = 0;
6164d0e5007SSukumar Swaminathan 	fwcmd->params.req.pci_function_id = dev->fn;
6174d0e5007SSukumar Swaminathan 	fwcmd->params.req.cq_id = cq->cq_id;
6184d0e5007SSukumar Swaminathan 
6194d0e5007SSukumar Swaminathan 	oce_page_list(wq->ring->dbuf, fwcmd->params.req.pages,
6204d0e5007SSukumar Swaminathan 	    wq->ring->dbuf->num_pages);
6214d0e5007SSukumar Swaminathan 
6224d0e5007SSukumar Swaminathan 	/* fill rest of mbx */
6234d0e5007SSukumar Swaminathan 	mbx.u0.s.embedded = 1;
6244d0e5007SSukumar Swaminathan 	mbx.payload_length = sizeof (struct mbx_create_nic_wq);
6254d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
6264d0e5007SSukumar Swaminathan 
6274d0e5007SSukumar Swaminathan 	/* now post the command */
6284d0e5007SSukumar Swaminathan 	ret = oce_mbox_post(dev, &mbx, NULL);
6294d0e5007SSukumar Swaminathan 	if (ret != DDI_SUCCESS) {
6304d0e5007SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG,
6314d0e5007SSukumar Swaminathan 		    "WQ create failed: %d", ret);
6328d738d7dSSukumar Swaminathan 		oce_cq_del(dev, cq);
6338d738d7dSSukumar Swaminathan 		return (ret);
6344d0e5007SSukumar Swaminathan 	}
6354d0e5007SSukumar Swaminathan 
6364d0e5007SSukumar Swaminathan 	/* interpret the response */
6374d0e5007SSukumar Swaminathan 	wq->wq_id = LE_16(fwcmd->params.rsp.wq_id);
6388d738d7dSSukumar Swaminathan 	wq->qstate = QCREATED;
6394d0e5007SSukumar Swaminathan 	wq->cq = cq;
6404d0e5007SSukumar Swaminathan 	/* set the WQCQ handlers */
6418d738d7dSSukumar Swaminathan 	wq->cq->cq_handler = oce_drain_wq_cq;
6428d738d7dSSukumar Swaminathan 	wq->cq->cb_arg = (void *)wq;
6438d738d7dSSukumar Swaminathan 	/* All are free to start with */
6448d738d7dSSukumar Swaminathan 	wq->wq_free = wq->cfg.q_len;
6458d738d7dSSukumar Swaminathan 	/* reset indicies */
6468d738d7dSSukumar Swaminathan 	wq->ring->cidx = 0;
6478d738d7dSSukumar Swaminathan 	wq->ring->pidx = 0;
648*3abb112fSGarrett D'Amore 	oce_log(dev, CE_NOTE, MOD_CONFIG, "WQ CREATED WQID = %d",
649*3abb112fSGarrett D'Amore 	    wq->wq_id);
650*3abb112fSGarrett D'Amore 
6518d738d7dSSukumar Swaminathan 	return (0);
6528d738d7dSSukumar Swaminathan }
6534d0e5007SSukumar Swaminathan 
6544d0e5007SSukumar Swaminathan /*
6554d0e5007SSukumar Swaminathan  * function to delete a WQ
6564d0e5007SSukumar Swaminathan  *
6574d0e5007SSukumar Swaminathan  * dev - software handle to the device
6584d0e5007SSukumar Swaminathan  * wq - WQ to delete
6594d0e5007SSukumar Swaminathan  *
6608d738d7dSSukumar Swaminathan  * return none
6614d0e5007SSukumar Swaminathan  */
6628d738d7dSSukumar Swaminathan static void
oce_wq_del(struct oce_dev * dev,struct oce_wq * wq)6634d0e5007SSukumar Swaminathan oce_wq_del(struct oce_dev *dev, struct oce_wq *wq)
6644d0e5007SSukumar Swaminathan {
6658d738d7dSSukumar Swaminathan 	struct oce_mbx mbx;
6668d738d7dSSukumar Swaminathan 	struct mbx_delete_nic_wq *fwcmd;
6674d0e5007SSukumar Swaminathan 
6684d0e5007SSukumar Swaminathan 
6698d738d7dSSukumar Swaminathan 	ASSERT(dev != NULL);
6708d738d7dSSukumar Swaminathan 	ASSERT(wq != NULL);
6718d738d7dSSukumar Swaminathan 	if (wq->qstate == QCREATED) {
6728d738d7dSSukumar Swaminathan 		bzero(&mbx, sizeof (struct oce_mbx));
6738d738d7dSSukumar Swaminathan 		/* now fill the command */
6748d738d7dSSukumar Swaminathan 		fwcmd = (struct mbx_delete_nic_wq *)&mbx.payload;
6758d738d7dSSukumar Swaminathan 		fwcmd->params.req.wq_id = wq->wq_id;
6768d738d7dSSukumar Swaminathan 		(void) oce_destroy_q(dev, &mbx,
6778d738d7dSSukumar Swaminathan 		    sizeof (struct mbx_delete_nic_wq),
6788d738d7dSSukumar Swaminathan 		    QTYPE_WQ);
6798d738d7dSSukumar Swaminathan 		wq->qstate = QDELETED;
6808d738d7dSSukumar Swaminathan 		oce_cq_del(dev, wq->cq);
6818d738d7dSSukumar Swaminathan 		wq->cq = NULL;
6828d738d7dSSukumar Swaminathan 	}
6834d0e5007SSukumar Swaminathan } /* oce_wq_del */
6844d0e5007SSukumar Swaminathan 
6854d0e5007SSukumar Swaminathan /*
6868d738d7dSSukumar Swaminathan  * function to allocate RQ resources
6874d0e5007SSukumar Swaminathan  *
6884d0e5007SSukumar Swaminathan  * dev - software handle to the device
6894d0e5007SSukumar Swaminathan  * rqcfg - configuration structure providing RQ config parameters
6904d0e5007SSukumar Swaminathan  *
6914d0e5007SSukumar Swaminathan  * return pointer to the RQ created. NULL on failure
6924d0e5007SSukumar Swaminathan  */
6938d738d7dSSukumar Swaminathan static struct oce_rq *
oce_rq_init(struct oce_dev * dev,uint32_t q_len,uint32_t frag_size,uint32_t mtu,boolean_t rss)6948d738d7dSSukumar Swaminathan oce_rq_init(struct oce_dev *dev, uint32_t q_len,
6958d738d7dSSukumar Swaminathan     uint32_t frag_size, uint32_t mtu,
6964d0e5007SSukumar Swaminathan     boolean_t rss)
6974d0e5007SSukumar Swaminathan {
6988d738d7dSSukumar Swaminathan 
6994d0e5007SSukumar Swaminathan 	struct oce_rq *rq;
7004d0e5007SSukumar Swaminathan 	int ret;
7014d0e5007SSukumar Swaminathan 
7024d0e5007SSukumar Swaminathan 	/* validate q creation parameters */
7034d0e5007SSukumar Swaminathan 	if (!OCE_LOG2(frag_size))
7044d0e5007SSukumar Swaminathan 		return (NULL);
7054d0e5007SSukumar Swaminathan 	if ((q_len == 0) || (q_len > 1024))
7064d0e5007SSukumar Swaminathan 		return (NULL);
7074d0e5007SSukumar Swaminathan 
7084d0e5007SSukumar Swaminathan 	/* allocate the rq */
7094d0e5007SSukumar Swaminathan 	rq = kmem_zalloc(sizeof (struct oce_rq), KM_NOSLEEP);
7104d0e5007SSukumar Swaminathan 	if (rq == NULL) {
7114d0e5007SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
7124d0e5007SSukumar Swaminathan 		    "RQ allocation failed");
7134d0e5007SSukumar Swaminathan 		return (NULL);
7144d0e5007SSukumar Swaminathan 	}
7154d0e5007SSukumar Swaminathan 
7164d0e5007SSukumar Swaminathan 	rq->cfg.q_len = q_len;
7174d0e5007SSukumar Swaminathan 	rq->cfg.frag_size = frag_size;
7184d0e5007SSukumar Swaminathan 	rq->cfg.mtu = mtu;
7194d0e5007SSukumar Swaminathan 	rq->cfg.eqd = 0;
7205b9d3151SSukumar Swaminathan 	rq->cfg.nbufs = dev->rq_max_bufs;
7215b9d3151SSukumar Swaminathan 	rq->cfg.is_rss_queue = rss;
7224d0e5007SSukumar Swaminathan 
7234d0e5007SSukumar Swaminathan 	/* assign parent */
7244d0e5007SSukumar Swaminathan 	rq->parent = (void *)dev;
7254d0e5007SSukumar Swaminathan 
7265b9d3151SSukumar Swaminathan 	rq->rq_bdesc_array =
7275b9d3151SSukumar Swaminathan 	    kmem_zalloc((sizeof (oce_rq_bdesc_t) * rq->cfg.nbufs), KM_NOSLEEP);
7285b9d3151SSukumar Swaminathan 	if (rq->rq_bdesc_array == NULL) {
7295b9d3151SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
7305b9d3151SSukumar Swaminathan 		    "RQ bdesc alloc failed");
7315b9d3151SSukumar Swaminathan 		goto rqbd_alloc_fail;
7325b9d3151SSukumar Swaminathan 	}
7335b9d3151SSukumar Swaminathan 	/* create the rq buffer descriptor ring */
7345b9d3151SSukumar Swaminathan 	rq->shadow_ring =
7355b9d3151SSukumar Swaminathan 	    kmem_zalloc((rq->cfg.q_len * sizeof (oce_rq_bdesc_t *)),
7365b9d3151SSukumar Swaminathan 	    KM_NOSLEEP);
7375b9d3151SSukumar Swaminathan 	if (rq->shadow_ring == NULL) {
7385b9d3151SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
7395b9d3151SSukumar Swaminathan 		    "RQ shadow ring alloc failed ");
7405b9d3151SSukumar Swaminathan 		goto rq_shdw_fail;
7415b9d3151SSukumar Swaminathan 	}
7425b9d3151SSukumar Swaminathan 
7435b9d3151SSukumar Swaminathan 	/* allocate the free list array */
7445b9d3151SSukumar Swaminathan 	rq->rqb_freelist =
7455b9d3151SSukumar Swaminathan 	    kmem_zalloc(rq->cfg.nbufs * sizeof (oce_rq_bdesc_t *), KM_NOSLEEP);
7465b9d3151SSukumar Swaminathan 	if (rq->rqb_freelist == NULL) {
7475b9d3151SSukumar Swaminathan 		goto rqb_free_list_fail;
7485b9d3151SSukumar Swaminathan 	}
7495b9d3151SSukumar Swaminathan 	/* create the buffer pool */
7505b9d3151SSukumar Swaminathan 	ret  =  oce_rqb_cache_create(rq, dev->rq_frag_size +
7514d0e5007SSukumar Swaminathan 	    OCE_RQE_BUF_HEADROOM);
7524d0e5007SSukumar Swaminathan 	if (ret != DDI_SUCCESS) {
7534d0e5007SSukumar Swaminathan 		goto rqb_fail;
7544d0e5007SSukumar Swaminathan 	}
7554d0e5007SSukumar Swaminathan 
7564d0e5007SSukumar Swaminathan 	/* create the ring buffer */
7574d0e5007SSukumar Swaminathan 	rq->ring = create_ring_buffer(dev, q_len,
7585b9d3151SSukumar Swaminathan 	    sizeof (struct oce_nic_rqe), DDI_DMA_CONSISTENT | DDI_DMA_RDWR);
7594d0e5007SSukumar Swaminathan 	if (rq->ring == NULL) {
7604d0e5007SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
7614d0e5007SSukumar Swaminathan 		    "RQ ring create failed ");
7624d0e5007SSukumar Swaminathan 		goto rq_ringfail;
7634d0e5007SSukumar Swaminathan 	}
7644d0e5007SSukumar Swaminathan 
7658d738d7dSSukumar Swaminathan 	/* Initialize the RQ lock */
7668d738d7dSSukumar Swaminathan 	mutex_init(&rq->rx_lock, NULL, MUTEX_DRIVER,
7678d738d7dSSukumar Swaminathan 	    DDI_INTR_PRI(dev->intr_pri));
7688d738d7dSSukumar Swaminathan 	/* Initialize the recharge  lock */
7698d738d7dSSukumar Swaminathan 	mutex_init(&rq->rc_lock, NULL, MUTEX_DRIVER,
7708d738d7dSSukumar Swaminathan 	    DDI_INTR_PRI(dev->intr_pri));
7718d738d7dSSukumar Swaminathan 	atomic_inc_32(&dev->nrqs);
7728d738d7dSSukumar Swaminathan 	return (rq);
7738d738d7dSSukumar Swaminathan 
7748d738d7dSSukumar Swaminathan rq_ringfail:
7758d738d7dSSukumar Swaminathan 	oce_rqb_cache_destroy(rq);
7768d738d7dSSukumar Swaminathan rqb_fail:
7775b9d3151SSukumar Swaminathan 	kmem_free(rq->rqb_freelist,
7785b9d3151SSukumar Swaminathan 	    (rq->cfg.nbufs * sizeof (oce_rq_bdesc_t *)));
779*3abb112fSGarrett D'Amore rqb_free_list_fail:
780*3abb112fSGarrett D'Amore 
781*3abb112fSGarrett D'Amore 	kmem_free(rq->shadow_ring,
782*3abb112fSGarrett D'Amore 	    (rq->cfg.q_len * sizeof (oce_rq_bdesc_t *)));
7835b9d3151SSukumar Swaminathan rq_shdw_fail:
7845b9d3151SSukumar Swaminathan 	kmem_free(rq->rq_bdesc_array,
785*3abb112fSGarrett D'Amore 	    (sizeof (oce_rq_bdesc_t) * rq->cfg.nbufs));
7865b9d3151SSukumar Swaminathan rqbd_alloc_fail:
7878d738d7dSSukumar Swaminathan 	kmem_free(rq, sizeof (struct oce_rq));
7888d738d7dSSukumar Swaminathan 	return (NULL);
7898d738d7dSSukumar Swaminathan } /* oce_rq_create */
7908d738d7dSSukumar Swaminathan 
7918d738d7dSSukumar Swaminathan /*
7928d738d7dSSukumar Swaminathan  * function to delete an RQ
7938d738d7dSSukumar Swaminathan  *
7948d738d7dSSukumar Swaminathan  * dev - software handle to the device
7958d738d7dSSukumar Swaminathan  * rq - RQ to delete
7968d738d7dSSukumar Swaminathan  *
7978d738d7dSSukumar Swaminathan  * return none
7988d738d7dSSukumar Swaminathan  */
7998d738d7dSSukumar Swaminathan static void
oce_rq_fini(struct oce_dev * dev,struct oce_rq * rq)8008d738d7dSSukumar Swaminathan oce_rq_fini(struct oce_dev *dev, struct oce_rq *rq)
8018d738d7dSSukumar Swaminathan {
8028d738d7dSSukumar Swaminathan 	/* Destroy buffer cache */
8038d738d7dSSukumar Swaminathan 	oce_rqb_cache_destroy(rq);
8048d738d7dSSukumar Swaminathan 	destroy_ring_buffer(dev, rq->ring);
8058d738d7dSSukumar Swaminathan 	rq->ring = NULL;
8068d738d7dSSukumar Swaminathan 	kmem_free(rq->shadow_ring,
8075b9d3151SSukumar Swaminathan 	    sizeof (oce_rq_bdesc_t *) * rq->cfg.q_len);
8088d738d7dSSukumar Swaminathan 	rq->shadow_ring = NULL;
8095b9d3151SSukumar Swaminathan 	kmem_free(rq->rq_bdesc_array,
8105b9d3151SSukumar Swaminathan 	    (sizeof (oce_rq_bdesc_t) * rq->cfg.nbufs));
8115b9d3151SSukumar Swaminathan 	rq->rq_bdesc_array = NULL;
8125b9d3151SSukumar Swaminathan 	kmem_free(rq->rqb_freelist,
8135b9d3151SSukumar Swaminathan 	    (rq->cfg.nbufs * sizeof (oce_rq_bdesc_t *)));
8145b9d3151SSukumar Swaminathan 	rq->rqb_freelist = NULL;
8158d738d7dSSukumar Swaminathan 	mutex_destroy(&rq->rx_lock);
8168d738d7dSSukumar Swaminathan 	mutex_destroy(&rq->rc_lock);
8178d738d7dSSukumar Swaminathan 	kmem_free(rq, sizeof (struct oce_rq));
8188d738d7dSSukumar Swaminathan 	atomic_dec_32(&dev->nrqs);
8198d738d7dSSukumar Swaminathan } /* oce_rq_del */
8208d738d7dSSukumar Swaminathan 
8218d738d7dSSukumar Swaminathan 
8228d738d7dSSukumar Swaminathan static int
oce_rq_create(struct oce_rq * rq,uint32_t if_id,struct oce_eq * eq)8238d738d7dSSukumar Swaminathan oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq)
8248d738d7dSSukumar Swaminathan {
8258d738d7dSSukumar Swaminathan 	struct oce_mbx mbx;
8268d738d7dSSukumar Swaminathan 	struct mbx_create_nic_rq *fwcmd;
8278d738d7dSSukumar Swaminathan 	struct oce_dev *dev = rq->parent;
8288d738d7dSSukumar Swaminathan 	struct oce_cq *cq;
8298d738d7dSSukumar Swaminathan 	int ret;
8308d738d7dSSukumar Swaminathan 
8318d738d7dSSukumar Swaminathan 	cq = oce_cq_create(dev, eq, CQ_LEN_1024, sizeof (struct oce_nic_rx_cqe),
8328d738d7dSSukumar Swaminathan 	    B_FALSE, B_TRUE, B_FALSE, 3);
8338d738d7dSSukumar Swaminathan 
8348d738d7dSSukumar Swaminathan 	if (cq == NULL) {
8358d738d7dSSukumar Swaminathan 		return (DDI_FAILURE);
8368d738d7dSSukumar Swaminathan 	}
8378d738d7dSSukumar Swaminathan 
8384d0e5007SSukumar Swaminathan 	/* now fill the command */
8398d738d7dSSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
8404d0e5007SSukumar Swaminathan 	fwcmd = (struct mbx_create_nic_rq *)&mbx.payload;
8414d0e5007SSukumar Swaminathan 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
8424d0e5007SSukumar Swaminathan 	    MBX_SUBSYSTEM_NIC,
8434d0e5007SSukumar Swaminathan 	    OPCODE_CREATE_NIC_RQ, MBX_TIMEOUT_SEC,
8444d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_create_nic_rq));
8454d0e5007SSukumar Swaminathan 
8464d0e5007SSukumar Swaminathan 	fwcmd->params.req.num_pages = rq->ring->dbuf->num_pages;
8478d738d7dSSukumar Swaminathan 	fwcmd->params.req.frag_size = OCE_LOG2(rq->cfg.frag_size);
8484d0e5007SSukumar Swaminathan 	fwcmd->params.req.cq_id = cq->cq_id;
8494d0e5007SSukumar Swaminathan 	oce_page_list(rq->ring->dbuf, fwcmd->params.req.pages,
8504d0e5007SSukumar Swaminathan 	    rq->ring->dbuf->num_pages);
8514d0e5007SSukumar Swaminathan 
8524d0e5007SSukumar Swaminathan 	fwcmd->params.req.if_id = if_id;
8538d738d7dSSukumar Swaminathan 	fwcmd->params.req.max_frame_size = (uint16_t)rq->cfg.mtu;
8548d738d7dSSukumar Swaminathan 	fwcmd->params.req.is_rss_queue = rq->cfg.is_rss_queue;
8554d0e5007SSukumar Swaminathan 
8564d0e5007SSukumar Swaminathan 	/* fill rest of mbx */
8574d0e5007SSukumar Swaminathan 	mbx.u0.s.embedded = 1;
8584d0e5007SSukumar Swaminathan 	mbx.payload_length = sizeof (struct mbx_create_nic_rq);
8594d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
8604d0e5007SSukumar Swaminathan 
8614d0e5007SSukumar Swaminathan 	/* now post the command */
8624d0e5007SSukumar Swaminathan 	ret = oce_mbox_post(dev, &mbx, NULL);
8634d0e5007SSukumar Swaminathan 	if (ret != 0) {
8644d0e5007SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG,
8654d0e5007SSukumar Swaminathan 		    "RQ create failed: %d", ret);
8668d738d7dSSukumar Swaminathan 		oce_cq_del(dev, cq);
8678d738d7dSSukumar Swaminathan 		return (ret);
8684d0e5007SSukumar Swaminathan 	}
8694d0e5007SSukumar Swaminathan 
8704d0e5007SSukumar Swaminathan 	/* interpret the response */
8714d0e5007SSukumar Swaminathan 	rq->rq_id = LE_16(fwcmd->params.rsp.u0.s.rq_id);
8725b9d3151SSukumar Swaminathan 	rq->rss_cpuid = fwcmd->params.rsp.u0.s.rss_cpuid;
8738d738d7dSSukumar Swaminathan 	rq->cfg.if_id = if_id;
8748d738d7dSSukumar Swaminathan 	rq->qstate = QCREATED;
8754d0e5007SSukumar Swaminathan 	rq->cq = cq;
8764d0e5007SSukumar Swaminathan 
8774d0e5007SSukumar Swaminathan 	/* set the Completion Handler */
8788d738d7dSSukumar Swaminathan 	rq->cq->cq_handler = oce_drain_rq_cq;
8798d738d7dSSukumar Swaminathan 	rq->cq->cb_arg  = (void *)rq;
8808d738d7dSSukumar Swaminathan 	/* reset the indicies */
8818d738d7dSSukumar Swaminathan 	rq->ring->cidx = 0;
8828d738d7dSSukumar Swaminathan 	rq->ring->pidx = 0;
8838d738d7dSSukumar Swaminathan 	rq->buf_avail = 0;
884*3abb112fSGarrett D'Amore 	oce_log(dev, CE_NOTE, MOD_CONFIG, "RQ created, RQID : %d", rq->rq_id);
8858d738d7dSSukumar Swaminathan 	return (0);
8864d0e5007SSukumar Swaminathan 
8878d738d7dSSukumar Swaminathan }
8884d0e5007SSukumar Swaminathan 
8894d0e5007SSukumar Swaminathan /*
8904d0e5007SSukumar Swaminathan  * function to delete an RQ
8914d0e5007SSukumar Swaminathan  *
8924d0e5007SSukumar Swaminathan  * dev - software handle to the device
8934d0e5007SSukumar Swaminathan  * rq - RQ to delete
8944d0e5007SSukumar Swaminathan  *
8958d738d7dSSukumar Swaminathan  * return none
8964d0e5007SSukumar Swaminathan  */
8978d738d7dSSukumar Swaminathan static void
oce_rq_del(struct oce_dev * dev,struct oce_rq * rq)8984d0e5007SSukumar Swaminathan oce_rq_del(struct oce_dev *dev, struct oce_rq *rq)
8994d0e5007SSukumar Swaminathan {
9008d738d7dSSukumar Swaminathan 	struct oce_mbx mbx;
9018d738d7dSSukumar Swaminathan 	struct mbx_delete_nic_rq *fwcmd;
9024d0e5007SSukumar Swaminathan 
9034d0e5007SSukumar Swaminathan 	ASSERT(dev != NULL);
9044d0e5007SSukumar Swaminathan 	ASSERT(rq != NULL);
9054d0e5007SSukumar Swaminathan 
9068d738d7dSSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
9074d0e5007SSukumar Swaminathan 
9088d738d7dSSukumar Swaminathan 	/* delete the Queue  */
9098d738d7dSSukumar Swaminathan 	if (rq->qstate == QCREATED) {
9108d738d7dSSukumar Swaminathan 		fwcmd = (struct mbx_delete_nic_rq *)&mbx.payload;
9118d738d7dSSukumar Swaminathan 		fwcmd->params.req.rq_id = rq->rq_id;
9128d738d7dSSukumar Swaminathan 		(void) oce_destroy_q(dev, &mbx,
9138d738d7dSSukumar Swaminathan 		    sizeof (struct mbx_delete_nic_rq), QTYPE_RQ);
9148d738d7dSSukumar Swaminathan 		rq->qstate = QDELETED;
9158d738d7dSSukumar Swaminathan 		oce_clean_rq(rq);
9168d738d7dSSukumar Swaminathan 		/* Delete the associated CQ */
9178d738d7dSSukumar Swaminathan 		oce_cq_del(dev, rq->cq);
9188d738d7dSSukumar Swaminathan 		rq->cq = NULL;
9198d738d7dSSukumar Swaminathan 		/* free up the posted buffers */
9205b9d3151SSukumar Swaminathan 		oce_rq_discharge(rq);
9218d738d7dSSukumar Swaminathan 	}
9224d0e5007SSukumar Swaminathan } /* oce_rq_del */
9234d0e5007SSukumar Swaminathan 
9244d0e5007SSukumar Swaminathan /*
9254d0e5007SSukumar Swaminathan  * function to arm an EQ so that it can generate events
9264d0e5007SSukumar Swaminathan  *
9274d0e5007SSukumar Swaminathan  * dev - software handle to the device
9284d0e5007SSukumar Swaminathan  * qid - id of the EQ returned by the fw at the time of creation
9294d0e5007SSukumar Swaminathan  * npopped - number of EQEs to arm with
9304d0e5007SSukumar Swaminathan  * rearm - rearm bit
9314d0e5007SSukumar Swaminathan  * clearint - bit to clear the interrupt condition because of which
9324d0e5007SSukumar Swaminathan  *	EQEs are generated
9334d0e5007SSukumar Swaminathan  *
9344d0e5007SSukumar Swaminathan  * return none
9354d0e5007SSukumar Swaminathan  */
9364d0e5007SSukumar Swaminathan void
oce_arm_eq(struct oce_dev * dev,int16_t qid,int npopped,boolean_t rearm,boolean_t clearint)9374d0e5007SSukumar Swaminathan oce_arm_eq(struct oce_dev *dev, int16_t qid, int npopped,
9384d0e5007SSukumar Swaminathan     boolean_t rearm, boolean_t clearint)
9394d0e5007SSukumar Swaminathan {
9404d0e5007SSukumar Swaminathan 	eq_db_t eq_db = {0};
9414d0e5007SSukumar Swaminathan 
9424d0e5007SSukumar Swaminathan 	eq_db.bits.rearm = rearm;
9434d0e5007SSukumar Swaminathan 	eq_db.bits.event  = B_TRUE;
9444d0e5007SSukumar Swaminathan 	eq_db.bits.num_popped = npopped;
9454d0e5007SSukumar Swaminathan 	eq_db.bits.clrint = clearint;
9464d0e5007SSukumar Swaminathan 	eq_db.bits.qid = qid;
9474d0e5007SSukumar Swaminathan 	OCE_DB_WRITE32(dev, PD_EQ_DB, eq_db.dw0);
9484d0e5007SSukumar Swaminathan }
9494d0e5007SSukumar Swaminathan 
9504d0e5007SSukumar Swaminathan /*
9514d0e5007SSukumar Swaminathan  * function to arm a CQ with CQEs
9524d0e5007SSukumar Swaminathan  *
9534d0e5007SSukumar Swaminathan  * dev - software handle to the device
9544d0e5007SSukumar Swaminathan  * qid - the id of the CQ returned by the fw at the time of creation
9554d0e5007SSukumar Swaminathan  * npopped - number of CQEs to arm with
9564d0e5007SSukumar Swaminathan  * rearm - rearm bit enable/disable
9574d0e5007SSukumar Swaminathan  *
9584d0e5007SSukumar Swaminathan  * return none
9594d0e5007SSukumar Swaminathan  */
9604d0e5007SSukumar Swaminathan void
oce_arm_cq(struct oce_dev * dev,int16_t qid,int npopped,boolean_t rearm)9614d0e5007SSukumar Swaminathan oce_arm_cq(struct oce_dev *dev, int16_t qid, int npopped,
9624d0e5007SSukumar Swaminathan     boolean_t rearm)
9634d0e5007SSukumar Swaminathan {
9644d0e5007SSukumar Swaminathan 	cq_db_t cq_db = {0};
9654d0e5007SSukumar Swaminathan 	cq_db.bits.rearm = rearm;
9664d0e5007SSukumar Swaminathan 	cq_db.bits.num_popped = npopped;
9674d0e5007SSukumar Swaminathan 	cq_db.bits.event = 0;
9684d0e5007SSukumar Swaminathan 	cq_db.bits.qid = qid;
9694d0e5007SSukumar Swaminathan 	OCE_DB_WRITE32(dev, PD_CQ_DB, cq_db.dw0);
9704d0e5007SSukumar Swaminathan }
9714d0e5007SSukumar Swaminathan 
9724d0e5007SSukumar Swaminathan 
9734d0e5007SSukumar Swaminathan /*
9744d0e5007SSukumar Swaminathan  * function to delete a EQ, CQ, MQ, WQ or RQ
9754d0e5007SSukumar Swaminathan  *
9764d0e5007SSukumar Swaminathan  * dev - sofware handle to the device
9774d0e5007SSukumar Swaminathan  * mbx - mbox command to send to the fw to delete the queue
9784d0e5007SSukumar Swaminathan  *	mbx contains the queue information to delete
9794d0e5007SSukumar Swaminathan  * req_size - the size of the mbx payload dependent on the qtype
9804d0e5007SSukumar Swaminathan  * qtype - the type of queue i.e. EQ, CQ, MQ, WQ or RQ
9814d0e5007SSukumar Swaminathan  *
9824d0e5007SSukumar Swaminathan  * return DDI_SUCCESS => success, failure otherwise
9834d0e5007SSukumar Swaminathan  */
9844d0e5007SSukumar Swaminathan int
oce_destroy_q(struct oce_dev * dev,struct oce_mbx * mbx,size_t req_size,enum qtype qtype)9854d0e5007SSukumar Swaminathan oce_destroy_q(struct oce_dev *dev, struct oce_mbx  *mbx, size_t req_size,
9864d0e5007SSukumar Swaminathan     enum qtype qtype)
9874d0e5007SSukumar Swaminathan {
9884d0e5007SSukumar Swaminathan 	struct mbx_hdr *hdr = (struct mbx_hdr *)&mbx->payload;
9894d0e5007SSukumar Swaminathan 	int opcode;
9904d0e5007SSukumar Swaminathan 	int subsys;
9914d0e5007SSukumar Swaminathan 	int ret;
9924d0e5007SSukumar Swaminathan 
9934d0e5007SSukumar Swaminathan 	switch (qtype) {
9944d0e5007SSukumar Swaminathan 	case QTYPE_EQ: {
9954d0e5007SSukumar Swaminathan 		opcode = OPCODE_DESTROY_COMMON_EQ;
9964d0e5007SSukumar Swaminathan 		subsys = MBX_SUBSYSTEM_COMMON;
9974d0e5007SSukumar Swaminathan 		break;
9984d0e5007SSukumar Swaminathan 	}
9994d0e5007SSukumar Swaminathan 	case QTYPE_CQ: {
10004d0e5007SSukumar Swaminathan 		opcode = OPCODE_DESTROY_COMMON_CQ;
10014d0e5007SSukumar Swaminathan 		subsys = MBX_SUBSYSTEM_COMMON;
10024d0e5007SSukumar Swaminathan 		break;
10034d0e5007SSukumar Swaminathan 	}
10044d0e5007SSukumar Swaminathan 	case QTYPE_MQ: {
10054d0e5007SSukumar Swaminathan 		opcode = OPCODE_DESTROY_COMMON_MQ;
10064d0e5007SSukumar Swaminathan 		subsys = MBX_SUBSYSTEM_COMMON;
10074d0e5007SSukumar Swaminathan 		break;
10084d0e5007SSukumar Swaminathan 	}
10094d0e5007SSukumar Swaminathan 	case QTYPE_WQ: {
10104d0e5007SSukumar Swaminathan 		opcode = OPCODE_DELETE_NIC_WQ;
10114d0e5007SSukumar Swaminathan 		subsys = MBX_SUBSYSTEM_NIC;
10124d0e5007SSukumar Swaminathan 		break;
10134d0e5007SSukumar Swaminathan 	}
10144d0e5007SSukumar Swaminathan 	case QTYPE_RQ: {
10154d0e5007SSukumar Swaminathan 		opcode = OPCODE_DELETE_NIC_RQ;
10164d0e5007SSukumar Swaminathan 		subsys = MBX_SUBSYSTEM_NIC;
10174d0e5007SSukumar Swaminathan 		break;
10184d0e5007SSukumar Swaminathan 	}
10194d0e5007SSukumar Swaminathan 	default: {
10204d0e5007SSukumar Swaminathan 		ASSERT(0);
10214d0e5007SSukumar Swaminathan 		break;
10224d0e5007SSukumar Swaminathan 	}
10234d0e5007SSukumar Swaminathan 	}
10244d0e5007SSukumar Swaminathan 
10254d0e5007SSukumar Swaminathan 	mbx_common_req_hdr_init(hdr, 0, 0, subsys,
10264d0e5007SSukumar Swaminathan 	    opcode, MBX_TIMEOUT_SEC, req_size);
10274d0e5007SSukumar Swaminathan 
10284d0e5007SSukumar Swaminathan 	/* fill rest of mbx */
10294d0e5007SSukumar Swaminathan 	mbx->u0.s.embedded = 1;
10304d0e5007SSukumar Swaminathan 	mbx->payload_length = (uint32_t)req_size;
10314d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(mbx), mbx->payload_length + OCE_BMBX_RHDR_SZ);
10324d0e5007SSukumar Swaminathan 
10334d0e5007SSukumar Swaminathan 	/* send command */
10344d0e5007SSukumar Swaminathan 	ret = oce_mbox_post(dev, mbx, NULL);
10354d0e5007SSukumar Swaminathan 
10364d0e5007SSukumar Swaminathan 	if (ret != 0) {
10374d0e5007SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
10384d0e5007SSukumar Swaminathan 		    "Failed to del q ");
10394d0e5007SSukumar Swaminathan 	}
10404d0e5007SSukumar Swaminathan 	return (ret);
10414d0e5007SSukumar Swaminathan }
10424d0e5007SSukumar Swaminathan 
10434d0e5007SSukumar Swaminathan /*
10444d0e5007SSukumar Swaminathan  * function to set the delay parameter in the EQ for interrupt coalescing
10454d0e5007SSukumar Swaminathan  *
10464d0e5007SSukumar Swaminathan  * dev - software handle to the device
10474d0e5007SSukumar Swaminathan  * eq_arr - array of EQ ids to delete
10484d0e5007SSukumar Swaminathan  * eq_cnt - number of elements in eq_arr
10494d0e5007SSukumar Swaminathan  * eq_delay - delay parameter
10504d0e5007SSukumar Swaminathan  *
10514d0e5007SSukumar Swaminathan  * return DDI_SUCCESS => success, failure otherwise
10524d0e5007SSukumar Swaminathan  */
10534d0e5007SSukumar Swaminathan int
oce_set_eq_delay(struct oce_dev * dev,uint32_t * eq_arr,uint32_t eq_cnt,uint32_t eq_delay)10544d0e5007SSukumar Swaminathan oce_set_eq_delay(struct oce_dev *dev, uint32_t *eq_arr,
10554d0e5007SSukumar Swaminathan     uint32_t eq_cnt, uint32_t eq_delay)
10564d0e5007SSukumar Swaminathan {
10574d0e5007SSukumar Swaminathan 	struct oce_mbx mbx;
10584d0e5007SSukumar Swaminathan 	struct mbx_modify_common_eq_delay *fwcmd;
10594d0e5007SSukumar Swaminathan 	int ret;
10604d0e5007SSukumar Swaminathan 	int neq;
10614d0e5007SSukumar Swaminathan 
10624d0e5007SSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
10634d0e5007SSukumar Swaminathan 	fwcmd = (struct mbx_modify_common_eq_delay *)&mbx.payload;
10644d0e5007SSukumar Swaminathan 
10654d0e5007SSukumar Swaminathan 	/* fill the command */
10664d0e5007SSukumar Swaminathan 	fwcmd->params.req.num_eq = eq_cnt;
10674d0e5007SSukumar Swaminathan 	for (neq = 0; neq < eq_cnt; neq++) {
10684d0e5007SSukumar Swaminathan 		fwcmd->params.req.delay[neq].eq_id = eq_arr[neq];
10694d0e5007SSukumar Swaminathan 		fwcmd->params.req.delay[neq].phase = 0;
10704d0e5007SSukumar Swaminathan 		fwcmd->params.req.delay[neq].dm = eq_delay;
10714d0e5007SSukumar Swaminathan 
10724d0e5007SSukumar Swaminathan 	}
10734d0e5007SSukumar Swaminathan 
10744d0e5007SSukumar Swaminathan 	/* initialize the ioctl header */
10754d0e5007SSukumar Swaminathan 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
10764d0e5007SSukumar Swaminathan 	    MBX_SUBSYSTEM_COMMON,
10774d0e5007SSukumar Swaminathan 	    OPCODE_MODIFY_COMMON_EQ_DELAY,
10784d0e5007SSukumar Swaminathan 	    MBX_TIMEOUT_SEC,
10794d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_modify_common_eq_delay));
10804d0e5007SSukumar Swaminathan 
10814d0e5007SSukumar Swaminathan 	/* fill rest of mbx */
10824d0e5007SSukumar Swaminathan 	mbx.u0.s.embedded = 1;
10834d0e5007SSukumar Swaminathan 	mbx.payload_length = sizeof (struct mbx_modify_common_eq_delay);
10844d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
10854d0e5007SSukumar Swaminathan 
10864d0e5007SSukumar Swaminathan 	/* post the command */
10874d0e5007SSukumar Swaminathan 	ret = oce_mbox_post(dev, &mbx, NULL);
10884d0e5007SSukumar Swaminathan 	if (ret != 0) {
10894d0e5007SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG,
10904d0e5007SSukumar Swaminathan 		    "Failed to set EQ delay %d", ret);
10914d0e5007SSukumar Swaminathan 	}
10924d0e5007SSukumar Swaminathan 
10934d0e5007SSukumar Swaminathan 	return (ret);
10944d0e5007SSukumar Swaminathan } /* oce_set_eq_delay */
10954d0e5007SSukumar Swaminathan 
10964d0e5007SSukumar Swaminathan /*
10974d0e5007SSukumar Swaminathan  * function to cleanup the eqs used during stop
10984d0e5007SSukumar Swaminathan  *
10994d0e5007SSukumar Swaminathan  * eq - pointer to event queue structure
11004d0e5007SSukumar Swaminathan  *
11014d0e5007SSukumar Swaminathan  * return none
11024d0e5007SSukumar Swaminathan  */
11034d0e5007SSukumar Swaminathan void
oce_drain_eq(struct oce_eq * eq)11044d0e5007SSukumar Swaminathan oce_drain_eq(struct oce_eq *eq)
11054d0e5007SSukumar Swaminathan {
11064d0e5007SSukumar Swaminathan 	struct oce_eqe *eqe;
11074d0e5007SSukumar Swaminathan 	uint16_t num_eqe = 0;
11088d738d7dSSukumar Swaminathan 	struct oce_dev *dev;
11094d0e5007SSukumar Swaminathan 
11108d738d7dSSukumar Swaminathan 	dev = eq->parent;
11114d0e5007SSukumar Swaminathan 	/* get the first item in eq to process */
11124d0e5007SSukumar Swaminathan 	eqe = RING_GET_CONSUMER_ITEM_VA(eq->ring, struct oce_eqe);
11134d0e5007SSukumar Swaminathan 
11144d0e5007SSukumar Swaminathan 	while (eqe->u0.dw0) {
11154d0e5007SSukumar Swaminathan 		eqe->u0.dw0 = LE_32(eqe->u0.dw0);
11164d0e5007SSukumar Swaminathan 
11174d0e5007SSukumar Swaminathan 		/* clear valid bit */
11184d0e5007SSukumar Swaminathan 		eqe->u0.dw0 = 0;
11194d0e5007SSukumar Swaminathan 
11204d0e5007SSukumar Swaminathan 		/* process next eqe */
11214d0e5007SSukumar Swaminathan 		RING_GET(eq->ring, 1);
11224d0e5007SSukumar Swaminathan 
11234d0e5007SSukumar Swaminathan 		eqe = RING_GET_CONSUMER_ITEM_VA(eq->ring, struct oce_eqe);
11244d0e5007SSukumar Swaminathan 		num_eqe++;
11254d0e5007SSukumar Swaminathan 	} /* for all EQEs */
11268d738d7dSSukumar Swaminathan 	if (num_eqe) {
11278d738d7dSSukumar Swaminathan 		oce_arm_eq(dev, eq->eq_id, num_eqe, B_FALSE, B_TRUE);
11288d738d7dSSukumar Swaminathan 	}
11294d0e5007SSukumar Swaminathan } /* oce_drain_eq */
11308d738d7dSSukumar Swaminathan 
11318d738d7dSSukumar Swaminathan 
11328d738d7dSSukumar Swaminathan int
oce_init_txrx(struct oce_dev * dev)11338d738d7dSSukumar Swaminathan oce_init_txrx(struct oce_dev  *dev)
11348d738d7dSSukumar Swaminathan {
11355b9d3151SSukumar Swaminathan 	int qid = 0;
11368d738d7dSSukumar Swaminathan 
11375b9d3151SSukumar Swaminathan 	/* enable RSS if rx queues > 1 */
11385b9d3151SSukumar Swaminathan 	dev->rss_enable = (dev->rx_rings > 1) ? B_TRUE : B_FALSE;
11395b9d3151SSukumar Swaminathan 
11405b9d3151SSukumar Swaminathan 	for (qid = 0; qid < dev->tx_rings; qid++) {
11415b9d3151SSukumar Swaminathan 		dev->wq[qid] = oce_wq_init(dev, dev->tx_ring_size,
11425b9d3151SSukumar Swaminathan 		    NIC_WQ_TYPE_STANDARD);
11435b9d3151SSukumar Swaminathan 		if (dev->wq[qid] == NULL) {
11445b9d3151SSukumar Swaminathan 			goto queue_fail;
11455b9d3151SSukumar Swaminathan 		}
11468d738d7dSSukumar Swaminathan 	}
11478d738d7dSSukumar Swaminathan 
11485b9d3151SSukumar Swaminathan 	/* Now create the Rx Queues */
11495b9d3151SSukumar Swaminathan 	/* qid 0 is always default non rss queue for rss */
11505b9d3151SSukumar Swaminathan 	dev->rq[0] = oce_rq_init(dev, dev->rx_ring_size, dev->rq_frag_size,
11515b9d3151SSukumar Swaminathan 	    OCE_MAX_JUMBO_FRAME_SIZE, B_FALSE);
11528d738d7dSSukumar Swaminathan 	if (dev->rq[0] == NULL) {
11538d738d7dSSukumar Swaminathan 		goto queue_fail;
11548d738d7dSSukumar Swaminathan 	}
11555b9d3151SSukumar Swaminathan 
11565b9d3151SSukumar Swaminathan 	for (qid = 1; qid < dev->rx_rings; qid++) {
11575b9d3151SSukumar Swaminathan 		dev->rq[qid] = oce_rq_init(dev, dev->rx_ring_size,
11585b9d3151SSukumar Swaminathan 		    dev->rq_frag_size, OCE_MAX_JUMBO_FRAME_SIZE,
11595b9d3151SSukumar Swaminathan 		    dev->rss_enable);
11605b9d3151SSukumar Swaminathan 		if (dev->rq[qid] == NULL) {
11615b9d3151SSukumar Swaminathan 			goto queue_fail;
11625b9d3151SSukumar Swaminathan 		}
11635b9d3151SSukumar Swaminathan 	}
11645b9d3151SSukumar Swaminathan 
11658d738d7dSSukumar Swaminathan 	return (DDI_SUCCESS);
11668d738d7dSSukumar Swaminathan queue_fail:
11678d738d7dSSukumar Swaminathan 	oce_fini_txrx(dev);
11688d738d7dSSukumar Swaminathan 	return (DDI_FAILURE);
11698d738d7dSSukumar Swaminathan }
11708d738d7dSSukumar Swaminathan void
oce_fini_txrx(struct oce_dev * dev)11718d738d7dSSukumar Swaminathan oce_fini_txrx(struct oce_dev *dev)
11728d738d7dSSukumar Swaminathan {
11735b9d3151SSukumar Swaminathan 	int qid;
11745b9d3151SSukumar Swaminathan 	int nqs;
11755b9d3151SSukumar Swaminathan 
11765b9d3151SSukumar Swaminathan 	/* free all the tx rings */
11775b9d3151SSukumar Swaminathan 	/* nwqs is decremented in fini so copy count first */
11785b9d3151SSukumar Swaminathan 	nqs = dev->nwqs;
11795b9d3151SSukumar Swaminathan 	for (qid = 0; qid < nqs; qid++) {
11805b9d3151SSukumar Swaminathan 		if (dev->wq[qid] != NULL) {
11815b9d3151SSukumar Swaminathan 			oce_wq_fini(dev, dev->wq[qid]);
11825b9d3151SSukumar Swaminathan 			dev->wq[qid] = NULL;
11835b9d3151SSukumar Swaminathan 		}
11848d738d7dSSukumar Swaminathan 	}
11855b9d3151SSukumar Swaminathan 	/* free all the rx rings */
11865b9d3151SSukumar Swaminathan 	nqs = dev->nrqs;
11875b9d3151SSukumar Swaminathan 	for (qid = 0; qid < nqs; qid++) {
11885b9d3151SSukumar Swaminathan 		if (dev->rq[qid] != NULL) {
11895b9d3151SSukumar Swaminathan 			oce_rq_fini(dev, dev->rq[qid]);
11905b9d3151SSukumar Swaminathan 			dev->rq[qid] = NULL;
11915b9d3151SSukumar Swaminathan 		}
11928d738d7dSSukumar Swaminathan 	}
11938d738d7dSSukumar Swaminathan }
11948d738d7dSSukumar Swaminathan 
11958d738d7dSSukumar Swaminathan int
oce_create_queues(struct oce_dev * dev)11968d738d7dSSukumar Swaminathan oce_create_queues(struct oce_dev *dev)
11978d738d7dSSukumar Swaminathan {
11988d738d7dSSukumar Swaminathan 
11998d738d7dSSukumar Swaminathan 	int i;
12008d738d7dSSukumar Swaminathan 	struct oce_eq *eq;
12018d738d7dSSukumar Swaminathan 	struct oce_mq *mq;
12028d738d7dSSukumar Swaminathan 
12038d738d7dSSukumar Swaminathan 	for (i = 0; i < dev->num_vectors; i++) {
12048d738d7dSSukumar Swaminathan 		eq = oce_eq_create(dev, EQ_LEN_1024, EQE_SIZE_4, 0);
12058d738d7dSSukumar Swaminathan 		if (eq == NULL) {
12068d738d7dSSukumar Swaminathan 			goto rings_fail;
12078d738d7dSSukumar Swaminathan 		}
12088d738d7dSSukumar Swaminathan 		dev->eq[i] = eq;
12098d738d7dSSukumar Swaminathan 	}
12105b9d3151SSukumar Swaminathan 	for (i = 0; i < dev->nwqs; i++) {
12115b9d3151SSukumar Swaminathan 		if (oce_wq_create(dev->wq[i], dev->eq[0]) != 0)
12125b9d3151SSukumar Swaminathan 			goto rings_fail;
12135b9d3151SSukumar Swaminathan 	}
12145b9d3151SSukumar Swaminathan 
12155b9d3151SSukumar Swaminathan 	for (i = 0; i < dev->nrqs; i++) {
12165b9d3151SSukumar Swaminathan 		if (oce_rq_create(dev->rq[i], dev->if_id,
12175b9d3151SSukumar Swaminathan 		    dev->neqs > 1 ? dev->eq[1 + i] : dev->eq[0]) != 0)
12185b9d3151SSukumar Swaminathan 			goto rings_fail;
12195b9d3151SSukumar Swaminathan 	}
12208d738d7dSSukumar Swaminathan 	mq = oce_mq_create(dev, dev->eq[0], 64);
12218d738d7dSSukumar Swaminathan 	if (mq == NULL)
12228d738d7dSSukumar Swaminathan 		goto rings_fail;
12238d738d7dSSukumar Swaminathan 	dev->mq = mq;
12248d738d7dSSukumar Swaminathan 	return (DDI_SUCCESS);
12258d738d7dSSukumar Swaminathan rings_fail:
12268d738d7dSSukumar Swaminathan 	oce_delete_queues(dev);
12278d738d7dSSukumar Swaminathan 	return (DDI_FAILURE);
12288d738d7dSSukumar Swaminathan 
12298d738d7dSSukumar Swaminathan }
12308d738d7dSSukumar Swaminathan 
12318d738d7dSSukumar Swaminathan void
oce_delete_queues(struct oce_dev * dev)12328d738d7dSSukumar Swaminathan oce_delete_queues(struct oce_dev *dev)
12338d738d7dSSukumar Swaminathan {
12348d738d7dSSukumar Swaminathan 	int i;
12355b9d3151SSukumar Swaminathan 	int neqs = dev->neqs;
12368d738d7dSSukumar Swaminathan 	if (dev->mq != NULL) {
12378d738d7dSSukumar Swaminathan 		oce_mq_del(dev, dev->mq);
12388d738d7dSSukumar Swaminathan 		dev->mq = NULL;
12398d738d7dSSukumar Swaminathan 	}
12408d738d7dSSukumar Swaminathan 
12418d738d7dSSukumar Swaminathan 	for (i = 0; i < dev->nrqs; i++) {
12428d738d7dSSukumar Swaminathan 		oce_rq_del(dev, dev->rq[i]);
12438d738d7dSSukumar Swaminathan 	}
12448d738d7dSSukumar Swaminathan 	for (i = 0; i < dev->nwqs; i++) {
12458d738d7dSSukumar Swaminathan 		oce_wq_del(dev, dev->wq[i]);
12468d738d7dSSukumar Swaminathan 	}
12475b9d3151SSukumar Swaminathan 	/* delete as many eqs as the number of vectors */
12485b9d3151SSukumar Swaminathan 	for (i = 0; i < neqs; i++) {
12498d738d7dSSukumar Swaminathan 		oce_eq_del(dev, dev->eq[i]);
12508d738d7dSSukumar Swaminathan 		dev->eq[i] = NULL;
12518d738d7dSSukumar Swaminathan 	}
12528d738d7dSSukumar Swaminathan }
1253*3abb112fSGarrett D'Amore 
1254*3abb112fSGarrett D'Amore void
oce_dev_rss_ready(struct oce_dev * dev)1255*3abb112fSGarrett D'Amore oce_dev_rss_ready(struct oce_dev *dev)
1256*3abb112fSGarrett D'Amore {
1257*3abb112fSGarrett D'Amore 	uint8_t dev_index = 0;
1258*3abb112fSGarrett D'Amore 	uint8_t adapter_rss = 0;
1259*3abb112fSGarrett D'Amore 
1260*3abb112fSGarrett D'Amore 	/* Return if rx_rings <= 1 (No RSS) */
1261*3abb112fSGarrett D'Amore 	if (dev->rx_rings <= 1) {
1262*3abb112fSGarrett D'Amore 		oce_log(dev, CE_NOTE, MOD_CONFIG,
1263*3abb112fSGarrett D'Amore 		    "Rx rings = %d, Not enabling RSS", dev->rx_rings);
1264*3abb112fSGarrett D'Amore 		return;
1265*3abb112fSGarrett D'Amore 	}
1266*3abb112fSGarrett D'Amore 
1267*3abb112fSGarrett D'Amore 	/*
1268*3abb112fSGarrett D'Amore 	 * Count the number of PCI functions enabling RSS on this
1269*3abb112fSGarrett D'Amore 	 * adapter
1270*3abb112fSGarrett D'Amore 	 */
1271*3abb112fSGarrett D'Amore 	while (dev_index < MAX_DEVS) {
1272*3abb112fSGarrett D'Amore 		if ((oce_dev_list[dev_index] != NULL) &&
1273*3abb112fSGarrett D'Amore 		    (dev->pci_bus == oce_dev_list[dev_index]->pci_bus) &&
1274*3abb112fSGarrett D'Amore 		    (dev->pci_device == oce_dev_list[dev_index]->pci_device) &&
1275*3abb112fSGarrett D'Amore 		    (oce_dev_list[dev_index]->rss_enable)) {
1276*3abb112fSGarrett D'Amore 			adapter_rss++;
1277*3abb112fSGarrett D'Amore 		}
1278*3abb112fSGarrett D'Amore 		dev_index++;
1279*3abb112fSGarrett D'Amore 	}
1280*3abb112fSGarrett D'Amore 
1281*3abb112fSGarrett D'Amore 	/*
1282*3abb112fSGarrett D'Amore 	 * If there are already MAX_RSS_PER_ADAPTER PCI functions using
1283*3abb112fSGarrett D'Amore 	 * RSS on this adapter, reduce the number of rx rings to 1
1284*3abb112fSGarrett D'Amore 	 * (No RSS)
1285*3abb112fSGarrett D'Amore 	 */
1286*3abb112fSGarrett D'Amore 	if (adapter_rss >= MAX_RSS_PER_ADAPTER) {
1287*3abb112fSGarrett D'Amore 		dev->rx_rings = 1;
1288*3abb112fSGarrett D'Amore 	}
1289*3abb112fSGarrett D'Amore }
1290