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