1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2010 Emulex.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Source file containing Queue handling functions
29  *
30  */
31 
32 #include <oce_impl.h>
33 
34 int oce_destroy_q(struct oce_dev  *oce, struct oce_mbx  *mbx, size_t req_size,
35     enum qtype  qtype);
36 /* MAil box Queue functions */
37 struct oce_mq *
38 oce_mq_create(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len);
39 
40 /* event queue handling */
41 struct oce_eq *
42 oce_eq_create(struct oce_dev *dev, uint32_t q_len, uint32_t item_size,
43     uint32_t eq_delay);
44 
45 /* completion queue handling */
46 struct oce_cq *
47 oce_cq_create(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len,
48     uint32_t item_size, boolean_t sol_event, boolean_t is_eventable,
49     boolean_t nodelay, uint32_t ncoalesce);
50 
51 
52 /* Tx  WQ functions */
53 static struct oce_wq *oce_wq_init(struct oce_dev *dev,  uint32_t q_len,
54     int wq_type);
55 static void oce_wq_fini(struct oce_dev *dev, struct oce_wq *wq);
56 static int oce_wq_create(struct oce_wq *wq, struct oce_eq *eq);
57 static void oce_wq_del(struct oce_dev *dev, struct oce_wq *wq);
58 /* Rx Queue functions */
59 static struct oce_rq *oce_rq_init(struct oce_dev *dev, uint32_t q_len,
60     uint32_t frag_size, uint32_t mtu,
61     boolean_t rss);
62 static void oce_rq_fini(struct oce_dev *dev, struct oce_rq *rq);
63 static int oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq);
64 static void oce_rq_del(struct oce_dev *dev, struct oce_rq *rq);
65 
66 /*
67  * function to create an event queue
68  *
69  * dev - software handle to the device
70  * eqcfg - pointer to a config structure containg the eq parameters
71  *
72  * return pointer to EQ; NULL on failure
73  */
74 struct oce_eq *
75 oce_eq_create(struct oce_dev *dev, uint32_t q_len, uint32_t item_size,
76     uint32_t eq_delay)
77 {
78 	struct oce_eq *eq;
79 	struct oce_mbx mbx;
80 	struct mbx_create_common_eq *fwcmd;
81 	int ret = 0;
82 
83 	/* allocate an eq */
84 	eq = kmem_zalloc(sizeof (struct oce_eq), KM_NOSLEEP);
85 
86 	if (eq == NULL) {
87 		return (NULL);
88 	}
89 
90 	bzero(&mbx, sizeof (struct oce_mbx));
91 	/* allocate mbx */
92 	fwcmd = (struct mbx_create_common_eq *)&mbx.payload;
93 
94 	eq->ring = create_ring_buffer(dev, q_len,
95 	    item_size, DDI_DMA_CONSISTENT);
96 
97 	if (eq->ring == NULL) {
98 		oce_log(dev, CE_WARN, MOD_CONFIG,
99 		    "EQ ring alloc failed:0x%p",
100 		    (void *)eq->ring);
101 		kmem_free(eq, sizeof (struct oce_eq));
102 		return (NULL);
103 	}
104 
105 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
106 	    MBX_SUBSYSTEM_COMMON,
107 	    OPCODE_CREATE_COMMON_EQ, MBX_TIMEOUT_SEC,
108 	    sizeof (struct mbx_create_common_eq));
109 
110 	fwcmd->params.req.num_pages = eq->ring->dbuf->num_pages;
111 	oce_page_list(eq->ring->dbuf, &fwcmd->params.req.pages[0],
112 	    eq->ring->dbuf->num_pages);
113 
114 	/* dw 0 */
115 	fwcmd->params.req.eq_ctx.size = (item_size == 4) ? 0 : 1;
116 	fwcmd->params.req.eq_ctx.valid = 1;
117 	/* dw 1 */
118 	fwcmd->params.req.eq_ctx.armed = 0;
119 	fwcmd->params.req.eq_ctx.pd = 0;
120 	fwcmd->params.req.eq_ctx.count = OCE_LOG2(q_len/256);
121 
122 	/* dw 2 */
123 	fwcmd->params.req.eq_ctx.function = dev->fn;
124 	fwcmd->params.req.eq_ctx.nodelay  = 0;
125 	fwcmd->params.req.eq_ctx.phase = 0;
126 	/* todo: calculate multiplier from max min and cur */
127 	fwcmd->params.req.eq_ctx.delay_mult = eq_delay;
128 
129 	/* fill rest of mbx */
130 	mbx.u0.s.embedded = 1;
131 	mbx.payload_length = sizeof (struct mbx_create_common_eq);
132 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
133 
134 	/* now post the command */
135 	ret = oce_mbox_post(dev, &mbx, NULL);
136 
137 	if (ret != 0) {
138 		oce_log(dev, CE_WARN, MOD_CONFIG,
139 		    "EQ create failed: %d", ret);
140 		destroy_ring_buffer(dev, eq->ring);
141 		kmem_free(eq, sizeof (struct oce_eq));
142 		return (NULL);
143 	}
144 
145 	/* interpret the response */
146 	eq->eq_id = LE_16(fwcmd->params.rsp.eq_id);
147 	eq->eq_cfg.q_len = q_len;
148 	eq->eq_cfg.item_size = item_size;
149 	eq->eq_cfg.cur_eqd = (uint8_t)eq_delay;
150 	eq->parent = (void *)dev;
151 	atomic_inc_32(&dev->neqs);
152 	oce_log(dev, CE_NOTE, MOD_CONFIG,
153 	    "EQ created, eq=0x%p eq_id=0x%x", (void *)eq, eq->eq_id);
154 	/* Save the eq pointer */
155 	return (eq);
156 } /* oce_eq_create */
157 
158 /*
159  * function to delete an event queue
160  *
161  * dev - software handle to the device
162  * eq - handle to the eq to be deleted
163  *
164  * return 0=>success, failure otherwise
165  */
166 void
167 oce_eq_del(struct oce_dev *dev, struct oce_eq *eq)
168 {
169 	struct oce_mbx mbx;
170 	struct mbx_destroy_common_eq *fwcmd;
171 
172 	/* drain the residual events */
173 	oce_drain_eq(eq);
174 
175 	/* destroy the ring */
176 	destroy_ring_buffer(dev, eq->ring);
177 	eq->ring = NULL;
178 
179 	/* send a command to delete the EQ */
180 	fwcmd = (struct mbx_destroy_common_eq *)&mbx.payload;
181 	fwcmd->params.req.id = eq->eq_id;
182 	(void) oce_destroy_q(dev, &mbx,
183 	    sizeof (struct mbx_destroy_common_eq),
184 	    QTYPE_EQ);
185 	kmem_free(eq, sizeof (struct oce_eq));
186 	atomic_dec_32(&dev->neqs);
187 }
188 
189 /*
190  * function to create a completion queue
191  *
192  * dev - software handle to the device
193  * eq - optional eq to be associated with to the cq
194  * cqcfg - configuration for this queue
195  *
196  * return pointer to the cq created. NULL on failure
197  */
198 struct oce_cq *
199 oce_cq_create(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len,
200     uint32_t item_size, boolean_t sol_event, boolean_t is_eventable,
201     boolean_t nodelay, uint32_t ncoalesce)
202 {
203 	struct oce_cq *cq = NULL;
204 	struct oce_mbx mbx;
205 	struct mbx_create_common_cq *fwcmd;
206 	int ret = 0;
207 
208 	/* create cq */
209 	cq = kmem_zalloc(sizeof (struct oce_cq), KM_NOSLEEP);
210 	if (cq == NULL) {
211 		oce_log(dev, CE_NOTE, MOD_CONFIG, "%s",
212 		    "CQ allocation failed");
213 		return (NULL);
214 	}
215 
216 	/* create the ring buffer for this queue */
217 	cq->ring = create_ring_buffer(dev, q_len,
218 	    item_size, DDI_DMA_CONSISTENT);
219 	if (cq->ring == NULL) {
220 		oce_log(dev, CE_WARN, MOD_CONFIG,
221 		    "CQ ring alloc failed:0x%p",
222 		    (void *)cq->ring);
223 		kmem_free(cq, sizeof (struct oce_cq));
224 		return (NULL);
225 	}
226 	/* initialize mailbox */
227 	bzero(&mbx, sizeof (struct oce_mbx));
228 	fwcmd = (struct mbx_create_common_cq *)&mbx.payload;
229 
230 	/* fill the command header */
231 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
232 	    MBX_SUBSYSTEM_COMMON,
233 	    OPCODE_CREATE_COMMON_CQ, MBX_TIMEOUT_SEC,
234 	    sizeof (struct mbx_create_common_cq));
235 
236 	/* fill command context */
237 	/* dw0 */
238 	fwcmd->params.req.cq_ctx.eventable = is_eventable;
239 	fwcmd->params.req.cq_ctx.sol_event = sol_event;
240 	fwcmd->params.req.cq_ctx.valid = 1;
241 	fwcmd->params.req.cq_ctx.count = OCE_LOG2(q_len/256);
242 	fwcmd->params.req.cq_ctx.nodelay = nodelay;
243 	fwcmd->params.req.cq_ctx.coalesce_wm = ncoalesce;
244 
245 	/* dw1 */
246 	fwcmd->params.req.cq_ctx.armed = B_FALSE;
247 	fwcmd->params.req.cq_ctx.eq_id = eq->eq_id;
248 	fwcmd->params.req.cq_ctx.pd = 0;
249 	/* dw2 */
250 	fwcmd->params.req.cq_ctx.function = dev->fn;
251 
252 	/* fill the rest of the command */
253 	fwcmd->params.req.num_pages = cq->ring->dbuf->num_pages;
254 	oce_page_list(cq->ring->dbuf, &fwcmd->params.req.pages[0],
255 	    cq->ring->dbuf->num_pages);
256 
257 	/* fill rest of mbx */
258 	mbx.u0.s.embedded = 1;
259 	mbx.payload_length = sizeof (struct mbx_create_common_cq);
260 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
261 
262 	/* now send the mail box */
263 	ret = oce_mbox_post(dev, &mbx, NULL);
264 
265 	if (ret != 0) {
266 		oce_log(dev, CE_WARN, MOD_CONFIG,
267 		    "CQ create failed: 0x%x", ret);
268 		destroy_ring_buffer(dev, cq->ring);
269 		kmem_free(cq, sizeof (struct oce_cq));
270 		return (NULL);
271 	}
272 
273 	cq->parent = dev;
274 	cq->eq = eq; /* eq array index */
275 	cq->cq_cfg.q_len = q_len;
276 	cq->cq_cfg.item_size = item_size;
277 	cq->cq_cfg.sol_eventable = (uint8_t)sol_event;
278 	cq->cq_cfg.nodelay = (uint8_t)nodelay;
279 	/* interpret the response */
280 	cq->cq_id = LE_16(fwcmd->params.rsp.cq_id);
281 	dev->cq[cq->cq_id] = cq;
282 	atomic_inc_32(&eq->ref_count);
283 	return (cq);
284 } /* oce_cq_create */
285 
286 /*
287  * function to delete a completion queue
288  *
289  * dev - software handle to the device
290  * cq - handle to the CQ to delete
291  *
292  * return none
293  */
294 static void
295 oce_cq_del(struct oce_dev *dev, struct oce_cq *cq)
296 {
297 	struct oce_mbx mbx;
298 	struct mbx_destroy_common_cq *fwcmd;
299 
300 	/* destroy the ring */
301 	destroy_ring_buffer(dev, cq->ring);
302 	cq->ring = NULL;
303 
304 	bzero(&mbx, sizeof (struct oce_mbx));
305 	/* send a command to delete the CQ */
306 	fwcmd = (struct mbx_destroy_common_cq *)&mbx.payload;
307 	fwcmd->params.req.id = cq->cq_id;
308 	(void) oce_destroy_q(dev, &mbx,
309 	    sizeof (struct mbx_destroy_common_cq),
310 	    QTYPE_CQ);
311 
312 	/* Reset the handler */
313 	cq->cq_handler = NULL;
314 	dev->cq[cq->cq_id] = NULL;
315 	atomic_dec_32(&cq->eq->ref_count);
316 	mutex_destroy(&cq->lock);
317 
318 	/* release the eq */
319 	kmem_free(cq, sizeof (struct oce_cq));
320 } /* oce_cq_del */
321 
322 /*
323  * function to create an MQ
324  *
325  * dev - software handle to the device
326  * eq - the EQ to associate with the MQ for event notification
327  * q_len - the number of entries to create in the MQ
328  *
329  * return pointer to the created MQ, failure otherwise
330  */
331 struct oce_mq *
332 oce_mq_create(struct oce_dev *dev, struct oce_eq *eq, uint32_t q_len)
333 {
334 	struct oce_mbx mbx;
335 	struct mbx_create_common_mq *fwcmd;
336 	struct oce_mq *mq = NULL;
337 	int ret = 0;
338 	struct oce_cq  *cq;
339 
340 	/* Create the Completion Q */
341 	cq = oce_cq_create(dev, eq, CQ_LEN_256,
342 	    sizeof (struct oce_mq_cqe),
343 	    B_FALSE, B_TRUE, B_TRUE, 0);
344 	if (cq == NULL) {
345 		return (NULL);
346 	}
347 
348 
349 	/* allocate the mq */
350 	mq = kmem_zalloc(sizeof (struct oce_mq), KM_NOSLEEP);
351 
352 	if (mq == NULL) {
353 		goto mq_alloc_fail;
354 	}
355 
356 	bzero(&mbx, sizeof (struct oce_mbx));
357 	/* allocate mbx */
358 	fwcmd = (struct mbx_create_common_mq *)&mbx.payload;
359 
360 	/* create the ring buffer for this queue */
361 	mq->ring = create_ring_buffer(dev, q_len,
362 	    sizeof (struct oce_mbx), DDI_DMA_CONSISTENT);
363 	if (mq->ring == NULL) {
364 		oce_log(dev, CE_WARN, MOD_CONFIG,
365 		    "MQ ring alloc failed:0x%p",
366 		    (void *)mq->ring);
367 		goto mq_ring_alloc;
368 	}
369 
370 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
371 	    MBX_SUBSYSTEM_COMMON,
372 	    OPCODE_CREATE_COMMON_MQ, MBX_TIMEOUT_SEC,
373 	    sizeof (struct mbx_create_common_mq));
374 
375 	fwcmd->params.req.num_pages = mq->ring->dbuf->num_pages;
376 	oce_page_list(mq->ring->dbuf, fwcmd->params.req.pages,
377 	    mq->ring->dbuf->num_pages);
378 	fwcmd->params.req.context.u0.s.cq_id = cq->cq_id;
379 	fwcmd->params.req.context.u0.s.ring_size =
380 	    OCE_LOG2(q_len) + 1;
381 	fwcmd->params.req.context.u0.s.valid = 1;
382 	fwcmd->params.req.context.u0.s.fid = dev->fn;
383 
384 	/* fill rest of mbx */
385 	mbx.u0.s.embedded = 1;
386 	mbx.payload_length = sizeof (struct mbx_create_common_mq);
387 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
388 
389 	/* now send the mail box */
390 	ret = oce_mbox_post(dev, &mbx, NULL);
391 	if (ret != DDI_SUCCESS) {
392 		oce_log(dev, CE_WARN, MOD_CONFIG,
393 		    "MQ create failed: 0x%x", ret);
394 		goto mq_fail;
395 	}
396 
397 	/* interpret the response */
398 	mq->mq_id = LE_16(fwcmd->params.rsp.mq_id);
399 	mq->cq = cq;
400 	mq->cfg.q_len = (uint8_t)q_len;
401 	mq->cfg.eqd = 0;
402 
403 	/* fill rest of the mq */
404 	mq->parent = dev;
405 
406 	/* set the MQCQ handlers */
407 	cq->cq_handler = oce_drain_mq_cq;
408 	cq->cb_arg = (void *)mq;
409 	mutex_init(&mq->lock, NULL, MUTEX_DRIVER,
410 	    DDI_INTR_PRI(dev->intr_pri));
411 	return (mq);
412 
413 mq_fail:
414 	destroy_ring_buffer(dev, mq->ring);
415 mq_ring_alloc:
416 	kmem_free(mq, sizeof (struct oce_mq));
417 mq_alloc_fail:
418 	oce_cq_del(dev, cq);
419 	return (NULL);
420 } /* oce_mq_create */
421 
422 /*
423  * function to delete an MQ
424  *
425  * dev - software handle to the device
426  * mq - pointer to the MQ to delete
427  *
428  * return none
429  */
430 static void
431 oce_mq_del(struct oce_dev *dev, struct oce_mq *mq)
432 {
433 	struct oce_mbx mbx;
434 	struct mbx_destroy_common_mq *fwcmd;
435 
436 	/* destroy the ring */
437 	destroy_ring_buffer(dev, mq->ring);
438 	mq->ring = NULL;
439 	bzero(&mbx, sizeof (struct oce_mbx));
440 	fwcmd = (struct mbx_destroy_common_mq *)&mbx.payload;
441 	fwcmd->params.req.id = mq->mq_id;
442 	(void) oce_destroy_q(dev, &mbx,
443 	    sizeof (struct mbx_destroy_common_mq),
444 	    QTYPE_MQ);
445 	oce_cq_del(dev, mq->cq);
446 	mq->cq = NULL;
447 	mutex_destroy(&mq->lock);
448 	kmem_free(mq, sizeof (struct oce_mq));
449 } /* oce_mq_del */
450 
451 /*
452  * function to create a WQ for NIC Tx
453  *
454  * dev - software handle to the device
455  * wqcfg - configuration structure providing WQ config parameters
456  *
457  * return pointer to the WQ created. NULL on failure
458  */
459 static struct oce_wq *
460 oce_wq_init(struct oce_dev *dev,  uint32_t q_len, int wq_type)
461 {
462 	struct oce_wq *wq;
463 	char str[MAX_POOL_NAME];
464 	int ret;
465 
466 	ASSERT(dev != NULL);
467 	/* q_len must be min 256 and max 2k */
468 	if (q_len < 256 || q_len > 2048) {
469 		oce_log(dev, CE_WARN, MOD_CONFIG,
470 		    "Invalid q length. Must be "
471 		    "[256, 2000]: 0x%x", q_len);
472 		return (NULL);
473 	}
474 
475 	/* allocate wq */
476 	wq = kmem_zalloc(sizeof (struct oce_wq), KM_NOSLEEP);
477 	if (wq == NULL) {
478 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
479 		    "WQ allocation failed");
480 		return (NULL);
481 	}
482 
483 	/* Set the wq config */
484 	wq->cfg.q_len = q_len;
485 	wq->cfg.wq_type = (uint8_t)wq_type;
486 	wq->cfg.eqd = OCE_DEFAULT_WQ_EQD;
487 	wq->cfg.nbufs = 2 * wq->cfg.q_len;
488 	wq->cfg.nhdl = 2 * wq->cfg.q_len;
489 
490 	/* assign parent */
491 	wq->parent = (void *)dev;
492 
493 	/* Create the WQ Buffer pool */
494 	ret  = oce_wqb_cache_create(wq, dev->tx_bcopy_limit);
495 	if (ret != DDI_SUCCESS) {
496 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
497 		    "WQ Buffer Pool create failed ");
498 		goto wqb_fail;
499 	}
500 
501 	/* Create a pool of memory handles */
502 	ret = oce_wqm_cache_create(wq);
503 	if (ret != DDI_SUCCESS) {
504 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
505 		    "WQ MAP Handles Pool create failed ");
506 		goto wqm_fail;
507 	}
508 
509 	(void) snprintf(str, MAX_POOL_NAME, "%s%d", "oce_wqed_", dev->dev_id);
510 	wq->wqed_cache = kmem_cache_create(str, sizeof (oce_wqe_desc_t),
511 	    0, oce_wqe_desc_ctor,
512 	    oce_wqe_desc_dtor, NULL, NULL, NULL, 0);
513 	if (wq->wqed_cache == NULL) {
514 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
515 		    "WQ Packet Desc Pool create failed ");
516 		goto wqed_fail;
517 	}
518 
519 	/* create the ring buffer */
520 	wq->ring = create_ring_buffer(dev, q_len,
521 	    NIC_WQE_SIZE, DDI_DMA_CONSISTENT);
522 	if (wq->ring == NULL) {
523 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
524 		    "Failed to create WQ ring ");
525 		goto wq_ringfail;
526 	}
527 
528 	/* Initialize WQ lock */
529 	mutex_init(&wq->tx_lock, NULL, MUTEX_DRIVER,
530 	    DDI_INTR_PRI(dev->intr_pri));
531 	/* Initialize WQ lock */
532 	mutex_init(&wq->txc_lock, NULL, MUTEX_DRIVER,
533 	    DDI_INTR_PRI(dev->intr_pri));
534 	atomic_inc_32(&dev->nwqs);
535 
536 	OCE_LIST_CREATE(&wq->wqe_desc_list, DDI_INTR_PRI(dev->intr_pri));
537 	return (wq);
538 
539 wqcq_fail:
540 	destroy_ring_buffer(dev, wq->ring);
541 wq_ringfail:
542 	kmem_cache_destroy(wq->wqed_cache);
543 wqed_fail:
544 	oce_wqm_cache_destroy(wq);
545 wqm_fail:
546 	oce_wqb_cache_destroy(wq);
547 wqb_fail:
548 	kmem_free(wq, sizeof (struct oce_wq));
549 	return (NULL);
550 } /* oce_wq_create */
551 
552 /*
553  * function to delete a WQ
554  *
555  * dev - software handle to the device
556  * wq - WQ to delete
557  *
558  * return 0 => success, failure otherwise
559  */
560 static void
561 oce_wq_fini(struct oce_dev *dev, struct oce_wq *wq)
562 {
563 	/* destroy cq */
564 	oce_wqb_cache_destroy(wq);
565 	oce_wqm_cache_destroy(wq);
566 	kmem_cache_destroy(wq->wqed_cache);
567 
568 	/* Free the packet descriptor list */
569 	OCE_LIST_DESTROY(&wq->wqe_desc_list);
570 	destroy_ring_buffer(dev, wq->ring);
571 	wq->ring = NULL;
572 	/* Destroy the Mutex */
573 	mutex_destroy(&wq->tx_lock);
574 	mutex_destroy(&wq->txc_lock);
575 	kmem_free(wq, sizeof (struct oce_wq));
576 	atomic_dec_32(&dev->nwqs);
577 } /* oce_wq_del */
578 
579 
580 static int
581 oce_wq_create(struct oce_wq *wq, struct oce_eq *eq)
582 {
583 
584 	struct oce_mbx mbx;
585 	struct mbx_create_nic_wq *fwcmd;
586 	struct oce_dev *dev = wq->parent;
587 	struct oce_cq *cq;
588 	int ret;
589 
590 	/* create the CQ */
591 	cq = oce_cq_create(dev, eq, CQ_LEN_1024,
592 	    sizeof (struct oce_nic_tx_cqe),
593 	    B_FALSE, B_TRUE, B_FALSE, 3);
594 	if (cq == NULL) {
595 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
596 		    "WCCQ create failed ");
597 		return (DDI_FAILURE);
598 	}
599 	/* now fill the command */
600 	bzero(&mbx, sizeof (struct oce_mbx));
601 	fwcmd = (struct mbx_create_nic_wq *)&mbx.payload;
602 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
603 	    MBX_SUBSYSTEM_NIC,
604 	    OPCODE_CREATE_NIC_WQ, MBX_TIMEOUT_SEC,
605 	    sizeof (struct mbx_create_nic_wq));
606 
607 	fwcmd->params.req.nic_wq_type = (uint8_t)wq->cfg.wq_type;
608 	fwcmd->params.req.num_pages = wq->ring->dbuf->num_pages;
609 	oce_log(dev, CE_NOTE, MOD_CONFIG, "NUM_PAGES = 0x%d size = %lu",
610 	    (uint32_t)wq->ring->dbuf->num_pages,
611 	    wq->ring->dbuf->size);
612 
613 	/* workaround: fill 0x01 for ulp_mask in rsvd0 */
614 	fwcmd->params.req.rsvd0 = 0x01;
615 	fwcmd->params.req.wq_size = OCE_LOG2(wq->cfg.q_len) + 1;
616 	fwcmd->params.req.valid = 1;
617 	fwcmd->params.req.pd_id = 0;
618 	fwcmd->params.req.pci_function_id = dev->fn;
619 	fwcmd->params.req.cq_id = cq->cq_id;
620 
621 	oce_page_list(wq->ring->dbuf, fwcmd->params.req.pages,
622 	    wq->ring->dbuf->num_pages);
623 
624 	/* fill rest of mbx */
625 	mbx.u0.s.embedded = 1;
626 	mbx.payload_length = sizeof (struct mbx_create_nic_wq);
627 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
628 
629 	/* now post the command */
630 	ret = oce_mbox_post(dev, &mbx, NULL);
631 	if (ret != DDI_SUCCESS) {
632 		oce_log(dev, CE_WARN, MOD_CONFIG,
633 		    "WQ create failed: %d", ret);
634 		oce_cq_del(dev, cq);
635 		return (ret);
636 
637 	}
638 
639 	/* interpret the response */
640 	wq->wq_id = LE_16(fwcmd->params.rsp.wq_id);
641 	wq->qstate = QCREATED;
642 	wq->cq = cq;
643 	/* set the WQCQ handlers */
644 	wq->cq->cq_handler = oce_drain_wq_cq;
645 	wq->cq->cb_arg = (void *)wq;
646 	/* All are free to start with */
647 	wq->wq_free = wq->cfg.q_len;
648 	/* reset indicies */
649 	wq->ring->cidx = 0;
650 	wq->ring->pidx = 0;
651 	return (0);
652 }
653 
654 /*
655  * function to delete a WQ
656  *
657  * dev - software handle to the device
658  * wq - WQ to delete
659  *
660  * return none
661  */
662 static void
663 oce_wq_del(struct oce_dev *dev, struct oce_wq *wq)
664 {
665 	struct oce_mbx mbx;
666 	struct mbx_delete_nic_wq *fwcmd;
667 
668 
669 	ASSERT(dev != NULL);
670 	ASSERT(wq != NULL);
671 	if (wq->qstate == QCREATED) {
672 		bzero(&mbx, sizeof (struct oce_mbx));
673 		/* now fill the command */
674 		fwcmd = (struct mbx_delete_nic_wq *)&mbx.payload;
675 		fwcmd->params.req.wq_id = wq->wq_id;
676 		(void) oce_destroy_q(dev, &mbx,
677 		    sizeof (struct mbx_delete_nic_wq),
678 		    QTYPE_WQ);
679 		wq->qstate = QDELETED;
680 		oce_cq_del(dev, wq->cq);
681 		wq->cq = NULL;
682 	}
683 } /* oce_wq_del */
684 
685 /*
686  * function to allocate RQ resources
687  *
688  * dev - software handle to the device
689  * rqcfg - configuration structure providing RQ config parameters
690  *
691  * return pointer to the RQ created. NULL on failure
692  */
693 /* ARGSUSED */
694 static struct oce_rq *
695 oce_rq_init(struct oce_dev *dev, uint32_t q_len,
696     uint32_t frag_size, uint32_t mtu,
697     boolean_t rss)
698 {
699 
700 	struct oce_rq *rq;
701 	int ret;
702 
703 	/* validate q creation parameters */
704 	if (!OCE_LOG2(frag_size))
705 		return (NULL);
706 	if ((q_len == 0) || (q_len > 1024))
707 		return (NULL);
708 
709 	/* allocate the rq */
710 	rq = kmem_zalloc(sizeof (struct oce_rq), KM_NOSLEEP);
711 	if (rq == NULL) {
712 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
713 		    "RQ allocation failed");
714 		return (NULL);
715 	}
716 
717 	rq->cfg.q_len = q_len;
718 	rq->cfg.frag_size = frag_size;
719 	rq->cfg.mtu = mtu;
720 	rq->cfg.eqd = 0;
721 	rq->cfg.nbufs = 8 * 1024;
722 
723 	/* assign parent */
724 	rq->parent = (void *)dev;
725 
726 	/* create the cache */
727 	ret  =  oce_rqb_cache_create(rq, OCE_RQ_BUF_SIZE +
728 	    OCE_RQE_BUF_HEADROOM);
729 	if (ret != DDI_SUCCESS) {
730 		goto rqb_fail;
731 	}
732 
733 	/* create the ring buffer */
734 	rq->ring = create_ring_buffer(dev, q_len,
735 	    sizeof (struct oce_nic_rqe), DDI_DMA_CONSISTENT);
736 	if (rq->ring == NULL) {
737 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
738 		    "RQ ring create failed ");
739 		goto rq_ringfail;
740 	}
741 
742 	/* allocate mbx */
743 	rq->shadow_ring = kmem_zalloc(sizeof (struct rq_shadow_entry) *
744 	    q_len, KM_SLEEP);
745 
746 	/* Initialize the RQ lock */
747 	mutex_init(&rq->rx_lock, NULL, MUTEX_DRIVER,
748 	    DDI_INTR_PRI(dev->intr_pri));
749 	/* Initialize the recharge  lock */
750 	mutex_init(&rq->rc_lock, NULL, MUTEX_DRIVER,
751 	    DDI_INTR_PRI(dev->intr_pri));
752 	atomic_inc_32(&dev->nrqs);
753 	return (rq);
754 
755 rqcq_fail:
756 	kmem_free(rq->shadow_ring,
757 	    sizeof (struct rq_shadow_entry) * q_len);
758 	destroy_ring_buffer(dev, rq->ring);
759 rq_ringfail:
760 	oce_rqb_cache_destroy(rq);
761 rqb_fail:
762 	kmem_free(rq, sizeof (struct oce_rq));
763 	return (NULL);
764 } /* oce_rq_create */
765 
766 /*
767  * function to delete an RQ
768  *
769  * dev - software handle to the device
770  * rq - RQ to delete
771  *
772  * return none
773  */
774 static void
775 oce_rq_fini(struct oce_dev *dev, struct oce_rq *rq)
776 {
777 	/* Destroy buffer cache */
778 	oce_rqb_cache_destroy(rq);
779 	destroy_ring_buffer(dev, rq->ring);
780 	rq->ring = NULL;
781 	kmem_free(rq->shadow_ring,
782 	    sizeof (struct rq_shadow_entry) * rq->cfg.q_len);
783 	rq->shadow_ring = NULL;
784 	mutex_destroy(&rq->rx_lock);
785 	mutex_destroy(&rq->rc_lock);
786 	kmem_free(rq, sizeof (struct oce_rq));
787 	atomic_dec_32(&dev->nrqs);
788 } /* oce_rq_del */
789 
790 
791 static int
792 oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq)
793 {
794 	struct oce_mbx mbx;
795 	struct mbx_create_nic_rq *fwcmd;
796 	struct oce_dev *dev = rq->parent;
797 	struct oce_cq *cq;
798 	int ret;
799 
800 	cq = oce_cq_create(dev, eq, CQ_LEN_1024, sizeof (struct oce_nic_rx_cqe),
801 	    B_FALSE, B_TRUE, B_FALSE, 3);
802 
803 	if (cq == NULL) {
804 		return (DDI_FAILURE);
805 	}
806 
807 	/* now fill the command */
808 	bzero(&mbx, sizeof (struct oce_mbx));
809 	fwcmd = (struct mbx_create_nic_rq *)&mbx.payload;
810 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
811 	    MBX_SUBSYSTEM_NIC,
812 	    OPCODE_CREATE_NIC_RQ, MBX_TIMEOUT_SEC,
813 	    sizeof (struct mbx_create_nic_rq));
814 
815 	fwcmd->params.req.num_pages = rq->ring->dbuf->num_pages;
816 	fwcmd->params.req.frag_size = OCE_LOG2(rq->cfg.frag_size);
817 	fwcmd->params.req.cq_id = cq->cq_id;
818 	oce_page_list(rq->ring->dbuf, fwcmd->params.req.pages,
819 	    rq->ring->dbuf->num_pages);
820 
821 	fwcmd->params.req.if_id = if_id;
822 	fwcmd->params.req.max_frame_size = (uint16_t)rq->cfg.mtu;
823 	fwcmd->params.req.is_rss_queue = rq->cfg.is_rss_queue;
824 
825 	/* fill rest of mbx */
826 	mbx.u0.s.embedded = 1;
827 	mbx.payload_length = sizeof (struct mbx_create_nic_rq);
828 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
829 
830 	/* now post the command */
831 	ret = oce_mbox_post(dev, &mbx, NULL);
832 	if (ret != 0) {
833 		oce_log(dev, CE_WARN, MOD_CONFIG,
834 		    "RQ create failed: %d", ret);
835 		oce_cq_del(dev, cq);
836 		return (ret);
837 	}
838 
839 	/* interpret the response */
840 	rq->rq_id = LE_16(fwcmd->params.rsp.u0.s.rq_id);
841 	/* rq->rss_cpuid = fwcmd->params.rsp.u0.bits.rss_cpuid; */
842 	rq->cfg.if_id = if_id;
843 	rq->qstate = QCREATED;
844 	rq->cq = cq;
845 
846 	/* set the Completion Handler */
847 	rq->cq->cq_handler = oce_drain_rq_cq;
848 	rq->cq->cb_arg  = (void *)rq;
849 	/* reset the indicies */
850 	rq->ring->cidx = 0;
851 	rq->ring->pidx = 0;
852 	rq->buf_avail = 0;
853 	return (0);
854 
855 }
856 
857 /*
858  * function to delete an RQ
859  *
860  * dev - software handle to the device
861  * rq - RQ to delete
862  *
863  * return none
864  */
865 static void
866 oce_rq_del(struct oce_dev *dev, struct oce_rq *rq)
867 {
868 	struct oce_mbx mbx;
869 	struct mbx_delete_nic_rq *fwcmd;
870 
871 	ASSERT(dev != NULL);
872 	ASSERT(rq != NULL);
873 
874 	bzero(&mbx, sizeof (struct oce_mbx));
875 
876 	/* delete the Queue  */
877 	if (rq->qstate == QCREATED) {
878 		fwcmd = (struct mbx_delete_nic_rq *)&mbx.payload;
879 		fwcmd->params.req.rq_id = rq->rq_id;
880 		(void) oce_destroy_q(dev, &mbx,
881 		    sizeof (struct mbx_delete_nic_rq), QTYPE_RQ);
882 		rq->qstate = QDELETED;
883 		oce_clean_rq(rq);
884 		/* Delete the associated CQ */
885 		oce_cq_del(dev, rq->cq);
886 		rq->cq = NULL;
887 		/* free up the posted buffers */
888 		oce_rq_discharge(dev->rq[0]);
889 	}
890 } /* oce_rq_del */
891 
892 /*
893  * function to arm an EQ so that it can generate events
894  *
895  * dev - software handle to the device
896  * qid - id of the EQ returned by the fw at the time of creation
897  * npopped - number of EQEs to arm with
898  * rearm - rearm bit
899  * clearint - bit to clear the interrupt condition because of which
900  *	EQEs are generated
901  *
902  * return none
903  */
904 void
905 oce_arm_eq(struct oce_dev *dev, int16_t qid, int npopped,
906     boolean_t rearm, boolean_t clearint)
907 {
908 	eq_db_t eq_db = {0};
909 
910 	eq_db.bits.rearm = rearm;
911 	eq_db.bits.event  = B_TRUE;
912 	eq_db.bits.num_popped = npopped;
913 	eq_db.bits.clrint = clearint;
914 	eq_db.bits.qid = qid;
915 	OCE_DB_WRITE32(dev, PD_EQ_DB, eq_db.dw0);
916 	if (oce_fm_check_acc_handle(dev, dev->db_handle) != DDI_FM_OK) {
917 		ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
918 	}
919 }
920 
921 /*
922  * function to arm a CQ with CQEs
923  *
924  * dev - software handle to the device
925  * qid - the id of the CQ returned by the fw at the time of creation
926  * npopped - number of CQEs to arm with
927  * rearm - rearm bit enable/disable
928  *
929  * return none
930  */
931 void
932 oce_arm_cq(struct oce_dev *dev, int16_t qid, int npopped,
933     boolean_t rearm)
934 {
935 	cq_db_t cq_db = {0};
936 	cq_db.bits.rearm = rearm;
937 	cq_db.bits.num_popped = npopped;
938 	cq_db.bits.event = 0;
939 	cq_db.bits.qid = qid;
940 	OCE_DB_WRITE32(dev, PD_CQ_DB, cq_db.dw0);
941 	if (oce_fm_check_acc_handle(dev, dev->db_handle) != DDI_FM_OK) {
942 		ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
943 	}
944 }
945 
946 
947 /*
948  * function to delete a EQ, CQ, MQ, WQ or RQ
949  *
950  * dev - sofware handle to the device
951  * mbx - mbox command to send to the fw to delete the queue
952  *	mbx contains the queue information to delete
953  * req_size - the size of the mbx payload dependent on the qtype
954  * qtype - the type of queue i.e. EQ, CQ, MQ, WQ or RQ
955  *
956  * return DDI_SUCCESS => success, failure otherwise
957  */
958 int
959 oce_destroy_q(struct oce_dev *dev, struct oce_mbx  *mbx, size_t req_size,
960     enum qtype qtype)
961 {
962 	struct mbx_hdr *hdr = (struct mbx_hdr *)&mbx->payload;
963 	int opcode;
964 	int subsys;
965 	int ret;
966 
967 	switch (qtype) {
968 	case QTYPE_EQ: {
969 		opcode = OPCODE_DESTROY_COMMON_EQ;
970 		subsys = MBX_SUBSYSTEM_COMMON;
971 		break;
972 	}
973 	case QTYPE_CQ: {
974 		opcode = OPCODE_DESTROY_COMMON_CQ;
975 		subsys = MBX_SUBSYSTEM_COMMON;
976 		break;
977 	}
978 	case QTYPE_MQ: {
979 		opcode = OPCODE_DESTROY_COMMON_MQ;
980 		subsys = MBX_SUBSYSTEM_COMMON;
981 		break;
982 	}
983 	case QTYPE_WQ: {
984 		opcode = OPCODE_DELETE_NIC_WQ;
985 		subsys = MBX_SUBSYSTEM_NIC;
986 		break;
987 	}
988 	case QTYPE_RQ: {
989 		opcode = OPCODE_DELETE_NIC_RQ;
990 		subsys = MBX_SUBSYSTEM_NIC;
991 		break;
992 	}
993 	default: {
994 		ASSERT(0);
995 		break;
996 	}
997 	}
998 
999 	mbx_common_req_hdr_init(hdr, 0, 0, subsys,
1000 	    opcode, MBX_TIMEOUT_SEC, req_size);
1001 
1002 	/* fill rest of mbx */
1003 	mbx->u0.s.embedded = 1;
1004 	mbx->payload_length = (uint32_t)req_size;
1005 	DW_SWAP(u32ptr(mbx), mbx->payload_length + OCE_BMBX_RHDR_SZ);
1006 
1007 	/* send command */
1008 	ret = oce_mbox_post(dev, mbx, NULL);
1009 
1010 	if (ret != 0) {
1011 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
1012 		    "Failed to del q ");
1013 	}
1014 	return (ret);
1015 }
1016 
1017 /*
1018  * function to set the delay parameter in the EQ for interrupt coalescing
1019  *
1020  * dev - software handle to the device
1021  * eq_arr - array of EQ ids to delete
1022  * eq_cnt - number of elements in eq_arr
1023  * eq_delay - delay parameter
1024  *
1025  * return DDI_SUCCESS => success, failure otherwise
1026  */
1027 int
1028 oce_set_eq_delay(struct oce_dev *dev, uint32_t *eq_arr,
1029     uint32_t eq_cnt, uint32_t eq_delay)
1030 {
1031 	struct oce_mbx mbx;
1032 	struct mbx_modify_common_eq_delay *fwcmd;
1033 	int ret;
1034 	int neq;
1035 
1036 	bzero(&mbx, sizeof (struct oce_mbx));
1037 	fwcmd = (struct mbx_modify_common_eq_delay *)&mbx.payload;
1038 
1039 	/* fill the command */
1040 	fwcmd->params.req.num_eq = eq_cnt;
1041 	for (neq = 0; neq < eq_cnt; neq++) {
1042 		fwcmd->params.req.delay[neq].eq_id = eq_arr[neq];
1043 		fwcmd->params.req.delay[neq].phase = 0;
1044 		fwcmd->params.req.delay[neq].dm = eq_delay;
1045 
1046 	}
1047 
1048 	/* initialize the ioctl header */
1049 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1050 	    MBX_SUBSYSTEM_COMMON,
1051 	    OPCODE_MODIFY_COMMON_EQ_DELAY,
1052 	    MBX_TIMEOUT_SEC,
1053 	    sizeof (struct mbx_modify_common_eq_delay));
1054 
1055 	/* fill rest of mbx */
1056 	mbx.u0.s.embedded = 1;
1057 	mbx.payload_length = sizeof (struct mbx_modify_common_eq_delay);
1058 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1059 
1060 	/* post the command */
1061 	ret = oce_mbox_post(dev, &mbx, NULL);
1062 	if (ret != 0) {
1063 		oce_log(dev, CE_WARN, MOD_CONFIG,
1064 		    "Failed to set EQ delay %d", ret);
1065 	}
1066 
1067 	return (ret);
1068 } /* oce_set_eq_delay */
1069 
1070 /*
1071  * function to cleanup the eqs used during stop
1072  *
1073  * eq - pointer to event queue structure
1074  *
1075  * return none
1076  */
1077 void
1078 oce_drain_eq(struct oce_eq *eq)
1079 {
1080 	struct oce_eqe *eqe;
1081 	uint16_t num_eqe = 0;
1082 	struct oce_dev *dev;
1083 
1084 	dev = eq->parent;
1085 	/* get the first item in eq to process */
1086 	eqe = RING_GET_CONSUMER_ITEM_VA(eq->ring, struct oce_eqe);
1087 
1088 	while (eqe->u0.dw0) {
1089 		eqe->u0.dw0 = LE_32(eqe->u0.dw0);
1090 
1091 		/* clear valid bit */
1092 		eqe->u0.dw0 = 0;
1093 
1094 		/* process next eqe */
1095 		RING_GET(eq->ring, 1);
1096 
1097 		eqe = RING_GET_CONSUMER_ITEM_VA(eq->ring, struct oce_eqe);
1098 		num_eqe++;
1099 	} /* for all EQEs */
1100 	if (num_eqe) {
1101 		oce_arm_eq(dev, eq->eq_id, num_eqe, B_FALSE, B_TRUE);
1102 	}
1103 } /* oce_drain_eq */
1104 
1105 
1106 int
1107 oce_init_txrx(struct oce_dev  *dev)
1108 {
1109 	dev->wq[0] = oce_wq_init(dev, dev->tx_ring_size, NIC_WQ_TYPE_STANDARD);
1110 
1111 	if (dev->wq[0] == NULL) {
1112 		goto queue_fail;
1113 	}
1114 
1115 	dev->rq[0] = oce_rq_init(dev, dev->rx_ring_size, OCE_RQ_BUF_SIZE,
1116 	    OCE_RQ_MAX_FRAME_SZ, B_FALSE);
1117 	if (dev->rq[0] == NULL) {
1118 		goto queue_fail;
1119 	}
1120 	return (DDI_SUCCESS);
1121 queue_fail:
1122 	oce_fini_txrx(dev);
1123 	return (DDI_FAILURE);
1124 }
1125 void
1126 oce_fini_txrx(struct oce_dev *dev)
1127 {
1128 	if (dev->wq[0] != NULL) {
1129 		oce_wq_fini(dev, dev->wq[0]);
1130 		dev->wq[0] = NULL;
1131 	}
1132 	if (dev->rq[0] != NULL) {
1133 		oce_rq_fini(dev, dev->rq[0]);
1134 		dev->rq[0] = NULL;
1135 	}
1136 	return;
1137 
1138 }
1139 
1140 int
1141 oce_create_queues(struct oce_dev *dev)
1142 {
1143 
1144 	int i;
1145 	struct oce_eq *eq;
1146 	struct oce_mq *mq;
1147 
1148 	for (i = 0; i < dev->num_vectors; i++) {
1149 		eq = oce_eq_create(dev, EQ_LEN_1024, EQE_SIZE_4, 0);
1150 		if (eq == NULL) {
1151 			goto rings_fail;
1152 		}
1153 		dev->eq[i] = eq;
1154 	}
1155 	if (oce_wq_create(dev->wq[0], dev->eq[0]) != 0)
1156 		goto rings_fail;
1157 	if (oce_rq_create(dev->rq[0], dev->if_id,
1158 	    dev->neqs > 1 ? dev->eq[1] : dev->eq[0]) != 0)
1159 		goto rings_fail;
1160 	mq = oce_mq_create(dev, dev->eq[0], 64);
1161 	if (mq == NULL)
1162 		goto rings_fail;
1163 	dev->mq = mq;
1164 	return (DDI_SUCCESS);
1165 rings_fail:
1166 	oce_delete_queues(dev);
1167 	return (DDI_FAILURE);
1168 
1169 }
1170 
1171 void
1172 oce_delete_queues(struct oce_dev *dev)
1173 {
1174 	int i;
1175 	if (dev->mq != NULL) {
1176 		oce_mq_del(dev, dev->mq);
1177 		dev->mq = NULL;
1178 	}
1179 
1180 	for (i = 0; i < dev->nrqs; i++) {
1181 		oce_rq_del(dev, dev->rq[i]);
1182 	}
1183 	for (i = 0; i < dev->nwqs; i++) {
1184 		oce_wq_del(dev, dev->wq[i]);
1185 	}
1186 	/* create as many eqs as the number of vectors */
1187 	for (i = 0; i < dev->num_vectors; i++) {
1188 		oce_eq_del(dev, dev->eq[i]);
1189 		dev->eq[i] = NULL;
1190 	}
1191 }
1192