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