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