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