1231437Sluigi/*-
2252869Sdelphij * Copyright (C) 2013 Emulex
3231437Sluigi * All rights reserved.
4231437Sluigi *
5231437Sluigi * Redistribution and use in source and binary forms, with or without
6231437Sluigi * modification, are permitted provided that the following conditions are met:
7231437Sluigi *
8231437Sluigi * 1. Redistributions of source code must retain the above copyright notice,
9231437Sluigi *    this list of conditions and the following disclaimer.
10231437Sluigi *
11231437Sluigi * 2. Redistributions in binary form must reproduce the above copyright
12231437Sluigi *    notice, this list of conditions and the following disclaimer in the
13231437Sluigi *    documentation and/or other materials provided with the distribution.
14231437Sluigi *
15231437Sluigi * 3. Neither the name of the Emulex Corporation nor the names of its
16231437Sluigi *    contributors may be used to endorse or promote products derived from
17231437Sluigi *    this software without specific prior written permission.
18231437Sluigi *
19231437Sluigi * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20231437Sluigi * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21231437Sluigi * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22231437Sluigi * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23231437Sluigi * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24231437Sluigi * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25231437Sluigi * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26231437Sluigi * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27231437Sluigi * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28231437Sluigi * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29231437Sluigi * POSSIBILITY OF SUCH DAMAGE.
30231437Sluigi *
31231437Sluigi * Contact Information:
32231437Sluigi * freebsd-drivers@emulex.com
33231437Sluigi *
34231437Sluigi * Emulex
35231437Sluigi * 3333 Susan Street
36231437Sluigi * Costa Mesa, CA 92626
37231437Sluigi */
38231437Sluigi
39231437Sluigi/* $FreeBSD$ */
40231437Sluigi
41231437Sluigi#include "oce_if.h"
42231437Sluigi
43231437Sluigi/*****************************************************
44231437Sluigi * local queue functions
45231437Sluigi *****************************************************/
46231437Sluigi
47231437Sluigistatic struct oce_wq *oce_wq_init(POCE_SOFTC sc,
48231437Sluigi				  uint32_t q_len, uint32_t wq_type);
49231437Sluigistatic int oce_wq_create(struct oce_wq *wq, struct oce_eq *eq);
50231437Sluigistatic void oce_wq_free(struct oce_wq *wq);
51231437Sluigistatic void oce_wq_del(struct oce_wq *wq);
52231437Sluigistatic struct oce_rq *oce_rq_init(POCE_SOFTC sc,
53231437Sluigi				  uint32_t q_len,
54231437Sluigi				  uint32_t frag_size,
55231437Sluigi				  uint32_t mtu, uint32_t rss);
56231437Sluigistatic int oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq);
57231437Sluigistatic void oce_rq_free(struct oce_rq *rq);
58231437Sluigistatic void oce_rq_del(struct oce_rq *rq);
59231437Sluigistatic struct oce_eq *oce_eq_create(POCE_SOFTC sc,
60231437Sluigi				    uint32_t q_len,
61231437Sluigi				    uint32_t item_size,
62231437Sluigi				    uint32_t eq_delay,
63231437Sluigi				    uint32_t vector);
64231437Sluigistatic void oce_eq_del(struct oce_eq *eq);
65231437Sluigistatic struct oce_mq *oce_mq_create(POCE_SOFTC sc,
66231437Sluigi				    struct oce_eq *eq, uint32_t q_len);
67231437Sluigistatic void oce_mq_free(struct oce_mq *mq);
68231437Sluigistatic int oce_destroy_q(POCE_SOFTC sc, struct oce_mbx
69231437Sluigi			 *mbx, size_t req_size, enum qtype qtype);
70231437Sluigistruct oce_cq *oce_cq_create(POCE_SOFTC sc,
71231437Sluigi			     struct oce_eq *eq,
72231437Sluigi			     uint32_t q_len,
73231437Sluigi			     uint32_t item_size,
74231437Sluigi			     uint32_t sol_event,
75231437Sluigi			     uint32_t is_eventable,
76231437Sluigi			     uint32_t nodelay, uint32_t ncoalesce);
77231437Sluigistatic void oce_cq_del(POCE_SOFTC sc, struct oce_cq *cq);
78231437Sluigi
79231437Sluigi
80231437Sluigi
81231437Sluigi/**
82231437Sluigi * @brief	Create and initialize all the queues on the board
83231437Sluigi * @param sc	software handle to the device
84231437Sluigi * @returns 0	if successful, or error
85231437Sluigi **/
86231437Sluigiint
87231437Sluigioce_queue_init_all(POCE_SOFTC sc)
88231437Sluigi{
89231437Sluigi	int rc = 0, i, vector;
90231437Sluigi	struct oce_wq *wq;
91231437Sluigi	struct oce_rq *rq;
92247880Sdelphij	struct oce_aic_obj *aic;
93231437Sluigi
94231437Sluigi	/* alloc TX/RX queues */
95231437Sluigi	for_all_wq_queues(sc, wq, i) {
96231437Sluigi		sc->wq[i] = oce_wq_init(sc, sc->tx_ring_size,
97231437Sluigi					 NIC_WQ_TYPE_STANDARD);
98231437Sluigi		if (!sc->wq[i])
99231437Sluigi			goto error;
100231437Sluigi
101231437Sluigi	}
102231437Sluigi
103231437Sluigi	for_all_rq_queues(sc, rq, i) {
104231437Sluigi		sc->rq[i] = oce_rq_init(sc, sc->rx_ring_size, sc->rq_frag_size,
105231437Sluigi					OCE_MAX_JUMBO_FRAME_SIZE,
106252869Sdelphij					(i == 0) ? 0 : is_rss_enabled(sc));
107231437Sluigi		if (!sc->rq[i])
108231437Sluigi			goto error;
109231437Sluigi	}
110231437Sluigi
111231437Sluigi	/* Create network interface on card */
112231437Sluigi	if (oce_create_nw_interface(sc))
113231437Sluigi		goto error;
114231437Sluigi
115231437Sluigi	/* create all of the event queues */
116231437Sluigi	for (vector = 0; vector < sc->intr_count; vector++) {
117247880Sdelphij		/* setup aic defaults for each event queue */
118247880Sdelphij		aic = &sc->aic_obj[vector];
119247880Sdelphij		aic->max_eqd = OCE_MAX_EQD;
120247880Sdelphij		aic->min_eqd = OCE_MIN_EQD;
121247880Sdelphij		aic->et_eqd = OCE_MIN_EQD;
122247880Sdelphij		aic->enable = TRUE;
123247880Sdelphij
124231437Sluigi		sc->eq[vector] = oce_eq_create(sc, EQ_LEN_1024, EQE_SIZE_4,
125231437Sluigi						 0, vector);
126231437Sluigi		if (!sc->eq[vector])
127231437Sluigi			goto error;
128231437Sluigi	}
129231437Sluigi
130231437Sluigi	/* create Tx, Rx and mcc queues */
131231437Sluigi	for_all_wq_queues(sc, wq, i) {
132231437Sluigi		rc = oce_wq_create(wq, sc->eq[i]);
133231437Sluigi		if (rc)
134231437Sluigi			goto error;
135231437Sluigi		wq->queue_index = i;
136231437Sluigi		TASK_INIT(&wq->txtask, 1, oce_tx_task, wq);
137231437Sluigi	}
138231437Sluigi
139231437Sluigi	for_all_rq_queues(sc, rq, i) {
140231437Sluigi		rc = oce_rq_create(rq, sc->if_id,
141231437Sluigi					sc->eq[(i == 0) ? 0:(i-1)]);
142231437Sluigi		if (rc)
143231437Sluigi			goto error;
144231437Sluigi		rq->queue_index = i;
145231437Sluigi	}
146231437Sluigi
147231437Sluigi	sc->mq = oce_mq_create(sc, sc->eq[0], 64);
148231437Sluigi	if (!sc->mq)
149231437Sluigi		goto error;
150231437Sluigi
151231437Sluigi	return rc;
152231437Sluigi
153231437Sluigierror:
154231437Sluigi	oce_queue_release_all(sc);
155231437Sluigi	return 1;
156231437Sluigi}
157231437Sluigi
158231437Sluigi
159231437Sluigi
160231437Sluigi/**
161231437Sluigi * @brief Releases all mailbox queues created
162231437Sluigi * @param sc		software handle to the device
163231437Sluigi */
164231437Sluigivoid
165231437Sluigioce_queue_release_all(POCE_SOFTC sc)
166231437Sluigi{
167231437Sluigi	int i = 0;
168231437Sluigi	struct oce_wq *wq;
169231437Sluigi	struct oce_rq *rq;
170231437Sluigi	struct oce_eq *eq;
171231437Sluigi
172231437Sluigi	for_all_rq_queues(sc, rq, i) {
173231437Sluigi		if (rq) {
174231437Sluigi			oce_rq_del(sc->rq[i]);
175231437Sluigi			oce_rq_free(sc->rq[i]);
176231437Sluigi		}
177231437Sluigi	}
178231437Sluigi
179231437Sluigi	for_all_wq_queues(sc, wq, i) {
180231437Sluigi		if (wq) {
181231437Sluigi			oce_wq_del(sc->wq[i]);
182231437Sluigi			oce_wq_free(sc->wq[i]);
183231437Sluigi		}
184231437Sluigi	}
185231437Sluigi
186231437Sluigi	if (sc->mq)
187231437Sluigi		oce_mq_free(sc->mq);
188231437Sluigi
189231437Sluigi	for_all_evnt_queues(sc, eq, i) {
190231437Sluigi		if (eq)
191231437Sluigi			oce_eq_del(sc->eq[i]);
192231437Sluigi	}
193231437Sluigi}
194231437Sluigi
195231437Sluigi
196231437Sluigi
197231437Sluigi/**
198231437Sluigi * @brief 		Function to create a WQ for NIC Tx
199231437Sluigi * @param sc 		software handle to the device
200231437Sluigi * @param qlen		number of entries in the queue
201231437Sluigi * @param wq_type	work queue type
202231437Sluigi * @returns		the pointer to the WQ created or NULL on failure
203231437Sluigi */
204231437Sluigistatic struct
205231437Sluigioce_wq *oce_wq_init(POCE_SOFTC sc, uint32_t q_len, uint32_t wq_type)
206231437Sluigi{
207231437Sluigi	struct oce_wq *wq;
208231437Sluigi	int rc = 0, i;
209231437Sluigi
210231437Sluigi	/* q_len must be min 256 and max 2k */
211231437Sluigi	if (q_len < 256 || q_len > 2048) {
212231437Sluigi		device_printf(sc->dev,
213231437Sluigi			  "Invalid q length. Must be "
214231437Sluigi			  "[256, 2000]: 0x%x\n", q_len);
215231437Sluigi		return NULL;
216231437Sluigi	}
217231437Sluigi
218231437Sluigi	/* allocate wq */
219231437Sluigi	wq = malloc(sizeof(struct oce_wq), M_DEVBUF, M_NOWAIT | M_ZERO);
220231437Sluigi	if (!wq)
221231437Sluigi		return NULL;
222231437Sluigi
223231437Sluigi	/* Set the wq config */
224231437Sluigi	wq->cfg.q_len = q_len;
225231437Sluigi	wq->cfg.wq_type = (uint8_t) wq_type;
226231437Sluigi	wq->cfg.eqd = OCE_DEFAULT_WQ_EQD;
227231437Sluigi	wq->cfg.nbufs = 2 * wq->cfg.q_len;
228231437Sluigi	wq->cfg.nhdl = 2 * wq->cfg.q_len;
229231437Sluigi
230231437Sluigi	wq->parent = (void *)sc;
231231437Sluigi
232231437Sluigi	rc = bus_dma_tag_create(bus_get_dma_tag(sc->dev),
233231437Sluigi				1, 0,
234231437Sluigi				BUS_SPACE_MAXADDR,
235231437Sluigi				BUS_SPACE_MAXADDR,
236231437Sluigi				NULL, NULL,
237231437Sluigi				OCE_MAX_TX_SIZE,
238231437Sluigi				OCE_MAX_TX_ELEMENTS,
239231437Sluigi				PAGE_SIZE, 0, NULL, NULL, &wq->tag);
240231437Sluigi
241231437Sluigi	if (rc)
242231437Sluigi		goto free_wq;
243231437Sluigi
244231437Sluigi
245231437Sluigi	for (i = 0; i < OCE_WQ_PACKET_ARRAY_SIZE; i++) {
246231437Sluigi		rc = bus_dmamap_create(wq->tag, 0, &wq->pckts[i].map);
247231437Sluigi		if (rc)
248231437Sluigi			goto free_wq;
249231437Sluigi	}
250231437Sluigi
251231437Sluigi	wq->ring = oce_create_ring_buffer(sc, q_len, NIC_WQE_SIZE);
252231437Sluigi	if (!wq->ring)
253231437Sluigi		goto free_wq;
254231437Sluigi
255231437Sluigi
256231437Sluigi	LOCK_CREATE(&wq->tx_lock, "TX_lock");
257231437Sluigi
258231437Sluigi#if __FreeBSD_version >= 800000
259231437Sluigi	/* Allocate buf ring for multiqueue*/
260231437Sluigi	wq->br = buf_ring_alloc(4096, M_DEVBUF,
261231437Sluigi			M_WAITOK, &wq->tx_lock.mutex);
262231437Sluigi	if (!wq->br)
263231437Sluigi		goto free_wq;
264231437Sluigi#endif
265231437Sluigi	return wq;
266231437Sluigi
267231437Sluigi
268231437Sluigifree_wq:
269231437Sluigi	device_printf(sc->dev, "Create WQ failed\n");
270231437Sluigi	oce_wq_free(wq);
271231437Sluigi	return NULL;
272231437Sluigi}
273231437Sluigi
274231437Sluigi
275231437Sluigi
276231437Sluigi/**
277231437Sluigi * @brief 		Frees the work queue
278231437Sluigi * @param wq		pointer to work queue to free
279231437Sluigi */
280231437Sluigistatic void
281231437Sluigioce_wq_free(struct oce_wq *wq)
282231437Sluigi{
283231437Sluigi	POCE_SOFTC sc = (POCE_SOFTC) wq->parent;
284231437Sluigi	int i;
285231437Sluigi
286231437Sluigi	taskqueue_drain(taskqueue_swi, &wq->txtask);
287231437Sluigi
288231437Sluigi	if (wq->ring != NULL) {
289231437Sluigi		oce_destroy_ring_buffer(sc, wq->ring);
290231437Sluigi		wq->ring = NULL;
291231437Sluigi	}
292231437Sluigi
293231437Sluigi	for (i = 0; i < OCE_WQ_PACKET_ARRAY_SIZE; i++) {
294231437Sluigi		if (wq->pckts[i].map != NULL) {
295231437Sluigi			bus_dmamap_unload(wq->tag, wq->pckts[i].map);
296231437Sluigi			bus_dmamap_destroy(wq->tag, wq->pckts[i].map);
297231437Sluigi			wq->pckts[i].map = NULL;
298231437Sluigi		}
299231437Sluigi	}
300231437Sluigi
301231437Sluigi	if (wq->tag != NULL)
302231437Sluigi		bus_dma_tag_destroy(wq->tag);
303231437Sluigi	if (wq->br != NULL)
304231437Sluigi		buf_ring_free(wq->br, M_DEVBUF);
305231437Sluigi
306231437Sluigi	LOCK_DESTROY(&wq->tx_lock);
307231437Sluigi	free(wq, M_DEVBUF);
308231437Sluigi}
309231437Sluigi
310231437Sluigi
311231437Sluigi
312231437Sluigi/**
313231437Sluigi * @brief 		Create a work queue
314231437Sluigi * @param wq		pointer to work queue
315231437Sluigi * @param eq		pointer to associated event queue
316231437Sluigi */
317231437Sluigistatic int
318231437Sluigioce_wq_create(struct oce_wq *wq, struct oce_eq *eq)
319231437Sluigi{
320231437Sluigi	POCE_SOFTC sc = wq->parent;
321231437Sluigi	struct oce_cq *cq;
322231437Sluigi	int rc = 0;
323231437Sluigi
324231437Sluigi	/* create the CQ */
325231437Sluigi	cq = oce_cq_create(sc,
326231437Sluigi			   eq,
327231437Sluigi			   CQ_LEN_1024,
328231437Sluigi			   sizeof(struct oce_nic_tx_cqe), 0, 1, 0, 3);
329231437Sluigi	if (!cq)
330231437Sluigi		return ENXIO;
331231437Sluigi
332231437Sluigi
333231437Sluigi	wq->cq = cq;
334231437Sluigi
335231437Sluigi	rc = oce_mbox_create_wq(wq);
336231437Sluigi	if (rc)
337231437Sluigi		goto error;
338231437Sluigi
339231437Sluigi	wq->qstate = QCREATED;
340231437Sluigi	wq->wq_free = wq->cfg.q_len;
341231437Sluigi	wq->ring->cidx = 0;
342231437Sluigi	wq->ring->pidx = 0;
343231437Sluigi
344231437Sluigi	eq->cq[eq->cq_valid] = cq;
345231437Sluigi	eq->cq_valid++;
346231437Sluigi	cq->cb_arg = wq;
347231437Sluigi	cq->cq_handler = oce_wq_handler;
348231437Sluigi
349231437Sluigi	return 0;
350231437Sluigi
351231437Sluigierror:
352231437Sluigi	device_printf(sc->dev, "WQ create failed\n");
353231437Sluigi	oce_wq_del(wq);
354231437Sluigi	return rc;
355231437Sluigi}
356231437Sluigi
357231437Sluigi
358231437Sluigi
359231437Sluigi
360231437Sluigi/**
361231437Sluigi * @brief 		Delete a work queue
362231437Sluigi * @param wq		pointer to work queue
363231437Sluigi */
364231437Sluigistatic void
365231437Sluigioce_wq_del(struct oce_wq *wq)
366231437Sluigi{
367231437Sluigi	struct oce_mbx mbx;
368231437Sluigi	struct mbx_delete_nic_wq *fwcmd;
369231437Sluigi	POCE_SOFTC sc = (POCE_SOFTC) wq->parent;
370231437Sluigi
371231437Sluigi	if (wq->qstate == QCREATED) {
372231437Sluigi		bzero(&mbx, sizeof(struct oce_mbx));
373231437Sluigi		/* now fill the command */
374231437Sluigi		fwcmd = (struct mbx_delete_nic_wq *)&mbx.payload;
375231437Sluigi		fwcmd->params.req.wq_id = wq->wq_id;
376231437Sluigi		(void)oce_destroy_q(sc, &mbx,
377231437Sluigi				sizeof(struct mbx_delete_nic_wq), QTYPE_WQ);
378231437Sluigi		wq->qstate = QDELETED;
379231437Sluigi	}
380231437Sluigi
381231437Sluigi	if (wq->cq != NULL) {
382231437Sluigi		oce_cq_del(sc, wq->cq);
383231437Sluigi		wq->cq = NULL;
384231437Sluigi	}
385231437Sluigi}
386231437Sluigi
387231437Sluigi
388231437Sluigi
389231437Sluigi/**
390231437Sluigi * @brief 		function to allocate receive queue resources
391231437Sluigi * @param sc		software handle to the device
392231437Sluigi * @param q_len		length of receive queue
393231437Sluigi * @param frag_size	size of an receive queue fragment
394231437Sluigi * @param mtu		maximum transmission unit
395231437Sluigi * @param rss		is-rss-queue flag
396231437Sluigi * @returns		the pointer to the RQ created or NULL on failure
397231437Sluigi */
398231437Sluigistatic struct
399231437Sluigioce_rq *oce_rq_init(POCE_SOFTC sc,
400231437Sluigi				  uint32_t q_len,
401231437Sluigi				  uint32_t frag_size,
402231437Sluigi				  uint32_t mtu, uint32_t rss)
403231437Sluigi{
404231437Sluigi	struct oce_rq *rq;
405231437Sluigi	int rc = 0, i;
406231437Sluigi
407231437Sluigi	if (OCE_LOG2(frag_size) <= 0)
408231437Sluigi		return NULL;
409231437Sluigi
410231437Sluigi	if ((q_len == 0) || (q_len > 1024))
411231437Sluigi		return NULL;
412231437Sluigi
413231437Sluigi	/* allocate the rq */
414231437Sluigi	rq = malloc(sizeof(struct oce_rq), M_DEVBUF, M_NOWAIT | M_ZERO);
415231437Sluigi	if (!rq)
416231437Sluigi		return NULL;
417231437Sluigi
418231437Sluigi
419231437Sluigi	rq->cfg.q_len = q_len;
420231437Sluigi	rq->cfg.frag_size = frag_size;
421231437Sluigi	rq->cfg.mtu = mtu;
422231437Sluigi	rq->cfg.eqd = 0;
423231437Sluigi	rq->lro_pkts_queued = 0;
424231437Sluigi	rq->cfg.is_rss_queue = rss;
425231437Sluigi	rq->packets_in = 0;
426231437Sluigi        rq->packets_out = 0;
427231437Sluigi        rq->pending = 0;
428231437Sluigi
429231437Sluigi	rq->parent = (void *)sc;
430231437Sluigi
431231437Sluigi	rc = bus_dma_tag_create(bus_get_dma_tag(sc->dev),
432231437Sluigi				1, 0,
433231437Sluigi				BUS_SPACE_MAXADDR,
434231437Sluigi				BUS_SPACE_MAXADDR,
435231437Sluigi				NULL, NULL,
436231437Sluigi				OCE_MAX_RX_SIZE,
437231437Sluigi				1, PAGE_SIZE, 0, NULL, NULL, &rq->tag);
438231437Sluigi
439231437Sluigi	if (rc)
440231437Sluigi		goto free_rq;
441231437Sluigi
442231437Sluigi	for (i = 0; i < OCE_RQ_PACKET_ARRAY_SIZE; i++) {
443231437Sluigi		rc = bus_dmamap_create(rq->tag, 0, &rq->pckts[i].map);
444231437Sluigi		if (rc)
445231437Sluigi			goto free_rq;
446231437Sluigi	}
447231437Sluigi
448231437Sluigi	/* create the ring buffer */
449231437Sluigi	rq->ring = oce_create_ring_buffer(sc, q_len,
450231437Sluigi				 sizeof(struct oce_nic_rqe));
451231437Sluigi	if (!rq->ring)
452231437Sluigi		goto free_rq;
453231437Sluigi
454231437Sluigi	LOCK_CREATE(&rq->rx_lock, "RX_lock");
455231437Sluigi
456231437Sluigi	return rq;
457231437Sluigi
458231437Sluigifree_rq:
459231437Sluigi	device_printf(sc->dev, "Create RQ failed\n");
460231437Sluigi	oce_rq_free(rq);
461231437Sluigi	return NULL;
462231437Sluigi}
463231437Sluigi
464231437Sluigi
465231437Sluigi
466231437Sluigi
467231437Sluigi/**
468231437Sluigi * @brief 		Free a receive queue
469231437Sluigi * @param rq		pointer to receive queue
470231437Sluigi */
471231437Sluigistatic void
472231437Sluigioce_rq_free(struct oce_rq *rq)
473231437Sluigi{
474231437Sluigi	POCE_SOFTC sc = (POCE_SOFTC) rq->parent;
475231437Sluigi	int i = 0 ;
476231437Sluigi
477231437Sluigi	if (rq->ring != NULL) {
478231437Sluigi		oce_destroy_ring_buffer(sc, rq->ring);
479231437Sluigi		rq->ring = NULL;
480231437Sluigi	}
481231437Sluigi	for (i = 0; i < OCE_RQ_PACKET_ARRAY_SIZE; i++) {
482231437Sluigi		if (rq->pckts[i].map != NULL) {
483231437Sluigi			bus_dmamap_unload(rq->tag, rq->pckts[i].map);
484231437Sluigi			bus_dmamap_destroy(rq->tag, rq->pckts[i].map);
485231437Sluigi			rq->pckts[i].map = NULL;
486231437Sluigi		}
487231437Sluigi		if (rq->pckts[i].mbuf) {
488231437Sluigi			m_free(rq->pckts[i].mbuf);
489231437Sluigi			rq->pckts[i].mbuf = NULL;
490231437Sluigi		}
491231437Sluigi	}
492231437Sluigi
493231437Sluigi	if (rq->tag != NULL)
494231437Sluigi		bus_dma_tag_destroy(rq->tag);
495231437Sluigi
496231437Sluigi	LOCK_DESTROY(&rq->rx_lock);
497231437Sluigi	free(rq, M_DEVBUF);
498231437Sluigi}
499231437Sluigi
500231437Sluigi
501231437Sluigi
502231437Sluigi
503231437Sluigi/**
504231437Sluigi * @brief 		Create a receive queue
505231437Sluigi * @param rq 		receive queue
506231437Sluigi * @param if_id		interface identifier index`
507231437Sluigi * @param eq		pointer to event queue
508231437Sluigi */
509231437Sluigistatic int
510231437Sluigioce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq)
511231437Sluigi{
512231437Sluigi	POCE_SOFTC sc = rq->parent;
513231437Sluigi	struct oce_cq *cq;
514231437Sluigi
515231437Sluigi	cq = oce_cq_create(sc,
516231437Sluigi			   eq,
517231437Sluigi			   CQ_LEN_1024,
518231437Sluigi			   sizeof(struct oce_nic_rx_cqe), 0, 1, 0, 3);
519231437Sluigi	if (!cq)
520231437Sluigi		return ENXIO;
521231437Sluigi
522231437Sluigi	rq->cq = cq;
523231437Sluigi	rq->cfg.if_id = if_id;
524231437Sluigi
525231437Sluigi	/* Dont create RQ here. Create in if_activate */
526231437Sluigi	rq->qstate     = 0;
527231437Sluigi	rq->ring->cidx = 0;
528231437Sluigi	rq->ring->pidx = 0;
529231437Sluigi	eq->cq[eq->cq_valid] = cq;
530231437Sluigi	eq->cq_valid++;
531231437Sluigi	cq->cb_arg = rq;
532231437Sluigi	cq->cq_handler = oce_rq_handler;
533231437Sluigi
534231437Sluigi	return 0;
535231437Sluigi
536231437Sluigi}
537231437Sluigi
538231437Sluigi
539231437Sluigi
540231437Sluigi
541231437Sluigi/**
542231437Sluigi * @brief 		Delete a receive queue
543231437Sluigi * @param rq		receive queue
544231437Sluigi */
545231437Sluigistatic void
546231437Sluigioce_rq_del(struct oce_rq *rq)
547231437Sluigi{
548231437Sluigi	POCE_SOFTC sc = (POCE_SOFTC) rq->parent;
549231437Sluigi	struct oce_mbx mbx;
550231437Sluigi	struct mbx_delete_nic_rq *fwcmd;
551231437Sluigi
552231437Sluigi	if (rq->qstate == QCREATED) {
553231437Sluigi		bzero(&mbx, sizeof(mbx));
554231437Sluigi
555231437Sluigi		fwcmd = (struct mbx_delete_nic_rq *)&mbx.payload;
556231437Sluigi		fwcmd->params.req.rq_id = rq->rq_id;
557231437Sluigi		(void)oce_destroy_q(sc, &mbx,
558231437Sluigi				sizeof(struct mbx_delete_nic_rq), QTYPE_RQ);
559231437Sluigi		rq->qstate = QDELETED;
560231437Sluigi	}
561231437Sluigi
562231437Sluigi	if (rq->cq != NULL) {
563231437Sluigi		oce_cq_del(sc, rq->cq);
564231437Sluigi		rq->cq = NULL;
565231437Sluigi	}
566231437Sluigi}
567231437Sluigi
568231437Sluigi
569231437Sluigi
570231437Sluigi/**
571231437Sluigi * @brief		function to create an event queue
572231437Sluigi * @param sc		software handle to the device
573231437Sluigi * @param q_len		length of event queue
574231437Sluigi * @param item_size	size of an event queue item
575231437Sluigi * @param eq_delay	event queue delay
576231437Sluigi * @retval eq      	success, pointer to event queue
577231437Sluigi * @retval NULL		failure
578231437Sluigi */
579231437Sluigistatic struct
580231437Sluigioce_eq *oce_eq_create(POCE_SOFTC sc, uint32_t q_len,
581231437Sluigi				    uint32_t item_size,
582231437Sluigi				    uint32_t eq_delay,
583231437Sluigi				    uint32_t vector)
584231437Sluigi{
585231437Sluigi	struct oce_eq *eq;
586231437Sluigi	int rc = 0;
587231437Sluigi
588231437Sluigi	/* allocate an eq */
589231437Sluigi	eq = malloc(sizeof(struct oce_eq), M_DEVBUF, M_NOWAIT | M_ZERO);
590231437Sluigi	if (eq == NULL)
591231437Sluigi		return NULL;
592231437Sluigi
593231437Sluigi	eq->parent = (void *)sc;
594231437Sluigi	eq->eq_id = 0xffff;
595231437Sluigi	eq->ring = oce_create_ring_buffer(sc, q_len, item_size);
596231437Sluigi	if (!eq->ring)
597231437Sluigi		goto free_eq;
598231437Sluigi
599231437Sluigi	eq->eq_cfg.q_len = q_len;
600231437Sluigi	eq->eq_cfg.item_size = item_size;
601231437Sluigi	eq->eq_cfg.cur_eqd = (uint8_t) eq_delay;
602231437Sluigi
603231437Sluigi	rc = oce_mbox_create_eq(eq);
604231437Sluigi	if (rc)
605231437Sluigi		goto free_eq;
606231437Sluigi
607231437Sluigi	sc->intrs[sc->neqs++].eq = eq;
608231437Sluigi
609231437Sluigi	return eq;
610231437Sluigi
611231437Sluigifree_eq:
612231437Sluigi	oce_eq_del(eq);
613231437Sluigi	return NULL;
614231437Sluigi}
615231437Sluigi
616231437Sluigi
617231437Sluigi
618231437Sluigi
619231437Sluigi/**
620231437Sluigi * @brief 		Function to delete an event queue
621231437Sluigi * @param eq		pointer to an event queue
622231437Sluigi */
623231437Sluigistatic void
624231437Sluigioce_eq_del(struct oce_eq *eq)
625231437Sluigi{
626231437Sluigi	struct oce_mbx mbx;
627231437Sluigi	struct mbx_destroy_common_eq *fwcmd;
628231437Sluigi	POCE_SOFTC sc = (POCE_SOFTC) eq->parent;
629231437Sluigi
630231437Sluigi	if (eq->eq_id != 0xffff) {
631231437Sluigi		bzero(&mbx, sizeof(mbx));
632231437Sluigi		fwcmd = (struct mbx_destroy_common_eq *)&mbx.payload;
633231437Sluigi		fwcmd->params.req.id = eq->eq_id;
634231437Sluigi		(void)oce_destroy_q(sc, &mbx,
635231437Sluigi			sizeof(struct mbx_destroy_common_eq), QTYPE_EQ);
636231437Sluigi	}
637231437Sluigi
638231437Sluigi	if (eq->ring != NULL) {
639231437Sluigi		oce_destroy_ring_buffer(sc, eq->ring);
640231437Sluigi		eq->ring = NULL;
641231437Sluigi	}
642231437Sluigi
643231437Sluigi	free(eq, M_DEVBUF);
644231437Sluigi
645231437Sluigi}
646231437Sluigi
647231437Sluigi
648231437Sluigi
649231437Sluigi
650231437Sluigi/**
651231437Sluigi * @brief		Function to create an MQ
652231437Sluigi * @param sc		software handle to the device
653231437Sluigi * @param eq		the EQ to associate with the MQ for event notification
654231437Sluigi * @param q_len		the number of entries to create in the MQ
655231437Sluigi * @returns		pointer to the created MQ, failure otherwise
656231437Sluigi */
657231437Sluigistatic struct oce_mq *
658231437Sluigioce_mq_create(POCE_SOFTC sc, struct oce_eq *eq, uint32_t q_len)
659231437Sluigi{
660231437Sluigi	struct oce_mbx mbx;
661231879Sluigi	struct mbx_create_common_mq_ex *fwcmd = NULL;
662231437Sluigi	struct oce_mq *mq = NULL;
663231437Sluigi	int rc = 0;
664231437Sluigi	struct oce_cq *cq;
665231879Sluigi	oce_mq_ext_ctx_t *ctx;
666231437Sluigi	uint32_t num_pages;
667231437Sluigi	uint32_t page_size;
668247880Sdelphij	int version;
669231437Sluigi
670231437Sluigi	cq = oce_cq_create(sc, eq, CQ_LEN_256,
671231437Sluigi			sizeof(struct oce_mq_cqe), 1, 1, 0, 0);
672231437Sluigi	if (!cq)
673231437Sluigi		return NULL;
674231437Sluigi
675231437Sluigi	/* allocate the mq */
676231437Sluigi	mq = malloc(sizeof(struct oce_mq), M_DEVBUF, M_NOWAIT | M_ZERO);
677231437Sluigi	if (!mq) {
678231437Sluigi		oce_cq_del(sc, cq);
679231437Sluigi		goto error;
680231437Sluigi	}
681231437Sluigi
682231437Sluigi	mq->parent = sc;
683231437Sluigi
684231437Sluigi	mq->ring = oce_create_ring_buffer(sc, q_len, sizeof(struct oce_mbx));
685231437Sluigi	if (!mq->ring)
686231437Sluigi		goto error;
687231437Sluigi
688231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
689231437Sluigi
690247880Sdelphij	IS_XE201(sc) ? (version = OCE_MBX_VER_V1) : (version = OCE_MBX_VER_V0);
691231879Sluigi	fwcmd = (struct mbx_create_common_mq_ex *)&mbx.payload;
692231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
693231437Sluigi				MBX_SUBSYSTEM_COMMON,
694231879Sluigi				OPCODE_COMMON_CREATE_MQ_EXT,
695231437Sluigi				MBX_TIMEOUT_SEC,
696231879Sluigi				sizeof(struct mbx_create_common_mq_ex),
697231437Sluigi				version);
698231437Sluigi
699231437Sluigi	num_pages = oce_page_list(mq->ring, &fwcmd->params.req.pages[0]);
700231437Sluigi	page_size = mq->ring->num_items * mq->ring->item_size;
701231437Sluigi
702231437Sluigi	ctx = &fwcmd->params.req.context;
703231437Sluigi
704247880Sdelphij	if (IS_XE201(sc)) {
705247880Sdelphij		ctx->v1.num_pages = num_pages;
706247880Sdelphij		ctx->v1.ring_size = OCE_LOG2(q_len) + 1;
707247880Sdelphij		ctx->v1.cq_id = cq->cq_id;
708247880Sdelphij		ctx->v1.valid = 1;
709247880Sdelphij		ctx->v1.async_cq_id = cq->cq_id;
710247880Sdelphij		ctx->v1.async_cq_valid = 1;
711247880Sdelphij		/* Subscribe to Link State and Group 5 Events(bits 1 & 5 set) */
712247880Sdelphij		ctx->v1.async_evt_bitmap |= LE_32(0x00000022);
713247880Sdelphij		ctx->v1.async_evt_bitmap |= LE_32(1 << ASYNC_EVENT_CODE_DEBUG);
714247880Sdelphij		ctx->v1.async_evt_bitmap |=
715247880Sdelphij					LE_32(1 << ASYNC_EVENT_CODE_SLIPORT);
716247880Sdelphij	}
717247880Sdelphij	else {
718247880Sdelphij		ctx->v0.num_pages = num_pages;
719247880Sdelphij		ctx->v0.cq_id = cq->cq_id;
720247880Sdelphij		ctx->v0.ring_size = OCE_LOG2(q_len) + 1;
721247880Sdelphij		ctx->v0.valid = 1;
722247880Sdelphij		/* Subscribe to Link State and Group5 Events(bits 1 & 5 set) */
723247880Sdelphij		ctx->v0.async_evt_bitmap = 0xffffffff;
724247880Sdelphij	}
725247880Sdelphij
726231437Sluigi	mbx.u0.s.embedded = 1;
727231879Sluigi	mbx.payload_length = sizeof(struct mbx_create_common_mq_ex);
728231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
729231437Sluigi
730231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
731247880Sdelphij	if (!rc)
732247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
733247880Sdelphij	if (rc) {
734247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
735247880Sdelphij			      __FUNCTION__, rc);
736231437Sluigi		goto error;
737247880Sdelphij	}
738231437Sluigi	mq->mq_id = LE_16(fwcmd->params.rsp.mq_id);
739231437Sluigi	mq->cq = cq;
740231437Sluigi	eq->cq[eq->cq_valid] = cq;
741231437Sluigi	eq->cq_valid++;
742231437Sluigi	mq->cq->eq = eq;
743231437Sluigi	mq->cfg.q_len = (uint8_t) q_len;
744231437Sluigi	mq->cfg.eqd = 0;
745231437Sluigi	mq->qstate = QCREATED;
746231437Sluigi
747231437Sluigi	mq->cq->cb_arg = mq;
748231437Sluigi	mq->cq->cq_handler = oce_mq_handler;
749231437Sluigi
750231437Sluigi	return mq;
751231437Sluigi
752231437Sluigierror:
753231437Sluigi	device_printf(sc->dev, "MQ create failed\n");
754231437Sluigi	oce_mq_free(mq);
755231437Sluigi	mq = NULL;
756231437Sluigi	return mq;
757231437Sluigi}
758231437Sluigi
759231437Sluigi
760231437Sluigi
761231437Sluigi
762231437Sluigi
763231437Sluigi/**
764231437Sluigi * @brief		Function to free a mailbox queue
765231437Sluigi * @param mq		pointer to a mailbox queue
766231437Sluigi */
767231437Sluigistatic void
768231437Sluigioce_mq_free(struct oce_mq *mq)
769231437Sluigi{
770231437Sluigi	POCE_SOFTC sc = (POCE_SOFTC) mq->parent;
771231437Sluigi	struct oce_mbx mbx;
772231437Sluigi	struct mbx_destroy_common_mq *fwcmd;
773231437Sluigi
774231437Sluigi	if (!mq)
775231437Sluigi		return;
776231437Sluigi
777231437Sluigi	if (mq->ring != NULL) {
778231437Sluigi		oce_destroy_ring_buffer(sc, mq->ring);
779231437Sluigi		mq->ring = NULL;
780231437Sluigi		if (mq->qstate == QCREATED) {
781231437Sluigi			bzero(&mbx, sizeof (struct oce_mbx));
782231437Sluigi			fwcmd = (struct mbx_destroy_common_mq *)&mbx.payload;
783231437Sluigi			fwcmd->params.req.id = mq->mq_id;
784231437Sluigi			(void) oce_destroy_q(sc, &mbx,
785231437Sluigi				sizeof (struct mbx_destroy_common_mq),
786231437Sluigi				QTYPE_MQ);
787231437Sluigi		}
788231437Sluigi		mq->qstate = QDELETED;
789231437Sluigi	}
790231437Sluigi
791231437Sluigi	if (mq->cq != NULL) {
792231437Sluigi		oce_cq_del(sc, mq->cq);
793231437Sluigi		mq->cq = NULL;
794231437Sluigi	}
795231437Sluigi
796231437Sluigi	free(mq, M_DEVBUF);
797231437Sluigi	mq = NULL;
798231437Sluigi}
799231437Sluigi
800231437Sluigi
801231437Sluigi
802231437Sluigi/**
803231437Sluigi * @brief		Function to delete a EQ, CQ, MQ, WQ or RQ
804231437Sluigi * @param sc		sofware handle to the device
805231437Sluigi * @param mbx		mailbox command to send to the fw to delete the queue
806231437Sluigi *			(mbx contains the queue information to delete)
807231437Sluigi * @param req_size	the size of the mbx payload dependent on the qtype
808231437Sluigi * @param qtype		the type of queue i.e. EQ, CQ, MQ, WQ or RQ
809231437Sluigi * @returns 		0 on success, failure otherwise
810231437Sluigi */
811231437Sluigistatic int
812231437Sluigioce_destroy_q(POCE_SOFTC sc, struct oce_mbx *mbx, size_t req_size,
813231437Sluigi		enum qtype qtype)
814231437Sluigi{
815231437Sluigi	struct mbx_hdr *hdr = (struct mbx_hdr *)&mbx->payload;
816231437Sluigi	int opcode;
817231437Sluigi	int subsys;
818231437Sluigi	int rc = 0;
819231437Sluigi
820231437Sluigi	switch (qtype) {
821231437Sluigi	case QTYPE_EQ:
822231437Sluigi		opcode = OPCODE_COMMON_DESTROY_EQ;
823231437Sluigi		subsys = MBX_SUBSYSTEM_COMMON;
824231437Sluigi		break;
825231437Sluigi	case QTYPE_CQ:
826231437Sluigi		opcode = OPCODE_COMMON_DESTROY_CQ;
827231437Sluigi		subsys = MBX_SUBSYSTEM_COMMON;
828231437Sluigi		break;
829231437Sluigi	case QTYPE_MQ:
830231437Sluigi		opcode = OPCODE_COMMON_DESTROY_MQ;
831231437Sluigi		subsys = MBX_SUBSYSTEM_COMMON;
832231437Sluigi		break;
833231437Sluigi	case QTYPE_WQ:
834231437Sluigi		opcode = NIC_DELETE_WQ;
835231437Sluigi		subsys = MBX_SUBSYSTEM_NIC;
836231437Sluigi		break;
837231437Sluigi	case QTYPE_RQ:
838231437Sluigi		opcode = NIC_DELETE_RQ;
839231437Sluigi		subsys = MBX_SUBSYSTEM_NIC;
840231437Sluigi		break;
841231437Sluigi	default:
842231437Sluigi		return EINVAL;
843231437Sluigi	}
844231437Sluigi
845231437Sluigi	mbx_common_req_hdr_init(hdr, 0, 0, subsys,
846231437Sluigi				opcode, MBX_TIMEOUT_SEC, req_size,
847231437Sluigi				OCE_MBX_VER_V0);
848231437Sluigi
849231437Sluigi	mbx->u0.s.embedded = 1;
850231437Sluigi	mbx->payload_length = (uint32_t) req_size;
851231437Sluigi	DW_SWAP(u32ptr(mbx), mbx->payload_length + OCE_BMBX_RHDR_SZ);
852231437Sluigi
853231437Sluigi	rc = oce_mbox_post(sc, mbx, NULL);
854247880Sdelphij	if (!rc)
855247880Sdelphij                rc = hdr->u0.rsp.status;
856247880Sdelphij	if (rc)
857247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
858247880Sdelphij			      __FUNCTION__, rc);
859231437Sluigi	return rc;
860231437Sluigi}
861231437Sluigi
862231437Sluigi
863231437Sluigi
864231437Sluigi/**
865231437Sluigi * @brief		Function to create a completion queue
866231437Sluigi * @param sc		software handle to the device
867231437Sluigi * @param eq		optional eq to be associated with to the cq
868231437Sluigi * @param q_len		length of completion queue
869231437Sluigi * @param item_size	size of completion queue items
870231437Sluigi * @param sol_event	command context event
871231437Sluigi * @param is_eventable	event table
872231437Sluigi * @param nodelay	no delay flag
873231437Sluigi * @param ncoalesce	no coalescence flag
874231437Sluigi * @returns 		pointer to the cq created, NULL on failure
875231437Sluigi */
876231437Sluigistruct oce_cq *
877231437Sluigioce_cq_create(POCE_SOFTC sc, struct oce_eq *eq,
878231437Sluigi			     uint32_t q_len,
879231437Sluigi			     uint32_t item_size,
880231437Sluigi			     uint32_t sol_event,
881231437Sluigi			     uint32_t is_eventable,
882231437Sluigi			     uint32_t nodelay, uint32_t ncoalesce)
883231437Sluigi{
884231437Sluigi	struct oce_cq *cq = NULL;
885231437Sluigi	int rc = 0;
886231437Sluigi
887231437Sluigi	cq = malloc(sizeof(struct oce_cq), M_DEVBUF, M_NOWAIT | M_ZERO);
888231437Sluigi	if (!cq)
889231437Sluigi		return NULL;
890231437Sluigi
891231437Sluigi	cq->ring = oce_create_ring_buffer(sc, q_len, item_size);
892231437Sluigi	if (!cq->ring)
893231437Sluigi		goto error;
894231437Sluigi
895231437Sluigi	cq->parent = sc;
896231437Sluigi	cq->eq = eq;
897231437Sluigi	cq->cq_cfg.q_len = q_len;
898231437Sluigi	cq->cq_cfg.item_size = item_size;
899231437Sluigi	cq->cq_cfg.nodelay = (uint8_t) nodelay;
900231437Sluigi
901231437Sluigi	rc = oce_mbox_cq_create(cq, ncoalesce, is_eventable);
902231437Sluigi	if (rc)
903231437Sluigi		goto error;
904231437Sluigi
905231437Sluigi	sc->cq[sc->ncqs++] = cq;
906231437Sluigi
907231437Sluigi	return cq;
908231437Sluigi
909231437Sluigierror:
910231437Sluigi	device_printf(sc->dev, "CQ create failed\n");
911231437Sluigi	oce_cq_del(sc, cq);
912231437Sluigi	return NULL;
913231437Sluigi}
914231437Sluigi
915231437Sluigi
916231437Sluigi
917231437Sluigi/**
918231437Sluigi * @brief		Deletes the completion queue
919231437Sluigi * @param sc		software handle to the device
920231437Sluigi * @param cq		pointer to a completion queue
921231437Sluigi */
922231437Sluigistatic void
923231437Sluigioce_cq_del(POCE_SOFTC sc, struct oce_cq *cq)
924231437Sluigi{
925231437Sluigi	struct oce_mbx mbx;
926231437Sluigi	struct mbx_destroy_common_cq *fwcmd;
927231437Sluigi
928231437Sluigi	if (cq->ring != NULL) {
929231437Sluigi
930231437Sluigi		bzero(&mbx, sizeof(struct oce_mbx));
931231437Sluigi		/* now fill the command */
932231437Sluigi		fwcmd = (struct mbx_destroy_common_cq *)&mbx.payload;
933231437Sluigi		fwcmd->params.req.id = cq->cq_id;
934231437Sluigi		(void)oce_destroy_q(sc, &mbx,
935231437Sluigi			sizeof(struct mbx_destroy_common_cq), QTYPE_CQ);
936231437Sluigi		/*NOW destroy the ring */
937231437Sluigi		oce_destroy_ring_buffer(sc, cq->ring);
938231437Sluigi		cq->ring = NULL;
939231437Sluigi	}
940231437Sluigi
941231437Sluigi	free(cq, M_DEVBUF);
942231437Sluigi	cq = NULL;
943231437Sluigi}
944231437Sluigi
945231437Sluigi
946231437Sluigi
947231437Sluigi/**
948231437Sluigi * @brief		Start a receive queue
949231437Sluigi * @param rq		pointer to a receive queue
950231437Sluigi */
951231437Sluigiint
952231437Sluigioce_start_rq(struct oce_rq *rq)
953231437Sluigi{
954231437Sluigi	int rc;
955231437Sluigi
956231437Sluigi	rc = oce_alloc_rx_bufs(rq, rq->cfg.q_len);
957231437Sluigi
958231437Sluigi	if (rc == 0)
959231437Sluigi		oce_arm_cq(rq->parent, rq->cq->cq_id, 0, TRUE);
960231437Sluigi	return rc;
961231437Sluigi}
962231437Sluigi
963231437Sluigi
964231437Sluigi
965231437Sluigi/**
966231437Sluigi * @brief		Start a work queue
967231437Sluigi * @param wq		pointer to a work queue
968231437Sluigi */
969231437Sluigiint
970231437Sluigioce_start_wq(struct oce_wq *wq)
971231437Sluigi{
972231437Sluigi	oce_arm_cq(wq->parent, wq->cq->cq_id, 0, TRUE);
973231437Sluigi	return 0;
974231437Sluigi}
975231437Sluigi
976231437Sluigi
977231437Sluigi
978231437Sluigi/**
979231437Sluigi * @brief		Start a mailbox queue
980231437Sluigi * @param mq		pointer to a mailbox queue
981231437Sluigi */
982231437Sluigiint
983231437Sluigioce_start_mq(struct oce_mq *mq)
984231437Sluigi{
985231437Sluigi	oce_arm_cq(mq->parent, mq->cq->cq_id, 0, TRUE);
986231437Sluigi	return 0;
987231437Sluigi}
988231437Sluigi
989231437Sluigi
990231437Sluigi
991231437Sluigi/**
992231437Sluigi * @brief		Function to arm an EQ so that it can generate events
993231437Sluigi * @param sc		software handle to the device
994231437Sluigi * @param qid		id of the EQ returned by the fw at the time of creation
995231437Sluigi * @param npopped	number of EQEs to arm
996231437Sluigi * @param rearm		rearm bit enable/disable
997231437Sluigi * @param clearint	bit to clear the interrupt condition because of which
998231437Sluigi *			EQEs are generated
999231437Sluigi */
1000231437Sluigivoid
1001231437Sluigioce_arm_eq(POCE_SOFTC sc,
1002231437Sluigi	   int16_t qid, int npopped, uint32_t rearm, uint32_t clearint)
1003231437Sluigi{
1004231437Sluigi	eq_db_t eq_db = { 0 };
1005231437Sluigi
1006231437Sluigi	eq_db.bits.rearm = rearm;
1007231437Sluigi	eq_db.bits.event = 1;
1008231437Sluigi	eq_db.bits.num_popped = npopped;
1009231437Sluigi	eq_db.bits.clrint = clearint;
1010231437Sluigi	eq_db.bits.qid = qid;
1011231437Sluigi	OCE_WRITE_REG32(sc, db, PD_EQ_DB, eq_db.dw0);
1012231437Sluigi
1013231437Sluigi}
1014231437Sluigi
1015231437Sluigi
1016231437Sluigi
1017231437Sluigi
1018231437Sluigi/**
1019231437Sluigi * @brief		Function to arm a CQ with CQEs
1020231437Sluigi * @param sc		software handle to the device
1021231437Sluigi * @param qid		id of the CQ returned by the fw at the time of creation
1022231437Sluigi * @param npopped	number of CQEs to arm
1023231437Sluigi * @param rearm		rearm bit enable/disable
1024231437Sluigi */
1025231437Sluigivoid oce_arm_cq(POCE_SOFTC sc, int16_t qid, int npopped, uint32_t rearm)
1026231437Sluigi{
1027231437Sluigi	cq_db_t cq_db = { 0 };
1028231437Sluigi
1029231437Sluigi	cq_db.bits.rearm = rearm;
1030231437Sluigi	cq_db.bits.num_popped = npopped;
1031231437Sluigi	cq_db.bits.event = 0;
1032231437Sluigi	cq_db.bits.qid = qid;
1033231437Sluigi	OCE_WRITE_REG32(sc, db, PD_CQ_DB, cq_db.dw0);
1034231437Sluigi
1035231437Sluigi}
1036231437Sluigi
1037231437Sluigi
1038231437Sluigi
1039231437Sluigi
1040231437Sluigi/*
1041231437Sluigi * @brief		function to cleanup the eqs used during stop
1042231437Sluigi * @param eq		pointer to event queue structure
1043231437Sluigi * @returns		the number of EQs processed
1044231437Sluigi */
1045231437Sluigivoid
1046231437Sluigioce_drain_eq(struct oce_eq *eq)
1047231437Sluigi{
1048231437Sluigi
1049231437Sluigi	struct oce_eqe *eqe;
1050231437Sluigi	uint16_t num_eqe = 0;
1051231437Sluigi	POCE_SOFTC sc = eq->parent;
1052231437Sluigi
1053231437Sluigi	do {
1054231437Sluigi		eqe = RING_GET_CONSUMER_ITEM_VA(eq->ring, struct oce_eqe);
1055231437Sluigi		if (eqe->evnt == 0)
1056231437Sluigi			break;
1057231437Sluigi		eqe->evnt = 0;
1058231437Sluigi		bus_dmamap_sync(eq->ring->dma.tag, eq->ring->dma.map,
1059231437Sluigi					BUS_DMASYNC_POSTWRITE);
1060231437Sluigi		num_eqe++;
1061231437Sluigi		RING_GET(eq->ring, 1);
1062231437Sluigi
1063231437Sluigi	} while (TRUE);
1064231437Sluigi
1065231437Sluigi	oce_arm_eq(sc, eq->eq_id, num_eqe, FALSE, TRUE);
1066231437Sluigi
1067231437Sluigi}
1068231437Sluigi
1069231437Sluigi
1070231437Sluigi
1071231437Sluigivoid
1072231437Sluigioce_drain_wq_cq(struct oce_wq *wq)
1073231437Sluigi{
1074231437Sluigi        POCE_SOFTC sc = wq->parent;
1075231437Sluigi        struct oce_cq *cq = wq->cq;
1076231437Sluigi        struct oce_nic_tx_cqe *cqe;
1077231437Sluigi        int num_cqes = 0;
1078231437Sluigi
1079231437Sluigi	bus_dmamap_sync(cq->ring->dma.tag, cq->ring->dma.map,
1080231437Sluigi				 BUS_DMASYNC_POSTWRITE);
1081231437Sluigi
1082231437Sluigi	do {
1083231437Sluigi		cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_tx_cqe);
1084231437Sluigi		if (cqe->u0.dw[3] == 0)
1085231437Sluigi			break;
1086231437Sluigi		cqe->u0.dw[3] = 0;
1087231437Sluigi		bus_dmamap_sync(cq->ring->dma.tag, cq->ring->dma.map,
1088231437Sluigi				 BUS_DMASYNC_POSTWRITE);
1089231437Sluigi		RING_GET(cq->ring, 1);
1090231437Sluigi		num_cqes++;
1091231437Sluigi
1092231437Sluigi	} while (TRUE);
1093231437Sluigi
1094231437Sluigi	oce_arm_cq(sc, cq->cq_id, num_cqes, FALSE);
1095231437Sluigi
1096231437Sluigi}
1097231437Sluigi
1098231437Sluigi
1099231437Sluigi/*
1100231437Sluigi * @brief		function to drain a MCQ and process its CQEs
1101231437Sluigi * @param dev		software handle to the device
1102231437Sluigi * @param cq		pointer to the cq to drain
1103231437Sluigi * @returns		the number of CQEs processed
1104231437Sluigi */
1105231437Sluigivoid
1106231437Sluigioce_drain_mq_cq(void *arg)
1107231437Sluigi{
1108231437Sluigi	/* TODO: additional code. */
1109231437Sluigi	return;
1110231437Sluigi}
1111231437Sluigi
1112231437Sluigi
1113231437Sluigi
1114231437Sluigi/**
1115231437Sluigi * @brief		function to process a Recieve queue
1116231437Sluigi * @param arg		pointer to the RQ to charge
1117231437Sluigi * @return		number of cqes processed
1118231437Sluigi */
1119231437Sluigivoid
1120231437Sluigioce_drain_rq_cq(struct oce_rq *rq)
1121231437Sluigi{
1122231437Sluigi	struct oce_nic_rx_cqe *cqe;
1123231437Sluigi	uint16_t num_cqe = 0;
1124231437Sluigi	struct oce_cq  *cq;
1125231437Sluigi	POCE_SOFTC sc;
1126231437Sluigi
1127231437Sluigi	sc = rq->parent;
1128231437Sluigi	cq = rq->cq;
1129231437Sluigi	cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_rx_cqe);
1130231437Sluigi	/* dequeue till you reach an invalid cqe */
1131231437Sluigi	while (RQ_CQE_VALID(cqe)) {
1132231437Sluigi		RQ_CQE_INVALIDATE(cqe);
1133231437Sluigi		RING_GET(cq->ring, 1);
1134231437Sluigi		cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring,
1135231437Sluigi		    struct oce_nic_rx_cqe);
1136231437Sluigi		num_cqe++;
1137231437Sluigi	}
1138231437Sluigi	oce_arm_cq(sc, cq->cq_id, num_cqe, FALSE);
1139231437Sluigi
1140231437Sluigi	return;
1141231437Sluigi}
1142231437Sluigi
1143231437Sluigi
1144231437Sluigivoid
1145231437Sluigioce_free_posted_rxbuf(struct oce_rq *rq)
1146231437Sluigi{
1147231437Sluigi	struct oce_packet_desc *pd;
1148231437Sluigi
1149231437Sluigi	while (rq->pending) {
1150231437Sluigi
1151231437Sluigi		pd = &rq->pckts[rq->packets_out];
1152231437Sluigi		bus_dmamap_sync(rq->tag, pd->map, BUS_DMASYNC_POSTWRITE);
1153231437Sluigi		bus_dmamap_unload(rq->tag, pd->map);
1154231437Sluigi		if (pd->mbuf != NULL) {
1155231437Sluigi			m_freem(pd->mbuf);
1156231437Sluigi			pd->mbuf = NULL;
1157231437Sluigi		}
1158231437Sluigi
1159231437Sluigi		if ((rq->packets_out + 1) == OCE_RQ_PACKET_ARRAY_SIZE)
1160231437Sluigi			rq->packets_out = 0;
1161231437Sluigi		else
1162231437Sluigi			rq->packets_out++;
1163231437Sluigi
1164231437Sluigi                rq->pending--;
1165231437Sluigi	}
1166231437Sluigi
1167231437Sluigi}
1168231437Sluigi
1169231437Sluigivoid
1170231437Sluigioce_stop_rx(POCE_SOFTC sc)
1171231437Sluigi{
1172231437Sluigi	struct oce_mbx mbx;
1173231437Sluigi	struct mbx_delete_nic_rq *fwcmd;
1174231437Sluigi	struct oce_rq *rq;
1175231437Sluigi	int i = 0;
1176231437Sluigi
1177231437Sluigi	for_all_rq_queues(sc, rq, i) {
1178231437Sluigi		if (rq->qstate == QCREATED) {
1179231437Sluigi			/* Delete rxq in firmware */
1180231437Sluigi
1181231437Sluigi			bzero(&mbx, sizeof(mbx));
1182231437Sluigi			fwcmd = (struct mbx_delete_nic_rq *)&mbx.payload;
1183231437Sluigi			fwcmd->params.req.rq_id = rq->rq_id;
1184231437Sluigi
1185231437Sluigi			(void)oce_destroy_q(sc, &mbx,
1186231437Sluigi				sizeof(struct mbx_delete_nic_rq), QTYPE_RQ);
1187231437Sluigi
1188231437Sluigi			rq->qstate = QDELETED;
1189231437Sluigi
1190231437Sluigi			DELAY(1);
1191231437Sluigi
1192231437Sluigi			/* Free posted RX buffers that are not used */
1193231437Sluigi			oce_free_posted_rxbuf(rq);
1194231437Sluigi
1195231437Sluigi		}
1196231437Sluigi	}
1197231437Sluigi}
1198231437Sluigi
1199231437Sluigi
1200231437Sluigi
1201231437Sluigiint
1202231437Sluigioce_start_rx(POCE_SOFTC sc)
1203231437Sluigi{
1204231437Sluigi	struct oce_rq *rq;
1205231437Sluigi	int rc = 0, i;
1206231437Sluigi
1207231437Sluigi	for_all_rq_queues(sc, rq, i) {
1208231437Sluigi		if (rq->qstate == QCREATED)
1209231437Sluigi			continue;
1210231437Sluigi		rc = oce_mbox_create_rq(rq);
1211231437Sluigi		if (rc)
1212231437Sluigi			goto error;
1213231437Sluigi		/* reset queue pointers */
1214231437Sluigi		rq->qstate 	 = QCREATED;
1215231437Sluigi		rq->pending	 = 0;
1216231437Sluigi		rq->ring->cidx	 = 0;
1217231437Sluigi		rq->ring->pidx	 = 0;
1218231437Sluigi		rq->packets_in	 = 0;
1219231437Sluigi		rq->packets_out	 = 0;
1220231437Sluigi	}
1221231437Sluigi
1222231437Sluigi	DELAY(1);
1223231437Sluigi
1224231437Sluigi	/* RSS config */
1225252869Sdelphij	if (is_rss_enabled(sc)) {
1226231437Sluigi		rc = oce_config_nic_rss(sc, (uint8_t) sc->if_id, RSS_ENABLE);
1227231437Sluigi		if (rc)
1228231437Sluigi			goto error;
1229231437Sluigi
1230231437Sluigi	}
1231231437Sluigi
1232231437Sluigi	return rc;
1233231437Sluigierror:
1234231437Sluigi	device_printf(sc->dev, "Start RX failed\n");
1235231437Sluigi	return rc;
1236231437Sluigi
1237231437Sluigi}
1238231437Sluigi
1239231437Sluigi
1240231437Sluigi
1241