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