Deleted Added
full compact
1/*-
2 * Copyright (C) 2012 Emulex
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the Emulex Corporation nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * Contact Information:
32 * freebsd-drivers@emulex.com
33 *
34 * Emulex
35 * 3333 Susan Street
36 * Costa Mesa, CA 92626
37 */
38
39/* $FreeBSD: head/sys/dev/oce/oce_if.c 246482 2013-02-07 15:20:54Z rrs $ */
39/* $FreeBSD: head/sys/dev/oce/oce_if.c 246799 2013-02-14 17:34:17Z jpaetzel $ */
40
41#include "opt_inet6.h"
42#include "opt_inet.h"
43
44#include "oce_if.h"
45
46
47/* Driver entry points prototypes */
48static int oce_probe(device_t dev);
49static int oce_attach(device_t dev);
50static int oce_detach(device_t dev);
51static int oce_shutdown(device_t dev);
52static int oce_ioctl(struct ifnet *ifp, u_long command, caddr_t data);
53static void oce_init(void *xsc);
54static int oce_multiq_start(struct ifnet *ifp, struct mbuf *m);
55static void oce_multiq_flush(struct ifnet *ifp);
56
57/* Driver interrupt routines protypes */
58static void oce_intr(void *arg, int pending);
59static int oce_setup_intr(POCE_SOFTC sc);
60static int oce_fast_isr(void *arg);
61static int oce_alloc_intr(POCE_SOFTC sc, int vector,
62 void (*isr) (void *arg, int pending));
63
64/* Media callbacks prototypes */
65static void oce_media_status(struct ifnet *ifp, struct ifmediareq *req);
66static int oce_media_change(struct ifnet *ifp);
67
68/* Transmit routines prototypes */
69static int oce_tx(POCE_SOFTC sc, struct mbuf **mpp, int wq_index);
70static void oce_tx_restart(POCE_SOFTC sc, struct oce_wq *wq);
71static void oce_tx_complete(struct oce_wq *wq, uint32_t wqe_idx,
72 uint32_t status);
73static int oce_multiq_transmit(struct ifnet *ifp, struct mbuf *m,
74 struct oce_wq *wq);
75
76/* Receive routines prototypes */
77static void oce_discard_rx_comp(struct oce_rq *rq, struct oce_nic_rx_cqe *cqe);
78static int oce_cqe_vtp_valid(POCE_SOFTC sc, struct oce_nic_rx_cqe *cqe);
79static int oce_cqe_portid_valid(POCE_SOFTC sc, struct oce_nic_rx_cqe *cqe);
80static void oce_rx(struct oce_rq *rq, uint32_t rqe_idx,
81 struct oce_nic_rx_cqe *cqe);
82
83/* Helper function prototypes in this file */
84static int oce_attach_ifp(POCE_SOFTC sc);
85static void oce_add_vlan(void *arg, struct ifnet *ifp, uint16_t vtag);
86static void oce_del_vlan(void *arg, struct ifnet *ifp, uint16_t vtag);
87static int oce_vid_config(POCE_SOFTC sc);
88static void oce_mac_addr_set(POCE_SOFTC sc);
89static int oce_handle_passthrough(struct ifnet *ifp, caddr_t data);
90static void oce_local_timer(void *arg);
91static void oce_if_deactivate(POCE_SOFTC sc);
92static void oce_if_activate(POCE_SOFTC sc);
93static void setup_max_queues_want(POCE_SOFTC sc);
94static void update_queues_got(POCE_SOFTC sc);
95static void process_link_state(POCE_SOFTC sc,
96 struct oce_async_cqe_link_state *acqe);
97
98
99/* IP specific */
100#if defined(INET6) || defined(INET)
101static int oce_init_lro(POCE_SOFTC sc);
102static void oce_rx_flush_lro(struct oce_rq *rq);
103static struct mbuf * oce_tso_setup(POCE_SOFTC sc, struct mbuf **mpp);
104#endif
105
106static device_method_t oce_dispatch[] = {
107 DEVMETHOD(device_probe, oce_probe),
108 DEVMETHOD(device_attach, oce_attach),
109 DEVMETHOD(device_detach, oce_detach),
110 DEVMETHOD(device_shutdown, oce_shutdown),
111
112 DEVMETHOD_END
113};
114
115static driver_t oce_driver = {
116 "oce",
117 oce_dispatch,
118 sizeof(OCE_SOFTC)
119};
120static devclass_t oce_devclass;
121
122
123DRIVER_MODULE(oce, pci, oce_driver, oce_devclass, 0, 0);
124MODULE_DEPEND(oce, pci, 1, 1, 1);
125MODULE_DEPEND(oce, ether, 1, 1, 1);
126MODULE_VERSION(oce, 1);
127
128
129/* global vars */
130const char component_revision[32] = {"///" COMPONENT_REVISION "///"};
131
132/* Module capabilites and parameters */
133uint32_t oce_max_rsp_handled = OCE_MAX_RSP_HANDLED;
134uint32_t oce_enable_rss = OCE_MODCAP_RSS;
135
136
137TUNABLE_INT("hw.oce.max_rsp_handled", &oce_max_rsp_handled);
138TUNABLE_INT("hw.oce.enable_rss", &oce_enable_rss);
139
140
141/* Supported devices table */
142static uint32_t supportedDevices[] = {
143 (PCI_VENDOR_SERVERENGINES << 16) | PCI_PRODUCT_BE2,
144 (PCI_VENDOR_SERVERENGINES << 16) | PCI_PRODUCT_BE3,
145 (PCI_VENDOR_EMULEX << 16) | PCI_PRODUCT_BE3,
146 (PCI_VENDOR_EMULEX << 16) | PCI_PRODUCT_XE201,
147 (PCI_VENDOR_EMULEX << 16) | PCI_PRODUCT_XE201_VF,
148};
149
150
151
152
153/*****************************************************************************
154 * Driver entry points functions *
155 *****************************************************************************/
156
157static int
158oce_probe(device_t dev)
159{
160 uint16_t vendor = 0;
161 uint16_t device = 0;
162 int i = 0;
163 char str[256] = {0};
164 POCE_SOFTC sc;
165
166 sc = device_get_softc(dev);
167 bzero(sc, sizeof(OCE_SOFTC));
168 sc->dev = dev;
169
170 vendor = pci_get_vendor(dev);
171 device = pci_get_device(dev);
172
173 for (i = 0; i < (sizeof(supportedDevices) / sizeof(uint32_t)); i++) {
174 if (vendor == ((supportedDevices[i] >> 16) & 0xffff)) {
175 if (device == (supportedDevices[i] & 0xffff)) {
176 sprintf(str, "%s:%s", "Emulex CNA NIC function",
177 component_revision);
178 device_set_desc_copy(dev, str);
179
180 switch (device) {
181 case PCI_PRODUCT_BE2:
182 sc->flags |= OCE_FLAGS_BE2;
183 break;
184 case PCI_PRODUCT_BE3:
185 sc->flags |= OCE_FLAGS_BE3;
186 break;
187 case PCI_PRODUCT_XE201:
188 case PCI_PRODUCT_XE201_VF:
189 sc->flags |= OCE_FLAGS_XE201;
190 break;
191 default:
192 return ENXIO;
193 }
194 return BUS_PROBE_DEFAULT;
195 }
196 }
197 }
198
199 return ENXIO;
200}
201
202
203static int
204oce_attach(device_t dev)
205{
206 POCE_SOFTC sc;
207 int rc = 0;
208
209 sc = device_get_softc(dev);
210
211 rc = oce_hw_pci_alloc(sc);
212 if (rc)
213 return rc;
214
215 sc->rss_enable = oce_enable_rss;
216 sc->tx_ring_size = OCE_TX_RING_SIZE;
217 sc->rx_ring_size = OCE_RX_RING_SIZE;
218 sc->rq_frag_size = OCE_RQ_BUF_SIZE;
219 sc->flow_control = OCE_DEFAULT_FLOW_CONTROL;
220 sc->promisc = OCE_DEFAULT_PROMISCUOUS;
221
222 LOCK_CREATE(&sc->bmbx_lock, "Mailbox_lock");
223 LOCK_CREATE(&sc->dev_lock, "Device_lock");
224
225 /* initialise the hardware */
226 rc = oce_hw_init(sc);
227 if (rc)
228 goto pci_res_free;
229
230 setup_max_queues_want(sc);
231
232 rc = oce_setup_intr(sc);
233 if (rc)
234 goto mbox_free;
235
236 rc = oce_queue_init_all(sc);
237 if (rc)
238 goto intr_free;
239
240 rc = oce_attach_ifp(sc);
241 if (rc)
242 goto queues_free;
243
244#if defined(INET6) || defined(INET)
245 rc = oce_init_lro(sc);
246 if (rc)
247 goto ifp_free;
248#endif
249
250 rc = oce_hw_start(sc);
251 if (rc)
252 goto lro_free;
253
254 sc->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
255 oce_add_vlan, sc, EVENTHANDLER_PRI_FIRST);
256 sc->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
257 oce_del_vlan, sc, EVENTHANDLER_PRI_FIRST);
258
259 rc = oce_stats_init(sc);
260 if (rc)
261 goto vlan_free;
262
263 oce_add_sysctls(sc);
264
265 callout_init(&sc->timer, CALLOUT_MPSAFE);
266 rc = callout_reset(&sc->timer, 2 * hz, oce_local_timer, sc);
267 if (rc)
268 goto stats_free;
269#ifdef DEV_NETMAP
270#endif /* DEV_NETMAP */
271
272 return 0;
273
274stats_free:
275 callout_drain(&sc->timer);
276 oce_stats_free(sc);
277vlan_free:
278 if (sc->vlan_attach)
279 EVENTHANDLER_DEREGISTER(vlan_config, sc->vlan_attach);
280 if (sc->vlan_detach)
281 EVENTHANDLER_DEREGISTER(vlan_unconfig, sc->vlan_detach);
282 oce_hw_intr_disable(sc);
283lro_free:
284#if defined(INET6) || defined(INET)
285 oce_free_lro(sc);
286ifp_free:
287#endif
288 ether_ifdetach(sc->ifp);
289 if_free(sc->ifp);
290queues_free:
291 oce_queue_release_all(sc);
292intr_free:
293 oce_intr_free(sc);
294mbox_free:
295 oce_dma_free(sc, &sc->bsmbx);
296pci_res_free:
297 oce_hw_pci_free(sc);
298 LOCK_DESTROY(&sc->dev_lock);
299 LOCK_DESTROY(&sc->bmbx_lock);
300 return rc;
301
302}
303
304
305static int
306oce_detach(device_t dev)
307{
308 POCE_SOFTC sc = device_get_softc(dev);
309
310 LOCK(&sc->dev_lock);
311 oce_if_deactivate(sc);
312 UNLOCK(&sc->dev_lock);
313
314 callout_drain(&sc->timer);
315
316 if (sc->vlan_attach != NULL)
317 EVENTHANDLER_DEREGISTER(vlan_config, sc->vlan_attach);
318 if (sc->vlan_detach != NULL)
319 EVENTHANDLER_DEREGISTER(vlan_unconfig, sc->vlan_detach);
320
321 ether_ifdetach(sc->ifp);
322
323 if_free(sc->ifp);
324
325 oce_hw_shutdown(sc);
326
327 bus_generic_detach(dev);
328
329 return 0;
330}
331
332
333static int
334oce_shutdown(device_t dev)
335{
336 int rc;
337
338 rc = oce_detach(dev);
339
340 return rc;
341}
342
343
344static int
345oce_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
346{
347 struct ifreq *ifr = (struct ifreq *)data;
348 POCE_SOFTC sc = ifp->if_softc;
349 int rc = 0;
350 uint32_t u;
351
352 switch (command) {
353
354 case SIOCGIFMEDIA:
355 rc = ifmedia_ioctl(ifp, ifr, &sc->media, command);
356 break;
357
358 case SIOCSIFMTU:
359 if (ifr->ifr_mtu > OCE_MAX_MTU)
360 rc = EINVAL;
361 else
362 ifp->if_mtu = ifr->ifr_mtu;
363 break;
364
365 case SIOCSIFFLAGS:
366 if (ifp->if_flags & IFF_UP) {
367 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
368 sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
369 oce_init(sc);
370 }
371 device_printf(sc->dev, "Interface Up\n");
372 } else {
373 LOCK(&sc->dev_lock);
374
375 sc->ifp->if_drv_flags &=
376 ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
377 oce_if_deactivate(sc);
378
379 UNLOCK(&sc->dev_lock);
380
381 device_printf(sc->dev, "Interface Down\n");
382 }
383
384 if ((ifp->if_flags & IFF_PROMISC) && !sc->promisc) {
385 sc->promisc = TRUE;
386 oce_rxf_set_promiscuous(sc, sc->promisc);
387 } else if (!(ifp->if_flags & IFF_PROMISC) && sc->promisc) {
388 sc->promisc = FALSE;
389 oce_rxf_set_promiscuous(sc, sc->promisc);
390 }
391
392 break;
393
394 case SIOCADDMULTI:
395 case SIOCDELMULTI:
396 rc = oce_hw_update_multicast(sc);
397 if (rc)
398 device_printf(sc->dev,
399 "Update multicast address failed\n");
400 break;
401
402 case SIOCSIFCAP:
403 u = ifr->ifr_reqcap ^ ifp->if_capenable;
404
405 if (u & IFCAP_TXCSUM) {
406 ifp->if_capenable ^= IFCAP_TXCSUM;
407 ifp->if_hwassist ^= (CSUM_TCP | CSUM_UDP | CSUM_IP);
408
409 if (IFCAP_TSO & ifp->if_capenable &&
410 !(IFCAP_TXCSUM & ifp->if_capenable)) {
411 ifp->if_capenable &= ~IFCAP_TSO;
412 ifp->if_hwassist &= ~CSUM_TSO;
413 if_printf(ifp,
414 "TSO disabled due to -txcsum.\n");
415 }
416 }
417
418 if (u & IFCAP_RXCSUM)
419 ifp->if_capenable ^= IFCAP_RXCSUM;
420
421 if (u & IFCAP_TSO4) {
422 ifp->if_capenable ^= IFCAP_TSO4;
423
424 if (IFCAP_TSO & ifp->if_capenable) {
425 if (IFCAP_TXCSUM & ifp->if_capenable)
426 ifp->if_hwassist |= CSUM_TSO;
427 else {
428 ifp->if_capenable &= ~IFCAP_TSO;
429 ifp->if_hwassist &= ~CSUM_TSO;
430 if_printf(ifp,
431 "Enable txcsum first.\n");
432 rc = EAGAIN;
433 }
434 } else
435 ifp->if_hwassist &= ~CSUM_TSO;
436 }
437
438 if (u & IFCAP_VLAN_HWTAGGING)
439 ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
440
441 if (u & IFCAP_VLAN_HWFILTER) {
442 ifp->if_capenable ^= IFCAP_VLAN_HWFILTER;
443 oce_vid_config(sc);
444 }
445#if defined(INET6) || defined(INET)
446 if (u & IFCAP_LRO)
447 ifp->if_capenable ^= IFCAP_LRO;
448#endif
449
450 break;
451
452 case SIOCGPRIVATE_0:
453 rc = oce_handle_passthrough(ifp, data);
454 break;
455 default:
456 rc = ether_ioctl(ifp, command, data);
457 break;
458 }
459
460 return rc;
461}
462
463
464static void
465oce_init(void *arg)
466{
467 POCE_SOFTC sc = arg;
468
469 LOCK(&sc->dev_lock);
470
471 if (sc->ifp->if_flags & IFF_UP) {
472 oce_if_deactivate(sc);
473 oce_if_activate(sc);
474 }
475
476 UNLOCK(&sc->dev_lock);
477
478}
479
480
481static int
482oce_multiq_start(struct ifnet *ifp, struct mbuf *m)
483{
484 POCE_SOFTC sc = ifp->if_softc;
485 struct oce_wq *wq = NULL;
486 int queue_index = 0;
487 int status = 0;
488
489 if ((m->m_flags & M_FLOWID) != 0)
490 queue_index = m->m_pkthdr.flowid % sc->nwqs;
491
492 wq = sc->wq[queue_index];
493
494 if (TRY_LOCK(&wq->tx_lock)) {
495 status = oce_multiq_transmit(ifp, m, wq);
496 UNLOCK(&wq->tx_lock);
497 } else {
498 status = drbr_enqueue(ifp, wq->br, m);
499 }
500 return status;
501
502}
503
504
505static void
506oce_multiq_flush(struct ifnet *ifp)
507{
508 POCE_SOFTC sc = ifp->if_softc;
509 struct mbuf *m;
510 int i = 0;
511
512 for (i = 0; i < sc->nwqs; i++) {
513 while ((m = buf_ring_dequeue_sc(sc->wq[i]->br)) != NULL)
514 m_freem(m);
515 }
516 if_qflush(ifp);
517}
518
519
520
521/*****************************************************************************
522 * Driver interrupt routines functions *
523 *****************************************************************************/
524
525static void
526oce_intr(void *arg, int pending)
527{
528
529 POCE_INTR_INFO ii = (POCE_INTR_INFO) arg;
530 POCE_SOFTC sc = ii->sc;
531 struct oce_eq *eq = ii->eq;
532 struct oce_eqe *eqe;
533 struct oce_cq *cq = NULL;
534 int i, num_eqes = 0;
535
536
537 bus_dmamap_sync(eq->ring->dma.tag, eq->ring->dma.map,
538 BUS_DMASYNC_POSTWRITE);
539 do {
540 eqe = RING_GET_CONSUMER_ITEM_VA(eq->ring, struct oce_eqe);
541 if (eqe->evnt == 0)
542 break;
543 eqe->evnt = 0;
544 bus_dmamap_sync(eq->ring->dma.tag, eq->ring->dma.map,
545 BUS_DMASYNC_POSTWRITE);
546 RING_GET(eq->ring, 1);
547 num_eqes++;
548
549 } while (TRUE);
550
551 if (!num_eqes)
552 goto eq_arm; /* Spurious */
553
554 /* Clear EQ entries, but dont arm */
555 oce_arm_eq(sc, eq->eq_id, num_eqes, FALSE, FALSE);
556
557 /* Process TX, RX and MCC. But dont arm CQ*/
558 for (i = 0; i < eq->cq_valid; i++) {
559 cq = eq->cq[i];
560 (*cq->cq_handler)(cq->cb_arg);
561 }
562
563 /* Arm all cqs connected to this EQ */
564 for (i = 0; i < eq->cq_valid; i++) {
565 cq = eq->cq[i];
566 oce_arm_cq(sc, cq->cq_id, 0, TRUE);
567 }
568
569eq_arm:
570 oce_arm_eq(sc, eq->eq_id, 0, TRUE, FALSE);
571 return;
572}
573
574
575static int
576oce_setup_intr(POCE_SOFTC sc)
577{
578 int rc = 0, use_intx = 0;
579 int vector = 0, req_vectors = 0;
580
581 if (sc->rss_enable)
582 req_vectors = MAX((sc->nrqs - 1), sc->nwqs);
583 else
584 req_vectors = 1;
585
586 if (sc->flags & OCE_FLAGS_MSIX_CAPABLE) {
587 sc->intr_count = req_vectors;
588 rc = pci_alloc_msix(sc->dev, &sc->intr_count);
589 if (rc != 0) {
590 use_intx = 1;
591 pci_release_msi(sc->dev);
592 } else
593 sc->flags |= OCE_FLAGS_USING_MSIX;
594 } else
595 use_intx = 1;
596
597 if (use_intx)
598 sc->intr_count = 1;
599
600 /* Scale number of queues based on intr we got */
601 update_queues_got(sc);
602
603 if (use_intx) {
604 device_printf(sc->dev, "Using legacy interrupt\n");
605 rc = oce_alloc_intr(sc, vector, oce_intr);
606 if (rc)
607 goto error;
608 } else {
609 for (; vector < sc->intr_count; vector++) {
610 rc = oce_alloc_intr(sc, vector, oce_intr);
611 if (rc)
612 goto error;
613 }
614 }
615
616 return 0;
617error:
618 oce_intr_free(sc);
619 return rc;
620}
621
622
623static int
624oce_fast_isr(void *arg)
625{
626 POCE_INTR_INFO ii = (POCE_INTR_INFO) arg;
627 POCE_SOFTC sc = ii->sc;
628
629 if (ii->eq == NULL)
630 return FILTER_STRAY;
631
632 oce_arm_eq(sc, ii->eq->eq_id, 0, FALSE, TRUE);
633
634 taskqueue_enqueue_fast(ii->tq, &ii->task);
635
636 return FILTER_HANDLED;
637}
638
639
640static int
641oce_alloc_intr(POCE_SOFTC sc, int vector, void (*isr) (void *arg, int pending))
642{
643 POCE_INTR_INFO ii = &sc->intrs[vector];
644 int rc = 0, rr;
645
646 if (vector >= OCE_MAX_EQ)
647 return (EINVAL);
648
649 /* Set the resource id for the interrupt.
650 * MSIx is vector + 1 for the resource id,
651 * INTx is 0 for the resource id.
652 */
653 if (sc->flags & OCE_FLAGS_USING_MSIX)
654 rr = vector + 1;
655 else
656 rr = 0;
657 ii->intr_res = bus_alloc_resource_any(sc->dev,
658 SYS_RES_IRQ,
659 &rr, RF_ACTIVE|RF_SHAREABLE);
660 ii->irq_rr = rr;
661 if (ii->intr_res == NULL) {
662 device_printf(sc->dev,
663 "Could not allocate interrupt\n");
664 rc = ENXIO;
665 return rc;
666 }
667
668 TASK_INIT(&ii->task, 0, isr, ii);
669 ii->vector = vector;
670 sprintf(ii->task_name, "oce_task[%d]", ii->vector);
671 ii->tq = taskqueue_create_fast(ii->task_name,
672 M_NOWAIT,
673 taskqueue_thread_enqueue,
674 &ii->tq);
675 taskqueue_start_threads(&ii->tq, 1, PI_NET, "%s taskq",
676 device_get_nameunit(sc->dev));
677
678 ii->sc = sc;
679 rc = bus_setup_intr(sc->dev,
680 ii->intr_res,
681 INTR_TYPE_NET,
682 oce_fast_isr, NULL, ii, &ii->tag);
683 return rc;
684
685}
686
687
688void
689oce_intr_free(POCE_SOFTC sc)
690{
691 int i = 0;
692
693 for (i = 0; i < sc->intr_count; i++) {
694
695 if (sc->intrs[i].tag != NULL)
696 bus_teardown_intr(sc->dev, sc->intrs[i].intr_res,
697 sc->intrs[i].tag);
698 if (sc->intrs[i].tq != NULL)
699 taskqueue_free(sc->intrs[i].tq);
700
701 if (sc->intrs[i].intr_res != NULL)
702 bus_release_resource(sc->dev, SYS_RES_IRQ,
703 sc->intrs[i].irq_rr,
704 sc->intrs[i].intr_res);
705 sc->intrs[i].tag = NULL;
706 sc->intrs[i].intr_res = NULL;
707 }
708
709 if (sc->flags & OCE_FLAGS_USING_MSIX)
710 pci_release_msi(sc->dev);
711
712}
713
714
715
716/******************************************************************************
717* Media callbacks functions *
718******************************************************************************/
719
720static void
721oce_media_status(struct ifnet *ifp, struct ifmediareq *req)
722{
723 POCE_SOFTC sc = (POCE_SOFTC) ifp->if_softc;
724
725
726 req->ifm_status = IFM_AVALID;
727 req->ifm_active = IFM_ETHER;
728
729 if (sc->link_status == 1)
730 req->ifm_status |= IFM_ACTIVE;
731 else
732 return;
733
734 switch (sc->link_speed) {
735 case 1: /* 10 Mbps */
736 req->ifm_active |= IFM_10_T | IFM_FDX;
737 sc->speed = 10;
738 break;
739 case 2: /* 100 Mbps */
740 req->ifm_active |= IFM_100_TX | IFM_FDX;
741 sc->speed = 100;
742 break;
743 case 3: /* 1 Gbps */
744 req->ifm_active |= IFM_1000_T | IFM_FDX;
745 sc->speed = 1000;
746 break;
747 case 4: /* 10 Gbps */
748 req->ifm_active |= IFM_10G_SR | IFM_FDX;
749 sc->speed = 10000;
750 break;
751 }
752
753 return;
754}
755
756
757int
758oce_media_change(struct ifnet *ifp)
759{
760 return 0;
761}
762
763
764
765
766/*****************************************************************************
767 * Transmit routines functions *
768 *****************************************************************************/
769
770static int
771oce_tx(POCE_SOFTC sc, struct mbuf **mpp, int wq_index)
772{
773 int rc = 0, i, retry_cnt = 0;
774 bus_dma_segment_t segs[OCE_MAX_TX_ELEMENTS];
775 struct mbuf *m, *m_temp;
776 struct oce_wq *wq = sc->wq[wq_index];
777 struct oce_packet_desc *pd;
778 uint32_t out;
779 struct oce_nic_hdr_wqe *nichdr;
780 struct oce_nic_frag_wqe *nicfrag;
781 int num_wqes;
782 uint32_t reg_value;
783
784 m = *mpp;
785 if (!m)
786 return EINVAL;
787
788 if (!(m->m_flags & M_PKTHDR)) {
789 rc = ENXIO;
790 goto free_ret;
791 }
792
793 if (m->m_pkthdr.csum_flags & CSUM_TSO) {
794 /* consolidate packet buffers for TSO/LSO segment offload */
795#if defined(INET6) || defined(INET)
796 m = oce_tso_setup(sc, mpp);
797#else
798 m = NULL;
799#endif
800 if (m == NULL) {
801 rc = ENXIO;
802 goto free_ret;
803 }
804 }
805
806 out = wq->packets_out + 1;
807 if (out == OCE_WQ_PACKET_ARRAY_SIZE)
808 out = 0;
809 if (out == wq->packets_in)
810 return EBUSY;
811
812 pd = &wq->pckts[wq->packets_out];
813retry:
814 rc = bus_dmamap_load_mbuf_sg(wq->tag,
815 pd->map,
816 m, segs, &pd->nsegs, BUS_DMA_NOWAIT);
817 if (rc == 0) {
818 num_wqes = pd->nsegs + 1;
819 if (IS_BE(sc)) {
820 /*Dummy required only for BE3.*/
821 if (num_wqes & 1)
822 num_wqes++;
823 }
824 if (num_wqes >= RING_NUM_FREE(wq->ring)) {
825 bus_dmamap_unload(wq->tag, pd->map);
826 return EBUSY;
827 }
828
829 bus_dmamap_sync(wq->tag, pd->map, BUS_DMASYNC_PREWRITE);
830 pd->mbuf = m;
831 wq->packets_out = out;
832
833 nichdr =
834 RING_GET_PRODUCER_ITEM_VA(wq->ring, struct oce_nic_hdr_wqe);
835 nichdr->u0.dw[0] = 0;
836 nichdr->u0.dw[1] = 0;
837 nichdr->u0.dw[2] = 0;
838 nichdr->u0.dw[3] = 0;
839
840 nichdr->u0.s.complete = 1;
841 nichdr->u0.s.event = 1;
842 nichdr->u0.s.crc = 1;
843 nichdr->u0.s.forward = 0;
844 nichdr->u0.s.ipcs = (m->m_pkthdr.csum_flags & CSUM_IP) ? 1 : 0;
845 nichdr->u0.s.udpcs =
846 (m->m_pkthdr.csum_flags & CSUM_UDP) ? 1 : 0;
847 nichdr->u0.s.tcpcs =
848 (m->m_pkthdr.csum_flags & CSUM_TCP) ? 1 : 0;
849 nichdr->u0.s.num_wqe = num_wqes;
850 nichdr->u0.s.total_length = m->m_pkthdr.len;
851 if (m->m_flags & M_VLANTAG) {
852 nichdr->u0.s.vlan = 1; /*Vlan present*/
853 nichdr->u0.s.vlan_tag = m->m_pkthdr.ether_vtag;
854 }
855 if (m->m_pkthdr.csum_flags & CSUM_TSO) {
856 if (m->m_pkthdr.tso_segsz) {
857 nichdr->u0.s.lso = 1;
858 nichdr->u0.s.lso_mss = m->m_pkthdr.tso_segsz;
859 }
860 if (!IS_BE(sc))
861 nichdr->u0.s.ipcs = 1;
862 }
863
864 RING_PUT(wq->ring, 1);
865 wq->ring->num_used++;
866
867 for (i = 0; i < pd->nsegs; i++) {
868 nicfrag =
869 RING_GET_PRODUCER_ITEM_VA(wq->ring,
870 struct oce_nic_frag_wqe);
871 nicfrag->u0.s.rsvd0 = 0;
872 nicfrag->u0.s.frag_pa_hi = ADDR_HI(segs[i].ds_addr);
873 nicfrag->u0.s.frag_pa_lo = ADDR_LO(segs[i].ds_addr);
874 nicfrag->u0.s.frag_len = segs[i].ds_len;
875 pd->wqe_idx = wq->ring->pidx;
876 RING_PUT(wq->ring, 1);
877 wq->ring->num_used++;
878 }
879 if (num_wqes > (pd->nsegs + 1)) {
880 nicfrag =
881 RING_GET_PRODUCER_ITEM_VA(wq->ring,
882 struct oce_nic_frag_wqe);
883 nicfrag->u0.dw[0] = 0;
884 nicfrag->u0.dw[1] = 0;
885 nicfrag->u0.dw[2] = 0;
886 nicfrag->u0.dw[3] = 0;
887 pd->wqe_idx = wq->ring->pidx;
888 RING_PUT(wq->ring, 1);
889 wq->ring->num_used++;
890 pd->nsegs++;
891 }
892
893 sc->ifp->if_opackets++;
894 wq->tx_stats.tx_reqs++;
895 wq->tx_stats.tx_wrbs += num_wqes;
896 wq->tx_stats.tx_bytes += m->m_pkthdr.len;
897 wq->tx_stats.tx_pkts++;
898
899 bus_dmamap_sync(wq->ring->dma.tag, wq->ring->dma.map,
900 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
901 reg_value = (num_wqes << 16) | wq->wq_id;
902 OCE_WRITE_REG32(sc, db, PD_TXULP_DB, reg_value);
903
904 } else if (rc == EFBIG) {
905 if (retry_cnt == 0) {
906 m_temp = m_defrag(m, M_NOWAIT);
907 if (m_temp == NULL)
908 goto free_ret;
909 m = m_temp;
910 *mpp = m_temp;
911 retry_cnt = retry_cnt + 1;
912 goto retry;
913 } else
914 goto free_ret;
915 } else if (rc == ENOMEM)
916 return rc;
917 else
918 goto free_ret;
919
920 return 0;
921
922free_ret:
923 m_freem(*mpp);
924 *mpp = NULL;
925 return rc;
926}
927
928
929static void
930oce_tx_complete(struct oce_wq *wq, uint32_t wqe_idx, uint32_t status)
931{
932 uint32_t in;
933 struct oce_packet_desc *pd;
934 POCE_SOFTC sc = (POCE_SOFTC) wq->parent;
935 struct mbuf *m;
936
937 if (wq->packets_out == wq->packets_in)
938 device_printf(sc->dev, "WQ transmit descriptor missing\n");
939
940 in = wq->packets_in + 1;
941 if (in == OCE_WQ_PACKET_ARRAY_SIZE)
942 in = 0;
943
944 pd = &wq->pckts[wq->packets_in];
945 wq->packets_in = in;
946 wq->ring->num_used -= (pd->nsegs + 1);
947 bus_dmamap_sync(wq->tag, pd->map, BUS_DMASYNC_POSTWRITE);
948 bus_dmamap_unload(wq->tag, pd->map);
949
950 m = pd->mbuf;
951 m_freem(m);
952 pd->mbuf = NULL;
953
954 if (sc->ifp->if_drv_flags & IFF_DRV_OACTIVE) {
955 if (wq->ring->num_used < (wq->ring->num_items / 2)) {
956 sc->ifp->if_drv_flags &= ~(IFF_DRV_OACTIVE);
957 oce_tx_restart(sc, wq);
958 }
959 }
960}
961
962
963static void
964oce_tx_restart(POCE_SOFTC sc, struct oce_wq *wq)
965{
966
967 if ((sc->ifp->if_drv_flags & IFF_DRV_RUNNING) != IFF_DRV_RUNNING)
968 return;
969
970#if __FreeBSD_version >= 800000
971 if (!drbr_empty(sc->ifp, wq->br))
972#else
973 if (!IFQ_DRV_IS_EMPTY(&sc->ifp->if_snd))
974#endif
975 taskqueue_enqueue_fast(taskqueue_swi, &wq->txtask);
976
977}
978
979
980#if defined(INET6) || defined(INET)
981static struct mbuf *
982oce_tso_setup(POCE_SOFTC sc, struct mbuf **mpp)
983{
984 struct mbuf *m;
985#ifdef INET
986 struct ip *ip;
987#endif
988#ifdef INET6
989 struct ip6_hdr *ip6;
990#endif
991 struct ether_vlan_header *eh;
992 struct tcphdr *th;
993 uint16_t etype;
994 int total_len = 0, ehdrlen = 0;
995
996 m = *mpp;
997
998 if (M_WRITABLE(m) == 0) {
999 m = m_dup(*mpp, M_NOWAIT);
1000 if (!m)
1001 return NULL;
1002 m_freem(*mpp);
1003 *mpp = m;
1004 }
1005
1006 eh = mtod(m, struct ether_vlan_header *);
1007 if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
1008 etype = ntohs(eh->evl_proto);
1009 ehdrlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
1010 } else {
1011 etype = ntohs(eh->evl_encap_proto);
1012 ehdrlen = ETHER_HDR_LEN;
1013 }
1014
1015 switch (etype) {
1016#ifdef INET
1017 case ETHERTYPE_IP:
1018 ip = (struct ip *)(m->m_data + ehdrlen);
1019 if (ip->ip_p != IPPROTO_TCP)
1020 return NULL;
1021 th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2));
1022
1023 total_len = ehdrlen + (ip->ip_hl << 2) + (th->th_off << 2);
1024 break;
1025#endif
1026#ifdef INET6
1027 case ETHERTYPE_IPV6:
1028 ip6 = (struct ip6_hdr *)(m->m_data + ehdrlen);
1029 if (ip6->ip6_nxt != IPPROTO_TCP)
1030 return NULL;
1031 th = (struct tcphdr *)((caddr_t)ip6 + sizeof(struct ip6_hdr));
1032
1033 total_len = ehdrlen + sizeof(struct ip6_hdr) + (th->th_off << 2);
1034 break;
1035#endif
1036 default:
1037 return NULL;
1038 }
1039
1040 m = m_pullup(m, total_len);
1041 if (!m)
1042 return NULL;
1043 *mpp = m;
1044 return m;
1045
1046}
1047#endif /* INET6 || INET */
1048
1049void
1050oce_tx_task(void *arg, int npending)
1051{
1052 struct oce_wq *wq = arg;
1053 POCE_SOFTC sc = wq->parent;
1054 struct ifnet *ifp = sc->ifp;
1055 int rc = 0;
1056
1057#if __FreeBSD_version >= 800000
1058 if (TRY_LOCK(&wq->tx_lock)) {
1059 rc = oce_multiq_transmit(ifp, NULL, wq);
1060 if (rc) {
1061 device_printf(sc->dev,
1062 "TX[%d] restart failed\n", wq->queue_index);
1063 }
1064 UNLOCK(&wq->tx_lock);
1065 }
1066#else
1067 oce_start(ifp);
1068#endif
1069
1070}
1071
1072
1073void
1074oce_start(struct ifnet *ifp)
1075{
1076 POCE_SOFTC sc = ifp->if_softc;
1077 struct mbuf *m;
1078 int rc = 0;
1079 int def_q = 0; /* Defualt tx queue is 0*/
1080
1081 if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
1082 IFF_DRV_RUNNING)
1083 return;
1084
1085 do {
1086 IF_DEQUEUE(&sc->ifp->if_snd, m);
1087 if (m == NULL)
1088 break;
1089
1090 LOCK(&sc->wq[def_q]->tx_lock);
1091 rc = oce_tx(sc, &m, def_q);
1092 UNLOCK(&sc->wq[def_q]->tx_lock);
1093 if (rc) {
1094 if (m != NULL) {
1095 sc->wq[def_q]->tx_stats.tx_stops ++;
1096 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1097 IFQ_DRV_PREPEND(&ifp->if_snd, m);
1098 m = NULL;
1099 }
1100 break;
1101 }
1102 if (m != NULL)
1103 ETHER_BPF_MTAP(ifp, m);
1104
1105 } while (TRUE);
1106
1107 return;
1108}
1109
1110
1111/* Handle the Completion Queue for transmit */
1112uint16_t
1113oce_wq_handler(void *arg)
1114{
1115 struct oce_wq *wq = (struct oce_wq *)arg;
1116 POCE_SOFTC sc = wq->parent;
1117 struct oce_cq *cq = wq->cq;
1118 struct oce_nic_tx_cqe *cqe;
1119 int num_cqes = 0;
1120
1121 LOCK(&wq->tx_lock);
1122 bus_dmamap_sync(cq->ring->dma.tag,
1123 cq->ring->dma.map, BUS_DMASYNC_POSTWRITE);
1124 cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_tx_cqe);
1125 while (cqe->u0.dw[3]) {
1126 DW_SWAP((uint32_t *) cqe, sizeof(oce_wq_cqe));
1127
1128 wq->ring->cidx = cqe->u0.s.wqe_index + 1;
1129 if (wq->ring->cidx >= wq->ring->num_items)
1130 wq->ring->cidx -= wq->ring->num_items;
1131
1132 oce_tx_complete(wq, cqe->u0.s.wqe_index, cqe->u0.s.status);
1133 wq->tx_stats.tx_compl++;
1134 cqe->u0.dw[3] = 0;
1135 RING_GET(cq->ring, 1);
1136 bus_dmamap_sync(cq->ring->dma.tag,
1137 cq->ring->dma.map, BUS_DMASYNC_POSTWRITE);
1138 cqe =
1139 RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_tx_cqe);
1140 num_cqes++;
1141 }
1142
1143 if (num_cqes)
1144 oce_arm_cq(sc, cq->cq_id, num_cqes, FALSE);
1145 UNLOCK(&wq->tx_lock);
1146
1147 return 0;
1148}
1149
1150
1151static int
1152oce_multiq_transmit(struct ifnet *ifp, struct mbuf *m, struct oce_wq *wq)
1153{
1154 POCE_SOFTC sc = ifp->if_softc;
1155 int status = 0, queue_index = 0;
1156 struct mbuf *next = NULL;
1157 struct buf_ring *br = NULL;
1158
1159 br = wq->br;
1160 queue_index = wq->queue_index;
1161
1162 if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
1163 IFF_DRV_RUNNING) {
1164 if (m != NULL)
1165 status = drbr_enqueue(ifp, br, m);
1166 return status;
1167 }
1168
1169 if (m != NULL) {
1170 if ((status = drbr_enqueue(ifp, br, m)) != 0)
1171 return status;
1172 }
1173 while ((next = drbr_peek(ifp, br)) != NULL) {
1174 if (oce_tx(sc, &next, queue_index)) {
1175 if (next == NULL) {
1176 drbr_advance(ifp, br);
1177 } else {
1178 drbr_putback(ifp, br, next);
1179 wq->tx_stats.tx_stops ++;
1180 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1181 status = drbr_enqueue(ifp, br, next);
1182 }
1183 break;
1184 }
1185 drbr_advance(ifp, br);
1186 ifp->if_obytes += next->m_pkthdr.len;
1187 if (next->m_flags & M_MCAST)
1188 ifp->if_omcasts++;
1189 ETHER_BPF_MTAP(ifp, next);
1190 }
1191
1192 return status;
1193}
1194
1195
1196
1197
1198/*****************************************************************************
1199 * Receive routines functions *
1200 *****************************************************************************/
1201
1202static void
1203oce_rx(struct oce_rq *rq, uint32_t rqe_idx, struct oce_nic_rx_cqe *cqe)
1204{
1205 uint32_t out;
1206 struct oce_packet_desc *pd;
1207 POCE_SOFTC sc = (POCE_SOFTC) rq->parent;
1208 int i, len, frag_len;
1209 struct mbuf *m = NULL, *tail = NULL;
1210 uint16_t vtag;
1211
1212 len = cqe->u0.s.pkt_size;
1213 if (!len) {
1214 /*partial DMA workaround for Lancer*/
1215 oce_discard_rx_comp(rq, cqe);
1216 goto exit;
1217 }
1218
1219 /* Get vlan_tag value */
1220 if(IS_BE(sc))
1221 vtag = BSWAP_16(cqe->u0.s.vlan_tag);
1222 else
1223 vtag = cqe->u0.s.vlan_tag;
1224
1225
1226 for (i = 0; i < cqe->u0.s.num_fragments; i++) {
1227
1228 if (rq->packets_out == rq->packets_in) {
1229 device_printf(sc->dev,
1230 "RQ transmit descriptor missing\n");
1231 }
1232 out = rq->packets_out + 1;
1233 if (out == OCE_RQ_PACKET_ARRAY_SIZE)
1234 out = 0;
1235 pd = &rq->pckts[rq->packets_out];
1236 rq->packets_out = out;
1237
1238 bus_dmamap_sync(rq->tag, pd->map, BUS_DMASYNC_POSTWRITE);
1239 bus_dmamap_unload(rq->tag, pd->map);
1240 rq->pending--;
1241
1242 frag_len = (len > rq->cfg.frag_size) ? rq->cfg.frag_size : len;
1243 pd->mbuf->m_len = frag_len;
1244
1245 if (tail != NULL) {
1246 /* additional fragments */
1247 pd->mbuf->m_flags &= ~M_PKTHDR;
1248 tail->m_next = pd->mbuf;
1249 tail = pd->mbuf;
1250 } else {
1251 /* first fragment, fill out much of the packet header */
1252 pd->mbuf->m_pkthdr.len = len;
1253 pd->mbuf->m_pkthdr.csum_flags = 0;
1254 if (IF_CSUM_ENABLED(sc)) {
1255 if (cqe->u0.s.l4_cksum_pass) {
1256 pd->mbuf->m_pkthdr.csum_flags |=
1257 (CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
1258 pd->mbuf->m_pkthdr.csum_data = 0xffff;
1259 }
1260 if (cqe->u0.s.ip_cksum_pass) {
1261 if (!cqe->u0.s.ip_ver) { /* IPV4 */
1262 pd->mbuf->m_pkthdr.csum_flags |=
1263 (CSUM_IP_CHECKED|CSUM_IP_VALID);
1264 }
1265 }
1266 }
1267 m = tail = pd->mbuf;
1268 }
1269 pd->mbuf = NULL;
1270 len -= frag_len;
1271 }
1272
1273 if (m) {
1274 if (!oce_cqe_portid_valid(sc, cqe)) {
1275 m_freem(m);
1276 goto exit;
1277 }
1278
1279 m->m_pkthdr.rcvif = sc->ifp;
1280#if __FreeBSD_version >= 800000
1281 m->m_pkthdr.flowid = rq->queue_index;
1282 m->m_flags |= M_FLOWID;
1283#endif
1284 /* This deternies if vlan tag is Valid */
1285 if (oce_cqe_vtp_valid(sc, cqe)) {
1286 if (sc->function_mode & FNM_FLEX10_MODE) {
1287 /* FLEX10. If QnQ is not set, neglect VLAN */
1288 if (cqe->u0.s.qnq) {
1289 m->m_pkthdr.ether_vtag = vtag;
1290 m->m_flags |= M_VLANTAG;
1291 }
1292 } else if (sc->pvid != (vtag & VLAN_VID_MASK)) {
1293 /* In UMC mode generally pvid will be striped by
1294 hw. But in some cases we have seen it comes
1295 with pvid. So if pvid == vlan, neglect vlan.
1296 */
1297 m->m_pkthdr.ether_vtag = vtag;
1298 m->m_flags |= M_VLANTAG;
1299 }
1300 }
1301
1302 sc->ifp->if_ipackets++;
1303#if defined(INET6) || defined(INET)
1304 /* Try to queue to LRO */
1305 if (IF_LRO_ENABLED(sc) &&
1306 !(m->m_flags & M_VLANTAG) &&
1307 (cqe->u0.s.ip_cksum_pass) &&
1308 (cqe->u0.s.l4_cksum_pass) &&
1309 (!cqe->u0.s.ip_ver) &&
1310 (rq->lro.lro_cnt != 0)) {
1311
1312 if (tcp_lro_rx(&rq->lro, m, 0) == 0) {
1313 rq->lro_pkts_queued ++;
1314 goto post_done;
1315 }
1316 /* If LRO posting fails then try to post to STACK */
1317 }
1318#endif
1319
1320 (*sc->ifp->if_input) (sc->ifp, m);
1321#if defined(INET6) || defined(INET)
1322post_done:
1323#endif
1324 /* Update rx stats per queue */
1325 rq->rx_stats.rx_pkts++;
1326 rq->rx_stats.rx_bytes += cqe->u0.s.pkt_size;
1327 rq->rx_stats.rx_frags += cqe->u0.s.num_fragments;
1328 if (cqe->u0.s.pkt_type == OCE_MULTICAST_PACKET)
1329 rq->rx_stats.rx_mcast_pkts++;
1330 if (cqe->u0.s.pkt_type == OCE_UNICAST_PACKET)
1331 rq->rx_stats.rx_ucast_pkts++;
1332 }
1333exit:
1334 return;
1335}
1336
1337
1338static void
1339oce_discard_rx_comp(struct oce_rq *rq, struct oce_nic_rx_cqe *cqe)
1340{
1341 uint32_t out, i = 0;
1342 struct oce_packet_desc *pd;
1343 POCE_SOFTC sc = (POCE_SOFTC) rq->parent;
1344 int num_frags = cqe->u0.s.num_fragments;
1345
1346 if (IS_XE201(sc) && cqe->u0.s.error) {
1347 /* Lancer A0 workaround
1348 * num_frags will be 1 more than actual in case of error
1349 */
1350 if (num_frags)
1351 num_frags -= 1;
1352 }
1353 for (i = 0; i < num_frags; i++) {
1354 if (rq->packets_out == rq->packets_in) {
1355 device_printf(sc->dev,
1356 "RQ transmit descriptor missing\n");
1357 }
1358 out = rq->packets_out + 1;
1359 if (out == OCE_RQ_PACKET_ARRAY_SIZE)
1360 out = 0;
1361 pd = &rq->pckts[rq->packets_out];
1362 rq->packets_out = out;
1363
1364 bus_dmamap_sync(rq->tag, pd->map, BUS_DMASYNC_POSTWRITE);
1365 bus_dmamap_unload(rq->tag, pd->map);
1366 rq->pending--;
1367 m_freem(pd->mbuf);
1368 }
1369
1370}
1371
1372
1373static int
1374oce_cqe_vtp_valid(POCE_SOFTC sc, struct oce_nic_rx_cqe *cqe)
1375{
1376 struct oce_nic_rx_cqe_v1 *cqe_v1;
1377 int vtp = 0;
1378
1379 if (sc->be3_native) {
1380 cqe_v1 = (struct oce_nic_rx_cqe_v1 *)cqe;
1381 vtp = cqe_v1->u0.s.vlan_tag_present;
1382 } else
1383 vtp = cqe->u0.s.vlan_tag_present;
1384
1385 return vtp;
1386
1387}
1388
1389
1390static int
1391oce_cqe_portid_valid(POCE_SOFTC sc, struct oce_nic_rx_cqe *cqe)
1392{
1393 struct oce_nic_rx_cqe_v1 *cqe_v1;
1394 int port_id = 0;
1395
1396 if (sc->be3_native && IS_BE(sc)) {
1397 cqe_v1 = (struct oce_nic_rx_cqe_v1 *)cqe;
1398 port_id = cqe_v1->u0.s.port;
1399 if (sc->port_id != port_id)
1400 return 0;
1401 } else
1402 ;/* For BE3 legacy and Lancer this is dummy */
1403
1404 return 1;
1405
1406}
1407
1408#if defined(INET6) || defined(INET)
1409static void
1410oce_rx_flush_lro(struct oce_rq *rq)
1411{
1412 struct lro_ctrl *lro = &rq->lro;
1413 struct lro_entry *queued;
1414 POCE_SOFTC sc = (POCE_SOFTC) rq->parent;
1415
1416 if (!IF_LRO_ENABLED(sc))
1417 return;
1418
1419 while ((queued = SLIST_FIRST(&lro->lro_active)) != NULL) {
1420 SLIST_REMOVE_HEAD(&lro->lro_active, next);
1421 tcp_lro_flush(lro, queued);
1422 }
1423 rq->lro_pkts_queued = 0;
1424
1425 return;
1426}
1427
1428
1429static int
1430oce_init_lro(POCE_SOFTC sc)
1431{
1432 struct lro_ctrl *lro = NULL;
1433 int i = 0, rc = 0;
1434
1435 for (i = 0; i < sc->nrqs; i++) {
1436 lro = &sc->rq[i]->lro;
1437 rc = tcp_lro_init(lro);
1438 if (rc != 0) {
1439 device_printf(sc->dev, "LRO init failed\n");
1440 return rc;
1441 }
1442 lro->ifp = sc->ifp;
1443 }
1444
1445 return rc;
1446}
1447
1448
1449void
1450oce_free_lro(POCE_SOFTC sc)
1451{
1452 struct lro_ctrl *lro = NULL;
1453 int i = 0;
1454
1455 for (i = 0; i < sc->nrqs; i++) {
1456 lro = &sc->rq[i]->lro;
1457 if (lro)
1458 tcp_lro_free(lro);
1459 }
1460}
1461#endif /* INET6 || INET */
1462
1463int
1464oce_alloc_rx_bufs(struct oce_rq *rq, int count)
1465{
1466 POCE_SOFTC sc = (POCE_SOFTC) rq->parent;
1467 int i, in, rc;
1468 struct oce_packet_desc *pd;
1469 bus_dma_segment_t segs[6];
1470 int nsegs, added = 0;
1471 struct oce_nic_rqe *rqe;
1472 pd_rxulp_db_t rxdb_reg;
1473
1474
1475 for (i = 0; i < count; i++) {
1476 in = rq->packets_in + 1;
1477 if (in == OCE_RQ_PACKET_ARRAY_SIZE)
1478 in = 0;
1479 if (in == rq->packets_out)
1480 break; /* no more room */
1481
1482 pd = &rq->pckts[rq->packets_in];
1483 pd->mbuf = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1484 if (pd->mbuf == NULL)
1485 break;
1486
1487 pd->mbuf->m_len = pd->mbuf->m_pkthdr.len = MCLBYTES;
1488 rc = bus_dmamap_load_mbuf_sg(rq->tag,
1489 pd->map,
1490 pd->mbuf,
1491 segs, &nsegs, BUS_DMA_NOWAIT);
1492 if (rc) {
1493 m_free(pd->mbuf);
1494 break;
1495 }
1496
1497 if (nsegs != 1) {
1498 i--;
1499 continue;
1500 }
1501
1502 rq->packets_in = in;
1503 bus_dmamap_sync(rq->tag, pd->map, BUS_DMASYNC_PREREAD);
1504
1505 rqe = RING_GET_PRODUCER_ITEM_VA(rq->ring, struct oce_nic_rqe);
1506 rqe->u0.s.frag_pa_hi = ADDR_HI(segs[0].ds_addr);
1507 rqe->u0.s.frag_pa_lo = ADDR_LO(segs[0].ds_addr);
1508 DW_SWAP(u32ptr(rqe), sizeof(struct oce_nic_rqe));
1509 RING_PUT(rq->ring, 1);
1510 added++;
1511 rq->pending++;
1512 }
1513 if (added != 0) {
1514 for (i = added / OCE_MAX_RQ_POSTS; i > 0; i--) {
1515 DELAY(1);
1516 rxdb_reg.bits.num_posted = OCE_MAX_RQ_POSTS;
1517 rxdb_reg.bits.qid = rq->rq_id;
1518 OCE_WRITE_REG32(sc, db, PD_RXULP_DB, rxdb_reg.dw0);
1519 added -= OCE_MAX_RQ_POSTS;
1520 }
1521 if (added > 0) {
1522 DELAY(1);
1523 rxdb_reg.bits.qid = rq->rq_id;
1524 rxdb_reg.bits.num_posted = added;
1525 OCE_WRITE_REG32(sc, db, PD_RXULP_DB, rxdb_reg.dw0);
1526 }
1527 }
1528
1529 return 0;
1530}
1531
1532
1533/* Handle the Completion Queue for receive */
1534uint16_t
1535oce_rq_handler(void *arg)
1536{
1537 struct oce_rq *rq = (struct oce_rq *)arg;
1538 struct oce_cq *cq = rq->cq;
1539 POCE_SOFTC sc = rq->parent;
1540 struct oce_nic_rx_cqe *cqe;
1541 int num_cqes = 0, rq_buffers_used = 0;
1542
1543
1544 LOCK(&rq->rx_lock);
1545 bus_dmamap_sync(cq->ring->dma.tag,
1546 cq->ring->dma.map, BUS_DMASYNC_POSTWRITE);
1547 cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_rx_cqe);
1548 while (cqe->u0.dw[2]) {
1549 DW_SWAP((uint32_t *) cqe, sizeof(oce_rq_cqe));
1550
1551 RING_GET(rq->ring, 1);
1552 if (cqe->u0.s.error == 0) {
1553 oce_rx(rq, cqe->u0.s.frag_index, cqe);
1554 } else {
1555 rq->rx_stats.rxcp_err++;
1556 sc->ifp->if_ierrors++;
1557 if (IS_XE201(sc))
1558 /* Lancer A0 no buffer workaround */
1559 oce_discard_rx_comp(rq, cqe);
1560 else
1561 /* Post L3/L4 errors to stack.*/
1562 oce_rx(rq, cqe->u0.s.frag_index, cqe);
1563
1564 }
1565 rq->rx_stats.rx_compl++;
1566 cqe->u0.dw[2] = 0;
1567
1568#if defined(INET6) || defined(INET)
1569 if (IF_LRO_ENABLED(sc) && rq->lro_pkts_queued >= 16) {
1570 oce_rx_flush_lro(rq);
1571 }
1572#endif
1573
1574 RING_GET(cq->ring, 1);
1575 bus_dmamap_sync(cq->ring->dma.tag,
1576 cq->ring->dma.map, BUS_DMASYNC_POSTWRITE);
1577 cqe =
1578 RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_nic_rx_cqe);
1579 num_cqes++;
1580 if (num_cqes >= (IS_XE201(sc) ? 8 : oce_max_rsp_handled))
1581 break;
1582 }
1583
1584#if defined(INET6) || defined(INET)
1585 if (IF_LRO_ENABLED(sc))
1586 oce_rx_flush_lro(rq);
1587#endif
1588
1589 if (num_cqes) {
1590 oce_arm_cq(sc, cq->cq_id, num_cqes, FALSE);
1591 rq_buffers_used = OCE_RQ_PACKET_ARRAY_SIZE - rq->pending;
1592 if (rq_buffers_used > 1)
1593 oce_alloc_rx_bufs(rq, (rq_buffers_used - 1));
1594 }
1595
1596 UNLOCK(&rq->rx_lock);
1597
1598 return 0;
1599
1600}
1601
1602
1603
1604
1605/*****************************************************************************
1606 * Helper function prototypes in this file *
1607 *****************************************************************************/
1608
1609static int
1610oce_attach_ifp(POCE_SOFTC sc)
1611{
1612
1613 sc->ifp = if_alloc(IFT_ETHER);
1614 if (!sc->ifp)
1615 return ENOMEM;
1616
1617 ifmedia_init(&sc->media, IFM_IMASK, oce_media_change, oce_media_status);
1618 ifmedia_add(&sc->media, IFM_ETHER | IFM_AUTO, 0, NULL);
1619 ifmedia_set(&sc->media, IFM_ETHER | IFM_AUTO);
1620
1621 sc->ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST;
1622 sc->ifp->if_ioctl = oce_ioctl;
1623 sc->ifp->if_start = oce_start;
1624 sc->ifp->if_init = oce_init;
1625 sc->ifp->if_mtu = ETHERMTU;
1626 sc->ifp->if_softc = sc;
1627#if __FreeBSD_version >= 800000
1628 sc->ifp->if_transmit = oce_multiq_start;
1629 sc->ifp->if_qflush = oce_multiq_flush;
1630#endif
1631
1632 if_initname(sc->ifp,
1633 device_get_name(sc->dev), device_get_unit(sc->dev));
1634
1635 sc->ifp->if_snd.ifq_drv_maxlen = OCE_MAX_TX_DESC - 1;
1636 IFQ_SET_MAXLEN(&sc->ifp->if_snd, sc->ifp->if_snd.ifq_drv_maxlen);
1637 IFQ_SET_READY(&sc->ifp->if_snd);
1638
1639 sc->ifp->if_hwassist = OCE_IF_HWASSIST;
1640 sc->ifp->if_hwassist |= CSUM_TSO;
1641 sc->ifp->if_hwassist |= (CSUM_IP | CSUM_TCP | CSUM_UDP);
1642
1643 sc->ifp->if_capabilities = OCE_IF_CAPABILITIES;
1644 sc->ifp->if_capabilities |= IFCAP_HWCSUM;
1645 sc->ifp->if_capabilities |= IFCAP_VLAN_HWFILTER;
1646
1647#if defined(INET6) || defined(INET)
1648 sc->ifp->if_capabilities |= IFCAP_TSO;
1649 sc->ifp->if_capabilities |= IFCAP_LRO;
1650 sc->ifp->if_capabilities |= IFCAP_VLAN_HWTSO;
1651#endif
1652
1653 sc->ifp->if_capenable = sc->ifp->if_capabilities;
1654 if_initbaudrate(sc->ifp, IF_Gbps(10));
1655
1656 ether_ifattach(sc->ifp, sc->macaddr.mac_addr);
1657
1658 return 0;
1659}
1660
1661
1662static void
1663oce_add_vlan(void *arg, struct ifnet *ifp, uint16_t vtag)
1664{
1665 POCE_SOFTC sc = ifp->if_softc;
1666
1667 if (ifp->if_softc != arg)
1668 return;
1669 if ((vtag == 0) || (vtag > 4095))
1670 return;
1671
1672 sc->vlan_tag[vtag] = 1;
1673 sc->vlans_added++;
1674 oce_vid_config(sc);
1675}
1676
1677
1678static void
1679oce_del_vlan(void *arg, struct ifnet *ifp, uint16_t vtag)
1680{
1681 POCE_SOFTC sc = ifp->if_softc;
1682
1683 if (ifp->if_softc != arg)
1684 return;
1685 if ((vtag == 0) || (vtag > 4095))
1686 return;
1687
1688 sc->vlan_tag[vtag] = 0;
1689 sc->vlans_added--;
1690 oce_vid_config(sc);
1691}
1692
1693
1694/*
1695 * A max of 64 vlans can be configured in BE. If the user configures
1696 * more, place the card in vlan promiscuous mode.
1697 */
1698static int
1699oce_vid_config(POCE_SOFTC sc)
1700{
1701 struct normal_vlan vtags[MAX_VLANFILTER_SIZE];
1702 uint16_t ntags = 0, i;
1703 int status = 0;
1704
1705 if ((sc->vlans_added <= MAX_VLANFILTER_SIZE) &&
1706 (sc->ifp->if_capenable & IFCAP_VLAN_HWFILTER)) {
1707 for (i = 0; i < MAX_VLANS; i++) {
1708 if (sc->vlan_tag[i]) {
1709 vtags[ntags].vtag = i;
1710 ntags++;
1711 }
1712 }
1713 if (ntags)
1714 status = oce_config_vlan(sc, (uint8_t) sc->if_id,
1715 vtags, ntags, 1, 0);
1716 } else
1717 status = oce_config_vlan(sc, (uint8_t) sc->if_id,
1718 NULL, 0, 1, 1);
1719 return status;
1720}
1721
1722
1723static void
1724oce_mac_addr_set(POCE_SOFTC sc)
1725{
1726 uint32_t old_pmac_id = sc->pmac_id;
1727 int status = 0;
1728
1729
1730 status = bcmp((IF_LLADDR(sc->ifp)), sc->macaddr.mac_addr,
1731 sc->macaddr.size_of_struct);
1732 if (!status)
1733 return;
1734
1735 status = oce_mbox_macaddr_add(sc, (uint8_t *)(IF_LLADDR(sc->ifp)),
1736 sc->if_id, &sc->pmac_id);
1737 if (!status) {
1738 status = oce_mbox_macaddr_del(sc, sc->if_id, old_pmac_id);
1739 bcopy((IF_LLADDR(sc->ifp)), sc->macaddr.mac_addr,
1740 sc->macaddr.size_of_struct);
1741 }
1742 if (status)
1743 device_printf(sc->dev, "Failed update macaddress\n");
1744
1745}
1746
1747
1748static int
1749oce_handle_passthrough(struct ifnet *ifp, caddr_t data)
1750{
1751 POCE_SOFTC sc = ifp->if_softc;
1752 struct ifreq *ifr = (struct ifreq *)data;
1753 int rc = ENXIO;
1754 char cookie[32] = {0};
1755 void *priv_data = (void *)ifr->ifr_data;
1756 void *ioctl_ptr;
1757 uint32_t req_size;
1758 struct mbx_hdr req;
1759 OCE_DMA_MEM dma_mem;
1760
1761
1762 if (copyin(priv_data, cookie, strlen(IOCTL_COOKIE)))
1763 return EFAULT;
1764
1765 if (memcmp(cookie, IOCTL_COOKIE, strlen(IOCTL_COOKIE)))
1766 return EINVAL;
1767
1768 ioctl_ptr = (char *)priv_data + strlen(IOCTL_COOKIE);
1769 if (copyin(ioctl_ptr, &req, sizeof(struct mbx_hdr)))
1770 return EFAULT;
1771
1772 req_size = le32toh(req.u0.req.request_length);
1773 if (req_size > 65536)
1774 return EINVAL;
1775
1776 req_size += sizeof(struct mbx_hdr);
1777 rc = oce_dma_alloc(sc, req_size, &dma_mem, 0);
1778 if (rc)
1779 return ENOMEM;
1780
1781 if (copyin(ioctl_ptr, OCE_DMAPTR(&dma_mem,char), req_size)) {
1782 rc = EFAULT;
1783 goto dma_free;
1784 }
1785
1786 rc = oce_pass_through_mbox(sc, &dma_mem, req_size);
1787 if (rc) {
1788 rc = EIO;
1789 goto dma_free;
1790 }
1791
1792 if (copyout(OCE_DMAPTR(&dma_mem,char), ioctl_ptr, req_size))
1793 rc = EFAULT;
1794
1795dma_free:
1796 oce_dma_free(sc, &dma_mem);
1797 return rc;
1798
1799}
1800
1801
1802static void
1803oce_local_timer(void *arg)
1804{
1805 POCE_SOFTC sc = arg;
1806 int i = 0;
1807
1808 oce_refresh_nic_stats(sc);
1809 oce_refresh_queue_stats(sc);
1810 oce_mac_addr_set(sc);
1811
1812 /* TX Watch Dog*/
1813 for (i = 0; i < sc->nwqs; i++)
1814 oce_tx_restart(sc, sc->wq[i]);
1815
1816 callout_reset(&sc->timer, hz, oce_local_timer, sc);
1817}
1818
1819
1820/* NOTE : This should only be called holding
1821 * DEVICE_LOCK.
1822*/
1823static void
1824oce_if_deactivate(POCE_SOFTC sc)
1825{
1826 int i, mtime = 0;
1827 int wait_req = 0;
1828 struct oce_rq *rq;
1829 struct oce_wq *wq;
1830 struct oce_eq *eq;
1831
1832 sc->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
1833
1834 /*Wait for max of 400ms for TX completions to be done */
1835 while (mtime < 400) {
1836 wait_req = 0;
1837 for_all_wq_queues(sc, wq, i) {
1838 if (wq->ring->num_used) {
1839 wait_req = 1;
1840 DELAY(1);
1841 break;
1842 }
1843 }
1844 mtime += 1;
1845 if (!wait_req)
1846 break;
1847 }
1848
1849 /* Stop intrs and finish any bottom halves pending */
1850 oce_hw_intr_disable(sc);
1851
1852 /* Since taskqueue_drain takes a Giant Lock, We should not acquire
1853 any other lock. So unlock device lock and require after
1854 completing taskqueue_drain.
1855 */
1856 UNLOCK(&sc->dev_lock);
1857 for (i = 0; i < sc->intr_count; i++) {
1858 if (sc->intrs[i].tq != NULL) {
1859 taskqueue_drain(sc->intrs[i].tq, &sc->intrs[i].task);
1860 }
1861 }
1862 LOCK(&sc->dev_lock);
1863
1864 /* Delete RX queue in card with flush param */
1865 oce_stop_rx(sc);
1866
1867 /* Invalidate any pending cq and eq entries*/
1868 for_all_evnt_queues(sc, eq, i)
1869 oce_drain_eq(eq);
1870 for_all_rq_queues(sc, rq, i)
1871 oce_drain_rq_cq(rq);
1872 for_all_wq_queues(sc, wq, i)
1873 oce_drain_wq_cq(wq);
1874
1875 /* But still we need to get MCC aync events.
1876 So enable intrs and also arm first EQ
1877 */
1878 oce_hw_intr_enable(sc);
1879 oce_arm_eq(sc, sc->eq[0]->eq_id, 0, TRUE, FALSE);
1880
1881 DELAY(10);
1882}
1883
1884
1885static void
1886oce_if_activate(POCE_SOFTC sc)
1887{
1888 struct oce_eq *eq;
1889 struct oce_rq *rq;
1890 struct oce_wq *wq;
1891 int i, rc = 0;
1892
1893 sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
1894
1895 oce_hw_intr_disable(sc);
1896
1897 oce_start_rx(sc);
1898
1899 for_all_rq_queues(sc, rq, i) {
1900 rc = oce_start_rq(rq);
1901 if (rc)
1902 device_printf(sc->dev, "Unable to start RX\n");
1903 }
1904
1905 for_all_wq_queues(sc, wq, i) {
1906 rc = oce_start_wq(wq);
1907 if (rc)
1908 device_printf(sc->dev, "Unable to start TX\n");
1909 }
1910
1911
1912 for_all_evnt_queues(sc, eq, i)
1913 oce_arm_eq(sc, eq->eq_id, 0, TRUE, FALSE);
1914
1915 oce_hw_intr_enable(sc);
1916
1917}
1918
1919static void
1920process_link_state(POCE_SOFTC sc, struct oce_async_cqe_link_state *acqe)
1921{
1922 /* Update Link status */
1923 if ((acqe->u0.s.link_status & ~ASYNC_EVENT_LOGICAL) ==
1924 ASYNC_EVENT_LINK_UP) {
1925 sc->link_status = ASYNC_EVENT_LINK_UP;
1926 if_link_state_change(sc->ifp, LINK_STATE_UP);
1927 } else {
1928 sc->link_status = ASYNC_EVENT_LINK_DOWN;
1929 if_link_state_change(sc->ifp, LINK_STATE_DOWN);
1930 }
1931
1932 /* Update speed */
1933 sc->link_speed = acqe->u0.s.speed;
1934 sc->qos_link_speed = (uint32_t) acqe->u0.s.qos_link_speed * 10;
1935
1936}
1937
1938
1939/* Handle the Completion Queue for the Mailbox/Async notifications */
1940uint16_t
1941oce_mq_handler(void *arg)
1942{
1943 struct oce_mq *mq = (struct oce_mq *)arg;
1944 POCE_SOFTC sc = mq->parent;
1945 struct oce_cq *cq = mq->cq;
1946 int num_cqes = 0, evt_type = 0, optype = 0;
1947 struct oce_mq_cqe *cqe;
1948 struct oce_async_cqe_link_state *acqe;
1949 struct oce_async_event_grp5_pvid_state *gcqe;
1950
1951
1952 bus_dmamap_sync(cq->ring->dma.tag,
1953 cq->ring->dma.map, BUS_DMASYNC_POSTWRITE);
1954 cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_mq_cqe);
1955
1956 while (cqe->u0.dw[3]) {
1957 DW_SWAP((uint32_t *) cqe, sizeof(oce_mq_cqe));
1958 if (cqe->u0.s.async_event) {
1959 evt_type = cqe->u0.s.event_type;
1960 optype = cqe->u0.s.async_type;
1961 if (evt_type == ASYNC_EVENT_CODE_LINK_STATE) {
1962 /* Link status evt */
1963 acqe = (struct oce_async_cqe_link_state *)cqe;
1964 process_link_state(sc, acqe);
1965 } else if ((evt_type == ASYNC_EVENT_GRP5) &&
1966 (optype == ASYNC_EVENT_PVID_STATE)) {
1967 /* GRP5 PVID */
1968 gcqe =
1969 (struct oce_async_event_grp5_pvid_state *)cqe;
1970 if (gcqe->enabled)
1971 sc->pvid = gcqe->tag & VLAN_VID_MASK;
1972 else
1973 sc->pvid = 0;
1974
1975 }
1976 }
1977 cqe->u0.dw[3] = 0;
1978 RING_GET(cq->ring, 1);
1979 bus_dmamap_sync(cq->ring->dma.tag,
1980 cq->ring->dma.map, BUS_DMASYNC_POSTWRITE);
1981 cqe = RING_GET_CONSUMER_ITEM_VA(cq->ring, struct oce_mq_cqe);
1982 num_cqes++;
1983 }
1984
1985 if (num_cqes)
1986 oce_arm_cq(sc, cq->cq_id, num_cqes, FALSE);
1987
1988 return 0;
1989}
1990
1991
1992static void
1993setup_max_queues_want(POCE_SOFTC sc)
1994{
1995 int max_rss = 0;
1996
1997 /* Check if it is FLEX machine. Is so dont use RSS */
1998 if ((sc->function_mode & FNM_FLEX10_MODE) ||
1999 (sc->function_mode & FNM_UMC_MODE) ||
2000 (sc->function_mode & FNM_VNIC_MODE) ||
2001 (!sc->rss_enable) ||
2002 (sc->flags & OCE_FLAGS_BE2)) {
2003 sc->nrqs = 1;
2004 sc->nwqs = 1;
2005 sc->rss_enable = 0;
2006 } else {
2007 /* For multiq, our deisgn is to have TX rings equal to
2008 RSS rings. So that we can pair up one RSS ring and TX
2009 to a single intr, which improves CPU cache efficiency.
2010 */
2011 if (IS_BE(sc) && (!sc->be3_native))
2012 max_rss = OCE_LEGACY_MODE_RSS;
2013 else
2014 max_rss = OCE_MAX_RSS;
2015
2016 sc->nrqs = MIN(OCE_NCPUS, max_rss) + 1; /* 1 for def RX */
2017 sc->nwqs = MIN(OCE_NCPUS, max_rss);
2018 }
2019
2020}
2021
2022
2023static void
2024update_queues_got(POCE_SOFTC sc)
2025{
2026 if (sc->rss_enable) {
2027 sc->nrqs = sc->intr_count + 1;
2028 sc->nwqs = sc->intr_count;
2029 } else {
2030 sc->nrqs = 1;
2031 sc->nwqs = 1;
2032 }
2033}
2034