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