oce_queue.c revision 331722
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: stable/11/sys/dev/oce/oce_queue.c 331722 2018-03-29 02:50:57Z eadler $ */
40
41#include "oce_if.h"
42
43/*****************************************************
44 * local queue functions
45 *****************************************************/
46
47static struct oce_wq *oce_wq_init(POCE_SOFTC sc,
48				  uint32_t q_len, uint32_t wq_type);
49static int oce_wq_create(struct oce_wq *wq, struct oce_eq *eq);
50static void oce_wq_free(struct oce_wq *wq);
51static void oce_wq_del(struct oce_wq *wq);
52static 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);
56static int oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq);
57static void oce_rq_free(struct oce_rq *rq);
58static void oce_rq_del(struct oce_rq *rq);
59static 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);
64static void oce_eq_del(struct oce_eq *eq);
65static struct oce_mq *oce_mq_create(POCE_SOFTC sc,
66				    struct oce_eq *eq, uint32_t q_len);
67static void oce_mq_free(struct oce_mq *mq);
68static int oce_destroy_q(POCE_SOFTC sc, struct oce_mbx
69			 *mbx, size_t req_size, enum qtype qtype);
70struct 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);
77static 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 **/
86int
87oce_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
153error:
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 */
164void
165oce_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 */
204static struct
205oce_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
268free_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 */
280static void
281oce_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 */
317static int
318oce_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
351error:
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 */
364static void
365oce_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 */
398static struct
399oce_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
458free_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 */
471static void
472oce_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 */
509static int
510oce_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 */
545static void
546oce_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 */
579static struct
580oce_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
611free_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 */
623static void
624oce_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 */
657static struct oce_mq *
658oce_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
752error:
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 */
767static void
768oce_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 */
811static int
812oce_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 */
876struct oce_cq *
877oce_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
909error:
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 */
922static void
923oce_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 */
951int
952oce_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 */
969int
970oce_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 */
982int
983oce_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 */
1000void
1001oce_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 */
1025void 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 */
1045void
1046oce_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
1071void
1072oce_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 */
1105void
1106oce_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 */
1119void
1120oce_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
1144void
1145oce_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
1169void
1170oce_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
1201int
1202oce_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;
1233error:
1234	device_printf(sc->dev, "Start RX failed\n");
1235	return rc;
1236
1237}
1238
1239
1240
1241