xref: /freebsd/sys/dev/oce/oce_queue.c (revision 9bd3250a02c34dea617b02eff5970004d4eb7fc0)
1 /*-
2  * Copyright (C) 2012 Emulex
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the Emulex Corporation nor the names of its
16  *    contributors may be used to endorse or promote products derived from
17  *    this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  * Contact Information:
32  * freebsd-drivers@emulex.com
33  *
34  * Emulex
35  * 3333 Susan Street
36  * Costa Mesa, CA 92626
37  */
38 
39 /* $FreeBSD$ */
40 
41 #include "oce_if.h"
42 
43 /*****************************************************
44  * local queue functions
45  *****************************************************/
46 
47 static struct oce_wq *oce_wq_init(POCE_SOFTC sc,
48 				  uint32_t q_len, uint32_t wq_type);
49 static int oce_wq_create(struct oce_wq *wq, struct oce_eq *eq);
50 static void oce_wq_free(struct oce_wq *wq);
51 static void oce_wq_del(struct oce_wq *wq);
52 static struct oce_rq *oce_rq_init(POCE_SOFTC sc,
53 				  uint32_t q_len,
54 				  uint32_t frag_size,
55 				  uint32_t mtu, uint32_t rss);
56 static int oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq);
57 static void oce_rq_free(struct oce_rq *rq);
58 static void oce_rq_del(struct oce_rq *rq);
59 static struct oce_eq *oce_eq_create(POCE_SOFTC sc,
60 				    uint32_t q_len,
61 				    uint32_t item_size,
62 				    uint32_t eq_delay,
63 				    uint32_t vector);
64 static void oce_eq_del(struct oce_eq *eq);
65 static struct oce_mq *oce_mq_create(POCE_SOFTC sc,
66 				    struct oce_eq *eq, uint32_t q_len);
67 static void oce_mq_free(struct oce_mq *mq);
68 static int oce_destroy_q(POCE_SOFTC sc, struct oce_mbx
69 			 *mbx, size_t req_size, enum qtype qtype);
70 struct oce_cq *oce_cq_create(POCE_SOFTC sc,
71 			     struct oce_eq *eq,
72 			     uint32_t q_len,
73 			     uint32_t item_size,
74 			     uint32_t sol_event,
75 			     uint32_t is_eventable,
76 			     uint32_t nodelay, uint32_t ncoalesce);
77 static void oce_cq_del(POCE_SOFTC sc, struct oce_cq *cq);
78 
79 
80 
81 /**
82  * @brief	Create and initialize all the queues on the board
83  * @param sc	software handle to the device
84  * @returns 0	if successful, or error
85  **/
86 int
87 oce_queue_init_all(POCE_SOFTC sc)
88 {
89 	int rc = 0, i, vector;
90 	struct oce_wq *wq;
91 	struct oce_rq *rq;
92 
93 	/* alloc TX/RX queues */
94 	for_all_wq_queues(sc, wq, i) {
95 		sc->wq[i] = oce_wq_init(sc, sc->tx_ring_size,
96 					 NIC_WQ_TYPE_STANDARD);
97 		if (!sc->wq[i])
98 			goto error;
99 
100 	}
101 
102 	for_all_rq_queues(sc, rq, i) {
103 		sc->rq[i] = oce_rq_init(sc, sc->rx_ring_size, sc->rq_frag_size,
104 					OCE_MAX_JUMBO_FRAME_SIZE,
105 					(i == 0) ? 0 : sc->rss_enable);
106 		if (!sc->rq[i])
107 			goto error;
108 	}
109 
110 	/* Create network interface on card */
111 	if (oce_create_nw_interface(sc))
112 		goto error;
113 
114 	/* create all of the event queues */
115 	for (vector = 0; vector < sc->intr_count; vector++) {
116 		sc->eq[vector] = oce_eq_create(sc, EQ_LEN_1024, EQE_SIZE_4,
117 						 0, vector);
118 		if (!sc->eq[vector])
119 			goto error;
120 	}
121 
122 	/* create Tx, Rx and mcc queues */
123 	for_all_wq_queues(sc, wq, i) {
124 		rc = oce_wq_create(wq, sc->eq[i]);
125 		if (rc)
126 			goto error;
127 		wq->queue_index = i;
128 		TASK_INIT(&wq->txtask, 1, oce_tx_task, wq);
129 	}
130 
131 	for_all_rq_queues(sc, rq, i) {
132 		rc = oce_rq_create(rq, sc->if_id,
133 					sc->eq[(i == 0) ? 0:(i-1)]);
134 		if (rc)
135 			goto error;
136 		rq->queue_index = i;
137 	}
138 
139 	sc->mq = oce_mq_create(sc, sc->eq[0], 64);
140 	if (!sc->mq)
141 		goto error;
142 
143 	return rc;
144 
145 error:
146 	oce_queue_release_all(sc);
147 	return 1;
148 }
149 
150 
151 
152 /**
153  * @brief Releases all mailbox queues created
154  * @param sc		software handle to the device
155  */
156 void
157 oce_queue_release_all(POCE_SOFTC sc)
158 {
159 	int i = 0;
160 	struct oce_wq *wq;
161 	struct oce_rq *rq;
162 	struct oce_eq *eq;
163 
164 	for_all_rq_queues(sc, rq, i) {
165 		if (rq) {
166 			oce_rq_del(sc->rq[i]);
167 			oce_rq_free(sc->rq[i]);
168 		}
169 	}
170 
171 	for_all_wq_queues(sc, wq, i) {
172 		if (wq) {
173 			oce_wq_del(sc->wq[i]);
174 			oce_wq_free(sc->wq[i]);
175 		}
176 	}
177 
178 	if (sc->mq)
179 		oce_mq_free(sc->mq);
180 
181 	for_all_evnt_queues(sc, eq, i) {
182 		if (eq)
183 			oce_eq_del(sc->eq[i]);
184 	}
185 }
186 
187 
188 
189 /**
190  * @brief 		Function to create a WQ for NIC Tx
191  * @param sc 		software handle to the device
192  * @param qlen		number of entries in the queue
193  * @param wq_type	work queue type
194  * @returns		the pointer to the WQ created or NULL on failure
195  */
196 static struct
197 oce_wq *oce_wq_init(POCE_SOFTC sc, uint32_t q_len, uint32_t wq_type)
198 {
199 	struct oce_wq *wq;
200 	int rc = 0, i;
201 
202 	/* q_len must be min 256 and max 2k */
203 	if (q_len < 256 || q_len > 2048) {
204 		device_printf(sc->dev,
205 			  "Invalid q length. Must be "
206 			  "[256, 2000]: 0x%x\n", q_len);
207 		return NULL;
208 	}
209 
210 	/* allocate wq */
211 	wq = malloc(sizeof(struct oce_wq), M_DEVBUF, M_NOWAIT | M_ZERO);
212 	if (!wq)
213 		return NULL;
214 
215 	/* Set the wq config */
216 	wq->cfg.q_len = q_len;
217 	wq->cfg.wq_type = (uint8_t) wq_type;
218 	wq->cfg.eqd = OCE_DEFAULT_WQ_EQD;
219 	wq->cfg.nbufs = 2 * wq->cfg.q_len;
220 	wq->cfg.nhdl = 2 * wq->cfg.q_len;
221 
222 	wq->parent = (void *)sc;
223 
224 	rc = bus_dma_tag_create(bus_get_dma_tag(sc->dev),
225 				1, 0,
226 				BUS_SPACE_MAXADDR,
227 				BUS_SPACE_MAXADDR,
228 				NULL, NULL,
229 				OCE_MAX_TX_SIZE,
230 				OCE_MAX_TX_ELEMENTS,
231 				PAGE_SIZE, 0, NULL, NULL, &wq->tag);
232 
233 	if (rc)
234 		goto free_wq;
235 
236 
237 	for (i = 0; i < OCE_WQ_PACKET_ARRAY_SIZE; i++) {
238 		rc = bus_dmamap_create(wq->tag, 0, &wq->pckts[i].map);
239 		if (rc)
240 			goto free_wq;
241 	}
242 
243 	wq->ring = oce_create_ring_buffer(sc, q_len, NIC_WQE_SIZE);
244 	if (!wq->ring)
245 		goto free_wq;
246 
247 
248 	LOCK_CREATE(&wq->tx_lock, "TX_lock");
249 
250 #if __FreeBSD_version >= 800000
251 	/* Allocate buf ring for multiqueue*/
252 	wq->br = buf_ring_alloc(4096, M_DEVBUF,
253 			M_WAITOK, &wq->tx_lock.mutex);
254 	if (!wq->br)
255 		goto free_wq;
256 #endif
257 	return wq;
258 
259 
260 free_wq:
261 	device_printf(sc->dev, "Create WQ failed\n");
262 	oce_wq_free(wq);
263 	return NULL;
264 }
265 
266 
267 
268 /**
269  * @brief 		Frees the work queue
270  * @param wq		pointer to work queue to free
271  */
272 static void
273 oce_wq_free(struct oce_wq *wq)
274 {
275 	POCE_SOFTC sc = (POCE_SOFTC) wq->parent;
276 	int i;
277 
278 	taskqueue_drain(taskqueue_swi, &wq->txtask);
279 
280 	if (wq->ring != NULL) {
281 		oce_destroy_ring_buffer(sc, wq->ring);
282 		wq->ring = NULL;
283 	}
284 
285 	for (i = 0; i < OCE_WQ_PACKET_ARRAY_SIZE; i++) {
286 		if (wq->pckts[i].map != NULL) {
287 			bus_dmamap_unload(wq->tag, wq->pckts[i].map);
288 			bus_dmamap_destroy(wq->tag, wq->pckts[i].map);
289 			wq->pckts[i].map = NULL;
290 		}
291 	}
292 
293 	if (wq->tag != NULL)
294 		bus_dma_tag_destroy(wq->tag);
295 	if (wq->br != NULL)
296 		buf_ring_free(wq->br, M_DEVBUF);
297 
298 	LOCK_DESTROY(&wq->tx_lock);
299 	free(wq, M_DEVBUF);
300 }
301 
302 
303 
304 /**
305  * @brief 		Create a work queue
306  * @param wq		pointer to work queue
307  * @param eq		pointer to associated event queue
308  */
309 static int
310 oce_wq_create(struct oce_wq *wq, struct oce_eq *eq)
311 {
312 	POCE_SOFTC sc = wq->parent;
313 	struct oce_cq *cq;
314 	int rc = 0;
315 
316 	/* create the CQ */
317 	cq = oce_cq_create(sc,
318 			   eq,
319 			   CQ_LEN_1024,
320 			   sizeof(struct oce_nic_tx_cqe), 0, 1, 0, 3);
321 	if (!cq)
322 		return ENXIO;
323 
324 
325 	wq->cq = cq;
326 
327 	rc = oce_mbox_create_wq(wq);
328 	if (rc)
329 		goto error;
330 
331 	wq->qstate = QCREATED;
332 	wq->wq_free = wq->cfg.q_len;
333 	wq->ring->cidx = 0;
334 	wq->ring->pidx = 0;
335 
336 	eq->cq[eq->cq_valid] = cq;
337 	eq->cq_valid++;
338 	cq->cb_arg = wq;
339 	cq->cq_handler = oce_wq_handler;
340 
341 	return 0;
342 
343 error:
344 	device_printf(sc->dev, "WQ create failed\n");
345 	oce_wq_del(wq);
346 	return rc;
347 }
348 
349 
350 
351 
352 /**
353  * @brief 		Delete a work queue
354  * @param wq		pointer to work queue
355  */
356 static void
357 oce_wq_del(struct oce_wq *wq)
358 {
359 	struct oce_mbx mbx;
360 	struct mbx_delete_nic_wq *fwcmd;
361 	POCE_SOFTC sc = (POCE_SOFTC) wq->parent;
362 
363 	if (wq->qstate == QCREATED) {
364 		bzero(&mbx, sizeof(struct oce_mbx));
365 		/* now fill the command */
366 		fwcmd = (struct mbx_delete_nic_wq *)&mbx.payload;
367 		fwcmd->params.req.wq_id = wq->wq_id;
368 		(void)oce_destroy_q(sc, &mbx,
369 				sizeof(struct mbx_delete_nic_wq), QTYPE_WQ);
370 		wq->qstate = QDELETED;
371 	}
372 
373 	if (wq->cq != NULL) {
374 		oce_cq_del(sc, wq->cq);
375 		wq->cq = NULL;
376 	}
377 }
378 
379 
380 
381 /**
382  * @brief 		function to allocate receive queue resources
383  * @param sc		software handle to the device
384  * @param q_len		length of receive queue
385  * @param frag_size	size of an receive queue fragment
386  * @param mtu		maximum transmission unit
387  * @param rss		is-rss-queue flag
388  * @returns		the pointer to the RQ created or NULL on failure
389  */
390 static struct
391 oce_rq *oce_rq_init(POCE_SOFTC sc,
392 				  uint32_t q_len,
393 				  uint32_t frag_size,
394 				  uint32_t mtu, uint32_t rss)
395 {
396 	struct oce_rq *rq;
397 	int rc = 0, i;
398 
399 	if (OCE_LOG2(frag_size) <= 0)
400 		return NULL;
401 
402 	if ((q_len == 0) || (q_len > 1024))
403 		return NULL;
404 
405 	/* allocate the rq */
406 	rq = malloc(sizeof(struct oce_rq), M_DEVBUF, M_NOWAIT | M_ZERO);
407 	if (!rq)
408 		return NULL;
409 
410 
411 	rq->cfg.q_len = q_len;
412 	rq->cfg.frag_size = frag_size;
413 	rq->cfg.mtu = mtu;
414 	rq->cfg.eqd = 0;
415 	rq->lro_pkts_queued = 0;
416 	rq->cfg.is_rss_queue = rss;
417 	rq->packets_in = 0;
418         rq->packets_out = 0;
419         rq->pending = 0;
420 
421 	rq->parent = (void *)sc;
422 
423 	rc = bus_dma_tag_create(bus_get_dma_tag(sc->dev),
424 				1, 0,
425 				BUS_SPACE_MAXADDR,
426 				BUS_SPACE_MAXADDR,
427 				NULL, NULL,
428 				OCE_MAX_RX_SIZE,
429 				1, PAGE_SIZE, 0, NULL, NULL, &rq->tag);
430 
431 	if (rc)
432 		goto free_rq;
433 
434 	for (i = 0; i < OCE_RQ_PACKET_ARRAY_SIZE; i++) {
435 		rc = bus_dmamap_create(rq->tag, 0, &rq->pckts[i].map);
436 		if (rc)
437 			goto free_rq;
438 	}
439 
440 	/* create the ring buffer */
441 	rq->ring = oce_create_ring_buffer(sc, q_len,
442 				 sizeof(struct oce_nic_rqe));
443 	if (!rq->ring)
444 		goto free_rq;
445 
446 	LOCK_CREATE(&rq->rx_lock, "RX_lock");
447 
448 	return rq;
449 
450 free_rq:
451 	device_printf(sc->dev, "Create RQ failed\n");
452 	oce_rq_free(rq);
453 	return NULL;
454 }
455 
456 
457 
458 
459 /**
460  * @brief 		Free a receive queue
461  * @param rq		pointer to receive queue
462  */
463 static void
464 oce_rq_free(struct oce_rq *rq)
465 {
466 	POCE_SOFTC sc = (POCE_SOFTC) rq->parent;
467 	int i = 0 ;
468 
469 	if (rq->ring != NULL) {
470 		oce_destroy_ring_buffer(sc, rq->ring);
471 		rq->ring = NULL;
472 	}
473 	for (i = 0; i < OCE_RQ_PACKET_ARRAY_SIZE; i++) {
474 		if (rq->pckts[i].map != NULL) {
475 			bus_dmamap_unload(rq->tag, rq->pckts[i].map);
476 			bus_dmamap_destroy(rq->tag, rq->pckts[i].map);
477 			rq->pckts[i].map = NULL;
478 		}
479 		if (rq->pckts[i].mbuf) {
480 			m_free(rq->pckts[i].mbuf);
481 			rq->pckts[i].mbuf = NULL;
482 		}
483 	}
484 
485 	if (rq->tag != NULL)
486 		bus_dma_tag_destroy(rq->tag);
487 
488 	LOCK_DESTROY(&rq->rx_lock);
489 	free(rq, M_DEVBUF);
490 }
491 
492 
493 
494 
495 /**
496  * @brief 		Create a receive queue
497  * @param rq 		receive queue
498  * @param if_id		interface identifier index`
499  * @param eq		pointer to event queue
500  */
501 static int
502 oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq)
503 {
504 	POCE_SOFTC sc = rq->parent;
505 	struct oce_cq *cq;
506 
507 	cq = oce_cq_create(sc,
508 			   eq,
509 			   CQ_LEN_1024,
510 			   sizeof(struct oce_nic_rx_cqe), 0, 1, 0, 3);
511 	if (!cq)
512 		return ENXIO;
513 
514 	rq->cq = cq;
515 	rq->cfg.if_id = if_id;
516 
517 	/* Dont create RQ here. Create in if_activate */
518 	rq->qstate     = 0;
519 	rq->ring->cidx = 0;
520 	rq->ring->pidx = 0;
521 	eq->cq[eq->cq_valid] = cq;
522 	eq->cq_valid++;
523 	cq->cb_arg = rq;
524 	cq->cq_handler = oce_rq_handler;
525 
526 	return 0;
527 
528 }
529 
530 
531 
532 
533 /**
534  * @brief 		Delete a receive queue
535  * @param rq		receive queue
536  */
537 static void
538 oce_rq_del(struct oce_rq *rq)
539 {
540 	POCE_SOFTC sc = (POCE_SOFTC) rq->parent;
541 	struct oce_mbx mbx;
542 	struct mbx_delete_nic_rq *fwcmd;
543 
544 	if (rq->qstate == QCREATED) {
545 		bzero(&mbx, sizeof(mbx));
546 
547 		fwcmd = (struct mbx_delete_nic_rq *)&mbx.payload;
548 		fwcmd->params.req.rq_id = rq->rq_id;
549 		(void)oce_destroy_q(sc, &mbx,
550 				sizeof(struct mbx_delete_nic_rq), QTYPE_RQ);
551 		rq->qstate = QDELETED;
552 	}
553 
554 	if (rq->cq != NULL) {
555 		oce_cq_del(sc, rq->cq);
556 		rq->cq = NULL;
557 	}
558 }
559 
560 
561 
562 /**
563  * @brief		function to create an event queue
564  * @param sc		software handle to the device
565  * @param q_len		length of event queue
566  * @param item_size	size of an event queue item
567  * @param eq_delay	event queue delay
568  * @retval eq      	success, pointer to event queue
569  * @retval NULL		failure
570  */
571 static struct
572 oce_eq *oce_eq_create(POCE_SOFTC sc, uint32_t q_len,
573 				    uint32_t item_size,
574 				    uint32_t eq_delay,
575 				    uint32_t vector)
576 {
577 	struct oce_eq *eq;
578 	int rc = 0;
579 
580 	/* allocate an eq */
581 	eq = malloc(sizeof(struct oce_eq), M_DEVBUF, M_NOWAIT | M_ZERO);
582 	if (eq == NULL)
583 		return NULL;
584 
585 	eq->parent = (void *)sc;
586 	eq->eq_id = 0xffff;
587 	eq->ring = oce_create_ring_buffer(sc, q_len, item_size);
588 	if (!eq->ring)
589 		goto free_eq;
590 
591 	eq->eq_cfg.q_len = q_len;
592 	eq->eq_cfg.item_size = item_size;
593 	eq->eq_cfg.cur_eqd = (uint8_t) eq_delay;
594 
595 	rc = oce_mbox_create_eq(eq);
596 	if (rc)
597 		goto free_eq;
598 
599 	sc->intrs[sc->neqs++].eq = eq;
600 
601 	return eq;
602 
603 free_eq:
604 	oce_eq_del(eq);
605 	return NULL;
606 }
607 
608 
609 
610 
611 /**
612  * @brief 		Function to delete an event queue
613  * @param eq		pointer to an event queue
614  */
615 static void
616 oce_eq_del(struct oce_eq *eq)
617 {
618 	struct oce_mbx mbx;
619 	struct mbx_destroy_common_eq *fwcmd;
620 	POCE_SOFTC sc = (POCE_SOFTC) eq->parent;
621 
622 	if (eq->eq_id != 0xffff) {
623 		bzero(&mbx, sizeof(mbx));
624 		fwcmd = (struct mbx_destroy_common_eq *)&mbx.payload;
625 		fwcmd->params.req.id = eq->eq_id;
626 		(void)oce_destroy_q(sc, &mbx,
627 			sizeof(struct mbx_destroy_common_eq), QTYPE_EQ);
628 	}
629 
630 	if (eq->ring != NULL) {
631 		oce_destroy_ring_buffer(sc, eq->ring);
632 		eq->ring = NULL;
633 	}
634 
635 	free(eq, M_DEVBUF);
636 
637 }
638 
639 
640 
641 
642 /**
643  * @brief		Function to create an MQ
644  * @param sc		software handle to the device
645  * @param eq		the EQ to associate with the MQ for event notification
646  * @param q_len		the number of entries to create in the MQ
647  * @returns		pointer to the created MQ, failure otherwise
648  */
649 static struct oce_mq *
650 oce_mq_create(POCE_SOFTC sc, struct oce_eq *eq, uint32_t q_len)
651 {
652 	struct oce_mbx mbx;
653 	struct mbx_create_common_mq_ex *fwcmd = NULL;
654 	struct oce_mq *mq = NULL;
655 	int rc = 0;
656 	struct oce_cq *cq;
657 	oce_mq_ext_ctx_t *ctx;
658 	uint32_t num_pages;
659 	uint32_t page_size;
660 	uint32_t version;
661 
662 
663 	cq = oce_cq_create(sc, eq, CQ_LEN_256,
664 			sizeof(struct oce_mq_cqe), 1, 1, 0, 0);
665 	if (!cq)
666 		return NULL;
667 
668 	/* allocate the mq */
669 	mq = malloc(sizeof(struct oce_mq), M_DEVBUF, M_NOWAIT | M_ZERO);
670 	if (!mq) {
671 		oce_cq_del(sc, cq);
672 		goto error;
673 	}
674 
675 	mq->parent = sc;
676 
677 	mq->ring = oce_create_ring_buffer(sc, q_len, sizeof(struct oce_mbx));
678 	if (!mq->ring)
679 		goto error;
680 
681 	bzero(&mbx, sizeof(struct oce_mbx));
682 
683 	fwcmd = (struct mbx_create_common_mq_ex *)&mbx.payload;
684 	version = OCE_MBX_VER_V0;
685 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
686 				MBX_SUBSYSTEM_COMMON,
687 				OPCODE_COMMON_CREATE_MQ_EXT,
688 				MBX_TIMEOUT_SEC,
689 				sizeof(struct mbx_create_common_mq_ex),
690 				version);
691 
692 	num_pages = oce_page_list(mq->ring, &fwcmd->params.req.pages[0]);
693 	page_size = mq->ring->num_items * mq->ring->item_size;
694 
695 	ctx = &fwcmd->params.req.context;
696 	ctx->v0.num_pages = num_pages;
697 	ctx->v0.cq_id = cq->cq_id;
698 	ctx->v0.ring_size = OCE_LOG2(q_len) + 1;
699 	ctx->v0.valid = 1;
700 	/* Subscribe to Link State and Group 5 Events(bits 1 and 5 set) */
701 	ctx->v0.async_evt_bitmap = 0xffffffff;
702 
703 	mbx.u0.s.embedded = 1;
704 	mbx.payload_length = sizeof(struct mbx_create_common_mq_ex);
705 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
706 
707 	rc = oce_mbox_post(sc, &mbx, NULL);
708 	if (rc)
709 		goto error;
710 
711 	mq->mq_id = LE_16(fwcmd->params.rsp.mq_id);
712 	mq->cq = cq;
713 	eq->cq[eq->cq_valid] = cq;
714 	eq->cq_valid++;
715 	mq->cq->eq = eq;
716 	mq->cfg.q_len = (uint8_t) q_len;
717 	mq->cfg.eqd = 0;
718 	mq->qstate = QCREATED;
719 
720 	mq->cq->cb_arg = mq;
721 	mq->cq->cq_handler = oce_mq_handler;
722 
723 	return mq;
724 
725 error:
726 	device_printf(sc->dev, "MQ create failed\n");
727 	oce_mq_free(mq);
728 	mq = NULL;
729 	return mq;
730 }
731 
732 
733 
734 
735 
736 /**
737  * @brief		Function to free a mailbox queue
738  * @param mq		pointer to a mailbox queue
739  */
740 static void
741 oce_mq_free(struct oce_mq *mq)
742 {
743 	POCE_SOFTC sc = (POCE_SOFTC) mq->parent;
744 	struct oce_mbx mbx;
745 	struct mbx_destroy_common_mq *fwcmd;
746 
747 	if (!mq)
748 		return;
749 
750 	if (mq->ring != NULL) {
751 		oce_destroy_ring_buffer(sc, mq->ring);
752 		mq->ring = NULL;
753 		if (mq->qstate == QCREATED) {
754 			bzero(&mbx, sizeof (struct oce_mbx));
755 			fwcmd = (struct mbx_destroy_common_mq *)&mbx.payload;
756 			fwcmd->params.req.id = mq->mq_id;
757 			(void) oce_destroy_q(sc, &mbx,
758 				sizeof (struct mbx_destroy_common_mq),
759 				QTYPE_MQ);
760 		}
761 		mq->qstate = QDELETED;
762 	}
763 
764 	if (mq->cq != NULL) {
765 		oce_cq_del(sc, mq->cq);
766 		mq->cq = NULL;
767 	}
768 
769 	free(mq, M_DEVBUF);
770 	mq = NULL;
771 }
772 
773 
774 
775 /**
776  * @brief		Function to delete a EQ, CQ, MQ, WQ or RQ
777  * @param sc		sofware handle to the device
778  * @param mbx		mailbox command to send to the fw to delete the queue
779  *			(mbx contains the queue information to delete)
780  * @param req_size	the size of the mbx payload dependent on the qtype
781  * @param qtype		the type of queue i.e. EQ, CQ, MQ, WQ or RQ
782  * @returns 		0 on success, failure otherwise
783  */
784 static int
785 oce_destroy_q(POCE_SOFTC sc, struct oce_mbx *mbx, size_t req_size,
786 		enum qtype qtype)
787 {
788 	struct mbx_hdr *hdr = (struct mbx_hdr *)&mbx->payload;
789 	int opcode;
790 	int subsys;
791 	int rc = 0;
792 
793 	switch (qtype) {
794 	case QTYPE_EQ:
795 		opcode = OPCODE_COMMON_DESTROY_EQ;
796 		subsys = MBX_SUBSYSTEM_COMMON;
797 		break;
798 	case QTYPE_CQ:
799 		opcode = OPCODE_COMMON_DESTROY_CQ;
800 		subsys = MBX_SUBSYSTEM_COMMON;
801 		break;
802 	case QTYPE_MQ:
803 		opcode = OPCODE_COMMON_DESTROY_MQ;
804 		subsys = MBX_SUBSYSTEM_COMMON;
805 		break;
806 	case QTYPE_WQ:
807 		opcode = NIC_DELETE_WQ;
808 		subsys = MBX_SUBSYSTEM_NIC;
809 		break;
810 	case QTYPE_RQ:
811 		opcode = NIC_DELETE_RQ;
812 		subsys = MBX_SUBSYSTEM_NIC;
813 		break;
814 	default:
815 		return EINVAL;
816 	}
817 
818 	mbx_common_req_hdr_init(hdr, 0, 0, subsys,
819 				opcode, MBX_TIMEOUT_SEC, req_size,
820 				OCE_MBX_VER_V0);
821 
822 	mbx->u0.s.embedded = 1;
823 	mbx->payload_length = (uint32_t) req_size;
824 	DW_SWAP(u32ptr(mbx), mbx->payload_length + OCE_BMBX_RHDR_SZ);
825 
826 	rc = oce_mbox_post(sc, mbx, NULL);
827 
828 	if (rc != 0)
829 		device_printf(sc->dev, "Failed to del q\n");
830 
831 	return rc;
832 }
833 
834 
835 
836 /**
837  * @brief		Function to create a completion queue
838  * @param sc		software handle to the device
839  * @param eq		optional eq to be associated with to the cq
840  * @param q_len		length of completion queue
841  * @param item_size	size of completion queue items
842  * @param sol_event	command context event
843  * @param is_eventable	event table
844  * @param nodelay	no delay flag
845  * @param ncoalesce	no coalescence flag
846  * @returns 		pointer to the cq created, NULL on failure
847  */
848 struct oce_cq *
849 oce_cq_create(POCE_SOFTC sc, struct oce_eq *eq,
850 			     uint32_t q_len,
851 			     uint32_t item_size,
852 			     uint32_t sol_event,
853 			     uint32_t is_eventable,
854 			     uint32_t nodelay, uint32_t ncoalesce)
855 {
856 	struct oce_cq *cq = NULL;
857 	int rc = 0;
858 
859 	cq = malloc(sizeof(struct oce_cq), M_DEVBUF, M_NOWAIT | M_ZERO);
860 	if (!cq)
861 		return NULL;
862 
863 	cq->ring = oce_create_ring_buffer(sc, q_len, item_size);
864 	if (!cq->ring)
865 		goto error;
866 
867 	cq->parent = sc;
868 	cq->eq = eq;
869 	cq->cq_cfg.q_len = q_len;
870 	cq->cq_cfg.item_size = item_size;
871 	cq->cq_cfg.nodelay = (uint8_t) nodelay;
872 
873 	rc = oce_mbox_cq_create(cq, ncoalesce, is_eventable);
874 	if (rc)
875 		goto error;
876 
877 	sc->cq[sc->ncqs++] = cq;
878 
879 	return cq;
880 
881 error:
882 	device_printf(sc->dev, "CQ create failed\n");
883 	oce_cq_del(sc, cq);
884 	return NULL;
885 }
886 
887 
888 
889 /**
890  * @brief		Deletes the completion queue
891  * @param sc		software handle to the device
892  * @param cq		pointer to a completion queue
893  */
894 static void
895 oce_cq_del(POCE_SOFTC sc, struct oce_cq *cq)
896 {
897 	struct oce_mbx mbx;
898 	struct mbx_destroy_common_cq *fwcmd;
899 
900 	if (cq->ring != NULL) {
901 
902 		bzero(&mbx, sizeof(struct oce_mbx));
903 		/* now fill the command */
904 		fwcmd = (struct mbx_destroy_common_cq *)&mbx.payload;
905 		fwcmd->params.req.id = cq->cq_id;
906 		(void)oce_destroy_q(sc, &mbx,
907 			sizeof(struct mbx_destroy_common_cq), QTYPE_CQ);
908 		/*NOW destroy the ring */
909 		oce_destroy_ring_buffer(sc, cq->ring);
910 		cq->ring = NULL;
911 	}
912 
913 	free(cq, M_DEVBUF);
914 	cq = NULL;
915 }
916 
917 
918 
919 /**
920  * @brief		Start a receive queue
921  * @param rq		pointer to a receive queue
922  */
923 int
924 oce_start_rq(struct oce_rq *rq)
925 {
926 	int rc;
927 
928 	rc = oce_alloc_rx_bufs(rq, rq->cfg.q_len);
929 
930 	if (rc == 0)
931 		oce_arm_cq(rq->parent, rq->cq->cq_id, 0, TRUE);
932 	return rc;
933 }
934 
935 
936 
937 /**
938  * @brief		Start a work queue
939  * @param wq		pointer to a work queue
940  */
941 int
942 oce_start_wq(struct oce_wq *wq)
943 {
944 	oce_arm_cq(wq->parent, wq->cq->cq_id, 0, TRUE);
945 	return 0;
946 }
947 
948 
949 
950 /**
951  * @brief		Start a mailbox queue
952  * @param mq		pointer to a mailbox queue
953  */
954 int
955 oce_start_mq(struct oce_mq *mq)
956 {
957 	oce_arm_cq(mq->parent, mq->cq->cq_id, 0, TRUE);
958 	return 0;
959 }
960 
961 
962 
963 /**
964  * @brief		Function to arm an EQ so that it can generate events
965  * @param sc		software handle to the device
966  * @param qid		id of the EQ returned by the fw at the time of creation
967  * @param npopped	number of EQEs to arm
968  * @param rearm		rearm bit enable/disable
969  * @param clearint	bit to clear the interrupt condition because of which
970  *			EQEs are generated
971  */
972 void
973 oce_arm_eq(POCE_SOFTC sc,
974 	   int16_t qid, int npopped, uint32_t rearm, uint32_t clearint)
975 {
976 	eq_db_t eq_db = { 0 };
977 
978 	eq_db.bits.rearm = rearm;
979 	eq_db.bits.event = 1;
980 	eq_db.bits.num_popped = npopped;
981 	eq_db.bits.clrint = clearint;
982 	eq_db.bits.qid = qid;
983 	OCE_WRITE_REG32(sc, db, PD_EQ_DB, eq_db.dw0);
984 
985 }
986 
987 
988 
989 
990 /**
991  * @brief		Function to arm a CQ with CQEs
992  * @param sc		software handle to the device
993  * @param qid		id of the CQ returned by the fw at the time of creation
994  * @param npopped	number of CQEs to arm
995  * @param rearm		rearm bit enable/disable
996  */
997 void oce_arm_cq(POCE_SOFTC sc, int16_t qid, int npopped, uint32_t rearm)
998 {
999 	cq_db_t cq_db = { 0 };
1000 
1001 	cq_db.bits.rearm = rearm;
1002 	cq_db.bits.num_popped = npopped;
1003 	cq_db.bits.event = 0;
1004 	cq_db.bits.qid = qid;
1005 	OCE_WRITE_REG32(sc, db, PD_CQ_DB, cq_db.dw0);
1006 
1007 }
1008 
1009 
1010 
1011 
1012 /*
1013  * @brief		function to cleanup the eqs used during stop
1014  * @param eq		pointer to event queue structure
1015  * @returns		the number of EQs processed
1016  */
1017 void
1018 oce_drain_eq(struct oce_eq *eq)
1019 {
1020 
1021 	struct oce_eqe *eqe;
1022 	uint16_t num_eqe = 0;
1023 	POCE_SOFTC sc = eq->parent;
1024 
1025 	do {
1026 		eqe = RING_GET_CONSUMER_ITEM_VA(eq->ring, struct oce_eqe);
1027 		if (eqe->evnt == 0)
1028 			break;
1029 		eqe->evnt = 0;
1030 		bus_dmamap_sync(eq->ring->dma.tag, eq->ring->dma.map,
1031 					BUS_DMASYNC_POSTWRITE);
1032 		num_eqe++;
1033 		RING_GET(eq->ring, 1);
1034 
1035 	} while (TRUE);
1036 
1037 	oce_arm_eq(sc, eq->eq_id, num_eqe, FALSE, TRUE);
1038 
1039 }
1040 
1041 
1042 
1043 void
1044 oce_drain_wq_cq(struct oce_wq *wq)
1045 {
1046         POCE_SOFTC sc = wq->parent;
1047         struct oce_cq *cq = wq->cq;
1048         struct oce_nic_tx_cqe *cqe;
1049         int num_cqes = 0;
1050 
1051 	bus_dmamap_sync(cq->ring->dma.tag, cq->ring->dma.map,
1052 				 BUS_DMASYNC_POSTWRITE);
1053 
1054 	do {
1055 		cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_tx_cqe);
1056 		if (cqe->u0.dw[3] == 0)
1057 			break;
1058 		cqe->u0.dw[3] = 0;
1059 		bus_dmamap_sync(cq->ring->dma.tag, cq->ring->dma.map,
1060 				 BUS_DMASYNC_POSTWRITE);
1061 		RING_GET(cq->ring, 1);
1062 		num_cqes++;
1063 
1064 	} while (TRUE);
1065 
1066 	oce_arm_cq(sc, cq->cq_id, num_cqes, FALSE);
1067 
1068 }
1069 
1070 
1071 /*
1072  * @brief		function to drain a MCQ and process its CQEs
1073  * @param dev		software handle to the device
1074  * @param cq		pointer to the cq to drain
1075  * @returns		the number of CQEs processed
1076  */
1077 void
1078 oce_drain_mq_cq(void *arg)
1079 {
1080 	/* TODO: additional code. */
1081 	return;
1082 }
1083 
1084 
1085 
1086 /**
1087  * @brief		function to process a Recieve queue
1088  * @param arg		pointer to the RQ to charge
1089  * @return		number of cqes processed
1090  */
1091 void
1092 oce_drain_rq_cq(struct oce_rq *rq)
1093 {
1094 	struct oce_nic_rx_cqe *cqe;
1095 	uint16_t num_cqe = 0;
1096 	struct oce_cq  *cq;
1097 	POCE_SOFTC sc;
1098 
1099 	sc = rq->parent;
1100 	cq = rq->cq;
1101 	cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_rx_cqe);
1102 	/* dequeue till you reach an invalid cqe */
1103 	while (RQ_CQE_VALID(cqe)) {
1104 		RQ_CQE_INVALIDATE(cqe);
1105 		RING_GET(cq->ring, 1);
1106 		cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring,
1107 		    struct oce_nic_rx_cqe);
1108 		num_cqe++;
1109 	}
1110 	oce_arm_cq(sc, cq->cq_id, num_cqe, FALSE);
1111 
1112 	return;
1113 }
1114 
1115 
1116 void
1117 oce_free_posted_rxbuf(struct oce_rq *rq)
1118 {
1119 	struct oce_packet_desc *pd;
1120 
1121 	while (rq->pending) {
1122 
1123 		pd = &rq->pckts[rq->packets_out];
1124 		bus_dmamap_sync(rq->tag, pd->map, BUS_DMASYNC_POSTWRITE);
1125 		bus_dmamap_unload(rq->tag, pd->map);
1126 		if (pd->mbuf != NULL) {
1127 			m_freem(pd->mbuf);
1128 			pd->mbuf = NULL;
1129 		}
1130 
1131 		if ((rq->packets_out + 1) == OCE_RQ_PACKET_ARRAY_SIZE)
1132 			rq->packets_out = 0;
1133 		else
1134 			rq->packets_out++;
1135 
1136                 rq->pending--;
1137 	}
1138 
1139 }
1140 
1141 void
1142 oce_stop_rx(POCE_SOFTC sc)
1143 {
1144 	struct oce_mbx mbx;
1145 	struct mbx_delete_nic_rq *fwcmd;
1146 	struct oce_rq *rq;
1147 	int i = 0;
1148 
1149 	for_all_rq_queues(sc, rq, i) {
1150 		if (rq->qstate == QCREATED) {
1151 			/* Delete rxq in firmware */
1152 
1153 			bzero(&mbx, sizeof(mbx));
1154 			fwcmd = (struct mbx_delete_nic_rq *)&mbx.payload;
1155 			fwcmd->params.req.rq_id = rq->rq_id;
1156 
1157 			(void)oce_destroy_q(sc, &mbx,
1158 				sizeof(struct mbx_delete_nic_rq), QTYPE_RQ);
1159 
1160 			rq->qstate = QDELETED;
1161 
1162 			DELAY(1);
1163 
1164 			/* Free posted RX buffers that are not used */
1165 			oce_free_posted_rxbuf(rq);
1166 
1167 		}
1168 	}
1169 }
1170 
1171 
1172 
1173 int
1174 oce_start_rx(POCE_SOFTC sc)
1175 {
1176 	struct oce_rq *rq;
1177 	int rc = 0, i;
1178 
1179 	for_all_rq_queues(sc, rq, i) {
1180 		if (rq->qstate == QCREATED)
1181 			continue;
1182 		rc = oce_mbox_create_rq(rq);
1183 		if (rc)
1184 			goto error;
1185 		/* reset queue pointers */
1186 		rq->qstate 	 = QCREATED;
1187 		rq->pending	 = 0;
1188 		rq->ring->cidx	 = 0;
1189 		rq->ring->pidx	 = 0;
1190 		rq->packets_in	 = 0;
1191 		rq->packets_out	 = 0;
1192 	}
1193 
1194 	DELAY(1);
1195 
1196 	/* RSS config */
1197 	if (sc->rss_enable) {
1198 		rc = oce_config_nic_rss(sc, (uint8_t) sc->if_id, RSS_ENABLE);
1199 		if (rc)
1200 			goto error;
1201 
1202 	}
1203 
1204 	return rc;
1205 error:
1206 	device_printf(sc->dev, "Start RX failed\n");
1207 	return rc;
1208 
1209 }
1210 
1211 
1212 
1213