1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (C) 2013 Emulex
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the Emulex Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived from
19 * this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 * Contact Information:
34 * [email protected]
35 *
36 * Emulex
37 * 3333 Susan Street
38 * Costa Mesa, CA 92626
39 */
40
41 /* $FreeBSD$ */
42
43 #include "oce_if.h"
44
45 /*****************************************************
46 * local queue functions
47 *****************************************************/
48
49 static struct oce_wq *oce_wq_init(POCE_SOFTC sc,
50 uint32_t q_len, uint32_t wq_type);
51 static int oce_wq_create(struct oce_wq *wq, struct oce_eq *eq);
52 static void oce_wq_free(struct oce_wq *wq);
53 static void oce_wq_del(struct oce_wq *wq);
54 static struct oce_rq *oce_rq_init(POCE_SOFTC sc,
55 uint32_t q_len,
56 uint32_t frag_size,
57 uint32_t mtu, uint32_t rss);
58 static int oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq);
59 static void oce_rq_free(struct oce_rq *rq);
60 static void oce_rq_del(struct oce_rq *rq);
61 static struct oce_eq *oce_eq_create(POCE_SOFTC sc,
62 uint32_t q_len,
63 uint32_t item_size,
64 uint32_t eq_delay,
65 uint32_t vector);
66 static void oce_eq_del(struct oce_eq *eq);
67 static struct oce_mq *oce_mq_create(POCE_SOFTC sc,
68 struct oce_eq *eq, uint32_t q_len);
69 static void oce_mq_free(struct oce_mq *mq);
70 static int oce_destroy_q(POCE_SOFTC sc, struct oce_mbx
71 *mbx, size_t req_size, enum qtype qtype, int version);
72 struct oce_cq *oce_cq_create(POCE_SOFTC sc,
73 struct oce_eq *eq,
74 uint32_t q_len,
75 uint32_t item_size,
76 uint32_t sol_event,
77 uint32_t is_eventable,
78 uint32_t nodelay, uint32_t ncoalesce);
79 static void oce_cq_del(POCE_SOFTC sc, struct oce_cq *cq);
80
81
82
83 /**
84 * @brief Create and initialize all the queues on the board
85 * @param sc software handle to the device
86 * @returns 0 if successful, or error
87 **/
88 int
oce_queue_init_all(POCE_SOFTC sc)89 oce_queue_init_all(POCE_SOFTC sc)
90 {
91 int rc = 0, i, vector;
92 struct oce_wq *wq;
93 struct oce_rq *rq;
94 struct oce_aic_obj *aic;
95
96 /* alloc TX/RX queues */
97 for_all_wq_queues(sc, wq, i) {
98 sc->wq[i] = oce_wq_init(sc, sc->tx_ring_size,
99 NIC_WQ_TYPE_STANDARD);
100 if (!sc->wq[i])
101 goto error;
102
103 }
104
105 for_all_rq_queues(sc, rq, i) {
106 sc->rq[i] = oce_rq_init(sc, sc->rx_ring_size, sc->rq_frag_size,
107 OCE_MAX_JUMBO_FRAME_SIZE,
108 (i == 0) ? 0 : is_rss_enabled(sc));
109 if (!sc->rq[i])
110 goto error;
111 }
112
113 /* Create network interface on card */
114 if (oce_create_nw_interface(sc))
115 goto error;
116
117 /* create all of the event queues */
118 for (vector = 0; vector < sc->intr_count; vector++) {
119 /* setup aic defaults for each event queue */
120 aic = &sc->aic_obj[vector];
121 aic->max_eqd = OCE_MAX_EQD;
122 aic->min_eqd = OCE_MIN_EQD;
123 aic->et_eqd = OCE_MIN_EQD;
124 aic->enable = TRUE;
125
126 sc->eq[vector] = oce_eq_create(sc, sc->enable_hwlro ? EQ_LEN_2048 : EQ_LEN_1024,
127 EQE_SIZE_4,0, vector);
128
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 /* before deleting lro queues, we have to disable hwlro */
176 if(sc->enable_hwlro)
177 oce_mbox_nic_set_iface_lro_config(sc, 0);
178
179 for_all_rq_queues(sc, rq, i) {
180 if (rq) {
181 oce_rq_del(sc->rq[i]);
182 oce_rq_free(sc->rq[i]);
183 }
184 }
185
186 for_all_wq_queues(sc, wq, i) {
187 if (wq) {
188 oce_wq_del(sc->wq[i]);
189 oce_wq_free(sc->wq[i]);
190 }
191 }
192
193 if (sc->mq)
194 oce_mq_free(sc->mq);
195
196 for_all_evnt_queues(sc, eq, i) {
197 if (eq)
198 oce_eq_del(sc->eq[i]);
199 }
200 }
201
202
203
204 /**
205 * @brief Function to create a WQ for NIC Tx
206 * @param sc software handle to the device
207 * @param qlen number of entries in the queue
208 * @param wq_type work queue type
209 * @returns the pointer to the WQ created or NULL on failure
210 */
211 static struct
oce_wq_init(POCE_SOFTC sc,uint32_t q_len,uint32_t wq_type)212 oce_wq *oce_wq_init(POCE_SOFTC sc, uint32_t q_len, uint32_t wq_type)
213 {
214 struct oce_wq *wq;
215 int rc = 0, i;
216
217 /* q_len must be min 256 and max 2k */
218 if (q_len < 256 || q_len > 2048) {
219 device_printf(sc->dev,
220 "Invalid q length. Must be "
221 "[256, 2000]: 0x%x\n", q_len);
222 return NULL;
223 }
224
225 /* allocate wq */
226 wq = malloc(sizeof(struct oce_wq), M_DEVBUF, M_NOWAIT | M_ZERO);
227 if (!wq)
228 return NULL;
229
230 /* Set the wq config */
231 wq->cfg.q_len = q_len;
232 wq->cfg.wq_type = (uint8_t) wq_type;
233 wq->cfg.eqd = OCE_DEFAULT_WQ_EQD;
234 wq->cfg.nbufs = 2 * wq->cfg.q_len;
235 wq->cfg.nhdl = 2 * wq->cfg.q_len;
236
237 wq->parent = (void *)sc;
238
239 rc = bus_dma_tag_create(bus_get_dma_tag(sc->dev),
240 1, 0,
241 BUS_SPACE_MAXADDR,
242 BUS_SPACE_MAXADDR,
243 NULL, NULL,
244 OCE_MAX_TX_SIZE,
245 OCE_MAX_TX_ELEMENTS,
246 PAGE_SIZE, 0, NULL, NULL, &wq->tag);
247
248 if (rc)
249 goto free_wq;
250
251
252 for (i = 0; i < OCE_WQ_PACKET_ARRAY_SIZE; i++) {
253 rc = bus_dmamap_create(wq->tag, 0, &wq->pckts[i].map);
254 if (rc)
255 goto free_wq;
256 }
257
258 wq->ring = oce_create_ring_buffer(sc, q_len, NIC_WQE_SIZE);
259 if (!wq->ring)
260 goto free_wq;
261
262
263 LOCK_CREATE(&wq->tx_lock, "TX_lock");
264 LOCK_CREATE(&wq->tx_compl_lock, "WQ_HANDLER_LOCK");
265
266 #if __FreeBSD_version >= 800000
267 /* Allocate buf ring for multiqueue*/
268 wq->br = buf_ring_alloc(4096, M_DEVBUF,
269 M_WAITOK, &wq->tx_lock.mutex);
270 if (!wq->br)
271 goto free_wq;
272 #endif
273 return wq;
274
275
276 free_wq:
277 device_printf(sc->dev, "Create WQ failed\n");
278 oce_wq_free(wq);
279 return NULL;
280 }
281
282
283
284 /**
285 * @brief Frees the work queue
286 * @param wq pointer to work queue to free
287 */
288 static void
oce_wq_free(struct oce_wq * wq)289 oce_wq_free(struct oce_wq *wq)
290 {
291 POCE_SOFTC sc = (POCE_SOFTC) wq->parent;
292 int i;
293
294 taskqueue_drain(taskqueue_swi, &wq->txtask);
295
296 if (wq->ring != NULL) {
297 oce_destroy_ring_buffer(sc, wq->ring);
298 wq->ring = NULL;
299 }
300
301 for (i = 0; i < OCE_WQ_PACKET_ARRAY_SIZE; i++) {
302 if (wq->pckts[i].map != NULL) {
303 bus_dmamap_unload(wq->tag, wq->pckts[i].map);
304 bus_dmamap_destroy(wq->tag, wq->pckts[i].map);
305 wq->pckts[i].map = NULL;
306 }
307 }
308
309 if (wq->tag != NULL)
310 bus_dma_tag_destroy(wq->tag);
311 if (wq->br != NULL)
312 buf_ring_free(wq->br, M_DEVBUF);
313
314 LOCK_DESTROY(&wq->tx_lock);
315 LOCK_DESTROY(&wq->tx_compl_lock);
316 free(wq, M_DEVBUF);
317 }
318
319
320
321 /**
322 * @brief Create a work queue
323 * @param wq pointer to work queue
324 * @param eq pointer to associated event queue
325 */
326 static int
oce_wq_create(struct oce_wq * wq,struct oce_eq * eq)327 oce_wq_create(struct oce_wq *wq, struct oce_eq *eq)
328 {
329 POCE_SOFTC sc = wq->parent;
330 struct oce_cq *cq;
331 int rc = 0;
332
333 /* create the CQ */
334 cq = oce_cq_create(sc,
335 eq,
336 CQ_LEN_1024,
337 sizeof(struct oce_nic_tx_cqe), 0, 1, 0, 3);
338 if (!cq)
339 return ENXIO;
340
341
342 wq->cq = cq;
343
344 rc = oce_mbox_create_wq(wq);
345 if (rc)
346 goto error;
347
348 wq->qstate = QCREATED;
349 wq->wq_free = wq->cfg.q_len;
350 wq->ring->cidx = 0;
351 wq->ring->pidx = 0;
352
353 eq->cq[eq->cq_valid] = cq;
354 eq->cq_valid++;
355 cq->cb_arg = wq;
356 cq->cq_handler = oce_wq_handler;
357
358 return 0;
359
360 error:
361 device_printf(sc->dev, "WQ create failed\n");
362 oce_wq_del(wq);
363 return rc;
364 }
365
366
367
368
369 /**
370 * @brief Delete a work queue
371 * @param wq pointer to work queue
372 */
373 static void
oce_wq_del(struct oce_wq * wq)374 oce_wq_del(struct oce_wq *wq)
375 {
376 struct oce_mbx mbx;
377 struct mbx_delete_nic_wq *fwcmd;
378 POCE_SOFTC sc = (POCE_SOFTC) wq->parent;
379
380 if (wq->qstate == QCREATED) {
381 bzero(&mbx, sizeof(struct oce_mbx));
382 /* now fill the command */
383 fwcmd = (struct mbx_delete_nic_wq *)&mbx.payload;
384 fwcmd->params.req.wq_id = wq->wq_id;
385 (void)oce_destroy_q(sc, &mbx,
386 sizeof(struct mbx_delete_nic_wq), QTYPE_WQ, 0);
387 wq->qstate = QDELETED;
388 }
389
390 if (wq->cq != NULL) {
391 oce_cq_del(sc, wq->cq);
392 wq->cq = NULL;
393 }
394 }
395
396
397
398 /**
399 * @brief function to allocate receive queue resources
400 * @param sc software handle to the device
401 * @param q_len length of receive queue
402 * @param frag_size size of an receive queue fragment
403 * @param mtu maximum transmission unit
404 * @param rss is-rss-queue flag
405 * @returns the pointer to the RQ created or NULL on failure
406 */
407 static struct
oce_rq_init(POCE_SOFTC sc,uint32_t q_len,uint32_t frag_size,uint32_t mtu,uint32_t rss)408 oce_rq *oce_rq_init(POCE_SOFTC sc,
409 uint32_t q_len,
410 uint32_t frag_size,
411 uint32_t mtu, uint32_t rss)
412 {
413 struct oce_rq *rq;
414 int rc = 0, i;
415
416 if (OCE_LOG2(frag_size) <= 0)
417 return NULL;
418
419 if ((q_len == 0) || (q_len > 1024))
420 return NULL;
421
422 /* allocate the rq */
423 rq = malloc(sizeof(struct oce_rq), M_DEVBUF, M_NOWAIT | M_ZERO);
424 if (!rq)
425 return NULL;
426
427
428 rq->cfg.q_len = q_len;
429 rq->cfg.frag_size = frag_size;
430 rq->cfg.mtu = mtu;
431 rq->cfg.eqd = 0;
432 rq->lro_pkts_queued = 0;
433 rq->cfg.is_rss_queue = rss;
434 rq->pending = 0;
435
436 rq->parent = (void *)sc;
437
438 rc = bus_dma_tag_create(bus_get_dma_tag(sc->dev),
439 1, 0,
440 BUS_SPACE_MAXADDR,
441 BUS_SPACE_MAXADDR,
442 NULL, NULL,
443 oce_rq_buf_size,
444 1, oce_rq_buf_size, 0, NULL, NULL, &rq->tag);
445 if (rc)
446 goto free_rq;
447
448 for (i = 0; i < OCE_RQ_PACKET_ARRAY_SIZE; i++) {
449 rc = bus_dmamap_create(rq->tag, 0, &rq->pckts[i].map);
450 if (rc)
451 goto free_rq;
452 }
453
454 /* create the ring buffer */
455 rq->ring = oce_create_ring_buffer(sc, q_len,
456 sizeof(struct oce_nic_rqe));
457 if (!rq->ring)
458 goto free_rq;
459
460 LOCK_CREATE(&rq->rx_lock, "RX_lock");
461
462 return rq;
463
464 free_rq:
465 device_printf(sc->dev, "Create RQ failed\n");
466 oce_rq_free(rq);
467 return NULL;
468 }
469
470
471
472
473 /**
474 * @brief Free a receive queue
475 * @param rq pointer to receive queue
476 */
477 static void
oce_rq_free(struct oce_rq * rq)478 oce_rq_free(struct oce_rq *rq)
479 {
480 POCE_SOFTC sc = (POCE_SOFTC) rq->parent;
481 int i = 0 ;
482
483 if (rq->ring != NULL) {
484 oce_destroy_ring_buffer(sc, rq->ring);
485 rq->ring = NULL;
486 }
487 for (i = 0; i < OCE_RQ_PACKET_ARRAY_SIZE; i++) {
488 if (rq->pckts[i].map != NULL) {
489 bus_dmamap_unload(rq->tag, rq->pckts[i].map);
490 bus_dmamap_destroy(rq->tag, rq->pckts[i].map);
491 rq->pckts[i].map = NULL;
492 }
493 if (rq->pckts[i].mbuf) {
494 m_free(rq->pckts[i].mbuf);
495 rq->pckts[i].mbuf = NULL;
496 }
497 }
498
499 if (rq->tag != NULL)
500 bus_dma_tag_destroy(rq->tag);
501
502 LOCK_DESTROY(&rq->rx_lock);
503 free(rq, M_DEVBUF);
504 }
505
506
507
508
509 /**
510 * @brief Create a receive queue
511 * @param rq receive queue
512 * @param if_id interface identifier index`
513 * @param eq pointer to event queue
514 */
515 static int
oce_rq_create(struct oce_rq * rq,uint32_t if_id,struct oce_eq * eq)516 oce_rq_create(struct oce_rq *rq, uint32_t if_id, struct oce_eq *eq)
517 {
518 POCE_SOFTC sc = rq->parent;
519 struct oce_cq *cq;
520
521 cq = oce_cq_create(sc, eq,
522 sc->enable_hwlro ? CQ_LEN_2048 : CQ_LEN_1024,
523 sizeof(struct oce_nic_rx_cqe), 0, 1, 0, 3);
524
525 if (!cq)
526 return ENXIO;
527
528 rq->cq = cq;
529 rq->cfg.if_id = if_id;
530
531 /* Dont create RQ here. Create in if_activate */
532 rq->qstate = 0;
533 rq->ring->cidx = 0;
534 rq->ring->pidx = 0;
535 eq->cq[eq->cq_valid] = cq;
536 eq->cq_valid++;
537 cq->cb_arg = rq;
538 cq->cq_handler = oce_rq_handler;
539
540 return 0;
541
542 }
543
544
545
546
547 /**
548 * @brief Delete a receive queue
549 * @param rq receive queue
550 */
551 static void
oce_rq_del(struct oce_rq * rq)552 oce_rq_del(struct oce_rq *rq)
553 {
554 POCE_SOFTC sc = (POCE_SOFTC) rq->parent;
555 struct oce_mbx mbx;
556 struct mbx_delete_nic_rq *fwcmd;
557 struct mbx_delete_nic_rq_v1 *fwcmd1;
558
559 if (rq->qstate == QCREATED) {
560 bzero(&mbx, sizeof(mbx));
561 if(!rq->islro) {
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, sizeof(struct mbx_delete_nic_rq), QTYPE_RQ, 0);
565 }else {
566 fwcmd1 = (struct mbx_delete_nic_rq_v1 *)&mbx.payload;
567 fwcmd1->params.req.rq_id = rq->rq_id;
568 fwcmd1->params.req.rq_flags = (NIC_RQ_FLAGS_RSS | NIC_RQ_FLAGS_LRO);
569 (void)oce_destroy_q(sc, &mbx, sizeof(struct mbx_delete_nic_rq_v1), QTYPE_RQ, 1);
570 }
571 rq->qstate = QDELETED;
572 }
573
574 if (rq->cq != NULL) {
575 oce_cq_del(sc, rq->cq);
576 rq->cq = NULL;
577 }
578 }
579
580
581
582 /**
583 * @brief function to create an event queue
584 * @param sc software handle to the device
585 * @param q_len length of event queue
586 * @param item_size size of an event queue item
587 * @param eq_delay event queue delay
588 * @retval eq success, pointer to event queue
589 * @retval NULL failure
590 */
591 static struct
oce_eq_create(POCE_SOFTC sc,uint32_t q_len,uint32_t item_size,uint32_t eq_delay,uint32_t vector)592 oce_eq *oce_eq_create(POCE_SOFTC sc, uint32_t q_len,
593 uint32_t item_size,
594 uint32_t eq_delay,
595 uint32_t vector)
596 {
597 struct oce_eq *eq;
598 int rc = 0;
599
600 /* allocate an eq */
601 eq = malloc(sizeof(struct oce_eq), M_DEVBUF, M_NOWAIT | M_ZERO);
602 if (eq == NULL)
603 return NULL;
604
605 eq->parent = (void *)sc;
606 eq->eq_id = 0xffff;
607 eq->ring = oce_create_ring_buffer(sc, q_len, item_size);
608 if (!eq->ring)
609 goto free_eq;
610
611 eq->eq_cfg.q_len = q_len;
612 eq->eq_cfg.item_size = item_size;
613 eq->eq_cfg.cur_eqd = (uint8_t) eq_delay;
614
615 rc = oce_mbox_create_eq(eq);
616 if (rc)
617 goto free_eq;
618
619 sc->intrs[sc->neqs++].eq = eq;
620
621 return eq;
622
623 free_eq:
624 oce_eq_del(eq);
625 return NULL;
626 }
627
628
629
630
631 /**
632 * @brief Function to delete an event queue
633 * @param eq pointer to an event queue
634 */
635 static void
oce_eq_del(struct oce_eq * eq)636 oce_eq_del(struct oce_eq *eq)
637 {
638 struct oce_mbx mbx;
639 struct mbx_destroy_common_eq *fwcmd;
640 POCE_SOFTC sc = (POCE_SOFTC) eq->parent;
641
642 if (eq->eq_id != 0xffff) {
643 bzero(&mbx, sizeof(mbx));
644 fwcmd = (struct mbx_destroy_common_eq *)&mbx.payload;
645 fwcmd->params.req.id = eq->eq_id;
646 (void)oce_destroy_q(sc, &mbx,
647 sizeof(struct mbx_destroy_common_eq), QTYPE_EQ, 0);
648 }
649
650 if (eq->ring != NULL) {
651 oce_destroy_ring_buffer(sc, eq->ring);
652 eq->ring = NULL;
653 }
654
655 free(eq, M_DEVBUF);
656
657 }
658
659
660
661
662 /**
663 * @brief Function to create an MQ
664 * @param sc software handle to the device
665 * @param eq the EQ to associate with the MQ for event notification
666 * @param q_len the number of entries to create in the MQ
667 * @returns pointer to the created MQ, failure otherwise
668 */
669 static struct oce_mq *
oce_mq_create(POCE_SOFTC sc,struct oce_eq * eq,uint32_t q_len)670 oce_mq_create(POCE_SOFTC sc, struct oce_eq *eq, uint32_t q_len)
671 {
672 struct oce_mbx mbx;
673 struct mbx_create_common_mq_ex *fwcmd = NULL;
674 struct oce_mq *mq = NULL;
675 int rc = 0;
676 struct oce_cq *cq;
677 oce_mq_ext_ctx_t *ctx;
678 uint32_t num_pages;
679 uint32_t page_size;
680 int version;
681
682 cq = oce_cq_create(sc, eq, CQ_LEN_256,
683 sizeof(struct oce_mq_cqe), 1, 1, 0, 0);
684 if (!cq)
685 return NULL;
686
687 /* allocate the mq */
688 mq = malloc(sizeof(struct oce_mq), M_DEVBUF, M_NOWAIT | M_ZERO);
689 if (!mq) {
690 oce_cq_del(sc, cq);
691 goto error;
692 }
693
694 mq->parent = sc;
695
696 mq->ring = oce_create_ring_buffer(sc, q_len, sizeof(struct oce_mbx));
697 if (!mq->ring)
698 goto error;
699
700 bzero(&mbx, sizeof(struct oce_mbx));
701
702 IS_XE201(sc) ? (version = OCE_MBX_VER_V1) : (version = OCE_MBX_VER_V0);
703 fwcmd = (struct mbx_create_common_mq_ex *)&mbx.payload;
704 mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
705 MBX_SUBSYSTEM_COMMON,
706 OPCODE_COMMON_CREATE_MQ_EXT,
707 MBX_TIMEOUT_SEC,
708 sizeof(struct mbx_create_common_mq_ex),
709 version);
710
711 num_pages = oce_page_list(mq->ring, &fwcmd->params.req.pages[0]);
712 page_size = mq->ring->num_items * mq->ring->item_size;
713
714 ctx = &fwcmd->params.req.context;
715
716 if (IS_XE201(sc)) {
717 ctx->v1.num_pages = num_pages;
718 ctx->v1.ring_size = OCE_LOG2(q_len) + 1;
719 ctx->v1.cq_id = cq->cq_id;
720 ctx->v1.valid = 1;
721 ctx->v1.async_cq_id = cq->cq_id;
722 ctx->v1.async_cq_valid = 1;
723 /* Subscribe to Link State and Group 5 Events(bits 1 & 5 set) */
724 ctx->v1.async_evt_bitmap |= LE_32(0x00000022);
725 ctx->v1.async_evt_bitmap |= LE_32(1 << ASYNC_EVENT_CODE_DEBUG);
726 ctx->v1.async_evt_bitmap |=
727 LE_32(1 << ASYNC_EVENT_CODE_SLIPORT);
728 }
729 else {
730 ctx->v0.num_pages = num_pages;
731 ctx->v0.cq_id = cq->cq_id;
732 ctx->v0.ring_size = OCE_LOG2(q_len) + 1;
733 ctx->v0.valid = 1;
734 /* Subscribe to Link State and Group5 Events(bits 1 & 5 set) */
735 ctx->v0.async_evt_bitmap = 0xffffffff;
736 }
737
738 mbx.u0.s.embedded = 1;
739 mbx.payload_length = sizeof(struct mbx_create_common_mq_ex);
740 DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
741
742 rc = oce_mbox_post(sc, &mbx, NULL);
743 if (!rc)
744 rc = fwcmd->hdr.u0.rsp.status;
745 if (rc) {
746 device_printf(sc->dev,"%s failed - cmd status: %d\n",
747 __FUNCTION__, rc);
748 goto error;
749 }
750 mq->mq_id = LE_16(fwcmd->params.rsp.mq_id);
751 mq->cq = cq;
752 eq->cq[eq->cq_valid] = cq;
753 eq->cq_valid++;
754 mq->cq->eq = eq;
755 mq->cfg.q_len = (uint8_t) q_len;
756 mq->cfg.eqd = 0;
757 mq->qstate = QCREATED;
758
759 mq->cq->cb_arg = mq;
760 mq->cq->cq_handler = oce_mq_handler;
761
762 return mq;
763
764 error:
765 device_printf(sc->dev, "MQ create failed\n");
766 oce_mq_free(mq);
767 mq = NULL;
768 return mq;
769 }
770
771
772
773
774
775 /**
776 * @brief Function to free a mailbox queue
777 * @param mq pointer to a mailbox queue
778 */
779 static void
oce_mq_free(struct oce_mq * mq)780 oce_mq_free(struct oce_mq *mq)
781 {
782 POCE_SOFTC sc = (POCE_SOFTC) mq->parent;
783 struct oce_mbx mbx;
784 struct mbx_destroy_common_mq *fwcmd;
785
786 if (!mq)
787 return;
788
789 if (mq->ring != NULL) {
790 oce_destroy_ring_buffer(sc, mq->ring);
791 mq->ring = NULL;
792 if (mq->qstate == QCREATED) {
793 bzero(&mbx, sizeof (struct oce_mbx));
794 fwcmd = (struct mbx_destroy_common_mq *)&mbx.payload;
795 fwcmd->params.req.id = mq->mq_id;
796 (void) oce_destroy_q(sc, &mbx,
797 sizeof (struct mbx_destroy_common_mq),
798 QTYPE_MQ, 0);
799 }
800 mq->qstate = QDELETED;
801 }
802
803 if (mq->cq != NULL) {
804 oce_cq_del(sc, mq->cq);
805 mq->cq = NULL;
806 }
807
808 free(mq, M_DEVBUF);
809 mq = NULL;
810 }
811
812
813
814 /**
815 * @brief Function to delete a EQ, CQ, MQ, WQ or RQ
816 * @param sc sofware handle to the device
817 * @param mbx mailbox command to send to the fw to delete the queue
818 * (mbx contains the queue information to delete)
819 * @param req_size the size of the mbx payload dependent on the qtype
820 * @param qtype the type of queue i.e. EQ, CQ, MQ, WQ or RQ
821 * @returns 0 on success, failure otherwise
822 */
823 static int
oce_destroy_q(POCE_SOFTC sc,struct oce_mbx * mbx,size_t req_size,enum qtype qtype,int version)824 oce_destroy_q(POCE_SOFTC sc, struct oce_mbx *mbx, size_t req_size,
825 enum qtype qtype, int version)
826 {
827 struct mbx_hdr *hdr = (struct mbx_hdr *)&mbx->payload;
828 int opcode;
829 int subsys;
830 int rc = 0;
831
832 switch (qtype) {
833 case QTYPE_EQ:
834 opcode = OPCODE_COMMON_DESTROY_EQ;
835 subsys = MBX_SUBSYSTEM_COMMON;
836 break;
837 case QTYPE_CQ:
838 opcode = OPCODE_COMMON_DESTROY_CQ;
839 subsys = MBX_SUBSYSTEM_COMMON;
840 break;
841 case QTYPE_MQ:
842 opcode = OPCODE_COMMON_DESTROY_MQ;
843 subsys = MBX_SUBSYSTEM_COMMON;
844 break;
845 case QTYPE_WQ:
846 opcode = NIC_DELETE_WQ;
847 subsys = MBX_SUBSYSTEM_NIC;
848 break;
849 case QTYPE_RQ:
850 opcode = NIC_DELETE_RQ;
851 subsys = MBX_SUBSYSTEM_NIC;
852 break;
853 default:
854 return EINVAL;
855 }
856
857 mbx_common_req_hdr_init(hdr, 0, 0, subsys,
858 opcode, MBX_TIMEOUT_SEC, req_size,
859 version);
860
861 mbx->u0.s.embedded = 1;
862 mbx->payload_length = (uint32_t) req_size;
863 DW_SWAP(u32ptr(mbx), mbx->payload_length + OCE_BMBX_RHDR_SZ);
864
865 rc = oce_mbox_post(sc, mbx, NULL);
866 if (!rc)
867 rc = hdr->u0.rsp.status;
868 if (rc)
869 device_printf(sc->dev,"%s failed - cmd status: %d\n",
870 __FUNCTION__, rc);
871 return rc;
872 }
873
874
875
876 /**
877 * @brief Function to create a completion queue
878 * @param sc software handle to the device
879 * @param eq optional eq to be associated with to the cq
880 * @param q_len length of completion queue
881 * @param item_size size of completion queue items
882 * @param sol_event command context event
883 * @param is_eventable event table
884 * @param nodelay no delay flag
885 * @param ncoalesce no coalescence flag
886 * @returns pointer to the cq created, NULL on failure
887 */
888 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)889 oce_cq_create(POCE_SOFTC sc, struct oce_eq *eq,
890 uint32_t q_len,
891 uint32_t item_size,
892 uint32_t sol_event,
893 uint32_t is_eventable,
894 uint32_t nodelay, uint32_t ncoalesce)
895 {
896 struct oce_cq *cq = NULL;
897 int rc = 0;
898
899 cq = malloc(sizeof(struct oce_cq), M_DEVBUF, M_NOWAIT | M_ZERO);
900 if (!cq)
901 return NULL;
902
903 cq->ring = oce_create_ring_buffer(sc, q_len, item_size);
904 if (!cq->ring)
905 goto error;
906
907 cq->parent = sc;
908 cq->eq = eq;
909 cq->cq_cfg.q_len = q_len;
910 cq->cq_cfg.item_size = item_size;
911 cq->cq_cfg.nodelay = (uint8_t) nodelay;
912
913 rc = oce_mbox_cq_create(cq, ncoalesce, is_eventable);
914 if (rc)
915 goto error;
916
917 sc->cq[sc->ncqs++] = cq;
918
919 return cq;
920
921 error:
922 device_printf(sc->dev, "CQ create failed\n");
923 oce_cq_del(sc, cq);
924 return NULL;
925 }
926
927
928
929 /**
930 * @brief Deletes the completion queue
931 * @param sc software handle to the device
932 * @param cq pointer to a completion queue
933 */
934 static void
oce_cq_del(POCE_SOFTC sc,struct oce_cq * cq)935 oce_cq_del(POCE_SOFTC sc, struct oce_cq *cq)
936 {
937 struct oce_mbx mbx;
938 struct mbx_destroy_common_cq *fwcmd;
939
940 if (cq->ring != NULL) {
941
942 bzero(&mbx, sizeof(struct oce_mbx));
943 /* now fill the command */
944 fwcmd = (struct mbx_destroy_common_cq *)&mbx.payload;
945 fwcmd->params.req.id = cq->cq_id;
946 (void)oce_destroy_q(sc, &mbx,
947 sizeof(struct mbx_destroy_common_cq), QTYPE_CQ, 0);
948 /*NOW destroy the ring */
949 oce_destroy_ring_buffer(sc, cq->ring);
950 cq->ring = NULL;
951 }
952
953 free(cq, M_DEVBUF);
954 cq = NULL;
955 }
956
957
958
959 /**
960 * @brief Start a receive queue
961 * @param rq pointer to a receive queue
962 */
963 int
oce_start_rq(struct oce_rq * rq)964 oce_start_rq(struct oce_rq *rq)
965 {
966 POCE_SOFTC sc = (POCE_SOFTC) rq->parent;
967 int rc;
968
969 if(sc->enable_hwlro)
970 rc = oce_alloc_rx_bufs(rq, 960);
971 else
972 rc = oce_alloc_rx_bufs(rq, rq->cfg.q_len - 1);
973
974 if (rc == 0)
975 oce_arm_cq(rq->parent, rq->cq->cq_id, 0, TRUE);
976
977 return rc;
978 }
979
980
981
982 /**
983 * @brief Start a work queue
984 * @param wq pointer to a work queue
985 */
986 int
oce_start_wq(struct oce_wq * wq)987 oce_start_wq(struct oce_wq *wq)
988 {
989 oce_arm_cq(wq->parent, wq->cq->cq_id, 0, TRUE);
990 return 0;
991 }
992
993
994
995 /**
996 * @brief Start a mailbox queue
997 * @param mq pointer to a mailbox queue
998 */
999 int
oce_start_mq(struct oce_mq * mq)1000 oce_start_mq(struct oce_mq *mq)
1001 {
1002 oce_arm_cq(mq->parent, mq->cq->cq_id, 0, TRUE);
1003 return 0;
1004 }
1005
1006
1007
1008 /**
1009 * @brief Function to arm an EQ so that it can generate events
1010 * @param sc software handle to the device
1011 * @param qid id of the EQ returned by the fw at the time of creation
1012 * @param npopped number of EQEs to arm
1013 * @param rearm rearm bit enable/disable
1014 * @param clearint bit to clear the interrupt condition because of which
1015 * EQEs are generated
1016 */
1017 void
oce_arm_eq(POCE_SOFTC sc,int16_t qid,int npopped,uint32_t rearm,uint32_t clearint)1018 oce_arm_eq(POCE_SOFTC sc,
1019 int16_t qid, int npopped, uint32_t rearm, uint32_t clearint)
1020 {
1021 eq_db_t eq_db = { 0 };
1022
1023 eq_db.bits.rearm = rearm;
1024 eq_db.bits.event = 1;
1025 eq_db.bits.num_popped = npopped;
1026 eq_db.bits.clrint = clearint;
1027 eq_db.bits.qid = qid;
1028 OCE_WRITE_REG32(sc, db, PD_EQ_DB, eq_db.dw0);
1029
1030 }
1031
1032
1033
1034
1035 /**
1036 * @brief Function to arm a CQ with CQEs
1037 * @param sc software handle to the device
1038 * @param qid id of the CQ returned by the fw at the time of creation
1039 * @param npopped number of CQEs to arm
1040 * @param rearm rearm bit enable/disable
1041 */
oce_arm_cq(POCE_SOFTC sc,int16_t qid,int npopped,uint32_t rearm)1042 void oce_arm_cq(POCE_SOFTC sc, int16_t qid, int npopped, uint32_t rearm)
1043 {
1044 cq_db_t cq_db = { 0 };
1045
1046 cq_db.bits.rearm = rearm;
1047 cq_db.bits.num_popped = npopped;
1048 cq_db.bits.event = 0;
1049 cq_db.bits.qid = qid;
1050 OCE_WRITE_REG32(sc, db, PD_CQ_DB, cq_db.dw0);
1051
1052 }
1053
1054
1055
1056
1057 /*
1058 * @brief function to cleanup the eqs used during stop
1059 * @param eq pointer to event queue structure
1060 * @returns the number of EQs processed
1061 */
1062 void
oce_drain_eq(struct oce_eq * eq)1063 oce_drain_eq(struct oce_eq *eq)
1064 {
1065
1066 struct oce_eqe *eqe;
1067 uint16_t num_eqe = 0;
1068 POCE_SOFTC sc = eq->parent;
1069
1070 do {
1071 eqe = RING_GET_CONSUMER_ITEM_VA(eq->ring, struct oce_eqe);
1072 if (eqe->evnt == 0)
1073 break;
1074 eqe->evnt = 0;
1075 bus_dmamap_sync(eq->ring->dma.tag, eq->ring->dma.map,
1076 BUS_DMASYNC_POSTWRITE);
1077 num_eqe++;
1078 RING_GET(eq->ring, 1);
1079
1080 } while (TRUE);
1081
1082 oce_arm_eq(sc, eq->eq_id, num_eqe, FALSE, TRUE);
1083
1084 }
1085
1086
1087
1088 void
oce_drain_wq_cq(struct oce_wq * wq)1089 oce_drain_wq_cq(struct oce_wq *wq)
1090 {
1091 POCE_SOFTC sc = wq->parent;
1092 struct oce_cq *cq = wq->cq;
1093 struct oce_nic_tx_cqe *cqe;
1094 int num_cqes = 0;
1095
1096 bus_dmamap_sync(cq->ring->dma.tag, cq->ring->dma.map,
1097 BUS_DMASYNC_POSTWRITE);
1098
1099 do {
1100 cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_tx_cqe);
1101 if (cqe->u0.dw[3] == 0)
1102 break;
1103 cqe->u0.dw[3] = 0;
1104 bus_dmamap_sync(cq->ring->dma.tag, cq->ring->dma.map,
1105 BUS_DMASYNC_POSTWRITE);
1106 RING_GET(cq->ring, 1);
1107 num_cqes++;
1108
1109 } while (TRUE);
1110
1111 oce_arm_cq(sc, cq->cq_id, num_cqes, FALSE);
1112
1113 }
1114
1115
1116 /*
1117 * @brief function to drain a MCQ and process its CQEs
1118 * @param dev software handle to the device
1119 * @param cq pointer to the cq to drain
1120 * @returns the number of CQEs processed
1121 */
1122 void
oce_drain_mq_cq(void * arg)1123 oce_drain_mq_cq(void *arg)
1124 {
1125 /* TODO: additional code. */
1126 return;
1127 }
1128
1129
1130
1131 /**
1132 * @brief function to process a Recieve queue
1133 * @param arg pointer to the RQ to charge
1134 * @return number of cqes processed
1135 */
1136 void
oce_drain_rq_cq(struct oce_rq * rq)1137 oce_drain_rq_cq(struct oce_rq *rq)
1138 {
1139 struct oce_nic_rx_cqe *cqe;
1140 uint16_t num_cqe = 0;
1141 struct oce_cq *cq;
1142 POCE_SOFTC sc;
1143
1144 sc = rq->parent;
1145 cq = rq->cq;
1146 cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_rx_cqe);
1147 /* dequeue till you reach an invalid cqe */
1148 while (RQ_CQE_VALID(cqe)) {
1149 RQ_CQE_INVALIDATE(cqe);
1150 RING_GET(cq->ring, 1);
1151 cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring,
1152 struct oce_nic_rx_cqe);
1153 num_cqe++;
1154 }
1155 oce_arm_cq(sc, cq->cq_id, num_cqe, FALSE);
1156
1157 return;
1158 }
1159
1160
1161 void
oce_free_posted_rxbuf(struct oce_rq * rq)1162 oce_free_posted_rxbuf(struct oce_rq *rq)
1163 {
1164 struct oce_packet_desc *pd;
1165
1166 while (rq->pending) {
1167
1168 pd = &rq->pckts[rq->ring->cidx];
1169 bus_dmamap_sync(rq->tag, pd->map, BUS_DMASYNC_POSTWRITE);
1170 bus_dmamap_unload(rq->tag, pd->map);
1171 if (pd->mbuf != NULL) {
1172 m_freem(pd->mbuf);
1173 pd->mbuf = NULL;
1174 }
1175
1176 RING_GET(rq->ring,1);
1177 rq->pending--;
1178 }
1179
1180 }
1181
1182 void
oce_rx_cq_clean_hwlro(struct oce_rq * rq)1183 oce_rx_cq_clean_hwlro(struct oce_rq *rq)
1184 {
1185 struct oce_cq *cq = rq->cq;
1186 POCE_SOFTC sc = rq->parent;
1187 struct nic_hwlro_singleton_cqe *cqe;
1188 struct nic_hwlro_cqe_part2 *cqe2;
1189 int flush_wait = 0;
1190 int flush_compl = 0;
1191 int num_frags = 0;
1192
1193 for (;;) {
1194 bus_dmamap_sync(cq->ring->dma.tag,cq->ring->dma.map, BUS_DMASYNC_POSTWRITE);
1195 cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct nic_hwlro_singleton_cqe);
1196 if(cqe->valid) {
1197 if(cqe->cqe_type == 0) { /* singleton cqe */
1198 /* we should not get singleton cqe after cqe1 on same rq */
1199 if(rq->cqe_firstpart != NULL) {
1200 device_printf(sc->dev, "Got singleton cqe after cqe1 \n");
1201 goto exit_rx_cq_clean_hwlro;
1202 }
1203 num_frags = cqe->pkt_size / rq->cfg.frag_size;
1204 if(cqe->pkt_size % rq->cfg.frag_size)
1205 num_frags++;
1206 oce_discard_rx_comp(rq, num_frags);
1207 /* Check if CQE is flush completion */
1208 if(!cqe->pkt_size)
1209 flush_compl = 1;
1210 cqe->valid = 0;
1211 RING_GET(cq->ring, 1);
1212 }else if(cqe->cqe_type == 0x1) { /* first part */
1213 /* we should not get cqe1 after cqe1 on same rq */
1214 if(rq->cqe_firstpart != NULL) {
1215 device_printf(sc->dev, "Got cqe1 after cqe1 \n");
1216 goto exit_rx_cq_clean_hwlro;
1217 }
1218 rq->cqe_firstpart = (struct nic_hwlro_cqe_part1 *)cqe;
1219 RING_GET(cq->ring, 1);
1220 }else if(cqe->cqe_type == 0x2) { /* second part */
1221 cqe2 = (struct nic_hwlro_cqe_part2 *)cqe;
1222 /* We should not get cqe2 without cqe1 */
1223 if(rq->cqe_firstpart == NULL) {
1224 device_printf(sc->dev, "Got cqe2 without cqe1 \n");
1225 goto exit_rx_cq_clean_hwlro;
1226 }
1227 num_frags = cqe2->coalesced_size / rq->cfg.frag_size;
1228 if(cqe2->coalesced_size % rq->cfg.frag_size)
1229 num_frags++;
1230
1231 /* Flush completion will always come in singleton CQE */
1232 oce_discard_rx_comp(rq, num_frags);
1233
1234 rq->cqe_firstpart->valid = 0;
1235 cqe2->valid = 0;
1236 rq->cqe_firstpart = NULL;
1237 RING_GET(cq->ring, 1);
1238 }
1239 oce_arm_cq(sc, cq->cq_id, 1, FALSE);
1240 if(flush_compl)
1241 break;
1242 }else {
1243 if (flush_wait++ > 100) {
1244 device_printf(sc->dev, "did not receive hwlro flush compl\n");
1245 break;
1246 }
1247 oce_arm_cq(sc, cq->cq_id, 0, TRUE);
1248 DELAY(1000);
1249 }
1250 }
1251
1252 /* After cleanup, leave the CQ in unarmed state */
1253 oce_arm_cq(sc, cq->cq_id, 0, FALSE);
1254
1255 exit_rx_cq_clean_hwlro:
1256 return;
1257 }
1258
1259
1260 void
oce_rx_cq_clean(struct oce_rq * rq)1261 oce_rx_cq_clean(struct oce_rq *rq)
1262 {
1263 struct oce_nic_rx_cqe *cqe;
1264 struct oce_cq *cq;
1265 POCE_SOFTC sc;
1266 int flush_wait = 0;
1267 int flush_compl = 0;
1268 sc = rq->parent;
1269 cq = rq->cq;
1270
1271 for (;;) {
1272 bus_dmamap_sync(cq->ring->dma.tag,
1273 cq->ring->dma.map, BUS_DMASYNC_POSTWRITE);
1274 cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_rx_cqe);
1275 if(RQ_CQE_VALID(cqe)) {
1276 DW_SWAP((uint32_t *) cqe, sizeof(oce_rq_cqe));
1277 oce_discard_rx_comp(rq, cqe->u0.s.num_fragments);
1278 /* Check if CQE is flush completion */
1279 if((cqe->u0.s.num_fragments==0)&&(cqe->u0.s.pkt_size == 0)&&(cqe->u0.s.error == 0))
1280 flush_compl = 1;
1281
1282 RQ_CQE_INVALIDATE(cqe);
1283 RING_GET(cq->ring, 1);
1284 #if defined(INET6) || defined(INET)
1285 if (IF_LRO_ENABLED(sc))
1286 oce_rx_flush_lro(rq);
1287 #endif
1288 oce_arm_cq(sc, cq->cq_id, 1, FALSE);
1289 if(flush_compl)
1290 break;
1291 }else {
1292 if (flush_wait++ > 100) {
1293 device_printf(sc->dev, "did not receive flush compl\n");
1294 break;
1295 }
1296 oce_arm_cq(sc, cq->cq_id, 0, TRUE);
1297 DELAY(1000);
1298 }
1299 }
1300
1301 /* After cleanup, leave the CQ in unarmed state */
1302 oce_arm_cq(sc, cq->cq_id, 0, FALSE);
1303 }
1304
1305 void
oce_stop_rx(POCE_SOFTC sc)1306 oce_stop_rx(POCE_SOFTC sc)
1307 {
1308 struct oce_mbx mbx;
1309 struct mbx_delete_nic_rq *fwcmd;
1310 struct mbx_delete_nic_rq_v1 *fwcmd1;
1311 struct oce_rq *rq;
1312 int i = 0;
1313
1314 /* before deleting disable hwlro */
1315 if(sc->enable_hwlro)
1316 oce_mbox_nic_set_iface_lro_config(sc, 0);
1317
1318 for_all_rq_queues(sc, rq, i) {
1319 if (rq->qstate == QCREATED) {
1320 /* Delete rxq in firmware */
1321 LOCK(&rq->rx_lock);
1322
1323 bzero(&mbx, sizeof(mbx));
1324 if(!rq->islro) {
1325 fwcmd = (struct mbx_delete_nic_rq *)&mbx.payload;
1326 fwcmd->params.req.rq_id = rq->rq_id;
1327 (void)oce_destroy_q(sc, &mbx, sizeof(struct mbx_delete_nic_rq), QTYPE_RQ, 0);
1328 }else {
1329 fwcmd1 = (struct mbx_delete_nic_rq_v1 *)&mbx.payload;
1330 fwcmd1->params.req.rq_id = rq->rq_id;
1331 fwcmd1->params.req.rq_flags = (NIC_RQ_FLAGS_RSS | NIC_RQ_FLAGS_LRO);
1332
1333 (void)oce_destroy_q(sc,&mbx,sizeof(struct mbx_delete_nic_rq_v1),QTYPE_RQ,1);
1334 }
1335 rq->qstate = QDELETED;
1336
1337 DELAY(1000);
1338
1339 if(!rq->islro)
1340 oce_rx_cq_clean(rq);
1341 else
1342 oce_rx_cq_clean_hwlro(rq);
1343
1344 /* Free posted RX buffers that are not used */
1345 oce_free_posted_rxbuf(rq);
1346 UNLOCK(&rq->rx_lock);
1347 }
1348 }
1349 }
1350
1351
1352
1353 int
oce_start_rx(POCE_SOFTC sc)1354 oce_start_rx(POCE_SOFTC sc)
1355 {
1356 struct oce_rq *rq;
1357 int rc = 0, i;
1358
1359 for_all_rq_queues(sc, rq, i) {
1360 if (rq->qstate == QCREATED)
1361 continue;
1362 if((i == 0) || (!sc->enable_hwlro)) {
1363 rc = oce_mbox_create_rq(rq);
1364 if (rc)
1365 goto error;
1366 rq->islro = 0;
1367 }else {
1368 rc = oce_mbox_create_rq_v2(rq);
1369 if (rc)
1370 goto error;
1371 rq->islro = 1;
1372 }
1373 /* reset queue pointers */
1374 rq->qstate = QCREATED;
1375 rq->pending = 0;
1376 rq->ring->cidx = 0;
1377 rq->ring->pidx = 0;
1378 }
1379
1380 if(sc->enable_hwlro) {
1381 rc = oce_mbox_nic_set_iface_lro_config(sc, 1);
1382 if (rc)
1383 goto error;
1384 }
1385
1386 DELAY(1);
1387
1388 /* RSS config */
1389 if (is_rss_enabled(sc)) {
1390 rc = oce_config_nic_rss(sc, (uint8_t) sc->if_id, RSS_ENABLE);
1391 if (rc)
1392 goto error;
1393
1394 }
1395
1396 DELAY(1);
1397 return rc;
1398 error:
1399 device_printf(sc->dev, "Start RX failed\n");
1400 return rc;
1401
1402 }
1403
1404
1405
1406